Beispiel #1
0
    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()
Beispiel #4
0
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])
Beispiel #5
0
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)
Beispiel #7
0
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()
Beispiel #8
0
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)