From 9cc30959e412ead6fd579b2ade38bacef3c3494c Mon Sep 17 00:00:00 2001
From: Adam Olsen <rhamph@gmail.com>
Date: Sat, 19 May 2001 00:05:35 +0000
Subject: [PATCH] Sound now uses runtime plugins.  Much thanks to Deek for
 doing all the thinking :) set fs_pluginpath to point to the right dir, and
 set snd_plugin to pick a sound plugin.

Current issues:
- alsa 0.5 won't build properly, dunno why
- segfault on exit.  I think I know the cause of this, and how to fix it
- alsa 0.9, gus, sgi, sun, and win32 havn't been tested
---
 configure.in                          | 207 ++++++++++++++-----------
 include/QF/plugin/sound.h             |   3 +
 libs/audio/Makefile.am                |  11 ++
 libs/audio/snd.c                      | 208 ++++++++++++++++++++++++++
 libs/audio/{targets => }/snd_common.c |   0
 libs/audio/targets/Makefile.am        |  93 +++++++-----
 libs/audio/targets/snd_alsa_0_5.c     |  68 +++++++++
 libs/audio/targets/snd_alsa_0_9.c     |  67 +++++++++
 libs/audio/targets/snd_disk.c         |  68 +++++++++
 libs/audio/targets/snd_dma.c          | 167 +++++++++++----------
 libs/audio/targets/snd_mem.c          |   6 +-
 libs/audio/targets/snd_mix.c          |  13 +-
 libs/audio/targets/snd_null.c         | 108 ++++++++++---
 libs/audio/targets/snd_oss.c          |  67 +++++++++
 libs/audio/targets/snd_sdl.c          |  72 ++++++++-
 libs/audio/targets/snd_sgi.c          |  67 +++++++++
 libs/audio/targets/snd_sun.c          |  68 +++++++++
 libs/util/plugin.c                    |   8 +-
 nq/source/Makefile.am                 |   4 +-
 qw/source/Makefile.am                 |   4 +-
 qw/source/cl_main.c                   |   4 +-
 21 files changed, 1074 insertions(+), 239 deletions(-)
 create mode 100644 libs/audio/snd.c
 rename libs/audio/{targets => }/snd_common.c (100%)

diff --git a/configure.in b/configure.in
index 841528da2..3f833f7a6 100644
--- a/configure.in
+++ b/configure.in
@@ -754,59 +754,47 @@ dnl ==================================================================
 AC_CHECK_LIB(mme, waveOutOpen, HAVE_LIBMME=yes)
 
 AC_ARG_ENABLE(alsa,
-[  --enable-alsa           enable checks for ALSA support],
-)
+	[  --disable-alsa          disable checks for ALSA support])
 
 AC_ARG_ENABLE(sound,
-[  --disable-sound         disable sound outright],
+	[  --disable-sound         disable sound outright]
 )
 
-SNDTYPE=""
-SOUND_LIBS=""
-SOUND_CFLAGS=""
+SOUND_TYPES=
 AC_MSG_CHECKING(for sound support)
 
-dnl SDL digital audio
-AC_ARG_ENABLE(sdl-audio,
-[  --enable-sdl-audio      use SDL for audio output],
-	if test -z "$SNDTYPE" -a "x$HAVE_SDL" = "xyes"; then
-		SNDTYPE="SDL"
-		SOUND_LIBS="$SDL_LIBS"
-		SOUND_CFLAGS="$SDL_CFLAGS"
-	fi
-)
-
-if test "x$enable_alsa" = "xyes"; then
-	if test -z "$SNDTYPE" -a "x$ac_cv_header_sys_asoundlib_h" = "xyes"; then
+if test "x$enable_alsa" != "xno" -a \
+		"x$ac_cv_header_sys_asoundlib_h" = "xyes"; then
+	AC_EGREP_CPP([QF_maGiC_VALUE],
+		[
+#include <sys/asoundlib.h>
+#if defined(SND_LIB_MAJOR) && defined(SND_LIB_MINOR)
+#if SND_LIB_MAJOR > 0 || (SND_LIB_MAJOR == 0 && SND_LIB_MINOR == 5)
+QF_maGiC_VALUE
+#endif
+#endif
+		],
+		SOUND_TYPES="$SOUND_TYPES ALSA0.5"
+		ALSA_LIBS="-lasound",
 		AC_EGREP_CPP([QF_maGiC_VALUE],
 			[
 #include <sys/asoundlib.h>
 #if defined(SND_LIB_MAJOR) && defined(SND_LIB_MINOR)
-#if SND_LIB_MAJOR>0 || (SND_LIB_MAJOR==0 && SND_LIB_MINOR==5)
+#if SND_LIB_MAJOR > 0 || (SND_LIB_MAJOR == 0 && SND_LIB_MINOR >= 9)
 QF_maGiC_VALUE
 #endif
 #endif
 			],
-			SNDTYPE="ALSA_0_5"
-			SOUND_LIBS="-lasound",
-			AC_EGREP_CPP([QF_maGiC_VALUE],
-				[
-#include <sys/asoundlib.h>
-#if defined(SND_LIB_MAJOR) && defined(SND_LIB_MINOR)
-#if SND_LIB_MAJOR>0 || (SND_LIB_MAJOR==0 && SND_LIB_MINOR>=9)
-QF_maGiC_VALUE
-#endif
-#endif
-				],
-				SNDTYPE="ALSA_0_9"
-				SOUND_LIBS="-lasound"
-			)
+			SOUND_TYPES="$SOUND_TYPES ALSA0.9"
+			ALSA_LIBS="-lasound"
 		)
-	fi
+	)
 fi
+AC_SUBST(ALSA_LIBS)
 
 dnl MME
-if test -z "$SNDTYPE" -a "x$ac_cv_header_mme_mmsystem_h" = "xyes" -a "x$HAVE_LIBMME" = "xyes"; then
+if test "x$ac_cv_header_mme_mmsystem_h" = "xyes" -a \
+		"x$HAVE_LIBMME" = "xyes"; then
 	AC_EGREP_CPP([QF_maGiC_VALUE],
 		[
 #include <mme/mmsystem.h>
@@ -814,96 +802,119 @@ if test -z "$SNDTYPE" -a "x$ac_cv_header_mme_mmsystem_h" = "xyes" -a "x$HAVE_LIB
 QF_maGiC_VALUE
 #endif
 		],
-		SNDTYPE="MME"
-		SOUND_LIBS="-lmme"
+		SOUND_TYPES="$SOUND_TYPES MME"
+		MME_LIBS="-lmme"
 	)
 fi
+AC_SUBST(MME_LIBS)
 
 dnl OSS
-if test -z "$SNDTYPE" -a "x$ac_cv_header_sys_soundcard_h" = "xyes"; then
-	AC_EGREP_CPP([QF_maGiC_VALUE],[
+if test "x$ac_cv_header_sys_soundcard_h" = "xyes" -o \
+		"x$ac_cv_header_machine_soundcard_h" = "xyes" -o \
+		"x$ac_cv_header_linux_soundcard_h" = "xyes"; then
+	AC_EGREP_CPP([QF_maGiC_VALUE],
+		[
 #include <sys/soundcard.h>
 #ifdef SNDCTL_DSP_SETTRIGGER
 QF_maGiC_VALUE
 #endif
-	], SNDTYPE="OSS")
-fi
-if test -z "$SNDTYPE" -a "x$ac_cv_header_linux_soundcard_h" = "xyes"; then
-	AC_EGREP_CPP([QF_maGiC_VALUE],[
+		],
+		SOUND_TYPES="$SOUND_TYPES OSS",
+		AC_EGREP_CPP([QF_maGiC_VALUE],
+			[
 #include <linux/soundcard.h>
 #ifdef SNDCTL_DSP_SETTRIGGER
 QF_maGiC_VALUE
 #endif
-	], SNDTYPE="OSS")
-fi
-if test -z "$SNDTYPE" -a "x$ac_cv_header_machine_soundcard_h" = "xyes"; then
-	AC_EGREP_CPP([QF_maGiC_VALUE],[
+			],
+			SOUND_TYPES="$SOUND_TYPES OSS",
+			AC_EGREP_CPP([QF_maGiC_VALUE],
+				[
 #include <machine/soundcard.h>
 #ifdef SNDCTL_DSP_SETTRIGGER
 QF_maGiC_VALUE
 #endif
-	], SNDTYPE="OSS")
+				],
+				SOUND_TYPES="$SOUND_TYPES OSS"
+			)
+		)
+	)
 fi
 
+dnl SDL digital audio
+AC_ARG_ENABLE(sdl-audio,
+[  --enable-sdl-audio      use SDL for audio output],
+	if test "x$HAVE_SDL" = "xyes"; then
+		SOUND_TYPES="$SOUND_TYPES SDL"
+	fi
+)
+
 dnl SGI
-if test -z "$SNDTYPE" -a "x$ac_cv_header_dmedia_audio_h" = "xyes"; then
-   AC_EGREP_CPP([QF_maGiC_VALUE],[
+if test "x$ac_cv_header_dmedia_audio_h" = "xyes"; then
+   AC_EGREP_CPP([QF_maGiC_VALUE],
+   		[
 #include <dmedia/audio.h>
 #ifdef AL_SAMPLE_16
-#ifdef AL_RATE
+# ifdef AL_RATE
 QF_maGiC_VALUE
+# endif
 #endif
-#endif
-	], SNDTYPE="SGI" SOUND_LIBS="-laudio")
+		],
+		SOUND_TYPES="$SOUND_TYPES SGI"
+		SGISND_LIBS="-laudio")
 fi
+AC_SUBST(SGISND_LIBS)
 
 dnl Sun
-if test -z "$SNDTYPE" -a "x$ac_cv_header_sys_audioio_h" = "xyes"; then
-   AC_EGREP_CPP([QF_maGiC_VALUE],[
+if test "x$ac_cv_header_sys_audioio_h" = "xyes"; then
+	AC_EGREP_CPP([QF_maGiC_VALUE],
+		[
 #include <sys/audioio.h>
 #ifdef AUDIO_SETINFO
 QF_maGiC_VALUE
 #endif
-	], SNDTYPE="SUN")
+		],
+		SOUND_TYPES="$SOUND_TYPES SUN"
+	)
 fi
 
 dnl Win32
-if test -z "$SNDTYPE" -a "x$ac_cv_header_windows_h" = "xyes" -a \
-	"x$ac_cv_header_dsound_h" = "xyes"; then
-  AC_EGREP_CPP([QF_maGiC_VALUE],[
+if test "x$ac_cv_header_windows_h" = "xyes" -a \
+		"x$ac_cv_header_dsound_h" = "xyes"; then
+	AC_EGREP_CPP([QF_maGiC_VALUE],
+		[
 #include <windows.h>
 #include <dsound.h>
 #ifdef GMEM_MOVEABLE
-#ifdef DirectSoundEnumerate
+# ifdef DirectSoundEnumerate
 QF_maGiC_VALUE
+# endif
 #endif
-#endif
-    ], SNDTYPE="WIN32"
-       SOUND_LIBS="-lwinmm")
+		],
+		SOUND_TYPES="$SOUND_TYPES Win32"
+		WINSND_LIBS="-lwinmm"
+	)
 fi
+AC_SUBST(WINSND_LIBS)
 
 if test "x$enable_sound" = "xno"; then
-	SNDTYPE=""
-	SOUND_LIBS=""
+	SOUND_TYPES=""
 fi
 
-if test "$SNDTYPE"; then
-	AC_MSG_RESULT([yes ($SNDTYPE)])
+AM_CONDITIONAL(HAVE_SND_ALSA_0_5, test "`echo $SOUND_TYPES | grep ALSA0.5`")
+AM_CONDITIONAL(HAVE_SND_ALSA_0_9, test "`echo $SOUND_TYPES | grep ALSA0.9`")
+AM_CONDITIONAL(HAVE_SND_MME, test "`echo $SOUND_TYPES | grep MME`")
+AM_CONDITIONAL(HAVE_SND_OSS, test "`echo $SOUND_TYPES | grep OSS`")
+AM_CONDITIONAL(HAVE_SND_SDL, test "`echo $SOUND_TYPES | grep SDL`")
+AM_CONDITIONAL(HAVE_SND_SGI, test "`echo $SOUND_TYPES | grep SGI`")
+AM_CONDITIONAL(HAVE_SND_SUN, test "`echo $SOUND_TYPES | grep SUN`")
+AM_CONDITIONAL(HAVE_SND_WIN32, test "`echo $SOUND_TYPES | grep Win32`")
+
+if test "$SOUND_TYPES"; then
+	AC_MSG_RESULT([$SOUND_TYPES])
 else
 	AC_MSG_RESULT([no, using null sound driver])
 fi
-AC_SUBST(SOUND_LIBS)
-AC_SUBST(SOUND_CFLAGS)
-
-AM_CONDITIONAL(SNDTYPE_ALSA_0_5, test "$SNDTYPE" = "ALSA_0_5")
-AM_CONDITIONAL(SNDTYPE_ALSA_0_9, test "$SNDTYPE" = "ALSA_0_9")
-AM_CONDITIONAL(SNDTYPE_MME, test "$SNDTYPE" = "MME")
-AM_CONDITIONAL(SNDTYPE_OSS, test "$SNDTYPE" = "OSS")
-AM_CONDITIONAL(SNDTYPE_SDL, test "$SNDTYPE" = "SDL")
-AM_CONDITIONAL(SNDTYPE_SGI, test "$SNDTYPE" = "SGI")
-AM_CONDITIONAL(SNDTYPE_SUN, test "$SNDTYPE" = "SUN")
-AM_CONDITIONAL(SNDTYPE_WIN32, test "$SNDTYPE" = "WIN32")
-AM_CONDITIONAL(SNDTYPE_NULL, test "$SNDTYPE" != "ALSA_0_5" -a "$SNDTYPE" != "ALSA_0_9" -a "$SNDTYPE" != "MME" -a "$SNDTYPE" != "OSS" -a "$SNDTYPE" != "SDL" -a "$SNDTYPE" != "SGI" -a "$SNDTYPE" != "SUN" -a "$SNDTYPE" != "WIN32")
 
 dnl Tests for joystick support
 AC_MSG_CHECKING(for joystick support)
@@ -1142,6 +1153,7 @@ elif test "x$pluginpath" = xno; then
 	pluginpath="."
 fi
 AC_DEFINE_UNQUOTED(FS_PLUGINPATH, "$pluginpath")
+AC_SUBST(pluginpath)
 
 dnl CFLAGS for release and devel versions
 CFLAGS=""
@@ -1180,14 +1192,14 @@ if test "x$optimize" = xyes; then
 	AC_MSG_RESULT(yes)
 	BUILD_TYPE="$BUILD_TYPE Optimize"
 	if test "x$GCC" = xyes; then
-		CFLAGS="$CFLAGS -O6 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations"
+		CFLAGS="$CFLAGS -O3 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations"
 		AC_MSG_CHECKING(for special compiler settings)
 		case "${host_cpu}" in
 			i?86)
 				if test "x$HAVE_AMD" = "xyes"; then
-					MORE_CFLAGS="-march=k6 -malign-loops=2 -malign-jumps=2 -malign-functions=2"
+					MORE_CFLAGS="-march=k6"
 				else
-					MORE_CFLAGS="-march=${host_cpu} -malign-loops=2 -malign-jumps=2 -malign-functions=2"
+					MORE_CFLAGS="-march=${host_cpu}"
 				fi
 				;;
 			*)
@@ -1224,7 +1236,7 @@ AC_ARG_ENABLE(profile,
 if test "x$profile" = xyes; then
 	BUILD_TYPE="$BUILD_TYPE Profile"
 	if test "x$GCC" = xyes; then
-		CFLAGS="$(echo $CFLAGS | sed -e 's/-fomit-frame-pointer//g') -pg"
+		CFLAGS="`echo $CFLAGS | sed -e 's/-fomit-frame-pointer//g'` -pg"
 		LDFLAGS="$LDFLAGS -pg"
 	else
 		CFLAGS="$CFLAGS -p"
@@ -1402,6 +1414,7 @@ QW_TARGETS=""
 NQ_TARGETS=""
 CD_TARGETS=""
 SND_TARGETS=""
+SND_PLUGIN_TARGETS=""
 VID_TARGETS=""
 BUILD_GL=no
 BUILD_SW=no
@@ -1479,12 +1492,37 @@ fi
 if test -n "$VID_TARGETS"; then
 	CD_TARGETS="libQFcd.la"
 	SND_TARGETS="libQFsound.la"
+	if test "`echo $SOUND_TYPES | grep ALSA0.5`"; then
+		SND_PLUGIN_TARGETS="$SND_PLUGIN_TARGETS libsound_alsa0_5.la"
+	fi
+	if test "`echo $SOUND_TYPES | grep ALSA0.9`"; then
+		SND_PLUGIN_TARGETS="$SND_PLUGIN_TARGETS libsound_alsa0_9.la"
+	fi
+	if test "`echo $SOUND_TYPES | grep MME`"; then
+		SND_PLUGIN_TARGETS="$SND_PLUGIN_TARGETS libsound_mme.la"
+	fi
+	if test "`echo $SOUND_TYPES | grep OSS`"; then
+		SND_PLUGIN_TARGETS="$SND_PLUGIN_TARGETS libsound_oss.la"
+	fi
+	if test "`echo $SOUND_TYPES | grep SDL`"; then
+		SND_PLUGIN_TARGETS="$SND_PLUGIN_TARGETS libsound_sdl.la"
+	fi
+	if test "`echo $SOUND_TYPES | grep SGI`"; then
+		SND_PLUGIN_TARGETS="$SND_PLUGIN_TARGETS libsound_sgi.la"
+	fi
+	if test "`echo $SOUND_TYPES | grep SUN`"; then
+		SND_PLUGIN_TARGETS="$SND_PLUGIN_TARGETS libsound_sun.la"
+	fi
+	if test "`echo $SOUND_TYPES | grep Win32`"; then
+		SND_PLUGIN_TARGETS="$SND_PLUGIN_TARGETS libsound_win.la"
+	fi
 	VID_TARGETS="libQFjs.la $VID_TARGETS"
 fi
 AC_SUBST(NQ_TARGETS)
 AC_SUBST(QW_TARGETS)
 AC_SUBST(CD_TARGETS)
 AC_SUBST(SND_TARGETS)
+AC_SUBST(SND_PLUGIN_TARGETS)
 AC_SUBST(VID_TARGETS)
 
 AM_CONDITIONAL(BUILD_GL, test "$BUILD_GL" = "yes")
@@ -1540,7 +1578,7 @@ AC_MSG_RESULT([
 	Build type:$BUILD_TYPE
 	Server support: $SV_TARGETS
 	Client support:$CL_TARGETS
-	Sound system: $SNDTYPE
+	Sound support:$SOUND_TYPES
 	CD Audio system: $CDTYPE
 	IPv6 networking: $NETTYPE_IPV6
 	Compression support: $HAVE_ZLIB
@@ -1556,4 +1594,3 @@ if test -d $srcdir/CVS; then
 	echo "(This is from a development CVS tree. Expect problems)"
 	echo
 fi
-
diff --git a/include/QF/plugin/sound.h b/include/QF/plugin/sound.h
index 99b66fe31..a5fc279c0 100644
--- a/include/QF/plugin/sound.h
+++ b/include/QF/plugin/sound.h
@@ -72,6 +72,9 @@ typedef struct sound_funcs_s {
 } sound_funcs_t;
 
 typedef struct sound_data_s {
+	struct model_s ***worldmodel;
+	double *host_frametime;
+	int *viewentity;
 } sound_data_t;
 
 #endif // __QF_plugin_sound_h_
diff --git a/libs/audio/Makefile.am b/libs/audio/Makefile.am
index 0de51f366..b4d183811 100644
--- a/libs/audio/Makefile.am
+++ b/libs/audio/Makefile.am
@@ -2,3 +2,14 @@ SUBDIRS=	cd targets
 
 clean-local:
 	rm -f *.a
+
+INCLUDES= -I$(top_srcdir)/include
+
+lib_LTLIBRARIES = libQFsound.la
+
+libQFsound_la_SOURCES= snd_common.c snd.c
+libQFsound_la_LDFLAGS = -version-info 1:0:0
+libQFsound.la: $(libQFsound_la_OBJECTS) $(libQFsound_la_DEPENDENCIES)
+	$(LINK) -rpath $(libdir) $(libQFsound_la_LDFLAGS) $(libQFsound_la_OBJECTS) $(libQFsound_la_LIBADD) $(LIBS)
+
+LIBLIST = libQFsound.la @LIBRARY_SEARCH_PATH@
diff --git a/libs/audio/snd.c b/libs/audio/snd.c
new file mode 100644
index 000000000..8e99e46f2
--- /dev/null
+++ b/libs/audio/snd.c
@@ -0,0 +1,208 @@
+/*
+	snd_plugin.c
+
+	sound plugin wrapper
+
+	Copyright (C) 1996-1997  Id Software, Inc.
+	Copyright (C) 1999,2000  contributors of the QuakeForge project
+	Please see the file "AUTHORS" for a list of contributors
+
+	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$
+*/
+
+#include "QF/qtypes.h"
+#include "QF/sound.h"
+#include "QF/plugin.h"
+#include "QF/console.h"
+#include "QF/model.h"
+
+// =======================================================================
+// Various variables also defined in snd_dma.c
+// FIXME - should be put in one place
+// =======================================================================
+extern channel_t       channels[MAX_CHANNELS];
+extern int             total_channels;
+extern volatile dma_t *shm;
+extern cvar_t         *loadas8bit;
+extern int             paintedtime;				// sample PAIRS
+extern qboolean        snd_initialized;
+
+extern cvar_t         *bgmvolume;
+extern cvar_t         *volume;
+extern cvar_t         *snd_interp;
+
+cvar_t                *snd_plugin;
+plugin_t              *sndmodule = NULL;
+
+// FIXME: ewwwies
+extern double host_frametime; // From host.h
+
+extern struct model_s       **snd_worldmodel;
+extern int snd_viewentity;
+
+void
+S_Init (void)
+{
+	S_Init_Cvars ();
+	sndmodule = PI_LoadPlugin ("sound", snd_plugin->string);
+	if (!sndmodule) {
+		Con_Printf ("Loading of sound module: %s failed!\n", snd_plugin->string);
+	}
+	else {
+		sndmodule->data->sound->worldmodel = &snd_worldmodel;
+		sndmodule->data->sound->viewentity = &snd_viewentity;
+		sndmodule->data->sound->host_frametime = &host_frametime;
+		sndmodule->functions->general->p_Init ();
+	}
+}
+
+void
+S_Init_Cvars (void)
+{
+	volume = Cvar_Get ("volume", "0.7", CVAR_ARCHIVE, NULL,
+			"Volume level of sounds");
+	loadas8bit =
+		Cvar_Get ("loadas8bit", "0", CVAR_NONE, NULL, "Load samples as 8-bit");
+	bgmvolume = Cvar_Get ("bgmvolume", "1", CVAR_ARCHIVE, NULL,
+			"CD music volume");
+	snd_interp = Cvar_Get ("snd_interp", "1", CVAR_ARCHIVE, NULL,
+	                              "control sample interpolation");
+	snd_plugin = Cvar_Get ("snd_plugin", "null", CVAR_ARCHIVE, NULL,
+			"Sound Plugin to use");
+}
+
+void
+S_AmbientOff (void)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_AmbientOff ();
+}
+
+void
+S_AmbientOn (void)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_AmbientOn ();
+}
+
+void
+S_Shutdown (void)
+{
+	if (sndmodule) {
+		sndmodule->functions->general->p_Shutdown ();
+		PI_UnloadPlugin (sndmodule);
+		sndmodule = NULL;
+	}
+}
+
+void
+S_TouchSound (char *sample)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_TouchSound (sample);
+}
+
+void
+S_ClearBuffer (void)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_ClearBuffer ();
+}
+
+void
+S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_StaticSound (sfx, origin, vol, attenuation);
+}
+
+void
+S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,
+			  float attenuation)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_StartSound (entnum, entchannel, sfx, origin, fvol, attenuation);
+}
+
+void
+S_StopSound (int entnum, int entchannel)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_StopSound (entnum, entchannel);
+}
+
+sfx_t      *
+S_PrecacheSound (char *sample)
+{
+	if (sndmodule)
+		return sndmodule->functions->sound->pS_PrecacheSound (sample);
+	else
+		return NULL;
+}
+
+void
+S_ClearPrecache (void)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_ClearPrecache ();
+}
+
+void
+S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_Update (origin, v_forward, v_right, v_up);
+}
+
+void
+S_StopAllSounds (qboolean clear)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_StopAllSounds (clear);
+}
+
+void
+S_BeginPrecaching (void)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_BeginPrecaching ();
+}
+
+void
+S_EndPrecaching (void)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_EndPrecaching ();
+}
+
+void
+S_ExtraUpdate (void)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_ExtraUpdate ();
+}
+
+void
+S_LocalSound (char *s)
+{
+	if (sndmodule)
+		sndmodule->functions->sound->pS_LocalSound (s);
+}
diff --git a/libs/audio/targets/snd_common.c b/libs/audio/snd_common.c
similarity index 100%
rename from libs/audio/targets/snd_common.c
rename to libs/audio/snd_common.c
diff --git a/libs/audio/targets/Makefile.am b/libs/audio/targets/Makefile.am
index c2aedfb52..c1c39c72f 100644
--- a/libs/audio/targets/Makefile.am
+++ b/libs/audio/targets/Makefile.am
@@ -1,44 +1,59 @@
-INCLUDES= -I$(top_srcdir)/include $(SOUND_CFLAGS)
+INCLUDES= -I$(top_srcdir)/include $(ALSA_CFLAGS) $(MME_CFLAGS) $(OSS_CFLAGS) $(SGISND_CFLAGS) $(SUNSND_CFLAGS) $(WIN32SND_CFLAGS) $(SDL_CFLAGS)
 
-lib_LTLIBRARIES = @SND_TARGETS@
-EXTRA_LTLIBRARIES = libQFsound.la
+lib_LTLIBRARIES = @SND_PLUGIN_TARGETS@ libsound_null.la libsound_disk.la
+EXTRA_LTLIBRARIES = libsound_sdl.la libsound_alsa0_5.la libsound_alsa0_9.la libsound_mme.la libsound_oss.la libsound_sgi.la libsound_sun.la libsound_win.la
 
-libQFsound_la_LDFLAGS = -version-info 1:0:0 $(CD_LIBS)
+common_sound_files= snd_dma.c snd_mem.c snd_mix.c snd_mixa.S
 
-#
-# ... Audio targets
-#
-common_sound_files=	snd_common.c snd_dma.c snd_mem.c snd_mix.c snd_mixa.S
-if SNDTYPE_SDL
-libQFsound_la_SOURCES=	$(common_sound_files) snd_sdl.c
-endif
-if SNDTYPE_ALSA_0_5
-libQFsound_la_SOURCES=	$(common_sound_files) snd_alsa_0_5.c
-endif
-if SNDTYPE_ALSA_0_9
-libQFsound_la_SOURCES=	$(common_sound_files) snd_alsa_0_9.c
-endif
-# No idea what this is.  it's in configure.in though...
-#if SNDTYPE_MME
-#libQFsound_la_SOURCES=	$(common_sound_files) snd_mme.c
-#endif
-if SNDTYPE_OSS
-libQFsound_la_SOURCES=	$(common_sound_files) snd_oss.c
-endif
-if SNDTYPE_SGI
-libQFsound_la_SOURCES=	$(common_sound_files) snd_sgi.c
-endif
-if SNDTYPE_SUN
-libQFsound_la_SOURCES=	$(common_sound_files) snd_sun.c
-endif
-if SNDTYPE_WIN32
-libQFsound_la_SOURCES=	$(common_sound_files) snd_win.c
-endif
-if SNDTYPE_NULL
-libQFsound_la_SOURCES=	snd_common.c snd_null.c
-endif
-libQFsound.la: $(libQFsound_la_OBJECTS) $(libQFsound_la_DEPENDENCIES)
-	$(LINK) -rpath $(libdir) $(libQFsound_la_LDFLAGS) $(libQFsound_la_OBJECTS) $(libQFsound_la_LIBADD) $(LIBS)
+libsound_sdl_la_LDFLAGS= -version-info 1:0:0 $(SDL_LIBS)
+libsound_alsa0_5_la_LDFLAGS= -version-info 1:0:0 $(ALSA_LIBS)
+libsound_alsa0_9_la_LDFLAGS= -version-info 1:0:0 $(ALSA_LIBS)
+libsound_mme_la_LDFLAGS= -version-info 1:0:0 $(MME_LIBS)
+libsound_oss_la_LDFLAGS= -version-info 1:0:0 $(OSS_LIBS)
+libsound_sgi_la_LDFLAGS= -version-info 1:0:0 $(SGISND_LIBS)
+libsound_sun_la_LDFLAGS= -version-info 1:0:0 $(SUN_LIBS)
+libsound_win_la_LDFLAGS= -version-info 1:0:0 $(WIN_LIBS)
+libsound_disk_la_LDFLAGS= -version-info 1:0:0
+libsound_null_la_LDFLAGS= -version-info 1:0:0
 
+libsound_sdl_la_SOURCES= $(common_sound_files) snd_sdl.c
+libsound_sdl.la: $(libsound_sdl_la_OBJECTS) $(libsound_sdl_la_DEPENDENCIES)
+	$(LINK) -rpath $(pluginpath) $(libsound_sdl_la_LDFLAGS) $(libsound_sdl_la_OBJECTS) $(libsound_sdl_la_LIBADD) $(LIBS)
 
-LIBLIST = libQFsound.la @LIBRARY_SEARCH_PATH@
+libsound_alsa0_5_la_SOURCES= $(common_sound_files) snd_alsa_0_5.c
+libsound_alsa0_5.la: $(libsound_alsa0_5_la_OBJECTS) $(libsound_alsa0_5_la_DEPENDENCIES)
+	$(LINK) -rpath $(pluginpath) $(libsound_alsa0_5_la_LDFLAGS) $(libsound_ALSA_0_5_la_OBJECTS) $(libsound_alsa0_5_la_LIBADD) $(LIBS)
+
+libsound_alsa0_9_la_SOURCES= $(common_sound_files) snd_alsa_0_9.c
+libsound_alsa0_9.la: $(libsound_alsa0_9_la_OBJECTS) $(libsound_alsa0_9_la_DEPENDENCIES)
+	$(LINK) -rpath $(pluginpath) $(libsound_alsa0_9_la_LDFLAGS) $(libsound_ALSA_0_5_la_OBJECTS) $(libsound_alsa0_9_la_LIBADD) $(LIBS)
+
+libsound_mme_la_SOURCES= $(common_sound_files) snd_mme.c
+libsound_mme.la: $(libsound_mme_la_OBJECTS) $(libsound_mme_la_DEPENDENCIES)
+	$(LINK) -rpath $(pluginpath) $(libsound_mme_la_LDFLAGS) $(libsound_mme_la_OBJECTS) $(libsound_mme_la_LIBADD) $(LIBS)
+
+libsound_oss_la_SOURCES= $(common_sound_files) snd_oss.c
+libsound_oss.la: $(libsound_oss_la_OBJECTS) $(libsound_oss_la_DEPENDENCIES)
+	$(LINK) -rpath $(pluginpath) $(libsound_oss_la_LDFLAGS) $(libsound_oss_la_OBJECTS) $(libsound_oss_la_LIBADD) $(LIBS)
+
+libsound_sgi_la_SOURCES= $(common_sound_files) snd_sgi.c
+libsound_sgi.la: $(libsound_sgi_la_OBJECTS) $(libsound_sgi_la_DEPENDENCIES)
+	$(LINK) -rpath $(pluginpath) $(libsound_sgi_la_LDFLAGS) $(libsound_sgi_la_OBJECTS) $(libsound_sgi_la_LIBADD) $(LIBS)
+
+libsound_sun_la_SOURCES= $(common_sound_files) snd_sun.c
+libsound_sun.la: $(libsound_sun_la_OBJECTS) $(libsound_sun_la_DEPENDENCIES)
+	$(LINK) -rpath $(pluginpath) $(libsound_sun_la_LDFLAGS) $(libsound_sun_la_OBJECTS) $(libsound_sun_la_LIBADD) $(LIBS)
+
+libsound_win_la_SOURCES= $(common_sound_files) snd_win.c
+libsound_win.la: $(libsound_win_la_OBJECTS) $(libsound_win_la_DEPENDENCIES)
+	$(LINK) -rpath $(pluginpath) $(libsound_win_la_LDFLAGS) $(libsound_win_la_OBJECTS) $(libsound_win_la_LIBADD) $(LIBS)
+
+libsound_disk_la_SOURCES= $(common_sound_files) snd_disk.c
+libsound_disk.la: $(libsound_disk_la_OBJECTS) $(libsound_disk_la_DEPENDENCIES)
+	$(LINK) -rpath $(pluginpath) $(libsound_disk_la_LDFLAGS) $(libsound_disk_la_OBJECTS) $(libsound_disk_la_LIBADD) $(LIBS)
+
+libsound_null_la_SOURCES= snd_null.c
+libsound_null.la: $(libsound_null_la_OBJECTS) $(libsound_null_la_DEPENDENCIES)
+	$(LINK) -rpath $(pluginpath) $(libsound_null_la_LDFLAGS) $(libsound_null_la_OBJECTS) $(libsound_null_la_LIBADD) $(LIBS)
+
+LIBLIST = $(lib_LTLIBRARIES) @LIBRARY_SEARCH_PATH@
diff --git a/libs/audio/targets/snd_alsa_0_5.c b/libs/audio/targets/snd_alsa_0_5.c
index 784a1ff2d..10df487cc 100644
--- a/libs/audio/targets/snd_alsa_0_5.c
+++ b/libs/audio/targets/snd_alsa_0_5.c
@@ -57,6 +57,7 @@
 #include "QF/console.h"
 #include "QF/qargs.h"
 #include "QF/sound.h"
+#include "QF/plugin.h"
 
 #ifndef MAP_FAILED
 # define MAP_FAILED ((void*)-1)
@@ -72,6 +73,32 @@ static snd_pcm_mmap_control_t *mmap_control = NULL;
 static char *mmap_data = NULL;
 static int  card = -1, dev = -1;
 
+plugin_t           plugin_info;
+plugin_data_t      plugin_info_data;
+plugin_funcs_t     plugin_info_funcs;
+general_data_t     plugin_info_general_data;
+general_funcs_t    plugin_info_general_funcs;
+sound_data_t       plugin_info_sound_data;
+sound_funcs_t      plugin_info_sound_funcs;
+
+void I_S_Init (void);
+void I_S_Shutdown (void);
+void I_S_AmbientOff (void);
+void I_S_AmbientOn (void);
+void I_S_TouchSound (char *sample);
+void I_S_ClearBuffer (void);
+void I_S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
+void I_S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,  float attenuation);
+void I_S_StopSound (int entnum, int entchannel);
+sfx_t *I_S_PrecacheSound (char *sample);
+void I_S_ClearPrecache (void);
+void I_S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
+void I_S_StopAllSounds (qboolean clear);
+void I_S_BeginPrecaching (void);
+void I_S_EndPrecaching (void);
+void I_S_ExtraUpdate (void);
+void I_S_LocalSound (char *s);
+
 int
 check_card (int card)
 {
@@ -356,3 +383,44 @@ SNDDMA_Submit (void)
 			break;
 	}
 }
+
+plugin_t *
+PluginInfo (void) {
+	plugin_info.type = qfp_sound;
+	plugin_info.api_version = QFPLUGIN_VERSION;
+	plugin_info.plugin_version = "0.1";
+	plugin_info.description = "ALSA 0.5.x digital output";
+	plugin_info.copyright = "Copyright (C) 1996-1997 id Software, Inc.\n"
+        "Copyright (C) 1999,2000,2001  contributors of the QuakeForge project\n"        "Please see the file \"AUTHORS\" for a list of contributors";
+	plugin_info.functions = &plugin_info_funcs;
+	plugin_info.data = &plugin_info_data;
+
+	plugin_info_data.general = &plugin_info_general_data;
+	plugin_info_data.input = NULL;
+	plugin_info_data.sound = &plugin_info_sound_data;
+
+	plugin_info_funcs.general = &plugin_info_general_funcs;
+	plugin_info_funcs.input = NULL;
+	plugin_info_funcs.sound = &plugin_info_sound_funcs;
+
+	plugin_info_general_funcs.p_Init = I_S_Init;
+	plugin_info_general_funcs.p_Shutdown = I_S_Shutdown;
+
+	plugin_info_sound_funcs.pS_AmbientOff = I_S_AmbientOff;
+    plugin_info_sound_funcs.pS_AmbientOn = I_S_AmbientOn;
+    plugin_info_sound_funcs.pS_TouchSound = I_S_TouchSound;
+    plugin_info_sound_funcs.pS_ClearBuffer = I_S_ClearBuffer;
+    plugin_info_sound_funcs.pS_StaticSound = I_S_StaticSound;
+    plugin_info_sound_funcs.pS_StartSound = I_S_StartSound;
+    plugin_info_sound_funcs.pS_StopSound = I_S_StopSound;
+    plugin_info_sound_funcs.pS_PrecacheSound = I_S_PrecacheSound;
+    plugin_info_sound_funcs.pS_ClearPrecache = I_S_ClearPrecache;
+    plugin_info_sound_funcs.pS_Update = I_S_Update;
+    plugin_info_sound_funcs.pS_StopAllSounds = I_S_StopAllSounds;
+    plugin_info_sound_funcs.pS_BeginPrecaching = I_S_BeginPrecaching;
+    plugin_info_sound_funcs.pS_EndPrecaching = I_S_EndPrecaching;
+    plugin_info_sound_funcs.pS_ExtraUpdate = I_S_ExtraUpdate;
+    plugin_info_sound_funcs.pS_LocalSound = I_S_LocalSound;
+
+	return &plugin_info;
+}
diff --git a/libs/audio/targets/snd_alsa_0_9.c b/libs/audio/targets/snd_alsa_0_9.c
index 0eee0e35d..d3121265f 100644
--- a/libs/audio/targets/snd_alsa_0_9.c
+++ b/libs/audio/targets/snd_alsa_0_9.c
@@ -39,6 +39,7 @@
 #include "QF/sound.h"
 #include "QF/qargs.h"
 #include "QF/console.h"
+#include "QF/plugin.h"
 
 static int  snd_inited;
 
@@ -47,6 +48,32 @@ static snd_pcm_t *pcm;
 static char *pcmname = NULL;
 size_t      buffer_size;
 
+plugin_t           plugin_info;
+plugin_data_t      plugin_info_data;
+plugin_funcs_t     plugin_info_funcs;
+general_data_t     plugin_info_general_data;
+general_funcs_t    plugin_info_general_funcs;
+sound_data_t       plugin_info_sound_data;
+sound_funcs_t      plugin_info_sound_funcs;
+
+void I_S_Init (void);
+void I_S_Shutdown (void);
+void I_S_AmbientOff (void);
+void I_S_AmbientOn (void);
+void I_S_TouchSound (char *sample);
+void I_S_ClearBuffer (void);
+void I_S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
+void I_S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,  float attenuation);
+void I_S_StopSound (int entnum, int entchannel);
+sfx_t *I_S_PrecacheSound (char *sample);
+void I_S_ClearPrecache (void);
+void I_S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
+void I_S_StopAllSounds (qboolean clear);
+void I_S_BeginPrecaching (void);
+void I_S_EndPrecaching (void);
+void I_S_ExtraUpdate (void);
+void I_S_LocalSound (char *s);
+
 qboolean
 SNDDMA_Init (void)
 {
@@ -283,3 +310,43 @@ SNDDMA_Submit (void)
 			break;
 	}
 }
+plugin_t *
+PluginInfo (void) {
+    plugin_info.type = qfp_sound;
+    plugin_info.api_version = QFPLUGIN_VERSION;
+    plugin_info.plugin_version = "0.1";
+    plugin_info.description = "ALSA 0.9.x digital output";
+    plugin_info.copyright = "Copyright (C) 1996-1997 id Software, Inc.\n"
+        "Copyright (C) 1999,2000,2001  contributors of the QuakeForge project\n"        "Please see the file \"AUTHORS\" for a list of contributors";
+    plugin_info.functions = &plugin_info_funcs;
+    plugin_info.data = &plugin_info_data;
+
+    plugin_info_data.general = &plugin_info_general_data;
+    plugin_info_data.input = NULL;
+    plugin_info_data.sound = &plugin_info_sound_data;
+
+    plugin_info_funcs.general = &plugin_info_general_funcs;
+    plugin_info_funcs.input = NULL;
+    plugin_info_funcs.sound = &plugin_info_sound_funcs;
+
+    plugin_info_general_funcs.p_Init = I_S_Init;
+    plugin_info_general_funcs.p_Shutdown = I_S_Shutdown;
+
+    plugin_info_sound_funcs.pS_AmbientOff = I_S_AmbientOff;
+    plugin_info_sound_funcs.pS_AmbientOn = I_S_AmbientOn;
+    plugin_info_sound_funcs.pS_TouchSound = I_S_TouchSound;
+    plugin_info_sound_funcs.pS_ClearBuffer = I_S_ClearBuffer;
+    plugin_info_sound_funcs.pS_StaticSound = I_S_StaticSound;
+    plugin_info_sound_funcs.pS_StartSound = I_S_StartSound;
+    plugin_info_sound_funcs.pS_StopSound = I_S_StopSound;
+    plugin_info_sound_funcs.pS_PrecacheSound = I_S_PrecacheSound;
+    plugin_info_sound_funcs.pS_ClearPrecache = I_S_ClearPrecache;
+    plugin_info_sound_funcs.pS_Update = I_S_Update;
+    plugin_info_sound_funcs.pS_StopAllSounds = I_S_StopAllSounds;
+    plugin_info_sound_funcs.pS_BeginPrecaching = I_S_BeginPrecaching;
+    plugin_info_sound_funcs.pS_EndPrecaching = I_S_EndPrecaching;
+    plugin_info_sound_funcs.pS_ExtraUpdate = I_S_ExtraUpdate;
+    plugin_info_sound_funcs.pS_LocalSound = I_S_LocalSound;
+
+    return &plugin_info;
+}
diff --git a/libs/audio/targets/snd_disk.c b/libs/audio/targets/snd_disk.c
index 68e2c7169..dc4efcb0d 100644
--- a/libs/audio/targets/snd_disk.c
+++ b/libs/audio/targets/snd_disk.c
@@ -42,10 +42,37 @@
 #include "QF/console.h"
 #include "QF/sound.h"
 #include "QF/qargs.h"
+#include "QF/plugin.h"
 
 static int  snd_inited;
 QFile      *snd_file;
 
+plugin_t           plugin_info;
+plugin_data_t      plugin_info_data;
+plugin_funcs_t     plugin_info_funcs;
+general_data_t     plugin_info_general_data;
+general_funcs_t    plugin_info_general_funcs;
+sound_data_t       plugin_info_sound_data;
+sound_funcs_t      plugin_info_sound_funcs;
+
+void I_S_Init (void);
+void I_S_Shutdown (void);
+void I_S_AmbientOff (void);
+void I_S_AmbientOn (void);
+void I_S_TouchSound (char *sample);
+void I_S_ClearBuffer (void);
+void I_S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
+void I_S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,  float attenuation);
+void I_S_StopSound (int entnum, int entchannel);
+sfx_t *I_S_PrecacheSound (char *sample);
+void I_S_ClearPrecache (void);
+void I_S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
+void I_S_StopAllSounds (qboolean clear);
+void I_S_BeginPrecaching (void);
+void I_S_EndPrecaching (void);
+void I_S_ExtraUpdate (void);
+void I_S_LocalSound (char *s);
+
 qboolean
 SNDDMA_Init (void)
 {
@@ -106,3 +133,44 @@ SNDDMA_Submit (void)
 
 	Qwrite (snd_file, shm->buffer, count);
 }
+
+plugin_t *
+PluginInfo (void) {
+    plugin_info.type = qfp_sound;
+    plugin_info.api_version = QFPLUGIN_VERSION;
+    plugin_info.plugin_version = "0.1";
+    plugin_info.description = "disk output";
+    plugin_info.copyright = "Copyright (C) 1996-1997 id Software, Inc.\n"
+        "Copyright (C) 1999,2000,2001  contributors of the QuakeForge project\n"        "Please see the file \"AUTHORS\" for a list of contributors";
+    plugin_info.functions = &plugin_info_funcs;
+    plugin_info.data = &plugin_info_data;
+
+    plugin_info_data.general = &plugin_info_general_data;
+    plugin_info_data.input = NULL;
+    plugin_info_data.sound = &plugin_info_sound_data;
+
+    plugin_info_funcs.general = &plugin_info_general_funcs;
+    plugin_info_funcs.input = NULL;
+    plugin_info_funcs.sound = &plugin_info_sound_funcs;
+
+    plugin_info_general_funcs.p_Init = I_S_Init;
+    plugin_info_general_funcs.p_Shutdown = I_S_Shutdown;
+
+    plugin_info_sound_funcs.pS_AmbientOff = I_S_AmbientOff;
+    plugin_info_sound_funcs.pS_AmbientOn = I_S_AmbientOn;
+    plugin_info_sound_funcs.pS_TouchSound = I_S_TouchSound;
+    plugin_info_sound_funcs.pS_ClearBuffer = I_S_ClearBuffer;
+    plugin_info_sound_funcs.pS_StaticSound = I_S_StaticSound;
+    plugin_info_sound_funcs.pS_StartSound = I_S_StartSound;
+    plugin_info_sound_funcs.pS_StopSound = I_S_StopSound;
+    plugin_info_sound_funcs.pS_PrecacheSound = I_S_PrecacheSound;
+    plugin_info_sound_funcs.pS_ClearPrecache = I_S_ClearPrecache;
+    plugin_info_sound_funcs.pS_Update = I_S_Update;
+    plugin_info_sound_funcs.pS_StopAllSounds = I_S_StopAllSounds;
+    plugin_info_sound_funcs.pS_BeginPrecaching = I_S_BeginPrecaching;
+    plugin_info_sound_funcs.pS_EndPrecaching = I_S_EndPrecaching;
+    plugin_info_sound_funcs.pS_ExtraUpdate = I_S_ExtraUpdate;
+    plugin_info_sound_funcs.pS_LocalSound = I_S_LocalSound;
+
+    return &plugin_info;
+}
diff --git a/libs/audio/targets/snd_dma.c b/libs/audio/targets/snd_dma.c
index cd77d167b..48a952965 100644
--- a/libs/audio/targets/snd_dma.c
+++ b/libs/audio/targets/snd_dma.c
@@ -48,13 +48,21 @@
 #include "QF/qargs.h"
 #include "QF/sys.h"
 #include "QF/sound.h"
+#include "QF/plugin.h"
 
-void        S_Play (void);
-void        S_PlayVol (void);
-void        S_SoundList (void);
-void        S_Update_ (void);
-void        S_StopAllSounds (qboolean clear);
-void        S_StopAllSoundsC (void);
+void        I_S_Play (void);
+void        I_S_PlayVol (void);
+void        I_S_SoundList (void);
+void        I_S_Update_ (void);
+void        I_S_StopAllSounds (qboolean clear);
+void        I_S_StopAllSoundsC (void);
+
+sfx_t		*I_S_PrecacheSound (char *name);
+sfxcache_t	*I_S_LoadSound (sfx_t *s);
+void		I_S_ClearBuffer (void);
+void		I_S_PaintChannels (int endtime);
+
+void		I_S_Init_Cvars ();
 
 // QuakeWorld hack...
 //#define	viewentity	playernum+1
@@ -65,7 +73,7 @@ void        S_StopAllSoundsC (void);
 
 extern channel_t   channels[MAX_CHANNELS];
 extern int         total_channels;
-extern double host_frametime; // From host.h
+//extern double host_frametime; // From host.h
 
 int         snd_blocked = 0;
 static qboolean snd_ambient = 1;
@@ -125,7 +133,7 @@ cvar_t     *_snd_mixahead;
 //
 // Fake dma is a synchronous faking of the DMA progress used for
 // isolating performance in the renderer.  The fakedma_updates is
-// number of times S_Update() is called per second.
+// number of times I_S_Update() is called per second.
 //
 
 qboolean    fakedma = false;
@@ -133,25 +141,24 @@ int         fakedma_updates = 15;
 
 // FIXME: Evil hack that doesn't deserve to see the light of day.
 // (pending merge of nq and qw client_stat_t's)
-extern int snd_viewentity;
-extern struct model_s **snd_worldmodel;
+extern sound_data_t plugin_info_sound_data;
 
 void
-S_AmbientOff (void)
+I_S_AmbientOff (void)
 {
 	snd_ambient = false;
 }
 
 
 void
-S_AmbientOn (void)
+I_S_AmbientOn (void)
 {
 	snd_ambient = true;
 }
 
 
 void
-S_SoundInfo_f (void)
+I_S_SoundInfo_f (void)
 {
 	if (!sound_started || !shm) {
 		Con_Printf ("sound system not started\n");
@@ -170,11 +177,11 @@ S_SoundInfo_f (void)
 
 
 /*
-	S_Startup
+	I_S_Startup
 */
 
 void
-S_Startup (void)
+I_S_Startup (void)
 {
 	int         rc;
 
@@ -198,25 +205,27 @@ S_Startup (void)
 
 
 /*
-	S_Init
+	I_S_Init
 */
 void
-S_Init (void)
+I_S_Init (void)
 {
 
 	Con_Printf ("\nSound Initialization\n");
 
-	Cmd_AddCommand ("play", S_Play,
+	Cmd_AddCommand ("play", I_S_Play,
 					"Play selected sound effect (play pathto/sound.wav)");
-	Cmd_AddCommand ("playvol", S_PlayVol,
+	Cmd_AddCommand ("playvol", I_S_PlayVol,
 					"Play selected sound effect at selected volume (playvol pathto/sound.wav num");
-	Cmd_AddCommand ("stopsound", S_StopAllSoundsC,
+	Cmd_AddCommand ("stopsound", I_S_StopAllSoundsC,
 					"Stops all sounds currently being played");
-	Cmd_AddCommand ("soundlist", S_SoundList,
+	Cmd_AddCommand ("soundlist", I_S_SoundList,
 					"Reports a list of sounds in the cache");
-	Cmd_AddCommand ("soundinfo", S_SoundInfo_f,
+	Cmd_AddCommand ("soundinfo", I_S_SoundInfo_f,
 					"Report information on the sound system");
 
+	I_S_Init_Cvars ();
+
 	if (COM_CheckParm ("-nosound"))
 		return;
 
@@ -232,7 +241,7 @@ S_Init (void)
 
 	snd_initialized = true;
 
-	S_Startup ();
+	I_S_Startup ();
 
 	if (sound_started == 0)				// sound startup failed? Bail out.
 		return;
@@ -265,14 +274,14 @@ S_Init (void)
 //  if (shm->buffer)
 //      shm->buffer[4] = shm->buffer[5] = 0x7f; // force a pop for debugging
 
-	ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
-	ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav");
+	ambient_sfx[AMBIENT_WATER] = I_S_PrecacheSound ("ambience/water1.wav");
+	ambient_sfx[AMBIENT_SKY] = I_S_PrecacheSound ("ambience/wind2.wav");
 
-	S_StopAllSounds (true);
+	I_S_StopAllSounds (true);
 }
 
 void
-S_Init_Cvars (void)
+I_S_Init_Cvars (void)
 {
 	snd_device = Cvar_Get ("snd_device", "", CVAR_ROM, NULL,
 						   "sound device. \"\" is system default");
@@ -330,7 +339,7 @@ S_Init_Cvars (void)
 // =======================================================================
 
 void
-S_Shutdown (void)
+I_S_Shutdown (void)
 {
 
 	if (!sound_started)
@@ -353,10 +362,10 @@ S_Shutdown (void)
 // =======================================================================
 
 /*
-	S_FindName
+	I_S_FindName
 */
 sfx_t      *
-S_FindName (char *name)
+I_S_FindName (char *name)
 {
 	int         i;
 	sfx_t      *sfx;
@@ -386,36 +395,36 @@ S_FindName (char *name)
 
 
 /*
-	S_TouchSound
+	I_S_TouchSound
 */
 void
-S_TouchSound (char *name)
+I_S_TouchSound (char *name)
 {
 	sfx_t      *sfx;
 
 	if (!sound_started)
 		return;
 
-	sfx = S_FindName (name);
+	sfx = I_S_FindName (name);
 	Cache_Check (&sfx->cache);
 }
 
 /*
-	S_PrecacheSound
+	I_S_PrecacheSound
 */
 sfx_t      *
-S_PrecacheSound (char *name)
+I_S_PrecacheSound (char *name)
 {
 	sfx_t      *sfx;
 
 	if (!sound_started || nosound->int_val)
 		return NULL;
 
-	sfx = S_FindName (name);
+	sfx = I_S_FindName (name);
 
 // cache it in
 	if (precache->int_val)
-		S_LoadSound (sfx);
+		I_S_LoadSound (sfx);
 
 	return sfx;
 }
@@ -446,7 +455,7 @@ SND_PickChannel (int entnum, int entchannel)
 			break;
 		}
 		// don't let monster sounds override player sounds
-		if (channels[ch_idx].entnum == snd_viewentity && entnum != snd_viewentity
+		if (channels[ch_idx].entnum == *plugin_info_sound_data.viewentity && entnum != *plugin_info_sound_data.viewentity
 			&& channels[ch_idx].sfx)
 			continue;
 
@@ -479,7 +488,7 @@ SND_Spatialize (channel_t *ch)
 	sfx_t      *snd;
 
 // anything coming from the view entity will always be full volume
-	if (ch->entnum == snd_viewentity) {
+	if (ch->entnum == *plugin_info_sound_data.viewentity) {
 		ch->leftvol = ch->master_vol;
 		ch->rightvol = ch->master_vol;
 		ch->phase = 0;
@@ -524,7 +533,7 @@ SND_Spatialize (channel_t *ch)
 // =======================================================================
 
 void
-S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,
+I_S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,
 			  float attenuation)
 {
 	channel_t  *target_chan, *check;
@@ -562,7 +571,7 @@ S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,
 		return;							// not audible at all
 
 // new channel
-	sc = S_LoadSound (sfx);
+	sc = I_S_LoadSound (sfx);
 	if (!sc) {
 		target_chan->sfx = NULL;
 		return;							// couldn't load the sound's data
@@ -592,7 +601,7 @@ S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,
 }
 
 void
-S_StopSound (int entnum, int entchannel)
+I_S_StopSound (int entnum, int entchannel)
 {
 	int         i;
 
@@ -607,7 +616,7 @@ S_StopSound (int entnum, int entchannel)
 }
 
 void
-S_StopAllSounds (qboolean clear)
+I_S_StopAllSounds (qboolean clear)
 {
 	int         i;
 
@@ -623,17 +632,17 @@ S_StopAllSounds (qboolean clear)
 	memset (channels, 0, MAX_CHANNELS * sizeof (channel_t));
 
 	if (clear)
-		S_ClearBuffer ();
+		I_S_ClearBuffer ();
 }
 
 void
-S_StopAllSoundsC (void)
+I_S_StopAllSoundsC (void)
 {
-	S_StopAllSounds (true);
+	I_S_StopAllSounds (true);
 }
 
 void
-S_ClearBuffer (void)
+I_S_ClearBuffer (void)
 {
 	int         clear;
 
@@ -661,10 +670,10 @@ S_ClearBuffer (void)
 
 
 /*
-	S_StaticSound
+	I_S_StaticSound
 */
 void
-S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
+I_S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
 {
 	channel_t  *ss;
 	sfxcache_t *sc;
@@ -680,7 +689,7 @@ S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
 	ss = &channels[total_channels];
 	total_channels++;
 
-	sc = S_LoadSound (sfx);
+	sc = I_S_LoadSound (sfx);
 	if (!sc)
 		return;
 
@@ -703,10 +712,10 @@ S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
 //=============================================================================
 
 /*
-	S_UpdateAmbientSounds
+	I_S_UpdateAmbientSounds
 */
 void
-S_UpdateAmbientSounds (void)
+I_S_UpdateAmbientSounds (void)
 {
 	mleaf_t    *l;
 	float       vol;
@@ -717,10 +726,10 @@ S_UpdateAmbientSounds (void)
 		return;
 
 // calc ambient sound levels
-	if (!*snd_worldmodel)
+	if (!**plugin_info_sound_data.worldmodel) // FIXME: eww
 		return;
 
-	l = Mod_PointInLeaf (listener_origin, *snd_worldmodel);
+	l = Mod_PointInLeaf (listener_origin, **plugin_info_sound_data.worldmodel);
 	if (!l || !ambient_level->value) {
 		for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
 			 ambient_channel++)
@@ -738,11 +747,11 @@ S_UpdateAmbientSounds (void)
 
 		// don't adjust volume too fast
 		if (chan->master_vol < vol) {
-			chan->master_vol += host_frametime * ambient_fade->value;
+			chan->master_vol += *plugin_info_sound_data.host_frametime * ambient_fade->value;
 			if (chan->master_vol > vol)
 				chan->master_vol = vol;
 		} else if (chan->master_vol > vol) {
-			chan->master_vol -= host_frametime * ambient_fade->value;
+			chan->master_vol -= *plugin_info_sound_data.host_frametime * ambient_fade->value;
 			if (chan->master_vol < vol)
 				chan->master_vol = vol;
 		}
@@ -753,12 +762,12 @@ S_UpdateAmbientSounds (void)
 
 
 /*
-	S_Update
+	I_S_Update
 
 	Called once each time through the main loop
 */
 void
-S_Update (vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
+I_S_Update (vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
 {
 	int         i, j;
 	int         total;
@@ -774,7 +783,7 @@ S_Update (vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
 	VectorCopy (up, listener_up);
 
 // update general area ambient sound sources
-	S_UpdateAmbientSounds ();
+	I_S_UpdateAmbientSounds ();
 
 	combine = NULL;
 
@@ -837,7 +846,7 @@ S_Update (vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
 		Con_Printf ("----(%i)----\n", total);
 	}
 // mix some sound
-	S_Update_ ();
+	I_S_Update_ ();
 }
 
 void
@@ -851,7 +860,7 @@ GetSoundtime (void)
 	fullsamples = shm->samples / shm->channels;
 
 // it is possible to miscount buffers if it has wrapped twice between
-// calls to S_Update.  Oh well.
+// calls to I_S_Update.  Oh well.
 	samplepos = SNDDMA_GetDMAPos ();
 
 	if (samplepos < oldsamplepos) {
@@ -861,7 +870,7 @@ GetSoundtime (void)
 			// 32 bit limits
 			buffers = 0;
 			paintedtime = fullsamples;
-			S_StopAllSounds (true);
+			I_S_StopAllSounds (true);
 		}
 	}
 	oldsamplepos = samplepos;
@@ -870,17 +879,17 @@ GetSoundtime (void)
 }
 
 void
-S_ExtraUpdate (void)
+I_S_ExtraUpdate (void)
 {
 	if (snd_noextraupdate->int_val)
 		return;							// don't pollute timings
-	S_Update_ ();
+	I_S_Update_ ();
 }
 
 
 
 void
-S_Update_ (void)
+I_S_Update_ (void)
 {
 	unsigned int endtime;
 	int         samps;
@@ -907,7 +916,7 @@ S_Update_ (void)
 		DSOUND_Restore ();
 #endif
 
-	S_PaintChannels (endtime);
+	I_S_PaintChannels (endtime);
 
 	SNDDMA_Submit ();
 }
@@ -917,7 +926,7 @@ S_Update_ (void)
 */
 
 void
-S_Play (void)
+I_S_Play (void)
 {
 	static int  hash = 345;
 	int         i;
@@ -931,14 +940,14 @@ S_Play (void)
 			strncat (name, ".wav", sizeof (name) - strlen (name));
 		} else
 			strcpy (name, Cmd_Argv (i));
-		sfx = S_PrecacheSound (name);
-		S_StartSound (hash++, 0, sfx, listener_origin, 1.0, 1.0);
+		sfx = I_S_PrecacheSound (name);
+		I_S_StartSound (hash++, 0, sfx, listener_origin, 1.0, 1.0);
 		i++;
 	}
 }
 
 void
-S_PlayVol (void)
+I_S_PlayVol (void)
 {
 	static int  hash = 543;
 	int         i;
@@ -953,15 +962,15 @@ S_PlayVol (void)
 			strncat (name, ".wav", sizeof (name) - strlen (name));
 		} else
 			strcpy (name, Cmd_Argv (i));
-		sfx = S_PrecacheSound (name);
+		sfx = I_S_PrecacheSound (name);
 		vol = atof (Cmd_Argv (i + 1));
-		S_StartSound (hash++, 0, sfx, listener_origin, vol, 1.0);
+		I_S_StartSound (hash++, 0, sfx, listener_origin, vol, 1.0);
 		i += 2;
 	}
 }
 
 void
-S_SoundList (void)
+I_S_SoundList (void)
 {
 	int         i;
 	sfx_t      *sfx;
@@ -986,7 +995,7 @@ S_SoundList (void)
 
 
 void
-S_LocalSound (char *sound)
+I_S_LocalSound (char *sound)
 {
 	sfx_t      *sfx;
 
@@ -995,28 +1004,28 @@ S_LocalSound (char *sound)
 	if (!sound_started)
 		return;
 
-	sfx = S_PrecacheSound (sound);
+	sfx = I_S_PrecacheSound (sound);
 	if (!sfx) {
 		Con_Printf ("S_LocalSound: can't cache %s\n", sound);
 		return;
 	}
-	S_StartSound (snd_viewentity, -1, sfx, vec3_origin, 1, 1);
+	I_S_StartSound (*plugin_info_sound_data.viewentity, -1, sfx, vec3_origin, 1, 1);
 }
 
 
 void
-S_ClearPrecache (void)
+I_S_ClearPrecache (void)
 {
 }
 
 
 void
-S_BeginPrecaching (void)
+I_S_BeginPrecaching (void)
 {
 }
 
 
 void
-S_EndPrecaching (void)
+I_S_EndPrecaching (void)
 {
 }
diff --git a/libs/audio/targets/snd_mem.c b/libs/audio/targets/snd_mem.c
index ccbc32d2d..081fdae86 100644
--- a/libs/audio/targets/snd_mem.c
+++ b/libs/audio/targets/snd_mem.c
@@ -44,7 +44,7 @@
 
 int         cache_full_cycle;
 
-byte       *S_Alloc (int size);
+byte       *I_S_Alloc (int size);
 
 /*
 	ResampleSfx
@@ -163,10 +163,10 @@ ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte * data)
 //=============================================================================
 
 /*
-	S_LoadSound
+	I_S_LoadSound
 */
 sfxcache_t *
-S_LoadSound (sfx_t *s)
+I_S_LoadSound (sfx_t *s)
 {
 	char        namebuffer[256];
 	byte       *data;
diff --git a/libs/audio/targets/snd_mix.c b/libs/audio/targets/snd_mix.c
index 654dbae0a..0771070f2 100644
--- a/libs/audio/targets/snd_mix.c
+++ b/libs/audio/targets/snd_mix.c
@@ -56,6 +56,7 @@ int        *snd_p, snd_linear_count, snd_vol;
 short      *snd_out;
 
 void        Snd_WriteLinearBlastStereo16 (void);
+sfxcache_t *I_S_LoadSound (sfx_t *s);
 
 #ifndef USE_INTEL_ASM
 void
@@ -85,7 +86,7 @@ Snd_WriteLinearBlastStereo16 (void)
 #endif
 
 void
-S_TransferStereo16 (int endtime)
+I_S_TransferStereo16 (int endtime)
 {
 	int         lpos;
 	int         lpaintedtime;
@@ -135,7 +136,7 @@ S_TransferStereo16 (int endtime)
 }
 
 void
-S_TransferPaintBuffer (int endtime)
+I_S_TransferPaintBuffer (int endtime)
 {
 	int         out_idx;
 	int         count;
@@ -147,7 +148,7 @@ S_TransferPaintBuffer (int endtime)
 	DWORD      *pbuf;
 
 	if (shm->samplebits == 16 && shm->channels == 2) {
-		S_TransferStereo16 (endtime);
+		I_S_TransferStereo16 (endtime);
 		return;
 	}
 
@@ -213,7 +214,7 @@ void        SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime);
 void        SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime);
 
 void
-S_PaintChannels (int endtime)
+I_S_PaintChannels (int endtime)
 {
 	int         i;
 	int         end;
@@ -239,7 +240,7 @@ S_PaintChannels (int endtime)
 				continue;
 			if (!ch->leftvol && !ch->rightvol)
 				continue;
-			sc = S_LoadSound (ch->sfx);
+			sc = I_S_LoadSound (ch->sfx);
 			if (!sc)
 				continue;
 
@@ -274,7 +275,7 @@ S_PaintChannels (int endtime)
 		}
 
 		// transfer out according to DMA format
-		S_TransferPaintBuffer (end);
+		I_S_TransferPaintBuffer (end);
 
 		memmove (paintbuffer, paintbuffer + end - paintedtime,
 				 max_overpaint * sizeof (paintbuffer[0]));
diff --git a/libs/audio/targets/snd_null.c b/libs/audio/targets/snd_null.c
index 179e6ea83..a32a9dbc0 100644
--- a/libs/audio/targets/snd_null.c
+++ b/libs/audio/targets/snd_null.c
@@ -31,6 +31,7 @@
 
 #include "QF/qtypes.h"
 #include "QF/sound.h"
+#include "QF/plugin.h"
 
 // =======================================================================
 // Various variables also defined in snd_dma.c
@@ -47,15 +48,42 @@ extern cvar_t         *bgmvolume;
 extern cvar_t         *volume;
 extern cvar_t         *snd_interp;
 
+plugin_t           plugin_info;
+plugin_data_t      plugin_info_data;
+plugin_funcs_t     plugin_info_funcs;
+general_data_t     plugin_info_general_data;
+general_funcs_t    plugin_info_general_funcs;
+sound_data_t       plugin_info_sound_data;
+sound_funcs_t      plugin_info_sound_funcs;
+
+void I_S_Init (void);
+void I_S_Shutdown (void);
+void I_S_AmbientOff (void);
+void I_S_AmbientOn (void);
+void I_S_TouchSound (char *sample);
+void I_S_ClearBuffer (void);
+void I_S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
+void I_S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,  float attenuation);
+void I_S_StopSound (int entnum, int entchannel);
+sfx_t *I_S_PrecacheSound (char *sample);
+void I_S_ClearPrecache (void);
+void I_S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
+void I_S_StopAllSounds (qboolean clear);
+void I_S_BeginPrecaching (void);
+void I_S_EndPrecaching (void);
+void I_S_ExtraUpdate (void);
+void I_S_LocalSound (char *s);
+
+void I_S_Init_Cvars (void);
 
 void
-S_Init (void)
+I_S_Init (void)
 {
-	S_Init_Cvars ();
+	I_S_Init_Cvars ();
 }
 
 void
-S_Init_Cvars (void)
+I_S_Init_Cvars (void)
 {
 	volume = Cvar_Get ("volume", "0.7", CVAR_ARCHIVE, NULL,
 			"Volume level of sounds");
@@ -68,83 +96,125 @@ S_Init_Cvars (void)
 }
 
 void
-S_AmbientOff (void)
+I_S_AmbientOff (void)
 {
 }
 
 void
-S_AmbientOn (void)
+I_S_AmbientOn (void)
 {
 }
 
 void
-S_Shutdown (void)
+I_S_Shutdown (void)
 {
 }
 
 void
-S_TouchSound (char *sample)
+I_S_TouchSound (char *sample)
 {
 }
 
 void
-S_ClearBuffer (void)
+I_S_ClearBuffer (void)
 {
 }
 
 void
-S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
+I_S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
 {
 }
 
 void
-S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,
+I_S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,
 			  float attenuation)
 {
 }
 
 void
-S_StopSound (int entnum, int entchannel)
+I_S_StopSound (int entnum, int entchannel)
 {
 }
 
 sfx_t      *
-S_PrecacheSound (char *sample)
+I_S_PrecacheSound (char *sample)
 {
 	return NULL;
 }
 
 void
-S_ClearPrecache (void)
+I_S_ClearPrecache (void)
 {
 }
 
 void
-S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up)
+I_S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up)
 {
 }
 
 void
-S_StopAllSounds (qboolean clear)
+I_S_StopAllSounds (qboolean clear)
 {
 }
 
 void
-S_BeginPrecaching (void)
+I_S_BeginPrecaching (void)
 {
 }
 
 void
-S_EndPrecaching (void)
+I_S_EndPrecaching (void)
 {
 }
 
 void
-S_ExtraUpdate (void)
+I_S_ExtraUpdate (void)
 {
 }
 
 void
-S_LocalSound (char *s)
+I_S_LocalSound (char *s)
 {
 }
+
+plugin_t *
+PluginInfo (void) {
+    plugin_info.type = qfp_sound;
+    plugin_info.api_version = QFPLUGIN_VERSION;
+    plugin_info.plugin_version = "0.1";
+    plugin_info.description = "ALSA 0.5.x digital output";
+    plugin_info.copyright = "Copyright (C) 1996-1997 id Software, Inc.\n"
+		"Copyright (C) 1999,2000,2001  contributors of the QuakeForge project\n"
+		"Please see the file \"AUTHORS\" for a list of contributors";
+    plugin_info.functions = &plugin_info_funcs;
+    plugin_info.data = &plugin_info_data;
+
+    plugin_info_data.general = &plugin_info_general_data;
+    plugin_info_data.input = NULL;
+    plugin_info_data.sound = &plugin_info_sound_data;
+
+    plugin_info_funcs.general = &plugin_info_general_funcs;
+    plugin_info_funcs.input = NULL;
+    plugin_info_funcs.sound = &plugin_info_sound_funcs;
+
+    plugin_info_general_funcs.p_Init = I_S_Init;
+    plugin_info_general_funcs.p_Shutdown = I_S_Shutdown;
+
+    plugin_info_sound_funcs.pS_AmbientOff = I_S_AmbientOff;
+    plugin_info_sound_funcs.pS_AmbientOn = I_S_AmbientOn;
+    plugin_info_sound_funcs.pS_TouchSound = I_S_TouchSound;
+    plugin_info_sound_funcs.pS_ClearBuffer = I_S_ClearBuffer;
+    plugin_info_sound_funcs.pS_StaticSound = I_S_StaticSound;
+    plugin_info_sound_funcs.pS_StartSound = I_S_StartSound;
+    plugin_info_sound_funcs.pS_StopSound = I_S_StopSound;
+    plugin_info_sound_funcs.pS_PrecacheSound = I_S_PrecacheSound;
+    plugin_info_sound_funcs.pS_ClearPrecache = I_S_ClearPrecache;
+    plugin_info_sound_funcs.pS_Update = I_S_Update;
+    plugin_info_sound_funcs.pS_StopAllSounds = I_S_StopAllSounds;
+    plugin_info_sound_funcs.pS_BeginPrecaching = I_S_BeginPrecaching;
+    plugin_info_sound_funcs.pS_EndPrecaching = I_S_EndPrecaching;
+    plugin_info_sound_funcs.pS_ExtraUpdate = I_S_ExtraUpdate;
+    plugin_info_sound_funcs.pS_LocalSound = I_S_LocalSound;
+
+    return &plugin_info;
+}
diff --git a/libs/audio/targets/snd_oss.c b/libs/audio/targets/snd_oss.c
index 09581c380..ff401a20d 100644
--- a/libs/audio/targets/snd_oss.c
+++ b/libs/audio/targets/snd_oss.c
@@ -59,6 +59,7 @@
 #include "QF/console.h"
 #include "QF/qargs.h"
 #include "QF/sound.h"
+#include "QF/plugin.h"
 
 #ifndef MAP_FAILED
 # define MAP_FAILED ((void *) -1)
@@ -70,6 +71,32 @@ static char       *snd_dev = "/dev/dsp";
 
 static int  tryrates[] = { 11025, 22050, 22051, 44100, 8000 };
 
+plugin_t           plugin_info;
+plugin_data_t      plugin_info_data;
+plugin_funcs_t     plugin_info_funcs;
+general_data_t     plugin_info_general_data;
+general_funcs_t    plugin_info_general_funcs;
+sound_data_t       plugin_info_sound_data;
+sound_funcs_t      plugin_info_sound_funcs;
+
+void I_S_Init (void);
+void I_S_Shutdown (void);
+void I_S_AmbientOff (void);
+void I_S_AmbientOn (void);
+void I_S_TouchSound (char *sample);
+void I_S_ClearBuffer (void);
+void I_S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
+void I_S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,  float attenuation);
+void I_S_StopSound (int entnum, int entchannel);
+sfx_t *I_S_PrecacheSound (char *sample);
+void I_S_ClearPrecache (void);
+void I_S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
+void I_S_StopAllSounds (qboolean clear);
+void I_S_BeginPrecaching (void);
+void I_S_EndPrecaching (void);
+void I_S_ExtraUpdate (void);
+void I_S_LocalSound (char *s);
+
 qboolean
 SNDDMA_Init (void)
 {
@@ -299,3 +326,43 @@ void
 SNDDMA_Submit (void)
 {
 }
+plugin_t *
+PluginInfo (void) {
+    plugin_info.type = qfp_sound;
+    plugin_info.api_version = QFPLUGIN_VERSION;
+    plugin_info.plugin_version = "0.1";
+    plugin_info.description = "OSS digital output";
+    plugin_info.copyright = "Copyright (C) 1996-1997 id Software, Inc.\n"
+        "Copyright (C) 1999,2000,2001  contributors of the QuakeForge project\n"        "Please see the file \"AUTHORS\" for a list of contributors";
+    plugin_info.functions = &plugin_info_funcs;
+    plugin_info.data = &plugin_info_data;
+
+    plugin_info_data.general = &plugin_info_general_data;
+    plugin_info_data.input = NULL;
+    plugin_info_data.sound = &plugin_info_sound_data;
+
+    plugin_info_funcs.general = &plugin_info_general_funcs;
+    plugin_info_funcs.input = NULL;
+    plugin_info_funcs.sound = &plugin_info_sound_funcs;
+
+    plugin_info_general_funcs.p_Init = I_S_Init;
+    plugin_info_general_funcs.p_Shutdown = I_S_Shutdown;
+
+    plugin_info_sound_funcs.pS_AmbientOff = I_S_AmbientOff;
+    plugin_info_sound_funcs.pS_AmbientOn = I_S_AmbientOn;
+    plugin_info_sound_funcs.pS_TouchSound = I_S_TouchSound;
+    plugin_info_sound_funcs.pS_ClearBuffer = I_S_ClearBuffer;
+    plugin_info_sound_funcs.pS_StaticSound = I_S_StaticSound;
+    plugin_info_sound_funcs.pS_StartSound = I_S_StartSound;
+    plugin_info_sound_funcs.pS_StopSound = I_S_StopSound;
+    plugin_info_sound_funcs.pS_PrecacheSound = I_S_PrecacheSound;
+    plugin_info_sound_funcs.pS_ClearPrecache = I_S_ClearPrecache;
+    plugin_info_sound_funcs.pS_Update = I_S_Update;
+    plugin_info_sound_funcs.pS_StopAllSounds = I_S_StopAllSounds;
+    plugin_info_sound_funcs.pS_BeginPrecaching = I_S_BeginPrecaching;
+    plugin_info_sound_funcs.pS_EndPrecaching = I_S_EndPrecaching;
+    plugin_info_sound_funcs.pS_ExtraUpdate = I_S_ExtraUpdate;
+    plugin_info_sound_funcs.pS_LocalSound = I_S_LocalSound;
+
+    return &plugin_info;
+}
diff --git a/libs/audio/targets/snd_sdl.c b/libs/audio/targets/snd_sdl.c
index 630747fed..d20630725 100644
--- a/libs/audio/targets/snd_sdl.c
+++ b/libs/audio/targets/snd_sdl.c
@@ -39,6 +39,7 @@
 #include "QF/qargs.h"
 #include "QF/sound.h"
 #include "QF/sys.h"
+#include "QF/plugin.h"
 
 static dma_t the_shm;
 static int  snd_inited;
@@ -46,6 +47,34 @@ static int  snd_inited;
 extern int  desired_speed;
 extern int  desired_bits;
 
+plugin_t           plugin_info;
+plugin_data_t      plugin_info_data;
+plugin_funcs_t     plugin_info_funcs;
+general_data_t     plugin_info_general_data;
+general_funcs_t    plugin_info_general_funcs;
+sound_data_t       plugin_info_sound_data;
+sound_funcs_t      plugin_info_sound_funcs;
+
+void I_S_Init (void);
+void I_S_Shutdown (void);
+void I_S_AmbientOff (void);
+void I_S_AmbientOn (void);
+void I_S_TouchSound (char *sample);
+void I_S_ClearBuffer (void);
+void I_S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
+void I_S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,  float attenuation);
+void I_S_StopSound (int entnum, int entchannel);
+sfx_t *I_S_PrecacheSound (char *sample);
+void I_S_ClearPrecache (void);
+void I_S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
+void I_S_StopAllSounds (qboolean clear);
+void I_S_BeginPrecaching (void);
+void I_S_EndPrecaching (void);
+void I_S_ExtraUpdate (void);
+void I_S_LocalSound (char *s);
+
+void I_S_PaintChannels (int endtime);
+
 static void
 paint_audio (void *unused, Uint8 * stream, int len)
 {
@@ -61,7 +90,7 @@ paint_audio (void *unused, Uint8 * stream, int len)
 		shm->samplepos += streamsamples;
 		while (shm->samplepos >= shm->samples)
 			shm->samplepos -= shm->samples;
-		S_PaintChannels (soundtime + streamsamples);
+		I_S_PaintChannels (soundtime + streamsamples);
 
 		if (shm->samplepos + streamsamples <= shm->samples)
 			memcpy (stream, shm->buffer + sampleposbytes, len);
@@ -184,3 +213,44 @@ SNDDMA_Submit (void)
 	SDL_UnlockAudio();
 	SDL_LockAudio();
 }
+
+plugin_t *
+PluginInfo (void) {
+    plugin_info.type = qfp_sound;
+    plugin_info.api_version = QFPLUGIN_VERSION;
+    plugin_info.plugin_version = "0.1";
+    plugin_info.description = "SDL digital output";
+    plugin_info.copyright = "Copyright (C) 1996-1997 id Software, Inc.\n"
+        "Copyright (C) 1999,2000,2001  contributors of the QuakeForge project\n"        "Please see the file \"AUTHORS\" for a list of contributors";
+    plugin_info.functions = &plugin_info_funcs;
+    plugin_info.data = &plugin_info_data;
+
+    plugin_info_data.general = &plugin_info_general_data;
+    plugin_info_data.input = NULL;
+    plugin_info_data.sound = &plugin_info_sound_data;
+
+    plugin_info_funcs.general = &plugin_info_general_funcs;
+    plugin_info_funcs.input = NULL;
+    plugin_info_funcs.sound = &plugin_info_sound_funcs;
+
+    plugin_info_general_funcs.p_Init = I_S_Init;
+    plugin_info_general_funcs.p_Shutdown = I_S_Shutdown;
+
+    plugin_info_sound_funcs.pS_AmbientOff = I_S_AmbientOff;
+    plugin_info_sound_funcs.pS_AmbientOn = I_S_AmbientOn;
+    plugin_info_sound_funcs.pS_TouchSound = I_S_TouchSound;
+    plugin_info_sound_funcs.pS_ClearBuffer = I_S_ClearBuffer;
+    plugin_info_sound_funcs.pS_StaticSound = I_S_StaticSound;
+    plugin_info_sound_funcs.pS_StartSound = I_S_StartSound;
+    plugin_info_sound_funcs.pS_StopSound = I_S_StopSound;
+    plugin_info_sound_funcs.pS_PrecacheSound = I_S_PrecacheSound;
+    plugin_info_sound_funcs.pS_ClearPrecache = I_S_ClearPrecache;
+    plugin_info_sound_funcs.pS_Update = I_S_Update;
+    plugin_info_sound_funcs.pS_StopAllSounds = I_S_StopAllSounds;
+    plugin_info_sound_funcs.pS_BeginPrecaching = I_S_BeginPrecaching;
+    plugin_info_sound_funcs.pS_EndPrecaching = I_S_EndPrecaching;
+    plugin_info_sound_funcs.pS_ExtraUpdate = I_S_ExtraUpdate;
+    plugin_info_sound_funcs.pS_LocalSound = I_S_LocalSound;
+
+    return &plugin_info;
+}
diff --git a/libs/audio/targets/snd_sgi.c b/libs/audio/targets/snd_sgi.c
index 5048f17ed..038dd7c15 100644
--- a/libs/audio/targets/snd_sgi.c
+++ b/libs/audio/targets/snd_sgi.c
@@ -37,6 +37,7 @@
 #include "QF/qtypes.h"
 #include "QF/qargs.h"
 #include "QF/sound.h"
+#include "QF/plugin.h"
 
 static int  snd_inited = 0;
 static ALconfig alc;
@@ -49,6 +50,32 @@ static int  bufsize;
 static int  wbufp;
 static int  framecount;
 
+plugin_t           plugin_info;
+plugin_data_t      plugin_info_data;
+plugin_funcs_t     plugin_info_funcs;
+general_data_t     plugin_info_general_data;
+general_funcs_t    plugin_info_general_funcs;
+sound_data_t       plugin_info_sound_data;
+sound_funcs_t      plugin_info_sound_funcs;
+
+void I_S_Init (void);
+void I_S_Shutdown (void);
+void I_S_AmbientOff (void);
+void I_S_AmbientOn (void);
+void I_S_TouchSound (char *sample);
+void I_S_ClearBuffer (void);
+void I_S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
+void I_S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,  float attenuation);
+void I_S_StopSound (int entnum, int entchannel);
+sfx_t *I_S_PrecacheSound (char *sample);
+void I_S_ClearPrecache (void);
+void I_S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
+void I_S_StopAllSounds (qboolean clear);
+void I_S_BeginPrecaching (void);
+void I_S_EndPrecaching (void);
+void I_S_ExtraUpdate (void);
+void I_S_LocalSound (char *s);
+
 qboolean
 SNDDMA_Init (void)
 {
@@ -308,4 +335,44 @@ SNDDMA_Submit (void)
 	framecount += bytes / bsize;
 }
 
+plugin_t *
+PluginInfo (void) {
+    plugin_info.type = qfp_sound;
+    plugin_info.api_version = QFPLUGIN_VERSION;
+    plugin_info.plugin_version = "0.1";
+    plugin_info.description = "SGI digital output";
+    plugin_info.copyright = "Copyright (C) 1996-1997 id Software, Inc.\n"
+        "Copyright (C) 1999,2000,2001  contributors of the QuakeForge project\n"        "Please see the file \"AUTHORS\" for a list of contributors";
+    plugin_info.functions = &plugin_info_funcs;
+    plugin_info.data = &plugin_info_data;
+
+    plugin_info_data.general = &plugin_info_general_data;
+    plugin_info_data.input = NULL;
+    plugin_info_data.sound = &plugin_info_sound_data;
+
+    plugin_info_funcs.general = &plugin_info_general_funcs;
+    plugin_info_funcs.input = NULL;
+    plugin_info_funcs.sound = &plugin_info_sound_funcs;
+
+    plugin_info_general_funcs.p_Init = I_S_Init;
+    plugin_info_general_funcs.p_Shutdown = I_S_Shutdown;
+
+    plugin_info_sound_funcs.pS_AmbientOff = I_S_AmbientOff;
+    plugin_info_sound_funcs.pS_AmbientOn = I_S_AmbientOn;
+    plugin_info_sound_funcs.pS_TouchSound = I_S_TouchSound;
+    plugin_info_sound_funcs.pS_ClearBuffer = I_S_ClearBuffer;
+    plugin_info_sound_funcs.pS_StaticSound = I_S_StaticSound;
+    plugin_info_sound_funcs.pS_StartSound = I_S_StartSound;
+    plugin_info_sound_funcs.pS_StopSound = I_S_StopSound;
+    plugin_info_sound_funcs.pS_PrecacheSound = I_S_PrecacheSound;
+    plugin_info_sound_funcs.pS_ClearPrecache = I_S_ClearPrecache;
+    plugin_info_sound_funcs.pS_Update = I_S_Update;
+    plugin_info_sound_funcs.pS_StopAllSounds = I_S_StopAllSounds;
+    plugin_info_sound_funcs.pS_BeginPrecaching = I_S_BeginPrecaching;
+    plugin_info_sound_funcs.pS_EndPrecaching = I_S_EndPrecaching;
+    plugin_info_sound_funcs.pS_ExtraUpdate = I_S_ExtraUpdate;
+    plugin_info_sound_funcs.pS_LocalSound = I_S_LocalSound;
+
+    return &plugin_info;
+}
 /* end of file */
diff --git a/libs/audio/targets/snd_sun.c b/libs/audio/targets/snd_sun.c
index 8bd7052bd..232db6335 100644
--- a/libs/audio/targets/snd_sun.c
+++ b/libs/audio/targets/snd_sun.c
@@ -50,6 +50,7 @@
 #include "QF/qtypes.h"
 #include "QF/qargs.h"
 #include "QF/sound.h"
+#include "QF/plugin.h"
 
 int         audio_fd;
 int         snd_inited;
@@ -63,6 +64,32 @@ unsigned char dma_buffer[BUFFER_SIZE];
 unsigned char pend_buffer[BUFFER_SIZE];
 int         pending;
 
+plugin_t           plugin_info;
+plugin_data_t      plugin_info_data;
+plugin_funcs_t     plugin_info_funcs;
+general_data_t     plugin_info_general_data;
+general_funcs_t    plugin_info_general_funcs;
+sound_data_t       plugin_info_sound_data;
+sound_funcs_t      plugin_info_sound_funcs;
+
+void I_S_Init (void);
+void I_S_Shutdown (void);
+void I_S_AmbientOff (void);
+void I_S_AmbientOn (void);
+void I_S_TouchSound (char *sample);
+void I_S_ClearBuffer (void);
+void I_S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
+void I_S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol,  float attenuation);
+void I_S_StopSound (int entnum, int entchannel);
+sfx_t *I_S_PrecacheSound (char *sample);
+void I_S_ClearPrecache (void);
+void I_S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
+void I_S_StopAllSounds (qboolean clear);
+void I_S_BeginPrecaching (void);
+void I_S_EndPrecaching (void);
+void I_S_ExtraUpdate (void);
+void I_S_LocalSound (char *s);
+
 qboolean
 SNDDMA_Init (void)
 {
@@ -226,3 +253,44 @@ SNDDMA_Submit (void)
 		printf ("audio can't keep up!\n");
 
 }
+
+plugin_t *
+PluginInfo (void) {
+    plugin_info.type = qfp_sound;
+    plugin_info.api_version = QFPLUGIN_VERSION;
+    plugin_info.plugin_version = "0.1";
+    plugin_info.description = "SUN digital output";
+    plugin_info.copyright = "Copyright (C) 1996-1997 id Software, Inc.\n"
+        "Copyright (C) 1999,2000,2001  contributors of the QuakeForge project\n"        "Please see the file \"AUTHORS\" for a list of contributors";
+    plugin_info.functions = &plugin_info_funcs;
+    plugin_info.data = &plugin_info_data;
+
+    plugin_info_data.general = &plugin_info_general_data;
+    plugin_info_data.input = NULL;
+    plugin_info_data.sound = &plugin_info_sound_data;
+
+    plugin_info_funcs.general = &plugin_info_general_funcs;
+    plugin_info_funcs.input = NULL;
+    plugin_info_funcs.sound = &plugin_info_sound_funcs;
+
+    plugin_info_general_funcs.p_Init = I_S_Init;
+    plugin_info_general_funcs.p_Shutdown = I_S_Shutdown;
+
+    plugin_info_sound_funcs.pS_AmbientOff = I_S_AmbientOff;
+    plugin_info_sound_funcs.pS_AmbientOn = I_S_AmbientOn;
+    plugin_info_sound_funcs.pS_TouchSound = I_S_TouchSound;
+    plugin_info_sound_funcs.pS_ClearBuffer = I_S_ClearBuffer;
+    plugin_info_sound_funcs.pS_StaticSound = I_S_StaticSound;
+    plugin_info_sound_funcs.pS_StartSound = I_S_StartSound;
+    plugin_info_sound_funcs.pS_StopSound = I_S_StopSound;
+    plugin_info_sound_funcs.pS_PrecacheSound = I_S_PrecacheSound;
+    plugin_info_sound_funcs.pS_ClearPrecache = I_S_ClearPrecache;
+    plugin_info_sound_funcs.pS_Update = I_S_Update;
+    plugin_info_sound_funcs.pS_StopAllSounds = I_S_StopAllSounds;
+    plugin_info_sound_funcs.pS_BeginPrecaching = I_S_BeginPrecaching;
+    plugin_info_sound_funcs.pS_EndPrecaching = I_S_EndPrecaching;
+    plugin_info_sound_funcs.pS_ExtraUpdate = I_S_ExtraUpdate;
+    plugin_info_sound_funcs.pS_LocalSound = I_S_LocalSound;
+
+    return &plugin_info;
+}
diff --git a/libs/util/plugin.c b/libs/util/plugin.c
index 605f9ab21..84c0a134c 100644
--- a/libs/util/plugin.c
+++ b/libs/util/plugin.c
@@ -98,19 +98,23 @@ PI_LoadPlugin (char *type, char *name)
 	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",
+	snprintf (realname, sizeof (realname), "%s/lib%s_%s.so",
 				fs_pluginpath->string, type, (tmpname ? tmpname + 1 : name));
 
-	if (!(dlhand = dlopen (realname, RTLD_LAZY)))	// lib not found
+	if (!(dlhand = dlopen (realname, RTLD_LAZY))) {	// lib not found
+		Con_Printf ("%s\n", dlerror());
 		return NULL;
+	}
 
 	if (!(plugin_info = dlsym (dlhand, "PluginInfo"))) {	// info function not found
 		dlclose (dlhand);
+		Con_Printf ("info function not found\n");
 		return NULL;
 	}
 
 	if (!(plugin = plugin_info ())) {	// Something went badly wrong
 		dlclose (dlhand);
+		Con_Printf ("soemthing went badly wrong\n");
 		return NULL;
 	}
 
diff --git a/nq/source/Makefile.am b/nq/source/Makefile.am
index 5adff50e0..a49806393 100644
--- a/nq/source/Makefile.am
+++ b/nq/source/Makefile.am
@@ -66,10 +66,10 @@ qf_client_LIBS= $(top_builddir)/libs/video/targets/libQFjs.la \
 				$(top_builddir)/libs/gamecode/libQFgamecode.la \
 				$(top_builddir)/libs/gib/libQFgib.la \
 				$(top_builddir)/libs/audio/cd/libQFcd.la \
-				$(top_builddir)/libs/audio/targets/libQFsound.la \
+				$(top_builddir)/libs/audio/libQFsound.la \
 				$(top_builddir)/libs/util/libQFutil.la
 
-client_LIBS=	-L. -lqfnet $(qf_client_LIBS) $(SOUND_LIBS) $(NET_LIBS)
+client_LIBS=	-L. -lqfnet $(qf_client_LIBS) $(NET_LIBS)
 client_LIB_DEPS=	libqfnet.a $(qf_client_LIBS)
 
 client_SOURCES=	cl_cam.c cl_cmd.c cl_demo.c cl_input.c cl_main.c cl_parse.c \
diff --git a/qw/source/Makefile.am b/qw/source/Makefile.am
index db3eec3da..1f34b9963 100644
--- a/qw/source/Makefile.am
+++ b/qw/source/Makefile.am
@@ -88,10 +88,10 @@ endif
 qf_client_LIBS=	$(top_builddir)/libs/video/targets/libQFjs.la \
 				$(top_builddir)/libs/gamecode/libQFgamecode.la \
 				$(top_builddir)/libs/audio/cd/libQFcd.la \
-				$(top_builddir)/libs/audio/targets/libQFsound.la \
+				$(top_builddir)/libs/audio/libQFsound.la \
 				$(top_builddir)/libs/util/libQFutil.la
 
-client_LIBS= -L. -lqfnet $(qf_client_LIBS) $(SOUND_LIBS) $(NET_LIBS)
+client_LIBS= -L. -lqfnet $(qf_client_LIBS) $(NET_LIBS)
 client_LIB_DEPS=	libqfnet.a $(qf_client_LIBS)
 # libQFjs is seperate because it needs to be linked after when building statically
 
diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c
index 9398739d3..3ef5c13d6 100644
--- a/qw/source/cl_main.c
+++ b/qw/source/cl_main.c
@@ -1133,8 +1133,10 @@ CL_Init (void)
 	Info_SetValueForStarKey (cls.userinfo, "*ver", st, MAX_INFO_STRING);
 	Info_SetValueForStarKey (cls.userinfo, "stdver", QW_QSG_VERSION,
 							 MAX_INFO_STRING);
+
+	PI_Init ();
 #ifdef PACKET_LOGGING
-        Net_Log_Init();
+	Net_Log_Init ();
 #endif
 	CL_Input_Init ();
 	CL_Ents_Init ();