From 31e51483e47c49d7148a30d517138485a63f67c1 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Tue, 7 Mar 2017 14:40:39 +0100 Subject: [PATCH 01/15] Update Danish translation --- resources/language/Danish/strings.xml | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/resources/language/Danish/strings.xml b/resources/language/Danish/strings.xml index ddb27394..0342a57c 100644 --- a/resources/language/Danish/strings.xml +++ b/resources/language/Danish/strings.xml @@ -222,7 +222,7 @@ Synkronisere ekstra Fanart Sync film BoxSets - [Farve gul] Nulstille lokale Kodi database[/COLOR] + [COLOR yellow] Nulstille lokale Kodi database[/COLOR] Vælg Set / Genoptag status sync DB Sync angivelse: Afspil Sync angivelse: @@ -283,7 +283,7 @@ Brug alternativ adresse Alternative server adresse Brug alternative enhed navn - [Farve gul] Nulstille login attempts[/COLOR] + [COLOR yellow] Nulstille login attempts[/COLOR] Indstillinger for synkronisering Vis synkronisering fremskridt Sync tomme TV shows @@ -295,7 +295,7 @@ Aktiver hurtig opstart (kræver server plugin) Maksimale elementer til at anmode serveren på én gang Afspilning - [Farve gul] Indtast netværk info[/COLOR] + [COLOR yellow] Indtast netværk info[/COLOR] Aktiverer Plex trailere (Plexpass er nødvendig) Bede om at afspille trailere Spring Plex slet bekræftelse over i kontekstmenuen (brug på eget ansvar) @@ -313,7 +313,7 @@ Varigheden af den video bibliotek pop op (i sekunder) Varigheden af den musikbibliotek pop op (i sekunder) Server beskeder - [Farve gul] Generere en ny unik enheds Id (f.eks. Når kloning Kodi)[/COLOR] + [COLOR yellow] Generere en ny unik enheds Id (f.eks. Når kloning Kodi)[/COLOR] Brugerne skal logge ind hver gang Kodi genstarter GENSTART KODI, HVIS DU FORETAGER ÆNDRINGER Komplet re-synkronisere nødvendigt @@ -382,10 +382,10 @@ Deaktivere Plex musikbibliotek? (Det anbefales at bruge Plex musik med direkte adgang til store musikbiblioteker. Kodi kan gå ned, ellers) Ønsker du at finjustere PKC nu, gå til plugins for dette. Du skal genstarte Kodi! - [Farve gul] Reparere lokale database (opdatere alt indhold)[/COLOR] - [Farve rød] Fuld eller delvis nulstilling af Database og PKC[/COLOR] - [Farve gul] Cachelagre alle billeder til Kodi tekstur cache now[/COLOR] - [Farve gul] Sync Emby tema medier til Kodi[/COLOR] + [COLOR yellow] Reparere lokale database (opdatere alt indhold)[/COLOR] + [COLOR red] Fuld eller delvis nulstilling af Database og PKC[/COLOR] + [COLOR yellow] Cachelagre alle billeder til Kodi tekstur cache now[/COLOR] + [COLOR yellow] Sync Emby tema medier til Kodi[/COLOR] lokal Kunne ikke godkendes. Loggede du ind på plex.tv? @@ -415,7 +415,7 @@ Senest Tilføjet: Vis titel til episode Senest Tilføjet: Føj sæson - og episode-nummer SxxExx Intet virker? Prøv en fuld reset! - [Farve gul] Vælg Plex Server fra listen[/COLOR] + [COLOR yellow] Vælg Plex Server fra listen[/COLOR] Vente før sync af nye/ændrede PMS element [s] Baggrundssynkronisering Kør en fuld bibliotek synkronisering hvert x minut @@ -432,7 +432,7 @@ Senest tilføjet: Vis allerede set episoder Senest tilføjet: Vis allerede set film (Opdater Plex spilleliste/noder!) Din nuværende Plex Media Server: - [Farve gul] Manuelt indtast Plex Media Server address[/COLOR] + [COLOR yellow] Manuelt indtast Plex Media Server address[/COLOR] Nuværende adresse: Nuværende port: Nuværende plex.tv status: @@ -455,7 +455,7 @@ Plex kan låse din konto, hvis dit login forsøg fejler for mange gange. Vil du fortsætte alligevel? Nulstille PMS forbindelser, vent Undladt at nulstille PKC. Prøv at genstarte Kodi. - [Farve gul] Skifte plex.tv login (logge på eller logge ud)[/COLOR] + [COLOR yellow] Skifte plex.tv login (logge på eller logge ud)[/COLOR] Endnu ikke forbundet med Plex Server Se senere Offline @@ -467,7 +467,7 @@ Afbryde (ja) eller gemme adresse alligevel (Nej)? Tilsluttet Plex.tv skift vellykket - [Farve gul] Se efter for manglende fanart på FanartTV nu![/COLOR] + [COLOR yellow] Se efter for manglende fanart på FanartTV nu![/COLOR] Søg kun efter manglende fanart eller Opdater alle fanart? Scanningen vil tage lang tid og sker i baggrunden. Opdater alle Mangler kun @@ -513,4 +513,7 @@ Kunne ikke stoppe den kørende database. Prøv igen senere. Fjern alle cachelagrede illustrationer? (anbefales!) Nulstil alle indstillinger for PlexKodiConnect Addon? (dette er normalt ikke anbefalet og unødvendigt!) + + Amazon Alexa (Voice Recognition) + Alexa aktivieren \ No newline at end of file From 47ea9f29686fa78b1b6944776a5827353a2bbd02 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Tue, 7 Mar 2017 16:37:36 +0100 Subject: [PATCH 02/15] Plex Channels! --- default.py | 12 +++-- resources/lib/entrypoint.py | 87 ++++++++++++++++++++++++++++++++++++- 2 files changed, 94 insertions(+), 5 deletions(-) diff --git a/default.py b/default.py index bfc9b517..fe646441 100644 --- a/default.py +++ b/default.py @@ -102,9 +102,11 @@ class Main(): 'ondeck': entrypoint.getOnDeck, 'chooseServer': entrypoint.chooseServer, 'watchlater': entrypoint.watchlater, + 'channels': entrypoint.channels, 'enterPMS': entrypoint.enterPMS, 'togglePlexTV': entrypoint.togglePlexTV, - 'Plex_Node': entrypoint.Plex_Node + 'Plex_Node': entrypoint.Plex_Node, + 'browse_plex_folder': entrypoint.browse_plex_folder } if "/extrafanart" in argv[0]: @@ -134,10 +136,10 @@ class Main(): elif mode in ("nextup", "inprogressepisodes"): limit = int(params['limit']) modes[mode](params['tagname'], limit) - - elif mode in ("channels","getsubfolders"): + + elif mode in ("getsubfolders"): modes[mode](itemid) - + elif mode == "browsecontent": modes[mode](itemid, params.get('type'), params.get('folderid')) @@ -162,6 +164,8 @@ class Main(): elif mode == 'Plex_Node': modes[mode](params.get('id'), params.get('viewOffset')) + elif mode == 'browse_plex_folder': + modes[mode](params.get('id')) else: modes[mode]() else: diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index 2aa33cd3..50eae44b 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -106,7 +106,10 @@ def Plex_Node(url, viewOffset, playdirectly=False, node=True): log.info('Plex_Node called with url: %s, viewOffset: %s' % (url, viewOffset)) # Plex redirect, e.g. watch later. Need to get actual URLs - xml = downloadutils.DownloadUtils().downloadUrl(url) + if url.startswith('http'): + xml = downloadutils.DownloadUtils().downloadUrl(url) + else: + xml = downloadutils.DownloadUtils().downloadUrl('{server}%s' % url) try: xml[0].attrib except: @@ -194,6 +197,9 @@ def doMainListing(): # Plex Watch later addDirectoryItem(lang(39211), "plugin://plugin.video.plexkodiconnect/?mode=watchlater") + # Plex Channels + addDirectoryItem(lang(30173), + "plugin://plugin.video.plexkodiconnect/?mode=channels") # Plex user switch addDirectoryItem(lang(39200) + window('plex_username'), "plugin://plugin.video.plexkodiconnect/" @@ -927,6 +933,85 @@ def watchlater(): cacheToDisc=settings('enableTextureCache') == 'true') +def channels(): + """ + Listing for Plex Channels + """ + if window('plex_restricteduser') == 'true': + log.error('No Plex Channels - restricted user') + return xbmcplugin.endOfDirectory(HANDLE, False) + + xml = downloadutils.DownloadUtils().downloadUrl('{server}/channels/all') + try: + xml[0].attrib + except (ValueError, AttributeError, IndexError): + log.error('Could not download Plex Channels') + return xbmcplugin.endOfDirectory(HANDLE, False) + + log.info('Displaying Plex Channels') + xbmcplugin.setContent(HANDLE, 'files') + for item in xml: + __build_folder(item) + xbmcplugin.endOfDirectory( + handle=HANDLE, + cacheToDisc=settings('enableTextureCache') == 'true') + + +def browse_plex_folder(key): + """ + Lists the content of a Plex folder, e.g. channels + """ + xml = downloadutils.DownloadUtils().downloadUrl('{server}%s' % key) + try: + xml[0].attrib + except (ValueError, AttributeError, IndexError): + log.error('Could not browse to %s' % key) + return xbmcplugin.endOfDirectory(HANDLE, False) + xbmcplugin.setContent(HANDLE, 'files') + for item in xml: + if item.tag == 'Directory': + __build_folder(item) + else: + __build_item(item) + xbmcplugin.endOfDirectory( + handle=HANDLE, + cacheToDisc=settings('enableTextureCache') == 'true') + + +def __build_folder(xml_element): + url = "plugin://plugin.video.plexkodiconnect/" + params = { + 'mode': "browse_plex_folder", + 'id': xml_element.attrib.get('key') + } + listitem = ListItem(xml_element.attrib.get('title')) + listitem.setArt({'thumb': xml_element.attrib.get('thumb'), + 'poster': xml_element.attrib.get('art')}) + xbmcplugin.addDirectoryItem( + handle=HANDLE, + url="%s?%s" % (url, urlencode(params)), + isFolder=True, + listitem=listitem) + + +def __build_item(xml_element): + url = "plugin://plugin.video.plexkodiconnect/" + api = API(xml_element) + listitem = api.CreateListItemFromPlexItem() + api.AddStreamInfo(listitem) + api.set_listitem_artwork(listitem) + params = { + 'mode': "Plex_Node", + 'id': xml_element.attrib.get('key'), + 'viewOffset': xml_element.attrib.get('viewOffset', '0'), + 'plex_type': xml_element.attrib.get('type') + } + xbmcplugin.addDirectoryItem( + handle=HANDLE, + url="%s?%s" % (url, urlencode(params)), + listitem=listitem) + + def enterPMS(): """ Opens dialogs for the user the plug in the PMS details From 4bc31cf4bc5a22b30dba5b67791ab47d2995f10c Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Wed, 8 Mar 2017 10:39:05 +0100 Subject: [PATCH 03/15] Code refactoring default.py --- default.py | 250 ++++++++++++++++++++---------------- resources/lib/entrypoint.py | 23 ---- 2 files changed, 136 insertions(+), 137 deletions(-) diff --git a/default.py b/default.py index fe646441..f70813a1 100644 --- a/default.py +++ b/default.py @@ -36,6 +36,7 @@ from utils import window, pickl_window, reset, passwordsXML, language as lang,\ dialog from pickler import unpickle_me from PKC_listitem import convert_PKC_to_listitem +import variables as v ############################################################################### @@ -65,133 +66,154 @@ class Main(): itemid = '' if mode == 'play': - # Put the request into the "queue" - while window('plex_play_new_item'): - sleep(50) - window('plex_play_new_item', - value='%s%s' % (mode, argv[2])) - # Wait for the result - while not pickl_window('plex_result'): - sleep(50) - result = unpickle_me() - if result is None: - log.error('Error encountered, aborting') - dialog('notification', - heading='{plex}', - message=lang(30128), - icon='{error}', - time=3000) - setResolvedUrl(HANDLE, False, ListItem()) - elif result.listitem: - listitem = convert_PKC_to_listitem(result.listitem) - setResolvedUrl(HANDLE, True, listitem) - return + self.play() - modes = { - 'reset': reset, - 'resetauth': entrypoint.resetAuth, - 'passwords': passwordsXML, - 'getsubfolders': entrypoint.GetSubFolders, - 'nextup': entrypoint.getNextUpEpisodes, - 'inprogressepisodes': entrypoint.getInProgressEpisodes, - 'recentepisodes': entrypoint.getRecentEpisodes, - 'refreshplaylist': entrypoint.refreshPlaylist, - 'switchuser': entrypoint.switchPlexUser, - 'deviceid': entrypoint.resetDeviceId, - 'browseplex': entrypoint.BrowsePlexContent, - 'ondeck': entrypoint.getOnDeck, - 'chooseServer': entrypoint.chooseServer, - 'watchlater': entrypoint.watchlater, - 'channels': entrypoint.channels, - 'enterPMS': entrypoint.enterPMS, - 'togglePlexTV': entrypoint.togglePlexTV, - 'Plex_Node': entrypoint.Plex_Node, - 'browse_plex_folder': entrypoint.browse_plex_folder - } + elif mode == 'ondeck': + entrypoint.getOnDeck(itemid, + params.get('type'), + params.get('tagname'), + int(params.get('limit'))) - if "/extrafanart" in argv[0]: + elif mode == 'recentepisodes': + entrypoint.getRecentEpisodes(itemid, + params.get('type'), + params.get('tagname'), + int(params.get('limit'))) + + elif mode == 'nextup': + entrypoint.getNextUpEpisodes(params['tagname'], + int(params['limit'])) + + elif mode == "inprogressepisodes": + entrypoint.getInProgressEpisodes(params['tagname'], + int(params['limit'])) + + elif mode == 'Plex_Node': + entrypoint.Plex_Node(params.get('id'), params.get('viewOffset')) + + elif mode == 'browse_plex_folder': + entrypoint.browse_plex_folder(params.get('id')) + + elif mode == 'browseplex': + entrypoint.BrowsePlexContent(itemid, + params.get('type'), + params.get('folderid')) + + elif mode == "getsubfolders": + entrypoint.GetSubFolders(itemid) + + elif mode == 'watchlater': + entrypoint.watchlater() + + elif mode == 'channels': + entrypoint.channels() + + elif mode == "settings": + executebuiltin('Addon.OpenSettings(%s)' % v.ADDON_ID) + + elif mode == "enterPMS": + entrypoint.enterPMS() + + elif mode == 'reset': + reset() + + elif mode == 'togglePlexTV': + entrypoint.togglePlexTV() + + elif mode == 'resetauth': + entrypoint.resetAuth() + + elif mode == 'passwords': + passwordsXML() + + elif mode == 'switchuser': + entrypoint.switchPlexUser() + + elif mode in ("manualsync", "repair"): + if window('plex_online') != "true": + # Server is not online, do not run the sync + dialog('ok', + heading=lang(29999), + message=lang(39205)) + log.error("Not connected to a PMS.") + else: + if mode == 'repair': + window('plex_runLibScan', value="repair") + log.info("Requesting repair lib sync") + elif mode == 'manualsync': + log.info("Requesting full library scan") + window('plex_runLibScan', value="full") + + elif mode == "texturecache": + window('plex_runLibScan', value='del_textures') + + elif mode == "chooseServer": + entrypoint.chooseServer() + + elif mode == "refreshplaylist": + log.info('Requesting playlist/nodes refresh') + window('plex_runLibScan', value="views") + + elif mode == "deviceid": + self.deviceid() + + elif mode == 'fanart': + log.info('User requested fanarttv refresh') + window('plex_runLibScan', value='fanart') + + elif "/extrafanart" in argv[0]: plexpath = argv[2][1:] plexid = params.get('id') entrypoint.getExtraFanArt(plexid, plexpath) entrypoint.getVideoFiles(plexid, plexpath) - return - - if mode == 'fanart': - log.info('User requested fanarttv refresh') - window('plex_runLibScan', value='fanart') # Called by e.g. 3rd party plugin video extras - if ("/Extras" in argv[0] or "/VideoFiles" in argv[0] or + elif ("/Extras" in argv[0] or "/VideoFiles" in argv[0] or "/Extras" in argv[2]): plexId = params.get('id', None) entrypoint.getVideoFiles(plexId, params) - if modes.get(mode): - # Simple functions - if mode == "play": - dbid = params.get('dbid') - # modes[mode](itemid, dbid) - modes[mode](itemid, dbid) - - elif mode in ("nextup", "inprogressepisodes"): - limit = int(params['limit']) - modes[mode](params['tagname'], limit) - - elif mode in ("getsubfolders"): - modes[mode](itemid) - - elif mode == "browsecontent": - modes[mode](itemid, params.get('type'), params.get('folderid')) - - elif mode == 'browseplex': - modes[mode]( - itemid, - params.get('type'), - params.get('folderid')) - - elif mode in ('ondeck', 'recentepisodes'): - modes[mode]( - itemid, - params.get('type'), - params.get('tagname'), - int(params.get('limit'))) - - elif mode == "channelsfolder": - folderid = params['folderid'] - modes[mode](itemid, folderid) - elif mode == "companion": - modes[mode](itemid, params=argv[2]) - elif mode == 'Plex_Node': - modes[mode](params.get('id'), - params.get('viewOffset')) - elif mode == 'browse_plex_folder': - modes[mode](params.get('id')) - else: - modes[mode]() else: - # Other functions - if mode == "settings": - executebuiltin('Addon.OpenSettings(plugin.video.plexkodiconnect)') - elif mode in ("manualsync", "repair"): - if window('plex_online') != "true": - # Server is not online, do not run the sync - dialog('ok', - heading=lang(29999), - message=lang(39205)) - log.error("Not connected to a PMS.") - else: - if mode == 'repair': - window('plex_runLibScan', value="repair") - log.info("Requesting repair lib sync") - elif mode == 'manualsync': - log.info("Requesting full library scan") - window('plex_runLibScan', value="full") - elif mode == "texturecache": - window('plex_runLibScan', value='del_textures') - else: - entrypoint.doMainListing() + entrypoint.doMainListing() + + def play(self): + # Put the request into the "queue" + while window('plex_play_new_item'): + sleep(50) + window('plex_play_new_item', + value='%s%s' % ('play', argv[2])) + # Wait for the result + while not pickl_window('plex_result'): + sleep(50) + result = unpickle_me() + if result is None: + log.error('Error encountered, aborting') + dialog('notification', + heading='{plex}', + message=lang(30128), + icon='{error}', + time=3000) + setResolvedUrl(HANDLE, False, ListItem()) + elif result.listitem: + listitem = convert_PKC_to_listitem(result.listitem) + setResolvedUrl(HANDLE, True, listitem) + + def deviceid(self): + deviceId_old = window('plex_client_Id') + from clientinfo import getDeviceId + try: + deviceId = getDeviceId(reset=True) + except Exception as e: + log.error("Failed to generate a new device Id: %s" % e) + dialog('ok', lang(29999), lang(33032)) + else: + log.info("Successfully removed old device ID: %s New deviceId:" + "%s" % (deviceId_old, deviceId)) + # "Kodi will now restart to apply the changes" + dialog('ok', lang(29999), lang(33033)) + executebuiltin('RestartApp') if __name__ == "__main__": - log.info('plugin.video.plexkodiconnect started') + log.info('%s started' % v.ADDON_ID) Main() - log.info('plugin.video.plexkodiconnect stopped') + log.info('%s stopped' % v.ADDON_ID) diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index 50eae44b..80a84821 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -217,23 +217,6 @@ def doMainListing(): xbmcplugin.endOfDirectory(HANDLE) -##### Generate a new deviceId -def resetDeviceId(): - deviceId_old = window('plex_client_Id') - from clientinfo import getDeviceId - try: - deviceId = getDeviceId(reset=True) - except Exception as e: - log.error("Failed to generate a new device Id: %s" % e) - dialog('ok', lang(29999), lang(33032)) - else: - log.info("Successfully removed old deviceId: %s New deviceId: %s" - % (deviceId_old, deviceId)) - # "Kodi will now restart to apply the changes" - dialog('ok', lang(29999), lang(33033)) - executebuiltin('RestartApp') - - def switchPlexUser(): """ Signs out currently logged in user (if applicable). Triggers sign-in of a @@ -255,12 +238,6 @@ def switchPlexUser(): __LogIn() -##### REFRESH EMBY PLAYLISTS ##### -def refreshPlaylist(): - log.info('Requesting playlist/nodes refresh') - window('plex_runLibScan', value="views") - - #### SHOW SUBFOLDERS FOR NODE ##### def GetSubFolders(nodeindex): nodetypes = ["",".recent",".recentepisodes",".inprogress",".inprogressepisodes",".unwatched",".nextepisodes",".sets",".genres",".random",".recommended"] From fd7e30f84c7fbb9e6e6e13cbd5f94822d3d10694 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Wed, 8 Mar 2017 10:46:10 +0100 Subject: [PATCH 04/15] Remove boilerplate --- resources/lib/entrypoint.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index 80a84821..792d5c92 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -888,22 +888,8 @@ def watchlater(): log.info('Displaying watch later plex.tv items') xbmcplugin.setContent(HANDLE, 'movies') - url = "plugin://plugin.video.plexkodiconnect/" - params = { - 'mode': "Plex_Node", - } for item in xml: - api = API(item) - listitem = api.CreateListItemFromPlexItem() - api.AddStreamInfo(listitem) - api.set_listitem_artwork(listitem) - params['id'] = item.attrib.get('key') - params['viewOffset'] = item.attrib.get('viewOffset', '0') - params['plex_type'] = item.attrib.get('type') - xbmcplugin.addDirectoryItem( - handle=HANDLE, - url="%s?%s" % (url, urlencode(params)), - listitem=listitem) + __build_item(item) xbmcplugin.endOfDirectory( handle=HANDLE, From 2a48a71673bb99ded3e220d3595a5b99c958b221 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Wed, 8 Mar 2017 10:51:21 +0100 Subject: [PATCH 05/15] Code optimization --- resources/lib/entrypoint.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index 792d5c92..e3a97abc 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -942,7 +942,7 @@ def browse_plex_folder(key): def __build_folder(xml_element): - url = "plugin://plugin.video.plexkodiconnect/" + url = "plugin://%s/" % v.ADDON_ID params = { 'mode': "browse_plex_folder", 'id': xml_element.attrib.get('key') @@ -950,15 +950,14 @@ def __build_folder(xml_element): listitem = ListItem(xml_element.attrib.get('title')) listitem.setArt({'thumb': xml_element.attrib.get('thumb'), 'poster': xml_element.attrib.get('art')}) - xbmcplugin.addDirectoryItem( - handle=HANDLE, - url="%s?%s" % (url, urlencode(params)), - isFolder=True, - listitem=listitem) + xbmcplugin.addDirectoryItem(handle=HANDLE, + url="%s?%s" % (url, urlencode(params)), + isFolder=True, + listitem=listitem) def __build_item(xml_element): - url = "plugin://plugin.video.plexkodiconnect/" + url = "plugin://%s/" % v.ADDON_ID api = API(xml_element) listitem = api.CreateListItemFromPlexItem() api.AddStreamInfo(listitem) @@ -969,10 +968,9 @@ def __build_item(xml_element): 'viewOffset': xml_element.attrib.get('viewOffset', '0'), 'plex_type': xml_element.attrib.get('type') } - xbmcplugin.addDirectoryItem( - handle=HANDLE, - url="%s?%s" % (url, urlencode(params)), - listitem=listitem) + xbmcplugin.addDirectoryItem(handle=HANDLE, + url="%s?%s" % (url, urlencode(params)), + listitem=listitem) def enterPMS(): From 65fde9088f053b1766af53b31b2a36704fde5814 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Wed, 8 Mar 2017 10:58:08 +0100 Subject: [PATCH 06/15] Code refactoring --- default.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/default.py b/default.py index f70813a1..2e67a255 100644 --- a/default.py +++ b/default.py @@ -58,12 +58,8 @@ class Main(): log.debug("Full sys.argv received: %s" % argv) # Parse parameters params = dict(parse_qsl(argv[2][1:])) - try: - mode = params['mode'] - itemid = params.get('id', '') - except: - mode = "" - itemid = '' + mode = params.get('mode', '') + itemid = params.get('id', '') if mode == 'play': self.play() @@ -89,10 +85,10 @@ class Main(): int(params['limit'])) elif mode == 'Plex_Node': - entrypoint.Plex_Node(params.get('id'), params.get('viewOffset')) + entrypoint.Plex_Node(itemid, params.get('viewOffset')) elif mode == 'browse_plex_folder': - entrypoint.browse_plex_folder(params.get('id')) + entrypoint.browse_plex_folder(itemid) elif mode == 'browseplex': entrypoint.BrowsePlexContent(itemid, @@ -163,14 +159,14 @@ class Main(): elif "/extrafanart" in argv[0]: plexpath = argv[2][1:] - plexid = params.get('id') + plexid = itemid entrypoint.getExtraFanArt(plexid, plexpath) entrypoint.getVideoFiles(plexid, plexpath) # Called by e.g. 3rd party plugin video extras elif ("/Extras" in argv[0] or "/VideoFiles" in argv[0] or "/Extras" in argv[2]): - plexId = params.get('id', None) + plexId = itemid or None entrypoint.getVideoFiles(plexId, params) else: From 78e4a17430355b94fe7f307f40a6de59303611ea Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Wed, 8 Mar 2017 11:02:25 +0100 Subject: [PATCH 07/15] Code refactoring --- default.py | 55 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/default.py b/default.py index 2e67a255..321514b7 100644 --- a/default.py +++ b/default.py @@ -43,7 +43,7 @@ import variables as v import loghandler loghandler.config() -log = logging.getLogger("PLEX.default") +log = logging.getLogger('PLEX.default') ############################################################################### @@ -51,11 +51,10 @@ HANDLE = int(argv[1]) class Main(): - # MAIN ENTRY POINT # @utils.profiling() def __init__(self): - log.debug("Full sys.argv received: %s" % argv) + log.debug('Full sys.argv received: %s' % argv) # Parse parameters params = dict(parse_qsl(argv[2][1:])) mode = params.get('mode', '') @@ -80,7 +79,7 @@ class Main(): entrypoint.getNextUpEpisodes(params['tagname'], int(params['limit'])) - elif mode == "inprogressepisodes": + elif mode == 'inprogressepisodes': entrypoint.getInProgressEpisodes(params['tagname'], int(params['limit'])) @@ -95,7 +94,7 @@ class Main(): params.get('type'), params.get('folderid')) - elif mode == "getsubfolders": + elif mode == 'getsubfolders': entrypoint.GetSubFolders(itemid) elif mode == 'watchlater': @@ -104,10 +103,10 @@ class Main(): elif mode == 'channels': entrypoint.channels() - elif mode == "settings": + elif mode == 'settings': executebuiltin('Addon.OpenSettings(%s)' % v.ADDON_ID) - elif mode == "enterPMS": + elif mode == 'enterPMS': entrypoint.enterPMS() elif mode == 'reset': @@ -125,47 +124,47 @@ class Main(): elif mode == 'switchuser': entrypoint.switchPlexUser() - elif mode in ("manualsync", "repair"): - if window('plex_online') != "true": + elif mode in ('manualsync', 'repair'): + if window('plex_online') != 'true': # Server is not online, do not run the sync dialog('ok', heading=lang(29999), message=lang(39205)) - log.error("Not connected to a PMS.") + log.error('Not connected to a PMS.') else: if mode == 'repair': - window('plex_runLibScan', value="repair") - log.info("Requesting repair lib sync") + window('plex_runLibScan', value='repair') + log.info('Requesting repair lib sync') elif mode == 'manualsync': - log.info("Requesting full library scan") - window('plex_runLibScan', value="full") + log.info('Requesting full library scan') + window('plex_runLibScan', value='full') - elif mode == "texturecache": + elif mode == 'texturecache': window('plex_runLibScan', value='del_textures') - elif mode == "chooseServer": + elif mode == 'chooseServer': entrypoint.chooseServer() - elif mode == "refreshplaylist": + elif mode == 'refreshplaylist': log.info('Requesting playlist/nodes refresh') - window('plex_runLibScan', value="views") + window('plex_runLibScan', value='views') - elif mode == "deviceid": + elif mode == 'deviceid': self.deviceid() elif mode == 'fanart': log.info('User requested fanarttv refresh') window('plex_runLibScan', value='fanart') - elif "/extrafanart" in argv[0]: + elif '/extrafanart' in argv[0]: plexpath = argv[2][1:] plexid = itemid entrypoint.getExtraFanArt(plexid, plexpath) entrypoint.getVideoFiles(plexid, plexpath) # Called by e.g. 3rd party plugin video extras - elif ("/Extras" in argv[0] or "/VideoFiles" in argv[0] or - "/Extras" in argv[2]): + elif ('/Extras' in argv[0] or '/VideoFiles' in argv[0] or + '/Extras' in argv[2]): plexId = itemid or None entrypoint.getVideoFiles(plexId, params) @@ -173,7 +172,7 @@ class Main(): entrypoint.doMainListing() def play(self): - # Put the request into the "queue" + # Put the request into the 'queue' while window('plex_play_new_item'): sleep(50) window('plex_play_new_item', @@ -200,16 +199,16 @@ class Main(): try: deviceId = getDeviceId(reset=True) except Exception as e: - log.error("Failed to generate a new device Id: %s" % e) + log.error('Failed to generate a new device Id: %s' % e) dialog('ok', lang(29999), lang(33032)) else: - log.info("Successfully removed old device ID: %s New deviceId:" - "%s" % (deviceId_old, deviceId)) - # "Kodi will now restart to apply the changes" + log.info('Successfully removed old device ID: %s New deviceId:' + '%s' % (deviceId_old, deviceId)) + # 'Kodi will now restart to apply the changes' dialog('ok', lang(29999), lang(33033)) executebuiltin('RestartApp') -if __name__ == "__main__": +if __name__ == '__main__': log.info('%s started' % v.ADDON_ID) Main() log.info('%s stopped' % v.ADDON_ID) From be7ecb95dbe076ab61ae169a4ef786b68e025046 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Wed, 8 Mar 2017 16:21:00 +0100 Subject: [PATCH 08/15] Specify Kodi sort methods --- default.py | 8 +- resources/lib/entrypoint.py | 171 +++++++++++++++++++----------------- resources/lib/variables.py | 92 ++++++++++++++++++- 3 files changed, 181 insertions(+), 90 deletions(-) diff --git a/default.py b/default.py index 321514b7..1887faea 100644 --- a/default.py +++ b/default.py @@ -86,13 +86,9 @@ class Main(): elif mode == 'Plex_Node': entrypoint.Plex_Node(itemid, params.get('viewOffset')) - elif mode == 'browse_plex_folder': - entrypoint.browse_plex_folder(itemid) - elif mode == 'browseplex': - entrypoint.BrowsePlexContent(itemid, - params.get('type'), - params.get('folderid')) + entrypoint.browse_plex(key=params.get('key'), + plex_section_id=params.get('id')) elif mode == 'getsubfolders': entrypoint.GetSubFolders(itemid) diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index e3a97abc..f693e49e 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -644,83 +644,6 @@ def RunLibScan(mode): window('plex_runLibScan', value='full') -def BrowsePlexContent(viewid, mediatype="", folderid=""): - """ - Browse Plex Photos: - viewid: PMS name of the library - mediatype: mediatype, 'photos' - nodetype: e.g. 'ondeck' (TBD!!) - """ - log.debug("BrowsePlexContent called with viewid: %s, mediatype: " - "%s, folderid: %s" % (viewid, mediatype, folderid)) - - if not folderid: - # Top-level navigation, so get the content of this section - # Get all sections - xml = GetPlexSectionResults( - viewid, - containerSize=int(settings('limitindex'))) - try: - xml.attrib - except AttributeError: - log.error("Error download section %s" % viewid) - return xbmcplugin.endOfDirectory(HANDLE, False) - else: - # folderid was passed so we can directly access the folder - xml = downloadutils.DownloadUtils().downloadUrl( - "{server}%s" % folderid) - try: - xml.attrib - except AttributeError: - log.error("Error downloading %s" % folderid) - return xbmcplugin.endOfDirectory(HANDLE, False) - - # Set the folder's name - xbmcplugin.setPluginCategory(HANDLE, - xml.attrib.get('librarySectionTitle')) - - # set the correct params for the content type - if mediatype == "photos": - xbmcplugin.setContent(HANDLE, 'photos') - - # process the listing - for item in xml: - api = API(item) - if item.tag == 'Directory': - li = ListItem(item.attrib.get('title', 'Missing title')) - # for folders we add an additional browse request, passing the - # folderId - li.setProperty('IsFolder', 'true') - li.setProperty('IsPlayable', 'false') - path = "%s?id=%s&mode=browseplex&type=%s&folderid=%s" \ - % (ARGV_0, viewid, mediatype, api.getKey()) - api.set_listitem_artwork(li) - xbmcplugin.addDirectoryItem(handle=HANDLE, - url=path, - listitem=li, - isFolder=True) - else: - li = api.CreateListItemFromPlexItem() - api.set_listitem_artwork(li) - xbmcplugin.addDirectoryItem( - handle=HANDLE, - url=li.getProperty("path"), - listitem=li) - - xbmcplugin.addSortMethod(HANDLE, - xbmcplugin.SORT_METHOD_VIDEO_TITLE) - xbmcplugin.addSortMethod(HANDLE, - xbmcplugin.SORT_METHOD_DATE) - xbmcplugin.addSortMethod(HANDLE, - xbmcplugin.SORT_METHOD_VIDEO_RATING) - xbmcplugin.addSortMethod(HANDLE, - xbmcplugin.SORT_METHOD_VIDEO_RUNTIME) - - xbmcplugin.endOfDirectory( - handle=HANDLE, - cacheToDisc=settings('enableTextureCache') == 'true') - - def getOnDeck(viewid, mediatype, tagname, limit): """ Retrieves Plex On Deck items, currently only for TV shows @@ -913,6 +836,8 @@ def channels(): log.info('Displaying Plex Channels') xbmcplugin.setContent(HANDLE, 'files') + for method in v.SORT_METHODS_DIRECTORY: + xbmcplugin.addSortMethod(HANDLE, getattr(xbmcplugin, method)) for item in xml: __build_folder(item) xbmcplugin.endOfDirectory( @@ -920,22 +845,102 @@ def channels(): cacheToDisc=settings('enableTextureCache') == 'true') -def browse_plex_folder(key): +def browse_plex(key=None, plex_section_id=None): """ - Lists the content of a Plex folder, e.g. channels + Lists the content of a Plex folder, e.g. channels. Either pass in key (to + be used directly for PMS url {server}) or the plex_section_id """ - xml = downloadutils.DownloadUtils().downloadUrl('{server}%s' % key) + if key: + xml = downloadutils.DownloadUtils().downloadUrl('{server}%s' % key) + else: + xml = GetPlexSectionResults( + plex_section_id, + containerSize=int(settings('limitindex'))) try: xml[0].attrib except (ValueError, AttributeError, IndexError): log.error('Could not browse to %s' % key) return xbmcplugin.endOfDirectory(HANDLE, False) - xbmcplugin.setContent(HANDLE, 'files') + + directory = False + photos = False + movies = False + clips = False + tvshows = False + episodes = False + songs = False + artists = False + albums = False + musicvideos = False for item in xml: + typus = item.attrib.get('type') if item.tag == 'Directory': + directory = True __build_folder(item) else: __build_item(item) + if typus == v.PLEX_TYPE_PHOTO: + photos = True + elif typus == v.PLEX_TYPE_MOVIE: + movies = True + elif typus == v.PLEX_TYPE_CLIP: + clips = True + elif typus in (v.PLEX_TYPE_SHOW, v.PLEX_TYPE_SEASON): + tvshows = True + elif typus == v.PLEX_TYPE_EPISODE: + episodes = True + elif typus == v.PLEX_TYPE_SONG: + songs = True + elif typus == v.PLEX_TYPE_ARTIST: + artists = True + elif typus == v.PLEX_TYPE_ALBUM: + albums = True + elif typus == v.PLEX_TYPE_MUSICVIDEO: + musicvideos = True + + # Set the correct content type + if directory is True: + xbmcplugin.setContent(HANDLE, 'files') + sort_methods = v.SORT_METHODS_DIRECTORY + elif photos is True: + # E.g. Plex foto sections with videos (both!!) + xbmcplugin.setContent(HANDLE, 'files') + sort_methods = v.SORT_METHODS_PHOTOS + elif clips is True: + xbmcplugin.setContent(HANDLE, 'movies') + sort_methods = v.SORT_METHODS_CLIPS + elif movies is True: + xbmcplugin.setContent(HANDLE, 'movies') + sort_methods = v.SORT_METHODS_MOVIES + elif tvshows is True: + xbmcplugin.setContent(HANDLE, 'tvshows') + sort_methods = v.SORT_METHOD_TVSHOWS + elif episodes is True: + xbmcplugin.setContent(HANDLE, 'episodes') + sort_methods = v.SORT_METHODS_EPISODES + elif songs is True: + xbmcplugin.setContent(HANDLE, 'songs') + sort_methods = v.SORT_METHODS_SONGS + elif artists is True: + xbmcplugin.setContent(HANDLE, 'artists') + sort_methods = v.SORT_METHODS_ARTISTS + elif albums is True: + xbmcplugin.setContent(HANDLE, 'albums') + sort_methods = v.SORT_METHODS_ALBUMS + elif musicvideos is True: + xbmcplugin.setContent(HANDLE, 'musicvideos') + sort_methods = v.SORT_METHODS_MOVIES + else: + xbmcplugin.setContent(HANDLE, 'files') + sort_methods = v.SORT_METHODS_DIRECTORY + + for method in sort_methods: + xbmcplugin.addSortMethod(HANDLE, getattr(xbmcplugin, method)) + + # Set the Kodi title for this view + title = xml.attrib.get('librarySectionTitle', xml.attrib.get('title1')) + xbmcplugin.setPluginCategory(HANDLE, title) + xbmcplugin.endOfDirectory( handle=HANDLE, cacheToDisc=settings('enableTextureCache') == 'true') @@ -944,8 +949,8 @@ def browse_plex_folder(key): def __build_folder(xml_element): url = "plugin://%s/" % v.ADDON_ID params = { - 'mode': "browse_plex_folder", - 'id': xml_element.attrib.get('key') + 'mode': "browseplex", + 'key': xml_element.attrib.get('key') } listitem = ListItem(xml_element.attrib.get('title')) listitem.setArt({'thumb': xml_element.attrib.get('thumb'), diff --git a/resources/lib/variables.py b/resources/lib/variables.py index 1ed3fa9c..f28af541 100644 --- a/resources/lib/variables.py +++ b/resources/lib/variables.py @@ -113,6 +113,7 @@ PLEX_TYPE_AUDIO = 'music' PLEX_TYPE_SONG = 'track' PLEX_TYPE_ALBUM = 'album' PLEX_TYPE_ARTIST = 'artist' +PLEX_TYPE_MUSICVIDEO = 'musicvideo' PLEX_TYPE_PHOTO = 'photo' @@ -131,6 +132,7 @@ KODI_TYPE_AUDIO = 'audio' KODI_TYPE_SONG = 'song' KODI_TYPE_ALBUM = 'album' KODI_TYPE_ARTIST = 'artist' +KODI_TYPE_MUSICVIDEO = 'musicvideo' KODI_TYPE_PHOTO = 'photo' @@ -195,7 +197,8 @@ KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE = { PLEX_TYPE_ARTIST: KODI_TYPE_AUDIO, PLEX_TYPE_ALBUM: KODI_TYPE_AUDIO, PLEX_TYPE_SONG: KODI_TYPE_AUDIO, - PLEX_TYPE_AUDIO: KODI_TYPE_AUDIO + PLEX_TYPE_AUDIO: KODI_TYPE_AUDIO, + PLEX_TYPE_PHOTO: 'picture' } @@ -266,3 +269,90 @@ ALEXA_TO_COMPANION = { 'queryContainerKey': 'containerKey', 'queryToken': 'token', } + +# Kodi sort methods for xbmcplugin.addSortMethod() +SORT_METHODS_DIRECTORY = ( + 'SORT_METHOD_UNSORTED', # sorted as returned from Plex + 'SORT_METHOD_LABEL', +) + +SORT_METHODS_PHOTOS = ( + 'SORT_METHOD_UNSORTED', + 'SORT_METHOD_LABEL', + 'SORT_METHOD_DATE', + 'SORT_METHOD_DATEADDED', +) + +SORT_METHODS_CLIPS = ( + 'SORT_METHOD_UNSORTED', + 'SORT_METHOD_TITLE', + 'SORT_METHOD_DURATION', +) + +SORT_METHODS_MOVIES = ( + 'SORT_METHOD_UNSORTED', + 'SORT_METHOD_TITLE', + 'SORT_METHOD_DURATION', + 'SORT_METHOD_VIDEO_RATING', + 'SORT_METHOD_VIDEO_USER_RATING', + 'SORT_METHOD_MPAA_RATING', + 'SORT_METHOD_COUNTRY', + 'SORT_METHOD_STUDIO', + 'SORT_METHOD_GENRE', +) + +SORT_METHOD_TVSHOWS = ( + 'SORT_METHOD_UNSORTED', + 'SORT_METHOD_TITLE', + 'SORT_METHOD_VIDEO_RATING', + 'SORT_METHOD_VIDEO_USER_RATING', + 'SORT_METHOD_MPAA_RATING', + 'SORT_METHOD_COUNTRY', + 'SORT_METHOD_GENRE', +) + +SORT_METHODS_EPISODES = ( + 'SORT_METHOD_UNSORTED', + 'SORT_METHOD_TITLE', + 'SORT_METHOD_DURATION', + 'SORT_METHOD_VIDEO_RATING', + 'SORT_METHOD_VIDEO_USER_RATING', + 'SORT_METHOD_EPISODE', + 'SORT_METHOD_VIDEO_SORT_TITLE', + 'SORT_METHOD_MPAA_RATING', + 'SORT_METHOD_COUNTRY', + 'SORT_METHOD_STUDIO', + 'SORT_METHOD_GENRE', +) + +SORT_METHODS_SONGS = ( + 'SORT_METHOD_UNSORTED', + 'SORT_METHOD_TITLE', + 'SORT_METHOD_TRACKNUM', + 'SORT_METHOD_DURATION', + 'SORT_METHOD_ARTIST', + 'SORT_METHOD_ARTIST_AND_YEAR', + 'SORT_METHOD_ALBUM', + 'SORT_METHOD_SONG_RATING', + 'SORT_METHOD_SONG_USER_RATING' +) + +SORT_METHODS_ARTISTS = ( + 'SORT_METHOD_UNSORTED', + 'SORT_METHOD_TITLE', + 'SORT_METHOD_TRACKNUM', + 'SORT_METHOD_DURATION', + 'SORT_METHOD_ARTIST', + 'SORT_METHOD_ARTIST_AND_YEAR', + 'SORT_METHOD_ALBUM', +) + +SORT_METHODS_ALBUMS = ( + 'SORT_METHOD_UNSORTED', + 'SORT_METHOD_TITLE', + 'SORT_METHOD_TRACKNUM', + 'SORT_METHOD_DURATION', + 'SORT_METHOD_ARTIST', + 'SORT_METHOD_ARTIST_AND_YEAR', + 'SORT_METHOD_ALBUM', +) From 6f7d5d5d596688655e34e106f23b4ab8beb4073e Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Wed, 8 Mar 2017 16:41:49 +0100 Subject: [PATCH 09/15] Browse video nodes by folder/path --- resources/language/English/strings.xml | 1 + resources/lib/videonodes.py | 95 ++++++++++++++------------ 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml index f2de1455..69313894 100644 --- a/resources/language/English/strings.xml +++ b/resources/language/English/strings.xml @@ -516,4 +516,5 @@ Amazon Alexa (Voice Recognition) Activate Alexa + Browse by folder diff --git a/resources/lib/videonodes.py b/resources/lib/videonodes.py index da621151..6b9fb4a8 100644 --- a/resources/lib/videonodes.py +++ b/resources/lib/videonodes.py @@ -131,58 +131,64 @@ class VideoNodes(object): '9': "genres", '10': "random", '11': "recommended", - '12': "ondeck" + '12': "ondeck", + '13': 'browsefiles' } mediatypes = { # label according to nodetype per mediatype - 'movies': + 'movies': { - '1': tagname, - '2': 30174, - # '4': 30177, - # '6': 30189, - '8': 39501, - '9': 135, - '10': 30227, - '11': 30230, - '12': 39500, + '1': tagname, + '2': 30174, + # '4': 30177, + # '6': 30189, + '8': 39501, + '9': 135, + '10': 30227, + '11': 30230, + '12': 39500, + '13': 39702 }, - 'tvshows': + 'tvshows': { - '1': tagname, - # '2': 30170, - '3': 30174, - # '4': 30171, - # '5': 30178, - # '7': 30179, - '9': 135, - '10': 30227, - # '11': 30230, - '12': 39500, - }, - - 'homevideos': - { - '1': tagname, - '2': 30251, - '11': 30253 - }, - - 'photos': - { - '1': tagname, - '2': 30252, - '8': 30255, - '11': 30254 + '1': tagname, + # '2': 30170, + '3': 30174, + # '4': 30171, + # '5': 30178, + # '7': 30179, + '9': 135, + '10': 30227, + # '11': 30230, + '12': 39500, + '13': 39702 }, - 'musicvideos': + 'homevideos': { - '1': tagname, - '2': 30256, - '4': 30257, - '6': 30258 + '1': tagname, + '2': 30251, + '11': 30253, + '13': 39702 + }, + + 'photos': + { + '1': tagname, + '2': 30252, + '8': 30255, + '11': 30254, + '13': 39702 + }, + + 'musicvideos': + { + '1': tagname, + '2': 30256, + '4': 30257, + '6': 30258, + '13': 39702 } } @@ -200,6 +206,7 @@ class VideoNodes(object): '10': '8', # "random", '11': '5', # "recommended", '12': '1', # "ondeck" + '13': '9' # browse by folder } nodes = mediatypes[mediatype] @@ -244,6 +251,8 @@ class VideoNodes(object): elif mediatype =="movies": # Reset nodetype; we got the label nodetype = 'inprogress' + elif nodetype == 'browsefiles': + path = 'plugin://plugin.video.plexkodiconnect?mode=browseplex&key=/library/sections/%s/folder' % viewid else: path = "library://video/Plex-%s/%s_%s.xml" % (dirname, viewid, nodetype) @@ -285,7 +294,7 @@ class VideoNodes(object): continue # Create the root - if (nodetype in ("nextepisodes", "ondeck", 'recentepisodes') or mediatype == "homevideos"): + if (nodetype in ("nextepisodes", "ondeck", 'recentepisodes', 'browsefiles') or mediatype == "homevideos"): # Folder type with plugin path root = self.commonRoot(order=sortorder[node], label=label, tagname=tagname, roottype=2) etree.SubElement(root, 'path').text = path From 80e2ad49085294f1e6b2b84616701ab4e23bdbfe Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Wed, 8 Mar 2017 17:02:26 +0100 Subject: [PATCH 10/15] Tweaking of browse by folder --- resources/lib/entrypoint.py | 18 ++++++------------ resources/lib/variables.py | 8 +++----- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index f693e49e..65f5f0fa 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -862,7 +862,6 @@ def browse_plex(key=None, plex_section_id=None): log.error('Could not browse to %s' % key) return xbmcplugin.endOfDirectory(HANDLE, False) - directory = False photos = False movies = False clips = False @@ -875,7 +874,6 @@ def browse_plex(key=None, plex_section_id=None): for item in xml: typus = item.attrib.get('type') if item.tag == 'Directory': - directory = True __build_folder(item) else: __build_item(item) @@ -899,19 +897,15 @@ def browse_plex(key=None, plex_section_id=None): musicvideos = True # Set the correct content type - if directory is True: - xbmcplugin.setContent(HANDLE, 'files') - sort_methods = v.SORT_METHODS_DIRECTORY - elif photos is True: - # E.g. Plex foto sections with videos (both!!) - xbmcplugin.setContent(HANDLE, 'files') - sort_methods = v.SORT_METHODS_PHOTOS + if movies is True: + xbmcplugin.setContent(HANDLE, 'movies') + sort_methods = v.SORT_METHODS_MOVIES elif clips is True: xbmcplugin.setContent(HANDLE, 'movies') sort_methods = v.SORT_METHODS_CLIPS - elif movies is True: - xbmcplugin.setContent(HANDLE, 'movies') - sort_methods = v.SORT_METHODS_MOVIES + elif photos is True: + xbmcplugin.setContent(HANDLE, 'files') + sort_methods = v.SORT_METHODS_PHOTOS elif tvshows is True: xbmcplugin.setContent(HANDLE, 'tvshows') sort_methods = v.SORT_METHOD_TVSHOWS diff --git a/resources/lib/variables.py b/resources/lib/variables.py index f28af541..dda52ac5 100644 --- a/resources/lib/variables.py +++ b/resources/lib/variables.py @@ -314,15 +314,13 @@ SORT_METHOD_TVSHOWS = ( SORT_METHODS_EPISODES = ( 'SORT_METHOD_UNSORTED', 'SORT_METHOD_TITLE', + 'SORT_METHOD_EPISODE', 'SORT_METHOD_DURATION', 'SORT_METHOD_VIDEO_RATING', 'SORT_METHOD_VIDEO_USER_RATING', - 'SORT_METHOD_EPISODE', - 'SORT_METHOD_VIDEO_SORT_TITLE', 'SORT_METHOD_MPAA_RATING', - 'SORT_METHOD_COUNTRY', - 'SORT_METHOD_STUDIO', - 'SORT_METHOD_GENRE', + 'SORT_METHOD_FILE', + 'SORT_METHOD_FULLPATH', ) SORT_METHODS_SONGS = ( From cbbb5b1cebeea242ecf2135f65264c1d2815f467 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Wed, 8 Mar 2017 17:06:30 +0100 Subject: [PATCH 11/15] Change playlist type from 'picture' to 'photo' --- resources/lib/playqueue.py | 2 ++ resources/lib/variables.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/resources/lib/playqueue.py b/resources/lib/playqueue.py index 7adfca1a..551bd5f3 100644 --- a/resources/lib/playqueue.py +++ b/resources/lib/playqueue.py @@ -53,6 +53,8 @@ class Playqueue(Thread): else: # Currently, only video or audio playqueues available playqueue.kodi_pl = PlayList(PLAYLIST_VIDEO) + # Overwrite 'picture' with 'photo' + playqueue.type = v.KODI_TYPE_PHOTO self.playqueues.append(playqueue) # sort the list by their playlistid, just in case self.playqueues = sorted( diff --git a/resources/lib/variables.py b/resources/lib/variables.py index dda52ac5..cf05a893 100644 --- a/resources/lib/variables.py +++ b/resources/lib/variables.py @@ -198,7 +198,7 @@ KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE = { PLEX_TYPE_ALBUM: KODI_TYPE_AUDIO, PLEX_TYPE_SONG: KODI_TYPE_AUDIO, PLEX_TYPE_AUDIO: KODI_TYPE_AUDIO, - PLEX_TYPE_PHOTO: 'picture' + PLEX_TYPE_PHOTO: KODI_TYPE_PHOTO } From a12b5033b9df90a1365cfb93720f719602787cee Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Wed, 8 Mar 2017 17:53:43 +0100 Subject: [PATCH 12/15] Rewire Plex photo navigation --- resources/lib/entrypoint.py | 10 +++++++--- resources/lib/videonodes.py | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index 65f5f0fa..3a077484 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -874,7 +874,7 @@ def browse_plex(key=None, plex_section_id=None): for item in xml: typus = item.attrib.get('type') if item.tag == 'Directory': - __build_folder(item) + __build_folder(item, plex_section_id=plex_section_id) else: __build_item(item) if typus == v.PLEX_TYPE_PHOTO: @@ -940,11 +940,15 @@ def browse_plex(key=None, plex_section_id=None): cacheToDisc=settings('enableTextureCache') == 'true') -def __build_folder(xml_element): +def __build_folder(xml_element, plex_section_id=None): url = "plugin://%s/" % v.ADDON_ID + key = xml_element.attrib.get('fastKey', xml_element.attrib.get('key')) + if not key.startswith('/'): + key = '/library/sections/%s/%s' % (plex_section_id, key) params = { 'mode': "browseplex", - 'key': xml_element.attrib.get('key') + 'key': key, + 'id': plex_section_id } listitem = ListItem(xml_element.attrib.get('title')) listitem.setArt({'thumb': xml_element.attrib.get('thumb'), diff --git a/resources/lib/videonodes.py b/resources/lib/videonodes.py index 6b9fb4a8..3d16fd91 100644 --- a/resources/lib/videonodes.py +++ b/resources/lib/videonodes.py @@ -102,7 +102,7 @@ class VideoNodes(object): return if mediatype == "photos": - path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=getsubfolders" % indexnumber + path = "plugin://plugin.video.plexkodiconnect?mode=browseplex&key=/library/sections/%s&id=%s" % (viewid, viewid) window('Plex.nodes.%s.index' % indexnumber, value=path) From 7171fc7df4fd164ec121edf3aa100dacedfc83e7 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Wed, 8 Mar 2017 18:07:36 +0100 Subject: [PATCH 13/15] Remove method --- resources/lib/playutils.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/resources/lib/playutils.py b/resources/lib/playutils.py index 7c4e1af4..410819c5 100644 --- a/resources/lib/playutils.py +++ b/resources/lib/playutils.py @@ -70,19 +70,6 @@ class PlayUtils(): log.info("The playurl is: %s" % playurl) return playurl - def httpPlay(self): - # Audio, Video, Photo - - itemid = self.item['Id'] - mediatype = self.item['MediaType'] - - if mediatype == "Audio": - playurl = "%s/emby/Audio/%s/stream" % (self.server, itemid) - else: - playurl = "%s/emby/Videos/%s/stream?static=true" % (self.server, itemid) - - return playurl - def isDirectPlay(self): """ Returns the path/playurl if we can direct play, None otherwise From 012371c0103bfb06ae1cba2236d78faa4ba95852 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Wed, 8 Mar 2017 18:24:50 +0100 Subject: [PATCH 14/15] Update playback of photos --- resources/lib/entrypoint.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index 3a077484..123c2283 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -960,19 +960,23 @@ def __build_folder(xml_element, plex_section_id=None): def __build_item(xml_element): - url = "plugin://%s/" % v.ADDON_ID api = API(xml_element) listitem = api.CreateListItemFromPlexItem() api.AddStreamInfo(listitem) api.set_listitem_artwork(listitem) - params = { - 'mode': "Plex_Node", - 'id': xml_element.attrib.get('key'), - 'viewOffset': xml_element.attrib.get('viewOffset', '0'), - 'plex_type': xml_element.attrib.get('type') - } + if api.getType() != v.PLEX_TYPE_PHOTO: + url = "plugin://%s/" % v.ADDON_ID + params = { + 'mode': "Plex_Node", + 'id': xml_element.attrib.get('key'), + 'viewOffset': xml_element.attrib.get('viewOffset', '0'), + 'plex_type': xml_element.attrib.get('type') + } + url = '%s?%s' % (url, urlencode(params)) + else: + url = listitem.getProperty('path') xbmcplugin.addDirectoryItem(handle=HANDLE, - url="%s?%s" % (url, urlencode(params)), + url=url, listitem=listitem) From 0fc9f31aca15cefe9e0ab508597d6a2775395942 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Wed, 8 Mar 2017 19:09:27 +0100 Subject: [PATCH 15/15] Version bump --- addon.xml | 2 +- changelog.txt | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 7c699048..b7a9df67 100644 --- a/addon.xml +++ b/addon.xml @@ -1,7 +1,7 @@ diff --git a/changelog.txt b/changelog.txt index f9eb03a3..4e056649 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,9 @@ +version 1.6.5 (beta only) +- Plex Channels! +- Browse video nodes by folder/path +- Update Danish translation +- Code optimization + version 1.6.4 (beta only) - Amazon Alexa support! Be mindful to check the Alexa forum thread first; there are still many issues completely unrelated to PKC - Enable skipping for Plex Companion