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 transcode(self): item = TheVoid('GetItem', { 'Id': self.item['Id'], 'ServerId': self.server }).get() Actions(self.server).play(item, self.kodi_id, True)
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()
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 __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()
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]))
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()
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)
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()
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
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