diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index 2039a9ab217c5..a38332f5bcc4c 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -924,11 +924,12 @@ Remember to quote string arguments in input.conf (see `Flat command syntax`_). empty string, ``KEYUP`` will be set on all keys. Otherwise, ``KEYUP`` will only be set on the key specified by ``name``. -``keybind `` - Binds a key to an input command. ``command`` must be a complete command +``keybind []`` + Binds a key to an input command. ``cmd`` must be a complete command containing all the desired arguments and flags. Both ``name`` and - ``command`` use the ``input.conf`` naming scheme. This is primarily - useful for the client API. + ``cmd`` use the ``input.conf`` naming scheme. ``comment`` is an optional + string which can be read as the ``comment`` entry of ``input-bindings``. + This is primarily useful for the client API. ``audio-add [ [ [<lang>]]]`` Load the given audio file. See ``sub-add`` command. diff --git a/input/input.c b/input/input.c index 61547a90ad600..60b43e2032e35 100644 --- a/input/input.c +++ b/input/input.c @@ -1427,8 +1427,7 @@ static int parse_config(struct input_ctx *ictx, bool builtin, bstr data, char *name = bstrdup0(NULL, keyname); int keys[MP_MAX_KEY_DOWN]; int num_keys = 0; - if (!mp_input_get_keys_from_string(name, MP_MAX_KEY_DOWN, &num_keys, keys)) - { + if (!mp_input_get_keys_from_string(name, MP_MAX_KEY_DOWN, &num_keys, keys)) { talloc_free(name); MP_ERR(ictx, "Unknown key '%.*s' at %s\n", BSTR_P(keyname), cur_loc); continue; @@ -1643,44 +1642,23 @@ void mp_input_run_cmd(struct input_ctx *ictx, const char **cmd) input_unlock(ictx); } -void mp_input_bind_key(struct input_ctx *ictx, int key, bstr command) +bool mp_input_bind_key(struct input_ctx *ictx, const char *key, bstr command, + const char *desc) { - input_lock(ictx); - struct cmd_bind_section *bs = get_bind_section(ictx, (bstr){0}); - struct cmd_bind *bind = NULL; - - for (int n = 0; n < bs->num_binds; n++) { - struct cmd_bind *b = &bs->binds[n]; - if (bind_matches_key(b, 1, &key) && b->is_builtin == false) { - bind = b; - break; - } - } - - if (!bind) { - struct cmd_bind empty = {{0}}; - MP_TARRAY_APPEND(bs, bs->binds, bs->num_binds, empty); - bind = &bs->binds[bs->num_binds - 1]; + char *name = talloc_strdup(NULL, key); + int keys[MP_MAX_KEY_DOWN]; + int num_keys = 0; + if (!mp_input_get_keys_from_string(name, MP_MAX_KEY_DOWN, &num_keys, keys)) { + talloc_free(name); + return false; } + talloc_free(name); - bind_dealloc(bind); - - *bind = (struct cmd_bind) { - .cmd = bstrdup0(bs->binds, command), - .location = talloc_strdup(bs->binds, "keybind-command"), - .owner = bs, - .is_builtin = false, - .num_keys = 1, - }; - memcpy(bind->keys, &key, 1 * sizeof(bind->keys[0])); - if (mp_msg_test(ictx->log, MSGL_DEBUG)) { - char *s = mp_input_get_key_combo_name(&key, 1); - MP_TRACE(ictx, "add:section='%.*s' key='%s'%s cmd='%s' location='%s'\n", - BSTR_P(bind->owner->section), s, bind->is_builtin ? " builtin" : "", - bind->cmd, bind->location); - talloc_free(s); - } + input_lock(ictx); + bind_keys(ictx, false, (bstr){0}, keys, num_keys, command, + "keybind-command", desc); input_unlock(ictx); + return true; } struct mpv_node mp_input_get_bindings(struct input_ctx *ictx) diff --git a/input/input.h b/input/input.h index aafabdb9cb7b7..8c5b85e117abf 100644 --- a/input/input.h +++ b/input/input.h @@ -215,8 +215,9 @@ bool mp_input_use_media_keys(struct input_ctx *ictx); // Like mp_input_parse_cmd_strv, but also run the command. void mp_input_run_cmd(struct input_ctx *ictx, const char **cmd); -// Binds a command to a key. -void mp_input_bind_key(struct input_ctx *ictx, int key, bstr command); +// Binds a command to a key. Returns true if the bind is successful. +bool mp_input_bind_key(struct input_ctx *ictx, const char *key, bstr command, + const char *desc); void mp_input_set_repeat_info(struct input_ctx *ictx, int rate, int delay); diff --git a/player/command.c b/player/command.c index 4a52b4fead0ff..de15e04f8419f 100644 --- a/player/command.c +++ b/player/command.c @@ -6549,7 +6549,7 @@ static void cmd_delete_watch_later_config(void *p) struct MPContext *mpctx = cmd->mpctx; char *filename = cmd->args[0].v.s; - if (filename && !*filename) + if (filename && !filename[0]) filename = NULL; mp_delete_watch_later_conf(mpctx, filename); } @@ -6612,7 +6612,7 @@ static void cmd_key(void *p) } else { int code = mp_input_get_key_from_name(key_name); if (code < 0) { - MP_ERR(mpctx, "%s is not a valid input name.\n", key_name); + MP_ERR(mpctx, "'%s' is not a valid input name.\n", key_name); cmd->success = false; return; } @@ -6626,14 +6626,15 @@ static void cmd_key_bind(void *p) struct mp_cmd_ctx *cmd = p; struct MPContext *mpctx = cmd->mpctx; - int code = mp_input_get_key_from_name(cmd->args[0].v.s); - if (code < 0) { - MP_ERR(mpctx, "%s is not a valid input name.\n", cmd->args[0].v.s); + const char *key = cmd->args[0].v.s; + const char *target_cmd = cmd->args[1].v.s; + const char *comment = cmd->args[2].v.s; + if (comment && !comment[0]) + comment = NULL; + if (!mp_input_bind_key(mpctx->input, key, bstr0(target_cmd), comment)) { + MP_ERR(mpctx, "'%s' is not a valid input name.\n", key); cmd->success = false; - return; } - const char *target_cmd = cmd->args[1].v.s; - mp_input_bind_key(mpctx->input, code, bstr0(target_cmd)); } static void cmd_apply_profile(void *p) @@ -7244,7 +7245,8 @@ const struct mp_cmd_def mp_cmds[] = { {"single", 0}, {"double", 1}), .flags = MP_CMD_OPT_ARG}}}, { "keybind", cmd_key_bind, { {"name", OPT_STRING(v.s)}, - {"cmd", OPT_STRING(v.s)} }}, + {"cmd", OPT_STRING(v.s)}, + {"comment", OPT_STRING(v.s), .flags = MP_CMD_OPT_ARG} }}, { "keypress", cmd_key, { {"name", OPT_STRING(v.s)}, {"scale", OPT_DOUBLE(v.d), OPTDEF_DOUBLE(1)} }, .priv = &(const int){0}},