command: add a playlist-unshuffle command

Has a number of restrictions.

See: #2491, #7294
This commit is contained in:
wm4 2019-12-28 21:32:03 +01:00
parent 582f3f7cc0
commit 5a26150717
4 changed files with 42 additions and 0 deletions

View File

@ -426,6 +426,12 @@ Remember to quote string arguments in input.conf (see `Flat command syntax`_).
Shuffle the playlist. This is similar to what is done on start if the Shuffle the playlist. This is similar to what is done on start if the
``--shuffle`` option is used. ``--shuffle`` option is used.
``playlist-unshuffle``
Attempt to revert the previous ``playlist-shuffle`` command. This works
only once (multiple successive ``playlist-unshuffle`` commands do nothing).
May not work correctly if new recursive playlists have been opened since
a ``playlist-shuffle`` command.
``run <command> [<arg1> [<arg2> [...]]]`` ``run <command> [<arg1> [<arg2> [...]]]``
Run the given command. Unlike in MPlayer/mplayer2 and earlier versions of Run the given command. Unlike in MPlayer/mplayer2 and earlier versions of
mpv (0.2.x and older), this doesn't call the shell. Instead, the command mpv (0.2.x and older), this doesn't call the shell. Instead, the command

View File

@ -33,6 +33,7 @@ struct playlist_entry *playlist_entry_new(const char *filename)
char *local_filename = mp_file_url_to_filename(e, bstr0(filename)); char *local_filename = mp_file_url_to_filename(e, bstr0(filename));
e->filename = local_filename ? local_filename : talloc_strdup(e, filename); e->filename = local_filename ? local_filename : talloc_strdup(e, filename);
e->stream_flags = STREAM_ORIGIN_DIRECT; e->stream_flags = STREAM_ORIGIN_DIRECT;
e->original_index = -1;
return e; return e;
} }
@ -141,6 +142,8 @@ void playlist_add_file(struct playlist *pl, const char *filename)
void playlist_shuffle(struct playlist *pl) void playlist_shuffle(struct playlist *pl)
{ {
for (int n = 0; n < pl->num_entries; n++)
pl->entries[n]->original_index = n;
for (int n = 0; n < pl->num_entries - 1; n++) { for (int n = 0; n < pl->num_entries - 1; n++) {
int j = (int)((double)(pl->num_entries - n) * rand() / (RAND_MAX + 1.0)); int j = (int)((double)(pl->num_entries - n) * rand() / (RAND_MAX + 1.0));
MPSWAP(struct playlist_entry *, pl->entries[n], pl->entries[n + j]); MPSWAP(struct playlist_entry *, pl->entries[n], pl->entries[n + j]);
@ -148,6 +151,25 @@ void playlist_shuffle(struct playlist *pl)
playlist_update_indexes(pl, 0, -1); playlist_update_indexes(pl, 0, -1);
} }
#define CMP_INT(a, b) ((a) == (b) ? 0 : ((a) > (b) ? 1 : -1))
static int cmp_unshuffle(const void *a, const void *b)
{
struct playlist_entry *ea = *(struct playlist_entry **)a;
struct playlist_entry *eb = *(struct playlist_entry **)b;
if (ea->original_index >= 0 && ea->original_index != eb->original_index)
return CMP_INT(ea->original_index, eb->original_index);
return CMP_INT(ea->pl_index, eb->pl_index);
}
void playlist_unshuffle(struct playlist *pl)
{
if (pl->num_entries)
qsort(pl->entries, pl->num_entries, sizeof(pl->entries[0]), cmp_unshuffle);
playlist_update_indexes(pl, 0, -1);
}
// (Explicitly ignores current_was_replaced.) // (Explicitly ignores current_was_replaced.)
struct playlist_entry *playlist_get_first(struct playlist *pl) struct playlist_entry *playlist_get_first(struct playlist *pl)
{ {

View File

@ -42,6 +42,9 @@ struct playlist_entry {
char **redirects; char **redirects;
int num_redirects; int num_redirects;
// Used for unshuffling: the pl_index before it was shuffled. -1 => unknown.
int original_index;
// Set to true if playback didn't seem to work, or if the file could be // Set to true if playback didn't seem to work, or if the file could be
// played only for a very short time. This is used to make playlist // played only for a very short time. This is used to make playlist
// navigation just work in case the user has unplayable files in the // navigation just work in case the user has unplayable files in the
@ -87,6 +90,7 @@ void playlist_move(struct playlist *pl, struct playlist_entry *entry,
void playlist_add_file(struct playlist *pl, const char *filename); void playlist_add_file(struct playlist *pl, const char *filename);
void playlist_shuffle(struct playlist *pl); void playlist_shuffle(struct playlist *pl);
void playlist_unshuffle(struct playlist *pl);
struct playlist_entry *playlist_get_first(struct playlist *pl); struct playlist_entry *playlist_get_first(struct playlist *pl);
struct playlist_entry *playlist_get_last(struct playlist *pl); struct playlist_entry *playlist_get_last(struct playlist *pl);
struct playlist_entry *playlist_get_next(struct playlist *pl, int direction); struct playlist_entry *playlist_get_next(struct playlist *pl, int direction);

View File

@ -4916,6 +4916,15 @@ static void cmd_playlist_shuffle(void *p)
mp_notify(mpctx, MP_EVENT_CHANGE_PLAYLIST, NULL); mp_notify(mpctx, MP_EVENT_CHANGE_PLAYLIST, NULL);
} }
static void cmd_playlist_unshuffle(void *p)
{
struct mp_cmd_ctx *cmd = p;
struct MPContext *mpctx = cmd->mpctx;
playlist_unshuffle(mpctx->playlist);
mp_notify(mpctx, MP_EVENT_CHANGE_PLAYLIST, NULL);
}
static void cmd_stop(void *p) static void cmd_stop(void *p)
{ {
struct mp_cmd_ctx *cmd = p; struct mp_cmd_ctx *cmd = p;
@ -5629,6 +5638,7 @@ const struct mp_cmd_def mp_cmds[] = {
.priv = &(const int){-1}, .priv = &(const int){-1},
}, },
{ "playlist-shuffle", cmd_playlist_shuffle, }, { "playlist-shuffle", cmd_playlist_shuffle, },
{ "playlist-unshuffle", cmd_playlist_unshuffle, },
{ "sub-step", cmd_sub_step_seek, { OPT_INT("skip", v.i, 0) }, { "sub-step", cmd_sub_step_seek, { OPT_INT("skip", v.i, 0) },
.allow_auto_repeat = true, .priv = &(const bool){true} }, .allow_auto_repeat = true, .priv = &(const bool){true} },
{ "sub-seek", cmd_sub_step_seek, { OPT_INT("skip", v.i, 0) }, { "sub-seek", cmd_sub_step_seek, { OPT_INT("skip", v.i, 0) },