Merge remote-tracking branch 'MediaBrowser/master' into develop
This commit is contained in:
commit
4b2e069bff
7 changed files with 89 additions and 58 deletions
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<addon id="plugin.video.plexkodiconnect"
|
||||
name="PlexKodiConnect"
|
||||
version="2.0.0"
|
||||
version="2.0.1"
|
||||
provider-name="croneter">
|
||||
<requires>
|
||||
<import addon="xbmc.python" version="2.1.0"/>
|
||||
|
|
|
@ -278,4 +278,13 @@
|
|||
<string id="30408">Emby addon settings</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>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Read an api response and convert more complex cases
|
||||
|
||||
##################################################################################################
|
||||
|
||||
import clientinfo
|
||||
|
@ -11,8 +13,9 @@ import utils
|
|||
class API():
|
||||
|
||||
def __init__(self, item):
|
||||
|
||||
# item is the api response
|
||||
self.item = item
|
||||
|
||||
self.clientinfo = clientinfo.ClientInfo()
|
||||
self.addonName = self.clientinfo.getAddonName()
|
||||
|
||||
|
@ -377,7 +380,7 @@ class API():
|
|||
# Specific format modification
|
||||
if 'Dvd'in videotype:
|
||||
filepath = "%s/VIDEO_TS/VIDEO_TS.IFO" % filepath
|
||||
elif 'Bluray' in videotype:
|
||||
elif 'BluRay' in videotype:
|
||||
filepath = "%s/BDMV/index.bdmv" % filepath
|
||||
|
||||
if "\\" in filepath:
|
||||
|
@ -388,6 +391,7 @@ class API():
|
|||
|
||||
def updateUserRating(self, itemid, like=None, favourite=None, deletelike=False):
|
||||
#updates the userrating to Emby
|
||||
# This should be moved to read_embyserver.py
|
||||
import downloadutils
|
||||
doUtils = downloadutils.DownloadUtils()
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class Playlist():
|
|||
emby_db = embydb.Embydb_Functions(embycursor)
|
||||
|
||||
self.logMsg("---*** PLAY ALL ***---", 1)
|
||||
self.logMsg("Items: %s" % itemids)
|
||||
self.logMsg("Items: %s and start at: %s" % (itemids, startat))
|
||||
|
||||
player = xbmc.Player()
|
||||
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
||||
|
@ -50,6 +50,7 @@ class Playlist():
|
|||
mediatype = embydb_item[4]
|
||||
except TypeError:
|
||||
# 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)
|
||||
self.addtoPlaylist_xbmc(playlist, item)
|
||||
else:
|
||||
|
@ -66,6 +67,7 @@ class Playlist():
|
|||
# Seek to the starting position
|
||||
seektime = startat / 10000000.0
|
||||
player.seekTime(seektime)
|
||||
self.logMsg("Seeking to: %s" % seektime, 1)
|
||||
|
||||
self.verifyPlaylist()
|
||||
embycursor.close()
|
||||
|
|
|
@ -853,6 +853,7 @@ class WebSocketApp(object):
|
|||
if self.sock:
|
||||
raise WebSocketException("socket is already opened")
|
||||
thread = None
|
||||
self.keep_running = True
|
||||
|
||||
try:
|
||||
self.sock = WebSocket(self.get_mask_key, sockopt=sockopt, sslopt=sslopt)
|
||||
|
|
|
@ -44,7 +44,10 @@ class WebSocket_Client(threading.Thread):
|
|||
threading.Thread.__init__(self)
|
||||
|
||||
def sendProgressUpdate(self, data):
|
||||
self.logMsg("sendProgressUpdate", 2)
|
||||
|
||||
log = self.logMsg
|
||||
|
||||
log("sendProgressUpdate", 2)
|
||||
try:
|
||||
messageData = {
|
||||
|
||||
|
@ -53,20 +56,24 @@ class WebSocket_Client(threading.Thread):
|
|||
}
|
||||
messageString = json.dumps(messageData)
|
||||
self.client.send(messageString)
|
||||
self.logMsg("Message data: %s" % messageString, 2)
|
||||
log("Message data: %s" % messageString, 2)
|
||||
|
||||
except Exception as e:
|
||||
self.logMsg("Exception: %s" % e, 1)
|
||||
log("Exception: %s" % e, 1)
|
||||
|
||||
def on_message(self, ws, message):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
lang = utils.language
|
||||
|
||||
result = json.loads(message)
|
||||
messageType = result['MessageType']
|
||||
data = result['Data']
|
||||
|
||||
if messageType not in ('SessionEnded'):
|
||||
# Mute certain events
|
||||
self.logMsg("Message: %s" % message, 1)
|
||||
log("Message: %s" % message, 1)
|
||||
|
||||
if messageType == "Play":
|
||||
# A remote control play command has been sent from the server.
|
||||
|
@ -75,12 +82,11 @@ class WebSocket_Client(threading.Thread):
|
|||
|
||||
pl = playlist.Playlist()
|
||||
dialog = xbmcgui.Dialog()
|
||||
dialog.notification("Emby for Kodi", "Adding %s items to playlist." % len(itemIds))
|
||||
|
||||
if command == "PlayNow":
|
||||
dialog.notification(
|
||||
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",
|
||||
sound=False)
|
||||
startat = data.get('StartPositionTicks', 0)
|
||||
|
@ -89,7 +95,7 @@ class WebSocket_Client(threading.Thread):
|
|||
elif command == "PlayNext":
|
||||
dialog.notification(
|
||||
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",
|
||||
sound=False)
|
||||
newplaylist = pl.modifyPlaylist(itemIds)
|
||||
|
@ -117,12 +123,12 @@ class WebSocket_Client(threading.Thread):
|
|||
seekto = data['SeekPositionTicks']
|
||||
seektime = seekto / 10000000.0
|
||||
action(seektime)
|
||||
self.logMsg("Seek to %s." % seektime, 1)
|
||||
log("Seek to %s." % seektime, 1)
|
||||
else:
|
||||
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":
|
||||
# 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'])
|
||||
currentFile = player.getPlayingFile()
|
||||
|
||||
mapping = utils.window('emby_%s.indexMapping' % currentFile)
|
||||
mapping = window('emby_%s.indexMapping' % currentFile)
|
||||
if mapping:
|
||||
externalIndex = json.loads(mapping)
|
||||
# If there's external subtitles added via playbackutils
|
||||
|
@ -184,7 +190,7 @@ class WebSocket_Client(threading.Thread):
|
|||
player.setSubtitleStream(index - audioTracks - 1)
|
||||
|
||||
# Let service know
|
||||
utils.window('emby_command', value="true")
|
||||
window('emby_command', value="true")
|
||||
|
||||
elif command == "DisplayMessage":
|
||||
|
||||
|
@ -243,8 +249,8 @@ class WebSocket_Client(threading.Thread):
|
|||
elif messageType == "ServerRestarting":
|
||||
if utils.settings('supressRestartMsg') == "true":
|
||||
xbmcgui.Dialog().notification(
|
||||
heading="Emby server",
|
||||
message="Server is restarting.",
|
||||
heading="Emby for Kodi",
|
||||
message=lang(33006),
|
||||
icon="special://home/addons/plugin.video.plexkodiconnect/icon.png")
|
||||
|
||||
elif messageType == "UserConfigurationUpdated":
|
||||
|
@ -267,13 +273,16 @@ class WebSocket_Client(threading.Thread):
|
|||
|
||||
def run(self):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
monitor = self.monitor
|
||||
loglevel = int(utils.window('emby_logLevel'))
|
||||
|
||||
loglevel = int(window('emby_logLevel'))
|
||||
# websocket.enableTrace(True)
|
||||
|
||||
userId = utils.window('emby_currUser')
|
||||
server = utils.window('emby_server%s' % userId)
|
||||
token = utils.window('emby_accessToken%s' % userId)
|
||||
userId = window('emby_currUser')
|
||||
server = window('emby_server%s' % userId)
|
||||
token = window('emby_accessToken%s' % userId)
|
||||
deviceId = self.deviceId
|
||||
|
||||
# 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
|
||||
websocket_url = ""
|
||||
# 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,
|
||||
on_message=self.on_message,
|
||||
|
@ -292,11 +301,11 @@ class WebSocket_Client(threading.Thread):
|
|||
on_close=self.on_close)
|
||||
|
||||
self.client.on_open = self.on_open
|
||||
self.logMsg("----===## Starting WebSocketClient ##===----", 0)
|
||||
log("----===## Starting WebSocketClient ##===----", 0)
|
||||
|
||||
while not monitor.abortRequested():
|
||||
|
||||
self.client.run_forever(ping_interval = 10)
|
||||
self.client.run_forever(ping_interval=10)
|
||||
if self.stopWebsocket:
|
||||
break
|
||||
|
||||
|
@ -304,7 +313,7 @@ class WebSocket_Client(threading.Thread):
|
|||
# Abort was requested, exit
|
||||
break
|
||||
|
||||
self.logMsg("##===---- WebSocketClient Stopped ----===##", 0)
|
||||
log("##===---- WebSocketClient Stopped ----===##", 0)
|
||||
|
||||
def stopClient(self):
|
||||
|
||||
|
|
68
service.py
68
service.py
|
@ -53,23 +53,26 @@ class Service():
|
|||
|
||||
def __init__(self):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
|
||||
self.clientInfo = clientinfo.ClientInfo()
|
||||
logLevel = userclient.UserClient().getLogLevel()
|
||||
self.monitor = xbmc.Monitor()
|
||||
|
||||
utils.window('emby_logLevel', value=str(logLevel))
|
||||
utils.window('emby_kodiProfile', value=xbmc.translatePath("special://profile"))
|
||||
utils.window('emby_pluginpath', value=utils.settings('useDirectPaths'))
|
||||
window('emby_logLevel', value=str(logLevel))
|
||||
window('emby_kodiProfile', value=xbmc.translatePath("special://profile"))
|
||||
window('emby_pluginpath', value=utils.settings('useDirectPaths'))
|
||||
|
||||
self.runPlexCompanion = utils.settings('plexCompanion')
|
||||
|
||||
# Initial logging
|
||||
self.logMsg("======== START %s ========" % self.addonName, 0)
|
||||
self.logMsg("Platform: %s" % (self.clientInfo.getPlatform()), 0)
|
||||
self.logMsg("KODI Version: %s" % xbmc.getInfoLabel('System.BuildVersion'), 0)
|
||||
self.logMsg("%s Version: %s" % (self.addonName, self.clientInfo.getVersion()), 0)
|
||||
self.logMsg("Using plugin paths: %s" % (utils.settings('useDirectPaths') != "true"), 0)
|
||||
self.logMsg("Log Level: %s" % logLevel, 0)
|
||||
log("======== START %s ========" % self.addonName, 0)
|
||||
log("Platform: %s" % (self.clientInfo.getPlatform()), 0)
|
||||
log("KODI Version: %s" % xbmc.getInfoLabel('System.BuildVersion'), 0)
|
||||
log("%s Version: %s" % (self.addonName, self.clientInfo.getVersion()), 0)
|
||||
log("Using plugin paths: %s" % (utils.settings('useDirectPaths') != "true"), 0)
|
||||
log("Log Level: %s" % logLevel, 0)
|
||||
|
||||
# Reset window props for profile switch
|
||||
properties = [
|
||||
|
@ -81,15 +84,20 @@ class Service():
|
|||
"plex_runLibScan"
|
||||
]
|
||||
for prop in properties:
|
||||
utils.window(prop, clear=True)
|
||||
window(prop, clear=True)
|
||||
|
||||
# Clear video nodes properties
|
||||
videonodes.VideoNodes().clearProperties()
|
||||
|
||||
# Set the minimum database version
|
||||
utils.window('emby_minDBVersion', value="1.1.63")
|
||||
window('emby_minDBVersion', value="1.1.63")
|
||||
|
||||
def ServiceEntryPoint(self):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
lang = utils.language
|
||||
|
||||
# Important: Threads depending on abortRequest will not trigger
|
||||
# if profile switch happens more than once.
|
||||
monitor = self.monitor
|
||||
|
@ -111,10 +119,9 @@ class Service():
|
|||
|
||||
while not monitor.abortRequested():
|
||||
|
||||
if utils.window('emby_kodiProfile') != kodiProfile:
|
||||
if window('emby_kodiProfile') != kodiProfile:
|
||||
# Profile change happened, terminate this thread and others
|
||||
self.logMsg(
|
||||
"Kodi profile was: %s and changed to: %s. Terminating old Emby thread."
|
||||
log("Kodi profile was: %s and changed to: %s. Terminating old Emby thread."
|
||||
% (kodiProfile, utils.window('emby_kodiProfile')), 1)
|
||||
|
||||
break
|
||||
|
@ -124,7 +131,7 @@ class Service():
|
|||
# 2. User is set
|
||||
# 3. User has access to the server
|
||||
|
||||
if utils.window('emby_online') == "true":
|
||||
if window('emby_online') == "true":
|
||||
|
||||
# Emby server is online
|
||||
# Verify if user is set and has access to the server
|
||||
|
@ -150,15 +157,15 @@ class Service():
|
|||
kplayer.reportPlayback()
|
||||
lastProgressUpdate = datetime.today()
|
||||
|
||||
elif utils.window('emby_command') == "true":
|
||||
elif window('emby_command') == "true":
|
||||
# Received a remote control command that
|
||||
# requires updating immediately
|
||||
utils.window('emby_command', clear=True)
|
||||
window('emby_command', clear=True)
|
||||
kplayer.reportPlayback()
|
||||
lastProgressUpdate = datetime.today()
|
||||
|
||||
except Exception as e:
|
||||
self.logMsg("Exception in Playback Monitor Service: %s" % e, 1)
|
||||
log("Exception in Playback Monitor Service: %s" % e, 1)
|
||||
pass
|
||||
else:
|
||||
# Start up events
|
||||
|
@ -174,8 +181,8 @@ class Service():
|
|||
add = ""
|
||||
xbmcgui.Dialog().notification(
|
||||
heading=self.addonName,
|
||||
message="Welcome %s%s"
|
||||
% (user.currUser, add),
|
||||
message="%s %s%s!"
|
||||
% (lang(33000), user.currUser, add),
|
||||
icon="special://home/addons/plugin.video."
|
||||
"plexkodiconnect/icon.png",
|
||||
time=2000,
|
||||
|
@ -198,7 +205,7 @@ class Service():
|
|||
if (user.currUser is None) and self.warn_auth:
|
||||
# Alert user is not authenticated and suppress future warning
|
||||
self.warn_auth = False
|
||||
self.logMsg("Not authenticated yet.", 1)
|
||||
log("Not authenticated yet.", 1)
|
||||
|
||||
# User access is restricted.
|
||||
# Keep verifying until access is granted
|
||||
|
@ -207,7 +214,7 @@ class Service():
|
|||
# Verify access with an API call
|
||||
user.hasAccess()
|
||||
|
||||
if utils.window('emby_online') != "true":
|
||||
if window('emby_online') != "true":
|
||||
# Server went offline
|
||||
break
|
||||
|
||||
|
@ -229,13 +236,12 @@ class Service():
|
|||
# Server is offline.
|
||||
# Alert the user and suppress future warning
|
||||
if self.server_online:
|
||||
self.logMsg("Server is offline.", 1)
|
||||
utils.window('emby_online', value="false")
|
||||
log("Server is offline.", 1)
|
||||
window('emby_online', value="false")
|
||||
|
||||
xbmcgui.Dialog().notification(
|
||||
heading="Error connecting",
|
||||
message="%s Server is unreachable."
|
||||
% self.addonName,
|
||||
heading=lang(33001),
|
||||
message="%s %s" % (self.addonName, lang(33002)),
|
||||
icon="special://home/addons/plugin.video."
|
||||
"plexkodiconnect/icon.png",
|
||||
sound=False)
|
||||
|
@ -253,15 +259,15 @@ class Service():
|
|||
# Alert the user that server is online.
|
||||
xbmcgui.Dialog().notification(
|
||||
heading=self.addonName,
|
||||
message="Server is online.",
|
||||
message=lang(33003),
|
||||
icon="special://home/addons/plugin.video."
|
||||
"plexkodiconnect/icon.png",
|
||||
time=2000,
|
||||
sound=False)
|
||||
|
||||
self.server_online = True
|
||||
self.logMsg("Server is online and ready.", 1)
|
||||
utils.window('emby_online', value="true")
|
||||
log("Server is online and ready.", 1)
|
||||
window('emby_online', value="true")
|
||||
|
||||
# Start the userclient thread
|
||||
if not self.userclient_running:
|
||||
|
@ -298,7 +304,7 @@ class Service():
|
|||
if self.userclient_running:
|
||||
user.stopThread()
|
||||
|
||||
self.logMsg("======== STOP %s ========" % self.addonName, 0)
|
||||
log("======== STOP %s ========" % self.addonName, 0)
|
||||
|
||||
# Delay option
|
||||
delay = int(utils.settings('startupDelay'))
|
||||
|
|
Loading…
Reference in a new issue