]> git.sesse.net Git - vlc/blob - src/misc/objects.c
* ./src/misc/beos_specific.cpp: the BeOS BApplication thread now uses the
[vlc] / src / misc / objects.c
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 $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *
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.
13  * 
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.
18  *
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  *****************************************************************************/
23
24 #include <vlc/vlc.h>
25
26 #ifdef HAVE_STDLIB_H
27 #   include <stdlib.h>                                          /* realloc() */
28 #endif
29
30 #include "stream_control.h"
31 #include "input_ext-intf.h"
32 #include "input_ext-dec.h"
33
34 #include "video.h"
35 #include "video_output.h"
36
37 #include "vdec_ext-plugins.h"
38
39 #include "audio_output.h"
40
41 #include "playlist.h"
42 #include "interface.h"
43
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 * );
47
48 #define MAX_TREE_DEPTH 100
49
50 void __vlc_dumpstructure( vlc_object_t *p_this )
51 {
52     char psz_foo[2 * MAX_TREE_DEPTH + 1];
53
54     vlc_mutex_lock( &p_this->p_vlc->structure_lock );
55     psz_foo[0] = '|';
56     vlc_dumpstructure_inner( p_this, 0, psz_foo );
57     vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
58 }
59
60 static void vlc_dumpstructure_inner( vlc_object_t *p_this,
61                                      int i_level, char *psz_foo )
62 {
63     int i;
64     char i_back = psz_foo[i_level];
65     char psz_children[20], psz_refcount[20], psz_thread[20], psz_name[50];
66
67     psz_name[0] = '\0';
68     if( p_this->psz_object_name )
69     {
70         snprintf( psz_name, 50, " \"%s\"", p_this->psz_object_name );
71         psz_name[48] = '\"';
72         psz_name[49] = '\0';
73     }
74
75     psz_children[0] = '\0';
76     switch( p_this->i_children )
77     {
78         case 0:
79             break;
80         case 1:
81             strcpy( psz_children, ", 1 child" );
82             break;
83         default:
84             snprintf( psz_children, 20, ", %i children", p_this->i_children );
85             psz_children[19] = '\0';
86             break;
87     }
88
89     psz_refcount[0] = '\0';
90     if( p_this->i_refcount )
91     {
92         snprintf( psz_refcount, 20, ", refcount %i", p_this->i_refcount );
93         psz_refcount[19] = '\0';
94     }
95
96     psz_thread[0] = '\0';
97     if( p_this->b_thread )
98     {
99         snprintf( psz_thread, 20, " (thread %d)", p_this->thread_id );
100         psz_thread[19] = '\0';
101     }
102
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;
107
108     if( i_level / 2 >= MAX_TREE_DEPTH )
109     {
110         msg_Warn( p_this, "structure tree is too deep" );
111         return;
112     }
113
114     for( i = 0 ; i < p_this->i_children ; i++ )
115     {
116         if( i_level )
117         {
118             psz_foo[i_level-1] = ' ';
119
120             if( psz_foo[i_level-2] == '`' )
121             {
122                 psz_foo[i_level-2] = ' ';
123             }
124         }
125
126         if( i == p_this->i_children - 1 )
127         {
128             psz_foo[i_level] = '`';
129         }
130         else
131         {
132             psz_foo[i_level] = '|';
133         }
134
135         psz_foo[i_level+1] = '-';
136         psz_foo[i_level+2] = '\0';
137
138         vlc_dumpstructure_inner( p_this->pp_children[i], i_level + 2, psz_foo );
139     }
140 }
141
142 /* vlc_object_create: initialize a vlc object */
143 void * __vlc_object_create( vlc_object_t *p_this, int i_type )
144 {
145     vlc_object_t * p_new;
146     char *         psz_type;
147     size_t         i_size;
148
149     switch( i_type )
150     {
151         case VLC_OBJECT_ROOT:
152             i_size = sizeof(vlc_t);
153             psz_type = "root";
154             break;
155         case VLC_OBJECT_MODULE:
156             i_size = sizeof(module_t);
157             psz_type = "module";
158             break;
159         case VLC_OBJECT_INTF:
160             i_size = sizeof(intf_thread_t);
161             psz_type = "interface";
162             break;
163         case VLC_OBJECT_PLAYLIST:
164             i_size = sizeof(playlist_t);
165             psz_type = "playlist";
166             break;
167         case VLC_OBJECT_INPUT:
168             i_size = sizeof(input_thread_t);
169             psz_type = "input";
170             break;
171         case VLC_OBJECT_DECODER:
172             i_size = sizeof(decoder_fifo_t);
173             psz_type = "decoder";
174             break;
175         case VLC_OBJECT_VOUT:
176             i_size = sizeof(vout_thread_t);
177             psz_type = "video output";
178             break;
179         case VLC_OBJECT_AOUT:
180             i_size = sizeof(aout_thread_t);
181             psz_type = "audio output";
182             break;
183         default:
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";
188             break;
189     }
190
191     p_new = malloc( i_size );
192
193     if( !p_new )
194     {
195         return NULL;
196     }
197
198     memset( p_new, 0, i_size );
199
200     p_new->i_object_type = i_type;
201     p_new->psz_object_type = psz_type;
202
203     p_new->psz_object_name = NULL;
204
205     p_new->i_refcount = 0;
206     p_new->b_die = 0;
207     p_new->b_error = 0;
208
209     p_new->p_this = p_new;
210
211     /* If i_type is root, then p_new is our own p_vlc */
212     if( i_type == VLC_OBJECT_ROOT )
213     {
214         p_new->p_vlc = (vlc_t*)p_new;
215         p_new->p_vlc->i_counter = 0;
216         p_new->i_object_id = 0;
217     }
218     else
219     {
220         p_new->p_vlc = p_this->p_vlc;
221
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 );
226     }
227
228     p_new->pp_parents = NULL;
229     p_new->i_parents = 0;
230     p_new->pp_children = NULL;
231     p_new->i_children = 0;
232
233     //msg_Dbg( p_new, "created object" );
234
235     return p_new;
236 }
237
238 /* vlc_object_destroy: initialize a vlc object and set its parent */
239 void __vlc_object_destroy( vlc_object_t *p_this )
240 {
241     if( p_this->i_refcount )
242     {
243         msg_Err( p_this, "refcount is %i", p_this->i_refcount );
244         vlc_dumpstructure( p_this );
245     }
246
247     if( p_this->i_children )
248     {
249         msg_Err( p_this, "object still has children" );
250         vlc_dumpstructure( p_this );
251     }
252
253     if( p_this->i_parents )
254     {
255         msg_Err( p_this, "object still has parents" );
256         vlc_dumpstructure( p_this );
257     }
258
259     //msg_Dbg( p_this, "destroyed object" );
260
261     free( p_this );
262 }
263
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 )
266 {
267     vlc_object_t *p_found;
268
269     vlc_mutex_lock( &p_this->p_vlc->structure_lock );
270
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 )
273     {
274         p_this->i_refcount++;
275         vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
276         return p_this;
277     }
278
279     /* Otherwise, recursively look for the object */
280     p_found = vlc_object_find_inner( p_this, i_type, i_mode );
281
282     vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
283
284     return p_found;
285 }
286
287 static vlc_object_t * vlc_object_find_inner( vlc_object_t *p_this,
288                                              int i_type, int i_mode )
289 {
290     int i;
291     vlc_object_t *p_tmp;
292
293     switch( i_mode & 0x000f )
294     {
295     case FIND_PARENT:
296         for( i = p_this->i_parents; i--; )
297         {
298             p_tmp = p_this->pp_parents[i];
299             if( p_tmp->i_object_type == i_type )
300             {
301                 p_tmp->i_refcount++;
302                 return p_tmp;
303             }
304             else if( p_tmp->i_parents )
305             {
306                 p_tmp = vlc_object_find_inner( p_tmp, i_type, i_mode );
307                 if( p_tmp )
308                 {
309                     return p_tmp;
310                 }
311             }
312         }
313         break;
314
315     case FIND_CHILD:
316         for( i = p_this->i_children; i--; )
317         {
318             p_tmp = p_this->pp_children[i];
319             if( p_tmp->i_object_type == i_type )
320             {
321                 p_tmp->i_refcount++;
322                 return p_tmp;
323             }
324             else if( p_tmp->i_children )
325             {
326                 p_tmp = vlc_object_find_inner( p_tmp, i_type, i_mode );
327                 if( p_tmp )
328                 {
329                     return p_tmp;
330                 }
331             }
332         }
333         break;
334
335     case FIND_ANYWHERE:
336         /* FIXME: unimplemented */
337         break;
338     }
339
340     return NULL;
341 }
342
343 /* vlc_object_yield: increment an object refcount */
344 void __vlc_object_yield( vlc_object_t *p_this )
345 {
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 );
349 }
350
351 /* vlc_object_release: decrement an object refcount */
352 void __vlc_object_release( vlc_object_t *p_this )
353 {
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 );
357 }
358
359 /* vlc_object_unlink: detach object from its parents */
360 void __vlc_object_unlink_all( vlc_object_t *p_this )
361 {
362     vlc_mutex_lock( &p_this->p_vlc->structure_lock );
363
364     /* FIXME: BORK ! BORK ! BORK !!! THIS STUFF IS BORKED !! FIXME */
365     while( p_this->i_parents )
366     {
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] );
371     }
372
373     vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
374 }
375
376 /* vlc_object_unlink: remove a parent/child link */
377 void __vlc_object_unlink( vlc_object_t *p_this, vlc_object_t *p_parent )
378 {
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 );
382 }
383
384 static void vlc_object_unlink_inner( vlc_object_t *p_this,
385                                      vlc_object_t *p_parent )
386 {
387     int i_index, i;
388
389     /* Remove all of p_this's parents which are p_parent */
390     for( i_index = p_this->i_parents ; i_index-- ; )
391     {
392         if( p_this->pp_parents[i_index] == p_parent )
393         {
394             p_this->i_parents--;
395             for( i = i_index ; i < p_this->i_parents ; i++ )
396             {
397                 p_this->pp_parents[i] = p_this->pp_parents[i+1];
398             }
399         }
400     }
401
402     if( p_this->i_parents )
403     {
404         p_this->pp_parents = (vlc_object_t **)realloc( p_this->pp_parents,
405                                 p_this->i_parents * sizeof(vlc_object_t *) );
406     }
407     else
408     {
409         free( p_this->pp_parents );
410         p_this->pp_parents = NULL;
411     }
412
413     /* Remove all of p_parent's children which are p_this */
414     for( i_index = p_parent->i_children ; i_index-- ; )
415     {
416         if( p_parent->pp_children[i_index] == p_this )
417         {
418             p_parent->i_children--;
419             for( i = i_index ; i < p_parent->i_children ; i++ )
420             {
421                 p_parent->pp_children[i] = p_parent->pp_children[i+1];
422             }
423         }
424     }
425
426     if( p_parent->i_children )
427     {
428         p_parent->pp_children = (vlc_object_t **)realloc( p_parent->pp_children,
429                                p_parent->i_children * sizeof(vlc_object_t *) );
430     }
431     else
432     {
433         free( p_parent->pp_children );
434         p_parent->pp_children = NULL;
435     }
436 }
437
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 )
440 {
441     vlc_mutex_lock( &p_this->p_vlc->structure_lock );
442
443     p_this->i_parents++;
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;
447
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;
452
453     vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
454 }
455
456 #if 0 /* UNUSED */
457 /* vlc_object_setchild: attach a child object */
458 void __vlc_object_setchild( vlc_object_t *p_this, vlc_object_t *p_child )
459 {
460     vlc_mutex_lock( &p_this->p_vlc->structure_lock );
461
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;
466
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;
471
472     vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
473 }
474 #endif
475