From 893f4a0feebde98247141855700173011bdeb353 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 13 Sep 2014 16:47:30 +0200 Subject: input: distinguish playlist navigation and quit commands for abort Refine the ugly hack from the previous commit, and let the "quit" command and some others abort playback immediately. For playlist_next/playlist_prev, still use the old hack, because we can't know if they would stop playback or not. --- input/cmd_list.c | 33 +++++++++++++++++++-------------- input/cmd_list.h | 4 +++- input/input.c | 28 +++++++++++++++------------- 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/input/cmd_list.c b/input/cmd_list.c index 88e5b78f91..08b9ea5735 100644 --- a/input/cmd_list.c +++ b/input/cmd_list.c @@ -251,31 +251,36 @@ bool mp_replace_legacy_cmd(void *t, bstr *s) return false; } -static bool is_abort_cmd(int cmd_id) +// 0: no, 1: maybe, 2: sure +static int is_abort_cmd(struct mp_cmd *cmd) { - switch (cmd_id) { + switch (cmd->id) { case MP_CMD_QUIT: case MP_CMD_QUIT_WATCH_LATER: case MP_CMD_STOP: + return 2; case MP_CMD_PLAYLIST_NEXT: case MP_CMD_PLAYLIST_PREV: - return true; + return 1; + case MP_CMD_COMMAND_LIST:; + int r = 0; + for (struct mp_cmd *sub = cmd->args[0].v.p; sub; sub = sub->queue_next) { + int x = is_abort_cmd(cmd); + r = MPMAX(r, x); + } + return r; } - return false; + return 0; +} + +bool mp_input_is_maybe_abort_cmd(struct mp_cmd *cmd) +{ + return is_abort_cmd(cmd) >= 1; } bool mp_input_is_abort_cmd(struct mp_cmd *cmd) { - if (is_abort_cmd(cmd->id)) - return true; - if (cmd->id == MP_CMD_COMMAND_LIST) { - for (struct mp_cmd *sub = cmd->args[0].v.p; sub; sub = sub->queue_next) - { - if (mp_input_is_abort_cmd(sub)) - return true; - } - } - return false; + return is_abort_cmd(cmd) >= 2; } bool mp_input_is_repeatable_cmd(struct mp_cmd *cmd) diff --git a/input/cmd_list.h b/input/cmd_list.h index ada1932f8d..b2b8e2a4d2 100644 --- a/input/cmd_list.h +++ b/input/cmd_list.h @@ -101,8 +101,10 @@ enum mp_command_type { MP_CMD_COMMAND_LIST, // list of sub-commands in args[0].v.p }; -// Executing this command will abort playback (play something else, or quit). +// 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); +// This command will definitely abort playback. bool mp_input_is_abort_cmd(struct mp_cmd *cmd); bool mp_input_is_repeatable_cmd(struct mp_cmd *cmd); diff --git a/input/input.c b/input/input.c index 3e9b40d158..02589e1941 100644 --- a/input/input.c +++ b/input/input.c @@ -245,17 +245,6 @@ static int queue_count_cmds(struct cmd_queue *queue) return res; } -static bool has_abort_cmds(struct input_ctx *ictx) -{ - bool ret = false; - for (struct mp_cmd *cmd = ictx->cmd_queue.first; cmd; cmd = cmd->queue_next) - if (mp_input_is_abort_cmd(cmd)) { - ret = true; - break; - } - return ret; -} - static void queue_remove(struct cmd_queue *queue, struct mp_cmd *cmd) { struct mp_cmd **p_prev = &queue->first; @@ -794,12 +783,25 @@ static void adjust_max_wait_time(struct input_ctx *ictx, double *time) } } +static bool test_abort_cmd(struct input_ctx *ictx, struct mp_cmd *new) +{ + if (!mp_input_is_maybe_abort_cmd(new)) + return false; + if (mp_input_is_abort_cmd(new)) + return true; + // Abort only if there are going to be at least 2 commands in the queue. + for (struct mp_cmd *cmd = ictx->cmd_queue.first; cmd; cmd = cmd->queue_next) { + if (mp_input_is_maybe_abort_cmd(cmd)) + return true; + } + return false; +} + int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd) { input_lock(ictx); if (cmd) { - // Abort only if there are going to be at least 2 commands in the queue. - if (ictx->cancel && mp_input_is_abort_cmd(cmd) && has_abort_cmds(ictx)) + if (ictx->cancel && test_abort_cmd(ictx, cmd)) mp_cancel_trigger(ictx->cancel); queue_add_tail(&ictx->cmd_queue, cmd); mp_input_wakeup(ictx); -- cgit v1.2.3