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
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
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
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
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
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 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
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
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
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
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
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