diff --git a/acconfig.h b/acconfig.h index 1eb3b2540..18c80d03e 100644 --- a/acconfig.h +++ b/acconfig.h @@ -25,6 +25,9 @@ /* Define this to the location of the user config file */ #undef FS_USERCFG +/* Define this to the path from which to load plugins */ +#undef FS_PLUGINPATH + /* Define this to the shared game directory root */ #undef FS_SHAREPATH diff --git a/configure.in b/configure.in index b39e00611..1c72224c5 100644 --- a/configure.in +++ b/configure.in @@ -1053,7 +1053,7 @@ dnl ================================================================== dnl Set $prefix and $exec_prefix to $ac_default_prefix if they are not set test "x$prefix" = xNONE && prefix=$ac_default_prefix -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' +test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" if test "x$SYSTYPE" = xWIN32; then default_globalconf="~/${PACKAGE}.conf" @@ -1112,6 +1112,20 @@ elif test "x$userpath" = xno; then fi AC_DEFINE_UNQUOTED(FS_USERPATH, "$userpath") +AC_ARG_WITH(userpath, +[ --with-plugin-path=DIR Use DIR for loading plugins, defaults to + \${libdir}/quakeforge], +pluginpath=$withval, pluginpath="auto") + +eval foo="$libdir" +default_pluginpath="$foo/$PACKAGE" +if test "x$pluginpath" = "xauto" -o "x$pluginpath" = "xyes" -o "x$pluginpath" = "x"; then + pluginpath="$default_pluginpath" +elif test "x$pluginpath" = xno; then + pluginpath="." +fi +AC_DEFINE_UNQUOTED(FS_PLUGINPATH, "$pluginpath") + dnl CFLAGS for release and devel versions CFLAGS="" AC_ARG_ENABLE(debug, @@ -1496,6 +1510,7 @@ AC_MSG_RESULT([ Shared game data directory: $sharepath Per-user game data directory: $userpath + Plugin load directory: $pluginpath Global configuration file: $globalconf User configuration file: $userconf ]) diff --git a/include/QF/plugin.h b/include/QF/plugin.h new file mode 100644 index 000000000..58123e001 --- /dev/null +++ b/include/QF/plugin.h @@ -0,0 +1,88 @@ +/* + plugin.h + + QuakeForge plugin API structures and prototypes + + Copyright (C) 2001 Jeff Teunissen + + 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 the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifndef __QF_plugin_h_ +#define __QF_plugin_h_ + +#define QFPLUGIN_VERSION "1.0" + +#define QFPLUGIN + +#include +#include +#include +#include + +typedef enum { + qfp_null = 0, // Not real + qfp_input, // Input (pointing devices, joysticks, etc) + qfp_sound, // Wave output (OSS, ALSA, Win32) +} plugin_type_t; + +typedef struct plugin_funcs_s { + general_funcs_t *general; + input_funcs_t *input; + sound_funcs_t *sound; +} plugin_funcs_t; + +typedef struct plugin_data_s { + general_data_t *general; + input_data_t *input; + sound_data_t *sound; +} plugin_data_t; + +typedef struct plugin_s { + plugin_type_t type; + void *handle; + char *api_version; + char *plugin_version; + char *description; + char *copyright; + plugin_funcs_t *functions; + plugin_data_t *data; +} plugin_t; + +/* + General plugin info return function type +*/ +typedef plugin_t * (*P_PluginInfo) (void); + +/* + Plugin system variables +*/ +extern cvar_t *fs_pluginpath; + +/* + Function prototypes +*/ +plugin_t *PI_LoadPlugin (char *, char *); +qboolean PI_UnloadPlugin (plugin_t *); +void PI_Init (void); +void PI_Shutdown (void); + +#endif // __QF_plugin_h_ diff --git a/include/QF/plugin/general.h b/include/QF/plugin/general.h new file mode 100644 index 000000000..0b34462e7 --- /dev/null +++ b/include/QF/plugin/general.h @@ -0,0 +1,50 @@ +/* + QF/plugin/general.h + + General plugin data and structures + + Copyright (C) 2001 Jeff Teunissen + + 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 the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifndef __QF_plugin_general_h_ +#define __QF_plugin_general_h_ + +#include +#include + +/* + All plugins, of all types, must export these functions +*/ + +typedef void (QFPLUGIN *P_Init) (void); +typedef void (QFPLUGIN *P_Shutdown) (void); + +typedef struct general_func_s { + P_Init p_Init; + P_Shutdown p_Shutdown; +} general_funcs_t; + +typedef struct general_data_s { +} general_data_t; + +#endif // __QF_plugin_general_h_ diff --git a/include/QF/plugin/input.h b/include/QF/plugin/input.h new file mode 100644 index 000000000..50fe2fc3b --- /dev/null +++ b/include/QF/plugin/input.h @@ -0,0 +1,56 @@ +/* + QF/plugin/input.h + + Input plugin data and structures + + Copyright (C) 2001 Jeff Teunissen + + 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 the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifndef __QF_plugin_input_h_ +#define __QF_plugin_input_h_ + +#include +#include +#include + +/* + All input plugins must export these functions +*/ +typedef void (QFPLUGIN *P_IN_Commands) (void); +typedef void (QFPLUGIN *P_IN_SendKeyEvents) (void); +typedef void (QFPLUGIN *P_IN_Move) (void); +typedef void (QFPLUGIN *P_IN_ModeChanged) (void); +typedef void (QFPLUGIN *P_IN_HandlePause) (qboolean paused); + +typedef struct input_funcs_s { + P_IN_Commands pIN_Commands; + P_IN_SendKeyEvents pIN_SendKeyEvents; + P_IN_Move pIN_Move; + P_IN_ModeChanged pIN_ModeChanged; + P_IN_HandlePause pIN_HandlePause; +} input_funcs_t; + +typedef struct input_data_s { +} input_data_t; + +#endif // __QF_plugin_input_h_ diff --git a/include/QF/plugin/sound.h b/include/QF/plugin/sound.h new file mode 100644 index 000000000..99b66fe31 --- /dev/null +++ b/include/QF/plugin/sound.h @@ -0,0 +1,77 @@ +/* + QF/plugin/sound.h + + Sound plugin data types + + Copyright (C) 2001 Jeff Teunissen + + 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 the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ +#ifndef __QF_plugin_sound_h_ +#define __QF_plugin_sound_h_ + +#include +#include +#include + +/* + All sound plugins must export these functions +*/ +typedef void (QFPLUGIN *P_S_Init) (void); +typedef void (QFPLUGIN *P_S_Shutdown) (void); +typedef void (QFPLUGIN *P_S_AmbientOff) (void); +typedef void (QFPLUGIN *P_S_AmbientOn) (void); +typedef void (QFPLUGIN *P_S_TouchSound) (char *sample); +typedef void (QFPLUGIN *P_S_ClearBuffer) (void); +typedef void (QFPLUGIN *P_S_StartSound) (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation); +typedef void (QFPLUGIN *P_S_StaticSound) (sfx_t *sfx, vec3_t origin, float vol, float attenuation); +typedef void (QFPLUGIN *P_S_StopSound) (int entnum, int entchannel); +typedef sfx_t * (QFPLUGIN *P_S_PrecacheSound) (char *sample); +typedef void (QFPLUGIN *P_S_ClearPrecache) (void); +typedef void (QFPLUGIN *P_S_Update) (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up); +typedef void (QFPLUGIN *P_S_StopAllSounds) (qboolean clear); +typedef void (QFPLUGIN *P_S_BeginPrecaching) (void); +typedef void (QFPLUGIN *P_S_EndPrecaching) (void); +typedef void (QFPLUGIN *P_S_ExtraUpdate) (void); +typedef void (QFPLUGIN *P_S_LocalSound) (char *s); + +typedef struct sound_funcs_s { + P_S_AmbientOff pS_AmbientOff; + P_S_AmbientOn pS_AmbientOn; + P_S_TouchSound pS_TouchSound; + P_S_ClearBuffer pS_ClearBuffer; + P_S_StaticSound pS_StaticSound; + P_S_StartSound pS_StartSound; + P_S_StopSound pS_StopSound; + P_S_PrecacheSound pS_PrecacheSound; + P_S_ClearPrecache pS_ClearPrecache; + P_S_Update pS_Update; + P_S_StopAllSounds pS_StopAllSounds; + P_S_BeginPrecaching pS_BeginPrecaching; + P_S_EndPrecaching pS_EndPrecaching; + P_S_ExtraUpdate pS_ExtraUpdate; + P_S_LocalSound pS_LocalSound; +} sound_funcs_t; + +typedef struct sound_data_s { +} sound_data_t; + +#endif // __QF_plugin_sound_h_ diff --git a/libs/util/Makefile.am b/libs/util/Makefile.am index c8873e7c0..130a48c47 100644 --- a/libs/util/Makefile.am +++ b/libs/util/Makefile.am @@ -7,7 +7,7 @@ libQFutil_la_SOURCES = \ checksum.c cmd.c console.c con_print.c crc.c cvar.c hash.c \ info.c link.c math.S \ mathlib.c \ - mdfour.c msg.c qargs.c qendian.c qfplist.c quakefs.c quakeio.c \ - sizebuf.c sys.c sys_error.c va.c ver_check.c zone.c + mdfour.c msg.c plugin.c qargs.c qendian.c qfplist.c quakefs.c \ + quakeio.c sizebuf.c sys.c sys_error.c va.c ver_check.c zone.c LIBLIST = libQFutil.la @LIBRARY_SEARCH_PATH@ diff --git a/libs/util/plugin.c b/libs/util/plugin.c new file mode 100644 index 000000000..605f9ab21 --- /dev/null +++ b/libs/util/plugin.c @@ -0,0 +1,140 @@ +/* + plugin.c + + QuakeForge plugin API functions + + Copyright (C) 2001 Jeff Teunissen + + 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 the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STDIO_H +# include +#endif + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_STRINGS_H +# include +#endif + +#ifdef HAVE_DLFCN_H +# include +#endif +#ifndef RTLD_LAZY +# ifdef DL_LAZY +# define RTLD_LAZY DL_LAZY +# else +# define RTLD_LAZY 0 +# endif +#endif + +#include +#include + +cvar_t *fs_pluginpath; + +void +PI_InitCvars (void) +{ + fs_pluginpath = Cvar_Get ("fs_pluginpath", FS_PLUGINPATH, CVAR_ROM, NULL, + "Location of your plugin directory"); +} + +/* + PI_Init + + Eventually this function will likely initialize libltdl. It doesn't, yet, + since we aren't using libltdl yet. +*/ +void +PI_Init (void) +{ + PI_InitCvars (); +} + +void +PI_Shutdown (void) +{ +} + +plugin_t * +PI_LoadPlugin (char *type, char *name) +{ +#ifdef HAVE_DLOPEN + char realname[4096]; + char *tmpname; + void *dlhand = NULL; + plugin_t *plugin = NULL; + P_PluginInfo plugin_info = NULL; + + if (!name) + return NULL; + + tmpname = strrchr (name, '/'); // Get the base name, don't allow paths + + // Build the path to the file to load + snprintf (realname, sizeof (realname), "%s/%s_%s.o", + fs_pluginpath->string, type, (tmpname ? tmpname + 1 : name)); + + if (!(dlhand = dlopen (realname, RTLD_LAZY))) // lib not found + return NULL; + + if (!(plugin_info = dlsym (dlhand, "PluginInfo"))) { // info function not found + dlclose (dlhand); + return NULL; + } + + if (!(plugin = plugin_info ())) { // Something went badly wrong + dlclose (dlhand); + return NULL; + } + + plugin->handle = dlhand; + return plugin; +#else + return NULL; // no plugin support +#endif +} + +qboolean +PI_UnloadPlugin (plugin_t *plugin) +{ + if (plugin + && plugin->functions + && plugin->functions->general + && plugin->functions->general->p_Shutdown) { + plugin->functions->general->p_Shutdown (); + } else { + Con_Printf ("Warning: No shutdown function for plugin!"); + } +#ifdef HAVE_DLOPEN + return (dlclose (plugin->handle) == 0); +#else + return false; +#endif +}