diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index fd13b71b..61af9eaa 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -39,9 +39,9 @@ def plexCompanion(fullurl, resume=None): except IndexError: # No matches found, url not like: # http://192.168.0.2:32400/library/metadata/243480 - utils.logMsg("plexCompanion", "Could not parse url: %s" % fullurl, -1) + utils.logMsg("entrypoint - plexCompanion", + "Could not parse url: %s" % fullurl, -1) return False - # TODO: direct play an URL # Initialize embydb embyconn = utils.kodiSQL('emby') embycursor = embyconn.cursor() @@ -272,14 +272,16 @@ def switchPlexUser(): # Delete any userimages. Since there's always only 1 user: position = 0 # position = 0 # utils.window('EmbyAdditionalUserImage.%s' % position, clear=True) - utils.logMsg("PLEX", "Plex home user switch requested", 0) + utils.logMsg("entrypoint switchPlexUser", + "Plex home user switch requested", 0) # Pause library sync thread - user needs to be auth in order to sync utils.window('suspend_LibraryThread', value='true') + # Wait 1 second to ensure that library thread is indeed suspended + xbmc.sleep(1000) # Log out currently signed in user: utils.window('emby_serverStatus', value="401") # Request lib sync to get user view data (e.g. watched/unwatched) utils.window('plex_runLibScan', value='true') - # Reset Plex userdata: resume points, watched/unwatched status ##### THEME MUSIC/VIDEOS ##### diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index c0823861..b58cb372 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -178,6 +178,7 @@ class ThreadedShowSyncInfo(threading.Thread): @utils.logging +@utils.ThreadMethodsAdditionalSuspend('suspend_LibraryThread') @utils.ThreadMethodsStopsync @utils.ThreadMethods class LibrarySync(threading.Thread): @@ -225,7 +226,7 @@ class LibrarySync(threading.Thread): self.maintainViews() completed = False - completed = self.fastSync() + # completed = self.fastSync() if not completed: # Fast sync failed or server plugin is not found @@ -1158,9 +1159,14 @@ class LibrarySync(threading.Thread): # This will prevent an infinite loop in case something goes wrong. startupComplete = True - # Process updates if utils.window('emby_dbScan') != "true": - self.incrementalSync() + # Currently no db scan, so we can start a new scan + if utils.window('plex_runLibScan') == "true": + self.logMsg('Full library scan requested, starting', 1) + utils.window('plex_runLibScan', value='false') + self.fullSync(manualrun=True) + else: + self.incrementalSync() if (utils.window('emby_onWake') == "true" and utils.window('emby_online') == "true"): @@ -1172,10 +1178,7 @@ class LibrarySync(threading.Thread): librarySync = self.startSync() self.logMsg("SyncDatabase onWake (finished) %s" % librarySync, 0) - if self.threadStopped(): - # Set in service.py - self.logMsg("Service terminated thread.", 2) - break + xbmc.sleep(1000) self.logMsg("###===--- LibrarySync Stopped ---===###", 0) diff --git a/resources/lib/playbackutils.py b/resources/lib/playbackutils.py index 5d1b304f..396853d5 100644 --- a/resources/lib/playbackutils.py +++ b/resources/lib/playbackutils.py @@ -42,7 +42,8 @@ class PlaybackUtils(): def play(self, itemid, dbid=None, seektime=None): - self.logMsg("Play called.", 1) + self.logMsg("Play called with itemid: %s, dbid: %s, seektime: %s." + % (itemid, dbid, seektime), 1) doUtils = self.doUtils item = self.item diff --git a/resources/lib/player.py b/resources/lib/player.py index 83feb5ee..05fb90bf 100644 --- a/resources/lib/player.py +++ b/resources/lib/player.py @@ -82,6 +82,7 @@ class Player(xbmc.Player): else: tryCount += 1 else: + utils.window('Plex_currently_playing_itemid', value=itemId) self.logMsg("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId), 0) # Only proceed if an itemId was found. @@ -113,7 +114,7 @@ class Player(xbmc.Player): muted = result.get('muted') # Postdata structure to send to Emby server - url = "{server}/emby/Sessions/Playing" + url = "{server}/:/timeline?" postdata = { 'QueueableMediaTypes': "Video", @@ -194,8 +195,8 @@ class Player(xbmc.Player): # Post playback to server - self.logMsg("Sending POST play started: %s." % postdata, 2) - self.doUtils.downloadUrl(url, postBody=postdata, type="POST") + # self.logMsg("Sending POST play started: %s." % postdata, 2) + # self.doUtils.downloadUrl(url, postBody=postdata, type="POST") # Ensure we do have a runtime try: @@ -370,10 +371,9 @@ class Player(xbmc.Player): # Report progress via websocketclient # postdata = json.dumps(postdata) - self.logMsg("Report: %s" % postdata, 2) # self.ws.sendProgressUpdate(postdata) - url = "{server}/:/timeline?" + urlencode(postdata) - self.doUtils.downloadUrl(url, type="GET") + self.doUtils.downloadUrl( + "{server}/:/timeline?" + urlencode(postdata), type="GET") def onPlayBackPaused( self ): diff --git a/resources/lib/plexbmchelper/subscribers.py b/resources/lib/plexbmchelper/subscribers.py index 56e55e9a..3da2a600 100644 --- a/resources/lib/plexbmchelper/subscribers.py +++ b/resources/lib/plexbmchelper/subscribers.py @@ -19,7 +19,6 @@ class SubscriptionManager: self.protocol = "http" self.port = "" self.playerprops = {} - self.sentstopped = True self.download = downloadutils.DownloadUtils() def getVolume(self): @@ -60,11 +59,25 @@ class SubscriptionManager: ret = "\r\n"+' 10: + break + keyid = str(WINDOW.getProperty('Plex_currently_playing_itemid')) + xbmc.sleep(1000) + count += 1 if keyid: self.lastkey = "/library/metadata/%s"%keyid self.lastratingkey = keyid + ret += ' containerKey="%s"' % (self.lastkey) + ret += ' key="%s"' % (self.lastkey) + ret += ' ratingKey="%s"' % (self.lastratingkey) if pbmc_server: (self.server, self.port) = pbmc_server.split(':') serv = getServerByHost(self.server) @@ -76,9 +89,6 @@ class SubscriptionManager: ret += ' address="%s"' % serv.get('server', self.server) ret += ' port="%s"' % serv.get('port', self.port) ret += ' guid="%s"' % info['guid'] - ret += ' containerKey="%s"' % (self.lastkey or "/library/metadata/900000") - ret += ' key="%s"' % (self.lastkey or "/library/metadata/900000") - ret += ' ratingKey="%s"' % (self.lastratingkey or "900000") ret += ' volume="%s"' % info['volume'] ret += ' shuffle="%s"' % info['shuffle'] @@ -103,7 +113,8 @@ class SubscriptionManager: return True def notifyServer(self, players): - if not players and self.sentstopped: return True + if not players: + return True params = {'state': 'stopped'} for p in players.values(): info = self.playerprops[p.get('playerid')] @@ -120,14 +131,12 @@ class SubscriptionManager: + serv.get('port', 32400) + "/:/timeline" self.download.downloadUrl(url, type="GET", parameters=params) # requests.getwithparams(serv.get('server', 'localhost'), serv.get('port', 32400), "/:/timeline", params, getPlexHeaders(), serv.get('protocol', 'http')) + printDebug("params: %s" % params) + printDebug("players: %s" % players) printDebug("sent server notification with state = %s" % params['state']) WINDOW = xbmcgui.Window(10000) WINDOW.setProperty('plexbmc.nowplaying.sent', '1') - if players: - self.sentstopped = False - else: - self.sentstopped = True - + def controllable(self): return "playPause,play,stop,skipPrevious,skipNext,volume,stepBack,stepForward,seekTo" diff --git a/resources/lib/userclient.py b/resources/lib/userclient.py index 52cb4774..19bffa45 100644 --- a/resources/lib/userclient.py +++ b/resources/lib/userclient.py @@ -260,7 +260,6 @@ class UserClient(threading.Thread): def authenticate(self): # Get /profile/addon_data plx = PlexAPI.PlexAPI() - lib = librarysync.LibrarySync() addondir = xbmc.translatePath(self.addon.getAddonInfo('profile')).decode('utf-8') hasSettings = xbmcvfs.exists("%ssettings.xml" % addondir) @@ -288,7 +287,8 @@ class UserClient(threading.Thread): self.logMsg("Current user: %s" % self.currUser, 1) self.logMsg("Current userId: %s" % self.currUserId, 1) self.logMsg("Current accessToken: xxxx", 1) - lib.resumeThread() + + utils.window('suspend_LibraryThread', value='false') return ##### AUTHENTICATE USER ##### @@ -326,7 +326,7 @@ class UserClient(threading.Thread): utils.window('plex_machineIdentifier', plex_machineIdentifier) self.retry = 0 # Make sure that lib sync thread is not paused - lib.resumeThread() + utils.window('suspend_LibraryThread', value='false') else: self.logMsg("Error: user authentication failed.", -1) utils.settings('accessToken', value="") diff --git a/resources/lib/utils.py b/resources/lib/utils.py index 6e05a511..edc05f52 100644 --- a/resources/lib/utils.py +++ b/resources/lib/utils.py @@ -37,6 +37,22 @@ def ThreadMethodsStopsync(cls): return cls +def ThreadMethodsAdditionalSuspend(windowAttribute): + """ + Decorator to replace threadSuspended(): thread now also suspends if a + Kodi windowAttribute is set to 'true', e.g. 'suspend_LibraryThread' + + Use with any library sync threads. @ThreadMethods still required FIRST + """ + def wrapper(cls): + def threadSuspended(self): + return (self._threadSuspended or True if + window(windowAttribute) == 'true' else False) + cls.threadSuspended = threadSuspended + return cls + return wrapper + + def ThreadMethods(cls): """ Decorator to add the following methods to a threading class: @@ -86,8 +102,8 @@ def ThreadMethods(cls): def logging(cls): """ - A decorator adding logging capabilities to classes. Also adds - self.addonName to the class + A decorator adding logging capabilities to classes. + Also adds self.addonName to the class Syntax: self.logMsg(message, loglevel) @@ -102,9 +118,6 @@ def logging(cls): logMsg(title, msg, lvl) cls.logMsg = newFunction - # Override the name, we don't want the decorators name showing up - __name__ = cls.__name__ - # Return class to render this a decorator return cls @@ -143,7 +156,6 @@ def window(property, value=None, clear=False, windowid=10000): property = property.encode("utf-8") if isinstance(value, unicode): value = value.encode("utf-8")''' - if clear: WINDOW.clearProperty(property) elif value is not None: