diff options
-rw-r--r-- | playtree.c | 92 | ||||
-rw-r--r-- | playtree.h | 11 |
2 files changed, 96 insertions, 7 deletions
diff --git a/playtree.c b/playtree.c index b940c7cb0d..5a43966f1c 100644 --- a/playtree.c +++ b/playtree.c @@ -406,6 +406,36 @@ play_tree_set_params_from(play_tree_t* dest,play_tree_t* src) { } +// all childs if deep < 0 +void +play_tree_set_flag(play_tree_t* pt, int flags , int deep) { + play_tree_t* i; + + pt->flags |= flags; + + if(deep && pt->child) { + if(deep > 0) deep--; + for(i = pt->child ; i ; i = i->next) + play_tree_set_flag(i,flags,deep); + } +} + +void +play_tree_unset_flag(play_tree_t* pt, int flags , int deep) { + play_tree_t* i; + + pt->flags &= ~flags; + + if(deep && pt->child) { + if(deep > 0) deep--; + for(i = pt->child ; i ; i = i->next) + play_tree_unset_flag(i,flags,deep); + } +} + + +//////////////////////////////////// ITERATOR ////////////////////////////////////// + static void play_tree_iter_push_params(play_tree_iter_t* iter) { int n; @@ -480,6 +510,34 @@ play_tree_iter_free(play_tree_iter_t* iter) { free(iter); } +static play_tree_t* +play_tree_rnd_step(play_tree_t* pt) { + int count = 0; + int r; + play_tree_t *i,*head; + + // Count how many free choice we have + for(i = pt ; i->prev ; i = i->prev) + if(!(i->flags & PLAY_TREE_RND_PLAYED)) count++; + head = i; + if(!(i->flags & PLAY_TREE_RND_PLAYED)) count++; + for(i = pt->next ; i ; i = i->next) + if(!(i->flags & PLAY_TREE_RND_PLAYED)) count++; + + if(!count) return NULL; + + r = (int)((count-1.0) * rand() / RAND_MAX); + + for(i = head ; i ; i=i->next) { + if(!(i->flags & PLAY_TREE_RND_PLAYED)) r--; + if(r < 0) return i; + } + + mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Random stepping error\n"); + return NULL; +} + + int play_tree_iter_step(play_tree_iter_t* iter, int d,int with_nodes) { play_tree_t* pt; @@ -503,14 +561,29 @@ play_tree_iter_step(play_tree_iter_t* iter, int d,int with_nodes) { m_config_pop(iter->config); } - iter->file = -1; - if( d > 0 ) - pt = iter->tree->next; - else if(d < 0) - pt = iter->tree->prev; + if(iter->tree->parent && (iter->tree->parent->flags & PLAY_TREE_RND)) + iter->mode = PLAY_TREE_ITER_RND; else - pt = iter->tree; + iter->mode = PLAY_TREE_ITER_NORMAL; + iter->file = -1; + if(iter->mode == PLAY_TREE_ITER_RND) + pt = play_tree_rnd_step(iter->tree); + else if( d > 0 ) { + int i; + pt = iter->tree; + for(i = d ; i > 0 && pt ; i--) + pt = pt->next; + d = i ? i : 1; + } else if(d < 0) { + int i; + pt = iter->tree; + for(i = d ; i < 0 && pt ; i++) + pt = pt->prev; + d = i ? i : -1; + } else + pt = iter->tree; + if(pt == NULL) { // No next // Must we loop? 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) ) ) ) { @@ -562,6 +635,8 @@ play_tree_iter_step(play_tree_iter_t* iter, int d,int with_nodes) { if(iter->config) { play_tree_iter_push_params(iter); iter->entry_pushed = 1; + if(iter->mode == PLAY_TREE_ITER_RND) + pt->flags |= PLAY_TREE_RND_PLAYED; } return PLAY_TREE_ITER_ENTRY; @@ -625,8 +700,11 @@ play_tree_iter_up_step(play_tree_iter_t* iter, int d,int with_nodes) { iter->tree = iter->tree->parent; // Pop subtree params - if(iter->config) + if(iter->config) { m_config_pop(iter->config); + if(iter->mode == PLAY_TREE_ITER_RND) + iter->tree->flags |= PLAY_TREE_RND_PLAYED; + } return play_tree_iter_step(iter,d,with_nodes); } diff --git a/playtree.h b/playtree.h index 00491d23b5..c7e7f056cb 100644 --- a/playtree.h +++ b/playtree.h @@ -16,6 +16,15 @@ struct m_config; #define PLAY_TREE_ENTRY_TV 2 #define PLAY_TREE_ENTRY_FILE 3 +// Playtree flags +#define PLAY_TREE_RND (1<<0) +// Playtree flags used by the iter +#define PLAY_TREE_RND_PLAYED (1<<8) + +// Iter mode +#define PLAY_TREE_ITER_NORMAL 0 +#define PLAY_TREE_ITER_RND 1 + typedef struct play_tree play_tree_t; typedef struct play_tree_iter play_tree_iter_t; typedef struct play_tree_param play_tree_param_t; @@ -50,6 +59,7 @@ struct play_tree { int loop; char** files; int entry_type; + int flags; }; struct play_tree_iter { @@ -60,6 +70,7 @@ struct play_tree_iter { int file; int num_files; int entry_pushed; + int mode; int* status_stack; // loop/valid stack to save/revert status when we go up/down int stack_size; // status stack size |