From 30abe0f2fbf2d85cc2d85bef7ac38a9153944788 Mon Sep 17 00:00:00 2001 From: croneter Date: Sun, 8 Apr 2018 14:34:38 +0200 Subject: [PATCH] Fix some playqueue inconsistencies using Plex Companion - Also fix movie helper and TV show helper add-ons --- addon.xml | 4 ++-- resources/lib/PlexFunctions.py | 2 +- resources/lib/playback.py | 37 ++++++++++++++++++++-------------- resources/lib/player.py | 1 + resources/lib/state.py | 6 +++++- 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/addon.xml b/addon.xml index f51ee650..7377c817 100644 --- a/addon.xml +++ b/addon.xml @@ -3,8 +3,8 @@ - - + + video audio image diff --git a/resources/lib/PlexFunctions.py b/resources/lib/PlexFunctions.py index b54279f9..f0105c21 100644 --- a/resources/lib/PlexFunctions.py +++ b/resources/lib/PlexFunctions.py @@ -636,7 +636,7 @@ def init_plex_playqueue(itemid, librarySectionUUID, mediatype='movie', xml[0].tag except (IndexError, TypeError, AttributeError): LOG.error("Error retrieving metadata for %s", url) - return None + return return xml diff --git a/resources/lib/playback.py b/resources/lib/playback.py index 116e3b96..3dea359b 100644 --- a/resources/lib/playback.py +++ b/resources/lib/playback.py @@ -49,10 +49,11 @@ def playback_triage(plex_id=None, plex_type=None, path=None, resolve=True): the first pass - e.g. if you're calling this function from the original service.py Python instance """ - LOG.info('playback_triage called with plex_id %s, plex_type %s, path %s', - plex_id, plex_type, path) + LOG.info('playback_triage called with plex_id %s, plex_type %s, path %s, ' + 'resolve %s,', plex_id, plex_type, path, resolve) global RESOLVE - RESOLVE = resolve + # If started via Kodi context menu, we never resolve + RESOLVE = resolve if not state.CONTEXT_MENU_PLAY else False if not state.AUTHENTICATED: LOG.error('Not yet authenticated for PMS, abort starting playback') # "Unauthorized for PMS" @@ -64,7 +65,7 @@ def playback_triage(plex_id=None, plex_type=None, path=None, resolve=True): pos = js.get_position(playqueue.playlistid) # Can return -1 (as in "no playlist") pos = pos if pos != -1 else 0 - LOG.debug('playQueue position: %s for %s', pos, playqueue) + LOG.debug('playQueue position %s for %s', pos, playqueue) # Have we already initiated playback? try: item = playqueue.items[pos] @@ -98,7 +99,7 @@ def _playback_init(plex_id, plex_type, playqueue, pos): try: _init_existing_kodi_playlist(playqueue, pos) except PL.PlaylistError: - LOG.error('Aborting playback_init for longer Kodi playlist') + LOG.error('Playback_init for existing Kodi playlist failed') _ensure_resolve(abort=True) return # Now we need to use setResolvedUrl for the item at position ZERO @@ -107,7 +108,8 @@ def _playback_init(plex_id, plex_type, playqueue, pos): return # "Usual" case - consider trailers and parts and build both Kodi and Plex # playqueues - # Fail the item we're trying to play now so we can restart the player + # Pass dummy PKC video with 0 length so Kodi immediately stops playback + # and we can build our own playqueue. _ensure_resolve() api = API(xml[0]) trailers = False @@ -120,6 +122,10 @@ def _playback_init(plex_id, plex_type, playqueue, pos): else: trailers = True LOG.debug('Playing trailers: %s', trailers) + if RESOLVE: + # Sleep a bit to let setResolvedUrl do its thing - bit ugly + while not state.PKC_CAUSED_STOP_DONE: + sleep(50) playqueue.clear() if plex_type != v.PLEX_TYPE_CLIP: # Post to the PMS to create a playqueue - in any case due to Companion @@ -132,13 +138,13 @@ def _playback_init(plex_id, plex_type, playqueue, pos): plex_id, xml.attrib.get('librarySectionUUID')) # "Play error" dialog('notification', lang(29999), lang(30128), icon='{error}') - _ensure_resolve(abort=True) + # Do NOT use _ensure_resolve() because we resolved above already + state.CONTEXT_MENU_PLAY = False + state.FORCE_TRANSCODE = False + state.RESUME_PLAYBACK = False return - # Should already be empty, but just in case PL.get_playlist_details_from_xml(playqueue, xml) stack = _prep_playlist_stack(xml) - # Sleep a bit to let setResolvedUrl do its thing - bit ugly - sleep(200) _process_stack(playqueue, stack) # Always resume if playback initiated via PMS and there IS a resume # point @@ -146,7 +152,6 @@ def _playback_init(plex_id, plex_type, playqueue, pos): # Reset some playback variables state.CONTEXT_MENU_PLAY = False state.FORCE_TRANSCODE = False - # Do NOT set offset, because Kodi player will return here to resolveURL # New thread to release this one sooner (e.g. harddisk spinning up) thread = Thread(target=threaded_playback, args=(playqueue.kodi_pl, pos, offset)) @@ -173,9 +178,10 @@ def _ensure_resolve(abort=False): """ if RESOLVE: LOG.debug('Passing dummy path to Kodi') - if not state.CONTEXT_MENU_PLAY: - # Because playback won't start with context menu play - state.PKC_CAUSED_STOP = True + # if not state.CONTEXT_MENU_PLAY: + # Because playback won't start with context menu play + state.PKC_CAUSED_STOP = True + state.PKC_CAUSED_STOP_DONE = False result = Playback_Successful() result.listitem = PKC_ListItem(path=NULL_VIDEO) pickle_me(result) @@ -345,7 +351,8 @@ def process_indirect(key, offset, resolve=True): Set resolve to False if playback should be kicked off directly, not via setResolvedUrl """ - LOG.info('process_indirect called with key: %s, offset: %s', key, offset) + LOG.info('process_indirect called with key: %s, offset: %s, resolve: %s', + key, offset, resolve) global RESOLVE RESOLVE = resolve result = Playback_Successful() diff --git a/resources/lib/player.py b/resources/lib/player.py index 67c5dcdc..1cea6808 100644 --- a/resources/lib/player.py +++ b/resources/lib/player.py @@ -151,6 +151,7 @@ class PKC_Player(xbmc.Player): LOG.debug("ONPLAYBACK_ENDED") if state.PKC_CAUSED_STOP is True: state.PKC_CAUSED_STOP = False + state.PKC_CAUSED_STOP_DONE = True LOG.debug('PKC caused this playback stop - ignoring') else: playback_cleanup(ended=True) diff --git a/resources/lib/state.py b/resources/lib/state.py index 88c3e599..d136d74e 100644 --- a/resources/lib/state.py +++ b/resources/lib/state.py @@ -95,8 +95,12 @@ WEBSOCKET_QUEUE = None # Which Kodi player is/has been active? (either int 1, 2 or 3) ACTIVE_PLAYERS = [] -# Failsafe for throwing failing ListItems() back to Kodi's setResolvedUrl +# Failsafe for throwing an empty video back to Kodi's setResolvedUrl to set +# up our own playlist from the very beginning PKC_CAUSED_STOP = False +# Flag if the 0 length PKC video has already failed so we can start resolving +# playback (set in player.py) +PKC_CAUSED_STOP_DONE = True # Kodi player states - here, initial values are set PLAYER_STATES = {