diff --git a/resources/lib/kodimonitor.py b/resources/lib/kodimonitor.py index 3bf5f058..1c034989 100644 --- a/resources/lib/kodimonitor.py +++ b/resources/lib/kodimonitor.py @@ -12,7 +12,7 @@ import xbmcgui import downloadutils import embydb_functions as embydb import playbackutils as pbutils -from utils import window, settings +from utils import window, settings, create_id from ga_client import log_error from database import DatabaseConn @@ -125,7 +125,7 @@ class KodiMonitor(xbmc.Monitor): return self._on_play_(data) else: if ((settings('useDirectPaths') == "1" and not item_type == "song") or - (item_type == "song" and settings('enableMusic') == "true")): + (item_type == "song" and settings('enableMusic') == "true")): # Set up properties for player item_id = self._get_item_id(kodi_id, item_type) if item_id: @@ -142,15 +142,13 @@ class KodiMonitor(xbmc.Monitor): count += 1 xbmc.sleep(200) else: - listitem = xbmcgui.ListItem() - playback = pbutils.PlaybackUtils(result) + window('emby_%s.play.json' % playurl, { - if item_type == "song" and settings('streamMusic') == "true": - window('emby_%s.playmethod' % playurl, value="DirectStream") - else: - window('emby_%s.playmethod' % playurl, value="DirectPlay") - # Set properties for player.py - playback.set_properties(playurl, listitem) + 'playmethod': "DirectStream" if item_type == "song" and settings('streamMusic') == "true" else "DirectPlay", + 'playsession_id': str(create_id()).replace("-", "") + }) + listitem = xbmcgui.ListItem() + pbutils.PlaybackUtils(result).set_properties(playurl, listitem) def _video_update(self, data): # Manually marking as watched/unwatched @@ -242,7 +240,7 @@ class SpecialMonitor(threading.Thread): elif isPlaying and not window('emby.external_check'): time = player.getTime() - if time > 1: + if time > 1: # Not external player. window('emby.external_check', value="true") self.external_count = 0 elif self.external_count == 15: diff --git a/resources/lib/playbackutils.py b/resources/lib/playbackutils.py index ca434dde..9b32ea2a 100644 --- a/resources/lib/playbackutils.py +++ b/resources/lib/playbackutils.py @@ -163,7 +163,7 @@ class PlaybackUtils(object): # Set listitem and properties for each additional parts pb = PlaybackUtils(part) pb.set_properties(url, listitem) - pb.setArtwork(listitem) + pb.set_artwork(listitem, part['Type']) self.stack.append([url, listitem]) @@ -217,16 +217,19 @@ class PlaybackUtils(object): item_id = self.item['Id'] item_type = self.item['Type'] - play_method = window('emby_%s.playmethod' % url) - window('emby_%s.playmethod' % url, clear=True) + info = window('emby_%s.play.json' % url) + window('emby_%s.play.json' % url, clear=True) + window('emby_%s.json' % url, { 'url': url, 'runtime': str(self.item.get('RunTimeTicks')), 'type': item_type, 'id': item_id, + 'mediasource_id': info.get('mediasource_id', item_id), 'refreshid': self.item.get('SeriesId') if item_type == "Episode" else item_id, - 'playmethod': play_method + 'playmethod': info['playmethod'], + 'playsession_id': info['playsession_id'] }) self.set_artwork(listitem, item_type) @@ -279,6 +282,7 @@ class PlaybackUtils(object): else: listitem.setArt({art: path}) + def play_all(self, item_ids, seektime=None, **kwargs): self.playlist.clear() diff --git a/resources/lib/player.py b/resources/lib/player.py index 0dca7b63..61c43769 100644 --- a/resources/lib/player.py +++ b/resources/lib/player.py @@ -11,6 +11,7 @@ import xbmcgui import clientinfo import downloadutils +import read_embyserver as embyserver import websocket_client as wsc from utils import window, settings, language as lang, JSONRPC from ga_client import GoogleAnalytics, log_error @@ -37,6 +38,7 @@ class Player(xbmc.Player): self.clientInfo = clientinfo.ClientInfo() self.doUtils = downloadutils.DownloadUtils().downloadUrl + self.emby = embyserver.Read_EmbyServer() self.ws = wsc.WebSocketClient() self.xbmcplayer = xbmc.Player() @@ -128,6 +130,9 @@ class Player(xbmc.Player): refresh_id = item.get('refreshid') play_method = item.get('playmethod') item_type = item.get('type') + playsession_id = item.get('playsession_id') + mediasource_id = item.get('mediasource_id') + #self.set_audio_subs(item.get('forcedaudio'), item.get('forcedsubs')) @@ -156,14 +161,15 @@ class Player(xbmc.Player): url = "{server}/emby/Sessions/Playing" postdata = { - 'QueueableMediaTypes': "Video", + 'QueueableMediaTypes': "Video,Audio", 'CanSeek': True, 'ItemId': item_id, - 'MediaSourceId': item_id, + 'MediaSourceId': mediasource_id or item_id, 'PlayMethod': play_method, 'VolumeLevel': volume, 'PositionTicks': int(seekTime * 10000000), - 'IsMuted': muted + 'IsMuted': muted, + 'PlaySessionId': playsession_id } # Get the current audio track and subtitles @@ -249,13 +255,15 @@ class Player(xbmc.Player): 'runtime': runtime, 'item_id': item_id, + 'mediasource_id': mediasource_id, 'refresh_id': refresh_id, 'currentfile': currentFile, 'AudioStreamIndex': postdata['AudioStreamIndex'], 'SubtitleStreamIndex': postdata['SubtitleStreamIndex'], 'playmethod': play_method, 'Type': item_type, - 'currentPosition': int(seekTime) + 'currentPosition': int(seekTime), + 'playsession_id': playsession_id } self.played_info[currentFile] = data @@ -282,6 +290,8 @@ class Player(xbmc.Player): playTime = data['currentPosition'] playMethod = data['playmethod'] paused = data.get('paused', False) + playsession_id = data.get('playsession_id') + mediasource_id = data.get('mediasource_id') # Get playback volume @@ -297,12 +307,13 @@ class Player(xbmc.Player): 'QueueableMediaTypes': "Video", 'CanSeek': True, 'ItemId': itemId, - 'MediaSourceId': itemId, + 'MediaSourceId': mediasource_id or itemId, 'PlayMethod': playMethod, 'PositionTicks': int(playTime * 10000000), 'IsPaused': paused, 'VolumeLevel': volume, - 'IsMuted': muted + 'IsMuted': muted, + 'PlaySessionId': playsession_id } if playMethod == "Transcode": @@ -525,24 +536,9 @@ class Player(xbmc.Player): def stopPlayback(self, data): - log.debug("stopPlayback called") - - itemId = data['item_id'] - currentPosition = data['currentPosition'] - positionTicks = int(currentPosition * 10000000) + log.debug("stopPlayback called.") - url = "{server}/emby/Sessions/Playing/Stopped" - postdata = { - - 'ItemId': itemId, - 'MediaSourceId': itemId, - 'PositionTicks': positionTicks - } - self.doUtils(url, postBody=postdata, action_type="POST") - - #If needed, close any livestreams - livestreamid = window("emby_%s.livestreamid" % self.currentFile) - if livestreamid: - url = "{server}/emby/LiveStreams/Close" - postdata = { 'LiveStreamId': livestreamid } - self.doUtils(url, postBody=postdata, action_type="POST") + position_ticks = int(data['currentPosition'] * 10000000) + position = data['runtime'] if position_ticks and window('emby.external') else position_ticks + + self.emby.stop_playback(data['item_id'], position, data['playsession_id'], data.get('mediasource_id')) diff --git a/resources/lib/playutils.py b/resources/lib/playutils.py index f8968f08..cab4124d 100644 --- a/resources/lib/playutils.py +++ b/resources/lib/playutils.py @@ -4,6 +4,7 @@ import collections import logging +import requests import os import urllib @@ -14,7 +15,7 @@ import xbmcvfs import clientinfo import downloadutils import read_embyserver as embyserver -from utils import window, settings, language as lang, urllib_path +from utils import window, settings, language as lang, urllib_path, create_id ################################################################################################# @@ -25,6 +26,7 @@ log = logging.getLogger("EMBY."+__name__) class PlayUtils(): + play_session_id = None method = "DirectPlay" force_transcode = False @@ -40,6 +42,7 @@ class PlayUtils(): self.emby = embyserver.Read_EmbyServer() self.server = window('emby_server%s' % window('emby_currUser')) + self.play_session_id = str(create_id()).replace("-", "") def get_play_url(self, force_transcode=False): @@ -50,20 +53,25 @@ class PlayUtils(): self.force_transcode = force_transcode info = self.get_playback_info() - play_url = False if info == False else None + url = False if info == False else None if info: - play_url = info['Path'].encode('utf-8') - window('emby_%s.playmethod' % play_url, value=self.method) + url = info['Path'].encode('utf-8') + window('emby_%s.play.json' % url, { + + 'playmethod': self.method, + 'playsession_id': self.play_session_id, + 'mediasource_id': info.get('Id') or self.item['Id'] + }) if self.method == "DirectPlay": # Log filename, used by other addons eg subtitles which require the file name - window('embyfilename', value=play_url) + window('embyfilename', value=url) log.info("playback info: %s", info) - log.info("play method: %s play url: %s", self.method, play_url) + log.info("play method: %s play url: %s", self.method, url) - return play_url + return url def get_playback_info(self): @@ -208,35 +216,35 @@ class PlayUtils(): transcode = False break - play_url = self.get_transcode_url(source) if transcode else self.get_direct_url(source) - - user_token = downloadutils.DownloadUtils().get_token() - play_url += "&api_key=" + user_token + url = self.get_transcode_url(source) if transcode else self.get_direct_url(source) + url += "&MediaSourceId=%s" % source['Id'] + url += "&PlaySessionId=%s" % self.play_session_id + url += "&api_key=%s" % downloadutils.DownloadUtils().get_token() - return play_url + return url def get_direct_url(self, source): self.method = "DirectStream" if self.item['Type'] == "Audio": - play_url = "%s/emby/Audio/%s/stream.%s?static=true" % (self.server, self.item['Id'], self.item['MediaSources'][0]['Container']) + url = "%s/emby/Audio/%s/stream.%s?static=true" % (self.server, self.item['Id'], self.item['MediaSources'][0]['Container']) else: - play_url = "%s/emby/Videos/%s/stream?static=true" % (self.server, self.item['Id']) + url = "%s/emby/Videos/%s/stream?static=true" % (self.server, self.item['Id']) # Append external subtitles if settings('enableExternalSubs') == "true": - self.set_external_subs(source, play_url) + self.set_external_subs(source, url) - return play_url + return url def get_transcode_url(self, source): self.method = "Transcode" item_id = self.item['Id'] - play_url = urllib_path("%s/emby/Videos/%s/master.m3u8" % (self.server, item_id), { - 'MediaSourceId': source['Id'], + url = urllib_path("%s/emby/Videos/%s/master.m3u8" % (self.server, item_id), { + 'VideoCodec': "h264", 'AudioCodec': "ac3", 'MaxAudioChannels': 6, @@ -246,14 +254,14 @@ class PlayUtils(): # Limit to 8 bit if user selected transcode Hi10P if settings('transcodeHi10P') == "true": - play_url += "&MaxVideoBitDepth=8" + url += "&MaxVideoBitDepth=8" # Adjust the video resolution - play_url += "&maxWidth=%s&maxHeight=%s" % (self.get_resolution()) + url += "&maxWidth=%s&maxHeight=%s" % (self.get_resolution()) # Select audio and subtitles - play_url += self.get_audio_subs(source) + url += self.get_audio_subs(source) - return play_url + return url def set_external_subs(self, source, play_url):