def plugin_widgetlisting(pluginpath, sublevel=""):
    '''get all nodes in a plugin listing'''
    widgets = []
    if sublevel:
        media_array = kodi_json('Files.GetDirectory', {
            "directory": pluginpath,
            "media": "files"
        })
    else:
        if not getCondVisibility("System.HasAddon(%s)" % pluginpath):
            return []
        media_array = kodi_json('Files.GetDirectory', {
            "directory": "plugin://%s" % pluginpath,
            "media": "files"
        })
    for item in media_array:
        log_msg("skinshortcuts widgets processing: %s" % (item["file"]))
        content = item["file"]
        label = item["label"]
        # extendedinfo has some login-required widgets, skip those
        if ("script.extendedinfo" in pluginpath and not EXTINFO_CREDS
                and ("info=starred" in content or "info=rated" in content
                     or "info=account" in content)):
            continue
        if item.get("filetype", "") == "file":
            continue
        mutils = MetadataUtils()
        media_type = mutils.detect_plugin_content(item["file"])
        del mutils
        if media_type == "empty":
            continue
        if media_type == "folder":
            content = "plugin://script.skin.helper.service?action=widgets&path=%s&sublevel=%s" % (
                urlencode(item["file"]), label)
        # add reload param for widgets
        if "reload=" not in content:
            if "movies" in content:
                reloadstr = "&reload=$INFO[Window(Home).Property(widgetreload-movies)]"
            elif "episodes" in content:
                reloadstr = "&reload=$INFO[Window(Home).Property(widgetreload-episodes)]"
            elif "tvshows" in content:
                reloadstr = "&reload=$INFO[Window(Home).Property(widgetreload-tvshows)]"
            elif "musicvideos" in content:
                reloadstr = "&reload=$INFO[Window(Home).Property(widgetreload-musicvideos)]"
            elif "albums" in content or "songs" in content or "artists" in content:
                reloadstr = "&reload=$INFO[Window(Home).Property(widgetreload-music)]"
            else:
                reloadstr = "&reload=$INFO[Window(Home).Property(widgetreload)]"\
                    "$INFO[Window(Home).Property(widgetreload2)]"
            content = content + reloadstr
        content = content.replace("&limit=100", "&limit=25")
        widgets.append([label, content, media_type])
        if pluginpath == "script.extendedinfo" and not sublevel:
            # some additional entrypoints for extendedinfo...
            widgets += extendedinfo_youtube_widgets()
    return widgets
    def getcast(self):
        '''helper to get all cast for a given media item'''
        db_id = None
        all_cast = []
        all_cast_names = list()
        cache_str = ""
        download_thumbs = self.params.get("downloadthumbs", "") == "true"
        extended_cast_action = self.params.get("castaction",
                                               "") == "extendedinfo"
        movie = self.params.get("movie")
        tvshow = self.params.get("tvshow")
        episode = self.params.get("episode")
        movieset = self.params.get("movieset")

        try:  # try to parse db_id
            if movieset:
                cache_str = "movieset.castcache-%s-%s" % (
                    self.params["movieset"], download_thumbs)
                db_id = int(movieset)
            elif tvshow:
                cache_str = "tvshow.castcache-%s-%s" % (self.params["tvshow"],
                                                        download_thumbs)
                db_id = int(tvshow)
            elif movie:
                cache_str = "movie.castcache-%s-%s" % (self.params["movie"],
                                                       download_thumbs)
                db_id = int(movie)
            elif episode:
                cache_str = "episode.castcache-%s-%s" % (
                    self.params["episode"], download_thumbs)
                db_id = int(episode)
        except Exception:
            pass

        cachedata = self.cache.get(cache_str)
        if cachedata:
            # get data from cache
            all_cast = cachedata
        else:
            # retrieve data from json api...
            if movie and db_id:
                all_cast = self.mutils.kodidb.movie(db_id)["cast"]
            elif movie and not db_id:
                filters = [{
                    "operator": "is",
                    "field": "title",
                    "value": movie
                }]
                result = self.mutils.kodidb.movies(filters=filters)
                all_cast = result[0]["cast"] if result else []
            elif tvshow and db_id:
                all_cast = self.mutils.kodidb.tvshow(db_id)["cast"]
            elif tvshow and not db_id:
                filters = [{
                    "operator": "is",
                    "field": "title",
                    "value": tvshow
                }]
                result = self.mutils.kodidb.tvshows(filters=filters)
                all_cast = result[0]["cast"] if result else []
            elif episode and db_id:
                all_cast = self.mutils.kodidb.episode(db_id)["cast"]
            elif episode and not db_id:
                filters = [{
                    "operator": "is",
                    "field": "title",
                    "value": episode
                }]
                result = self.mutils.kodidb.episodes(filters=filters)
                all_cast = result[0]["cast"] if result else []
            elif movieset:
                if not db_id:
                    for item in self.mutils.kodidb.moviesets():
                        if item["title"].lower() == movieset.lower():
                            db_id = item["setid"]
                if db_id:
                    json_result = self.mutils.kodidb.movieset(
                        db_id, include_set_movies_fields=["cast"])
                    if "movies" in json_result:
                        for movie in json_result['movies']:
                            all_cast += movie['cast']

            # optional: download missing actor thumbs
            if all_cast and download_thumbs:
                for cast in all_cast:
                    if cast.get("thumbnail"):
                        cast["thumbnail"] = self.mutils.get_clean_image(
                            cast.get("thumbnail"))
                    if not cast.get("thumbnail"):
                        artwork = self.mutils.tmdb.get_actor(cast["name"])
                        cast["thumbnail"] = artwork.get("thumb", "")
            # lookup tmdb if item is requested that is not in local db
            if not all_cast:
                tmdbdetails = {}
                if movie and not db_id:
                    tmdbdetails = self.mutils.tmdb.search_movie(movie)
                elif tvshow and not db_id:
                    tmdbdetails = self.mutils.tmdb.search_tvshow(tvshow)
                if tmdbdetails.get("cast"):
                    all_cast = tmdbdetails["cast"]
            # save to cache
            self.cache.set(cache_str, all_cast)

        # process listing with the results...
        for cast in all_cast:
            if cast.get("name") not in all_cast_names:
                liz = xbmcgui.ListItem(label=cast.get("name"),
                                       label2=cast.get("role"))
                liz.setArt({"thumb": cast.get("thumbnail")})
                if extended_cast_action:
                    url = "RunScript(script.extendedinfo,info=extendedactorinfo,name=%s)" % cast.get(
                        "name")
                    url = "plugin://script.skin.helper.service/?action=launch&path=%s" % url
                    is_folder = False
                else:
                    url = "RunScript(script.skin.helper.service,action=getcastmedia,name=%s)" % cast.get(
                        "name")
                    url = "plugin://script.skin.helper.service/?action=launch&path=%s" % urlencode(
                        url)
                    is_folder = False
                all_cast_names.append(cast.get("name"))
                liz.setArt({"thumb": cast.get("thumbnail")})
                xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),
                                            url=url,
                                            listitem=liz,
                                            isFolder=is_folder)
        xbmcplugin.endOfDirectory(int(sys.argv[1]))
    def update_backgrounds(self):
        '''update all our provided backgrounds'''

        # conditional background
        self.win.setProperty("SkinHelper.ConditionalBackground",
                             get_cond_background())

        # movies backgrounds
        if xbmc.getCondVisibility("Library.HasContent(movies)"):
            # random/all movies
            self.set_background("SkinHelper.AllMoviesBackground",
                                "videodb://movies/titles/",
                                label=32010)
            # in progress movies
            self.set_background(
                "SkinHelper.InProgressMoviesBackground",
                "videodb://movies/titles/?xsp=%s" % urlencode(
                    '{"limit":50,"order":{"direction":"ascending","method":"random"},'
                    '"rules":{"and":[{"field":"inprogress","operator":"true","value":[]}]},"type":"movies"}'
                ),
                label=32012)
            # recent movies
            self.set_background("SkinHelper.RecentMoviesBackground",
                                "videodb://recentlyaddedmovies/",
                                label=32011)
            # unwatched movies
            self.set_background(
                "SkinHelper.UnwatchedMoviesBackground",
                "videodb://movies/titles/?xsp=%s" % urlencode(
                    '{"limit":50,"order":{"direction":"ascending","method":"random"},'
                    '"rules":{"and":[{"field":"playcount","operator":"is","value":0}]},"type":"movies"}'
                ),
                label=32013)

        # tvshows backgrounds
        if xbmc.getCondVisibility("Library.HasContent(tvshows)"):
            # random/all tvshows
            self.set_background("SkinHelper.AllTvShowsBackground",
                                "videodb://tvshows/titles/",
                                label=32014)
            # in progress tv shows
            self.set_background(
                "SkinHelper.InProgressShowsBackground",
                "videodb://tvshows/titles/?xsp=%s" % urlencode(
                    '{"limit":50,"order":{"direction":"ascending","method":"random"},'
                    '"rules":{"and":[{"field":"inprogress","operator":"true","value":[]}]},"type":"tvshows"}'
                ),
                label=32016)
            # recent episodes
            self.set_background("SkinHelper.RecentEpisodesBackground",
                                "videodb://recentlyaddedepisodes/",
                                label=32015)

        # all musicvideos
        if xbmc.getCondVisibility("Library.HasContent(musicvideos)"):
            self.set_background("SkinHelper.AllMusicVideosBackground",
                                "videodb://musicvideos/titles",
                                label=32018)

        # all music
        if xbmc.getCondVisibility("Library.HasContent(music)"):
            # music artists
            self.set_background("SkinHelper.AllMusicBackground",
                                "musicdb://artists/",
                                label=32019)
            # recent albums
            self.set_background("SkinHelper.RecentMusicBackground",
                                "musicdb://recentlyaddedalbums/",
                                label=32023)
            # random songs
            self.set_background("SkinHelper.AllMusicSongsBackground",
                                "musicdb://songs/",
                                label=32022)

        # tmdb backgrounds (extendedinfo)
        if xbmc.getCondVisibility("System.HasAddon(script.extendedinfo)"):
            self.set_background(
                "SkinHelper.TopRatedMovies",
                "plugin://script.extendedinfo/?info=topratedmovies",
                label=32020)
            self.set_background(
                "SkinHelper.TopRatedShows",
                "plugin://script.extendedinfo/?info=topratedtvshows",
                label=32021)

        # pictures background
        self.set_background("SkinHelper.PicturesBackground",
                            "pictures",
                            label=32017)

        # pvr background
        if xbmc.getCondVisibility("PVR.HasTvChannels"):
            self.set_background("SkinHelper.PvrBackground", "pvr", label=32024)

        # smartshortcuts backgrounds
        for node in self.smartshortcuts.get_smartshortcuts_nodes():
            self.set_background(node[0], node[1], label=node[2])

        # global backgrounds
        self.set_global_background("SkinHelper.GlobalFanartBackground", [
            "SkinHelper.AllMoviesBackground",
            "SkinHelper.AllTvShowsBackground",
            "SkinHelper.AllMusicVideosBackground",
            "SkinHelper.AllMusicBackground"
        ],
                                   label=32009)
        self.set_global_background("SkinHelper.AllVideosBackground", [
            "SkinHelper.AllMoviesBackground",
            "SkinHelper.AllTvShowsBackground",
            "SkinHelper.AllMusicVideosBackground"
        ],
                                   label=32025)
        self.set_global_background("SkinHelper.AllVideosBackground2", [
            "SkinHelper.AllMoviesBackground", "SkinHelper.AllTvShowsBackground"
        ],
                                   label=32026)
        self.set_global_background("SkinHelper.RecentVideosBackground", [
            "SkinHelper.RecentMoviesBackground",
            "SkinHelper.RecentEpisodesBackground"
        ],
                                   label=32027)
        self.set_global_background("SkinHelper.InProgressVideosBackground", [
            "SkinHelper.InProgressMoviesBackground",
            "SkinHelper.InProgressShowsBackground"
        ],
                                   label=32028)