From d6a79bf01b422b89a8cad5cf9e424d6ef21a9634 Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Mon, 7 Mar 2016 16:23:26 -0600 Subject: [PATCH 01/12] Version bump 2.2.9 --- addon.xml | 8 ++++---- changelog.txt | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/addon.xml b/addon.xml index f87c512d..12d11eb6 100644 --- a/addon.xml +++ b/addon.xml @@ -1,14 +1,14 @@ - - - + + + diff --git a/changelog.txt b/changelog.txt index baa14c63..1d873a7d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +version 2.2.9 +- Fix extrafanart + version 2.2.8 - Fix to photos not displaying directories without picutres. - Fix to grouped views causing crash From 8bde429da41ac2cc70b8f2f11c44d2802f1c1088 Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Tue, 8 Mar 2016 18:51:23 -0600 Subject: [PATCH 02/12] Slight adjust for manual sync Can't return value in __init__, instead calling a function to know if manual sync succeeded or not. --- default.py | 2 +- resources/lib/librarysync.py | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/default.py b/default.py index 40c4edf4..724e7303 100644 --- a/default.py +++ b/default.py @@ -114,7 +114,7 @@ class Main: import librarysync lib = librarysync.LibrarySync() if mode == "manualsync": - librarysync.ManualSync(dialog=True) + librarysync.ManualSync().sync(dialog=True) else: lib.fullSync(repair=True) else: diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index 4b885ca9..dacebbde 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -93,7 +93,7 @@ class LibrarySync(threading.Thread): if not completed: # Fast sync failed or server plugin is not found - completed = ManualSync() + completed = ManualSync().sync() else: # Install sync is not completed completed = self.fullSync() @@ -1069,11 +1069,14 @@ class LibrarySync(threading.Thread): class ManualSync(LibrarySync): - def __init__(self, dialog=False): + def __init__(self): LibrarySync.__init__(self) - self.fullSync(manualrun=True, forceddialog=dialog) + def sync(self, dialog=False): + + return self.fullSync(manualrun=True, forceddialog=dialog) + def movies(self, embycursor, kodicursor, pdialog): From a5d74c8a17a374b571376fe56c1ebf2bd1717a55 Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Wed, 9 Mar 2016 17:05:35 -0600 Subject: [PATCH 03/12] Add delete keymap entrypoint RunPlugin(plugin://plugin.video.emby?mode=delete) --- default.py | 3 ++- resources/lib/entrypoint.py | 50 +++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/default.py b/default.py index 724e7303..94117d69 100644 --- a/default.py +++ b/default.py @@ -62,7 +62,8 @@ class Main: 'inprogressepisodes': entrypoint.getInProgressEpisodes, 'recentepisodes': entrypoint.getRecentEpisodes, 'refreshplaylist': entrypoint.refreshPlaylist, - 'deviceid': entrypoint.resetDeviceId + 'deviceid': entrypoint.resetDeviceId, + 'delete': entrypoint.deleteItem } if "/extrafanart" in sys.argv[0]: diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index af69a251..12ed547a 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -118,6 +118,56 @@ def resetDeviceId(): line1=language(33033)) xbmc.executebuiltin('RestartApp') +##### Delete Item, like the context menu action +def deleteItem(): + + # Serves as a keymap action + dbid = xbmc.getInfoLabel('ListItem.DBID') + itemtype = xbmc.getInfoLabel('ListItem.DBTYPE') + + if not itemtype: + + if xbmc.getCondVisibility('Container.Content(albums)'): + itemtype = "album" + elif xbmc.getCondVisibility('Container.Content(artists)'): + itemtype = "artist" + elif xbmc.getCondVisibility('Container.Content(songs)'): + itemtype = "song" + elif xbmc.getCondVisibility('Container.Content(pictures)'): + itemtype = "picture" + else: + utils.logMsg("EMBY delete", "Unknown type, unable to proceed.", 1) + return + + if xbmc.getInfoLabel('ListItem.Property(embyid)'): # If we already have the embyid + embyid = xbmc.getInfoLabel('ListItem.Property(embyid)') + else: + embyconn = utils.kodiSQL('emby') + embycursor = embyconn.cursor() + emby_db = embydb.Embydb_Functions(embycursor) + item = emby_db.getItem_byKodiId(dbid, itemtype) + embycursor.close() + + try: + embyid = item[0] + except TypeError: + utils.logMsg("EMBY delete", "Unknown embyId, unable to proceed.", 1) + return + + if utils.settings('skipContextMenu') != "true": + resp = xbmcgui.Dialog().yesno( + heading="Confirm delete", + line1=("Delete file from Emby Server? This will " + "also delete the file(s) from disk!")) + if not resp: + utils.logMsg("EMBY delete", "User skipped deletion for: %s." % embyid, 1) + return + + doUtils = downloadutils.DownloadUtils() + url = "{server}/emby/Items/%s?format=json" % embyid + utils.logMsg("EMBY delete", "Deleting request: %s" % embyid, 0) + doUtils.downloadUrl(url, type="DELETE") + ##### ADD ADDITIONAL USERS ##### def addUser(): From 9ab82905cb9b4bd9ee9fc9edb1961405e2db2f98 Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Wed, 9 Mar 2016 17:06:42 -0600 Subject: [PATCH 04/12] Fix open cursor --- contextmenu.py | 1 + 1 file changed, 1 insertion(+) diff --git a/contextmenu.py b/contextmenu.py index 66256dca..be7a3df7 100644 --- a/contextmenu.py +++ b/contextmenu.py @@ -51,6 +51,7 @@ if __name__ == '__main__': embycursor = embyconn.cursor() emby_db = embydb.Embydb_Functions(embycursor) item = emby_db.getItem_byKodiId(itemid, itemtype) + embycursor.close() if item: embyid = item[0] logMsg("Contextmenu opened for embyid: %s - itemtype: %s" %(embyid,itemtype)) From db4cb448b0e4fd82662f8b82a800d8da8ea33688 Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Wed, 9 Mar 2016 20:15:45 -0600 Subject: [PATCH 05/12] Adjust delete logic for entrypoint --- resources/lib/entrypoint.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index 12ed547a..b565392a 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -118,30 +118,30 @@ def resetDeviceId(): line1=language(33033)) xbmc.executebuiltin('RestartApp') -##### Delete Item, like the context menu action +##### Delete Item def deleteItem(): # Serves as a keymap action - dbid = xbmc.getInfoLabel('ListItem.DBID') - itemtype = xbmc.getInfoLabel('ListItem.DBTYPE') - - if not itemtype: - - if xbmc.getCondVisibility('Container.Content(albums)'): - itemtype = "album" - elif xbmc.getCondVisibility('Container.Content(artists)'): - itemtype = "artist" - elif xbmc.getCondVisibility('Container.Content(songs)'): - itemtype = "song" - elif xbmc.getCondVisibility('Container.Content(pictures)'): - itemtype = "picture" - else: - utils.logMsg("EMBY delete", "Unknown type, unable to proceed.", 1) - return - if xbmc.getInfoLabel('ListItem.Property(embyid)'): # If we already have the embyid embyid = xbmc.getInfoLabel('ListItem.Property(embyid)') else: + dbid = xbmc.getInfoLabel('ListItem.DBID') + itemtype = xbmc.getInfoLabel('ListItem.DBTYPE') + + if not itemtype: + + if xbmc.getCondVisibility('Container.Content(albums)'): + itemtype = "album" + elif xbmc.getCondVisibility('Container.Content(artists)'): + itemtype = "artist" + elif xbmc.getCondVisibility('Container.Content(songs)'): + itemtype = "song" + elif xbmc.getCondVisibility('Container.Content(pictures)'): + itemtype = "picture" + else: + utils.logMsg("EMBY delete", "Unknown type, unable to proceed.", 1) + return + embyconn = utils.kodiSQL('emby') embycursor = embyconn.cursor() emby_db = embydb.Embydb_Functions(embycursor) From bfd7135a1ded20504785818fc072015a39d278cd Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Thu, 10 Mar 2016 08:06:50 +0100 Subject: [PATCH 06/12] Update Readme --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6380889b..98e5dad6 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,13 @@ **Installation in Kodi** 1. You might want to uninstall everything else Plex related first, e.g. PlexBMC and PlexBMC Helper. Starting with a fresh Kodi install might be a good idea. Be sure to use a "normal", unmodded Skin in Kodi. -If you're updating, you might also want to do a complete reset of the plugin: Settings -> Advanced -> "Performe full DB reset". Choose "Yes" for everything. +If you're updating, you might also want to do a complete reset of the plugin: Settings -> Advanced -> "Perform full DB reset". Choose "Yes" for all questions. 2. Simply fire up Kodi and Install from ZIP from here on. -3. Install the 2 needed dependencies first (be sure to NOT download the sources but the additional release files): https://github.com/croneter/plugin.video.plexkodiconnect.tvshows/releases/tag/1.0.0 and https://github.com/croneter/plugin.video.plexkodiconnect.movies/releases/tag/1.0.0 +3. Install the 2 needed dependencies first (be sure to NOT download the sources but the additional release files): https://github.com/croneter/plugin.video.plexkodiconnect.tvshows/releases/ and https://github.com/croneter/plugin.video.plexkodiconnect.movies/releases/ 5. Then install PlexKodiConnect, again the additional release file from here: https://github.com/croneter/PlexKodiConnect/releases/ 6. Within a few seconds you should be prompted to log into plex.tv. This is mandatory for Plex Home, otherwise you can skip. If nothing happens, try to restart Kodi 7. Once you're succesfully authenticated to your Plex server, the initial sync will start. -8. The first sync of the Plex server to local Kodi database may take a LONG time. With my setup (~400 movies, ~600 episodes, couple of Test music albums and a very powerful NAS), sync take approximately 5 minutes. +8. The first sync of the Plex server to local Kodi database may take a LONG time. With my setup (~400 movies, ~600 episodes, couple of Test music albums and a very powerful NAS), sync takes approximately 5 minutes. 9. Once the full sync is done, you can browse your media in Kodi, syncs will be automatically done in the background. 10. Restart! @@ -62,6 +62,8 @@ Guess what, this is BETA. Currently these features are working: - Pictures - Watch Later - Music Videos +- Playlists +- Play directly from SMB paths ("\\\\server\\Plex\\movie.mkv" on Windows) instead of HTTP ("192.168.1.1:32400") - TV Shows Theme Music (ultra-low prio) From 6d205b5804a8a0de8f6916b7c21459144a525174 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Thu, 10 Mar 2016 08:26:39 +0100 Subject: [PATCH 07/12] Manually trigger full library scan from settings --- default.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/default.py b/default.py index 27e4d37f..2dc5ac6e 100644 --- a/default.py +++ b/default.py @@ -8,6 +8,7 @@ import urlparse import xbmc import xbmcaddon +import xbmcgui ################################################################################################# @@ -111,21 +112,15 @@ class Main: elif mode in ("manualsync", "repair"): if utils.window('emby_online') != "true": # Server is not online, do not run the sync - xbmcgui.Dialog().ok(heading="Emby for Kodi", + xbmcgui.Dialog().ok(heading="PlexKodiConnect", line1=("Unable to run the sync, the add-on is not " "connected to the Emby server.")) - utils.logMsg("EMBY", "Not connected to the emby server.", 1) + utils.logMsg("PLEX", "Not connected to the emby server.", 1) return - if utils.window('emby_dbScan') != "true": - import librarysync - lib = librarysync.LibrarySync() - if mode == "manualsync": - librarysync.ManualSync().sync(dialog=True) - else: - lib.fullSync(repair=True) else: - utils.logMsg("EMBY", "Database scan is already running.", 1) + utils.logMsg("PLEX", "Requesting full library scan", 1) + utils.window('plex_runLibScan', value="full") elif mode == "texturecache": import artwork From 3ccc58894554456dad681200df457b572b615ce9 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Thu, 10 Mar 2016 08:51:24 +0100 Subject: [PATCH 08/12] Optimize notifications for library syncs --- resources/language/English/strings.xml | 1 + resources/language/German/strings.xml | 1 + resources/lib/librarysync.py | 77 +++++++++++++++----------- 3 files changed, 46 insertions(+), 33 deletions(-) diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml index ebb0b7a0..40caa5a8 100644 --- a/resources/language/English/strings.xml +++ b/resources/language/English/strings.xml @@ -405,5 +405,6 @@ Startup syncing process failed repeatedly. Try restarting Kodi. Stopping Sync for now. Plex playlists/nodes refreshed Plex playlists/nodes refresh failed + Full library sync finished diff --git a/resources/language/German/strings.xml b/resources/language/German/strings.xml index 932977f4..4b3b55cc 100644 --- a/resources/language/German/strings.xml +++ b/resources/language/German/strings.xml @@ -337,5 +337,6 @@ Der Startup Synchronisations-Prozess der Plex Bibliotheken ist mehrmals fehlgeschlagen. Bitte Kodi neu starten. Synch wird jetzt gestoppt. Plex Playlisten/Nodes aktualisiert Plex Playlisten/Nodes Aktualisierung fehlgeschlagen + Plex Bibliotheken aktualisiert diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index 828f0ac5..415f04f9 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -70,7 +70,7 @@ class ThreadedGetMetadata(Thread): # Did not receive a valid XML - skip that item for now self.logMsg("Could not get metadata for %s. " "Skipping that item for now" - % updateItem['itemId'], -1) + % updateItem['itemId'], 0) # Increase BOTH counters - since metadata won't be processed with lock: getMetadataCount += 1 @@ -223,8 +223,8 @@ class LibrarySync(Thread): self.user = userclient.UserClient() self.emby = embyserver.Read_EmbyServer() self.vnodes = videonodes.VideoNodes() - self.syncThreadNumber = int(utils.settings('syncThreadNumber')) + self.syncThreadNumber = int(utils.settings('syncThreadNumber')) self.installSyncDone = True if \ utils.settings('SyncInstallRunDone') == 'true' else False self.showDbSync = True if \ @@ -236,18 +236,30 @@ class LibrarySync(Thread): Thread.__init__(self) - def showKodiNote(self, message, forced=False): + def showKodiNote(self, message, forced=False, icon="plex"): """ Shows a Kodi popup, if user selected to do so. Pass message in unicode or string + + icon: "plex": shows Plex icon + "error": shows Kodi error icon """ if not (self.showDbSync or forced): return - xbmcgui.Dialog().notification( - heading=self.addonName, - message=message, - icon="special://home/addons/plugin.video.plexkodiconnect/icon.png", - sound=False) + if icon == "plex": + xbmcgui.Dialog().notification( + heading=self.addonName, + message=message, + icon="special://home/addons/plugin.video.plexkodiconnect/icon.png", + time=5000, + sound=False) + elif icon == "error": + xbmcgui.Dialog().notification( + heading=self.addonName, + message=message, + icon=xbmcgui.NOTIFICATION_ERROR, + time=7000, + sound=True) def fastSync(self): """ @@ -307,7 +319,8 @@ class LibrarySync(Thread): elif self.updatelist[0]['itemType'] == 'Music': self.updateKodiMusicLib = True self.GetAndProcessXMLs( - PlexFunctions.GetItemClassFromType(plexType)) + PlexFunctions.GetItemClassFromType(plexType), + showProgress=False) self.updatelist = [] # Update userdata @@ -698,7 +711,7 @@ class LibrarySync(Thread): 'viewId': viewId, 'title': title}) - def GetAndProcessXMLs(self, itemType): + def GetAndProcessXMLs(self, itemType, showProgress=True): """ Downloads all XMLs for itemType (e.g. Movies, TV-Shows). Processes them by then calling itemtypes.() @@ -706,6 +719,7 @@ class LibrarySync(Thread): Input: itemType: 'Movies', 'TVShows', ... self.updatelist + showProgress If False, NEVER shows sync progress """ # Some logging, just in case. self.logMsg("self.updatelist: %s" % self.updatelist, 2) @@ -750,17 +764,18 @@ class LibrarySync(Thread): threads.append(thread) self.logMsg("Processing thread spawned", 1) # Start one thread to show sync progress - if self.showDbSync: - dialog = xbmcgui.DialogProgressBG() - thread = ThreadedShowSyncInfo( - dialog, - [getMetadataLock, processMetadataLock], - itemNumber, - itemType) - thread.setDaemon(True) - thread.start() - threads.append(thread) - self.logMsg("Kodi Infobox thread spawned", 1) + if showProgress: + if self.showDbSync: + dialog = xbmcgui.DialogProgressBG() + thread = ThreadedShowSyncInfo( + dialog, + [getMetadataLock, processMetadataLock], + itemNumber, + itemType) + thread.setDaemon(True) + thread.start() + threads.append(thread) + self.logMsg("Kodi Infobox thread spawned", 1) # Wait until finished getMetadataQueue.join() @@ -1229,6 +1244,8 @@ class LibrarySync(Thread): fullSync(manualrun=True) window('emby_dbScan', clear=True) count = 0 + # Full library sync finished + self.showKodiNote(string(39407), forced=True) # Reset views was requested from somewhere else elif window('plex_runLibScan') == "views": log('Refresh playlist and nodes requested, starting', 0) @@ -1244,22 +1261,14 @@ class LibrarySync(Thread): # Ran successfully log("Refresh playlists/nodes completed", 0) # "Plex playlists/nodes refreshed" - dialog.notification( - heading=self.addonName, - message=string(39405), - icon="special://home/addons/plugin.video.plexkodiconnect/icon.png", - time=3000, - sound=True) + self.showKodiNote(string(39405), forced=True) else: # Failed log("Refresh playlists/nodes failed", -1) # "Plex playlists/nodes refresh failed" - dialog.notification( - heading=self.addonName, - message=string(39406), - icon=xbmcgui.NOTIFICATION_ERROR, - time=3000, - sound=True) + self.showKodiNote(string(39406), + forced=True, + icon="error") window('emby_dbScan', clear=True) elif enableBackgroundSync: # Run full lib scan approx every 30min @@ -1269,6 +1278,8 @@ class LibrarySync(Thread): log('Running background full lib scan', 0) fullSync(manualrun=True) window('emby_dbScan', clear=True) + # Full library sync finished + self.showKodiNote(string(39407), forced=False) # Run fast sync otherwise (ever second or so) else: window('emby_dbScan', value="true") From 0064029885522e5a32cf58005ebcb3574f53e198 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Thu, 10 Mar 2016 09:30:20 +0100 Subject: [PATCH 09/12] Dump XMLs of failed PMS items in the log --- resources/lib/itemtypes.py | 58 ++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/resources/lib/itemtypes.py b/resources/lib/itemtypes.py index d3a05f63..03d297d1 100644 --- a/resources/lib/itemtypes.py +++ b/resources/lib/itemtypes.py @@ -287,10 +287,16 @@ class Movies(Items): try: self.run_add_update(item, viewtag, viewid) except Exception as e: - utils.window('emby_dbScan', clear=True) self.logMsg('itemtypes.py for movies has crashed for item %s. ' 'Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + self.logMsg('The item xml is:', -1) + try: + import xml.etree.cElementTree as etree + except ImportError: + import xml.etree.ElementTree as etree + etree.dump(item) + utils.window('plex_scancrashed', value='true') # skip this item for now return @@ -920,10 +926,16 @@ class TVShows(Items): try: self.run_add_update(item, viewtag, viewid) except Exception as e: - utils.window('emby_dbScan', clear=True) self.logMsg('itemtypes.py for tv show has crashed for item %s. ' 'Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + self.logMsg('The item xml is:', -1) + try: + import xml.etree.cElementTree as etree + except ImportError: + import xml.etree.ElementTree as etree + etree.dump(item) + utils.window('plex_scancrashed', value='true') # skip this item for now return @@ -1117,10 +1129,16 @@ class TVShows(Items): try: self.run_add_updateSeason(item, viewtag, viewid) except Exception as e: - utils.window('emby_dbScan', clear=True) self.logMsg('itemtypes.py for tv seasons has crashed for item %s. ' 'Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + self.logMsg('The item xml is:', -1) + try: + import xml.etree.cElementTree as etree + except ImportError: + import xml.etree.ElementTree as etree + etree.dump(item) + utils.window('plex_scancrashed', value='true') # skip this item for now return @@ -1162,10 +1180,16 @@ class TVShows(Items): try: self.run_add_updateEpisode(item, viewtag, viewid) except Exception as e: - utils.window('emby_dbScan', clear=True) self.logMsg('itemtypes.py for tv episode has crashed for item %s. ' 'Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + self.logMsg('The item xml is:', -1) + try: + import xml.etree.cElementTree as etree + except ImportError: + import xml.etree.ElementTree as etree + etree.dump(item) + utils.window('plex_scancrashed', value='true') # skip this item for now return @@ -1642,11 +1666,17 @@ class Music(Items): try: self.run_add_updateArtist(item, viewtag, viewid, artisttype) except Exception as e: - utils.window('emby_dbScan', clear=True) self.logMsg('itemtypes.py for music artist has crashed for ' 'item %s. Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + self.logMsg('The item xml is:', -1) + try: + import xml.etree.cElementTree as etree + except ImportError: + import xml.etree.ElementTree as etree + etree.dump(item) + utils.window('plex_scancrashed', value='true') # skip this item for now return @@ -1738,11 +1768,17 @@ class Music(Items): try: self.run_add_updateAlbum(item, viewtag, viewid) except Exception as e: - utils.window('emby_dbScan', clear=True) self.logMsg('itemtypes.py for music album has crashed for ' 'item %s. Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + self.logMsg('The item xml is:', -1) + try: + import xml.etree.cElementTree as etree + except ImportError: + import xml.etree.ElementTree as etree + etree.dump(item) + utils.window('plex_scancrashed', value='true') # skip this item for now return @@ -1936,11 +1972,17 @@ class Music(Items): try: self.run_add_updateSong(item, viewtag, viewid) except Exception as e: - utils.window('emby_dbScan', clear=True) self.logMsg('itemtypes.py for music song has crashed for ' 'item %s. Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + self.logMsg('The item xml is:', -1) + try: + import xml.etree.cElementTree as etree + except ImportError: + import xml.etree.ElementTree as etree + etree.dump(item) + utils.window('plex_scancrashed', value='true') # skip this item for now return @@ -2275,4 +2317,4 @@ class Music(Items): artwork = self.artwork artwork.deleteArtwork(kodiid, "artist", kodicursor) - kodicursor.execute("DELETE FROM artist WHERE idArtist = ?", (kodiid,)) \ No newline at end of file + kodicursor.execute("DELETE FROM artist WHERE idArtist = ?", (kodiid,)) From a5d37caef0509f3de272fa0303911778901f2be7 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Thu, 10 Mar 2016 09:51:35 +0100 Subject: [PATCH 10/12] Show dialog if some items could not be processed --- resources/language/English/strings.xml | 1 + resources/language/German/strings.xml | 1 + resources/lib/librarysync.py | 8 ++++++++ 3 files changed, 10 insertions(+) diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml index 40caa5a8..180830bd 100644 --- a/resources/language/English/strings.xml +++ b/resources/language/English/strings.xml @@ -406,5 +406,6 @@ Plex playlists/nodes refreshed Plex playlists/nodes refresh failed Full library sync finished + Sync had to skip some items because they could not be processed. Please post your Kodi logs to the Plex forum. diff --git a/resources/language/German/strings.xml b/resources/language/German/strings.xml index 4b3b55cc..032c2d38 100644 --- a/resources/language/German/strings.xml +++ b/resources/language/German/strings.xml @@ -338,5 +338,6 @@ Plex Playlisten/Nodes aktualisiert Plex Playlisten/Nodes Aktualisierung fehlgeschlagen Plex Bibliotheken aktualisiert + Einige Plex Einträge mussten übersprungen werden, da sie nicht verarbeitet werden konnten. Bitte teilen Sie Ihr Kodi log im Plex Forum. diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index 415f04f9..ceccb137 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -340,6 +340,10 @@ class LibrarySync(Thread): # Reset and return self.allPlexElementsId = {} + # Show warning if itemtypes.py crashed at some point + if utils.window('plex_scancrashed') == 'true': + xbmcgui.Dialog().ok(self.addonName, self.__language__(39408)) + utils.window('plex_scancrashed', clear=True) return True def saveLastSync(self): @@ -413,6 +417,10 @@ class LibrarySync(Thread): utils.window('emby_initialScan', clear=True) xbmc.executebuiltin('InhibitIdleShutdown(false)') utils.setScreensaver(value=screensaver) + # Show warning if itemtypes.py crashed at some point + if utils.window('plex_scancrashed') == 'true': + xbmcgui.Dialog().ok(self.addonName, self.__language__(39408)) + utils.window('plex_scancrashed', clear=True) return True def processView(self, folderItem, kodi_db, emby_db, totalnodes): From 58d986f4ad08451b36bc08faa88fa64001e3e806 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Thu, 10 Mar 2016 09:58:26 +0100 Subject: [PATCH 11/12] Add traceback to library sync --- resources/lib/itemtypes.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/resources/lib/itemtypes.py b/resources/lib/itemtypes.py index 03d297d1..d5e49c85 100644 --- a/resources/lib/itemtypes.py +++ b/resources/lib/itemtypes.py @@ -290,6 +290,8 @@ class Movies(Items): self.logMsg('itemtypes.py for movies has crashed for item %s. ' 'Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + import traceback + self.logMsg("Traceback:\n%s" % traceback.format_exc(), 0) self.logMsg('The item xml is:', -1) try: import xml.etree.cElementTree as etree @@ -929,6 +931,8 @@ class TVShows(Items): self.logMsg('itemtypes.py for tv show has crashed for item %s. ' 'Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + import traceback + self.logMsg("Traceback:\n%s" % traceback.format_exc(), 0) self.logMsg('The item xml is:', -1) try: import xml.etree.cElementTree as etree @@ -1132,6 +1136,8 @@ class TVShows(Items): self.logMsg('itemtypes.py for tv seasons has crashed for item %s. ' 'Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + import traceback + self.logMsg("Traceback:\n%s" % traceback.format_exc(), 0) self.logMsg('The item xml is:', -1) try: import xml.etree.cElementTree as etree @@ -1183,6 +1189,8 @@ class TVShows(Items): self.logMsg('itemtypes.py for tv episode has crashed for item %s. ' 'Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + import traceback + self.logMsg("Traceback:\n%s" % traceback.format_exc(), 0) self.logMsg('The item xml is:', -1) try: import xml.etree.cElementTree as etree @@ -1670,6 +1678,8 @@ class Music(Items): 'item %s. Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + import traceback + self.logMsg("Traceback:\n%s" % traceback.format_exc(), 0) self.logMsg('The item xml is:', -1) try: import xml.etree.cElementTree as etree @@ -1772,6 +1782,8 @@ class Music(Items): 'item %s. Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + import traceback + self.logMsg("Traceback:\n%s" % traceback.format_exc(), 0) self.logMsg('The item xml is:', -1) try: import xml.etree.cElementTree as etree @@ -1976,6 +1988,8 @@ class Music(Items): 'item %s. Error:' % item.attrib.get('ratingKey', None), -1) self.logMsg(e, -1) + import traceback + self.logMsg("Traceback:\n%s" % traceback.format_exc(), 0) self.logMsg('The item xml is:', -1) try: import xml.etree.cElementTree as etree From fa7bc1285e7bece6ec823aa2f7cc7d0071cfffae Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Thu, 10 Mar 2016 10:47:24 +0100 Subject: [PATCH 12/12] Version bump --- addon.xml | 2 +- changelog.txt | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index a4a6ba85..89a63ccf 100644 --- a/addon.xml +++ b/addon.xml @@ -1,7 +1,7 @@ diff --git a/changelog.txt b/changelog.txt index c0c96be0..2ed31db3 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,10 @@ +version 1.0.6 +- Enable traceback and dump XMLs of failed PMS items in the log for lib sync +- Optimize notifications for library syncs +- Manually trigger full library scan from settings +- Merge with MediaBrowser/master up until db4cb448b0e4fd82662f8b82a800d8da8ea33688 + + version 1.0.5 - Catch exceptions in itemtypes and log them - Slightly increased download timeouts