From 52a5d352957d62e4f066de48faa4a184627adc8c Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Wed, 17 Feb 2016 02:13:37 -0600 Subject: [PATCH] Update for strings --- resources/lib/librarysync.py | 287 ++++++++++++++++-------------- resources/lib/playbackutils.py | 79 ++++---- resources/lib/player.py | 116 ++++++------ resources/lib/playlist.py | 23 ++- resources/lib/playutils.py | 117 ++++++------ resources/lib/read_embyserver.py | 22 ++- resources/lib/userclient.py | 204 +++++++++++---------- resources/lib/videonodes.py | 10 +- resources/lib/websocket_client.py | 2 +- service.py | 6 +- 10 files changed, 477 insertions(+), 389 deletions(-) diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index ecbb63cf..261e6c48 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -47,7 +47,7 @@ class LibrarySync(threading.Thread): self.clientInfo = clientinfo.ClientInfo() self.addonName = self.clientInfo.getAddonName() - self.doUtils = downloadutils.DownloadUtils() + self.doUtils = downloadutils.DownloadUtils().downloadUrl self.user = userclient.UserClient() self.emby = embyserver.Read_EmbyServer() self.vnodes = videonodes.VideoNodes() @@ -72,17 +72,19 @@ class LibrarySync(threading.Thread): return dialog def startSync(self): + + settings = utils.settings # Run at start up - optional to use the server plugin - if utils.settings('SyncInstallRunDone') == "true": + if settings('SyncInstallRunDone') == "true": # Validate views self.refreshViews() completed = False # Verify if server plugin is installed. - if utils.settings('serverSync') == "true": + if settings('serverSync') == "true": # Try to use fast start up url = "{server}/emby/Plugins?format=json" - result = self.doUtils.downloadUrl(url) + result = self.doUtils(url) for plugin in result: if plugin['Name'] == "Emby.Kodi Sync Queue": @@ -100,30 +102,43 @@ class LibrarySync(threading.Thread): def fastSync(self): + log = self.logMsg + + doUtils = self.doUtils + lastSync = utils.settings('LastIncrementalSync') if not lastSync: lastSync = "2010-01-01T00:00:00Z" lastSyncTime = utils.convertdate(lastSync) - self.logMsg("Last sync run: %s" % lastSyncTime, 1) + log("Last sync run: %s" % lastSyncTime, 1) # get server RetentionDateTime url = "{server}/Emby.Kodi.SyncQueue/GetServerDateTime?format=json" - result = self.doUtils.downloadUrl(url) + result = doUtils(url) retention_time = "2010-01-01T00:00:00Z" if result and result.get('RetentionDateTime'): retention_time = result['RetentionDateTime'] + + #Try/except equivalent + ''' + try: + retention_time = result['RetentionDateTime'] + except (TypeError, KeyError): + retention_time = "2010-01-01T00:00:00Z" + ''' + retention_time = utils.convertdate(retention_time) - self.logMsg("RetentionDateTime: %s" % retention_time, 1) + log("RetentionDateTime: %s" % retention_time, 1) # if last sync before retention time do a full sync if retention_time > lastSyncTime: - self.logMsg("Fast sync server retention insurficient, fall back to full sync", 1) + log("Fast sync server retention insufficient, fall back to full sync", 1) return False url = "{server}/emby/Emby.Kodi.SyncQueue/{UserId}/GetItems?format=json" params = {'LastUpdateDT': lastSync} - result = self.doUtils.downloadUrl(url, parameters=params) + result = doUtils(url, parameters=params) try: processlist = { @@ -135,36 +150,38 @@ class LibrarySync(threading.Thread): } except (KeyError, TypeError): - self.logMsg("Failed to retrieve latest updates using fast sync.", 1) + log("Failed to retrieve latest updates using fast sync.", 1) return False else: - self.logMsg("Fast sync changes: %s" % result, 1) + log("Fast sync changes: %s" % result, 1) for action in processlist: self.triage_items(action, processlist[action]) return True def saveLastSync(self): + + log = self.logMsg # Save last sync time overlap = 2 url = "{server}/Emby.Kodi.SyncQueue/GetServerDateTime?format=json" - result = self.doUtils.downloadUrl(url) + result = self.doUtils(url) try: # datetime fails when used more than once, TypeError server_time = result['ServerDateTime'] server_time = utils.convertdate(server_time) except Exception as e: # If the server plugin is not installed or an error happened. - self.logMsg("An exception occurred: %s" % e, 1) + log("An exception occurred: %s" % e, 1) time_now = datetime.utcnow()-timedelta(minutes=overlap) lastSync = time_now.strftime('%Y-%m-%dT%H:%M:%SZ') - self.logMsg("New sync time: client time -%s min: %s" % (overlap, lastSync), 1) + log("New sync time: client time -%s min: %s" % (overlap, lastSync), 1) else: lastSync = (server_time - timedelta(minutes=overlap)).strftime('%Y-%m-%dT%H:%M:%SZ') - self.logMsg("New sync time: server time -%s min: %s" % (overlap, lastSync), 1) + log("New sync time: server time -%s min: %s" % (overlap, lastSync), 1) finally: utils.settings('LastIncrementalSync', value=lastSync) @@ -179,32 +196,39 @@ class LibrarySync(threading.Thread): return False def dbCommit(self, connection): + + log = self.logMsg + window = utils.window # Central commit, verifies if Kodi database update is running - kodidb_scan = utils.window('emby_kodiScan') == "true" + kodidb_scan = window('emby_kodiScan') == "true" while kodidb_scan: - self.logMsg("Kodi scan is running. Waiting...", 1) - kodidb_scan = utils.window('emby_kodiScan') == "true" + log("Kodi scan is running. Waiting...", 1) + kodidb_scan = window('emby_kodiScan') == "true" if self.shouldStop(): - self.logMsg("Commit unsuccessful. Sync terminated.", 1) + log("Commit unsuccessful. Sync terminated.", 1) break if self.monitor.waitForAbort(1): # Abort was requested while waiting. We should exit - self.logMsg("Commit unsuccessful.", 1) + log("Commit unsuccessful.", 1) break else: connection.commit() - self.logMsg("Commit successful.", 1) + log("Commit successful.", 1) def fullSync(self, manualrun=False, repair=False): + + log = self.logMsg + window = utils.window + settings = utils.settings # Only run once when first setting up. Can be run manually. emby = self.emby music_enabled = utils.settings('enableMusic') == "true" - utils.window('emby_dbScan', value="true") + window('emby_dbScan', value="true") # Add sources utils.sourcesXML() @@ -232,7 +256,7 @@ class LibrarySync(threading.Thread): message = "Repair sync" else: message = "Initial sync" - utils.window('emby_initialScan', value="true") + window('emby_initialScan', value="true") pDialog = self.progressDialog("%s" % message, forced=True) starttotal = datetime.now() @@ -253,7 +277,7 @@ class LibrarySync(threading.Thread): completed = process[itemtype](embycursor, kodicursor, pDialog) if not completed: - utils.window('emby_dbScan', clear=True) + window('emby_dbScan', clear=True) if pDialog: pDialog.close() @@ -264,8 +288,7 @@ class LibrarySync(threading.Thread): self.dbCommit(kodiconn) embyconn.commit() elapsedTime = datetime.now() - startTime - self.logMsg( - "SyncDatabase (finished %s in: %s)" + log("SyncDatabase (finished %s in: %s)" % (itemtype, str(elapsedTime).split('.')[0]), 1) else: # Close the Kodi cursor @@ -281,7 +304,7 @@ class LibrarySync(threading.Thread): completed = self.music(embycursor, musiccursor, pDialog) if not completed: - utils.window('emby_dbScan', clear=True) + window('emby_dbScan', clear=True) if pDialog: pDialog.close() @@ -292,8 +315,7 @@ class LibrarySync(threading.Thread): musicconn.commit() embyconn.commit() elapsedTime = datetime.now() - startTime - self.logMsg( - "SyncDatabase (finished music in: %s)" + log("SyncDatabase (finished music in: %s)" % (str(elapsedTime).split('.')[0]), 1) musiccursor.close() @@ -302,18 +324,18 @@ class LibrarySync(threading.Thread): embycursor.close() - utils.settings('SyncInstallRunDone', value="true") - utils.settings("dbCreatedWithVersion", self.clientInfo.getVersion()) + settings('SyncInstallRunDone', value="true") + settings("dbCreatedWithVersion", self.clientInfo.getVersion()) self.saveLastSync() xbmc.executebuiltin('UpdateLibrary(video)') elapsedtotal = datetime.now() - starttotal - utils.window('emby_dbScan', clear=True) - utils.window('emby_initialScan', clear=True) + window('emby_dbScan', clear=True) + window('emby_initialScan', clear=True) xbmcgui.Dialog().notification( heading="Emby for Kodi", - message="%s completed in: %s" % - (message, str(elapsedtotal).split('.')[0]), + message="%s %s %s" % + (message, utils.language(33025), str(elapsedtotal).split('.')[0]), icon="special://home/addons/plugin.video.emby/icon.png", sound=False) return True @@ -336,6 +358,8 @@ class LibrarySync(threading.Thread): embycursor.close() def maintainViews(self, embycursor, kodicursor): + + log = self.logMsg # Compare the views to emby emby_db = embydb.Embydb_Functions(embycursor) kodi_db = kodidb.Kodidb_Functions(kodicursor) @@ -344,14 +368,14 @@ class LibrarySync(threading.Thread): # Get views url = "{server}/emby/Users/{UserId}/Views?format=json" - result = doUtils.downloadUrl(url) + result = doUtils(url) grouped_views = result['Items'] try: groupedFolders = self.user.userSettings['Configuration']['GroupedFolders'] except TypeError: url = "{server}/emby/Users/{UserId}?format=json" - result = doUtils.downloadUrl(url) + result = doUtils(url) groupedFolders = result['Configuration']['GroupedFolders'] # total nodes for window properties @@ -402,7 +426,7 @@ class LibrarySync(threading.Thread): emby_db.addView(folderid, foldername, viewtype, tagid) else: - self.logMsg(' '.join(( + log(' '.join(( "Found viewid: %s" % folderid, "viewname: %s" % current_viewname, @@ -411,7 +435,7 @@ class LibrarySync(threading.Thread): # View was modified, update with latest info if current_viewname != foldername: - self.logMsg("viewid: %s new viewname: %s" % (folderid, foldername), 1) + log("viewid: %s new viewname: %s" % (folderid, foldername), 1) tagid = kodi_db.createTag(foldername) # Update view with new info @@ -466,6 +490,9 @@ class LibrarySync(threading.Thread): utils.window('Emby.nodes.total', str(totalnodes)) def movies(self, embycursor, kodicursor, pdialog): + + log = self.logMsg + lang = utils.language # Get movies from emby emby = self.emby emby_db = embydb.Embydb_Functions(embycursor) @@ -473,7 +500,7 @@ class LibrarySync(threading.Thread): views = emby_db.getView_byType('movies') views += emby_db.getView_byType('mixed') - self.logMsg("Media folders: %s" % views, 1) + log("Media folders: %s" % views, 1) ##### PROCESS MOVIES ##### for view in views: @@ -488,7 +515,7 @@ class LibrarySync(threading.Thread): if pdialog: pdialog.update( heading="Emby for Kodi", - message="Gathering movies from view: %s..." % viewName) + message="%s %s..." % (lang(33017), viewName)) # Initial or repair sync all_embymovies = emby.getMovies(viewId, dialog=pdialog) @@ -511,12 +538,12 @@ class LibrarySync(threading.Thread): count += 1 movies.add_update(embymovie, viewName, viewId) else: - self.logMsg("Movies finished.", 2) + log("Movies finished.", 2) ##### PROCESS BOXSETS ##### if pdialog: - pdialog.update(heading="Emby for Kodi", message="Gathering boxsets from server...") + pdialog.update(heading="Emby for Kodi", message=lang(33018)) boxsets = emby.getBoxset(dialog=pdialog) total = boxsets['TotalRecordCount'] @@ -538,18 +565,20 @@ class LibrarySync(threading.Thread): count += 1 movies.add_updateBoxset(boxset) else: - self.logMsg("Boxsets finished.", 2) + log("Boxsets finished.", 2) return True def musicvideos(self, embycursor, kodicursor, pdialog): + + log = self.logMsg # Get musicvideos from emby emby = self.emby emby_db = embydb.Embydb_Functions(embycursor) mvideos = itemtypes.MusicVideos(embycursor, kodicursor) views = emby_db.getView_byType('musicvideos') - self.logMsg("Media folders: %s" % views, 1) + log("Media folders: %s" % views, 1) for view in views: @@ -563,7 +592,7 @@ class LibrarySync(threading.Thread): if pdialog: pdialog.update( heading="Emby for Kodi", - message="Gathering musicvideos from view: %s..." % viewName) + message="%s %s..." % (utils.language(33019), viewName)) # Initial or repair sync all_embymvideos = emby.getMusicVideos(viewId, dialog=pdialog) @@ -586,11 +615,13 @@ class LibrarySync(threading.Thread): count += 1 mvideos.add_update(embymvideo, viewName, viewId) else: - self.logMsg("MusicVideos finished.", 2) + log("MusicVideos finished.", 2) return True def tvshows(self, embycursor, kodicursor, pdialog): + + log = self.logMsg # Get shows from emby emby = self.emby emby_db = embydb.Embydb_Functions(embycursor) @@ -598,7 +629,7 @@ class LibrarySync(threading.Thread): views = emby_db.getView_byType('tvshows') views += emby_db.getView_byType('mixed') - self.logMsg("Media folders: %s" % views, 1) + log("Media folders: %s" % views, 1) for view in views: @@ -612,7 +643,7 @@ class LibrarySync(threading.Thread): if pdialog: pdialog.update( heading="Emby for Kodi", - message="Gathering tvshows from view: %s..." % viewName) + message="%s %s..." % (utils.language(33020), viewName)) all_embytvshows = emby.getShows(viewId, dialog=pdialog) total = all_embytvshows['TotalRecordCount'] @@ -648,7 +679,7 @@ class LibrarySync(threading.Thread): pdialog.update(percentage, message="%s - %s" % (title, episodetitle)) tvshows.add_updateEpisode(episode) else: - self.logMsg("TVShows finished.", 2) + log("TVShows finished.", 2) return True @@ -665,19 +696,19 @@ class LibrarySync(threading.Thread): 'songs': [emby.getSongs, music.add_updateSong] } types = ['artists', 'albums', 'songs'] - for type in types: + for itemtype in types: if pdialog: pdialog.update( heading="Emby for Kodi", - message="Gathering %s..." % type) + message="%s %s..." % (utils.language(33021), itemtype)) - all_embyitems = process[type][0](dialog=pdialog) + all_embyitems = process[itemtype][0](dialog=pdialog) total = all_embyitems['TotalRecordCount'] embyitems = all_embyitems['Items'] if pdialog: - pdialog.update(heading="Processing %s / %s items" % (type, total)) + pdialog.update(heading="Processing %s / %s items" % (itemtype, total)) count = 0 for embyitem in embyitems: @@ -691,9 +722,9 @@ class LibrarySync(threading.Thread): pdialog.update(percentage, message=title) count += 1 - process[type][1](embyitem) + process[itemtype][1](embyitem) else: - self.logMsg("%s finished." % type, 2) + self.logMsg("%s finished." % itemtype, 2) return True @@ -719,6 +750,8 @@ class LibrarySync(threading.Thread): def incrementalSync(self): + log = self.logMsg + embyconn = utils.kodiSQL('emby') embycursor = embyconn.cursor() kodiconn = utils.kodiSQL('video') @@ -788,7 +821,7 @@ class LibrarySync(threading.Thread): if update_embydb: update_embydb = False - self.logMsg("Updating emby database.", 1) + log("Updating emby database.", 1) embyconn.commit() self.saveLastSync() @@ -797,7 +830,7 @@ class LibrarySync(threading.Thread): self.forceLibraryUpdate = False self.dbCommit(kodiconn) - self.logMsg("Updating video library.", 1) + log("Updating video library.", 1) utils.window('emby_kodiScan', value="true") xbmc.executebuiltin('UpdateLibrary(video)') @@ -839,10 +872,16 @@ class LibrarySync(threading.Thread): def run_internal(self): + log = self.logMsg + lang = utils.language + window = utils.window + settings = utils.settings + dialog = xbmcgui.Dialog() + startupComplete = False monitor = self.monitor - self.logMsg("---===### Starting LibrarySync ###===---", 0) + log("---===### Starting LibrarySync ###===---", 0) while not monitor.abortRequested(): @@ -853,36 +892,24 @@ class LibrarySync(threading.Thread): # Abort was requested while waiting. We should exit break - if (utils.window('emby_dbCheck') != "true" and - utils.settings('SyncInstallRunDone') == "true"): - + if (window('emby_dbCheck') != "true" and settings('SyncInstallRunDone') == "true"): # Verify the validity of the database - currentVersion = utils.settings('dbCreatedWithVersion') - minVersion = utils.window('emby_minDBVersion') + currentVersion = settings('dbCreatedWithVersion') + minVersion = window('emby_minDBVersion') uptoDate = self.compareDBVersion(currentVersion, minVersion) if not uptoDate: - self.logMsg( - "Db version out of date: %s minimum version required: %s" + log("Database version out of date: %s minimum version required: %s" % (currentVersion, minVersion), 0) - resp = xbmcgui.Dialog().yesno( - heading="Db Version", - line1=( - "Detected the database needs to be " - "recreated for this version of Emby for Kodi. " - "Proceed?")) + resp = dialog.yesno("Emby for Kodi", lang(33022)) if not resp: - self.logMsg("Db version out of date! USER IGNORED!", 0) - xbmcgui.Dialog().ok( - heading="Emby for Kodi", - line1=( - "Emby for Kodi may not work correctly " - "until the database is reset.")) + log("Database version is out of date! USER IGNORED!", 0) + dialog.ok("Emby for Kodi", lang(33023)) else: utils.reset() - utils.window('emby_dbCheck', value="true") + window('emby_dbCheck', value="true") if not startupComplete: @@ -890,58 +917,52 @@ class LibrarySync(threading.Thread): videoDb = utils.getKodiVideoDBPath() if not xbmcvfs.exists(videoDb): # Database does not exists - self.logMsg( - "The current Kodi version is incompatible " - "with the Emby for Kodi add-on. Please visit " - "https://github.com/MediaBrowser/Emby.Kodi/wiki " - "to know which Kodi versions are supported.", 0) + log( + "The current Kodi version is incompatible " + "with the Emby for Kodi add-on. Please visit " + "https://github.com/MediaBrowser/Emby.Kodi/wiki " + "to know which Kodi versions are supported.", 0) - xbmcgui.Dialog().ok( - heading="Emby Warning", - line1=( - "Cancelling the database syncing process. " - "Current Kodi versoin: %s is unsupported. " - "Please verify your logs for more info." - % xbmc.getInfoLabel('System.BuildVersion'))) + dialog.ok( + heading="Emby for Kodi", + line1=lang(33024)) break # Run start up sync - self.logMsg("Db version: %s" % utils.settings('dbCreatedWithVersion'), 0) - self.logMsg("SyncDatabase (started)", 1) + log("Database version: %s" % settings('dbCreatedWithVersion'), 0) + log("SyncDatabase (started)", 1) startTime = datetime.now() librarySync = self.startSync() elapsedTime = datetime.now() - startTime - self.logMsg( - "SyncDatabase (finished in: %s) %s" + log("SyncDatabase (finished in: %s) %s" % (str(elapsedTime).split('.')[0], librarySync), 1) # Only try the initial sync once per kodi session regardless # This will prevent an infinite loop in case something goes wrong. startupComplete = True # Process updates - if utils.window('emby_dbScan') != "true": + if window('emby_dbScan') != "true": self.incrementalSync() - if (utils.window('emby_onWake') == "true" and - utils.window('emby_online') == "true"): + if window('emby_onWake') == "true" and window('emby_online') == "true": # Kodi is waking up # Set in kodimonitor.py - utils.window('emby_onWake', clear=True) - if utils.window('emby_syncRunning') != "true": - self.logMsg("SyncDatabase onWake (started)", 0) + window('emby_onWake', clear=True) + if window('emby_syncRunning') != "true": + log("SyncDatabase onWake (started)", 0) librarySync = self.startSync() - self.logMsg("SyncDatabase onWake (finished) %s" % librarySync, 0) + log("SyncDatabase onWake (finished) %s" % librarySync, 0) if self.stop_thread: # Set in service.py - self.logMsg("Service terminated thread.", 2) + log("Service terminated thread.", 2) break if monitor.waitForAbort(1): # Abort was requested while waiting. We should exit break - self.logMsg("###===--- LibrarySync Stopped ---===###", 0) + log("###===--- LibrarySync Stopped ---===###", 0) def stopThread(self): self.stop_thread = True @@ -966,6 +987,9 @@ class ManualSync(LibrarySync): def movies(self, embycursor, kodicursor, pdialog): + + log = self.logMsg + lang = utils.language # Get movies from emby emby = self.emby emby_db = embydb.Embydb_Functions(embycursor) @@ -973,7 +997,7 @@ class ManualSync(LibrarySync): views = emby_db.getView_byType('movies') views += emby_db.getView_byType('mixed') - self.logMsg("Media folders: %s" % views, 1) + log("Media folders: %s" % views, 1) # Pull the list of movies and boxsets in Kodi try: @@ -1003,7 +1027,7 @@ class ManualSync(LibrarySync): if pdialog: pdialog.update( heading="Emby for Kodi", - message="Comparing movies from view: %s..." % viewName) + message="%s %s..." % (lang(33026), viewName)) all_embymovies = emby.getMovies(viewId, basic=True, dialog=pdialog) for embymovie in all_embymovies['Items']: @@ -1020,7 +1044,7 @@ class ManualSync(LibrarySync): # Only update if movie is not in Kodi or checksum is different updatelist.append(itemid) - self.logMsg("Movies to update for %s: %s" % (viewName, updatelist), 1) + log("Movies to update for %s: %s" % (viewName, updatelist), 1) embymovies = emby.getFullItems(updatelist) total = len(updatelist) del updatelist[:] @@ -1047,9 +1071,7 @@ class ManualSync(LibrarySync): embyboxsets = [] if pdialog: - pdialog.update( - heading="Emby for Kodi", - message="Comparing boxsets...") + pdialog.update("Emby for Kodi", lang(33027)) for boxset in boxsets['Items']: @@ -1066,7 +1088,7 @@ class ManualSync(LibrarySync): updatelist.append(itemid) embyboxsets.append(boxset) - self.logMsg("Boxsets to update: %s" % updatelist, 1) + log("Boxsets to update: %s" % updatelist, 1) total = len(updatelist) if pdialog: @@ -1091,24 +1113,26 @@ class ManualSync(LibrarySync): if kodimovie not in all_embymoviesIds: movies.remove(kodimovie) else: - self.logMsg("Movies compare finished.", 1) + log("Movies compare finished.", 1) for boxset in all_kodisets: if boxset not in all_embyboxsetsIds: movies.remove(boxset) else: - self.logMsg("Boxsets compare finished.", 1) + log("Boxsets compare finished.", 1) return True def musicvideos(self, embycursor, kodicursor, pdialog): + + log = self.logMsg # Get musicvideos from emby emby = self.emby emby_db = embydb.Embydb_Functions(embycursor) mvideos = itemtypes.MusicVideos(embycursor, kodicursor) views = emby_db.getView_byType('musicvideos') - self.logMsg("Media folders: %s" % views, 1) + log("Media folders: %s" % views, 1) # Pull the list of musicvideos in Kodi try: @@ -1131,7 +1155,7 @@ class ManualSync(LibrarySync): if pdialog: pdialog.update( heading="Emby for Kodi", - message="Comparing musicvideos from view: %s..." % viewName) + message="%s %s..." % (utils.language(33028), viewName)) all_embymvideos = emby.getMusicVideos(viewId, basic=True, dialog=pdialog) for embymvideo in all_embymvideos['Items']: @@ -1148,7 +1172,7 @@ class ManualSync(LibrarySync): # Only update if musicvideo is not in Kodi or checksum is different updatelist.append(itemid) - self.logMsg("MusicVideos to update for %s: %s" % (viewName, updatelist), 1) + log("MusicVideos to update for %s: %s" % (viewName, updatelist), 1) embymvideos = emby.getFullItems(updatelist) total = len(updatelist) del updatelist[:] @@ -1176,11 +1200,14 @@ class ManualSync(LibrarySync): if kodimvideo not in all_embymvideosIds: mvideos.remove(kodimvideo) else: - self.logMsg("MusicVideos compare finished.", 1) + log("MusicVideos compare finished.", 1) return True def tvshows(self, embycursor, kodicursor, pdialog): + + log = self.logMsg + lang = utils.language # Get shows from emby emby = self.emby emby_db = embydb.Embydb_Functions(embycursor) @@ -1188,7 +1215,7 @@ class ManualSync(LibrarySync): views = emby_db.getView_byType('tvshows') views += emby_db.getView_byType('mixed') - self.logMsg("Media folders: %s" % views, 1) + log("Media folders: %s" % views, 1) # Pull the list of tvshows and episodes in Kodi try: @@ -1218,7 +1245,7 @@ class ManualSync(LibrarySync): if pdialog: pdialog.update( heading="Emby for Kodi", - message="Comparing tvshows from view: %s..." % viewName) + message="%s %s..." % (lang(33029), viewName)) all_embytvshows = emby.getShows(viewId, basic=True, dialog=pdialog) for embytvshow in all_embytvshows['Items']: @@ -1235,7 +1262,7 @@ class ManualSync(LibrarySync): # Only update if movie is not in Kodi or checksum is different updatelist.append(itemid) - self.logMsg("TVShows to update for %s: %s" % (viewName, updatelist), 1) + log("TVShows to update for %s: %s" % (viewName, updatelist), 1) embytvshows = emby.getFullItems(updatelist) total = len(updatelist) del updatelist[:] @@ -1263,7 +1290,7 @@ class ManualSync(LibrarySync): if pdialog: pdialog.update( heading="Emby for Kodi", - message="Comparing episodes from view: %s..." % viewName) + message="%s %s..." % (lang(33030), viewName)) all_embyepisodes = emby.getEpisodes(viewId, basic=True, dialog=pdialog) for embyepisode in all_embyepisodes['Items']: @@ -1279,7 +1306,7 @@ class ManualSync(LibrarySync): # Only update if movie is not in Kodi or checksum is different updatelist.append(itemid) - self.logMsg("Episodes to update for %s: %s" % (viewName, updatelist), 1) + log("Episodes to update for %s: %s" % (viewName, updatelist), 1) embyepisodes = emby.getFullItems(updatelist) total = len(updatelist) del updatelist[:] @@ -1305,17 +1332,19 @@ class ManualSync(LibrarySync): if koditvshow not in all_embytvshowsIds: tvshows.remove(koditvshow) else: - self.logMsg("TVShows compare finished.", 1) + log("TVShows compare finished.", 1) for kodiepisode in all_kodiepisodes: if kodiepisode not in all_embyepisodesIds: tvshows.remove(kodiepisode) else: - self.logMsg("Episodes compare finished.", 1) + log("Episodes compare finished.", 1) return True def music(self, embycursor, kodicursor, pdialog): + + log = self.logMsg # Get music from emby emby = self.emby emby_db = embydb.Embydb_Functions(embycursor) @@ -1354,7 +1383,7 @@ class ManualSync(LibrarySync): if pdialog: pdialog.update( heading="Emby for Kodi", - message="Comparing %s..." % type) + message="%s %s..." % (utils.language(33031), type)) if type != "artists": all_embyitems = process[type][0](basic=True, dialog=pdialog) @@ -1383,7 +1412,7 @@ class ManualSync(LibrarySync): # Only update if songs is not in Kodi or checksum is different updatelist.append(itemid) - self.logMsg("%s to update: %s" % (type, updatelist), 1) + log("%s to update: %s" % (type, updatelist), 1) embyitems = emby.getFullItems(updatelist) total = len(updatelist) del updatelist[:] @@ -1411,18 +1440,18 @@ class ManualSync(LibrarySync): if kodiartist not in all_embyartistsIds and all_kodiartists[kodiartist] is not None: music.remove(kodiartist) else: - self.logMsg("Artist compare finished.", 1) + log("Artist compare finished.", 1) for kodialbum in all_kodialbums: if kodialbum not in all_embyalbumsIds: music.remove(kodialbum) else: - self.logMsg("Albums compare finished.", 1) + log("Albums compare finished.", 1) for kodisong in all_kodisongs: if kodisong not in all_embysongsIds: music.remove(kodisong) else: - self.logMsg("Songs compare finished.", 1) + log("Songs compare finished.", 1) return True \ No newline at end of file diff --git a/resources/lib/playbackutils.py b/resources/lib/playbackutils.py index 65c1d8b9..93b8273a 100644 --- a/resources/lib/playbackutils.py +++ b/resources/lib/playbackutils.py @@ -31,7 +31,7 @@ class PlaybackUtils(): self.clientInfo = clientinfo.ClientInfo() self.addonName = self.clientInfo.getAddonName() - self.doUtils = downloadutils.DownloadUtils() + self.doUtils = downloadutils.DownloadUtils().downloadUrl self.userid = utils.window('emby_currUser') self.server = utils.window('emby_server%s' % self.userid) @@ -48,7 +48,9 @@ class PlaybackUtils(): def play(self, itemid, dbid=None): - self.logMsg("Play called.", 1) + log = self.logMsg + window = utils.window + settings = utils.settings doUtils = self.doUtils item = self.item @@ -56,6 +58,7 @@ class PlaybackUtils(): listitem = xbmcgui.ListItem() playutils = putils.PlayUtils(item) + log("Play called.", 1) playurl = playutils.getPlayUrl() if not playurl: return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem) @@ -74,13 +77,13 @@ class PlaybackUtils(): sizePlaylist = playlist.size() currentPosition = startPos - propertiesPlayback = utils.window('emby_playbackProps') == "true" + propertiesPlayback = window('emby_playbackProps') == "true" introsPlaylist = False dummyPlaylist = False - self.logMsg("Playlist start position: %s" % startPos, 1) - self.logMsg("Playlist plugin position: %s" % currentPosition, 1) - self.logMsg("Playlist size: %s" % sizePlaylist, 1) + log("Playlist start position: %s" % startPos, 2) + log("Playlist plugin position: %s" % currentPosition, 2) + log("Playlist size: %s" % sizePlaylist, 2) ############### RESUME POINT ################ @@ -91,13 +94,13 @@ class PlaybackUtils(): # Otherwise we get a loop. if not propertiesPlayback: - utils.window('emby_playbackProps', value="true") - self.logMsg("Setting up properties in playlist.", 1) + window('emby_playbackProps', value="true") + log("Setting up properties in playlist.", 1) if (not homeScreen and not seektime and - utils.window('emby_customPlaylist') != "true"): + window('emby_customPlaylist') != "true"): - self.logMsg("Adding dummy file to playlist.", 2) + log("Adding dummy file to playlist.", 2) dummyPlaylist = True playlist.add(playurl, listitem, index=startPos) # Remove the original item from playlist @@ -108,27 +111,27 @@ class PlaybackUtils(): ############### -- CHECK FOR INTROS ################ - if utils.settings('enableCinema') == "true" and not seektime: + if settings('enableCinema') == "true" and not seektime: # if we have any play them when the movie/show is not being resumed url = "{server}/emby/Users/{UserId}/Items/%s/Intros?format=json" % itemid - intros = doUtils.downloadUrl(url) + intros = doUtils(url) if intros['TotalRecordCount'] != 0: getTrailers = True - if utils.settings('askCinema') == "true": - resp = xbmcgui.Dialog().yesno("Emby Cinema Mode", "Play trailers?") + if settings('askCinema') == "true": + resp = xbmcgui.Dialog().yesno("Emby for Kodi", utils.language(33016)) if not resp: # User selected to not play trailers getTrailers = False - self.logMsg("Skip trailers.", 1) + log("Skip trailers.", 1) if getTrailers: for intro in intros['Items']: # The server randomly returns intros, process them. introListItem = xbmcgui.ListItem() introPlayurl = putils.PlayUtils(intro).getPlayUrl() - self.logMsg("Adding Intro: %s" % introPlayurl, 1) + log("Adding Intro: %s" % introPlayurl, 1) # Set listitem and properties for intros pbutils = PlaybackUtils(intro) @@ -144,7 +147,7 @@ class PlaybackUtils(): if homeScreen and not seektime and not sizePlaylist: # Extend our current playlist with the actual item to play # only if there's no playlist first - self.logMsg("Adding main item to playlist.", 1) + log("Adding main item to playlist.", 1) self.pl.addtoPlaylist(dbid, item['Type'].lower()) # Ensure that additional parts are played after the main item @@ -156,12 +159,12 @@ class PlaybackUtils(): # Only add to the playlist after intros have played partcount = item['PartCount'] url = "{server}/emby/Videos/%s/AdditionalParts?format=json" % itemid - parts = doUtils.downloadUrl(url) + parts = doUtils(url) for part in parts['Items']: additionalListItem = xbmcgui.ListItem() additionalPlayurl = putils.PlayUtils(part).getPlayUrl() - self.logMsg("Adding additional part: %s" % partcount, 1) + log("Adding additional part: %s" % partcount, 1) # Set listitem and properties for each additional parts pbutils = PlaybackUtils(part) @@ -175,58 +178,60 @@ class PlaybackUtils(): if dummyPlaylist: # Added a dummy file to the playlist, # because the first item is going to fail automatically. - self.logMsg("Processed as a playlist. First item is skipped.", 1) + log("Processed as a playlist. First item is skipped.", 1) return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem) # We just skipped adding properties. Reset flag for next time. elif propertiesPlayback: - self.logMsg("Resetting properties playback flag.", 2) - utils.window('emby_playbackProps', clear=True) + log("Resetting properties playback flag.", 2) + window('emby_playbackProps', clear=True) #self.pl.verifyPlaylist() ########## SETUP MAIN ITEM ########## # For transcoding only, ask for audio/subs pref - if utils.window('emby_%s.playmethod' % playurl) == "Transcode": + if window('emby_%s.playmethod' % playurl) == "Transcode": playurl = playutils.audioSubsPref(playurl, listitem) - utils.window('emby_%s.playmethod' % playurl, value="Transcode") + window('emby_%s.playmethod' % playurl, value="Transcode") listitem.setPath(playurl) self.setProperties(playurl, listitem) ############### PLAYBACK ################ - if homeScreen and seektime and utils.window('emby_customPlaylist') != "true": - self.logMsg("Play as a widget item.", 1) + if homeScreen and seektime and window('emby_customPlaylist') != "true": + log("Play as a widget item.", 1) self.setListItem(listitem) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem) - elif ((introsPlaylist and utils.window('emby_customPlaylist') == "true") or - (homeScreen and not sizePlaylist)): + elif ((introsPlaylist and window('emby_customPlaylist') == "true") or + (homeScreen and not sizePlaylist)): # Playlist was created just now, play it. - self.logMsg("Play playlist.", 1) + log("Play playlist.", 1) xbmc.Player().play(playlist, startpos=startPos) else: - self.logMsg("Play as a regular item.", 1) + log("Play as a regular item.", 1) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem) def setProperties(self, playurl, listitem): + + window = utils.window # Set all properties necessary for plugin path playback item = self.item itemid = item['Id'] itemtype = item['Type'] embyitem = "emby_%s" % playurl - utils.window('%s.runtime' % embyitem, value=str(item.get('RunTimeTicks'))) - utils.window('%s.type' % embyitem, value=itemtype) - utils.window('%s.itemid' % embyitem, value=itemid) + window('%s.runtime' % embyitem, value=str(item.get('RunTimeTicks'))) + window('%s.type' % embyitem, value=itemtype) + window('%s.itemid' % embyitem, value=itemid) if itemtype == "Episode": - utils.window('%s.refreshid' % embyitem, value=item.get('SeriesId')) + window('%s.refreshid' % embyitem, value=item.get('SeriesId')) else: - utils.window('%s.refreshid' % embyitem, value=itemid) + window('%s.refreshid' % embyitem, value=itemid) # Append external subtitles to stream playmethod = utils.window('%s.playmethod' % embyitem) @@ -316,7 +321,7 @@ class PlaybackUtils(): def setListItem(self, listItem): item = self.item - type = item['Type'] + itemtype = item['Type'] API = self.API people = API.getPeople() studios = API.getStudios() @@ -336,7 +341,7 @@ class PlaybackUtils(): 'votes': item.get('VoteCount') } - if "Episode" in type: + if "Episode" in itemtype: # Only for tv shows thumbId = item.get('SeriesId') season = item.get('ParentIndexNumber', -1) diff --git a/resources/lib/player.py b/resources/lib/player.py index ed3fb414..d4b2e624 100644 --- a/resources/lib/player.py +++ b/resources/lib/player.py @@ -32,7 +32,7 @@ class Player(xbmc.Player): self.clientInfo = clientinfo.ClientInfo() self.addonName = self.clientInfo.getAddonName() - self.doUtils = downloadutils.DownloadUtils() + self.doUtils = downloadutils.DownloadUtils().downloadUrl self.ws = wsc.WebSocket_Client() self.xbmcplayer = xbmc.Player() @@ -47,7 +47,10 @@ class Player(xbmc.Player): def GetPlayStats(self): return self.playStats - def onPlayBackStarted( self ): + def onPlayBackStarted(self): + + log = self.logMsg + window = utils.window # Will be called when xbmc starts playing a file xbmcplayer = self.xbmcplayer self.stopAll() @@ -66,7 +69,7 @@ class Player(xbmc.Player): except: pass if count == 5: # try 5 times - self.logMsg("Cancelling playback report...", 1) + log("Cancelling playback report...", 1) break else: count += 1 @@ -76,36 +79,34 @@ class Player(xbmc.Player): self.currentFile = currentFile # We may need to wait for info to be set in kodi monitor - itemId = utils.window("emby_%s.itemid" % currentFile) + itemId = window("emby_%s.itemid" % currentFile) tryCount = 0 while not itemId: xbmc.sleep(200) - itemId = utils.window("emby_%s.itemid" % currentFile) + itemId = window("emby_%s.itemid" % currentFile) if tryCount == 20: # try 20 times or about 10 seconds - self.logMsg("Could not find itemId, cancelling playback report...", 1) + log("Could not find itemId, cancelling playback report...", 1) break else: tryCount += 1 else: - self.logMsg("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId), 0) + log("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId), 0) # Only proceed if an itemId was found. embyitem = "emby_%s" % currentFile - runtime = utils.window("%s.runtime" % embyitem) - refresh_id = utils.window("%s.refreshid" % embyitem) - playMethod = utils.window("%s.playmethod" % embyitem) - itemType = utils.window("%s.type" % embyitem) - utils.window('emby_skipWatched%s' % itemId, value="true") + runtime = window("%s.runtime" % embyitem) + refresh_id = window("%s.refreshid" % embyitem) + playMethod = window("%s.playmethod" % embyitem) + itemType = window("%s.type" % embyitem) + window('emby_skipWatched%s' % itemId, value="true") - - if (utils.window('emby_customPlaylist') == "true" and - utils.window('emby_customPlaylist.seektime')): + customseek = window('emby_customPlaylist.seektime') + if window('emby_customPlaylist') == "true" and customseek: # Start at, when using custom playlist (play to Kodi from webclient) - seektime = utils.window('emby_customPlaylist.seektime') - self.logMsg("Seeking to: %s" % seektime, 1) - xbmcplayer.seekTime(int(seektime)/10000000.0) - utils.window('emby_customPlaylist.seektime', clear=True) + log("Seeking to: %s" % customseek, 1) + xbmcplayer.seekTime(int(customseek)/10000000.0) + window('emby_customPlaylist.seektime', clear=True) seekTime = xbmcplayer.getTime() @@ -144,9 +145,8 @@ class Player(xbmc.Player): # Get the current audio track and subtitles if playMethod == "Transcode": # property set in PlayUtils.py - postdata['AudioStreamIndex'] = utils.window("%sAudioStreamIndex" % currentFile) - postdata['SubtitleStreamIndex'] = utils.window("%sSubtitleStreamIndex" - % currentFile) + postdata['AudioStreamIndex'] = window("%sAudioStreamIndex" % currentFile) + postdata['SubtitleStreamIndex'] = window("%sSubtitleStreamIndex" % currentFile) else: # Get the current kodi audio and subtitles and convert to Emby equivalent tracks_query = { @@ -187,11 +187,11 @@ class Player(xbmc.Player): # Number of audiotracks to help get Emby Index audioTracks = len(xbmc.Player().getAvailableAudioStreams()) - mapping = utils.window("%s.indexMapping" % embyitem) + mapping = window("%s.indexMapping" % embyitem) if mapping: # Set in playbackutils.py - self.logMsg("Mapping for external subtitles index: %s" % mapping, 2) + log("Mapping for external subtitles index: %s" % mapping, 2) externalIndex = json.loads(mapping) if externalIndex.get(str(indexSubs)): @@ -209,15 +209,15 @@ 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") + log("Sending POST play started: %s." % postdata, 2) + self.doUtils(url, postBody=postdata, type="POST") # Ensure we do have a runtime try: runtime = int(runtime) except ValueError: runtime = xbmcplayer.getTotalTime() - self.logMsg("Runtime is missing, Kodi runtime: %s" % runtime, 1) + log("Runtime is missing, Kodi runtime: %s" % runtime, 1) # Save data map for updates and position calls data = { @@ -234,7 +234,7 @@ class Player(xbmc.Player): } self.played_info[currentFile] = data - self.logMsg("ADDING_FILE: %s" % self.played_info, 1) + log("ADDING_FILE: %s" % self.played_info, 1) # log some playback stats '''if(itemType != None): @@ -253,7 +253,9 @@ class Player(xbmc.Player): def reportPlayback(self): - self.logMsg("reportPlayback Called", 2) + log = self.logMsg + + log("reportPlayback Called", 2) xbmcplayer = self.xbmcplayer # Get current file @@ -281,7 +283,7 @@ class Player(xbmc.Player): "properties": ["volume", "muted"] } - } + } result = xbmc.executeJSONRPC(json.dumps(volume_query)) result = json.loads(result) result = result.get('result') @@ -352,7 +354,7 @@ class Player(xbmc.Player): if mapping: # Set in PlaybackUtils.py - self.logMsg("Mapping for external subtitles index: %s" % mapping, 2) + log("Mapping for external subtitles index: %s" % mapping, 2) externalIndex = json.loads(mapping) if externalIndex.get(str(indexSubs)): @@ -372,7 +374,7 @@ class Player(xbmc.Player): # Report progress via websocketclient postdata = json.dumps(postdata) - self.logMsg("Report: %s" % postdata, 2) + log("Report: %s" % postdata, 2) self.ws.sendProgressUpdate(postdata) def onPlayBackPaused( self ): @@ -407,12 +409,15 @@ class Player(xbmc.Player): self.reportPlayback() def onPlayBackStopped( self ): + + log = self.logMsg + window = utils.window # Will be called when user stops xbmc playing a file - self.logMsg("ONPLAYBACK_STOPPED", 2) - utils.window('emby_customPlaylist', clear=True) - utils.window('emby_customPlaylist.seektime', clear=True) - utils.window('emby_playbackProps', clear=True) - self.logMsg("Clear playlist properties.", 1) + logMsg("ONPLAYBACK_STOPPED", 2) + window('emby_customPlaylist', clear=True) + window('emby_customPlaylist.seektime', clear=True) + window('emby_playbackProps', clear=True) + logMsg("Clear playlist properties.", 1) self.stopAll() def onPlayBackEnded( self ): @@ -423,20 +428,24 @@ class Player(xbmc.Player): def stopAll(self): + log = self.logMsg + lang = utils.language + settings = utils.settings + doUtils = self.doUtils if not self.played_info: return - self.logMsg("Played_information: %s" % self.played_info, 1) + log("Played_information: %s" % self.played_info, 1) # Process each items for item in self.played_info: data = self.played_info.get(item) if data: - self.logMsg("Item path: %s" % item, 2) - self.logMsg("Item data: %s" % data, 2) + log("Item path: %s" % item, 2) + log("Item data: %s" % data, 2) runtime = data['runtime'] currentPosition = data['currentPosition'] @@ -453,9 +462,8 @@ class Player(xbmc.Player): # Runtime is 0. percentComplete = 0 - markPlayedAt = float(utils.settings('markPlayed')) / 100 - self.logMsg( - "Percent complete: %s Mark played at: %s" + markPlayedAt = float(settings('markPlayed')) / 100 + log("Percent complete: %s Mark played at: %s" % (percentComplete, markPlayedAt), 1) # Prevent manually mark as watched in Kodi monitor @@ -464,34 +472,32 @@ class Player(xbmc.Player): self.stopPlayback(data) # Stop transcoding if playMethod == "Transcode": - self.logMsg("Transcoding for %s terminated." % itemid, 1) + log("Transcoding for %s terminated." % itemid, 1) deviceId = self.clientInfo.getDeviceId() url = "{server}/emby/Videos/ActiveEncodings?DeviceId=%s" % deviceId - doUtils.downloadUrl(url, type="DELETE") + doUtils(url, type="DELETE") # Send the delete action to the server. offerDelete = False - if type == "Episode" and utils.settings('deleteTV') == "true": + if type == "Episode" and settings('deleteTV') == "true": offerDelete = True - elif type == "Movie" and utils.settings('deleteMovies') == "true": + elif type == "Movie" and settings('deleteMovies') == "true": offerDelete = True - if utils.settings('offerDelete') != "true": + if settings('offerDelete') != "true": # Delete could be disabled, even if the subsetting is enabled. offerDelete = False if percentComplete >= markPlayedAt and offerDelete: - resp = xbmcgui.Dialog().yesno( - heading="Confirm delete", - line1="Delete file on Emby Server?") + resp = xbmcgui.Dialog().yesno(lang(30091), lang(33015)) if not resp: - self.logMsg("User skipped deletion.", 1) + log("User skipped deletion.", 1) continue url = "{server}/emby/Items/%s?format=json" % itemid - self.logMsg("Deleting request: %s" % itemid) - doUtils.downloadUrl(url, type="DELETE") + log("Deleting request: %s" % itemid, 1) + doUtils(url, type="DELETE") self.played_info.clear() @@ -510,4 +516,4 @@ class Player(xbmc.Player): 'MediaSourceId': itemId, 'PositionTicks': positionTicks } - self.doUtils.downloadUrl(url, postBody=postdata, type="POST") \ No newline at end of file + self.doUtils(url, postBody=postdata, type="POST") \ No newline at end of file diff --git a/resources/lib/playlist.py b/resources/lib/playlist.py index c265cb79..383d34a8 100644 --- a/resources/lib/playlist.py +++ b/resources/lib/playlist.py @@ -39,6 +39,9 @@ class Playlist(): def playAll(self, itemids, startat): + log = self.logMsg + window = utils.window + embyconn = utils.kodiSQL('emby') embycursor = embyconn.cursor() emby_db = embydb.Embydb_Functions(embycursor) @@ -47,15 +50,15 @@ class Playlist(): playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) playlist.clear() - self.logMsg("---*** PLAY ALL ***---", 1) - self.logMsg("Items: %s and start at: %s" % (itemids, startat)) + log("---*** PLAY ALL ***---", 1) + log("Items: %s and start at: %s" % (itemids, startat), 1) started = False - utils.window('emby_customplaylist', value="true") + window('emby_customplaylist', value="true") if startat != 0: # Seek to the starting position - utils.window('emby_customplaylist.seektime', str(startat)) + window('emby_customplaylist.seektime', str(startat)) for itemid in itemids: embydb_item = emby_db.getItem_byId(itemid) @@ -64,14 +67,14 @@ class Playlist(): mediatype = embydb_item[4] except TypeError: # Item is not found in our database, add item manually - self.logMsg("Item was not found in the database, manually adding item.", 1) + log("Item was not found in the database, manually adding item.", 1) item = self.emby.getItem(itemid) self.addtoPlaylist_xbmc(playlist, item) else: # Add to playlist self.addtoPlaylist(dbid, mediatype) - self.logMsg("Adding %s to playlist." % itemid, 1) + log("Adding %s to playlist." % itemid, 1) if not started: started = True @@ -82,12 +85,14 @@ class Playlist(): def modifyPlaylist(self, itemids): + log = self.logMsg + embyconn = utils.kodiSQL('emby') embycursor = embyconn.cursor() emby_db = embydb.Embydb_Functions(embycursor) - self.logMsg("---*** ADD TO PLAYLIST ***---", 1) - self.logMsg("Items: %s" % itemids, 1) + log("---*** ADD TO PLAYLIST ***---", 1) + log("Items: %s" % itemids, 1) player = xbmc.Player() playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) @@ -105,7 +110,7 @@ class Playlist(): # Add to playlist self.addtoPlaylist(dbid, mediatype) - self.logMsg("Adding %s to playlist." % itemid, 1) + log("Adding %s to playlist." % itemid, 1) self.verifyPlaylist() embycursor.close() diff --git a/resources/lib/playutils.py b/resources/lib/playutils.py index 5617a6e9..37332b16 100644 --- a/resources/lib/playutils.py +++ b/resources/lib/playutils.py @@ -33,43 +33,46 @@ class PlayUtils(): def getPlayUrl(self): + log = self.logMsg + window = utils.window + item = self.item playurl = None if (item.get('Type') in ("Recording", "TvChannel") and item.get('MediaSources') and item['MediaSources'][0]['Protocol'] == "Http"): # Play LiveTV or recordings - self.logMsg("File protocol is http (livetv).", 1) + log("File protocol is http (livetv).", 1) playurl = "%s/emby/Videos/%s/live.m3u8?static=true" % (self.server, item['Id']) - utils.window('emby_%s.playmethod' % playurl, value="Transcode") + window('emby_%s.playmethod' % playurl, value="Transcode") elif item.get('MediaSources') and item['MediaSources'][0]['Protocol'] == "Http": # Only play as http, used for channels, or online hosting of content - self.logMsg("File protocol is http.", 1) + log("File protocol is http.", 1) playurl = self.httpPlay() - utils.window('emby_%s.playmethod' % playurl, value="DirectStream") + window('emby_%s.playmethod' % playurl, value="DirectStream") elif self.isDirectPlay(): - self.logMsg("File is direct playing.", 1) + log("File is direct playing.", 1) playurl = self.directPlay() playurl = playurl.encode('utf-8') # Set playmethod property - utils.window('emby_%s.playmethod' % playurl, value="DirectPlay") + window('emby_%s.playmethod' % playurl, value="DirectPlay") elif self.isDirectStream(): - self.logMsg("File is direct streaming.", 1) + log("File is direct streaming.", 1) playurl = self.directStream() # Set playmethod property - utils.window('emby_%s.playmethod' % playurl, value="DirectStream") + window('emby_%s.playmethod' % playurl, value="DirectStream") elif self.isTranscoding(): - self.logMsg("File is transcoding.", 1) + log("File is transcoding.", 1) playurl = self.transcoding() # Set playmethod property - utils.window('emby_%s.playmethod' % playurl, value="Transcode") + window('emby_%s.playmethod' % playurl, value="Transcode") return playurl @@ -90,16 +93,21 @@ class PlayUtils(): def isDirectPlay(self): + log = self.logMsg + lang = utils.language + settings = utils.settings + dialog = xbmcgui.Dialog() + item = self.item # Requirement: Filesystem, Accessible path - if utils.settings('playFromStream') == "true": + if settings('playFromStream') == "true": # User forcing to play via HTTP - self.logMsg("Can't direct play, play from HTTP enabled.", 1) + log("Can't direct play, play from HTTP enabled.", 1) return False videotrack = item['MediaSources'][0]['Name'] - transcodeH265 = utils.settings('transcodeH265') + transcodeH265 = settings('transcodeH265') if transcodeH265 in ("1", "2", "3") and ("HEVC" in videotrack or "H265" in videotrack): # Avoid H265/HEVC depending on the resolution @@ -110,46 +118,45 @@ class PlayUtils(): '2': 720, '3': 1080 } - self.logMsg("Resolution is: %sP, transcode for resolution: %sP+" - % (resolution, res[transcodeH265]), 1) + log("Resolution is: %sP, transcode for resolution: %sP+" + % (resolution, res[transcodeH265]), 1) if res[transcodeH265] <= resolution: return False canDirectPlay = item['MediaSources'][0]['SupportsDirectPlay'] # Make sure direct play is supported by the server if not canDirectPlay: - self.logMsg("Can't direct play, server doesn't allow/support it.", 1) + log("Can't direct play, server doesn't allow/support it.", 1) return False location = item['LocationType'] if location == "FileSystem": # Verify the path if not self.fileExists(): - self.logMsg("Unable to direct play.") + log("Unable to direct play.") try: - count = int(utils.settings('failCount')) + count = int(settings('failCount')) except ValueError: count = 0 - self.logMsg("Direct play failed: %s times." % count, 1) + log("Direct play failed: %s times." % count, 1) if count < 2: # Let the user know that direct play failed - utils.settings('failCount', value=str(count+1)) - xbmcgui.Dialog().notification( - heading="Emby server", - message="Unable to direct play.", - icon="special://home/addons/plugin.video.emby/icon.png", - sound=False) - elif utils.settings('playFromStream') != "true": + settings('failCount', value=str(count+1)) + dialog.notification( + heading="Emby for Kodi", + message=lang(33011), + icon="special://home/addons/plugin.video.emby/icon.png", + sound=False) + elif settings('playFromStream') != "true": # Permanently set direct stream as true - utils.settings('playFromStream', value="true") - utils.settings('failCount', value="0") - xbmcgui.Dialog().notification( - heading="Emby server", - message=("Direct play failed 3 times. Enabled play " - "from HTTP in the add-on settings."), - icon="special://home/addons/plugin.video.emby/icon.png", - sound=False) + settings('playFromStream', value="true") + settings('failCount', value="0") + dialog.notification( + heading="Emby for Kodi", + message=lang(33012), + icon="special://home/addons/plugin.video.emby/icon.png", + sound=False) return False return True @@ -185,28 +192,32 @@ class PlayUtils(): def fileExists(self): + log = self.logMsg + if 'Path' not in self.item: # File has no path defined in server return False # Convert path to direct play path = self.directPlay() - self.logMsg("Verifying path: %s" % path, 1) + log("Verifying path: %s" % path, 1) if xbmcvfs.exists(path): - self.logMsg("Path exists.", 1) + log("Path exists.", 1) return True elif ":" not in path: - self.logMsg("Can't verify path, assumed linux. Still try to direct play.", 1) + log("Can't verify path, assumed linux. Still try to direct play.", 1) return True else: - self.logMsg("Failed to find file.") + log("Failed to find file.", 1) return False def isDirectStream(self): + log = self.logMsg + item = self.item videotrack = item['MediaSources'][0]['Name'] @@ -221,8 +232,8 @@ class PlayUtils(): '2': 720, '3': 1080 } - self.logMsg("Resolution is: %sP, transcode for resolution: %sP+" - % (resolution, res[transcodeH265]), 1) + log("Resolution is: %sP, transcode for resolution: %sP+" + % (resolution, res[transcodeH265]), 1) if res[transcodeH265] <= resolution: return False @@ -234,7 +245,7 @@ class PlayUtils(): # Verify the bitrate if not self.isNetworkSufficient(): - self.logMsg("The network speed is insufficient to direct stream file.", 1) + log("The network speed is insufficient to direct stream file.", 1) return False return True @@ -245,12 +256,12 @@ class PlayUtils(): server = self.server itemid = item['Id'] - type = item['Type'] + itemtype = item['Type'] if 'Path' in item and item['Path'].endswith('.strm'): # Allow strm loading when direct streaming playurl = self.directPlay() - elif type == "Audio": + elif itemtype == "Audio": playurl = "%s/emby/Audio/%s/stream.mp3" % (server, itemid) else: playurl = "%s/emby/Videos/%s/stream?static=true" % (server, itemid) @@ -259,15 +270,17 @@ class PlayUtils(): def isNetworkSufficient(self): + log = self.logMsg + settings = self.getBitrate()*1000 try: sourceBitrate = int(self.item['MediaSources'][0]['Bitrate']) except (KeyError, TypeError): - self.logMsg("Bitrate value is missing.", 1) + log("Bitrate value is missing.", 1) else: - self.logMsg("The add-on settings bitrate is: %s, the video bitrate required is: %s" - % (settings, sourceBitrate), 1) + log("The add-on settings bitrate is: %s, the video bitrate required is: %s" + % (settings, sourceBitrate), 1) if settings < sourceBitrate: return False @@ -335,6 +348,10 @@ class PlayUtils(): return bitrate.get(videoQuality, 2147483) def audioSubsPref(self, url, listitem): + + log = self.logMsg + lang = utils.language + dialog = xbmcgui.Dialog() # For transcoding only # Present the list of audio to select from audioStreamsList = {} @@ -373,8 +390,6 @@ class PlayUtils(): audioStreams.append(track) elif 'Subtitle' in type: - '''if stream['IsExternal']: - continue''' try: track = "%s - %s" % (index, stream['Language']) except: @@ -396,7 +411,7 @@ class PlayUtils(): if len(audioStreams) > 1: - resp = xbmcgui.Dialog().select("Choose the audio stream", audioStreams) + resp = dialog.select(lang(33013), audioStreams) if resp > -1: # User selected audio selected = audioStreams[resp] @@ -409,7 +424,7 @@ class PlayUtils(): playurlprefs += "&AudioStreamIndex=%s" % selectAudioIndex if len(subtitleStreams) > 1: - resp = xbmcgui.Dialog().select("Choose the subtitle stream", subtitleStreams) + resp = dialog.select(lang(33014), subtitleStreams) if resp == 0: # User selected no subtitles pass @@ -424,7 +439,7 @@ class PlayUtils(): itemid = item['Id'] url = [("%s/Videos/%s/%s/Subtitles/%s/Stream.srt" % (self.server, itemid, itemid, selectSubsIndex))] - self.logMsg("Set up subtitles: %s %s" % (selectSubsIndex, url), 1) + log("Set up subtitles: %s %s" % (selectSubsIndex, url), 1) listitem.setSubtitles(url) else: # Burn subtitles diff --git a/resources/lib/read_embyserver.py b/resources/lib/read_embyserver.py index e26c90e3..bff2c91d 100644 --- a/resources/lib/read_embyserver.py +++ b/resources/lib/read_embyserver.py @@ -18,12 +18,14 @@ class Read_EmbyServer(): def __init__(self): + window = utils.window + self.clientInfo = clientinfo.ClientInfo() self.addonName = self.clientInfo.getAddonName() self.doUtils = downloadutils.DownloadUtils().downloadUrl - self.userId = utils.window('emby_currUser') - self.server = utils.window('emby_server%s' % self.userId) + self.userId = window('emby_currUser') + self.server = window('emby_server%s' % self.userId) def logMsg(self, msg, lvl=1): @@ -183,6 +185,8 @@ class Read_EmbyServer(): def getSection(self, parentid, itemtype=None, sortby="SortName", basic=False, dialog=None): + log = self.logMsg + doUtils = self.doUtils items = { @@ -208,7 +212,7 @@ class Read_EmbyServer(): items['TotalRecordCount'] = total except TypeError: # Failed to retrieve - self.logMsg("%s:%s Failed to retrieve the server response." % (url, params), 2) + log("%s:%s Failed to retrieve the server response." % (url, params), 2) else: index = 0 @@ -250,27 +254,27 @@ class Read_EmbyServer(): # Something happened to the connection if not throttled: throttled = True - self.logMsg("Throttle activated.", 1) + log("Throttle activated.", 1) if jump == highestjump: # We already tried with the highestjump, but it failed. Reset value. - self.logMsg("Reset highest value.", 1) + log("Reset highest value.", 1) highestjump = 0 # Lower the number by half if highestjump: throttled = False jump = highestjump - self.logMsg("Throttle deactivated.", 1) + log("Throttle deactivated.", 1) else: jump = int(jump/4) - self.logMsg("Set jump limit to recover: %s" % jump, 1) + log("Set jump limit to recover: %s" % jump, 2) retry = 0 while utils.window('emby_online') != "true": # Wait server to come back online if retry == 3: - self.logMsg("Unable to reconnect to server. Abort process.", 1) + log("Unable to reconnect to server. Abort process.", 1) return retry += 1 @@ -298,7 +302,7 @@ class Read_EmbyServer(): increment = 10 jump += increment - self.logMsg("Increase jump limit to: %s" % jump, 1) + log("Increase jump limit to: %s" % jump, 1) return items def getViews(self, type, root=False): diff --git a/resources/lib/userclient.py b/resources/lib/userclient.py index 9b4bce17..7fa353da 100644 --- a/resources/lib/userclient.py +++ b/resources/lib/userclient.py @@ -81,42 +81,46 @@ class UserClient(threading.Thread): def getUserId(self): + log = self.logMsg + window = utils.window + settings = utils.settings + username = self.getUsername() - w_userId = utils.window('emby_userId%s' % username) - s_userId = utils.settings('userId%s' % username) + w_userId = window('emby_currUser') + s_userId = settings('userId%s' % username) # Verify the window property if w_userId: if not s_userId: # Save access token if it's missing from settings - utils.settings('userId%s' % username, value=w_userId) - self.logMsg( - "Returning userId from WINDOW for username: %s UserId: %s" + settings('userId%s' % username, value=w_userId) + log("Returning userId from WINDOW for username: %s UserId: %s" % (username, w_userId), 2) return w_userId # Verify the settings elif s_userId: - self.logMsg( - "Returning userId from SETTINGS for username: %s userId: %s" + log("Returning userId from SETTINGS for username: %s userId: %s" % (username, s_userId), 2) return s_userId # No userId found else: - self.logMsg("No userId saved for username: %s." % username, 1) + log("No userId saved for username: %s." % username, 1) def getServer(self, prefix=True): - alternate = utils.settings('altip') == "true" + settings = utils.settings + + alternate = settings('altip') == "true" if alternate: # Alternate host - HTTPS = utils.settings('secondhttps') == "true" - host = utils.settings('secondipaddress') - port = utils.settings('secondport') + HTTPS = settings('secondhttps') == "true" + host = settings('secondipaddress') + port = settings('secondport') else: # Original host - HTTPS = utils.settings('https') == "true" - host = utils.settings('ipaddress') - port = utils.settings('port') + HTTPS = settings('https') == "true" + host = settings('ipaddress') + port = settings('port') server = host + ":" + port @@ -138,35 +142,40 @@ class UserClient(threading.Thread): def getToken(self): + log = self.logMsg + window = utils.window + settings = utils.settings + username = self.getUsername() - w_token = utils.window('emby_accessToken%s' % username) - s_token = utils.settings('accessToken') + userId = self.getUserId() + w_token = window('emby_accessToken%s' % userId) + s_token = settings('accessToken') # Verify the window property if w_token: if not s_token: # Save access token if it's missing from settings - utils.settings('accessToken', value=w_token) - self.logMsg( - "Returning accessToken from WINDOW for username: %s accessToken: %s" + settings('accessToken', value=w_token) + log("Returning accessToken from WINDOW for username: %s accessToken: %s" % (username, w_token), 2) return w_token # Verify the settings elif s_token: - self.logMsg( - "Returning accessToken from SETTINGS for username: %s accessToken: %s" + log("Returning accessToken from SETTINGS for username: %s accessToken: %s" % (username, s_token), 2) - utils.window('emby_accessToken%s' % username, value=s_token) + window('emby_accessToken%s' % username, value=s_token) return s_token else: - self.logMsg("No token found.", 1) + log("No token found.", 1) return "" def getSSLverify(self): # Verify host certificate - s_sslverify = utils.settings('sslverify') - if utils.settings('altip') == "true": - s_sslverify = utils.settings('secondsslverify') + settings = utils.settings + + s_sslverify = settings('sslverify') + if settings('altip') == "true": + s_sslverify = settings('secondsslverify') if s_sslverify == "true": return True @@ -175,9 +184,11 @@ class UserClient(threading.Thread): def getSSL(self): # Client side certificate - s_cert = utils.settings('sslcert') - if utils.settings('altip') == "true": - s_cert = utils.settings('secondsslcert') + settings = utils.settings + + s_cert = settings('sslcert') + if settings('altip') == "true": + s_cert = settings('secondsslcert') if s_cert == "None": return None @@ -186,11 +197,11 @@ class UserClient(threading.Thread): def setUserPref(self): - doUtils = self.doUtils + doUtils = self.doUtils.downloadUrl art = artwork.Artwork() url = "{server}/emby/Users/{UserId}?format=json" - result = doUtils.downloadUrl(url) + result = doUtils(url) self.userSettings = result # Set user image for skin display if result.get('PrimaryImageTag'): @@ -198,7 +209,7 @@ class UserClient(threading.Thread): # Set resume point max url = "{server}/emby/System/Configuration?format=json" - result = doUtils.downloadUrl(url) + result = doUtils(url) utils.settings('markPlayed', value=str(result['MaxResumePct'])) @@ -218,26 +229,31 @@ class UserClient(threading.Thread): def hasAccess(self): # hasAccess is verified in service.py + log = self.logMsg + window = utils.window + url = "{server}/emby/Users?format=json" result = self.doUtils.downloadUrl(url) if result == False: # Access is restricted, set in downloadutils.py via exception - self.logMsg("Access is restricted.", 1) + log("Access is restricted.", 1) self.HasAccess = False - elif utils.window('emby_online') != "true": + elif window('emby_online') != "true": # Server connection failed pass - elif utils.window('emby_serverStatus') == "restricted": - self.logMsg("Access is granted.", 1) + elif window('emby_serverStatus') == "restricted": + log("Access is granted.", 1) self.HasAccess = True - utils.window('emby_serverStatus', clear=True) - xbmcgui.Dialog().notification("Emby server", "Access is enabled.") + window('emby_serverStatus', clear=True) + xbmcgui.Dialog().notification("Emby for Kodi", utils.language(33007)) def loadCurrUser(self, authenticated=False): + window = utils.window + doUtils = self.doUtils username = self.getUsername() userId = self.getUserId() @@ -252,8 +268,8 @@ class UserClient(threading.Thread): # Test the validity of current token if authenticated == False: url = "%s/emby/Users/%s?format=json" % (self.currServer, userId) - utils.window('emby_currUser', value=userId) - utils.window('emby_accessToken%s' % userId, value=self.currToken) + window('emby_currUser', value=userId) + window('emby_accessToken%s' % userId, value=self.currToken) result = doUtils.downloadUrl(url) if result == 401: @@ -262,10 +278,10 @@ class UserClient(threading.Thread): return False # Set to windows property - utils.window('emby_currUser', value=userId) - utils.window('emby_accessToken%s' % userId, value=self.currToken) - utils.window('emby_server%s' % userId, value=self.currServer) - utils.window('emby_server_%s' % userId, value=self.getServer(prefix=False)) + window('emby_currUser', value=userId) + window('emby_accessToken%s' % userId, value=self.currToken) + window('emby_server%s' % userId, value=self.currServer) + window('emby_server_%s' % userId, value=self.getServer(prefix=False)) # Set DownloadUtils values doUtils.setUsername(username) @@ -284,6 +300,13 @@ class UserClient(threading.Thread): def authenticate(self): + + log = self.logMsg + lang = utils.language + window = utils.window + settings = utils.settings + dialog = xbmcgui.Dialog() + # Get /profile/addon_data addondir = xbmc.translatePath(self.addon.getAddonInfo('profile')).decode('utf-8') hasSettings = xbmcvfs.exists("%ssettings.xml" % addondir) @@ -293,12 +316,12 @@ class UserClient(threading.Thread): # If there's no settings.xml if not hasSettings: - self.logMsg("No settings.xml found.", 1) + log("No settings.xml found.", 1) self.auth = False return # If no user information elif not server or not username: - self.logMsg("Missing server information.", 1) + log("Missing server information.", 1) self.auth = False return # If there's a token, load the user @@ -308,9 +331,9 @@ class UserClient(threading.Thread): if result == False: pass else: - self.logMsg("Current user: %s" % self.currUser, 1) - self.logMsg("Current userId: %s" % self.currUserId, 1) - self.logMsg("Current accessToken: %s" % self.currToken, 2) + log("Current user: %s" % self.currUser, 1) + log("Current userId: %s" % self.currUserId, 1) + log("Current accessToken: %s" % self.currToken, 2) return ##### AUTHENTICATE USER ##### @@ -325,92 +348,93 @@ class UserClient(threading.Thread): if username.decode('utf-8') in name: # If user has password if user['HasPassword'] == True: - password = xbmcgui.Dialog().input( - heading="Enter password for user: %s" % username, + password = dialog.input( + heading="%s %s" % (lang(33008), username), option=xbmcgui.ALPHANUM_HIDE_INPUT) # If password dialog is cancelled if not password: - self.logMsg("No password entered.", 0) - utils.window('emby_serverStatus', value="Stop") + log("No password entered.", 0) + window('emby_serverStatus', value="Stop") self.auth = False return break else: # Manual login, user is hidden - password = xbmcgui.Dialog().input( - heading="Enter password for user: %s" % username, - option=xbmcgui.ALPHANUM_HIDE_INPUT) + password = dialog.input( + heading="%s %s" % (lang(33008), username), + option=xbmcgui.ALPHANUM_HIDE_INPUT) sha1 = hashlib.sha1(password) sha1 = sha1.hexdigest() # Authenticate username and password url = "%s/emby/Users/AuthenticateByName?format=json" % server data = {'username': username, 'password': sha1} - self.logMsg(data, 2) + log(data, 2) result = self.doUtils.downloadUrl(url, postBody=data, type="POST", authenticate=False) try: - self.logMsg("Auth response: %s" % result, 1) + log("Auth response: %s" % result, 1) accessToken = result['AccessToken'] except (KeyError, TypeError): - self.logMsg("Failed to retrieve the api key.", 1) + log("Failed to retrieve the api key.", 1) accessToken = None if accessToken is not None: self.currUser = username - xbmcgui.Dialog().notification("Emby server", "Welcome %s!" % self.currUser) + dialog.notification("Emby for Kodi", "%s %s!" % (lang(33000), self.currUser), 1) userId = result['User']['Id'] - utils.settings('accessToken', value=accessToken) - utils.settings('userId%s' % username, value=userId) - self.logMsg("User Authenticated: %s" % accessToken, 1) + settings('accessToken', value=accessToken) + settings('userId%s' % username, value=userId) + log("User Authenticated: %s" % accessToken, 1) self.loadCurrUser(authenticated=True) - utils.window('emby_serverStatus', clear=True) + window('emby_serverStatus', clear=True) self.retry = 0 else: - self.logMsg("User authentication failed.", 1) - utils.settings('accessToken', value="") - utils.settings('userId%s' % username, value="") - xbmcgui.Dialog().ok("Error connecting", "Invalid username or password.") + log("User authentication failed.", 1) + settings('accessToken', value="") + settings('userId%s' % username, value="") + dialog.ok(lang(33001), lang(33009)) # Give two attempts at entering password if self.retry == 2: - self.logMsg( - """Too many retries. You can retry by resetting - attempts in the addon settings.""", 1) - utils.window('emby_serverStatus', value="Stop") - xbmcgui.Dialog().ok( - heading="Error connecting", - line1="Failed to authenticate too many times.", - line2="You can retry by resetting attempts in the addon settings.") + log("Too many retries. " + "You can retry by resetting attempts in the addon settings.", 1) + window('emby_serverStatus', value="Stop") + dialog.ok(lang(33001), lang(33010)) self.retry += 1 self.auth = False def resetClient(self): - self.logMsg("Reset UserClient authentication.", 1) - username = self.getUsername() + log = self.logMsg + + log("Reset UserClient authentication.", 1) + userId = self.getUserId() if self.currToken is not None: # In case of 401, removed saved token utils.settings('accessToken', value="") - utils.window('emby_accessToken%s' % username, clear=True) + utils.window('emby_accessToken%s' % userId, clear=True) self.currToken = None - self.logMsg("User token has been removed.", 1) + log("User token has been removed.", 1) self.auth = True self.currUser = None def run(self): + log = self.logMsg + window = utils.window + monitor = xbmc.Monitor() - self.logMsg("----===## Starting UserClient ##===----", 0) + log("----===## Starting UserClient ##===----", 0) while not monitor.abortRequested(): - status = utils.window('emby_serverStatus') + status = window('emby_serverStatus') if status: # Verify the connection status to server if status == "restricted": @@ -419,12 +443,12 @@ class UserClient(threading.Thread): elif status == "401": # Unauthorized access, revoke token - utils.window('emby_serverStatus', value="Auth") + window('emby_serverStatus', value="Auth") self.resetClient() if self.auth and (self.currUser is None): # Try to authenticate user - status = utils.window('emby_serverStatus') + status = window('emby_serverStatus') if not status or status == "Auth": # Set auth flag because we no longer need # to authenticate the user @@ -436,13 +460,13 @@ class UserClient(threading.Thread): # If authenticate failed. server = self.getServer() username = self.getUsername() - status = utils.window('emby_serverStatus') + status = window('emby_serverStatus') # The status Stop is for when user cancelled password dialog. if server and username and status != "Stop": # Only if there's information found to login - self.logMsg("Server found: %s" % server, 2) - self.logMsg("Username found: %s" % username, 2) + log("Server found: %s" % server, 2) + log("Username found: %s" % username, 2) self.auth = True @@ -454,8 +478,8 @@ class UserClient(threading.Thread): # Abort was requested while waiting. We should exit break - self.doUtils.stopSession() - self.logMsg("##===---- UserClient Stopped ----===##", 0) + self.doUtils.stopSession() + log("##===---- UserClient Stopped ----===##", 0) def stopClient(self): # When emby for kodi terminates diff --git a/resources/lib/videonodes.py b/resources/lib/videonodes.py index 6b5aba72..19aa1d6f 100644 --- a/resources/lib/videonodes.py +++ b/resources/lib/videonodes.py @@ -23,7 +23,7 @@ class VideoNodes(object): clientInfo = clientinfo.ClientInfo() self.addonName = clientInfo.getAddonName() - self.kodiversion = int(xbmc.getInfoLabel("System.BuildVersion")[:2]) + self.kodiversion = int(xbmc.getInfoLabel('System.BuildVersion')[:2]) def logMsg(self, msg, lvl=1): @@ -75,7 +75,7 @@ class VideoNodes(object): xbmcvfs.exists(path) # Create the node directory - if not xbmcvfs.exists(nodepath) and not mediatype=="photos": + if not xbmcvfs.exists(nodepath) and not mediatype == "photos": # We need to copy over the default items xbmcvfs.mkdirs(nodepath) else: @@ -102,7 +102,7 @@ class VideoNodes(object): window('Emby.nodes.%s.index' % indexnumber, value=path) # Root - if not mediatype=="photos": + if not mediatype == "photos": root = self.commonRoot(order=0, label=tagname, tagname=tagname, roottype=0) try: utils.indent(root) @@ -181,7 +181,7 @@ class VideoNodes(object): nodeXML = "%s%s_%s.xml" % (nodepath, cleantagname, nodetype) # Get label stringid = nodes[node] - if node != '1': + if node != "1": label = utils.language(stringid) if not label: label = xbmc.getLocalizedString(stringid) @@ -323,7 +323,7 @@ class VideoNodes(object): cleantagname = utils.normalize_nodes(tagname) nodepath = xbmc.translatePath("special://profile/library/video/").decode('utf-8') nodeXML = "%semby_%s.xml" % (nodepath, cleantagname) - path = "library://video/emby_%s.xml" % (cleantagname) + path = "library://video/emby_%s.xml" % cleantagname windowpath = "ActivateWindow(Video,%s,return)" % path # Create the video node directory diff --git a/resources/lib/websocket_client.py b/resources/lib/websocket_client.py index 0da3f4a6..acf0df36 100644 --- a/resources/lib/websocket_client.py +++ b/resources/lib/websocket_client.py @@ -324,4 +324,4 @@ class WebSocket_Client(threading.Thread): self.stopWebsocket = True self.client.close() - self.logMsg("Stopping thread.") \ No newline at end of file + self.logMsg("Stopping thread.", 1) \ No newline at end of file diff --git a/service.py b/service.py index 244e77c8..3681b64e 100644 --- a/service.py +++ b/service.py @@ -277,14 +277,14 @@ class Service(): ##### Emby thread is terminating. ##### + if self.userclient_running: + user.stopClient() + if self.library_running: library.stopThread() if self.websocket_running: ws.stopClient() - - if self.userclient_running: - user.stopClient() log("======== STOP %s ========" % self.addonName, 0)