Revamp playback start, part 4
This commit is contained in:
parent
7ecaa376a2
commit
2791da9f65
6 changed files with 148 additions and 342 deletions
|
@ -1268,6 +1268,15 @@ class API():
|
||||||
res = '2000-01-01 10:00:00'
|
res = '2000-01-01 10:00:00'
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def getViewCount(self):
|
||||||
|
"""
|
||||||
|
Returns the play count for the item as an int or the int 0 if not found
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return int(self.item.attrib['viewCount'])
|
||||||
|
except (KeyError, ValueError):
|
||||||
|
return 0
|
||||||
|
|
||||||
def getUserData(self):
|
def getUserData(self):
|
||||||
"""
|
"""
|
||||||
Returns a dict with None if a value is missing
|
Returns a dict with None if a value is missing
|
||||||
|
|
|
@ -45,6 +45,7 @@ STATE_SETTINGS = {
|
||||||
'enableMusic': 'ENABLE_MUSIC',
|
'enableMusic': 'ENABLE_MUSIC',
|
||||||
'enableBackgroundSync': 'BACKGROUND_SYNC'
|
'enableBackgroundSync': 'BACKGROUND_SYNC'
|
||||||
}
|
}
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,6 +56,8 @@ class KodiMonitor(Monitor):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.xbmcplayer = Player()
|
self.xbmcplayer = Player()
|
||||||
Monitor.__init__(self)
|
Monitor.__init__(self)
|
||||||
|
for playerid in state.PLAYER_STATES:
|
||||||
|
state.PLAYER_STATES[playerid] = dict(state.PLAYSTATE)
|
||||||
LOG.info("Kodi monitor started.")
|
LOG.info("Kodi monitor started.")
|
||||||
|
|
||||||
def onScanStarted(self, library):
|
def onScanStarted(self, library):
|
||||||
|
@ -315,6 +318,8 @@ class KodiMonitor(Monitor):
|
||||||
LOG.info('Aborting playback report - item invalid for updates %s',
|
LOG.info('Aborting playback report - item invalid for updates %s',
|
||||||
data)
|
data)
|
||||||
return
|
return
|
||||||
|
# Remember that this player has been active
|
||||||
|
state.ACTIVE_PLAYERS.append(playerid)
|
||||||
playqueue = PQ.PLAYQUEUES[playerid]
|
playqueue = PQ.PLAYQUEUES[playerid]
|
||||||
info = js.get_player_props(playerid)
|
info = js.get_player_props(playerid)
|
||||||
json_item = js.get_item(playerid)
|
json_item = js.get_item(playerid)
|
||||||
|
@ -356,13 +361,15 @@ class KodiMonitor(Monitor):
|
||||||
container_key = '/library/metadata/%s' % plex_id
|
container_key = '/library/metadata/%s' % plex_id
|
||||||
state.PLAYER_STATES[playerid]['container_key'] = container_key
|
state.PLAYER_STATES[playerid]['container_key'] = container_key
|
||||||
LOG.debug('Set the Plex container_key to: %s', container_key)
|
LOG.debug('Set the Plex container_key to: %s', container_key)
|
||||||
|
status = state.PLAYER_STATES[playerid]
|
||||||
state.PLAYER_STATES[playerid].update(info)
|
status.update(info)
|
||||||
state.PLAYER_STATES[playerid]['file'] = path
|
status['file'] = path
|
||||||
state.PLAYER_STATES[playerid]['kodi_id'] = kodi_id
|
status['kodi_id'] = kodi_id
|
||||||
state.PLAYER_STATES[playerid]['kodi_type'] = kodi_type
|
status['kodi_type'] = kodi_type
|
||||||
state.PLAYER_STATES[playerid]['plex_id'] = plex_id
|
status['plex_id'] = plex_id
|
||||||
state.PLAYER_STATES[playerid]['plex_type'] = plex_type
|
status['plex_type'] = plex_type
|
||||||
|
status['playmethod'] = item.playmethod
|
||||||
|
status['playcount'] = item.playcount
|
||||||
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):
|
||||||
|
|
|
@ -138,6 +138,7 @@ def _prep_playlist_stack(xml):
|
||||||
# We will never store clips (trailers) in the Kodi DB
|
# We will never store clips (trailers) in the Kodi DB
|
||||||
kodi_id = None
|
kodi_id = None
|
||||||
kodi_type = None
|
kodi_type = None
|
||||||
|
resume, _ = api.getRuntime()
|
||||||
for part, _ in enumerate(item[0]):
|
for part, _ in enumerate(item[0]):
|
||||||
api.setPartNumber(part)
|
api.setPartNumber(part)
|
||||||
if kodi_id is None:
|
if kodi_id is None:
|
||||||
|
@ -161,7 +162,9 @@ def _prep_playlist_stack(xml):
|
||||||
'file': path,
|
'file': path,
|
||||||
'xml_video_element': item,
|
'xml_video_element': item,
|
||||||
'listitem': listitem,
|
'listitem': listitem,
|
||||||
'part': part
|
'part': part,
|
||||||
|
'playcount': api.getViewCount(),
|
||||||
|
'offset': resume
|
||||||
})
|
})
|
||||||
return stack
|
return stack
|
||||||
|
|
||||||
|
@ -188,6 +191,8 @@ def _process_stack(playqueue, stack):
|
||||||
kodi_id=item['kodi_id'],
|
kodi_id=item['kodi_id'],
|
||||||
kodi_type=item['kodi_type'],
|
kodi_type=item['kodi_type'],
|
||||||
xml_video_element=item['xml_video_element'])
|
xml_video_element=item['xml_video_element'])
|
||||||
|
playlist_item.playcount = item['playcount']
|
||||||
|
playlist_item.offset = item['offset']
|
||||||
playlist_item.part = item['part']
|
playlist_item.part = item['part']
|
||||||
playlist_item.init_done = True
|
playlist_item.init_done = True
|
||||||
pos += 1
|
pos += 1
|
||||||
|
|
|
@ -2,15 +2,14 @@
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from json import loads
|
|
||||||
|
|
||||||
from xbmc import Player, sleep
|
from xbmc import Player
|
||||||
|
|
||||||
from utils import window, DateToKodi, getUnixTimestamp, tryDecode, tryEncode
|
from utils import window, DateToKodi, getUnixTimestamp, kodi_time_to_millis
|
||||||
import downloadutils
|
from downloadutils import DownloadUtils as DU
|
||||||
import plexdb_functions as plexdb
|
import plexdb_functions as plexdb
|
||||||
import kodidb_functions as kodidb
|
import kodidb_functions as kodidb
|
||||||
import json_rpc as js
|
from plexbmchelper.subscribers import LOCKER
|
||||||
import variables as v
|
import variables as v
|
||||||
import state
|
import state
|
||||||
|
|
||||||
|
@ -22,326 +21,104 @@ LOG = getLogger("PLEX." + __name__)
|
||||||
|
|
||||||
|
|
||||||
class PKC_Player(Player):
|
class PKC_Player(Player):
|
||||||
|
|
||||||
played_info = state.PLAYED_INFO
|
|
||||||
playStats = state.PLAYER_STATES
|
|
||||||
currentFile = None
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.doUtils = downloadutils.DownloadUtils
|
|
||||||
Player.__init__(self)
|
Player.__init__(self)
|
||||||
LOG.info("Started playback monitor.")
|
LOG.info("Started playback monitor.")
|
||||||
|
|
||||||
def onPlayBackStarted(self):
|
def onPlayBackStarted(self):
|
||||||
"""
|
"""
|
||||||
Will be called when xbmc starts playing a file.
|
Will be called when xbmc starts playing a file.
|
||||||
Window values need to have been set in Kodimonitor.py
|
|
||||||
"""
|
"""
|
||||||
return
|
pass
|
||||||
self.stopAll()
|
|
||||||
|
|
||||||
# Get current file (in utf-8!)
|
|
||||||
try:
|
|
||||||
currentFile = tryDecode(self.getPlayingFile())
|
|
||||||
sleep(300)
|
|
||||||
except:
|
|
||||||
currentFile = ""
|
|
||||||
count = 0
|
|
||||||
while not currentFile:
|
|
||||||
sleep(100)
|
|
||||||
try:
|
|
||||||
currentFile = tryDecode(self.getPlayingFile())
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if count == 20:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
count += 1
|
|
||||||
if not currentFile:
|
|
||||||
LOG.warn('Error getting currently playing file; abort reporting')
|
|
||||||
return
|
|
||||||
|
|
||||||
# Save currentFile for cleanup later and for references
|
|
||||||
self.currentFile = currentFile
|
|
||||||
window('plex_lastPlayedFiled', value=currentFile)
|
|
||||||
# We may need to wait for info to be set in kodi monitor
|
|
||||||
itemId = window("plex_%s.itemid" % tryEncode(currentFile))
|
|
||||||
count = 0
|
|
||||||
while not itemId:
|
|
||||||
sleep(200)
|
|
||||||
itemId = window("plex_%s.itemid" % tryEncode(currentFile))
|
|
||||||
if count == 5:
|
|
||||||
LOG.warn("Could not find itemId, cancelling playback report!")
|
|
||||||
return
|
|
||||||
count += 1
|
|
||||||
|
|
||||||
LOG.info("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId))
|
|
||||||
|
|
||||||
plexitem = "plex_%s" % tryEncode(currentFile)
|
|
||||||
runtime = window("%s.runtime" % plexitem)
|
|
||||||
refresh_id = window("%s.refreshid" % plexitem)
|
|
||||||
playMethod = window("%s.playmethod" % plexitem)
|
|
||||||
itemType = window("%s.type" % plexitem)
|
|
||||||
try:
|
|
||||||
playcount = int(window("%s.playcount" % plexitem))
|
|
||||||
except ValueError:
|
|
||||||
playcount = 0
|
|
||||||
window('plex_skipWatched%s' % itemId, value="true")
|
|
||||||
|
|
||||||
LOG.debug("Playing itemtype is: %s" % itemType)
|
|
||||||
|
|
||||||
customseek = window('plex_customplaylist.seektime')
|
|
||||||
if customseek:
|
|
||||||
# Start at, when using custom playlist (play to Kodi from
|
|
||||||
# webclient)
|
|
||||||
LOG.info("Seeking to: %s" % customseek)
|
|
||||||
try:
|
|
||||||
self.seekTime(int(customseek))
|
|
||||||
except:
|
|
||||||
LOG.error('Could not seek!')
|
|
||||||
window('plex_customplaylist.seektime', clear=True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
seekTime = self.getTime()
|
|
||||||
except RuntimeError:
|
|
||||||
LOG.error('Could not get current seektime from xbmc player')
|
|
||||||
seekTime = 0
|
|
||||||
volume = js.get_volume()
|
|
||||||
muted = js.get_muted()
|
|
||||||
|
|
||||||
# Postdata structure to send to plex server
|
|
||||||
url = "{server}/:/timeline?"
|
|
||||||
postdata = {
|
|
||||||
|
|
||||||
'QueueableMediaTypes': "Video",
|
|
||||||
'CanSeek': True,
|
|
||||||
'ItemId': itemId,
|
|
||||||
'MediaSourceId': itemId,
|
|
||||||
'PlayMethod': playMethod,
|
|
||||||
'VolumeLevel': volume,
|
|
||||||
'PositionTicks': int(seekTime * 10000000),
|
|
||||||
'IsMuted': muted
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get the current audio track and subtitles
|
|
||||||
if playMethod == "Transcode":
|
|
||||||
# property set in PlayUtils.py
|
|
||||||
postdata['AudioStreamIndex'] = window("%sAudioStreamIndex"
|
|
||||||
% tryEncode(currentFile))
|
|
||||||
postdata['SubtitleStreamIndex'] = window("%sSubtitleStreamIndex"
|
|
||||||
% tryEncode(currentFile))
|
|
||||||
else:
|
|
||||||
# Get the current kodi audio and subtitles and convert to plex equivalent
|
|
||||||
indexAudio = js.current_audiostream(1).get('index', 0)
|
|
||||||
subsEnabled = js.subtitle_enabled(1)
|
|
||||||
if subsEnabled:
|
|
||||||
indexSubs = js.current_subtitle(1).get('index', 0)
|
|
||||||
else:
|
|
||||||
indexSubs = 0
|
|
||||||
|
|
||||||
# Postdata for the audio
|
|
||||||
postdata['AudioStreamIndex'] = indexAudio + 1
|
|
||||||
|
|
||||||
# Postdata for the subtitles
|
|
||||||
if subsEnabled and len(Player().getAvailableSubtitleStreams()) > 0:
|
|
||||||
|
|
||||||
# Number of audiotracks to help get plex Index
|
|
||||||
audioTracks = len(Player().getAvailableAudioStreams())
|
|
||||||
mapping = window("%s.indexMapping" % plexitem)
|
|
||||||
|
|
||||||
if mapping: # Set in playbackutils.py
|
|
||||||
|
|
||||||
LOG.debug("Mapping for external subtitles index: %s"
|
|
||||||
% mapping)
|
|
||||||
externalIndex = loads(mapping)
|
|
||||||
|
|
||||||
if externalIndex.get(str(indexSubs)):
|
|
||||||
# If the current subtitle is in the mapping
|
|
||||||
postdata['SubtitleStreamIndex'] = externalIndex[str(indexSubs)]
|
|
||||||
else:
|
|
||||||
# Internal subtitle currently selected
|
|
||||||
subindex = indexSubs - len(externalIndex) + audioTracks + 1
|
|
||||||
postdata['SubtitleStreamIndex'] = subindex
|
|
||||||
|
|
||||||
else: # Direct paths enabled scenario or no external subtitles set
|
|
||||||
postdata['SubtitleStreamIndex'] = indexSubs + audioTracks + 1
|
|
||||||
else:
|
|
||||||
postdata['SubtitleStreamIndex'] = ""
|
|
||||||
|
|
||||||
|
|
||||||
# Post playback to server
|
|
||||||
# log("Sending POST play started: %s." % postdata, 2)
|
|
||||||
# self.doUtils(url, postBody=postdata, type="POST")
|
|
||||||
|
|
||||||
# Ensure we do have a runtime
|
|
||||||
try:
|
|
||||||
runtime = int(runtime)
|
|
||||||
except ValueError:
|
|
||||||
try:
|
|
||||||
runtime = self.getTotalTime()
|
|
||||||
LOG.error("Runtime is missing, Kodi runtime: %s" % runtime)
|
|
||||||
except:
|
|
||||||
LOG.error('Could not get kodi runtime, setting to zero')
|
|
||||||
runtime = 0
|
|
||||||
|
|
||||||
with plexdb.Get_Plex_DB() as plex_db:
|
|
||||||
plex_dbitem = plex_db.getItem_byId(itemId)
|
|
||||||
try:
|
|
||||||
fileid = plex_dbitem[1]
|
|
||||||
except TypeError:
|
|
||||||
LOG.info("Could not find fileid in plex db.")
|
|
||||||
fileid = None
|
|
||||||
# Save data map for updates and position calls
|
|
||||||
data = {
|
|
||||||
'runtime': runtime,
|
|
||||||
'item_id': itemId,
|
|
||||||
'refresh_id': refresh_id,
|
|
||||||
'currentfile': currentFile,
|
|
||||||
'AudioStreamIndex': postdata['AudioStreamIndex'],
|
|
||||||
'SubtitleStreamIndex': postdata['SubtitleStreamIndex'],
|
|
||||||
'playmethod': playMethod,
|
|
||||||
'Type': itemType,
|
|
||||||
'currentPosition': int(seekTime),
|
|
||||||
'fileid': fileid,
|
|
||||||
'itemType': itemType,
|
|
||||||
'playcount': playcount
|
|
||||||
}
|
|
||||||
|
|
||||||
self.played_info[currentFile] = data
|
|
||||||
LOG.info("ADDING_FILE: %s" % data)
|
|
||||||
|
|
||||||
# log some playback stats
|
|
||||||
'''if(itemType != None):
|
|
||||||
if(self.playStats.get(itemType) != None):
|
|
||||||
count = self.playStats.get(itemType) + 1
|
|
||||||
self.playStats[itemType] = count
|
|
||||||
else:
|
|
||||||
self.playStats[itemType] = 1
|
|
||||||
|
|
||||||
if(playMethod != None):
|
|
||||||
if(self.playStats.get(playMethod) != None):
|
|
||||||
count = self.playStats.get(playMethod) + 1
|
|
||||||
self.playStats[playMethod] = count
|
|
||||||
else:
|
|
||||||
self.playStats[playMethod] = 1'''
|
|
||||||
|
|
||||||
def onPlayBackPaused(self):
|
def onPlayBackPaused(self):
|
||||||
|
"""
|
||||||
currentFile = self.currentFile
|
Will be called when playback is paused
|
||||||
LOG.info("PLAYBACK_PAUSED: %s" % currentFile)
|
"""
|
||||||
|
pass
|
||||||
if self.played_info.get(currentFile):
|
|
||||||
self.played_info[currentFile]['paused'] = True
|
|
||||||
|
|
||||||
def onPlayBackResumed(self):
|
def onPlayBackResumed(self):
|
||||||
|
"""
|
||||||
currentFile = self.currentFile
|
Will be called when playback is resumed
|
||||||
LOG.info("PLAYBACK_RESUMED: %s" % currentFile)
|
"""
|
||||||
|
pass
|
||||||
if self.played_info.get(currentFile):
|
|
||||||
self.played_info[currentFile]['paused'] = False
|
|
||||||
|
|
||||||
def onPlayBackSeek(self, time, seekOffset):
|
def onPlayBackSeek(self, time, seekOffset):
|
||||||
# Make position when seeking a bit more accurate
|
"""
|
||||||
currentFile = self.currentFile
|
Will be called when user seeks to a certain time during playback
|
||||||
LOG.info("PLAYBACK_SEEK: %s" % currentFile)
|
"""
|
||||||
|
pass
|
||||||
if self.played_info.get(currentFile):
|
|
||||||
try:
|
|
||||||
position = self.getTime()
|
|
||||||
except RuntimeError:
|
|
||||||
# When Kodi is not playing
|
|
||||||
return
|
|
||||||
self.played_info[currentFile]['currentPosition'] = position
|
|
||||||
|
|
||||||
def onPlayBackStopped(self):
|
def onPlayBackStopped(self):
|
||||||
# Will be called when user stops xbmc playing a file
|
"""
|
||||||
|
Will be called when playback is stopped by the user
|
||||||
|
"""
|
||||||
LOG.info("ONPLAYBACK_STOPPED")
|
LOG.info("ONPLAYBACK_STOPPED")
|
||||||
|
self.cleanup_playback()
|
||||||
|
|
||||||
self.stopAll()
|
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',
|
for item in ('plex_currently_playing_itemid',
|
||||||
'plex_customplaylist',
|
'plex_customplaylist',
|
||||||
'plex_customplaylist.seektime',
|
'plex_customplaylist.seektime',
|
||||||
'plex_forcetranscode'):
|
'plex_forcetranscode'):
|
||||||
window(item, clear=True)
|
window(item, clear=True)
|
||||||
# We might have saved a transient token from a user flinging media via
|
for playerid in state.ACTIVE_PLAYERS:
|
||||||
# Companion (if we could not use the playqueue to store the token)
|
status = state.PLAYER_STATES[playerid]
|
||||||
state.PLEX_TRANSIENT_TOKEN = None
|
# Check whether we need to mark an item as completely watched
|
||||||
LOG.debug("Cleared playlist properties.")
|
if not status['kodi_id'] or not status['plex_id']:
|
||||||
|
LOG.info('No PKC info safed for the element just played by Kodi'
|
||||||
def onPlayBackEnded(self):
|
' player %s', playerid)
|
||||||
# Will be called when xbmc stops playing a file, because the file ended
|
|
||||||
LOG.info("ONPLAYBACK_ENDED")
|
|
||||||
self.onPlayBackStopped()
|
|
||||||
|
|
||||||
def stopAll(self):
|
|
||||||
if not self.played_info:
|
|
||||||
return
|
|
||||||
LOG.info("Played_information: %s" % self.played_info)
|
|
||||||
# Process each items
|
|
||||||
for item in self.played_info:
|
|
||||||
data = self.played_info.get(item)
|
|
||||||
if not data:
|
|
||||||
continue
|
continue
|
||||||
LOG.debug("Item path: %s" % item)
|
# Stop transcoding
|
||||||
LOG.debug("Item data: %s" % data)
|
if status['playmethod'] == 'Transcode':
|
||||||
|
LOG.info('Tell the PMS to stop transcoding')
|
||||||
runtime = data['runtime']
|
DU().downloadUrl(
|
||||||
currentPosition = data['currentPosition']
|
'{server}/video/:/transcode/universal/stop',
|
||||||
itemid = data['item_id']
|
parameters={'session': v.PKC_MACHINE_IDENTIFIER})
|
||||||
refresh_id = data['refresh_id']
|
if status['plex_type'] == v.PLEX_TYPE_SONG:
|
||||||
currentFile = data['currentfile']
|
LOG.debug('Song has been played, not cleaning up playstate')
|
||||||
media_type = data['Type']
|
|
||||||
playMethod = data['playmethod']
|
|
||||||
|
|
||||||
# Prevent manually mark as watched in Kodi monitor
|
|
||||||
window('plex_skipWatched%s' % itemid, value="true")
|
|
||||||
|
|
||||||
if not currentPosition or not runtime:
|
|
||||||
continue
|
continue
|
||||||
try:
|
resume = kodi_time_to_millis(status['time'])
|
||||||
percentComplete = float(currentPosition) / float(runtime)
|
runtime = kodi_time_to_millis(status['totaltime'])
|
||||||
except ZeroDivisionError:
|
LOG.info('Item playback progress %s out of %s', resume, runtime)
|
||||||
# Runtime is 0.
|
if not resume or not runtime:
|
||||||
percentComplete = 0
|
continue
|
||||||
LOG.info("Percent complete: %s Mark played at: %s"
|
complete = float(resume) / float(runtime)
|
||||||
% (percentComplete, v.MARK_PLAYED_AT))
|
LOG.info("Percent complete: %s. Mark played at: %s",
|
||||||
if percentComplete >= v.MARK_PLAYED_AT:
|
complete, v.MARK_PLAYED_AT)
|
||||||
|
if complete >= v.MARK_PLAYED_AT:
|
||||||
# Tell Kodi that we've finished watching (Plex knows)
|
# Tell Kodi that we've finished watching (Plex knows)
|
||||||
if (data['fileid'] is not None and
|
with plexdb.Get_Plex_DB() as plex_db:
|
||||||
data['itemType'] in (v.KODI_TYPE_MOVIE,
|
plex_dbitem = plex_db.getItem_byId(status['plex_id'])
|
||||||
v.KODI_TYPE_EPISODE)):
|
file_id = plex_dbitem[1] if plex_dbitem else None
|
||||||
with kodidb.GetKodiDB('video') as kodi_db:
|
if file_id is None:
|
||||||
kodi_db.addPlaystate(
|
LOG.error('No file_id found for %s', status)
|
||||||
data['fileid'],
|
continue
|
||||||
None,
|
with kodidb.GetKodiDB('video') as kodi_db:
|
||||||
None,
|
kodi_db.addPlaystate(
|
||||||
data['playcount'] + 1,
|
file_id,
|
||||||
DateToKodi(getUnixTimestamp()))
|
None,
|
||||||
|
None,
|
||||||
# Clean the WINDOW properties
|
status['playcount'] + 1,
|
||||||
for filename in self.played_info:
|
DateToKodi(getUnixTimestamp()))
|
||||||
plex_item = 'plex_%s' % tryEncode(filename)
|
LOG.info('Marked plex element %s as completely watched',
|
||||||
cleanup = (
|
status['plex_id'])
|
||||||
'%s.itemid' % plex_item,
|
# As all playback has halted, reset the players that have been active
|
||||||
'%s.runtime' % plex_item,
|
state.ACTIVE_PLAYERS = []
|
||||||
'%s.refreshid' % plex_item,
|
for playerid in state.PLAYER_STATES:
|
||||||
'%s.playmethod' % plex_item,
|
state.PLAYER_STATES[playerid] = dict(state.PLAYSTATE)
|
||||||
'%s.type' % plex_item,
|
LOG.info('Finished PKC playback cleanup')
|
||||||
'%s.runtime' % plex_item,
|
|
||||||
'%s.playcount' % plex_item,
|
|
||||||
'%s.playlistPosition' % plex_item,
|
|
||||||
'%s.subtitle' % plex_item,
|
|
||||||
)
|
|
||||||
for item in cleanup:
|
|
||||||
window(item, clear=True)
|
|
||||||
|
|
||||||
# Stop transcoding
|
|
||||||
if playMethod == "Transcode":
|
|
||||||
LOG.info("Transcoding for %s terminating" % itemid)
|
|
||||||
self.doUtils().downloadUrl(
|
|
||||||
"{server}/video/:/transcode/universal/stop",
|
|
||||||
parameters={'session': v.PKC_MACHINE_IDENTIFIER})
|
|
||||||
|
|
||||||
self.played_info.clear()
|
|
||||||
|
|
|
@ -190,6 +190,8 @@ class Playlist_Item(object):
|
||||||
guid = None [str] Weird Plex guid
|
guid = None [str] Weird Plex guid
|
||||||
xml = None [etree] XML from PMS, 1 lvl below <MediaContainer>
|
xml = None [etree] XML from PMS, 1 lvl below <MediaContainer>
|
||||||
playmethod = None [str] either 'DirectPlay', 'DirectStream', 'Transcode'
|
playmethod = None [str] either 'DirectPlay', 'DirectStream', 'Transcode'
|
||||||
|
playcount = None [int] how many times the item has already been played
|
||||||
|
offset = None [int] the item's view offset UPON START in Plex time
|
||||||
part = 0 [int] part number if Plex video consists of mult. parts
|
part = 0 [int] part number if Plex video consists of mult. parts
|
||||||
init_done = False Set to True only if run through playback init
|
init_done = False Set to True only if run through playback init
|
||||||
"""
|
"""
|
||||||
|
@ -205,6 +207,8 @@ class Playlist_Item(object):
|
||||||
self.guid = None
|
self.guid = None
|
||||||
self.xml = None
|
self.xml = None
|
||||||
self.playmethod = None
|
self.playmethod = None
|
||||||
|
self.playcount = None
|
||||||
|
self.offset = None
|
||||||
# If Plex video consists of several parts; part number
|
# If Plex video consists of several parts; part number
|
||||||
self.part = 0
|
self.part = 0
|
||||||
self.init_done = False
|
self.init_done = False
|
||||||
|
|
|
@ -82,44 +82,48 @@ COMMAND_PIPELINE_QUEUE = None
|
||||||
# Websocket_client queue to communicate with librarysync
|
# Websocket_client queue to communicate with librarysync
|
||||||
WEBSOCKET_QUEUE = None
|
WEBSOCKET_QUEUE = None
|
||||||
|
|
||||||
|
# Which Kodi player is/has been active? (either int 1, 2 or 3)
|
||||||
|
ACTIVE_PLAYERS = []
|
||||||
|
|
||||||
# Kodi player states - here, initial values are set
|
# Kodi player states - here, initial values are set
|
||||||
PLAYER_STATES = {
|
PLAYER_STATES = {
|
||||||
1: {
|
1: {},
|
||||||
'type': 'movie',
|
|
||||||
'time': {
|
|
||||||
'hours': 0,
|
|
||||||
'minutes': 0,
|
|
||||||
'seconds': 0,
|
|
||||||
'milliseconds': 0
|
|
||||||
},
|
|
||||||
'totaltime': {
|
|
||||||
'hours': 0,
|
|
||||||
'minutes': 0,
|
|
||||||
'seconds': 0,
|
|
||||||
'milliseconds': 0
|
|
||||||
},
|
|
||||||
'speed': 0,
|
|
||||||
'shuffled': False,
|
|
||||||
'repeat': 'off',
|
|
||||||
'position': -1,
|
|
||||||
'playlistid': -1,
|
|
||||||
'currentvideostream': -1,
|
|
||||||
'currentaudiostream': -1,
|
|
||||||
'subtitleenabled': False,
|
|
||||||
'currentsubtitle': -1,
|
|
||||||
######
|
|
||||||
'file': '',
|
|
||||||
'kodi_id': None,
|
|
||||||
'kodi_type': None,
|
|
||||||
'plex_id': None,
|
|
||||||
'plex_type': None,
|
|
||||||
'container_key': None,
|
|
||||||
'volume': 100,
|
|
||||||
'muted': False
|
|
||||||
},
|
|
||||||
2: {},
|
2: {},
|
||||||
3: {}
|
3: {}
|
||||||
}
|
}
|
||||||
|
# "empty" dict for the PLAYER_STATES above
|
||||||
|
PLAYSTATE = {
|
||||||
|
'type': None,
|
||||||
|
'time': {
|
||||||
|
'hours': 0,
|
||||||
|
'minutes': 0,
|
||||||
|
'seconds': 0,
|
||||||
|
'milliseconds': 0},
|
||||||
|
'totaltime': {
|
||||||
|
'hours': 0,
|
||||||
|
'minutes': 0,
|
||||||
|
'seconds': 0,
|
||||||
|
'milliseconds': 0},
|
||||||
|
'speed': 0,
|
||||||
|
'shuffled': False,
|
||||||
|
'repeat': 'off',
|
||||||
|
'position': None,
|
||||||
|
'playlistid': None,
|
||||||
|
'currentvideostream': -1,
|
||||||
|
'currentaudiostream': -1,
|
||||||
|
'subtitleenabled': False,
|
||||||
|
'currentsubtitle': -1,
|
||||||
|
'file': None,
|
||||||
|
'kodi_id': None,
|
||||||
|
'kodi_type': None,
|
||||||
|
'plex_id': None,
|
||||||
|
'plex_type': None,
|
||||||
|
'container_key': None,
|
||||||
|
'volume': 100,
|
||||||
|
'muted': False,
|
||||||
|
'playmethod': None,
|
||||||
|
'playcount': None
|
||||||
|
}
|
||||||
# Dict containing all filenames as keys with plex id as values - used for addon
|
# Dict containing all filenames as keys with plex id as values - used for addon
|
||||||
# paths for playback (since we're not receiving a Kodi id)
|
# paths for playback (since we're not receiving a Kodi id)
|
||||||
PLEX_IDS = {}
|
PLEX_IDS = {}
|
||||||
|
|
Loading…
Reference in a new issue