diff --git a/resources/lib/PlexAPI.py b/resources/lib/PlexAPI.py index 7a45ccce..5eda10d1 100644 --- a/resources/lib/PlexAPI.py +++ b/resources/lib/PlexAPI.py @@ -2065,9 +2065,9 @@ class API(): action 'DirectPlay', 'DirectStream' or 'Transcode' quality: { - 'videoResolution': 'resolution', - 'videoQuality': 'quality', - 'maxVideoBitrate': 'bitrate' + 'videoResolution': e.g. '1024x768', + 'videoQuality': e.g. '60', + 'maxVideoBitrate': e.g. '2000' (in kbits) } (one or several of these options) subtitle {'selected', 'dontBurnIn', 'size'} @@ -2081,47 +2081,26 @@ class API(): # Set Client capabilities clientArgs = { 'X-Plex-Client-Capabilities': - "protocols=shoutcast," - "http-live-streaming," - "http-streaming-video," - "http-streaming-video-720p," - "http-streaming-video-1080p," - "http-mp4-streaming," - "http-mp4-video," - "http-mp4-video-720p," - "http-mp4-video-1080p;" - "videoDecoders=" - "h264{profile:high&resolution:1080&level:51}," - "h265{profile:high&resolution:1080&level:51}," - "mpeg1video," - "mpeg2video," - "mpeg4," - "msmpeg4," - "mjpeg," - "wmv2," - "wmv3," - "vc1," - "cinepak," - "h263;" - "audioDecoders=" - "mp3," - "aac," - "ac3{bitrate:800000&channels:8}," - "dts{bitrate:800000&channels:8}," - "truehd," - "eac3," - "dca," - "mp2," - "pcm," - "wmapro," - "wmav2," - "wmavoice," - "wmalossless;" + 'protocols=' + 'shoutcast,' + 'http-video;' + 'videoDecoders=' + 'h264{profile:high&resolution:1080&level:51};' + 'audioDecoders=' + 'mp3,aac,dts{bitrate:800000&channels:8},' + 'ac3{bitrate:800000&channels:8}', + 'X-Plex-Client-Profile-Extra': + 'add-transcode-target-audio-codec' + '(type=videoProfile&' + 'context=streaming&' + 'protocol=*&' + 'audioCodec=dca,ac3)' } - path = self.item[0][self.part].attrib['key'] xargs = PlexAPI().getXArgsDeviceInfo() + # For DirectPlay, path/key of PART is needed if action == "DirectPlay": + path = self.item[0][self.part].attrib['key'] url = self.server + path if '?' in url: url += '&' + urlencode(xargs) @@ -2130,13 +2109,27 @@ class API(): return url # For Direct Streaming or Transcoding + # Path/key to VIDEO item of xml PMS response is needed, not part + path = self.item.attrib['key'] + # transcodePath = self.server + \ + # '/video/:/transcode/universal/start.m3u8?' transcodePath = self.server + \ - '/video/:/transcode/universal/start.m3u8?' + '/video/:/transcode/universal/start.mkv?' + # args = { + # 'path': path, + # 'mediaIndex': 0, # Probably refering to XML reply sheme + # 'partIndex': self.part, + # 'protocol': 'hls', # seen in the wild: 'dash', 'http', 'hls' + # 'offset': 0, # Resume point + # 'fastSeek': 1 + # } args = { + 'copyts': 1, 'path': path, 'mediaIndex': 0, # Probably refering to XML reply sheme 'partIndex': self.part, - 'protocol': 'hls', # seen in the wild: 'dash', 'http', 'hls' + 'protocol': 'http', # seen in the wild: 'dash', 'http', 'hls' + 'session': self.clientId, 'offset': 0, # Resume point 'fastSeek': 1 } diff --git a/resources/lib/itemtypes.py b/resources/lib/itemtypes.py index 8303f0ca..dd7cb3db 100644 --- a/resources/lib/itemtypes.py +++ b/resources/lib/itemtypes.py @@ -232,7 +232,6 @@ class Items(object): Updates the Kodi watched state of the item from PMS. Also retrieves Plex resume points for movies in progress. """ - self.logMsg("Entering updateUserdata", 1) for mediaitem in xml: API = PlexAPI.API(mediaitem) itemid = API.getRatingKey() @@ -300,8 +299,7 @@ class Movies(Items): movieid = emby_dbitem[0] fileid = emby_dbitem[1] pathid = emby_dbitem[2] - self.logMsg("movieid: %s fileid: %s pathid: %s" % (movieid, fileid, pathid), 1) - + except TypeError: update_item = False self.logMsg("movieid: %s not found." % itemid, 2) @@ -911,10 +909,8 @@ class TVShows(Items): try: showid = emby_dbitem[0] pathid = emby_dbitem[2] - self.logMsg("showid: %s pathid: %s" % (showid, pathid), 1) except TypeError: update_item = False - self.logMsg("showid: %s not found." % itemid, 2) self.logMsg("View tag found: %s" % viewtag, 2) diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index 0c3acf73..06538ac2 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -189,9 +189,8 @@ class ThreadedShowSyncInfo(threading.Thread): try: dialog.update( percentage, - message="Downloaded: %s, Processed: %s: %s" - % (getMetadataProgress, processMetadataProgress, - viewName)) + message="Downloaded: %s, Processed: %s" + % (getMetadataProgress, processMetadataProgress)) except: # Wierd formating of the string viewName?!? pass diff --git a/resources/lib/playbackutils.py b/resources/lib/playbackutils.py index 7ee55927..343e3647 100644 --- a/resources/lib/playbackutils.py +++ b/resources/lib/playbackutils.py @@ -102,11 +102,10 @@ class PlaybackUtils(): # Get playurls per part and process them listitems = [] - for playurl in playutils.getPlayUrl(): + for counter, playurl in enumerate(playutils.getPlayUrl()): # Add item via Kodi db, if found. Preserves metadata emby_dbitem = emby_db.getItem_byId(self.API.getRatingKey()) if emby_dbitem: - self.logMsg('emby_dbitem found', 1) kodi_id = emby_dbitem[0] media_type = emby_dbitem[4] pl.insertintoPlaylist( @@ -121,32 +120,33 @@ class PlaybackUtils(): self.logMsg('emby_dbitem not found. Plex ratingKey was %s' % self.API.getRatingKey(), 1) listitem = xbmcgui.ListItem() - # Set artwork - self.setProperties(playurl, listitem) - # Set metadata + self.setArtwork(listitem) self.setListItem(listitem) self.playlist.add( playurl, listitem, index=self.currentPosition) + playmethod = utils.window('emby_%s.playmethod' % playurl) + # For transcoding only, ask for audio/subs pref - if utils.window('emby_%s.playmethod' % playurl) == "Transcode": - playurl = playutils.audioSubsPref(playurl, listitem) + if playmethod == "Transcode": + utils.window('emby_%s.playmethod' % playurl, clear=True) + playurl = playutils.audioSubsPref( + playurl, listitem, part=counter) utils.window('emby_%s.playmethod' % playurl, value="Transcode") + self.setProperties(playurl, listitem) # Update the playurl to the PMS xml response (hence no loop) listitem.setPath(playurl) + # Append external subtitles to stream + # Only for direct play and direct stream + if playmethod != "Transcode": + # Direct play automatically appends external + listitem.setSubtitles(self.API.externalSubs(playurl)) + listitems.append(listitem) self.currentPosition += 1 - # We need to keep track of playQueueItemIDs for Plex Companion - playQueueItemID = self.API.GetPlayQueueItemID() - utils.window( - 'plex_%s.playQueueItemID' % playurl, playQueueItemID) - utils.window( - 'plex_%s.playlistPosition' - % playurl, str(self.currentPosition)) - return listitems def setProperties(self, playurl, listitem): @@ -160,23 +160,20 @@ class PlaybackUtils(): utils.window('%s.type' % embyitem, value=itemtype) utils.window('%s.itemid' % embyitem, value=itemid) + # We need to keep track of playQueueItemIDs for Plex Companion + playQueueItemID = self.API.GetPlayQueueItemID() + utils.window( + 'plex_%s.playQueueItemID' % playurl, playQueueItemID) + utils.window( + 'plex_%s.playlistPosition' + % playurl, str(self.currentPosition)) + if itemtype == "episode": utils.window('%s.refreshid' % embyitem, value=self.API.getParentRatingKey()) else: utils.window('%s.refreshid' % embyitem, value=itemid) - # Append external subtitles to stream - playmethod = utils.window('%s.playmethod' % embyitem) - # Only for direct play and direct stream - # subtitles = self.externalSubs(playurl) - subtitles = self.API.externalSubs(playurl) - if playmethod != "Transcode": - # Direct play automatically appends external - listitem.setSubtitles(subtitles) - - self.setArtwork(listitem) - def externalSubs(self, playurl): externalsubs = [] @@ -290,8 +287,7 @@ class PlaybackUtils(): 'dateadded': API.getDateCreated(), 'lastplayed': userdata['LastPlayedDate'], 'mpaa': API.getMpaa(), - 'aired': API.getPremiereDate(), - 'votes': None + 'aired': API.getPremiereDate() } if "Episode" in mediaType: diff --git a/resources/lib/playutils.py b/resources/lib/playutils.py index 5a2af78d..ca10d6ea 100644 --- a/resources/lib/playutils.py +++ b/resources/lib/playutils.py @@ -276,7 +276,7 @@ class PlayUtils(): # max bit rate supported by server (max signed 32bit integer) return bitrate.get(videoQuality, 2147483) - def audioSubsPref(self, url, listitem, child=0): + def audioSubsPref(self, url, listitem, part=None): # For transcoding only # Present the list of audio to select from audioStreamsList = {} @@ -289,42 +289,46 @@ class PlayUtils(): selectSubsIndex = "" playurlprefs = "%s" % url + # Set part where we're at + self.API.setPartNumber(part) item = self.item try: - mediasources = item['MediaSources'][0] - mediastreams = mediasources['MediaStreams'] + mediasources = item[0] + mediastreams = mediasources[part] except (TypeError, KeyError, IndexError): return for stream in mediastreams: # Since Emby returns all possible tracks together, have to sort them. - index = stream['Index'] - type = stream['Type'] + index = stream['index'] + type = stream['streamType'] - if 'Audio' in type: - codec = stream['Codec'] - channelLayout = stream.get('ChannelLayout', "") + # Audio + if type == "2": + codec = stream['codec'] + channelLayout = stream.get('audioChannelLayout', "") try: - track = "%s - %s - %s %s" % (index, stream['Language'], codec, channelLayout) + track = "%s - %s - %s %s" % (index, stream['language'], codec, channelLayout) except: track = "%s - %s %s" % (index, codec, channelLayout) - audioStreamsChannelsList[index] = stream['Channels'] + audioStreamsChannelsList[index] = stream['channels'] audioStreamsList[track] = index audioStreams.append(track) - elif 'Subtitle' in type: + # Subtitles + elif type == "3": '''if stream['IsExternal']: continue''' try: - track = "%s - %s" % (index, stream['Language']) + track = "%s - %s" % (index, stream['language']) except: - track = "%s - %s" % (index, stream['Codec']) + track = "%s - %s" % (index, stream['codec']) - default = stream['IsDefault'] - forced = stream['IsForced'] - downloadable = stream['IsTextSubtitleStream'] + default = stream.get('default', None) + forced = stream.get('forced', None) + downloadable = True if stream.get('format', None) else False if default: track = "%s - Default" % track