diff --git a/include/QF/plugin.h b/include/QF/plugin.h index 80efd5ab8..10b21e4e0 100644 --- a/include/QF/plugin.h +++ b/include/QF/plugin.h @@ -107,6 +107,7 @@ extern struct cvar_s *fs_pluginpath; */ plugin_t *PI_LoadPlugin (const char *, const char *); qboolean PI_UnloadPlugin (plugin_t *); +void PI_RegisterPlugins (plugin_list_t *); void PI_Init (void); void PI_Shutdown (void); diff --git a/libs/audio/cd.c b/libs/audio/cd.c index 61b01ba06..e4672b8cd 100644 --- a/libs/audio/cd.c +++ b/libs/audio/cd.c @@ -93,6 +93,7 @@ CD_f (void) int CDAudio_Init (void) { + PI_RegisterPlugins (cd_plugin_list); cd_plugin = Cvar_Get ("cd_plugin", "null", CVAR_ARCHIVE, NULL, "CD Plugin to use"); cdmodule = PI_LoadPlugin ("cd", cd_plugin->string); diff --git a/libs/audio/snd.c b/libs/audio/snd.c index 5fc60066b..c5f55c8cd 100644 --- a/libs/audio/snd.c +++ b/libs/audio/snd.c @@ -84,6 +84,8 @@ S_Init (void) return; } + PI_RegisterPlugins (snd_output_list); + PI_RegisterPlugins (snd_render_list); snd_output_module = PI_LoadPlugin ("snd_output", snd_output->string); if (!snd_output_module) { Sys_Printf ("Loading of sound output module: %s failed!\n", diff --git a/libs/util/plugin.c b/libs/util/plugin.c index f75f683e5..106910db1 100644 --- a/libs/util/plugin.c +++ b/libs/util/plugin.c @@ -55,13 +55,21 @@ static const char rcsid[] = #endif #include "QF/cvar.h" +#include "QF/hash.h" #include "QF/plugin.h" #include "QF/sys.h" #include "compat.h" -cvar_t *fs_pluginpath; +cvar_t *fs_pluginpath; +hashtab_t *registered_plugins; + +static const char * +get_key (void *pl, void *unused) +{ + return ((plugin_list_t *)pl)->name; +} void PI_InitCvars (void) @@ -80,6 +88,7 @@ void PI_Init (void) { PI_InitCvars (); + registered_plugins = Hash_NewTable (253, get_key, 0, 0); } void @@ -91,62 +100,74 @@ plugin_t * PI_LoadPlugin (const char *type, const char *name) { char realname[4096]; + char plugin_name[1024]; char plugin_info_name[1024]; char *tmpname; void *dlhand = NULL; plugin_t *plugin = NULL; P_PluginInfo plugin_info = NULL; + plugin_list_t *pl; if (!name) return NULL; tmpname = strrchr (name, '/'); // Get the base name, don't allow paths - // Build the plugin info name - snprintf (plugin_info_name, sizeof (plugin_info_name), "%s_%s_PluginInfo", - type, name); - // Build the path to the file to load + // Build the plugin name + snprintf (plugin_name, sizeof (plugin_name), "%s_%s", type, name); + pl = Hash_Find (registered_plugins, plugin_name); + if (pl) { + plugin_info = pl->info; + } + if (!plugin_info) { + // Build the plugin info name + snprintf (plugin_info_name, sizeof (plugin_info_name), + "%s_%s_PluginInfo", type, name); + // Build the path to the file to load #if defined(HAVE_DLOPEN) - snprintf (realname, sizeof (realname), "%s/lib%s_%s.so", - fs_pluginpath->string, type, (tmpname ? tmpname + 1 : name)); + snprintf (realname, sizeof (realname), "%s/lib%s_%s.so", + fs_pluginpath->string, type, + (tmpname ? tmpname + 1 : name)); #elif defined(_WIN32) - snprintf (realname, sizeof (realname), "%s/QF%s_%s.dll", - fs_pluginpath->string, type, (tmpname ? tmpname + 1 : name)); + snprintf (realname, sizeof (realname), "%s/QF%s_%s.dll", + fs_pluginpath->string, type, + (tmpname ? tmpname + 1 : name)); #else # error "No shared library support. FIXME" - return NULL; + return NULL; #endif #if defined(HAVE_DLOPEN) - if (!(dlhand = dlopen (realname, RTLD_GLOBAL | RTLD_NOW))) { - // lib not found - Sys_Printf ("Could not load plugin \"%s\": %s\n", realname, - dlerror ()); - return NULL; - } + if (!(dlhand = dlopen (realname, RTLD_GLOBAL | RTLD_NOW))) { + // lib not found + Sys_Printf ("Could not load plugin \"%s\": %s\n", realname, + dlerror ()); + return NULL; + } #elif defined (_WIN32) - if (!(dlhand = LoadLibrary (realname))) { // lib not found - Sys_Printf ("Could not load plugin \"%s\".\n", realname); - return NULL; - } + if (!(dlhand = LoadLibrary (realname))) { // lib not found + Sys_Printf ("Could not load plugin \"%s\".\n", realname); + return NULL; + } #endif #if defined(HAVE_DLOPEN) - if (!(plugin_info = dlsym (dlhand, plugin_info_name))) { - // info function not found - dlclose (dlhand); - Sys_Printf ("Plugin info function not found\n"); - return NULL; - } + if (!(plugin_info = dlsym (dlhand, plugin_info_name))) { + // info function not found + dlclose (dlhand); + Sys_Printf ("Plugin info function not found\n"); + return NULL; + } #elif defined (_WIN32) - if (!(plugin_info = (P_PluginInfo) GetProcAddress (dlhand, - plugin_info_name))) { - // info function not found - FreeLibrary (dlhand); - Sys_Printf ("Plugin info function not found\n"); - return NULL; - } + if (!(plugin_info = (P_PluginInfo) GetProcAddress (dlhand, + plugin_info_name))) { + // info function not found + FreeLibrary (dlhand); + Sys_Printf ("Plugin info function not found\n"); + return NULL; + } #endif + } if (!(plugin = plugin_info ())) { // Something went badly wrong #if defined(HAVE_DLOPEN) @@ -173,9 +194,18 @@ PI_UnloadPlugin (plugin_t *plugin) } else { Sys_Printf ("Warning: No shutdown function for type %d plugin!\n", plugin->type); } + if (!plugin->handle) // we didn't load it + return true; #if defined(HAVE_DLOPEN) return (dlclose (plugin->handle) == 0); #elif defined (_WIN32) return (FreeLibrary (plugin->handle) == 0); #endif } + +void +PI_RegisterPlugins (plugin_list_t *plugins) +{ + while (plugins->name) + Hash_Add (registered_plugins, plugins++); +}