changeset 2049:5f6550e5184f

Merged SDL-ryan-multiple-audio-device branch r2803:2871 into the trunk.
author Ryan C. Gordon <icculus@icculus.org>
date Tue, 17 Oct 2006 09:15:21 +0000
parents 6067c7f9a672
children bbc89e09503f
files 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
diffstat 69 files changed, 5066 insertions(+), 5802 deletions(-) [+]
line wrap: on
line diff
--- 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 ---*/
 
-static unsigned long cookie_snd, cookie_mch;
-static cookie_stfa_t *cookie_stfa;
+static unsigned long cookie_snd = 0;
+static unsigned long cookie_mch = 0;
+static cookie_stfa_t *cookie_stfa = NULL;
 
 static const int freqs[16] = {
     4995, 6269, 7493, 8192,
@@ -69,157 +70,66 @@
     30720, 32336, 43885, 49152
 };
 
-/*--- 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)
+static void
+MINTSTFA_LockDevice(_THIS)
 {
-    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;
-    }
-
-    /* Cookie STFA present ? */
-    if (Getcookie(C_STFA, (long *) &cookie_stfa) != C_FOUND) {
-        DEBUG_PRINT((DEBUG_NAME "no STFA audio\n"));
-        return (0);
-    }
-
-    SDL_MintAudio_stfa = cookie_stfa;
-
-    DEBUG_PRINT((DEBUG_NAME "STFA 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_STFA_bootstrap = {
-    MINT_AUDIO_DRIVER_NAME, "MiNT STFA audio driver",
-    Audio_Available, Audio_CreateDevice
-};
-
-static void
-Mint_LockAudio(_THIS)
-{
-    void *oldpile;
-
     /* Stop replay */
-    oldpile = (void *) Super(0);
+    void *oldpile = (void *) Super(0);
     cookie_stfa->sound_enable = STFA_PLAY_DISABLE;
     Super(oldpile);
 }
 
 static void
-Mint_UnlockAudio(_THIS)
+MINTSTFA_UnlockDevice(_THIS)
 {
-    void *oldpile;
-
     /* Restart replay */
-    oldpile = (void *) Super(0);
+    void *oldpile = (void *) Super(0);
     cookie_stfa->sound_enable = STFA_PLAY_ENABLE | STFA_PLAY_REPEAT;
     Super(oldpile);
 }
 
 static void
-Mint_CloseAudio(_THIS)
+MINTSTFA_CloseDevice(_THIS)
 {
-    void *oldpile;
-
-    /* Stop replay */
-    oldpile = (void *) Super(0);
-    cookie_stfa->sound_enable = STFA_PLAY_DISABLE;
-    Super(oldpile);
+    if (this->hidden != NULL) {
+        /* Stop replay */
+        void *oldpile = (void *) Super(0);
+        cookie_stfa->sound_enable = STFA_PLAY_DISABLE;
+        Super(oldpile);
 
-    /* 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;
+        }
+
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
 }
 
 static int
-Mint_CheckAudio(_THIS, SDL_AudioSpec * spec)
+MINTSTFA_CheckAudio(_THIS)
 {
     int i;
 
     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 (SDL_AUDIO_BITSIZE(spec->format) > 16) {
-        spec->format = AUDIO_S16SYS;    /* clamp out int32/float32 ... */
+    if (SDL_AUDIO_BITSIZE(this->spec.format) > 16) {
+        this->spec.format = AUDIO_S16SYS;    /* clamp out int32/float32 ... */
     }
 
-    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 */
@@ -237,29 +147,25 @@
     }
 #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)
+MINTSTFA_InitAudio(_THIS)
 {
-    void *buffer;
-    void *oldpile;
-
-    buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
-
-    oldpile = (void *) Super(0);
+    void *buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
+    void *oldpile = (void *) Super(0);
 
     /* Stop replay */
     cookie_stfa->sound_enable = STFA_PLAY_DISABLE;
@@ -267,22 +173,22 @@
     /* Select replay format */
     cookie_stfa->sound_control =
         MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor;
-    if (SDL_AUDIO_BITSIZE(spec->format) == 8) {
+    if (SDL_AUDIO_BITSIZE(this->spec.format) == 8) {
         cookie_stfa->sound_control |= STFA_FORMAT_8BIT;
     } else {
         cookie_stfa->sound_control |= STFA_FORMAT_16BIT;
     }
-    if (spec->channels == 2) {
+    if (this->spec.channels == 2) {
         cookie_stfa->sound_control |= STFA_FORMAT_STEREO;
     } else {
         cookie_stfa->sound_control |= STFA_FORMAT_MONO;
     }
-    if (SDL_AUDIO_ISSIGNED(spec->format) != 0) {
+    if (SDL_AUDIO_ISSIGNED(this->spec.format) != 0) {
         cookie_stfa->sound_control |= STFA_FORMAT_SIGNED;
     } else {
         cookie_stfa->sound_control |= STFA_FORMAT_UNSIGNED;
     }
-    if (SDL_AUDIO_ISBIGENDIAN(spec->format) != 0) {
+    if (SDL_AUDIO_ISBIGENDIAN(this->spec.format) != 0) {
         cookie_stfa->sound_control |= STFA_FORMAT_BIGENDIAN;
     } else {
         cookie_stfa->sound_control |= STFA_FORMAT_LITENDIAN;
@@ -290,7 +196,7 @@
 
     /* Set buffer */
     cookie_stfa->sound_start = (unsigned long) buffer;
-    cookie_stfa->sound_end = (unsigned long) (buffer + spec->size);
+    cookie_stfa->sound_end = (unsigned long) (buffer + this->spec.size);
 
     /* Set interrupt */
     cookie_stfa->stfa_it = SDL_MintAudio_StfaInterrupt;
@@ -304,29 +210,40 @@
 }
 
 static int
-Mint_OpenAudio(_THIS, SDL_AudioSpec * spec)
+MINTSTFA_OpenDevice(_THIS, const char *devname, int iscapture)
 {
     SDL_MintAudio_device = this;
 
     /* Check audio capabilities */
-    if (Mint_CheckAudio(this, spec) == -1) {
-        return -1;
+    if (MINTSTFA_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_OutOfMemory()
+        SDL_free(this->hidden);
+        this->hidden = NULL;
+        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",
@@ -337,9 +254,49 @@
     SDL_MintAudio_CheckFpu();
 
     /* Setup audio hardware */
-    Mint_InitAudio(this, spec);
+    MINTSTFA_InitAudio(this);
 
-    return (1);                 /* We don't use threaded audio */
+    return 1;  /* good to go. */
 }
 
+
+static int
+MINTSTFA_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;
+    }
+
+    /* Cookie STFA present ? */
+    if (Getcookie(C_STFA, (long *) &cookie_stfa) != C_FOUND) {
+        SDL_SetError(DEBUG_NAME "no STFA audio");
+        return (0);
+    }
+
+    SDL_MintAudio_stfa = cookie_stfa;
+
+    DEBUG_PRINT((DEBUG_NAME "STFA audio available!\n"));
+
+    /* Set the function pointers */
+    impl->OpenDevice = MINTSTFA_OpenDevice;
+    impl->CloseDevice = MINTSTFA_CloseDevice;
+    impl->LockAudio = MINTSTFA_LockAudio;
+    impl->UnlockAudio = MINTSTFA_UnlockAudio;
+    impl->OnlyHasDefaultOutputDevice = 1;
+    impl->ProvidesOwnCallbackThread = 1;
+    impl->SkipMixerLock = 1;
+
+    return 1;
+}
+
+AudioBootStrap MINTAUDIO_STFA_bootstrap = {
+    MINT_AUDIO_DRIVER_NAME, "MiNT STFA audio driver", MINTSTFA_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/mint/SDL_mintaudio_xbios.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/mint/SDL_mintaudio_xbios.c	Tue Oct 17 09:15:21 2006 +0000
@@ -60,147 +60,50 @@
 #define DEBUG_PRINT(what)
 #endif
 
-/*--- Static variables ---*/
-
-static unsigned long cookie_snd;
-
-/*--- 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); */
-    SDL_MintAudio_mint_present = SDL_FALSE;
-
-    /* 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 _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);
-    }
-
-    /* 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 "XBIOS audio available!\n"));
-    return (1);
-}
+static unsigned long cookie_snd = 0;
 
 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_XBIOS_bootstrap = {
-    MINT_AUDIO_DRIVER_NAME, "MiNT XBIOS audio driver",
-    Audio_Available, Audio_CreateDevice
-};
-
-static void
-Mint_LockAudio(_THIS)
+MINTXBIOS_LockDevice(_THIS)
 {
     /* Stop replay */
     Buffoper(0);
 }
 
 static void
-Mint_UnlockAudio(_THIS)
+MINTXBIOS_UnlockDevice(_THIS)
 {
     /* Restart replay */
     Buffoper(SB_PLA_ENA | SB_PLA_RPT);
 }
 
 static void
-Mint_CloseAudio(_THIS)
+MINTXBIOS_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();
 }
 
 /* Falcon XBIOS implementation of Devconnect() is buggy with external clock */
@@ -269,7 +172,7 @@
 }
 
 static void
-Mint_CheckExternalClock(_THIS)
+MINTXBIOS_CheckExternalClock(_THIS)
 {
 #define SIZE_BUF_CLOCK_MEASURE (44100/10)
 
@@ -355,33 +258,33 @@
 }
 
 static int
-Mint_CheckAudio(_THIS, SDL_AudioSpec * spec)
+MINTXBIOS_CheckAudio(_THIS)
 {
     int i;
     Uint32 extclock;
 
     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));
 
-    spec->format |= SDL_AUDIO_MASK_SIGNED;      /* Audio is always signed */
+    this->spec.format |= SDL_AUDIO_MASK_SIGNED;   /* Audio is always signed */
 
     /* clamp out int32/float32 */
-    if (SDL_AUDIO_BITSIZE(spec->format) >= 16) {
-        spec->format = AUDIO_S16MSB;    /* Audio is always big endian */
-        spec->channels = 2;     /* 16 bits always stereo */
-    } else if (spec->channels > 2) {
-        spec->channels = 2;     /* no more than stereo! */
+    if (SDL_AUDIO_BITSIZE(this->spec.format) >= 16) {
+        this->spec.format = AUDIO_S16MSB;    /* Audio is always big endian */
+        this->spec.channels = 2;     /* 16 bits always stereo */
+    } else if (this->spec.channels > 2) {
+        this->spec.channels = 2;     /* no more than stereo! */
     }
 
     MINTAUDIO_freqcount = 0;
 
     /* Add external clocks if present */
-    Mint_CheckExternalClock(this);
+    MINTXBIOS_CheckExternalClock(this);
 
     /* Standard clocks */
     for (i = 1; i < 12; i++) {
@@ -404,22 +307,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)
+MINTXBIOS_InitAudio(_THIS)
 {
     int channels_mode, dmaclock, prediv;
     void *buffer;
@@ -436,9 +339,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;
@@ -461,7 +364,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"));
     }
 
@@ -485,35 +388,46 @@
 }
 
 static int
-Mint_OpenAudio(_THIS, SDL_AudioSpec * spec)
+MINTXBIOS_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("MINTXBIOS_OpenAudio: Audio system already in use");
+        return 0;
     }
 
     SDL_MintAudio_device = this;
 
     /* Check audio capabilities */
-    if (Mint_CheckAudio(this, spec) == -1) {
-        return -1;
+    if (MINTXBIOS_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",
@@ -524,9 +438,58 @@
     SDL_MintAudio_CheckFpu();
 
     /* Setup audio hardware */
-    Mint_InitAudio(this, spec);
+    MINTXBIOS_InitAudio(this);
 
-    return (1);                 /* We don't use SDL threaded audio */
+    return 1;  /* good to go. */
 }
 
+static int
+MINTXBIOS_Init(SDL_AudioDriverImpl *impl)
+{
+    unsigned long dummy = 0;
+    /*SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND); */
+    SDL_MintAudio_mint_present = SDL_FALSE;
+
+    /* We can't use XBIOS in interrupt with Magic, don't know about thread */
+    if (Getcookie(C_MagX, &dummy) == C_FOUND) {
+        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) {
+        SDL_SetError(DEBUG_NAME "no 16-bit sound");
+        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 "XBIOS audio available!\n"));
+
+    /* Set the function pointers */
+    impl->OpenDevice = MINTXBIOS_OpenDevice;
+    impl->CloseDevice = MINTXBIOS_CloseDevice;
+    impl->LockAudio = MINTXBIOS_LockAudio;
+    impl->UnlockAudio = MINTXBIOS_UnlockAudio;
+    impl->OnlyHasDefaultOutputDevice = 1;
+    impl->ProvidesOwnCallbackThread = 1;
+    impl->SkipMixerLock = 1;
+
+    return 1;
+}
+
+AudioBootStrap MINTAUDIO_XBIOS_bootstrap = {
+    MINT_AUDIO_DRIVER_NAME, "MiNT XBIOS audio driver", MINTXBIOS_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/mme/SDL_mmeaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/mme/SDL_mmeaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -31,70 +31,6 @@
 
 static BOOL inUse[NUM_BUFFERS];
 
-/* Audio driver functions */
-static int MME_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void MME_WaitAudio(_THIS);
-static Uint8 *MME_GetAudioBuf(_THIS);
-static void MME_PlayAudio(_THIS);
-static void MME_WaitDone(_THIS);
-static void MME_CloseAudio(_THIS);
-
-/* Audio driver bootstrap functions */
-static int
-Audio_Available(void)
-{
-    return (1);
-}
-
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
-    if (device) {
-        if (device->hidden) {
-            SDL_free(device->hidden);
-            device->hidden = NULL;
-        }
-        SDL_free(device);
-        device = NULL;
-    }
-}
-
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
-{
-    SDL_AudioDevice *this;
-
-/* Initialize all variables that we clean on shutdown */
-    this = SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = 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 = MME_OpenAudio;
-    this->WaitAudio = MME_WaitAudio;
-    this->PlayAudio = MME_PlayAudio;
-    this->GetAudioBuf = MME_GetAudioBuf;
-    this->WaitDone = MME_WaitDone;
-    this->CloseAudio = MME_CloseAudio;
-    this->free = Audio_DeleteDevice;
-
-    return this;
-}
-
-AudioBootStrap MMEAUDIO_bootstrap = {
-    "waveout", "Tru64 MME WaveOut",
-    Audio_Available, Audio_CreateDevice
-};
-
 static void
 SetMMerror(char *function, MMRESULT code)
 {
@@ -108,7 +44,7 @@
 }
 
 static void CALLBACK
-MME_CALLBACK(HWAVEOUT hwo,
+MME_Callback(HWAVEOUT hwo,
              UINT uMsg, DWORD dwInstance, LPARAM dwParam1, LPARAM dwParam2)
 {
     WAVEHDR *wp = (WAVEHDR *) dwParam1;
@@ -118,116 +54,137 @@
 }
 
 static int
-MME_OpenAudio(_THIS, SDL_AudioSpec * spec)
+MME_OpenDevice(_THIS, const char *devname, int iscapture)
 {
+    int valid_format = 0;
     MMRESULT result;
+    Uint8 *mixbuf = NULL;
     int i;
 
-    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));
 
     /* Set basic WAVE format parameters */
-    shm = mmeAllocMem(sizeof(*shm));
-    if (shm == NULL) {
-        SDL_SetError("Out of memory: shm");
-        return (-1);
+    this->hidden->shm = mmeAllocMem(sizeof(*this->hidden->shm));
+    if (this->hidden->shm == NULL) {
+        MME_CloseDevice(this);
+        SDL_OutOfMemory();
+        return 0;
     }
-    shm->sound = 0;
-    shm->wFmt.wf.wFormatTag = WAVE_FORMAT_PCM;
+
+    SDL_memset(this->hidden->shm, '\0', sizeof (*this->hidden->shm));
+    this->hidden->shm->sound = 0;
+    this->hidden->shm->wFmt.wf.wFormatTag = WAVE_FORMAT_PCM;
 
     /* Determine the audio parameters from the AudioSpec */
-    switch (SDL_AUDIO_BITSIZE(spec->format)) {
-    case 8:
-        /* Unsigned 8 bit audio data */
-        spec->format = AUDIO_U8;
-        shm->wFmt.wBitsPerSample = 8;
-        break;
-    case 16:
-        /* Signed 16 bit audio data */
-        spec->format = AUDIO_S16;
-        shm->wFmt.wBitsPerSample = 16;
-        break;
-    case 32:
-        /* Signed 32 bit audio data */
-        spec->format = AUDIO_S32;
-        shm->wFmt.wBitsPerSample = 32;
-        break;
-    default:
+    /* Try for a closest match on audio format */
+    for (test_format = SDL_FirstAudioFormat(this->spec.format);
+         !valid_format && test_format;) {
+        valid_format = 1;
+        switch (test_format) {
+            case AUDIO_U8:
+            case AUDIO_S16:
+            case AUDIO_S32:
+                break;
+            default:
+                valid_format = 0;
+                test_format = SDL_NextAudioFormat();
+        }
+    }
+
+    if (!valid_format) {
+        MME_CloseDevice(this);
         SDL_SetError("Unsupported audio format");
-        return (-1);
+        return 0;
     }
 
+    this->spec.format = test_format;
+    this->hidden->shm->wFmt.wBitsPerSample = SDL_AUDIO_BITSIZE(test_format);
+
     /* !!! FIXME: Can this handle more than stereo? */
-    shm->wFmt.wf.nChannels = spec->channels;
-    shm->wFmt.wf.nSamplesPerSec = spec->freq;
-    shm->wFmt.wf.nBlockAlign =
-        shm->wFmt.wf.nChannels * shm->wFmt.wBitsPerSample / 8;
-    shm->wFmt.wf.nAvgBytesPerSec =
-        shm->wFmt.wf.nSamplesPerSec * shm->wFmt.wf.nBlockAlign;
+    this->hidden->shm->wFmt.wf.nChannels = this->spec.channels;
+    this->hidden->shm->wFmt.wf.nSamplesPerSec = this->spec.freq;
+    this->hidden->shm->wFmt.wf.nBlockAlign =
+                                this->hidden->shm->wFmt.wf.nChannels *
+                                this->hidden->shm->wFmt.wBitsPerSample / 8;
+    this->hidden->shm->wFmt.wf.nAvgBytesPerSec =
+                                this->hidden->shm->wFmt.wf.nSamplesPerSec *
+                                this->hidden->shm->wFmt.wf.nBlockAlign;
 
     /* Check the buffer size -- minimum of 1/4 second (word aligned) */
-    if (spec->samples < (spec->freq / 4))
-        spec->samples = ((spec->freq / 4) + 3) & ~3;
+    if (this->spec.samples < (this->spec.freq / 4))
+        this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
 
     /* Update the fragment size as size in bytes */
-    SDL_CalculateAudioSpec(spec);
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* Open the audio device */
-    result = waveOutOpen(&(shm->sound),
+    result = waveOutOpen(&(this->hidden->shm->sound),
                          WAVE_MAPPER,
-                         &(shm->wFmt.wf),
-                         MME_CALLBACK,
+                         &(this->hidden->shm->wFmt.wf),
+                         MME_Callback,
                          NULL, (CALLBACK_FUNCTION | WAVE_OPEN_SHAREABLE));
     if (result != MMSYSERR_NOERROR) {
+        MME_CloseDevice(this);
         SetMMerror("waveOutOpen()", result);
-        return (-1);
+        return 0;
     }
 
     /* Create the sound buffers */
-    mixbuf = (Uint8 *) mmeAllocBuffer(NUM_BUFFERS * (spec->size));
+    mixbuf = (Uint8 *) mmeAllocBuffer(NUM_BUFFERS * (this->spec.size));
     if (mixbuf == NULL) {
-        SDL_SetError("Out of memory: mixbuf");
-        return (-1);
+        MME_CloseDevice(this);
+        SDL_OutOfMemory();
+        return 0;
     }
+    this->hidden->mixbuf = mixbuf;
 
     for (i = 0; i < NUM_BUFFERS; i++) {
-        shm->wHdr[i].lpData = &mixbuf[i * (spec->size)];
-        shm->wHdr[i].dwBufferLength = spec->size;
-        shm->wHdr[i].dwFlags = 0;
-        shm->wHdr[i].dwUser = i;
-        shm->wHdr[i].dwLoops = 0;       /* loop control counter */
-        shm->wHdr[i].lpNext = NULL;     /* reserved for driver */
-        shm->wHdr[i].reserved = 0;
+        this->hidden->shm->wHdr[i].lpData = &mixbuf[i * (this->spec.size)];
+        this->hidden->shm->wHdr[i].dwBufferLength = this->spec.size;
+        this->hidden->shm->wHdr[i].dwFlags = 0;
+        this->hidden->shm->wHdr[i].dwUser = i;
+        this->hidden->shm->wHdr[i].dwLoops = 0;    /* loop control counter */
+        this->hidden->shm->wHdr[i].lpNext = NULL;  /* reserved for driver */
+        this->hidden->shm->wHdr[i].reserved = 0;
         inUse[i] = FALSE;
     }
-    next_buffer = 0;
-    return 0;
+    this->hidden->next_buffer = 0;
+
+    return 1;
 }
 
 static void
-MME_WaitAudio(_THIS)
+MME_WaitDevice(_THIS)
 {
-    while (inUse[next_buffer]) {
+    while (inUse[this->hidden->next_buffer]) {
         mmeWaitForCallbacks();
         mmeProcessCallbacks();
     }
 }
 
 static Uint8 *
-MME_GetAudioBuf(_THIS)
+MME_GetDeviceBuf(_THIS)
 {
-    Uint8 *retval;
-
-    inUse[next_buffer] = TRUE;
-    retval = (Uint8 *) (shm->wHdr[next_buffer].lpData);
-    return retval;
+    void *retval = this->hidden->shm->wHdr[this->hidden->next_buffer].lpData;
+    inUse[this->hidden->next_buffer] = TRUE;
+    return (Uint8 *) retval;
 }
 
 static void
-MME_PlayAudio(_THIS)
+MME_PlayDevice(_THIS)
 {
     /* Queue it up */
-    waveOutWrite(shm->sound, &(shm->wHdr[next_buffer]), sizeof(WAVEHDR));
-    next_buffer = (next_buffer + 1) % NUM_BUFFERS;
+    waveOutWrite(this->hidden->shm->sound,
+                 &(this->hidden->shm->wHdr[this->hidden->next_buffer]),
+                 sizeof (WAVEHDR));
+    this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
 }
 
 static void
@@ -236,13 +193,13 @@
     MMRESULT result;
     int i;
 
-    if (shm->sound) {
+    if (this->hidden->shm->sound) {
         for (i = 0; i < NUM_BUFFERS; i++)
             while (inUse[i]) {
                 mmeWaitForCallbacks();
                 mmeProcessCallbacks();
             }
-        result = waveOutReset(shm->sound);
+        result = waveOutReset(this->hidden->shm->sound);
         if (result != MMSYSERR_NOERROR)
             SetMMerror("waveOutReset()", result);
         mmeProcessCallbacks();
@@ -250,29 +207,54 @@
 }
 
 static void
-MME_CloseAudio(_THIS)
+MME_CloseDevice(_THIS)
 {
-    MMRESULT result;
+    if (this->hidden != NULL) {
+        MMRESULT result;
 
-    if (mixbuf) {
-        result = mmeFreeBuffer(mixbuf);
-        if (result != MMSYSERR_NOERROR)
-            SetMMerror("mmeFreeBuffer", result);
-        mixbuf = NULL;
-    }
+        if (this->hidden->mixbuf) {
+            result = mmeFreeBuffer(this->hidden->mixbuf);
+            if (result != MMSYSERR_NOERROR)
+                SetMMerror("mmeFreeBuffer", result);
+            this->hidden->mixbuf = NULL;
+        }
 
-    if (shm) {
-        if (shm->sound) {
-            result = waveOutClose(shm->sound);
+        if (this->hidden->shm) {
+            if (this->hidden->shm->sound) {
+                result = waveOutClose(this->hidden->shm->sound);
+                if (result != MMSYSERR_NOERROR)
+                    SetMMerror("waveOutClose()", result);
+                mmeProcessCallbacks();
+            }
+            result = mmeFreeMem(this->hidden->shm);
             if (result != MMSYSERR_NOERROR)
-                SetMMerror("waveOutClose()", result);
-            mmeProcessCallbacks();
+                SetMMerror("mmeFreeMem()", result);
+            this->hidden->shm = NULL;
         }
-        result = mmeFreeMem(shm);
-        if (result != MMSYSERR_NOERROR)
-            SetMMerror("mmeFreeMem()", result);
-        shm = NULL;
+
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
 }
 
+static int
+MME_Init(SDL_AudioDriverImpl *impl)
+{
+    /* Set the function pointers */
+    impl->OpenDevice = MME_OpenDevice;
+    impl->WaitDevice = MME_WaitDevice;
+    impl->WaitDone = MME_WaitDone;
+    impl->PlayDevice = MME_PlayDevice;
+    impl->GetDeviceBuf = MME_GetDeviceBuf;
+    impl->CloseDevice = MME_CloseDevice;
+    impl->OnlyHasDefaultOutputDevice = 1;
+
+    return 1;
+}
+
+/* !!! FIXME: Windows "windib" driver is called waveout, too */
+AudioBootStrap MMEAUDIO_bootstrap = {
+    "waveout", "Tru64 MME WaveOut", MME_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/mme/SDL_mmeaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/mme/SDL_mmeaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -23,12 +23,12 @@
 
 /* Allow access to a raw mixing buffer */
 
-#ifndef _SDL_lowaudio_h
-#define _SDL_lowaudio_h
+#ifndef _SDL_mmeaudio_h
+#define _SDL_mmeaudio_h
 
 #include "../SDL_sysaudio.h"
 
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *this
 #define NUM_BUFFERS 2
 
@@ -46,9 +46,6 @@
     int next_buffer;
 };
 
-#define shm			(this->hidden->shm)
-#define mixbuf			(this->hidden->mixbuf)
-#define next_buffer		(this->hidden->next_buffer)
-/* Old variable names */
-#endif /* _SDL_lowaudio_h */
+#endif /* _SDL_mmeaudio_h */
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/nas/SDL_nasaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/nas/SDL_nasaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -32,106 +32,149 @@
 
 #include "SDL_timer.h"
 #include "SDL_audio.h"
+#include "SDL_loadso.h"
 #include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
-#include "../SDL_audiodev_c.h"
 #include "SDL_nasaudio.h"
 
-/* The tag name used by artsc audio */
+/* The tag name used by nas audio */
 #define NAS_DRIVER_NAME         "nas"
 
 static struct SDL_PrivateAudioData *this2 = NULL;
 
-/* Audio driver functions */
-static int NAS_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void NAS_WaitAudio(_THIS);
-static void NAS_PlayAudio(_THIS);
-static Uint8 *NAS_GetAudioBuf(_THIS);
-static void NAS_CloseAudio(_THIS);
 
-/* Audio driver bootstrap functions */
+static void (*NAS_AuCloseServer)(AuServer *);
+static void (*NAS_AuNextEvent)(AuServer *, AuBool, AuEvent *);
+static AuBool (*NAS_AuDispatchEvent)(AuServer *, AuEvent *);
+static AuFlowID (*NAS_AuCreateFlow)(AuServer *, AuStatus *);
+static void (*NAS_AuStartFlow)(AuServer *, AuFlowID, AuStatus *);
+static void (*NAS_AuSetElements)
+    (AuServer *, AuFlowID, AuBool, int, AuElement *, AuStatus *);
+static void (*NAS_AuWriteElement)
+    (AuServer *, AuFlowID, int, AuUint32, AuPointer, AuBool, AuStatus *);
+static AuServer *(*NAS_AuOpenServer)
+    (_AuConst char *, int, _AuConst char *, int, _AuConst char *, char **);
+static AuEventHandlerRec *(*NAS_AuRegisterEventHandler)
+    (AuServer *, AuMask, int, AuID, AuEventHandlerCallback, AuPointer);
+
+
+#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
+
+static const char *nas_library = SDL_AUDIO_DRIVER_NAS_DYNAMIC;
+static void *nas_handle = NULL;
 
 static int
-Audio_Available(void)
+load_nas_sym(const char *fn, void **addr)
 {
-    AuServer *aud = AuOpenServer("", 0, NULL, 0, NULL, NULL);
-    if (!aud)
+    *addr = SDL_LoadFunction(nas_handle, fn);
+    if (*addr == NULL) {
         return 0;
-
-    AuCloseServer(aud);
+    }
     return 1;
 }
 
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
+/* cast funcs to char* first, to please GCC's strict aliasing rules. */
+#define SDL_NAS_SYM(x) \
+    if (!load_nas_sym(#x, (void **) (char *) &NAS_##x)) return -1
+#else
+#define SDL_NAS_SYM(x) NAS_##x = x
+#endif
+
+static int load_nas_syms(void)
 {
-    SDL_free(device->hidden);
-    SDL_free(device);
+    SDL_NAS_SYM(AuCloseServer);
+    SDL_NAS_SYM(AuNextEvent);
+    SDL_NAS_SYM(AuDispatchEvent);
+    SDL_NAS_SYM(AuCreateFlow);
+    SDL_NAS_SYM(AuStartFlow);
+    SDL_NAS_SYM(AuSetElements);
+    SDL_NAS_SYM(AuWriteElement);
+    SDL_NAS_SYM(AuOpenServer);
+    SDL_NAS_SYM(AuRegisterEventHandler);
+    return 0;
+}
+#undef SDL_NAS_SYM
+
+#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
+
+static void
+UnloadNASLibrary(void)
+{
+    if (nas_handle != NULL) {
+        SDL_UnloadObject(nas_handle);
+        nas_handle = NULL;
+    }
 }
 
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
+static int
+LoadNASLibrary(void)
 {
-    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));
+    int retval = 0;
+    if (nas_handle == NULL) {
+        nas_handle = SDL_LoadObject(nas_library);
+        if (nas_handle == NULL) {
+            /* Copy error string so we can use it in a new SDL_SetError(). */
+            char *origerr = SDL_GetError();
+            size_t len = SDL_strlen(origerr) + 1;
+            char *err = (char *) alloca(len);
+            SDL_strlcpy(err, origerr, len);
+            retval = -1;
+            SDL_SetError("NAS: SDL_LoadObject('%s') failed: %s\n",
+                          nas_library, err);
+        } else {
+            retval = load_nas_syms();
+            if (retval < 0) {
+                UnloadNASLibrary();
+            }
+        }
     }
-    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 = NAS_OpenAudio;
-    this->WaitAudio = NAS_WaitAudio;
-    this->PlayAudio = NAS_PlayAudio;
-    this->GetAudioBuf = NAS_GetAudioBuf;
-    this->CloseAudio = NAS_CloseAudio;
-
-    this->free = Audio_DeleteDevice;
-
-    return this;
+    return retval;
 }
 
-AudioBootStrap NAS_bootstrap = {
-    NAS_DRIVER_NAME, "Network Audio System",
-    Audio_Available, Audio_CreateDevice
-};
+#else
+
+static void
+UnloadNASLibrary(void)
+{
+}
+
+static int
+LoadNASLibrary(void)
+{
+    load_nas_syms();
+    return 0;
+}
+
+#endif /* SDL_AUDIO_DRIVER_NAS_DYNAMIC */
 
 /* This function waits until it is possible to write a full sound buffer */
 static void
-NAS_WaitAudio(_THIS)
+NAS_WaitDevice(_THIS)
 {
     while (this->hidden->buf_free < this->hidden->mixlen) {
         AuEvent ev;
-        AuNextEvent(this->hidden->aud, AuTrue, &ev);
-        AuDispatchEvent(this->hidden->aud, &ev);
+        NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
+        NAS_AuDispatchEvent(this->hidden->aud, &ev);
     }
 }
 
 static void
-NAS_PlayAudio(_THIS)
+NAS_PlayDevice(_THIS)
 {
-    while (this->hidden->mixlen > this->hidden->buf_free) {     /* We think the buffer is full? Yikes! Ask the server for events,
-                                                                   in the hope that some of them is LowWater events telling us more
-                                                                   of the buffer is free now than what we think. */
+    while (this->hidden->mixlen > this->hidden->buf_free) {
+        /*
+         * We think the buffer is full? Yikes! Ask the server for events,
+         *  in the hope that some of them is LowWater events telling us more
+         *  of the buffer is free now than what we think.
+         */
         AuEvent ev;
-        AuNextEvent(this->hidden->aud, AuTrue, &ev);
-        AuDispatchEvent(this->hidden->aud, &ev);
+        NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
+        NAS_AuDispatchEvent(this->hidden->aud, &ev);
     }
     this->hidden->buf_free -= this->hidden->mixlen;
 
     /* Write the audio data */
-    AuWriteElement(this->hidden->aud, this->hidden->flow, 0,
+    NAS_AuWriteElement(this->hidden->aud, this->hidden->flow, 0,
                    this->hidden->mixlen, this->hidden->mixbuf, AuFalse, NULL);
 
     this->hidden->written += this->hidden->mixlen;
@@ -142,21 +185,25 @@
 }
 
 static Uint8 *
-NAS_GetAudioBuf(_THIS)
+NAS_GetDeviceBuf(_THIS)
 {
     return (this->hidden->mixbuf);
 }
 
 static void
-NAS_CloseAudio(_THIS)
+NAS_CloseDevice(_THIS)
 {
-    if (this->hidden->mixbuf != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-    }
-    if (this->hidden->aud) {
-        AuCloseServer(this->hidden->aud);
-        this->hidden->aud = 0;
+    if (this->hidden != NULL) {
+        if (this->hidden->mixbuf != NULL) {
+            SDL_FreeAudioMem(this->hidden->mixbuf);
+            this->hidden->mixbuf = NULL;
+        }
+        if (this->hidden->aud) {
+            NAS_AuCloseServer(this->hidden->aud);
+            this->hidden->aud = 0;
+        }
+        SDL_free(this->hidden);
+        this2 = this->hidden = NULL;
     }
 }
 
@@ -221,6 +268,7 @@
 static AuDeviceID
 find_device(_THIS, int nch)
 {
+    /* These "Au" things are all macros, not functions... */
     int i;
     for (i = 0; i < AuServerNumDevices(this->hidden->aud); i++) {
         if ((AuDeviceKind(AuServerDevice(this->hidden->aud, i)) ==
@@ -233,46 +281,53 @@
 }
 
 static int
-NAS_OpenAudio(_THIS, SDL_AudioSpec * spec)
+NAS_OpenDevice(_THIS, const char *devname, int iscapture)
 {
     AuElement elms[3];
     int buffer_size;
     SDL_AudioFormat test_format, format;
 
-    this->hidden->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;
-    for (test_format = SDL_FirstAudioFormat(spec->format);
+    for (test_format = SDL_FirstAudioFormat(this->spec.format);
          !format && test_format;) {
         format = sdlformat_to_auformat(test_format);
-
         if (format == AuNone) {
             test_format = SDL_NextAudioFormat();
         }
     }
     if (format == 0) {
-        SDL_SetError("Couldn't find any hardware audio formats");
-        return (-1);
+        NAS_CloseDevice(this);
+        SDL_SetError("NAS: Couldn't find any hardware audio formats");
+        return 0;
     }
-    spec->format = test_format;
+    this->spec.format = test_format;
 
-    this->hidden->aud = AuOpenServer("", 0, NULL, 0, NULL, NULL);
+    this->hidden->aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
     if (this->hidden->aud == 0) {
-        SDL_SetError("Couldn't open connection to NAS server");
-        return (-1);
+        NAS_CloseDevice(this);
+        SDL_SetError("NAS: Couldn't open connection to NAS server");
+        return 0;
     }
 
-    this->hidden->dev = find_device(this, spec->channels);
+    this->hidden->dev = find_device(this, this->spec.channels);
     if ((this->hidden->dev == AuNone)
-        || (!(this->hidden->flow = AuCreateFlow(this->hidden->aud, NULL)))) {
-        AuCloseServer(this->hidden->aud);
-        this->hidden->aud = 0;
-        SDL_SetError("Couldn't find a fitting playback device on NAS server");
-        return (-1);
+        || (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, 0)))) {
+        NAS_CloseDevice(this);
+        SDL_SetError("NAS: Couldn't find a fitting device on NAS server");
+        return 0;
     }
 
-    buffer_size = spec->freq;
+    buffer_size = this->spec.freq;
     if (buffer_size < 4096)
         buffer_size = 4096;
 
@@ -280,35 +335,70 @@
         buffer_size = 32768;    /* So that the buffer won't get unmanageably big. */
 
     /* Calculate the final parameters for this audio specification */
-    SDL_CalculateAudioSpec(spec);
+    SDL_CalculateAudioSpec(&this->spec);
 
     this2 = this->hidden;
 
-    AuMakeElementImportClient(elms, spec->freq, format, spec->channels,
+    AuMakeElementImportClient(elms,this->spec.freq,format,this->spec.channels,
                               AuTrue, buffer_size, buffer_size / 4, 0, NULL);
-    AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, spec->freq,
+    AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq,
                               AuUnlimitedSamples, 0, NULL);
-    AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms,
-                  NULL);
-    AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
-                           this->hidden->flow, event_handler,
-                           (AuPointer) NULL);
+    NAS_AuSetElements(this->hidden->aud, this->hidden->flow,
+                      AuTrue, 2, elms, NULL);
+    NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
+                               this->hidden->flow, event_handler,
+                               (AuPointer) NULL);
 
-    AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);
+    NAS_AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);
 
     /* Allocate mixing buffer */
-    this->hidden->mixlen = spec->size;
+    this->hidden->mixlen = this->spec.size;
     this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
-        return (-1);
+        NAS_CloseDevice(this);
+        SDL_OutOfMemory();
+        return 0;
     }
-    SDL_memset(this->hidden->mixbuf, spec->silence, spec->size);
-
-    /* Get the parent process id (we're the parent of the audio thread) */
-    this->hidden->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
+NAS_Deinitialize(void)
+{
+    UnloadNASLibrary();
 }
 
+static int
+NAS_Init(SDL_AudioDriverImpl *impl)
+{
+    if (LoadNASLibrary() < 0) {
+        return 0;
+    } else {
+        AuServer *aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
+        if (aud == NULL) {
+            SDL_SetError("NAS: AuOpenServer() failed (no audio server?)");
+            return 0;
+        }
+        NAS_AuCloseServer(aud);
+    }
+
+    /* Set the function pointers */
+    impl->OpenDevice = NAS_OpenDevice;
+    impl->PlayDevice = NAS_PlayDevice;
+    impl->WaitDevice = NAS_WaitDevice;
+    impl->GetDeviceBuf = NAS_GetDeviceBuf;
+    impl->CloseDevice = NAS_CloseDevice;
+    impl->Deinitialize = NAS_Deinitialize;
+    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: is this true? */
+
+    return 1;
+}
+
+AudioBootStrap NAS_bootstrap = {
+    NAS_DRIVER_NAME, "Network Audio System", NAS_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/nas/SDL_nasaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/nas/SDL_nasaudio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -37,7 +37,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,9 +46,6 @@
     AuFlowID flow;
     AuDeviceID dev;
 
-    /* The parent process id, to detect when application quits */
-    pid_t parent;
-
     /* Raw mixing buffer */
     Uint8 *mixbuf;
     int mixlen;
@@ -60,4 +57,5 @@
     int buf_free;
 };
 #endif /* _SDL_nasaudio_h */
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/nto/SDL_nto_audio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/nto/SDL_nto_audio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -69,13 +69,13 @@
     {"Vortex 8830", QSA_MMAP_WORKAROUND},
 };
 
-/* Audio driver functions */
-static void NTO_ThreadInit(_THIS);
-static int NTO_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void NTO_WaitAudio(_THIS);
-static void NTO_PlayAudio(_THIS);
-static Uint8 *NTO_GetAudioBuf(_THIS);
-static void NTO_CloseAudio(_THIS);
+
+static inline void
+NTO_SetError(const char *fn, int rval)
+{
+    SDL_SetError("NTO: %s failed: %s", fn, snd_strerror(rval));
+}
+
 
 /* card names check to apply the workarounds */
 static int
@@ -84,7 +84,7 @@
     char scardname[33];
     int it;
 
-    if (snd_card_get_name(cardno, scardname, 32) < 0) {
+    if (snd_card_get_name(this->hidden->cardno, scardname, 32) < 0) {
         return 0;
     }
 
@@ -102,11 +102,10 @@
 static void
 NTO_ThreadInit(_THIS)
 {
-    int status;
     struct sched_param param;
+    int status = SchedGet(0, 0, &param);
 
     /* increasing default 10 priority to 25 to avoid jerky sound */
-    status = SchedGet(0, 0, &param);
     param.sched_priority = param.sched_curpriority + 15;
     status = SchedSet(0, 0, SCHED_NOCHANGE, &param);
 }
@@ -130,111 +129,26 @@
     cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX;
 }
 
-static int
-NTO_AudioAvailable(void)
-{
-    /*  See if we can open a nonblocking channel.
-       Return value '1' means we can.
-       Return value '0' means we cannot. */
-
-    int available;
-    int rval;
-    snd_pcm_t *handle;
-
-    available = 0;
-    handle = NULL;
-
-    rval = snd_pcm_open_preferred(&handle, NULL, NULL, OPEN_FLAGS);
-
-    if (rval >= 0) {
-        available = 1;
-
-        if ((rval = snd_pcm_close(handle)) < 0) {
-            SDL_SetError
-                ("NTO_AudioAvailable(): snd_pcm_close failed: %s\n",
-                 snd_strerror(rval));
-            available = 0;
-        }
-    } else {
-        SDL_SetError
-            ("NTO_AudioAvailable(): there are no available audio devices.\n");
-    }
-
-    return (available);
-}
-
-static void
-NTO_DeleteAudioDevice(SDL_AudioDevice * device)
-{
-    if ((device) && (device->hidden)) {
-        SDL_free(device->hidden);
-    }
-    if (device) {
-        SDL_free(device);
-    }
-}
-
-static SDL_AudioDevice *
-NTO_CreateAudioDevice(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(SDL_AudioDevice));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc(sizeof(struct SDL_PrivateAudioData));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this) {
-            SDL_free(this);
-        }
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData));
-    audio_handle = NULL;
-
-    /* Set the function pointers */
-    this->ThreadInit = NTO_ThreadInit;
-    this->OpenAudio = NTO_OpenAudio;
-    this->WaitAudio = NTO_WaitAudio;
-    this->PlayAudio = NTO_PlayAudio;
-    this->GetAudioBuf = NTO_GetAudioBuf;
-    this->CloseAudio = NTO_CloseAudio;
-
-    this->free = NTO_DeleteAudioDevice;
-
-    return this;
-}
-
-AudioBootStrap QNXNTOAUDIO_bootstrap = {
-    DRIVER_NAME, "QNX6 QSA-NTO Audio",
-    NTO_AudioAvailable,
-    NTO_CreateAudioDevice
-};
 
 /* This function waits until it is possible to write a full sound buffer */
 static void
-NTO_WaitAudio(_THIS)
+NTO_WaitDevice(_THIS)
 {
     fd_set wfds;
     int selectret;
 
     FD_ZERO(&wfds);
-    FD_SET(audio_fd, &wfds);
+    FD_SET(this->hidden->audio_fd, &wfds);
 
     do {
-        selectret = select(audio_fd + 1, NULL, &wfds, NULL, NULL);
+        selectret = select(this->hidden->audio_fd+1, NULL, &wfds, NULL, NULL);
         switch (selectret) {
         case -1:
         case 0:
-            SDL_SetError("NTO_WaitAudio(): select() failed: %s\n",
-                         strerror(errno));
+            SDL_SetError("NTO: select() failed: %s\n", strerror(errno));
             return;
         default:
-            if (FD_ISSET(audio_fd, &wfds)) {
+            if (FD_ISSET(this->hidden->audio_fd, &wfds)) {
                 return;
             }
             break;
@@ -244,22 +158,24 @@
 }
 
 static void
-NTO_PlayAudio(_THIS)
+NTO_PlayDevice(_THIS)
 {
+    snd_pcm_channel_status_t cstatus;
     int written, rval;
     int towrite;
     void *pcmbuffer;
 
-    if (!this->enabled) {
+    if ((!this->enabled) || (!this->hidden)) {
         return;
     }
 
     towrite = this->spec.size;
-    pcmbuffer = pcm_buf;
+    pcmbuffer = this->hidden->pcm_buf;
 
     /* Write the audio data, checking for EAGAIN (buffer full) and underrun */
     do {
-        written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite);
+        written = snd_pcm_plugin_write(this->hidden->audio_handle,
+                                       pcmbuffer, towrite);
         if (written != towrite) {
             if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
                 /* Let a little CPU time go by and try to write again */
@@ -268,33 +184,28 @@
                 towrite -= written;
                 pcmbuffer += written * this->spec.channels;
                 continue;
-            } else {
-                if ((errno == EINVAL) || (errno == EIO)) {
-                    SDL_memset(&cstatus, 0, sizeof(cstatus));
-                    cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
-                    if ((rval =
-                         snd_pcm_plugin_status(audio_handle, &cstatus)) < 0) {
-                        SDL_SetError
-                            ("NTO_PlayAudio(): snd_pcm_plugin_status failed: %s\n",
-                             snd_strerror(rval));
+            } else if ((errno == EINVAL) || (errno == EIO)) {
+                SDL_memset(&cstatus, 0, sizeof (cstatus));
+                cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
+                rval = snd_pcm_plugin_status(this->hidden->audio_handle,
+                                             &cstatus);
+                if (rval < 0) {
+                    NTO_SetError("snd_pcm_plugin_status", rval);
+                    return;
+                }
+
+                if ( (cstatus.status == SND_PCM_STATUS_UNDERRUN) ||
+                     (cstatus.status == SND_PCM_STATUS_READY)) {
+                    rval = snd_pcm_plugin_prepare(this->hidden->audio_handle,
+                                                   SND_PCM_CHANNEL_PLAYBACK);
+                    if (rval < 0) {
+                        NTO_SetError("snd_pcm_plugin_prepare", rval);
                         return;
                     }
-                    if ((cstatus.status == SND_PCM_STATUS_UNDERRUN)
-                        || (cstatus.status == SND_PCM_STATUS_READY)) {
-                        if ((rval =
-                             snd_pcm_plugin_prepare(audio_handle,
-                                                    SND_PCM_CHANNEL_PLAYBACK))
-                            < 0) {
-                            SDL_SetError
-                                ("NTO_PlayAudio(): snd_pcm_plugin_prepare failed: %s\n",
-                                 snd_strerror(rval));
-                            return;
-                        }
-                    }
-                    continue;
-                } else {
-                    return;
                 }
+                continue;
+            } else {
+                return;
             }
         } else {
             /* we wrote all remaining data */
@@ -308,77 +219,74 @@
     if (towrite != 0) {
         this->enabled = 0;
     }
-
-    return;
 }
 
 static Uint8 *
-NTO_GetAudioBuf(_THIS)
+NTO_GetDeviceBuf(_THIS)
 {
-    return pcm_buf;
+    return this->hidden->pcm_buf;
 }
 
 static void
-NTO_CloseAudio(_THIS)
+NTO_CloseDevice(_THIS)
 {
-    int rval;
-
-    this->enabled = 0;
-
-    if (audio_handle != NULL) {
-        if ((rval =
-             snd_pcm_plugin_flush(audio_handle,
-                                  SND_PCM_CHANNEL_PLAYBACK)) < 0) {
-            SDL_SetError
-                ("NTO_CloseAudio(): snd_pcm_plugin_flush failed: %s\n",
-                 snd_strerror(rval));
-            return;
+    if (this->hidden != NULL) {
+        if (this->hidden->audio_handle != NULL) {
+            snd_pcm_plugin_flush(this->hidden->audio_handle,
+                                 SND_PCM_CHANNEL_PLAYBACK);
+            snd_pcm_close(this->hidden->audio_handle);
+            this->hidden->audio_handle = NULL;
         }
-        if ((rval = snd_pcm_close(audio_handle)) < 0) {
-            SDL_SetError("NTO_CloseAudio(): snd_pcm_close failed: %s\n",
-                         snd_strerror(rval));
-            return;
+        if (this->hidden->pcm_buf != NULL) {
+            SDL_FreeAudioMem(this->hidden->pcm_buf);
+            this->hidden->pcm_buf = NULL;
         }
-        audio_handle = NULL;
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
 }
 
 static int
-NTO_OpenAudio(_THIS, SDL_AudioSpec * spec)
+NTO_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-    int rval;
-    int format;
-    SDL_AudioFormat test_format;
-    int found;
+    int rval = 0;
+    int format = 0;
+    SDL_AudioFormat test_format = 0;
+    int found = 0;
+    snd_pcm_channel_setup_t csetup;
+    snd_pcm_channel_params_t cparams;
 
-    audio_handle = NULL;
-    this->enabled = 0;
-
-    if (pcm_buf != NULL) {
-        SDL_FreeAudioMem(pcm_buf);
-        pcm_buf = 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));
 
     /* initialize channel transfer parameters to default */
     NTO_InitAudioParams(&cparams);
 
     /* Open the audio device */
-    rval =
-        snd_pcm_open_preferred(&audio_handle, &cardno, &deviceno, OPEN_FLAGS);
+    rval = snd_pcm_open_preferred(&this->hidden->audio_handle,
+                                  &this->hidden->cardno,
+                                  &this->hidden->deviceno, OPEN_FLAGS);
+
     if (rval < 0) {
-        SDL_SetError("NTO_OpenAudio(): snd_pcm_open failed: %s\n",
-                     snd_strerror(rval));
-        return (-1);
+        NTO_CloseDevice(this);
+        NTO_SetError("snd_pcm_open", rval);
+        return 0;
     }
 
     if (!NTO_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) {
         /* enable count status parameter */
-        if ((rval =
-             snd_pcm_plugin_set_disable(audio_handle,
-                                        PLUGIN_DISABLE_MMAP)) < 0) {
-            SDL_SetError("snd_pcm_plugin_set_disable failed: %s\n",
-                         snd_strerror(rval));
-            return (-1);
+        rval = snd_pcm_plugin_set_disable(this->hidden->audio_handle,
+                                          PLUGIN_DISABLE_MMAP);
+        if (rval < 0) {
+            NTO_CloseDevice(this);
+            NTO_SetError("snd_pcm_plugin_set_disable", rval);
+            return 0;
         }
     }
 
@@ -387,7 +295,7 @@
     /* can't use format as SND_PCM_SFMT_U8 = 0 in nto */
     found = 0;
 
-    for (test_format = SDL_FirstAudioFormat(spec->format); !found;) {
+    for (test_format = SDL_FirstAudioFormat(this->spec.format); !found;) {
         /* if match found set format to equivalent ALSA format */
         switch (test_format) {
         case AUDIO_U8:
@@ -441,86 +349,115 @@
 
     /* assumes test_format not 0 on success */
     if (test_format == 0) {
-        SDL_SetError
-            ("NTO_OpenAudio(): Couldn't find any hardware audio formats");
-        return (-1);
+        NTO_CloseDevice(this);
+        SDL_SetError("NTO: Couldn't find any hardware audio formats");
+        return 0;
     }
 
-    spec->format = test_format;
+    this->spec.format = test_format;
 
     /* Set the audio format */
     cparams.format.format = format;
 
     /* Set mono or stereo audio (currently only two channels supported) */
-    cparams.format.voices = spec->channels;
+    cparams.format.voices = this->spec.channels;
 
     /* Set rate */
-    cparams.format.rate = spec->freq;
+    cparams.format.rate = this->spec.freq;
 
     /* Setup the transfer parameters according to cparams */
-    rval = snd_pcm_plugin_params(audio_handle, &cparams);
+    rval = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams);
     if (rval < 0) {
-        SDL_SetError
-            ("NTO_OpenAudio(): snd_pcm_channel_params failed: %s\n",
-             snd_strerror(rval));
-        return (-1);
+        NTO_CloseDevice(this);
+        NTO_SetError("snd_pcm_channel_params", rval);
+        return 0;
     }
 
     /* Make sure channel is setup right one last time */
-    SDL_memset(&csetup, 0x00, sizeof(csetup));
+    SDL_memset(&csetup, '\0', sizeof (csetup));
     csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
-    if (snd_pcm_plugin_setup(audio_handle, &csetup) < 0) {
-        SDL_SetError("NTO_OpenAudio(): Unable to setup playback channel\n");
-        return -1;
+    if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) {
+        NTO_CloseDevice(this);
+        SDL_SetError("NTO: Unable to setup playback channel\n");
+        return 0;
     }
 
-
     /* Calculate the final parameters for this audio specification */
-    SDL_CalculateAudioSpec(spec);
+    SDL_CalculateAudioSpec(&this->spec);
 
-    pcm_len = spec->size;
+    this->hidden->pcm_len = this->spec.size;
 
-    if (pcm_len == 0) {
-        pcm_len =
-            csetup.buf.block.frag_size * spec->channels *
+    if (this->hidden->pcm_len == 0) {
+        this->hidden->pcm_len =
+            csetup.buf.block.frag_size * this->spec.channels *
             (snd_pcm_format_width(format) / 8);
     }
 
-    /* Allocate memory to the audio buffer and initialize with silence (Note that
-       buffer size must be a multiple of fragment size, so find closest multiple)
+    /*
+     * Allocate memory to the audio buffer and initialize with silence
+     *  (Note that buffer size must be a multiple of fragment size, so find
+     *  closest multiple)
      */
-    pcm_buf = (Uint8 *) SDL_AllocAudioMem(pcm_len);
-    if (pcm_buf == NULL) {
-        SDL_SetError("NTO_OpenAudio(): pcm buffer allocation failed\n");
-        return (-1);
+    this->hidden->pcm_buf = (Uint8 *) SDL_AllocAudioMem(this->hidden->pcm_len);
+    if (this->hidden->pcm_buf == NULL) {
+        NTO_CloseDevice(this);
+        SDL_OutOfMemory();
+        return 0;
     }
-    SDL_memset(pcm_buf, spec->silence, pcm_len);
+    SDL_memset(this->hidden->pcm_buf,this->spec.silence,this->hidden->pcm_len);
 
     /* get the file descriptor */
-    if ((audio_fd =
-         snd_pcm_file_descriptor(audio_handle,
-                                 SND_PCM_CHANNEL_PLAYBACK)) < 0) {
-        SDL_SetError
-            ("NTO_OpenAudio(): snd_pcm_file_descriptor failed with error code: %s\n",
-             snd_strerror(rval));
-        return (-1);
+    this->hidden->audio_fd = snd_pcm_file_descriptor(this->hidden->audio_handle,
+                                                     SND_PCM_CHANNEL_PLAYBACK);
+    if (this->hidden->audio_fd < 0) {
+        NTO_CloseDevice(this);
+        NTO_SetError("snd_pcm_file_descriptor", rval);
+        return 0;
     }
 
     /* Trigger audio playback */
-    rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK);
+    rval = snd_pcm_plugin_prepare(this->hidden->audio_handle,
+                                  SND_PCM_CHANNEL_PLAYBACK);
     if (rval < 0) {
-        SDL_SetError("snd_pcm_plugin_prepare failed: %s\n",
-                     snd_strerror(rval));
-        return (-1);
+        NTO_CloseDevice(this);
+        NTO_SetError("snd_pcm_plugin_prepare", rval);
+        return 0;
     }
 
-    this->enabled = 1;
-
-    /* Get the parent process id (we're the parent of the audio thread) */
-    parent = getpid();
-
     /* We're really ready to rock and roll. :-) */
-    return (0);
+    return 1;
 }
 
+
+static int
+NTO_Init(SDL_AudioDriverImpl *impl)
+{
+    /*  See if we can open a nonblocking channel. */
+    snd_pcm_t *handle = NULL;
+    int rval = snd_pcm_open_preferred(&handle, NULL, NULL, OPEN_FLAGS);
+    if (rval < 0) {
+        SDL_SetError("NTO: couldn't open preferred audio device");
+        return 0;
+    }
+    if ((rval = snd_pcm_close(handle)) < 0) {
+        SDL_SetError("NTO: couldn't close test audio device");
+        return 0;
+    }
+
+    /* Set the function pointers */
+    impl->OpenDevice = NTO_OpenDevice;
+    impl->ThreadInit = NTO_ThreadInit;
+    impl->WaitDevice = NTO_WaitDevice;
+    impl->PlayDevice = NTO_PlayDevice;
+    impl->GetDeviceBuf = NTO_GetDeviceBuf;
+    impl->CloseDevice = NTO_CloseDevice;
+    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: add device enum! */
+
+    return 1;
+}
+
+AudioBootStrap QNXNTOAUDIO_bootstrap = {
+    DRIVER_NAME, "QNX6 QSA-NTO Audio", NTO_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/nto/SDL_nto_audio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/nto/SDL_nto_audio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -47,23 +47,7 @@
     /* Raw mixing buffer */
     Uint8 *pcm_buf;
     Uint32 pcm_len;
-
-    /* QSA parameters */
-    snd_pcm_channel_status_t cstatus;
-    snd_pcm_channel_params_t cparams;
-    snd_pcm_channel_setup_t csetup;
 };
 
-#define cardno          (this->hidden->cardno)
-#define deviceno        (this->hidden->deviceno)
-#define audio_handle    (this->hidden->audio_handle)
-#define audio_fd        (this->hidden->audio_fd)
-#define parent          (this->hidden->parent)
-#define pcm_buf         (this->hidden->pcm_buf)
-#define pcm_len         (this->hidden->pcm_len)
-#define cstatus         (this->hidden->cstatus)
-#define cparams         (this->hidden->cparams)
-#define csetup          (this->hidden->csetup)
-
 #endif /* __SDL_NTO_AUDIO_H__ */
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/paudio/SDL_paudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/paudio/SDL_paudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -30,16 +30,17 @@
 #include <fcntl.h>
 #include <sys/time.h>
 #include <sys/ioctl.h>
+#include <sys/types.h>
 #include <sys/stat.h>
 
 #include "SDL_timer.h"
 #include "SDL_audio.h"
+#include "SDL_stdinc.h"
 #include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
-#include "../SDL_audiodev_c.h"
 #include "SDL_paudio.h"
 
-#define DEBUG_AUDIO 1
+#define DEBUG_AUDIO 0
 
 /* A conflict within AIX 4.3.3 <sys/> headers and probably others as well.
  * I guess nobody ever uses audio... Shame over AIX header files.  */
@@ -48,94 +49,95 @@
 #include <sys/audio.h>
 
 /* The tag name used by paud audio */
-#define Paud_DRIVER_NAME         "paud"
+#define PAUDIO_DRIVER_NAME         "paud"
 
 /* Open the audio device for playback, and don't block if busy */
 /* #define OPEN_FLAGS	(O_WRONLY|O_NONBLOCK) */
 #define OPEN_FLAGS	O_WRONLY
 
-/* Audio driver functions */
-static int Paud_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void Paud_WaitAudio(_THIS);
-static void Paud_PlayAudio(_THIS);
-static Uint8 *Paud_GetAudioBuf(_THIS);
-static void Paud_CloseAudio(_THIS);
+/* Get the name of the audio device we use for output */
+
+#ifndef _PATH_DEV_DSP
+#define _PATH_DEV_DSP	"/dev/%caud%c/%c"
+#endif
 
-/* Audio driver bootstrap functions */
+static 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
-Audio_Available(void)
+OpenUserDefinedDevice(char *path, int maxlen, int flags)
 {
+    const char *audiodev;
     int fd;
-    int available;
 
-    available = 0;
-    fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
-    if (fd >= 0) {
-        available = 1;
-        close(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;
     }
-    return (available);
-}
-
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
+    fd = open(audiodev, flags, 0);
+    if (path != NULL) {
+        SDL_strlcpy(path, audiodev, maxlen);
+        path[maxlen - 1] = '\0';
+    }
+    return fd;
 }
 
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
+static int
+OpenAudioPath(char *path, int maxlen, int flags, int classic)
 {
-    SDL_AudioDevice *this;
+    struct stat sb;
+    int cycle = 0;
+    int fd = OpenUserDefinedDevice(path, maxlen, flags);
 
-    /* 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);
+    if (fd != -1) {
+        return fd;
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-    audio_fd = -1;
 
-    /* Set the function pointers */
-    this->OpenAudio = Paud_OpenAudio;
-    this->WaitAudio = Paud_WaitAudio;
-    this->PlayAudio = Paud_PlayAudio;
-    this->GetAudioBuf = Paud_GetAudioBuf;
-    this->CloseAudio = Paud_CloseAudio;
+    /* !!! FIXME: do we really need a table here? */
+    while (devsettings[cycle][0] != '\0') {
+        char audiopath[1024];
+        SDL_snprintf(audiopath, SDL_arraysize(audiopath),
+                     _PATH_DEV_DSP,
+                     devsettings[cycle][0],
+                     devsettings[cycle][1], devsettings[cycle][2]);
 
-    this->free = Audio_DeleteDevice;
-
-    return this;
+        if (stat(audiopath, &sb) == 0) {
+            fd = open(audiopath, flags, 0);
+            if (fd > 0) {
+                if (path != NULL) {
+                    SDL_strlcpy(path, audiopath, maxlen);
+                }
+                return fd;
+            }
+        }
+    }
+    return -1;
 }
 
-AudioBootStrap Paud_bootstrap = {
-    Paud_DRIVER_NAME, "AIX Paudio",
-    Audio_Available, Audio_CreateDevice
-};
-
 /* This function waits until it is possible to write a full sound buffer */
 static void
-Paud_WaitAudio(_THIS)
+PAUDIO_WaitDevice(_THIS)
 {
     fd_set fdset;
 
     /* See if we need to use timed audio synchronization */
-    if (frame_ticks) {
+    if (this->hidden->frame_ticks) {
         /* Use timer for general audio synchronization */
         Sint32 ticks;
 
-        ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS;
+        ticks = ((Sint32)(this->hidden->next_frame-SDL_GetTicks()))-FUDGE_TICKS;
         if (ticks > 0) {
             SDL_Delay(ticks);
         }
@@ -145,9 +147,9 @@
         /* Use select() for audio synchronization */
         struct timeval timeout;
         FD_ZERO(&fdset);
-        FD_SET(audio_fd, &fdset);
+        FD_SET(this->hidden->audio_fd, &fdset);
 
-        if (ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
+        if (ioctl(this->hidden->audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
 #ifdef DEBUG_AUDIO
             fprintf(stderr, "Couldn't get audio buffer information\n");
 #endif
@@ -168,7 +170,7 @@
 #ifdef DEBUG_AUDIO
         fprintf(stderr, "Waiting for audio to get ready\n");
 #endif
-        if (select(audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) {
+        if (select(this->hidden->audio_fd+1,NULL,&fdset,NULL,&timeout) <= 0) {
             const char *message =
                 "Audio timeout - buggy audio driver? (disabled)";
             /*
@@ -179,7 +181,7 @@
             fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message);
             this->enabled = 0;
             /* Don't try to close - may hang */
-            audio_fd = -1;
+            this->hidden->audio_fd = -1;
 #ifdef DEBUG_AUDIO
             fprintf(stderr, "Done disabling audio\n");
 #endif
@@ -191,13 +193,15 @@
 }
 
 static void
-Paud_PlayAudio(_THIS)
+PAUDIO_PlayDevice(_THIS)
 {
-    int written;
+    int written = 0;
+    const Uint8 *mixbuf = this->hidden->mixbuf;
+    const size_t mixlen = this->hidden->mixlen;
 
     /* Write the audio data, checking for EAGAIN on broken audio drivers */
     do {
-        written = write(audio_fd, mixbuf, mixlen);
+        written = write(this->hidden->audio_fd, mixbuf, mixlen);
         if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) {
             SDL_Delay(1);       /* Let a little CPU time go by */
         }
@@ -206,8 +210,8 @@
            ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)));
 
     /* 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 */
@@ -220,28 +224,34 @@
 }
 
 static Uint8 *
-Paud_GetAudioBuf(_THIS)
+PAUDIO_GetDeviceBuf(_THIS)
 {
-    return mixbuf;
+    return this->hidden->mixbuf;
 }
 
 static void
-Paud_CloseAudio(_THIS)
+PAUDIO_CloseDevice(_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
-Paud_OpenAudio(_THIS, SDL_AudioSpec * spec)
+PAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
 {
+    const char *workaround = SDL_getenv("SDL_DSP_NOSELECT");
     char audiodev[1024];
+    const char *err = NULL;
     int format;
     int bytes_per_sample;
     SDL_AudioFormat test_format;
@@ -250,32 +260,40 @@
     audio_status paud_status;
     audio_control paud_control;
     audio_change paud_change;
+    int fd = -1;
 
-    /* Reset the timer synchronization flag */
-    frame_ticks = 0.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) {
+    fd = OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
+    this->hidden->audio_fd = fd;
+    if (fd < 0) {
+        PAUDIO_CloseDevice(this);
         SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
-        return -1;
+        return 0;
     }
 
     /*
      * We can't set the buffer size - just ask the device for the maximum
      * that we can have.
      */
-    if (ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
+    if (ioctl(fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
+        PAUDIO_CloseDevice(this);
         SDL_SetError("Couldn't get audio buffer information");
-        return -1;
+        return 0;
     }
 
-    mixbuf = NULL;
-
-    if (spec->channels > 1)
-        spec->channels = 2;
+    if (this->spec.channels > 1)
+        this->spec.channels = 2;
     else
-        spec->channels = 1;
+        this->spec.channels = 1;
 
     /*
      * Fields in the audio_init structure:
@@ -322,14 +340,14 @@
      * paud.position_resolution; * smallest increment for position
      */
 
-    paud_init.srate = spec->freq;
+    paud_init.srate = this->spec.freq;
     paud_init.mode = PCM;
     paud_init.operation = PLAY;
-    paud_init.channels = spec->channels;
+    paud_init.channels = this->spec.channels;
 
     /* 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);
@@ -382,31 +400,32 @@
 #ifdef DEBUG_AUDIO
         fprintf(stderr, "Couldn't find any hardware audio formats\n");
 #endif
+        PAUDIO_CloseDevice(this);
         SDL_SetError("Couldn't find any hardware audio formats");
-        return -1;
+        return 0;
     }
-    spec->format = test_format;
+    this->spec.format = test_format;
 
     /*
      * We know the buffer size and the max number of subsequent writes
-     * that can be pending. If more than one can pend, allow the application
-     * to do something like double buffering between our write buffer and
-     * the device's own buffer that we are filling with write() anyway.
+     *  that can be pending. If more than one can pend, allow the application
+     *  to do something like double buffering between our write buffer and
+     *  the device's own buffer that we are filling with write() anyway.
      *
-     * We calculate spec->samples like this because SDL_CalculateAudioSpec()
-     * will give put paud_bufinfo.write_buf_cap (or paud_bufinfo.write_buf_cap/2)
-     * into spec->size in return.
+     * We calculate this->spec.samples like this because
+     *  SDL_CalculateAudioSpec() will give put paud_bufinfo.write_buf_cap
+     *  (or paud_bufinfo.write_buf_cap/2) into this->spec.size in return.
      */
     if (paud_bufinfo.request_buf_cap == 1) {
-        spec->samples = paud_bufinfo.write_buf_cap
-            / bytes_per_sample / spec->channels;
+        this->spec.samples = paud_bufinfo.write_buf_cap
+            / bytes_per_sample / this->spec.channels;
     } else {
-        spec->samples = paud_bufinfo.write_buf_cap
-            / bytes_per_sample / spec->channels / 2;
+        this->spec.samples = paud_bufinfo.write_buf_cap
+            / bytes_per_sample / this->spec.channels / 2;
     }
-    paud_init.bsize = bytes_per_sample * spec->channels;
+    paud_init.bsize = bytes_per_sample * this->spec.channels;
 
-    SDL_CalculateAudioSpec(spec);
+    SDL_CalculateAudioSpec(&this->spec);
 
     /*
      * The AIX paud device init can't modify the values of the audio_init
@@ -416,47 +435,44 @@
      * /dev/paud supports all of the encoding formats, so we don't need
      * to do anything like reopening the device, either.
      */
-    if (ioctl(audio_fd, AUDIO_INIT, &paud_init) < 0) {
+    if (ioctl(fd, AUDIO_INIT, &paud_init) < 0) {
         switch (paud_init.rc) {
         case 1:
-            SDL_SetError
-                ("Couldn't set audio format: DSP can't do play requests");
-            return -1;
+            err = "Couldn't set audio format: DSP can't do play requests";
             break;
         case 2:
-            SDL_SetError
-                ("Couldn't set audio format: DSP can't do record requests");
-            return -1;
+            err = "Couldn't set audio format: DSP can't do record requests";
             break;
         case 4:
-            SDL_SetError("Couldn't set audio format: request was invalid");
-            return -1;
+            err = "Couldn't set audio format: request was invalid";
             break;
         case 5:
-            SDL_SetError
-                ("Couldn't set audio format: conflict with open's flags");
-            return -1;
+            err = "Couldn't set audio format: conflict with open's flags";
             break;
         case 6:
-            SDL_SetError
-                ("Couldn't set audio format: out of DSP MIPS or memory");
-            return -1;
+            err = "Couldn't set audio format: out of DSP MIPS or memory";
             break;
         default:
-            SDL_SetError
-                ("Couldn't set audio format: not documented in sys/audio.h");
-            return -1;
+            err = "Couldn't set audio format: not documented in sys/audio.h";
             break;
         }
     }
 
+    if (err != NULL) {
+        PAUDIO_CloseDevice(this);
+        SDL_SetError("Paudio: %s", err);
+        return 0;
+    }
+
     /* 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) {
+        PAUDIO_CloseDevice(this);
+        SDL_OutOfMemory();
+        return 0;
     }
-    SDL_memset(mixbuf, spec->silence, spec->size);
+    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
 
     /*
      * Set some paramters: full volume, first speaker that we can find.
@@ -475,7 +491,7 @@
 
     paud_control.ioctl_request = AUDIO_CHANGE;
     paud_control.request_info = (char *) &paud_change;
-    if (ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0) {
+    if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) {
 #ifdef DEBUG_AUDIO
         fprintf(stderr, "Can't change audio display settings\n");
 #endif
@@ -487,29 +503,49 @@
      */
     paud_control.ioctl_request = AUDIO_START;
     paud_control.position = 0;
-    if (ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0) {
+    if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) {
+        PAUDIO_CloseDevice(this);
 #ifdef DEBUG_AUDIO
         fprintf(stderr, "Can't start audio play\n");
 #endif
         SDL_SetError("Can't start audio play");
-        return -1;
+        return 0;
     }
 
     /* 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;
-        }
+    if (workaround != NULL) {
+        this->hidden->frame_ticks = (float) (this->spec.samples * 1000) /
+                                                this->spec.freq;
+        this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks;
     }
 
-    /* Get the parent process id (we're the parent of the audio thread) */
-    parent = getpid();
-
     /* We're ready to rock and roll. :-) */
-    return 0;
+    return 1;
 }
 
+static int
+PAUDIO_Init(SDL_AudioDriverImpl *impl)
+{
+    int fd = OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
+    if (fd < 0) {
+        SDL_SetError("PAUDIO: Couldn't open audio device");
+        return 0;
+    }
+    close(fd);
+
+    /* Set the function pointers */
+    impl->OpenDevice = DSP_OpenDevice;
+    impl->PlayDevice = DSP_PlayDevice;
+    impl->PlayDevice = DSP_WaitDevice;
+    impl->GetDeviceBuf = DSP_GetDeviceBuf;
+    impl->CloseDevice = DSP_CloseDevice;
+    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: add device enum! */
+
+    return 1;
+}
+
+AudioBootStrap PAUDIO_bootstrap = {
+    PAUDIO_DRIVER_NAME, "AIX Paudio", PAUDIO_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/paudio/SDL_paudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/paudio/SDL_paudio.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,9 +34,6 @@
     /* 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;
@@ -47,13 +44,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_paudaudio_h */
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/sun/SDL_sunaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/sun/SDL_sunaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -1,3 +1,8 @@
+/* I'm gambling no one uses this audio backend...we'll see who emails.  :)  */
+#error this code has not been updated for SDL 1.3.
+#error if no one emails icculus at icculus.org and tells him that this
+#error  code is needed, this audio backend will eventually be removed from SDL.
+
 /*
     SDL - Simple DirectMedia Layer
     Copyright (C) 1997-2006 Sam Lantinga
@@ -116,7 +121,7 @@
 
 AudioBootStrap SUNAUDIO_bootstrap = {
     "audio", "UNIX /dev/audio interface",
-    Audio_Available, Audio_CreateDevice
+    Audio_Available, Audio_CreateDevice, 0
 };
 
 #ifdef DEBUG_AUDIO
--- a/src/audio/sun/SDL_sunaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/sun/SDL_sunaudio.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_sunaudio_h
+#define _SDL_sunaudio_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
@@ -53,5 +53,6 @@
 #define fragsize		(this->hidden->fragsize)
 #define frequency		(this->hidden->frequency)
 
-#endif /* _SDL_lowaudio_h */
+#endif /* _SDL_sunaudio_h */
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/ums/SDL_umsaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/ums/SDL_umsaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -1,3 +1,8 @@
+/* I'm gambling no one uses this audio backend...we'll see who emails.  :)  */
+#error this code has not been updated for SDL 1.3.
+#error if no one emails icculus at icculus.org and tells him that this
+#error  code is needed, this audio backend will eventually be removed from SDL.
+
 /*
     SDL - Simple DirectMedia Layer
     Copyright (C) 1997-2006 Sam Lantinga
@@ -36,7 +41,6 @@
 
 #include "SDL_audio.h"
 #include "../SDL_audio_c.h"
-#include "../SDL_audiodev_c.h"
 #include "SDL_umsaudio.h"
 
 /* The tag name used by UMS audio */
@@ -152,7 +156,7 @@
 
 AudioBootStrap UMS_bootstrap = {
     UMS_DRIVER_NAME, "AIX UMS audio",
-    Audio_Available, Audio_CreateDevice
+    Audio_Available, Audio_CreateDevice, 0
 };
 
 static Uint8 *
--- a/src/audio/ums/SDL_umsaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/ums/SDL_umsaudio.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
--- a/src/audio/windib/SDL_dibaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/windib/SDL_dibaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -35,71 +35,13 @@
 #include "win_ce_semaphore.h"
 #endif
 
-
-/* Audio driver functions */
-static int DIB_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void DIB_ThreadInit(_THIS);
-static void DIB_WaitAudio(_THIS);
-static Uint8 *DIB_GetAudioBuf(_THIS);
-static void DIB_PlayAudio(_THIS);
-static void DIB_WaitDone(_THIS);
-static void DIB_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 = DIB_OpenAudio;
-    this->ThreadInit = DIB_ThreadInit;
-    this->WaitAudio = DIB_WaitAudio;
-    this->PlayAudio = DIB_PlayAudio;
-    this->GetAudioBuf = DIB_GetAudioBuf;
-    this->WaitDone = DIB_WaitDone;
-    this->CloseAudio = DIB_CloseAudio;
-
-    this->free = Audio_DeleteDevice;
-
-    return this;
-}
-
-AudioBootStrap WAVEOUT_bootstrap = {
-    "waveout", "Win95/98/NT/2000 WaveOut",
-    Audio_Available, Audio_CreateDevice
-};
-
+#if defined(_WIN32_WCE)
+#define WINDOWS_OS_NAME "Windows CE/PocketPC"
+#elif defined(WIN64)
+#define WINDOWS_OS_NAME "Win64"
+#else
+#define WINDOWS_OS_NAME "Win32"
+#endif
 
 /* The Win32 callback for filling the WAVE device */
 static void CALLBACK
@@ -114,9 +56,9 @@
 
     /* Signal that we are done playing a buffer */
 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
-    ReleaseSemaphoreCE(audio_sem, 1, NULL);
+    ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL);
 #else
-    ReleaseSemaphore(audio_sem, 1, NULL);
+    ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
 #endif
 }
 
@@ -146,48 +88,47 @@
 
 /* Set high priority for the audio thread */
 static void
-DIB_ThreadInit(_THIS)
+WINWAVEOUT_ThreadInit(_THIS)
 {
     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
 }
 
 void
-DIB_WaitAudio(_THIS)
+WINWAVEOUT_WaitDevice(_THIS)
 {
     /* Wait for an audio chunk to finish */
 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
-    WaitForSemaphoreCE(audio_sem, INFINITE);
+    WaitForSemaphoreCE(this->hidden->audio_sem, INFINITE);
 #else
-    WaitForSingleObject(audio_sem, INFINITE);
+    WaitForSingleObject(this->hidden->audio_sem, INFINITE);
 #endif
 }
 
 Uint8 *
-DIB_GetAudioBuf(_THIS)
+WINWAVEOUT_GetDeviceBuf(_THIS)
 {
-    Uint8 *retval;
-
-    retval = (Uint8 *) (wavebuf[next_buffer].lpData);
-    return retval;
+    return (Uint8 *) (this->hidden->wavebuf[this->hidden->next_buffer].lpData);
 }
 
 void
-DIB_PlayAudio(_THIS)
+WINWAVEOUT_PlayDevice(_THIS)
 {
     /* Queue it up */
-    waveOutWrite(sound, &wavebuf[next_buffer], sizeof(wavebuf[0]));
-    next_buffer = (next_buffer + 1) % NUM_BUFFERS;
+    waveOutWrite(this->hidden->sound,
+                 &this->hidden->wavebuf[this->hidden->next_buffer],
+                 sizeof (this->hidden->wavebuf[0]));
+    this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
 }
 
 void
-DIB_WaitDone(_THIS)
+WINWAVEOUT_WaitDone(_THIS)
 {
     int i, left;
 
     do {
         left = NUM_BUFFERS;
         for (i = 0; i < NUM_BUFFERS; ++i) {
-            if (wavebuf[i].dwFlags & WHDR_DONE) {
+            if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
                 --left;
             }
         }
@@ -199,143 +140,197 @@
 }
 
 void
-DIB_CloseAudio(_THIS)
+WINWAVEOUT_CloseDevice(_THIS)
 {
-    int i;
-
     /* Close up audio */
-    if (audio_sem) {
+    if (this->hidden != NULL) {
+        int i;
+
+        if (this->hidden->audio_sem) {
 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
-        CloseSynchHandle(audio_sem);
+            CloseSynchHandle(this->hidden->audio_sem);
 #else
-        CloseHandle(audio_sem);
+            CloseHandle(this->hidden->audio_sem);
 #endif
-    }
-    if (sound) {
-        waveOutClose(sound);
-    }
+            this->hidden->audio_sem = 0;
+        }
+
+        if (this->hidden->sound) {
+            waveOutClose(this->hidden->sound);
+            this->hidden->sound = 0;
+        }
 
-    /* Clean up mixing buffers */
-    for (i = 0; i < NUM_BUFFERS; ++i) {
-        if (wavebuf[i].dwUser != 0xFFFF) {
-            waveOutUnprepareHeader(sound, &wavebuf[i], sizeof(wavebuf[i]));
-            wavebuf[i].dwUser = 0xFFFF;
+        /* Clean up mixing buffers */
+        for (i = 0; i < NUM_BUFFERS; ++i) {
+            if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
+                waveOutUnprepareHeader(this->hidden->sound,
+                                       &this->hidden->wavebuf[i],
+                                       sizeof (this->hidden->wavebuf[i]));
+                this->hidden->wavebuf[i].dwUser = 0xFFFF;
+            }
         }
-    }
-    /* Free raw mixing buffer */
-    if (mixbuf != NULL) {
-        SDL_free(mixbuf);
-        mixbuf = NULL;
+
+        if (this->hidden->mixbuf != NULL) {
+            /* Free raw mixing buffer */
+            SDL_free(this->hidden->mixbuf);
+            this->hidden->mixbuf = NULL;
+        }
+
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
 }
 
 int
-DIB_OpenAudio(_THIS, SDL_AudioSpec * spec)
+WINWAVEOUT_OpenDevice(_THIS, const char *devname, int iscapture)
 {
+    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
+    int valid_datatype = 0;
     MMRESULT result;
+    WAVEFORMATEX waveformat;
     int i;
-    WAVEFORMATEX waveformat;
+
+    /* 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));
 
     /* Initialize the wavebuf structures for closing */
-    sound = NULL;
-    audio_sem = NULL;
     for (i = 0; i < NUM_BUFFERS; ++i)
-        wavebuf[i].dwUser = 0xFFFF;
-    mixbuf = NULL;
+        this->hidden->wavebuf[i].dwUser = 0xFFFF;
+
+    while ((!valid_datatype) && (test_format)) {
+        valid_datatype = 1;
+        _this->spec.format = test_format;
+        switch (test_format) {
+            case AUDIO_U8:
+            case AUDIO_S16:
+            case AUDIO_S32:
+                break;  /* valid. */
+
+            default:
+                valid_datatype = 0;
+                test_format = SDL_NextAudioFormat();
+                break;
+        }
+    }
+
+    if (!valid_datatype) {
+        WINWAVEOUT_CloseDevice(this);
+        SDL_SetError("Unsupported audio format");
+        return 0;
+    }
 
     /* Set basic WAVE format parameters */
-    SDL_memset(&waveformat, 0, sizeof(waveformat));
+    SDL_memset(&waveformat, '\0', sizeof (waveformat));
     waveformat.wFormatTag = WAVE_FORMAT_PCM;
+    waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
 
-    /* Determine the audio parameters from the AudioSpec */
-    switch (SDL_AUDIO_BITSIZE(spec->format)) {
-    case 8:
-        /* Unsigned 8 bit audio data */
-        spec->format = AUDIO_U8;
-        waveformat.wBitsPerSample = 8;
-        break;
-    case 16:
-        /* Signed 16 bit audio data */
-        spec->format = AUDIO_S16;
-        waveformat.wBitsPerSample = 16;
-        break;
-    case 32:
-        /* Signed 32 bit audio data */
-        spec->format = AUDIO_S32;
-        waveformat.wBitsPerSample = 32;
-        break;
-    default:
-        SDL_SetError("Unsupported audio format");
-        return (-1);
-    }
-    waveformat.nChannels = spec->channels;
-    waveformat.nSamplesPerSec = spec->freq;
+    if (this->spec.channels > 2)
+        this->spec.channels = 2;  /* !!! FIXME: is this right? */
+
+    waveformat.nChannels = this->spec.channels;
+    waveformat.nSamplesPerSec = this->spec.freq;
     waveformat.nBlockAlign =
         waveformat.nChannels * (waveformat.wBitsPerSample / 8);
     waveformat.nAvgBytesPerSec =
         waveformat.nSamplesPerSec * waveformat.nBlockAlign;
 
     /* Check the buffer size -- minimum of 1/4 second (word aligned) */
-    if (spec->samples < (spec->freq / 4))
-        spec->samples = ((spec->freq / 4) + 3) & ~3;
+    if (this->spec.samples < (this->spec.freq / 4))
+        this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
 
     /* Update the fragment size as size in bytes */
-    SDL_CalculateAudioSpec(spec);
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* Open the audio device */
-    result = waveOutOpen(&sound, WAVE_MAPPER, &waveformat,
+    result = waveOutOpen(&this->hidden->sound, WAVE_MAPPER, &waveformat,
                          (DWORD_PTR) FillSound, (DWORD_PTR) this,
                          CALLBACK_FUNCTION);
     if (result != MMSYSERR_NOERROR) {
+        WINWAVEOUT_CloseDevice(this);
         SetMMerror("waveOutOpen()", result);
-        return (-1);
+        return 0;
     }
 #ifdef SOUND_DEBUG
     /* Check the sound device we retrieved */
     {
         WAVEOUTCAPS caps;
 
-        result = waveOutGetDevCaps((UINT) sound, &caps, sizeof(caps));
+        result = waveOutGetDevCaps((UINT) this->hidden->sound,
+                                   &caps, sizeof(caps));
         if (result != MMSYSERR_NOERROR) {
+            WINWAVEOUT_CloseDevice(this);
             SetMMerror("waveOutGetDevCaps()", result);
-            return (-1);
+            return 0;
         }
         printf("Audio device: %s\n", caps.szPname);
     }
 #endif
 
     /* Create the audio buffer semaphore */
+    this->hidden->audio_sem = 
 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
-    audio_sem = CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
+            CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
 #else
-    audio_sem = CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
+            CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
 #endif
-    if (audio_sem == NULL) {
+    if (this->hidden->audio_sem == NULL) {
+        WINWAVEOUT_CloseDevice(this);
         SDL_SetError("Couldn't create semaphore");
-        return (-1);
+        return 0;
     }
 
     /* Create the sound buffers */
-    mixbuf = (Uint8 *) SDL_malloc(NUM_BUFFERS * spec->size);
+    this->hidden->mixbuf = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
     if (mixbuf == NULL) {
-        SDL_SetError("Out of memory");
-        return (-1);
+        WINWAVEOUT_CloseDevice(this);
+        SDL_OutOfMemory();
+        return 0;
     }
     for (i = 0; i < NUM_BUFFERS; ++i) {
-        SDL_memset(&wavebuf[i], 0, sizeof(wavebuf[i]));
-        wavebuf[i].lpData = (LPSTR) & mixbuf[i * spec->size];
-        wavebuf[i].dwBufferLength = spec->size;
-        wavebuf[i].dwFlags = WHDR_DONE;
-        result = waveOutPrepareHeader(sound, &wavebuf[i], sizeof(wavebuf[i]));
+        SDL_memset(&this->hidden->wavebuf[i], '\0',
+                    sizeof (this->hidden->wavebuf[i]));
+        this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
+        this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
+        this->hidden->wavebuf[i].lpData =
+                            (LPSTR) &this->hidden->mixbuf[i * this->spec.size];
+        result = waveOutPrepareHeader(this->hidden->sound,
+                                      &this->hidden->wavebuf[i],
+                                      sizeof (this->hidden->wavebuf[i]));
         if (result != MMSYSERR_NOERROR) {
+            WINWAVEOUT_CloseDevice(this);
             SetMMerror("waveOutPrepareHeader()", result);
-            return (-1);
+            return 0;
         }
     }
 
-    /* Ready to go! */
-    next_buffer = 0;
-    return (0);
+    return 1;   /* Ready to go! */
 }
 
+
+static int
+WINWAVEOUT_Init(SDL_AudioDriverImpl *impl)
+{
+    /* Set the function pointers */
+    impl->OpenDevice = WINWAVEOUT_OpenDevice;
+    impl->ThreadInit = WINWAVEOUT_ThreadInit;
+    impl->PlayDevice = WINWAVEOUT_PlayDevice;
+    impl->WaitDevice = WINWAVEOUT_WaitDevice;
+    impl->WaitDone = WINWAVEOUT_WaitDone;
+    impl->GetDeviceBuf = WINWAVEOUT_GetDeviceBuf;
+    impl->CloseDevice = WINWAVEOUT_CloseDevice;
+    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: Is this true? */
+
+    return 1;
+}
+
+AudioBootStrap WINWAVEOUT_bootstrap = {
+    "waveout", WINDOWS_OS_NAME " WaveOut", WINWAVEOUT_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/windib/SDL_dibaudio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/windib/SDL_dibaudio.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_dibaudio_h
+#define _SDL_dibaudio_h
 
 #include "../SDL_sysaudio.h"
 
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *this
 
 #define NUM_BUFFERS 2           /* -- Don't lower this! */
@@ -40,12 +40,6 @@
     int next_buffer;
 };
 
-/* Old variable names */
-#define sound			(this->hidden->sound)
-#define audio_sem 		(this->hidden->audio_sem)
-#define mixbuf			(this->hidden->mixbuf)
-#define wavebuf			(this->hidden->wavebuf)
-#define next_buffer		(this->hidden->next_buffer)
+#endif /* _SDL_dibaudio_h */
 
-#endif /* _SDL_lowaudio_h */
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/windx5/SDL_dx5audio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/windx5/SDL_dx5audio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -28,160 +28,65 @@
 #include "../SDL_audio_c.h"
 #include "SDL_dx5audio.h"
 
-/* Define this if you want to use DirectX 6 DirectSoundNotify interface */
-//#define USE_POSITION_NOTIFY
+/* !!! FIXME: move this somewhere that other drivers can use it... */
+#if defined(_WIN32_WCE)
+#define WINDOWS_OS_NAME "Windows CE/PocketPC"
+#elif defined(WIN64)
+#define WINDOWS_OS_NAME "Win64"
+#else
+#define WINDOWS_OS_NAME "Win32"
+#endif
 
 /* DirectX function pointers for audio */
-HRESULT(WINAPI * DSoundCreate) (LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
-
-/* Audio driver functions */
-static int DX5_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void DX5_ThreadInit(_THIS);
-static void DX5_WaitAudio_BusyWait(_THIS);
-#ifdef USE_POSITION_NOTIFY
-static void DX6_WaitAudio_EventWait(_THIS);
-#endif
-static void DX5_PlayAudio(_THIS);
-static Uint8 *DX5_GetAudioBuf(_THIS);
-static void DX5_WaitDone(_THIS);
-static void DX5_CloseAudio(_THIS);
-
-/* Audio driver bootstrap functions */
-
-static int
-Audio_Available(void)
-{
-    HINSTANCE DSoundDLL;
-    int dsound_ok;
-
-    /* Version check DSOUND.DLL (Is DirectX okay?) */
-    dsound_ok = 0;
-    DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL"));
-    if (DSoundDLL != NULL) {
-        /* We just use basic DirectSound, we're okay */
-        /* Yay! */
-        /* Unfortunately, the sound drivers on NT have
-           higher latencies than the audio buffers used
-           by many SDL applications, so there are gaps
-           in the audio - it sounds terrible.  Punt for now.
-         */
-        OSVERSIONINFO ver;
-        ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-        GetVersionEx(&ver);
-        switch (ver.dwPlatformId) {
-        case VER_PLATFORM_WIN32_NT:
-            if (ver.dwMajorVersion > 4) {
-                /* Win2K */
-                dsound_ok = 1;
-            } else {
-                /* WinNT */
-                dsound_ok = 0;
-            }
-            break;
-        default:
-            /* Win95 or Win98 */
-            dsound_ok = 1;
-            break;
-        }
-        /* Now check for DirectX 5 or better - otherwise
-         * we will fail later in DX5_OpenAudio without a chance
-         * to fall back to the DIB driver. */
-        if (dsound_ok) {
-            /* DirectSoundCaptureCreate was added in DX5 */
-            if (!GetProcAddress(DSoundDLL, TEXT("DirectSoundCaptureCreate")))
-                dsound_ok = 0;
-
-        }
-        /* Clean up.. */
-        FreeLibrary(DSoundDLL);
-    }
-    return (dsound_ok);
-}
-
-/* Functions for loading the DirectX functions dynamically */
 static HINSTANCE DSoundDLL = NULL;
+static HRESULT (WINAPI *DSoundCreate)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN) = NULL;
 
 static void
-DX5_Unload(void)
+DSOUND_Unload(void)
 {
     if (DSoundDLL != NULL) {
         FreeLibrary(DSoundDLL);
-        DSoundCreate = NULL;
-        DSoundDLL = NULL;
     }
-}
-static int
-DX5_Load(void)
-{
-    int status;
 
-    DX5_Unload();
-    DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL"));
-    if (DSoundDLL != NULL) {
-        DSoundCreate = (void *) GetProcAddress(DSoundDLL,
-                                               TEXT("DirectSoundCreate"));
-    }
-    if (DSoundDLL && DSoundCreate) {
-        status = 0;
-    } else {
-        DX5_Unload();
-        status = -1;
-    }
-    return status;
-}
-
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
-    DX5_Unload();
-    SDL_free(device->hidden);
-    SDL_free(device);
+    DSoundCreate = NULL;
+    DSoundDLL = NULL;
 }
 
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
+
+static int
+DSOUND_Load(void)
 {
-    SDL_AudioDevice *this;
+    int loaded = 0;
+
+    DSOUND_Unload();
 
-    /* Load DirectX */
-    if (DX5_Load() < 0) {
-        return (NULL);
+    DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL"));
+    if (DSoundDLL == NULL) {
+        SDL_SetError("DirectSound: failed to load DSOUND.DLL");
+    } else {
+        /* Now make sure we have DirectX 5 or better... */
+        /*  (DirectSoundCaptureCreate was added in DX5) */
+        if (!GetProcAddress(DSoundDLL, TEXT("DirectSoundCaptureCreate"))) {
+            SDL_SetError("DirectSound: System doesn't appear to have DX5.");
+        } else {
+            DSoundCreate = (void *) GetProcAddress(DSoundDLL,
+                                               TEXT("DirectSoundCreate"));
+        }
+
+        if (!DSoundCreate) {
+            SDL_SetError("DirectSound: Failed to find DirectSoundCreate");
+        } else {
+            loaded = 1;
+        }
     }
 
-    /* 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);
+    if (!loaded) {
+        DSOUND_Unload();
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
 
-    /* Set the function pointers */
-    this->OpenAudio = DX5_OpenAudio;
-    this->ThreadInit = DX5_ThreadInit;
-    this->WaitAudio = DX5_WaitAudio_BusyWait;
-    this->PlayAudio = DX5_PlayAudio;
-    this->GetAudioBuf = DX5_GetAudioBuf;
-    this->WaitDone = DX5_WaitDone;
-    this->CloseAudio = DX5_CloseAudio;
-
-    this->free = Audio_DeleteDevice;
-
-    return this;
+    return loaded;
 }
 
-AudioBootStrap DSOUND_bootstrap = {
-    "dsound", "Win95/98/2000 DirectSound",
-    Audio_Available, Audio_CreateDevice
-};
 
 static void
 SetDSerror(const char *function, int code)
@@ -192,8 +97,7 @@
     errbuf[0] = 0;
     switch (code) {
     case E_NOINTERFACE:
-        error =
-            "Unsupported interface\n-- Is DirectX 5.0 or later installed?";
+        error = "Unsupported interface -- Is DirectX 5.0 or later installed?";
         break;
     case DSERR_ALLOCATED:
         error = "Audio device in use";
@@ -241,32 +145,36 @@
 /* DirectSound needs to be associated with a window */
 static HWND mainwin = NULL;
 /* */
+
 void
-DX5_SoundFocus(HWND hwnd)
+DSOUND_SoundFocus(HWND hwnd)
 {
+    /* !!! FIXME: probably broken with multi-window support in SDL 1.3 ... */
     mainwin = hwnd;
 }
 
 static void
-DX5_ThreadInit(_THIS)
+DSOUND_ThreadInit(_THIS)
 {
     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
 }
 
 static void
-DX5_WaitAudio_BusyWait(_THIS)
+DSOUND_WaitDevice(_THIS)
 {
-    DWORD status;
-    DWORD cursor, junk;
-    HRESULT result;
+    DWORD status = 0;
+    DWORD cursor = 0;
+    DWORD junk = 0;
+    HRESULT result = DS_OK;
 
     /* Semi-busy wait, since we have no way of getting play notification
        on a primary mixing buffer located in hardware (DirectX 5.0)
      */
-    result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor);
+    result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
+                                                   &junk, &cursor);
     if (result != DS_OK) {
         if (result == DSERR_BUFFERLOST) {
-            IDirectSoundBuffer_Restore(mixbuf);
+            IDirectSoundBuffer_Restore(this->hidden->mixbuf);
         }
 #ifdef DEBUG_SOUND
         SetDSerror("DirectSound GetCurrentPosition", result);
@@ -274,21 +182,22 @@
         return;
     }
 
-    while ((cursor / mixlen) == lastchunk) {
+    while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) {
         /* FIXME: find out how much time is left and sleep that long */
         SDL_Delay(1);
 
         /* Try to restore a lost sound buffer */
-        IDirectSoundBuffer_GetStatus(mixbuf, &status);
+        IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
         if ((status & DSBSTATUS_BUFFERLOST)) {
-            IDirectSoundBuffer_Restore(mixbuf);
-            IDirectSoundBuffer_GetStatus(mixbuf, &status);
+            IDirectSoundBuffer_Restore(this->hidden->mixbuf);
+            IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
             if ((status & DSBSTATUS_BUFFERLOST)) {
                 break;
             }
         }
         if (!(status & DSBSTATUS_PLAYING)) {
-            result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING);
+            result = IDirectSoundBuffer_Play(this->hidden->mixbuf, 0, 0,
+                                             DSBPLAY_LOOPING);
             if (result == DS_OK) {
                 continue;
             }
@@ -299,7 +208,7 @@
         }
 
         /* Find out where we are playing */
-        result = IDirectSoundBuffer_GetCurrentPosition(mixbuf,
+        result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
                                                        &junk, &cursor);
         if (result != DS_OK) {
             SetDSerror("DirectSound GetCurrentPosition", result);
@@ -308,222 +217,122 @@
     }
 }
 
-#ifdef USE_POSITION_NOTIFY
 static void
-DX6_WaitAudio_EventWait(_THIS)
-{
-    DWORD status;
-    HRESULT result;
-
-    /* Try to restore a lost sound buffer */
-    IDirectSoundBuffer_GetStatus(mixbuf, &status);
-    if ((status & DSBSTATUS_BUFFERLOST)) {
-        IDirectSoundBuffer_Restore(mixbuf);
-        IDirectSoundBuffer_GetStatus(mixbuf, &status);
-        if ((status & DSBSTATUS_BUFFERLOST)) {
-            return;
-        }
-    }
-    if (!(status & DSBSTATUS_PLAYING)) {
-        result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING);
-        if (result != DS_OK) {
-#ifdef DEBUG_SOUND
-            SetDSerror("DirectSound Play", result);
-#endif
-            return;
-        }
-    }
-    WaitForSingleObject(audio_event, INFINITE);
-}
-#endif /* USE_POSITION_NOTIFY */
-
-static void
-DX5_PlayAudio(_THIS)
+DSOUND_PlayDevice(_THIS)
 {
     /* Unlock the buffer, allowing it to play */
-    if (locked_buf) {
-        IDirectSoundBuffer_Unlock(mixbuf, locked_buf, mixlen, NULL, 0);
+    if (this->hidden->locked_buf) {
+        IDirectSoundBuffer_Unlock(this->hidden->mixbuf,
+                                  this->hidden->locked_buf,
+                                  this->hidden->mixlen, NULL, 0);
     }
 
 }
 
 static Uint8 *
-DX5_GetAudioBuf(_THIS)
+DSOUND_GetDeviceBuf(_THIS)
 {
-    DWORD cursor, junk;
-    HRESULT result;
-    DWORD rawlen;
+    DWORD cursor = 0;
+    DWORD junk = 0;
+    HRESULT result = DS_OK;
+    DWORD rawlen = 0;
 
     /* Figure out which blocks to fill next */
-    locked_buf = NULL;
-    result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor);
+    this->hidden->locked_buf = NULL;
+    result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
+                                                   &junk, &cursor);
     if (result == DSERR_BUFFERLOST) {
-        IDirectSoundBuffer_Restore(mixbuf);
-        result = IDirectSoundBuffer_GetCurrentPosition(mixbuf,
+        IDirectSoundBuffer_Restore(this->hidden->mixbuf);
+        result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
                                                        &junk, &cursor);
     }
     if (result != DS_OK) {
         SetDSerror("DirectSound GetCurrentPosition", result);
         return (NULL);
     }
-    cursor /= mixlen;
+    cursor /= this->hidden->mixlen;
 #ifdef DEBUG_SOUND
     /* Detect audio dropouts */
     {
         DWORD spot = cursor;
-        if (spot < lastchunk) {
-            spot += NUM_BUFFERS;
+        if (spot < this->hidden->lastchunk) {
+            spot += this->hidden->num_buffers;
         }
-        if (spot > lastchunk + 1) {
+        if (spot > this->hidden->lastchunk + 1) {
             fprintf(stderr, "Audio dropout, missed %d fragments\n",
-                    (spot - (lastchunk + 1)));
+                    (spot - (this->hidden->lastchunk + 1)));
         }
     }
 #endif
-    lastchunk = cursor;
-    cursor = (cursor + 1) % NUM_BUFFERS;
-    cursor *= mixlen;
+    this->hidden->lastchunk = cursor;
+    cursor = (cursor + 1) % this->hidden->num_buffers;
+    cursor *= this->hidden->mixlen;
 
     /* Lock the audio buffer */
-    result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,
-                                     (LPVOID *) & locked_buf, &rawlen, NULL,
-                                     &junk, 0);
+    result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
+                                     this->hidden->mixlen,
+                                     (LPVOID *) &this->hidden->locked_buf,
+                                     &rawlen, NULL, &junk, 0);
     if (result == DSERR_BUFFERLOST) {
-        IDirectSoundBuffer_Restore(mixbuf);
-        result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,
-                                         (LPVOID *) & locked_buf, &rawlen,
-                                         NULL, &junk, 0);
+        IDirectSoundBuffer_Restore(this->hidden->mixbuf);
+        result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
+                                         this->hidden->mixlen,
+                                         (LPVOID *) &this->hidden->locked_buf,
+                                         &rawlen, NULL, &junk, 0);
     }
     if (result != DS_OK) {
         SetDSerror("DirectSound Lock", result);
         return (NULL);
     }
-    return (locked_buf);
-}
-
-static void
-DX5_WaitDone(_THIS)
-{
-    Uint8 *stream;
-
-    /* Wait for the playing chunk to finish */
-    stream = this->GetAudioBuf(this);
-    if (stream != NULL) {
-        SDL_memset(stream, silence, mixlen);
-        this->PlayAudio(this);
-    }
-    this->WaitAudio(this);
-
-    /* Stop the looping sound buffer */
-    IDirectSoundBuffer_Stop(mixbuf);
+    return (this->hidden->locked_buf);
 }
 
 static void
-DX5_CloseAudio(_THIS)
+DSOUND_WaitDone(_THIS)
 {
-    if (sound != NULL) {
-        if (mixbuf != NULL) {
-            /* Clean up the audio buffer */
-            IDirectSoundBuffer_Release(mixbuf);
-            mixbuf = NULL;
-        }
-        if (audio_event != NULL) {
-            CloseHandle(audio_event);
-            audio_event = NULL;
-        }
-        IDirectSound_Release(sound);
-        sound = NULL;
+    Uint8 *stream = DSOUND_GetDeviceBuf(this);
+
+    /* Wait for the playing chunk to finish */
+    if (stream != NULL) {
+        SDL_memset(stream, this->spec.silence, this->hidden->mixlen);
+        DSOUND_PlayDevice(this);
     }
+    DSOUND_WaitDevice(this);
+
+    /* Stop the looping sound buffer */
+    IDirectSoundBuffer_Stop(this->hidden->mixbuf);
 }
 
-#ifdef USE_PRIMARY_BUFFER
-/* This function tries to create a primary audio buffer, and returns the
-   number of audio chunks available in the created buffer.
-*/
-static int
-CreatePrimary(LPDIRECTSOUND sndObj, HWND focus,
-              LPDIRECTSOUNDBUFFER * sndbuf, WAVEFORMATEX * wavefmt,
-              Uint32 chunksize)
+static void
+DSOUND_CloseDevice(_THIS)
 {
-    HRESULT result;
-    DSBUFFERDESC format;
-    DSBCAPS caps;
-    int numchunks;
+    if (this->hidden != NULL) {
+        if (this->hidden->sound != NULL) {
+            if (this->hidden->mixbuf != NULL) {
+                /* Clean up the audio buffer */
+                IDirectSoundBuffer_Release(this->hidden->mixbuf);
+                this->hidden->mixbuf = NULL;
+            }
+            IDirectSound_Release(this->hidden->sound);
+            this->hidden->sound = NULL;
+        }
 
-    /* Try to set primary mixing privileges */
-    result = IDirectSound_SetCooperativeLevel(sndObj, focus,
-                                              DSSCL_WRITEPRIMARY);
-    if (result != DS_OK) {
-#ifdef DEBUG_SOUND
-        SetDSerror("DirectSound SetCooperativeLevel", result);
-#endif
-        return (-1);
-    }
-
-    /* Try to create the primary buffer */
-    SDL_memset(&format, 0, sizeof(format));
-    format.dwSize = sizeof(format);
-    format.dwFlags = (DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2);
-    format.dwFlags |= DSBCAPS_STICKYFOCUS;
-#ifdef USE_POSITION_NOTIFY
-    format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY;
-#endif
-    result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
-    if (result != DS_OK) {
-#ifdef DEBUG_SOUND
-        SetDSerror("DirectSound CreateSoundBuffer", result);
-#endif
-        return (-1);
+        SDL_free(this->hidden);
+        this->hidden = NULL;
     }
-
-    /* Check the size of the fragment buffer */
-    SDL_memset(&caps, 0, sizeof(caps));
-    caps.dwSize = sizeof(caps);
-    result = IDirectSoundBuffer_GetCaps(*sndbuf, &caps);
-    if (result != DS_OK) {
-#ifdef DEBUG_SOUND
-        SetDSerror("DirectSound GetCaps", result);
-#endif
-        IDirectSoundBuffer_Release(*sndbuf);
-        return (-1);
-    }
-    if ((chunksize > caps.dwBufferBytes) ||
-        ((caps.dwBufferBytes % chunksize) != 0)) {
-        /* The primary buffer size is not a multiple of 'chunksize'
-           -- this hopefully doesn't happen when 'chunksize' is a 
-           power of 2.
-         */
-        IDirectSoundBuffer_Release(*sndbuf);
-        SDL_SetError
-            ("Primary buffer size is: %d, cannot break it into chunks of %d bytes\n",
-             caps.dwBufferBytes, chunksize);
-        return (-1);
-    }
-    numchunks = (caps.dwBufferBytes / chunksize);
-
-    /* Set the primary audio format */
-    result = IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt);
-    if (result != DS_OK) {
-#ifdef DEBUG_SOUND
-        SetDSerror("DirectSound SetFormat", result);
-#endif
-        IDirectSoundBuffer_Release(*sndbuf);
-        return (-1);
-    }
-    return (numchunks);
 }
-#endif /* USE_PRIMARY_BUFFER */
 
 /* This function tries to create a secondary audio buffer, and returns the
    number of audio chunks available in the created buffer.
 */
 static int
-CreateSecondary(LPDIRECTSOUND sndObj, HWND focus,
-                LPDIRECTSOUNDBUFFER * sndbuf, WAVEFORMATEX * wavefmt,
-                Uint32 chunksize)
+CreateSecondary(_THIS, HWND focus, WAVEFORMATEX *wavefmt)
 {
+    LPDIRECTSOUND sndObj = this->hidden->sound;
+    LPDIRECTSOUNDBUFFER *sndbuf = this->hidden->mixbuf;
+    Uint32 chunksize = this->spec.size;
     const int numchunks = 8;
-    HRESULT result;
+    HRESULT result = DS_OK;
     DSBUFFERDESC format;
     LPVOID pvAudioPtr1, pvAudioPtr2;
     DWORD dwAudioBytes1, dwAudioBytes2;
@@ -538,9 +347,7 @@
                                                   DSSCL_NORMAL);
     }
     if (result != DS_OK) {
-#ifdef DEBUG_SOUND
         SetDSerror("DirectSound SetCooperativeLevel", result);
-#endif
         return (-1);
     }
 
@@ -548,9 +355,6 @@
     SDL_memset(&format, 0, sizeof(format));
     format.dwSize = sizeof(format);
     format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
-#ifdef USE_POSITION_NOTIFY
-    format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY;
-#endif
     if (!focus) {
         format.dwFlags |= DSBCAPS_GLOBALFOCUS;
     } else {
@@ -578,11 +382,7 @@
                                      (LPVOID *) & pvAudioPtr2, &dwAudioBytes2,
                                      DSBLOCK_ENTIREBUFFER);
     if (result == DS_OK) {
-        if (wavefmt->wBitsPerSample == 8) {
-            SDL_memset(pvAudioPtr1, 0x80, dwAudioBytes1);
-        } else {
-            SDL_memset(pvAudioPtr1, 0x00, dwAudioBytes1);
-        }
+        SDL_memset(pvAudioPtr1, this->spec.silence, dwAudioBytes1);
         IDirectSoundBuffer_Unlock(*sndbuf,
                                   (LPVOID) pvAudioPtr1, dwAudioBytes1,
                                   (LPVOID) pvAudioPtr2, dwAudioBytes2);
@@ -592,148 +392,125 @@
     return (numchunks);
 }
 
-/* This function tries to set position notify events on the mixing buffer */
-#ifdef USE_POSITION_NOTIFY
 static int
-CreateAudioEvent(_THIS)
-{
-    LPDIRECTSOUNDNOTIFY notify;
-    DSBPOSITIONNOTIFY *notify_positions;
-    int i, retval;
-    HRESULT result;
-
-    /* Default to fail on exit */
-    retval = -1;
-    notify = NULL;
-
-    /* Query for the interface */
-    result = IDirectSoundBuffer_QueryInterface(mixbuf,
-                                               &IID_IDirectSoundNotify,
-                                               (void *) &notify);
-    if (result != DS_OK) {
-        goto done;
-    }
-
-    /* Allocate the notify structures */
-    notify_positions = (DSBPOSITIONNOTIFY *) SDL_malloc(NUM_BUFFERS *
-                                                        sizeof
-                                                        (*notify_positions));
-    if (notify_positions == NULL) {
-        goto done;
-    }
-
-    /* Create the notify event */
-    audio_event = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (audio_event == NULL) {
-        goto done;
-    }
-
-    /* Set up the notify structures */
-    for (i = 0; i < NUM_BUFFERS; ++i) {
-        notify_positions[i].dwOffset = i * mixlen;
-        notify_positions[i].hEventNotify = audio_event;
-    }
-    result = IDirectSoundNotify_SetNotificationPositions(notify,
-                                                         NUM_BUFFERS,
-                                                         notify_positions);
-    if (result == DS_OK) {
-        retval = 0;
-    }
-  done:
-    if (notify != NULL) {
-        IDirectSoundNotify_Release(notify);
-    }
-    return (retval);
-}
-#endif /* USE_POSITION_NOTIFY */
-
-static int
-DX5_OpenAudio(_THIS, SDL_AudioSpec * spec)
+DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
 {
     HRESULT result;
     WAVEFORMATEX waveformat;
+    int valid_format = 0;
+    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
 
-    /* Set basic WAVE format parameters */
+    /* !!! FIXME: handle devname */
+    /* !!! FIXME: handle iscapture */
+
+    /* 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));
+
+    while ((!valid_format) && (test_format)) {
+        switch (test_format) {
+            case AUDIO_U8:
+            case AUDIO_S16:
+            case AUDIO_S32:
+                this->spec.format = test_format;
+                valid_format = 1;
+                break;
+        }
+        test_format = SDL_NextAudioFormat();
+    }
+
+    if (!valid_format) {
+        DSOUND_CloseDevice(this);
+        SDL_SetError("DirectSound: Unsupported audio format");
+        return 0;
+    }
+
     SDL_memset(&waveformat, 0, sizeof(waveformat));
     waveformat.wFormatTag = WAVE_FORMAT_PCM;
-
-    /* Determine the audio parameters from the AudioSpec */
-    switch (SDL_AUDIO_BITSIZE(spec->format)) {
-    case 8:
-        /* Unsigned 8 bit audio data */
-        spec->format = AUDIO_U8;
-        silence = 0x80;
-        waveformat.wBitsPerSample = 8;
-        break;
-    case 16:
-        /* Signed 16 bit audio data */
-        spec->format = AUDIO_S16;
-        silence = 0x00;
-        waveformat.wBitsPerSample = 16;
-        break;
-    case 32:
-        /* Signed 32 bit audio data */
-        spec->format = AUDIO_S32;
-        silence = 0x00;
-        waveformat.wBitsPerSample = 32;
-        break;
-    default:
-        SDL_SetError("Unsupported audio format");
-        return (-1);
-    }
-    waveformat.nChannels = spec->channels;
-    waveformat.nSamplesPerSec = spec->freq;
+    waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
+    waveformat.nChannels = this->spec.channels;
+    waveformat.nSamplesPerSec = this->spec.freq;
     waveformat.nBlockAlign =
         waveformat.nChannels * (waveformat.wBitsPerSample / 8);
     waveformat.nAvgBytesPerSec =
         waveformat.nSamplesPerSec * waveformat.nBlockAlign;
 
     /* Update the fragment size as size in bytes */
-    SDL_CalculateAudioSpec(spec);
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* Open the audio device */
-    result = DSoundCreate(NULL, &sound, NULL);
+    result = DSoundCreate(NULL, &this->hidden->sound, NULL);
     if (result != DS_OK) {
+        DSOUND_CloseDevice(this);
         SetDSerror("DirectSoundCreate", result);
-        return (-1);
+        return 0;
     }
 
     /* Create the audio buffer to which we write */
-    NUM_BUFFERS = -1;
-#ifdef USE_PRIMARY_BUFFER
-    if (mainwin) {
-        NUM_BUFFERS = CreatePrimary(sound, mainwin, &mixbuf,
-                                    &waveformat, spec->size);
-    }
-#endif /* USE_PRIMARY_BUFFER */
-    if (NUM_BUFFERS < 0) {
-        NUM_BUFFERS = CreateSecondary(sound, mainwin, &mixbuf,
-                                      &waveformat, spec->size);
-        if (NUM_BUFFERS < 0) {
-            return (-1);
-        }
-#ifdef DEBUG_SOUND
-        fprintf(stderr, "Using secondary audio buffer\n");
-#endif
+    this->hidden->num_buffers = CreateSecondary(this, mainwin, &waveformat);
+    if (this->hidden->num_buffers < 0) {
+        DSOUND_CloseDevice(this);
+        return 0;
     }
-#ifdef DEBUG_SOUND
-    else
-        fprintf(stderr, "Using primary audio buffer\n");
-#endif
 
-    /* The buffer will auto-start playing in DX5_WaitAudio() */
-    lastchunk = 0;
-    mixlen = spec->size;
+    /* The buffer will auto-start playing in DSOUND_WaitDevice() */
+    this->hidden->mixlen = this->spec.size;
 
-#ifdef USE_POSITION_NOTIFY
-    /* See if we can use DirectX 6 event notification */
-    if (CreateAudioEvent(this) == 0) {
-        this->WaitAudio = DX6_WaitAudio_EventWait;
-    } else {
-        this->WaitAudio = DX5_WaitAudio_BusyWait;
-    }
-#endif
-    return (0);
+    return 1;  /* good to go. */
+}
+
+
+static void
+DSOUND_Deinitialize(void)
+{
+    DSOUND_Unload();
 }
 
+
+static int
+DSOUND_Init(SDL_AudioDriverImpl *impl)
+{
+    OSVERSIONINFO ver;
+
+    /*
+     * Unfortunately, the sound drivers on NT have higher latencies than the
+     *  audio buffers used by many SDL applications, so there are gaps in the
+     *  audio - it sounds terrible.  Punt for now.
+     */
+    SDL_memset(&ver, '\0', sizeof (OSVERSIONINFO));
+    ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+    GetVersionEx(&ver);
+    if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT)
+        if (ver.dwMajorVersion <= 4) {
+            return 0;  /* NT4.0 or earlier. Disable dsound support. */
+        }
+    }
+
+    if (!DSOUND_Load()) {
+        return 0;
+    }
+
+    /* Set the function pointers */
+    impl->OpenDevice = DSOUND_OpenDevice;
+    impl->PlayDevice = DSOUND_PlayDevice;
+    impl->WaitDevice = DSOUND_WaitDevice;
+    impl->WaitDone = DSOUND_WaitDone;
+    impl->ThreadInit = DSOUND_ThreadInit;
+    impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
+    impl->CloseDevice = DSOUND_CloseDevice;
+    impl->Deinitialize = DSOUND_Deinitialize;
+    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME */
+
+    return 1;
+}
+
+AudioBootStrap DSOUND_bootstrap = {
+    "dsound", WINDOWS_OS_NAME "DirectSound", DSOUND_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/windx5/SDL_dx5audio.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/windx5/SDL_dx5audio.h	Tue Oct 17 09:15:21 2006 +0000
@@ -21,14 +21,14 @@
 */
 #include "SDL_config.h"
 
-#ifndef _SDL_lowaudio_h
-#define _SDL_lowaudio_h
+#ifndef _SDL_dx5audio_h
+#define _SDL_dx5audio_h
 
 #include "directx.h"
 
 #include "../SDL_sysaudio.h"
 
-/* Hidden "this" pointer for the video functions */
+/* Hidden "this" pointer for the audio functions */
 #define _THIS	SDL_AudioDevice *this
 
 /* The DirectSound objects */
@@ -36,23 +36,12 @@
 {
     LPDIRECTSOUND sound;
     LPDIRECTSOUNDBUFFER mixbuf;
-    int NUM_BUFFERS;
-    int mixlen, silence;
+    int num_buffers;
+    int mixlen;
     DWORD lastchunk;
     Uint8 *locked_buf;
-    HANDLE audio_event;
 };
 
-/* Old variable names */
-#define sound			(this->hidden->sound)
-#define mixbuf			(this->hidden->mixbuf)
-#define NUM_BUFFERS		(this->hidden->NUM_BUFFERS)
-#define mixlen			(this->hidden->mixlen)
-#define silence			(this->hidden->silence)
-#define lastchunk		(this->hidden->lastchunk)
-#define locked_buf		(this->hidden->locked_buf)
-#define audio_event		(this->hidden->audio_event)
-
-#endif /* _SDL_lowaudio_h */
+#endif /* _SDL_dx5audio_h */
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/events/SDL_mouse.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/events/SDL_mouse.c	Tue Oct 17 09:15:21 2006 +0000
@@ -165,7 +165,7 @@
     return mouse->focus;
 }
 
-static int
+static int SDLCALL
 FlushMouseMotion(void *param, SDL_Event * event)
 {
     if (event->type == SDL_MOUSEMOTION
--- a/src/timer/os2/SDL_systimer.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/timer/os2/SDL_systimer.c	Tue Oct 17 09:15:21 2006 +0000
@@ -65,24 +65,28 @@
 */
     /* inline asm to avoid runtime inclusion */
     _asm {
-    push edx
-            push eax
-            mov eax, dword ptr hires_now
-            mov edx, dword ptr hires_now + 4
-            sub eax, dword ptr hires_start_ticks
-            sbb edx, dword ptr hires_start_ticks + 4
-            mov ebx, 1000
-            mov ecx, edx
-            mul ebx
-            push eax
-            push edx
-            mov eax, ecx
-            mul ebx
-            pop eax
-            add edx, eax
-            pop eax
-            mov ebx, dword ptr hires_ticks_per_second
-            div ebx mov dword ptr ticks, eax pop edx pop eax}
+        push edx
+        push eax
+        mov eax, dword ptr hires_now
+        mov edx, dword ptr hires_now + 4
+        sub eax, dword ptr hires_start_ticks
+        sbb edx, dword ptr hires_start_ticks + 4
+        mov ebx, 1000
+        mov ecx, edx
+        mul ebx
+        push eax
+        push edx
+        mov eax, ecx
+        mul ebx
+        pop eax
+        add edx, eax
+        pop eax
+        mov ebx, dword ptr hires_ticks_per_second
+        div ebx
+        mov dword ptr ticks, eax
+        pop edx
+        pop eax
+    }
 
     return ticks;
 
@@ -178,7 +182,7 @@
 static int timer_alive = 0;
 static SDL_Thread *timer = NULL;
 
-static int
+static int SDLCALL
 RunTimer(void *unused)
 {
     DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
--- a/src/video/SDL_rendercopy.h	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/video/SDL_rendercopy.h	Tue Oct 17 09:15:21 2006 +0000
@@ -33,10 +33,10 @@
 #define SDL_RENDERCOPY_NEAREST          0x0100
 
 typedef struct {
-    void *src;
+    Uint8 *src;
     int src_w, src_h;
     int src_pitch;
-    void *dst;
+    Uint8 *dst;
     int dst_w, dst_h;
     int dst_pitch;
     void *aux_data;
@@ -44,7 +44,7 @@
     Uint8 r, g, b, a;
 } SDL_RenderCopyData;
 
-typedef int (*SDL_RenderCopyFunc)(SDL_RenderCopyData *data);
+typedef int (SDLCALL * SDL_RenderCopyFunc)(SDL_RenderCopyData *data);
 
 extern SDL_RenderCopyFunc SDLCALL SDL_GetRenderCopyFunc(Uint32 src_format, Uint32 dst_format, int modMode, int blendMode, int scaleMode);
 
--- a/test/Makefile.in	Sun Oct 01 16:10:41 2006 +0000
+++ b/test/Makefile.in	Tue Oct 17 09:15:21 2006 +0000
@@ -7,7 +7,7 @@
 CFLAGS  = @CFLAGS@
 LIBS	= @LIBS@
 
-TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testcursor$(EXE) testdyngl$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE)
+TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testaudioinfo$(EXE) testmultiaudio$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testcursor$(EXE) testdyngl$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE)
 
 all: Makefile $(TARGETS)
 
@@ -23,6 +23,12 @@
 loopwave$(EXE): $(srcdir)/loopwave.c
 	$(CC) -o $@ $? $(CFLAGS) $(LIBS)
 
+testaudioinfo$(EXE): $(srcdir)/testaudioinfo.c
+	$(CC) -o $@ $? $(CFLAGS) $(LIBS)
+
+testmultiaudio$(EXE): $(srcdir)/testmultiaudio.c
+	$(CC) -o $@ $? $(CFLAGS) $(LIBS)
+
 testalpha$(EXE): $(srcdir)/testalpha.c
 	$(CC) -o $@ $? $(CFLAGS) $(LIBS) @MATHLIB@
 
--- a/test/loopwave.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/test/loopwave.c	Tue Oct 17 09:15:21 2006 +0000
@@ -69,26 +69,12 @@
 {
     int i, n;
 
-    /* Print available audio drivers */
-    n = SDL_GetNumAudioDrivers();
-    if (n == 0) {
-        printf("No built-in audio drivers\n");
-    } else {
-        printf("Built-in audio drivers:");
-        for (i = 0; i < n; ++i) {
-            if (i > 0) {
-                printf(",");
-            }
-            printf(" %s", SDL_GetAudioDriver(i));
-        }
-        printf("\n");
-    }
-
     /* Load the SDL library */
     if (SDL_Init(SDL_INIT_AUDIO) < 0) {
         fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
         return (1);
     }
+
     if (argv[1] == NULL) {
         argv[1] = "sample.wav";
     }
@@ -120,7 +106,6 @@
     SDL_PauseAudio(0);
 
     /* Let the audio run */
-    printf("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
     while (!done && (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING))
         SDL_Delay(1000);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testaudioinfo.c	Tue Oct 17 09:15:21 2006 +0000
@@ -0,0 +1,53 @@
+#include "SDL.h"
+
+static void print_devices(int iscapture)
+{
+    const char *typestr = ((iscapture) ? "capture" : "output");
+    int n = SDL_GetNumAudioDevices(iscapture);
+
+    printf("%s devices:\n", typestr);
+
+    if (n == -1)
+        printf("  Driver can't detect specific devices.\n\n", typestr);
+    else if (n == 0)
+        printf("  No %s devices found.\n\n", typestr);
+    else
+    {
+        int i;
+        for (i = 0; i < n; i++) {
+            printf("  %s\n", SDL_GetAudioDeviceName(i, iscapture));
+        }
+        printf("\n");
+    }
+}
+
+int main(int argc, char **argv)
+{
+    /* Print available audio drivers */
+    int n = SDL_GetNumAudioDrivers();
+    if (n == 0) {
+        printf("No built-in audio drivers\n\n");
+    } else {
+        int i;
+        printf("Built-in audio drivers:\n");
+        for (i = 0; i < n; ++i) {
+            printf("  %s\n", SDL_GetAudioDriver(i));
+        }
+        printf("\n");
+    }
+
+    /* Load the SDL library */
+    if (SDL_Init(SDL_INIT_AUDIO) < 0) {
+        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
+        return (1);
+    }
+
+    printf("Using audio driver: %s\n\n", SDL_GetCurrentAudioDriver());
+
+    print_devices(0);
+    print_devices(1);
+
+    SDL_Quit();
+    return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testmultiaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -0,0 +1,136 @@
+#include "SDL.h"
+
+static SDL_AudioSpec spec;
+static Uint8 *sound = NULL;            /* Pointer to wave data */
+static Uint32 soundlen = 0;            /* Length of wave data */
+
+typedef struct
+{
+    SDL_AudioDeviceID dev;
+    int soundpos;
+    volatile int done;
+} callback_data;
+
+void SDLCALL play_through_once(void *arg, Uint8 * stream, int len)
+{
+    callback_data *cbd = (callback_data *) arg;
+    Uint8 *waveptr = sound + cbd->soundpos;
+    int waveleft = soundlen - cbd->soundpos;
+    int cpy = len;
+    if (cpy > waveleft)
+        cpy = waveleft;
+
+    memcpy(stream, waveptr, cpy);
+    len -= cpy;
+    cbd->soundpos += cpy;
+    if (len > 0) {
+        stream += cpy;
+        memset(stream, spec.silence, len);
+        cbd->done++;
+    }
+}
+
+static void test_multi_audio(int devcount)
+{
+    callback_data cbd[64];
+    int keep_going = 1;
+    int i;
+
+    if (devcount > 64) {
+        fprintf(stderr, "Too many devices (%d), clamping to 64...\n", devcount);
+        devcount = 64;
+    }
+
+    spec.callback = play_through_once;
+
+    for (i = 0; i < devcount; i++) {
+        const char *devname = SDL_GetAudioDeviceName(i, 0);
+        printf("playing on device #%d: ('%s')...", i, devname);
+        fflush(stdout);
+
+        memset(&cbd[0], '\0', sizeof (callback_data));
+        spec.userdata = &cbd[0];
+        cbd[0].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL);
+        if (cbd[0].dev == 0) {
+            printf("Open device failed: %s\n", SDL_GetError());
+        } else {
+            SDL_PauseAudioDevice(cbd[0].dev, 0);
+            while (!cbd[0].done)
+                SDL_Delay(100);
+            SDL_PauseAudioDevice(cbd[0].dev, 1);
+            printf("done.\n");
+            SDL_CloseAudioDevice(cbd[0].dev);
+        }
+    }
+
+    memset(cbd, '\0', sizeof (cbd));
+
+    printf("playing on all devices...\n");
+    for (i = 0; i < devcount; i++) {
+        const char *devname = SDL_GetAudioDeviceName(i, 0);
+        spec.userdata = &cbd[i];
+        cbd[i].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL);
+        if (cbd[i].dev == 0) {
+            printf("Open device %d failed: %s\n", i, SDL_GetError());
+        }
+    }
+
+    for (i = 0; i < devcount; i++) {
+        if (cbd[i].dev) {
+            SDL_PauseAudioDevice(cbd[i].dev, 0);
+        }
+    }
+
+    while (keep_going) {
+        keep_going = 0;
+        for (i = 0; i < devcount; i++) {
+            if ((cbd[i].dev) && (!cbd[i].done)) {
+                keep_going = 1;
+            }
+        }
+        SDL_Delay(100);
+    }
+
+    for (i = 0; i < devcount; i++) {
+        if (cbd[i].dev) {
+            SDL_PauseAudioDevice(cbd[i].dev, 1);
+            SDL_CloseAudioDevice(cbd[i].dev);
+        }
+    }
+
+    printf("All done!\n");
+}
+
+
+int main(int argc, char **argv)
+{
+    int devcount = 0;
+
+    /* Load the SDL library */
+    if (SDL_Init(SDL_INIT_AUDIO) < 0) {
+        fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
+        return (1);
+    }
+
+    printf("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
+
+    devcount = SDL_GetNumAudioDevices(0);
+    if (devcount < 1) {
+        fprintf(stderr, "Don't see any specific audio devices!\n");
+    } else {
+        if (argv[1] == NULL) {
+            argv[1] = "sample.wav";
+        }
+
+        /* Load the wave file into memory */
+        if (SDL_LoadWAV(argv[1], &spec, &sound, &soundlen) == NULL) {
+            fprintf(stderr, "Couldn't load %s: %s\n", argv[1], SDL_GetError());
+        } else {
+            test_multi_audio(devcount);
+            SDL_FreeWAV(sound);
+        }
+    }
+
+    SDL_Quit();
+    return 0;
+}