From aac892fed80c2e9f3c9b4acad10f837eec58823e Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Mon, 9 Jan 2017 19:56:57 +0100 Subject: [PATCH] Rewire Plex Companion startup --- resources/lib/entrypoint.py | 97 +----------------- resources/lib/playback_starter.py | 7 +- resources/lib/playbackutils.py | 160 +++++++++++++++++------------- resources/lib/playqueue.py | 32 +++--- 4 files changed, 116 insertions(+), 180 deletions(-) diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index 6d9e60fe..eca0ac3c 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -23,6 +23,7 @@ import playbackutils as pbutils import PlexFunctions import PlexAPI from PKC_listitem import convert_PKC_to_listitem +from playqueue import Playqueue ############################################################################### @@ -121,7 +122,8 @@ def Plex_Node(url, viewOffset, plex_type, playdirectly=False): window('plex_customplaylist.seektime', value=str(viewOffset)) log.info('Set resume point to %s' % str(viewOffset)) typus = PlexFunctions.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[plex_type] - result = pbutils.PlaybackUtils(xml[0],playlist_type=typus).play( + playqueue = Playqueue().get_playqueue_from_type(typus) + result = pbutils.PlaybackUtils(xml, playqueue).play( None, kodi_id='plexnode', plex_lib_UUID=xml.attrib.get('librarySectionUUID')) @@ -383,99 +385,6 @@ def BrowseContent(viewname, browse_type="", folderid=""): xbmcplugin.endOfDirectory(handle=int(sys.argv[1])) -##### CREATE LISTITEM FROM EMBY METADATA ##### -# def createListItemFromEmbyItem(item,art=artwork.Artwork(),doUtils=downloadutils.DownloadUtils()): -def createListItemFromEmbyItem(item,art=None,doUtils=downloadutils.DownloadUtils()): - API = PlexAPI.API(item) - itemid = item['Id'] - - title = item.get('Name') - li = xbmcgui.ListItem(title) - - premieredate = item.get('PremiereDate',"") - if not premieredate: premieredate = item.get('DateCreated',"") - if premieredate: - premieredatelst = premieredate.split('T')[0].split("-") - premieredate = "%s.%s.%s" %(premieredatelst[2],premieredatelst[1],premieredatelst[0]) - - li.setProperty("plexid",itemid) - - allart = art.getAllArtwork(item) - - if item["Type"] == "Photo": - #listitem setup for pictures... - img_path = allart.get('Primary') - li.setProperty("path",img_path) - picture = doUtils.downloadUrl("{server}/Items/%s/Images" %itemid) - if picture: - picture = picture[0] - if picture.get("Width") > picture.get("Height"): - li.setArt( {"fanart": img_path}) #add image as fanart for use with skinhelper auto thumb/backgrund creation - li.setInfo('pictures', infoLabels={ "picturepath": img_path, "date": premieredate, "size": picture.get("Size"), "exif:width": str(picture.get("Width")), "exif:height": str(picture.get("Height")), "title": title}) - li.setThumbnailImage(img_path) - li.setProperty("plot",API.getOverview()) - li.setArt({'icon': 'DefaultPicture.png'}) - else: - #normal video items - li.setProperty('IsPlayable', 'true') - path = "%s?id=%s&mode=play" % (sys.argv[0], item.get("Id")) - li.setProperty("path",path) - genre = API.getGenres() - overlay = 0 - userdata = API.getUserData() - runtime = item.get("RunTimeTicks",0)/ 10000000.0 - seektime = userdata['Resume'] - if seektime: - li.setProperty("resumetime", str(seektime)) - li.setProperty("totaltime", str(runtime)) - - played = userdata['Played'] - if played: overlay = 7 - else: overlay = 6 - playcount = userdata['PlayCount'] - if playcount is None: - playcount = 0 - - rating = item.get('CommunityRating') - if not rating: rating = userdata['UserRating'] - - # Populate the extradata list and artwork - extradata = { - 'id': itemid, - 'rating': rating, - 'year': item.get('ProductionYear'), - 'genre': genre, - 'playcount': str(playcount), - 'title': title, - 'plot': API.getOverview(), - 'Overlay': str(overlay), - 'duration': runtime - } - if premieredate: - extradata["premieredate"] = premieredate - extradata["date"] = premieredate - li.setInfo('video', infoLabels=extradata) - if allart.get('Primary'): - li.setThumbnailImage(allart.get('Primary')) - else: li.setThumbnailImage('DefaultTVShows.png') - li.setArt({'icon': 'DefaultTVShows.png'}) - if not allart.get('Background'): #add image as fanart for use with skinhelper auto thumb/backgrund creation - li.setArt( {"fanart": allart.get('Primary') } ) - else: - pbutils.PlaybackUtils(item).setArtwork(li) - - mediastreams = API.getMediaStreams() - videostreamFound = False - if mediastreams: - for key, value in mediastreams.iteritems(): - if key == "video" and value: videostreamFound = True - if value: li.addStreamInfo(key, value[0]) - if not videostreamFound: - #just set empty streamdetails to prevent errors in the logs - li.addStreamInfo("video", {'duration': runtime}) - - return li - ##### BROWSE EMBY CHANNELS ##### def BrowseChannels(itemid, folderid=None): diff --git a/resources/lib/playback_starter.py b/resources/lib/playback_starter.py index 0b97724c..e22feba7 100644 --- a/resources/lib/playback_starter.py +++ b/resources/lib/playback_starter.py @@ -8,7 +8,8 @@ from PKC_listitem import PKC_ListItem from pickler import pickle_me, Playback_Successful from playbackutils import PlaybackUtils from utils import window -from PlexFunctions import GetPlexMetadata, PLEX_TYPE_PHOTO +from PlexFunctions import GetPlexMetadata, PLEX_TYPE_PHOTO, \ + KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE from PlexAPI import API from playqueue import lock @@ -54,8 +55,10 @@ class Playback_Starter(Thread): result.listitem = listitem else: # Video and Music + playqueue = self.playqueue.get_playqueue_from_type( + KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[api.getType()]) with lock: - result = PlaybackUtils(xml[0], self.mgr).play( + result = PlaybackUtils(xml, playqueue).play( plex_id, kodi_id, xml.attrib.get('librarySectionUUID')) diff --git a/resources/lib/playbackutils.py b/resources/lib/playbackutils.py index 5eba8272..d7195ad2 100644 --- a/resources/lib/playbackutils.py +++ b/resources/lib/playbackutils.py @@ -14,14 +14,14 @@ from utils import window, settings, tryEncode, tryDecode import downloadutils from PlexAPI import API -from PlexFunctions import GetPlexPlaylist, KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE, \ - KODITYPE_FROM_PLEXTYPE, PLEX_TYPE_MOVIE +from PlexFunctions import GetPlexPlaylist, KODITYPE_FROM_PLEXTYPE, \ + PLEX_TYPE_CLIP, PLEX_TYPE_MOVIE from PKC_listitem import PKC_ListItem as ListItem from playlist_func import add_item_to_kodi_playlist, \ get_playlist_details_from_xml, add_listitem_to_Kodi_playlist, \ add_listitem_to_playlist, remove_from_Kodi_playlist -from playqueue import lock, Playqueue from pickler import Playback_Successful +from plexdb_functions import Get_Plex_DB ############################################################################### @@ -34,17 +34,9 @@ addonName = "PlexKodiConnect" class PlaybackUtils(): - def __init__(self, item, callback=None, playlist_type=None): - self.item = item - self.api = API(item) - playlist_type = playlist_type if playlist_type else \ - KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[self.api.getType()] - if callback: - self.mgr = callback - self.playqueue = self.mgr.playqueue.get_playqueue_from_type( - playlist_type) - else: - self.playqueue = Playqueue().get_playqueue_from_type(playlist_type) + def __init__(self, xml, playqueue): + self.xml = xml + self.playqueue = playqueue def play(self, plex_id, kodi_id=None, plex_lib_UUID=None): """ @@ -52,8 +44,8 @@ class PlaybackUtils(): to the PMS """ log.info("Playbackutils called") - item = self.item - api = self.api + item = self.xml[0] + api = API(item) playqueue = self.playqueue xml = None result = Playback_Successful() @@ -179,7 +171,12 @@ class PlaybackUtils(): # -- ADD TRAILERS ################ if trailers: - introsPlaylist = self.AddTrailers(xml) + for i, item in enumerate(xml): + if i == len(xml) - 1: + # Don't add the main movie itself + break + self.add_trailer(item) + introsPlaylist = True # -- ADD MAIN ITEM ONLY FOR HOMESCREEN ############## if homeScreen and not seektime and not sizePlaylist: @@ -223,40 +220,14 @@ class PlaybackUtils(): # -- CHECK FOR ADDITIONAL PARTS ################ if len(item[0]) > 1: - # Only add to the playlist after intros have played - for counter, part in enumerate(item[0]): - # Never add first part - if counter == 0: - continue - # Set listitem and properties for each additional parts - api.setPartNumber(counter) - additionalListItem = xbmcgui.ListItem() - additionalPlayurl = playutils.getPlayUrl( - partNumber=counter) - log.debug("Adding additional part: %s, url: %s" - % (counter, additionalPlayurl)) - api.CreateListItemFromPlexItem(additionalListItem) - api.set_playback_win_props(additionalPlayurl, - additionalListItem) - api.set_listitem_artwork(additionalListItem) - add_listitem_to_playlist( - playqueue, - self.currentPosition, - additionalListItem, - kodi_id=kodi_id, - kodi_type=kodi_type, - plex_id=plex_id, - file=additionalPlayurl) - self.currentPosition += 1 - api.setPartNumber(0) + self.add_part(item, api, kodi_id, kodi_type) if dummyPlaylist: # Added a dummy file to the playlist, # because the first item is going to fail automatically. log.info("Processed as a playlist. First item is skipped.") # Delete the item that's gonna fail! - with lock: - del playqueue.items[startPos] + del playqueue.items[startPos] # Don't attach listitem return result @@ -304,38 +275,89 @@ class PlaybackUtils(): result.listitem = listitem return result - def AddTrailers(self, xml): + def play_all(self): """ - Adds trailers to a movie, if applicable. Returns True if trailers were - added + Play all items contained in the xml passed in. Called by Plex Companion """ - # Failure when getting trailers, e.g. when no plex pass - if xml.attrib.get('size') == '1': - return False + log.info("Playbackutils play_all called") + window('plex_playbackProps', value="true") + self.currentPosition = 0 + for item in self.xml: + log.debug('item.attrib: %s' % item.attrib) + api = API(item) + if api.getType() == PLEX_TYPE_CLIP: + self.add_trailer(item) + continue + with Get_Plex_DB() as plex_db: + db_item = plex_db.getItem_byId(api.getRatingKey()) + try: + add_item_to_kodi_playlist(self.playqueue, + self.currentPosition, + kodi_id=db_item[0], + kodi_type=db_item[4]) + self.currentPosition += 1 + if len(item[0]) > 1: + self.add_part(item, + api, + db_item[0], + db_item[4]) + except TypeError: + # Item not in Kodi DB + self.add_trailer(item) + continue + + def add_trailer(self, item): # Playurl needs to point back so we can get metadata! path = "plugin://plugin.video.plexkodiconnect/movies/" params = { 'mode': "play", 'dbid': 'plextrailer' } - for counter, intro in enumerate(xml): - # Don't process the last item - it's the original movie - if counter == len(xml)-1: - break - introAPI = API(intro) - listitem = introAPI.CreateListItemFromPlexItem() - params['id'] = introAPI.getRatingKey() - params['filename'] = introAPI.getKey() - introPlayurl = path + '?' + urlencode(params) - introAPI.set_listitem_artwork(listitem) - # Overwrite the Plex url - listitem.setPath(introPlayurl) - log.info("Adding Intro: %s" % introPlayurl) - add_listitem_to_Kodi_playlist( + introAPI = API(item) + listitem = introAPI.CreateListItemFromPlexItem() + params['id'] = introAPI.getRatingKey() + params['filename'] = introAPI.getKey() + introPlayurl = path + '?' + urlencode(params) + introAPI.set_listitem_artwork(listitem) + # Overwrite the Plex url + listitem.setPath(introPlayurl) + log.info("Adding Plex trailer: %s" % introPlayurl) + add_listitem_to_Kodi_playlist( + self.playqueue, + self.currentPosition, + listitem, + introPlayurl, + xml_video_element=item) + self.currentPosition += 1 + + def add_part(self, item, api, kodi_id, kodi_type): + """ + Adds an additional part to the playlist + """ + # Only add to the playlist after intros have played + for counter, part in enumerate(item[0]): + # Never add first part + if counter == 0: + continue + # Set listitem and properties for each additional parts + api.setPartNumber(counter) + additionalListItem = xbmcgui.ListItem() + playutils = putils.PlayUtils(item) + additionalPlayurl = playutils.getPlayUrl( + partNumber=counter) + log.debug("Adding additional part: %s, url: %s" + % (counter, additionalPlayurl)) + api.CreateListItemFromPlexItem(additionalListItem) + api.set_playback_win_props(additionalPlayurl, + additionalListItem) + api.set_listitem_artwork(additionalListItem) + add_listitem_to_playlist( self.playqueue, self.currentPosition, - listitem, - introPlayurl, - intro) + additionalListItem, + kodi_id=kodi_id, + kodi_type=kodi_type, + plex_id=api.getRatingKey(), + file=additionalPlayurl) self.currentPosition += 1 - return True + api.setPartNumber(0) diff --git a/resources/lib/playqueue.py b/resources/lib/playqueue.py index 096c2c96..3b79023e 100644 --- a/resources/lib/playqueue.py +++ b/resources/lib/playqueue.py @@ -8,6 +8,7 @@ from xbmc import sleep, Player, PlayList, PLAYLIST_MUSIC, PLAYLIST_VIDEO from utils import window, ThreadMethods, ThreadMethodsAdditionalSuspend import playlist_func as PL from PlexFunctions import ConvertPlexToKodiTime +from playbackutils import PlaybackUtils ############################################################################### log = logging.getLogger("PLEX."+__name__) @@ -86,7 +87,12 @@ class Playqueue(Thread): if playqueue_id != playqueue.ID: log.debug('Need to fetch new playQueue from the PMS') xml = PL.get_PMS_playlist(playqueue, playqueue_id) - PL.update_playlist_from_PMS(playqueue, playqueue_id, xml=xml) + if xml is None: + log.error('Could not get playqueue ID %s' % playqueue_id) + return + playqueue.clear() + PL.get_playlist_details_from_xml(playqueue, xml) + PlaybackUtils(xml, playqueue).play_all() else: log.debug('Restarting existing playQueue') PL.refresh_playlist_from_PMS(playqueue) @@ -99,21 +105,17 @@ class Playqueue(Thread): if item.ID == playqueue.selectedItemID: break else: - startpos = None + startpos = 0 # Start playback. Player does not return in time - if startpos: - log.debug('Start position Plex Companion playback: %s' - % startpos) - thread = Thread(target=Player().play, - args=(playqueue.kodi_pl, - None, - False, - startpos)) - else: - log.debug('Start Plex Companion playback from beginning') - thread = Thread(target=Player().play, - args=(playqueue.kodi_pl,)) - log.debug('Playqueues are: %s' % self.playqueues) + log.debug('Playqueues after Plex Companion update are now: %s' + % self.playqueues) + log.debug('Start position Plex Companion playback: %s' + % startpos) + thread = Thread(target=Player().play, + args=(playqueue.kodi_pl, + None, + False, + startpos)) thread.setDaemon(True) thread.start()