mirror of https://github.com/mpv-player/mpv
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.
This commit is contained in:
parent
2e91d44e20
commit
893f4a0fee
|
@ -251,31 +251,36 @@ bool mp_replace_legacy_cmd(void *t, bstr *s)
|
||||||
return false;
|
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:
|
||||||
case MP_CMD_QUIT_WATCH_LATER:
|
case MP_CMD_QUIT_WATCH_LATER:
|
||||||
case MP_CMD_STOP:
|
case MP_CMD_STOP:
|
||||||
|
return 2;
|
||||||
case MP_CMD_PLAYLIST_NEXT:
|
case MP_CMD_PLAYLIST_NEXT:
|
||||||
case MP_CMD_PLAYLIST_PREV:
|
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)
|
bool mp_input_is_abort_cmd(struct mp_cmd *cmd)
|
||||||
{
|
{
|
||||||
if (is_abort_cmd(cmd->id))
|
return is_abort_cmd(cmd) >= 2;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mp_input_is_repeatable_cmd(struct mp_cmd *cmd)
|
bool mp_input_is_repeatable_cmd(struct mp_cmd *cmd)
|
||||||
|
|
|
@ -101,8 +101,10 @@ enum mp_command_type {
|
||||||
MP_CMD_COMMAND_LIST, // list of sub-commands in args[0].v.p
|
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;
|
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_abort_cmd(struct mp_cmd *cmd);
|
||||||
|
|
||||||
bool mp_input_is_repeatable_cmd(struct mp_cmd *cmd);
|
bool mp_input_is_repeatable_cmd(struct mp_cmd *cmd);
|
||||||
|
|
|
@ -245,17 +245,6 @@ static int queue_count_cmds(struct cmd_queue *queue)
|
||||||
return res;
|
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)
|
static void queue_remove(struct cmd_queue *queue, struct mp_cmd *cmd)
|
||||||
{
|
{
|
||||||
struct mp_cmd **p_prev = &queue->first;
|
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)
|
int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd)
|
||||||
{
|
{
|
||||||
input_lock(ictx);
|
input_lock(ictx);
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
// Abort only if there are going to be at least 2 commands in the queue.
|
if (ictx->cancel && test_abort_cmd(ictx, cmd))
|
||||||
if (ictx->cancel && mp_input_is_abort_cmd(cmd) && has_abort_cmds(ictx))
|
|
||||||
mp_cancel_trigger(ictx->cancel);
|
mp_cancel_trigger(ictx->cancel);
|
||||||
queue_add_tail(&ictx->cmd_queue, cmd);
|
queue_add_tail(&ictx->cmd_queue, cmd);
|
||||||
mp_input_wakeup(ictx);
|
mp_input_wakeup(ictx);
|
||||||
|
|
Loading…
Reference in New Issue