diff options
author | wm4 <wm4@nowhere> | 2020-03-21 17:08:43 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2020-03-21 19:32:50 +0100 |
commit | e9e93b4dbe748cd341a6fbea355e6ba013ada81b (patch) | |
tree | ae548b385123e620adf4432f3ab4666f425874c7 | |
parent | 68d9d11ddf2817b682b0a9f87d4d42791d5666ca (diff) | |
download | mpv-e9e93b4dbe748cd341a6fbea355e6ba013ada81b.tar.bz2 mpv-e9e93b4dbe748cd341a6fbea355e6ba013ada81b.tar.xz |
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.
-rw-r--r-- | DOCS/interface-changes.rst | 6 | ||||
-rw-r--r-- | DOCS/man/input.rst | 89 | ||||
-rw-r--r-- | common/playlist.c | 4 | ||||
-rw-r--r-- | player/command.c | 72 | ||||
-rw-r--r-- | player/loadfile.c | 4 |
5 files changed, 156 insertions, 19 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index c63669ad7c..15be443190 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -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 diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index 8f81b63f9f..e58bd2c507 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -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 diff --git a/common/playlist.c b/common/playlist.c index 1fd202b98f..89c644dc33 100644 --- a/common/playlist.c +++ b/common/playlist.c @@ -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; } diff --git a/player/command.c b/player/command.c index fd5ad60891..f8e248880a 100644 --- a/player/command.c +++ b/player/command.c @@ -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)} }, diff --git a/player/loadfile.c b/player/loadfile.c index 0ae59a0e65..5dd8b7efbf 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -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); |