16 play_tree_is_valid(play_tree_t
* pt
);
20 play_tree_t
* r
= (play_tree_t
*)calloc(1,sizeof(play_tree_t
));
22 mp_msg(MSGT_PLAYTREE
,MSGL_ERR
,"Can't allocate %d bytes of memory\n",sizeof(play_tree_t
));
23 r
->entry_type
= PLAY_TREE_ENTRY_NODE
;
28 play_tree_free(play_tree_t
* pt
, int childs
) {
36 for(iter
= pt
->child
; iter
!= NULL
; ) {
37 play_tree_t
* nxt
=iter
->next
;
38 play_tree_free(iter
,1);
44 play_tree_remove(pt
,0,0);
46 for(iter
= pt
->child
; iter
!= NULL
; iter
= iter
->next
)
49 //if(pt->params) free(pt->params);
52 for(i
= 0 ; pt
->files
[i
] != NULL
; i
++)
61 play_tree_free_list(play_tree_t
* pt
, int childs
) {
68 for(iter
= pt
; iter
->prev
!= NULL
; iter
= iter
->prev
)
72 play_tree_t
* nxt
= iter
->next
;
73 play_tree_free(iter
,childs
);
81 play_tree_append_entry(play_tree_t
* pt
, play_tree_t
* entry
) {
86 assert(entry
!= NULL
);
92 for(iter
= pt
; iter
->next
!= NULL
; iter
= iter
->next
)
95 entry
->parent
= iter
->parent
;
102 play_tree_prepend_entry(play_tree_t
* pt
, play_tree_t
* entry
) {
107 assert(entry
!= NULL
);
110 for(iter
= pt
; iter
->prev
!= NULL
; iter
= iter
->prev
)
115 entry
->parent
= iter
->parent
;
120 assert(entry
->parent
->child
== iter
);
122 entry
->parent
->child
= entry
;
127 play_tree_insert_entry(play_tree_t
* pt
, play_tree_t
* entry
) {
131 assert(entry
!= NULL
);
134 entry
->parent
= pt
->parent
;
138 assert(pt
->next
->prev
== pt
);
140 entry
->next
= pt
->next
;
141 entry
->next
->prev
= entry
;
149 play_tree_remove(play_tree_t
* pt
, int free_it
,int with_childs
) {
156 if(pt
->prev
&& pt
->next
) {
158 assert(pt
->prev
->next
== pt
);
159 assert(pt
->next
->prev
== pt
);
161 pt
->prev
->next
= pt
->next
;
162 pt
->next
->prev
= pt
->prev
;
166 assert(pt
->prev
->next
== pt
);
168 pt
->prev
->next
= NULL
;
169 } // Begining of list
172 assert(pt
->next
->prev
== pt
);
174 pt
->next
->prev
= NULL
;
177 assert(pt
->parent
->child
== pt
);
179 pt
->parent
->child
= pt
->next
;
182 else if(pt
->parent
) {
184 assert(pt
->parent
->child
== pt
);
186 pt
->parent
->child
= NULL
;
189 pt
->prev
= pt
->next
= pt
->parent
= NULL
;
191 play_tree_free(pt
,with_childs
);
196 play_tree_set_child(play_tree_t
* pt
, play_tree_t
* child
) {
201 assert(pt
->entry_type
== PLAY_TREE_ENTRY_NODE
);
204 //DEBUG_FF: Where are the childs freed ?
205 // Attention in using this function!
206 for(iter
= pt
->child
; iter
!= NULL
; iter
= iter
->next
)
209 // Go back to first one
210 for(iter
= child
; iter
->prev
!= NULL
; iter
= iter
->prev
)
215 for( ; iter
!= NULL
; iter
= iter
->next
)
221 play_tree_set_parent(play_tree_t
* pt
, play_tree_t
* parent
) {
229 pt
->parent
->child
= NULL
;
231 for(iter
= pt
; iter
!= NULL
; iter
= iter
->next
)
232 iter
->parent
= parent
;
235 for(iter
= pt
->prev
; iter
->prev
!= NULL
; iter
= iter
->prev
)
236 iter
->parent
= parent
;
237 iter
->parent
= parent
;
238 parent
->child
= iter
;
246 play_tree_add_file(play_tree_t
* pt
,char* file
) {
252 assert(pt
->child
== NULL
);
253 assert(file
!= NULL
);
256 if(pt
->entry_type
!= PLAY_TREE_ENTRY_NODE
&&
257 pt
->entry_type
!= PLAY_TREE_ENTRY_FILE
)
261 for(n
= 0 ; pt
->files
[n
] != NULL
; n
++)
264 pt
->files
= (char**)realloc(pt
->files
,(n
+2)*sizeof(char*));
265 if(pt
->files
==NULL
) {
266 mp_msg(MSGT_PLAYTREE
,MSGL_ERR
,"Can't allocate %d bytes of memory\n",(n
+2)*sizeof(char*));
270 e
= pt
->files
[n
] = strdup(file
);
271 pt
->files
[n
+1] = NULL
;
273 pt
->entry_type
= PLAY_TREE_ENTRY_FILE
;
278 play_tree_remove_file(play_tree_t
* pt
,char* file
) {
283 assert(file
!= NULL
);
284 assert(pt
->entry_type
!= PLAY_TREE_ENTRY_NODE
);
287 for(n
=0 ; pt
->files
[n
] != NULL
; n
++) {
288 if(strcmp(file
,pt
->files
[n
]) == 0)
292 if(f
< 0) // Not found
302 memmove(&pt
->files
[f
],&pt
->files
[f
+1],(n
-f
)*sizeof(char*));
303 pt
->files
= (char**)realloc(pt
->files
,n
*sizeof(char*));
304 if(pt
->files
== NULL
) {
305 mp_msg(MSGT_PLAYTREE
,MSGL_ERR
,"Can't allocate %d bytes of memory\n",(n
+2)*sizeof(char*));
317 play_tree_set_param(play_tree_t
* pt
, char* name
, char* val
) {
322 assert(name
!= NULL
);
326 for( ; pt
->params
[n
].name
!= NULL
; n
++) {
327 if(strcasecmp(pt
->params
[n
].name
,name
) == 0)
333 if(pt
->params
[n
].value
!= NULL
) free(pt
->params
[n
].value
);
334 pt
->params
[n
].value
= val
!= NULL
? strdup(val
) : NULL
;
338 pt
->params
= (play_tree_param_t
*)realloc(pt
->params
,(n
+2)*sizeof(play_tree_param_t
));
339 if(pt
->params
== NULL
) {
340 mp_msg(MSGT_PLAYTREE
,MSGL_ERR
,"Can't realloc params (%d bytes of memory)\n",(n
+2)*sizeof(play_tree_param_t
));
343 pt
->params
[n
].name
= strdup(name
);
344 pt
->params
[n
].value
= val
!= NULL
? strdup(val
) : NULL
;
345 memset(&pt
->params
[n
+1],0,sizeof(play_tree_param_t
));
351 play_tree_unset_param(play_tree_t
* pt
, char* name
) {
356 assert(name
!= NULL
);
357 assert(pt
->params
!= NULL
);
360 for(n
= 0 ; pt
->params
[n
].name
!= NULL
; n
++) {
361 if(strcasecmp(pt
->params
[n
].name
,name
) == 0)
368 if(pt
->params
[ni
].name
) free(pt
->params
[ni
].name
);
369 if(pt
->params
[ni
].value
) free(pt
->params
[ni
].value
);
372 memmove(&pt
->params
[ni
],&pt
->params
[ni
+1],(n
-ni
)*sizeof(play_tree_param_t
));
373 pt
->params
= (play_tree_param_t
*)realloc(pt
->params
,n
*sizeof(play_tree_param_t
));
374 if(pt
->params
== NULL
) {
375 mp_msg(MSGT_PLAYTREE
,MSGL_ERR
,"Can't allocate %d bytes of memory\n",n
*sizeof(play_tree_param_t
));
387 play_tree_set_params_from(play_tree_t
* dest
,play_tree_t
* src
) {
391 assert(dest
!= NULL
);
398 for(i
= 0; src
->params
[i
].name
!= NULL
; i
++)
399 play_tree_set_param(dest
,src
->params
[i
].name
,src
->params
[i
].value
);
400 if(src
->flags
& PLAY_TREE_RND
) // pass the random flag too
401 dest
->flags
|= PLAY_TREE_RND
;
405 // all childs if deep < 0
407 play_tree_set_flag(play_tree_t
* pt
, int flags
, int deep
) {
412 if(deep
&& pt
->child
) {
414 for(i
= pt
->child
; i
; i
= i
->next
)
415 play_tree_set_flag(i
,flags
,deep
);
420 play_tree_unset_flag(play_tree_t
* pt
, int flags
, int deep
) {
425 if(deep
&& pt
->child
) {
427 for(i
= pt
->child
; i
; i
= i
->next
)
428 play_tree_unset_flag(i
,flags
,deep
);
433 //////////////////////////////////// ITERATOR //////////////////////////////////////
436 play_tree_iter_push_params(play_tree_iter_t
* iter
) {
440 assert(iter
!= NULL
);
441 assert(iter
->config
!= NULL
);
442 assert(iter
->tree
!= NULL
);
447 // We always push a config because we can set some option
449 m_config_push(iter
->config
);
451 if(pt
->params
== NULL
)
455 for(n
= 0; pt
->params
[n
].name
!= NULL
; n
++) {
457 if((e
= m_config_set_option(iter
->config
,pt
->params
[n
].name
,pt
->params
[n
].value
)) < 0) {
458 mp_msg(MSGT_PLAYTREE
,MSGL_ERR
,"Error %d while setting option '%s' with value '%s'\n",e
,
459 pt
->params
[n
].name
,pt
->params
[n
].value
);
464 iter
->entry_pushed
= 1;
469 play_tree_iter_new(play_tree_t
* pt
,m_config_t
* config
) {
470 play_tree_iter_t
* iter
;
474 assert(config
!= NULL
);
477 if( ! play_tree_is_valid(pt
))
480 iter
= (play_tree_iter_t
*)calloc(1,sizeof(play_tree_iter_t
));
482 mp_msg(MSGT_PLAYTREE
,MSGL_ERR
,"Can't allocate new iterator (%d bytes of memory)\n",sizeof(play_tree_iter_t
));
487 iter
->config
= config
;
490 iter
->loop
= pt
->parent
->loop
;
496 play_tree_iter_free(play_tree_iter_t
* iter
) {
499 assert(iter
!= NULL
);
502 if(iter
->status_stack
) {
504 assert(iter
->stack_size
> 0);
506 free(iter
->status_stack
);
513 play_tree_rnd_step(play_tree_t
* pt
) {
516 play_tree_t
*i
,*head
;
518 // Count how many free choice we have
519 for(i
= pt
; i
->prev
; i
= i
->prev
)
520 if(!(i
->flags
& PLAY_TREE_RND_PLAYED
)) count
++;
522 if(!(i
->flags
& PLAY_TREE_RND_PLAYED
)) count
++;
523 for(i
= pt
->next
; i
; i
= i
->next
)
524 if(!(i
->flags
& PLAY_TREE_RND_PLAYED
)) count
++;
526 if(!count
) return NULL
;
528 r
= (int)((float)(count
) * rand() / (RAND_MAX
+ 1.0));
530 for(i
= head
; i
; i
=i
->next
) {
531 if(!(i
->flags
& PLAY_TREE_RND_PLAYED
)) r
--;
535 mp_msg(MSGT_PLAYTREE
,MSGL_ERR
,"Random stepping error\n");
541 play_tree_iter_step(play_tree_iter_t
* iter
, int d
,int with_nodes
) {
544 if ( !iter
) return PLAY_TREE_ITER_ENTRY
;
545 if ( !iter
->root
) return PLAY_TREE_ITER_ENTRY
;
548 assert(iter
!= NULL
);
549 assert(iter
->root
!= NULL
);
550 //printf("PT : Stepping = %d\n",d);
553 if(iter
->tree
== NULL
) {
554 iter
->tree
= iter
->root
;
555 return play_tree_iter_step(iter
,0,with_nodes
);
558 if(iter
->config
&& iter
->entry_pushed
> 0) {
559 iter
->entry_pushed
= 0;
560 m_config_pop(iter
->config
);
563 if(iter
->tree
->parent
&& (iter
->tree
->parent
->flags
& PLAY_TREE_RND
))
564 iter
->mode
= PLAY_TREE_ITER_RND
;
566 iter
->mode
= PLAY_TREE_ITER_NORMAL
;
569 if(iter
->mode
== PLAY_TREE_ITER_RND
)
570 pt
= play_tree_rnd_step(iter
->tree
);
574 for(i
= d
; i
> 0 && pt
; i
--)
580 for(i
= d
; i
< 0 && pt
; i
++)
586 if(pt
== NULL
) { // No next
588 if (iter
->mode
== PLAY_TREE_ITER_RND
) {
589 if (iter
->root
->loop
== 0)
590 return PLAY_TREE_ITER_END
;
591 play_tree_unset_flag(iter
->root
, PLAY_TREE_RND_PLAYED
, -1);
592 if (iter
->root
->loop
> 0) iter
->root
->loop
--;
594 return play_tree_iter_step(iter
, 0, with_nodes
);
596 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
) ) ) ) {
597 if(d
> 0) { // Go back to the first one
598 for(pt
= iter
->tree
; pt
->prev
!= NULL
; pt
= pt
->prev
)
600 if(iter
->loop
> 0) iter
->loop
--;
601 } else if( d
< 0 ) { // Or the last one
602 for(pt
= iter
->tree
; pt
->next
!= NULL
; pt
= pt
->next
)
604 if(iter
->loop
>= 0 && iter
->loop
< iter
->tree
->parent
->loop
) iter
->loop
++;
607 return play_tree_iter_step(iter
,0,with_nodes
);
610 return play_tree_iter_up_step(iter
,d
,with_nodes
);
614 // Is there any valid childs ?
615 if(pt
->child
&& play_tree_is_valid(pt
->child
)) {
617 if(with_nodes
) { // Stop on the node
618 return PLAY_TREE_ITER_NODE
;
619 } else // Or follow it
620 return play_tree_iter_down_step(iter
,d
,with_nodes
);
623 // Is it a valid enty ?
624 if(! play_tree_is_valid(pt
)) {
625 if(d
== 0) { // Can this happen ? FF: Yes!
626 mp_msg(MSGT_PLAYTREE
,MSGL_ERR
,"What to do now ???? Infinite loop if we continue\n");
627 return PLAY_TREE_ITER_ERROR
;
628 } // Not a valid entry : go to next one
629 return play_tree_iter_step(iter
,d
,with_nodes
);
633 assert(pt
->files
!= NULL
);
638 for(d
= 0 ; iter
->tree
->files
[d
] != NULL
; d
++)
643 play_tree_iter_push_params(iter
);
644 iter
->entry_pushed
= 1;
645 if(iter
->mode
== PLAY_TREE_ITER_RND
)
646 pt
->flags
|= PLAY_TREE_RND_PLAYED
;
649 return PLAY_TREE_ITER_ENTRY
;
654 play_tree_is_valid(play_tree_t
* pt
) {
661 if(pt
->entry_type
!= PLAY_TREE_ENTRY_NODE
) {
663 assert(pt
->child
== NULL
);
667 else if (pt
->child
!= NULL
) {
668 for(iter
= pt
->child
; iter
!= NULL
; iter
= iter
->next
) {
669 if(play_tree_is_valid(iter
))
677 play_tree_iter_up_step(play_tree_iter_t
* iter
, int d
,int with_nodes
) {
680 assert(iter
!= NULL
);
681 assert(iter
->tree
!= NULL
);
682 //printf("PT : Go UP\n");
686 if(iter
->tree
->parent
== iter
->root
->parent
)
687 return PLAY_TREE_ITER_END
;
690 assert(iter
->tree
->parent
!= NULL
);
691 assert(iter
->stack_size
> 0);
692 assert(iter
->status_stack
!= NULL
);
696 iter
->loop
= iter
->status_stack
[iter
->stack_size
];
697 if(iter
->stack_size
> 0)
698 iter
->status_stack
= (int*)realloc(iter
->status_stack
,iter
->stack_size
*sizeof(int));
700 free(iter
->status_stack
);
701 iter
->status_stack
= NULL
;
703 if(iter
->stack_size
> 0 && iter
->status_stack
== NULL
) {
704 mp_msg(MSGT_PLAYTREE
,MSGL_ERR
,"Can't allocate %d bytes of memory\n",iter
->stack_size
*sizeof(char*));
705 return PLAY_TREE_ITER_ERROR
;
707 iter
->tree
= iter
->tree
->parent
;
709 // Pop subtree params
711 m_config_pop(iter
->config
);
712 if(iter
->mode
== PLAY_TREE_ITER_RND
)
713 iter
->tree
->flags
|= PLAY_TREE_RND_PLAYED
;
716 return play_tree_iter_step(iter
,d
,with_nodes
);
720 play_tree_iter_down_step(play_tree_iter_t
* iter
, int d
,int with_nodes
) {
723 assert(iter
->tree
->files
== NULL
);
724 assert(iter
->tree
->child
!= NULL
);
725 assert(iter
->tree
->child
->parent
== iter
->tree
);
726 //printf("PT : Go DOWN\n");
731 // Push subtree params
733 play_tree_iter_push_params(iter
);
736 iter
->status_stack
= (int*)realloc(iter
->status_stack
,iter
->stack_size
*sizeof(int));
737 if(iter
->status_stack
== NULL
) {
738 mp_msg(MSGT_PLAYTREE
,MSGL_ERR
,"Can't allocate %d bytes of memory\n",iter
->stack_size
*sizeof(int));
739 return PLAY_TREE_ITER_ERROR
;
741 iter
->status_stack
[iter
->stack_size
-1] = iter
->loop
;
743 iter
->loop
= iter
->tree
->loop
-1;
745 iter
->tree
= iter
->tree
->child
;
748 for(pt
= iter
->tree
->child
; pt
->next
!= NULL
; pt
= pt
->next
)
753 return play_tree_iter_step(iter
,0,with_nodes
);
757 play_tree_iter_get_file(play_tree_iter_t
* iter
, int d
) {
760 assert(iter
!= NULL
);
761 assert(iter
->tree
->child
== NULL
);
764 if(iter
->tree
->files
== NULL
)
768 assert(iter
->num_files
> 0);
771 if(iter
->file
>= iter
->num_files
-1 || iter
->file
< -1)
775 if(iter
->file
>= iter
->num_files
- 1)
781 iter
->file
= iter
->num_files
- 1;
785 return iter
->tree
->files
[iter
->file
];
789 play_tree_cleanup(play_tree_t
* pt
) {
790 play_tree_t
* iter
, *tmp
, *first
;
796 if( ! play_tree_is_valid(pt
)) {
797 play_tree_remove(pt
,1,1);
803 for(iter
= pt
->child
; iter
!= NULL
; ) {
806 if(! play_tree_is_valid(tmp
)) {
807 play_tree_remove(tmp
,1,1);
808 if(tmp
== first
) first
= iter
;
812 for(iter
= first
; iter
!= NULL
; ) {
815 play_tree_cleanup(tmp
);
823 play_tree_iter_new_copy(play_tree_iter_t
* old
) {
824 play_tree_iter_t
* iter
;
830 iter
= (play_tree_iter_t
*)malloc(sizeof(play_tree_iter_t
));
832 mp_msg(MSGT_PLAYTREE
,MSGL_ERR
,"Can't allocate %d bytes of memory\n",sizeof(play_tree_iter_t
));
836 memcpy(iter
,old
,sizeof(play_tree_iter_t
));
837 if(old
->status_stack
) {
838 iter
->status_stack
= (int*)malloc(old
->stack_size
* sizeof(int));
839 if(iter
->status_stack
== NULL
) {
840 mp_msg(MSGT_PLAYTREE
,MSGL_ERR
,"Can't allocate %d bytes of memory\n",old
->stack_size
* sizeof(int));
844 memcpy(iter
->status_stack
,old
->status_stack
,iter
->stack_size
*sizeof(int));
851 // HIGH Level API, by Fabian Franz (mplayer@fabian-franz.de)
853 play_tree_iter_t
* pt_iter_create(play_tree_t
** ppt
, m_config_t
* config
)
855 play_tree_iter_t
* r
=NULL
;
860 *ppt
=play_tree_cleanup(*ppt
);
863 r
= play_tree_iter_new(*ppt
,config
);
864 if (r
&& play_tree_iter_step(r
,0,0) != PLAY_TREE_ITER_ENTRY
)
866 play_tree_iter_free(r
);
874 void pt_iter_destroy(play_tree_iter_t
** iter
)
883 char* pt_iter_get_file(play_tree_iter_t
* iter
, int d
)
891 r
= play_tree_iter_get_file(iter
,d
);
895 if (play_tree_iter_step(iter
,d
,0) != PLAY_TREE_ITER_ENTRY
)
897 r
=play_tree_iter_get_file(iter
,d
);
904 void pt_iter_insert_entry(play_tree_iter_t
* iter
, play_tree_t
* entry
)
906 play_tree_t
*pt
= iter
->tree
;
913 play_tree_insert_entry(pt
, entry
);
914 play_tree_set_params_from(entry
,pt
);
917 void pt_iter_replace_entry(play_tree_iter_t
* iter
, play_tree_t
* entry
)
919 play_tree_t
*pt
= iter
->tree
;
921 pt_iter_insert_entry(iter
, entry
);
922 play_tree_remove(pt
, 1, 1);
926 //Add a new file as a new entry
927 void pt_add_file(play_tree_t
** ppt
, char* filename
)
929 play_tree_t
*pt
= *ppt
, *entry
= play_tree_new();
934 play_tree_add_file(entry
, filename
);
936 play_tree_append_entry(pt
, entry
);
942 play_tree_set_params_from(entry
,pt
);
945 void pt_add_gui_file(play_tree_t
** ppt
, char* path
, char* file
)
947 char* wholename
= malloc(strlen(path
)+strlen(file
)+2);
951 strcpy(wholename
, path
);
952 strcat(wholename
, "/");
953 strcat(wholename
, file
);
954 pt_add_file(ppt
, wholename
);
955 free(wholename
); // As pt_add_file strdups it anyway!
959 void pt_iter_goto_head(play_tree_iter_t
* iter
)
961 iter
->tree
=iter
->root
;
962 play_tree_iter_step(iter
, 0, 0);