summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2018-05-01 02:38:59 +0200
committerJan Ekström <jeebjp@gmail.com>2018-05-03 01:20:01 +0300
commitfb9bbf2a0d7f8dba0d0674595cc2dc0dab68ad94 (patch)
treeb386f221e961ad81e35a3bc23bb66320ba942b80
parente8b073584d749bb864f495d9e1cd31b102c6283d (diff)
downloadmpv-fb9bbf2a0d7f8dba0d0674595cc2dc0dab68ad94.tar.bz2
mpv-fb9bbf2a0d7f8dba0d0674595cc2dc0dab68ad94.tar.xz
command: split big command handler switch into separate functions
This gets rid of run_command() and its big switch statement, which was an idiotically big function of almost 1000 lines. The switch is replaced with a callback per command, and each command is now implemented in its own function. Command IDs are not needed anymore, so the mp_command_type enum disappears. There should be no functional changes, but since this refactors 64 commands, regressions are possible. The handler() parameter is void*, because in theory the input code is supposed to be independent of the player core code. For example, you should be able to reuse the command parser code for some other part of mpv. In practice, the variable containing command list is defined in the player core anyway, so you could say this doesn't work. But I'm still trying to hold onto this idea, so I went with void*.
-rw-r--r--input/cmd_list.h92
-rw-r--r--input/cmd_parse.c3
-rw-r--r--player/command.c1770
-rw-r--r--player/command.h19
4 files changed, 1018 insertions, 866 deletions
diff --git a/input/cmd_list.h b/input/cmd_list.h
index c6d7c66100..5f44602907 100644
--- a/input/cmd_list.h
+++ b/input/cmd_list.h
@@ -25,10 +25,13 @@
#define MP_CMD_OPT_ARG 0x1000
+struct mp_cmd_ctx;
+
struct mp_cmd_def {
- int id; // one of MP_CMD_...
const char *name; // user-visible name (as used in input.conf)
+ void (*handler)(void *ctx);
const struct m_option args[MP_CMD_DEF_MAX_ARGS];
+ const void *priv; // for free use by handler()
bool allow_auto_repeat; // react to repeated key events
bool on_updown; // always emit it on both up and down key events
bool vararg; // last argument can be given 0 to multiple times
@@ -40,93 +43,6 @@ struct mp_cmd_def {
extern const struct mp_cmd_def mp_cmds[];
-// All command IDs
-enum mp_command_type {
- MP_CMD_IGNORE,
- MP_CMD_SEEK,
- MP_CMD_REVERT_SEEK,
- MP_CMD_QUIT,
- MP_CMD_QUIT_WATCH_LATER,
- MP_CMD_PLAYLIST_NEXT,
- MP_CMD_PLAYLIST_PREV,
- MP_CMD_SCREENSHOT,
- MP_CMD_SCREENSHOT_TO_FILE,
- MP_CMD_SCREENSHOT_RAW,
- MP_CMD_LOADFILE,
- MP_CMD_LOADLIST,
- MP_CMD_PLAYLIST_CLEAR,
- MP_CMD_PLAYLIST_REMOVE,
- MP_CMD_PLAYLIST_MOVE,
- MP_CMD_PLAYLIST_SHUFFLE,
- MP_CMD_SUB_STEP,
- MP_CMD_SUB_SEEK,
- MP_CMD_TV_LAST_CHANNEL,
- MP_CMD_FRAME_STEP,
- MP_CMD_FRAME_BACK_STEP,
- MP_CMD_RUN,
- MP_CMD_SUB_ADD,
- MP_CMD_SUB_REMOVE,
- MP_CMD_SUB_RELOAD,
- MP_CMD_SET,
- MP_CMD_CHANGE_LIST,
- MP_CMD_PRINT_TEXT,
- MP_CMD_SHOW_TEXT,
- MP_CMD_EXPAND_TEXT,
- MP_CMD_SHOW_PROGRESS,
- MP_CMD_ADD,
- MP_CMD_CYCLE,
- MP_CMD_MULTIPLY,
- MP_CMD_CYCLE_VALUES,
- MP_CMD_STOP,
- MP_CMD_AUDIO_ADD,
- MP_CMD_AUDIO_REMOVE,
- MP_CMD_AUDIO_RELOAD,
-
- MP_CMD_ENABLE_INPUT_SECTION,
- MP_CMD_DISABLE_INPUT_SECTION,
- MP_CMD_DEFINE_INPUT_SECTION,
-
- MP_CMD_AB_LOOP,
-
- MP_CMD_DROP_BUFFERS,
-
- MP_CMD_MOUSE,
- MP_CMD_KEYPRESS,
- MP_CMD_KEYDOWN,
- MP_CMD_KEYUP,
-
- /// Audio Filter commands
- MP_CMD_AF,
- MP_CMD_AF_COMMAND,
- MP_CMD_AO_RELOAD,
-
- /// Video filter commands
- MP_CMD_VF,
- MP_CMD_VF_COMMAND,
-
- /// Internal for Lua scripts
- MP_CMD_SCRIPT_BINDING,
- MP_CMD_SCRIPT_MESSAGE,
- MP_CMD_SCRIPT_MESSAGE_TO,
-
- MP_CMD_OVERLAY_ADD,
- MP_CMD_OVERLAY_REMOVE,
-
- MP_CMD_WRITE_WATCH_LATER_CONFIG,
-
- MP_CMD_HOOK_ADD,
- MP_CMD_HOOK_ACK,
-
- MP_CMD_RESCAN_EXTERNAL_FILES,
-
- MP_CMD_APPLY_PROFILE,
-
- MP_CMD_LOAD_SCRIPT,
-
- // Internal
- MP_CMD_COMMAND_LIST, // list of sub-commands in args[0].v.p
-};
-
// Executing this command will maybe abort playback (play something else, or quit).
struct mp_cmd;
bool mp_input_is_maybe_abort_cmd(struct mp_cmd *cmd);
diff --git a/input/cmd_parse.c b/input/cmd_parse.c
index ae518fdf98..f401e5b9c7 100644
--- a/input/cmd_parse.c
+++ b/input/cmd_parse.c
@@ -29,7 +29,6 @@
#include "libmpv/client.h"
const struct mp_cmd_def mp_cmd_list = {
- .id = MP_CMD_COMMAND_LIST,
.name = "list",
};
@@ -87,7 +86,6 @@ static bool find_cmd(struct mp_log *log, struct mp_cmd *cmd, bstr name)
if (strcmp(nname, mp_cmds[n].name) == 0) {
cmd->def = &mp_cmds[n];
cmd->name = (char *)cmd->def->name;
- cmd->id = cmd->def->id;
return true;
}
}
@@ -341,7 +339,6 @@ mp_cmd_t *mp_input_parse_cmd_(struct mp_log *log, bstr str, const char *loc)
struct mp_cmd *list = talloc_ptrtype(NULL, list);
talloc_set_destructor(list, destroy_cmd);
*list = (struct mp_cmd) {
- .id = mp_cmd_list.id,
.name = (char *)mp_cmd_list.name,
.def = &mp_cmd_list,
.original = bstrdup(list, original),
diff --git a/player/command.c b/player/command.c
index c820a1ceb5..d5cedb235a 100644
--- a/player/command.c
+++ b/player/command.c
@@ -4582,11 +4582,16 @@ static void replace_overlay(struct MPContext *mpctx, int id, struct overlay *new
recreate_overlays(mpctx);
}
-static int overlay_add(struct MPContext *mpctx, int id, int x, int y,
- char *file, int offset, char *fmt, int w, int h,
- int stride)
+static void cmd_overlay_add(void *pcmd)
{
- int r = -1;
+ struct mp_cmd_ctx *cmd = pcmd;
+ struct MPContext *mpctx = cmd->mpctx;
+ int id = cmd->args[0].v.i, x = cmd->args[1].v.i, y = cmd->args[2].v.i;
+ char *file = cmd->args[3].v.s;
+ int offset = cmd->args[4].v.i;
+ char *fmt = cmd->args[5].v.s;
+ int w = cmd->args[6].v.i, h = cmd->args[7].v.i, stride = cmd->args[8].v.i;
+
if (strcmp(fmt, "bgra") != 0) {
MP_ERR(mpctx, "overlay-add: unsupported OSD format '%s'\n", fmt);
goto error;
@@ -4644,15 +4649,18 @@ static int overlay_add(struct MPContext *mpctx, int id, int x, int y,
munmap(p, map_size);
replace_overlay(mpctx, id, &overlay);
- r = 0;
+ return;
error:
- return r;
+ cmd->success = false;
}
-static void overlay_remove(struct MPContext *mpctx, int id)
+static void cmd_overlay_remove(void *p)
{
- struct command_ctx *cmd = mpctx->command_ctx;
- if (id >= 0 && id < cmd->num_overlays)
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
+ struct command_ctx *cmdctx = mpctx->command_ctx;
+ int id = cmd->args[0].v.i;
+ if (id >= 0 && id < cmdctx->num_overlays)
replace_overlay(mpctx, id, &(struct overlay){0});
}
@@ -4662,7 +4670,7 @@ static void overlay_uninit(struct MPContext *mpctx)
if (!mpctx->osd)
return;
for (int id = 0; id < cmd->num_overlays; id++)
- overlay_remove(mpctx, id);
+ replace_overlay(mpctx, id, &(struct overlay){0});
osd_set_external2(mpctx->osd, NULL);
for (int n = 0; n < 2; n++)
mp_image_unrefp(&cmd->overlay_osd[n].packed);
@@ -4708,36 +4716,32 @@ static bool check_property_scalable(char *property, struct MPContext *mpctx)
prop.type == &m_option_type_aspect;
}
-static int show_property_status(struct MPContext *mpctx, struct mp_cmd *cmd,
- const char *name, int r)
+static void show_property_status(struct mp_cmd_ctx *cmd, const char *name, int r)
{
+ struct MPContext *mpctx = cmd->mpctx;
struct MPOpts *opts = mpctx->opts;
int osd_duration = opts->osd_duration;
- int on_osd = cmd->flags & MP_ON_OSD_FLAGS;
- bool auto_osd = on_osd == MP_ON_OSD_AUTO;
- bool msg_osd = auto_osd || (on_osd & MP_ON_OSD_MSG);
- int osdl = msg_osd ? 1 : OSD_LEVEL_INVISIBLE;
+ int osdl = cmd->msg_osd ? 1 : OSD_LEVEL_INVISIBLE;
if (r == M_PROPERTY_OK || r == M_PROPERTY_UNAVAILABLE) {
- show_property_osd(mpctx, name, on_osd);
+ show_property_osd(mpctx, name, cmd->on_osd);
if (r == M_PROPERTY_UNAVAILABLE)
- return -1;
+ cmd->success = false;
} else if (r == M_PROPERTY_UNKNOWN) {
set_osd_msg(mpctx, osdl, osd_duration, "Unknown property: '%s'", name);
- return -1;
+ cmd->success = false;
} else if (r <= 0) {
set_osd_msg(mpctx, osdl, osd_duration, "Failed to set property '%s'",
name);
- return -1;
+ cmd->success = false;
}
- return 0;
}
-static int change_property_cmd(struct MPContext *mpctx, struct mp_cmd *cmd,
- const char *name, int action, void *arg)
+static void change_property_cmd(struct mp_cmd_ctx *cmd,
+ const char *name, int action, void *arg)
{
- int r = mp_property_do(name, action, arg, mpctx);
- return show_property_status(mpctx, cmd, name, r);
+ int r = mp_property_do(name, action, arg, cmd->mpctx);
+ show_property_status(cmd, name, r);
}
static bool compare_values(struct m_option *type, void *a, void *b)
@@ -4752,8 +4756,10 @@ static bool compare_values(struct m_option *type, void *a, void *b)
return res;
}
-static int cycle_values_cmd(struct MPContext *mpctx, struct mp_cmd *cmd)
+static void cmd_cycle_values(void *p)
{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
int first = 0, dir = 1;
if (strcmp(cmd->args[first].v.s, "!reverse") == 0) {
@@ -4764,26 +4770,31 @@ static int cycle_values_cmd(struct MPContext *mpctx, struct mp_cmd *cmd)
const char *name = cmd->args[first].v.s;
first += 1;
- if (first >= cmd->nargs) {
+ if (first >= cmd->num_args) {
MP_ERR(mpctx, "cycle-values command does not have any value arguments.\n");
- return -1;
+ cmd->success = false;
+ return;
}
struct m_option prop = {0};
int r = mp_property_do(name, M_PROPERTY_GET_TYPE, &prop, mpctx);
- if (r <= 0)
- return show_property_status(mpctx, cmd, name, r);
+ if (r <= 0) {
+ show_property_status(cmd, name, r);
+ return;
+ }
union m_option_value curval = {0};
r = mp_property_do(name, M_PROPERTY_GET, &curval, mpctx);
- if (r <= 0)
- return show_property_status(mpctx, cmd, name, r);
+ if (r <= 0) {
+ show_property_status(cmd, name, r);
+ return;
+ }
// Find the current value. Note that we even though compare_values() uses
// strings internally, we need to convert the cycle-values arguments to
// native anyway to "normalize" the value for comparison.
int current = -1;
- for (int n = first; n < cmd->nargs; n++) {
+ for (int n = first; n < cmd->num_args; n++) {
union m_option_value val = {0};
if (m_option_parse(mpctx->log, &prop, bstr0(name),
bstr0(cmd->args[n].v.s), &val) <= 0)
@@ -4803,32 +4814,37 @@ static int cycle_values_cmd(struct MPContext *mpctx, struct mp_cmd *cmd)
if (current >= 0) {
current += dir;
if (current < first)
- current = cmd->nargs - 1;
- if (current >= cmd->nargs)
+ current = cmd->num_args - 1;
+ if (current >= cmd->num_args)
current = first;
} else {
MP_VERBOSE(mpctx, "Current value not found. Picking default.\n");
- current = dir > 0 ? first : cmd->nargs - 1;
+ current = dir > 0 ? first : cmd->num_args - 1;
}
- return change_property_cmd(mpctx, cmd, name, M_PROPERTY_SET_STRING,
- cmd->args[current].v.s);
+ change_property_cmd(cmd, name, M_PROPERTY_SET_STRING, cmd->args[current].v.s);
}
int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *res)
{
- struct command_ctx *cmdctx = mpctx->command_ctx;
- struct MPOpts *opts = mpctx->opts;
- int osd_duration = opts->osd_duration;
- int on_osd = cmd->flags & MP_ON_OSD_FLAGS;
- bool auto_osd = on_osd == MP_ON_OSD_AUTO;
- bool msg_osd = auto_osd || (on_osd & MP_ON_OSD_MSG);
- bool bar_osd = auto_osd || (on_osd & MP_ON_OSD_BAR);
- bool seek_msg_osd = auto_osd ? opts->osd_on_seek & 2 : msg_osd;
- bool seek_bar_osd = auto_osd ? opts->osd_on_seek & 1 : bar_osd;
+ struct mpv_node dummy_node = {0};
+ struct mp_cmd_ctx *ctx = &(struct mp_cmd_ctx){
+ .mpctx = mpctx,
+ .cmd = cmd,
+ .args = cmd->args,
+ .num_args = cmd->nargs,
+ .priv = cmd->def->priv,
+ .success = true,
+ .result = res ? res : &dummy_node,
+ };
- int osdl = msg_osd ? 1 : OSD_LEVEL_INVISIBLE;
- bool async = cmd->flags & MP_ASYNC_CMD;
+ struct MPOpts *opts = mpctx->opts;
+ ctx->on_osd = cmd->flags & MP_ON_OSD_FLAGS;
+ bool auto_osd = ctx->on_osd == MP_ON_OSD_AUTO;
+ ctx->msg_osd = auto_osd || (ctx->on_osd & MP_ON_OSD_MSG);
+ ctx->bar_osd = auto_osd || (ctx->on_osd & MP_ON_OSD_BAR);
+ ctx->seek_msg_osd = auto_osd ? opts->osd_on_seek & 2 : ctx->msg_osd;
+ ctx->seek_bar_osd = auto_osd ? opts->osd_on_seek & 1 : ctx->bar_osd;
mp_cmd_dump(mpctx->log, cmd->def->is_ignore ? MSGL_TRACE : MSGL_DEBUG,
"Run command:", cmd);
@@ -4845,774 +4861,959 @@ int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *re
}
}
- switch (cmd->id) {
- case MP_CMD_SEEK: {
- double v = cmd->args[0].v.d * cmd->scale;
- int abs = cmd->args[1].v.i & 3;
- enum seek_precision precision = MPSEEK_DEFAULT;
- switch (((cmd->args[2].v.i | cmd->args[1].v.i) >> 3) & 3) {
- case 1: precision = MPSEEK_KEYFRAME; break;
- case 2: precision = MPSEEK_EXACT; break;
- }
- if (!mpctx->playback_initialized)
- return -1;
- mark_seek(mpctx);
- switch (abs) {
- case 0: { // Relative seek
- queue_seek(mpctx, MPSEEK_RELATIVE, v, precision, MPSEEK_FLAG_DELAY);
- set_osd_function(mpctx, (v > 0) ? OSD_FFW : OSD_REW);
- break;
- }
- case 1: { // Absolute seek by percentage
- double ratio = v / 100.0;
- double cur_pos = get_current_pos_ratio(mpctx, false);
- queue_seek(mpctx, MPSEEK_FACTOR, ratio, precision, MPSEEK_FLAG_DELAY);
- set_osd_function(mpctx, cur_pos < ratio ? OSD_FFW : OSD_REW);
- break;
- }
- case 2: { // Absolute seek to a timestamp in seconds
- if (v < 0) {
- // Seek from end
- double len = get_time_length(mpctx);
- if (len < 0)
- return -1;
- v = MPMAX(0, len + v);
+ if (cmd->def == &mp_cmd_list) {
+ for (struct mp_cmd *sub = cmd->args[0].v.p; sub; sub = sub->queue_next)
+ run_command(mpctx, sub, NULL);
+ } else {
+ assert(cmd->def->handler);
+ cmd->def->handler(ctx);
+ }
+
+ if (!ctx->success)
+ mpv_free_node_contents(ctx->result);
+
+ mpv_free_node_contents(&dummy_node);
+
+ return ctx->success ? 0 : -1;
+}
+
+static void cmd_seek(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
+
+ double v = cmd->args[0].v.d * cmd->cmd->scale;
+ int abs = cmd->args[1].v.i & 3;
+ enum seek_precision precision = MPSEEK_DEFAULT;
+ switch (((cmd->args[2].v.i | cmd->args[1].v.i) >> 3) & 3) {
+ case 1: precision = MPSEEK_KEYFRAME; break;
+ case 2: precision = MPSEEK_EXACT; break;
+ }
+ if (!mpctx->playback_initialized) {
+ cmd->success = false;
+ return;
+ }
+
+ mark_seek(mpctx);
+ switch (abs) {
+ case 0: { // Relative seek
+ queue_seek(mpctx, MPSEEK_RELATIVE, v, precision, MPSEEK_FLAG_DELAY);
+ set_osd_function(mpctx, (v > 0) ? OSD_FFW : OSD_REW);
+ break;
+ }
+ case 1: { // Absolute seek by percentage
+ double ratio = v / 100.0;
+ double cur_pos = get_current_pos_ratio(mpctx, false);
+ queue_seek(mpctx, MPSEEK_FACTOR, ratio, precision, MPSEEK_FLAG_DELAY);
+ set_osd_function(mpctx, cur_pos < ratio ? OSD_FFW : OSD_REW);
+ break;
+ }
+ case 2: { // Absolute seek to a timestamp in seconds
+ if (v < 0) {
+ // Seek from end
+ double len = get_time_length(mpctx);
+ if (len < 0) {
+ cmd->success = false;
+ return;
}
- queue_seek(mpctx, MPSEEK_ABSOLUTE, v, precision, MPSEEK_FLAG_DELAY);
- set_osd_function(mpctx,
- v > get_current_time(mpctx) ? OSD_FFW : OSD_REW);
- break;
+ v = MPMAX(0, len + v);
}
- case 3: { // Relative seek by percentage
- queue_seek(mpctx, MPSEEK_FACTOR,
- get_current_pos_ratio(mpctx, false) + v / 100.0,
- precision, MPSEEK_FLAG_DELAY);
- set_osd_function(mpctx, v > 0 ? OSD_FFW : OSD_REW);
- break;
- }}
- if (seek_bar_osd)
+ queue_seek(mpctx, MPSEEK_ABSOLUTE, v, precision, MPSEEK_FLAG_DELAY);
+ set_osd_function(mpctx,
+ v > get_current_time(mpctx) ? OSD_FFW : OSD_REW);
+ break;
+ }
+ case 3: { // Relative seek by percentage
+ queue_seek(mpctx, MPSEEK_FACTOR,
+ get_current_pos_ratio(mpctx, false) + v / 100.0,
+ precision, MPSEEK_FLAG_DELAY);
+ set_osd_function(mpctx, v > 0 ? OSD_FFW : OSD_REW);
+ break;
+ }}
+ if (cmd->seek_bar_osd)
+ mpctx->add_osd_seek_info |= OSD_SEEK_INFO_BAR;
+ if (cmd->seek_msg_osd)
+ mpctx->add_osd_seek_info |= OSD_SEEK_INFO_TEXT;
+}
+
+static void cmd_revert_seek(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
+ struct command_ctx *cmdctx = mpctx->command_ctx;
+
+ if (!mpctx->playback_initialized) {
+ cmd->success = false;
+ return;
+ }
+
+ double oldpts = cmdctx->last_seek_pts;
+ if (cmdctx->marked_pts != MP_NOPTS_VALUE)
+ oldpts = cmdctx->marked_pts;
+ if (cmd->args[0].v.i == 1) {
+ cmdctx->marked_pts = get_current_time(mpctx);
+ } else if (oldpts != MP_NOPTS_VALUE) {
+ cmdctx->last_seek_pts = get_current_time(mpctx);
+ cmdctx->marked_pts = MP_NOPTS_VALUE;
+ queue_seek(mpctx, MPSEEK_ABSOLUTE, oldpts, MPSEEK_EXACT,
+ MPSEEK_FLAG_DELAY);
+ set_osd_function(mpctx, OSD_REW);
+ if (cmd->seek_bar_osd)
mpctx->add_osd_seek_info |= OSD_SEEK_INFO_BAR;
- if (seek_msg_osd)
+ if (cmd->seek_msg_osd)
mpctx->add_osd_seek_info |= OSD_SEEK_INFO_TEXT;
- break;
+ } else {
+ cmd->success = false;
}
+}
- case MP_CMD_REVERT_SEEK: {
- if (!mpctx->playback_initialized)
- return -1;
- double oldpts = cmdctx->last_seek_pts;
- if (cmdctx->marked_pts != MP_NOPTS_VALUE)
- oldpts = cmdctx->marked_pts;
- if (cmd->args[0].v.i == 1) {
- cmdctx->marked_pts = get_current_time(mpctx);
- } else if (oldpts != MP_NOPTS_VALUE) {
- cmdctx->last_seek_pts = get_current_time(mpctx);
- cmdctx->marked_pts = MP_NOPTS_VALUE;
- queue_seek(mpctx, MPSEEK_ABSOLUTE, oldpts, MPSEEK_EXACT,
- MPSEEK_FLAG_DELAY);
- set_osd_function(mpctx, OSD_REW);
- if (seek_bar_osd)
- mpctx->add_osd_seek_info |= OSD_SEEK_INFO_BAR;
- if (seek_msg_osd)
- mpctx->add_osd_seek_info |= OSD_SEEK_INFO_TEXT;
- } else {
- return -1;
- }
- break;
+static void cmd_set(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+
+ change_property_cmd(cmd, cmd->args[0].v.s,
+ M_PROPERTY_SET_STRING, cmd->args[1].v.s);
+}
+
+static void cmd_change_list(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
+ char *name = cmd->args[0].v.s;
+ char *op = cmd->args[1].v.s;
+ char *value = cmd->args[2].v.s;
+ int osd_duration = mpctx->opts->osd_duration;
+ int osdl = cmd->msg_osd ? 1 : OSD_LEVEL_INVISIBLE;
+
+ struct m_config_option *co = m_config_get_co(mpctx->mconfig, bstr0(name));
+ if (!co) {
+ set_osd_msg(mpctx, osdl, osd_duration, "Unknown option: '%s'", name);
+ cmd->success = false;
+ return;
}
- case MP_CMD_SET: {
- return change_property_cmd(mpctx, cmd, cmd->args[0].v.s,
- M_PROPERTY_SET_STRING, cmd->args[1].v.s);
+ const struct m_option_type *type = co->opt->type;
+ bool found = false;
+ for (int i = 0; type->actions && type->actions[i].name; i++) {
+ const struct m_option_action *action = &type->actions[i];
+ if (strcmp(action->name, op) == 0)
+ found = true;
+ }
+ if (!found) {
+ set_osd_msg(mpctx, osdl, osd_duration, "Unknown action: '%s'", op);
+ cmd->success = false;
+ return;
}
- case MP_CMD_CHANGE_LIST: {
- char *name = cmd->args[0].v.s;
- char *op = cmd->args[1].v.s;
- char *value = cmd->args[2].v.s;
- struct m_config_option *co = m_config_get_co(mpctx->mconfig, bstr0(name));
- if (!co) {
- set_osd_msg(mpctx, osdl, osd_duration, "Unknown option: '%s'", name);
- return -1;
- }
- const struct m_option_type *type = co->opt->type;
- bool found = false;
- for (int i = 0; type->actions && type->actions[i].name; i++) {
- const struct m_option_action *action = &type->actions[i];
- if (strcmp(action->name, op) == 0)
- found = true;
- }
- if (!found) {
- set_osd_msg(mpctx, osdl, osd_duration, "Unknown action: '%s'", op);
- return -1;
- }
- char *optname = mp_tprintf(80, "%s-%s", name, op); // the dirty truth
- int r = m_config_set_option_cli(mpctx->mconfig, bstr0(optname),
- bstr0(value), M_SETOPT_RUNTIME);
- if (r < 0) {
- set_osd_msg(mpctx, osdl, osd_duration,
- "Failed setting option: '%s'", name);
- return -1;
- }
- show_property_osd(mpctx, name, on_osd);
- break;
+ char *optname = mp_tprintf(80, "%s-%s", name, op); // the dirty truth
+ int r = m_config_set_option_cli(mpctx->mconfig, bstr0(optname),
+ bstr0(value), M_SETOPT_RUNTIME);
+ if (r < 0) {
+ set_osd_msg(mpctx, osdl, osd_duration,
+ "Failed setting option: '%s'", name);
+ cmd->success = false;
+ return;
}
- case MP_CMD_ADD:
- case MP_CMD_CYCLE:
- {
- char *property = cmd->args[0].v.s;
- if (cmd->repeated && !check_property_autorepeat(property, mpctx)) {
- MP_VERBOSE(mpctx, "Dropping command '%.*s' from auto-repeated key.\n",
- BSTR_P(cmd->original));
- break;
- }
- double scale = 1;
- int scale_units = cmd->scale_units;
- if (check_property_scalable(property, mpctx)) {
- scale = cmd->scale;
- scale_units = 1;
- }
- for (int i = 0; i < scale_units; i++) {
- struct m_property_switch_arg s = {
- .inc = cmd->args[1].v.d * scale,
- .wrap = cmd->id == MP_CMD_CYCLE,
- };
- int r =
- change_property_cmd(mpctx, cmd, property, M_PROPERTY_SWITCH, &s);
- if (r < 0)
- return r;
- }
- break;
+ show_property_osd(mpctx, name, cmd->on_osd);
+}
+
+static void cmd_add_cycle(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
+ bool is_cycle = !!cmd->priv;
+
+ char *property = cmd->args[0].v.s;
+ if (cmd->cmd->repeated && !check_property_autorepeat(property, mpctx)) {
+ MP_VERBOSE(mpctx, "Dropping command '%.*s' from auto-repeated key.\n",
+ BSTR_P(cmd->cmd->original));
+ return;
}
- case MP_CMD_MULTIPLY: {
- return change_property_cmd(mpctx, cmd, cmd->args[0].v.s,
- M_PROPERTY_MULTIPLY, &cmd->args[1].v.d);
+ double scale = 1;
+ int scale_units = cmd->cmd->scale_units;
+ if (check_property_scalable(property, mpctx)) {
+ scale = cmd->cmd->scale;
+ scale_units = 1;
}
- case MP_CMD_CYCLE_VALUES:
- return cycle_values_cmd(mpctx, cmd);
+ for (int i = 0; i < scale_units; i++) {
+ struct m_property_switch_arg s = {
+ .inc = cmd->args[1].v.d * scale,
+ .wrap = is_cycle,
+ };
+ change_property_cmd(cmd, property, M_PROPERTY_SWITCH, &s);
+ if (!cmd->success)
+ return;
+ }
+}
+
+static void cmd_multiply(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+
+ change_property_cmd(cmd, cmd->args[0].v.s,
+ M_PROPERTY_MULTIPLY, &cmd->args[1].v.d);
+}
+
+static void cmd_frame_step(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
- case MP_CMD_FRAME_STEP:
- if (!mpctx->playback_initialized)
- return -1;
- if (cmd->is_up_down) {
- if (cmd->is_up) {
- if (mpctx->step_frames < 1)
- set_pause_state(mpctx, true);
+ if (!mpctx->playback_initialized) {
+ cmd->success = false;
+ return;
+ }
+
+ if (cmd->cmd->is_up_down) {
+ if (cmd->cmd->is_up) {
+ if (mpctx->step_frames < 1)
+ set_pause_state(mpctx, true);
+ } else {
+ if (cmd->cmd->repeated) {
+ set_pause_state(mpctx, false);
} else {
- if (cmd->repeated) {
- set_pause_state(mpctx, false);
- } else {
- add_step_frame(mpctx, 1);
- }
+ add_step_frame(mpctx, 1);
}
- } else {
- add_step_frame(mpctx, 1);
}
- break;
+ } else {
+ add_step_frame(mpctx, 1);
+ }
+}
- case MP_CMD_FRAME_BACK_STEP:
- if (!mpctx->playback_initialized)
- return -1;
- add_step_frame(mpctx, -1);
- break;
+static void cmd_frame_back_step(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
- case MP_CMD_QUIT:
- case MP_CMD_QUIT_WATCH_LATER:
- if (cmd->id == MP_CMD_QUIT_WATCH_LATER || opts->position_save_on_quit)
- mp_write_watch_later_conf(mpctx);
- mpctx->stop_play = PT_QUIT;
- mpctx->quit_custom_rc = cmd->args[0].v.i;
- mpctx->has_quit_custom_rc = true;
- mp_wakeup_core(mpctx);
- break;
+ if (!mpctx->playback_initialized) {
+ cmd->success = false;
+ return;
+ }
- case MP_CMD_PLAYLIST_NEXT:
- case MP_CMD_PLAYLIST_PREV:
- {
- int dir = cmd->id == MP_CMD_PLAYLIST_PREV ? -1 : +1;
- int force = cmd->args[0].v.i;
+ add_step_frame(mpctx, -1);
+}
- struct playlist_entry *e = mp_next_file(mpctx, dir, force, true);
- if (!e && !force)
- return -1;
- mp_set_playlist_entry(mpctx, e);
- if (on_osd & MP_ON_OSD_MSG)
- mpctx->add_osd_seek_info |= OSD_SEEK_INFO_CURRENT_FILE;
- break;
+static void cmd_quit(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
+ bool write_watch_later = *(bool *)cmd->priv;
+ if (write_watch_later || mpctx->opts->position_save_on_quit)
+ mp_write_watch_later_conf(mpctx);
+ mpctx->stop_play = PT_QUIT;
+ mpctx->quit_custom_rc = cmd->args[0].v.i;
+ mpctx->has_quit_custom_rc = true;
+ mp_wakeup_core(mpctx);
+}
+
+static void cmd_playlist_next_prev(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
+ int dir = *(int *)cmd->priv;
+ int force = cmd->args[0].v.i;
+
+ struct playlist_entry *e = mp_next_file(mpctx, dir, force, true);
+ if (!e && !force) {
+ cmd->success = false;
+ return;
}
- case MP_CMD_SUB_STEP:
- case MP_CMD_SUB_SEEK: {
- if (!mpctx->playback_initialized)
- return -1;
- struct track *track = mpctx->current_track[0][STREAM_SUB];
- struct dec_sub *sub = track ? track->d_sub : NULL;
- double refpts = get_current_time(mpctx);
- if (sub && refpts != MP_NOPTS_VALUE) {
- double a[2];
- a[0] = refpts;
- a[1] = cmd->args[0].v.i;
- if (sub_control(sub, SD_CTRL_SUB_STEP, a) > 0) {
- if (cmd->id == MP_CMD_SUB_STEP) {
- opts->subs_rend->sub_delay -= a[0] - refpts;
- m_config_notify_change_opt_ptr(mpctx->mconfig,
- &opts->subs_rend->sub_delay);
- show_property_osd(mpctx, "sub-delay", on_osd);
- } else {
- // We can easily get stuck by failing to seek to the video
- // frame which actually shows the sub first (because video
- // frame PTS and sub PTS rarely match exactly). Add some
- // rounding for the mess of it.
- a[0] += 0.01 * (a[1] >= 0 ? 1 : -1);
- mark_seek(mpctx);
- queue_seek(mpctx, MPSEEK_ABSOLUTE, a[0], MPSEEK_EXACT,
- MPSEEK_FLAG_DELAY);
- set_osd_function(mpctx, (a[0] > refpts) ? OSD_FFW : OSD_REW);
- if (seek_bar_osd)
- mpctx->add_osd_seek_info |= OSD_SEEK_INFO_BAR;
- if (seek_msg_osd)
- mpctx->add_osd_seek_info |= OSD_SEEK_INFO_TEXT;
- }
+ mp_set_playlist_entry(mpctx, e);
+ if (cmd->on_osd & MP_ON_OSD_MSG)
+ mpctx->add_osd_seek_info |= OSD_SEEK_INFO_CURRENT_FILE;
+}
+
+static void cmd_sub_step_seek(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
+ bool step = *(bool *)cmd->priv;
+
+ if (!mpctx->playback_initialized) {
+ cmd->success = false;
+ return;
+ }
+
+ struct track *track = mpctx->current_track[0][STREAM_SUB];
+ struct dec_sub *sub = track ? track->d_sub : NULL;
+ double refpts = get_current_time(mpctx);
+ if (sub && refpts != MP_NOPTS_VALUE) {
+ double a[2];
+ a[0] = refpts;
+ a[1] = cmd->args[0].v.i;
+ if (sub_control(sub, SD_CTRL_SUB_STEP, a) > 0) {
+ if (step) {
+ mpctx->opts->subs_rend->sub_delay -= a[0] - refpts;
+ m_config_notify_change_opt_ptr(mpctx->mconfig,
+ &mpctx->opts->subs_rend->sub_delay);
+ show_property_osd(mpctx, "sub-delay", cmd->on_osd);
+ } else {
+ // We can easily get stuck by failing to seek to the video
+ // frame which actually shows the sub first (because video
+ // frame PTS and sub PTS rarely match exactly). Add some
+ // rounding for the mess of it.
+ a[0] += 0.01 * (a[1] >= 0 ? 1 : -1);
+ mark_seek(mpctx);
+ queue_seek(mpctx, MPSEEK_ABSOLUTE, a[0], MPSEEK_EXACT,
+ MPSEEK_FLAG_DELAY);
+ set_osd_function(mpctx, (a[0] > refpts) ? OSD_FFW : OSD_REW);
+ if (cmd->seek_bar_osd)
+ mpctx->add_osd_seek_info |= OSD_SEEK_INFO_BAR;
+ if (cmd->seek_msg_osd)
+ mpctx->add_osd_seek_info |= OSD_SEEK_INFO_TEXT;
}
}
- break;
}
+}
- case MP_CMD_PRINT_TEXT: {
- MP_INFO(mpctx, "%s\n", cmd->args[0].v.s);
- break;
- }
+static void cmd_print_text(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
- case MP_CMD_SHOW_TEXT: {
- // if no argument supplied use default osd_duration, else <arg> ms.
- set_osd_msg(mpctx, cmd->args[2].v.i,
- (cmd->args[1].v.i < 0 ? osd_duration : cmd->args[1].v.i),
- "%s", cmd->args[0].v.s);
- break;
+ MP_INFO(mpctx, "%s\n", cmd->args[0].v.s);
+}
+
+static void cmd_show_text(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
+ int osd_duration = mpctx->opts->osd_duration;
+
+ // if no argument supplied use default osd_duration, else <arg> ms.
+ set_osd_msg(mpctx, cmd->args[2].v.i,
+ (cmd->args[1].v.i < 0 ? osd_duration : cmd->args[1].v.i),
+ "%s", cmd->args[0].v.s);
+}
+
+static void cmd_expand_text(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
+
+ *cmd->result = (mpv_node){
+ .format = MPV_FORMAT_STRING,
+ .u.string = mp_property_expand_string(mpctx, cmd->args[0].v.s)
+ };
+}
+
+static void cmd_loadfile(void *p)
+{
+ struct mp_cmd_ctx *cmd = p;
+ struct MPContext *mpctx = cmd->mpctx;
+ char *filename = cmd->args[0].v.s;
+ int append = cmd->args[1].v.i;
+
+ if (!append)
+ playlist_clear(mpctx->playlist);
+
+ struct playlist_entry *entry = playlist_entry_new(filename);
+ if (cmd->args[2].v.str_list) {
+ char **pairs = cmd->args[2].v.str_list;
+ for (int i = 0; pairs[i] && pairs[i + 1]; i += 2)
+ playlist_entry_add_param(entry, bstr0(pairs[i]), bstr0(pairs[i + 1]));
}
+ playlist_add(mpctx->playlist, entry);
- case MP_CMD_EXPAND_TEXT: {
- if (!res)
- return -1;
- *res = (mpv_node){
- .format = MPV_FORMAT_STRING,
- .u.string = mp_property_expand_string(mpctx, cmd->args[0].v.s)
- };
- break;
+ if (!append || (append == 2 && !mpctx->playlist->current)) {