Companion: fix audio stream and subtitle stream
This commit is contained in:
parent
0b54e24947
commit
8189eb6b4c
3 changed files with 64 additions and 6 deletions
|
@ -12,6 +12,7 @@ from utils import tryEncode, escape_html
|
||||||
from PlexAPI import API
|
from PlexAPI import API
|
||||||
from PlexFunctions import GetPlexMetadata
|
from PlexFunctions import GetPlexMetadata
|
||||||
import json_rpc as js
|
import json_rpc as js
|
||||||
|
import variables as v
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
@ -148,6 +149,23 @@ class Playlist_Item(object):
|
||||||
answ += '%s: %s, ' % (key, str(getattr(self, key)))
|
answ += '%s: %s, ' % (key, str(getattr(self, key)))
|
||||||
return answ[:-2] + ">"
|
return answ[:-2] + ">"
|
||||||
|
|
||||||
|
def plex_stream_index(self, kodi_stream_index, stream_type):
|
||||||
|
"""
|
||||||
|
Pass in the kodi_stream_index [int] in order to receive the Plex stream
|
||||||
|
index.
|
||||||
|
|
||||||
|
stream_type: 'video', 'audio', 'subtitle'
|
||||||
|
|
||||||
|
Returns None if unsuccessful
|
||||||
|
"""
|
||||||
|
stream_type = v.PLEX_STREAM_TYPE_FROM_STREAM_TYPE[stream_type]
|
||||||
|
count = 0
|
||||||
|
for stream in self.xml[0][self.part]:
|
||||||
|
if stream.attrib['streamType'] == stream_type:
|
||||||
|
if count == kodi_stream_index:
|
||||||
|
return stream.attrib['id']
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
|
||||||
def playlist_item_from_kodi(kodi_item):
|
def playlist_item_from_kodi(kodi_item):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -28,6 +28,12 @@ CONTROLLABLE = {
|
||||||
'stepBack,stepForward'
|
'stepBack,stepForward'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STREAM_DETAILS = {
|
||||||
|
'video': 'currentvideostream',
|
||||||
|
'audio': 'currentaudiostream',
|
||||||
|
'subtitle': 'currentsubtitle'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class SubscriptionMgr(object):
|
class SubscriptionMgr(object):
|
||||||
"""
|
"""
|
||||||
|
@ -73,7 +79,11 @@ class SubscriptionMgr(object):
|
||||||
return server
|
return server
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def _msg(self, players):
|
def msg(self, players):
|
||||||
|
"""
|
||||||
|
Returns a timeline xml as str
|
||||||
|
(xml containing video, audio, photo player state)
|
||||||
|
"""
|
||||||
LOG.debug('players: %s', players)
|
LOG.debug('players: %s', players)
|
||||||
msg = v.XML_HEADER
|
msg = v.XML_HEADER
|
||||||
msg += '<MediaContainer size="3" commandID="INSERTCOMMANDID"'
|
msg += '<MediaContainer size="3" commandID="INSERTCOMMANDID"'
|
||||||
|
@ -105,6 +115,17 @@ class SubscriptionMgr(object):
|
||||||
state.PLAYER_STATES[playerid]['plex_id']
|
state.PLAYER_STATES[playerid]['plex_id']
|
||||||
return key
|
return key
|
||||||
|
|
||||||
|
def _kodi_stream_index(self, playerid, stream_type):
|
||||||
|
"""
|
||||||
|
Returns the current Kodi stream index [int] for the player playerid
|
||||||
|
|
||||||
|
stream_type: 'video', 'audio', 'subtitle'
|
||||||
|
"""
|
||||||
|
playqueue = self.playqueue.playqueues[playerid]
|
||||||
|
info = state.PLAYER_STATES[playerid]
|
||||||
|
return playqueue.items[info['position']].plex_stream_index(
|
||||||
|
info[STREAM_DETAILS[stream_type]]['index'], stream_type)
|
||||||
|
|
||||||
def _timeline_xml(self, player, ptype):
|
def _timeline_xml(self, player, ptype):
|
||||||
if player is None:
|
if player is None:
|
||||||
return ' <Timeline state="stopped" controllable="%s" type="%s" ' \
|
return ' <Timeline state="stopped" controllable="%s" type="%s" ' \
|
||||||
|
@ -135,11 +156,11 @@ class SubscriptionMgr(object):
|
||||||
ret += ' ratingKey="%s"' % info['plex_id']
|
ret += ' ratingKey="%s"' % info['plex_id']
|
||||||
# PlayQueue stuff
|
# PlayQueue stuff
|
||||||
playqueue = self.playqueue.playqueues[playerid]
|
playqueue = self.playqueue.playqueues[playerid]
|
||||||
|
pos = info['position']
|
||||||
key = self._get_container_key(playerid)
|
key = self._get_container_key(playerid)
|
||||||
if key is not None and key.startswith('/playQueues'):
|
if key is not None and key.startswith('/playQueues'):
|
||||||
self.container_key = key
|
self.container_key = key
|
||||||
ret += ' containerKey="%s"' % self.container_key
|
ret += ' containerKey="%s"' % self.container_key
|
||||||
pos = info['position']
|
|
||||||
ret += ' playQueueItemID="%s"' % playqueue.items[pos].id or 'null'
|
ret += ' playQueueItemID="%s"' % playqueue.items[pos].id or 'null'
|
||||||
ret += ' playQueueID="%s"' % playqueue.id or 'null'
|
ret += ' playQueueID="%s"' % playqueue.id or 'null'
|
||||||
ret += ' playQueueVersion="%s"' % playqueue.version or 'null'
|
ret += ' playQueueVersion="%s"' % playqueue.version or 'null'
|
||||||
|
@ -157,9 +178,21 @@ class SubscriptionMgr(object):
|
||||||
elif playqueue.plex_transient_token:
|
elif playqueue.plex_transient_token:
|
||||||
ret += ' token="%s"' % playqueue.plex_transient_token
|
ret += ' token="%s"' % playqueue.plex_transient_token
|
||||||
# Might need an update in the future
|
# Might need an update in the future
|
||||||
if ptype == 'video':
|
if ptype != v.KODI_TYPE_PHOTO:
|
||||||
ret += ' subtitleStreamID="-1"'
|
strm_id = self._kodi_stream_index(playerid, 'audio')
|
||||||
ret += ' audioStreamID="-1"'
|
if strm_id is not None:
|
||||||
|
ret += ' audioStreamID="%s"' % strm_id
|
||||||
|
else:
|
||||||
|
LOG.error('We could not select a Plex audiostream')
|
||||||
|
if ptype == v.KODI_TYPE_VIDEO and info['subtitleenabled']:
|
||||||
|
try:
|
||||||
|
strm_id = self._kodi_stream_index(playerid, 'subtitle')
|
||||||
|
except KeyError:
|
||||||
|
# subtitleenabled can be True while currentsubtitle can be {}
|
||||||
|
strm_id = None
|
||||||
|
if strm_id is not None:
|
||||||
|
# If None, then the subtitle is only present on Kodi side
|
||||||
|
ret += ' subtitleStreamID="%s"' % strm_id
|
||||||
ret += '/>\n'
|
ret += '/>\n'
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@ -181,7 +214,7 @@ class SubscriptionMgr(object):
|
||||||
players = js.get_players()
|
players = js.get_players()
|
||||||
# fetch the message, subscribers or not, since the server
|
# fetch the message, subscribers or not, since the server
|
||||||
# will need the info anyway
|
# will need the info anyway
|
||||||
msg = self._msg(players)
|
msg = self.msg(players)
|
||||||
if self.subscribers:
|
if self.subscribers:
|
||||||
with RLock():
|
with RLock():
|
||||||
for subscriber in self.subscribers.values():
|
for subscriber in self.subscribers.values():
|
||||||
|
|
|
@ -405,3 +405,10 @@ PLEX_REPEAT_FROM_KODI_REPEAT = {
|
||||||
'one': '1',
|
'one': '1',
|
||||||
'all': '2' # does this work?!?
|
'all': '2' # does this work?!?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Stream in PMS xml contains a streamType to distinguish the kind of stream
|
||||||
|
PLEX_STREAM_TYPE_FROM_STREAM_TYPE = {
|
||||||
|
'video': '1',
|
||||||
|
'audio': '2',
|
||||||
|
'subtitle': '3'
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue