1 /*****************************************************************************
2 * objects.c: vlc_object_t handling
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: objects.c,v 1.37 2003/06/26 12:19:59 sam Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
30 # include <stdlib.h> /* realloc() */
33 #include "stream_control.h"
34 #include "input_ext-intf.h"
35 #include "input_ext-dec.h"
37 #include "vlc_video.h"
38 #include "video_output.h"
40 #include "audio_output.h"
41 #include "aout_internal.h"
42 #include "stream_output.h"
44 #include "vlc_playlist.h"
45 #include "vlc_interface.h"
48 /*****************************************************************************
50 *****************************************************************************/
51 static int DumpCommand( vlc_object_t
*, char const *,
52 vlc_value_t
, vlc_value_t
, void * );
54 static vlc_object_t
* FindObject ( vlc_object_t
*, int, int );
55 static void DetachObject ( vlc_object_t
* );
56 static void PrintObject ( vlc_object_t
*, const char * );
57 static void DumpStructure ( vlc_object_t
*, int, char * );
58 static int FindIndex ( vlc_object_t
*, vlc_object_t
**, int );
59 static void SetAttachment ( vlc_object_t
*, vlc_bool_t
);
61 static vlc_list_t
* NewList ( int );
62 static void ListReplace ( vlc_list_t
*, vlc_object_t
*, int );
63 static void ListAppend ( vlc_list_t
*, vlc_object_t
* );
64 static int CountChildren ( vlc_object_t
*, int );
65 static void ListChildren ( vlc_list_t
*, vlc_object_t
*, int );
67 /*****************************************************************************
68 * Local structure lock
69 *****************************************************************************/
70 static vlc_mutex_t structure_lock
;
72 /*****************************************************************************
73 * vlc_object_create: initialize a vlc object
74 *****************************************************************************
75 * This function allocates memory for a vlc object and initializes it. If
76 * i_type is not a known value such as VLC_OBJECT_ROOT, VLC_OBJECT_VOUT and
77 * so on, vlc_object_create will use its value for the object size.
78 *****************************************************************************/
79 void * __vlc_object_create( vlc_object_t
*p_this
, int i_type
)
88 i_size
= sizeof(libvlc_t
);
92 i_size
= sizeof(vlc_t
);
95 case VLC_OBJECT_MODULE
:
96 i_size
= sizeof(module_t
);
100 i_size
= sizeof(intf_thread_t
);
101 psz_type
= "interface";
103 case VLC_OBJECT_PLAYLIST
:
104 i_size
= sizeof(playlist_t
);
105 psz_type
= "playlist";
107 case VLC_OBJECT_INPUT
:
108 i_size
= sizeof(input_thread_t
);
111 case VLC_OBJECT_DECODER
:
112 i_size
= sizeof(decoder_fifo_t
);
113 psz_type
= "decoder";
115 case VLC_OBJECT_VOUT
:
116 i_size
= sizeof(vout_thread_t
);
117 psz_type
= "video output";
119 case VLC_OBJECT_AOUT
:
120 i_size
= sizeof(aout_instance_t
);
121 psz_type
= "audio output";
123 case VLC_OBJECT_SOUT
:
124 i_size
= sizeof(sout_instance_t
);
125 psz_type
= "stream output";
127 case VLC_OBJECT_HTTPD
:
128 i_size
= sizeof( httpd_t
);
129 psz_type
= "http daemon";
133 ? i_type
> (int)sizeof(vlc_object_t
)
134 ? i_type
: (int)sizeof(vlc_object_t
)
135 : (int)sizeof(vlc_object_t
);
136 i_type
= VLC_OBJECT_GENERIC
;
137 psz_type
= "generic";
141 if( i_type
== VLC_OBJECT_ROOT
)
147 p_new
= malloc( i_size
);
154 memset( p_new
, 0, i_size
);
157 p_new
->i_object_type
= i_type
;
158 p_new
->psz_object_type
= psz_type
;
160 p_new
->psz_object_name
= NULL
;
162 p_new
->b_die
= VLC_FALSE
;
163 p_new
->b_error
= VLC_FALSE
;
164 p_new
->b_dead
= VLC_FALSE
;
165 p_new
->b_attached
= VLC_FALSE
;
168 p_new
->p_vars
= (variable_t
*)malloc( 16 * sizeof( variable_t
) );
176 if( i_type
== VLC_OBJECT_ROOT
)
178 /* If i_type is root, then p_new is actually p_libvlc */
179 p_new
->p_libvlc
= (libvlc_t
*)p_new
;
182 p_new
->p_libvlc
->i_counter
= 0;
183 p_new
->i_object_id
= 0;
185 p_new
->p_libvlc
->i_objects
= 1;
186 p_new
->p_libvlc
->pp_objects
= malloc( sizeof(vlc_object_t
*) );
187 p_new
->p_libvlc
->pp_objects
[0] = p_new
;
188 p_new
->b_attached
= VLC_TRUE
;
192 p_new
->p_libvlc
= p_this
->p_libvlc
;
193 p_new
->p_vlc
= ( i_type
== VLC_OBJECT_VLC
) ? (vlc_t
*)p_new
196 vlc_mutex_lock( &structure_lock
);
198 p_new
->p_libvlc
->i_counter
++;
199 p_new
->i_object_id
= p_new
->p_libvlc
->i_counter
;
201 /* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's
202 * useless to try and recover anything if pp_objects gets smashed. */
203 INSERT_ELEM( p_new
->p_libvlc
->pp_objects
,
204 p_new
->p_libvlc
->i_objects
,
205 p_new
->p_libvlc
->i_objects
,
208 vlc_mutex_unlock( &structure_lock
);
211 p_new
->i_refcount
= 0;
212 p_new
->p_parent
= NULL
;
213 p_new
->pp_children
= NULL
;
214 p_new
->i_children
= 0;
216 p_new
->p_private
= NULL
;
218 /* Initialize mutexes and condvars */
219 vlc_mutex_init( p_new
, &p_new
->object_lock
);
220 vlc_cond_init( p_new
, &p_new
->object_wait
);
221 vlc_mutex_init( p_new
, &p_new
->var_lock
);
223 if( i_type
== VLC_OBJECT_ROOT
)
225 vlc_mutex_init( p_new
, &structure_lock
);
227 var_Create( p_new
, "list", VLC_VAR_STRING
| VLC_VAR_ISCOMMAND
);
228 var_AddCallback( p_new
, "list", DumpCommand
, NULL
);
229 var_Create( p_new
, "tree", VLC_VAR_STRING
| VLC_VAR_ISCOMMAND
);
230 var_AddCallback( p_new
, "tree", DumpCommand
, NULL
);
236 /*****************************************************************************
237 * vlc_object_destroy: destroy a vlc object
238 *****************************************************************************
239 * This function destroys an object that has been previously allocated with
240 * vlc_object_create. The object's refcount must be zero and it must not be
241 * attached to other objects in any way.
242 *****************************************************************************/
243 void __vlc_object_destroy( vlc_object_t
*p_this
)
247 if( p_this
->i_children
)
249 msg_Err( p_this
, "cannot delete object with children" );
253 if( p_this
->p_parent
)
255 msg_Err( p_this
, "cannot delete object with a parent" );
259 while( p_this
->i_refcount
)
263 /* Don't warn immediately ... 100ms seems OK */
266 msg_Warn( p_this
, "refcount is %i, delaying before deletion",
267 p_this
->i_refcount
);
269 else if( i_delay
== 12 )
271 msg_Err( p_this
, "refcount is %i, I have a bad feeling about this",
272 p_this
->i_refcount
);
274 else if( i_delay
== 42 )
276 msg_Err( p_this
, "we waited too long, cancelling destruction" );
283 /* Destroy the associated variables, starting from the end so that
284 * no memmove calls have to be done. */
285 while( p_this
->i_vars
)
287 var_Destroy( p_this
, p_this
->p_vars
[p_this
->i_vars
- 1].psz_name
);
290 free( p_this
->p_vars
);
291 vlc_mutex_destroy( &p_this
->var_lock
);
293 if( p_this
->i_object_type
== VLC_OBJECT_ROOT
)
295 /* We are the root object ... no need to lock. */
296 free( p_this
->p_libvlc
->pp_objects
);
297 p_this
->p_libvlc
->pp_objects
= NULL
;
298 p_this
->p_libvlc
->i_objects
--;
300 vlc_mutex_destroy( &structure_lock
);
306 vlc_mutex_lock( &structure_lock
);
308 /* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's
309 * useless to try and recover anything if pp_objects gets smashed. */
310 i_index
= FindIndex( p_this
, p_this
->p_libvlc
->pp_objects
,
311 p_this
->p_libvlc
->i_objects
);
312 REMOVE_ELEM( p_this
->p_libvlc
->pp_objects
,
313 p_this
->p_libvlc
->i_objects
, i_index
);
315 vlc_mutex_unlock( &structure_lock
);
318 vlc_mutex_destroy( &p_this
->object_lock
);
319 vlc_cond_destroy( &p_this
->object_wait
);
324 /*****************************************************************************
325 * vlc_object_get: find an object given its ID
326 *****************************************************************************
327 * This function looks for the object whose i_object_id field is i_id. We
328 * use a dichotomy so that lookups are in log2(n).
329 *****************************************************************************/
330 void * __vlc_object_get( vlc_object_t
*p_this
, int i_id
)
333 vlc_object_t
**pp_objects
;
335 vlc_mutex_lock( &structure_lock
);
337 pp_objects
= p_this
->p_libvlc
->pp_objects
;
339 /* Perform our dichotomy */
340 for( i_max
= p_this
->p_libvlc
->i_objects
- 1 ; ; )
342 i_middle
= i_max
/ 2;
344 if( pp_objects
[i_middle
]->i_object_id
> i_id
)
348 else if( pp_objects
[i_middle
]->i_object_id
< i_id
)
352 pp_objects
+= i_middle
;
357 /* This happens when there are only two remaining objects */
358 if( pp_objects
[i_middle
+1]->i_object_id
== i_id
)
360 vlc_mutex_unlock( &structure_lock
);
361 pp_objects
[i_middle
+1]->i_refcount
++;
362 return pp_objects
[i_middle
+1];
369 vlc_mutex_unlock( &structure_lock
);
370 pp_objects
[i_middle
]->i_refcount
++;
371 return pp_objects
[i_middle
];
376 /* this means that i_max == i_middle, and since we have already
377 * tested pp_objects[i_middle]), p_found is properly set. */
382 vlc_mutex_unlock( &structure_lock
);
386 /*****************************************************************************
387 * vlc_object_find: find a typed object and increment its refcount
388 *****************************************************************************
389 * This function recursively looks for a given object type. i_mode can be one
390 * of FIND_PARENT, FIND_CHILD or FIND_ANYWHERE.
391 *****************************************************************************/
392 void * __vlc_object_find( vlc_object_t
*p_this
, int i_type
, int i_mode
)
394 vlc_object_t
*p_found
;
396 vlc_mutex_lock( &structure_lock
);
398 /* If we are of the requested type ourselves, don't look further */
399 if( !(i_mode
& FIND_STRICT
) && p_this
->i_object_type
== i_type
)
401 p_this
->i_refcount
++;
402 vlc_mutex_unlock( &structure_lock
);
406 /* Otherwise, recursively look for the object */
407 if( (i_mode
& 0x000f) == FIND_ANYWHERE
)
409 p_found
= FindObject( VLC_OBJECT(p_this
->p_vlc
), i_type
,
410 (i_mode
& ~0x000f) | FIND_CHILD
);
414 p_found
= FindObject( p_this
, i_type
, i_mode
);
417 vlc_mutex_unlock( &structure_lock
);
422 /*****************************************************************************
423 * vlc_object_yield: increment an object refcount
424 *****************************************************************************/
425 void __vlc_object_yield( vlc_object_t
*p_this
)
427 vlc_mutex_lock( &structure_lock
);
428 p_this
->i_refcount
++;
429 vlc_mutex_unlock( &structure_lock
);
432 /*****************************************************************************
433 * vlc_object_release: decrement an object refcount
434 *****************************************************************************/
435 void __vlc_object_release( vlc_object_t
*p_this
)
437 vlc_mutex_lock( &structure_lock
);
438 p_this
->i_refcount
--;
439 vlc_mutex_unlock( &structure_lock
);
442 /*****************************************************************************
443 * vlc_object_attach: attach object to a parent object
444 *****************************************************************************
445 * This function sets p_this as a child of p_parent, and p_parent as a parent
446 * of p_this. This link can be undone using vlc_object_detach.
447 *****************************************************************************/
448 void __vlc_object_attach( vlc_object_t
*p_this
, vlc_object_t
*p_parent
)
450 vlc_mutex_lock( &structure_lock
);
452 /* Attach the parent to its child */
453 p_this
->p_parent
= p_parent
;
455 /* Attach the child to its parent */
456 INSERT_ELEM( p_parent
->pp_children
, p_parent
->i_children
,
457 p_parent
->i_children
, p_this
);
459 /* Climb up the tree to see whether we are connected with the root */
460 if( p_parent
->b_attached
)
462 SetAttachment( p_this
, VLC_TRUE
);
465 vlc_mutex_unlock( &structure_lock
);
468 /*****************************************************************************
469 * vlc_object_detach: detach object from its parent
470 *****************************************************************************
471 * This function removes all links between an object and its parent.
472 *****************************************************************************/
473 void __vlc_object_detach( vlc_object_t
*p_this
)
475 vlc_mutex_lock( &structure_lock
);
476 if( !p_this
->p_parent
)
478 msg_Err( p_this
, "object is not attached" );
479 vlc_mutex_unlock( &structure_lock
);
483 /* Climb up the tree to see whether we are connected with the root */
484 if( p_this
->p_parent
->b_attached
)
486 SetAttachment( p_this
, VLC_FALSE
);
489 DetachObject( p_this
);
490 vlc_mutex_unlock( &structure_lock
);
493 /*****************************************************************************
494 * vlc_list_find: find a list typed objects and increment their refcount
495 *****************************************************************************
496 * This function recursively looks for a given object type. i_mode can be one
497 * of FIND_PARENT, FIND_CHILD or FIND_ANYWHERE.
498 *****************************************************************************/
499 vlc_list_t
* __vlc_list_find( vlc_object_t
*p_this
, int i_type
, int i_mode
)
502 vlc_object_t
**pp_current
, **pp_end
;
503 int i_count
= 0, i_index
= 0;
505 vlc_mutex_lock( &structure_lock
);
507 /* Look for the objects */
508 switch( i_mode
& 0x000f )
511 pp_current
= p_this
->p_libvlc
->pp_objects
;
512 pp_end
= pp_current
+ p_this
->p_libvlc
->i_objects
;
514 for( ; pp_current
< pp_end
; pp_current
++ )
516 if( (*pp_current
)->b_attached
517 && (*pp_current
)->i_object_type
== i_type
)
523 p_list
= NewList( i_count
);
524 pp_current
= p_this
->p_libvlc
->pp_objects
;
526 for( ; pp_current
< pp_end
; pp_current
++ )
528 if( (*pp_current
)->b_attached
529 && (*pp_current
)->i_object_type
== i_type
)
531 ListReplace( p_list
, *pp_current
, i_index
);
532 if( i_index
< i_count
) i_index
++;
538 i_count
= CountChildren( p_this
, i_type
);
539 p_list
= NewList( i_count
);
541 /* Check allocation was successful */
542 if( p_list
->i_count
!= i_count
)
544 msg_Err( p_this
, "list allocation failed!" );
550 ListChildren( p_list
, p_this
, i_type
);
554 msg_Err( p_this
, "unimplemented!" );
555 p_list
= NewList( 0 );
559 vlc_mutex_unlock( &structure_lock
);
564 /*****************************************************************************
565 * DumpCommand: print the current vlc structure
566 *****************************************************************************
567 * This function prints either an ASCII tree showing the connections between
568 * vlc objects, and additional information such as their refcount, thread ID,
569 * etc. (command "tree"), or the same data as a simple list (command "list").
570 *****************************************************************************/
571 static int DumpCommand( vlc_object_t
*p_this
, char const *psz_cmd
,
572 vlc_value_t oldval
, vlc_value_t newval
, void *p_data
)
574 if( *psz_cmd
== 't' )
576 char psz_foo
[2 * MAX_DUMPSTRUCTURE_DEPTH
+ 1];
577 vlc_object_t
*p_object
;
579 if( *newval
.psz_string
)
581 p_object
= vlc_object_get( p_this
, atoi(newval
.psz_string
) );
590 p_object
= p_this
->p_vlc
? VLC_OBJECT(p_this
->p_vlc
) : p_this
;
593 vlc_mutex_lock( &structure_lock
);
596 DumpStructure( p_object
, 0, psz_foo
);
598 vlc_mutex_unlock( &structure_lock
);
600 if( *newval
.psz_string
)
602 vlc_object_release( p_this
);
605 else if( *psz_cmd
== 'l' )
607 vlc_object_t
**pp_current
, **pp_end
;
609 vlc_mutex_lock( &structure_lock
);
611 pp_current
= p_this
->p_libvlc
->pp_objects
;
612 pp_end
= pp_current
+ p_this
->p_libvlc
->i_objects
;
614 for( ; pp_current
< pp_end
; pp_current
++ )
616 if( (*pp_current
)->b_attached
)
618 PrintObject( *pp_current
, "" );
622 printf( " o %.8i %s (not attached)\n",
623 (*pp_current
)->i_object_id
,
624 (*pp_current
)->psz_object_type
);
628 vlc_mutex_unlock( &structure_lock
);
634 /*****************************************************************************
635 * vlc_list_release: free a list previously allocated by vlc_list_find
636 *****************************************************************************
637 * This function decreases the refcount of all objects in the list and
639 *****************************************************************************/
640 void vlc_list_release( vlc_list_t
*p_list
)
644 for( i_index
= 0; i_index
< p_list
->i_count
; i_index
++ )
646 vlc_mutex_lock( &structure_lock
);
648 p_list
->p_values
[i_index
].p_object
->i_refcount
--;
650 vlc_mutex_unlock( &structure_lock
);
653 free( p_list
->p_values
);
657 /* Following functions are local */
659 /*****************************************************************************
660 * FindIndex: find the index of an object in an array of objects
661 *****************************************************************************
662 * This function assumes that p_this can be found in pp_objects. It will not
663 * crash if p_this cannot be found, but will return a wrong value. It is your
664 * duty to check the return value if you are not certain that the object could
666 *****************************************************************************/
667 static int FindIndex( vlc_object_t
*p_this
,
668 vlc_object_t
**pp_objects
, int i_count
)
670 int i_middle
= i_count
/ 2;
677 if( pp_objects
[i_middle
] == p_this
)
687 /* We take advantage of the sorted array */
688 if( pp_objects
[i_middle
]->i_object_id
< p_this
->i_object_id
)
690 return i_middle
+ FindIndex( p_this
, pp_objects
+ i_middle
,
691 i_count
- i_middle
);
695 return FindIndex( p_this
, pp_objects
, i_middle
);
699 static vlc_object_t
* FindObject( vlc_object_t
*p_this
, int i_type
, int i_mode
)
704 switch( i_mode
& 0x000f )
707 p_tmp
= p_this
->p_parent
;
710 if( p_tmp
->i_object_type
== i_type
)
717 return FindObject( p_tmp
, i_type
, i_mode
);
723 for( i
= p_this
->i_children
; i
--; )
725 p_tmp
= p_this
->pp_children
[i
];
726 if( p_tmp
->i_object_type
== i_type
)
731 else if( p_tmp
->i_children
)
733 p_tmp
= FindObject( p_tmp
, i_type
, i_mode
);
743 /* Handled in vlc_object_find */
750 static void DetachObject( vlc_object_t
*p_this
)
752 vlc_object_t
*p_parent
= p_this
->p_parent
;
755 /* Remove p_this's parent */
756 p_this
->p_parent
= NULL
;
758 /* Remove all of p_parent's children which are p_this */
759 for( i_index
= p_parent
->i_children
; i_index
-- ; )
761 if( p_parent
->pp_children
[i_index
] == p_this
)
763 p_parent
->i_children
--;
764 for( i
= i_index
; i
< p_parent
->i_children
; i
++ )
766 p_parent
->pp_children
[i
] = p_parent
->pp_children
[i
+1];
771 if( p_parent
->i_children
)
773 p_parent
->pp_children
= (vlc_object_t
**)realloc( p_parent
->pp_children
,
774 p_parent
->i_children
* sizeof(vlc_object_t
*) );
778 free( p_parent
->pp_children
);
779 p_parent
->pp_children
= NULL
;
783 /*****************************************************************************
784 * SetAttachment: recursively set the b_attached flag of a subtree.
785 *****************************************************************************
786 * This function is used by the attach and detach functions to propagate
787 * the b_attached flag in a subtree.
788 *****************************************************************************/
789 static void SetAttachment( vlc_object_t
*p_this
, vlc_bool_t b_attached
)
793 for( i_index
= p_this
->i_children
; i_index
-- ; )
795 SetAttachment( p_this
->pp_children
[i_index
], b_attached
);
798 p_this
->b_attached
= b_attached
;
801 static void PrintObject( vlc_object_t
*p_this
, const char *psz_prefix
)
803 char psz_children
[20], psz_refcount
[20], psz_thread
[20], psz_name
[50];
806 if( p_this
->psz_object_name
)
808 snprintf( psz_name
, 50, " \"%s\"", p_this
->psz_object_name
);
813 psz_children
[0] = '\0';
814 switch( p_this
->i_children
)
819 strcpy( psz_children
, ", 1 child" );
822 snprintf( psz_children
, 20,
823 ", %i children", p_this
->i_children
);
824 psz_children
[19] = '\0';
828 psz_refcount
[0] = '\0';
829 if( p_this
->i_refcount
)
831 snprintf( psz_refcount
, 20, ", refcount %i", p_this
->i_refcount
);
832 psz_refcount
[19] = '\0';
835 psz_thread
[0] = '\0';
836 if( p_this
->b_thread
)
838 snprintf( psz_thread
, 20, " (thread %d)", (int)p_this
->thread_id
);
839 psz_thread
[19] = '\0';
842 printf( " %so %.8i %s%s%s%s%s\n", psz_prefix
,
843 p_this
->i_object_id
, p_this
->psz_object_type
,
844 psz_name
, psz_thread
, psz_refcount
, psz_children
);
847 static void DumpStructure( vlc_object_t
*p_this
, int i_level
, char *psz_foo
)
850 char i_back
= psz_foo
[i_level
];
851 psz_foo
[i_level
] = '\0';
853 PrintObject( p_this
, psz_foo
);
855 psz_foo
[i_level
] = i_back
;
857 if( i_level
/ 2 >= MAX_DUMPSTRUCTURE_DEPTH
)
859 msg_Warn( p_this
, "structure tree is too deep" );
863 for( i
= 0 ; i
< p_this
->i_children
; i
++ )
867 psz_foo
[i_level
-1] = ' ';
869 if( psz_foo
[i_level
-2] == '`' )
871 psz_foo
[i_level
-2] = ' ';
875 if( i
== p_this
->i_children
- 1 )
877 psz_foo
[i_level
] = '`';
881 psz_foo
[i_level
] = '|';
884 psz_foo
[i_level
+1] = '-';
885 psz_foo
[i_level
+2] = '\0';
887 DumpStructure( p_this
->pp_children
[i
], i_level
+ 2, psz_foo
);
891 static vlc_list_t
* NewList( int i_count
)
893 vlc_list_t
* p_list
= (vlc_list_t
*)malloc( sizeof( vlc_list_t
) );
899 p_list
->i_count
= i_count
;
903 p_list
->p_values
= NULL
;
907 p_list
->p_values
= malloc( i_count
* sizeof( vlc_value_t
) );
908 if( p_list
->p_values
== NULL
)
917 static void ListReplace( vlc_list_t
*p_list
, vlc_object_t
*p_object
,
920 if( p_list
== NULL
|| i_index
>= p_list
->i_count
)
925 p_object
->i_refcount
++;
927 p_list
->p_values
[i_index
].p_object
= p_object
;
932 static void ListAppend( vlc_list_t
*p_list
, vlc_object_t
*p_object
)
939 p_list
->p_values
= realloc( p_list
->p_values
, (p_list
->i_count
+ 1)
940 * sizeof( vlc_value_t
) );
941 if( p_list
->p_values
== NULL
)
947 p_object
->i_refcount
++;
949 p_list
->p_values
[p_list
->i_count
].p_object
= p_object
;
955 static int CountChildren( vlc_object_t
*p_this
, int i_type
)
960 for( i
= 0; i
< p_this
->i_children
; i
++ )
962 p_tmp
= p_this
->pp_children
[i
];
964 if( p_tmp
->i_object_type
== i_type
)
969 if( p_tmp
->i_children
)
971 i_count
+= CountChildren( p_tmp
, i_type
);
978 static void ListChildren( vlc_list_t
*p_list
, vlc_object_t
*p_this
, int i_type
)
983 for( i
= 0; i
< p_this
->i_children
; i
++ )
985 p_tmp
= p_this
->pp_children
[i
];
987 if( p_tmp
->i_object_type
== i_type
)
989 ListReplace( p_list
, p_tmp
, p_list
->i_count
++ );
992 if( p_tmp
->i_children
)
994 ListChildren( p_list
, p_tmp
, i_type
);