* objects.c: vlc_object_t handling
*****************************************************************************
* Copyright (C) 2004-2008 the VideoLAN team
+ * Copyright (C) 2006-2010 RĂ©mi Denis-Courmont
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
# include <unistd.h>
#else
# include <io.h>
-# include <fcntl.h>
-# include <errno.h> /* ENOSYS */
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# undef read
+# define read( a, b, c ) recv (a, b, c, 0)
+# undef write
+# define write( a, b, c ) send (a, b, c, 0)
+# undef close
+# define close( a ) closesocket (a)
#endif
+#include <search.h>
#include <limits.h>
#include <assert.h>
#if defined (HAVE_SYS_EVENTFD_H)
# include <sys/eventfd.h>
+# ifndef EFD_CLOEXEC
+# define EFD_CLOEXEC 0
+# warning EFD_CLOEXEC missing. Consider updating libc.
+# endif
#endif
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 PrintObject ( vlc_object_t *, const char * );
-static void DumpStructure ( vlc_object_t *, int, char * );
+static vlc_object_t * FindParent ( vlc_object_t *, int );
+static vlc_object_t * FindChild ( vlc_object_internals_t *, int );
+static vlc_object_t * FindParentName( vlc_object_t *, const char * );
+static vlc_object_t * FindChildName ( vlc_object_internals_t *, const char * );
+static void PrintObject( vlc_object_internals_t *, const char * );
+static void DumpStructure( vlc_object_internals_t *, unsigned, char * );
static vlc_list_t * NewList ( int );
-static void ListReplace ( vlc_list_t *, vlc_object_t *, int );
-/*static void ListAppend ( vlc_list_t *, vlc_object_t * );*/
-static int CountChildren ( vlc_object_t *, int );
-static void ListChildren ( vlc_list_t *, vlc_object_t *, int );
static void vlc_object_destroy( vlc_object_t *p_this );
-static void vlc_object_detach_unlocked (vlc_object_t *p_this);
-#ifndef NDEBUG
-static void vlc_object_dump( vlc_object_t *p_this );
-#endif
/*****************************************************************************
* Local structure lock
vlc_mutex_unlock (&(libvlc_priv (p_libvlc)->structure_lock));
}
-void *__vlc_custom_create( vlc_object_t *p_this, size_t i_size,
- int i_type, const char *psz_type )
+#undef vlc_custom_create
+void *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;
p_priv->psz_name = NULL;
p_new->b_die = false;
- p_new->b_error = false;
p_new->b_force = false;
p_new->psz_header = NULL;
p_new->i_flags = p_this->i_flags
& (OBJECT_FLAGS_NODBG|OBJECT_FLAGS_QUIET|OBJECT_FLAGS_NOINTERACT);
- p_priv->p_vars = calloc( 16, sizeof( variable_t ) );
-
- if( !p_priv->p_vars )
- {
- free( p_priv );
- return NULL;
- }
+ p_priv->var_root = NULL;
if( p_this == NULL )
{
libvlc_int_t *self = (libvlc_int_t*)p_new;
p_new->p_libvlc = self;
vlc_mutex_init (&(libvlc_priv (self)->structure_lock));
- p_this = p_priv->next = p_priv->prev = p_new;
+ p_this = p_new;
}
else
p_new->p_libvlc = p_this->p_libvlc;
p_priv->pf_destructor = NULL;
p_priv->b_thread = false;
p_new->p_parent = NULL;
- p_priv->pp_children = NULL;
- p_priv->i_children = 0;
+ p_priv->first = NULL;
/* Initialize mutexes and condvars */
vlc_mutex_init( &p_priv->var_lock );
vlc_cond_init( &p_priv->var_wait );
p_priv->pipes[0] = p_priv->pipes[1] = -1;
- p_priv->next = p_this;
- libvlc_lock (p_new->p_libvlc);
- p_priv->prev = vlc_internals (p_this)->prev;
- vlc_internals (p_this)->prev = p_new;
- vlc_internals (p_priv->prev)->next = p_new;
- libvlc_unlock (p_new->p_libvlc);
-
if (p_new == VLC_OBJECT(p_new->p_libvlc))
{ /* TODO: should be in src/libvlc.c */
int canc = vlc_savecancel ();
- 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 );
return p_new;
}
-
+#undef vlc_object_create
/**
* 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).
+ * @param i_size object byte size
*
* @return the new object, or NULL on error.
*/
-void * __vlc_object_create( vlc_object_t *p_this, int i_type )
+void *vlc_object_create( vlc_object_t *p_this, size_t i_size )
{
- const char * psz_type;
- size_t i_size;
-
- switch( i_type )
- {
- case VLC_OBJECT_DECODER:
- i_size = sizeof(decoder_t);
- psz_type = "decoder";
- break;
- case VLC_OBJECT_AOUT:
- i_size = sizeof(aout_instance_t);
- psz_type = "audio output";
- break;
- default:
- assert( i_type > 0 ); /* unknown type?! */
- i_size = i_type;
- i_type = VLC_OBJECT_GENERIC;
- psz_type = "generic";
- break;
- }
-
- return vlc_custom_create( p_this, i_size, i_type, psz_type );
+ return vlc_custom_create( p_this, i_size, VLC_OBJECT_GENERIC, "generic" );
}
-
+#undef vlc_object_set_destructor
/**
****************************************************************************
* Set the destructor of a vlc object
* when the object is destroyed when the its refcount reaches 0.
* (It is called by the internal function vlc_object_destroy())
*****************************************************************************/
-void __vlc_object_set_destructor( vlc_object_t *p_this,
- vlc_destructor_t pf_destructor )
+void vlc_object_set_destructor( vlc_object_t *p_this,
+ vlc_destructor_t pf_destructor )
{
vlc_object_internals_t *p_priv = vlc_internals(p_this );
vlc_spin_unlock( &p_priv->ref_spin );
}
+static vlc_mutex_t name_lock = VLC_STATIC_MUTEX;
+
#undef vlc_object_set_name
int vlc_object_set_name(vlc_object_t *obj, const char *name)
{
vlc_object_internals_t *priv = vlc_internals(obj);
+ char *newname = name ? strdup (name) : NULL;
+ char *oldname;
- /* Object must be named before it is attached (or never) */
- assert(obj->p_parent == NULL);
- assert(priv->i_children == 0);
+ vlc_mutex_lock (&name_lock);
+ oldname = priv->psz_name;
+ priv->psz_name = newname;
+ vlc_mutex_unlock (&name_lock);
- free(priv->psz_name);
- priv->psz_name = name ? strdup(name) : NULL;
+ free (oldname);
return (priv->psz_name || !name) ? VLC_SUCCESS : VLC_ENOMEM;
}
#undef vlc_object_get_name
-const char *vlc_object_get_name(const vlc_object_t *obj)
+char *vlc_object_get_name(const vlc_object_t *obj)
{
vlc_object_internals_t *priv = vlc_internals(obj);
+ char *name;
+
+ vlc_mutex_lock (&name_lock);
+ name = priv->psz_name ? strdup (priv->psz_name) : NULL;
+ vlc_mutex_unlock (&name_lock);
- return priv->psz_name;
+ return name;
}
/**
{
vlc_object_internals_t *p_priv = vlc_internals( p_this );
- /* Objects are always detached beforehand */
- assert( !p_this->p_parent );
-
/* Send a kill to the object's thread if applicable */
vlc_object_kill( p_this );
/* Any thread must have been cleaned up at this point. */
assert( !p_priv->b_thread );
- /* Destroy the associated variables, starting from the end so that
- * no memmove calls have to be done. */
- while( p_priv->i_vars )
- {
- var_Destroy( p_this, p_priv->p_vars[p_priv->i_vars - 1].psz_name );
- }
+ /* Destroy the associated variables. */
+ var_DestroyAll( p_this );
- free( p_priv->p_vars );
vlc_cond_destroy( &p_priv->var_wait );
vlc_mutex_destroy( &p_priv->var_lock );
#ifdef WIN32
-# include <winsock2.h>
-# include <ws2tcpip.h>
-
/**
* select()-able pipes emulated using Winsock
*/
closesocket (c);
return -1;
}
-
-#undef read
-#define read( a, b, c ) recv (a, b, c, 0)
-#undef write
-#define write( a, b, c ) send (a, b, c, 0)
-#undef close
-#define close( a ) closesocket (a)
#endif /* WIN32 */
static vlc_mutex_t pipe_lock = VLC_STATIC_MUTEX;
/* This can only ever happen if someone killed us without locking: */
assert (internals->pipes[1] == -1);
-#ifdef HAVE_EVENTFD
- internals->pipes[0] = internals->pipes[1] = eventfd (0, 0);
+ /* pipe() is not a cancellation point, but write() is and eventfd() is
+ * unspecified (not in POSIX). */
+ int canc = vlc_savecancel ();
+#if defined (HAVE_SYS_EVENTFD_H)
+ internals->pipes[0] = internals->pipes[1] = eventfd (0, EFD_CLOEXEC);
if (internals->pipes[0] == -1)
#endif
{
msg_Dbg (obj, "waitpipe: object already dying");
write (internals->pipes[1], &(uint64_t){ 1 }, sizeof (uint64_t));
}
+ vlc_restorecancel (canc);
}
vlc_mutex_unlock (&pipe_lock);
return internals->pipes[0];
}
-
+#undef vlc_object_kill
/**
* Requests termination of an object, cancels the object thread, and make the
* object wait pipe (if it exists) readable. Not a cancellation point.
*/
-void __vlc_object_kill( vlc_object_t *p_this )
+void vlc_object_kill( vlc_object_t *p_this )
{
vlc_object_internals_t *priv = vlc_internals( p_this );
int fd = -1;
}
}
-
+#undef vlc_object_find
/*****************************************************************************
* find a typed object and increment its refcount
*****************************************************************************
* This function recursively looks for a given object type. i_mode can be one
* of FIND_PARENT, FIND_CHILD or FIND_ANYWHERE.
*****************************************************************************/
-void * __vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode )
+void * vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode )
{
vlc_object_t *p_found;
/* If we are of the requested type ourselves, don't look further */
- if( !(i_mode & FIND_STRICT)
- && vlc_internals (p_this)->i_object_type == i_type )
+ if( vlc_internals (p_this)->i_object_type == i_type )
{
vlc_object_hold( p_this );
return p_this;
}
/* Otherwise, recursively look for the object */
- if ((i_mode & 0x000f) == FIND_ANYWHERE)
- return vlc_object_find (p_this->p_libvlc, i_type,
- (i_mode & ~0x000f)|FIND_CHILD);
+ if (i_mode == FIND_ANYWHERE)
+ return vlc_object_find (VLC_OBJECT(p_this->p_libvlc), i_type, FIND_CHILD);
+
+ switch (i_type)
+ {
+ case VLC_OBJECT_VOUT:
+ case VLC_OBJECT_AOUT:
+ break;
+ case VLC_OBJECT_INPUT:
+ /* input can only be accessed like this from children,
+ * otherwise we could not promise that it is initialized */
+ if (i_mode != FIND_PARENT)
+ return NULL;
+ break;
+ default:
+ return NULL;
+ }
libvlc_lock (p_this->p_libvlc);
- p_found = FindObject( p_this, i_type, i_mode );
+ switch (i_mode)
+ {
+ case FIND_PARENT:
+ p_found = FindParent (p_this, i_type);
+ break;
+ case FIND_CHILD:
+ p_found = FindChild (vlc_internals (p_this), i_type);
+ break;
+ default:
+ assert (0);
+ }
libvlc_unlock (p_this->p_libvlc);
return p_found;
}
static int objnamecmp(const vlc_object_t *obj, const char *name)
{
- if (!vlc_object_get_name(obj))
+ char *objname = vlc_object_get_name(obj);
+ if (objname == NULL)
return INT_MIN;
- return strcmp( vlc_object_get_name(obj), name );
+
+ int ret = strcmp (objname, name);
+ free (objname);
+ return ret;
}
#undef vlc_object_find_name
* Use a libvlc address variable instead for that sort of things! */
msg_Warn( p_this, "%s(%s) is not safe!", __func__, psz_name );
/* If have the requested name ourselves, don't look further */
- if( !(i_mode & FIND_STRICT) && !objnamecmp(p_this, psz_name) )
+ if( !objnamecmp(p_this, psz_name) )
{
vlc_object_hold( p_this );
return p_this;
}
- libvlc_lock (p_this->p_libvlc);
-
/* 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;
- }
+ if (i_mode == FIND_ANYWHERE)
+ return vlc_object_find_name (VLC_OBJECT(p_this->p_libvlc), psz_name,
+ FIND_CHILD);
- 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
+ libvlc_lock (p_this->p_libvlc);
+ vlc_mutex_lock (&name_lock);
+ switch (i_mode)
{
- p_found = FindObjectName( p_this, psz_name, i_mode );
+ case FIND_PARENT:
+ p_found = FindParentName (p_this, psz_name);
+ break;
+ case FIND_CHILD:
+ p_found = FindChildName (vlc_internals (p_this), psz_name);
+ break;
+ default:
+ assert (0);
}
-
+ vlc_mutex_unlock (&name_lock);
libvlc_unlock (p_this->p_libvlc);
return p_found;
}
+#undef vlc_object_hold
/**
* Increment an object reference counter.
*/
-void * __vlc_object_hold( vlc_object_t *p_this )
+void * vlc_object_hold( vlc_object_t *p_this )
{
vlc_object_internals_t *internals = vlc_internals( p_this );
return p_this;
}
+#undef vlc_object_release
/*****************************************************************************
* Decrement an object refcount
* And destroy the object if its refcount reach zero.
*****************************************************************************/
-void __vlc_object_release( vlc_object_t *p_this )
+void vlc_object_release( vlc_object_t *p_this )
{
vlc_object_internals_t *internals = vlc_internals( p_this );
vlc_object_t *parent = NULL;
if( b_should_destroy )
{
+ /* Detach from parent to protect against FIND_CHILDREN */
parent = p_this->p_parent;
-
-#ifndef NDEBUG
- if( VLC_OBJECT(p_this->p_libvlc) == p_this )
+ if (likely(parent))
{
- /* Test for leaks */
- vlc_object_t *leaked = internals->next;
- while( leaked != p_this )
- {
- /* We are leaking this object */
- fprintf( stderr,
- "ERROR: leaking object (%p, type:%s, name:%s)\n",
- leaked, leaked->psz_object_type,
- vlc_object_get_name(leaked) );
- /* Dump object to ease debugging */
- vlc_object_dump( leaked );
- fflush(stderr);
- leaked = vlc_internals (leaked)->next;
- }
-
- if( internals->next != p_this )
- /* Dump libvlc object to ease debugging */
- vlc_object_dump( p_this );
+ /* Unlink */
+ if (internals->prev != NULL)
+ internals->prev->next = internals->next;
+ else
+ vlc_internals(parent)->first = internals->next;
+ if (internals->next != NULL)
+ internals->next->prev = internals->prev;
}
-#endif
- /* Remove the object from object list
- * so that it cannot be encountered by vlc_object_get() */
- vlc_internals (internals->next)->prev = internals->prev;
- vlc_internals (internals->prev)->next = internals->next;
-
- if (parent)
- /* Detach from parent to protect against FIND_CHILDREN */
- vlc_object_detach_unlocked (p_this);
/* We have no children */
- assert (internals->i_children == 0);
+ assert (internals->first == NULL);
}
libvlc_unlock (p_this->p_libvlc);
}
}
+#undef vlc_object_attach
/**
****************************************************************************
* attach object to a parent object
*****************************************************************************
* This function sets p_this as a child of p_parent, and p_parent as a parent
- * of p_this. This link can be undone using vlc_object_detach.
+ * of p_this.
*****************************************************************************/
-void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent )
+void vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent )
{
if( !p_this ) return;
+ vlc_object_internals_t *pap = vlc_internals (p_parent);
+ vlc_object_internals_t *priv = vlc_internals (p_this);
+
+ priv->prev = NULL;
vlc_object_hold (p_parent);
libvlc_lock (p_this->p_libvlc);
/* Attach the parent to its child */
- assert (!p_this->p_parent);
+ assert (p_this->p_parent == NULL);
p_this->p_parent = p_parent;
/* Attach the child to its parent */
- vlc_object_internals_t *priv = vlc_internals( p_parent );
- INSERT_ELEM( priv->pp_children, priv->i_children, priv->i_children,
- p_this );
+ priv->next = pap->first;
+ if (priv->next != NULL)
+ priv->next->prev = priv;
+ pap->first = priv;
libvlc_unlock (p_this->p_libvlc);
}
-static void vlc_object_detach_unlocked (vlc_object_t *p_this)
+#undef vlc_list_children
+/**
+ * Gets the list of children of an objects, and increment their reference
+ * count.
+ * @return a list (possibly empty) or NULL in case of error.
+ */
+vlc_list_t *vlc_list_children( vlc_object_t *obj )
{
- if (p_this->p_parent == NULL)
- return;
-
- vlc_object_internals_t *priv = vlc_internals( p_this->p_parent );
-
- int i_index, i;
-
- /* Remove p_this's parent */
- p_this->p_parent = NULL;
+ vlc_list_t *l;
+ vlc_object_internals_t *priv;
+ unsigned count = 0;
- /* Remove all of p_parent's children which are p_this */
- for( i_index = priv->i_children ; i_index-- ; )
+ libvlc_lock (obj->p_libvlc);
+ for (priv = vlc_internals (obj)->first; priv; priv = priv->next)
+ count++;
+ l = NewList (count);
+ if (likely(l != NULL))
{
- if( priv->pp_children[i_index] == p_this )
- {
- priv->i_children--;
- for( i = i_index ; i < priv->i_children ; i++ )
- priv->pp_children[i] = priv->pp_children[i+1];
- }
- }
+ unsigned i = 0;
- if( priv->i_children )
- {
- vlc_object_t **pp_children = (vlc_object_t **)
- realloc( priv->pp_children,
- priv->i_children * sizeof(vlc_object_t *) );
- if( pp_children )
- priv->pp_children = pp_children;
- }
- else
- {
- /* Special case - don't realloc() to zero to avoid leaking */
- free( priv->pp_children );
- priv->pp_children = NULL;
+ for (priv = vlc_internals (obj)->first; priv; priv = priv->next)
+ l->p_values[i++].p_object = vlc_object_hold (vlc_externals (priv));
}
+ libvlc_unlock (obj->p_libvlc);
+ return l;
}
-
-/**
- ****************************************************************************
- * detach object from its parent
- *****************************************************************************
- * This function removes all links between an object and its parent.
- *****************************************************************************/
-void __vlc_object_detach( vlc_object_t *p_this )
+static void DumpVariable (const void *data, const VISIT which, const int depth)
{
- vlc_object_t *p_parent;
- if( !p_this ) return;
-
- libvlc_lock (p_this->p_libvlc);
- p_parent = p_this->p_parent;
- if (p_parent)
- vlc_object_detach_unlocked( p_this );
- libvlc_unlock (p_this->p_libvlc);
-
- if (p_parent)
- vlc_object_release (p_parent);
-}
+ if (which != postorder && which != leaf)
+ return;
+ (void) depth;
+ const variable_t *p_var = *(const variable_t **)data;
+ const char *psz_type = "unknown";
-/**
- ****************************************************************************
- * find a list typed objects and increment their refcount
- *****************************************************************************
- * This function recursively looks for a given object type. i_mode can be one
- * of FIND_PARENT, FIND_CHILD or FIND_ANYWHERE.
- *****************************************************************************/
-vlc_list_t * vlc_list_find( vlc_object_t *p_this, int i_type, int i_mode )
-{
- vlc_list_t *p_list;
- int i_count = 0;
-
- /* Look for the objects */
- switch( i_mode & 0x000f )
+ switch( p_var->i_type & VLC_VAR_TYPE )
{
- case FIND_ANYWHERE:
- return vlc_list_find (VLC_OBJECT(p_this->p_libvlc), i_type, FIND_CHILD);
-
- case FIND_CHILD:
- libvlc_lock (p_this->p_libvlc);
- i_count = CountChildren( p_this, i_type );
- p_list = NewList( i_count );
-
- /* Check allocation was successful */
- if( p_list->i_count != i_count )
- {
- libvlc_unlock (p_this->p_libvlc);
- p_list->i_count = 0;
+#define MYCASE( type, nice ) \
+ case VLC_VAR_ ## type: \
+ psz_type = nice; \
break;
- }
-
- p_list->i_count = 0;
- ListChildren( p_list, p_this, i_type );
- libvlc_unlock (p_this->p_libvlc);
- break;
-
- default:
- msg_Err( p_this, "unimplemented!" );
- p_list = NewList( 0 );
- 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( COORDS, "coords" );
+ MYCASE( ADDRESS, "address" );
+ MYCASE( MUTEX, "mutex" );
+#undef MYCASE
}
-
- return p_list;
-}
-
-/**
- * Gets the list of children of an objects, and increment their reference
- * count.
- * @return a list (possibly empty) or NULL in case of error.
- */
-vlc_list_t *__vlc_list_children( vlc_object_t *obj )
-{
- vlc_list_t *l;
- vlc_object_internals_t *priv = vlc_internals( obj );
-
- libvlc_lock (obj->p_libvlc);
- l = NewList( priv->i_children );
- for (int i = 0; i < l->i_count; i++)
- {
- vlc_object_hold( priv->pp_children[i] );
- l->p_values[i].p_object = priv->pp_children[i];
+ printf( " *-o \"%s\" (%s", p_var->psz_name, psz_type );
+ if( p_var->psz_text )
+ printf( ", %s", p_var->psz_text );
+ fputc( ')', stdout );
+ if( p_var->i_type & VLC_VAR_HASCHOICE )
+ fputs( ", has choices", stdout );
+ if( p_var->i_type & VLC_VAR_ISCOMMAND )
+ fputs( ", command", stdout );
+ if( p_var->i_entries )
+ printf( ", %d callbacks", p_var->i_entries );
+ switch( p_var->i_type & VLC_VAR_CLASS )
+ {
+ 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( ": %"PRId64, 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( ": %"PRIi64, (int64_t)p_var->val.i_time );
+ break;
+ case VLC_VAR_COORDS:
+ printf( ": %"PRId32"x%"PRId32,
+ p_var->val.coords.x, p_var->val.coords.y );
+ break;
+ case VLC_VAR_ADDRESS:
+ printf( ": %p", p_var->val.p_address );
+ break;
}
- libvlc_unlock (obj->p_libvlc);
- return l;
+ fputc( '\n', stdout );
}
/*****************************************************************************
static int DumpCommand( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data )
{
- libvlc_int_t *p_libvlc = p_this->p_libvlc;
-
(void)oldval; (void)p_data;
- if( *psz_cmd == 'l' )
- {
- vlc_object_t *cur = VLC_OBJECT (p_libvlc);
+ vlc_object_t *p_object = NULL;
- libvlc_lock (p_this->p_libvlc);
- do
- {
- PrintObject (cur, "");
- cur = vlc_internals (cur)->next;
- }
- while (cur != VLC_OBJECT(p_libvlc));
- libvlc_unlock (p_this->p_libvlc);
- }
- else
+ if( *newval.psz_string )
{
- vlc_object_t *p_object = NULL;
-
- if( *newval.psz_string )
+ /* try using the object's name to find it */
+ p_object = vlc_object_find_name( p_this, newval.psz_string,
+ FIND_ANYWHERE );
+ if( !p_object )
{
- /* try using the object's name to find it */
- p_object = vlc_object_find_name( p_this, newval.psz_string,
- FIND_ANYWHERE );
- if( !p_object )
- {
- return VLC_ENOOBJ;
- }
+ return VLC_ENOOBJ;
}
+ }
- libvlc_lock (p_this->p_libvlc);
- if( *psz_cmd == 't' )
- {
- char psz_foo[2 * MAX_DUMPSTRUCTURE_DEPTH + 1];
-
- if( !p_object )
- p_object = VLC_OBJECT(p_this->p_libvlc);
-
- psz_foo[0] = '|';
- DumpStructure( p_object, 0, psz_foo );
- }
- else if( *psz_cmd == 'v' )
- {
- int i;
-
- if( !p_object )
- p_object = p_this->p_libvlc ? VLC_OBJECT(p_this->p_libvlc) : p_this;
+ libvlc_lock (p_this->p_libvlc);
+ if( *psz_cmd == 't' )
+ {
+ char psz_foo[2 * MAX_DUMPSTRUCTURE_DEPTH + 1];
- PrintObject( p_object, "" );
+ if( !p_object )
+ p_object = VLC_OBJECT(p_this->p_libvlc);
- if( !vlc_internals( p_object )->i_vars )
- printf( " `-o No variables\n" );
- for( i = 0; i < vlc_internals( p_object )->i_vars; i++ )
- {
- variable_t *p_var = vlc_internals( p_object )->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 == vlc_internals( p_object )->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_HASCHOICE )
- printf( ", has choices" );
- 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 & VLC_VAR_CLASS )
- {
- 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( ": %"PRIi64, (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" );
- }
- }
- libvlc_unlock (p_this->p_libvlc);
+ psz_foo[0] = '|';
+ DumpStructure( vlc_internals(p_object), 0, psz_foo );
+ }
+ else if( *psz_cmd == 'v' )
+ {
+ 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_object );
- }
+ PrintObject( vlc_internals(p_object), "" );
+ vlc_mutex_lock( &vlc_internals( p_object )->var_lock );
+ if( vlc_internals( p_object )->var_root == NULL )
+ puts( " `-o No variables" );
+ else
+ twalk( vlc_internals( p_object )->var_root, DumpVariable );
+ vlc_mutex_unlock( &vlc_internals( p_object )->var_lock );
}
+ libvlc_unlock (p_this->p_libvlc);
+ if( *newval.psz_string )
+ {
+ vlc_object_release( p_object );
+ }
return VLC_SUCCESS;
}
free( p_list );
}
-/*****************************************************************************
- * dump an object. (Debug function)
- *****************************************************************************/
-#ifndef NDEBUG
-static void vlc_object_dump( vlc_object_t *p_this )
-{
- char psz_foo[2 * MAX_DUMPSTRUCTURE_DEPTH + 1];
- psz_foo[0] = '|';
-
- DumpStructure( p_this, 0, psz_foo );
-}
-#endif
-
/* Following functions are local */
-static vlc_object_t * FindObject( vlc_object_t *p_this, int i_type, int i_mode )
+static vlc_object_t *FindParent (vlc_object_t *p_this, int i_type)
{
- int i;
- vlc_object_t *p_tmp;
+ for (vlc_object_t *parent = p_this->p_parent;
+ parent != NULL;
+ parent = parent->p_parent)
+ {
+ if (vlc_internals (parent)->i_object_type == i_type)
+ return vlc_object_hold (parent);
+ }
+ return NULL;
+}
- switch( i_mode & 0x000f )
+static vlc_object_t *FindParentName (vlc_object_t *p_this, const char *name)
+{
+ for (vlc_object_t *parent = p_this->p_parent;
+ parent != NULL;
+ parent = parent->p_parent)
{
- case FIND_PARENT:
- p_tmp = p_this->p_parent;
- if( p_tmp )
- {
- if( vlc_internals( p_tmp )->i_object_type == i_type )
- {
- vlc_object_hold( p_tmp );
- return p_tmp;
- }
- else
- {
- return FindObject( p_tmp, i_type, i_mode );
- }
- }
- break;
+ const char *objname = vlc_internals (parent)->psz_name;
+ if (objname && !strcmp (objname, name))
+ return vlc_object_hold (parent);
+ }
+ return NULL;
+}
- case FIND_CHILD:
- for( i = vlc_internals( p_this )->i_children; i--; )
- {
- p_tmp = vlc_internals( p_this )->pp_children[i];
- if( vlc_internals( p_tmp )->i_object_type == i_type )
- {
- vlc_object_hold( p_tmp );
- return p_tmp;
- }
- else if( vlc_internals( p_tmp )->i_children )
- {
- p_tmp = FindObject( p_tmp, i_type, i_mode );
- if( p_tmp )
- {
- return p_tmp;
- }
- }
- }
- break;
+static vlc_object_t *FindChild (vlc_object_internals_t *priv, int i_type)
+{
+ for (priv = priv->first; priv != NULL; priv = priv->next)
+ {
+ if (priv->i_object_type == i_type)
+ return vlc_object_hold (vlc_externals (priv));
- case FIND_ANYWHERE:
- /* Handled in vlc_object_find */
- break;
+ vlc_object_t *found = FindChild (priv, i_type);
+ if (found != NULL)
+ return found;
}
-
return NULL;
}
-static vlc_object_t * FindObjectName( vlc_object_t *p_this,
- const char *psz_name,
- int i_mode )
+static vlc_object_t *FindChildName (vlc_object_internals_t *priv,
+ const char *name)
{
- int i;
- vlc_object_t *p_tmp;
-
- switch( i_mode & 0x000f )
+ for (priv = priv->first; priv != NULL; priv = priv->next)
{
- case FIND_PARENT:
- p_tmp = p_this->p_parent;
- if( p_tmp )
- {
- if( !objnamecmp(p_tmp, psz_name) )
- {
- vlc_object_hold( p_tmp );
- return p_tmp;
- }
- else
- {
- return FindObjectName( p_tmp, psz_name, i_mode );
- }
- }
- break;
+ if (priv->psz_name && !strcmp (priv->psz_name, name))
+ return vlc_object_hold (vlc_externals (priv));
- case FIND_CHILD:
- for( i = vlc_internals( p_this )->i_children; i--; )
- {
- p_tmp = vlc_internals( p_this )->pp_children[i];
- if( !objnamecmp(p_tmp, psz_name ) )
- {
- vlc_object_hold( p_tmp );
- return p_tmp;
- }
- else if( vlc_internals( 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;
+ vlc_object_t *found = FindChildName (priv, name);
+ if (found != NULL)
+ return found;
}
-
return NULL;
}
-
-static void PrintObject( vlc_object_t *p_this, const char *psz_prefix )
+static void PrintObject( vlc_object_internals_t *priv,
+ const char *psz_prefix )
{
- char psz_children[20], psz_refcount[20], psz_thread[30], psz_name[50],
- psz_parent[20];
+ char psz_refcount[20], psz_thread[30], psz_name[50], psz_parent[20];
int canc = vlc_savecancel ();
memset( &psz_name, 0, sizeof(psz_name) );
- if( vlc_object_get_name(p_this) )
+
+ vlc_mutex_lock (&name_lock);
+ if (priv->psz_name != NULL)
{
- snprintf( psz_name, 49, " \"%s\"",
- vlc_object_get_name(p_this) );
+ snprintf( psz_name, 49, " \"%s\"", priv->psz_name );
if( psz_name[48] )
psz_name[48] = '\"';
}
-
- psz_children[0] = '\0';
- switch( vlc_internals( p_this )->i_children )
- {
- case 0:
- break;
- case 1:
- strcpy( psz_children, ", 1 child" );
- break;
- default:
- snprintf( psz_children, 19, ", %i children",
- vlc_internals( p_this )->i_children );
- break;
- }
+ vlc_mutex_unlock (&name_lock);
psz_refcount[0] = '\0';
- if( vlc_internals( p_this )->i_refcount > 0 )
- snprintf( psz_refcount, 19, ", refcount %u",
- vlc_internals( p_this )->i_refcount );
+ if( priv->i_refcount > 0 )
+ snprintf( psz_refcount, 19, ", %u refs", priv->i_refcount );
psz_thread[0] = '\0';
- if( vlc_internals( p_this )->b_thread )
+ if( priv->b_thread )
snprintf( psz_thread, 29, " (thread %lu)",
- (unsigned long)vlc_internals( p_this )->thread_id );
+ (unsigned long)priv->thread_id );
psz_parent[0] = '\0';
- if( p_this->p_parent )
- snprintf( psz_parent, 19, ", parent %p", p_this->p_parent );
-
- printf( " %so %p %s%s%s%s%s%s\n", psz_prefix,
- p_this, p_this->psz_object_type,
- psz_name, psz_thread, psz_refcount, psz_children,
- psz_parent );
+ /* FIXME: need structure lock!!! */
+ if( vlc_externals(priv)->p_parent )
+ snprintf( psz_parent, 19, ", parent %p",
+ vlc_externals(priv)->p_parent );
+
+ printf( " %so %p %s%s%s%s%s\n", psz_prefix,
+ vlc_externals(priv), vlc_externals(priv)->psz_object_type,
+ psz_name, psz_thread, psz_refcount, psz_parent );
vlc_restorecancel (canc);
}
-static void DumpStructure( vlc_object_t *p_this, int i_level, char *psz_foo )
+static void DumpStructure (vlc_object_internals_t *priv, unsigned i_level,
+ char *psz_foo)
{
- int i;
char i_back = psz_foo[i_level];
psz_foo[i_level] = '\0';
- PrintObject( p_this, psz_foo );
+ PrintObject (priv, psz_foo);
psz_foo[i_level] = i_back;
if( i_level / 2 >= MAX_DUMPSTRUCTURE_DEPTH )
{
- msg_Warn( p_this, "structure tree is too deep" );
+ msg_Warn( vlc_externals(priv), "structure tree is too deep" );
return;
}
- for( i = 0 ; i < vlc_internals( p_this )->i_children ; i++ )
+ for (priv = priv->first; priv != NULL; priv = priv->next)
{
if( i_level )
{
}
}
- if( i == vlc_internals( p_this )->i_children - 1 )
- {
- psz_foo[i_level] = '`';
- }
- else
- {
- psz_foo[i_level] = '|';
- }
-
+ psz_foo[i_level] = priv->next ? '|' : '`';
psz_foo[i_level+1] = '-';
psz_foo[i_level+2] = '\0';
- DumpStructure( vlc_internals( p_this )->pp_children[i], i_level + 2,
- psz_foo );
+ DumpStructure (priv, i_level + 2, psz_foo);
}
}
static vlc_list_t * NewList( int i_count )
{
- vlc_list_t * p_list = (vlc_list_t *)malloc( sizeof( vlc_list_t ) );
+ vlc_list_t * p_list = malloc( sizeof( vlc_list_t ) );
if( p_list == NULL )
- {
return NULL;
- }
p_list->i_count = i_count;
return p_list;
}
-
-static void ListReplace( vlc_list_t *p_list, vlc_object_t *p_object,
- int i_index )
-{
- if( p_list == NULL || i_index >= p_list->i_count )
- {
- return;
- }
-
- vlc_object_hold( p_object );
-
- p_list->p_values[i_index].p_object = p_object;
-
- return;
-}
-
-/*static void ListAppend( vlc_list_t *p_list, vlc_object_t *p_object )
-{
- if( p_list == NULL )
- {
- return;
- }
-
- p_list->p_values = realloc( p_list->p_values, (p_list->i_count + 1)
- * sizeof( vlc_value_t ) );
- if( p_list->p_values == NULL )
- {
- p_list->i_count = 0;
- return;
- }
-
- vlc_object_hold( p_object );
-
- p_list->p_values[p_list->i_count].p_object = p_object;
- p_list->i_count++;
-
- return;
-}*/
-
-static int CountChildren( vlc_object_t *p_this, int i_type )
-{
- vlc_object_t *p_tmp;
- int i, i_count = 0;
-
- for( i = 0; i < vlc_internals( p_this )->i_children; i++ )
- {
- p_tmp = vlc_internals( p_this )->pp_children[i];
-
- if( vlc_internals( p_tmp )->i_object_type == i_type )
- {
- i_count++;
- }
- i_count += CountChildren( p_tmp, i_type );
- }
-
- return i_count;
-}
-
-static void ListChildren( vlc_list_t *p_list, vlc_object_t *p_this, int i_type )
-{
- vlc_object_t *p_tmp;
- int i;
-
- for( i = 0; i < vlc_internals( p_this )->i_children; i++ )
- {
- p_tmp = vlc_internals( p_this )->pp_children[i];
-
- if( vlc_internals( p_tmp )->i_object_type == i_type )
- ListReplace( p_list, p_tmp, p_list->i_count++ );
-
- ListChildren( p_list, p_tmp, i_type );
- }
-}