test/libmpv: use common wrappers for properties and commands

This is mainly for better, more descriptive logging when something goes
wrong and fails. Common operations that manipulate properties and
commands go through shared functions that do better detailed logging.
Also it means we don't need check_api_error around anymore so get rid of
that. libmpv_lifetime is left untouched since that one is a bit special
and works a little differently.
This commit is contained in:
Dudemanguy committed 2025-10-02 15:15:48 +00:00
1 parent e0cf3f8061
commit 3bbb94077d
7 files changed
+123 -71

No files matched your search

+64 -12
View File
@@ -26,6 +26,15 @@
#include "osdep/compiler.h"
#define command(cmd) command_impl(__FILE__, __LINE__, (cmd))
#define command_string(cmd) command_string_impl(__FILE__, __LINE__, (cmd))
#define get_property(property, format, result) \
get_property_impl(__FILE__, __LINE__, (property), (format), (result))
#define set_option_or_property(property, format, value, option) \
set_option_or_property_impl(__FILE__, __LINE__, (property), (format), (value), (option))
#define set_property_string(property, value) \
set_property_string_impl(__FILE__, __LINE__, (property), (value))
// Global handle.
static mpv_handle *ctx;
MP_NORETURN PRINTF_ATTRIBUTE(1, 2)
@@ -65,16 +74,55 @@ static inline mpv_event *wrap_wait_event(void)
}
}
static inline void check_api_error(int status)
static inline void command_impl(const char *file, int line, const char *cmd[])
{
if (status < 0)
fail("mpv API error: %s\n", mpv_error_string(status));
int ret = mpv_command(ctx, cmd);
if (ret < 0)
fail("mpv API error while running command '%s' at %s:%d (%s)\n",
cmd[0], file, line, mpv_error_string(ret));
}
static inline void command_string_impl(const char *file, int line, const char *cmd)
{
int ret = mpv_command_string(ctx, cmd);
if (ret < 0)
fail("mpv API error while running command '%s' at %s:%d (%s)\n",
cmd, file, line, mpv_error_string(ret));
}
static inline void get_property_impl(const char *file, int line, const char *property,
int format, void *result)
{
int ret = mpv_get_property(ctx, property, format, result);
if (ret < 0)
fail("mpv API error while getting property '%s' at %s:%d (%s)\n",
property, file, line, mpv_error_string(ret));
}
static inline void set_option_or_property_impl(const char *file, int line, const char *property,
int format, void *value, bool option)
{
int ret = option ? mpv_set_option(ctx, property, format, value) :
mpv_set_property(ctx, property, format, value);
if (ret < 0)
fail("mpv API while setting %s '%s' at %s:%d (%s)\n", option ? "option" : "property",
property, file, line, mpv_error_string(ret));
}
static inline void set_property_string_impl(const char *file, int line, const char *property,
const char *value)
{
int ret = mpv_set_property_string(ctx, property, value);
if (ret < 0)
fail("mpv API error while setting property '%s' to '%s' at %s:%d (%s)\n",
property, value, file, line, mpv_error_string(ret));
}
MP_UNUSED static void check_double(const char *property, double expect)
{
double result_double;
check_api_error(mpv_get_property(ctx, property, MPV_FORMAT_DOUBLE, &result_double));
get_property(property, MPV_FORMAT_DOUBLE, &result_double);
if (expect != result_double)
fail("Double: expected '%f' but got '%f'!\n", expect, result_double);
}
@@ -82,7 +130,7 @@ MP_UNUSED static void check_double(const char *property, double expect)
MP_UNUSED static void check_flag(const char *property, int expect)
{
int result_flag;
check_api_error(mpv_get_property(ctx, property, MPV_FORMAT_FLAG, &result_flag));
get_property(property, MPV_FORMAT_FLAG, &result_flag);
if (expect != result_flag)
fail("Flag: expected '%d' but got '%d'!\n", expect, result_flag);
}
@@ -90,7 +138,7 @@ MP_UNUSED static void check_flag(const char *property, int expect)
MP_UNUSED static void check_int(const char *property, int64_t expect)
{
int64_t result_int;
check_api_error(mpv_get_property(ctx, property, MPV_FORMAT_INT64, &result_int));
get_property(property, MPV_FORMAT_INT64, &result_int);
if (expect != result_int)
fail("Int: expected '%" PRId64 "' but got '%" PRId64 "'!\n", expect, result_int);
}
@@ -98,7 +146,7 @@ MP_UNUSED static void check_int(const char *property, int64_t expect)
MP_UNUSED static inline void check_string(const char *property, const char *expect)
{
char *result_string;
check_api_error(mpv_get_property(ctx, property, MPV_FORMAT_STRING, &result_string));
get_property(property, MPV_FORMAT_STRING, &result_string);
if (strcmp(expect, result_string) != 0)
fail("String: expected '%s' but got '%s'!\n", expect, result_string);
mpv_free(result_string);
@@ -106,16 +154,20 @@ MP_UNUSED static inline void check_string(const char *property, const char *expe
static inline void initialize(void)
{
check_api_error(mpv_set_option_string(ctx, "vo", "null"));
check_api_error(mpv_set_option_string(ctx, "ao", "null"));
check_api_error(mpv_request_log_messages(ctx, "debug"));
check_api_error(mpv_initialize(ctx));
set_property_string("vo", "null");
set_property_string("ao", "null");
int ret = mpv_request_log_messages(ctx, "debug");
if (ret < 0)
fail("mpv API error while setting log level to debug: %s\n", mpv_error_string(ret));
ret = mpv_initialize(ctx);
if (ret < 0)
fail("mpv API error while initializing mpv: %s\n", mpv_error_string(ret));
}
static inline void reload_file(const char *path)
{
const char *cmd[] = {"loadfile", path, NULL};
check_api_error(mpv_command(ctx, cmd));
command(cmd);
bool loaded = false;
while (!loaded) {
mpv_event *event = wrap_wait_event();
+7 -7
View File
@@ -93,19 +93,19 @@ int main(int argc, char *argv[])
out_path = path;
#endif
check_api_error(mpv_set_option_string(ctx, "o", out_path));
check_api_error(mpv_set_option_string(ctx, "of", "matroska"));
check_api_error(mpv_set_option_string(ctx, "end", "1.5"));
check_api_error(mpv_set_option_string(ctx, "terminal", "yes"));
check_api_error(mpv_set_option_string(ctx, "msg-level", "all=v"));
set_property_string("o", out_path);
set_property_string("of", "matroska");
set_property_string("end", "1.5");
set_property_string("terminal", "yes");
set_property_string("msg-level", "all=v");
if (mpv_initialize(ctx) != 0)
return 1;
check_api_error(mpv_set_option_string(ctx, "idle", "once"));
set_property_string("idle", "once");
const char *cmd[] = {"loadfile", "av://lavfi:testsrc", NULL};
check_api_error(mpv_command(ctx, cmd));
command(cmd);
wait_done();
mpv_destroy(ctx);
+2 -2
View File
@@ -20,7 +20,7 @@
static void test_file_loading(char *file)
{
const char *cmd[] = {"loadfile", file, NULL};
check_api_error(mpv_command(ctx, cmd));
command(cmd);
bool loaded = false;
bool finished = false;
while (!finished) {
@@ -58,7 +58,7 @@ int main(int argc, char *argv[])
test_file_loading(argv[1]);
printf("================ SHUTDOWN ================\n");
mpv_command_string(ctx, "quit");
command_string("quit");
while (wrap_wait_event()->event_id != MPV_EVENT_SHUTDOWN) {}
return 0;
+5 -5
View File
@@ -20,7 +20,7 @@
static void test_lavfi_complex(char *file)
{
const char *cmd[] = {"loadfile", file, NULL};
check_api_error(mpv_command(ctx, cmd));
command(cmd);
bool finished = false;
bool loaded = false;
while (!finished) {
@@ -29,10 +29,10 @@ static void test_lavfi_complex(char *file)
case MPV_EVENT_FILE_LOADED:
// Add file as external and toggle lavfi-complex on.
if (!loaded) {
check_api_error(mpv_set_property_string(ctx, "external-files", file));
set_property_string("external-files", file);
const char *add_cmd[] = {"video-add", file, "auto", NULL};
check_api_error(mpv_command(ctx, add_cmd));
check_api_error(mpv_set_property_string(ctx, "lavfi-complex", "[vid1] [vid2] vstack [vo]"));
command(add_cmd);
set_property_string("lavfi-complex", "[vid1] [vid2] vstack [vo]");
}
loaded = true;
break;
@@ -64,7 +64,7 @@ int main(int argc, char *argv[])
test_lavfi_complex(argv[1]);
printf("================ SHUTDOWN ================\n");
mpv_command_string(ctx, "quit");
command_string("quit");
while (wrap_wait_event()->event_id != MPV_EVENT_SHUTDOWN) {}
return 0;
+10 -10
View File
@@ -49,20 +49,20 @@ static void set_options_and_properties(const char *options[], const char *proper
for (int i = 0; options[i]; i++) {
switch (formats[i]) {
case MPV_FORMAT_STRING:
check_api_error(mpv_set_option(ctx, options[i], formats[i], &str));
check_api_error(mpv_set_property(ctx, properties[i], formats[i], &str));
set_option_or_property(options[i], formats[i], &str, true);
set_option_or_property(properties[i], formats[i], &str, false);
break;
case MPV_FORMAT_FLAG:
check_api_error(mpv_set_option(ctx, options[i], formats[i], &flag));
check_api_error(mpv_set_property(ctx, properties[i], formats[i], &flag));
set_option_or_property(options[i], formats[i], &flag, true);
set_option_or_property(properties[i], formats[i], &flag, false);
break;
case MPV_FORMAT_INT64:
check_api_error(mpv_set_option(ctx, options[i], formats[i], &int_));
check_api_error(mpv_set_property(ctx, properties[i], formats[i], &int_));
set_option_or_property(options[i], formats[i], &int_, true);
set_option_or_property(properties[i], formats[i], &int_, false);
break;
case MPV_FORMAT_DOUBLE:
check_api_error(mpv_set_option(ctx, options[i], formats[i], &double_));
check_api_error(mpv_set_property(ctx, properties[i], formats[i], &double_));
set_option_or_property(options[i], formats[i], &double_, true);
set_option_or_property(properties[i], formats[i], &double_, false);
break;
}
}
@@ -105,7 +105,7 @@ static void test_options_and_properties(void)
// Ensure the format is still MPV_FORMAT_FLAG for these property types.
mpv_node result_node;
check_api_error(mpv_get_property(ctx, "idle-active", MPV_FORMAT_NODE, &result_node));
get_property("idle-active", MPV_FORMAT_NODE, &result_node);
if (result_node.format != MPV_FORMAT_FLAG)
fail("Node: expected mpv format '%d' but got '%d'!\n", MPV_FORMAT_FLAG, result_node.format);
@@ -132,7 +132,7 @@ int main(int argc, char *argv[])
test_options_and_properties();
printf("================ SHUTDOWN ================\n");
mpv_command_string(ctx, "quit");
command_string("quit");
while (wrap_wait_event()->event_id != MPV_EVENT_SHUTDOWN) {}
return 0;
+5 -5
View File
@@ -33,9 +33,9 @@ static void test_sdh_filter(char *file, char *path, char *harder)
if (ret)
fail("Test file, '%s', was not found!\n", path);
check_api_error(mpv_set_property_string(ctx, "sub-filter-sdh", "yes"));
set_property_string("sub-filter-sdh", "yes");
if (harder)
check_api_error(mpv_set_property_string(ctx, "sub-filter-sdh-harder", "yes"));
set_property_string("sub-filter-sdh-harder", "yes");
char *expect = "";
if (strcmp(file, "sdh_default") == 0 && harder) {
@@ -91,13 +91,13 @@ int main(int argc, char *argv[])
const char *fmt = "================ TEST: %s %s ================\n";
printf(fmt, "test_sdh_filter", argv[1]);
// Set pause and start from 1 second to ensure the subtitle is loaded.
mpv_set_property_string(ctx, "pause", "yes");
mpv_set_property_string(ctx, "start", "1");
set_property_string("pause", "yes");
set_property_string("start", "1");
mpv_observe_property(ctx, 0, "sub-text", MPV_FORMAT_STRING);
test_sdh_filter(argv[1], argv[2], argv[3]);
printf("================ SHUTDOWN ================\n");
mpv_command_string(ctx, "quit");
command_string("quit");
while (wrap_wait_event()->event_id != MPV_EVENT_SHUTDOWN) {}
return 0;
+30 -30
View File
@@ -106,12 +106,12 @@ static void test_track_selection(char *file, char *path)
check_string("current-tracks/sub/selected", "yes");
// --subs-falback=no
check_api_error(mpv_set_property_string(ctx, "subs-fallback", "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
check_api_error(mpv_set_property_string(ctx, "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 ||
@@ -125,7 +125,7 @@ static void test_track_selection(char *file, char *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
check_api_error(mpv_set_property_string(ctx, "subs-fallback-forced", "always"));
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) {
@@ -134,7 +134,7 @@ static void test_track_selection(char *file, char *path)
check_string("track-list/2/selected", "no");
// --subs-fallback=yes
check_api_error(mpv_set_property_string(ctx, "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) {
@@ -143,26 +143,26 @@ static void test_track_selection(char *file, char *path)
check_string("current-tracks/sub/lang", "eng");
// default german subs
check_api_error(mpv_set_property_string(ctx, "subs-match-os-language", "no"));
set_property_string("subs-match-os-language", "no");
reload_file(path);
check_string("current-tracks/sub/lang", "ger");
} else if (strcmp(file, "multilang.mkv") == 0) {
// --alang=jpn should select forced jpn subs
check_api_error(mpv_set_property_string(ctx, "alang", "jpn"));
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
check_api_error(mpv_set_property_string(ctx, "alang", "pol"));
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
check_api_error(mpv_set_property_string(ctx, "alang", "eng"));
check_api_error(mpv_set_property_string(ctx, "slang", "eng"));
check_api_error(mpv_set_property_string(ctx, "subs-with-matching-audio", "no"));
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");
@@ -171,65 +171,65 @@ static void test_track_selection(char *file, char *path)
check_string("track-list/8/selected", "no");
// --subs-with-matching-audio=forced checks
check_api_error(mpv_set_property_string(ctx, "subs-with-matching-audio", "forced"));
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
check_api_error(mpv_set_property_string(ctx, "alang", "jpn"));
check_api_error(mpv_set_property_string(ctx, "slang", "jpn"));
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
check_api_error(mpv_set_property_string(ctx, "alang", "ger"));
check_api_error(mpv_set_property_string(ctx, "slang", "ger"));
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
check_api_error(mpv_set_property_string(ctx, "alang", "it"));
check_api_error(mpv_set_property_string(ctx, "slang", "pt,it,pol,ger"));
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
check_api_error(mpv_set_property_string(ctx, "alang", "ger"));
check_api_error(mpv_set_property_string(ctx, "slang", "jpn,pol"));
check_api_error(mpv_set_property_string(ctx, "subs-with-matching-audio", "yes"));
check_api_error(mpv_set_property_string(ctx, "subs-fallback-forced", "always"));
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");
} else if (strcmp(file, "multilang2.mkv") == 0) {
// default jpn subs
check_api_error(mpv_set_property_string(ctx, "subs-match-os-language", "no"));
check_api_error(mpv_set_property_string(ctx, "alang", "jpn"));
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
check_api_error(mpv_set_property_string(ctx, "alang", "eng"));
set_property_string("alang", "eng");
reload_file(path);
check_string("track-list/4/selected", "yes");
// default jpn subs
check_api_error(mpv_set_property_string(ctx, "subs-fallback-forced", "no"));
set_property_string("subs-fallback-forced", "no");
reload_file(path);
check_string("track-list/3/selected", "yes");
// default eng subs
check_api_error(mpv_set_property_string(ctx, "slang", "eng"));
set_property_string("slang", "eng");
reload_file(path);
check_string("track-list/6/selected", "yes");
// no subs
check_api_error(mpv_set_property_string(ctx, "slang", ""));
check_api_error(mpv_set_property_string(ctx, "subs-fallback", "no"));
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");
@@ -237,7 +237,7 @@ static void test_track_selection(char *file, char *path)
check_string("track-list/6/selected", "no");
// untagged eng subs
check_api_error(mpv_set_property_string(ctx, "sid", "3"));
set_property_string("sid", "3");
reload_file(path);
check_string("track-list/5/selected", "yes");
}
@@ -266,7 +266,7 @@ int main(int argc, char *argv[])
test_track_selection(argv[1], argv[2]);
printf("================ SHUTDOWN ================\n");
mpv_command_string(ctx, "quit");
command_string("quit");
while (wrap_wait_event()->event_id != MPV_EVENT_SHUTDOWN) {}
return 0;