Attempt #1 at fixing playback report/resume

Cleaning up the code, using websocket to report playback progress.
This commit is contained in:
angelblue05 2015-04-28 17:23:26 -05:00
parent ed899e9365
commit 2f3d609f53
5 changed files with 181 additions and 269 deletions

View file

@ -32,16 +32,16 @@ class DownloadUtils():
def __init__(self): def __init__(self):
self.__dict__ = self._shared_state self.__dict__ = self._shared_state
self.className = self.__class__.__name__
def logMsg(self, msg, lvl=1): def logMsg(self, msg, lvl=1):
self.className = self.__class__.__name__
utils.logMsg("%s %s" % (self.addonName, self.className), msg, int(lvl)) utils.logMsg("%s %s" % (self.addonName, self.className), msg, int(lvl))
def setUsername(self, username): def setUsername(self, username):
# Reserved for UserClient only # Reserved for UserClient only
self.username = username self.username = username
self.logMsg("Set username: %s" % username, 1) self.logMsg("Set username: %s" % username, 2)
def setUserId(self, userId): def setUserId(self, userId):
# Reserved for UserClient only # Reserved for UserClient only
@ -71,8 +71,9 @@ class DownloadUtils():
url = "{server}/mediabrowser/Sessions?DeviceId=%s&format=json" % deviceId url = "{server}/mediabrowser/Sessions?DeviceId=%s&format=json" % deviceId
result = self.downloadUrl(url) result = self.downloadUrl(url)
# sessionId result # sessionId result
self.logMsg("Session result: %s" % result, 1) self.logMsg("Session result: %s" % result, 2)
self.sessionId = result[0][u'Id'] self.sessionId = result[0][u'Id']
self.WINDOW.setProperty('sessionId%s' % self.username, self.sessionId)
# Settings for capabilities # Settings for capabilities
playableMediaTypes = "Audio,Video" playableMediaTypes = "Audio,Video"
@ -129,7 +130,7 @@ class DownloadUtils():
if not authenticate: if not authenticate:
# If user is not authenticated # If user is not authenticated
auth = 'MediaBrowser Client="Kodi", Device="%s", DeviceId="%s", Version="%s"' % (deviceName, deviceId, version) 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) self.logMsg("Header: %s" % header, 2)
return header return header
@ -139,7 +140,7 @@ class DownloadUtils():
token = self.token token = self.token
# Attached to the requests session # Attached to the requests session
auth = 'MediaBrowser UserId="%s", Client="Kodi", Device="%s", DeviceId="%s", Version="%s"' % (userId, deviceName, deviceId, version) 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) self.logMsg("Header: %s" % header, 2)
return header return header
@ -159,16 +160,16 @@ class DownloadUtils():
# Replace for the real values and append api_key # Replace for the real values and append api_key
url = url.replace("{server}", self.server, 1) url = url.replace("{server}", self.server, 1)
url = url.replace("{UserId}", self.userId, 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) self.logMsg("URL: %s" % url, 2)
# Prepare request # Prepare request
if type == "GET": if type == "GET":
r = s.get(url, params=postBody, timeout=timeout) r = s.get(url, json=postBody, timeout=timeout)
elif type == "POST": elif type == "POST":
r = s.post(url, params=postBody, timeout=timeout) r = s.post(url, json=postBody, timeout=timeout)
elif type == "DELETE": elif type == "DELETE":
r = s.delete(url, params=postBody, timeout=timeout) r = s.delete(url, json=postBody, timeout=timeout)
# If user is not authenticated # If user is not authenticated
elif not authenticate: elif not authenticate:
@ -185,9 +186,9 @@ class DownloadUtils():
# Prepare request # Prepare request
if type == "GET": 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": 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 # Process the response
try: try:

View file

@ -6,8 +6,10 @@ import os
import threading import threading
import json import json
import inspect import inspect
import KodiMonitor import KodiMonitor
import Utils as utils import Utils as utils
from DownloadUtils import DownloadUtils from DownloadUtils import DownloadUtils
from WebSocketClient import WebSocketThread from WebSocketClient import WebSocketThread
from PlayUtils import PlayUtils from PlayUtils import PlayUtils
@ -21,36 +23,34 @@ librarySync = LibrarySync()
# service class for playback monitoring # service class for playback monitoring
class Player( xbmc.Player ): 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 logLevel = 0
played_information = {} played_information = {}
downloadUtils = None
settings = None settings = None
playStats = {} playStats = {}
def __init__( self, *args ): def __init__( self, *args ):
self.settings = xbmcaddon.Addon(id='plugin.video.emby') self.__dict__ = self._shared_state
self.downloadUtils = DownloadUtils() self.logMsg("Starting playback monitor service", 1)
try:
self.logLevel = int(self.settings.getSetting('logLevel'))
except:
pass
self.printDebug("emby Service -> starting playback monitor service",1)
self.played_information = {}
pass
def printDebug(self, msg, level = 1): def logMsg(self, msg, lvl=1):
if(self.logLevel >= level):
if(self.logLevel == 2): self.className = self.__class__.__name__
try: utils.logMsg("%s %s" % (self.addonName, self.className), msg, int(lvl))
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 hasData(self, data): def hasData(self, data):
if(data == None or len(data) == 0 or data == "None"): if(data == None or len(data) == 0 or data == "None"):
@ -60,19 +60,19 @@ class Player( xbmc.Player ):
def stopAll(self): def stopAll(self):
WebSocketThread().processPendingActions() self.ws.processPendingActions()
if(len(self.played_information) == 0): if(len(self.played_information) == 0):
return return
addonSettings = xbmcaddon.Addon(id='plugin.video.emby') 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: for item_url in self.played_information:
data = self.played_information.get(item_url) data = self.played_information.get(item_url)
if(data != None): if (data is not None):
self.printDebug("emby Service -> item_url : " + item_url) self.logMsg("emby Service -> item_url : " + item_url)
self.printDebug("emby Service -> item_data : " + str(data)) self.logMsg("emby Service -> item_data : " + str(data))
runtime = data.get("runtime") runtime = data.get("runtime")
currentPosition = data.get("currentPosition") currentPosition = data.get("currentPosition")
@ -83,11 +83,11 @@ class Player( xbmc.Player ):
if(currentPosition != None and self.hasData(runtime)): if(currentPosition != None and self.hasData(runtime)):
runtimeTicks = int(runtime) runtimeTicks = int(runtime)
self.printDebug("emby Service -> runtimeticks:" + str(runtimeTicks)) self.logMsg("emby Service -> runtimeticks:" + str(runtimeTicks))
percentComplete = (currentPosition * 10000000) / runtimeTicks percentComplete = (currentPosition * 10000000) / runtimeTicks
markPlayedAt = float(90) / 100 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) self.stopPlayback(data)
if(refresh_id != None): if(refresh_id != None):
@ -96,125 +96,116 @@ class Player( xbmc.Player ):
self.played_information.clear() 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? # stop transcoding - todo check we are actually transcoding?
clientInfo = ClientInformation() clientInfo = ClientInformation()
txt_mac = clientInfo.getMachineId() txt_mac = clientInfo.getMachineId()
url = "%s/mediabrowser/Videos/ActiveEncodings" % server url = "{server}/mediabrowser/Videos/ActiveEncodings"
url = url + '?DeviceId=' + txt_mac url = url + '?DeviceId=' + txt_mac
self.downloadUtils.downloadUrl(url, type="DELETE") self.doUtils.downloadUrl(url, type="DELETE")
def stopPlayback(self, data): 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") item_id = data.get("item_id")
audioindex = data.get("AudioStreamIndex") audioindex = data.get("AudioStreamIndex")
subtitleindex = data.get("SubtitleStreamIndex") subtitleindex = data.get("SubtitleStreamIndex")
playMethod = data.get("playmethod") playMethod = data.get("playmethod")
currentPosition = data.get("currentPosition") currentPosition = data.get("currentPosition")
positionTicks = str(int(currentPosition * 10000000)) positionTicks = int(currentPosition * 10000000)
url = "{server}/mediabrowser/Sessions/Playing/Stopped"
WINDOW = xbmcgui.Window(10000) postdata = {
username = WINDOW.getProperty('currUser') 'QueueableMediaTypes': "Video",
server = WINDOW.getProperty('server%s' % username) 'CanSeek': True,
'ItemId': item_id,
'MediaSourceId': item_id,
'PlayMethod': playMethod,
'PositionTicks': positionTicks
}
url = "%s/mediabrowser/Sessions/Playing/Stopped" % server if audioindex:
postdata['AudioStreamIndex'] = audioindex
url = url + "?itemId=" + item_id
url = url + "&canSeek=true" if subtitleindex:
url = url + "&PlayMethod=" + playMethod postdata['SubtitleStreamIndex'] = subtitleindex
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!=""): self.doUtils.downloadUrl(url, postBody=postdata, type="POST")
url = url + "&SubtitleStreamIndex=" + subtitleindex
self.downloadUtils.downloadUrl(url, postBody="", type="POST")
def reportPlayback(self): 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) data = self.played_information.get(currentFile)
# only report playback if emby has initiated the playback (item_id has value) # only report playback if emby has initiated the playback (item_id has value)
if(data != None and data.get("item_id") != None): if (data is not None) and (data.get("item_id") is not None):
addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
# Get playback information
item_id = data.get("item_id") item_id = data.get("item_id")
audioindex = data.get("AudioStreamIndex") audioindex = data.get("AudioStreamIndex")
subtitleindex = data.get("SubtitleStreamIndex") subtitleindex = data.get("SubtitleStreamIndex")
playTime = data.get("currentPosition")
playMethod = data.get("playmethod") playMethod = data.get("playmethod")
paused = data.get("paused") paused = data.get("paused")
if paused is None:
paused = False
WINDOW = xbmcgui.Window(10000) #url = "{server}/mediabrowser/Sessions/Playing/Progress"
username = WINDOW.getProperty('currUser') postdata = {
server = WINDOW.getProperty('server%s' % username) 'QueueableMediaTypes': "Video",
'CanSeek': True,
url = "%s/mediabrowser/Sessions/Playing/Progress" % server 'ItemId': item_id,
'MediaSourceId': item_id,
url = url + "?itemId=" + item_id 'IsPaused': paused,
'PlayMethod': playMethod
}
url = url + "&canSeek=true" if playTime:
url = url + "&PlayMethod=" + playMethod postdata['PositionTicks'] = int(playTime * 10000000)
url = url + "&QueueableMediaTypes=Video"
url = url + "&MediaSourceId=" + item_id if audioindex:
postdata['AudioStreamIndex'] = audioindex
url = url + "&PositionTicks=" + str(int(playTime * 10000000))
if subtitleindex:
if(audioindex != None and audioindex!=""): postdata['SubtitleStreamIndex'] = subtitleindex
url = url + "&AudioStreamIndex=" + audioindex
postdata = json.dumps(postdata)
if(subtitleindex != None and subtitleindex!=""): self.logMsg("Report: %s" % postdata)
url = url + "&SubtitleStreamIndex=" + subtitleindex self.ws.sendProgressUpdate(postdata)
if(paused == None):
paused = "false"
url = url + "&IsPaused=" + paused
self.downloadUtils.downloadUrl(url, postBody="", type="POST")
def onPlayBackPaused( self ): def onPlayBackPaused( self ):
currentFile = xbmc.Player().getPlayingFile() currentFile = xbmc.Player().getPlayingFile()
self.printDebug("PLAYBACK_PAUSED : " + currentFile,2) self.logMsg("PLAYBACK_PAUSED : " + currentFile,2)
if(self.played_information.get(currentFile) != None): if(self.played_information.get(currentFile) != None):
self.played_information[currentFile]["paused"] = "true" self.played_information[currentFile]["paused"] = "true"
self.reportPlayback() self.reportPlayback()
def onPlayBackResumed( self ): def onPlayBackResumed( self ):
currentFile = xbmc.Player().getPlayingFile() currentFile = xbmc.Player().getPlayingFile()
self.printDebug("PLAYBACK_RESUMED : " + currentFile,2) self.logMsg("PLAYBACK_RESUMED : " + currentFile,2)
if(self.played_information.get(currentFile) != None): if(self.played_information.get(currentFile) != None):
self.played_information[currentFile]["paused"] = "false" self.played_information[currentFile]["paused"] = "false"
self.reportPlayback() self.reportPlayback()
def onPlayBackSeek( self, time, seekOffset ): def onPlayBackSeek( self, time, seekOffset ):
self.printDebug("PLAYBACK_SEEK",2) self.logMsg("PLAYBACK_SEEK",2)
self.reportPlayback() self.reportPlayback()
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 = xbmcgui.Window( 10000 ) WINDOW = self.WINDOW
xbmcplayer = self.xbmcplayer
self.stopAll() self.stopAll()
addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
xbmcplayer = xbmc.Player()
if xbmcplayer.isPlaying(): if xbmcplayer.isPlaying():
currentFile = xbmcplayer.getPlayingFile() 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 # we may need to wait until the info is available
item_id = WINDOW.getProperty(currentFile + "item_id") item_id = WINDOW.getProperty(currentFile + "item_id")
@ -236,33 +227,35 @@ class Player( xbmc.Player ):
playMethod = WINDOW.getProperty(currentFile + "playmethod") playMethod = WINDOW.getProperty(currentFile + "playmethod")
itemType = WINDOW.getProperty(currentFile + "type") itemType = WINDOW.getProperty(currentFile + "type")
seekTime = WINDOW.getProperty(currentFile + "seektime") seekTime = WINDOW.getProperty(currentFile + "seektime")
username = WINDOW.getProperty('currUser')
sessionId = WINDOW.getProperty('sessionId%s' % username)
if seekTime != "": if seekTime != "":
PlaybackUtils().seekToPosition(int(seekTime)) PlaybackUtils().seekToPosition(int(seekTime))
if(item_id == None or len(item_id) == 0): if (not item_id) or (len(item_id) == 0):
self.printDebug("emby Service -> onPlayBackStarted : No info for current playing file", 0) self.logMsg("onPlayBackStarted: No info for current playing file", 0)
return return
username = WINDOW.getProperty('currUser') url = "{server}/mediabrowser/Sessions/Playing"
server = WINDOW.getProperty('server%s' % username) 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!=""): self.logMsg("Sending POST play started.", 1)
url = url + "&AudioStreamIndex=" + audioindex #self.logMsg("emby Service -> Sending Post Play Started : " + url, 0)
self.doUtils.downloadUrl(url, postBody=postdata, type="POST")
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")
# save data map for updates and position calls # save data map for updates and position calls
data = {} data = {}
@ -276,8 +269,8 @@ class Player( xbmc.Player ):
data["Type"] = itemType data["Type"] = itemType
self.played_information[currentFile] = data self.played_information[currentFile] = data
self.printDebug("emby Service -> ADDING_FILE : " + currentFile, 0) self.logMsg("emby Service -> ADDING_FILE : " + currentFile, 0)
self.printDebug("emby Service -> ADDING_FILE : " + str(self.played_information), 0) self.logMsg("emby Service -> ADDING_FILE : " + str(self.played_information), 0)
# log some playback stats # log some playback stats
if(itemType != None): if(itemType != None):
@ -302,7 +295,7 @@ class Player( xbmc.Player ):
def onPlayBackEnded( self ): def onPlayBackEnded( self ):
# Will be called when xbmc stops playing a file # 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 #workaround when strm files are launched through the addon - mark watched when finished playing
#TODO --> mark watched when 95% is played of the file #TODO --> mark watched when 95% is played of the file
@ -311,12 +304,8 @@ class Player( xbmc.Player ):
try: try:
id = WINDOW.getProperty("virtualstrm") id = WINDOW.getProperty("virtualstrm")
type = WINDOW.getProperty("virtualstrmtype") type = WINDOW.getProperty("virtualstrmtype")
addon = xbmcaddon.Addon(id='plugin.video.emby') watchedurl = "{server}/mediabrowser/Users/{UserId}/PlayedItems/%s" % id
username = WINDOW.getProperty('currUser') self.doUtils.downloadUrl(watchedurl, postBody="", type="POST")
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")
librarySync.updatePlayCount(id) librarySync.updatePlayCount(id)
except: pass except: pass
WINDOW.clearProperty("virtualstrm") WINDOW.clearProperty("virtualstrm")
@ -325,7 +314,7 @@ class Player( xbmc.Player ):
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
self.printDebug("emby Service -> onPlayBackStopped") self.logMsg("onPlayBackStopped", 0)
self.stopAll() self.stopAll()
@ -352,8 +341,8 @@ class Player( xbmc.Player ):
if userData!=None and userData["Played"]==True: if userData!=None and userData["Played"]==True:
pDialog = xbmcgui.DialogProgress() pDialog = xbmcgui.DialogProgress()
seasonId = MB3Episode["SeasonId"] 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) 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.downloadUtils.downloadUrl(url, suppress=False, popup=1 ) jsonData = self.doUtils.downloadUrl(url)
if(jsonData != ""): if(jsonData != ""):
seasonData = json.loads(jsonData) seasonData = json.loads(jsonData)
if seasonData.get("Items") != None: if seasonData.get("Items") != None:

View file

@ -30,6 +30,8 @@ language = addonSettings.getLocalizedString
def logMsg(title, msg, level = 1): def logMsg(title, msg, level = 1):
logLevel = int(addonSettings.getSetting("logLevel")) logLevel = int(addonSettings.getSetting("logLevel"))
WINDOW = xbmcgui.Window(10000)
WINDOW.setProperty('logLevel', str(logLevel))
if(logLevel >= level): if(logLevel >= level):
if(logLevel == 2): # inspect.stack() is expensive if(logLevel == 2): # inspect.stack() is expensive
try: try:

View file

@ -13,12 +13,13 @@ import socket
import websocket import websocket
import KodiMonitor import KodiMonitor
import Utils as utils
from ClientInformation import ClientInformation from ClientInformation import ClientInformation
from DownloadUtils import DownloadUtils from DownloadUtils import DownloadUtils
from PlaybackUtils import PlaybackUtils from PlaybackUtils import PlaybackUtils
from LibrarySync import LibrarySync from LibrarySync import LibrarySync
from WriteKodiDB import WriteKodiDB from WriteKodiDB import WriteKodiDB
import Utils as utils
pendingUserDataList = [] pendingUserDataList = []
pendingItemsToRemove = [] pendingItemsToRemove = []
@ -27,79 +28,39 @@ _MODE_BASICPLAY=12
class WebSocketThread(threading.Thread): class WebSocketThread(threading.Thread):
logLevel = 0 _shared_state = {}
clientInfo = ClientInformation()
KodiMonitor = KodiMonitor.Kodi_Monitor()
addonName = clientInfo.getAddonName()
client = None client = None
keepRunning = True keepRunning = True
def __init__(self, *args): def __init__(self, *args):
self.KodiMonitor = KodiMonitor.Kodi_Monitor() self.__dict__ = self._shared_state
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))
threading.Thread.__init__(self, *args) threading.Thread.__init__(self, *args)
def logMsg(self, msg, level = 1): def logMsg(self, msg, lvl=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 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")
def playbackStopped(self, itemId, ticks): self.className = self.__class__.__name__
if(self.client != None): utils.logMsg("%s %s" % (self.addonName, self.className), msg, int(lvl))
def sendProgressUpdate(self, data):
self.logMsg("sendProgressUpdate", 1)
if self.client:
try: try:
self.logMsg("Sending Playback Stopped") # Send progress update
messageData = {} messageData = {
messageData["MessageType"] = "PlaybackStopped" 'MessageType': "ReportPlaybackProgress",
messageData["Data"] = itemId + "|" + str(ticks) 'Data': data
}
messageString = json.dumps(messageData) messageString = json.dumps(messageData)
self.client.send(messageString) self.client.send(messageString)
self.logMsg("Message data: %s" % messageString, 2)
except Exception, e: except Exception, e:
self.logMsg("Exception : " + str(e), level=0) self.logMsg("Exception: %s" % e, 1)
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")
'''
def stopClient(self): def stopClient(self):
# stopping the client is tricky, first set keep_running to false and then trigger one # 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") self.logMsg("Closed")
def on_open(self, ws): def on_open(self, ws):
pass
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
def run(self): def run(self):
addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
WINDOW = xbmcgui.Window(10000) WINDOW = xbmcgui.Window(10000)
logLevel = int(WINDOW.getProperty('logLevel'))
username = WINDOW.getProperty('currUser') username = WINDOW.getProperty('currUser')
server = WINDOW.getProperty('server%s' % username) 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) websocket.enableTrace(True)
'''
wsPort = self.getWebSocketPort(mb3Host, mb3Port); # Get the appropriate prefix for websocket
self.logMsg("WebSocketPortNumber = " + str(wsPort))
if(wsPort == -1):
self.logMsg("Could not retrieve WebSocket port, can not run WebScoket Client")
return
'''
if "https" in server: if "https" in server:
webSocketUrl = "wss://%s/mediabrowser" % host server = server.replace('https', 'wss')
else: else:
webSocketUrl = "ws://%s/mediabrowser" % host server = server.replace('http', 'ws')
# Make a call to /System/Info. WebSocketPortNumber is the port hosting the web socket.
#webSocketUrl = "ws://" + host + "/mediabrowser" websocketUrl = "%s?api_key=%s&deviceId=%s" % (server, token, deviceId)
self.logMsg("WebSocket URL : " + webSocketUrl) self.logMsg("websocket URL: %s" % websocketUrl)
self.client = websocket.WebSocketApp(webSocketUrl,
self.client = websocket.WebSocketApp(websocketUrl,
on_message = self.on_message, on_message = self.on_message,
on_error = self.on_error, on_error = self.on_error,
on_close = self.on_close) on_close = self.on_close)
@ -344,5 +266,4 @@ class WebSocketThread(threading.Thread):
pendingItemsToRemove = [] pendingItemsToRemove = []
if pendingItemsToUpdate != []: if pendingItemsToUpdate != []:
self.update_items(pendingItemsToUpdate) self.update_items(pendingItemsToUpdate)
pendingItemsToUpdate = [] pendingItemsToUpdate = []

View file

@ -35,16 +35,15 @@ class Service():
def __init__(self, *args ): def __init__(self, *args ):
self.KodiMonitor = KodiMonitor.Kodi_Monitor() self.KodiMonitor = KodiMonitor.Kodi_Monitor()
addonName = self.addonName addonName = self.addonName
self.className = self.__class__.__name__
self.logMsg("Starting Monitor", 0) self.logMsg("Starting Monitor", 0)
self.logMsg("======== START %s ========" % addonName, 0) self.logMsg("======== START %s ========" % addonName, 0)
self.logMsg("KODI Version: %s" % xbmc.getInfoLabel("System.BuildVersion"), 0) self.logMsg("KODI Version: %s" % xbmc.getInfoLabel("System.BuildVersion"), 0)
self.logMsg("%s Version: %s" % (addonName, self.clientInfo.getVersion()), 0) self.logMsg("%s Version: %s" % (addonName, self.clientInfo.getVersion()), 0)
pass
def logMsg(self, msg, lvl=1): def logMsg(self, msg, lvl=1):
self.className = self.__class__.__name__
utils.logMsg("%s %s" % (self.addonName, self.className), str(msg), int(lvl)) utils.logMsg("%s %s" % (self.addonName, self.className), str(msg), int(lvl))
def ServiceEntryPoint(self): def ServiceEntryPoint(self):
@ -77,18 +76,18 @@ class Service():
playTime = xbmc.Player().getTime() playTime = xbmc.Player().getTime()
totalTime = xbmc.Player().getTotalTime() totalTime = xbmc.Player().getTotalTime()
currentFile = xbmc.Player().getPlayingFile() currentFile = xbmc.Player().getPlayingFile()
if(player.played_information.get(currentFile) != None): if(player.played_information.get(currentFile) != None):
player.played_information[currentFile]["currentPosition"] = playTime player.played_information[currentFile]["currentPosition"] = playTime
# send update # send update
td = datetime.today() - lastProgressUpdate td = datetime.today() - lastProgressUpdate
secDiff = td.seconds secDiff = td.seconds
if(secDiff > 10): if(secDiff > 3):
try: try:
player.reportPlayback() player.reportPlayback()
except Exception, msg: except Exception, msg:
xbmc.log("MB3 Sync Service -> Exception reporting progress : " + msg) self.logMsg("Exception reporting progress: %s" % msg)
pass pass
lastProgressUpdate = datetime.today() lastProgressUpdate = datetime.today()
# only try autoplay when there's 20 seconds or less remaining and only once! # only try autoplay when there's 20 seconds or less remaining and only once!
@ -97,7 +96,7 @@ class Service():
player.autoPlayPlayback() player.autoPlayPlayback()
except Exception, e: 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 pass
else: else:
if (self.newUserClient == None): if (self.newUserClient == None):
@ -113,11 +112,11 @@ class Service():
#full sync #full sync
if(startupComplete == False): if(startupComplete == False):
xbmc.log("Doing_Db_Sync: syncDatabase (Started)") self.logMsg("Doing_Db_Sync: syncDatabase (Started)")
libSync = librarySync.syncDatabase() libSync = librarySync.syncDatabase()
xbmc.log("Doing_Db_Sync: syncDatabase (Finished) " + str(libSync)) self.logMsg("Doing_Db_Sync: syncDatabase (Finished) " + str(libSync))
countSync = librarySync.updatePlayCounts() 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 # Force refresh newly set thumbnails
xbmc.executebuiltin("UpdateLibrary(video)") xbmc.executebuiltin("UpdateLibrary(video)")
@ -130,9 +129,9 @@ class Service():
WebSocketThread().processPendingActions() WebSocketThread().processPendingActions()
else: 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. # If user reset library database.
WINDOW = xbmcgui.Window(10000) WINDOW = xbmcgui.Window(10000)