Merge branch 'beta-version' into code-opt

This commit is contained in:
croneter 2019-08-10 13:27:11 +02:00
commit f1aa42b957
5 changed files with 76 additions and 54 deletions

View file

@ -234,14 +234,9 @@ def _playback_init(plex_id, plex_type, playqueue, pos):
playqueue.clear() playqueue.clear()
if plex_type != v.PLEX_TYPE_CLIP: if plex_type != v.PLEX_TYPE_CLIP:
# Post to the PMS to create a playqueue - in any case due to Companion # Post to the PMS to create a playqueue - in any case due to Companion
section_uuid = xml.attrib.get('librarySectionUUID') xml = PF.init_plex_playqueue(plex_id, plex_type, trailers=trailers)
xml = PF.init_plex_playqueue(plex_id,
section_uuid,
mediatype=plex_type,
trailers=trailers)
if xml is None: if xml is None:
LOG.error('Could not get a playqueue xml for plex id %s, UUID %s', LOG.error('Could not get a playqueue xml for plex id %s', plex_id)
plex_id, section_uuid)
# "Play error" # "Play error"
utils.dialog('notification', utils.dialog('notification',
utils.lang(29999), utils.lang(29999),

View file

@ -129,6 +129,21 @@ class Playqueue_Object(object):
self.kodi_playlist_playback = False self.kodi_playlist_playback = False
LOG.debug('Playlist cleared: %s', self) LOG.debug('Playlist cleared: %s', self)
def position_from_plex_id(self, plex_id):
"""
Returns the position [int] for the very first item with plex_id [int]
(Plex seems uncapable of adding the same element multiple times to a
playqueue or playlist)
Raises KeyError if not found
"""
for position, item in enumerate(self.items):
if item.plex_id == plex_id:
break
else:
raise KeyError('Did not find plex_id %s in %s', plex_id, self)
return position
class PlaylistItem(object): class PlaylistItem(object):
""" """
@ -137,11 +152,10 @@ class PlaylistItem(object):
id = None [int] Plex playlist/playqueue id, e.g. playQueueItemID id = None [int] Plex playlist/playqueue id, e.g. playQueueItemID
plex_id = None [int] Plex unique item id, "ratingKey" plex_id = None [int] Plex unique item id, "ratingKey"
plex_type = None [str] Plex type, e.g. 'movie', 'clip' plex_type = None [str] Plex type, e.g. 'movie', 'clip'
plex_uuid = None [str] Plex librarySectionUUID
kodi_id = None [int] Kodi unique kodi id (unique only within type!) kodi_id = None [int] Kodi unique kodi id (unique only within type!)
kodi_type = None [str] Kodi type: 'movie' kodi_type = None [str] Kodi type: 'movie'
file = None [str] Path to the item's file. STRING!! file = None [str] Path to the item's file. STRING!!
uri = None [str] Weird Plex uri path involving plex_uuid. STRING! uri = None [str] PMS path to item; will be auto-set with plex_id
guid = None [str] Weird Plex guid guid = None [str] Weird Plex guid
xml = None [etree] XML from PMS, 1 lvl below <MediaContainer> xml = None [etree] XML from PMS, 1 lvl below <MediaContainer>
playmethod = None [str] either 'DirectPlay', 'DirectStream', 'Transcode' playmethod = None [str] either 'DirectPlay', 'DirectStream', 'Transcode'
@ -157,7 +171,7 @@ class PlaylistItem(object):
self.kodi_id = None self.kodi_id = None
self.kodi_type = None self.kodi_type = None
self.file = None self.file = None
self.uri = None self._uri = None
self.guid = None self.guid = None
self.xml = None self.xml = None
self.playmethod = None self.playmethod = None
@ -179,17 +193,21 @@ class PlaylistItem(object):
@plex_id.setter @plex_id.setter
def plex_id(self, value): def plex_id(self, value):
self._plex_id = value self._plex_id = value
self._uri = ('server://%s/com.plexapp.plugins.library/library/metadata/%s' %
(app.CONN.machine_identifier, value))
@property
def uri(self):
return self._uri
def __unicode__(self): def __unicode__(self):
return ("{{" return ("{{"
"'id': {self.id}, " "'id': {self.id}, "
"'plex_id': {self.plex_id}, " "'plex_id': {self.plex_id}, "
"'plex_type': '{self.plex_type}', " "'plex_type': '{self.plex_type}', "
"'plex_uuid': '{self.plex_uuid}', "
"'kodi_id': {self.kodi_id}, " "'kodi_id': {self.kodi_id}, "
"'kodi_type': '{self.kodi_type}', " "'kodi_type': '{self.kodi_type}', "
"'file': '{self.file}', " "'file': '{self.file}', "
"'uri': '{self.uri}', "
"'guid': '{self.guid}', " "'guid': '{self.guid}', "
"'playmethod': '{self.playmethod}', " "'playmethod': '{self.playmethod}', "
"'playcount': {self.playcount}, " "'playcount': {self.playcount}, "
@ -272,7 +290,6 @@ def playlist_item_from_kodi(kodi_item):
if db_item: if db_item:
item.plex_id = db_item['plex_id'] item.plex_id = db_item['plex_id']
item.plex_type = db_item['plex_type'] item.plex_type = db_item['plex_type']
item.plex_uuid = db_item['plex_id'] # we dont need the uuid yet :-)
item.file = kodi_item.get('file') item.file = kodi_item.get('file')
if item.plex_id is None and item.file is not None: if item.plex_id is None and item.file is not None:
try: try:
@ -282,13 +299,6 @@ def playlist_item_from_kodi(kodi_item):
query = dict(utils.parse_qsl(query)) query = dict(utils.parse_qsl(query))
item.plex_id = utils.cast(int, query.get('plex_id')) item.plex_id = utils.cast(int, query.get('plex_id'))
item.plex_type = query.get('itemType') item.plex_type = query.get('itemType')
if item.plex_id is None and item.file is not None:
item.uri = ('library://whatever/item/%s'
% utils.quote(item.file, safe=''))
else:
# TO BE VERIFIED - PLEX DOESN'T LIKE PLAYLIST ADDS IN THIS MANNER
item.uri = ('library://%s/item/library%%2Fmetadata%%2F%s' %
(item.plex_uuid, item.plex_id))
LOG.debug('Made playlist item from Kodi: %s', item) LOG.debug('Made playlist item from Kodi: %s', item)
return item return item
@ -352,9 +362,6 @@ def playlist_item_from_plex(plex_id):
item.kodi_type = db_item['kodi_type'] item.kodi_type = db_item['kodi_type']
else: else:
raise KeyError('Could not find plex_id %s in database' % plex_id) raise KeyError('Could not find plex_id %s in database' % plex_id)
item.plex_uuid = plex_id
item.uri = ('library://%s/item/library%%2Fmetadata%%2F%s' %
(item.plex_uuid, plex_id))
LOG.debug('Made playlist item from plex: %s', item) LOG.debug('Made playlist item from plex: %s', item)
return item return item
@ -432,6 +439,8 @@ def update_playlist_from_PMS(playlist, playlist_id=None, xml=None):
need to fetch a new playqueue need to fetch a new playqueue
If an xml is passed in, the playlist will be overwritten with its info If an xml is passed in, the playlist will be overwritten with its info
Raises PlaylistError if something went wront
""" """
if xml is None: if xml is None:
xml = get_PMS_playlist(playlist, playlist_id) xml = get_PMS_playlist(playlist, playlist_id)
@ -468,6 +477,8 @@ def init_plex_playqueue(playlist, plex_id=None, kodi_item=None):
xml = DU().downloadUrl(url="{server}/%ss" % playlist.kind, xml = DU().downloadUrl(url="{server}/%ss" % playlist.kind,
action_type="POST", action_type="POST",
parameters=params) parameters=params)
if xml in (None, 401):
raise PlaylistError('Did not receive a valid xml from the PMS')
get_playlist_details_from_xml(playlist, xml) get_playlist_details_from_xml(playlist, xml)
# Need to get the details for the playlist item # Need to get the details for the playlist item
item = playlist_item_from_xml(xml[0]) item = playlist_item_from_xml(xml[0])
@ -651,7 +662,7 @@ def get_PMS_playlist(playlist, playlist_id=None):
Fetches the PMS playlist/playqueue as an XML. Pass in playlist_id if we Fetches the PMS playlist/playqueue as an XML. Pass in playlist_id if we
need to fetch a new playlist need to fetch a new playlist
Returns None if something went wrong Raises PlaylistError if something went wrong
""" """
playlist_id = playlist_id if playlist_id else playlist.id playlist_id = playlist_id if playlist_id else playlist.id
if playlist.kind == 'playList': if playlist.kind == 'playList':
@ -661,7 +672,7 @@ def get_PMS_playlist(playlist, playlist_id=None):
try: try:
xml.attrib xml.attrib
except AttributeError: except AttributeError:
xml = None raise PlaylistError('Did not get a valid xml')
return xml return xml

View file

@ -49,13 +49,21 @@ def update_playqueue_from_PMS(playqueue,
if transient_token is None: if transient_token is None:
transient_token = playqueue.plex_transient_token transient_token = playqueue.plex_transient_token
with app.APP.lock_playqueues: with app.APP.lock_playqueues:
xml = PL.get_PMS_playlist(playqueue, playqueue_id)
try: try:
xml.attrib xml = PL.get_PMS_playlist(playqueue, playqueue_id)
except AttributeError: except PL.PlaylistError:
LOG.error('Could now download playqueue %s', playqueue_id) LOG.error('Could now download playqueue %s', playqueue_id)
return return
playqueue.clear() if playqueue.id == playqueue_id:
# This seems to be happening ONLY if a Plex Companion device
# reconnects and Kodi is already playing something - silly, really
# For all other cases, a new playqueue is generated by Plex
LOG.debug('Update for existing playqueue detected')
new = False
else:
new = True
playqueue.clear()
# Get new metadata for the playqueue first
try: try:
PL.get_playlist_details_from_xml(playqueue, xml) PL.get_playlist_details_from_xml(playqueue, xml)
except PL.PlaylistError: except PL.PlaylistError:
@ -63,10 +71,33 @@ def update_playqueue_from_PMS(playqueue,
return return
playqueue.repeat = 0 if not repeat else int(repeat) playqueue.repeat = 0 if not repeat else int(repeat)
playqueue.plex_transient_token = transient_token playqueue.plex_transient_token = transient_token
playback.play_xml(playqueue, if new:
xml, playback.play_xml(playqueue,
offset=offset, xml,
start_plex_id=start_plex_id) offset=offset,
start_plex_id=start_plex_id)
return
# Updates to playqueues could potentially become a bit more ugly...
if app.APP.is_playing:
try:
playerid = js.get_player_ids()[0]
except IndexError:
LOG.error('Unexpectately could not get Kodi player id')
return
if app.PLAYSTATE.player_states[playerid]['plex_id'] == start_plex_id:
# Nothing to do - let's not seek to avoid jumps in playback
return
pos = playqueue.position_from_plex_id(start_plex_id)
LOG.debug('Skipping to position %s for %s', pos, playqueue)
js.skipto(pos)
if offset:
js.seek_to(offset)
return
# Need to initiate playback again using our existing playqueue
app.APP.player.play(playqueue.kodi_pl,
None,
False,
playqueue.position_from_plex_id(start_plex_id))
class PlexCompanion(backgroundthread.KillableThread): class PlexCompanion(backgroundthread.KillableThread):
@ -165,7 +196,7 @@ class PlexCompanion(backgroundthread.KillableThread):
update_playqueue_from_PMS(playqueue, update_playqueue_from_PMS(playqueue,
playqueue_id=container_key, playqueue_id=container_key,
repeat=query.get('repeat'), repeat=query.get('repeat'),
offset=data.get('offset'), offset=utils.cast(int, data.get('offset')),
transient_token=data.get('token'), transient_token=data.get('token'),
start_plex_id=key) start_plex_id=key)

View file

@ -820,16 +820,15 @@ def get_plex_sections():
return xml return xml
def init_plex_playqueue(plex_id, librarySectionUUID, mediatype='movie', def init_plex_playqueue(plex_id, plex_type, trailers=False):
trailers=False):
""" """
Returns raw API metadata XML dump for a playlist with e.g. trailers. Returns raw API metadata XML dump for a playlist with e.g. trailers.
""" """
url = "{server}/playQueues" url = "{server}/playQueues"
args = { args = {
'type': mediatype, 'type': plex_type,
'uri': ('library://{0}/item/%2Flibrary%2Fmetadata%2F{1}'.format( 'uri': ('server://%s/com.plexapp.plugins.library/library/metadata/%s' %
librarySectionUUID, plex_id)), (app.CONN.machine_identifier, plex_id)),
'includeChapters': '1', 'includeChapters': '1',
'shuffle': '0', 'shuffle': '0',
'repeat': '0' 'repeat': '0'

View file

@ -362,7 +362,7 @@ KODI_PLAYLIST_TYPE_FROM_KODI_TYPE = {
REMAP_TYPE_FROM_PLEXTYPE = { REMAP_TYPE_FROM_PLEXTYPE = {
PLEX_TYPE_MOVIE: 'movie', PLEX_TYPE_MOVIE: 'movie',
PLEX_TYPE_CLIP: 'clip', PLEX_TYPE_CLIP: 'movie',
PLEX_TYPE_SHOW: 'tv', PLEX_TYPE_SHOW: 'tv',
PLEX_TYPE_SEASON: 'tv', PLEX_TYPE_SEASON: 'tv',
PLEX_TYPE_EPISODE: 'tv', PLEX_TYPE_EPISODE: 'tv',
@ -400,20 +400,6 @@ TRANSLATION_FROM_PLEXTYPE = {
PLEX_TYPE_PHOTO: 1, PLEX_TYPE_PHOTO: 1,
} }
REMAP_TYPE_FROM_PLEXTYPE = {
'movie': 'movie',
'show': 'tv',
'season': 'tv',
'episode': 'tv',
'artist': 'music',
'album': 'music',
'song': 'music',
'track': 'music',
'clip': 'clip',
'photo': 'photo'
}
PLEX_TYPE_FROM_WEBSOCKET = { PLEX_TYPE_FROM_WEBSOCKET = {
1: PLEX_TYPE_MOVIE, 1: PLEX_TYPE_MOVIE,
2: PLEX_TYPE_SHOW, 2: PLEX_TYPE_SHOW,