X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Fobjects.c;h=b03a1dce4d435e15693649a79cdccd409830488e;hb=06a3889008d908f8505e4c5548605ad7ebf53430;hp=923ced51d4e17a58293d2cf125b73bced95127b6;hpb=05ac379f73824945b7fed32d4d53bb38703404e5;p=vlc diff --git a/src/misc/objects.c b/src/misc/objects.c index 923ced51d4..b03a1dce4d 100644 --- a/src/misc/objects.c +++ b/src/misc/objects.c @@ -1,8 +1,8 @@ /***************************************************************************** * objects.c: vlc_object_t handling ***************************************************************************** - * Copyright (C) 2002 VideoLAN - * $Id: objects.c,v 1.28 2002/11/09 16:34:53 sam Exp $ + * Copyright (C) 2004 the VideoLAN team + * $Id$ * * Authors: Samuel Hocevar * @@ -10,7 +10,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -21,32 +21,47 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/ +/** + * \file + * This file contains the functions to handle the vlc_object_t type + */ + + /***************************************************************************** * Preamble *****************************************************************************/ #include +#include #ifdef HAVE_STDLIB_H # include /* realloc() */ #endif -#include "stream_control.h" -#include "input_ext-intf.h" -#include "input_ext-dec.h" - -#include "video.h" +#include "vlc_video.h" #include "video_output.h" +#include "vlc_spu.h" #include "audio_output.h" #include "aout_internal.h" +#include "stream_output.h" #include "vlc_playlist.h" -#include "interface.h" +#include "vlc_interface.h" +#include "vlc_codec.h" +#include "vlc_filter.h" + +#include "vlc_httpd.h" +#include "vlc_vlm.h" +#include "vlc_vod.h" +#include "vlc_tls.h" +#include "vlc_xml.h" +#include "vlc_osd.h" /***************************************************************************** * Local prototypes *****************************************************************************/ -static int DumpCommand( vlc_object_t *, char *, char * ); +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 void DetachObject ( vlc_object_t * ); @@ -55,8 +70,11 @@ 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 vlc_list_t * NewList ( void ); -static vlc_list_t * ListAppend ( vlc_list_t *, vlc_object_t * ); +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 ); /***************************************************************************** * Local structure lock @@ -70,6 +88,14 @@ static vlc_mutex_t structure_lock; * i_type is not a known value such as VLC_OBJECT_ROOT, VLC_OBJECT_VOUT and * so on, vlc_object_create will use its value for the object size. *****************************************************************************/ + +/** + * Initialize a vlc object + * + * This function allocates memory for a vlc object and initializes it. If + * i_type is not a known value such as VLC_OBJECT_ROOT, VLC_OBJECT_VOUT and + * so on, vlc_object_create will use its value for the object size. + */ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) { vlc_object_t * p_new; @@ -94,31 +120,103 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) i_size = sizeof(intf_thread_t); psz_type = "interface"; break; + case VLC_OBJECT_DIALOGS: + i_size = sizeof(intf_thread_t); + psz_type = "dialogs provider"; + 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"; + 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"; + break; case VLC_OBJECT_DECODER: - i_size = sizeof(decoder_fifo_t); + i_size = sizeof(decoder_t); psz_type = "decoder"; break; + case VLC_OBJECT_PACKETIZER: + i_size = sizeof(decoder_t); + psz_type = "packetizer"; + break; + case VLC_OBJECT_ENCODER: + i_size = sizeof(encoder_t); + psz_type = "encoder"; + break; + case VLC_OBJECT_FILTER: + i_size = sizeof(filter_t); + psz_type = "filter"; + break; case VLC_OBJECT_VOUT: i_size = sizeof(vout_thread_t); psz_type = "video output"; break; + case VLC_OBJECT_SPU: + i_size = sizeof(spu_t); + psz_type = "subpicture unit"; + break; case VLC_OBJECT_AOUT: i_size = sizeof(aout_instance_t); psz_type = "audio output"; break; + case VLC_OBJECT_SOUT: + i_size = sizeof(sout_instance_t); + psz_type = "stream output"; + break; + case VLC_OBJECT_HTTPD: + i_size = sizeof( httpd_t ); + psz_type = "http daemon"; + 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_TLS: + i_size = sizeof( tls_t ); + psz_type = "tls"; + 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 provider"; + break; + case VLC_OBJECT_ANNOUNCE: + i_size = sizeof( announce_handler_t ); + psz_type = "announce handler"; + break; + case VLC_OBJECT_OSDMENU: + i_size = sizeof( osd_menu_t ); + psz_type = "osd menu"; + break; default: i_size = i_type > 0 - ? i_type > sizeof(vlc_object_t) - ? i_type : sizeof(vlc_object_t) - : sizeof(vlc_object_t); + ? i_type > (int)sizeof(vlc_object_t) + ? i_type : (int)sizeof(vlc_object_t) + : (int)sizeof(vlc_object_t); i_type = VLC_OBJECT_GENERIC; psz_type = "generic"; break; @@ -131,12 +229,7 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) else { p_new = malloc( i_size ); - - if( !p_new ) - { - return NULL; - } - + if( !p_new ) return NULL; memset( p_new, 0, i_size ); } @@ -149,13 +242,15 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) 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->i_vars = 0; p_new->p_vars = (variable_t *)malloc( 16 * sizeof( variable_t ) ); if( !p_new->p_vars ) { - free( p_new ); + if( i_type != VLC_OBJECT_ROOT ) + free( p_new ); return NULL; } @@ -208,23 +303,21 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type ) if( i_type == VLC_OBJECT_ROOT ) { - vlc_value_t val; - val.p_address = DumpCommand; - vlc_mutex_init( p_new, &structure_lock ); - var_Create( p_new, "list", VLC_VAR_COMMAND ); - var_Set( p_new, "list", val ); - var_Create( p_new, "tree", VLC_VAR_COMMAND ); - var_Set( p_new, "tree", val ); + 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; } -/***************************************************************************** - * vlc_object_destroy: destroy a vlc object - ***************************************************************************** +/** + **************************************************************************** + * Destroy a vlc object + * * This function destroys an object that has been previously allocated with * vlc_object_create. The object's refcount must be zero and it must not be * attached to other objects in any way. @@ -235,13 +328,15 @@ void __vlc_object_destroy( vlc_object_t *p_this ) if( p_this->i_children ) { - msg_Err( p_this, "cannot delete object with children" ); + msg_Err( p_this, "cannot delete object (%i, %s) with children" , + p_this->i_object_id, p_this->psz_object_name ); return; } if( p_this->p_parent ) { - msg_Err( p_this, "cannot delete object with a parent" ); + msg_Err( p_this, "cannot delete object (%i, %s) with a parent", + p_this->i_object_id, p_this->psz_object_name ); return; } @@ -252,17 +347,23 @@ void __vlc_object_destroy( vlc_object_t *p_this ) /* Don't warn immediately ... 100ms seems OK */ if( i_delay == 2 ) { - msg_Warn( p_this, "refcount is %i, delaying before deletion", - p_this->i_refcount ); + msg_Warn( p_this, + "refcount is %i, delaying before deletion (id=%d,type=%d)", + p_this->i_refcount, p_this->i_object_id, + p_this->i_object_type ); } - else if( i_delay == 12 ) + else if( i_delay == 10 ) { - msg_Err( p_this, "refcount is %i, I have a bad feeling about this", - p_this->i_refcount ); + msg_Err( p_this, + "refcount is %i, delaying again (id=%d,type=%d)", + p_this->i_refcount, p_this->i_object_id, + p_this->i_object_type ); } - else if( i_delay == 42 ) + else if( i_delay == 20 ) { - msg_Err( p_this, "we waited too long, cancelling destruction" ); + msg_Err( p_this, + "we waited too long, cancelling destruction (id=%d,type=%d)", + p_this->i_object_id, p_this->i_object_type ); return; } @@ -307,12 +408,14 @@ void __vlc_object_destroy( vlc_object_t *p_this ) vlc_mutex_destroy( &p_this->object_lock ); vlc_cond_destroy( &p_this->object_wait ); - free( p_this ); + /* root is not dynamically allocated by vlc_object_create */ + if( p_this->i_object_type != VLC_OBJECT_ROOT ) + free( p_this ); } -/***************************************************************************** - * vlc_object_get: find an object given its ID - ***************************************************************************** +/** + * find an object given its ID + * * This function looks for the object whose i_object_id field is i_id. We * use a dichotomy so that lookups are in log2(n). *****************************************************************************/ @@ -347,6 +450,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++; return pp_objects[i_middle+1]; } break; @@ -355,6 +459,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++; return pp_objects[i_middle]; } @@ -370,8 +475,9 @@ void * __vlc_object_get( vlc_object_t *p_this, int i_id ) return NULL; } -/***************************************************************************** - * vlc_object_find: find a typed object and increment its refcount +/** + **************************************************************************** + * 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. @@ -393,8 +499,21 @@ void * __vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode ) /* Otherwise, recursively look for the object */ if( (i_mode & 0x000f) == FIND_ANYWHERE ) { - p_found = FindObject( VLC_OBJECT(p_this->p_vlc), i_type, - (i_mode & ~0x000f) | FIND_CHILD ); + vlc_object_t *p_root = p_this; + + /* Find the root */ + while( p_root->p_parent != NULL && + p_root != VLC_OBJECT( p_this->p_vlc ) ) + { + p_root = p_root->p_parent; + } + + p_found = FindObject( p_root, i_type, (i_mode & ~0x000f)|FIND_CHILD ); + if( p_found == NULL && p_root != VLC_OBJECT( p_this->p_vlc ) ) + { + p_found = FindObject( VLC_OBJECT( p_this->p_vlc ), + i_type, (i_mode & ~0x000f)|FIND_CHILD ); + } } else { @@ -406,8 +525,9 @@ void * __vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode ) return p_found; } -/***************************************************************************** - * vlc_object_yield: increment an object refcount +/** + **************************************************************************** + * increment an object refcount *****************************************************************************/ void __vlc_object_yield( vlc_object_t *p_this ) { @@ -416,8 +536,9 @@ void __vlc_object_yield( vlc_object_t *p_this ) vlc_mutex_unlock( &structure_lock ); } -/***************************************************************************** - * vlc_object_release: decrement an object refcount +/** + **************************************************************************** + * decrement an object refcount *****************************************************************************/ void __vlc_object_release( vlc_object_t *p_this ) { @@ -426,8 +547,9 @@ void __vlc_object_release( vlc_object_t *p_this ) vlc_mutex_unlock( &structure_lock ); } -/***************************************************************************** - * vlc_object_attach: attach object to a parent object +/** + **************************************************************************** + * 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. @@ -452,8 +574,9 @@ void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent ) vlc_mutex_unlock( &structure_lock ); } -/***************************************************************************** - * vlc_object_detach: detach object from its parent +/** + **************************************************************************** + * detach object from its parent ***************************************************************************** * This function removes all links between an object and its parent. *****************************************************************************/ @@ -477,23 +600,25 @@ void __vlc_object_detach( vlc_object_t *p_this ) vlc_mutex_unlock( &structure_lock ); } -/***************************************************************************** - * vlc_list_find: find a list typed objects and increment their refcount +/** + **************************************************************************** + * 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 = NewList(); + 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 */ - if( (i_mode & 0x000f) == FIND_ANYWHERE ) + switch( i_mode & 0x000f ) { - vlc_object_t **pp_current, **pp_end; - + case FIND_ANYWHERE: pp_current = p_this->p_libvlc->pp_objects; pp_end = pp_current + p_this->p_libvlc->i_objects; @@ -502,13 +627,44 @@ vlc_list_t * __vlc_list_find( vlc_object_t *p_this, int i_type, int i_mode ) if( (*pp_current)->b_attached && (*pp_current)->i_object_type == i_type ) { - p_list = ListAppend( p_list, *pp_current ); + i_count++; } } - } - else - { + + 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 ); @@ -523,16 +679,17 @@ vlc_list_t * __vlc_list_find( vlc_object_t *p_this, int i_type, int i_mode ) * 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 *psz_cmd, char *psz_arg ) +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( *psz_arg ) + if( *newval.psz_string ) { - p_object = vlc_object_get( p_this, atoi(psz_arg) ); + p_object = vlc_object_get( p_this, atoi(newval.psz_string) ); if( !p_object ) { @@ -550,6 +707,11 @@ static int DumpCommand( vlc_object_t *p_this, char *psz_cmd, char *psz_arg ) 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' ) { @@ -588,21 +750,18 @@ static int DumpCommand( vlc_object_t *p_this, char *psz_cmd, char *psz_arg ) *****************************************************************************/ void vlc_list_release( vlc_list_t *p_list ) { - if( p_list->i_count ) - { - vlc_object_t ** pp_current = p_list->pp_objects; + int i_index; + for( i_index = 0; i_index < p_list->i_count; i_index++ ) + { vlc_mutex_lock( &structure_lock ); - while( pp_current[0] ) - { - pp_current[0]->i_refcount--; - pp_current++; - } + p_list->p_values[i_index].p_object->i_refcount--; vlc_mutex_unlock( &structure_lock ); } + free( p_list->p_values ); free( p_list ); } @@ -840,58 +999,110 @@ static void DumpStructure( vlc_object_t *p_this, int i_level, char *psz_foo ) } } -static vlc_list_t * NewList( void ) +static vlc_list_t * NewList( int i_count ) { - vlc_list_t *p_list = malloc( sizeof( vlc_list_t ) - + 3 * sizeof( vlc_object_t * ) ); - + vlc_list_t * p_list = (vlc_list_t *)malloc( sizeof( vlc_list_t ) ); if( p_list == NULL ) { return NULL; } - p_list->i_count = 0; - p_list->pp_objects = &p_list->_p_first; + p_list->i_count = i_count; - /* We allocated space for NULL and for three extra objects */ - p_list->_i_extra = 3; - p_list->_p_first = NULL; + if( i_count == 0 ) + { + p_list->p_values = NULL; + return p_list; + } + + p_list->p_values = malloc( i_count * sizeof( vlc_value_t ) ); + if( p_list->p_values == NULL ) + { + p_list->i_count = 0; + return p_list; + } return p_list; } -static vlc_list_t * ListAppend( vlc_list_t *p_list, vlc_object_t *p_object ) +static void ListReplace( vlc_list_t *p_list, vlc_object_t *p_object, + int i_index ) { - if( p_list == NULL ) + if( p_list == NULL || i_index >= p_list->i_count ) { - return NULL; + return; } - if( p_list->_i_extra == 0 ) + p_object->i_refcount++; + + 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 ) { - /* If we had X objects it means the array has a size of X+1, we - * make it size 2X+2, so we alloc 2X+1 because there is already - * one allocated in the real structure */ - p_list = realloc( p_list, sizeof( vlc_list_t ) - + (p_list->i_count * 2 + 1) - * sizeof( vlc_object_t * ) ); - if( p_list == NULL ) - { - return NULL; - } + return; + } - /* We have X+1 extra slots */ - p_list->_i_extra = p_list->i_count + 1; - p_list->pp_objects = &p_list->_p_first; + 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; } p_object->i_refcount++; - p_list->pp_objects[p_list->i_count] = p_object; + p_list->p_values[p_list->i_count].p_object = p_object; p_list->i_count++; - p_list->pp_objects[p_list->i_count] = NULL; - p_list->_i_extra--; - return p_list; + 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 < p_this->i_children; i++ ) + { + p_tmp = p_this->pp_children[i]; + + if( p_tmp->i_object_type == i_type ) + { + i_count++; + } + + if( p_tmp->i_children ) + { + 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 < p_this->i_children; i++ ) + { + p_tmp = p_this->pp_children[i]; + + if( p_tmp->i_object_type == i_type ) + { + ListReplace( p_list, p_tmp, p_list->i_count++ ); + } + + if( p_tmp->i_children ) + { + ListChildren( p_list, p_tmp, i_type ); + } + } +}