76
78
static int CountChildren ( vlc_object_t *, int );
77
79
static void ListChildren ( vlc_list_t *, vlc_object_t *, int );
81
static void vlc_object_destroy( vlc_object_t *p_this );
82
static void vlc_object_detach_unlocked (vlc_object_t *p_this);
84
#ifdef LIBVLC_REFCHECK
85
static vlc_threadvar_t held_objects;
86
typedef struct held_list_t
88
struct held_list_t *next;
91
static void held_objects_destroy (void *);
79
94
/*****************************************************************************
80
95
* Local structure lock
81
96
*****************************************************************************/
82
static vlc_mutex_t structure_lock;
84
/*****************************************************************************
85
* vlc_object_create: initialize a vlc object
86
*****************************************************************************
87
* This function allocates memory for a vlc object and initializes it. If
88
* i_type is not a known value such as VLC_OBJECT_ROOT, VLC_OBJECT_VOUT and
89
* so on, vlc_object_create will use its value for the object size.
90
*****************************************************************************/
97
static vlc_mutex_t structure_lock;
98
static unsigned object_counter = 0;
100
void *__vlc_custom_create( vlc_object_t *p_this, size_t i_size,
101
int i_type, const char *psz_type )
104
vlc_object_internals_t *p_priv;
107
* VLC objects are laid out as follow:
108
* - first the LibVLC-private per-object data,
109
* - then VLC_COMMON members from vlc_object_t,
110
* - finally, the type-specific data (if any).
112
* This function initializes the LibVLC and common data,
113
* and zeroes the rest.
115
p_priv = calloc( 1, sizeof( *p_priv ) + i_size );
119
assert (i_size >= sizeof (vlc_object_t));
120
p_new = (vlc_object_t *)(p_priv + 1);
122
p_new->i_object_type = i_type;
123
p_new->psz_object_type = psz_type;
124
p_new->psz_object_name = NULL;
126
p_new->b_die = false;
127
p_new->b_error = false;
128
p_new->b_dead = false;
129
p_new->b_force = false;
131
p_new->psz_header = NULL;
134
p_new->i_flags = p_this->i_flags
135
& (OBJECT_FLAGS_NODBG|OBJECT_FLAGS_QUIET|OBJECT_FLAGS_NOINTERACT);
137
p_priv->p_vars = calloc( sizeof( variable_t ), 16 );
139
if( !p_priv->p_vars )
145
libvlc_global_data_t *p_libvlc_global;
148
/* Only the global root object is created out of the blue */
149
p_libvlc_global = (libvlc_global_data_t *)p_new;
150
p_new->p_libvlc = NULL;
152
object_counter = 0; /* reset */
153
p_priv->next = p_priv->prev = p_new;
154
vlc_mutex_init( &structure_lock );
155
#ifdef LIBVLC_REFCHECK
156
/* TODO: use the destruction callback to track ref leaks */
157
vlc_threadvar_create( &held_objects, held_objects_destroy );
162
p_libvlc_global = vlc_global();
163
if( i_type == VLC_OBJECT_LIBVLC )
164
p_new->p_libvlc = (libvlc_int_t*)p_new;
166
p_new->p_libvlc = p_this->p_libvlc;
169
vlc_spin_init( &p_priv->ref_spin );
170
p_priv->i_refcount = 1;
171
p_priv->pf_destructor = NULL;
172
p_priv->b_thread = false;
173
p_new->p_parent = NULL;
174
p_priv->pp_children = NULL;
175
p_priv->i_children = 0;
177
p_new->p_private = NULL;
179
/* Initialize mutexes and condvars */
180
vlc_mutex_init( &p_priv->lock );
181
vlc_cond_init( p_new, &p_priv->wait );
182
vlc_mutex_init( &p_priv->var_lock );
183
vlc_spin_init( &p_priv->spin );
184
p_priv->pipes[0] = p_priv->pipes[1] = -1;
186
p_priv->next = VLC_OBJECT (p_libvlc_global);
187
#if !defined (LIBVLC_REFCHECK)
189
#elif defined (LIBVLC_USE_PTHREAD)
190
p_priv->creator_id = pthread_self ();
191
#elif defined (WIN32)
192
p_priv->creator_id = GetCurrentThreadId ();
194
vlc_mutex_lock( &structure_lock );
195
p_priv->prev = vlc_internals (p_libvlc_global)->prev;
196
vlc_internals (p_libvlc_global)->prev = p_new;
197
vlc_internals (p_priv->prev)->next = p_new;
198
p_new->i_object_id = object_counter++; /* fetch THEN increment */
199
vlc_mutex_unlock( &structure_lock );
201
if( i_type == VLC_OBJECT_LIBVLC )
203
var_Create( p_new, "list", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
204
var_AddCallback( p_new, "list", DumpCommand, NULL );
205
var_Create( p_new, "tree", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
206
var_AddCallback( p_new, "tree", DumpCommand, NULL );
207
var_Create( p_new, "vars", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
208
var_AddCallback( p_new, "vars", DumpCommand, NULL );
93
* Initialize a vlc object
95
* This function allocates memory for a vlc object and initializes it. If
96
* i_type is not a known value such as VLC_OBJECT_ROOT, VLC_OBJECT_VOUT and
97
* so on, vlc_object_create will use its value for the object size.
216
* Allocates and initializes a vlc object.
218
* @param i_type known object type (all of them are negative integer values),
219
* or object byte size (always positive).
221
* @return the new object, or NULL on error.
99
223
void * __vlc_object_create( vlc_object_t *p_this, int i_type )
101
vlc_object_t * p_new;
102
225
const char * psz_type;
107
case VLC_OBJECT_ROOT:
108
i_size = sizeof(libvlc_t);
112
i_size = sizeof(vlc_t);
115
case VLC_OBJECT_MODULE:
116
i_size = sizeof(module_t);
119
230
case VLC_OBJECT_INTF:
120
231
i_size = sizeof(intf_thread_t);
121
232
psz_type = "interface";
123
case VLC_OBJECT_DIALOGS:
124
i_size = sizeof(intf_thread_t);
125
psz_type = "dialogs";
127
case VLC_OBJECT_PLAYLIST:
128
i_size = sizeof(playlist_t);
129
psz_type = "playlist";
132
i_size = sizeof(services_discovery_t);
133
psz_type = "services discovery";
135
case VLC_OBJECT_INPUT:
136
i_size = sizeof(input_thread_t);
139
case VLC_OBJECT_DEMUX:
140
i_size = sizeof(demux_t);
143
case VLC_OBJECT_STREAM:
144
i_size = sizeof(stream_t);
147
case VLC_OBJECT_ACCESS:
148
i_size = sizeof(access_t);
151
234
case VLC_OBJECT_DECODER:
152
235
i_size = sizeof(decoder_t);
153
236
psz_type = "decoder";
212
255
i_size = sizeof( announce_handler_t );
213
256
psz_type = "announce";
215
case VLC_OBJECT_OSDMENU:
216
i_size = sizeof( osd_menu_t );
217
psz_type = "osd menu";
219
case VLC_OBJECT_STATS:
220
i_size = sizeof( stats_handler_t );
221
psz_type = "statistics";
224
i_size = i_type > (int)sizeof(vlc_object_t)
225
? i_type : (int)sizeof(vlc_object_t);
259
assert( i_type > 0 ); /* unknown type?! */
226
261
i_type = VLC_OBJECT_GENERIC;
227
262
psz_type = "generic";
231
if( i_type == VLC_OBJECT_ROOT )
237
p_new = malloc( i_size );
238
if( !p_new ) return NULL;
239
memset( p_new, 0, i_size );
242
p_new->i_object_type = i_type;
243
p_new->psz_object_type = psz_type;
245
p_new->psz_object_name = NULL;
247
p_new->b_die = VLC_FALSE;
248
p_new->b_error = VLC_FALSE;
249
p_new->b_dead = VLC_FALSE;
250
p_new->b_attached = VLC_FALSE;
251
p_new->b_force = VLC_FALSE;
253
p_new->psz_header = NULL;
256
if( p_this->i_flags & OBJECT_FLAGS_NODBG )
257
p_new->i_flags |= OBJECT_FLAGS_NODBG;
258
if( p_this->i_flags & OBJECT_FLAGS_QUIET )
259
p_new->i_flags |= OBJECT_FLAGS_QUIET;
260
if( p_this->i_flags & OBJECT_FLAGS_NOINTERACT )
261
p_new->i_flags |= OBJECT_FLAGS_NOINTERACT;
264
p_new->p_vars = (variable_t *)malloc( 16 * sizeof( variable_t ) );
268
if( i_type != VLC_OBJECT_ROOT )
273
if( i_type == VLC_OBJECT_ROOT )
275
/* If i_type is root, then p_new is actually p_libvlc */
276
p_new->p_libvlc = (libvlc_t*)p_new;
279
p_new->p_libvlc->i_counter = 0;
280
p_new->i_object_id = 0;
282
p_new->p_libvlc->i_objects = 1;
283
p_new->p_libvlc->pp_objects = malloc( sizeof(vlc_object_t *) );
284
p_new->p_libvlc->pp_objects[0] = p_new;
285
p_new->b_attached = VLC_TRUE;
289
p_new->p_libvlc = p_this->p_libvlc;
290
p_new->p_vlc = ( i_type == VLC_OBJECT_VLC ) ? (vlc_t*)p_new
293
vlc_mutex_lock( &structure_lock );
295
p_new->p_libvlc->i_counter++;
296
p_new->i_object_id = p_new->p_libvlc->i_counter;
298
/* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's
299
* useless to try and recover anything if pp_objects gets smashed. */
300
INSERT_ELEM( p_new->p_libvlc->pp_objects,
301
p_new->p_libvlc->i_objects,
302
p_new->p_libvlc->i_objects,
305
vlc_mutex_unlock( &structure_lock );
308
p_new->i_refcount = 0;
309
p_new->p_parent = NULL;
310
p_new->pp_children = NULL;
311
p_new->i_children = 0;
313
p_new->p_private = NULL;
315
/* Initialize mutexes and condvars */
316
vlc_mutex_init( p_new, &p_new->object_lock );
317
vlc_cond_init( p_new, &p_new->object_wait );
318
vlc_mutex_init( p_new, &p_new->var_lock );
320
if( i_type == VLC_OBJECT_ROOT )
322
vlc_mutex_init( p_new, &structure_lock );
324
var_Create( p_new, "list", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
325
var_AddCallback( p_new, "list", DumpCommand, NULL );
326
var_Create( p_new, "tree", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
327
var_AddCallback( p_new, "tree", DumpCommand, NULL );
334
****************************************************************************
335
* Destroy a vlc object
266
return vlc_custom_create( p_this, i_size, i_type, psz_type );
271
****************************************************************************
272
* Set the destructor of a vlc object
274
* This function sets the destructor of the vlc object. It will be called
275
* when the object is destroyed when the its refcount reaches 0.
276
* (It is called by the internal function vlc_object_destroy())
277
*****************************************************************************/
278
void __vlc_object_set_destructor( vlc_object_t *p_this,
279
vlc_destructor_t pf_destructor )
281
vlc_object_internals_t *p_priv = vlc_internals(p_this );
282
p_priv->pf_destructor = pf_destructor;
286
****************************************************************************
287
* Destroy a vlc object (Internal)
337
289
* This function destroys an object that has been previously allocated with
338
290
* vlc_object_create. The object's refcount must be zero and it must not be
339
291
* attached to other objects in any way.
340
292
*****************************************************************************/
341
void __vlc_object_destroy( vlc_object_t *p_this )
293
static void vlc_object_destroy( vlc_object_t *p_this )
345
if( p_this->i_children )
347
msg_Err( p_this, "cannot delete object (%i, %s) with children" ,
348
p_this->i_object_id, p_this->psz_object_name );
352
if( p_this->p_parent )
354
msg_Err( p_this, "cannot delete object (%i, %s) with a parent",
355
p_this->i_object_id, p_this->psz_object_name );
359
while( p_this->i_refcount )
363
/* Don't warn immediately ... 100ms seems OK */
367
"refcount is %i, delaying before deletion (id=%d,type=%d)",
368
p_this->i_refcount, p_this->i_object_id,
369
p_this->i_object_type );
371
else if( i_delay == 10 )
374
"refcount is %i, delaying again (id=%d,type=%d)",
375
p_this->i_refcount, p_this->i_object_id,
376
p_this->i_object_type );
378
else if( i_delay == 20 )
381
"waited too long, cancelling destruction (id=%d,type=%d)",
382
p_this->i_object_id, p_this->i_object_type );
295
vlc_object_internals_t *p_priv = vlc_internals( p_this );
297
/* Objects are always detached beforehand */
298
assert( !p_this->p_parent );
300
/* Send a kill to the object's thread if applicable */
301
vlc_object_kill( p_this );
303
/* If we are running on a thread, wait until it ends */
304
if( p_priv->b_thread )
306
msg_Warn (p_this->p_libvlc, /* do NOT use a dead object for logging! */
307
"%s %d destroyed while thread alive (VLC might crash)",
308
p_this->psz_object_type, p_this->i_object_id);
309
vlc_thread_join( p_this );
312
/* Call the custom "subclass" destructor */
313
if( p_priv->pf_destructor )
314
p_priv->pf_destructor( p_this );
389
316
/* Destroy the associated variables, starting from the end so that
390
317
* no memmove calls have to be done. */
391
while( p_this->i_vars )
318
while( p_priv->i_vars )
393
var_Destroy( p_this, p_this->p_vars[p_this->i_vars - 1].psz_name );
320
var_Destroy( p_this, p_priv->p_vars[p_priv->i_vars - 1].psz_name );
396
free( p_this->p_vars );
397
vlc_mutex_destroy( &p_this->var_lock );
399
if( p_this->psz_header ) free( p_this->psz_header );
401
if( p_this->i_object_type == VLC_OBJECT_ROOT )
323
free( p_priv->p_vars );
324
vlc_mutex_destroy( &p_priv->var_lock );
326
free( p_this->psz_header );
328
if( p_this->p_libvlc == NULL )
403
/* We are the root object ... no need to lock. */
404
free( p_this->p_libvlc->pp_objects );
405
p_this->p_libvlc->pp_objects = NULL;
406
p_this->p_libvlc->i_objects--;
331
libvlc_global_data_t *p_global = (libvlc_global_data_t *)p_this;
333
assert( p_global == vlc_global() );
335
if (p_priv->next != p_this)
337
vlc_object_t *leaked = p_priv->next, *first = leaked;
340
/* We are leaking this object */
342
"ERROR: leaking object (id:%i, type:%s, name:%s)\n",
343
leaked->i_object_id, leaked->psz_object_type,
344
leaked->psz_object_name );
345
/* Dump libvlc object to ease debugging */
346
vlc_object_dump( leaked );
348
leaked = vlc_internals (leaked)->next;
350
while (leaked != first);
352
/* Dump global object to ease debugging */
353
vlc_object_dump( p_this );
354
/* Strongly abort, cause we want these to be fixed */
359
/* We are the global object ... no need to lock. */
408
360
vlc_mutex_destroy( &structure_lock );
361
#ifdef LIBVLC_REFCHECK
362
held_objects_destroy( vlc_threadvar_get( &held_objects ) );
363
vlc_threadvar_delete( &held_objects );
367
FREENULL( p_this->psz_object_name );
369
#if defined(WIN32) || defined(UNDER_CE)
370
/* if object has an associated thread, close it now */
371
if( p_priv->thread_id )
372
CloseHandle(p_priv->thread_id);
375
vlc_spin_destroy( &p_priv->ref_spin );
376
vlc_mutex_destroy( &p_priv->lock );
377
vlc_cond_destroy( &p_priv->wait );
378
vlc_spin_destroy( &p_priv->spin );
379
if( p_priv->pipes[1] != -1 )
380
close( p_priv->pipes[1] );
381
if( p_priv->pipes[0] != -1 )
382
close( p_priv->pipes[0] );
388
/** Inter-object signaling */
390
void __vlc_object_lock( vlc_object_t *obj )
392
vlc_mutex_lock( &(vlc_internals(obj)->lock) );
395
void __vlc_object_unlock( vlc_object_t *obj )
397
vlc_assert_locked( &(vlc_internals(obj)->lock) );
398
vlc_mutex_unlock( &(vlc_internals(obj)->lock) );
402
# include <winsock2.h>
403
# include <ws2tcpip.h>
406
* select()-able pipes emulated using Winsock
408
static int pipe (int fd[2])
411
int addrlen = sizeof (addr);
413
SOCKET l = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP), a,
414
c = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
415
if ((l == INVALID_SOCKET) || (c == INVALID_SOCKET))
418
memset (&addr, 0, sizeof (addr));
419
addr.sin_family = AF_INET;
420
addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
421
if (bind (l, (PSOCKADDR)&addr, sizeof (addr))
422
|| getsockname (l, (PSOCKADDR)&addr, &addrlen)
424
|| connect (c, (PSOCKADDR)&addr, addrlen))
427
a = accept (l, NULL, NULL);
428
if (a == INVALID_SOCKET)
439
if (l != INVALID_SOCKET)
441
if (c != INVALID_SOCKET)
447
#define read( a, b, c ) recv (a, b, c, 0)
449
#define write( a, b, c ) send (a, b, c, 0)
451
#define close( a ) closesocket (a)
455
* Returns the readable end of a pipe that becomes readable once termination
456
* of the object is requested (vlc_object_kill()).
457
* This can be used to wake-up out of a select() or poll() event loop, such
458
* typically when doing network I/O.
460
* Note that the pipe will remain the same for the lifetime of the object.
461
* DO NOT read the pipe nor close it yourself. Ever.
463
* @param obj object that would be "killed"
464
* @return a readable pipe descriptor, or -1 on error.
466
int __vlc_object_waitpipe( vlc_object_t *obj )
468
int pfd[2] = { -1, -1 };
469
vlc_object_internals_t *internals = vlc_internals( obj );
472
vlc_spin_lock (&internals->spin);
473
if (internals->pipes[0] == -1)
475
/* This can only ever happen if someone killed us without locking: */
476
assert (internals->pipes[1] == -1);
477
vlc_spin_unlock (&internals->spin);
482
vlc_spin_lock (&internals->spin);
483
if (internals->pipes[0] == -1)
485
internals->pipes[0] = pfd[0];
486
internals->pipes[1] = pfd[1];
487
pfd[0] = pfd[1] = -1;
491
vlc_spin_unlock (&internals->spin);
495
/* Race condition: vlc_object_kill() already invoked! */
498
vlc_spin_lock (&internals->spin);
499
fd = internals->pipes[1];
500
internals->pipes[1] = -1;
501
vlc_spin_unlock (&internals->spin);
503
msg_Dbg (obj, "waitpipe: object already dying");
508
/* Race condition: two threads call pipe() - unlikely */
514
return internals->pipes[0];
519
* Waits for the object to be signaled (using vlc_object_signal()).
520
* It is assumed that the caller has locked the object. This function will
521
* unlock the object, and lock it again before returning.
522
* If the object was signaled before the caller locked the object, it is
523
* undefined whether the signal will be lost or will wake the process.
525
* @return true if the object is dying and should terminate.
527
void __vlc_object_wait( vlc_object_t *obj )
529
vlc_object_internals_t *priv = vlc_internals( obj );
530
vlc_assert_locked( &priv->lock);
531
vlc_cond_wait( &priv->wait, &priv->lock );
536
* Waits for the object to be signaled (using vlc_object_signal()), or for
537
* a timer to expire. It is asserted that the caller holds the object lock.
539
* @return 0 if the object was signaled before the timer expiration, or
540
* ETIMEDOUT if the timer expired without any signal.
542
int __vlc_object_timedwait( vlc_object_t *obj, mtime_t deadline )
544
vlc_object_internals_t *priv = vlc_internals( obj );
545
vlc_assert_locked( &priv->lock);
546
return vlc_cond_timedwait( &priv->wait, &priv->lock, deadline );
551
* Signals an object for which the lock is held.
552
* At least one thread currently sleeping in vlc_object_wait() or
553
* vlc_object_timedwait() will wake up, assuming that there is at least one
554
* such thread in the first place. Otherwise, it is undefined whether the
555
* signal will be lost or will wake up one or more thread later.
557
void __vlc_object_signal_unlocked( vlc_object_t *obj )
559
vlc_assert_locked (&(vlc_internals(obj)->lock));
560
vlc_cond_signal( &(vlc_internals(obj)->wait) );
565
* Requests termination of an object.
566
* If the object is LibVLC, also request to terminate all its children.
568
void __vlc_object_kill( vlc_object_t *p_this )
570
vlc_object_internals_t *priv = vlc_internals( p_this );
573
vlc_object_lock( p_this );
574
p_this->b_die = true;
576
vlc_spin_lock (&priv->spin);
579
vlc_spin_unlock (&priv->spin);
583
msg_Dbg (p_this, "waitpipe: object killed");
587
vlc_object_signal_unlocked( p_this );
588
/* This also serves as a memory barrier toward vlc_object_alive(): */
589
vlc_object_unlock( p_this );
594
* Find an object given its ID.
596
* This function looks for the object whose i_object_id field is i_id.
597
* This function is slow, and often used to hide bugs. Do not use it.
598
* If you need to retain reference to an object, yield the object pointer with
599
* vlc_object_yield(), use the pointer as your reference, and call
600
* vlc_object_release() when you're done.
602
void * vlc_object_get( int i_id )
604
libvlc_global_data_t *p_libvlc_global = vlc_global();
605
vlc_object_t *obj = NULL;
607
vlc_object_t *caller = vlc_threadobj ();
610
msg_Dbg (caller, "uses deprecated vlc_object_get(%d)", i_id);
414
vlc_mutex_lock( &structure_lock );
416
/* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's
417
* useless to try and recover anything if pp_objects gets smashed. */
418
i_index = FindIndex( p_this, p_this->p_libvlc->pp_objects,
419
p_this->p_libvlc->i_objects );
420
REMOVE_ELEM( p_this->p_libvlc->pp_objects,
421
p_this->p_libvlc->i_objects, i_index );
423
vlc_mutex_unlock( &structure_lock );
426
vlc_mutex_destroy( &p_this->object_lock );
427
vlc_cond_destroy( &p_this->object_wait );
429
/* root is not dynamically allocated by vlc_object_create */
430
if( p_this->i_object_type != VLC_OBJECT_ROOT )
435
* find an object given its ID
437
* This function looks for the object whose i_object_id field is i_id. We
438
* use a dichotomy so that lookups are in log2(n).
439
*****************************************************************************/
440
void * __vlc_object_get( vlc_object_t *p_this, int i_id )
443
vlc_object_t **pp_objects;
612
fprintf (stderr, "main thread uses deprecated vlc_object_get(%d)\n",
445
615
vlc_mutex_lock( &structure_lock );
447
pp_objects = p_this->p_libvlc->pp_objects;
449
/* Perform our dichotomy */
450
for( i_max = p_this->p_libvlc->i_objects - 1 ; ; )
617
for( obj = vlc_internals (p_libvlc_global)->next;
618
obj != VLC_OBJECT (p_libvlc_global);
619
obj = vlc_internals (obj)->next )
452
i_middle = i_max / 2;
454
if( pp_objects[i_middle]->i_object_id > i_id )
458
else if( pp_objects[i_middle]->i_object_id < i_id )
462
pp_objects += i_middle;
467
/* This happens when there are only two remaining objects */
468
if( pp_objects[i_middle+1]->i_object_id == i_id )
470
vlc_mutex_unlock( &structure_lock );
471
pp_objects[i_middle+1]->i_refcount++;
472
return pp_objects[i_middle+1];
479
vlc_mutex_unlock( &structure_lock );
480
pp_objects[i_middle]->i_refcount++;
481
return pp_objects[i_middle];
486
/* this means that i_max == i_middle, and since we have already
487
* tested pp_objects[i_middle]), p_found is properly set. */
621
if( obj->i_object_id == i_id )
623
vlc_object_yield( obj );
630
msg_Warn (caller, "wants non-existing object %d", i_id);
632
fprintf (stderr, "main thread wants non-existing object %d\n", i_id);
492
635
vlc_mutex_unlock( &structure_lock );
700
994
static int DumpCommand( vlc_object_t *p_this, char const *psz_cmd,
701
995
vlc_value_t oldval, vlc_value_t newval, void *p_data )
703
if( *psz_cmd == 't' )
705
char psz_foo[2 * MAX_DUMPSTRUCTURE_DEPTH + 1];
706
vlc_object_t *p_object;
997
(void)oldval; (void)p_data;
998
if( *psz_cmd == 'l' )
1000
vlc_object_t *root = VLC_OBJECT (vlc_global ()), *cur = root;
1002
vlc_mutex_lock( &structure_lock );
1005
PrintObject (cur, "");
1006
cur = vlc_internals (cur)->next;
1008
while (cur != root);
1009
vlc_mutex_unlock( &structure_lock );
1013
vlc_object_t *p_object = NULL;
708
1015
if( *newval.psz_string )
710
p_object = vlc_object_get( p_this, atoi(newval.psz_string) );
1018
int i_id = strtol( newval.psz_string, &end, 0 );
1019
if( end != newval.psz_string )
1020
p_object = vlc_object_get( i_id );
1022
/* try using the object's name to find it */
1023
p_object = vlc_object_find_name( p_this, newval.psz_string,
714
1028
return VLC_ENOOBJ;
719
p_object = p_this->p_vlc ? VLC_OBJECT(p_this->p_vlc) : p_this;
722
1032
vlc_mutex_lock( &structure_lock );
725
DumpStructure( p_object, 0, psz_foo );
1034
if( *psz_cmd == 't' )
1036
char psz_foo[2 * MAX_DUMPSTRUCTURE_DEPTH + 1];
1039
p_object = p_this->p_libvlc ? VLC_OBJECT(p_this->p_libvlc) : p_this;
1042
DumpStructure( p_object, 0, psz_foo );
1044
else if( *psz_cmd == 'v' )
1049
p_object = p_this->p_libvlc ? VLC_OBJECT(p_this->p_libvlc) : p_this;
1051
PrintObject( p_object, "" );
1053
if( !vlc_internals( p_object )->i_vars )
1054
printf( " `-o No variables\n" );
1055
for( i = 0; i < vlc_internals( p_object )->i_vars; i++ )
1057
variable_t *p_var = vlc_internals( p_object )->p_vars + i;
1059
const char *psz_type = "unknown";
1060
switch( p_var->i_type & VLC_VAR_TYPE )
1062
#define MYCASE( type, nice ) \
1063
case VLC_VAR_ ## type: \
1066
MYCASE( VOID, "void" );
1067
MYCASE( BOOL, "bool" );
1068
MYCASE( INTEGER, "integer" );
1069
MYCASE( HOTKEY, "hotkey" );
1070
MYCASE( STRING, "string" );
1071
MYCASE( MODULE, "module" );
1072
MYCASE( FILE, "file" );
1073
MYCASE( DIRECTORY, "directory" );
1074
MYCASE( VARIABLE, "variable" );
1075
MYCASE( FLOAT, "float" );
1076
MYCASE( TIME, "time" );
1077
MYCASE( ADDRESS, "address" );
1078
MYCASE( MUTEX, "mutex" );
1079
MYCASE( LIST, "list" );
1082
printf( " %c-o \"%s\" (%s",
1083
i + 1 == vlc_internals( p_object )->i_vars ? '`' : '|',
1084
p_var->psz_name, psz_type );
1085
if( p_var->psz_text )
1086
printf( ", %s", p_var->psz_text );
1088
if( p_var->i_type & VLC_VAR_ISCOMMAND )
1089
printf( ", command" );
1090
if( p_var->i_entries )
1091
printf( ", %d callbacks", p_var->i_entries );
1092
switch( p_var->i_type & 0x00f0 )
1098
printf( ": %s", p_var->val.b_bool ? "true" : "false" );
1100
case VLC_VAR_INTEGER:
1101
printf( ": %d", p_var->val.i_int );
1103
case VLC_VAR_STRING:
1104
printf( ": \"%s\"", p_var->val.psz_string );
1107
printf( ": %f", p_var->val.f_float );
1110
printf( ": %"PRIi64, (int64_t)p_var->val.i_time );
1112
case VLC_VAR_ADDRESS:
1113
printf( ": %p", p_var->val.p_address );
727
1123
vlc_mutex_unlock( &structure_lock );
729
1125
if( *newval.psz_string )
731
vlc_object_release( p_this );
734
else if( *psz_cmd == 'l' )
736
vlc_object_t **pp_current, **pp_end;
738
vlc_mutex_lock( &structure_lock );
740
pp_current = p_this->p_libvlc->pp_objects;
741
pp_end = pp_current + p_this->p_libvlc->i_objects;
743
for( ; pp_current < pp_end ; pp_current++ )
745
if( (*pp_current)->b_attached )
747
PrintObject( *pp_current, "" );
751
printf( " o %.8i %s (not attached)\n",
752
(*pp_current)->i_object_id,
753
(*pp_current)->psz_object_type );
757
vlc_mutex_unlock( &structure_lock );
1127
vlc_object_release( p_object );
760
1131
return VLC_SUCCESS;