/*****************************************************************************
* objects.c: vlc_object_t handling
*****************************************************************************
- * Copyright (C) 2004-2007 the VideoLAN team
+ * Copyright (C) 2004-2008 the VideoLAN team
* $Id$
*
* Authors: Samuel Hocevar <sam@zoy.org>
#include <vlc_sout.h>
#include "stream_output/stream_output.h"
-#include "vlc_playlist.h"
#include "vlc_interface.h"
#include "vlc_codec.h"
#include "vlc_filter.h"
-#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"
-#include "vlc_osd.h"
-#include "vlc_meta.h"
-
#include "variables.h"
#ifndef WIN32
# include <unistd.h>
#endif
#include <assert.h>
+/*****************************************************************************
+ * Constants
+ *****************************************************************************/
+
+const vlc_destructor_t kVLCDestructor = NULL;
+
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static void PrintObject ( vlc_object_t *, const char * );
static void DumpStructure ( vlc_object_t *, int, char * );
static int FindIndex ( vlc_object_t *, vlc_object_t **, int );
-static void SetAttachment ( vlc_object_t *, vlc_bool_t );
+static void SetAttachment ( vlc_object_t *, bool );
static vlc_list_t * NewList ( int );
static void ListReplace ( 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 )
+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;
+ /* NOTE:
+ * VLC objects are laid out as follow:
+ * - first the LibVLC-private per-object data,
+ * - then VLC_COMMON members from vlc_object_t,
+ * - finally, the type-specific data (if any).
+ *
+ * This function initializes the LibVLC and common data,
+ * and zeroes the rest.
+ */
+ p_priv = calloc( 1, sizeof( *p_priv ) + i_size );
+ if( p_priv == NULL )
+ return NULL;
+
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;
-
+ assert (i_size >= sizeof (vlc_object_t));
p_new = (vlc_object_t *)(p_priv + 1);
}
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->b_die = false;
+ p_new->b_error = false;
+ p_new->b_dead = false;
+ p_priv->b_attached = false;
+ p_new->b_force = 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_new->i_flags |= p_this->i_flags
+ & (OBJECT_FLAGS_NODBG|OBJECT_FLAGS_QUIET|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 );
+ free( p_priv );
return NULL;
}
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;
+ p_priv->b_attached = true;
+ vlc_mutex_init( p_new, &structure_lock );
}
else
{
if( i_type == VLC_OBJECT_LIBVLC )
{
p_new->p_libvlc = (libvlc_int_t*)p_new;
- p_priv->b_attached = VLC_TRUE;
+ p_priv->b_attached = true;
}
else
{
}
p_priv->i_refcount = 1;
+ p_priv->pf_destructor = kVLCDestructor;
+ p_priv->b_thread = false;
p_new->p_parent = NULL;
p_new->pp_children = NULL;
p_new->i_children = 0;
vlc_spin_init( &p_priv->spin );
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 );
switch( i_type )
{
- case VLC_OBJECT_GLOBAL:
- i_size = sizeof(libvlc_global_data_t);
- psz_type = "global";
- break;
case VLC_OBJECT_LIBVLC:
i_size = sizeof(libvlc_int_t);
psz_type = "libvlc";
i_size = sizeof(intf_thread_t);
psz_type = "dialogs";
break;
- case VLC_OBJECT_PLAYLIST:
- i_size = sizeof(playlist_t);
- psz_type = "playlist";
- break;
- case VLC_OBJECT_SD:
- i_size = sizeof(services_discovery_t);
- psz_type = "services discovery";
- break;
- case VLC_OBJECT_INPUT:
- i_size = sizeof(input_thread_t);
- psz_type = "input";
- break;
case VLC_OBJECT_DEMUX:
i_size = sizeof(demux_t);
psz_type = "demux";
i_size = sizeof(vout_thread_t);
psz_type = "video output";
break;
- case VLC_OBJECT_SPU:
- i_size = sizeof(spu_t);
- psz_type = "subpicture";
- break;
case VLC_OBJECT_AOUT:
i_size = sizeof(aout_instance_t);
psz_type = "audio output";
i_size = sizeof(sout_instance_t);
psz_type = "stream output";
break;
- case VLC_OBJECT_VLM:
- i_size = sizeof( vlm_t );
- psz_type = "vlm dameon";
- break;
- case VLC_OBJECT_VOD:
- i_size = sizeof( vod_t );
- psz_type = "vod server";
- break;
- case VLC_OBJECT_XML:
- i_size = sizeof( xml_t );
- psz_type = "xml";
- break;
case VLC_OBJECT_OPENGL:
i_size = sizeof( vout_thread_t );
psz_type = "opengl";
i_size = sizeof( announce_handler_t );
psz_type = "announce";
break;
- case VLC_OBJECT_META_ENGINE:
- i_size = sizeof( meta_engine_t );
- psz_type = "meta engine";
- break;
- case VLC_OBJECT_OSDMENU:
- i_size = sizeof( osd_menu_t );
- psz_type = "osd menu";
+ case VLC_OBJECT_INTERACTION:
+ i_size = sizeof( interaction_t );
+ psz_type = "interaction";
break;
default:
i_size = i_type > (int)sizeof(vlc_object_t)
}
+/**
+ ****************************************************************************
+ * Set the destructor of a vlc object
+ *
+ * This function sets the destructor of the vlc object. It will be called
+ * 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 )
+{
+ vlc_object_internals_t *p_priv = vlc_internals(p_this );
+
+ vlc_mutex_lock( &structure_lock );
+ p_priv->pf_destructor = pf_destructor;
+ vlc_mutex_unlock( &structure_lock );
+}
+
/**
****************************************************************************
* Destroy a vlc object (Internal)
{
vlc_object_internals_t *p_priv = vlc_internals( p_this );
+ /* Automatically detach the object from its parents */
+ if( p_this->p_parent ) vlc_object_detach( p_this );
+
+
+ /* Send a kill to the object's thread if applicable */
+ vlc_object_kill( p_this );
+
+ /* If we are running on a thread, wait until it ends */
+ if( p_priv->b_thread )
+ vlc_thread_join( p_this );
+
+ /* Call the custom "subclass" destructor */
+ if( p_priv->pf_destructor )
+ p_priv->pf_destructor( p_this );
+
/* Sanity checks */
if( p_this->i_children )
{
p_this->pp_children[i]->psz_object_name );
}
fflush(stderr);
- abort();
- }
- if( p_this->p_parent )
- {
- fprintf( stderr,
- "ERROR: cannot delete object (id:%i, type:%s, name:%s) "
- "with a parent (id:%i, type:%s, name:%s)\n",
- p_this->i_object_id, p_this->psz_object_type,
- p_this->psz_object_name, p_this->p_parent->i_object_id,
- p_this->p_parent->psz_object_type,
- p_this->p_parent->psz_object_name );
- fflush(stderr);
+ /* Dump libvlc object to ease debugging */
+ vlc_object_dump( p_this->p_libvlc );
+
abort();
}
p_global->pp_objects[i]->i_object_id,
p_global->pp_objects[i]->psz_object_type,
p_global->pp_objects[i]->psz_object_name );
+
+ /* Dump libvlc object to ease debugging */
+ vlc_object_dump( p_global->pp_objects[i] );
+
fflush(stderr);
}
+
+ /* Dump libvlc object to ease debugging */
+ vlc_object_dump( p_this );
+
/* Strongly abort, cause we want these to be fixed */
abort();
}
vlc_mutex_destroy( &structure_lock );
}
+ FREENULL( p_this->psz_object_name );
+
#if defined(WIN32) || defined(UNDER_CE)
/* if object has an associated thread, close it now */
if( p_priv->thread_id.hThread )
if( p_priv->pipes[0] != -1 )
close( p_priv->pipes[0] );
- /* global is not dynamically allocated by vlc_object_create */
- if( p_this->i_object_type != VLC_OBJECT_GLOBAL )
- free( p_priv );
+ free( p_priv );
}
{
int pfd[2] = { -1, -1 };
struct vlc_object_internals_t *internals = obj->p_internals;
- vlc_bool_t killed = VLC_FALSE;
+ bool killed = false;
vlc_spin_lock (&internals->spin);
if (internals->pipes[0] == -1)
*
* @return true if the object is dying and should terminate.
*/
-vlc_bool_t __vlc_object_wait( vlc_object_t *obj )
+bool __vlc_object_wait( vlc_object_t *obj )
{
vlc_assert_locked( &obj->object_lock );
vlc_cond_wait( &obj->object_wait, &obj->object_lock );
*
* @return true iff the object has not been killed yet
*/
-vlc_bool_t __vlc_object_alive( vlc_object_t *obj )
+bool __vlc_object_alive( vlc_object_t *obj )
{
vlc_assert_locked( &obj->object_lock );
return !obj->b_die;
int fd;
vlc_mutex_lock( &p_this->object_lock );
- p_this->b_die = VLC_TRUE;
+ p_this->b_die = true;
vlc_spin_lock (&internals->spin);
fd = internals->pipes[1];
else
{
/* This happens when there are only two remaining objects */
- if( pp_objects[i_middle+1]->i_object_id == i_id )
+ if( pp_objects[i_middle+1]->i_object_id == i_id
+ && pp_objects[i_middle+1]->p_internals->i_refcount > 0 )
{
vlc_object_yield_locked( pp_objects[i_middle+1] );
vlc_mutex_unlock( &structure_lock );
break;
}
}
- else
+ else if( pp_objects[i_middle]->p_internals->i_refcount > 0 )
{
vlc_object_yield_locked( pp_objects[i_middle] );
vlc_mutex_unlock( &structure_lock );
vlc_mutex_lock( &structure_lock );
- /* Avoid obvious freed object uses */
- assert( p_this->p_internals->i_refcount > 0 );
-
/* If we are of the requested type ourselves, don't look further */
- if( !(i_mode & FIND_STRICT) && p_this->i_object_type == i_type )
+ if( !(i_mode & FIND_STRICT) && p_this->i_object_type == i_type
+ && p_this->p_internals->i_refcount > 0 )
{
vlc_object_yield_locked( p_this );
vlc_mutex_unlock( &structure_lock );
/* 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 ) )
+ && !strcmp( p_this->psz_object_name, psz_name )
+ && p_this->p_internals->i_refcount > 0 )
{
vlc_object_yield_locked( p_this );
vlc_mutex_unlock( &structure_lock );
/* When the structure_lock is locked */
static void vlc_object_yield_locked( vlc_object_t *p_this )
{
+ vlc_assert_locked (&structure_lock);
+
/* Avoid obvious freed object uses */
assert( p_this->p_internals->i_refcount > 0 );
*****************************************************************************/
void __vlc_object_release( vlc_object_t *p_this )
{
- vlc_bool_t b_should_destroy;
+ bool b_should_destroy;
vlc_mutex_lock( &structure_lock );
/* Climb up the tree to see whether we are connected with the root */
if( p_parent->p_internals->b_attached )
{
- SetAttachment( p_this, VLC_TRUE );
+ SetAttachment( p_this, true );
}
vlc_mutex_unlock( &structure_lock );
vlc_mutex_lock( &structure_lock );
- /* Avoid obvious freed object uses */
- assert( p_this->p_internals->i_refcount > 0 );
-
if( !p_this->p_parent )
{
msg_Err( p_this, "object is not attached" );
/* Climb up the tree to see whether we are connected with the root */
if( p_this->p_parent->p_internals->b_attached )
{
- SetAttachment( p_this, VLC_FALSE );
+ SetAttachment( p_this, false );
}
DetachObject( p_this );
vlc_mutex_lock( &structure_lock );
- /* Avoid obvious freed object uses */
- assert( p_this->p_internals->i_refcount > 0 );
-
/* Look for the objects */
switch( i_mode & 0x000f )
{
printf( ": %f", p_var->val.f_float );
break;
case VLC_VAR_TIME:
- printf( ": " I64Fi, (int64_t)p_var->val.i_time );
+ printf( ": %"PRIi64, (int64_t)p_var->val.i_time );
break;
case VLC_VAR_ADDRESS:
printf( ": %p", p_var->val.p_address );
free( p_list );
}
+/*****************************************************************************
+ * dump an object. (Debug function)
+ *****************************************************************************/
+void __vlc_object_dump( vlc_object_t *p_this )
+{
+ vlc_mutex_lock( &structure_lock );
+ char psz_foo[2 * MAX_DUMPSTRUCTURE_DEPTH + 1];
+ psz_foo[0] = '|';
+ DumpStructure( p_this, 0, psz_foo );
+ vlc_mutex_unlock( &structure_lock );
+}
+
/* Following functions are local */
/*****************************************************************************
p_tmp = p_this->p_parent;
if( p_tmp )
{
- if( p_tmp->i_object_type == i_type )
+ if( p_tmp->i_object_type == i_type
+ && p_tmp->p_internals->i_refcount > 0 )
{
vlc_object_yield_locked( p_tmp );
return p_tmp;
for( i = p_this->i_children; i--; )
{
p_tmp = p_this->pp_children[i];
- if( p_tmp->i_object_type == i_type )
+ if( p_tmp->i_object_type == i_type
+ && p_tmp->p_internals->i_refcount > 0 )
{
vlc_object_yield_locked( p_tmp );
return p_tmp;
if( p_tmp )
{
if( p_tmp->psz_object_name
- && !strcmp( p_tmp->psz_object_name, psz_name ) )
+ && !strcmp( p_tmp->psz_object_name, psz_name )
+ && p_tmp->p_internals->i_refcount > 0 )
{
vlc_object_yield_locked( p_tmp );
return p_tmp;
{
p_tmp = p_this->pp_children[i];
if( p_tmp->psz_object_name
- && !strcmp( p_tmp->psz_object_name, psz_name ) )
+ && !strcmp( p_tmp->psz_object_name, psz_name )
+ && p_tmp->p_internals->i_refcount > 0 )
{
vlc_object_yield_locked( p_tmp );
return p_tmp;
* This function is used by the attach and detach functions to propagate
* the b_attached flag in a subtree.
*****************************************************************************/
-static void SetAttachment( vlc_object_t *p_this, vlc_bool_t b_attached )
+static void SetAttachment( vlc_object_t *p_this, bool b_attached )
{
int i_index;
char psz_children[20], psz_refcount[20], psz_thread[30], psz_name[50],
psz_parent[20];
- psz_name[0] = '\0';
+ memset( &psz_name, 0, sizeof(psz_name) );
if( p_this->psz_object_name )
{
snprintf( psz_name, 49, " \"%s\"", p_this->psz_object_name );