diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index 8d34fcf99e..0384796699 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -45,6 +45,7 @@ Interface changes - add `--audio-file-exts`, `--cover-art-auto-exts`, and `--sub-auto-exts` - change `slang` default back to NULL - remove special handling of the `auto` value from `--alang/slang/vlang` options + - add `--subs-match-os-language` as a replacement for `--slang=auto` --- mpv 0.36.0 --- - add `--target-contrast` - Target luminance value is now also applied when ICC profile is used. diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 94d7bce6e8..b4e9a2b8d3 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -139,6 +139,12 @@ Track Selection When autoselecting a subtitle track, select a full/non-forced one even if the selected audio stream matches your preferred subtitle language (default: yes). +``--subs-match-os-language=`` + When autoselecting a subtitle track, select the track that matches the language of your OS + if the audio stream is in a different language if suitable (default track or a forced track + under the right conditions). Note that if ``-slang`` is set, this will be completely ignored + (default: yes). + ``--subs-fallback=`` When autoselecting a subtitle track, if no tracks match your preferred languages, select a full track even if it doesn't match your preferred subtitle language (default: default). diff --git a/options/options.c b/options/options.c index 13fefd5f0d..14fb4039c0 100644 --- a/options/options.c +++ b/options/options.c @@ -522,6 +522,7 @@ static const m_option_t mp_opts[] = { {"vlang", OPT_STRINGLIST(stream_lang[STREAM_VIDEO])}, {"track-auto-selection", OPT_BOOL(stream_auto_sel)}, {"subs-with-matching-audio", OPT_BOOL(subs_with_matching_audio)}, + {"subs-match-os-language", OPT_BOOL(subs_match_os_language)}, {"subs-fallback", OPT_CHOICE(subs_fallback, {"no", 0}, {"default", 1}, {"yes", 2})}, {"subs-fallback-forced", OPT_BOOL(subs_fallback_forced)}, @@ -1044,6 +1045,7 @@ static const struct MPOpts mp_default_opts = { [STREAM_SUB] = -2, }, }, .stream_auto_sel = true, .subs_with_matching_audio = true, + .subs_match_os_language = true, .subs_fallback = 1, .subs_fallback_forced = true, .audio_display = 1, diff --git a/options/options.h b/options/options.h index 6f8c8a5998..52547183a2 100644 --- a/options/options.h +++ b/options/options.h @@ -268,6 +268,7 @@ typedef struct MPOpts { char **stream_lang[STREAM_TYPE_COUNT]; bool stream_auto_sel; bool subs_with_matching_audio; + bool subs_match_os_language; int subs_fallback; bool subs_fallback_forced; int audio_display; diff --git a/player/loadfile.c b/player/loadfile.c index 3b0dcb1a39..2a83f57241 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -472,10 +472,11 @@ static int match_lang(char **langs, const char *lang) * 1) track is external (no_default cancels this) * 1b) track was passed explicitly (is not an auto-loaded subtitle) * 1c) track matches the program ID of the video - * 2) earlier match in lang list + * 2) earlier match in lang list but not if we're using os_langs * 3a) track is marked forced and we're preferring forced tracks * 3b) track is marked non-forced and we're preferring non-forced tracks * 3c) track is marked default + * 3d) match in lang list with os_langs * 4) attached picture, HLS bitrate * 5) lower track number * If select_fallback is not set, 5) is only used to determine whether a @@ -485,7 +486,7 @@ static int match_lang(char **langs, const char *lang) */ // Return whether t1 is preferred over t2 static bool compare_track(struct track *t1, struct track *t2, char **langs, - struct MPOpts *opts, int preferred_program) + bool os_langs, struct MPOpts *opts, int preferred_program) { if (!opts->autoload_files && t1->is_external != t2->is_external) return !t1->is_external; @@ -505,10 +506,12 @@ static bool compare_track(struct track *t1, struct track *t2, char **langs, return t1->program_id == preferred_program; } int l1 = match_lang(langs, t1->lang), l2 = match_lang(langs, t2->lang); - if (l1 != l2) + if (!os_langs && l1 != l2) return l1 > l2; if (t1->default_track != t2->default_track) return t1->default_track; + if (os_langs && l1 != l2) + return l1 > l2; if (t1->attached_picture != t2->attached_picture) return !t1->attached_picture; if (t1->stream && t2->stream && opts->hls_bitrate >= 0 && @@ -546,19 +549,19 @@ static bool append_lang(size_t *nb, char ***out, char *in) return true; } -static bool add_auto_langs(size_t *nb, char ***out) +static char **add_os_langs(void) { - bool ret = false; + size_t nb = 0; + char **out = NULL; char **autos = mp_get_user_langs(); for (int i = 0; autos && autos[i]; i++) { - if (!append_lang(nb, out, autos[i])) + if (!append_lang(&nb, &out, autos[i])) goto cleanup; } - ret = true; cleanup: talloc_free(autos); - return ret; + return out; } static char **process_langs(char **in) @@ -611,6 +614,13 @@ struct track *select_default_track(struct MPContext *mpctx, int order, if (tid == -2) return NULL; char **langs = process_langs(opts->stream_lang[type]); + bool os_langs = false; + // Try to add OS languages if enabled by the user and we don't already have a lang from slang. + if (type == STREAM_SUB && (!langs || !strcmp(langs[0], "")) && opts->subs_match_os_language) { + talloc_free(langs); + langs = add_os_langs(); + os_langs = true; + } const char *audio_lang = get_audio_lang(mpctx); bool sub = type == STREAM_SUB; bool fallback_forced = sub && opts->subs_fallback_forced; @@ -633,12 +643,12 @@ struct track *select_default_track(struct MPContext *mpctx, int order, continue; if (duplicate_track(mpctx, order, type, track)) continue; - if (!pick || compare_track(track, pick, langs, mpctx->opts, preferred_program)) + if (!pick || compare_track(track, pick, langs, os_langs, mpctx->opts, preferred_program)) pick = track; // We only try to autoselect forced tracks if they match the audio language and are subs if (fallback_forced && track->forced_track && mp_match_lang_single(audio_lang, track->lang) && - (!forced_pick || compare_track(track, forced_pick, langs, mpctx->opts, preferred_program))) + (!forced_pick || compare_track(track, forced_pick, langs, os_langs, mpctx->opts, preferred_program))) forced_pick = track; } @@ -652,7 +662,7 @@ struct track *select_default_track(struct MPContext *mpctx, int order, sub_fallback = (pick->is_external && !pick->no_default) || opts->subs_fallback == 2 || (opts->subs_fallback == 1 && pick->default_track); } - if (pick && !forced_pick && sub && !match_lang(langs, pick->lang) && + if (pick && !forced_pick && sub && (!match_lang(langs, pick->lang) || os_langs) && ((!opts->subs_with_matching_audio && audio_matches) || !sub_fallback)) pick = NULL;