]> git.sesse.net Git - vlc/blobdiff - src/misc/modules.c
* Make it possible to give names to vlc objects (psz_object_name
[vlc] / src / misc / modules.c
index 48e23aabfca654405ff420eddfc76a34bd7ac8c9..ade1fbc9a9b827ead9816f90ca8119b0529abaac 100644 (file)
 #   endif
 #endif
 
-#include "vlc_interface.h"
+#include "misc/configuration.h"
 
+#include "vlc_interface.h"
 #include "vlc_playlist.h"
 
+#include "vlc_stream.h"
+#include "vlc_access.h"
+#include "vlc_demux.h"
+
 #include "vlc_vout.h"
 #include "vlc_vout_synchro.h"
 
@@ -132,7 +137,7 @@ static int  AllocatePluginFile  ( vlc_object_t *, char *, int64_t, int64_t );
 static module_t * AllocatePlugin( vlc_object_t *, char * );
 #endif
 static int  AllocateBuiltinModule( vlc_object_t *, int ( * ) ( module_t * ) );
-static int  DeleteModule ( module_t * );
+static int  DeleteModule ( module_t *, vlc_bool_t );
 #ifdef HAVE_DYNAMIC_PLUGINS
 static void   DupModule        ( module_t * );
 static void   UndupModule      ( module_t * );
@@ -153,6 +158,8 @@ static char * GetWindowsError  ( void );
 #endif
 #endif
 
+static void module_LoadMain( vlc_object_t *p_this );
+
 
 /* Sub-version number
  * (only used to avoid breakage in dev version when cache structure changes) */
@@ -166,7 +173,7 @@ static char * GetWindowsError  ( void );
  *****************************************************************************/
 void __module_InitBank( vlc_object_t *p_this )
 {
-    module_bank_t *p_bank;
+    module_bank_t *p_bank = NULL;
     vlc_value_t  lockval;
 
     var_Create( p_this->p_libvlc_global, "libvlc", VLC_VAR_MUTEX );
@@ -183,10 +190,12 @@ void __module_InitBank( vlc_object_t *p_this )
     var_Destroy( p_this->p_libvlc_global, "libvlc" );
 
     p_bank = vlc_object_create( p_this, sizeof(module_bank_t) );
+    if( !p_bank )
+        return;
     p_bank->psz_object_name = "module bank";
     p_bank->i_usage = 1;
     p_bank->i_cache = p_bank->i_loaded_cache = 0;
-    p_bank->pp_cache = p_bank->pp_loaded_cache = 0;
+    p_bank->pp_cache = p_bank->pp_loaded_cache = NULL;
     p_bank->b_cache = p_bank->b_cache_dirty =
         p_bank->b_cache_delete = VLC_FALSE;
 
@@ -202,8 +211,6 @@ void __module_InitBank( vlc_object_t *p_this )
     vlc_object_attach( p_bank, p_this->p_libvlc_global );
 
     module_LoadMain( p_this );
-
-    return;
 }
 
 /*****************************************************************************
@@ -226,7 +233,7 @@ void __module_ResetBank( vlc_object_t *p_this )
  *****************************************************************************/
 void __module_EndBank( vlc_object_t *p_this )
 {
-    module_t * p_next;
+    module_t * p_next = NULL;
     vlc_value_t lockval;
 
     var_Create( p_this->p_libvlc_global, "libvlc", VLC_VAR_MUTEX );
@@ -254,19 +261,30 @@ void __module_EndBank( vlc_object_t *p_this )
     if( p_bank->b_cache ) CacheSave( p_this );
     while( p_bank->i_loaded_cache-- )
     {
-        free( p_bank->pp_loaded_cache[p_bank->i_loaded_cache]->psz_file );
-        free( p_bank->pp_loaded_cache[p_bank->i_loaded_cache] );
+        if( p_bank->pp_loaded_cache[p_bank->i_loaded_cache] )
+        {
+            DeleteModule( p_bank->pp_loaded_cache[p_bank->i_loaded_cache]->p_module, p_bank->pp_loaded_cache[p_bank->i_loaded_cache]->b_used );
+            free( p_bank->pp_loaded_cache[p_bank->i_loaded_cache]->psz_file );
+            free( p_bank->pp_loaded_cache[p_bank->i_loaded_cache] );
+            p_bank->pp_loaded_cache[p_bank->i_loaded_cache] = NULL;
+        }
     }
     if( p_bank->pp_loaded_cache )
+    {
         free( p_bank->pp_loaded_cache );
-
+        p_bank->pp_loaded_cache = NULL;
+    }
     while( p_bank->i_cache-- )
     {
         free( p_bank->pp_cache[p_bank->i_cache]->psz_file );
         free( p_bank->pp_cache[p_bank->i_cache] );
+        p_bank->pp_cache[p_bank->i_cache] = NULL;
     }
     if( p_bank->pp_cache )
+    {
         free( p_bank->pp_cache );
+        p_bank->pp_cache = NULL;
+    }
 #undef p_bank
 #endif
 
@@ -276,7 +294,7 @@ void __module_EndBank( vlc_object_t *p_this )
     {
         p_next = (module_t *)p_this->p_libvlc_global->p_module_bank->pp_children[0];
 
-        if( DeleteModule( p_next ) )
+        if( DeleteModule( p_next, VLC_TRUE ) )
         {
             /* Module deletion failed */
             msg_Err( p_this, "module \"%s\" can't be removed, trying harder",
@@ -302,7 +320,7 @@ void __module_EndBank( vlc_object_t *p_this )
  * as another module, and for instance the configuration options of main will
  * be available in the module bank structure just as for every other module.
  *****************************************************************************/
-void __module_LoadMain( vlc_object_t *p_this )
+static void module_LoadMain( vlc_object_t *p_this )
 {
     vlc_value_t lockval;
 
@@ -410,7 +428,7 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
     module_t *p_module;
 
     int   i_shortcuts = 0;
-    char *psz_shortcuts = NULL, *psz_var = NULL;
+    char *psz_shortcuts = NULL, *psz_var = NULL, *psz_alias = NULL;
     vlc_bool_t b_force_backup = p_this->b_force;
 
 
@@ -495,54 +513,39 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
         if( i_shortcuts > 0 )
         {
             vlc_bool_t b_trash;
-            int i_dummy, i_short = i_shortcuts;
-            char *psz_name = psz_shortcuts;
+            const char *psz_name = psz_shortcuts;
 
             /* Let's drop modules with a <= 0 score (unless they are
              * explicitly requested) */
             b_trash = p_module->i_score <= 0;
 
-            while( i_short > 0 )
+            for( unsigned i_short = i_shortcuts; i_short > 0; i_short-- )
             {
-                for( i_dummy = 0; p_module->pp_shortcuts[i_dummy]; i_dummy++ )
+                for( unsigned i = 0; p_module->pp_shortcuts[i]; i++ )
                 {
-                    if( !strcasecmp( psz_name,
-                                     p_module->pp_shortcuts[i_dummy] ) )
+                    char *c;
+                    if( ( c = strchr( psz_name, '@' ) )
+                        ? !strncasecmp( psz_name, p_module->pp_shortcuts[i],
+                                        c-psz_name )
+                        : !strcasecmp( psz_name, p_module->pp_shortcuts[i] ) )
                     {
                         /* Found it */
-                        b_trash = VLC_FALSE;
+                        if( c && c[1] )
+                            psz_alias = c+1;
                         i_shortcut_bonus = i_short * 10000;
-                        break;
+                        goto found_shortcut;
                     }
                 }
 
-                if( i_shortcut_bonus )
-                {
-                    /* We found it... remember ? */
-                    break;
-                }
-
                 /* Go to the next shortcut... This is so lame! */
-                while( *psz_name )
-                {
-                    psz_name++;
-                }
-                psz_name++;
-                i_short--;
+                psz_name += strlen( psz_name ) + 1;
             }
 
             /* If we are in "strict" mode and we couldn't
              * find the module in the list of provided shortcuts,
              * then kick the bastard out of here!!! */
-            if( i_short == 0 && b_strict )
-            {
-                b_trash = VLC_TRUE;
-            }
-
-            if( b_trash )
-            {
+            if( b_strict )
                 continue;
-            }
         }
         /* If we didn't require a shortcut, trash <= 0 scored plugins */
         else if( p_module->i_score <= 0 )
@@ -550,6 +553,8 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
             continue;
         }
 
+found_shortcut:
+
         /* Special case: test if we requested a particular intf plugin */
         if( !i_shortcuts && p_module->psz_program
              && !strcmp( psz_capability, "interface" )
@@ -628,8 +633,10 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
     {
 #ifdef HAVE_DYNAMIC_PLUGINS
         /* Make sure the module is loaded in mem */
-        module_t *p_module = p_tmp->p_module->b_submodule ?
-            (module_t *)p_tmp->p_module->p_parent : p_tmp->p_module;
+        module_t *p_module = p_tmp->p_module;
+        if( p_module->b_submodule )
+            p_module = (module_t *)p_module->p_parent;
+
         if( !p_module->b_builtin && !p_module->b_loaded )
         {
             module_t *p_new_module =
@@ -638,7 +645,7 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
             {
                 CacheMerge( p_this, p_module, p_new_module );
                 vlc_object_attach( p_new_module, p_module );
-                DeleteModule( p_new_module );
+                DeleteModule( p_new_module, VLC_TRUE );
             }
         }
 #endif
@@ -691,6 +698,9 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
         {
             msg_Err( p_this, "no %s module matched \"%s\"",
                  psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
+
+            msg_StackSet( VLC_EGENERIC, "no %s module matched \"%s\"",
+                 psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
         }
     }
     else if( psz_name != NULL && *psz_name )
@@ -698,6 +708,14 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
         msg_Warn( p_this, "no %s module matching \"%s\" could be loaded",
                   psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
     }
+    else
+        msg_StackSet( VLC_EGENERIC, "no suitable %s module", psz_capability );
+
+    if( psz_alias && !p_this->psz_object_name )
+        /* This assumes that p_this is the object which will be using the
+         * module. That's not always the case ... but it is in most cases.
+         */
+        p_this->psz_object_name = strdup( psz_alias );
 
     if( psz_shortcuts )
     {
@@ -734,6 +752,31 @@ void __module_Unneed( vlc_object_t * p_this, module_t * p_module )
     return;
 }
 
+/*****************************************************************************
+ * module_Exists: tell if a module exists.
+ *****************************************************************************
+ * This function is a boolean function that tells if a module exist or not.
+ *****************************************************************************/
+
+vlc_bool_t __module_Exists(  vlc_object_t *p_this, const char * psz_name )
+{
+    vlc_list_t *p_list;
+    int i;
+    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
+    for( i = 0 ; i < p_list->i_count; i++)
+    {
+        if (!strcmp(
+              ((module_t *) p_list->p_values[i].p_object)->psz_shortname ,
+              psz_name ) )
+        {
+            /* We can release the list, and return yes */
+            vlc_list_release( p_list ); return VLC_TRUE;
+        }
+    }
+    vlc_list_release( p_list ); return VLC_FALSE;
+}
+
+
 /*****************************************************************************
  * Following functions are local.
  *****************************************************************************/
@@ -991,7 +1034,7 @@ static void AllocatePluginDir( vlc_object_t *p_this, const char *psz_dir,
 static int AllocatePluginFile( vlc_object_t * p_this, char * psz_file,
                                int64_t i_file_time, int64_t i_file_size )
 {
-    module_t * p_module;
+    module_t * p_module = NULL;
     module_cache_t *p_cache_entry = NULL;
 
     /*
@@ -1013,7 +1056,7 @@ static int AllocatePluginFile( vlc_object_t * p_this, char * psz_file,
         }
         else
         {
-            module_config_t *p_item, *p_end;
+            module_config_t *p_item = NULL, *p_end = NULL;
 
             p_module = p_cache_entry->p_module;
             p_module->b_loaded = VLC_FALSE;
@@ -1025,8 +1068,13 @@ static int AllocatePluginFile( vlc_object_t * p_this, char * psz_file,
                  p_item < p_end; p_item++ )
             {
                 if( p_item->pf_callback || p_item->i_action )
+                {
                     p_module = AllocatePlugin( p_this, psz_file );
+                    break;
+                }
             }
+            if( p_module == p_cache_entry->p_module )
+                p_cache_entry->b_used = VLC_TRUE;
         }
     }
 
@@ -1040,21 +1088,25 @@ static int AllocatePluginFile( vlc_object_t * p_this, char * psz_file,
                     p_module->psz_object_name, p_module->psz_longname ); */
 
         vlc_object_attach( p_module, p_this->p_libvlc_global->p_module_bank );
-    }
 
-    if( !p_this->p_libvlc_global->p_module_bank->b_cache ) return 0;
+        if( !p_this->p_libvlc_global->p_module_bank->b_cache )
+            return 0;
 
-    /* Add entry to cache */
+        /* Add entry to cache */
 #define p_bank p_this->p_libvlc_global->p_module_bank
-    p_bank->pp_cache =
-        realloc( p_bank->pp_cache, (p_bank->i_cache + 1) * sizeof(void *) );
-    p_bank->pp_cache[p_bank->i_cache] = malloc( sizeof(module_cache_t) );
-    p_bank->pp_cache[p_bank->i_cache]->psz_file = strdup( psz_file );
-    p_bank->pp_cache[p_bank->i_cache]->i_time = i_file_time;
-    p_bank->pp_cache[p_bank->i_cache]->i_size = i_file_size;
-    p_bank->pp_cache[p_bank->i_cache]->b_junk = p_module ? 0 : 1;
-    p_bank->pp_cache[p_bank->i_cache]->p_module = p_module;
-    p_bank->i_cache++;
+        p_bank->pp_cache =
+            realloc( p_bank->pp_cache, (p_bank->i_cache + 1) * sizeof(void *) );
+        p_bank->pp_cache[p_bank->i_cache] = malloc( sizeof(module_cache_t) );
+        if( !p_bank->pp_cache[p_bank->i_cache] )
+            return -1;
+        p_bank->pp_cache[p_bank->i_cache]->psz_file = strdup( psz_file );
+        p_bank->pp_cache[p_bank->i_cache]->i_time = i_file_time;
+        p_bank->pp_cache[p_bank->i_cache]->i_size = i_file_size;
+        p_bank->pp_cache[p_bank->i_cache]->b_junk = p_module ? 0 : 1;
+        p_bank->pp_cache[p_bank->i_cache]->b_used = VLC_TRUE;
+        p_bank->pp_cache[p_bank->i_cache]->p_module = p_module;
+        p_bank->i_cache++;
+    }
 
     return p_module ? 0 : -1;
 }
@@ -1068,10 +1120,11 @@ static int AllocatePluginFile( vlc_object_t * p_this, char * psz_file,
  *****************************************************************************/
 static module_t * AllocatePlugin( vlc_object_t * p_this, char * psz_file )
 {
-    module_t * p_module;
+    module_t * p_module = NULL;
     module_handle_t handle;
 
-    if( LoadModule( p_this, psz_file, &handle ) ) return NULL;
+    if( LoadModule( p_this, psz_file, &handle ) )
+        return NULL;
 
     /* Now that we have successfully loaded the module, we can
      * allocate a structure for it */
@@ -1224,9 +1277,11 @@ static int AllocateBuiltinModule( vlc_object_t * p_this,
  *****************************************************************************
  * This function can only be called if the module isn't being used.
  *****************************************************************************/
-static int DeleteModule( module_t * p_module )
+static int DeleteModule( module_t * p_module, vlc_bool_t b_detach )
 {
-    vlc_object_detach( p_module );
+    if( !p_module ) return VLC_EGENERIC;
+    if( b_detach )
+        vlc_object_detach( p_module );
 
     /* We free the structures that we strdup()ed in Allocate*Module(). */
 #ifdef HAVE_DYNAMIC_PLUGINS
@@ -1251,7 +1306,7 @@ static int DeleteModule( module_t * p_module )
 
     config_Free( p_module );
     vlc_object_destroy( p_module );
-
+    p_module = NULL;
     return 0;
 }
 
@@ -1733,6 +1788,7 @@ static void CacheLoad( vlc_object_t *p_this )
         LOAD_IMMEDIATE( pp_cache[i]->i_time );
         LOAD_IMMEDIATE( pp_cache[i]->i_size );
         LOAD_IMMEDIATE( pp_cache[i]->b_junk );
+        pp_cache[i]->b_used = VLC_FALSE;
 
         if( pp_cache[i]->b_junk ) continue;
 
@@ -2175,7 +2231,7 @@ static void CacheMerge( vlc_object_t *p_this, module_t *p_cache,
 }
 
 /*****************************************************************************
- * FindPluginCache: finds the cache entry corresponding to a file
+ * CacheFind: finds the cache entry corresponding to a file
  *****************************************************************************/
 static module_cache_t *CacheFind( vlc_object_t *p_this, char *psz_file,
                                   int64_t i_time, int64_t i_size )