* modules.c : Built-in and plugin modules management functions
*****************************************************************************
* Copyright (C) 2001 VideoLAN
- * $Id: modules.c,v 1.43 2001/11/28 15:08:06 massiot Exp $
+ * $Id: modules.c,v 1.56 2002/03/01 16:07:00 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Ethan C. Baldridge <BaldridgeE@cadmus.com>
+ * Hans-Peter Jansen <hpj@urpla.net>
*
* 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
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
-#include "defs.h"
-
-#include "config.h"
/* Some faulty libcs have a broken struct dirent when _FILE_OFFSET_BITS
* is set to 64. Don't try to be cleverer. */
#include <stdio.h> /* sprintf() */
#include <string.h> /* strdup() */
+#include <videolan/vlc.h>
+
#if !defined( _MSC_VER )
#include <dirent.h>
#endif
# undef HAVE_DYNAMIC_PLUGINS
#endif
-#ifdef SYS_BEOS
-# include "beos_specific.h"
-#endif
-
-#ifdef SYS_DARWIN
-# include "darwin_specific.h"
-#endif
-#include "common.h"
-#include "intf_msg.h"
-#include "threads.h"
-#include "mtime.h"
-#include "tests.h"
#include "netutils.h"
-#include "modules.h"
#include "interface.h"
#include "intf_playlist.h"
+#include "intf_eject.h"
#include "stream_control.h"
#include "input_ext-intf.h"
#include "iso_lang.h"
#ifdef HAVE_DYNAMIC_PLUGINS
-# include "modules_core.h"
+# include "modules_plugin.h"
#endif
#include "modules_builtin.h"
-#include "modules_export.h"
-
-#include "main.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
#ifdef HAVE_DYNAMIC_PLUGINS
-static int AllocatePluginModule ( char * );
+static void AllocateAllPlugins ( void );
+static int AllocatePluginModule ( char * );
#endif
-#ifdef ALLOCATE_ALL_BUILTINS
-static int AllocateBuiltinModule( int ( * ) ( module_t * ),
- int ( * ) ( module_t * ),
- int ( * ) ( module_t * ) );
-#endif
-static int DeleteModule ( module_t * );
-static int LockModule ( module_t * );
-static int UnlockModule ( module_t * );
+static int AllocateBuiltinModule( int ( * ) ( module_t * ),
+ int ( * ) ( module_t * ),
+ int ( * ) ( module_t * ) );
+static int DeleteModule ( module_t * );
+static int LockModule ( module_t * );
+static int UnlockModule ( module_t * );
#ifdef HAVE_DYNAMIC_PLUGINS
-static int HideModule ( module_t * );
-static int CallSymbol ( module_t *, char * );
+static int HideModule ( module_t * );
+static int CallSymbol ( module_t *, char * );
#endif
+#ifdef HAVE_DYNAMIC_PLUGINS
static module_symbols_t symbols;
+#endif
/*****************************************************************************
* module_InitBank: create the module bank.
*****************************************************************************
- * This function creates a module bank structure and fills it with the
- * built-in modules, as well as all the plugin modules it can find.
+ * This function creates a module bank structure which will be filled later
+ * on with all the modules found.
*****************************************************************************/
void module_InitBank( void )
{
-#ifdef HAVE_DYNAMIC_PLUGINS
- static char * path[] = { ".", "plugins", PLUGIN_PATH, NULL, NULL };
-
- char ** ppsz_path = path;
- char * psz_fullpath;
- char * psz_file;
-#if defined( SYS_BEOS ) || defined( SYS_DARWIN )
- char * psz_vlcpath = system_GetProgramPath();
- int i_vlclen = strlen( psz_vlcpath );
- boolean_t b_notinroot;
-#endif
- DIR * dir;
- struct dirent * file;
-#endif /* HAVE_DYNAMIC_PLUGINS */
-
p_module_bank->first = NULL;
+ p_module_bank->i_count = 0;
vlc_mutex_init( &p_module_bank->lock );
/*
* Store the symbols to be exported
*/
+#ifdef HAVE_DYNAMIC_PLUGINS
STORE_SYMBOLS( &symbols );
-#ifdef TRACE
- STORE_TRACE_SYMBOLS( &symbols );
#endif
- /*
- * Check all the built-in modules
- */
-#ifdef ALLOCATE_ALL_BUILTINS
- intf_WarnMsg( 2, "module: checking built-in modules" );
+ return;
+}
+/*****************************************************************************
+ * module_LoadMain: load the main program info into the module bank.
+ *****************************************************************************
+ * This function fills the module bank structure with the main module infos.
+ * This is very useful as it will allow us to consider the main program just
+ * 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( void )
+{
+ AllocateBuiltinModule( InitModule__MODULE_main,
+ ActivateModule__MODULE_main,
+ DeactivateModule__MODULE_main );
+}
+
+/*****************************************************************************
+ * module_LoadBuiltins: load all modules which we built with.
+ *****************************************************************************
+ * This function fills the module bank structure with the built-in modules.
+ *****************************************************************************/
+void module_LoadBuiltins( void )
+{
+ intf_WarnMsg( 2, "module: checking built-in modules" );
ALLOCATE_ALL_BUILTINS();
-#endif
+}
- /*
- * Check all the plugin modules we can find
- */
+/*****************************************************************************
+ * module_LoadPlugins: load all plugin modules we can find.
+ *****************************************************************************
+ * This function fills the module bank structure with the plugin modules.
+ *****************************************************************************/
+void module_LoadPlugins( void )
+{
#ifdef HAVE_DYNAMIC_PLUGINS
intf_WarnMsg( 2, "module: checking plugin modules" );
-
- for( ; *ppsz_path != NULL ; ppsz_path++ )
- {
- /* Store strlen(*ppsz_path) for later use. */
- int i_dirlen = strlen( *ppsz_path );
-
-#if defined( SYS_BEOS ) || defined( SYS_DARWIN )
- b_notinroot = 0;
- /* Under BeOS, we need to add beos_GetProgramPath() to access
- * files under the current directory */
- if( ( i_dirlen > 1 ) && strncmp( *ppsz_path, "/", 1 ) )
- {
- i_dirlen += i_vlclen + 2;
- b_notinroot = 1;
-
- psz_fullpath = malloc( i_dirlen );
- if( psz_fullpath == NULL )
- {
- continue;
- }
- sprintf( psz_fullpath, "%s/%s", psz_vlcpath, *ppsz_path );
- }
- else
+ AllocateAllPlugins();
#endif
- {
- psz_fullpath = *ppsz_path;
- }
-
- intf_WarnMsgImm( 1, "module: browsing `%s'", psz_fullpath );
-
- if( (dir = opendir( psz_fullpath )) )
- {
- /* Parse the directory and try to load all files it contains. */
- while( (file = readdir( dir )) )
- {
- int i_filelen = strlen( file->d_name );
-
- /* We only load files ending with ".so" */
- if( i_filelen > 3
- && !strncmp( file->d_name + i_filelen - 3, ".so", 3 ) )
- {
- psz_file = malloc( i_dirlen + i_filelen + 2 );
- if( psz_file == NULL )
- {
- continue;
- }
- sprintf( psz_file, "%s/%s", psz_fullpath, file->d_name );
-
- /* We created a nice filename -- now we just try to load
- * it as a plugin module. */
- AllocatePluginModule( psz_file );
-
- /* We don't care if the allocation succeeded */
- free( psz_file );
- }
- }
-
- /* Close the directory if successfully opened */
- closedir( dir );
- }
-
-#if defined( SYS_BEOS ) || defined( SYS_DARWIN )
- if( b_notinroot )
- {
- free( psz_fullpath );
- }
-#endif
- }
-#endif /* HAVE_DYNAMIC_PLUGINS */
-
- intf_WarnMsg( 3, "module: module bank initialized" );
-
- return;
}
/*****************************************************************************
if( DeleteModule( p_module_bank->first ) )
{
/* Module deletion failed */
- intf_ErrMsg( "module error: `%s' can't be removed. trying harder.",
+ intf_ErrMsg( "module error: `%s' can't be removed, trying harder",
p_module_bank->first->psz_name );
/* We just free the module by hand. Niahahahahaha. */
*****************************************************************************
* This function returns the module that best fits the asked capabilities.
*****************************************************************************/
-module_t * module_Need( int i_capabilities, void *p_data )
+module_t * module_Need( int i_capability, char *psz_name, void *p_data )
{
- module_t * p_module;
- module_t * p_bestmodule = NULL;
- int i_score, i_totalscore, i_bestscore = 0;
- int i_index;
+ typedef struct module_list_s
+ {
+ struct module_s *p_module;
+ struct module_list_s* p_next;
+ } module_list_t;
+ struct module_list_s *p_list, *p_first, *p_tolock;
+
+ int i_ret, i_index = 0;
+ boolean_t b_intf = 0;
+
+ module_t *p_module;
+ char *psz_realname = NULL;
/* We take the global lock */
vlc_mutex_lock( &p_module_bank->lock );
+ if( psz_name != NULL && *psz_name )
+ {
+ /* A module name was requested. */
+ psz_realname = strdup( psz_name );
+ if( psz_realname )
+ {
+ char *p;
+ p = strchr( psz_realname, ':' );
+ if( p )
+ {
+ *p = '\0';
+ }
+ psz_name = psz_realname;
+ }
+ }
+
+ /* Sort the modules and test them */
+ p_list = malloc( p_module_bank->i_count * sizeof( module_list_t ) );
+ p_first = NULL;
+
/* Parse the module list for capabilities and probe each of them */
for( p_module = p_module_bank->first ;
p_module != NULL ;
p_module = p_module->next )
{
/* Test that this module can do everything we need */
- if( ( p_module->i_capabilities & i_capabilities ) == i_capabilities )
+ if( !(p_module->i_capabilities & ( 1 << i_capability )) )
+ {
+ continue;
+ }
+
+ /* Test if we have the required CPU */
+ if( (p_module->i_cpu_capabilities & p_main->i_cpu_capabilities)
+ != p_module->i_cpu_capabilities )
+ {
+ continue;
+ }
+
+ /* Test if this plugin exports the required shortcut */
+ if( psz_name != NULL && *psz_name )
{
- i_totalscore = 0;
+ boolean_t b_ok = 0;
+ int i_dummy;
- LockModule( p_module );
+ for( i_dummy = 0;
+ !b_ok && p_module->pp_shortcuts[i_dummy];
+ i_dummy++ )
+ {
+ b_ok = !strcmp( psz_name, p_module->pp_shortcuts[i_dummy] );
+ }
- /* Parse all the requested capabilities and test them */
- for( i_index = 0 ; (1 << i_index) <= i_capabilities ; i_index++ )
+ if( !b_ok )
{
- if( ( (1 << i_index) & i_capabilities ) )
- {
- i_score = ( (function_list_t *)p_module->p_functions)
- [i_index].pf_probe( p_data );
+ continue;
+ }
+ }
- if( i_score )
- {
- i_totalscore += i_score;
- }
- else
- {
- break;
- }
+ /* Special case: test if we requested a particular intf plugin */
+ if( i_capability == MODULE_CAPABILITY_INTF )
+ {
+ if( p_module->psz_program != NULL
+ && !strcmp( p_module->psz_program, p_main->psz_arg0 ) )
+ {
+ if( !b_intf )
+ {
+ /* Remove previous non-matching plugins */
+ i_index = 0;
+ b_intf = 1;
}
}
- intf_WarnMsg( 3, "module: %s has score %d",
- p_module->psz_name, i_totalscore );
-
- /* If the high score was broken, we have a new champion */
- if( i_totalscore > i_bestscore )
+ else
{
- /* Keep the current module locked, but release the previous */
- if( p_bestmodule != NULL )
+ if( b_intf )
{
- UnlockModule( p_bestmodule );
+ /* This one doesn't match */
+ continue;
}
+ }
+ }
- /* This is the new best module */
- i_bestscore = i_totalscore;
- p_bestmodule = p_module;
+ /* Store this new module */
+ p_list[ i_index ].p_module = p_module;
+
+ /* Add it to the modules-to-probe list */
+ if( i_index == 0 )
+ {
+ p_list[ 0 ].p_next = NULL;
+ p_first = p_list;
+ }
+ else
+ {
+ /* Ok, so at school you learned that quicksort is quick, and
+ * bubble sort sucks raw eggs. But that's when dealing with
+ * thousands of items. Here we have barely 50. */
+ struct module_list_s *p_newlist = p_first;
+
+ if( p_first->p_module->pi_score[i_capability]
+ < p_module->pi_score[i_capability] )
+ {
+ p_list[ i_index ].p_next = p_first;
+ p_first = &p_list[ i_index ];
}
else
{
- /* This module wasn't interesting, unlock it and forget it */
- UnlockModule( p_module );
+ while( p_newlist->p_next != NULL
+ && p_newlist->p_next->p_module->pi_score[i_capability]
+ >= p_module->pi_score[i_capability] )
+ {
+ p_newlist = p_newlist->p_next;
+ }
+
+ p_list[ i_index ].p_next = p_newlist->p_next;
+ p_newlist->p_next = &p_list[ i_index ];
}
}
+
+ i_index++;
}
- /* We can release the global lock, module refcount was incremented */
+ /* Lock all selected modules */
+ p_tolock = p_first;
+ while( p_tolock != NULL )
+ {
+ LockModule( p_tolock->p_module );
+ p_tolock = p_tolock->p_next;
+ }
+
+ /* We can release the global lock, module refcounts were incremented */
vlc_mutex_unlock( &p_module_bank->lock );
- if( p_bestmodule != NULL )
+ /* Parse the linked list and use the first successful module */
+ while( p_first != NULL )
+ {
+ /* Test the requested capability */
+ switch( i_capability )
+ {
+ case MODULE_CAPABILITY_ACCESS:
+ i_ret = p_first->p_module->p_functions->access.functions.
+ access.pf_open( (struct input_thread_s *)p_data );
+ break;
+
+ case MODULE_CAPABILITY_DEMUX:
+ i_ret = p_first->p_module->p_functions->demux.functions.
+ demux.pf_init( (struct input_thread_s *)p_data );
+ break;
+
+ case MODULE_CAPABILITY_NETWORK:
+ i_ret = p_first->p_module->p_functions->network.functions.
+ network.pf_open( (struct network_socket_s *)p_data );
+ break;
+
+ case MODULE_CAPABILITY_DECODER:
+ i_ret = p_first->p_module->p_functions->dec.functions.
+ dec.pf_probe( (u8 *)p_data );
+ break;
+
+ case MODULE_CAPABILITY_INTF:
+ i_ret = p_first->p_module->p_functions->intf.functions.
+ intf.pf_open( (struct intf_thread_s *)p_data );
+ break;
+
+ case MODULE_CAPABILITY_AOUT:
+ i_ret = p_first->p_module->p_functions->aout.functions.
+ aout.pf_open( (struct aout_thread_s *)p_data );
+ break;
+
+ case MODULE_CAPABILITY_VOUT:
+ i_ret = p_first->p_module->p_functions->vout.functions.
+ vout.pf_create( (struct vout_thread_s *)p_data );
+ break;
+
+ case MODULE_CAPABILITY_CHROMA:
+ i_ret = p_first->p_module->p_functions->chroma.functions.
+ chroma.pf_init( (struct vout_thread_s *)p_data );
+ break;
+
+ case MODULE_CAPABILITY_IDCT:
+ case MODULE_CAPABILITY_IMDCT:
+ case MODULE_CAPABILITY_MOTION:
+ case MODULE_CAPABILITY_DOWNMIX:
+ case MODULE_CAPABILITY_MEMCPY:
+ /* This one always works */
+ i_ret = 0;
+ break;
+
+ default:
+ intf_ErrMsg( "module error: unknown module type %i",
+ i_capability );
+ i_ret = -1;
+ break;
+ }
+
+ /* If the high score was broken, we have a new champion */
+ if( i_ret == 0 )
+ {
+ break;
+ }
+ else
+ {
+ UnlockModule( p_first->p_module );
+ }
+
+ p_first = p_first->p_next;
+ }
+
+ /* Store the locked module value */
+ if( p_first != NULL )
+ {
+ p_module = p_first->p_module;
+ p_first = p_first->p_next;
+ }
+ else
+ {
+ p_module = NULL;
+ }
+
+ /* Unlock the remaining modules */
+ while( p_first != NULL )
+ {
+ UnlockModule( p_first->p_module );
+ p_first = p_first->p_next;
+ }
+
+ free( p_list );
+
+ if( p_module != NULL )
+ {
+ intf_WarnMsg( 1, "module: locking %s module `%s'",
+ GetCapabilityName( i_capability ),
+ p_module->psz_name );
+ }
+ else if( psz_name != NULL && *psz_name )
+ {
+ intf_ErrMsg( "module error: requested %s module `%s' unavailable",
+ GetCapabilityName( i_capability ), psz_name );
+ }
+
+ if( psz_realname )
{
- intf_WarnMsg( 1, "module: locking module `%s'",
- p_bestmodule->psz_name );
+ free( psz_realname );
}
- /* Don't forget that the module is still locked if bestmodule != NULL */
- return( p_bestmodule );
+ /* Don't forget that the module is still locked */
+ return( p_module );
}
/*****************************************************************************
* Following functions are local.
*****************************************************************************/
+/*****************************************************************************
+ * AllocateAllPlugins: load all plugin modules we can find.
+ *****************************************************************************/
#ifdef HAVE_DYNAMIC_PLUGINS
+static void AllocateAllPlugins( void )
+{
+ static char * path[] = { ".", "plugins", PLUGIN_PATH, NULL, NULL };
+
+ char ** ppsz_path = path;
+ char * psz_fullpath;
+ char * psz_file;
+#if defined( SYS_BEOS ) || defined( SYS_DARWIN )
+ char * psz_vlcpath = system_GetProgramPath();
+ int i_vlclen = strlen( psz_vlcpath );
+ boolean_t b_notinroot;
+#endif
+ DIR * dir;
+ struct dirent * file;
+
+ for( ; *ppsz_path != NULL ; ppsz_path++ )
+ {
+ /* Store strlen(*ppsz_path) for later use. */
+ int i_dirlen = strlen( *ppsz_path );
+
+#if defined( SYS_BEOS ) || defined( SYS_DARWIN )
+ b_notinroot = 0;
+ /* Under BeOS, we need to add beos_GetProgramPath() to access
+ * files under the current directory */
+ if( ( i_dirlen > 1 ) && strncmp( *ppsz_path, "/", 1 ) )
+ {
+ i_dirlen += i_vlclen + 2;
+ b_notinroot = 1;
+
+ psz_fullpath = malloc( i_dirlen );
+ if( psz_fullpath == NULL )
+ {
+ continue;
+ }
+ sprintf( psz_fullpath, "%s/%s", psz_vlcpath, *ppsz_path );
+ }
+ else
+#endif
+ {
+ psz_fullpath = *ppsz_path;
+ }
+
+ intf_WarnMsg( 1, "module: browsing `%s'", psz_fullpath );
+
+ if( (dir = opendir( psz_fullpath )) )
+ {
+ /* Parse the directory and try to load all files it contains. */
+ while( (file = readdir( dir )) )
+ {
+ int i_filelen = strlen( file->d_name );
+
+ /* We only load files ending with ".so" */
+ if( i_filelen > 3
+ && !strncmp( file->d_name + i_filelen - 3, ".so", 3 ) )
+ {
+ psz_file = malloc( i_dirlen + i_filelen + 2 );
+ if( psz_file == NULL )
+ {
+ continue;
+ }
+ sprintf( psz_file, "%s/%s", psz_fullpath, file->d_name );
+
+ /* We created a nice filename -- now we just try to load
+ * it as a plugin module. */
+ AllocatePluginModule( psz_file );
+
+ /* We don't care if the allocation succeeded */
+ free( psz_file );
+ }
+ }
+
+ /* Close the directory if successfully opened */
+ closedir( dir );
+ }
+
+#if defined( SYS_BEOS ) || defined( SYS_DARWIN )
+ if( b_notinroot )
+ {
+ free( psz_fullpath );
+ }
+#endif
+ }
+}
+
/*****************************************************************************
* AllocatePluginModule: load a module into memory and initialize it.
*****************************************************************************
*****************************************************************************/
static int AllocatePluginModule( char * psz_filename )
{
+ char **pp_shortcut;
module_t * p_module, * p_othermodule;
module_handle_t handle;
if( module_load( psz_filename, &handle ) )
{
/* The plugin module couldn't be opened */
- intf_WarnMsgImm( 1, "module warning: cannot open %s (%s)",
+ intf_WarnMsg( 1, "module warning: cannot open %s (%s)",
psz_filename, module_error() );
return( -1 );
}
p_module->is.plugin.handle = handle;
p_module->p_symbols = &symbols;
- /* Initialize the module : fill p_module->psz_name, etc. */
- if( CallSymbol( p_module, "InitModule" ) != 0 )
+ /* Initialize the module : fill p_module->psz_name, default config, etc. */
+ if( CallSymbol( p_module, "InitModule" MODULE_SUFFIX ) != 0 )
{
/* We couldn't call InitModule() */
free( p_module );
return( -1 );
}
- /* Check that version numbers match */
- if( strcmp( VERSION, p_module->psz_version ) )
- {
- free( p_module );
- module_unload( handle );
- return( -1 );
- }
-
/* Check that we don't already have a module with this name */
for( p_othermodule = p_module_bank->first ;
p_othermodule != NULL ;
{
if( !strcmp( p_othermodule->psz_name, p_module->psz_name ) )
{
+ intf_WarnMsg( 5, "module warning: cannot load %s, a module named "
+ "`%s' already exists",
+ psz_filename, p_module->psz_name );
free( p_module );
module_unload( handle );
return( -1 );
}
/* Activate the module : fill the capability structure, etc. */
- if( CallSymbol( p_module, "ActivateModule" ) != 0 )
+ if( CallSymbol( p_module, "ActivateModule" MODULE_SUFFIX ) != 0 )
{
/* We couldn't call ActivateModule() */
free( p_module );
return( -1 );
}
+ for( pp_shortcut = p_module->pp_shortcuts ; *pp_shortcut ; pp_shortcut++ )
+ {
+ *pp_shortcut = strdup( *pp_shortcut );
+ }
+
/* We strdup() these entries so that they are still valid when the
* module is unloaded. */
p_module->is.plugin.psz_filename =
strdup( p_module->is.plugin.psz_filename );
p_module->psz_name = strdup( p_module->psz_name );
p_module->psz_longname = strdup( p_module->psz_longname );
- p_module->psz_version = strdup( p_module->psz_version );
+
if( p_module->is.plugin.psz_filename == NULL
|| p_module->psz_name == NULL
- || p_module->psz_longname == NULL
- || p_module->psz_version == NULL )
+ || p_module->psz_longname == NULL )
{
intf_ErrMsg( "module error: can't duplicate strings" );
- if( p_module->is.plugin.psz_filename != NULL )
- {
- free( p_module->is.plugin.psz_filename );
- }
-
- if( p_module->psz_name != NULL )
- {
- free( p_module->psz_name );
- }
-
- if( p_module->psz_longname != NULL )
- {
- free( p_module->psz_longname );
- }
-
- if( p_module->psz_version != NULL )
- {
- free( p_module->psz_version );
- }
+ free( p_module->is.plugin.psz_filename );
+ free( p_module->psz_name );
+ free( p_module->psz_longname );
+ free( p_module->psz_program );
free( p_module );
module_unload( handle );
return( -1 );
}
+ if( p_module->psz_program != NULL )
+ {
+ p_module->psz_program = strdup( p_module->psz_program );
+ }
+
/* Everything worked fine ! The module is ready to be added to the list. */
p_module->i_usage = 0;
p_module->i_unused_delay = 0;
p_module->next = p_module_bank->first;
p_module->prev = NULL;
p_module_bank->first = p_module;
+ p_module_bank->i_count++;
/* Immediate message so that a slow module doesn't make the user wait */
- intf_WarnMsgImm( 2, "module: new plugin module `%s', %s",
+ intf_WarnMsg( 2, "module: new plugin module `%s', %s",
p_module->psz_name, p_module->psz_longname );
return( 0 );
}
#endif /* HAVE_DYNAMIC_PLUGINS */
-#ifdef ALLOCATE_ALL_BUILTINS
/*****************************************************************************
* AllocateBuiltinModule: initialize a built-in module.
*****************************************************************************
return( -1 );
}
- /* Check that version numbers match */
- if( strcmp( VERSION, p_module->psz_version ) )
- {
- free( p_module );
- return( -1 );
- }
-
/* Check that we don't already have a module with this name */
for( p_othermodule = p_module_bank->first ;
p_othermodule != NULL ;
{
if( !strcmp( p_othermodule->psz_name, p_module->psz_name ) )
{
+ intf_WarnMsg( 5, "module warning: cannot load builtin `%s', a "
+ "module named `%s' already exists",
+ p_module->psz_name, p_module->psz_name );
free( p_module );
return( -1 );
}
return( -1 );
}
- /* We strdup() these entries so that they are still valid when the
- * module is unloaded. */
- p_module->psz_name = strdup( p_module->psz_name );
- p_module->psz_longname = strdup( p_module->psz_longname );
- p_module->psz_version = strdup( p_module->psz_version );
- if( p_module->psz_name == NULL
- || p_module->psz_longname == NULL
- || p_module->psz_version == NULL )
- {
- intf_ErrMsg( "module error: can't duplicate strings" );
-
- if( p_module->psz_name != NULL )
- {
- free( p_module->psz_name );
- }
-
- if( p_module->psz_longname != NULL )
- {
- free( p_module->psz_longname );
- }
-
- if( p_module->psz_version != NULL )
- {
- free( p_module->psz_version );
- }
-
- free( p_module );
- return( -1 );
- }
-
/* Everything worked fine ! The module is ready to be added to the list. */
p_module->i_usage = 0;
p_module->i_unused_delay = 0;
p_module->next = p_module_bank->first;
p_module->prev = NULL;
p_module_bank->first = p_module;
+ p_module_bank->i_count++;
/* Immediate message so that a slow module doesn't make the user wait */
- intf_WarnMsgImm( 2, "module: new builtin module `%s', %s",
+ intf_WarnMsg( 2, "module: new builtin module `%s', %s",
p_module->psz_name, p_module->psz_longname );
return( 0 );
}
-#endif /* ALLOCATE_ALL_BUILTINS */
/*****************************************************************************
* DeleteModule: delete a module and its structure.
#endif
/* Unlink the module from the linked list. */
- if( p_module == p_module_bank->first )
- {
- p_module_bank->first = p_module->next;
- }
-
if( p_module->prev != NULL )
{
p_module->prev->next = p_module->next;
}
+ else
+ {
+ p_module_bank->first = p_module->next;
+ }
if( p_module->next != NULL )
{
p_module->next->prev = p_module->prev;
}
+ p_module_bank->i_count--;
+
/* We free the structures that we strdup()ed in Allocate*Module(). */
#ifdef HAVE_DYNAMIC_PLUGINS
if( !p_module->b_builtin )
{
+ char **pp_shortcut = p_module->pp_shortcuts;
+
+ for( ; *pp_shortcut ; pp_shortcut++ )
+ {
+ free( *pp_shortcut );
+ }
+
free( p_module->is.plugin.psz_filename );
+ free( p_module->psz_name );
+ free( p_module->psz_longname );
+ free( p_module->psz_program );
}
#endif
- free( p_module->psz_name );
- free( p_module->psz_longname );
- free( p_module->psz_version );
free( p_module );
* to be a bit more clever here. */
/* Activate the module : fill the capability structure, etc. */
- if( CallSymbol( p_module, "ActivateModule" ) != 0 )
+ if( CallSymbol( p_module, "ActivateModule" MODULE_SUFFIX ) != 0 )
{
/* We couldn't call ActivateModule() -- looks nasty, but
* we can't do much about it. Just try to unload module. */
}
/* Deactivate the module : free the capability structure, etc. */
- if( CallSymbol( p_module, "DeactivateModule" ) != 0 )
+ if( CallSymbol( p_module, "DeactivateModule" MODULE_SUFFIX ) != 0 )
{
/* We couldn't call DeactivateModule() -- looks nasty, but
* we can't do much about it. Just try to unload module anyway. */