Mercurial > mplayer.hg
comparison playtree.c @ 4043:25590564842f
tree-based playlist parser code by Alban Bedel <albeu@free.fr>
author | arpi |
---|---|
date | Tue, 08 Jan 2002 01:24:25 +0000 |
parents | |
children | da61596bcd87 |
comparison
equal
deleted
inserted
replaced
4042:d651a7b5d213 | 4043:25590564842f |
---|---|
1 | |
2 #include <stdlib.h> | |
3 #include <string.h> | |
4 #include <stdio.h> | |
5 #include <assert.h> | |
6 #include "playtree.h" | |
7 #include "mp_msg.h" | |
8 | |
9 static int | |
10 play_tree_is_valid(play_tree_t* pt); | |
11 | |
12 play_tree_t* | |
13 play_tree_new(void) { | |
14 play_tree_t* r = (play_tree_t*)calloc(1,sizeof(play_tree_t)); | |
15 if(r == NULL) | |
16 mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",sizeof(play_tree_t)); | |
17 return r; | |
18 } | |
19 | |
20 void | |
21 play_tree_free(play_tree_t* pt, int childs) { | |
22 play_tree_t* iter; | |
23 | |
24 #ifdef DEBUG | |
25 assert(pt != NULL); | |
26 #endif | |
27 | |
28 if(childs) { | |
29 for(iter = pt->child; iter != NULL; iter = iter->next) | |
30 play_tree_free(iter,1); | |
31 pt->child = NULL; | |
32 } | |
33 | |
34 play_tree_remove(pt,0,0); | |
35 | |
36 for(iter = pt->child ; iter != NULL ; iter = iter->next) | |
37 iter->parent = NULL; | |
38 | |
39 //if(pt->params) free(pt->params); | |
40 if(pt->files) { | |
41 int i; | |
42 for(i = 0 ; pt->files[i] != NULL ; i++) | |
43 free(pt->files[i]); | |
44 free(pt->files); | |
45 } | |
46 | |
47 free(pt); | |
48 } | |
49 | |
50 void | |
51 play_tree_free_list(play_tree_t* pt, int childs) { | |
52 play_tree_t* iter; | |
53 | |
54 #ifdef DEBUG | |
55 assert(pt != NULL); | |
56 #endif | |
57 | |
58 for(iter = pt ; iter->prev != NULL ; iter = iter->prev) | |
59 /* NOTHING */; | |
60 | |
61 for( ; iter != NULL ; iter = iter->next) | |
62 play_tree_free(iter,childs); | |
63 | |
64 | |
65 } | |
66 | |
67 void | |
68 play_tree_append_entry(play_tree_t* pt, play_tree_t* entry) { | |
69 play_tree_t* iter; | |
70 | |
71 #ifdef DEBUG | |
72 assert(pt != NULL); | |
73 assert(entry != NULL); | |
74 #endif | |
75 | |
76 if(pt == entry) | |
77 return; | |
78 | |
79 for(iter = pt ; iter->next != NULL ; iter = iter->next) | |
80 /* NOTHING */; | |
81 | |
82 entry->parent = iter->parent; | |
83 entry->prev = iter; | |
84 entry->next = NULL; | |
85 iter->next = entry; | |
86 } | |
87 | |
88 void | |
89 play_tree_prepend_entry(play_tree_t* pt, play_tree_t* entry) { | |
90 play_tree_t* iter; | |
91 | |
92 #ifdef DEBUG | |
93 assert(pt != NULL); | |
94 assert(entry != NULL); | |
95 #endif | |
96 | |
97 for(iter = pt ; iter->prev != NULL; iter = iter->prev) | |
98 /* NOTHING */; | |
99 | |
100 entry->prev = NULL; | |
101 entry->next = iter; | |
102 entry->parent = iter->parent; | |
103 | |
104 iter->prev = entry; | |
105 if(entry->parent) { | |
106 #ifdef DEBUG | |
107 assert(entry->parent->child == iter); | |
108 #endif | |
109 entry->parent->child = entry; | |
110 } | |
111 } | |
112 | |
113 void | |
114 play_tree_insert_entry(play_tree_t* pt, play_tree_t* entry) { | |
115 | |
116 #ifdef DEBUG | |
117 assert(pt != NULL); | |
118 assert(entry != NULL); | |
119 #endif | |
120 | |
121 entry->parent = pt->parent; | |
122 entry->prev = pt; | |
123 if(pt->next) { | |
124 #ifdef DEBUG | |
125 assert(pt->next->prev == pt); | |
126 #endif | |
127 entry->next = pt->next; | |
128 entry->next->prev = entry; | |
129 } else | |
130 entry->next = NULL; | |
131 pt->next = entry; | |
132 | |
133 } | |
134 | |
135 void | |
136 play_tree_remove(play_tree_t* pt, int free_it,int with_childs) { | |
137 | |
138 #ifdef DEBUG | |
139 assert(pt != NULL); | |
140 #endif | |
141 | |
142 // Middle of list | |
143 if(pt->prev && pt->next) { | |
144 #ifdef DEBUG | |
145 assert(pt->prev->next == pt); | |
146 assert(pt->next->prev == pt); | |
147 #endif | |
148 pt->prev->next = pt->next; | |
149 pt->next->prev = pt->prev; | |
150 } // End of list | |
151 else if(pt->prev) { | |
152 #ifdef DEBUG | |
153 assert(pt->prev->next == pt); | |
154 #endif | |
155 pt->prev->next = NULL; | |
156 } // Begining of list | |
157 else if(pt->next) { | |
158 #ifdef DEBUG | |
159 assert(pt->next->prev == pt); | |
160 #endif | |
161 pt->next->prev = NULL; | |
162 if(pt->parent) { | |
163 #ifdef DEBUG | |
164 assert(pt->parent->child == pt); | |
165 #endif | |
166 pt->parent->child = pt->next; | |
167 } | |
168 } // The only one | |
169 else if(pt->parent) { | |
170 #ifdef DEBUG | |
171 assert(pt->parent->child == pt); | |
172 #endif | |
173 pt->parent->child = NULL; | |
174 } | |
175 | |
176 pt->prev = pt->next = pt->parent = NULL; | |
177 if(free_it) | |
178 play_tree_free(pt,with_childs); | |
179 | |
180 } | |
181 | |
182 void | |
183 play_tree_set_child(play_tree_t* pt, play_tree_t* child) { | |
184 play_tree_t* iter; | |
185 | |
186 #ifdef DEBUG | |
187 assert(pt != NULL); | |
188 assert(pt->files == NULL); | |
189 #endif | |
190 | |
191 for(iter = pt->child ; iter != NULL ; iter = iter->next) | |
192 iter->parent = NULL; | |
193 | |
194 // Go back to first one | |
195 for(iter = child ; iter->prev != NULL ; iter = iter->prev) | |
196 /* NOTHING */; | |
197 | |
198 pt->child = iter; | |
199 | |
200 for( ; iter != NULL ; iter= iter->next) | |
201 iter->parent = pt; | |
202 | |
203 } | |
204 | |
205 void | |
206 play_tree_set_parent(play_tree_t* pt, play_tree_t* parent) { | |
207 play_tree_t* iter; | |
208 | |
209 #ifdef DEBUG | |
210 assert(pt != NULL); | |
211 #endif | |
212 | |
213 if(pt->parent) | |
214 pt->parent->child = NULL; | |
215 | |
216 for(iter = pt ; iter != NULL ; iter = iter->next) | |
217 iter->parent = parent; | |
218 | |
219 if(pt->prev) { | |
220 for(iter = pt->prev ; iter->prev != NULL ; iter = iter->prev) | |
221 iter->parent = parent; | |
222 iter->parent = parent; | |
223 parent->child = iter; | |
224 } else | |
225 parent->child = pt; | |
226 | |
227 } | |
228 | |
229 | |
230 void | |
231 play_tree_add_file(play_tree_t* pt,char* file) { | |
232 int n = 0; | |
233 | |
234 #ifdef DEBUG | |
235 assert(pt != NULL); | |
236 assert(pt->child == NULL); | |
237 assert(file != NULL); | |
238 #endif | |
239 | |
240 if(pt->files) { | |
241 for(n = 0 ; pt->files[n] != NULL ; n++) | |
242 /* NOTHING */; | |
243 } | |
244 pt->files = (char**)realloc(pt->files,(n+2)*sizeof(char*)); | |
245 if(pt->files ==NULL) { | |
246 mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",(n+2)*sizeof(char*)); | |
247 return; | |
248 } | |
249 | |
250 pt->files[n] = strdup(file); | |
251 pt->files[n+1] = NULL; | |
252 | |
253 } | |
254 | |
255 int | |
256 play_tree_remove_file(play_tree_t* pt,char* file) { | |
257 int n,f = -1; | |
258 | |
259 #ifdef DEBUG | |
260 assert(pt != NULL); | |
261 assert(file != NULL); | |
262 assert(pt->files != NULL); | |
263 #endif | |
264 | |
265 for(n=0 ; pt->files[n] != NULL ; n++) { | |
266 if(strcmp(file,pt->files[n]) == 0) | |
267 f = n; | |
268 } | |
269 | |
270 if(f < 0) // Not found | |
271 return 0; | |
272 | |
273 #ifdef DEBUG | |
274 assert(n > f); | |
275 #endif | |
276 | |
277 free(pt->files[f]); | |
278 | |
279 if(n > 1) { | |
280 memmove(&pt->files[f],&pt->files[f+1],(n-f)*sizeof(char*)); | |
281 pt->files = (char**)realloc(pt->files,n*sizeof(char*)); | |
282 if(pt->files == NULL) { | |
283 mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",(n+2)*sizeof(char*)); | |
284 return -1; | |
285 } | |
286 } else { | |
287 free(pt->files); | |
288 pt->files = NULL; | |
289 } | |
290 | |
291 return 1; | |
292 } | |
293 | |
294 #if 0 | |
295 void | |
296 play_tree_set_param(play_tree_t* pt, char* name, char* val) { | |
297 int n = 0,ni = -1; | |
298 | |
299 #ifdef DEBUG | |
300 assert(pt != NULL); | |
301 assert(name != NULL); | |
302 #endif | |
303 | |
304 if(pt->params) { | |
305 for( ; pt->params[n].name != NULL ; n++) { | |
306 if(strcasecmp(pt->params[n].name,name) == 0) | |
307 ni = n; | |
308 } | |
309 } | |
310 | |
311 if(ni > 0) { | |
312 if(pt->params[n].value != NULL) free(pt->params[n].value); | |
313 pt->params[n].value = val; | |
314 return; | |
315 } | |
316 | |
317 pt->params = (play_tree_param_t*)realloc(pt->params,(n+2)*sizeof(play_tree_param_t)); | |
318 pt->params[n].name = strdup(name); | |
319 pt->params[n].value = val != NULL ? strdup(val) : NULL; | |
320 memset(&pt->params[n+1],0,sizeof(play_tree_param_t)); | |
321 | |
322 return; | |
323 } | |
324 | |
325 int | |
326 play_tree_unset_param(play_tree_t* pt, char* name) { | |
327 int n,ni = 0; | |
328 | |
329 #ifdef DEBUG | |
330 assert(pt != NULL); | |
331 assert(name != NULL); | |
332 assert(pt->params != NULL); | |
333 #endif | |
334 | |
335 for(n = 0 ; pt->params[n].name != NULL ; n++) { | |
336 if(strcasecmp(pt->params[n].name,name) == 0) | |
337 ni = n; | |
338 } | |
339 | |
340 if(ni < 0) | |
341 return 0; | |
342 | |
343 if(n > 1) { | |
344 memmove(&pt->params[ni],&pt->params[ni+1],(n-ni)*sizeof(play_tree_param_t)); | |
345 pt->params = (play_tree_param_t*)realloc(pt->params,n*sizeof(play_tree_param_t)); | |
346 assert(pt->params != NULL); | |
347 } else { | |
348 free(pt->params); | |
349 pt->params = NULL; | |
350 } | |
351 | |
352 return 1; | |
353 } | |
354 | |
355 #endif | |
356 | |
357 play_tree_iter_t* | |
358 play_tree_iter_new(play_tree_t* pt) { | |
359 play_tree_iter_t* iter; | |
360 | |
361 #ifdef DEBUG | |
362 assert(pt != NULL); | |
363 #endif | |
364 | |
365 if( ! play_tree_is_valid(pt)) | |
366 return NULL; | |
367 | |
368 iter = (play_tree_iter_t*)calloc(1,sizeof(play_tree_iter_t)); | |
369 if(! iter) return NULL; | |
370 iter->root = pt; | |
371 iter->tree = NULL; | |
372 | |
373 if(pt->parent) | |
374 iter->loop = pt->parent->loop; | |
375 | |
376 return iter; | |
377 } | |
378 | |
379 void | |
380 play_tree_iter_free(play_tree_iter_t* iter) { | |
381 | |
382 #ifdef DEBUG | |
383 assert(iter != NULL); | |
384 #endif | |
385 | |
386 if(iter->status_stack) { | |
387 #ifdef DEBUG | |
388 assert(iter->stack_size > 0); | |
389 #endif | |
390 free(iter->status_stack); | |
391 } | |
392 | |
393 free(iter); | |
394 } | |
395 | |
396 int | |
397 play_tree_iter_step(play_tree_iter_t* iter, int d,int with_nodes) { | |
398 play_tree_t* pt; | |
399 | |
400 #ifdef DEBUG | |
401 assert(iter != NULL); | |
402 assert(iter->root != NULL); | |
403 #endif | |
404 | |
405 if(iter->tree == NULL) { | |
406 iter->tree = iter->root; | |
407 return play_tree_iter_step(iter,0,with_nodes); | |
408 } | |
409 | |
410 iter->file = 0; | |
411 if( d > 0 ) | |
412 pt = iter->tree->next; | |
413 else if(d < 0) | |
414 pt = iter->tree->prev; | |
415 else | |
416 pt = iter->tree; | |
417 | |
418 if(pt == NULL) { // No next | |
419 // Must we loop? | |
420 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) ) ) ) { | |
421 if(d > 0) { // Go back to the first one | |
422 for(pt = iter->tree ; pt->prev != NULL; pt = pt->prev) | |
423 /* NOTHNG */; | |
424 if(iter->loop > 0) iter->loop--; | |
425 } else if( d < 0 ) { // Or the last one | |
426 for(pt = iter->tree ; pt->next != NULL; pt = pt->next) | |
427 /* NOTHNG */; | |
428 if(iter->loop >= 0 && iter->loop < iter->tree->parent->loop) iter->loop++; | |
429 } | |
430 iter->tree = pt; | |
431 return play_tree_iter_step(iter,0,with_nodes); | |
432 } | |
433 // Go up one level | |
434 return play_tree_iter_up_step(iter,d,with_nodes); | |
435 | |
436 } | |
437 | |
438 // Is there any valid childs ? | |
439 if(pt->child && play_tree_is_valid(pt->child)) { | |
440 iter->tree = pt; | |
441 if(with_nodes) { // Stop on the node | |
442 return PLAY_TREE_ITER_NODE; | |
443 } else // Or follow it | |
444 return play_tree_iter_down_step(iter,d,with_nodes); | |
445 } | |
446 | |
447 // Is it a valid enty ? | |
448 if(! play_tree_is_valid(pt)) { | |
449 if(d == 0) { // Can this happen ? | |
450 mp_msg(MSGT_PLAYTREE,MSGL_ERR,"What to do now ???? Infinite loop if we continue\n"); | |
451 return PLAY_TREE_ITER_ERROR; | |
452 } // Not a valid entry : go to next one | |
453 return play_tree_iter_step(iter,d,with_nodes); | |
454 } | |
455 | |
456 #ifdef DEBUG | |
457 assert(iter->tree->files != NULL); | |
458 #endif | |
459 | |
460 iter->tree = pt; | |
461 for(d = 0 ; iter->tree->files[d] != NULL ; d++) | |
462 /* NOTHING */; | |
463 iter->num_files = d; | |
464 | |
465 return PLAY_TREE_ITER_ENTRY; | |
466 | |
467 } | |
468 | |
469 static int | |
470 play_tree_is_valid(play_tree_t* pt) { | |
471 play_tree_t* iter; | |
472 | |
473 #ifdef DEBUG | |
474 assert(pt != NULL); | |
475 #endif | |
476 | |
477 if(pt->files != NULL) | |
478 return 1; | |
479 else if (pt->child != NULL) { | |
480 for(iter = pt->child ; iter != NULL ; iter = iter->next) { | |
481 if(play_tree_is_valid(iter)) | |
482 return 1; | |
483 } | |
484 } | |
485 return 0; | |
486 } | |
487 | |
488 int | |
489 play_tree_iter_up_step(play_tree_iter_t* iter, int d,int with_nodes) { | |
490 | |
491 #ifdef DEBUG | |
492 assert(iter != NULL); | |
493 assert(iter->tree != NULL); | |
494 #endif | |
495 | |
496 iter->file = 0; | |
497 if(iter->tree->parent == iter->root->parent) | |
498 return PLAY_TREE_ITER_END; | |
499 | |
500 #ifdef DEBUG | |
501 assert(iter->tree->parent != NULL); | |
502 assert(iter->stack_size > 0); | |
503 assert(iter->status_stack != NULL); | |
504 #endif | |
505 | |
506 // Pop status | |
507 iter->stack_size--; | |
508 iter->loop = iter->status_stack[iter->stack_size]; | |
509 iter->status_stack = (int*)realloc(iter->status_stack,iter->stack_size*sizeof(int)); | |
510 if(iter->stack_size > 0 && iter->status_stack == NULL) { | |
511 mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",iter->stack_size*sizeof(char*)); | |
512 return PLAY_TREE_ITER_ERROR; | |
513 } | |
514 iter->tree = iter->tree->parent; | |
515 return play_tree_iter_step(iter,d,with_nodes); | |
516 } | |
517 | |
518 int | |
519 play_tree_iter_down_step(play_tree_iter_t* iter, int d,int with_nodes) { | |
520 | |
521 #ifdef DEBUG | |
522 assert(iter->tree->files == NULL); | |
523 assert(iter->tree->child != NULL); | |
524 assert(iter->tree->child->parent == iter->tree); | |
525 #endif | |
526 | |
527 iter->file = 0; | |
528 // Push status | |
529 iter->stack_size++; | |
530 iter->status_stack = (int*)realloc(iter->status_stack,iter->stack_size*sizeof(int)); | |
531 if(iter->status_stack == NULL) { | |
532 mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",iter->stack_size*sizeof(int)); | |
533 return PLAY_TREE_ITER_ERROR; | |
534 } | |
535 iter->status_stack[iter->stack_size-1] = iter->loop; | |
536 // Set new status | |
537 iter->loop = iter->tree->loop-1; | |
538 if(d >= 0) | |
539 iter->tree = iter->tree->child; | |
540 else { | |
541 play_tree_t* pt; | |
542 for(pt = iter->tree->child ; pt->next != NULL ; pt = pt->next) | |
543 /*NOTING*/; | |
544 iter->tree = pt; | |
545 } | |
546 return play_tree_iter_step(iter,0,with_nodes); | |
547 } | |
548 | |
549 char* | |
550 play_tree_iter_get_file(play_tree_iter_t* iter, int d) { | |
551 | |
552 #ifdef DEBUG | |
553 assert(iter != NULL); | |
554 assert(iter->tree->child == NULL); | |
555 #endif | |
556 | |
557 if(iter->tree->files == NULL) | |
558 return NULL; | |
559 | |
560 if(d > 0) { | |
561 if(iter->tree->files[iter->file] == NULL) | |
562 return NULL; | |
563 iter->file++; | |
564 } else if(d < 0) { | |
565 if(iter->file == 0) | |
566 return NULL; | |
567 iter->file--; | |
568 } | |
569 return iter->tree->files[iter->file-1]; | |
570 } | |
571 | |
572 play_tree_t* | |
573 play_tree_cleanup(play_tree_t* pt) { | |
574 play_tree_t* iter, *tmp, *first; | |
575 | |
576 #ifdef DEBUG | |
577 assert(pt != NULL); | |
578 #endif | |
579 | |
580 if( ! play_tree_is_valid(pt)) { | |
581 play_tree_remove(pt,1,1); | |
582 return NULL; | |
583 } | |
584 | |
585 first = pt->child; | |
586 | |
587 for(iter = pt->child ; iter != NULL ; ) { | |
588 tmp = iter; | |
589 iter = iter->next; | |
590 if(! play_tree_is_valid(tmp)) { | |
591 play_tree_remove(tmp,1,1); | |
592 if(tmp == first) first = iter; | |
593 } | |
594 } | |
595 | |
596 for(iter = first ; iter != NULL ; ) { | |
597 tmp = iter; | |
598 iter = iter->next; | |
599 play_tree_cleanup(tmp); | |
600 } | |
601 | |
602 return pt; | |
603 | |
604 } | |
605 | |
606 play_tree_iter_t* | |
607 play_tree_iter_new_copy(play_tree_iter_t* old) { | |
608 play_tree_iter_t* iter; | |
609 | |
610 #ifdef DEBUG | |
611 assert(old != NULL); | |
612 #endif | |
613 | |
614 iter = (play_tree_iter_t*)malloc(sizeof(play_tree_iter_t)); | |
615 if(iter == NULL) { | |
616 mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",sizeof(play_tree_iter_t)); | |
617 return NULL; | |
618 } | |
619 ; | |
620 memcpy(iter,old,sizeof(play_tree_iter_t)); | |
621 if(old->status_stack) { | |
622 iter->status_stack = (int*)malloc(old->stack_size * sizeof(int)); | |
623 if(iter->status_stack == NULL) { | |
624 mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",old->stack_size * sizeof(int)); | |
625 free(iter); | |
626 return NULL; | |
627 } | |
628 memcpy(iter->status_stack,old->status_stack,iter->stack_size*sizeof(int)); | |
629 } | |
630 return iter; | |
631 } |