diff --git a/app/app.js b/app/app.js index 034bfbf7..bf853c3f 100644 --- a/app/app.js +++ b/app/app.js @@ -360,7 +360,7 @@ ipcMain.on('home-tab-clientclicked',function(event,clientId){ } plex.chosenClient.on('client-update', function(){ - mainWindow.send('pt-sendPoll-manual') + //mainWindow.send('pt-sendPoll-manual') } ) event.sender.send('fire-notification','Plex Client','Successfully connected to ' + client.name) @@ -529,6 +529,9 @@ ipcMain.on('join-room-ok',function(event,data,details,currentUsers){ mainWindow.send('start-handling-room-events',data,details,currentUsers) }) ipcMain.on('pt-sendPoll',function(event,data){ + if (!global.socket){ + return + } global.socket.pollStartTime = (new Date).getTime() global.log.info('Sending our data to the PT server') global.socket.emit('poll',data) diff --git a/app/js/home.js b/app/js/home.js index d04723fa..74e25efa 100644 --- a/app/js/home.js +++ b/app/js/home.js @@ -16,6 +16,7 @@ var ptServerTickers = [] var plexClientTickers= []; var $ = require('jquery') +var clientTestInProgress = false // Fetch our Plex Data ipcRenderer.send('home-tab-initialize') @@ -79,10 +80,15 @@ ipcRenderer.on('home-tab-initialize-result', function(event, username, clients, var clientsObj = document.querySelectorAll('.plexClient') for (let i = 0; i < clientsObj.length; i++){ clientsObj[i].addEventListener('click', function (event) { + if (clientTestInProgress) { + return + } + clientTestInProgress = true var clientId = event.toElement.getAttribute('plexId') event.toElement.style.color = '#ffb74d' var plex = remote.getGlobal('plex') if (plex.chosenClient != null) { + plex.chosenClient.clearEvents(function(){}) plex.chosenClient.unsubscribe(function(){}) } ipcRenderer.send('home-tab-clientclicked',clientId) @@ -171,6 +177,7 @@ ipcRenderer.on('home-tab-clientclicked-result',function(event,result,client){ } } } + clientTestInProgress = false }) @@ -182,7 +189,11 @@ function checkRatingKey(){ // ---If they're different, retrieve new metadata from PMS //global.renderLog.info('Checking the rating key') var plex = remote.getGlobal('plex') + if (!plex.chosenClient){ + return + } plex.chosenClient.getTimeline(function(result,responseTime){ + console.log(plex.chosenClient.lastTimelineObject) if (!result) { return } @@ -326,6 +337,7 @@ ipcRenderer.on('start-handling-room-events',function(event){ roomEvents() }) ipcRenderer.on('pt-sendPoll-manual',function(event){ + console.log('Sending manual poll data') sendValidData() }) function roomEvents(){ @@ -342,6 +354,9 @@ function roomEvents(){ function sendPoll() { var plex = remote.getGlobal('plex') + if (plex.chosenClient == null || plex.chosenClient == undefined) { + return + } plex.chosenClient.getTimeline(function(result,responseTime){ sendValidData() }) @@ -442,6 +457,9 @@ function handleHostUpdate(data){ if (plex.chosenClient == null){ return } + if (!plex.chosenClient.lastTimelineObject){ + return + } if (plex.chosenClient.lastMessageToServer == null){ // Need to wait for some data from our client first return @@ -506,12 +524,11 @@ function handleHostUpdate(data){ } else { if (plex.chosenClient.oldTimelineObject == plex.chosenClient.lastTimelineObject){ // We've already checked all of this timelines data! - global.renderLog.info('Already checked this timeline object') + //global.renderLog.info('Already checked this timeline object') resetAccess() return } } - console.log(plex.chosenClient.oldTimelineObject.time - plex.chosenClient.lastTimelineObject.time) if (freshTime == null){ // Non-valid response @@ -526,12 +543,9 @@ function handleHostUpdate(data){ } //Check if we need to pause or unpause } if (data.playerState == 'paused' && freshPlayerState == 'paused'){ - //Need to press pause - fireNotification('Plex Together Sync','Host pressed pause - pressing pause now') - plex.chosenClient.pressPause(function(){ - resetAccess() - }) - return + //Need to press pause + resetAccess() + return } if (data.playerState == 'playing' && freshPlayerState == 'paused'){ //Need to press play @@ -569,8 +583,19 @@ function handleHostUpdate(data){ var ourTime = (+freshTime + +ourClientResponseTime) var difference = Math.abs(predictedHostTime - ourTime) global.renderLog.info('Difference from host is ' + difference) - - if (difference > 2000){ + let status = 'behind' + if (ourTime > predictedHostTime) { + status = 'ahead' + } + console.log('We are ' + status) + console.log('Our Socket Response time: ' + responseTime) + console.log('Predicted time past since this host data: ' + predictedTimePast) + console.log('The predicted time our host is at ' + predictedHostTime) + console.log('The hosts raw time: ' + data.time) + console.log('Our raw time: ' + plex.chosenClient.lastTimelineObject.time ) + console.log('Our predicted time ' + ourTime) + console.log('The difference: ' + difference) + if (difference > 3000){ //We're too far out, we should seek to the same time //Check if they're actually playing something.. if (data.title == null || data.title == 'Nothing'){ @@ -586,6 +611,7 @@ function handleHostUpdate(data){ plex.chosenClient.bufferTime = 0 } seekTime = seekTime + plex.chosenClient.bufferTime + console.log('We are going to be seeking ahead ' + seekTime) waitTime = 3000 } fireNotification('Plex Together Sync','Seeking to get back inline with the host') @@ -789,8 +815,12 @@ function handleHostUpdate(data){ } } function checkBufferTime(){ - // This function is used to estimate how long it takes to buffer content when a seek occurs + // This function is used to estimate how long it takes to buffer content when a seek occurs + // Broken at the moment var plex = remote.getGlobal('plex') + + plex.chosenClient.bufferTime = (0) + return var i = 0 var firstTime = 0 var checkInterval = 200 @@ -803,26 +833,25 @@ function checkBufferTime(){ plex.chosenClient.getTimeline(function(timelines,responseTime){ if (!timelines) { return - } - plex.chosenClient.updateTimelineObject(timelines,responseTime,function(result){ - let videoTimeline = result - if (i == 0) { - firstTime = videoTimeline.time - i = i + 1 + } + if (i == 0) { + firstTime = plex.chosenClient.lastTimelineObject.time + i = i + 1 + return + } else { + i = i + 1 + // Check if the player is actually playing content now + console.log('Iteration: ' + i + ') Player is at ' + plex.chosenClient.lastTimelineObject.time + ' but our first time is ' + firstTime) + if (plex.chosenClient.lastTimelineObject.time != firstTime) { + // We're now playing something! + plex.chosenClient.bufferTime = (i * checkInterval) + global.renderLog.info('Calculated buffer time to be roughly ' + plex.chosenClient.bufferTime + 'ms') + clearInterval(checkBuffer) return } else { - i = i + 1 - // Check if the player is actually playing content now - if (videoTimeline.time > firstTime) { - // We're now playing something! - plex.chosenClient.bufferTime = (i * checkInterval) - global.renderLog.info('Calculated buffer time to be roughly ' + plex.chosenClient.bufferTime + 'ms') - clearInterval(checkBuffer) - } else { - global.renderLog.info('Buffer iteration at ' + i) - } + global.renderLog.info('Buffer iteration at ' + i) } - }) + } }) diff --git a/app/js/plex/PlexClient.js b/app/js/plex/PlexClient.js index e25a7345..09acf619 100644 --- a/app/js/plex/PlexClient.js +++ b/app/js/plex/PlexClient.js @@ -8,9 +8,8 @@ var fs = require('fs'); var PlexServer = require('./PlexServer.js') var PlexTv = require('./PlexTv.js') var PlexConnection = require('./PlexConnection.js') -module.exports = function PlexClient(){ +module.exports = function PlexClient(){ this.commandId = 0; - this.name = null; this.product = null; this.productVersion = null; @@ -56,7 +55,7 @@ module.exports = function PlexClient(){ return } for (let i = 0; i < toProc.length; i++ ) { - //global.log.info('Firing event: ' + msg) + global.log.info('Firing event: ' + msg) toProc[i]() } } @@ -66,23 +65,8 @@ module.exports = function PlexClient(){ } this.events[msg].push(callback) } - this.updateTimelineObject = function(timelines,responseTime,callback) { - if (timelines != null){ - // Valid timeline data - if (responseTime != null) { - this.lastResponseTime = responseTime - } - for (let i in timelines){ - let _timeline = timelines[i]['$'] - if (_timeline.type == 'video'){ - this.lastTimelineObject = timelines[i]['$'] - this.lastTimelineObject.recievedAt = new Date().getTime() - this.fire('client-update') - return callback(_timeline) - } - } - } - return callback(null) + this.clearEvents = function(callback) { + this.events = {} } this.hitApi = function(command,params,connection,callback){ var that = this; @@ -179,10 +163,11 @@ module.exports = function PlexClient(){ //Get the timeline object from the client this.hitApi('/player/timeline/poll',{'wait':0},this.chosenConnection,function(result,responseTime){ if (result){ + //console.log(JSON.stringify(result,null,4)) //Valid response back from the client if (result.MediaContainer != null){ that.updateTimelineObject(result,responseTime,function(){ - return callback(result.MediaContainer.Timeline,responseTime) + return callback(result,responseTime) }) //return (callback(result.MediaContainer.Timeline,responseTime)) } @@ -193,6 +178,27 @@ module.exports = function PlexClient(){ }) } + this.updateTimelineObject = function(result,responseTime,callback) { + if (!result.MediaContainer.Timeline){ + // Not a valid timeline object + return + } + // Valid timeline data + if (responseTime != null) { + this.lastResponseTime = responseTime + } + let timelines = result.MediaContainer.Timeline + for (let i = 0; i < timelines.length; i++){ + let _timeline = timelines[i]['$'] + if (_timeline.type == 'video') { + this.lastTimelineObject = timelines[i]['$'] + this.lastTimelineObject.recievedAt = new Date().getTime() + this.fire('client-update') + return callback(_timeline) + } + } + return callback(null) + } this.pressPlay = function(callback){ //Press play on the client this.hitApi('/player/playback/play',{'wait':0},this.chosenConnection,function(result){ @@ -302,8 +308,6 @@ module.exports = function PlexClient(){ this.getPlayerTime = function(callback){ //Get the current playback time in ms this.hitApi('/player/timeline/poll',{'wait':0},this.chosenConnection,function(result,responseTime,code){ - global.log.info('getPlayerTime result: ' + result) - global.log.info('getPlayerTime code: ' + code) if (result){ //Valid response back from the client var allTimelines = result.MediaContainer.Timeline @@ -326,20 +330,67 @@ module.exports = function PlexClient(){ //We need the following variables to build our paramaters: //MediaId Key, Offset (0 for simplicity), server MachineId, //Server Ip, Server Port, Server Protocol, Path - var command = '/player/playback/playMedia' - var mediaId = '/library/metadata/' + key - var offset = 0 - var serverId = serverObject.clientIdentifier - var address = serverObject.chosenConnection.address - var port = serverObject.chosenConnection.port - var protocol = serverObject.chosenConnection.protocol - var path = serverObject.chosenConnection.uri + mediaId + var that = this + // First lets mirror the item so the user has an idea of what we're about to play + this.mirrorContent(key,serverObject,function(){ + let command = '/player/playback/playMedia' + let mediaId = '/library/metadata/' + key + let offset = 0 + let serverId = serverObject.clientIdentifier + let address = serverObject.chosenConnection.address + let port = serverObject.chosenConnection.port + let protocol = serverObject.chosenConnection.protocol + let path = serverObject.chosenConnection.uri + mediaId - var params = { + let params = { - 'X-Plex-Client-Identifier' : 'PlexTogether', + 'X-Plex-Client-Identifier' : 'PlexTogether_' + that.uuid, + 'key' : mediaId, + 'offset' : offset, + 'machineIdentifier' : serverId, + 'address' : address, + 'port' : port, + 'protocol' : protocol, + 'path' : path, + 'wait' : 0, + 'token': serverObject.accessToken + } + //Now that we've built our params, it's time to hit the client api + that.hitApi(command,params,that.chosenConnection,function(result,the,code){ + global.log.info('play result: ') + global.log.info(code) + if (result != null){ + return callback(result,code,that) + } + else { + return callback(false,code,that) + } + //global.log.info(that.name + ' returned ' + result) + }) + }) + + } + this.mirrorContent = function(key,serverObject,callback) { + //Mirror a media item given a mediaId key and a server to play from + //We need the following variables to build our paramaters: + //MediaId Key, Offset (0 for simplicity), server MachineId, + //Server Ip, Server Port, Server Protocol, Path + var that = this + global.log.info('Trying to mirror content') + + let command = '/player/mirror/details' + let mediaId = '/library/metadata/' + key + let offset = 0 + let serverId = serverObject.clientIdentifier + let address = serverObject.chosenConnection.address + let port = serverObject.chosenConnection.port + let protocol = serverObject.chosenConnection.protocol + let path = serverObject.chosenConnection.uri + mediaId + + let params = { + + 'X-Plex-Client-Identifier' : 'PlexTogether_' + that.uuid, 'key' : mediaId, - 'offset' : offset, 'machineIdentifier' : serverId, 'address' : address, 'port' : port, @@ -350,16 +401,12 @@ module.exports = function PlexClient(){ } //Now that we've built our params, it's time to hit the client api this.hitApi(command,params,this.chosenConnection,function(result,that,code){ - global.log.info('play result: ') - global.log.info(result) - global.log.info(code) if (result != null){ return callback(result,code,that) } else { return callback(false,code,that) } - //global.log.info(that.name + ' returned ' + result) }) } this.subscribe = function(callback) { diff --git a/app/js/plex/PlexServer.js b/app/js/plex/PlexServer.js index bffa139b..603824d0 100644 --- a/app/js/plex/PlexServer.js +++ b/app/js/plex/PlexServer.js @@ -157,7 +157,7 @@ module.exports = function PlexServer(){ this.hitApi('/library/metadata/'+ratingKey,{},function(result,that){ validResults = [] global.log.info('Response back from metadata request') - global.log.info(result) + //global.log.info(result) if (result != null){ if (result._children) { // Old Server version compatibility diff --git a/app/js/plex/PlexTv.js b/app/js/plex/PlexTv.js index 4541adef..c0a7f8b6 100644 --- a/app/js/plex/PlexTv.js +++ b/app/js/plex/PlexTv.js @@ -230,12 +230,12 @@ module.exports = function(){ }); req.on('end', function () { // Check if we got a response from the client we want - // global.log.info('GOT DATA FROM SUBSCRIBE TIMELINE') + global.log.info('GOT DATA FROM SUBSCRIBE TIMELINE') if (req.headers['x-plex-client-identifier'] == that.chosenClient.clientIdentifier) { parseXMLString(body, function(err,result){ if (!err) { //this.lastTimelineObject = result - var allTimelines = result.MediaContainer.Timeline + var allTimelines = result that.chosenClient.updateTimelineObject(allTimelines,null,function(){ }) } diff --git a/app/js/settings.js b/app/js/settings.js index 697105ef..60c19bec 100644 --- a/app/js/settings.js +++ b/app/js/settings.js @@ -139,12 +139,12 @@ function getHandshakeUser(){ } function getSavedCustomPTServer(input){ - console.log("Loading custom server from storage"); + global.renderLog.info("Loading custom server from storage"); var storage = remote.getGlobal('storage'); storage.get('plex-together-custom-settings', function(error, data) { if (error) throw error; if(data.customPTServer != null){ - console.log("custom PT is defined " + data.customPTServer); + global.renderLog.info("custom PT is defined " + data.customPTServer); input.val(data.customPTServer); }else{ //if key doesn't exists, create one with value "http://" @@ -157,7 +157,7 @@ function getSavedCustomPTServer(input){ } function saveCustomPTServer(address){ - console.log("Saving custom server " + address + " to storage"); + global.renderLog.info("Saving custom server " + address + " to storage"); var storage = remote.getGlobal('storage'); storage.set('plex-together-custom-settings',{'customPTServer':address}, function(error) { if (error) throw error; diff --git a/app/js/splash.js b/app/js/splash.js index fa223302..785833cc 100644 --- a/app/js/splash.js +++ b/app/js/splash.js @@ -3,7 +3,7 @@ // const remote = require('remote'); const {ipcRenderer} = require('electron'); var path = require('path'); -splashLog = require('electron-log') +var splashLog = require('electron-log') splashLog.transports.file.format = '[Splash] [{level}] {h}:{i}:{s}:{ms} {text}' ipcRenderer.on('splash-update-status', function(event, msg){ splashLog.info('msg: ' + msg)