+ SetAttachment( p_this, VLC_FALSE );
+ }
+
+ DetachObject( p_this );
+ vlc_mutex_unlock( &structure_lock );
+}
+
+/**
+ ****************************************************************************
+ * 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;
+ vlc_object_t **pp_current, **pp_end;
+ int i_count = 0, i_index = 0;
+
+ vlc_mutex_lock( &structure_lock );
+
+ /* Look for the objects */
+ switch( i_mode & 0x000f )
+ {
+ case FIND_ANYWHERE:
+ pp_current = p_this->p_libvlc->pp_objects;
+ pp_end = pp_current + p_this->p_libvlc->i_objects;
+
+ for( ; pp_current < pp_end ; pp_current++ )
+ {
+ if( (*pp_current)->b_attached
+ && (*pp_current)->i_object_type == i_type )
+ {
+ i_count++;
+ }
+ }
+
+ p_list = NewList( i_count );
+ pp_current = p_this->p_libvlc->pp_objects;
+
+ for( ; pp_current < pp_end ; pp_current++ )
+ {
+ if( (*pp_current)->b_attached
+ && (*pp_current)->i_object_type == i_type )
+ {
+ ListReplace( p_list, *pp_current, i_index );
+ if( i_index < i_count ) i_index++;
+ }
+ }
+ break;
+
+ case FIND_CHILD:
+ i_count = CountChildren( p_this, i_type );
+ p_list = NewList( i_count );
+
+ /* Check allocation was successful */
+ if( p_list->i_count != i_count )
+ {
+ msg_Err( p_this, "list allocation failed!" );
+ p_list->i_count = 0;
+ break;
+ }
+
+ p_list->i_count = 0;
+ ListChildren( p_list, p_this, i_type );
+ break;
+
+ default:
+ msg_Err( p_this, "unimplemented!" );
+ p_list = NewList( 0 );
+ break;
+ }
+
+ vlc_mutex_unlock( &structure_lock );
+
+ return p_list;
+}
+
+/*****************************************************************************
+ * DumpCommand: print the current vlc structure
+ *****************************************************************************
+ * This function prints either an ASCII tree showing the connections between
+ * vlc objects, and additional information such as their refcount, thread ID,
+ * etc. (command "tree"), or the same data as a simple list (command "list").
+ *****************************************************************************/
+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' )
+ {
+ char psz_foo[2 * MAX_DUMPSTRUCTURE_DEPTH + 1];
+ vlc_object_t *p_object;
+
+ if( *newval.psz_string )
+ {
+ p_object = vlc_object_get( p_this, atoi(newval.psz_string) );
+
+ if( !p_object )
+ {
+ return VLC_ENOOBJ;
+ }
+ }
+ else
+ {
+ p_object = p_this->p_vlc ? VLC_OBJECT(p_this->p_vlc) : p_this;
+ }
+
+ vlc_mutex_lock( &structure_lock );
+
+ psz_foo[0] = '|';
+ DumpStructure( p_object, 0, psz_foo );
+
+ vlc_mutex_unlock( &structure_lock );
+
+ if( *newval.psz_string )
+ {
+ vlc_object_release( p_this );
+ }
+ }
+ else if( *psz_cmd == 'l' )
+ {
+ vlc_object_t **pp_current, **pp_end;
+
+ vlc_mutex_lock( &structure_lock );
+
+ pp_current = p_this->p_libvlc->pp_objects;
+ pp_end = pp_current + p_this->p_libvlc->i_objects;
+
+ for( ; pp_current < pp_end ; pp_current++ )
+ {
+ if( (*pp_current)->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 );
+ }
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * vlc_list_release: free a list previously allocated by vlc_list_find
+ *****************************************************************************
+ * This function decreases the refcount of all objects in the list and
+ * frees the list.
+ *****************************************************************************/
+void vlc_list_release( vlc_list_t *p_list )
+{
+ int i_index;
+
+ 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 );
+ }
+
+ free( p_list->p_values );
+ free( p_list );
+}
+
+/* Following functions are local */
+
+/*****************************************************************************
+ * FindIndex: find the index of an object in an array of objects
+ *****************************************************************************
+ * This function assumes that p_this can be found in pp_objects. It will not
+ * crash if p_this cannot be found, but will return a wrong value. It is your
+ * duty to check the return value if you are not certain that the object could
+ * be found for sure.
+ *****************************************************************************/
+static int FindIndex( vlc_object_t *p_this,
+ vlc_object_t **pp_objects, int i_count )
+{
+ int i_middle = i_count / 2;
+
+ if( i_count == 0 )
+ {
+ return 0;
+ }
+
+ if( pp_objects[i_middle] == p_this )
+ {
+ return i_middle;
+ }
+
+ if( i_count == 1 )
+ {
+ return 0;
+ }
+
+ /* We take advantage of the sorted array */
+ if( pp_objects[i_middle]->i_object_id < p_this->i_object_id )
+ {
+ return i_middle + FindIndex( p_this, pp_objects + i_middle,
+ i_count - i_middle );
+ }
+ else
+ {
+ return FindIndex( p_this, pp_objects, i_middle );
+ }
+}
+
+static vlc_object_t * FindObject( vlc_object_t *p_this, int i_type, 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->i_object_type == i_type )
+ {
+ p_tmp->i_refcount++;
+ return p_tmp;
+ }
+ else
+ {
+ return FindObject( p_tmp, i_type, i_mode );
+ }
+ }
+ break;
+
+ case FIND_CHILD:
+ for( i = p_this->i_children; i--; )
+ {
+ p_tmp = p_this->pp_children[i];
+ if( p_tmp->i_object_type == i_type )
+ {
+ p_tmp->i_refcount++;
+ return p_tmp;
+ }
+ else if( p_tmp->i_children )
+ {
+ p_tmp = FindObject( p_tmp, i_type, i_mode );
+ if( p_tmp )
+ {
+ return p_tmp;
+ }
+ }
+ }
+ break;
+
+ case FIND_ANYWHERE:
+ /* Handled in vlc_object_find */
+ break;