Skip to content

Commit

Permalink
command: add playlist-next-playlist and playlist-prev-playlist
Browse files Browse the repository at this point in the history
playlist-prev-playlist goes to the beginning of the previous playlist
because this seems more useful and symmetrical to
playlist-next-playlist. It does not go to the beginning when the current
playlist-path starts with the previous playlist-path, e.g. with mpv
--loop-playlist foo/, which expands to foo/{1..9}.zip, the current
playlist path foo/1.zip beings with the playlist-path foo/ of {2..9}.zip
and thus playlist-prev-playlist goes to 9.zip rather than to 2.zip.

Closes #12495.
  • Loading branch information
guidocella committed Oct 9, 2023
1 parent bcb9ed5 commit 3cdf9a3
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 0 deletions.
1 change: 1 addition & 0 deletions DOCS/interface-changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ Interface changes
- `--config-dir` no longer forces cache and state files to also reside in there
- deprecate `--demuxer-cue-codepage` in favor of `--metadata-codepage`
- change the default of `metadata-codepage` to `auto`
- add `playlist-next-playlist` and `playlist-prev-playlist` commands
--- mpv 0.36.0 ---
- add `--target-contrast`
- Target luminance value is now also applied when ICC profile is used.
Expand Down
7 changes: 7 additions & 0 deletions DOCS/man/input.rst
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,13 @@ Remember to quote string arguments in input.conf (see `Flat command syntax`_).
force
Terminate playback if the first file is being played.

``playlist-next-playlist``
Go to the next entry on the playlist with a different ``playlist-path``.

``playlist-prev-playlist``
Go to the first of the previous entries on the playlist with a different
``playlist-path``.

``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:
Expand Down
68 changes: 68 additions & 0 deletions common/playlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,74 @@ struct playlist_entry *playlist_entry_get_rel(struct playlist_entry *e,
return playlist_entry_from_index(e->pl, e->pl_index + direction);
}

struct playlist_entry *playlist_get_first_in_next_playlist(struct playlist *pl,
int direction)
{
struct playlist_entry *entry = playlist_get_next(pl, direction);
if (!entry)
return NULL;

while (entry && entry->playlist_path &&
strcmp(entry->playlist_path, pl->current->playlist_path) == 0)
entry = playlist_entry_get_rel(entry, direction);

if (direction < 0)
entry = playlist_get_first_in_same_playlist(entry,
pl->current->playlist_path);

return entry;
}

struct playlist_entry *playlist_get_first_in_same_playlist(
struct playlist_entry *entry, char *current_playlist_path)
{
void *tmp = talloc_new(NULL);

if (!entry || !entry->playlist_path)
goto exit;

// Don't go to the beginning of the playlist when the current playlist-path
// starts with the previous playlist-path, e.g. with mpv --loop-playlist
// archive_dir/, which expands to archive_dir/{1..9}.zip, the current
// playlist path "archive_dir/1.zip" begins with the playlist-path
// "archive_dir/" of {2..9}.zip, so go to 9.zip instead of 2.zip. But
// playlist-prev-playlist from e.g. the directory "foobar" to the directory
// "foo" should still go to the first entry in "foo/", and this should all
// work whether mpv's arguments have trailing slashes or not, e.g. in the
// first example:
// mpv archive_dir results in the playlist-paths "archive_dir/1.zip" and
// "archive_dir"
// mpv archive_dir/ in "archive_dir/1.zip" and "archive_dir/"
// mpv archive_dir// in "archive_dir//1.zip" and "archive_dir//"
// Always adding a separator to entry->playlist_path to fix the foobar foo
// case would break the previous 2 cases instead. Stripping the separator
// from entry->playlist_path if present and appending it again makes this
// work in all cases.
char* playlist_path = talloc_strdup(tmp, entry->playlist_path);
mp_path_strip_trailing_separator(playlist_path);
if (bstr_startswith(bstr0(current_playlist_path),
bstr0(talloc_strdup_append(playlist_path, "/")))
#if HAVE_DOS_PATHS
||
bstr_startswith(bstr0(current_playlist_path),
bstr0(talloc_strdup_append(playlist_path, "\\")))
#endif
)
goto exit;

struct playlist_entry *prev = playlist_entry_get_rel(entry, -1);

while (prev && prev->playlist_path &&
strcmp(prev->playlist_path, entry->playlist_path) == 0) {
entry = prev;
prev = playlist_entry_get_rel(entry, -1);
}

exit:
talloc_free(tmp);
return entry;
}

void playlist_add_base_path(struct playlist *pl, bstr base_path)
{
if (base_path.len == 0 || bstrcmp0(base_path, ".") == 0)
Expand Down
4 changes: 4 additions & 0 deletions common/playlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ struct playlist_entry *playlist_get_last(struct playlist *pl);
struct playlist_entry *playlist_get_next(struct playlist *pl, int direction);
struct playlist_entry *playlist_entry_get_rel(struct playlist_entry *e,
int direction);
struct playlist_entry *playlist_get_first_in_next_playlist(struct playlist *pl,
int direction);
struct playlist_entry *playlist_get_first_in_same_playlist(struct playlist_entry *entry,
char *current_playlist_path);
void playlist_add_base_path(struct playlist *pl, bstr base_path);
void playlist_set_stream_flags(struct playlist *pl, int flags);
int64_t playlist_transfer_entries(struct playlist *pl, struct playlist *source_pl);
Expand Down
43 changes: 43 additions & 0 deletions player/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -5321,6 +5321,45 @@ static void cmd_playlist_next_prev(void *p)
mpctx->add_osd_seek_info |= OSD_SEEK_INFO_CURRENT_FILE;
}

static void cmd_playlist_next_prev_playlist(void *p)
{
struct mp_cmd_ctx *cmd = p;
struct MPContext *mpctx = cmd->mpctx;
int direction = *(int *)cmd->priv;

struct playlist_entry *entry =
playlist_get_first_in_next_playlist(mpctx->playlist, direction);

if (!entry && mpctx->opts->loop_times != 1 && mpctx->playlist->current) {
entry = direction > 0 ? playlist_get_first(mpctx->playlist)
: playlist_get_last(mpctx->playlist);

if (entry && entry->playlist_path &&
strcmp(entry->playlist_path,
mpctx->playlist->current->playlist_path) == 0)
entry = NULL;

if (direction > 0 && entry && mpctx->opts->loop_times > 1) {
mpctx->opts->loop_times--;
m_config_notify_change_opt_ptr(mpctx->mconfig,
&mpctx->opts->loop_times);
}

if (direction < 0)
entry = playlist_get_first_in_same_playlist(
entry, mpctx->playlist->current->playlist_path);
}

if (!entry) {
cmd->success = false;
return;
}

mp_set_playlist_entry(mpctx, entry);
if (cmd->on_osd & MP_ON_OSD_MSG)
mpctx->add_osd_seek_info |= OSD_SEEK_INFO_CURRENT_FILE;
}

static void cmd_playlist_play_index(void *p)
{
struct mp_cmd_ctx *cmd = p;
Expand Down Expand Up @@ -6373,6 +6412,10 @@ const struct mp_cmd_def mp_cmds[] = {
},
.priv = &(const int){-1},
},
{ "playlist-next-playlist", cmd_playlist_next_prev_playlist,
.priv = &(const int){1} },
{ "playlist-prev-playlist", cmd_playlist_next_prev_playlist,
.priv = &(const int){-1} },
{ "playlist-play-index", cmd_playlist_play_index,
{
{"index", OPT_CHOICE(v.i, {"current", -2}, {"none", -1}),
Expand Down

0 comments on commit 3cdf9a3

Please sign in to comment.