Ticket #1424: mplayer-shuffle.diff

File mplayer-shuffle.diff, 4.2 KB (added by hhaamu@…, 14 years ago)

Shuffle playtree with Fisher-Yates when entering the branch

  • playtree.c

     
    221221
    222222}
    223223
     224static play_tree_t*
     225play_tree_shuffle(play_tree_t* head) {
     226  play_tree_t* iter;
     227  play_tree_t** list;
     228  int i, r;
     229  int count = 1;
     230
     231  while (head->prev)
     232    head = head->prev;
     233
     234  iter = head;
     235  while (iter = iter->next)
     236    count++;
     237
     238  if (count <= 1)
     239    return head;
     240
     241  list = malloc(count * sizeof(*list));
     242  if (list == NULL) {
     243    mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory to shuffle playlist\n",(int)sizeof(*list) * count);
     244    return head;
     245  }
     246
     247  for (i = 0, iter = head; i < count; i++) {
     248    list[i] = iter;
     249    iter = iter->next;
     250  }
     251
     252  // shuffle
     253  for (i = count - 1; i > 0; i--) {
     254    r = (int)((float)(i) * rand() / (RAND_MAX + 1.0));
     255    iter = list[i];
     256    list[i] = list[r];
     257    list[r] = iter;
     258  }
     259
     260  // rebuild playtree
     261  for (i = 0; i < count; i++) {
     262    list[i]->prev = NULL;
     263    list[i]->next = NULL;
     264  }
     265
     266  head = list[0];
     267  for (i = 1; i < count; i++) {
     268    play_tree_append_entry(head, list[i]);
     269    head = list[i];
     270  }
     271
     272  head = list[0];
     273  play_tree_set_parent(head, head->parent);
     274
     275  free(list);
     276
     277  return head;
     278}
     279
    224280void
    225281play_tree_set_child(play_tree_t* pt, play_tree_t* child) {
    226282  play_tree_t* iter;
     
    517573  free(iter);
    518574}
    519575
    520 static play_tree_t*
    521 play_tree_rnd_step(play_tree_t* pt) {
    522   int count = 0;
    523   int r;
    524   play_tree_t *i,*head;
    525576
    526   // Count how many free choice we have
    527   for(i = pt ; i->prev ; i = i->prev)
    528     if(!(i->flags & PLAY_TREE_RND_PLAYED)) count++;
    529   head = i;
    530   if(!(i->flags & PLAY_TREE_RND_PLAYED)) count++;
    531   for(i = pt->next ; i ; i = i->next)
    532     if(!(i->flags & PLAY_TREE_RND_PLAYED)) count++;
    533 
    534   if(!count) return NULL;
    535 
    536   r = (int)((float)(count) * rand() / (RAND_MAX + 1.0));
    537 
    538   for(i = head ; i  ; i=i->next) {
    539     if(!(i->flags & PLAY_TREE_RND_PLAYED)) r--;
    540     if(r < 0) return i;
    541   }
    542 
    543   mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Random stepping error\n");
    544   return NULL;
    545 }
    546 
    547 
    548577int
    549578play_tree_iter_step(play_tree_iter_t* iter, int d,int with_nodes) {
    550   play_tree_t* pt;
     579  play_tree_t *pt, *parent;
    551580
    552581  if ( !iter ) return PLAY_TREE_ITER_ENTRY;
    553582  if ( !iter->root ) return PLAY_TREE_ITER_ENTRY;
     
    568597    m_config_pop(iter->config);
    569598  }
    570599
    571   if(iter->tree->parent && (iter->tree->parent->flags & PLAY_TREE_RND))
    572     iter->mode = PLAY_TREE_ITER_RND;
    573   else
    574     iter->mode = PLAY_TREE_ITER_NORMAL;
     600  parent = iter->tree->parent;
     601  if(parent && (parent->flags & PLAY_TREE_RND)) {
     602    iter->tree = play_tree_shuffle(iter->tree);
     603    parent->flags &= ~PLAY_TREE_RND;
     604  }
    575605
    576606  iter->file = -1;
    577   if(iter->mode == PLAY_TREE_ITER_RND)
    578     pt = play_tree_rnd_step(iter->tree);
    579   else if( d > 0 ) {
     607  pt = iter->tree;
     608  if( d > 0 ) {
    580609    int i;
    581     pt = iter->tree;
    582610    for(i = d ; i > 0 && pt ; i--)
    583611      pt = pt->next;
    584612    d = i ? i : 1;
    585613  } else if(d < 0) {
    586614    int i;
    587     pt = iter->tree;
    588615    for(i = d ; i < 0 && pt ; i++)
    589616      pt = pt->prev;
    590617    d = i ? i : -1;
    591   } else
    592     pt = iter->tree;
     618  }
    593619
    594620  if(pt == NULL) { // No next
    595621    // Must we loop?
    596     if (iter->mode == PLAY_TREE_ITER_RND) {
    597       if (iter->root->loop == 0)
    598         return PLAY_TREE_ITER_END;
    599       play_tree_unset_flag(iter->root, PLAY_TREE_RND_PLAYED, -1);
    600       if (iter->root->loop > 0) iter->root->loop--;
    601       // try again
    602       return play_tree_iter_step(iter, 0, with_nodes);
    603     } else
    604622    if(iter->tree->parent && iter->tree->parent->loop != 0 && ((d > 0 && iter->loop != 0) || ( d < 0 && (iter->loop < 0 || iter->loop < iter->tree->parent->loop) ) ) ) {
    605623      if(d > 0) { // Go back to the first one
    606624        for(pt = iter->tree ; pt->prev != NULL; pt = pt->prev)
     
    650668  if(iter->config) {
    651669    play_tree_iter_push_params(iter);
    652670    iter->entry_pushed = 1;
    653     if(iter->mode == PLAY_TREE_ITER_RND)
    654       pt->flags |= PLAY_TREE_RND_PLAYED;
    655671  }
    656672
    657673  return PLAY_TREE_ITER_ENTRY;
     
    717733  // Pop subtree params
    718734  if(iter->config) {
    719735    m_config_pop(iter->config);
    720     if(iter->mode == PLAY_TREE_ITER_RND)
    721       iter->tree->flags |= PLAY_TREE_RND_PLAYED;
    722736  }
    723737
    724738  return play_tree_iter_step(iter,d,with_nodes);