diff --git a/resources/lib/PlexAPI.py b/resources/lib/PlexAPI.py index 3337a2a9..71ca8bef 100644 --- a/resources/lib/PlexAPI.py +++ b/resources/lib/PlexAPI.py @@ -50,7 +50,8 @@ import downloadutils from utils import window, settings, language as lang, tryDecode, tryEncode, \ DateToKodi, KODILANGUAGE from PlexFunctions import PLEX_TO_KODI_TIMEFACTOR, PMSHttpsEnabled, \ - REMAP_TYPE_FROM_PLEXTYPE, PLEX_TYPE_MOVIE, PLEX_TYPE_SHOW + REMAP_TYPE_FROM_PLEXTYPE, PLEX_TYPE_MOVIE, PLEX_TYPE_SHOW, \ + PLEX_TYPE_EPISODE import plexdb_functions as plexdb ############################################################################### @@ -2318,7 +2319,7 @@ class API(): externalsubs.append(url) kodiindex += 1 mapping = json.dumps(mapping) - window('emby_%s.indexMapping' % playurl, value=mapping) + window('plex_%s.indexMapping' % playurl, value=mapping) log.info('Found external subs: %s' % externalsubs) return externalsubs @@ -2563,3 +2564,68 @@ class API(): line1=lang(39031) + url, line2=lang(39032)) return resp + + def set_listitem_artwork(self, listitem): + """ + Set all artwork to the listitem + """ + allartwork = self.getAllArtwork(parentInfo=True) + arttypes = { + 'poster': "Primary", + 'tvshow.poster': "Thumb", + 'clearart': "Art", + 'tvshow.clearart': "Art", + 'clearart': "Primary", + 'tvshow.clearart': "Primary", + 'clearlogo': "Logo", + 'tvshow.clearlogo': "Logo", + 'discart': "Disc", + 'fanart_image': "Backdrop", + 'landscape': "Backdrop", + "banner": "Banner" + } + for arttype in arttypes: + art = arttypes[arttype] + if art == "Backdrop": + try: + # Backdrop is a list, grab the first backdrop + self._set_listitem_artprop(listitem, + arttype, + allartwork[art][0]) + except: + pass + else: + self._set_listitem_artprop(listitem, arttype, allartwork[art]) + + def _set_listitem_artprop(self, listitem, arttype, path): + if arttype in ( + 'thumb', 'fanart_image', 'small_poster', 'tiny_poster', + 'medium_landscape', 'medium_poster', 'small_fanartimage', + 'medium_fanartimage', 'fanart_noindicators'): + listitem.setProperty(arttype, path) + else: + listitem.setArt({arttype: path}) + + def set_playback_win_props(self, playurl, listitem): + """ + Set all properties necessary for plugin path playback for listitem + """ + itemtype = self.getType() + userdata = self.getUserData() + + plexitem = "plex_%s" % playurl + window('%s.runtime' % plexitem, value=str(userdata['Runtime'])) + window('%s.type' % plexitem, value=itemtype) + window('%s.itemid' % plexitem, value=self.getRatingKey()) + window('%s.playcount' % plexitem, value=str(userdata['PlayCount'])) + + if itemtype == PLEX_TYPE_EPISODE: + window('%s.refreshid' % plexitem, value=self.getParentRatingKey()) + else: + window('%s.refreshid' % plexitem, value=self.getRatingKey()) + + # Append external subtitles to stream + playmethod = window('%s.playmethod' % plexitem) + if playmethod in ("DirectStream", "DirectPlay"): + subtitles = self.externalSubs(playurl) + listitem.setSubtitles(subtitles) diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index 251ae0b5..2e6a934e 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -1035,14 +1035,14 @@ def BrowsePlexContent(viewid, mediatype="", folderid=""): li.setProperty('IsPlayable', 'false') path = "%s?id=%s&mode=browseplex&type=%s&folderid=%s" \ % (sys.argv[0], viewid, mediatype, API.getKey()) - pbutils.PlaybackUtils(item).setArtwork(li) + API.set_listitem_artwork(li) xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=path, listitem=li, isFolder=True) else: li = API.CreateListItemFromPlexItem() - pbutils.PlaybackUtils(item).setArtwork(li) + API.set_listitem_artwork(li) xbmcplugin.addDirectoryItem( handle=int(sys.argv[1]), url=li.getProperty("path"), @@ -1099,7 +1099,7 @@ def getOnDeck(viewid, mediatype, tagname, limit): appendShowTitle=appendShowTitle, appendSxxExx=appendSxxExx) API.AddStreamInfo(listitem) - pbutils.PlaybackUtils(item).setArtwork(listitem) + API.set_listitem_artwork(listitem) if directpaths: url = API.getFilePath() else: @@ -1252,7 +1252,7 @@ def watchlater(): API = PlexAPI.API(item) listitem = API.CreateListItemFromPlexItem() API.AddStreamInfo(listitem) - pbutils.PlaybackUtils(item).setArtwork(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') diff --git a/resources/lib/kodidb_functions.py b/resources/lib/kodidb_functions.py index d02d2fb6..db83ea1b 100644 --- a/resources/lib/kodidb_functions.py +++ b/resources/lib/kodidb_functions.py @@ -32,8 +32,8 @@ class GetKodiDB(): def __enter__(self): self.kodiconn = kodiSQL(self.itemType) - self.emby_db = Kodidb_Functions(self.kodiconn.cursor()) - return self.emby_db + kodi_db = Kodidb_Functions(self.kodiconn.cursor()) + return kodi_db def __exit__(self, type, value, traceback): self.kodiconn.commit() diff --git a/resources/lib/kodimonitor.py b/resources/lib/kodimonitor.py index 4aeafa13..019c1b5f 100644 --- a/resources/lib/kodimonitor.py +++ b/resources/lib/kodimonitor.py @@ -3,17 +3,16 @@ ############################################################################### import logging -import json +from json import loads -import xbmc -import xbmcgui +from xbmc import Monitor, Player, sleep import downloadutils import plexdb_functions as plexdb -import playbackutils as pbutils from utils import window, settings, CatchExceptions, tryDecode, tryEncode from PlexFunctions import scrobble, REMAP_TYPE_FROM_PLEXTYPE from kodidb_functions import get_kodiid_from_filename +from PlexAPI import API ############################################################################### @@ -22,14 +21,14 @@ log = logging.getLogger("PLEX."+__name__) ############################################################################### -class KodiMonitor(xbmc.Monitor): +class KodiMonitor(Monitor): def __init__(self, callback): self.mgr = callback self.doUtils = downloadutils.DownloadUtils().downloadUrl - self.xbmcplayer = xbmc.Player() + self.xbmcplayer = Player() self.playqueue = self.mgr.playqueue - xbmc.Monitor.__init__(self) + Monitor.__init__(self) log.info("Kodi monitor started.") def onScanStarted(self, library): @@ -71,7 +70,7 @@ class KodiMonitor(xbmc.Monitor): def onNotification(self, sender, method, data): if data: - data = json.loads(data, 'utf-8') + data = loads(data, 'utf-8') log.debug("Method: %s Data: %s" % (method, data)) if method == "Player.OnPlay": @@ -102,9 +101,9 @@ class KodiMonitor(xbmc.Monitor): "video library update") else: # Stop from manually marking as watched unwatched, with actual playback. - if window('emby_skipWatched%s' % itemid) == "true": + if window('plex_skipWatched%s' % itemid) == "true": # property is set in player.py - window('emby_skipWatched%s' % itemid, clear=True) + window('plex_skipWatched%s' % itemid, clear=True) else: # notify the server if playcount != 0: @@ -122,13 +121,13 @@ class KodiMonitor(xbmc.Monitor): elif method == "System.OnWake": # Allow network to wake up - xbmc.sleep(10000) + sleep(10000) window('plex_onWake', value="true") window('plex_online', value="false") elif method == "GUI.OnScreensaverDeactivated": if settings('dbSyncScreensaver') == "true": - xbmc.sleep(5000) + sleep(5000) window('plex_runLibScan', value="full") def PlayBackStart(self, data): @@ -142,7 +141,7 @@ class KodiMonitor(xbmc.Monitor): currentFile = None count = 0 while currentFile is None: - xbmc.sleep(100) + sleep(100) try: currentFile = self.xbmcplayer.getPlayingFile() except: @@ -166,7 +165,7 @@ class KodiMonitor(xbmc.Monitor): # Try to get a Kodi ID # If PKC was used - native paths, not direct paths - plexid = window('emby_%s.itemid' % tryEncode(currentFile)) + plexid = window('plex_%s.itemid' % tryEncode(currentFile)) # Get rid of the '' if the window property was not set plexid = None if not plexid else plexid kodiid = None @@ -210,24 +209,25 @@ class KodiMonitor(xbmc.Monitor): # Save currentFile for cleanup later and to be able to access refs window('plex_lastPlayedFiled', value=currentFile) window('plex_currently_playing_itemid', value=plexid) - window("emby_%s.itemid" % tryEncode(currentFile), value=plexid) + window("plex_%s.itemid" % tryEncode(currentFile), value=plexid) log.info('Finish playback startup') def StartDirectPath(self, plexid, type, currentFile): """ Set some additional stuff if playback was initiated by Kodi, not PKC """ - result = self.doUtils('{server}/library/metadata/%s' % plexid) + xml = self.doUtils('{server}/library/metadata/%s' % plexid) try: - result[0].attrib + xml[0].attrib except: log.error('Did not receive a valid XML for plexid %s.' % plexid) return False # Setup stuff, because playback was started by Kodi, not PKC - pbutils.PlaybackUtils(result[0]).setProperties( - currentFile, xbmcgui.ListItem()) + api = API(xml[0]) + listitem = api.CreateListItemFromPlexItem() + api.set_playback_win_props(currentFile, listitem) if type == "song" and settings('streamMusic') == "true": - window('emby_%s.playmethod' % currentFile, value="DirectStream") + window('plex_%s.playmethod' % currentFile, value="DirectStream") else: - window('emby_%s.playmethod' % currentFile, value="DirectPlay") + window('plex_%s.playmethod' % currentFile, value="DirectPlay") log.debug('Window properties set for direct paths!') diff --git a/resources/lib/playback_starter.py b/resources/lib/playback_starter.py index c4b78b3f..cf910c63 100644 --- a/resources/lib/playback_starter.py +++ b/resources/lib/playback_starter.py @@ -45,7 +45,7 @@ class Playback_Starter(Thread): api = API(xml[0]) listitem = api.CreateListItemFromPlexItem(listitem) api.AddStreamInfo(listitem) - listitem = PlaybackUtils(xml[0], self.mgr).setArtwork(listitem) + api.set_listitem_artwork(listitem) result.listitem = listitem else: # Video and Music diff --git a/resources/lib/playbackutils.py b/resources/lib/playbackutils.py index 65043071..5eba8272 100644 --- a/resources/lib/playbackutils.py +++ b/resources/lib/playbackutils.py @@ -68,10 +68,10 @@ class PlaybackUtils(): # Item is not in Kodi database, is a trailer/clip or plex redirect # e.g. plex.tv watch later api.CreateListItemFromPlexItem(listitem) - self.setArtwork(listitem) + api.set_listitem_artwork(listitem) if kodi_id == 'plexnode': # Need to get yet another xml to get final url - window('emby_%s.playmethod' % playurl, clear=True) + window('plex_%s.playmethod' % playurl, clear=True) xml = downloadutils.DownloadUtils().downloadUrl( '{server}%s' % item[0][0].attrib.get('key')) try: @@ -81,16 +81,16 @@ class PlaybackUtils(): % item[0][0].attrib.get('key')) return playurl = tryEncode(xml[0].attrib.get('key')) - window('emby_%s.playmethod' % playurl, value='DirectStream') + window('plex_%s.playmethod' % playurl, value='DirectStream') - playmethod = window('emby_%s.playmethod' % playurl) + playmethod = window('plex_%s.playmethod' % playurl) if playmethod == "Transcode": - window('emby_%s.playmethod' % playurl, clear=True) + window('plex_%s.playmethod' % playurl, clear=True) playurl = tryEncode(playutils.audioSubsPref( listitem, tryDecode(playurl))) - window('emby_%s.playmethod' % playurl, "Transcode") + window('plex_%s.playmethod' % playurl, "Transcode") listitem.setPath(playurl) - self.setProperties(playurl, listitem) + api.set_playback_win_props(playurl, listitem) result.listitem = listitem return result @@ -197,16 +197,16 @@ class PlaybackUtils(): # Cannot add via JSON with full metadata because then we # Would be using the direct path log.debug("Adding contextmenu item for direct paths") - if window('emby_%s.playmethod' % playurl) == "Transcode": - window('emby_%s.playmethod' % playurl, + if window('plex_%s.playmethod' % playurl) == "Transcode": + window('plex_%s.playmethod' % playurl, clear=True) playurl = tryEncode(playutils.audioSubsPref( listitem, tryDecode(playurl))) - window('emby_%s.playmethod' % playurl, + window('plex_%s.playmethod' % playurl, value="Transcode") api.CreateListItemFromPlexItem(listitem) - self.setProperties(playurl, listitem) - self.setArtwork(listitem) + api.set_playback_win_props(playurl, listitem) + api.set_listitem_artwork(listitem) kodiPl.add(playurl, listitem, index=self.currentPosition+1) else: # Full metadata @@ -236,8 +236,9 @@ class PlaybackUtils(): log.debug("Adding additional part: %s, url: %s" % (counter, additionalPlayurl)) api.CreateListItemFromPlexItem(additionalListItem) - self.setProperties(additionalPlayurl, additionalListItem) - self.setArtwork(additionalListItem) + api.set_playback_win_props(additionalPlayurl, + additionalListItem) + api.set_listitem_artwork(additionalListItem) add_listitem_to_playlist( playqueue, self.currentPosition, @@ -266,15 +267,16 @@ class PlaybackUtils(): # SETUP MAIN ITEM ########## # For transcoding only, ask for audio/subs pref - if (window('emby_%s.playmethod' % playurl) == "Transcode" and + if (window('plex_%s.playmethod' % playurl) == "Transcode" and not contextmenu_play): - window('emby_%s.playmethod' % playurl, clear=True) + window('plex_%s.playmethod' % playurl, clear=True) playurl = tryEncode(playutils.audioSubsPref( listitem, tryDecode(playurl))) - window('emby_%s.playmethod' % playurl, value="Transcode") + window('plex_%s.playmethod' % playurl, value="Transcode") listitem.setPath(playurl) - self.setProperties(playurl, listitem) + api.set_playback_win_props(playurl, listitem) + api.set_listitem_artwork(listitem) # PLAYBACK ################ if (homeScreen and seektime and window('plex_customplaylist') != "true" @@ -325,7 +327,7 @@ class PlaybackUtils(): params['id'] = introAPI.getRatingKey() params['filename'] = introAPI.getKey() introPlayurl = path + '?' + urlencode(params) - self.setArtwork(listitem, introAPI) + introAPI.set_listitem_artwork(listitem) # Overwrite the Plex url listitem.setPath(introPlayurl) log.info("Adding Intro: %s" % introPlayurl) @@ -337,67 +339,3 @@ class PlaybackUtils(): intro) self.currentPosition += 1 return True - - def setProperties(self, playurl, listitem): - # Set all properties necessary for plugin path playback - itemid = self.api.getRatingKey() - itemtype = self.api.getType() - userdata = self.api.getUserData() - - embyitem = "emby_%s" % playurl - window('%s.runtime' % embyitem, value=str(userdata['Runtime'])) - window('%s.type' % embyitem, value=itemtype) - window('%s.itemid' % embyitem, value=itemid) - window('%s.playcount' % embyitem, value=str(userdata['PlayCount'])) - - if itemtype == "episode": - window('%s.refreshid' % embyitem, - value=self.api.getParentRatingKey()) - else: - window('%s.refreshid' % embyitem, value=itemid) - - # Append external subtitles to stream - playmethod = window('%s.playmethod' % embyitem) - if playmethod in ("DirectStream", "DirectPlay"): - subtitles = self.api.externalSubs(playurl) - listitem.setSubtitles(subtitles) - - self.setArtwork(listitem) - - def setArtwork(self, listItem, api=None): - if api is None: - api = self.api - allartwork = api.getAllArtwork(parentInfo=True) - arttypes = { - 'poster': "Primary", - 'tvshow.poster': "Thumb", - 'clearart': "Art", - 'tvshow.clearart': "Art", - 'clearart': "Primary", - 'tvshow.clearart': "Primary", - 'clearlogo': "Logo", - 'tvshow.clearlogo': "Logo", - 'discart': "Disc", - 'fanart_image': "Backdrop", - 'landscape': "Backdrop", - "banner": "Banner" - } - for arttype in arttypes: - art = arttypes[arttype] - if art == "Backdrop": - try: - # Backdrop is a list, grab the first backdrop - self.setArtProp(listItem, arttype, allartwork[art][0]) - except: - pass - else: - self.setArtProp(listItem, arttype, allartwork[art]) - - def setArtProp(self, listItem, arttype, path): - if arttype in ( - 'thumb', 'fanart_image', 'small_poster', 'tiny_poster', - 'medium_landscape', 'medium_poster', 'small_fanartimage', - 'medium_fanartimage', 'fanart_noindicators'): - listItem.setProperty(arttype, path) - else: - listItem.setArt({arttype: path}) diff --git a/resources/lib/player.py b/resources/lib/player.py index 6c79d76c..14e4a3af 100644 --- a/resources/lib/player.py +++ b/resources/lib/player.py @@ -77,11 +77,11 @@ class Player(xbmc.Player): self.currentFile = currentFile window('plex_lastPlayedFiled', value=currentFile) # We may need to wait for info to be set in kodi monitor - itemId = window("emby_%s.itemid" % currentFile) + itemId = window("plex_%s.itemid" % currentFile) count = 0 while not itemId: xbmc.sleep(200) - itemId = window("emby_%s.itemid" % currentFile) + itemId = window("plex_%s.itemid" % currentFile) if count == 5: log.warn("Could not find itemId, cancelling playback report!") return @@ -89,7 +89,7 @@ class Player(xbmc.Player): log.info("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId)) - plexitem = "emby_%s" % currentFile + plexitem = "plex_%s" % currentFile runtime = window("%s.runtime" % plexitem) refresh_id = window("%s.refreshid" % plexitem) playMethod = window("%s.playmethod" % plexitem) @@ -98,7 +98,7 @@ class Player(xbmc.Player): playcount = int(window("%s.playcount" % plexitem)) except ValueError: playcount = 0 - window('emby_skipWatched%s' % itemId, value="true") + window('plex_skipWatched%s' % itemId, value="true") log.debug("Playing itemtype is: %s" % itemType) @@ -339,7 +339,7 @@ class Player(xbmc.Player): playMethod = data['playmethod'] # Prevent manually mark as watched in Kodi monitor - window('emby_skipWatched%s' % itemid, value="true") + window('plex_skipWatched%s' % itemid, value="true") if currentPosition and runtime: try: @@ -392,13 +392,13 @@ class Player(xbmc.Player): # Clean the WINDOW properties for filename in self.played_info: cleanup = ( - 'emby_%s.itemid' % filename, - 'emby_%s.runtime' % filename, - 'emby_%s.refreshid' % filename, - 'emby_%s.playmethod' % filename, - 'emby_%s.type' % filename, - 'emby_%s.runtime' % filename, - 'emby_%s.playcount' % filename, + 'plex_%s.itemid' % filename, + 'plex_%s.runtime' % filename, + 'plex_%s.refreshid' % filename, + 'plex_%s.playmethod' % filename, + 'plex_%s.type' % filename, + 'plex_%s.runtime' % filename, + 'plex_%s.playcount' % filename, 'plex_%s.playlistPosition' % filename ) for item in cleanup: diff --git a/resources/lib/playlist_func.py b/resources/lib/playlist_func.py index 30479f74..ee2794f5 100644 --- a/resources/lib/playlist_func.py +++ b/resources/lib/playlist_func.py @@ -212,7 +212,7 @@ def update_playlist_from_PMS(playlist, playlist_id=None, xml=None): try: xml.attrib['%sVersion' % playlist.kind] except: - log.error('Could not download Plex playlist.') + log.error('Could not process Plex playlist') return # Clear our existing playlist and the associated Kodi playlist playlist.clear() diff --git a/resources/lib/playqueue.py b/resources/lib/playqueue.py index c58f127a..096c2c96 100644 --- a/resources/lib/playqueue.py +++ b/resources/lib/playqueue.py @@ -85,7 +85,8 @@ class Playqueue(Thread): with lock: if playqueue_id != playqueue.ID: log.debug('Need to fetch new playQueue from the PMS') - PL.update_playlist_from_PMS(playqueue, playqueue_id) + xml = PL.get_PMS_playlist(playqueue, playqueue_id) + PL.update_playlist_from_PMS(playqueue, playqueue_id, xml=xml) else: log.debug('Restarting existing playQueue') PL.refresh_playlist_from_PMS(playqueue) diff --git a/resources/lib/playutils.py b/resources/lib/playutils.py index 254c33a1..af6d6b8e 100644 --- a/resources/lib/playutils.py +++ b/resources/lib/playutils.py @@ -45,14 +45,14 @@ class PlayUtils(): log.info("File is direct playing.") playurl = tryEncode(playurl) # Set playmethod property - window('emby_%s.playmethod' % playurl, "DirectPlay") + window('plex_%s.playmethod' % playurl, "DirectPlay") elif self.isDirectStream(): log.info("File is direct streaming.") playurl = tryEncode( self.API.getTranscodeVideoPath('DirectStream')) # Set playmethod property - window('emby_%s.playmethod' % playurl, "DirectStream") + window('plex_%s.playmethod' % playurl, "DirectStream") else: log.info("File is transcoding.") @@ -64,7 +64,7 @@ class PlayUtils(): 'videoQuality': '100' })) # Set playmethod property - window('emby_%s.playmethod' % playurl, value="Transcode") + window('plex_%s.playmethod' % playurl, value="Transcode") log.info("The playurl is: %s" % playurl) return playurl