This commit is contained in:
croneter 2017-12-14 17:39:50 +01:00
parent bb0ba08329
commit 5f4016e22e
2 changed files with 52 additions and 45 deletions

View file

@ -1,15 +1,13 @@
# -*- coding: utf-8 -*- """
PKC Kodi Monitoring implementation
############################################################################### """
from logging import getLogger from logging import getLogger
from json import loads from json import loads
from xbmc import Monitor, Player, sleep from xbmc import Monitor, Player, sleep
from downloadutils import DownloadUtils
import plexdb_functions as plexdb import plexdb_functions as plexdb
from utils import window, settings, CatchExceptions, tryDecode, tryEncode, \ from utils import window, settings, CatchExceptions, plex_command
plex_command
from PlexFunctions import scrobble from PlexFunctions import scrobble
from kodidb_functions import kodiid_from_filename from kodidb_functions import kodiid_from_filename
from PlexAPI import API from PlexAPI import API
@ -19,7 +17,7 @@ import variables as v
############################################################################### ###############################################################################
log = getLogger("PLEX."+__name__) LOG = getLogger("PLEX." + __name__)
# settings: window-variable # settings: window-variable
WINDOW_SETTINGS = { WINDOW_SETTINGS = {
@ -48,22 +46,29 @@ STATE_SETTINGS = {
class KodiMonitor(Monitor): class KodiMonitor(Monitor):
"""
PKC implementation of the Kodi Monitor class. Invoke only once.
"""
def __init__(self, callback): def __init__(self, callback):
self.mgr = callback self.mgr = callback
self.doUtils = DownloadUtils().downloadUrl
self.xbmcplayer = Player() self.xbmcplayer = Player()
self.playqueue = self.mgr.playqueue self.playqueue = self.mgr.playqueue
Monitor.__init__(self) Monitor.__init__(self)
log.info("Kodi monitor started.") LOG.info("Kodi monitor started.")
def onScanStarted(self, library): def onScanStarted(self, library):
log.debug("Kodi library scan %s running." % library) """
Will be called when Kodi starts scanning the library
"""
LOG.debug("Kodi library scan %s running." % library)
if library == "video": if library == "video":
window('plex_kodiScan', value="true") window('plex_kodiScan', value="true")
def onScanFinished(self, library): def onScanFinished(self, library):
log.debug("Kodi library scan %s finished." % library) """
Will be called when Kodi finished scanning the library
"""
LOG.debug("Kodi library scan %s finished." % library)
if library == "video": if library == "video":
window('plex_kodiScan', clear=True) window('plex_kodiScan', clear=True)
@ -71,17 +76,17 @@ class KodiMonitor(Monitor):
""" """
Monitor the PKC settings for changes made by the user Monitor the PKC settings for changes made by the user
""" """
log.debug('PKC settings change detected') LOG.debug('PKC settings change detected')
changed = False changed = False
# Reset the window variables from the settings variables # Reset the window variables from the settings variables
for settings_value, window_value in WINDOW_SETTINGS.iteritems(): for settings_value, window_value in WINDOW_SETTINGS.iteritems():
if window(window_value) != settings(settings_value): if window(window_value) != settings(settings_value):
changed = True changed = True
log.debug('PKC window settings changed: %s is now %s' LOG.debug('PKC window settings changed: %s is now %s',
% (settings_value, settings(settings_value))) settings_value, settings(settings_value))
window(window_value, value=settings(settings_value)) window(window_value, value=settings(settings_value))
if settings_value == 'fetch_pms_item_number': if settings_value == 'fetch_pms_item_number':
log.info('Requesting playlist/nodes refresh') LOG.info('Requesting playlist/nodes refresh')
plex_command('RUN_LIB_SCAN', 'views') plex_command('RUN_LIB_SCAN', 'views')
# Reset the state variables in state.py # Reset the state variables in state.py
for settings_value, state_name in STATE_SETTINGS.iteritems(): for settings_value, state_name in STATE_SETTINGS.iteritems():
@ -92,11 +97,11 @@ class KodiMonitor(Monitor):
new = False new = False
if getattr(state, state_name) != new: if getattr(state, state_name) != new:
changed = True changed = True
log.debug('PKC state settings %s changed from %s to %s' LOG.debug('PKC state settings %s changed from %s to %s',
% (settings_value, getattr(state, state_name), new)) settings_value, getattr(state, state_name), new)
setattr(state, state_name, new) setattr(state, state_name, new)
# Special cases, overwrite all internal settings # Special cases, overwrite all internal settings
state.FULL_SYNC_INTERVALL = int(settings('fullSyncInterval'))*60 state.FULL_SYNC_INTERVALL = int(settings('fullSyncInterval')) * 60
state.BACKGROUNDSYNC_SAFTYMARGIN = int( state.BACKGROUNDSYNC_SAFTYMARGIN = int(
settings('backgroundsync_saftyMargin')) settings('backgroundsync_saftyMargin'))
state.SYNC_THREAD_NUMBER = int(settings('syncThreadNumber')) state.SYNC_THREAD_NUMBER = int(settings('syncThreadNumber'))
@ -110,10 +115,12 @@ class KodiMonitor(Monitor):
@CatchExceptions(warnuser=False) @CatchExceptions(warnuser=False)
def onNotification(self, sender, method, data): def onNotification(self, sender, method, data):
"""
Called when a bunch of different stuff happens on the Kodi side
"""
if data: if data:
data = loads(data, 'utf-8') data = loads(data, 'utf-8')
log.debug("Method: %s Data: %s" % (method, data)) LOG.debug("Method: %s Data: %s", method, data)
if method == "Player.OnPlay": if method == "Player.OnPlay":
self.PlayBackStart(data) self.PlayBackStart(data)
@ -132,7 +139,7 @@ class KodiMonitor(Monitor):
kodiid = item['id'] kodiid = item['id']
item_type = item['type'] item_type = item['type']
except (KeyError, TypeError): except (KeyError, TypeError):
log.info("Item is invalid for playstate update.") LOG.info("Item is invalid for playstate update.")
else: else:
# Send notification to the server. # Send notification to the server.
with plexdb.Get_Plex_DB() as plexcur: with plexdb.Get_Plex_DB() as plexcur:
@ -140,7 +147,7 @@ class KodiMonitor(Monitor):
try: try:
itemid = plex_dbitem[0] itemid = plex_dbitem[0]
except TypeError: except TypeError:
log.error("Could not find itemid in plex database for a " LOG.error("Could not find itemid in plex database for a "
"video library update") "video library update")
else: else:
# Stop from manually marking as watched unwatched, with # Stop from manually marking as watched unwatched, with
@ -160,7 +167,7 @@ class KodiMonitor(Monitor):
elif method == "System.OnSleep": elif method == "System.OnSleep":
# Connection is going to sleep # Connection is going to sleep
log.info("Marking the server as offline. SystemOnSleep activated.") LOG.info("Marking the server as offline. SystemOnSleep activated.")
window('plex_online', value="sleep") window('plex_online', value="sleep")
elif method == "System.OnWake": elif method == "System.OnWake":
@ -175,12 +182,12 @@ class KodiMonitor(Monitor):
plex_command('RUN_LIB_SCAN', 'full') plex_command('RUN_LIB_SCAN', 'full')
elif method == "System.OnQuit": elif method == "System.OnQuit":
log.info('Kodi OnQuit detected - shutting down') LOG.info('Kodi OnQuit detected - shutting down')
state.STOP_PKC = True state.STOP_PKC = True
def PlayBackStart(self, data): def PlayBackStart(self, data):
""" """
Called whenever a playback is started. Example data: Called whenever playback is started. Example data:
{ {
u'item': {u'type': u'movie', u'title': u''}, u'item': {u'type': u'movie', u'title': u''},
u'player': {u'playerid': 1, u'speed': 1} u'player': {u'playerid': 1, u'speed': 1}
@ -193,14 +200,14 @@ class KodiMonitor(Monitor):
kodi_type = data['item']['type'] kodi_type = data['item']['type']
playerid = data['player']['playerid'] playerid = data['player']['playerid']
except (TypeError, KeyError): except (TypeError, KeyError):
log.info('Aborting playback report - item invalid for updates %s', LOG.info('Aborting playback report - item invalid for updates %s',
data) data)
return return
json_data = js.get_item(playerid) json_data = js.get_item(playerid)
path = json_data.get('file') path = json_data.get('file')
kodi_id = json_data.get('id') kodi_id = json_data.get('id')
if not path and not kodi_id: if not path and not kodi_id:
log.info('Aborting playback report - no Kodi id or file for %s', LOG.info('Aborting playback report - no Kodi id or file for %s',
json_data) json_data)
return return
# Plex id will NOT be set with direct paths # Plex id will NOT be set with direct paths
@ -239,7 +246,7 @@ class KodiMonitor(Monitor):
# Set other stuff like volume # Set other stuff like volume
state.PLAYER_STATES[playerid]['volume'] = js.get_volume() state.PLAYER_STATES[playerid]['volume'] = js.get_volume()
state.PLAYER_STATES[playerid]['muted'] = js.get_muted() state.PLAYER_STATES[playerid]['muted'] = js.get_muted()
log.debug('Set the player state: %s', state.PLAYER_STATES[playerid]) LOG.debug('Set the player state: %s', state.PLAYER_STATES[playerid])
def StartDirectPath(self, plex_id, type, currentFile): def StartDirectPath(self, plex_id, type, currentFile):
""" """
@ -249,7 +256,7 @@ class KodiMonitor(Monitor):
try: try:
xml[0].attrib xml[0].attrib
except: except:
log.error('Did not receive a valid XML for plex_id %s.' % plex_id) LOG.error('Did not receive a valid XML for plex_id %s.' % plex_id)
return False return False
# Setup stuff, because playback was started by Kodi, not PKC # Setup stuff, because playback was started by Kodi, not PKC
api = API(xml[0]) api = API(xml[0])
@ -259,4 +266,4 @@ class KodiMonitor(Monitor):
window('plex_%s.playmethod' % currentFile, value="DirectStream") window('plex_%s.playmethod' % currentFile, value="DirectStream")
else: else:
window('plex_%s.playmethod' % currentFile, value="DirectPlay") window('plex_%s.playmethod' % currentFile, value="DirectPlay")
log.debug('Window properties set for direct paths!') LOG.debug('Window properties set for direct paths!')

View file

@ -99,7 +99,7 @@ class MyHandler(BaseHTTPRequestHandler):
elif request_path == "verify": elif request_path == "verify":
self.response("XBMC JSON connection test:\n" + self.response("XBMC JSON connection test:\n" +
js.ping()) js.ping())
elif "resources" == request_path: elif request_path == 'resources':
resp = ('%s' resp = ('%s'
'<MediaContainer>' '<MediaContainer>'
'<Player' '<Player'
@ -121,19 +121,6 @@ class MyHandler(BaseHTTPRequestHandler):
v.ADDON_VERSION)) v.ADDON_VERSION))
LOG.debug("crafted resources response: %s", resp) LOG.debug("crafted resources response: %s", resp)
self.response(resp, getXArgsDeviceInfo(include_token=False)) self.response(resp, getXArgsDeviceInfo(include_token=False))
elif "/subscribe" in request_path:
self.response(v.COMPANION_OK_MESSAGE,
getXArgsDeviceInfo(include_token=False))
protocol = params.get('protocol', False)
host = self.client_address[0]
port = params.get('port', False)
uuid = self.headers.get('X-Plex-Client-Identifier', "")
command_id = params.get('commandID', 0)
sub_mgr.add_subscriber(protocol,
host,
port,
uuid,
command_id)
elif "/poll" in request_path: elif "/poll" in request_path:
if params.get('wait', False) == '1': if params.get('wait', False) == '1':
sleep(950) sleep(950)
@ -151,6 +138,19 @@ class MyHandler(BaseHTTPRequestHandler):
'X-Plex-Client-Identifier', 'X-Plex-Client-Identifier',
'Content-Type': 'text/xml;charset=utf-8' 'Content-Type': 'text/xml;charset=utf-8'
}) })
elif "/subscribe" in request_path:
self.response(v.COMPANION_OK_MESSAGE,
getXArgsDeviceInfo(include_token=False))
protocol = params.get('protocol', False)
host = self.client_address[0]
port = params.get('port', False)
uuid = self.headers.get('X-Plex-Client-Identifier', "")
command_id = params.get('commandID', 0)
sub_mgr.add_subscriber(protocol,
host,
port,
uuid,
command_id)
elif "/unsubscribe" in request_path: elif "/unsubscribe" in request_path:
self.response(v.COMPANION_OK_MESSAGE, self.response(v.COMPANION_OK_MESSAGE,
getXArgsDeviceInfo(include_token=False)) getXArgsDeviceInfo(include_token=False))