From 93ad4ae0cbfe128d2d380f8cb3f97f95df0d75d6 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Sun, 3 Jan 2016 19:17:59 +0100 Subject: [PATCH] Movie with multiple parts now working --- resources/lib/PlexAPI.py | 51 ++++++++++++++++++++++++++++------ resources/lib/playbackutils.py | 28 +++++++++---------- resources/lib/playutils.py | 14 ++++++++-- 3 files changed, 67 insertions(+), 26 deletions(-) diff --git a/resources/lib/PlexAPI.py b/resources/lib/PlexAPI.py index 36c0ee88..3045f616 100644 --- a/resources/lib/PlexAPI.py +++ b/resources/lib/PlexAPI.py @@ -1272,6 +1272,8 @@ class API(): self.item = item # which child in the XML response shall we look at? self.child = 0 + # which media part in the XML response shall we look at? + self.part = 0 self.clientinfo = clientinfo.ClientInfo() self.addonName = self.clientinfo.getAddonName() self.clientId = self.clientinfo.getDeviceId() @@ -1287,15 +1289,28 @@ class API(): """ Which child in the XML response shall we look at and work with? """ - self.child = number + self.child = int(number) self.logMsg("Set child number to %s" % number, 1) - def getChild(self): + def getChildNumber(self): """ Returns the child in the XML response that we're currently looking at """ return self.child + def setPartNumber(self, number=0): + """ + Sets the part number to work with (used to deal with Movie with several + parts). + """ + self.part = int(number) + + def getPartNumber(self): + """ + Returns the current media part number we're dealing with. + """ + return self.part + def convert_date(self, stamp): """ convert_date(stamp) converts a Unix time stamp (seconds passed since @@ -1630,9 +1645,10 @@ class API(): Output: resume, runtime as floats. 0.0 if not found """ - item = self.item time_factor = 1.0 / 1000.0 # millisecond -> seconds + item = self.item item = item[self.child].attrib + try: runtime = float(item['duration']) except KeyError: @@ -1970,29 +1986,36 @@ class API(): Input: action 'Transcode' OR any other string + quality: { 'videoResolution': 'resolution', 'videoQuality': 'quality', 'maxVideoBitrate': 'bitrate' } subtitle {'selected', 'dontBurnIn', 'size'} - audioboost Guess this takes an int as str - partIndex No idea + audioboost e.g. 100 + partIndex Index number of media part, starting with 0 options dict() of PlexConnect-options as received from aTV Output: final path to pull in PMS transcoder + + TODO: mediaIndex """ # path to item transcodePath = self.server + \ '/video/:/transcode/universal/start.m3u8?' ID = self.getKey() - path = self.server + '/library/metadata/' + ID + if partIndex is not None: + path = self.server + '/library/metadata/' + ID + else: + path = self.item[self.child][0][self.part].attrib['key'] args = { 'session': self.clientId, - 'protocol': 'hls', + 'protocol': 'hls', # also seen: 'dash' 'fastSeek': '1', 'path': path, + 'mediaIndex': 0, # Probably refering to XML reply sheme 'X-Plex-Client-Capabilities': "protocols=http-live-streaming," "http-streaming-video," "http-streaming-video-720p," @@ -2008,12 +2031,16 @@ class API(): "aac{bitrate:160000}," "ac3{channels:6}," "dts{channels:6}" - # 'partIndex': partIndex What do we do with this?!? + # 'offset': 0 # Resume point + # 'directPlay': 0 # 1 if Kodi can also handle the container } # All the settings + if partIndex is not None: + args['partIndex'] = partIndex if subtitle: args_update = { - 'subtitleSize': subtitle['size'], + 'subtitles': 'burn', + 'subtitleSize': subtitle['size'], # E.g. 100 'skipSubtitles': subtitle['dontBurnIn'] # '1': shut off PMS } args.update(args_update) @@ -2118,3 +2145,9 @@ class API(): if not xml: self.logMsg("Error retrieving metadata for %s" % url, 1) return xml + + def GetParts(self): + """ + Returns the parts of the specified video child in the XML response + """ + return self.item[self.child][0] \ No newline at end of file diff --git a/resources/lib/playbackutils.py b/resources/lib/playbackutils.py index 97e2fcf0..68c8ec6e 100644 --- a/resources/lib/playbackutils.py +++ b/resources/lib/playbackutils.py @@ -123,7 +123,7 @@ class PlaybackUtils(): getTrailers = False self.logMsg("Skip trailers.", 1) if getTrailers: - for i in range(0, playListSize): + for i in range(0, playListSize - 1): # The server randomly returns intros, process them # Set the child in XML Plex response to a trailer API.setChildNumber(i) @@ -154,28 +154,28 @@ class PlaybackUtils(): currentPosition += 1 ############### -- CHECK FOR ADDITIONAL PARTS ################ - - # Plex: TODO. Guess parts are sent back like trailers. - # if item.get('PartCount'): - if False: + parts = API.GetParts() + partcount = len(parts) + if partcount > 1: # Only add to the playlist after intros have played - partcount = item['PartCount'] - url = "{server}/emby/Videos/%s/AdditionalParts?format=json" % itemid - parts = doUtils.downloadUrl(url) - for part in parts['Items']: - + i = 0 + for part in parts: + API.setPartNumber(i) additionalListItem = xbmcgui.ListItem() - additionalPlayurl = putils.PlayUtils(part).getPlayUrl() - self.logMsg("Adding additional part: %s" % partcount, 1) + additionalPlayurl = playutils.getPlayUrl( + child=-1, + partIndex=i) + self.logMsg("Adding additional part: %s" % i, 1) # Set listitem and properties for each additional parts - pbutils = PlaybackUtils(part) + pbutils = PlaybackUtils(item) pbutils.setProperties(additionalPlayurl, additionalListItem) pbutils.setArtwork(additionalListItem) playlist.add(additionalPlayurl, additionalListItem, index=currentPosition) self.pl.verifyPlaylist() currentPosition += 1 + i = i + 1 if dummyPlaylist: # Added a dummy file to the playlist, @@ -194,7 +194,7 @@ class PlaybackUtils(): # For transcoding only, ask for audio/subs pref if utils.window('emby_%s.playmethod' % playurl) == "Transcode": - playurl = playutils.audioSubsPref(playurl, child=self.API.getChild()) + playurl = playutils.audioSubsPref(playurl, child=self.API.getChildNumber()) utils.window('emby_%s.playmethod' % playurl, value="Transcode") listitem.setPath(playurl) diff --git a/resources/lib/playutils.py b/resources/lib/playutils.py index 7b1d1d7b..bb0118e3 100644 --- a/resources/lib/playutils.py +++ b/resources/lib/playutils.py @@ -36,10 +36,13 @@ class PlayUtils(): utils.logMsg("%s %s" % (self.addonName, self.className), msg, lvl) - def getPlayUrl(self, child=0): + def getPlayUrl(self, child=0, partIndex=None): item = self.item + # NO, I am not very fond of this construct! self.API.setChildNumber(child) + if partIndex is not None: + self.API.setPartNumber(partIndex) playurl = None # if item['MediaSources'][0]['Protocol'] == "Http": @@ -59,7 +62,10 @@ class PlayUtils(): if self.isDirectStream(): self.logMsg("File is direct streaming.", 1) - playurl = self.API.getTranscodeVideoPath('direct') + playurl = self.API.getTranscodeVideoPath( + 'direct', + partIndex=partIndex + ) # Set playmethod property utils.window('emby_%s.playmethod' % playurl, value="DirectStream") @@ -70,7 +76,9 @@ class PlayUtils(): 'bitrate': self.getBitrate() } playurl = self.API.getTranscodeVideoPath( - 'Transcode', quality=quality + 'Transcode', + quality=quality, + partIndex=partIndex ) # Set playmethod property utils.window('emby_%s.playmethod' % playurl, value="Transcode")