changeset 294:d2d48e10f370

Added a new header file: SDL_loadso.h It contains the following functions: SDL_LoadObject(), SDL_LoadFunction(), SDL_UnloadObject() The UNIX esd and arts audio code use these to dynamically load their respective audio libraries.
author Sam Lantinga <slouken@libsdl.org>
date Wed, 06 Mar 2002 05:20:11 +0000
parents 585a7e1285ae
children 54ad1d2f1325
files WhatsNew configure.in docs.html include/Makefile.am include/SDL.h include/SDL_loadso.h include/SDL_name.h src/Makefile.am src/SDL_loadso.c src/audio/arts/Makefile.am src/audio/arts/SDL_artsaudio.c src/audio/esd/Makefile.am src/audio/esd/SDL_esdaudio.c
diffstat 13 files changed, 516 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/WhatsNew	Tue Mar 05 23:19:37 2002 +0000
+++ b/WhatsNew	Wed Mar 06 05:20:11 2002 +0000
@@ -4,6 +4,12 @@
 Version 1.0:
 
 1.2.4:
+	Added a new header file: SDL_loadso.h
+	It contains the following functions:
+		SDL_LoadObject(), SDL_LoadFunction(), SDL_UnloadObject()
+	The UNIX esd and arts audio code use these to dynamically load
+	their respective audio libraries.
+
 	Added SDL_LockRect() and SDL_UnlockRect() to lock a portion of a
 	surface.  This may be more efficient than a full lock if you are
 	using a hardware surface and plan to make a few changes to small
--- a/configure.in	Tue Mar 05 23:19:37 2002 +0000
+++ b/configure.in	Wed Mar 06 05:20:11 2002 +0000
@@ -324,12 +324,26 @@
 [  --enable-esd            support the Enlightened Sound Daemon [default=yes]],
                   , enable_esd=yes)
     if test x$enable_audio = xyes -a x$enable_esd = xyes; then
-        AM_PATH_ESD(0.2.8, [
-            CFLAGS="$CFLAGS -DESD_SUPPORT $ESD_CFLAGS"
-            SYSTEM_LIBS="$SYSTEM_LIBS $ESD_LIBS"
+	use_esd=no
+        AM_PATH_ESD(0.2.8, use_esd=yes)
+	if test x$use_esd = xyes; then
+            AC_ARG_ENABLE(esd-shared,
+[  --enable-esd-shared     dynamically load ESD support [default=yes]],
+                          , enable_esd_shared=yes)
+            esd_lib_spec=`echo $ESD_LIBS | sed 's/.*-L\([[^ ]]*\).*/\1\/libesd.so.*/'`
+	    esd_lib=`ls $esd_lib_spec | head -1 | sed 's/.*\/\(.*\)/\1/'`
+	    echo "-- $esd_lib_spec -> $esd_lib"
+            if test x$enable_dlopen = xyes && \
+               test x$enable_esd_shared = xyes && test x$esd_lib != x; then
+                CFLAGS="$CFLAGS -DESD_SUPPORT -DESD_DYNAMIC=\$(esd_lib) $ESD_CFLAGS"
+		AC_SUBST(esd_lib)
+            else
+                CFLAGS="$CFLAGS -DESD_SUPPORT $ESD_CFLAGS"
+                SYSTEM_LIBS="$SYSTEM_LIBS $ESD_LIBS"
+            fi
             AUDIO_SUBDIRS="$AUDIO_SUBDIRS esd"
             AUDIO_DRIVERS="$AUDIO_DRIVERS esd/libaudio_esd.la"
-        ])
+        fi
     fi
 }
 
@@ -359,8 +373,20 @@
             CFLAGS="$save_CFLAGS"
             AC_MSG_RESULT($audio_arts)
             if test x$audio_arts = xyes; then
-                CFLAGS="$CFLAGS -DARTSC_SUPPORT $ARTSC_CFLAGS"
-                SYSTEM_LIBS="$SYSTEM_LIBS $ARTSC_LIBS"
+                AC_ARG_ENABLE(arts-shared,
+[  --enable-arts-shared     dynamically load ESD support [default=yes]],
+                              , enable_arts_shared=yes)
+                arts_lib_spec=`echo $ARTSC_LIBS | sed 's/.*-L\([[^ ]]*\).*/\1\/libarts.so.*/'`
+	        arts_lib=`ls $arts_lib_spec | head -1 | sed 's/.*\/\(.*\)/\1/'`
+	        echo "-- $arts_lib_spec -> $arts_lib"
+                if test x$enable_dlopen = xyes && \
+                   test x$enable_arts_shared = xyes && test x$arts_lib != x; then
+                    CFLAGS="$CFLAGS -DARTSC_SUPPORT -DARTSC_DYNAMIC=\$(arts_lib) $ARTSC_CFLAGS"
+		    AC_SUBST(arts_lib)
+                else
+                    CFLAGS="$CFLAGS -DARTSC_SUPPORT $ARTSC_CFLAGS"
+                    SYSTEM_LIBS="$SYSTEM_LIBS $ARTSC_LIBS"
+                fi
                 AUDIO_SUBDIRS="$AUDIO_SUBDIRS arts"
                 AUDIO_DRIVERS="$AUDIO_DRIVERS arts/libaudio_arts.la"
             fi
@@ -1353,11 +1379,36 @@
     VIDEO_DRIVERS="$VIDEO_DRIVERS quartz/libvideo_quartz.la"
 }
 
+dnl Check for the dlfcn.h interface for dynamically loading objects
+CheckDLOPEN()
+{
+    AC_ARG_ENABLE(dlopen,
+[  --enable-dlopen         use dlopen for shared object loading [default=yes]],
+                  , enable_dlopen=yes)
+    if test x$enable_dlopen = xyes; then
+        AC_MSG_CHECKING(for dlopen)
+        use_dlopen=no
+        AC_TRY_COMPILE([
+         #include <dlfcn.h>
+        ],[
+        ],[
+        use_dlopen=yes
+        ])
+        AC_MSG_RESULT($use_dlopen)
+
+        if test x$use_dlopen = xyes; then
+            CFLAGS="$CFLAGS -DUSE_DLOPEN"
+            SYSTEM_LIBS="$SYSTEM_LIBS -ldl"
+        fi
+    fi
+}
+
 case "$target" in
     *-*-linux*)
         ARCH=linux
         CheckDummyVideo
         CheckDiskAudio
+	CheckDLOPEN
         CheckNASM
         CheckOSS
         CheckALSA
@@ -1429,6 +1480,7 @@
         ARCH=bsdi
         CheckDummyVideo
         CheckDiskAudio
+	CheckDLOPEN
         CheckNASM
         CheckOSS
         CheckARTSC
@@ -1480,6 +1532,7 @@
         ARCH=freebsd
         CheckDummyVideo
         CheckDiskAudio
+	CheckDLOPEN
         CheckVGL
         CheckNASM
         CheckOSS
@@ -1535,6 +1588,7 @@
         ARCH=netbsd
         CheckDummyVideo
         CheckDiskAudio
+	CheckDLOPEN
         CheckNASM
         CheckOSS
         CheckARTSC
@@ -1588,6 +1642,7 @@
         ARCH=openbsd
         CheckDummyVideo
         CheckDiskAudio
+	CheckDLOPEN
         CheckOPENBSDAUDIO
         CheckNASM
         CheckOSS
@@ -1647,6 +1702,7 @@
         ARCH=sysv5
         CheckDummyVideo
         CheckDiskAudio
+	CheckDLOPEN
         CheckNASM
         CheckOSS
         CheckARTSC
@@ -1696,6 +1752,7 @@
         CFLAGS="$CFLAGS -D__ELF__" # Fix for nasm on Solaris x86
         CheckDummyVideo
         CheckDiskAudio
+	CheckDLOPEN
         CheckNASM
         CheckOSS
         CheckARTSC
@@ -1744,6 +1801,7 @@
         ARCH=irix
         CheckDummyVideo
         CheckDiskAudio
+	CheckDLOPEN
         CheckDMEDIA
         CheckESD
         CheckNAS
@@ -1806,6 +1864,7 @@
         ARCH=hpux
         CheckDummyVideo
         CheckDiskAudio
+	CheckDLOPEN
         CheckOSS
         CheckNAS
         CheckX11
@@ -1853,6 +1912,7 @@
         ARCH=aix
         CheckDummyVideo
         CheckDiskAudio
+	CheckDLOPEN
         CheckOSS
         CheckNAS
         CheckX11
@@ -1898,6 +1958,7 @@
         ARCH=osf
         CheckDummyVideo
         CheckDiskAudio
+	CheckDLOPEN
         CheckNAS
         CheckX11
         CheckGGI
@@ -1944,6 +2005,7 @@
         ARCH=qnx
         CheckDummyVideo
         CheckDiskAudio
+	CheckDLOPEN
         CheckNAS
         CheckPHOTON
         CheckX11
--- a/docs.html	Tue Mar 05 23:19:37 2002 +0000
+++ b/docs.html	Wed Mar 06 05:20:11 2002 +0000
@@ -16,6 +16,7 @@
 Major changes since SDL 1.0.0:
 </H2>
 <UL>
+	<LI> 1.2.4: Added shared object loading functions in SDL_loadso.h
 	<LI> 1.2.4: Added SDL_LockRect() and SDL_UnlockRect()
 	<LI> 1.2.4: Incorporated XFree86 extension libraries into the source
 	<LI> 1.2.4: Added initial support for Atari (thanks Patrice!)
--- a/include/Makefile.am	Tue Mar 05 23:19:37 2002 +0000
+++ b/include/Makefile.am	Wed Mar 06 05:20:11 2002 +0000
@@ -18,6 +18,7 @@
 	SDL_joystick.h		\
 	SDL_keyboard.h		\
 	SDL_keysym.h		\
+	SDL_loadso.h		\
 	SDL_main.h		\
 	SDL_mouse.h		\
 	SDL_mutex.h		\
--- a/include/SDL.h	Tue Mar 05 23:19:37 2002 +0000
+++ b/include/SDL.h	Wed Mar 06 05:20:11 2002 +0000
@@ -34,6 +34,7 @@
 #include "SDL_types.h"
 #include "SDL_getenv.h"
 #include "SDL_error.h"
+#include "SDL_loadso.h"
 #include "SDL_rwops.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/SDL_loadso.h	Wed Mar 06 05:20:11 2002 +0000
@@ -0,0 +1,61 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* System dependent library loading routines                           */
+
+#ifndef _SDL_loadso_h
+#define _SDL_loadso_h
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This function dynamically loads a shared object and returns a pointer
+ * to the object handle (or NULL if there was an error).
+ * The 'sofile' parameter is a system dependent name of the object file.
+ */
+extern DECLSPEC void *SDL_LoadObject(const char *sofile);
+
+/* Given an object handle, this function looks up the address of the
+ * named function in the shared object and returns it.  This address
+ * is no longer valid after calling SDL_UnloadObject().
+ */
+extern DECLSPEC void *SDL_LoadFunction(void *handle, const char *name);
+
+/* Unload a shared object from memory */
+extern DECLSPEC void SDL_UnloadObject(void *handle);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* _SDL_loadso_h */
--- a/include/SDL_name.h	Tue Mar 05 23:19:37 2002 +0000
+++ b/include/SDL_name.h	Wed Mar 06 05:20:11 2002 +0000
@@ -6,8 +6,6 @@
 #define NeedFunctionPrototypes 1
 #endif
 
-#ifndef SDL_NAME
 #define SDL_NAME(X)	SDL_##X
-#endif
 
 #endif /* _SDLname_h_ */
--- a/src/Makefile.am	Tue Mar 05 23:19:37 2002 +0000
+++ b/src/Makefile.am	Wed Mar 06 05:20:11 2002 +0000
@@ -37,5 +37,6 @@
 	SDL_error_c.h		\
 	SDL_fatal.c		\
 	SDL_fatal.h		\
-	SDL_getenv.c
+	SDL_getenv.c		\
+	SDL_loadso.c
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/SDL_loadso.c	Wed Mar 06 05:20:11 2002 +0000
@@ -0,0 +1,193 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* System dependent library loading routines                           */
+
+#include <stdio.h>
+#if defined(USE_DLOPEN)
+# include <dlfcn.h>
+#elif defined(WIN32)
+# include <windows.h>
+#elif defined(__BEOS__)
+# include <be/kernel/image.h>
+#elif defined(macintosh)
+# include <string.h>
+# include <Strings.h>
+# include <CodeFragments.h>
+# include <Errors.h>
+#else
+/*#error Unsupported dynamic link environment*/
+#endif /* system type */
+
+#include "SDL_error.h"
+#include "SDL_loadso.h"
+
+void *SDL_LoadObject(const char *sofile)
+{
+	void *handle = NULL;
+	const char *loaderror = "SDL_LoadObject() not implemented";
+#if defined(USE_DLOPEN)
+/* * */
+	handle = dlopen(sofile, RTLD_NOW);
+	loaderror = (char *)dlerror();
+#elif defined(WIN32)
+/* * */
+	char errbuf[512];
+
+	handle = (void *)LoadLibrary(sofile);
+
+	/* Generate an error message if all loads failed */
+	if ( handle == NULL ) {
+		FormatMessage((FORMAT_MESSAGE_IGNORE_INSERTS |
+					FORMAT_MESSAGE_FROM_SYSTEM),
+				NULL, GetLastError(), 
+				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+				errbuf, SDL_TABLESIZE(errbuf), NULL);
+		loaderror = errbuf;
+	}
+#elif defined(__BEOS__)
+/* * */
+	image_id library_id;
+
+	library_id = load_add_on(sofile);
+	if ( library_id == B_ERROR ) {
+		loaderror = "BeOS error";
+	} else {
+		handle = (void *)(library_id);
+	}
+#elif defined(macintosh)
+/* * */
+	CFragConnectionID library_id;
+	Ptr mainAddr;
+	Str255 errName;
+	OSErr error;
+	char psofile[512];
+
+	strncpy(psofile, sofile, SDL_TABLESIZE(psofile));
+	psofile[SDL_TABLESIZE(psofile)-1] = '\0';
+	error = GetSharedLibrary(C2PStr(psofile), kCompiledCFragArch,
+			kLoadCFrag, &library_id, &mainAddr, errName);
+	switch (error) {
+		case noErr:
+			break;
+		case cfragNoLibraryErr:
+			loaderror = "Library not found";
+			break;
+		case cfragUnresolvedErr:
+			loaderror = "Unabled to resolve symbols";
+			break;
+		case cfragNoPrivateMemErr:
+		case cfragNoClientMemErr:
+			loaderror = "Out of memory";
+			break;
+		default:
+			loaderror = "Unknown Code Fragment Manager error";
+			break;
+	}
+	if ( loaderror == NULL ) {
+		handle = (void *)(library_id);
+	}
+#endif /* system type */
+
+	if ( handle == NULL ) {
+		SDL_SetError("Failed loading %s: %s", sofile, loaderror);
+	}
+	return(handle);
+}
+
+void *SDL_LoadFunction(void *handle, const char *name)
+{
+	void *symbol = NULL;
+	const char *loaderror = "SDL_LoadFunction not implemented";
+#if defined(USE_DLOPEN)
+/* * */
+	symbol = dlsym(handle, name);
+	if ( symbol == NULL ) {
+		loaderror = (char *)dlerror();
+	}
+#elif defined(WIN32)
+/* * */
+	char errbuf[512];
+
+	symbol = (void *)GetProcAddress((HMODULE)handle, name);
+	if ( symbol == NULL ) {
+		FormatMessage((FORMAT_MESSAGE_IGNORE_INSERTS |
+					FORMAT_MESSAGE_FROM_SYSTEM),
+				NULL, GetLastError(), 
+				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+				errbuf, SDL_TABLESIZE(errbuf), NULL);
+		loaderror = errbuf;
+	}
+#elif defined(__BEOS__)
+/* * */
+	image_id library_id = (image_id)handle;
+	if ( get_image_symbol(library_id,
+		name, B_SYMBOL_TYPE_TEXT, &symbol) != B_NO_ERROR ) {
+		loaderror = "Symbol not found";
+	}
+#elif defined(macintosh)
+/* * */
+	CFragSymbolClass class;
+	CFragConnectionID library_id = (CFragConnectionID)handle;
+	char pname[512];
+
+	strncpy(pname, name, SDL_TABLESIZE(pname));
+	pname[SDL_TABLESIZE(pname)-1] = '\0';
+	if ( FindSymbol(library_id, C2PStr(pname),
+	                (char **)&symbol, &class) != noErr ) {
+		loaderror = "Symbol not found";
+	}
+#endif /* system type */
+
+	if ( symbol == NULL ) {
+		SDL_SetError("Failed loading %s: %s", name, loaderror);
+	}
+	return(symbol);
+}
+
+void SDL_UnloadObject(void *handle)
+{
+	if ( handle == NULL ) {
+		return;
+	}
+#if defined(USE_DLOPEN)
+/* * */
+	dlclose(handle);
+#elif defined(WIN32)
+/* * */
+	FreeLibrary((HMODULE)handle);
+#elif defined(__BEOS__)
+/* * */
+	image_id library_id = (image_id)handle;
+	unload_add_on(library_id);
+#elif defined(macintosh)
+/* * */
+	CFragConnectionID library_id = (CFragConnectionID)handle;
+	CloseConnection(library_id);
+#endif /* system type */
+}
--- a/src/audio/arts/Makefile.am	Tue Mar 05 23:19:37 2002 +0000
+++ b/src/audio/arts/Makefile.am	Wed Mar 06 05:20:11 2002 +0000
@@ -4,6 +4,8 @@
 noinst_LTLIBRARIES = libaudio_arts.la
 libaudio_arts_la_SOURCES = $(SRCS)
 
+arts_lib = \"@arts_lib@\"
+
 # The SDL audio driver sources
 SRCS =	SDL_artsaudio.c	\
 	SDL_artsaudio.h
--- a/src/audio/arts/SDL_artsaudio.c	Tue Mar 05 23:19:37 2002 +0000
+++ b/src/audio/arts/SDL_artsaudio.c	Wed Mar 06 05:20:11 2002 +0000
@@ -43,6 +43,13 @@
 #include "SDL_audiodev_c.h"
 #include "SDL_artsaudio.h"
 
+#ifdef ARTSC_DYNAMIC
+#include "SDL_name.h"
+#include "SDL_loadso.h"
+#else
+#define SDL_NAME(X)	X
+#endif
+
 /* The tag name used by artsc audio */
 #define ARTSC_DRIVER_NAME         "artsc"
 
@@ -53,20 +60,96 @@
 static Uint8 *ARTSC_GetAudioBuf(_THIS);
 static void ARTSC_CloseAudio(_THIS);
 
+#ifdef ARTSC_DYNAMIC
+
+static const char *arts_library = ARTSC_DYNAMIC;
+static void *arts_handle = NULL;
+static int arts_loaded = 0;
+
+static int (*SDL_NAME(arts_init))();
+static int (*SDL_NAME(arts_free))();
+static int (*SDL_NAME(arts_play_stream))();
+static int (*SDL_NAME(arts_stream_set))();
+static int (*SDL_NAME(arts_stream_get))();
+static int (*SDL_NAME(arts_write))();
+static int (*SDL_NAME(arts_close_stream))();
+static struct {
+	const char *name;
+	void **func;
+} arts_functions[] = {
+	{ "arts_init",		(void **)&SDL_NAME(arts_init)		},
+	{ "arts_free",		(void **)&SDL_NAME(arts_free)		},
+	{ "arts_play_stream",	(void **)&SDL_NAME(arts_play_stream)	},
+	{ "arts_stream_set",	(void **)&SDL_NAME(arts_stream_set)	},
+	{ "arts_stream_get",	(void **)&SDL_NAME(arts_stream_get)	},
+	{ "arts_write",		(void **)&SDL_NAME(arts_write)		},
+	{ "arts_close_stream",	(void **)&SDL_NAME(arts_close_stream)	},
+};
+
+static void UnloadARTSLibrary()
+{
+	if ( arts_loaded ) {
+		SDL_UnloadObject(arts_handle);
+		arts_handle = NULL;
+		arts_loaded = 0;
+	}
+}
+
+static int LoadARTSLibrary(void)
+{
+	int i, retval = -1;
+
+	arts_handle = SDL_LoadObject(arts_library);
+	if ( arts_handle ) {
+		arts_loaded = 1;
+		retval = 0;
+		for ( i=0; i<SDL_TABLESIZE(arts_functions); ++i ) {
+			*arts_functions[i].func = SDL_LoadFunction(arts_handle, arts_functions[i].name);
+			if ( ! arts_functions[i].func ) {
+				retval = -1;
+				UnloadARTSLibrary();
+				break;
+			}
+		}
+	}
+	return retval;
+}
+
+#else
+
+static void UnloadARTSLibrary()
+{
+	return;
+}
+
+static int LoadARTSLibrary(void)
+{
+	return 0;
+}
+
+#endif /* ARTSC_DYNAMIC */
+
 /* Audio driver bootstrap functions */
 
 static int Audio_Available(void)
 {
-	if(arts_init())
-		return 0;
-	else
-		return 1;
+	int available = 0;
+
+	if ( LoadARTSLibrary() < 0 ) {
+		return available;
+	}
+	if ( SDL_NAME(arts_init)() == 0 ) {
+		available = 1;
+		SDL_NAME(arts_free)();
+	}
+	UnloadARTSLibrary();
 }
 
 static void Audio_DeleteDevice(SDL_AudioDevice *device)
 {
 	free(device->hidden);
 	free(device);
+	UnloadARTSLibrary();
 }
 
 static SDL_AudioDevice *Audio_CreateDevice(int devindex)
@@ -74,6 +157,7 @@
 	SDL_AudioDevice *this;
 
 	/* Initialize all variables that we clean on shutdown */
+	LoadARTSLibrary();
 	this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
 	if ( this ) {
 		memset(this, 0, (sizeof *this));
@@ -136,7 +220,7 @@
 	int written;
 
 	/* Write the audio data */
-	written = arts_write(stream, mixbuf, mixlen);
+	written = SDL_NAME(arts_write)(stream, mixbuf, mixlen);
 	
 	/* If timer synchronization is enabled, set the next write frame */
 	if ( frame_ticks ) {
@@ -164,9 +248,10 @@
 		mixbuf = NULL;
 	}
 	if ( stream ) {
-		arts_close_stream(stream);
+		SDL_NAME(arts_close_stream)(stream);
 		stream = 0;
 	}
+	SDL_NAME(arts_free)();
 }
 
 static int ARTSC_OpenAudio(_THIS, SDL_AudioSpec *spec)
@@ -210,7 +295,11 @@
 	}
 	spec->format = test_format;
 
-	stream = arts_play_stream(spec->freq, bits, spec->channels, "SDL");
+	if ( SDL_NAME(arts_init)() != 0 ) {
+		SDL_SetError("Unable to initialize ARTS");
+		return(-1);
+	}
+	stream = SDL_NAME(arts_play_stream)(spec->freq, bits, spec->channels, "SDL");
 
 	/* Calculate the final parameters for this audio specification */
 	SDL_CalculateAudioSpec(spec);
@@ -224,12 +313,12 @@
 	frag_spec |= 0x00020000;	/* two fragments, for low latency */
 
 #ifdef ARTS_P_PACKET_SETTINGS
-	arts_stream_set(stream, ARTS_P_PACKET_SETTINGS, frag_spec);
+	SDL_NAME(arts_stream_set)(stream, ARTS_P_PACKET_SETTINGS, frag_spec);
 #else
-	arts_stream_set(stream, ARTS_P_PACKET_SIZE, frag_spec&0xffff);
-	arts_stream_set(stream, ARTS_P_PACKET_COUNT, frag_spec>>16);
+	SDL_NAME(arts_stream_set)(stream, ARTS_P_PACKET_SIZE, frag_spec&0xffff);
+	SDL_NAME(arts_stream_set)(stream, ARTS_P_PACKET_COUNT, frag_spec>>16);
 #endif
-	spec->size = arts_stream_get(stream, ARTS_P_PACKET_SIZE);
+	spec->size = SDL_NAME(arts_stream_get)(stream, ARTS_P_PACKET_SIZE);
 
 	/* Allocate mixing buffer */
 	mixlen = spec->size;
--- a/src/audio/esd/Makefile.am	Tue Mar 05 23:19:37 2002 +0000
+++ b/src/audio/esd/Makefile.am	Wed Mar 06 05:20:11 2002 +0000
@@ -4,6 +4,8 @@
 noinst_LTLIBRARIES = libaudio_esd.la
 libaudio_esd_la_SOURCES = $(SRCS)
 
+esd_lib = \"@esd_lib@\"
+
 # The SDL audio driver sources
 SRCS =	SDL_esdaudio.c	\
 	SDL_esdaudio.h
--- a/src/audio/esd/SDL_esdaudio.c	Tue Mar 05 23:19:37 2002 +0000
+++ b/src/audio/esd/SDL_esdaudio.c	Wed Mar 06 05:20:11 2002 +0000
@@ -46,6 +46,13 @@
 #include "SDL_audiodev_c.h"
 #include "SDL_esdaudio.h"
 
+#ifdef ESD_DYNAMIC
+#include "SDL_name.h"
+#include "SDL_loadso.h"
+#else
+#define SDL_NAME(X)	X
+#endif
+
 /* The tag name used by ESD audio */
 #define ESD_DRIVER_NAME		"esd"
 
@@ -56,6 +63,68 @@
 static Uint8 *ESD_GetAudioBuf(_THIS);
 static void ESD_CloseAudio(_THIS);
 
+#ifdef ESD_DYNAMIC
+
+static const char *esd_library = ESD_DYNAMIC;
+static void *esd_handle = NULL;
+static int esd_loaded = 0;
+
+static int (*SDL_NAME(esd_open_sound))( const char *host );
+static int (*SDL_NAME(esd_close))( int esd );
+static int (*SDL_NAME(esd_play_stream))( esd_format_t format, int rate,
+                                         const char *host, const char *name );
+static struct {
+	const char *name;
+	void **func;
+} esd_functions[] = {
+	{ "esd_open_sound",	(void **)&SDL_NAME(esd_open_sound)	},
+	{ "esd_close",		(void **)&SDL_NAME(esd_close)		},
+	{ "esd_play_stream",	(void **)&SDL_NAME(esd_play_stream)	},
+};
+
+static void UnloadESDLibrary()
+{
+	if ( esd_loaded ) {
+		SDL_UnloadObject(esd_handle);
+		esd_handle = NULL;
+		esd_loaded = 0;
+	}
+}
+
+static int LoadESDLibrary(void)
+{
+	int i, retval = -1;
+
+	esd_handle = SDL_LoadObject(esd_library);
+	if ( esd_handle ) {
+		esd_loaded = 1;
+		retval = 0;
+		for ( i=0; i<SDL_TABLESIZE(esd_functions); ++i ) {
+			*esd_functions[i].func = SDL_LoadFunction(esd_handle, esd_functions[i].name);
+			if ( ! esd_functions[i].func ) {
+				retval = -1;
+				UnloadESDLibrary();
+				break;
+			}
+		}
+	}
+	return retval;
+}
+
+#else
+
+static void UnloadESDLibrary()
+{
+	return;
+}
+
+static int LoadESDLibrary(void)
+{
+	return 0;
+}
+
+#endif /* ESD_DYNAMIC */
+
 /* Audio driver bootstrap functions */
 
 static int Audio_Available(void)
@@ -64,11 +133,15 @@
 	int available;
 
 	available = 0;
-	connection = esd_open_sound(NULL);
+	if ( LoadESDLibrary() < 0 ) {
+		return available;
+	}
+	connection = SDL_NAME(esd_open_sound)(NULL);
 	if ( connection >= 0 ) {
 		available = 1;
-		esd_close(connection);
+		SDL_NAME(esd_close)(connection);
 	}
+	UnloadESDLibrary();
 	return(available);
 }
 
@@ -76,6 +149,7 @@
 {
 	free(device->hidden);
 	free(device);
+	UnloadESDLibrary();
 }
 
 static SDL_AudioDevice *Audio_CreateDevice(int devindex)
@@ -83,6 +157,7 @@
 	SDL_AudioDevice *this;
 
 	/* Initialize all variables that we clean on shutdown */
+	LoadESDLibrary();
 	this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
 	if ( this ) {
 		memset(this, 0, (sizeof *this));
@@ -174,7 +249,7 @@
 		mixbuf = NULL;
 	}
 	if ( audio_fd >= 0 ) {
-		close(audio_fd);
+		SDL_NAME(esd_close)(audio_fd);
 		audio_fd = -1;
 	}
 }
@@ -231,7 +306,7 @@
 #endif
 
 	/* Open a connection to the ESD audio server */
-	audio_fd = esd_play_stream(format, spec->freq, NULL, get_progname());
+	audio_fd = SDL_NAME(esd_play_stream)(format, spec->freq, NULL, get_progname());
 	if ( audio_fd < 0 ) {
 		SDL_SetError("Couldn't open ESD connection");
 		return(-1);