This commit is contained in:
angelblue05 2016-09-08 22:13:25 -05:00 committed by GitHub
parent e941674e74
commit b945459dfb
8 changed files with 447 additions and 419 deletions

View file

@ -98,9 +98,9 @@ class PlaybackUtils():
dummyPlaylist = True
playlist.add(playurl, listitem, index=startPos)
# Remove the original item from playlist
self.pl.removefromPlaylist(startPos+1)
self.pl.remove_from_playlist(startPos+1)
# Readd the original item to playlist - via jsonrpc so we have full metadata
self.pl.insertintoPlaylist(currentPosition+1, dbid, self.item['Type'].lower())
self.pl.insert_to_playlist(currentPosition+1, dbid, self.item['Type'].lower())
currentPosition += 1
############### -- CHECK FOR INTROS ################
@ -131,7 +131,7 @@ class PlaybackUtils():
pbutils = PlaybackUtils(intro)
pbutils.setProperties(introPlayurl, introListItem)
self.pl.insertintoPlaylist(currentPosition, url=introPlayurl)
self.pl.insert_to_playlist(currentPosition, url=introPlayurl)
introsPlaylist = True
currentPosition += 1
@ -142,7 +142,7 @@ class PlaybackUtils():
# Extend our current playlist with the actual item to play
# only if there's no playlist first
log.info("Adding main item to playlist.")
self.pl.addtoPlaylist(dbid, self.item['Type'].lower())
self.pl.add_to_playlist(dbid, self.item['Type'].lower())
# Ensure that additional parts are played after the main item
currentPosition += 1
@ -166,7 +166,7 @@ class PlaybackUtils():
pbutils.setArtwork(additionalListItem)
playlist.add(additionalPlayurl, additionalListItem, index=currentPosition)
self.pl.verifyPlaylist()
self.pl.verify_playlist()
currentPosition += 1
if dummyPlaylist:
@ -181,7 +181,7 @@ class PlaybackUtils():
log.debug("Resetting properties playback flag.")
window('emby_playbackProps', clear=True)
#self.pl.verifyPlaylist()
#self.pl.verify_playlist()
########## SETUP MAIN ITEM ##########
# For transcoding only, ask for audio/subs pref

View file

@ -38,7 +38,7 @@ class Player(xbmc.Player):
self.clientInfo = clientinfo.ClientInfo()
self.doUtils = downloadutils.DownloadUtils().downloadUrl
self.ws = wsc.WebSocket_Client()
self.ws = wsc.WebSocketClient()
self.xbmcplayer = xbmc.Player()
log.debug("Starting playback monitor.")

View file

@ -2,18 +2,16 @@
#################################################################################################
import json
import logging
import xbmc
import xbmcgui
import xbmcplugin
import playutils
import playbackutils
import embydb_functions as embydb
import read_embyserver as embyserver
from utils import window, settings, language as lang, kodiSQL
from utils import window, kodiSQL, JSONRPC
#################################################################################################
@ -22,169 +20,141 @@ log = logging.getLogger("EMBY."+__name__)
#################################################################################################
class Playlist():
class Playlist(object):
def __init__(self):
self.userid = window('emby_currUser')
self.server = window('emby_server%s' % self.userid)
self.emby = embyserver.Read_EmbyServer()
def playAll(self, itemids, startat):
def play_all(self, item_ids, start_at):
embyconn = kodiSQL('emby')
embycursor = embyconn.cursor()
emby_db = embydb.Embydb_Functions(embycursor)
conn = kodiSQL('emby')
cursor = conn.cursor()
emby_db = embydb.Embydb_Functions(cursor)
player = xbmc.Player()
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
playlist.clear()
log.info("---*** PLAY ALL ***---")
log.info("Items: %s and start at: %s" % (itemids, startat))
log.info("Items: %s and start at: %s", item_ids, start_at)
started = False
window('emby_customplaylist', value="true")
if startat != 0:
if start_at:
# Seek to the starting position
window('emby_customplaylist.seektime', str(startat))
window('emby_customplaylist.seektime', str(start_at))
for itemid in itemids:
embydb_item = emby_db.getItem_byId(itemid)
for item_id in item_ids:
log.info("Adding %s to playlist", item_id)
item = emby_db.getItem_byId(item_id)
try:
dbid = embydb_item[0]
mediatype = embydb_item[4]
db_id = item[0]
media_type = item[4]
except TypeError:
# Item is not found in our database, add item manually
log.info("Item was not found in the database, manually adding item.")
item = self.emby.getItem(itemid)
self.addtoPlaylist_xbmc(playlist, item)
else:
# Add to playlist
self.addtoPlaylist(dbid, mediatype)
log.info("Item was not found in the database, manually adding item")
item = self.emby.getItem(item_id)
self.add_to_xbmc_playlist(playlist, item)
log.info("Adding %s to playlist." % itemid)
else: # Add to playlist
self.add_to_playlist(db_id, media_type)
if not started:
started = True
player.play(playlist)
self.verifyPlaylist()
embycursor.close()
self.verify_playlist()
cursor.close()
def modifyPlaylist(self, itemids):
def modify_playlist(self, item_ids):
embyconn = kodiSQL('emby')
embycursor = embyconn.cursor()
emby_db = embydb.Embydb_Functions(embycursor)
conn = kodiSQL('emby')
cursor = conn.cursor()
emby_db = embydb.Embydb_Functions(cursor)
log.info("---*** ADD TO PLAYLIST ***---")
log.info("Items: %s" % itemids)
log.info("Items: %s", item_ids)
player = xbmc.Player()
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
for itemid in itemids:
embydb_item = emby_db.getItem_byId(itemid)
for item_id in item_ids:
log.info("Adding %s to playlist", item_id)
item = emby_db.getItem_byId(item_id)
try:
dbid = embydb_item[0]
mediatype = embydb_item[4]
db_id = item[0]
media_type = item[4]
except TypeError:
# Item is not found in our database, add item manually
item = self.emby.getItem(itemid)
self.addtoPlaylist_xbmc(playlist, item)
else:
# Add to playlist
self.addtoPlaylist(dbid, mediatype)
item = self.emby.getItem(item_id)
self.add_to_xbmc_playlist(playlist, item)
log.info("Adding %s to playlist." % itemid)
else: # Add to playlist
self.add_to_playlist(db_id, media_type)
self.verifyPlaylist()
embycursor.close()
self.verify_playlist()
cursor.close()
return playlist
def addtoPlaylist(self, dbid=None, mediatype=None, url=None):
pl = {
'jsonrpc': "2.0",
'id': 1,
'method': "Playlist.Add",
'params': {
'playlistid': 1
}
}
if dbid is not None:
pl['params']['item'] = {'%sid' % mediatype: int(dbid)}
else:
pl['params']['item'] = {'file': url}
log.debug(xbmc.executeJSONRPC(json.dumps(pl)))
def addtoPlaylist_xbmc(self, playlist, item):
@classmethod
def add_to_xbmc_playlist(cls, playlist, item):
playurl = playutils.PlayUtils(item).getPlayUrl()
if not playurl:
# Playurl failed
log.info("Failed to retrieve playurl.")
log.info("Failed to retrieve playurl")
return
log.info("Playurl: %s" % playurl)
log.info("Playurl: %s", playurl)
listitem = xbmcgui.ListItem()
playbackutils.PlaybackUtils(item).setProperties(playurl, listitem)
playlist.add(playurl, listitem)
def insertintoPlaylist(self, position, dbid=None, mediatype=None, url=None):
@classmethod
def add_to_playlist(cls, db_id=None, media_type=None, url=None):
pl = {
params = {
'jsonrpc': "2.0",
'id': 1,
'method': "Playlist.Insert",
'params': {
'playlistid': 1,
'position': position
}
'playlistid': 1
}
if dbid is not None:
pl['params']['item'] = {'%sid' % mediatype: int(dbid)}
if db_id is not None:
params['item'] = {'%sid' % media_type: int(db_id)}
else:
pl['params']['item'] = {'file': url}
params['item'] = {'file': url}
log.debug(xbmc.executeJSONRPC(json.dumps(pl)))
log.debug(JSONRPC('Playlist.Add').execute(params))
def verifyPlaylist(self):
@classmethod
def insert_to_playlist(cls, position, db_id=None, media_type=None, url=None):
pl = {
params = {
'jsonrpc': "2.0",
'id': 1,
'method': "Playlist.GetItems",
'params': {
'playlistid': 1
}
'playlistid': 1,
'position': position
}
log.debug(xbmc.executeJSONRPC(json.dumps(pl)))
if db_id is not None:
params['item'] = {'%sid' % media_type: int(db_id)}
else:
params['item'] = {'file': url}
def removefromPlaylist(self, position):
log.debug(JSONRPC('Playlist.Insert').execute(params))
pl = {
@classmethod
def verify_playlist(cls):
log.debug(JSONRPC('Playlist.GetItems').execute({'playlistid': 1}))
'jsonrpc': "2.0",
'id': 1,
'method': "Playlist.Remove",
'params': {
@classmethod
def remove_from_playlist(cls, position):
'playlistid': 1,
'position': position
}
params = {
'playlistid': 1,
'position': position
}
log.debug(xbmc.executeJSONRPC(json.dumps(pl)))
log.debug(JSONRPC('Playlist.Remove').execute(params))

View file

@ -57,12 +57,16 @@ def dialog(type_, **kwargs):
if "icon" in kwargs:
kwargs['icon'] = kwargs['icon'].replace("{emby}",
"special://home/addons/plugin.video.emby/icon.png")
if "heading" in kwargs:
kwargs['heading'] = kwargs['heading'].replace("{emby}", language(29999))
types = {
'yesno': d.yesno,
'ok': d.ok,
'notification': d.notification,
'input': d.input
'input': d.input,
'select': d.select,
'numeric': d.numeric
}
return types[type_](**kwargs)

View file

@ -23,7 +23,7 @@ log = logging.getLogger("EMBY."+__name__)
##################################################################################################
class WebSocket_Client(threading.Thread):
class WebSocketClient(threading.Thread):
_shared_state = {}
@ -35,12 +35,12 @@ class WebSocket_Client(threading.Thread):
self.__dict__ = self._shared_state
self.monitor = xbmc.Monitor()
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)
@ -66,15 +66,15 @@ class WebSocket_Client(threading.Thread):
message_type = result['MessageType']
data = result['Data']
if message_type not in ('SessionEnded'):
if message_type not in ('NotificationAdded', 'SessionEnded'):
# Mute certain events
log.info("Message: %s" % message)
log.info("Message: %s", message)
if message_type == "Play":
if message_type == 'Play':
# A remote control play command has been sent from the server.
self._play_(data)
elif message_type == "Playstate":
elif message_type == 'Playstate':
# A remote control update playstate command has been sent from the server.
self._playstate_(data)
@ -84,16 +84,7 @@ class WebSocket_Client(threading.Thread):
self.library_sync.triage_items("userdata", userdata_list)
elif message_type == "LibraryChanged":
librarySync = self.library_sync
processlist = {
'added': data['ItemsAdded'],
'update': data['ItemsUpdated'],
'remove': data['ItemsRemoved']
}
for action in processlist:
librarySync.triage_items(action, processlist[action])
self._library_changed(data)
elif message_type == "GeneralCommand":
self._general_commands(data)
@ -118,26 +109,26 @@ class WebSocket_Client(threading.Thread):
playlist_ = playlist.Playlist()
if command == "PlayNow":
if command == 'PlayNow':
startat = data.get('StartPositionTicks', 0)
playlist_.playAll(item_ids, startat)
playlist_.play_all(item_ids, startat)
dialog(type_="notification",
heading=lang(29999),
heading="{emby}",
message="%s %s" % (len(item_ids), lang(33004)),
icon="{emby}",
sound=False)
elif command == "PlayNext":
newplaylist = playlist_.modifyPlaylist(item_ids)
elif command == 'PlayNext':
new_playlist = playlist_.modify_playlist(item_ids)
dialog(type_="notification",
heading=lang(29999),
heading="{emby}",
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)
player.play(new_playlist)
@classmethod
def _playstate_(cls, data):
@ -151,21 +142,36 @@ class WebSocket_Client(threading.Thread):
'Unpause': player.pause,
'Pause': player.pause,
'NextTrack': player.playnext,
'PreviousTrack': player.playprevious,
'Seek': player.seekTime
'PreviousTrack': player.playprevious
}
action = actions[command]
if command == "Seek":
seekto = data['SeekPositionTicks']
seektime = seekto / 10000000.0
action(seektime)
log.info("Seek to %s", seektime)
else:
action()
if command == 'Seek':
seek_to = data['SeekPositionTicks']
seek_time = seek_to / 10000000.0
player.seekTime(seek_time)
log.info("Seek to %s", seek_time)
elif command in actions:
actions[command]()
log.info("Command: %s completed", command)
else:
log.info("Unknown command: %s", command)
return
window('emby_command', value="true")
def _library_changed(self, data):
process_list = {
'added': data['ItemsAdded'],
'update': data['ItemsUpdated'],
'remove': data['ItemsRemoved']
}
for action in process_list:
self.library_sync.triage_items(action, process_list[action])
@classmethod
def _general_commands(cls, data):
@ -177,42 +183,46 @@ class WebSocket_Client(threading.Thread):
player = xbmc.Player()
# These commands need to be reported back
if command == "Mute":
if command == 'Mute':
xbmc.executebuiltin('Mute')
elif command == "Unmute":
elif command == 'Unmute':
xbmc.executebuiltin('Mute')
elif command == "SetVolume":
elif command == 'SetVolume':
volume = arguments['Volume']
xbmc.executebuiltin('SetVolume(%s[,showvolumebar])' % volume)
elif command == "SetAudioStreamIndex":
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)
elif command == 'SetSubtitleStreamIndex':
emby_index = int(arguments['Index'])
current_file = player.getPlayingFile()
mapping = window('emby_%s.indexMapping' % current_file)
if mapping:
externalIndex = json.loads(mapping)
external_index = json.loads(mapping)
# If there's external subtitles added via playbackutils
for index in externalIndex:
if externalIndex[index] == embyindex:
for index in external_index:
if external_index[index] == emby_index:
player.setSubtitleStream(int(index))
break
else:
# User selected internal subtitles
external = len(externalIndex)
audioTracks = len(player.getAvailableAudioStreams())
player.setSubtitleStream(external + embyindex - audioTracks - 1)
external = len(external_index)
audio_tracks = len(player.getAvailableAudioStreams())
player.setSubtitleStream(external + emby_index - audio_tracks - 1)
else:
# Emby merges audio and subtitle index together
audioTracks = len(player.getAvailableAudioStreams())
player.setSubtitleStream(index - audioTracks - 1)
audio_tracks = len(player.getAvailableAudioStreams())
player.setSubtitleStream(index - audio_tracks - 1)
# Let service know
window('emby_command', value="true")
elif command == "DisplayMessage":
elif command == 'DisplayMessage':
header = arguments['Header']
text = arguments['Text']
@ -222,26 +232,28 @@ class WebSocket_Client(threading.Thread):
icon="{emby}",
time=4000)
elif command == "SendString":
elif command == 'SendString':
params = {
'text': arguments['String'],
'done': False
}
result = JSONRPC("Input.SendText").execute(params)
JSONRPC('Input.SendText').execute(params)
elif command in ("MoveUp", "MoveDown", "MoveRight", "MoveLeft"):
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()
JSONRPC(actions[command]).execute()
elif command == "GoHome":
result = JSONRPC("GUI.ActivateWindow").execute({"window":"home"})
elif command == 'GoHome':
JSONRPC('GUI.ActivateWindow').execute({'window': "home"})
else:
builtin = {
@ -262,16 +274,15 @@ class WebSocket_Client(threading.Thread):
'VolumeUp': 'Action(VolumeUp)',
'VolumeDown': 'Action(VolumeDown)',
}
action = builtin.get(command)
if action:
xbmc.executebuiltin(action)
if command in builtin:
xbmc.executebuiltin(builtin[command])
@classmethod
def _server_restarting(cls):
if settings('supressRestartMsg') == "true":
dialog(type_="notification",
heading=lang(29999),
heading="{emby}",
message=lang(33006),
icon="{emby}")
@ -282,6 +293,7 @@ class WebSocket_Client(threading.Thread):
self.doutils.postCapabilities(self.device_id)
def on_error(self, ws, error):
if "10061" in str(error):
# Server is offline
pass
@ -291,7 +303,6 @@ class WebSocket_Client(threading.Thread):
def run(self):
# websocket.enableTrace(True)
user_id = window('emby_currUser')
server = window('emby_server%s' % user_id)
token = window('emby_accessToken%s' % user_id)
@ -305,9 +316,9 @@ class WebSocket_Client(threading.Thread):
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)
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 ##===----")