From bf6bc26d46fa06b07b3ac883c79e885c5ebd43a3 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Mon, 13 Mar 2017 21:39:07 +0100 Subject: [PATCH] Move plex node navigation, playback to main thread --- default.py | 9 ++-- resources/lib/PlexCompanion.py | 38 +++++++++-------- resources/lib/entrypoint.py | 63 ++-------------------------- resources/lib/playback_starter.py | 68 ++++++++++++++++++++++++++++++- 4 files changed, 96 insertions(+), 82 deletions(-) diff --git a/default.py b/default.py index 1887faea..7eee823b 100644 --- a/default.py +++ b/default.py @@ -63,6 +63,9 @@ class Main(): if mode == 'play': self.play() + elif mode == 'plex_node': + self.play() + elif mode == 'ondeck': entrypoint.getOnDeck(itemid, params.get('type'), @@ -83,9 +86,6 @@ class Main(): entrypoint.getInProgressEpisodes(params['tagname'], int(params['limit'])) - elif mode == 'Plex_Node': - entrypoint.Plex_Node(itemid, params.get('viewOffset')) - elif mode == 'browseplex': entrypoint.browse_plex(key=params.get('key'), plex_section_id=params.get('id')) @@ -168,6 +168,9 @@ class Main(): entrypoint.doMainListing() def play(self): + """ + Start up playback_starter in main Python thread + """ # Put the request into the 'queue' while window('plex_play_new_item'): sleep(50) diff --git a/resources/lib/PlexCompanion.py b/resources/lib/PlexCompanion.py index fd79d8bf..a233e103 100644 --- a/resources/lib/PlexCompanion.py +++ b/resources/lib/PlexCompanion.py @@ -3,20 +3,18 @@ import logging from threading import Thread import Queue from socket import SHUT_RDWR +from urllib import urlencode -from xbmc import sleep +from xbmc import sleep, executebuiltin -from utils import settings, ThreadMethodsAdditionalSuspend, ThreadMethods, \ - window +from utils import settings, ThreadMethodsAdditionalSuspend, ThreadMethods from plexbmchelper import listener, plexgdm, subscribers, functions, \ httppersist, plexsettings from PlexFunctions import ParseContainerKey, GetPlexMetadata from PlexAPI import API import player -from entrypoint import Plex_Node import variables as v - ############################################################################### log = logging.getLogger("PLEX."+__name__) @@ -93,23 +91,27 @@ class PlexCompanion(Thread): self.mgr.playqueue.init_playqueue_from_plex_children( api.getRatingKey()) else: - thread = Thread(target=Plex_Node, - args=('{server}%s' % data.get('key'), - data.get('offset'), - True, - False),) - thread.setDaemon(True) - thread.start() + params = { + 'mode': 'plex_node', + 'key': '{server}%s' % data.get('key'), + 'view_offset': data.get('offset'), + 'play_directly': 'true', + 'node': 'false' + } + executebuiltin('RunPlugin(plugin://%s?%s)' + % (v.ADDON_ID, urlencode(params))) elif (task['action'] == 'playlist' and data.get('address') == 'node.plexapp.com'): # E.g. watch later initiated by Companion - thread = Thread(target=Plex_Node, - args=('{server}%s' % data.get('key'), - data.get('offset'), - True),) - thread.setDaemon(True) - thread.start() + params = { + 'mode': 'plex_node', + 'key': '{server}%s' % data.get('key'), + 'view_offset': data.get('offset'), + 'play_directly': 'true' + } + executebuiltin('RunPlugin(plugin://%s?%s)' + % (v.ADDON_ID, urlencode(params))) elif task['action'] == 'playlist': # Get the playqueue ID diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index dc298df4..9f440d61 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -97,62 +97,6 @@ def togglePlexTV(): sound=False) -def Plex_Node(url, viewOffset, playdirectly=False, node=True): - """ - Called only for a SINGLE element for Plex.tv watch later - - Always to return with a "setResolvedUrl" - """ - log.info('Plex_Node called with url: %s, viewOffset: %s' - % (url, viewOffset)) - # Plex redirect, e.g. watch later. Need to get actual URLs - if url.startswith('http') or url.startswith('{server}'): - xml = downloadutils.DownloadUtils().downloadUrl(url) - else: - xml = downloadutils.DownloadUtils().downloadUrl('{server}%s' % url) - try: - xml[0].attrib - except: - log.error('Could not download PMS metadata') - return - if viewOffset != '0': - try: - viewOffset = int(v.PLEX_TO_KODI_TIMEFACTOR * float(viewOffset)) - except: - pass - else: - window('plex_customplaylist.seektime', value=str(viewOffset)) - log.info('Set resume point to %s' % str(viewOffset)) - api = API(xml[0]) - typus = v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[api.getType()] - if node is True: - plex_id = None - kodi_id = 'plexnode' - else: - plex_id = api.getRatingKey() - kodi_id = None - with plexdb.Get_Plex_DB() as plex_db: - plexdb_item = plex_db.getItem_byId(plex_id) - try: - kodi_id = plexdb_item[0] - except TypeError: - log.info('Couldnt find item %s in Kodi db' - % api.getRatingKey()) - playqueue = Playqueue().get_playqueue_from_type(typus) - result = pbutils.PlaybackUtils(xml, playqueue).play( - plex_id, - kodi_id=kodi_id, - plex_lib_UUID=xml.attrib.get('librarySectionUUID')) - if result.listitem: - listitem = convert_PKC_to_listitem(result.listitem) - else: - return - if playdirectly: - Player().play(listitem.getfilename(), listitem) - else: - xbmcplugin.setResolvedUrl(HANDLE, True, listitem) - - ##### DO RESET AUTH ##### def resetAuth(): # User tried login and failed too many times @@ -969,10 +913,9 @@ def __build_item(xml_element): if (api.getKey().startswith('/system/services') or api.getKey().startswith('http')): params = { - 'mode': "Plex_Node", - 'id': xml_element.attrib.get('key'), - 'viewOffset': xml_element.attrib.get('viewOffset', '0'), - 'plex_type': xml_element.attrib.get('type') + 'mode': 'plex_node', + 'key': xml_element.attrib.get('key'), + 'view_offset': xml_element.attrib.get('viewOffset', '0'), } else: params = { diff --git a/resources/lib/playback_starter.py b/resources/lib/playback_starter.py index 548f5ac9..f8883c07 100644 --- a/resources/lib/playback_starter.py +++ b/resources/lib/playback_starter.py @@ -4,6 +4,8 @@ import logging from threading import Thread from urlparse import parse_qsl +from xbmc import Player + from PKC_listitem import PKC_ListItem from pickler import pickle_me, Playback_Successful from playbackutils import PlaybackUtils @@ -12,6 +14,9 @@ from PlexFunctions import GetPlexMetadata from PlexAPI import API from playqueue import lock import variables as v +from downloadutils import DownloadUtils +from PKC_listitem import convert_PKC_to_listitem +import plexdb_functions as plexdb ############################################################################### log = logging.getLogger("PLEX."+__name__) @@ -66,9 +71,64 @@ class Playback_Starter(Thread): % self.playqueue.playqueues) return result + def process_plex_node(self, url, viewOffset, directplay=False, + node=True): + """ + Called for Plex directories or redirect for playback (e.g. trailers, + clips, watchlater) + """ + log.info('process_plex_node called with url: %s, viewOffset: %s' + % (url, viewOffset)) + # Plex redirect, e.g. watch later. Need to get actual URLs + if url.startswith('http') or url.startswith('{server}'): + xml = DownloadUtils().downloadUrl(url) + else: + xml = DownloadUtils().downloadUrl('{server}%s' % url) + try: + xml[0].attrib + except: + log.error('Could not download PMS metadata') + return + if viewOffset != '0': + try: + viewOffset = int(v.PLEX_TO_KODI_TIMEFACTOR * float(viewOffset)) + except: + pass + else: + window('plex_customplaylist.seektime', value=str(viewOffset)) + log.info('Set resume point to %s' % str(viewOffset)) + api = API(xml[0]) + typus = v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[api.getType()] + if node is True: + plex_id = None + kodi_id = 'plexnode' + else: + plex_id = api.getRatingKey() + kodi_id = None + with plexdb.Get_Plex_DB() as plex_db: + plexdb_item = plex_db.getItem_byId(plex_id) + try: + kodi_id = plexdb_item[0] + except TypeError: + log.info('Couldnt find item %s in Kodi db' + % api.getRatingKey()) + playqueue = self.playqueue.get_playqueue_from_type(typus) + with lock: + result = PlaybackUtils(xml, playqueue).play( + plex_id, + kodi_id=kodi_id, + plex_lib_UUID=xml.attrib.get('librarySectionUUID')) + if directplay: + if result.listitem: + listitem = convert_PKC_to_listitem(result.listitem) + Player().play(listitem.getfilename(), listitem) + else: + return result + def triage(self, item): - mode, params = item.split('?', 1) + _, params = item.split('?', 1) params = dict(parse_qsl(params)) + mode = params.get('mode') log.debug('Received mode: %s, params: %s' % (mode, params)) try: if mode == 'play': @@ -76,6 +136,12 @@ class Playback_Starter(Thread): params.get('dbid')) elif mode == 'companion': result = self.process_companion() + elif mode == 'plex_node': + result = self.process_plex_node( + params.get('key'), + params.get('view_offset'), + directplay=True if params.get('play_directly') else False, + node=False if params.get('node') == 'false' else True) except: log.error('Error encountered for mode %s, params %s' % (mode, params))