Merge remote-tracking branch 'MediaBrowser/master' into develop

This commit is contained in:
tomkat83 2016-02-03 13:06:27 +01:00
commit 4b2e069bff
7 changed files with 89 additions and 58 deletions

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.plexkodiconnect" <addon id="plugin.video.plexkodiconnect"
name="PlexKodiConnect" name="PlexKodiConnect"
version="2.0.0" version="2.0.1"
provider-name="croneter"> provider-name="croneter">
<requires> <requires>
<import addon="xbmc.python" version="2.1.0"/> <import addon="xbmc.python" version="2.1.0"/>

View file

@ -278,4 +278,13 @@
<string id="30408">Emby addon settings</string> <string id="30408">Emby addon settings</string>
<string id="30409">Delete item from the server</string> <string id="30409">Delete item from the server</string>
<!-- service add-on -->
<string id="33000">Welcome</string>
<string id="33001">Error connecting</string>
<string id="33002">Server is unreachable</string>
<string id="33003">Server is online</string>
<string id="33004">items added to playlist</string>
<string id="33005">items queued to playlist</string>
<string id="33006">Server is restarting</string>
</strings> </strings>

View file

@ -1,5 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Read an api response and convert more complex cases
################################################################################################## ##################################################################################################
import clientinfo import clientinfo
@ -11,8 +13,9 @@ import utils
class API(): class API():
def __init__(self, item): def __init__(self, item):
# item is the api response
self.item = item self.item = item
self.clientinfo = clientinfo.ClientInfo() self.clientinfo = clientinfo.ClientInfo()
self.addonName = self.clientinfo.getAddonName() self.addonName = self.clientinfo.getAddonName()
@ -377,7 +380,7 @@ class API():
# Specific format modification # Specific format modification
if 'Dvd'in videotype: if 'Dvd'in videotype:
filepath = "%s/VIDEO_TS/VIDEO_TS.IFO" % filepath filepath = "%s/VIDEO_TS/VIDEO_TS.IFO" % filepath
elif 'Bluray' in videotype: elif 'BluRay' in videotype:
filepath = "%s/BDMV/index.bdmv" % filepath filepath = "%s/BDMV/index.bdmv" % filepath
if "\\" in filepath: if "\\" in filepath:
@ -388,6 +391,7 @@ class API():
def updateUserRating(self, itemid, like=None, favourite=None, deletelike=False): def updateUserRating(self, itemid, like=None, favourite=None, deletelike=False):
#updates the userrating to Emby #updates the userrating to Emby
# This should be moved to read_embyserver.py
import downloadutils import downloadutils
doUtils = downloadutils.DownloadUtils() doUtils = downloadutils.DownloadUtils()

View file

@ -32,7 +32,7 @@ class Playlist():
emby_db = embydb.Embydb_Functions(embycursor) emby_db = embydb.Embydb_Functions(embycursor)
self.logMsg("---*** PLAY ALL ***---", 1) self.logMsg("---*** PLAY ALL ***---", 1)
self.logMsg("Items: %s" % itemids) self.logMsg("Items: %s and start at: %s" % (itemids, startat))
player = xbmc.Player() player = xbmc.Player()
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
@ -50,6 +50,7 @@ class Playlist():
mediatype = embydb_item[4] mediatype = embydb_item[4]
except TypeError: except TypeError:
# Item is not found in our database, add item manually # Item is not found in our database, add item manually
self.logMsg("Item was not found in the database, manually adding item.", 1)
item = self.emby.getItem(itemid) item = self.emby.getItem(itemid)
self.addtoPlaylist_xbmc(playlist, item) self.addtoPlaylist_xbmc(playlist, item)
else: else:
@ -66,6 +67,7 @@ class Playlist():
# Seek to the starting position # Seek to the starting position
seektime = startat / 10000000.0 seektime = startat / 10000000.0
player.seekTime(seektime) player.seekTime(seektime)
self.logMsg("Seeking to: %s" % seektime, 1)
self.verifyPlaylist() self.verifyPlaylist()
embycursor.close() embycursor.close()

View file

@ -853,6 +853,7 @@ class WebSocketApp(object):
if self.sock: if self.sock:
raise WebSocketException("socket is already opened") raise WebSocketException("socket is already opened")
thread = None thread = None
self.keep_running = True
try: try:
self.sock = WebSocket(self.get_mask_key, sockopt=sockopt, sslopt=sslopt) self.sock = WebSocket(self.get_mask_key, sockopt=sockopt, sslopt=sslopt)

View file

@ -44,7 +44,10 @@ class WebSocket_Client(threading.Thread):
threading.Thread.__init__(self) threading.Thread.__init__(self)
def sendProgressUpdate(self, data): def sendProgressUpdate(self, data):
self.logMsg("sendProgressUpdate", 2)
log = self.logMsg
log("sendProgressUpdate", 2)
try: try:
messageData = { messageData = {
@ -53,20 +56,24 @@ class WebSocket_Client(threading.Thread):
} }
messageString = json.dumps(messageData) messageString = json.dumps(messageData)
self.client.send(messageString) self.client.send(messageString)
self.logMsg("Message data: %s" % messageString, 2) log("Message data: %s" % messageString, 2)
except Exception as e: except Exception as e:
self.logMsg("Exception: %s" % e, 1) log("Exception: %s" % e, 1)
def on_message(self, ws, message): def on_message(self, ws, message):
log = self.logMsg
window = utils.window
lang = utils.language
result = json.loads(message) result = json.loads(message)
messageType = result['MessageType'] messageType = result['MessageType']
data = result['Data'] data = result['Data']
if messageType not in ('SessionEnded'): if messageType not in ('SessionEnded'):
# Mute certain events # Mute certain events
self.logMsg("Message: %s" % message, 1) log("Message: %s" % message, 1)
if messageType == "Play": if messageType == "Play":
# A remote control play command has been sent from the server. # A remote control play command has been sent from the server.
@ -75,12 +82,11 @@ class WebSocket_Client(threading.Thread):
pl = playlist.Playlist() pl = playlist.Playlist()
dialog = xbmcgui.Dialog() dialog = xbmcgui.Dialog()
dialog.notification("Emby for Kodi", "Adding %s items to playlist." % len(itemIds))
if command == "PlayNow": if command == "PlayNow":
dialog.notification( dialog.notification(
heading="Emby for Kodi", heading="Emby for Kodi",
message="Adding %s items to playlist." % len(itemIds), message="%s %s" % (len(itemIds), lang(33004)),
icon="special://home/addons/plugin.video.plexkodiconnect/icon.png", icon="special://home/addons/plugin.video.plexkodiconnect/icon.png",
sound=False) sound=False)
startat = data.get('StartPositionTicks', 0) startat = data.get('StartPositionTicks', 0)
@ -89,7 +95,7 @@ class WebSocket_Client(threading.Thread):
elif command == "PlayNext": elif command == "PlayNext":
dialog.notification( dialog.notification(
heading="Emby for Kodi", heading="Emby for Kodi",
message="Queueing %s items to playlist." % len(itemIds), message="%s %s" % (len(itemIds), lang(33005)),
icon="special://home/addons/plugin.video.plexkodiconnect/icon.png", icon="special://home/addons/plugin.video.plexkodiconnect/icon.png",
sound=False) sound=False)
newplaylist = pl.modifyPlaylist(itemIds) newplaylist = pl.modifyPlaylist(itemIds)
@ -117,12 +123,12 @@ class WebSocket_Client(threading.Thread):
seekto = data['SeekPositionTicks'] seekto = data['SeekPositionTicks']
seektime = seekto / 10000000.0 seektime = seekto / 10000000.0
action(seektime) action(seektime)
self.logMsg("Seek to %s." % seektime, 1) log("Seek to %s." % seektime, 1)
else: else:
action() action()
self.logMsg("Command: %s completed." % command, 1) log("Command: %s completed." % command, 1)
utils.window('emby_command', value="true") window('emby_command', value="true")
elif messageType == "UserDataChanged": elif messageType == "UserDataChanged":
# A user changed their personal rating for an item, or their playstate was updated # A user changed their personal rating for an item, or their playstate was updated
@ -165,7 +171,7 @@ class WebSocket_Client(threading.Thread):
embyindex = int(arguments['Index']) embyindex = int(arguments['Index'])
currentFile = player.getPlayingFile() currentFile = player.getPlayingFile()
mapping = utils.window('emby_%s.indexMapping' % currentFile) mapping = window('emby_%s.indexMapping' % currentFile)
if mapping: if mapping:
externalIndex = json.loads(mapping) externalIndex = json.loads(mapping)
# If there's external subtitles added via playbackutils # If there's external subtitles added via playbackutils
@ -184,7 +190,7 @@ class WebSocket_Client(threading.Thread):
player.setSubtitleStream(index - audioTracks - 1) player.setSubtitleStream(index - audioTracks - 1)
# Let service know # Let service know
utils.window('emby_command', value="true") window('emby_command', value="true")
elif command == "DisplayMessage": elif command == "DisplayMessage":
@ -243,8 +249,8 @@ class WebSocket_Client(threading.Thread):
elif messageType == "ServerRestarting": elif messageType == "ServerRestarting":
if utils.settings('supressRestartMsg') == "true": if utils.settings('supressRestartMsg') == "true":
xbmcgui.Dialog().notification( xbmcgui.Dialog().notification(
heading="Emby server", heading="Emby for Kodi",
message="Server is restarting.", message=lang(33006),
icon="special://home/addons/plugin.video.plexkodiconnect/icon.png") icon="special://home/addons/plugin.video.plexkodiconnect/icon.png")
elif messageType == "UserConfigurationUpdated": elif messageType == "UserConfigurationUpdated":
@ -267,13 +273,16 @@ class WebSocket_Client(threading.Thread):
def run(self): def run(self):
log = self.logMsg
window = utils.window
monitor = self.monitor monitor = self.monitor
loglevel = int(utils.window('emby_logLevel'))
loglevel = int(window('emby_logLevel'))
# websocket.enableTrace(True) # websocket.enableTrace(True)
userId = utils.window('emby_currUser') userId = window('emby_currUser')
server = utils.window('emby_server%s' % userId) server = window('emby_server%s' % userId)
token = utils.window('emby_accessToken%s' % userId) token = window('emby_accessToken%s' % userId)
deviceId = self.deviceId deviceId = self.deviceId
# Get the appropriate prefix for the websocket # Get the appropriate prefix for the websocket
@ -284,7 +293,7 @@ class WebSocket_Client(threading.Thread):
#EDIT: realized the ws url is at: ws://server.local:32400/:/websockets/notifications #EDIT: realized the ws url is at: ws://server.local:32400/:/websockets/notifications
websocket_url = "" websocket_url = ""
# websocket_url = "%s/:/websockets/notifications/?X-Plex-Token=%s" % (server, token) # websocket_url = "%s/:/websockets/notifications/?X-Plex-Token=%s" % (server, token)
self.logMsg("websocket url: %s" % websocket_url, 1) log("websocket url: %s" % websocket_url, 1)
self.client = websocket.WebSocketApp(websocket_url, self.client = websocket.WebSocketApp(websocket_url,
on_message=self.on_message, on_message=self.on_message,
@ -292,11 +301,11 @@ class WebSocket_Client(threading.Thread):
on_close=self.on_close) on_close=self.on_close)
self.client.on_open = self.on_open self.client.on_open = self.on_open
self.logMsg("----===## Starting WebSocketClient ##===----", 0) log("----===## Starting WebSocketClient ##===----", 0)
while not monitor.abortRequested(): while not monitor.abortRequested():
self.client.run_forever(ping_interval = 10) self.client.run_forever(ping_interval=10)
if self.stopWebsocket: if self.stopWebsocket:
break break
@ -304,7 +313,7 @@ class WebSocket_Client(threading.Thread):
# Abort was requested, exit # Abort was requested, exit
break break
self.logMsg("##===---- WebSocketClient Stopped ----===##", 0) log("##===---- WebSocketClient Stopped ----===##", 0)
def stopClient(self): def stopClient(self):

View file

@ -53,23 +53,26 @@ class Service():
def __init__(self): def __init__(self):
log = self.logMsg
window = utils.window
self.clientInfo = clientinfo.ClientInfo() self.clientInfo = clientinfo.ClientInfo()
logLevel = userclient.UserClient().getLogLevel() logLevel = userclient.UserClient().getLogLevel()
self.monitor = xbmc.Monitor() self.monitor = xbmc.Monitor()
utils.window('emby_logLevel', value=str(logLevel)) window('emby_logLevel', value=str(logLevel))
utils.window('emby_kodiProfile', value=xbmc.translatePath("special://profile")) window('emby_kodiProfile', value=xbmc.translatePath("special://profile"))
utils.window('emby_pluginpath', value=utils.settings('useDirectPaths')) window('emby_pluginpath', value=utils.settings('useDirectPaths'))
self.runPlexCompanion = utils.settings('plexCompanion') self.runPlexCompanion = utils.settings('plexCompanion')
# Initial logging # Initial logging
self.logMsg("======== START %s ========" % self.addonName, 0) log("======== START %s ========" % self.addonName, 0)
self.logMsg("Platform: %s" % (self.clientInfo.getPlatform()), 0) log("Platform: %s" % (self.clientInfo.getPlatform()), 0)
self.logMsg("KODI Version: %s" % xbmc.getInfoLabel('System.BuildVersion'), 0) log("KODI Version: %s" % xbmc.getInfoLabel('System.BuildVersion'), 0)
self.logMsg("%s Version: %s" % (self.addonName, self.clientInfo.getVersion()), 0) log("%s Version: %s" % (self.addonName, self.clientInfo.getVersion()), 0)
self.logMsg("Using plugin paths: %s" % (utils.settings('useDirectPaths') != "true"), 0) log("Using plugin paths: %s" % (utils.settings('useDirectPaths') != "true"), 0)
self.logMsg("Log Level: %s" % logLevel, 0) log("Log Level: %s" % logLevel, 0)
# Reset window props for profile switch # Reset window props for profile switch
properties = [ properties = [
@ -81,15 +84,20 @@ class Service():
"plex_runLibScan" "plex_runLibScan"
] ]
for prop in properties: for prop in properties:
utils.window(prop, clear=True) window(prop, clear=True)
# Clear video nodes properties # Clear video nodes properties
videonodes.VideoNodes().clearProperties() videonodes.VideoNodes().clearProperties()
# Set the minimum database version # Set the minimum database version
utils.window('emby_minDBVersion', value="1.1.63") window('emby_minDBVersion', value="1.1.63")
def ServiceEntryPoint(self): def ServiceEntryPoint(self):
log = self.logMsg
window = utils.window
lang = utils.language
# Important: Threads depending on abortRequest will not trigger # Important: Threads depending on abortRequest will not trigger
# if profile switch happens more than once. # if profile switch happens more than once.
monitor = self.monitor monitor = self.monitor
@ -111,10 +119,9 @@ class Service():
while not monitor.abortRequested(): while not monitor.abortRequested():
if utils.window('emby_kodiProfile') != kodiProfile: if window('emby_kodiProfile') != kodiProfile:
# Profile change happened, terminate this thread and others # Profile change happened, terminate this thread and others
self.logMsg( log("Kodi profile was: %s and changed to: %s. Terminating old Emby thread."
"Kodi profile was: %s and changed to: %s. Terminating old Emby thread."
% (kodiProfile, utils.window('emby_kodiProfile')), 1) % (kodiProfile, utils.window('emby_kodiProfile')), 1)
break break
@ -124,7 +131,7 @@ class Service():
# 2. User is set # 2. User is set
# 3. User has access to the server # 3. User has access to the server
if utils.window('emby_online') == "true": if window('emby_online') == "true":
# Emby server is online # Emby 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
@ -150,15 +157,15 @@ class Service():
kplayer.reportPlayback() kplayer.reportPlayback()
lastProgressUpdate = datetime.today() lastProgressUpdate = datetime.today()
elif utils.window('emby_command') == "true": elif window('emby_command') == "true":
# Received a remote control command that # Received a remote control command that
# requires updating immediately # requires updating immediately
utils.window('emby_command', clear=True) window('emby_command', clear=True)
kplayer.reportPlayback() kplayer.reportPlayback()
lastProgressUpdate = datetime.today() lastProgressUpdate = datetime.today()
except Exception as e: except Exception as e:
self.logMsg("Exception in Playback Monitor Service: %s" % e, 1) log("Exception in Playback Monitor Service: %s" % e, 1)
pass pass
else: else:
# Start up events # Start up events
@ -174,8 +181,8 @@ class Service():
add = "" add = ""
xbmcgui.Dialog().notification( xbmcgui.Dialog().notification(
heading=self.addonName, heading=self.addonName,
message="Welcome %s%s" message="%s %s%s!"
% (user.currUser, add), % (lang(33000), user.currUser, add),
icon="special://home/addons/plugin.video." icon="special://home/addons/plugin.video."
"plexkodiconnect/icon.png", "plexkodiconnect/icon.png",
time=2000, time=2000,
@ -198,7 +205,7 @@ class Service():
if (user.currUser is None) and self.warn_auth: if (user.currUser is None) and self.warn_auth:
# Alert user is not authenticated and suppress future warning # Alert user is not authenticated and suppress future warning
self.warn_auth = False self.warn_auth = False
self.logMsg("Not authenticated yet.", 1) log("Not authenticated yet.", 1)
# User access is restricted. # User access is restricted.
# Keep verifying until access is granted # Keep verifying until access is granted
@ -207,7 +214,7 @@ class Service():
# Verify access with an API call # Verify access with an API call
user.hasAccess() user.hasAccess()
if utils.window('emby_online') != "true": if window('emby_online') != "true":
# Server went offline # Server went offline
break break
@ -229,13 +236,12 @@ class Service():
# Server is offline. # Server is offline.
# Alert the user and suppress future warning # Alert the user and suppress future warning
if self.server_online: if self.server_online:
self.logMsg("Server is offline.", 1) log("Server is offline.", 1)
utils.window('emby_online', value="false") window('emby_online', value="false")
xbmcgui.Dialog().notification( xbmcgui.Dialog().notification(
heading="Error connecting", heading=lang(33001),
message="%s Server is unreachable." message="%s %s" % (self.addonName, lang(33002)),
% self.addonName,
icon="special://home/addons/plugin.video." icon="special://home/addons/plugin.video."
"plexkodiconnect/icon.png", "plexkodiconnect/icon.png",
sound=False) sound=False)
@ -253,15 +259,15 @@ class Service():
# Alert the user that server is online. # Alert the user that server is online.
xbmcgui.Dialog().notification( xbmcgui.Dialog().notification(
heading=self.addonName, heading=self.addonName,
message="Server is online.", message=lang(33003),
icon="special://home/addons/plugin.video." icon="special://home/addons/plugin.video."
"plexkodiconnect/icon.png", "plexkodiconnect/icon.png",
time=2000, time=2000,
sound=False) sound=False)
self.server_online = True self.server_online = True
self.logMsg("Server is online and ready.", 1) log("Server is online and ready.", 1)
utils.window('emby_online', value="true") window('emby_online', value="true")
# Start the userclient thread # Start the userclient thread
if not self.userclient_running: if not self.userclient_running:
@ -298,7 +304,7 @@ class Service():
if self.userclient_running: if self.userclient_running:
user.stopThread() user.stopThread()
self.logMsg("======== STOP %s ========" % self.addonName, 0) log("======== STOP %s ========" % self.addonName, 0)
# Delay option # Delay option
delay = int(utils.settings('startupDelay')) delay = int(utils.settings('startupDelay'))