def __init__(self): self.win = xbmcgui.Window(10000) self.addon = xbmcaddon.Addon(ADDON_ID) self.metadatautils = MetadataUtils() self.addonname = self.addon.getAddonInfo('name').decode("utf-8") self.addonversion = self.addon.getAddonInfo('version').decode("utf-8") self.kodimonitor = KodiMonitor(metadatautils=self.metadatautils, win=self.win) listitem_monitor = ListItemMonitor( metadatautils=self.metadatautils, win=self.win, monitor=self.kodimonitor) webservice = WebService(metadatautils=self.metadatautils) # start the extra threads listitem_monitor.start() webservice.start() self.win.clearProperty("SkinHelperShutdownRequested") log_msg('%s version %s started' % (self.addonname, self.addonversion), xbmc.LOGNOTICE) # run as service, check skin every 10 seconds and keep the other threads alive while not self.kodimonitor.abortRequested(): # check skin version info self.check_skin_version() # sleep for 10 seconds self.kodimonitor.waitForAbort(10) # Abort was requested while waiting. We should exit self.win.setProperty("SkinHelperShutdownRequested", "shutdown") log_msg('Shutdown requested !', xbmc.LOGNOTICE) # stop the extra threads listitem_monitor.stop() webservice.stop() # cleanup objects self.close()
def __init__(self): self.win = xbmcgui.Window(10000) self.addon = xbmcaddon.Addon(ADDON_ID) self.artutils = ArtUtils() self.addonname = self.addon.getAddonInfo('name').decode("utf-8") self.addonversion = self.addon.getAddonInfo('version').decode("utf-8") self.kodimonitor = KodiMonitor(artutils=self.artutils, win=self.win) listitem_monitor = ListItemMonitor( artutils=self.artutils, win=self.win, monitor=self.kodimonitor) webservice = WebService(artutils=self.artutils) widget_task_interval = 520 # start the extra threads listitem_monitor.start() webservice.start() self.win.clearProperty("SkinHelperShutdownRequested") log_msg('%s version %s started' % (self.addonname, self.addonversion), xbmc.LOGNOTICE) # run as service, check skin every 10 seconds and keep the other threads alive while not self.kodimonitor.abortRequested(): # check skin version info self.check_skin_version() # set generic widget reload widget_task_interval += 10 if widget_task_interval >= 300: self.win.setProperty("widgetreload2", time.strftime("%Y%m%d%H%M%S", time.gmtime())) widget_task_interval = 0 # sleep for 10 seconds self.kodimonitor.waitForAbort(10) # Abort was requested while waiting. We should exit self.win.setProperty("SkinHelperShutdownRequested", "shutdown") log_msg('Shutdown requested !', xbmc.LOGNOTICE) # stop the extra threads listitem_monitor.stop() webservice.stop() # cleanup objects self.close()
def __init__(self): self.win = xbmcgui.Window(10000) self.addon = xbmcaddon.Addon(ADDON_ID) self.metadatautils = MetadataUtils() self.addonname = self.addon.getAddonInfo('name').decode("utf-8") self.addonversion = self.addon.getAddonInfo('version').decode("utf-8") self.kodimonitor = KodiMonitor(metadatautils=self.metadatautils, win=self.win) listitem_monitor = ListItemMonitor(metadatautils=self.metadatautils, win=self.win, monitor=self.kodimonitor) webservice = WebService(metadatautils=self.metadatautils) # start the extra threads listitem_monitor.start() webservice.start() self.win.clearProperty("SkinHelperShutdownRequested") log_msg('%s version %s started' % (self.addonname, self.addonversion), xbmc.LOGNOTICE) # run as service, check skin every 10 seconds and keep the other threads alive while not self.kodimonitor.abortRequested(): # check skin version info self.check_skin_version() # sleep for 10 seconds self.kodimonitor.waitForAbort(10) # Abort was requested while waiting. We should exit self.win.setProperty("SkinHelperShutdownRequested", "shutdown") log_msg('Shutdown requested !', xbmc.LOGNOTICE) # stop the extra threads listitem_monitor.stop() webservice.stop() # cleanup objects self.close()
class Monitor(xbmc.Monitor): servers = [] sleep = False def __init__(self): self.player = player.Player() self.device_id = get_device_id() self.listener = Listener(self) self.listener.start() self.webservice = WebService() self.webservice.start() xbmc.Monitor.__init__(self) def onScanStarted(self, library): LOG.info("-->[ kodi scan/%s ]", library) def onScanFinished(self, library): LOG.info("--<[ kodi scan/%s ]", library) def onNotification(self, sender, method, data): if sender.lower() not in ('plugin.video.jellyfin', 'xbmc', 'upnextprovider.signal'): return if sender == 'plugin.video.jellyfin': method = method.split('.')[1] if method not in ('GetItem', 'ReportProgressRequested', 'LoadServer', 'RandomItems', 'Recommended', 'GetServerAddress', 'GetPlaybackInfo', 'Browse', 'GetImages', 'GetToken', 'PlayPlaylist', 'Play', 'GetIntros', 'GetAdditionalParts', 'RefreshItem', 'Genres', 'FavoriteItem', 'DeleteItem', 'AddUser', 'GetSession', 'GetUsers', 'GetThemes', 'GetTheme', 'Playstate', 'GeneralCommand', 'GetTranscodeOptions', 'RecentlyAdded', 'BrowseSeason', 'LiveTV', 'GetLiveStream'): return data = json.loads(data)[0] elif sender.startswith('upnextprovider'): LOG.info('Attempting to play the next episode via upnext') method = method.split('.', 1)[1] if method not in ('plugin.video.jellyfin_play_action', ): LOG.info('Received invalid upnext method: %s', method) return data = json.loads(data) method = "Play" if data: data = json.loads(binascii.unhexlify(data[0])) else: if method not in ('Player.OnPlay', 'VideoLibrary.OnUpdate', 'Player.OnAVChange'): ''' We have to clear the playlist if it was stopped before it has been played completely. Otherwise the next played item will be added the previous queue. ''' if method == "Player.OnStop": xbmc.sleep( 3000 ) # let's wait for the player so we don't clear the canceled playlist by mistake. if xbmc.getCondVisibility( "!Player.HasMedia + !Window.IsVisible(busydialog)" ): xbmc.executebuiltin("Playlist.Clear") LOG.info("[ playlist ] cleared") return data = json.loads(data) LOG.debug("[ %s: %s ] %s", sender, method, JsonDebugPrinter(data)) if self.sleep: LOG.info("System.OnSleep detected, ignore monitor request.") return try: if not data.get('ServerId'): server = Jellyfin() else: if method != 'LoadServer' and data[ 'ServerId'] not in self.servers: try: connect.Connect().register(data['ServerId']) self.server_instance(data['ServerId']) except Exception as error: LOG.exception(error) dialog("ok", heading="{jellyfin}", line1=translate(33142)) return server = Jellyfin(data['ServerId']) except Exception as error: LOG.exception(error) server = Jellyfin() if method == 'GetItem': item = server.jellyfin.get_item(data['Id']) self.void_responder(data, item) elif method == 'GetAdditionalParts': item = server.jellyfin.get_additional_parts(data['Id']) self.void_responder(data, item) elif method == 'GetIntros': item = server.jellyfin.get_intros(data['Id']) self.void_responder(data, item) elif method == 'GetImages': item = server.jellyfin.get_images(data['Id']) self.void_responder(data, item) elif method == 'GetServerAddress': server_address = server.auth.get_server_info( server.auth.server_id)['address'] self.void_responder(data, server_address) elif method == 'GetPlaybackInfo': sources = server.jellyfin.get_play_info(data['Id'], data['Profile']) self.void_responder(data, sources) elif method == 'GetLiveStream': sources = server.jellyfin.get_live_stream(data['Id'], data['PlaySessionId'], data['Token'], data['Profile']) self.void_responder(data, sources) elif method == 'GetToken': token = server.auth.jellyfin_token() self.void_responder(data, token) elif method == 'GetSession': session = server.jellyfin.get_device(self.device_id) self.void_responder(data, session) elif method == 'GetUsers': users = server.jellyfin.get_users() self.void_responder(data, users) elif method == 'GetTranscodeOptions': result = server.jellyfin.get_transcode_settings() self.void_responder(data, result) elif method == 'GetThemes': if data['Type'] == 'Video': theme = server.jellyfin.get_items_theme_video(data['Id']) else: theme = server.jellyfin.get_items_theme_song(data['Id']) self.void_responder(data, theme) elif method == 'GetTheme': theme = server.jellyfin.get_themes(data['Id']) self.void_responder(data, theme) elif method == 'Browse': result = downloader.get_filtered_section(data.get('Id'), data.get('Media'), data.get('Limit'), data.get('Recursive'), data.get('Sort'), data.get('SortOrder'), data.get('Filters'), data.get('Params'), data.get('ServerId')) self.void_responder(data, result) elif method == 'BrowseSeason': result = server.jellyfin.get_seasons(data['Id']) self.void_responder(data, result) elif method == 'LiveTV': result = server.jellyfin.get_channels() self.void_responder(data, result) elif method == 'RecentlyAdded': result = server.jellyfin.get_recently_added( data.get('Media'), data.get('Id'), data.get('Limit')) self.void_responder(data, result) elif method == 'Genres': result = server.jellyfin.get_genres(data.get('Id')) self.void_responder(data, result) elif method == 'Recommended': result = server.jellyfin.get_recommendation( data.get('Id'), data.get('Limit')) self.void_responder(data, result) elif method == 'RefreshItem': server.jellyfin.refresh_item(data['Id']) elif method == 'FavoriteItem': server.jellyfin.favorite(data['Id'], data['Favorite']) elif method == 'DeleteItem': server.jellyfin.delete_item(data['Id']) elif method == 'PlayPlaylist': server.jellyfin.post_session( server.config.data['app.session'], "Playing", { 'PlayCommand': "PlayNow", 'ItemIds': data['Id'], 'StartPositionTicks': 0 }) elif method == 'Play': items = server.jellyfin.get_items(data['ItemIds']) PlaylistWorker(data.get('ServerId'), items, data['PlayCommand'] == 'PlayNow', data.get('StartPositionTicks', 0), data.get('AudioStreamIndex'), data.get('SubtitleStreamIndex')).start() elif method in ('ReportProgressRequested', 'Player.OnAVChange'): self.player.report_playback(data.get('Report', True)) elif method == 'Playstate': self.playstate(data) elif method == 'GeneralCommand': self.general_commands(data) elif method == 'LoadServer': self.server_instance(data['ServerId']) elif method == 'AddUser': server.jellyfin.session_add_user(server.config.data['app.session'], data['Id'], data['Add']) self.additional_users(server) elif method == 'Player.OnPlay': on_play(data, server) elif method == 'VideoLibrary.OnUpdate': on_update(data, server) def void_responder(self, data, result): window('jellyfin_%s.json' % data['VoidName'], result) LOG.debug("--->[ nostromo/jellyfin_%s.json ] sent", data['VoidName']) def server_instance(self, server_id=None): server = Jellyfin(server_id) self.post_capabilities(server) if server_id is not None: self.servers.append(server_id) elif settings('additionalUsers'): users = settings('additionalUsers').split(',') all_users = server.jellyfin.get_users() for additional in users: for user in all_users: if user['Name'].lower() in additional.lower(): server.jellyfin.session_add_user( server.config.data['app.session'], user['Id'], True) self.additional_users(server) def post_capabilities(self, server): LOG.info("--[ post capabilities/%s ]", server.auth.server_id) server.jellyfin.post_capabilities({ 'PlayableMediaTypes': "Audio,Video", 'SupportsMediaControl': True, 'SupportedCommands': ("MoveUp,MoveDown,MoveLeft,MoveRight,Select," "Back,ToggleContextMenu,ToggleFullscreen,ToggleOsdMenu," "GoHome,PageUp,NextLetter,GoToSearch," "GoToSettings,PageDown,PreviousLetter,TakeScreenshot," "VolumeUp,VolumeDown,ToggleMute,SendString,DisplayMessage," "SetAudioStreamIndex,SetSubtitleStreamIndex," "SetRepeatMode," "Mute,Unmute,SetVolume," "Play,Playstate,PlayNext,PlayMediaSource"), }) session = server.jellyfin.get_device(self.device_id) server.config.data['app.session'] = session[0]['Id'] def additional_users(self, server): ''' Setup additional users images. ''' for i in range(10): window('JellyfinAdditionalUserImage.%s' % i, clear=True) try: session = server.jellyfin.get_device(self.device_id) except Exception as error: LOG.exception(error) return for index, user in enumerate(session[0]['AdditionalUsers']): info = server.jellyfin.get_user(user['UserId']) image = api.API( info, server.config.data['auth.server']).get_user_artwork( user['UserId']) window('JellyfinAdditionalUserImage.%s' % index, image) window('JellyfinAdditionalUserPosition.%s' % user['UserId'], str(index)) def playstate(self, data): ''' Jellyfin playstate updates. ''' command = data['Command'] actions = { 'Stop': self.player.stop, 'Unpause': self.player.pause, 'Pause': self.player.pause, 'PlayPause': self.player.pause, 'NextTrack': self.player.playnext, 'PreviousTrack': self.player.playprevious } if command == 'Seek': if self.player.isPlaying(): seektime = data['SeekPositionTicks'] / 10000000.0 self.player.seekTime(seektime) LOG.info("[ seek/%s ]", seektime) elif command in actions: actions[command]() LOG.info("[ command/%s ]", command) def general_commands(self, data): ''' General commands from Jellyfin to control the Kodi interface. ''' command = data['Name'] args = data['Arguments'] if command in ('Mute', 'Unmute', 'SetVolume', 'SetSubtitleStreamIndex', 'SetAudioStreamIndex', 'SetRepeatMode'): if command == 'Mute': xbmc.executebuiltin('Mute') elif command == 'Unmute': xbmc.executebuiltin('Mute') elif command == 'SetVolume': xbmc.executebuiltin('SetVolume(%s[,showvolumebar])' % args['Volume']) elif command == 'SetRepeatMode': xbmc.executebuiltin('xbmc.PlayerControl(%s)' % args['RepeatMode']) elif command == 'SetAudioStreamIndex': self.player.set_audio_subs(args['Index']) elif command == 'SetSubtitleStreamIndex': self.player.set_audio_subs(None, args['Index']) self.player.report_playback() elif command == 'DisplayMessage': dialog("notification", heading=args['Header'], message=args['Text'], icon="{jellyfin}", time=int(settings('displayMessage')) * 1000) elif command == 'SendString': JSONRPC('Input.SendText').execute({ 'text': args['String'], 'done': False }) elif command == 'GoHome': JSONRPC('GUI.ActivateWindow').execute({'window': "home"}) elif command == 'Guide': JSONRPC('GUI.ActivateWindow').execute({'window': "tvguide"}) elif command in ('MoveUp', 'MoveDown', 'MoveRight', 'MoveLeft'): actions = { 'MoveUp': "Input.Up", 'MoveDown': "Input.Down", 'MoveRight': "Input.Right", 'MoveLeft': "Input.Left" } JSONRPC(actions[command]).execute() 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)', } if command in builtin: xbmc.executebuiltin(builtin[command])
from exploiter import Exploiter from webservice import WebService from submitter import Submitter from frontend import Frontend import signal import logging.config if __name__ == '__main__': logging.config.fileConfig(fname='log.conf') logger_exploiter = logging.getLogger('exploiter') logger_submitter = logging.getLogger('submitter') logger_webservice = logging.getLogger('webservice') WebService.start(logger_webservice) Exploiter.start(logger_exploiter) Submitter.start(logger_submitter) Frontend.start() signal.pause()
class MainService: '''our main background service running the various threads''' last_skin = "" def __init__(self): self.win = xbmcgui.Window(10000) self.addon = xbmcaddon.Addon(ADDON_ID) self.metadatautils = MetadataUtils() self.addonname = self.addon.getAddonInfo('name').decode("utf-8") self.addonversion = self.addon.getAddonInfo('version').decode("utf-8") self.kodimonitor = KodiMonitor(metadatautils=self.metadatautils, win=self.win) self.listitem_monitor = ListItemMonitor( metadatautils=self.metadatautils, win=self.win, monitor=self.kodimonitor) self.webservice = WebService(self.metadatautils) self.win.clearProperty("SkinHelperShutdownRequested") # start the extra threads self.listitem_monitor.start() self.webservice.start() log_msg('%s version %s started' % (self.addonname, self.addonversion), xbmc.LOGNOTICE) # run as service, check skin every 10 seconds and keep the other threads alive while not self.kodimonitor.abortRequested(): # check skin version info self.check_skin_version() # sleep for 10 seconds self.kodimonitor.waitForAbort(10) # Abort was requested while waiting. We should exit self.close() def close(self): '''Cleanup Kodi Cpython instances''' self.win.setProperty("SkinHelperShutdownRequested", "shutdown") log_msg('Shutdown requested !', xbmc.LOGNOTICE) self.listitem_monitor.stop() self.metadatautils.close() self.webservice.stop() del self.win del self.kodimonitor #del self.metadatautils #del self.webservice log_msg('%s version %s stopped' % (self.addonname, self.addonversion), xbmc.LOGNOTICE) def check_skin_version(self): '''check if skin changed''' try: skin = xbmc.getSkinDir() skin_addon = xbmcaddon.Addon(id=skin) skin_label = skin_addon.getAddonInfo('name').decode("utf-8") skin_version = skin_addon.getAddonInfo('version').decode("utf-8") this_skin = "%s-%s" % (skin_label, skin_version) del skin_addon if self.last_skin != this_skin: # auto correct skin settings if needed self.last_skin = this_skin self.win.setProperty("SkinHelper.skinTitle", "%s - %s: %s" % (skin_label, xbmc.getLocalizedString(19114), skin_version)) self.win.setProperty("SkinHelper.skin_version", "%s: %s" % (xbmc.getLocalizedString(19114), skin_version)) self.win.setProperty("SkinHelper.Version", self.addonversion.replace(".", "")) SkinSettings().correct_skin_settings() except Exception as exc: log_exception(__name__, exc)
from evtmgr import EventManager from webservice import WebService from serialcom import SerialCom def open_porta( who ): if mod_arduino.send_packet('porta', action='unlock'): print('porta aperta! ;)') else: print('porta chiusa :(') event_manager = EventManager() mod_webserver = WebService( event_manager ) mod_arduino = SerialCom( event_manager, '/dev/ttyATH0', 115200 ) event_manager.listen_event('on_porta_unlock_request', open_porta) mod_webserver.start()
class Monitor(xbmc.Monitor): servers = [] sleep = False def __init__(self): self.player = player.Player() self.device_id = get_device_id() self.listener = Listener(self) self.listener.start() self.webservice = WebService() self.webservice.start() self.workers_threads = [] self.queue = Queue.Queue() xbmc.Monitor.__init__(self) def onScanStarted(self, library): LOG.info("-->[ kodi scan/%s ]", library) def onScanFinished(self, library): LOG.info("--<[ kodi scan/%s ]", library) def _get_server(self, method, data): ''' Retrieve the Emby server. ''' try: if not data.get('ServerId'): raise Exception("ServerId undefined.") if method != 'LoadServer' and data['ServerId'] not in self.servers: try: connect.Connect().register(data['ServerId']) self.server_instance(data['ServerId']) except Exception as error: LOG.error(error) dialog("ok", heading="{emby}", line1=_(33142)) return server = Emby(data['ServerId']).get_client() except Exception: server = Emby().get_client() return server def add_worker(self, method): ''' Use threads to avoid blocking the onNotification function. ''' if len(self.workers_threads) < 3: new_thread = MonitorWorker(self) new_thread.start() self.workers_threads.append(new_thread) LOG.info("-->[ q:monitor/%s ]", method) def onNotification(self, sender, method, data): if sender.lower() not in ('plugin.video.emby', 'xbmc', 'upnextprovider.signal'): return if sender == 'plugin.video.emby': method = method.split('.')[1] if method not in ('GetItem', 'ReportProgressRequested', 'LoadServer', 'RandomItems', 'Recommended', 'GetServerAddress', 'GetPlaybackInfo', 'Browse', 'GetImages', 'GetToken', 'PlayPlaylist', 'Play', 'GetIntros', 'GetAdditionalParts', 'RefreshItem', 'Genres', 'FavoriteItem', 'DeleteItem', 'AddUser', 'GetSession', 'GetUsers', 'GetThemes', 'GetTheme', 'Playstate', 'GeneralCommand', 'GetTranscodeOptions', 'RecentlyAdded', 'BrowseSeason', 'LiveTV', 'GetLiveStream'): return data = json.loads(data)[0] elif sender.startswith('upnextprovider'): method = method.split('.')[1] if method not in ('plugin.video.emby_play_action'): return method = "Play" data = json.loads(data) data = json.loads(binascii.unhexlify(data[0])) if data else data else: if method not in ('Player.OnPlay', 'Player.OnStop', 'VideoLibrary.OnUpdate', 'Player.OnAVChange', 'Playlist.OnClear'): return data = json.loads(data) LOG.debug("[ %s: %s ] %s", sender, method, json.dumps(data, indent=4)) if self.sleep: LOG.info("System.OnSleep detected, ignore monitor request.") return server = self._get_server(method, data) self.queue.put((getattr(self, method.replace('.', '_')), server, data,)) self.add_worker(method) return def void_responder(self, data, result): window('emby_%s.json' % data['VoidName'], result) LOG.debug("--->[ nostromo/emby_%s.json ] sent", data['VoidName']) def server_instance(self, server_id=None): server = Emby(server_id) self.post_capabilities(server) if server_id is not None: self.servers.append(server_id) elif settings('additionalUsers'): users = settings('additionalUsers').split(',') all_users = server['api'].get_users() for additional in users: for user in all_users: if user['Name'].lower() in additional.decode('utf-8').lower(): server['api'].session_add_user(server['config/app.session'], user['Id'], True) self.additional_users(server) def post_capabilities(self, server): LOG.info("--[ post capabilities/%s ]", server['auth/server-id']) server['api'].post_capabilities({ 'PlayableMediaTypes': "Audio,Video", 'SupportsMediaControl': True, 'SupportedCommands': ( "MoveUp,MoveDown,MoveLeft,MoveRight,Select," "Back,ToggleContextMenu,ToggleFullscreen,ToggleOsdMenu," "GoHome,PageUp,NextLetter,GoToSearch," "GoToSettings,PageDown,PreviousLetter,TakeScreenshot," "VolumeUp,VolumeDown,ToggleMute,SendString,DisplayMessage," "SetAudioStreamIndex,SetSubtitleStreamIndex," "SetRepeatMode," "Mute,Unmute,SetVolume," "Play,Playstate,PlayNext,PlayMediaSource" ), 'IconUrl': "https://raw.githubusercontent.com/MediaBrowser/plugin.video.emby/master/kodi_icon.png", }) session = server['api'].get_device(self.device_id) server['config']['app.session'] = session[0]['Id'] def additional_users(self, server): ''' Setup additional users images. ''' for i in range(10): window('EmbyAdditionalUserImage.%s' % i, clear=True) try: session = server['api'].get_device(self.device_id) except Exception as error: LOG.error(error) return for index, user in enumerate(session[0]['AdditionalUsers']): info = server['api'].get_user(user['UserId']) image = api.API(info, server['config/auth.server']).get_user_artwork(user['UserId']) window('EmbyAdditionalUserImage.%s' % index, image) window('EmbyAdditionalUserPosition.%s' % user['UserId'], str(index)) def GetItem(self, server, data, *args, **kwargs): item = server['api'].get_item(data['Id']) self.void_responder(data, item) def GetAdditionalParts(self, server, data, *args, **kwargs): item = server['api'].get_additional_parts(data['Id']) self.void_responder(data, item) def GetIntros(self, server, data, *args, **kwargs): item = server['api'].get_intros(data['Id']) self.void_responder(data, item) def GetImages(self, server, data, *args, **kwargs): item = server['api'].get_images(data['Id']) self.void_responder(data, item) def GetServerAddress(self, server, data, *args, **kwargs): server_address = server['auth/server-address'] self.void_responder(data, server_address) def GetPlaybackInfo(self, server, data, *args, **kwargs): sources = server['api'].get_play_info(data['Id'], data['Profile']) self.void_responder(data, sources) def GetLiveStream(self, server, data, *args, **kwargs): sources = server['api'].get_live_stream(data['Id'], data['PlaySessionId'], data['Token'], data['Profile']) self.void_responder(data, sources) def GetToken(self, server, data, *args, **kwargs): token = server['auth/token'] self.void_responder(data, token) def GetSession(self, server, data, *args, **kwargs): session = server['api'].get_device(self.device_id) self.void_responder(data, session) def GetUsers(self, server, data, *args, **kwargs): users = server['api'].get_users(data.get('IsDisabled', True), data.get('IsHidden', True)) self.void_responder(data, users) def GetTranscodeOptions(self, server, data, *args, **kwargs): result = server['api'].get_transcode_settings() self.void_responder(data, result) def GetThemes(self, server, data, *args, **kwargs): if data['Type'] == 'Video': theme = server['api'].get_items_theme_video(data['Id']) else: theme = server['api'].get_items_theme_song(data['Id']) self.void_responder(data, theme) def GetTheme(self, server, data, *args, **kwargs): theme = server['api'].get_themes(data['Id']) self.void_responder(data, theme) def Browse(self, server, data, *args, **kwargs): result = downloader.get_filtered_section(data.get('Id'), data.get('Media'), data.get('Limit'), data.get('Recursive'), data.get('Sort'), data.get('SortOrder'), data.get('Filters'), data.get('Params'), data.get('ServerId')) self.void_responder(data, result) def BrowseSeason(self, server, data, *args, **kwargs): result = server['api'].get_seasons(data['Id']) self.void_responder(data, result) def LiveTV(self, server, data, *args, **kwargs): result = server['api'].get_channels() self.void_responder(data, result) def RecentlyAdded(self, server, data, *args, **kwargs): result = server['api'].get_recently_added(data.get('Media'), data.get('Id'), data.get('Limit')) self.void_responder(data, result) def Genres(self, server, data, *args, **kwargs): result = server['api'].get_genres(data.get('Id')) self.void_responder(data, result) def Recommended(self, server, data, *args, **kwargs): result = server['api'].get_recommendation(data.get('Id'), data.get('Limit')) self.void_responder(data, result) def RefreshItem(self, server, data, *args, **kwargs): server['api'].refresh_item(data['Id']) def FavoriteItem(self, server, data, *args, **kwargs): server['api'].favorite(data['Id'], data['Favorite']) def DeleteItem(self, server, data, *args, **kwargs): server['api'].delete_item(data['Id']) def PlayPlaylist(self, server, data, *args, **kwargs): server['api'].post_session(server['config/app.session'], "Playing", { 'PlayCommand': "PlayNow", 'ItemIds': data['Id'], 'StartPositionTicks': 0 }) def Play(self, server, data, *args, **kwargs): items = server['api'].get_items(data['ItemIds']) PlaylistWorker(data.get('ServerId'), items, data['PlayCommand'] == 'PlayNow', data.get('StartPositionTicks', 0), data.get('AudioStreamIndex'), data.get('SubtitleStreamIndex')).start() def Player_OnAVChange(self, *args, **kwargs): self.ReportProgressRequested(*args, **kwargs) def ReportProgressRequested(self, server, data, *args, **kwargs): self.player.report_playback(data.get('Report', True)) def Playstate(self, server, data, *args, **kwargs): ''' Emby playstate updates. ''' command = data['Command'] actions = { 'Stop': self.player.stop, 'Unpause': self.player.pause, 'Pause': self.player.pause, 'PlayPause': self.player.pause, 'NextTrack': self.player.playnext, 'PreviousTrack': self.player.playprevious } if command == 'Seek': if self.player.isPlaying(): seektime = data['SeekPositionTicks'] / 10000000.0 self.player.seekTime(seektime) LOG.info("[ seek/%s ]", seektime) elif command in actions: actions[command]() LOG.info("[ command/%s ]", command) def GeneralCommand(self, server, data, *args, **kwargs): ''' General commands from Emby to control the Kodi interface. ''' command = data['Name'] args = data['Arguments'] if command in ('Mute', 'Unmute', 'SetVolume', 'SetSubtitleStreamIndex', 'SetAudioStreamIndex', 'SetRepeatMode'): if command == 'Mute': xbmc.executebuiltin('Mute') elif command == 'Unmute': xbmc.executebuiltin('Mute') elif command == 'SetVolume': xbmc.executebuiltin('SetVolume(%s[,showvolumebar])' % args['Volume']) elif command == 'SetRepeatMode': xbmc.executebuiltin('xbmc.PlayerControl(%s)' % args['RepeatMode']) elif command == 'SetAudioStreamIndex': self.player.set_audio_subs(args['Index']) elif command == 'SetSubtitleStreamIndex': self.player.set_audio_subs(None, args['Index']) self.player.report_playback() elif command == 'DisplayMessage': dialog("notification", heading=args['Header'], message=args['Text'], icon="{emby}", time=int(settings('displayMessage'))*1000) elif command == 'SendString': JSONRPC('Input.SendText').execute({'text': args['String'], 'done': False}) elif command == 'GoHome': JSONRPC('GUI.ActivateWindow').execute({'window': "home"}) elif command == 'Guide': JSONRPC('GUI.ActivateWindow').execute({'window': "tvguide"}) elif command in ('MoveUp', 'MoveDown', 'MoveRight', 'MoveLeft'): actions = { 'MoveUp': "Input.Up", 'MoveDown': "Input.Down", 'MoveRight': "Input.Right", 'MoveLeft': "Input.Left" } JSONRPC(actions[command]).execute() 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)', } if command in builtin: xbmc.executebuiltin(builtin[command]) def LoadServer(self, server, data, *args, **kwargs): self.server_instance(data['ServerId']) def AddUser(self, server, data, *args, **kwargs): server['api'].session_add_user(server['config/app.session'], data['Id'], data['Add']) self.additional_users(server) def Player_OnPlay(self, server, data, *args, **kwargs): on_play(data, server) def Player_OnStop(self, *args, **kwargs): ''' We have to clear the playlist if it was stopped before it has been played completely. Otherwise the next played item will be added the previous queue. Let's wait for the player so we don't clear the canceled playlist by mistake. ''' xbmc.sleep(3000) if not self.player.isPlaying() and xbmcgui.getCurrentWindowId() not in [12005, 10138]: xbmc.PlayList(xbmc.PLAYLIST_VIDEO).clear() def Playlist_OnClear(self, server, data, *args, **kwargs): ''' Widgets do not truly clear the playlist. ''' if xbmc.PlayList(xbmc.PLAYLIST_VIDEO).size(): window('emby_playlistclear.bool', True) self.player.stop_playback() def VideoLibrary_OnUpdate(self, server, data, *args, **kwargs): on_update(data, server)