Beispiel #1
0
def ListEmbeddedSubsForItemMenu(**kwargs):
    rating_key = kwargs["rating_key"]
    part_id = kwargs["part_id"]
    title = kwargs["title"]
    kwargs.pop("randomize")

    oc = SubFolderObjectContainer(title2=title, replace_parent=True)

    oc.add(
        DirectoryObject(key=Callback(ItemDetailsMenu,
                                     rating_key=kwargs["rating_key"],
                                     item_title=kwargs["item_title"],
                                     base_title=kwargs["base_title"],
                                     title=kwargs["item_title"],
                                     randomize=timestamp()),
                        title=u"< Back to %s" % kwargs["title"],
                        thumb=default_thumb))

    plex_item = get_item(rating_key)
    part = get_part(plex_item, part_id)

    if part:
        for stream_data in get_embedded_subtitle_streams(
                part, skip_duplicate_unknown=False):
            language = stream_data["language"]
            is_unknown = stream_data["is_unknown"]
            stream = stream_data["stream"]
            is_forced = stream_data["is_forced"]

            if language:
                oc.add(
                    DirectoryObject(
                        key=Callback(TriggerExtractEmbeddedSubForItemMenu,
                                     randomize=timestamp(),
                                     stream_index=str(stream.index),
                                     language=language,
                                     with_mods=True,
                                     **kwargs),
                        title=u"Extract stream %s, "
                        u"%s%s%s%s with default mods" %
                        (stream.index, display_language(language),
                         " (unknown)" if is_unknown else "",
                         " (forced)" if is_forced else "",
                         " (\"%s\")" % stream.title if stream.title else ""),
                    ))
                oc.add(
                    DirectoryObject(
                        key=Callback(TriggerExtractEmbeddedSubForItemMenu,
                                     randomize=timestamp(),
                                     stream_index=str(stream.index),
                                     language=language,
                                     **kwargs),
                        title=u"Extract stream %s, %s%s%s%s" %
                        (stream.index, display_language(language),
                         " (unknown)" if is_unknown else "",
                         " (forced)" if is_forced else "",
                         " (\"%s\")" % stream.title if stream.title else ""),
                    ))
    return oc
Beispiel #2
0
def ListEmbeddedSubsForItemMenu(**kwargs):
    rating_key = kwargs["rating_key"]
    part_id = kwargs["part_id"]
    title = kwargs["title"]
    kwargs.pop("randomize")

    oc = SubFolderObjectContainer(title2=title, replace_parent=True)

    oc.add(DirectoryObject(
        key=Callback(ItemDetailsMenu, rating_key=kwargs["rating_key"], item_title=kwargs["item_title"],
                     base_title=kwargs["base_title"], title=kwargs["item_title"], randomize=timestamp()),
        title=_("< Back to %s", kwargs["title"]),
        thumb=default_thumb
    ))

    plex_item = get_item(rating_key)
    part = get_part(plex_item, part_id)

    if part:
        for stream_data in get_embedded_subtitle_streams(part, skip_duplicate_unknown=False):
            language = stream_data["language"]
            is_unknown = stream_data["is_unknown"]
            stream = stream_data["stream"]
            is_forced = stream_data["is_forced"]

            if language:
                oc.add(DirectoryObject(
                    key=Callback(TriggerExtractEmbeddedSubForItemMenu, randomize=timestamp(),
                                 stream_index=str(stream.index), language=language, with_mods=True, **kwargs),
                    title=_(u"Extract stream %(stream_index)s, %(language)s%(unknown_state)s%(forced_state)s"
                            u"%(stream_title)s with default mods",
                            stream_index=stream.index,
                            language=display_language(language),
                            unknown_state=_(" (unknown)") if is_unknown else "",
                            forced_state=_(" (forced)") if is_forced else "",
                            stream_title=" (\"%s\")" % stream.title if stream.title else ""),
                ))
                oc.add(DirectoryObject(
                    key=Callback(TriggerExtractEmbeddedSubForItemMenu, randomize=timestamp(),
                                 stream_index=str(stream.index), language=language, **kwargs),
                    title=_(u"Extract stream %(stream_index)s, %(language)s%(unknown_state)s%(forced_state)s"
                            u"%(stream_title)s",
                            stream_index=stream.index,
                            language=display_language(language),
                            unknown_state=_(" (unknown)") if is_unknown else "",
                            forced_state=_(" (forced)") if is_forced else "",
                            stream_title=" (\"%s\")" % stream.title if stream.title else ""),
                ))
    return oc
Beispiel #3
0
def HistoryMenu():
    from support.history import get_history
    history = get_history()
    oc = SubFolderObjectContainer(title2=_("History"), replace_parent=True)

    for item in history.items[:100]:
        possible_language = item.language
        language_display = item.lang_name if not possible_language else display_language(
            possible_language)

        oc.add(
            DirectoryObject(key=Callback(ItemDetailsMenu,
                                         title=item.title,
                                         item_title=item.item_title,
                                         rating_key=item.rating_key),
                            title=u"%s (%s)" %
                            (item.item_title, _(item.mode_verbose)),
                            summary=_(u"%s in %s (%s, score: %s), %s",
                                      language_display, item.section_title,
                                      _(item.provider_name), item.score,
                                      df(item.time)),
                            thumb=item.thumb or default_thumb))

    history.destroy()

    return oc
def ListStoredSubsForItemMenu(**kwargs):
    oc = SubFolderObjectContainer(title2=unicode(kwargs["title"]), replace_parent=True)
    rating_key = kwargs["rating_key"]
    part_id = kwargs["part_id"]
    language = Language.fromietf(kwargs["language"])

    current_sub, stored_subs, storage = get_current_sub(rating_key, part_id, language)
    all_subs = stored_subs.get_all(part_id, language)
    kwargs.pop("randomize")

    for key, subtitle in sorted(filter(lambda x: x[0] != "current", all_subs.items()),
                                key=lambda x: x[1].date_added, reverse=True):
        is_current = key == all_subs["current"]

        summary = u"added: %s, %s, Language: %s, Score: %i, Storage: %s" % \
                  (df(subtitle.date_added),
                   subtitle.mode_verbose, display_language(language), subtitle.score,
                   subtitle.storage_type)

        sub_name = subtitle.provider_name
        if sub_name == "embedded":
            sub_name += " (%s)" % subtitle.id

        oc.add(DirectoryObject(
            key=Callback(SelectStoredSubForItemMenu, randomize=timestamp(), sub_key="__".join(key), **kwargs),
            title=u"%s%s, Score: %s" % ("Current: " if is_current else "Stored: ", sub_name,
                                        subtitle.score),
            summary=summary
        ))

    return oc
def ManageBlacklistMenu(**kwargs):
    oc = SubFolderObjectContainer(title2=unicode(kwargs["title"]),
                                  replace_parent=True)
    rating_key = kwargs["rating_key"]
    part_id = kwargs["part_id"]
    language = kwargs["language"]
    remove_sub_key = kwargs.pop("remove_sub_key", None)
    current_data = unicode(kwargs["current_data"])

    current_sub, stored_subs, storage = get_current_sub(
        rating_key, part_id, language)
    current_bl, subs = stored_subs.get_blacklist(part_id, language)

    if remove_sub_key:
        remove_sub_key = tuple(remove_sub_key.split("__"))
        stored_subs.blacklist(part_id, language, remove_sub_key, add=False)
        storage.save(stored_subs)
        Log.Info("Removed %s from blacklist", remove_sub_key)

    kwargs.pop("randomize")

    oc.add(
        DirectoryObject(key=Callback(ItemDetailsMenu,
                                     rating_key=kwargs["rating_key"],
                                     item_title=kwargs["item_title"],
                                     title=kwargs["title"],
                                     randomize=timestamp()),
                        title=_(u"< Back to %s", kwargs["title"]),
                        summary=current_data,
                        thumb=default_thumb))

    def sorter(pair):
        # thanks RestrictedModule parser for messing with lambda (x, y)
        return pair[1]["date_added"]

    for sub_key, data in sorted(current_bl.iteritems(),
                                key=sorter,
                                reverse=True):
        provider_name, subtitle_id = sub_key
        title = _(
            u"%(provider_name)s, %(subtitle_id)s (added: %(date_added)s, %(mode)s), Language: %(language)s, "
            u"Score: %(score)i, Storage: %(storage_type)s",
            provider_name=provider_name,
            subtitle_id=subtitle_id,
            date_added=df(data["date_added"]),
            mode=current_sub.get_mode_verbose(data["mode"]),
            language=display_language(Language.fromietf(language)),
            score=data["score"],
            storage_type=data["storage_type"])
        oc.add(
            DirectoryObject(key=Callback(ManageBlacklistMenu,
                                         remove_sub_key="__".join(sub_key),
                                         randomize=timestamp(),
                                         **kwargs),
                            title=title,
                            summary=_(u"Remove subtitle from blacklist")))

    storage.destroy()

    return oc
Beispiel #6
0
def ManageBlacklistMenu(**kwargs):
    oc = SubFolderObjectContainer(title2=unicode(kwargs["title"]), replace_parent=True)
    rating_key = kwargs["rating_key"]
    part_id = kwargs["part_id"]
    language = kwargs["language"]
    remove_sub_key = kwargs.pop("remove_sub_key", None)
    current_data = unicode(kwargs["current_data"])

    current_sub, stored_subs, storage = get_current_sub(rating_key, part_id, language)
    current_bl, subs = stored_subs.get_blacklist(part_id, language)

    if remove_sub_key:
        remove_sub_key = tuple(remove_sub_key.split("__"))
        stored_subs.blacklist(part_id, language, remove_sub_key, add=False)
        storage.save(stored_subs)
        Log.Info("Removed %s from blacklist", remove_sub_key)

    kwargs.pop("randomize")

    oc.add(DirectoryObject(
        key=Callback(ItemDetailsMenu, rating_key=kwargs["rating_key"], item_title=kwargs["item_title"],
                     title=kwargs["title"], randomize=timestamp()),
        title=_(u"< Back to %s", kwargs["title"]),
        summary=current_data,
        thumb=default_thumb
    ))

    def sorter(pair):
        # thanks RestrictedModule parser for messing with lambda (x, y)
        return pair[1]["date_added"]

    for sub_key, data in sorted(current_bl.iteritems(), key=sorter, reverse=True):
        provider_name, subtitle_id = sub_key
        title = _(u"%(provider_name)s, %(subtitle_id)s (added: %(date_added)s, %(mode)s), Language: %(language)s, "
                  u"Score: %(score)i, Storage: %(storage_type)s",
                  provider_name=_(provider_name),
                  subtitle_id=subtitle_id,
                  date_added=df(data["date_added"]),
                  mode=_(current_sub.get_mode_verbose(data["mode"])),
                  language=display_language(Language.fromietf(language)),
                  score=data["score"],
                  storage_type=data["storage_type"])
        oc.add(DirectoryObject(
            key=Callback(ManageBlacklistMenu, remove_sub_key="__".join(sub_key), randomize=timestamp(), **kwargs),
            title=title,
            summary=_(u"Remove subtitle from blacklist")
        ))

    storage.destroy()

    return oc
Beispiel #7
0
def RecentMissingSubtitlesMenu(force=False, randomize=None):
    title = _("Items with missing subtitles")
    oc = SubFolderObjectContainer(title2=title, no_cache=True, no_history=True)

    running = scheduler.is_task_running("MissingSubtitles")
    task_data = scheduler.get_task_data("MissingSubtitles")
    missing_items = task_data["missing_subtitles"] if task_data else None

    if ((missing_items is None) or force) and not running:
        scheduler.dispatch_task("MissingSubtitles")
        running = True

    if not running:
        oc.add(
            DirectoryObject(
                key=Callback(RecentMissingSubtitlesMenu,
                             force=True,
                             randomize=timestamp()),
                title=_(u"Find recent items with missing subtitles"),
                thumb=default_thumb))
    else:
        oc.add(
            DirectoryObject(key=Callback(RecentMissingSubtitlesMenu,
                                         force=False,
                                         randomize=timestamp()),
                            title=_(u"Updating, refresh here ..."),
                            thumb=default_thumb))

    if missing_items is not None:
        for added_at, item_id, item_title, item, missing_languages in missing_items:
            oc.add(
                DirectoryObject(key=Callback(ItemDetailsMenu,
                                             title=title + " > " + item_title,
                                             item_title=item_title,
                                             rating_key=item_id),
                                title=item_title,
                                summary=_(
                                    "Missing: %s", ", ".join(
                                        display_language(l)
                                        for l in missing_languages)),
                                thumb=get_item_thumb(item) or default_thumb))

    return oc
Beispiel #8
0
def HistoryMenu():
    from support.history import get_history
    history = get_history()
    oc = SubFolderObjectContainer(title2=_("History"), replace_parent=True)

    for item in history.items[:100]:
        possible_language = item.language
        language_display = item.lang_name if not possible_language else display_language(possible_language)

        oc.add(DirectoryObject(
            key=Callback(ItemDetailsMenu, title=item.title, item_title=item.item_title,
                         rating_key=item.rating_key),
            title=u"%s (%s)" % (item.item_title, _(item.mode_verbose)),
            summary=_(u"%s in %s (%s, score: %s), %s", language_display, item.section_title,
                                                       _(item.provider_name), item.score, df(item.time)),
            thumb=item.thumb or default_thumb
        ))

    history.destroy()

    return oc
Beispiel #9
0
def RecentMissingSubtitlesMenu(force=False, randomize=None):
    title = _("Items with missing subtitles")
    oc = SubFolderObjectContainer(title2=title, no_cache=True, no_history=True)

    running = scheduler.is_task_running("MissingSubtitles")
    task_data = scheduler.get_task_data("MissingSubtitles")
    missing_items = task_data["missing_subtitles"] if task_data else None

    if ((missing_items is None) or force) and not running:
        scheduler.dispatch_task("MissingSubtitles")
        running = True

    if not running:
        oc.add(DirectoryObject(
            key=Callback(RecentMissingSubtitlesMenu, force=True, randomize=timestamp()),
            title=_(u"Find recent items with missing subtitles"),
            thumb=default_thumb
        ))
    else:
        oc.add(DirectoryObject(
            key=Callback(RecentMissingSubtitlesMenu, force=False, randomize=timestamp()),
            title=_(u"Updating, refresh here ..."),
            thumb=default_thumb
        ))

    if missing_items is not None:
        for added_at, item_id, item_title, item, missing_languages in missing_items:
            oc.add(DirectoryObject(
                key=Callback(ItemDetailsMenu, title=title + " > " + item_title, item_title=item_title,
                             rating_key=item_id),
                title=item_title,
                summary=_("Missing: %s", ", ".join(display_language(l) for l in missing_languages)),
                thumb=get_item_thumb(item) or default_thumb
            ))

    return oc
Beispiel #10
0
def ListStoredSubsForItemMenu(**kwargs):
    oc = SubFolderObjectContainer(title2=unicode(kwargs["title"]), replace_parent=True)
    rating_key = kwargs["rating_key"]
    part_id = kwargs["part_id"]
    language = Language.fromietf(kwargs["language"])

    current_sub, stored_subs, storage = get_current_sub(rating_key, part_id, language)
    all_subs = stored_subs.get_all(part_id, language)
    kwargs.pop("randomize")

    for key, subtitle in sorted(filter(lambda x: x[0] not in ("current", "blacklist"), all_subs.items()),
                                key=lambda x: x[1].date_added, reverse=True):
        is_current = key == all_subs["current"]

        summary = _(u"added: %(date_added)s, %(mode)s, Language: %(language)s, Score: %(score)i, Storage: "
                    u"%(storage_type)s",
                    date_added=df(subtitle.date_added),
                    mode=_(subtitle.mode_verbose),
                    language=display_language(language),
                    score=subtitle.score,
                    storage_type=subtitle.storage_type)

        sub_name = subtitle.provider_name
        if sub_name == "embedded":
            sub_name += " (%s)" % subtitle.id

        oc.add(DirectoryObject(
            key=Callback(SelectStoredSubForItemMenu, randomize=timestamp(), sub_key="__".join(key), **kwargs),
            title=_(u"%(current_state)s%(subtitle_name)s, Score: %(score)s",
                    current_state=_("Current: ") if is_current else _("Stored: "),
                    subtitle_name=sub_name,
                    score=subtitle.score),
            summary=summary
        ))

    return oc
def ListAvailableSubsForItemMenu(rating_key=None, part_id=None, title=None, item_title=None, filename=None,
                                 item_type="episode", language=None, language_name=None, force=False, current_id=None,
                                 current_data=None,
                                 current_provider=None, current_score=None, randomize=None):
    assert rating_key, part_id

    running = scheduler.is_task_running("AvailableSubsForItem")
    search_results = get_item_task_data("AvailableSubsForItem", rating_key, language)

    if (search_results is None or force) and not running:
        scheduler.dispatch_task("AvailableSubsForItem", rating_key=rating_key, item_type=item_type, part_id=part_id,
                                language=language)
        running = True

    oc = SubFolderObjectContainer(title2=unicode(title), replace_parent=True)
    oc.add(DirectoryObject(
        key=Callback(ItemDetailsMenu, rating_key=rating_key, item_title=item_title, title=title, randomize=timestamp()),
        title=u"< Back to %s" % title,
        summary=current_data,
        thumb=default_thumb
    ))

    metadata = get_plex_metadata(rating_key, part_id, item_type)
    plex_part = None
    if not config.low_impact_mode:
        scanned_parts = scan_videos([metadata], ignore_all=True)

        if not scanned_parts:
            Log.Error("Couldn't list available subtitles for %s", rating_key)
            return oc

        video, plex_part = scanned_parts.items()[0]

        video_display_data = [video.format] if video.format else []
        if video.release_group:
            video_display_data.append(u"by %s" % video.release_group)
        video_display_data = " ".join(video_display_data)
    else:
        video_display_data = metadata["filename"]

    current_display = (u"Current: %s (%s) " % (current_provider, current_score) if current_provider else "")
    if not running:
        oc.add(DirectoryObject(
            key=Callback(ListAvailableSubsForItemMenu, rating_key=rating_key, item_title=item_title, language=language,
                         filename=filename, part_id=part_id, title=title, current_id=current_id, force=True,
                         current_provider=current_provider, current_score=current_score,
                         current_data=current_data, item_type=item_type, randomize=timestamp()),
            title=u"Search for %s subs (%s)" % (get_language(language).name, video_display_data),
            summary=u"%sFilename: %s" % (current_display, filename),
            thumb=default_thumb
        ))

        if search_results == "found_none":
            oc.add(DirectoryObject(
                key=Callback(ListAvailableSubsForItemMenu, rating_key=rating_key, item_title=item_title,
                             language=language, filename=filename, current_data=current_data, force=True,
                             part_id=part_id, title=title, current_id=current_id, item_type=item_type,
                             current_provider=current_provider, current_score=current_score,
                             randomize=timestamp()),
                title=u"No subtitles found",
                summary=u"%sFilename: %s" % (current_display, filename),
                thumb=default_thumb
            ))
    else:
        oc.add(DirectoryObject(
            key=Callback(ListAvailableSubsForItemMenu, rating_key=rating_key, item_title=item_title,
                         language=language, filename=filename, current_data=current_data,
                         part_id=part_id, title=title, current_id=current_id, item_type=item_type,
                         current_provider=current_provider, current_score=current_score,
                         randomize=timestamp()),
            title=u"Searching for %s subs (%s), refresh here ..." % (display_language(get_language(language)),
                                                                     video_display_data),
            summary=u"%sFilename: %s" % (current_display, filename),
            thumb=default_thumb
        ))

    if not search_results or search_results == "found_none":
        return oc

    current_sub, stored_subs, storage = get_current_sub(rating_key, part_id, language)
    current_bl, subs = stored_subs.get_blacklist(part_id, language)

    seen = []
    for subtitle in search_results:
        if subtitle.id in seen:
            continue

        bl_addon = ""
        if (str(subtitle.provider_name), str(subtitle.id)) in current_bl:
            bl_addon = "Blacklisted "

        wrong_fps_addon = ""
        if subtitle.wrong_fps:
            if plex_part:
                wrong_fps_addon = " (wrong FPS, sub: %s, media: %s)" % (subtitle.fps, plex_part.fps)
            else:
                wrong_fps_addon = " (wrong FPS, sub: %s, media: unknown, low impact mode)" % subtitle.fps

        oc.add(DirectoryObject(
            key=Callback(TriggerDownloadSubtitle, rating_key=rating_key, randomize=timestamp(), item_title=item_title,
                         subtitle_id=str(subtitle.id), language=language),
            title=u"%s%s: %s, score: %s%s" % (bl_addon, "Available" if current_id != subtitle.id else "Current",
                                              subtitle.provider_name, subtitle.score, wrong_fps_addon),
            summary=u"Release: %s, Matches: %s" % (subtitle.release_info, ", ".join(subtitle.matches)),
            thumb=default_thumb
        ))

        seen.append(subtitle.id)

    return oc
def ItemDetailsMenu(rating_key, title=None, base_title=None, item_title=None, randomize=None, header=None):
    """
    displays the item details menu of an item that doesn't contain any deeper tree, such as a movie or an episode
    :param rating_key:
    :param title:
    :param base_title:
    :param item_title:
    :param randomize:
    :return:
    """
    from interface.main import IgnoreMenu

    title = unicode(base_title) + " > " + unicode(title) if base_title else unicode(title)
    item = plex_item = get_item(rating_key)
    current_kind = get_item_kind_from_rating_key(rating_key)

    timeout = 30

    oc = SubFolderObjectContainer(title2=title, replace_parent=True, header=header)

    if not item:
        oc.add(DirectoryObject(
            key=Callback(ItemDetailsMenu, rating_key=rating_key, title=title, base_title=base_title,
                         item_title=item_title, randomize=timestamp()),
            title=u"Item not found: %s!" % item_title,
            summary="Plex didn't return any information about the item, please refresh it and come back later",
            thumb=default_thumb
        ))
        return oc

    # add back to season for episode
    if current_kind == "episode":
        from interface.menu import MetadataMenu
        show = get_item(item.show.rating_key)
        season = get_item(item.season.rating_key)

        oc.add(DirectoryObject(
            key=Callback(MetadataMenu, rating_key=season.rating_key, title=season.title, base_title=show.title,
                         previous_item_type="show", previous_rating_key=show.rating_key,
                         display_items=True, randomize=timestamp()),
            title=u"< Back to %s" % season.title,
            summary="Back to %s > %s" % (show.title, season.title),
            thumb=season.thumb or default_thumb
        ))

    oc.add(DirectoryObject(
        key=Callback(RefreshItem, rating_key=rating_key, item_title=item_title, randomize=timestamp(),
                     timeout=timeout * 1000),
        title=u"Refresh: %s" % item_title,
        summary="Refreshes the %s, possibly searching for missing and picking up new subtitles on disk" % current_kind,
        thumb=item.thumb or default_thumb
    ))
    oc.add(DirectoryObject(
        key=Callback(RefreshItem, rating_key=rating_key, item_title=item_title, force=True, randomize=timestamp(),
                     timeout=timeout * 1000),
        title=u"Force-find subtitles: %s" % item_title,
        summary="Issues a forced refresh, ignoring known subtitles and searching for new ones",
        thumb=item.thumb or default_thumb
    ))

    # get stored subtitle info for item id
    subtitle_storage = get_subtitle_storage()
    stored_subs = subtitle_storage.load_or_new(item)

    # look for subtitles for all available media parts and all of their languages
    has_multiple_parts = len(plex_item.media) > 1
    part_index = 0
    for media in plex_item.media:
        for part in media.parts:
            filename = os.path.basename(part.file)
            if not os.path.exists(part.file):
                continue

            part_id = str(part.id)
            part_index += 1

            part_index_addon = ""
            part_summary_addon = ""
            if has_multiple_parts:
                part_index_addon = u"File %s: " % part_index
                part_summary_addon = "%s " % filename

            # iterate through all configured languages
            for lang in config.lang_list:
                # get corresponding stored subtitle data for that media part (physical media item), for language
                current_sub = stored_subs.get_any(part_id, lang)
                current_sub_id = None
                current_sub_provider_name = None

                summary = u"%sNo current subtitle in storage" % part_summary_addon
                current_score = None
                if current_sub:
                    current_sub_id = current_sub.id
                    current_sub_provider_name = current_sub.provider_name
                    current_score = current_sub.score

                    summary = u"%sCurrent subtitle: %s (added: %s, %s), Language: %s, Score: %i, Storage: %s" % \
                              (part_summary_addon, current_sub.provider_name, df(current_sub.date_added),
                               current_sub.mode_verbose, display_language(lang), current_sub.score,
                               current_sub.storage_type)

                    oc.add(DirectoryObject(
                        key=Callback(SubtitleOptionsMenu, rating_key=rating_key, part_id=part_id, title=title,
                                     item_title=item_title, language=lang, language_name=display_language(lang),
                                     current_id=current_sub_id,
                                     item_type=plex_item.type, filename=filename, current_data=summary,
                                     randomize=timestamp(), current_provider=current_sub_provider_name,
                                     current_score=current_score),
                        title=u"%sManage %s subtitle" % (part_index_addon, display_language(lang)),
                        summary=summary
                    ))
                else:
                    oc.add(DirectoryObject(
                        key=Callback(ListAvailableSubsForItemMenu, rating_key=rating_key, part_id=part_id, title=title,
                                     item_title=item_title, language=lang, language_name=display_language(lang),
                                     current_id=current_sub_id,
                                     item_type=plex_item.type, filename=filename, current_data=summary,
                                     randomize=timestamp(), current_provider=current_sub_provider_name,
                                     current_score=current_score),
                        title=u"%sList %s subtitles" % (part_index_addon, display_language(lang)),
                        summary=summary
                    ))

            if config.plex_transcoder:
                # embedded subtitles
                embedded_count = 0
                embedded_langs = []
                for stream in part.streams:
                    # subtitle stream
                    if stream.stream_type == 3 and not stream.stream_key and stream.codec in TEXT_SUBTITLE_EXTS:
                        lang = get_language_from_stream(stream.language_code)

                        if not lang and config.treat_und_as_first:
                            lang = list(config.lang_list)[0]

                        if lang:
                            embedded_langs.append(lang)
                            embedded_count += 1

                if embedded_count:
                    oc.add(DirectoryObject(
                        key=Callback(ListEmbeddedSubsForItemMenu, rating_key=rating_key, part_id=part_id, title=title,
                                     item_type=plex_item.type, item_title=item_title, base_title=base_title,
                                     randomize=timestamp()),
                        title=u"%sEmbedded subtitles (%s)" % (part_index_addon, ", ".join(display_language(l) for l in
                                                                                          set(embedded_langs))),
                        summary=u"Extract and activate embedded subtitle streams"
                    ))

    ignore_title = item_title
    if current_kind == "episode":
        ignore_title = get_item_title(item)
    add_ignore_options(oc, "videos", title=ignore_title, rating_key=rating_key, callback_menu=IgnoreMenu)
    subtitle_storage.destroy()

    return oc
def extract_embedded_sub(**kwargs):
    rating_key = kwargs["rating_key"]
    part_id = kwargs.pop("part_id")
    stream_index = kwargs.pop("stream_index")
    with_mods = kwargs.pop("with_mods", False)
    language = Language.fromietf(kwargs.pop("language"))
    refresh = kwargs.pop("refresh", True)
    set_current = kwargs.pop("set_current", True)

    plex_item = kwargs.pop("plex_item", get_item(rating_key))
    item_type = get_item_kind_from_item(plex_item)
    part = kwargs.pop("part", get_part(plex_item, part_id))
    scanned_videos = kwargs.pop("scanned_videos", None)

    any_successful = False

    if part:
        if not scanned_videos:
            metadata = get_plex_metadata(rating_key,
                                         part_id,
                                         item_type,
                                         plex_item=plex_item)
            scanned_videos = scan_videos([metadata],
                                         ignore_all=True,
                                         skip_hashing=True)

        for stream in part.streams:
            # subtitle stream
            if str(stream.index) == stream_index:
                is_forced = is_stream_forced(stream)
                bn = os.path.basename(part.file)

                set_refresh_menu_state(u"Extracting subtitle %s of %s" %
                                       (stream_index, bn))
                Log.Info(u"Extracting stream %s (%s) of %s", stream_index,
                         display_language(language), bn)

                out_codec = stream.codec if stream.codec != "mov_text" else "srt"

                args = [
                    config.plex_transcoder, "-i", part.file, "-map",
                    "0:%s" % stream_index, "-f", out_codec, "-"
                ]
                output = None
                try:
                    output = subprocess.check_output(quote_args(args),
                                                     stderr=subprocess.PIPE,
                                                     shell=True)
                except:
                    Log.Error("Extraction failed: %s", traceback.format_exc())

                if output:
                    subtitle = ModifiedSubtitle(
                        language,
                        mods=config.default_mods if with_mods else None)
                    subtitle.content = output
                    subtitle.provider_name = "embedded"
                    subtitle.id = "stream_%s" % stream_index
                    subtitle.score = 0
                    subtitle.set_encoding("utf-8")

                    # fixme: speedup video; only video.name is needed
                    save_successful = save_subtitles(
                        scanned_videos, {scanned_videos.keys()[0]: [subtitle]},
                        mode="m",
                        set_current=set_current,
                        is_forced=is_forced)
                    set_refresh_menu_state(None)

                    if save_successful and refresh:
                        refresh_item(rating_key)

                    any_successful = True

    return any_successful
Beispiel #14
0
def MetadataMenu(rating_key, title=None, base_title=None, display_items=False, previous_item_type=None,
                 previous_rating_key=None, message=None, header=None, randomize=None):
    """
    displays the contents of a section based on whether it has a deeper tree or not (movies->movie (item) list; series->series list)
    :param rating_key:
    :param title:
    :param base_title:
    :param display_items:
    :param previous_item_type:
    :param previous_rating_key:
    :return:
    """
    title = unicode(title)
    item_title = title
    title = base_title + " > " + title
    oc = SubFolderObjectContainer(title2=title, no_cache=True, no_history=True, header=header, message=message,
                                  view_group="full_details")

    current_kind = get_item_kind_from_rating_key(rating_key)

    if display_items:
        timeout = 30
        show = None

        # add back to series for season
        if current_kind == "season":
            timeout = 720

            show = get_item(previous_rating_key)
            oc.add(DirectoryObject(
                key=Callback(MetadataMenu, rating_key=show.rating_key, title=show.title, base_title=show.section.title,
                             previous_item_type="section", display_items=True, randomize=timestamp()),
                title=_(u"< Back to %s", show.title),
                thumb=show.thumb or default_thumb
            ))
        elif current_kind == "series":
            # it shouldn't take more than 6 minutes to scan all of a series' files and determine the force refresh
            timeout = 3600

        items = get_all_items(key="children", value=rating_key, base="library/metadata")
        kind, deeper = get_items_info(items)
        dig_tree(oc, items, MetadataMenu,
                 pass_kwargs={"base_title": title, "display_items": deeper, "previous_item_type": kind,
                              "previous_rating_key": rating_key})

        # we don't know exactly where we are here, only add ignore option to series
        if current_kind in ("series", "season"):
            item = get_item(rating_key)
            sub_title = get_item_title(item)
            add_ignore_options(oc, current_kind, title=sub_title, rating_key=rating_key, callback_menu=IgnoreMenu)

        # mass-extract embedded
        if current_kind == "season" and config.plex_transcoder:
            for lang in config.lang_list:
                oc.add(DirectoryObject(
                    key=Callback(SeasonExtractEmbedded, rating_key=rating_key, language=lang,
                                 base_title=show.section.title, display_items=display_items, item_title=item_title,
                                 title=title,
                                 previous_item_type=previous_item_type, with_mods=True,
                                 previous_rating_key=previous_rating_key, randomize=timestamp()),
                    title=_(u"Extract missing %(language)s embedded subtitles", language=display_language(lang)),
                    summary=_("Extracts the not yet extracted embedded subtitles of all episodes for the current "
                              "season with all configured default modifications")
                ))
                oc.add(DirectoryObject(
                    key=Callback(SeasonExtractEmbedded, rating_key=rating_key, language=lang,
                                 base_title=show.section.title, display_items=display_items, item_title=item_title,
                                 title=title, force=True,
                                 previous_item_type=previous_item_type, with_mods=True,
                                 previous_rating_key=previous_rating_key, randomize=timestamp()),
                    title=_(u"Extract and activate %(language)s embedded subtitles", language=display_language(lang)),
                    summary=_("Extracts embedded subtitles of all episodes for the current season "
                              "with all configured default modifications")
                ))

        # add refresh
        oc.add(DirectoryObject(
            key=Callback(RefreshItem, rating_key=rating_key, item_title=title, refresh_kind=current_kind,
                         previous_rating_key=previous_rating_key, timeout=timeout * 1000, randomize=timestamp()),
            title=_(u"Refresh: %s", item_title),
            summary=_("Refreshes %(the_movie_series_season_episode)s, possibly searching for missing and picking up "
                      "new subtitles on disk", the_movie_series_season_episode=_(u"the %s" % current_kind))
        ))
        oc.add(DirectoryObject(
            key=Callback(RefreshItem, rating_key=rating_key, item_title=title, force=True,
                         refresh_kind=current_kind, previous_rating_key=previous_rating_key, timeout=timeout * 1000,
                         randomize=timestamp()),
            title=_(u"Auto-Find subtitles: %s", item_title),
            summary=_("Issues a forced refresh, ignoring known subtitles and searching for new ones")
        ))
    else:
        return ItemDetailsMenu(rating_key=rating_key, title=title, item_title=item_title)

    return oc
Beispiel #15
0
def ItemDetailsMenu(rating_key, title=None, base_title=None, item_title=None, randomize=None, header=None,
                    message=None):
    """
    displays the item details menu of an item that doesn't contain any deeper tree, such as a movie or an episode
    :param rating_key:
    :param title:
    :param base_title:
    :param item_title:
    :param randomize:
    :return:
    """
    from interface.main import InclExclMenu

    title = unicode(base_title) + " > " + unicode(title) if base_title else unicode(title)
    item = plex_item = get_item(rating_key)
    current_kind = get_item_kind_from_rating_key(rating_key)

    timeout = 30

    oc = SubFolderObjectContainer(
            title2=title,
            replace_parent=True,
            header=header,
            message=message)

    if not item:
        oc.add(DirectoryObject(
            key=Callback(
                    ItemDetailsMenu,
                    rating_key=rating_key,
                    title=title,
                    base_title=base_title,
                    item_title=item_title,
                    randomize=timestamp()),
            title=_(u"Item not found: %s!", item_title),
            summary=_("Plex didn't return any information about the item, please refresh it and come back later"),
            thumb=default_thumb
        ))
        return oc

    # add back to season for episode
    if current_kind == "episode":
        from interface.menu import MetadataMenu
        show = get_item(item.show.rating_key)
        season = get_item(item.season.rating_key)

        oc.add(DirectoryObject(
            key=Callback(
                    MetadataMenu,
                    rating_key=season.rating_key,
                    title=season.title,
                    base_title=show.title,
                    previous_item_type="show",
                    previous_rating_key=show.rating_key,
                    display_items=True,
                    randomize=timestamp()),
            title=_(u"< Back to %s", season.title),
            summary=_("Back to %s > %s", show.title, season.title),
            thumb=season.thumb or default_thumb
        ))

    oc.add(DirectoryObject(
        key=Callback(
                RefreshItem,
                rating_key=rating_key,
                item_title=item_title,
                randomize=timestamp(),
                timeout=timeout * 1000),
        title=_(u"Refresh: %s", item_title),
        summary=_("Refreshes %(the_movie_series_season_episode)s, possibly searching for missing and picking up "
                  "new subtitles on disk", the_movie_series_season_episode=_(u"the %s" % current_kind)),
        thumb=item.thumb or default_thumb
    ))
    oc.add(DirectoryObject(
        key=Callback(RefreshItem, rating_key=rating_key, item_title=item_title, force=True, randomize=timestamp(),
                     timeout=timeout * 1000),
        title=_(u"Force-find subtitles: %(item_title)s", item_title=item_title),
        summary=_("Issues a forced refresh, ignoring known subtitles and searching for new ones"),
        thumb=item.thumb or default_thumb
    ))

    # get stored subtitle info for item id
    subtitle_storage = get_subtitle_storage()
    stored_subs = subtitle_storage.load_or_new(item)

    # look for subtitles for all available media parts and all of their languages
    has_multiple_parts = len(plex_item.media) > 1
    part_index = 0
    for media in plex_item.media:
        for part in media.parts:
            filename = os.path.basename(part.file)
            if not os.path.exists(part.file):
                continue

            part_id = str(part.id)
            part_index += 1

            part_index_addon = u""
            part_summary_addon = u""
            if has_multiple_parts:
                part_index_addon = _(u"File %(file_part_index)s: ", file_part_index=part_index)
                part_summary_addon = u"%s " % filename

            # iterate through all configured languages
            for lang in config.lang_list:
                # get corresponding stored subtitle data for that media part (physical media item), for language
                current_sub = stored_subs.get_any(part_id, lang)
                current_sub_id = None
                current_sub_provider_name = None

                summary = _(u"%(part_summary)sNo current subtitle in storage", part_summary=part_summary_addon)
                current_score = None
                if current_sub:
                    current_sub_id = current_sub.id
                    current_sub_provider_name = current_sub.provider_name
                    current_score = current_sub.score

                    summary = _(u"%(part_summary)sCurrent subtitle: %(provider_name)s (added: %(date_added)s, "
                                u"%(mode)s), Language: %(language)s, Score: %(score)i, Storage: %(storage_type)s",
                                part_summary=part_summary_addon,
                                provider_name=_(current_sub.provider_name),
                                date_added=df(current_sub.date_added),
                                mode=_(current_sub.mode_verbose),
                                language=display_language(lang),
                                score=current_sub.score,
                                storage_type=current_sub.storage_type)

                    oc.add(DirectoryObject(
                        key=Callback(SubtitleOptionsMenu, rating_key=rating_key, part_id=part_id, title=title,
                                     item_title=item_title, language=lang, language_name=display_language(lang),
                                     current_id=current_sub_id,
                                     item_type=plex_item.type, filename=filename, current_data=summary,
                                     randomize=timestamp(), current_provider=current_sub_provider_name,
                                     current_score=current_score),
                        title=_(u"%(part_summary)sManage %(language)s subtitle", part_summary=part_index_addon,
                                language=display_language(lang)),
                        summary=summary
                    ))
                else:
                    oc.add(DirectoryObject(
                        key=Callback(ListAvailableSubsForItemMenu, rating_key=rating_key, part_id=part_id, title=title,
                                     item_title=item_title, language=lang, language_name=display_language(lang),
                                     current_id=current_sub_id,
                                     item_type=plex_item.type, filename=filename, current_data=summary,
                                     randomize=timestamp(), current_provider=current_sub_provider_name,
                                     current_score=current_score),
                        title=_(u"%(part_summary)sList %(language)s subtitles", part_summary=part_index_addon,
                                language=display_language(lang)),
                        summary=summary
                    ))

            if config.plex_transcoder:
                # embedded subtitles
                embedded_count = 0
                embedded_langs = []
                for stream in part.streams:
                    # subtitle stream
                    if stream.stream_type == 3 and not stream.stream_key and stream.codec in TEXT_SUBTITLE_EXTS:
                        lang = get_language_from_stream(stream.language_code)
                        is_forced = is_stream_forced(stream)

                        if not lang and config.treat_und_as_first:
                            lang = list(config.lang_list)[0]

                        if lang:
                            lang = Language.rebuild(lang, forced=is_forced)
                            embedded_langs.append(lang)
                            embedded_count += 1

                if embedded_count:
                    oc.add(DirectoryObject(
                        key=Callback(ListEmbeddedSubsForItemMenu, rating_key=rating_key, part_id=part_id, title=title,
                                     item_type=plex_item.type, item_title=item_title, base_title=base_title,
                                     randomize=timestamp()),
                        title=_(u"%(part_summary)sEmbedded subtitles (%(languages)s)",
                                part_summary=part_index_addon,
                                languages=", ".join(display_language(l)
                                                    for l in list(OrderedDict.fromkeys(embedded_langs)))),
                        summary=_(u"Extract embedded subtitle streams")
                    ))

    ignore_title = item_title
    if current_kind == "episode":
        ignore_title = get_item_title(item)
    add_incl_excl_options(oc, "videos", title=ignore_title, rating_key=rating_key, callback_menu=InclExclMenu)
    subtitle_storage.destroy()

    return oc
Beispiel #16
0
def ListAvailableSubsForItemMenu(rating_key=None, part_id=None, title=None, item_title=None, filename=None,
                                 item_type="episode", language=None, language_name=None, force=False, current_id=None,
                                 current_data=None,
                                 current_provider=None, current_score=None, randomize=None):
    assert rating_key, part_id

    running = scheduler.is_task_running("AvailableSubsForItem")
    search_results = get_item_task_data("AvailableSubsForItem", rating_key, language)

    current_data = unicode(current_data) if current_data else None

    if (search_results is None or force) and not running:
        scheduler.dispatch_task("AvailableSubsForItem", rating_key=rating_key, item_type=item_type, part_id=part_id,
                                language=language)
        running = True

    oc = SubFolderObjectContainer(title2=unicode(title), replace_parent=True)
    oc.add(DirectoryObject(
        key=Callback(ItemDetailsMenu, rating_key=rating_key, item_title=item_title, title=title, randomize=timestamp()),
        title=_(u"< Back to %s", title),
        summary=current_data,
        thumb=default_thumb
    ))

    metadata = get_plex_metadata(rating_key, part_id, item_type)
    plex_part = None
    if not config.low_impact_mode:
        scanned_parts = scan_videos([metadata], ignore_all=True)

        if not scanned_parts:
            Log.Error("Couldn't list available subtitles for %s", rating_key)
            return oc

        video, plex_part = scanned_parts.items()[0]

        video_display_data = [video.format] if video.format else []
        if video.release_group:
            video_display_data.append(unicode(_(u"by %(release_group)s", release_group=video.release_group)))
        video_display_data = " ".join(video_display_data)
    else:
        video_display_data = metadata["filename"]

    current_display = (_(u"Current: %(provider_name)s (%(score)s) ",
                         provider_name=_(current_provider),
                         score=current_score if current_provider else ""))
    if not running:
        oc.add(DirectoryObject(
            key=Callback(ListAvailableSubsForItemMenu, rating_key=rating_key, item_title=item_title, language=language,
                         filename=filename, part_id=part_id, title=title, current_id=current_id, force=True,
                         current_provider=current_provider, current_score=current_score,
                         current_data=current_data, item_type=item_type, randomize=timestamp()),
            title=_(u"Search for %(language)s subs (%(video_data)s)",
                    language=get_language(language).name,
                    video_data=video_display_data),
            summary=_(u"%(current_info)sFilename: %(filename)s", current_info=current_display, filename=filename),
            thumb=default_thumb
        ))

        if search_results == "found_none":
            oc.add(DirectoryObject(
                key=Callback(ListAvailableSubsForItemMenu, rating_key=rating_key, item_title=item_title,
                             language=language, filename=filename, current_data=current_data, force=True,
                             part_id=part_id, title=title, current_id=current_id, item_type=item_type,
                             current_provider=current_provider, current_score=current_score,
                             randomize=timestamp()),
                title=_(u"No subtitles found"),
                summary=_(u"%(current_info)sFilename: %(filename)s", current_info=current_display, filename=filename),
                thumb=default_thumb
            ))
    else:
        oc.add(DirectoryObject(
            key=Callback(ListAvailableSubsForItemMenu, rating_key=rating_key, item_title=item_title,
                         language=language, filename=filename, current_data=current_data,
                         part_id=part_id, title=title, current_id=current_id, item_type=item_type,
                         current_provider=current_provider, current_score=current_score,
                         randomize=timestamp()),
            title=_(u"Searching for %(language)s subs (%(video_data)s), refresh here ...",
                    language=display_language(get_language(language)),
                    video_data=video_display_data),
            summary=_(u"%(current_info)sFilename: %(filename)s", current_info=current_display, filename=filename),
            thumb=default_thumb
        ))

    if not search_results or search_results == "found_none":
        return oc

    current_sub, stored_subs, storage = get_current_sub(rating_key, part_id, language)
    current_bl, subs = stored_subs.get_blacklist(part_id, language)

    seen = []
    for subtitle in search_results:
        if subtitle.id in seen:
            continue

        bl_addon = ""
        if (str(subtitle.provider_name), str(subtitle.id)) in current_bl:
            bl_addon = "Blacklisted "

        wrong_fps_addon = ""
        wrong_series_addon = ""
        wrong_season_ep_addon = ""
        if subtitle.wrong_fps:
            if plex_part:
                wrong_fps_addon = _(" (wrong FPS, sub: %(subtitle_fps)s, media: %(media_fps)s)",
                                    subtitle_fps=subtitle.fps,
                                    media_fps=plex_part.fps)
            else:
                wrong_fps_addon = _(" (wrong FPS, sub: %(subtitle_fps)s, media: unknown, low impact mode)",
                                    subtitle_fps=subtitle.fps)

        if subtitle.wrong_series:
            wrong_series_addon = _(" (possibly wrong series)")

        if subtitle.wrong_season_ep:
            wrong_season_ep_addon = _(" (possibly wrong season/episode)")

        oc.add(DirectoryObject(
            key=Callback(TriggerDownloadSubtitle, rating_key=rating_key, randomize=timestamp(), item_title=item_title,
                         subtitle_id=str(subtitle.id), language=language),
            title=_(u"%(blacklisted_state)s%(current_state)s: %(provider_name)s, score: %(score)s%(wrong_fps_state)s"
                    u"%(wrong_series_state)s%(wrong_season_ep_state)s",
                    blacklisted_state=bl_addon,
                    current_state=_("Available") if current_id != subtitle.id else _("Current"),
                    provider_name=_(subtitle.provider_name),
                    score=subtitle.score,
                    wrong_fps_state=wrong_fps_addon,
                    wrong_series_state=wrong_series_addon,
                    wrong_season_ep_state=wrong_season_ep_addon),
            summary=_(u"Release: %(release_info)s, Matches: %(matches)s",
                      release_info=subtitle.release_info,
                      matches=", ".join(subtitle.matches)),
            thumb=default_thumb
        ))

        seen.append(subtitle.id)

    return oc
Beispiel #17
0
def MetadataMenu(rating_key, title=None, base_title=None, display_items=False, previous_item_type=None,
                 previous_rating_key=None, message=None, header=None, randomize=None):
    """
    displays the contents of a section based on whether it has a deeper tree or not (movies->movie (item) list; series->series list)
    :param rating_key:
    :param title:
    :param base_title:
    :param display_items:
    :param previous_item_type:
    :param previous_rating_key:
    :return:
    """
    title = unicode(title)
    item_title = title
    title = base_title + " > " + title
    oc = SubFolderObjectContainer(title2=title, no_cache=True, no_history=True, header=header, message=message,
                                  view_group="full_details")

    current_kind = get_item_kind_from_rating_key(rating_key)

    if display_items:
        timeout = 30
        show = None

        # add back to series for season
        if current_kind == "season":
            timeout = 720

            show = get_item(previous_rating_key)
            oc.add(DirectoryObject(
                key=Callback(MetadataMenu, rating_key=show.rating_key, title=show.title, base_title=show.section.title,
                             previous_item_type="section", display_items=True, randomize=timestamp()),
                title=_(u"< Back to %s", show.title),
                thumb=show.thumb or default_thumb
            ))
        elif current_kind == "series":
            # it shouldn't take more than 6 minutes to scan all of a series' files and determine the force refresh
            timeout = 3600

        items = get_all_items(key="children", value=rating_key, base="library/metadata")
        kind, deeper = get_items_info(items)
        dig_tree(oc, items, MetadataMenu,
                 pass_kwargs={"base_title": title, "display_items": deeper, "previous_item_type": kind,
                              "previous_rating_key": rating_key})

        # we don't know exactly where we are here, only add ignore option to series
        if current_kind in ("series", "season"):
            item = get_item(rating_key)
            sub_title = get_item_title(item)
            add_incl_excl_options(oc, current_kind, title=sub_title, rating_key=rating_key, callback_menu=InclExclMenu)

        # mass-extract embedded
        if current_kind == "season" and config.plex_transcoder:
            for lang in config.lang_list:
                oc.add(DirectoryObject(
                    key=Callback(SeasonExtractEmbedded, rating_key=rating_key, language=lang,
                                 base_title=show.section.title, display_items=display_items, item_title=item_title,
                                 title=title,
                                 previous_item_type=previous_item_type, with_mods=True,
                                 previous_rating_key=previous_rating_key, randomize=timestamp()),
                    title=_(u"Extract missing %(language)s embedded subtitles", language=display_language(lang)),
                    summary=_("Extracts the not yet extracted embedded subtitles of all episodes for the current "
                              "season with all configured default modifications")
                ))
                oc.add(DirectoryObject(
                    key=Callback(SeasonExtractEmbedded, rating_key=rating_key, language=lang,
                                 base_title=show.section.title, display_items=display_items, item_title=item_title,
                                 title=title, force=True,
                                 previous_item_type=previous_item_type, with_mods=True,
                                 previous_rating_key=previous_rating_key, randomize=timestamp()),
                    title=_(u"Extract and activate %(language)s embedded subtitles", language=display_language(lang)),
                    summary=_("Extracts embedded subtitles of all episodes for the current season "
                              "with all configured default modifications")
                ))

        # add refresh
        oc.add(DirectoryObject(
            key=Callback(RefreshItem, rating_key=rating_key, item_title=title, refresh_kind=current_kind,
                         previous_rating_key=previous_rating_key, timeout=timeout * 1000, randomize=timestamp()),
            title=_(u"Refresh: %s", item_title),
            summary=_("Refreshes %(the_movie_series_season_episode)s, possibly searching for missing and picking up "
                      "new subtitles on disk", the_movie_series_season_episode=_(u"the %s" % current_kind))
        ))
        oc.add(DirectoryObject(
            key=Callback(RefreshItem, rating_key=rating_key, item_title=title, force=True,
                         refresh_kind=current_kind, previous_rating_key=previous_rating_key, timeout=timeout * 1000,
                         randomize=timestamp()),
            title=_(u"Auto-Find subtitles: %s", item_title),
            summary=_("Issues a forced refresh, ignoring known subtitles and searching for new ones")
        ))
    else:
        return ItemDetailsMenu(rating_key=rating_key, title=title, item_title=item_title)

    return oc