diff --git a/default.py b/default.py index 96983316..164db4c4 100644 --- a/default.py +++ b/default.py @@ -33,7 +33,7 @@ sys_path.append(_base_resource) import entrypoint from utils import window, pickl_window, reset, passwordsXML, language as lang,\ - dialog + dialog, plex_command from pickler import unpickle_me from PKC_listitem import convert_PKC_to_listitem import variables as v @@ -127,28 +127,29 @@ class Main(): log.error('Not connected to a PMS.') else: if mode == 'repair': - window('plex_runLibScan', value='repair') log.info('Requesting repair lib sync') + plex_command('RUN_LIB_SCAN', 'repair') elif mode == 'manualsync': log.info('Requesting full library scan') - window('plex_runLibScan', value='full') + plex_command('RUN_LIB_SCAN', 'full') elif mode == 'texturecache': - window('plex_runLibScan', value='del_textures') + log.info('Requesting texture caching of all textures') + plex_command('RUN_LIB_SCAN', 'textures') elif mode == 'chooseServer': entrypoint.chooseServer() elif mode == 'refreshplaylist': log.info('Requesting playlist/nodes refresh') - window('plex_runLibScan', value='views') + plex_command('RUN_LIB_SCAN', 'views') elif mode == 'deviceid': self.deviceid() elif mode == 'fanart': log.info('User requested fanarttv refresh') - window('plex_runLibScan', value='fanart') + plex_command('RUN_LIB_SCAN', 'fanart') elif '/extrafanart' in argv[0]: plexpath = argv[2][1:] @@ -165,7 +166,8 @@ class Main(): else: entrypoint.doMainListing(content_type=params.get('content_type')) - def play(self): + @staticmethod + def play(): """ Start up playback_starter in main Python thread """ @@ -190,7 +192,8 @@ class Main(): listitem = convert_PKC_to_listitem(result.listitem) setResolvedUrl(HANDLE, True, listitem) - def deviceid(self): + @staticmethod + def deviceid(): deviceId_old = window('plex_client_Id') from clientinfo import getDeviceId try: @@ -205,6 +208,7 @@ class Main(): dialog('ok', lang(29999), lang(33033)) executebuiltin('RestartApp') + if __name__ == '__main__': log.info('%s started' % v.ADDON_ID) Main() diff --git a/resources/lib/command_pipeline.py b/resources/lib/command_pipeline.py index 64fc799c..a50edd8a 100644 --- a/resources/lib/command_pipeline.py +++ b/resources/lib/command_pipeline.py @@ -64,6 +64,8 @@ class Monitor_Window(Thread): elif value.startswith('PLEX_USERNAME-'): state.PLEX_USERNAME = \ value.replace('PLEX_USERNAME-', '') or None + elif value.startswith('RUN_LIB_SCAN-'): + state.RUN_LIB_SCAN = value.replace('RUN_LIB_SCAN-', '') else: raise NotImplementedError('%s not implemented' % value) else: diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index 5dfc93d2..3fc8f0a8 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -975,7 +975,7 @@ def __LogIn(): SUSPEND_LIBRARY_THREAD is set to False in service.py if user was signed out! """ - window('plex_runLibScan', value='full') + plex_command('RUN_LIB_SCAN', 'full') # Restart user client plex_command('SUSPEND_USER_CLIENT', 'False') diff --git a/resources/lib/kodimonitor.py b/resources/lib/kodimonitor.py index 3c60a944..a46c509a 100644 --- a/resources/lib/kodimonitor.py +++ b/resources/lib/kodimonitor.py @@ -9,7 +9,8 @@ from xbmc import Monitor, Player, sleep import downloadutils import plexdb_functions as plexdb -from utils import window, settings, CatchExceptions, tryDecode, tryEncode +from utils import window, settings, CatchExceptions, tryDecode, tryEncode, \ + plex_command from PlexFunctions import scrobble from kodidb_functions import get_kodiid_from_filename from PlexAPI import API @@ -80,7 +81,7 @@ class KodiMonitor(Monitor): window(window_value, value=settings(settings_value)) if settings_value == 'fetch_pms_item_number': log.info('Requesting playlist/nodes refresh') - window('plex_runLibScan', value="views") + plex_command('RUN_LIB_SCAN', 'views') # Reset the state variables in state.py for settings_value, state_value in STATE_SETTINGS.iteritems(): new = settings(settings_value) @@ -157,7 +158,7 @@ class KodiMonitor(Monitor): elif method == "GUI.OnScreensaverDeactivated": if settings('dbSyncScreensaver') == "true": sleep(5000) - window('plex_runLibScan', value="full") + plex_command('RUN_LIB_SCAN', 'full') elif method == "System.OnQuit": log.info('Kodi OnQuit detected - shutting down') diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index 85e6697f..a555e601 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -1391,6 +1391,69 @@ class LibrarySync(Thread): 'refresh': refresh }) + def triage_lib_scans(self): + """ + """ + if state.RUN_LIB_SCAN in ("full", "repair"): + log.info('Full library scan requested, starting') + window('plex_dbScan', value="true") + state.DB_SCAN = True + if state.RUN_LIB_SCAN == "full": + self.fullSync() + elif state.RUN_LIB_SCAN == "repair": + self.fullSync(repair=True) + state.RUN_LIB_SCAN = None + window('plex_dbScan', clear=True) + state.DB_SCAN = False + # Full library sync finished + self.showKodiNote(lang(39407)) + # Reset views was requested from somewhere else + elif state.RUN_LIB_SCAN == "views": + log.info('Refresh playlist and nodes requested, starting') + window('plex_dbScan', value="true") + state.DB_SCAN = True + state.RUN_LIB_SCAN = None + + # First remove playlists + deletePlaylists() + # Remove video nodes + deleteNodes() + # Kick off refresh + if self.maintainViews() is True: + # Ran successfully + log.info("Refresh playlists/nodes completed") + # "Plex playlists/nodes refreshed" + self.showKodiNote(lang(39405)) + else: + # Failed + log.error("Refresh playlists/nodes failed") + # "Plex playlists/nodes refresh failed" + self.showKodiNote(lang(39406), + icon="error") + window('plex_dbScan', clear=True) + state.DB_SCAN = False + elif state.RUN_LIB_SCAN == 'fanart': + state.RUN_LIB_SCAN = None + # Only look for missing fanart (No) + # or refresh all fanart (Yes) + self.fanartSync(refresh=dialog( + 'yesno', + heading='{plex}', + line1=lang(39223), + nolabel=lang(39224), + yeslabel=lang(39225))) + elif state.RUN_LIB_SCAN == 'textures': + state.RUN_LIB_SCAN = None + state.DB_SCAN = True + window('plex_dbScan', value="true") + import artwork + artwork.Artwork().fullTextureCacheSync() + window('plex_dbScan', clear=True) + state.DB_SCAN = False + else: + raise NotImplementedError('Library scan not defined: %s' + % state.RUN_LIB_SCAN) + def run(self): try: self.run_internal() @@ -1522,115 +1585,62 @@ class LibrarySync(Thread): # Currently no db scan, so we can start a new scan elif state.DB_SCAN is False: - # Force-show dialogs since they are user-initiated - self.force_dialog = True # Full scan was requested from somewhere else, e.g. userclient - if window('plex_runLibScan') in ("full", "repair"): - log.info('Full library scan requested, starting') - window('plex_dbScan', value="true") + if state.RUN_LIB_SCAN is not None: + # Force-show dialogs since they are user-initiated + self.force_dialog = True + self.triage_lib_scans() + self.force_dialog = False + continue + now = getUnixTimestamp() + # Standard syncs - don't force-show dialogs + self.force_dialog = False + if (now - lastSync > fullSyncInterval and + not self.xbmcplayer.isPlaying()): + lastSync = now + log.info('Doing scheduled full library scan') state.DB_SCAN = True - if window('plex_runLibScan') == "full": - fullSync() - elif window('plex_runLibScan') == "repair": - fullSync(repair=True) - window('plex_runLibScan', clear=True) + window('plex_dbScan', value="true") + if fullSync() is False and not thread_stopped(): + log.error('Could not finish scheduled full sync') + self.force_dialog = True + self.showKodiNote(lang(39410), + icon='error') + self.force_dialog = False window('plex_dbScan', clear=True) state.DB_SCAN = False # Full library sync finished self.showKodiNote(lang(39407)) - # Reset views was requested from somewhere else - elif window('plex_runLibScan') == "views": - log.info('Refresh playlist and nodes requested, starting') - window('plex_dbScan', value="true") - state.DB_SCAN = True - window('plex_runLibScan', clear=True) - - # First remove playlists - deletePlaylists() - # Remove video nodes - deleteNodes() - # Kick off refresh - if self.maintainViews() is True: - # Ran successfully - log.info("Refresh playlists/nodes completed") - # "Plex playlists/nodes refreshed" - self.showKodiNote(lang(39405)) - else: - # Failed - log.error("Refresh playlists/nodes failed") - # "Plex playlists/nodes refresh failed" - self.showKodiNote(lang(39406), - icon="error") - window('plex_dbScan', clear=True) - state.DB_SCAN = False - elif window('plex_runLibScan') == 'fanart': - window('plex_runLibScan', clear=True) - # Only look for missing fanart (No) - # or refresh all fanart (Yes) - self.fanartSync(refresh=dialog( - 'yesno', - heading='{plex}', - line1=lang(39223), - nolabel=lang(39224), - yeslabel=lang(39225))) - elif window('plex_runLibScan') == 'del_textures': - window('plex_runLibScan', clear=True) + elif now - lastTimeSync > oneDay: + lastTimeSync = now + log.info('Starting daily time sync') state.DB_SCAN = True window('plex_dbScan', value="true") - import artwork - artwork.Artwork().fullTextureCacheSync() + self.syncPMStime() window('plex_dbScan', clear=True) state.DB_SCAN = False - else: - now = getUnixTimestamp() - # Standard syncs - don't force-show dialogs - self.force_dialog = False - if (now - lastSync > fullSyncInterval and - not self.xbmcplayer.isPlaying()): - lastSync = now - log.info('Doing scheduled full library scan') - state.DB_SCAN = True - window('plex_dbScan', value="true") - if fullSync() is False and not thread_stopped(): - log.error('Could not finish scheduled full sync') - self.force_dialog = True - self.showKodiNote(lang(39410), - icon='error') - self.force_dialog = False - window('plex_dbScan', clear=True) - state.DB_SCAN = False - # Full library sync finished - self.showKodiNote(lang(39407)) - elif now - lastTimeSync > oneDay: - lastTimeSync = now - log.info('Starting daily time sync') - state.DB_SCAN = True - window('plex_dbScan', value="true") - self.syncPMStime() - window('plex_dbScan', clear=True) - state.DB_SCAN = False - elif enableBackgroundSync: - # Check back whether we should process something - # Only do this once every while (otherwise, potentially - # many screen refreshes lead to flickering) - if now - lastProcessing > 5: - lastProcessing = now - processItems() - # See if there is a PMS message we need to handle - try: - message = queue.get(block=False) - except Queue.Empty: - xbmc.sleep(100) - continue - # Got a message from PMS; process it - else: - processMessage(message) - queue.task_done() - # NO sleep! - continue - else: - # Still sleep if backgroundsync disabled + elif enableBackgroundSync: + # Check back whether we should process something + # Only do this once every while (otherwise, potentially + # many screen refreshes lead to flickering) + if now - lastProcessing > 5: + lastProcessing = now + processItems() + # See if there is a PMS message we need to handle + try: + message = queue.get(block=False) + except Queue.Empty: xbmc.sleep(100) + continue + # Got a message from PMS; process it + else: + processMessage(message) + queue.task_done() + # NO sleep! + continue + else: + # Still sleep if backgroundsync disabled + xbmc.sleep(100) xbmc.sleep(100) diff --git a/resources/lib/state.py b/resources/lib/state.py index 91c9d913..7a9cd8ef 100644 --- a/resources/lib/state.py +++ b/resources/lib/state.py @@ -26,6 +26,8 @@ RESTRICTED_USER = False DIRECT_PATHS = False # Shall we replace custom user ratings with the number of versions available? INDICATE_MEDIA_VERSIONS = False +# Do we need to run a special library scan? +RUN_LIB_SCAN = None # Stemming from the PKC settings.xml # Shall we show Kodi dialogs when synching? diff --git a/service.py b/service.py index c17fb082..e0990f92 100644 --- a/service.py +++ b/service.py @@ -110,7 +110,7 @@ class Service(): "plex_dbCheck", "plex_kodiScan", "plex_shouldStop", "plex_dbScan", "plex_initialScan", "plex_customplayqueue", "plex_playbackProps", - "plex_runLibScan", "pms_token", "plex_token", + "pms_token", "plex_token", "pms_server", "plex_machineIdentifier", "plex_servername", "plex_authenticated", "PlexUserImage", "useDirectPaths", "kodiplextimeoffset", "countError", "countUnauthorized",