]> git.sesse.net Git - vlc/commitdiff
* ./src/misc/objects.c: implemented vlc_list_find() which works like
authorSam Hocevar <sam@videolan.org>
Wed, 14 Aug 2002 17:06:53 +0000 (17:06 +0000)
committerSam Hocevar <sam@videolan.org>
Wed, 14 Aug 2002 17:06:53 +0000 (17:06 +0000)
    vlc_object_find() but returns a list of _all_ the matching objects. Only
    works with FIND_ANYWHERE at the moment.
  * ./modules/gui/gtk/preferences.c, ./modules/gui/kde/preferences.cpp,
    ./modules/gui/win32/preferences.cpp: the module lists in the preferences
    menus work again.
  * ./src/misc/objects.c: added a missing sizeof that caused crashes because
    the reindexing of the global object array was incomplete.
  * ./include/modules_inner.h: propagated the module long description to its
    submodules.

include/modules_inner.h
include/vlc/vlc.h
include/vlc_common.h
include/vlc_objects.h
include/vlc_symbols.h
modules/gui/gtk/preferences.c
modules/gui/kde/preferences.cpp
modules/gui/win32/preferences.cpp
src/misc/modules.c
src/misc/modules_plugin.h
src/misc/objects.c

index 4b4a92d1ae77ed123a0e384e77ef1e002f50f65c..cd2c5d9026d223629e87882fa6eb4849ff545a1c 100644 (file)
@@ -2,7 +2,7 @@
  * modules_inner.h : Macros used from within a module.
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: modules_inner.h,v 1.29 2002/08/08 22:28:22 sam Exp $
+ * $Id: modules_inner.h,v 1.30 2002/08/14 17:06:53 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
                                 p_module->pp_shortcuts[ i_shortcut ];         \
     }                                                                         \
     p_submodule->psz_object_name = p_module->psz_object_name;                 \
+    p_submodule->psz_longname = p_module->psz_longname;                       \
     p_submodule->psz_program = p_module->psz_program;                         \
     p_submodule->psz_capability = p_module->psz_capability;                   \
     p_submodule->i_score = p_module->i_score;                                 \
index 01a629bff2bb4c1ab6ab88b0ee480e1f6ae3d3bb..9d4264ecc2e47ed92442a2450d7e36335eea709f 100644 (file)
@@ -2,7 +2,7 @@
  * vlc.h: global header for vlc
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: vlc.h,v 1.7 2002/08/08 00:35:10 sam Exp $
+ * $Id: vlc.h,v 1.8 2002/08/14 17:06:53 sam Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,10 +29,8 @@ extern "C" {
 /*****************************************************************************
  * Our custom types
  *****************************************************************************/
-struct vlc_t;
-struct vlc_object_t;
-
 typedef struct vlc_t vlc_t;
+typedef struct vlc_list_t vlc_list_t;
 typedef struct vlc_object_t vlc_object_t;
 
 typedef signed int vlc_error_t;
index 19d19b92a36ee3a1a89f430fddb224380ed4890d..1be334513cc2895b4a458ade85985550c5a1d7a7 100644 (file)
@@ -3,7 +3,7 @@
  * Collection of useful common types and macros definitions
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: vlc_common.h,v 1.19 2002/08/12 22:12:50 massiot Exp $
+ * $Id: vlc_common.h,v 1.20 2002/08/14 17:06:53 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@via.ecp.fr>
  *          Vincent Seguin <seguin@via.ecp.fr>
@@ -270,6 +270,17 @@ struct vlc_object_t
     VLC_COMMON_MEMBERS
 };
 
+/* The object list */
+struct vlc_list_t
+{
+    int             i_count;
+    vlc_object_t ** pp_objects;
+
+    /* Private */
+    int             _i_extra;
+    vlc_object_t *  _p_first;
+};  
+
 /* VLC_OBJECT: attempt at doing a clever cast */
 #define VLC_OBJECT( x ) \
     ((vlc_object_t *)(x))+0*(x)->be_sure_to_add_VLC_COMMON_MEMBERS_to_struct
index d2d18d4ff9d0d81096ea8d060a8071fcfa55afa7..2e40685c8ee685982c9c992ac1d8cc782c03b3a5 100644 (file)
@@ -2,7 +2,7 @@
  * vlc_objects.h: vlc_object_t definition.
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: vlc_objects.h,v 1.8 2002/08/14 08:17:24 sam Exp $
+ * $Id: vlc_objects.h,v 1.9 2002/08/14 17:06:53 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -31,7 +31,7 @@
 #define VLC_OBJECT_DECODER    (-7)
 #define VLC_OBJECT_VOUT       (-8)
 #define VLC_OBJECT_AOUT       (-9)
-#define VLC_OBJECT_SOUT       (-10)
+#define VLC_OBJECT_SOUT      (-10)
 #define VLC_OBJECT_GENERIC  (-666)
 
 /* Object search mode */
 
 #define FIND_STRICT         0x0010
 
-/* Object cast */
-
-
 /*****************************************************************************
  * Prototypes
  *****************************************************************************/
 VLC_EXPORT( void *, __vlc_object_create, ( vlc_object_t *, int ) );
 VLC_EXPORT( void, __vlc_object_destroy, ( vlc_object_t * ) );
+VLC_EXPORT( void, __vlc_object_attach, ( vlc_object_t *, vlc_object_t * ) );
+VLC_EXPORT( void, __vlc_object_detach, ( vlc_object_t * ) );
 VLC_EXPORT( void *, __vlc_object_find, ( vlc_object_t *, int, int ) );
 VLC_EXPORT( void, __vlc_object_yield, ( vlc_object_t * ) );
 VLC_EXPORT( void, __vlc_object_release, ( vlc_object_t * ) );
-VLC_EXPORT( void, __vlc_object_detach, ( vlc_object_t * ) );
-VLC_EXPORT( void, __vlc_object_attach, ( vlc_object_t *, vlc_object_t * ) );
-#if 0
-//VLC_EXPORT( void, __vlc_object_setchild, ( vlc_object_t *, vlc_object_t * ) );
-#endif
+VLC_EXPORT( vlc_list_t *, __vlc_list_find, ( vlc_object_t *, int, int ) );
+VLC_EXPORT( void, __vlc_list_release, ( vlc_object_t *, vlc_list_t * ) );
 
 VLC_EXPORT( void, __vlc_liststructure, ( vlc_object_t * ) );
 VLC_EXPORT( void, __vlc_dumpstructure, ( vlc_object_t * ) );
@@ -68,6 +64,12 @@ VLC_EXPORT( void, __vlc_dumpstructure, ( vlc_object_t * ) );
     __vlc_object_destroy( VLC_OBJECT(a) ); \
     (a) = NULL; } while(0)
 
+#define vlc_object_detach(a) \
+    __vlc_object_detach( VLC_OBJECT(a) )
+
+#define vlc_object_attach(a,b) \
+    __vlc_object_attach( VLC_OBJECT(a), VLC_OBJECT(b) )
+
 #define vlc_object_find(a,b,c) \
     __vlc_object_find( VLC_OBJECT(a),b,c)
 
@@ -77,16 +79,11 @@ VLC_EXPORT( void, __vlc_dumpstructure, ( vlc_object_t * ) );
 #define vlc_object_release(a) \
     __vlc_object_release( VLC_OBJECT(a) )
 
-#define vlc_object_detach(a) \
-    __vlc_object_detach( VLC_OBJECT(a) )
-
-#define vlc_object_attach(a,b) \
-    __vlc_object_attach( VLC_OBJECT(a), VLC_OBJECT(b) )
+#define vlc_list_find(a,b,c) \
+    __vlc_list_find( VLC_OBJECT(a),b,c)
 
-#if 0
-#define vlc_object_setchild(a,b) \
-    __vlc_object_setchild( VLC_OBJECT(a), VLC_OBJECT(b) )
-#endif
+#define vlc_list_release(a,b) \
+    __vlc_list_release( VLC_OBJECT(a),b )
 
 #define vlc_liststructure(a) \
     __vlc_liststructure( VLC_OBJECT(a) )
index cb41fb20b59763c7fa6c8d5ff51ae241e3cbec2e..5d5224446c7c8dd6c124835545d556065cf0eaa6 100644 (file)
@@ -71,6 +71,7 @@ struct module_symbols_t
     u32 (* UnalignedShowBits_inner) ( bit_stream_t *, unsigned int ) ;
     vlc_bool_t (* NextDataPacket_inner) ( decoder_fifo_t *, data_packet_t ** ) ;
     vlc_error_t (* intf_RunThread_inner) ( intf_thread_t * ) ;
+    vlc_list_t * (* __vlc_list_find_inner) ( vlc_object_t *, int, int ) ;
     void (* BitstreamNextDataPacket_inner) ( bit_stream_t * ) ;
     void (* CurrentPTS_inner) ( bit_stream_t *, mtime_t *, mtime_t * ) ;
     void (* DecoderError_inner) ( decoder_fifo_t * p_fifo ) ;
@@ -92,6 +93,7 @@ struct module_symbols_t
     void (* __msg_Unsubscribe_inner) ( vlc_object_t *, msg_subscription_t * ) ;
     void (* __msg_Warn_inner) ( void *, const char *, ... ) ;
     void (* __vlc_dumpstructure_inner) ( vlc_object_t * ) ;
+    void (* __vlc_list_release_inner) ( vlc_object_t *, vlc_list_t * ) ;
     void (* __vlc_liststructure_inner) ( vlc_object_t * ) ;
     void (* __vlc_object_attach_inner) ( vlc_object_t *, vlc_object_t * ) ;
     void (* __vlc_object_destroy_inner) ( vlc_object_t * ) ;
@@ -188,6 +190,8 @@ struct module_symbols_t
 #   define __vlc_cond_destroy p_symbols->__vlc_cond_destroy_inner
 #   define __vlc_cond_init p_symbols->__vlc_cond_init_inner
 #   define __vlc_dumpstructure p_symbols->__vlc_dumpstructure_inner
+#   define __vlc_list_find p_symbols->__vlc_list_find_inner
+#   define __vlc_list_release p_symbols->__vlc_list_release_inner
 #   define __vlc_liststructure p_symbols->__vlc_liststructure_inner
 #   define __vlc_mutex_destroy p_symbols->__vlc_mutex_destroy_inner
 #   define __vlc_mutex_init p_symbols->__vlc_mutex_init_inner
index 8a6f9db4b145339c4fe35ca3d2e3859a5ef27746..0fa41c413ec70ceff39193d04f796d1f5b210f82 100644 (file)
@@ -2,7 +2,7 @@
  * gtk_preferences.c: functions to handle the preferences dialog box.
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
- * $Id: preferences.c,v 1.2 2002/08/08 22:28:22 sam Exp $
+ * $Id: preferences.c,v 1.3 2002/08/14 17:06:53 sam Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *          Loïc Minier <lool@via.ecp.fr>
@@ -118,7 +118,7 @@ void GtkPreferencesShow( GtkMenuItem * menuitem, gpointer user_data )
 static void GtkCreateConfigDialog( char *psz_module_name,
                                    intf_thread_t *p_intf )
 {
-    module_t *p_module, *p_module_bis;
+    module_t *p_module;
     module_config_t *p_item;
 
     guint rows = 0;
@@ -318,27 +318,22 @@ static void GtkCreateConfigDialog( char *psz_module_name,
             /* build a list of available modules */
             {
                 gchar * entry[2];
-                char *  psz_capability;
+                vlc_list_t *p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE,
+                                                            FIND_ANYWHERE );
+                module_t **pp_parser = (module_t **)p_list->pp_objects;
 
-                for( p_module_bis = p_intf->p_vlc->p_module_bank->first ;
-                     p_module_bis != NULL ;
-                     p_module_bis = p_module_bis->next )
+                for( ; *pp_parser ; pp_parser++ )
                 {
-#if 0 /* FIXME */
-                    for( psz_capability = p_module_bis->pp_capabilities[0] ;
-                         *psz_capability ;
-                         psz_capability++ )
+                    if( !strcmp( (*pp_parser)->psz_capability,
+                                 p_item->psz_type ) )
                     {
-                        if( !strcmp( psz_capability, p_item->psz_type ) )
-                        {
-                            entry[0] = p_module_bis->psz_object_name;
-                            entry[1] = p_module_bis->psz_longname;
-                            gtk_clist_append( GTK_CLIST(module_clist), entry );
-                            break;
-                        }
+                        entry[0] = (*pp_parser)->psz_object_name;
+                        entry[1] = (*pp_parser)->psz_longname;
+                        gtk_clist_append( GTK_CLIST(module_clist), entry );
                     }
-#endif
                 }
+
+                vlc_list_release( p_intf, p_list );
             }
 
             gtk_clist_set_column_auto_resize( GTK_CLIST(module_clist),
index 7e53b266036668ecf45b35f4456f8b226cb35d5b..8726567f7c27c44cf13326032ef93e2218dba2c9 100644 (file)
@@ -2,7 +2,7 @@
  * preferences.cpp: preferences window for the kde gui
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: preferences.cpp,v 1.2 2002/08/12 17:38:10 sigmunau Exp $
+ * $Id: preferences.cpp,v 1.3 2002/08/14 17:06:53 sam Exp $
  *
  * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no> Mon Aug 12 2002
  *
@@ -51,7 +51,9 @@ KPreferences::KPreferences(intf_thread_t *p_intf, const char *psz_module_name,
     KDialogBase ( Tabbed, caption, Ok| Apply|Cancel|User1, Ok, parent,
                   "vlc preferences", true, false, "Save")
 {
-    module_t *p_module, *p_module_bis;
+    module_t *p_module;
+    module_t **pp_parser;
+    vlc_list_t *p_list;
     module_config_t *p_item;
     QVBox *category_table = NULL;
     QString *category_label;
@@ -116,18 +118,22 @@ KPreferences::KPreferences(intf_thread_t *p_intf, const char *psz_module_name,
 
                 
                 /* build a list of available plugins */
-                
-#if 0 /* FIXME */
-                for( p_module_bis = p_intf->p_vlc->p_module_bank->first ;
-                     p_module_bis != NULL ;
-                     p_module_bis = p_module_bis->next ) {
-                    if( p_module_bis->i_capabilities & (1 << p_item->i_value)){
+                p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE,
+                                                FIND_ANYWHERE );
+                pp_parser = (module_t **)p_list->pp_objects;
+
+                for( ; *pp_parser ; pp_parser++ )
+                {
+                    if( !strcmp( (*pp_parser)->psz_capability,
+                                 p_item->psz_type ) )
+                    {
                         new QListViewItem(item_frame->getListView(),
-                                          p_module_bis->psz_object_name,
-                                          p_module_bis->psz_longname);
+                                          (*pp_parser)->psz_object_name,
+                                          (*pp_parser)->psz_longname);
                     }
                 }
-#endif
+                vlc_list_release( p_intf, p_list );
+
                 vlc_mutex_unlock( p_item->p_lock );
             }
             break;
index 8cceece5d37307e05ae313ed507e72cae1a11282..e29682ff9649067d0152f5ef486b9cc40862c2a8 100644 (file)
@@ -360,7 +360,10 @@ void __fastcall TPreferencesDlg::FormHide( TObject *Sender )
 \r
 void __fastcall TPreferencesDlg::CreateConfigDialog( char *psz_module_name )\r
 {\r
-    module_t           *p_module, *p_module_plugins;\r
+    module_t           *p_module;\r
+    module_t          **pp_parser;\r
+    vlc_list_t         *p_list;\r
+\r
     module_config_t    *p_item;\r
     int                 i_pages, i_ctrl;\r
     \r
@@ -422,20 +425,20 @@ void __fastcall TPreferencesDlg::CreateConfigDialog( char *psz_module_name )
             /* add panel as separator */\r
             ADD_PANEL;\r
 \r
-#if 0 /* FIXME */\r
-            /* build a list of available plugins */\r
-            for( p_module_plugins = p_intfGlobal->p_vlc->p_module_bank->first ;\r
-                 p_module_plugins != NULL ;\r
-                 p_module_plugins = p_module_plugins->next )\r
+            /* Look for valid modules */\r
+            p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );\r
+            pp_parser = (module_t **)p_list->pp_objects;\r
+\r
+            for( ; *pp_parser ; pp_parser++ )\r
             {\r
-                if( p_module_plugins->i_capabilities &\r
-                    ( 1 << p_item->i_value ) )\r
+                if( !strcmp( (*pp_parser)->psz_capability, p_item->psz_type ) )\r
                 {\r
                     ListItem = GroupBoxPlugin->ListView->Items->Add();\r
-                    ListItem->Caption = p_module_plugins->psz_object_name;\r
+                    ListItem->Caption = (*pp_parser)->psz_object_name;\r
                 }\r
             }\r
-#endif\r
+\r
+            vlc_list_release( p_intf, p_list );\r
 \r
             break;\r
 \r
index bb7e5f14d79a2160285bf36a75d1d681ae60f1d9..0dd888af8811da63defcec1668e9272331cb89f0 100644 (file)
@@ -2,7 +2,7 @@
  * modules.c : Builtin and plugin modules management functions
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: modules.c,v 1.85 2002/08/14 08:17:24 sam Exp $
+ * $Id: modules.c,v 1.86 2002/08/14 17:06:53 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Ethan C. Baldridge <BaldridgeE@cadmus.com>
@@ -170,7 +170,8 @@ void __module_EndBank( vlc_object_t *p_this )
 
             /* We just free the module by hand. Niahahahahaha. */
             p_next = p_this->p_vlc->p_module_bank->first->next;
-            free( p_this->p_vlc->p_module_bank->first );
+            vlc_object_detach( p_this->p_vlc->p_module_bank->first );
+            vlc_object_destroy( p_this->p_vlc->p_module_bank->first );
             p_this->p_vlc->p_module_bank->first = p_next;
         }
     }
@@ -748,6 +749,7 @@ static int AllocatePluginFile( vlc_object_t * p_this, char * psz_file )
     if( CallEntry( p_module ) != 0 )
     {
         /* We couldn't call module_init() */
+        msg_Err( p_this, "failed calling entry point in `%s'", psz_file );
         vlc_object_destroy( p_module );
         module_unload( handle );
         return -1;
index 15fef75c429e88ad185e64cf68e29c3490419b27..a46bc764602727b79cc3d8faf6b845697a8919a3 100644 (file)
@@ -298,11 +298,13 @@ static const char * module_error( char *psz_buffer )
     (p_symbols)->__msg_Unsubscribe_inner = __msg_Unsubscribe; \
     (p_symbols)->__vlc_object_create_inner = __vlc_object_create; \
     (p_symbols)->__vlc_object_destroy_inner = __vlc_object_destroy; \
+    (p_symbols)->__vlc_object_attach_inner = __vlc_object_attach; \
+    (p_symbols)->__vlc_object_detach_inner = __vlc_object_detach; \
     (p_symbols)->__vlc_object_find_inner = __vlc_object_find; \
     (p_symbols)->__vlc_object_yield_inner = __vlc_object_yield; \
     (p_symbols)->__vlc_object_release_inner = __vlc_object_release; \
-    (p_symbols)->__vlc_object_detach_inner = __vlc_object_detach; \
-    (p_symbols)->__vlc_object_attach_inner = __vlc_object_attach; \
+    (p_symbols)->__vlc_list_find_inner = __vlc_list_find; \
+    (p_symbols)->__vlc_list_release_inner = __vlc_list_release; \
     (p_symbols)->__vlc_liststructure_inner = __vlc_liststructure; \
     (p_symbols)->__vlc_dumpstructure_inner = __vlc_dumpstructure; \
     (p_symbols)->playlist_Command_inner = playlist_Command; \
index 62c1efa67d764ff07c73256c479de9745032e921..24f42f558dd97bb78f587fb90a2c0f44f4f64db0 100644 (file)
@@ -2,7 +2,7 @@
  * objects.c: vlc_object_t handling
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: objects.c,v 1.17 2002/08/14 08:17:24 sam Exp $
+ * $Id: objects.c,v 1.18 2002/08/14 17:06:53 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static vlc_object_t * vlc_object_find_inner( vlc_object_t *, int, int );
-static void vlc_object_detach_inner( vlc_object_t * );
-static void vlc_dumpstructure_inner( vlc_object_t *, int, char * );
-static int  find_index_inner( vlc_object_t *, vlc_object_t **, int );
-static void set_attachment_flag( vlc_object_t *, vlc_bool_t );
+static vlc_object_t * FindObject    ( vlc_object_t *, int, int );
+static void           DetachObject  ( vlc_object_t * );
+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 vlc_list_t *   NewList       ( void );
+static vlc_list_t *   ListAppend    ( vlc_list_t *, vlc_object_t * );
 
 /*****************************************************************************
  * vlc_object_create: initialize a vlc object
@@ -228,11 +232,12 @@ void __vlc_object_destroy( vlc_object_t *p_this )
      * useless to try and recover anything if pp_objects gets smashed. */
     if( p_this->p_vlc->i_objects > 1 )
     {
-        int i_index = find_index_inner( p_this, p_this->p_vlc->pp_objects,
-                                                p_this->p_vlc->i_objects );
+        int i_index = FindIndex( p_this, p_this->p_vlc->pp_objects,
+                                         p_this->p_vlc->i_objects );
         memmove( p_this->p_vlc->pp_objects + i_index,
                  p_this->p_vlc->pp_objects + i_index + 1,
-                 p_this->p_vlc->i_objects - i_index - 1 );
+                 (p_this->p_vlc->i_objects - i_index - 1)
+                   * sizeof( vlc_object_t *) );
 
         p_this->p_vlc->pp_objects =
             realloc( p_this->p_vlc->pp_objects,
@@ -254,46 +259,6 @@ void __vlc_object_destroy( vlc_object_t *p_this )
     free( p_this );
 }
 
-/*****************************************************************************
- * find_index_inner: 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 random 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 find_index_inner( 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 + find_index_inner( p_this, pp_objects + i_middle,
-                                                    i_count - i_middle );
-    }
-    else
-    {
-        return find_index_inner( p_this, pp_objects, i_middle );
-    }
-}
-
 /*****************************************************************************
  * vlc_object_find: find a typed object and increment its refcount
  *****************************************************************************
@@ -317,13 +282,12 @@ 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 = vlc_object_find_inner( VLC_OBJECT(p_this->p_vlc),
-                                         i_type,
-                                         (i_mode & ~0x000f) | FIND_CHILD );
+        p_found = FindObject( VLC_OBJECT(p_this->p_vlc), i_type,
+                              (i_mode & ~0x000f) | FIND_CHILD );
     }
     else
     {
-        p_found = vlc_object_find_inner( p_this, i_type, i_mode );
+        p_found = FindObject( p_this, i_type, i_mode );
     }
 
     vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
@@ -331,58 +295,6 @@ void * __vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode )
     return p_found;
 }
 
-static vlc_object_t * vlc_object_find_inner( 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 vlc_object_find_inner( 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 = vlc_object_find_inner( p_tmp, i_type, i_mode );
-                if( p_tmp )
-                {
-                    return p_tmp;
-                }
-            }
-        }
-        break;
-
-    case FIND_ANYWHERE:
-        /* Handled in vlc_object_find */
-        break;
-    }
-
-    return NULL;
-}
-
 /*****************************************************************************
  * vlc_object_yield: increment an object refcount
  *****************************************************************************/
@@ -425,7 +337,7 @@ void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent )
     /* Climb up the tree to see whether we are connected with the root */
     if( p_parent->b_attached )
     {
-        set_attachment_flag( p_this, VLC_TRUE );
+        SetAttachment( p_this, VLC_TRUE );
     }
 
     vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
@@ -449,14 +361,219 @@ void __vlc_object_detach( vlc_object_t *p_this )
     /* Climb up the tree to see whether we are connected with the root */
     if( p_this->p_parent->b_attached )
     {
-        set_attachment_flag( p_this, VLC_FALSE );
+        SetAttachment( p_this, VLC_FALSE );
+    }
+
+    DetachObject( p_this );
+    vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
+}
+
+/*****************************************************************************
+ * vlc_list_find: 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_mutex_lock( &p_this->p_vlc->structure_lock );
+
+    /* Look for the objects */
+    if( (i_mode & 0x000f) == FIND_ANYWHERE )
+    {
+        vlc_object_t **pp_current, **pp_end;
+
+        pp_current = p_this->p_vlc->pp_objects;
+        pp_end = pp_current + p_this->p_vlc->i_objects;
+
+        for( ; pp_current < pp_end ; pp_current++ )
+        {
+            if( (*pp_current)->b_attached
+                 && (*pp_current)->i_object_type == i_type )
+            {
+                p_list = ListAppend( p_list, *pp_current );
+            }
+        }
+    }
+    else
+    {
+        msg_Err( p_this, "unimplemented!" );
+    }
+
+    vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
+
+    return p_list;
+}
+
+/*****************************************************************************
+ * vlc_liststructure: print the current vlc objects
+ *****************************************************************************
+ * This function prints an ASCII tree showing the connections between vlc
+ * objects, and additional information such as their refcount, thread ID,
+ * address, etc.
+ *****************************************************************************/
+void __vlc_liststructure( vlc_object_t *p_this )
+{
+    vlc_object_t **pp_current, **pp_end;
+
+    vlc_mutex_lock( &p_this->p_vlc->structure_lock );
+
+    pp_current = p_this->p_vlc->pp_objects;
+    pp_end = pp_current + p_this->p_vlc->i_objects;
+
+    for( ; pp_current < pp_end ; pp_current++ )
+    {
+        if( (*pp_current)->b_attached )
+        {
+            PrintObject( *pp_current, "" );
+        }
+        else
+        {
+            msg_Info( p_this->p_vlc, "o %.6x %s (not attached)",
+                      (*pp_current)->i_object_id,
+                      (*pp_current)->psz_object_type );
+        }
     }
 
-    vlc_object_detach_inner( p_this );
     vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
 }
 
-static void vlc_object_detach_inner( vlc_object_t *p_this )
+/*****************************************************************************
+ * vlc_dumpstructure: print the current vlc structure
+ *****************************************************************************
+ * This function prints an ASCII tree showing the connections between vlc
+ * objects, and additional information such as their refcount, thread ID,
+ * address, etc.
+ *****************************************************************************/
+void __vlc_dumpstructure( vlc_object_t *p_this )
+{
+    char psz_foo[2 * MAX_DUMPSTRUCTURE_DEPTH + 1];
+
+    vlc_mutex_lock( &p_this->p_vlc->structure_lock );
+    psz_foo[0] = '|';
+    DumpStructure( p_this, 0, psz_foo );
+    vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
+}
+
+/*****************************************************************************
+ * 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_object_t *p_this, vlc_list_t *p_list )
+{
+    vlc_object_t **p_current = p_list->pp_objects;
+
+    vlc_mutex_lock( &p_this->p_vlc->structure_lock );
+
+    while( p_current[0] )
+    {
+        p_current[0]->i_refcount--;
+        p_current++;
+    }
+
+    vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
+
+    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;
+    }
+
+    return NULL;
+}
+
+static void DetachObject( vlc_object_t *p_this )
 {
     vlc_object_t *p_parent = p_this->p_parent;
     int i_index, i;
@@ -490,24 +607,24 @@ static void vlc_object_detach_inner( vlc_object_t *p_this )
 }
 
 /*****************************************************************************
- * set_attachment_flag: recursively set the b_attached flag of a subtree.
+ * SetAttachment: recursively set the b_attached flag of a subtree.
  *****************************************************************************
  * This function is used by the attach and detach functions to propagate
  * the b_attached flag in a subtree.
  *****************************************************************************/
-static void set_attachment_flag( vlc_object_t *p_this, vlc_bool_t b_attached )
+static void SetAttachment( vlc_object_t *p_this, vlc_bool_t b_attached )
 {
     int i_index;
 
     for( i_index = p_this->i_children ; i_index-- ; )
     {
-        set_attachment_flag( p_this->pp_children[i_index], b_attached );
+        SetAttachment( p_this->pp_children[i_index], b_attached );
     }
 
     p_this->b_attached = b_attached;
 }
 
-static void vlc_print_object( vlc_object_t *p_this, const char *psz_prefix )
+static void PrintObject( vlc_object_t *p_this, const char *psz_prefix )
 {
     char psz_children[20], psz_refcount[20], psz_thread[20], psz_name[50];
 
@@ -553,65 +670,13 @@ static void vlc_print_object( vlc_object_t *p_this, const char *psz_prefix )
               psz_name, psz_thread, psz_refcount, psz_children );
 }
 
-/*****************************************************************************
- * vlc_liststructure: print the current vlc objects
- *****************************************************************************
- * This function prints an ASCII tree showing the connections between vlc
- * objects, and additional information such as their refcount, thread ID,
- * address, etc.
- *****************************************************************************/
-void __vlc_liststructure( vlc_object_t *p_this )
-{
-    vlc_object_t ** p_all;
-    vlc_object_t *  p_current;
-    int             i_total;
-
-    vlc_mutex_lock( &p_this->p_vlc->structure_lock );
-
-    i_total = p_this->p_vlc->i_objects;
-    p_all = p_this->p_vlc->pp_objects;
-
-    for( p_current = p_all[0] ; p_current < p_all[i_total] ; p_current++ )
-    {
-        if( p_current->b_attached )
-        {
-            vlc_print_object( p_current, "" );
-        }
-        else
-        {
-            msg_Info( p_this->p_vlc, "o %.6x %s (not attached)",
-                      p_current->i_object_id, p_current->psz_object_type );
-        }
-    }
-
-    vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
-}
-
-/*****************************************************************************
- * vlc_dumpstructure: print the current vlc structure
- *****************************************************************************
- * This function prints an ASCII tree showing the connections between vlc
- * objects, and additional information such as their refcount, thread ID,
- * address, etc.
- *****************************************************************************/
-void __vlc_dumpstructure( vlc_object_t *p_this )
-{
-    char psz_foo[2 * MAX_DUMPSTRUCTURE_DEPTH + 1];
-
-    vlc_mutex_lock( &p_this->p_vlc->structure_lock );
-    psz_foo[0] = '|';
-    vlc_dumpstructure_inner( p_this, 0, psz_foo );
-    vlc_mutex_unlock( &p_this->p_vlc->structure_lock );
-}
-
-static void vlc_dumpstructure_inner( vlc_object_t *p_this,
-                                     int i_level, char *psz_foo )
+static void DumpStructure( vlc_object_t *p_this, int i_level, char *psz_foo )
 {
     int i;
     char i_back = psz_foo[i_level];
     psz_foo[i_level] = '\0';
 
-    vlc_print_object( p_this, psz_foo );
+    PrintObject( p_this, psz_foo );
 
     psz_foo[i_level] = i_back;
 
@@ -645,7 +710,62 @@ static void vlc_dumpstructure_inner( vlc_object_t *p_this,
         psz_foo[i_level+1] = '-';
         psz_foo[i_level+2] = '\0';
 
-        vlc_dumpstructure_inner( p_this->pp_children[i], i_level + 2, psz_foo );
+        DumpStructure( p_this->pp_children[i], i_level + 2, psz_foo );
+    }
+}
+
+static vlc_list_t * NewList( void )
+{
+    vlc_list_t *p_list = malloc( sizeof( vlc_list_t )
+                                     + 3 * sizeof( vlc_object_t * ) );
+
+    if( p_list == NULL )
+    {
+        return NULL;
+    }
+
+    p_list->i_count = 0;
+    p_list->pp_objects = &p_list->_p_first;
+
+    /* We allocated space for NULL and for three extra objects */
+    p_list->_i_extra = 3;
+    p_list->_p_first = NULL;
+
+    return p_list;
+}
+
+static vlc_list_t * ListAppend( vlc_list_t *p_list, vlc_object_t *p_object )
+{
+    if( p_list == NULL )
+    {
+        return NULL;
     }
+
+    if( p_list->_i_extra == 0 )
+    {
+        /* 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;
+        }
+
+        /* We have X+1 extra slots */
+        p_list->_i_extra = p_list->i_count + 1;
+        p_list->pp_objects = &p_list->_p_first;
+    }
+
+    p_object->i_refcount++;
+
+    p_list->pp_objects[p_list->i_count] = p_object;
+    p_list->i_count++;
+    p_list->pp_objects[p_list->i_count] = NULL;
+    p_list->_i_extra--;
+
+    return p_list;
 }