This commit is contained in:
angelblue05 2016-09-07 02:14:02 -05:00
parent b65d6baad0
commit e941674e74
4 changed files with 235 additions and 221 deletions

View File

@ -368,7 +368,7 @@ class Player(xbmc.Player):
# Report progress via websocketclient
postdata = json.dumps(postdata)
log.debug("Report: %s" % postdata)
self.ws.sendProgressUpdate(postdata)
self.ws.send_progress_update(postdata)
def onPlayBackPaused(self):

View File

@ -55,7 +55,7 @@ def dialog(type_, **kwargs):
d = xbmcgui.Dialog()
if "icon" in kwargs:
kwargs['icon'] = kwargs['icon'].replace("{default}",
kwargs['icon'] = kwargs['icon'].replace("{emby}",
"special://home/addons/plugin.video.emby/icon.png")
types = {

View File

@ -8,14 +8,13 @@ import threading
import websocket
import xbmc
import xbmcgui
import clientinfo
import downloadutils
import librarysync
import playlist
import userclient
from utils import window, settings, language as lang, JSONRPC
from utils import window, settings, dialog, language as lang, JSONRPC
##################################################################################################
@ -28,8 +27,8 @@ class WebSocket_Client(threading.Thread):
_shared_state = {}
client = None
stopWebsocket = False
_client = None
_stop_websocket = False
def __init__(self):
@ -37,103 +36,56 @@ class WebSocket_Client(threading.Thread):
self.__dict__ = self._shared_state
self.monitor = xbmc.Monitor()
self.doUtils = downloadutils.DownloadUtils()
self.clientInfo = clientinfo.ClientInfo()
self.deviceId = self.clientInfo.get_device_id()
self.librarySync = librarysync.LibrarySync()
self.doutils = downloadutils.DownloadUtils()
self.client_info = clientinfo.ClientInfo()
self.device_id = self.client_info.get_device_id()
self.library_sync = librarysync.LibrarySync()
threading.Thread.__init__(self)
def sendProgressUpdate(self, data):
def send_progress_update(self, data):
log.debug("sendProgressUpdate")
try:
messageData = {
message = {
'MessageType': "ReportPlaybackProgress",
'Data': data
}
messageString = json.dumps(messageData)
self.client.send(messageString)
log.debug("Message data: %s" % messageString)
message_str = json.dumps(message)
self._client.send(message_str)
log.debug("Message data: %s", message_str)
except Exception as e:
log.exception(e)
except Exception as error:
log.exception(error)
def on_message(self, ws, message):
result = json.loads(message)
messageType = result['MessageType']
message_type = result['MessageType']
data = result['Data']
dialog = xbmcgui.Dialog()
if messageType not in ('SessionEnded'):
if message_type not in ('SessionEnded'):
# Mute certain events
log.info("Message: %s" % message)
if messageType == "Play":
if message_type == "Play":
# A remote control play command has been sent from the server.
itemIds = data['ItemIds']
command = data['PlayCommand']
self._play_(data)
pl = playlist.Playlist()
if command == "PlayNow":
dialog.notification(
heading=lang(29999),
message="%s %s" % (len(itemIds), lang(33004)),
icon="special://home/addons/plugin.video.emby/icon.png",
sound=False)
startat = data.get('StartPositionTicks', 0)
pl.playAll(itemIds, startat)
elif command == "PlayNext":
dialog.notification(
heading=lang(29999),
message="%s %s" % (len(itemIds), lang(33005)),
icon="special://home/addons/plugin.video.emby/icon.png",
sound=False)
newplaylist = pl.modifyPlaylist(itemIds)
player = xbmc.Player()
if not player.isPlaying():
# Only start the playlist if nothing is playing
player.play(newplaylist)
elif messageType == "Playstate":
elif message_type == "Playstate":
# A remote control update playstate command has been sent from the server.
command = data['Command']
player = xbmc.Player()
self._playstate_(data)
actions = {
'Stop': player.stop,
'Unpause': player.pause,
'Pause': player.pause,
'NextTrack': player.playnext,
'PreviousTrack': player.playprevious,
'Seek': player.seekTime
}
action = actions[command]
if command == "Seek":
seekto = data['SeekPositionTicks']
seektime = seekto / 10000000.0
action(seektime)
log.info("Seek to %s." % seektime)
else:
action()
log.info("Command: %s completed." % command)
window('emby_command', value="true")
elif messageType == "UserDataChanged":
elif message_type == "UserDataChanged":
# A user changed their personal rating for an item, or their playstate was updated
userdata_list = data['UserDataList']
self.librarySync.triage_items("userdata", userdata_list)
self.library_sync.triage_items("userdata", userdata_list)
elif messageType == "LibraryChanged":
elif message_type == "LibraryChanged":
librarySync = self.librarySync
librarySync = self.library_sync
processlist = {
'added': data['ItemsAdded'],
@ -143,163 +95,226 @@ class WebSocket_Client(threading.Thread):
for action in processlist:
librarySync.triage_items(action, processlist[action])
elif messageType == "GeneralCommand":
command = data['Name']
arguments = data['Arguments']
elif message_type == "GeneralCommand":
self._general_commands(data)
if command in ('Mute', 'Unmute', 'SetVolume',
'SetSubtitleStreamIndex', 'SetAudioStreamIndex'):
elif message_type == "ServerRestarting":
self._server_restarting()
player = xbmc.Player()
# These commands need to be reported back
if command == "Mute":
xbmc.executebuiltin('Mute')
elif command == "Unmute":
xbmc.executebuiltin('Mute')
elif command == "SetVolume":
volume = arguments['Volume']
xbmc.executebuiltin('SetVolume(%s[,showvolumebar])' % volume)
elif command == "SetAudioStreamIndex":
index = int(arguments['Index'])
player.setAudioStream(index - 1)
elif command == "SetSubtitleStreamIndex":
embyindex = int(arguments['Index'])
currentFile = player.getPlayingFile()
mapping = window('emby_%s.indexMapping' % currentFile)
if mapping:
externalIndex = json.loads(mapping)
# If there's external subtitles added via playbackutils
for index in externalIndex:
if externalIndex[index] == embyindex:
player.setSubtitleStream(int(index))
break
else:
# User selected internal subtitles
external = len(externalIndex)
audioTracks = len(player.getAvailableAudioStreams())
player.setSubtitleStream(external + embyindex - audioTracks - 1)
else:
# Emby merges audio and subtitle index together
audioTracks = len(player.getAvailableAudioStreams())
player.setSubtitleStream(index - audioTracks - 1)
# Let service know
window('emby_command', value="true")
elif command == "DisplayMessage":
header = arguments['Header']
text = arguments['Text']
dialog.notification(
heading=header,
message=text,
icon="special://home/addons/plugin.video.emby/icon.png",
time=4000)
elif command == "SendString":
params = {
'text': arguments['String'],
'done': False
}
result = JSONRPC("Input.SendText").execute(params)
elif command in ("MoveUp", "MoveDown", "MoveRight", "MoveLeft"):
# Commands that should wake up display
actions = {
'MoveUp': "Input.Up",
'MoveDown': "Input.Down",
'MoveRight': "Input.Right",
'MoveLeft': "Input.Left"
}
result = JSONRPC(actions[command]).execute()
elif command == "GoHome":
result = JSONRPC("GUI.ActivateWindow").execute({"window":"home"})
else:
builtin = {
'ToggleFullscreen': 'Action(FullScreen)',
'ToggleOsdMenu': 'Action(OSD)',
'ToggleContextMenu': 'Action(ContextMenu)',
'Select': 'Action(Select)',
'Back': 'Action(back)',
'PageUp': 'Action(PageUp)',
'NextLetter': 'Action(NextLetter)',
'GoToSearch': 'VideoLibrary.Search',
'GoToSettings': 'ActivateWindow(Settings)',
'PageDown': 'Action(PageDown)',
'PreviousLetter': 'Action(PrevLetter)',
'TakeScreenshot': 'TakeScreenshot',
'ToggleMute': 'Mute',
'VolumeUp': 'Action(VolumeUp)',
'VolumeDown': 'Action(VolumeDown)',
}
action = builtin.get(command)
if action:
xbmc.executebuiltin(action)
elif messageType == "ServerRestarting":
if settings('supressRestartMsg') == "true":
dialog.notification(
heading=lang(29999),
message=lang(33006),
icon="special://home/addons/plugin.video.emby/icon.png")
elif messageType == "UserConfigurationUpdated":
elif message_type == "UserConfigurationUpdated":
# Update user data set in userclient
userclient.UserClient().get_user(data)
self.librarySync.refresh_views = True
self.library_sync.refresh_views = True
elif messageType == "ServerShuttingDown":
elif message_type == "ServerShuttingDown":
# Server went offline
window('emby_online', value="false")
@classmethod
def _play_(cls, data):
item_ids = data['ItemIds']
command = data['PlayCommand']
playlist_ = playlist.Playlist()
if command == "PlayNow":
startat = data.get('StartPositionTicks', 0)
playlist_.playAll(item_ids, startat)
dialog(type_="notification",
heading=lang(29999),
message="%s %s" % (len(item_ids), lang(33004)),
icon="{emby}",
sound=False)
elif command == "PlayNext":
newplaylist = playlist_.modifyPlaylist(item_ids)
dialog(type_="notification",
heading=lang(29999),
message="%s %s" % (len(item_ids), lang(33005)),
icon="{emby}",
sound=False)
player = xbmc.Player()
if not player.isPlaying():
# Only start the playlist if nothing is playing
player.play(newplaylist)
@classmethod
def _playstate_(cls, data):
command = data['Command']
player = xbmc.Player()
actions = {
'Stop': player.stop,
'Unpause': player.pause,
'Pause': player.pause,
'NextTrack': player.playnext,
'PreviousTrack': player.playprevious,
'Seek': player.seekTime
}
action = actions[command]
if command == "Seek":
seekto = data['SeekPositionTicks']
seektime = seekto / 10000000.0
action(seektime)
log.info("Seek to %s", seektime)
else:
action()
log.info("Command: %s completed", command)
window('emby_command', value="true")
@classmethod
def _general_commands(cls, data):
command = data['Name']
arguments = data['Arguments']
if command in ('Mute', 'Unmute', 'SetVolume',
'SetSubtitleStreamIndex', 'SetAudioStreamIndex'):
player = xbmc.Player()
# These commands need to be reported back
if command == "Mute":
xbmc.executebuiltin('Mute')
elif command == "Unmute":
xbmc.executebuiltin('Mute')
elif command == "SetVolume":
volume = arguments['Volume']
xbmc.executebuiltin('SetVolume(%s[,showvolumebar])' % volume)
elif command == "SetAudioStreamIndex":
index = int(arguments['Index'])
player.setAudioStream(index - 1)
elif command == "SetSubtitleStreamIndex":
embyindex = int(arguments['Index'])
currentFile = player.getPlayingFile()
mapping = window('emby_%s.indexMapping' % currentFile)
if mapping:
externalIndex = json.loads(mapping)
# If there's external subtitles added via playbackutils
for index in externalIndex:
if externalIndex[index] == embyindex:
player.setSubtitleStream(int(index))
break
else:
# User selected internal subtitles
external = len(externalIndex)
audioTracks = len(player.getAvailableAudioStreams())
player.setSubtitleStream(external + embyindex - audioTracks - 1)
else:
# Emby merges audio and subtitle index together
audioTracks = len(player.getAvailableAudioStreams())
player.setSubtitleStream(index - audioTracks - 1)
# Let service know
window('emby_command', value="true")
elif command == "DisplayMessage":
header = arguments['Header']
text = arguments['Text']
dialog(type_="notification",
heading=header,
message=text,
icon="{emby}",
time=4000)
elif command == "SendString":
params = {
'text': arguments['String'],
'done': False
}
result = JSONRPC("Input.SendText").execute(params)
elif command in ("MoveUp", "MoveDown", "MoveRight", "MoveLeft"):
# Commands that should wake up display
actions = {
'MoveUp': "Input.Up",
'MoveDown': "Input.Down",
'MoveRight': "Input.Right",
'MoveLeft': "Input.Left"
}
result = JSONRPC(actions[command]).execute()
elif command == "GoHome":
result = JSONRPC("GUI.ActivateWindow").execute({"window":"home"})
else:
builtin = {
'ToggleFullscreen': 'Action(FullScreen)',
'ToggleOsdMenu': 'Action(OSD)',
'ToggleContextMenu': 'Action(ContextMenu)',
'Select': 'Action(Select)',
'Back': 'Action(back)',
'PageUp': 'Action(PageUp)',
'NextLetter': 'Action(NextLetter)',
'GoToSearch': 'VideoLibrary.Search',
'GoToSettings': 'ActivateWindow(Settings)',
'PageDown': 'Action(PageDown)',
'PreviousLetter': 'Action(PrevLetter)',
'TakeScreenshot': 'TakeScreenshot',
'ToggleMute': 'Mute',
'VolumeUp': 'Action(VolumeUp)',
'VolumeDown': 'Action(VolumeDown)',
}
action = builtin.get(command)
if action:
xbmc.executebuiltin(action)
@classmethod
def _server_restarting(cls):
if settings('supressRestartMsg') == "true":
dialog(type_="notification",
heading=lang(29999),
message=lang(33006),
icon="{emby}")
def on_close(self, ws):
log.debug("Closed.")
log.debug("closed")
def on_open(self, ws):
self.doUtils.postCapabilities(self.deviceId)
self.doutils.postCapabilities(self.device_id)
def on_error(self, ws, error):
if "10061" in str(error):
# Server is offline
pass
else:
log.debug("Error: %s" % error)
log.debug("Error: %s", error)
def run(self):
loglevel = int(window('emby_logLevel'))
# websocket.enableTrace(True)
userId = window('emby_currUser')
server = window('emby_server%s' % userId)
token = window('emby_accessToken%s' % userId)
user_id = window('emby_currUser')
server = window('emby_server%s' % user_id)
token = window('emby_accessToken%s' % user_id)
# Get the appropriate prefix for the websocket
if "https" in server:
server = server.replace('https', "wss")
else:
server = server.replace('http', "ws")
websocket_url = "%s?api_key=%s&deviceId=%s" % (server, token, self.deviceId)
log.info("websocket url: %s" % websocket_url)
websocket_url = "%s?api_key=%s&deviceId=%s" % (server, token, self.device_id)
log.info("websocket url: %s", websocket_url)
self.client = websocket.WebSocketApp(websocket_url,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close)
self.client.on_open = self.on_open
self._client = websocket.WebSocketApp(websocket_url,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close)
self._client.on_open = self.on_open
log.warn("----===## Starting WebSocketClient ##===----")
while not self.monitor.abortRequested():
self.client.run_forever(ping_interval=10)
if self.stopWebsocket:
self._client.run_forever(ping_interval=10)
if self._stop_websocket:
break
if self.monitor.waitForAbort(5):
@ -308,8 +323,8 @@ class WebSocket_Client(threading.Thread):
log.warn("##===---- WebSocketClient Stopped ----===##")
def stopClient(self):
def stop_client(self):
self.stopWebsocket = True
self.client.close()
log.info("Stopping thread.")
self._stop_websocket = True
self._client.close()
log.info("Stopping thread")

View File

@ -10,7 +10,6 @@ from datetime import datetime
import xbmc
import xbmcaddon
import xbmcgui
#################################################################################################
@ -55,22 +54,22 @@ class Service(object):
def __init__(self):
self.clientInfo = clientinfo.ClientInfo()
self.addonName = self.clientInfo.get_addon_name()
logLevel = settings('logLevel')
self.client_info = clientinfo.ClientInfo()
self.addon_name = self.client_info.get_addon_name()
log_level = settings('logLevel')
self.monitor = xbmc.Monitor()
window('emby_logLevel', value=str(logLevel))
window('emby_logLevel', value=str(log_level))
window('emby_kodiProfile', value=xbmc.translatePath('special://profile'))
# Initial logging
log.warn("======== START %s ========", self.addonName)
log.warn("======== START %s ========", self.addon_name)
log.warn("Python Version: %s", sys.version)
log.warn("Platform: %s", self.clientInfo.get_platform())
log.warn("Platform: %s", self.client_info.get_platform())
log.warn("KODI Version: %s", xbmc.getInfoLabel('System.BuildVersion'))
log.warn("%s Version: %s", self.addonName, self.clientInfo.get_version())
log.warn("%s Version: %s", self.addon_name, self.client_info.get_version())
log.warn("Using plugin paths: %s", settings('useDirectPaths') == "0")
log.warn("Log Level: %s", logLevel)
log.warn("Log Level: %s", log_level)
# Reset window props for profile switch
properties = [
@ -89,7 +88,7 @@ class Service(object):
# Set the minimum database version
window('emby_minDBVersion', value="1.1.63")
def service_entry_point(self):
# Important: Threads depending on abortRequest will not trigger
@ -173,7 +172,7 @@ class Service(object):
message=("%s %s%s!"
% (lang(33000), user.get_username().decode('utf-8'),
add.decode('utf-8'))),
icon="{default}",
icon="{emby}",
time=2000,
sound=False)
@ -227,16 +226,16 @@ class Service(object):
if settings('offlineMsg') == "true":
dialog(type_="notification",
heading=lang(33001),
message="%s %s" % (self.addonName, lang(33002)),
icon="{default}",
message="%s %s" % (self.addon_name, lang(33002)),
icon="{emby}",
sound=False)
self.server_online = False
elif window('emby_online') == "sleep":
# device going to sleep
if self.websocket_running:
ws.stopClient()
ws.stop_client()
ws = wsc.WebSocket_Client()
self.websocket_running = False
@ -257,7 +256,7 @@ class Service(object):
dialog(type_="notification",
heading=lang(29999),
message=lang(33003),
icon="{default}",
icon="{emby}",
time=2000,
sound=False)
@ -289,9 +288,9 @@ class Service(object):
library.stopThread()
if self.websocket_running:
ws.stopClient()
ws.stop_client()
log.warn("======== STOP %s ========", self.addonName)
log.warn("======== STOP %s ========", self.addon_name)
# Delay option
DELAY = int(settings('startupDelay'))