Update to MPlayer SVN rev 30819 and FFmpeg SVN rev 22169.
[vaapi:miks-mplayer.git] / playtree.c
1 /*
2  * This file is part of MPlayer.
3  *
4  * MPlayer is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * MPlayer is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 /// \file
20 /// \ingroup Playtree
21
22 #include "config.h"
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #ifdef MP_DEBUG
29 #include <assert.h>
30 #endif
31 #include "m_config.h"
32 #include "playtree.h"
33 #include "mp_msg.h"
34
35 static int
36 play_tree_is_valid(play_tree_t* pt);
37
38 play_tree_t*
39 play_tree_new(void) {
40   play_tree_t* r = calloc(1,sizeof(play_tree_t));
41   if(r == NULL) {
42     mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",(int)sizeof(play_tree_t));
43     return NULL;
44   }
45   r->entry_type = PLAY_TREE_ENTRY_NODE;
46   return r;
47 }
48
49 void
50 play_tree_free(play_tree_t* pt, int children) {
51   play_tree_t* iter;
52
53 #ifdef MP_DEBUG
54   assert(pt != NULL);
55 #endif
56
57   if(children) {
58     for(iter = pt->child; iter != NULL; ) {
59       play_tree_t* nxt=iter->next;
60       play_tree_free(iter,1);
61       iter = nxt;
62     }
63     pt->child = NULL;
64   }
65
66   play_tree_remove(pt,0,0);
67
68   for(iter = pt->child ; iter != NULL ; iter = iter->next)
69     iter->parent = NULL;
70
71   //if(pt->params) free(pt->params);
72   if(pt->files) {
73     int i;
74     for(i = 0 ; pt->files[i] != NULL ; i++)
75       free(pt->files[i]);
76     free(pt->files);
77   }
78
79   free(pt);
80 }
81
82 void
83 play_tree_free_list(play_tree_t* pt, int children) {
84   play_tree_t* iter;
85
86 #ifdef MP_DEBUG
87   assert(pt != NULL);
88 #endif
89
90   for(iter = pt ; iter->prev != NULL ; iter = iter->prev)
91     /* NOTHING */;
92
93   while(iter) {
94     play_tree_t* nxt = iter->next;
95     play_tree_free(iter, children);
96     iter = nxt;
97   }
98
99
100 }
101
102 void
103 play_tree_append_entry(play_tree_t* pt, play_tree_t* entry) {
104   play_tree_t* iter;
105
106 #ifdef MP_DEBUG
107   assert(pt != NULL);
108   assert(entry != NULL);
109 #endif
110
111   if(pt == entry)
112     return;
113
114   for(iter = pt ; iter->next != NULL ; iter = iter->next)
115     /* NOTHING */;
116
117   entry->parent = iter->parent;
118   entry->prev = iter;
119   entry->next = NULL;
120   iter->next = entry;
121 }
122
123 void
124 play_tree_prepend_entry(play_tree_t* pt, play_tree_t* entry) {
125   play_tree_t* iter;
126
127 #ifdef MP_DEBUG
128   assert(pt != NULL);
129   assert(entry != NULL);
130 #endif
131
132   for(iter = pt ; iter->prev != NULL; iter = iter->prev)
133     /* NOTHING */;
134
135   entry->prev = NULL;
136   entry->next = iter;
137   entry->parent = iter->parent;
138
139   iter->prev = entry;
140   if(entry->parent) {
141 #ifdef MP_DEBUG
142     assert(entry->parent->child == iter);
143 #endif
144     entry->parent->child = entry;
145   }
146 }
147
148 void
149 play_tree_insert_entry(play_tree_t* pt, play_tree_t* entry) {
150
151 #ifdef MP_DEBUG
152   assert(pt != NULL);
153   assert(entry != NULL);
154 #endif
155
156   entry->parent = pt->parent;
157   entry->prev = pt;
158   if(pt->next) {
159 #ifdef MP_DEBUG
160     assert(pt->next->prev == pt);
161 #endif
162     entry->next = pt->next;
163     entry->next->prev = entry;
164   } else
165     entry->next = NULL;
166   pt->next = entry;
167
168 }
169
170 void
171 play_tree_remove(play_tree_t* pt, int free_it, int with_children) {
172
173 #ifdef MP_DEBUG
174   assert(pt != NULL);
175 #endif
176
177   // Middle of list
178   if(pt->prev && pt->next) {
179 #ifdef MP_DEBUG
180     assert(pt->prev->next == pt);
181     assert(pt->next->prev == pt);
182 #endif
183     pt->prev->next = pt->next;
184     pt->next->prev = pt->prev;
185   } // End of list
186   else if(pt->prev) {
187 #ifdef MP_DEBUG
188     assert(pt->prev->next == pt);
189 #endif
190     pt->prev->next = NULL;
191   } // Beginning of list
192   else if(pt->next) {
193 #ifdef MP_DEBUG
194     assert(pt->next->prev == pt);
195 #endif
196     pt->next->prev = NULL;
197     if(pt->parent) {
198 #ifdef MP_DEBUG
199       assert(pt->parent->child == pt);
200 #endif
201       pt->parent->child = pt->next;
202     }
203   } // The only one
204   else if(pt->parent) {
205 #ifdef MP_DEBUG
206     assert(pt->parent->child == pt);
207 #endif
208     pt->parent->child = NULL;
209   }
210
211   pt->prev = pt->next = pt->parent = NULL;
212   if(free_it)
213     play_tree_free(pt,with_children);
214
215 }
216
217 void
218 play_tree_set_child(play_tree_t* pt, play_tree_t* child) {
219   play_tree_t* iter;
220
221 #ifdef MP_DEBUG
222   assert(pt != NULL);
223   assert(pt->entry_type == PLAY_TREE_ENTRY_NODE);
224 #endif
225
226   //DEBUG_FF: Where are the children freed?
227   // Attention in using this function!
228   for(iter = pt->child ; iter != NULL ; iter = iter->next)
229     iter->parent = NULL;
230
231   // Go back to first one
232   for(iter = child ; iter->prev != NULL ; iter = iter->prev)
233     /* NOTHING */;
234
235   pt->child = iter;
236
237   for( ; iter != NULL ; iter= iter->next)
238     iter->parent = pt;
239
240 }
241
242 void
243 play_tree_set_parent(play_tree_t* pt, play_tree_t* parent) {
244   play_tree_t* iter;
245
246 #ifdef MP_DEBUG
247   assert(pt != NULL);
248 #endif
249
250   if(pt->parent)
251     pt->parent->child = NULL;
252
253   for(iter = pt ; iter != NULL ; iter = iter->next)
254     iter->parent = parent;
255
256   if(pt->prev) {
257     for(iter = pt->prev ; iter->prev != NULL ; iter = iter->prev)
258       iter->parent = parent;
259     iter->parent = parent;
260     parent->child = iter;
261   } else
262     parent->child = pt;
263
264 }
265
266
267 void
268 play_tree_add_file(play_tree_t* pt,char* file) {
269   int n = 0;
270   char* e;
271
272 #ifdef MP_DEBUG
273   assert(pt != NULL);
274   assert(pt->child == NULL);
275   assert(file != NULL);
276 #endif
277
278   if(pt->entry_type != PLAY_TREE_ENTRY_NODE &&
279      pt->entry_type != PLAY_TREE_ENTRY_FILE)
280     return;
281
282   if(pt->files) {
283     for(n = 0 ; pt->files[n] != NULL ; n++)
284       /* NOTHING */;
285   }
286   pt->files = realloc(pt->files, (n + 2) * sizeof(char*));
287   if(pt->files ==NULL) {
288     mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",(n+2)*(int)sizeof(char*));
289     return;
290   }
291
292   e = pt->files[n] = strdup(file);
293   pt->files[n+1] = NULL;
294
295   pt->entry_type = PLAY_TREE_ENTRY_FILE;
296
297 }
298
299 int
300 play_tree_remove_file(play_tree_t* pt,char* file) {
301   int n,f = -1;
302
303 #ifdef MP_DEBUG
304   assert(pt != NULL);
305   assert(file != NULL);
306   assert(pt->entry_type != PLAY_TREE_ENTRY_NODE);
307 #endif
308
309   for(n=0 ; pt->files[n] != NULL ; n++) {
310     if(strcmp(file,pt->files[n]) == 0)
311       f = n;
312   }
313
314   if(f < 0) // Not found
315     return 0;
316
317 #ifdef MP_DEBUG
318   assert(n > f);
319 #endif
320
321   free(pt->files[f]);
322
323   if(n > 1) {
324     memmove(&pt->files[f],&pt->files[f+1],(n-f)*sizeof(char*));
325     pt->files = realloc(pt->files, n * sizeof(char*));
326     if(pt->files == NULL) {
327       mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",(n+2)*(int)sizeof(char*));
328       return -1;
329     }
330   } else {
331     free(pt->files);
332     pt->files = NULL;
333   }
334
335   return 1;
336 }
337
338 void
339 play_tree_set_param(play_tree_t* pt, char* name, char* val) {
340   int n = 0;
341
342 #ifdef MP_DEBUG
343   assert(pt != NULL);
344   assert(name != NULL);
345 #endif
346
347   if(pt->params)
348     for ( ; pt->params[n].name != NULL ; n++ ) { }
349
350   pt->params = realloc(pt->params, (n + 2) * sizeof(play_tree_param_t));
351   if(pt->params == NULL) {
352       mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't realloc params (%d bytes of memory)\n",(n+2)*(int)sizeof(play_tree_param_t));
353       return;
354   }
355   pt->params[n].name = strdup(name);
356   pt->params[n].value = val != NULL ? strdup(val) : NULL;
357   memset(&pt->params[n+1],0,sizeof(play_tree_param_t));
358
359   return;
360 }
361
362 int
363 play_tree_unset_param(play_tree_t* pt, char* name) {
364   int n,ni = -1;
365
366 #ifdef MP_DEBUG
367   assert(pt != NULL);
368   assert(name != NULL);
369   assert(pt->params != NULL);
370 #endif
371
372   for(n = 0 ; pt->params[n].name != NULL ; n++) {
373     if(strcasecmp(pt->params[n].name,name) == 0)
374       ni = n;
375   }
376
377   if(ni < 0)
378     return 0;
379
380   if(pt->params[ni].name) free(pt->params[ni].name);
381   if(pt->params[ni].value) free(pt->params[ni].value);
382
383   if(n > 1) {
384     memmove(&pt->params[ni],&pt->params[ni+1],(n-ni)*sizeof(play_tree_param_t));
385     pt->params = realloc(pt->params, n * sizeof(play_tree_param_t));
386     if(pt->params == NULL) {
387       mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",n*(int)sizeof(play_tree_param_t));
388       return -1;
389     }
390   } else {
391     free(pt->params);
392     pt->params = NULL;
393   }
394
395   return 1;
396 }
397
398 void
399 play_tree_set_params_from(play_tree_t* dest,play_tree_t* src) {
400   int i;
401
402 #ifdef MP_DEBUG
403   assert(dest != NULL);
404   assert(src != NULL);
405 #endif
406
407   if(!src->params)
408     return;
409
410   for(i = 0; src->params[i].name != NULL ; i++)
411     play_tree_set_param(dest,src->params[i].name,src->params[i].value);
412   if(src->flags & PLAY_TREE_RND) // pass the random flag too
413     dest->flags |= PLAY_TREE_RND;
414
415 }
416
417 static void
418 play_tree_unset_flag(play_tree_t* pt, int flags , int deep) {
419   play_tree_t*  i;
420
421   pt->flags &= ~flags;
422
423   if(deep && pt->child) {
424     if(deep > 0) deep--;
425     for(i = pt->child ; i ; i = i->next)
426       play_tree_unset_flag(i,flags,deep);
427   }
428 }
429
430
431 //////////////////////////////////// ITERATOR //////////////////////////////////////
432
433 static void
434 play_tree_iter_push_params(play_tree_iter_t* iter) {
435   int n;
436   play_tree_t* pt;
437 #ifdef MP_DEBUG
438   assert(iter != NULL);
439   assert(iter->config != NULL);
440   assert(iter->tree != NULL);
441 #endif
442
443   pt = iter->tree;
444
445   // We always push a config because we can set some option
446   // while playing
447   m_config_push(iter->config);
448
449   if(pt->params == NULL)
450     return;
451
452
453   for(n = 0; pt->params[n].name != NULL ; n++) {
454     int e;
455     if((e = m_config_set_option(iter->config,pt->params[n].name,pt->params[n].value)) < 0) {
456       mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Error %d while setting option '%s' with value '%s'\n",e,
457              pt->params[n].name,pt->params[n].value);
458     }
459   }
460
461   if(!pt->child)
462     iter->entry_pushed = 1;
463   return;
464 }
465
466 play_tree_iter_t*
467 play_tree_iter_new(play_tree_t* pt,m_config_t* config) {
468   play_tree_iter_t* iter;
469
470 #ifdef MP_DEBUG
471   assert(pt != NULL);
472   assert(config != NULL);
473 #endif
474
475   if( ! play_tree_is_valid(pt))
476     return NULL;
477
478   iter = calloc(1,sizeof(play_tree_iter_t));
479   if(! iter) {
480       mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate new iterator (%d bytes of memory)\n",(int)sizeof(play_tree_iter_t));
481       return NULL;
482   }
483   iter->root = pt;
484   iter->tree = NULL;
485   iter->config = config;
486
487   if(pt->parent)
488     iter->loop = pt->parent->loop;
489
490   return iter;
491 }
492
493 void
494 play_tree_iter_free(play_tree_iter_t* iter) {
495
496 #ifdef MP_DEBUG
497   assert(iter != NULL);
498 #endif
499
500   if(iter->status_stack) {
501 #ifdef MP_DEBUG
502     assert(iter->stack_size > 0);
503 #endif
504     free(iter->status_stack);
505   }
506
507   free(iter);
508 }
509
510 static play_tree_t*
511 play_tree_rnd_step(play_tree_t* pt) {
512   int count = 0;
513   int r;
514   play_tree_t *i,*head;
515
516   // Count how many free choice we have
517   for(i = pt ; i->prev ; i = i->prev)
518     if(!(i->flags & PLAY_TREE_RND_PLAYED)) count++;
519   head = i;
520   if(!(i->flags & PLAY_TREE_RND_PLAYED)) count++;
521   for(i = pt->next ; i ; i = i->next)
522     if(!(i->flags & PLAY_TREE_RND_PLAYED)) count++;
523
524   if(!count) return NULL;
525
526   r = (int)((float)(count) * rand() / (RAND_MAX + 1.0));
527
528   for(i = head ; i  ; i=i->next) {
529     if(!(i->flags & PLAY_TREE_RND_PLAYED)) r--;
530     if(r < 0) return i;
531   }
532
533   mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Random stepping error\n");
534   return NULL;
535 }
536
537
538 int
539 play_tree_iter_step(play_tree_iter_t* iter, int d,int with_nodes) {
540   play_tree_t* pt;
541
542   if ( !iter ) return PLAY_TREE_ITER_ENTRY;
543   if ( !iter->root ) return PLAY_TREE_ITER_ENTRY;
544
545 #ifdef MP_DEBUG
546   assert(iter != NULL);
547   assert(iter->root != NULL);
548   //printf("PT : Stepping = %d\n",d);
549 #endif
550
551   if(iter->tree == NULL) {
552     iter->tree = iter->root;
553     return play_tree_iter_step(iter,0,with_nodes);
554   }
555
556   if(iter->config && iter->entry_pushed > 0) {
557     iter->entry_pushed = 0;
558     m_config_pop(iter->config);
559   }
560
561   if(iter->tree->parent && (iter->tree->parent->flags & PLAY_TREE_RND))
562     iter->mode = PLAY_TREE_ITER_RND;
563   else
564     iter->mode = PLAY_TREE_ITER_NORMAL;
565
566   iter->file = -1;
567   if(iter->mode == PLAY_TREE_ITER_RND)
568     pt = play_tree_rnd_step(iter->tree);
569   else if( d > 0 ) {
570     int i;
571     pt = iter->tree;
572     for(i = d ; i > 0 && pt ; i--)
573       pt = pt->next;
574     d = i ? i : 1;
575   } else if(d < 0) {
576     int i;
577     pt = iter->tree;
578     for(i = d ; i < 0 && pt ; i++)
579       pt = pt->prev;
580     d = i ? i : -1;
581   } else
582     pt = iter->tree;
583
584   if(pt == NULL) { // No next
585     // Must we loop?
586     if (iter->mode == PLAY_TREE_ITER_RND) {
587       if (iter->root->loop == 0)
588         return PLAY_TREE_ITER_END;
589       play_tree_unset_flag(iter->root, PLAY_TREE_RND_PLAYED, -1);
590       if (iter->root->loop > 0) iter->root->loop--;
591       // try again
592       return play_tree_iter_step(iter, 0, with_nodes);
593     } else
594     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) ) ) ) {
595       if(d > 0) { // Go back to the first one
596         for(pt = iter->tree ; pt->prev != NULL; pt = pt->prev)
597           /* NOTHNG */;
598         if(iter->loop > 0) iter->loop--;
599       } else if( d < 0 ) { // Or the last one
600         for(pt = iter->tree ; pt->next != NULL; pt = pt->next)
601           /* NOTHNG */;
602         if(iter->loop >= 0 && iter->loop < iter->tree->parent->loop) iter->loop++;
603       }
604       iter->tree = pt;
605       return play_tree_iter_step(iter,0,with_nodes);
606     }
607     // Go up one level
608     return play_tree_iter_up_step(iter,d,with_nodes);
609
610   }
611
612   // Is there any valid child?
613   if(pt->child && play_tree_is_valid(pt->child)) {
614     iter->tree = pt;
615     if(with_nodes) { // Stop on the node
616       return PLAY_TREE_ITER_NODE;
617     } else      // Or follow it
618       return play_tree_iter_down_step(iter,d,with_nodes);
619   }
620
621   // Is it a valid entry?
622   if(! play_tree_is_valid(pt)) {
623     if(d == 0) { // Can this happen ? FF: Yes!
624       mp_msg(MSGT_PLAYTREE,MSGL_ERR,"What to do now ???? Infinite loop if we continue\n");
625       return PLAY_TREE_ITER_ERROR;
626     } // Not a valid entry : go to next one
627     return play_tree_iter_step(iter,d,with_nodes);
628   }
629
630 #ifdef MP_DEBUG
631   assert(pt->files != NULL);
632 #endif
633
634   iter->tree = pt;
635
636   for(d = 0 ; iter->tree->files[d] != NULL ; d++)
637     /* NOTHING */;
638   iter->num_files = d;
639
640   if(iter->config) {
641     play_tree_iter_push_params(iter);
642     iter->entry_pushed = 1;
643     if(iter->mode == PLAY_TREE_ITER_RND)
644       pt->flags |= PLAY_TREE_RND_PLAYED;
645   }
646
647   return PLAY_TREE_ITER_ENTRY;
648
649 }
650
651 static int
652 play_tree_is_valid(play_tree_t* pt) {
653   play_tree_t* iter;
654
655 #ifdef MP_DEBUG
656   assert(pt != NULL);
657 #endif
658
659   if(pt->entry_type != PLAY_TREE_ENTRY_NODE) {
660 #ifdef MP_DEBUG
661     assert(pt->child == NULL);
662 #endif
663     return 1;
664   }
665   else if (pt->child != NULL) {
666     for(iter = pt->child ; iter != NULL ; iter = iter->next) {
667       if(play_tree_is_valid(iter))
668         return 1;
669     }
670   }
671   return 0;
672 }
673
674 int
675 play_tree_iter_up_step(play_tree_iter_t* iter, int d,int with_nodes) {
676
677 #ifdef MP_DEBUG
678   assert(iter != NULL);
679   assert(iter->tree != NULL);
680   //printf("PT : Go UP\n");
681 #endif
682
683   iter->file = -1;
684   if(iter->tree->parent == iter->root->parent)
685     return PLAY_TREE_ITER_END;
686
687 #ifdef MP_DEBUG
688   assert(iter->tree->parent != NULL);
689   assert(iter->stack_size > 0);
690   assert(iter->status_stack != NULL);
691 #endif
692
693   iter->stack_size--;
694   iter->loop = iter->status_stack[iter->stack_size];
695   if(iter->stack_size > 0)
696     iter->status_stack = realloc(iter->status_stack, iter->stack_size * sizeof(int));
697   else {
698     free(iter->status_stack);
699     iter->status_stack = NULL;
700   }
701   if(iter->stack_size > 0 && iter->status_stack == NULL) {
702     mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",iter->stack_size*(int)sizeof(char*));
703     return PLAY_TREE_ITER_ERROR;
704   }
705   iter->tree = iter->tree->parent;
706
707   // Pop subtree params
708   if(iter->config) {
709     m_config_pop(iter->config);
710     if(iter->mode == PLAY_TREE_ITER_RND)
711       iter->tree->flags |= PLAY_TREE_RND_PLAYED;
712   }
713
714   return play_tree_iter_step(iter,d,with_nodes);
715 }
716
717 int
718 play_tree_iter_down_step(play_tree_iter_t* iter, int d,int with_nodes) {
719
720 #ifdef MP_DEBUG
721   assert(iter->tree->files == NULL);
722   assert(iter->tree->child != NULL);
723   assert(iter->tree->child->parent == iter->tree);
724   //printf("PT : Go DOWN\n");
725 #endif
726
727   iter->file = -1;
728
729   //  Push subtree params
730   if(iter->config)
731     play_tree_iter_push_params(iter);
732
733   iter->stack_size++;
734   iter->status_stack = realloc(iter->status_stack, iter->stack_size * sizeof(int));
735   if(iter->status_stack == NULL) {
736     mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",iter->stack_size*(int)sizeof(int));
737     return PLAY_TREE_ITER_ERROR;
738   }
739   iter->status_stack[iter->stack_size-1] = iter->loop;
740   // Set new status
741   iter->loop = iter->tree->loop-1;
742   if(d >= 0)
743     iter->tree = iter->tree->child;
744   else {
745     play_tree_t* pt;
746     for(pt = iter->tree->child ; pt->next != NULL ; pt = pt->next)
747       /*NOTING*/;
748     iter->tree = pt;
749   }
750
751   return play_tree_iter_step(iter,0,with_nodes);
752 }
753
754 char*
755 play_tree_iter_get_file(play_tree_iter_t* iter, int d) {
756 #ifdef MP_DEBUG
757   assert(iter != NULL);
758   assert(iter->tree->child == NULL);
759 #endif
760
761   if(iter->tree->files == NULL)
762     return NULL;
763
764 #ifdef MP_DEBUG
765   assert(iter->num_files > 0);
766 #endif
767
768   if(iter->file >= iter->num_files-1 || iter->file < -1)
769     return NULL;
770
771   if(d > 0) {
772     if(iter->file >= iter->num_files - 1)
773       iter->file = 0;
774     else
775       iter->file++;
776   } else if(d < 0) {
777     if(iter->file <= 0)
778       iter->file = iter->num_files - 1;
779     else
780       iter->file--;
781   }
782   return iter->tree->files[iter->file];
783 }
784
785 play_tree_t*
786 play_tree_cleanup(play_tree_t* pt) {
787   play_tree_t* iter, *tmp, *first;
788
789 #ifdef MP_DEBUG
790   assert(pt != NULL);
791 #endif
792
793   if( ! play_tree_is_valid(pt)) {
794     play_tree_remove(pt,1,1);
795     return NULL;
796   }
797
798   first = pt->child;
799
800   for(iter = pt->child ; iter != NULL ; ) {
801     tmp = iter;
802     iter = iter->next;
803     if(! play_tree_is_valid(tmp)) {
804       play_tree_remove(tmp,1,1);
805       if(tmp == first) first = iter;
806     }
807   }
808
809   for(iter = first ; iter != NULL ; ) {
810     tmp = iter;
811     iter = iter->next;
812     play_tree_cleanup(tmp);
813   }
814
815   return pt;
816
817 }
818
819 play_tree_iter_t*
820 play_tree_iter_new_copy(play_tree_iter_t* old) {
821   play_tree_iter_t* iter;
822
823 #ifdef MP_DEBUG
824   assert(old != NULL);
825 #endif
826
827   iter = malloc(sizeof(play_tree_iter_t));
828   if(iter == NULL) {
829     mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",(int)sizeof(play_tree_iter_t));
830     return NULL;
831   }
832 ;
833   memcpy(iter,old,sizeof(play_tree_iter_t));
834   if(old->status_stack) {
835     iter->status_stack = malloc(old->stack_size * sizeof(int));
836     if(iter->status_stack == NULL) {
837       mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",old->stack_size * (int)sizeof(int));
838       free(iter);
839       return NULL;
840     }
841     memcpy(iter->status_stack,old->status_stack,iter->stack_size*sizeof(int));
842   }
843   iter->config = NULL;
844
845   return iter;
846 }
847
848 // HIGH Level API, by Fabian Franz (mplayer@fabian-franz.de)
849 //
850 play_tree_iter_t* pt_iter_create(play_tree_t** ppt, m_config_t* config)
851 {
852   play_tree_iter_t* r=NULL;
853 #ifdef MP_DEBUG
854   assert(*ppt!=NULL);
855 #endif
856
857   *ppt=play_tree_cleanup(*ppt);
858
859   if(*ppt) {
860     r = play_tree_iter_new(*ppt,config);
861     if (r && play_tree_iter_step(r,0,0) != PLAY_TREE_ITER_ENTRY)
862     {
863       play_tree_iter_free(r);
864       r = NULL;
865     }
866   }
867
868   return r;
869 }
870
871 void pt_iter_destroy(play_tree_iter_t** iter)
872 {
873   if (iter && *iter)
874   {
875     free(*iter);
876     iter=NULL;
877   }
878 }
879
880 char* pt_iter_get_file(play_tree_iter_t* iter, int d)
881 {
882   int i=0;
883   char* r;
884
885   if (iter==NULL)
886     return NULL;
887
888   r = play_tree_iter_get_file(iter,d);
889
890   while (!r && d!=0)
891   {
892     if (play_tree_iter_step(iter,d,0) != PLAY_TREE_ITER_ENTRY)
893         break;
894     r=play_tree_iter_get_file(iter,d);
895     i++;
896   }
897
898   return r;
899 }
900
901 void pt_iter_insert_entry(play_tree_iter_t* iter, play_tree_t* entry)
902 {
903   play_tree_t *pt = iter->tree;
904 #ifdef MP_DEBUG
905   assert(pt!=NULL);
906   assert(entry!=NULL);
907   assert(entry!=pt);
908 #endif
909
910   play_tree_insert_entry(pt, entry);
911   play_tree_set_params_from(entry,pt);
912 }
913
914 void pt_iter_replace_entry(play_tree_iter_t* iter, play_tree_t* entry)
915 {
916   play_tree_t *pt = iter->tree;
917
918   pt_iter_insert_entry(iter, entry);
919   play_tree_remove(pt, 1, 1);
920   iter->tree=entry;
921 }
922
923 //Add a new file as a new entry
924 void pt_add_file(play_tree_t** ppt, char* filename)
925 {
926   play_tree_t *pt = *ppt, *entry = play_tree_new();
927 #ifdef MP_DEBUG
928   assert(entry!=NULL);
929 #endif
930
931   play_tree_add_file(entry, filename);
932   if (pt)
933     play_tree_append_entry(pt, entry);
934   else
935   {
936     pt=entry;
937     *ppt=pt;
938   }
939   play_tree_set_params_from(entry,pt);
940 }
941
942 void pt_add_gui_file(play_tree_t** ppt, char* path, char* file)
943 {
944   char* wholename = malloc(strlen(path)+strlen(file)+2);
945
946   if (wholename)
947   {
948     strcpy(wholename, path);
949     strcat(wholename, "/");
950     strcat(wholename, file);
951     pt_add_file(ppt, wholename);
952     free(wholename); // As pt_add_file strdups it anyway!
953   }
954 }
955
956 void pt_iter_goto_head(play_tree_iter_t* iter)
957 {
958   iter->tree=iter->root;
959   play_tree_iter_step(iter, 0, 0);
960 }