def add_items(self, items=None, pagination=True, parent_params=None, property_params=None, kodi_db=None, cache_only=True):
        if not items:
            return
        check_is_aired = parent_params.get('info') not in NO_LABEL_FORMATTING
        hide_nodate = ADDON.getSettingBool('nodate_is_unaired')

        # Pre-game details and artwork cache for seasons/episodes before threading to avoid multiple API calls
        ftv_art = None
        if parent_params.get('info') in ['seasons', 'episodes', 'episode_groups', 'trakt_upnext']:
            details = self.tmdb_api.get_details('tv', parent_params.get('tmdb_id'), parent_params.get('season', 0), cache_only=cache_only)
            ftv_art = self.get_ftv_artwork(ListItem(parent_params=parent_params, **details))

        # Build empty queue and thread pool
        self.items_queue, pool = [None] * len(items), [None] * len(items)

        # Start item build threads
        for x, i in enumerate(items):
            if not pagination and 'next_page' in i:
                continue
            if self.item_is_excluded(i):
                continue
            li = ListItem(parent_params=parent_params, **i)
            pool[x] = Thread(target=self._add_item, args=[x, li, cache_only, ftv_art])
            pool[x].start()

        # Wait to join threads in pool first before adding item to directory
        for x, i in enumerate(pool):
            if not i:
                continue
            i.join()
            li = self.items_queue[x]
            if not li:
                continue
            li.set_episode_label()
            if check_is_aired and li.is_unaired(no_date=hide_nodate):
                continue
            li.set_details(details=self.get_kodi_details(li), reverse=True)  # Quick because local db
            li.set_playcount(playcount=self.get_playcount_from_trakt(li))  # Quick because of agressive caching of Trakt object and pre-emptive dict comprehension
            if self.hide_watched and try_int(li.infolabels.get('playcount')) != 0:
                continue
            li.set_cast()
            li.set_context_menu()  # Set the context menu items
            li.set_uids_to_info()  # Add unique ids to properties so accessible in skins
            li.set_thumb_to_art(self.thumb_override == 2) if self.thumb_override else None
            li.set_params_reroute(self.ftv_forced_lookup, self.flatten_seasons)  # Reroute details to proper end point
            li.set_params_to_info(self.plugin_category)  # Set path params to properties for use in skins
            li.infoproperties.update(property_params or {})
            if self.thumb_override:
                li.infolabels.pop('dbid', None)  # Need to pop the DBID if overriding thumb otherwise Kodi overrides after item is created
            xbmcplugin.addDirectoryItem(
                handle=self.handle,
                url=li.get_url(),
                listitem=li.get_listitem(),
                isFolder=li.is_folder)
Esempio n. 2
0
 def select_player(self,
                   detailed=True,
                   clear_player=False,
                   header=ADDON.getLocalizedString(32042)):
     """ Returns user selected player via dialog - detailed bool switches dialog style """
     dialog_players = [] if not clear_player else [{
         'name':
         ADDON.getLocalizedString(32311),
         'plugin_name':
         'plugin.video.themoviedb.helper',
         'plugin_icon':
         u'{}/resources/icons/other/kodi.png'.format(ADDONPATH)
     }]
     dialog_players += self.dialog_players
     players = [
         ListItem(label=i.get('name'),
                  label2=u'{} v{}'.format(
                      i.get('plugin_name'),
                      xbmcaddon.Addon(i.get('plugin_name',
                                            '')).getAddonInfo('version')),
                  art={
                      'thumb': i.get('plugin_icon')
                  }).get_listitem() for i in dialog_players
     ]
     x = xbmcgui.Dialog().select(header, players, useDetails=detailed)
     if x == -1:
         return {}
     player = dialog_players[x]
     player['idx'] = x
     return player
 def add_items(self, items=None, pagination=True, parent_params=None, property_params=None, kodi_db=None, tmdb_cache_only=True):
     if not items:
         return
     check_is_aired = parent_params.get('info') not in NO_LABEL_FORMATTING
     for i in items:
         if not pagination and 'next_page' in i:
             continue
         if self.item_is_excluded(i):
             continue
         li = ListItem(parent_params=parent_params, **i)
         li.set_details(details=self.get_tmdb_details(li, cache_only=tmdb_cache_only))  # Quick because only get cached
         li.set_episode_label()
         if check_is_aired and li.is_unaired():
             continue
         li.set_details(details=self.get_ftv_artwork(li), reverse=True)  # Slow when not cache only
         li.set_details(details=self.get_kodi_details(li), reverse=True)  # Quick because local db
         li.set_playcount(playcount=self.get_playcount_from_trakt(li))  # Quick because of agressive caching of Trakt object and pre-emptive dict comprehension
         if self.hide_watched and try_int(li.infolabels.get('playcount')) != 0:
             continue
         li.set_context_menu()  # Set the context menu items
         li.set_uids_to_info()  # Add unique ids to properties so accessible in skins
         li.set_params_reroute(self.ftv_forced_lookup, self.flatten_seasons)  # Reroute details to proper end point
         li.set_params_to_info(self.plugin_category)  # Set path params to properties for use in skins
         li.infoproperties.update(property_params or {})
         xbmcplugin.addDirectoryItem(
             handle=self.handle,
             url=li.get_url(),
             listitem=li.get_listitem(),
             isFolder=li.is_folder)
Esempio n. 4
0
def resolve_to_dummy(handle=None, stop_after=1, delay_wait=0):
    """
    Kodi does 5x retries to resolve url if isPlayable property is set - strm files force this property.
    However, external plugins might not resolve directly to URL and instead might require PlayMedia.
    Also, if external plugin endpoint is a folder we need to do ActivateWindow/Container.Update instead.
    Passing False to setResolvedUrl doesn't work correctly and the retry is triggered anyway.
    In these instances we use a hack to avoid the retry by first resolving to a dummy file instead.
    """
    # If we don't have a handle there's nothing to resolve
    if handle is None:
        return

    # Set our dummy resolved url
    path = u'{}/resources/dummy.mp4'.format(ADDONPATH)
    kodi_log(['lib.player.players - attempt to resolve dummy file\n', path], 1)
    xbmcplugin.setResolvedUrl(handle, True, ListItem(path=path).get_listitem())

    # Wait till our file plays and then stop after setting duration
    if wait_for_player(to_start='dummy.mp4', stop_after=stop_after) <= 0:
        kodi_log(['lib.player.players - resolving dummy file timeout\n', path], 1)
        return -1

    # Wait for our file to stop before continuing
    if wait_for_player() <= 0:
        kodi_log(['lib.player.players - stopping dummy file timeout\n', path], 1)
        return -1

    # Added delay
    with busy_dialog(False if delay_wait < 1 else True):
        xbmc.Monitor().waitForAbort(delay_wait)

    # Success
    kodi_log(['lib.player.players -- successfully resolved dummy file\n', path], 1)
Esempio n. 5
0
def get_item_details(tmdb_type, tmdb_id, season=None, episode=None):
    details = TMDb().get_details(tmdb_type, tmdb_id, season, episode)
    if not details:
        return
    details = ListItem(**details)
    details.infolabels['mediatype'] == 'movie' if tmdb_type == 'movie' else 'episode'
    details.set_details(details=get_external_ids(details, season=season, episode=episode))
    return details
Esempio n. 6
0
    def _player_dialog_select(self, folder, auto=False):
        d_items = []
        for f in folder:

            # Skip items without labels as probably not worth playing
            if not f.get('label') or f.get('label') == 'None':
                continue

            # Get the label of the item
            label_a = f.get('label')

            # Add year to our label if exists and not special value of 1601
            if f.get('year') and f.get('year') != 1601:
                label_a = u'{} ({})'.format(label_a, f.get('year'))

            # Add season and episode numbers to label
            if try_int(f.get('season', 0)) > 0 and try_int(f.get('episode', 0)) > 0:
                label_a = u'{}x{}. {}'.format(f.get('season'), f.get('episode'), label_a)

            # Add various stream details to ListItem.Label2 (aka label_b)
            label_b_list = []
            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'):
                    label_b_list.append(u'{}x{}'.format(sdv.get('width'), sdv.get('height')))
                if sdv.get('codec'):
                    label_b_list.append(u'{}'.format(sdv.get('codec', '').upper()))
                if sda.get('codec'):
                    label_b_list.append(u'{}'.format(sda.get('codec', '').upper()))
                if sda.get('channels'):
                    label_b_list.append(u'{} CH'.format(sda.get('channels', '')))
                for i in sda_list:
                    if i.get('language'):
                        label_b_list.append(u'{}'.format(i.get('language', '').upper()))
                if sdv.get('duration'):
                    label_b_list.append(u'{} mins'.format(try_int(sdv.get('duration', 0)) // 60))
            if f.get('size'):
                label_b_list.append(u'{}'.format(normalise_filesize(f.get('size', 0))))
            label_b = ' | '.join(label_b_list) if label_b_list else ''

            # Add item to select dialog list
            d_items.append(ListItem(label=label_a, label2=label_b, art={'thumb': f.get('thumbnail')}).get_listitem())

        if not d_items:
            return -1  # No items so ask user to select new player

        # If autoselect enabled and only 1 item choose that otherwise ask user to choose
        idx = 0 if auto and len(d_items) == 1 else xbmcgui.Dialog().select(ADDON.getLocalizedString(32236), d_items, useDetails=True)

        if idx == -1:
            return  # User exited the dialog so return nothing

        is_folder = False if folder[idx].get('filetype') == 'file' else True
        return (folder[idx].get('file'), is_folder)  # Return the player
def get_item_details(tmdb_type, tmdb_id, season=None, episode=None, language=None):
    tmdb_api = TMDb(language=language) if language else TMDb()
    details = tmdb_api.get_details(tmdb_type, tmdb_id, season, episode)
    del tmdb_api
    if not details:
        return
    details = ListItem(**details)
    details.infolabels['mediatype'] == 'movie' if tmdb_type == 'movie' else 'episode'
    details.set_details(details=get_external_ids(details, season=season, episode=episode))
    return details
Esempio n. 8
0
 def get_tmdb_id_from_query(self, tmdb_type, query, header=None, use_details=False, get_listitem=False, auto_single=False):
     if not query or not tmdb_type:
         return
     response = self.get_tmdb_id(tmdb_type, query=query, raw_data=True)
     items = [ListItem(**self.mapper.get_info(i, tmdb_type)).get_listitem() for i in response]
     if not items:
         return
     x = 0
     if not auto_single or len(items) != 1:
         x = xbmcgui.Dialog().select(header, items, useDetails=use_details)
     if x != -1:
         return items[x] if get_listitem else items[x].getUniqueID('tmdb')
def _get_dialog_players(players):
    return [
        ListItem(
            label=v.get('name'),
            label2=k,
            art={
                'thumb':
                v.get('icon', '').format(ADDONPATH)
                or xbmcaddon.Addon(v.get('plugin', '')).getAddonInfo('icon')
            }).get_listitem() for k, v in
        sorted(viewitems(players),
               key=lambda i: try_int(i[1].get('priority')) or PLAYERS_PRIORITY)
    ]
Esempio n. 10
0
    def select_artwork(self, ftv_id, ftv_type, container_refresh=True, blacklist=[]):
        if ftv_type not in ['movies', 'tv']:
            return
        with busy_dialog():
            artwork = self.get_artwork_request(ftv_id, ftv_type)
        if not artwork:
            return xbmcgui.Dialog().notification('FanartTV', ADDON.getLocalizedString(32217).format(ftv_type, ftv_id))

        # Choose Type
        _artwork_types = ['poster', 'fanart', 'clearart', 'clearlogo', 'landscape', 'banner']
        _artwork_types.append('discart' if ftv_type == 'movies' else 'characterart')
        artwork_types = [i for i in _artwork_types if i not in blacklist]  # Remove types that we previously looked for
        choice = xbmcgui.Dialog().select(xbmc.getLocalizedString(13511), artwork_types)
        if choice == -1:
            return

        # Get artwork of user's choosing
        artwork_type = artwork_types[choice]
        artwork_items = self.get_artwork(ftv_id, ftv_type, artwork_type, get_list=True)

        # If there was not artwork of that type found then blacklist it before re-prompting
        if not artwork_items:
            xbmcgui.Dialog().notification('FanartTV', ADDON.getLocalizedString(32217).format(ftv_type, ftv_id))
            blacklist.append(artwork_types[choice])
            return self.select_artwork(ftv_id, ftv_type, container_refresh, blacklist)

        # Choose artwork from options
        items = [
            ListItem(
                label=i.get('url'),
                label2=ADDON.getLocalizedString(32219).format(i.get('lang', ''), i.get('likes', 0), i.get('id', '')),
                art={'thumb': i.get('url')}).get_listitem() for i in artwork_items if i.get('url')]
        choice = xbmcgui.Dialog().select(xbmc.getLocalizedString(13511), items, useDetails=True)
        if choice == -1:  # If user hits back go back to main menu rather than exit completely
            return self.select_artwork(ftv_id, ftv_type, container_refresh, blacklist)

        # Cache our choice as the best artwork forever since it was selected manually
        # Some types have have HD and SD variants so set cache for both
        for i in ARTWORK_TYPES.get(ftv_type, {}).get(artwork_type, []):
            success = self._cache.set_cache(
                artwork_items[choice].get('url'),
                cache_name=u'FanartTV.best.{}.{}.{}.{}'.format(self.language, ftv_id, ftv_type, i),
                cache_days=10000)
        if success and container_refresh:
            xbmc.executebuiltin('Container.Refresh')
            xbmc.executebuiltin('UpdateLibrary(video,/fake/path/to/force/refresh/on/home)')
    def add_items(self, items=None, pagination=True, parent_params=None, property_params=None, kodi_db=None, tmdb_cache_only=True):
        if not items:
            return
        self.check_is_aired = parent_params.get('info') not in NO_LABEL_FORMATTING

        # Build empty queue and thread pool
        self.items_queue, pool = [None] * len(items), [None] * len(items)

        # Start item build threads
        for x, i in enumerate(items):
            if not pagination and 'next_page' in i:
                continue
            if self.item_is_excluded(i):
                continue
            li = ListItem(parent_params=parent_params, **i)
            pool[x] = Thread(target=self._add_item, args=[x, li, tmdb_cache_only])
            pool[x].start()

        # Wait to join threads in pool first before adding item to directory
        for x, i in enumerate(pool):
            if not i:
                continue
            i.join()
            li = self.items_queue[x]
            if not li:
                continue
            li.set_episode_label()
            if self.check_is_aired and li.is_unaired():
                return
            li.set_details(details=self.get_kodi_details(li), reverse=True)  # Quick because local db
            li.set_playcount(playcount=self.get_playcount_from_trakt(li))  # Quick because of agressive caching of Trakt object and pre-emptive dict comprehension
            if self.hide_watched and try_int(li.infolabels.get('playcount')) != 0:
                continue
            li.set_context_menu()  # Set the context menu items
            li.set_uids_to_info()  # Add unique ids to properties so accessible in skins
            li.set_params_reroute(self.ftv_forced_lookup, self.flatten_seasons)  # Reroute details to proper end point
            li.set_params_to_info(self.plugin_category)  # Set path params to properties for use in skins
            li.infoproperties.update(property_params or {})
            xbmcplugin.addDirectoryItem(
                handle=self.handle,
                url=li.get_url(),
                listitem=li.get_listitem(),
                isFolder=li.is_folder)
Esempio n. 12
0
def _get_ftv_id(**kwargs):
    details = refresh_details(confirm=False, **kwargs)
    if not details:
        return
    return ListItem(**details).get_ftv_id()