Commit e7abe37c authored by Gildas Bazin's avatar Gildas Bazin

* include/*,src/*: New plugins cache feature for faster load times.

   This is still experimental so isn't enabled by default (use --plugins-cache).
   There are also a few issues that aren't dealt with yet:
     - translation of module strings.
     - config options callbacks and actions.
     - a few memory leaks.
     - and likely other things ;)
   You can easily reset the plugins cache with --reset-plugins-cache.
parent cda63044
......@@ -55,6 +55,17 @@ struct module_bank_t
VLC_COMMON_MEMBERS
module_symbols_t symbols;
/* Plugins cache */
vlc_bool_t b_cache;
vlc_bool_t b_cache_dirty;
vlc_bool_t b_cache_delete;
int i_cache;
module_cache_t **pp_cache;
int i_loaded_cache;
module_cache_t **pp_loaded_cache;
};
/*****************************************************************************
......@@ -104,6 +115,7 @@ struct module_t
char * psz_filename; /* Module filename */
vlc_bool_t b_builtin; /* Set to true if the module is built in */
vlc_bool_t b_loaded; /* Set to true if the dll is loaded */
/*
* Symbol table we send to the module so that it can access vlc symbols
......@@ -111,6 +123,21 @@ struct module_t
module_symbols_t *p_symbols;
};
/*****************************************************************************
* Module cache description structure
*****************************************************************************/
struct module_cache_t
{
/* Mandatory cache entry header */
char *psz_file;
int64_t i_time;
int64_t i_size;
vlc_bool_t b_junk;
/* Optional extra data */
module_t *p_module;
};
/*****************************************************************************
* Exported functions.
*****************************************************************************/
......
......@@ -199,6 +199,7 @@ typedef struct module_bank_t module_bank_t;
typedef struct module_t module_t;
typedef struct module_config_t module_config_t;
typedef struct module_symbols_t module_symbols_t;
typedef struct module_cache_t module_cache_t;
/* Interface */
typedef struct intf_thread_t intf_thread_t;
......
......@@ -58,6 +58,7 @@
# define CONFIG_DIR ".vlc"
#endif
#define CONFIG_FILE "vlcrc"
#define PLUGINSCACHE_FILE "vlcplugins"
/*****************************************************************************
* Interface configuration
......
......@@ -340,6 +340,12 @@ int VLC_Init( int i_object, int i_argc, char *ppsz_argv[] )
p_vlc->psz_homedir = config_GetHomeDir();
p_vlc->psz_configfile = config_GetPsz( p_vlc, "config" );
/* Check for plugins cache options */
if( config_GetInt( p_vlc, "reset-plugins-cache" ) )
{
libvlc.p_module_bank->b_cache_delete = VLC_TRUE;
}
/* Hack: remove the help module here */
vlc_object_detach( p_help_module );
/* End hack */
......@@ -729,6 +735,11 @@ int VLC_Destroy( int i_object )
p_vlc->p_memcpy_module = NULL;
}
/*
* XXX: Free module bank !
*/
module_EndBank( p_vlc );
if( p_vlc->psz_homedir )
{
free( p_vlc->psz_homedir );
......@@ -747,11 +758,6 @@ int VLC_Destroy( int i_object )
p_vlc->p_hotkeys = NULL;
}
/*
* XXX: Free module bank !
*/
/*module_EndBank( p_vlc );*/
/*
* System specific cleaning code
*/
......
......@@ -86,16 +86,6 @@ static char *ppsz_language_text[] =
"show all the available options, including those that most users should " \
"never touch.")
#define INTF_PATH_TEXT N_("Interface default search path")
#define INTF_PATH_LONGTEXT N_( \
"This option allows you to set the default path that the interface will " \
"open when looking for a file.")
#define PLUGIN_PATH_TEXT N_("Modules search path")
#define PLUGIN_PATH_LONGTEXT N_( \
"This option allows you to specify an additional path for VLC to look " \
"for its modules.")
#define AOUT_CAT_LONGTEXT N_( \
"These options allow you to modify the behavior of the audio " \
"subsystem, and to add audio filters which can be used for " \
......@@ -586,10 +576,20 @@ static char *ppsz_align_descriptions[] =
"priorities. You can use it to tune VLC priority against other " \
"programs, or against other VLC instances.")
#define MINIMIZE_THREADS_TXT N_("Minimize number of threads")
#define MINIMIZE_THREADS_LONGTXT N_( \
#define MINIMIZE_THREADS_TEXT N_("Minimize number of threads")
#define MINIMIZE_THREADS_LONGTEXT N_( \
"This option minimizes the number of threads needed to run VLC")
#define PLUGIN_PATH_TEXT N_("Modules search path")
#define PLUGIN_PATH_LONGTEXT N_( \
"This option allows you to specify an additional path for VLC to look " \
"for its modules.")
#define PLUGINS_CACHE_TEXT N_("Use a plugins cache")
#define PLUGINS_CACHE_LONGTEXT N_( \
"This option allows you to use a plugins cache which will greatly " \
"improve the start time of VLC.")
#define ONEINSTANCE_TEXT N_("Allow only one running instance")
#define ONEINSTANCE_LONGTEXT N_( \
"Allowing only one running instance of VLC can sometimes be useful, " \
......@@ -767,10 +767,6 @@ vlc_module_begin();
add_bool( "color", 0, NULL, COLOR_TEXT, COLOR_LONGTEXT, VLC_TRUE );
add_bool( "advanced", 0, NULL, ADVANCED_TEXT,
ADVANCED_LONGTEXT, VLC_FALSE );
add_directory( "search-path", NULL, NULL, INTF_PATH_TEXT,
INTF_PATH_LONGTEXT, VLC_TRUE );
add_directory( "plugin-path", NULL, NULL,
PLUGIN_PATH_TEXT, PLUGIN_PATH_LONGTEXT, VLC_TRUE );
/* Audio options */
add_category_hint( N_("Audio"), AOUT_CAT_LONGTEXT , VLC_FALSE );
......@@ -956,25 +952,38 @@ vlc_module_begin();
/* Misc options */
add_category_hint( N_("Miscellaneous"), MISC_CAT_LONGTEXT, VLC_TRUE );
add_module( "memcpy", "memcpy", NULL, NULL, MEMCPY_TEXT, MEMCPY_LONGTEXT, VLC_TRUE );
add_module( "access", "access", NULL, NULL, ACCESS_TEXT, ACCESS_LONGTEXT, VLC_TRUE );
add_module( "demux", "demux", NULL, NULL, DEMUX_TEXT, DEMUX_LONGTEXT, VLC_TRUE );
add_bool( "minimize-threads", 0, NULL, MINIMIZE_THREADS_TXT, MINIMIZE_THREADS_LONGTXT, VLC_TRUE );
add_module( "memcpy", "memcpy", NULL, NULL, MEMCPY_TEXT,
MEMCPY_LONGTEXT, VLC_TRUE );
add_module( "access", "access", NULL, NULL, ACCESS_TEXT,
ACCESS_LONGTEXT, VLC_TRUE );
add_module( "demux", "demux", NULL, NULL, DEMUX_TEXT,
DEMUX_LONGTEXT, VLC_TRUE );
add_bool( "minimize-threads", 0, NULL, MINIMIZE_THREADS_TEXT,
MINIMIZE_THREADS_LONGTEXT, VLC_TRUE );
add_directory( "plugin-path", NULL, NULL, PLUGIN_PATH_TEXT,
PLUGIN_PATH_LONGTEXT, VLC_TRUE );
add_bool( "plugins-cache", 0, NULL, PLUGINS_CACHE_TEXT,
PLUGINS_CACHE_LONGTEXT, VLC_TRUE );
#if !defined(SYS_DARWIN) && !defined(SYS_BEOS) && defined(PTHREAD_COND_T_IN_PTHREAD_H)
add_bool( "rt-priority", 0, NULL, RT_PRIORITY_TEXT, RT_PRIORITY_LONGTEXT, VLC_TRUE );
add_bool( "rt-priority", 0, NULL, RT_PRIORITY_TEXT,
RT_PRIORITY_LONGTEXT, VLC_TRUE );
#endif
#if !defined(SYS_BEOS) && defined(PTHREAD_COND_T_IN_PTHREAD_H)
add_integer( "rt-offset", 0, NULL, RT_OFFSET_TEXT, RT_OFFSET_LONGTEXT, VLC_TRUE );
add_integer( "rt-offset", 0, NULL, RT_OFFSET_TEXT,
RT_OFFSET_LONGTEXT, VLC_TRUE );
#endif
#if defined(WIN32)
add_bool( "one-instance", 0, NULL, ONEINSTANCE_TEXT, ONEINSTANCE_LONGTEXT, VLC_TRUE );
add_bool( "high-priority", 0, NULL, HPRIORITY_TEXT, HPRIORITY_LONGTEXT, VLC_TRUE );
add_bool( "fast-mutex", 0, NULL, FAST_MUTEX_TEXT, FAST_MUTEX_LONGTEXT, VLC_TRUE );
add_integer( "win9x-cv-method", 1, NULL, WIN9X_CV_TEXT, WIN9X_CV_LONGTEXT, VLC_TRUE );
add_bool( "one-instance", 0, NULL, ONEINSTANCE_TEXT,
ONEINSTANCE_LONGTEXT, VLC_TRUE );
add_bool( "high-priority", 0, NULL, HPRIORITY_TEXT,
HPRIORITY_LONGTEXT, VLC_TRUE );
add_bool( "fast-mutex", 0, NULL, FAST_MUTEX_TEXT,
FAST_MUTEX_LONGTEXT, VLC_TRUE );
add_integer( "win9x-cv-method", 1, NULL, WIN9X_CV_TEXT,
WIN9X_CV_LONGTEXT, VLC_TRUE );
#endif
/* Hotkey options*/
......@@ -1108,6 +1117,8 @@ static module_config_t p_help_config[] =
N_("reset the current config to the default values") },
{ CONFIG_ITEM_STRING, NULL, "config", '\0',
N_("use alternate config file") },
{ CONFIG_ITEM_BOOL, NULL, "reset-plugins-cache", '\0',
N_("resets the current plugins cache") },
{ CONFIG_ITEM_BOOL, NULL, "version", '\0',
N_("print version information") },
{ CONFIG_HINT_END, NULL, NULL, '\0', NULL }
......
......@@ -2,9 +2,9 @@
* configuration.c management of the modules configuration
*****************************************************************************
* Copyright (C) 2001-2004 VideoLAN
* $Id: configuration.c,v 1.76 2004/01/29 17:04:01 gbazin Exp $
* $Id$
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
* Authors: Gildas Bazin <gbazin@videolan.org>
*
* 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
......@@ -909,6 +909,45 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
return 0;
}
/*****************************************************************************
* config_CreateConfigDir: Create configuration directory if it doesn't exist.
*****************************************************************************/
int config_CreateDir( vlc_object_t *p_this, char *psz_dirname )
{
if( !psz_dirname && !*psz_dirname ) return -1;
#if defined( UNDER_CE )
{
wchar_t psz_new[ MAX_PATH ];
MultiByteToWideChar( CP_ACP, 0, psz_dirname, -1, psz_new, MAX_PATH );
if( CreateDirectory( psz_new, NULL ) )
{
msg_Err( p_this, "could not create %s", psz_filename );
}
}
#elif defined( HAVE_ERRNO_H )
# if defined( WIN32 )
if( mkdir( psz_dirname ) && errno != EEXIST )
# else
if( mkdir( psz_dirname, 0755 ) && errno != EEXIST )
# endif
{
msg_Err( p_this, "could not create %s (%s)",
psz_dirname, strerror(errno) );
}
#else
if( mkdir( psz_dirname ) )
{
msg_Err( p_this, "could not create %s", psz_dirname );
}
#endif
return 0;
}
/*****************************************************************************
* config_SaveConfigFile: Save a module's config options.
*****************************************************************************
......@@ -967,35 +1006,7 @@ int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
return -1;
}
#if defined( UNDER_CE )
{
wchar_t psz_new[ MAX_PATH ];
MultiByteToWideChar( CP_ACP, 0, psz_filename, -1, psz_new,
MAX_PATH );
if( CreateDirectory( psz_new, NULL ) )
{
msg_Err( p_this, "could not create %s", psz_filename );
}
}
#elif defined( HAVE_ERRNO_H )
# if defined( WIN32 )
if( mkdir( psz_filename ) && errno != EEXIST )
# else
if( mkdir( psz_filename, 0755 ) && errno != EEXIST )
# endif
{
msg_Err( p_this, "could not create %s (%s)",
psz_filename, strerror(errno) );
}
#else
if( mkdir( psz_filename ) )
{
msg_Err( p_this, "could not create %s", psz_filename );
}
#endif
config_CreateDir( p_this, psz_filename );
strcat( psz_filename, "/" CONFIG_FILE );
}
......
......@@ -7,6 +7,7 @@
* Authors: Sam Hocevar <sam@zoy.org>
* Ethan C. Baldridge <BaldridgeE@cadmus.com>
* Hans-Peter Jansen <hpj@urpla.net>
* Gildas Bazin <gbazin@videolan.org>
*
* 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
......@@ -133,9 +134,10 @@
* Local prototypes
*****************************************************************************/
#ifdef HAVE_DYNAMIC_PLUGINS
static void AllocateAllPlugins ( vlc_object_t * );
static void AllocatePluginDir ( vlc_object_t *, const MYCHAR *, int );
static int AllocatePluginFile ( vlc_object_t *, MYCHAR * );
static void AllocateAllPlugins ( vlc_object_t * );
static void AllocatePluginDir ( vlc_object_t *, const char *, int );
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 * );
......@@ -143,8 +145,16 @@ static int DeleteModule ( module_t * );
static void DupModule ( module_t * );
static void UndupModule ( module_t * );
static int CallEntry ( module_t * );
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 void CacheSave ( vlc_object_t * );
static void CacheSaveConfig ( module_t *, FILE * );
static void CacheMerge ( vlc_object_t *, module_t *, module_t * );
static module_cache_t * CacheFind( vlc_object_t *, char *, int64_t, int64_t );
#if defined(HAVE_DL_WINDOWS)
static char * GetWindowsError ( void );
#endif
......@@ -162,6 +172,10 @@ void __module_InitBank( vlc_object_t *p_this )
p_bank = vlc_object_create( p_this, sizeof(module_bank_t) );
p_bank->psz_object_name = "module bank";
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 =
p_bank->b_cache_delete = VLC_FALSE;
/*
* Store the symbols to be exported
......@@ -199,6 +213,10 @@ void __module_EndBank( vlc_object_t *p_this )
{
module_t * p_next;
#ifdef HAVE_DYNAMIC_PLUGINS
if( p_this->p_libvlc->p_module_bank->b_cache ) CacheSave( p_this );
#endif
vlc_object_detach( p_this->p_libvlc->p_module_bank );
while( p_this->p_libvlc->p_module_bank->i_children )
......@@ -255,6 +273,13 @@ void __module_LoadPlugins( vlc_object_t * p_this )
{
#ifdef HAVE_DYNAMIC_PLUGINS
msg_Dbg( p_this, "checking plugin modules" );
if( config_GetInt( p_this, "plugins-cache" ) )
p_this->p_libvlc->p_module_bank->b_cache = VLC_TRUE;
if( p_this->p_libvlc->p_module_bank->b_cache ||
p_this->p_libvlc->p_module_bank->b_cache_delete ) CacheLoad( p_this );
AllocateAllPlugins( p_this );
#endif
}
......@@ -516,6 +541,23 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
p_tmp = p_first;
while( p_tmp != NULL )
{
#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;
if( !p_module->b_builtin && !p_module->b_loaded )
{
module_t *p_new_module =
AllocatePlugin( p_this, p_module->psz_filename );
if( p_new_module )
{
CacheMerge( p_this, p_module, p_new_module );
vlc_object_attach( p_new_module, p_module );
DeleteModule( p_new_module );
}
}
#endif
if( p_tmp->p_module->pf_activate
&& p_tmp->p_module->pf_activate( p_this ) == VLC_SUCCESS )
{
......@@ -614,13 +656,9 @@ static void AllocateAllPlugins( vlc_object_t *p_this )
char ** ppsz_path = path;
char * psz_fullpath;
#if defined( UNDER_CE )
wchar_t psz_dir[MAX_PATH];
#endif
/* If the user provided a plugin path, we add it to the list */
path[ sizeof(path)/sizeof(char*) - 2 ] = config_GetPsz( p_this,
"plugin-path" );
path[ sizeof(path)/sizeof(char*) - 2 ] =
config_GetPsz( p_this, "plugin-path" );
for( ; *ppsz_path != NULL ; ppsz_path++ )
{
......@@ -659,12 +697,7 @@ static void AllocateAllPlugins( vlc_object_t *p_this )
msg_Dbg( p_this, "recursively browsing `%s'", psz_fullpath );
/* Don't go deeper than 5 subdirectories */
#if defined( UNDER_CE )
MultiByteToWideChar( CP_ACP, 0, psz_fullpath, -1, psz_dir, MAX_PATH );
AllocatePluginDir( p_this, psz_dir, 5 );
#else
AllocatePluginDir( p_this, psz_fullpath, 5 );
#endif
free( psz_fullpath );
}
......@@ -678,12 +711,13 @@ static void AllocateAllPlugins( vlc_object_t *p_this )
/*****************************************************************************
* AllocatePluginDir: recursively parse a directory to look for plugins
*****************************************************************************/
static void AllocatePluginDir( vlc_object_t *p_this, const MYCHAR *psz_dir,
static void AllocatePluginDir( vlc_object_t *p_this, const char *psz_dir,
int i_maxdepth )
{
#if defined( UNDER_CE ) || defined( _MSC_VER )
#ifdef UNDER_CE
MYCHAR psz_path[MAX_PATH + 256];
wchar_t psz_wdir[MAX_PATH];
#else
char psz_path[MAX_PATH + 256];
#endif
......@@ -693,9 +727,9 @@ static void AllocatePluginDir( vlc_object_t *p_this, const MYCHAR *psz_dir,
#else
int i_dirlen;
DIR * dir;
char * psz_file;
struct dirent * file;
#endif
char * psz_file;
if( p_this->p_vlc->b_die || i_maxdepth < 0 )
{
......@@ -703,7 +737,9 @@ static void AllocatePluginDir( vlc_object_t *p_this, const MYCHAR *psz_dir,
}
#if defined( UNDER_CE ) || defined( _MSC_VER )
rc = GetFileAttributes( psz_dir );
MultiByteToWideChar( CP_ACP, 0, psz_dir, -1, psz_wdir, MAX_PATH );
rc = GetFileAttributes( psz_wdir );
if( !(rc & FILE_ATTRIBUTE_DIRECTORY) )
{
/* Not a directory */
......@@ -754,7 +790,16 @@ static void AllocatePluginDir( vlc_object_t *p_this, const MYCHAR *psz_dir,
LIBEXT, strlen( LIBEXT ) ) )
#endif
{
AllocatePluginFile( p_this, psz_path );
#ifdef UNDER_CE
char psz_filename[MAX_PATH];
WideCharToMultiByte( CP_ACP, WC_DEFAULTCHAR, psz_path, -1,
psz_filename, MAX_PATH, NULL, NULL );
psz_file = psz_filename;
#else
psz_file = psz_path;
#endif
AllocatePluginFile( p_this, psz_file, 0, 0 );
}
}
while( !p_this->p_vlc->b_die && FindNextFile( handle, &finddata ) );
......@@ -776,6 +821,7 @@ static void AllocatePluginDir( vlc_object_t *p_this, const MYCHAR *psz_dir,
{
struct stat statbuf;
unsigned int i_len;
int i_stat;
/* Skip ".", ".." and anything starting with "." */
if( !*file->d_name || *file->d_name == '.' )
......@@ -791,7 +837,8 @@ static void AllocatePluginDir( vlc_object_t *p_this, const MYCHAR *psz_dir,
sprintf( psz_file, "%s/%s", psz_dir, file->d_name );
#endif
if( !stat( psz_file, &statbuf ) && statbuf.st_mode & S_IFDIR )
i_stat = stat( psz_file, &statbuf );
if( !i_stat && statbuf.st_mode & S_IFDIR )
{
AllocatePluginDir( p_this, psz_file, i_maxdepth - 1 );
}
......@@ -800,7 +847,15 @@ static void AllocatePluginDir( vlc_object_t *p_this, const MYCHAR *psz_dir,
&& !strncasecmp( file->d_name + i_len - strlen( LIBEXT ),
LIBEXT, strlen( LIBEXT ) ) )
{
AllocatePluginFile( p_this, psz_file );
int64_t i_time = 0, i_size = 0;
if( !i_stat )
{
i_time = statbuf.st_mtime;
i_size = statbuf.st_size;
}
AllocatePluginFile( p_this, psz_file, i_time, i_size );
}
free( psz_file );
......@@ -819,143 +874,78 @@ static void AllocatePluginDir( vlc_object_t *p_this, const MYCHAR *psz_dir,
* for its information data. The module can then be handled by module_Need
* and module_Unneed. It can be removed by DeleteModule.
*****************************************************************************/
static int AllocatePluginFile( vlc_object_t * p_this, MYCHAR * psz_file )
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_handle_t handle;
module_cache_t *p_cache_entry = NULL;
/*
* Try to dynamically load the module. This part is very platform-
* specific, and error messages should be as verbose as possible.
* Check our plugins cache first then load plugin if needed
*/
p_cache_entry =
CacheFind( p_this, psz_file, i_file_time, i_file_size );
#if defined(HAVE_DL_DYLD)
NSObjectFileImage image;
NSObjectFileImageReturnCode ret;
ret = NSCreateObjectFileImageFromFile( psz_file, &image );
if( ret != NSObjectFileImageSuccess )
if( !p_cache_entry )
{
msg_Warn( p_this, "cannot create image from `%s'", psz_file );
return -1;
p_module = AllocatePlugin( p_this, psz_file );
}
/* Open the dynamic module */
handle = NSLinkModule( image, psz_file,
NSLINKMODULE_OPTION_RETURN_ON_ERROR );
if( !handle )
{
NSLinkEditErrors errors;
const char *psz_file, *psz_err;
int i_errnum;
NSLinkEditError( &errors, &i_errnum, &psz_file, &psz_err );
msg_Warn( p_this, "cannot link module `%s' (%s)", psz_file, psz_err );
NSDestroyObjectFileImage( image );
return -1;
}
/* Destroy our image, we won't need it */
NSDestroyObjectFileImage( image );
#elif defined(HAVE_DL_BEOS)
handle = load_add_on( psz_file );
if( handle < 0 )
{
msg_Warn( p_this, "cannot load module `%s'", psz_file );
return -1;
}
#elif defined(HAVE_DL_WINDOWS) && defined(UNDER_CE)
char psz_filename[MAX_PATH];
WideCharToMultiByte( CP_ACP, WC_DEFAULTCHAR, psz_file, -1,
psz_filename, MAX_PATH, NULL, NULL );
handle = LoadLibrary( psz_filename );
if( handle == NULL )
{
char *psz_error = GetWindowsError();
msg_Warn( p_this, "cannot load module `%s' (%s)",
psz_filename, psz_error );
free( psz_error );
}
#elif defined(HAVE_DL_WINDOWS) && defined(WIN32)
handle = LoadLibrary( psz_file );
if( handle == NULL )
{
char *psz_error = GetWindowsError();
msg_Warn( p_this, "cannot load module `%s' (%s)",
psz_file, psz_error );
free( psz_error );
}
#elif defined(HAVE_DL_DLOPEN) && defined(RTLD_NOW)
/* static is OK, we are called atomically */
static vlc_bool_t b_kde = VLC_FALSE;
# if defined(SYS_LINUX)
/* XXX HACK #1 - we should NOT open modules with RTLD_GLOBAL, or we
* are going to get namespace collisions when two modules have common
* public symbols, but ALSA is being a pest here. */
if( strstr( psz_file, "alsa_plugin" ) )
else
{
handle = dlopen( psz_file, RTLD_NOW | RTLD_GLOBAL );
if( handle == NULL )
/* If junk dll, don't try to load it */
if( p_cache_entry->b_junk )
{
msg_Warn( p_this, "cannot load module `%s' (%s)",
psz_file, dlerror() );
return -1;
p_module = NULL;
}
else
{
p_module = p_cache_entry->p_module;
p_module->b_loaded = VLC_FALSE;
}
}
# endif
/* XXX HACK #2 - the ugly KDE workaround. It seems that libkdewhatever
* causes dlopen() to segfault if libstdc++ is not loaded in the caller,
* so we just load libstdc++. Bwahahaha! ph34r! -- Sam. */
/* Update: FYI, this is Debian bug #180505, and seems to be fixed. */
if( !b_kde && !strstr( psz_file, "kde" ) )
{
dlopen( "libstdc++.so.6", RTLD_NOW )
|| dlopen( "libstdc++.so.5", RTLD_NOW )
|| dlopen( "libstdc++.so.4", RTLD_NOW )
|| dlopen( "libstdc++.so.3", RTLD_NOW );
b_kde = VLC_TRUE;
}
handle = dlopen( psz_file, RTLD_NOW );
if( handle == NULL )
if( p_module )
{
msg_Warn( p_this, "cannot load module `%s' (%s)",
psz_file, dlerror() );
return -1;
}
/* Everything worked fine !
* The module is ready to be added to the list. */
p_module->b_builtin = VLC_FALSE;
#elif defined(HAVE_DL_DLOPEN)
# if defined(DL_LAZY)
handle = dlopen( psz_file, DL_LAZY );
# else
handle = dlopen( psz_file, 0 );
# endif
if( handle == NULL )
{
msg_Warn( p_this, "cannot load module `%s' (%s)",
psz_file, dlerror() );
return -1;
}
/* msg_Dbg( p_this, "plugin \"%s\", %s",
p_module->psz_object_name, p_module->psz_longname ); */
#elif defined(HAVE_DL_SHL_LOAD)
handle = shl_load( psz_file, BIND_IMMEDIATE | BIND_NONFATAL, NULL );
if( handle == NULL )
{
msg_Warn( p_this, "cannot load module `%s' (%s)",
psz_file, strerror(errno) );
return -1;
vlc_object_attach( p_module, p_this->p_libvlc->p_module_bank );
}
#else
# error "Something is wrong in modules.c"
if( !p_this->p_libvlc->p_module_bank->b_cache ) return 0;
/* Add entry to cache */
#define p_bank p_this->p_libvlc->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++;
return p_module ? 0 : -1;
}
#endif
/*****************************************************************************
* AllocatePlugin: load a module into memory and initialize it.
*****************************************************************************
* This function loads a dynamically loadable module and allocates a structure
* for its information data. The module can then be handled by module_Need
* and module_Unneed. It can be removed by DeleteModule.
*****************************************************************************/
static module_t * AllocatePlugin( vlc_object_t * p_this, char * psz_file )
{
module_t * p_module;
module_handle_t handle;
if( LoadModule( p_this, psz_file, &handle ) ) return NULL;
/* Now that we have successfully loaded the module, we can
* allocate a structure for it */
......@@ -964,25 +954,22 @@ static int AllocatePluginFile( vlc_object_t * p_this, MYCHAR * psz_file )
{
msg_Err( p_this, "out of memory" );
CloseModule( handle );
return -1;
return NULL;
}
/* We need to fill these since they may be needed by CallEntry() */
#ifdef UNDER_CE
p_module->psz_filename = psz_filename;
#else
p_module->psz_filename = psz_file;
#endif
p_module->handle = handle;
p_module->p_symbols = &p_this->p_libvlc->p_module_bank->symbols;
p_module->b_loaded = VLC_TRUE;
/* Initialize the module: fill p_module->psz_object_name, default config */
/* Initialize the module: fill p_module, default config */
if( CallEntry( p_module ) != 0 )
{
/* We couldn't call module_init() */
vlc_object_destroy( p_module );