Revamp playback start, part 6
This commit is contained in:
parent
510952f9de
commit
cfff75926a
5 changed files with 93 additions and 93 deletions
|
@ -415,6 +415,10 @@ class InitialSetup():
|
|||
# Disable cleaning of library - not compatible with PKC
|
||||
xml.set_setting(['videolibrary', 'cleanonupdate'],
|
||||
value='false')
|
||||
# Set completely watched point same as plex (and not 92%)
|
||||
xml.set_setting(['video', 'ignorepercentatend'], value='10')
|
||||
xml.set_setting(['video', 'playcountminimumpercent'],
|
||||
value='90')
|
||||
reboot = xml.write_xml
|
||||
except etree.ParseError:
|
||||
cache = None
|
||||
|
|
|
@ -14,6 +14,7 @@ from utils import window, settings, plex_command, thread_methods
|
|||
from PlexFunctions import scrobble
|
||||
from kodidb_functions import kodiid_from_filename
|
||||
from plexbmchelper.subscribers import LOCKER
|
||||
from playback import playback_triage
|
||||
import playqueue as PQ
|
||||
import json_rpc as js
|
||||
import playlist_func as PL
|
||||
|
@ -60,6 +61,7 @@ class KodiMonitor(Monitor):
|
|||
Monitor.__init__(self)
|
||||
for playerid in state.PLAYER_STATES:
|
||||
state.PLAYER_STATES[playerid] = dict(state.PLAYSTATE)
|
||||
state.OLD_PLAYER_STATES[playerid] = dict(state.PLAYSTATE)
|
||||
LOG.info("Kodi monitor started.")
|
||||
|
||||
def onScanStarted(self, library):
|
||||
|
@ -143,32 +145,34 @@ class KodiMonitor(Monitor):
|
|||
# Manually marking as watched/unwatched
|
||||
playcount = data.get('playcount')
|
||||
item = data.get('item')
|
||||
if playcount is None or item is None:
|
||||
return
|
||||
try:
|
||||
kodiid = item['id']
|
||||
item_type = item['type']
|
||||
except (KeyError, TypeError):
|
||||
LOG.info("Item is invalid for playstate update.")
|
||||
return
|
||||
# Send notification to the server.
|
||||
with plexdb.Get_Plex_DB() as plexcur:
|
||||
plex_dbitem = plexcur.getItem_byKodiId(kodiid, item_type)
|
||||
try:
|
||||
itemid = plex_dbitem[0]
|
||||
except TypeError:
|
||||
LOG.error("Could not find itemid in plex database for a "
|
||||
"video library update")
|
||||
else:
|
||||
# Send notification to the server.
|
||||
with plexdb.Get_Plex_DB() as plexcur:
|
||||
plex_dbitem = plexcur.getItem_byKodiId(kodiid, item_type)
|
||||
try:
|
||||
itemid = plex_dbitem[0]
|
||||
except TypeError:
|
||||
LOG.error("Could not find itemid in plex database for a "
|
||||
"video library update")
|
||||
# Stop from manually marking as watched unwatched, with
|
||||
# actual playback.
|
||||
if window('plex_skipWatched%s' % itemid) == "true":
|
||||
# property is set in player.py
|
||||
window('plex_skipWatched%s' % itemid, clear=True)
|
||||
else:
|
||||
# Stop from manually marking as watched unwatched, with
|
||||
# actual playback.
|
||||
if window('plex_skipWatched%s' % itemid) == "true":
|
||||
# property is set in player.py
|
||||
window('plex_skipWatched%s' % itemid, clear=True)
|
||||
# notify the server
|
||||
if playcount > 0:
|
||||
scrobble(itemid, 'watched')
|
||||
else:
|
||||
# notify the server
|
||||
if playcount > 0:
|
||||
scrobble(itemid, 'watched')
|
||||
else:
|
||||
scrobble(itemid, 'unwatched')
|
||||
scrobble(itemid, 'unwatched')
|
||||
elif method == "VideoLibrary.OnRemove":
|
||||
pass
|
||||
elif method == "System.OnSleep":
|
||||
|
@ -202,6 +206,21 @@ class KodiMonitor(Monitor):
|
|||
Will NOT be called if playback initiated by Kodi widgets
|
||||
"""
|
||||
playqueue = PQ.PLAYQUEUES[data['playlistid']]
|
||||
# Kodi remembers the last setResolvedUrl - which is empty in our case
|
||||
kodi_item = js.get_item(data['playlistid'])
|
||||
LOG.debug('kodi_item: %s', kodi_item)
|
||||
# if kodi_item.get('file') == '':
|
||||
# LOG.info('Detected re-start of playback of last item')
|
||||
# old = state.OLD_PLAYER_STATES[data['playlistid']]
|
||||
# kwargs = {
|
||||
# 'plex_id': old['plex_id'],
|
||||
# 'plex_type': old['plex_type'],
|
||||
# 'path': old['file'],
|
||||
# 'resolve': False
|
||||
# }
|
||||
# thread = Thread(target=playback_triage, kwargs=kwargs)
|
||||
# thread.start()
|
||||
# return
|
||||
# Have we initiated the playqueue already? If not, ignore this
|
||||
if not playqueue.items:
|
||||
LOG.debug('Playqueue not initiated - ignoring')
|
||||
|
@ -211,11 +230,10 @@ class KodiMonitor(Monitor):
|
|||
LOG.debug('PKC added this item to the playqueue - ignoring')
|
||||
return
|
||||
# Check whether we even need to update our known playqueue
|
||||
kodi_playqueue = js.playlist_get_items(data['playlistid'])
|
||||
if playqueue.old_kodi_pl == kodi_playqueue:
|
||||
# We already know the latest playqueue (e.g. because Plex
|
||||
# initiated playback)
|
||||
return
|
||||
# if playqueue.old_kodi_pl == kodi_playqueue:
|
||||
# # We already know the latest playqueue (e.g. because Plex
|
||||
# # initiated playback)
|
||||
# return
|
||||
# Playlist has been updated; need to tell Plex about it
|
||||
if playqueue.id is None:
|
||||
PL.init_Plex_playlist(playqueue, kodi_item=data['item'])
|
||||
|
@ -224,7 +242,7 @@ class KodiMonitor(Monitor):
|
|||
data['position'],
|
||||
kodi_item=data['item'])
|
||||
# Make sure that we won't re-add this item
|
||||
playqueue.old_kodi_pl = kodi_playqueue
|
||||
# playqueue.old_kodi_pl = kodi_playqueue
|
||||
|
||||
@LOCKER.lockthis
|
||||
def _playlist_onremove(self, data):
|
||||
|
|
|
@ -29,7 +29,7 @@ LOG = getLogger("PLEX." + __name__)
|
|||
|
||||
|
||||
@LOCKER.lockthis
|
||||
def playback_triage(plex_id=None, plex_type=None, path=None):
|
||||
def playback_triage(plex_id=None, plex_type=None, path=None, resolve=True):
|
||||
"""
|
||||
Hit this function for addon path playback, Plex trailers, etc.
|
||||
Will setup playback first, then on second call complete playback.
|
||||
|
@ -40,6 +40,10 @@ def playback_triage(plex_id=None, plex_type=None, path=None):
|
|||
If trailers or additional (movie-)parts are added, default.py is released
|
||||
and a completely new player instance is called with a new playlist. This
|
||||
circumvents most issues with Kodi & playqueues
|
||||
|
||||
Set resolve to False if you do not want setResolvedUrl to be called on
|
||||
the first pass - e.g. if you're calling this function from the original
|
||||
service.py Python instance
|
||||
"""
|
||||
LOG.info('playback_triage called with plex_id %s, plex_type %s, path %s',
|
||||
plex_id, plex_type, path)
|
||||
|
@ -61,9 +65,10 @@ def playback_triage(plex_id=None, plex_type=None, path=None):
|
|||
playqueue.items[pos]
|
||||
except IndexError:
|
||||
# Release our default.py before starting our own Kodi player instance
|
||||
result = Playback_Successful()
|
||||
result.listitem = PKC_ListItem()
|
||||
pickle_me(result)
|
||||
if resolve is True:
|
||||
result = Playback_Successful()
|
||||
result.listitem = PKC_ListItem(path='PKC_Dummy_Path')
|
||||
pickle_me(result)
|
||||
playback_init(plex_id, plex_type, playqueue)
|
||||
else:
|
||||
# kick off playback on second pass
|
||||
|
|
|
@ -5,10 +5,8 @@ from logging import getLogger
|
|||
|
||||
from xbmc import Player
|
||||
|
||||
from utils import window, DateToKodi, getUnixTimestamp, kodi_time_to_millis
|
||||
from utils import window
|
||||
from downloadutils import DownloadUtils as DU
|
||||
import plexdb_functions as plexdb
|
||||
import kodidb_functions as kodidb
|
||||
from plexbmchelper.subscribers import LOCKER
|
||||
import variables as v
|
||||
import state
|
||||
|
@ -20,6 +18,35 @@ LOG = getLogger("PLEX." + __name__)
|
|||
###############################################################################
|
||||
|
||||
|
||||
@LOCKER.lockthis
|
||||
def playback_cleanup():
|
||||
"""
|
||||
PKC cleanup after playback ends/is stopped
|
||||
"""
|
||||
# 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
|
||||
for item in ('plex_customplaylist',
|
||||
'plex_customplaylist.seektime',
|
||||
'plex_forcetranscode'):
|
||||
window(item, clear=True)
|
||||
for playerid in state.ACTIVE_PLAYERS:
|
||||
status = state.PLAYER_STATES[playerid]
|
||||
# Remember the last played item later
|
||||
state.OLD_PLAYER_STATES[playerid] = dict(status)
|
||||
# Stop transcoding
|
||||
if status['playmethod'] == 'Transcode':
|
||||
LOG.info('Tell the PMS to stop transcoding')
|
||||
DU().downloadUrl(
|
||||
'{server}/video/:/transcode/universal/stop',
|
||||
parameters={'session': v.PKC_MACHINE_IDENTIFIER})
|
||||
# Reset the player's status
|
||||
status = dict(state.PLAYSTATE)
|
||||
# As all playback has halted, reset the players that have been active
|
||||
state.ACTIVE_PLAYERS = []
|
||||
LOG.info('Finished PKC playback cleanup')
|
||||
|
||||
|
||||
class PKC_Player(Player):
|
||||
def __init__(self):
|
||||
Player.__init__(self)
|
||||
|
@ -54,71 +81,11 @@ class PKC_Player(Player):
|
|||
Will be called when playback is stopped by the user
|
||||
"""
|
||||
LOG.info("ONPLAYBACK_STOPPED")
|
||||
self.cleanup_playback()
|
||||
playback_cleanup()
|
||||
|
||||
def onPlayBackEnded(self):
|
||||
"""
|
||||
Will be called when playback ends due to the media file being finished
|
||||
"""
|
||||
LOG.info("ONPLAYBACK_ENDED")
|
||||
self.cleanup_playback()
|
||||
|
||||
@LOCKER.lockthis
|
||||
def cleanup_playback(self):
|
||||
"""
|
||||
PKC cleanup after playback ends/is stopped
|
||||
"""
|
||||
# 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
|
||||
for item in ('plex_currently_playing_itemid',
|
||||
'plex_customplaylist',
|
||||
'plex_customplaylist.seektime',
|
||||
'plex_forcetranscode'):
|
||||
window(item, clear=True)
|
||||
for playerid in state.ACTIVE_PLAYERS:
|
||||
status = state.PLAYER_STATES[playerid]
|
||||
# Check whether we need to mark an item as completely watched
|
||||
if not status['kodi_id'] or not status['plex_id']:
|
||||
LOG.info('No PKC info safed for the element just played by Kodi'
|
||||
' player %s', playerid)
|
||||
continue
|
||||
# Stop transcoding
|
||||
if status['playmethod'] == 'Transcode':
|
||||
LOG.info('Tell the PMS to stop transcoding')
|
||||
DU().downloadUrl(
|
||||
'{server}/video/:/transcode/universal/stop',
|
||||
parameters={'session': v.PKC_MACHINE_IDENTIFIER})
|
||||
if status['plex_type'] == v.PLEX_TYPE_SONG:
|
||||
LOG.debug('Song has been played, not cleaning up playstate')
|
||||
continue
|
||||
resume = kodi_time_to_millis(status['time'])
|
||||
runtime = kodi_time_to_millis(status['totaltime'])
|
||||
LOG.info('Item playback progress %s out of %s', resume, runtime)
|
||||
if not resume or not runtime:
|
||||
continue
|
||||
complete = float(resume) / float(runtime)
|
||||
LOG.info("Percent complete: %s. Mark played at: %s",
|
||||
complete, v.MARK_PLAYED_AT)
|
||||
if complete >= v.MARK_PLAYED_AT:
|
||||
# Tell Kodi that we've finished watching (Plex knows)
|
||||
with plexdb.Get_Plex_DB() as plex_db:
|
||||
plex_dbitem = plex_db.getItem_byId(status['plex_id'])
|
||||
file_id = plex_dbitem[1] if plex_dbitem else None
|
||||
if file_id is None:
|
||||
LOG.error('No file_id found for %s', status)
|
||||
continue
|
||||
with kodidb.GetKodiDB('video') as kodi_db:
|
||||
kodi_db.addPlaystate(
|
||||
file_id,
|
||||
None,
|
||||
None,
|
||||
status['playcount'] + 1,
|
||||
DateToKodi(getUnixTimestamp()))
|
||||
LOG.info('Marked plex element %s as completely watched',
|
||||
status['plex_id'])
|
||||
# As all playback has halted, reset the players that have been active
|
||||
state.ACTIVE_PLAYERS = []
|
||||
for playerid in state.PLAYER_STATES:
|
||||
state.PLAYER_STATES[playerid] = dict(state.PLAYSTATE)
|
||||
LOG.info('Finished PKC playback cleanup')
|
||||
playback_cleanup()
|
||||
|
|
|
@ -91,6 +91,12 @@ PLAYER_STATES = {
|
|||
2: {},
|
||||
3: {}
|
||||
}
|
||||
# The LAST playstate once playback is finished
|
||||
OLD_PLAYER_STATES = {
|
||||
1: {},
|
||||
2: {},
|
||||
3: {}
|
||||
}
|
||||
# "empty" dict for the PLAYER_STATES above
|
||||
PLAYSTATE = {
|
||||
'type': None,
|
||||
|
|
Loading…
Reference in a new issue