Merged SDL-ryan-multiple-audio-device branch r2803:2871 into the trunk.
authorRyan C. Gordon <icculus@icculus.org>
Tue, 17 Oct 2006 09:15:21 +0000
changeset 2049 5f6550e5184f
parent 2048 6067c7f9a672
child 2050 bbc89e09503f
Merged SDL-ryan-multiple-audio-device branch r2803:2871 into the trunk.
configure.in
include/SDL_audio.h
include/SDL_config.h.in
include/SDL_thread.h
src/SDL_error.c
src/audio/SDL_audio.c
src/audio/SDL_audiocvt.c
src/audio/SDL_audiodev.c
src/audio/SDL_audiodev_c.h
src/audio/SDL_mixer.c
src/audio/SDL_sysaudio.h
src/audio/alsa/SDL_alsa_audio.c
src/audio/alsa/SDL_alsa_audio.h
src/audio/amigaos/SDL_ahiaudio.c
src/audio/amigaos/SDL_ahiaudio.h
src/audio/arts/SDL_artsaudio.c
src/audio/arts/SDL_artsaudio.h
src/audio/baudio/SDL_beaudio.cc
src/audio/baudio/SDL_beaudio.h
src/audio/bsd/SDL_bsdaudio.c
src/audio/bsd/SDL_bsdaudio.h
src/audio/dart/SDL_dart.c
src/audio/dart/SDL_dart.h
src/audio/dc/SDL_dcaudio.c
src/audio/dc/SDL_dcaudio.h
src/audio/disk/SDL_diskaudio.c
src/audio/disk/SDL_diskaudio.h
src/audio/dma/SDL_dmaaudio.c
src/audio/dma/SDL_dmaaudio.h
src/audio/dmedia/SDL_irixaudio.c
src/audio/dmedia/SDL_irixaudio.h
src/audio/dsp/SDL_dspaudio.c
src/audio/dsp/SDL_dspaudio.h
src/audio/dummy/SDL_dummyaudio.c
src/audio/dummy/SDL_dummyaudio.h
src/audio/esd/SDL_esdaudio.c
src/audio/esd/SDL_esdaudio.h
src/audio/macosx/SDL_coreaudio.c
src/audio/macosx/SDL_coreaudio.h
src/audio/macrom/SDL_romaudio.c
src/audio/macrom/SDL_romaudio.h
src/audio/mint/SDL_mintaudio_dma8.c
src/audio/mint/SDL_mintaudio_gsxb.c
src/audio/mint/SDL_mintaudio_mcsn.c
src/audio/mint/SDL_mintaudio_stfa.c
src/audio/mint/SDL_mintaudio_xbios.c
src/audio/mme/SDL_mmeaudio.c
src/audio/mme/SDL_mmeaudio.h
src/audio/nas/SDL_nasaudio.c
src/audio/nas/SDL_nasaudio.h
src/audio/nto/SDL_nto_audio.c
src/audio/nto/SDL_nto_audio.h
src/audio/paudio/SDL_paudio.c
src/audio/paudio/SDL_paudio.h
src/audio/sun/SDL_sunaudio.c
src/audio/sun/SDL_sunaudio.h
src/audio/ums/SDL_umsaudio.c
src/audio/ums/SDL_umsaudio.h
src/audio/windib/SDL_dibaudio.c
src/audio/windib/SDL_dibaudio.h
src/audio/windx5/SDL_dx5audio.c
src/audio/windx5/SDL_dx5audio.h
src/events/SDL_mouse.c
src/timer/os2/SDL_systimer.c
src/video/SDL_rendercopy.h
test/Makefile.in
test/loopwave.c
test/testaudioinfo.c
test/testmultiaudio.c
--- a/configure.in	Sun Oct 01 16:10:41 2006 +0000
+++ b/configure.in	Tue Oct 17 09:15:21 2006 +0000
@@ -511,9 +511,17 @@
 AC_HELP_STRING([--enable-nas], [support the NAS audio API [[default=yes]]]),
                   , enable_nas=yes)
     if test x$enable_audio = xyes -a x$enable_nas = xyes; then
+        AC_CHECK_HEADER(audio/audiolib.h, have_nas_hdr=yes)
+        AC_CHECK_LIB(audio, AuOpenServer, have_nas_lib=yes)
+
         AC_MSG_CHECKING(for NAS audio support)
         have_nas=no
-        if test -r /usr/X11R6/include/audio/audiolib.h; then
+
+        if test x$have_nas_hdr = xyes -a x$have_nas_lib = xyes; then
+            have_nas=yes
+            NAS_LIBS="-laudio"
+
+        elif test -r /usr/X11R6/include/audio/audiolib.h; then
             have_nas=yes
             NAS_CFLAGS="-I/usr/X11R6/include/"
             NAS_LIBS="-L/usr/X11R6/lib -laudio -lXt"
@@ -525,12 +533,40 @@
             have_nas=yes
             NAS_LIBS="-lnas -lXt"
         fi
+
         AC_MSG_RESULT($have_nas)
+
         if test x$have_nas = xyes; then
+            AC_ARG_ENABLE(nas-shared,
+AC_HELP_STRING([--enable-nas-shared], [dynamically load NAS audio support [[default=yes]]]),
+                          , enable_nas_shared=yes)
+            if test "x`echo $NAS_LIBS | grep -- -L`" = "x"; then
+                if test "x`ls /lib/libaudio.so.* 2> /dev/null`" != "x"; then
+                    NAS_LIBS="-L/lib $NAS_LIBS"
+                elif test "x`ls /usr/lib/libaudio.so.* 2> /dev/null`" != "x"; then
+                    NAS_LIBS="-L/usr/lib $NAS_LIBS"
+                elif test "x`ls /usr/local/lib/libaudio.so.* 2> /dev/null`" != "x"; then
+                    NAS_LIBS="-L/usr/local/lib $NAS_LIBS"
+                fi
+            fi
+            nas_lib_spec=`echo $NAS_LIBS | sed 's/.*-L\([[^ ]]*\).*/\1\/libaudio.so.*/'`
+            nas_lib=`ls -- $nas_lib_spec | sed 's/.*\/\(.*\)/\1/; q'`
+            echo "-- $nas_lib_spec -> $nas_lib"
+
+            if test x$have_loadso != xyes && \
+               test x$enable_nas_shared = xyes; then
+                AC_MSG_WARN([You must have SDL_LoadObject() support for dynamic NAS loading])
+            fi
+            if test x$have_loadso = xyes && \
+               test x$enable_nas_shared = xyes && test x$alsa_lib != x; then
+                AC_DEFINE_UNQUOTED(SDL_AUDIO_DRIVER_NAS_DYNAMIC, "$nas_lib")
+            else
+                EXTRA_LDFLAGS="$EXTRA_LDFLAGS $NAS_LIBS"
+            fi
+
             AC_DEFINE(SDL_AUDIO_DRIVER_NAS)
             SOURCES="$SOURCES $srcdir/src/audio/nas/*.c"
             EXTRA_CFLAGS="$EXTRA_CFLAGS $NAS_CFLAGS"
-            EXTRA_LDFLAGS="$EXTRA_LDFLAGS $NAS_LIBS"
             have_audio=yes
         fi
     fi
@@ -2006,7 +2042,7 @@
                 have_audio=yes
             ;;
             aix)
-                AC_DEFINE(SDL_AUDIO_DRIVER_PAUD)
+                AC_DEFINE(SDL_AUDIO_DRIVER_PAUDIO)
                 SOURCES="$SOURCES $srcdir/src/audio/paudio/*.c"
                 have_audio=yes
             ;;
@@ -2206,7 +2242,7 @@
         CheckBeGL
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
-            AC_DEFINE(SDL_AUDIO_DRIVER_BAUDIO)
+            AC_DEFINE(SDL_AUDIO_DRIVER_BEOSAUDIO)
             SOURCES="$SOURCES $srcdir/src/audio/baudio/*.cc"
             have_audio=yes
         fi
@@ -2323,7 +2359,7 @@
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
         # If either the audio or CD driver is used, add the AudioUnit framework
         if test x$enable_audio = xyes -o x$enable_cdrom = xyes; then
-            EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit"
+            EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreAudio -framework,AudioToolbox -Wl,-framework,AudioUnit"
         fi
         ;;
     *-*-mint*)
--- a/include/SDL_audio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/include/SDL_audio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -153,7 +153,7 @@
 
 /* Function prototypes */
 
-/* These functions return the list of built in video drivers, in the 
+/* These functions return the list of built in audio drivers, in the
  * order that they are normally initialized by default.
  */
 extern DECLSPEC int SDLCALL SDL_GetNumAudioDrivers(void);
@@ -212,7 +212,7 @@
  * may modify the requested size of the audio buffer, you should allocate
  * any local mixing buffers after you open the audio device.
  */
-extern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired,
+extern DECLSPEC int SDLCALL SDL_OpenAudio(const SDL_AudioSpec * desired,
                                           SDL_AudioSpec * obtained);
 
 /*
@@ -228,6 +228,13 @@
 /*
  * Get the number of available devices exposed by the current driver.
  *  Only valid after a successfully initializing the audio subsystem.
+ *  Returns -1 if an explicit list of devices can't be determined; this is
+ *  not an error. For example, if SDL is set up to talk to a remote audio
+ *  server, it can't list every one available on the Internet, but it will
+ *  still allow a specific host to be specified to SDL_OpenAudioDevice().
+ * In many common cases, when this function returns a value <= 0, it can still
+ *  successfully open the default device (NULL for first argument of
+ *  SDL_OpenAudioDevice()).
  */
 extern DECLSPEC int SDLCALL SDL_GetNumAudioDevices(int iscapture);
 
@@ -235,15 +242,28 @@
  * Get the human-readable name of a specific audio device.
  *  Must be a value between 0 and (number of audio devices-1).
  *  Only valid after a successfully initializing the audio subsystem.
+ *  The values returned by this function reflect the latest call to
+ *  SDL_GetNumAudioDevices(); recall that function to redetect available
+ *  hardware.
+ *
+ * The string returned by this function is UTF-8 encoded, read-only, and
+ *  managed internally. You are not to free it. If you need to keep the
+ *  string for any length of time, you should make your own copy of it, as it
+ *  will be invalid next time any of several other SDL functions is called.
  */
-extern DECLSPEC const char *SDLCALL SDL_GetAudioDevice(int index,
-                                                       int iscapture);
+extern DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(int index,
+                                                           int iscapture);
 
 
 /*
- * Open a specific audio device. Passing in a device name of NULL is
- *  equivalent to SDL_OpenAudio(). Returns 0 on error, a valid device ID
- *  on success.
+ * Open a specific audio device. Passing in a device name of NULL requests
+ *  the most reasonable default (and is equivalent to calling SDL_OpenAudio()).
+ * The device name is a UTF-8 string reported by SDL_GetAudioDevice(), but
+ *  some drivers allow arbitrary and driver-specific strings, such as a
+ *  hostname/IP address for a remote audio server, or a filename in the
+ *  diskaudio driver.
+ * Returns 0 on error, a valid device ID that is >= 2 on success.
+ *  SDL_OpenAudio(), unlike this function, always acts on device ID 1.
  */
 extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(const char
                                                               *device,
--- a/include/SDL_config.h.in	Sun Oct 01 16:10:41 2006 +0000
+++ b/include/SDL_config.h.in	Tue Oct 17 09:15:21 2006 +0000
@@ -154,7 +154,7 @@
 #undef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
 #undef SDL_AUDIO_DRIVER_ARTS
 #undef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
-#undef SDL_AUDIO_DRIVER_BAUDIO
+#undef SDL_AUDIO_DRIVER_BEOSAUDIO
 #undef SDL_AUDIO_DRIVER_BSD
 #undef SDL_AUDIO_DRIVER_COREAUDIO
 #undef SDL_AUDIO_DRIVER_DART
@@ -168,9 +168,10 @@
 #undef SDL_AUDIO_DRIVER_MINT
 #undef SDL_AUDIO_DRIVER_MMEAUDIO
 #undef SDL_AUDIO_DRIVER_NAS
+#undef SDL_AUDIO_DRIVER_NAS_DYNAMIC
 #undef SDL_AUDIO_DRIVER_OSS
 #undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H
-#undef SDL_AUDIO_DRIVER_PAUD
+#undef SDL_AUDIO_DRIVER_PAUDIO
 #undef SDL_AUDIO_DRIVER_QNXNTO
 #undef SDL_AUDIO_DRIVER_SNDMGR
 #undef SDL_AUDIO_DRIVER_SUNAUDIO
--- a/include/SDL_thread.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/include/SDL_thread.h	Tue Oct 17 09:15:21 2006 +0000
@@ -91,7 +91,7 @@
 typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
 #endif
 
-extern DECLSPEC SDL_Thread *SDLCALL SDL_CreateThread(int (*fn) (void *),
+extern DECLSPEC SDL_Thread *SDLCALL SDL_CreateThread(int (SDLCALL * f) (void *),
                                                      void *data,
                                                      pfnSDL_CurrentBeginThread
                                                      pfnBeginThread,
--- a/src/SDL_error.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/SDL_error.c	Tue Oct 17 09:15:21 2006 +0000
@@ -28,6 +28,7 @@
 
 /* Routine to get the thread-specific error variable */
 #if SDL_THREADS_DISABLED
+/* !!! FIXME: what does this comment mean? Victim of Search and Replace? */
 /* The  SDL_arraysize(The ),default (non-thread-safe) global error variable */
 static SDL_error SDL_global_error;
 #define SDL_GetErrBuf()	(&SDL_global_error)
--- a/src/audio/SDL_audio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/SDL_audio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -28,11 +28,48 @@
 #include "SDL_audiomem.h"
 #include "SDL_sysaudio.h"
 
-#ifdef __OS2__
-/* We'll need the DosSetPriority() API! */
-#define INCL_DOSPROCESS
-#include <os2.h>
-#endif
+#define _THIS	SDL_AudioDevice *this
+
+static SDL_AudioDriver current_audio;
+static SDL_AudioDevice *open_devices[16];
+
+/* !!! FIXME: These are wordy and unlocalized... */
+#define DEFAULT_OUTPUT_DEVNAME "System audio output device"
+#define DEFAULT_INPUT_DEVNAME "System audio capture device"
+
+
+/*
+ * Not all of these will be compiled and linked in, but it's convenient
+ *  to have a complete list here and saves yet-another block of #ifdefs...
+ *  Please see bootstrap[], below, for the actual #ifdef mess.
+ */
+extern AudioBootStrap BSD_AUDIO_bootstrap;
+extern AudioBootStrap DSP_bootstrap;
+extern AudioBootStrap DMA_bootstrap;
+extern AudioBootStrap ALSA_bootstrap;
+extern AudioBootStrap QNXNTOAUDIO_bootstrap;
+extern AudioBootStrap SUNAUDIO_bootstrap;
+extern AudioBootStrap DMEDIA_bootstrap;
+extern AudioBootStrap ARTS_bootstrap;
+extern AudioBootStrap ESD_bootstrap;
+extern AudioBootStrap NAS_bootstrap;
+extern AudioBootStrap DSOUND_bootstrap;
+extern AudioBootStrap WAVEOUT_bootstrap;
+extern AudioBootStrap PAUDIO_bootstrap;
+extern AudioBootStrap BEOSAUDIO_bootstrap;
+extern AudioBootStrap COREAUDIO_bootstrap;
+extern AudioBootStrap SNDMGR_bootstrap;
+extern AudioBootStrap MINTAUDIO_GSXB_bootstrap;
+extern AudioBootStrap MINTAUDIO_MCSN_bootstrap;
+extern AudioBootStrap MINTAUDIO_STFA_bootstrap;
+extern AudioBootStrap MINTAUDIO_XBIOS_bootstrap;
+extern AudioBootStrap MINTAUDIO_DMA8_bootstrap;
+extern AudioBootStrap DISKAUD_bootstrap;
+extern AudioBootStrap DUMMYAUD_bootstrap;
+extern AudioBootStrap DCAUD_bootstrap;
+extern AudioBootStrap MMEAUDIO_bootstrap;
+extern AudioBootStrap DART_bootstrap;
+
 
 /* Available audio drivers */
 static AudioBootStrap *bootstrap[] = {
@@ -70,11 +107,11 @@
 #if SDL_AUDIO_DRIVER_WAVEOUT
     &WAVEOUT_bootstrap,
 #endif
-#if SDL_AUDIO_DRIVER_PAUD
-    &Paud_bootstrap,
+#if SDL_AUDIO_DRIVER_PAUDIO
+    &PAUDIO_bootstrap,
 #endif
-#if SDL_AUDIO_DRIVER_BAUDIO
-    &BAUDIO_bootstrap,
+#if SDL_AUDIO_DRIVER_BEOSAUDIO
+    &BEOSAUDIO_bootstrap,
 #endif
 #if SDL_AUDIO_DRIVER_COREAUDIO
     &COREAUDIO_bootstrap,
@@ -82,9 +119,6 @@
 #if SDL_AUDIO_DRIVER_SNDMGR
     &SNDMGR_bootstrap,
 #endif
-#if SDL_AUDIO_DRIVER_AHI
-    &AHI_bootstrap,
-#endif
 #if SDL_AUDIO_DRIVER_MINT
     &MINTAUDIO_GSXB_bootstrap,
     &MINTAUDIO_MCSN_bootstrap,
@@ -109,227 +143,201 @@
 #endif
     NULL
 };
-SDL_AudioDevice *current_audio = NULL;
+
+static SDL_AudioDevice *get_audio_device(SDL_AudioDeviceID id)
+{
+    id--;
+    if ( (id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL) ) {
+        SDL_SetError("Invalid audio device ID");
+        return NULL;
+    }
+
+    return open_devices[id];
+}
+
+
+/* stubs for audio drivers that don't need a specific entry point... */
+static int SDL_AudioDetectDevices_Default(int iscapture) { return -1; }
+static void SDL_AudioThreadInit_Default(_THIS) { /* no-op. */ }
+static void SDL_AudioWaitDevice_Default(_THIS) { /* no-op. */ }
+static void SDL_AudioPlayDevice_Default(_THIS) { /* no-op. */ }
+static Uint8 *SDL_AudioGetDeviceBuf_Default(_THIS) { return NULL; }
+static void SDL_AudioWaitDone_Default(_THIS) { /* no-op. */ }
+static void SDL_AudioCloseDevice_Default(_THIS) { /* no-op. */ }
+static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ }
+
+static int
+SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
+{
+    return 0;
+}
+
+static const char *SDL_AudioGetDeviceName_Default(int index, int iscapture)
+{
+    SDL_SetError("No such device");
+    return NULL;
+}
 
-/* Various local functions */
-int SDL_AudioInit(const char *driver_name);
-void SDL_AudioQuit(void);
+static void
+SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
+{
+    if (device->thread && (SDL_ThreadID() == device->threadid)) {
+        return;
+    }
+    SDL_mutexP(device->mixer_lock);
+}
+
+static void
+SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
+{
+    if (device->thread && (SDL_ThreadID() == device->threadid)) {
+        return;
+    }
+    SDL_mutexV(device->mixer_lock);
+}
+
 
-#if SDL_AUDIO_DRIVER_AHI
-static int audio_configured = 0;
-#endif
+static void finalize_audio_entry_points(void)
+{
+    /*
+     * Fill in stub functions for unused driver entry points. This lets us
+     *  blindly call them without having to check for validity first.
+     */
+
+    #define FILL_STUB(x) \
+        if (current_audio.impl.x == NULL) { \
+            current_audio.impl.x = SDL_Audio##x##_Default; \
+        }
+    FILL_STUB(DetectDevices);
+    FILL_STUB(GetDeviceName);
+    FILL_STUB(OpenDevice);
+    FILL_STUB(ThreadInit);
+    FILL_STUB(WaitDevice);
+    FILL_STUB(PlayDevice);
+    FILL_STUB(GetDeviceBuf);
+    FILL_STUB(WaitDone);
+    FILL_STUB(CloseDevice);
+    FILL_STUB(LockDevice);
+    FILL_STUB(UnlockDevice);
+    FILL_STUB(Deinitialize);
+    #undef FILL_STUB
+}
+
 
 /* The general mixing thread function */
 int SDLCALL
-SDL_RunAudio(void *audiop)
+SDL_RunAudio(void *devicep)
 {
-    SDL_AudioDevice *audio = (SDL_AudioDevice *) audiop;
+    SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
+    const int legacy_device = (device == open_devices[0]);
     Uint8 *stream;
     int stream_len;
     void *udata;
     void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
     int silence;
-#if SDL_AUDIO_DRIVER_AHI
-    int started = 0;
-
-/* AmigaOS NEEDS that the audio driver is opened in the thread that uses it! */
-
-    D(bug("Task audio started audio struct:<%lx>...\n", audiop));
-
-    D(bug("Before Openaudio..."));
-    if (audio->OpenAudio(audio, &audio->spec) == -1) {
-        D(bug("Open audio failed...\n"));
-        return (-1);
-    }
-    D(bug("OpenAudio...OK\n"));
-#endif
 
     /* Perform any thread setup */
-    if (audio->ThreadInit) {
-        audio->ThreadInit(audio);
-    }
-    audio->threadid = SDL_ThreadID();
+    device->threadid = SDL_ThreadID();
+    current_audio.impl.ThreadInit(device);
 
     /* Set up the mixing function */
-    fill = audio->spec.callback;
-    udata = audio->spec.userdata;
-
-#if SDL_AUDIO_DRIVER_AHI
-    audio_configured = 1;
+    fill = device->spec.callback;
+    udata = device->spec.userdata;
 
-    D(bug("Audio configured... Checking for conversion\n"));
-    SDL_mutexP(audio->mixer_lock);
-    D(bug("Semaphore obtained...\n"));
-#endif
-
-    if (audio->convert.needed) {
-        if (audio->convert.src_format == AUDIO_U8) {
+    if (device->convert.needed) {
+        if (device->convert.src_format == AUDIO_U8) {
             silence = 0x80;
         } else {
             silence = 0;
         }
-        stream_len = audio->convert.len;
+        stream_len = device->convert.len;
     } else {
-        silence = audio->spec.silence;
-        stream_len = audio->spec.size;
+        silence = device->spec.silence;
+        stream_len = device->spec.size;
     }
 
-#if SDL_AUDIO_DRIVER_AHI
-    SDL_mutexV(audio->mixer_lock);
-    D(bug("Entering audio loop...\n"));
-#endif
-
-#ifdef __OS2__
-    /* Increase the priority of this thread to make sure that
-       the audio will be continuous all the time! */
-#ifdef USE_DOSSETPRIORITY
-    if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) {
-#ifdef DEBUG_BUILD
-        printf
-            ("[SDL_RunAudio] : Setting priority to TimeCritical+0! (TID%d)\n",
-             SDL_ThreadID());
-#endif
-        DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
-    } else {
-#ifdef DEBUG_BUILD
-        printf
-            ("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n",
-             SDL_ThreadID());
-#endif
-        DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
-    }
-#endif
-#endif
-
     /* Loop, filling the audio buffers */
-    while (audio->enabled) {
+    while (device->enabled) {
 
         /* Fill the current buffer with sound */
-        if (audio->convert.needed) {
-            if (audio->convert.buf) {
-                stream = audio->convert.buf;
+        if (device->convert.needed) {
+            if (device->convert.buf) {
+                stream = device->convert.buf;
             } else {
                 continue;
             }
         } else {
-            stream = audio->GetAudioBuf(audio);
+            stream = current_audio.impl.GetDeviceBuf(device);
             if (stream == NULL) {
-                stream = audio->fake_stream;
+                stream = device->fake_stream;
             }
         }
-        SDL_memset(stream, silence, stream_len);
 
-        if (!audio->paused) {
-            SDL_mutexP(audio->mixer_lock);
+        /* New code should fill buffer or set it to silence themselves. */
+        if (legacy_device) {
+            SDL_memset(stream, silence, stream_len);
+        }
+
+        if (!device->paused) {
+            SDL_mutexP(device->mixer_lock);
             (*fill) (udata, stream, stream_len);
-            SDL_mutexV(audio->mixer_lock);
+            SDL_mutexV(device->mixer_lock);
         }
 
         /* Convert the audio if necessary */
-        if (audio->convert.needed) {
-            SDL_ConvertAudio(&audio->convert);
-            stream = audio->GetAudioBuf(audio);
+        if (device->convert.needed) {
+            SDL_ConvertAudio(&device->convert);
+            stream = current_audio.impl.GetDeviceBuf(device);
             if (stream == NULL) {
-                stream = audio->fake_stream;
+                stream = device->fake_stream;
             }
-            SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt);
+            SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt);
         }
 
         /* Ready current buffer for play and change current buffer */
-        if (stream != audio->fake_stream) {
-            audio->PlayAudio(audio);
+        if (stream != device->fake_stream) {
+            current_audio.impl.PlayDevice(device);
         }
 
         /* Wait for an audio buffer to become available */
-        if (stream == audio->fake_stream) {
-            SDL_Delay((audio->spec.samples * 1000) / audio->spec.freq);
+        if (stream == device->fake_stream) {
+            SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
         } else {
-            audio->WaitAudio(audio);
+            current_audio.impl.WaitDevice(device);
         }
     }
 
     /* Wait for the audio to drain.. */
-    if (audio->WaitDone) {
-        audio->WaitDone(audio);
-    }
-#if SDL_AUDIO_DRIVER_AHI
-    D(bug("WaitAudio...Done\n"));
-
-    audio->CloseAudio(audio);
+    current_audio.impl.WaitDone(device);
 
-    D(bug("CloseAudio..Done, subtask exiting...\n"));
-    audio_configured = 0;
-#endif
-#ifdef __OS2__
-#ifdef DEBUG_BUILD
-    printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID());
-#endif
-#endif
     return (0);
 }
 
-static void
-SDL_LockAudio_Default(SDL_AudioDevice * audio)
-{
-    if (audio->thread && (SDL_ThreadID() == audio->threadid)) {
-        return;
-    }
-    SDL_mutexP(audio->mixer_lock);
-}
-
-static void
-SDL_UnlockAudio_Default(SDL_AudioDevice * audio)
-{
-    if (audio->thread && (SDL_ThreadID() == audio->threadid)) {
-        return;
-    }
-    SDL_mutexV(audio->mixer_lock);
-}
 
 static SDL_AudioFormat
 SDL_ParseAudioFormat(const char *string)
 {
-    SDL_AudioFormat format = 0;
-
-    switch (*string) {
-    case 'U':
-        ++string;
-        format |= 0x0000;
-        break;
-    case 'S':
-        ++string;
-        format |= 0x8000;
-        break;
-    default:
-        return 0;
-    }
-    switch (SDL_atoi(string)) {
-    case 8:
-        string += 1;
-        format |= 8;
-        break;
-    case 16:
-        string += 2;
-        format |= 16;
-        if (SDL_strcmp(string, "LSB") == 0
-#if SDL_BYTEORDER == SDL_LIL_ENDIAN
-            || SDL_strcmp(string, "SYS") == 0
-#endif
-            ) {
-            format |= 0x0000;
-        }
-        if (SDL_strcmp(string, "MSB") == 0
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
-            || SDL_strcmp(string, "SYS") == 0
-#endif
-            ) {
-            format |= 0x1000;
-        }
-        break;
-    default:
-        return 0;
-    }
-    return format;
+    #define CHECK_FMT_STRING(x) if (strcmp(string, #x) == 0) return AUDIO_##x
+    CHECK_FMT_STRING(U8);
+    CHECK_FMT_STRING(S8);
+    CHECK_FMT_STRING(U16LSB);
+    CHECK_FMT_STRING(S16LSB);
+    CHECK_FMT_STRING(U16MSB);
+    CHECK_FMT_STRING(S16MSB);
+    CHECK_FMT_STRING(U16SYS);
+    CHECK_FMT_STRING(S16SYS);
+    CHECK_FMT_STRING(U16);
+    CHECK_FMT_STRING(S16);
+    CHECK_FMT_STRING(S32LSB);
+    CHECK_FMT_STRING(S32MSB);
+    CHECK_FMT_STRING(S32SYS);
+    CHECK_FMT_STRING(S32);
+    CHECK_FMT_STRING(F32LSB);
+    CHECK_FMT_STRING(F32MSB);
+    CHECK_FMT_STRING(F32SYS);
+    CHECK_FMT_STRING(F32);
+    #undef CHECK_FMT_STRING
+    return 0;
 }
 
 int
@@ -350,92 +358,53 @@
 int
 SDL_AudioInit(const char *driver_name)
 {
-    SDL_AudioDevice *audio;
-    int i = 0, idx;
+    int i = 0;
+    int initialized = 0;
+    int tried_to_init = 0;
 
-    /* Check to make sure we don't overwrite 'current_audio' */
-    if (current_audio != NULL) {
-        SDL_AudioQuit();
+    if (SDL_WasInit(SDL_INIT_AUDIO)) {
+        SDL_AudioQuit();  /* shutdown driver if already running. */
     }
 
+    SDL_memset(&current_audio, '\0', sizeof (current_audio));
+    SDL_memset(open_devices, '\0', sizeof (open_devices));
+
     /* Select the proper audio driver */
-    audio = NULL;
-    idx = 0;
     if (driver_name == NULL) {
         driver_name = SDL_getenv("SDL_AUDIODRIVER");
     }
-#if SDL_AUDIO_DRIVER_ESD
-    if ((driver_name == NULL) && (SDL_getenv("ESPEAKER") != NULL)) {
-        /* Ahem, we know that if ESPEAKER is set, user probably wants
-           to use ESD, but don't start it if it's not already running.
-           This probably isn't the place to do this, but... Shh! :)
-         */
-        for (i = 0; bootstrap[i]; ++i) {
-            if (SDL_strcasecmp(bootstrap[i]->name, "esd") == 0) {
-#ifdef HAVE_PUTENV
-                const char *esd_no_spawn;
+
+    for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
+        /* make sure we should even try this driver before doing so... */
+        const AudioBootStrap *backend = bootstrap[i];
+        if ( ((driver_name) && (SDL_strcasecmp(backend->name, driver_name))) ||
+             ((!driver_name) && (backend->demand_only)) ) {
+            continue;
+        }
 
-                /* Don't start ESD if it's not running */
-                esd_no_spawn = getenv("ESD_NO_SPAWN");
-                if (esd_no_spawn == NULL) {
-                    putenv("ESD_NO_SPAWN=1");
-                }
-#endif
-                if (bootstrap[i]->available()) {
-                    audio = bootstrap[i]->create(0);
-                    break;
-                }
-#ifdef HAVE_UNSETENV
-                if (esd_no_spawn == NULL) {
-                    unsetenv("ESD_NO_SPAWN");
-                }
-#endif
-            }
-        }
+        tried_to_init = 1;
+        SDL_memset(&current_audio, 0, sizeof (current_audio));
+        current_audio.name = backend->name;
+        current_audio.desc = backend->desc;
+        initialized = backend->init(&current_audio.impl);
     }
-#endif /* SDL_AUDIO_DRIVER_ESD */
-    if (audio == NULL) {
-        if (driver_name != NULL) {
-            for (i = 0; bootstrap[i]; ++i) {
-                if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) {
-                    if (bootstrap[i]->available()) {
-                        audio = bootstrap[i]->create(idx);
-                    }
-                    break;
-                }
-            }
-        } else {
-            for (i = 0; bootstrap[i]; ++i) {
-                if (bootstrap[i]->available()) {
-                    audio = bootstrap[i]->create(idx);
-                    if (audio != NULL) {
-                        break;
-                    }
-                }
-            }
-        }
-        if (audio == NULL) {
+
+    if (!initialized) {
+        /* specific drivers will set the error message if they fail... */
+        if (!tried_to_init) {
             if (driver_name) {
                 SDL_SetError("%s not available", driver_name);
             } else {
                 SDL_SetError("No available audio device");
             }
-#if 0
-            /* Don't fail SDL_Init() if audio isn't available.
-               SDL_OpenAudio() will handle it at that point.  *sigh*
-             */
-            return (-1);
-#endif
         }
+
+        SDL_memset(&current_audio, 0, sizeof (current_audio));
+        return (-1);  /* No driver was available, so fail. */
     }
-    current_audio = audio;
-    if (current_audio) {
-        current_audio->name = bootstrap[i]->name;
-        if (!current_audio->LockAudio && !current_audio->UnlockAudio) {
-            current_audio->LockAudio = SDL_LockAudio_Default;
-            current_audio->UnlockAudio = SDL_UnlockAudio_Default;
-        }
-    }
+
+    finalize_audio_entry_points();
+
     return (0);
 }
 
@@ -445,222 +414,369 @@
 const char *
 SDL_GetCurrentAudioDriver()
 {
-    if (current_audio) {
-        return current_audio->name;
-    }
-    return (NULL);
+    return current_audio.name;
 }
 
+
 int
-SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
+SDL_GetNumAudioDevices(int iscapture)
 {
-    SDL_AudioDevice *audio;
-    const char *env;
+    if (!SDL_WasInit(SDL_INIT_AUDIO)) {
+        return -1;
+    }
+    if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
+        return 0;
+    }
+
+    if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
+        return 1;
+    }
+
+    if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
+        return 1;
+    }
+
+    return current_audio.impl.DetectDevices(iscapture);
+}
+
 
-    /* Start up the audio driver, if necessary */
-    if (!current_audio) {
-        if ((SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) ||
-            (current_audio == NULL)) {
-            return (-1);
-        }
+const char *
+SDL_GetAudioDeviceName(int index, int iscapture)
+{
+    if (!SDL_WasInit(SDL_INIT_AUDIO)) {
+        SDL_SetError("Audio subsystem is not initialized");
+        return NULL;
+    }
+
+    if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
+        SDL_SetError("No capture support");
+        return NULL;
     }
-    audio = current_audio;
+
+    if (index < 0) {
+        SDL_SetError("No such device");
+        return NULL;
+    }
 
-    if (audio->opened) {
-        SDL_SetError("Audio device is already opened");
-        return (-1);
+    if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
+        return DEFAULT_INPUT_DEVNAME;
+    }
+
+    if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
+        return DEFAULT_OUTPUT_DEVNAME;
     }
 
-    /* Verify some parameters */
-    if (desired->freq == 0) {
-        env = SDL_getenv("SDL_AUDIO_FREQUENCY");
-        if (env) {
-            desired->freq = SDL_atoi(env);
+    return current_audio.impl.GetDeviceName(index, iscapture);
+}
+
+
+static void
+close_audio_device(SDL_AudioDevice *device)
+{
+    device->enabled = 0;
+    if (device->thread != NULL) {
+        SDL_WaitThread(device->thread, NULL);
+    }
+    if (device->mixer_lock != NULL) {
+        SDL_DestroyMutex(device->mixer_lock);
+    }
+    if (device->fake_stream != NULL) {
+        SDL_FreeAudioMem(device->fake_stream);
+    }
+    if (device->convert.needed) {
+        SDL_FreeAudioMem(device->convert.buf);
+    }
+    if (device->opened) {
+        current_audio.impl.CloseDevice(device);
+        device->opened = 0;
+    }
+    SDL_FreeAudioMem(device);
+}
+
+
+/*
+ * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
+ *  Fills in a sanitized copy in (prepared).
+ *  Returns non-zero if okay, zero on fatal parameters in (orig).
+ */
+static int
+prepare_audiospec(const SDL_AudioSpec *orig, SDL_AudioSpec *prepared)
+{
+    SDL_memcpy(prepared, orig, sizeof (SDL_AudioSpec));
+
+    if (orig->callback == NULL) {
+        SDL_SetError("SDL_OpenAudio() passed a NULL callback");
+        return 0;
+    }
+
+    if (orig->freq == 0) {
+        const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
+        if ( (!env) || ((prepared->freq = SDL_atoi(env)) == 0) ) {
+            prepared->freq = 22050;  /* a reasonable default */
         }
     }
-    if (desired->freq == 0) {
-        /* Pick some default audio frequency */
-        desired->freq = 22050;
-    }
-    if (desired->format == 0) {
-        env = SDL_getenv("SDL_AUDIO_FORMAT");
-        if (env) {
-            desired->format = SDL_ParseAudioFormat(env);
+
+    if (orig->format == 0) {
+        const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
+        if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
+            prepared->format = AUDIO_S16;  /* a reasonable default */
         }
     }
-    if (desired->format == 0) {
-        /* Pick some default audio format */
-        desired->format = AUDIO_S16;
+
+    switch (orig->channels) {
+    case 0: {
+        const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
+        if ( (!env) || ((prepared->channels = SDL_atoi(env)) == 0) ) {
+            prepared->channels = 2;  /* a reasonable default */
+        }
+        break;
     }
-    if (desired->channels == 0) {
-        env = SDL_getenv("SDL_AUDIO_CHANNELS");
-        if (env) {
-            desired->channels = (Uint8) SDL_atoi(env);
-        }
-    }
-    if (desired->channels == 0) {
-        /* Pick a default number of channels */
-        desired->channels = 2;
-    }
-    switch (desired->channels) {
     case 1:                    /* Mono */
     case 2:                    /* Stereo */
     case 4:                    /* surround */
     case 6:                    /* surround with center and lfe */
         break;
     default:
-        SDL_SetError("1 (mono) and 2 (stereo) channels supported");
-        return (-1);
+        SDL_SetError("Unsupported number of audio channels.");
+        return 0;
     }
-    if (desired->samples == 0) {
-        env = SDL_getenv("SDL_AUDIO_SAMPLES");
-        if (env) {
-            desired->samples = (Uint16) SDL_atoi(env);
+
+    if (orig->samples == 0) {
+        const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
+        if ( (!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0) ) {
+            /* Pick a default of ~46 ms at desired frequency */
+            /* !!! FIXME: remove this when the non-Po2 resampling is in. */
+            const int samples = (prepared->freq / 1000) * 46;
+            int power2 = 1;
+            while (power2 < samples) {
+                power2 *= 2;
+            }
+            prepared->samples = power2;
         }
     }
-    if (desired->samples == 0) {
-        /* Pick a default of ~46 ms at desired frequency */
-        int samples = (desired->freq / 1000) * 46;
-        int power2 = 1;
-        while (power2 < samples) {
-            power2 *= 2;
-        }
-        desired->samples = power2;
-    }
-    if (desired->callback == NULL) {
-        SDL_SetError("SDL_OpenAudio() passed a NULL callback");
-        return (-1);
-    }
-#if defined(__MINT__) && SDL_THREADS_DISABLED
-    /* Uses interrupt driven audio, without thread */
-#else
-    /* Create a semaphore for locking the sound buffers */
-    audio->mixer_lock = SDL_CreateMutex();
-    if (audio->mixer_lock == NULL) {
-        SDL_SetError("Couldn't create mixer lock");
-        SDL_CloseAudio();
-        return (-1);
-    }
-#endif /* __MINT__ */
 
     /* Calculate the silence and size of the audio specification */
-    SDL_CalculateAudioSpec(desired);
-
-    /* Open the audio subsystem */
-    SDL_memcpy(&audio->spec, desired, sizeof(audio->spec));
-    audio->convert.needed = 0;
-    audio->enabled = 1;
-    audio->paused = 1;
-
-#if !SDL_AUDIO_DRIVER_AHI
+    SDL_CalculateAudioSpec(prepared);
 
-/* AmigaOS opens audio inside the main loop */
-    audio->opened = audio->OpenAudio(audio, &audio->spec) + 1;
-
-    if (!audio->opened) {
-        SDL_CloseAudio();
-        return (-1);
-    }
-#else
-    D(bug("Locking semaphore..."));
-    SDL_mutexP(audio->mixer_lock);
+    return 1;
+}
 
 
-    audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
-    D(bug("Created thread...\n"));
+static SDL_AudioDeviceID
+open_audio_device(const char *devname, int iscapture,
+                    const SDL_AudioSpec *_desired, SDL_AudioSpec *obtained,
+                    int min_id)
+{
+    SDL_AudioDeviceID id = 0;
+    SDL_AudioSpec desired;
+    SDL_AudioDevice *device;
+    int i = 0;
 
-    if (audio->thread == NULL) {
-        SDL_mutexV(audio->mixer_lock);
-        SDL_CloseAudio();
-        SDL_SetError("Couldn't create audio thread");
-        return (-1);
+    if (!SDL_WasInit(SDL_INIT_AUDIO)) {
+        SDL_SetError("Audio subsystem is not initialized");
+        return 0;
+    }
+
+    if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
+        SDL_SetError("No capture support");
+        return 0;
+    }
+
+    if (!prepare_audiospec(_desired, &desired)) {
+        return 0;
+    }
+
+    /* If app doesn't care about a specific device, let the user override. */
+    if (devname == NULL) {
+        devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
     }
 
-    while (!audio_configured)
-        SDL_Delay(100);
-#endif
+    /*
+     * Catch device names at the high level for the simple case...
+     * This lets us have a basic "device enumeration" for systems that
+     *  don't have multiple devices, but makes sure the device name is
+     *  always NULL when it hits the low level.
+     *
+     * Also make sure that the simple case prevents multiple simultaneous
+     *  opens of the default system device.
+     */
+
+    if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
+        if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
+            SDL_SetError("No such device");
+            return 0;
+        }
+        devname = NULL;
+
+        for (i = 0; i < SDL_arraysize(open_devices); i++) {
+            if ((open_devices[i]) && (open_devices[i]->iscapture)) {
+                SDL_SetError("Audio device already open");
+                return 0;
+            }
+        }
+    }
+
+    if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
+        if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
+            SDL_SetError("No such device");
+            return 0;
+        }
+        devname = NULL;
+
+        for (i = 0; i < SDL_arraysize(open_devices); i++) {
+            if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
+                SDL_SetError("Audio device already open");
+                return 0;
+            }
+        }
+    }
+
+    device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof (SDL_AudioDevice));
+    if (device == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(device, '\0', sizeof (SDL_AudioDevice));
+    SDL_memcpy(&device->spec, &desired, sizeof (SDL_AudioSpec));
+    device->enabled = 1;
+    device->paused = 1;
+    device->iscapture = iscapture;
+
+    /* Create a semaphore for locking the sound buffers */
+    if (!current_audio.impl.SkipMixerLock) {
+        device->mixer_lock = SDL_CreateMutex();
+        if (device->mixer_lock == NULL) {
+            close_audio_device(device);
+            SDL_SetError("Couldn't create mixer lock");
+            return 0;
+        }
+    }
+
+    if (!current_audio.impl.OpenDevice(device, devname, iscapture)) {
+        close_audio_device(device);
+        return 0;
+    }
+    device->opened = 1;
 
     /* If the audio driver changes the buffer size, accept it */
-    if (audio->spec.samples != desired->samples) {
-        desired->samples = audio->spec.samples;
-        SDL_CalculateAudioSpec(desired);
+    if (device->spec.samples != desired.samples) {
+        desired.samples = device->spec.samples;
+        SDL_CalculateAudioSpec(&device->spec);
     }
 
     /* Allocate a fake audio memory buffer */
-    audio->fake_stream = SDL_AllocAudioMem(audio->spec.size);
-    if (audio->fake_stream == NULL) {
-        SDL_CloseAudio();
+    device->fake_stream = SDL_AllocAudioMem(device->spec.size);
+    if (device->fake_stream == NULL) {
+        close_audio_device(device);
         SDL_OutOfMemory();
-        return (-1);
+        return 0;
     }
 
     /* See if we need to do any conversion */
     if (obtained != NULL) {
-        SDL_memcpy(obtained, &audio->spec, sizeof(audio->spec));
-    } else if (desired->freq != audio->spec.freq ||
-               desired->format != audio->spec.format ||
-               desired->channels != audio->spec.channels) {
+        SDL_memcpy(obtained, &device->spec, sizeof(SDL_AudioSpec));
+    } else if (desired.freq != device->spec.freq ||
+               desired.format != device->spec.format ||
+               desired.channels != device->spec.channels) {
         /* Build an audio conversion block */
-        if (SDL_BuildAudioCVT(&audio->convert,
-                              desired->format, desired->channels,
-                              desired->freq,
-                              audio->spec.format, audio->spec.channels,
-                              audio->spec.freq) < 0) {
-            SDL_CloseAudio();
-            return (-1);
+        if (SDL_BuildAudioCVT(&device->convert,
+                              desired.format, desired.channels,
+                              desired.freq,
+                              device->spec.format, device->spec.channels,
+                              device->spec.freq) < 0) {
+            close_audio_device(device);
+            return 0;
         }
-        if (audio->convert.needed) {
-            audio->convert.len = desired->size;
-            audio->convert.buf =
-                (Uint8 *) SDL_AllocAudioMem(audio->convert.len *
-                                            audio->convert.len_mult);
-            if (audio->convert.buf == NULL) {
-                SDL_CloseAudio();
+        if (device->convert.needed) {
+            device->convert.len = desired.size;
+            device->convert.buf =
+                (Uint8 *) SDL_AllocAudioMem(device->convert.len *
+                                            device->convert.len_mult);
+            if (device->convert.buf == NULL) {
+                close_audio_device(device);
                 SDL_OutOfMemory();
-                return (-1);
+                return 0;
             }
         }
     }
-#if !SDL_AUDIO_DRIVER_AHI
+
+    /* Find an available device ID and store the structure... */
+    for (id = min_id-1; id < SDL_arraysize(open_devices); id++) {
+        if (open_devices[id] == NULL) {
+            open_devices[id] = device;
+            break;
+        }
+    }
+
+    if (id == SDL_arraysize(open_devices)) {
+        SDL_SetError("Too many open audio devices");
+        close_audio_device(device);
+        return 0;
+    }
+
     /* Start the audio thread if necessary */
-    switch (audio->opened) {
-    case 1:
+    if (!current_audio.impl.ProvidesOwnCallbackThread) {
         /* Start the audio thread */
+/* !!! FIXME: this is nasty. */
 #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC)
 #undef SDL_CreateThread
-        audio->thread = SDL_CreateThread(SDL_RunAudio, audio, NULL, NULL);
+        device->thread = SDL_CreateThread(SDL_RunAudio, device, NULL, NULL);
 #else
-        audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
+        device->thread = SDL_CreateThread(SDL_RunAudio, device);
 #endif
-        if (audio->thread == NULL) {
-            SDL_CloseAudio();
+        if (device->thread == NULL) {
+            SDL_CloseAudioDevice(id+1);
             SDL_SetError("Couldn't create audio thread");
+            return 0;
+        }
+    }
+
+    return id+1;
+}
+
+
+int
+SDL_OpenAudio(const SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
+{
+    SDL_AudioDeviceID id = 0;
+
+    /* Start up the audio driver, if necessary. This is legacy behaviour! */
+    if (!SDL_WasInit(SDL_INIT_AUDIO)) {
+        if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
             return (-1);
         }
-        break;
+    }
 
-    default:
-        /* The audio is now playing */
-        break;
+    /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
+    if (open_devices[0] != NULL) {
+        SDL_SetError("Audio device is already opened");
+        return (-1);
     }
-#else
-    SDL_mutexV(audio->mixer_lock);
-    D(bug("SDL_OpenAudio USCITA...\n"));
+
+    id = open_audio_device(NULL, 0, desired, obtained, 1);
+    if (id > 1) {  /* this should never happen in theory... */
+        SDL_CloseAudioDevice(id);
+        SDL_SetError("Internal error");  /* MUST be Device ID #1! */
+        return (-1);
+    }
 
-#endif
+    return ((id == 0) ? -1 : 0);
+}
 
-    return (0);
+SDL_AudioDeviceID
+SDL_OpenAudioDevice(const char *device, int iscapture,
+                    const SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
+{
+    return open_audio_device(device, iscapture, desired, obtained, 2);
 }
 
 SDL_audiostatus
-SDL_GetAudioStatus(void)
+SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
 {
-    SDL_AudioDevice *audio = current_audio;
-    SDL_audiostatus status;
-
-    status = SDL_AUDIO_STOPPED;
-    if (audio && audio->enabled) {
-        if (audio->paused) {
+    SDL_AudioDevice *device = get_audio_device(devid);
+    SDL_audiostatus status = SDL_AUDIO_STOPPED;
+    if (device && device->enabled) {
+        if (device->paused) {
             status = SDL_AUDIO_PAUSED;
         } else {
             status = SDL_AUDIO_PLAYING;
@@ -669,74 +785,89 @@
     return (status);
 }
 
+
+SDL_audiostatus
+SDL_GetAudioStatus(void)
+{
+    return SDL_GetAudioDeviceStatus(1);
+}
+
+void
+SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
+{
+    SDL_AudioDevice *device = get_audio_device(devid);
+    if (device) {
+        device->paused = pause_on;
+    }
+}
+
 void
 SDL_PauseAudio(int pause_on)
 {
-    SDL_AudioDevice *audio = current_audio;
+    SDL_PauseAudioDevice(1, pause_on);
+}
+
 
-    if (audio) {
-        audio->paused = pause_on;
+void
+SDL_LockAudioDevice(SDL_AudioDeviceID devid)
+{
+    /* Obtain a lock on the mixing buffers */
+    SDL_AudioDevice *device = get_audio_device(devid);
+    if (device) {
+        current_audio.impl.LockDevice(device);
     }
 }
 
 void
 SDL_LockAudio(void)
 {
-    SDL_AudioDevice *audio = current_audio;
+    SDL_LockAudioDevice(1);
+}
 
+void
+SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
+{
     /* Obtain a lock on the mixing buffers */
-    if (audio && audio->LockAudio) {
-        audio->LockAudio(audio);
+    SDL_AudioDevice *device = get_audio_device(devid);
+    if (device) {
+        current_audio.impl.UnlockDevice(device);
     }
 }
 
 void
 SDL_UnlockAudio(void)
 {
-    SDL_AudioDevice *audio = current_audio;
+    SDL_UnlockAudioDevice(1);
+}
 
-    /* Release lock on the mixing buffers */
-    if (audio && audio->UnlockAudio) {
-        audio->UnlockAudio(audio);
+void
+SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
+{
+    SDL_AudioDevice *device = get_audio_device(devid);
+    if (device) {
+        close_audio_device(device);
+        open_devices[devid-1] = NULL;
     }
 }
 
 void
 SDL_CloseAudio(void)
 {
-    SDL_QuitSubSystem(SDL_INIT_AUDIO);
+    SDL_CloseAudioDevice(1);
 }
 
 void
 SDL_AudioQuit(void)
 {
-    SDL_AudioDevice *audio = current_audio;
+    SDL_AudioDeviceID i;
+    for (i = 0; i < SDL_arraysize(open_devices); i++) {
+        SDL_CloseAudioDevice(i);
+    }
 
-    if (audio) {
-        audio->enabled = 0;
-        if (audio->thread != NULL) {
-            SDL_WaitThread(audio->thread, NULL);
-        }
-        if (audio->mixer_lock != NULL) {
-            SDL_DestroyMutex(audio->mixer_lock);
-        }
-        if (audio->fake_stream != NULL) {
-            SDL_FreeAudioMem(audio->fake_stream);
-        }
-        if (audio->convert.needed) {
-            SDL_FreeAudioMem(audio->convert.buf);
-
-        }
-#if !SDL_AUDIO_DRIVER_AHI
-        if (audio->opened) {
-            audio->CloseAudio(audio);
-            audio->opened = 0;
-        }
-#endif
-        /* Free the driver data */
-        audio->free(audio);
-        current_audio = NULL;
-    }
+    /* Free the driver data */
+    current_audio.impl.Deinitialize();
+    SDL_memset(&current_audio, '\0', sizeof (current_audio));
+    SDL_memset(open_devices, '\0', sizeof (open_devices));
 }
 
 #define NUM_FORMATS 10
@@ -797,9 +928,30 @@
         spec->silence = 0x00;
         break;
     }
-    spec->size = (spec->format & 0xFF) / 8;
+    spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
     spec->size *= spec->channels;
     spec->size *= spec->samples;
 }
 
+
+/*
+ * Moved here from SDL_mixer.c, since it relies on internals of an opened
+ *  audio device (and is deprecated, by the way!).
+ */
+void
+SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
+{
+    /* Mix the user-level audio format */
+    SDL_AudioDevice *device = get_audio_device(1);
+    if (device != NULL) {
+        SDL_AudioFormat format;
+        if (device->convert.needed) {
+            format = device->convert.src_format;
+        } else {
+            format = device->spec.format;
+        }
+        SDL_MixAudioFormat(dst, src, format, len, volume);
+    }
+}
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/SDL_audiocvt.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/SDL_audiocvt.c	Tue Oct 17 09:15:21 2006 +0000
@@ -159,21 +159,19 @@
             float *dst = (float *) cvt->buf;
             if (SDL_AUDIO_ISBIGENDIAN(format)) {
                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
-                    float src1, src2;
-                    src1 = SDL_SwapFloatBE(src[0]);
-                    src2 = SDL_SwapFloatBE(src[1]);
+                    const float src1 = SDL_SwapFloatBE(src[0]);
+                    const float src2 = SDL_SwapFloatBE(src[1]);
                     const double added = ((double) src1) + ((double) src2);
-                    src1 = (float) (added * 0.5);
-                    *(dst++) = SDL_SwapFloatBE(src1);
+                    const float halved = (float) (added * 0.5);
+                    *(dst++) = SDL_SwapFloatBE(halved);
                 }
             } else {
                 for (i = cvt->len_cvt / 8; i; --i, src += 2) {
-                    float src1, src2;
-                    src1 = SDL_SwapFloatLE(src[0]);
-                    src2 = SDL_SwapFloatLE(src[1]);
+                    const float src1 = SDL_SwapFloatLE(src[0]);
+                    const float src2 = SDL_SwapFloatLE(src[1]);
                     const double added = ((double) src1) + ((double) src2);
-                    src1 = (float) (added * 0.5);
-                    *(dst++) = SDL_SwapFloatLE(src1);
+                    const float halved = (float) (added * 0.5);
+                    *(dst++) = SDL_SwapFloatLE(halved);
                 }
             }
         }
--- a/src/audio/SDL_audiodev.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/SDL_audiodev.c	Tue Oct 17 09:15:21 2006 +0000
@@ -46,14 +46,63 @@
 #define _PATH_DEV_AUDIO	"/dev/audio"
 #endif
 
+static inline void
+test_device(const char *fname, int flags, int (*test)(int fd),
+            char ***devices, int *devCount)
+{
+    struct stat sb;
+    if ( (stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode)) ) {
+        int audio_fd = open(fname, flags, 0);
+        if ( (audio_fd >= 0) && (test(audio_fd)) ) {
+            void *p = SDL_realloc(*devices, ((*devCount)+1) * sizeof (char *));
+            if (p != NULL) {
+                size_t len = strlen(fname) + 1;
+                char *str = (char *) SDL_malloc(len);
+                *devices = (char **) p;
+                if (str != NULL) {
+                    SDL_strlcpy(str, fname, len);
+                    (*devices)[(*devCount)++] = str;
+                }
+            }
+            close(audio_fd);
+        }
+    }
+}
 
-int
-SDL_OpenAudioPath(char *path, int maxlen, int flags, int classic)
+void
+SDL_FreeUnixAudioDevices(char ***devices, int *devCount)
+{
+    int i = *devCount;
+    if ((i > 0) && (*devices != NULL)) {
+        while (i--) {
+            SDL_free( (*devices)[*devCount] );
+        }
+    }
+
+    if (*devices != NULL) {
+        SDL_free(*devices);
+    }
+
+    *devices = NULL;
+    *devCount = 0;
+}
+
+static int
+test_stub(int fd)
+{
+    return 1;
+}
+
+void
+SDL_EnumUnixAudioDevices(int flags, int classic, int (*test)(int fd),
+                         char ***devices, int *devCount)
 {
     const char *audiodev;
-    int audio_fd;
     char audiopath[1024];
 
+    if (test == NULL)
+        test = test_stub;
+
     /* Figure out what our audio device is */
     if (((audiodev = SDL_getenv("SDL_PATH_DSP")) == NULL) &&
         ((audiodev = SDL_getenv("AUDIODEV")) == NULL)) {
@@ -72,111 +121,16 @@
             }
         }
     }
-    audio_fd = open(audiodev, flags, 0);
-
-    /* If the first open fails, look for other devices */
-    if ((audio_fd < 0) && (SDL_strlen(audiodev) < (sizeof(audiopath) - 3))) {
-        int exists, instance;
-        struct stat sb;
-
-        instance = 1;
-        do {                    /* Don't use errno ENOENT - it may not be thread-safe */
-            SDL_snprintf(audiopath, SDL_arraysize(audiopath),
-                         "%s%d", audiodev, instance++);
-            exists = 0;
-            if (stat(audiopath, &sb) == 0) {
-                exists = 1;
-                audio_fd = open(audiopath, flags, 0);
-            }
-        }
-        while (exists && (audio_fd < 0));
-        audiodev = audiopath;
-    }
-    if (path != NULL) {
-        SDL_strlcpy(path, audiodev, maxlen);
-        path[maxlen - 1] = '\0';
-    }
-    return (audio_fd);
-}
-
-#elif SDL_AUDIO_DRIVER_PAUD
-
-/* Get the name of the audio device we use for output */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "SDL_stdinc.h"
-#include "SDL_audiodev_c.h"
-
-#ifndef _PATH_DEV_DSP
-#define _PATH_DEV_DSP	"/dev/%caud%c/%c"
-#endif
+    test_device(audiodev, flags, test, devices, devCount);
 
-char devsettings[][3] = {
-    {'p', '0', '1'}, {'p', '0', '2'}, {'p', '0', '3'}, {'p', '0', '4'},
-    {'p', '1', '1'}, {'p', '1', '2'}, {'p', '1', '3'}, {'p', '1', '4'},
-    {'p', '2', '1'}, {'p', '2', '2'}, {'p', '2', '3'}, {'p', '2', '4'},
-    {'p', '3', '1'}, {'p', '3', '2'}, {'p', '3', '3'}, {'p', '3', '4'},
-    {'b', '0', '1'}, {'b', '0', '2'}, {'b', '0', '3'}, {'b', '0', '4'},
-    {'b', '1', '1'}, {'b', '1', '2'}, {'b', '1', '3'}, {'b', '1', '4'},
-    {'b', '2', '1'}, {'b', '2', '2'}, {'b', '2', '3'}, {'b', '2', '4'},
-    {'b', '3', '1'}, {'b', '3', '2'}, {'b', '3', '3'}, {'b', '3', '4'},
-    {'\0', '\0', '\0'}
-};
-
-static int
-OpenUserDefinedDevice(char *path, int maxlen, int flags)
-{
-    const char *audiodev;
-    int audio_fd;
-
-    /* Figure out what our audio device is */
-    if ((audiodev = SDL_getenv("SDL_PATH_DSP")) == NULL) {
-        audiodev = SDL_getenv("AUDIODEV");
-    }
-    if (audiodev == NULL) {
-        return -1;
-    }
-    audio_fd = open(audiodev, flags, 0);
-    if (path != NULL) {
-        SDL_strlcpy(path, audiodev, maxlen);
-        path[maxlen - 1] = '\0';
-    }
-    return audio_fd;
-}
-
-int
-SDL_OpenAudioPath(char *path, int maxlen, int flags, int classic)
-{
-    struct stat sb;
-    int audio_fd;
-    char audiopath[1024];
-    int cycle;
-
-    audio_fd = OpenUserDefinedDevice(path, maxlen, flags);
-    if (audio_fd != -1) {
-        return audio_fd;
-    }
-
-    cycle = 0;
-    while (devsettings[cycle][0] != '\0') {
-        SDL_snprintf(audiopath, SDL_arraysize(audiopath),
-                     _PATH_DEV_DSP,
-                     devsettings[cycle][0],
-                     devsettings[cycle][1], devsettings[cycle][2]);
-
-        if (stat(audiopath, &sb) == 0) {
-            audio_fd = open(audiopath, flags, 0);
-            if (audio_fd > 0) {
-                if (path != NULL) {
-                    SDL_strlcpy(path, audiopath, maxlen);
-                }
-                return audio_fd;
-            }
+    if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) {
+        int instance = 0;
+        while (instance++ <= 64) {
+            SDL_snprintf(audiopath, SDL_arraysize(audiopath),
+                         "%s%d", audiodev, instance);
+            test_device(audiopath, flags, test, devices, devCount);
         }
     }
-    return -1;
 }
 
 #endif /* Audio driver selection */
--- a/src/audio/SDL_audiodev_c.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/SDL_audiodev_c.h	Tue Oct 17 09:15:21 2006 +0000
@@ -21,6 +21,8 @@
 */
 #include "SDL_config.h"
 
-/* Open the audio device, storing the pathname in 'path'  */
-extern int SDL_OpenAudioPath(char *path, int maxlen, int flags, int classic);
+void SDL_EnumUnixAudioDevices(int flags, int classic, int (*test)(int fd),
+                              char ***devs, int *count);
+void SDL_FreeUnixAudioDevices(char ***devices, int *devCount);
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/SDL_mixer.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/SDL_mixer.c	Tue Oct 17 09:15:21 2006 +0000
@@ -89,21 +89,6 @@
 #define ADJUST_VOLUME(s, v)	(s = (s*v)/SDL_MIX_MAXVOLUME)
 #define ADJUST_VOLUME_U8(s, v)	(s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128)
 
-void
-SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
-{
-    /* Mix the user-level audio format */
-    if (current_audio) {
-        SDL_AudioFormat format;
-        if (current_audio->convert.needed) {
-            format = current_audio->convert.src_format;
-        } else {
-            format = current_audio->spec.format;
-        }
-        SDL_MixAudioFormat(dst, src, format, len, volume);
-    }
-}
-
 
 void
 SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
--- a/src/audio/SDL_sysaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/SDL_sysaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -29,13 +29,33 @@
 
 /* The SDL audio driver */
 typedef struct SDL_AudioDevice SDL_AudioDevice;
+#define _THIS	SDL_AudioDevice *_this
 
-/* Define the SDL audio driver structure */
-#define _THIS	SDL_AudioDevice *_this
-#ifndef _STATUS
-#define _STATUS	SDL_status *status
-#endif
-struct SDL_AudioDevice
+typedef struct SDL_AudioDriverImpl
+{
+    int (*DetectDevices)(int iscapture);
+    const char *(*GetDeviceName)(int index, int iscapture);
+    int (*OpenDevice) (_THIS, const char *devname, int iscapture);
+    void (*ThreadInit) (_THIS); /* Called by audio thread at start */
+    void (*WaitDevice) (_THIS);
+    void (*PlayDevice) (_THIS);
+    Uint8 *(*GetDeviceBuf) (_THIS);
+    void (*WaitDone) (_THIS);
+    void (*CloseDevice) (_THIS);
+    void (*LockDevice) (_THIS);
+    void (*UnlockDevice) (_THIS);
+    void (*Deinitialize) (void);
+
+    /* Some flags to push duplicate code into the core and reduce #ifdefs. */
+    int ProvidesOwnCallbackThread:1;
+    int SkipMixerLock:1;
+    int HasCaptureSupport:1;
+    int OnlyHasDefaultOutputDevice:1;
+    int OnlyHasDefaultInputDevice:1;
+} SDL_AudioDriverImpl;
+
+
+typedef struct SDL_AudioDriver
 {
     /* * * */
     /* The name of this audio driver */
@@ -45,21 +65,13 @@
     /* The description of this audio driver */
     const char *desc;
 
-    /* * * */
-    /* Public driver functions */
-    int (*OpenAudio) (_THIS, SDL_AudioSpec * spec);
-    void (*ThreadInit) (_THIS); /* Called by audio thread at start */
-    void (*WaitAudio) (_THIS);
-    void (*PlayAudio) (_THIS);
-    Uint8 *(*GetAudioBuf) (_THIS);
-    void (*WaitDone) (_THIS);
-    void (*CloseAudio) (_THIS);
+    SDL_AudioDriverImpl impl;
+} SDL_AudioDriver;
+
 
-    /* * * */
-    /* Lock / Unlock functions added for the Mac port */
-    void (*LockAudio) (_THIS);
-    void (*UnlockAudio) (_THIS);
-
+/* Define the SDL audio driver structure */
+struct SDL_AudioDevice
+{
     /* * * */
     /* Data common to all devices */
 
@@ -70,6 +82,7 @@
     SDL_AudioCVT convert;
 
     /* Current state flags */
+    int iscapture;
     int enabled;
     int paused;
     int opened;
@@ -87,10 +100,6 @@
     /* * * */
     /* Data private to this driver */
     struct SDL_PrivateAudioData *hidden;
-
-    /* * * */
-    /* The function used to dispose of this structure */
-    void (*free) (_THIS);
 };
 #undef _THIS
 
@@ -98,84 +107,10 @@
 {
     const char *name;
     const char *desc;
-    int (*available) (void);
-    SDL_AudioDevice *(*create) (int devindex);
+    int (*init) (SDL_AudioDriverImpl *impl);
+    int demand_only:1;  /* 1==request explicitly, or it won't be available. */
 } AudioBootStrap;
 
-#if SDL_AUDIO_DRIVER_BSD
-extern AudioBootStrap BSD_AUDIO_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_OSS
-extern AudioBootStrap DSP_bootstrap;
-extern AudioBootStrap DMA_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_ALSA
-extern AudioBootStrap ALSA_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_QNXNTO
-extern AudioBootStrap QNXNTOAUDIO_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_SUNAUDIO
-extern AudioBootStrap SUNAUDIO_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_DMEDIA
-extern AudioBootStrap DMEDIA_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_ARTS
-extern AudioBootStrap ARTS_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_ESD
-extern AudioBootStrap ESD_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_NAS
-extern AudioBootStrap NAS_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_DSOUND
-extern AudioBootStrap DSOUND_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_WAVEOUT
-extern AudioBootStrap WAVEOUT_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_PAUD
-extern AudioBootStrap Paud_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_BAUDIO
-extern AudioBootStrap BAUDIO_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_COREAUDIO
-extern AudioBootStrap COREAUDIO_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_SNDMGR
-extern AudioBootStrap SNDMGR_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_AHI
-extern AudioBootStrap AHI_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_MINT
-extern AudioBootStrap MINTAUDIO_GSXB_bootstrap;
-extern AudioBootStrap MINTAUDIO_MCSN_bootstrap;
-extern AudioBootStrap MINTAUDIO_STFA_bootstrap;
-extern AudioBootStrap MINTAUDIO_XBIOS_bootstrap;
-extern AudioBootStrap MINTAUDIO_DMA8_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_DISK
-extern AudioBootStrap DISKAUD_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_DUMMY
-extern AudioBootStrap DUMMYAUD_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_DC
-extern AudioBootStrap DCAUD_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_MMEAUDIO
-extern AudioBootStrap MMEAUDIO_bootstrap;
-#endif
-#if SDL_AUDIO_DRIVER_DART
-extern AudioBootStrap DART_bootstrap;
-#endif
+#endif /* _SDL_sysaudio_h */
 
-/* This is the current audio device */
-extern SDL_AudioDevice *current_audio;
-
-#endif /* _SDL_sysaudio_h */
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/alsa/SDL_alsa_audio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/alsa/SDL_alsa_audio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -25,6 +25,9 @@
 
 #include <sys/types.h>
 #include <signal.h>             /* For kill() */
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
 
 #include "SDL_timer.h"
 #include "SDL_audio.h"
@@ -32,14 +35,6 @@
 #include "../SDL_audio_c.h"
 #include "SDL_alsa_audio.h"
 
-#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
-#include <dlfcn.h>
-#include "SDL_name.h"
-#include "SDL_loadso.h"
-#else
-#define SDL_NAME(X)	X
-#endif
-
 
 /* The tag name used by ALSA audio */
 #define DRIVER_NAME         "alsa"
@@ -47,182 +42,138 @@
 /* The default ALSA audio driver */
 #define DEFAULT_DEVICE	"default"
 
-/* Audio driver functions */
-static int ALSA_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void ALSA_WaitAudio(_THIS);
-static void ALSA_PlayAudio(_THIS);
-static Uint8 *ALSA_GetAudioBuf(_THIS);
-static void ALSA_CloseAudio(_THIS);
+static int (*ALSA_snd_pcm_open)
+                (snd_pcm_t **, const char *, snd_pcm_stream_t, int);
+static int (*ALSA_snd_pcm_close)(snd_pcm_t * pcm);
+static snd_pcm_sframes_t(*ALSA_snd_pcm_writei)
+                (snd_pcm_t *,const void *, snd_pcm_uframes_t);
+static int (*ALSA_snd_pcm_resume)(snd_pcm_t *);
+static int (*ALSA_snd_pcm_prepare)(snd_pcm_t *);
+static int (*ALSA_snd_pcm_drain)(snd_pcm_t *);
+static const char *(*ALSA_snd_strerror)(int);
+static size_t(*ALSA_snd_pcm_hw_params_sizeof)(void);
+static size_t(*ALSA_snd_pcm_sw_params_sizeof)(void);
+static int (*ALSA_snd_pcm_hw_params_any)(snd_pcm_t *, snd_pcm_hw_params_t *);
+static int (*ALSA_snd_pcm_hw_params_set_access)
+                (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_access_t);
+static int (*ALSA_snd_pcm_hw_params_set_format)
+                (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_format_t);
+static int (*ALSA_snd_pcm_hw_params_set_channels)
+                (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int);
+static int (*ALSA_snd_pcm_hw_params_get_channels)(const snd_pcm_hw_params_t *);
+static unsigned int (*ALSA_snd_pcm_hw_params_set_rate_near)
+                (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int, int *);
+static snd_pcm_uframes_t (*ALSA_snd_pcm_hw_params_set_period_size_near)
+                (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_uframes_t, int *);
+static snd_pcm_sframes_t (*ALSA_snd_pcm_hw_params_get_period_size)
+                (const snd_pcm_hw_params_t *);
+static unsigned int (*ALSA_snd_pcm_hw_params_set_periods_near)
+                (snd_pcm_t *,snd_pcm_hw_params_t *, unsigned int, int *);
+static int (*ALSA_snd_pcm_hw_params_get_periods)(snd_pcm_hw_params_t *);
+static int (*ALSA_snd_pcm_hw_params)(snd_pcm_t *, snd_pcm_hw_params_t *);
+static int (*ALSA_snd_pcm_sw_params_current)(snd_pcm_t*, snd_pcm_sw_params_t*);
+static int (*ALSA_snd_pcm_sw_params_set_start_threshold)
+                (snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
+static int (*ALSA_snd_pcm_sw_params_set_avail_min)
+                (snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
+static int (*ALSA_snd_pcm_sw_params)(snd_pcm_t *, snd_pcm_sw_params_t *);
+static int (*ALSA_snd_pcm_nonblock)(snd_pcm_t *, int);
+#define snd_pcm_hw_params_sizeof ALSA_snd_pcm_hw_params_sizeof
+#define snd_pcm_sw_params_sizeof ALSA_snd_pcm_sw_params_sizeof
+
 
 #ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
 
 static const char *alsa_library = SDL_AUDIO_DRIVER_ALSA_DYNAMIC;
 static void *alsa_handle = NULL;
-static int alsa_loaded = 0;
+
+static int
+load_alsa_sym(const char *fn, void **addr)
+{
+    /*
+     * !!! FIXME:
+     * Eventually, this will deal with fallbacks, version changes, and
+     *  missing symbols we can workaround. But for now, it doesn't.
+     */
 
-static int (*SDL_snd_pcm_open) (snd_pcm_t ** pcm, const char *name,
-                                snd_pcm_stream_t stream, int mode);
-static int (*SDL_NAME(snd_pcm_open)) (snd_pcm_t ** pcm, const char *name,
-                                      snd_pcm_stream_t stream, int mode);
-static int (*SDL_NAME(snd_pcm_close)) (snd_pcm_t * pcm);
-static snd_pcm_sframes_t(*SDL_NAME(snd_pcm_writei)) (snd_pcm_t * pcm,
-                                                     const void *buffer,
-                                                     snd_pcm_uframes_t size);
-static int (*SDL_NAME(snd_pcm_resume)) (snd_pcm_t * pcm);
-static int (*SDL_NAME(snd_pcm_prepare)) (snd_pcm_t * pcm);
-static int (*SDL_NAME(snd_pcm_drain)) (snd_pcm_t * pcm);
-static const char *(*SDL_NAME(snd_strerror)) (int errnum);
-static size_t(*SDL_NAME(snd_pcm_hw_params_sizeof)) (void);
-static size_t(*SDL_NAME(snd_pcm_sw_params_sizeof)) (void);
-static int (*SDL_NAME(snd_pcm_hw_params_any)) (snd_pcm_t * pcm,
-                                               snd_pcm_hw_params_t * params);
-static int (*SDL_NAME(snd_pcm_hw_params_set_access)) (snd_pcm_t * pcm,
-                                                      snd_pcm_hw_params_t *
-                                                      params,
-                                                      snd_pcm_access_t
-                                                      access);
-static int (*SDL_NAME(snd_pcm_hw_params_set_format)) (snd_pcm_t * pcm,
-                                                      snd_pcm_hw_params_t *
-                                                      params,
-                                                      snd_pcm_format_t val);
-static int (*SDL_NAME(snd_pcm_hw_params_set_channels)) (snd_pcm_t * pcm,
-                                                        snd_pcm_hw_params_t *
-                                                        params,
-                                                        unsigned int val);
-static int (*SDL_NAME(snd_pcm_hw_params_get_channels)) (const
-                                                        snd_pcm_hw_params_t *
-                                                        params);
-static unsigned int
-    (*SDL_NAME(snd_pcm_hw_params_set_rate_near)) (snd_pcm_t *
-                                                  pcm,
-                                                  snd_pcm_hw_params_t
-                                                  * params,
-                                                  unsigned int val, int *dir);
-static snd_pcm_uframes_t
-    (*SDL_NAME(snd_pcm_hw_params_set_period_size_near)) (snd_pcm_t * pcm,
-                                                         snd_pcm_hw_params_t
-                                                         * params,
-                                                         snd_pcm_uframes_t
-                                                         val, int *dir);
-static snd_pcm_sframes_t
-    (*SDL_NAME(snd_pcm_hw_params_get_period_size)) (const
-                                                    snd_pcm_hw_params_t
-                                                    * params);
-static unsigned int
-    (*SDL_NAME(snd_pcm_hw_params_set_periods_near)) (snd_pcm_t * pcm,
-                                                     snd_pcm_hw_params_t
-                                                     * params,
-                                                     unsigned int val,
-                                                     int *dir);
-static int (*SDL_NAME(snd_pcm_hw_params_get_periods)) (snd_pcm_hw_params_t *
-                                                       params);
-static int (*SDL_NAME(snd_pcm_hw_params)) (snd_pcm_t * pcm,
-                                           snd_pcm_hw_params_t * params);
-/*
-*/
-static int (*SDL_NAME(snd_pcm_sw_params_current)) (snd_pcm_t * pcm,
-                                                   snd_pcm_sw_params_t *
-                                                   swparams);
-static int (*SDL_NAME(snd_pcm_sw_params_set_start_threshold)) (snd_pcm_t *
-                                                               pcm,
-                                                               snd_pcm_sw_params_t
-                                                               * params,
-                                                               snd_pcm_uframes_t
-                                                               val);
-static int (*SDL_NAME(snd_pcm_sw_params_set_avail_min)) (snd_pcm_t * pcm,
-                                                         snd_pcm_sw_params_t
-                                                         * params,
-                                                         snd_pcm_uframes_t
-                                                         val);
-static int (*SDL_NAME(snd_pcm_sw_params)) (snd_pcm_t * pcm,
-                                           snd_pcm_sw_params_t * params);
-static int (*SDL_NAME(snd_pcm_nonblock)) (snd_pcm_t * pcm, int nonblock);
-#define snd_pcm_hw_params_sizeof SDL_NAME(snd_pcm_hw_params_sizeof)
-#define snd_pcm_sw_params_sizeof SDL_NAME(snd_pcm_sw_params_sizeof)
+#if HAVE_DLVSYM
+    *addr = dlvsym(alsa_handle, fn, "ALSA_0.9");
+    if (*addr == NULL)
+#endif
+    {
+        *addr = dlsym(alsa_handle, fn);
+        if (*addr == NULL) {
+            SDL_SetError("dlsym('%s') failed: %s", fn, strerror(errno));
+            return 0;
+        }
+    }
+
+    return 1;
+}
 
 /* cast funcs to char* first, to please GCC's strict aliasing rules. */
-static struct
+#define SDL_ALSA_SYM(x) \
+    if (!load_alsa_sym(#x, (void **) (char *) &ALSA_##x)) return -1
+#else
+#define SDL_ALSA_SYM(x) ALSA_##x = x
+#endif
+
+static int load_alsa_syms(void)
 {
-    const char *name;
-    void **func;
-} alsa_functions[] = {
-    {
-    "snd_pcm_open", (void **) (char *) &SDL_NAME(snd_pcm_open)}, {
-    "snd_pcm_close", (void **) (char *) &SDL_NAME(snd_pcm_close)}, {
-    "snd_pcm_writei", (void **) (char *) &SDL_NAME(snd_pcm_writei)}, {
-    "snd_pcm_resume", (void **) (char *) &SDL_NAME(snd_pcm_resume)}, {
-    "snd_pcm_prepare", (void **) (char *) &SDL_NAME(snd_pcm_prepare)}, {
-    "snd_pcm_drain", (void **) (char *) &SDL_NAME(snd_pcm_drain)}, {
-    "snd_strerror", (void **) (char *) &SDL_NAME(snd_strerror)}, {
-    "snd_pcm_hw_params_sizeof",
-            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_sizeof)}, {
-    "snd_pcm_sw_params_sizeof",
-            (void **) (char *) &SDL_NAME(snd_pcm_sw_params_sizeof)}, {
-    "snd_pcm_hw_params_any",
-            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_any)}, {
-    "snd_pcm_hw_params_set_access",
-            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_access)}, {
-    "snd_pcm_hw_params_set_format",
-            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_format)}, {
-    "snd_pcm_hw_params_set_channels",
-            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_channels)}, {
-    "snd_pcm_hw_params_get_channels",
-            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_get_channels)}, {
-    "snd_pcm_hw_params_set_rate_near",
-            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_rate_near)}, {
-        "snd_pcm_hw_params_set_period_size_near", (void **) (char *)
-    &SDL_NAME(snd_pcm_hw_params_set_period_size_near)}, {
-    "snd_pcm_hw_params_get_period_size",
-            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_get_period_size)},
-    {
-        "snd_pcm_hw_params_set_periods_near", (void **) (char *)
-    &SDL_NAME(snd_pcm_hw_params_set_periods_near)}, {
-    "snd_pcm_hw_params_get_periods",
-            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_get_periods)}, {
-    "snd_pcm_hw_params", (void **) (char *) &SDL_NAME(snd_pcm_hw_params)}, {
-    "snd_pcm_sw_params_current",
-            (void **) (char *) &SDL_NAME(snd_pcm_sw_params_current)}, {
-        "snd_pcm_sw_params_set_start_threshold", (void **) (char *)
-    &SDL_NAME(snd_pcm_sw_params_set_start_threshold)}, {
-    "snd_pcm_sw_params_set_avail_min",
-            (void **) (char *) &SDL_NAME(snd_pcm_sw_params_set_avail_min)}, {
-    "snd_pcm_sw_params", (void **) (char *) &SDL_NAME(snd_pcm_sw_params)}, {
-"snd_pcm_nonblock", (void **) (char *) &SDL_NAME(snd_pcm_nonblock)},};
+    SDL_ALSA_SYM(snd_pcm_open);
+    SDL_ALSA_SYM(snd_pcm_close);
+    SDL_ALSA_SYM(snd_pcm_writei);
+    SDL_ALSA_SYM(snd_pcm_resume);
+    SDL_ALSA_SYM(snd_pcm_prepare);
+    SDL_ALSA_SYM(snd_pcm_drain);
+    SDL_ALSA_SYM(snd_strerror);
+    SDL_ALSA_SYM(snd_pcm_hw_params_sizeof);
+    SDL_ALSA_SYM(snd_pcm_sw_params_sizeof);
+    SDL_ALSA_SYM(snd_pcm_hw_params_any);
+    SDL_ALSA_SYM(snd_pcm_hw_params_set_access);
+    SDL_ALSA_SYM(snd_pcm_hw_params_set_format);
+    SDL_ALSA_SYM(snd_pcm_hw_params_set_channels);
+    SDL_ALSA_SYM(snd_pcm_hw_params_get_channels);
+    SDL_ALSA_SYM(snd_pcm_hw_params_set_rate_near);
+    SDL_ALSA_SYM(snd_pcm_hw_params_set_period_size_near);
+    SDL_ALSA_SYM(snd_pcm_hw_params_get_period_size);
+    SDL_ALSA_SYM(snd_pcm_hw_params_set_periods_near);
+    SDL_ALSA_SYM(snd_pcm_hw_params_get_periods);
+    SDL_ALSA_SYM(snd_pcm_hw_params);
+    SDL_ALSA_SYM(snd_pcm_sw_params_current);
+    SDL_ALSA_SYM(snd_pcm_sw_params_set_start_threshold);
+    SDL_ALSA_SYM(snd_pcm_sw_params_set_avail_min);
+    SDL_ALSA_SYM(snd_pcm_sw_params);
+    SDL_ALSA_SYM(snd_pcm_nonblock);
+    return 0;
+}
+#undef SDL_ALSA_SYM
+
+#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
 
 static void
 UnloadALSALibrary(void)
 {
-    if (alsa_loaded) {
-/*		SDL_UnloadObject(alsa_handle);*/
+    if (alsa_handle != NULL) {
         dlclose(alsa_handle);
         alsa_handle = NULL;
-        alsa_loaded = 0;
     }
 }
 
 static int
 LoadALSALibrary(void)
 {
-    int i, retval = -1;
-
-/*	alsa_handle = SDL_LoadObject(alsa_library);*/
-    alsa_handle = dlopen(alsa_library, RTLD_NOW);
-    if (alsa_handle) {
-        alsa_loaded = 1;
-        retval = 0;
-        for (i = 0; i < SDL_arraysize(alsa_functions); i++) {
-/*			*alsa_functions[i].func = SDL_LoadFunction(alsa_handle,alsa_functions[i].name);*/
-#if HAVE_DLVSYM
-            *alsa_functions[i].func =
-                dlvsym(alsa_handle, alsa_functions[i].name, "ALSA_0.9");
-            if (!*alsa_functions[i].func)
-#endif
-                *alsa_functions[i].func =
-                    dlsym(alsa_handle, alsa_functions[i].name);
-            if (!*alsa_functions[i].func) {
-                retval = -1;
+    int retval = 0;
+    if (alsa_handle == NULL) {
+        alsa_handle = dlopen(alsa_library, RTLD_NOW);
+        if (alsa_handle == NULL) {
+            retval = -1;
+            SDL_SetError("ALSA: dlopen('%s') failed: %s\n",
+                          alsa_library, strerror(errno));
+        } else {
+            retval = load_alsa_syms();
+            if (retval < 0) {
                 UnloadALSALibrary();
-                break;
             }
         }
     }
@@ -234,12 +185,12 @@
 static void
 UnloadALSALibrary(void)
 {
-    return;
 }
 
 static int
 LoadALSALibrary(void)
 {
+    load_alsa_syms();
     return 0;
 }
 
@@ -262,80 +213,10 @@
     return device;
 }
 
-/* Audio driver bootstrap functions */
-
-static int
-Audio_Available(void)
-{
-    int available;
-    int status;
-    snd_pcm_t *handle;
-
-    available = 0;
-    if (LoadALSALibrary() < 0) {
-        return available;
-    }
-    status =
-        SDL_NAME(snd_pcm_open) (&handle, get_audio_device(2),
-                                SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
-    if (status >= 0) {
-        available = 1;
-        SDL_NAME(snd_pcm_close) (handle);
-    }
-    UnloadALSALibrary();
-    return (available);
-}
-
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
-    UnloadALSALibrary();
-}
-
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
-{
-    SDL_AudioDevice *this;
-
-    /* Initialize all variables that we clean on shutdown */
-    LoadALSALibrary();
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    /* Set the function pointers */
-    this->OpenAudio = ALSA_OpenAudio;
-    this->WaitAudio = ALSA_WaitAudio;
-    this->PlayAudio = ALSA_PlayAudio;
-    this->GetAudioBuf = ALSA_GetAudioBuf;
-    this->CloseAudio = ALSA_CloseAudio;
-
-    this->free = Audio_DeleteDevice;
-
-    return this;
-}
-
-AudioBootStrap ALSA_bootstrap = {
-    DRIVER_NAME, "ALSA 0.9 PCM audio",
-    Audio_Available, Audio_CreateDevice
-};
 
 /* This function waits until it is possible to write a full sound buffer */
 static void
-ALSA_WaitAudio(_THIS)
+ALSA_WaitDevice(_THIS)
 {
     /* Check to see if the thread-parent process is still alive */
     {
@@ -343,8 +224,9 @@
         /* Note that this only works with thread implementations 
            that use a different process id for each thread.
          */
-        if (parent && (((++cnt) % 10) == 0)) {  /* Check every 10 loops */
-            if (kill(parent, 0) < 0) {
+        /* Check every 10 loops */
+        if (this->hidden->parent && (((++cnt) % 10) == 0)) {
+            if (kill(this->hidden->parent, 0) < 0) {
                 this->enabled = 0;
             }
         }
@@ -352,13 +234,14 @@
 }
 
 
+/* !!! FIXME: is there a channel swizzler in alsalib instead? */
 /*
  * http://bugzilla.libsdl.org/show_bug.cgi?id=110
  * "For Linux ALSA, this is FL-FR-RL-RR-C-LFE
  *  and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-RL-RR"
  */
 #define SWIZ6(T) \
-    T *ptr = (T *) mixbuf; \
+    T *ptr = (T *) this->hidden->mixbuf; \
     const Uint32 count = (this->spec.samples / 6); \
     Uint32 i; \
     for (i = 0; i < count; i++, ptr += 6) { \
@@ -392,8 +275,8 @@
 
 
 /*
- * Called right before feeding this->mixbuf to the hardware. Swizzle channels
- *  from Windows/Mac order to the format alsalib will want.
+ * Called right before feeding this->hidden->mixbuf to the hardware. Swizzle
+ *  channels from Windows/Mac order to the format alsalib will want.
  */
 static __inline__ void
 swizzle_alsa_channels(_THIS)
@@ -415,7 +298,7 @@
 
 
 static void
-ALSA_PlayAudio(_THIS)
+ALSA_PlayDevice(_THIS)
 {
     int status;
     int sample_len;
@@ -424,11 +307,12 @@
     swizzle_alsa_channels(this);
 
     sample_len = this->spec.samples;
-    sample_buf = (signed short *) mixbuf;
+    sample_buf = (signed short *) this->hidden->mixbuf;
 
     while (sample_len > 0) {
-        status =
-            SDL_NAME(snd_pcm_writei) (pcm_handle, sample_buf, sample_len);
+        status = ALSA_snd_pcm_writei(this->hidden->pcm_handle,
+                                     sample_buf, sample_len);
+
         if (status < 0) {
             if (status == -EAGAIN) {
                 SDL_Delay(1);
@@ -437,11 +321,11 @@
             if (status == -ESTRPIPE) {
                 do {
                     SDL_Delay(1);
-                    status = SDL_NAME(snd_pcm_resume) (pcm_handle);
+                    status = ALSA_snd_pcm_resume(this->hidden->pcm_handle);
                 } while (status == -EAGAIN);
             }
             if (status < 0) {
-                status = SDL_NAME(snd_pcm_prepare) (pcm_handle);
+                status = ALSA_snd_pcm_prepare(this->hidden->pcm_handle);
             }
             if (status < 0) {
                 /* Hmm, not much we can do - abort */
@@ -456,74 +340,89 @@
 }
 
 static Uint8 *
-ALSA_GetAudioBuf(_THIS)
+ALSA_GetDeviceBuf(_THIS)
 {
-    return (mixbuf);
+    return (this->hidden->mixbuf);
 }
 
 static void
-ALSA_CloseAudio(_THIS)
+ALSA_CloseDevice(_THIS)
 {
-    if (mixbuf != NULL) {
-        SDL_FreeAudioMem(mixbuf);
-        mixbuf = NULL;
-    }
-    if (pcm_handle) {
-        SDL_NAME(snd_pcm_drain) (pcm_handle);
-        SDL_NAME(snd_pcm_close) (pcm_handle);
-        pcm_handle = NULL;
+    if (this->hidden != NULL) {
+        if (this->hidden->mixbuf != NULL) {
+            SDL_FreeAudioMem(this->hidden->mixbuf);
+            this->hidden->mixbuf = NULL;
+        }
+        if (this->hidden->pcm_handle) {
+            ALSA_snd_pcm_drain(this->hidden->pcm_handle);
+            ALSA_snd_pcm_close(this->hidden->pcm_handle);
+            this->hidden->pcm_handle = NULL;
+        }
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
 }
 
 static int
-ALSA_OpenAudio(_THIS, SDL_AudioSpec * spec)
+ALSA_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-    int status;
-    snd_pcm_hw_params_t *hwparams;
-    snd_pcm_sw_params_t *swparams;
-    snd_pcm_format_t format;
-    snd_pcm_uframes_t frames;
-    SDL_AudioFormat test_format;
+    int status = 0;
+    snd_pcm_t *pcm_handle = NULL;
+    snd_pcm_hw_params_t *hwparams = NULL;
+    snd_pcm_sw_params_t *swparams = NULL;
+    snd_pcm_format_t format = 0;
+    snd_pcm_uframes_t frames = 0;
+    SDL_AudioFormat test_format = 0;
+
+    /* Initialize all variables that we clean on shutdown */
+    this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
 
     /* Open the audio device */
     /* Name of device should depend on # channels in spec */
-    status =
-        SDL_NAME(snd_pcm_open) (&pcm_handle,
-                                get_audio_device(spec->channels),
-                                SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
+    status = ALSA_snd_pcm_open(&pcm_handle,
+                               get_audio_device(this->spec.channels),
+                               SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
 
     if (status < 0) {
-        SDL_SetError("Couldn't open audio device: %s",
-                     SDL_NAME(snd_strerror) (status));
-        return (-1);
+        ALSA_CloseDevice(this);
+        SDL_SetError("ALSA: Couldn't open audio device: %s",
+                     ALSA_snd_strerror(status));
+        return 0;
     }
 
+    this->hidden->pcm_handle = pcm_handle;
+
     /* Figure out what the hardware is capable of */
     snd_pcm_hw_params_alloca(&hwparams);
-    status = SDL_NAME(snd_pcm_hw_params_any) (pcm_handle, hwparams);
+    status = ALSA_snd_pcm_hw_params_any(pcm_handle, hwparams);
     if (status < 0) {
-        SDL_SetError("Couldn't get hardware config: %s",
-                     SDL_NAME(snd_strerror) (status));
-        ALSA_CloseAudio(this);
-        return (-1);
+        ALSA_CloseDevice(this);
+        SDL_SetError("ALSA: Couldn't get hardware config: %s",
+                     ALSA_snd_strerror(status));
+        return 0;
     }
 
     /* SDL only uses interleaved sample output */
-    status =
-        SDL_NAME(snd_pcm_hw_params_set_access) (pcm_handle, hwparams,
-                                                SND_PCM_ACCESS_RW_INTERLEAVED);
+    status = ALSA_snd_pcm_hw_params_set_access(pcm_handle, hwparams,
+                                               SND_PCM_ACCESS_RW_INTERLEAVED);
     if (status < 0) {
-        SDL_SetError("Couldn't set interleaved access: %s",
-                     SDL_NAME(snd_strerror) (status));
-        ALSA_CloseAudio(this);
-        return (-1);
+        ALSA_CloseDevice(this);
+        SDL_SetError("ALSA: Couldn't set interleaved access: %s",
+                     ALSA_snd_strerror(status));
+        return 0;
     }
 
     /* Try for a closest match on audio format */
     status = -1;
-    for (test_format = SDL_FirstAudioFormat(spec->format);
+    for (test_format = SDL_FirstAudioFormat(this->spec.format);
          test_format && (status < 0);) {
-        status = 0;             /* if we can't support a format, it'll become -1. */
+        status = 0;      /* if we can't support a format, it'll become -1. */
         switch (test_format) {
         case AUDIO_U8:
             format = SND_PCM_FORMAT_U8;
@@ -560,131 +459,151 @@
             break;
         }
         if (status >= 0) {
-            status =
-                SDL_NAME(snd_pcm_hw_params_set_format) (pcm_handle,
-                                                        hwparams, format);
+            status = ALSA_snd_pcm_hw_params_set_format(pcm_handle,
+                                                       hwparams, format);
         }
         if (status < 0) {
             test_format = SDL_NextAudioFormat();
         }
     }
     if (status < 0) {
-        SDL_SetError("Couldn't find any hardware audio formats");
-        ALSA_CloseAudio(this);
-        return (-1);
+        ALSA_CloseDevice(this);
+        SDL_SetError("ALSA: Couldn't find any hardware audio formats");
+        return 0;
     }
-    spec->format = test_format;
+    this->spec.format = test_format;
 
     /* Set the number of channels */
-    status =
-        SDL_NAME(snd_pcm_hw_params_set_channels) (pcm_handle, hwparams,
-                                                  spec->channels);
+    status = ALSA_snd_pcm_hw_params_set_channels(pcm_handle, hwparams,
+                                                 this->spec.channels);
     if (status < 0) {
-        status = SDL_NAME(snd_pcm_hw_params_get_channels) (hwparams);
+        status = ALSA_snd_pcm_hw_params_get_channels(hwparams);
         if ((status <= 0) || (status > 2)) {
-            SDL_SetError("Couldn't set audio channels");
-            ALSA_CloseAudio(this);
-            return (-1);
+            ALSA_CloseDevice(this);
+            SDL_SetError("ALSA: Couldn't set audio channels");
+            return 0;
         }
-        spec->channels = status;
+        this->spec.channels = status;
     }
 
     /* Set the audio rate */
-    status =
-        SDL_NAME(snd_pcm_hw_params_set_rate_near) (pcm_handle, hwparams,
-                                                   spec->freq, NULL);
+    status = ALSA_snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams,
+                                                  this->spec.freq, NULL);
     if (status < 0) {
-        SDL_SetError("Couldn't set audio frequency: %s",
-                     SDL_NAME(snd_strerror) (status));
-        ALSA_CloseAudio(this);
-        return (-1);
+        ALSA_CloseDevice(this);
+        SDL_SetError("ALSA: Couldn't set audio frequency: %s",
+                     ALSA_snd_strerror(status));
+        return 0;
     }
-    spec->freq = status;
+    this->spec.freq = status;
 
     /* Set the buffer size, in samples */
-    frames = spec->samples;
-    frames =
-        SDL_NAME(snd_pcm_hw_params_set_period_size_near) (pcm_handle,
-                                                          hwparams, frames,
-                                                          NULL);
-    spec->samples = frames;
-    SDL_NAME(snd_pcm_hw_params_set_periods_near) (pcm_handle, hwparams, 2,
-                                                  NULL);
+    frames = this->spec.samples;
+    frames = ALSA_snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams,
+                                                         frames, NULL);
+    this->spec.samples = frames;
+    ALSA_snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, 2, NULL);
 
     /* "set" the hardware with the desired parameters */
-    status = SDL_NAME(snd_pcm_hw_params) (pcm_handle, hwparams);
+    status = ALSA_snd_pcm_hw_params(pcm_handle, hwparams);
     if (status < 0) {
-        SDL_SetError("Couldn't set hardware audio parameters: %s",
-                     SDL_NAME(snd_strerror) (status));
-        ALSA_CloseAudio(this);
-        return (-1);
+        ALSA_CloseDevice(this);
+        SDL_SetError("ALSA: Couldn't set hardware audio parameters: %s",
+                     ALSA_snd_strerror(status));
+        return 0;
     }
 
-/* This is useful for debugging... */
-/*
-{ snd_pcm_sframes_t bufsize; int fragments;
-   bufsize = SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams);
-   fragments = SDL_NAME(snd_pcm_hw_params_get_periods)(hwparams);
-
-   fprintf(stderr, "ALSA: bufsize = %ld, fragments = %d\n", bufsize, fragments);
+#if AUDIO_DEBUG
+{
+    snd_pcm_sframes_t bufsize;
+    int fragments;
+    bufsize = ALSA_snd_pcm_hw_params_get_period_size(hwparams);
+    fragments = ALSA_snd_pcm_hw_params_get_periods(hwparams);
+    fprintf(stderr,"ALSA: bufsize = %ld, fragments = %d\n",bufsize,fragments);
 }
-*/
+#endif
 
     /* Set the software parameters */
     snd_pcm_sw_params_alloca(&swparams);
-    status = SDL_NAME(snd_pcm_sw_params_current) (pcm_handle, swparams);
+    status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams);
     if (status < 0) {
-        SDL_SetError("Couldn't get software config: %s",
-                     SDL_NAME(snd_strerror) (status));
-        ALSA_CloseAudio(this);
-        return (-1);
-    }
-    status =
-        SDL_NAME(snd_pcm_sw_params_set_start_threshold) (pcm_handle,
-                                                         swparams, 0);
-    if (status < 0) {
-        SDL_SetError("Couldn't set start threshold: %s",
-                     SDL_NAME(snd_strerror) (status));
-        ALSA_CloseAudio(this);
-        return (-1);
+        ALSA_CloseDevice(this);
+        SDL_SetError("ALSA: Couldn't get software config: %s",
+                     ALSA_snd_strerror(status));
+        return 0;
     }
-    status =
-        SDL_NAME(snd_pcm_sw_params_set_avail_min) (pcm_handle, swparams,
-                                                   frames);
+    status = ALSA_snd_pcm_sw_params_set_start_threshold(pcm_handle,swparams,0);
+    if (status < 0) {
+        ALSA_CloseDevice(this);
+        SDL_SetError("ALSA: Couldn't set start threshold: %s",
+                     ALSA_snd_strerror(status));
+        return 0;
+    }
+    status = ALSA_snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, frames);
     if (status < 0) {
-        SDL_SetError("Couldn't set avail min: %s",
-                     SDL_NAME(snd_strerror) (status));
-        ALSA_CloseAudio(this);
-        return (-1);
+        ALSA_CloseDevice(this);
+        SDL_SetError("Couldn't set avail min: %s", ALSA_snd_strerror(status));
+        return 0;
     }
-    status = SDL_NAME(snd_pcm_sw_params) (pcm_handle, swparams);
+    status = ALSA_snd_pcm_sw_params(pcm_handle, swparams);
     if (status < 0) {
+        ALSA_CloseDevice(this);
         SDL_SetError("Couldn't set software audio parameters: %s",
-                     SDL_NAME(snd_strerror) (status));
-        ALSA_CloseAudio(this);
-        return (-1);
+                     ALSA_snd_strerror(status));
+        return 0;
     }
 
     /* Calculate the final parameters for this audio specification */
-    SDL_CalculateAudioSpec(spec);
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* Allocate mixing buffer */
-    mixlen = spec->size;
-    mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen);
-    if (mixbuf == NULL) {
-        ALSA_CloseAudio(this);
-        return (-1);
+    this->hidden->mixlen = this->spec.size;
+    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+    if (this->hidden->mixbuf == NULL) {
+        ALSA_CloseDevice(this);
+        SDL_OutOfMemory();
+        return 0;
     }
-    SDL_memset(mixbuf, spec->silence, spec->size);
+    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
 
     /* Get the parent process id (we're the parent of the audio thread) */
-    parent = getpid();
+    this->hidden->parent = getpid();
 
     /* Switch to blocking mode for playback */
-    SDL_NAME(snd_pcm_nonblock) (pcm_handle, 0);
+    ALSA_snd_pcm_nonblock(pcm_handle, 0);
 
     /* We're ready to rock and roll. :-) */
-    return (0);
+    return 1;
+}
+
+static void
+ALSA_Deinitialize(void)
+{
+    UnloadALSALibrary();
 }
 
+static int
+ALSA_Init(SDL_AudioDriverImpl *impl)
+{
+    if (LoadALSALibrary() < 0) {
+        return 0;
+    }
+
+    /* Set the function pointers */
+    impl->OpenDevice = ALSA_OpenDevice;
+    impl->WaitDevice = ALSA_WaitDevice;
+    impl->GetDeviceBuf = ALSA_GetDeviceBuf;
+    impl->PlayDevice = ALSA_PlayDevice;
+    impl->CloseDevice = ALSA_CloseDevice;
+    impl->Deinitialize = ALSA_Deinitialize;
+    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: Add device enum! */
+
+    return 1;
+}
+
+
+AudioBootStrap ALSA_bootstrap = {
+    DRIVER_NAME, "ALSA 0.9 PCM audio", ALSA_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/alsa/SDL_alsa_audio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/alsa/SDL_alsa_audio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -30,7 +30,7 @@
 
 #include "../SDL_sysaudio.h"
 
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *this
 
 struct SDL_PrivateAudioData
@@ -46,11 +46,5 @@
     int mixlen;
 };
 
-/* Old variable names */
-#define pcm_handle		(this->hidden->pcm_handle)
-#define parent			(this->hidden->parent)
-#define mixbuf			(this->hidden->mixbuf)
-#define mixlen			(this->hidden->mixlen)
-
 #endif /* _ALSA_PCM_audio_h */
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/amigaos/SDL_ahiaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,360 +0,0 @@
-/*
-    SDL - Simple DirectMedia Layer
-    Copyright (C) 1997-2006 Sam Lantinga
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 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
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-    Sam Lantinga
-    slouken@libsdl.org
-*/
-#include "SDL_config.h"
-
-/* Allow access to a raw mixing buffer (for AmigaOS) */
-
-#include "SDL_audio.h"
-#include "../SDL_audio_c.h"
-#include "SDL_ahiaudio.h"
-
-/* Audio driver functions */
-static int AHI_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void AHI_WaitAudio(_THIS);
-static void AHI_PlayAudio(_THIS);
-static Uint8 *AHI_GetAudioBuf(_THIS);
-static void AHI_CloseAudio(_THIS);
-
-#ifndef __SASC
-#define mymalloc(x) AllocVec(x,MEMF_PUBLIC)
-#define myfree FreeVec
-#else
-#define mymalloc malloc
-#define myfree free
-#endif
-
-/* Audio driver bootstrap functions */
-
-static int
-Audio_Available(void)
-{
-    int ok = 0;
-    struct MsgPort *p;
-    struct AHIRequest *req;
-
-    if (p = CreateMsgPort()) {
-        if (req =
-            (struct AHIRequest *) CreateIORequest(p,
-                                                  sizeof(struct
-                                                         AHIRequest))) {
-            req->ahir_Version = 4;
-
-            if (!OpenDevice(AHINAME, 0, (struct IORequest *) req, NULL)) {
-                D(bug("AHI available.\n"));
-                ok = 1;
-                CloseDevice((struct IORequest *) req);
-            }
-            DeleteIORequest((struct IORequest *) req);
-        }
-        DeleteMsgPort(p);
-    }
-
-    D(if (!ok) bug("AHI not available\n"));
-    return ok;
-}
-
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
-}
-
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
-{
-    SDL_AudioDevice *this;
-
-#ifndef NO_AMIGADEBUG
-    D(bug("AHI created...\n"));
-#endif
-
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    /* Set the function pointers */
-    this->OpenAudio = AHI_OpenAudio;
-    this->WaitAudio = AHI_WaitAudio;
-    this->PlayAudio = AHI_PlayAudio;
-    this->GetAudioBuf = AHI_GetAudioBuf;
-    this->CloseAudio = AHI_CloseAudio;
-
-    this->free = Audio_DeleteDevice;
-
-    return this;
-}
-
-AudioBootStrap AHI_bootstrap = {
-    "AHI", Audio_Available, Audio_CreateDevice
-};
-
-
-void static
-AHI_WaitAudio(_THIS)
-{
-    if (!CheckIO((struct IORequest *) audio_req[current_buffer])) {
-        WaitIO((struct IORequest *) audio_req[current_buffer]);
-//              AbortIO((struct IORequest *)audio_req[current_buffer]);
-    }
-}
-
-static void
-AHI_PlayAudio(_THIS)
-{
-    if (playing > 1)
-        WaitIO((struct IORequest *) audio_req[current_buffer]);
-
-    /* Write the audio data out */
-    audio_req[current_buffer]->ahir_Std.io_Message.mn_Node.ln_Pri = 60;
-    audio_req[current_buffer]->ahir_Std.io_Data = mixbuf[current_buffer];
-    audio_req[current_buffer]->ahir_Std.io_Length = this->hidden->size;
-    audio_req[current_buffer]->ahir_Std.io_Offset = 0;
-    audio_req[current_buffer]->ahir_Std.io_Command = CMD_WRITE;
-    audio_req[current_buffer]->ahir_Frequency = this->hidden->freq;
-    audio_req[current_buffer]->ahir_Volume = 0x10000;
-    audio_req[current_buffer]->ahir_Type = this->hidden->type;
-    audio_req[current_buffer]->ahir_Position = 0x8000;
-    audio_req[current_buffer]->ahir_Link =
-        (playing > 0 ? audio_req[current_buffer ^ 1] : NULL);
-
-    SendIO((struct IORequest *) audio_req[current_buffer]);
-    current_buffer ^= 1;
-
-    playing++;
-}
-
-static Uint8 *
-AHI_GetAudioBuf(_THIS)
-{
-    return (mixbuf[current_buffer]);
-}
-
-static void
-AHI_CloseAudio(_THIS)
-{
-    D(bug("Closing audio...\n"));
-
-    playing = 0;
-
-    if (audio_req[0]) {
-        if (audio_req[1]) {
-            D(bug("Break req[1]...\n"));
-
-            AbortIO((struct IORequest *) audio_req[1]);
-            WaitIO((struct IORequest *) audio_req[1]);
-        }
-
-        D(bug("Break req[0]...\n"));
-
-        AbortIO((struct IORequest *) audio_req[0]);
-        WaitIO((struct IORequest *) audio_req[0]);
-
-        if (audio_req[1]) {
-            D(bug("Break AGAIN req[1]...\n"));
-            AbortIO((struct IORequest *) audio_req[1]);
-            WaitIO((struct IORequest *) audio_req[1]);
-        }
-// Double abort to be sure to break the dbuffering process.
-
-        SDL_Delay(200);
-
-        D(bug("Reqs breaked, closing device...\n"));
-        CloseDevice((struct IORequest *) audio_req[0]);
-        D(bug("Device closed, freeing memory...\n"));
-        myfree(audio_req[1]);
-        D(bug("Memory freed, deleting IOReq...\n"));
-        DeleteIORequest((struct IORequest *) audio_req[0]);
-        audio_req[0] = audio_req[1] = NULL;
-    }
-
-    D(bug("Freeing mixbuf[0]...\n"));
-    if (mixbuf[0] != NULL) {
-        myfree(mixbuf[0]);
-//              SDL_FreeAudioMem(mixbuf[0]);
-        mixbuf[0] = NULL;
-    }
-
-    D(bug("Freeing mixbuf[1]...\n"));
-    if (mixbuf[1] != NULL) {
-        myfree(mixbuf[1]);
-//              SDL_FreeAudioMem(mixbuf[1]);
-        mixbuf[1] = NULL;
-    }
-
-    D(bug("Freeing audio_port...\n"));
-
-    if (audio_port != NULL) {
-        DeleteMsgPort(audio_port);
-        audio_port = NULL;
-    }
-    D(bug("...done!\n"));
-}
-
-static int
-AHI_OpenAudio(_THIS, SDL_AudioSpec * spec)
-{
-//      int width;
-    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
-    int valid_datatype = 1;
-
-    D(bug("AHI opening...\n"));
-
-    /* Determine the audio parameters from the AudioSpec */
-    while ((!valid_datatype) && (test_format)) {
-        valid_datatype = 1;
-        switch (test_format) {
-        case AUDIO_S8:
-            D(bug("AUDIO_S8...\n"));
-            spec->format = AUDIO_S8;
-            this->hidden->bytespersample = 1;
-            if (spec->channels < 2)
-                this->hidden->type = AHIST_M8S;
-            else
-                this->hidden->type = AHIST_S8S;
-            break;
-
-        case AUDIO_S16MSB:
-            D(bug("AUDIO_S16MSB...\n"));
-            spec->format = AUDIO_S16MSB;
-            this->hidden->bytespersample = 2;
-            if (spec->channels < 2)
-                this->hidden->type = AHIST_M16S;
-            else
-                this->hidden->type = AHIST_S16S;
-            break;
-
-        case AUDIO_S32MSB:
-            D(bug("AUDIO_S32MSB...\n"));
-            spec->format = AUDIO_S32MSB;
-            this->hidden->bytespersample = 4;
-            if (spec->channels < 2)
-                this->hidden->type = AHIST_M32S;
-            else
-                this->hidden->type = AHIST_S32S;
-            break;
-
-        default:
-            valid_datatype = 0;
-            test_format = SDL_NextAudioFormat();
-            break;
-        }
-    }
-
-    if (!valid_datatype) {      /* shouldn't happen, but just in case... */
-        SDL_SetError("Unsupported audio format");
-        return (-1);
-    }
-
-    if (spec->channels > 2) {
-        spec->channels = 2;     /* will convert at higher level. */
-    }
-
-    D(bug("Before CalculateAudioSpec\n"));
-    /* Update the fragment size as size in bytes */
-    SDL_CalculateAudioSpec(spec);
-
-    D(bug("Before CreateMsgPort\n"));
-
-    if (!(audio_port = CreateMsgPort())) {
-        SDL_SetError("Unable to create a MsgPort");
-        return -1;
-    }
-
-    D(bug("Before CreateIORequest\n"));
-
-    if (!
-        (audio_req[0] =
-         (struct AHIRequest *) CreateIORequest(audio_port,
-                                               sizeof(struct AHIRequest)))) {
-        SDL_SetError("Unable to create an AHIRequest");
-        DeleteMsgPort(audio_port);
-        return -1;
-    }
-
-    audio_req[0]->ahir_Version = 4;
-
-    if (OpenDevice(AHINAME, 0, (struct IORequest *) audio_req[0], NULL)) {
-        SDL_SetError("Unable to open AHI device!\n");
-        DeleteIORequest((struct IORequest *) audio_req[0]);
-        DeleteMsgPort(audio_port);
-        return -1;
-    }
-
-    D(bug("AFTER opendevice\n"));
-
-    /* Set output frequency and size */
-    this->hidden->freq = spec->freq;
-    this->hidden->size = spec->size;
-
-    D(bug("Before buffer allocation\n"));
-
-    /* Allocate mixing buffer */
-    mixbuf[0] = (Uint8 *) mymalloc(spec->size);
-    mixbuf[1] = (Uint8 *) mymalloc(spec->size);
-
-    D(bug("Before audio_req allocation\n"));
-
-    if (!(audio_req[1] = mymalloc(sizeof(struct AHIRequest)))) {
-        SDL_OutOfMemory();
-        return (-1);
-    }
-
-    D(bug("Before audio_req memcpy\n"));
-
-    SDL_memcpy(audio_req[1], audio_req[0], sizeof(struct AHIRequest));
-
-    if (mixbuf[0] == NULL || mixbuf[1] == NULL) {
-        SDL_OutOfMemory();
-        return (-1);
-    }
-
-    D(bug("Before mixbuf memset\n"));
-
-    SDL_memset(mixbuf[0], spec->silence, spec->size);
-    SDL_memset(mixbuf[1], spec->silence, spec->size);
-
-    current_buffer = 0;
-    playing = 0;
-
-    D(bug
-      ("AHI opened: freq:%ld mixbuf:%lx/%lx buflen:%ld bits:%ld channels:%ld\n",
-       spec->freq, mixbuf[0], mixbuf[1], spec->size,
-       this->hidden->bytespersample * 8, spec->channels));
-
-    /* We're ready to rock and roll. :-) */
-    return (0);
-}
-
-/* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/amigaos/SDL_ahiaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
-    SDL - Simple DirectMedia Layer
-    Copyright (C) 1997-2006 Sam Lantinga
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 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
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-    Sam Lantinga
-    slouken@libsdl.org
-*/
-#include "SDL_config.h"
-
-#ifndef _SDL_ahiaudio_h
-#define _SDL_ahiaudio_h
-
-#include <exec/exec.h>
-#include <dos/dos.h>
-#ifdef __SASC
-#include <proto/exec.h>
-#else
-#include <inline/exec.h>
-#endif
-
-#include <devices/ahi.h>
-#include "mydebug.h"
-
-#include "../SDL_sysaudio.h"
-
-/* Hidden "this" pointer for the audio functions */
-#define _THIS	SDL_AudioDevice *this
-
-struct SDL_PrivateAudioData
-{
-    /* The handle for the audio device */
-    struct AHIRequest *audio_req[2];
-    struct MsgPort *audio_port;
-    Sint32 freq, type, bytespersample, size;
-    Uint8 *mixbuf[2];           /* The app mixing buffer */
-    int current_buffer;
-    Uint32 playing;
-};
-
-/* Old variable names */
-#define audio_port		(this->hidden->audio_port)
-#define audio_req		(this->hidden->audio_req)
-#define mixbuf			(this->hidden->mixbuf)
-#define current_buffer		(this->hidden->current_buffer)
-#define playing			(this->hidden->playing)
-
-#endif /* _SDL_ahiaudio_h */
-/* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/arts/SDL_artsaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/arts/SDL_artsaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -27,7 +27,6 @@
 #include "SDL_audio.h"
 #include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
-#include "../SDL_audiodev_c.h"
 #include "SDL_artsaudio.h"
 
 #ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
@@ -40,19 +39,12 @@
 /* The tag name used by artsc audio */
 #define ARTS_DRIVER_NAME         "arts"
 
-/* Audio driver functions */
-static int ARTS_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void ARTS_WaitAudio(_THIS);
-static void ARTS_PlayAudio(_THIS);
-static Uint8 *ARTS_GetAudioBuf(_THIS);
-static void ARTS_CloseAudio(_THIS);
-
 #ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
 
 static const char *arts_library = SDL_AUDIO_DRIVER_ARTS_DYNAMIC;
 static void *arts_handle = NULL;
-static int arts_loaded = 0;
 
+/* !!! FIXME: I hate this SDL_NAME clutter...it makes everything so messy! */
 static int (*SDL_NAME(arts_init)) (void);
 static void (*SDL_NAME(arts_free)) (void);
 static arts_stream_t(*SDL_NAME(arts_play_stream)) (int rate, int bits,
@@ -65,28 +57,32 @@
 static int (*SDL_NAME(arts_write)) (arts_stream_t s, const void *buffer,
                                     int count);
 static void (*SDL_NAME(arts_close_stream)) (arts_stream_t s);
+static void (*SDL_NAME(arts_close_stream)) (arts_stream_t s);
+static const char *(*SDL_NAME(arts_error_text)) (int errorcode);
 
+#define SDL_ARTS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
 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)},};
+    SDL_ARTS_SYM(arts_init),
+    SDL_ARTS_SYM(arts_free),
+    SDL_ARTS_SYM(arts_play_stream),
+    SDL_ARTS_SYM(arts_stream_set),
+    SDL_ARTS_SYM(arts_stream_get),
+    SDL_ARTS_SYM(arts_write),
+    SDL_ARTS_SYM(arts_close_stream),
+    SDL_ARTS_SYM(arts_error_text),
+};
+#undef SDL_ARTS_SYM
 
 static void
 UnloadARTSLibrary()
 {
-    if (arts_loaded) {
+    if (arts_handle != NULL) {
         SDL_UnloadObject(arts_handle);
         arts_handle = NULL;
-        arts_loaded = 0;
     }
 }
 
@@ -95,20 +91,22 @@
 {
     int i, retval = -1;
 
-    arts_handle = SDL_LoadObject(arts_library);
-    if (arts_handle) {
-        arts_loaded = 1;
-        retval = 0;
-        for (i = 0; i < SDL_arraysize(arts_functions); ++i) {
-            *arts_functions[i].func =
-                SDL_LoadFunction(arts_handle, arts_functions[i].name);
-            if (!*arts_functions[i].func) {
-                retval = -1;
-                UnloadARTSLibrary();
-                break;
+    if (arts_handle == NULL) {
+        arts_handle = SDL_LoadObject(arts_library);
+        if (arts_handle != NULL) {
+            retval = 0;
+            for (i = 0; i < SDL_arraysize(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;
 }
 
@@ -128,117 +126,45 @@
 
 #endif /* SDL_AUDIO_DRIVER_ARTS_DYNAMIC */
 
-/* Audio driver bootstrap functions */
-
-static int
-Audio_Available(void)
-{
-    int available = 0;
-
-    if (LoadARTSLibrary() < 0) {
-        return available;
-    }
-    if (SDL_NAME(arts_init) () == 0) {
-#define ARTS_CRASH_HACK         /* Play a stream so aRts doesn't crash */
-#ifdef ARTS_CRASH_HACK
-        arts_stream_t stream2;
-        stream2 = SDL_NAME(arts_play_stream) (44100, 16, 2, "SDL");
-        SDL_NAME(arts_write) (stream2, "", 0);
-        SDL_NAME(arts_close_stream) (stream2);
-#endif
-        available = 1;
-        SDL_NAME(arts_free) ();
-    }
-    UnloadARTSLibrary();
-
-    return available;
-}
-
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
-    UnloadARTSLibrary();
-}
-
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
-{
-    SDL_AudioDevice *this;
-
-    /* Initialize all variables that we clean on shutdown */
-    LoadARTSLibrary();
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-    stream = 0;
-
-    /* Set the function pointers */
-    this->OpenAudio = ARTS_OpenAudio;
-    this->WaitAudio = ARTS_WaitAudio;
-    this->PlayAudio = ARTS_PlayAudio;
-    this->GetAudioBuf = ARTS_GetAudioBuf;
-    this->CloseAudio = ARTS_CloseAudio;
-
-    this->free = Audio_DeleteDevice;
-
-    return this;
-}
-
-AudioBootStrap ARTS_bootstrap = {
-    ARTS_DRIVER_NAME, "Analog Realtime Synthesizer",
-    Audio_Available, Audio_CreateDevice
-};
-
 /* This function waits until it is possible to write a full sound buffer */
 static void
-ARTS_WaitAudio(_THIS)
+ARTS_WaitDevice(_THIS)
 {
     Sint32 ticks;
 
     /* Check to see if the thread-parent process is still alive */
     {
         static int cnt = 0;
-        /* Note that this only works with thread implementations 
+        /* Note that this only works with thread implementations
            that use a different process id for each thread.
          */
-        if (parent && (((++cnt) % 10) == 0)) {  /* Check every 10 loops */
-            if (kill(parent, 0) < 0) {
+        /* Check every 10 loops */
+        if (this->hidden->parent && (((++cnt) % 10) == 0)) {
+            if (kill(this->hidden->parent, 0) < 0) {
                 this->enabled = 0;
             }
         }
     }
 
     /* Use timer for general audio synchronization */
-    ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS;
+    ticks = ((Sint32) (this->hidden->next_frame-SDL_GetTicks())) - FUDGE_TICKS;
     if (ticks > 0) {
         SDL_Delay(ticks);
     }
 }
 
 static void
-ARTS_PlayAudio(_THIS)
+ARTS_PlayDevice(_THIS)
 {
-    int written;
-
     /* Write the audio data */
-    written = SDL_NAME(arts_write) (stream, mixbuf, mixlen);
+    int written = SDL_NAME(arts_write) (
+                        this->hidden->stream,
+                        this->hidden->mixbuf,
+                        this->hidden->mixlen);
 
     /* If timer synchronization is enabled, set the next write frame */
-    if (frame_ticks) {
-        next_frame += frame_ticks;
+    if (this->hidden->frame_ticks) {
+        this->hidden->next_frame += this->hidden->frame_ticks;
     }
 
     /* If we couldn't write, assume fatal error for now */
@@ -250,41 +176,57 @@
 #endif
 }
 
-static Uint8 *
-ARTS_GetAudioBuf(_THIS)
+static void
+ARTS_WaitDone(_THIS)
 {
-    return (mixbuf);
+    /* !!! FIXME: camp here until buffer drains... SDL_Delay(???); */
 }
 
+
+static Uint8 *
+ARTS_GetDeviceBuf(_THIS)
+{
+    return (this->hidden->mixbuf);
+}
+
+
 static void
-ARTS_CloseAudio(_THIS)
+ARTS_CloseDevice(_THIS)
 {
-    if (mixbuf != NULL) {
-        SDL_FreeAudioMem(mixbuf);
-        mixbuf = NULL;
+    if (this->hidden != NULL) {
+        if (this->hidden->mixbuf != NULL) {
+            SDL_FreeAudioMem(this->hidden->mixbuf);
+            this->hidden->mixbuf = NULL;
+        }
+        if (this->hidden->stream) {
+            SDL_NAME(arts_close_stream) (this->hidden->stream);
+            this->hidden->stream = 0;
+        }
+        SDL_NAME(arts_free) ();
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
-    if (stream) {
-        SDL_NAME(arts_close_stream) (stream);
-        stream = 0;
-    }
-    SDL_NAME(arts_free) ();
 }
 
+
 static int
-ARTS_OpenAudio(_THIS, SDL_AudioSpec * spec)
+ARTS_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-    int bits, frag_spec;
-    SDL_AudioFormat test_format, format;
+    int rc = 0;
+    int bits = 0, frag_spec = 0;
+    SDL_AudioFormat test_format = 0, format = 0;
 
-    /* Reset the timer synchronization flag */
-    frame_ticks = 0.0;
-
-    mixbuf = NULL;
+    /* Initialize all variables that we clean on shutdown */
+    this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
 
     /* Try for a closest match on audio format */
-    format = 0;
-    bits = 0;
-    for (test_format = SDL_FirstAudioFormat(spec->format);
+    for (test_format = SDL_FirstAudioFormat(this->spec.format);
          !format && test_format;) {
 #ifdef DEBUG_AUDIO
         fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
@@ -307,51 +249,108 @@
         }
     }
     if (format == 0) {
+        ARTS_CloseDevice(this);
         SDL_SetError("Couldn't find any hardware audio formats");
-        return (-1);
+        return 0;
     }
-    spec->format = test_format;
+    this->spec.format = test_format;
 
-    if (SDL_NAME(arts_init) () != 0) {
-        SDL_SetError("Unable to initialize ARTS");
-        return (-1);
+    if ((rc = SDL_NAME(arts_init) ()) != 0) {
+        ARTS_CloseDevice(this);
+        SDL_SetError( "Unable to initialize ARTS: %s",
+                      SDL_NAME(arts_error_text)(rc) );
+        return 0;
     }
-    stream =
-        SDL_NAME(arts_play_stream) (spec->freq, bits, spec->channels, "SDL");
+    this->hidden->stream = SDL_NAME(arts_play_stream) (
+                                            this->spec.freq,
+                                            bits, this->spec.channels,
+                                            "SDL");
 
     /* Calculate the final parameters for this audio specification */
-    SDL_CalculateAudioSpec(spec);
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* Determine the power of two of the fragment size */
-    for (frag_spec = 0; (0x01 << frag_spec) < spec->size; ++frag_spec);
-    if ((0x01 << frag_spec) != spec->size) {
+    for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec);
+    if ((0x01 << frag_spec) != this->spec.size) {
+        ARTS_CloseDevice(this);
         SDL_SetError("Fragment size must be a power of two");
-        return (-1);
+        return 0;
     }
     frag_spec |= 0x00020000;    /* two fragments, for low latency */
 
 #ifdef ARTS_P_PACKET_SETTINGS
-    SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_SETTINGS, frag_spec);
+    SDL_NAME(arts_stream_set) (this->hidden->stream,
+                                ARTS_P_PACKET_SETTINGS, frag_spec);
 #else
-    SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_SIZE,
+    SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_SIZE,
                                frag_spec & 0xffff);
-    SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_COUNT, frag_spec >> 16);
+    SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_COUNT,
+                               frag_spec >> 16);
 #endif
-    spec->size = SDL_NAME(arts_stream_get) (stream, ARTS_P_PACKET_SIZE);
+    this->spec.size = SDL_NAME(arts_stream_get) (this->hidden->stream,
+                                                 ARTS_P_PACKET_SIZE);
 
     /* Allocate mixing buffer */
-    mixlen = spec->size;
-    mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen);
-    if (mixbuf == NULL) {
-        return (-1);
+    this->hidden->mixlen = this->spec.size;
+    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+    if (this->hidden->mixbuf == NULL) {
+        ARTS_CloseDevice(this);
+        SDL_OutOfMemory();
+        return 0;
     }
-    SDL_memset(mixbuf, spec->silence, spec->size);
+    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
 
     /* Get the parent process id (we're the parent of the audio thread) */
-    parent = getpid();
+    this->hidden->parent = getpid();
 
     /* We're ready to rock and roll. :-) */
-    return (0);
+    return 1;
+}
+
+
+static void
+ARTS_Deinitialize(void)
+{
+    UnloadARTSLibrary();
 }
 
+
+static int
+ARTS_Init(SDL_AudioDriverImpl *impl)
+{
+    if (LoadARTSLibrary() < 0) {
+        return 0;
+    } else {
+        if (SDL_NAME(arts_init) () != 0) {
+            UnloadARTSLibrary();
+            SDL_SetError("ARTS: arts_init failed (no audio server?)");
+            return 0;
+        }
+
+        /* Play a stream so aRts doesn't crash */
+        arts_stream_t stream;
+        stream = SDL_NAME(arts_play_stream) (44100, 16, 2, "SDL");
+        SDL_NAME(arts_write) (stream, "", 0);
+        SDL_NAME(arts_close_stream) (stream);
+        SDL_NAME(arts_free) ();
+    }
+
+    /* Set the function pointers */
+    impl->OpenDevice = ARTS_OpenDevice;
+    impl->PlayDevice = ARTS_PlayDevice;
+    impl->WaitDevice = ARTS_WaitDevice;
+    impl->GetDeviceBuf = ARTS_GetDeviceBuf;
+    impl->CloseDevice = ARTS_CloseDevice;
+    impl->WaitDone = ARTS_WaitDone;
+    impl->Deinitialize = ARTS_Deinitialize;
+    impl->OnlyHasDefaultOutputDevice = 1;
+
+    return 1;
+}
+
+
+AudioBootStrap ARTS_bootstrap = {
+    ARTS_DRIVER_NAME, "Analog RealTime Synthesizer", ARTS_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/arts/SDL_artsaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/arts/SDL_artsaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -28,7 +28,7 @@
 
 #include "../SDL_sysaudio.h"
 
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *this
 
 struct SDL_PrivateAudioData
@@ -49,13 +49,5 @@
 };
 #define FUDGE_TICKS	10      /* The scheduler overhead ticks per frame */
 
-/* Old variable names */
-#define stream			(this->hidden->stream)
-#define parent			(this->hidden->parent)
-#define mixbuf			(this->hidden->mixbuf)
-#define mixlen			(this->hidden->mixlen)
-#define frame_ticks		(this->hidden->frame_ticks)
-#define next_frame		(this->hidden->next_frame)
-
 #endif /* _SDL_artscaudio_h */
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/baudio/SDL_beaudio.cc	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/baudio/SDL_beaudio.cc	Tue Oct 17 09:15:21 2006 +0000
@@ -36,138 +36,81 @@
 #include "../../thread/beos/SDL_systhread_c.h"
 #include "SDL_beaudio.h"
 
+}
 
-/* Audio driver functions */
-    static int BE_OpenAudio(_THIS, SDL_AudioSpec * spec);
-    static void BE_WaitAudio(_THIS);
-    static void BE_PlayAudio(_THIS);
-    static Uint8 *BE_GetAudioBuf(_THIS);
-    static void BE_CloseAudio(_THIS);
-
-/* Audio driver bootstrap functions */
 
-    static int Audio_Available(void)
-    {
-        return (1);
-    }
-
-    static void Audio_DeleteDevice(SDL_AudioDevice * device)
-    {
-        SDL_free(device->hidden);
-        SDL_free(device);
-    }
-
-    static SDL_AudioDevice *Audio_CreateDevice(int devindex)
-    {
-        SDL_AudioDevice *device;
+/* !!! FIXME: have the callback call the higher level to avoid code dupe. */
+/* The BeOS callback for handling the audio buffer */
+static void
+FillSound(void *device, void *stream, size_t len,
+          const media_raw_audio_format & format)
+{
+    SDL_AudioDevice *audio = (SDL_AudioDevice *) device;
 
-        /* Initialize all variables that we clean on shutdown */
-        device = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-        if (device) {
-            SDL_memset(device, 0, (sizeof *device));
-            device->hidden = (struct SDL_PrivateAudioData *)
-                SDL_malloc((sizeof *device->hidden));
-        }
-        if ((device == NULL) || (device->hidden == NULL)) {
-            SDL_OutOfMemory();
-            if (device) {
-                SDL_free(device);
-            }
-            return (0);
-        }
-        SDL_memset(device->hidden, 0, (sizeof *device->hidden));
-
-        /* Set the function pointers */
-        device->OpenAudio = BE_OpenAudio;
-        device->WaitAudio = BE_WaitAudio;
-        device->PlayAudio = BE_PlayAudio;
-        device->GetAudioBuf = BE_GetAudioBuf;
-        device->CloseAudio = BE_CloseAudio;
-
-        device->free = Audio_DeleteDevice;
+    /* Silence the buffer, since it's ours */
+    SDL_memset(stream, audio->spec.silence, len);
 
-        return device;
-    }
-
-    AudioBootStrap BAUDIO_bootstrap = {
-        "baudio", "BeOS BSoundPlayer",
-        Audio_Available, Audio_CreateDevice
-    };
+    /* Only do soemthing if audio is enabled */
+    if (!audio->enabled)
+        return;
 
-/* The BeOS callback for handling the audio buffer */
-    static void FillSound(void *device, void *stream, size_t len,
-                          const media_raw_audio_format & format)
-    {
-        SDL_AudioDevice *audio = (SDL_AudioDevice *) device;
-
-        /* Silence the buffer, since it's ours */
-        SDL_memset(stream, audio->spec.silence, len);
-
-        /* Only do soemthing if audio is enabled */
-        if (!audio->enabled)
-            return;
-
-        if (!audio->paused) {
-            if (audio->convert.needed) {
-                SDL_mutexP(audio->mixer_lock);
-                (*audio->spec.callback) (audio->spec.userdata,
+    if (!audio->paused) {
+        if (audio->convert.needed) {
+            SDL_mutexP(audio->mixer_lock);
+            (*audio->spec.callback) (audio->spec.userdata,
                                          (Uint8 *) audio->convert.buf,
                                          audio->convert.len);
-                SDL_mutexV(audio->mixer_lock);
-                SDL_ConvertAudio(&audio->convert);
-                SDL_memcpy(stream, audio->convert.buf,
-                           audio->convert.len_cvt);
-            } else {
-                SDL_mutexP(audio->mixer_lock);
-                (*audio->spec.callback) (audio->spec.userdata,
-                                         (Uint8 *) stream, len);
-                SDL_mutexV(audio->mixer_lock);
-            }
+            SDL_mutexV(audio->mixer_lock);
+            SDL_ConvertAudio(&audio->convert);
+            SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt);
+        } else {
+            SDL_mutexP(audio->mixer_lock);
+            (*audio->spec.callback) (audio->spec.userdata,
+                                        (Uint8 *) stream, len);
+            SDL_mutexV(audio->mixer_lock);
         }
-        return;
     }
+}
 
-/* Dummy functions -- we don't use thread-based audio */
-    void BE_WaitAudio(_THIS)
-    {
-        return;
-    }
-    void BE_PlayAudio(_THIS)
-    {
-        return;
-    }
-    Uint8 *BE_GetAudioBuf(_THIS)
-    {
-        return (NULL);
-    }
-
-    void BE_CloseAudio(_THIS)
-    {
-        if (audio_obj) {
-            audio_obj->Stop();
-            delete audio_obj;
-            audio_obj = NULL;
+static void
+BEOSAUDIO_CloseDevice(_THIS)
+{
+    if (_this->hidden != NULL) {
+        if (_this->hidden->audio_obj) {
+            _this->hidden->audio_obj->Stop();
+            delete _this->hidden->audio_obj;
+            _this->hidden->audio_obj = NULL;
         }
 
-        /* Quit the Be Application, if there's nothing left to do */
-        SDL_QuitBeApp();
+        delete _this->hidden;
+        _this->hidden = NULL;
     }
+}
 
-    int BE_OpenAudio(_THIS, SDL_AudioSpec * spec)
-    {
-        int valid_datatype = 0;
-        media_raw_audio_format format;
-        SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
+static int
+BEOSAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
+{
+    int valid_datatype = 0;
+    media_raw_audio_format format;
+    SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
 
-        /* Parse the audio format and fill the Be raw audio format */
-        memset(&format, '\0', sizeof(media_raw_audio_format));
-        format.byte_order = B_MEDIA_LITTLE_ENDIAN;
-        format.frame_rate = (float) spec->freq;
-        format.channel_count = spec->channels;  /* !!! FIXME: support > 2? */
-        while ((!valid_datatype) && (test_format)) {
-            valid_datatype = 1;
-            spec->format = test_format;
-            switch (test_format) {
+    /* Initialize all variables that we clean on shutdown */
+    _this->hidden = new SDL_PrivateAudioData;
+    if (_this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(_this->hidden, 0, (sizeof *_this->hidden));
+
+    /* Parse the audio format and fill the Be raw audio format */
+    SDL_memset(&format, '\0', sizeof(media_raw_audio_format));
+    format.byte_order = B_MEDIA_LITTLE_ENDIAN;
+    format.frame_rate = (float) _this->spec.freq;
+    format.channel_count = _this->spec.channels;  /* !!! FIXME: support > 2? */
+    while ((!valid_datatype) && (test_format)) {
+        valid_datatype = 1;
+        _this->spec.format = test_format;
+        switch (test_format) {
             case AUDIO_S8:
                 format.format = media_raw_audio_format::B_AUDIO_CHAR;
                 break;
@@ -207,43 +150,67 @@
                 valid_datatype = 0;
                 test_format = SDL_NextAudioFormat();
                 break;
-            }
         }
+    }
 
-        format.buffer_size = spec->samples;
+    format.buffer_size = _this->spec.samples;
 
-        if (!valid_datatype) {  /* shouldn't happen, but just in case... */
-            SDL_SetError("Unsupported audio format");
-            return (-1);
-        }
+    if (!valid_datatype) {  /* shouldn't happen, but just in case... */
+        BEOSAUDIO_CloseDevice(_this);
+        SDL_SetError("Unsupported audio format");
+        return 0;
+    }
 
-        /* Initialize the Be Application, if it's not already started */
-        if (SDL_InitBeApp() < 0) {
-            return (-1);
-        }
-
-        /* Calculate the final parameters for this audio specification */
-        SDL_CalculateAudioSpec(spec);
+    /* Calculate the final parameters for this audio specification */
+    SDL_CalculateAudioSpec(&_this->spec);
 
-        /* Subscribe to the audio stream (creates a new thread) */
-        {
-            sigset_t omask;
-            SDL_MaskSignals(&omask);
-            audio_obj = new BSoundPlayer(&format, "SDL Audio", FillSound,
-                                         NULL, _this);
-            SDL_UnmaskSignals(&omask);
-        }
-        if (audio_obj->Start() == B_NO_ERROR) {
-            audio_obj->SetHasData(true);
-        } else {
-            SDL_SetError("Unable to start Be audio");
-            return (-1);
-        }
+    /* Subscribe to the audio stream (creates a new thread) */
+    sigset_t omask;
+    SDL_MaskSignals(&omask);
+    _this->hidden->audio_obj = new BSoundPlayer(&format, "SDL Audio",
+                                                FillSound, NULL, _this);
+    SDL_UnmaskSignals(&omask);
 
-        /* We're running! */
-        return (1);
+    if (_this->hidden->audio_obj->Start() == B_NO_ERROR) {
+        _this->hidden->audio_obj->SetHasData(true);
+    } else {
+        BEOSAUDIO_CloseDevice(_this);
+        SDL_SetError("Unable to start Be audio");
+        return 0;
     }
 
-};                              /* Extern C */
+    /* We're running! */
+    return 1;
+}
+
+static void
+BEOSAUDIO_Deinitialize(void)
+{
+    SDL_QuitBeApp();
+}
+
+static int
+BEOSAUDIO_Init(SDL_AudioDriverImpl *impl)
+{
+    /* Initialize the Be Application, if it's not already started */
+    if (SDL_InitBeApp() < 0) {
+        return 0;
+    }
+
+    /* Set the function pointers */
+    impl->OpenDevice = BEOSAUDIO_OpenDevice;
+    impl->CloseDevice = BEOSAUDIO_CloseDevice;
+    impl->Deinitialize = BEOSAUDIO_Deinitialize;
+    impl->ProvidesOwnCallbackThread = 1;
+    impl->OnlyHasDefaultOutputDevice = 1;
+
+    return 1;
+}
+
+extern "C" { extern AudioBootStrap BEOSAUDIO_bootstrap; }
+AudioBootStrap BEOSAUDIO_bootstrap = {
+    "baudio", "BeOS BSoundPlayer", BEOSAUDIO_Init, 0
+};
 
 /* vi: set ts=4 sw=4 expandtab: */
+
--- a/src/audio/baudio/SDL_beaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/baudio/SDL_beaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -21,12 +21,12 @@
 */
 #include "SDL_config.h"
 
-#ifndef _SDL_lowaudio_h
-#define _SDL_lowaudio_h
+#ifndef _SDL_beaudio_h
+#define _SDL_beaudio_h
 
 #include "../SDL_sysaudio.h"
 
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *_this
 
 struct SDL_PrivateAudioData
@@ -34,8 +34,6 @@
     BSoundPlayer *audio_obj;
 };
 
-/* Old variable names */
-#define audio_obj	(_this->hidden->audio_obj)
+#endif /* _SDL_beaudio_h */
 
-#endif /* _SDL_lowaudio_h */
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/bsd/SDL_bsdaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/bsd/SDL_bsdaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -61,195 +61,91 @@
 /* #define DEBUG_AUDIO_STREAM */
 
 #ifdef USE_BLOCKING_WRITES
-#define OPEN_FLAGS	O_WRONLY
+#define OPEN_FLAGS_OUTPUT O_WRONLY
+#define OPEN_FLAGS_INPUT O_RDONLY
 #else
-#define OPEN_FLAGS	(O_WRONLY|O_NONBLOCK)
-#endif
-
-/* Audio driver functions */
-static void OBSD_WaitAudio(_THIS);
-static int OBSD_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void OBSD_PlayAudio(_THIS);
-static Uint8 *OBSD_GetAudioBuf(_THIS);
-static void OBSD_CloseAudio(_THIS);
-
-#ifdef DEBUG_AUDIO
-static void OBSD_Status(_THIS);
+#define OPEN_FLAGS_OUTPUT (O_WRONLY|O_NONBLOCK)
+#define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK)
 #endif
 
-/* Audio driver bootstrap functions */
-
-static int
-Audio_Available(void)
-{
-    int fd;
-    int available;
+/* !!! FIXME: so much cut and paste with dsp/dma drivers... */
+static char **outputDevices = NULL;
+static int outputDeviceCount = 0;
+static char **inputDevices = NULL;
+static int inputDeviceCount = 0;
 
-    available = 0;
-    fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
-    if (fd >= 0) {
-        available = 1;
-        close(fd);
-    }
-    return (available);
+static inline void
+free_device_list(char ***devs, int *count)
+{
+    SDL_FreeUnixAudioDevices(devs, count);
 }
 
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
+static inline void
+build_device_list(int iscapture, char ***devs, int *count)
 {
-    SDL_free(device->hidden);
-    SDL_free(device);
+    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
+    free_device_list(devs, count);
+    SDL_EnumUnixAudioDevices(flags, 0, NULL, devs, count);
 }
 
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
+static inline void
+build_device_lists(void)
 {
-    SDL_AudioDevice *this;
+    build_device_list(0, &outputDevices, &outputDeviceCount);
+    build_device_list(1, &inputDevices, &inputDeviceCount);
+}
 
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this)
-            SDL_free(this);
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-    audio_fd = -1;
 
-    /* Set the function pointers */
-    this->OpenAudio = OBSD_OpenAudio;
-    this->WaitAudio = OBSD_WaitAudio;
-    this->PlayAudio = OBSD_PlayAudio;
-    this->GetAudioBuf = OBSD_GetAudioBuf;
-    this->CloseAudio = OBSD_CloseAudio;
-
-    this->free = Audio_DeleteDevice;
-
-    return this;
+static inline void
+free_device_lists(void)
+{
+    free_device_list(&outputDevices, &outputDeviceCount);
+    free_device_list(&inputDevices, &inputDeviceCount);
 }
 
-AudioBootStrap BSD_AUDIO_bootstrap = {
-    BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC,
-    Audio_Available, Audio_CreateDevice
-};
-
-/* This function waits until it is possible to write a full sound buffer */
-static void
-OBSD_WaitAudio(_THIS)
-{
-#ifndef USE_BLOCKING_WRITES     /* Not necessary when using blocking writes */
-    /* See if we need to use timed audio synchronization */
-    if (frame_ticks) {
-        /* Use timer for general audio synchronization */
-        Sint32 ticks;
-
-        ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS;
-        if (ticks > 0) {
-            SDL_Delay(ticks);
-        }
-    } else {
-        /* Use select() for audio synchronization */
-        fd_set fdset;
-        struct timeval timeout;
-
-        FD_ZERO(&fdset);
-        FD_SET(audio_fd, &fdset);
-        timeout.tv_sec = 10;
-        timeout.tv_usec = 0;
-#ifdef DEBUG_AUDIO
-        fprintf(stderr, "Waiting for audio to get ready\n");
-#endif
-        if (select(audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) {
-            const char *message =
-                "Audio timeout - buggy audio driver? (disabled)";
-            /* In general we should never print to the screen,
-               but in this case we have no other way of letting
-               the user know what happened.
-             */
-            fprintf(stderr, "SDL: %s\n", message);
-            this->enabled = 0;
-            /* Don't try to close - may hang */
-            audio_fd = -1;
-#ifdef DEBUG_AUDIO
-            fprintf(stderr, "Done disabling audio\n");
-#endif
-        }
-#ifdef DEBUG_AUDIO
-        fprintf(stderr, "Ready!\n");
-#endif
-    }
-#endif /* !USE_BLOCKING_WRITES */
-}
 
 static void
-OBSD_PlayAudio(_THIS)
+BSDAUDIO_Deinitialize(void)
 {
-    int written, p = 0;
+    free_device_lists();
+}
+
 
-    /* Write the audio data, checking for EAGAIN on broken audio drivers */
-    do {
-        written = write(audio_fd, &mixbuf[p], mixlen - p);
-        if (written > 0)
-            p += written;
-        if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
-            /* Non recoverable error has occurred. It should be reported!!! */
-            perror("audio");
-            break;
-        }
-
-        if (p < written
-            || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) {
-            SDL_Delay(1);       /* Let a little CPU time go by */
-        }
-    }
-    while (p < written);
-
-    /* If timer synchronization is enabled, set the next write frame */
-    if (frame_ticks) {
-        next_frame += frame_ticks;
+static int
+BSDAUDIO_DetectDevices(int iscapture)
+{
+    if (iscapture) {
+        build_device_list(1, &inputDevices, &inputDeviceCount);
+        return inputDeviceCount;
+    } else {
+        build_device_list(0, &outputDevices, &outputDeviceCount);
+        return outputDeviceCount;
     }
 
-    /* If we couldn't write, assume fatal error for now */
-    if (written < 0) {
-        this->enabled = 0;
-    }
-#ifdef DEBUG_AUDIO
-    fprintf(stderr, "Wrote %d bytes of audio data\n", written);
-#endif
+    return 0;  /* shouldn't ever hit this. */
 }
 
-static Uint8 *
-OBSD_GetAudioBuf(_THIS)
+static const char *
+BSDAUDIO_GetDeviceName(int index, int iscapture)
 {
-    return (mixbuf);
+    if ((iscapture) && (index < inputDeviceCount)) {
+        return inputDevices[index];
+    } else if ((!iscapture) && (index < outputDeviceCount)) {
+        return outputDevices[index];
+    }
+
+    SDL_SetError("No such device");
+    return NULL;
 }
 
+
 static void
-OBSD_CloseAudio(_THIS)
+BSDAUDIO_Status(_THIS)
 {
-    if (mixbuf != NULL) {
-        SDL_FreeAudioMem(mixbuf);
-        mixbuf = NULL;
-    }
-    if (audio_fd >= 0) {
-        close(audio_fd);
-        audio_fd = -1;
-    }
-}
-
 #ifdef DEBUG_AUDIO
-void
-OBSD_Status(_THIS)
-{
     audio_info_t info;
 
-    if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) {
+    if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
         fprintf(stderr, "AUDIO_GETINFO failed.\n");
         return;
     }
@@ -269,46 +165,18 @@
             "waiting		:   %s\n"
             "active		:   %s\n"
             "",
-            info.
-            play.
-            buffer_size,
-            info.
-            play.
-            sample_rate,
-            info.
-            play.
-            channels,
-            info.
-            play.
-            precision,
-            info.
-            play.
-            encoding,
-            info.
-            play.
-            seek,
-            info.
-            play.
-            samples,
-            info.
-            play.
-            eof,
-            info.
-            play.
-            pause
-            ?
-            "yes"
-            :
-            "no",
-            info.
-            play.
-            error
-            ?
-            "yes"
-            :
-            "no",
-            info.
-            play.waiting ? "yes" : "no", info.play.active ? "yes" : "no");
+            info.play.buffer_size,
+            info.play.sample_rate,
+            info.play.channels,
+            info.play.precision,
+            info.play.encoding,
+            info.play.seek,
+            info.play.samples,
+            info.play.eof,
+            info.play.pause ? "yes" : "no",
+            info.play.error ? "yes" : "no",
+            info.play.waiting ? "yes" : "no",
+            info.play.active ? "yes" : "no");
 
     fprintf(stderr, "\n"
             "[audio info]\n"
@@ -324,42 +192,170 @@
             (info.mode == AUMODE_PLAY) ? "PLAY"
             : (info.mode = AUMODE_RECORD) ? "RECORD"
             : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?"));
+#endif /* DEBUG_AUDIO */
 }
-#endif /* DEBUG_AUDIO */
+
+
+/* This function waits until it is possible to write a full sound buffer */
+static void
+BSDAUDIO_WaitDevice(_THIS)
+{
+#ifndef USE_BLOCKING_WRITES     /* Not necessary when using blocking writes */
+    /* See if we need to use timed audio synchronization */
+    if (this->hidden->frame_ticks) {
+        /* Use timer for general audio synchronization */
+        Sint32 ticks;
+
+        ticks = ((Sint32)(this->hidden->next_frame-SDL_GetTicks()))-FUDGE_TICKS;
+        if (ticks > 0) {
+            SDL_Delay(ticks);
+        }
+    } else {
+        /* Use select() for audio synchronization */
+        fd_set fdset;
+        struct timeval timeout;
+
+        FD_ZERO(&fdset);
+        FD_SET(this->hidden->audio_fd, &fdset);
+        timeout.tv_sec = 10;
+        timeout.tv_usec = 0;
+#ifdef DEBUG_AUDIO
+        fprintf(stderr, "Waiting for audio to get ready\n");
+#endif
+        if (select(this->hidden->audio_fd+1,NULL,&fdset,NULL,&timeout) <= 0) {
+            const char *message =
+                "Audio timeout - buggy audio driver? (disabled)";
+            /* In general we should never print to the screen,
+               but in this case we have no other way of letting
+               the user know what happened.
+             */
+            fprintf(stderr, "SDL: %s\n", message);
+            this->enabled = 0;
+            /* Don't try to close - may hang */
+            this->hidden->audio_fd = -1;
+#ifdef DEBUG_AUDIO
+            fprintf(stderr, "Done disabling audio\n");
+#endif
+        }
+#ifdef DEBUG_AUDIO
+        fprintf(stderr, "Ready!\n");
+#endif
+    }
+#endif /* !USE_BLOCKING_WRITES */
+}
+
+static void
+BSDAUDIO_PlayDevice(_THIS)
+{
+    int written, p = 0;
+
+    /* Write the audio data, checking for EAGAIN on broken audio drivers */
+    do {
+        written = write(this->hidden->audio_fd,
+                        &this->hidden->mixbuf[p],
+                        this->hidden->mixlen - p);
+
+        if (written > 0)
+            p += written;
+        if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
+            /* Non recoverable error has occurred. It should be reported!!! */
+            perror("audio");
+            break;
+        }
+
+        if (p < written
+            || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) {
+            SDL_Delay(1);       /* Let a little CPU time go by */
+        }
+    }
+    while (p < written);
+
+    /* If timer synchronization is enabled, set the next write frame */
+    if (this->hidden->frame_ticks) {
+        this->hidden->next_frame += this->hidden->frame_ticks;
+    }
+
+    /* If we couldn't write, assume fatal error for now */
+    if (written < 0) {
+        this->enabled = 0;
+    }
+#ifdef DEBUG_AUDIO
+    fprintf(stderr, "Wrote %d bytes of audio data\n", written);
+#endif
+}
+
+static Uint8 *
+BSDAUDIO_GetDeviceBuf(_THIS)
+{
+    return (this->hidden->mixbuf);
+}
+
+static void
+BSDAUDIO_CloseDevice(_THIS)
+{
+    if (this->hidden != NULL) {
+        if (this->hidden->mixbuf != NULL) {
+            SDL_FreeAudioMem(this->hidden->mixbuf);
+            this->hidden->mixbuf = NULL;
+        }
+        if (this->hidden->audio_fd >= 0) {
+            close(this->hidden->audio_fd);
+            this->hidden->audio_fd = -1;
+        }
+        SDL_free(this->hidden);
+        this->hidden = NULL;
+    }
+}
 
 static int
-OBSD_OpenAudio(_THIS, SDL_AudioSpec * spec)
+BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-    char audiodev[64];
-    SDL_AudioFormat format;
+    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
+    SDL_AudioFormat format = 0;
     audio_info_t info;
 
+    /* We don't care what the devname is...we'll try to open anything. */
+    /*  ...but default to first name in the list... */
+    if (devname == NULL) {
+        if ( ((iscapture) && (inputDeviceCount == 0)) ||
+             ((!iscapture) && (outputDeviceCount == 0)) ) {
+            SDL_SetError("No such audio device");
+            return 0;
+        }
+        devname = ((iscapture) ? inputDevices[0] : outputDevices[0]);
+    }
+
+    /* Initialize all variables that we clean on shutdown */
+    this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+
+    /* Open the audio device */
+    this->hidden->audio_fd = open(devname, flags, 0);
+    if (this->hidden->audio_fd < 0) {
+        SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
+        return 0;
+    }
+
     AUDIO_INITINFO(&info);
 
     /* Calculate the final parameters for this audio specification */
-    SDL_CalculateAudioSpec(spec);
-
-#ifdef USE_TIMER_SYNC
-    frame_ticks = 0.0;
-#endif
-
-    /* Open the audio device */
-    audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
-    if (audio_fd < 0) {
-        SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
-        return (-1);
-    }
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* Set to play mode */
     info.mode = AUMODE_PLAY;
-    if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) {
+    if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
+        BSDAUDIO_CloseDevice(this);
         SDL_SetError("Couldn't put device into play mode");
-        return (-1);
+        return 0;
     }
 
-    mixbuf = NULL;
     AUDIO_INITINFO(&info);
-    for (format = SDL_FirstAudioFormat(spec->format);
+    for (format = SDL_FirstAudioFormat(this->spec.format);
          format; format = SDL_NextAudioFormat()) {
         switch (format) {
         case AUDIO_U8:
@@ -389,46 +385,69 @@
         default:
             continue;
         }
-        if (ioctl(audio_fd, AUDIO_SETINFO, &info) == 0)
+
+        if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) {
             break;
+        }
     }
 
     if (!format) {
-        SDL_SetError("No supported encoding for 0x%x", spec->format);
-        return (-1);
+        BSDAUDIO_CloseDevice(this);
+        SDL_SetError("No supported encoding for 0x%x", this->spec.format);
+        return 0;
     }
 
-    spec->format = format;
+    this->spec.format = format;
 
     AUDIO_INITINFO(&info);
-    info.play.channels = spec->channels;
-    if (ioctl(audio_fd, AUDIO_SETINFO, &info) == -1)
-        spec->channels = 1;
+    info.play.channels = this->spec.channels;
+    if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) {
+        this->spec.channels = 1;
+    }
     AUDIO_INITINFO(&info);
-    info.play.sample_rate = spec->freq;
-    info.blocksize = spec->size;
+    info.play.sample_rate = this->spec.freq;
+    info.blocksize = this->spec.size;
     info.hiwat = 5;
     info.lowat = 3;
-    (void) ioctl(audio_fd, AUDIO_SETINFO, &info);
-    (void) ioctl(audio_fd, AUDIO_GETINFO, &info);
-    spec->freq = info.play.sample_rate;
+    (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
+    (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
+    this->spec.freq = info.play.sample_rate;
     /* Allocate mixing buffer */
-    mixlen = spec->size;
-    mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen);
-    if (mixbuf == NULL) {
-        return (-1);
+    this->hidden->mixlen = this->spec.size;
+    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+    if (this->hidden->mixbuf == NULL) {
+        BSDAUDIO_CloseDevice(this);
+        SDL_OutOfMemory();
+        return 0;
     }
-    SDL_memset(mixbuf, spec->silence, spec->size);
+    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
 
-    /* Get the parent process id (we're the parent of the audio thread) */
-    parent = getpid();
-
-#ifdef DEBUG_AUDIO
-    OBSD_Status(this);
-#endif
+    BSDAUDIO_Status(this);
 
     /* We're ready to rock and roll. :-) */
     return (0);
 }
 
+static int
+BSDAUDIO_Init(SDL_AudioDriverImpl *impl)
+{
+    /* Set the function pointers */
+    impl->DetectDevices = BSDAUDIO_DetectDevices;
+    impl->GetDeviceName = BSDAUDIO_GetDeviceName;
+    impl->OpenDevice = BSDAUDIO_OpenDevice;
+    impl->PlayDevice = BSDAUDIO_PlayDevice;
+    impl->WaitDevice = BSDAUDIO_WaitDevice;
+    impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
+    impl->CloseDevice = BSDAUDIO_CloseDevice;
+    impl->Deinitialize = BSDAUDIO_Deinitialize;
+
+    build_device_lists();
+    return 1;
+}
+
+
+AudioBootStrap BSD_AUDIO_bootstrap = {
+    BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC, BSDAUDIO_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/bsd/SDL_bsdaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/bsd/SDL_bsdaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -21,8 +21,8 @@
 */
 #include "SDL_config.h"
 
-#ifndef _SDL_openbsdaudio_h
-#define _SDL_openbsdaudio_h
+#ifndef _SDL_bsdaudio_h
+#define _SDL_bsdaudio_h
 
 #include "../SDL_sysaudio.h"
 
@@ -47,13 +47,6 @@
 
 #define FUDGE_TICKS	10      /* The scheduler overhead ticks per frame */
 
-/* Old variable names */
-#define audio_fd		(this->hidden->audio_fd)
-#define parent			(this->hidden->parent)
-#define mixbuf			(this->hidden->mixbuf)
-#define mixlen			(this->hidden->mixlen)
-#define frame_ticks		(this->hidden->frame_ticks)
-#define next_frame		(this->hidden->next_frame)
+#endif /* _SDL_bsdaudio_h */
 
-#endif /* _SDL_openbsdaudio_h */
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/dart/SDL_dart.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/dart/SDL_dart.c	Tue Oct 17 09:15:21 2006 +0000
@@ -42,10 +42,10 @@
 //---------------------------------------------------------------------
 // DARTEventFunc
 //
-// This function is called by DART, when an event occures, like end of 
+// This function is called by DART, when an event occurs, like end of
 // playback of a buffer, etc...
 //---------------------------------------------------------------------
-LONG APIENTRY
+static LONG APIENTRY
 DARTEventFunc(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags)
 {
     if (ulFlags && MIX_WRITE_COMPLETE) {        // Playback of buffer completed!
@@ -71,13 +71,12 @@
 }
 
 
-int
-DART_OpenAudio(_THIS, SDL_AudioSpec * spec)
+static int
+DART_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
+    SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
     int valid_datatype = 0;
     MCI_AMP_OPEN_PARMS AmpOpenParms;
-    MCI_GENERIC_PARMS GenericParms;
     int iDeviceOrd = 0;         // Default device to be used
     int bOpenShared = 1;        // Try opening it shared
     int iBits = 16;             // Default is 16 bits signed
@@ -89,6 +88,15 @@
     int iSilence;
     int rc;
 
+    /* Initialize all variables that we clean on shutdown */
+    _this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *_this->hidden));
+    if (_this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(_this->hidden, 0, (sizeof *_this->hidden));
+
     // First thing is to try to open a given DART device!
     SDL_memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
     // pszDeviceType should contain the device type in low word, and device ordinal in high word!
@@ -100,30 +108,34 @@
         iOpenMode |= MCI_OPEN_SHAREABLE;
 
     rc = mciSendCommand(0, MCI_OPEN, iOpenMode, (PVOID) & AmpOpenParms, 0);
-    if (rc != MCIERR_SUCCESS)   // No audio available??
-        return (-1);
+    if (rc != MCIERR_SUCCESS) {  // No audio available??
+        DART_CloseDevice(_this);
+        SDL_SetError("DART: Couldn't open audio device.");
+        return 0;
+    }
+
     // Save the device ID we got from DART!
     // We will use this in the next calls!
-    iDeviceOrd = AmpOpenParms.usDeviceID;
+    _this->hidden->iCurrDeviceOrd = iDeviceOrd = AmpOpenParms.usDeviceID;
 
     // Determine the audio parameters from the AudioSpec
-    if (spec->channels > 2)
-        spec->channels = 2;     // !!! FIXME: more than stereo support in OS/2?
+    if (_this->spec.channels > 4)
+        _this->spec.channels = 4;
 
     while ((!valid_datatype) && (test_format)) {
-        spec->format = test_format;
+        _this->spec.format = test_format;
         valid_datatype = 1;
         switch (test_format) {
         case AUDIO_U8:
             // Unsigned 8 bit audio data
             iSilence = 0x80;
-            iBits = 8;
+            _this->hidden->iCurrBits = iBits = 8;
             break;
 
         case AUDIO_S16LSB:
             // Signed 16 bit audio data
             iSilence = 0x00;
-            iBits = 16;
+            _this->hidden->iCurrBits = iBits = 16;
             break;
 
             // !!! FIXME: int32?
@@ -137,16 +149,16 @@
 
     if (!valid_datatype) {      // shouldn't happen, but just in case...
         // Close DART, and exit with error code!
-        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+        DART_CloseDevice(_this);
         SDL_SetError("Unsupported audio format");
-        return (-1);
+        return 0;
     }
 
-    iFreq = spec->freq;
-    iChannels = spec->channels;
+    _this->hidden->iCurrFreq = iFreq = _this->spec.freq;
+    _this->hidden->iCurrChannels = iChannels = _this->spec.channels;
     /* Update the fragment size as size in bytes */
-    SDL_CalculateAudioSpec(spec);
-    iBufSize = spec->size;
+    SDL_CalculateAudioSpec(&_this->spec);
+    _this->hidden->iCurrBufSize = iBufSize = _this->spec.size;
 
     // Now query this device if it supports the given freq/bits/channels!
     SDL_memset(&(_this->hidden->MixSetupParms), 0,
@@ -163,9 +175,9 @@
                         &(_this->hidden->MixSetupParms), 0);
     if (rc != MCIERR_SUCCESS) { // The device cannot handle this format!
         // Close DART, and exit with error code!
-        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+        DART_CloseDevice(_this);
         SDL_SetError("Audio device doesn't support requested audio format");
-        return (-1);
+        return 0;
     }
     // The device can handle this format, so initialize!
     rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP,
@@ -173,9 +185,9 @@
                         &(_this->hidden->MixSetupParms), 0);
     if (rc != MCIERR_SUCCESS) { // The device could not be opened!
         // Close DART, and exit with error code!
-        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+        DART_CloseDevice(_this);
         SDL_SetError("Audio device could not be set up");
-        return (-1);
+        return 0;
     }
     // Ok, the device is initialized.
     // Now we should allocate buffers. For this, we need a place where
@@ -184,9 +196,9 @@
         (MCI_MIX_BUFFER *) SDL_malloc(sizeof(MCI_MIX_BUFFER) * iNumBufs);
     if (!(_this->hidden->pMixBuffers)) {        // Not enough memory!
         // Close DART, and exit with error code!
-        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
-        SDL_SetError("Not enough memory for audio buffer descriptors");
-        return (-1);
+        DART_CloseDevice(_this);
+        SDL_OutOfMemory();
+        return 0;
     }
     // Now that we have the place for buffer list, we can ask DART for the
     // buffers!
@@ -201,12 +213,12 @@
         || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers)
         || (_this->hidden->BufferParms.ulBufferSize == 0)) {    // Could not allocate memory!
         // Close DART, and exit with error code!
-        SDL_free(_this->hidden->pMixBuffers);
-        _this->hidden->pMixBuffers = NULL;
-        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+        DART_CloseDevice(_this);
         SDL_SetError("DART could not allocate buffers");
-        return (-1);
+        return 0;
     }
+    _this->hidden->iCurrNumBufs = iNumBufs;
+
     // Ok, we have all the buffers allocated, let's mark them!
     {
         int i;
@@ -216,24 +228,9 @@
             // Check if this buffer was really allocated by DART
             if ((!(_this->hidden->pMixBuffers[i].pBuffer))
                 || (!pBufferDesc)) {    // Wrong buffer!
-                // Close DART, and exit with error code!
-                // Free buffer descriptions
-                {
-                    int j;
-                    for (j = 0; j < i; j++)
-                        SDL_free((void *) (_this->hidden->pMixBuffers[j].
-                                           ulUserParm));
-                }
-                // and cleanup
-                mciSendCommand(iDeviceOrd, MCI_BUFFER,
-                               MCI_WAIT | MCI_DEALLOCATE_MEMORY,
-                               &(_this->hidden->BufferParms), 0);
-                SDL_free(_this->hidden->pMixBuffers);
-                _this->hidden->pMixBuffers = NULL;
-                mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT,
-                               &GenericParms, 0);
+                DART_CloseDevice(_this);
                 SDL_SetError("Error at internal buffer check");
-                return (-1);
+                return 0;
             }
             pBufferDesc->iBufferUsage = BUFFER_EMPTY;
             pBufferDesc->pSDLAudioDevice = _this;
@@ -254,43 +251,41 @@
     if (DosCreateEventSem
         (NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE) != NO_ERROR)
     {
-        // Could not create event semaphore!
-        {
-            int i;
-            for (i = 0; i < iNumBufs; i++)
-                SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm));
-        }
-        mciSendCommand(iDeviceOrd, MCI_BUFFER,
-                       MCI_WAIT | MCI_DEALLOCATE_MEMORY,
-                       &(_this->hidden->BufferParms), 0);
-        SDL_free(_this->hidden->pMixBuffers);
-        _this->hidden->pMixBuffers = NULL;
-        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+        DART_CloseDevice(_this);
         SDL_SetError("Could not create event semaphore");
-        return (-1);
+        return 0;
     }
-    // Store the new settings in global variables
-    _this->hidden->iCurrDeviceOrd = iDeviceOrd;
-    _this->hidden->iCurrFreq = iFreq;
-    _this->hidden->iCurrBits = iBits;
-    _this->hidden->iCurrChannels = iChannels;
-    _this->hidden->iCurrNumBufs = iNumBufs;
-    _this->hidden->iCurrBufSize = iBufSize;
 
-    return (0);
+    return 1;
 }
 
-
-
-void
+static void
 DART_ThreadInit(_THIS)
 {
-    return;
+    /* Increase the priority of this thread to make sure that
+       the audio will be continuous all the time! */
+#ifdef USE_DOSSETPRIORITY
+    if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) {
+#ifdef DEBUG_BUILD
+        printf
+            ("[DART_ThreadInit] : Setting priority to TimeCritical+0! (TID%d)\n",
+             SDL_ThreadID());
+#endif
+        DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
+    } else {
+#ifdef DEBUG_BUILD
+        printf
+            ("[DART_ThreadInit] : Setting priority to ForegroundServer+0! (TID%d)\n",
+             SDL_ThreadID());
+#endif
+        DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
+    }
+#endif
 }
 
 /* This function waits until it is possible to write a full sound buffer */
-void
-DART_WaitAudio(_THIS)
+static void
+DART_WaitDevice(_THIS)
 {
     int i;
     pMixBufferDesc pBufDesc;
@@ -308,8 +303,8 @@
     return;
 }
 
-void
-DART_PlayAudio(_THIS)
+static void
+DART_PlayDevice(_THIS)
 {
     int iFreeBuf = _this->hidden->iNextFreeBuffer;
     pMixBufferDesc pBufDesc;
@@ -328,8 +323,8 @@
     _this->hidden->iNextFreeBuffer = iFreeBuf;
 }
 
-Uint8 *
-DART_GetAudioBuf(_THIS)
+static Uint8 *
+DART_GetDeviceBuf(_THIS)
 {
     int iFreeBuf;
     Uint8 *pResult;
@@ -348,125 +343,110 @@
                     return pResult;
                 }
             } else
-                printf("[DART_GetAudioBuf] : ERROR! pBufDesc = %p\n",
+                printf("[DART_GetDeviceBuf] : ERROR! pBufDesc = %p\n",
                        pBufDesc);
         } else
-            printf("[DART_GetAudioBuf] : ERROR! _this->hidden = %p\n",
+            printf("[DART_GetDeviceBuf] : ERROR! _this->hidden = %p\n",
                    _this->hidden);
     } else
-        printf("[DART_GetAudioBuf] : ERROR! _this = %p\n", _this);
+        printf("[DART_GetDeviceBuf] : ERROR! _this = %p\n", _this);
     return NULL;
 }
 
-void
+static void
 DART_WaitDone(_THIS)
 {
     pMixBufferDesc pBufDesc;
-    ULONG ulPostCount;
-    APIRET rc;
+    ULONG ulPostCount = 0;
+    APIRET rc = NO_ERROR;
 
-    pBufDesc =
-        (pMixBufferDesc) _this->hidden->pMixBuffers[_this->hidden->
-                                                    iLastPlayedBuf].
-        ulUserParm;
-    rc = NO_ERROR;
+    pBufDesc = (pMixBufferDesc)
+          _this->hidden->pMixBuffers[_this->hidden->iLastPlayedBuf].ulUserParm;
+
     while ((pBufDesc->iBufferUsage != BUFFER_EMPTY) && (rc == NO_ERROR)) {
         DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount);
         rc = DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000);        // 1 sec timeout! Important!
     }
 }
 
-void
-DART_CloseAudio(_THIS)
+static void
+DART_CloseDevice(_THIS)
 {
     MCI_GENERIC_PARMS GenericParms;
     int rc;
+    int i;
 
-    // Stop DART playback
-    rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP, MCI_WAIT,
-                        &GenericParms, 0);
-    if (rc != MCIERR_SUCCESS) {
+    if (_this->hidden != NULL) {
+        // Stop DART playback
+        if (_this->hidden->iCurrDeviceOrd) {
+            rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP,
+                                MCI_WAIT, &GenericParms, 0);
 #ifdef SFX_DEBUG_BUILD
-        printf("Could not stop DART playback!\n");
-        fflush(stdout);
+            if (rc != MCIERR_SUCCESS) {
+                printf("Could not stop DART playback!\n");
+                fflush(stdout);
+            }
 #endif
-    }
-    // Close event semaphore
-    DosCloseEventSem(_this->hidden->hevAudioBufferPlayed);
+        }
 
-    // Free memory of buffer descriptions
-    {
-        int i;
-        for (i = 0; i < _this->hidden->iCurrNumBufs; i++)
-            SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm));
-    }
+        // Close event semaphore
+        if (_this->hidden->hevAudioBufferPlayed) {
+            DosCloseEventSem(_this->hidden->hevAudioBufferPlayed);
+            _this->hidden->hevAudioBufferPlayed = 0;
+        }
 
-    // Deallocate buffers
-    rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER,
-                        MCI_WAIT | MCI_DEALLOCATE_MEMORY,
-                        &(_this->hidden->BufferParms), 0);
+        // Free memory of buffer descriptions
+        for (i = 0; i < _this->hidden->iCurrNumBufs; i++) {
+            SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm));
+            _this->hidden->pMixBuffers[i].ulUserParm = 0;
+        }
+        _this->hidden->iCurrNumBufs = 0;
 
-    // Free bufferlist
-    SDL_free(_this->hidden->pMixBuffers);
-    _this->hidden->pMixBuffers = NULL;
+        // Deallocate buffers
+        if (_this->hidden->iCurrDeviceOrd) {
+            rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER,
+                                MCI_WAIT | MCI_DEALLOCATE_MEMORY,
+                                &(_this->hidden->BufferParms), 0);
+        }
 
-    // Close dart
-    rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE, MCI_WAIT,
-                        &(GenericParms), 0);
-}
+        // Free bufferlist
+        if (_this->hidden->pMixBuffers != NULL) {
+            SDL_free(_this->hidden->pMixBuffers);
+            _this->hidden->pMixBuffers = NULL;
+        }
 
-/* Audio driver bootstrap functions */
+        // Close dart
+        if (_this->hidden->iCurrDeviceOrd) {
+            rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE,
+                                MCI_WAIT, &(GenericParms), 0);
+        }
+        _this->hidden->iCurrDeviceOrd = 0;
 
-int
-Audio_Available(void)
-{
-    return (1);
+        SDL_free(_this->hidden);
+        _this->hidden = NULL;
+    }
 }
 
-void
-Audio_DeleteDevice(SDL_AudioDevice * device)
+
+static int
+DART_Init(SDL_AudioDriverImpl *impl)
 {
-    SDL_free(device->hidden);
-    SDL_free(device);
+    /* Set the function pointers */
+    impl->OpenDevice = DART_OpenDevice;
+    impl->ThreadInit = DART_ThreadInit;
+    impl->WaitDevice = DART_WaitDevice;
+    impl->GetDeviceBuf = DART_GetDeviceBuf;
+    impl->PlayDevice = DART_PlayDevice;
+    impl->WaitDone = DART_WaitDone;
+    impl->CloseDevice = DART_CloseDevice;
+    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: is this right? */
+
+    return 1;
 }
 
-SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
-{
-    SDL_AudioDevice *this;
-
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this)
-            SDL_free(this);
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    /* Set the function pointers */
-    this->OpenAudio = DART_OpenAudio;
-    this->ThreadInit = DART_ThreadInit;
-    this->WaitAudio = DART_WaitAudio;
-    this->PlayAudio = DART_PlayAudio;
-    this->GetAudioBuf = DART_GetAudioBuf;
-    this->WaitDone = DART_WaitDone;
-    this->CloseAudio = DART_CloseAudio;
-
-    this->free = Audio_DeleteDevice;
-
-    return this;
-}
 
 AudioBootStrap DART_bootstrap = {
-    "dart", "OS/2 Direct Audio RouTines (DART)",
-    Audio_Available, Audio_CreateDevice
+    "dart", "OS/2 Direct Audio RouTines (DART)", DART_Init, 0
 };
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/dart/SDL_dart.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/dart/SDL_dart.h	Tue Oct 17 09:15:21 2006 +0000
@@ -21,14 +21,15 @@
 */
 #include "SDL_config.h"
 
-#ifndef _SDL_lowaudio_h
-#define _SDL_lowaudio_h
+#ifndef _SDL_dart_h
+#define _SDL_dart_h
 
 #define INCL_TYPES
 #define INCL_DOSSEMAPHORES
 #define INCL_DOSRESOURCES
 #define INCL_DOSMISC
 #define INCL_DOSERRORS
+#define INCL_DOSPROCESS
 
 #define INCL_OS2MM
 #define INCL_MMIOOS2
@@ -60,5 +61,6 @@
     HEV hevAudioBufferPlayed;   // Event semaphore to indicate that an audio buffer has been played by DART
 };
 
-#endif /* _SDL_lowaudio_h */
+#endif /* _SDL_dart_h */
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/dc/SDL_dcaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/dc/SDL_dcaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -28,85 +28,11 @@
 #include "SDL_audio.h"
 #include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
-#include "../SDL_audiodev_c.h"
 #include "SDL_dcaudio.h"
 
 #include "aica.h"
 #include <dc/spu.h>
 
-/* Audio driver functions */
-static int DCAUD_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void DCAUD_WaitAudio(_THIS);
-static void DCAUD_PlayAudio(_THIS);
-static Uint8 *DCAUD_GetAudioBuf(_THIS);
-static void DCAUD_CloseAudio(_THIS);
-
-/* Audio driver bootstrap functions */
-static int
-DCAUD_Available(void)
-{
-    return 1;
-}
-
-static void
-DCAUD_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
-}
-
-static SDL_AudioDevice *
-DCAUD_CreateDevice(int devindex)
-{
-    SDL_AudioDevice *this;
-
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    /* Set the function pointers */
-    this->OpenAudio = DCAUD_OpenAudio;
-    this->WaitAudio = DCAUD_WaitAudio;
-    this->PlayAudio = DCAUD_PlayAudio;
-    this->GetAudioBuf = DCAUD_GetAudioBuf;
-    this->CloseAudio = DCAUD_CloseAudio;
-
-    this->free = DCAUD_DeleteDevice;
-
-    spu_init();
-
-    return this;
-}
-
-AudioBootStrap DCAUD_bootstrap = {
-    "dcaudio", "Dreamcast AICA audio",
-    DCAUD_Available, DCAUD_CreateDevice
-};
-
-/* This function waits until it is possible to write a full sound buffer */
-static void
-DCAUD_WaitAudio(_THIS)
-{
-    if (this->hidden->playing) {
-        /* wait */
-        while (aica_get_pos(0) / this->spec.samples == this->hidden->nextbuf) {
-            thd_pass();
-        }
-    }
-}
-
 #define	SPU_RAM_BASE	0xa0800000
 
 static void
@@ -152,7 +78,7 @@
 }
 
 static void
-DCAUD_PlayAudio(_THIS)
+DCAUD_PlayDevice(_THIS)
 {
     SDL_AudioSpec *spec = &this->spec;
     unsigned int offset;
@@ -200,28 +126,59 @@
 }
 
 static Uint8 *
-DCAUD_GetAudioBuf(_THIS)
+DCAUD_GetDeviceBuf(_THIS)
 {
     return (this->hidden->mixbuf);
 }
 
+/* This function waits until it is possible to write a full sound buffer */
 static void
-DCAUD_CloseAudio(_THIS)
+DCAUD_WaitDevice(_THIS)
 {
-    aica_stop(0);
-    if (this->spec.channels == 2)
-        aica_stop(1);
-    if (this->hidden->mixbuf != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
+    if (this->hidden->playing) {
+        /* wait */
+        while (aica_get_pos(0) / this->spec.samples == this->hidden->nextbuf) {
+            thd_pass();
+        }
+    }
+}
+
+static void
+DCAUD_CloseDevice(_THIS)
+{
+    if (this->hidden != NULL) {
+        aica_stop(0);
+        if (this->spec.channels == 2) {
+            aica_stop(1);
+        }
+        if (this->hidden->mixbuf != NULL) {
+            SDL_FreeAudioMem(this->hidden->mixbuf);
+            this->hidden->mixbuf = NULL;
+        }
+        SDL_free(this->hidden);
+        this->hidden = NULL;
+
+        /* !!! FIXME: is there a reverse of spu_init()? */
     }
 }
 
 static int
-DCAUD_OpenAudio(_THIS, SDL_AudioSpec * spec)
+DCAUD_OpenDevice(_THIS, SDL_AudioSpec * spec)
 {
     SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
     int valid_datatype = 0;
+
+    /* Initialize all variables that we clean on shutdown */
+    this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+
+    spu_init();
+
     while ((!valid_datatype) && (test_format)) {
         spec->format = test_format;
         switch (test_format) {
@@ -238,8 +195,9 @@
     }
 
     if (!valid_datatype) {      /* shouldn't happen, but just in case... */
+        DCAUD_CloseDevice(this);
         SDL_SetError("Unsupported audio format");
-        return (-1);
+        return 0;
     }
 
     if (spec->channels > 2)
@@ -252,7 +210,9 @@
     this->hidden->mixlen = spec->size;
     this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
-        return (-1);
+        DCAUD_CloseDevice(this);
+        SDL_OutOfMemory();
+        return 0;
     }
     SDL_memset(this->hidden->mixbuf, spec->silence, spec->size);
     this->hidden->leftpos = 0x11000;
@@ -261,7 +221,25 @@
     this->hidden->nextbuf = 0;
 
     /* We're ready to rock and roll. :-) */
-    return (0);
+    return 1;
 }
 
+static int
+DCAUD_Init(SDL_AudioDriverImpl *impl)
+{
+    /* Set the function pointers */
+    impl->OpenDevice = DCAUD_OpenDevice;
+    impl->PlayDevice = DCAUD_PlayDevice;
+    impl->WaitDevice = DCAUD_WaitDevice;
+    impl->GetDeviceBuf = DCAUD_GetDeviceBuf;
+    impl->CloseDevice = DCAUD_CloseDevice;
+    impl->OnlyHasDefaultOutputDevice = 1;
+
+    return 1;
+}
+
+AudioBootStrap DCAUD_bootstrap = {
+    "dcaudio", "Dreamcast AICA audio", DCAUD_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/dc/SDL_dcaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/dc/SDL_dcaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -26,7 +26,7 @@
 
 #include "../SDL_sysaudio.h"
 
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *this
 
 struct SDL_PrivateAudioData
--- a/src/audio/disk/SDL_diskaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/disk/SDL_diskaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -34,7 +34,6 @@
 #include "SDL_audio.h"
 #include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
-#include "../SDL_audiodev_c.h"
 #include "SDL_diskaudio.h"
 
 /* The tag name used by DISK audio */
@@ -46,90 +45,27 @@
 #define DISKENVR_WRITEDELAY      "SDL_DISKAUDIODELAY"
 #define DISKDEFAULT_WRITEDELAY   150
 
-/* Audio driver functions */
-static int DISKAUD_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void DISKAUD_WaitAudio(_THIS);
-static void DISKAUD_PlayAudio(_THIS);
-static Uint8 *DISKAUD_GetAudioBuf(_THIS);
-static void DISKAUD_CloseAudio(_THIS);
-
 static const char *
-DISKAUD_GetOutputFilename(void)
-{
-    const char *envr = SDL_getenv(DISKENVR_OUTFILE);
-    return ((envr != NULL) ? envr : DISKDEFAULT_OUTFILE);
-}
-
-/* Audio driver bootstrap functions */
-static int
-DISKAUD_Available(void)
-{
-    const char *envr = SDL_getenv("SDL_AUDIODRIVER");
-    if (envr && (SDL_strcmp(envr, DISKAUD_DRIVER_NAME) == 0)) {
-        return (1);
-    }
-    return (0);
-}
-
-static void
-DISKAUD_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
-}
-
-static SDL_AudioDevice *
-DISKAUD_CreateDevice(int devindex)
+DISKAUD_GetOutputFilename(const char *devname)
 {
-    SDL_AudioDevice *this;
-    const char *envr;
-
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
+    if (devname == NULL) {
+        devname = SDL_getenv(DISKENVR_OUTFILE);
+        if (devname == NULL) {
+            devname = DISKDEFAULT_OUTFILE;
         }
-        return (0);
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    envr = SDL_getenv(DISKENVR_WRITEDELAY);
-    this->hidden->write_delay =
-        (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
-
-    /* Set the function pointers */
-    this->OpenAudio = DISKAUD_OpenAudio;
-    this->WaitAudio = DISKAUD_WaitAudio;
-    this->PlayAudio = DISKAUD_PlayAudio;
-    this->GetAudioBuf = DISKAUD_GetAudioBuf;
-    this->CloseAudio = DISKAUD_CloseAudio;
-
-    this->free = DISKAUD_DeleteDevice;
-
-    return this;
+    return devname;
 }
 
-AudioBootStrap DISKAUD_bootstrap = {
-    DISKAUD_DRIVER_NAME, "direct-to-disk audio",
-    DISKAUD_Available, DISKAUD_CreateDevice
-};
-
 /* This function waits until it is possible to write a full sound buffer */
 static void
-DISKAUD_WaitAudio(_THIS)
+DISKAUD_WaitDevice(_THIS)
 {
     SDL_Delay(this->hidden->write_delay);
 }
 
 static void
-DISKAUD_PlayAudio(_THIS)
+DISKAUD_PlayDevice(_THIS)
 {
     int written;
 
@@ -147,49 +83,86 @@
 }
 
 static Uint8 *
-DISKAUD_GetAudioBuf(_THIS)
+DISKAUD_GetDeviceBuf(_THIS)
 {
     return (this->hidden->mixbuf);
 }
 
 static void
-DISKAUD_CloseAudio(_THIS)
+DISKAUD_CloseDevice(_THIS)
 {
-    if (this->hidden->mixbuf != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-    }
-    if (this->hidden->output != NULL) {
-        SDL_RWclose(this->hidden->output);
-        this->hidden->output = NULL;
+    if (this->hidden != NULL) {
+        if (this->hidden->mixbuf != NULL) {
+            SDL_FreeAudioMem(this->hidden->mixbuf);
+            this->hidden->mixbuf = NULL;
+        }
+        if (this->hidden->output != NULL) {
+            SDL_RWclose(this->hidden->output);
+            this->hidden->output = NULL;
+        }
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
 }
 
 static int
-DISKAUD_OpenAudio(_THIS, SDL_AudioSpec * spec)
+DISKAUD_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-    const char *fname = DISKAUD_GetOutputFilename();
+    const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
+    const char *fname = DISKAUD_GetOutputFilename(devname);
+
+    this->hidden = (struct SDL_PrivateAudioData *)
+            SDL_malloc(sizeof (*this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(this->hidden, 0, sizeof (*this->hidden));
 
     /* Open the audio device */
     this->hidden->output = SDL_RWFromFile(fname, "wb");
     if (this->hidden->output == NULL) {
-        return (-1);
+        DISKAUD_CloseDevice(this);
+        return 0;
     }
-#if HAVE_STDIO_H
-    fprintf(stderr, "WARNING: You are using the SDL disk writer"
-            " audio driver!\n Writing to file [%s].\n", fname);
-#endif
 
     /* Allocate mixing buffer */
-    this->hidden->mixlen = spec->size;
     this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
-        return (-1);
+        DISKAUD_CloseDevice(this);
+        return 0;
     }
-    SDL_memset(this->hidden->mixbuf, spec->silence, spec->size);
+    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
+
+    this->hidden->mixlen = this->spec.size;
+    this->hidden->write_delay =
+        (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
+
+#if HAVE_STDIO_H
+    fprintf(stderr,
+            "WARNING: You are using the SDL disk writer audio driver!\n"
+            " Writing to file [%s].\n", fname);
+#endif
 
     /* We're ready to rock and roll. :-) */
-    return (0);
+    return 1;
 }
 
+static int
+DISKAUD_Init(SDL_AudioDriverImpl *impl)
+{
+    /* Set the function pointers */
+    impl->OpenDevice = DISKAUD_OpenDevice;
+    impl->WaitDevice = DISKAUD_WaitDevice;
+    impl->PlayDevice = DISKAUD_PlayDevice;
+    impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
+    impl->CloseDevice = DISKAUD_CloseDevice;
+
+    return 1;
+}
+
+AudioBootStrap DISKAUD_bootstrap = {
+    DISKAUD_DRIVER_NAME, "direct-to-disk audio", DISKAUD_Init, 1
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/disk/SDL_diskaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/disk/SDL_diskaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -27,7 +27,7 @@
 #include "SDL_rwops.h"
 #include "../SDL_sysaudio.h"
 
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *this
 
 struct SDL_PrivateAudioData
--- a/src/audio/dma/SDL_dmaaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/dma/SDL_dmaaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -21,6 +21,8 @@
 */
 #include "SDL_config.h"
 
+/* !!! FIXME: merge this driver with "dsp". */
+
 /* Allow access to a raw mixing buffer */
 
 #include <stdio.h>
@@ -57,89 +59,353 @@
 #define DMA_DRIVER_NAME         "dma"
 
 /* Open the audio device for playback, and don't block if busy */
-#define OPEN_FLAGS	(O_RDWR|O_NONBLOCK)
+#define OPEN_FLAGS_INPUT    (O_RDWR|O_NONBLOCK)
+#define OPEN_FLAGS_OUTPUT   (O_RDWR|O_NONBLOCK)
+
+static char **outputDevices = NULL;
+static int outputDeviceCount = 0;
+static char **inputDevices = NULL;
+static int inputDeviceCount = 0;
+
+static int
+test_for_mmap(int fd)
+{
+    int caps = 0;
+    struct audio_buf_info info;
+    if ((ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) == 0) &&
+        (caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) &&
+        (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) == 0))
+    {
+        size_t len = info.fragstotal * info.fragsize;
+        Uint8 *buf = (Uint8 *) mmap(NULL, len, PROT_WRITE, MAP_SHARED, fd, 0);
+        if (buf != MAP_FAILED) {
+            munmap(buf, len);
+            return 1;
+        }
+    }
+    return 0;
+}
+
 
-/* Audio driver functions */
-static int DMA_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void DMA_WaitAudio(_THIS);
-static void DMA_PlayAudio(_THIS);
-static Uint8 *DMA_GetAudioBuf(_THIS);
-static void DMA_CloseAudio(_THIS);
+static inline void
+free_device_list(char ***devs, int *count)
+{
+    SDL_FreeUnixAudioDevices(devs, count);
+}
+
+static inline void
+build_device_list(int iscapture, char ***devs, int *count)
+{
+    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
+    free_device_list(devs, count);
+    SDL_EnumUnixAudioDevices(flags, 0, test_for_mmap, devs, count);
+}
 
-/* Audio driver bootstrap functions */
+static inline void
+build_device_lists(void)
+{
+    build_device_list(0, &outputDevices, &outputDeviceCount);
+    build_device_list(1, &inputDevices, &inputDeviceCount);
+}
+
+
+static inline void
+free_device_lists(void)
+{
+    free_device_list(&outputDevices, &outputDeviceCount);
+    free_device_list(&inputDevices, &inputDeviceCount);
+}
+
+
+static void DMA_Deinitialize(void)
+{
+    free_device_lists();
+}
 
 static int
-Audio_Available(void)
+DMA_DetectDevices(int iscapture)
+{
+    if (iscapture) {
+        build_device_list(1, &inputDevices, &inputDeviceCount);
+        return inputDeviceCount;
+    } else {
+        build_device_list(0, &outputDevices, &outputDeviceCount);
+        return outputDeviceCount;
+    }
+
+    return 0;  /* shouldn't ever hit this. */
+}
+
+
+static const char *
+DMA_GetDeviceName(int index, int iscapture)
 {
-    int available;
-    int fd;
+    if ((iscapture) && (index < inputDeviceCount)) {
+        return inputDevices[index];
+    } else if ((!iscapture) && (index < outputDeviceCount)) {
+        return outputDevices[index];
+    }
+
+    SDL_SetError("No such device");
+    return NULL;
+}
+
 
-    available = 0;
+static int
+DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo)
+{
+    int frag_spec;
+    int value;
+
+    /* Close and then reopen the audio device */
+    close(audio_fd);
+    audio_fd = open(audiodev, O_RDWR, 0);
+    if (audio_fd < 0) {
+        SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
+        return (-1);
+    }
 
-    fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
-    if (fd >= 0) {
-        int caps;
-        struct audio_buf_info info;
+    /* Calculate the final parameters for this audio specification */
+    SDL_CalculateAudioSpec(&this->spec);
+
+    /* Determine the power of two of the fragment size */
+    for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec);
+    if ((0x01 << frag_spec) != this->spec.size) {
+        SDL_SetError("Fragment size must be a power of two");
+        return (-1);
+    }
+
+    /* Set the audio buffering parameters */
+    if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) {
+        SDL_SetError("Couldn't set audio fragment spec");
+        return (-1);
+    }
 
-        if ((ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) == 0) &&
-            (caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) &&
-            (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) == 0)) {
-            available = 1;
-        }
-        close(fd);
+    /* Set the audio format */
+    value = format;
+    if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
+        SDL_SetError("Couldn't set audio format");
+        return (-1);
+    }
+
+    /* Set mono or stereo audio */
+    value = (this->spec.channels > 1);
+    if ((ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) < 0) ||
+        (value != stereo)) {
+        SDL_SetError("Couldn't set audio channels");
+        return (-1);
     }
-    return (available);
+
+    /* Set the DSP frequency */
+    value = this->spec.freq;
+    if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
+        SDL_SetError("Couldn't set audio frequency");
+        return (-1);
+    }
+    this->spec.freq = value;
+
+    /* We successfully re-opened the audio */
+    return (0);
 }
 
+
 static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
+DMA_CloseDevice(_THIS)
 {
-    SDL_free(device->hidden);
-    SDL_free(device);
+    if (this->hidden != NULL) {
+        if (dma_buf != NULL) {
+            munmap(dma_buf, dma_len);
+            dma_buf = NULL;
+        }
+        if (audio_fd >= 0) {
+            close(audio_fd);
+            audio_fd = -1;
+        }
+        SDL_free(this->hidden);
+        this->hidden = NULL;
+    }
 }
 
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
+
+static int
+DMA_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-    SDL_AudioDevice *this;
+    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
+    int format;
+    int stereo;
+    int value;
+    SDL_AudioFormat test_format;
+    struct audio_buf_info info;
+
+    /* We don't care what the devname is...we'll try to open anything. */
+    /*  ...but default to first name in the list... */
+    if (devname == NULL) {
+        if ( ((iscapture) && (inputDeviceCount == 0)) ||
+             ((!iscapture) && (outputDeviceCount == 0)) ) {
+            SDL_SetError("No such audio device");
+            return 0;
+        }
+        devname = ((iscapture) ? inputDevices[0] : outputDevices[0]);
+    }
 
     /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
+    this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *this->hidden));
+    if (this->hidden == NULL) {
         SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
+        return 0;
     }
     SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-    audio_fd = -1;
+
+    /* Open the audio device */
+    audio_fd = open(devname, flags, 0);
+    if (audio_fd < 0) {
+        DMA_CloseDevice(this);
+        SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
+        return 0;
+    }
+    dma_buf = NULL;
+    ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
+
+    /* Get a list of supported hardware formats */
+    if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
+        DMA_CloseDevice(this);
+        SDL_SetError("Couldn't get audio format list");
+        return 0;
+    }
+
+    /* Try for a closest match on audio format */
+    format = 0;
+    for (test_format = SDL_FirstAudioFormat(this->spec.format);
+         !format && test_format;) {
+#ifdef DEBUG_AUDIO
+        fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
+#endif
+        switch (test_format) {
+        case AUDIO_U8:
+            if (value & AFMT_U8) {
+                format = AFMT_U8;
+            }
+            break;
+        case AUDIO_S8:
+            if (value & AFMT_S8) {
+                format = AFMT_S8;
+            }
+            break;
+        case AUDIO_S16LSB:
+            if (value & AFMT_S16_LE) {
+                format = AFMT_S16_LE;
+            }
+            break;
+        case AUDIO_S16MSB:
+            if (value & AFMT_S16_BE) {
+                format = AFMT_S16_BE;
+            }
+            break;
+        case AUDIO_U16LSB:
+            if (value & AFMT_U16_LE) {
+                format = AFMT_U16_LE;
+            }
+            break;
+        case AUDIO_U16MSB:
+            if (value & AFMT_U16_BE) {
+                format = AFMT_U16_BE;
+            }
+            break;
+        default:
+            format = 0;
+            break;
+        }
+        if (!format) {
+            test_format = SDL_NextAudioFormat();
+        }
+    }
+    if (format == 0) {
+        DMA_CloseDevice(this);
+        SDL_SetError("Couldn't find any hardware audio formats");
+        return 0;
+    }
+    this->spec.format = test_format;
 
-    /* Set the function pointers */
-    this->OpenAudio = DMA_OpenAudio;
-    this->WaitAudio = DMA_WaitAudio;
-    this->PlayAudio = DMA_PlayAudio;
-    this->GetAudioBuf = DMA_GetAudioBuf;
-    this->CloseAudio = DMA_CloseAudio;
+    /* Set the audio format */
+    value = format;
+    if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
+        DMA_CloseDevice(this);
+        SDL_SetError("Couldn't set audio format");
+        return 0;
+    }
+
+    /* Set mono or stereo audio (currently only two channels supported) */
+    stereo = (this->spec.channels > 1);
+    ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo);
+    if (stereo) {
+        this->spec.channels = 2;
+    } else {
+        this->spec.channels = 1;
+    }
+
+    /* Because some drivers don't allow setting the buffer size
+       after setting the format, we must re-open the audio device
+       once we know what format and channels are supported
+     */
+    if (DMA_ReopenAudio(this, devname, format, stereo) < 0) {
+        DMA_CloseDevice(this);
+        /* Error is set by DMA_ReopenAudio() */
+        return 0;
+    }
 
-    this->free = Audio_DeleteDevice;
+    /* Memory map the audio buffer */
+    if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
+        DMA_CloseDevice(this);
+        SDL_SetError("Couldn't get OSPACE parameters");
+        return 0;
+    }
+    this->spec.size = info.fragsize;
+    this->spec.samples = this->spec.size / ((this->spec.format & 0xFF) / 8);
+    this->spec.samples /= this->spec.channels;
+    num_buffers = info.fragstotal;
+    dma_len = num_buffers * this->spec.size;
+    dma_buf = (Uint8 *) mmap(NULL, dma_len, PROT_WRITE, MAP_SHARED,
+                             audio_fd, 0);
+    if (dma_buf == MAP_FAILED) {
+        DMA_CloseDevice(this);
+        SDL_SetError("DMA memory map failed");
+        dma_buf = NULL;
+        return 0;
+    }
+    SDL_memset(dma_buf, this->spec.silence, dma_len);
 
-    return this;
+    /* Check to see if we need to use select() workaround */
+    {
+        char *workaround;
+        workaround = SDL_getenv("SDL_DSP_NOSELECT");
+        if (workaround) {
+            frame_ticks = (float) (this->spec.samples*1000) / this->spec.freq;
+            next_frame = SDL_GetTicks() + frame_ticks;
+        }
+    }
+
+    /* Trigger audio playback */
+    value = 0;
+    ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value);
+    value = PCM_ENABLE_OUTPUT;
+    if (ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value) < 0) {
+        DMA_CloseDevice(this);
+        SDL_SetError("Couldn't trigger audio output");
+        return 0;
+    }
+
+    /* Get the parent process id (we're the parent of the audio thread) */
+    parent = getpid();
+
+    /* We're ready to rock and roll. :-) */
+    return 1;
 }
 
-AudioBootStrap DMA_bootstrap = {
-    DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio",
-    Audio_Available, Audio_CreateDevice
-};
 
 /* This function waits until it is possible to write a full sound buffer */
 static void
-DMA_WaitAudio(_THIS)
+DMA_WaitDevice(_THIS)
 {
     fd_set fdset;
 
@@ -189,8 +455,8 @@
             fprintf(stderr, "SDL: %s\n", message);
 #ifdef AUDIO_OSPACE_HACK
             /* We may be able to use GET_OSPACE trick */
-            frame_ticks = (float) (this->spec->samples * 1000) /
-                this->spec->freq;
+            frame_ticks = (float) (this->spec.samples * 1000) /
+                this->spec.freq;
             next_frame = SDL_GetTicks() + frame_ticks;
 #else
             this->enabled = 0;
@@ -208,7 +474,7 @@
 }
 
 static void
-DMA_PlayAudio(_THIS)
+DMA_PlayDevice(_THIS)
 {
     /* If timer synchronization is enabled, set the next write frame */
     if (frame_ticks) {
@@ -218,7 +484,7 @@
 }
 
 static Uint8 *
-DMA_GetAudioBuf(_THIS)
+DMA_GetDeviceBuf(_THIS)
 {
     count_info info;
     int playing;
@@ -243,225 +509,26 @@
     return (dma_buf + (filling * this->spec.size));
 }
 
-static void
-DMA_CloseAudio(_THIS)
-{
-    if (dma_buf != NULL) {
-        munmap(dma_buf, dma_len);
-        dma_buf = NULL;
-    }
-    if (audio_fd >= 0) {
-        close(audio_fd);
-        audio_fd = -1;
-    }
-}
-
-static int
-DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo,
-                SDL_AudioSpec * spec)
-{
-    int frag_spec;
-    int value;
-
-    /* Close and then reopen the audio device */
-    close(audio_fd);
-    audio_fd = open(audiodev, O_RDWR, 0);
-    if (audio_fd < 0) {
-        SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
-        return (-1);
-    }
-
-    /* Calculate the final parameters for this audio specification */
-    SDL_CalculateAudioSpec(spec);
-
-    /* Determine the power of two of the fragment size */
-    for (frag_spec = 0; (0x01 << frag_spec) < spec->size; ++frag_spec);
-    if ((0x01 << frag_spec) != spec->size) {
-        SDL_SetError("Fragment size must be a power of two");
-        return (-1);
-    }
-
-    /* Set the audio buffering parameters */
-    if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) {
-        SDL_SetError("Couldn't set audio fragment spec");
-        return (-1);
-    }
-
-    /* Set the audio format */
-    value = format;
-    if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
-        SDL_SetError("Couldn't set audio format");
-        return (-1);
-    }
-
-    /* Set mono or stereo audio */
-    value = (spec->channels > 1);
-    if ((ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) < 0) ||
-        (value != stereo)) {
-        SDL_SetError("Couldn't set audio channels");
-        return (-1);
-    }
-
-    /* Set the DSP frequency */
-    value = spec->freq;
-    if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
-        SDL_SetError("Couldn't set audio frequency");
-        return (-1);
-    }
-    spec->freq = value;
-
-    /* We successfully re-opened the audio */
-    return (0);
-}
 
 static int
-DMA_OpenAudio(_THIS, SDL_AudioSpec * spec)
+DMA_Init(SDL_AudioDriverImpl *impl)
 {
-    char audiodev[1024];
-    int format;
-    int stereo;
-    int value;
-    SDL_AudioFormat test_format;
-    struct audio_buf_info info;
-
-    /* Reset the timer synchronization flag */
-    frame_ticks = 0.0;
-
-    /* Open the audio device */
-    audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
-    if (audio_fd < 0) {
-        SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
-        return (-1);
-    }
-    dma_buf = NULL;
-    ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
-
-    /* Get a list of supported hardware formats */
-    if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
-        SDL_SetError("Couldn't get audio format list");
-        return (-1);
-    }
+    /* Set the function pointers */
+    impl->DetectDevices = DMA_DetectDevices;
+    impl->GetDeviceName = DMA_GetDeviceName;
+    impl->OpenDevice = DMA_OpenDevice;
+    impl->WaitDevice = DMA_WaitDevice;
+    impl->PlayDevice = DMA_PlayDevice;
+    impl->GetDeviceBuf = DMA_GetDeviceBuf;
+    impl->CloseDevice = DMA_CloseDevice;
+    impl->Deinitialize = DMA_Deinitialize;
 
-    /* Try for a closest match on audio format */
-    format = 0;
-    for (test_format = SDL_FirstAudioFormat(spec->format);
-         !format && test_format;) {
-#ifdef DEBUG_AUDIO
-        fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
-#endif
-        switch (test_format) {
-        case AUDIO_U8:
-            if (value & AFMT_U8) {
-                format = AFMT_U8;
-            }
-            break;
-        case AUDIO_S8:
-            if (value & AFMT_S8) {
-                format = AFMT_S8;
-            }
-            break;
-        case AUDIO_S16LSB:
-            if (value & AFMT_S16_LE) {
-                format = AFMT_S16_LE;
-            }
-            break;
-        case AUDIO_S16MSB:
-            if (value & AFMT_S16_BE) {
-                format = AFMT_S16_BE;
-            }
-            break;
-        case AUDIO_U16LSB:
-            if (value & AFMT_U16_LE) {
-                format = AFMT_U16_LE;
-            }
-            break;
-        case AUDIO_U16MSB:
-            if (value & AFMT_U16_BE) {
-                format = AFMT_U16_BE;
-            }
-            break;
-        default:
-            format = 0;
-            break;
-        }
-        if (!format) {
-            test_format = SDL_NextAudioFormat();
-        }
-    }
-    if (format == 0) {
-        SDL_SetError("Couldn't find any hardware audio formats");
-        return (-1);
-    }
-    spec->format = test_format;
-
-    /* Set the audio format */
-    value = format;
-    if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
-        SDL_SetError("Couldn't set audio format");
-        return (-1);
-    }
-
-    /* Set mono or stereo audio (currently only two channels supported) */
-    stereo = (spec->channels > 1);
-    ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo);
-    if (stereo) {
-        spec->channels = 2;
-    } else {
-        spec->channels = 1;
-    }
-
-    /* Because some drivers don't allow setting the buffer size
-       after setting the format, we must re-open the audio device
-       once we know what format and channels are supported
-     */
-    if (DMA_ReopenAudio(this, audiodev, format, stereo, spec) < 0) {
-        /* Error is set by DMA_ReopenAudio() */
-        return (-1);
-    }
-
-    /* Memory map the audio buffer */
-    if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
-        SDL_SetError("Couldn't get OSPACE parameters");
-        return (-1);
-    }
-    spec->size = info.fragsize;
-    spec->samples = spec->size / ((spec->format & 0xFF) / 8);
-    spec->samples /= spec->channels;
-    num_buffers = info.fragstotal;
-    dma_len = num_buffers * spec->size;
-    dma_buf = (Uint8 *) mmap(NULL, dma_len, PROT_WRITE, MAP_SHARED,
-                             audio_fd, 0);
-    if (dma_buf == MAP_FAILED) {
-        SDL_SetError("DMA memory map failed");
-        dma_buf = NULL;
-        return (-1);
-    }
-    SDL_memset(dma_buf, spec->silence, dma_len);
-
-    /* Check to see if we need to use select() workaround */
-    {
-        char *workaround;
-        workaround = SDL_getenv("SDL_DSP_NOSELECT");
-        if (workaround) {
-            frame_ticks = (float) (spec->samples * 1000) / spec->freq;
-            next_frame = SDL_GetTicks() + frame_ticks;
-        }
-    }
-
-    /* Trigger audio playback */
-    value = 0;
-    ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value);
-    value = PCM_ENABLE_OUTPUT;
-    if (ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value) < 0) {
-        SDL_SetError("Couldn't trigger audio output");
-        return (-1);
-    }
-
-    /* Get the parent process id (we're the parent of the audio thread) */
-    parent = getpid();
-
-    /* We're ready to rock and roll. :-) */
-    return (0);
+    build_device_lists();
+    return 1;
 }
 
+AudioBootStrap DMA_bootstrap = {
+    DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio", DMA_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/dma/SDL_dmaaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/dma/SDL_dmaaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -21,12 +21,12 @@
 */
 #include "SDL_config.h"
 
-#ifndef _SDL_dspaudio_h
-#define _SDL_dspaudio_h
+#ifndef _SDL_dmaaudio_h
+#define _SDL_dmaaudio_h
 
 #include "../SDL_sysaudio.h"
 
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *this
 
 struct SDL_PrivateAudioData
@@ -49,6 +49,7 @@
 #define FUDGE_TICKS	10      /* The scheduler overhead ticks per frame */
 
 /* Old variable names */
+/* !!! FIXME: remove these. */
 #define audio_fd		(this->hidden->audio_fd)
 #define parent			(this->hidden->parent)
 #define dma_buf			(this->hidden->dma_buf)
@@ -57,5 +58,6 @@
 #define frame_ticks		(this->hidden->frame_ticks)
 #define next_frame		(this->hidden->next_frame)
 
-#endif /* _SDL_dspaudio_h */
+#endif /* _SDL_dmaaudio_h */
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/dmedia/SDL_irixaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/dmedia/SDL_irixaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -45,73 +45,12 @@
 #define alSetWidth(x,y) ALsetwidth(x,y)
 #endif
 
-/* Audio driver functions */
-static int AL_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void AL_WaitAudio(_THIS);
-static void AL_PlayAudio(_THIS);
-static Uint8 *AL_GetAudioBuf(_THIS);
-static void AL_CloseAudio(_THIS);
-
-/* Audio driver bootstrap functions */
-
-static int
-Audio_Available(void)
-{
-    return 1;
-}
-
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
-}
-
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
-{
-    SDL_AudioDevice *this;
-
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    /* Set the function pointers */
-    this->OpenAudio = AL_OpenAudio;
-    this->WaitAudio = AL_WaitAudio;
-    this->PlayAudio = AL_PlayAudio;
-    this->GetAudioBuf = AL_GetAudioBuf;
-    this->CloseAudio = AL_CloseAudio;
-
-    this->free = Audio_DeleteDevice;
-
-    return this;
-}
-
-AudioBootStrap DMEDIA_bootstrap = {
-    "AL", "IRIX DMedia audio",
-    Audio_Available, Audio_CreateDevice
-};
-
-
 void static
-AL_WaitAudio(_THIS)
+IRIXAUDIO_WaitDevice(_THIS)
 {
     Sint32 timeleft;
 
-    timeleft = this->spec.samples - alGetFillable(audio_port);
+    timeleft = this->spec.samples - alGetFillable(this->hidden->audio_port);
     if (timeleft > 0) {
         timeleft /= (this->spec.freq / 1000);
         SDL_Delay((Uint32) timeleft);
@@ -119,61 +58,78 @@
 }
 
 static void
-AL_PlayAudio(_THIS)
+IRIXAUDIO_PlayDevice(_THIS)
 {
     /* Write the audio data out */
-    if (alWriteFrames(audio_port, mixbuf, this->spec.samples) < 0) {
+    ALport port = this->hidden->audio_port;
+    Uint8 *mixbuf = this->hidden->mixbuf;
+    if (alWriteFrames(port, mixbuf, this->spec.samples) < 0) {
         /* Assume fatal error, for now */
         this->enabled = 0;
     }
 }
 
 static Uint8 *
-AL_GetAudioBuf(_THIS)
+IRIXAUDIO_GetDeviceBuf(_THIS)
 {
-    return (mixbuf);
+    return (this->hidden->mixbuf);
 }
 
 static void
-AL_CloseAudio(_THIS)
+IRIXAUDIO_CloseDevice(_THIS)
 {
-    if (mixbuf != NULL) {
-        SDL_FreeAudioMem(mixbuf);
-        mixbuf = NULL;
-    }
-    if (audio_port != NULL) {
-        alClosePort(audio_port);
-        audio_port = NULL;
+    if (this->hidden != NULL) {
+        if (this->hidden->mixbuf != NULL) {
+            SDL_FreeAudioMem(this->hidden->mixbuf);
+            this->hidden->mixbuf = NULL;
+        }
+        if (this->hidden->audio_port != NULL) {
+            alClosePort(this->hidden->audio_port);
+            this->hidden->audio_port = NULL;
+        }
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
 }
 
 static int
-AL_OpenAudio(_THIS, SDL_AudioSpec * spec)
+IRIXAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
+    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
     long width = 0;
     long fmt = 0;
     int valid = 0;
 
+    /* !!! FIXME: Handle multiple devices and capture? */
+
+    /* Initialize all variables that we clean on shutdown */
+    this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+
 #ifdef OLD_IRIX_AUDIO
     {
         long audio_param[2];
         audio_param[0] = AL_OUTPUT_RATE;
-        audio_param[1] = spec->freq;
+        audio_param[1] = this->spec.freq;
         valid = (ALsetparams(AL_DEFAULT_DEVICE, audio_param, 2) < 0);
     }
 #else
     {
         ALpv audio_param;
         audio_param.param = AL_RATE;
-        audio_param.value.i = spec->freq;
+        audio_param.value.i = this->spec.freq;
         valid = (alSetParams(AL_DEFAULT_OUTPUT, &audio_param, 1) < 0);
     }
 #endif
 
     while ((!valid) && (test_format)) {
         valid = 1;
-        spec->format = test_format;
+        this->spec.format = test_format;
 
         switch (test_format) {
         case AUDIO_S8:
@@ -203,30 +159,31 @@
             ALconfig audio_config = alNewConfig();
             valid = 0;
             if (audio_config) {
-                if (alSetChannels(audio_config, spec->channels) < 0) {
-                    if (spec->channels > 2) {   /* can't handle > stereo? */
-                        spec->channels = 2;     /* try again below. */
+                if (alSetChannels(audio_config, this->spec.channels) < 0) {
+                    if (this->spec.channels > 2) { /* can't handle > stereo? */
+                        this->spec.channels = 2;   /* try again below. */
                     }
                 }
 
                 if ((alSetSampFmt(audio_config, fmt) >= 0) &&
                     ((!width) || (alSetWidth(audio_config, width) >= 0)) &&
-                    (alSetQueueSize(audio_config, spec->samples * 2) >= 0) &&
-                    (alSetChannels(audio_config, spec->channels) >= 0)) {
+                    (alSetQueueSize(audio_config,this->spec.samples*2) >= 0) &&
+                    (alSetChannels(audio_config, this->spec.channels) >= 0)) {
 
-                    audio_port = alOpenPort("SDL audio", "w", audio_config);
-                    if (audio_port == NULL) {
+                    this->hidden->audio_port = alOpenPort("SDL audio", "w",
+                                                          audio_config);
+                    if (this->hidden->audio_port == NULL) {
                         /* docs say AL_BAD_CHANNELS happens here, too. */
                         int err = oserror();
                         if (err == AL_BAD_CHANNELS) {
-                            spec->channels = 2;
-                            alSetChannels(audio_config, spec->channels);
-                            audio_port = alOpenPort("SDL audio", "w",
-                                                    audio_config);
+                            this->spec.channels = 2;
+                            alSetChannels(audio_config, this->spec.channels);
+                            this->hidden->audio_port = alOpenPort("SDL audio", "w",
+                                                                 audio_config);
                         }
                     }
 
-                    if (audio_port != NULL) {
+                    if (this->hidden->audio_port != NULL) {
                         valid = 1;
                     }
                 }
@@ -237,23 +194,43 @@
     }
 
     if (!valid) {
+        IRIXAUDIO_CloseDevice(this);
         SDL_SetError("Unsupported audio format");
-        return (-1);
+        return 0;
     }
 
     /* Update the fragment size as size in bytes */
-    SDL_CalculateAudioSpec(spec);
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* Allocate mixing buffer */
-    mixbuf = (Uint8 *) SDL_AllocAudioMem(spec->size);
-    if (mixbuf == NULL) {
+    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->spec.size);
+    if (this->hidden->mixbuf == NULL) {
+        IRIXAUDIO_CloseDevice(this);
         SDL_OutOfMemory();
-        return (-1);
+        return 0;
     }
-    SDL_memset(mixbuf, spec->silence, spec->size);
+    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
 
     /* We're ready to rock and roll. :-) */
-    return (0);
+    return 1;
 }
 
+static int
+IRIXAUDIO_Init(SDL_AudioDriverImpl *impl)
+{
+    /* Set the function pointers */
+    impl->OpenDevice = DSP_OpenDevice;
+    impl->PlayDevice = DSP_PlayDevice;
+    impl->WaitDevice = DSP_WaitDevice;
+    impl->GetDeviceBuf = DSP_GetDeviceBuf;
+    impl->CloseDevice = DSP_CloseDevice;
+    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: not true, I think. */
+
+    return 1;
+}
+
+AudioBootStrap IRIXAUDIO_bootstrap = {
+    "AL", "IRIX DMedia audio", IRIXAUDIO_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/dmedia/SDL_irixaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/dmedia/SDL_irixaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -21,8 +21,8 @@
 */
 #include "SDL_config.h"
 
-#ifndef _SDL_lowaudio_h
-#define _SDL_lowaudio_h
+#ifndef _SDL_irixaudio_h
+#define _SDL_irixaudio_h
 
 #include <dmedia/audio.h>
 
@@ -33,15 +33,10 @@
 
 struct SDL_PrivateAudioData
 {
-    /* The handle for the audio device */
-    ALport audio_port;
-
-    Uint8 *mixbuf;              /* The app mixing buffer */
+    ALport audio_port;    /* The handle for the audio device */
+    Uint8 *mixbuf;        /* The app mixing buffer */
 };
 
-/* Old variable names */
-#define audio_port		(this->hidden->audio_port)
-#define mixbuf			(this->hidden->mixbuf)
+#endif /* _SDL_irixaudio_h */
 
-#endif /* _SDL_lowaudio_h */
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/dsp/SDL_dspaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/dsp/SDL_dspaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -55,156 +55,158 @@
 #define DSP_DRIVER_NAME         "dsp"
 
 /* Open the audio device for playback, and don't block if busy */
-#define OPEN_FLAGS	(O_WRONLY|O_NONBLOCK)
-
-/* Audio driver functions */
-static int DSP_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void DSP_WaitAudio(_THIS);
-static void DSP_PlayAudio(_THIS);
-static Uint8 *DSP_GetAudioBuf(_THIS);
-static void DSP_CloseAudio(_THIS);
-
-/* Audio driver bootstrap functions */
+#define OPEN_FLAGS_OUTPUT    (O_WRONLY|O_NONBLOCK)
+#define OPEN_FLAGS_INPUT    (O_RDONLY|O_NONBLOCK)
 
-static int
-Audio_Available(void)
-{
-    int fd;
-    int available;
+static char **outputDevices = NULL;
+static int outputDeviceCount = 0;
+static char **inputDevices = NULL;
+static int inputDeviceCount = 0;
 
-    available = 0;
-    fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
-    if (fd >= 0) {
-        available = 1;
-        close(fd);
-    }
-    return (available);
+static inline void
+free_device_list(char ***devs, int *count)
+{
+    SDL_FreeUnixAudioDevices(devs, count);
 }
 
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
+static inline void
+build_device_list(int iscapture, char ***devs, int *count)
+{
+    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
+    free_device_list(devs, count);
+    SDL_EnumUnixAudioDevices(flags, 0, NULL, devs, count);
+}
+
+static inline void
+build_device_lists(void)
 {
-    SDL_free(device->hidden);
-    SDL_free(device);
+    build_device_list(0, &outputDevices, &outputDeviceCount);
+    build_device_list(1, &inputDevices, &inputDeviceCount);
+}
+
+
+static inline void
+free_device_lists(void)
+{
+    free_device_list(&outputDevices, &outputDeviceCount);
+    free_device_list(&inputDevices, &inputDeviceCount);
+}
+
+
+static void
+DSP_Deinitialize(void)
+{
+    free_device_lists();
 }
 
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
+
+static int
+DSP_DetectDevices(int iscapture)
 {
-    SDL_AudioDevice *this;
-
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
+    if (iscapture) {
+        build_device_list(1, &inputDevices, &inputDeviceCount);
+        return inputDeviceCount;
+    } else {
+        build_device_list(0, &outputDevices, &outputDeviceCount);
+        return outputDeviceCount;
     }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-    audio_fd = -1;
 
-    /* Set the function pointers */
-    this->OpenAudio = DSP_OpenAudio;
-    this->WaitAudio = DSP_WaitAudio;
-    this->PlayAudio = DSP_PlayAudio;
-    this->GetAudioBuf = DSP_GetAudioBuf;
-    this->CloseAudio = DSP_CloseAudio;
-
-    this->free = Audio_DeleteDevice;
-
-    return this;
+    return 0;  /* shouldn't ever hit this. */
 }
 
-AudioBootStrap DSP_bootstrap = {
-    DSP_DRIVER_NAME, "OSS /dev/dsp standard audio",
-    Audio_Available, Audio_CreateDevice
-};
+static const char *
+DSP_GetDeviceName(int index, int iscapture)
+{
+    if ((iscapture) && (index < inputDeviceCount)) {
+        return inputDevices[index];
+    } else if ((!iscapture) && (index < outputDeviceCount)) {
+        return outputDevices[index];
+    }
 
-/* This function waits until it is possible to write a full sound buffer */
-static void
-DSP_WaitAudio(_THIS)
-{
-    /* Not needed at all since OSS handles waiting automagically */
+    SDL_SetError("No such device");
+    return NULL;
 }
 
+
 static void
-DSP_PlayAudio(_THIS)
-{
-    if (write(audio_fd, mixbuf, mixlen) == -1) {
-        perror("Audio write");
-        this->enabled = 0;
-    }
-#ifdef DEBUG_AUDIO
-    fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen);
-#endif
-}
-
-static Uint8 *
-DSP_GetAudioBuf(_THIS)
+DSP_CloseDevice(_THIS)
 {
-    return (mixbuf);
-}
-
-static void
-DSP_CloseAudio(_THIS)
-{
-    if (mixbuf != NULL) {
-        SDL_FreeAudioMem(mixbuf);
-        mixbuf = NULL;
-    }
-    if (audio_fd >= 0) {
-        close(audio_fd);
-        audio_fd = -1;
+    if (this->hidden != NULL) {
+        if (this->hidden->mixbuf != NULL) {
+            SDL_FreeAudioMem(this->hidden->mixbuf);
+            this->hidden->mixbuf = NULL;
+        }
+        if (this->hidden->audio_fd >= 0) {
+            close(this->hidden->audio_fd);
+            this->hidden->audio_fd = -1;
+        }
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
 }
 
+
 static int
-DSP_OpenAudio(_THIS, SDL_AudioSpec * spec)
+DSP_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-    char audiodev[1024];
+    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
     int format;
     int value;
     int frag_spec;
     SDL_AudioFormat test_format;
 
+    /* We don't care what the devname is...we'll try to open anything. */
+    /*  ...but default to first name in the list... */
+    if (devname == NULL) {
+        if ( ((iscapture) && (inputDeviceCount == 0)) ||
+             ((!iscapture) && (outputDeviceCount == 0)) ) {
+            SDL_SetError("No such audio device");
+            return 0;
+        }
+        devname = ((iscapture) ? inputDevices[0] : outputDevices[0]);
+    }
+
+    /* Initialize all variables that we clean on shutdown */
+    this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+
     /* Open the audio device */
-    audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
-    if (audio_fd < 0) {
-        SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
-        return (-1);
+    this->hidden->audio_fd = open(devname, flags, 0);
+    if (this->hidden->audio_fd < 0) {
+        DSP_CloseDevice(this);
+        SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
+        return 0;
     }
-    mixbuf = NULL;
+    this->hidden->mixbuf = NULL;
 
     /* Make the file descriptor use blocking writes with fcntl() */
     {
-        long flags;
-        flags = fcntl(audio_fd, F_GETFL);
-        flags &= ~O_NONBLOCK;
-        if (fcntl(audio_fd, F_SETFL, flags) < 0) {
+        long ctlflags;
+        ctlflags = fcntl(this->hidden->audio_fd, F_GETFL);
+        ctlflags &= ~O_NONBLOCK;
+        if (fcntl(this->hidden->audio_fd, F_SETFL, ctlflags) < 0) {
+            DSP_CloseDevice(this);
             SDL_SetError("Couldn't set audio blocking mode");
-            DSP_CloseAudio(this);
-            return (-1);
+            return 0;
         }
     }
 
     /* Get a list of supported hardware formats */
-    if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
+    if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
         perror("SNDCTL_DSP_GETFMTS");
+        DSP_CloseDevice(this);
         SDL_SetError("Couldn't get audio format list");
-        DSP_CloseAudio(this);
-        return (-1);
+        return 0;
     }
 
     /* Try for a closest match on audio format */
     format = 0;
-    for (test_format = SDL_FirstAudioFormat(spec->format);
+    for (test_format = SDL_FirstAudioFormat(this->spec.format);
          !format && test_format;) {
 #ifdef DEBUG_AUDIO
         fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
@@ -255,50 +257,51 @@
         }
     }
     if (format == 0) {
+        DSP_CloseDevice(this);
         SDL_SetError("Couldn't find any hardware audio formats");
-        DSP_CloseAudio(this);
-        return (-1);
+        return 0;
     }
-    spec->format = test_format;
+    this->spec.format = test_format;
 
     /* Set the audio format */
     value = format;
-    if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
+    if ( (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) ||
+         (value != format) ) {
         perror("SNDCTL_DSP_SETFMT");
+        DSP_CloseDevice(this);
         SDL_SetError("Couldn't set audio format");
-        DSP_CloseAudio(this);
-        return (-1);
+        return 0;
     }
 
     /* Set the number of channels of output */
-    value = spec->channels;
-    if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0) {
+    value = this->spec.channels;
+    if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0) {
         perror("SNDCTL_DSP_CHANNELS");
+        DSP_CloseDevice(this);
         SDL_SetError("Cannot set the number of channels");
-        DSP_CloseAudio(this);
-        return (-1);
+        return 0;
     }
-    spec->channels = value;
+    this->spec.channels = value;
 
     /* Set the DSP frequency */
-    value = spec->freq;
-    if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
+    value = this->spec.freq;
+    if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
         perror("SNDCTL_DSP_SPEED");
+        DSP_CloseDevice(this);
         SDL_SetError("Couldn't set audio frequency");
-        DSP_CloseAudio(this);
-        return (-1);
+        return 0;
     }
-    spec->freq = value;
+    this->spec.freq = value;
 
     /* Calculate the final parameters for this audio specification */
-    SDL_CalculateAudioSpec(spec);
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* Determine the power of two of the fragment size */
-    for (frag_spec = 0; (0x01U << frag_spec) < spec->size; ++frag_spec);
-    if ((0x01U << frag_spec) != spec->size) {
+    for (frag_spec = 0; (0x01U << frag_spec) < this->spec.size; ++frag_spec);
+    if ((0x01U << frag_spec) != this->spec.size) {
+        DSP_CloseDevice(this);
         SDL_SetError("Fragment size must be a power of two");
-        DSP_CloseAudio(this);
-        return (-1);
+        return 0;
     }
     frag_spec |= 0x00020000;    /* two fragments, for low latency */
 
@@ -307,13 +310,13 @@
     fprintf(stderr, "Requesting %d fragments of size %d\n",
             (frag_spec >> 16), 1 << (frag_spec & 0xFFFF));
 #endif
-    if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) {
+    if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) {
         perror("SNDCTL_DSP_SETFRAGMENT");
     }
 #ifdef DEBUG_AUDIO
     {
         audio_buf_info info;
-        ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info);
+        ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETOSPACE, &info);
         fprintf(stderr, "fragments = %d\n", info.fragments);
         fprintf(stderr, "fragstotal = %d\n", info.fragstotal);
         fprintf(stderr, "fragsize = %d\n", info.fragsize);
@@ -322,19 +325,59 @@
 #endif
 
     /* Allocate mixing buffer */
-    mixlen = spec->size;
-    mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen);
-    if (mixbuf == NULL) {
-        DSP_CloseAudio(this);
-        return (-1);
+    this->hidden->mixlen = this->spec.size;
+    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+    if (this->hidden->mixbuf == NULL) {
+        DSP_CloseDevice(this);
+        SDL_OutOfMemory();
+        return 0;
     }
-    SDL_memset(mixbuf, spec->silence, spec->size);
-
-    /* Get the parent process id (we're the parent of the audio thread) */
-    parent = getpid();
+    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
 
     /* We're ready to rock and roll. :-) */
-    return (0);
+    return 1;
+}
+
+
+static void
+DSP_PlayDevice(_THIS)
+{
+    const Uint8 *mixbuf = this->hidden->mixbuf;
+    const int mixlen = this->hidden->mixlen;
+    if (write(this->hidden->audio_fd, mixbuf, mixlen) == -1) {
+        perror("Audio write");
+        this->enabled = 0;
+    }
+#ifdef DEBUG_AUDIO
+    fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen);
+#endif
 }
 
+static Uint8 *
+DSP_GetDeviceBuf(_THIS)
+{
+    return (this->hidden->mixbuf);
+}
+
+static int
+DSP_Init(SDL_AudioDriverImpl *impl)
+{
+    /* Set the function pointers */
+    impl->DetectDevices = DSP_DetectDevices;
+    impl->GetDeviceName = DSP_GetDeviceName;
+    impl->OpenDevice = DSP_OpenDevice;
+    impl->PlayDevice = DSP_PlayDevice;
+    impl->GetDeviceBuf = DSP_GetDeviceBuf;
+    impl->CloseDevice = DSP_CloseDevice;
+    impl->Deinitialize = DSP_Deinitialize;
+
+    build_device_lists();
+    return 1;
+}
+
+
+AudioBootStrap DSP_bootstrap = {
+    DSP_DRIVER_NAME, "OSS /dev/dsp standard audio", DSP_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/dsp/SDL_dspaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/dsp/SDL_dspaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -26,7 +26,7 @@
 
 #include "../SDL_sysaudio.h"
 
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *this
 
 struct SDL_PrivateAudioData
@@ -34,22 +34,11 @@
     /* The file descriptor for the audio device */
     int audio_fd;
 
-    /* The parent process id, to detect when application quits */
-    pid_t parent;
-
     /* Raw mixing buffer */
     Uint8 *mixbuf;
     int mixlen;
 };
 #define FUDGE_TICKS	10      /* The scheduler overhead ticks per frame */
 
-/* Old variable names */
-#define audio_fd		(this->hidden->audio_fd)
-#define parent			(this->hidden->parent)
-#define mixbuf			(this->hidden->mixbuf)
-#define mixlen			(this->hidden->mixlen)
-#define frame_ticks		(this->hidden->frame_ticks)
-#define next_frame		(this->hidden->next_frame)
-
 #endif /* _SDL_dspaudio_h */
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/dummy/SDL_dummyaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/dummy/SDL_dummyaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -25,141 +25,27 @@
 
 /* Output audio to nowhere... */
 
-#include "SDL_rwops.h"
-#include "SDL_timer.h"
 #include "SDL_audio.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
-#include "../SDL_audiodev_c.h"
 #include "SDL_dummyaudio.h"
 
-/* The tag name used by DUMMY audio */
-#define DUMMYAUD_DRIVER_NAME         "dummy"
-
-/* Audio driver functions */
-static int DUMMYAUD_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void DUMMYAUD_WaitAudio(_THIS);
-static void DUMMYAUD_PlayAudio(_THIS);
-static Uint8 *DUMMYAUD_GetAudioBuf(_THIS);
-static void DUMMYAUD_CloseAudio(_THIS);
-
-/* Audio driver bootstrap functions */
 static int
-DUMMYAUD_Available(void)
+DUMMYAUD_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-    const char *envr = SDL_getenv("SDL_AUDIODRIVER");
-    if (envr && (SDL_strcmp(envr, DUMMYAUD_DRIVER_NAME) == 0)) {
-        return (1);
-    }
-    return (0);
+    return 1;   /* always succeeds. */
 }
 
-static void
-DUMMYAUD_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
-}
-
-static SDL_AudioDevice *
-DUMMYAUD_CreateDevice(int devindex)
+static int
+DUMMYAUD_Init(SDL_AudioDriverImpl *impl)
 {
-    SDL_AudioDevice *this;
-
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
     /* Set the function pointers */
-    this->OpenAudio = DUMMYAUD_OpenAudio;
-    this->WaitAudio = DUMMYAUD_WaitAudio;
-    this->PlayAudio = DUMMYAUD_PlayAudio;
-    this->GetAudioBuf = DUMMYAUD_GetAudioBuf;
-    this->CloseAudio = DUMMYAUD_CloseAudio;
-
-    this->free = DUMMYAUD_DeleteDevice;
-
-    return this;
+    impl->OpenDevice = DUMMYAUD_OpenDevice;
+    impl->OnlyHasDefaultOutputDevice = 1;
+    return 1;
 }
 
 AudioBootStrap DUMMYAUD_bootstrap = {
-    DUMMYAUD_DRIVER_NAME, "SDL dummy audio driver",
-    DUMMYAUD_Available, DUMMYAUD_CreateDevice
+    "dummy", "SDL dummy audio driver", DUMMYAUD_Init, 1
 };
 
-/* This function waits until it is possible to write a full sound buffer */
-static void
-DUMMYAUD_WaitAudio(_THIS)
-{
-    /* Don't block on first calls to simulate initial fragment filling. */
-    if (this->hidden->initial_calls)
-        this->hidden->initial_calls--;
-    else
-        SDL_Delay(this->hidden->write_delay);
-}
-
-static void
-DUMMYAUD_PlayAudio(_THIS)
-{
-    /* no-op...this is a null driver. */
-}
-
-static Uint8 *
-DUMMYAUD_GetAudioBuf(_THIS)
-{
-    return (this->hidden->mixbuf);
-}
-
-static void
-DUMMYAUD_CloseAudio(_THIS)
-{
-    if (this->hidden->mixbuf != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-    }
-}
-
-static int
-DUMMYAUD_OpenAudio(_THIS, SDL_AudioSpec * spec)
-{
-    float bytes_per_sec = 0.0f;
-
-    /* Allocate mixing buffer */
-    this->hidden->mixlen = spec->size;
-    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
-    if (this->hidden->mixbuf == NULL) {
-        return (-1);
-    }
-    SDL_memset(this->hidden->mixbuf, spec->silence, spec->size);
-
-    bytes_per_sec = (float) (((spec->format & 0xFF) / 8) *
-                             spec->channels * spec->freq);
-
-    /*
-     * We try to make this request more audio at the correct rate for
-     *  a given audio spec, so timing stays fairly faithful.
-     * Also, we have it not block at all for the first two calls, so
-     *  it seems like we're filling two audio fragments right out of the
-     *  gate, like other SDL drivers tend to do.
-     */
-    this->hidden->initial_calls = 2;
-    this->hidden->write_delay =
-        (Uint32) ((((float) spec->size) / bytes_per_sec) * 1000.0f);
-
-    /* We're ready to rock and roll. :-) */
-    return (0);
-}
-
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/dummy/SDL_dummyaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/dummy/SDL_dummyaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -26,7 +26,7 @@
 
 #include "../SDL_sysaudio.h"
 
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *this
 
 struct SDL_PrivateAudioData
--- a/src/audio/esd/SDL_esdaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/esd/SDL_esdaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -33,7 +33,6 @@
 #include "SDL_audio.h"
 #include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
-#include "../SDL_audiodev_c.h"
 #include "SDL_esdaudio.h"
 
 #ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC
@@ -46,40 +45,34 @@
 /* The tag name used by ESD audio */
 #define ESD_DRIVER_NAME		"esd"
 
-/* Audio driver functions */
-static int ESD_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void ESD_WaitAudio(_THIS);
-static void ESD_PlayAudio(_THIS);
-static Uint8 *ESD_GetAudioBuf(_THIS);
-static void ESD_CloseAudio(_THIS);
-
 #ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC
 
 static const char *esd_library = SDL_AUDIO_DRIVER_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);
+
+#define SDL_ESD_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
 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)},};
+    SDL_ESD_SYM(esd_open_sound),
+    SDL_ESD_SYM(esd_close),
+    SDL_ESD_SYM(esd_play_stream),
+};
+#undef SDL_ESD_SYM
 
 static void
 UnloadESDLibrary()
 {
-    if (esd_loaded) {
+    if (esd_handle != NULL) {
         SDL_UnloadObject(esd_handle);
         esd_handle = NULL;
-        esd_loaded = 0;
     }
 }
 
@@ -88,17 +81,18 @@
 {
     int i, retval = -1;
 
-    esd_handle = SDL_LoadObject(esd_library);
-    if (esd_handle) {
-        esd_loaded = 1;
-        retval = 0;
-        for (i = 0; i < SDL_arraysize(esd_functions); ++i) {
-            *esd_functions[i].func =
-                SDL_LoadFunction(esd_handle, esd_functions[i].name);
-            if (!*esd_functions[i].func) {
-                retval = -1;
-                UnloadESDLibrary();
-                break;
+    if (esd_handle == NULL) {
+        esd_handle = SDL_LoadObject(esd_library);
+        if (esd_handle) {
+            retval = 0;
+            for (i = 0; i < SDL_arraysize(esd_functions); ++i) {
+                *esd_functions[i].func =
+                    SDL_LoadFunction(esd_handle, esd_functions[i].name);
+                if (!*esd_functions[i].func) {
+                    retval = -1;
+                    UnloadESDLibrary();
+                    break;
+                }
             }
         }
     }
@@ -121,78 +115,10 @@
 
 #endif /* SDL_AUDIO_DRIVER_ESD_DYNAMIC */
 
-/* Audio driver bootstrap functions */
-
-static int
-Audio_Available(void)
-{
-    int connection;
-    int available;
-
-    available = 0;
-    if (LoadESDLibrary() < 0) {
-        return available;
-    }
-    connection = SDL_NAME(esd_open_sound) (NULL);
-    if (connection >= 0) {
-        available = 1;
-        SDL_NAME(esd_close) (connection);
-    }
-    UnloadESDLibrary();
-    return (available);
-}
-
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
-    UnloadESDLibrary();
-}
-
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
-{
-    SDL_AudioDevice *this;
-
-    /* Initialize all variables that we clean on shutdown */
-    LoadESDLibrary();
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-    audio_fd = -1;
-
-    /* Set the function pointers */
-    this->OpenAudio = ESD_OpenAudio;
-    this->WaitAudio = ESD_WaitAudio;
-    this->PlayAudio = ESD_PlayAudio;
-    this->GetAudioBuf = ESD_GetAudioBuf;
-    this->CloseAudio = ESD_CloseAudio;
-
-    this->free = Audio_DeleteDevice;
-
-    return this;
-}
-
-AudioBootStrap ESD_bootstrap = {
-    ESD_DRIVER_NAME, "Enlightened Sound Daemon",
-    Audio_Available, Audio_CreateDevice
-};
 
 /* This function waits until it is possible to write a full sound buffer */
 static void
-ESD_WaitAudio(_THIS)
+ESD_WaitDevice(_THIS)
 {
     Sint32 ticks;
 
@@ -202,28 +128,31 @@
         /* Note that this only works with thread implementations 
            that use a different process id for each thread.
          */
-        if (parent && (((++cnt) % 10) == 0)) {  /* Check every 10 loops */
-            if (kill(parent, 0) < 0) {
+        /* Check every 10 loops */
+        if (this->hidden->parent && (((++cnt) % 10) == 0)) {
+            if (kill(this->hidden->parent, 0) < 0) {
                 this->enabled = 0;
             }
         }
     }
 
     /* Use timer for general audio synchronization */
-    ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS;
+    ticks = ((Sint32) (this->hidden->next_frame-SDL_GetTicks())) - FUDGE_TICKS;
     if (ticks > 0) {
         SDL_Delay(ticks);
     }
 }
 
 static void
-ESD_PlayAudio(_THIS)
+ESD_PlayDevice(_THIS)
 {
-    int written;
+    int written = 0;
 
     /* Write the audio data, checking for EAGAIN on broken audio drivers */
     do {
-        written = write(audio_fd, mixbuf, mixlen);
+        written = write(this->hidden->audio_fd,
+                        this->hidden->mixbuf,
+                        this->hidden->mixlen);
         if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) {
             SDL_Delay(1);       /* Let a little CPU time go by */
         }
@@ -232,7 +161,7 @@
            ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)));
 
     /* Set the next write frame */
-    next_frame += frame_ticks;
+    this->hidden->next_frame += this->hidden->frame_ticks;
 
     /* If we couldn't write, assume fatal error for now */
     if (written < 0) {
@@ -241,21 +170,26 @@
 }
 
 static Uint8 *
-ESD_GetAudioBuf(_THIS)
+ESD_GetDeviceBuf(_THIS)
 {
-    return (mixbuf);
+    return (this->hidden->mixbuf);
 }
 
 static void
-ESD_CloseAudio(_THIS)
+ESD_CloseDevice(_THIS)
 {
-    if (mixbuf != NULL) {
-        SDL_FreeAudioMem(mixbuf);
-        mixbuf = NULL;
-    }
-    if (audio_fd >= 0) {
-        SDL_NAME(esd_close) (audio_fd);
-        audio_fd = -1;
+    if (this->hidden != NULL) {
+        if (this->hidden->mixbuf != NULL) {
+            SDL_FreeAudioMem(this->hidden->mixbuf);
+            this->hidden->mixbuf = NULL;
+        }
+        if (this->hidden->audio_fd >= 0) {
+            SDL_NAME(esd_close) (this->hidden->audio_fd);
+            this->hidden->audio_fd = -1;
+        }
+
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
 }
 
@@ -285,59 +219,135 @@
     return (progname);
 }
 
+
 static int
-ESD_OpenAudio(_THIS, SDL_AudioSpec * spec)
+ESD_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-    esd_format_t format;
+    esd_format_t format = (ESD_STREAM | ESD_PLAY);
+    SDL_AudioFormat test_format = 0;
+    int found = 0;
+
+    /* Initialize all variables that we clean on shutdown */
+    this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    this->hidden->audio_fd = -1;
 
     /* Convert audio spec to the ESD audio format */
-    format = (ESD_STREAM | ESD_PLAY);
-    switch (spec->format & 0xFF) {
-    case 8:
-        format |= ESD_BITS8;
-        break;
-    case 16:
-        format |= ESD_BITS16;
-        break;
-    default:
-        SDL_SetError("Unsupported ESD audio format");
-        return (-1);
+    /* Try for a closest match on audio format */
+    for (test_format = SDL_FirstAudioFormat(this->spec.format);
+         !found && test_format; test_format = SDL_NextAudioFormat()) {
+#ifdef DEBUG_AUDIO
+        fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
+#endif
+        found = 1;
+        switch (test_format) {
+            case AUDIO_U8:
+                format |= ESD_BITS8;
+                break;
+            case AUDIO_S16SYS:
+                format |= ESD_BITS16;
+                break;
+            default:
+                found = 0;
+                break;
+        }
     }
-    if (spec->channels == 1) {
+
+    if (!found) {
+        ESD_CloseDevice(this);
+        SDL_SetError("Couldn't find any hardware audio formats");
+        return 0;
+    }
+
+    if (this->spec.channels == 1) {
         format |= ESD_MONO;
     } else {
         format |= ESD_STEREO;
     }
 #if 0
-    spec->samples = ESD_BUF_SIZE;       /* Darn, no way to change this yet */
+    this->spec.samples = ESD_BUF_SIZE;   /* Darn, no way to change this yet */
 #endif
 
     /* Open a connection to the ESD audio server */
-    audio_fd =
-        SDL_NAME(esd_play_stream) (format, spec->freq, NULL, get_progname());
-    if (audio_fd < 0) {
+    this->hidden->audio_fd =
+        SDL_NAME(esd_play_stream)(format,this->spec.freq,NULL,get_progname());
+
+    if (this->hidden->audio_fd < 0) {
+        ESD_CloseDevice(this);
         SDL_SetError("Couldn't open ESD connection");
-        return (-1);
+        return 0;
     }
 
     /* Calculate the final parameters for this audio specification */
-    SDL_CalculateAudioSpec(spec);
-    frame_ticks = (float) (spec->samples * 1000) / spec->freq;
-    next_frame = SDL_GetTicks() + frame_ticks;
+    SDL_CalculateAudioSpec(&this->spec);
+    this->hidden->frame_ticks = (float) (this->spec.samples*1000) / this->spec.freq;
+    this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks;
 
     /* Allocate mixing buffer */
-    mixlen = spec->size;
-    mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen);
-    if (mixbuf == NULL) {
-        return (-1);
+    this->hidden->mixlen = this->spec.size;
+    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+    if (this->hidden->mixbuf == NULL) {
+        ESD_CloseDevice(this);
+        SDL_OutOfMemory();
+        return 0;
     }
-    SDL_memset(mixbuf, spec->silence, spec->size);
+    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
 
     /* Get the parent process id (we're the parent of the audio thread) */
-    parent = getpid();
+    this->hidden->parent = getpid();
 
     /* We're ready to rock and roll. :-) */
-    return (0);
+    return 1;
+}
+
+static void
+ESD_Deinitialize(void)
+{
+    UnloadESDLibrary();
 }
 
+static int
+ESD_Init(SDL_AudioDriverImpl *impl)
+{
+    if (LoadESDLibrary() < 0) {
+        return 0;
+    } else {
+        int connection = 0;
+
+        /* Don't start ESD if it's not running */
+        if (SDL_getenv("ESD_NO_SPAWN") == NULL) {
+            SDL_putenv("ESD_NO_SPAWN=1");
+        }
+
+        connection = SDL_NAME(esd_open_sound) (NULL);
+        if (connection < 0) {
+            UnloadESDLibrary();
+            SDL_SetError("ESD: esd_open_sound failed (no audio server?)");
+            return 0;
+        }
+        SDL_NAME(esd_close) (connection);
+    }
+
+    /* Set the function pointers */
+    impl->OpenDevice = ESD_OpenDevice;
+    impl->PlayDevice = ESD_PlayDevice;
+    impl->WaitDevice = ESD_WaitDevice;
+    impl->GetDeviceBuf = ESD_GetDeviceBuf;
+    impl->CloseDevice = ESD_CloseDevice;
+    impl->Deinitialize = ESD_Deinitialize;
+    impl->OnlyHasDefaultOutputDevice = 1;
+
+    return 1;
+}
+
+
+AudioBootStrap ESD_bootstrap = {
+    ESD_DRIVER_NAME, "Enlightened Sound Daemon", ESD_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/esd/SDL_esdaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/esd/SDL_esdaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -26,7 +26,7 @@
 
 #include "../SDL_sysaudio.h"
 
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *this
 
 struct SDL_PrivateAudioData
@@ -47,13 +47,5 @@
 };
 #define FUDGE_TICKS	10      /* The scheduler overhead ticks per frame */
 
-/* Old variable names */
-#define audio_fd		(this->hidden->audio_fd)
-#define parent			(this->hidden->parent)
-#define mixbuf			(this->hidden->mixbuf)
-#define mixlen			(this->hidden->mixlen)
-#define frame_ticks		(this->hidden->frame_ticks)
-#define next_frame		(this->hidden->next_frame)
-
 #endif /* _SDL_esdaudio_h */
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/macosx/SDL_coreaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/macosx/SDL_coreaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -21,6 +21,7 @@
 */
 #include "SDL_config.h"
 
+#include <CoreAudio/CoreAudio.h>
 #include <AudioUnit/AudioUnit.h>
 
 #include "SDL_audio.h"
@@ -28,79 +29,233 @@
 #include "../SDL_sysaudio.h"
 #include "SDL_coreaudio.h"
 
-
-/* Audio driver functions */
+#define DEBUG_COREAUDIO 0
 
-static int Core_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void Core_WaitAudio(_THIS);
-static void Core_PlayAudio(_THIS);
-static Uint8 *Core_GetAudioBuf(_THIS);
-static void Core_CloseAudio(_THIS);
+typedef struct COREAUDIO_DeviceList
+{
+    AudioDeviceID id;
+    const char *name;
+} COREAUDIO_DeviceList;
 
-/* Audio driver bootstrap functions */
-
-static int
-Audio_Available(void)
-{
-    return (1);
-}
+static COREAUDIO_DeviceList *inputDevices = NULL;
+static int inputDeviceCount = 0;
+static COREAUDIO_DeviceList *outputDevices = NULL;
+static int outputDeviceCount = 0;
 
 static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
+free_device_list(COREAUDIO_DeviceList **devices, int *devCount)
 {
-    SDL_free(device->hidden);
-    SDL_free(device);
+    if (*devices) {
+        int i = *devCount;
+        while (i--)
+            SDL_free((void *) (*devices)[i].name);
+        SDL_free(*devices);
+        *devices = NULL;
+    }
+    *devCount = 0;
 }
 
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
+
+static void
+build_device_list(int iscapture, COREAUDIO_DeviceList **devices, int *devCount)
 {
-    SDL_AudioDevice *this;
+    Boolean outWritable = 0;
+    OSStatus result = noErr;
+    UInt32 size = 0;
+    AudioDeviceID *devs = NULL;
+    UInt32 i = 0;
+    UInt32 max = 0;
+
+    free_device_list(devices, devCount);
+
+    result = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,
+                                         &size, &outWritable);
+
+    if (result != kAudioHardwareNoError)
+        return;
+
+    devs = (AudioDeviceID *) alloca(size);
+    if (devs == NULL)
+        return;
+
+    max = size / sizeof (AudioDeviceID);
+    *devices = (COREAUDIO_DeviceList *) SDL_malloc(max * sizeof (**devices));
+    if (*devices == NULL)
+        return;
+
+    result = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
+                                     &size, devs);
+    if (result != kAudioHardwareNoError)
+        return;
+
+    for (i = 0; i < max; i++) {
+        CFStringRef cfstr = NULL;
+        char *ptr = NULL;
+        AudioDeviceID dev = devs[i];
+        AudioBufferList *buflist = NULL;
+        int usable = 0;
+        CFIndex len = 0;
+
+        result = AudioDeviceGetPropertyInfo(dev, 0, iscapture,
+                                      kAudioDevicePropertyStreamConfiguration,
+                                      &size, &outWritable);
+        if (result != noErr)
+            continue;
+
+        buflist = (AudioBufferList *) SDL_malloc(size);
+        if (buflist == NULL)
+            continue;
+
+        result = AudioDeviceGetProperty(dev, 0, iscapture,
+                                      kAudioDevicePropertyStreamConfiguration,
+                                      &size, buflist);
 
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
+        if (result == noErr) {
+            UInt32 j;
+            for (j = 0; j < buflist->mNumberBuffers; j++) {
+                if (buflist->mBuffers[j].mNumberChannels > 0) {
+                    usable = 1;
+                    break;
+                }
+            }
+        }
+
+        SDL_free(buflist);
+
+        if (!usable)
+            continue;
+
+        size = sizeof (CFStringRef);
+        result = AudioDeviceGetProperty(dev, 0, iscapture,
+                                        kAudioObjectPropertyName,
+                                        &size, &cfstr);
+
+        if (result != kAudioHardwareNoError)
+            continue;
+
+        len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr),
+                                                kCFStringEncodingUTF8);
+
+        ptr = (char *) SDL_malloc(len + 1);
+        usable = ( (ptr != NULL) &&
+                (CFStringGetCString(cfstr,ptr,len+1,kCFStringEncodingUTF8)) );
+
+        CFRelease(cfstr);
+
+        if (usable) {
+            len = strlen(ptr);
+            /* Some devices have whitespace at the end...trim it. */
+            while ((len > 0) && (ptr[len-1] == ' ')) {
+                len--;
+            }
+            usable = (len > 0);
+        }
+
+        if (!usable) {
+            SDL_free(ptr);
+        } else {
+            ptr[len] = '\0';
+
+            #if DEBUG_COREAUDIO
+            printf("COREAUDIO: Found %s device #%d: '%s' (devid %d)\n",
+                    ((iscapture) ? "capture" : "output"),
+                    (int) *devCount, ptr, (int) dev);
+            #endif
+
+            (*devices)[*devCount].id = dev;
+            (*devices)[*devCount].name = ptr;
+            (*devCount)++;
+        }
     }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    /* Set the function pointers */
-    this->OpenAudio = Core_OpenAudio;
-    this->WaitAudio = Core_WaitAudio;
-    this->PlayAudio = Core_PlayAudio;
-    this->GetAudioBuf = Core_GetAudioBuf;
-    this->CloseAudio = Core_CloseAudio;
-
-    this->free = Audio_DeleteDevice;
-
-    return this;
 }
 
-AudioBootStrap COREAUDIO_bootstrap = {
-    "coreaudio", "Mac OS X CoreAudio",
-    Audio_Available, Audio_CreateDevice
-};
+static inline void
+build_device_lists(void)
+{
+    build_device_list(0, &outputDevices, &outputDeviceCount);
+    build_device_list(1, &inputDevices, &inputDeviceCount);
+}
+
+
+static inline void
+free_device_lists(void)
+{
+    free_device_list(&outputDevices, &outputDeviceCount);
+    free_device_list(&inputDevices, &inputDeviceCount);
+}
+
+
+static int
+find_device_id(const char *devname, int iscapture, AudioDeviceID *id)
+{
+    int i = ((iscapture) ? inputDeviceCount : outputDeviceCount);
+    COREAUDIO_DeviceList *devs = ((iscapture) ? inputDevices : outputDevices);
+    while (i--) {
+        if (SDL_strcmp(devname, devs->name) == 0) {
+            *id = devs->id;
+            return 1;
+        }
+        devs++;
+    }
+
+    return 0;
+}
+
+
+static int
+COREAUDIO_DetectDevices(int iscapture)
+{
+    if (iscapture) {
+        build_device_list(1, &inputDevices, &inputDeviceCount);
+        return inputDeviceCount;
+    } else {
+        build_device_list(0, &outputDevices, &outputDeviceCount);
+        return outputDeviceCount;
+    }
+
+    return 0;  /* shouldn't ever hit this. */
+}
+
+
+static const char *
+COREAUDIO_GetDeviceName(int index, int iscapture)
+{
+    if ((iscapture) && (index < inputDeviceCount)) {
+        return inputDevices[index].name;
+    } else if ((!iscapture) && (index < outputDeviceCount)) {
+        return outputDevices[index].name;
+    }
+
+    SDL_SetError("No such device");
+    return NULL;
+}
+
+
+static void
+COREAUDIO_Deinitialize(void)
+{
+    free_device_lists();
+}
+
 
 /* The CoreAudio callback */
 static OSStatus
-audioCallback(void *inRefCon,
-              AudioUnitRenderActionFlags inActionFlags,
+outputCallback(void *inRefCon,
+              AudioUnitRenderActionFlags *ioActionFlags,
               const AudioTimeStamp * inTimeStamp,
-              UInt32 inBusNumber, AudioBuffer * ioData)
+              UInt32 inBusNumber, UInt32 inNumberFrames,
+              AudioBufferList *ioDataList)
 {
     SDL_AudioDevice *this = (SDL_AudioDevice *) inRefCon;
+    AudioBuffer *ioData = &ioDataList->mBuffers[0];
     UInt32 remaining, len;
     void *ptr;
 
+    /* Is there ever more than one buffer, and what do you do with it? */
+    if (ioDataList->mNumberBuffers != 1) {
+        return noErr;
+    }
+
     /* Only do anything if audio is enabled and not paused */
     if (!this->enabled || this->paused) {
         SDL_memset(ioData->mData, this->spec.silence, ioData->mDataByteSize);
@@ -118,109 +273,251 @@
     remaining = ioData->mDataByteSize;
     ptr = ioData->mData;
     while (remaining > 0) {
-        if (bufferOffset >= bufferSize) {
+        if (this->hidden->bufferOffset >= this->hidden->bufferSize) {
             /* Generate the data */
-            SDL_memset(buffer, this->spec.silence, bufferSize);
+            SDL_memset(this->hidden->buffer, this->spec.silence,
+                       this->hidden->bufferSize);
             SDL_mutexP(this->mixer_lock);
-            (*this->spec.callback) (this->spec.userdata, buffer, bufferSize);
+            (*this->spec.callback) (this->spec.userdata, this->hidden->buffer,
+                                    this->hidden->bufferSize);
             SDL_mutexV(this->mixer_lock);
-            bufferOffset = 0;
+            this->hidden->bufferOffset = 0;
         }
 
-        len = bufferSize - bufferOffset;
+        len = this->hidden->bufferSize - this->hidden->bufferOffset;
         if (len > remaining)
             len = remaining;
-        SDL_memcpy(ptr, (char *) buffer + bufferOffset, len);
+        SDL_memcpy(ptr,
+                    (char *) this->hidden->buffer + this->hidden->bufferOffset,
+                    len);
         ptr = (char *) ptr + len;
         remaining -= len;
-        bufferOffset += len;
+        this->hidden->bufferOffset += len;
     }
 
     return 0;
 }
 
-/* Dummy functions -- we don't use thread-based audio */
-void
-Core_WaitAudio(_THIS)
+static OSStatus
+inputCallback(void *inRefCon,
+              AudioUnitRenderActionFlags *ioActionFlags,
+              const AudioTimeStamp * inTimeStamp,
+              UInt32 inBusNumber, UInt32 inNumberFrames,
+              AudioBufferList *ioData)
 {
-    return;
-}
-
-void
-Core_PlayAudio(_THIS)
-{
-    return;
-}
-
-Uint8 *
-Core_GetAudioBuf(_THIS)
-{
-    return (NULL);
+    //err = AudioUnitRender(afr->fAudioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, afr->fAudioBuffer);
+    // !!! FIXME: write me!
+    return noErr;
 }
 
-void
-Core_CloseAudio(_THIS)
+
+static void
+COREAUDIO_CloseDevice(_THIS)
 {
-    OSStatus result;
-    struct AudioUnitInputCallback callback;
-
-    /* stop processing the audio unit */
-    result = AudioOutputUnitStop(outputAudioUnit);
-    if (result != noErr) {
-        SDL_SetError("Core_CloseAudio: AudioOutputUnitStop");
-        return;
-    }
+    if (this->hidden != NULL) {
+        OSStatus result = noErr;
+        AURenderCallbackStruct callback;
+        const AudioUnitElement output_bus = 0;
+        const AudioUnitElement input_bus = 1;
+        const int iscapture = this->iscapture;
+        const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus);
+        const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output :
+                                                    kAudioUnitScope_Input);
 
-    /* Remove the input callback */
-    callback.inputProc = 0;
-    callback.inputProcRefCon = 0;
-    result = AudioUnitSetProperty(outputAudioUnit,
-                                  kAudioUnitProperty_SetInputCallback,
-                                  kAudioUnitScope_Input,
-                                  0, &callback, sizeof(callback));
-    if (result != noErr) {
-        SDL_SetError
-            ("Core_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)");
-        return;
+        /* stop processing the audio unit */
+        result = AudioOutputUnitStop(this->hidden->audioUnit);
+
+        /* Remove the input callback */
+        SDL_memset(&callback, '\0', sizeof (AURenderCallbackStruct));
+        result = AudioUnitSetProperty(this->hidden->audioUnit,
+                                      kAudioUnitProperty_SetRenderCallback,
+                                      scope, bus, &callback, sizeof (callback));
+
+        CloseComponent(this->hidden->audioUnit);
+
+        SDL_free(this->hidden->buffer);
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
+}
 
-    result = CloseComponent(outputAudioUnit);
-    if (result != noErr) {
-        SDL_SetError("Core_CloseAudio: CloseComponent");
-        return;
-    }
-
-    SDL_free(buffer);
-}
 
 #define CHECK_RESULT(msg) \
     if (result != noErr) { \
+        COREAUDIO_CloseDevice(this); \
         SDL_SetError("CoreAudio error (%s): %d", msg, (int) result); \
-        return -1; \
+        return 0; \
+    }
+
+static int
+find_device_by_name(_THIS, const char *devname, int iscapture)
+{
+    AudioDeviceID devid = 0;
+    OSStatus result = noErr;
+    UInt32 size = 0;
+    UInt32 alive = 0;
+    pid_t pid = 0;
+
+    if (devname == NULL) {
+        size = sizeof (AudioDeviceID);
+        const AudioHardwarePropertyID propid =
+                    ((iscapture) ? kAudioHardwarePropertyDefaultInputDevice :
+                                   kAudioHardwarePropertyDefaultOutputDevice);
+
+        result = AudioHardwareGetProperty(propid, &size, &devid);
+        CHECK_RESULT("AudioHardwareGetProperty (default device)");
+    } else {
+        if (!find_device_id(devname, iscapture, &devid)) {
+            SDL_SetError("CoreAudio: No such audio device.");
+            return 0;
+        }
     }
 
+    size = sizeof (alive);
+    result = AudioDeviceGetProperty(devid, 0, iscapture,
+                                    kAudioDevicePropertyDeviceIsAlive,
+                                    &size, &alive);
+    CHECK_RESULT("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)");
 
-int
-Core_OpenAudio(_THIS, SDL_AudioSpec * spec)
+    if (!alive) {
+        SDL_SetError("CoreAudio: requested device exists, but isn't alive.");
+        return 0;
+    }
+
+    size = sizeof (pid);
+    result = AudioDeviceGetProperty(devid, 0, iscapture,
+                                    kAudioDevicePropertyHogMode, &size, &pid);
+
+    /* some devices don't support this property, so errors are fine here. */
+    if ((result == noErr) && (pid != -1)) {
+        SDL_SetError("CoreAudio: requested device is being hogged.");
+        return 0;
+    }
+
+    this->hidden->deviceID = devid;
+    return 1;
+}
+
+
+static int
+prepare_audiounit(_THIS, const char *devname, int iscapture,
+                  const AudioStreamBasicDescription *strdesc)
 {
     OSStatus result = noErr;
-    Component comp;
+    AURenderCallbackStruct callback;
     ComponentDescription desc;
-    struct AudioUnitInputCallback callback;
+    Component comp = NULL;
+    int use_system_device = 0;
+    UInt32 enableIO = 0;
+    const AudioUnitElement output_bus = 0;
+    const AudioUnitElement input_bus = 1;
+    const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus);
+    const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output :
+                                                kAudioUnitScope_Input);
+
+    if (!find_device_by_name(this, devname, iscapture)) {
+        SDL_SetError("Couldn't find requested CoreAudio device");
+        return 0;
+    }
+
+    SDL_memset(&desc, '\0', sizeof(ComponentDescription));
+    desc.componentType = kAudioUnitType_Output;
+    desc.componentSubType = kAudioUnitSubType_HALOutput;
+    desc.componentManufacturer = kAudioUnitManufacturer_Apple;
+
+    comp = FindNextComponent(NULL, &desc);
+    if (comp == NULL) {
+        SDL_SetError("Couldn't find requested CoreAudio component");
+        return 0;
+    }
+
+    /* Open & initialize the audio unit */
+    result = OpenAComponent(comp, &this->hidden->audioUnit);
+    CHECK_RESULT("OpenAComponent");
+
+    // !!! FIXME: this is wrong?
+    enableIO = ((iscapture) ? 1 : 0);
+    result = AudioUnitSetProperty(this->hidden->audioUnit,
+                                  kAudioOutputUnitProperty_EnableIO,
+                                  kAudioUnitScope_Input, input_bus,
+                                  &enableIO, sizeof (enableIO));
+    CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_EnableIO input)");
+
+    // !!! FIXME: this is wrong?
+    enableIO = ((iscapture) ? 0 : 1);
+    result = AudioUnitSetProperty(this->hidden->audioUnit,
+                                  kAudioOutputUnitProperty_EnableIO,
+                                  kAudioUnitScope_Output, output_bus,
+                                  &enableIO, sizeof (enableIO));
+    CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_EnableIO output)");
+
+    result = AudioUnitSetProperty(this->hidden->audioUnit,
+                                  kAudioOutputUnitProperty_CurrentDevice,
+                                  kAudioUnitScope_Global, 0,
+                                  &this->hidden->deviceID,
+                                  sizeof (AudioDeviceID));
+    CHECK_RESULT("AudioUnitSetProperty (kAudioOutputUnitProperty_CurrentDevice)");
+
+    /* Set the data format of the audio unit. */
+    result = AudioUnitSetProperty(this->hidden->audioUnit,
+                                  kAudioUnitProperty_StreamFormat,
+                                  scope, bus, strdesc, sizeof (*strdesc));
+    CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)");
+
+    /* Set the audio callback */
+    SDL_memset(&callback, '\0', sizeof (AURenderCallbackStruct));
+    callback.inputProc = ((iscapture) ? inputCallback : outputCallback);
+    callback.inputProcRefCon = this;
+    result = AudioUnitSetProperty(this->hidden->audioUnit,
+                                  kAudioUnitProperty_SetRenderCallback,
+                                  scope, bus, &callback, sizeof (callback));
+    CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)");
+
+    /* Calculate the final parameters for this audio specification */
+    SDL_CalculateAudioSpec(&this->spec);
+
+    /* Allocate a sample buffer */
+    this->hidden->bufferOffset = this->hidden->bufferSize = this->spec.size;
+    this->hidden->buffer = SDL_malloc(this->hidden->bufferSize);
+
+    result = AudioUnitInitialize(this->hidden->audioUnit);
+    CHECK_RESULT("AudioUnitInitialize");
+
+    /* Finally, start processing of the audio unit */
+    result = AudioOutputUnitStart(this->hidden->audioUnit);
+    CHECK_RESULT("AudioOutputUnitStart");
+
+    /* We're running! */
+    return 1;
+}
+
+
+static int
+COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
+{
     AudioStreamBasicDescription strdesc;
-    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
+    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
     int valid_datatype = 0;
 
+    /* Initialize all variables that we clean on shutdown */
+    this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return (0);
+    }
+    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+
     /* Setup a AudioStreamBasicDescription with the requested format */
-    memset(&strdesc, '\0', sizeof(AudioStreamBasicDescription));
+    SDL_memset(&strdesc, '\0', sizeof(AudioStreamBasicDescription));
     strdesc.mFormatID = kAudioFormatLinearPCM;
     strdesc.mFormatFlags = kLinearPCMFormatFlagIsPacked;
-    strdesc.mChannelsPerFrame = spec->channels;
-    strdesc.mSampleRate = spec->freq;
+    strdesc.mChannelsPerFrame = this->spec.channels;
+    strdesc.mSampleRate = this->spec.freq;
     strdesc.mFramesPerPacket = 1;
 
     while ((!valid_datatype) && (test_format)) {
-        spec->format = test_format;
+        this->spec.format = test_format;
         /* Just a list of valid SDL formats, so people don't pass junk here. */
         switch (test_format) {
         case AUDIO_U8:
@@ -234,13 +531,13 @@
         case AUDIO_F32LSB:
         case AUDIO_F32MSB:
             valid_datatype = 1;
-            strdesc.mBitsPerChannel = SDL_AUDIO_BITSIZE(spec->format);
-            if (SDL_AUDIO_ISBIGENDIAN(spec->format))
+            strdesc.mBitsPerChannel = SDL_AUDIO_BITSIZE(this->spec.format);
+            if (SDL_AUDIO_ISBIGENDIAN(this->spec.format))
                 strdesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
 
-            if (SDL_AUDIO_ISFLOAT(spec->format))
+            if (SDL_AUDIO_ISFLOAT(this->spec.format))
                 strdesc.mFormatFlags |= kLinearPCMFormatFlagIsFloat;
-            else if (SDL_AUDIO_ISSIGNED(spec->format))
+            else if (SDL_AUDIO_ISSIGNED(this->spec.format))
                 strdesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
             break;
         }
@@ -248,7 +545,7 @@
 
     if (!valid_datatype) {      /* shouldn't happen, but just in case... */
         SDL_SetError("Unsupported audio format");
-        return (-1);
+        return 0;
     }
 
     strdesc.mBytesPerFrame =
@@ -256,52 +553,31 @@
     strdesc.mBytesPerPacket =
         strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
 
-    /* Locate the default output audio unit */
-    memset(&desc, '\0', sizeof(ComponentDescription));
-    desc.componentType = kAudioUnitComponentType;
-    desc.componentSubType = kAudioUnitSubType_Output;
-    desc.componentManufacturer = kAudioUnitID_DefaultOutput;
-    desc.componentFlags = 0;
-    desc.componentFlagsMask = 0;
-
-    comp = FindNextComponent(NULL, &desc);
-    if (comp == NULL) {
-        SDL_SetError
-            ("Failed to start CoreAudio: FindNextComponent returned NULL");
-        return -1;
+    if (!prepare_audiounit(this, devname, iscapture, &strdesc)) {
+        return 0;  /* prepare_audiounit() will call SDL_SetError()... */
     }
 
-    /* Open & initialize the default output audio unit */
-    result = OpenAComponent(comp, &outputAudioUnit);
-    CHECK_RESULT("OpenAComponent")
-        result = AudioUnitInitialize(outputAudioUnit);
-    CHECK_RESULT("AudioUnitInitialize")
-        /* Set the input format of the audio unit. */
-        result = AudioUnitSetProperty(outputAudioUnit,
-                                      kAudioUnitProperty_StreamFormat,
-                                      kAudioUnitScope_Input,
-                                      0, &strdesc, sizeof(strdesc));
-    CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)")
-        /* Set the audio callback */
-        callback.inputProc = audioCallback;
-    callback.inputProcRefCon = this;
-    result = AudioUnitSetProperty(outputAudioUnit,
-                                  kAudioUnitProperty_SetInputCallback,
-                                  kAudioUnitScope_Input,
-                                  0, &callback, sizeof(callback));
-    CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)")
-        /* Calculate the final parameters for this audio specification */
-        SDL_CalculateAudioSpec(spec);
-
-    /* Allocate a sample buffer */
-    bufferOffset = bufferSize = this->spec.size;
-    buffer = SDL_malloc(bufferSize);
-
-    /* Finally, start processing of the audio unit */
-    result = AudioOutputUnitStart(outputAudioUnit);
-    CHECK_RESULT("AudioOutputUnitStart")
-        /* We're running! */
-        return (1);
+    return 1;  /* good to go. */
 }
 
+static int
+COREAUDIO_Init(SDL_AudioDriverImpl *impl)
+{
+    /* Set the function pointers */
+    impl->DetectDevices = COREAUDIO_DetectDevices;
+    impl->GetDeviceName = COREAUDIO_GetDeviceName;
+    impl->OpenDevice = COREAUDIO_OpenDevice;
+    impl->CloseDevice = COREAUDIO_CloseDevice;
+    impl->Deinitialize = COREAUDIO_Deinitialize;
+    impl->ProvidesOwnCallbackThread = 1;
+
+    build_device_lists();  /* do an initial check for devices... */
+
+    return 1;
+}
+
+AudioBootStrap COREAUDIO_bootstrap = {
+    "coreaudio", "Mac OS X CoreAudio", COREAUDIO_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/macosx/SDL_coreaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/macosx/SDL_coreaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -26,22 +26,17 @@
 
 #include "../SDL_sysaudio.h"
 
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *this
 
 struct SDL_PrivateAudioData
 {
-    AudioUnit outputAudioUnit;
+    AudioUnit audioUnit;
     void *buffer;
     UInt32 bufferOffset;
     UInt32 bufferSize;
+    AudioDeviceID deviceID;
 };
 
-/* Old variable names */
-#define outputAudioUnit		(this->hidden->outputAudioUnit)
-#define buffer		(this->hidden->buffer)
-#define bufferOffset		(this->hidden->bufferOffset)
-#define bufferSize		(this->hidden->bufferSize)
-
 #endif /* _SDL_coreaudio_h */
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/macrom/SDL_romaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/macrom/SDL_romaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -21,11 +21,16 @@
 */
 #include "SDL_config.h"
 
+/* This should work on PowerPC and Intel Mac OS X, and Carbonized Mac OS 9. */
+
 #if defined(__APPLE__) && defined(__MACH__)
+#  define SDL_MACOS_NAME "Mac OS X"
 #  include <Carbon/Carbon.h>
 #elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335)
+#  define SDL_MACOS_NAME "Mac OS 9"
 #  include <Carbon.h>
 #else
+#  define SDL_MACOS_NAME "Mac OS 9"
 #  include <Sound.h>            /* SoundManager interface */
 #  include <Gestalt.h>
 #  include <DriverServices.h>
@@ -45,72 +50,6 @@
 #include "../SDL_sysaudio.h"
 #include "SDL_romaudio.h"
 
-/* Audio driver functions */
-
-static void Mac_CloseAudio(_THIS);
-static int Mac_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void Mac_LockAudio(_THIS);
-static void Mac_UnlockAudio(_THIS);
-
-/* Audio driver bootstrap functions */
-
-
-static int
-Audio_Available(void)
-{
-    return (1);
-}
-
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
-}
-
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
-{
-    SDL_AudioDevice *this;
-
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    /* Set the function pointers */
-    this->OpenAudio = Mac_OpenAudio;
-    this->CloseAudio = Mac_CloseAudio;
-    this->LockAudio = Mac_LockAudio;
-    this->UnlockAudio = Mac_UnlockAudio;
-    this->free = Audio_DeleteDevice;
-
-#ifdef __MACOSX__               /* Mac OS X uses threaded audio, so normal thread code is okay */
-    this->LockAudio = NULL;
-    this->UnlockAudio = NULL;
-#endif
-    return this;
-}
-
-AudioBootStrap SNDMGR_bootstrap = {
-    "sndmgr", "MacOS SoundManager 3.0",
-    Audio_Available, Audio_CreateDevice
-};
-
-#if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE)
-/* This works correctly on Mac OS X */
-
 #pragma options align=power
 
 static volatile SInt32 audio_is_locked = 0;
@@ -121,6 +60,7 @@
 static CmpSoundHeader header;
 static volatile Uint32 fill_me = 0;
 
+
 static void
 mix_buffer(SDL_AudioDevice * audio, UInt8 * buffer)
 {
@@ -150,13 +90,13 @@
 }
 
 static void
-Mac_LockAudio(_THIS)
+SNDMGR_LockDevice(_THIS)
 {
     IncrementAtomic((SInt32 *) & audio_is_locked);
 }
 
 static void
-Mac_UnlockAudio(_THIS)
+SNDMGR_UnlockDevice(_THIS)
 {
     SInt32 oldval;
 
@@ -198,7 +138,7 @@
     cmd.param2 = (long) &header;
     SndDoCommand(chan, &cmd, 0);
 
-    memset(buffer[fill_me], 0, audio->spec.size);
+    SDL_memset(buffer[fill_me], 0, audio->spec.size);
 
     /*
      * if audio device isn't locked, mix the next buffer to be queued in
@@ -219,14 +159,25 @@
 }
 
 static int
-Mac_OpenAudio(_THIS, SDL_AudioSpec * spec)
+SNDMGR_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-
+    SDL_AudioSpec *spec = &this->spec;
+    SndChannelPtr channel = NULL;
     SndCallBackUPP callback;
     int sample_bits;
     int i;
     long initOptions;
 
+    /* Initialize all variables that we clean on shutdown */
+    this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+
+    /* !!! FIXME: iterate through format matrix... */
     /* Very few conversions are required, but... */
     switch (spec->format) {
     case AUDIO_S8:
@@ -242,10 +193,10 @@
         spec->format = AUDIO_F32MSB;
         break;
     }
-    SDL_CalculateAudioSpec(spec);
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* initialize bufferCmd header */
-    memset(&header, 0, sizeof(header));
+    SDL_memset(&header, 0, sizeof(header));
     callback = (SndCallBackUPP) NewSndCallBackUPP(callBackProc);
     sample_bits = spec->size / spec->samples / spec->channels * 8;
 
@@ -278,20 +229,23 @@
 
     /* allocate 2 buffers */
     for (i = 0; i < 2; i++) {
-        buffer[i] = (UInt8 *) malloc(sizeof(UInt8) * spec->size);
+        buffer[i] = (UInt8 *) SDL_malloc(sizeof(UInt8) * spec->size);
         if (buffer[i] == NULL) {
+            SNDMGR_CloseDevice(this);
             SDL_OutOfMemory();
-            return (-1);
+            return 0;
         }
-        memset(buffer[i], 0, spec->size);
+        SDL_memset(buffer[i], 0, spec->size);
     }
 
     /* Create the sound manager channel */
     channel = (SndChannelPtr) SDL_malloc(sizeof(*channel));
     if (channel == NULL) {
+        SNDMGR_CloseDevice(this);
         SDL_OutOfMemory();
-        return (-1);
+        return 0;
     }
+    this->hidden->channel = channel;
     if (spec->channels >= 2) {
         initOptions = initStereo;
     } else {
@@ -300,10 +254,9 @@
     channel->userInfo = (long) this;
     channel->qLength = 128;
     if (SndNewChannel(&channel, sampledSynth, initOptions, callback) != noErr) {
+        SNDMGR_CloseDevice(this);
         SDL_SetError("Unable to create audio channel");
-        SDL_free(channel);
-        channel = NULL;
-        return (-1);
+        return 0;
     }
 
     /* start playback */
@@ -319,16 +272,15 @@
 }
 
 static void
-Mac_CloseAudio(_THIS)
+SNDMGR_CloseDevice(_THIS)
 {
-
     int i;
 
     running = 0;
 
-    if (channel) {
-        SndDisposeChannel(channel, true);
-        channel = NULL;
+    if (this->hidden->channel) {
+        SndDisposeChannel(this->hidden->channel, true);
+        this->hidden->channel = NULL;
     }
 
     for (i = 0; i < 2; ++i) {
@@ -337,193 +289,31 @@
             buffer[i] = NULL;
         }
     }
-}
-
-#else /* !TARGET_API_MAC_CARBON && !USE_RYANS_SOUNDCODE */
-
-static void
-Mac_LockAudio(_THIS)
-{
-    /* no-op. */
-}
-
-static void
-Mac_UnlockAudio(_THIS)
-{
-    /* no-op. */
-}
-
-
-/* This function is called by Sound Manager when it has exhausted one of
-   the buffers, so we'll zero it to silence and fill it with audio if
-   we're not paused.
-*/
-static pascal void
-sndDoubleBackProc(SndChannelPtr chan, SndDoubleBufferPtr newbuf)
-{
-    SDL_AudioDevice *audio = (SDL_AudioDevice *) newbuf->dbUserInfo[0];
-
-    /* If audio is quitting, don't do anything */
-    if (!audio->enabled) {
-        return;
-    }
-    memset(newbuf->dbSoundData, 0, audio->spec.size);
-    newbuf->dbNumFrames = audio->spec.samples;
-    if (!audio->paused) {
-        if (audio->convert.needed) {
-            audio->spec.callback(audio->spec.userdata,
-                                 (Uint8 *) audio->convert.buf,
-                                 audio->convert.len);
-            SDL_ConvertAudio(&audio->convert);
-#if 0
-            if (audio->convert.len_cvt != audio->spec.size) {
-                /* Uh oh... probably crashes here */ ;
-            }
-#endif
-            SDL_memcpy(newbuf->dbSoundData, audio->convert.buf,
-                       audio->convert.len_cvt);
-        } else {
-            audio->spec.callback(audio->spec.userdata,
-                                 (Uint8 *) newbuf->dbSoundData,
-                                 audio->spec.size);
-        }
-    }
-    newbuf->dbFlags |= dbBufferReady;
+    SDL_free(this->hidden);
+    this->hidden = NULL;
 }
 
 static int
-DoubleBufferAudio_Available(void)
-{
-    int available;
-    NumVersion sndversion;
-    long response;
-
-    available = 0;
-    sndversion = SndSoundManagerVersion();
-    if (sndversion.majorRev >= 3) {
-        if (Gestalt(gestaltSoundAttr, &response) == noErr) {
-            if ((response & (1 << gestaltSndPlayDoubleBuffer))) {
-                available = 1;
-            }
-        }
-    } else {
-        if (Gestalt(gestaltSoundAttr, &response) == noErr) {
-            if ((response & (1 << gestaltHasASC))) {
-                available = 1;
-            }
-        }
-    }
-    return (available);
-}
-
-static void
-Mac_CloseAudio(_THIS)
+SNDMGR_Init(SDL_AudioDriverImpl *impl)
 {
-    int i;
-
-    if (channel != NULL) {
-        /* Clean up the audio channel */
-        SndDisposeChannel(channel, true);
-        channel = NULL;
-    }
-    for (i = 0; i < 2; ++i) {
-        if (audio_buf[i]) {
-            SDL_free(audio_buf[i]);
-            audio_buf[i] = NULL;
-        }
-    }
-}
-
-static int
-Mac_OpenAudio(_THIS, SDL_AudioSpec * spec)
-{
-    SndDoubleBufferHeader2 audio_dbh;
-    int i;
-    long initOptions;
-    int sample_bits;
-    SndDoubleBackUPP doubleBackProc;
-
-    /* Check to make sure double-buffered audio is available */
-    if (!DoubleBufferAudio_Available()) {
-        SDL_SetError("Sound manager doesn't support double-buffering");
-        return (-1);
-    }
+    /* Set the function pointers */
+    impl->OpenDevice = SNDMGR_OpenDevice;
+    impl->CloseDevice = SNDMGR_CloseDevice;
+    impl->ProvidesOwnCallbackThread = 1;
+    impl->OnlyHasDefaultOutputDevice = 1;
 
-    /* Very few conversions are required, but... */
-    switch (spec->format) {
-    case AUDIO_S8:
-        spec->format = AUDIO_U8;
-        break;
-    case AUDIO_U16LSB:
-        spec->format = AUDIO_S16LSB;
-        break;
-    case AUDIO_U16MSB:
-        spec->format = AUDIO_S16MSB;
-        break;
-    }
-    SDL_CalculateAudioSpec(spec);
-
-    /* initialize the double-back header */
-    SDL_memset(&audio_dbh, 0, sizeof(audio_dbh));
-    doubleBackProc = NewSndDoubleBackProc(sndDoubleBackProc);
-    sample_bits = spec->size / spec->samples / spec->channels * 8;
-
-    audio_dbh.dbhNumChannels = spec->channels;
-    audio_dbh.dbhSampleSize = sample_bits;
-    audio_dbh.dbhCompressionID = 0;
-    audio_dbh.dbhPacketSize = 0;
-    audio_dbh.dbhSampleRate = spec->freq << 16;
-    audio_dbh.dbhDoubleBack = doubleBackProc;
-    audio_dbh.dbhFormat = 0;
-
-    /* Note that we install the 16bitLittleEndian Converter if needed. */
-    if (spec->format == 0x8010) {
-        audio_dbh.dbhCompressionID = fixedCompression;
-        audio_dbh.dbhFormat = k16BitLittleEndianFormat;
-    }
-
-    /* allocate the 2 double-back buffers */
-    for (i = 0; i < 2; ++i) {
-        audio_buf[i] = SDL_calloc(1, sizeof(SndDoubleBuffer) + spec->size);
-        if (audio_buf[i] == NULL) {
-            SDL_OutOfMemory();
-            return (-1);
-        }
-        audio_buf[i]->dbNumFrames = spec->samples;
-        audio_buf[i]->dbFlags = dbBufferReady;
-        audio_buf[i]->dbUserInfo[0] = (long) this;
-        audio_dbh.dbhBufferPtr[i] = audio_buf[i];
-    }
-
-    /* Create the sound manager channel */
-    channel = (SndChannelPtr) SDL_malloc(sizeof(*channel));
-    if (channel == NULL) {
-        SDL_OutOfMemory();
-        return (-1);
-    }
-    if (spec->channels >= 2) {
-        initOptions = initStereo;
-    } else {
-        initOptions = initMono;
-    }
-    channel->userInfo = 0;
-    channel->qLength = 128;
-    if (SndNewChannel(&channel, sampledSynth, initOptions, 0L) != noErr) {
-        SDL_SetError("Unable to create audio channel");
-        SDL_free(channel);
-        channel = NULL;
-        return (-1);
-    }
-
-    /* Start playback */
-    if (SndPlayDoubleBuffer(channel, (SndDoubleBufferHeaderPtr) & audio_dbh)
-        != noErr) {
-        SDL_SetError("Unable to play double buffered audio");
-        return (-1);
-    }
+/* Mac OS X uses threaded audio, so normal thread code is okay */
+#ifndef __MACOSX__
+    impl->LockDevice = SNDMGR_LockDevice;
+    impl->UnlockDevice = SNDMGR_UnlockDevice;
+    impl->SkipMixerLock = 1;
+#endif
 
     return 1;
 }
 
-#endif /* TARGET_API_MAC_CARBON || USE_RYANS_SOUNDCODE */
+AudioBootStrap SNDMGR_bootstrap = {
+    "sndmgr", SDL_MACOS_NAME " SoundManager", SNDMGR_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/macrom/SDL_romaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/macrom/SDL_romaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -26,27 +26,14 @@
 
 #include "../SDL_sysaudio.h"
 
-/* This is Ryan's improved MacOS sound code, with locking support */
-#define USE_RYANS_SOUNDCODE
-
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *this
 
 struct SDL_PrivateAudioData
 {
     /* Sound manager audio channel */
     SndChannelPtr channel;
-#if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE)
-    /* FIXME: Add Ryan's static data here */
-#else
-    /* Double buffering variables */
-    SndDoubleBufferPtr audio_buf[2];
-#endif
 };
 
-/* Old variable names */
-#define channel		(this->hidden->channel)
-#define audio_buf	(this->hidden->audio_buf)
-
 #endif /* _SDL_romaudio_h */
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/mint/SDL_mintaudio_dma8.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/mint/SDL_mintaudio_dma8.c	Tue Oct 17 09:15:21 2006 +0000
@@ -61,105 +61,8 @@
 
 static unsigned long cookie_snd, cookie_mch;
 
-/*--- Audio driver functions ---*/
-
-static void Mint_CloseAudio(_THIS);
-static int Mint_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void Mint_LockAudio(_THIS);
-static void Mint_UnlockAudio(_THIS);
-
-/* To check/init hardware audio */
-static int Mint_CheckAudio(_THIS, SDL_AudioSpec * spec);
-static void Mint_InitAudio(_THIS, SDL_AudioSpec * spec);
-
-/*--- Audio driver bootstrap functions ---*/
-
-static int
-Audio_Available(void)
-{
-    const char *envr = SDL_getenv("SDL_AUDIODRIVER");
-
-    /* Check if user asked a different audio driver */
-    if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME) != 0)) {
-        DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
-        return 0;
-    }
-
-    /* Cookie _MCH present ? if not, assume ST machine */
-    if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
-        cookie_mch = MCH_ST;
-    }
-
-    /* Cookie _SND present ? if not, assume ST machine */
-    if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
-        cookie_snd = SND_PSG;
-    }
-
-    /* Check if we have 8 bits audio */
-    if ((cookie_snd & SND_8BIT) == 0) {
-        DEBUG_PRINT((DEBUG_NAME "no 8 bits sound\n"));
-        return (0);
-    }
-
-    /* Check if audio is lockable */
-    if (cookie_snd & SND_16BIT) {
-        if (Locksnd() != 1) {
-            DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
-            return (0);
-        }
-
-        Unlocksnd();
-    }
-
-    DEBUG_PRINT((DEBUG_NAME "8 bits audio available!\n"));
-    return (1);
-}
-
 static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
-}
-
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
-{
-    SDL_AudioDevice *this;
-
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    /* Set the function pointers */
-    this->OpenAudio = Mint_OpenAudio;
-    this->CloseAudio = Mint_CloseAudio;
-    this->LockAudio = Mint_LockAudio;
-    this->UnlockAudio = Mint_UnlockAudio;
-    this->free = Audio_DeleteDevice;
-
-    return this;
-}
-
-AudioBootStrap MINTAUDIO_DMA8_bootstrap = {
-    MINT_AUDIO_DRIVER_NAME, "MiNT DMA 8 bits audio driver",
-    Audio_Available, Audio_CreateDevice
-};
-
-static void
-Mint_LockAudio(_THIS)
+MINTDMA8_LockDevice(_THIS)
 {
     void *oldpile;
 
@@ -170,7 +73,7 @@
 }
 
 static void
-Mint_UnlockAudio(_THIS)
+MINTDMA8_UnlockDevice(_THIS)
 {
     void *oldpile;
 
@@ -181,57 +84,59 @@
 }
 
 static void
-Mint_CloseAudio(_THIS)
+MINTDMA8_CloseDevice(_THIS)
 {
-    void *oldpile;
+    if (this->hidden != NULL) {
+        /* Stop replay */
+        void *oldpile = (void *) Super(0);
 
-    /* Stop replay */
-    oldpile = (void *) Super(0);
-    DMAAUDIO_IO.control = 0;
-    Super(oldpile);
+        DMAAUDIO_IO.control = 0;
+        Super(oldpile);
+
+        DEBUG_PRINT((DEBUG_NAME "closeaudio: replay stopped\n"));
 
-    DEBUG_PRINT((DEBUG_NAME "closeaudio: replay stopped\n"));
+        /* Disable interrupt */
+        Jdisint(MFP_DMASOUND);
 
-    /* Disable interrupt */
-    Jdisint(MFP_DMASOUND);
+        DEBUG_PRINT((DEBUG_NAME "closeaudio: interrupt disabled\n"));
 
-    DEBUG_PRINT((DEBUG_NAME "closeaudio: interrupt disabled\n"));
+        /* Wait if currently playing sound */
+        while (SDL_MintAudio_mutex != 0) {}
 
-    /* Wait if currently playing sound */
-    while (SDL_MintAudio_mutex != 0) {
-    }
-
-    DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n"));
+        DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n"));
 
-    /* Clear buffers */
-    if (SDL_MintAudio_audiobuf[0]) {
-        Mfree(SDL_MintAudio_audiobuf[0]);
-        SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
+        /* Clear buffers */
+        if (SDL_MintAudio_audiobuf[0]) {
+            Mfree(SDL_MintAudio_audiobuf[0]);
+            SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
+        }
+
+        DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n"));
+        SDL_free(this->buffer);
+        this->buffer = NULL;
     }
-
-    DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n"));
 }
 
 static int
-Mint_CheckAudio(_THIS, SDL_AudioSpec * spec)
+MINTDMA8_CheckAudio(_THIS)
 {
     int i, masterprediv, sfreq;
     unsigned long masterclock;
 
     DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",
-                 SDL_AUDIO_BITSIZE(spec->format)));
-    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format)));
-    DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format)));
-    DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format)));
-    DEBUG_PRINT(("channels=%d, ", spec->channels));
-    DEBUG_PRINT(("freq=%d\n", spec->freq));
+                 SDL_AUDIO_BITSIZE(this->spec.format)));
+    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
+    DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format)));
+    DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
+    DEBUG_PRINT(("channels=%d, ", this->spec.channels));
+    DEBUG_PRINT(("freq=%d\n", this->spec.freq));
 
-    if (spec->channels > 2) {
-        spec->channels = 2;     /* no more than stereo! */
+    if (this->spec.channels > 2) {
+        this->spec.channels = 2;     /* no more than stereo! */
     }
 
     /* Check formats available */
-    spec->format = AUDIO_S8;
+    this->spec.format = AUDIO_S8;
 
     /* Calculate and select the closest frequency */
     sfreq = 0;
@@ -272,22 +177,22 @@
     }
 #endif
 
-    MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, spec->freq);
-    spec->freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
+    MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq);
+    this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
 
     DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",
-                 SDL_AUDIO_BITSIZE(spec->format)));
-    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format)));
-    DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format)));
-    DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format)));
-    DEBUG_PRINT(("channels=%d, ", spec->channels));
-    DEBUG_PRINT(("freq=%d\n", spec->freq));
+                 SDL_AUDIO_BITSIZE(this->spec.format)));
+    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
+    DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format)));
+    DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
+    DEBUG_PRINT(("channels=%d, ", this->spec.channels));
+    DEBUG_PRINT(("freq=%d\n", this->spec.freq));
 
     return 0;
 }
 
 static void
-Mint_InitAudio(_THIS, SDL_AudioSpec * spec)
+MINTDMA8_InitAudio(_THIS)
 {
     void *oldpile;
     unsigned long buffer;
@@ -316,7 +221,7 @@
     DMAAUDIO_IO.end_low = buffer & 255;
 
     mode = 3 - MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor;
-    if (spec->channels == 1) {
+    if (this->spec.channels == 1) {
         mode |= 1 << 7;
     }
     DMAAUDIO_IO.sound_ctrl = mode;
@@ -339,29 +244,40 @@
 }
 
 static int
-Mint_OpenAudio(_THIS, SDL_AudioSpec * spec)
+MINTDMA8_OpenDevice(_THIS, const char *devname, int iscapture)
 {
     SDL_MintAudio_device = this;
 
     /* Check audio capabilities */
-    if (Mint_CheckAudio(this, spec) == -1) {
-        return -1;
+    if (MINTDMA8_CheckAudio(this) == -1) {
+        return 0;
     }
 
-    SDL_CalculateAudioSpec(spec);
+    /* Initialize all variables that we clean on shutdown */
+    this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* Allocate memory for audio buffers in DMA-able RAM */
-    DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
+    DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size));
 
-    SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size * 2, MX_STRAM);
+    SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(this->spec.size * 2, MX_STRAM);
     if (SDL_MintAudio_audiobuf[0] == NULL) {
-        SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
-        return (-1);
+        SDL_free(this->hidden);
+        this->hidden = NULL;
+        SDL_OutOfMemory();
+        return 0;
     }
-    SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size;
+    SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size;
     SDL_MintAudio_numbuf = 0;
-    SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size * 2);
-    SDL_MintAudio_audiosize = spec->size;
+    SDL_memset(SDL_MintAudio_audiobuf[0],this->spec.silence,this->spec.size*2);
+    SDL_MintAudio_audiosize = this->spec.size;
     SDL_MintAudio_mutex = 0;
 
     DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n",
@@ -372,9 +288,56 @@
     SDL_MintAudio_CheckFpu();
 
     /* Setup audio hardware */
-    Mint_InitAudio(this, spec);
+    MINTDMA8_InitAudio(this);
 
-    return (1);                 /* We don't use threaded audio */
+    return 1;  /* good to go. */
 }
 
+static int
+MINTDMA8_Init(SDL_AudioDriverImpl *impl)
+{
+    /* Cookie _MCH present ? if not, assume ST machine */
+    if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
+        cookie_mch = MCH_ST;
+    }
+
+    /* Cookie _SND present ? if not, assume ST machine */
+    if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
+        cookie_snd = SND_PSG;
+    }
+
+    /* Check if we have 8 bits audio */
+    if ((cookie_snd & SND_8BIT) == 0) {
+        SDL_SetError(DEBUG_NAME "no 8 bits sound");
+        return 0;
+    }
+
+    /* Check if audio is lockable */
+    if (cookie_snd & SND_16BIT) {
+        if (Locksnd() != 1) {
+            SDL_SetError(DEBUG_NAME "audio locked by other application");
+            return 0;
+        }
+
+        Unlocksnd();
+    }
+
+    DEBUG_PRINT((DEBUG_NAME "8 bits audio available!\n"));
+
+    /* Set the function pointers */
+    impl->OpenDevice = MINTDMA8_OpenDevice;
+    impl->CloseDevice = MINTDMA8_CloseDevice;
+    impl->LockAudio = MINTDMA8_LockAudio;
+    impl->UnlockAudio = MINTDMA8_UnlockAudio;
+    impl->OnlyHasDefaultOutputDevice = 1;
+    impl->ProvidesOwnCallbackThread = 1;
+    impl->SkipMixerLock = 1;
+
+    return 1;
+}
+
+AudioBootStrap MINTAUDIO_DMA8_bootstrap = {
+    MINT_AUDIO_DRIVER_NAME, "MiNT DMA 8 bits audio driver", MINTDMA8_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/mint/SDL_mintaudio_gsxb.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/mint/SDL_mintaudio_gsxb.c	Tue Oct 17 09:15:21 2006 +0000
@@ -63,176 +63,83 @@
 
 /*--- Audio driver functions ---*/
 
-static void Mint_CloseAudio(_THIS);
-static int Mint_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void Mint_LockAudio(_THIS);
-static void Mint_UnlockAudio(_THIS);
-
-/* To check/init hardware audio */
-static int Mint_CheckAudio(_THIS, SDL_AudioSpec * spec);
-static void Mint_InitAudio(_THIS, SDL_AudioSpec * spec);
-
 /* GSXB callbacks */
-static void Mint_GsxbInterrupt(void);
-static void Mint_GsxbNullInterrupt(void);
-
-/*--- Audio driver bootstrap functions ---*/
-
-static int
-Audio_Available(void)
-{
-    const char *envr = SDL_getenv("SDL_AUDIODRIVER");
-
-    /* Check if user asked a different audio driver */
-    if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME) != 0)) {
-        DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
-        return (0);
-    }
-
-    /* Cookie _SND present ? if not, assume ST machine */
-    if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
-        cookie_snd = SND_PSG;
-    }
-
-    /* Check if we have 16 bits audio */
-    if ((cookie_snd & SND_16BIT) == 0) {
-        DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
-        return (0);
-    }
-
-    /* Cookie GSXB present ? */
-    cookie_gsxb = (Getcookie(C_GSXB, &cookie_gsxb) == C_FOUND);
-
-    /* Is it GSXB ? */
-    if (((cookie_snd & SND_GSXB) == 0) || (cookie_gsxb == 0)) {
-        DEBUG_PRINT((DEBUG_NAME "no GSXB audio\n"));
-        return (0);
-    }
-
-    /* Check if audio is lockable */
-    if (Locksnd() != 1) {
-        DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
-        return (0);
-    }
-
-    Unlocksnd();
-
-    DEBUG_PRINT((DEBUG_NAME "GSXB audio available!\n"));
-    return (1);
-}
+static void MINTGSXB_GsxbInterrupt(void);
+static void MINTGSXB_GsxbNullInterrupt(void);
 
 static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
-}
-
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
-{
-    SDL_AudioDevice *this;
-
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    /* Set the function pointers */
-    this->OpenAudio = Mint_OpenAudio;
-    this->CloseAudio = Mint_CloseAudio;
-    this->LockAudio = Mint_LockAudio;
-    this->UnlockAudio = Mint_UnlockAudio;
-    this->free = Audio_DeleteDevice;
-
-    return this;
-}
-
-AudioBootStrap MINTAUDIO_GSXB_bootstrap = {
-    MINT_AUDIO_DRIVER_NAME, "MiNT GSXB audio driver",
-    Audio_Available, Audio_CreateDevice
-};
-
-static void
-Mint_LockAudio(_THIS)
+MINTGSXB_LockDevice(_THIS)
 {
     /* Stop replay */
     Buffoper(0);
 }
 
 static void
-Mint_UnlockAudio(_THIS)
+MINTGSXB_UnlockDevice(_THIS)
 {
     /* Restart replay */
     Buffoper(SB_PLA_ENA | SB_PLA_RPT);
 }
 
 static void
-Mint_CloseAudio(_THIS)
+MINTGSXB_CloseDevice(_THIS)
 {
-    /* Stop replay */
-    Buffoper(0);
+    if (this->hidden != NULL) {
+        /* Stop replay */
+        Buffoper(0);
 
-    /* Uninstall interrupt */
-    if (NSetinterrupt(2, SI_NONE, Mint_GsxbNullInterrupt) < 0) {
-        DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed in close\n"));
-    }
+        /* Uninstall interrupt */
+        if (NSetinterrupt(2, SI_NONE, MINTGSXB_GsxbNullInterrupt) < 0) {
+            DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed in close\n"));
+        }
 
-    /* Wait if currently playing sound */
-    while (SDL_MintAudio_mutex != 0) {
-    }
+        /* Wait if currently playing sound */
+        while (SDL_MintAudio_mutex != 0) {}
 
-    /* Clear buffers */
-    if (SDL_MintAudio_audiobuf[0]) {
-        Mfree(SDL_MintAudio_audiobuf[0]);
-        SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
+        /* Clear buffers */
+        if (SDL_MintAudio_audiobuf[0]) {
+            Mfree(SDL_MintAudio_audiobuf[0]);
+            SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
+        }
+
+        /* Unlock sound system */
+        Unlocksnd();
+
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
-
-    /* Unlock sound system */
-    Unlocksnd();
 }
 
 static int
-Mint_CheckAudio(_THIS, SDL_AudioSpec * spec)
+MINTGSXB_CheckAudio(_THIS)
 {
     long snd_format;
     int i, resolution, format_signed, format_bigendian;
-    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
+    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
     int valid_datatype = 0;
 
-    resolution = SDL_AUDIO_BITSIZE(spec->format);
-    format_signed = SDL_AUDIO_ISSIGNED(spec->format);
-    format_bigendian = SDL_AUDIO_ISBIGENDIAN(spec->format);
+    resolution = SDL_AUDIO_BITSIZE(this->spec.format);
+    format_signed = SDL_AUDIO_ISSIGNED(this->spec.format);
+    format_bigendian = SDL_AUDIO_ISBIGENDIAN(this->spec.format);
 
     DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ", resolution));
-    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format)));
+    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
     DEBUG_PRINT(("signed=%d, ", format_signed));
     DEBUG_PRINT(("big endian=%d, ", format_bigendian));
-    DEBUG_PRINT(("channels=%d, ", spec->channels));
-    DEBUG_PRINT(("freq=%d\n", spec->freq));
+    DEBUG_PRINT(("channels=%d, ", this->spec.channels));
+    DEBUG_PRINT(("freq=%d\n", this->spec.freq));
 
-    if (spec->channels > 2) {
-        spec->channels = 2;     /* no more than stereo! */
+    if (this->spec.channels > 2) {
+        this->spec.channels = 2;     /* no more than stereo! */
     }
 
     while ((!valid_datatype) && (test_format)) {
         /* Check formats available */
         snd_format = Sndstatus(SND_QUERYFORMATS);
-        spec->format = test_format;
-        resolution = SDL_AUDIO_BITSIZE(spec->format);
-        format_signed = SDL_AUDIO_ISSIGNED(spec->format);
-        format_bigendian = SDL_AUDIO_ISBIGENDIAN(spec->format);
+        this->spec.format = test_format;
+        resolution = SDL_AUDIO_BITSIZE(this->spec.format);
+        format_signed = SDL_AUDIO_ISSIGNED(this->spec.format);
+        format_bigendian = SDL_AUDIO_ISBIGENDIAN(this->spec.format);
         switch (test_format) {
             case AUDIO_U8:
             case AUDIO_S8:
@@ -279,14 +186,14 @@
             /* Ok */
         } else if (snd_format & SND_FORMATUNSIGNED) {
             /* Give unsigned format */
-            spec->format = spec->format & (~SDL_AUDIO_MASK_SIGNED);
+            this->spec.format = this->spec.format & (~SDL_AUDIO_MASK_SIGNED);
         }
     } else {
         if (snd_format & SND_FORMATUNSIGNED) {
             /* Ok */
         } else if (snd_format & SND_FORMATSIGNED) {
             /* Give signed format */
-            spec->format |= SDL_AUDIO_MASK_SIGNED;
+            this->spec.format |= SDL_AUDIO_MASK_SIGNED;
         }
     }
 
@@ -295,14 +202,14 @@
             /* Ok */
         } else if (snd_format & SND_FORMATLITTLEENDIAN) {
             /* Give little endian format */
-            spec->format = spec->format & (~SDL_AUDIO_MASK_ENDIAN);
+            this->spec.format = this->spec.format & (~SDL_AUDIO_MASK_ENDIAN);
         }
     } else {
         if (snd_format & SND_FORMATLITTLEENDIAN) {
             /* Ok */
         } else if (snd_format & SND_FORMATBIGENDIAN) {
             /* Give big endian format */
-            spec->format |= SDL_AUDIO_MASK_ENDIAN;
+            this->spec.format |= SDL_AUDIO_MASK_ENDIAN;
         }
     }
 
@@ -324,22 +231,22 @@
     }
 #endif
 
-    MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, spec->freq);
-    spec->freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
+    MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq);
+    this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
 
     DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",
-                 SDL_AUDIO_BITSIZE(spec->format)));
-    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format)));
-    DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format)));
-    DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format)));
-    DEBUG_PRINT(("channels=%d, ", spec->channels));
-    DEBUG_PRINT(("freq=%d\n", spec->freq));
+                 SDL_AUDIO_BITSIZE(this->spec.format)));
+    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
+    DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format)));
+    DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
+    DEBUG_PRINT(("channels=%d, ", this->spec.channels));
+    DEBUG_PRINT(("freq=%d\n", this->spec.freq));
 
     return 0;
 }
 
 static void
-Mint_InitAudio(_THIS, SDL_AudioSpec * spec)
+MINTGSXB_InitAudio(_THIS)
 {
     int channels_mode, prediv;
     void *buffer;
@@ -352,23 +259,23 @@
     Setmontracks(0);
 
     /* Select replay format */
-    switch (SDL_AUDIO_BITSIZE(spec->format)) {
+    switch (SDL_AUDIO_BITSIZE(this->spec.format)) {
     case 8:
-        if (spec->channels == 2) {
+        if (this->spec.channels == 2) {
             channels_mode = STEREO8;
         } else {
             channels_mode = MONO8;
         }
         break;
     case 16:
-        if (spec->channels == 2) {
+        if (this->spec.channels == 2) {
             channels_mode = STEREO16;
         } else {
             channels_mode = MONO16;
         }
         break;
     case 32:
-        if (spec->channels == 2) {
+        if (this->spec.channels == 2) {
             channels_mode = STEREO32;
         } else {
             channels_mode = MONO32;
@@ -387,12 +294,12 @@
 
     /* Set buffer */
     buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
-    if (Setbuffer(0, buffer, buffer + spec->size) < 0) {
+    if (Setbuffer(0, buffer, buffer + this->spec.size) < 0) {
         DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
     }
 
     /* Install interrupt */
-    if (NSetinterrupt(2, SI_PLAY, Mint_GsxbInterrupt) < 0) {
+    if (NSetinterrupt(2, SI_PLAY, MINTGSXB_GsxbInterrupt) < 0) {
         DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed\n"));
     }
 
@@ -402,35 +309,46 @@
 }
 
 static int
-Mint_OpenAudio(_THIS, SDL_AudioSpec * spec)
+MINTGSXB_OpenDevice(_THIS, const char *devname, int iscapture)
 {
     /* Lock sound system */
     if (Locksnd() != 1) {
-        SDL_SetError("Mint_OpenAudio: Audio system already in use");
-        return (-1);
+        SDL_SetError("MINTGSXB_OpenDevice: Audio system already in use");
+        return 0;
     }
 
     SDL_MintAudio_device = this;
 
     /* Check audio capabilities */
-    if (Mint_CheckAudio(this, spec) == -1) {
-        return -1;
+    if (MINTGSXB_CheckAudio(this) == -1) {
+        return 0;
     }
 
-    SDL_CalculateAudioSpec(spec);
+    /* Initialize all variables that we clean on shutdown */
+    this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* Allocate memory for audio buffers in DMA-able RAM */
-    DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
+    DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size));
 
-    SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size * 2, MX_STRAM);
+    SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(this->spec.size * 2, MX_STRAM);
     if (SDL_MintAudio_audiobuf[0] == NULL) {
-        SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
-        return (-1);
+        SDL_free(this->hidden);
+        this->hidden = NULL;
+        SDL_OutOfMemory();
+        return 0;
     }
-    SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size;
+    SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size;
     SDL_MintAudio_numbuf = 0;
-    SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size * 2);
-    SDL_MintAudio_audiosize = spec->size;
+    SDL_memset(SDL_MintAudio_audiobuf[0],this->spec.silence,this->spec.size*2);
+    SDL_MintAudio_audiosize = this->spec.size;
     SDL_MintAudio_mutex = 0;
 
     DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n",
@@ -441,13 +359,13 @@
     SDL_MintAudio_CheckFpu();
 
     /* Setup audio hardware */
-    Mint_InitAudio(this, spec);
+    MINTGSXB_InitAudio(this);
 
-    return (1);                 /* We don't use threaded audio */
+    return 1;  /* good to go. */
 }
 
 static void
-Mint_GsxbInterrupt(void)
+MINTGSXB_GsxbInterrupt(void)
 {
     Uint8 *newbuf;
 
@@ -465,8 +383,57 @@
 }
 
 static void
-Mint_GsxbNullInterrupt(void)
+MINTGSXB_GsxbNullInterrupt(void)
 {
 }
 
+static int
+MINTGSXB_Init(SDL_AudioDriverImpl *impl)
+{
+    /* Cookie _SND present ? if not, assume ST machine */
+    if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
+        cookie_snd = SND_PSG;
+    }
+
+    /* Check if we have 16 bits audio */
+    if ((cookie_snd & SND_16BIT) == 0) {
+        SDL_SetError(DEBUG_NAME "no 16-bit sound");
+        return 0;
+    }
+
+    /* Cookie GSXB present ? */
+    cookie_gsxb = (Getcookie(C_GSXB, &cookie_gsxb) == C_FOUND);
+
+    /* Is it GSXB ? */
+    if (((cookie_snd & SND_GSXB) == 0) || (cookie_gsxb == 0)) {
+        SDL_SetError(DEBUG_NAME "no GSXB audio");
+        return 0;
+    }
+
+    /* Check if audio is lockable */
+    if (Locksnd() != 1) {
+        SDL_SetError(DEBUG_NAME "audio locked by other application");
+        return 0;
+    }
+
+    Unlocksnd();
+
+    DEBUG_PRINT((DEBUG_NAME "GSXB audio available!\n"));
+
+    /* Set the function pointers */
+    impl->OpenDevice = MINTGSXB_OpenDevice;
+    impl->CloseDevice = MINTGSXB_CloseDevice;
+    impl->LockAudio = MINTGSXB_LockAudio;
+    impl->UnlockAudio = MINTGSXB_UnlockAudio;
+    impl->OnlyHasDefaultOutputDevice = 1;
+    impl->ProvidesOwnCallbackThread = 1;
+    impl->SkipMixerLock = 1;
+
+    return 1;
+}
+
+AudioBootStrap MINTAUDIO_GSXB_bootstrap = {
+    MINT_AUDIO_DRIVER_NAME, "MiNT GSXB audio driver", MINTGSXB_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/mint/SDL_mintaudio_mcsn.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/mint/SDL_mintaudio_mcsn.c	Tue Oct 17 09:15:21 2006 +0000
@@ -61,192 +61,82 @@
 
 /*--- Static variables ---*/
 
-static unsigned long cookie_snd, cookie_mch;
-static cookie_mcsn_t *cookie_mcsn;
-
-/*--- Audio driver functions ---*/
-
-static void Mint_CloseAudio(_THIS);
-static int Mint_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void Mint_LockAudio(_THIS);
-static void Mint_UnlockAudio(_THIS);
-
-/* To check/init hardware audio */
-static int Mint_CheckAudio(_THIS, SDL_AudioSpec * spec);
-static void Mint_InitAudio(_THIS, SDL_AudioSpec * spec);
-
-/*--- Audio driver bootstrap functions ---*/
-
-static int
-Audio_Available(void)
-{
-    unsigned long dummy;
-    const char *envr = SDL_getenv("SDL_AUDIODRIVER");
-
-    SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND);
-
-    /* We can't use XBIOS in interrupt with Magic, don't know about thread */
-    if (Getcookie(C_MagX, &dummy) == C_FOUND) {
-        return (0);
-    }
-
-    /* Check if user asked a different audio driver */
-    if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME) != 0)) {
-        DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
-        return (0);
-    }
-
-    /* Cookie _MCH present ? if not, assume ST machine */
-    if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
-        cookie_mch = MCH_ST;
-    }
-
-    /* Cookie _SND present ? if not, assume ST machine */
-    if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
-        cookie_snd = SND_PSG;
-    }
-
-    /* Check if we have 16 bits audio */
-    if ((cookie_snd & SND_16BIT) == 0) {
-        DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
-        return (0);
-    }
-
-    /* Cookie MCSN present ? */
-    if (Getcookie(C_McSn, (long *) &cookie_mcsn) != C_FOUND) {
-        DEBUG_PRINT((DEBUG_NAME "no MCSN audio\n"));
-        return (0);
-    }
-
-    /* Check if interrupt at end of replay */
-    if (cookie_mcsn->pint == 0) {
-        DEBUG_PRINT((DEBUG_NAME "no interrupt at end of replay\n"));
-        return (0);
-    }
-
-    /* Check if audio is lockable */
-    if (Locksnd() != 1) {
-        DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
-        return (0);
-    }
-
-    Unlocksnd();
-
-    DEBUG_PRINT((DEBUG_NAME "MCSN audio available!\n"));
-    return (1);
-}
+static unsigned long cookie_snd = 0;
+static unsigned long cookie_mch = 0;
+static cookie_mcsn_t *cookie_mcsn = NULL;
 
 static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
-}
-
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
-{
-    SDL_AudioDevice *this;
-
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    /* Set the function pointers */
-    this->OpenAudio = Mint_OpenAudio;
-    this->CloseAudio = Mint_CloseAudio;
-    this->LockAudio = Mint_LockAudio;
-    this->UnlockAudio = Mint_UnlockAudio;
-    this->free = Audio_DeleteDevice;
-
-    return this;
-}
-
-AudioBootStrap MINTAUDIO_MCSN_bootstrap = {
-    MINT_AUDIO_DRIVER_NAME, "MiNT MCSN audio driver",
-    Audio_Available, Audio_CreateDevice
-};
-
-static void
-Mint_LockAudio(_THIS)
+MINTMCSN_LockDevice(_THIS)
 {
     /* Stop replay */
     Buffoper(0);
 }
 
 static void
-Mint_UnlockAudio(_THIS)
+MINTMCSN_UnlockDevice(_THIS)
 {
     /* Restart replay */
     Buffoper(SB_PLA_ENA | SB_PLA_RPT);
 }
 
 static void
-Mint_CloseAudio(_THIS)
+MINTMCSN_CloseDevice(_THIS)
 {
-    /* Stop replay */
-    SDL_MintAudio_WaitThread();
-    Buffoper(0);
+    if (this->hidden != NULL) {
+        /* Stop replay */
+        SDL_MintAudio_WaitThread();
+        Buffoper(0);
 
-    if (!SDL_MintAudio_mint_present) {
-        /* Uninstall interrupt */
-        Jdisint(MFP_DMASOUND);
-    }
+        if (!SDL_MintAudio_mint_present) {
+            /* Uninstall interrupt */
+            Jdisint(MFP_DMASOUND);
+        }
 
-    /* Wait if currently playing sound */
-    while (SDL_MintAudio_mutex != 0) {
-    }
+        /* Wait if currently playing sound */
+        while (SDL_MintAudio_mutex != 0) {}
 
-    /* Clear buffers */
-    if (SDL_MintAudio_audiobuf[0]) {
-        Mfree(SDL_MintAudio_audiobuf[0]);
-        SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
+        /* Clear buffers */
+        if (SDL_MintAudio_audiobuf[0]) {
+            Mfree(SDL_MintAudio_audiobuf[0]);
+            SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
+        }
+
+        /* Unlock sound system */
+        Unlocksnd();
+
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
-
-    /* Unlock sound system */
-    Unlocksnd();
 }
 
 static int
-Mint_CheckAudio(_THIS, SDL_AudioSpec * spec)
+MINTMCSN_CheckAudio(_THIS)
 {
     int i;
     unsigned long masterclock, masterprediv;
 
     DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",
-                 SDL_AUDIO_BITSIZE(spec->format)));
-    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format)));
-    DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format)));
-    DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format)));
-    DEBUG_PRINT(("channels=%d, ", spec->channels));
-    DEBUG_PRINT(("freq=%d\n", spec->freq));
+                 SDL_AUDIO_BITSIZE(this->spec.format)));
+    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
+    DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format)));
+    DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
+    DEBUG_PRINT(("channels=%d, ", this->spec.channels));
+    DEBUG_PRINT(("freq=%d\n", this->spec.freq));
 
-    if (spec->channels > 2) {
-        spec->channels = 2;     /* no more than stereo! */
+    if (this->spec.channels > 2) {
+        this->spec.channels = 2;     /* no more than stereo! */
     }
 
     /* Check formats available */
     MINTAUDIO_freqcount = 0;
     switch (cookie_mcsn->play) {
     case MCSN_ST:
-        spec->channels = 1;
-        spec->format = AUDIO_S8;        /* FIXME: is it signed or unsigned ? */
+        this->spec.channels = 1;
+        this->spec.format = AUDIO_S8;  /* FIXME: is it signed or unsigned ? */
         SDL_MintAudio_AddFrequency(this, 12500, 0, 0, -1);
         break;
     case MCSN_TT:              /* Also STE, Mega STE */
-        spec->format = AUDIO_S8;
+        this->spec.format = AUDIO_S8;
         masterclock = MASTERCLOCK_STE;
         masterprediv = MASTERPREDIV_STE;
         if ((cookie_mch >> 16) == MCH_TT) {
@@ -280,10 +170,10 @@
                                            (1 << i) - 1, -1);
             }
         }
-        spec->format |= SDL_AUDIO_MASK_SIGNED;  /* Audio is always signed */
-        if ((SDL_AUDIO_BITSIZE(spec->format)) == 16) {
-            spec->format |= SDL_AUDIO_MASK_ENDIAN;      /* Audio is always big endian */
-            spec->channels = 2; /* 16 bits always stereo */
+        this->spec.format |= SDL_AUDIO_MASK_SIGNED;  /* Audio is always signed */
+        if ((SDL_AUDIO_BITSIZE(this->spec.format)) == 16) {
+            this->spec.format |= SDL_AUDIO_MASK_ENDIAN;      /* Audio is always big endian */
+            this->spec.channels = 2; /* 16 bits always stereo */
         }
         break;
     }
@@ -297,22 +187,22 @@
     }
 #endif
 
-    MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, spec->freq);
-    spec->freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
+    MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq);
+    this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
 
     DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",
-                 SDL_AUDIO_BITSIZE(spec->format)));
-    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format)));
-    DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format)));
-    DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format)));
-    DEBUG_PRINT(("channels=%d, ", spec->channels));
-    DEBUG_PRINT(("freq=%d\n", spec->freq));
+                 SDL_AUDIO_BITSIZE(this->spec.format)));
+    DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
+    DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format)));
+    DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
+    DEBUG_PRINT(("channels=%d, ", this->spec.channels));
+    DEBUG_PRINT(("freq=%d\n", this->spec.freq));
 
     return 0;
 }
 
 static void
-Mint_InitAudio(_THIS, SDL_AudioSpec * spec)
+MINTMCSN_InitAudio(_THIS)
 {
     int channels_mode, prediv, dmaclock;
     void *buffer;
@@ -329,9 +219,9 @@
 
     /* Select replay format */
     channels_mode = STEREO16;
-    switch (SDL_AUDIO_BITSIZE(spec->format)) {
+    switch (SDL_AUDIO_BITSIZE(this->spec.format)) {
     case 8:
-        if (spec->channels == 2) {
+        if (this->spec.channels == 2) {
             channels_mode = STEREO8;
         } else {
             channels_mode = MONO8;
@@ -358,7 +248,7 @@
 
     /* Set buffer */
     buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
-    if (Setbuffer(0, buffer, buffer + spec->size) < 0) {
+    if (Setbuffer(0, buffer, buffer + this->spec.size) < 0) {
         DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
     }
 
@@ -381,35 +271,46 @@
 }
 
 static int
-Mint_OpenAudio(_THIS, SDL_AudioSpec * spec)
+MINTMCSN_OpenDevice(_THIS, const char *devname, int iscapture)
 {
     /* Lock sound system */
     if (Locksnd() != 1) {
-        SDL_SetError("Mint_OpenAudio: Audio system already in use");
-        return (-1);
+        SDL_SetError("MINTMCSN_OpenDevice: Audio system already in use");
+        return 0;
     }
 
     SDL_MintAudio_device = this;
 
     /* Check audio capabilities */
-    if (Mint_CheckAudio(this, spec) == -1) {
-        return -1;
+    if (MINTMCSN_CheckAudio(this) == -1) {
+        return 0;
     }
 
-    SDL_CalculateAudioSpec(spec);
+    /* Initialize all variables that we clean on shutdown */
+    this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *this->hidden));
+    if (this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* Allocate memory for audio buffers in DMA-able RAM */
-    DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
+    DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size));
 
-    SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size * 2, MX_STRAM);
+    SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(this->spec.size * 2, MX_STRAM);
     if (SDL_MintAudio_audiobuf[0] == NULL) {
-        SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
-        return (-1);
+        SDL_free(this->hidden);
+        this->hidden = NULL;
+        SDL_OutOfMemory();
+        return 0;
     }
-    SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size;
+    SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size;
     SDL_MintAudio_numbuf = 0;
-    SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size * 2);
-    SDL_MintAudio_audiosize = spec->size;
+    SDL_memset(SDL_MintAudio_audiobuf[0],this->spec.silence,this->spec.size*2);
+    SDL_MintAudio_audiosize = this->spec.size;
     SDL_MintAudio_mutex = 0;
 
     DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n",
@@ -420,9 +321,75 @@
     SDL_MintAudio_CheckFpu();
 
     /* Setup audio hardware */
-    Mint_InitAudio(this, spec);
+    MINTMCSN_InitAudio(this);
 
-    return (1);                 /* We don't use SDL threaded audio */
+    return 1;  /* good to go. */
 }
 
+static int
+MINTMCSN_Init(SDL_AudioDriverImpl *impl)
+{
+    unsigned long dummy = 0;
+
+    SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND);
+
+    /* We can't use XBIOS in interrupt with Magic, don't know about thread */
+    if (Getcookie(C_MagX, &dummy) == C_FOUND) {
+        return 0;
+    }
+
+    /* Cookie _MCH present ? if not, assume ST machine */
+    if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
+        cookie_mch = MCH_ST;
+    }
+
+    /* Cookie _SND present ? if not, assume ST machine */
+    if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
+        cookie_snd = SND_PSG;
+    }
+
+    /* Check if we have 16 bits audio */
+    if ((cookie_snd & SND_16BIT) == 0) {
+        SDL_SetError(DEBUG_NAME "no 16-bit sound");
+        return 0;
+    }
+
+    /* Cookie MCSN present ? */
+    if (Getcookie(C_McSn, (long *) &cookie_mcsn) != C_FOUND) {
+        SDL_SetError(DEBUG_NAME "no MCSN audio");
+        return 0;
+    }
+
+    /* Check if interrupt at end of replay */
+    if (cookie_mcsn->pint == 0) {
+        SDL_SetError(DEBUG_NAME "no interrupt at end of replay");
+        return 0;
+    }
+
+    /* Check if audio is lockable */
+    if (Locksnd() != 1) {
+        SDL_SetError(DEBUG_NAME "audio locked by other application");
+        return 0;
+    }
+
+    Unlocksnd();
+
+    DEBUG_PRINT((DEBUG_NAME "MCSN audio available!\n"));
+
+    /* Set the function pointers */
+    impl->OpenDevice = MINTMCSN_OpenDevice;
+    impl->CloseDevice = MINTMCSN_CloseDevice;
+    impl->LockAudio = MINTMCSN_LockAudio;
+    impl->UnlockAudio = MINTMCSN_UnlockAudio;
+    impl->OnlyHasDefaultOutputDevice = 1;
+    impl->ProvidesOwnCallbackThread = 1;
+    impl->SkipMixerLock = 1;
+
+    return 1;
+}
+
+AudioBootStrap MINTAUDIO_MCSN_bootstrap = {
+    MINT_AUDIO_DRIVER_NAME, "MiNT MCSN audio driver", MINTMCSN_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/mint/SDL_mintaudio_stfa.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/mint/SDL_mintaudio_stfa.c	Tue Oct 17 09:15:21 2006 +0000
@@ -59,8 +59,9 @@
 
 /*--- Static variables ---*/