X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmisc%2Fobjects.c;h=79a64d203bc75c6ce5f5e25531631491a2c6ca12;hb=5a7d66bf55429e2206a1ee2dd65a9a1ffe521cc7;hp=c2f76f5fe3e250165e39585e88701897454895da;hpb=d3fe7f28797d4dba65ffcdd60bf932e758a48a9e;p=vlc diff --git a/src/misc/objects.c b/src/misc/objects.c index c2f76f5fe3..79a64d203b 100644 --- a/src/misc/objects.c +++ b/src/misc/objects.c @@ -1,7 +1,7 @@ /***************************************************************************** * objects.c: vlc_object_t handling ***************************************************************************** - * Copyright (C) 2004 the VideoLAN team + * Copyright (C) 2004-2007 the VideoLAN team * $Id$ * * Authors: Samuel Hocevar @@ -32,10 +32,7 @@ *****************************************************************************/ #include -#ifdef HAVE_STDLIB_H -# include /* realloc() */ -#endif - +#include "../libvlc.h" #include #include #include "audio_output/aout_internal.h" @@ -54,6 +51,7 @@ #include "vlc_httpd.h" #include "vlc_vlm.h" +#include "input/vlm_internal.h" #include "vlc_vod.h" #include "vlc_tls.h" #include "vlc_xml.h" @@ -61,6 +59,12 @@ #include "vlc_meta.h" #include "variables.h" +#ifndef WIN32 +# include +#else +# include +# include +#endif /***************************************************************************** * Local prototypes @@ -69,6 +73,7 @@ static int DumpCommand( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); static vlc_object_t * FindObject ( vlc_object_t *, int, int ); +static vlc_object_t * FindObjectName( vlc_object_t *, const char *, int ); static void DetachObject ( vlc_object_t * ); static void PrintObject ( vlc_object_t *, const char * ); static void DumpStructure ( vlc_object_t *, int, char * ); @@ -85,17 +90,141 @@ static void ListChildren ( vlc_list_t *, vlc_object_t *, int ); * Local structure lock *****************************************************************************/ static vlc_mutex_t structure_lock; +static vlc_object_internals_t global_internals; + +vlc_object_t *vlc_custom_create( vlc_object_t *p_this, size_t i_size, + int i_type, const char *psz_type ) +{ + vlc_object_t *p_new; + vlc_object_internals_t *p_priv; + + if( i_type == VLC_OBJECT_GLOBAL ) + { + p_new = p_this; + p_priv = &global_internals; + memset( p_priv, 0, sizeof( *p_priv ) ); + } + else + { + p_priv = calloc( 1, sizeof( *p_priv ) + i_size ); + if( p_priv == NULL ) + return NULL; + + p_new = (vlc_object_t *)(p_priv + 1); + } + + p_new->p_internals = p_priv; + p_new->i_object_type = i_type; + p_new->psz_object_type = psz_type; + + p_new->psz_object_name = NULL; + + p_new->b_die = VLC_FALSE; + p_new->b_error = VLC_FALSE; + p_new->b_dead = VLC_FALSE; + p_priv->b_attached = VLC_FALSE; + p_new->b_force = VLC_FALSE; + + p_new->psz_header = NULL; + + if( p_this->i_flags & OBJECT_FLAGS_NODBG ) + p_new->i_flags |= OBJECT_FLAGS_NODBG; + if( p_this->i_flags & OBJECT_FLAGS_QUIET ) + p_new->i_flags |= OBJECT_FLAGS_QUIET; + if( p_this->i_flags & OBJECT_FLAGS_NOINTERACT ) + p_new->i_flags |= OBJECT_FLAGS_NOINTERACT; + + p_priv->p_vars = calloc( sizeof( variable_t ), 16 ); + + if( !p_priv->p_vars ) + { + if( i_type != VLC_OBJECT_GLOBAL ) + free( p_priv ); + return NULL; + } + + if( i_type == VLC_OBJECT_GLOBAL ) + { + /* If i_type is global, then p_new is actually p_libvlc_global */ + libvlc_global_data_t *p_libvlc_global = (libvlc_global_data_t *)p_new; + p_new->p_libvlc = NULL; + + p_libvlc_global->i_counter = 0; + p_new->i_object_id = 0; + + p_libvlc_global->i_objects = 1; + p_libvlc_global->pp_objects = malloc( sizeof(vlc_object_t *) ); + p_libvlc_global->pp_objects[0] = p_new; + p_priv->b_attached = VLC_TRUE; + } + else + { + libvlc_global_data_t *p_libvlc_global = vlc_global(); + if( i_type == VLC_OBJECT_LIBVLC ) + { + p_new->p_libvlc = (libvlc_int_t*)p_new; + p_priv->b_attached = VLC_TRUE; + } + else + { + p_new->p_libvlc = p_this->p_libvlc; + } + + vlc_mutex_lock( &structure_lock ); + + p_libvlc_global->i_counter++; + p_new->i_object_id = p_libvlc_global->i_counter; + + /* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's + * useless to try and recover anything if pp_objects gets smashed. */ + TAB_APPEND( p_libvlc_global->i_objects, p_libvlc_global->pp_objects, + p_new ); + + vlc_mutex_unlock( &structure_lock ); + } + + p_priv->i_refcount = 0; + p_new->p_parent = NULL; + p_new->pp_children = NULL; + p_new->i_children = 0; + + p_new->p_private = NULL; + + /* Initialize mutexes and condvars */ + vlc_mutex_init( p_new, &p_new->object_lock ); + vlc_cond_init( p_new, &p_new->object_wait ); + vlc_mutex_init( p_new, &p_priv->var_lock ); + p_priv->pipes[0] = p_priv->pipes[1] = -1; + + if( i_type == VLC_OBJECT_GLOBAL ) + { + vlc_mutex_init( p_new, &structure_lock ); + } + + if( i_type == VLC_OBJECT_LIBVLC ) + { + var_Create( p_new, "list", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); + var_AddCallback( p_new, "list", DumpCommand, NULL ); + var_Create( p_new, "tree", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); + var_AddCallback( p_new, "tree", DumpCommand, NULL ); + var_Create( p_new, "vars", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); + var_AddCallback( p_new, "vars", DumpCommand, NULL ); + } + + return p_new; +} + /** - * Initialize a vlc object + * Allocates and initializes a vlc object. + * + * @param i_type known object type (all of them are negative integer values), + * or object byte size (always positive). * - * This function allocates memory for a vlc object and initializes it. If - * i_type is not a known value such as VLC_OBJECT_LIBVLC, VLC_OBJECT_VOUT and - * so on, vlc_object_create will use its value for the object size. + * @return the new object, or NULL on error. */ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) { - vlc_object_t * p_new; const char * psz_type; size_t i_size; @@ -109,10 +238,6 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) i_size = sizeof(libvlc_int_t); psz_type = "libvlc"; break; - case VLC_OBJECT_MODULE: - i_size = sizeof(module_t); - psz_type = "module"; - break; case VLC_OBJECT_INTF: i_size = sizeof(intf_thread_t); psz_type = "interface"; @@ -137,10 +262,6 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) i_size = sizeof(demux_t); psz_type = "demux"; break; - case VLC_OBJECT_STREAM: - i_size = sizeof(stream_t); - psz_type = "stream"; - break; case VLC_OBJECT_ACCESS: i_size = sizeof(access_t); psz_type = "access"; @@ -177,14 +298,6 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) i_size = sizeof(sout_instance_t); psz_type = "stream output"; break; - case VLC_OBJECT_HTTPD: - i_size = sizeof( httpd_t ); - psz_type = "http server"; - break; - case VLC_OBJECT_HTTPD_HOST: - i_size = sizeof( httpd_host_t ); - psz_type = "http server"; - break; case VLC_OBJECT_VLM: i_size = sizeof( vlm_t ); psz_type = "vlm dameon"; @@ -193,10 +306,6 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) i_size = sizeof( vod_t ); psz_type = "vod server"; break; - case VLC_OBJECT_TLS: - i_size = sizeof( tls_t ); - psz_type = "tls"; - break; case VLC_OBJECT_XML: i_size = sizeof( xml_t ); psz_type = "xml"; @@ -225,107 +334,10 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) break; } - if( i_type == VLC_OBJECT_GLOBAL ) - { - p_new = p_this; - } - else - { - p_new = malloc( i_size ); - if( !p_new ) return NULL; - memset( p_new, 0, i_size ); - } - - p_new->i_object_type = i_type; - p_new->psz_object_type = psz_type; - - p_new->psz_object_name = NULL; - - p_new->b_die = VLC_FALSE; - p_new->b_error = VLC_FALSE; - p_new->b_dead = VLC_FALSE; - p_new->b_attached = VLC_FALSE; - p_new->b_force = VLC_FALSE; - - p_new->psz_header = NULL; - - p_new->i_flags = 0; - if( p_this->i_flags & OBJECT_FLAGS_NODBG ) - p_new->i_flags |= OBJECT_FLAGS_NODBG; - if( p_this->i_flags & OBJECT_FLAGS_QUIET ) - p_new->i_flags |= OBJECT_FLAGS_QUIET; - if( p_this->i_flags & OBJECT_FLAGS_NOINTERACT ) - p_new->i_flags |= OBJECT_FLAGS_NOINTERACT; - - p_new->i_vars = 0; - p_new->p_vars = (variable_t *)malloc( 16 * sizeof( variable_t ) ); - - if( !p_new->p_vars ) - { - if( i_type != VLC_OBJECT_GLOBAL ) - free( p_new ); - return NULL; - } - - if( i_type == VLC_OBJECT_GLOBAL ) - { - /* If i_type is global, then p_new is actually p_libvlc_global */ - p_new->p_libvlc_global = (libvlc_global_data_t*)p_new; - p_new->p_libvlc = NULL; - - p_new->p_libvlc_global->i_counter = 0; - p_new->i_object_id = 0; - - p_new->p_libvlc_global->i_objects = 1; - p_new->p_libvlc_global->pp_objects = malloc( sizeof(vlc_object_t *) ); - p_new->p_libvlc_global->pp_objects[0] = p_new; - p_new->b_attached = VLC_TRUE; - } - else - { - p_new->p_libvlc_global = p_this->p_libvlc_global; - p_new->p_libvlc = ( i_type == VLC_OBJECT_LIBVLC ) ? (libvlc_int_t*)p_new - : p_this->p_libvlc; - - vlc_mutex_lock( &structure_lock ); - - p_new->p_libvlc_global->i_counter++; - p_new->i_object_id = p_new->p_libvlc_global->i_counter; - - /* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's - * useless to try and recover anything if pp_objects gets smashed. */ - TAB_APPEND( p_new->p_libvlc_global->i_objects, - p_new->p_libvlc_global->pp_objects, - p_new ); - - vlc_mutex_unlock( &structure_lock ); - } - - p_new->i_refcount = 0; - p_new->p_parent = NULL; - p_new->pp_children = NULL; - p_new->i_children = 0; - - p_new->p_private = NULL; - - /* Initialize mutexes and condvars */ - vlc_mutex_init( p_new, &p_new->object_lock ); - vlc_cond_init( p_new, &p_new->object_wait ); - vlc_mutex_init( p_new, &p_new->var_lock ); - - if( i_type == VLC_OBJECT_GLOBAL ) - { - vlc_mutex_init( p_new, &structure_lock ); - - var_Create( p_new, "list", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); - var_AddCallback( p_new, "list", DumpCommand, NULL ); - var_Create( p_new, "tree", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); - var_AddCallback( p_new, "tree", DumpCommand, NULL ); - } - - return p_new; + return vlc_custom_create( p_this, i_size, i_type, psz_type ); } + /** **************************************************************************** * Destroy a vlc object @@ -336,6 +348,7 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) *****************************************************************************/ void __vlc_object_destroy( vlc_object_t *p_this ) { + vlc_object_internals_t *p_priv = vlc_internals( p_this ); int i_delay = 0; if( p_this->i_children ) @@ -352,7 +365,7 @@ void __vlc_object_destroy( vlc_object_t *p_this ) return; } - while( p_this->i_refcount ) + while( p_priv->i_refcount > 0 ) { i_delay++; @@ -360,15 +373,15 @@ void __vlc_object_destroy( vlc_object_t *p_this ) if( i_delay == 2 ) { msg_Warn( p_this, - "refcount is %i, delaying before deletion (id=%d,type=%d)", - p_this->i_refcount, p_this->i_object_id, + "refcount is %u, delaying before deletion (id=%d,type=%d)", + p_priv->i_refcount, p_this->i_object_id, p_this->i_object_type ); } else if( i_delay == 10 ) { msg_Err( p_this, - "refcount is %i, delaying again (id=%d,type=%d)", - p_this->i_refcount, p_this->i_object_id, + "refcount is %u, delaying again (id=%d,type=%d)", + p_priv->i_refcount, p_this->i_object_id, p_this->i_object_type ); } else if( i_delay == 20 ) @@ -384,49 +397,201 @@ void __vlc_object_destroy( vlc_object_t *p_this ) /* Destroy the associated variables, starting from the end so that * no memmove calls have to be done. */ - while( p_this->i_vars ) + while( p_priv->i_vars ) { - var_Destroy( p_this, p_this->p_vars[p_this->i_vars - 1].psz_name ); + var_Destroy( p_this, p_priv->p_vars[p_priv->i_vars - 1].psz_name ); } - free( p_this->p_vars ); - vlc_mutex_destroy( &p_this->var_lock ); + free( p_priv->p_vars ); + vlc_mutex_destroy( &p_priv->var_lock ); if( p_this->psz_header ) free( p_this->psz_header ); if( p_this->i_object_type == VLC_OBJECT_GLOBAL ) { + libvlc_global_data_t *p_global = (libvlc_global_data_t *)p_this; /* We are the global object ... no need to lock. */ - free( p_this->p_libvlc_global->pp_objects ); - p_this->p_libvlc_global->pp_objects = NULL; - p_this->p_libvlc_global->i_objects--; + free( p_global->pp_objects ); + p_global->pp_objects = NULL; + p_global->i_objects--; vlc_mutex_destroy( &structure_lock ); } else { + libvlc_global_data_t *p_libvlc_global = vlc_global(); int i_index; vlc_mutex_lock( &structure_lock ); /* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's * useless to try and recover anything if pp_objects gets smashed. */ - i_index = FindIndex( p_this, p_this->p_libvlc_global->pp_objects, - p_this->p_libvlc_global->i_objects ); - REMOVE_ELEM( p_this->p_libvlc_global->pp_objects, - p_this->p_libvlc_global->i_objects, i_index ); + i_index = FindIndex( p_this, p_libvlc_global->pp_objects, + p_libvlc_global->i_objects ); + REMOVE_ELEM( p_libvlc_global->pp_objects, + p_libvlc_global->i_objects, i_index ); vlc_mutex_unlock( &structure_lock ); } +#if defined(WIN32) || defined(UNDER_CE) + /* if object has an associated thread, close it now */ + if( p_priv->thread_id.hThread ) + CloseHandle(p_priv->thread_id.hThread); +#endif + vlc_mutex_destroy( &p_this->object_lock ); vlc_cond_destroy( &p_this->object_wait ); + if( p_priv->pipes[0] != -1 ) + close( p_priv->pipes[0] ); + if( p_priv->pipes[1] != -1 ) + close( p_priv->pipes[1] ); /* global is not dynamically allocated by vlc_object_create */ if( p_this->i_object_type != VLC_OBJECT_GLOBAL ) - free( p_this ); + free( p_priv ); +} + + +/** Inter-object signaling */ + +void __vlc_object_lock( vlc_object_t *obj ) +{ + vlc_mutex_lock( &obj->object_lock ); +} + +void __vlc_object_unlock( vlc_object_t *obj ) +{ + vlc_assert_locked( &obj->object_lock ); + vlc_mutex_unlock( &obj->object_lock ); } +/** + * Returns the readable end of a pipe that becomes readable whenever + * an object is signaled. This can be used to wait for VLC object events + * inside select(), poll() loops or frameworks providing an event loop. + * + * Note that the pipe will remain the same for the lifetime of the object. + * DO NOT close it yourself. Ever. + * + * DO NOT try to read from the pipe either: call vlc_object_wait() instead. + * Assuming the pipe is readable, vlc_object_wait() will not block. + * Also note that, as with vlc_object_wait(), there may be spurious wakeups. + * + * @param obj object that would be signaled (object lock MUST hold) + * @return a readable pipe descriptor, or -1 on error. + */ +int vlc_object_waitpipe( vlc_object_t *obj ) +{ + int *pipes = obj->p_internals->pipes; + vlc_assert_locked( &obj->object_lock ); + + if( pipes[1] == -1 ) + { + /* This can only ever happen if someone killed us without locking */ + assert( pipes[0] == -1 ); + +#ifndef WIN32 + if( pipe( pipes ) ) +#else + if( _pipe( pipes, 1, _O_BINARY ) ) +#endif + return -1; + } + + return pipes[0]; +} + + +/** + * Waits for the object to be signaled (using vlc_object_signal()). + * If the object already has a signal pending, this function will return + * immediately. It is asserted that the caller holds the object lock. + * + * @return true if the object is dying and should terminate. + */ +vlc_bool_t __vlc_object_wait( vlc_object_t *obj ) +{ + vlc_assert_locked( &obj->object_lock ); + + int fd = obj->p_internals->pipes[0]; + if( fd != -1 ) + { + if( read( fd, &(char){ 0 }, 1 ) == 0 ) + { + close( fd ); + obj->p_internals->pipes[1] = -1; + } + return obj->b_die; + } + + vlc_cond_wait( &obj->object_wait, &obj->object_lock ); + return obj->b_die; +} + + +/** + * Waits for the object to be signaled (using vlc_object_signal()), or for + * a timer to expire. + * If the object already has a signal pending, this function will return + * immediately. It is asserted that the caller holds the object lock. + * + * @return negative if the object is dying and should terminate, + * positive if the the object has been signaled but is not dying, + * 0 if timeout has been reached. + */ +int __vlc_object_timedwait( vlc_object_t *obj, mtime_t deadline ) +{ + int v; + + vlc_assert_locked( &obj->object_lock ); + v = vlc_cond_timedwait( &obj->object_wait, &obj->object_lock, deadline ); + if( v == 0 ) /* signaled */ + return obj->b_die ? -1 : 1; + return 0; +} + + +/** + * Signals an object for which the lock is held. + */ +void __vlc_object_signal_unlocked( vlc_object_t *obj ) +{ + vlc_assert_locked( &obj->object_lock ); + + int fd = obj->p_internals->pipes[1]; + if( fd != -1 ) + while( write( fd, &(char){ 0 }, 1 ) < 0 ); + + vlc_cond_signal( &obj->object_wait ); +} + + +/** + * Requests termination of an object. + * If the object is LibVLC, also request to terminate all its children. + */ +void __vlc_object_kill( vlc_object_t *p_this ) +{ + vlc_mutex_lock( &p_this->object_lock ); + p_this->b_die = VLC_TRUE; + + if( p_this->i_object_type == VLC_OBJECT_LIBVLC ) + for( int i = 0; i < p_this->i_children ; i++ ) + vlc_object_kill( p_this->pp_children[i] ); + + int fd = p_this->p_internals->pipes[1]; + if( fd != -1 ) + { + close( fd ); /* closing a pipe makes it readable too */ + p_this->p_internals->pipes[1] = -1; + } + + vlc_object_signal_unlocked( p_this ); + vlc_mutex_unlock( &p_this->object_lock ); +} + + /** * find an object given its ID * @@ -437,13 +602,14 @@ void * __vlc_object_get( vlc_object_t *p_this, int i_id ) { int i_max, i_middle; vlc_object_t **pp_objects; + libvlc_global_data_t *p_libvlc_global = vlc_global(); vlc_mutex_lock( &structure_lock ); - pp_objects = p_this->p_libvlc_global->pp_objects; + pp_objects = p_libvlc_global->pp_objects; /* Perform our dichotomy */ - for( i_max = p_this->p_libvlc_global->i_objects - 1 ; ; ) + for( i_max = p_libvlc_global->i_objects - 1 ; ; ) { i_middle = i_max / 2; @@ -464,7 +630,7 @@ void * __vlc_object_get( vlc_object_t *p_this, int i_id ) if( pp_objects[i_middle+1]->i_object_id == i_id ) { vlc_mutex_unlock( &structure_lock ); - pp_objects[i_middle+1]->i_refcount++; + pp_objects[i_middle+1]->p_internals->i_refcount++; return pp_objects[i_middle+1]; } break; @@ -473,7 +639,7 @@ void * __vlc_object_get( vlc_object_t *p_this, int i_id ) else { vlc_mutex_unlock( &structure_lock ); - pp_objects[i_middle]->i_refcount++; + pp_objects[i_middle]->p_internals->i_refcount++; return pp_objects[i_middle]; } @@ -505,7 +671,7 @@ void * __vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode ) /* If we are of the requested type ourselves, don't look further */ if( !(i_mode & FIND_STRICT) && p_this->i_object_type == i_type ) { - p_this->i_refcount++; + p_this->p_internals->i_refcount++; vlc_mutex_unlock( &structure_lock ); return p_this; } @@ -541,23 +707,82 @@ void * __vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode ) /** **************************************************************************** - * increment an object refcount + * find a named object and increment its refcount + ***************************************************************************** + * This function recursively looks for a given object name. i_mode can be one + * of FIND_PARENT, FIND_CHILD or FIND_ANYWHERE. *****************************************************************************/ -void __vlc_object_yield( vlc_object_t *p_this ) +void * __vlc_object_find_name( vlc_object_t *p_this, const char *psz_name, + int i_mode ) { + vlc_object_t *p_found; + vlc_mutex_lock( &structure_lock ); - p_this->i_refcount++; + + /* If have the requested name ourselves, don't look further */ + if( !(i_mode & FIND_STRICT) + && p_this->psz_object_name + && !strcmp( p_this->psz_object_name, psz_name ) ) + { + p_this->p_internals->i_refcount++; + vlc_mutex_unlock( &structure_lock ); + return p_this; + } + + /* Otherwise, recursively look for the object */ + if( (i_mode & 0x000f) == FIND_ANYWHERE ) + { + vlc_object_t *p_root = p_this; + + /* Find the root */ + while( p_root->p_parent != NULL && + p_root != VLC_OBJECT( p_this->p_libvlc ) ) + { + p_root = p_root->p_parent; + } + + p_found = FindObjectName( p_root, psz_name, + (i_mode & ~0x000f)|FIND_CHILD ); + if( p_found == NULL && p_root != VLC_OBJECT( p_this->p_libvlc ) ) + { + p_found = FindObjectName( VLC_OBJECT( p_this->p_libvlc ), + psz_name, (i_mode & ~0x000f)|FIND_CHILD ); + } + } + else + { + p_found = FindObjectName( p_this, psz_name, i_mode ); + } + vlc_mutex_unlock( &structure_lock ); + + return p_found; } /** **************************************************************************** + * increment an object refcount + *****************************************************************************/ +void __vlc_object_yield( vlc_object_t *p_this ) +{ + vlc_mutex_lock( &structure_lock ); + p_this->p_internals->i_refcount++; + vlc_mutex_unlock( &structure_lock ); +} + +static inline void Release( vlc_object_t *obj ) +{ + assert( obj->p_internals->i_refcount > 0 ); + obj->p_internals->i_refcount--; +} + +/***************************************************************************** * decrement an object refcount *****************************************************************************/ void __vlc_object_release( vlc_object_t *p_this ) { vlc_mutex_lock( &structure_lock ); - p_this->i_refcount--; + Release( p_this ); vlc_mutex_unlock( &structure_lock ); } @@ -570,6 +795,8 @@ void __vlc_object_release( vlc_object_t *p_this ) *****************************************************************************/ void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent ) { + if( !p_this ) return; + vlc_mutex_lock( &structure_lock ); /* Attach the parent to its child */ @@ -580,7 +807,7 @@ void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent ) p_parent->i_children, p_this ); /* Climb up the tree to see whether we are connected with the root */ - if( p_parent->b_attached ) + if( p_parent->p_internals->b_attached ) { SetAttachment( p_this, VLC_TRUE ); } @@ -596,6 +823,8 @@ void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent ) *****************************************************************************/ void __vlc_object_detach( vlc_object_t *p_this ) { + if( !p_this ) return; + vlc_mutex_lock( &structure_lock ); if( !p_this->p_parent ) { @@ -605,13 +834,14 @@ void __vlc_object_detach( vlc_object_t *p_this ) } /* Climb up the tree to see whether we are connected with the root */ - if( p_this->p_parent->b_attached ) + if( p_this->p_parent->p_internals->b_attached ) { SetAttachment( p_this, VLC_FALSE ); } DetachObject( p_this ); vlc_mutex_unlock( &structure_lock ); + p_this = NULL; } /** @@ -626,6 +856,7 @@ vlc_list_t * __vlc_list_find( vlc_object_t *p_this, int i_type, int i_mode ) vlc_list_t *p_list; vlc_object_t **pp_current, **pp_end; int i_count = 0, i_index = 0; + libvlc_global_data_t *p_libvlc_global = vlc_global(); vlc_mutex_lock( &structure_lock ); @@ -633,12 +864,12 @@ vlc_list_t * __vlc_list_find( vlc_object_t *p_this, int i_type, int i_mode ) switch( i_mode & 0x000f ) { case FIND_ANYWHERE: - pp_current = p_this->p_libvlc_global->pp_objects; - pp_end = pp_current + p_this->p_libvlc_global->i_objects; + pp_current = p_libvlc_global->pp_objects; + pp_end = pp_current + p_libvlc_global->i_objects; for( ; pp_current < pp_end ; pp_current++ ) { - if( (*pp_current)->b_attached + if( (*pp_current)->p_internals->b_attached && (*pp_current)->i_object_type == i_type ) { i_count++; @@ -646,11 +877,11 @@ vlc_list_t * __vlc_list_find( vlc_object_t *p_this, int i_type, int i_mode ) } p_list = NewList( i_count ); - pp_current = p_this->p_libvlc_global->pp_objects; + pp_current = p_libvlc_global->pp_objects; for( ; pp_current < pp_end ; pp_current++ ) { - if( (*pp_current)->b_attached + if( (*pp_current)->p_internals->b_attached && (*pp_current)->i_object_type == i_type ) { ListReplace( p_list, *pp_current, i_index ); @@ -696,61 +927,168 @@ vlc_list_t * __vlc_list_find( vlc_object_t *p_this, int i_type, int i_mode ) static int DumpCommand( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ) { - if( *psz_cmd == 't' ) + libvlc_global_data_t *p_libvlc_global = vlc_global(); + + (void)oldval; (void)p_data; + if( *psz_cmd == 'l' ) + { + vlc_mutex_lock( &structure_lock ); + + vlc_object_t **pp_current, **pp_end; + + pp_current = p_libvlc_global->pp_objects; + pp_end = pp_current + p_libvlc_global->i_objects; + + for( ; pp_current < pp_end ; pp_current++ ) + { + if( (*pp_current)->p_internals->b_attached ) + { + PrintObject( *pp_current, "" ); + } + else + { + printf( " o %.8i %s (not attached)\n", + (*pp_current)->i_object_id, + (*pp_current)->psz_object_type ); + } + } + + vlc_mutex_unlock( &structure_lock ); + } + else { - char psz_foo[2 * MAX_DUMPSTRUCTURE_DEPTH + 1]; - vlc_object_t *p_object; + vlc_object_t *p_object = NULL; if( *newval.psz_string ) { - p_object = vlc_object_get( p_this, atoi(newval.psz_string) ); + char *end; + int i_id = strtol( newval.psz_string, &end, 0 ); + if( end != newval.psz_string ) + p_object = vlc_object_get( p_this, i_id ); + else + { + /* try using the object's name to find it */ + vlc_object_t *p_libvlc = vlc_object_get( p_this, 1 ); + if( p_libvlc ) + { + /* Look in p_libvlc's children tree */ + p_object = vlc_object_find_name( p_libvlc, + newval.psz_string, + FIND_CHILD ); + vlc_object_release( p_libvlc ); + } + if( !p_object ) + { + /* If it's not in libvlc, look in libvlc_global (== p_this) */ + p_object = vlc_object_find_name( p_this, + newval.psz_string, + FIND_CHILD ); + } + } if( !p_object ) { return VLC_ENOOBJ; } } - else - { - p_object = p_this->p_libvlc ? VLC_OBJECT(p_this->p_libvlc) : p_this; - } vlc_mutex_lock( &structure_lock ); - psz_foo[0] = '|'; - DumpStructure( p_object, 0, psz_foo ); + if( *psz_cmd == 't' ) + { + char psz_foo[2 * MAX_DUMPSTRUCTURE_DEPTH + 1]; - vlc_mutex_unlock( &structure_lock ); + if( !p_object ) + p_object = p_this->p_libvlc ? VLC_OBJECT(p_this->p_libvlc) : p_this; - if( *newval.psz_string ) - { - vlc_object_release( p_this ); + psz_foo[0] = '|'; + DumpStructure( p_object, 0, psz_foo ); } - } - else if( *psz_cmd == 'l' ) - { - vlc_object_t **pp_current, **pp_end; + else if( *psz_cmd == 'v' ) + { + int i; - vlc_mutex_lock( &structure_lock ); + if( !p_object ) + p_object = p_this->p_libvlc ? VLC_OBJECT(p_this->p_libvlc) : p_this; - pp_current = p_this->p_libvlc_global->pp_objects; - pp_end = pp_current + p_this->p_libvlc_global->i_objects; + PrintObject( p_object, "" ); - for( ; pp_current < pp_end ; pp_current++ ) - { - if( (*pp_current)->b_attached ) + if( !p_object->p_internals->i_vars ) + printf( " `-o No variables\n" ); + for( i = 0; i < p_object->p_internals->i_vars; i++ ) { - PrintObject( *pp_current, "" ); - } - else - { - printf( " o %.8i %s (not attached)\n", - (*pp_current)->i_object_id, - (*pp_current)->psz_object_type ); + variable_t *p_var = p_object->p_internals->p_vars + i; + + const char *psz_type = "unknown"; + switch( p_var->i_type & VLC_VAR_TYPE ) + { +#define MYCASE( type, nice ) \ + case VLC_VAR_ ## type: \ + psz_type = nice; \ + break; + MYCASE( VOID, "void" ); + MYCASE( BOOL, "bool" ); + MYCASE( INTEGER, "integer" ); + MYCASE( HOTKEY, "hotkey" ); + MYCASE( STRING, "string" ); + MYCASE( MODULE, "module" ); + MYCASE( FILE, "file" ); + MYCASE( DIRECTORY, "directory" ); + MYCASE( VARIABLE, "variable" ); + MYCASE( FLOAT, "float" ); + MYCASE( TIME, "time" ); + MYCASE( ADDRESS, "address" ); + MYCASE( MUTEX, "mutex" ); + MYCASE( LIST, "list" ); +#undef MYCASE + } + printf( " %c-o \"%s\" (%s", + i + 1 == p_object->p_internals->i_vars ? '`' : '|', + p_var->psz_name, psz_type ); + if( p_var->psz_text ) + printf( ", %s", p_var->psz_text ); + printf( ")" ); + if( p_var->i_type & VLC_VAR_ISCOMMAND ) + printf( ", command" ); + if( p_var->i_entries ) + printf( ", %d callbacks", p_var->i_entries ); + switch( p_var->i_type & 0x00f0 ) + { + case VLC_VAR_VOID: + case VLC_VAR_MUTEX: + break; + case VLC_VAR_BOOL: + printf( ": %s", p_var->val.b_bool ? "true" : "false" ); + break; + case VLC_VAR_INTEGER: + printf( ": %d", p_var->val.i_int ); + break; + case VLC_VAR_STRING: + printf( ": \"%s\"", p_var->val.psz_string ); + break; + case VLC_VAR_FLOAT: + printf( ": %f", p_var->val.f_float ); + break; + case VLC_VAR_TIME: + printf( ": " I64Fi, (int64_t)p_var->val.i_time ); + break; + case VLC_VAR_ADDRESS: + printf( ": %p", p_var->val.p_address ); + break; + case VLC_VAR_LIST: + printf( ": TODO" ); + break; + } + printf( "\n" ); } } vlc_mutex_unlock( &structure_lock ); + + if( *newval.psz_string ) + { + vlc_object_release( p_object ); + } } return VLC_SUCCESS; @@ -766,14 +1104,12 @@ void vlc_list_release( vlc_list_t *p_list ) { int i_index; + vlc_mutex_lock( &structure_lock ); for( i_index = 0; i_index < p_list->i_count; i_index++ ) { - vlc_mutex_lock( &structure_lock ); - - p_list->p_values[i_index].p_object->i_refcount--; - - vlc_mutex_unlock( &structure_lock ); + Release( p_list->p_values[i_index].p_object ); } + vlc_mutex_unlock( &structure_lock ); free( p_list->p_values ); free( p_list ); @@ -834,7 +1170,7 @@ static vlc_object_t * FindObject( vlc_object_t *p_this, int i_type, int i_mode ) { if( p_tmp->i_object_type == i_type ) { - p_tmp->i_refcount++; + p_tmp->p_internals->i_refcount++; return p_tmp; } else @@ -850,7 +1186,7 @@ static vlc_object_t * FindObject( vlc_object_t *p_this, int i_type, int i_mode ) p_tmp = p_this->pp_children[i]; if( p_tmp->i_object_type == i_type ) { - p_tmp->i_refcount++; + p_tmp->p_internals->i_refcount++; return p_tmp; } else if( p_tmp->i_children ) @@ -872,6 +1208,61 @@ static vlc_object_t * FindObject( vlc_object_t *p_this, int i_type, int i_mode ) return NULL; } +static vlc_object_t * FindObjectName( vlc_object_t *p_this, + const char *psz_name, + int i_mode ) +{ + int i; + vlc_object_t *p_tmp; + + switch( i_mode & 0x000f ) + { + case FIND_PARENT: + p_tmp = p_this->p_parent; + if( p_tmp ) + { + if( p_tmp->psz_object_name + && !strcmp( p_tmp->psz_object_name, psz_name ) ) + { + p_tmp->p_internals->i_refcount++; + return p_tmp; + } + else + { + return FindObjectName( p_tmp, psz_name, i_mode ); + } + } + break; + + case FIND_CHILD: + for( i = p_this->i_children; i--; ) + { + p_tmp = p_this->pp_children[i]; + if( p_tmp->psz_object_name + && !strcmp( p_tmp->psz_object_name, psz_name ) ) + { + p_tmp->p_internals->i_refcount++; + return p_tmp; + } + else if( p_tmp->i_children ) + { + p_tmp = FindObjectName( p_tmp, psz_name, i_mode ); + if( p_tmp ) + { + return p_tmp; + } + } + } + break; + + case FIND_ANYWHERE: + /* Handled in vlc_object_find */ + break; + } + + return NULL; +} + static void DetachObject( vlc_object_t *p_this ) { vlc_object_t *p_parent = p_this->p_parent; @@ -920,19 +1311,20 @@ static void SetAttachment( vlc_object_t *p_this, vlc_bool_t b_attached ) SetAttachment( p_this->pp_children[i_index], b_attached ); } - p_this->b_attached = b_attached; + p_this->p_internals->b_attached = b_attached; } static void PrintObject( vlc_object_t *p_this, const char *psz_prefix ) { - char psz_children[20], psz_refcount[20], psz_thread[20], psz_name[50]; + char psz_children[20], psz_refcount[20], psz_thread[30], psz_name[50], + psz_parent[20]; psz_name[0] = '\0'; if( p_this->psz_object_name ) { - snprintf( psz_name, 50, " \"%s\"", p_this->psz_object_name ); - psz_name[48] = '\"'; - psz_name[49] = '\0'; + snprintf( psz_name, 49, " \"%s\"", p_this->psz_object_name ); + if( psz_name[48] ) + psz_name[48] = '\"'; } psz_children[0] = '\0'; @@ -944,29 +1336,32 @@ static void PrintObject( vlc_object_t *p_this, const char *psz_prefix ) strcpy( psz_children, ", 1 child" ); break; default: - snprintf( psz_children, 20, - ", %i children", p_this->i_children ); - psz_children[19] = '\0'; + snprintf( psz_children, 19, ", %i children", p_this->i_children ); break; } psz_refcount[0] = '\0'; - if( p_this->i_refcount ) - { - snprintf( psz_refcount, 20, ", refcount %i", p_this->i_refcount ); - psz_refcount[19] = '\0'; - } + if( p_this->p_internals->i_refcount > 0 ) + snprintf( psz_refcount, 19, ", refcount %u", + p_this->p_internals->i_refcount ); psz_thread[0] = '\0'; - if( p_this->b_thread ) - { - snprintf( psz_thread, 20, " (thread %d)", (int)p_this->thread_id ); - psz_thread[19] = '\0'; - } + if( p_this->p_internals->b_thread ) + snprintf( psz_thread, 29, " (thread %u)", +#if defined(WIN32) || defined(UNDER_CE) + (unsigned)p_this->p_internals->thread_id.id ); +#else + (unsigned)p_this->p_internals->thread_id ); +#endif + + psz_parent[0] = '\0'; + if( p_this->p_parent ) + snprintf( psz_parent, 19, ", parent %i", p_this->p_parent->i_object_id ); - printf( " %so %.8i %s%s%s%s%s\n", psz_prefix, + printf( " %so %.8i %s%s%s%s%s%s\n", psz_prefix, p_this->i_object_id, p_this->psz_object_type, - psz_name, psz_thread, psz_refcount, psz_children ); + psz_name, psz_thread, psz_refcount, psz_children, + psz_parent ); } static void DumpStructure( vlc_object_t *p_this, int i_level, char *psz_foo ) @@ -1047,7 +1442,7 @@ static void ListReplace( vlc_list_t *p_list, vlc_object_t *p_object, return; } - p_object->i_refcount++; + p_object->p_internals->i_refcount++; p_list->p_values[i_index].p_object = p_object; @@ -1069,7 +1464,7 @@ static void ListReplace( vlc_list_t *p_list, vlc_object_t *p_object, return; } - p_object->i_refcount++; + p_object->p_internals->i_refcount++; p_list->p_values[p_list->i_count].p_object = p_object; p_list->i_count++;