Esempio n. 1
0
    def __init__(self, params, server_id=None):
        ''' Workflow: Strm that calls our webservice in database. When played,
            the webserivce returns a dummy file to play. Meanwhile,
            PlayStrm adds the real listitems for items to play to the playlist.
        '''
        self.info = {
            'Intros': None,
            'Item': None,
            'Id': params.get('Id'),
            'DbId': params.get('KodiId'),
            'Transcode': params.get('transcode'),
            'AdditionalParts': None,
            'ServerId': server_id,
            'KodiPlaylist': xbmc.PlayList(xbmc.PLAYLIST_VIDEO),
            'Server': Emby(server_id).get_client()
        }
        if self.info['Transcode'] is None:
            self.info['Transcode'] = settings(
                'playFromTranscode.bool') if settings(
                    'playFromStream.bool') else None

        self.actions = Actions(server_id,
                               self.info['Server']['auth/server-address'])
        self.set_listitem = self.actions.set_listitem
        self.params = params
        self._detect_play()
        LOG.info("[ play strm ]")
Esempio n. 2
0
    def transcode(self):

        item = TheVoid('GetItem', {
            'Id': self.item['Id'],
            'ServerId': self.server
        }).get()
        Actions(self.server).play(item, self.kodi_id, True)
Esempio n. 3
0
    def __init__(self, addon_context_files, addon, addon_path,
                 addon_data_path):
        self._addon = addon
        self._addon_path = addon_path
        self._addon_data_path = addon_data_path

        self._xoze = Actions()
        for filepath in addon_context_files:
            self._load_actions(
                file.resolve_file_path(baseDirPath=addon_path,
                                       filename=filepath))
        self._initialize_mvc()
Esempio n. 4
0
    def __init__(self, params, server_id=None):

        ''' Workflow: Strm that calls our webservice in database. When played,
            the webserivce returns a dummy file to play. Meanwhile,
            PlayStrm adds the real listitems for items to play to the playlist.
        '''
        self.info = {
            'Item': None,
            'Id': params.get('id'),
            'DbId': params.get('dbid'),
            'Transcode': params.get('transcode'),
            'ServerId': server_id,
            'Server': TheVoid('GetServerAddress', {'ServerId': server_id}).get(),
        }
        if self.info['Transcode'] is None:
             self.info['Transcode'] = settings('playFromTranscode.bool') if settings('playFromStream.bool') else None

        self.actions = Actions(server_id, self.info['Server'])
        self.set_listitem = self.actions.set_listitem
        self.params = params
        self._detect_play()
        LOG.info("[ play simple ]")
Esempio n. 5
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:

            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()
Esempio n. 6
0
def browse(media, view_id=None, folder=None, server_id=None):

    ''' Browse content dynamically.
    '''
    LOG.info("--[ v:%s/%s ] %s", view_id, media, folder)

    if not window('emby_online.bool') and server_id is None:

        monitor = xbmc.Monitor()

        for i in range(300):
            if window('emby_online.bool'):
                break
            elif monitor.waitForAbort(0.1):
                return
        else:
            LOG.error("Default server is not online.")

            return

    folder = folder.lower() if folder else None

    if folder is None and media in ('homevideos', 'movies', 'books', 'audiobooks'):
        return browse_subfolders(media, view_id, server_id)

    if folder and folder == 'firstletter':
        return browse_letters(media, view_id, server_id)

    if view_id:

        view = TheVoid('GetItem', {'ServerId': server_id, 'Id': view_id}).get()
        xbmcplugin.setPluginCategory(int(sys.argv[1]), view['Name'])

    content_type = "files"

    if media in ('tvshows', 'seasons', 'episodes', 'movies', 'musicvideos', 'songs', 'albums'):
        content_type = media
    elif media in ('homevideos', 'photos'):
        content_type = "images"
    elif media in ('books', 'audiobooks'):
        content_type = "videos"
    elif media == 'music':
        content_type = "artists"


    if folder == 'recentlyadded':
        listing = TheVoid('RecentlyAdded', {'Id': view_id, 'ServerId': server_id}).get()
    elif folder == 'genres':
        listing = TheVoid('Genres', {'Id': view_id, 'ServerId': server_id}).get()
    elif media == 'livetv':
        listing = TheVoid('LiveTV', {'Id': view_id, 'ServerId': server_id}).get()
    elif folder == 'unwatched':
        listing = TheVoid('Browse', {'Id': view_id, 'ServerId': server_id, 'Filters': ['IsUnplayed']}).get()
    elif folder == 'favorite':
        listing = TheVoid('Browse', {'Id': view_id, 'ServerId': server_id, 'Filters': ['IsFavorite']}).get()
    elif folder == 'inprogress':
        listing = TheVoid('Browse', {'Id': view_id, 'ServerId': server_id, 'Filters': ['IsResumable']}).get()
    elif folder == 'boxsets':
        listing = TheVoid('Browse', {'Id': view_id, 'ServerId': server_id, 'Media': get_media_type('boxsets'), 'Recursive': True}).get()
    elif folder == 'random':
        listing = TheVoid('Browse', {'Id': view_id, 'ServerId': server_id, 'Media': get_media_type(content_type), 'Sort': "Random", 'Limit': 25, 'Recursive': True}).get()
    elif (folder or "").startswith('firstletter-'):
        listing = TheVoid('Browse', {'Id': view_id, 'ServerId': server_id, 'Media': get_media_type(content_type), 'Params': {'NameStartsWith': folder.split('-')[1]}}).get()
    elif (folder or "").startswith('genres-'):
        listing = TheVoid('Browse', {'Id': view_id, 'ServerId': server_id, 'Media': get_media_type(content_type), 'Params': {'GenreIds': folder.split('-')[1]}}).get()
    elif folder == 'favepisodes':
        listing = TheVoid('Browse', {'Media': get_media_type(content_type), 'ServerId': server_id, 'Limit': 25, 'Filters': ['IsFavorite']}).get()
    elif media == 'homevideos':
        listing = TheVoid('Browse', {'Id': folder or view_id, 'Media': get_media_type(content_type), 'ServerId': server_id, 'Recursive': False}).get()
    elif media == 'movies':
        listing = TheVoid('Browse', {'Id': folder or view_id, 'Media': get_media_type(content_type), 'ServerId': server_id, 'Recursive': True}).get()
    elif media in ('boxset', 'library'):
        listing = TheVoid('Browse', {'Id': folder or view_id, 'ServerId': server_id, 'Recursive': True}).get()
    elif media == 'episodes':
        listing = TheVoid('Browse', {'Id': folder or view_id, 'Media': get_media_type(content_type), 'ServerId': server_id, 'Recursive': True}).get()
    elif media == 'boxsets':
        listing = TheVoid('Browse', {'Id': folder or view_id, 'ServerId': server_id, 'Recursive': False, 'Filters': ["Boxsets"]}).get()
    elif media == 'tvshows':
        listing = TheVoid('Browse', {'Id': folder or view_id, 'ServerId': server_id, 'Recursive': True, 'Media': get_media_type(content_type)}).get()
    elif media == 'seasons':
        listing = TheVoid('BrowseSeason', {'Id': folder, 'ServerId': server_id}).get()
    elif media != 'files':
        listing = TheVoid('Browse', {'Id': folder or view_id, 'ServerId': server_id, 'Recursive': False, 'Media': get_media_type(content_type)}).get()
    else:
        listing = TheVoid('Browse', {'Id': folder or view_id, 'ServerId': server_id, 'Recursive': False}).get()


    if listing:

        actions = Actions(server_id)
        list_li = []
        listing = listing if type(listing) == list else listing.get('Items', [])

        for item in listing:

            li = xbmcgui.ListItem()
            li.setProperty('embyid', item['Id'])
            li.setProperty('embyserver', server_id)
            actions.set_listitem(item, li)

            if item.get('IsFolder'):

                params = {
                    'id': view_id or item['Id'],
                    'mode': "browse",
                    'type': get_folder_type(item, media) or media,
                    'folder': item['Id'],
                    'server': server_id
                }
                path = "%s?%s" % ("plugin://plugin.video.emby/",  urllib.urlencode(params))
                context = []

                if item['Type'] in ('Series', 'Season', 'Playlist'):
                    context.append(("Play", "RunPlugin(plugin://plugin.video.emby/?mode=playlist&id=%s&server=%s)" % (item['Id'], server_id)))

                if item['UserData']['Played']:
                    context.append((_(16104), "RunPlugin(plugin://plugin.video.emby/?mode=unwatched&id=%s&server=%s)" % (item['Id'], server_id)))
                else:
                    context.append((_(16103), "RunPlugin(plugin://plugin.video.emby/?mode=watched&id=%s&server=%s)" % (item['Id'], server_id)))

                li.addContextMenuItems(context)
                list_li.append((path, li, True))

            elif item['Type'] == 'Genre':

                params = {
                    'id': view_id or item['Id'],
                    'mode': "browse",
                    'type': get_folder_type(item, media) or media,
                    'folder': 'genres-%s' % item['Id'],
                    'server': server_id
                }
                path = "%s?%s" % ("plugin://plugin.video.emby/",  urllib.urlencode(params))
                list_li.append((path, li, True))

            else:
                if item['Type'] not in ('Photo', 'PhotoAlbum'):
                    params = {
                        'id': item['Id'],
                        'mode': "play",
                        'server': server_id
                    }
                    path = "%s?%s" % ("plugin://plugin.video.emby/", urllib.urlencode(params))
                    li.setProperty('path', path)
                    context = [(_(13412), "RunPlugin(plugin://plugin.video.emby/?mode=playlist&id=%s&server=%s)" % (item['Id'], server_id))]

                    if item['UserData']['Played']:
                        context.append((_(16104), "RunPlugin(plugin://plugin.video.emby/?mode=unwatched&id=%s&server=%s)" % (item['Id'], server_id)))
                    else:
                        context.append((_(16103), "RunPlugin(plugin://plugin.video.emby/?mode=watched&id=%s&server=%s)" % (item['Id'], server_id)))

                    li.addContextMenuItems(context)

                list_li.append((li.getProperty('path'), li, False))

        xbmcplugin.addDirectoryItems(int(sys.argv[1]), list_li, len(list_li))

    if content_type == 'images':
        xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE)
        xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_YEAR)
        xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_DATE)
        xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_RATING)
        xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_RUNTIME)

    xbmcplugin.setContent(int(sys.argv[1]), content_type)
    xbmcplugin.endOfDirectory(int(sys.argv[1]))
Esempio n. 7
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()
Esempio n. 8
0
def browse(media, view_id=None, folder=None, server_id=None, api_client=None):
    ''' Browse content dynamically.
    '''
    LOG.info("--[ v:%s/%s ] %s", view_id, media, folder)

    if not window('jellyfin_online.bool') and server_id is None:

        monitor = xbmc.Monitor()

        for i in range(300):
            if window('jellyfin_online.bool'):
                break
            elif monitor.waitForAbort(0.1):
                return
        else:
            LOG.error("Default server is not online.")

            return

    folder = folder.lower() if folder else None

    if folder is None and media in ('homevideos', 'movies', 'books',
                                    'audiobooks'):
        return browse_subfolders(media, view_id, server_id)

    if folder and folder == 'firstletter':
        return browse_letters(media, view_id, server_id)

    if view_id:

        view = api_client.get_item(view_id)
        xbmcplugin.setPluginCategory(PROCESS_HANDLE, view['Name'])

    content_type = "files"

    if media in ('tvshows', 'seasons', 'episodes', 'movies', 'musicvideos',
                 'songs', 'albums'):
        content_type = media
    elif media in ('homevideos', 'photos'):
        content_type = "images"
    elif media in ('books', 'audiobooks'):
        content_type = "videos"
    elif media == 'music':
        content_type = "artists"

    if folder == 'recentlyadded':
        listing = api_client.get_recently_added(None, view_id, None)
    elif folder == 'genres':
        listing = api_client.get_genres(view_id)
    elif media == 'livetv':
        listing = api_client.get_channels()
    elif folder == 'unwatched':
        listing = get_filtered_section(view_id, None, None, None, None, None,
                                       ['IsUnplayed'], None, server_id,
                                       api_client)
    elif folder == 'favorite':
        listing = get_filtered_section(view_id, None, None, None, None, None,
                                       ['IsFavorite'], None, server_id,
                                       api_client)
    elif folder == 'inprogress':
        listing = get_filtered_section(view_id, None, None, None, None, None,
                                       ['IsResumable'], None, server_id,
                                       api_client)
    elif folder == 'boxsets':
        listing = get_filtered_section(view_id, get_media_type('boxsets'),
                                       None, True, None, None, None, None,
                                       server_id, api_client)
    elif folder == 'random':
        listing = get_filtered_section(view_id, get_media_type(content_type),
                                       25, True, "Random", None, None, None,
                                       server_id, api_client)
    elif (folder or "").startswith('firstletter-'):
        listing = get_filtered_section(
            view_id, get_media_type(content_type), None, None, None, None,
            None, {'NameStartsWith': folder.split('-')[1]}, server_id,
            api_client)
    elif (folder or "").startswith('genres-'):
        listing = get_filtered_section(view_id, get_media_type(content_type),
                                       None, None, None, None, None,
                                       {'GenreIds': folder.split('-')[1]},
                                       server_id, api_client)
    elif folder == 'favepisodes':
        listing = get_filtered_section(None, get_media_type(content_type), 25,
                                       None, None, None, ['IsFavorite'], None,
                                       server_id, api_client)
    elif folder and media == 'playlists':
        listing = get_filtered_section(folder, get_media_type(content_type),
                                       None, False, 'None', None, None, None,
                                       server_id, api_client)
    elif media == 'homevideos':
        listing = get_filtered_section(folder or view_id,
                                       get_media_type(content_type), None,
                                       False, None, None, None, None,
                                       server_id, api_client)
    elif media in ['movies', 'episodes']:
        listing = get_filtered_section(folder or view_id,
                                       get_media_type(content_type), None,
                                       True, None, None, None, None, server_id,
                                       api_client)
    elif media in ('boxset', 'library'):
        listing = get_filtered_section(folder or view_id, None, None, True,
                                       None, None, None, None, server_id,
                                       api_client)
    elif media == 'boxsets':
        listing = get_filtered_section(folder or view_id, None, None, False,
                                       None, None, ['Boxsets'], None,
                                       server_id, api_client)
    elif media == 'tvshows':
        listing = get_filtered_section(folder or view_id,
                                       get_media_type(content_type), None,
                                       True, None, None, None, None, server_id,
                                       api_client)
    elif media == 'seasons':
        listing = api_client.get_seasons(folder)
    elif media != 'files':
        listing = get_filtered_section(folder or view_id,
                                       get_media_type(content_type), None,
                                       False, None, None, None, None,
                                       server_id, api_client)
    else:
        listing = get_filtered_section(folder or view_id, None, None, False,
                                       None, None, None, None, server_id,
                                       api_client)

    if listing:

        actions = Actions(server_id, api_client)
        list_li = []
        listing = listing if type(listing) == list else listing.get(
            'Items', [])

        for item in listing:

            li = xbmcgui.ListItem()
            li.setProperty('jellyfinid', item['Id'])
            li.setProperty('jellyfinserver', server_id)
            actions.set_listitem(item, li)

            if item.get('IsFolder'):

                params = {
                    'id': view_id or item['Id'],
                    'mode': "browse",
                    'type': get_folder_type(item, media) or media,
                    'folder': item['Id'],
                    'server': server_id
                }
                path = "%s?%s" % ("plugin://plugin.video.jellyfin/",
                                  urlencode(params))
                context = []

                if item['Type'] in ('Series', 'Season', 'Playlist'):
                    context.append((
                        "Play",
                        "RunPlugin(plugin://plugin.video.jellyfin/?mode=playlist&id=%s&server=%s)"
                        % (item['Id'], server_id)))

                if item['UserData']['Played']:
                    context.append((translate(
                        16104
                    ), "RunPlugin(plugin://plugin.video.jellyfin/?mode=unwatched&id=%s&server=%s)"
                                    % (item['Id'], server_id)))
                else:
                    context.append((translate(
                        16103
                    ), "RunPlugin(plugin://plugin.video.jellyfin/?mode=watched&id=%s&server=%s)"
                                    % (item['Id'], server_id)))

                li.addContextMenuItems(context)
                list_li.append((path, li, True))

            elif item['Type'] == 'Genre':

                params = {
                    'id': view_id or item['Id'],
                    'mode': "browse",
                    'type': get_folder_type(item, media) or media,
                    'folder': 'genres-%s' % item['Id'],
                    'server': server_id
                }
                path = "%s?%s" % ("plugin://plugin.video.jellyfin/",
                                  urlencode(params))
                list_li.append((path, li, True))

            else:
                if item['Type'] not in ('Photo', 'PhotoAlbum'):
                    params = {
                        'id': item['Id'],
                        'mode': "play",
                        'server': server_id
                    }
                    path = "%s?%s" % ("plugin://plugin.video.jellyfin/",
                                      urlencode(params))
                    li.setProperty('path', path)
                    context = [(translate(
                        13412
                    ), "RunPlugin(plugin://plugin.video.jellyfin/?mode=playlist&id=%s&server=%s)"
                                % (item['Id'], server_id))]

                    if item['UserData']['Played']:
                        context.append((translate(
                            16104
                        ), "RunPlugin(plugin://plugin.video.jellyfin/?mode=unwatched&id=%s&server=%s)"
                                        % (item['Id'], server_id)))
                    else:
                        context.append((translate(
                            16103
                        ), "RunPlugin(plugin://plugin.video.jellyfin/?mode=watched&id=%s&server=%s)"
                                        % (item['Id'], server_id)))

                    li.addContextMenuItems(context)

                list_li.append((li.getProperty('path'), li, False))

        xbmcplugin.addDirectoryItems(PROCESS_HANDLE, list_li, len(list_li))

    if content_type == 'images':
        xbmcplugin.addSortMethod(PROCESS_HANDLE,
                                 xbmcplugin.SORT_METHOD_VIDEO_TITLE)
        xbmcplugin.addSortMethod(PROCESS_HANDLE, xbmcplugin.SORT_METHOD_DATE)
        xbmcplugin.addSortMethod(PROCESS_HANDLE,
                                 xbmcplugin.SORT_METHOD_VIDEO_RATING)
        xbmcplugin.addSortMethod(PROCESS_HANDLE,
                                 xbmcplugin.SORT_METHOD_VIDEO_RUNTIME)

    xbmcplugin.setContent(PROCESS_HANDLE, content_type)
    xbmcplugin.endOfDirectory(PROCESS_HANDLE)
Esempio n. 9
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()
Esempio n. 10
0
class PlayStrm(object):
    def __init__(self, params, server_id=None):
        ''' Workflow: Strm that calls our webservice in database. When played,
            the webserivce returns a dummy file to play. Meanwhile,
            PlayStrm adds the real listitems for items to play to the playlist.
        '''
        self.info = {
            'Intros': None,
            'Item': None,
            'Id': params.get('Id'),
            'DbId': params.get('KodiId'),
            'Transcode': params.get('transcode'),
            'AdditionalParts': None,
            'ServerId': server_id,
            'KodiPlaylist': xbmc.PlayList(xbmc.PLAYLIST_VIDEO),
            'Server': Emby(server_id).get_client()
        }
        if self.info['Transcode'] is None:
            self.info['Transcode'] = settings(
                'playFromTranscode.bool') if settings(
                    'playFromStream.bool') else None

        self.actions = Actions(server_id,
                               self.info['Server']['auth/server-address'])
        self.set_listitem = self.actions.set_listitem
        self.params = params
        self._detect_play()
        LOG.info("[ play strm ]")

    def remove_from_playlist(self, index, playlist_id=None):

        playlist = playlist_id or 1
        JSONRPC('Playlist.Remove').execute({
            'playlistid': playlist_id,
            'position': index
        })

    def remove_from_playlist_by_path(self, path):

        LOG.debug("[ removing ] %s", path)
        self.info['KodiPlaylist'].remove(path)

    def _get_intros(self):
        self.info['Intros'] = self.info['Server']['api'].get_intros(
            self.info['Id'])

    def _get_additional_parts(self):
        self.info['AdditionalParts'] = self.info['Server'][
            'api'].get_additional_parts(self.info['Id'])

    def _get_item(self):
        self.info['Item'] = self.info['Server']['api'].get_item(
            self.info['Id'])

    def _detect_play(self):
        ''' Download all information needed to build the playlist for item requested.
        '''
        if self.info['Id']:

            self._get_intros()
            self._get_item()
            self._get_additional_parts()

    def start_playback(self, index=0):
        xbmc.Player().play(self.info['KodiPlaylist'],
                           startpos=index,
                           windowed=False)

    def play(self, delayed=True):
        ''' Create and add listitems to the Kodi playlist.
        '''
        if window('emby_playlistclear.bool'):

            LOG.info("[ play clearing playlist ]")
            self.actions.get_playlist(self.info['Item']).clear()
            window('emby_playlistclear.bool', clear=True)

        self.info['StartIndex'] = max(self.info['KodiPlaylist'].getposition(),
                                      0)
        self.info['Index'] = self.info['StartIndex']
        LOG.info("[ play/%s/%s ]", self.info['Id'], self.info['Index'])

        listitem = xbmcgui.ListItem()
        self._set_playlist(listitem)

        if not delayed:
            self.start_playback(self.info['StartIndex'])

        return self.info['StartIndex']

    def play_folder(self, position=None):
        ''' When an entire queue is requested, 
            queue playlist items using strm links to setup playback later.
        '''
        self.info['StartIndex'] = position or max(
            self.info['KodiPlaylist'].size(), 0)
        self.info['Index'] = self.info['StartIndex'] + 1
        LOG.info("[ play folder/%s/%s ]", self.info['Id'], self.info['Index'])

        listitem = xbmcgui.ListItem()
        self.actions.set_listitem(self.info['Item'], listitem,
                                  self.info['DbId'])
        url = "http://127.0.0.1:57578/emby/play/file.strm?mode=playfolder&Id=%s" % self.info[
            'Id']

        if self.info['DbId']:
            url += "&KodiId=%s" % self.info['DbId']

        if self.info['ServerId']:
            url += "&server=%s" % self.info['ServerId']

        if self.info['Transcode']:
            url += "&transcode=true"

        listitem.setPath(url)
        self.info['KodiPlaylist'].add(url=url,
                                      listitem=listitem,
                                      index=self.info['Index'])

        return self.info['Index']

    def _set_playlist(self, listitem):
        ''' Verify seektime, set intros, set main item and set additional parts.
            Detect the seektime for video type content.
            Verify the default video action set in Kodi for accurate resume behavior.
        '''
        seektime = window('emby.resume')
        window('emby.resume', clear=True)
        seektime = seektime == 'true' if seektime else None

        if seektime is None and self.info['Item']['MediaType'] in ('Video',
                                                                   'Audio'):
            resume = self.info['Item']['UserData'].get('PlaybackPositionTicks')

            if resume:
                choice = self.actions.resume_dialog(
                    api.API(self.info['Item'],
                            self.info['Server']).adjust_resume(
                                (resume or 0) / 10000000.0), self.info['Item'])

                if choice is None:
                    raise Exception("User backed out of resume dialog.")

                seektime = False if not choice else True

        if settings('enableCinema.bool') and not seektime:
            self._set_intros()

        LOG.info("[ main/%s/%s ] %s", self.info['Item']['Id'],
                 self.info['Index'], self.info['Item']['Name'])
        play = playutils.PlayUtilsStrm(self.info['Item'],
                                       self.info['Transcode'],
                                       self.info['ServerId'],
                                       self.info['Server'])
        source = play.select_source(play.get_sources())

        if not source:
            raise Exception("Playback selection cancelled")

        play.set_external_subs(source, listitem)
        self.set_listitem(self.info['Item'], listitem, self.info['DbId'],
                          seektime)
        listitem.setPath(self.info['Item']['PlaybackInfo']['Path'])
        playutils.set_properties(self.info['Item'],
                                 self.info['Item']['PlaybackInfo']['Method'],
                                 self.info['ServerId'])

        self.info['KodiPlaylist'].add(
            url=self.info['Item']['PlaybackInfo']['Path'],
            listitem=listitem,
            index=self.info['Index'])
        self.info['Index'] += 1

        if self.info['Item'].get('PartCount'):
            self._set_additional_parts()

    def _set_intros(self):
        ''' if we have any play them when the movie/show is not being resumed.
        '''
        if self.info['Intros']['Items']:
            enabled = True

            if settings('askCinema') == "true":

                resp = dialog("yesno", heading="{emby}", line1=_(33016))
                if not resp:

                    enabled = False
                    LOG.info("Skip trailers.")

            if enabled:
                for intro in self.info['Intros']['Items']:

                    listitem = xbmcgui.ListItem()
                    LOG.info("[ intro/%s/%s ] %s", intro['Id'],
                             self.info['Index'], intro['Name'])

                    play = playutils.PlayUtilsStrm(intro, False,
                                                   self.info['ServerId'],
                                                   self.info['Server'])
                    source = play.select_source(play.get_sources())
                    self.set_listitem(intro, listitem, intro=True)
                    listitem.setPath(intro['PlaybackInfo']['Path'])
                    playutils.set_properties(intro,
                                             intro['PlaybackInfo']['Method'],
                                             self.info['ServerId'])

                    self.info['KodiPlaylist'].add(
                        url=intro['PlaybackInfo']['Path'],
                        listitem=listitem,
                        index=self.info['Index'])
                    self.info['Index'] += 1

                    window('emby.skip.%s' % intro['Id'], value="true")

    def _set_additional_parts(self, item_id):
        ''' Create listitems and add them to the stack of playlist.
        '''
        for part in self.info['AdditionalParts']['Items']:

            listitem = xbmcgui.ListItem()
            LOG.info("[ part/%s/%s ] %s", part['Id'], self.info['Index'],
                     part['Name'])

            play = playutils.PlayUtilsStrm(part, self.info['Transcode'],
                                           self.info['ServerId'],
                                           self.info['Server'])
            source = play.select_source(play.get_sources())
            play.set_external_subs(source, listitem)
            self.set_listitem(part, listitem)
            listitem.setPath(part['PlaybackInfo']['Path'])
            playutils.set_properties(part, part['PlaybackInfo']['Method'],
                                     self.info['ServerId'])

            self.info['KodiPlaylist'].add(url=part['PlaybackInfo']['Path'],
                                          listitem=listitem,
                                          index=self.info['Index'])
            self.info['Index'] += 1
Esempio n. 11
0
class PlaySimple(object):

    def __init__(self, params, server_id=None):

        ''' Workflow: Strm that calls our webservice in database. When played,
            the webserivce returns a dummy file to play. Meanwhile,
            PlayStrm adds the real listitems for items to play to the playlist.
        '''
        self.info = {
            'Item': None,
            'Id': params.get('id'),
            'DbId': params.get('dbid'),
            'Transcode': params.get('transcode'),
            'ServerId': server_id,
            'Server': TheVoid('GetServerAddress', {'ServerId': server_id}).get(),
        }
        if self.info['Transcode'] is None:
             self.info['Transcode'] = settings('playFromTranscode.bool') if settings('playFromStream.bool') else None

        self.actions = Actions(server_id, self.info['Server'])
        self.set_listitem = self.actions.set_listitem
        self.params = params
        self._detect_play()
        LOG.info("[ play simple ]")

    def _get_item(self):
        self.info['Item'] = TheVoid('GetItem', {'Id': self.info['Id'], 'ServerId': self.info['Server']}).get()

    def _detect_play(self):

        ''' Download all information needed to build the playlist for item requested.
        '''
        if self.info['Id']:
            self._get_item()

    def play(self):

        ''' Create and add listitems to the Kodi playlist.
        '''
        LOG.info("[ play/%s ]", self.info['Id'])

        listitem = xbmcgui.ListItem()
        self._set_playlist(listitem)

        return xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)

    def _set_playlist(self, listitem):

        ''' Verify seektime, set intros, set main item and set additional parts.
            Detect the seektime for video type content.
            Verify the default video action set in Kodi for accurate resume behavior.
        '''
        seektime = self._resume()

        LOG.info("[ main/%s ] %s", self.info['Item']['Id'], self.info['Item']['Name'])
        play = playutils.PlayUtils(self.info['Item'], self.info['Transcode'], self.info['ServerId'], self.info['Server'])
        source = play.select_source(play.get_sources())

        if not source:
            raise Exception("Playback selection cancelled")

        play.set_external_subs(source, listitem)
        self.set_listitem(self.info['Item'], listitem, self.info['DbId'], seektime)
        listitem.setPath(self.info['Item']['PlaybackInfo']['Path'])
        playutils.set_properties(self.info['Item'], self.info['Item']['PlaybackInfo']['Method'], self.info['ServerId'])

    def _resume(self):

        ''' Resume item if available.
            Returns bool or raise an exception if resume was cancelled by user.
        '''
        seektime = window('emby.resume')
        seektime = seektime == 'true' if seektime else None
        auto_play = window('emby.autoplay.bool')
        window('emby.resume', clear=True)

        if auto_play:

            seektime = False
            LOG.info("[ skip resume for auto play ]")

        elif seektime is None and self.info['Item']['MediaType'] in ('Video', 'Audio'):
            resume = self.info['Item']['UserData'].get('PlaybackPositionTicks')

            if resume:

                adjusted = api.API(self.info['Item'], self.info['Server']).adjust_resume((resume or 0) / 10000000.0)
                seektime = self.actions.resume_dialog(adjusted, self.info['Item'])
                LOG.info("Resume: %s", adjusted)

                if seektime is None:
                    raise Exception("User backed out of resume dialog.")

            window('emby.autoplay.bool', True)

        return seektime