Attempt #1 at fixing playback report/resume
Cleaning up the code, using websocket to report playback progress.
This commit is contained in:
parent
ed899e9365
commit
2f3d609f53
5 changed files with 181 additions and 269 deletions
|
@ -32,16 +32,16 @@ class DownloadUtils():
|
|||
def __init__(self):
|
||||
|
||||
self.__dict__ = self._shared_state
|
||||
self.className = self.__class__.__name__
|
||||
|
||||
def logMsg(self, msg, lvl=1):
|
||||
|
||||
self.className = self.__class__.__name__
|
||||
utils.logMsg("%s %s" % (self.addonName, self.className), msg, int(lvl))
|
||||
|
||||
def setUsername(self, username):
|
||||
# Reserved for UserClient only
|
||||
self.username = username
|
||||
self.logMsg("Set username: %s" % username, 1)
|
||||
self.logMsg("Set username: %s" % username, 2)
|
||||
|
||||
def setUserId(self, userId):
|
||||
# Reserved for UserClient only
|
||||
|
@ -71,8 +71,9 @@ class DownloadUtils():
|
|||
url = "{server}/mediabrowser/Sessions?DeviceId=%s&format=json" % deviceId
|
||||
result = self.downloadUrl(url)
|
||||
# sessionId result
|
||||
self.logMsg("Session result: %s" % result, 1)
|
||||
self.logMsg("Session result: %s" % result, 2)
|
||||
self.sessionId = result[0][u'Id']
|
||||
self.WINDOW.setProperty('sessionId%s' % self.username, self.sessionId)
|
||||
|
||||
# Settings for capabilities
|
||||
playableMediaTypes = "Audio,Video"
|
||||
|
@ -129,7 +130,7 @@ class DownloadUtils():
|
|||
if not authenticate:
|
||||
# If user is not authenticated
|
||||
auth = 'MediaBrowser Client="Kodi", Device="%s", DeviceId="%s", Version="%s"' % (deviceName, deviceId, version)
|
||||
header = {"Accept-encoding": "gzip", "Accept-Charset": "UTF-8,*", "Authorization": auth}
|
||||
header = {'Content-type': 'application/json', 'Accept-encoding': 'gzip', 'Accept-Charset': 'UTF-8,*', 'Authorization': auth}
|
||||
|
||||
self.logMsg("Header: %s" % header, 2)
|
||||
return header
|
||||
|
@ -139,7 +140,7 @@ class DownloadUtils():
|
|||
token = self.token
|
||||
# Attached to the requests session
|
||||
auth = 'MediaBrowser UserId="%s", Client="Kodi", Device="%s", DeviceId="%s", Version="%s"' % (userId, deviceName, deviceId, version)
|
||||
header = {"Accept-encoding": "gzip", "Accept-Charset": "UTF-8,*", "Authorization": auth, "X-MediaBrowser-Token": token}
|
||||
header = {'Content-type': 'application/json', 'Accept-encoding': 'gzip', 'Accept-Charset': 'UTF-8,*', 'Authorization': auth, 'X-MediaBrowser-Token': token}
|
||||
|
||||
self.logMsg("Header: %s" % header, 2)
|
||||
return header
|
||||
|
@ -159,16 +160,16 @@ class DownloadUtils():
|
|||
# Replace for the real values and append api_key
|
||||
url = url.replace("{server}", self.server, 1)
|
||||
url = url.replace("{UserId}", self.userId, 1)
|
||||
url = "%s&api_key=%s" % (url, self.token)
|
||||
#url = "%s&api_key=%s" % (url, self.token)
|
||||
|
||||
self.logMsg("URL: %s" % url, 2)
|
||||
# Prepare request
|
||||
if type == "GET":
|
||||
r = s.get(url, params=postBody, timeout=timeout)
|
||||
r = s.get(url, json=postBody, timeout=timeout)
|
||||
elif type == "POST":
|
||||
r = s.post(url, params=postBody, timeout=timeout)
|
||||
r = s.post(url, json=postBody, timeout=timeout)
|
||||
elif type == "DELETE":
|
||||
r = s.delete(url, params=postBody, timeout=timeout)
|
||||
r = s.delete(url, json=postBody, timeout=timeout)
|
||||
|
||||
# If user is not authenticated
|
||||
elif not authenticate:
|
||||
|
@ -185,9 +186,9 @@ class DownloadUtils():
|
|||
|
||||
# Prepare request
|
||||
if type == "GET":
|
||||
r = requests.get(url, params=postBody, headers=header, timeout=timeout, verify=verifyssl)
|
||||
r = requests.get(url, json=postBody, headers=header, timeout=timeout, verify=verifyssl)
|
||||
elif type == "POST":
|
||||
r = requests.post(url, params=postBody, headers=header, timeout=timeout, verify=verifyssl)
|
||||
r = requests.post(url, json=postBody, headers=header, timeout=timeout, verify=verifyssl)
|
||||
|
||||
# Process the response
|
||||
try:
|
||||
|
|
|
@ -6,8 +6,10 @@ import os
|
|||
import threading
|
||||
import json
|
||||
import inspect
|
||||
|
||||
import KodiMonitor
|
||||
import Utils as utils
|
||||
|
||||
from DownloadUtils import DownloadUtils
|
||||
from WebSocketClient import WebSocketThread
|
||||
from PlayUtils import PlayUtils
|
||||
|
@ -21,36 +23,34 @@ librarySync = LibrarySync()
|
|||
# service class for playback monitoring
|
||||
class Player( xbmc.Player ):
|
||||
|
||||
# Borg - multiple instances, shared state
|
||||
_shared_state = {}
|
||||
|
||||
xbmcplayer = xbmc.Player()
|
||||
doUtils = DownloadUtils()
|
||||
clientInfo = ClientInformation()
|
||||
ws = WebSocketThread()
|
||||
|
||||
addonName = clientInfo.getAddonName()
|
||||
addonId = clientInfo.getAddonId()
|
||||
addon = xbmcaddon.Addon(id=addonId)
|
||||
|
||||
WINDOW = xbmcgui.Window(10000)
|
||||
|
||||
logLevel = 0
|
||||
played_information = {}
|
||||
downloadUtils = None
|
||||
settings = None
|
||||
playStats = {}
|
||||
|
||||
def __init__( self, *args ):
|
||||
|
||||
self.settings = xbmcaddon.Addon(id='plugin.video.emby')
|
||||
self.downloadUtils = DownloadUtils()
|
||||
try:
|
||||
self.logLevel = int(self.settings.getSetting('logLevel'))
|
||||
except:
|
||||
pass
|
||||
self.printDebug("emby Service -> starting playback monitor service",1)
|
||||
self.played_information = {}
|
||||
pass
|
||||
self.__dict__ = self._shared_state
|
||||
self.logMsg("Starting playback monitor service", 1)
|
||||
|
||||
def printDebug(self, msg, level = 1):
|
||||
if(self.logLevel >= level):
|
||||
if(self.logLevel == 2):
|
||||
try:
|
||||
xbmc.log("emby " + str(level) + " -> " + inspect.stack()[1][3] + " : " + str(msg))
|
||||
except UnicodeEncodeError:
|
||||
xbmc.log("emby " + str(level) + " -> " + inspect.stack()[1][3] + " : " + str(msg.encode('utf-8')))
|
||||
else:
|
||||
try:
|
||||
xbmc.log("emby " + str(level) + " -> " + str(msg))
|
||||
except UnicodeEncodeError:
|
||||
xbmc.log("emby " + str(level) + " -> " + str(msg.encode('utf-8')))
|
||||
def logMsg(self, msg, lvl=1):
|
||||
|
||||
self.className = self.__class__.__name__
|
||||
utils.logMsg("%s %s" % (self.addonName, self.className), msg, int(lvl))
|
||||
|
||||
def hasData(self, data):
|
||||
if(data == None or len(data) == 0 or data == "None"):
|
||||
|
@ -60,19 +60,19 @@ class Player( xbmc.Player ):
|
|||
|
||||
def stopAll(self):
|
||||
|
||||
WebSocketThread().processPendingActions()
|
||||
self.ws.processPendingActions()
|
||||
if(len(self.played_information) == 0):
|
||||
return
|
||||
|
||||
addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
|
||||
self.printDebug("emby Service -> played_information : " + str(self.played_information))
|
||||
self.logMsg("emby Service -> played_information : " + str(self.played_information))
|
||||
|
||||
for item_url in self.played_information:
|
||||
data = self.played_information.get(item_url)
|
||||
|
||||
if(data != None):
|
||||
self.printDebug("emby Service -> item_url : " + item_url)
|
||||
self.printDebug("emby Service -> item_data : " + str(data))
|
||||
if (data is not None):
|
||||
self.logMsg("emby Service -> item_url : " + item_url)
|
||||
self.logMsg("emby Service -> item_data : " + str(data))
|
||||
|
||||
runtime = data.get("runtime")
|
||||
currentPosition = data.get("currentPosition")
|
||||
|
@ -83,11 +83,11 @@ class Player( xbmc.Player ):
|
|||
|
||||
if(currentPosition != None and self.hasData(runtime)):
|
||||
runtimeTicks = int(runtime)
|
||||
self.printDebug("emby Service -> runtimeticks:" + str(runtimeTicks))
|
||||
self.logMsg("emby Service -> runtimeticks:" + str(runtimeTicks))
|
||||
percentComplete = (currentPosition * 10000000) / runtimeTicks
|
||||
markPlayedAt = float(90) / 100
|
||||
|
||||
self.printDebug("emby Service -> Percent Complete:" + str(percentComplete) + " Mark Played At:" + str(markPlayedAt))
|
||||
self.logMsg("emby Service -> Percent Complete:" + str(percentComplete) + " Mark Played At:" + str(markPlayedAt))
|
||||
self.stopPlayback(data)
|
||||
|
||||
if(refresh_id != None):
|
||||
|
@ -96,125 +96,116 @@ class Player( xbmc.Player ):
|
|||
|
||||
|
||||
self.played_information.clear()
|
||||
WINDOW = xbmcgui.Window(10000)
|
||||
username = WINDOW.getProperty('currUser')
|
||||
server = WINDOW.getProperty('server%s' % username)
|
||||
|
||||
# stop transcoding - todo check we are actually transcoding?
|
||||
clientInfo = ClientInformation()
|
||||
txt_mac = clientInfo.getMachineId()
|
||||
url = "%s/mediabrowser/Videos/ActiveEncodings" % server
|
||||
url = "{server}/mediabrowser/Videos/ActiveEncodings"
|
||||
url = url + '?DeviceId=' + txt_mac
|
||||
self.downloadUtils.downloadUrl(url, type="DELETE")
|
||||
self.doUtils.downloadUrl(url, type="DELETE")
|
||||
|
||||
def stopPlayback(self, data):
|
||||
self.printDebug("stopPlayback called")
|
||||
addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
|
||||
|
||||
self.logMsg("stopPlayback called", 2)
|
||||
|
||||
item_id = data.get("item_id")
|
||||
audioindex = data.get("AudioStreamIndex")
|
||||
subtitleindex = data.get("SubtitleStreamIndex")
|
||||
playMethod = data.get("playmethod")
|
||||
currentPosition = data.get("currentPosition")
|
||||
positionTicks = str(int(currentPosition * 10000000))
|
||||
positionTicks = int(currentPosition * 10000000)
|
||||
|
||||
WINDOW = xbmcgui.Window(10000)
|
||||
username = WINDOW.getProperty('currUser')
|
||||
server = WINDOW.getProperty('server%s' % username)
|
||||
url = "{server}/mediabrowser/Sessions/Playing/Stopped"
|
||||
|
||||
url = "%s/mediabrowser/Sessions/Playing/Stopped" % server
|
||||
postdata = {
|
||||
'QueueableMediaTypes': "Video",
|
||||
'CanSeek': True,
|
||||
'ItemId': item_id,
|
||||
'MediaSourceId': item_id,
|
||||
'PlayMethod': playMethod,
|
||||
'PositionTicks': positionTicks
|
||||
}
|
||||
|
||||
url = url + "?itemId=" + item_id
|
||||
if audioindex:
|
||||
postdata['AudioStreamIndex'] = audioindex
|
||||
|
||||
url = url + "&canSeek=true"
|
||||
url = url + "&PlayMethod=" + playMethod
|
||||
url = url + "&QueueableMediaTypes=Video"
|
||||
url = url + "&MediaSourceId=" + item_id
|
||||
url = url + "&PositionTicks=" + positionTicks
|
||||
if(audioindex != None and audioindex!=""):
|
||||
url = url + "&AudioStreamIndex=" + audioindex
|
||||
|
||||
if(subtitleindex != None and subtitleindex!=""):
|
||||
url = url + "&SubtitleStreamIndex=" + subtitleindex
|
||||
|
||||
self.downloadUtils.downloadUrl(url, postBody="", type="POST")
|
||||
if subtitleindex:
|
||||
postdata['SubtitleStreamIndex'] = subtitleindex
|
||||
|
||||
self.doUtils.downloadUrl(url, postBody=postdata, type="POST")
|
||||
|
||||
def reportPlayback(self):
|
||||
self.printDebug("reportPlayback Called",2)
|
||||
|
||||
currentFile = xbmc.Player().getPlayingFile()
|
||||
|
||||
#TODO need to change this to use the one in the data map
|
||||
playTime = xbmc.Player().getTime()
|
||||
self.logMsg("reportPlayback Called", 2)
|
||||
xbmcplayer = self.xbmcplayer
|
||||
|
||||
currentFile = xbmcplayer.getPlayingFile()
|
||||
data = self.played_information.get(currentFile)
|
||||
|
||||
# only report playback if emby has initiated the playback (item_id has value)
|
||||
if(data != None and data.get("item_id") != None):
|
||||
addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
|
||||
if (data is not None) and (data.get("item_id") is not None):
|
||||
|
||||
# Get playback information
|
||||
item_id = data.get("item_id")
|
||||
audioindex = data.get("AudioStreamIndex")
|
||||
subtitleindex = data.get("SubtitleStreamIndex")
|
||||
playTime = data.get("currentPosition")
|
||||
playMethod = data.get("playmethod")
|
||||
paused = data.get("paused")
|
||||
|
||||
WINDOW = xbmcgui.Window(10000)
|
||||
username = WINDOW.getProperty('currUser')
|
||||
server = WINDOW.getProperty('server%s' % username)
|
||||
if paused is None:
|
||||
paused = False
|
||||
|
||||
url = "%s/mediabrowser/Sessions/Playing/Progress" % server
|
||||
#url = "{server}/mediabrowser/Sessions/Playing/Progress"
|
||||
postdata = {
|
||||
'QueueableMediaTypes': "Video",
|
||||
'CanSeek': True,
|
||||
'ItemId': item_id,
|
||||
'MediaSourceId': item_id,
|
||||
'IsPaused': paused,
|
||||
'PlayMethod': playMethod
|
||||
}
|
||||
|
||||
url = url + "?itemId=" + item_id
|
||||
if playTime:
|
||||
postdata['PositionTicks'] = int(playTime * 10000000)
|
||||
|
||||
url = url + "&canSeek=true"
|
||||
url = url + "&PlayMethod=" + playMethod
|
||||
url = url + "&QueueableMediaTypes=Video"
|
||||
url = url + "&MediaSourceId=" + item_id
|
||||
if audioindex:
|
||||
postdata['AudioStreamIndex'] = audioindex
|
||||
|
||||
url = url + "&PositionTicks=" + str(int(playTime * 10000000))
|
||||
if subtitleindex:
|
||||
postdata['SubtitleStreamIndex'] = subtitleindex
|
||||
|
||||
if(audioindex != None and audioindex!=""):
|
||||
url = url + "&AudioStreamIndex=" + audioindex
|
||||
|
||||
if(subtitleindex != None and subtitleindex!=""):
|
||||
url = url + "&SubtitleStreamIndex=" + subtitleindex
|
||||
|
||||
if(paused == None):
|
||||
paused = "false"
|
||||
url = url + "&IsPaused=" + paused
|
||||
|
||||
self.downloadUtils.downloadUrl(url, postBody="", type="POST")
|
||||
postdata = json.dumps(postdata)
|
||||
self.logMsg("Report: %s" % postdata)
|
||||
self.ws.sendProgressUpdate(postdata)
|
||||
|
||||
def onPlayBackPaused( self ):
|
||||
currentFile = xbmc.Player().getPlayingFile()
|
||||
self.printDebug("PLAYBACK_PAUSED : " + currentFile,2)
|
||||
self.logMsg("PLAYBACK_PAUSED : " + currentFile,2)
|
||||
if(self.played_information.get(currentFile) != None):
|
||||
self.played_information[currentFile]["paused"] = "true"
|
||||
self.reportPlayback()
|
||||
|
||||
def onPlayBackResumed( self ):
|
||||
currentFile = xbmc.Player().getPlayingFile()
|
||||
self.printDebug("PLAYBACK_RESUMED : " + currentFile,2)
|
||||
self.logMsg("PLAYBACK_RESUMED : " + currentFile,2)
|
||||
if(self.played_information.get(currentFile) != None):
|
||||
self.played_information[currentFile]["paused"] = "false"
|
||||
self.reportPlayback()
|
||||
|
||||
def onPlayBackSeek( self, time, seekOffset ):
|
||||
self.printDebug("PLAYBACK_SEEK",2)
|
||||
self.logMsg("PLAYBACK_SEEK",2)
|
||||
self.reportPlayback()
|
||||
|
||||
def onPlayBackStarted( self ):
|
||||
# Will be called when xbmc starts playing a file
|
||||
WINDOW = xbmcgui.Window( 10000 )
|
||||
WINDOW = self.WINDOW
|
||||
xbmcplayer = self.xbmcplayer
|
||||
self.stopAll()
|
||||
addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
|
||||
xbmcplayer = xbmc.Player()
|
||||
|
||||
if xbmcplayer.isPlaying():
|
||||
currentFile = xbmcplayer.getPlayingFile()
|
||||
self.printDebug("emby Service -> onPlayBackStarted : " + currentFile, 0)
|
||||
self.logMsg("onPlayBackStarted: %s" % currentFile, 0)
|
||||
|
||||
# we may need to wait until the info is available
|
||||
item_id = WINDOW.getProperty(currentFile + "item_id")
|
||||
|
@ -236,33 +227,35 @@ class Player( xbmc.Player ):
|
|||
playMethod = WINDOW.getProperty(currentFile + "playmethod")
|
||||
itemType = WINDOW.getProperty(currentFile + "type")
|
||||
seekTime = WINDOW.getProperty(currentFile + "seektime")
|
||||
|
||||
username = WINDOW.getProperty('currUser')
|
||||
sessionId = WINDOW.getProperty('sessionId%s' % username)
|
||||
|
||||
if seekTime != "":
|
||||
PlaybackUtils().seekToPosition(int(seekTime))
|
||||
|
||||
if(item_id == None or len(item_id) == 0):
|
||||
self.printDebug("emby Service -> onPlayBackStarted : No info for current playing file", 0)
|
||||
if (not item_id) or (len(item_id) == 0):
|
||||
self.logMsg("onPlayBackStarted: No info for current playing file", 0)
|
||||
return
|
||||
|
||||
username = WINDOW.getProperty('currUser')
|
||||
server = WINDOW.getProperty('server%s' % username)
|
||||
url = "{server}/mediabrowser/Sessions/Playing"
|
||||
postdata = {
|
||||
'QueueableMediaTypes': "Video",
|
||||
'CanSeek': True,
|
||||
'ItemId': item_id,
|
||||
'MediaSourceId': item_id,
|
||||
'PlayMethod': playMethod
|
||||
}
|
||||
|
||||
url = "%s/mediabrowser/Sessions/Playing" % server
|
||||
if audioindex:
|
||||
postdata['AudioStreamIndex'] = audioindex
|
||||
|
||||
url = url + "?itemId=" + item_id
|
||||
if subtitleindex:
|
||||
postdata['SubtitleStreamIndex'] = subtitleindex
|
||||
|
||||
url = url + "&canSeek=true"
|
||||
url = url + "&PlayMethod=" + playMethod
|
||||
url = url + "&QueueableMediaTypes=Video"
|
||||
url = url + "&MediaSourceId=" + item_id
|
||||
|
||||
if(audioindex != None and audioindex!=""):
|
||||
url = url + "&AudioStreamIndex=" + audioindex
|
||||
|
||||
if(subtitleindex != None and subtitleindex!=""):
|
||||
url = url + "&SubtitleStreamIndex=" + subtitleindex
|
||||
|
||||
self.printDebug("emby Service -> Sending Post Play Started : " + url, 0)
|
||||
self.downloadUtils.downloadUrl(url, postBody="", type="POST")
|
||||
self.logMsg("Sending POST play started.", 1)
|
||||
#self.logMsg("emby Service -> Sending Post Play Started : " + url, 0)
|
||||
self.doUtils.downloadUrl(url, postBody=postdata, type="POST")
|
||||
|
||||
# save data map for updates and position calls
|
||||
data = {}
|
||||
|
@ -276,8 +269,8 @@ class Player( xbmc.Player ):
|
|||
data["Type"] = itemType
|
||||
self.played_information[currentFile] = data
|
||||
|
||||
self.printDebug("emby Service -> ADDING_FILE : " + currentFile, 0)
|
||||
self.printDebug("emby Service -> ADDING_FILE : " + str(self.played_information), 0)
|
||||
self.logMsg("emby Service -> ADDING_FILE : " + currentFile, 0)
|
||||
self.logMsg("emby Service -> ADDING_FILE : " + str(self.played_information), 0)
|
||||
|
||||
# log some playback stats
|
||||
if(itemType != None):
|
||||
|
@ -302,7 +295,7 @@ class Player( xbmc.Player ):
|
|||
|
||||
def onPlayBackEnded( self ):
|
||||
# Will be called when xbmc stops playing a file
|
||||
self.printDebug("emby Service -> onPlayBackEnded")
|
||||
self.logMsg("onPlayBackEnded", 0)
|
||||
|
||||
#workaround when strm files are launched through the addon - mark watched when finished playing
|
||||
#TODO --> mark watched when 95% is played of the file
|
||||
|
@ -311,12 +304,8 @@ class Player( xbmc.Player ):
|
|||
try:
|
||||
id = WINDOW.getProperty("virtualstrm")
|
||||
type = WINDOW.getProperty("virtualstrmtype")
|
||||
addon = xbmcaddon.Addon(id='plugin.video.emby')
|
||||
username = WINDOW.getProperty('currUser')
|
||||
userid = WINDOW.getProperty('userId%s' % username)
|
||||
server = WINDOW.getProperty('server%s' % username)
|
||||
watchedurl = "%s/mediabrowser/Users/%s/PlayedItems/%s" % (server, userid, id)
|
||||
self.downloadUtils.downloadUrl(watchedurl, postBody="", type="POST")
|
||||
watchedurl = "{server}/mediabrowser/Users/{UserId}/PlayedItems/%s" % id
|
||||
self.doUtils.downloadUrl(watchedurl, postBody="", type="POST")
|
||||
librarySync.updatePlayCount(id)
|
||||
except: pass
|
||||
WINDOW.clearProperty("virtualstrm")
|
||||
|
@ -325,7 +314,7 @@ class Player( xbmc.Player ):
|
|||
|
||||
def onPlayBackStopped( self ):
|
||||
# Will be called when user stops xbmc playing a file
|
||||
self.printDebug("emby Service -> onPlayBackStopped")
|
||||
self.logMsg("onPlayBackStopped", 0)
|
||||
self.stopAll()
|
||||
|
||||
|
||||
|
@ -352,8 +341,8 @@ class Player( xbmc.Player ):
|
|||
if userData!=None and userData["Played"]==True:
|
||||
pDialog = xbmcgui.DialogProgress()
|
||||
seasonId = MB3Episode["SeasonId"]
|
||||
url = "%s/mediabrowser/Users/%s/Items?ParentId=%s&ImageTypeLimit=1&Limit=1&SortBy=SortName&SortOrder=Ascending&Filters=IsUnPlayed&IncludeItemTypes=Episode&IsVirtualUnaired=false&Recursive=true&IsMissing=False&format=json" % (server, userid, seasonId)
|
||||
jsonData = self.downloadUtils.downloadUrl(url, suppress=False, popup=1 )
|
||||
url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s&ImageTypeLimit=1&Limit=1&SortBy=SortName&SortOrder=Ascending&Filters=IsUnPlayed&IncludeItemTypes=Episode&IsVirtualUnaired=false&Recursive=true&IsMissing=False&format=json" % seasonId
|
||||
jsonData = self.doUtils.downloadUrl(url)
|
||||
if(jsonData != ""):
|
||||
seasonData = json.loads(jsonData)
|
||||
if seasonData.get("Items") != None:
|
||||
|
|
|
@ -30,6 +30,8 @@ language = addonSettings.getLocalizedString
|
|||
|
||||
def logMsg(title, msg, level = 1):
|
||||
logLevel = int(addonSettings.getSetting("logLevel"))
|
||||
WINDOW = xbmcgui.Window(10000)
|
||||
WINDOW.setProperty('logLevel', str(logLevel))
|
||||
if(logLevel >= level):
|
||||
if(logLevel == 2): # inspect.stack() is expensive
|
||||
try:
|
||||
|
|
|
@ -13,12 +13,13 @@ import socket
|
|||
import websocket
|
||||
|
||||
import KodiMonitor
|
||||
import Utils as utils
|
||||
|
||||
from ClientInformation import ClientInformation
|
||||
from DownloadUtils import DownloadUtils
|
||||
from PlaybackUtils import PlaybackUtils
|
||||
from LibrarySync import LibrarySync
|
||||
from WriteKodiDB import WriteKodiDB
|
||||
import Utils as utils
|
||||
|
||||
pendingUserDataList = []
|
||||
pendingItemsToRemove = []
|
||||
|
@ -27,79 +28,39 @@ _MODE_BASICPLAY=12
|
|||
|
||||
class WebSocketThread(threading.Thread):
|
||||
|
||||
logLevel = 0
|
||||
_shared_state = {}
|
||||
|
||||
clientInfo = ClientInformation()
|
||||
KodiMonitor = KodiMonitor.Kodi_Monitor()
|
||||
addonName = clientInfo.getAddonName()
|
||||
|
||||
client = None
|
||||
keepRunning = True
|
||||
|
||||
def __init__(self, *args):
|
||||
|
||||
self.KodiMonitor = KodiMonitor.Kodi_Monitor()
|
||||
addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
|
||||
level = addonSettings.getSetting('logLevel')
|
||||
self.logLevel = 0
|
||||
if(level != None):
|
||||
self.logLevel = int(level)
|
||||
|
||||
xbmc.log("emby WebSocketThread -> Log Level:" + str(self.logLevel))
|
||||
|
||||
self.__dict__ = self._shared_state
|
||||
threading.Thread.__init__(self, *args)
|
||||
|
||||
def logMsg(self, msg, level = 1):
|
||||
if(self.logLevel >= level):
|
||||
try:
|
||||
xbmc.log("emby WebSocketThread -> " + str(msg))
|
||||
except UnicodeEncodeError:
|
||||
try:
|
||||
xbmc.log("emby WebSocketThread -> " + str(msg.encode('utf-8')))
|
||||
except: pass
|
||||
def logMsg(self, msg, lvl=1):
|
||||
|
||||
'''
|
||||
def playbackStarted(self, itemId):
|
||||
if(self.client != None):
|
||||
try:
|
||||
self.logMsg("Sending Playback Started")
|
||||
messageData = {}
|
||||
messageData["MessageType"] = "PlaybackStart"
|
||||
messageData["Data"] = itemId + "|true|audio,video"
|
||||
messageString = json.dumps(messageData)
|
||||
self.logMsg("Message Data : " + messageString)
|
||||
self.client.send(messageString)
|
||||
except Exception, e:
|
||||
self.logMsg("Exception : " + str(e), level=0)
|
||||
else:
|
||||
self.logMsg("Sending Playback Started NO Object ERROR")
|
||||
self.className = self.__class__.__name__
|
||||
utils.logMsg("%s %s" % (self.addonName, self.className), msg, int(lvl))
|
||||
|
||||
def playbackStopped(self, itemId, ticks):
|
||||
if(self.client != None):
|
||||
def sendProgressUpdate(self, data):
|
||||
self.logMsg("sendProgressUpdate", 1)
|
||||
if self.client:
|
||||
try:
|
||||
self.logMsg("Sending Playback Stopped")
|
||||
messageData = {}
|
||||
messageData["MessageType"] = "PlaybackStopped"
|
||||
messageData["Data"] = itemId + "|" + str(ticks)
|
||||
# Send progress update
|
||||
messageData = {
|
||||
'MessageType': "ReportPlaybackProgress",
|
||||
'Data': data
|
||||
}
|
||||
messageString = json.dumps(messageData)
|
||||
self.client.send(messageString)
|
||||
self.logMsg("Message data: %s" % messageString, 2)
|
||||
except Exception, e:
|
||||
self.logMsg("Exception : " + str(e), level=0)
|
||||
else:
|
||||
self.logMsg("Sending Playback Stopped NO Object ERROR")
|
||||
'''
|
||||
|
||||
'''
|
||||
def sendProgressUpdate(self, itemId, ticks):
|
||||
if(self.client != None):
|
||||
try:
|
||||
self.logMsg("Sending Progress Update")
|
||||
messageData = {}
|
||||
messageData["MessageType"] = "PlaybackProgress"
|
||||
messageData["Data"] = itemId + "|" + str(ticks) + "|false|false"
|
||||
messageString = json.dumps(messageData)
|
||||
self.logMsg("Message Data : " + messageString)
|
||||
self.client.send(messageString)
|
||||
except Exception, e:
|
||||
self.logMsg("Exception : " + str(e), level=0)
|
||||
else:
|
||||
self.logMsg("Sending Progress Update NO Object ERROR")
|
||||
'''
|
||||
self.logMsg("Exception: %s" % e, 1)
|
||||
|
||||
def stopClient(self):
|
||||
# stopping the client is tricky, first set keep_running to false and then trigger one
|
||||
|
@ -253,69 +214,30 @@ class WebSocketThread(threading.Thread):
|
|||
self.logMsg("Closed")
|
||||
|
||||
def on_open(self, ws):
|
||||
|
||||
clientInfo = ClientInformation()
|
||||
machineId = clientInfo.getMachineId()
|
||||
version = clientInfo.getVersion()
|
||||
messageData = {}
|
||||
messageData["MessageType"] = "Identity"
|
||||
|
||||
addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
|
||||
deviceName = addonSettings.getSetting('deviceName')
|
||||
deviceName = deviceName.replace("\"", "_")
|
||||
|
||||
messageData["Data"] = "Kodi|" + machineId + "|" + version + "|" + deviceName
|
||||
messageString = json.dumps(messageData)
|
||||
self.logMsg("Opened : " + str(messageString))
|
||||
ws.send(messageString)
|
||||
'''
|
||||
# Set Capabilities
|
||||
xbmc.log("postcapabilities_called")
|
||||
downloadUtils = DownloadUtils()
|
||||
downloadUtils.startSession()'''
|
||||
|
||||
|
||||
def getWebSocketPort(self, host, port):
|
||||
|
||||
userUrl = "http://" + host + ":" + port + "/mediabrowser/System/Info?format=json"
|
||||
|
||||
downloadUtils = DownloadUtils()
|
||||
jsonData = downloadUtils.downloadUrl(userUrl, suppress=False, popup=1 )
|
||||
if(jsonData == ""):
|
||||
return -1
|
||||
|
||||
result = json.loads(jsonData)
|
||||
|
||||
wsPort = result.get("WebSocketPortNumber")
|
||||
if(wsPort != None):
|
||||
return wsPort
|
||||
else:
|
||||
return -1
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
|
||||
|
||||
WINDOW = xbmcgui.Window(10000)
|
||||
logLevel = int(WINDOW.getProperty('logLevel'))
|
||||
username = WINDOW.getProperty('currUser')
|
||||
server = WINDOW.getProperty('server%s' % username)
|
||||
host = WINDOW.getProperty('server_%s' % username)
|
||||
token = WINDOW.getProperty('accessToken%s' % username)
|
||||
deviceId = ClientInformation().getMachineId()
|
||||
|
||||
if(self.logLevel >= 1):
|
||||
if (logLevel == 2):
|
||||
websocket.enableTrace(True)
|
||||
'''
|
||||
wsPort = self.getWebSocketPort(mb3Host, mb3Port);
|
||||
self.logMsg("WebSocketPortNumber = " + str(wsPort))
|
||||
if(wsPort == -1):
|
||||
self.logMsg("Could not retrieve WebSocket port, can not run WebScoket Client")
|
||||
return
|
||||
'''
|
||||
|
||||
# Get the appropriate prefix for websocket
|
||||
if "https" in server:
|
||||
webSocketUrl = "wss://%s/mediabrowser" % host
|
||||
server = server.replace('https', 'wss')
|
||||
else:
|
||||
webSocketUrl = "ws://%s/mediabrowser" % host
|
||||
# Make a call to /System/Info. WebSocketPortNumber is the port hosting the web socket.
|
||||
#webSocketUrl = "ws://" + host + "/mediabrowser"
|
||||
self.logMsg("WebSocket URL : " + webSocketUrl)
|
||||
self.client = websocket.WebSocketApp(webSocketUrl,
|
||||
server = server.replace('http', 'ws')
|
||||
|
||||
websocketUrl = "%s?api_key=%s&deviceId=%s" % (server, token, deviceId)
|
||||
self.logMsg("websocket URL: %s" % websocketUrl)
|
||||
|
||||
self.client = websocket.WebSocketApp(websocketUrl,
|
||||
on_message = self.on_message,
|
||||
on_error = self.on_error,
|
||||
on_close = self.on_close)
|
||||
|
@ -345,4 +267,3 @@ class WebSocketThread(threading.Thread):
|
|||
if pendingItemsToUpdate != []:
|
||||
self.update_items(pendingItemsToUpdate)
|
||||
pendingItemsToUpdate = []
|
||||
|
||||
|
|
19
service.py
19
service.py
|
@ -35,16 +35,15 @@ class Service():
|
|||
def __init__(self, *args ):
|
||||
self.KodiMonitor = KodiMonitor.Kodi_Monitor()
|
||||
addonName = self.addonName
|
||||
self.className = self.__class__.__name__
|
||||
|
||||
self.logMsg("Starting Monitor", 0)
|
||||
self.logMsg("======== START %s ========" % addonName, 0)
|
||||
self.logMsg("KODI Version: %s" % xbmc.getInfoLabel("System.BuildVersion"), 0)
|
||||
self.logMsg("%s Version: %s" % (addonName, self.clientInfo.getVersion()), 0)
|
||||
pass
|
||||
|
||||
def logMsg(self, msg, lvl=1):
|
||||
|
||||
self.className = self.__class__.__name__
|
||||
utils.logMsg("%s %s" % (self.addonName, self.className), str(msg), int(lvl))
|
||||
|
||||
def ServiceEntryPoint(self):
|
||||
|
@ -84,11 +83,11 @@ class Service():
|
|||
# send update
|
||||
td = datetime.today() - lastProgressUpdate
|
||||
secDiff = td.seconds
|
||||
if(secDiff > 10):
|
||||
if(secDiff > 3):
|
||||
try:
|
||||
player.reportPlayback()
|
||||
except Exception, msg:
|
||||
xbmc.log("MB3 Sync Service -> Exception reporting progress : " + msg)
|
||||
self.logMsg("Exception reporting progress: %s" % msg)
|
||||
pass
|
||||
lastProgressUpdate = datetime.today()
|
||||
# only try autoplay when there's 20 seconds or less remaining and only once!
|
||||
|
@ -97,7 +96,7 @@ class Service():
|
|||
player.autoPlayPlayback()
|
||||
|
||||
except Exception, e:
|
||||
xbmc.log("MB3 Sync Service -> Exception in Playback Monitor Service : " + str(e))
|
||||
self.logMsg("Exception in Playback Monitor Service: %s" % e)
|
||||
pass
|
||||
else:
|
||||
if (self.newUserClient == None):
|
||||
|
@ -113,11 +112,11 @@ class Service():
|
|||
|
||||
#full sync
|
||||
if(startupComplete == False):
|
||||
xbmc.log("Doing_Db_Sync: syncDatabase (Started)")
|
||||
self.logMsg("Doing_Db_Sync: syncDatabase (Started)")
|
||||
libSync = librarySync.syncDatabase()
|
||||
xbmc.log("Doing_Db_Sync: syncDatabase (Finished) " + str(libSync))
|
||||
self.logMsg("Doing_Db_Sync: syncDatabase (Finished) " + str(libSync))
|
||||
countSync = librarySync.updatePlayCounts()
|
||||
xbmc.log("Doing_Db_Sync: updatePlayCounts (Finished) " + str(countSync))
|
||||
self.logMsg("Doing_Db_Sync: updatePlayCounts (Finished) " + str(countSync))
|
||||
|
||||
# Force refresh newly set thumbnails
|
||||
xbmc.executebuiltin("UpdateLibrary(video)")
|
||||
|
@ -130,9 +129,9 @@ class Service():
|
|||
WebSocketThread().processPendingActions()
|
||||
|
||||
else:
|
||||
xbmc.log("Not authenticated yet")
|
||||
self.logMsg("Not authenticated yet", 0)
|
||||
|
||||
utils.logMsg("MB3 Sync Service", "stopping Service",0)
|
||||
self.logMsg("stopping Service", 0)
|
||||
|
||||
# If user reset library database.
|
||||
WINDOW = xbmcgui.Window(10000)
|
||||
|
|
Loading…
Reference in a new issue