def __init__(self, method, data): ''' If you call get, this will block until response is received. This is used to communicate between entrypoints. ''' if type(data) != dict: raise Exception("unexpected data format") data['VoidName'] = str(create_id()) LOG.info("---[ contact MU-TH-UR 6000/%s ]", method) LOG.debug(data) event(method, data) self.method = method self.data = data
def service(self): ''' Keeps the service monitor going. Exit on Kodi shutdown or profile switch. if profile switch happens more than once, Threads depending on abortRequest will not trigger. ''' self.monitor = monitor.Monitor() player = self.monitor.player self.connect = connect.Connect() self.start_default() self.settings['mode'] = settings('useDirectPaths') while self.running: if window('emby_online.bool'): if self.settings['profile'] != window('emby_kodiProfile'): LOG.info("[ profile switch ] %s", self.settings['profile']) break if player.isPlaying() and player.is_playing_file( player.get_playing_file()): difference = datetime.today( ) - self.settings['last_progress'] if difference.seconds > 10: self.settings['last_progress'] = datetime.today() update = (datetime.today() - self.settings['last_progress_report'] ).seconds > 250 event('ReportProgressRequested', {'Report': update}) if update: self.settings[ 'last_progress_report'] = datetime.today() if window('emby.restart.bool'): window('emby.restart', clear=True) raise Exception('RestartService') if self.waitForAbort(1): break self.shutdown()
def next_up(self): item = self.get_file_info(self.get_playing_file()) objects = Objects() if item['Type'] != 'Episode' or not item.get('CurrentEpisode'): return next_items = item['Server'].jellyfin.get_adjacent_episodes( item['CurrentEpisode']['tvshowid'], item['Id']) for index, next_item in enumerate(next_items['Items']): if next_item['Id'] == item['Id']: try: next_item = next_items['Items'][index + 1] except IndexError: LOG.warning("No next up episode.") return break server_address = item['Server'].auth.get_server_info( item['Server'].auth.server_id)['address'] API = api.API(next_item, server_address) data = objects.map(next_item, "UpNext") artwork = API.get_all_artwork(objects.map(next_item, 'ArtworkParent'), True) data['art'] = { 'tvshow.poster': artwork.get('Series.Primary'), 'tvshow.fanart': None, 'thumb': artwork.get('Primary') } if artwork['Backdrop']: data['art']['tvshow.fanart'] = artwork['Backdrop'][0] next_info = { 'play_info': { 'ItemIds': [data['episodeid']], 'ServerId': item['ServerId'], 'PlayCommand': 'PlayNow' }, 'current_episode': item['CurrentEpisode'], 'next_episode': data } LOG.info("--[ next up ] %s", next_info) event("upnext_data", next_info, hexlify=True)
def delete_item(self): delete = True if not settings('skipContextMenu.bool'): if not dialog("yesno", heading="{emby}", line1=_(33015)): delete = False if delete: self.server['api'].delete_item(self.item['Id']) event( "LibraryChanged", { 'ItemsRemoved': [self.item['Id']], 'ItemsVerify': [self.item['Id']], 'ItemsUpdated': [], 'ItemsAdded': [] })
def get_views(self): ''' Get the media folders. Add or remove them. Do not proceed if issue getting libraries. ''' media = { 'movies': "Movie", 'tvshows': "Series", 'musicvideos': "MusicVideo" } try: libraries = self.get_libraries() except IndexError as error: LOG.exception(error) return self.sync['SortedViews'] = [x['Id'] for x in libraries] for library in libraries: if library['Type'] == 'Channel': library['Media'] = "channels" else: library['Media'] = library.get( 'OriginalCollectionType', library.get('CollectionType', "mixed")) self.add_library(library) with Database('jellyfin') as jellyfindb: views = jellyfin_db.JellyfinDatabase(jellyfindb.cursor).get_views() removed = [] for view in views: if view[0] not in self.sync['SortedViews']: removed.append(view[0]) if removed: event('RemoveLibrary', {'Id': ','.join(removed)}) save_sync(self.sync)
def add_user(api_client): ''' Add or remove users from the default server session. ''' if not window('jellyfin_online.bool'): return session = api_client.get_device(client.get_device_id()) users = api_client.get_users() current = session[0]['AdditionalUsers'] result = dialog("select", translate(33061), [translate(33062), translate(33063)] if current else [translate(33062)]) if result < 0: return if not result: # Add user eligible = [ x for x in users if x['Id'] not in [current_user['UserId'] for current_user in current] ] resp = dialog("select", translate(33064), [x['Name'] for x in eligible]) if resp < 0: return user = eligible[resp] event('AddUser', {'Id': user['Id'], 'Add': True}) else: # Remove user resp = dialog("select", translate(33064), [x['UserName'] for x in current]) if resp < 0: return user = current[resp] event('AddUser', {'Id': user['UserId'], 'Add': False})
def register_client(self, credentials=None, options=None, server_id=None, server_selection=False): client = self.get_client(server_id) self.client = client self.connect_manager = client.auth if server_id is None: client.config.data['app.default'] = True try: state = client.authenticate(credentials or {}, options or {}) if state['State'] == CONNECTION_STATE['SignedIn']: client.callback_ws = event if server_id is None: # Only assign for default server client.callback = event self.get_user(client) settings('serverName', client.config.data['auth.server-name']) settings('server', client.config.data['auth.server']) event('ServerOnline', {'ServerId': server_id}) event('LoadServer', {'ServerId': server_id}) return state['Credentials'] elif (server_selection or state['State'] == CONNECTION_STATE['ServerSelection'] or state['State'] == CONNECTION_STATE['Unavailable'] and not settings('SyncInstallRunDone.bool')): self.select_servers(state) elif state['State'] == CONNECTION_STATE['ServerSignIn']: if 'ExchangeToken' not in state['Servers'][0]: self.login() elif state['State'] == CONNECTION_STATE['Unavailable'] and state['Status_Code'] == 401: # If the saved credentials don't work, restart the addon to force the password dialog to open window('jellyfin.restart', clear=True) elif state['State'] == CONNECTION_STATE['Unavailable']: raise HTTPException('ServerUnreachable', {}) return self.register_client(state['Credentials'], options, server_id, False) except RuntimeError as error: LOG.exception(error) xbmc.executebuiltin('Addon.OpenSettings(%s)' % addon_id()) raise Exception('User sign in interrupted') except HTTPException as error: if error.status == 'ServerUnreachable': event('ServerUnreachable', {'ServerId': server_id}) return client.get_credentials()
def server_instance(self, server_id=None): server = Emby(server_id).get_client() self.post_capabilities(server) if server_id is not None: self.servers.append(server_id) elif settings('addUsers'): users = settings('addUsers').split(',') hidden = None if settings('addUsersHidden.bool') else False all_users = server['api'].get_users(hidden=hidden) for additional in users: for user in all_users: if user['Id'] == additional: server['api'].session_add_user( server['config/app.session'], user['Id']) self.additional_users(server) event('ServerOnline', {'ServerId': server_id})
def add_user(): ''' Add or remove users from the default server session. ''' if not window('jellyfin_online.bool'): return session = TheVoid('GetSession', {}).get() users = TheVoid('GetUsers', {'IsDisabled': False, 'IsHidden': False}).get() current = session[0]['AdditionalUsers'] result = dialog("select", _(33061), [_(33062), _(33063)] if current else [_(33062)]) if result < 0: return if not result: # Add user eligible = [ x for x in users if x['Id'] not in [current_user['UserId'] for current_user in current] ] resp = dialog("select", _(33064), [x['Name'] for x in eligible]) if resp < 0: return user = eligible[resp] event('AddUser', {'Id': user['Id'], 'Add': True}) else: # Remove user resp = dialog("select", _(33064), [x['UserName'] for x in current]) if resp < 0: return user = current[resp] event('AddUser', {'Id': user['UserId'], 'Add': False})
def get_views(self): ''' Get the media folders. Add or remove them. ''' media = { 'movies': "Movie", 'tvshows': "Series", 'musicvideos': "MusicVideo" } libraries = self.get_libraries() self.sync['SortedViews'] = [x['Id'] for x in libraries] for library in libraries: if library['Type'] == 'Channel': library['Media'] = "channels" else: library['Media'] = library.get( 'OriginalCollectionType', library.get('CollectionType', "mixed")) self.add_library(library) with Database('emby') as embydb: views = emby_db.EmbyDatabase(embydb.cursor).get_views() removed = [] for view in views: if view[0] not in self.sync['SortedViews']: removed.append(view[0]) if removed: event('RemoveLibrary', {'Id': ','.join(removed)}) save_sync(self.sync)
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 __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()
def select_libraries(self, mode=None): ''' Select from libraries synced. Either update or repair libraries. Send event back to service.py ''' modes = { 'SyncLibrarySelection': 'SyncLibrary', 'RepairLibrarySelection': 'RepairLibrary', 'AddLibrarySelection': 'SyncLibrary', 'RemoveLibrarySelection': 'RemoveLibrary' } sync = get_sync() whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']] libraries = [] with Database('jellyfin') as jellyfindb: db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor) if mode in ('SyncLibrarySelection', 'RepairLibrarySelection', 'RemoveLibrarySelection'): for library in sync['Whitelist']: name = db.get_view_name(library.replace('Mixed:', "")) libraries.append({'Id': library, 'Name': name}) else: available = [ x for x in sync['SortedViews'] if x not in whitelist ] for library in available: name, media = db.get_view(library) if media in ('movies', 'tvshows', 'musicvideos', 'mixed', 'music'): libraries.append({'Id': library, 'Name': name}) choices = [x['Name'] for x in libraries] choices.insert(0, translate(33121)) titles = { "RepairLibrarySelection": 33199, "SyncLibrarySelection": 33198, "RemoveLibrarySelection": 33200, "AddLibrarySelection": 33120 } title = titles.get(mode, "Failed to get title {}".format(mode)) selection = dialog("multi", translate(title), choices) if selection is None: return if 0 in selection: selection = list(range(1, len(libraries) + 1)) selected_libraries = [] for x in selection: library = libraries[x - 1] selected_libraries.append(library['Id']) event( modes[mode], { 'Id': ','.join([libraries[x - 1]['Id'] for x in selection]), 'Update': mode == 'SyncLibrarySelection' })
def __init__(self): global CONTENT_TYPE ''' Parse the parameters. Reroute to our service.py where user is fully identified already. ''' base_url = sys.argv[0] path = sys.argv[2] try: params = dict(urlparse.parse_qsl(path[1:])) except Exception: params = {} if 'content_type' in params: window('emby.plugin.content.type', params['content_type']) CONTENT_TYPE = params['content_type'] else: CONTENT_TYPE = window('emby.plugin.content.type') or None mode = params.get('mode') server = params.get('server') if server == 'None' or not server: server = None LOG.warn("path: %s params: %s", path, json.dumps(params, indent=4)) if '/extrafanart' in base_url: emby_path = path[1:] emby_id = params.get('id') get_fanart(emby_id, emby_path, server) elif '/Extras' in base_url or '/VideoFiles' in base_url: emby_path = path[1:] emby_id = params.get('id') get_video_extras(emby_id, emby_path, server) elif mode == 'play': window('emby.sync.pause.bool', True) window('emby.playlist.plugin.bool', True) try: objects.PlayPlugin(params, server).play('trailer' in base_url) except Exception as error: LOG.exception(error) if not xbmc.Player().isPlaying(): xbmc.Player().stop() xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xbmcgui.ListItem()) window('emby.sync.pause.bool', clear=True) window('emby.playlist.plugin', clear=True) elif mode =='playstrm': window('emby.sync.pause.bool', True) window('emby.playlist.plugin.bool', True) while not window('emby.playlist.play.bool'): xbmc.sleep(50) if window('emby.playlist.aborted.bool'): LOG.warn("[ playback aborted ]") break else: LOG.info("[ playback started ]") xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xbmcgui.ListItem()) window('emby.playlist.aborted', clear=True) window('emby.sync.pause', clear=True) window('emby.playlist.plugin', clear=True) elif mode == 'playsingle': window('emby.sync.pause.bool', True) window('emby.playlist.plugin.bool', True) try: objects.PlaySingle(params, server).play() except Exception as error: LOG.exception(error) if not xbmc.Player().isPlaying(): xbmc.Player().stop() xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xbmcgui.ListItem()) window('emby.sync.pause', clear=True) window('emby.playlist.plugin', clear=True) elif mode == 'playlist': event('PlayPlaylist', {'Id': params['id'], 'ServerId': server}) elif mode == 'photoviewer': xbmc.executebuiltin('ShowPicture(%s/emby/Items/%s/Images/Primary)' % (Emby(server)['auth/server-address'], params['id'])) elif mode == 'deviceid': client.reset_device_id() elif mode == 'reset': reset() elif mode == 'delete': delete_item() elif mode == 'refreshboxsets': event('SyncLibrary', {'Id': "Boxsets:Refresh"}) elif mode == 'nextepisodes': get_next_episodes(params['id'], params['limit']) elif mode == 'browse': browse(params.get('type'), params.get('id'), params.get('folder'), server) elif mode == 'synclib': event('SyncLibrary', {'Id': params.get('id')}) elif mode == 'updatelib': event('SyncLibrary', {'Id': params.get('id'), 'Update': True}) elif mode == 'repairlib': event('RepairLibrary', {'Id': params.get('id')}) elif mode == 'removelib': event('RemoveLibrary', {'Id': params.get('id')}) elif mode == 'repairlibs': event('RepairLibrarySelection') elif mode == 'updatelibs': event('SyncLibrarySelection') elif mode == 'removelibs': event('RemoveLibrarySelection') elif mode == 'addlibs': event('AddLibrarySelection') elif mode == 'connect': event('EmbyConnect') elif mode == 'addserver': event('AddServer') elif mode == 'login': event('ServerConnect', {'Id': server}) elif mode == 'removeserver': event('RemoveServer', {'Id': server}) elif mode == 'settings': xbmc.executebuiltin('Addon.OpenSettings(plugin.video.emby)') elif mode == 'adduser': add_user(params.get('permanent') == 'true') elif mode == 'checkupdate': event('CheckUpdate') elif mode == 'resetupdate': event('ResetUpdate') elif mode == 'updateserver': event('UpdateServer') elif mode == 'thememedia': get_themes() elif mode == 'managelibs': manage_libraries() elif mode == 'texturecache': cache_artwork() elif mode == 'backup': backup() elif mode == 'restartservice': window('emby.restart.bool', True) elif mode == 'patchmusic': event('PatchMusic', {'Notification': True}) elif mode == 'changelog': changelog() elif mode == 'setssl': event('SetServerSSL', {'Id': server}) else: listing()
def stop_playback(self): ''' Stop all playback. Check for external player for positionticks. Immediately force an internal update for the item to remove the visual delay waiting on the callback from server. ''' LOG.debug("[ played info ] %s", self.played) for file in self.played: try: item = self.get_file_info(file) if not item['Track']: LOG.info("[ skip stop ] %s", file) continue LOG.info("[ played info ] %s", item) item['Track'] = False self.played[file] = item window('emby.skip.%s.bool' % item['Id'], True) if window('emby.external.bool'): window('emby.external', clear=True) if int(item['CurrentPosition']) == 1: item['CurrentPosition'] = int(item['Runtime']) data = { 'ItemId': item['Id'], 'MediaSourceId': item['MediaSourceId'], 'PositionTicks': int(item['CurrentPosition'] * 10000000), 'PlaySessionId': item['PlaySessionId'] } item['Server']['api'].session_stop(data) event( "LibraryChanged", { 'ItemsRemoved': [], 'ItemsVerify': [], 'ItemsUpdated': [item['Id']], 'ItemsAdded': [] }) if item.get('LiveStreamId'): LOG.info("<[ livestream/%s ]", item['LiveStreamId']) item['Server']['api'].close_live_stream( item['LiveStreamId']) elif item['PlayMethod'] == 'Transcode': LOG.info("<[ transcode/%s ]", item['Id']) item['Server']['api'].close_transcode(item['DeviceId']) path = xbmc.translatePath( "special://profile/addon_data/plugin.video.emby/temp/" ).decode('utf-8') if xbmcvfs.exists(path): dirs, files = xbmcvfs.listdir(path) for file in files: xbmcvfs.delete(os.path.join(path, file.decode('utf-8'))) result = item['Server']['api'].get_item(item['Id']) or {} if 'UserData' in result and result['UserData']['Played']: delete = False if result['Type'] == 'Episode' and settings( 'deleteTV.bool'): delete = True elif result['Type'] == 'Movie' and settings( 'deleteMovies.bool'): delete = True if not settings('offerDelete.bool'): delete = False if delete: LOG.info("Offer delete option") if dialog("yesno", heading=_(30091), line1=_(33015), autoclose=120000): item['Server']['api'].delete_item(item['Id']) event( "LibraryChanged", { 'ItemsRemoved': [item['Id']], 'ItemsVerify': [item['Id']], 'ItemsUpdated': [], 'ItemsAdded': [] }) except Exception as error: LOG.error(error) window('emby.play.reset', clear=True) window('emby.external_check', clear=True) window('emby.sync.pause', clear=True)
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 add_user(permanent=False): ''' Add or remove users from the default server session. permanent=True from the add-on settings. ''' if not window('emby_online.bool'): return session = TheVoid('GetSession', {}).get() users = TheVoid('GetUsers', {'IsDisabled': False, 'IsHidden': False}).get() for user in users: if user['Id'] == session[0]['UserId']: users.remove(user) break while True: session = TheVoid('GetSession', {}).get() additional = current = session[0]['AdditionalUsers'] add_session = True if permanent: perm_users = settings('addUsers').split(',') if settings('addUsers') else [] current = [] for user in users: for perm_user in perm_users: if user['Id'] == perm_user: current.append({'UserName': user['Name'], 'UserId': user['Id']}) result = dialog("select", _(33061), [_(33062), _(33063)] if current else [_(33062)]) if result < 0: break if not result: # Add user eligible = [x for x in users if x['Id'] not in [current_user['UserId'] for current_user in current]] resp = dialog("select", _(33064), [x['Name'] for x in eligible]) if resp < 0: break user = eligible[resp] if permanent: perm_users.append(user['Id']) settings('addUsers', ','.join(perm_users)) if user['Id'] in [current_user['UserId'] for current_user in additional]: add_session = False if add_session: event('AddUser', {'Id': user['Id'], 'Add': True}) dialog("notification", heading="{emby}", message="%s %s" % (_(33067), user['Name']), icon="{emby}", time=1000, sound=False) else: # Remove user resp = dialog("select", _(33064), [x['UserName'] for x in current]) if resp < 0: break user = current[resp] if permanent: perm_users.remove(user['UserId']) settings('addUsers', ','.join(perm_users)) if add_session: event('AddUser', {'Id': user['UserId'], 'Add': False}) dialog("notification", heading="{emby}", message="%s %s" % (_(33066), user['UserName']), icon="{emby}", time=1000, sound=False)
def service(self): ''' Keeps the service monitor going. Exit on Kodi shutdown or profile switch. if profile switch happens more than once, Threads depending on abortRequest will not trigger. ''' self.monitor = monitor.Monitor() player = self.monitor.player self.connect = connect.Connect() self.start_default() self.settings['mode'] = settings('useDirectPaths') while self.running: if window('emby_online.bool'): if self.settings['profile'] != window('emby_kodiProfile'): LOG.info("[ profile switch ] %s", self.settings['profile']) break if player.isPlaying() and player.is_playing_file( player.get_playing_file()): difference = datetime.today( ) - self.settings['last_progress'] if difference.seconds > 4: self.settings['last_progress'] = datetime.today() update = (datetime.today() - self.settings['last_progress_report'] ).seconds > 250 event('ReportProgressRequested', {'Report': update}) if update: self.settings[ 'last_progress_report'] = datetime.today() if self.webservice is not None and not self.webservice.is_alive(): LOG.info("[ restarting due to socket disconnect ]") window('emby.restart.bool', True) if window('emby.restart.bool'): window('emby.restart', clear=True) dialog("notification", heading="{emby}", message=_(33193), icon="{emby}", time=1000, sound=False) raise Exception('RestartService') if self.waitForAbort(1): break self.shutdown() raise Exception("ExitService")