]> git.sesse.net Git - vlc/blobdiff - src/misc/modules.c
* forgot the most important file of the commit :)
[vlc] / src / misc / modules.c
index 2f44dd560b90a88855cf7ed307580b1c910f6b9c..06d78d0675c8e167482af60b31101b9a5d68a7e5 100644 (file)
@@ -35,6 +35,7 @@
 #include <string.h>                                              /* strdup() */
 
 #include <vlc/vlc.h>
+#include <vlc/input.h>
 
 #ifdef HAVE_DIRENT_H
 #   include <dirent.h>
 #include "vlc_interface.h"
 #include "intf_eject.h"
 
-#include "stream_control.h"
-#include "input_ext-intf.h"
-#include "input_ext-dec.h"
-#include "input_ext-plugins.h"
-#include "ninput.h"
-
 #include "vlc_playlist.h"
 
 #include "vlc_video.h"
@@ -148,7 +143,7 @@ static int    LoadModule       ( vlc_object_t *, char *, module_handle_t * );
 static void   CloseModule      ( module_handle_t );
 static void * GetSymbol        ( module_handle_t, const char * );
 static void   CacheLoad        ( vlc_object_t * );
-static void   CacheLoadConfig  ( module_t *, FILE * );
+static int    CacheLoadConfig  ( module_t *, FILE * );
 static void   CacheSave        ( vlc_object_t * );
 static void   CacheSaveConfig  ( module_t *, FILE * );
 static void   CacheMerge       ( vlc_object_t *, module_t *, module_t * );
@@ -168,9 +163,24 @@ static char * GetWindowsError  ( void );
 void __module_InitBank( vlc_object_t *p_this )
 {
     module_bank_t *p_bank;
+    vlc_value_t  lockval;
+
+    var_Create( p_this->p_libvlc, "libvlc", VLC_VAR_MUTEX );
+    var_Get( p_this->p_libvlc, "libvlc", &lockval );
+    vlc_mutex_lock( lockval.p_address );
+    if( p_this->p_libvlc->p_module_bank )
+    {
+        p_this->p_libvlc->p_module_bank->i_usage++;
+        vlc_mutex_unlock( lockval.p_address );
+        var_Destroy( p_this->p_libvlc, "libvlc" );
+        return;
+    }
+    vlc_mutex_unlock( lockval.p_address );
+    var_Destroy( p_this->p_libvlc, "libvlc" );
 
     p_bank = vlc_object_create( p_this, sizeof(module_bank_t) );
     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->b_cache = p_bank->b_cache_dirty =
@@ -187,6 +197,8 @@ void __module_InitBank( vlc_object_t *p_this )
     p_this->p_libvlc->p_module_bank = p_bank;
     vlc_object_attach( p_bank, p_this->p_libvlc );
 
+    module_LoadMain( p_this );
+
     return;
 }
 
@@ -211,6 +223,25 @@ void __module_ResetBank( vlc_object_t *p_this )
 void __module_EndBank( vlc_object_t *p_this )
 {
     module_t * p_next;
+    vlc_value_t  lockval;
+
+    var_Create( p_this->p_libvlc, "libvlc", VLC_VAR_MUTEX );
+    var_Get( p_this->p_libvlc, "libvlc", &lockval );
+    vlc_mutex_lock( lockval.p_address );
+    if( !p_this->p_libvlc->p_module_bank )
+    {
+        vlc_mutex_unlock( lockval.p_address );
+        var_Destroy( p_this->p_libvlc, "libvlc" );
+        return;
+    }
+    if( --p_this->p_libvlc->p_module_bank->i_usage )
+    {
+        vlc_mutex_unlock( lockval.p_address );
+        var_Destroy( p_this->p_libvlc, "libvlc" );
+        return;
+    }
+    vlc_mutex_unlock( lockval.p_address );
+    var_Destroy( p_this->p_libvlc, "libvlc" );
 
 #ifdef HAVE_DYNAMIC_PLUGINS
     if( p_this->p_libvlc->p_module_bank->b_cache ) CacheSave( p_this );
@@ -297,6 +328,7 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
     {
         module_t *p_module;
         int i_score;
+        vlc_bool_t b_force;
         module_list_t *p_next;
     };
 
@@ -372,33 +404,16 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
     /* Parse the module list for capabilities and probe each of them */
     for( i_which_module = 0; i_which_module < p_all->i_count; i_which_module++ )
     {
-        module_t * p_submodule = NULL;
-        int i_shortcut_bonus = 0, i_submodule;
+        int i_shortcut_bonus = 0;
 
         p_module = (module_t *)p_all->p_values[i_which_module].p_object;
 
         /* Test that this module can do what we need */
         if( strcmp( p_module->psz_capability, psz_capability ) )
         {
-            for( i_submodule = 0;
-                 i_submodule < p_module->i_children;
-                 i_submodule++ )
-            {
-                if( !strcmp( ((module_t*)p_module->pp_children[ i_submodule ])
-                                           ->psz_capability, psz_capability ) )
-                {
-                    p_submodule =
-                            (module_t*)p_module->pp_children[ i_submodule ];
-                    break;
-                }
-            }
-
-            if( p_submodule == NULL )
-            {
-                continue;
-            }
-
-            p_module = p_submodule;
+            /* Don't recurse through the sub-modules because vlc_list_find()
+             * will list them anyway. */
+            continue;
         }
 
         /* Test if we have the required CPU */
@@ -487,6 +502,7 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
         /* Store this new module */
         p_list[ i_index ].p_module = p_module;
         p_list[ i_index ].i_score = p_module->i_score + i_shortcut_bonus;
+        p_list[ i_index ].b_force = !!i_shortcut_bonus;
 
         /* Add it to the modules-to-probe list */
         if( i_index == 0 )
@@ -557,6 +573,7 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
         }
 #endif
 
+        p_this->b_force = p_tmp->b_force;
         if( p_tmp->p_module->pf_activate
              && p_tmp->p_module->pf_activate( p_this ) == VLC_SUCCESS )
         {
@@ -586,6 +603,7 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
     }
 
     free( p_list );
+    p_this->b_force = VLC_FALSE;
 
     if( p_module != NULL )
     {
@@ -594,8 +612,16 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
     }
     else if( p_first == NULL )
     {
-        msg_Err( p_this, "no %s module matched \"%s\"",
+        if( !strcmp( psz_capability, "access_demux" ) )
+        {
+            msg_Warn( p_this, "no %s module matched \"%s\"",
                  psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
+        }
+        else
+        {  
+            msg_Err( p_this, "no %s module matched \"%s\"",
+                 psz_capability, (psz_name && *psz_name) ? psz_name : "any" );
+        }
     }
     else if( psz_name != NULL && *psz_name )
     {
@@ -898,8 +924,20 @@ static int AllocatePluginFile( vlc_object_t * p_this, char * psz_file,
         }
         else
         {
+            module_config_t *p_item;
+
             p_module = p_cache_entry->p_module;
             p_module->b_loaded = VLC_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_item->i_type != CONFIG_HINT_END; p_item++ )
+            {
+                if( p_item->pf_callback || p_item->i_action )
+                    p_module = AllocatePlugin( p_this, psz_file );
+            }
         }
     }
 
@@ -1460,8 +1498,9 @@ static void CacheLoad( vlc_object_t *p_this )
     FILE *file;
     int i, j, i_size, i_read;
     char p_cachestring[sizeof(PLUGINSCACHE_FILE COPYRIGHT_MESSAGE)];
-    int *pi_cache;
+    int i_cache;
     module_cache_t **pp_cache = 0;
+    int32_t i_file_size;
 
     psz_homedir = p_this->p_vlc->psz_homedir;
     if( !psz_homedir )
@@ -1502,6 +1541,26 @@ static void CacheLoad( vlc_object_t *p_this )
     }
     free( psz_filename );
 
+    /* Check the file size */
+    i_read = fread( &i_file_size, sizeof(char), sizeof(i_file_size), file );
+    if( i_read != sizeof(i_file_size) )
+    {
+        msg_Warn( p_this, "This doesn't look like a valid plugins cache "
+                  "(too short)" );
+        fclose( file );
+        return;
+    }
+
+    fseek( file, 0, SEEK_END );
+    if( ftell( file ) != i_file_size )
+    {
+        msg_Warn( p_this, "This doesn't look like a valid plugins cache "
+                  "(corrupted size)" );
+        fclose( file );
+        return;
+    }
+    fseek( file, sizeof(i_file_size), SEEK_SET );
+
     /* Check the file is a plugins cache */
     i_size = sizeof(PLUGINSCACHE_FILE COPYRIGHT_MESSAGE) - 1;
     i_read = fread( p_cachestring, sizeof(char), i_size, file );
@@ -1509,29 +1568,35 @@ static void CacheLoad( vlc_object_t *p_this )
         memcmp( p_cachestring, PLUGINSCACHE_FILE COPYRIGHT_MESSAGE, i_size ) )
     {
         msg_Warn( p_this, "This doesn't look like a valid plugins cache" );
+        fclose( file );
+        return;
     }
 
-    pi_cache = &p_this->p_libvlc->p_module_bank->i_loaded_cache;
-    fread( pi_cache, sizeof(char), sizeof(*pi_cache), file );
+    p_this->p_libvlc->p_module_bank->i_loaded_cache = 0;
+    fread( &i_cache, sizeof(char), sizeof(i_cache), file );
     pp_cache = p_this->p_libvlc->p_module_bank->pp_loaded_cache =
-        malloc( *pi_cache * sizeof(void *) );
-
-    for( i = 0; i < *pi_cache; i++ )
-    {
-        int32_t i_size;
-        int i_submodules;
+        malloc( i_cache * sizeof(void *) );
 
 #define LOAD_IMMEDIATE(a) \
-        fread( &a, sizeof(char), sizeof(a), file )
+    if( fread( &a, sizeof(char), sizeof(a), file ) != sizeof(a) ) goto error
 #define LOAD_STRING(a) \
-        { fread( &i_size, sizeof(char), sizeof(int32_t), file ); \
-          if( i_size ) { \
-            a = malloc( i_size ); \
-            fread( a, sizeof(char), i_size, file ); \
-          } else a = 0; \
-        } while(0)
+    { if( fread( &i_size, sizeof(char), sizeof(i_size), file ) \
+          != sizeof(i_size) ) goto error; \
+      if( i_size ) { \
+          a = malloc( i_size ); \
+          if( fread( a, sizeof(char), i_size, file ) != (size_t)i_size ) \
+              goto error; \
+      } else a = 0; \
+    } while(0)
+
+
+    for( i = 0; i < i_cache; i++ )
+    {
+        int16_t i_size;
+        int i_submodules;
 
         pp_cache[i] = malloc( sizeof(module_cache_t) );
+        p_this->p_libvlc->p_module_bank->i_loaded_cache++;
 
         /* Save common info */
         LOAD_STRING( pp_cache[i]->psz_file );
@@ -1560,7 +1625,8 @@ static void CacheLoad( vlc_object_t *p_this )
         LOAD_IMMEDIATE( pp_cache[i]->p_module->b_submodule );
 
         /* Config stuff */
-        CacheLoadConfig( pp_cache[i]->p_module, file );
+        if( CacheLoadConfig( pp_cache[i]->p_module, file ) != VLC_SUCCESS )
+            goto error;
 
         LOAD_STRING( pp_cache[i]->p_module->psz_filename );
 
@@ -1589,14 +1655,23 @@ static void CacheLoad( vlc_object_t *p_this )
     }
 
     fclose( file );
+    return;
 
+ error:
+
+    msg_Warn( p_this, "plugins cache not loaded (corrupted)" );
+
+    /* TODO: cleanup */
+    p_this->p_libvlc->p_module_bank->i_loaded_cache = 0;
+
+    fclose( file );
     return;
 }
 
-void CacheLoadConfig( module_t *p_module, FILE *file )
+int CacheLoadConfig( module_t *p_module, FILE *file )
 {
     int i, j, i_lines;
-    int32_t i_size;
+    int16_t i_size;
 
     /* Calculate the structure length */
     LOAD_IMMEDIATE( p_module->i_config_items );
@@ -1610,7 +1685,7 @@ void CacheLoadConfig( module_t *p_module, FILE *file )
     if( p_module->p_config == NULL )
     {
         msg_Err( p_module, "config error: can't duplicate p_config" );
-        return;
+        return VLC_ENOMEM;
     }
 
     /* Do the duplication job */
@@ -1682,10 +1757,16 @@ void CacheLoadConfig( module_t *p_module, FILE *file )
             }
         }
 
-        p_module->p_config[i].pf_callback = 0;
+        LOAD_IMMEDIATE( p_module->p_config[i].pf_callback );
     }
 
     p_module->p_config[i].i_type = CONFIG_HINT_END;
+
+    return VLC_SUCCESS;
+
+ error:
+
+    return VLC_EGENERIC;
 }
 
 /*****************************************************************************
@@ -1697,6 +1778,7 @@ static void CacheSave( vlc_object_t *p_this )
     FILE *file;
     int i, j, i_cache;
     module_cache_t **pp_cache;
+    int32_t i_file_size = 0;
 
     psz_homedir = p_this->p_vlc->psz_homedir;
     if( !psz_homedir )
@@ -1733,6 +1815,9 @@ static void CacheSave( vlc_object_t *p_this )
     }
     free( psz_filename );
 
+    /* Empty space for file size */
+    fwrite( &i_file_size, sizeof(char), sizeof(i_file_size), file );
+
     /* Contains version number */
     fprintf( file, PLUGINSCACHE_FILE COPYRIGHT_MESSAGE );
 
@@ -1741,19 +1826,19 @@ static void CacheSave( vlc_object_t *p_this )
 
     fwrite( &i_cache, sizeof(char), sizeof(i_cache), file );
 
+#define SAVE_IMMEDIATE(a) \
+    fwrite( &a, sizeof(char), sizeof(a), file )
+#define SAVE_STRING(a) \
+    { i_size = a ? strlen( a ) + 1 : 0; \
+      fwrite( &i_size, sizeof(char), sizeof(i_size), file ); \
+      if( a ) fwrite( a, sizeof(char), i_size, file ); \
+    } while(0)
+
     for( i = 0; i < i_cache; i++ )
     {
-        int32_t i_size;
+        int16_t i_size;
         int32_t i_submodule;
 
-#define SAVE_IMMEDIATE(a) \
-        fwrite( &a, sizeof(char), sizeof(a), file )
-#define SAVE_STRING(a) \
-        { i_size = a ? strlen( a ) + 1 : 0; \
-          fwrite( &i_size, sizeof(char), sizeof(int32_t), file ); \
-          if( a ) fwrite( a, sizeof(char), i_size, file ); \
-        } while(0)
-
         /* Save common info */
         SAVE_STRING( pp_cache[i]->psz_file );
         SAVE_IMMEDIATE( pp_cache[i]->i_time );
@@ -1807,6 +1892,11 @@ static void CacheSave( vlc_object_t *p_this )
         }
     }
 
+    /* Fill-up file size */
+    i_file_size = ftell( file );
+    fseek( file, 0, SEEK_SET );
+    fwrite( &i_file_size, sizeof(char), sizeof(i_file_size), file );
+
     fclose( file );
 
     return;
@@ -1816,7 +1906,7 @@ void CacheSaveConfig( module_t *p_module, FILE *file )
 {
     int i, j, i_lines = 0;
     module_config_t *p_item;
-    int32_t i_size;
+    int16_t i_size;
 
     SAVE_IMMEDIATE( p_module->i_config_items );
     SAVE_IMMEDIATE( p_module->i_bool_items );
@@ -1858,6 +1948,8 @@ void CacheSaveConfig( module_t *p_module, FILE *file )
 
         for( j = 0; j < p_module->p_config[i].i_action; j++ )
             SAVE_STRING( p_module->p_config[i].ppsz_action_text[j] );
+
+        SAVE_IMMEDIATE( p_module->p_config[i].pf_callback );
     }
 }