Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

objects.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * objects.c: vlc_object_t handling
00003  *****************************************************************************
00004  * Copyright (C) 2004 the VideoLAN team
00005  * $Id: objects.c 12116 2005-08-10 22:08:50Z jpsaman $
00006  *
00007  * Authors: Samuel Hocevar <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00030 /*****************************************************************************
00031  * Preamble
00032  *****************************************************************************/
00033 #include <vlc/vlc.h>
00034 #include <vlc/input.h>
00035 
00036 #ifdef HAVE_STDLIB_H
00037 #   include <stdlib.h>                                          /* realloc() */
00038 #endif
00039 
00040 #include "vlc_video.h"
00041 #include "video_output.h"
00042 #include "vlc_spu.h"
00043 
00044 #include "audio_output.h"
00045 #include "aout_internal.h"
00046 #include "stream_output.h"
00047 
00048 #include "vlc_playlist.h"
00049 #include "vlc_interface.h"
00050 #include "vlc_codec.h"
00051 #include "vlc_filter.h"
00052 
00053 #include "vlc_httpd.h"
00054 #include "vlc_vlm.h"
00055 #include "vlc_vod.h"
00056 #include "vlc_tls.h"
00057 #include "vlc_xml.h"
00058 #include "vlc_osd.h"
00059 
00060 /*****************************************************************************
00061  * Local prototypes
00062  *****************************************************************************/
00063 static int  DumpCommand( vlc_object_t *, char const *,
00064                          vlc_value_t, vlc_value_t, void * );
00065 
00066 static vlc_object_t * FindObject    ( vlc_object_t *, int, int );
00067 static void           DetachObject  ( vlc_object_t * );
00068 static void           PrintObject   ( vlc_object_t *, const char * );
00069 static void           DumpStructure ( vlc_object_t *, int, char * );
00070 static int            FindIndex     ( vlc_object_t *, vlc_object_t **, int );
00071 static void           SetAttachment ( vlc_object_t *, vlc_bool_t );
00072 
00073 static vlc_list_t   * NewList       ( int );
00074 static void           ListReplace   ( vlc_list_t *, vlc_object_t *, int );
00075 /*static void           ListAppend    ( vlc_list_t *, vlc_object_t * );*/
00076 static int            CountChildren ( vlc_object_t *, int );
00077 static void           ListChildren  ( vlc_list_t *, vlc_object_t *, int );
00078 
00079 /*****************************************************************************
00080  * Local structure lock
00081  *****************************************************************************/
00082 static vlc_mutex_t    structure_lock;
00083 
00084 /*****************************************************************************
00085  * vlc_object_create: initialize a vlc object
00086  *****************************************************************************
00087  * This function allocates memory for a vlc object and initializes it. If
00088  * i_type is not a known value such as VLC_OBJECT_ROOT, VLC_OBJECT_VOUT and
00089  * so on, vlc_object_create will use its value for the object size.
00090  *****************************************************************************/
00091 
00099 void * __vlc_object_create( vlc_object_t *p_this, int i_type )
00100 {
00101     vlc_object_t * p_new;
00102     char *         psz_type;
00103     size_t         i_size;
00104 
00105     switch( i_type )
00106     {
00107         case VLC_OBJECT_ROOT:
00108             i_size = sizeof(libvlc_t);
00109             psz_type = "root";
00110             break;
00111         case VLC_OBJECT_VLC:
00112             i_size = sizeof(vlc_t);
00113             psz_type = "vlc";
00114             break;
00115         case VLC_OBJECT_MODULE:
00116             i_size = sizeof(module_t);
00117             psz_type = "module";
00118             break;
00119         case VLC_OBJECT_INTF:
00120             i_size = sizeof(intf_thread_t);
00121             psz_type = "interface";
00122             break;
00123         case VLC_OBJECT_DIALOGS:
00124             i_size = sizeof(intf_thread_t);
00125             psz_type = "dialogs provider";
00126             break;
00127         case VLC_OBJECT_PLAYLIST:
00128             i_size = sizeof(playlist_t);
00129             psz_type = "playlist";
00130             break;
00131         case VLC_OBJECT_SD:
00132             i_size = sizeof(services_discovery_t);
00133             psz_type = "services discovery";
00134             break;
00135         case VLC_OBJECT_INPUT:
00136             i_size = sizeof(input_thread_t);
00137             psz_type = "input";
00138             break;
00139         case VLC_OBJECT_DEMUX:
00140             i_size = sizeof(demux_t);
00141             psz_type = "demux";
00142             break;
00143         case VLC_OBJECT_STREAM:
00144             i_size = sizeof(stream_t);
00145             psz_type = "stream";
00146             break;
00147         case VLC_OBJECT_ACCESS:
00148             i_size = sizeof(access_t);
00149             psz_type = "access";
00150             break;
00151         case VLC_OBJECT_DECODER:
00152             i_size = sizeof(decoder_t);
00153             psz_type = "decoder";
00154             break;
00155         case VLC_OBJECT_PACKETIZER:
00156             i_size = sizeof(decoder_t);
00157             psz_type = "packetizer";
00158             break;
00159         case VLC_OBJECT_ENCODER:
00160             i_size = sizeof(encoder_t);
00161             psz_type = "encoder";
00162             break;
00163         case VLC_OBJECT_FILTER:
00164             i_size = sizeof(filter_t);
00165             psz_type = "filter";
00166             break;
00167         case VLC_OBJECT_VOUT:
00168             i_size = sizeof(vout_thread_t);
00169             psz_type = "video output";
00170             break;
00171         case VLC_OBJECT_SPU:
00172             i_size = sizeof(spu_t);
00173             psz_type = "subpicture unit";
00174             break;
00175         case VLC_OBJECT_AOUT:
00176             i_size = sizeof(aout_instance_t);
00177             psz_type = "audio output";
00178             break;
00179         case VLC_OBJECT_SOUT:
00180             i_size = sizeof(sout_instance_t);
00181             psz_type = "stream output";
00182             break;
00183         case VLC_OBJECT_HTTPD:
00184             i_size = sizeof( httpd_t );
00185             psz_type = "http daemon";
00186             break;
00187         case VLC_OBJECT_VLM:
00188             i_size = sizeof( vlm_t );
00189             psz_type = "vlm dameon";
00190             break;
00191         case VLC_OBJECT_VOD:
00192             i_size = sizeof( vod_t );
00193             psz_type = "vod server";
00194             break;
00195         case VLC_OBJECT_TLS:
00196             i_size = sizeof( tls_t );
00197             psz_type = "tls";
00198             break;
00199         case VLC_OBJECT_XML:
00200             i_size = sizeof( xml_t );
00201             psz_type = "xml";
00202             break;
00203         case VLC_OBJECT_OPENGL:
00204             i_size = sizeof( vout_thread_t );
00205             psz_type = "opengl provider";
00206             break;
00207         case VLC_OBJECT_ANNOUNCE:
00208             i_size = sizeof( announce_handler_t );
00209             psz_type = "announce handler";
00210             break;
00211         case VLC_OBJECT_OSDMENU:
00212             i_size = sizeof( osd_menu_t );
00213             psz_type = "osd menu";
00214             break;
00215         default:
00216             i_size = i_type > 0
00217                       ? i_type > (int)sizeof(vlc_object_t)
00218                          ? i_type : (int)sizeof(vlc_object_t)
00219                       : (int)sizeof(vlc_object_t);
00220             i_type = VLC_OBJECT_GENERIC;
00221             psz_type = "generic";
00222             break;
00223     }
00224 
00225     if( i_type == VLC_OBJECT_ROOT )
00226     {
00227         p_new = p_this;
00228     }
00229     else
00230     {
00231         p_new = malloc( i_size );
00232         if( !p_new ) return NULL;
00233         memset( p_new, 0, i_size );
00234     }
00235 
00236     p_new->i_object_type = i_type;
00237     p_new->psz_object_type = psz_type;
00238 
00239     p_new->psz_object_name = NULL;
00240 
00241     p_new->b_die = VLC_FALSE;
00242     p_new->b_error = VLC_FALSE;
00243     p_new->b_dead = VLC_FALSE;
00244     p_new->b_attached = VLC_FALSE;
00245     p_new->b_force = VLC_FALSE;
00246 
00247     p_new->i_vars = 0;
00248     p_new->p_vars = (variable_t *)malloc( 16 * sizeof( variable_t ) );
00249 
00250     if( !p_new->p_vars )
00251     {
00252         if( i_type != VLC_OBJECT_ROOT )
00253             free( p_new );
00254         return NULL;
00255     }
00256 
00257     if( i_type == VLC_OBJECT_ROOT )
00258     {
00259         /* If i_type is root, then p_new is actually p_libvlc */
00260         p_new->p_libvlc = (libvlc_t*)p_new;
00261         p_new->p_vlc = NULL;
00262 
00263         p_new->p_libvlc->i_counter = 0;
00264         p_new->i_object_id = 0;
00265 
00266         p_new->p_libvlc->i_objects = 1;
00267         p_new->p_libvlc->pp_objects = malloc( sizeof(vlc_object_t *) );
00268         p_new->p_libvlc->pp_objects[0] = p_new;
00269         p_new->b_attached = VLC_TRUE;
00270     }
00271     else
00272     {
00273         p_new->p_libvlc = p_this->p_libvlc;
00274         p_new->p_vlc = ( i_type == VLC_OBJECT_VLC ) ? (vlc_t*)p_new
00275                                                     : p_this->p_vlc;
00276 
00277         vlc_mutex_lock( &structure_lock );
00278 
00279         p_new->p_libvlc->i_counter++;
00280         p_new->i_object_id = p_new->p_libvlc->i_counter;
00281 
00282         /* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's
00283          * useless to try and recover anything if pp_objects gets smashed. */
00284         INSERT_ELEM( p_new->p_libvlc->pp_objects,
00285                      p_new->p_libvlc->i_objects,
00286                      p_new->p_libvlc->i_objects,
00287                      p_new );
00288 
00289         vlc_mutex_unlock( &structure_lock );
00290     }
00291 
00292     p_new->i_refcount = 0;
00293     p_new->p_parent = NULL;
00294     p_new->pp_children = NULL;
00295     p_new->i_children = 0;
00296 
00297     p_new->p_private = NULL;
00298 
00299     /* Initialize mutexes and condvars */
00300     vlc_mutex_init( p_new, &p_new->object_lock );
00301     vlc_cond_init( p_new, &p_new->object_wait );
00302     vlc_mutex_init( p_new, &p_new->var_lock );
00303 
00304     if( i_type == VLC_OBJECT_ROOT )
00305     {
00306         vlc_mutex_init( p_new, &structure_lock );
00307 
00308         var_Create( p_new, "list", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
00309         var_AddCallback( p_new, "list", DumpCommand, NULL );
00310         var_Create( p_new, "tree", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
00311         var_AddCallback( p_new, "tree", DumpCommand, NULL );
00312     }
00313 
00314     return p_new;
00315 }
00316 
00325 void __vlc_object_destroy( vlc_object_t *p_this )
00326 {
00327     int i_delay = 0;
00328 
00329     if( p_this->i_children )
00330     {
00331         msg_Err( p_this, "cannot delete object (%i, %s) with children" ,
00332                  p_this->i_object_id, p_this->psz_object_name );
00333         return;
00334     }
00335 
00336     if( p_this->p_parent )
00337     {
00338         msg_Err( p_this, "cannot delete object (%i, %s) with a parent",
00339                  p_this->i_object_id, p_this->psz_object_name );
00340         return;
00341     }
00342 
00343     while( p_this->i_refcount )
00344     {
00345         i_delay++;
00346 
00347         /* Don't warn immediately ... 100ms seems OK */
00348         if( i_delay == 2 )
00349         {
00350             msg_Warn( p_this,
00351                   "refcount is %i, delaying before deletion (id=%d,type=%d)",
00352                   p_this->i_refcount, p_this->i_object_id,
00353                   p_this->i_object_type );
00354         }
00355         else if( i_delay == 10 )
00356         {
00357             msg_Err( p_this,
00358                   "refcount is %i, delaying again (id=%d,type=%d)",
00359                   p_this->i_refcount, p_this->i_object_id,
00360                   p_this->i_object_type );
00361         }
00362         else if( i_delay == 20 )
00363         {
00364             msg_Err( p_this,
00365                   "we waited too long, cancelling destruction (id=%d,type=%d)",
00366                   p_this->i_object_id, p_this->i_object_type );
00367             return;
00368         }
00369 
00370         msleep( 100000 );
00371     }
00372 
00373     /* Destroy the associated variables, starting from the end so that
00374      * no memmove calls have to be done. */
00375     while( p_this->i_vars )
00376     {
00377         var_Destroy( p_this, p_this->p_vars[p_this->i_vars - 1].psz_name );
00378     }
00379 
00380     free( p_this->p_vars );
00381     vlc_mutex_destroy( &p_this->var_lock );
00382 
00383     if( p_this->i_object_type == VLC_OBJECT_ROOT )
00384     {
00385         /* We are the root object ... no need to lock. */
00386         free( p_this->p_libvlc->pp_objects );
00387         p_this->p_libvlc->pp_objects = NULL;
00388         p_this->p_libvlc->i_objects--;
00389 
00390         vlc_mutex_destroy( &structure_lock );
00391     }
00392     else
00393     {
00394         int i_index;
00395 
00396         vlc_mutex_lock( &structure_lock );
00397 
00398         /* Wooohaa! If *this* fails, we're in serious trouble! Anyway it's
00399          * useless to try and recover anything if pp_objects gets smashed. */
00400         i_index = FindIndex( p_this, p_this->p_libvlc->pp_objects,
00401                              p_this->p_libvlc->i_objects );
00402         REMOVE_ELEM( p_this->p_libvlc->pp_objects,
00403                      p_this->p_libvlc->i_objects, i_index );
00404 
00405         vlc_mutex_unlock( &structure_lock );
00406     }
00407 
00408     vlc_mutex_destroy( &p_this->object_lock );
00409     vlc_cond_destroy( &p_this->object_wait );
00410 
00411     /* root is not dynamically allocated by vlc_object_create */
00412     if( p_this->i_object_type != VLC_OBJECT_ROOT )
00413         free( p_this );
00414 }
00415 
00422 void * __vlc_object_get( vlc_object_t *p_this, int i_id )
00423 {
00424     int i_max, i_middle;
00425     vlc_object_t **pp_objects;
00426 
00427     vlc_mutex_lock( &structure_lock );
00428 
00429     pp_objects = p_this->p_libvlc->pp_objects;
00430 
00431     /* Perform our dichotomy */
00432     for( i_max = p_this->p_libvlc->i_objects - 1 ; ; )
00433     {
00434         i_middle = i_max / 2;
00435 
00436         if( pp_objects[i_middle]->i_object_id > i_id )
00437         {
00438             i_max = i_middle;
00439         }
00440         else if( pp_objects[i_middle]->i_object_id < i_id )
00441         {
00442             if( i_middle )
00443             {
00444                 pp_objects += i_middle;
00445                 i_max -= i_middle;
00446             }
00447             else
00448             {
00449                 /* This happens when there are only two remaining objects */
00450                 if( pp_objects[i_middle+1]->i_object_id == i_id )
00451                 {
00452                     vlc_mutex_unlock( &structure_lock );
00453                     pp_objects[i_middle+1]->i_refcount++;
00454                     return pp_objects[i_middle+1];
00455                 }
00456                 break;
00457             }
00458         }
00459         else
00460         {
00461             vlc_mutex_unlock( &structure_lock );
00462             pp_objects[i_middle]->i_refcount++;
00463             return pp_objects[i_middle];
00464         }
00465 
00466         if( i_max == 0 )
00467         {
00468             /* this means that i_max == i_middle, and since we have already
00469              * tested pp_objects[i_middle]), p_found is properly set. */
00470             break;
00471         }
00472     }
00473 
00474     vlc_mutex_unlock( &structure_lock );
00475     return NULL;
00476 }
00477 
00485 void * __vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode )
00486 {
00487     vlc_object_t *p_found;
00488 
00489     vlc_mutex_lock( &structure_lock );
00490 
00491     /* If we are of the requested type ourselves, don't look further */
00492     if( !(i_mode & FIND_STRICT) && p_this->i_object_type == i_type )
00493     {
00494         p_this->i_refcount++;
00495         vlc_mutex_unlock( &structure_lock );
00496         return p_this;
00497     }
00498 
00499     /* Otherwise, recursively look for the object */
00500     if( (i_mode & 0x000f) == FIND_ANYWHERE )
00501     {
00502         vlc_object_t *p_root = p_this;
00503 
00504         /* Find the root */
00505         while( p_root->p_parent != NULL &&
00506                p_root != VLC_OBJECT( p_this->p_vlc ) )
00507         {
00508             p_root = p_root->p_parent;
00509         }
00510 
00511         p_found = FindObject( p_root, i_type, (i_mode & ~0x000f)|FIND_CHILD );
00512         if( p_found == NULL && p_root != VLC_OBJECT( p_this->p_vlc ) )
00513         {
00514             p_found = FindObject( VLC_OBJECT( p_this->p_vlc ),
00515                                   i_type, (i_mode & ~0x000f)|FIND_CHILD );
00516         }
00517     }
00518     else
00519     {
00520         p_found = FindObject( p_this, i_type, i_mode );
00521     }
00522 
00523     vlc_mutex_unlock( &structure_lock );
00524 
00525     return p_found;
00526 }
00527 
00532 void __vlc_object_yield( vlc_object_t *p_this )
00533 {
00534     vlc_mutex_lock( &structure_lock );
00535     p_this->i_refcount++;
00536     vlc_mutex_unlock( &structure_lock );
00537 }
00538 
00543 void __vlc_object_release( vlc_object_t *p_this )
00544 {
00545     vlc_mutex_lock( &structure_lock );
00546     p_this->i_refcount--;
00547     vlc_mutex_unlock( &structure_lock );
00548 }
00549 
00557 void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent )
00558 {
00559     vlc_mutex_lock( &structure_lock );
00560 
00561     /* Attach the parent to its child */
00562     p_this->p_parent = p_parent;
00563 
00564     /* Attach the child to its parent */
00565     INSERT_ELEM( p_parent->pp_children, p_parent->i_children,
00566                  p_parent->i_children, p_this );
00567 
00568     /* Climb up the tree to see whether we are connected with the root */
00569     if( p_parent->b_attached )
00570     {
00571         SetAttachment( p_this, VLC_TRUE );
00572     }
00573 
00574     vlc_mutex_unlock( &structure_lock );
00575 }
00576 
00583 void __vlc_object_detach( vlc_object_t *p_this )
00584 {
00585     vlc_mutex_lock( &structure_lock );
00586     if( !p_this->p_parent )
00587     {
00588         msg_Err( p_this, "object is not attached" );
00589         vlc_mutex_unlock( &structure_lock );
00590         return;
00591     }
00592 
00593     /* Climb up the tree to see whether we are connected with the root */
00594     if( p_this->p_parent->b_attached )
00595     {
00596         SetAttachment( p_this, VLC_FALSE );
00597     }
00598 
00599     DetachObject( p_this );
00600     vlc_mutex_unlock( &structure_lock );
00601 }
00602 
00610 vlc_list_t * __vlc_list_find( vlc_object_t *p_this, int i_type, int i_mode )
00611 {
00612     vlc_list_t *p_list;
00613     vlc_object_t **pp_current, **pp_end;
00614     int i_count = 0, i_index = 0;
00615 
00616     vlc_mutex_lock( &structure_lock );
00617 
00618     /* Look for the objects */
00619     switch( i_mode & 0x000f )
00620     {
00621     case FIND_ANYWHERE:
00622         pp_current = p_this->p_libvlc->pp_objects;
00623         pp_end = pp_current + p_this->p_libvlc->i_objects;
00624 
00625         for( ; pp_current < pp_end ; pp_current++ )
00626         {
00627             if( (*pp_current)->b_attached
00628                  && (*pp_current)->i_object_type == i_type )
00629             {
00630                 i_count++;
00631             }
00632         }
00633 
00634         p_list = NewList( i_count );
00635         pp_current = p_this->p_libvlc->pp_objects;
00636 
00637         for( ; pp_current < pp_end ; pp_current++ )
00638         {
00639             if( (*pp_current)->b_attached
00640                  && (*pp_current)->i_object_type == i_type )
00641             {
00642                 ListReplace( p_list, *pp_current, i_index );
00643                 if( i_index < i_count ) i_index++;
00644             }
00645         }
00646     break;
00647 
00648     case FIND_CHILD:
00649         i_count = CountChildren( p_this, i_type );
00650         p_list = NewList( i_count );
00651 
00652         /* Check allocation was successful */
00653         if( p_list->i_count != i_count )
00654         {
00655             msg_Err( p_this, "list allocation failed!" );
00656             p_list->i_count = 0;
00657             break;
00658         }
00659 
00660         p_list->i_count = 0;
00661         ListChildren( p_list, p_this, i_type );
00662         break;
00663 
00664     default:
00665         msg_Err( p_this, "unimplemented!" );
00666         p_list = NewList( 0 );
00667         break;
00668     }
00669 
00670     vlc_mutex_unlock( &structure_lock );
00671 
00672     return p_list;
00673 }
00674 
00675 /*****************************************************************************
00676  * DumpCommand: print the current vlc structure
00677  *****************************************************************************
00678  * This function prints either an ASCII tree showing the connections between
00679  * vlc objects, and additional information such as their refcount, thread ID,
00680  * etc. (command "tree"), or the same data as a simple list (command "list").
00681  *****************************************************************************/
00682 static int DumpCommand( vlc_object_t *p_this, char const *psz_cmd,
00683                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
00684 {
00685     if( *psz_cmd == 't' )
00686     {
00687         char psz_foo[2 * MAX_DUMPSTRUCTURE_DEPTH + 1];
00688         vlc_object_t *p_object;
00689 
00690         if( *newval.psz_string )
00691         {
00692             p_object = vlc_object_get( p_this, atoi(newval.psz_string) );
00693 
00694             if( !p_object )
00695             {
00696                 return VLC_ENOOBJ;
00697             }
00698         }
00699         else
00700         {
00701             p_object = p_this->p_vlc ? VLC_OBJECT(p_this->p_vlc) : p_this;
00702         }
00703 
00704         vlc_mutex_lock( &structure_lock );
00705 
00706         psz_foo[0] = '|';
00707         DumpStructure( p_object, 0, psz_foo );
00708 
00709         vlc_mutex_unlock( &structure_lock );
00710 
00711         if( *newval.psz_string )
00712         {
00713             vlc_object_release( p_this );
00714         }
00715     }
00716     else if( *psz_cmd == 'l' )
00717     {
00718         vlc_object_t **pp_current, **pp_end;
00719 
00720         vlc_mutex_lock( &structure_lock );
00721 
00722         pp_current = p_this->p_libvlc->pp_objects;
00723         pp_end = pp_current + p_this->p_libvlc->i_objects;
00724 
00725         for( ; pp_current < pp_end ; pp_current++ )
00726         {
00727             if( (*pp_current)->b_attached )
00728             {
00729                 PrintObject( *pp_current, "" );
00730             }
00731             else
00732             {
00733                 printf( " o %.8i %s (not attached)\n",
00734                         (*pp_current)->i_object_id,
00735                         (*pp_current)->psz_object_type );
00736             }
00737         }
00738 
00739         vlc_mutex_unlock( &structure_lock );
00740     }
00741 
00742     return VLC_SUCCESS;
00743 }
00744 
00745 /*****************************************************************************
00746  * vlc_list_release: free a list previously allocated by vlc_list_find
00747  *****************************************************************************
00748  * This function decreases the refcount of all objects in the list and
00749  * frees the list.
00750  *****************************************************************************/
00751 void vlc_list_release( vlc_list_t *p_list )
00752 {
00753     int i_index;
00754 
00755     for( i_index = 0; i_index < p_list->i_count; i_index++ )
00756     {
00757         vlc_mutex_lock( &structure_lock );
00758 
00759         p_list->p_values[i_index].p_object->i_refcount--;
00760 
00761         vlc_mutex_unlock( &structure_lock );
00762     }
00763 
00764     free( p_list->p_values );
00765     free( p_list );
00766 }
00767 
00768 /* Following functions are local */
00769 
00770 /*****************************************************************************
00771  * FindIndex: find the index of an object in an array of objects
00772  *****************************************************************************
00773  * This function assumes that p_this can be found in pp_objects. It will not
00774  * crash if p_this cannot be found, but will return a wrong value. It is your
00775  * duty to check the return value if you are not certain that the object could
00776  * be found for sure.
00777  *****************************************************************************/
00778 static int FindIndex( vlc_object_t *p_this,
00779                       vlc_object_t **pp_objects, int i_count )
00780 {
00781     int i_middle = i_count / 2;
00782 
00783     if( i_count == 0 )
00784     {
00785         return 0;
00786     }
00787 
00788     if( pp_objects[i_middle] == p_this )
00789     {
00790         return i_middle;
00791     }
00792 
00793     if( i_count == 1 )
00794     {
00795         return 0;
00796     }
00797 
00798     /* We take advantage of the sorted array */
00799     if( pp_objects[i_middle]->i_object_id < p_this->i_object_id )
00800     {
00801         return i_middle + FindIndex( p_this, pp_objects + i_middle,
00802                                              i_count - i_middle );
00803     }
00804     else
00805     {
00806         return FindIndex( p_this, pp_objects, i_middle );
00807     }
00808 }
00809 
00810 static vlc_object_t * FindObject( vlc_object_t *p_this, int i_type, int i_mode )
00811 {
00812     int i;
00813     vlc_object_t *p_tmp;
00814 
00815     switch( i_mode & 0x000f )
00816     {
00817     case FIND_PARENT:
00818         p_tmp = p_this->p_parent;
00819         if( p_tmp )
00820         {
00821             if( p_tmp->i_object_type == i_type )
00822             {
00823                 p_tmp->i_refcount++;
00824                 return p_tmp;
00825             }
00826             else
00827             {
00828                 return FindObject( p_tmp, i_type, i_mode );
00829             }
00830         }
00831         break;
00832 
00833     case FIND_CHILD:
00834         for( i = p_this->i_children; i--; )
00835         {
00836             p_tmp = p_this->pp_children[i];
00837             if( p_tmp->i_object_type == i_type )
00838             {
00839                 p_tmp->i_refcount++;
00840                 return p_tmp;
00841             }
00842             else if( p_tmp->i_children )
00843             {
00844                 p_tmp = FindObject( p_tmp, i_type, i_mode );
00845                 if( p_tmp )
00846                 {
00847                     return p_tmp;
00848                 }
00849             }
00850         }
00851         break;
00852 
00853     case FIND_ANYWHERE:
00854         /* Handled in vlc_object_find */
00855         break;
00856     }
00857 
00858     return NULL;
00859 }
00860 
00861 static void DetachObject( vlc_object_t *p_this )
00862 {
00863     vlc_object_t *p_parent = p_this->p_parent;
00864     int i_index, i;
00865 
00866     /* Remove p_this's parent */
00867     p_this->p_parent = NULL;
00868 
00869     /* Remove all of p_parent's children which are p_this */
00870     for( i_index = p_parent->i_children ; i_index-- ; )
00871     {
00872         if( p_parent->pp_children[i_index] == p_this )
00873         {
00874             p_parent->i_children--;
00875             for( i = i_index ; i < p_parent->i_children ; i++ )
00876             {
00877                 p_parent->pp_children[i] = p_parent->pp_children[i+1];
00878             }
00879         }
00880     }
00881 
00882     if( p_parent->i_children )
00883     {
00884         p_parent->pp_children = (vlc_object_t **)realloc( p_parent->pp_children,
00885                                p_parent->i_children * sizeof(vlc_object_t *) );
00886     }
00887     else
00888     {
00889         free( p_parent->pp_children );
00890         p_parent->pp_children = NULL;
00891     }
00892 }
00893 
00894 /*****************************************************************************
00895  * SetAttachment: recursively set the b_attached flag of a subtree.
00896  *****************************************************************************
00897  * This function is used by the attach and detach functions to propagate
00898  * the b_attached flag in a subtree.
00899  *****************************************************************************/
00900 static void SetAttachment( vlc_object_t *p_this, vlc_bool_t b_attached )
00901 {
00902     int i_index;
00903 
00904     for( i_index = p_this->i_children ; i_index-- ; )
00905     {
00906         SetAttachment( p_this->pp_children[i_index], b_attached );
00907     }
00908 
00909     p_this->b_attached = b_attached;
00910 }
00911 
00912 static void PrintObject( vlc_object_t *p_this, const char *psz_prefix )
00913 {
00914     char psz_children[20], psz_refcount[20], psz_thread[20], psz_name[50];
00915 
00916     psz_name[0] = '\0';
00917     if( p_this->psz_object_name )
00918     {
00919         snprintf( psz_name, 50, " \"%s\"", p_this->psz_object_name );
00920         psz_name[48] = '\"';
00921         psz_name[49] = '\0';
00922     }
00923 
00924     psz_children[0] = '\0';
00925     switch( p_this->i_children )
00926     {
00927         case 0:
00928             break;
00929         case 1:
00930             strcpy( psz_children, ", 1 child" );
00931             break;
00932         default:
00933             snprintf( psz_children, 20,
00934                       ", %i children", p_this->i_children );
00935             psz_children[19] = '\0';
00936             break;
00937     }
00938 
00939     psz_refcount[0] = '\0';
00940     if( p_this->i_refcount )
00941     {
00942         snprintf( psz_refcount, 20, ", refcount %i", p_this->i_refcount );
00943         psz_refcount[19] = '\0';
00944     }
00945 
00946     psz_thread[0] = '\0';
00947     if( p_this->b_thread )
00948     {
00949         snprintf( psz_thread, 20, " (thread %d)", (int)p_this->thread_id );
00950         psz_thread[19] = '\0';
00951     }
00952 
00953     printf( " %so %.8i %s%s%s%s%s\n", psz_prefix,
00954             p_this->i_object_id, p_this->psz_object_type,
00955             psz_name, psz_thread, psz_refcount, psz_children );
00956 }
00957 
00958 static void DumpStructure( vlc_object_t *p_this, int i_level, char *psz_foo )
00959 {
00960     int i;
00961     char i_back = psz_foo[i_level];
00962     psz_foo[i_level] = '\0';
00963 
00964     PrintObject( p_this, psz_foo );
00965 
00966     psz_foo[i_level] = i_back;
00967 
00968     if( i_level / 2 >= MAX_DUMPSTRUCTURE_DEPTH )
00969     {
00970         msg_Warn( p_this, "structure tree is too deep" );
00971         return;
00972     }
00973 
00974     for( i = 0 ; i < p_this->i_children ; i++ )
00975     {
00976         if( i_level )
00977         {
00978             psz_foo[i_level-1] = ' ';
00979 
00980             if( psz_foo[i_level-2] == '`' )
00981             {
00982                 psz_foo[i_level-2] = ' ';
00983             }
00984         }
00985 
00986         if( i == p_this->i_children - 1 )
00987         {
00988             psz_foo[i_level] = '`';
00989         }
00990         else
00991         {
00992             psz_foo[i_level] = '|';
00993         }
00994 
00995         psz_foo[i_level+1] = '-';
00996         psz_foo[i_level+2] = '\0';
00997 
00998         DumpStructure( p_this->pp_children[i], i_level + 2, psz_foo );
00999     }
01000 }
01001 
01002 static vlc_list_t * NewList( int i_count )
01003 {
01004     vlc_list_t * p_list = (vlc_list_t *)malloc( sizeof( vlc_list_t ) );
01005     if( p_list == NULL )
01006     {
01007         return NULL;
01008     }
01009 
01010     p_list->i_count = i_count;
01011 
01012     if( i_count == 0 )
01013     {
01014         p_list->p_values = NULL;
01015         return p_list;
01016     }
01017 
01018     p_list->p_values = malloc( i_count * sizeof( vlc_value_t ) );
01019     if( p_list->p_values == NULL )
01020     {
01021         p_list->i_count = 0;
01022         return p_list;
01023     }
01024 
01025     return p_list;
01026 }
01027 
01028 static void ListReplace( vlc_list_t *p_list, vlc_object_t *p_object,
01029                          int i_index )
01030 {
01031     if( p_list == NULL || i_index >= p_list->i_count )
01032     {
01033         return;
01034     }
01035 
01036     p_object->i_refcount++;
01037 
01038     p_list->p_values[i_index].p_object = p_object;
01039 
01040     return;
01041 }
01042 
01043 /*static void ListAppend( vlc_list_t *p_list, vlc_object_t *p_object )
01044 {
01045     if( p_list == NULL )
01046     {
01047         return;
01048     }
01049 
01050     p_list->p_values = realloc( p_list->p_values, (p_list->i_count + 1)
01051                                 * sizeof( vlc_value_t ) );
01052     if( p_list->p_values == NULL )
01053     {
01054         p_list->i_count = 0;
01055         return;
01056     }
01057 
01058     p_object->i_refcount++;
01059 
01060     p_list->p_values[p_list->i_count].p_object = p_object;
01061     p_list->i_count++;
01062 
01063     return;
01064 }*/
01065 
01066 static int CountChildren( vlc_object_t *p_this, int i_type )
01067 {
01068     vlc_object_t *p_tmp;
01069     int i, i_count = 0;
01070 
01071     for( i = 0; i < p_this->i_children; i++ )
01072     {
01073         p_tmp = p_this->pp_children[i];
01074 
01075         if( p_tmp->i_object_type == i_type )
01076         {
01077             i_count++;
01078         }
01079 
01080         if( p_tmp->i_children )
01081         {
01082             i_count += CountChildren( p_tmp, i_type );
01083         }
01084     }
01085 
01086     return i_count;
01087 }
01088 
01089 static void ListChildren( vlc_list_t *p_list, vlc_object_t *p_this, int i_type )
01090 {
01091     vlc_object_t *p_tmp;
01092     int i;
01093 
01094     for( i = 0; i < p_this->i_children; i++ )
01095     {
01096         p_tmp = p_this->pp_children[i];
01097 
01098         if( p_tmp->i_object_type == i_type )
01099         {
01100             ListReplace( p_list, p_tmp, p_list->i_count++ );
01101         }
01102 
01103         if( p_tmp->i_children )
01104         {
01105             ListChildren( p_list, p_tmp, i_type );
01106         }
01107     }
01108 }

Generated on Tue Dec 20 10:15:00 2005 for vlc-0.8.4a by  doxygen 1.4.2