From 1798e6e01d50e4641c0bad606e9cbf9f74bc3e0f Mon Sep 17 00:00:00 2001
From: angelblue05 <tamara.angel05@gmail.com>
Date: Sun, 14 Jan 2018 20:17:57 -0600
Subject: [PATCH] Fix source selection for direct stream

And missing imports. Fix set_artwork.
---
 resources/lib/kodimonitor.py   | 20 ++++++-------
 resources/lib/playbackutils.py | 12 +++++---
 resources/lib/player.py        | 48 ++++++++++++++-----------------
 resources/lib/playutils.py     | 52 ++++++++++++++++++++--------------
 4 files changed, 69 insertions(+), 63 deletions(-)

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):