mirror of https://github.com/mpv-player/mpv
playtree: --shuffle shouldn't make playlist navigation useless
When --shuffle was used, the pt_step -1 jumped to the next file, instead of the previously played file. This was because the playtree entries were never actually shuffled, but instead a random unplayed file was picked. Fix this by actually shuffling the playtree in advance. I couldn't see any clear location where exactly this should happen, so it's done when a playtree iterator is created. Not removing the old code, since new playtree entries could be added while an iterator is active.
This commit is contained in:
parent
3b03f4995d
commit
34b22ec6ea
54
playtree.c
54
playtree.c
|
@ -411,6 +411,58 @@ play_tree_iter_push_params(play_tree_iter_t* iter) {
|
|||
iter->entry_pushed = 1;
|
||||
}
|
||||
|
||||
// Shuffle the tree if the PLAY_TREE_RND flag is set, and unset it.
|
||||
// This is done recursively, but only the siblings with the same parent are
|
||||
// shuffled with each other.
|
||||
static void shuffle_tree(play_tree_t *pt) {
|
||||
if (!pt)
|
||||
return;
|
||||
|
||||
int count = 0;
|
||||
play_tree_t *child = pt->child;
|
||||
while (child) {
|
||||
// possibly shuffle children
|
||||
shuffle_tree(child);
|
||||
child = child->next;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (pt->flags & PLAY_TREE_RND) {
|
||||
// Move a random element to the front and go to the next, until no
|
||||
// elements are left.
|
||||
// prev = pointer to next-link to the first yet-unshuffled entry
|
||||
play_tree_t** prev = &pt->child;
|
||||
while (count > 1) {
|
||||
int n = (int)((double)(count) * rand() / (RAND_MAX + 1.0));
|
||||
// move = element that is moved to front (inserted after prev)
|
||||
play_tree_t **before_move = prev;
|
||||
play_tree_t *move = *before_move;
|
||||
while (n > 0) {
|
||||
before_move = &move->next;
|
||||
move = *before_move;
|
||||
n--;
|
||||
}
|
||||
// unlink from old list
|
||||
*before_move = move->next;
|
||||
// insert between prev and the following element
|
||||
// note that move could be the first unshuffled element
|
||||
move->next = (*prev == move) ? move->next : *prev;
|
||||
*prev = move;
|
||||
prev = &move->next;
|
||||
count--;
|
||||
}
|
||||
// reconstruct prev links
|
||||
child = pt->child;
|
||||
play_tree_t *prev_child = NULL;
|
||||
while (child) {
|
||||
child->prev = prev_child;
|
||||
prev_child = child;
|
||||
child = child->next;
|
||||
}
|
||||
pt->flags = pt->flags & ~PLAY_TREE_RND;
|
||||
}
|
||||
}
|
||||
|
||||
play_tree_iter_t*
|
||||
play_tree_iter_new(play_tree_t* pt,m_config_t* config) {
|
||||
play_tree_iter_t* iter;
|
||||
|
@ -430,6 +482,8 @@ play_tree_iter_new(play_tree_t* pt,m_config_t* config) {
|
|||
iter->tree = NULL;
|
||||
iter->config = config;
|
||||
|
||||
shuffle_tree(pt);
|
||||
|
||||
if(pt->parent)
|
||||
iter->loop = pt->parent->loop;
|
||||
|
||||
|
|
Loading…
Reference in New Issue