1
0
mirror of https://github.com/mpv-player/mpv synced 2025-03-21 18:57:35 +00:00

player: add a number of new playlist contol commands/properties

Should give a good deal more explicit control and insight over the
player state.

Some feel a bit pointless, and/or expose internal weirdness. However,
it's not like the existing weirdness didn't exist before, or can be made
go away. (In part, the weirdness is because certain in-between states
are visible. Hiding them would make things simpler, but less flexible.)

Maybe this actually gives users a better idea how the API _should_ look
like, too.

On a side note, this tries to really guarantee that mpctx->playing is
set between playback start/end. For that, the loadfile.c changes assume
that mpctx->playing is set (guaranteed by code above the change), and
that playing->filename is set (probably could never be false; was broken
before and actually would have crashed if that could ever happen; in any
case, also add an assert to playlist.c for this).

playlist_entry_to_index() now tolerates playlist_entrys that are not
part of the playlist. This is also needed for mpctx->playing.
This commit is contained in:
wm4 2020-03-21 17:08:43 +01:00
parent 68d9d11ddf
commit e9e93b4dbe
5 changed files with 156 additions and 19 deletions

View File

@ -48,6 +48,12 @@ Interface changes
- the playlist-pos and playlist-pos-1 properties now can return and accept
-1, and are never unavailable. Out of range indexes are now accepted, but
behave like writing -1.
- the playlist-pos and playlist-pos-1 properties deprecate the current
behavior when writing back the current value to the property: currently,
this restarts playback, but in the future, it will do nothing.
Using the "playlist-play-index" command is recommended instead.
- add "playlist-play-index" command
- add playlist-current-pos, playlist-playing-pos properties
--- mpv 0.32.0 ---
- change behavior when using legacy option syntax with options that start
with two dashes (``--`` instead of a ``-``). Now, using the recommended

View File

@ -377,6 +377,29 @@ Remember to quote string arguments in input.conf (see `Flat command syntax`_).
force
Terminate playback if the first file is being played.
``playlist-play-index <integer|current|none>``
Start (or restart) playback of the given playlist index. In addition to the
0-based playlist entry index, it supports the following values:
<current>
The current playlist entry (as in ``playlist-current-pos``) will be
played again (unload and reload). If none is set, playback is stopped.
(In corner cases, ``playlist-current-pos`` can point to a playlist entry
even if playback is currently inactive,
<none>
Playback is stopped. If idle mode (``--idle``) is enabled, the player
will enter idle mode, otherwise it will exit.
This comm and is similar to ``loadfile`` in that it only manipulates the
state of what to play next, without waiting until the current file is
unloaded, and the next one is loaded.
Setting ``playlist-pos`` or similar properties can have a similar effect to
this command. However, it's more explicit, and guarantees that playback is
restarted if for example the new playlist entry is the same as the previous
one.
``loadfile <url> [<flags> [<options>]]``
Load the given file or URL and play it. Technically, this is just a playlist
manipulation command (which either replaces the playlist or appends an entry
@ -649,11 +672,17 @@ Remember to quote string arguments in input.conf (see `Flat command syntax`_).
Write the resume config file that the ``quit-watch-later`` command writes,
but continue playback normally.
``stop``
``stop [<flags>]``
Stop playback and clear playlist. With default settings, this is
essentially like ``quit``. Useful for the client API: playback can be
stopped without terminating the player.
The first argument is optional, and supports the following flags:
keep-playlist
Do not clear the playlist.
``mouse <x> <y> [<button> [<mode>]]``
Send a mouse event with given coordinate (``<x>``, ``<y>``).
@ -2242,6 +2271,9 @@ Property list
Current position on playlist. The first entry is on position 0. Writing to
this property may start playback at the new position.
In some cases, this is not necessarily the currently playing file. See
explanation of ``current`` and ``playing`` flags in ``playlist``.
If there the playlist is empty, or if it's non-empty, but no entry is
"current", this property returns -1. Likewise, writing -1 will put the
player into idle mode (or exit playback if idle mode is not enabled). If an
@ -2249,15 +2281,47 @@ Property list
(Before mpv 0.33.0, instead of returning -1, this property was unavailable
if no playlist entry was current.)
What happens if you write the same value back to the property is
implementation dependent. Currently, writing the same value will restart
playback from the beginning. It is possible (but not necessarily planned)
that in the future, write access if the same value is written will be
ignored.
Writing the current value back to the property is subject to change.
Currently, it will restart playback of the playlist entry. But in the
future, writing the current value will be ignored. Use the
``playlist-play-index`` command to get guaranteed behavior.
``playlist-pos-1`` (RW)
Same as ``playlist-pos``, but 1-based.
``playlist-current-pos`` (RW)
Index of the "current" item on playlist. This usually, but not necessarily,
the currently playing item (see ``playlist-playing-pos``). Depending on the
exact internal state of the player, it may refer to the playlist item to
play next, or the playlist item used to determine what to play next.
For reading, this is exactly the same as ``playlist-pos``.
For writing, this *only* sets the position of the "current" item, without
stopping playback of the current file (or starting playback, if this is done
in idle mode). Use -1 to remove the current flag.
This property is only vaguely useful. If set during playback, it will
typically cause the playlist entry *after* it to be played next. Another
possibly odd observable state is that if ``playlist-next`` is run during
playback, this property is set to the playlist entry to play next (unlike
the previous case). There is an internal flag that decides whether the
current playlist entry or the next one should be played, and this flag is
currently inaccessible for API users. (Whether this behavior will kept is
possibly subject to change.)
``playlist-playing-pos``
Index of the "playing" item on playlist. A playlist item is "playing" if
it's being loaded, actually playing, or being unloaded. This property is set
during the ``MPV_EVENT_START_FILE`` (``start-file``) and the
``MPV_EVENT_START_END`` (``end-file``) events. Outside of that, it returns
-1. If the playlist entry was somehow removed during playback, but playback
hasn't stopped yet, or is in progress of being stopped, it also returns -1.
(This can happen at least during state transitions.)
In the "playing" state, this is usually the same as ``playlist-pos``, except
during state changes, or if ``playlist-current-pos`` was written explicitly.
``playlist-count``
Number of total playlist entries.
@ -2274,12 +2338,13 @@ Property list
``playlist/N/filename``
Filename of the Nth entry.
``playlist/N/current``, ``playlist/N/playing``
``yes`` if this entry is currently playing (or being loaded).
Unavailable or ``no`` otherwise. When changing files, ``current`` and
``playing`` can be different, because the currently playing file hasn't
been unloaded yet; in this case, ``current`` refers to the new
selection. (Since mpv 0.7.0.)
``playlist/N/playing``
``yes`` if the ``playlist-playing-pos`` property points to this entry,
unavailable or ``no`` otherwise.
``playlist/N/current``
``yes`` if the ``playlist-current-pos`` property points to this entry,
unavailable or ``no`` otherwise.
``playlist/N/title``
Name of the Nth entry. Only available if the playlist file contains

View File

@ -62,6 +62,7 @@ static void playlist_update_indexes(struct playlist *pl, int start, int end)
void playlist_add(struct playlist *pl, struct playlist_entry *add)
{
assert(add->filename);
MP_TARRAY_APPEND(pl, pl->entries, pl->num_entries, add);
add->pl = pl;
add->pl_index = pl->num_entries - 1;
@ -283,9 +284,8 @@ void playlist_append_entries(struct playlist *pl, struct playlist *source_pl)
// Return -1 if e is not on the list, or if e is NULL.
int playlist_entry_to_index(struct playlist *pl, struct playlist_entry *e)
{
if (!e)
if (!e || e->pl != pl)
return -1;
assert(e->pl == pl);
return e->pl_index;
}

View File

@ -2700,6 +2700,39 @@ static int mp_property_sub_end(void *ctx, struct m_property *prop,
return m_property_double_ro(action, arg, end);
}
static int mp_property_playlist_current_pos(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
struct playlist *pl = mpctx->playlist;
switch (action) {
case M_PROPERTY_GET: {
*(int *)arg = playlist_entry_to_index(pl, pl->current);
return M_PROPERTY_OK;
}
case M_PROPERTY_SET: {
pl->current = playlist_entry_from_index(pl, *(int *)arg);
mp_notify(mpctx, MP_EVENT_CHANGE_PLAYLIST, NULL);
return M_PROPERTY_OK;
}
case M_PROPERTY_GET_TYPE:
*(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_INT};
return M_PROPERTY_OK;
}
return M_PROPERTY_NOT_IMPLEMENTED;
}
static int mp_property_playlist_playing_pos(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
struct playlist *pl = mpctx->playlist;
return m_property_int_ro(action, arg,
playlist_entry_to_index(pl, mpctx->playing));
}
static int mp_property_playlist_pos_x(void *ctx, struct m_property *prop,
int action, void *arg, int base)
{
@ -2714,6 +2747,11 @@ static int mp_property_playlist_pos_x(void *ctx, struct m_property *prop,
}
case M_PROPERTY_SET: {
int pos = *(int *)arg - base;
if (pos >= 0 && playlist_entry_to_index(pl, pl->current) == pos) {
MP_WARN(mpctx, "Behavior of %s when writing the same value will "
"change (currently restarts, it will stop doing this).\n",
prop->name);
}
mp_set_playlist_entry(mpctx, playlist_entry_from_index(pl, pos));
return M_PROPERTY_OK;
}
@ -3348,6 +3386,8 @@ static const struct m_property mp_properties_base[] = {
{"playlist", mp_property_playlist},
{"playlist-pos", mp_property_playlist_pos},
{"playlist-pos-1", mp_property_playlist_pos_1},
{"playlist-current-pos", mp_property_playlist_current_pos},
{"playlist-playing-pos", mp_property_playlist_playing_pos},
M_PROPERTY_ALIAS("playlist-count", "playlist/count"),
// Audio
@ -3508,7 +3548,8 @@ static const char *const *const mp_event_property_change[] = {
E(MP_EVENT_WIN_STATE, "display-names", "display-fps"),
E(MP_EVENT_WIN_STATE2, "display-hidpi-scale"),
E(MP_EVENT_CHANGE_PLAYLIST, "playlist", "playlist-pos", "playlist-pos-1",
"playlist-count", "playlist/count"),
"playlist-count", "playlist/count", "playlist-current-pos",
"playlist-playing-pos"),
E(MP_EVENT_CORE_IDLE, "core-idle", "eof-reached"),
};
#undef E
@ -4722,6 +4763,21 @@ static void cmd_playlist_next_prev(void *p)
mpctx->add_osd_seek_info |= OSD_SEEK_INFO_CURRENT_FILE;
}
static void cmd_playlist_play_index(void *p)
{
struct mp_cmd_ctx *cmd = p;
struct MPContext *mpctx = cmd->mpctx;
struct playlist *pl = mpctx->playlist;
int pos = cmd->args[0].v.i;
if (pos == -2)
pos = playlist_entry_to_index(pl, pl->current);
mp_set_playlist_entry(mpctx, playlist_entry_from_index(pl, pos));
if (cmd->on_osd & MP_ON_OSD_MSG)
mpctx->add_osd_seek_info |= OSD_SEEK_INFO_CURRENT_FILE;
}
static void cmd_sub_step_seek(void *p)
{
struct mp_cmd_ctx *cmd = p;
@ -4940,8 +4996,10 @@ static void cmd_stop(void *p)
{
struct mp_cmd_ctx *cmd = p;
struct MPContext *mpctx = cmd->mpctx;
int flags = cmd->args[0].v.i;
playlist_clear(mpctx->playlist);
if (!(flags & 1))
playlist_clear(mpctx->playlist);
if (mpctx->stop_play != PT_QUIT)
mpctx->stop_play = PT_STOP;
mp_wakeup_core(mpctx);
@ -5605,7 +5663,9 @@ const struct mp_cmd_def mp_cmds[] = {
{ "quit-watch-later", cmd_quit, { {"code", OPT_INT(v.i),
.flags = MP_CMD_OPT_ARG} },
.priv = &(const bool){1} },
{ "stop", cmd_stop, },
{ "stop", cmd_stop,
{ {"flags", OPT_FLAGS(v.i, {"keep-playlist", 1}), .flags = MP_CMD_OPT_ARG} }
},
{ "frame-step", cmd_frame_step, .allow_auto_repeat = true,
.on_updown = true },
{ "frame-back-step", cmd_frame_back_step, .allow_auto_repeat = true },
@ -5627,6 +5687,12 @@ const struct mp_cmd_def mp_cmds[] = {
},
.priv = &(const int){-1},
},
{ "playlist-play-index", cmd_playlist_play_index,
{
{"index", OPT_CHOICE(v.i, {"current", -2}, {"none", -1}),
M_RANGE(-1, INT_MAX)},
}
},
{ "playlist-shuffle", cmd_playlist_shuffle, },
{ "playlist-unshuffle", cmd_playlist_unshuffle, },
{ "sub-step", cmd_sub_step_seek, { {"skip", OPT_INT(v.i)} },

View File

@ -1409,8 +1409,8 @@ static void play_current_file(struct MPContext *mpctx)
reset_playback_state(mpctx);
mpctx->playing = mpctx->playlist->current;
if (!mpctx->playing || !mpctx->playing->filename)
goto terminate_playback;
assert(mpctx->playing);
assert(mpctx->playing->filename);
mpctx->playing->reserved += 1;
mpctx->filename = talloc_strdup(NULL, mpctx->playing->filename);