diff --git a/resources/lib/DownloadUtils.py b/resources/lib/DownloadUtils.py index 436a19d5..c76681bd 100644 --- a/resources/lib/DownloadUtils.py +++ b/resources/lib/DownloadUtils.py @@ -21,8 +21,7 @@ class DownloadUtils(): clientInfo = ClientInformation() addonName = clientInfo.getAddonName() - addonId = clientInfo.getAddonId() - addon = xbmcaddon.Addon(id=addonId) + addon = xbmcaddon.Addon() WINDOW = xbmcgui.Window(10000) # Requests session @@ -79,6 +78,7 @@ class DownloadUtils(): "GoHome,PageUp,NextLetter,GoToSearch," "GoToSettings,PageDown,PreviousLetter,TakeScreenshot," "VolumeUp,VolumeDown,ToggleMute,SendString,DisplayMessage," + "SetAudioStreamIndex,SetSubtitleStreamIndex," "Mute,Unmute,SetVolume," "Play,Playstate,PlayNext" @@ -183,7 +183,6 @@ class DownloadUtils(): # Replace for the real values and append api_key url = url.replace("{server}", self.server, 1) url = url.replace("{UserId}", self.userId, 1) - #url = "%s&api_key=%s" % (url, self.token) self.logMsg("URL: %s" % url, 2) # Prepare request @@ -293,7 +292,7 @@ class DownloadUtils(): if r.headers['X-Application-Error-Code'] == "ParentalControl": # Parental control - access restricted WINDOW.setProperty("Server_status", "restricted") - xbmcgui.Dialog().notification("Emby server", "Access restricted.", xbmcgui.NOTIFICATION_ERROR, time=5000) + xbmcgui.Dialog().notification("Emby server", "Access restricted.", xbmcgui.NOTIFICATION_ERROR, icon="special://home/addons/plugin.video.emby/icon.png", time=5000) return False if (status == "401") or (status == "Auth"): @@ -303,7 +302,7 @@ class DownloadUtils(): # Tell UserClient token has been revoked. WINDOW.setProperty("Server_status", "401") self.logMsg("HTTP Error: %s" % e, 0) - xbmcgui.Dialog().notification("Error connecting", "Unauthorized.", xbmcgui.NOTIFICATION_ERROR) + xbmcgui.Dialog().notification("Error connecting", "Unauthorized.", xbmcgui.NOTIFICATION_ERROR, icon="special://home/addons/plugin.video.emby/icon.png") return 401 elif (r.status_code == 301) or (r.status_code == 302): diff --git a/resources/lib/PlayUtils.py b/resources/lib/PlayUtils.py index 7d7e8f90..69bc92a7 100644 --- a/resources/lib/PlayUtils.py +++ b/resources/lib/PlayUtils.py @@ -210,11 +210,6 @@ class PlayUtils(): deviceId = self.clientInfo.getMachineId() playurl = "%s/mediabrowser/Videos/%s/master.m3u8?mediaSourceId=%s" % (server, id, id) playurl = "%s&VideoCodec=h264&AudioCodec=aac,ac3&deviceId=%s&VideoBitrate=%s" % (playurl, deviceId, self.getVideoBitRate()*1000) - - mediaSources = result[u'MediaSources'] - prefs = self.audioSubsPref(mediaSources) - - playurl = "%s%s" % (playurl, prefs) self.logMsg("Playurl: %s" % playurl) return playurl @@ -312,110 +307,4 @@ class PlayUtils(): return True else: self.logMsg("Path is detected as follow: %s. Try direct streaming." % path, 2) - return False - - def audioSubsPref(self, mediaSources): - - addon = xbmcaddon.Addon() - - defaultAudio = mediaSources[0][u'DefaultAudioStreamIndex'] - playurlprefs = "&AudioStreamIndex=%s" % defaultAudio - - codecs = [ - # Possible codecs - u'und', u'ac3', u'dts', u'5.1', u'aac', u'mp3', u'dca' - ] - - try: - mediaStream = mediaSources[0].get('MediaStreams') - audiotracks = {} - substracks = {} - defaultSubs = None - - for stream in mediaStream: - # Since Emby returns all possible tracks together, have to sort them. - if u'Audio' in stream[u'Type']: - if u'Language' in stream: - audiotracks[stream[u'Language']] = stream[u'Index'] - else: - audiotracks[stream[u'Codec']] = stream[u'Index'] - - if u'Subtitle' in stream[u'Type']: - if u'Language' in stream: - substracks[stream[u'Language']] = stream[u'Index'] - if stream[u'IsDefault'] == True: - defaultSubs = stream[u'Language'] - else: - substracks[stream[u'Codec']] = stream[u'Index'] - if stream[u'IsDefault']: - defaultSubs = stream[u'Codec'] - - self.logMsg("%s %s %s" % (defaultSubs, audiotracks, substracks), 1) - - if len(audiotracks) == 1 and len(substracks) == 0: - # There's only one audio track and no subtitles - playurlprefs = "&AudioStreamIndex=%s" % defaultAudio - return playurlprefs - - codec_intrack = False - for codec in codecs: - for track in audiotracks: - if codec in track: - codec_intrack = True - - if self.audioPref in audiotracks: - self.logMsg("Door 1", 2) - # Audio pref is available - playurlprefs = "&AudioStreamIndex=%s" % audiotracks[self.audioPref] - - if addon.getSetting('subsoverride') == "true": - # Subs are forced. - if self.subsPref in substracks: - self.logMsg("Door 1.1", 2) - playurlprefs = "%s&SubtitleStreamIndex=%s" % (playurlprefs, substracks[self.subsPref]) - else: - # Use default subs - if defaultSubs != None: - self.logMsg("Door 1.2", 2) - playurlprefs = "%s&SubtitleStreamIndex=%s" % (playurlprefs, substracks[defaultSubs]) - - elif (len(audiotracks) == 1) and not codec_intrack: - self.logMsg("Door 2", 2) - # 1. There's one audio track. - # 2. The audio is defined as a language. - # 3. Audio pref is not available, guaranteed. - playurlprefs = "&AudioStreamIndex=%s" % defaultAudio - - if self.subsPref in substracks: - self.logMsg("Door 2.1", 2) - # Subs pref is available. - playurlprefs = "%s&SubtitleStreamIndex=%s" % (playurlprefs, substracks[self.subsPref]) - else: - # Use default subs - if defaultSubs != None: - self.logMsg("Door 2.2", 2) - playurlprefs = "%s&SubtitleStreamIndex=%s" % (playurlprefs, substracks[defaultSubs]) - - elif len(audiotracks) == 1 and codec_intrack: - self.logMsg("Door 3", 2) - # 1. There one audio track. - # 2. The audio is undefined or a codec. - # 3. Audio track is mislabeled. - playurlprefs = "&AudioStreamIndex=%s" % defaultAudio - - if self.subsPref in substracks: - # If the subtitle is available, only display - # if the setting is enabled. - if addon.getSetting('subsoverride') == "true": - # Subs are forced. - self.logMsg("Door 3.1", 2) - playurlprefs = "%s&SubtitleStreamIndex=%s" % (playurlprefs, substracks[self.subsPref]) - else: - # Use default subs - if defaultSubs != None: - self.logMsg("Door 3.2", 2) - playurlprefs = "%s&SubtitleStreamIndex=%s" % (playurlprefs, substracks[defaultSubs]) - - except: pass - - return playurlprefs \ No newline at end of file + return False \ No newline at end of file diff --git a/resources/lib/PlaybackUtils.py b/resources/lib/PlaybackUtils.py index 7940f39f..b6a85329 100644 --- a/resources/lib/PlaybackUtils.py +++ b/resources/lib/PlaybackUtils.py @@ -97,6 +97,13 @@ class PlaybackUtils(): xbmc.log("Failed to retrieve the playback path/url.") return + if WINDOW.getProperty("%splaymethod" % playurl) == "Transcode": + 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 @@ -146,22 +153,6 @@ class PlaybackUtils(): WINDOW.setProperty(playurl+"runtimeticks", str(result.get("RunTimeTicks"))) WINDOW.setProperty(playurl+"type", result.get("Type")) WINDOW.setProperty(playurl+"item_id", id) - - mediaSources = result.get("MediaSources") - if(mediaSources != None): - mediaStream = mediaSources[0].get('MediaStreams') - defaultsubs = "" - for stream in mediaStream: - if u'Subtitle' in stream[u'Type'] and stream[u'IsDefault']: - if u'Language' in stream: - defaultsubs = stream[u'Language'] - else: - defaultsubs = stream[u'Codec'] - WINDOW.setProperty("%ssubs" % playurl, defaultsubs.encode('utf-8')) - if mediaSources[0].get('DefaultAudioStreamIndex') != None: - WINDOW.setProperty(playurl+"AudioStreamIndex", str(mediaSources[0].get('DefaultAudioStreamIndex'))) - if mediaSources[0].get('DefaultSubtitleStreamIndex') != None: - WINDOW.setProperty(playurl+"SubtitleStreamIndex", str(mediaSources[0].get('DefaultSubtitleStreamIndex'))) #launch the playback - only set the listitem props if we're not using the setresolvedurl approach if setup == "service": @@ -174,6 +165,76 @@ class PlaybackUtils(): else: xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem) + def audioSubsPref(self, url, mediaSources): + + WINDOW = xbmcgui.Window(10000) + # Present the list of audio to select from + audioStreamsList = {} + audioStreams = [] + selectAudioIndex = "" + subtitleStreamsList = {} + subtitleStreams = ['No subtitles'] + selectSubsIndex = "" + playurlprefs = "%s" % url + + mediaStream = mediaSources[0].get('MediaStreams') + for stream in mediaStream: + index = stream['Index'] + # Since Emby returns all possible tracks together, have to sort them. + if 'Audio' in stream['Type']: + try: + track = stream['Language'] + audioStreamsList[track] = index + audioStreams.append(track) + except: + track = stream['Codec'] + audioStreamsList[track] = index + audioStreams.append(track) + + elif 'Subtitle' in stream['Type']: + try: + track = stream['Language'] + subtitleStreamsList[track] = index + subtitleStreams.append(track) + except: + track = stream['Codec'] + subtitleStreamsList[track] = index + subtitleStreams.append(track) + + if len(audioStreams) > 1: + resp = xbmcgui.Dialog().select("Choose the audio stream", audioStreams) + if resp > -1: + # User selected audio + selected = audioStreams[resp] + selected_audioIndex = audioStreamsList[selected] + playurlprefs += "&AudioStreamIndex=%s" % selected_audioIndex + selectAudioIndex = str(selected_audioIndex) + else: return False + else: # There's only one audiotrack. + audioIndex = audioStreamsList[audioStreams[0]] + playurlprefs += "&AudioStreamIndex=%s" % audioIndex + selectAudioIndex = str(audioIndex) + + if len(subtitleStreams) > 1: + resp = xbmcgui.Dialog().select("Choose the subtitle stream", subtitleStreams) + if resp == 0: + # User selected no subtitles + pass + elif resp > -1: + # User selected subtitles + selected = subtitleStreams[resp] + selected_subsIndex = subtitleStreamsList[selected] + playurlprefs += "&SubtitleStreamIndex=%s" % selected_subsIndex + selectSubsIndex = str(selected_subsIndex) + else: return False + + # Reset the method with the new playurl + WINDOW.setProperty("%splaymethod" % playurlprefs, "Transcode") + WINDOW.setProperty("%sAudioStreamIndex" % playurlprefs, selectAudioIndex) + WINDOW.setProperty("%sSubtitleStreamIndex" % playurlprefs, selectSubsIndex) + + return playurlprefs + def setArt(self, list,name,path): if name=='thumb' or name=='fanart_image' or name=='small_poster' or name=='tiny_poster' or name == "medium_landscape" or name=='medium_poster' or name=='small_fanartimage' or name=='medium_fanartimage' or name=='fanart_noindicators': list.setProperty(name, path) diff --git a/resources/lib/Player.py b/resources/lib/Player.py index 4eab6ea2..81d95a84 100644 --- a/resources/lib/Player.py +++ b/resources/lib/Player.py @@ -68,6 +68,8 @@ class Player( xbmc.Player ): def stopAll(self): + WINDOW = xbmcgui.Window(10000) + if(len(self.played_information) == 0): return @@ -86,6 +88,7 @@ class Player( xbmc.Player ): refresh_id = data.get("refresh_id") currentFile = data.get("currentfile") type = data.get("Type") + playMethod = data.get('playmethod') # Prevent websocket feedback self.WINDOW.setProperty("played_itemId", item_id) @@ -116,12 +119,12 @@ class Player( xbmc.Player ): listItem = [item_id] LibrarySync().removefromDB(listItem, True) - # Stop transcoding - if self.WINDOW.getProperty("transcoding%s" % item_id) == "true": - deviceId = self.clientInfo.getMachineId() - url = "{server}/mediabrowser/Videos/ActiveEncodings?DeviceId=%s" % deviceId - self.doUtils.downloadUrl(url, type="DELETE") - self.WINDOW.clearProperty("transcoding%s" % item_id) + # Stop transcoding + if playMethod == "Transcode": + self.logMsg("Transcoding for %s terminated." % item_id) + deviceId = self.clientInfo.getMachineId() + url = "{server}/mediabrowser/Videos/ActiveEncodings?DeviceId=%s" % deviceId + self.doUtils.downloadUrl(url, type="DELETE") self.played_information.clear() @@ -190,11 +193,38 @@ class Player( xbmc.Player ): if playTime: postdata['PositionTicks'] = int(playTime * 10000000) - if audioindex: - postdata['AudioStreamIndex'] = audioindex + if playMethod != "Transcode": + # Get current audio and subtitles track + 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) + indexAudio = result['result']['currentaudiostream']['index'] + indexSubs = result['result']['currentsubtitle']['index'] + subsEnabled = result['result']['subtitleenabled'] - if subtitleindex: - postdata['SubtitleStreamIndex'] = subtitleindex + # Convert back into an Emby index + audioTracks = len(xbmc.Player().getAvailableAudioStreams()) + indexAudio = indexAudio + 1 + if subsEnabled: + indexSubs = indexSubs + audioTracks + 1 + else: + indexSubs = "" + + if audioindex == indexAudio: + postdata['AudioStreamIndex'] = audioindex + else: + postdata['AudioStreamIndex'] = indexAudio + data['AudioStreamIndex'] = indexAudio + + if subtitleindex == indexSubs: + postdata['SubtitleStreamIndex'] = subtitleindex + else: + postdata['SubtitleStreamIndex'] = indexSubs + data['SubtitleStreamIndex'] = indexSubs + + else: + data['AudioStreamIndex'] = audioindex + data['SubtitleStreamIndex'] = subtitleindex postdata = json.dumps(postdata) self.logMsg("Report: %s" % postdata, 2) @@ -227,7 +257,7 @@ class Player( xbmc.Player ): def onPlayBackStarted( self ): # Will be called when xbmc starts playing a file - WINDOW = self.WINDOW + WINDOW = xbmcgui.Window(10000) addon = self.addon xbmcplayer = self.xbmcplayer self.stopAll() @@ -255,8 +285,6 @@ class Player( xbmc.Player ): # only ever use the win props here, use the data map in all other places runtime = WINDOW.getProperty(currentFile + "runtimeticks") refresh_id = WINDOW.getProperty(currentFile + "refresh_id") - audioindex = WINDOW.getProperty(currentFile + "AudioStreamIndex") - subtitleindex = WINDOW.getProperty(currentFile + "SubtitleStreamIndex") playMethod = WINDOW.getProperty(currentFile + "playmethod") itemType = WINDOW.getProperty(currentFile + "type") @@ -281,11 +309,27 @@ class Player( xbmc.Player ): 'IsMuted': muted } - if audioindex: + # Get the current audio track and subtitles + if playMethod == "Transcode": + audioindex = WINDOW.getProperty(currentFile + "AudioStreamIndex") + subtitleindex = WINDOW.getProperty(currentFile + "SubtitleStreamIndex") postdata['AudioStreamIndex'] = audioindex - - if subtitleindex: postdata['SubtitleStreamIndex'] = subtitleindex + + else: + 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) + indexAudio = result['result']['currentaudiostream']['index'] + indexSubs = result['result']['currentsubtitle']['index'] + subsEnabled = result['result']['subtitleenabled'] + + postdata['AudioStreamIndex'] = indexAudio + 1 + if subsEnabled: + audioTracks = len(xbmc.Player().getAvailableAudioStreams()) + postdata['SubtitleStreamIndex'] = indexSubs + audioTracks + 1 + else: + postdata['SubtitleStreamIndex'] = "" # Post playback to server self.logMsg("Sending POST play started.", 1) @@ -297,8 +341,8 @@ class Player( xbmc.Player ): 'item_id': item_id, 'refresh_id': refresh_id, 'currentfile': currentFile, - 'AudioStreamIndex': audioindex, - 'SubtitleStreamIndex': subtitleindex, + 'AudioStreamIndex': postdata['AudioStreamIndex'], + 'SubtitleStreamIndex': postdata['SubtitleStreamIndex'], 'playmethod': playMethod, 'Type': itemType, 'currentPosition': int(seekTime) @@ -349,4 +393,4 @@ class Player( xbmc.Player ): def onPlayBackStopped( self ): # Will be called when user stops xbmc playing a file self.logMsg("onPlayBackStopped", 0) - self.stopAll() + self.stopAll() \ No newline at end of file diff --git a/resources/lib/WebSocketClient.py b/resources/lib/WebSocketClient.py index 97d3097e..938eadf4 100644 --- a/resources/lib/WebSocketClient.py +++ b/resources/lib/WebSocketClient.py @@ -96,7 +96,7 @@ class WebSocketThread(threading.Thread): xbmc.executebuiltin("Dialog.Close(all,true)") xbmc.executebuiltin("XBMC.Notification(Playlist: Added %s items to Playlist,)" % len(itemIds)) PlaybackUtils().PLAYAllItems(itemIds, startPositionTicks) - # Don't think this is being used. + elif "PlayNext" in playCommand: xbmc.executebuiltin("XBMC.Notification(Playlist: Added %s items to Playlist,)" % len(itemIds)) playlist = PlaybackUtils().AddToPlaylist(itemIds) @@ -155,7 +155,7 @@ class WebSocketThread(threading.Thread): command = data['Name'] arguments = data.get("Arguments") - if command in ('Mute', 'Unmute', 'SetVolume'): + if command in ('Mute', 'Unmute', 'SetVolume', 'SetSubtitleStreamIndex', 'SetAudioStreamIndex'): # These commands need to be reported back if command == "Mute": xbmc.executebuiltin('Mute') @@ -164,6 +164,14 @@ class WebSocketThread(threading.Thread): elif command == "SetVolume": volume = arguments['Volume'] 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) + elif command == "SetAudioStreamIndex": + index = int(arguments['Index']) + xbmc.Player().setAudioStream(index - 1) # Report playback WINDOW.setProperty('commandUpdate', "true") diff --git a/resources/settings.xml b/resources/settings.xml index 08628b03..ad857d3c 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -33,8 +33,6 @@ - -