summaryrefslogtreecommitdiffstats
path: root/input/cmd_list.c
diff options
context:
space:
mode:
Diffstat (limited to 'input/cmd_list.c')
-rw-r--r--input/cmd_list.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/input/cmd_list.c b/input/cmd_list.c
new file mode 100644
index 0000000000..05dcb72d25
--- /dev/null
+++ b/input/cmd_list.c
@@ -0,0 +1,281 @@
+/*
+ * This file is part of MPlayer.
+ *
+ * MPlayer is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MPlayer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <limits.h>
+
+#include "common/common.h"
+#include "common/msg.h"
+#include "options/m_option.h"
+
+#include "input.h"
+#include "cmd_list.h"
+#include "cmd_parse.h"
+
+// This does not specify the real destination of the command parameter values,
+// it just provides a dummy for the OPT_ macros.
+#define OPT_BASE_STRUCT struct mp_cmd_arg
+#define ARG(t) "", v. t
+
+/* This array defines all known commands.
+ * The first field is an id used to recognize the command.
+ * The second is the command name used in slave mode and input.conf.
+ * Then comes the definition of each argument, first mandatory arguments
+ * (ARG_INT, ARG_FLOAT, ARG_STRING) if any, then optional arguments
+ * (OARG_INT(default), etc) if any. The command will be given the default
+ * 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.
+ */
+
+#define ARG_INT OPT_INT(ARG(i), 0)
+#define ARG_FLOAT OPT_FLOAT(ARG(f), 0)
+#define ARG_DOUBLE OPT_DOUBLE(ARG(d), 0)
+#define ARG_STRING OPT_STRING(ARG(s), 0)
+#define ARG_CHOICE(c) OPT_CHOICE(ARG(i), 0, c)
+#define ARG_CHOICE_OR_INT(...) OPT_CHOICE_OR_INT(ARG(i), 0, __VA_ARGS__)
+#define ARG_TIME OPT_TIME(ARG(d), 0)
+#define OARG_DOUBLE(def) OPT_DOUBLE(ARG(d), 0, OPTDEF_DOUBLE(def))
+#define OARG_INT(def) OPT_INT(ARG(i), 0, OPTDEF_INT(def))
+#define OARG_CHOICE(def, c) OPT_CHOICE(ARG(i), 0, c, OPTDEF_INT(def))
+
+#define OARG_CYCLEDIR(def) OPT_CYCLEDIR(ARG(d), 0, OPTDEF_DOUBLE(def))
+
+const struct mp_cmd_def mp_cmds[] = {
+ { MP_CMD_IGNORE, "ignore", },
+
+ { MP_CMD_SEEK, "seek", {
+ ARG_TIME,
+ OARG_CHOICE(0, ({"relative", 0}, {"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})),
+ },
+ .allow_auto_repeat = true,
+ },
+ { MP_CMD_REVERT_SEEK, "revert_seek", },
+ { MP_CMD_QUIT, "quit", { OARG_INT(0) } },
+ { MP_CMD_QUIT_WATCH_LATER, "quit_watch_later", },
+ { MP_CMD_STOP, "stop", },
+ { MP_CMD_FRAME_STEP, "frame_step", .allow_auto_repeat = true },
+ { MP_CMD_FRAME_BACK_STEP, "frame_back_step", .allow_auto_repeat = true },
+ { 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 }, .allow_auto_repeat = true },
+ { MP_CMD_SUB_SEEK, "sub_seek", { ARG_INT }, .allow_auto_repeat = true },
+ { MP_CMD_OSD, "osd", { OARG_INT(-1) } },
+ { MP_CMD_PRINT_TEXT, "print_text", { ARG_STRING }, .allow_auto_repeat = true },
+ { MP_CMD_SHOW_TEXT, "show_text", { ARG_STRING, OARG_INT(-1), OARG_INT(0) },
+ .allow_auto_repeat = true},
+ { MP_CMD_SHOW_PROGRESS, "show_progress", .allow_auto_repeat = true},
+ { MP_CMD_SUB_ADD, "sub_add", { ARG_STRING } },
+ { MP_CMD_SUB_REMOVE, "sub_remove", { OARG_INT(-1) } },
+ { MP_CMD_SUB_RELOAD, "sub_reload", { OARG_INT(-1) } },
+
+ { MP_CMD_TV_START_SCAN, "tv_start_scan", },
+ { MP_CMD_TV_STEP_CHANNEL, "tv_step_channel", { ARG_INT } },
+ { MP_CMD_TV_STEP_NORM, "tv_step_norm", },
+ { MP_CMD_TV_STEP_CHANNEL_LIST, "tv_step_chanlist", },
+ { MP_CMD_TV_SET_CHANNEL, "tv_set_channel", { ARG_STRING } },
+ { MP_CMD_TV_LAST_CHANNEL, "tv_last_channel", },
+ { 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_DVB_SET_CHANNEL, "dvb_set_channel", { ARG_INT, ARG_INT } },
+
+ { MP_CMD_SCREENSHOT, "screenshot", {
+ OARG_CHOICE(2, ({"video", 0},
+ {"window", 1},
+ {"subtitles", 2}, {"-", 2})),
+ OARG_CHOICE(0, ({"single", 0},
+ {"each-frame", 1})),
+ }},
+ { MP_CMD_SCREENSHOT_TO_FILE, "screenshot_to_file", {
+ ARG_STRING,
+ OARG_CHOICE(2, ({"video", 0},
+ {"window", 1},
+ {"subtitles", 2})),
+ }},
+ { 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_PLAYLIST_REMOVE, "playlist_remove", {
+ ARG_CHOICE_OR_INT(0, INT_MAX, ({"current", -1})),
+ }},
+ { MP_CMD_PLAYLIST_MOVE, "playlist_move", { ARG_INT, ARG_INT } },
+ { MP_CMD_RUN, "run", { ARG_STRING, ARG_STRING }, .vararg = true },
+
+ { MP_CMD_SET, "set", { ARG_STRING, ARG_STRING } },
+ { MP_CMD_GET_PROPERTY, "get_property", { ARG_STRING } },
+ { MP_CMD_ADD, "add", { ARG_STRING, OARG_DOUBLE(0) },
+ .allow_auto_repeat = true},
+ { MP_CMD_CYCLE, "cycle", {
+ ARG_STRING,
+ OARG_CYCLEDIR(1),
+ },
+ .allow_auto_repeat = true
+ },
+ { MP_CMD_MULTIPLY, "multiply", { ARG_STRING, ARG_DOUBLE },
+ .allow_auto_repeat = true},
+
+ { MP_CMD_CYCLE_VALUES, "cycle_values", { ARG_STRING, ARG_STRING, ARG_STRING },
+ .vararg = true, .allow_auto_repeat = true},
+
+ { MP_CMD_ENABLE_INPUT_SECTION, "enable_section", {
+ ARG_STRING,
+ OARG_CHOICE(0, ({"default", 0},
+ {"exclusive", 1})),
+ }},
+ { MP_CMD_DISABLE_INPUT_SECTION, "disable_section", { ARG_STRING } },
+
+ { MP_CMD_DVDNAV, "dvdnav", { ARG_STRING } },
+
+ { MP_CMD_AF, "af", { ARG_STRING, ARG_STRING } },
+
+ { MP_CMD_VF, "vf", { ARG_STRING, ARG_STRING } },
+
+ { MP_CMD_VO_CMDLINE, "vo_cmdline", { ARG_STRING } },
+
+ { MP_CMD_SCRIPT_DISPATCH, "script_dispatch", { ARG_STRING, ARG_INT } },
+
+ { MP_CMD_OVERLAY_ADD, "overlay_add",
+ { ARG_INT, ARG_INT, ARG_INT, ARG_STRING, ARG_INT, ARG_STRING, ARG_INT,
+ ARG_INT, ARG_INT }},
+ { MP_CMD_OVERLAY_REMOVE, "overlay_remove", { ARG_INT } },
+
+ {0}
+};
+
+#undef OPT_BASE_STRUCT
+#undef ARG
+
+// Map legacy commands to proper commands
+struct legacy_cmd {
+ const char *old, *new;
+};
+static const struct legacy_cmd legacy_cmds[] = {
+ {"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", "cycle fullscreen"},
+ {"panscan", "add panscan"},
+ {"vo_ontop", "cycle ontop"},
+ {"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_load", "sub_add"},
+ {"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"},
+ {"osd_show_text", "show_text"},
+ {"osd_show_property_text", "show_text"},
+ {"osd_show_progression", "show_progress"},
+ {"show_chapters_osd", "show_text ${chapter-list}"},
+ {"show_chapters", "show_text ${chapter-list}"},
+ {"show_tracks_osd", "show_text ${track-list}"},
+ {"show_tracks", "show_text ${track-list}"},
+ {"show_playlist", "show_text ${playlist}"},
+ {"speed_mult", "multiply speed"},
+
+ // 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}
+};
+
+bool mp_replace_legacy_cmd(void *t, bstr *s)
+{
+ for (const struct legacy_cmd *entry = legacy_cmds; entry->old; entry++) {
+ bstr old = bstr0(entry->old);
+ if (bstrcasecmp(bstr_splice(*s, 0, old.len), old) == 0) {
+ bstr rest = bstr_cut(*s, old.len);
+ *s = bstr0(talloc_asprintf(t, "%s%.*s", entry->new, BSTR_P(rest)));
+ return true;
+ }
+ }
+ return false;
+}
+
+bool mp_input_is_abort_cmd(int cmd_id)
+{
+ switch (cmd_id) {
+ case MP_CMD_QUIT:
+ case MP_CMD_PLAYLIST_NEXT:
+ case MP_CMD_PLAYLIST_PREV:
+ return true;
+ }
+ return false;
+}
+
+void mp_print_cmd_list(struct mp_log *out)
+{
+ for (int i = 0; mp_cmds[i].name; i++) {
+ const struct mp_cmd_def *def = &mp_cmds[i];
+ mp_info(out, "%-20.20s", def->name);
+ for (int j = 0; j < MP_CMD_MAX_ARGS && def->args[j].type; j++) {
+ const char *type = def->args[j].type->name;
+ if (def->args[j].defval)
+ mp_info(out, " [%s]", type);
+ else
+ mp_info(out, " %s", type);
+ }
+ mp_info(out, "\n");
+ }
+}