示例#1
0
    def shutdown(self):

        LOG.info("---<[ EXITING ]")
        window('jellyfin_should_stop.bool', True)

        properties = [  # TODO: review
            "jellyfin_state", "jellyfin_serverStatus", "jellyfin_currUser",
            "jellyfin_play", "jellyfin_online", "jellyfin.connected",
            "jellyfin.resume", "jellyfin_startup", "jellyfin.external",
            "jellyfin.external_check", "jellyfin_deviceId",
            "jellyfin_db_check", "jellyfin_pathverified", "jellyfin_sync"
        ]
        for prop in properties:
            window(prop, clear=True)

        Jellyfin.close_all()

        if self.library_thread is not None:
            self.library_thread.stop_client()

        if self.monitor is not None:

            self.monitor.listener.stop()
            self.monitor.webservice.stop()

        LOG.info("---<<<[ %s ]", client.get_addon_name())
示例#2
0
    def __init__(self, transcode=False, delete=False):

        try:
            self.kodi_id = sys.listitem.getVideoInfoTag().getDbId() or None
            self.media = self.get_media_type()
            self.server_id = sys.listitem.getProperty('jellyfinserver') or None
            self.api_client = Jellyfin(self.server_id).get_client().jellyfin
            item_id = sys.listitem.getProperty('jellyfinid')
        except AttributeError:
            self.server_id = None

            if xbmc.getInfoLabel('ListItem.Property(jellyfinid)'):
                item_id = xbmc.getInfoLabel('ListItem.Property(jellyfinid)')
            else:
                self.kodi_id = xbmc.getInfoLabel('ListItem.DBID')
                self.media = xbmc.getInfoLabel('ListItem.DBTYPE')
                item_id = None

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

        try:
            server_data = data['Servers'][0]
            self.api_client.config.data['auth.server'] = server_data.get(
                'address')
            self.api_client.config.data['auth.server-name'] = server_data.get(
                'Name')
            self.api_client.config.data['auth.user_id'] = server_data.get(
                'UserId')
            self.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))

        if self.server_id or item_id:
            self.item = self.api_client.get_item(item_id)
        else:
            self.item = self.get_item_id()

        if self.item:

            if transcode:
                self.transcode()

            elif delete:
                self.delete_item()

            elif self.select_menu():
                self.action_menu()

                if self._selected_option in (OPTIONS['Delete'],
                                             OPTIONS['AddFav'],
                                             OPTIONS['RemoveFav']):

                    xbmc.sleep(500)
                    xbmc.executebuiltin('Container.Refresh')
示例#3
0
def _http(action, url, request=None, server_id=None):

    if request is None:
        request = {}

    request.update({'url': url, 'type': action})
    return Jellyfin(server_id).http.request(request)
示例#4
0
    def set_item(self, file, item):

        ''' Set playback information.
        '''
        try:
            item['Runtime'] = int(item['Runtime'])
        except (TypeError, ValueError):
            try:
                item['Runtime'] = int(self.getTotalTime())
                LOG.info("Runtime is missing, Kodi runtime: %s" % item['Runtime'])
            except Exception:
                item['Runtime'] = 0
                LOG.info("Runtime is missing, Using Zero")

        try:
            seektime = self.getTime()
        except Exception:  # at this point we should be playing and if not then bail out
            return

        result = JSONRPC('Application.GetProperties').execute({'properties': ["volume", "muted"]})
        result = result.get('result', {})
        volume = result.get('volume')
        muted = result.get('muted')

        item.update({
            'File': file,
            'CurrentPosition': item.get('CurrentPosition') or int(seektime),
            'Muted': muted,
            'Volume': volume,
            'Server': Jellyfin(item['ServerId']).get_client(),
            'Paused': False
        })

        self.played[file] = item
        LOG.info("-->[ play/%s ] %s", item['Id'], item)
示例#5
0
    def __init__(self, monitor):

        self.media = {'Movies': Movies, 'TVShows': TVShows, 'MusicVideos': MusicVideos, 'Music': Music}
        self.MEDIA = MEDIA

        self.direct_path = settings('useDirectPaths') == "1"
        self.progress_display = int(settings('syncProgress') or 50)
        self.monitor = monitor
        self.player = monitor.monitor.player
        self.server = Jellyfin().get_client()
        self.updated_queue = Queue.Queue()
        self.userdata_queue = Queue.Queue()
        self.removed_queue = Queue.Queue()
        self.updated_output = self.__new_queues__()
        self.userdata_output = self.__new_queues__()
        self.removed_output = self.__new_queues__()
        self.notify_output = Queue.Queue()

        self.jellyfin_threads = []
        self.download_threads = []
        self.notify_threads = []
        self.writer_threads = {'updated': [], 'userdata': [], 'removed': []}
        self.database_lock = threading.Lock()
        self.music_database_lock = threading.Lock()

        threading.Thread.__init__(self)
示例#6
0
    def stop_default(self):

        window('jellyfin_online', clear=True)
        Jellyfin().close()

        if self.library_thread is not None:

            self.library_thread.stop_client()
            self.library_thread = None
示例#7
0
    def get_client(self, server_id=None):

        ''' Get Jellyfin client.
        '''
        client = Jellyfin(server_id)
        client.config.app("Kodi", self.info['Version'], self.info['DeviceName'], self.info['DeviceId'])
        client.config.data['http.user_agent'] = "Jellyfin-Kodi/%s" % self.info['Version']
        client.config.data['auth.ssl'] = self.get_ssl()

        return client
示例#8
0
    def __init__(self, transcode=False, delete=False):

        try:
            self.kodi_id = sys.listitem.getVideoInfoTag().getDbId() or None
            self.media = self.get_media_type()
            self.server_id = sys.listitem.getProperty('jellyfinserver') or None
            self.api_client = Jellyfin(self.server_id).get_client().jellyfin
            item_id = sys.listitem.getProperty('jellyfinid')
        except AttributeError:
            self.server_id = None

            if xbmc.getInfoLabel('ListItem.Property(jellyfinid)'):
                item_id = xbmc.getInfoLabel('ListItem.Property(jellyfinid)')
            else:
                self.kodi_id = xbmc.getInfoLabel('ListItem.DBID')
                self.media = xbmc.getInfoLabel('ListItem.DBTYPE')
                item_id = None

        if self.server_id or item_id:
            self.item = self.api_client.get_item(item_id)
        else:
            self.item = self.get_item_id()

        if self.item:

            if transcode:
                self.transcode()

            elif delete:
                self.delete_item()

            elif self.select_menu():
                self.action_menu()

                if self._selected_option in (OPTIONS['Delete'],
                                             OPTIONS['AddFav'],
                                             OPTIONS['RemoveFav']):

                    xbmc.sleep(500)
                    xbmc.executebuiltin('Container.Refresh')
示例#9
0
    def remove_server(self, server_id):
        ''' Stop client and remove server.
        '''
        Jellyfin(server_id).close()
        credentials = get_credentials()

        for server in credentials['Servers']:
            if server['Id'] == server_id:
                credentials['Servers'].remove(server)

                break

        save_credentials(credentials)
        LOG.info("[ remove server ] %s", server_id)
示例#10
0
    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)
示例#11
0
def browse_letters(media, view_id, server_id=None):
    ''' Display letters as options.
    '''
    letters = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ"

    view = Jellyfin(server_id).get_client().jellyfin.get_item(view_id)
    xbmcplugin.setPluginCategory(PROCESS_HANDLE, view['Name'])

    for node in letters:

        params = {
            'id': view_id,
            'mode': "browse",
            'type': media,
            'folder': 'firstletter-%s' % node,
            'server': server_id
        }
        path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urlencode(params))
        directory(node, path)

    xbmcplugin.setContent(PROCESS_HANDLE, 'files')
    xbmcplugin.endOfDirectory(PROCESS_HANDLE)
示例#12
0
    def register(self, server_id=None, options={}):
        ''' Login into server. If server is None, then it will show the proper prompts to login, etc.
            If a server id is specified then only a login dialog will be shown for that server.
        '''
        LOG.info("--[ server/%s ]", server_id or 'default')
        credentials = dict(get_credentials())
        servers = credentials['Servers']

        if server_id is None and credentials['Servers']:
            credentials['Servers'] = [credentials['Servers'][0]]

        elif credentials['Servers']:

            for server in credentials['Servers']:

                if server['Id'] == server_id:
                    credentials['Servers'] = [server]

        server_select = True if server_id is None and not settings(
            'SyncInstallRunDone.bool') else False
        new_credentials = self.register_client(credentials, options, server_id,
                                               server_select)

        for server in servers:
            if server['Id'] == new_credentials['Servers'][0]['Id']:
                server = new_credentials['Servers'][0]

                break
        else:
            servers = new_credentials['Servers']

        credentials['Servers'] = servers
        save_credentials(credentials)

        try:
            Jellyfin(server_id).start(True)
        except ValueError as error:
            LOG.error(error)
示例#13
0
def browse_subfolders(media, view_id, server_id=None):
    ''' Display submenus for jellyfin views.
    '''
    from views import DYNNODES

    view = Jellyfin(server_id).get_client().jellyfin.get_item(view_id)
    xbmcplugin.setPluginCategory(PROCESS_HANDLE, view['Name'])
    nodes = DYNNODES[media]

    for node in nodes:

        params = {
            'id': view_id,
            'mode': "browse",
            'type': media,
            'folder': view_id if node[0] == 'all' else node[0],
            'server': server_id
        }
        path = "%s?%s" % ("plugin://plugin.video.jellyfin/", urlencode(params))
        directory(node[1] or view['Name'], path)

    xbmcplugin.setContent(PROCESS_HANDLE, 'files')
    xbmcplugin.endOfDirectory(PROCESS_HANDLE)
示例#14
0
    def __init__(self, server_id=None, api_client=None):

        self.server_id = server_id or None
        if not api_client:
            LOG.debug('No api client provided, attempting to use config file')
            jellyfin_client = Jellyfin(server_id).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))

        self.api_client = api_client
        self.server = self.api_client.config.data['auth.server']

        self.stack = []
示例#15
0
    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)
示例#16
0
    def onNotification(self, sender, method, data):
        ''' All notifications are sent via NotifyAll built-in or Kodi.
            Central hub.
        '''
        if sender.lower() not in ('plugin.video.jellyfin', 'xbmc'):
            return

        if sender == 'plugin.video.jellyfin':
            method = method.split('.')[1]

            if method not in ('ServerUnreachable', 'ServerShuttingDown',
                              'UserDataChanged', 'ServerConnect',
                              'LibraryChanged', 'ServerOnline', 'SyncLibrary',
                              'RepairLibrary', 'RemoveLibrary',
                              'SyncLibrarySelection', 'RepairLibrarySelection',
                              'AddServer', 'Unauthorized', 'UpdateServer',
                              'UserConfigurationUpdated', 'ServerRestarting',
                              'RemoveServer', 'AddLibrarySelection',
                              'RemoveLibrarySelection'):
                return

            data = json.loads(data)[0]
        else:
            if method not in ('System.OnQuit', 'System.OnSleep',
                              'System.OnWake'):
                return

            data = json.loads(data)

        LOG.debug("[ %s: %s ] %s", sender, method, json.dumps(data, indent=4))

        if method == 'ServerOnline':
            if data.get('ServerId') is None:

                window('jellyfin_online.bool', True)
                self.settings['auth_check'] = True
                self.warn = True

                if settings('connectMsg.bool'):

                    users = [
                        user for user in (
                            settings('additionalUsers') or "").split(',')
                        if user
                    ]
                    users.insert(0, settings('username'))
                    dialog("notification",
                           heading="{jellyfin}",
                           message="%s %s" %
                           (translate(33000), ", ".join(users)),
                           icon="{jellyfin}",
                           time=1500,
                           sound=False)

                if self.library_thread is None:

                    self.library_thread = library.Library(self)
                    self.library_thread.start()

        elif method in ('ServerUnreachable', 'ServerShuttingDown'):

            if self.warn or data.get('ServerId'):

                self.warn = data.get('ServerId') is not None
                dialog("notification",
                       heading="{jellyfin}",
                       message=translate(33146)
                       if data.get('ServerId') is None else translate(33149),
                       icon=xbmcgui.NOTIFICATION_ERROR)

            if data.get('ServerId') is None:
                self.stop_default()

                if self.waitForAbort(120):
                    return

                self.start_default()

        elif method == 'Unauthorized':
            dialog("notification",
                   heading="{jellyfin}",
                   message=translate(33147)
                   if data['ServerId'] is None else translate(33148),
                   icon=xbmcgui.NOTIFICATION_ERROR)

            if data.get('ServerId') is None and self.settings['auth_check']:

                self.settings['auth_check'] = False
                self.stop_default()

                if self.waitForAbort(5):
                    return

                self.start_default()

        elif method == 'ServerRestarting':
            if data.get('ServerId'):
                return

            if settings('restartMsg.bool'):
                dialog("notification",
                       heading="{jellyfin}",
                       message=translate(33006),
                       icon="{jellyfin}")

            self.stop_default()

            if self.waitForAbort(15):
                return

            self.start_default()

        elif method == 'ServerConnect':
            self.connect.register(data['Id'])
            xbmc.executebuiltin("Container.Refresh")

        elif method == 'AddServer':

            self.connect.setup_manual_server()
            xbmc.executebuiltin("Container.Refresh")

        elif method == 'RemoveServer':

            self.connect.remove_server(data['Id'])
            xbmc.executebuiltin("Container.Refresh")

        elif method == 'UpdateServer':

            dialog("ok", heading="{jellyfin}", line1=translate(33151))
            self.connect.setup_manual_server()

        elif method == 'UserDataChanged' and self.library_thread:
            if data.get('ServerId') or not window('jellyfin_startup.bool'):
                return

            LOG.info("[ UserDataChanged ] %s", data)
            self.library_thread.userdata(data['UserDataList'])

        elif method == 'LibraryChanged' and self.library_thread:
            if data.get('ServerId') or not window('jellyfin_startup.bool'):
                return

            LOG.info("[ LibraryChanged ] %s", data)
            self.library_thread.updated(data['ItemsUpdated'] +
                                        data['ItemsAdded'])
            self.library_thread.removed(data['ItemsRemoved'])

        elif method == 'System.OnQuit':
            window('jellyfin_should_stop.bool', True)
            self.running = False

        elif method in ('SyncLibrarySelection', 'RepairLibrarySelection',
                        'AddLibrarySelection', 'RemoveLibrarySelection'):
            self.library_thread.select_libraries(method)

        elif method == 'SyncLibrary':
            if not data.get('Id'):
                return

            self.library_thread.add_library(data['Id'],
                                            data.get('Update', False))
            xbmc.executebuiltin("Container.Refresh")

        elif method == 'RepairLibrary':
            if not data.get('Id'):
                return

            libraries = data['Id'].split(',')

            for lib in libraries:

                if not self.library_thread.remove_library(lib):
                    return

            self.library_thread.add_library(data['Id'])
            xbmc.executebuiltin("Container.Refresh")

        elif method == 'RemoveLibrary':
            libraries = data['Id'].split(',')

            for lib in libraries:

                if not self.library_thread.remove_library(lib):
                    return

            xbmc.executebuiltin("Container.Refresh")

        elif method == 'System.OnSleep':

            LOG.info("-->[ sleep ]")
            window('jellyfin_should_stop.bool', True)

            if self.library_thread is not None:

                self.library_thread.stop_client()
                self.library_thread = None

            Jellyfin.close_all()
            self.monitor.server = []
            self.monitor.sleep = True

        elif method == 'System.OnWake':

            if not self.monitor.sleep:
                LOG.warning(
                    "System.OnSleep was never called, skip System.OnWake")

                return

            LOG.info("--<[ sleep ]")
            xbmc.sleep(10000)  # Allow network to wake up
            self.monitor.sleep = False
            window('jellyfin_should_stop', clear=True)

            try:
                self.connect.register()
            except Exception as error:
                LOG.exception(error)

        elif method == 'GUI.OnScreensaverDeactivated':

            LOG.info("--<[ screensaver ]")
            xbmc.sleep(5000)

            if self.library_thread is not None:
                self.library_thread.fast_sync()

        elif method == 'UserConfigurationUpdated':

            if data.get('ServerId') is None:
                Views().get_views()
示例#17
0
    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()
示例#18
0
# -*- coding: utf-8 -*-
from __future__ import division, absolute_import, print_function, unicode_literals

#################################################################################################

import logging

from kodi_six import xbmc, xbmcvfs

from helper import loghandler
from jellyfin import Jellyfin

from .default import Events
from .service import Service
from .context import Context

#################################################################################################

Jellyfin.set_loghandler(loghandler.LogHandler, logging.DEBUG)
loghandler.reset()
loghandler.config()
LOG = logging.getLogger('JELLYFIN.entrypoint')

#################################################################################################
示例#19
0
def _http(action, url, request={}, server_id=None):
    request.update({'url': url, 'type': action})

    return Jellyfin(server_id)['http/request'](request)
示例#20
0
    def __init__(self):

        self.sync = get_sync()
        self.server = Jellyfin()
示例#21
0
class Context(object):

    _selected_option = None

    def __init__(self, transcode=False, delete=False):

        try:
            self.kodi_id = sys.listitem.getVideoInfoTag().getDbId() or None
            self.media = self.get_media_type()
            self.server_id = sys.listitem.getProperty('jellyfinserver') or None
            self.api_client = Jellyfin(self.server_id).get_client().jellyfin
            item_id = sys.listitem.getProperty('jellyfinid')
        except AttributeError:
            self.server_id = None

            if xbmc.getInfoLabel('ListItem.Property(jellyfinid)'):
                item_id = xbmc.getInfoLabel('ListItem.Property(jellyfinid)')
            else:
                self.kodi_id = xbmc.getInfoLabel('ListItem.DBID')
                self.media = xbmc.getInfoLabel('ListItem.DBTYPE')
                item_id = None

        if self.server_id or item_id:
            self.item = self.api_client.get_item(item_id)
        else:
            self.item = self.get_item_id()

        if self.item:

            if transcode:
                self.transcode()

            elif delete:
                self.delete_item()

            elif self.select_menu():
                self.action_menu()

                if self._selected_option in (OPTIONS['Delete'],
                                             OPTIONS['AddFav'],
                                             OPTIONS['RemoveFav']):

                    xbmc.sleep(500)
                    xbmc.executebuiltin('Container.Refresh')

    def get_media_type(self):
        ''' Get media type based on sys.listitem. If unfilled, base on visible window.
        '''
        media = sys.listitem.getVideoInfoTag().getMediaType()

        if not media:

            if xbmc.getCondVisibility('Container.Content(albums)'):
                media = "album"
            elif xbmc.getCondVisibility('Container.Content(artists)'):
                media = "artist"
            elif xbmc.getCondVisibility('Container.Content(songs)'):
                media = "song"
            elif xbmc.getCondVisibility('Container.Content(pictures)'):
                media = "picture"
            else:
                LOG.info("media is unknown")

        return media

    def get_item_id(self):
        ''' Get synced item from jellyfindb.
        '''
        item = database.get_item(self.kodi_id, self.media)

        if not item:
            return

        return {
            'Id': item[0],
            'UserData': json.loads(item[4]) if item[4] else {},
            'Type': item[3]
        }

    def select_menu(self):
        ''' Display the select dialog.
            Favorites, Refresh, Delete (opt), Settings.
        '''
        options = []

        if self.item['Type'] not in ('Season'):

            if self.item['UserData'].get('IsFavorite'):
                options.append(OPTIONS['RemoveFav'])
            else:
                options.append(OPTIONS['AddFav'])

        options.append(OPTIONS['Refresh'])

        if settings('enableContextDelete.bool'):
            options.append(OPTIONS['Delete'])

        options.append(OPTIONS['Addon'])

        context_menu = context.ContextMenu("script-jellyfin-context.xml",
                                           *XML_PATH)
        context_menu.set_options(options)
        context_menu.doModal()

        if context_menu.is_selected():
            self._selected_option = context_menu.get_selected()

        return self._selected_option

    def action_menu(self):

        selected = self._selected_option

        if selected == OPTIONS['Refresh']:
            self.api_client.refresh_item(self.item['Id'])

        elif selected == OPTIONS['AddFav']:
            self.api_client.favorite(self.item['Id'], True)

        elif selected == OPTIONS['RemoveFav']:
            self.api_client.favorite(self.item['Id'], False)

        elif selected == OPTIONS['Addon']:
            xbmc.executebuiltin('Addon.OpenSettings(plugin.video.jellyfin)')

        elif selected == OPTIONS['Delete']:
            self.delete_item()

    def delete_item(self):
        if settings('skipContextMenu.bool') or dialog("yesno", "{jellyfin}",
                                                      translate(33015)):

            self.api_client.delete_item(self.item['Id'])

    def transcode(self):
        filename = xbmc.getInfoLabel("ListItem.Filenameandpath")
        filename += "&transcode=true"
        xbmc.executebuiltin("PlayMedia(%s)" % filename)