PlexKodiConnect/resources/lib/PlexCompanion.py

214 lines
7.5 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
2016-09-03 01:20:19 +10:00
import logging
2016-12-21 02:38:04 +11:00
from threading import Thread
import Queue
2016-12-21 02:38:04 +11:00
from socket import SHUT_RDWR
2016-12-21 02:38:04 +11:00
from xbmc import sleep
2016-09-03 01:20:19 +10:00
from utils import settings, ThreadMethodsAdditionalSuspend, ThreadMethods
from plexbmchelper import listener, plexgdm, subscribers, functions, \
2016-09-03 01:20:19 +10:00
httppersist, plexsettings
2017-01-25 02:57:12 +11:00
from PlexFunctions import ParseContainerKey
2016-08-07 23:33:36 +10:00
import player
2017-01-03 01:41:38 +11:00
from entrypoint import Plex_Node
2017-01-25 02:57:12 +11:00
from variables import KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE
2016-09-03 01:20:19 +10:00
###############################################################################
2016-09-03 01:20:19 +10:00
log = logging.getLogger("PLEX."+__name__)
###############################################################################
@ThreadMethodsAdditionalSuspend('plex_serverStatus')
@ThreadMethods
2016-12-21 02:38:04 +11:00
class PlexCompanion(Thread):
2016-07-21 02:36:31 +10:00
"""
"""
2016-12-28 03:33:52 +11:00
def __init__(self, callback=None):
2016-09-03 01:20:19 +10:00
log.info("----===## Starting PlexCompanion ##===----")
2016-12-28 03:33:52 +11:00
if callback is not None:
self.mgr = callback
2016-09-03 01:20:19 +10:00
self.settings = plexsettings.getSettings()
# Start GDM for server/client discovery
self.client = plexgdm.plexgdm()
self.client.clientDetails(self.settings)
2016-09-03 01:20:19 +10:00
log.debug("Registration string is: %s "
% self.client.getClientDetails())
2016-07-24 02:06:47 +10:00
# kodi player instance
2016-08-07 23:33:36 +10:00
self.player = player.Player()
2016-07-24 02:06:47 +10:00
2016-12-21 02:38:04 +11:00
Thread.__init__(self)
def _getStartItem(self, string):
"""
Grabs the Plex id from e.g. '/library/metadata/12987'
and returns the tuple (typus, id) where typus is either 'queueId' or
'plexId' and id is the corresponding id as a string
"""
typus = 'plexId'
if string.startswith('/library/metadata'):
try:
string = string.split('/')[3]
except IndexError:
string = ''
else:
2016-09-03 01:20:19 +10:00
log.error('Unknown string! %s' % string)
return typus, string
def processTasks(self, task):
"""
2016-12-28 23:14:21 +11:00
Processes tasks picked up e.g. by Companion listener, e.g.
{'action': 'playlist',
'data': {'address': 'xyz.plex.direct',
'commandID': '7',
'containerKey': '/playQueues/6669?own=1&repeat=0&window=200',
'key': '/library/metadata/220493',
'machineIdentifier': 'xyz',
'offset': '0',
'port': '32400',
'protocol': 'https',
'token': 'transient-cd2527d1-0484-48e0-a5f7-f5caa7d591bd',
'type': 'video'}}
"""
2016-09-03 01:20:19 +10:00
log.debug('Processing: %s' % task)
data = task['data']
2017-01-03 01:41:38 +11:00
if (task['action'] == 'playlist' and
data.get('address') == 'node.plexapp.com'):
# E.g. watch later initiated by Companion
thread = Thread(target=Plex_Node,
2017-01-03 02:42:07 +11:00
args=('{server}%s' % data.get('key'),
2017-01-03 01:41:38 +11:00
data.get('offset'),
2017-01-03 02:42:07 +11:00
data.get('type'),
True),)
2017-01-03 01:41:38 +11:00
thread.setDaemon(True)
thread.start()
elif task['action'] == 'playlist':
2016-12-28 03:33:52 +11:00
# Get the playqueue ID
try:
2016-12-28 03:33:52 +11:00
_, ID, query = ParseContainerKey(data['containerKey'])
except Exception as e:
2016-09-03 01:20:19 +10:00
log.error('Exception while processing: %s' % e)
import traceback
2016-09-03 01:20:19 +10:00
log.error("Traceback:\n%s" % traceback.format_exc())
return
2016-12-28 23:14:21 +11:00
playqueue = self.mgr.playqueue.get_playqueue_from_type(
KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE[data['type']])
2017-01-03 00:07:24 +11:00
self.mgr.playqueue.update_playqueue_from_PMS(
playqueue,
ID,
repeat=query.get('repeat'),
offset=data.get('offset'))
def run(self):
httpd = False
# Cache for quicker while loops
client = self.client
threadStopped = self.threadStopped
threadSuspended = self.threadSuspended
# Start up instances
requestMgr = httppersist.RequestMgr()
jsonClass = functions.jsonClass(requestMgr, self.settings)
subscriptionManager = subscribers.SubscriptionManager(
2016-12-28 23:14:21 +11:00
jsonClass, requestMgr, self.player, self.mgr)
queue = Queue.Queue(maxsize=100)
2016-09-03 01:20:19 +10:00
if settings('plexCompanion') == 'true':
# Start up httpd
start_count = 0
while True:
try:
httpd = listener.ThreadedHTTPServer(
client,
subscriptionManager,
jsonClass,
self.settings,
queue,
('', self.settings['myport']),
listener.MyHandler)
httpd.timeout = 0.95
break
except:
2016-09-03 01:20:19 +10:00
log.error("Unable to start PlexCompanion. Traceback:")
2016-12-21 02:38:04 +11:00
import traceback
2016-09-03 01:20:19 +10:00
log.error(traceback.print_exc())
2016-12-21 02:38:04 +11:00
sleep(3000)
if start_count == 3:
2016-09-03 01:20:19 +10:00
log.error("Error: Unable to start web helper.")
httpd = False
break
start_count += 1
else:
2016-09-03 01:20:19 +10:00
log.info('User deactivated Plex Companion')
client.start_all()
message_count = 0
if httpd:
2016-12-21 02:38:04 +11:00
t = Thread(target=httpd.handle_request)
while not threadStopped():
2016-03-11 02:02:46 +11:00
# If we are not authorized, sleep
# Otherwise, we trigger a download which leads to a
# re-authorizations
while threadSuspended():
if threadStopped():
break
2016-12-21 02:38:04 +11:00
sleep(1000)
try:
message_count += 1
if httpd:
if not t.isAlive():
2016-08-11 03:03:37 +10:00
# Use threads cause the method will stall
2016-12-21 02:38:04 +11:00
t = Thread(target=httpd.handle_request)
t.start()
if message_count == 3000:
message_count = 0
if client.check_client_registration():
2016-09-03 01:20:19 +10:00
log.debug("Client is still registered")
else:
2016-09-05 01:13:28 +10:00
log.info("Client is no longer registered. "
2016-09-03 01:20:19 +10:00
"Plex Companion still running on port %s"
% self.settings['myport'])
# Get and set servers
if message_count % 30 == 0:
subscriptionManager.serverlist = client.getServerList()
subscriptionManager.notify()
if not httpd:
message_count = 0
except:
2016-09-03 01:20:19 +10:00
log.warn("Error in loop, continuing anyway. Traceback:")
2016-12-21 02:38:04 +11:00
import traceback
2016-09-03 01:20:19 +10:00
log.warn(traceback.format_exc())
# See if there's anything we need to process
try:
task = queue.get(block=False)
except Queue.Empty:
pass
else:
# Got instructions, process them
self.processTasks(task)
queue.task_done()
# Don't sleep
continue
2016-12-21 02:38:04 +11:00
sleep(20)
client.stop_all()
if httpd:
try:
2016-12-21 02:38:04 +11:00
httpd.socket.shutdown(SHUT_RDWR)
except:
pass
finally:
httpd.socket.close()
2016-09-03 01:20:19 +10:00
log.info("----===## Plex Companion stopped ##===----")