From 88849fd1d4056bc22305cc4433dc56360dd6d0e9 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 24 Sep 2012 21:57:43 +0200 Subject: commands: add choice type to input commands Allow using the choice type (as it used for command line) for arguments of input commands. Change the magic integer arguments of some commands (like seek) to use choices instead. The old numeric values are still allowed (but only those which made sense before, not arbitrary integers). In order to do this, remove the input.c specific types (like MP_CMD_ARG_INT) completely and specify commands using the m_option types. Also, add the special choice "-" to some arguments. It's supposed to signify the default value, so arguments can be easily skipped. Maybe the choice option should recognize this and not change the previous value, but we'll leave this for later. For now, leave compatibility integer values for all new choice arguments, e.g. "0" maps to 0. We could let the choice option type do this automatically, but we don't, because we want user input values and internal mplayer values decoupled in general. The compatibility options will be removed one day, too. Also, remove optional args for strings - would require either annoying additional code, or copying strings twice. It's not used, so remove it. --- input/input.c | 106 ++++++++++++++++++++++++++++++++++------------------------ input/input.h | 8 ++--- 2 files changed, 64 insertions(+), 50 deletions(-) (limited to 'input') diff --git a/input/input.c b/input/input.c index b5b9c4ce1b..a1ab808125 100644 --- a/input/input.c +++ b/input/input.c @@ -85,12 +85,20 @@ struct key_name { * argument value if the user didn't give enough arguments to specify it. * A command can take a maximum of MP_CMD_MAX_ARGS arguments (10). */ -#define ARG_INT { .type = MP_CMD_ARG_INT } -#define OARG_INT(def) { .type = MP_CMD_ARG_INT, .optional = true, .v.i = def } -#define ARG_FLOAT { .type = MP_CMD_ARG_FLOAT } -#define OARG_FLOAT(def) { .type = MP_CMD_ARG_FLOAT, .optional = true, .v.f = def } -#define ARG_STRING { .type = MP_CMD_ARG_STRING } -#define OARG_STRING(def) { .type = MP_CMD_ARG_STRING, .optional = true, .v.s = def } + +#define ARG_INT { .type = {"", NULL, &m_option_type_int} } +#define ARG_FLOAT { .type = {"", NULL, &m_option_type_float} } +#define ARG_STRING { .type = {"", NULL, &m_option_type_string} } +#define ARG_CHOICE(c) { .type = {"", NULL, &m_option_type_choice, \ + M_CHOICES(c)} } + +#define OARG_FLOAT(def) { .type = {"", NULL, &m_option_type_float}, \ + .optional = true, .v.f = def } +#define OARG_INT(def) { .type = {"", NULL, &m_option_type_int}, \ + .optional = true, .v.i = def } +#define OARG_CHOICE(def, c) { .type = {"", NULL, &m_option_type_choice, \ + M_CHOICES(c)}, \ + .optional = true, .v.i = def } static const mp_cmd_t mp_cmds[] = { { MP_CMD_IGNORE, "ignore", }, @@ -100,14 +108,28 @@ static const mp_cmd_t mp_cmds[] = { { MP_CMD_RADIO_SET_FREQ, "radio_set_freq", { ARG_FLOAT } }, { MP_CMD_RADIO_STEP_FREQ, "radio_step_freq", {ARG_FLOAT } }, #endif - { MP_CMD_SEEK, "seek", { ARG_FLOAT, OARG_INT(0), OARG_INT(0) } }, + { MP_CMD_SEEK, "seek", { + ARG_FLOAT, + OARG_CHOICE(0, ({"relative", 0}, {"0", 0}, + {"absolute-percent", 1}, {"1", 1}, + {"absolute", 2}, {"2", 2})), + OARG_CHOICE(0, ({"default-precise", 0}, {"0", 0}, + {"exact", 1}, {"1", 1}, + {"keyframes", -1}, {"-1", -1})), + }}, { MP_CMD_EDL_MARK, "edl_mark", }, { MP_CMD_SPEED_MULT, "speed_mult", { ARG_FLOAT } }, { MP_CMD_QUIT, "quit", { OARG_INT(0) } }, { MP_CMD_STOP, "stop", }, { MP_CMD_FRAME_STEP, "frame_step", }, - { MP_CMD_PLAYLIST_NEXT, "playlist_next", { OARG_INT(0) } }, - { MP_CMD_PLAYLIST_PREV, "playlist_prev", { OARG_INT(0) } }, + { MP_CMD_PLAYLIST_NEXT, "playlist_next", { + OARG_CHOICE(0, ({"weak", 0}, {"0", 0}, + {"force", 1}, {"1", 1})), + }}, + { MP_CMD_PLAYLIST_PREV, "playlist_prev", { + OARG_CHOICE(0, ({"weak", 0}, {"0", 0}, + {"force", 1}, {"1", 1})), + }}, { MP_CMD_SUB_STEP, "sub_step", { ARG_INT, OARG_INT(0) } }, { MP_CMD_OSD, "osd", { OARG_INT(-1) } }, { MP_CMD_SHOW_TEXT, "show_text", { ARG_STRING, OARG_INT(-1), OARG_INT(0) } }, @@ -127,9 +149,22 @@ static const mp_cmd_t mp_cmds[] = { #ifdef CONFIG_DVBIN { MP_CMD_DVB_SET_CHANNEL, "dvb_set_channel", { ARG_INT, ARG_INT } }, #endif - { MP_CMD_SCREENSHOT, "screenshot", { OARG_INT(0), OARG_INT(0) } }, - { MP_CMD_LOADFILE, "loadfile", { ARG_STRING, OARG_INT(0) } }, - { MP_CMD_LOADLIST, "loadlist", { ARG_STRING, OARG_INT(0) } }, + { MP_CMD_SCREENSHOT, "screenshot", { + OARG_CHOICE(0, ({"single", 0}, {"0", 0}, + {"each-frame", 1}, {"1", 1})), + OARG_CHOICE(0, ({"video", 0}, {"0", 0}, + {"window", 1}, {"1", 1})), + }}, + { MP_CMD_LOADFILE, "loadfile", { + ARG_STRING, + OARG_CHOICE(0, ({"replace", 0}, {"0", 0}, + {"append", 1}, {"1", 1})), + }}, + { MP_CMD_LOADLIST, "loadlist", { + ARG_STRING, + OARG_CHOICE(0, ({"replace", 0}, {"0", 0}, + {"append", 1}, {"1", 1})), + }}, { MP_CMD_PLAYLIST_CLEAR, "playlist_clear", }, { MP_CMD_RUN, "run", { ARG_STRING } }, @@ -838,11 +873,13 @@ mp_cmd_t *mp_input_parse_cmd(bstr str) cmd->on_osd = on_osd; for (int i = 0; i < MP_CMD_MAX_ARGS; i++) { - if (!cmd->args[i].type) + struct mp_cmd_arg *cmdarg = &cmd->args[i]; + if (!cmdarg->type.type) break; + cmd->nargs++; str = bstr_lstrip(str); bstr arg = {0}; - if (cmd->args[i].type == MP_CMD_ARG_STRING && + if (cmdarg->type.type == &m_option_type_string && bstr_eatstart0(&str, "\"")) { if (!read_escaped_string(tmp, &str, &arg)) { @@ -858,26 +895,20 @@ mp_cmd_t *mp_input_parse_cmd(bstr str) } else { if (!read_token(str, &str, &arg)) break; + if (cmdarg->optional && bstrcmp0(arg, "-") == 0) + continue; } // Prevent option API from trying to deallocate static strings - cmd->args[i].v = ((struct mp_cmd_arg) {0}).v; - struct m_option opt = {0}; - switch (cmd->args[i].type) { - case MP_CMD_ARG_INT: opt.type = &m_option_type_int; break; - case MP_CMD_ARG_FLOAT: opt.type = &m_option_type_float; break; - case MP_CMD_ARG_STRING: opt.type = &m_option_type_string; break; - default: abort(); - } - int r = m_option_parse(&opt, bstr0(cmd->name), arg, &cmd->args[i].v); + cmdarg->v = ((struct mp_cmd_arg) {{0}}).v; + int r = m_option_parse(&cmdarg->type, bstr0(cmd->name), arg, &cmdarg->v); if (r < 0) { mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d " "can't be parsed: %s.\n", cmd->name, i + 1, m_option_strerror(r)); goto error; } - if (opt.type == &m_option_type_string) - cmd->args[i].v.s = talloc_steal(cmd, cmd->args[i].v.s); - cmd->nargs++; + if (cmdarg->type.type == &m_option_type_string) + cmdarg->v.s = talloc_steal(cmd, cmdarg->v.s); } bstr dummy; @@ -889,7 +920,7 @@ mp_cmd_t *mp_input_parse_cmd(bstr str) } int min_args = 0; - while (min_args < MP_CMD_MAX_ARGS && cmd->args[min_args].type + while (min_args < MP_CMD_MAX_ARGS && cmd->args[min_args].type.type && !cmd->args[min_args].optional) { min_args++; @@ -1424,8 +1455,8 @@ mp_cmd_t *mp_cmd_clone(mp_cmd_t *cmd) ret = talloc_memdup(NULL, cmd, sizeof(mp_cmd_t)); ret->name = talloc_strdup(ret, cmd->name); - for (i = 0; i < MP_CMD_MAX_ARGS && cmd->args[i].type; i++) { - if (cmd->args[i].type == MP_CMD_ARG_STRING && cmd->args[i].v.s != NULL) + for (i = 0; i < MP_CMD_MAX_ARGS; i++) { + if (cmd->args[i].type.type == &m_option_type_string) ret->args[i].v.s = talloc_strdup(ret, cmd->args[i].v.s); } @@ -1771,24 +1802,11 @@ static int print_cmd_list(m_option_t *cfg, char *optname, char *optparam) { const mp_cmd_t *cmd; int i, j; - const char *type; for (i = 0; (cmd = &mp_cmds[i])->name != NULL; i++) { printf("%-20.20s", cmd->name); - for (j = 0; j < MP_CMD_MAX_ARGS && cmd->args[j].type; j++) { - switch (cmd->args[j].type) { - case MP_CMD_ARG_INT: - type = "Integer"; - break; - case MP_CMD_ARG_FLOAT: - type = "Float"; - break; - case MP_CMD_ARG_STRING: - type = "String"; - break; - default: - type = "??"; - } + for (j = 0; j < MP_CMD_MAX_ARGS && cmd->args[j].type.type; j++) { + const char *type = cmd->args[j].type.type->name; if (cmd->args[j].optional) printf(" [%s]", type); else diff --git a/input/input.h b/input/input.h index 4823ab75f0..e4eb0a8d32 100644 --- a/input/input.h +++ b/input/input.h @@ -21,6 +21,7 @@ #include #include "bstr.h" +#include "m_option.h" // All command IDs enum mp_command_type { @@ -80,11 +81,6 @@ enum mp_command_type { MP_CMD_VO_CMDLINE, }; -// The arg types -#define MP_CMD_ARG_INT 1 -#define MP_CMD_ARG_FLOAT 2 -#define MP_CMD_ARG_STRING 3 - #define MP_CMD_MAX_ARGS 10 // Error codes for the drivers @@ -115,7 +111,7 @@ enum mp_input_section_flags { struct input_ctx; struct mp_cmd_arg { - int type; + struct m_option type; bool optional; union { int i; -- cgit v1.2.3