From 1691fd5e8b330fde5342e36e81a41c27c929fe1b Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Mon, 24 Aug 2015 05:55:37 -0500 Subject: [PATCH] External subtitles Add external subtitles as tracks for direct play and direct stream. Important to note, when direct streaming, the tracks are defined as Unknown(external). There's no way to correct this. --- resources/lib/PlayUtils.py | 6 ----- resources/lib/PlaybackUtils.py | 42 ++++++++++++++++++++++++++++++++ resources/lib/Player.py | 42 +++++++++++++++++++++++++++++--- resources/lib/WebSocketClient.py | 25 ++++++++++++++++--- 4 files changed, 103 insertions(+), 12 deletions(-) diff --git a/resources/lib/PlayUtils.py b/resources/lib/PlayUtils.py index 3c291790..a5b97af1 100644 --- a/resources/lib/PlayUtils.py +++ b/resources/lib/PlayUtils.py @@ -166,12 +166,6 @@ class PlayUtils(): elif "Video" in type: playurl = "%s/mediabrowser/Videos/%s/stream?static=true" % (server, id) - # Verify audio and subtitles - mediaSources = result[u'MediaSources'] - if mediaSources[0].get('DefaultAudioStreamIndex') != None: - playurl = "%s&AudioStreamIndex=%s" % (playurl, mediaSources[0].get('DefaultAudioStreamIndex')) - if mediaSources[0].get('DefaultSubtitleStreamIndex') != None: - playurl = "%s&SubtitleStreamIndex=%s" % (playurl, mediaSources[0].get('DefaultSubtitleStreamIndex')) elif "Audio" in type: playurl = "%s/mediabrowser/Audio/%s/stream.mp3" % (server, id) diff --git a/resources/lib/PlaybackUtils.py b/resources/lib/PlaybackUtils.py index f61510e7..c6aa8782 100644 --- a/resources/lib/PlaybackUtils.py +++ b/resources/lib/PlaybackUtils.py @@ -91,18 +91,21 @@ class PlaybackUtils(): return self.AddToPlaylist(itemsToPlay) playurl = PlayUtils().getPlayUrl(server, id, result) + if playurl == False or WINDOW.getProperty('playurlFalse') == "true": WINDOW.clearProperty('playurlFalse') xbmc.log("Failed to retrieve the playback path/url.") return if WINDOW.getProperty("%splaymethod" % playurl) == "Transcode": + # Transcoding, we pull every track to set before playback starts playurlprefs = self.audioSubsPref(playurl, result.get("MediaSources")) if playurlprefs: playurl = playurlprefs else: # User cancelled dialog return + thumbPath = API().getArtwork(result, "Primary") #if the file is a virtual strm file, we need to override the path by reading it's contents @@ -114,6 +117,13 @@ class PlaybackUtils(): listItem = xbmcgui.ListItem(path=playurl, iconImage=thumbPath, thumbnailImage=thumbPath) + if WINDOW.getProperty("%splaymethod" % playurl) != "Transcode": + # Only for direct play and direct stream + # Append external subtitles to stream + subtitleList = self.externalSubs(id, playurl, server, result.get('MediaSources')) + listItem.setSubtitles(subtitleList) + #pass + # Can not play virtual items if (result.get("LocationType") == "Virtual"): xbmcgui.Dialog().ok(self.language(30128), self.language(30129)) @@ -164,6 +174,38 @@ class PlaybackUtils(): else: xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem) + def externalSubs(self, id, playurl, server, mediaSources): + + externalsubs = [] + mapping = {} + + mediaStream = mediaSources[0].get('MediaStreams') + kodiindex = 0 + for stream in mediaStream: + + index = stream['Index'] + # Since Emby returns all possible tracks together, have to pull only external subtitles. + # IsTextSubtitleStream if true, is available to download from emby. + if "Subtitle" in stream['Type'] and stream['IsExternal'] and stream['IsTextSubtitleStream']: + + playmethod = utils.window("%splaymethod" % playurl) + + if "DirectPlay" in playmethod: + # Direct play, get direct path + url = PlayUtils().directPlay(stream) + elif "DirectStream" in playmethod: # Direct stream + url = "%s/Videos/%s/%s/Subtitles/%s/Stream.srt" % (server, id, id, index) + + # map external subtitles for mapping + mapping[kodiindex] = index + externalsubs.append(url) + kodiindex += 1 + + mapping = json.dumps(mapping) + utils.window('%sIndexMapping' % playurl, mapping) + + return externalsubs + def audioSubsPref(self, url, mediaSources): WINDOW = xbmcgui.Window(10000) diff --git a/resources/lib/Player.py b/resources/lib/Player.py index 1de341cf..9997f7d7 100644 --- a/resources/lib/Player.py +++ b/resources/lib/Player.py @@ -211,8 +211,24 @@ class Player( xbmc.Player ): # Convert back into an Emby index audioTracks = len(xbmc.Player().getAvailableAudioStreams()) indexAudio = indexAudio + 1 + if subsEnabled and len(xbmc.Player().getAvailableSubtitleStreams()) > 0: - indexSubs = indexSubs + audioTracks + 1 + WINDOW = xbmcgui.Window(10000) + mapping = WINDOW.getProperty("%sIndexMapping" % currentFile) + externalIndex = json.loads(mapping) + if externalIndex: + # If there's external subtitles added via PlaybackUtils + if externalIndex.get(str(indexSubs)): + # If the current subtitle is in the mapping + indexSubs = externalIndex[str(indexSubs)] + else: + # Internal subtitle currently selected + external = len(externalIndex) + indexSubs = indexSubs - external + audioTracks + 1 + else: + # No external subtitles added via PlayUtils + audioTracks = len(xbmc.Player().getAvailableAudioStreams()) + indexSubs = indexSubs + audioTracks + 1 else: indexSubs = "" @@ -292,6 +308,9 @@ class Player( xbmc.Player ): refresh_id = WINDOW.getProperty(currentFile + "refresh_id") playMethod = WINDOW.getProperty(currentFile + "playmethod") itemType = WINDOW.getProperty(currentFile + "type") + mapping = WINDOW.getProperty("%sIndexMapping" % currentFile) + + self.logMsg("Mapping for index: %s" % mapping) # Get playback volume volume_query = '{"jsonrpc": "2.0", "method": "Application.GetProperties", "params": {"properties": ["volume","muted"]}, "id": 1}' @@ -304,6 +323,7 @@ class Player( xbmc.Player ): url = "{server}/mediabrowser/Sessions/Playing" postdata = { + 'QueueableMediaTypes': "Video", 'CanSeek': True, 'ItemId': item_id, @@ -325,6 +345,7 @@ class Player( xbmc.Player ): track_query = '{"jsonrpc": "2.0", "method": "Player.GetProperties", "params": {"playerid": 1,"properties": ["currentsubtitle","currentaudiostream","subtitleenabled"]} , "id": 1}' result = xbmc.executeJSONRPC(track_query) result = json.loads(result) + # Audio tracks indexAudio = result.get('result', 0) if indexAudio: @@ -337,11 +358,25 @@ class Player( xbmc.Player ): subsEnabled = result.get('result', "") if subsEnabled: subsEnabled = subsEnabled.get('subtitleenabled', "") + # Postdata for the audio and subs tracks + audioTracks = len(xbmc.Player().getAvailableAudioStreams()) postdata['AudioStreamIndex'] = indexAudio + 1 + if subsEnabled and len(xbmc.Player().getAvailableSubtitleStreams()) > 0: - audioTracks = len(xbmc.Player().getAvailableAudioStreams()) - postdata['SubtitleStreamIndex'] = indexSubs + audioTracks + 1 + externalIndex = json.loads(mapping) + if externalIndex: + # If there's external subtitles added via PlaybackUtils + if externalIndex.get(str(indexSubs)): + # If the current subtitle is in the mapping + postdata['SubtitleStreamIndex'] = externalIndex[str(indexSubs)] + else: + # Internal subtitle currently selected + external = len(externalIndex) + postdata['SubtitleStreamIndex'] = indexSubs - external + audioTracks + 1 + else: + # No external subtitles added via PlayUtils + postdata['SubtitleStreamIndex'] = indexSubs + audioTracks + 1 else: postdata['SubtitleStreamIndex'] = "" @@ -349,6 +384,7 @@ class Player( xbmc.Player ): self.logMsg("Sending POST play started.", 1) self.doUtils.downloadUrl(url, postBody=postdata, type="POST") + # save data map for updates and position calls data = { 'runtime': runtime, diff --git a/resources/lib/WebSocketClient.py b/resources/lib/WebSocketClient.py index 5f15f924..39cfd6b2 100644 --- a/resources/lib/WebSocketClient.py +++ b/resources/lib/WebSocketClient.py @@ -165,9 +165,28 @@ class WebSocketThread(threading.Thread): xbmc.executebuiltin('SetVolume(%s[,showvolumebar])' % volume) elif command == "SetSubtitleStreamIndex": # Emby merges audio and subtitle index together - audioTracks = len(xbmc.Player().getAvailableAudioStreams()) - index = int(arguments['Index']) - audioTracks - xbmc.Player().setSubtitleStream(index - 1) + xbmcplayer = xbmc.Player() + currentFile = xbmcplayer.getPlayingFile() + embyIndex = int(arguments['Index']) + + mapping = WINDOW.getProperty("%sIndexMapping" % currentFile) + externalIndex = json.loads(mapping) + + if externalIndex: + # If there's external subtitles added via PlaybackUtils + for index in externalIndex: + if externalIndex[index] == embyIndex: + xbmcplayer.setSubtitleStream(int(index)) + else: + # User selected internal subtitles + external = len(externalIndex) + audioTracks = len(xbmcplayer.getAvailableAudioStreams()) + xbmcplayer.setSubtitleStream(external + embyIndex - audioTracks - 1) + else: + # Emby merges audio and subtitle index together + audioTracks = len(xbmcplayer.getAvailableAudioStreams()) + xbmcplayer.setSubtitleStream(index - audioTracks - 1) + elif command == "SetAudioStreamIndex": index = int(arguments['Index']) xbmc.Player().setAudioStream(index - 1)