コード例 #1
0
    def __init__(self, method, data):

        ''' If you call get, this will block until response is received.
            This is used to communicate between entrypoints.
        '''
        if type(data) != dict:
            raise Exception("unexpected data format")

        data['VoidName'] = str(create_id())
        LOG.info("---[ contact MU-TH-UR 6000/%s ]", method)
        LOG.debug(data)

        event(method, data)
        self.method = method
        self.data = data
コード例 #2
0
    def service(self):
        ''' Keeps the service monitor going.
            Exit on Kodi shutdown or profile switch.

            if profile switch happens more than once, 
            Threads depending on abortRequest will not trigger.
        '''
        self.monitor = monitor.Monitor()
        player = self.monitor.player
        self.connect = connect.Connect()
        self.start_default()

        self.settings['mode'] = settings('useDirectPaths')

        while self.running:
            if window('emby_online.bool'):

                if self.settings['profile'] != window('emby_kodiProfile'):
                    LOG.info("[ profile switch ] %s", self.settings['profile'])

                    break

                if player.isPlaying() and player.is_playing_file(
                        player.get_playing_file()):
                    difference = datetime.today(
                    ) - self.settings['last_progress']

                    if difference.seconds > 10:
                        self.settings['last_progress'] = datetime.today()

                        update = (datetime.today() -
                                  self.settings['last_progress_report']
                                  ).seconds > 250
                        event('ReportProgressRequested', {'Report': update})

                        if update:
                            self.settings[
                                'last_progress_report'] = datetime.today()

            if window('emby.restart.bool'):
                window('emby.restart', clear=True)

                raise Exception('RestartService')

            if self.waitForAbort(1):
                break

        self.shutdown()
コード例 #3
0
    def next_up(self):

        item = self.get_file_info(self.get_playing_file())
        objects = Objects()

        if item['Type'] != 'Episode' or not item.get('CurrentEpisode'):
            return

        next_items = item['Server'].jellyfin.get_adjacent_episodes(
            item['CurrentEpisode']['tvshowid'], item['Id'])

        for index, next_item in enumerate(next_items['Items']):
            if next_item['Id'] == item['Id']:

                try:
                    next_item = next_items['Items'][index + 1]
                except IndexError:
                    LOG.warning("No next up episode.")

                    return

                break
        server_address = item['Server'].auth.get_server_info(
            item['Server'].auth.server_id)['address']
        API = api.API(next_item, server_address)
        data = objects.map(next_item, "UpNext")
        artwork = API.get_all_artwork(objects.map(next_item, 'ArtworkParent'),
                                      True)
        data['art'] = {
            'tvshow.poster': artwork.get('Series.Primary'),
            'tvshow.fanart': None,
            'thumb': artwork.get('Primary')
        }
        if artwork['Backdrop']:
            data['art']['tvshow.fanart'] = artwork['Backdrop'][0]

        next_info = {
            'play_info': {
                'ItemIds': [data['episodeid']],
                'ServerId': item['ServerId'],
                'PlayCommand': 'PlayNow'
            },
            'current_episode': item['CurrentEpisode'],
            'next_episode': data
        }

        LOG.info("--[ next up ] %s", next_info)
        event("upnext_data", next_info, hexlify=True)
コード例 #4
0
    def delete_item(self):
        delete = True

        if not settings('skipContextMenu.bool'):

            if not dialog("yesno", heading="{emby}", line1=_(33015)):
                delete = False

        if delete:

            self.server['api'].delete_item(self.item['Id'])
            event(
                "LibraryChanged", {
                    'ItemsRemoved': [self.item['Id']],
                    'ItemsVerify': [self.item['Id']],
                    'ItemsUpdated': [],
                    'ItemsAdded': []
                })
コード例 #5
0
ファイル: views.py プロジェクト: scottwedge/jellyfin-kodi
    def get_views(self):
        ''' Get the media folders. Add or remove them. Do not proceed if issue getting libraries.
        '''
        media = {
            'movies': "Movie",
            'tvshows': "Series",
            'musicvideos': "MusicVideo"
        }

        try:
            libraries = self.get_libraries()
        except IndexError as error:
            LOG.exception(error)

            return

        self.sync['SortedViews'] = [x['Id'] for x in libraries]

        for library in libraries:

            if library['Type'] == 'Channel':
                library['Media'] = "channels"
            else:
                library['Media'] = library.get(
                    'OriginalCollectionType',
                    library.get('CollectionType', "mixed"))

            self.add_library(library)

        with Database('jellyfin') as jellyfindb:

            views = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views()
            removed = []

            for view in views:

                if view[0] not in self.sync['SortedViews']:
                    removed.append(view[0])

            if removed:
                event('RemoveLibrary', {'Id': ','.join(removed)})

        save_sync(self.sync)
コード例 #6
0
ファイル: default.py プロジェクト: woniu798/jellyfin-kodi
def add_user(api_client):
    ''' Add or remove users from the default server session.
    '''
    if not window('jellyfin_online.bool'):
        return

    session = api_client.get_device(client.get_device_id())
    users = api_client.get_users()
    current = session[0]['AdditionalUsers']

    result = dialog("select", translate(33061),
                    [translate(33062), translate(33063)]
                    if current else [translate(33062)])

    if result < 0:
        return

    if not result:  # Add user
        eligible = [
            x for x in users if x['Id'] not in
            [current_user['UserId'] for current_user in current]
        ]
        resp = dialog("select", translate(33064),
                      [x['Name'] for x in eligible])

        if resp < 0:
            return

        user = eligible[resp]
        event('AddUser', {'Id': user['Id'], 'Add': True})
    else:  # Remove user
        resp = dialog("select", translate(33064),
                      [x['UserName'] for x in current])

        if resp < 0:
            return

        user = current[resp]
        event('AddUser', {'Id': user['UserId'], 'Add': False})
コード例 #7
0
ファイル: connect.py プロジェクト: macearl/jellyfin-kodi
    def register_client(self, credentials=None, options=None, server_id=None, server_selection=False):

        client = self.get_client(server_id)
        self.client = client
        self.connect_manager = client.auth

        if server_id is None:
            client.config.data['app.default'] = True

        try:
            state = client.authenticate(credentials or {}, options or {})

            if state['State'] == CONNECTION_STATE['SignedIn']:
                client.callback_ws = event

                if server_id is None:  # Only assign for default server

                    client.callback = event
                    self.get_user(client)

                    settings('serverName', client.config.data['auth.server-name'])
                    settings('server', client.config.data['auth.server'])

                event('ServerOnline', {'ServerId': server_id})
                event('LoadServer', {'ServerId': server_id})

                return state['Credentials']

            elif (server_selection or state['State'] == CONNECTION_STATE['ServerSelection'] or state['State'] == CONNECTION_STATE['Unavailable'] and not settings('SyncInstallRunDone.bool')):

                self.select_servers(state)

            elif state['State'] == CONNECTION_STATE['ServerSignIn']:
                if 'ExchangeToken' not in state['Servers'][0]:
                    self.login()

            elif state['State'] == CONNECTION_STATE['Unavailable'] and state['Status_Code'] == 401:
                # If the saved credentials don't work, restart the addon to force the password dialog to open
                window('jellyfin.restart', clear=True)

            elif state['State'] == CONNECTION_STATE['Unavailable']:
                raise HTTPException('ServerUnreachable', {})

            return self.register_client(state['Credentials'], options, server_id, False)

        except RuntimeError as error:

            LOG.exception(error)
            xbmc.executebuiltin('Addon.OpenSettings(%s)' % addon_id())

            raise Exception('User sign in interrupted')

        except HTTPException as error:

            if error.status == 'ServerUnreachable':
                event('ServerUnreachable', {'ServerId': server_id})

            return client.get_credentials()
コード例 #8
0
    def server_instance(self, server_id=None):

        server = Emby(server_id).get_client()
        self.post_capabilities(server)

        if server_id is not None:
            self.servers.append(server_id)
        elif settings('addUsers'):

            users = settings('addUsers').split(',')
            hidden = None if settings('addUsersHidden.bool') else False
            all_users = server['api'].get_users(hidden=hidden)

            for additional in users:
                for user in all_users:

                    if user['Id'] == additional:
                        server['api'].session_add_user(
                            server['config/app.session'], user['Id'])

            self.additional_users(server)

        event('ServerOnline', {'ServerId': server_id})
コード例 #9
0
def add_user():
    ''' Add or remove users from the default server session.
    '''
    if not window('jellyfin_online.bool'):
        return

    session = TheVoid('GetSession', {}).get()
    users = TheVoid('GetUsers', {'IsDisabled': False, 'IsHidden': False}).get()
    current = session[0]['AdditionalUsers']

    result = dialog("select", _(33061),
                    [_(33062), _(33063)] if current else [_(33062)])

    if result < 0:
        return

    if not result:  # Add user
        eligible = [
            x for x in users if x['Id'] not in
            [current_user['UserId'] for current_user in current]
        ]
        resp = dialog("select", _(33064), [x['Name'] for x in eligible])

        if resp < 0:
            return

        user = eligible[resp]
        event('AddUser', {'Id': user['Id'], 'Add': True})
    else:  # Remove user
        resp = dialog("select", _(33064), [x['UserName'] for x in current])

        if resp < 0:
            return

        user = current[resp]
        event('AddUser', {'Id': user['UserId'], 'Add': False})
コード例 #10
0
ファイル: views.py プロジェクト: Astate/jellyfin-kodi
    def get_views(self):
        ''' Get the media folders. Add or remove them.
        '''
        media = {
            'movies': "Movie",
            'tvshows': "Series",
            'musicvideos': "MusicVideo"
        }
        libraries = self.get_libraries()
        self.sync['SortedViews'] = [x['Id'] for x in libraries]

        for library in libraries:

            if library['Type'] == 'Channel':
                library['Media'] = "channels"
            else:
                library['Media'] = library.get(
                    'OriginalCollectionType',
                    library.get('CollectionType', "mixed"))

            self.add_library(library)

        with Database('emby') as embydb:

            views = emby_db.EmbyDatabase(embydb.cursor).get_views()
            removed = []

            for view in views:

                if view[0] not in self.sync['SortedViews']:
                    removed.append(view[0])

            if removed:
                event('RemoveLibrary', {'Id': ','.join(removed)})

        save_sync(self.sync)
コード例 #11
0
ファイル: default.py プロジェクト: woniu798/jellyfin-kodi
    def __init__(self):
        ''' Parse the parameters. Reroute to our service.py
            where user is fully identified already.
        '''
        base_url = ADDON_BASE_URL
        path = QUERY_STRING

        try:
            params = dict(parse_qsl(path[1:]))
        except Exception:
            params = {}

        mode = params.get('mode')
        server = params.get('server')

        if server == 'None':
            server = None

        jellyfin_client = Jellyfin(server).get_client()
        api_client = jellyfin_client.jellyfin

        addon_data = xbmc.translatePath(
            "special://profile/addon_data/plugin.video.jellyfin/data.json")
        try:
            with open(addon_data, 'rb') as infile:
                data = json.load(infile)

            server_data = data['Servers'][0]
            api_client.config.data['auth.server'] = server_data.get('address')
            api_client.config.data['auth.server-name'] = server_data.get(
                'Name')
            api_client.config.data['auth.user_id'] = server_data.get('UserId')
            api_client.config.data['auth.token'] = server_data.get(
                'AccessToken')
        except Exception as e:
            LOG.warning('Addon appears to not be configured yet: {}'.format(e))

        LOG.info("path: %s params: %s", path, JsonDebugPrinter(params))

        if '/extrafanart' in base_url:

            jellyfin_path = path[1:]
            jellyfin_id = params.get('id')
            get_fanart(jellyfin_id, jellyfin_path, server, api_client)

        elif '/Extras' in base_url or '/VideoFiles' in base_url:

            jellyfin_path = path[1:]
            jellyfin_id = params.get('id')
            get_video_extras(jellyfin_id, jellyfin_path, server, api_client)

        elif mode == 'play':

            item = api_client.get_item(params['id'])
            item["resumePlayback"] = sys.argv[3].split(":")[1] == "true"
            Actions(server,
                    api_client).play(item,
                                     params.get('dbid'),
                                     params.get('transcode') == 'true',
                                     playlist=params.get('playlist') == 'true')

        elif mode == 'playlist':
            api_client.post_session(
                api_client.config.data['app.session'], "Playing", {
                    'PlayCommand': "PlayNow",
                    'ItemIds': params['id'],
                    'StartPositionTicks': 0
                })
        elif mode == 'deviceid':
            client.reset_device_id()
        elif mode == 'reset':
            reset()
        elif mode == 'delete':
            delete_item()
        elif mode == 'refreshboxsets':
            event('SyncLibrary', {'Id': "Boxsets:Refresh"})
        elif mode == 'nextepisodes':
            get_next_episodes(params['id'], params['limit'])
        elif mode == 'browse':
            browse(params.get('type'), params.get('id'), params.get('folder'),
                   server, api_client)
        elif mode == 'synclib':
            event('SyncLibrary', {'Id': params.get('id')})
        elif mode == 'updatelib':
            event('SyncLibrary', {'Id': params.get('id'), 'Update': True})
        elif mode == 'repairlib':
            event('RepairLibrary', {'Id': params.get('id')})
        elif mode == 'removelib':
            event('RemoveLibrary', {'Id': params.get('id')})
        elif mode == 'repairlibs':
            event('RepairLibrarySelection')
        elif mode == 'updatelibs':
            event('SyncLibrarySelection')
        elif mode == 'removelibs':
            event('RemoveLibrarySelection')
        elif mode == 'addlibs':
            event('AddLibrarySelection')
        elif mode == 'addserver':
            event('AddServer')
        elif mode == 'login':
            event('ServerConnect', {'Id': server})
        elif mode == 'removeserver':
            event('RemoveServer', {'Id': server})
        elif mode == 'settings':
            xbmc.executebuiltin('Addon.OpenSettings(plugin.video.jellyfin)')
        elif mode == 'adduser':
            add_user(api_client)
        elif mode == 'updatepassword':
            event('UpdatePassword')
        elif mode == 'thememedia':
            get_themes(api_client)
        elif mode == 'managelibs':
            manage_libraries()
        elif mode == 'backup':
            backup()
        elif mode == 'restartservice':
            window('jellyfin.restart.bool', True)
        else:
            listing()
コード例 #12
0
    def __init__(self):
        ''' Parse the parameters. Reroute to our service.py
            where user is fully identified already.
        '''
        base_url = sys.argv[0]
        path = sys.argv[2]

        try:
            params = dict(urlparse.parse_qsl(path[1:]))
        except Exception:
            params = {}

        mode = params.get('mode')
        server = params.get('server')

        if server == 'None':
            server = None

        LOG.warn("path: %s params: %s", path, json.dumps(params, indent=4))

        if '/extrafanart' in base_url:

            jellyfin_path = path[1:]
            jellyfin_id = params.get('id')
            get_fanart(jellyfin_id, jellyfin_path, server)

        elif '/Extras' in base_url or '/VideoFiles' in base_url:

            jellyfin_path = path[1:]
            jellyfin_id = params.get('id')
            get_video_extras(jellyfin_id, jellyfin_path, server)

        elif mode == 'play':

            item = TheVoid('GetItem', {
                'Id': params['id'],
                'ServerId': server
            }).get()
            Actions(server).play(item,
                                 params.get('dbid'),
                                 params.get('transcode') == 'true',
                                 playlist=params.get('playlist') == 'true')

        elif mode == 'playlist':
            event('PlayPlaylist', {'Id': params['id'], 'ServerId': server})
        elif mode == 'deviceid':
            client.reset_device_id()
        elif mode == 'reset':
            reset()
        elif mode == 'delete':
            delete_item()
        elif mode == 'refreshboxsets':
            event('SyncLibrary', {'Id': "Boxsets:Refresh"})
        elif mode == 'nextepisodes':
            get_next_episodes(params['id'], params['limit'])
        elif mode == 'browse':
            browse(params.get('type'), params.get('id'), params.get('folder'),
                   server)
        elif mode == 'synclib':
            event('SyncLibrary', {'Id': params.get('id')})
        elif mode == 'updatelib':
            event('SyncLibrary', {'Id': params.get('id'), 'Update': True})
        elif mode == 'repairlib':
            event('RepairLibrary', {'Id': params.get('id')})
        elif mode == 'removelib':
            event('RemoveLibrary', {'Id': params.get('id')})
        elif mode == 'repairlibs':
            event('RepairLibrarySelection')
        elif mode == 'updatelibs':
            event('SyncLibrarySelection')
        elif mode == 'removelibs':
            event('RemoveLibrarySelection')
        elif mode == 'addlibs':
            event('AddLibrarySelection')
        elif mode == 'addserver':
            event('AddServer')
        elif mode == 'login':
            event('ServerConnect', {'Id': server})
        elif mode == 'removeserver':
            event('RemoveServer', {'Id': server})
        elif mode == 'settings':
            xbmc.executebuiltin('Addon.OpenSettings(plugin.video.jellyfin)')
        elif mode == 'adduser':
            add_user()
        elif mode == 'updateserver':
            event('UpdateServer')
        elif mode == 'thememedia':
            get_themes()
        elif mode == 'managelibs':
            manage_libraries()
        elif mode == 'backup':
            backup()
        elif mode == 'restartservice':
            window('jellyfin.restart.bool', True)
        else:
            listing()
コード例 #13
0
ファイル: library.py プロジェクト: burnes82/jellyfin-kodi
    def select_libraries(self, mode=None):
        ''' Select from libraries synced. Either update or repair libraries.
            Send event back to service.py
        '''
        modes = {
            'SyncLibrarySelection': 'SyncLibrary',
            'RepairLibrarySelection': 'RepairLibrary',
            'AddLibrarySelection': 'SyncLibrary',
            'RemoveLibrarySelection': 'RemoveLibrary'
        }
        sync = get_sync()
        whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']]
        libraries = []

        with Database('jellyfin') as jellyfindb:
            db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor)

            if mode in ('SyncLibrarySelection', 'RepairLibrarySelection',
                        'RemoveLibrarySelection'):
                for library in sync['Whitelist']:

                    name = db.get_view_name(library.replace('Mixed:', ""))
                    libraries.append({'Id': library, 'Name': name})
            else:
                available = [
                    x for x in sync['SortedViews'] if x not in whitelist
                ]

                for library in available:
                    name, media = db.get_view(library)

                    if media in ('movies', 'tvshows', 'musicvideos', 'mixed',
                                 'music'):
                        libraries.append({'Id': library, 'Name': name})

        choices = [x['Name'] for x in libraries]
        choices.insert(0, translate(33121))

        titles = {
            "RepairLibrarySelection": 33199,
            "SyncLibrarySelection": 33198,
            "RemoveLibrarySelection": 33200,
            "AddLibrarySelection": 33120
        }
        title = titles.get(mode, "Failed to get title {}".format(mode))

        selection = dialog("multi", translate(title), choices)

        if selection is None:
            return

        if 0 in selection:
            selection = list(range(1, len(libraries) + 1))

        selected_libraries = []

        for x in selection:

            library = libraries[x - 1]
            selected_libraries.append(library['Id'])

        event(
            modes[mode], {
                'Id': ','.join([libraries[x - 1]['Id'] for x in selection]),
                'Update': mode == 'SyncLibrarySelection'
            })
コード例 #14
0
    def __init__(self):
        global CONTENT_TYPE
        ''' Parse the parameters. Reroute to our service.py
            where user is fully identified already.
        '''
        base_url = sys.argv[0]
        path = sys.argv[2]

        try:
            params = dict(urlparse.parse_qsl(path[1:]))
        except Exception:
            params = {}

        if 'content_type' in params:

            window('emby.plugin.content.type', params['content_type'])
            CONTENT_TYPE = params['content_type']
        else:
            CONTENT_TYPE = window('emby.plugin.content.type') or None

        mode = params.get('mode')
        server = params.get('server')

        if server == 'None' or not server:
            server = None

        LOG.warn("path: %s params: %s", path, json.dumps(params, indent=4))

        if '/extrafanart' in base_url:

            emby_path = path[1:]
            emby_id = params.get('id')
            get_fanart(emby_id, emby_path, server)

        elif '/Extras' in base_url or '/VideoFiles' in base_url:

            emby_path = path[1:]
            emby_id = params.get('id')
            get_video_extras(emby_id, emby_path, server)

        elif mode == 'play':

            window('emby.sync.pause.bool', True)
            window('emby.playlist.plugin.bool', True)

            try:
                objects.PlayPlugin(params, server).play('trailer' in base_url)
            except Exception as error:
                LOG.exception(error)

                if not xbmc.Player().isPlaying():
                    xbmc.Player().stop()

                xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xbmcgui.ListItem())

            window('emby.sync.pause.bool', clear=True)
            window('emby.playlist.plugin', clear=True)

        elif mode =='playstrm':

            window('emby.sync.pause.bool', True)
            window('emby.playlist.plugin.bool', True)

            while not window('emby.playlist.play.bool'):
                xbmc.sleep(50)

                if window('emby.playlist.aborted.bool'):
                    LOG.warn("[ playback aborted ]")

                    break
            else:
                LOG.info("[ playback started ]")
                xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xbmcgui.ListItem())

            window('emby.playlist.aborted', clear=True)
            window('emby.sync.pause', clear=True)
            window('emby.playlist.plugin', clear=True)

        elif mode == 'playsingle':

            window('emby.sync.pause.bool', True)
            window('emby.playlist.plugin.bool', True)

            try:
                objects.PlaySingle(params, server).play()
            except Exception as error:
                LOG.exception(error)

                if not xbmc.Player().isPlaying():
                    xbmc.Player().stop()

                xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xbmcgui.ListItem())

            window('emby.sync.pause', clear=True)
            window('emby.playlist.plugin', clear=True)

        elif mode == 'playlist':
            event('PlayPlaylist', {'Id': params['id'], 'ServerId': server})
        elif mode == 'photoviewer':
            xbmc.executebuiltin('ShowPicture(%s/emby/Items/%s/Images/Primary)' % (Emby(server)['auth/server-address'], params['id']))
        elif mode == 'deviceid':
            client.reset_device_id()
        elif mode == 'reset':
            reset()
        elif mode == 'delete':
            delete_item()
        elif mode == 'refreshboxsets':
            event('SyncLibrary', {'Id': "Boxsets:Refresh"})
        elif mode == 'nextepisodes':
            get_next_episodes(params['id'], params['limit'])
        elif mode == 'browse':
            browse(params.get('type'), params.get('id'), params.get('folder'), server)
        elif mode == 'synclib':
            event('SyncLibrary', {'Id': params.get('id')})
        elif mode == 'updatelib':
            event('SyncLibrary', {'Id': params.get('id'), 'Update': True})
        elif mode == 'repairlib':
            event('RepairLibrary', {'Id': params.get('id')})
        elif mode == 'removelib':
            event('RemoveLibrary', {'Id': params.get('id')})
        elif mode == 'repairlibs':
            event('RepairLibrarySelection')
        elif mode == 'updatelibs':
            event('SyncLibrarySelection')
        elif mode == 'removelibs':
            event('RemoveLibrarySelection')
        elif mode == 'addlibs':
            event('AddLibrarySelection')
        elif mode == 'connect':
            event('EmbyConnect')
        elif mode == 'addserver':
            event('AddServer')
        elif mode == 'login':
            event('ServerConnect', {'Id': server})
        elif mode == 'removeserver':
            event('RemoveServer', {'Id': server})
        elif mode == 'settings':
            xbmc.executebuiltin('Addon.OpenSettings(plugin.video.emby)')
        elif mode == 'adduser':
            add_user(params.get('permanent') == 'true')
        elif mode == 'checkupdate':
            event('CheckUpdate')
        elif mode == 'resetupdate':
            event('ResetUpdate')
        elif mode == 'updateserver':
            event('UpdateServer')
        elif mode == 'thememedia':
            get_themes()
        elif mode == 'managelibs':
            manage_libraries()
        elif mode == 'texturecache':
            cache_artwork()
        elif mode == 'backup':
            backup()
        elif mode == 'restartservice':
            window('emby.restart.bool', True)
        elif mode == 'patchmusic':
            event('PatchMusic', {'Notification': True})
        elif mode == 'changelog':
            changelog()
        elif mode == 'setssl':
            event('SetServerSSL', {'Id': server})
        else:
            listing()
コード例 #15
0
    def stop_playback(self):
        ''' Stop all playback. Check for external player for positionticks.
            Immediately force an internal update for the item to remove the visual delay waiting on the callback from server.
        '''
        LOG.debug("[ played info ] %s", self.played)

        for file in self.played:

            try:
                item = self.get_file_info(file)

                if not item['Track']:
                    LOG.info("[ skip stop ] %s", file)

                    continue

                LOG.info("[ played info ] %s", item)
                item['Track'] = False
                self.played[file] = item
                window('emby.skip.%s.bool' % item['Id'], True)

                if window('emby.external.bool'):
                    window('emby.external', clear=True)

                    if int(item['CurrentPosition']) == 1:
                        item['CurrentPosition'] = int(item['Runtime'])

                data = {
                    'ItemId': item['Id'],
                    'MediaSourceId': item['MediaSourceId'],
                    'PositionTicks': int(item['CurrentPosition'] * 10000000),
                    'PlaySessionId': item['PlaySessionId']
                }
                item['Server']['api'].session_stop(data)
                event(
                    "LibraryChanged", {
                        'ItemsRemoved': [],
                        'ItemsVerify': [],
                        'ItemsUpdated': [item['Id']],
                        'ItemsAdded': []
                    })

                if item.get('LiveStreamId'):

                    LOG.info("<[ livestream/%s ]", item['LiveStreamId'])
                    item['Server']['api'].close_live_stream(
                        item['LiveStreamId'])

                elif item['PlayMethod'] == 'Transcode':

                    LOG.info("<[ transcode/%s ]", item['Id'])
                    item['Server']['api'].close_transcode(item['DeviceId'])

                path = xbmc.translatePath(
                    "special://profile/addon_data/plugin.video.emby/temp/"
                ).decode('utf-8')

                if xbmcvfs.exists(path):
                    dirs, files = xbmcvfs.listdir(path)

                    for file in files:
                        xbmcvfs.delete(os.path.join(path,
                                                    file.decode('utf-8')))

                result = item['Server']['api'].get_item(item['Id']) or {}

                if 'UserData' in result and result['UserData']['Played']:
                    delete = False

                    if result['Type'] == 'Episode' and settings(
                            'deleteTV.bool'):
                        delete = True
                    elif result['Type'] == 'Movie' and settings(
                            'deleteMovies.bool'):
                        delete = True

                    if not settings('offerDelete.bool'):
                        delete = False

                    if delete:
                        LOG.info("Offer delete option")

                        if dialog("yesno",
                                  heading=_(30091),
                                  line1=_(33015),
                                  autoclose=120000):
                            item['Server']['api'].delete_item(item['Id'])
                            event(
                                "LibraryChanged", {
                                    'ItemsRemoved': [item['Id']],
                                    'ItemsVerify': [item['Id']],
                                    'ItemsUpdated': [],
                                    'ItemsAdded': []
                                })

            except Exception as error:
                LOG.error(error)

        window('emby.play.reset', clear=True)
        window('emby.external_check', clear=True)
        window('emby.sync.pause', clear=True)
コード例 #16
0
ファイル: default.py プロジェクト: sualfred/plugin.video.emby
    def __init__(self):

        ''' Parse the parameters. Reroute to our service.py
            where user is fully identified already.
        '''
        base_url = sys.argv[0]
        path = sys.argv[2]

        try:
            params = dict(urlparse.parse_qsl(path[1:]))
        except Exception:
            params = {}

        mode = params.get('mode')
        server = params.get('server')

        if server == 'None':
            server = None

        LOG.warn("path: %s params: %s", path, json.dumps(params, indent=4))

        if '/extrafanart' in base_url:

            emby_path = path[1:]
            emby_id = params.get('id')
            get_fanart(emby_id, emby_path, server)

        elif '/Extras' in base_url or '/VideoFiles' in base_url:

            emby_path = path[1:]
            emby_id = params.get('id')
            get_video_extras(emby_id, emby_path, server)

        elif mode == 'play':

            item = TheVoid('GetItem', {'Id': params['id'], 'ServerId': server}).get()
            Actions(server).play(item, params.get('dbid'), params.get('transcode') == 'true', playlist=params.get('playlist') == 'true')

        elif mode =='playstrm':

            while not window('emby.playlist.play.bool'):
                xbmc.sleep(50)

                if window('emby.playlist.aborted.bool'):
                    LOG.info("[ playback aborted ]")

                    break
            else:
                LOG.info("[ playback started ]")
                xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xbmcgui.ListItem())

            window('emby.playlist.aborted', clear=True)

        elif mode == 'playsimple':
            from helper import playsimple

            playsimple.PlaySimple(params, server).play()

        elif mode == 'playlist':
            event('PlayPlaylist', {'Id': params['id'], 'ServerId': server})
        elif mode == 'deviceid':
            client.reset_device_id()
        elif mode == 'reset':
            reset()
        elif mode == 'delete':
            delete_item()
        elif mode == 'refreshboxsets':
            event('SyncLibrary', {'Id': "Boxsets:Refresh"})
        elif mode == 'nextepisodes':
            get_next_episodes(params['id'], params['limit'])
        elif mode == 'browse':
            browse(params.get('type'), params.get('id'), params.get('folder'), server)
        elif mode == 'synclib':
            event('SyncLibrary', {'Id': params.get('id')})
        elif mode == 'updatelib':
            event('SyncLibrary', {'Id': params.get('id'), 'Update': True})
        elif mode == 'repairlib':
            event('RepairLibrary', {'Id': params.get('id')})
        elif mode == 'removelib':
            event('RemoveLibrary', {'Id': params.get('id')})
        elif mode == 'repairlibs':
            event('RepairLibrarySelection')
        elif mode == 'updatelibs':
            event('SyncLibrarySelection')
        elif mode == 'removelibs':
            event('RemoveLibrarySelection')
        elif mode == 'addlibs':
            event('AddLibrarySelection')
        elif mode == 'connect':
            event('EmbyConnect')
        elif mode == 'addserver':
            event('AddServer')
        elif mode == 'login':
            event('ServerConnect', {'Id': server})
        elif mode == 'removeserver':
            event('RemoveServer', {'Id': server})
        elif mode == 'settings':
            xbmc.executebuiltin('Addon.OpenSettings(plugin.video.emby)')
        elif mode == 'adduser':
            add_user(params.get('permanent') == 'true')
        elif mode == 'checkupdate':
            event('CheckUpdate')
        elif mode == 'updateserver':
            event('UpdateServer')
        elif mode == 'thememedia':
            get_themes()
        elif mode == 'managelibs':
            manage_libraries()
        elif mode == 'texturecache':
            cache_artwork()
        elif mode == 'backup':
            backup()
        elif mode == 'restartservice':
            window('emby.restart.bool', True)
        elif mode == 'patchmusic':
            event('PatchMusic', {'Notification': True})
        else:
            listing()
コード例 #17
0
ファイル: default.py プロジェクト: sualfred/plugin.video.emby
def add_user(permanent=False):

    ''' Add or remove users from the default server session.
        permanent=True from the add-on settings.
    '''
    if not window('emby_online.bool'):
        return

    session = TheVoid('GetSession', {}).get()
    users = TheVoid('GetUsers', {'IsDisabled': False, 'IsHidden': False}).get()

    for user in users:

        if user['Id'] == session[0]['UserId']:
            users.remove(user)

            break

    while True:

        session = TheVoid('GetSession', {}).get()
        additional = current = session[0]['AdditionalUsers']
        add_session = True

        if permanent:

            perm_users = settings('addUsers').split(',') if settings('addUsers') else []
            current = []

            for user in users:
                for perm_user in perm_users:

                    if user['Id'] == perm_user:
                        current.append({'UserName': user['Name'], 'UserId': user['Id']})

        result = dialog("select", _(33061), [_(33062), _(33063)] if current else [_(33062)])

        if result < 0:
            break

        if not result: # Add user

            eligible = [x for x in users if x['Id'] not in [current_user['UserId'] for current_user in current]]
            resp = dialog("select", _(33064), [x['Name'] for x in eligible])

            if resp < 0:
                break

            user = eligible[resp]

            if permanent:

                perm_users.append(user['Id'])
                settings('addUsers', ','.join(perm_users))

                if user['Id'] in [current_user['UserId'] for current_user in additional]:
                    add_session = False
            
            if add_session:
                event('AddUser', {'Id': user['Id'], 'Add': True})

            dialog("notification", heading="{emby}", message="%s %s" % (_(33067), user['Name']), icon="{emby}", time=1000, sound=False)
        else: # Remove user
            resp = dialog("select", _(33064), [x['UserName'] for x in current])

            if resp < 0:
                break

            user = current[resp]

            if permanent:

                perm_users.remove(user['UserId'])
                settings('addUsers', ','.join(perm_users))
            
            if add_session:
                event('AddUser', {'Id': user['UserId'], 'Add': False})

            dialog("notification", heading="{emby}", message="%s %s" % (_(33066), user['UserName']), icon="{emby}", time=1000, sound=False)
コード例 #18
0
    def service(self):
        ''' Keeps the service monitor going.
            Exit on Kodi shutdown or profile switch.

            if profile switch happens more than once, 
            Threads depending on abortRequest will not trigger.
        '''
        self.monitor = monitor.Monitor()
        player = self.monitor.player
        self.connect = connect.Connect()
        self.start_default()

        self.settings['mode'] = settings('useDirectPaths')

        while self.running:
            if window('emby_online.bool'):

                if self.settings['profile'] != window('emby_kodiProfile'):
                    LOG.info("[ profile switch ] %s", self.settings['profile'])

                    break

                if player.isPlaying() and player.is_playing_file(
                        player.get_playing_file()):
                    difference = datetime.today(
                    ) - self.settings['last_progress']

                    if difference.seconds > 4:
                        self.settings['last_progress'] = datetime.today()

                        update = (datetime.today() -
                                  self.settings['last_progress_report']
                                  ).seconds > 250
                        event('ReportProgressRequested', {'Report': update})

                        if update:
                            self.settings[
                                'last_progress_report'] = datetime.today()

            if self.webservice is not None and not self.webservice.is_alive():

                LOG.info("[ restarting due to socket disconnect ]")
                window('emby.restart.bool', True)

            if window('emby.restart.bool'):

                window('emby.restart', clear=True)
                dialog("notification",
                       heading="{emby}",
                       message=_(33193),
                       icon="{emby}",
                       time=1000,
                       sound=False)

                raise Exception('RestartService')

            if self.waitForAbort(1):
                break

        self.shutdown()

        raise Exception("ExitService")