Revamp monitor
This commit is contained in:
parent
ad6c160524
commit
643e6171c4
1 changed files with 110 additions and 102 deletions
|
@ -25,6 +25,13 @@ STRINGS = (utils.lang(12021).encode('utf-8'),
|
|||
utils.lang(12023).encode('utf-8'))
|
||||
|
||||
|
||||
class MonitorError(Exception):
|
||||
"""
|
||||
Exception we raise for all errors associated with xbmc.Monitor
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class KodiMonitor(xbmc.Monitor):
|
||||
"""
|
||||
PKC implementation of the Kodi Monitor class. Invoke only once.
|
||||
|
@ -32,11 +39,14 @@ class KodiMonitor(xbmc.Monitor):
|
|||
def __init__(self):
|
||||
self._already_slept = False
|
||||
self.hack_replay = None
|
||||
# Info to the currently playing item
|
||||
self.playerid = None
|
||||
self.playlistid = None
|
||||
xbmc.Monitor.__init__(self)
|
||||
self.playqueue = None
|
||||
for playerid in app.PLAYSTATE.player_states:
|
||||
app.PLAYSTATE.player_states[playerid] = copy.deepcopy(app.PLAYSTATE.template)
|
||||
app.PLAYSTATE.old_player_states[playerid] = copy.deepcopy(app.PLAYSTATE.template)
|
||||
xbmc.Monitor.__init__(self)
|
||||
LOG.info("Kodi monitor started.")
|
||||
|
||||
def onScanStarted(self, library):
|
||||
|
@ -74,7 +84,7 @@ class KodiMonitor(xbmc.Monitor):
|
|||
|
||||
if method == "Player.OnPlay":
|
||||
with app.APP.lock_playqueues:
|
||||
self.PlayBackStart(data)
|
||||
self.on_play(data)
|
||||
elif method == "Player.OnStop":
|
||||
# Should refresh our video nodes, e.g. on deck
|
||||
# xbmc.executebuiltin('ReloadSkin()')
|
||||
|
@ -279,7 +289,88 @@ class KodiMonitor(xbmc.Monitor):
|
|||
json_item.get('type'),
|
||||
json_item.get('file'))
|
||||
|
||||
def PlayBackStart(self, data):
|
||||
def _get_playerid(self, data):
|
||||
"""
|
||||
Sets self.playerid with an int 0, 1 [or 2] or raises MonitorError
|
||||
0: usually video
|
||||
1: usually audio
|
||||
"""
|
||||
try:
|
||||
self.playerid = data['player']['playerid']
|
||||
except (TypeError, KeyError):
|
||||
LOG.info('Aborting playback report - data invalid for updates: %s',
|
||||
data)
|
||||
raise MonitorError()
|
||||
if self.playerid == -1:
|
||||
# Kodi might return -1 for "last player"
|
||||
try:
|
||||
self.playerid = js.get_player_ids()[0]
|
||||
except IndexError:
|
||||
LOG.error('Coud not get playerid for data: %s', data)
|
||||
raise MonitorError()
|
||||
|
||||
def _check_playing_item(self, data):
|
||||
"""
|
||||
Returns a PF.Playlist_Item() for the currently playing item
|
||||
Raises MonitorError or IndexError if we need to init the PKC playqueue
|
||||
"""
|
||||
info = js.get_player_props(self.playerid)
|
||||
LOG.debug('Current info for player %s: %s', self.playerid, info)
|
||||
position = info['position'] if info['position'] != -1 else 0
|
||||
kodi_playlist = js.playlist_get_items(self.playerid)
|
||||
LOG.debug('Current Kodi playlist: %s', kodi_playlist)
|
||||
kodi_item = PL.playlist_item_from_kodi(kodi_playlist[position])
|
||||
if (position == 1 and
|
||||
len(kodi_playlist) == len(self.playqueue.items) + 1 and
|
||||
kodi_playlist[0].get('type') == 'unknown' and
|
||||
kodi_playlist[0].get('file') and
|
||||
kodi_playlist[0].get('file').startswith('http://127.0.0.1')):
|
||||
if kodi_item == self.playqueue.items[0]:
|
||||
# Delete the very first item that we used to start playback:
|
||||
# {
|
||||
# u'title': u'',
|
||||
# u'type': u'unknown',
|
||||
# u'file': u'http://127.0.0.1:57578/plex/kodi/....',
|
||||
# u'label': u''
|
||||
# }
|
||||
LOG.debug('Deleting the very first playqueue item')
|
||||
js.playlist_remove(self.playqueue.playlistid, 0)
|
||||
position = 0
|
||||
else:
|
||||
LOG.debug('Different item in PKC playlist: %s vs. %s',
|
||||
self.playqueue.items[0], kodi_item)
|
||||
raise MonitorError()
|
||||
elif kodi_item != self.playqueue.items[position]:
|
||||
LOG.debug('Different playqueue items: %s vs. %s ',
|
||||
kodi_item, self.playqueue.items[position])
|
||||
raise MonitorError()
|
||||
# Return the PKC playqueue item - contains more info
|
||||
return self.playqueue.items[position]
|
||||
|
||||
def _load_playerstate(self, item):
|
||||
"""
|
||||
Pass in a PF.Playlist_Item(). Will then set the currently playing
|
||||
state with app.PLAYSTATE.player_states[self.playerid]
|
||||
"""
|
||||
if self.playqueue.id:
|
||||
container_key = '/playQueues/%s' % self.playqueue.id
|
||||
else:
|
||||
container_key = '/library/metadata/%s' % item.plex_id
|
||||
status = app.PLAYSTATE.player_states[self.playerid]
|
||||
# Remember that this player has been active
|
||||
app.PLAYSTATE.active_players.add(self.playerid)
|
||||
status.update(js.get_player_props(self.playerid))
|
||||
status['container_key'] = container_key
|
||||
status['file'] = item.file
|
||||
status['kodi_id'] = item.kodi_id
|
||||
status['kodi_type'] = item.kodi_type
|
||||
status['plex_id'] = item.plex_id
|
||||
status['plex_type'] = item.plex_type
|
||||
status['playmethod'] = item.playmethod
|
||||
status['playcount'] = item.playcount
|
||||
LOG.debug('Set the player state: %s', status)
|
||||
|
||||
def on_play(self, data):
|
||||
"""
|
||||
Called whenever playback is started. Example data:
|
||||
{
|
||||
|
@ -288,87 +379,26 @@ class KodiMonitor(xbmc.Monitor):
|
|||
}
|
||||
Unfortunately when using Widgets, Kodi doesn't tell us shit
|
||||
"""
|
||||
# Some init
|
||||
self._already_slept = False
|
||||
self.playlistid = None
|
||||
self.playerid = None
|
||||
# Get the type of media we're playing
|
||||
try:
|
||||
playerid = data['player']['playerid']
|
||||
except (TypeError, KeyError):
|
||||
LOG.info('Aborting playback report - item invalid for updates %s',
|
||||
data)
|
||||
self._get_playerid(data)
|
||||
except MonitorError:
|
||||
return
|
||||
kodi_id = data['item'].get('id') if 'item' in data else None
|
||||
kodi_type = data['item'].get('type') if 'item' in data else None
|
||||
path = data['item'].get('file') if 'item' in data else None
|
||||
if playerid == -1:
|
||||
# Kodi might return -1 for "last player"
|
||||
# Getting the playerid is really a PITA
|
||||
self.playqueue = PQ.PLAYQUEUES[self.playerid]
|
||||
LOG.debug('Current PKC playqueue: %s', self.playqueue)
|
||||
item = None
|
||||
try:
|
||||
playerid = js.get_player_ids()[0]
|
||||
except IndexError:
|
||||
# E.g. Kodi 18 doesn't tell us anything useful
|
||||
if kodi_type in v.KODI_VIDEOTYPES:
|
||||
playlist_type = v.KODI_TYPE_VIDEO_PLAYLIST
|
||||
elif kodi_type in v.KODI_AUDIOTYPES:
|
||||
playlist_type = v.KODI_TYPE_AUDIO_PLAYLIST
|
||||
else:
|
||||
LOG.error('Unexpected type %s, data %s', kodi_type, data)
|
||||
return
|
||||
playerid = js.get_playlist_id(playlist_type)
|
||||
if not playerid:
|
||||
LOG.error('Coud not get playerid for data %s', data)
|
||||
return
|
||||
playqueue = PQ.PLAYQUEUES[playerid]
|
||||
info = js.get_player_props(playerid)
|
||||
if playqueue.kodi_playlist_playback:
|
||||
# Kodi will tell us the wrong position - of the playlist, not the
|
||||
# playqueue, when user starts playing from a playlist :-(
|
||||
pos = 0
|
||||
LOG.debug('Detected playback from a Kodi playlist')
|
||||
else:
|
||||
pos = info['position'] if info['position'] != -1 else 0
|
||||
LOG.debug('Detected position %s for %s', pos, playqueue)
|
||||
status = app.PLAYSTATE.player_states[playerid]
|
||||
try:
|
||||
item = playqueue.items[pos]
|
||||
LOG.debug('PKC playqueue item is: %s', item)
|
||||
except IndexError:
|
||||
# PKC playqueue not yet initialized
|
||||
LOG.debug('Position %s not in PKC playqueue yet', pos)
|
||||
initialize = True
|
||||
else:
|
||||
if not kodi_id:
|
||||
kodi_id, kodi_type, path = self._json_item(playerid)
|
||||
if kodi_id and item.kodi_id:
|
||||
if item.kodi_id != kodi_id or item.kodi_type != kodi_type:
|
||||
LOG.debug('Detected different Kodi id')
|
||||
initialize = True
|
||||
else:
|
||||
initialize = False
|
||||
else:
|
||||
# E.g. clips set-up previously with no Kodi DB entry
|
||||
if not path:
|
||||
kodi_id, kodi_type, path = self._json_item(playerid)
|
||||
if path == '':
|
||||
LOG.debug('Detected empty path: aborting playback report')
|
||||
return
|
||||
if item.file != path:
|
||||
# Clips will get a new path
|
||||
LOG.debug('Detected different path')
|
||||
try:
|
||||
tmp_plex_id = int(utils.REGEX_PLEX_ID.findall(path)[0])
|
||||
except IndexError:
|
||||
LOG.debug('No Plex id in path, need to init playqueue')
|
||||
initialize = True
|
||||
else:
|
||||
if tmp_plex_id == item.plex_id:
|
||||
LOG.debug('Detected different path for the same id')
|
||||
initialize = False
|
||||
else:
|
||||
LOG.debug('Different Plex id, need to init playqueue')
|
||||
initialize = True
|
||||
else:
|
||||
initialize = False
|
||||
if initialize:
|
||||
item = self._check_playing_item(data)
|
||||
except (MonitorError, IndexError):
|
||||
LOG.debug('Detected that we need to initialize the PKC playqueue')
|
||||
|
||||
if not item:
|
||||
# Initialize the PKC playqueue
|
||||
# Yet TODO
|
||||
LOG.debug('Need to initialize Plex and PKC playqueue')
|
||||
if not kodi_id or not kodi_type:
|
||||
kodi_id, kodi_type, path = self._json_item(playerid)
|
||||
|
@ -388,29 +418,7 @@ class KodiMonitor(xbmc.Monitor):
|
|||
container_key = '/playQueues/%s' % container_key
|
||||
elif plex_id is not None:
|
||||
container_key = '/library/metadata/%s' % plex_id
|
||||
else:
|
||||
LOG.debug('No need to initialize playqueues')
|
||||
kodi_id = item.kodi_id
|
||||
kodi_type = item.kodi_type
|
||||
plex_id = item.plex_id
|
||||
plex_type = item.plex_type
|
||||
if playqueue.id:
|
||||
container_key = '/playQueues/%s' % playqueue.id
|
||||
else:
|
||||
container_key = '/library/metadata/%s' % plex_id
|
||||
# Remember that this player has been active
|
||||
app.PLAYSTATE.active_players.add(playerid)
|
||||
status.update(info)
|
||||
LOG.debug('Set the Plex container_key to: %s', container_key)
|
||||
status['container_key'] = container_key
|
||||
status['file'] = path
|
||||
status['kodi_id'] = kodi_id
|
||||
status['kodi_type'] = kodi_type
|
||||
status['plex_id'] = plex_id
|
||||
status['plex_type'] = plex_type
|
||||
status['playmethod'] = item.playmethod
|
||||
status['playcount'] = item.playcount
|
||||
LOG.debug('Set the player state: %s', status)
|
||||
self._load_playerstate(item)
|
||||
|
||||
|
||||
def _playback_cleanup(ended=False):
|
||||
|
|
Loading…
Reference in a new issue