Optimize player and playlist instances
This commit is contained in:
parent
ee802428f9
commit
a2693b3485
8 changed files with 71 additions and 212 deletions
|
@ -12,6 +12,7 @@ from plexbmchelper import listener, plexgdm, subscribers, functions, \
|
||||||
from PlexFunctions import ParseContainerKey, GetPlayQueue, \
|
from PlexFunctions import ParseContainerKey, GetPlayQueue, \
|
||||||
ConvertPlexToKodiTime
|
ConvertPlexToKodiTime
|
||||||
import playlist
|
import playlist
|
||||||
|
import player
|
||||||
|
|
||||||
|
|
||||||
@utils.logging
|
@utils.logging
|
||||||
|
@ -21,7 +22,7 @@ class PlexCompanion(threading.Thread):
|
||||||
"""
|
"""
|
||||||
Initialize with a Queue for callbacks
|
Initialize with a Queue for callbacks
|
||||||
"""
|
"""
|
||||||
def __init__(self, player=None):
|
def __init__(self):
|
||||||
self.logMsg("----===## Starting PlexCompanion ##===----", 1)
|
self.logMsg("----===## Starting PlexCompanion ##===----", 1)
|
||||||
self.settings = settings.getSettings()
|
self.settings = settings.getSettings()
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ class PlexCompanion(threading.Thread):
|
||||||
self.playlist = None
|
self.playlist = None
|
||||||
|
|
||||||
# kodi player instance
|
# kodi player instance
|
||||||
self.player = player
|
self.player = player.Player()
|
||||||
|
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ class PlexCompanion(threading.Thread):
|
||||||
requestMgr = httppersist.RequestMgr()
|
requestMgr = httppersist.RequestMgr()
|
||||||
jsonClass = functions.jsonClass(requestMgr, self.settings)
|
jsonClass = functions.jsonClass(requestMgr, self.settings)
|
||||||
subscriptionManager = subscribers.SubscriptionManager(
|
subscriptionManager = subscribers.SubscriptionManager(
|
||||||
jsonClass, requestMgr)
|
jsonClass, requestMgr, self.player)
|
||||||
|
|
||||||
queue = Queue.Queue(maxsize=100)
|
queue = Queue.Queue(maxsize=100)
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,10 @@ from PlexFunctions import scrobble
|
||||||
@utils.logging
|
@utils.logging
|
||||||
class KodiMonitor(xbmc.Monitor):
|
class KodiMonitor(xbmc.Monitor):
|
||||||
|
|
||||||
def __init__(self, player=None):
|
def __init__(self):
|
||||||
|
|
||||||
self.doUtils = downloadutils.DownloadUtils().downloadUrl
|
self.doUtils = downloadutils.DownloadUtils().downloadUrl
|
||||||
self.xbmcplayer = player
|
self.xbmcplayer = xbmc.Player()
|
||||||
xbmc.Monitor.__init__(self)
|
xbmc.Monitor.__init__(self)
|
||||||
self.logMsg("Kodi monitor started.", 1)
|
self.logMsg("Kodi monitor started.", 1)
|
||||||
|
|
||||||
|
|
|
@ -1549,9 +1549,9 @@ class LibrarySync(Thread):
|
||||||
with itemFkt() as Fkt:
|
with itemFkt() as Fkt:
|
||||||
Fkt.updatePlaystate(item)
|
Fkt.updatePlaystate(item)
|
||||||
|
|
||||||
def run(self, player=None):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
self.run_internal(player)
|
self.run_internal()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
utils.window('plex_dbScan', clear=True)
|
utils.window('plex_dbScan', clear=True)
|
||||||
self.logMsg('LibrarySync thread crashed', -1)
|
self.logMsg('LibrarySync thread crashed', -1)
|
||||||
|
@ -1563,7 +1563,7 @@ class LibrarySync(Thread):
|
||||||
self.__language__(39400))
|
self.__language__(39400))
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def run_internal(self, player=None):
|
def run_internal(self):
|
||||||
# Re-assign handles to have faster calls
|
# Re-assign handles to have faster calls
|
||||||
window = utils.window
|
window = utils.window
|
||||||
settings = utils.settings
|
settings = utils.settings
|
||||||
|
@ -1582,7 +1582,7 @@ class LibrarySync(Thread):
|
||||||
lastProcessing = 0
|
lastProcessing = 0
|
||||||
oneDay = 60*60*24
|
oneDay = 60*60*24
|
||||||
|
|
||||||
xbmcplayer = player
|
xbmcplayer = xbmc.Player()
|
||||||
|
|
||||||
queue = self.queue
|
queue = self.queue
|
||||||
|
|
||||||
|
|
|
@ -279,151 +279,6 @@ class Player(xbmc.Player):
|
||||||
else:
|
else:
|
||||||
self.playStats[playMethod] = 1'''
|
self.playStats[playMethod] = 1'''
|
||||||
|
|
||||||
def reportPlayback(self):
|
|
||||||
# Done by Plex Companion
|
|
||||||
return
|
|
||||||
|
|
||||||
self.logMsg("reportPlayback Called", 2)
|
|
||||||
|
|
||||||
# Get current file
|
|
||||||
currentFile = self.currentFile
|
|
||||||
data = self.played_info.get(currentFile)
|
|
||||||
|
|
||||||
# only report playback if emby has initiated the playback (item_id has value)
|
|
||||||
if data:
|
|
||||||
# Get playback inforation
|
|
||||||
itemId = data['item_id']
|
|
||||||
audioindex = data['AudioStreamIndex']
|
|
||||||
subtitleindex = data['SubtitleStreamIndex']
|
|
||||||
playTime = data['currentPosition']
|
|
||||||
playMethod = data['playmethod']
|
|
||||||
paused = data.get('paused', False)
|
|
||||||
duration = data.get('runtime', '')
|
|
||||||
|
|
||||||
|
|
||||||
# Get playback volume
|
|
||||||
volume_query = {
|
|
||||||
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": 1,
|
|
||||||
"method": "Application.GetProperties",
|
|
||||||
"params": {
|
|
||||||
|
|
||||||
"properties": ["volume", "muted"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = xbmc.executeJSONRPC(json.dumps(volume_query))
|
|
||||||
result = json.loads(result)
|
|
||||||
result = result.get('result')
|
|
||||||
|
|
||||||
volume = result.get('volume')
|
|
||||||
muted = result.get('muted')
|
|
||||||
|
|
||||||
# Postdata for the websocketclient report
|
|
||||||
# postdata = {
|
|
||||||
|
|
||||||
# 'QueueableMediaTypes': "Video",
|
|
||||||
# 'CanSeek': True,
|
|
||||||
# 'ItemId': itemId,
|
|
||||||
# 'MediaSourceId': itemId,
|
|
||||||
# 'PlayMethod': playMethod,
|
|
||||||
# 'PositionTicks': int(playTime * 10000000),
|
|
||||||
# 'IsPaused': paused,
|
|
||||||
# 'VolumeLevel': volume,
|
|
||||||
# 'IsMuted': muted
|
|
||||||
# }
|
|
||||||
if paused == 'stopped':
|
|
||||||
state = 'stopped'
|
|
||||||
elif paused is True:
|
|
||||||
state = 'paused'
|
|
||||||
else:
|
|
||||||
state = 'playing'
|
|
||||||
postdata = {
|
|
||||||
'ratingKey': itemId,
|
|
||||||
'state': state, # 'stopped', 'paused', 'buffering', 'playing'
|
|
||||||
'time': int(playTime) * 1000,
|
|
||||||
'duration': int(duration) * 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
# For PMS playQueues/playlists only
|
|
||||||
if data.get('playQueueID'):
|
|
||||||
postdata['containerKey'] = '/playQueues/' + data.get('playQueueID')
|
|
||||||
postdata['playQueueVersion'] = data.get('playQueueVersion')
|
|
||||||
postdata['playQueueItemID'] = data.get('playQueueItemID')
|
|
||||||
|
|
||||||
if playMethod == "Transcode":
|
|
||||||
# Track can't be changed, keep reporting the same index
|
|
||||||
postdata['AudioStreamIndex'] = audioindex
|
|
||||||
postdata['AudioStreamIndex'] = subtitleindex
|
|
||||||
|
|
||||||
else:
|
|
||||||
# Get current audio and subtitles track
|
|
||||||
tracks_query = {
|
|
||||||
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": 1,
|
|
||||||
"method": "Player.GetProperties",
|
|
||||||
"params": {
|
|
||||||
|
|
||||||
"playerid": 1,
|
|
||||||
"properties": ["currentsubtitle","currentaudiostream","subtitleenabled"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = xbmc.executeJSONRPC(json.dumps(tracks_query))
|
|
||||||
result = json.loads(result)
|
|
||||||
result = result.get('result')
|
|
||||||
|
|
||||||
try: # Audio tracks
|
|
||||||
indexAudio = result['currentaudiostream']['index']
|
|
||||||
except (KeyError, TypeError):
|
|
||||||
indexAudio = 0
|
|
||||||
|
|
||||||
try: # Subtitles tracks
|
|
||||||
indexSubs = result['currentsubtitle']['index']
|
|
||||||
except (KeyError, TypeError):
|
|
||||||
indexSubs = 0
|
|
||||||
|
|
||||||
try: # If subtitles are enabled
|
|
||||||
subsEnabled = result['subtitleenabled']
|
|
||||||
except (KeyError, TypeError):
|
|
||||||
subsEnabled = ""
|
|
||||||
|
|
||||||
# Postdata for the audio
|
|
||||||
data['AudioStreamIndex'], postdata['AudioStreamIndex'] = [indexAudio + 1] * 2
|
|
||||||
|
|
||||||
# Postdata for the subtitles
|
|
||||||
if subsEnabled and len(xbmc.Player().getAvailableSubtitleStreams()) > 0:
|
|
||||||
|
|
||||||
# Number of audiotracks to help get Emby Index
|
|
||||||
audioTracks = len(xbmc.Player().getAvailableAudioStreams())
|
|
||||||
mapping = utils.window("emby_%s.indexMapping" % currentFile)
|
|
||||||
|
|
||||||
if mapping: # Set in PlaybackUtils.py
|
|
||||||
|
|
||||||
self.logMsg("Mapping for external subtitles index: %s" % mapping, 2)
|
|
||||||
externalIndex = json.loads(mapping)
|
|
||||||
|
|
||||||
if externalIndex.get(str(indexSubs)):
|
|
||||||
# If the current subtitle is in the mapping
|
|
||||||
subindex = [externalIndex[str(indexSubs)]] * 2
|
|
||||||
data['SubtitleStreamIndex'], postdata['SubtitleStreamIndex'] = subindex
|
|
||||||
else:
|
|
||||||
# Internal subtitle currently selected
|
|
||||||
subindex = [indexSubs - len(externalIndex) + audioTracks + 1] * 2
|
|
||||||
data['SubtitleStreamIndex'], postdata['SubtitleStreamIndex'] = subindex
|
|
||||||
|
|
||||||
else: # Direct paths enabled scenario or no external subtitles set
|
|
||||||
subindex = [indexSubs + audioTracks + 1] * 2
|
|
||||||
data['SubtitleStreamIndex'], postdata['SubtitleStreamIndex'] = subindex
|
|
||||||
else:
|
|
||||||
data['SubtitleStreamIndex'], postdata['SubtitleStreamIndex'] = [""] * 2
|
|
||||||
|
|
||||||
# Report progress via websocketclient
|
|
||||||
# postdata = json.dumps(postdata)
|
|
||||||
# self.ws.sendProgressUpdate(postdata)
|
|
||||||
self.doUtils(
|
|
||||||
"{server}/:/timeline?" + urlencode(postdata), action_type="GET")
|
|
||||||
|
|
||||||
def onPlayBackPaused(self):
|
def onPlayBackPaused(self):
|
||||||
|
|
||||||
currentFile = self.currentFile
|
currentFile = self.currentFile
|
||||||
|
@ -431,7 +286,6 @@ class Player(xbmc.Player):
|
||||||
|
|
||||||
if self.played_info.get(currentFile):
|
if self.played_info.get(currentFile):
|
||||||
self.played_info[currentFile]['paused'] = True
|
self.played_info[currentFile]['paused'] = True
|
||||||
self.reportPlayback()
|
|
||||||
|
|
||||||
def onPlayBackResumed(self):
|
def onPlayBackResumed(self):
|
||||||
|
|
||||||
|
@ -440,7 +294,6 @@ class Player(xbmc.Player):
|
||||||
|
|
||||||
if self.played_info.get(currentFile):
|
if self.played_info.get(currentFile):
|
||||||
self.played_info[currentFile]['paused'] = False
|
self.played_info[currentFile]['paused'] = False
|
||||||
self.reportPlayback()
|
|
||||||
|
|
||||||
def onPlayBackSeek(self, time, seekOffset):
|
def onPlayBackSeek(self, time, seekOffset):
|
||||||
# Make position when seeking a bit more accurate
|
# Make position when seeking a bit more accurate
|
||||||
|
@ -454,7 +307,6 @@ class Player(xbmc.Player):
|
||||||
# When Kodi is not playing
|
# When Kodi is not playing
|
||||||
return
|
return
|
||||||
self.played_info[currentFile]['currentPosition'] = position * 1000
|
self.played_info[currentFile]['currentPosition'] = position * 1000
|
||||||
self.reportPlayback()
|
|
||||||
|
|
||||||
def onPlayBackStopped(self):
|
def onPlayBackStopped(self):
|
||||||
# Will be called when user stops xbmc playing a file
|
# Will be called when user stops xbmc playing a file
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from urllib import urlencode
|
from urllib import urlencode
|
||||||
|
from threading import Lock
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
|
|
||||||
|
@ -16,12 +18,32 @@ import PlexAPI
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
class lockMethod:
|
||||||
|
lock = Lock()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def decorate(cls, func):
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
with cls.lock:
|
||||||
|
result = func(*args, **kwargs)
|
||||||
|
return result
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
@utils.logging
|
@utils.logging
|
||||||
class Playlist():
|
class Playlist():
|
||||||
"""
|
"""
|
||||||
Initiate with Playlist(typus='video' or 'music')
|
Initiate with Playlist(typus='video' or 'music')
|
||||||
"""
|
"""
|
||||||
def __init__(self, typus=None, player=None):
|
# Borg - multiple instances, shared state
|
||||||
|
_shared_state = {}
|
||||||
|
|
||||||
|
@lockMethod.decorate
|
||||||
|
def __init__(self, typus=None):
|
||||||
|
# Borg
|
||||||
|
self.__dict__ = self._shared_state
|
||||||
|
|
||||||
self.userid = utils.window('currUserId')
|
self.userid = utils.window('currUserId')
|
||||||
self.server = utils.window('pms_server')
|
self.server = utils.window('pms_server')
|
||||||
# Construct the Kodi playlist instance
|
# Construct the Kodi playlist instance
|
||||||
|
@ -38,11 +60,11 @@ class Playlist():
|
||||||
self.typus = None
|
self.typus = None
|
||||||
if self.playlist is not None:
|
if self.playlist is not None:
|
||||||
self.playlistId = self.playlist.getPlayListId()
|
self.playlistId = self.playlist.getPlayListId()
|
||||||
# kodi player instance
|
self.player = xbmc.Player()
|
||||||
self.player = player
|
|
||||||
# "interal" PKC playlist
|
# "interal" PKC playlist
|
||||||
self.items = []
|
self.items = []
|
||||||
|
|
||||||
|
@lockMethod.decorate
|
||||||
def clear(self):
|
def clear(self):
|
||||||
"""
|
"""
|
||||||
Empties current Kodi playlist and internal self.items list
|
Empties current Kodi playlist and internal self.items list
|
||||||
|
@ -90,7 +112,7 @@ class Playlist():
|
||||||
if self.playlist is not None:
|
if self.playlist is not None:
|
||||||
self.playlistId = self.playlist.getPlayListId()
|
self.playlistId = self.playlist.getPlayListId()
|
||||||
|
|
||||||
def _addToPlaylist(self, startitem, startPlayer=False):
|
def _processItems(self, startitem, startPlayer=False):
|
||||||
startpos = None
|
startpos = None
|
||||||
with embydb.GetEmbyDB() as emby_db:
|
with embydb.GetEmbyDB() as emby_db:
|
||||||
for pos, item in enumerate(self.items):
|
for pos, item in enumerate(self.items):
|
||||||
|
@ -113,7 +135,7 @@ class Playlist():
|
||||||
# Add to playlist
|
# Add to playlist
|
||||||
self.logMsg("Adding %s PlexId %s, KodiId %s to playlist."
|
self.logMsg("Adding %s PlexId %s, KodiId %s to playlist."
|
||||||
% (mediatype, plexId, kodiId), 1)
|
% (mediatype, plexId, kodiId), 1)
|
||||||
self.addtoPlaylist(kodiId, mediatype)
|
self._addtoPlaylist(kodiId, mediatype)
|
||||||
# Add the kodiId
|
# Add the kodiId
|
||||||
if kodiId is not None:
|
if kodiId is not None:
|
||||||
item['kodiId'] = str(kodiId)
|
item['kodiId'] = str(kodiId)
|
||||||
|
@ -128,6 +150,7 @@ class Playlist():
|
||||||
'starting with the first entry', 1)
|
'starting with the first entry', 1)
|
||||||
self.player.play(self.playlist)
|
self.player.play(self.playlist)
|
||||||
|
|
||||||
|
@lockMethod.decorate
|
||||||
def playAll(self, items, startitem, offset):
|
def playAll(self, items, startitem, offset):
|
||||||
"""
|
"""
|
||||||
items: list of dicts of the form
|
items: list of dicts of the form
|
||||||
|
@ -155,21 +178,26 @@ class Playlist():
|
||||||
if offset != 0:
|
if offset != 0:
|
||||||
# Seek to the starting position
|
# Seek to the starting position
|
||||||
utils.window('plex_customplaylist.seektime', str(offset))
|
utils.window('plex_customplaylist.seektime', str(offset))
|
||||||
self._addToPlaylist(startitem, startPlayer=True)
|
self._processItems(startitem, startPlayer=True)
|
||||||
# Log playlist
|
# Log playlist
|
||||||
self.verifyPlaylist()
|
self._verifyPlaylist()
|
||||||
self.logMsg('Internal playlist: %s' % self.items, 2)
|
self.logMsg('Internal playlist: %s' % self.items, 2)
|
||||||
|
|
||||||
|
@lockMethod.decorate
|
||||||
def modifyPlaylist(self, itemids):
|
def modifyPlaylist(self, itemids):
|
||||||
self.logMsg("---*** ADD TO PLAYLIST ***---", 1)
|
self.logMsg("---*** ADD TO PLAYLIST ***---", 1)
|
||||||
self.logMsg("Items: %s" % itemids, 1)
|
self.logMsg("Items: %s" % itemids, 1)
|
||||||
|
|
||||||
self._initiatePlaylist(itemids)
|
self._initiatePlaylist(itemids)
|
||||||
self._addToPlaylist(itemids, startPlayer=True)
|
self._processItems(itemids, startPlayer=True)
|
||||||
|
|
||||||
self.verifyPlaylist()
|
self._verifyPlaylist()
|
||||||
|
|
||||||
|
@lockMethod.decorate
|
||||||
def addtoPlaylist(self, dbid=None, mediatype=None, url=None):
|
def addtoPlaylist(self, dbid=None, mediatype=None, url=None):
|
||||||
|
self._addtoPlaylist(dbid=None, mediatype=None, url=None)
|
||||||
|
|
||||||
|
def _addtoPlaylist(self, dbid=None, mediatype=None, url=None):
|
||||||
"""
|
"""
|
||||||
mediatype: Kodi type: 'movie', 'episode', 'musicvideo', 'artist',
|
mediatype: Kodi type: 'movie', 'episode', 'musicvideo', 'artist',
|
||||||
'album', 'song', 'genre'
|
'album', 'song', 'genre'
|
||||||
|
@ -205,6 +233,7 @@ class Playlist():
|
||||||
|
|
||||||
self.playlist.add(playurl, listitem)
|
self.playlist.add(playurl, listitem)
|
||||||
|
|
||||||
|
@lockMethod.decorate
|
||||||
def insertintoPlaylist(self, position, dbid=None, mediatype=None, url=None):
|
def insertintoPlaylist(self, position, dbid=None, mediatype=None, url=None):
|
||||||
|
|
||||||
pl = {
|
pl = {
|
||||||
|
@ -226,8 +255,11 @@ class Playlist():
|
||||||
|
|
||||||
self.logMsg(xbmc.executeJSONRPC(json.dumps(pl)), 2)
|
self.logMsg(xbmc.executeJSONRPC(json.dumps(pl)), 2)
|
||||||
|
|
||||||
|
@lockMethod.decorate
|
||||||
def verifyPlaylist(self):
|
def verifyPlaylist(self):
|
||||||
|
self._verifyPlaylist()
|
||||||
|
|
||||||
|
def _verifyPlaylist(self):
|
||||||
pl = {
|
pl = {
|
||||||
|
|
||||||
'jsonrpc': "2.0",
|
'jsonrpc': "2.0",
|
||||||
|
@ -241,6 +273,7 @@ class Playlist():
|
||||||
}
|
}
|
||||||
self.logMsg(xbmc.executeJSONRPC(json.dumps(pl)), 2)
|
self.logMsg(xbmc.executeJSONRPC(json.dumps(pl)), 2)
|
||||||
|
|
||||||
|
@lockMethod.decorate
|
||||||
def removefromPlaylist(self, position):
|
def removefromPlaylist(self, position):
|
||||||
|
|
||||||
pl = {
|
pl = {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import re
|
import re
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from xbmc import Player
|
|
||||||
|
|
||||||
import downloadutils
|
import downloadutils
|
||||||
from utils import window, logging
|
from utils import window, logging
|
||||||
import PlexFunctions as pf
|
import PlexFunctions as pf
|
||||||
|
@ -11,7 +9,7 @@ from functions import *
|
||||||
|
|
||||||
@logging
|
@logging
|
||||||
class SubscriptionManager:
|
class SubscriptionManager:
|
||||||
def __init__(self, jsonClass, RequestMgr):
|
def __init__(self, jsonClass, RequestMgr, player):
|
||||||
self.serverlist = []
|
self.serverlist = []
|
||||||
self.subscribers = {}
|
self.subscribers = {}
|
||||||
self.info = {}
|
self.info = {}
|
||||||
|
@ -25,7 +23,7 @@ class SubscriptionManager:
|
||||||
self.port = ""
|
self.port = ""
|
||||||
self.playerprops = {}
|
self.playerprops = {}
|
||||||
self.doUtils = downloadutils.DownloadUtils().downloadUrl
|
self.doUtils = downloadutils.DownloadUtils().downloadUrl
|
||||||
self.xbmcplayer = Player()
|
self.xbmcplayer = player
|
||||||
|
|
||||||
self.js = jsonClass
|
self.js = jsonClass
|
||||||
self.RequestMgr = RequestMgr
|
self.RequestMgr = RequestMgr
|
||||||
|
|
|
@ -16,6 +16,7 @@ from functools import wraps
|
||||||
from calendar import timegm
|
from calendar import timegm
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcaddon
|
import xbmcaddon
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
|
@ -111,6 +112,19 @@ def IfExists(path):
|
||||||
return answer
|
return answer
|
||||||
|
|
||||||
|
|
||||||
|
def forEveryMethod(decorator):
|
||||||
|
"""
|
||||||
|
Wrapper for classes to add the decorator "decorator" to all methods of the
|
||||||
|
class
|
||||||
|
"""
|
||||||
|
def decorate(cls):
|
||||||
|
for attr in cls.__dict__: # there's propably a better way to do this
|
||||||
|
if callable(getattr(cls, attr)):
|
||||||
|
setattr(cls, attr, decorator(getattr(cls, attr)))
|
||||||
|
return cls
|
||||||
|
return decorate
|
||||||
|
|
||||||
|
|
||||||
def CatchExceptions(warnuser=False):
|
def CatchExceptions(warnuser=False):
|
||||||
"""
|
"""
|
||||||
Decorator for methods to catch exceptions and log them. Useful for e.g.
|
Decorator for methods to catch exceptions and log them. Useful for e.g.
|
||||||
|
|
45
service.py
45
service.py
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime
|
|
||||||
import Queue
|
import Queue
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
|
@ -39,7 +38,6 @@ import clientinfo
|
||||||
import initialsetup
|
import initialsetup
|
||||||
import kodimonitor
|
import kodimonitor
|
||||||
import librarysync
|
import librarysync
|
||||||
import player
|
|
||||||
import videonodes
|
import videonodes
|
||||||
import websocket_client as wsc
|
import websocket_client as wsc
|
||||||
import downloadutils
|
import downloadutils
|
||||||
|
@ -139,12 +137,8 @@ class Service():
|
||||||
user = userclient.UserClient()
|
user = userclient.UserClient()
|
||||||
ws = wsc.WebSocket(queue)
|
ws = wsc.WebSocket(queue)
|
||||||
library = librarysync.LibrarySync(queue)
|
library = librarysync.LibrarySync(queue)
|
||||||
kplayer = player.Player()
|
|
||||||
plx = PlexAPI.PlexAPI()
|
plx = PlexAPI.PlexAPI()
|
||||||
|
|
||||||
# Sync and progress report
|
|
||||||
lastProgressUpdate = datetime.today()
|
|
||||||
|
|
||||||
counter = 0
|
counter = 0
|
||||||
while not monitor.abortRequested():
|
while not monitor.abortRequested():
|
||||||
|
|
||||||
|
@ -153,9 +147,8 @@ class Service():
|
||||||
log("Kodi profile was: %s and changed to: %s. Terminating old "
|
log("Kodi profile was: %s and changed to: %s. Terminating old "
|
||||||
"PlexKodiConnect thread."
|
"PlexKodiConnect thread."
|
||||||
% (kodiProfile, utils.window('plex_kodiProfile')), 1)
|
% (kodiProfile, utils.window('plex_kodiProfile')), 1)
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
# Before proceeding, need to make sure:
|
# Before proceeding, need to make sure:
|
||||||
# 1. Server is online
|
# 1. Server is online
|
||||||
# 2. User is set
|
# 2. User is set
|
||||||
|
@ -165,36 +158,6 @@ class Service():
|
||||||
# Plex server is online
|
# Plex server is online
|
||||||
# Verify if user is set and has access to the server
|
# Verify if user is set and has access to the server
|
||||||
if (user.currUser is not None) and user.HasAccess:
|
if (user.currUser is not None) and user.HasAccess:
|
||||||
# If an item is playing
|
|
||||||
if kplayer.isPlaying():
|
|
||||||
try:
|
|
||||||
# Update and report progress
|
|
||||||
playtime = kplayer.getTime()
|
|
||||||
totalTime = kplayer.getTotalTime()
|
|
||||||
currentFile = kplayer.currentFile
|
|
||||||
|
|
||||||
# Update positionticks
|
|
||||||
if kplayer.played_info.get(currentFile) is not None:
|
|
||||||
kplayer.played_info[currentFile]['currentPosition'] = playtime
|
|
||||||
|
|
||||||
td = datetime.today() - lastProgressUpdate
|
|
||||||
secDiff = td.seconds
|
|
||||||
|
|
||||||
# Report progress to Plex server
|
|
||||||
if (secDiff > 3):
|
|
||||||
kplayer.reportPlayback()
|
|
||||||
lastProgressUpdate = datetime.today()
|
|
||||||
|
|
||||||
elif window('plex_command') == "true":
|
|
||||||
# Received a remote control command that
|
|
||||||
# requires updating immediately
|
|
||||||
window('plex_command', clear=True)
|
|
||||||
kplayer.reportPlayback()
|
|
||||||
lastProgressUpdate = datetime.today()
|
|
||||||
except Exception as e:
|
|
||||||
log("Exception in Playback Monitor Service: %s" % e, 1)
|
|
||||||
pass
|
|
||||||
|
|
||||||
if not self.kodimonitor_running:
|
if not self.kodimonitor_running:
|
||||||
# Start up events
|
# Start up events
|
||||||
self.warn_auth = True
|
self.warn_auth = True
|
||||||
|
@ -208,8 +171,7 @@ class Service():
|
||||||
time=2000,
|
time=2000,
|
||||||
sound=False)
|
sound=False)
|
||||||
# Start monitoring kodi events
|
# Start monitoring kodi events
|
||||||
self.kodimonitor_running = kodimonitor.KodiMonitor(
|
self.kodimonitor_running = kodimonitor.KodiMonitor()
|
||||||
player=kplayer)
|
|
||||||
|
|
||||||
# Start the Websocket Client
|
# Start the Websocket Client
|
||||||
if not self.websocket_running:
|
if not self.websocket_running:
|
||||||
|
@ -222,8 +184,7 @@ class Service():
|
||||||
# Start the Plex Companion thread
|
# Start the Plex Companion thread
|
||||||
if not self.plexCompanion_running:
|
if not self.plexCompanion_running:
|
||||||
self.plexCompanion_running = True
|
self.plexCompanion_running = True
|
||||||
plexCompanion = PlexCompanion.PlexCompanion(
|
plexCompanion = PlexCompanion.PlexCompanion()
|
||||||
player=kplayer)
|
|
||||||
plexCompanion.start()
|
plexCompanion.start()
|
||||||
else:
|
else:
|
||||||
if (user.currUser is None) and self.warn_auth:
|
if (user.currUser is None) and self.warn_auth:
|
||||||
|
|
Loading…
Reference in a new issue