Skip to content

Commit d31b534

Browse files
committed
misc/language: parse forced tag from external subtitle tracks
Fixes: mpv-player#16060
1 parent 6c42182 commit d31b534

9 files changed

+80
-60
lines changed

common/common.h

+8
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ enum video_sync {
9191
VS_NONE,
9292
};
9393

94+
enum track_flags {
95+
// starts at 4, for cmd_track_add backwards compatibility
96+
TRACK_HEARING_IMPAIRED = 1 << 2,
97+
TRACK_VISUAL_IMPAIRED = 1 << 3,
98+
TRACK_ATTACHED_PICTURE = 1 << 4,
99+
TRACK_FORCED = 1 << 5,
100+
};
101+
94102
#define VS_IS_DISP(x) ((x) == VS_DISP_RESAMPLE || \
95103
(x) == VS_DISP_RESAMPLE_VDROP || \
96104
(x) == VS_DISP_RESAMPLE_NONE || \

misc/language.c

+13-9
Original file line numberDiff line numberDiff line change
@@ -297,15 +297,15 @@ int mp_match_lang(char **langs, const char *lang)
297297
return best_score;
298298
}
299299

300-
bstr mp_guess_lang_from_filename(bstr name, int *lang_start, bool *hearing_impaired)
300+
bstr mp_guess_lang_from_filename(bstr name, int *lang_start, enum track_flags *flags)
301301
{
302302
name = bstr_strip(bstr_strip_ext(name));
303303

304304
if (lang_start)
305305
*lang_start = -1;
306306

307-
if (hearing_impaired)
308-
*hearing_impaired = false;
307+
if (flags)
308+
*flags = 0;
309309

310310
if (name.len < 2)
311311
return (bstr){0};
@@ -324,26 +324,30 @@ bstr mp_guess_lang_from_filename(bstr name, int *lang_start, bool *hearing_impai
324324
i--;
325325
}
326326

327-
bool *hi = hearing_impaired ? hearing_impaired : &(bool){0};
328-
bool checked_hi = false;
327+
enum track_flags *f = flags ? flags : &(enum track_flags){0};
329328

330329
while (true) {
331330
while (i >= 0 && mp_isalpha(name.start[i])) {
332331
lang_length++;
333332
i--;
334333
}
335334

336-
if (i >= 0 && lang_length >= 2 && !checked_hi && name.start[i] == delimiter) {
337-
checked_hi = true;
335+
if (i >= 0 && lang_length >= 2 && name.start[i] == delimiter) {
336+
bool matched = false;
338337
static const char *const suffixes[] = { "sdh", "hi", "cc" };
339338
bstr tag = { name.start + i + 1, lang_length };
340339
for (int n = 0; n < MP_ARRAY_SIZE(suffixes); n++) {
341340
if (!bstrcasecmp0(tag, suffixes[n])) {
342-
*hi = true;
341+
*f |= TRACK_HEARING_IMPAIRED;
342+
matched = true;
343343
break;
344344
}
345345
}
346-
if (*hi) {
346+
if (!bstrcasecmp0(tag, "forced")) {
347+
*f |= TRACK_FORCED;
348+
matched = true;
349+
}
350+
if (matched) {
347351
lang_length = 0;
348352
i -= (delimiter != '.') ? 2 : 1;
349353
continue;

misc/language.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@
2121
#define MP_LANGUAGE_H
2222

2323
#include "misc/bstr.h"
24+
#include "common/common.h"
2425

2526
// Result numerically higher => better match. 0 == no match.
2627
int mp_match_lang(char **langs, const char *lang);
2728
char **mp_get_user_langs(void);
28-
bstr mp_guess_lang_from_filename(bstr name, int *lang_start, bool *hearing_impaired);
29+
bstr mp_guess_lang_from_filename(bstr name, int *lang_start, enum track_flags *flags);
2930

3031
#endif /* MP_LANGUAGE_H */

player/command.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -6305,6 +6305,7 @@ static void cmd_track_reload(void *p)
63056305
flags |= t->attached_picture ? TRACK_ATTACHED_PICTURE : 0;
63066306
flags |= t->hearing_impaired_track ? TRACK_HEARING_IMPAIRED : 0;
63076307
flags |= t->visual_impaired_track ? TRACK_VISUAL_IMPAIRED : 0;
6308+
flags |= t->forced_track ? TRACK_FORCED : 0;
63086309
mp_remove_track(mpctx, t);
63096310
nt_num = mp_add_external_file(mpctx, filename, type, cmd->abort->cancel,
63106311
flags);
@@ -6319,9 +6320,12 @@ static void cmd_track_reload(void *p)
63196320
struct track *nt = mpctx->tracks[nt_num];
63206321

63216322
if (!nt->lang) {
6323+
enum track_flags flags = 0;
63226324
bstr lang = mp_guess_lang_from_filename(bstr0(nt->external_filename), NULL,
6323-
&nt->hearing_impaired_track);
6325+
&flags);
63246326
nt->lang = bstrto0(nt, lang);
6327+
nt->hearing_impaired_track = flags & TRACK_HEARING_IMPAIRED;
6328+
nt->forced_track = flags & TRACK_FORCED;
63256329
}
63266330

63276331
mp_switch_track(mpctx, nt->type, nt, 0);

player/core.h

-7
Original file line numberDiff line numberDiff line change
@@ -491,13 +491,6 @@ struct mp_abort_entry {
491491
#define WHITE_CIRCLE "\xe2\x97\x8b"
492492
#define BLACK_CIRCLE "\xe2\x97\x8f"
493493

494-
enum track_flags {
495-
// starts at 4, for cmd_track_add backwards compatibility
496-
TRACK_HEARING_IMPAIRED = 1 << 2,
497-
TRACK_VISUAL_IMPAIRED = 1 << 3,
498-
TRACK_ATTACHED_PICTURE = 1 << 4,
499-
};
500-
501494
// audio.c
502495
void reset_audio_state(struct MPContext *mpctx);
503496
void reinit_audio_chain(struct MPContext *mpctx);

player/external_files.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ static void append_dir_subtitles(struct mpv_global *global, struct MPOpts *opts,
155155

156156
bstr lang = {0};
157157
int start = 0;
158-
bool hearing_impaired = false;
159-
lang = mp_guess_lang_from_filename(dename, &start, &hearing_impaired);
158+
enum track_flags flags = 0;
159+
lang = mp_guess_lang_from_filename(dename, &start, &flags);
160160
if (bstr_case_startswith(tmp_fname_trim, f_fname_trim)) {
161161
if (lang.len && start == f_fname_trim.len)
162162
prio |= 16; // exact movie name + followed by lang
@@ -201,7 +201,7 @@ static void append_dir_subtitles(struct mpv_global *global, struct MPOpts *opts,
201201
sub->priority = prio;
202202
sub->fname = subpath;
203203
sub->lang = lang.len ? bstrdup0(*slist, lang) : NULL;
204-
sub->hearing_impaired = hearing_impaired;
204+
sub->flags = flags;
205205
} else
206206
talloc_free(subpath);
207207
}

player/external_files.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020

2121
#include <stdbool.h>
2222

23+
#include "common/common.h"
24+
2325
struct subfn {
2426
int type; // STREAM_SUB/STREAM_AUDIO/STREAM_VIDEO(coverart)
2527
int priority;
2628
char *fname;
2729
char *lang;
28-
bool hearing_impaired;
30+
enum track_flags flags;
2931
};
3032

3133
struct mpv_global;

player/loadfile.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,7 @@ int mp_add_external_file(struct MPContext *mpctx, char *filename,
917917
t->no_auto_select = t->no_default;
918918
t->hearing_impaired_track = flags & TRACK_HEARING_IMPAIRED;
919919
t->visual_impaired_track = flags & TRACK_VISUAL_IMPAIRED;
920+
t->forced_track = flags & TRACK_FORCED;
920921
// if we found video, and we are loading cover art, flag as such.
921922
t->attached_picture = t->type == STREAM_VIDEO && (flags & TRACK_ATTACHED_PICTURE);
922923
if (first_num < 0 && (filter == STREAM_TYPE_COUNT || sh->type == filter))
@@ -987,8 +988,7 @@ void autoload_external_files(struct MPContext *mpctx, struct mp_cancel *cancel)
987988
if (e->type == STREAM_VIDEO && (sc[STREAM_VIDEO] || !sc[STREAM_AUDIO]))
988989
goto skip;
989990

990-
enum track_flags flags = 0;
991-
flags |= e->hearing_impaired ? TRACK_HEARING_IMPAIRED : 0;
991+
enum track_flags flags = e->flags;
992992
// when given filter is set to video, we are loading up cover art
993993
flags |= e->type == STREAM_VIDEO ? TRACK_ATTACHED_PICTURE : 0;
994994
int first = mp_add_external_file(mpctx, e->fname, e->type, cancel, flags);

test/language.c

+44-36
Original file line numberDiff line numberDiff line change
@@ -57,47 +57,55 @@ int main(void)
5757

5858
void *ta_ctx = talloc_new(NULL);
5959

60-
#define TEST_LANG_GUESS(filename, expected_lang, expected_start, expected_hi) \
61-
do { \
62-
int start; \
63-
bool hearing_impaired; \
64-
bstr lang = mp_guess_lang_from_filename(bstr0(filename), &start, \
65-
&hearing_impaired); \
66-
assert_string_equal(bstrto0(ta_ctx, lang), expected_lang); \
67-
assert_int_equal(start, expected_start); \
68-
assert_true(hearing_impaired == expected_hi); \
60+
#define TEST_LANG_GUESS(filename, expected_lang, expected_start, expected_flags) \
61+
do { \
62+
int start; \
63+
enum track_flags flags; \
64+
bstr lang = mp_guess_lang_from_filename(bstr0(filename), &start, &flags); \
65+
assert_string_equal(bstrto0(ta_ctx, lang), expected_lang); \
66+
assert_int_equal(start, expected_start); \
67+
assert_int_equal(flags, expected_flags); \
6968
} while (0)
7069

71-
TEST_LANG_GUESS("foo.en.srt", "en", 3, false);
72-
TEST_LANG_GUESS("foo.eng.srt", "eng", 3, false);
73-
TEST_LANG_GUESS("foo.e.srt", "", -1, false);
74-
TEST_LANG_GUESS("foo.engg.srt", "", -1, false);
75-
TEST_LANG_GUESS("foo.00.srt", "", -1, false);
76-
TEST_LANG_GUESS("foo.srt", "", -1, false);
77-
TEST_LANG_GUESS(NULL, "", -1, false);
70+
TEST_LANG_GUESS("foo.en.srt", "en", 3, 0);
71+
TEST_LANG_GUESS("foo.eng.srt", "eng", 3, 0);
72+
TEST_LANG_GUESS("foo.e.srt", "", -1, 0);
73+
TEST_LANG_GUESS("foo.engg.srt", "", -1, 0);
74+
TEST_LANG_GUESS("foo.00.srt", "", -1, 0);
75+
TEST_LANG_GUESS("foo.srt", "", -1, 0);
76+
TEST_LANG_GUESS(NULL, "", -1, 0);
7877

79-
TEST_LANG_GUESS("foo.en-US.srt", "en-US", 3, false);
80-
TEST_LANG_GUESS("foo.en-US.hi.srt", "en-US", 3, true);
81-
TEST_LANG_GUESS("foo.en-US.sdh.srt", "en-US", 3, true);
82-
TEST_LANG_GUESS("foo.en-simple.srt", "en-simple", 3, false);
83-
TEST_LANG_GUESS("foo.sgn-FSL.srt", "sgn-FSL", 3, false);
84-
TEST_LANG_GUESS("foo.gsw-u-sd-chzh.srt", "gsw-u-sd-chzh", 3, false);
85-
TEST_LANG_GUESS("foo.en-.srt", "", -1, false);
86-
TEST_LANG_GUESS("foo.en-US-.srt", "", -1, false);
87-
TEST_LANG_GUESS("foo.en-aaaaaaaaa.srt", "", -1, false);
88-
TEST_LANG_GUESS("foo.en-0.srt", "", -1, false);
78+
TEST_LANG_GUESS("foo.en-US.srt", "en-US", 3, 0);
79+
TEST_LANG_GUESS("foo.en-US.hi.srt", "en-US", 3, TRACK_HEARING_IMPAIRED);
80+
TEST_LANG_GUESS("foo.en-US.sdh.srt", "en-US", 3, TRACK_HEARING_IMPAIRED);
81+
TEST_LANG_GUESS("foo.en-US.forced.srt", "en-US", 3, TRACK_FORCED);
82+
TEST_LANG_GUESS("foo.en-US.forced.sdh.srt", "en-US", 3, TRACK_HEARING_IMPAIRED | TRACK_FORCED);
83+
TEST_LANG_GUESS("foo.en-US.sdh.forced.srt", "en-US", 3, TRACK_HEARING_IMPAIRED | TRACK_FORCED);
84+
TEST_LANG_GUESS("foo.en-simple.srt", "en-simple", 3, 0);
85+
TEST_LANG_GUESS("foo.sgn-FSL.srt", "sgn-FSL", 3, 0);
86+
TEST_LANG_GUESS("foo.gsw-u-sd-chzh.srt", "gsw-u-sd-chzh", 3, 0);
87+
TEST_LANG_GUESS("foo.en-.srt", "", -1, 0);
88+
TEST_LANG_GUESS("foo.en-US-.srt", "", -1, 0);
89+
TEST_LANG_GUESS("foo.en-aaaaaaaaa.srt", "", -1, 0);
90+
TEST_LANG_GUESS("foo.en-0.srt", "", -1, 0);
8991

90-
TEST_LANG_GUESS("foo[en].srt", "en", 3, false);
91-
TEST_LANG_GUESS("foo[en-US].srt", "en-US", 3, false);
92-
TEST_LANG_GUESS("foo[en-US][hi].srt", "en-US", 3, true);
93-
TEST_LANG_GUESS("foo[en-US][sdh].srt", "en-US", 3, true);
94-
TEST_LANG_GUESS("foo[].srt", "", -1, false);
92+
TEST_LANG_GUESS("foo[en].srt", "en", 3, 00);
93+
TEST_LANG_GUESS("foo[en-US].srt", "en-US", 3, 0);
94+
TEST_LANG_GUESS("foo[en-US][hi].srt", "en-US", 3, TRACK_HEARING_IMPAIRED);
95+
TEST_LANG_GUESS("foo[en-US][sdh].srt", "en-US", 3, TRACK_HEARING_IMPAIRED);
96+
TEST_LANG_GUESS("foo[en-US][forced].srt", "en-US", 3, TRACK_FORCED);
97+
TEST_LANG_GUESS("foo[en-US][forced][sdh].srt", "en-US", 3, TRACK_HEARING_IMPAIRED | TRACK_FORCED);
98+
TEST_LANG_GUESS("foo[en-US][sdh][forced].srt", "en-US", 3, TRACK_HEARING_IMPAIRED | TRACK_FORCED);
99+
TEST_LANG_GUESS("foo[].srt", "", -1, 0);
95100

96-
TEST_LANG_GUESS("foo(en).srt", "en", 3, false);
97-
TEST_LANG_GUESS("foo(en-US).srt", "en-US", 3, false);
98-
TEST_LANG_GUESS("foo(en-US)(hi).srt", "en-US", 3, true);
99-
TEST_LANG_GUESS("foo(en-US)(sdh).srt", "en-US", 3, true);
100-
TEST_LANG_GUESS("foo().srt", "", -1, false);
101+
TEST_LANG_GUESS("foo(en).srt", "en", 3, 0);
102+
TEST_LANG_GUESS("foo(en-US).srt", "en-US", 3, 0);
103+
TEST_LANG_GUESS("foo(en-US)(hi).srt", "en-US", 3, TRACK_HEARING_IMPAIRED);
104+
TEST_LANG_GUESS("foo(en-US)(sdh).srt", "en-US", 3, TRACK_HEARING_IMPAIRED);
105+
TEST_LANG_GUESS("foo(en-US)(forced).srt", "en-US", 3, TRACK_FORCED);
106+
TEST_LANG_GUESS("foo(en-US)(forced)(sdh).srt", "en-US", 3, TRACK_HEARING_IMPAIRED | TRACK_FORCED);
107+
TEST_LANG_GUESS("foo(en-US)(sdh)(forced).srt", "en-US", 3, TRACK_HEARING_IMPAIRED | TRACK_FORCED);
108+
TEST_LANG_GUESS("foo().srt", "", -1, 0);
101109

102110
talloc_free(ta_ctx);
103111
}

0 commit comments

Comments
 (0)