From 0a54f5e741e395ffb14a1305529c70e817679596 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 6 Sep 2012 05:29:38 +0200 Subject: commands: remove legacy slave mode get commands These have been replaced by properties. Also remove some other slave- mode specific get commands that can be replaced by property uses. The get_metadata() function didn't actually contain anything useful, and just replicated code from other parts of mplayer. --- input/input.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index 7f9021e35b..38e89d4577 100644 --- a/input/input.c +++ b/input/input.c @@ -138,23 +138,6 @@ static const mp_cmd_t mp_cmds[] = { #ifdef CONFIG_ASS { MP_CMD_ASS_USE_MARGINS, "ass_use_margins", { OARG_INT(-1) } }, #endif - { MP_CMD_GET_PERCENT_POS, "get_percent_pos", }, - { MP_CMD_GET_TIME_POS, "get_time_pos", }, - { MP_CMD_GET_TIME_LENGTH, "get_time_length", }, - { MP_CMD_GET_FILENAME, "get_file_name", }, - { MP_CMD_GET_VIDEO_CODEC, "get_video_codec", }, - { MP_CMD_GET_VIDEO_BITRATE, "get_video_bitrate", }, - { MP_CMD_GET_VIDEO_RESOLUTION, "get_video_resolution", }, - { MP_CMD_GET_AUDIO_CODEC, "get_audio_codec", }, - { MP_CMD_GET_AUDIO_BITRATE, "get_audio_bitrate", }, - { MP_CMD_GET_AUDIO_SAMPLES, "get_audio_samples", }, - { MP_CMD_GET_META_TITLE, "get_meta_title", }, - { MP_CMD_GET_META_ARTIST, "get_meta_artist", }, - { MP_CMD_GET_META_ALBUM, "get_meta_album", }, - { MP_CMD_GET_META_YEAR, "get_meta_year", }, - { MP_CMD_GET_META_COMMENT, "get_meta_comment", }, - { MP_CMD_GET_META_TRACK, "get_meta_track", }, - { MP_CMD_GET_META_GENRE, "get_meta_genre", }, { MP_CMD_SWITCH_AUDIO, "switch_audio", { OARG_INT(-1) } }, { MP_CMD_SWITCH_ANGLE, "switch_angle", { OARG_INT(-1) } }, { MP_CMD_SWITCH_TITLE, "switch_title", { OARG_INT(-1) } }, @@ -190,8 +173,6 @@ static const mp_cmd_t mp_cmds[] = { { MP_CMD_PLAYLIST_CLEAR, "playlist_clear", }, { MP_CMD_RUN, "run", { ARG_STRING } }, - { MP_CMD_GET_VO_FULLSCREEN, "get_vo_fullscreen", }, - { MP_CMD_GET_SUB_VISIBILITY, "get_sub_visibility", }, { MP_CMD_KEYDOWN_EVENTS, "key_down_event", { ARG_INT } }, { MP_CMD_SET_PROPERTY, "set_property", { ARG_STRING, ARG_STRING } }, { MP_CMD_SET_PROPERTY_OSD, "set_property_osd", { ARG_STRING, ARG_STRING } }, -- cgit v1.2.3 From e41378ea7186a4be1d5ed3f0d55a1d4cb93f2f10 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 6 Sep 2012 07:19:41 +0200 Subject: commands: simplify legacy command-to-property bridge There are many input commands which are redundant to properties. They were parsed like normal commands, but set_property_command() in command.c handled them automatically using the property mechanism. This still required having the command specifications around, and the code in command.c was quite messy. Replace this with a text based replacement mechanism. Some corner cases are not handled: commands of form "seek_chapter 3 1" are supposed to set the "chapter" property to 3. This use is probably rare, and doesn't show up in the default input.conf. The reason compatibility is kept is because breaking input.conf is quite annoying, so a minimal effort is made to avoid this. Currently we print an annoying warning every time a legacy command is used, though. Also add a compatibility entry for "pt_step", which was removed some time ago. Variations in whitespace are not handled, but it's good enough to deal with old input.conf entries. --- input/input.c | 103 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 40 deletions(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index 38e89d4577..a2bc7d838a 100644 --- a/input/input.c +++ b/input/input.c @@ -101,46 +101,21 @@ static const mp_cmd_t mp_cmds[] = { #endif { MP_CMD_SEEK, "seek", { ARG_FLOAT, OARG_INT(0), OARG_INT(0) } }, { MP_CMD_EDL_MARK, "edl_mark", }, - { MP_CMD_AUDIO_DELAY, "audio_delay", { ARG_FLOAT, OARG_INT(0) } }, { MP_CMD_SPEED_INCR, "speed_incr", { ARG_FLOAT } }, { MP_CMD_SPEED_MULT, "speed_mult", { ARG_FLOAT } }, { MP_CMD_SPEED_SET, "speed_set", { ARG_FLOAT } }, { MP_CMD_QUIT, "quit", { OARG_INT(0) } }, { MP_CMD_STOP, "stop", }, - { MP_CMD_PAUSE, "pause", }, { 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_LOOP, "loop", { ARG_INT, OARG_INT(0) } }, - { MP_CMD_SUB_DELAY, "sub_delay", { ARG_FLOAT, OARG_INT(0) } }, { MP_CMD_SUB_STEP, "sub_step", { ARG_INT, OARG_INT(0) } }, { MP_CMD_OSD, "osd", { OARG_INT(-1) } }, { MP_CMD_OSD_SHOW_TEXT, "osd_show_text", { ARG_STRING, OARG_INT(-1), OARG_INT(0) } }, { MP_CMD_OSD_SHOW_PROPERTY_TEXT, "osd_show_property_text", { ARG_STRING, OARG_INT(-1), OARG_INT(0) } }, { MP_CMD_OSD_SHOW_PROGRESSION, "osd_show_progression", }, - { MP_CMD_VOLUME, "volume", { ARG_FLOAT, OARG_INT(0) } }, - { MP_CMD_BALANCE, "balance", { ARG_FLOAT, OARG_INT(0) } }, { MP_CMD_MIXER_USEMASTER, "use_master", }, - { MP_CMD_MUTE, "mute", { OARG_INT(-1) } }, - { MP_CMD_CONTRAST, "contrast", { ARG_INT, OARG_INT(0) } }, - { MP_CMD_GAMMA, "gamma", { ARG_INT, OARG_INT(0) } }, - { MP_CMD_BRIGHTNESS, "brightness", { ARG_INT, OARG_INT(0) } }, - { MP_CMD_HUE, "hue", { ARG_INT, OARG_INT(0) } }, - { MP_CMD_SATURATION, "saturation", { ARG_INT, OARG_INT(0) } }, - { MP_CMD_FRAMEDROPPING, "frame_drop", { OARG_INT(-1) } }, - { MP_CMD_SUB_POS, "sub_pos", { ARG_INT, OARG_INT(0) } }, - { MP_CMD_SUB_ALIGNMENT, "sub_alignment", { OARG_INT(-1) } }, - { MP_CMD_SUB_VISIBILITY, "sub_visibility", { OARG_INT(-1) } }, { MP_CMD_SUB_LOAD, "sub_load", { ARG_STRING } }, - { MP_CMD_SUB_SELECT, "vobsub_lang", { OARG_INT(-2) } }, // for compatibility - { MP_CMD_SUB_SELECT, "sub_select", { OARG_INT(-2) } }, - { MP_CMD_SUB_SCALE, "sub_scale", { ARG_FLOAT, OARG_INT(0) } }, -#ifdef CONFIG_ASS - { MP_CMD_ASS_USE_MARGINS, "ass_use_margins", { OARG_INT(-1) } }, -#endif - { MP_CMD_SWITCH_AUDIO, "switch_audio", { OARG_INT(-1) } }, - { MP_CMD_SWITCH_ANGLE, "switch_angle", { OARG_INT(-1) } }, - { MP_CMD_SWITCH_TITLE, "switch_title", { OARG_INT(-1) } }, #ifdef CONFIG_TV { MP_CMD_TV_START_SCAN, "tv_start_scan", }, { MP_CMD_TV_STEP_CHANNEL, "tv_step_channel", { ARG_INT } }, @@ -151,23 +126,12 @@ static const mp_cmd_t mp_cmds[] = { { MP_CMD_TV_SET_FREQ, "tv_set_freq", { ARG_FLOAT } }, { MP_CMD_TV_STEP_FREQ, "tv_step_freq", { ARG_FLOAT } }, { MP_CMD_TV_SET_NORM, "tv_set_norm", { ARG_STRING } }, - { MP_CMD_TV_SET_BRIGHTNESS, "tv_set_brightness", { ARG_INT, OARG_INT(1) } }, - { MP_CMD_TV_SET_CONTRAST, "tv_set_contrast", { ARG_INT, OARG_INT(1) } }, - { MP_CMD_TV_SET_HUE, "tv_set_hue", { ARG_INT, OARG_INT(1) } }, - { MP_CMD_TV_SET_SATURATION, "tv_set_saturation", { ARG_INT, OARG_INT(1) } }, #endif - { MP_CMD_SUB_FORCED_ONLY, "forced_subs_only", { OARG_INT(-1) } }, #ifdef CONFIG_DVBIN { MP_CMD_DVB_SET_CHANNEL, "dvb_set_channel", { ARG_INT, ARG_INT } }, #endif { MP_CMD_SWITCH_RATIO, "switch_ratio", { OARG_FLOAT(0) } }, - { MP_CMD_VO_FULLSCREEN, "vo_fullscreen", { OARG_INT(-1) } }, - { MP_CMD_VO_ONTOP, "vo_ontop", { OARG_INT(-1) } }, - { MP_CMD_VO_ROOTWIN, "vo_rootwin", { OARG_INT(-1) } }, - { MP_CMD_VO_BORDER, "vo_border", { OARG_INT(-1) } }, { MP_CMD_SCREENSHOT, "screenshot", { OARG_INT(0), OARG_INT(0) } }, - { MP_CMD_PANSCAN, "panscan", { ARG_FLOAT, OARG_INT(0) } }, - { MP_CMD_SWITCH_VSYNC, "switch_vsync", { OARG_INT(0) } }, { MP_CMD_LOADFILE, "loadfile", { ARG_STRING, OARG_INT(0) } }, { MP_CMD_LOADLIST, "loadlist", { ARG_STRING, OARG_INT(0) } }, { MP_CMD_PLAYLIST_CLEAR, "playlist_clear", }, @@ -180,7 +144,6 @@ static const mp_cmd_t mp_cmds[] = { { MP_CMD_STEP_PROPERTY, "step_property", { ARG_STRING, OARG_FLOAT(0), OARG_INT(0) } }, { MP_CMD_STEP_PROPERTY_OSD, "step_property_osd", { ARG_STRING, OARG_FLOAT(0), OARG_INT(0) } }, - { MP_CMD_SEEK_CHAPTER, "seek_chapter", { ARG_INT, OARG_INT(0) } }, { MP_CMD_SET_MOUSE_POS, "set_mouse_pos", { ARG_INT, ARG_INT } }, { MP_CMD_AF_SWITCH, "af_switch", { ARG_STRING } }, @@ -197,6 +160,50 @@ static const mp_cmd_t mp_cmds[] = { {0} }; +// Map legacy commands to proper commands +struct legacy_cmd { + const char *old, *new; +}; +#define LEGACY_STEP(old) {old, "step_property_osd " old} +static const struct legacy_cmd legacy_cmds[] = { + LEGACY_STEP("loop"), + {"seek_chapter", "step_property_osd chapter"}, + {"switch_angle", "step_property_osd angle"}, + LEGACY_STEP("pause"), + LEGACY_STEP("volume"), + LEGACY_STEP("mute"), + LEGACY_STEP("audio_delay"), + LEGACY_STEP("switch_audio"), + LEGACY_STEP("balance"), + {"vo_fullscreen", "step_property fullscreen"}, + LEGACY_STEP("panscan"), + {"vo_ontop", "step_property_osd ontop"}, + {"vo_rootwin", "step_property_osd rootwin"}, + {"vo_border", "step_property_osd border"}, + {"frame_drop", "step_property_osd framedropping"}, + LEGACY_STEP("gamma"), + LEGACY_STEP("brightness"), + LEGACY_STEP("contrast"), + LEGACY_STEP("saturation"), + LEGACY_STEP("hue"), + {"switch_vsync", "step_property_osd vsync"}, + {"sub_select", "step_property_osd sub"}, + LEGACY_STEP("sub_pos"), + LEGACY_STEP("sub_delay"), + LEGACY_STEP("sub_visibility"), + {"forced_subs_only", "step_property_osd sub_forced_only"}, + LEGACY_STEP("sub_scale"), + LEGACY_STEP("ass_use_margins"), + {"tv_set_brightness", "tv_brightness"}, + {"tv_set_hue", "tv_hue"}, + {"tv_set_saturation", "tv_saturation"}, + {"tv_set_contrast", "tv_contrast"}, + {"pt_step 1", "playlist_next"}, + {"pt_step -1", "playlist_prev"}, + {0} +}; + + /// The names of the keys as used in input.conf /// If you add some new keys, you also need to add them here @@ -685,6 +692,8 @@ mp_cmd_t *mp_input_parse_cmd(char *str) int pausing = 0; char *ptr; const mp_cmd_t *cmd_def; + mp_cmd_t *cmd = NULL; + void *tmp = NULL; // Ignore heading spaces. while (str[0] == ' ' || str[0] == '\t') @@ -704,6 +713,18 @@ mp_cmd_t *mp_input_parse_cmd(char *str) str = &str[19]; } + for (const struct legacy_cmd *entry = legacy_cmds; entry->old; entry++) { + size_t old_len = strlen(entry->old); + if (strncasecmp(entry->old, str, old_len) == 0) { + mp_tmsg(MSGT_INPUT, MSGL_WARN, "Warning: command '%s' is " + "deprecated, replaced with '%s'. Fix your input.conf!\n", + entry->old, entry->new); + str = talloc_asprintf(NULL, "%s%s", entry->new, str + old_len); + tmp = str; + break; + } + } + ptr = str + strcspn(str, "\t "); if (*ptr != 0) l = ptr - str; @@ -711,7 +732,7 @@ mp_cmd_t *mp_input_parse_cmd(char *str) l = strlen(str); if (l == 0) - return NULL; + goto error; for (i = 0; mp_cmds[i].name != NULL; i++) { if (strncasecmp(mp_cmds[i].name, str, l) == 0) @@ -719,11 +740,11 @@ mp_cmd_t *mp_input_parse_cmd(char *str) } if (mp_cmds[i].name == NULL) - return NULL; + goto error; cmd_def = &mp_cmds[i]; - mp_cmd_t *cmd = talloc_ptrtype(NULL, cmd); + cmd = talloc_ptrtype(NULL, cmd); *cmd = (mp_cmd_t){ .id = cmd_def->id, .name = talloc_strdup(cmd, cmd_def->name), @@ -815,10 +836,12 @@ mp_cmd_t *mp_input_parse_cmd(char *str) if (i < MP_CMD_MAX_ARGS) cmd->args[i].type = 0; + talloc_free(tmp); return cmd; error: mp_cmd_free(cmd); + talloc_free(tmp); return NULL; } -- cgit v1.2.3 From a668ae0ff90c43ebcdea4f581aef0c98aeebd382 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 9 Sep 2012 02:08:08 +0200 Subject: commands: change input commands to make OSD usage explicit Most input commands had their own policy whether to display an OSD message for user feedback or not. Some commands had two variants, one that showed an OSD message and one that didn't (e.g. step_property_osd and step_property). Change it such that all commands show a message on the OSD. Add a "no-osd" modifier that disables OSD for that command. Rename the "step_property" and "step_property_osd" command to "switch", and rename "set_property" and "set_property_osd" to "set". Note that commands which haven't used OSD before still don't use OSD. That will possibly be fixed later. (E.g. "screenshot" could display an OSD message instead of just printing a message on the terminal.) The chapter and edition properties still produce OSD messages even with "no-osd", because they don't map so well to the property_osd_display[] mechanism. --- input/input.c | 66 +++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 20 deletions(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index a2bc7d838a..5d3ab686df 100644 --- a/input/input.c +++ b/input/input.c @@ -138,11 +138,9 @@ static const mp_cmd_t mp_cmds[] = { { MP_CMD_RUN, "run", { ARG_STRING } }, { MP_CMD_KEYDOWN_EVENTS, "key_down_event", { ARG_INT } }, - { MP_CMD_SET_PROPERTY, "set_property", { ARG_STRING, ARG_STRING } }, - { MP_CMD_SET_PROPERTY_OSD, "set_property_osd", { ARG_STRING, ARG_STRING } }, + { MP_CMD_SET, "set", { ARG_STRING, ARG_STRING } }, { MP_CMD_GET_PROPERTY, "get_property", { ARG_STRING } }, - { MP_CMD_STEP_PROPERTY, "step_property", { ARG_STRING, OARG_FLOAT(0), OARG_INT(0) } }, - { MP_CMD_STEP_PROPERTY_OSD, "step_property_osd", { ARG_STRING, OARG_FLOAT(0), OARG_INT(0) } }, + { MP_CMD_SWITCH, "switch", { ARG_STRING, OARG_FLOAT(0), OARG_INT(0) } }, { MP_CMD_SET_MOUSE_POS, "set_mouse_pos", { ARG_INT, ARG_INT } }, @@ -164,40 +162,44 @@ static const mp_cmd_t mp_cmds[] = { struct legacy_cmd { const char *old, *new; }; -#define LEGACY_STEP(old) {old, "step_property_osd " old} +#define LEGACY_STEP(old) {old, "switch " old} static const struct legacy_cmd legacy_cmds[] = { LEGACY_STEP("loop"), - {"seek_chapter", "step_property_osd chapter"}, - {"switch_angle", "step_property_osd angle"}, + {"seek_chapter", "switch chapter"}, + {"switch_angle", "switch angle"}, LEGACY_STEP("pause"), LEGACY_STEP("volume"), LEGACY_STEP("mute"), LEGACY_STEP("audio_delay"), LEGACY_STEP("switch_audio"), LEGACY_STEP("balance"), - {"vo_fullscreen", "step_property fullscreen"}, + {"vo_fullscreen", "no-osd switch fullscreen"}, LEGACY_STEP("panscan"), - {"vo_ontop", "step_property_osd ontop"}, - {"vo_rootwin", "step_property_osd rootwin"}, - {"vo_border", "step_property_osd border"}, - {"frame_drop", "step_property_osd framedropping"}, + {"vo_ontop", "switch ontop"}, + {"vo_rootwin", "switch rootwin"}, + {"vo_border", "switch border"}, + {"frame_drop", "switch framedropping"}, LEGACY_STEP("gamma"), LEGACY_STEP("brightness"), LEGACY_STEP("contrast"), LEGACY_STEP("saturation"), LEGACY_STEP("hue"), - {"switch_vsync", "step_property_osd vsync"}, - {"sub_select", "step_property_osd sub"}, + {"switch_vsync", "switch vsync"}, + {"sub_select", "switch sub"}, LEGACY_STEP("sub_pos"), LEGACY_STEP("sub_delay"), LEGACY_STEP("sub_visibility"), - {"forced_subs_only", "step_property_osd sub_forced_only"}, + {"forced_subs_only", "switch sub_forced_only"}, LEGACY_STEP("sub_scale"), LEGACY_STEP("ass_use_margins"), {"tv_set_brightness", "tv_brightness"}, {"tv_set_hue", "tv_hue"}, {"tv_set_saturation", "tv_saturation"}, {"tv_set_contrast", "tv_contrast"}, + {"step_property_osd", "switch"}, + {"step_property", "no-osd switch"}, + {"set_property", "no-osd set"}, + {"set_property_osd", "set"}, {"pt_step 1", "playlist_next"}, {"pt_step -1", "playlist_prev"}, {0} @@ -686,18 +688,31 @@ int mp_input_add_key_fd(struct input_ctx *ictx, int fd, int select, return 1; } +static char *skip_ws(char *str) +{ + while (str[0] == ' ' || str[0] == '\t') + ++str; + return str; +} + +static char *skip_no_ws(char *str) +{ + while (str[0] && !(str[0] == ' ' || str[0] == '\t')) + ++str; + return str; +} + mp_cmd_t *mp_input_parse_cmd(char *str) { int i, l; int pausing = 0; + int on_osd = MP_ON_OSD_AUTO; char *ptr; const mp_cmd_t *cmd_def; mp_cmd_t *cmd = NULL; void *tmp = NULL; - // Ignore heading spaces. - while (str[0] == ' ' || str[0] == '\t') - ++str; + str = skip_ws(str); if (strncmp(str, "pausing ", 8) == 0) { pausing = 1; @@ -713,6 +728,8 @@ mp_cmd_t *mp_input_parse_cmd(char *str) str = &str[19]; } + str = skip_ws(str); + for (const struct legacy_cmd *entry = legacy_cmds; entry->old; entry++) { size_t old_len = strlen(entry->old); if (strncasecmp(entry->old, str, old_len) == 0) { @@ -725,7 +742,14 @@ mp_cmd_t *mp_input_parse_cmd(char *str) } } - ptr = str + strcspn(str, "\t "); + str = skip_ws(str); + + if (strncmp(str, "no-osd ", 7) == 0) { + on_osd = MP_ON_OSD_NO; + str = &str[7]; + } + + ptr = skip_no_ws(str); if (*ptr != 0) l = ptr - str; else @@ -735,7 +759,8 @@ mp_cmd_t *mp_input_parse_cmd(char *str) goto error; for (i = 0; mp_cmds[i].name != NULL; i++) { - if (strncasecmp(mp_cmds[i].name, str, l) == 0) + const char *cmd = mp_cmds[i].name; + if (strncasecmp(cmd, str, l) == 0 && strlen(cmd) == l) break; } @@ -749,6 +774,7 @@ mp_cmd_t *mp_input_parse_cmd(char *str) .id = cmd_def->id, .name = talloc_strdup(cmd, cmd_def->name), .pausing = pausing, + .on_osd = on_osd, }; ptr = str; -- cgit v1.2.3 From cd25a671b58a94fbfa1942103137ad6617170a32 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 14 Sep 2012 22:07:33 +0200 Subject: commands: remove unimplemented "use_master" command The implementation for this command was removed in 2002. --- input/input.c | 1 - 1 file changed, 1 deletion(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index 5d3ab686df..97d6a6b25a 100644 --- a/input/input.c +++ b/input/input.c @@ -114,7 +114,6 @@ static const mp_cmd_t mp_cmds[] = { { MP_CMD_OSD_SHOW_TEXT, "osd_show_text", { ARG_STRING, OARG_INT(-1), OARG_INT(0) } }, { MP_CMD_OSD_SHOW_PROPERTY_TEXT, "osd_show_property_text", { ARG_STRING, OARG_INT(-1), OARG_INT(0) } }, { MP_CMD_OSD_SHOW_PROGRESSION, "osd_show_progression", }, - { MP_CMD_MIXER_USEMASTER, "use_master", }, { MP_CMD_SUB_LOAD, "sub_load", { ARG_STRING } }, #ifdef CONFIG_TV { MP_CMD_TV_START_SCAN, "tv_start_scan", }, -- cgit v1.2.3 From 4e2fab5846d2fe7f51a799abb4118515efac854b Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 15 Sep 2012 01:10:59 +0200 Subject: commands: rename properties, update input.conf Use "-" instead of "_" in property names. The intent is that property names and options names should be the same (if they refer to the same thing), and options use "-" as word separator. Rename some other properties too, e.g. "switch_audio" -> "audio". Add a way to translate the old property names to the new ones, similar to the input command legacy bridge. Update input.conf. Use the new property names, and don't use legacy commands. --- input/input.c | 77 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 39 deletions(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index 97d6a6b25a..7d751ea1bf 100644 --- a/input/input.c +++ b/input/input.c @@ -161,46 +161,45 @@ static const mp_cmd_t mp_cmds[] = { struct legacy_cmd { const char *old, *new; }; -#define LEGACY_STEP(old) {old, "switch " old} static const struct legacy_cmd legacy_cmds[] = { - LEGACY_STEP("loop"), - {"seek_chapter", "switch chapter"}, - {"switch_angle", "switch angle"}, - LEGACY_STEP("pause"), - LEGACY_STEP("volume"), - LEGACY_STEP("mute"), - LEGACY_STEP("audio_delay"), - LEGACY_STEP("switch_audio"), - LEGACY_STEP("balance"), - {"vo_fullscreen", "no-osd switch fullscreen"}, - LEGACY_STEP("panscan"), - {"vo_ontop", "switch ontop"}, - {"vo_rootwin", "switch rootwin"}, - {"vo_border", "switch border"}, - {"frame_drop", "switch framedropping"}, - LEGACY_STEP("gamma"), - LEGACY_STEP("brightness"), - LEGACY_STEP("contrast"), - LEGACY_STEP("saturation"), - LEGACY_STEP("hue"), - {"switch_vsync", "switch vsync"}, - {"sub_select", "switch sub"}, - LEGACY_STEP("sub_pos"), - LEGACY_STEP("sub_delay"), - LEGACY_STEP("sub_visibility"), - {"forced_subs_only", "switch sub_forced_only"}, - LEGACY_STEP("sub_scale"), - LEGACY_STEP("ass_use_margins"), - {"tv_set_brightness", "tv_brightness"}, - {"tv_set_hue", "tv_hue"}, - {"tv_set_saturation", "tv_saturation"}, - {"tv_set_contrast", "tv_contrast"}, - {"step_property_osd", "switch"}, - {"step_property", "no-osd switch"}, - {"set_property", "no-osd set"}, - {"set_property_osd", "set"}, - {"pt_step 1", "playlist_next"}, - {"pt_step -1", "playlist_prev"}, + {"loop", "switch loop"}, + {"seek_chapter", "switch chapter"}, + {"switch_angle", "switch angle"}, + {"pause", "switch pause"}, + {"volume", "switch volume"}, + {"mute", "switch mute"}, + {"audio_delay", "switch audio-delay"}, + {"switch_audio", "switch audio"}, + {"balance", "switch balance"}, + {"vo_fullscreen", "no-osd switch fullscreen"}, + {"panscan", "switch panscan"}, + {"vo_ontop", "switch ontop"}, + {"vo_rootwin", "switch rootwin"}, + {"vo_border", "switch border"}, + {"frame_drop", "switch framedropping"}, + {"gamma", "switch gamma"}, + {"brightness", "switch brightness"}, + {"contrast", "switch contrast"}, + {"saturation", "switch saturation"}, + {"hue", "switch hue"}, + {"switch_vsync", "switch vsync"}, + {"sub_select", "switch sub"}, + {"sub_pos", "switch sub-pos"}, + {"sub_delay", "switch sub-delay"}, + {"sub_visibility", "switch sub-visibility"}, + {"forced_subs_only", "switch sub-forced-only"}, + {"sub_scale", "switch sub-scale"}, + {"ass_use_margins", "switch ass-use-margins"}, + {"tv_set_brightness", "switch tv-brightness"}, + {"tv_set_hue", "switch tv-hue"}, + {"tv_set_saturation", "switch tv-saturation"}, + {"tv_set_contrast", "switch tv-contrast"}, + {"step_property_osd", "switch"}, + {"step_property", "no-osd switch"}, + {"set_property", "no-osd set"}, + {"set_property_osd", "set"}, + {"pt_step 1", "playlist_next"}, + {"pt_step -1", "playlist_prev"}, {0} }; -- cgit v1.2.3 From 950999dd7bcf863535634e2ac227d19979beadd4 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 15 Sep 2012 01:48:27 +0200 Subject: commands: remove speed_set/speed_incr commands Redundant with set/switch commands. --- input/input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index 7d751ea1bf..a4575d8f37 100644 --- a/input/input.c +++ b/input/input.c @@ -101,9 +101,7 @@ static const mp_cmd_t mp_cmds[] = { #endif { MP_CMD_SEEK, "seek", { ARG_FLOAT, OARG_INT(0), OARG_INT(0) } }, { MP_CMD_EDL_MARK, "edl_mark", }, - { MP_CMD_SPEED_INCR, "speed_incr", { ARG_FLOAT } }, { MP_CMD_SPEED_MULT, "speed_mult", { ARG_FLOAT } }, - { MP_CMD_SPEED_SET, "speed_set", { ARG_FLOAT } }, { MP_CMD_QUIT, "quit", { OARG_INT(0) } }, { MP_CMD_STOP, "stop", }, { MP_CMD_FRAME_STEP, "frame_step", }, @@ -198,6 +196,8 @@ static const struct legacy_cmd legacy_cmds[] = { {"step_property", "no-osd switch"}, {"set_property", "no-osd set"}, {"set_property_osd", "set"}, + {"speed_set", "set speed"}, + // Approximate {"pt_step 1", "playlist_next"}, {"pt_step -1", "playlist_prev"}, {0} -- cgit v1.2.3 From a749c614375107a09e5877f6bb654133c7947672 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 15 Sep 2012 02:04:57 +0200 Subject: commands: rename osd_show_[property_]text and osd_show_progression osd_show_[property_]text => show_text osd_show_progression => show_progress show_text, osd_show_property_text and osd_show_text both map to the code for the previous osd_show_property_text. The only special thing about osd_show_text is that you don't need to escape "$". Also, unfortunately osd_show_property_text requires escaping things twice, one time for the command parser, and the other time for the property formatting code, while osd_show_text needed only one level of escaping. --- input/input.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index a4575d8f37..abaa6fd7bd 100644 --- a/input/input.c +++ b/input/input.c @@ -109,9 +109,8 @@ static const mp_cmd_t mp_cmds[] = { { MP_CMD_PLAYLIST_PREV, "playlist_prev", { OARG_INT(0) } }, { MP_CMD_SUB_STEP, "sub_step", { ARG_INT, OARG_INT(0) } }, { MP_CMD_OSD, "osd", { OARG_INT(-1) } }, - { MP_CMD_OSD_SHOW_TEXT, "osd_show_text", { ARG_STRING, OARG_INT(-1), OARG_INT(0) } }, - { MP_CMD_OSD_SHOW_PROPERTY_TEXT, "osd_show_property_text", { ARG_STRING, OARG_INT(-1), OARG_INT(0) } }, - { MP_CMD_OSD_SHOW_PROGRESSION, "osd_show_progression", }, + { MP_CMD_SHOW_TEXT, "show_text", { ARG_STRING, OARG_INT(-1), OARG_INT(0) } }, + { MP_CMD_SHOW_PROGRESS, "show_progress", }, { MP_CMD_SUB_LOAD, "sub_load", { ARG_STRING } }, #ifdef CONFIG_TV { MP_CMD_TV_START_SCAN, "tv_start_scan", }, @@ -197,6 +196,9 @@ static const struct legacy_cmd legacy_cmds[] = { {"set_property", "no-osd set"}, {"set_property_osd", "set"}, {"speed_set", "set speed"}, + {"osd_show_text", "show_text"}, + {"osd_show_property_text", "show_text"}, + {"osd_show_progression", "show_progress"}, // Approximate {"pt_step 1", "playlist_next"}, {"pt_step -1", "playlist_prev"}, -- cgit v1.2.3 From a59eee489318d406497eb5fb8a95d7e23d5eee1f Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 15 Sep 2012 02:20:25 +0200 Subject: commands: remove third parameter for "switch" This could change the direction (i.e. invoke STEP_PROPERTY_DOWN), but you can just pass a negative value as second argument instead. --- input/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index abaa6fd7bd..10747b0891 100644 --- a/input/input.c +++ b/input/input.c @@ -136,7 +136,7 @@ static const mp_cmd_t mp_cmds[] = { { MP_CMD_KEYDOWN_EVENTS, "key_down_event", { ARG_INT } }, { MP_CMD_SET, "set", { ARG_STRING, ARG_STRING } }, { MP_CMD_GET_PROPERTY, "get_property", { ARG_STRING } }, - { MP_CMD_SWITCH, "switch", { ARG_STRING, OARG_FLOAT(0), OARG_INT(0) } }, + { MP_CMD_SWITCH, "switch", { ARG_STRING, OARG_FLOAT(0) } }, { MP_CMD_SET_MOUSE_POS, "set_mouse_pos", { ARG_INT, ARG_INT } }, -- cgit v1.2.3 From 6f1486b397d632feaa71f88b980491aea7b69256 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 17 Sep 2012 08:38:19 +0200 Subject: commands: replace --hardframedrop, change framedropping property Replace --hardframedrop with --framedrop=hard. Rename the framedrop property from "framedropping" to "framedrop" for the sake of making command line options have the same name as their corresponding property. Change the property to accept choice values instead of numeric values. Remove unused/forgotten auto_quality variable. --- input/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index 10747b0891..d783f53aca 100644 --- a/input/input.c +++ b/input/input.c @@ -173,7 +173,7 @@ static const struct legacy_cmd legacy_cmds[] = { {"vo_ontop", "switch ontop"}, {"vo_rootwin", "switch rootwin"}, {"vo_border", "switch border"}, - {"frame_drop", "switch framedropping"}, + {"frame_drop", "switch framedrop"}, {"gamma", "switch gamma"}, {"brightness", "switch brightness"}, {"contrast", "switch contrast"}, -- cgit v1.2.3 From 9939776e5ee70818d9cc4a5a7cd9f09da4239164 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 22 Sep 2012 05:13:29 +0200 Subject: commands: make "aspect" property writeable, replaces "switch_ratio" Move the code for "switch_ratio" to the M_PROPERTY_SET case of the "aspect" property. The rules are exactly the same, e.g. setting a ratio smaller than 0.1 sets the pixel aspect ratio to 1:1. For now, we define that writing "0" sets the PAR to 1:1, and disallow -1 (possibly reserve it to reset to default aspect ratio). --- input/input.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index d783f53aca..d3ad18075d 100644 --- a/input/input.c +++ b/input/input.c @@ -126,7 +126,6 @@ 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_SWITCH_RATIO, "switch_ratio", { OARG_FLOAT(0) } }, { 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) } }, @@ -199,9 +198,12 @@ static const struct legacy_cmd legacy_cmds[] = { {"osd_show_text", "show_text"}, {"osd_show_property_text", "show_text"}, {"osd_show_progression", "show_progress"}, - // Approximate + // Approximate (can fail if user added additional whitespace) {"pt_step 1", "playlist_next"}, {"pt_step -1", "playlist_prev"}, + // Switch_ratio without argument resets aspect ratio + {"switch_ratio ", "set aspect "}, + {"switch_ratio", "set aspect 0"}, {0} }; -- cgit v1.2.3 From 45b432f4c32be5cab798a0658d9461b3a40a6d94 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 22 Sep 2012 06:15:36 +0200 Subject: commands: replace "switch" with "add" and "cycle" Now it depends on the command whether a property wraps around, or stops at min/max valid property value. For practically all properties, it's quite unambiguous what the "switch" command should have done, and there's technically no need to replace it with these new commands. More over, most properties that cycle are boolean anyway. But it seems more orthogonal to make the difference explicit, rather than hardcoding it. Having different commands also makes it more explicit to the user what these commands do, both just due to the naming, and what wrapping policy is used. The code is simpler too. --- input/input.c | 71 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 35 deletions(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index d3ad18075d..6c3e0d709f 100644 --- a/input/input.c +++ b/input/input.c @@ -135,7 +135,8 @@ static const mp_cmd_t mp_cmds[] = { { MP_CMD_KEYDOWN_EVENTS, "key_down_event", { ARG_INT } }, { MP_CMD_SET, "set", { ARG_STRING, ARG_STRING } }, { MP_CMD_GET_PROPERTY, "get_property", { ARG_STRING } }, - { MP_CMD_SWITCH, "switch", { ARG_STRING, OARG_FLOAT(0) } }, + { MP_CMD_ADD, "add", { ARG_STRING, OARG_FLOAT(0) } }, + { MP_CMD_CYCLE, "cycle", { ARG_STRING, OARG_FLOAT(0) } }, { MP_CMD_SET_MOUSE_POS, "set_mouse_pos", { ARG_INT, ARG_INT } }, @@ -158,40 +159,40 @@ struct legacy_cmd { const char *old, *new; }; static const struct legacy_cmd legacy_cmds[] = { - {"loop", "switch loop"}, - {"seek_chapter", "switch chapter"}, - {"switch_angle", "switch angle"}, - {"pause", "switch pause"}, - {"volume", "switch volume"}, - {"mute", "switch mute"}, - {"audio_delay", "switch audio-delay"}, - {"switch_audio", "switch audio"}, - {"balance", "switch balance"}, - {"vo_fullscreen", "no-osd switch fullscreen"}, - {"panscan", "switch panscan"}, - {"vo_ontop", "switch ontop"}, - {"vo_rootwin", "switch rootwin"}, - {"vo_border", "switch border"}, - {"frame_drop", "switch framedrop"}, - {"gamma", "switch gamma"}, - {"brightness", "switch brightness"}, - {"contrast", "switch contrast"}, - {"saturation", "switch saturation"}, - {"hue", "switch hue"}, - {"switch_vsync", "switch vsync"}, - {"sub_select", "switch sub"}, - {"sub_pos", "switch sub-pos"}, - {"sub_delay", "switch sub-delay"}, - {"sub_visibility", "switch sub-visibility"}, - {"forced_subs_only", "switch sub-forced-only"}, - {"sub_scale", "switch sub-scale"}, - {"ass_use_margins", "switch ass-use-margins"}, - {"tv_set_brightness", "switch tv-brightness"}, - {"tv_set_hue", "switch tv-hue"}, - {"tv_set_saturation", "switch tv-saturation"}, - {"tv_set_contrast", "switch tv-contrast"}, - {"step_property_osd", "switch"}, - {"step_property", "no-osd switch"}, + {"loop", "cycle loop"}, + {"seek_chapter", "add chapter"}, + {"switch_angle", "cycle angle"}, + {"pause", "cycle pause"}, + {"volume", "add volume"}, + {"mute", "cycle mute"}, + {"audio_delay", "add audio-delay"}, + {"switch_audio", "cycle audio"}, + {"balance", "add balance"}, + {"vo_fullscreen", "no-osd cycle fullscreen"}, + {"panscan", "add panscan"}, + {"vo_ontop", "cycle ontop"}, + {"vo_rootwin", "cycle rootwin"}, + {"vo_border", "cycle border"}, + {"frame_drop", "cycle framedrop"}, + {"gamma", "add gamma"}, + {"brightness", "add brightness"}, + {"contrast", "add contrast"}, + {"saturation", "add saturation"}, + {"hue", "add hue"}, + {"switch_vsync", "cycle vsync"}, + {"sub_select", "cycle sub"}, + {"sub_pos", "add sub-pos"}, + {"sub_delay", "add sub-delay"}, + {"sub_visibility", "cycle sub-visibility"}, + {"forced_subs_only", "cycle sub-forced-only"}, + {"sub_scale", "add sub-scale"}, + {"ass_use_margins", "cycle ass-use-margins"}, + {"tv_set_brightness", "add tv-brightness"}, + {"tv_set_hue", "add tv-hue"}, + {"tv_set_saturation", "add tv-saturation"}, + {"tv_set_contrast", "add tv-contrast"}, + {"step_property_osd", "cycle"}, + {"step_property", "no-osd cycle"}, {"set_property", "no-osd set"}, {"set_property_osd", "set"}, {"speed_set", "set speed"}, -- cgit v1.2.3 From b591688a2774f1142a56e9c2034ecd3002fdb8d8 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 22 Sep 2012 06:33:04 +0200 Subject: input: verify input.conf on loading When input.conf is loaded, verify each command and print a warning if it's invalid or uses legacy commands. This is done for both the user's and the embedded config files. The diff is a bit noisy, because mp_input_parse_cmd() is changed to take a bstr as argument instead of a char*. --- input/input.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index 6c3e0d709f..5a0a8fd49c 100644 --- a/input/input.c +++ b/input/input.c @@ -705,7 +705,7 @@ static char *skip_no_ws(char *str) return str; } -mp_cmd_t *mp_input_parse_cmd(char *str) +mp_cmd_t *mp_input_parse_cmd(bstr str_b) { int i, l; int pausing = 0; @@ -713,7 +713,8 @@ mp_cmd_t *mp_input_parse_cmd(char *str) char *ptr; const mp_cmd_t *cmd_def; mp_cmd_t *cmd = NULL; - void *tmp = NULL; + void *tmp = talloc_new(NULL); + char *str = bstrdup0(tmp, str_b); str = skip_ws(str); @@ -739,8 +740,7 @@ mp_cmd_t *mp_input_parse_cmd(char *str) mp_tmsg(MSGT_INPUT, MSGL_WARN, "Warning: command '%s' is " "deprecated, replaced with '%s'. Fix your input.conf!\n", entry->old, entry->new); - str = talloc_asprintf(NULL, "%s%s", entry->new, str + old_len); - tmp = str; + str = talloc_asprintf(tmp, "%s%s", entry->new, str + old_len); break; } } @@ -1067,7 +1067,7 @@ static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, int n, int *keys) } if (strcmp(cmd, "ignore") == 0) return NULL; - ret = mp_input_parse_cmd(cmd); + ret = mp_input_parse_cmd(bstr0(cmd)); if (!ret) { char *key_buf = get_key_combo_name(keys, n); mp_tmsg(MSGT_INPUT, MSGL_ERR, @@ -1209,7 +1209,7 @@ static void read_cmd_fd(struct input_ctx *ictx, struct input_fd *cmd_fd) char *text; while ((r = read_cmd(cmd_fd, &text)) >= 0) { ictx->got_new_events = true; - struct mp_cmd *cmd = mp_input_parse_cmd(text); + struct mp_cmd *cmd = mp_input_parse_cmd(bstr0(text)); talloc_free(text); if (cmd) queue_add(&ictx->control_cmd_queue, cmd, false); @@ -1356,7 +1356,7 @@ int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd) mp_cmd_t *mp_input_get_cmd(struct input_ctx *ictx, int time, int peek_only) { if (async_quit_request) - return mp_input_parse_cmd("quit 1"); + return mp_input_parse_cmd(bstr0("quit 1")); if (ictx->control_cmd_queue.first || ictx->key_cmd_queue.first) time = 0; @@ -1531,6 +1531,9 @@ static int parse_config(struct input_ctx *ictx, bool builtin, bstr data) talloc_free(name); bind_keys(ictx, builtin, keys, command); n_binds++; + + // Print warnings if invalid commands are encountered. + talloc_free(mp_input_parse_cmd(command)); } return n_binds; -- cgit v1.2.3 From d232012287fe2e6e829ce9e4c20e0d9f9dc4ed5e Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 22 Sep 2012 14:54:57 +0200 Subject: input: handle escapes always in command parser Previously, both the command parser and property expansion (m_properties_expand_string) handled escapes with '\'. Move all escape handling into the command parser, and remove it from the property code. This removes the need to escape strings twice for commands that use property expansion. The command parser is practically rewritten: it uses m_option for the actual parsing, and reduces hackish C-string handling. --- input/input.c | 282 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 157 insertions(+), 125 deletions(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index 5a0a8fd49c..00544e38d8 100644 --- a/input/input.c +++ b/input/input.c @@ -691,185 +691,217 @@ int mp_input_add_key_fd(struct input_ctx *ictx, int fd, int select, return 1; } -static char *skip_ws(char *str) +static bool read_token(bstr str, bstr *out_rest, bstr *out_token) { - while (str[0] == ' ' || str[0] == '\t') - ++str; - return str; + bstr t = bstr_lstrip(str); + int next = bstrcspn(t, WHITESPACE "#"); + // Handle comments + if (t.start[next] == '#') + t = bstr_splice(t, 0, next); + if (!t.len) + return false; + *out_token = bstr_splice(t, 0, next); + *out_rest = bstr_cut(t, next); + return true; } -static char *skip_no_ws(char *str) +static bool eat_token(bstr *str, const char *tok) { - while (str[0] && !(str[0] == ' ' || str[0] == '\t')) - ++str; - return str; + bstr rest, token; + if (read_token(*str, &rest, &token) && bstrcmp0(token, tok) == 0) { + *str = rest; + return true; + } + return false; } -mp_cmd_t *mp_input_parse_cmd(bstr str_b) +static bool append_escape(bstr *code, char **str) +{ + if (code->len < 1) + return false; + char replace = 0; + switch (code->start[0]) { + case '"': replace = '"'; break; + case '\\': replace = '\\'; break; + case 'b': replace = '\b'; break; + case 'f': replace = '\f'; break; + case 'n': replace = '\n'; break; + case 'r': replace = '\r'; break; + case 't': replace = '\t'; break; + case 'e': replace = '\x1b'; break; + case '\'': replace = '\''; break; + } + if (replace) { + *str = talloc_strndup_append_buffer(*str, &replace, 1); + *code = bstr_cut(*code, 1); + return true; + } + if (code->start[0] == 'x' && code->len >= 3) { + bstr num = bstr_splice(*code, 1, 3); + char c = bstrtoll(num, &num, 16); + if (!num.len) + return false; + *str = talloc_strndup_append_buffer(*str, &c, 1); + *code = bstr_cut(*code, 3); + return true; + } + if (code->start[0] == 'u' && code->len >= 5) { + bstr num = bstr_splice(*code, 1, 5); + int c = bstrtoll(num, &num, 16); + if (num.len) + return false; + *str = append_utf8_buffer(*str, c); + *code = bstr_cut(*code, 5); + return true; + } + return false; +} + +static bool read_escaped_string(void *talloc_ctx, bstr *str, bstr *literal) +{ + bstr t = *str; + char *new = talloc_strdup(talloc_ctx, ""); + while (t.len) { + if (t.start[0] == '"') + break; + if (t.start[0] == '\\') { + t = bstr_cut(t, 1); + if (!append_escape(&t, &new)) + goto error; + } else { + new = talloc_strndup_append_buffer(new, t.start, 1); + t = bstr_cut(t, 1); + } + } + int len = str->len - t.len; + *literal = new ? bstr0(new) : bstr_splice(*str, 0, len); + *str = bstr_cut(*str, len); + return true; +error: + talloc_free(new); + return false; +} + +mp_cmd_t *mp_input_parse_cmd(bstr str) { - int i, l; int pausing = 0; int on_osd = MP_ON_OSD_AUTO; - char *ptr; - const mp_cmd_t *cmd_def; - mp_cmd_t *cmd = NULL; + struct mp_cmd *cmd = NULL; void *tmp = talloc_new(NULL); - char *str = bstrdup0(tmp, str_b); - - str = skip_ws(str); - if (strncmp(str, "pausing ", 8) == 0) { + if (eat_token(&str, "pausing")) { pausing = 1; - str = &str[8]; - } else if (strncmp(str, "pausing_keep ", 13) == 0) { + } else if (eat_token(&str, "pausing_keep")) { pausing = 2; - str = &str[13]; - } else if (strncmp(str, "pausing_toggle ", 15) == 0) { + } else if (eat_token(&str, "pausing_toggle")) { pausing = 3; - str = &str[15]; - } else if (strncmp(str, "pausing_keep_force ", 19) == 0) { + } else if (eat_token(&str, "pausing_keep_force")) { pausing = 4; - str = &str[19]; } - str = skip_ws(str); - + str = bstr_lstrip(str); for (const struct legacy_cmd *entry = legacy_cmds; entry->old; entry++) { size_t old_len = strlen(entry->old); - if (strncasecmp(entry->old, str, old_len) == 0) { + if (bstrcasecmp(bstr_splice(str, 0, old_len), + (bstr) {(char *)entry->old, old_len}) == 0) + { mp_tmsg(MSGT_INPUT, MSGL_WARN, "Warning: command '%s' is " "deprecated, replaced with '%s'. Fix your input.conf!\n", entry->old, entry->new); - str = talloc_asprintf(tmp, "%s%s", entry->new, str + old_len); + bstr s = bstr_cut(str, old_len); + str = bstr0(talloc_asprintf(tmp, "%s%.*s", entry->new, BSTR_P(s))); break; } } - str = skip_ws(str); - - if (strncmp(str, "no-osd ", 7) == 0) { + if (eat_token(&str, "no-osd")) { on_osd = MP_ON_OSD_NO; - str = &str[7]; } - ptr = skip_no_ws(str); - if (*ptr != 0) - l = ptr - str; - else - l = strlen(str); - - if (l == 0) - goto error; - - for (i = 0; mp_cmds[i].name != NULL; i++) { - const char *cmd = mp_cmds[i].name; - if (strncasecmp(cmd, str, l) == 0 && strlen(cmd) == l) + int cmd_idx = 0; + while (mp_cmds[cmd_idx].name != NULL) { + if (eat_token(&str, mp_cmds[cmd_idx].name)) break; + cmd_idx++; } - if (mp_cmds[i].name == NULL) + if (mp_cmds[cmd_idx].name == NULL) goto error; - cmd_def = &mp_cmds[i]; - cmd = talloc_ptrtype(NULL, cmd); - *cmd = (mp_cmd_t){ - .id = cmd_def->id, - .name = talloc_strdup(cmd, cmd_def->name), - .pausing = pausing, - .on_osd = on_osd, - }; - - ptr = str; + *cmd = mp_cmds[cmd_idx]; + cmd->pausing = pausing; + cmd->on_osd = on_osd; - for (i = 0; ptr && i < MP_CMD_MAX_ARGS; i++) { - while (ptr[0] != ' ' && ptr[0] != '\t' && ptr[0] != '\0') - ptr++; - if (ptr[0] == '\0') - break; - while (ptr[0] == ' ' || ptr[0] == '\t') - ptr++; - if (ptr[0] == '\0' || ptr[0] == '#') + for (int i = 0; i < MP_CMD_MAX_ARGS; i++) { + if (!cmd->args[i].type) break; - cmd->args[i].type = cmd_def->args[i].type; - switch (cmd_def->args[i].type) { - case MP_CMD_ARG_INT: - errno = 0; - cmd->args[i].v.i = atoi(ptr); - if (errno != 0) { + str = bstr_lstrip(str); + bstr arg = {0}; + if (cmd->args[i].type == MP_CMD_ARG_STRING && + bstr_eatstart0(&str, "\"")) + { + if (!read_escaped_string(tmp, &str, &arg)) { mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d " - "isn't an integer.\n", cmd_def->name, i + 1); + "has broken string escapes.\n", cmd->name, i + 1); goto error; } - break; - case MP_CMD_ARG_FLOAT: - errno = 0; - cmd->args[i].v.f = atof(ptr); - if (errno != 0) { - mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d " - "isn't a float.\n", cmd_def->name, i + 1); + if (!bstr_eatstart0(&str, "\"")) { + mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d is " + "unterminated.\n", cmd->name, i + 1); goto error; } - break; - case MP_CMD_ARG_STRING: { - int term = ' '; - if (*ptr == '\'' || *ptr == '"') - term = *ptr++; - char *argptr = talloc_size(cmd, strlen(ptr) + 1); - cmd->args[i].v.s = argptr; - while (1) { - if (*ptr == 0) { - if (term == ' ') - break; - mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s: argument %d is " - "unterminated.\n", cmd_def->name, i + 1); - goto error; - } - if (*ptr == term) - break; - if (*ptr == '\\') - ptr++; - if (*ptr != 0) - *argptr++ = *ptr++; - } - *argptr = 0; - break; + } else { + if (!read_token(str, &str, &arg)) + break; } - case 0: - ptr = NULL; - break; - default: - mp_tmsg(MSGT_INPUT, MSGL_ERR, "Unknown argument %d\n", i); + // 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); + 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++; } - cmd->nargs = i; - int min_args; - for (min_args = 0; min_args < MP_CMD_MAX_ARGS - && cmd_def->args[min_args].type - && !cmd_def->args[min_args].optional; min_args++); - if (cmd->nargs < min_args) { - mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command \"%s\" requires at least %d " - "arguments, we found only %d so far.\n", cmd_def->name, - min_args, cmd->nargs); + bstr dummy; + if (read_token(str, &dummy, &dummy)) { + mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s has trailing unused " + "arguments: '%.*s'.\n", cmd->name, BSTR_P(str)); + // Better make it fatal to make it clear something is wrong. goto error; } - for (; i < MP_CMD_MAX_ARGS && cmd_def->args[i].type; i++) { - memcpy(&cmd->args[i], &cmd_def->args[i], sizeof(struct mp_cmd_arg)); - if (cmd_def->args[i].type == MP_CMD_ARG_STRING - && cmd_def->args[i].v.s != NULL) - cmd->args[i].v.s = talloc_strdup(cmd, cmd_def->args[i].v.s); + int min_args = 0; + while (min_args < MP_CMD_MAX_ARGS && cmd->args[min_args].type + && !cmd->args[min_args].optional) + { + min_args++; + } + if (cmd->nargs < min_args) { + mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s requires at least %d " + "arguments, we found only %d so far.\n", cmd->name, min_args, + cmd->nargs); + goto error; } - - if (i < MP_CMD_MAX_ARGS) - cmd->args[i].type = 0; talloc_free(tmp); return cmd; - error: - mp_cmd_free(cmd); +error: + talloc_free(cmd); talloc_free(tmp); return NULL; } -- cgit v1.2.3 From 0de86f5bf386e987c0a28dbecdc69155c1abdbcd Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 22 Sep 2012 15:17:15 +0200 Subject: input: warn about non-existing commands, add explicit "ignore" command If a command is not found, warn about it at loading time (just like other command parsing errors are printed at loading time). Add an explicit "ignore" command. input.conf instructs users to use this command to cancel out existing mapping. This clashed with the warning added in this commit. Make "ignore" a real command and remove the specialcasing for it from get_cmd_from_keys(). Now "ignore" is ignored because it's not handled in command.c. --- input/input.c | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) (limited to 'input/input.c') diff --git a/input/input.c b/input/input.c index 00544e38d8..b5b9c4ce1b 100644 --- a/input/input.c +++ b/input/input.c @@ -93,6 +93,7 @@ struct key_name { #define OARG_STRING(def) { .type = MP_CMD_ARG_STRING, .optional = true, .v.s = def } static const mp_cmd_t mp_cmds[] = { + { MP_CMD_IGNORE, "ignore", }, #ifdef CONFIG_RADIO { MP_CMD_RADIO_STEP_CHANNEL, "radio_step_channel", { ARG_INT } }, { MP_CMD_RADIO_SET_CHANNEL, "radio_set_channel", { ARG_STRING } }, @@ -825,8 +826,11 @@ mp_cmd_t *mp_input_parse_cmd(bstr str) cmd_idx++; } - if (mp_cmds[cmd_idx].name == NULL) + if (mp_cmds[cmd_idx].name == NULL) { + mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command '%.*s' not found.\n", + BSTR_P(str)); goto error; + } cmd = talloc_ptrtype(NULL, cmd); *cmd = mp_cmds[cmd_idx]; @@ -1037,15 +1041,14 @@ static char *find_bind_for_key(const struct cmd_bind *binds, int n, int *keys) } static struct cmd_bind_section *get_bind_section(struct input_ctx *ictx, - bool builtin, - char *section) + bool builtin, bstr section) { struct cmd_bind_section *bind_section = ictx->cmd_bind_sections; - if (section == NULL) - section = "default"; + if (section.len == 0) + section = bstr0("default"); while (bind_section) { - if (strcmp(section, bind_section->section) == 0 + if (bstrcmp0(section, bind_section->section) == 0 && builtin == bind_section->is_builtin) return bind_section; if (bind_section->next == NULL) @@ -1060,7 +1063,7 @@ static struct cmd_bind_section *get_bind_section(struct input_ctx *ictx, bind_section = ictx->cmd_bind_sections; } bind_section->cmd_binds = NULL; - bind_section->section = talloc_strdup(bind_section, section); + bind_section->section = bstrdup0(bind_section, section); bind_section->is_builtin = builtin; bind_section->next = NULL; return bind_section; @@ -1070,9 +1073,9 @@ static char *section_find_bind_for_key(struct input_ctx *ictx, bool builtin, char *section, int n, int *keys) { - struct cmd_bind_section *bs = get_bind_section(ictx, builtin, section); - const struct cmd_bind *binds = bs->cmd_binds; - return binds ? find_bind_for_key(binds, n, keys) : NULL; + struct cmd_bind_section *bs = get_bind_section(ictx, builtin, + bstr0(section)); + return bs->cmd_binds ? find_bind_for_key(bs->cmd_binds, n, keys) : NULL; } static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, int n, int *keys) @@ -1097,8 +1100,6 @@ static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, int n, int *keys) talloc_free(key_buf); return NULL; } - if (strcmp(cmd, "ignore") == 0) - return NULL; ret = mp_input_parse_cmd(bstr0(cmd)); if (!ret) { char *key_buf = get_key_combo_name(keys, n); @@ -1493,24 +1494,14 @@ static int get_input_from_name(char *name, int *keys) return 1; } -static void bind_keys(struct input_ctx *ictx, bool builtin, +static void bind_keys(struct input_ctx *ictx, bool builtin, bstr section, const int keys[MP_MAX_KEY_DOWN + 1], bstr command) { int i = 0, j; struct cmd_bind *bind = NULL; struct cmd_bind_section *bind_section = NULL; - char *section = NULL; - - if (bstr_startswith0(command, "{")) { - int p = bstrchr(command, '}'); - if (p != -1) { - bstr bsection = bstr_strip(bstr_splice(command, 1, p)); - section = bstrdup0(NULL, bsection); - command = bstr_lstrip(bstr_cut(command, p + 1)); - } - } + bind_section = get_bind_section(ictx, builtin, section); - talloc_free(section); if (bind_section->cmd_binds) { for (i = 0; bind_section->cmd_binds[i].cmd != NULL; i++) { @@ -1561,7 +1552,17 @@ static int parse_config(struct input_ctx *ictx, bool builtin, bstr data) continue; } talloc_free(name); - bind_keys(ictx, builtin, keys, command); + + bstr section = {0}; + if (bstr_startswith0(command, "{")) { + int p = bstrchr(command, '}'); + if (p != -1) { + section = bstr_strip(bstr_splice(command, 1, p)); + command = bstr_lstrip(bstr_cut(command, p + 1)); + } + } + + bind_keys(ictx, builtin, section, keys, command); n_binds++; // Print warnings if invalid commands are encountered. -- cgit v1.2.3 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 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 62 insertions(+), 44 deletions(-) (limited to 'input/input.c') 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].option