From e17824609abca8a2e3c199a18a6c6a635af9847c Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Sat, 6 Jan 2018 15:19:12 +0100 Subject: [PATCH] Greatly simplify handling of PKC playqueues --- resources/lib/PlexCompanion.py | 40 ++- resources/lib/command_pipeline.py | 16 +- resources/lib/companion.py | 13 +- resources/lib/initialsetup.py | 106 ++++---- resources/lib/kodimonitor.py | 15 +- resources/lib/librarysync.py | 6 +- resources/lib/playback_starter.py | 55 ++-- resources/lib/playbackutils.py | 16 +- resources/lib/player.py | 1 - resources/lib/playqueue.py | 296 +++++++-------------- resources/lib/plexbmchelper/listener.py | 6 +- resources/lib/plexbmchelper/subscribers.py | 16 +- resources/lib/state.py | 11 +- resources/lib/userclient.py | 4 +- resources/lib/websocket_client.py | 9 +- service.py | 30 +-- 16 files changed, 259 insertions(+), 381 deletions(-) diff --git a/resources/lib/PlexCompanion.py b/resources/lib/PlexCompanion.py index 7e424166..653c9ca3 100644 --- a/resources/lib/PlexCompanion.py +++ b/resources/lib/PlexCompanion.py @@ -3,7 +3,7 @@ The Plex Companion master python file """ from logging import getLogger from threading import Thread -from Queue import Queue, Empty +from Queue import Empty from socket import SHUT_RDWR from urllib import urlencode @@ -19,6 +19,7 @@ import json_rpc as js import player import variables as v import state +import playqueue as PQ ############################################################################### @@ -32,9 +33,9 @@ class PlexCompanion(Thread): """ Plex Companion monitoring class. Invoke only once """ - def __init__(self, callback=None): + def __init__(self): LOG.info("----===## Starting PlexCompanion ##===----") - self.mgr = callback + # Init Plex Companion queue # Start GDM for server/client discovery self.client = plexgdm.plexgdm() self.client.clientDetails() @@ -42,7 +43,6 @@ class PlexCompanion(Thread): # kodi player instance self.player = player.PKC_Player() self.httpd = False - self.queue = None self.subscription_manager = None Thread.__init__(self) @@ -57,8 +57,9 @@ class PlexCompanion(Thread): api = API(xml[0]) if api.getType() == v.PLEX_TYPE_ALBUM: LOG.debug('Plex music album detected') - self.mgr.playqueue.init_playqueue_from_plex_children( - api.getRatingKey(), transient_token=data.get('token')) + PQ.init_playqueue_from_plex_children( + api.getRatingKey(), + transient_token=data.get('token')) else: state.PLEX_TRANSIENT_TOKEN = data.get('token') params = { @@ -91,7 +92,7 @@ class PlexCompanion(Thread): # Get the playqueue ID _, container_key, query = ParseContainerKey(data['containerKey']) try: - playqueue = self.mgr.playqueue.get_playqueue_from_type( + playqueue = PQ.get_playqueue_from_type( v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[data['type']]) except KeyError: # E.g. Plex web does not supply the media type @@ -103,13 +104,13 @@ class PlexCompanion(Thread): LOG.error('Could not download Plex metadata') return api = API(xml[0]) - playqueue = self.mgr.playqueue.get_playqueue_from_type( + playqueue = PQ.get_playqueue_from_type( v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[api.getType()]) if container_key == playqueue.id: LOG.info('Already know this playqueue - ignoring') playqueue.transient_token = data.get('token') else: - self.mgr.playqueue.update_playqueue_from_PMS( + PQ.update_playqueue_from_PMS( playqueue, playqueue_id=container_key, repeat=query.get('repeat'), @@ -121,7 +122,7 @@ class PlexCompanion(Thread): """ Plex Companion client adjusted audio or subtitle stream """ - playqueue = self.mgr.playqueue.get_playqueue_from_type( + playqueue = PQ.get_playqueue_from_type( v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[data['type']]) pos = js.get_position(playqueue.playlistid) if 'audioStreamID' in data: @@ -151,15 +152,13 @@ class PlexCompanion(Thread): plex_type = get_plextype_from_xml(xml) if plex_type is None: return - playqueue = self.mgr.playqueue.get_playqueue_from_type( + playqueue = PQ.get_playqueue_from_type( v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[plex_type]) playqueue.clear() return - playqueue = self.mgr.playqueue.get_playqueue_from_type( + playqueue = PQ.get_playqueue_from_type( v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[xml[0].attrib['type']]) - self.mgr.playqueue.update_playqueue_from_PMS( - playqueue, - data['playQueueID']) + PQ.update_playqueue_from_PMS(playqueue, data['playQueueID']) def _process_tasks(self, task): """ @@ -217,11 +216,9 @@ class PlexCompanion(Thread): # Start up instances request_mgr = httppersist.RequestMgr() - subscription_manager = subscribers.SubscriptionMgr( - request_mgr, self.player, self.mgr) + subscription_manager = subscribers.SubscriptionMgr(request_mgr, + self.player) self.subscription_manager = subscription_manager - queue = Queue(maxsize=100) - self.queue = queue if settings('plexCompanion') == 'true': # Start up httpd @@ -231,7 +228,6 @@ class PlexCompanion(Thread): httpd = listener.ThreadedHTTPServer( client, subscription_manager, - queue, ('', v.COMPANION_PORT), listener.MyHandler) httpd.timeout = 0.95 @@ -290,13 +286,13 @@ class PlexCompanion(Thread): LOG.warn(traceback.format_exc()) # See if there's anything we need to process try: - task = queue.get(block=False) + task = state.COMPANION_QUEUE.get(block=False) except Empty: pass else: # Got instructions, process them self._process_tasks(task) - queue.task_done() + state.COMPANION_QUEUE.task_done() # Don't sleep continue sleep(50) diff --git a/resources/lib/command_pipeline.py b/resources/lib/command_pipeline.py index 92c6cc57..20d37d4a 100644 --- a/resources/lib/command_pipeline.py +++ b/resources/lib/command_pipeline.py @@ -2,7 +2,6 @@ ############################################################################### import logging from threading import Thread -from Queue import Queue from xbmc import sleep @@ -10,8 +9,7 @@ from utils import window, thread_methods import state ############################################################################### -log = logging.getLogger("PLEX."+__name__) - +LOG = logging.getLogger("PLEX." + __name__) ############################################################################### @@ -23,16 +21,10 @@ class Monitor_Window(Thread): Adjusts state.py accordingly """ - # Borg - multiple instances, shared state - def __init__(self, callback=None): - self.mgr = callback - self.playback_queue = Queue() - Thread.__init__(self) - def run(self): thread_stopped = self.thread_stopped - queue = self.playback_queue - log.info("----===## Starting Kodi_Play_Client ##===----") + queue = state.COMMAND_PIPELINE_QUEUE + LOG.info("----===## Starting Kodi_Play_Client ##===----") while not thread_stopped(): if window('plex_command'): value = window('plex_command') @@ -70,4 +62,4 @@ class Monitor_Window(Thread): sleep(50) # Put one last item into the queue to let playback_starter end queue.put(None) - log.info("----===## Kodi_Play_Client stopped ##===----") + LOG.info("----===## Kodi_Play_Client stopped ##===----") diff --git a/resources/lib/companion.py b/resources/lib/companion.py index 0b24df4f..60aa29ce 100644 --- a/resources/lib/companion.py +++ b/resources/lib/companion.py @@ -6,7 +6,7 @@ from logging import getLogger from xbmc import Player from variables import ALEXA_TO_COMPANION -from playqueue import Playqueue +import playqueue as PQ from PlexFunctions import GetPlexKeyNumber import json_rpc as js import state @@ -29,9 +29,8 @@ def skip_to(params): LOG.debug('Skipping to playQueueItemID %s, plex_id %s', playqueue_item_id, plex_id) found = True - playqueues = Playqueue() for player in js.get_players().values(): - playqueue = playqueues.playqueues[player['playerid']] + playqueue = PQ.PLAYQUEUES[player['playerid']] for i, item in enumerate(playqueue.items): if item.id == playqueue_item_id: found = True @@ -57,7 +56,7 @@ def convert_alexa_to_companion(dictionary): del dictionary[key] -def process_command(request_path, params, queue=None): +def process_command(request_path, params): """ queue: Queue() of PlexCompanion.py """ @@ -67,12 +66,12 @@ def process_command(request_path, params, queue=None): if request_path == 'player/playback/playMedia': # We need to tell service.py action = 'alexa' if params.get('deviceName') == 'Alexa' else 'playlist' - queue.put({ + state.COMPANION_QUEUE.put({ 'action': action, 'data': params }) elif request_path == 'player/playback/refreshPlayQueue': - queue.put({ + state.COMPANION_QUEUE.put({ 'action': 'refreshPlayQueue', 'data': params }) @@ -114,7 +113,7 @@ def process_command(request_path, params, queue=None): elif request_path == "player/navigation/back": js.input_back() elif request_path == "player/playback/setStreams": - queue.put({ + state.COMPANION_QUEUE.put({ 'action': 'setStreams', 'data': params }) diff --git a/resources/lib/initialsetup.py b/resources/lib/initialsetup.py index 13641603..92b1eafc 100644 --- a/resources/lib/initialsetup.py +++ b/resources/lib/initialsetup.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- - ############################################################################### from logging import getLogger +from Queue import Queue import xbmc import xbmcgui @@ -15,10 +15,11 @@ from PlexAPI import PlexAPI from PlexFunctions import GetMachineIdentifier, get_PMS_settings import state from migration import check_migration +import playqueue as PQ ############################################################################### -log = getLogger("PLEX."+__name__) +LOG = getLogger("PLEX." + __name__) ############################################################################### @@ -26,7 +27,7 @@ log = getLogger("PLEX."+__name__) class InitialSetup(): def __init__(self): - log.debug('Entering initialsetup class') + LOG.debug('Entering initialsetup class') self.doUtils = downloadutils.DownloadUtils().downloadUrl self.plx = PlexAPI() self.dialog = xbmcgui.Dialog() @@ -42,7 +43,7 @@ class InitialSetup(): # Token for the PMS, not plex.tv self.pms_token = settings('accessToken') if self.plexToken: - log.debug('Found a plex.tv token in the settings') + LOG.debug('Found a plex.tv token in the settings') def PlexTVSignIn(self): """ @@ -68,7 +69,7 @@ class InitialSetup(): chk = self.plx.CheckConnection('plex.tv', token=self.plexToken) if chk in (401, 403): # HTTP Error: unauthorized. Token is no longer valid - log.info('plex.tv connection returned HTTP %s' % str(chk)) + LOG.info('plex.tv connection returned HTTP %s', str(chk)) # Delete token in the settings settings('plexToken', value='') settings('plexLogin', value='') @@ -77,12 +78,12 @@ class InitialSetup(): answer = self.PlexTVSignIn() elif chk is False or chk >= 400: # Problems connecting to plex.tv. Network or internet issue? - log.info('Problems connecting to plex.tv; connection returned ' - 'HTTP %s' % str(chk)) + LOG.info('Problems connecting to plex.tv; connection returned ' + 'HTTP %s', str(chk)) self.dialog.ok(lang(29999), lang(39010)) answer = False else: - log.info('plex.tv connection with token successful') + LOG.info('plex.tv connection with token successful') settings('plex_status', value=lang(39227)) # Refresh the info from Plex.tv xml = self.doUtils('https://plex.tv/users/account', @@ -91,14 +92,14 @@ class InitialSetup(): try: self.plexLogin = xml.attrib['title'] except (AttributeError, KeyError): - log.error('Failed to update Plex info from plex.tv') + LOG.error('Failed to update Plex info from plex.tv') else: settings('plexLogin', value=self.plexLogin) home = 'true' if xml.attrib.get('home') == '1' else 'false' settings('plexhome', value=home) settings('plexAvatar', value=xml.attrib.get('thumb')) settings('plexHomeSize', value=xml.attrib.get('homeSize', '1')) - log.info('Updated Plex info from plex.tv') + LOG.info('Updated Plex info from plex.tv') return answer def CheckPMS(self): @@ -114,24 +115,24 @@ class InitialSetup(): answer = True chk = self.plx.CheckConnection(self.server, verifySSL=False) if chk is False: - log.warn('Could not reach PMS %s' % self.server) + LOG.warn('Could not reach PMS %s', self.server) answer = False if answer is True and not self.serverid: - log.info('No PMS machineIdentifier found for %s. Trying to ' - 'get the PMS unique ID' % self.server) + LOG.info('No PMS machineIdentifier found for %s. Trying to ' + 'get the PMS unique ID', self.server) self.serverid = GetMachineIdentifier(self.server) if self.serverid is None: - log.warn('Could not retrieve machineIdentifier') + LOG.warn('Could not retrieve machineIdentifier') answer = False else: settings('plex_machineIdentifier', value=self.serverid) elif answer is True: tempServerid = GetMachineIdentifier(self.server) if tempServerid != self.serverid: - log.warn('The current PMS %s was expected to have a ' + LOG.warn('The current PMS %s was expected to have a ' 'unique machineIdentifier of %s. But we got ' - '%s. Pick a new server to be sure' - % (self.server, self.serverid, tempServerid)) + '%s. Pick a new server to be sure', + self.server, self.serverid, tempServerid) answer = False return answer @@ -142,7 +143,7 @@ class InitialSetup(): self.plx.discoverPMS(xbmc.getIPAddress(), plexToken=self.plexToken) serverlist = self.plx.returnServerList(self.plx.g_PMS) - log.debug('PMS serverlist: %s' % serverlist) + LOG.debug('PMS serverlist: %s', serverlist) return serverlist def _checkServerCon(self, server): @@ -209,7 +210,7 @@ class InitialSetup(): try: xml.attrib except AttributeError: - log.error('Could not get PMS settings for %s' % url) + LOG.error('Could not get PMS settings for %s', url) return for entry in xml: if entry.attrib.get('id', '') == 'allowMediaDeletion': @@ -236,9 +237,9 @@ class InitialSetup(): server = item if server is None: name = settings('plex_servername') - log.warn('The PMS you have used before with a unique ' + LOG.warn('The PMS you have used before with a unique ' 'machineIdentifier of %s and name %s is ' - 'offline' % (self.serverid, name)) + 'offline', self.serverid, name) return chk = self._checkServerCon(server) if chk == 504 and httpsUpdated is False: @@ -247,8 +248,8 @@ class InitialSetup(): httpsUpdated = True continue if chk == 401: - log.warn('Not yet authorized for Plex server %s' - % server['name']) + LOG.warn('Not yet authorized for Plex server %s', + server['name']) if self.CheckPlexTVSignIn() is True: if checkedPlexTV is False: # Try again @@ -256,7 +257,7 @@ class InitialSetup(): httpsUpdated = False continue else: - log.warn('Not authorized even though we are signed ' + LOG.warn('Not authorized even though we are signed ' ' in to plex.tv correctly') self.dialog.ok(lang(29999), '%s %s' % (lang(39214), @@ -266,11 +267,11 @@ class InitialSetup(): return # Problems connecting elif chk >= 400 or chk is False: - log.warn('Problems connecting to server %s. chk is %s' - % (server['name'], chk)) + LOG.warn('Problems connecting to server %s. chk is %s', + server['name'], chk) return - log.info('We found a server to automatically connect to: %s' - % server['name']) + LOG.info('We found a server to automatically connect to: %s', + server['name']) return server def _UserPickPMS(self): @@ -285,7 +286,7 @@ class InitialSetup(): serverlist = self._getServerList() # Exit if no servers found if len(serverlist) == 0: - log.warn('No plex media servers found!') + LOG.warn('No plex media servers found!') self.dialog.ok(lang(29999), lang(39011)) return # Get a nicer list @@ -322,8 +323,8 @@ class InitialSetup(): continue httpsUpdated = False if chk == 401: - log.warn('Not yet authorized for Plex server %s' - % server['name']) + LOG.warn('Not yet authorized for Plex server %s', + server['name']) # Please sign in to plex.tv self.dialog.ok(lang(29999), lang(39013) + server['name'], @@ -370,7 +371,7 @@ class InitialSetup(): scheme = server['scheme'] settings('ipaddress', server['ip']) settings('port', server['port']) - log.debug("Setting SSL verify to false, because server is " + LOG.debug("Setting SSL verify to false, because server is " "local") settings('sslverify', 'false') else: @@ -378,7 +379,7 @@ class InitialSetup(): scheme = baseURL[0] settings('ipaddress', baseURL[1].replace('//', '')) settings('port', baseURL[2]) - log.debug("Setting SSL verify to true, because server is not " + LOG.debug("Setting SSL verify to true, because server is not " "local") settings('sslverify', 'true') @@ -387,10 +388,10 @@ class InitialSetup(): else: settings('https', 'false') # And finally do some logging - log.debug("Writing to Kodi user settings file") - log.debug("PMS machineIdentifier: %s, ip: %s, port: %s, https: %s " - % (server['machineIdentifier'], server['ip'], - server['port'], server['scheme'])) + LOG.debug("Writing to Kodi user settings file") + LOG.debug("PMS machineIdentifier: %s, ip: %s, port: %s, https: %s ", + server['machineIdentifier'], server['ip'], server['port'], + server['scheme']) def setup(self): """ @@ -399,14 +400,14 @@ class InitialSetup(): Check server, user, direct paths, music, direct stream if not direct path. """ - log.info("Initial setup called.") + LOG.info("Initial setup called.") dialog = self.dialog # Get current Kodi video cache setting cache, _ = advancedsettings_xml(['cache', 'memorysize']) # Kodi default cache if no setting is set cache = str(cache.text) if cache is not None else '20971520' - log.info('Current Kodi video memory cache in bytes: %s', cache) + LOG.info('Current Kodi video memory cache in bytes: %s', cache) settings('kodi_video_cache', value=cache) # Disable foreground "Loading media information from files" # (still used by Kodi, even though the Wiki says otherwise) @@ -420,13 +421,20 @@ class InitialSetup(): if self.plexToken and self.myplexlogin: self.CheckPlexTVSignIn() + # Initialize the PKC playqueues + PQ.init_playqueues() + # Init some Queues() + state.COMMAND_PIPELINE_QUEUE = Queue() + state.COMPANION_QUEUE = Queue(maxsize=100) + state.WEBSOCKET_QUEUE = Queue() + # If a Plex server IP has already been set # return only if the right machine identifier is found if self.server: - log.info("PMS is already set: %s. Checking now..." % self.server) + LOG.info("PMS is already set: %s. Checking now...", self.server) if self.CheckPMS(): - log.info("Using PMS %s with machineIdentifier %s" - % (self.server, self.serverid)) + LOG.info("Using PMS %s with machineIdentifier %s", + self.server, self.serverid) self._write_PMS_settings(self.server, self.pms_token) return @@ -452,19 +460,19 @@ class InitialSetup(): lang(39028), nolabel="Addon (Default)", yeslabel="Native (Direct Paths)"): - log.debug("User opted to use direct paths.") + LOG.debug("User opted to use direct paths.") settings('useDirectPaths', value="1") state.DIRECT_PATHS = True # Are you on a system where you would like to replace paths # \\NAS\mymovie.mkv with smb://NAS/mymovie.mkv? (e.g. Windows) if dialog.yesno(heading=lang(29999), line1=lang(39033)): - log.debug("User chose to replace paths with smb") + LOG.debug("User chose to replace paths with smb") else: settings('replaceSMB', value="false") # complete replace all original Plex library paths with custom SMB if dialog.yesno(heading=lang(29999), line1=lang(39043)): - log.debug("User chose custom smb paths") + LOG.debug("User chose custom smb paths") settings('remapSMB', value="true") # Please enter your custom smb paths in the settings under # "Sync Options" and then restart Kodi @@ -475,22 +483,22 @@ class InitialSetup(): if dialog.yesno(heading=lang(29999), line1=lang(39029), line2=lang(39030)): - log.debug("Presenting network credentials dialog.") + LOG.debug("Presenting network credentials dialog.") from utils import passwordsXML passwordsXML() # Disable Plex music? if dialog.yesno(heading=lang(29999), line1=lang(39016)): - log.debug("User opted to disable Plex music library.") + LOG.debug("User opted to disable Plex music library.") settings('enableMusic', value="false") # Download additional art from FanArtTV if dialog.yesno(heading=lang(29999), line1=lang(39061)): - log.debug("User opted to use FanArtTV") + LOG.debug("User opted to use FanArtTV") settings('FanartTV', value="true") # Do you want to replace your custom user ratings with an indicator of # how many versions of a media item you posses? if dialog.yesno(heading=lang(29999), line1=lang(39718)): - log.debug("User opted to replace user ratings with version number") + LOG.debug("User opted to replace user ratings with version number") settings('indicate_media_versions', value="true") # If you use several Plex libraries of one kind, e.g. "Kids Movies" and diff --git a/resources/lib/kodimonitor.py b/resources/lib/kodimonitor.py index d250841b..17bf28eb 100644 --- a/resources/lib/kodimonitor.py +++ b/resources/lib/kodimonitor.py @@ -16,6 +16,7 @@ import json_rpc as js import playlist_func as PL import state import variables as v +import playqueue as PQ ############################################################################### @@ -51,10 +52,8 @@ class KodiMonitor(Monitor): """ PKC implementation of the Kodi Monitor class. Invoke only once. """ - def __init__(self, callback): - self.mgr = callback + def __init__(self): self.xbmcplayer = Player() - self.playqueue = self.mgr.playqueue Monitor.__init__(self) LOG.info("Kodi monitor started.") @@ -198,7 +197,7 @@ class KodiMonitor(Monitor): } Will NOT be called if playback initiated by Kodi widgets """ - playqueue = self.playqueue.playqueues[data['playlistid']] + playqueue = PQ.PLAYQUEUES[data['playlistid']] # Did PKC cause this add? Then lets not do anything if playqueue.is_kodi_onadd() is False: LOG.debug('PKC added this item to the playqueue - ignoring') @@ -228,7 +227,7 @@ class KodiMonitor(Monitor): u'position': 0 } """ - playqueue = self.playqueue.playqueues[data['playlistid']] + playqueue = PQ.PLAYQUEUES[data['playlistid']] # Did PKC cause this add? Then lets not do anything if playqueue.is_kodi_onremove() is False: LOG.debug('PKC removed this item already from playqueue - ignoring') @@ -249,7 +248,7 @@ class KodiMonitor(Monitor): u'playlistid': 1, } """ - playqueue = self.playqueue.playqueues[data['playlistid']] + playqueue = PQ.PLAYQUEUES[data['playlistid']] if playqueue.is_kodi_onclear() is False: LOG.debug('PKC already cleared the playqueue - ignoring') return @@ -317,7 +316,7 @@ class KodiMonitor(Monitor): LOG.debug('Set the player state: %s', state.PLAYER_STATES[playerid]) # Check whether we need to init our playqueues (e.g. direct play) init = False - playqueue = self.playqueue.playqueues[playerid] + playqueue = PQ.PLAYQUEUES[playerid] try: playqueue.items[info['position']] except IndexError: @@ -340,7 +339,7 @@ class KodiMonitor(Monitor): container_key = None if info['playlistid'] != -1: # -1 is Kodi's answer if there is no playlist - container_key = self.playqueue.playqueues[playerid].id + container_key = PQ.PLAYQUEUES[playerid].id if container_key is not None: container_key = '/playQueues/%s' % container_key elif plex_id is not None: diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index 6943ec65..28d173b0 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -43,9 +43,7 @@ log = getLogger("PLEX."+__name__) class LibrarySync(Thread): """ """ - def __init__(self, callback=None): - self.mgr = callback - + def __init__(self): self.itemsToProcess = [] self.sessionKeys = [] self.fanartqueue = Queue.Queue() @@ -1527,7 +1525,7 @@ class LibrarySync(Thread): oneDay = 60*60*24 # Link to Websocket queue - queue = self.mgr.ws.queue + queue = state.WEBSOCKET_QUEUE startupComplete = False self.views = [] diff --git a/resources/lib/playback_starter.py b/resources/lib/playback_starter.py index c097c4ca..901e75e6 100644 --- a/resources/lib/playback_starter.py +++ b/resources/lib/playback_starter.py @@ -12,7 +12,7 @@ from playbackutils import PlaybackUtils from utils import window from PlexFunctions import GetPlexMetadata from PlexAPI import API -from playqueue import LOCK +import playqueue as PQ import variables as v from downloadutils import DownloadUtils from PKC_listitem import convert_PKC_to_listitem @@ -21,7 +21,8 @@ from context_entry import ContextMenu import state ############################################################################### -log = getLogger("PLEX."+__name__) + +LOG = getLogger("PLEX." + __name__) ############################################################################### @@ -30,26 +31,21 @@ class Playback_Starter(Thread): """ Processes new plays """ - def __init__(self, callback=None): - self.mgr = callback - self.playqueue = self.mgr.playqueue - Thread.__init__(self) - def process_play(self, plex_id, kodi_id=None): """ Processes Kodi playback init for ONE item """ - log.info("Process_play called with plex_id %s, kodi_id %s" - % (plex_id, kodi_id)) + LOG.info("Process_play called with plex_id %s, kodi_id %s", + plex_id, kodi_id) if not state.AUTHENTICATED: - log.error('Not yet authenticated for PMS, abort starting playback') + LOG.error('Not yet authenticated for PMS, abort starting playback') # Todo: Warn user with dialog return xml = GetPlexMetadata(plex_id) try: xml[0].attrib except (IndexError, TypeError, AttributeError): - log.error('Could not get a PMS xml for plex id %s' % plex_id) + LOG.error('Could not get a PMS xml for plex id %s', plex_id) return api = API(xml[0]) if api.getType() == v.PLEX_TYPE_PHOTO: @@ -60,15 +56,14 @@ class Playback_Starter(Thread): result.listitem = listitem else: # Video and Music - playqueue = self.playqueue.get_playqueue_from_type( + playqueue = PQ.get_playqueue_from_type( v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[api.getType()]) - with LOCK: + with PQ.LOCK: result = PlaybackUtils(xml, playqueue).play( plex_id, kodi_id, xml.attrib.get('librarySectionUUID')) - log.info('Done process_play, playqueues: %s' - % self.playqueue.playqueues) + LOG.info('Done process_play, playqueues: %s', PQ.PLAYQUEUES) return result def process_plex_node(self, url, viewOffset, directplay=False, @@ -77,8 +72,8 @@ class Playback_Starter(Thread): 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)) + 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) @@ -87,7 +82,7 @@ class Playback_Starter(Thread): try: xml[0].attrib except: - log.error('Could not download PMS metadata') + LOG.error('Could not download PMS metadata') return if viewOffset != '0': try: @@ -96,7 +91,7 @@ class Playback_Starter(Thread): pass else: window('plex_customplaylist.seektime', value=str(viewOffset)) - log.info('Set resume point to %s' % str(viewOffset)) + LOG.info('Set resume point to %s', viewOffset) api = API(xml[0]) typus = v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[api.getType()] if node is True: @@ -110,10 +105,10 @@ class Playback_Starter(Thread): 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: + LOG.info('Couldnt find item %s in Kodi db', + api.getRatingKey()) + playqueue = PQ.get_playqueue_from_type(typus) + with PQ.LOCK: result = PlaybackUtils(xml, playqueue).play( plex_id, kodi_id=kodi_id, @@ -130,7 +125,7 @@ class Playback_Starter(Thread): _, params = item.split('?', 1) params = dict(parse_qsl(params)) mode = params.get('mode') - log.debug('Received mode: %s, params: %s' % (mode, params)) + LOG.debug('Received mode: %s, params: %s', mode, params) try: if mode == 'play': result = self.process_play(params.get('id'), @@ -147,18 +142,18 @@ class Playback_Starter(Thread): ContextMenu() result = Playback_Successful() except: - log.error('Error encountered for mode %s, params %s' - % (mode, params)) + LOG.error('Error encountered for mode %s, params %s', + mode, params) import traceback - log.error(traceback.format_exc()) + LOG.error(traceback.format_exc()) # Let default.py know! pickle_me(None) else: pickle_me(result) def run(self): - queue = self.mgr.command_pipeline.playback_queue - log.info("----===## Starting Playback_Starter ##===----") + queue = state.COMMAND_PIPELINE_QUEUE + LOG.info("----===## Starting Playback_Starter ##===----") while True: item = queue.get() if item is None: @@ -167,4 +162,4 @@ class Playback_Starter(Thread): else: self.triage(item) queue.task_done() - log.info("----===## Playback_Starter stopped ##===----") + LOG.info("----===## Playback_Starter stopped ##===----") diff --git a/resources/lib/playbackutils.py b/resources/lib/playbackutils.py index 03afcb8c..aedb0e6f 100644 --- a/resources/lib/playbackutils.py +++ b/resources/lib/playbackutils.py @@ -97,6 +97,7 @@ class PlaybackUtils(): startPos = max(playqueue.kodi_pl.getposition(), 0) self.currentPosition = startPos + propertiesPlayback = window('plex_playbackProps') == "true" introsPlaylist = False dummyPlaylist = False @@ -113,8 +114,8 @@ class PlaybackUtils(): # We need to ensure we add the intro and additional parts only once. # Otherwise we get a loop. - if not state.PLAYBACK_SETUP_DONE: - state.PLAYBACK_SETUP_DONE = True + if not propertiesPlayback: + window('plex_playbackProps', value="true") LOG.info("Setting up properties in playlist.") # Where will the player need to start? # Do we need to get trailers? @@ -139,7 +140,6 @@ class PlaybackUtils(): get_playlist_details_from_xml(playqueue, xml=xml) except KeyError: return - if (not homeScreen and not seektime and sizePlaylist < 2 and window('plex_customplaylist') != "true" and not contextmenu_play): @@ -198,7 +198,7 @@ class PlaybackUtils(): api.set_listitem_artwork(listitem) add_listitem_to_Kodi_playlist( playqueue, - self.currentPosition, + self.currentPosition+1, convert_PKC_to_listitem(listitem), file=playurl, kodi_item={'id': kodi_id, 'type': kodi_type}) @@ -206,7 +206,7 @@ class PlaybackUtils(): # Full metadata$ add_item_to_kodi_playlist( playqueue, - self.currentPosition, + self.currentPosition+1, kodi_id, kodi_type) self.currentPosition += 1 @@ -230,9 +230,9 @@ class PlaybackUtils(): return result # We just skipped adding properties. Reset flag for next time. - elif state.PLAYBACK_SETUP_DONE: + elif propertiesPlayback: LOG.debug("Resetting properties playback flag.") - state.PLAYBACK_SETUP_DONE = False + window('plex_playbackProps', clear=True) # SETUP MAIN ITEM ########## # For transcoding only, ask for audio/subs pref @@ -275,7 +275,7 @@ class PlaybackUtils(): Play all items contained in the xml passed in. Called by Plex Companion """ LOG.info("Playbackutils play_all called") - state.PLAYBACK_SETUP_DONE = True + window('plex_playbackProps', value="true") self.currentPosition = 0 for item in self.xml: api = API(item) diff --git a/resources/lib/player.py b/resources/lib/player.py index 1e13d431..be006ff2 100644 --- a/resources/lib/player.py +++ b/resources/lib/player.py @@ -268,7 +268,6 @@ class PKC_Player(Player): # We might have saved a transient token from a user flinging media via # Companion (if we could not use the playqueue to store the token) state.PLEX_TRANSIENT_TOKEN = None - state.PLAYBACK_SETUP_DONE = False LOG.debug("Cleared playlist properties.") def onPlayBackEnded(self): diff --git a/resources/lib/playqueue.py b/resources/lib/playqueue.py index 416078ca..40804803 100644 --- a/resources/lib/playqueue.py +++ b/resources/lib/playqueue.py @@ -4,9 +4,9 @@ Monitors the Kodi playqueue and adjusts the Plex playqueue accordingly from logging import getLogger from threading import RLock, Thread -from xbmc import sleep, Player, PlayList, PLAYLIST_MUSIC, PLAYLIST_VIDEO +from xbmc import Player, PlayList, PLAYLIST_MUSIC, PLAYLIST_VIDEO -from utils import window, thread_methods +from utils import window import playlist_func as PL from PlexFunctions import ConvertPlexToKodiTime, GetAllPlexChildren from PlexAPI import API @@ -20,218 +20,126 @@ LOG = getLogger("PLEX." + __name__) # lock used for playqueue manipulations LOCK = RLock() PLUGIN = 'plugin://%s' % v.ADDON_ID + +# Our PKC playqueues (3 instances of Playqueue_Object()) +PLAYQUEUES = [] ############################################################################### -@thread_methods(add_suspends=['PMS_STATUS']) -class Playqueue(Thread): +def init_playqueues(): """ - Monitors Kodi's playqueues for changes on the Kodi side + Call this once on startup to initialize the PKC playqueue objects in + the list PLAYQUEUES """ - # Borg - multiple instances, shared state - __shared_state = {} - playqueues = None - - def __init__(self, callback=None): - self.__dict__ = self.__shared_state - if self.playqueues is not None: - LOG.debug('Playqueue thread has already been initialized') - Thread.__init__(self) - return - self.mgr = callback - - # Initialize Kodi playqueues - with LOCK: - self.playqueues = [] + if PLAYQUEUES: + LOG.debug('Playqueues have already been initialized') + return + # Initialize Kodi playqueues + with LOCK: + for i in (0, 1, 2): + # Just in case the Kodi response is not sorted correctly for queue in js.get_playlists(): + if queue['playlistid'] != i: + continue playqueue = PL.Playqueue_Object() - playqueue.playlistid = queue['playlistid'] + playqueue.playlistid = i playqueue.type = queue['type'] # Initialize each Kodi playlist - if playqueue.type == 'audio': + if playqueue.type == v.KODI_TYPE_AUDIO: playqueue.kodi_pl = PlayList(PLAYLIST_MUSIC) - elif playqueue.type == 'video': + elif playqueue.type == v.KODI_TYPE_VIDEO: playqueue.kodi_pl = PlayList(PLAYLIST_VIDEO) else: # Currently, only video or audio playqueues available playqueue.kodi_pl = PlayList(PLAYLIST_VIDEO) # Overwrite 'picture' with 'photo' playqueue.type = v.KODI_TYPE_PHOTO - self.playqueues.append(playqueue) - # sort the list by their playlistid, just in case - self.playqueues = sorted( - self.playqueues, key=lambda i: i.playlistid) - LOG.debug('Initialized the Kodi play queues: %s', self.playqueues) - Thread.__init__(self) + PLAYQUEUES.append(playqueue) + LOG.debug('Initialized the Kodi playqueues: %s', PLAYQUEUES) - def get_playqueue_from_type(self, typus): - """ - Returns the playqueue according to the typus ('video', 'audio', - 'picture') passed in - """ - with LOCK: - for playqueue in self.playqueues: - if playqueue.type == typus: - break - else: - raise ValueError('Wrong playlist type passed in: %s' % typus) - return playqueue - def init_playqueue_from_plex_children(self, plex_id, transient_token=None): - """ - Init a new playqueue e.g. from an album. Alexa does this - - Returns the Playlist_Object - """ - xml = GetAllPlexChildren(plex_id) - try: - xml[0].attrib - except (TypeError, IndexError, AttributeError): - LOG.error('Could not download the PMS xml for %s', plex_id) - return - playqueue = self.get_playqueue_from_type( - v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[xml[0].attrib['type']]) - playqueue.clear() - for i, child in enumerate(xml): - api = API(child) - PL.add_item_to_playlist(playqueue, i, plex_id=api.getRatingKey()) - playqueue.plex_transient_token = transient_token - LOG.debug('Firing up Kodi player') - Player().play(playqueue.kodi_pl, None, False, 0) +def get_playqueue_from_type(typus): + """ + Returns the playqueue according to the typus ('video', 'audio', + 'picture') passed in + """ + with LOCK: + for playqueue in PLAYQUEUES: + if playqueue.type == typus: + break + else: + raise ValueError('Wrong playlist type passed in: %s' % typus) return playqueue - def update_playqueue_from_PMS(self, - playqueue, - playqueue_id=None, - repeat=None, - offset=None, - transient_token=None): - """ - Completely updates the Kodi playqueue with the new Plex playqueue. Pass - in playqueue_id if we need to fetch a new playqueue - repeat = 0, 1, 2 - offset = time offset in Plextime (milliseconds) - """ - LOG.info('New playqueue %s received from Plex companion with offset ' - '%s, repeat %s', playqueue_id, offset, repeat) - # Safe transient token from being deleted - if transient_token is None: - transient_token = playqueue.plex_transient_token - with LOCK: - xml = PL.get_PMS_playlist(playqueue, playqueue_id) - playqueue.clear() - try: - PL.get_playlist_details_from_xml(playqueue, xml) - except KeyError: - LOG.error('Could not get playqueue ID %s', playqueue_id) - return - playqueue.repeat = 0 if not repeat else int(repeat) - playqueue.plex_transient_token = transient_token - PlaybackUtils(xml, playqueue).play_all() - window('plex_customplaylist', value="true") - if offset not in (None, "0"): - window('plex_customplaylist.seektime', - str(ConvertPlexToKodiTime(offset))) - for startpos, item in enumerate(playqueue.items): - if item.id == playqueue.selectedItemID: - break - else: - startpos = 0 - # Start playback. Player does not return in time - LOG.debug('Playqueues after Plex Companion update are now: %s', - self.playqueues) - thread = Thread(target=Player().play, - args=(playqueue.kodi_pl, - None, - False, - startpos)) - thread.setDaemon(True) - thread.start() +def init_playqueue_from_plex_children(plex_id, transient_token=None): + """ + Init a new playqueue e.g. from an album. Alexa does this - def _compare_playqueues(self, playqueue, new): - """ - Used to poll the Kodi playqueue and update the Plex playqueue if needed - """ - old = list(playqueue.items) - index = list(range(0, len(old))) - LOG.debug('Comparing new Kodi playqueue %s with our play queue %s', - new, old) - if self.thread_stopped(): - # Chances are that we got an empty Kodi playlist due to - # Kodi exit + Returns the Playlist_Object + """ + xml = GetAllPlexChildren(plex_id) + try: + xml[0].attrib + except (TypeError, IndexError, AttributeError): + LOG.error('Could not download the PMS xml for %s', plex_id) + return + playqueue = get_playqueue_from_type( + v.KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[xml[0].attrib['type']]) + playqueue.clear() + for i, child in enumerate(xml): + api = API(child) + PL.add_item_to_playlist(playqueue, i, plex_id=api.getRatingKey()) + playqueue.plex_transient_token = transient_token + LOG.debug('Firing up Kodi player') + Player().play(playqueue.kodi_pl, None, False, 0) + return playqueue + + +def update_playqueue_from_PMS(playqueue, + playqueue_id=None, + repeat=None, + offset=None, + transient_token=None): + """ + Completely updates the Kodi playqueue with the new Plex playqueue. Pass + in playqueue_id if we need to fetch a new playqueue + + repeat = 0, 1, 2 + offset = time offset in Plextime (milliseconds) + """ + LOG.info('New playqueue %s received from Plex companion with offset ' + '%s, repeat %s', playqueue_id, offset, repeat) + # Safe transient token from being deleted + if transient_token is None: + transient_token = playqueue.plex_transient_token + with LOCK: + xml = PL.get_PMS_playlist(playqueue, playqueue_id) + playqueue.clear() + try: + PL.get_playlist_details_from_xml(playqueue, xml) + except KeyError: + LOG.error('Could not get playqueue ID %s', playqueue_id) return - for i, new_item in enumerate(new): - if (new_item['file'].startswith('plugin://') and - not new_item['file'].startswith(PLUGIN)): - # Ignore new media added by other addons - continue - for j, old_item in enumerate(old): - try: - if (old_item.file.startswith('plugin://') and - not old_item['file'].startswith(PLUGIN)): - # Ignore media by other addons - continue - except (TypeError, AttributeError): - # were not passed a filename; ignore - pass - if new_item.get('id') is None: - identical = old_item.file == new_item['file'] - else: - identical = (old_item.kodi_id == new_item['id'] and - old_item.kodi_type == new_item['type']) - if j == 0 and identical: - del old[j], index[j] - break - elif identical: - LOG.debug('Detected playqueue item %s moved to position %s', - i+j, i) - PL.move_playlist_item(playqueue, i + j, i) - del old[j], index[j] - break - else: - LOG.debug('Detected new Kodi element at position %s: %s ', - i, new_item) - if playqueue.id is None: - PL.init_Plex_playlist(playqueue, - kodi_item=new_item) - else: - PL.add_item_to_PMS_playlist(playqueue, - i, - kodi_item=new_item) - for j in range(i, len(index)): - index[j] += 1 - for i in reversed(index): - LOG.debug('Detected deletion of playqueue element at pos %s', i) - PL.delete_playlist_item_from_PMS(playqueue, i) - LOG.debug('Done comparing playqueues') - - def run(self): - thread_stopped = self.thread_stopped - thread_suspended = self.thread_suspended - LOG.info("----===## Starting PlayQueue client ##===----") - # Initialize the playqueues, if Kodi already got items in them - for playqueue in self.playqueues: - for i, item in enumerate(js.playlist_get_items(playqueue.id)): - if i == 0: - PL.init_Plex_playlist(playqueue, kodi_item=item) - else: - PL.add_item_to_PMS_playlist(playqueue, i, kodi_item=item) - while not thread_stopped(): - while thread_suspended(): - if thread_stopped(): - break - sleep(1000) - # with LOCK: - # for playqueue in self.playqueues: - # kodi_playqueue = js.playlist_get_items(playqueue.id) - # if playqueue.old_kodi_pl != kodi_playqueue: - # # compare old and new playqueue - # self._compare_playqueues(playqueue, kodi_playqueue) - # playqueue.old_kodi_pl = list(kodi_playqueue) - # # Still sleep a bit so Kodi does not become - # # unresponsive - # sleep(10) - # continue - sleep(200) - LOG.info("----===## PlayQueue client stopped ##===----") + playqueue.repeat = 0 if not repeat else int(repeat) + playqueue.plex_transient_token = transient_token + PlaybackUtils(xml, playqueue).play_all() + window('plex_customplaylist', value="true") + if offset not in (None, "0"): + window('plex_customplaylist.seektime', + str(ConvertPlexToKodiTime(offset))) + for startpos, item in enumerate(playqueue.items): + if item.id == playqueue.selectedItemID: + break + else: + startpos = 0 + # Start playback. Player does not return in time + LOG.debug('Playqueues after Plex Companion update are now: %s', + PLAYQUEUES) + thread = Thread(target=Player().play, + args=(playqueue.kodi_pl, + None, + False, + startpos)) + thread.setDaemon(True) + thread.start() diff --git a/resources/lib/plexbmchelper/listener.py b/resources/lib/plexbmchelper/listener.py index 2a03a432..d4aa46bc 100644 --- a/resources/lib/plexbmchelper/listener.py +++ b/resources/lib/plexbmchelper/listener.py @@ -9,7 +9,6 @@ from urlparse import urlparse, parse_qs from xbmc import sleep from companion import process_command -from utils import window import json_rpc as js from clientinfo import getXArgsDeviceInfo import variables as v @@ -154,7 +153,7 @@ class MyHandler(BaseHTTPRequestHandler): sub_mgr.remove_subscriber(uuid) else: # Throw it to companion.py - process_command(request_path, params, self.server.queue) + process_command(request_path, params) self.response('', getXArgsDeviceInfo(include_token=False)) @@ -164,7 +163,7 @@ class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): """ daemon_threads = True - def __init__(self, client, subscription_manager, queue, *args, **kwargs): + def __init__(self, client, subscription_manager, *args, **kwargs): """ client: Class handle to plexgdm.plexgdm. We can thus ask for an up-to- date serverlist without instantiating anything @@ -173,5 +172,4 @@ class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): """ self.client = client self.subscription_manager = subscription_manager - self.queue = queue HTTPServer.__init__(self, *args, **kwargs) diff --git a/resources/lib/plexbmchelper/subscribers.py b/resources/lib/plexbmchelper/subscribers.py index aea7e0cd..3ba4ebed 100644 --- a/resources/lib/plexbmchelper/subscribers.py +++ b/resources/lib/plexbmchelper/subscribers.py @@ -10,6 +10,7 @@ from utils import window, kodi_time_to_millis, Lock_Function import state import variables as v import json_rpc as js +import playqueue as PQ ############################################################################### @@ -111,7 +112,7 @@ class SubscriptionMgr(object): """ Manages Plex companion subscriptions """ - def __init__(self, request_mgr, player, mgr): + def __init__(self, request_mgr, player): self.serverlist = [] self.subscribers = {} self.info = {} @@ -124,11 +125,8 @@ class SubscriptionMgr(object): self.lastplayers = {} self.xbmcplayer = player - self.playqueue = mgr.playqueue self.request_mgr = request_mgr - - def _server_by_host(self, host): if len(self.serverlist) == 1: return self.serverlist[0] @@ -180,7 +178,7 @@ class SubscriptionMgr(object): def _timeline_dict(self, player, ptype): playerid = player['playerid'] info = state.PLAYER_STATES[playerid] - playqueue = self.playqueue.playqueues[playerid] + playqueue = PQ.PLAYQUEUES[playerid] pos = info['position'] try: item = playqueue.items[pos] @@ -284,7 +282,7 @@ class SubscriptionMgr(object): stream_type: 'video', 'audio', 'subtitle' """ - playqueue = self.playqueue.playqueues[playerid] + playqueue = PQ.PLAYQUEUES[playerid] info = state.PLAYER_STATES[playerid] return playqueue.items[info['position']].plex_stream_index( info[STREAM_DETAILS[stream_type]]['index'], stream_type) @@ -306,7 +304,7 @@ class SubscriptionMgr(object): """ for player in players.values(): info = state.PLAYER_STATES[player['playerid']] - playqueue = self.playqueue.playqueues[player['playerid']] + playqueue = PQ.PLAYQUEUES[player['playerid']] try: item = playqueue.items[info['position']] except IndexError: @@ -362,7 +360,7 @@ class SubscriptionMgr(object): def _get_pms_params(self, playerid): info = state.PLAYER_STATES[playerid] - playqueue = self.playqueue.playqueues[playerid] + playqueue = PQ.PLAYQUEUES[playerid] try: item = playqueue.items[info['position']] except IndexError: @@ -386,7 +384,7 @@ class SubscriptionMgr(object): def _send_pms_notification(self, playerid, params): serv = self._server_by_host(self.server) - playqueue = self.playqueue.playqueues[playerid] + playqueue = PQ.PLAYQUEUES[playerid] xargs = params_pms() xargs.update(params) if state.PLEX_TRANSIENT_TOKEN: diff --git a/resources/lib/state.py b/resources/lib/state.py index a9dc091c..a964ee51 100644 --- a/resources/lib/state.py +++ b/resources/lib/state.py @@ -75,6 +75,13 @@ PLEX_USER_ID = None # another user playing something! Token identifies user PLEX_TRANSIENT_TOKEN = None +# Plex Companion Queue() +COMPANION_QUEUE = None +# Command Pipeline Queue() +COMMAND_PIPELINE_QUEUE = None +# Websocket_client queue to communicate with librarysync +WEBSOCKET_QUEUE = None + # Kodi player states - here, initial values are set PLAYER_STATES = { 1: { @@ -117,10 +124,6 @@ PLAYER_STATES = { # paths for playback (since we're not receiving a Kodi id) PLEX_IDS = {} PLAYED_INFO = {} -# Former playbackProps; used by playbackutils.py and set to True if initial -# playback setup has been done (and playbackutils will be called again -# subsequently) -PLAYBACK_SETUP_DONE = False # Kodi webserver details WEBSERVER_PORT = 8080 diff --git a/resources/lib/userclient.py b/resources/lib/userclient.py index 17104d63..9e94598a 100644 --- a/resources/lib/userclient.py +++ b/resources/lib/userclient.py @@ -30,10 +30,8 @@ class UserClient(Thread): # Borg - multiple instances, shared state __shared_state = {} - def __init__(self, callback=None): + def __init__(self): self.__dict__ = self.__shared_state - if callback is not None: - self.mgr = callback self.auth = True self.retry = 0 diff --git a/resources/lib/websocket_client.py b/resources/lib/websocket_client.py index 748edfc0..dc42cb21 100644 --- a/resources/lib/websocket_client.py +++ b/resources/lib/websocket_client.py @@ -6,7 +6,6 @@ import websocket from json import loads import xml.etree.ElementTree as etree from threading import Thread -from Queue import Queue from ssl import CERT_NONE from xbmc import sleep @@ -165,9 +164,6 @@ class PMS_Websocket(WebSocket): """ Websocket connection with the PMS for Plex Companion """ - # Communication with librarysync - queue = Queue() - def getUri(self): server = window('pms_server') # Get the appropriate prefix for the websocket @@ -221,7 +217,7 @@ class PMS_Websocket(WebSocket): % self.__class__.__name__) else: # Put PMS message on queue and let libsync take care of it - self.queue.put(message) + state.WEBSOCKET_QUEUE.put(message) def IOError_response(self): log.warn("Repeatedly could not connect to PMS, " @@ -271,8 +267,7 @@ class Alexa_Websocket(WebSocket): % self.__class__.__name__) return process_command(message.attrib['path'][1:], - message.attrib, - queue=self.mgr.plexCompanion.queue) + message.attrib) def IOError_response(self): pass diff --git a/service.py b/service.py index 06dd1ab9..246c2daa 100644 --- a/service.py +++ b/service.py @@ -36,7 +36,6 @@ from librarysync import LibrarySync import videonodes from websocket_client import PMS_Websocket, Alexa_Websocket import downloadutils -from playqueue import Playqueue import clientinfo import PlexAPI @@ -80,14 +79,12 @@ class Service(): ws = None library = None plexCompanion = None - playqueue = None user_running = False ws_running = False alexa_running = False library_running = False plexCompanion_running = False - playqueue_running = False kodimonitor_running = False playback_starter_running = False image_cache_thread_running = False @@ -145,21 +142,20 @@ class Service(): monitor = self.monitor kodiProfile = v.KODI_PROFILE - # Detect playback start early on - self.command_pipeline = Monitor_Window(self) - self.command_pipeline.start() - # Server auto-detect initialsetup.InitialSetup().setup() + # Detect playback start early on + self.command_pipeline = Monitor_Window() + self.command_pipeline.start() + # Initialize important threads, handing over self for callback purposes - self.user = UserClient(self) - self.ws = PMS_Websocket(self) - self.alexa = Alexa_Websocket(self) - self.library = LibrarySync(self) - self.plexCompanion = PlexCompanion(self) - self.playqueue = Playqueue(self) - self.playback_starter = Playback_Starter(self) + self.user = UserClient() + self.ws = PMS_Websocket() + self.alexa = Alexa_Websocket() + self.library = LibrarySync() + self.plexCompanion = PlexCompanion() + self.playback_starter = Playback_Starter() if settings('enableTextureCache') == "true": self.image_cache_thread = Image_Cache_Thread() @@ -200,11 +196,7 @@ class Service(): time=2000, sound=False) # Start monitoring kodi events - self.kodimonitor_running = KodiMonitor(self) - # Start playqueue client - if not self.playqueue_running: - self.playqueue_running = True - self.playqueue.start() + self.kodimonitor_running = KodiMonitor() # Start the Websocket Client if not self.ws_running: self.ws_running = True