1 /*****************************************************************************
2 * objects.c: vlc_object_t handling
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: objects.c,v 1.3 2002/06/01 18:04:49 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->i_thread );
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 /* If i_type is root, then p_new is our own p_vlc */
210 if( i_type == VLC_OBJECT_ROOT )
212 p_new->p_vlc = (vlc_t*)p_new;
213 p_new->p_vlc->i_counter = 0;
214 p_new->i_object_id = 0;
218 p_new->p_vlc = p_this->p_vlc;
220 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
221 p_new->p_vlc->i_counter++;
222 p_new->i_object_id = p_new->p_vlc->i_counter;
223 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
226 p_new->pp_parents = NULL;
227 p_new->i_parents = 0;
228 p_new->pp_children = NULL;
229 p_new->i_children = 0;
231 //msg_Dbg( p_new, "created object" );
236 /* vlc_object_destroy: initialize a vlc object and set its parent */
237 void __vlc_object_destroy( vlc_object_t *p_this )
239 if( p_this->i_refcount )
241 msg_Err( p_this, "refcount is %i", p_this->i_refcount );
242 vlc_dumpstructure( p_this );
245 if( p_this->i_children )
247 msg_Err( p_this, "object still has children" );
248 vlc_dumpstructure( p_this );
251 if( p_this->i_parents )
253 msg_Err( p_this, "object still has parents" );
254 vlc_dumpstructure( p_this );
257 //msg_Dbg( p_this, "destroyed object" );
262 /* vlc_object_find: find a typed object and increment its refcount */
263 void * __vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode )
265 vlc_object_t *p_found;
267 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
269 /* If we are of the requested type ourselves, don't look further */
270 if( !(i_mode & FIND_STRICT) && p_this->i_object_type == i_type )
272 p_this->i_refcount++;
273 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
277 /* Otherwise, recursively look for the object */
278 p_found = vlc_object_find_inner( p_this, i_type, i_mode );
280 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
285 static vlc_object_t * vlc_object_find_inner( vlc_object_t *p_this,
286 int i_type, int i_mode )
291 switch( i_mode & 0x000f )
294 for( i = p_this->i_parents; i--; )
296 p_tmp = p_this->pp_parents[i];
297 if( p_tmp->i_object_type == i_type )
302 else if( p_tmp->i_parents )
304 p_tmp = vlc_object_find_inner( p_tmp, i_type, i_mode );
314 for( i = p_this->i_children; i--; )
316 p_tmp = p_this->pp_children[i];
317 if( p_tmp->i_object_type == i_type )
322 else if( p_tmp->i_children )
324 p_tmp = vlc_object_find_inner( p_tmp, i_type, i_mode );
334 /* FIXME: unimplemented */
341 /* vlc_object_yield: increment an object refcount */
342 void __vlc_object_yield( vlc_object_t *p_this )
344 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
345 p_this->i_refcount++;
346 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
349 /* vlc_object_release: decrement an object refcount */
350 void __vlc_object_release( vlc_object_t *p_this )
352 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
353 p_this->i_refcount--;
354 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
357 /* vlc_object_unlink: detach object from its parents */
358 void __vlc_object_unlink_all( vlc_object_t *p_this )
360 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
362 /* FIXME: BORK ! BORK ! BORK !!! THIS STUFF IS BORKED !! FIXME */
363 while( p_this->i_parents )
365 /* Not very effective because we know the index, but we'd have to
366 * parse p_parent->pp_children anyway. Plus, we remove duplicates
367 * by not using the object's index */
368 vlc_object_unlink_inner( p_this, p_this->pp_parents[0] );
371 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
374 /* vlc_object_unlink: remove a parent/child link */
375 void __vlc_object_unlink( vlc_object_t *p_this, vlc_object_t *p_parent )
377 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
378 vlc_object_unlink_inner( p_this, p_parent );
379 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
382 static void vlc_object_unlink_inner( vlc_object_t *p_this,
383 vlc_object_t *p_parent )
387 /* Remove all of p_this's parents which are p_parent */
388 for( i_index = p_this->i_parents ; i_index-- ; )
390 if( p_this->pp_parents[i_index] == p_parent )
393 for( i = i_index ; i < p_this->i_parents ; i++ )
395 p_this->pp_parents[i] = p_this->pp_parents[i+1];
400 if( p_this->i_parents )
402 p_this->pp_parents = (vlc_object_t **)realloc( p_this->pp_parents,
403 p_this->i_parents * sizeof(vlc_object_t *) );
407 free( p_this->pp_parents );
408 p_this->pp_parents = NULL;
411 /* Remove all of p_parent's children which are p_this */
412 for( i_index = p_parent->i_children ; i_index-- ; )
414 if( p_parent->pp_children[i_index] == p_this )
416 p_parent->i_children--;
417 for( i = i_index ; i < p_parent->i_children ; i++ )
419 p_parent->pp_children[i] = p_parent->pp_children[i+1];
424 if( p_parent->i_children )
426 p_parent->pp_children = (vlc_object_t **)realloc( p_parent->pp_children,
427 p_parent->i_children * sizeof(vlc_object_t *) );
431 free( p_parent->pp_children );
432 p_parent->pp_children = NULL;
436 /* vlc_object_attach: attach object to a parent object */
437 void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent )
439 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
442 p_this->pp_parents = (vlc_object_t **)realloc( p_this->pp_parents,
443 p_this->i_parents * sizeof(vlc_object_t *) );
444 p_this->pp_parents[p_this->i_parents - 1] = p_parent;
446 p_parent->i_children++;
447 p_parent->pp_children = (vlc_object_t **)realloc( p_parent->pp_children,
448 p_parent->i_children * sizeof(vlc_object_t *) );
449 p_parent->pp_children[p_parent->i_children - 1] = p_this;
451 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
455 /* vlc_object_setchild: attach a child object */
456 void __vlc_object_setchild( vlc_object_t *p_this, vlc_object_t *p_child )
458 vlc_mutex_lock( &p_this->p_vlc->structure_lock );
460 p_this->i_children++;
461 p_this->pp_children = (vlc_object_t **)realloc( p_this->pp_children,
462 p_this->i_children * sizeof(vlc_object_t *) );
463 p_this->pp_children[p_this->i_children - 1] = p_child;
465 p_child->i_parents++;
466 p_child->pp_parents = (vlc_object_t **)realloc( p_child->pp_parents,
467 p_child->i_parents * sizeof(vlc_object_t *) );
468 p_child->pp_parents[p_child->i_parents - 1] = p_this;
470 vlc_mutex_unlock( &p_this->p_vlc->structure_lock );