]> git.sesse.net Git - vlc/blobdiff - src/modules/modules.c
Forgotten people in THANKS...
[vlc] / src / modules / modules.c
index 5edffa05dae544df73515f19b1da1b4d8e596525..b4a1ca3c2e152352aeec484be578b918c2f19948 100644 (file)
@@ -148,28 +148,40 @@ void __module_InitBank( vlc_object_t *p_this )
     else
         p_module_bank->i_usage++;
 
-    vlc_mutex_unlock( &module_lock );
+    /* We do retain the module bank lock until the plugins are loaded as well.
+     * This is ugly, this staged loading approach is needed: LibVLC gets
+     * some configuration parameters relevant to loading the plugins from
+     * the main (builtin) module. The module bank becomes shared read-only data
+     * once it is ready, so we need to fully serialize initialization.
+     * DO NOT UNCOMMENT the following line unless you managed to squeeze
+     * module_LoadPlugins() before you unlock the mutex. */
+    /*vlc_mutex_unlock( &module_lock );*/
 }
 
-
+#undef module_EndBank
 /**
- * End bank
- *
  * Unloads all unused plugin modules and empties the module
  * bank in case of success.
  * \param p_this vlc object structure
  * \return nothing
  */
-void __module_EndBank( vlc_object_t *p_this )
+void module_EndBank( vlc_object_t *p_this, bool b_plugins )
 {
-    module_bank_t *p_bank;
+    module_bank_t *p_bank = p_module_bank;
+
+    assert (p_bank != NULL);
 
     /* Save the configuration */
-    config_AutoSaveConfigFile( p_this );
+    if( !config_GetInt( p_this, "ignore-config" ) )
+        config_AutoSaveConfigFile( p_this );
+
+    /* If plugins were _not_ loaded, then the caller still has the bank lock
+     * from module_InitBank(). */
+    if( b_plugins )
+        vlc_mutex_lock( &module_lock );
+    /*else
+        vlc_assert_locked( &module_lock ); not for static mutexes :( */
 
-    vlc_mutex_lock( &module_lock );
-    p_bank = p_module_bank;
-    assert (p_bank != NULL);
     if( --p_bank->i_usage > 0 )
     {
         vlc_mutex_unlock( &module_lock );
@@ -218,34 +230,32 @@ void __module_EndBank( vlc_object_t *p_this )
 
 #undef module_LoadPlugins
 /**
- * Load all plugins
- *
- * Load all plugin modules we can find.
+ * Loads module descriptions for all available plugins.
  * Fills the module bank structure with the plugin modules.
+ *
  * \param p_this vlc object structure
  * \return nothing
  */
 void module_LoadPlugins( vlc_object_t * p_this, bool b_cache_delete )
 {
+    module_bank_t *p_bank = p_module_bank;
+
+    assert( p_bank );
+    /*vlc_assert_locked( &module_lock ); not for static mutexes :( */
+
 #ifdef HAVE_DYNAMIC_PLUGINS
-    vlc_mutex_lock( &module_lock );
-    if( p_module_bank->b_plugins )
+    if( p_bank->i_usage == 1 )
     {
-        vlc_mutex_unlock( &module_lock );
-        return;
+        msg_Dbg( p_this, "checking plugin modules" );
+        p_module_bank->b_cache = config_GetInt( p_this, "plugins-cache" ) > 0;
+
+        if( p_module_bank->b_cache || b_cache_delete )
+            CacheLoad( p_this, p_module_bank, b_cache_delete );
+        AllocateAllPlugins( p_this, p_module_bank );
     }
+#endif
     p_module_bank->b_plugins = true;
     vlc_mutex_unlock( &module_lock );
-
-    msg_Dbg( p_this, "checking plugin modules" );
-    p_module_bank->b_cache = config_GetInt( p_this, "plugins-cache" ) > 0;
-
-    if( p_module_bank->b_cache || b_cache_delete )
-        CacheLoad( p_this, p_module_bank, b_cache_delete );
-
-    /* FIXME: race - do this under the lock */
-    AllocateAllPlugins( p_this, p_module_bank );
-#endif
 }
 
 /**
@@ -283,7 +293,7 @@ const char *module_get_name( const module_t *m, bool long_name )
     if( long_name && ( m->psz_longname != NULL) )
         return m->psz_longname;
 
-    return m->psz_shortname ?: m->psz_object_name;
+    return m->psz_shortname ? m->psz_shortname : m->psz_object_name;
 }
 
 /**
@@ -525,11 +535,10 @@ module_t * __module_need( vlc_object_t *p_this, const char *psz_capability,
             if( b_strict )
                 continue;
         }
-        /* If we didn't require a shortcut, trash <= 0 scored plugins */
-        else if( p_module->i_score <= 0 )
-        {
+
+        /* Trash <= 0 scored plugins (they can only be selected by shortcut) */
+        if( p_module->i_score <= 0 )
             continue;
-        }
 
 found_shortcut:
         /* Store this new module */
@@ -546,14 +555,8 @@ found_shortcut:
 
     /* Sort candidates by descending score */
     qsort (p_list, count, sizeof (p_list[0]), modulecmp);
-#ifdef WIN32
-    /* FIXME: Remove this hack after finding a general solution for %z's */
-    msg_Dbg( p_this, "looking for %s module: %u candidate%s", psz_capability,
-             count, count == 1 ? "" : "s" );
-#else
     msg_Dbg( p_this, "looking for %s module: %zu candidate%s", psz_capability,
              count, count == 1 ? "" : "s" );
-#endif
 
     /* Parse the linked list and use the first successful module */
     p_module = NULL;
@@ -762,16 +765,18 @@ char ** module_GetModulesNamesForCapability( const char *psz_capability,
 
     module_t **list = module_list_get (NULL);
 
-    /* Do it in two passes : count the number of modules before */
+    /* Proceed in two passes: count the number of modules first */
     for (size_t i = 0; list[i]; i++)
     {
         module_t *p_module = list[i];
         const char *psz_module_capability = p_module->psz_capability;
 
-        if( psz_module_capability && !strcmp( psz_module_capability, psz_capability ) )
+        if( psz_module_capability
+         && !strcmp( psz_module_capability, psz_capability ) )
             count++;
     }
 
+    /* Then get the names */
     psz_ret = malloc( sizeof(char*) * (count+1) );
     if( pppsz_longname )
         *pppsz_longname = malloc( sizeof(char*) * (count+1) );
@@ -792,16 +797,17 @@ char ** module_GetModulesNamesForCapability( const char *psz_capability,
         module_t *p_module = list[i];
         const char *psz_module_capability = p_module->psz_capability;
 
-        if( psz_module_capability && !strcmp( psz_module_capability, psz_capability ) )
+        if( psz_module_capability
+         && !strcmp( psz_module_capability, psz_capability ) )
         {
-            int k = -1; /* hack to handle submodules properly */
-            if( p_module->b_submodule )
-            {
-                while( p_module->pp_shortcuts[++k] != NULL );
-                k--;
-            }
-            psz_ret[j] = strdup( k>=0?p_module->pp_shortcuts[k]
-                                     :p_module->psz_object_name );
+            /* Explicit hack: Use the last shortcut. It _should_ be
+             * different from the object name, at least if the object
+             * contains multiple submodules with the same capability. */
+            unsigned k = 0;
+            while( p_module->pp_shortcuts[k] != NULL )
+                k++;
+            assert( k > 0); /* pp_shortcuts[0] is always set */
+            psz_ret[j] = strdup( p_module->pp_shortcuts[k - 1] );
             if( pppsz_longname )
                 (*pppsz_longname)[j] = strdup( module_get_name( p_module, true ) );
             j++;
@@ -1050,7 +1056,7 @@ static void AllocatePluginDir( vlc_object_t *p_this, module_bank_t *p_bank,
         if( GetFileAttributes( psz_path ) & FILE_ATTRIBUTE_DIRECTORY )
 #endif
         {
-            AllocatePluginDir( p_this, psz_path, i_maxdepth - 1 );
+            AllocatePluginDir( p_this, p_bank, psz_path, i_maxdepth - 1 );
         }
         else if( i_len > strlen( LIBEXT )
                   /* We only load files ending with LIBEXT */
@@ -1078,7 +1084,7 @@ static void AllocatePluginDir( vlc_object_t *p_this, module_bank_t *p_bank,
             }
             psz_file = psz_path;
 
-            AllocatePluginFile( p_this, psz_file, i_time, i_size );
+            AllocatePluginFile( p_this, p_bank, psz_file, i_time, i_size );
         }
     }
     while( !p_this->p_libvlc->b_die && FindNextFile( handle, &finddata ) );
@@ -1166,66 +1172,65 @@ static int AllocatePluginFile( vlc_object_t * p_this, module_bank_t *p_bank,
         p_module = AllocatePlugin( p_this, psz_file );
     }
     else
+    /* If junk dll, don't try to load it */
+    if( p_cache_entry->b_junk )
+        return -1;
+    else
     {
-        /* If junk dll, don't try to load it */
-        if( p_cache_entry->b_junk )
-        {
-            p_module = NULL;
-        }
-        else
-        {
-            module_config_t *p_item = NULL, *p_end = NULL;
+        module_config_t *p_item = NULL, *p_end = NULL;
 
-            p_module = p_cache_entry->p_module;
-            p_module->b_loaded = false;
+        p_module = p_cache_entry->p_module;
+        p_module->b_loaded = false;
 
-            /* For now we force loading if the module's config contains
-             * callbacks or actions.
-             * Could be optimized by adding an API call.*/
-            for( p_item = p_module->p_config, p_end = p_item + p_module->confsize;
-                 p_item < p_end; p_item++ )
+        /* For now we force loading if the module's config contains
+         * callbacks or actions.
+         * Could be optimized by adding an API call.*/
+        for( p_item = p_module->p_config, p_end = p_item + p_module->confsize;
+             p_item < p_end; p_item++ )
+        {
+            if( p_item->pf_callback || p_item->i_action )
             {
-                if( p_item->pf_callback || p_item->i_action )
-                {
-                    p_module = AllocatePlugin( p_this, psz_file );
-                    break;
-                }
+                p_module = AllocatePlugin( p_this, psz_file );
+                break;
             }
-            if( p_module == p_cache_entry->p_module )
-                p_cache_entry->b_used = true;
         }
+        if( p_module == p_cache_entry->p_module )
+            p_cache_entry->b_used = true;
     }
 
-    if( p_module )
-    {
-        /* Everything worked fine !
-         * The module is ready to be added to the list. */
-        p_module->b_builtin = false;
-
-        /* msg_Dbg( p_this, "plugin \"%s\", %s",
-                    p_module->psz_object_name, p_module->psz_longname ); */
-        p_module->next = p_bank->head;
-        p_bank->head = p_module;
-
-        if( !p_module_bank->b_cache )
-            return 0;
-
-        /* Add entry to 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 = true;
-        p_bank->pp_cache[p_bank->i_cache]->p_module = p_module;
-        p_bank->i_cache++;
-    }
+    if( p_module == NULL )
+        return -1;
 
-    return p_module ? 0 : -1;
+    /* Everything worked fine !
+     * The module is ready to be added to the list. */
+    p_module->b_builtin = false;
+
+    /* msg_Dbg( p_this, "plugin \"%s\", %s",
+                p_module->psz_object_name, p_module->psz_longname ); */
+    p_module->next = p_bank->head;
+    p_bank->head = p_module;
+
+    if( !p_module_bank->b_cache )
+        return 0;
+
+    /* Add entry to cache */
+    module_cache_t **pp_cache = p_bank->pp_cache;
+
+    pp_cache = realloc( pp_cache, (p_bank->i_cache + 1) * sizeof(void *) );
+    if( pp_cache == NULL )
+        return -1;
+    pp_cache[p_bank->i_cache] = malloc( sizeof(module_cache_t) );
+    if( pp_cache[p_bank->i_cache] == NULL )
+        return -1;
+    pp_cache[p_bank->i_cache]->psz_file = strdup( psz_file );
+    pp_cache[p_bank->i_cache]->i_time = i_file_time;
+    pp_cache[p_bank->i_cache]->i_size = i_file_size;
+    pp_cache[p_bank->i_cache]->b_junk = p_module ? 0 : 1;
+    pp_cache[p_bank->i_cache]->b_used = true;
+    pp_cache[p_bank->i_cache]->p_module = p_module;
+    p_bank->pp_cache = pp_cache;
+    p_bank->i_cache++;
+    return  0;
 }
 
 /*****************************************************************************
@@ -1252,8 +1257,7 @@ static module_t * AllocatePlugin( vlc_object_t * p_this, const char *psz_file )
         return NULL;
     }
 
-    /* We need to fill these since they may be needed by module_Call() */
-    p_module->psz_filename = psz_file;
+    p_module->psz_filename = strdup( psz_file );
     p_module->handle = handle;
     p_module->b_loaded = true;
 
@@ -1261,13 +1265,13 @@ static module_t * AllocatePlugin( vlc_object_t * p_this, const char *psz_file )
     if( module_Call( p_this, p_module ) != 0 )
     {
         /* We couldn't call module_init() */
+        free( p_module->psz_filename );
         module_release( p_module );
         module_Unload( handle );
         return NULL;
     }
 
     DupModule( p_module );
-    p_module->psz_filename = strdup( p_module->psz_filename );
 
     /* Everything worked fine ! The module is ready to be added to the list. */
     p_module->b_builtin = false;