1 /*****************************************************************************
2 * objects.c: vlc_object_t handling
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: objects.c,v 1.2 2002/06/01 13:52:24 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 *****************************************************************************/
27 # include <stdlib.h> /* realloc() */
30 #include "stream_control.h"
31 #include "input_ext-intf.h"
32 #include "input_ext-dec.h"
35 #include "video_output.h"
37 #include "vdec_ext-plugins.h"
39 #include "audio_output.h"
42 #include "interface.h"
44 static void vlc_dumpstructure_inner( vlc_object_t *, int, char * );
45 static vlc_object_t * vlc_object_find_inner( vlc_object_t *, int, int );
46 static void vlc_object_unlink_inner( vlc_object_t *, vlc_object_t * );
48 #define MAX_TREE_DEPTH 100
50 void __vlc_dumpstructure( vlc_object_t *p_this )
52 char psz_foo[2 * MAX_TREE_DEPTH + 1];
54 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
56 vlc_dumpstructure_inner( p_this, 0, psz_foo );
57 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
60 static void vlc_dumpstructure_inner( vlc_object_t *p_this,
61 int i_level, char *psz_foo )
64 char i_back = psz_foo[i_level];
65 char psz_children[20], psz_refcount[20], psz_thread[20], psz_name[50];
68 if( p_this->psz_object_name )
70 snprintf( psz_name, 50, " \"%s\"", p_this->psz_object_name );
75 psz_children[0] = '\0';
76 switch( p_this->i_children )
81 strcpy( psz_children, ", 1 child" );
84 snprintf( psz_children, 20, ", %i children", p_this->i_children );
85 psz_children[19] = '\0';
89 psz_refcount[0] = '\0';
90 if( p_this->i_refcount )
92 snprintf( psz_refcount, 20, ", refcount %i", p_this->i_refcount );
93 psz_refcount[19] = '\0';
97 if( p_this->b_thread )
99 snprintf( psz_thread, 20, " (thread %d)", p_this->thread_id );
100 psz_thread[19] = '\0';
103 psz_foo[i_level] = '\0';
104 msg_Info( p_this, "%so %s %p%s%s%s%s", psz_foo, p_this->psz_object_type,
105 p_this, psz_name, psz_thread, psz_refcount, psz_children );
106 psz_foo[i_level] = i_back;
108 if( i_level / 2 >= MAX_TREE_DEPTH )
110 msg_Warn( p_this, "structure tree is too deep" );
114 for( i = 0 ; i < p_this->i_children ; i++ )
118 psz_foo[i_level-1] = ' ';
120 if( psz_foo[i_level-2] == '`' )
122 psz_foo[i_level-2] = ' ';
126 if( i == p_this->i_children - 1 )
128 psz_foo[i_level] = '`';
132 psz_foo[i_level] = '|';
135 psz_foo[i_level+1] = '-';
136 psz_foo[i_level+2] = '\0';
138 vlc_dumpstructure_inner( p_this->pp_children[i], i_level + 2, psz_foo );
142 /* vlc_object_create: initialize a vlc object */
143 void * __vlc_object_create( vlc_object_t *p_this, int i_type )
145 vlc_object_t * p_new;
151 case VLC_OBJECT_ROOT:
152 i_size = sizeof(vlc_t);
155 case VLC_OBJECT_MODULE:
156 i_size = sizeof(module_t);
159 case VLC_OBJECT_INTF:
160 i_size = sizeof(intf_thread_t);
161 psz_type = "interface";
163 case VLC_OBJECT_PLAYLIST:
164 i_size = sizeof(playlist_t);
165 psz_type = "playlist";
167 case VLC_OBJECT_INPUT:
168 i_size = sizeof(input_thread_t);
171 case VLC_OBJECT_DECODER:
172 i_size = sizeof(decoder_fifo_t);
173 psz_type = "decoder";
175 case VLC_OBJECT_VOUT:
176 i_size = sizeof(vout_thread_t);
177 psz_type = "video output";
179 case VLC_OBJECT_AOUT:
180 i_size = sizeof(aout_thread_t);
181 psz_type = "audio output";
184 i_size = i_type > sizeof(vlc_object_t)
185 ? i_type : sizeof(vlc_object_t);
186 i_type = VLC_OBJECT_PRIVATE;
187 psz_type = "private";
191 p_new = malloc( i_size );
198 memset( p_new, 0, i_size );
200 p_new->i_object_type = i_type;
201 p_new->psz_object_type = psz_type;
203 p_new->psz_object_name = NULL;
205 p_new->i_refcount = 0;
209 p_new->p_this = p_new;
211 /* If i_type is root, then p_new is our own p_vlc */
212 if( i_type == VLC_OBJECT_ROOT )
214 p_new->p_vlc = (vlc_t*)p_new;
215 p_new->p_vlc->i_counter = 0;
216 p_new->i_object_id = 0;
220 p_new->p_vlc = p_this->p_vlc;
222 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
223 p_new->p_vlc->i_counter++;
224 p_new->i_object_id = p_new->p_vlc->i_counter;
225 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
228 p_new->pp_parents = NULL;
229 p_new->i_parents = 0;
230 p_new->pp_children = NULL;
231 p_new->i_children = 0;
233 //msg_Dbg( p_new, "created object" );
238 /* vlc_object_destroy: initialize a vlc object and set its parent */
239 void __vlc_object_destroy( vlc_object_t *p_this )
241 if( p_this->i_refcount )
243 msg_Err( p_this, "refcount is %i", p_this->i_refcount );
244 vlc_dumpstructure( p_this );
247 if( p_this->i_children )
249 msg_Err( p_this, "object still has children" );
250 vlc_dumpstructure( p_this );
253 if( p_this->i_parents )
255 msg_Err( p_this, "object still has parents" );
256 vlc_dumpstructure( p_this );
259 //msg_Dbg( p_this, "destroyed object" );
264 /* vlc_object_find: find a typed object and increment its refcount */
265 void * __vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode )
267 vlc_object_t *p_found;
269 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
271 /* If we are of the requested type ourselves, don't look further */
272 if( !(i_mode & FIND_STRICT) && p_this->i_object_type == i_type )
274 p_this->i_refcount++;
275 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
279 /* Otherwise, recursively look for the object */
280 p_found = vlc_object_find_inner( p_this, i_type, i_mode );
282 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
287 static vlc_object_t * vlc_object_find_inner( vlc_object_t *p_this,
288 int i_type, int i_mode )
293 switch( i_mode & 0x000f )
296 for( i = p_this->i_parents; i--; )
298 p_tmp = p_this->pp_parents[i];
299 if( p_tmp->i_object_type == i_type )
304 else if( p_tmp->i_parents )
306 p_tmp = vlc_object_find_inner( p_tmp, i_type, i_mode );
316 for( i = p_this->i_children; i--; )
318 p_tmp = p_this->pp_children[i];
319 if( p_tmp->i_object_type == i_type )
324 else if( p_tmp->i_children )
326 p_tmp = vlc_object_find_inner( p_tmp, i_type, i_mode );
336 /* FIXME: unimplemented */
343 /* vlc_object_yield: increment an object refcount */
344 void __vlc_object_yield( vlc_object_t *p_this )
346 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
347 p_this->i_refcount++;
348 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
351 /* vlc_object_release: decrement an object refcount */
352 void __vlc_object_release( vlc_object_t *p_this )
354 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
355 p_this->i_refcount--;
356 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
359 /* vlc_object_unlink: detach object from its parents */
360 void __vlc_object_unlink_all( vlc_object_t *p_this )
362 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
364 /* FIXME: BORK ! BORK ! BORK !!! THIS STUFF IS BORKED !! FIXME */
365 while( p_this->i_parents )
367 /* Not very effective because we know the index, but we'd have to
368 * parse p_parent->pp_children anyway. Plus, we remove duplicates
369 * by not using the object's index */
370 vlc_object_unlink_inner( p_this, p_this->pp_parents[0] );
373 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
376 /* vlc_object_unlink: remove a parent/child link */
377 void __vlc_object_unlink( vlc_object_t *p_this, vlc_object_t *p_parent )
379 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
380 vlc_object_unlink_inner( p_this, p_parent );
381 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
384 static void vlc_object_unlink_inner( vlc_object_t *p_this,
385 vlc_object_t *p_parent )
389 /* Remove all of p_this's parents which are p_parent */
390 for( i_index = p_this->i_parents ; i_index-- ; )
392 if( p_this->pp_parents[i_index] == p_parent )
395 for( i = i_index ; i < p_this->i_parents ; i++ )
397 p_this->pp_parents[i] = p_this->pp_parents[i+1];
402 if( p_this->i_parents )
404 p_this->pp_parents = (vlc_object_t **)realloc( p_this->pp_parents,
405 p_this->i_parents * sizeof(vlc_object_t *) );
409 free( p_this->pp_parents );
410 p_this->pp_parents = NULL;
413 /* Remove all of p_parent's children which are p_this */
414 for( i_index = p_parent->i_children ; i_index-- ; )
416 if( p_parent->pp_children[i_index] == p_this )
418 p_parent->i_children--;
419 for( i = i_index ; i < p_parent->i_children ; i++ )
421 p_parent->pp_children[i] = p_parent->pp_children[i+1];
426 if( p_parent->i_children )
428 p_parent->pp_children = (vlc_object_t **)realloc( p_parent->pp_children,
429 p_parent->i_children * sizeof(vlc_object_t *) );
433 free( p_parent->pp_children );
434 p_parent->pp_children = NULL;
438 /* vlc_object_attach: attach object to a parent object */
439 void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent )
441 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
444 p_this->pp_parents = (vlc_object_t **)realloc( p_this->pp_parents,
445 p_this->i_parents * sizeof(vlc_object_t *) );
446 p_this->pp_parents[p_this->i_parents - 1] = p_parent;
448 p_parent->i_children++;
449 p_parent->pp_children = (vlc_object_t **)realloc( p_parent->pp_children,
450 p_parent->i_children * sizeof(vlc_object_t *) );
451 p_parent->pp_children[p_parent->i_children - 1] = p_this;
453 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
457 /* vlc_object_setchild: attach a child object */
458 void __vlc_object_setchild( vlc_object_t *p_this, vlc_object_t *p_child )
460 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
462 p_this->i_children++;
463 p_this->pp_children = (vlc_object_t **)realloc( p_this->pp_children,
464 p_this->i_children * sizeof(vlc_object_t *) );
465 p_this->pp_children[p_this->i_children - 1] = p_child;
467 p_child->i_parents++;
468 p_child->pp_parents = (vlc_object_t **)realloc( p_child->pp_parents,
469 p_child->i_parents * sizeof(vlc_object_t *) );
470 p_child->pp_parents[p_child->i_parents - 1] = p_this;
472 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );