mirror of
https://github.com/mpv-player/mpv.git
synced 2026-10-25 12:42:04 +08:00
540 lines
20 KiB
C
540 lines
20 KiB
C
/*
|
|
* This file is part of mpv.
|
|
*
|
|
* mpv is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* mpv is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifdef __APPLE__
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
#include <assert.h>
|
|
|
|
#include <io.h>
|
|
#include <windows.h>
|
|
#else
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include "libmpv_common.h"
|
|
|
|
#ifndef F_OK
|
|
#define F_OK 0
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
static bool any_starts_with(const wchar_t *buffer, ULONG count, const wchar_t *str)
|
|
{
|
|
for (ULONG pos = 0, i = 0; i < count; ++i) {
|
|
assert(buffer[pos]);
|
|
if (wcsncmp(buffer + pos, str, wcslen(str)) == 0)
|
|
return true;
|
|
pos += wcslen(buffer + pos) + 1;
|
|
}
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
static bool have_english_locale(void)
|
|
{
|
|
#ifdef __APPLE__
|
|
CFArrayRef arr = CFLocaleCopyPreferredLanguages();
|
|
if (!arr)
|
|
return false;
|
|
CFIndex count = CFArrayGetCount(arr);
|
|
if (!count)
|
|
return false;
|
|
|
|
bool ret = false;
|
|
CFRange range = CFRangeMake(0, 2);
|
|
CFStringRef en = CFStringCreateWithCString(NULL, "en", kCFStringEncodingMacRoman);
|
|
for (CFIndex i = 0; i < count; i++) {
|
|
CFStringRef cfstr = CFArrayGetValueAtIndex(arr, i);
|
|
if (CFStringCompareWithOptions(cfstr, en, range, 0) == 0) {
|
|
ret = true;
|
|
break;
|
|
}
|
|
}
|
|
CFRelease(en);
|
|
return ret;
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
wchar_t buf[1024];
|
|
ULONG size = _countof(buf);
|
|
ULONG count = 0;
|
|
|
|
if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &count, buf, &size))
|
|
fail("GetUserPreferredUILanguages failed: %#lx\n", GetLastError());
|
|
|
|
if (any_starts_with(buf, count, L"en"))
|
|
return true;
|
|
|
|
if (any_starts_with(buf, count, L"en"))
|
|
return true;
|
|
|
|
return false;
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
static void test_track_selection(char *file, char *path)
|
|
{
|
|
int ret = access(path, F_OK);
|
|
if (ret)
|
|
fail("Test file, '%s', was not found!\n", path);
|
|
|
|
if (strcmp(file, "eng_default.mkv") == 0) {
|
|
// --no-config
|
|
reload_file(path);
|
|
check_string("current-tracks/sub/selected", "yes");
|
|
|
|
// --subs-falback=no
|
|
set_property_string("subs-fallback", "no");
|
|
reload_file(path);
|
|
check_string("track-list/2/selected", "no");
|
|
} else if (strcmp(file, "eng_default_forced.mkv") == 0) {
|
|
// --subs-fallback-forced=no
|
|
set_property_string("subs-fallback-forced", "no");
|
|
reload_file(path);
|
|
check_string("current-tracks/sub/selected", "yes");
|
|
} else if (strcmp(file, "eng_forced_matching_audio.mkv") == 0 ||
|
|
(strcmp(file, "eng_forced_matching_audio_region.mkv") == 0)) {
|
|
// select forced track
|
|
reload_file(path);
|
|
check_string("current-tracks/sub/selected", "yes");
|
|
} else if (strcmp(file, "eng_forced_no_matching_audio.mkv") == 0) {
|
|
// forced track should not be selected
|
|
reload_file(path);
|
|
check_string("track-list/2/selected", "no");
|
|
} else if (strcmp(file, "eng_forced_always_audio.mkv") == 0) {
|
|
// forced track should be selected anyway despite no matching audio
|
|
set_property_string("subs-fallback-forced", "always");
|
|
reload_file(path);
|
|
check_string("current-tracks/sub/selected", "yes");
|
|
} else if (strcmp(file, "eng_no_default.mkv") == 0) {
|
|
// track should not be selected
|
|
reload_file(path);
|
|
check_string("track-list/2/selected", "no");
|
|
|
|
// --subs-fallback=yes
|
|
set_property_string("subs-fallback", "yes");
|
|
reload_file(path);
|
|
check_string("current-tracks/sub/selected", "yes");
|
|
} else if (strcmp(file, "locale.mkv") == 0 ||
|
|
strcmp(file, "locale_forced.mkv") == 0) {
|
|
// default english subs
|
|
reload_file(path);
|
|
check_string("current-tracks/sub/lang", "eng");
|
|
|
|
// default german subs
|
|
set_property_string("subs-match-os-language", "no");
|
|
reload_file(path);
|
|
check_string("current-tracks/sub/lang", "ger");
|
|
} else if (strcmp(file, "locale_complex.mkv") == 0) {
|
|
set_property_string("subs-fallback", "yes");
|
|
set_property_string("subs-match-os-language", "yes");
|
|
|
|
// default+forced eng subs to match audio
|
|
set_property_string("alang", "eng");
|
|
reload_file(path);
|
|
check_string("current-tracks/audio/lang", "eng");
|
|
check_string("current-tracks/sub/lang", "eng");
|
|
// among all eng subs, track 4 should be selected
|
|
check_int("current-tracks/sub/id", 4);
|
|
|
|
// forced jpn subs to match audio
|
|
set_property_string("alang", "jpn");
|
|
reload_file(path);
|
|
check_string("current-tracks/audio/lang", "jpn");
|
|
check_string("current-tracks/sub/lang", "jpn");
|
|
|
|
// default, non-forced ger subs
|
|
set_property_string("alang", "ger");
|
|
reload_file(path);
|
|
check_string("current-tracks/audio/lang", "ger");
|
|
check_string("current-tracks/sub/lang", "ger");
|
|
|
|
// default+forced pol subs to match audio
|
|
set_property_string("alang", "pol");
|
|
reload_file(path);
|
|
check_string("current-tracks/audio/lang", "pol");
|
|
check_string("current-tracks/sub/lang", "pol");
|
|
|
|
// default+forced pol subs (first default track)
|
|
set_property_string("subs-match-os-language", "no");
|
|
set_property_string("subs-fallback-forced", "always");
|
|
reload_file(path);
|
|
check_string("current-tracks/sub/lang", "pol");
|
|
|
|
// default+forced eng subs to match OS lang
|
|
set_property_string("subs-match-os-language", "yes");
|
|
reload_file(path);
|
|
check_string("current-tracks/sub/lang", "eng");
|
|
// among all eng subs, track 4 should be selected
|
|
check_int("current-tracks/sub/id", 4);
|
|
|
|
// default, non-forced ger subs
|
|
set_property_string("subs-fallback-forced", "no");
|
|
reload_file(path);
|
|
check_string("current-tracks/sub/lang", "ger");
|
|
|
|
// default+forced eng subs to match slang
|
|
set_property_string("slang", "eng");
|
|
reload_file(path);
|
|
check_string("current-tracks/sub/lang", "eng");
|
|
// among all eng subs, track 4 should be selected
|
|
check_int("current-tracks/sub/id", 4);
|
|
} else if (strcmp(file, "multilang.mkv") == 0) {
|
|
// --alang=jpn should select forced jpn subs
|
|
set_property_string("alang", "jpn");
|
|
reload_file(path);
|
|
check_string("current-tracks/audio/lang", "jpn");
|
|
check_string("current-tracks/sub/lang", "jpn");
|
|
|
|
// --alang=pol should select default, non-forced ger subs
|
|
set_property_string("alang", "pol");
|
|
reload_file(path);
|
|
check_string("current-tracks/audio/lang", "pol");
|
|
check_string("current-tracks/sub/lang", "ger");
|
|
|
|
// --slang=eng and --subs-with-matching-audio should not pick any subs
|
|
set_property_string("alang", "eng");
|
|
set_property_string("slang", "eng");
|
|
set_property_string("subs-with-matching-audio", "no");
|
|
reload_file(path);
|
|
check_string("current-tracks/audio/lang", "eng");
|
|
check_string("track-list/5/selected", "no");
|
|
check_string("track-list/6/selected", "no");
|
|
check_string("track-list/7/selected", "no");
|
|
check_string("track-list/8/selected", "no");
|
|
|
|
// --subs-with-matching-audio=forced checks
|
|
set_property_string("subs-with-matching-audio", "forced");
|
|
reload_file(path);
|
|
check_string("current-tracks/audio/lang", "eng");
|
|
check_string("current-tracks/sub/lang", "eng");
|
|
|
|
// forced jpn subs should be selected
|
|
set_property_string("alang", "jpn");
|
|
set_property_string("slang", "jpn");
|
|
reload_file(path);
|
|
check_string("current-tracks/audio/lang", "jpn");
|
|
check_string("current-tracks/sub/lang", "jpn");
|
|
|
|
// default+forced eng subs should be selected
|
|
set_property_string("alang", "ger");
|
|
set_property_string("slang", "ger");
|
|
reload_file(path);
|
|
check_string("current-tracks/audio/lang", "ger");
|
|
check_string("current-tracks/sub/lang", "eng");
|
|
|
|
// eng audio and pol subs should be selected
|
|
set_property_string("alang", "it");
|
|
set_property_string("slang", "pt,it,pol,ger");
|
|
reload_file(path);
|
|
check_string("current-tracks/audio/lang", "eng");
|
|
check_string("current-tracks/sub/lang", "pol");
|
|
|
|
// forced jpn subs should be selected
|
|
set_property_string("alang", "ger");
|
|
set_property_string("slang", "jpn,pol");
|
|
set_property_string("subs-with-matching-audio", "yes");
|
|
set_property_string("subs-fallback-forced", "always");
|
|
reload_file(path);
|
|
check_string("current-tracks/audio/lang", "ger");
|
|
check_string("current-tracks/sub/lang", "jpn");
|
|
|
|
// default+forced eng subs should be selected
|
|
set_property_string("alang", "jpn");
|
|
set_property_string("slang", "");
|
|
set_property_string("subs-with-matching-audio", "yes");
|
|
set_property_string("subs-fallback-forced", "always");
|
|
reload_file(path);
|
|
check_string("current-tracks/audio/lang", "jpn");
|
|
check_string("current-tracks/sub/lang", "eng");
|
|
} else if (strcmp(file, "multilang2.mkv") == 0) {
|
|
// default jpn subs
|
|
set_property_string("subs-match-os-language", "no");
|
|
set_property_string("alang", "jpn");
|
|
reload_file(path);
|
|
check_string("track-list/3/selected", "yes");
|
|
|
|
// forced eng subs
|
|
set_property_string("alang", "eng");
|
|
reload_file(path);
|
|
check_string("track-list/4/selected", "yes");
|
|
|
|
// default jpn subs
|
|
set_property_string("subs-fallback-forced", "no");
|
|
reload_file(path);
|
|
check_string("track-list/3/selected", "yes");
|
|
|
|
// default eng subs
|
|
set_property_string("slang", "eng");
|
|
reload_file(path);
|
|
check_string("track-list/6/selected", "yes");
|
|
|
|
// no subs
|
|
set_property_string("slang", "");
|
|
set_property_string("subs-fallback", "no");
|
|
reload_file(path);
|
|
check_string("track-list/3/selected", "no");
|
|
check_string("track-list/4/selected", "no");
|
|
check_string("track-list/5/selected", "no");
|
|
check_string("track-list/6/selected", "no");
|
|
|
|
// untagged eng subs
|
|
set_property_string("sid", "3");
|
|
reload_file(path);
|
|
check_string("track-list/5/selected", "yes");
|
|
} else if (strcmp(file, "multiprogram.ts") == 0) {
|
|
// Program 1
|
|
// Stream #0:0[0x100]: Video
|
|
// Stream #0:1[0x101](eng): Subtitle
|
|
// Stream #0:2[0x104](fra): Subtitle
|
|
// Program 2
|
|
// Stream #0:3[0x102]: Video
|
|
// Stream #0:4[0x103](jpn): Subtitle
|
|
// Stream #0:2[0x104](fra): Subtitle
|
|
|
|
set_property_string("subs-match-os-language", "no");
|
|
set_property_string("edition", "1");
|
|
|
|
reload_file(path);
|
|
check_string("current-edition", "1");
|
|
|
|
// no subs are selected by default
|
|
check_string("track-list/count", "3");
|
|
check_string("track-list/0/type", "sub");
|
|
check_string("track-list/0/lang", "fra");
|
|
check_string("track-list/0/id", "2");
|
|
check_string("track-list/0/program-id", "1");
|
|
check_string("track-list/0/program-ids", "1,2");
|
|
check_string("track-list/0/selected", "no");
|
|
check_string("track-list/1/type", "video");
|
|
check_string("track-list/1/id", "2");
|
|
check_string("track-list/1/program-id", "2");
|
|
check_string("track-list/1/selected", "yes");
|
|
check_string("track-list/2/lang", "jpn");
|
|
check_string("track-list/2/id", "3");
|
|
check_string("track-list/2/program-id", "2");
|
|
check_string("track-list/2/selected", "no");
|
|
|
|
set_property_string("slang", "eng");
|
|
|
|
// no eng subs in edition 1
|
|
reload_file(path);
|
|
check_string("track-list/count", "3");
|
|
check_string("track-list/0/lang", "fra");
|
|
check_string("track-list/0/id", "2");
|
|
check_string("track-list/0/selected", "no");
|
|
check_string("track-list/1/type", "video");
|
|
check_string("track-list/1/id", "2");
|
|
check_string("track-list/1/selected", "yes");
|
|
check_string("track-list/2/lang", "jpn");
|
|
check_string("track-list/2/id", "3");
|
|
check_string("track-list/2/selected", "no");
|
|
|
|
check_string("current-tracks/video/id", "2");
|
|
check_string("current-tracks/video/program-id", "2");
|
|
|
|
// eng subs in edition 0
|
|
set_property_string("edition", "0");
|
|
check_string("current-edition", "0");
|
|
check_string("track-list/count", "3");
|
|
check_string("track-list/0/id", "1");
|
|
check_string("track-list/0/program-id", "1");
|
|
check_string("track-list/0/selected", "yes");
|
|
check_string("track-list/1/id", "1");
|
|
check_string("track-list/1/program-id", "1");
|
|
check_string("track-list/1/lang", "eng");
|
|
check_string("track-list/1/selected", "yes");
|
|
check_string("track-list/2/lang", "fra");
|
|
check_string("track-list/2/id", "2");
|
|
check_string("track-list/2/program-ids", "1,2");
|
|
check_string("track-list/2/selected", "no");
|
|
|
|
check_string("current-tracks/sub/lang", "eng");
|
|
check_string("current-tracks/sub/id", "1");
|
|
check_string("current-tracks/sub/program-id", "1");
|
|
check_string("current-tracks/video/id", "1");
|
|
check_string("current-tracks/video/program-id", "1");
|
|
|
|
// reload should give the same result
|
|
reload_file(path);
|
|
check_string("current-edition", "0");
|
|
check_string("track-list/count", "3");
|
|
check_string("track-list/0/id", "1");
|
|
check_string("track-list/0/program-id", "1");
|
|
check_string("track-list/0/selected", "yes");
|
|
check_string("track-list/1/id", "1");
|
|
check_string("track-list/1/program-id", "1");
|
|
check_string("track-list/1/lang", "eng");
|
|
check_string("track-list/1/selected", "yes");
|
|
check_string("track-list/2/lang", "fra");
|
|
check_string("track-list/2/id", "2");
|
|
check_string("track-list/2/selected", "no");
|
|
|
|
check_string("current-tracks/sub/lang", "eng");
|
|
check_string("current-tracks/sub/id", "1");
|
|
check_string("current-tracks/sub/program-id", "1");
|
|
check_string("current-tracks/video/id", "1");
|
|
check_string("current-tracks/video/program-id", "1");
|
|
|
|
set_property_string("subs-fallback", "yes");
|
|
set_property_string("edition", "1");
|
|
// fra is selected: both fra and jpn are in-program for program 2, but fra
|
|
// has a lower tid
|
|
check_string("current-edition", "1");
|
|
check_string("track-list/count", "3");
|
|
check_string("track-list/0/lang", "fra");
|
|
check_string("track-list/0/id", "2");
|
|
check_string("track-list/0/selected", "yes");
|
|
check_string("track-list/1/type", "video");
|
|
check_string("track-list/1/id", "2");
|
|
check_string("track-list/1/selected", "yes");
|
|
check_string("track-list/2/lang", "jpn");
|
|
check_string("track-list/2/id", "3");
|
|
check_string("track-list/2/selected", "no");
|
|
check_string("current-tracks/sub/lang", "fra");
|
|
check_string("current-tracks/sub/id", "2");
|
|
|
|
check_string("current-edition", "1");
|
|
check_string("track-list/count", "3");
|
|
check_string("track-list/0/lang", "fra");
|
|
check_string("track-list/0/id", "2");
|
|
check_string("track-list/0/program-id", "1");
|
|
check_string("track-list/0/selected", "yes");
|
|
check_string("track-list/1/id", "2");
|
|
check_string("track-list/1/program-id", "2");
|
|
check_string("track-list/1/selected", "yes");
|
|
|
|
check_string("current-tracks/sub/lang", "fra");
|
|
check_string("current-tracks/sub/id", "2");
|
|
check_string("current-tracks/sub/program-id", "1");
|
|
check_string("current-tracks/video/id", "2");
|
|
check_string("current-tracks/video/program-id", "2");
|
|
|
|
// flatten-editions: all 5 tracks exposed, no edition filtering
|
|
set_property_string("flatten-editions", "yes");
|
|
set_property_string("edition", "auto");
|
|
set_property_string("slang", "");
|
|
set_property_string("subs-fallback", "no");
|
|
reload_file(path);
|
|
check_string("track-list/count", "5");
|
|
check_string("edition-list/count", "0");
|
|
|
|
// video from program 1 selected (first video), no sub selected
|
|
check_string("track-list/0/type", "video");
|
|
check_string("track-list/0/id", "1");
|
|
check_string("track-list/0/program-id", "1");
|
|
check_string("track-list/0/selected", "yes");
|
|
check_string("track-list/1/lang", "eng");
|
|
check_string("track-list/1/id", "1");
|
|
check_string("track-list/1/program-id", "1");
|
|
check_string("track-list/2/lang", "fra");
|
|
check_string("track-list/2/id", "2");
|
|
check_string("track-list/2/program-id", "1");
|
|
check_string("track-list/2/program-ids", "1,2");
|
|
check_string("track-list/3/type", "video");
|
|
check_string("track-list/3/id", "2");
|
|
check_string("track-list/3/program-id", "2");
|
|
check_string("track-list/4/lang", "jpn");
|
|
check_string("track-list/4/id", "3");
|
|
check_string("track-list/4/program-id", "2");
|
|
check_string("current-tracks/video/id", "1");
|
|
check_string("current-tracks/video/program-id", "1");
|
|
check_string("sid", "no");
|
|
|
|
// eng sub in video 1 is picked when slang=eng
|
|
set_property_string("slang", "eng");
|
|
reload_file(path);
|
|
check_string("current-tracks/video/id", "1");
|
|
check_string("current-tracks/video/program-id", "1");
|
|
check_string("current-tracks/sub/lang", "eng");
|
|
check_string("current-tracks/sub/id", "1");
|
|
check_string("current-tracks/sub/program-id", "1");
|
|
|
|
// no matching sub for video 2 with slang=jpn
|
|
set_property_string("vid", "2");
|
|
reload_file(path);
|
|
check_string("sid", "no");
|
|
|
|
// jpn sub in video 2 is picked when slang=jpn
|
|
set_property_string("vid", "2");
|
|
set_property_string("slang", "jpn");
|
|
reload_file(path);
|
|
check_string("current-tracks/video/id", "2");
|
|
check_string("current-tracks/video/program-id", "2");
|
|
check_string("current-tracks/sub/lang", "jpn");
|
|
check_string("current-tracks/sub/id", "3");
|
|
check_string("current-tracks/sub/program-id", "2");
|
|
|
|
// no matching sub for video 1 with slang=jpn
|
|
set_property_string("vid", "1");
|
|
reload_file(path);
|
|
check_string("sid", "no");
|
|
|
|
// fra sub in program 2 is picked when slang=fra
|
|
set_property_string("slang", "fra");
|
|
set_property_string("vid", "1");
|
|
reload_file(path);
|
|
check_string("current-tracks/video/id", "1");
|
|
check_string("current-tracks/video/program-id", "1");
|
|
check_string("current-tracks/sub/lang", "fra");
|
|
check_string("current-tracks/sub/id", "2");
|
|
check_string("current-tracks/sub/program-ids", "1,2");
|
|
set_property_string("vid", "2");
|
|
reload_file(path);
|
|
check_string("current-tracks/video/id", "2");
|
|
check_string("current-tracks/video/program-id", "2");
|
|
check_string("current-tracks/sub/lang", "fra");
|
|
check_string("current-tracks/sub/id", "2");
|
|
check_string("current-tracks/sub/program-ids", "1,2");
|
|
}
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
if (argc < 3)
|
|
return 1;
|
|
|
|
const char *locale_test_prefix = "locale";
|
|
if (strncmp(argv[1], locale_test_prefix, strlen(locale_test_prefix)) == 0 &&
|
|
!have_english_locale()) {
|
|
printf("Non English language detected. Skipping locale test.\n");
|
|
return 77;
|
|
}
|
|
|
|
ctx = mpv_create();
|
|
if (!ctx)
|
|
return 1;
|
|
|
|
atexit(exit_cleanup);
|
|
|
|
initialize();
|
|
|
|
const char *fmt = "================ TEST: %s %s ================\n";
|
|
printf(fmt, "test_track_selection", argv[1]);
|
|
test_track_selection(argv[1], argv[2]);
|
|
printf("================ SHUTDOWN ================\n");
|
|
|
|
command_string("quit");
|
|
while (wrap_wait_event()->event_id != MPV_EVENT_SHUTDOWN) {}
|
|
|
|
return 0;
|
|
}
|