def play_external(self, playerindex=-1, force_dialog=False): playerindex = self.player_getnewindex(playerindex, force_dialog=force_dialog) # User cancelled dialog if not playerindex > -1: utils.kodi_log(u'Player -- User cancelled', 2) return False # Run through player actions player = self.player_resolveurl(self.actions[playerindex]) # Previous player failed so ask user to select a new one if player == -1: return self.play_external(playerindex, force_dialog=force_dialog) # Play/Search found item if player and player[1]: action = string_format_map(player[1], self.item) if player[0] and (action.endswith('.strm') or self.identifierlist[playerindex] == 'play_kodi'): # Action is play and is a strm/local so PlayMedia utils.kodi_log(u'Player -- Found strm or local.\nAttempting PLAYMEDIA({})'.format(action), 1) xbmc.executebuiltin(utils.try_decode_string(u'PlayMedia(\"{0}\")'.format(action))) elif player[0]: # Action is play and not a strm so play with player utils.kodi_log(u'Player -- Found file.\nAttempting to PLAY: {}'.format(action), 2) xbmcgui.Window(10000).setProperty('TMDbHelper.PlayerInfoString', self.playerstring) if self.playerstring else None xbmc.Player().play(action, ListItem(library='video', **self.details).set_listitem()) else: action = u'Container.Update({0})'.format(action) if xbmc.getCondVisibility("Window.IsMedia") else u'ActivateWindow(videos,{0},return)'.format(action) utils.kodi_log(u'Player -- Found folder.\nAttempting to OPEN: {}'.format(action), 2) xbmc.executebuiltin(utils.try_encode_string(utils.try_decode_string(action))) return action
def set_url_props(self, url, prefix='Item'): for k, v in url.items(): if not k or not v: continue try: self.infoproperties[u'{}.{}'.format( prefix, utils.try_decode_string(k))] = u'{}'.format( utils.try_decode_string(v)) except Exception as exc: utils.kodi_log( u'ERROR in ListItem set_url_props\nk:{} v:{}'.format( utils.try_decode_string(k), utils.try_decode_string(v)), 1) utils.kodi_log(exc, 1)
def action(action, tmdb_id=None, tmdb_type=None, season=None, episode=None, label=None, cache_refresh=False): _traktapi = TraktAPI() if action == 'history': func = _traktapi.sync_history elif action == 'collection': func = _traktapi.sync_collection elif action == 'watchlist': func = _traktapi.sync_watchlist elif action == 'add_to_userlist': return sync_userlist() elif action == 'remove_from_userlist': return sync_userlist(remove_item=True) elif action == 'library_userlist': return library_userlist() elif action == 'library': return library() elif action == 'play': return play() elif action == 'open': return browse() else: return with utils.busy_dialog(): if tmdb_type == 'episode' and (not season or not episode): return elif tmdb_id and tmdb_type: dbtype = utils.type_convert(tmdb_type, 'dbtype') label = label or 'this {}'.format(utils.type_convert(tmdb_type, 'trakt')) else: label = sys.listitem.getLabel() dbtype = sys.listitem.getVideoInfoTag().getMediaType() tmdb_id = sys.listitem.getProperty('tmdb_id') if not dbtype == 'episode' else sys.listitem.getProperty('tvshow.tmdb_id') season = sys.listitem.getVideoInfoTag().getSeason() if dbtype == 'episode' else None episode = sys.listitem.getVideoInfoTag().getEpisode() if dbtype == 'episode' else None tmdb_type = 'movie' if dbtype == 'movie' else 'tv' trakt_ids = func(utils.type_convert(tmdb_type, 'trakt'), 'tmdb', cache_refresh=cache_refresh) boolean = 'remove' if int(tmdb_id) in trakt_ids else 'add' dialog_header = 'Trakt {0}'.format(action.capitalize()) dialog_text = xbmcaddon.Addon().getLocalizedString(32065) if boolean == 'add' else xbmcaddon.Addon().getLocalizedString(32064) dialog_text = dialog_text.format(utils.try_decode_string(label), action.capitalize(), tmdb_type, tmdb_id) dialog_text = dialog_text + ' Season: {} Episode: {}'.format(season, episode) if dbtype == 'episode' else dialog_text if not xbmcgui.Dialog().yesno(dialog_header, dialog_text): return with utils.busy_dialog(): trakt_type = 'episode' if dbtype == 'episode' else utils.type_convert(tmdb_type, 'trakt') slug_type = 'show' if dbtype == 'episode' else trakt_type slug = _traktapi.get_traktslug(slug_type, 'tmdb', tmdb_id) item = _traktapi.get_details(slug_type, slug, season=season, episode=episode) items = {trakt_type + 's': [item]} func(slug_type, mode=boolean, items=items) dialog_header = 'Trakt {0}'.format(action.capitalize()) dialog_text = xbmcaddon.Addon().getLocalizedString(32062) if boolean == 'add' else xbmcaddon.Addon().getLocalizedString(32063) dialog_text = dialog_text.format(tmdb_id, action.capitalize()) xbmcgui.Dialog().ok(dialog_header, dialog_text) xbmc.executebuiltin('Container.Refresh')
def get_cur_item(self): self.dbtype = self.get_dbtype() self.dbid = self.get_infolabel('DBID') self.imdb_id = self.get_infolabel('IMDBNumber') self.query = self.get_infolabel('TvShowTitle') or self.get_infolabel('Title') or self.get_infolabel('Label') self.year = self.get_infolabel('year') self.season = self.get_infolabel('Season') if self.dbtype == 'episodes' else '' self.episode = self.get_infolabel('Episode') if self.dbtype == 'episodes' else '' self.query = utils.try_decode_string(self.query) return u'{0}.{1}.{2}.{3}.{4}'.format(self.imdb_id, self.query, self.year, self.season, self.episode)
def add_query(self): with utils.busy_dialog(): query = utils.try_decode_string(self.params.get('add_query', '')) item = utils.dialog_select_item(query) if not item: return tmdb_id = self.tmdb.get_tmdb_id(self.params.get('type'), query=item, selectdialog=True) if not tmdb_id: utils.kodi_log(u'Unable to find TMDb ID!\nQuery: {0} Type: {1}'.format(self.params.get('add_query'), self.params.get('type')), 1) return url = 'plugin://plugin.video.skin.info.provider/?info=details&type={0}&tmdb_id={1}'.format(self.params.get('type'), tmdb_id) if url == self.home.getProperty(self.prefixcurrent): return # Already added so let's quit as user probably clicked twice self.position = self.get_position() + 1 self.set_props(self.position, url) self.lock_path(self.params.get('prevent_del')) self.call_auto()
def get_playingitem(self): if not self.isPlayingVideo(): return # Not a video so don't get info if self.getVideoInfoTag().getMediaType() not in ['movie', 'episode']: return # Not a movie or episode so don't get info TODO Maybe get PVR details also? self.playerstring = _homewindow.getProperty('TMDbHelper.PlayerInfoString') self.playerstring = loads(self.playerstring) if self.playerstring else None self.totaltime = self.getTotalTime() self.dbtype = self.getVideoInfoTag().getMediaType() self.dbid = self.getVideoInfoTag().getDbId() self.imdb_id = self.getVideoInfoTag().getIMDBNumber() self.query = self.getVideoInfoTag().getTVShowTitle() if self.dbtype == 'episode' else self.getVideoInfoTag().getTitle() self.year = self.getVideoInfoTag().getYear() if self.dbtype == 'movie' else None self.season = self.getVideoInfoTag().getSeason() if self.dbtype == 'episodes' else None self.episode = self.getVideoInfoTag().getEpisode() if self.dbtype == 'episodes' else None self.query = utils.try_decode_string(self.query) self.tmdbtype = 'movie' if self.dbtype == 'movie' else 'tv' self.tmdb_id = self.get_tmdb_id(self.tmdbtype, self.imdb_id, self.query, self.year) self.details = self.tmdb.get_detailed_item(self.tmdbtype, self.tmdb_id, season=self.season, episode=self.episode) if not self.details: return self.reset_properties() # No self.details so lets clear everything if xbmc.getCondVisibility("!Skin.HasSetting(TMDbHelper.DisableRatings)"): self.details = self.get_omdb_ratings(self.details) self.details = self.get_top250_rank(self.details) if self.tmdbtype == 'movie' else self.details self.details = self.get_trakt_ratings(self.details, self.tmdbtype, self.tmdb_id, self.season, self.episode) if self.tmdbtype in ['movie', 'tv'] else self.details self.set_iter_properties(self.details.get('infoproperties', {}), _setprop_ratings) if xbmc.getCondVisibility("!Skin.HasSetting(TMDbHelper.DisableArtwork)"): self.details = self.get_fanarttv_artwork(self.details, self.tmdbtype) if self.addon.getSettingBool('service_fanarttv_lookup') else self.details self.details = self.get_kodi_artwork(self.details, self.dbtype, self.dbid) if self.addon.getSettingBool('local_db') else self.details self.set_iter_properties(self.details, _setmain_artwork) self.set_properties(self.details)
def play_external(self, force_dialog=False, playerindex=-1): if playerindex > -1: # Previous iteration didn't find an item to play so remove it and retry xbmcgui.Dialog().notification( self.itemlist[playerindex].getLabel(), self.addon.getLocalizedString(32040)) del self.actions[ playerindex] # Item not found so remove the player's action list del self.itemlist[ playerindex] # Item not found so remove the player's select dialog entry del self.identifierlist[ playerindex] # Item not found so remove the player's index playerindex = self.get_playerindex(force_dialog=force_dialog) # User cancelled dialog if not playerindex > -1: return False player = self.actions[playerindex] if not player or not player[1]: return False # External player has list of actions so let's iterate through them to find our item resolve_url = False if isinstance(player[1], list): actionlist = player[1] player = (False, actionlist[0]) for d in actionlist[1:]: if player[0]: break # Playable item was found in last action so let's break and play it folder = KodiLibrary().get_directory( string_format_map( player[1], self.item)) # Get the next folder from the plugin if d.get( 'dialog' ): # Special option to show dialog of items to select from d_items = [] for f in folder: # Create our list of items if not f.get('label') or f.get('label') == 'None': continue lb_list = [] label_a = f.get('label') if f.get('year') and f.get('year') != 1601: label_a = u'{} ({})'.format(label_a, f.get('year')) if utils.try_parse_int(f.get( 'season', 0)) > 0 and utils.try_parse_int( f.get('episode', 0)) > 0: label_a = u'{}x{}. {}'.format( f.get('season'), f.get('episode'), label_a) if f.get('streamdetails'): sdv_list = f.get('streamdetails', {}).get( 'video', [{}]) or [{}] sda_list = f.get('streamdetails', {}).get( 'audio', [{}]) or [{}] sdv, sda = sdv_list[0], sda_list[0] if sdv.get('width') or sdv.get('height'): lb_list.append(u'{}x{}'.format( sdv.get('width'), sdv.get('height'))) if sdv.get('codec'): lb_list.append(u'{}'.format( sdv.get('codec', '').upper())) if sda.get('codec'): lb_list.append(u'{}'.format( sda.get('codec', '').upper())) if sda.get('channels'): lb_list.append(u'{} CH'.format( sda.get('channels', ''))) for i in sda_list: if i.get('language'): lb_list.append(u'{}'.format( i.get('language', '').upper())) if sdv.get('duration'): lb_list.append(u'{} mins'.format( utils.try_parse_int(sdv.get('duration', 0)) // 60)) if f.get('size'): lb_list.append(u'{}'.format( utils.normalise_filesize(f.get('size', 0)))) label_b = ' | '.join(lb_list) if lb_list else '' d_items.append( ListItem(label=label_a, label2=label_b, icon=f.get('thumbnail')).set_listitem()) if d_items: idx = 0 if d.get('dialog', '').lower() != 'auto' or len(d_items) != 1: idx = xbmcgui.Dialog().select('Select Item', d_items, useDetails=True) if idx == -1: # User exited the dialog so return and do nothing return resolve_url = True if folder[idx].get( 'filetype' ) == 'file' else False # Set true for files so we can play player = (resolve_url, folder[idx].get('file') ) # Set the folder path to open/play break # Move onto next action else: # Ask user to select a different player if no items in dialog return self.play_external(force_dialog=force_dialog, playerindex=playerindex) x = 0 for f in folder: # Iterate through plugin folder looking for a matching item x += 1 # Keep an index for position matching for k, v in d.items( ): # Iterate through our key (infolabel) / value (infolabel must match) pairs of our action if k == 'position': # We're looking for an item position not an infolabel if utils.try_parse_int( string_format_map(v, self.item) ) != x: # Format our position value break # Not the item position we want so let's go to next item in folder elif not f.get(k) or string_format_map( v, self.item ) not in u'{}'.format( f.get(k, '') ): # Format our value and check if it matches the infolabel key break # Item's key value doesn't match value we are looking for so let's got to next item in folder else: # Item matched our criteria so let's open it up resolve_url = True if f.get( 'filetype' ) == 'file' else False # Set true for files so we can play player = (resolve_url, f.get('file') ) # Get ListItem.FolderPath for item break # Move onto next action (either open next folder or play file) else: return self.play_external( force_dialog=force_dialog, playerindex=playerindex ) # Ask user to select a different player # Play/Search found item if player and player[1]: action = string_format_map(player[1], self.item) if player[0] and action.endswith( '.strm'): # Action is play and is a strm so PlayMedia xbmc.executebuiltin( utils.try_decode_string(u'PlayMedia({0})'.format(action))) elif player[ 0]: # Action is play and not a strm so play with player xbmc.Player().play( action, ListItem(library='video', **self.details).set_listitem()) else: action = u'Container.Update({0})'.format( action) if xbmc.getCondVisibility( "Window.IsMedia" ) else u'ActivateWindow(videos,{0},return)'.format(action) xbmc.executebuiltin(utils.try_decode_string(action)) return action
def action(action, tmdb_id=None, tmdb_type=None, season=None, episode=None, label=None): _traktapi = TraktAPI() if action == 'history': func = _traktapi.sync_history elif action == 'collection': func = _traktapi.sync_collection elif action == 'watchlist': func = _traktapi.sync_watchlist elif action == 'add_to_userlist': return sync_userlist() elif action == 'remove_from_userlist': return sync_userlist(remove_item=True) elif action == 'library_userlist': return library_userlist() elif action == 'library': return library() elif action == 'refresh_item': return refresh_item() elif action == 'play': return play() elif action == 'open': return browse() else: return with utils.busy_dialog(): if tmdb_id and tmdb_type: # Passed details via script dbtype = utils.type_convert(tmdb_type, 'dbtype') label = label or 'this {}'.format(utils.type_convert(tmdb_type, 'trakt')) parent_tmdb_id = tmdb_id else: # Context menu so retrieve details from listitem label = sys.listitem.getLabel() dbtype = sys.listitem.getVideoInfoTag().getMediaType() tmdb_id = sys.listitem.getProperty('tmdb_id') parent_tmdb_id = sys.listitem.getProperty('tvshow.tmdb_id') if dbtype == 'episode' else tmdb_id season = sys.listitem.getVideoInfoTag().getSeason() if dbtype == 'episode' else None episode = sys.listitem.getVideoInfoTag().getEpisode() if dbtype == 'episode' else None if tmdb_type == 'episode': # Passed episode details via script if not season or not episode: # Need season and episode for episodes return # Need season and episode if run from script so leave # Retrieve episode details so that we can get tmdb_id for episode episode_details = _plugin.tmdb.get_detailed_item(tmdb_type, parent_tmdb_id, season=season, episode=episode) tmdb_id = episode_details.get('infoproperties', {}).get('imdb_id') if dbtype == 'movie': tmdb_type = 'movie' elif dbtype == 'tvshow': tmdb_type = 'tv' elif dbtype == 'episode': tmdb_type = 'episode' else: return # Check if we're adding or removing the item and confirm with the user that they want to do that trakt_ids = func(utils.type_convert(tmdb_type, 'trakt'), 'tmdb', cache_refresh=True) boolean = 'remove' if int(tmdb_id) in trakt_ids else 'add' dialog_header = 'Trakt {0}'.format(action.capitalize()) dialog_text = xbmcaddon.Addon().getLocalizedString(32065) if boolean == 'add' else xbmcaddon.Addon().getLocalizedString(32064) dialog_text = dialog_text.format(utils.try_decode_string(label), action.capitalize(), tmdb_type, tmdb_id) dialog_text = dialog_text + ' Season: {} Episode: {}'.format(season, episode) if dbtype == 'episode' else dialog_text if not xbmcgui.Dialog().yesno(dialog_header, dialog_text): return with utils.busy_dialog(): slug_type = 'show' if tmdb_type == 'episode' else utils.type_convert(tmdb_type, 'trakt') trakt_type = utils.type_convert(tmdb_type, 'trakt') slug = _traktapi.get_traktslug(slug_type, 'tmdb', parent_tmdb_id) item = _traktapi.get_details(slug_type, slug, season=season, episode=episode) items = {trakt_type + 's': [item]} func(slug_type, mode=boolean, items=items) dialog_header = 'Trakt {0}'.format(action.capitalize()) dialog_text = xbmcaddon.Addon().getLocalizedString(32062) if boolean == 'add' else xbmcaddon.Addon().getLocalizedString(32063) dialog_text = dialog_text.format(tmdb_id, action.capitalize()) xbmcgui.Dialog().ok(dialog_header, dialog_text) xbmc.executebuiltin('Container.Refresh')
def play_external(self, force_dialog=False): itemindex = self.get_itemindex(force_dialog=force_dialog) # User cancelled dialog if not itemindex > -1: return False player = self.actions[itemindex] if not player or not player[1]: return False # External player has list of actions so let's iterate through them to find our item resolve_url = False if isinstance(player[1], list): actionlist = player[1] player = (False, actionlist[0]) with utils.busy_dialog(): for d in actionlist[1:]: if player[0]: break # Playable item was found in last action so let's break and play it folder = KodiLibrary().get_directory( string_format_map( player[1], self.item)) # Get the next folder from the plugin x = 0 for f in folder: # Iterate through plugin folder looking for a matching item x += 1 # Keep an index for position matching for k, v in d.items( ): # Iterate through our key (infolabel) / value (infolabel must match) pairs of our action if k == 'position': # We're looking for an item position not an infolabel if utils.try_parse_int( string_format_map(v, self.item) ) != x: # Format our position value break # Not the item position we want so let's go to next item in folder elif not f.get(k) or string_format_map( v, self.item ) not in u'{}'.format( f.get(k, '') ): # Format our value and check if it matches the infolabel key break # Item's key value doesn't match value we are looking for so let's got to next item in folder else: # Item matched our criteria so let's open it up resolve_url = True if f.get( 'filetype' ) == 'file' else False # Set true for files so we can play player = (resolve_url, f.get('file') ) # Get ListItem.FolderPath for item break # Move onto next action (either open next folder or play file) else: xbmcgui.Dialog().notification( self.itemlist[itemindex].getLabel(), self.addon.getLocalizedString(32040)) del self.actions[ itemindex] # Item not found so remove the player's action list del self.itemlist[ itemindex] # Item not found so remove the player's select dialog entry return self.play_external( force_dialog=True ) # Ask user to select a different player # Play/Search found item if player and player[1]: action = string_format_map(player[1], self.item) if player[0]: # Action is play so let's play the item and return xbmc.Player().play( action, ListItem(library='video', **self.details).set_listitem()) return action # Action is search so let's load the plugin path action = u'Container.Update({0})'.format( action) if xbmc.getCondVisibility( "Window.IsMedia" ) else u'ActivateWindow(videos,{0},return)'.format(action) xbmc.executebuiltin(utils.try_decode_string(action)) return action