player: make external subtitle auto-loading stricter

By default --sub-auto uses "exact". This was far from an "exact" match,
because it added anything that started with the video filename (without
extension), and seemed to end in something that looked like a language
code.

Make this stricter. "exact" still tolerate a language code, but the
video's filename must come before it without any unknown extra
characters. This may not load subtitles in some situations where it
previously did, and where the user might think that the naming
convention is such that it should be considered an exact match.

The subtitle priority sorting seems a bit worthless. I suppose it may
have some value in higher "fuzz" modes (like --sub-auto=fuzzy).

Also remove the mysterious "prio += prio;" line. I probably shouldn't
have checked, but it goes back to commit f16fa9d31 (2003), where someone
wanted to "refine" the priority without changing the rest of the code or
something.

Mostly untested, so have fun.

Fixes: #7702
This commit is contained in:
wm4 2020-05-09 23:31:33 +02:00
parent 327302bdb9
commit caf228b218
2 changed files with 41 additions and 25 deletions

View File

@ -2423,7 +2423,8 @@ Subtitles
default.
:no: Don't automatically load external subtitle files.
:exact: Load the media filename with subtitle file extension (default).
:exact: Load the media filename with subtitle file extension and possibly
language suffixes (default).
:fuzzy: Load all subs containing media filename.
:all: Load all subs in the current and ``--sub-file-paths`` directories.

View File

@ -83,7 +83,7 @@ static int compare_sub_priority(const void *a, const void *b)
return strcoll(s1->fname, s2->fname);
}
static struct bstr guess_lang_from_filename(struct bstr name)
static struct bstr guess_lang_from_filename(struct bstr name, int *fn_start)
{
if (name.len < 2)
return (struct bstr){NULL, 0};
@ -91,16 +91,27 @@ static struct bstr guess_lang_from_filename(struct bstr name)
int n = 0;
int i = name.len - 1;
if (name.start[i] == ')' || name.start[i] == ']')
char thing = '.';
if (name.start[i] == ')') {
thing = '(';
i--;
}
if (name.start[i] == ']') {
thing = '[';
i--;
}
while (i >= 0 && mp_isalpha(name.start[i])) {
n++;
if (n > 3)
return (struct bstr){NULL, 0};
i--;
}
if (n < 2)
if (n < 2 || i == 0 || name.start[i] != thing)
return (struct bstr){NULL, 0};
*fn_start = i;
return (struct bstr){name.start + i + 1, n};
}
@ -165,40 +176,44 @@ static void append_dir_subtitles(struct mpv_global *global, struct MPOpts *opts,
goto next_sub;
// we have a (likely) subtitle file
// 0 = nothing
// 1 = any subtitle file
// 2 = any sub file containing movie name
// 3 = sub file containing movie name and the lang extension
// higher prio -> auto-selection may prefer it (0 = not loaded)
int prio = 0;
if (bstrcmp(tmp_fname_trim, f_fname_trim) == 0)
prio |= 32; // exact movie name match
bstr lang = {0};
if (bstr_startswith(tmp_fname_trim, f_fname_trim))
lang = guess_lang_from_filename(tmp_fname_trim);
if (bstr_startswith(tmp_fname_trim, f_fname_trim)) {
int start = 0;
lang = guess_lang_from_filename(tmp_fname_trim, &start);
if (lang.len && start == f_fname_trim.len)
prio |= 16; // exact movie name + followed by lang
}
for (int n = 0; langs && langs[n]; n++) {
if (lang.len && bstr_case_startswith(lang, bstr0(langs[n]))) {
prio = 4; // matches the movie name + lang extension
if (fuzz >= 1)
prio |= 8; // known language -> boost priority
break;
}
}
if (!prio && bstrcmp(tmp_fname_trim, f_fname_trim) == 0)
prio = 3; // matches the movie name
if (!prio && lang.len)
prio = 3; // matches the movie name + a language was matched
if (!prio && bstr_find(tmp_fname_trim, f_fname_trim) >= 0 && fuzz >= 1)
prio = 2; // contains the movie name
if (!prio) {
// doesn't contain the movie name
// don't try in the mplayer subtitle directory
if (!limit_fuzziness && fuzz >= 2) {
prio = 1;
}
}
if (lang.len && fuzz >= 1)
prio |= 4; // matches the movie name + a language was matched
if (bstr_find(tmp_fname_trim, f_fname_trim) >= 0 && fuzz >= 1)
prio |= 2; // contains the movie name
// doesn't contain the movie name
// don't try in the mplayer subtitle directory
if (!limit_fuzziness && fuzz >= 2)
prio |= 1;
mp_dbg(log, "Potential external file: \"%s\" Priority: %d\n",
de->d_name, prio);
if (prio) {
prio += prio;
char *subpath = mp_path_join_bstr(*slist, path, dename);
if (mp_path_exists(subpath)) {
MP_TARRAY_GROW(NULL, *slist, *nsub);