def add_item_to_kodi_playlist(playlist, pos, kodi_id=None, kodi_type=None, file=None): """ Adds an item to the KODI playlist only. WILL ALSO UPDATE OUR PLAYLISTS Returns False if unsuccessful file: str! """ log.debug('Adding new item kodi_id: %s, kodi_type: %s, file: %s to Kodi ' 'only at position %s for %s' % (kodi_id, kodi_type, file, pos, playlist)) params = { 'playlistid': playlist.playlistid, 'position': pos } if kodi_id is not None: params['item'] = {'%sid' % kodi_type: int(kodi_id)} else: params['item'] = {'file': file} reply = JSONRPC('Playlist.Insert').execute(params) if reply.get('error') is not None: log.error('Could not add item to playlist. Kodi reply. %s' % reply) return False else: playlist.items.insert(pos, playlist_item_from_kodi( {'id': kodi_id, 'type': kodi_type, 'file': file})) return True
def add_item_to_kodi_playlist(playlist, pos, kodi_id=None, kodi_type=None, file=None): """ Adds an item to the KODI playlist only. WILL ALSO UPDATE OUR PLAYLISTS Returns False if unsuccessful file: str! """ log.debug('Adding new item kodi_id: %s, kodi_type: %s, file: %s to Kodi ' 'only at position %s for %s' % (kodi_id, kodi_type, file, pos, playlist)) params = {'playlistid': playlist.playlistid, 'position': pos} if kodi_id is not None: params['item'] = {'%sid' % kodi_type: int(kodi_id)} else: params['item'] = {'file': file} reply = JSONRPC('Playlist.Insert').execute(params) if reply.get('error') is not None: log.error('Could not add item to playlist. Kodi reply. %s' % reply) return False else: playlist.items.insert( pos, playlist_item_from_kodi({ 'id': kodi_id, 'type': kodi_type, 'file': file })) return True
def getPlayers(): info = JSONRPC("Player.GetActivePlayers").execute()['result'] or [] ret = {} for player in info: player['playerid'] = int(player['playerid']) ret[player['type']] = player return ret
def add_to_playlist(cls, db_id=None, media_type=None, url=None): params = {'playlistid': 1} if db_id is not None: params['item'] = {'%sid' % media_type: int(db_id)} else: params['item'] = {'file': url} log.debug(JSONRPC('Playlist.Add').execute(params))
def getPlaylists(): """ Returns a list, e.g. [ {u'playlistid': 0, u'type': u'audio'}, {u'playlistid': 1, u'type': u'video'}, {u'playlistid': 2, u'type': u'picture'} ] """ return JSONRPC('Playlist.GetPlaylists').execute()
def add_to_Kodi_playlist(playlist, xml_video_element): """ Adds a new item to the Kodi playlist via JSON (at the end of the playlist). Pass in the PMS xml's video element (one level underneath MediaContainer). Returns a Playlist_Item or None if it did not work """ item = playlist_item_from_xml(playlist, xml_video_element) params = {'playlistid': playlist.playlistid} if item.kodi_id: params['item'] = {'%sid' % item.kodi_type: item.kodi_id} else: params['item'] = {'file': item.file} reply = JSONRPC('Playlist.Add').execute(params) if reply.get('error') is not None: log.error('Could not add item %s to Kodi playlist. Error: %s' % (xml_video_element, reply)) return None else: return item
def remove_from_Kodi_playlist(playlist, pos): """ Removes the item at position pos from the Kodi playlist using JSON. WILL NOT UPDATE THE PLEX SIDE, BUT WILL UPDATE OUR PLAYLISTS """ log.debug('Removing position %s from Kodi only from %s' % (pos, playlist)) reply = JSONRPC('Playlist.Remove').execute({ 'playlistid': playlist.playlistid, 'position': pos }) if reply.get('error') is not None: log.error('Could not delete the item from the playlist. Error: %s' % reply) return else: try: del playlist.items[pos] except IndexError: log.error('Cannot delete position %s for %s' % (pos, playlist))
def add_to_Kodi_playlist(playlist, xml_video_element): """ Adds a new item to the Kodi playlist via JSON (at the end of the playlist). Pass in the PMS xml's video element (one level underneath MediaContainer). Returns a Playlist_Item or None if it did not work """ item = playlist_item_from_xml(playlist, xml_video_element) params = { 'playlistid': playlist.playlistid } if item.kodi_id: params['item'] = {'%sid' % item.kodi_type: item.kodi_id} else: params['item'] = {'file': item.file} reply = JSONRPC('Playlist.Add').execute(params) if reply.get('error') is not None: log.error('Could not add item %s to Kodi playlist. Error: %s' % (xml_video_element, reply)) return None else: return item
def insert_to_playlist(cls, position, db_id=None, media_type=None, url=None): params = {'playlistid': 1, 'position': position} if db_id is not None: params['item'] = {'%sid' % media_type: int(db_id)} else: params['item'] = {'file': url} log.debug(JSONRPC('Playlist.Insert').execute(params))
def get_kodi_playqueues(): """ Example return: [{u'playlistid': 0, u'type': u'audio'}, {u'playlistid': 1, u'type': u'video'}, {u'playlistid': 2, u'type': u'picture'}] """ queues = JSONRPC('Playlist.GetPlaylists').execute() try: queues = queues['result'] except KeyError: raise KeyError('Could not get Kodi playqueues. JSON Result was: %s' % queues) return queues
def get_kodi_playlist_items(playlist): """ Returns a list of the current Kodi playlist items using JSON E.g.: [{u'title': u'3 Idiots', u'type': u'movie', u'id': 3, u'file': u'smb://nas/PlexMovies/3 Idiots 2009 pt1.mkv', u'label': u'3 Idiots'}] """ answ = JSONRPC('Playlist.GetItems').execute({ 'playlistid': playlist.playlistid, 'properties': ["title", "file"] }) try: answ = answ['result']['items'] except KeyError: answ = [] return answ
def _general_commands(cls, data): command = data['Name'] arguments = data['Arguments'] if command in ('Mute', 'Unmute', 'SetVolume', 'SetSubtitleStreamIndex', 'SetAudioStreamIndex'): player = xbmc.Player() # These commands need to be reported back if command == 'Mute': xbmc.executebuiltin('Mute') elif command == 'Unmute': xbmc.executebuiltin('Mute') elif command == 'SetVolume': volume = arguments['Volume'] xbmc.executebuiltin('SetVolume(%s[,showvolumebar])' % volume) elif command == 'SetAudioStreamIndex': index = int(arguments['Index']) player.setAudioStream(index - 1) elif command == 'SetSubtitleStreamIndex': emby_index = int(arguments['Index']) current_file = player.getPlayingFile() mapping = window('emby_%s.indexMapping' % current_file) if emby_index == -1: player.showSubtitles(False) elif mapping: external_index = json.loads(mapping) # If there's external subtitles added via playbackutils for index in external_index: if external_index[index] == emby_index: player.setSubtitleStream(int(index)) break else: # User selected internal subtitles external = len(external_index) audio_tracks = len(player.getAvailableAudioStreams()) player.setSubtitleStream(external + emby_index - audio_tracks - 1) else: # Emby merges audio and subtitle index together audio_tracks = len(player.getAvailableAudioStreams()) player.setSubtitleStream(emby_index - audio_tracks - 1) # Let service know window('emby_command', value="true") elif command == 'DisplayMessage': header = arguments['Header'] text = arguments['Text'] dialog(type_="notification", heading=header, message=text, icon="{emby}", time=int(settings('displayMessage'))*1000) elif command == 'SendString': params = { 'text': arguments['String'], 'done': False } JSONRPC('Input.SendText').execute(params) elif command in ('MoveUp', 'MoveDown', 'MoveRight', 'MoveLeft'): # Commands that should wake up display actions = { 'MoveUp': "Input.Up", 'MoveDown': "Input.Down", 'MoveRight': "Input.Right", 'MoveLeft': "Input.Left" } JSONRPC(actions[command]).execute() elif command == 'GoHome': JSONRPC('GUI.ActivateWindow').execute({'window': "home"}) else: builtin = { 'ToggleFullscreen': 'Action(FullScreen)', 'ToggleOsdMenu': 'Action(OSD)', 'ToggleContextMenu': 'Action(ContextMenu)', 'Select': 'Action(Select)', 'Back': 'Action(back)', 'PageUp': 'Action(PageUp)', 'NextLetter': 'Action(NextLetter)', 'GoToSearch': 'VideoLibrary.Search', 'GoToSettings': 'ActivateWindow(Settings)', 'PageDown': 'Action(PageDown)', 'PreviousLetter': 'Action(PrevLetter)', 'TakeScreenshot': 'TakeScreenshot', 'ToggleMute': 'Mute', 'VolumeUp': 'Action(VolumeUp)', 'VolumeDown': 'Action(VolumeDown)', } if command in builtin: xbmc.executebuiltin(builtin[command])
def _set_webserver_details(self): # Get the Kodi webserver details - used to set the texture cache get_setting_value = JSONRPC('Settings.GetSettingValue') web_query = {"setting": "services.webserver"} result = get_setting_value.execute(web_query) try: xbmc_webserver_enabled = result['result']['value'] except (KeyError, TypeError): xbmc_webserver_enabled = False if not xbmc_webserver_enabled: # Enable the webserver, it is disabled set_setting_value = JSONRPC('Settings.SetSettingValue') web_port = {"setting": "services.webserverport", "value": 8080} set_setting_value.execute(web_port) self.xbmc_port = 8080 web_user = {"setting": "services.webserver", "value": True} set_setting_value.execute(web_user) self.xbmc_username = "******" # Webserver already enabled web_port = {"setting": "services.webserverport"} result = get_setting_value.execute(web_port) try: self.xbmc_port = result['result']['value'] except (TypeError, KeyError): pass web_user = {"setting": "services.webserverusername"} result = get_setting_value.execute(web_user) try: self.xbmc_username = result['result']['value'] except (TypeError, KeyError): pass web_pass = {"setting": "services.webserverpassword"} result = get_setting_value.execute(web_pass) try: self.xbmc_password = result['result']['value'] except (TypeError, KeyError): pass
def getInProgressEpisodes(tagname, limit): count = 0 # if the addon is called with inprogressepisodes parameter, # we return the inprogressepisodes list of the given tagname xbmcplugin.setContent(HANDLE, 'episodes') # First we get a list of all the in-progress TV shows - filtered by tag params = { 'sort': { 'order': "descending", 'method': "lastplayed" }, 'filter': { 'and': [{ 'operator': "true", 'field': "inprogress", 'value': "" }, { 'operator': "is", 'field': "tag", 'value': "%s" % tagname }] }, 'properties': ['title', 'studio', 'mpaa', 'file', 'art'] } result = JSONRPC('VideoLibrary.GetTVShows').execute(params) # If we found any, find the oldest unwatched show for each one. try: items = result['result']['tvshows'] except (KeyError, TypeError): pass else: for item in items: params = { 'tvshowid': item['tvshowid'], 'sort': { 'method': "episode" }, 'filter': { 'operator': "true", 'field': "inprogress", 'value': "" }, 'properties': [ "title", "playcount", "season", "episode", "showtitle", "plot", "file", "rating", "resume", "tvshowid", "art", "cast", "streamdetails", "firstaired", "runtime", "writer", "dateadded", "lastplayed" ] } result = JSONRPC('VideoLibrary.GetEpisodes').execute(params) try: episodes = result['result']['episodes'] except (KeyError, TypeError): pass else: for episode in episodes: li = createListItem(episode) xbmcplugin.addDirectoryItem(handle=HANDLE, url=episode['file'], listitem=li) count += 1 if count == limit: break xbmcplugin.endOfDirectory(handle=HANDLE)
def process_command(request_path, params, queue=None): """ queue: Queue() of PlexCompanion.py """ if params.get('deviceName') == 'Alexa': convert_alexa_to_companion(params) log.debug('Received request_path: %s, params: %s' % (request_path, params)) if "/playMedia" in request_path: # We need to tell service.py action = 'alexa' if params.get('deviceName') == 'Alexa' else 'playlist' queue.put({'action': action, 'data': params}) elif request_path == "player/playback/setParameters": if 'volume' in params: volume = int(params['volume']) log.debug("Adjusting the volume to %s" % volume) JSONRPC('Application.SetVolume').execute({"volume": volume}) elif request_path == "player/playback/play": for playerid in getPlayerIds(): JSONRPC("Player.PlayPause").execute({ "playerid": playerid, "play": True }) elif request_path == "player/playback/pause": for playerid in getPlayerIds(): JSONRPC("Player.PlayPause").execute({ "playerid": playerid, "play": False }) elif request_path == "player/playback/stop": for playerid in getPlayerIds(): JSONRPC("Player.Stop").execute({"playerid": playerid}) elif request_path == "player/playback/seekTo": for playerid in getPlayerIds(): JSONRPC("Player.Seek").execute({ "playerid": playerid, "value": millisToTime(params.get('offset', 0)) }) elif request_path == "player/playback/stepForward": for playerid in getPlayerIds(): JSONRPC("Player.Seek").execute({ "playerid": playerid, "value": "smallforward" }) elif request_path == "player/playback/stepBack": for playerid in getPlayerIds(): JSONRPC("Player.Seek").execute({ "playerid": playerid, "value": "smallbackward" }) elif request_path == "player/playback/skipNext": for playerid in getPlayerIds(): JSONRPC("Player.GoTo").execute({ "playerid": playerid, "to": "next" }) elif request_path == "player/playback/skipPrevious": for playerid in getPlayerIds(): JSONRPC("Player.GoTo").execute({ "playerid": playerid, "to": "previous" }) elif request_path == "player/playback/skipTo": skipTo(params) elif request_path == "player/navigation/moveUp": JSONRPC("Input.Up").execute() elif request_path == "player/navigation/moveDown": JSONRPC("Input.Down").execute() elif request_path == "player/navigation/moveLeft": JSONRPC("Input.Left").execute() elif request_path == "player/navigation/moveRight": JSONRPC("Input.Right").execute() elif request_path == "player/navigation/select": JSONRPC("Input.Select").execute() elif request_path == "player/navigation/home": JSONRPC("Input.Home").execute() elif request_path == "player/navigation/back": JSONRPC("Input.Back").execute() else: log.error('Unknown request path: %s' % request_path)
def getRecentEpisodes(viewid, mediatype, tagname, limit): count = 0 # if the addon is called with recentepisodes parameter, # we return the recentepisodes list of the given tagname xbmcplugin.setContent(HANDLE, 'episodes') appendShowTitle = settings('RecentTvAppendShow') == 'true' appendSxxExx = settings('RecentTvAppendSeason') == 'true' # First we get a list of all the TV shows - filtered by tag params = { 'sort': { 'order': "descending", 'method': "dateadded" }, 'filter': { 'operator': "is", 'field': "tag", 'value': "%s" % tagname }, } result = JSONRPC('VideoLibrary.GetTVShows').execute(params) # If we found any, find the oldest unwatched show for each one. try: items = result['result'][mediatype] except (KeyError, TypeError): # No items, empty folder xbmcplugin.endOfDirectory(handle=HANDLE) return allshowsIds = set() for item in items: allshowsIds.add(item['tvshowid']) params = { 'sort': { 'order': "descending", 'method': "dateadded" }, 'properties': [ "title", "playcount", "season", "episode", "showtitle", "plot", "file", "rating", "resume", "tvshowid", "art", "streamdetails", "firstaired", "runtime", "cast", "writer", "dateadded", "lastplayed" ], "limits": { "end": limit } } if settings('TVShowWatched') == 'false': params['filter'] = { 'operator': "lessthan", 'field': "playcount", 'value': "1" } result = JSONRPC('VideoLibrary.GetEpisodes').execute(params) try: episodes = result['result']['episodes'] except (KeyError, TypeError): pass else: for episode in episodes: if episode['tvshowid'] in allshowsIds: li = createListItem(episode, appendShowTitle=appendShowTitle, appendSxxExx=appendSxxExx) xbmcplugin.addDirectoryItem(handle=HANDLE, url=episode['file'], listitem=li) count += 1 if count == limit: break xbmcplugin.endOfDirectory(handle=HANDLE)
def getOnDeck(viewid, mediatype, tagname, limit): """ Retrieves Plex On Deck items, currently only for TV shows Input: viewid: Plex id of the library section, e.g. '1' mediatype: Kodi mediatype, e.g. 'tvshows', 'movies', 'homevideos', 'photos' tagname: Name of the Plex library, e.g. "My Movies" limit: Max. number of items to retrieve, e.g. 50 """ xbmcplugin.setContent(HANDLE, 'episodes') appendShowTitle = settings('OnDeckTvAppendShow') == 'true' appendSxxExx = settings('OnDeckTvAppendSeason') == 'true' directpaths = settings('useDirectPaths') == 'true' if settings('OnDeckTVextended') == 'false': # Chances are that this view is used on Kodi startup # Wait till we've connected to a PMS. At most 30s counter = 0 while window('plex_authenticated') != 'true': counter += 1 if counter >= 300: log.error('Aborting On Deck view, we were not authenticated ' 'for the PMS') return xbmcplugin.endOfDirectory(HANDLE, False) sleep(100) xml = downloadutils.DownloadUtils().downloadUrl( '{server}/library/sections/%s/onDeck' % viewid) if xml in (None, 401): log.error('Could not download PMS xml for view %s' % viewid) return xbmcplugin.endOfDirectory(HANDLE) limitcounter = 0 for item in xml: api = API(item) listitem = api.CreateListItemFromPlexItem( appendShowTitle=appendShowTitle, appendSxxExx=appendSxxExx) if directpaths: url = api.getFilePath() else: params = { 'mode': "play", 'id': api.getRatingKey(), 'dbid': listitem.getProperty('dbid') } url = "plugin://plugin.video.plexkodiconnect/tvshows/?%s" \ % urlencode(params) xbmcplugin.addDirectoryItem(handle=HANDLE, url=url, listitem=listitem) limitcounter += 1 if limitcounter == limit: break return xbmcplugin.endOfDirectory( handle=HANDLE, cacheToDisc=settings('enableTextureCache') == 'true') # if the addon is called with nextup parameter, # we return the nextepisodes list of the given tagname # First we get a list of all the TV shows - filtered by tag params = { 'sort': { 'order': "descending", 'method': "lastplayed" }, 'filter': { 'and': [{ 'operator': "true", 'field': "inprogress", 'value': "" }, { 'operator': "is", 'field': "tag", 'value': "%s" % tagname }] } } result = JSONRPC('VideoLibrary.GetTVShows').execute(params) # If we found any, find the oldest unwatched show for each one. try: items = result['result'][mediatype] except (KeyError, TypeError): # Now items retrieved - empty directory xbmcplugin.endOfDirectory(handle=HANDLE) return params = { 'sort': { 'method': "episode" }, 'limits': { "end": 1 }, 'properties': [ "title", "playcount", "season", "episode", "showtitle", "plot", "file", "rating", "resume", "tvshowid", "art", "streamdetails", "firstaired", "runtime", "cast", "writer", "dateadded", "lastplayed" ], } if settings('ignoreSpecialsNextEpisodes') == "true": params['filter'] = { 'and': [{ 'operator': "lessthan", 'field': "playcount", 'value': "1" }, { 'operator': "greaterthan", 'field': "season", 'value': "0" }] } else: params['filter'] = { 'or': [{ 'operator': "lessthan", 'field': "playcount", 'value': "1" }, { 'operator': "true", 'field': "inprogress", 'value': "" }] } # Are there any episodes still in progress/not yet finished watching?!? # Then we should show this episode, NOT the "next up" inprog_params = { 'sort': { 'method': "episode" }, 'filter': { 'operator': "true", 'field': "inprogress", 'value': "" }, 'properties': params['properties'] } count = 0 for item in items: inprog_params['tvshowid'] = item['tvshowid'] result = JSONRPC('VideoLibrary.GetEpisodes').execute(inprog_params) try: episodes = result['result']['episodes'] except (KeyError, TypeError): # No, there are no episodes not yet finished. Get "next up" params['tvshowid'] = item['tvshowid'] result = JSONRPC('VideoLibrary.GetEpisodes').execute(params) try: episodes = result['result']['episodes'] except (KeyError, TypeError): # Also no episodes currently coming up continue for episode in episodes: # There will always be only 1 episode ('limit=1') li = createListItem(episode, appendShowTitle=appendShowTitle, appendSxxExx=appendSxxExx) xbmcplugin.addDirectoryItem(handle=HANDLE, url=episode['file'], listitem=li, isFolder=False) count += 1 if count >= limit: break xbmcplugin.endOfDirectory(handle=HANDLE)
def _set_webserver_details(self): # Get the Kodi webserver details - used to set the texture cache get_setting_value = JSONRPC('Settings.GetSettingValue') web_query = { "setting": "services.webserver" } result = get_setting_value.execute(web_query) try: xbmc_webserver_enabled = result['result']['value'] except (KeyError, TypeError): xbmc_webserver_enabled = False if not xbmc_webserver_enabled: # Enable the webserver, it is disabled set_setting_value = JSONRPC('Settings.SetSettingValue') web_port = { "setting": "services.webserverport", "value": 8080 } set_setting_value.execute(web_port) self.xbmc_port = 8080 web_user = { "setting": "services.webserver", "value": True } set_setting_value.execute(web_user) self.xbmc_username = "******" # Webserver already enabled web_port = { "setting": "services.webserverport" } result = get_setting_value.execute(web_port) try: self.xbmc_port = result['result']['value'] except (TypeError, KeyError): pass web_user = { "setting": "services.webserverusername" } result = get_setting_value.execute(web_user) try: self.xbmc_username = result['result']['value'] except (TypeError, KeyError): pass web_pass = { "setting": "services.webserverpassword" } result = get_setting_value.execute(web_pass) try: self.xbmc_password = result['result']['value'] except (TypeError, KeyError): pass
def remove_from_playlist(cls, position): params = {'playlistid': 1, 'position': position} log.debug(JSONRPC('Playlist.Remove').execute(params))
def verify_playlist(cls): log.debug(JSONRPC('Playlist.GetItems').execute({'playlistid': 1}))