Merged SDL-ryan-multiple-audio-device branch r2803:2871 into the trunk.
authorRyan C. Gordon <icculus@icculus.org>
Tue, 17 Oct 2006 09:15:21 +0000
changeset 20495f6550e5184f
parent 2048 6067c7f9a672
child 2050 bbc89e09503f
Merged SDL-ryan-multiple-audio-device branch r2803:2871 into the trunk.
configure.in
include/SDL_audio.h
include/SDL_config.h.in
include/SDL_thread.h
src/SDL_error.c
src/audio/SDL_audio.c
src/audio/SDL_audiocvt.c
src/audio/SDL_audiodev.c
src/audio/SDL_audiodev_c.h
src/audio/SDL_mixer.c
src/audio/SDL_sysaudio.h
src/audio/alsa/SDL_alsa_audio.c
src/audio/alsa/SDL_alsa_audio.h
src/audio/amigaos/SDL_ahiaudio.c
src/audio/amigaos/SDL_ahiaudio.h
src/audio/arts/SDL_artsaudio.c
src/audio/arts/SDL_artsaudio.h
src/audio/baudio/SDL_beaudio.cc
src/audio/baudio/SDL_beaudio.h
src/audio/bsd/SDL_bsdaudio.c
src/audio/bsd/SDL_bsdaudio.h
src/audio/dart/SDL_dart.c
src/audio/dart/SDL_dart.h
src/audio/dc/SDL_dcaudio.c
src/audio/dc/SDL_dcaudio.h
src/audio/disk/SDL_diskaudio.c
src/audio/disk/SDL_diskaudio.h
src/audio/dma/SDL_dmaaudio.c
src/audio/dma/SDL_dmaaudio.h
src/audio/dmedia/SDL_irixaudio.c
src/audio/dmedia/SDL_irixaudio.h
src/audio/dsp/SDL_dspaudio.c
src/audio/dsp/SDL_dspaudio.h
src/audio/dummy/SDL_dummyaudio.c
src/audio/dummy/SDL_dummyaudio.h
src/audio/esd/SDL_esdaudio.c
src/audio/esd/SDL_esdaudio.h
src/audio/macosx/SDL_coreaudio.c
src/audio/macosx/SDL_coreaudio.h
src/audio/macrom/SDL_romaudio.c
src/audio/macrom/SDL_romaudio.h
src/audio/mint/SDL_mintaudio_dma8.c
src/audio/mint/SDL_mintaudio_gsxb.c
src/audio/mint/SDL_mintaudio_mcsn.c
src/audio/mint/SDL_mintaudio_stfa.c
src/audio/mint/SDL_mintaudio_xbios.c
src/audio/mme/SDL_mmeaudio.c
src/audio/mme/SDL_mmeaudio.h
src/audio/nas/SDL_nasaudio.c
src/audio/nas/SDL_nasaudio.h
src/audio/nto/SDL_nto_audio.c
src/audio/nto/SDL_nto_audio.h
src/audio/paudio/SDL_paudio.c
src/audio/paudio/SDL_paudio.h
src/audio/sun/SDL_sunaudio.c
src/audio/sun/SDL_sunaudio.h
src/audio/ums/SDL_umsaudio.c
src/audio/ums/SDL_umsaudio.h
src/audio/windib/SDL_dibaudio.c
src/audio/windib/SDL_dibaudio.h
src/audio/windx5/SDL_dx5audio.c
src/audio/windx5/SDL_dx5audio.h
src/events/SDL_mouse.c
src/timer/os2/SDL_systimer.c
src/video/SDL_rendercopy.h
test/Makefile.in
test/loopwave.c
test/testaudioinfo.c
test/testmultiaudio.c
     1.1 --- a/configure.in	Sun Oct 01 16:10:41 2006 +0000
     1.2 +++ b/configure.in	Tue Oct 17 09:15:21 2006 +0000
     1.3 @@ -511,9 +511,17 @@
     1.4  AC_HELP_STRING([--enable-nas], [support the NAS audio API [[default=yes]]]),
     1.5                    , enable_nas=yes)
     1.6      if test x$enable_audio = xyes -a x$enable_nas = xyes; then
     1.7 +        AC_CHECK_HEADER(audio/audiolib.h, have_nas_hdr=yes)
     1.8 +        AC_CHECK_LIB(audio, AuOpenServer, have_nas_lib=yes)
     1.9 +
    1.10          AC_MSG_CHECKING(for NAS audio support)
    1.11          have_nas=no
    1.12 -        if test -r /usr/X11R6/include/audio/audiolib.h; then
    1.13 +
    1.14 +        if test x$have_nas_hdr = xyes -a x$have_nas_lib = xyes; then
    1.15 +            have_nas=yes
    1.16 +            NAS_LIBS="-laudio"
    1.17 +
    1.18 +        elif test -r /usr/X11R6/include/audio/audiolib.h; then
    1.19              have_nas=yes
    1.20              NAS_CFLAGS="-I/usr/X11R6/include/"
    1.21              NAS_LIBS="-L/usr/X11R6/lib -laudio -lXt"
    1.22 @@ -525,12 +533,40 @@
    1.23              have_nas=yes
    1.24              NAS_LIBS="-lnas -lXt"
    1.25          fi
    1.26 +
    1.27          AC_MSG_RESULT($have_nas)
    1.28 +
    1.29          if test x$have_nas = xyes; then
    1.30 +            AC_ARG_ENABLE(nas-shared,
    1.31 +AC_HELP_STRING([--enable-nas-shared], [dynamically load NAS audio support [[default=yes]]]),
    1.32 +                          , enable_nas_shared=yes)
    1.33 +            if test "x`echo $NAS_LIBS | grep -- -L`" = "x"; then
    1.34 +                if test "x`ls /lib/libaudio.so.* 2> /dev/null`" != "x"; then
    1.35 +                    NAS_LIBS="-L/lib $NAS_LIBS"
    1.36 +                elif test "x`ls /usr/lib/libaudio.so.* 2> /dev/null`" != "x"; then
    1.37 +                    NAS_LIBS="-L/usr/lib $NAS_LIBS"
    1.38 +                elif test "x`ls /usr/local/lib/libaudio.so.* 2> /dev/null`" != "x"; then
    1.39 +                    NAS_LIBS="-L/usr/local/lib $NAS_LIBS"
    1.40 +                fi
    1.41 +            fi
    1.42 +            nas_lib_spec=`echo $NAS_LIBS | sed 's/.*-L\([[^ ]]*\).*/\1\/libaudio.so.*/'`
    1.43 +            nas_lib=`ls -- $nas_lib_spec | sed 's/.*\/\(.*\)/\1/; q'`
    1.44 +            echo "-- $nas_lib_spec -> $nas_lib"
    1.45 +
    1.46 +            if test x$have_loadso != xyes && \
    1.47 +               test x$enable_nas_shared = xyes; then
    1.48 +                AC_MSG_WARN([You must have SDL_LoadObject() support for dynamic NAS loading])
    1.49 +            fi
    1.50 +            if test x$have_loadso = xyes && \
    1.51 +               test x$enable_nas_shared = xyes && test x$alsa_lib != x; then
    1.52 +                AC_DEFINE_UNQUOTED(SDL_AUDIO_DRIVER_NAS_DYNAMIC, "$nas_lib")
    1.53 +            else
    1.54 +                EXTRA_LDFLAGS="$EXTRA_LDFLAGS $NAS_LIBS"
    1.55 +            fi
    1.56 +
    1.57              AC_DEFINE(SDL_AUDIO_DRIVER_NAS)
    1.58              SOURCES="$SOURCES $srcdir/src/audio/nas/*.c"
    1.59              EXTRA_CFLAGS="$EXTRA_CFLAGS $NAS_CFLAGS"
    1.60 -            EXTRA_LDFLAGS="$EXTRA_LDFLAGS $NAS_LIBS"
    1.61              have_audio=yes
    1.62          fi
    1.63      fi
    1.64 @@ -2006,7 +2042,7 @@
    1.65                  have_audio=yes
    1.66              ;;
    1.67              aix)
    1.68 -                AC_DEFINE(SDL_AUDIO_DRIVER_PAUD)
    1.69 +                AC_DEFINE(SDL_AUDIO_DRIVER_PAUDIO)
    1.70                  SOURCES="$SOURCES $srcdir/src/audio/paudio/*.c"
    1.71                  have_audio=yes
    1.72              ;;
    1.73 @@ -2206,7 +2242,7 @@
    1.74          CheckBeGL
    1.75          # Set up files for the audio library
    1.76          if test x$enable_audio = xyes; then
    1.77 -            AC_DEFINE(SDL_AUDIO_DRIVER_BAUDIO)
    1.78 +            AC_DEFINE(SDL_AUDIO_DRIVER_BEOSAUDIO)
    1.79              SOURCES="$SOURCES $srcdir/src/audio/baudio/*.cc"
    1.80              have_audio=yes
    1.81          fi
    1.82 @@ -2323,7 +2359,7 @@
    1.83          EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
    1.84          # If either the audio or CD driver is used, add the AudioUnit framework
    1.85          if test x$enable_audio = xyes -o x$enable_cdrom = xyes; then
    1.86 -            EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit"
    1.87 +            EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreAudio -framework,AudioToolbox -Wl,-framework,AudioUnit"
    1.88          fi
    1.89          ;;
    1.90      *-*-mint*)
     2.1 --- a/include/SDL_audio.h	Sun Oct 01 16:10:41 2006 +0000
     2.2 +++ b/include/SDL_audio.h	Tue Oct 17 09:15:21 2006 +0000
     2.3 @@ -153,7 +153,7 @@
     2.4  
     2.5  /* Function prototypes */
     2.6  
     2.7 -/* These functions return the list of built in video drivers, in the 
     2.8 +/* These functions return the list of built in audio drivers, in the
     2.9   * order that they are normally initialized by default.
    2.10   */
    2.11  extern DECLSPEC int SDLCALL SDL_GetNumAudioDrivers(void);
    2.12 @@ -212,7 +212,7 @@
    2.13   * may modify the requested size of the audio buffer, you should allocate
    2.14   * any local mixing buffers after you open the audio device.
    2.15   */
    2.16 -extern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired,
    2.17 +extern DECLSPEC int SDLCALL SDL_OpenAudio(const SDL_AudioSpec * desired,
    2.18                                            SDL_AudioSpec * obtained);
    2.19  
    2.20  /*
    2.21 @@ -228,6 +228,13 @@
    2.22  /*
    2.23   * Get the number of available devices exposed by the current driver.
    2.24   *  Only valid after a successfully initializing the audio subsystem.
    2.25 + *  Returns -1 if an explicit list of devices can't be determined; this is
    2.26 + *  not an error. For example, if SDL is set up to talk to a remote audio
    2.27 + *  server, it can't list every one available on the Internet, but it will
    2.28 + *  still allow a specific host to be specified to SDL_OpenAudioDevice().
    2.29 + * In many common cases, when this function returns a value <= 0, it can still
    2.30 + *  successfully open the default device (NULL for first argument of
    2.31 + *  SDL_OpenAudioDevice()).
    2.32   */
    2.33  extern DECLSPEC int SDLCALL SDL_GetNumAudioDevices(int iscapture);
    2.34  
    2.35 @@ -235,15 +242,28 @@
    2.36   * Get the human-readable name of a specific audio device.
    2.37   *  Must be a value between 0 and (number of audio devices-1).
    2.38   *  Only valid after a successfully initializing the audio subsystem.
    2.39 + *  The values returned by this function reflect the latest call to
    2.40 + *  SDL_GetNumAudioDevices(); recall that function to redetect available
    2.41 + *  hardware.
    2.42 + *
    2.43 + * The string returned by this function is UTF-8 encoded, read-only, and
    2.44 + *  managed internally. You are not to free it. If you need to keep the
    2.45 + *  string for any length of time, you should make your own copy of it, as it
    2.46 + *  will be invalid next time any of several other SDL functions is called.
    2.47   */
    2.48 -extern DECLSPEC const char *SDLCALL SDL_GetAudioDevice(int index,
    2.49 -                                                       int iscapture);
    2.50 +extern DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(int index,
    2.51 +                                                           int iscapture);
    2.52  
    2.53  
    2.54  /*
    2.55 - * Open a specific audio device. Passing in a device name of NULL is
    2.56 - *  equivalent to SDL_OpenAudio(). Returns 0 on error, a valid device ID
    2.57 - *  on success.
    2.58 + * Open a specific audio device. Passing in a device name of NULL requests
    2.59 + *  the most reasonable default (and is equivalent to calling SDL_OpenAudio()).
    2.60 + * The device name is a UTF-8 string reported by SDL_GetAudioDevice(), but
    2.61 + *  some drivers allow arbitrary and driver-specific strings, such as a
    2.62 + *  hostname/IP address for a remote audio server, or a filename in the
    2.63 + *  diskaudio driver.
    2.64 + * Returns 0 on error, a valid device ID that is >= 2 on success.
    2.65 + *  SDL_OpenAudio(), unlike this function, always acts on device ID 1.
    2.66   */
    2.67  extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(const char
    2.68                                                                *device,
     3.1 --- a/include/SDL_config.h.in	Sun Oct 01 16:10:41 2006 +0000
     3.2 +++ b/include/SDL_config.h.in	Tue Oct 17 09:15:21 2006 +0000
     3.3 @@ -154,7 +154,7 @@
     3.4  #undef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
     3.5  #undef SDL_AUDIO_DRIVER_ARTS
     3.6  #undef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
     3.7 -#undef SDL_AUDIO_DRIVER_BAUDIO
     3.8 +#undef SDL_AUDIO_DRIVER_BEOSAUDIO
     3.9  #undef SDL_AUDIO_DRIVER_BSD
    3.10  #undef SDL_AUDIO_DRIVER_COREAUDIO
    3.11  #undef SDL_AUDIO_DRIVER_DART
    3.12 @@ -168,9 +168,10 @@
    3.13  #undef SDL_AUDIO_DRIVER_MINT
    3.14  #undef SDL_AUDIO_DRIVER_MMEAUDIO
    3.15  #undef SDL_AUDIO_DRIVER_NAS
    3.16 +#undef SDL_AUDIO_DRIVER_NAS_DYNAMIC
    3.17  #undef SDL_AUDIO_DRIVER_OSS
    3.18  #undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H
    3.19 -#undef SDL_AUDIO_DRIVER_PAUD
    3.20 +#undef SDL_AUDIO_DRIVER_PAUDIO
    3.21  #undef SDL_AUDIO_DRIVER_QNXNTO
    3.22  #undef SDL_AUDIO_DRIVER_SNDMGR
    3.23  #undef SDL_AUDIO_DRIVER_SUNAUDIO
     4.1 --- a/include/SDL_thread.h	Sun Oct 01 16:10:41 2006 +0000
     4.2 +++ b/include/SDL_thread.h	Tue Oct 17 09:15:21 2006 +0000
     4.3 @@ -91,7 +91,7 @@
     4.4  typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
     4.5  #endif
     4.6  
     4.7 -extern DECLSPEC SDL_Thread *SDLCALL SDL_CreateThread(int (*fn) (void *),
     4.8 +extern DECLSPEC SDL_Thread *SDLCALL SDL_CreateThread(int (SDLCALL * f) (void *),
     4.9                                                       void *data,
    4.10                                                       pfnSDL_CurrentBeginThread
    4.11                                                       pfnBeginThread,
     5.1 --- a/src/SDL_error.c	Sun Oct 01 16:10:41 2006 +0000
     5.2 +++ b/src/SDL_error.c	Tue Oct 17 09:15:21 2006 +0000
     5.3 @@ -28,6 +28,7 @@
     5.4  
     5.5  /* Routine to get the thread-specific error variable */
     5.6  #if SDL_THREADS_DISABLED
     5.7 +/* !!! FIXME: what does this comment mean? Victim of Search and Replace? */
     5.8  /* The  SDL_arraysize(The ),default (non-thread-safe) global error variable */
     5.9  static SDL_error SDL_global_error;
    5.10  #define SDL_GetErrBuf()	(&SDL_global_error)
     6.1 --- a/src/audio/SDL_audio.c	Sun Oct 01 16:10:41 2006 +0000
     6.2 +++ b/src/audio/SDL_audio.c	Tue Oct 17 09:15:21 2006 +0000
     6.3 @@ -28,11 +28,48 @@
     6.4  #include "SDL_audiomem.h"
     6.5  #include "SDL_sysaudio.h"
     6.6  
     6.7 -#ifdef __OS2__
     6.8 -/* We'll need the DosSetPriority() API! */
     6.9 -#define INCL_DOSPROCESS
    6.10 -#include <os2.h>
    6.11 -#endif
    6.12 +#define _THIS	SDL_AudioDevice *this
    6.13 +
    6.14 +static SDL_AudioDriver current_audio;
    6.15 +static SDL_AudioDevice *open_devices[16];
    6.16 +
    6.17 +/* !!! FIXME: These are wordy and unlocalized... */
    6.18 +#define DEFAULT_OUTPUT_DEVNAME "System audio output device"
    6.19 +#define DEFAULT_INPUT_DEVNAME "System audio capture device"
    6.20 +
    6.21 +
    6.22 +/*
    6.23 + * Not all of these will be compiled and linked in, but it's convenient
    6.24 + *  to have a complete list here and saves yet-another block of #ifdefs...
    6.25 + *  Please see bootstrap[], below, for the actual #ifdef mess.
    6.26 + */
    6.27 +extern AudioBootStrap BSD_AUDIO_bootstrap;
    6.28 +extern AudioBootStrap DSP_bootstrap;
    6.29 +extern AudioBootStrap DMA_bootstrap;
    6.30 +extern AudioBootStrap ALSA_bootstrap;
    6.31 +extern AudioBootStrap QNXNTOAUDIO_bootstrap;
    6.32 +extern AudioBootStrap SUNAUDIO_bootstrap;
    6.33 +extern AudioBootStrap DMEDIA_bootstrap;
    6.34 +extern AudioBootStrap ARTS_bootstrap;
    6.35 +extern AudioBootStrap ESD_bootstrap;
    6.36 +extern AudioBootStrap NAS_bootstrap;
    6.37 +extern AudioBootStrap DSOUND_bootstrap;
    6.38 +extern AudioBootStrap WAVEOUT_bootstrap;
    6.39 +extern AudioBootStrap PAUDIO_bootstrap;
    6.40 +extern AudioBootStrap BEOSAUDIO_bootstrap;
    6.41 +extern AudioBootStrap COREAUDIO_bootstrap;
    6.42 +extern AudioBootStrap SNDMGR_bootstrap;
    6.43 +extern AudioBootStrap MINTAUDIO_GSXB_bootstrap;
    6.44 +extern AudioBootStrap MINTAUDIO_MCSN_bootstrap;
    6.45 +extern AudioBootStrap MINTAUDIO_STFA_bootstrap;
    6.46 +extern AudioBootStrap MINTAUDIO_XBIOS_bootstrap;
    6.47 +extern AudioBootStrap MINTAUDIO_DMA8_bootstrap;
    6.48 +extern AudioBootStrap DISKAUD_bootstrap;
    6.49 +extern AudioBootStrap DUMMYAUD_bootstrap;
    6.50 +extern AudioBootStrap DCAUD_bootstrap;
    6.51 +extern AudioBootStrap MMEAUDIO_bootstrap;
    6.52 +extern AudioBootStrap DART_bootstrap;
    6.53 +
    6.54  
    6.55  /* Available audio drivers */
    6.56  static AudioBootStrap *bootstrap[] = {
    6.57 @@ -70,11 +107,11 @@
    6.58  #if SDL_AUDIO_DRIVER_WAVEOUT
    6.59      &WAVEOUT_bootstrap,
    6.60  #endif
    6.61 -#if SDL_AUDIO_DRIVER_PAUD
    6.62 -    &Paud_bootstrap,
    6.63 +#if SDL_AUDIO_DRIVER_PAUDIO
    6.64 +    &PAUDIO_bootstrap,
    6.65  #endif
    6.66 -#if SDL_AUDIO_DRIVER_BAUDIO
    6.67 -    &BAUDIO_bootstrap,
    6.68 +#if SDL_AUDIO_DRIVER_BEOSAUDIO
    6.69 +    &BEOSAUDIO_bootstrap,
    6.70  #endif
    6.71  #if SDL_AUDIO_DRIVER_COREAUDIO
    6.72      &COREAUDIO_bootstrap,
    6.73 @@ -82,9 +119,6 @@
    6.74  #if SDL_AUDIO_DRIVER_SNDMGR
    6.75      &SNDMGR_bootstrap,
    6.76  #endif
    6.77 -#if SDL_AUDIO_DRIVER_AHI
    6.78 -    &AHI_bootstrap,
    6.79 -#endif
    6.80  #if SDL_AUDIO_DRIVER_MINT
    6.81      &MINTAUDIO_GSXB_bootstrap,
    6.82      &MINTAUDIO_MCSN_bootstrap,
    6.83 @@ -109,227 +143,201 @@
    6.84  #endif
    6.85      NULL
    6.86  };
    6.87 -SDL_AudioDevice *current_audio = NULL;
    6.88  
    6.89 -/* Various local functions */
    6.90 -int SDL_AudioInit(const char *driver_name);
    6.91 -void SDL_AudioQuit(void);
    6.92 +static SDL_AudioDevice *get_audio_device(SDL_AudioDeviceID id)
    6.93 +{
    6.94 +    id--;
    6.95 +    if ( (id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL) ) {
    6.96 +        SDL_SetError("Invalid audio device ID");
    6.97 +        return NULL;
    6.98 +    }
    6.99  
   6.100 -#if SDL_AUDIO_DRIVER_AHI
   6.101 -static int audio_configured = 0;
   6.102 -#endif
   6.103 +    return open_devices[id];
   6.104 +}
   6.105 +
   6.106 +
   6.107 +/* stubs for audio drivers that don't need a specific entry point... */
   6.108 +static int SDL_AudioDetectDevices_Default(int iscapture) { return -1; }
   6.109 +static void SDL_AudioThreadInit_Default(_THIS) { /* no-op. */ }
   6.110 +static void SDL_AudioWaitDevice_Default(_THIS) { /* no-op. */ }
   6.111 +static void SDL_AudioPlayDevice_Default(_THIS) { /* no-op. */ }
   6.112 +static Uint8 *SDL_AudioGetDeviceBuf_Default(_THIS) { return NULL; }
   6.113 +static void SDL_AudioWaitDone_Default(_THIS) { /* no-op. */ }
   6.114 +static void SDL_AudioCloseDevice_Default(_THIS) { /* no-op. */ }
   6.115 +static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ }
   6.116 +
   6.117 +static int
   6.118 +SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
   6.119 +{
   6.120 +    return 0;
   6.121 +}
   6.122 +
   6.123 +static const char *SDL_AudioGetDeviceName_Default(int index, int iscapture)
   6.124 +{
   6.125 +    SDL_SetError("No such device");
   6.126 +    return NULL;
   6.127 +}
   6.128 +
   6.129 +static void
   6.130 +SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
   6.131 +{
   6.132 +    if (device->thread && (SDL_ThreadID() == device->threadid)) {
   6.133 +        return;
   6.134 +    }
   6.135 +    SDL_mutexP(device->mixer_lock);
   6.136 +}
   6.137 +
   6.138 +static void
   6.139 +SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
   6.140 +{
   6.141 +    if (device->thread && (SDL_ThreadID() == device->threadid)) {
   6.142 +        return;
   6.143 +    }
   6.144 +    SDL_mutexV(device->mixer_lock);
   6.145 +}
   6.146 +
   6.147 +
   6.148 +static void finalize_audio_entry_points(void)
   6.149 +{
   6.150 +    /*
   6.151 +     * Fill in stub functions for unused driver entry points. This lets us
   6.152 +     *  blindly call them without having to check for validity first.
   6.153 +     */
   6.154 +
   6.155 +    #define FILL_STUB(x) \
   6.156 +        if (current_audio.impl.x == NULL) { \
   6.157 +            current_audio.impl.x = SDL_Audio##x##_Default; \
   6.158 +        }
   6.159 +    FILL_STUB(DetectDevices);
   6.160 +    FILL_STUB(GetDeviceName);
   6.161 +    FILL_STUB(OpenDevice);
   6.162 +    FILL_STUB(ThreadInit);
   6.163 +    FILL_STUB(WaitDevice);
   6.164 +    FILL_STUB(PlayDevice);
   6.165 +    FILL_STUB(GetDeviceBuf);
   6.166 +    FILL_STUB(WaitDone);
   6.167 +    FILL_STUB(CloseDevice);
   6.168 +    FILL_STUB(LockDevice);
   6.169 +    FILL_STUB(UnlockDevice);
   6.170 +    FILL_STUB(Deinitialize);
   6.171 +    #undef FILL_STUB
   6.172 +}
   6.173 +
   6.174  
   6.175  /* The general mixing thread function */
   6.176  int SDLCALL
   6.177 -SDL_RunAudio(void *audiop)
   6.178 +SDL_RunAudio(void *devicep)
   6.179  {
   6.180 -    SDL_AudioDevice *audio = (SDL_AudioDevice *) audiop;
   6.181 +    SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
   6.182 +    const int legacy_device = (device == open_devices[0]);
   6.183      Uint8 *stream;
   6.184      int stream_len;
   6.185      void *udata;
   6.186      void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
   6.187      int silence;
   6.188 -#if SDL_AUDIO_DRIVER_AHI
   6.189 -    int started = 0;
   6.190 -
   6.191 -/* AmigaOS NEEDS that the audio driver is opened in the thread that uses it! */
   6.192 -
   6.193 -    D(bug("Task audio started audio struct:<%lx>...\n", audiop));
   6.194 -
   6.195 -    D(bug("Before Openaudio..."));
   6.196 -    if (audio->OpenAudio(audio, &audio->spec) == -1) {
   6.197 -        D(bug("Open audio failed...\n"));
   6.198 -        return (-1);
   6.199 -    }
   6.200 -    D(bug("OpenAudio...OK\n"));
   6.201 -#endif
   6.202  
   6.203      /* Perform any thread setup */
   6.204 -    if (audio->ThreadInit) {
   6.205 -        audio->ThreadInit(audio);
   6.206 -    }
   6.207 -    audio->threadid = SDL_ThreadID();
   6.208 +    device->threadid = SDL_ThreadID();
   6.209 +    current_audio.impl.ThreadInit(device);
   6.210  
   6.211      /* Set up the mixing function */
   6.212 -    fill = audio->spec.callback;
   6.213 -    udata = audio->spec.userdata;
   6.214 +    fill = device->spec.callback;
   6.215 +    udata = device->spec.userdata;
   6.216  
   6.217 -#if SDL_AUDIO_DRIVER_AHI
   6.218 -    audio_configured = 1;
   6.219 -
   6.220 -    D(bug("Audio configured... Checking for conversion\n"));
   6.221 -    SDL_mutexP(audio->mixer_lock);
   6.222 -    D(bug("Semaphore obtained...\n"));
   6.223 -#endif
   6.224 -
   6.225 -    if (audio->convert.needed) {
   6.226 -        if (audio->convert.src_format == AUDIO_U8) {
   6.227 +    if (device->convert.needed) {
   6.228 +        if (device->convert.src_format == AUDIO_U8) {
   6.229              silence = 0x80;
   6.230          } else {
   6.231              silence = 0;
   6.232          }
   6.233 -        stream_len = audio->convert.len;
   6.234 +        stream_len = device->convert.len;
   6.235      } else {
   6.236 -        silence = audio->spec.silence;
   6.237 -        stream_len = audio->spec.size;
   6.238 +        silence = device->spec.silence;
   6.239 +        stream_len = device->spec.size;
   6.240      }
   6.241  
   6.242 -#if SDL_AUDIO_DRIVER_AHI
   6.243 -    SDL_mutexV(audio->mixer_lock);
   6.244 -    D(bug("Entering audio loop...\n"));
   6.245 -#endif
   6.246 -
   6.247 -#ifdef __OS2__
   6.248 -    /* Increase the priority of this thread to make sure that
   6.249 -       the audio will be continuous all the time! */
   6.250 -#ifdef USE_DOSSETPRIORITY
   6.251 -    if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) {
   6.252 -#ifdef DEBUG_BUILD
   6.253 -        printf
   6.254 -            ("[SDL_RunAudio] : Setting priority to TimeCritical+0! (TID%d)\n",
   6.255 -             SDL_ThreadID());
   6.256 -#endif
   6.257 -        DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
   6.258 -    } else {
   6.259 -#ifdef DEBUG_BUILD
   6.260 -        printf
   6.261 -            ("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n",
   6.262 -             SDL_ThreadID());
   6.263 -#endif
   6.264 -        DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
   6.265 -    }
   6.266 -#endif
   6.267 -#endif
   6.268 -
   6.269      /* Loop, filling the audio buffers */
   6.270 -    while (audio->enabled) {
   6.271 +    while (device->enabled) {
   6.272  
   6.273          /* Fill the current buffer with sound */
   6.274 -        if (audio->convert.needed) {
   6.275 -            if (audio->convert.buf) {
   6.276 -                stream = audio->convert.buf;
   6.277 +        if (device->convert.needed) {
   6.278 +            if (device->convert.buf) {
   6.279 +                stream = device->convert.buf;
   6.280              } else {
   6.281                  continue;
   6.282              }
   6.283          } else {
   6.284 -            stream = audio->GetAudioBuf(audio);
   6.285 +            stream = current_audio.impl.GetDeviceBuf(device);
   6.286              if (stream == NULL) {
   6.287 -                stream = audio->fake_stream;
   6.288 +                stream = device->fake_stream;
   6.289              }
   6.290          }
   6.291 -        SDL_memset(stream, silence, stream_len);
   6.292  
   6.293 -        if (!audio->paused) {
   6.294 -            SDL_mutexP(audio->mixer_lock);
   6.295 +        /* New code should fill buffer or set it to silence themselves. */
   6.296 +        if (legacy_device) {
   6.297 +            SDL_memset(stream, silence, stream_len);
   6.298 +        }
   6.299 +
   6.300 +        if (!device->paused) {
   6.301 +            SDL_mutexP(device->mixer_lock);
   6.302              (*fill) (udata, stream, stream_len);
   6.303 -            SDL_mutexV(audio->mixer_lock);
   6.304 +            SDL_mutexV(device->mixer_lock);
   6.305          }
   6.306  
   6.307          /* Convert the audio if necessary */
   6.308 -        if (audio->convert.needed) {
   6.309 -            SDL_ConvertAudio(&audio->convert);
   6.310 -            stream = audio->GetAudioBuf(audio);
   6.311 +        if (device->convert.needed) {
   6.312 +            SDL_ConvertAudio(&device->convert);
   6.313 +            stream = current_audio.impl.GetDeviceBuf(device);
   6.314              if (stream == NULL) {
   6.315 -                stream = audio->fake_stream;
   6.316 +                stream = device->fake_stream;
   6.317              }
   6.318 -            SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt);
   6.319 +            SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt);
   6.320          }
   6.321  
   6.322          /* Ready current buffer for play and change current buffer */
   6.323 -        if (stream != audio->fake_stream) {
   6.324 -            audio->PlayAudio(audio);
   6.325 +        if (stream != device->fake_stream) {
   6.326 +            current_audio.impl.PlayDevice(device);
   6.327          }
   6.328  
   6.329          /* Wait for an audio buffer to become available */
   6.330 -        if (stream == audio->fake_stream) {
   6.331 -            SDL_Delay((audio->spec.samples * 1000) / audio->spec.freq);
   6.332 +        if (stream == device->fake_stream) {
   6.333 +            SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
   6.334          } else {
   6.335 -            audio->WaitAudio(audio);
   6.336 +            current_audio.impl.WaitDevice(device);
   6.337          }
   6.338      }
   6.339  
   6.340      /* Wait for the audio to drain.. */
   6.341 -    if (audio->WaitDone) {
   6.342 -        audio->WaitDone(audio);
   6.343 -    }
   6.344 -#if SDL_AUDIO_DRIVER_AHI
   6.345 -    D(bug("WaitAudio...Done\n"));
   6.346 +    current_audio.impl.WaitDone(device);
   6.347  
   6.348 -    audio->CloseAudio(audio);
   6.349 -
   6.350 -    D(bug("CloseAudio..Done, subtask exiting...\n"));
   6.351 -    audio_configured = 0;
   6.352 -#endif
   6.353 -#ifdef __OS2__
   6.354 -#ifdef DEBUG_BUILD
   6.355 -    printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID());
   6.356 -#endif
   6.357 -#endif
   6.358      return (0);
   6.359  }
   6.360  
   6.361 -static void
   6.362 -SDL_LockAudio_Default(SDL_AudioDevice * audio)
   6.363 -{
   6.364 -    if (audio->thread && (SDL_ThreadID() == audio->threadid)) {
   6.365 -        return;
   6.366 -    }
   6.367 -    SDL_mutexP(audio->mixer_lock);
   6.368 -}
   6.369 -
   6.370 -static void
   6.371 -SDL_UnlockAudio_Default(SDL_AudioDevice * audio)
   6.372 -{
   6.373 -    if (audio->thread && (SDL_ThreadID() == audio->threadid)) {
   6.374 -        return;
   6.375 -    }
   6.376 -    SDL_mutexV(audio->mixer_lock);
   6.377 -}
   6.378  
   6.379  static SDL_AudioFormat
   6.380  SDL_ParseAudioFormat(const char *string)
   6.381  {
   6.382 -    SDL_AudioFormat format = 0;
   6.383 -
   6.384 -    switch (*string) {
   6.385 -    case 'U':
   6.386 -        ++string;
   6.387 -        format |= 0x0000;
   6.388 -        break;
   6.389 -    case 'S':
   6.390 -        ++string;
   6.391 -        format |= 0x8000;
   6.392 -        break;
   6.393 -    default:
   6.394 -        return 0;
   6.395 -    }
   6.396 -    switch (SDL_atoi(string)) {
   6.397 -    case 8:
   6.398 -        string += 1;
   6.399 -        format |= 8;
   6.400 -        break;
   6.401 -    case 16:
   6.402 -        string += 2;
   6.403 -        format |= 16;
   6.404 -        if (SDL_strcmp(string, "LSB") == 0
   6.405 -#if SDL_BYTEORDER == SDL_LIL_ENDIAN
   6.406 -            || SDL_strcmp(string, "SYS") == 0
   6.407 -#endif
   6.408 -            ) {
   6.409 -            format |= 0x0000;
   6.410 -        }
   6.411 -        if (SDL_strcmp(string, "MSB") == 0
   6.412 -#if SDL_BYTEORDER == SDL_BIG_ENDIAN
   6.413 -            || SDL_strcmp(string, "SYS") == 0
   6.414 -#endif
   6.415 -            ) {
   6.416 -            format |= 0x1000;
   6.417 -        }
   6.418 -        break;
   6.419 -    default:
   6.420 -        return 0;
   6.421 -    }
   6.422 -    return format;
   6.423 +    #define CHECK_FMT_STRING(x) if (strcmp(string, #x) == 0) return AUDIO_##x
   6.424 +    CHECK_FMT_STRING(U8);
   6.425 +    CHECK_FMT_STRING(S8);
   6.426 +    CHECK_FMT_STRING(U16LSB);
   6.427 +    CHECK_FMT_STRING(S16LSB);
   6.428 +    CHECK_FMT_STRING(U16MSB);
   6.429 +    CHECK_FMT_STRING(S16MSB);
   6.430 +    CHECK_FMT_STRING(U16SYS);
   6.431 +    CHECK_FMT_STRING(S16SYS);
   6.432 +    CHECK_FMT_STRING(U16);
   6.433 +    CHECK_FMT_STRING(S16);
   6.434 +    CHECK_FMT_STRING(S32LSB);
   6.435 +    CHECK_FMT_STRING(S32MSB);
   6.436 +    CHECK_FMT_STRING(S32SYS);
   6.437 +    CHECK_FMT_STRING(S32);
   6.438 +    CHECK_FMT_STRING(F32LSB);
   6.439 +    CHECK_FMT_STRING(F32MSB);
   6.440 +    CHECK_FMT_STRING(F32SYS);
   6.441 +    CHECK_FMT_STRING(F32);
   6.442 +    #undef CHECK_FMT_STRING
   6.443 +    return 0;
   6.444  }
   6.445  
   6.446  int
   6.447 @@ -350,92 +358,53 @@
   6.448  int
   6.449  SDL_AudioInit(const char *driver_name)
   6.450  {
   6.451 -    SDL_AudioDevice *audio;
   6.452 -    int i = 0, idx;
   6.453 +    int i = 0;
   6.454 +    int initialized = 0;
   6.455 +    int tried_to_init = 0;
   6.456  
   6.457 -    /* Check to make sure we don't overwrite 'current_audio' */
   6.458 -    if (current_audio != NULL) {
   6.459 -        SDL_AudioQuit();
   6.460 +    if (SDL_WasInit(SDL_INIT_AUDIO)) {
   6.461 +        SDL_AudioQuit();  /* shutdown driver if already running. */
   6.462      }
   6.463  
   6.464 +    SDL_memset(&current_audio, '\0', sizeof (current_audio));
   6.465 +    SDL_memset(open_devices, '\0', sizeof (open_devices));
   6.466 +
   6.467      /* Select the proper audio driver */
   6.468 -    audio = NULL;
   6.469 -    idx = 0;
   6.470      if (driver_name == NULL) {
   6.471          driver_name = SDL_getenv("SDL_AUDIODRIVER");
   6.472      }
   6.473 -#if SDL_AUDIO_DRIVER_ESD
   6.474 -    if ((driver_name == NULL) && (SDL_getenv("ESPEAKER") != NULL)) {
   6.475 -        /* Ahem, we know that if ESPEAKER is set, user probably wants
   6.476 -           to use ESD, but don't start it if it's not already running.
   6.477 -           This probably isn't the place to do this, but... Shh! :)
   6.478 -         */
   6.479 -        for (i = 0; bootstrap[i]; ++i) {
   6.480 -            if (SDL_strcasecmp(bootstrap[i]->name, "esd") == 0) {
   6.481 -#ifdef HAVE_PUTENV
   6.482 -                const char *esd_no_spawn;
   6.483  
   6.484 -                /* Don't start ESD if it's not running */
   6.485 -                esd_no_spawn = getenv("ESD_NO_SPAWN");
   6.486 -                if (esd_no_spawn == NULL) {
   6.487 -                    putenv("ESD_NO_SPAWN=1");
   6.488 -                }
   6.489 -#endif
   6.490 -                if (bootstrap[i]->available()) {
   6.491 -                    audio = bootstrap[i]->create(0);
   6.492 -                    break;
   6.493 -                }
   6.494 -#ifdef HAVE_UNSETENV
   6.495 -                if (esd_no_spawn == NULL) {
   6.496 -                    unsetenv("ESD_NO_SPAWN");
   6.497 -                }
   6.498 -#endif
   6.499 -            }
   6.500 +    for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
   6.501 +        /* make sure we should even try this driver before doing so... */
   6.502 +        const AudioBootStrap *backend = bootstrap[i];
   6.503 +        if ( ((driver_name) && (SDL_strcasecmp(backend->name, driver_name))) ||
   6.504 +             ((!driver_name) && (backend->demand_only)) ) {
   6.505 +            continue;
   6.506          }
   6.507 +
   6.508 +        tried_to_init = 1;
   6.509 +        SDL_memset(&current_audio, 0, sizeof (current_audio));
   6.510 +        current_audio.name = backend->name;
   6.511 +        current_audio.desc = backend->desc;
   6.512 +        initialized = backend->init(&current_audio.impl);
   6.513      }
   6.514 -#endif /* SDL_AUDIO_DRIVER_ESD */
   6.515 -    if (audio == NULL) {
   6.516 -        if (driver_name != NULL) {
   6.517 -            for (i = 0; bootstrap[i]; ++i) {
   6.518 -                if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) {
   6.519 -                    if (bootstrap[i]->available()) {
   6.520 -                        audio = bootstrap[i]->create(idx);
   6.521 -                    }
   6.522 -                    break;
   6.523 -                }
   6.524 -            }
   6.525 -        } else {
   6.526 -            for (i = 0; bootstrap[i]; ++i) {
   6.527 -                if (bootstrap[i]->available()) {
   6.528 -                    audio = bootstrap[i]->create(idx);
   6.529 -                    if (audio != NULL) {
   6.530 -                        break;
   6.531 -                    }
   6.532 -                }
   6.533 -            }
   6.534 -        }
   6.535 -        if (audio == NULL) {
   6.536 +
   6.537 +    if (!initialized) {
   6.538 +        /* specific drivers will set the error message if they fail... */
   6.539 +        if (!tried_to_init) {
   6.540              if (driver_name) {
   6.541                  SDL_SetError("%s not available", driver_name);
   6.542              } else {
   6.543                  SDL_SetError("No available audio device");
   6.544              }
   6.545 -#if 0
   6.546 -            /* Don't fail SDL_Init() if audio isn't available.
   6.547 -               SDL_OpenAudio() will handle it at that point.  *sigh*
   6.548 -             */
   6.549 -            return (-1);
   6.550 -#endif
   6.551          }
   6.552 +
   6.553 +        SDL_memset(&current_audio, 0, sizeof (current_audio));
   6.554 +        return (-1);  /* No driver was available, so fail. */
   6.555      }
   6.556 -    current_audio = audio;
   6.557 -    if (current_audio) {
   6.558 -        current_audio->name = bootstrap[i]->name;
   6.559 -        if (!current_audio->LockAudio && !current_audio->UnlockAudio) {
   6.560 -            current_audio->LockAudio = SDL_LockAudio_Default;
   6.561 -            current_audio->UnlockAudio = SDL_UnlockAudio_Default;
   6.562 -        }
   6.563 -    }
   6.564 +
   6.565 +    finalize_audio_entry_points();
   6.566 +
   6.567      return (0);
   6.568  }
   6.569  
   6.570 @@ -445,222 +414,369 @@
   6.571  const char *
   6.572  SDL_GetCurrentAudioDriver()
   6.573  {
   6.574 -    if (current_audio) {
   6.575 -        return current_audio->name;
   6.576 -    }
   6.577 -    return (NULL);
   6.578 +    return current_audio.name;
   6.579  }
   6.580  
   6.581 +
   6.582  int
   6.583 -SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
   6.584 +SDL_GetNumAudioDevices(int iscapture)
   6.585  {
   6.586 -    SDL_AudioDevice *audio;
   6.587 -    const char *env;
   6.588 +    if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   6.589 +        return -1;
   6.590 +    }
   6.591 +    if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   6.592 +        return 0;
   6.593 +    }
   6.594  
   6.595 -    /* Start up the audio driver, if necessary */
   6.596 -    if (!current_audio) {
   6.597 -        if ((SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) ||
   6.598 -            (current_audio == NULL)) {
   6.599 -            return (-1);
   6.600 +    if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
   6.601 +        return 1;
   6.602 +    }
   6.603 +
   6.604 +    if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   6.605 +        return 1;
   6.606 +    }
   6.607 +
   6.608 +    return current_audio.impl.DetectDevices(iscapture);
   6.609 +}
   6.610 +
   6.611 +
   6.612 +const char *
   6.613 +SDL_GetAudioDeviceName(int index, int iscapture)
   6.614 +{
   6.615 +    if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   6.616 +        SDL_SetError("Audio subsystem is not initialized");
   6.617 +        return NULL;
   6.618 +    }
   6.619 +
   6.620 +    if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   6.621 +        SDL_SetError("No capture support");
   6.622 +        return NULL;
   6.623 +    }
   6.624 +
   6.625 +    if (index < 0) {
   6.626 +        SDL_SetError("No such device");
   6.627 +        return NULL;
   6.628 +    }
   6.629 +
   6.630 +    if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
   6.631 +        return DEFAULT_INPUT_DEVNAME;
   6.632 +    }
   6.633 +
   6.634 +    if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   6.635 +        return DEFAULT_OUTPUT_DEVNAME;
   6.636 +    }
   6.637 +
   6.638 +    return current_audio.impl.GetDeviceName(index, iscapture);
   6.639 +}
   6.640 +
   6.641 +
   6.642 +static void
   6.643 +close_audio_device(SDL_AudioDevice *device)
   6.644 +{
   6.645 +    device->enabled = 0;
   6.646 +    if (device->thread != NULL) {
   6.647 +        SDL_WaitThread(device->thread, NULL);
   6.648 +    }
   6.649 +    if (device->mixer_lock != NULL) {
   6.650 +        SDL_DestroyMutex(device->mixer_lock);
   6.651 +    }
   6.652 +    if (device->fake_stream != NULL) {
   6.653 +        SDL_FreeAudioMem(device->fake_stream);
   6.654 +    }
   6.655 +    if (device->convert.needed) {
   6.656 +        SDL_FreeAudioMem(device->convert.buf);
   6.657 +    }
   6.658 +    if (device->opened) {
   6.659 +        current_audio.impl.CloseDevice(device);
   6.660 +        device->opened = 0;
   6.661 +    }
   6.662 +    SDL_FreeAudioMem(device);
   6.663 +}
   6.664 +
   6.665 +
   6.666 +/*
   6.667 + * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
   6.668 + *  Fills in a sanitized copy in (prepared).
   6.669 + *  Returns non-zero if okay, zero on fatal parameters in (orig).
   6.670 + */
   6.671 +static int
   6.672 +prepare_audiospec(const SDL_AudioSpec *orig, SDL_AudioSpec *prepared)
   6.673 +{
   6.674 +    SDL_memcpy(prepared, orig, sizeof (SDL_AudioSpec));
   6.675 +
   6.676 +    if (orig->callback == NULL) {
   6.677 +        SDL_SetError("SDL_OpenAudio() passed a NULL callback");
   6.678 +        return 0;
   6.679 +    }
   6.680 +
   6.681 +    if (orig->freq == 0) {
   6.682 +        const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
   6.683 +        if ( (!env) || ((prepared->freq = SDL_atoi(env)) == 0) ) {
   6.684 +            prepared->freq = 22050;  /* a reasonable default */
   6.685          }
   6.686      }
   6.687 -    audio = current_audio;
   6.688  
   6.689 -    if (audio->opened) {
   6.690 -        SDL_SetError("Audio device is already opened");
   6.691 -        return (-1);
   6.692 +    if (orig->format == 0) {
   6.693 +        const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
   6.694 +        if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
   6.695 +            prepared->format = AUDIO_S16;  /* a reasonable default */
   6.696 +        }
   6.697      }
   6.698  
   6.699 -    /* Verify some parameters */
   6.700 -    if (desired->freq == 0) {
   6.701 -        env = SDL_getenv("SDL_AUDIO_FREQUENCY");
   6.702 -        if (env) {
   6.703 -            desired->freq = SDL_atoi(env);
   6.704 +    switch (orig->channels) {
   6.705 +    case 0: {
   6.706 +        const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
   6.707 +        if ( (!env) || ((prepared->channels = SDL_atoi(env)) == 0) ) {
   6.708 +            prepared->channels = 2;  /* a reasonable default */
   6.709          }
   6.710 +        break;
   6.711      }
   6.712 -    if (desired->freq == 0) {
   6.713 -        /* Pick some default audio frequency */
   6.714 -        desired->freq = 22050;
   6.715 -    }
   6.716 -    if (desired->format == 0) {
   6.717 -        env = SDL_getenv("SDL_AUDIO_FORMAT");
   6.718 -        if (env) {
   6.719 -            desired->format = SDL_ParseAudioFormat(env);
   6.720 -        }
   6.721 -    }
   6.722 -    if (desired->format == 0) {
   6.723 -        /* Pick some default audio format */
   6.724 -        desired->format = AUDIO_S16;
   6.725 -    }
   6.726 -    if (desired->channels == 0) {
   6.727 -        env = SDL_getenv("SDL_AUDIO_CHANNELS");
   6.728 -        if (env) {
   6.729 -            desired->channels = (Uint8) SDL_atoi(env);
   6.730 -        }
   6.731 -    }
   6.732 -    if (desired->channels == 0) {
   6.733 -        /* Pick a default number of channels */
   6.734 -        desired->channels = 2;
   6.735 -    }
   6.736 -    switch (desired->channels) {
   6.737      case 1:                    /* Mono */
   6.738      case 2:                    /* Stereo */
   6.739      case 4:                    /* surround */
   6.740      case 6:                    /* surround with center and lfe */
   6.741          break;
   6.742      default:
   6.743 -        SDL_SetError("1 (mono) and 2 (stereo) channels supported");
   6.744 -        return (-1);
   6.745 +        SDL_SetError("Unsupported number of audio channels.");
   6.746 +        return 0;
   6.747      }
   6.748 -    if (desired->samples == 0) {
   6.749 -        env = SDL_getenv("SDL_AUDIO_SAMPLES");
   6.750 -        if (env) {
   6.751 -            desired->samples = (Uint16) SDL_atoi(env);
   6.752 +
   6.753 +    if (orig->samples == 0) {
   6.754 +        const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
   6.755 +        if ( (!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0) ) {
   6.756 +            /* Pick a default of ~46 ms at desired frequency */
   6.757 +            /* !!! FIXME: remove this when the non-Po2 resampling is in. */
   6.758 +            const int samples = (prepared->freq / 1000) * 46;
   6.759 +            int power2 = 1;
   6.760 +            while (power2 < samples) {
   6.761 +                power2 *= 2;
   6.762 +            }
   6.763 +            prepared->samples = power2;
   6.764          }
   6.765      }
   6.766 -    if (desired->samples == 0) {
   6.767 -        /* Pick a default of ~46 ms at desired frequency */
   6.768 -        int samples = (desired->freq / 1000) * 46;
   6.769 -        int power2 = 1;
   6.770 -        while (power2 < samples) {
   6.771 -            power2 *= 2;
   6.772 -        }
   6.773 -        desired->samples = power2;
   6.774 -    }
   6.775 -    if (desired->callback == NULL) {
   6.776 -        SDL_SetError("SDL_OpenAudio() passed a NULL callback");
   6.777 -        return (-1);
   6.778 -    }
   6.779 -#if defined(__MINT__) && SDL_THREADS_DISABLED
   6.780 -    /* Uses interrupt driven audio, without thread */
   6.781 -#else
   6.782 -    /* Create a semaphore for locking the sound buffers */
   6.783 -    audio->mixer_lock = SDL_CreateMutex();
   6.784 -    if (audio->mixer_lock == NULL) {
   6.785 -        SDL_SetError("Couldn't create mixer lock");
   6.786 -        SDL_CloseAudio();
   6.787 -        return (-1);
   6.788 -    }
   6.789 -#endif /* __MINT__ */
   6.790  
   6.791      /* Calculate the silence and size of the audio specification */
   6.792 -    SDL_CalculateAudioSpec(desired);
   6.793 +    SDL_CalculateAudioSpec(prepared);
   6.794  
   6.795 -    /* Open the audio subsystem */
   6.796 -    SDL_memcpy(&audio->spec, desired, sizeof(audio->spec));
   6.797 -    audio->convert.needed = 0;
   6.798 -    audio->enabled = 1;
   6.799 -    audio->paused = 1;
   6.800 +    return 1;
   6.801 +}
   6.802  
   6.803 -#if !SDL_AUDIO_DRIVER_AHI
   6.804  
   6.805 -/* AmigaOS opens audio inside the main loop */
   6.806 -    audio->opened = audio->OpenAudio(audio, &audio->spec) + 1;
   6.807 +static SDL_AudioDeviceID
   6.808 +open_audio_device(const char *devname, int iscapture,
   6.809 +                    const SDL_AudioSpec *_desired, SDL_AudioSpec *obtained,
   6.810 +                    int min_id)
   6.811 +{
   6.812 +    SDL_AudioDeviceID id = 0;
   6.813 +    SDL_AudioSpec desired;
   6.814 +    SDL_AudioDevice *device;
   6.815 +    int i = 0;
   6.816  
   6.817 -    if (!audio->opened) {
   6.818 -        SDL_CloseAudio();
   6.819 -        return (-1);
   6.820 -    }
   6.821 -#else
   6.822 -    D(bug("Locking semaphore..."));
   6.823 -    SDL_mutexP(audio->mixer_lock);
   6.824 -
   6.825 -
   6.826 -    audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
   6.827 -    D(bug("Created thread...\n"));
   6.828 -
   6.829 -    if (audio->thread == NULL) {
   6.830 -        SDL_mutexV(audio->mixer_lock);
   6.831 -        SDL_CloseAudio();
   6.832 -        SDL_SetError("Couldn't create audio thread");
   6.833 -        return (-1);
   6.834 +    if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   6.835 +        SDL_SetError("Audio subsystem is not initialized");
   6.836 +        return 0;
   6.837      }
   6.838  
   6.839 -    while (!audio_configured)
   6.840 -        SDL_Delay(100);
   6.841 -#endif
   6.842 +    if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   6.843 +        SDL_SetError("No capture support");
   6.844 +        return 0;
   6.845 +    }
   6.846 +
   6.847 +    if (!prepare_audiospec(_desired, &desired)) {
   6.848 +        return 0;
   6.849 +    }
   6.850 +
   6.851 +    /* If app doesn't care about a specific device, let the user override. */
   6.852 +    if (devname == NULL) {
   6.853 +        devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
   6.854 +    }
   6.855 +
   6.856 +    /*
   6.857 +     * Catch device names at the high level for the simple case...
   6.858 +     * This lets us have a basic "device enumeration" for systems that
   6.859 +     *  don't have multiple devices, but makes sure the device name is
   6.860 +     *  always NULL when it hits the low level.
   6.861 +     *
   6.862 +     * Also make sure that the simple case prevents multiple simultaneous
   6.863 +     *  opens of the default system device.
   6.864 +     */
   6.865 +
   6.866 +    if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
   6.867 +        if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
   6.868 +            SDL_SetError("No such device");
   6.869 +            return 0;
   6.870 +        }
   6.871 +        devname = NULL;
   6.872 +
   6.873 +        for (i = 0; i < SDL_arraysize(open_devices); i++) {
   6.874 +            if ((open_devices[i]) && (open_devices[i]->iscapture)) {
   6.875 +                SDL_SetError("Audio device already open");
   6.876 +                return 0;
   6.877 +            }
   6.878 +        }
   6.879 +    }
   6.880 +
   6.881 +    if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   6.882 +        if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
   6.883 +            SDL_SetError("No such device");
   6.884 +            return 0;
   6.885 +        }
   6.886 +        devname = NULL;
   6.887 +
   6.888 +        for (i = 0; i < SDL_arraysize(open_devices); i++) {
   6.889 +            if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
   6.890 +                SDL_SetError("Audio device already open");
   6.891 +                return 0;
   6.892 +            }
   6.893 +        }
   6.894 +    }
   6.895 +
   6.896 +    device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof (SDL_AudioDevice));
   6.897 +    if (device == NULL) {
   6.898 +        SDL_OutOfMemory();
   6.899 +        return 0;
   6.900 +    }
   6.901 +    SDL_memset(device, '\0', sizeof (SDL_AudioDevice));
   6.902 +    SDL_memcpy(&device->spec, &desired, sizeof (SDL_AudioSpec));
   6.903 +    device->enabled = 1;
   6.904 +    device->paused = 1;
   6.905 +    device->iscapture = iscapture;
   6.906 +
   6.907 +    /* Create a semaphore for locking the sound buffers */
   6.908 +    if (!current_audio.impl.SkipMixerLock) {
   6.909 +        device->mixer_lock = SDL_CreateMutex();
   6.910 +        if (device->mixer_lock == NULL) {
   6.911 +            close_audio_device(device);
   6.912 +            SDL_SetError("Couldn't create mixer lock");
   6.913 +            return 0;
   6.914 +        }
   6.915 +    }
   6.916 +
   6.917 +    if (!current_audio.impl.OpenDevice(device, devname, iscapture)) {
   6.918 +        close_audio_device(device);
   6.919 +        return 0;
   6.920 +    }
   6.921 +    device->opened = 1;
   6.922  
   6.923      /* If the audio driver changes the buffer size, accept it */
   6.924 -    if (audio->spec.samples != desired->samples) {
   6.925 -        desired->samples = audio->spec.samples;
   6.926 -        SDL_CalculateAudioSpec(desired);
   6.927 +    if (device->spec.samples != desired.samples) {
   6.928 +        desired.samples = device->spec.samples;
   6.929 +        SDL_CalculateAudioSpec(&device->spec);
   6.930      }
   6.931  
   6.932      /* Allocate a fake audio memory buffer */
   6.933 -    audio->fake_stream = SDL_AllocAudioMem(audio->spec.size);
   6.934 -    if (audio->fake_stream == NULL) {
   6.935 -        SDL_CloseAudio();
   6.936 +    device->fake_stream = SDL_AllocAudioMem(device->spec.size);
   6.937 +    if (device->fake_stream == NULL) {
   6.938 +        close_audio_device(device);
   6.939          SDL_OutOfMemory();
   6.940 -        return (-1);
   6.941 +        return 0;
   6.942      }
   6.943  
   6.944      /* See if we need to do any conversion */
   6.945      if (obtained != NULL) {
   6.946 -        SDL_memcpy(obtained, &audio->spec, sizeof(audio->spec));
   6.947 -    } else if (desired->freq != audio->spec.freq ||
   6.948 -               desired->format != audio->spec.format ||
   6.949 -               desired->channels != audio->spec.channels) {
   6.950 +        SDL_memcpy(obtained, &device->spec, sizeof(SDL_AudioSpec));
   6.951 +    } else if (desired.freq != device->spec.freq ||
   6.952 +               desired.format != device->spec.format ||
   6.953 +               desired.channels != device->spec.channels) {
   6.954          /* Build an audio conversion block */
   6.955 -        if (SDL_BuildAudioCVT(&audio->convert,
   6.956 -                              desired->format, desired->channels,
   6.957 -                              desired->freq,
   6.958 -                              audio->spec.format, audio->spec.channels,
   6.959 -                              audio->spec.freq) < 0) {
   6.960 -            SDL_CloseAudio();
   6.961 -            return (-1);
   6.962 +        if (SDL_BuildAudioCVT(&device->convert,
   6.963 +                              desired.format, desired.channels,
   6.964 +                              desired.freq,
   6.965 +                              device->spec.format, device->spec.channels,
   6.966 +                              device->spec.freq) < 0) {
   6.967 +            close_audio_device(device);
   6.968 +            return 0;
   6.969          }
   6.970 -        if (audio->convert.needed) {
   6.971 -            audio->convert.len = desired->size;
   6.972 -            audio->convert.buf =
   6.973 -                (Uint8 *) SDL_AllocAudioMem(audio->convert.len *
   6.974 -                                            audio->convert.len_mult);
   6.975 -            if (audio->convert.buf == NULL) {
   6.976 -                SDL_CloseAudio();
   6.977 +        if (device->convert.needed) {
   6.978 +            device->convert.len = desired.size;
   6.979 +            device->convert.buf =
   6.980 +                (Uint8 *) SDL_AllocAudioMem(device->convert.len *
   6.981 +                                            device->convert.len_mult);
   6.982 +            if (device->convert.buf == NULL) {
   6.983 +                close_audio_device(device);
   6.984                  SDL_OutOfMemory();
   6.985 -                return (-1);
   6.986 +                return 0;
   6.987              }
   6.988          }
   6.989      }
   6.990 -#if !SDL_AUDIO_DRIVER_AHI
   6.991 +
   6.992 +    /* Find an available device ID and store the structure... */
   6.993 +    for (id = min_id-1; id < SDL_arraysize(open_devices); id++) {
   6.994 +        if (open_devices[id] == NULL) {
   6.995 +            open_devices[id] = device;
   6.996 +            break;
   6.997 +        }
   6.998 +    }
   6.999 +
  6.1000 +    if (id == SDL_arraysize(open_devices)) {
  6.1001 +        SDL_SetError("Too many open audio devices");
  6.1002 +        close_audio_device(device);
  6.1003 +        return 0;
  6.1004 +    }
  6.1005 +
  6.1006      /* Start the audio thread if necessary */
  6.1007 -    switch (audio->opened) {
  6.1008 -    case 1:
  6.1009 +    if (!current_audio.impl.ProvidesOwnCallbackThread) {
  6.1010          /* Start the audio thread */
  6.1011 +/* !!! FIXME: this is nasty. */
  6.1012  #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC)
  6.1013  #undef SDL_CreateThread
  6.1014 -        audio->thread = SDL_CreateThread(SDL_RunAudio, audio, NULL, NULL);
  6.1015 +        device->thread = SDL_CreateThread(SDL_RunAudio, device, NULL, NULL);
  6.1016  #else
  6.1017 -        audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
  6.1018 +        device->thread = SDL_CreateThread(SDL_RunAudio, device);
  6.1019  #endif
  6.1020 -        if (audio->thread == NULL) {
  6.1021 -            SDL_CloseAudio();
  6.1022 +        if (device->thread == NULL) {
  6.1023 +            SDL_CloseAudioDevice(id+1);
  6.1024              SDL_SetError("Couldn't create audio thread");
  6.1025 +            return 0;
  6.1026 +        }
  6.1027 +    }
  6.1028 +
  6.1029 +    return id+1;
  6.1030 +}
  6.1031 +
  6.1032 +
  6.1033 +int
  6.1034 +SDL_OpenAudio(const SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
  6.1035 +{
  6.1036 +    SDL_AudioDeviceID id = 0;
  6.1037 +
  6.1038 +    /* Start up the audio driver, if necessary. This is legacy behaviour! */
  6.1039 +    if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  6.1040 +        if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
  6.1041              return (-1);
  6.1042          }
  6.1043 -        break;
  6.1044 +    }
  6.1045  
  6.1046 -    default:
  6.1047 -        /* The audio is now playing */
  6.1048 -        break;
  6.1049 +    /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
  6.1050 +    if (open_devices[0] != NULL) {
  6.1051 +        SDL_SetError("Audio device is already opened");
  6.1052 +        return (-1);
  6.1053      }
  6.1054 -#else
  6.1055 -    SDL_mutexV(audio->mixer_lock);
  6.1056 -    D(bug("SDL_OpenAudio USCITA...\n"));
  6.1057  
  6.1058 -#endif
  6.1059 +    id = open_audio_device(NULL, 0, desired, obtained, 1);
  6.1060 +    if (id > 1) {  /* this should never happen in theory... */
  6.1061 +        SDL_CloseAudioDevice(id);
  6.1062 +        SDL_SetError("Internal error");  /* MUST be Device ID #1! */
  6.1063 +        return (-1);
  6.1064 +    }
  6.1065  
  6.1066 -    return (0);
  6.1067 +    return ((id == 0) ? -1 : 0);
  6.1068 +}
  6.1069 +
  6.1070 +SDL_AudioDeviceID
  6.1071 +SDL_OpenAudioDevice(const char *device, int iscapture,
  6.1072 +                    const SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
  6.1073 +{
  6.1074 +    return open_audio_device(device, iscapture, desired, obtained, 2);
  6.1075  }
  6.1076  
  6.1077  SDL_audiostatus
  6.1078 -SDL_GetAudioStatus(void)
  6.1079 +SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
  6.1080  {
  6.1081 -    SDL_AudioDevice *audio = current_audio;
  6.1082 -    SDL_audiostatus status;
  6.1083 -
  6.1084 -    status = SDL_AUDIO_STOPPED;
  6.1085 -    if (audio && audio->enabled) {
  6.1086 -        if (audio->paused) {
  6.1087 +    SDL_AudioDevice *device = get_audio_device(devid);
  6.1088 +    SDL_audiostatus status = SDL_AUDIO_STOPPED;
  6.1089 +    if (device && device->enabled) {
  6.1090 +        if (device->paused) {
  6.1091              status = SDL_AUDIO_PAUSED;
  6.1092          } else {
  6.1093              status = SDL_AUDIO_PLAYING;
  6.1094 @@ -669,74 +785,89 @@
  6.1095      return (status);
  6.1096  }
  6.1097  
  6.1098 +
  6.1099 +SDL_audiostatus
  6.1100 +SDL_GetAudioStatus(void)
  6.1101 +{
  6.1102 +    return SDL_GetAudioDeviceStatus(1);
  6.1103 +}
  6.1104 +
  6.1105 +void
  6.1106 +SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
  6.1107 +{
  6.1108 +    SDL_AudioDevice *device = get_audio_device(devid);
  6.1109 +    if (device) {
  6.1110 +        device->paused = pause_on;
  6.1111 +    }
  6.1112 +}
  6.1113 +
  6.1114  void
  6.1115  SDL_PauseAudio(int pause_on)
  6.1116  {
  6.1117 -    SDL_AudioDevice *audio = current_audio;
  6.1118 +    SDL_PauseAudioDevice(1, pause_on);
  6.1119 +}
  6.1120  
  6.1121 -    if (audio) {
  6.1122 -        audio->paused = pause_on;
  6.1123 +
  6.1124 +void
  6.1125 +SDL_LockAudioDevice(SDL_AudioDeviceID devid)
  6.1126 +{
  6.1127 +    /* Obtain a lock on the mixing buffers */
  6.1128 +    SDL_AudioDevice *device = get_audio_device(devid);
  6.1129 +    if (device) {
  6.1130 +        current_audio.impl.LockDevice(device);
  6.1131      }
  6.1132  }
  6.1133  
  6.1134  void
  6.1135  SDL_LockAudio(void)
  6.1136  {
  6.1137 -    SDL_AudioDevice *audio = current_audio;
  6.1138 +    SDL_LockAudioDevice(1);
  6.1139 +}
  6.1140  
  6.1141 +void
  6.1142 +SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
  6.1143 +{
  6.1144      /* Obtain a lock on the mixing buffers */
  6.1145 -    if (audio && audio->LockAudio) {
  6.1146 -        audio->LockAudio(audio);
  6.1147 +    SDL_AudioDevice *device = get_audio_device(devid);
  6.1148 +    if (device) {
  6.1149 +        current_audio.impl.UnlockDevice(device);
  6.1150      }
  6.1151  }
  6.1152  
  6.1153  void
  6.1154  SDL_UnlockAudio(void)
  6.1155  {
  6.1156 -    SDL_AudioDevice *audio = current_audio;
  6.1157 +    SDL_UnlockAudioDevice(1);
  6.1158 +}
  6.1159  
  6.1160 -    /* Release lock on the mixing buffers */
  6.1161 -    if (audio && audio->UnlockAudio) {
  6.1162 -        audio->UnlockAudio(audio);
  6.1163 +void
  6.1164 +SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
  6.1165 +{
  6.1166 +    SDL_AudioDevice *device = get_audio_device(devid);
  6.1167 +    if (device) {
  6.1168 +        close_audio_device(device);
  6.1169 +        open_devices[devid-1] = NULL;
  6.1170      }
  6.1171  }
  6.1172  
  6.1173  void
  6.1174  SDL_CloseAudio(void)
  6.1175  {
  6.1176 -    SDL_QuitSubSystem(SDL_INIT_AUDIO);
  6.1177 +    SDL_CloseAudioDevice(1);
  6.1178  }
  6.1179  
  6.1180  void
  6.1181  SDL_AudioQuit(void)
  6.1182  {
  6.1183 -    SDL_AudioDevice *audio = current_audio;
  6.1184 +    SDL_AudioDeviceID i;
  6.1185 +    for (i = 0; i < SDL_arraysize(open_devices); i++) {
  6.1186 +        SDL_CloseAudioDevice(i);
  6.1187 +    }
  6.1188  
  6.1189 -    if (audio) {
  6.1190 -        audio->enabled = 0;
  6.1191 -        if (audio->thread != NULL) {
  6.1192 -            SDL_WaitThread(audio->thread, NULL);
  6.1193 -        }
  6.1194 -        if (audio->mixer_lock != NULL) {
  6.1195 -            SDL_DestroyMutex(audio->mixer_lock);
  6.1196 -        }
  6.1197 -        if (audio->fake_stream != NULL) {
  6.1198 -            SDL_FreeAudioMem(audio->fake_stream);
  6.1199 -        }
  6.1200 -        if (audio->convert.needed) {
  6.1201 -            SDL_FreeAudioMem(audio->convert.buf);
  6.1202 -
  6.1203 -        }
  6.1204 -#if !SDL_AUDIO_DRIVER_AHI
  6.1205 -        if (audio->opened) {
  6.1206 -            audio->CloseAudio(audio);
  6.1207 -            audio->opened = 0;
  6.1208 -        }
  6.1209 -#endif
  6.1210 -        /* Free the driver data */
  6.1211 -        audio->free(audio);
  6.1212 -        current_audio = NULL;
  6.1213 -    }
  6.1214 +    /* Free the driver data */
  6.1215 +    current_audio.impl.Deinitialize();
  6.1216 +    SDL_memset(&current_audio, '\0', sizeof (current_audio));
  6.1217 +    SDL_memset(open_devices, '\0', sizeof (open_devices));
  6.1218  }
  6.1219  
  6.1220  #define NUM_FORMATS 10
  6.1221 @@ -797,9 +928,30 @@
  6.1222          spec->silence = 0x00;
  6.1223          break;
  6.1224      }
  6.1225 -    spec->size = (spec->format & 0xFF) / 8;
  6.1226 +    spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
  6.1227      spec->size *= spec->channels;
  6.1228      spec->size *= spec->samples;
  6.1229  }
  6.1230  
  6.1231 +
  6.1232 +/*
  6.1233 + * Moved here from SDL_mixer.c, since it relies on internals of an opened
  6.1234 + *  audio device (and is deprecated, by the way!).
  6.1235 + */
  6.1236 +void
  6.1237 +SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
  6.1238 +{
  6.1239 +    /* Mix the user-level audio format */
  6.1240 +    SDL_AudioDevice *device = get_audio_device(1);
  6.1241 +    if (device != NULL) {
  6.1242 +        SDL_AudioFormat format;
  6.1243 +        if (device->convert.needed) {
  6.1244 +            format = device->convert.src_format;
  6.1245 +        } else {
  6.1246 +            format = device->spec.format;
  6.1247 +        }
  6.1248 +        SDL_MixAudioFormat(dst, src, format, len, volume);
  6.1249 +    }
  6.1250 +}
  6.1251 +
  6.1252  /* vi: set ts=4 sw=4 expandtab: */
     7.1 --- a/src/audio/SDL_audiocvt.c	Sun Oct 01 16:10:41 2006 +0000
     7.2 +++ b/src/audio/SDL_audiocvt.c	Tue Oct 17 09:15:21 2006 +0000
     7.3 @@ -159,21 +159,19 @@
     7.4              float *dst = (float *) cvt->buf;
     7.5              if (SDL_AUDIO_ISBIGENDIAN(format)) {
     7.6                  for (i = cvt->len_cvt / 8; i; --i, src += 2) {
     7.7 -                    float src1, src2;
     7.8 -                    src1 = SDL_SwapFloatBE(src[0]);
     7.9 -                    src2 = SDL_SwapFloatBE(src[1]);
    7.10 +                    const float src1 = SDL_SwapFloatBE(src[0]);
    7.11 +                    const float src2 = SDL_SwapFloatBE(src[1]);
    7.12                      const double added = ((double) src1) + ((double) src2);
    7.13 -                    src1 = (float) (added * 0.5);
    7.14 -                    *(dst++) = SDL_SwapFloatBE(src1);
    7.15 +                    const float halved = (float) (added * 0.5);
    7.16 +                    *(dst++) = SDL_SwapFloatBE(halved);
    7.17                  }
    7.18              } else {
    7.19                  for (i = cvt->len_cvt / 8; i; --i, src += 2) {
    7.20 -                    float src1, src2;
    7.21 -                    src1 = SDL_SwapFloatLE(src[0]);
    7.22 -                    src2 = SDL_SwapFloatLE(src[1]);
    7.23 +                    const float src1 = SDL_SwapFloatLE(src[0]);
    7.24 +                    const float src2 = SDL_SwapFloatLE(src[1]);
    7.25                      const double added = ((double) src1) + ((double) src2);
    7.26 -                    src1 = (float) (added * 0.5);
    7.27 -                    *(dst++) = SDL_SwapFloatLE(src1);
    7.28 +                    const float halved = (float) (added * 0.5);
    7.29 +                    *(dst++) = SDL_SwapFloatLE(halved);
    7.30                  }
    7.31              }
    7.32          }
     8.1 --- a/src/audio/SDL_audiodev.c	Sun Oct 01 16:10:41 2006 +0000
     8.2 +++ b/src/audio/SDL_audiodev.c	Tue Oct 17 09:15:21 2006 +0000
     8.3 @@ -46,14 +46,63 @@
     8.4  #define _PATH_DEV_AUDIO	"/dev/audio"
     8.5  #endif
     8.6  
     8.7 +static inline void
     8.8 +test_device(const char *fname, int flags, int (*test)(int fd),
     8.9 +            char ***devices, int *devCount)
    8.10 +{
    8.11 +    struct stat sb;
    8.12 +    if ( (stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode)) ) {
    8.13 +        int audio_fd = open(fname, flags, 0);
    8.14 +        if ( (audio_fd >= 0) && (test(audio_fd)) ) {
    8.15 +            void *p = SDL_realloc(*devices, ((*devCount)+1) * sizeof (char *));
    8.16 +            if (p != NULL) {
    8.17 +                size_t len = strlen(fname) + 1;
    8.18 +                char *str = (char *) SDL_malloc(len);
    8.19 +                *devices = (char **) p;
    8.20 +                if (str != NULL) {
    8.21 +                    SDL_strlcpy(str, fname, len);
    8.22 +                    (*devices)[(*devCount)++] = str;
    8.23 +                }
    8.24 +            }
    8.25 +            close(audio_fd);
    8.26 +        }
    8.27 +    }
    8.28 +}
    8.29  
    8.30 -int
    8.31 -SDL_OpenAudioPath(char *path, int maxlen, int flags, int classic)
    8.32 +void
    8.33 +SDL_FreeUnixAudioDevices(char ***devices, int *devCount)
    8.34 +{
    8.35 +    int i = *devCount;
    8.36 +    if ((i > 0) && (*devices != NULL)) {
    8.37 +        while (i--) {
    8.38 +            SDL_free( (*devices)[*devCount] );
    8.39 +        }
    8.40 +    }
    8.41 +
    8.42 +    if (*devices != NULL) {
    8.43 +        SDL_free(*devices);
    8.44 +    }
    8.45 +
    8.46 +    *devices = NULL;
    8.47 +    *devCount = 0;
    8.48 +}
    8.49 +
    8.50 +static int
    8.51 +test_stub(int fd)
    8.52 +{
    8.53 +    return 1;
    8.54 +}
    8.55 +
    8.56 +void
    8.57 +SDL_EnumUnixAudioDevices(int flags, int classic, int (*test)(int fd),
    8.58 +                         char ***devices, int *devCount)
    8.59  {
    8.60      const char *audiodev;
    8.61 -    int audio_fd;
    8.62      char audiopath[1024];
    8.63  
    8.64 +    if (test == NULL)
    8.65 +        test = test_stub;
    8.66 +
    8.67      /* Figure out what our audio device is */
    8.68      if (((audiodev = SDL_getenv("SDL_PATH_DSP")) == NULL) &&
    8.69          ((audiodev = SDL_getenv("AUDIODEV")) == NULL)) {
    8.70 @@ -72,111 +121,16 @@
    8.71              }
    8.72          }
    8.73      }
    8.74 -    audio_fd = open(audiodev, flags, 0);
    8.75 +    test_device(audiodev, flags, test, devices, devCount);
    8.76  
    8.77 -    /* If the first open fails, look for other devices */
    8.78 -    if ((audio_fd < 0) && (SDL_strlen(audiodev) < (sizeof(audiopath) - 3))) {
    8.79 -        int exists, instance;
    8.80 -        struct stat sb;
    8.81 -
    8.82 -        instance = 1;
    8.83 -        do {                    /* Don't use errno ENOENT - it may not be thread-safe */
    8.84 +    if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) {
    8.85 +        int instance = 0;
    8.86 +        while (instance++ <= 64) {
    8.87              SDL_snprintf(audiopath, SDL_arraysize(audiopath),
    8.88 -                         "%s%d", audiodev, instance++);
    8.89 -            exists = 0;
    8.90 -            if (stat(audiopath, &sb) == 0) {
    8.91 -                exists = 1;
    8.92 -                audio_fd = open(audiopath, flags, 0);
    8.93 -            }
    8.94 -        }
    8.95 -        while (exists && (audio_fd < 0));
    8.96 -        audiodev = audiopath;
    8.97 -    }
    8.98 -    if (path != NULL) {
    8.99 -        SDL_strlcpy(path, audiodev, maxlen);
   8.100 -        path[maxlen - 1] = '\0';
   8.101 -    }
   8.102 -    return (audio_fd);
   8.103 -}
   8.104 -
   8.105 -#elif SDL_AUDIO_DRIVER_PAUD
   8.106 -
   8.107 -/* Get the name of the audio device we use for output */
   8.108 -
   8.109 -#include <sys/types.h>
   8.110 -#include <sys/stat.h>
   8.111 -
   8.112 -#include "SDL_stdinc.h"
   8.113 -#include "SDL_audiodev_c.h"
   8.114 -
   8.115 -#ifndef _PATH_DEV_DSP
   8.116 -#define _PATH_DEV_DSP	"/dev/%caud%c/%c"
   8.117 -#endif
   8.118 -
   8.119 -char devsettings[][3] = {
   8.120 -    {'p', '0', '1'}, {'p', '0', '2'}, {'p', '0', '3'}, {'p', '0', '4'},
   8.121 -    {'p', '1', '1'}, {'p', '1', '2'}, {'p', '1', '3'}, {'p', '1', '4'},
   8.122 -    {'p', '2', '1'}, {'p', '2', '2'}, {'p', '2', '3'}, {'p', '2', '4'},
   8.123 -    {'p', '3', '1'}, {'p', '3', '2'}, {'p', '3', '3'}, {'p', '3', '4'},
   8.124 -    {'b', '0', '1'}, {'b', '0', '2'}, {'b', '0', '3'}, {'b', '0', '4'},
   8.125 -    {'b', '1', '1'}, {'b', '1', '2'}, {'b', '1', '3'}, {'b', '1', '4'},
   8.126 -    {'b', '2', '1'}, {'b', '2', '2'}, {'b', '2', '3'}, {'b', '2', '4'},
   8.127 -    {'b', '3', '1'}, {'b', '3', '2'}, {'b', '3', '3'}, {'b', '3', '4'},
   8.128 -    {'\0', '\0', '\0'}
   8.129 -};
   8.130 -
   8.131 -static int
   8.132 -OpenUserDefinedDevice(char *path, int maxlen, int flags)
   8.133 -{
   8.134 -    const char *audiodev;
   8.135 -    int audio_fd;
   8.136 -
   8.137 -    /* Figure out what our audio device is */
   8.138 -    if ((audiodev = SDL_getenv("SDL_PATH_DSP")) == NULL) {
   8.139 -        audiodev = SDL_getenv("AUDIODEV");
   8.140 -    }
   8.141 -    if (audiodev == NULL) {
   8.142 -        return -1;
   8.143 -    }
   8.144 -    audio_fd = open(audiodev, flags, 0);
   8.145 -    if (path != NULL) {
   8.146 -        SDL_strlcpy(path, audiodev, maxlen);
   8.147 -        path[maxlen - 1] = '\0';
   8.148 -    }
   8.149 -    return audio_fd;
   8.150 -}
   8.151 -
   8.152 -int
   8.153 -SDL_OpenAudioPath(char *path, int maxlen, int flags, int classic)
   8.154 -{
   8.155 -    struct stat sb;
   8.156 -    int audio_fd;
   8.157 -    char audiopath[1024];
   8.158 -    int cycle;
   8.159 -
   8.160 -    audio_fd = OpenUserDefinedDevice(path, maxlen, flags);
   8.161 -    if (audio_fd != -1) {
   8.162 -        return audio_fd;
   8.163 -    }
   8.164 -
   8.165 -    cycle = 0;
   8.166 -    while (devsettings[cycle][0] != '\0') {
   8.167 -        SDL_snprintf(audiopath, SDL_arraysize(audiopath),
   8.168 -                     _PATH_DEV_DSP,
   8.169 -                     devsettings[cycle][0],
   8.170 -                     devsettings[cycle][1], devsettings[cycle][2]);
   8.171 -
   8.172 -        if (stat(audiopath, &sb) == 0) {
   8.173 -            audio_fd = open(audiopath, flags, 0);
   8.174 -            if (audio_fd > 0) {
   8.175 -                if (path != NULL) {
   8.176 -                    SDL_strlcpy(path, audiopath, maxlen);
   8.177 -                }
   8.178 -                return audio_fd;
   8.179 -            }
   8.180 +                         "%s%d", audiodev, instance);
   8.181 +            test_device(audiopath, flags, test, devices, devCount);
   8.182          }
   8.183      }
   8.184 -    return -1;
   8.185  }
   8.186  
   8.187  #endif /* Audio driver selection */
     9.1 --- a/src/audio/SDL_audiodev_c.h	Sun Oct 01 16:10:41 2006 +0000
     9.2 +++ b/src/audio/SDL_audiodev_c.h	Tue Oct 17 09:15:21 2006 +0000
     9.3 @@ -21,6 +21,8 @@
     9.4  */
     9.5  #include "SDL_config.h"
     9.6  
     9.7 -/* Open the audio device, storing the pathname in 'path'  */
     9.8 -extern int SDL_OpenAudioPath(char *path, int maxlen, int flags, int classic);
     9.9 +void SDL_EnumUnixAudioDevices(int flags, int classic, int (*test)(int fd),
    9.10 +                              char ***devs, int *count);
    9.11 +void SDL_FreeUnixAudioDevices(char ***devices, int *devCount);
    9.12 +
    9.13  /* vi: set ts=4 sw=4 expandtab: */
    10.1 --- a/src/audio/SDL_mixer.c	Sun Oct 01 16:10:41 2006 +0000
    10.2 +++ b/src/audio/SDL_mixer.c	Tue Oct 17 09:15:21 2006 +0000
    10.3 @@ -89,21 +89,6 @@
    10.4  #define ADJUST_VOLUME(s, v)	(s = (s*v)/SDL_MIX_MAXVOLUME)
    10.5  #define ADJUST_VOLUME_U8(s, v)	(s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128)
    10.6  
    10.7 -void
    10.8 -SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
    10.9 -{
   10.10 -    /* Mix the user-level audio format */
   10.11 -    if (current_audio) {
   10.12 -        SDL_AudioFormat format;
   10.13 -        if (current_audio->convert.needed) {
   10.14 -            format = current_audio->convert.src_format;
   10.15 -        } else {
   10.16 -            format = current_audio->spec.format;
   10.17 -        }
   10.18 -        SDL_MixAudioFormat(dst, src, format, len, volume);
   10.19 -    }
   10.20 -}
   10.21 -
   10.22  
   10.23  void
   10.24  SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
    11.1 --- a/src/audio/SDL_sysaudio.h	Sun Oct 01 16:10:41 2006 +0000
    11.2 +++ b/src/audio/SDL_sysaudio.h	Tue Oct 17 09:15:21 2006 +0000
    11.3 @@ -29,13 +29,33 @@
    11.4  
    11.5  /* The SDL audio driver */
    11.6  typedef struct SDL_AudioDevice SDL_AudioDevice;
    11.7 +#define _THIS	SDL_AudioDevice *_this
    11.8  
    11.9 -/* Define the SDL audio driver structure */
   11.10 -#define _THIS	SDL_AudioDevice *_this
   11.11 -#ifndef _STATUS
   11.12 -#define _STATUS	SDL_status *status
   11.13 -#endif
   11.14 -struct SDL_AudioDevice
   11.15 +typedef struct SDL_AudioDriverImpl
   11.16 +{
   11.17 +    int (*DetectDevices)(int iscapture);
   11.18 +    const char *(*GetDeviceName)(int index, int iscapture);
   11.19 +    int (*OpenDevice) (_THIS, const char *devname, int iscapture);
   11.20 +    void (*ThreadInit) (_THIS); /* Called by audio thread at start */
   11.21 +    void (*WaitDevice) (_THIS);
   11.22 +    void (*PlayDevice) (_THIS);
   11.23 +    Uint8 *(*GetDeviceBuf) (_THIS);
   11.24 +    void (*WaitDone) (_THIS);
   11.25 +    void (*CloseDevice) (_THIS);
   11.26 +    void (*LockDevice) (_THIS);
   11.27 +    void (*UnlockDevice) (_THIS);
   11.28 +    void (*Deinitialize) (void);
   11.29 +
   11.30 +    /* Some flags to push duplicate code into the core and reduce #ifdefs. */
   11.31 +    int ProvidesOwnCallbackThread:1;
   11.32 +    int SkipMixerLock:1;
   11.33 +    int HasCaptureSupport:1;
   11.34 +    int OnlyHasDefaultOutputDevice:1;
   11.35 +    int OnlyHasDefaultInputDevice:1;
   11.36 +} SDL_AudioDriverImpl;
   11.37 +
   11.38 +
   11.39 +typedef struct SDL_AudioDriver
   11.40  {
   11.41      /* * * */
   11.42      /* The name of this audio driver */
   11.43 @@ -45,21 +65,13 @@
   11.44      /* The description of this audio driver */
   11.45      const char *desc;
   11.46  
   11.47 -    /* * * */
   11.48 -    /* Public driver functions */
   11.49 -    int (*OpenAudio) (_THIS, SDL_AudioSpec * spec);
   11.50 -    void (*ThreadInit) (_THIS); /* Called by audio thread at start */
   11.51 -    void (*WaitAudio) (_THIS);
   11.52 -    void (*PlayAudio) (_THIS);
   11.53 -    Uint8 *(*GetAudioBuf) (_THIS);
   11.54 -    void (*WaitDone) (_THIS);
   11.55 -    void (*CloseAudio) (_THIS);
   11.56 +    SDL_AudioDriverImpl impl;
   11.57 +} SDL_AudioDriver;
   11.58  
   11.59 -    /* * * */
   11.60 -    /* Lock / Unlock functions added for the Mac port */
   11.61 -    void (*LockAudio) (_THIS);
   11.62 -    void (*UnlockAudio) (_THIS);
   11.63  
   11.64 +/* Define the SDL audio driver structure */
   11.65 +struct SDL_AudioDevice
   11.66 +{
   11.67      /* * * */
   11.68      /* Data common to all devices */
   11.69  
   11.70 @@ -70,6 +82,7 @@
   11.71      SDL_AudioCVT convert;
   11.72  
   11.73      /* Current state flags */
   11.74 +    int iscapture;
   11.75      int enabled;
   11.76      int paused;
   11.77      int opened;
   11.78 @@ -87,10 +100,6 @@
   11.79      /* * * */
   11.80      /* Data private to this driver */
   11.81      struct SDL_PrivateAudioData *hidden;
   11.82 -
   11.83 -    /* * * */
   11.84 -    /* The function used to dispose of this structure */
   11.85 -    void (*free) (_THIS);
   11.86  };
   11.87  #undef _THIS
   11.88  
   11.89 @@ -98,84 +107,10 @@
   11.90  {
   11.91      const char *name;
   11.92      const char *desc;
   11.93 -    int (*available) (void);
   11.94 -    SDL_AudioDevice *(*create) (int devindex);
   11.95 +    int (*init) (SDL_AudioDriverImpl *impl);
   11.96 +    int demand_only:1;  /* 1==request explicitly, or it won't be available. */
   11.97  } AudioBootStrap;
   11.98  
   11.99 -#if SDL_AUDIO_DRIVER_BSD
  11.100 -extern AudioBootStrap BSD_AUDIO_bootstrap;
  11.101 -#endif
  11.102 -#if SDL_AUDIO_DRIVER_OSS
  11.103 -extern AudioBootStrap DSP_bootstrap;
  11.104 -extern AudioBootStrap DMA_bootstrap;
  11.105 -#endif
  11.106 -#if SDL_AUDIO_DRIVER_ALSA
  11.107 -extern AudioBootStrap ALSA_bootstrap;
  11.108 -#endif
  11.109 -#if SDL_AUDIO_DRIVER_QNXNTO
  11.110 -extern AudioBootStrap QNXNTOAUDIO_bootstrap;
  11.111 -#endif
  11.112 -#if SDL_AUDIO_DRIVER_SUNAUDIO
  11.113 -extern AudioBootStrap SUNAUDIO_bootstrap;
  11.114 -#endif
  11.115 -#if SDL_AUDIO_DRIVER_DMEDIA
  11.116 -extern AudioBootStrap DMEDIA_bootstrap;
  11.117 -#endif
  11.118 -#if SDL_AUDIO_DRIVER_ARTS
  11.119 -extern AudioBootStrap ARTS_bootstrap;
  11.120 -#endif
  11.121 -#if SDL_AUDIO_DRIVER_ESD
  11.122 -extern AudioBootStrap ESD_bootstrap;
  11.123 -#endif
  11.124 -#if SDL_AUDIO_DRIVER_NAS
  11.125 -extern AudioBootStrap NAS_bootstrap;
  11.126 -#endif
  11.127 -#if SDL_AUDIO_DRIVER_DSOUND
  11.128 -extern AudioBootStrap DSOUND_bootstrap;
  11.129 -#endif
  11.130 -#if SDL_AUDIO_DRIVER_WAVEOUT
  11.131 -extern AudioBootStrap WAVEOUT_bootstrap;
  11.132 -#endif
  11.133 -#if SDL_AUDIO_DRIVER_PAUD
  11.134 -extern AudioBootStrap Paud_bootstrap;
  11.135 -#endif
  11.136 -#if SDL_AUDIO_DRIVER_BAUDIO
  11.137 -extern AudioBootStrap BAUDIO_bootstrap;
  11.138 -#endif
  11.139 -#if SDL_AUDIO_DRIVER_COREAUDIO
  11.140 -extern AudioBootStrap COREAUDIO_bootstrap;
  11.141 -#endif
  11.142 -#if SDL_AUDIO_DRIVER_SNDMGR
  11.143 -extern AudioBootStrap SNDMGR_bootstrap;
  11.144 -#endif
  11.145 -#if SDL_AUDIO_DRIVER_AHI
  11.146 -extern AudioBootStrap AHI_bootstrap;
  11.147 -#endif
  11.148 -#if SDL_AUDIO_DRIVER_MINT
  11.149 -extern AudioBootStrap MINTAUDIO_GSXB_bootstrap;
  11.150 -extern AudioBootStrap MINTAUDIO_MCSN_bootstrap;
  11.151 -extern AudioBootStrap MINTAUDIO_STFA_bootstrap;
  11.152 -extern AudioBootStrap MINTAUDIO_XBIOS_bootstrap;
  11.153 -extern AudioBootStrap MINTAUDIO_DMA8_bootstrap;
  11.154 -#endif
  11.155 -#if SDL_AUDIO_DRIVER_DISK
  11.156 -extern AudioBootStrap DISKAUD_bootstrap;
  11.157 -#endif
  11.158 -#if SDL_AUDIO_DRIVER_DUMMY
  11.159 -extern AudioBootStrap DUMMYAUD_bootstrap;
  11.160 -#endif
  11.161 -#if SDL_AUDIO_DRIVER_DC
  11.162 -extern AudioBootStrap DCAUD_bootstrap;
  11.163 -#endif
  11.164 -#if SDL_AUDIO_DRIVER_MMEAUDIO
  11.165 -extern AudioBootStrap MMEAUDIO_bootstrap;
  11.166 -#endif
  11.167 -#if SDL_AUDIO_DRIVER_DART
  11.168 -extern AudioBootStrap DART_bootstrap;
  11.169 -#endif
  11.170 +#endif /* _SDL_sysaudio_h */
  11.171  
  11.172 -/* This is the current audio device */
  11.173 -extern SDL_AudioDevice *current_audio;
  11.174 -
  11.175 -#endif /* _SDL_sysaudio_h */
  11.176  /* vi: set ts=4 sw=4 expandtab: */
    12.1 --- a/src/audio/alsa/SDL_alsa_audio.c	Sun Oct 01 16:10:41 2006 +0000
    12.2 +++ b/src/audio/alsa/SDL_alsa_audio.c	Tue Oct 17 09:15:21 2006 +0000
    12.3 @@ -25,6 +25,9 @@
    12.4  
    12.5  #include <sys/types.h>
    12.6  #include <signal.h>             /* For kill() */
    12.7 +#include <dlfcn.h>
    12.8 +#include <errno.h>
    12.9 +#include <string.h>
   12.10  
   12.11  #include "SDL_timer.h"
   12.12  #include "SDL_audio.h"
   12.13 @@ -32,14 +35,6 @@
   12.14  #include "../SDL_audio_c.h"
   12.15  #include "SDL_alsa_audio.h"
   12.16  
   12.17 -#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
   12.18 -#include <dlfcn.h>
   12.19 -#include "SDL_name.h"
   12.20 -#include "SDL_loadso.h"
   12.21 -#else
   12.22 -#define SDL_NAME(X)	X
   12.23 -#endif
   12.24 -
   12.25  
   12.26  /* The tag name used by ALSA audio */
   12.27  #define DRIVER_NAME         "alsa"
   12.28 @@ -47,182 +42,138 @@
   12.29  /* The default ALSA audio driver */
   12.30  #define DEFAULT_DEVICE	"default"
   12.31  
   12.32 -/* Audio driver functions */
   12.33 -static int ALSA_OpenAudio(_THIS, SDL_AudioSpec * spec);
   12.34 -static void ALSA_WaitAudio(_THIS);
   12.35 -static void ALSA_PlayAudio(_THIS);
   12.36 -static Uint8 *ALSA_GetAudioBuf(_THIS);
   12.37 -static void ALSA_CloseAudio(_THIS);
   12.38 +static int (*ALSA_snd_pcm_open)
   12.39 +                (snd_pcm_t **, const char *, snd_pcm_stream_t, int);
   12.40 +static int (*ALSA_snd_pcm_close)(snd_pcm_t * pcm);
   12.41 +static snd_pcm_sframes_t(*ALSA_snd_pcm_writei)
   12.42 +                (snd_pcm_t *,const void *, snd_pcm_uframes_t);
   12.43 +static int (*ALSA_snd_pcm_resume)(snd_pcm_t *);
   12.44 +static int (*ALSA_snd_pcm_prepare)(snd_pcm_t *);
   12.45 +static int (*ALSA_snd_pcm_drain)(snd_pcm_t *);
   12.46 +static const char *(*ALSA_snd_strerror)(int);
   12.47 +static size_t(*ALSA_snd_pcm_hw_params_sizeof)(void);
   12.48 +static size_t(*ALSA_snd_pcm_sw_params_sizeof)(void);
   12.49 +static int (*ALSA_snd_pcm_hw_params_any)(snd_pcm_t *, snd_pcm_hw_params_t *);
   12.50 +static int (*ALSA_snd_pcm_hw_params_set_access)
   12.51 +                (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_access_t);
   12.52 +static int (*ALSA_snd_pcm_hw_params_set_format)
   12.53 +                (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_format_t);
   12.54 +static int (*ALSA_snd_pcm_hw_params_set_channels)
   12.55 +                (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int);
   12.56 +static int (*ALSA_snd_pcm_hw_params_get_channels)(const snd_pcm_hw_params_t *);
   12.57 +static unsigned int (*ALSA_snd_pcm_hw_params_set_rate_near)
   12.58 +                (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int, int *);
   12.59 +static snd_pcm_uframes_t (*ALSA_snd_pcm_hw_params_set_period_size_near)
   12.60 +                (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_uframes_t, int *);
   12.61 +static snd_pcm_sframes_t (*ALSA_snd_pcm_hw_params_get_period_size)
   12.62 +                (const snd_pcm_hw_params_t *);
   12.63 +static unsigned int (*ALSA_snd_pcm_hw_params_set_periods_near)
   12.64 +                (snd_pcm_t *,snd_pcm_hw_params_t *, unsigned int, int *);
   12.65 +static int (*ALSA_snd_pcm_hw_params_get_periods)(snd_pcm_hw_params_t *);
   12.66 +static int (*ALSA_snd_pcm_hw_params)(snd_pcm_t *, snd_pcm_hw_params_t *);
   12.67 +static int (*ALSA_snd_pcm_sw_params_current)(snd_pcm_t*, snd_pcm_sw_params_t*);
   12.68 +static int (*ALSA_snd_pcm_sw_params_set_start_threshold)
   12.69 +                (snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
   12.70 +static int (*ALSA_snd_pcm_sw_params_set_avail_min)
   12.71 +                (snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
   12.72 +static int (*ALSA_snd_pcm_sw_params)(snd_pcm_t *, snd_pcm_sw_params_t *);
   12.73 +static int (*ALSA_snd_pcm_nonblock)(snd_pcm_t *, int);
   12.74 +#define snd_pcm_hw_params_sizeof ALSA_snd_pcm_hw_params_sizeof
   12.75 +#define snd_pcm_sw_params_sizeof ALSA_snd_pcm_sw_params_sizeof
   12.76 +
   12.77  
   12.78  #ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
   12.79  
   12.80  static const char *alsa_library = SDL_AUDIO_DRIVER_ALSA_DYNAMIC;
   12.81  static void *alsa_handle = NULL;
   12.82 -static int alsa_loaded = 0;
   12.83  
   12.84 -static int (*SDL_snd_pcm_open) (snd_pcm_t ** pcm, const char *name,
   12.85 -                                snd_pcm_stream_t stream, int mode);
   12.86 -static int (*SDL_NAME(snd_pcm_open)) (snd_pcm_t ** pcm, const char *name,
   12.87 -                                      snd_pcm_stream_t stream, int mode);
   12.88 -static int (*SDL_NAME(snd_pcm_close)) (snd_pcm_t * pcm);
   12.89 -static snd_pcm_sframes_t(*SDL_NAME(snd_pcm_writei)) (snd_pcm_t * pcm,
   12.90 -                                                     const void *buffer,
   12.91 -                                                     snd_pcm_uframes_t size);
   12.92 -static int (*SDL_NAME(snd_pcm_resume)) (snd_pcm_t * pcm);
   12.93 -static int (*SDL_NAME(snd_pcm_prepare)) (snd_pcm_t * pcm);
   12.94 -static int (*SDL_NAME(snd_pcm_drain)) (snd_pcm_t * pcm);
   12.95 -static const char *(*SDL_NAME(snd_strerror)) (int errnum);
   12.96 -static size_t(*SDL_NAME(snd_pcm_hw_params_sizeof)) (void);
   12.97 -static size_t(*SDL_NAME(snd_pcm_sw_params_sizeof)) (void);
   12.98 -static int (*SDL_NAME(snd_pcm_hw_params_any)) (snd_pcm_t * pcm,
   12.99 -                                               snd_pcm_hw_params_t * params);
  12.100 -static int (*SDL_NAME(snd_pcm_hw_params_set_access)) (snd_pcm_t * pcm,
  12.101 -                                                      snd_pcm_hw_params_t *
  12.102 -                                                      params,
  12.103 -                                                      snd_pcm_access_t
  12.104 -                                                      access);
  12.105 -static int (*SDL_NAME(snd_pcm_hw_params_set_format)) (snd_pcm_t * pcm,
  12.106 -                                                      snd_pcm_hw_params_t *
  12.107 -                                                      params,
  12.108 -                                                      snd_pcm_format_t val);
  12.109 -static int (*SDL_NAME(snd_pcm_hw_params_set_channels)) (snd_pcm_t * pcm,
  12.110 -                                                        snd_pcm_hw_params_t *
  12.111 -                                                        params,
  12.112 -                                                        unsigned int val);
  12.113 -static int (*SDL_NAME(snd_pcm_hw_params_get_channels)) (const
  12.114 -                                                        snd_pcm_hw_params_t *
  12.115 -                                                        params);
  12.116 -static unsigned int
  12.117 -    (*SDL_NAME(snd_pcm_hw_params_set_rate_near)) (snd_pcm_t *
  12.118 -                                                  pcm,
  12.119 -                                                  snd_pcm_hw_params_t
  12.120 -                                                  * params,
  12.121 -                                                  unsigned int val, int *dir);
  12.122 -static snd_pcm_uframes_t
  12.123 -    (*SDL_NAME(snd_pcm_hw_params_set_period_size_near)) (snd_pcm_t * pcm,
  12.124 -                                                         snd_pcm_hw_params_t
  12.125 -                                                         * params,
  12.126 -                                                         snd_pcm_uframes_t
  12.127 -                                                         val, int *dir);
  12.128 -static snd_pcm_sframes_t
  12.129 -    (*SDL_NAME(snd_pcm_hw_params_get_period_size)) (const
  12.130 -                                                    snd_pcm_hw_params_t
  12.131 -                                                    * params);
  12.132 -static unsigned int
  12.133 -    (*SDL_NAME(snd_pcm_hw_params_set_periods_near)) (snd_pcm_t * pcm,
  12.134 -                                                     snd_pcm_hw_params_t
  12.135 -                                                     * params,
  12.136 -                                                     unsigned int val,
  12.137 -                                                     int *dir);
  12.138 -static int (*SDL_NAME(snd_pcm_hw_params_get_periods)) (snd_pcm_hw_params_t *
  12.139 -                                                       params);
  12.140 -static int (*SDL_NAME(snd_pcm_hw_params)) (snd_pcm_t * pcm,
  12.141 -                                           snd_pcm_hw_params_t * params);
  12.142 -/*
  12.143 -*/
  12.144 -static int (*SDL_NAME(snd_pcm_sw_params_current)) (snd_pcm_t * pcm,
  12.145 -                                                   snd_pcm_sw_params_t *
  12.146 -                                                   swparams);
  12.147 -static int (*SDL_NAME(snd_pcm_sw_params_set_start_threshold)) (snd_pcm_t *
  12.148 -                                                               pcm,
  12.149 -                                                               snd_pcm_sw_params_t
  12.150 -                                                               * params,
  12.151 -                                                               snd_pcm_uframes_t
  12.152 -                                                               val);
  12.153 -static int (*SDL_NAME(snd_pcm_sw_params_set_avail_min)) (snd_pcm_t * pcm,
  12.154 -                                                         snd_pcm_sw_params_t
  12.155 -                                                         * params,
  12.156 -                                                         snd_pcm_uframes_t
  12.157 -                                                         val);
  12.158 -static int (*SDL_NAME(snd_pcm_sw_params)) (snd_pcm_t * pcm,
  12.159 -                                           snd_pcm_sw_params_t * params);
  12.160 -static int (*SDL_NAME(snd_pcm_nonblock)) (snd_pcm_t * pcm, int nonblock);
  12.161 -#define snd_pcm_hw_params_sizeof SDL_NAME(snd_pcm_hw_params_sizeof)
  12.162 -#define snd_pcm_sw_params_sizeof SDL_NAME(snd_pcm_sw_params_sizeof)
  12.163 +static int
  12.164 +load_alsa_sym(const char *fn, void **addr)
  12.165 +{
  12.166 +    /*
  12.167 +     * !!! FIXME:
  12.168 +     * Eventually, this will deal with fallbacks, version changes, and
  12.169 +     *  missing symbols we can workaround. But for now, it doesn't.
  12.170 +     */
  12.171 +
  12.172 +#if HAVE_DLVSYM
  12.173 +    *addr = dlvsym(alsa_handle, fn, "ALSA_0.9");
  12.174 +    if (*addr == NULL)
  12.175 +#endif
  12.176 +    {
  12.177 +        *addr = dlsym(alsa_handle, fn);
  12.178 +        if (*addr == NULL) {
  12.179 +            SDL_SetError("dlsym('%s') failed: %s", fn, strerror(errno));
  12.180 +            return 0;
  12.181 +        }
  12.182 +    }
  12.183 +
  12.184 +    return 1;
  12.185 +}
  12.186  
  12.187  /* cast funcs to char* first, to please GCC's strict aliasing rules. */
  12.188 -static struct
  12.189 +#define SDL_ALSA_SYM(x) \
  12.190 +    if (!load_alsa_sym(#x, (void **) (char *) &ALSA_##x)) return -1
  12.191 +#else
  12.192 +#define SDL_ALSA_SYM(x) ALSA_##x = x
  12.193 +#endif
  12.194 +
  12.195 +static int load_alsa_syms(void)
  12.196  {
  12.197 -    const char *name;
  12.198 -    void **func;
  12.199 -} alsa_functions[] = {
  12.200 -    {
  12.201 -    "snd_pcm_open", (void **) (char *) &SDL_NAME(snd_pcm_open)}, {
  12.202 -    "snd_pcm_close", (void **) (char *) &SDL_NAME(snd_pcm_close)}, {
  12.203 -    "snd_pcm_writei", (void **) (char *) &SDL_NAME(snd_pcm_writei)}, {
  12.204 -    "snd_pcm_resume", (void **) (char *) &SDL_NAME(snd_pcm_resume)}, {
  12.205 -    "snd_pcm_prepare", (void **) (char *) &SDL_NAME(snd_pcm_prepare)}, {
  12.206 -    "snd_pcm_drain", (void **) (char *) &SDL_NAME(snd_pcm_drain)}, {
  12.207 -    "snd_strerror", (void **) (char *) &SDL_NAME(snd_strerror)}, {
  12.208 -    "snd_pcm_hw_params_sizeof",
  12.209 -            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_sizeof)}, {
  12.210 -    "snd_pcm_sw_params_sizeof",
  12.211 -            (void **) (char *) &SDL_NAME(snd_pcm_sw_params_sizeof)}, {
  12.212 -    "snd_pcm_hw_params_any",
  12.213 -            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_any)}, {
  12.214 -    "snd_pcm_hw_params_set_access",
  12.215 -            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_access)}, {
  12.216 -    "snd_pcm_hw_params_set_format",
  12.217 -            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_format)}, {
  12.218 -    "snd_pcm_hw_params_set_channels",
  12.219 -            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_channels)}, {
  12.220 -    "snd_pcm_hw_params_get_channels",
  12.221 -            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_get_channels)}, {
  12.222 -    "snd_pcm_hw_params_set_rate_near",
  12.223 -            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_rate_near)}, {
  12.224 -        "snd_pcm_hw_params_set_period_size_near", (void **) (char *)
  12.225 -    &SDL_NAME(snd_pcm_hw_params_set_period_size_near)}, {
  12.226 -    "snd_pcm_hw_params_get_period_size",
  12.227 -            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_get_period_size)},
  12.228 -    {
  12.229 -        "snd_pcm_hw_params_set_periods_near", (void **) (char *)
  12.230 -    &SDL_NAME(snd_pcm_hw_params_set_periods_near)}, {
  12.231 -    "snd_pcm_hw_params_get_periods",
  12.232 -            (void **) (char *) &SDL_NAME(snd_pcm_hw_params_get_periods)}, {
  12.233 -    "snd_pcm_hw_params", (void **) (char *) &SDL_NAME(snd_pcm_hw_params)}, {
  12.234 -    "snd_pcm_sw_params_current",
  12.235 -            (void **) (char *) &SDL_NAME(snd_pcm_sw_params_current)}, {
  12.236 -        "snd_pcm_sw_params_set_start_threshold", (void **) (char *)
  12.237 -    &SDL_NAME(snd_pcm_sw_params_set_start_threshold)}, {
  12.238 -    "snd_pcm_sw_params_set_avail_min",
  12.239 -            (void **) (char *) &SDL_NAME(snd_pcm_sw_params_set_avail_min)}, {
  12.240 -    "snd_pcm_sw_params", (void **) (char *) &SDL_NAME(snd_pcm_sw_params)}, {
  12.241 -"snd_pcm_nonblock", (void **) (char *) &SDL_NAME(snd_pcm_nonblock)},};
  12.242 +    SDL_ALSA_SYM(snd_pcm_open);
  12.243 +    SDL_ALSA_SYM(snd_pcm_close);
  12.244 +    SDL_ALSA_SYM(snd_pcm_writei);
  12.245 +    SDL_ALSA_SYM(snd_pcm_resume);
  12.246 +    SDL_ALSA_SYM(snd_pcm_prepare);
  12.247 +    SDL_ALSA_SYM(snd_pcm_drain);
  12.248 +    SDL_ALSA_SYM(snd_strerror);
  12.249 +    SDL_ALSA_SYM(snd_pcm_hw_params_sizeof);
  12.250 +    SDL_ALSA_SYM(snd_pcm_sw_params_sizeof);
  12.251 +    SDL_ALSA_SYM(snd_pcm_hw_params_any);
  12.252 +    SDL_ALSA_SYM(snd_pcm_hw_params_set_access);
  12.253 +    SDL_ALSA_SYM(snd_pcm_hw_params_set_format);
  12.254 +    SDL_ALSA_SYM(snd_pcm_hw_params_set_channels);
  12.255 +    SDL_ALSA_SYM(snd_pcm_hw_params_get_channels);
  12.256 +    SDL_ALSA_SYM(snd_pcm_hw_params_set_rate_near);
  12.257 +    SDL_ALSA_SYM(snd_pcm_hw_params_set_period_size_near);
  12.258 +    SDL_ALSA_SYM(snd_pcm_hw_params_get_period_size);
  12.259 +    SDL_ALSA_SYM(snd_pcm_hw_params_set_periods_near);
  12.260 +    SDL_ALSA_SYM(snd_pcm_hw_params_get_periods);
  12.261 +    SDL_ALSA_SYM(snd_pcm_hw_params);
  12.262 +    SDL_ALSA_SYM(snd_pcm_sw_params_current);
  12.263 +    SDL_ALSA_SYM(snd_pcm_sw_params_set_start_threshold);
  12.264 +    SDL_ALSA_SYM(snd_pcm_sw_params_set_avail_min);
  12.265 +    SDL_ALSA_SYM(snd_pcm_sw_params);
  12.266 +    SDL_ALSA_SYM(snd_pcm_nonblock);
  12.267 +    return 0;
  12.268 +}
  12.269 +#undef SDL_ALSA_SYM
  12.270 +
  12.271 +#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
  12.272  
  12.273  static void
  12.274  UnloadALSALibrary(void)
  12.275  {
  12.276 -    if (alsa_loaded) {
  12.277 -/*		SDL_UnloadObject(alsa_handle);*/
  12.278 +    if (alsa_handle != NULL) {
  12.279          dlclose(alsa_handle);
  12.280          alsa_handle = NULL;
  12.281 -        alsa_loaded = 0;
  12.282      }
  12.283  }
  12.284  
  12.285  static int
  12.286  LoadALSALibrary(void)
  12.287  {
  12.288 -    int i, retval = -1;
  12.289 -
  12.290 -/*	alsa_handle = SDL_LoadObject(alsa_library);*/
  12.291 -    alsa_handle = dlopen(alsa_library, RTLD_NOW);
  12.292 -    if (alsa_handle) {
  12.293 -        alsa_loaded = 1;
  12.294 -        retval = 0;
  12.295 -        for (i = 0; i < SDL_arraysize(alsa_functions); i++) {
  12.296 -/*			*alsa_functions[i].func = SDL_LoadFunction(alsa_handle,alsa_functions[i].name);*/
  12.297 -#if HAVE_DLVSYM
  12.298 -            *alsa_functions[i].func =
  12.299 -                dlvsym(alsa_handle, alsa_functions[i].name, "ALSA_0.9");
  12.300 -            if (!*alsa_functions[i].func)
  12.301 -#endif
  12.302 -                *alsa_functions[i].func =
  12.303 -                    dlsym(alsa_handle, alsa_functions[i].name);
  12.304 -            if (!*alsa_functions[i].func) {
  12.305 -                retval = -1;
  12.306 +    int retval = 0;
  12.307 +    if (alsa_handle == NULL) {
  12.308 +        alsa_handle = dlopen(alsa_library, RTLD_NOW);
  12.309 +        if (alsa_handle == NULL) {
  12.310 +            retval = -1;
  12.311 +            SDL_SetError("ALSA: dlopen('%s') failed: %s\n",
  12.312 +                          alsa_library, strerror(errno));
  12.313 +        } else {
  12.314 +            retval = load_alsa_syms();
  12.315 +            if (retval < 0) {
  12.316                  UnloadALSALibrary();
  12.317 -                break;
  12.318              }
  12.319          }
  12.320      }
  12.321 @@ -234,12 +185,12 @@
  12.322  static void
  12.323  UnloadALSALibrary(void)
  12.324  {
  12.325 -    return;
  12.326  }
  12.327  
  12.328  static int
  12.329  LoadALSALibrary(void)
  12.330  {
  12.331 +    load_alsa_syms();
  12.332      return 0;
  12.333  }
  12.334  
  12.335 @@ -262,80 +213,10 @@
  12.336      return device;
  12.337  }
  12.338  
  12.339 -/* Audio driver bootstrap functions */
  12.340 -
  12.341 -static int
  12.342 -Audio_Available(void)
  12.343 -{
  12.344 -    int available;
  12.345 -    int status;
  12.346 -    snd_pcm_t *handle;
  12.347 -
  12.348 -    available = 0;
  12.349 -    if (LoadALSALibrary() < 0) {
  12.350 -        return available;
  12.351 -    }
  12.352 -    status =
  12.353 -        SDL_NAME(snd_pcm_open) (&handle, get_audio_device(2),
  12.354 -                                SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
  12.355 -    if (status >= 0) {
  12.356 -        available = 1;
  12.357 -        SDL_NAME(snd_pcm_close) (handle);
  12.358 -    }
  12.359 -    UnloadALSALibrary();
  12.360 -    return (available);
  12.361 -}
  12.362 -
  12.363 -static void
  12.364 -Audio_DeleteDevice(SDL_AudioDevice * device)
  12.365 -{
  12.366 -    SDL_free(device->hidden);
  12.367 -    SDL_free(device);
  12.368 -    UnloadALSALibrary();
  12.369 -}
  12.370 -
  12.371 -static SDL_AudioDevice *
  12.372 -Audio_CreateDevice(int devindex)
  12.373 -{
  12.374 -    SDL_AudioDevice *this;
  12.375 -
  12.376 -    /* Initialize all variables that we clean on shutdown */
  12.377 -    LoadALSALibrary();
  12.378 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
  12.379 -    if (this) {
  12.380 -        SDL_memset(this, 0, (sizeof *this));
  12.381 -        this->hidden = (struct SDL_PrivateAudioData *)
  12.382 -            SDL_malloc((sizeof *this->hidden));
  12.383 -    }
  12.384 -    if ((this == NULL) || (this->hidden == NULL)) {
  12.385 -        SDL_OutOfMemory();
  12.386 -        if (this) {
  12.387 -            SDL_free(this);
  12.388 -        }
  12.389 -        return (0);
  12.390 -    }
  12.391 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  12.392 -
  12.393 -    /* Set the function pointers */
  12.394 -    this->OpenAudio = ALSA_OpenAudio;
  12.395 -    this->WaitAudio = ALSA_WaitAudio;
  12.396 -    this->PlayAudio = ALSA_PlayAudio;
  12.397 -    this->GetAudioBuf = ALSA_GetAudioBuf;
  12.398 -    this->CloseAudio = ALSA_CloseAudio;
  12.399 -
  12.400 -    this->free = Audio_DeleteDevice;
  12.401 -
  12.402 -    return this;
  12.403 -}
  12.404 -
  12.405 -AudioBootStrap ALSA_bootstrap = {
  12.406 -    DRIVER_NAME, "ALSA 0.9 PCM audio",
  12.407 -    Audio_Available, Audio_CreateDevice
  12.408 -};
  12.409  
  12.410  /* This function waits until it is possible to write a full sound buffer */
  12.411  static void
  12.412 -ALSA_WaitAudio(_THIS)
  12.413 +ALSA_WaitDevice(_THIS)
  12.414  {
  12.415      /* Check to see if the thread-parent process is still alive */
  12.416      {
  12.417 @@ -343,8 +224,9 @@
  12.418          /* Note that this only works with thread implementations 
  12.419             that use a different process id for each thread.
  12.420           */
  12.421 -        if (parent && (((++cnt) % 10) == 0)) {  /* Check every 10 loops */
  12.422 -            if (kill(parent, 0) < 0) {
  12.423 +        /* Check every 10 loops */
  12.424 +        if (this->hidden->parent && (((++cnt) % 10) == 0)) {
  12.425 +            if (kill(this->hidden->parent, 0) < 0) {
  12.426                  this->enabled = 0;
  12.427              }
  12.428          }
  12.429 @@ -352,13 +234,14 @@
  12.430  }
  12.431  
  12.432  
  12.433 +/* !!! FIXME: is there a channel swizzler in alsalib instead? */
  12.434  /*
  12.435   * http://bugzilla.libsdl.org/show_bug.cgi?id=110
  12.436   * "For Linux ALSA, this is FL-FR-RL-RR-C-LFE
  12.437   *  and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-RL-RR"
  12.438   */
  12.439  #define SWIZ6(T) \
  12.440 -    T *ptr = (T *) mixbuf; \
  12.441 +    T *ptr = (T *) this->hidden->mixbuf; \
  12.442      const Uint32 count = (this->spec.samples / 6); \
  12.443      Uint32 i; \
  12.444      for (i = 0; i < count; i++, ptr += 6) { \
  12.445 @@ -392,8 +275,8 @@
  12.446  
  12.447  
  12.448  /*
  12.449 - * Called right before feeding this->mixbuf to the hardware. Swizzle channels
  12.450 - *  from Windows/Mac order to the format alsalib will want.
  12.451 + * Called right before feeding this->hidden->mixbuf to the hardware. Swizzle
  12.452 + *  channels from Windows/Mac order to the format alsalib will want.
  12.453   */
  12.454  static __inline__ void
  12.455  swizzle_alsa_channels(_THIS)
  12.456 @@ -415,7 +298,7 @@
  12.457  
  12.458  
  12.459  static void
  12.460 -ALSA_PlayAudio(_THIS)
  12.461 +ALSA_PlayDevice(_THIS)
  12.462  {
  12.463      int status;
  12.464      int sample_len;
  12.465 @@ -424,11 +307,12 @@
  12.466      swizzle_alsa_channels(this);
  12.467  
  12.468      sample_len = this->spec.samples;
  12.469 -    sample_buf = (signed short *) mixbuf;
  12.470 +    sample_buf = (signed short *) this->hidden->mixbuf;
  12.471  
  12.472      while (sample_len > 0) {
  12.473 -        status =
  12.474 -            SDL_NAME(snd_pcm_writei) (pcm_handle, sample_buf, sample_len);
  12.475 +        status = ALSA_snd_pcm_writei(this->hidden->pcm_handle,
  12.476 +                                     sample_buf, sample_len);
  12.477 +
  12.478          if (status < 0) {
  12.479              if (status == -EAGAIN) {
  12.480                  SDL_Delay(1);
  12.481 @@ -437,11 +321,11 @@
  12.482              if (status == -ESTRPIPE) {
  12.483                  do {
  12.484                      SDL_Delay(1);
  12.485 -                    status = SDL_NAME(snd_pcm_resume) (pcm_handle);
  12.486 +                    status = ALSA_snd_pcm_resume(this->hidden->pcm_handle);
  12.487                  } while (status == -EAGAIN);
  12.488              }
  12.489              if (status < 0) {
  12.490 -                status = SDL_NAME(snd_pcm_prepare) (pcm_handle);
  12.491 +                status = ALSA_snd_pcm_prepare(this->hidden->pcm_handle);
  12.492              }
  12.493              if (status < 0) {
  12.494                  /* Hmm, not much we can do - abort */
  12.495 @@ -456,74 +340,89 @@
  12.496  }
  12.497  
  12.498  static Uint8 *
  12.499 -ALSA_GetAudioBuf(_THIS)
  12.500 +ALSA_GetDeviceBuf(_THIS)
  12.501  {
  12.502 -    return (mixbuf);
  12.503 +    return (this->hidden->mixbuf);
  12.504  }
  12.505  
  12.506  static void
  12.507 -ALSA_CloseAudio(_THIS)
  12.508 +ALSA_CloseDevice(_THIS)
  12.509  {
  12.510 -    if (mixbuf != NULL) {
  12.511 -        SDL_FreeAudioMem(mixbuf);
  12.512 -        mixbuf = NULL;
  12.513 -    }
  12.514 -    if (pcm_handle) {
  12.515 -        SDL_NAME(snd_pcm_drain) (pcm_handle);
  12.516 -        SDL_NAME(snd_pcm_close) (pcm_handle);
  12.517 -        pcm_handle = NULL;
  12.518 +    if (this->hidden != NULL) {
  12.519 +        if (this->hidden->mixbuf != NULL) {
  12.520 +            SDL_FreeAudioMem(this->hidden->mixbuf);
  12.521 +            this->hidden->mixbuf = NULL;
  12.522 +        }
  12.523 +        if (this->hidden->pcm_handle) {
  12.524 +            ALSA_snd_pcm_drain(this->hidden->pcm_handle);
  12.525 +            ALSA_snd_pcm_close(this->hidden->pcm_handle);
  12.526 +            this->hidden->pcm_handle = NULL;
  12.527 +        }
  12.528 +        SDL_free(this->hidden);
  12.529 +        this->hidden = NULL;
  12.530      }
  12.531  }
  12.532  
  12.533  static int
  12.534 -ALSA_OpenAudio(_THIS, SDL_AudioSpec * spec)
  12.535 +ALSA_OpenDevice(_THIS, const char *devname, int iscapture)
  12.536  {
  12.537 -    int status;
  12.538 -    snd_pcm_hw_params_t *hwparams;
  12.539 -    snd_pcm_sw_params_t *swparams;
  12.540 -    snd_pcm_format_t format;
  12.541 -    snd_pcm_uframes_t frames;
  12.542 -    SDL_AudioFormat test_format;
  12.543 +    int status = 0;
  12.544 +    snd_pcm_t *pcm_handle = NULL;
  12.545 +    snd_pcm_hw_params_t *hwparams = NULL;
  12.546 +    snd_pcm_sw_params_t *swparams = NULL;
  12.547 +    snd_pcm_format_t format = 0;
  12.548 +    snd_pcm_uframes_t frames = 0;
  12.549 +    SDL_AudioFormat test_format = 0;
  12.550 +
  12.551 +    /* Initialize all variables that we clean on shutdown */
  12.552 +    this->hidden = (struct SDL_PrivateAudioData *)
  12.553 +                        SDL_malloc((sizeof *this->hidden));
  12.554 +    if (this->hidden == NULL) {
  12.555 +        SDL_OutOfMemory();
  12.556 +        return 0;
  12.557 +    }
  12.558 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  12.559  
  12.560      /* Open the audio device */
  12.561      /* Name of device should depend on # channels in spec */
  12.562 -    status =
  12.563 -        SDL_NAME(snd_pcm_open) (&pcm_handle,
  12.564 -                                get_audio_device(spec->channels),
  12.565 -                                SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
  12.566 +    status = ALSA_snd_pcm_open(&pcm_handle,
  12.567 +                               get_audio_device(this->spec.channels),
  12.568 +                               SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
  12.569  
  12.570      if (status < 0) {
  12.571 -        SDL_SetError("Couldn't open audio device: %s",
  12.572 -                     SDL_NAME(snd_strerror) (status));
  12.573 -        return (-1);
  12.574 +        ALSA_CloseDevice(this);
  12.575 +        SDL_SetError("ALSA: Couldn't open audio device: %s",
  12.576 +                     ALSA_snd_strerror(status));
  12.577 +        return 0;
  12.578      }
  12.579  
  12.580 +    this->hidden->pcm_handle = pcm_handle;
  12.581 +
  12.582      /* Figure out what the hardware is capable of */
  12.583      snd_pcm_hw_params_alloca(&hwparams);
  12.584 -    status = SDL_NAME(snd_pcm_hw_params_any) (pcm_handle, hwparams);
  12.585 +    status = ALSA_snd_pcm_hw_params_any(pcm_handle, hwparams);
  12.586      if (status < 0) {
  12.587 -        SDL_SetError("Couldn't get hardware config: %s",
  12.588 -                     SDL_NAME(snd_strerror) (status));
  12.589 -        ALSA_CloseAudio(this);
  12.590 -        return (-1);
  12.591 +        ALSA_CloseDevice(this);
  12.592 +        SDL_SetError("ALSA: Couldn't get hardware config: %s",
  12.593 +                     ALSA_snd_strerror(status));
  12.594 +        return 0;
  12.595      }
  12.596  
  12.597      /* SDL only uses interleaved sample output */
  12.598 -    status =
  12.599 -        SDL_NAME(snd_pcm_hw_params_set_access) (pcm_handle, hwparams,
  12.600 -                                                SND_PCM_ACCESS_RW_INTERLEAVED);
  12.601 +    status = ALSA_snd_pcm_hw_params_set_access(pcm_handle, hwparams,
  12.602 +                                               SND_PCM_ACCESS_RW_INTERLEAVED);
  12.603      if (status < 0) {
  12.604 -        SDL_SetError("Couldn't set interleaved access: %s",
  12.605 -                     SDL_NAME(snd_strerror) (status));
  12.606 -        ALSA_CloseAudio(this);
  12.607 -        return (-1);
  12.608 +        ALSA_CloseDevice(this);
  12.609 +        SDL_SetError("ALSA: Couldn't set interleaved access: %s",
  12.610 +                     ALSA_snd_strerror(status));
  12.611 +        return 0;
  12.612      }
  12.613  
  12.614      /* Try for a closest match on audio format */
  12.615      status = -1;
  12.616 -    for (test_format = SDL_FirstAudioFormat(spec->format);
  12.617 +    for (test_format = SDL_FirstAudioFormat(this->spec.format);
  12.618           test_format && (status < 0);) {
  12.619 -        status = 0;             /* if we can't support a format, it'll become -1. */
  12.620 +        status = 0;      /* if we can't support a format, it'll become -1. */
  12.621          switch (test_format) {
  12.622          case AUDIO_U8:
  12.623              format = SND_PCM_FORMAT_U8;
  12.624 @@ -560,131 +459,151 @@
  12.625              break;
  12.626          }
  12.627          if (status >= 0) {
  12.628 -            status =
  12.629 -                SDL_NAME(snd_pcm_hw_params_set_format) (pcm_handle,
  12.630 -                                                        hwparams, format);
  12.631 +            status = ALSA_snd_pcm_hw_params_set_format(pcm_handle,
  12.632 +                                                       hwparams, format);
  12.633          }
  12.634          if (status < 0) {
  12.635              test_format = SDL_NextAudioFormat();
  12.636          }
  12.637      }
  12.638      if (status < 0) {
  12.639 -        SDL_SetError("Couldn't find any hardware audio formats");
  12.640 -        ALSA_CloseAudio(this);
  12.641 -        return (-1);
  12.642 +        ALSA_CloseDevice(this);
  12.643 +        SDL_SetError("ALSA: Couldn't find any hardware audio formats");
  12.644 +        return 0;
  12.645      }
  12.646 -    spec->format = test_format;
  12.647 +    this->spec.format = test_format;
  12.648  
  12.649      /* Set the number of channels */
  12.650 -    status =
  12.651 -        SDL_NAME(snd_pcm_hw_params_set_channels) (pcm_handle, hwparams,
  12.652 -                                                  spec->channels);
  12.653 +    status = ALSA_snd_pcm_hw_params_set_channels(pcm_handle, hwparams,
  12.654 +                                                 this->spec.channels);
  12.655      if (status < 0) {
  12.656 -        status = SDL_NAME(snd_pcm_hw_params_get_channels) (hwparams);
  12.657 +        status = ALSA_snd_pcm_hw_params_get_channels(hwparams);
  12.658          if ((status <= 0) || (status > 2)) {
  12.659 -            SDL_SetError("Couldn't set audio channels");
  12.660 -            ALSA_CloseAudio(this);
  12.661 -            return (-1);
  12.662 +            ALSA_CloseDevice(this);
  12.663 +            SDL_SetError("ALSA: Couldn't set audio channels");
  12.664 +            return 0;
  12.665          }
  12.666 -        spec->channels = status;
  12.667 +        this->spec.channels = status;
  12.668      }
  12.669  
  12.670      /* Set the audio rate */
  12.671 -    status =
  12.672 -        SDL_NAME(snd_pcm_hw_params_set_rate_near) (pcm_handle, hwparams,
  12.673 -                                                   spec->freq, NULL);
  12.674 +    status = ALSA_snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams,
  12.675 +                                                  this->spec.freq, NULL);
  12.676      if (status < 0) {
  12.677 -        SDL_SetError("Couldn't set audio frequency: %s",
  12.678 -                     SDL_NAME(snd_strerror) (status));
  12.679 -        ALSA_CloseAudio(this);
  12.680 -        return (-1);
  12.681 +        ALSA_CloseDevice(this);
  12.682 +        SDL_SetError("ALSA: Couldn't set audio frequency: %s",
  12.683 +                     ALSA_snd_strerror(status));
  12.684 +        return 0;
  12.685      }
  12.686 -    spec->freq = status;
  12.687 +    this->spec.freq = status;
  12.688  
  12.689      /* Set the buffer size, in samples */
  12.690 -    frames = spec->samples;
  12.691 -    frames =
  12.692 -        SDL_NAME(snd_pcm_hw_params_set_period_size_near) (pcm_handle,
  12.693 -                                                          hwparams, frames,
  12.694 -                                                          NULL);
  12.695 -    spec->samples = frames;
  12.696 -    SDL_NAME(snd_pcm_hw_params_set_periods_near) (pcm_handle, hwparams, 2,
  12.697 -                                                  NULL);
  12.698 +    frames = this->spec.samples;
  12.699 +    frames = ALSA_snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams,
  12.700 +                                                         frames, NULL);
  12.701 +    this->spec.samples = frames;
  12.702 +    ALSA_snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, 2, NULL);
  12.703  
  12.704      /* "set" the hardware with the desired parameters */
  12.705 -    status = SDL_NAME(snd_pcm_hw_params) (pcm_handle, hwparams);
  12.706 +    status = ALSA_snd_pcm_hw_params(pcm_handle, hwparams);
  12.707      if (status < 0) {
  12.708 -        SDL_SetError("Couldn't set hardware audio parameters: %s",
  12.709 -                     SDL_NAME(snd_strerror) (status));
  12.710 -        ALSA_CloseAudio(this);
  12.711 -        return (-1);
  12.712 +        ALSA_CloseDevice(this);
  12.713 +        SDL_SetError("ALSA: Couldn't set hardware audio parameters: %s",
  12.714 +                     ALSA_snd_strerror(status));
  12.715 +        return 0;
  12.716      }
  12.717  
  12.718 -/* This is useful for debugging... */
  12.719 -/*
  12.720 -{ snd_pcm_sframes_t bufsize; int fragments;
  12.721 -   bufsize = SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams);
  12.722 -   fragments = SDL_NAME(snd_pcm_hw_params_get_periods)(hwparams);
  12.723 -
  12.724 -   fprintf(stderr, "ALSA: bufsize = %ld, fragments = %d\n", bufsize, fragments);
  12.725 +#if AUDIO_DEBUG
  12.726 +{
  12.727 +    snd_pcm_sframes_t bufsize;
  12.728 +    int fragments;
  12.729 +    bufsize = ALSA_snd_pcm_hw_params_get_period_size(hwparams);
  12.730 +    fragments = ALSA_snd_pcm_hw_params_get_periods(hwparams);
  12.731 +    fprintf(stderr,"ALSA: bufsize = %ld, fragments = %d\n",bufsize,fragments);
  12.732  }
  12.733 -*/
  12.734 +#endif
  12.735  
  12.736      /* Set the software parameters */
  12.737      snd_pcm_sw_params_alloca(&swparams);
  12.738 -    status = SDL_NAME(snd_pcm_sw_params_current) (pcm_handle, swparams);
  12.739 +    status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams);
  12.740      if (status < 0) {
  12.741 -        SDL_SetError("Couldn't get software config: %s",
  12.742 -                     SDL_NAME(snd_strerror) (status));
  12.743 -        ALSA_CloseAudio(this);
  12.744 -        return (-1);
  12.745 +        ALSA_CloseDevice(this);
  12.746 +        SDL_SetError("ALSA: Couldn't get software config: %s",
  12.747 +                     ALSA_snd_strerror(status));
  12.748 +        return 0;
  12.749      }
  12.750 -    status =
  12.751 -        SDL_NAME(snd_pcm_sw_params_set_start_threshold) (pcm_handle,
  12.752 -                                                         swparams, 0);
  12.753 +    status = ALSA_snd_pcm_sw_params_set_start_threshold(pcm_handle,swparams,0);
  12.754      if (status < 0) {
  12.755 -        SDL_SetError("Couldn't set start threshold: %s",
  12.756 -                     SDL_NAME(snd_strerror) (status));
  12.757 -        ALSA_CloseAudio(this);
  12.758 -        return (-1);
  12.759 +        ALSA_CloseDevice(this);
  12.760 +        SDL_SetError("ALSA: Couldn't set start threshold: %s",
  12.761 +                     ALSA_snd_strerror(status));
  12.762 +        return 0;
  12.763      }
  12.764 -    status =
  12.765 -        SDL_NAME(snd_pcm_sw_params_set_avail_min) (pcm_handle, swparams,
  12.766 -                                                   frames);
  12.767 +    status = ALSA_snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, frames);
  12.768      if (status < 0) {
  12.769 -        SDL_SetError("Couldn't set avail min: %s",
  12.770 -                     SDL_NAME(snd_strerror) (status));
  12.771 -        ALSA_CloseAudio(this);
  12.772 -        return (-1);
  12.773 +        ALSA_CloseDevice(this);
  12.774 +        SDL_SetError("Couldn't set avail min: %s", ALSA_snd_strerror(status));
  12.775 +        return 0;
  12.776      }
  12.777 -    status = SDL_NAME(snd_pcm_sw_params) (pcm_handle, swparams);
  12.778 +    status = ALSA_snd_pcm_sw_params(pcm_handle, swparams);
  12.779      if (status < 0) {
  12.780 +        ALSA_CloseDevice(this);
  12.781          SDL_SetError("Couldn't set software audio parameters: %s",
  12.782 -                     SDL_NAME(snd_strerror) (status));
  12.783 -        ALSA_CloseAudio(this);
  12.784 -        return (-1);
  12.785 +                     ALSA_snd_strerror(status));
  12.786 +        return 0;
  12.787      }
  12.788  
  12.789      /* Calculate the final parameters for this audio specification */
  12.790 -    SDL_CalculateAudioSpec(spec);
  12.791 +    SDL_CalculateAudioSpec(&this->spec);
  12.792  
  12.793      /* Allocate mixing buffer */
  12.794 -    mixlen = spec->size;
  12.795 -    mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen);
  12.796 -    if (mixbuf == NULL) {
  12.797 -        ALSA_CloseAudio(this);
  12.798 -        return (-1);
  12.799 +    this->hidden->mixlen = this->spec.size;
  12.800 +    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
  12.801 +    if (this->hidden->mixbuf == NULL) {
  12.802 +        ALSA_CloseDevice(this);
  12.803 +        SDL_OutOfMemory();
  12.804 +        return 0;
  12.805      }
  12.806 -    SDL_memset(mixbuf, spec->silence, spec->size);
  12.807 +    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
  12.808  
  12.809      /* Get the parent process id (we're the parent of the audio thread) */
  12.810 -    parent = getpid();
  12.811 +    this->hidden->parent = getpid();
  12.812  
  12.813      /* Switch to blocking mode for playback */
  12.814 -    SDL_NAME(snd_pcm_nonblock) (pcm_handle, 0);
  12.815 +    ALSA_snd_pcm_nonblock(pcm_handle, 0);
  12.816  
  12.817      /* We're ready to rock and roll. :-) */
  12.818 -    return (0);
  12.819 +    return 1;
  12.820  }
  12.821  
  12.822 +static void
  12.823 +ALSA_Deinitialize(void)
  12.824 +{
  12.825 +    UnloadALSALibrary();
  12.826 +}
  12.827 +
  12.828 +static int
  12.829 +ALSA_Init(SDL_AudioDriverImpl *impl)
  12.830 +{
  12.831 +    if (LoadALSALibrary() < 0) {
  12.832 +        return 0;
  12.833 +    }
  12.834 +
  12.835 +    /* Set the function pointers */
  12.836 +    impl->OpenDevice = ALSA_OpenDevice;
  12.837 +    impl->WaitDevice = ALSA_WaitDevice;
  12.838 +    impl->GetDeviceBuf = ALSA_GetDeviceBuf;
  12.839 +    impl->PlayDevice = ALSA_PlayDevice;
  12.840 +    impl->CloseDevice = ALSA_CloseDevice;
  12.841 +    impl->Deinitialize = ALSA_Deinitialize;
  12.842 +    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: Add device enum! */
  12.843 +
  12.844 +    return 1;
  12.845 +}
  12.846 +
  12.847 +
  12.848 +AudioBootStrap ALSA_bootstrap = {
  12.849 +    DRIVER_NAME, "ALSA 0.9 PCM audio", ALSA_Init, 0
  12.850 +};
  12.851 +
  12.852  /* vi: set ts=4 sw=4 expandtab: */
    13.1 --- a/src/audio/alsa/SDL_alsa_audio.h	Sun Oct 01 16:10:41 2006 +0000
    13.2 +++ b/src/audio/alsa/SDL_alsa_audio.h	Tue Oct 17 09:15:21 2006 +0000
    13.3 @@ -30,7 +30,7 @@
    13.4  
    13.5  #include "../SDL_sysaudio.h"
    13.6  
    13.7 -/* Hidden "this" pointer for the video functions */
    13.8 +/* Hidden "this" pointer for the audio functions */
    13.9  #define _THIS	SDL_AudioDevice *this
   13.10  
   13.11  struct SDL_PrivateAudioData
   13.12 @@ -46,11 +46,5 @@
   13.13      int mixlen;
   13.14  };
   13.15  
   13.16 -/* Old variable names */
   13.17 -#define pcm_handle		(this->hidden->pcm_handle)
   13.18 -#define parent			(this->hidden->parent)
   13.19 -#define mixbuf			(this->hidden->mixbuf)
   13.20 -#define mixlen			(this->hidden->mixlen)
   13.21 -
   13.22  #endif /* _ALSA_PCM_audio_h */
   13.23  /* vi: set ts=4 sw=4 expandtab: */
    14.1 --- a/src/audio/amigaos/SDL_ahiaudio.c	Sun Oct 01 16:10:41 2006 +0000
    14.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3 @@ -1,360 +0,0 @@
    14.4 -/*
    14.5 -    SDL - Simple DirectMedia Layer
    14.6 -    Copyright (C) 1997-2006 Sam Lantinga
    14.7 -
    14.8 -    This library is free software; you can redistribute it and/or
    14.9 -    modify it under the terms of the GNU Lesser General Public
   14.10 -    License as published by the Free Software Foundation; either
   14.11 -    version 2.1 of the License, or (at your option) any later version.
   14.12 -
   14.13 -    This library is distributed in the hope that it will be useful,
   14.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14.16 -    Lesser General Public License for more details.
   14.17 -
   14.18 -    You should have received a copy of the GNU Lesser General Public
   14.19 -    License along with this library; if not, write to the Free Software
   14.20 -    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   14.21 -
   14.22 -    Sam Lantinga
   14.23 -    slouken@libsdl.org
   14.24 -*/
   14.25 -#include "SDL_config.h"
   14.26 -
   14.27 -/* Allow access to a raw mixing buffer (for AmigaOS) */
   14.28 -
   14.29 -#include "SDL_audio.h"
   14.30 -#include "../SDL_audio_c.h"
   14.31 -#include "SDL_ahiaudio.h"
   14.32 -
   14.33 -/* Audio driver functions */
   14.34 -static int AHI_OpenAudio(_THIS, SDL_AudioSpec * spec);
   14.35 -static void AHI_WaitAudio(_THIS);
   14.36 -static void AHI_PlayAudio(_THIS);
   14.37 -static Uint8 *AHI_GetAudioBuf(_THIS);
   14.38 -static void AHI_CloseAudio(_THIS);
   14.39 -
   14.40 -#ifndef __SASC
   14.41 -#define mymalloc(x) AllocVec(x,MEMF_PUBLIC)
   14.42 -#define myfree FreeVec
   14.43 -#else
   14.44 -#define mymalloc malloc
   14.45 -#define myfree free
   14.46 -#endif
   14.47 -
   14.48 -/* Audio driver bootstrap functions */
   14.49 -
   14.50 -static int
   14.51 -Audio_Available(void)
   14.52 -{
   14.53 -    int ok = 0;
   14.54 -    struct MsgPort *p;
   14.55 -    struct AHIRequest *req;
   14.56 -
   14.57 -    if (p = CreateMsgPort()) {
   14.58 -        if (req =
   14.59 -            (struct AHIRequest *) CreateIORequest(p,
   14.60 -                                                  sizeof(struct
   14.61 -                                                         AHIRequest))) {
   14.62 -            req->ahir_Version = 4;
   14.63 -
   14.64 -            if (!OpenDevice(AHINAME, 0, (struct IORequest *) req, NULL)) {
   14.65 -                D(bug("AHI available.\n"));
   14.66 -                ok = 1;
   14.67 -                CloseDevice((struct IORequest *) req);
   14.68 -            }
   14.69 -            DeleteIORequest((struct IORequest *) req);
   14.70 -        }
   14.71 -        DeleteMsgPort(p);
   14.72 -    }
   14.73 -
   14.74 -    D(if (!ok) bug("AHI not available\n"));
   14.75 -    return ok;
   14.76 -}
   14.77 -
   14.78 -static void
   14.79 -Audio_DeleteDevice(SDL_AudioDevice * device)
   14.80 -{
   14.81 -    SDL_free(device->hidden);
   14.82 -    SDL_free(device);
   14.83 -}
   14.84 -
   14.85 -static SDL_AudioDevice *
   14.86 -Audio_CreateDevice(int devindex)
   14.87 -{
   14.88 -    SDL_AudioDevice *this;
   14.89 -
   14.90 -#ifndef NO_AMIGADEBUG
   14.91 -    D(bug("AHI created...\n"));
   14.92 -#endif
   14.93 -
   14.94 -    /* Initialize all variables that we clean on shutdown */
   14.95 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
   14.96 -    if (this) {
   14.97 -        SDL_memset(this, 0, (sizeof *this));
   14.98 -        this->hidden = (struct SDL_PrivateAudioData *)
   14.99 -            SDL_malloc((sizeof *this->hidden));
  14.100 -    }
  14.101 -    if ((this == NULL) || (this->hidden == NULL)) {
  14.102 -        SDL_OutOfMemory();
  14.103 -        if (this) {
  14.104 -            SDL_free(this);
  14.105 -        }
  14.106 -        return (0);
  14.107 -    }
  14.108 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  14.109 -
  14.110 -    /* Set the function pointers */
  14.111 -    this->OpenAudio = AHI_OpenAudio;
  14.112 -    this->WaitAudio = AHI_WaitAudio;
  14.113 -    this->PlayAudio = AHI_PlayAudio;
  14.114 -    this->GetAudioBuf = AHI_GetAudioBuf;
  14.115 -    this->CloseAudio = AHI_CloseAudio;
  14.116 -
  14.117 -    this->free = Audio_DeleteDevice;
  14.118 -
  14.119 -    return this;
  14.120 -}
  14.121 -
  14.122 -AudioBootStrap AHI_bootstrap = {
  14.123 -    "AHI", Audio_Available, Audio_CreateDevice
  14.124 -};
  14.125 -
  14.126 -
  14.127 -void static
  14.128 -AHI_WaitAudio(_THIS)
  14.129 -{
  14.130 -    if (!CheckIO((struct IORequest *) audio_req[current_buffer])) {
  14.131 -        WaitIO((struct IORequest *) audio_req[current_buffer]);
  14.132 -//              AbortIO((struct IORequest *)audio_req[current_buffer]);
  14.133 -    }
  14.134 -}
  14.135 -
  14.136 -static void
  14.137 -AHI_PlayAudio(_THIS)
  14.138 -{
  14.139 -    if (playing > 1)
  14.140 -        WaitIO((struct IORequest *) audio_req[current_buffer]);
  14.141 -
  14.142 -    /* Write the audio data out */
  14.143 -    audio_req[current_buffer]->ahir_Std.io_Message.mn_Node.ln_Pri = 60;
  14.144 -    audio_req[current_buffer]->ahir_Std.io_Data = mixbuf[current_buffer];
  14.145 -    audio_req[current_buffer]->ahir_Std.io_Length = this->hidden->size;
  14.146 -    audio_req[current_buffer]->ahir_Std.io_Offset = 0;
  14.147 -    audio_req[current_buffer]->ahir_Std.io_Command = CMD_WRITE;
  14.148 -    audio_req[current_buffer]->ahir_Frequency = this->hidden->freq;
  14.149 -    audio_req[current_buffer]->ahir_Volume = 0x10000;
  14.150 -    audio_req[current_buffer]->ahir_Type = this->hidden->type;
  14.151 -    audio_req[current_buffer]->ahir_Position = 0x8000;
  14.152 -    audio_req[current_buffer]->ahir_Link =
  14.153 -        (playing > 0 ? audio_req[current_buffer ^ 1] : NULL);
  14.154 -
  14.155 -    SendIO((struct IORequest *) audio_req[current_buffer]);
  14.156 -    current_buffer ^= 1;
  14.157 -
  14.158 -    playing++;
  14.159 -}
  14.160 -
  14.161 -static Uint8 *
  14.162 -AHI_GetAudioBuf(_THIS)
  14.163 -{
  14.164 -    return (mixbuf[current_buffer]);
  14.165 -}
  14.166 -
  14.167 -static void
  14.168 -AHI_CloseAudio(_THIS)
  14.169 -{
  14.170 -    D(bug("Closing audio...\n"));
  14.171 -
  14.172 -    playing = 0;
  14.173 -
  14.174 -    if (audio_req[0]) {
  14.175 -        if (audio_req[1]) {
  14.176 -            D(bug("Break req[1]...\n"));
  14.177 -
  14.178 -            AbortIO((struct IORequest *) audio_req[1]);
  14.179 -            WaitIO((struct IORequest *) audio_req[1]);
  14.180 -        }
  14.181 -
  14.182 -        D(bug("Break req[0]...\n"));
  14.183 -
  14.184 -        AbortIO((struct IORequest *) audio_req[0]);
  14.185 -        WaitIO((struct IORequest *) audio_req[0]);
  14.186 -
  14.187 -        if (audio_req[1]) {
  14.188 -            D(bug("Break AGAIN req[1]...\n"));
  14.189 -            AbortIO((struct IORequest *) audio_req[1]);
  14.190 -            WaitIO((struct IORequest *) audio_req[1]);
  14.191 -        }
  14.192 -// Double abort to be sure to break the dbuffering process.
  14.193 -
  14.194 -        SDL_Delay(200);
  14.195 -
  14.196 -        D(bug("Reqs breaked, closing device...\n"));
  14.197 -        CloseDevice((struct IORequest *) audio_req[0]);
  14.198 -        D(bug("Device closed, freeing memory...\n"));
  14.199 -        myfree(audio_req[1]);
  14.200 -        D(bug("Memory freed, deleting IOReq...\n"));
  14.201 -        DeleteIORequest((struct IORequest *) audio_req[0]);
  14.202 -        audio_req[0] = audio_req[1] = NULL;
  14.203 -    }
  14.204 -
  14.205 -    D(bug("Freeing mixbuf[0]...\n"));
  14.206 -    if (mixbuf[0] != NULL) {
  14.207 -        myfree(mixbuf[0]);
  14.208 -//              SDL_FreeAudioMem(mixbuf[0]);
  14.209 -        mixbuf[0] = NULL;
  14.210 -    }
  14.211 -
  14.212 -    D(bug("Freeing mixbuf[1]...\n"));
  14.213 -    if (mixbuf[1] != NULL) {
  14.214 -        myfree(mixbuf[1]);
  14.215 -//              SDL_FreeAudioMem(mixbuf[1]);
  14.216 -        mixbuf[1] = NULL;
  14.217 -    }
  14.218 -
  14.219 -    D(bug("Freeing audio_port...\n"));
  14.220 -
  14.221 -    if (audio_port != NULL) {
  14.222 -        DeleteMsgPort(audio_port);
  14.223 -        audio_port = NULL;
  14.224 -    }
  14.225 -    D(bug("...done!\n"));
  14.226 -}
  14.227 -
  14.228 -static int
  14.229 -AHI_OpenAudio(_THIS, SDL_AudioSpec * spec)
  14.230 -{
  14.231 -//      int width;
  14.232 -    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
  14.233 -    int valid_datatype = 1;
  14.234 -
  14.235 -    D(bug("AHI opening...\n"));
  14.236 -
  14.237 -    /* Determine the audio parameters from the AudioSpec */
  14.238 -    while ((!valid_datatype) && (test_format)) {
  14.239 -        valid_datatype = 1;
  14.240 -        switch (test_format) {
  14.241 -        case AUDIO_S8:
  14.242 -            D(bug("AUDIO_S8...\n"));
  14.243 -            spec->format = AUDIO_S8;
  14.244 -            this->hidden->bytespersample = 1;
  14.245 -            if (spec->channels < 2)
  14.246 -                this->hidden->type = AHIST_M8S;
  14.247 -            else
  14.248 -                this->hidden->type = AHIST_S8S;
  14.249 -            break;
  14.250 -
  14.251 -        case AUDIO_S16MSB:
  14.252 -            D(bug("AUDIO_S16MSB...\n"));
  14.253 -            spec->format = AUDIO_S16MSB;
  14.254 -            this->hidden->bytespersample = 2;
  14.255 -            if (spec->channels < 2)
  14.256 -                this->hidden->type = AHIST_M16S;
  14.257 -            else
  14.258 -                this->hidden->type = AHIST_S16S;
  14.259 -            break;
  14.260 -
  14.261 -        case AUDIO_S32MSB:
  14.262 -            D(bug("AUDIO_S32MSB...\n"));
  14.263 -            spec->format = AUDIO_S32MSB;
  14.264 -            this->hidden->bytespersample = 4;
  14.265 -            if (spec->channels < 2)
  14.266 -                this->hidden->type = AHIST_M32S;
  14.267 -            else
  14.268 -                this->hidden->type = AHIST_S32S;
  14.269 -            break;
  14.270 -
  14.271 -        default:
  14.272 -            valid_datatype = 0;
  14.273 -            test_format = SDL_NextAudioFormat();
  14.274 -            break;
  14.275 -        }
  14.276 -    }
  14.277 -
  14.278 -    if (!valid_datatype) {      /* shouldn't happen, but just in case... */
  14.279 -        SDL_SetError("Unsupported audio format");
  14.280 -        return (-1);
  14.281 -    }
  14.282 -
  14.283 -    if (spec->channels > 2) {
  14.284 -        spec->channels = 2;     /* will convert at higher level. */
  14.285 -    }
  14.286 -
  14.287 -    D(bug("Before CalculateAudioSpec\n"));
  14.288 -    /* Update the fragment size as size in bytes */
  14.289 -    SDL_CalculateAudioSpec(spec);
  14.290 -
  14.291 -    D(bug("Before CreateMsgPort\n"));
  14.292 -
  14.293 -    if (!(audio_port = CreateMsgPort())) {
  14.294 -        SDL_SetError("Unable to create a MsgPort");
  14.295 -        return -1;
  14.296 -    }
  14.297 -
  14.298 -    D(bug("Before CreateIORequest\n"));
  14.299 -
  14.300 -    if (!
  14.301 -        (audio_req[0] =
  14.302 -         (struct AHIRequest *) CreateIORequest(audio_port,
  14.303 -                                               sizeof(struct AHIRequest)))) {
  14.304 -        SDL_SetError("Unable to create an AHIRequest");
  14.305 -        DeleteMsgPort(audio_port);
  14.306 -        return -1;
  14.307 -    }
  14.308 -
  14.309 -    audio_req[0]->ahir_Version = 4;
  14.310 -
  14.311 -    if (OpenDevice(AHINAME, 0, (struct IORequest *) audio_req[0], NULL)) {
  14.312 -        SDL_SetError("Unable to open AHI device!\n");
  14.313 -        DeleteIORequest((struct IORequest *) audio_req[0]);
  14.314 -        DeleteMsgPort(audio_port);
  14.315 -        return -1;
  14.316 -    }
  14.317 -
  14.318 -    D(bug("AFTER opendevice\n"));
  14.319 -
  14.320 -    /* Set output frequency and size */
  14.321 -    this->hidden->freq = spec->freq;
  14.322 -    this->hidden->size = spec->size;
  14.323 -
  14.324 -    D(bug("Before buffer allocation\n"));
  14.325 -
  14.326 -    /* Allocate mixing buffer */
  14.327 -    mixbuf[0] = (Uint8 *) mymalloc(spec->size);
  14.328 -    mixbuf[1] = (Uint8 *) mymalloc(spec->size);
  14.329 -
  14.330 -    D(bug("Before audio_req allocation\n"));
  14.331 -
  14.332 -    if (!(audio_req[1] = mymalloc(sizeof(struct AHIRequest)))) {
  14.333 -        SDL_OutOfMemory();
  14.334 -        return (-1);
  14.335 -    }
  14.336 -
  14.337 -    D(bug("Before audio_req memcpy\n"));
  14.338 -
  14.339 -    SDL_memcpy(audio_req[1], audio_req[0], sizeof(struct AHIRequest));
  14.340 -
  14.341 -    if (mixbuf[0] == NULL || mixbuf[1] == NULL) {
  14.342 -        SDL_OutOfMemory();
  14.343 -        return (-1);
  14.344 -    }
  14.345 -
  14.346 -    D(bug("Before mixbuf memset\n"));
  14.347 -
  14.348 -    SDL_memset(mixbuf[0], spec->silence, spec->size);
  14.349 -    SDL_memset(mixbuf[1], spec->silence, spec->size);
  14.350 -
  14.351 -    current_buffer = 0;
  14.352 -    playing = 0;
  14.353 -
  14.354 -    D(bug
  14.355 -      ("AHI opened: freq:%ld mixbuf:%lx/%lx buflen:%ld bits:%ld channels:%ld\n",
  14.356 -       spec->freq, mixbuf[0], mixbuf[1], spec->size,
  14.357 -       this->hidden->bytespersample * 8, spec->channels));
  14.358 -
  14.359 -    /* We're ready to rock and roll. :-) */
  14.360 -    return (0);
  14.361 -}
  14.362 -
  14.363 -/* vi: set ts=4 sw=4 expandtab: */
    15.1 --- a/src/audio/amigaos/SDL_ahiaudio.h	Sun Oct 01 16:10:41 2006 +0000
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,62 +0,0 @@
    15.4 -/*
    15.5 -    SDL - Simple DirectMedia Layer
    15.6 -    Copyright (C) 1997-2006 Sam Lantinga
    15.7 -
    15.8 -    This library is free software; you can redistribute it and/or
    15.9 -    modify it under the terms of the GNU Lesser General Public
   15.10 -    License as published by the Free Software Foundation; either
   15.11 -    version 2.1 of the License, or (at your option) any later version.
   15.12 -
   15.13 -    This library is distributed in the hope that it will be useful,
   15.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15.16 -    Lesser General Public License for more details.
   15.17 -
   15.18 -    You should have received a copy of the GNU Lesser General Public
   15.19 -    License along with this library; if not, write to the Free Software
   15.20 -    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   15.21 -
   15.22 -    Sam Lantinga
   15.23 -    slouken@libsdl.org
   15.24 -*/
   15.25 -#include "SDL_config.h"
   15.26 -
   15.27 -#ifndef _SDL_ahiaudio_h
   15.28 -#define _SDL_ahiaudio_h
   15.29 -
   15.30 -#include <exec/exec.h>
   15.31 -#include <dos/dos.h>
   15.32 -#ifdef __SASC
   15.33 -#include <proto/exec.h>
   15.34 -#else
   15.35 -#include <inline/exec.h>
   15.36 -#endif
   15.37 -
   15.38 -#include <devices/ahi.h>
   15.39 -#include "mydebug.h"
   15.40 -
   15.41 -#include "../SDL_sysaudio.h"
   15.42 -
   15.43 -/* Hidden "this" pointer for the audio functions */
   15.44 -#define _THIS	SDL_AudioDevice *this
   15.45 -
   15.46 -struct SDL_PrivateAudioData
   15.47 -{
   15.48 -    /* The handle for the audio device */
   15.49 -    struct AHIRequest *audio_req[2];
   15.50 -    struct MsgPort *audio_port;
   15.51 -    Sint32 freq, type, bytespersample, size;
   15.52 -    Uint8 *mixbuf[2];           /* The app mixing buffer */
   15.53 -    int current_buffer;
   15.54 -    Uint32 playing;
   15.55 -};
   15.56 -
   15.57 -/* Old variable names */
   15.58 -#define audio_port		(this->hidden->audio_port)
   15.59 -#define audio_req		(this->hidden->audio_req)
   15.60 -#define mixbuf			(this->hidden->mixbuf)
   15.61 -#define current_buffer		(this->hidden->current_buffer)
   15.62 -#define playing			(this->hidden->playing)
   15.63 -
   15.64 -#endif /* _SDL_ahiaudio_h */
   15.65 -/* vi: set ts=4 sw=4 expandtab: */
    16.1 --- a/src/audio/arts/SDL_artsaudio.c	Sun Oct 01 16:10:41 2006 +0000
    16.2 +++ b/src/audio/arts/SDL_artsaudio.c	Tue Oct 17 09:15:21 2006 +0000
    16.3 @@ -27,7 +27,6 @@
    16.4  #include "SDL_audio.h"
    16.5  #include "../SDL_audiomem.h"
    16.6  #include "../SDL_audio_c.h"
    16.7 -#include "../SDL_audiodev_c.h"
    16.8  #include "SDL_artsaudio.h"
    16.9  
   16.10  #ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
   16.11 @@ -40,19 +39,12 @@
   16.12  /* The tag name used by artsc audio */
   16.13  #define ARTS_DRIVER_NAME         "arts"
   16.14  
   16.15 -/* Audio driver functions */
   16.16 -static int ARTS_OpenAudio(_THIS, SDL_AudioSpec * spec);
   16.17 -static void ARTS_WaitAudio(_THIS);
   16.18 -static void ARTS_PlayAudio(_THIS);
   16.19 -static Uint8 *ARTS_GetAudioBuf(_THIS);
   16.20 -static void ARTS_CloseAudio(_THIS);
   16.21 -
   16.22  #ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
   16.23  
   16.24  static const char *arts_library = SDL_AUDIO_DRIVER_ARTS_DYNAMIC;
   16.25  static void *arts_handle = NULL;
   16.26 -static int arts_loaded = 0;
   16.27  
   16.28 +/* !!! FIXME: I hate this SDL_NAME clutter...it makes everything so messy! */
   16.29  static int (*SDL_NAME(arts_init)) (void);
   16.30  static void (*SDL_NAME(arts_free)) (void);
   16.31  static arts_stream_t(*SDL_NAME(arts_play_stream)) (int rate, int bits,
   16.32 @@ -65,28 +57,32 @@
   16.33  static int (*SDL_NAME(arts_write)) (arts_stream_t s, const void *buffer,
   16.34                                      int count);
   16.35  static void (*SDL_NAME(arts_close_stream)) (arts_stream_t s);
   16.36 +static void (*SDL_NAME(arts_close_stream)) (arts_stream_t s);
   16.37 +static const char *(*SDL_NAME(arts_error_text)) (int errorcode);
   16.38  
   16.39 +#define SDL_ARTS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
   16.40  static struct
   16.41  {
   16.42      const char *name;
   16.43      void **func;
   16.44  } arts_functions[] = {
   16.45 -    {
   16.46 -    "arts_init", (void **) &SDL_NAME(arts_init)}, {
   16.47 -    "arts_free", (void **) &SDL_NAME(arts_free)}, {
   16.48 -    "arts_play_stream", (void **) &SDL_NAME(arts_play_stream)}, {
   16.49 -    "arts_stream_set", (void **) &SDL_NAME(arts_stream_set)}, {
   16.50 -    "arts_stream_get", (void **) &SDL_NAME(arts_stream_get)}, {
   16.51 -    "arts_write", (void **) &SDL_NAME(arts_write)}, {
   16.52 -"arts_close_stream", (void **) &SDL_NAME(arts_close_stream)},};
   16.53 +    SDL_ARTS_SYM(arts_init),
   16.54 +    SDL_ARTS_SYM(arts_free),
   16.55 +    SDL_ARTS_SYM(arts_play_stream),
   16.56 +    SDL_ARTS_SYM(arts_stream_set),
   16.57 +    SDL_ARTS_SYM(arts_stream_get),
   16.58 +    SDL_ARTS_SYM(arts_write),
   16.59 +    SDL_ARTS_SYM(arts_close_stream),
   16.60 +    SDL_ARTS_SYM(arts_error_text),
   16.61 +};
   16.62 +#undef SDL_ARTS_SYM
   16.63  
   16.64  static void
   16.65  UnloadARTSLibrary()
   16.66  {
   16.67 -    if (arts_loaded) {
   16.68 +    if (arts_handle != NULL) {
   16.69          SDL_UnloadObject(arts_handle);
   16.70          arts_handle = NULL;
   16.71 -        arts_loaded = 0;
   16.72      }
   16.73  }
   16.74  
   16.75 @@ -95,20 +91,22 @@
   16.76  {
   16.77      int i, retval = -1;
   16.78  
   16.79 -    arts_handle = SDL_LoadObject(arts_library);
   16.80 -    if (arts_handle) {
   16.81 -        arts_loaded = 1;
   16.82 -        retval = 0;
   16.83 -        for (i = 0; i < SDL_arraysize(arts_functions); ++i) {
   16.84 -            *arts_functions[i].func =
   16.85 -                SDL_LoadFunction(arts_handle, arts_functions[i].name);
   16.86 -            if (!*arts_functions[i].func) {
   16.87 -                retval = -1;
   16.88 -                UnloadARTSLibrary();
   16.89 -                break;
   16.90 +    if (arts_handle == NULL) {
   16.91 +        arts_handle = SDL_LoadObject(arts_library);
   16.92 +        if (arts_handle != NULL) {
   16.93 +            retval = 0;
   16.94 +            for (i = 0; i < SDL_arraysize(arts_functions); ++i) {
   16.95 +                *arts_functions[i].func =
   16.96 +                    SDL_LoadFunction(arts_handle, arts_functions[i].name);
   16.97 +                if (!*arts_functions[i].func) {
   16.98 +                    retval = -1;
   16.99 +                    UnloadARTSLibrary();
  16.100 +                    break;
  16.101 +                }
  16.102              }
  16.103          }
  16.104      }
  16.105 +
  16.106      return retval;
  16.107  }
  16.108  
  16.109 @@ -128,117 +126,45 @@
  16.110  
  16.111  #endif /* SDL_AUDIO_DRIVER_ARTS_DYNAMIC */
  16.112  
  16.113 -/* Audio driver bootstrap functions */
  16.114 -
  16.115 -static int
  16.116 -Audio_Available(void)
  16.117 -{
  16.118 -    int available = 0;
  16.119 -
  16.120 -    if (LoadARTSLibrary() < 0) {
  16.121 -        return available;
  16.122 -    }
  16.123 -    if (SDL_NAME(arts_init) () == 0) {
  16.124 -#define ARTS_CRASH_HACK         /* Play a stream so aRts doesn't crash */
  16.125 -#ifdef ARTS_CRASH_HACK
  16.126 -        arts_stream_t stream2;
  16.127 -        stream2 = SDL_NAME(arts_play_stream) (44100, 16, 2, "SDL");
  16.128 -        SDL_NAME(arts_write) (stream2, "", 0);
  16.129 -        SDL_NAME(arts_close_stream) (stream2);
  16.130 -#endif
  16.131 -        available = 1;
  16.132 -        SDL_NAME(arts_free) ();
  16.133 -    }
  16.134 -    UnloadARTSLibrary();
  16.135 -
  16.136 -    return available;
  16.137 -}
  16.138 -
  16.139 -static void
  16.140 -Audio_DeleteDevice(SDL_AudioDevice * device)
  16.141 -{
  16.142 -    SDL_free(device->hidden);
  16.143 -    SDL_free(device);
  16.144 -    UnloadARTSLibrary();
  16.145 -}
  16.146 -
  16.147 -static SDL_AudioDevice *
  16.148 -Audio_CreateDevice(int devindex)
  16.149 -{
  16.150 -    SDL_AudioDevice *this;
  16.151 -
  16.152 -    /* Initialize all variables that we clean on shutdown */
  16.153 -    LoadARTSLibrary();
  16.154 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
  16.155 -    if (this) {
  16.156 -        SDL_memset(this, 0, (sizeof *this));
  16.157 -        this->hidden = (struct SDL_PrivateAudioData *)
  16.158 -            SDL_malloc((sizeof *this->hidden));
  16.159 -    }
  16.160 -    if ((this == NULL) || (this->hidden == NULL)) {
  16.161 -        SDL_OutOfMemory();
  16.162 -        if (this) {
  16.163 -            SDL_free(this);
  16.164 -        }
  16.165 -        return (0);
  16.166 -    }
  16.167 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  16.168 -    stream = 0;
  16.169 -
  16.170 -    /* Set the function pointers */
  16.171 -    this->OpenAudio = ARTS_OpenAudio;
  16.172 -    this->WaitAudio = ARTS_WaitAudio;
  16.173 -    this->PlayAudio = ARTS_PlayAudio;
  16.174 -    this->GetAudioBuf = ARTS_GetAudioBuf;
  16.175 -    this->CloseAudio = ARTS_CloseAudio;
  16.176 -
  16.177 -    this->free = Audio_DeleteDevice;
  16.178 -
  16.179 -    return this;
  16.180 -}
  16.181 -
  16.182 -AudioBootStrap ARTS_bootstrap = {
  16.183 -    ARTS_DRIVER_NAME, "Analog Realtime Synthesizer",
  16.184 -    Audio_Available, Audio_CreateDevice
  16.185 -};
  16.186 -
  16.187  /* This function waits until it is possible to write a full sound buffer */
  16.188  static void
  16.189 -ARTS_WaitAudio(_THIS)
  16.190 +ARTS_WaitDevice(_THIS)
  16.191  {
  16.192      Sint32 ticks;
  16.193  
  16.194      /* Check to see if the thread-parent process is still alive */
  16.195      {
  16.196          static int cnt = 0;
  16.197 -        /* Note that this only works with thread implementations 
  16.198 +        /* Note that this only works with thread implementations
  16.199             that use a different process id for each thread.
  16.200           */
  16.201 -        if (parent && (((++cnt) % 10) == 0)) {  /* Check every 10 loops */
  16.202 -            if (kill(parent, 0) < 0) {
  16.203 +        /* Check every 10 loops */
  16.204 +        if (this->hidden->parent && (((++cnt) % 10) == 0)) {
  16.205 +            if (kill(this->hidden->parent, 0) < 0) {
  16.206                  this->enabled = 0;
  16.207              }
  16.208          }
  16.209      }
  16.210  
  16.211      /* Use timer for general audio synchronization */
  16.212 -    ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS;
  16.213 +    ticks = ((Sint32) (this->hidden->next_frame-SDL_GetTicks())) - FUDGE_TICKS;
  16.214      if (ticks > 0) {
  16.215          SDL_Delay(ticks);
  16.216      }
  16.217  }
  16.218  
  16.219  static void
  16.220 -ARTS_PlayAudio(_THIS)
  16.221 +ARTS_PlayDevice(_THIS)
  16.222  {
  16.223 -    int written;
  16.224 -
  16.225      /* Write the audio data */
  16.226 -    written = SDL_NAME(arts_write) (stream, mixbuf, mixlen);
  16.227 +    int written = SDL_NAME(arts_write) (
  16.228 +                        this->hidden->stream,
  16.229 +                        this->hidden->mixbuf,
  16.230 +                        this->hidden->mixlen);
  16.231  
  16.232      /* If timer synchronization is enabled, set the next write frame */
  16.233 -    if (frame_ticks) {
  16.234 -        next_frame += frame_ticks;
  16.235 +    if (this->hidden->frame_ticks) {
  16.236 +        this->hidden->next_frame += this->hidden->frame_ticks;
  16.237      }
  16.238  
  16.239      /* If we couldn't write, assume fatal error for now */
  16.240 @@ -250,41 +176,57 @@
  16.241  #endif
  16.242  }
  16.243  
  16.244 -static Uint8 *
  16.245 -ARTS_GetAudioBuf(_THIS)
  16.246 +static void
  16.247 +ARTS_WaitDone(_THIS)
  16.248  {
  16.249 -    return (mixbuf);
  16.250 +    /* !!! FIXME: camp here until buffer drains... SDL_Delay(???); */
  16.251  }
  16.252  
  16.253 -static void
  16.254 -ARTS_CloseAudio(_THIS)
  16.255 +
  16.256 +static Uint8 *
  16.257 +ARTS_GetDeviceBuf(_THIS)
  16.258  {
  16.259 -    if (mixbuf != NULL) {
  16.260 -        SDL_FreeAudioMem(mixbuf);
  16.261 -        mixbuf = NULL;
  16.262 -    }
  16.263 -    if (stream) {
  16.264 -        SDL_NAME(arts_close_stream) (stream);
  16.265 -        stream = 0;
  16.266 -    }
  16.267 -    SDL_NAME(arts_free) ();
  16.268 +    return (this->hidden->mixbuf);
  16.269  }
  16.270  
  16.271 +
  16.272 +static void
  16.273 +ARTS_CloseDevice(_THIS)
  16.274 +{
  16.275 +    if (this->hidden != NULL) {
  16.276 +        if (this->hidden->mixbuf != NULL) {
  16.277 +            SDL_FreeAudioMem(this->hidden->mixbuf);
  16.278 +            this->hidden->mixbuf = NULL;
  16.279 +        }
  16.280 +        if (this->hidden->stream) {
  16.281 +            SDL_NAME(arts_close_stream) (this->hidden->stream);
  16.282 +            this->hidden->stream = 0;
  16.283 +        }
  16.284 +        SDL_NAME(arts_free) ();
  16.285 +        SDL_free(this->hidden);
  16.286 +        this->hidden = NULL;
  16.287 +    }
  16.288 +}
  16.289 +
  16.290 +
  16.291  static int
  16.292 -ARTS_OpenAudio(_THIS, SDL_AudioSpec * spec)
  16.293 +ARTS_OpenDevice(_THIS, const char *devname, int iscapture)
  16.294  {
  16.295 -    int bits, frag_spec;
  16.296 -    SDL_AudioFormat test_format, format;
  16.297 +    int rc = 0;
  16.298 +    int bits = 0, frag_spec = 0;
  16.299 +    SDL_AudioFormat test_format = 0, format = 0;
  16.300  
  16.301 -    /* Reset the timer synchronization flag */
  16.302 -    frame_ticks = 0.0;
  16.303 -
  16.304 -    mixbuf = NULL;
  16.305 +    /* Initialize all variables that we clean on shutdown */
  16.306 +    this->hidden = (struct SDL_PrivateAudioData *)
  16.307 +                        SDL_malloc((sizeof *this->hidden));
  16.308 +    if (this->hidden == NULL) {
  16.309 +        SDL_OutOfMemory();
  16.310 +        return 0;
  16.311 +    }
  16.312 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  16.313  
  16.314      /* Try for a closest match on audio format */
  16.315 -    format = 0;
  16.316 -    bits = 0;
  16.317 -    for (test_format = SDL_FirstAudioFormat(spec->format);
  16.318 +    for (test_format = SDL_FirstAudioFormat(this->spec.format);
  16.319           !format && test_format;) {
  16.320  #ifdef DEBUG_AUDIO
  16.321          fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
  16.322 @@ -307,51 +249,108 @@
  16.323          }
  16.324      }
  16.325      if (format == 0) {
  16.326 +        ARTS_CloseDevice(this);
  16.327          SDL_SetError("Couldn't find any hardware audio formats");
  16.328 -        return (-1);
  16.329 +        return 0;
  16.330      }
  16.331 -    spec->format = test_format;
  16.332 +    this->spec.format = test_format;
  16.333  
  16.334 -    if (SDL_NAME(arts_init) () != 0) {
  16.335 -        SDL_SetError("Unable to initialize ARTS");
  16.336 -        return (-1);
  16.337 +    if ((rc = SDL_NAME(arts_init) ()) != 0) {
  16.338 +        ARTS_CloseDevice(this);
  16.339 +        SDL_SetError( "Unable to initialize ARTS: %s",
  16.340 +                      SDL_NAME(arts_error_text)(rc) );
  16.341 +        return 0;
  16.342      }
  16.343 -    stream =
  16.344 -        SDL_NAME(arts_play_stream) (spec->freq, bits, spec->channels, "SDL");
  16.345 +    this->hidden->stream = SDL_NAME(arts_play_stream) (
  16.346 +                                            this->spec.freq,
  16.347 +                                            bits, this->spec.channels,
  16.348 +                                            "SDL");
  16.349  
  16.350      /* Calculate the final parameters for this audio specification */
  16.351 -    SDL_CalculateAudioSpec(spec);
  16.352 +    SDL_CalculateAudioSpec(&this->spec);
  16.353  
  16.354      /* Determine the power of two of the fragment size */
  16.355 -    for (frag_spec = 0; (0x01 << frag_spec) < spec->size; ++frag_spec);
  16.356 -    if ((0x01 << frag_spec) != spec->size) {
  16.357 +    for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec);
  16.358 +    if ((0x01 << frag_spec) != this->spec.size) {
  16.359 +        ARTS_CloseDevice(this);
  16.360          SDL_SetError("Fragment size must be a power of two");
  16.361 -        return (-1);
  16.362 +        return 0;
  16.363      }
  16.364      frag_spec |= 0x00020000;    /* two fragments, for low latency */
  16.365  
  16.366  #ifdef ARTS_P_PACKET_SETTINGS
  16.367 -    SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_SETTINGS, frag_spec);
  16.368 +    SDL_NAME(arts_stream_set) (this->hidden->stream,
  16.369 +                                ARTS_P_PACKET_SETTINGS, frag_spec);
  16.370  #else
  16.371 -    SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_SIZE,
  16.372 +    SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_SIZE,
  16.373                                 frag_spec & 0xffff);
  16.374 -    SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_COUNT, frag_spec >> 16);
  16.375 +    SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_COUNT,
  16.376 +                               frag_spec >> 16);
  16.377  #endif
  16.378 -    spec->size = SDL_NAME(arts_stream_get) (stream, ARTS_P_PACKET_SIZE);
  16.379 +    this->spec.size = SDL_NAME(arts_stream_get) (this->hidden->stream,
  16.380 +                                                 ARTS_P_PACKET_SIZE);
  16.381  
  16.382      /* Allocate mixing buffer */
  16.383 -    mixlen = spec->size;
  16.384 -    mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen);
  16.385 -    if (mixbuf == NULL) {
  16.386 -        return (-1);
  16.387 +    this->hidden->mixlen = this->spec.size;
  16.388 +    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
  16.389 +    if (this->hidden->mixbuf == NULL) {
  16.390 +        ARTS_CloseDevice(this);
  16.391 +        SDL_OutOfMemory();
  16.392 +        return 0;
  16.393      }
  16.394 -    SDL_memset(mixbuf, spec->silence, spec->size);
  16.395 +    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
  16.396  
  16.397      /* Get the parent process id (we're the parent of the audio thread) */
  16.398 -    parent = getpid();
  16.399 +    this->hidden->parent = getpid();
  16.400  
  16.401      /* We're ready to rock and roll. :-) */
  16.402 -    return (0);
  16.403 +    return 1;
  16.404  }
  16.405  
  16.406 +
  16.407 +static void
  16.408 +ARTS_Deinitialize(void)
  16.409 +{
  16.410 +    UnloadARTSLibrary();
  16.411 +}
  16.412 +
  16.413 +
  16.414 +static int
  16.415 +ARTS_Init(SDL_AudioDriverImpl *impl)
  16.416 +{
  16.417 +    if (LoadARTSLibrary() < 0) {
  16.418 +        return 0;
  16.419 +    } else {
  16.420 +        if (SDL_NAME(arts_init) () != 0) {
  16.421 +            UnloadARTSLibrary();
  16.422 +            SDL_SetError("ARTS: arts_init failed (no audio server?)");
  16.423 +            return 0;
  16.424 +        }
  16.425 +
  16.426 +        /* Play a stream so aRts doesn't crash */
  16.427 +        arts_stream_t stream;
  16.428 +        stream = SDL_NAME(arts_play_stream) (44100, 16, 2, "SDL");
  16.429 +        SDL_NAME(arts_write) (stream, "", 0);
  16.430 +        SDL_NAME(arts_close_stream) (stream);
  16.431 +        SDL_NAME(arts_free) ();
  16.432 +    }
  16.433 +
  16.434 +    /* Set the function pointers */
  16.435 +    impl->OpenDevice = ARTS_OpenDevice;
  16.436 +    impl->PlayDevice = ARTS_PlayDevice;
  16.437 +    impl->WaitDevice = ARTS_WaitDevice;
  16.438 +    impl->GetDeviceBuf = ARTS_GetDeviceBuf;
  16.439 +    impl->CloseDevice = ARTS_CloseDevice;
  16.440 +    impl->WaitDone = ARTS_WaitDone;
  16.441 +    impl->Deinitialize = ARTS_Deinitialize;
  16.442 +    impl->OnlyHasDefaultOutputDevice = 1;
  16.443 +
  16.444 +    return 1;
  16.445 +}
  16.446 +
  16.447 +
  16.448 +AudioBootStrap ARTS_bootstrap = {
  16.449 +    ARTS_DRIVER_NAME, "Analog RealTime Synthesizer", ARTS_Init, 0
  16.450 +};
  16.451 +
  16.452  /* vi: set ts=4 sw=4 expandtab: */
    17.1 --- a/src/audio/arts/SDL_artsaudio.h	Sun Oct 01 16:10:41 2006 +0000
    17.2 +++ b/src/audio/arts/SDL_artsaudio.h	Tue Oct 17 09:15:21 2006 +0000
    17.3 @@ -28,7 +28,7 @@
    17.4  
    17.5  #include "../SDL_sysaudio.h"
    17.6  
    17.7 -/* Hidden "this" pointer for the video functions */
    17.8 +/* Hidden "this" pointer for the audio functions */
    17.9  #define _THIS	SDL_AudioDevice *this
   17.10  
   17.11  struct SDL_PrivateAudioData
   17.12 @@ -49,13 +49,5 @@
   17.13  };
   17.14  #define FUDGE_TICKS	10      /* The scheduler overhead ticks per frame */
   17.15  
   17.16 -/* Old variable names */
   17.17 -#define stream			(this->hidden->stream)
   17.18 -#define parent			(this->hidden->parent)
   17.19 -#define mixbuf			(this->hidden->mixbuf)
   17.20 -#define mixlen			(this->hidden->mixlen)
   17.21 -#define frame_ticks		(this->hidden->frame_ticks)
   17.22 -#define next_frame		(this->hidden->next_frame)
   17.23 -
   17.24  #endif /* _SDL_artscaudio_h */
   17.25  /* vi: set ts=4 sw=4 expandtab: */
    18.1 --- a/src/audio/baudio/SDL_beaudio.cc	Sun Oct 01 16:10:41 2006 +0000
    18.2 +++ b/src/audio/baudio/SDL_beaudio.cc	Tue Oct 17 09:15:21 2006 +0000
    18.3 @@ -36,138 +36,81 @@
    18.4  #include "../../thread/beos/SDL_systhread_c.h"
    18.5  #include "SDL_beaudio.h"
    18.6  
    18.7 +}
    18.8  
    18.9 -/* Audio driver functions */
   18.10 -    static int BE_OpenAudio(_THIS, SDL_AudioSpec * spec);
   18.11 -    static void BE_WaitAudio(_THIS);
   18.12 -    static void BE_PlayAudio(_THIS);
   18.13 -    static Uint8 *BE_GetAudioBuf(_THIS);
   18.14 -    static void BE_CloseAudio(_THIS);
   18.15  
   18.16 -/* Audio driver bootstrap functions */
   18.17 +/* !!! FIXME: have the callback call the higher level to avoid code dupe. */
   18.18 +/* The BeOS callback for handling the audio buffer */
   18.19 +static void
   18.20 +FillSound(void *device, void *stream, size_t len,
   18.21 +          const media_raw_audio_format & format)
   18.22 +{
   18.23 +    SDL_AudioDevice *audio = (SDL_AudioDevice *) device;
   18.24  
   18.25 -    static int Audio_Available(void)
   18.26 -    {
   18.27 -        return (1);
   18.28 -    }
   18.29 +    /* Silence the buffer, since it's ours */
   18.30 +    SDL_memset(stream, audio->spec.silence, len);
   18.31  
   18.32 -    static void Audio_DeleteDevice(SDL_AudioDevice * device)
   18.33 -    {
   18.34 -        SDL_free(device->hidden);
   18.35 -        SDL_free(device);
   18.36 -    }
   18.37 +    /* Only do soemthing if audio is enabled */
   18.38 +    if (!audio->enabled)
   18.39 +        return;
   18.40  
   18.41 -    static SDL_AudioDevice *Audio_CreateDevice(int devindex)
   18.42 -    {
   18.43 -        SDL_AudioDevice *device;
   18.44 -
   18.45 -        /* Initialize all variables that we clean on shutdown */
   18.46 -        device = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
   18.47 -        if (device) {
   18.48 -            SDL_memset(device, 0, (sizeof *device));
   18.49 -            device->hidden = (struct SDL_PrivateAudioData *)
   18.50 -                SDL_malloc((sizeof *device->hidden));
   18.51 -        }
   18.52 -        if ((device == NULL) || (device->hidden == NULL)) {
   18.53 -            SDL_OutOfMemory();
   18.54 -            if (device) {
   18.55 -                SDL_free(device);
   18.56 -            }
   18.57 -            return (0);
   18.58 -        }
   18.59 -        SDL_memset(device->hidden, 0, (sizeof *device->hidden));
   18.60 -
   18.61 -        /* Set the function pointers */
   18.62 -        device->OpenAudio = BE_OpenAudio;
   18.63 -        device->WaitAudio = BE_WaitAudio;
   18.64 -        device->PlayAudio = BE_PlayAudio;
   18.65 -        device->GetAudioBuf = BE_GetAudioBuf;
   18.66 -        device->CloseAudio = BE_CloseAudio;
   18.67 -
   18.68 -        device->free = Audio_DeleteDevice;
   18.69 -
   18.70 -        return device;
   18.71 -    }
   18.72 -
   18.73 -    AudioBootStrap BAUDIO_bootstrap = {
   18.74 -        "baudio", "BeOS BSoundPlayer",
   18.75 -        Audio_Available, Audio_CreateDevice
   18.76 -    };
   18.77 -
   18.78 -/* The BeOS callback for handling the audio buffer */
   18.79 -    static void FillSound(void *device, void *stream, size_t len,
   18.80 -                          const media_raw_audio_format & format)
   18.81 -    {
   18.82 -        SDL_AudioDevice *audio = (SDL_AudioDevice *) device;
   18.83 -
   18.84 -        /* Silence the buffer, since it's ours */
   18.85 -        SDL_memset(stream, audio->spec.silence, len);
   18.86 -
   18.87 -        /* Only do soemthing if audio is enabled */
   18.88 -        if (!audio->enabled)
   18.89 -            return;
   18.90 -
   18.91 -        if (!audio->paused) {
   18.92 -            if (audio->convert.needed) {
   18.93 -                SDL_mutexP(audio->mixer_lock);
   18.94 -                (*audio->spec.callback) (audio->spec.userdata,
   18.95 +    if (!audio->paused) {
   18.96 +        if (audio->convert.needed) {
   18.97 +            SDL_mutexP(audio->mixer_lock);
   18.98 +            (*audio->spec.callback) (audio->spec.userdata,
   18.99                                           (Uint8 *) audio->convert.buf,
  18.100                                           audio->convert.len);
  18.101 -                SDL_mutexV(audio->mixer_lock);
  18.102 -                SDL_ConvertAudio(&audio->convert);
  18.103 -                SDL_memcpy(stream, audio->convert.buf,
  18.104 -                           audio->convert.len_cvt);
  18.105 -            } else {
  18.106 -                SDL_mutexP(audio->mixer_lock);
  18.107 -                (*audio->spec.callback) (audio->spec.userdata,
  18.108 -                                         (Uint8 *) stream, len);
  18.109 -                SDL_mutexV(audio->mixer_lock);
  18.110 -            }
  18.111 +            SDL_mutexV(audio->mixer_lock);
  18.112 +            SDL_ConvertAudio(&audio->convert);
  18.113 +            SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt);
  18.114 +        } else {
  18.115 +            SDL_mutexP(audio->mixer_lock);
  18.116 +            (*audio->spec.callback) (audio->spec.userdata,
  18.117 +                                        (Uint8 *) stream, len);
  18.118 +            SDL_mutexV(audio->mixer_lock);
  18.119          }
  18.120 -        return;
  18.121      }
  18.122 +}
  18.123  
  18.124 -/* Dummy functions -- we don't use thread-based audio */
  18.125 -    void BE_WaitAudio(_THIS)
  18.126 -    {
  18.127 -        return;
  18.128 -    }
  18.129 -    void BE_PlayAudio(_THIS)
  18.130 -    {
  18.131 -        return;
  18.132 -    }
  18.133 -    Uint8 *BE_GetAudioBuf(_THIS)
  18.134 -    {
  18.135 -        return (NULL);
  18.136 -    }
  18.137 -
  18.138 -    void BE_CloseAudio(_THIS)
  18.139 -    {
  18.140 -        if (audio_obj) {
  18.141 -            audio_obj->Stop();
  18.142 -            delete audio_obj;
  18.143 -            audio_obj = NULL;
  18.144 +static void
  18.145 +BEOSAUDIO_CloseDevice(_THIS)
  18.146 +{
  18.147 +    if (_this->hidden != NULL) {
  18.148 +        if (_this->hidden->audio_obj) {
  18.149 +            _this->hidden->audio_obj->Stop();
  18.150 +            delete _this->hidden->audio_obj;
  18.151 +            _this->hidden->audio_obj = NULL;
  18.152          }
  18.153  
  18.154 -        /* Quit the Be Application, if there's nothing left to do */
  18.155 -        SDL_QuitBeApp();
  18.156 +        delete _this->hidden;
  18.157 +        _this->hidden = NULL;
  18.158      }
  18.159 +}
  18.160  
  18.161 -    int BE_OpenAudio(_THIS, SDL_AudioSpec * spec)
  18.162 -    {
  18.163 -        int valid_datatype = 0;
  18.164 -        media_raw_audio_format format;
  18.165 -        SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
  18.166 +static int
  18.167 +BEOSAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
  18.168 +{
  18.169 +    int valid_datatype = 0;
  18.170 +    media_raw_audio_format format;
  18.171 +    SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
  18.172  
  18.173 -        /* Parse the audio format and fill the Be raw audio format */
  18.174 -        memset(&format, '\0', sizeof(media_raw_audio_format));
  18.175 -        format.byte_order = B_MEDIA_LITTLE_ENDIAN;
  18.176 -        format.frame_rate = (float) spec->freq;
  18.177 -        format.channel_count = spec->channels;  /* !!! FIXME: support > 2? */
  18.178 -        while ((!valid_datatype) && (test_format)) {
  18.179 -            valid_datatype = 1;
  18.180 -            spec->format = test_format;
  18.181 -            switch (test_format) {
  18.182 +    /* Initialize all variables that we clean on shutdown */
  18.183 +    _this->hidden = new SDL_PrivateAudioData;
  18.184 +    if (_this->hidden == NULL) {
  18.185 +        SDL_OutOfMemory();
  18.186 +        return 0;
  18.187 +    }
  18.188 +    SDL_memset(_this->hidden, 0, (sizeof *_this->hidden));
  18.189 +
  18.190 +    /* Parse the audio format and fill the Be raw audio format */
  18.191 +    SDL_memset(&format, '\0', sizeof(media_raw_audio_format));
  18.192 +    format.byte_order = B_MEDIA_LITTLE_ENDIAN;
  18.193 +    format.frame_rate = (float) _this->spec.freq;
  18.194 +    format.channel_count = _this->spec.channels;  /* !!! FIXME: support > 2? */
  18.195 +    while ((!valid_datatype) && (test_format)) {
  18.196 +        valid_datatype = 1;
  18.197 +        _this->spec.format = test_format;
  18.198 +        switch (test_format) {
  18.199              case AUDIO_S8:
  18.200                  format.format = media_raw_audio_format::B_AUDIO_CHAR;
  18.201                  break;
  18.202 @@ -207,43 +150,67 @@
  18.203                  valid_datatype = 0;
  18.204                  test_format = SDL_NextAudioFormat();
  18.205                  break;
  18.206 -            }
  18.207          }
  18.208 -
  18.209 -        format.buffer_size = spec->samples;
  18.210 -
  18.211 -        if (!valid_datatype) {  /* shouldn't happen, but just in case... */
  18.212 -            SDL_SetError("Unsupported audio format");
  18.213 -            return (-1);
  18.214 -        }
  18.215 -
  18.216 -        /* Initialize the Be Application, if it's not already started */
  18.217 -        if (SDL_InitBeApp() < 0) {
  18.218 -            return (-1);
  18.219 -        }
  18.220 -
  18.221 -        /* Calculate the final parameters for this audio specification */
  18.222 -        SDL_CalculateAudioSpec(spec);
  18.223 -
  18.224 -        /* Subscribe to the audio stream (creates a new thread) */
  18.225 -        {
  18.226 -            sigset_t omask;
  18.227 -            SDL_MaskSignals(&omask);
  18.228 -            audio_obj = new BSoundPlayer(&format, "SDL Audio", FillSound,
  18.229 -                                         NULL, _this);
  18.230 -            SDL_UnmaskSignals(&omask);
  18.231 -        }
  18.232 -        if (audio_obj->Start() == B_NO_ERROR) {
  18.233 -            audio_obj->SetHasData(true);
  18.234 -        } else {
  18.235 -            SDL_SetError("Unable to start Be audio");
  18.236 -            return (-1);
  18.237 -        }
  18.238 -
  18.239 -        /* We're running! */
  18.240 -        return (1);
  18.241      }
  18.242  
  18.243 -};                              /* Extern C */
  18.244 +    format.buffer_size = _this->spec.samples;
  18.245 +
  18.246 +    if (!valid_datatype) {  /* shouldn't happen, but just in case... */
  18.247 +        BEOSAUDIO_CloseDevice(_this);
  18.248 +        SDL_SetError("Unsupported audio format");
  18.249 +        return 0;
  18.250 +    }
  18.251 +
  18.252 +    /* Calculate the final parameters for this audio specification */
  18.253 +    SDL_CalculateAudioSpec(&_this->spec);
  18.254 +
  18.255 +    /* Subscribe to the audio stream (creates a new thread) */
  18.256 +    sigset_t omask;
  18.257 +    SDL_MaskSignals(&omask);
  18.258 +    _this->hidden->audio_obj = new BSoundPlayer(&format, "SDL Audio",
  18.259 +                                                FillSound, NULL, _this);
  18.260 +    SDL_UnmaskSignals(&omask);
  18.261 +
  18.262 +    if (_this->hidden->audio_obj->Start() == B_NO_ERROR) {
  18.263 +        _this->hidden->audio_obj->SetHasData(true);
  18.264 +    } else {
  18.265 +        BEOSAUDIO_CloseDevice(_this);
  18.266 +        SDL_SetError("Unable to start Be audio");
  18.267 +        return 0;
  18.268 +    }
  18.269 +
  18.270 +    /* We're running! */
  18.271 +    return 1;
  18.272 +}
  18.273 +
  18.274 +static void
  18.275 +BEOSAUDIO_Deinitialize(void)
  18.276 +{
  18.277 +    SDL_QuitBeApp();
  18.278 +}
  18.279 +
  18.280 +static int
  18.281 +BEOSAUDIO_Init(SDL_AudioDriverImpl *impl)
  18.282 +{
  18.283 +    /* Initialize the Be Application, if it's not already started */
  18.284 +    if (SDL_InitBeApp() < 0) {
  18.285 +        return 0;
  18.286 +    }
  18.287 +
  18.288 +    /* Set the function pointers */
  18.289 +    impl->OpenDevice = BEOSAUDIO_OpenDevice;
  18.290 +    impl->CloseDevice = BEOSAUDIO_CloseDevice;
  18.291 +    impl->Deinitialize = BEOSAUDIO_Deinitialize;
  18.292 +    impl->ProvidesOwnCallbackThread = 1;
  18.293 +    impl->OnlyHasDefaultOutputDevice = 1;
  18.294 +
  18.295 +    return 1;
  18.296 +}
  18.297 +
  18.298 +extern "C" { extern AudioBootStrap BEOSAUDIO_bootstrap; }
  18.299 +AudioBootStrap BEOSAUDIO_bootstrap = {
  18.300 +    "baudio", "BeOS BSoundPlayer", BEOSAUDIO_Init, 0
  18.301 +};
  18.302  
  18.303  /* vi: set ts=4 sw=4 expandtab: */
  18.304 +
    19.1 --- a/src/audio/baudio/SDL_beaudio.h	Sun Oct 01 16:10:41 2006 +0000
    19.2 +++ b/src/audio/baudio/SDL_beaudio.h	Tue Oct 17 09:15:21 2006 +0000
    19.3 @@ -21,12 +21,12 @@
    19.4  */
    19.5  #include "SDL_config.h"
    19.6  
    19.7 -#ifndef _SDL_lowaudio_h
    19.8 -#define _SDL_lowaudio_h
    19.9 +#ifndef _SDL_beaudio_h
   19.10 +#define _SDL_beaudio_h
   19.11  
   19.12  #include "../SDL_sysaudio.h"
   19.13  
   19.14 -/* Hidden "this" pointer for the video functions */
   19.15 +/* Hidden "this" pointer for the audio functions */
   19.16  #define _THIS	SDL_AudioDevice *_this
   19.17  
   19.18  struct SDL_PrivateAudioData
   19.19 @@ -34,8 +34,6 @@
   19.20      BSoundPlayer *audio_obj;
   19.21  };
   19.22  
   19.23 -/* Old variable names */
   19.24 -#define audio_obj	(_this->hidden->audio_obj)
   19.25 +#endif /* _SDL_beaudio_h */
   19.26  
   19.27 -#endif /* _SDL_lowaudio_h */
   19.28  /* vi: set ts=4 sw=4 expandtab: */
    20.1 --- a/src/audio/bsd/SDL_bsdaudio.c	Sun Oct 01 16:10:41 2006 +0000
    20.2 +++ b/src/audio/bsd/SDL_bsdaudio.c	Tue Oct 17 09:15:21 2006 +0000
    20.3 @@ -61,195 +61,91 @@
    20.4  /* #define DEBUG_AUDIO_STREAM */
    20.5  
    20.6  #ifdef USE_BLOCKING_WRITES
    20.7 -#define OPEN_FLAGS	O_WRONLY
    20.8 +#define OPEN_FLAGS_OUTPUT O_WRONLY
    20.9 +#define OPEN_FLAGS_INPUT O_RDONLY
   20.10  #else
   20.11 -#define OPEN_FLAGS	(O_WRONLY|O_NONBLOCK)
   20.12 +#define OPEN_FLAGS_OUTPUT (O_WRONLY|O_NONBLOCK)
   20.13 +#define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK)
   20.14  #endif
   20.15  
   20.16 -/* Audio driver functions */
   20.17 -static void OBSD_WaitAudio(_THIS);
   20.18 -static int OBSD_OpenAudio(_THIS, SDL_AudioSpec * spec);
   20.19 -static void OBSD_PlayAudio(_THIS);
   20.20 -static Uint8 *OBSD_GetAudioBuf(_THIS);
   20.21 -static void OBSD_CloseAudio(_THIS);
   20.22 +/* !!! FIXME: so much cut and paste with dsp/dma drivers... */
   20.23 +static char **outputDevices = NULL;
   20.24 +static int outputDeviceCount = 0;
   20.25 +static char **inputDevices = NULL;
   20.26 +static int inputDeviceCount = 0;
   20.27  
   20.28 -#ifdef DEBUG_AUDIO
   20.29 -static void OBSD_Status(_THIS);
   20.30 -#endif
   20.31 +static inline void
   20.32 +free_device_list(char ***devs, int *count)
   20.33 +{
   20.34 +    SDL_FreeUnixAudioDevices(devs, count);
   20.35 +}
   20.36  
   20.37 -/* Audio driver bootstrap functions */
   20.38 +static inline void
   20.39 +build_device_list(int iscapture, char ***devs, int *count)
   20.40 +{
   20.41 +    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
   20.42 +    free_device_list(devs, count);
   20.43 +    SDL_EnumUnixAudioDevices(flags, 0, NULL, devs, count);
   20.44 +}
   20.45 +
   20.46 +static inline void
   20.47 +build_device_lists(void)
   20.48 +{
   20.49 +    build_device_list(0, &outputDevices, &outputDeviceCount);
   20.50 +    build_device_list(1, &inputDevices, &inputDeviceCount);
   20.51 +}
   20.52 +
   20.53 +
   20.54 +static inline void
   20.55 +free_device_lists(void)
   20.56 +{
   20.57 +    free_device_list(&outputDevices, &outputDeviceCount);
   20.58 +    free_device_list(&inputDevices, &inputDeviceCount);
   20.59 +}
   20.60 +
   20.61 +
   20.62 +static void
   20.63 +BSDAUDIO_Deinitialize(void)
   20.64 +{
   20.65 +    free_device_lists();
   20.66 +}
   20.67 +
   20.68  
   20.69  static int
   20.70 -Audio_Available(void)
   20.71 +BSDAUDIO_DetectDevices(int iscapture)
   20.72  {
   20.73 -    int fd;
   20.74 -    int available;
   20.75 +    if (iscapture) {
   20.76 +        build_device_list(1, &inputDevices, &inputDeviceCount);
   20.77 +        return inputDeviceCount;
   20.78 +    } else {
   20.79 +        build_device_list(0, &outputDevices, &outputDeviceCount);
   20.80 +        return outputDeviceCount;
   20.81 +    }
   20.82  
   20.83 -    available = 0;
   20.84 -    fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
   20.85 -    if (fd >= 0) {
   20.86 -        available = 1;
   20.87 -        close(fd);
   20.88 -    }
   20.89 -    return (available);
   20.90 +    return 0;  /* shouldn't ever hit this. */
   20.91  }
   20.92  
   20.93 -static void
   20.94 -Audio_DeleteDevice(SDL_AudioDevice * device)
   20.95 +static const char *
   20.96 +BSDAUDIO_GetDeviceName(int index, int iscapture)
   20.97  {
   20.98 -    SDL_free(device->hidden);
   20.99 -    SDL_free(device);
  20.100 +    if ((iscapture) && (index < inputDeviceCount)) {
  20.101 +        return inputDevices[index];
  20.102 +    } else if ((!iscapture) && (index < outputDeviceCount)) {
  20.103 +        return outputDevices[index];
  20.104 +    }
  20.105 +
  20.106 +    SDL_SetError("No such device");
  20.107 +    return NULL;
  20.108  }
  20.109  
  20.110 -static SDL_AudioDevice *
  20.111 -Audio_CreateDevice(int devindex)
  20.112 -{
  20.113 -    SDL_AudioDevice *this;
  20.114 -
  20.115 -    /* Initialize all variables that we clean on shutdown */
  20.116 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
  20.117 -    if (this) {
  20.118 -        SDL_memset(this, 0, (sizeof *this));
  20.119 -        this->hidden = (struct SDL_PrivateAudioData *)
  20.120 -            SDL_malloc((sizeof *this->hidden));
  20.121 -    }
  20.122 -    if ((this == NULL) || (this->hidden == NULL)) {
  20.123 -        SDL_OutOfMemory();
  20.124 -        if (this)
  20.125 -            SDL_free(this);
  20.126 -        return (0);
  20.127 -    }
  20.128 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  20.129 -    audio_fd = -1;
  20.130 -
  20.131 -    /* Set the function pointers */
  20.132 -    this->OpenAudio = OBSD_OpenAudio;
  20.133 -    this->WaitAudio = OBSD_WaitAudio;
  20.134 -    this->PlayAudio = OBSD_PlayAudio;
  20.135 -    this->GetAudioBuf = OBSD_GetAudioBuf;
  20.136 -    this->CloseAudio = OBSD_CloseAudio;
  20.137 -
  20.138 -    this->free = Audio_DeleteDevice;
  20.139 -
  20.140 -    return this;
  20.141 -}
  20.142 -
  20.143 -AudioBootStrap BSD_AUDIO_bootstrap = {
  20.144 -    BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC,
  20.145 -    Audio_Available, Audio_CreateDevice
  20.146 -};
  20.147 -
  20.148 -/* This function waits until it is possible to write a full sound buffer */
  20.149 -static void
  20.150 -OBSD_WaitAudio(_THIS)
  20.151 -{
  20.152 -#ifndef USE_BLOCKING_WRITES     /* Not necessary when using blocking writes */
  20.153 -    /* See if we need to use timed audio synchronization */
  20.154 -    if (frame_ticks) {
  20.155 -        /* Use timer for general audio synchronization */
  20.156 -        Sint32 ticks;
  20.157 -
  20.158 -        ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS;
  20.159 -        if (ticks > 0) {
  20.160 -            SDL_Delay(ticks);
  20.161 -        }
  20.162 -    } else {
  20.163 -        /* Use select() for audio synchronization */
  20.164 -        fd_set fdset;
  20.165 -        struct timeval timeout;
  20.166 -
  20.167 -        FD_ZERO(&fdset);
  20.168 -        FD_SET(audio_fd, &fdset);
  20.169 -        timeout.tv_sec = 10;
  20.170 -        timeout.tv_usec = 0;
  20.171 -#ifdef DEBUG_AUDIO
  20.172 -        fprintf(stderr, "Waiting for audio to get ready\n");
  20.173 -#endif
  20.174 -        if (select(audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) {
  20.175 -            const char *message =
  20.176 -                "Audio timeout - buggy audio driver? (disabled)";
  20.177 -            /* In general we should never print to the screen,
  20.178 -               but in this case we have no other way of letting
  20.179 -               the user know what happened.
  20.180 -             */
  20.181 -            fprintf(stderr, "SDL: %s\n", message);
  20.182 -            this->enabled = 0;
  20.183 -            /* Don't try to close - may hang */
  20.184 -            audio_fd = -1;
  20.185 -#ifdef DEBUG_AUDIO
  20.186 -            fprintf(stderr, "Done disabling audio\n");
  20.187 -#endif
  20.188 -        }
  20.189 -#ifdef DEBUG_AUDIO
  20.190 -        fprintf(stderr, "Ready!\n");
  20.191 -#endif
  20.192 -    }
  20.193 -#endif /* !USE_BLOCKING_WRITES */
  20.194 -}
  20.195  
  20.196  static void
  20.197 -OBSD_PlayAudio(_THIS)
  20.198 +BSDAUDIO_Status(_THIS)
  20.199  {
  20.200 -    int written, p = 0;
  20.201 -
  20.202 -    /* Write the audio data, checking for EAGAIN on broken audio drivers */
  20.203 -    do {
  20.204 -        written = write(audio_fd, &mixbuf[p], mixlen - p);
  20.205 -        if (written > 0)
  20.206 -            p += written;
  20.207 -        if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
  20.208 -            /* Non recoverable error has occurred. It should be reported!!! */
  20.209 -            perror("audio");
  20.210 -            break;
  20.211 -        }
  20.212 -
  20.213 -        if (p < written
  20.214 -            || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) {
  20.215 -            SDL_Delay(1);       /* Let a little CPU time go by */
  20.216 -        }
  20.217 -    }
  20.218 -    while (p < written);
  20.219 -
  20.220 -    /* If timer synchronization is enabled, set the next write frame */
  20.221 -    if (frame_ticks) {
  20.222 -        next_frame += frame_ticks;
  20.223 -    }
  20.224 -
  20.225 -    /* If we couldn't write, assume fatal error for now */
  20.226 -    if (written < 0) {
  20.227 -        this->enabled = 0;
  20.228 -    }
  20.229  #ifdef DEBUG_AUDIO
  20.230 -    fprintf(stderr, "Wrote %d bytes of audio data\n", written);
  20.231 -#endif
  20.232 -}
  20.233 -
  20.234 -static Uint8 *
  20.235 -OBSD_GetAudioBuf(_THIS)
  20.236 -{
  20.237 -    return (mixbuf);
  20.238 -}
  20.239 -
  20.240 -static void
  20.241 -OBSD_CloseAudio(_THIS)
  20.242 -{
  20.243 -    if (mixbuf != NULL) {
  20.244 -        SDL_FreeAudioMem(mixbuf);
  20.245 -        mixbuf = NULL;
  20.246 -    }
  20.247 -    if (audio_fd >= 0) {
  20.248 -        close(audio_fd);
  20.249 -        audio_fd = -1;
  20.250 -    }
  20.251 -}
  20.252 -
  20.253 -#ifdef DEBUG_AUDIO
  20.254 -void
  20.255 -OBSD_Status(_THIS)
  20.256 -{
  20.257      audio_info_t info;
  20.258  
  20.259 -    if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) {
  20.260 +    if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
  20.261          fprintf(stderr, "AUDIO_GETINFO failed.\n");
  20.262          return;
  20.263      }
  20.264 @@ -269,46 +165,18 @@
  20.265              "waiting		:   %s\n"
  20.266              "active		:   %s\n"
  20.267              "",
  20.268 -            info.
  20.269 -            play.
  20.270 -            buffer_size,
  20.271 -            info.
  20.272 -            play.
  20.273 -            sample_rate,
  20.274 -            info.
  20.275 -            play.
  20.276 -            channels,
  20.277 -            info.
  20.278 -            play.
  20.279 -            precision,
  20.280 -            info.
  20.281 -            play.
  20.282 -            encoding,
  20.283 -            info.
  20.284 -            play.
  20.285 -            seek,
  20.286 -            info.
  20.287 -            play.
  20.288 -            samples,
  20.289 -            info.
  20.290 -            play.
  20.291 -            eof,
  20.292 -            info.
  20.293 -            play.
  20.294 -            pause
  20.295 -            ?
  20.296 -            "yes"
  20.297 -            :
  20.298 -            "no",
  20.299 -            info.
  20.300 -            play.
  20.301 -            error
  20.302 -            ?
  20.303 -            "yes"
  20.304 -            :
  20.305 -            "no",
  20.306 -            info.
  20.307 -            play.waiting ? "yes" : "no", info.play.active ? "yes" : "no");
  20.308 +            info.play.buffer_size,
  20.309 +            info.play.sample_rate,
  20.310 +            info.play.channels,
  20.311 +            info.play.precision,
  20.312 +            info.play.encoding,
  20.313 +            info.play.seek,
  20.314 +            info.play.samples,
  20.315 +            info.play.eof,
  20.316 +            info.play.pause ? "yes" : "no",
  20.317 +            info.play.error ? "yes" : "no",
  20.318 +            info.play.waiting ? "yes" : "no",
  20.319 +            info.play.active ? "yes" : "no");
  20.320  
  20.321      fprintf(stderr, "\n"
  20.322              "[audio info]\n"
  20.323 @@ -324,42 +192,170 @@
  20.324              (info.mode == AUMODE_PLAY) ? "PLAY"
  20.325              : (info.mode = AUMODE_RECORD) ? "RECORD"
  20.326              : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?"));
  20.327 +#endif /* DEBUG_AUDIO */
  20.328  }
  20.329 -#endif /* DEBUG_AUDIO */
  20.330 +
  20.331 +
  20.332 +/* This function waits until it is possible to write a full sound buffer */
  20.333 +static void
  20.334 +BSDAUDIO_WaitDevice(_THIS)
  20.335 +{
  20.336 +#ifndef USE_BLOCKING_WRITES     /* Not necessary when using blocking writes */
  20.337 +    /* See if we need to use timed audio synchronization */
  20.338 +    if (this->hidden->frame_ticks) {
  20.339 +        /* Use timer for general audio synchronization */
  20.340 +        Sint32 ticks;
  20.341 +
  20.342 +        ticks = ((Sint32)(this->hidden->next_frame-SDL_GetTicks()))-FUDGE_TICKS;
  20.343 +        if (ticks > 0) {
  20.344 +            SDL_Delay(ticks);
  20.345 +        }
  20.346 +    } else {
  20.347 +        /* Use select() for audio synchronization */
  20.348 +        fd_set fdset;
  20.349 +        struct timeval timeout;
  20.350 +
  20.351 +        FD_ZERO(&fdset);
  20.352 +        FD_SET(this->hidden->audio_fd, &fdset);
  20.353 +        timeout.tv_sec = 10;
  20.354 +        timeout.tv_usec = 0;
  20.355 +#ifdef DEBUG_AUDIO
  20.356 +        fprintf(stderr, "Waiting for audio to get ready\n");
  20.357 +#endif
  20.358 +        if (select(this->hidden->audio_fd+1,NULL,&fdset,NULL,&timeout) <= 0) {
  20.359 +            const char *message =
  20.360 +                "Audio timeout - buggy audio driver? (disabled)";
  20.361 +            /* In general we should never print to the screen,
  20.362 +               but in this case we have no other way of letting
  20.363 +               the user know what happened.
  20.364 +             */
  20.365 +            fprintf(stderr, "SDL: %s\n", message);
  20.366 +            this->enabled = 0;
  20.367 +            /* Don't try to close - may hang */
  20.368 +            this->hidden->audio_fd = -1;
  20.369 +#ifdef DEBUG_AUDIO
  20.370 +            fprintf(stderr, "Done disabling audio\n");
  20.371 +#endif
  20.372 +        }
  20.373 +#ifdef DEBUG_AUDIO
  20.374 +        fprintf(stderr, "Ready!\n");
  20.375 +#endif
  20.376 +    }
  20.377 +#endif /* !USE_BLOCKING_WRITES */
  20.378 +}
  20.379 +
  20.380 +static void
  20.381 +BSDAUDIO_PlayDevice(_THIS)
  20.382 +{
  20.383 +    int written, p = 0;
  20.384 +
  20.385 +    /* Write the audio data, checking for EAGAIN on broken audio drivers */
  20.386 +    do {
  20.387 +        written = write(this->hidden->audio_fd,
  20.388 +                        &this->hidden->mixbuf[p],
  20.389 +                        this->hidden->mixlen - p);
  20.390 +
  20.391 +        if (written > 0)
  20.392 +            p += written;
  20.393 +        if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
  20.394 +            /* Non recoverable error has occurred. It should be reported!!! */
  20.395 +            perror("audio");
  20.396 +            break;
  20.397 +        }
  20.398 +
  20.399 +        if (p < written
  20.400 +            || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) {
  20.401 +            SDL_Delay(1);       /* Let a little CPU time go by */
  20.402 +        }
  20.403 +    }
  20.404 +    while (p < written);
  20.405 +
  20.406 +    /* If timer synchronization is enabled, set the next write frame */
  20.407 +    if (this->hidden->frame_ticks) {
  20.408 +        this->hidden->next_frame += this->hidden->frame_ticks;
  20.409 +    }
  20.410 +
  20.411 +    /* If we couldn't write, assume fatal error for now */
  20.412 +    if (written < 0) {
  20.413 +        this->enabled = 0;
  20.414 +    }
  20.415 +#ifdef DEBUG_AUDIO
  20.416 +    fprintf(stderr, "Wrote %d bytes of audio data\n", written);
  20.417 +#endif
  20.418 +}
  20.419 +
  20.420 +static Uint8 *
  20.421 +BSDAUDIO_GetDeviceBuf(_THIS)
  20.422 +{
  20.423 +    return (this->hidden->mixbuf);
  20.424 +}
  20.425 +
  20.426 +static void
  20.427 +BSDAUDIO_CloseDevice(_THIS)
  20.428 +{
  20.429 +    if (this->hidden != NULL) {
  20.430 +        if (this->hidden->mixbuf != NULL) {
  20.431 +            SDL_FreeAudioMem(this->hidden->mixbuf);
  20.432 +            this->hidden->mixbuf = NULL;
  20.433 +        }
  20.434 +        if (this->hidden->audio_fd >= 0) {
  20.435 +            close(this->hidden->audio_fd);
  20.436 +            this->hidden->audio_fd = -1;
  20.437 +        }
  20.438 +        SDL_free(this->hidden);
  20.439 +        this->hidden = NULL;
  20.440 +    }
  20.441 +}
  20.442  
  20.443  static int
  20.444 -OBSD_OpenAudio(_THIS, SDL_AudioSpec * spec)
  20.445 +BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
  20.446  {
  20.447 -    char audiodev[64];
  20.448 -    SDL_AudioFormat format;
  20.449 +    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
  20.450 +    SDL_AudioFormat format = 0;
  20.451      audio_info_t info;
  20.452  
  20.453 +    /* We don't care what the devname is...we'll try to open anything. */
  20.454 +    /*  ...but default to first name in the list... */
  20.455 +    if (devname == NULL) {
  20.456 +        if ( ((iscapture) && (inputDeviceCount == 0)) ||
  20.457 +             ((!iscapture) && (outputDeviceCount == 0)) ) {
  20.458 +            SDL_SetError("No such audio device");
  20.459 +            return 0;
  20.460 +        }
  20.461 +        devname = ((iscapture) ? inputDevices[0] : outputDevices[0]);
  20.462 +    }
  20.463 +
  20.464 +    /* Initialize all variables that we clean on shutdown */
  20.465 +    this->hidden = (struct SDL_PrivateAudioData *)
  20.466 +                        SDL_malloc((sizeof *this->hidden));
  20.467 +    if (this->hidden == NULL) {
  20.468 +        SDL_OutOfMemory();
  20.469 +        return 0;
  20.470 +    }
  20.471 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  20.472 +
  20.473 +    /* Open the audio device */
  20.474 +    this->hidden->audio_fd = open(devname, flags, 0);
  20.475 +    if (this->hidden->audio_fd < 0) {
  20.476 +        SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
  20.477 +        return 0;
  20.478 +    }
  20.479 +
  20.480      AUDIO_INITINFO(&info);
  20.481  
  20.482      /* Calculate the final parameters for this audio specification */
  20.483 -    SDL_CalculateAudioSpec(spec);
  20.484 -
  20.485 -#ifdef USE_TIMER_SYNC
  20.486 -    frame_ticks = 0.0;
  20.487 -#endif
  20.488 -
  20.489 -    /* Open the audio device */
  20.490 -    audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
  20.491 -    if (audio_fd < 0) {
  20.492 -        SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
  20.493 -        return (-1);
  20.494 -    }
  20.495 +    SDL_CalculateAudioSpec(&this->spec);
  20.496  
  20.497      /* Set to play mode */
  20.498      info.mode = AUMODE_PLAY;
  20.499 -    if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) {
  20.500 +    if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
  20.501 +        BSDAUDIO_CloseDevice(this);
  20.502          SDL_SetError("Couldn't put device into play mode");
  20.503 -        return (-1);
  20.504 +        return 0;
  20.505      }
  20.506  
  20.507 -    mixbuf = NULL;
  20.508      AUDIO_INITINFO(&info);
  20.509 -    for (format = SDL_FirstAudioFormat(spec->format);
  20.510 +    for (format = SDL_FirstAudioFormat(this->spec.format);
  20.511           format; format = SDL_NextAudioFormat()) {
  20.512          switch (format) {
  20.513          case AUDIO_U8:
  20.514 @@ -389,46 +385,69 @@
  20.515          default:
  20.516              continue;
  20.517          }
  20.518 -        if (ioctl(audio_fd, AUDIO_SETINFO, &info) == 0)
  20.519 +
  20.520 +        if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) {
  20.521              break;
  20.522 +        }
  20.523      }
  20.524  
  20.525      if (!format) {
  20.526 -        SDL_SetError("No supported encoding for 0x%x", spec->format);
  20.527 -        return (-1);
  20.528 +        BSDAUDIO_CloseDevice(this);
  20.529 +        SDL_SetError("No supported encoding for 0x%x", this->spec.format);
  20.530 +        return 0;
  20.531      }
  20.532  
  20.533 -    spec->format = format;
  20.534 +    this->spec.format = format;
  20.535  
  20.536      AUDIO_INITINFO(&info);
  20.537 -    info.play.channels = spec->channels;
  20.538 -    if (ioctl(audio_fd, AUDIO_SETINFO, &info) == -1)
  20.539 -        spec->channels = 1;
  20.540 +    info.play.channels = this->spec.channels;
  20.541 +    if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) {
  20.542 +        this->spec.channels = 1;
  20.543 +    }
  20.544      AUDIO_INITINFO(&info);
  20.545 -    info.play.sample_rate = spec->freq;
  20.546 -    info.blocksize = spec->size;
  20.547 +    info.play.sample_rate = this->spec.freq;
  20.548 +    info.blocksize = this->spec.size;
  20.549      info.hiwat = 5;
  20.550      info.lowat = 3;
  20.551 -    (void) ioctl(audio_fd, AUDIO_SETINFO, &info);
  20.552 -    (void) ioctl(audio_fd, AUDIO_GETINFO, &info);
  20.553 -    spec->freq = info.play.sample_rate;
  20.554 +    (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
  20.555 +    (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
  20.556 +    this->spec.freq = info.play.sample_rate;
  20.557      /* Allocate mixing buffer */
  20.558 -    mixlen = spec->size;
  20.559 -    mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen);
  20.560 -    if (mixbuf == NULL) {
  20.561 -        return (-1);
  20.562 +    this->hidden->mixlen = this->spec.size;
  20.563 +    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
  20.564 +    if (this->hidden->mixbuf == NULL) {
  20.565 +        BSDAUDIO_CloseDevice(this);
  20.566 +        SDL_OutOfMemory();
  20.567 +        return 0;
  20.568      }
  20.569 -    SDL_memset(mixbuf, spec->silence, spec->size);
  20.570 +    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
  20.571  
  20.572 -    /* Get the parent process id (we're the parent of the audio thread) */
  20.573 -    parent = getpid();
  20.574 -
  20.575 -#ifdef DEBUG_AUDIO
  20.576 -    OBSD_Status(this);
  20.577 -#endif
  20.578 +    BSDAUDIO_Status(this);
  20.579  
  20.580      /* We're ready to rock and roll. :-) */
  20.581      return (0);
  20.582  }
  20.583  
  20.584 +static int
  20.585 +BSDAUDIO_Init(SDL_AudioDriverImpl *impl)
  20.586 +{
  20.587 +    /* Set the function pointers */
  20.588 +    impl->DetectDevices = BSDAUDIO_DetectDevices;
  20.589 +    impl->GetDeviceName = BSDAUDIO_GetDeviceName;
  20.590 +    impl->OpenDevice = BSDAUDIO_OpenDevice;
  20.591 +    impl->PlayDevice = BSDAUDIO_PlayDevice;
  20.592 +    impl->WaitDevice = BSDAUDIO_WaitDevice;
  20.593 +    impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
  20.594 +    impl->CloseDevice = BSDAUDIO_CloseDevice;
  20.595 +    impl->Deinitialize = BSDAUDIO_Deinitialize;
  20.596 +
  20.597 +    build_device_lists();
  20.598 +    return 1;
  20.599 +}
  20.600 +
  20.601 +
  20.602 +AudioBootStrap BSD_AUDIO_bootstrap = {
  20.603 +    BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC, BSDAUDIO_Init, 0
  20.604 +};
  20.605 +
  20.606  /* vi: set ts=4 sw=4 expandtab: */
    21.1 --- a/src/audio/bsd/SDL_bsdaudio.h	Sun Oct 01 16:10:41 2006 +0000
    21.2 +++ b/src/audio/bsd/SDL_bsdaudio.h	Tue Oct 17 09:15:21 2006 +0000
    21.3 @@ -21,8 +21,8 @@
    21.4  */
    21.5  #include "SDL_config.h"
    21.6  
    21.7 -#ifndef _SDL_openbsdaudio_h
    21.8 -#define _SDL_openbsdaudio_h
    21.9 +#ifndef _SDL_bsdaudio_h
   21.10 +#define _SDL_bsdaudio_h
   21.11  
   21.12  #include "../SDL_sysaudio.h"
   21.13  
   21.14 @@ -47,13 +47,6 @@
   21.15  
   21.16  #define FUDGE_TICKS	10      /* The scheduler overhead ticks per frame */
   21.17  
   21.18 -/* Old variable names */
   21.19 -#define audio_fd		(this->hidden->audio_fd)
   21.20 -#define parent			(this->hidden->parent)
   21.21 -#define mixbuf			(this->hidden->mixbuf)
   21.22 -#define mixlen			(this->hidden->mixlen)
   21.23 -#define frame_ticks		(this->hidden->frame_ticks)
   21.24 -#define next_frame		(this->hidden->next_frame)
   21.25 +#endif /* _SDL_bsdaudio_h */
   21.26  
   21.27 -#endif /* _SDL_openbsdaudio_h */
   21.28  /* vi: set ts=4 sw=4 expandtab: */
    22.1 --- a/src/audio/dart/SDL_dart.c	Sun Oct 01 16:10:41 2006 +0000
    22.2 +++ b/src/audio/dart/SDL_dart.c	Tue Oct 17 09:15:21 2006 +0000
    22.3 @@ -42,10 +42,10 @@
    22.4  //---------------------------------------------------------------------
    22.5  // DARTEventFunc
    22.6  //
    22.7 -// This function is called by DART, when an event occures, like end of 
    22.8 +// This function is called by DART, when an event occurs, like end of
    22.9  // playback of a buffer, etc...
   22.10  //---------------------------------------------------------------------
   22.11 -LONG APIENTRY
   22.12 +static LONG APIENTRY
   22.13  DARTEventFunc(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags)
   22.14  {
   22.15      if (ulFlags && MIX_WRITE_COMPLETE) {        // Playback of buffer completed!
   22.16 @@ -71,13 +71,12 @@
   22.17  }
   22.18  
   22.19  
   22.20 -int
   22.21 -DART_OpenAudio(_THIS, SDL_AudioSpec * spec)
   22.22 +static int
   22.23 +DART_OpenDevice(_THIS, const char *devname, int iscapture)
   22.24  {
   22.25 -    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
   22.26 +    SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
   22.27      int valid_datatype = 0;
   22.28      MCI_AMP_OPEN_PARMS AmpOpenParms;
   22.29 -    MCI_GENERIC_PARMS GenericParms;
   22.30      int iDeviceOrd = 0;         // Default device to be used
   22.31      int bOpenShared = 1;        // Try opening it shared
   22.32      int iBits = 16;             // Default is 16 bits signed
   22.33 @@ -89,6 +88,15 @@
   22.34      int iSilence;
   22.35      int rc;
   22.36  
   22.37 +    /* Initialize all variables that we clean on shutdown */
   22.38 +    _this->hidden = (struct SDL_PrivateAudioData *)
   22.39 +                        SDL_malloc((sizeof *_this->hidden));
   22.40 +    if (_this->hidden == NULL) {
   22.41 +        SDL_OutOfMemory();
   22.42 +        return 0;
   22.43 +    }
   22.44 +    SDL_memset(_this->hidden, 0, (sizeof *_this->hidden));
   22.45 +
   22.46      // First thing is to try to open a given DART device!
   22.47      SDL_memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
   22.48      // pszDeviceType should contain the device type in low word, and device ordinal in high word!
   22.49 @@ -100,30 +108,34 @@
   22.50          iOpenMode |= MCI_OPEN_SHAREABLE;
   22.51  
   22.52      rc = mciSendCommand(0, MCI_OPEN, iOpenMode, (PVOID) & AmpOpenParms, 0);
   22.53 -    if (rc != MCIERR_SUCCESS)   // No audio available??
   22.54 -        return (-1);
   22.55 +    if (rc != MCIERR_SUCCESS) {  // No audio available??
   22.56 +        DART_CloseDevice(_this);
   22.57 +        SDL_SetError("DART: Couldn't open audio device.");
   22.58 +        return 0;
   22.59 +    }
   22.60 +
   22.61      // Save the device ID we got from DART!
   22.62      // We will use this in the next calls!
   22.63 -    iDeviceOrd = AmpOpenParms.usDeviceID;
   22.64 +    _this->hidden->iCurrDeviceOrd = iDeviceOrd = AmpOpenParms.usDeviceID;
   22.65  
   22.66      // Determine the audio parameters from the AudioSpec
   22.67 -    if (spec->channels > 2)
   22.68 -        spec->channels = 2;     // !!! FIXME: more than stereo support in OS/2?
   22.69 +    if (_this->spec.channels > 4)
   22.70 +        _this->spec.channels = 4;
   22.71  
   22.72      while ((!valid_datatype) && (test_format)) {
   22.73 -        spec->format = test_format;
   22.74 +        _this->spec.format = test_format;
   22.75          valid_datatype = 1;
   22.76          switch (test_format) {
   22.77          case AUDIO_U8:
   22.78              // Unsigned 8 bit audio data
   22.79              iSilence = 0x80;
   22.80 -            iBits = 8;
   22.81 +            _this->hidden->iCurrBits = iBits = 8;
   22.82              break;
   22.83  
   22.84          case AUDIO_S16LSB:
   22.85              // Signed 16 bit audio data
   22.86              iSilence = 0x00;
   22.87 -            iBits = 16;
   22.88 +            _this->hidden->iCurrBits = iBits = 16;
   22.89              break;
   22.90  
   22.91              // !!! FIXME: int32?
   22.92 @@ -137,16 +149,16 @@
   22.93  
   22.94      if (!valid_datatype) {      // shouldn't happen, but just in case...
   22.95          // Close DART, and exit with error code!
   22.96 -        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
   22.97 +        DART_CloseDevice(_this);
   22.98          SDL_SetError("Unsupported audio format");
   22.99 -        return (-1);
  22.100 +        return 0;
  22.101      }
  22.102  
  22.103 -    iFreq = spec->freq;
  22.104 -    iChannels = spec->channels;
  22.105 +    _this->hidden->iCurrFreq = iFreq = _this->spec.freq;
  22.106 +    _this->hidden->iCurrChannels = iChannels = _this->spec.channels;
  22.107      /* Update the fragment size as size in bytes */
  22.108 -    SDL_CalculateAudioSpec(spec);
  22.109 -    iBufSize = spec->size;
  22.110 +    SDL_CalculateAudioSpec(&_this->spec);
  22.111 +    _this->hidden->iCurrBufSize = iBufSize = _this->spec.size;
  22.112  
  22.113      // Now query this device if it supports the given freq/bits/channels!
  22.114      SDL_memset(&(_this->hidden->MixSetupParms), 0,
  22.115 @@ -163,9 +175,9 @@
  22.116                          &(_this->hidden->MixSetupParms), 0);
  22.117      if (rc != MCIERR_SUCCESS) { // The device cannot handle this format!
  22.118          // Close DART, and exit with error code!
  22.119 -        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
  22.120 +        DART_CloseDevice(_this);
  22.121          SDL_SetError("Audio device doesn't support requested audio format");
  22.122 -        return (-1);
  22.123 +        return 0;
  22.124      }
  22.125      // The device can handle this format, so initialize!
  22.126      rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP,
  22.127 @@ -173,9 +185,9 @@
  22.128                          &(_this->hidden->MixSetupParms), 0);
  22.129      if (rc != MCIERR_SUCCESS) { // The device could not be opened!
  22.130          // Close DART, and exit with error code!
  22.131 -        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
  22.132 +        DART_CloseDevice(_this);
  22.133          SDL_SetError("Audio device could not be set up");
  22.134 -        return (-1);
  22.135 +        return 0;
  22.136      }
  22.137      // Ok, the device is initialized.
  22.138      // Now we should allocate buffers. For this, we need a place where
  22.139 @@ -184,9 +196,9 @@
  22.140          (MCI_MIX_BUFFER *) SDL_malloc(sizeof(MCI_MIX_BUFFER) * iNumBufs);
  22.141      if (!(_this->hidden->pMixBuffers)) {        // Not enough memory!
  22.142          // Close DART, and exit with error code!
  22.143 -        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
  22.144 -        SDL_SetError("Not enough memory for audio buffer descriptors");
  22.145 -        return (-1);
  22.146 +        DART_CloseDevice(_this);
  22.147 +        SDL_OutOfMemory();
  22.148 +        return 0;
  22.149      }
  22.150      // Now that we have the place for buffer list, we can ask DART for the
  22.151      // buffers!
  22.152 @@ -201,12 +213,12 @@
  22.153          || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers)
  22.154          || (_this->hidden->BufferParms.ulBufferSize == 0)) {    // Could not allocate memory!
  22.155          // Close DART, and exit with error code!
  22.156 -        SDL_free(_this->hidden->pMixBuffers);
  22.157 -        _this->hidden->pMixBuffers = NULL;
  22.158 -        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
  22.159 +        DART_CloseDevice(_this);
  22.160          SDL_SetError("DART could not allocate buffers");
  22.161 -        return (-1);
  22.162 +        return 0;
  22.163      }
  22.164 +    _this->hidden->iCurrNumBufs = iNumBufs;
  22.165 +
  22.166      // Ok, we have all the buffers allocated, let's mark them!
  22.167      {
  22.168          int i;
  22.169 @@ -216,24 +228,9 @@
  22.170              // Check if this buffer was really allocated by DART
  22.171              if ((!(_this->hidden->pMixBuffers[i].pBuffer))
  22.172                  || (!pBufferDesc)) {    // Wrong buffer!
  22.173 -                // Close DART, and exit with error code!
  22.174 -                // Free buffer descriptions
  22.175 -                {
  22.176 -                    int j;
  22.177 -                    for (j = 0; j < i; j++)
  22.178 -                        SDL_free((void *) (_this->hidden->pMixBuffers[j].
  22.179 -                                           ulUserParm));
  22.180 -                }
  22.181 -                // and cleanup
  22.182 -                mciSendCommand(iDeviceOrd, MCI_BUFFER,
  22.183 -                               MCI_WAIT | MCI_DEALLOCATE_MEMORY,
  22.184 -                               &(_this->hidden->BufferParms), 0);
  22.185 -                SDL_free(_this->hidden->pMixBuffers);
  22.186 -                _this->hidden->pMixBuffers = NULL;
  22.187 -                mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT,
  22.188 -                               &GenericParms, 0);
  22.189 +                DART_CloseDevice(_this);
  22.190                  SDL_SetError("Error at internal buffer check");
  22.191 -                return (-1);
  22.192 +                return 0;
  22.193              }
  22.194              pBufferDesc->iBufferUsage = BUFFER_EMPTY;
  22.195              pBufferDesc->pSDLAudioDevice = _this;
  22.196 @@ -254,43 +251,41 @@
  22.197      if (DosCreateEventSem
  22.198          (NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE) != NO_ERROR)
  22.199      {
  22.200 -        // Could not create event semaphore!
  22.201 -        {
  22.202 -            int i;
  22.203 -            for (i = 0; i < iNumBufs; i++)
  22.204 -                SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm));
  22.205 -        }
  22.206 -        mciSendCommand(iDeviceOrd, MCI_BUFFER,
  22.207 -                       MCI_WAIT | MCI_DEALLOCATE_MEMORY,
  22.208 -                       &(_this->hidden->BufferParms), 0);
  22.209 -        SDL_free(_this->hidden->pMixBuffers);
  22.210 -        _this->hidden->pMixBuffers = NULL;
  22.211 -        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
  22.212 +        DART_CloseDevice(_this);
  22.213          SDL_SetError("Could not create event semaphore");
  22.214 -        return (-1);
  22.215 +        return 0;
  22.216      }
  22.217 -    // Store the new settings in global variables
  22.218 -    _this->hidden->iCurrDeviceOrd = iDeviceOrd;
  22.219 -    _this->hidden->iCurrFreq = iFreq;
  22.220 -    _this->hidden->iCurrBits = iBits;
  22.221 -    _this->hidden->iCurrChannels = iChannels;
  22.222 -    _this->hidden->iCurrNumBufs = iNumBufs;
  22.223 -    _this->hidden->iCurrBufSize = iBufSize;
  22.224  
  22.225 -    return (0);
  22.226 +    return 1;
  22.227  }
  22.228  
  22.229 -
  22.230 -
  22.231 -void
  22.232 +static void
  22.233  DART_ThreadInit(_THIS)
  22.234  {
  22.235 -    return;
  22.236 +    /* Increase the priority of this thread to make sure that
  22.237 +       the audio will be continuous all the time! */
  22.238 +#ifdef USE_DOSSETPRIORITY
  22.239 +    if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) {
  22.240 +#ifdef DEBUG_BUILD
  22.241 +        printf
  22.242 +            ("[DART_ThreadInit] : Setting priority to TimeCritical+0! (TID%d)\n",
  22.243 +             SDL_ThreadID());
  22.244 +#endif
  22.245 +        DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
  22.246 +    } else {
  22.247 +#ifdef DEBUG_BUILD
  22.248 +        printf
  22.249 +            ("[DART_ThreadInit] : Setting priority to ForegroundServer+0! (TID%d)\n",
  22.250 +             SDL_ThreadID());
  22.251 +#endif
  22.252 +        DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
  22.253 +    }
  22.254 +#endif
  22.255  }
  22.256  
  22.257  /* This function waits until it is possible to write a full sound buffer */
  22.258 -void
  22.259 -DART_WaitAudio(_THIS)
  22.260 +static void
  22.261 +DART_WaitDevice(_THIS)
  22.262  {
  22.263      int i;
  22.264      pMixBufferDesc pBufDesc;
  22.265 @@ -308,8 +303,8 @@
  22.266      return;
  22.267  }
  22.268  
  22.269 -void
  22.270 -DART_PlayAudio(_THIS)
  22.271 +static void
  22.272 +DART_PlayDevice(_THIS)
  22.273  {
  22.274      int iFreeBuf = _this->hidden->iNextFreeBuffer;
  22.275      pMixBufferDesc pBufDesc;
  22.276 @@ -328,8 +323,8 @@
  22.277      _this->hidden->iNextFreeBuffer = iFreeBuf;
  22.278  }
  22.279  
  22.280 -Uint8 *
  22.281 -DART_GetAudioBuf(_THIS)
  22.282 +static Uint8 *
  22.283 +DART_GetDeviceBuf(_THIS)
  22.284  {
  22.285      int iFreeBuf;
  22.286      Uint8 *pResult;
  22.287 @@ -348,125 +343,110 @@
  22.288                      return pResult;
  22.289                  }
  22.290              } else
  22.291 -                printf("[DART_GetAudioBuf] : ERROR! pBufDesc = %p\n",
  22.292 +                printf("[DART_GetDeviceBuf] : ERROR! pBufDesc = %p\n",
  22.293                         pBufDesc);
  22.294          } else
  22.295 -            printf("[DART_GetAudioBuf] : ERROR! _this->hidden = %p\n",
  22.296 +            printf("[DART_GetDeviceBuf] : ERROR! _this->hidden = %p\n",
  22.297                     _this->hidden);
  22.298      } else
  22.299 -        printf("[DART_GetAudioBuf] : ERROR! _this = %p\n", _this);
  22.300 +        printf("[DART_GetDeviceBuf] : ERROR! _this = %p\n", _this);
  22.301      return NULL;
  22.302  }
  22.303  
  22.304 -void
  22.305 +static void
  22.306  DART_WaitDone(_THIS)
  22.307  {
  22.308      pMixBufferDesc pBufDesc;
  22.309 -    ULONG ulPostCount;
  22.310 -    APIRET rc;
  22.311 +    ULONG ulPostCount = 0;
  22.312 +    APIRET rc = NO_ERROR;
  22.313  
  22.314 -    pBufDesc =
  22.315 -        (pMixBufferDesc) _this->hidden->pMixBuffers[_this->hidden->
  22.316 -                                                    iLastPlayedBuf].
  22.317 -        ulUserParm;
  22.318 -    rc = NO_ERROR;
  22.319 +    pBufDesc = (pMixBufferDesc)
  22.320 +          _this->hidden->pMixBuffers[_this->hidden->iLastPlayedBuf].ulUserParm;
  22.321 +
  22.322      while ((pBufDesc->iBufferUsage != BUFFER_EMPTY) && (rc == NO_ERROR)) {
  22.323          DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount);
  22.324          rc = DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000);        // 1 sec timeout! Important!
  22.325      }
  22.326  }
  22.327  
  22.328 -void
  22.329 -DART_CloseAudio(_THIS)
  22.330 +static void
  22.331 +DART_CloseDevice(_THIS)
  22.332  {
  22.333      MCI_GENERIC_PARMS GenericParms;
  22.334      int rc;
  22.335 +    int i;
  22.336  
  22.337 -    // Stop DART playback
  22.338 -    rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP, MCI_WAIT,
  22.339 -                        &GenericParms, 0);
  22.340 -    if (rc != MCIERR_SUCCESS) {
  22.341 +    if (_this->hidden != NULL) {
  22.342 +        // Stop DART playback
  22.343 +        if (_this->hidden->iCurrDeviceOrd) {
  22.344 +            rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP,
  22.345 +                                MCI_WAIT, &GenericParms, 0);
  22.346  #ifdef SFX_DEBUG_BUILD
  22.347 -        printf("Could not stop DART playback!\n");
  22.348 -        fflush(stdout);
  22.349 +            if (rc != MCIERR_SUCCESS) {
  22.350 +                printf("Could not stop DART playback!\n");
  22.351 +                fflush(stdout);
  22.352 +            }
  22.353  #endif
  22.354 +        }
  22.355 +
  22.356 +        // Close event semaphore
  22.357 +        if (_this->hidden->hevAudioBufferPlayed) {
  22.358 +            DosCloseEventSem(_this->hidden->hevAudioBufferPlayed);
  22.359 +            _this->hidden->hevAudioBufferPlayed = 0;
  22.360 +        }
  22.361 +
  22.362 +        // Free memory of buffer descriptions
  22.363 +        for (i = 0; i < _this->hidden->iCurrNumBufs; i++) {
  22.364 +            SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm));
  22.365 +            _this->hidden->pMixBuffers[i].ulUserParm = 0;
  22.366 +        }
  22.367 +        _this->hidden->iCurrNumBufs = 0;
  22.368 +
  22.369 +        // Deallocate buffers
  22.370 +        if (_this->hidden->iCurrDeviceOrd) {
  22.371 +            rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER,
  22.372 +                                MCI_WAIT | MCI_DEALLOCATE_MEMORY,
  22.373 +                                &(_this->hidden->BufferParms), 0);
  22.374 +        }
  22.375 +
  22.376 +        // Free bufferlist
  22.377 +        if (_this->hidden->pMixBuffers != NULL) {
  22.378 +            SDL_free(_this->hidden->pMixBuffers);
  22.379 +            _this->hidden->pMixBuffers = NULL;
  22.380 +        }
  22.381 +
  22.382 +        // Close dart
  22.383 +        if (_this->hidden->iCurrDeviceOrd) {
  22.384 +            rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE,
  22.385 +                                MCI_WAIT, &(GenericParms), 0);
  22.386 +        }
  22.387 +        _this->hidden->iCurrDeviceOrd = 0;
  22.388 +
  22.389 +        SDL_free(_this->hidden);
  22.390 +        _this->hidden = NULL;
  22.391      }
  22.392 -    // Close event semaphore
  22.393 -    DosCloseEventSem(_this->hidden->hevAudioBufferPlayed);
  22.394 -
  22.395 -    // Free memory of buffer descriptions
  22.396 -    {
  22.397 -        int i;
  22.398 -        for (i = 0; i < _this->hidden->iCurrNumBufs; i++)
  22.399 -            SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm));
  22.400 -    }
  22.401 -
  22.402 -    // Deallocate buffers
  22.403 -    rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER,
  22.404 -                        MCI_WAIT | MCI_DEALLOCATE_MEMORY,
  22.405 -                        &(_this->hidden->BufferParms), 0);
  22.406 -
  22.407 -    // Free bufferlist
  22.408 -    SDL_free(_this->hidden->pMixBuffers);
  22.409 -    _this->hidden->pMixBuffers = NULL;
  22.410 -
  22.411 -    // Close dart
  22.412 -    rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE, MCI_WAIT,
  22.413 -                        &(GenericParms), 0);
  22.414  }
  22.415  
  22.416 -/* Audio driver bootstrap functions */
  22.417  
  22.418 -int
  22.419 -Audio_Available(void)
  22.420 +static int
  22.421 +DART_Init(SDL_AudioDriverImpl *impl)
  22.422  {
  22.423 -    return (1);
  22.424 +    /* Set the function pointers */
  22.425 +    impl->OpenDevice = DART_OpenDevice;
  22.426 +    impl->ThreadInit = DART_ThreadInit;
  22.427 +    impl->WaitDevice = DART_WaitDevice;
  22.428 +    impl->GetDeviceBuf = DART_GetDeviceBuf;
  22.429 +    impl->PlayDevice = DART_PlayDevice;
  22.430 +    impl->WaitDone = DART_WaitDone;
  22.431 +    impl->CloseDevice = DART_CloseDevice;
  22.432 +    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: is this right? */
  22.433 +
  22.434 +    return 1;
  22.435  }
  22.436  
  22.437 -void
  22.438 -Audio_DeleteDevice(SDL_AudioDevice * device)
  22.439 -{
  22.440 -    SDL_free(device->hidden);
  22.441 -    SDL_free(device);
  22.442 -}
  22.443 -
  22.444 -SDL_AudioDevice *
  22.445 -Audio_CreateDevice(int devindex)
  22.446 -{
  22.447 -    SDL_AudioDevice *this;
  22.448 -
  22.449 -    /* Initialize all variables that we clean on shutdown */
  22.450 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
  22.451 -    if (this) {
  22.452 -        SDL_memset(this, 0, (sizeof *this));
  22.453 -        this->hidden = (struct SDL_PrivateAudioData *)
  22.454 -            SDL_malloc((sizeof *this->hidden));
  22.455 -    }
  22.456 -    if ((this == NULL) || (this->hidden == NULL)) {
  22.457 -        SDL_OutOfMemory();
  22.458 -        if (this)
  22.459 -            SDL_free(this);
  22.460 -        return (0);
  22.461 -    }
  22.462 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  22.463 -
  22.464 -    /* Set the function pointers */
  22.465 -    this->OpenAudio = DART_OpenAudio;
  22.466 -    this->ThreadInit = DART_ThreadInit;
  22.467 -    this->WaitAudio = DART_WaitAudio;
  22.468 -    this->PlayAudio = DART_PlayAudio;
  22.469 -    this->GetAudioBuf = DART_GetAudioBuf;
  22.470 -    this->WaitDone = DART_WaitDone;
  22.471 -    this->CloseAudio = DART_CloseAudio;
  22.472 -
  22.473 -    this->free = Audio_DeleteDevice;
  22.474 -
  22.475 -    return this;
  22.476 -}
  22.477  
  22.478  AudioBootStrap DART_bootstrap = {
  22.479 -    "dart", "OS/2 Direct Audio RouTines (DART)",
  22.480 -    Audio_Available, Audio_CreateDevice
  22.481 +    "dart", "OS/2 Direct Audio RouTines (DART)", DART_Init, 0
  22.482  };
  22.483  
  22.484  /* vi: set ts=4 sw=4 expandtab: */
    23.1 --- a/src/audio/dart/SDL_dart.h	Sun Oct 01 16:10:41 2006 +0000
    23.2 +++ b/src/audio/dart/SDL_dart.h	Tue Oct 17 09:15:21 2006 +0000
    23.3 @@ -21,14 +21,15 @@
    23.4  */
    23.5  #include "SDL_config.h"
    23.6  
    23.7 -#ifndef _SDL_lowaudio_h
    23.8 -#define _SDL_lowaudio_h
    23.9 +#ifndef _SDL_dart_h
   23.10 +#define _SDL_dart_h
   23.11  
   23.12  #define INCL_TYPES
   23.13  #define INCL_DOSSEMAPHORES
   23.14  #define INCL_DOSRESOURCES
   23.15  #define INCL_DOSMISC
   23.16  #define INCL_DOSERRORS
   23.17 +#define INCL_DOSPROCESS
   23.18  
   23.19  #define INCL_OS2MM
   23.20  #define INCL_MMIOOS2
   23.21 @@ -60,5 +61,6 @@
   23.22      HEV hevAudioBufferPlayed;   // Event semaphore to indicate that an audio buffer has been played by DART
   23.23  };
   23.24  
   23.25 -#endif /* _SDL_lowaudio_h */
   23.26 +#endif /* _SDL_dart_h */
   23.27 +
   23.28  /* vi: set ts=4 sw=4 expandtab: */
    24.1 --- a/src/audio/dc/SDL_dcaudio.c	Sun Oct 01 16:10:41 2006 +0000
    24.2 +++ b/src/audio/dc/SDL_dcaudio.c	Tue Oct 17 09:15:21 2006 +0000
    24.3 @@ -28,85 +28,11 @@
    24.4  #include "SDL_audio.h"
    24.5  #include "../SDL_audiomem.h"
    24.6  #include "../SDL_audio_c.h"
    24.7 -#include "../SDL_audiodev_c.h"
    24.8  #include "SDL_dcaudio.h"
    24.9  
   24.10  #include "aica.h"
   24.11  #include <dc/spu.h>
   24.12  
   24.13 -/* Audio driver functions */
   24.14 -static int DCAUD_OpenAudio(_THIS, SDL_AudioSpec * spec);
   24.15 -static void DCAUD_WaitAudio(_THIS);
   24.16 -static void DCAUD_PlayAudio(_THIS);
   24.17 -static Uint8 *DCAUD_GetAudioBuf(_THIS);
   24.18 -static void DCAUD_CloseAudio(_THIS);
   24.19 -
   24.20 -/* Audio driver bootstrap functions */
   24.21 -static int
   24.22 -DCAUD_Available(void)
   24.23 -{
   24.24 -    return 1;
   24.25 -}
   24.26 -
   24.27 -static void
   24.28 -DCAUD_DeleteDevice(SDL_AudioDevice * device)
   24.29 -{
   24.30 -    SDL_free(device->hidden);
   24.31 -    SDL_free(device);
   24.32 -}
   24.33 -
   24.34 -static SDL_AudioDevice *
   24.35 -DCAUD_CreateDevice(int devindex)
   24.36 -{
   24.37 -    SDL_AudioDevice *this;
   24.38 -
   24.39 -    /* Initialize all variables that we clean on shutdown */
   24.40 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
   24.41 -    if (this) {
   24.42 -        SDL_memset(this, 0, (sizeof *this));
   24.43 -        this->hidden = (struct SDL_PrivateAudioData *)
   24.44 -            SDL_malloc((sizeof *this->hidden));
   24.45 -    }
   24.46 -    if ((this == NULL) || (this->hidden == NULL)) {
   24.47 -        SDL_OutOfMemory();
   24.48 -        if (this) {
   24.49 -            SDL_free(this);
   24.50 -        }
   24.51 -        return (0);
   24.52 -    }
   24.53 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   24.54 -
   24.55 -    /* Set the function pointers */
   24.56 -    this->OpenAudio = DCAUD_OpenAudio;
   24.57 -    this->WaitAudio = DCAUD_WaitAudio;
   24.58 -    this->PlayAudio = DCAUD_PlayAudio;
   24.59 -    this->GetAudioBuf = DCAUD_GetAudioBuf;
   24.60 -    this->CloseAudio = DCAUD_CloseAudio;
   24.61 -
   24.62 -    this->free = DCAUD_DeleteDevice;
   24.63 -
   24.64 -    spu_init();
   24.65 -
   24.66 -    return this;
   24.67 -}
   24.68 -
   24.69 -AudioBootStrap DCAUD_bootstrap = {
   24.70 -    "dcaudio", "Dreamcast AICA audio",
   24.71 -    DCAUD_Available, DCAUD_CreateDevice
   24.72 -};
   24.73 -
   24.74 -/* This function waits until it is possible to write a full sound buffer */
   24.75 -static void
   24.76 -DCAUD_WaitAudio(_THIS)
   24.77 -{
   24.78 -    if (this->hidden->playing) {
   24.79 -        /* wait */
   24.80 -        while (aica_get_pos(0) / this->spec.samples == this->hidden->nextbuf) {
   24.81 -            thd_pass();
   24.82 -        }
   24.83 -    }
   24.84 -}
   24.85 -
   24.86  #define	SPU_RAM_BASE	0xa0800000
   24.87  
   24.88  static void
   24.89 @@ -152,7 +78,7 @@
   24.90  }
   24.91  
   24.92  static void
   24.93 -DCAUD_PlayAudio(_THIS)
   24.94 +DCAUD_PlayDevice(_THIS)
   24.95  {
   24.96      SDL_AudioSpec *spec = &this->spec;
   24.97      unsigned int offset;
   24.98 @@ -200,28 +126,59 @@
   24.99  }
  24.100  
  24.101  static Uint8 *
  24.102 -DCAUD_GetAudioBuf(_THIS)
  24.103 +DCAUD_GetDeviceBuf(_THIS)
  24.104  {
  24.105      return (this->hidden->mixbuf);
  24.106  }
  24.107  
  24.108 +/* This function waits until it is possible to write a full sound buffer */
  24.109  static void
  24.110 -DCAUD_CloseAudio(_THIS)
  24.111 +DCAUD_WaitDevice(_THIS)
  24.112  {
  24.113 -    aica_stop(0);
  24.114 -    if (this->spec.channels == 2)
  24.115 -        aica_stop(1);
  24.116 -    if (this->hidden->mixbuf != NULL) {
  24.117 -        SDL_FreeAudioMem(this->hidden->mixbuf);
  24.118 -        this->hidden->mixbuf = NULL;
  24.119 +    if (this->hidden->playing) {
  24.120 +        /* wait */
  24.121 +        while (aica_get_pos(0) / this->spec.samples == this->hidden->nextbuf) {
  24.122 +            thd_pass();
  24.123 +        }
  24.124 +    }
  24.125 +}
  24.126 +
  24.127 +static void
  24.128 +DCAUD_CloseDevice(_THIS)
  24.129 +{
  24.130 +    if (this->hidden != NULL) {
  24.131 +        aica_stop(0);
  24.132 +        if (this->spec.channels == 2) {
  24.133 +            aica_stop(1);
  24.134 +        }
  24.135 +        if (this->hidden->mixbuf != NULL) {
  24.136 +            SDL_FreeAudioMem(this->hidden->mixbuf);
  24.137 +            this->hidden->mixbuf = NULL;
  24.138 +        }
  24.139 +        SDL_free(this->hidden);
  24.140 +        this->hidden = NULL;
  24.141 +
  24.142 +        /* !!! FIXME: is there a reverse of spu_init()? */
  24.143      }
  24.144  }
  24.145  
  24.146  static int
  24.147 -DCAUD_OpenAudio(_THIS, SDL_AudioSpec * spec)
  24.148 +DCAUD_OpenDevice(_THIS, SDL_AudioSpec * spec)
  24.149  {
  24.150      SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
  24.151      int valid_datatype = 0;
  24.152 +
  24.153 +    /* Initialize all variables that we clean on shutdown */
  24.154 +    this->hidden = (struct SDL_PrivateAudioData *)
  24.155 +                        SDL_malloc((sizeof *this->hidden));
  24.156 +    if (this->hidden == NULL) {
  24.157 +        SDL_OutOfMemory();
  24.158 +        return 0;
  24.159 +    }
  24.160 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  24.161 +
  24.162 +    spu_init();
  24.163 +
  24.164      while ((!valid_datatype) && (test_format)) {
  24.165          spec->format = test_format;
  24.166          switch (test_format) {
  24.167 @@ -238,8 +195,9 @@
  24.168      }
  24.169  
  24.170      if (!valid_datatype) {      /* shouldn't happen, but just in case... */
  24.171 +        DCAUD_CloseDevice(this);
  24.172          SDL_SetError("Unsupported audio format");
  24.173 -        return (-1);
  24.174 +        return 0;
  24.175      }
  24.176  
  24.177      if (spec->channels > 2)
  24.178 @@ -252,7 +210,9 @@
  24.179      this->hidden->mixlen = spec->size;
  24.180      this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
  24.181      if (this->hidden->mixbuf == NULL) {
  24.182 -        return (-1);
  24.183 +        DCAUD_CloseDevice(this);
  24.184 +        SDL_OutOfMemory();
  24.185 +        return 0;
  24.186      }
  24.187      SDL_memset(this->hidden->mixbuf, spec->silence, spec->size);
  24.188      this->hidden->leftpos = 0x11000;
  24.189 @@ -261,7 +221,25 @@
  24.190      this->hidden->nextbuf = 0;
  24.191  
  24.192      /* We're ready to rock and roll. :-) */
  24.193 -    return (0);
  24.194 +    return 1;
  24.195  }
  24.196  
  24.197 +static int
  24.198 +DCAUD_Init(SDL_AudioDriverImpl *impl)
  24.199 +{
  24.200 +    /* Set the function pointers */
  24.201 +    impl->OpenDevice = DCAUD_OpenDevice;
  24.202 +    impl->PlayDevice = DCAUD_PlayDevice;
  24.203 +    impl->WaitDevice = DCAUD_WaitDevice;
  24.204 +    impl->GetDeviceBuf = DCAUD_GetDeviceBuf;
  24.205 +    impl->CloseDevice = DCAUD_CloseDevice;
  24.206 +    impl->OnlyHasDefaultOutputDevice = 1;
  24.207 +
  24.208 +    return 1;
  24.209 +}
  24.210 +
  24.211 +AudioBootStrap DCAUD_bootstrap = {
  24.212 +    "dcaudio", "Dreamcast AICA audio", DCAUD_Init, 0
  24.213 +};
  24.214 +
  24.215  /* vi: set ts=4 sw=4 expandtab: */
    25.1 --- a/src/audio/dc/SDL_dcaudio.h	Sun Oct 01 16:10:41 2006 +0000
    25.2 +++ b/src/audio/dc/SDL_dcaudio.h	Tue Oct 17 09:15:21 2006 +0000
    25.3 @@ -26,7 +26,7 @@
    25.4  
    25.5  #include "../SDL_sysaudio.h"
    25.6  
    25.7 -/* Hidden "this" pointer for the video functions */
    25.8 +/* Hidden "this" pointer for the audio functions */
    25.9  #define _THIS	SDL_AudioDevice *this
   25.10  
   25.11  struct SDL_PrivateAudioData
    26.1 --- a/src/audio/disk/SDL_diskaudio.c	Sun Oct 01 16:10:41 2006 +0000
    26.2 +++ b/src/audio/disk/SDL_diskaudio.c	Tue Oct 17 09:15:21 2006 +0000
    26.3 @@ -34,7 +34,6 @@
    26.4  #include "SDL_audio.h"
    26.5  #include "../SDL_audiomem.h"
    26.6  #include "../SDL_audio_c.h"
    26.7 -#include "../SDL_audiodev_c.h"
    26.8  #include "SDL_diskaudio.h"
    26.9  
   26.10  /* The tag name used by DISK audio */
   26.11 @@ -46,90 +45,27 @@
   26.12  #define DISKENVR_WRITEDELAY      "SDL_DISKAUDIODELAY"
   26.13  #define DISKDEFAULT_WRITEDELAY   150
   26.14  
   26.15 -/* Audio driver functions */
   26.16 -static int DISKAUD_OpenAudio(_THIS, SDL_AudioSpec * spec);
   26.17 -static void DISKAUD_WaitAudio(_THIS);
   26.18 -static void DISKAUD_PlayAudio(_THIS);
   26.19 -static Uint8 *DISKAUD_GetAudioBuf(_THIS);
   26.20 -static void DISKAUD_CloseAudio(_THIS);
   26.21 -
   26.22  static const char *
   26.23 -DISKAUD_GetOutputFilename(void)
   26.24 +DISKAUD_GetOutputFilename(const char *devname)
   26.25  {
   26.26 -    const char *envr = SDL_getenv(DISKENVR_OUTFILE);
   26.27 -    return ((envr != NULL) ? envr : DISKDEFAULT_OUTFILE);
   26.28 +    if (devname == NULL) {
   26.29 +        devname = SDL_getenv(DISKENVR_OUTFILE);
   26.30 +        if (devname == NULL) {
   26.31 +            devname = DISKDEFAULT_OUTFILE;
   26.32 +        }
   26.33 +    }
   26.34 +    return devname;
   26.35  }
   26.36  
   26.37 -/* Audio driver bootstrap functions */
   26.38 -static int
   26.39 -DISKAUD_Available(void)
   26.40 -{
   26.41 -    const char *envr = SDL_getenv("SDL_AUDIODRIVER");
   26.42 -    if (envr && (SDL_strcmp(envr, DISKAUD_DRIVER_NAME) == 0)) {
   26.43 -        return (1);
   26.44 -    }
   26.45 -    return (0);
   26.46 -}
   26.47 -
   26.48 -static void
   26.49 -DISKAUD_DeleteDevice(SDL_AudioDevice * device)
   26.50 -{
   26.51 -    SDL_free(device->hidden);
   26.52 -    SDL_free(device);
   26.53 -}
   26.54 -
   26.55 -static SDL_AudioDevice *
   26.56 -DISKAUD_CreateDevice(int devindex)
   26.57 -{
   26.58 -    SDL_AudioDevice *this;
   26.59 -    const char *envr;
   26.60 -
   26.61 -    /* Initialize all variables that we clean on shutdown */
   26.62 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
   26.63 -    if (this) {
   26.64 -        SDL_memset(this, 0, (sizeof *this));
   26.65 -        this->hidden = (struct SDL_PrivateAudioData *)
   26.66 -            SDL_malloc((sizeof *this->hidden));
   26.67 -    }
   26.68 -    if ((this == NULL) || (this->hidden == NULL)) {
   26.69 -        SDL_OutOfMemory();
   26.70 -        if (this) {
   26.71 -            SDL_free(this);
   26.72 -        }
   26.73 -        return (0);
   26.74 -    }
   26.75 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   26.76 -
   26.77 -    envr = SDL_getenv(DISKENVR_WRITEDELAY);
   26.78 -    this->hidden->write_delay =
   26.79 -        (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
   26.80 -
   26.81 -    /* Set the function pointers */
   26.82 -    this->OpenAudio = DISKAUD_OpenAudio;
   26.83 -    this->WaitAudio = DISKAUD_WaitAudio;
   26.84 -    this->PlayAudio = DISKAUD_PlayAudio;
   26.85 -    this->GetAudioBuf = DISKAUD_GetAudioBuf;
   26.86 -    this->CloseAudio = DISKAUD_CloseAudio;
   26.87 -
   26.88 -    this->free = DISKAUD_DeleteDevice;
   26.89 -
   26.90 -    return this;
   26.91 -}
   26.92 -
   26.93 -AudioBootStrap DISKAUD_bootstrap = {
   26.94 -    DISKAUD_DRIVER_NAME, "direct-to-disk audio",
   26.95 -    DISKAUD_Available, DISKAUD_CreateDevice
   26.96 -};
   26.97 -
   26.98  /* This function waits until it is possible to write a full sound buffer */
   26.99  static void
  26.100 -DISKAUD_WaitAudio(_THIS)
  26.101 +DISKAUD_WaitDevice(_THIS)
  26.102  {
  26.103      SDL_Delay(this->hidden->write_delay);
  26.104  }
  26.105  
  26.106  static void
  26.107 -DISKAUD_PlayAudio(_THIS)
  26.108 +DISKAUD_PlayDevice(_THIS)
  26.109  {
  26.110      int written;
  26.111  
  26.112 @@ -147,49 +83,86 @@
  26.113  }
  26.114  
  26.115  static Uint8 *
  26.116 -DISKAUD_GetAudioBuf(_THIS)
  26.117 +DISKAUD_GetDeviceBuf(_THIS)
  26.118  {
  26.119      return (this->hidden->mixbuf);
  26.120  }
  26.121  
  26.122  static void
  26.123 -DISKAUD_CloseAudio(_THIS)
  26.124 +DISKAUD_CloseDevice(_THIS)
  26.125  {
  26.126 -    if (this->hidden->mixbuf != NULL) {
  26.127 -        SDL_FreeAudioMem(this->hidden->mixbuf);
  26.128 -        this->hidden->mixbuf = NULL;
  26.129 -    }
  26.130 -    if (this->hidden->output != NULL) {
  26.131 -        SDL_RWclose(this->hidden->output);
  26.132 -        this->hidden->output = NULL;
  26.133 +    if (this->hidden != NULL) {
  26.134 +        if (this->hidden->mixbuf != NULL) {
  26.135 +            SDL_FreeAudioMem(this->hidden->mixbuf);
  26.136 +            this->hidden->mixbuf = NULL;
  26.137 +        }
  26.138 +        if (this->hidden->output != NULL) {
  26.139 +            SDL_RWclose(this->hidden->output);
  26.140 +            this->hidden->output = NULL;
  26.141 +        }
  26.142 +        SDL_free(this->hidden);
  26.143 +        this->hidden = NULL;
  26.144      }
  26.145  }
  26.146  
  26.147  static int
  26.148 -DISKAUD_OpenAudio(_THIS, SDL_AudioSpec * spec)
  26.149 +DISKAUD_OpenDevice(_THIS, const char *devname, int iscapture)
  26.150  {
  26.151 -    const char *fname = DISKAUD_GetOutputFilename();
  26.152 +    const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
  26.153 +    const char *fname = DISKAUD_GetOutputFilename(devname);
  26.154 +
  26.155 +    this->hidden = (struct SDL_PrivateAudioData *)
  26.156 +            SDL_malloc(sizeof (*this->hidden));
  26.157 +    if (this->hidden == NULL) {
  26.158 +        SDL_OutOfMemory();
  26.159 +        return 0;
  26.160 +    }
  26.161 +    SDL_memset(this->hidden, 0, sizeof (*this->hidden));
  26.162  
  26.163      /* Open the audio device */
  26.164      this->hidden->output = SDL_RWFromFile(fname, "wb");
  26.165      if (this->hidden->output == NULL) {
  26.166 -        return (-1);
  26.167 +        DISKAUD_CloseDevice(this);
  26.168 +        return 0;
  26.169      }
  26.170 +
  26.171 +    /* Allocate mixing buffer */
  26.172 +    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
  26.173 +    if (this->hidden->mixbuf == NULL) {
  26.174 +        DISKAUD_CloseDevice(this);
  26.175 +        return 0;
  26.176 +    }
  26.177 +    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
  26.178 +
  26.179 +    this->hidden->mixlen = this->spec.size;
  26.180 +    this->hidden->write_delay =
  26.181 +        (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
  26.182 +
  26.183  #if HAVE_STDIO_H
  26.184 -    fprintf(stderr, "WARNING: You are using the SDL disk writer"
  26.185 -            " audio driver!\n Writing to file [%s].\n", fname);
  26.186 +    fprintf(stderr,
  26.187 +            "WARNING: You are using the SDL disk writer audio driver!\n"
  26.188 +            " Writing to file [%s].\n", fname);
  26.189  #endif
  26.190  
  26.191 -    /* Allocate mixing buffer */
  26.192 -    this->hidden->mixlen = spec->size;
  26.193 -    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
  26.194 -    if (this->hidden->mixbuf == NULL) {
  26.195 -        return (-1);
  26.196 -    }
  26.197 -    SDL_memset(this->hidden->mixbuf, spec->silence, spec->size);
  26.198 -
  26.199      /* We're ready to rock and roll. :-) */
  26.200 -    return (0);
  26.201 +    return 1;
  26.202  }
  26.203  
  26.204 +static int
  26.205 +DISKAUD_Init(SDL_AudioDriverImpl *impl)
  26.206 +{
  26.207 +    /* Set the function pointers */
  26.208 +    impl->OpenDevice = DISKAUD_OpenDevice;
  26.209 +    impl->WaitDevice = DISKAUD_WaitDevice;
  26.210 +    impl->PlayDevice = DISKAUD_PlayDevice;
  26.211 +    impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
  26.212 +    impl->CloseDevice = DISKAUD_CloseDevice;
  26.213 +
  26.214 +    return 1;
  26.215 +}
  26.216 +
  26.217 +AudioBootStrap DISKAUD_bootstrap = {
  26.218 +    DISKAUD_DRIVER_NAME, "direct-to-disk audio", DISKAUD_Init, 1
  26.219 +};
  26.220 +
  26.221  /* vi: set ts=4 sw=4 expandtab: */
    27.1 --- a/src/audio/disk/SDL_diskaudio.h	Sun Oct 01 16:10:41 2006 +0000
    27.2 +++ b/src/audio/disk/SDL_diskaudio.h	Tue Oct 17 09:15:21 2006 +0000
    27.3 @@ -27,7 +27,7 @@
    27.4  #include "SDL_rwops.h"
    27.5  #include "../SDL_sysaudio.h"
    27.6  
    27.7 -/* Hidden "this" pointer for the video functions */
    27.8 +/* Hidden "this" pointer for the audio functions */
    27.9  #define _THIS	SDL_AudioDevice *this
   27.10  
   27.11  struct SDL_PrivateAudioData
    28.1 --- a/src/audio/dma/SDL_dmaaudio.c	Sun Oct 01 16:10:41 2006 +0000
    28.2 +++ b/src/audio/dma/SDL_dmaaudio.c	Tue Oct 17 09:15:21 2006 +0000
    28.3 @@ -21,6 +21,8 @@
    28.4  */
    28.5  #include "SDL_config.h"
    28.6  
    28.7 +/* !!! FIXME: merge this driver with "dsp". */
    28.8 +
    28.9  /* Allow access to a raw mixing buffer */
   28.10  
   28.11  #include <stdio.h>
   28.12 @@ -57,89 +59,353 @@
   28.13  #define DMA_DRIVER_NAME         "dma"
   28.14  
   28.15  /* Open the audio device for playback, and don't block if busy */
   28.16 -#define OPEN_FLAGS	(O_RDWR|O_NONBLOCK)
   28.17 +#define OPEN_FLAGS_INPUT    (O_RDWR|O_NONBLOCK)
   28.18 +#define OPEN_FLAGS_OUTPUT   (O_RDWR|O_NONBLOCK)
   28.19  
   28.20 -/* Audio driver functions */
   28.21 -static int DMA_OpenAudio(_THIS, SDL_AudioSpec * spec);
   28.22 -static void DMA_WaitAudio(_THIS);
   28.23 -static void DMA_PlayAudio(_THIS);
   28.24 -static Uint8 *DMA_GetAudioBuf(_THIS);
   28.25 -static void DMA_CloseAudio(_THIS);
   28.26 -
   28.27 -/* Audio driver bootstrap functions */
   28.28 +static char **outputDevices = NULL;
   28.29 +static int outputDeviceCount = 0;
   28.30 +static char **inputDevices = NULL;
   28.31 +static int inputDeviceCount = 0;
   28.32  
   28.33  static int
   28.34 -Audio_Available(void)
   28.35 +test_for_mmap(int fd)
   28.36  {
   28.37 -    int available;
   28.38 -    int fd;
   28.39 -
   28.40 -    available = 0;
   28.41 -
   28.42 -    fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
   28.43 -    if (fd >= 0) {
   28.44 -        int caps;
   28.45 -        struct audio_buf_info info;
   28.46 -
   28.47 -        if ((ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) == 0) &&
   28.48 -            (caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) &&
   28.49 -            (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) == 0)) {
   28.50 -            available = 1;
   28.51 +    int caps = 0;
   28.52 +    struct audio_buf_info info;
   28.53 +    if ((ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) == 0) &&
   28.54 +        (caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) &&
   28.55 +        (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) == 0))
   28.56 +    {
   28.57 +        size_t len = info.fragstotal * info.fragsize;
   28.58 +        Uint8 *buf = (Uint8 *) mmap(NULL, len, PROT_WRITE, MAP_SHARED, fd, 0);
   28.59 +        if (buf != MAP_FAILED) {
   28.60 +            munmap(buf, len);
   28.61 +            return 1;
   28.62          }
   28.63 -        close(fd);
   28.64      }
   28.65 -    return (available);
   28.66 +    return 0;
   28.67  }
   28.68  
   28.69 -static void
   28.70 -Audio_DeleteDevice(SDL_AudioDevice * device)
   28.71 +
   28.72 +static inline void
   28.73 +free_device_list(char ***devs, int *count)
   28.74  {
   28.75 -    SDL_free(device->hidden);
   28.76 -    SDL_free(device);
   28.77 +    SDL_FreeUnixAudioDevices(devs, count);
   28.78  }
   28.79  
   28.80 -static SDL_AudioDevice *
   28.81 -Audio_CreateDevice(int devindex)
   28.82 +static inline void
   28.83 +build_device_list(int iscapture, char ***devs, int *count)
   28.84  {
   28.85 -    SDL_AudioDevice *this;
   28.86 +    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
   28.87 +    free_device_list(devs, count);
   28.88 +    SDL_EnumUnixAudioDevices(flags, 0, test_for_mmap, devs, count);
   28.89 +}
   28.90 +
   28.91 +static inline void
   28.92 +build_device_lists(void)
   28.93 +{
   28.94 +    build_device_list(0, &outputDevices, &outputDeviceCount);
   28.95 +    build_device_list(1, &inputDevices, &inputDeviceCount);
   28.96 +}
   28.97 +
   28.98 +
   28.99 +static inline void
  28.100 +free_device_lists(void)
  28.101 +{
  28.102 +    free_device_list(&outputDevices, &outputDeviceCount);
  28.103 +    free_device_list(&inputDevices, &inputDeviceCount);
  28.104 +}
  28.105 +
  28.106 +
  28.107 +static void DMA_Deinitialize(void)
  28.108 +{
  28.109 +    free_device_lists();
  28.110 +}
  28.111 +
  28.112 +static int
  28.113 +DMA_DetectDevices(int iscapture)
  28.114 +{
  28.115 +    if (iscapture) {
  28.116 +        build_device_list(1, &inputDevices, &inputDeviceCount);
  28.117 +        return inputDeviceCount;
  28.118 +    } else {
  28.119 +        build_device_list(0, &outputDevices, &outputDeviceCount);
  28.120 +        return outputDeviceCount;
  28.121 +    }
  28.122 +
  28.123 +    return 0;  /* shouldn't ever hit this. */
  28.124 +}
  28.125 +
  28.126 +
  28.127 +static const char *
  28.128 +DMA_GetDeviceName(int index, int iscapture)
  28.129 +{
  28.130 +    if ((iscapture) && (index < inputDeviceCount)) {
  28.131 +        return inputDevices[index];
  28.132 +    } else if ((!iscapture) && (index < outputDeviceCount)) {
  28.133 +        return outputDevices[index];
  28.134 +    }
  28.135 +
  28.136 +    SDL_SetError("No such device");
  28.137 +    return NULL;
  28.138 +}
  28.139 +
  28.140 +
  28.141 +static int
  28.142 +DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo)
  28.143 +{
  28.144 +    int frag_spec;
  28.145 +    int value;
  28.146 +
  28.147 +    /* Close and then reopen the audio device */
  28.148 +    close(audio_fd);
  28.149 +    audio_fd = open(audiodev, O_RDWR, 0);
  28.150 +    if (audio_fd < 0) {
  28.151 +        SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
  28.152 +        return (-1);
  28.153 +    }
  28.154 +
  28.155 +    /* Calculate the final parameters for this audio specification */
  28.156 +    SDL_CalculateAudioSpec(&this->spec);
  28.157 +
  28.158 +    /* Determine the power of two of the fragment size */
  28.159 +    for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec);
  28.160 +    if ((0x01 << frag_spec) != this->spec.size) {
  28.161 +        SDL_SetError("Fragment size must be a power of two");
  28.162 +        return (-1);
  28.163 +    }
  28.164 +
  28.165 +    /* Set the audio buffering parameters */
  28.166 +    if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) {
  28.167 +        SDL_SetError("Couldn't set audio fragment spec");
  28.168 +        return (-1);
  28.169 +    }
  28.170 +
  28.171 +    /* Set the audio format */
  28.172 +    value = format;
  28.173 +    if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
  28.174 +        SDL_SetError("Couldn't set audio format");
  28.175 +        return (-1);
  28.176 +    }
  28.177 +
  28.178 +    /* Set mono or stereo audio */
  28.179 +    value = (this->spec.channels > 1);
  28.180 +    if ((ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) < 0) ||
  28.181 +        (value != stereo)) {
  28.182 +        SDL_SetError("Couldn't set audio channels");
  28.183 +        return (-1);
  28.184 +    }
  28.185 +
  28.186 +    /* Set the DSP frequency */
  28.187 +    value = this->spec.freq;
  28.188 +    if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
  28.189 +        SDL_SetError("Couldn't set audio frequency");
  28.190 +        return (-1);
  28.191 +    }
  28.192 +    this->spec.freq = value;
  28.193 +
  28.194 +    /* We successfully re-opened the audio */
  28.195 +    return (0);
  28.196 +}
  28.197 +
  28.198 +
  28.199 +static void
  28.200 +DMA_CloseDevice(_THIS)
  28.201 +{
  28.202 +    if (this->hidden != NULL) {
  28.203 +        if (dma_buf != NULL) {
  28.204 +            munmap(dma_buf, dma_len);
  28.205 +            dma_buf = NULL;
  28.206 +        }
  28.207 +        if (audio_fd >= 0) {
  28.208 +            close(audio_fd);
  28.209 +            audio_fd = -1;
  28.210 +        }
  28.211 +        SDL_free(this->hidden);
  28.212 +        this->hidden = NULL;
  28.213 +    }
  28.214 +}
  28.215 +
  28.216 +
  28.217 +static int
  28.218 +DMA_OpenDevice(_THIS, const char *devname, int iscapture)
  28.219 +{
  28.220 +    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
  28.221 +    int format;
  28.222 +    int stereo;
  28.223 +    int value;
  28.224 +    SDL_AudioFormat test_format;
  28.225 +    struct audio_buf_info info;
  28.226 +
  28.227 +    /* We don't care what the devname is...we'll try to open anything. */
  28.228 +    /*  ...but default to first name in the list... */
  28.229 +    if (devname == NULL) {
  28.230 +        if ( ((iscapture) && (inputDeviceCount == 0)) ||
  28.231 +             ((!iscapture) && (outputDeviceCount == 0)) ) {
  28.232 +            SDL_SetError("No such audio device");
  28.233 +            return 0;
  28.234 +        }
  28.235 +        devname = ((iscapture) ? inputDevices[0] : outputDevices[0]);
  28.236 +    }
  28.237  
  28.238      /* Initialize all variables that we clean on shutdown */
  28.239 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
  28.240 -    if (this) {
  28.241 -        SDL_memset(this, 0, (sizeof *this));
  28.242 -        this->hidden = (struct SDL_PrivateAudioData *)
  28.243 -            SDL_malloc((sizeof *this->hidden));
  28.244 -    }
  28.245 -    if ((this == NULL) || (this->hidden == NULL)) {
  28.246 +    this->hidden = (struct SDL_PrivateAudioData *)
  28.247 +                        SDL_malloc((sizeof *this->hidden));
  28.248 +    if (this->hidden == NULL) {
  28.249          SDL_OutOfMemory();
  28.250 -        if (this) {
  28.251 -            SDL_free(this);
  28.252 -        }
  28.253 -        return (0);
  28.254 +        return 0;
  28.255      }
  28.256      SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  28.257 -    audio_fd = -1;
  28.258  
  28.259 -    /* Set the function pointers */
  28.260 -    this->OpenAudio = DMA_OpenAudio;
  28.261 -    this->WaitAudio = DMA_WaitAudio;
  28.262 -    this->PlayAudio = DMA_PlayAudio;
  28.263 -    this->GetAudioBuf = DMA_GetAudioBuf;
  28.264 -    this->CloseAudio = DMA_CloseAudio;
  28.265 +    /* Open the audio device */
  28.266 +    audio_fd = open(devname, flags, 0);
  28.267 +    if (audio_fd < 0) {
  28.268 +        DMA_CloseDevice(this);
  28.269 +        SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
  28.270 +        return 0;
  28.271 +    }
  28.272 +    dma_buf = NULL;
  28.273 +    ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
  28.274  
  28.275 -    this->free = Audio_DeleteDevice;
  28.276 +    /* Get a list of supported hardware formats */
  28.277 +    if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
  28.278 +        DMA_CloseDevice(this);
  28.279 +        SDL_SetError("Couldn't get audio format list");
  28.280 +        return 0;
  28.281 +    }
  28.282  
  28.283 -    return this;
  28.284 +    /* Try for a closest match on audio format */
  28.285 +    format = 0;
  28.286 +    for (test_format = SDL_FirstAudioFormat(this->spec.format);
  28.287 +         !format && test_format;) {
  28.288 +#ifdef DEBUG_AUDIO
  28.289 +        fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
  28.290 +#endif
  28.291 +        switch (test_format) {
  28.292 +        case AUDIO_U8:
  28.293 +            if (value & AFMT_U8) {
  28.294 +                format = AFMT_U8;
  28.295 +            }
  28.296 +            break;
  28.297 +        case AUDIO_S8:
  28.298 +            if (value & AFMT_S8) {
  28.299 +                format = AFMT_S8;
  28.300 +            }
  28.301 +            break;
  28.302 +        case AUDIO_S16LSB:
  28.303 +            if (value & AFMT_S16_LE) {
  28.304 +                format = AFMT_S16_LE;
  28.305 +            }
  28.306 +            break;
  28.307 +        case AUDIO_S16MSB:
  28.308 +            if (value & AFMT_S16_BE) {
  28.309 +                format = AFMT_S16_BE;
  28.310 +            }
  28.311 +            break;
  28.312 +        case AUDIO_U16LSB:
  28.313 +            if (value & AFMT_U16_LE) {
  28.314 +                format = AFMT_U16_LE;
  28.315 +            }
  28.316 +            break;
  28.317 +        case AUDIO_U16MSB:
  28.318 +            if (value & AFMT_U16_BE) {
  28.319 +                format = AFMT_U16_BE;
  28.320 +            }
  28.321 +            break;
  28.322 +        default:
  28.323 +            format = 0;
  28.324 +            break;
  28.325 +        }
  28.326 +        if (!format) {
  28.327 +            test_format = SDL_NextAudioFormat();
  28.328 +        }
  28.329 +    }
  28.330 +    if (format == 0) {
  28.331 +        DMA_CloseDevice(this);
  28.332 +        SDL_SetError("Couldn't find any hardware audio formats");
  28.333 +        return 0;
  28.334 +    }
  28.335 +    this->spec.format = test_format;
  28.336 +
  28.337 +    /* Set the audio format */
  28.338 +    value = format;
  28.339 +    if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
  28.340 +        DMA_CloseDevice(this);
  28.341 +        SDL_SetError("Couldn't set audio format");
  28.342 +        return 0;
  28.343 +    }
  28.344 +
  28.345 +    /* Set mono or stereo audio (currently only two channels supported) */
  28.346 +    stereo = (this->spec.channels > 1);
  28.347 +    ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo);
  28.348 +    if (stereo) {
  28.349 +        this->spec.channels = 2;
  28.350 +    } else {
  28.351 +        this->spec.channels = 1;
  28.352 +    }
  28.353 +
  28.354 +    /* Because some drivers don't allow setting the buffer size
  28.355 +       after setting the format, we must re-open the audio device
  28.356 +       once we know what format and channels are supported
  28.357 +     */
  28.358 +    if (DMA_ReopenAudio(this, devname, format, stereo) < 0) {
  28.359 +        DMA_CloseDevice(this);
  28.360 +        /* Error is set by DMA_ReopenAudio() */
  28.361 +        return 0;
  28.362 +    }
  28.363 +
  28.364 +    /* Memory map the audio buffer */
  28.365 +    if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
  28.366 +        DMA_CloseDevice(this);
  28.367 +        SDL_SetError("Couldn't get OSPACE parameters");
  28.368 +        return 0;
  28.369 +    }
  28.370 +    this->spec.size = info.fragsize;
  28.371 +    this->spec.samples = this->spec.size / ((this->spec.format & 0xFF) / 8);
  28.372 +    this->spec.samples /= this->spec.channels;
  28.373 +    num_buffers = info.fragstotal;
  28.374 +    dma_len = num_buffers * this->spec.size;
  28.375 +    dma_buf = (Uint8 *) mmap(NULL, dma_len, PROT_WRITE, MAP_SHARED,
  28.376 +                             audio_fd, 0);
  28.377 +    if (dma_buf == MAP_FAILED) {
  28.378 +        DMA_CloseDevice(this);
  28.379 +        SDL_SetError("DMA memory map failed");
  28.380 +        dma_buf = NULL;
  28.381 +        return 0;
  28.382 +    }
  28.383 +    SDL_memset(dma_buf, this->spec.silence, dma_len);
  28.384 +
  28.385 +    /* Check to see if we need to use select() workaround */
  28.386 +    {
  28.387 +        char *workaround;
  28.388 +        workaround = SDL_getenv("SDL_DSP_NOSELECT");
  28.389 +        if (workaround) {
  28.390 +            frame_ticks = (float) (this->spec.samples*1000) / this->spec.freq;
  28.391 +            next_frame = SDL_GetTicks() + frame_ticks;
  28.392 +        }
  28.393 +    }
  28.394 +
  28.395 +    /* Trigger audio playback */
  28.396 +    value = 0;
  28.397 +    ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value);
  28.398 +    value = PCM_ENABLE_OUTPUT;
  28.399 +    if (ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value) < 0) {
  28.400 +        DMA_CloseDevice(this);
  28.401 +        SDL_SetError("Couldn't trigger audio output");
  28.402 +        return 0;
  28.403 +    }
  28.404 +
  28.405 +    /* Get the parent process id (we're the parent of the audio thread) */
  28.406 +    parent = getpid();
  28.407 +
  28.408 +    /* We're ready to rock and roll. :-) */
  28.409 +    return 1;
  28.410  }
  28.411  
  28.412 -AudioBootStrap DMA_bootstrap = {
  28.413 -    DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio",
  28.414 -    Audio_Available, Audio_CreateDevice
  28.415 -};
  28.416  
  28.417  /* This function waits until it is possible to write a full sound buffer */
  28.418  static void
  28.419 -DMA_WaitAudio(_THIS)
  28.420 +DMA_WaitDevice(_THIS)
  28.421  {
  28.422      fd_set fdset;
  28.423  
  28.424 @@ -189,8 +455,8 @@
  28.425              fprintf(stderr, "SDL: %s\n", message);
  28.426  #ifdef AUDIO_OSPACE_HACK
  28.427              /* We may be able to use GET_OSPACE trick */
  28.428 -            frame_ticks = (float) (this->spec->samples * 1000) /
  28.429 -                this->spec->freq;
  28.430 +            frame_ticks = (float) (this->spec.samples * 1000) /
  28.431 +                this->spec.freq;
  28.432              next_frame = SDL_GetTicks() + frame_ticks;
  28.433  #else
  28.434              this->enabled = 0;
  28.435 @@ -208,7 +474,7 @@
  28.436  }
  28.437  
  28.438  static void
  28.439 -DMA_PlayAudio(_THIS)
  28.440 +DMA_PlayDevice(_THIS)
  28.441  {
  28.442      /* If timer synchronization is enabled, set the next write frame */
  28.443      if (frame_ticks) {
  28.444 @@ -218,7 +484,7 @@
  28.445  }
  28.446  
  28.447  static Uint8 *
  28.448 -DMA_GetAudioBuf(_THIS)
  28.449 +DMA_GetDeviceBuf(_THIS)
  28.450  {
  28.451      count_info info;
  28.452      int playing;
  28.453 @@ -243,225 +509,26 @@
  28.454      return (dma_buf + (filling * this->spec.size));
  28.455  }
  28.456  
  28.457 -static void
  28.458 -DMA_CloseAudio(_THIS)
  28.459 +
  28.460 +static int
  28.461 +DMA_Init(SDL_AudioDriverImpl *impl)
  28.462  {
  28.463 -    if (dma_buf != NULL) {
  28.464 -        munmap(dma_buf, dma_len);
  28.465 -        dma_buf = NULL;
  28.466 -    }
  28.467 -    if (audio_fd >= 0) {
  28.468 -        close(audio_fd);
  28.469 -        audio_fd = -1;
  28.470 -    }
  28.471 +    /* Set the function pointers */
  28.472 +    impl->DetectDevices = DMA_DetectDevices;
  28.473 +    impl->GetDeviceName = DMA_GetDeviceName;
  28.474 +    impl->OpenDevice = DMA_OpenDevice;
  28.475 +    impl->WaitDevice = DMA_WaitDevice;
  28.476 +    impl->PlayDevice = DMA_PlayDevice;
  28.477 +    impl->GetDeviceBuf = DMA_GetDeviceBuf;
  28.478 +    impl->CloseDevice = DMA_CloseDevice;
  28.479 +    impl->Deinitialize = DMA_Deinitialize;
  28.480 +
  28.481 +    build_device_lists();
  28.482 +    return 1;
  28.483  }
  28.484  
  28.485 -static int
  28.486 -DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo,
  28.487 -                SDL_AudioSpec * spec)
  28.488 -{
  28.489 -    int frag_spec;
  28.490 -    int value;
  28.491 -
  28.492 -    /* Close and then reopen the audio device */
  28.493 -    close(audio_fd);
  28.494 -    audio_fd = open(audiodev, O_RDWR, 0);
  28.495 -    if (audio_fd < 0) {
  28.496 -        SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
  28.497 -        return (-1);
  28.498 -    }
  28.499 -
  28.500 -    /* Calculate the final parameters for this audio specification */
  28.501 -    SDL_CalculateAudioSpec(spec);
  28.502 -
  28.503 -    /* Determine the power of two of the fragment size */
  28.504 -    for (frag_spec = 0; (0x01 << frag_spec) < spec->size; ++frag_spec);
  28.505 -    if ((0x01 << frag_spec) != spec->size) {
  28.506 -        SDL_SetError("Fragment size must be a power of two");
  28.507 -        return (-1);
  28.508 -    }
  28.509 -
  28.510 -    /* Set the audio buffering parameters */
  28.511 -    if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) {
  28.512 -        SDL_SetError("Couldn't set audio fragment spec");
  28.513 -        return (-1);
  28.514 -    }
  28.515 -
  28.516 -    /* Set the audio format */
  28.517 -    value = format;
  28.518 -    if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
  28.519 -        SDL_SetError("Couldn't set audio format");
  28.520 -        return (-1);
  28.521 -    }
  28.522 -
  28.523 -    /* Set mono or stereo audio */
  28.524 -    value = (spec->channels > 1);
  28.525 -    if ((ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) < 0) ||
  28.526 -        (value != stereo)) {
  28.527 -        SDL_SetError("Couldn't set audio channels");
  28.528 -        return (-1);
  28.529 -    }
  28.530 -
  28.531 -    /* Set the DSP frequency */
  28.532 -    value = spec->freq;
  28.533 -    if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
  28.534 -        SDL_SetError("Couldn't set audio frequency");
  28.535 -        return (-1);
  28.536 -    }
  28.537 -    spec->freq = value;
  28.538 -
  28.539 -    /* We successfully re-opened the audio */
  28.540 -    return (0);
  28.541 -}
  28.542 -
  28.543 -static int
  28.544 -DMA_OpenAudio(_THIS, SDL_AudioSpec * spec)
  28.545 -{
  28.546 -    char audiodev[1024];
  28.547 -    int format;
  28.548 -    int stereo;
  28.549 -    int value;
  28.550 -    SDL_AudioFormat test_format;
  28.551 -    struct audio_buf_info info;
  28.552 -
  28.553 -    /* Reset the timer synchronization flag */
  28.554 -    frame_ticks = 0.0;
  28.555 -
  28.556 -    /* Open the audio device */
  28.557 -    audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
  28.558 -    if (audio_fd < 0) {
  28.559 -        SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
  28.560 -        return (-1);
  28.561 -    }
  28.562 -    dma_buf = NULL;
  28.563 -    ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
  28.564 -
  28.565 -    /* Get a list of supported hardware formats */
  28.566 -    if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
  28.567 -        SDL_SetError("Couldn't get audio format list");
  28.568 -        return (-1);
  28.569 -    }
  28.570 -
  28.571 -    /* Try for a closest match on audio format */
  28.572 -    format = 0;
  28.573 -    for (test_format = SDL_FirstAudioFormat(spec->format);
  28.574 -         !format && test_format;) {
  28.575 -#ifdef DEBUG_AUDIO
  28.576 -        fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
  28.577 -#endif
  28.578 -        switch (test_format) {
  28.579 -        case AUDIO_U8:
  28.580 -            if (value & AFMT_U8) {
  28.581 -                format = AFMT_U8;
  28.582 -            }
  28.583 -            break;
  28.584 -        case AUDIO_S8:
  28.585 -            if (value & AFMT_S8) {
  28.586 -                format = AFMT_S8;
  28.587 -            }
  28.588 -            break;
  28.589 -        case AUDIO_S16LSB:
  28.590 -            if (value & AFMT_S16_LE) {
  28.591 -                format = AFMT_S16_LE;
  28.592 -            }
  28.593 -            break;
  28.594 -        case AUDIO_S16MSB:
  28.595 -            if (value & AFMT_S16_BE) {
  28.596 -                format = AFMT_S16_BE;
  28.597 -            }
  28.598 -            break;
  28.599 -        case AUDIO_U16LSB:
  28.600 -            if (value & AFMT_U16_LE) {
  28.601 -                format = AFMT_U16_LE;
  28.602 -            }
  28.603 -            break;
  28.604 -        case AUDIO_U16MSB:
  28.605 -            if (value & AFMT_U16_BE) {
  28.606 -                format = AFMT_U16_BE;
  28.607 -            }
  28.608 -            break;
  28.609 -        default:
  28.610 -            format = 0;
  28.611 -            break;
  28.612 -        }
  28.613 -        if (!format) {
  28.614 -            test_format = SDL_NextAudioFormat();
  28.615 -        }
  28.616 -    }
  28.617 -    if (format == 0) {
  28.618 -        SDL_SetError("Couldn't find any hardware audio formats");
  28.619 -        return (-1);
  28.620 -    }
  28.621 -    spec->format = test_format;
  28.622 -
  28.623 -    /* Set the audio format */
  28.624 -    value = format;
  28.625 -    if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
  28.626 -        SDL_SetError("Couldn't set audio format");
  28.627 -        return (-1);
  28.628 -    }
  28.629 -
  28.630 -    /* Set mono or stereo audio (currently only two channels supported) */
  28.631 -    stereo = (spec->channels > 1);
  28.632 -    ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo);
  28.633 -    if (stereo) {
  28.634 -        spec->channels = 2;
  28.635 -    } else {
  28.636 -        spec->channels = 1;
  28.637 -    }
  28.638 -
  28.639 -    /* Because some drivers don't allow setting the buffer size
  28.640 -       after setting the format, we must re-open the audio device
  28.641 -       once we know what format and channels are supported
  28.642 -     */
  28.643 -    if (DMA_ReopenAudio(this, audiodev, format, stereo, spec) < 0) {
  28.644 -        /* Error is set by DMA_ReopenAudio() */
  28.645 -        return (-1);
  28.646 -    }
  28.647 -
  28.648 -    /* Memory map the audio buffer */
  28.649 -    if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
  28.650 -        SDL_SetError("Couldn't get OSPACE parameters");
  28.651 -        return (-1);
  28.652 -    }
  28.653 -    spec->size = info.fragsize;
  28.654 -    spec->samples = spec->size / ((spec->format & 0xFF) / 8);
  28.655 -    spec->samples /= spec->channels;
  28.656 -    num_buffers = info.fragstotal;
  28.657 -    dma_len = num_buffers * spec->size;
  28.658 -    dma_buf = (Uint8 *) mmap(NULL, dma_len, PROT_WRITE, MAP_SHARED,
  28.659 -                             audio_fd, 0);
  28.660 -    if (dma_buf == MAP_FAILED) {
  28.661 -        SDL_SetError("DMA memory map failed");
  28.662 -        dma_buf = NULL;
  28.663 -        return (-1);
  28.664 -    }
  28.665 -    SDL_memset(dma_buf, spec->silence, dma_len);
  28.666 -
  28.667 -    /* Check to see if we need to use select() workaround */
  28.668 -    {
  28.669 -        char *workaround;
  28.670 -        workaround = SDL_getenv("SDL_DSP_NOSELECT");
  28.671 -        if (workaround) {
  28.672 -            frame_ticks = (float) (spec->samples * 1000) / spec->freq;
  28.673 -            next_frame = SDL_GetTicks() + frame_ticks;
  28.674 -        }
  28.675 -    }
  28.676 -
  28.677 -    /* Trigger audio playback */
  28.678 -    value = 0;
  28.679 -    ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value);
  28.680 -    value = PCM_ENABLE_OUTPUT;
  28.681 -    if (ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value) < 0) {
  28.682 -        SDL_SetError("Couldn't trigger audio output");
  28.683 -        return (-1);
  28.684 -    }
  28.685 -
  28.686 -    /* Get the parent process id (we're the parent of the audio thread) */
  28.687 -    parent = getpid();
  28.688 -
  28.689 -    /* We're ready to rock and roll. :-) */
  28.690 -    return (0);
  28.691 -}
  28.692 +AudioBootStrap DMA_bootstrap = {
  28.693 +    DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio", DMA_Init, 0
  28.694 +};
  28.695  
  28.696  /* vi: set ts=4 sw=4 expandtab: */
    29.1 --- a/src/audio/dma/SDL_dmaaudio.h	Sun Oct 01 16:10:41 2006 +0000
    29.2 +++ b/src/audio/dma/SDL_dmaaudio.h	Tue Oct 17 09:15:21 2006 +0000
    29.3 @@ -21,12 +21,12 @@
    29.4  */
    29.5  #include "SDL_config.h"
    29.6  
    29.7 -#ifndef _SDL_dspaudio_h
    29.8 -#define _SDL_dspaudio_h
    29.9 +#ifndef _SDL_dmaaudio_h
   29.10 +#define _SDL_dmaaudio_h
   29.11  
   29.12  #include "../SDL_sysaudio.h"
   29.13  
   29.14 -/* Hidden "this" pointer for the video functions */
   29.15 +/* Hidden "this" pointer for the audio functions */
   29.16  #define _THIS	SDL_AudioDevice *this
   29.17  
   29.18  struct SDL_PrivateAudioData
   29.19 @@ -49,6 +49,7 @@
   29.20  #define FUDGE_TICKS	10      /* The scheduler overhead ticks per frame */
   29.21  
   29.22  /* Old variable names */
   29.23 +/* !!! FIXME: remove these. */
   29.24  #define audio_fd		(this->hidden->audio_fd)
   29.25  #define parent			(this->hidden->parent)
   29.26  #define dma_buf			(this->hidden->dma_buf)
   29.27 @@ -57,5 +58,6 @@
   29.28  #define frame_ticks		(this->hidden->frame_ticks)
   29.29  #define next_frame		(this->hidden->next_frame)
   29.30  
   29.31 -#endif /* _SDL_dspaudio_h */
   29.32 +#endif /* _SDL_dmaaudio_h */
   29.33 +
   29.34  /* vi: set ts=4 sw=4 expandtab: */
    30.1 --- a/src/audio/dmedia/SDL_irixaudio.c	Sun Oct 01 16:10:41 2006 +0000
    30.2 +++ b/src/audio/dmedia/SDL_irixaudio.c	Tue Oct 17 09:15:21 2006 +0000
    30.3 @@ -45,73 +45,12 @@
    30.4  #define alSetWidth(x,y) ALsetwidth(x,y)
    30.5  #endif
    30.6  
    30.7 -/* Audio driver functions */
    30.8 -static int AL_OpenAudio(_THIS, SDL_AudioSpec * spec);
    30.9 -static void AL_WaitAudio(_THIS);
   30.10 -static void AL_PlayAudio(_THIS);
   30.11 -static Uint8 *AL_GetAudioBuf(_THIS);
   30.12 -static void AL_CloseAudio(_THIS);
   30.13 -
   30.14 -/* Audio driver bootstrap functions */
   30.15 -
   30.16 -static int
   30.17 -Audio_Available(void)
   30.18 -{
   30.19 -    return 1;
   30.20 -}
   30.21 -
   30.22 -static void
   30.23 -Audio_DeleteDevice(SDL_AudioDevice * device)
   30.24 -{
   30.25 -    SDL_free(device->hidden);
   30.26 -    SDL_free(device);
   30.27 -}
   30.28 -
   30.29 -static SDL_AudioDevice *
   30.30 -Audio_CreateDevice(int devindex)
   30.31 -{
   30.32 -    SDL_AudioDevice *this;
   30.33 -
   30.34 -    /* Initialize all variables that we clean on shutdown */
   30.35 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
   30.36 -    if (this) {
   30.37 -        SDL_memset(this, 0, (sizeof *this));
   30.38 -        this->hidden = (struct SDL_PrivateAudioData *)
   30.39 -            SDL_malloc((sizeof *this->hidden));
   30.40 -    }
   30.41 -    if ((this == NULL) || (this->hidden == NULL)) {
   30.42 -        SDL_OutOfMemory();
   30.43 -        if (this) {
   30.44 -            SDL_free(this);
   30.45 -        }
   30.46 -        return (0);
   30.47 -    }
   30.48 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   30.49 -
   30.50 -    /* Set the function pointers */
   30.51 -    this->OpenAudio = AL_OpenAudio;
   30.52 -    this->WaitAudio = AL_WaitAudio;
   30.53 -    this->PlayAudio = AL_PlayAudio;
   30.54 -    this->GetAudioBuf = AL_GetAudioBuf;
   30.55 -    this->CloseAudio = AL_CloseAudio;
   30.56 -
   30.57 -    this->free = Audio_DeleteDevice;
   30.58 -
   30.59 -    return this;
   30.60 -}
   30.61 -
   30.62 -AudioBootStrap DMEDIA_bootstrap = {
   30.63 -    "AL", "IRIX DMedia audio",
   30.64 -    Audio_Available, Audio_CreateDevice
   30.65 -};
   30.66 -
   30.67 -
   30.68  void static
   30.69 -AL_WaitAudio(_THIS)
   30.70 +IRIXAUDIO_WaitDevice(_THIS)
   30.71  {
   30.72      Sint32 timeleft;
   30.73  
   30.74 -    timeleft = this->spec.samples - alGetFillable(audio_port);
   30.75 +    timeleft = this->spec.samples - alGetFillable(this->hidden->audio_port);
   30.76      if (timeleft > 0) {
   30.77          timeleft /= (this->spec.freq / 1000);
   30.78          SDL_Delay((Uint32) timeleft);
   30.79 @@ -119,61 +58,78 @@
   30.80  }
   30.81  
   30.82  static void
   30.83 -AL_PlayAudio(_THIS)
   30.84 +IRIXAUDIO_PlayDevice(_THIS)
   30.85  {
   30.86      /* Write the audio data out */
   30.87 -    if (alWriteFrames(audio_port, mixbuf, this->spec.samples) < 0) {
   30.88 +    ALport port = this->hidden->audio_port;
   30.89 +    Uint8 *mixbuf = this->hidden->mixbuf;
   30.90 +    if (alWriteFrames(port, mixbuf, this->spec.samples) < 0) {
   30.91          /* Assume fatal error, for now */
   30.92          this->enabled = 0;
   30.93      }
   30.94  }
   30.95  
   30.96  static Uint8 *
   30.97 -AL_GetAudioBuf(_THIS)
   30.98 +IRIXAUDIO_GetDeviceBuf(_THIS)
   30.99  {
  30.100 -    return (mixbuf);
  30.101 +    return (this->hidden->mixbuf);
  30.102  }
  30.103  
  30.104  static void
  30.105 -AL_CloseAudio(_THIS)
  30.106 +IRIXAUDIO_CloseDevice(_THIS)
  30.107  {
  30.108 -    if (mixbuf != NULL) {
  30.109 -        SDL_FreeAudioMem(mixbuf);
  30.110 -        mixbuf = NULL;
  30.111 -    }
  30.112 -    if (audio_port != NULL) {
  30.113 -        alClosePort(audio_port);
  30.114 -        audio_port = NULL;
  30.115 +    if (this->hidden != NULL) {
  30.116 +        if (this->hidden->mixbuf != NULL) {
  30.117 +            SDL_FreeAudioMem(this->hidden->mixbuf);
  30.118 +            this->hidden->mixbuf = NULL;
  30.119 +        }
  30.120 +        if (this->hidden->audio_port != NULL) {
  30.121 +            alClosePort(this->hidden->audio_port);
  30.122 +            this->hidden->audio_port = NULL;
  30.123 +        }
  30.124 +        SDL_free(this->hidden);
  30.125 +        this->hidden = NULL;
  30.126      }
  30.127  }
  30.128  
  30.129  static int
  30.130 -AL_OpenAudio(_THIS, SDL_AudioSpec * spec)
  30.131 +IRIXAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
  30.132  {
  30.133 -    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
  30.134 +    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
  30.135      long width = 0;
  30.136      long fmt = 0;
  30.137      int valid = 0;
  30.138  
  30.139 +    /* !!! FIXME: Handle multiple devices and capture? */
  30.140 +
  30.141 +    /* Initialize all variables that we clean on shutdown */
  30.142 +    this->hidden = (struct SDL_PrivateAudioData *)
  30.143 +                        SDL_malloc((sizeof *this->hidden));
  30.144 +    if (this->hidden == NULL) {
  30.145 +        SDL_OutOfMemory();
  30.146 +        return 0;
  30.147 +    }
  30.148 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  30.149 +
  30.150  #ifdef OLD_IRIX_AUDIO
  30.151      {
  30.152          long audio_param[2];
  30.153          audio_param[0] = AL_OUTPUT_RATE;
  30.154 -        audio_param[1] = spec->freq;
  30.155 +        audio_param[1] = this->spec.freq;
  30.156          valid = (ALsetparams(AL_DEFAULT_DEVICE, audio_param, 2) < 0);
  30.157      }
  30.158  #else
  30.159      {
  30.160          ALpv audio_param;
  30.161          audio_param.param = AL_RATE;
  30.162 -        audio_param.value.i = spec->freq;
  30.163 +        audio_param.value.i = this->spec.freq;
  30.164          valid = (alSetParams(AL_DEFAULT_OUTPUT, &audio_param, 1) < 0);
  30.165      }
  30.166  #endif
  30.167  
  30.168      while ((!valid) && (test_format)) {
  30.169          valid = 1;
  30.170 -        spec->format = test_format;
  30.171 +        this->spec.format = test_format;
  30.172  
  30.173          switch (test_format) {
  30.174          case AUDIO_S8:
  30.175 @@ -203,30 +159,31 @@
  30.176              ALconfig audio_config = alNewConfig();
  30.177              valid = 0;
  30.178              if (audio_config) {
  30.179 -                if (alSetChannels(audio_config, spec->channels) < 0) {
  30.180 -                    if (spec->channels > 2) {   /* can't handle > stereo? */
  30.181 -                        spec->channels = 2;     /* try again below. */
  30.182 +                if (alSetChannels(audio_config, this->spec.channels) < 0) {
  30.183 +                    if (this->spec.channels > 2) { /* can't handle > stereo? */
  30.184 +                        this->spec.channels = 2;   /* try again below. */
  30.185                      }
  30.186                  }
  30.187  
  30.188                  if ((alSetSampFmt(audio_config, fmt) >= 0) &&
  30.189                      ((!width) || (alSetWidth(audio_config, width) >= 0)) &&
  30.190 -                    (alSetQueueSize(audio_config, spec->samples * 2) >= 0) &&
  30.191 -                    (alSetChannels(audio_config, spec->channels) >= 0)) {
  30.192 +                    (alSetQueueSize(audio_config,this->spec.samples*2) >= 0) &&
  30.193 +                    (alSetChannels(audio_config, this->spec.channels) >= 0)) {
  30.194  
  30.195 -                    audio_port = alOpenPort("SDL audio", "w", audio_config);
  30.196 -                    if (audio_port == NULL) {
  30.197 +                    this->hidden->audio_port = alOpenPort("SDL audio", "w",
  30.198 +                                                          audio_config);
  30.199 +                    if (this->hidden->audio_port == NULL) {
  30.200                          /* docs say AL_BAD_CHANNELS happens here, too. */
  30.201                          int err = oserror();
  30.202                          if (err == AL_BAD_CHANNELS) {
  30.203 -                            spec->channels = 2;
  30.204 -                            alSetChannels(audio_config, spec->channels);
  30.205 -                            audio_port = alOpenPort("SDL audio", "w",
  30.206 -                                                    audio_config);
  30.207 +                            this->spec.channels = 2;
  30.208 +                            alSetChannels(audio_config, this->spec.channels);
  30.209 +                            this->hidden->audio_port = alOpenPort("SDL audio", "w",
  30.210 +                                                                 audio_config);
  30.211                          }
  30.212                      }
  30.213  
  30.214 -                    if (audio_port != NULL) {
  30.215 +                    if (this->hidden->audio_port != NULL) {
  30.216                          valid = 1;
  30.217                      }
  30.218                  }
  30.219 @@ -237,23 +194,43 @@
  30.220      }
  30.221  
  30.222      if (!valid) {
  30.223 +        IRIXAUDIO_CloseDevice(this);
  30.224          SDL_SetError("Unsupported audio format");
  30.225 -        return (-1);
  30.226 +        return 0;
  30.227      }
  30.228  
  30.229      /* Update the fragment size as size in bytes */
  30.230 -    SDL_CalculateAudioSpec(spec);
  30.231 +    SDL_CalculateAudioSpec(&this->spec);
  30.232  
  30.233      /* Allocate mixing buffer */
  30.234 -    mixbuf = (Uint8 *) SDL_AllocAudioMem(spec->size);
  30.235 -    if (mixbuf == NULL) {
  30.236 +    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->spec.size);
  30.237 +    if (this->hidden->mixbuf == NULL) {
  30.238 +        IRIXAUDIO_CloseDevice(this);
  30.239          SDL_OutOfMemory();
  30.240 -        return (-1);
  30.241 +        return 0;
  30.242      }
  30.243 -    SDL_memset(mixbuf, spec->silence, spec->size);
  30.244 +    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
  30.245  
  30.246      /* We're ready to rock and roll. :-) */
  30.247 -    return (0);
  30.248 +    return 1;
  30.249  }
  30.250  
  30.251 +static int
  30.252 +IRIXAUDIO_Init(SDL_AudioDriverImpl *impl)
  30.253 +{
  30.254 +    /* Set the function pointers */
  30.255 +    impl->OpenDevice = DSP_OpenDevice;
  30.256 +    impl->PlayDevice = DSP_PlayDevice;
  30.257 +    impl->WaitDevice = DSP_WaitDevice;
  30.258 +    impl->GetDeviceBuf = DSP_GetDeviceBuf;
  30.259 +    impl->CloseDevice = DSP_CloseDevice;
  30.260 +    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: not true, I think. */
  30.261 +
  30.262 +    return 1;
  30.263 +}
  30.264 +
  30.265 +AudioBootStrap IRIXAUDIO_bootstrap = {
  30.266 +    "AL", "IRIX DMedia audio", IRIXAUDIO_Init, 0
  30.267 +};
  30.268 +
  30.269  /* vi: set ts=4 sw=4 expandtab: */
    31.1 --- a/src/audio/dmedia/SDL_irixaudio.h	Sun Oct 01 16:10:41 2006 +0000
    31.2 +++ b/src/audio/dmedia/SDL_irixaudio.h	Tue Oct 17 09:15:21 2006 +0000
    31.3 @@ -21,8 +21,8 @@
    31.4  */
    31.5  #include "SDL_config.h"
    31.6  
    31.7 -#ifndef _SDL_lowaudio_h
    31.8 -#define _SDL_lowaudio_h
    31.9 +#ifndef _SDL_irixaudio_h
   31.10 +#define _SDL_irixaudio_h
   31.11  
   31.12  #include <dmedia/audio.h>
   31.13  
   31.14 @@ -33,15 +33,10 @@
   31.15  
   31.16  struct SDL_PrivateAudioData
   31.17  {
   31.18 -    /* The handle for the audio device */
   31.19 -    ALport audio_port;
   31.20 -
   31.21 -    Uint8 *mixbuf;              /* The app mixing buffer */
   31.22 +    ALport audio_port;    /* The handle for the audio device */
   31.23 +    Uint8 *mixbuf;        /* The app mixing buffer */
   31.24  };
   31.25  
   31.26 -/* Old variable names */
   31.27 -#define audio_port		(this->hidden->audio_port)
   31.28 -#define mixbuf			(this->hidden->mixbuf)
   31.29 +#endif /* _SDL_irixaudio_h */
   31.30  
   31.31 -#endif /* _SDL_lowaudio_h */
   31.32  /* vi: set ts=4 sw=4 expandtab: */
    32.1 --- a/src/audio/dsp/SDL_dspaudio.c	Sun Oct 01 16:10:41 2006 +0000
    32.2 +++ b/src/audio/dsp/SDL_dspaudio.c	Tue Oct 17 09:15:21 2006 +0000
    32.3 @@ -55,156 +55,158 @@
    32.4  #define DSP_DRIVER_NAME         "dsp"
    32.5  
    32.6  /* Open the audio device for playback, and don't block if busy */
    32.7 -#define OPEN_FLAGS	(O_WRONLY|O_NONBLOCK)
    32.8 +#define OPEN_FLAGS_OUTPUT    (O_WRONLY|O_NONBLOCK)
    32.9 +#define OPEN_FLAGS_INPUT    (O_RDONLY|O_NONBLOCK)
   32.10  
   32.11 -/* Audio driver functions */
   32.12 -static int DSP_OpenAudio(_THIS, SDL_AudioSpec * spec);
   32.13 -static void DSP_WaitAudio(_THIS);
   32.14 -static void DSP_PlayAudio(_THIS);
   32.15 -static Uint8 *DSP_GetAudioBuf(_THIS);
   32.16 -static void DSP_CloseAudio(_THIS);
   32.17 +static char **outputDevices = NULL;
   32.18 +static int outputDeviceCount = 0;
   32.19 +static char **inputDevices = NULL;
   32.20 +static int inputDeviceCount = 0;
   32.21  
   32.22 -/* Audio driver bootstrap functions */
   32.23 +static inline void
   32.24 +free_device_list(char ***devs, int *count)
   32.25 +{
   32.26 +    SDL_FreeUnixAudioDevices(devs, count);
   32.27 +}
   32.28 +
   32.29 +static inline void
   32.30 +build_device_list(int iscapture, char ***devs, int *count)
   32.31 +{
   32.32 +    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
   32.33 +    free_device_list(devs, count);
   32.34 +    SDL_EnumUnixAudioDevices(flags, 0, NULL, devs, count);
   32.35 +}
   32.36 +
   32.37 +static inline void
   32.38 +build_device_lists(void)
   32.39 +{
   32.40 +    build_device_list(0, &outputDevices, &outputDeviceCount);
   32.41 +    build_device_list(1, &inputDevices, &inputDeviceCount);
   32.42 +}
   32.43 +
   32.44 +
   32.45 +static inline void
   32.46 +free_device_lists(void)
   32.47 +{
   32.48 +    free_device_list(&outputDevices, &outputDeviceCount);
   32.49 +    free_device_list(&inputDevices, &inputDeviceCount);
   32.50 +}
   32.51 +
   32.52 +
   32.53 +static void
   32.54 +DSP_Deinitialize(void)
   32.55 +{
   32.56 +    free_device_lists();
   32.57 +}
   32.58 +
   32.59  
   32.60  static int
   32.61 -Audio_Available(void)
   32.62 +DSP_DetectDevices(int iscapture)
   32.63  {
   32.64 -    int fd;
   32.65 -    int available;
   32.66 +    if (iscapture) {
   32.67 +        build_device_list(1, &inputDevices, &inputDeviceCount);
   32.68 +        return inputDeviceCount;
   32.69 +    } else {
   32.70 +        build_device_list(0, &outputDevices, &outputDeviceCount);
   32.71 +        return outputDeviceCount;
   32.72 +    }
   32.73  
   32.74 -    available = 0;
   32.75 -    fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
   32.76 -    if (fd >= 0) {
   32.77 -        available = 1;
   32.78 -        close(fd);
   32.79 -    }
   32.80 -    return (available);
   32.81 +    return 0;  /* shouldn't ever hit this. */
   32.82  }
   32.83  
   32.84 -static void
   32.85 -Audio_DeleteDevice(SDL_AudioDevice * device)
   32.86 +static const char *
   32.87 +DSP_GetDeviceName(int index, int iscapture)
   32.88  {
   32.89 -    SDL_free(device->hidden);
   32.90 -    SDL_free(device);
   32.91 +    if ((iscapture) && (index < inputDeviceCount)) {
   32.92 +        return inputDevices[index];
   32.93 +    } else if ((!iscapture) && (index < outputDeviceCount)) {
   32.94 +        return outputDevices[index];
   32.95 +    }
   32.96 +
   32.97 +    SDL_SetError("No such device");
   32.98 +    return NULL;
   32.99  }
  32.100  
  32.101 -static SDL_AudioDevice *
  32.102 -Audio_CreateDevice(int devindex)
  32.103 -{
  32.104 -    SDL_AudioDevice *this;
  32.105 -
  32.106 -    /* Initialize all variables that we clean on shutdown */
  32.107 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
  32.108 -    if (this) {
  32.109 -        SDL_memset(this, 0, (sizeof *this));
  32.110 -        this->hidden = (struct SDL_PrivateAudioData *)
  32.111 -            SDL_malloc((sizeof *this->hidden));
  32.112 -    }
  32.113 -    if ((this == NULL) || (this->hidden == NULL)) {
  32.114 -        SDL_OutOfMemory();
  32.115 -        if (this) {
  32.116 -            SDL_free(this);
  32.117 -        }
  32.118 -        return (0);
  32.119 -    }
  32.120 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  32.121 -    audio_fd = -1;
  32.122 -
  32.123 -    /* Set the function pointers */
  32.124 -    this->OpenAudio = DSP_OpenAudio;
  32.125 -    this->WaitAudio = DSP_WaitAudio;
  32.126 -    this->PlayAudio = DSP_PlayAudio;
  32.127 -    this->GetAudioBuf = DSP_GetAudioBuf;
  32.128 -    this->CloseAudio = DSP_CloseAudio;
  32.129 -
  32.130 -    this->free = Audio_DeleteDevice;
  32.131 -
  32.132 -    return this;
  32.133 -}
  32.134 -
  32.135 -AudioBootStrap DSP_bootstrap = {
  32.136 -    DSP_DRIVER_NAME, "OSS /dev/dsp standard audio",
  32.137 -    Audio_Available, Audio_CreateDevice
  32.138 -};
  32.139 -
  32.140 -/* This function waits until it is possible to write a full sound buffer */
  32.141 -static void
  32.142 -DSP_WaitAudio(_THIS)
  32.143 -{
  32.144 -    /* Not needed at all since OSS handles waiting automagically */
  32.145 -}
  32.146  
  32.147  static void
  32.148 -DSP_PlayAudio(_THIS)
  32.149 +DSP_CloseDevice(_THIS)
  32.150  {
  32.151 -    if (write(audio_fd, mixbuf, mixlen) == -1) {
  32.152 -        perror("Audio write");
  32.153 -        this->enabled = 0;
  32.154 -    }
  32.155 -#ifdef DEBUG_AUDIO
  32.156 -    fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen);
  32.157 -#endif
  32.158 -}
  32.159 -
  32.160 -static Uint8 *
  32.161 -DSP_GetAudioBuf(_THIS)
  32.162 -{
  32.163 -    return (mixbuf);
  32.164 -}
  32.165 -
  32.166 -static void
  32.167 -DSP_CloseAudio(_THIS)
  32.168 -{
  32.169 -    if (mixbuf != NULL) {
  32.170 -        SDL_FreeAudioMem(mixbuf);
  32.171 -        mixbuf = NULL;
  32.172 -    }
  32.173 -    if (audio_fd >= 0) {
  32.174 -        close(audio_fd);
  32.175 -        audio_fd = -1;
  32.176 +    if (this->hidden != NULL) {
  32.177 +        if (this->hidden->mixbuf != NULL) {
  32.178 +            SDL_FreeAudioMem(this->hidden->mixbuf);
  32.179 +            this->hidden->mixbuf = NULL;
  32.180 +        }
  32.181 +        if (this->hidden->audio_fd >= 0) {
  32.182 +            close(this->hidden->audio_fd);
  32.183 +            this->hidden->audio_fd = -1;
  32.184 +        }
  32.185 +        SDL_free(this->hidden);
  32.186 +        this->hidden = NULL;
  32.187      }
  32.188  }
  32.189  
  32.190 +
  32.191  static int
  32.192 -DSP_OpenAudio(_THIS, SDL_AudioSpec * spec)
  32.193 +DSP_OpenDevice(_THIS, const char *devname, int iscapture)
  32.194  {
  32.195 -    char audiodev[1024];
  32.196 +    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
  32.197      int format;
  32.198      int value;
  32.199      int frag_spec;
  32.200      SDL_AudioFormat test_format;
  32.201  
  32.202 +    /* We don't care what the devname is...we'll try to open anything. */
  32.203 +    /*  ...but default to first name in the list... */
  32.204 +    if (devname == NULL) {
  32.205 +        if ( ((iscapture) && (inputDeviceCount == 0)) ||
  32.206 +             ((!iscapture) && (outputDeviceCount == 0)) ) {
  32.207 +            SDL_SetError("No such audio device");
  32.208 +            return 0;
  32.209 +        }
  32.210 +        devname = ((iscapture) ? inputDevices[0] : outputDevices[0]);
  32.211 +    }
  32.212 +
  32.213 +    /* Initialize all variables that we clean on shutdown */
  32.214 +    this->hidden = (struct SDL_PrivateAudioData *)
  32.215 +                        SDL_malloc((sizeof *this->hidden));
  32.216 +    if (this->hidden == NULL) {
  32.217 +        SDL_OutOfMemory();
  32.218 +        return 0;
  32.219 +    }
  32.220 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  32.221 +
  32.222      /* Open the audio device */
  32.223 -    audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
  32.224 -    if (audio_fd < 0) {
  32.225 -        SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
  32.226 -        return (-1);
  32.227 +    this->hidden->audio_fd = open(devname, flags, 0);
  32.228 +    if (this->hidden->audio_fd < 0) {
  32.229 +        DSP_CloseDevice(this);
  32.230 +        SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
  32.231 +        return 0;
  32.232      }
  32.233 -    mixbuf = NULL;
  32.234 +    this->hidden->mixbuf = NULL;
  32.235  
  32.236      /* Make the file descriptor use blocking writes with fcntl() */
  32.237      {
  32.238 -        long flags;
  32.239 -        flags = fcntl(audio_fd, F_GETFL);
  32.240 -        flags &= ~O_NONBLOCK;
  32.241 -        if (fcntl(audio_fd, F_SETFL, flags) < 0) {
  32.242 +        long ctlflags;
  32.243 +        ctlflags = fcntl(this->hidden->audio_fd, F_GETFL);
  32.244 +        ctlflags &= ~O_NONBLOCK;
  32.245 +        if (fcntl(this->hidden->audio_fd, F_SETFL, ctlflags) < 0) {
  32.246 +            DSP_CloseDevice(this);
  32.247              SDL_SetError("Couldn't set audio blocking mode");
  32.248 -            DSP_CloseAudio(this);
  32.249 -            return (-1);
  32.250 +            return 0;
  32.251          }
  32.252      }
  32.253  
  32.254      /* Get a list of supported hardware formats */
  32.255 -    if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
  32.256 +    if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
  32.257          perror("SNDCTL_DSP_GETFMTS");
  32.258 +        DSP_CloseDevice(this);
  32.259          SDL_SetError("Couldn't get audio format list");
  32.260 -        DSP_CloseAudio(this);
  32.261 -        return (-1);
  32.262 +        return 0;
  32.263      }
  32.264  
  32.265      /* Try for a closest match on audio format */
  32.266      format = 0;
  32.267 -    for (test_format = SDL_FirstAudioFormat(spec->format);
  32.268 +    for (test_format = SDL_FirstAudioFormat(this->spec.format);
  32.269           !format && test_format;) {
  32.270  #ifdef DEBUG_AUDIO
  32.271          fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
  32.272 @@ -255,50 +257,51 @@
  32.273          }
  32.274      }
  32.275      if (format == 0) {
  32.276 +        DSP_CloseDevice(this);
  32.277          SDL_SetError("Couldn't find any hardware audio formats");
  32.278 -        DSP_CloseAudio(this);
  32.279 -        return (-1);
  32.280 +        return 0;
  32.281      }
  32.282 -    spec->format = test_format;
  32.283 +    this->spec.format = test_format;
  32.284  
  32.285      /* Set the audio format */
  32.286      value = format;
  32.287 -    if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
  32.288 +    if ( (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) ||
  32.289 +         (value != format) ) {
  32.290          perror("SNDCTL_DSP_SETFMT");
  32.291 +        DSP_CloseDevice(this);
  32.292          SDL_SetError("Couldn't set audio format");
  32.293 -        DSP_CloseAudio(this);
  32.294 -        return (-1);
  32.295 +        return 0;
  32.296      }
  32.297  
  32.298      /* Set the number of channels of output */
  32.299 -    value = spec->channels;
  32.300 -    if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0) {
  32.301 +    value = this->spec.channels;
  32.302 +    if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0) {
  32.303          perror("SNDCTL_DSP_CHANNELS");
  32.304 +        DSP_CloseDevice(this);
  32.305          SDL_SetError("Cannot set the number of channels");
  32.306 -        DSP_CloseAudio(this);
  32.307 -        return (-1);
  32.308 +        return 0;
  32.309      }
  32.310 -    spec->channels = value;
  32.311 +    this->spec.channels = value;
  32.312  
  32.313      /* Set the DSP frequency */
  32.314 -    value = spec->freq;
  32.315 -    if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
  32.316 +    value = this->spec.freq;
  32.317 +    if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
  32.318          perror("SNDCTL_DSP_SPEED");
  32.319 +        DSP_CloseDevice(this);
  32.320          SDL_SetError("Couldn't set audio frequency");
  32.321 -        DSP_CloseAudio(this);
  32.322 -        return (-1);
  32.323 +        return 0;
  32.324      }
  32.325 -    spec->freq = value;
  32.326 +    this->spec.freq = value;
  32.327  
  32.328      /* Calculate the final parameters for this audio specification */
  32.329 -    SDL_CalculateAudioSpec(spec);
  32.330 +    SDL_CalculateAudioSpec(&this->spec);
  32.331  
  32.332      /* Determine the power of two of the fragment size */
  32.333 -    for (frag_spec = 0; (0x01U << frag_spec) < spec->size; ++frag_spec);
  32.334 -    if ((0x01U << frag_spec) != spec->size) {
  32.335 +    for (frag_spec = 0; (0x01U << frag_spec) < this->spec.size; ++frag_spec);
  32.336 +    if ((0x01U << frag_spec) != this->spec.size) {
  32.337 +        DSP_CloseDevice(this);
  32.338          SDL_SetError("Fragment size must be a power of two");
  32.339 -        DSP_CloseAudio(this);
  32.340 -        return (-1);
  32.341 +        return 0;
  32.342      }
  32.343      frag_spec |= 0x00020000;    /* two fragments, for low latency */
  32.344  
  32.345 @@ -307,13 +310,13 @@
  32.346      fprintf(stderr, "Requesting %d fragments of size %d\n",
  32.347              (frag_spec >> 16), 1 << (frag_spec & 0xFFFF));
  32.348  #endif
  32.349 -    if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) {
  32.350 +    if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) {
  32.351          perror("SNDCTL_DSP_SETFRAGMENT");
  32.352      }
  32.353  #ifdef DEBUG_AUDIO
  32.354      {
  32.355          audio_buf_info info;
  32.356 -        ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info);
  32.357 +        ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETOSPACE, &info);
  32.358          fprintf(stderr, "fragments = %d\n", info.fragments);
  32.359          fprintf(stderr, "fragstotal = %d\n", info.fragstotal);
  32.360          fprintf(stderr, "fragsize = %d\n", info.fragsize);
  32.361 @@ -322,19 +325,59 @@
  32.362  #endif
  32.363  
  32.364      /* Allocate mixing buffer */
  32.365 -    mixlen = spec->size;
  32.366 -    mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen);
  32.367 -    if (mixbuf == NULL) {
  32.368 -        DSP_CloseAudio(this);
  32.369 -        return (-1);
  32.370 +    this->hidden->mixlen = this->spec.size;
  32.371 +    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
  32.372 +    if (this->hidden->mixbuf == NULL) {
  32.373 +        DSP_CloseDevice(this);
  32.374 +        SDL_OutOfMemory();
  32.375 +        return 0;
  32.376      }
  32.377 -    SDL_memset(mixbuf, spec->silence, spec->size);
  32.378 -
  32.379 -    /* Get the parent process id (we're the parent of the audio thread) */
  32.380 -    parent = getpid();
  32.381 +    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
  32.382  
  32.383      /* We're ready to rock and roll. :-) */
  32.384 -    return (0);
  32.385 +    return 1;
  32.386  }
  32.387  
  32.388 +
  32.389 +static void
  32.390 +DSP_PlayDevice(_THIS)
  32.391 +{
  32.392 +    const Uint8 *mixbuf = this->hidden->mixbuf;
  32.393 +    const int mixlen = this->hidden->mixlen;
  32.394 +    if (write(this->hidden->audio_fd, mixbuf, mixlen) == -1) {
  32.395 +        perror("Audio write");
  32.396 +        this->enabled = 0;
  32.397 +    }
  32.398 +#ifdef DEBUG_AUDIO
  32.399 +    fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen);
  32.400 +#endif
  32.401 +}
  32.402 +
  32.403 +static Uint8 *
  32.404 +DSP_GetDeviceBuf(_THIS)
  32.405 +{
  32.406 +    return (this->hidden->mixbuf);
  32.407 +}
  32.408 +
  32.409 +static int
  32.410 +DSP_Init(SDL_AudioDriverImpl *impl)
  32.411 +{
  32.412 +    /* Set the function pointers */
  32.413 +    impl->DetectDevices = DSP_DetectDevices;
  32.414 +    impl->GetDeviceName = DSP_GetDeviceName;
  32.415 +    impl->OpenDevice = DSP_OpenDevice;
  32.416 +    impl->PlayDevice = DSP_PlayDevice;
  32.417 +    impl->GetDeviceBuf = DSP_GetDeviceBuf;
  32.418 +    impl->CloseDevice = DSP_CloseDevice;
  32.419 +    impl->Deinitialize = DSP_Deinitialize;
  32.420 +
  32.421 +    build_device_lists();
  32.422 +    return 1;
  32.423 +}
  32.424 +
  32.425 +
  32.426 +AudioBootStrap DSP_bootstrap = {
  32.427 +    DSP_DRIVER_NAME, "OSS /dev/dsp standard audio", DSP_Init, 0
  32.428 +};
  32.429 +
  32.430  /* vi: set ts=4 sw=4 expandtab: */
    33.1 --- a/src/audio/dsp/SDL_dspaudio.h	Sun Oct 01 16:10:41 2006 +0000
    33.2 +++ b/src/audio/dsp/SDL_dspaudio.h	Tue Oct 17 09:15:21 2006 +0000
    33.3 @@ -26,7 +26,7 @@
    33.4  
    33.5  #include "../SDL_sysaudio.h"
    33.6  
    33.7 -/* Hidden "this" pointer for the video functions */
    33.8 +/* Hidden "this" pointer for the audio functions */
    33.9  #define _THIS	SDL_AudioDevice *this
   33.10  
   33.11  struct SDL_PrivateAudioData
   33.12 @@ -34,22 +34,11 @@
   33.13      /* The file descriptor for the audio device */
   33.14      int audio_fd;
   33.15  
   33.16 -    /* The parent process id, to detect when application quits */
   33.17 -    pid_t parent;
   33.18 -
   33.19      /* Raw mixing buffer */
   33.20      Uint8 *mixbuf;
   33.21      int mixlen;
   33.22  };
   33.23  #define FUDGE_TICKS	10      /* The scheduler overhead ticks per frame */
   33.24  
   33.25 -/* Old variable names */
   33.26 -#define audio_fd		(this->hidden->audio_fd)
   33.27 -#define parent			(this->hidden->parent)
   33.28 -#define mixbuf			(this->hidden->mixbuf)
   33.29 -#define mixlen			(this->hidden->mixlen)
   33.30 -#define frame_ticks		(this->hidden->frame_ticks)
   33.31 -#define next_frame		(this->hidden->next_frame)
   33.32 -
   33.33  #endif /* _SDL_dspaudio_h */
   33.34  /* vi: set ts=4 sw=4 expandtab: */
    34.1 --- a/src/audio/dummy/SDL_dummyaudio.c	Sun Oct 01 16:10:41 2006 +0000
    34.2 +++ b/src/audio/dummy/SDL_dummyaudio.c	Tue Oct 17 09:15:21 2006 +0000
    34.3 @@ -25,141 +25,27 @@
    34.4  
    34.5  /* Output audio to nowhere... */
    34.6  
    34.7 -#include "SDL_rwops.h"
    34.8 -#include "SDL_timer.h"
    34.9  #include "SDL_audio.h"
   34.10 -#include "../SDL_audiomem.h"
   34.11  #include "../SDL_audio_c.h"
   34.12 -#include "../SDL_audiodev_c.h"
   34.13  #include "SDL_dummyaudio.h"
   34.14  
   34.15 -/* The tag name used by DUMMY audio */
   34.16 -#define DUMMYAUD_DRIVER_NAME         "dummy"
   34.17 -
   34.18 -/* Audio driver functions */
   34.19 -static int DUMMYAUD_OpenAudio(_THIS, SDL_AudioSpec * spec);
   34.20 -static void DUMMYAUD_WaitAudio(_THIS);
   34.21 -static void DUMMYAUD_PlayAudio(_THIS);
   34.22 -static Uint8 *DUMMYAUD_GetAudioBuf(_THIS);
   34.23 -static void DUMMYAUD_CloseAudio(_THIS);
   34.24 -
   34.25 -/* Audio driver bootstrap functions */
   34.26  static int
   34.27 -DUMMYAUD_Available(void)
   34.28 +DUMMYAUD_OpenDevice(_THIS, const char *devname, int iscapture)
   34.29  {
   34.30 -    const char *envr = SDL_getenv("SDL_AUDIODRIVER");
   34.31 -    if (envr && (SDL_strcmp(envr, DUMMYAUD_DRIVER_NAME) == 0)) {
   34.32 -        return (1);
   34.33 -    }
   34.34 -    return (0);
   34.35 +    return 1;   /* always succeeds. */
   34.36  }
   34.37  
   34.38 -static void
   34.39 -DUMMYAUD_DeleteDevice(SDL_AudioDevice * device)
   34.40 +static int
   34.41 +DUMMYAUD_Init(SDL_AudioDriverImpl *impl)
   34.42  {
   34.43 -    SDL_free(device->hidden);
   34.44 -    SDL_free(device);
   34.45 -}
   34.46 -
   34.47 -static SDL_AudioDevice *
   34.48 -DUMMYAUD_CreateDevice(int devindex)
   34.49 -{
   34.50 -    SDL_AudioDevice *this;
   34.51 -
   34.52 -    /* Initialize all variables that we clean on shutdown */
   34.53 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
   34.54 -    if (this) {
   34.55 -        SDL_memset(this, 0, (sizeof *this));
   34.56 -        this->hidden = (struct SDL_PrivateAudioData *)
   34.57 -            SDL_malloc((sizeof *this->hidden));
   34.58 -    }
   34.59 -    if ((this == NULL) || (this->hidden == NULL)) {
   34.60 -        SDL_OutOfMemory();
   34.61 -        if (this) {
   34.62 -            SDL_free(this);
   34.63 -        }
   34.64 -        return (0);
   34.65 -    }
   34.66 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   34.67 -
   34.68      /* Set the function pointers */
   34.69 -    this->OpenAudio = DUMMYAUD_OpenAudio;
   34.70 -    this->WaitAudio = DUMMYAUD_WaitAudio;
   34.71 -    this->PlayAudio = DUMMYAUD_PlayAudio;
   34.72 -    this->GetAudioBuf = DUMMYAUD_GetAudioBuf;
   34.73 -    this->CloseAudio = DUMMYAUD_CloseAudio;
   34.74 -
   34.75 -    this->free = DUMMYAUD_DeleteDevice;
   34.76 -
   34.77 -    return this;
   34.78 +    impl->OpenDevice = DUMMYAUD_OpenDevice;
   34.79 +    impl->OnlyHasDefaultOutputDevice = 1;
   34.80 +    return 1;
   34.81  }
   34.82  
   34.83  AudioBootStrap DUMMYAUD_bootstrap = {
   34.84 -    DUMMYAUD_DRIVER_NAME, "SDL dummy audio driver",
   34.85 -    DUMMYAUD_Available, DUMMYAUD_CreateDevice
   34.86 +    "dummy", "SDL dummy audio driver", DUMMYAUD_Init, 1
   34.87  };
   34.88  
   34.89 -/* This function waits until it is possible to write a full sound buffer */
   34.90 -static void
   34.91 -DUMMYAUD_WaitAudio(_THIS)
   34.92 -{
   34.93 -    /* Don't block on first calls to simulate initial fragment filling. */
   34.94 -    if (this->hidden->initial_calls)
   34.95 -        this->hidden->initial_calls--;
   34.96 -    else
   34.97 -        SDL_Delay(this->hidden->write_delay);
   34.98 -}
   34.99 -
  34.100 -static void
  34.101 -DUMMYAUD_PlayAudio(_THIS)
  34.102 -{
  34.103 -    /* no-op...this is a null driver. */
  34.104 -}
  34.105 -
  34.106 -static Uint8 *
  34.107 -DUMMYAUD_GetAudioBuf(_THIS)
  34.108 -{
  34.109 -    return (this->hidden->mixbuf);
  34.110 -}
  34.111 -
  34.112 -static void
  34.113 -DUMMYAUD_CloseAudio(_THIS)
  34.114 -{
  34.115 -    if (this->hidden->mixbuf != NULL) {
  34.116 -        SDL_FreeAudioMem(this->hidden->mixbuf);
  34.117 -        this->hidden->mixbuf = NULL;
  34.118 -    }
  34.119 -}
  34.120 -
  34.121 -static int
  34.122 -DUMMYAUD_OpenAudio(_THIS, SDL_AudioSpec * spec)
  34.123 -{
  34.124 -    float bytes_per_sec = 0.0f;
  34.125 -
  34.126 -    /* Allocate mixing buffer */
  34.127 -    this->hidden->mixlen = spec->size;
  34.128 -    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
  34.129 -    if (this->hidden->mixbuf == NULL) {
  34.130 -        return (-1);
  34.131 -    }
  34.132 -    SDL_memset(this->hidden->mixbuf, spec->silence, spec->size);
  34.133 -
  34.134 -    bytes_per_sec = (float) (((spec->format & 0xFF) / 8) *
  34.135 -                             spec->channels * spec->freq);
  34.136 -
  34.137 -    /*
  34.138 -     * We try to make this request more audio at the correct rate for
  34.139 -     *  a given audio spec, so timing stays fairly faithful.
  34.140 -     * Also, we have it not block at all for the first two calls, so
  34.141 -     *  it seems like we're filling two audio fragments right out of the
  34.142 -     *  gate, like other SDL drivers tend to do.
  34.143 -     */
  34.144 -    this->hidden->initial_calls = 2;
  34.145 -    this->hidden->write_delay =
  34.146 -        (Uint32) ((((float) spec->size) / bytes_per_sec) * 1000.0f);
  34.147 -
  34.148 -    /* We're ready to rock and roll. :-) */
  34.149 -    return (0);
  34.150 -}
  34.151 -
  34.152  /* vi: set ts=4 sw=4 expandtab: */
    35.1 --- a/src/audio/dummy/SDL_dummyaudio.h	Sun Oct 01 16:10:41 2006 +0000
    35.2 +++ b/src/audio/dummy/SDL_dummyaudio.h	Tue Oct 17 09:15:21 2006 +0000
    35.3 @@ -26,7 +26,7 @@
    35.4  
    35.5  #include "../SDL_sysaudio.h"
    35.6  
    35.7 -/* Hidden "this" pointer for the video functions */
    35.8 +/* Hidden "this" pointer for the audio functions */
    35.9  #define _THIS	SDL_AudioDevice *this
   35.10  
   35.11  struct SDL_PrivateAudioData
    36.1 --- a/src/audio/esd/SDL_esdaudio.c	Sun Oct 01 16:10:41 2006 +0000
    36.2 +++ b/src/audio/esd/SDL_esdaudio.c	Tue Oct 17 09:15:21 2006 +0000
    36.3 @@ -33,7 +33,6 @@
    36.4  #include "SDL_audio.h"
    36.5  #include "../SDL_audiomem.h"
    36.6  #include "../SDL_audio_c.h"
    36.7 -#include "../SDL_audiodev_c.h"
    36.8  #include "SDL_esdaudio.h"
    36.9  
   36.10  #ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC
   36.11 @@ -46,40 +45,34 @@
   36.12  /* The tag name used by ESD audio */
   36.13  #define ESD_DRIVER_NAME		"esd"
   36.14  
   36.15 -/* Audio driver functions */
   36.16 -static int ESD_OpenAudio(_THIS, SDL_AudioSpec * spec);
   36.17 -static void ESD_WaitAudio(_THIS);
   36.18 -static void ESD_PlayAudio(_THIS);
   36.19 -static Uint8 *ESD_GetAudioBuf(_THIS);
   36.20 -static void ESD_CloseAudio(_THIS);
   36.21 -
   36.22  #ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC
   36.23  
   36.24  static const char *esd_library = SDL_AUDIO_DRIVER_ESD_DYNAMIC;
   36.25  static void *esd_handle = NULL;
   36.26 -static int esd_loaded = 0;
   36.27  
   36.28  static int (*SDL_NAME(esd_open_sound)) (const char *host);
   36.29  static int (*SDL_NAME(esd_close)) (int esd);
   36.30  static int (*SDL_NAME(esd_play_stream)) (esd_format_t format, int rate,
   36.31                                           const char *host, const char *name);
   36.32 +
   36.33 +#define SDL_ESD_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
   36.34  static struct
   36.35  {
   36.36      const char *name;
   36.37      void **func;
   36.38  } esd_functions[] = {
   36.39 -    {
   36.40 -    "esd_open_sound", (void **) &SDL_NAME(esd_open_sound)}, {
   36.41 -    "esd_close", (void **) &SDL_NAME(esd_close)}, {
   36.42 -"esd_play_stream", (void **) &SDL_NAME(esd_play_stream)},};
   36.43 +    SDL_ESD_SYM(esd_open_sound),
   36.44 +    SDL_ESD_SYM(esd_close),
   36.45 +    SDL_ESD_SYM(esd_play_stream),
   36.46 +};
   36.47 +#undef SDL_ESD_SYM
   36.48  
   36.49  static void
   36.50  UnloadESDLibrary()
   36.51  {
   36.52 -    if (esd_loaded) {
   36.53 +    if (esd_handle != NULL) {
   36.54          SDL_UnloadObject(esd_handle);
   36.55          esd_handle = NULL;
   36.56 -        esd_loaded = 0;
   36.57      }
   36.58  }
   36.59  
   36.60 @@ -88,17 +81,18 @@
   36.61  {
   36.62      int i, retval = -1;
   36.63  
   36.64 -    esd_handle = SDL_LoadObject(esd_library);
   36.65 -    if (esd_handle) {
   36.66 -        esd_loaded = 1;
   36.67 -        retval = 0;
   36.68 -        for (i = 0; i < SDL_arraysize(esd_functions); ++i) {
   36.69 -            *esd_functions[i].func =
   36.70 -                SDL_LoadFunction(esd_handle, esd_functions[i].name);
   36.71 -            if (!*esd_functions[i].func) {
   36.72 -                retval = -1;
   36.73 -                UnloadESDLibrary();
   36.74 -                break;
   36.75 +    if (esd_handle == NULL) {
   36.76 +        esd_handle = SDL_LoadObject(esd_library);
   36.77 +        if (esd_handle) {
   36.78 +            retval = 0;
   36.79 +            for (i = 0; i < SDL_arraysize(esd_functions); ++i) {
   36.80 +                *esd_functions[i].func =
   36.81 +                    SDL_LoadFunction(esd_handle, esd_functions[i].name);
   36.82 +                if (!*esd_functions[i].func) {
   36.83 +                    retval = -1;
   36.84 +                    UnloadESDLibrary();
   36.85 +                    break;
   36.86 +                }
   36.87              }
   36.88          }
   36.89      }
   36.90 @@ -121,78 +115,10 @@
   36.91  
   36.92  #endif /* SDL_AUDIO_DRIVER_ESD_DYNAMIC */
   36.93  
   36.94 -/* Audio driver bootstrap functions */
   36.95 -
   36.96 -static int
   36.97 -Audio_Available(void)
   36.98 -{
   36.99 -    int connection;
  36.100 -    int available;
  36.101 -
  36.102 -    available = 0;
  36.103 -    if (LoadESDLibrary() < 0) {
  36.104 -        return available;
  36.105 -    }
  36.106 -    connection = SDL_NAME(esd_open_sound) (NULL);
  36.107 -    if (connection >= 0) {
  36.108 -        available = 1;
  36.109 -        SDL_NAME(esd_close) (connection);
  36.110 -    }
  36.111 -    UnloadESDLibrary();
  36.112 -    return (available);
  36.113 -}
  36.114 -
  36.115 -static void
  36.116 -Audio_DeleteDevice(SDL_AudioDevice * device)
  36.117 -{
  36.118 -    SDL_free(device->hidden);
  36.119 -    SDL_free(device);
  36.120 -    UnloadESDLibrary();
  36.121 -}
  36.122 -
  36.123 -static SDL_AudioDevice *
  36.124 -Audio_CreateDevice(int devindex)
  36.125 -{
  36.126 -    SDL_AudioDevice *this;
  36.127 -
  36.128 -    /* Initialize all variables that we clean on shutdown */
  36.129 -    LoadESDLibrary();
  36.130 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
  36.131 -    if (this) {
  36.132 -        SDL_memset(this, 0, (sizeof *this));
  36.133 -        this->hidden = (struct SDL_PrivateAudioData *)
  36.134 -            SDL_malloc((sizeof *this->hidden));
  36.135 -    }
  36.136 -    if ((this == NULL) || (this->hidden == NULL)) {
  36.137 -        SDL_OutOfMemory();
  36.138 -        if (this) {
  36.139 -            SDL_free(this);
  36.140 -        }
  36.141 -        return (0);
  36.142 -    }
  36.143 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  36.144 -    audio_fd = -1;
  36.145 -
  36.146 -    /* Set the function pointers */
  36.147 -    this->OpenAudio = ESD_OpenAudio;
  36.148 -    this->WaitAudio = ESD_WaitAudio;
  36.149 -    this->PlayAudio = ESD_PlayAudio;
  36.150 -    this->GetAudioBuf = ESD_GetAudioBuf;
  36.151 -    this->CloseAudio = ESD_CloseAudio;
  36.152 -
  36.153 -    this->free = Audio_DeleteDevice;
  36.154 -
  36.155 -    return this;
  36.156 -}
  36.157 -
  36.158 -AudioBootStrap ESD_bootstrap = {
  36.159 -    ESD_DRIVER_NAME, "Enlightened Sound Daemon",
  36.160 -    Audio_Available, Audio_CreateDevice
  36.161 -};
  36.162  
  36.163  /* This function waits until it is possible to write a full sound buffer */
  36.164  static void
  36.165 -ESD_WaitAudio(_THIS)
  36.166 +ESD_WaitDevice(_THIS)
  36.167  {
  36.168      Sint32 ticks;
  36.169  
  36.170 @@ -202,28 +128,31 @@
  36.171          /* Note that this only works with thread implementations 
  36.172             that use a different process id for each thread.
  36.173           */
  36.174 -        if (parent && (((++cnt) % 10) == 0)) {  /* Check every 10 loops */
  36.175 -            if (kill(parent, 0) < 0) {
  36.176 +        /* Check every 10 loops */
  36.177 +        if (this->hidden->parent && (((++cnt) % 10) == 0)) {
  36.178 +            if (kill(this->hidden->parent, 0) < 0) {
  36.179                  this->enabled = 0;
  36.180              }
  36.181          }
  36.182      }
  36.183  
  36.184      /* Use timer for general audio synchronization */
  36.185 -    ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS;
  36.186 +    ticks = ((Sint32) (this->hidden->next_frame-SDL_GetTicks())) - FUDGE_TICKS;
  36.187      if (ticks > 0) {
  36.188          SDL_Delay(ticks);
  36.189      }
  36.190  }
  36.191  
  36.192  static void
  36.193 -ESD_PlayAudio(_THIS)
  36.194 +ESD_PlayDevice(_THIS)
  36.195  {
  36.196 -    int written;
  36.197 +    int written = 0;
  36.198  
  36.199      /* Write the audio data, checking for EAGAIN on broken audio drivers */
  36.200      do {
  36.201 -        written = write(audio_fd, mixbuf, mixlen);
  36.202 +        written = write(this->hidden->audio_fd,
  36.203 +                        this->hidden->mixbuf,
  36.204 +                        this->hidden->mixlen);
  36.205          if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) {
  36.206              SDL_Delay(1);       /* Let a little CPU time go by */
  36.207          }
  36.208 @@ -232,7 +161,7 @@
  36.209             ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)));
  36.210  
  36.211      /* Set the next write frame */
  36.212 -    next_frame += frame_ticks;
  36.213 +    this->hidden->next_frame += this->hidden->frame_ticks;
  36.214  
  36.215      /* If we couldn't write, assume fatal error for now */
  36.216      if (written < 0) {
  36.217 @@ -241,21 +170,26 @@
  36.218  }
  36.219  
  36.220  static Uint8 *
  36.221 -ESD_GetAudioBuf(_THIS)
  36.222 +ESD_GetDeviceBuf(_THIS)
  36.223  {
  36.224 -    return (mixbuf);
  36.225 +    return (this->hidden->mixbuf);
  36.226  }
  36.227  
  36.228  static void
  36.229 -ESD_CloseAudio(_THIS)
  36.230 +ESD_CloseDevice(_THIS)
  36.231  {
  36.232 -    if (mixbuf != NULL) {
  36.233 -        SDL_FreeAudioMem(mixbuf);
  36.234 -        mixbuf = NULL;
  36.235 -    }
  36.236 -    if (audio_fd >= 0) {
  36.237 -        SDL_NAME(esd_close) (audio_fd);
  36.238 -        audio_fd = -1;
  36.239 +    if (this->hidden != NULL) {
  36.240 +        if (this->hidden->mixbuf != NULL) {
  36.241 +            SDL_FreeAudioMem(this->hidden->mixbuf);
  36.242 +            this->hidden->mixbuf = NULL;
  36.243 +        }
  36.244 +        if (this->hidden->audio_fd >= 0) {
  36.245 +            SDL_NAME(esd_close) (this->hidden->audio_fd);
  36.246 +            this->hidden->audio_fd = -1;
  36.247 +        }
  36.248 +
  36.249 +        SDL_free(this->hidden);
  36.250 +        this->hidden = NULL;
  36.251      }
  36.252  }
  36.253  
  36.254 @@ -285,59 +219,135 @@
  36.255      return (progname);
  36.256  }
  36.257  
  36.258 +
  36.259  static int
  36.260 -ESD_OpenAudio(_THIS, SDL_AudioSpec * spec)
  36.261 +ESD_OpenDevice(_THIS, const char *devname, int iscapture)
  36.262  {
  36.263 -    esd_format_t format;
  36.264 +    esd_format_t format = (ESD_STREAM | ESD_PLAY);
  36.265 +    SDL_AudioFormat test_format = 0;
  36.266 +    int found = 0;
  36.267 +
  36.268 +    /* Initialize all variables that we clean on shutdown */
  36.269 +    this->hidden = (struct SDL_PrivateAudioData *)
  36.270 +                        SDL_malloc((sizeof *this->hidden));
  36.271 +    if (this->hidden == NULL) {
  36.272 +        SDL_OutOfMemory();
  36.273 +        return 0;
  36.274 +    }
  36.275 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  36.276 +    this->hidden->audio_fd = -1;
  36.277  
  36.278      /* Convert audio spec to the ESD audio format */
  36.279 -    format = (ESD_STREAM | ESD_PLAY);
  36.280 -    switch (spec->format & 0xFF) {
  36.281 -    case 8:
  36.282 -        format |= ESD_BITS8;
  36.283 -        break;
  36.284 -    case 16:
  36.285 -        format |= ESD_BITS16;
  36.286 -        break;
  36.287 -    default:
  36.288 -        SDL_SetError("Unsupported ESD audio format");
  36.289 -        return (-1);
  36.290 +    /* Try for a closest match on audio format */
  36.291 +    for (test_format = SDL_FirstAudioFormat(this->spec.format);
  36.292 +         !found && test_format; test_format = SDL_NextAudioFormat()) {
  36.293 +#ifdef DEBUG_AUDIO
  36.294 +        fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
  36.295 +#endif
  36.296 +        found = 1;
  36.297 +        switch (test_format) {
  36.298 +            case AUDIO_U8:
  36.299 +                format |= ESD_BITS8;
  36.300 +                break;
  36.301 +            case AUDIO_S16SYS:
  36.302 +                format |= ESD_BITS16;
  36.303 +                break;
  36.304 +            default:
  36.305 +                found = 0;
  36.306 +                break;
  36.307 +        }
  36.308      }
  36.309 -    if (spec->channels == 1) {
  36.310 +
  36.311 +    if (!found) {
  36.312 +        ESD_CloseDevice(this);
  36.313 +        SDL_SetError("Couldn't find any hardware audio formats");
  36.314 +        return 0;
  36.315 +    }
  36.316 +
  36.317 +    if (this->spec.channels == 1) {
  36.318          format |= ESD_MONO;
  36.319      } else {
  36.320          format |= ESD_STEREO;
  36.321      }
  36.322  #if 0
  36.323 -    spec->samples = ESD_BUF_SIZE;       /* Darn, no way to change this yet */
  36.324 +    this->spec.samples = ESD_BUF_SIZE;   /* Darn, no way to change this yet */
  36.325  #endif
  36.326  
  36.327      /* Open a connection to the ESD audio server */
  36.328 -    audio_fd =
  36.329 -        SDL_NAME(esd_play_stream) (format, spec->freq, NULL, get_progname());
  36.330 -    if (audio_fd < 0) {
  36.331 +    this->hidden->audio_fd =
  36.332 +        SDL_NAME(esd_play_stream)(format,this->spec.freq,NULL,get_progname());
  36.333 +
  36.334 +    if (this->hidden->audio_fd < 0) {
  36.335 +        ESD_CloseDevice(this);
  36.336          SDL_SetError("Couldn't open ESD connection");
  36.337 -        return (-1);
  36.338 +        return 0;
  36.339      }
  36.340  
  36.341      /* Calculate the final parameters for this audio specification */
  36.342 -    SDL_CalculateAudioSpec(spec);
  36.343 -    frame_ticks = (float) (spec->samples * 1000) / spec->freq;
  36.344 -    next_frame = SDL_GetTicks() + frame_ticks;
  36.345 +    SDL_CalculateAudioSpec(&this->spec);
  36.346 +    this->hidden->frame_ticks = (float) (this->spec.samples*1000) / this->spec.freq;
  36.347 +    this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks;
  36.348  
  36.349      /* Allocate mixing buffer */
  36.350 -    mixlen = spec->size;
  36.351 -    mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen);
  36.352 -    if (mixbuf == NULL) {
  36.353 -        return (-1);
  36.354 +    this->hidden->mixlen = this->spec.size;
  36.355 +    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
  36.356 +    if (this->hidden->mixbuf == NULL) {
  36.357 +        ESD_CloseDevice(this);
  36.358 +        SDL_OutOfMemory();
  36.359 +        return 0;
  36.360      }
  36.361 -    SDL_memset(mixbuf, spec->silence, spec->size);
  36.362 +    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
  36.363  
  36.364      /* Get the parent process id (we're the parent of the audio thread) */
  36.365 -    parent = getpid();
  36.366 +    this->hidden->parent = getpid();
  36.367  
  36.368      /* We're ready to rock and roll. :-) */
  36.369 -    return (0);
  36.370 +    return 1;
  36.371  }
  36.372  
  36.373 +static void
  36.374 +ESD_Deinitialize(void)
  36.375 +{
  36.376 +    UnloadESDLibrary();
  36.377 +}
  36.378 +
  36.379 +static int
  36.380 +ESD_Init(SDL_AudioDriverImpl *impl)
  36.381 +{
  36.382 +    if (LoadESDLibrary() < 0) {
  36.383 +        return 0;
  36.384 +    } else {
  36.385 +        int connection = 0;
  36.386 +
  36.387 +        /* Don't start ESD if it's not running */
  36.388 +        if (SDL_getenv("ESD_NO_SPAWN") == NULL) {
  36.389 +            SDL_putenv("ESD_NO_SPAWN=1");
  36.390 +        }
  36.391 +
  36.392 +        connection = SDL_NAME(esd_open_sound) (NULL);
  36.393 +        if (connection < 0) {
  36.394 +            UnloadESDLibrary();
  36.395 +            SDL_SetError("ESD: esd_open_sound failed (no audio server?)");
  36.396 +            return 0;
  36.397 +        }
  36.398 +        SDL_NAME(esd_close) (connection);
  36.399 +    }
  36.400 +
  36.401 +    /* Set the function pointers */
  36.402 +    impl->OpenDevice = ESD_OpenDevice;
  36.403 +    impl->PlayDevice = ESD_PlayDevice;
  36.404 +    impl->WaitDevice = ESD_WaitDevice;
  36.405 +    impl->GetDeviceBuf = ESD_GetDeviceBuf;
  36.406 +    impl->CloseDevice = ESD_CloseDevice;
  36.407 +    impl->Deinitialize = ESD_Deinitialize;
  36.408 +    impl->OnlyHasDefaultOutputDevice = 1;
  36.409 +
  36.410 +    return 1;
  36.411 +}
  36.412 +
  36.413 +
  36.414 +AudioBootStrap ESD_bootstrap = {
  36.415 +    ESD_DRIVER_NAME, "Enlightened Sound Daemon", ESD_Init, 0
  36.416 +};
  36.417 +
  36.418  /* vi: set ts=4 sw=4 expandtab: */
    37.1 --- a/src/audio/esd/SDL_esdaudio.h	Sun Oct 01 16:10:41 2006 +0000
    37.2 +++ b/src/audio/esd/SDL_esdaudio.h	Tue Oct 17 09:15:21 2006 +0000
    37.3 @@ -26,7 +26,7 @@
    37.4  
    37.5  #include "../SDL_sysaudio.h"
    37.6  
    37.7 -/* Hidden "this" pointer for the video functions */
    37.8 +/* Hidden "this" pointer for the audio functions */
    37.9  #define _THIS	SDL_AudioDevice *this
   37.10  
   37.11  struct SDL_PrivateAudioData
   37.12 @@ -47,13 +47,5 @@
   37.13  };
   37.14  #define FUDGE_TICKS	10      /* The scheduler overhead ticks per frame */
   37.15  
   37.16 -/* Old variable names */
   37.17 -#define audio_fd		(this->hidden->audio_fd)
   37.18 -#define parent			(this->hidden->parent)
   37.19 -#define mixbuf			(this->hidden->mixbuf)
   37.20 -#define mixlen			(this->hidden->mixlen)
   37.21 -#define frame_ticks		(this->hidden->frame_ticks)
   37.22 -#define next_frame		(this->hidden->next_frame)
   37.23 -
   37.24  #endif /* _SDL_esdaudio_h */
   37.25  /* vi: set ts=4 sw=4 expandtab: */
    38.1 --- a/src/audio/macosx/SDL_coreaudio.c	Sun Oct 01 16:10:41 2006 +0000
    38.2 +++ b/src/audio/macosx/SDL_coreaudio.c	Tue Oct 17 09:15:21 2006 +0000
    38.3 @@ -21,6 +21,7 @@
    38.4  */
    38.5  #include "SDL_config.h"
    38.6  
    38.7 +#include <CoreAudio/CoreAudio.h>
    38.8  #include <AudioUnit/AudioUnit.h>
    38.9  
   38.10  #include "SDL_audio.h"
   38.11 @@ -28,79 +29,233 @@
   38.12  #include "../SDL_sysaudio.h"
   38.13  #include "SDL_coreaudio.h"
   38.14  
   38.15 +#define DEBUG_COREAUDIO 0
   38.16  
   38.17 -/* Audio driver functions */
   38.18 +typedef struct COREAUDIO_DeviceList
   38.19 +{
   38.20 +    AudioDeviceID id;
   38.21 +    const char *name;
   38.22 +} COREAUDIO_DeviceList;
   38.23  
   38.24 -static int Core_OpenAudio(_THIS, SDL_AudioSpec * spec);
   38.25 -static void Core_WaitAudio(_THIS);
   38.26 -static void Core_PlayAudio(_THIS);
   38.27 -static Uint8 *Core_GetAudioBuf(_THIS);
   38.28 -static void Core_CloseAudio(_THIS);
   38.29 +static COREAUDIO_DeviceList *inputDevices = NULL;
   38.30 +static int inputDeviceCount = 0;
   38.31 +static COREAUDIO_DeviceList *outputDevices = NULL;
   38.32 +static int outputDeviceCount = 0;
   38.33  
   38.34 -/* Audio driver bootstrap functions */
   38.35 +static void
   38.36 +free_device_list(COREAUDIO_DeviceList **devices, int *devCount)
   38.37 +{
   38.38 +    if (*devices) {
   38.39 +        int i = *devCount;
   38.40 +        while (i--)
   38.41 +            SDL_free((void *) (*devices)[i].name);
   38.42 +        SDL_free(*devices);
   38.43 +        *devices = NULL;
   38.44 +    }
   38.45 +    *devCount = 0;
   38.46 +}
   38.47 +
   38.48 +
   38.49 +static void
   38.50 +build_device_list(int iscapture, COREAUDIO_DeviceList **devices, int *devCount)
   38.51 +{
   38.52 +    Boolean outWritable = 0;
   38.53 +    OSStatus result = noErr;
   38.54 +    UInt32 size = 0;
   38.55 +    AudioDeviceID *devs = NULL;
   38.56 +    UInt32 i = 0;
   38.57 +    UInt32 max = 0;
   38.58 +
   38.59 +    free_device_list(devices, devCount);
   38.60 +
   38.61 +    result = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,
   38.62 +                                         &size, &outWritable);
   38.63 +
   38.64 +    if (result != kAudioHardwareNoError)
   38.65 +        return;
   38.66 +
   38.67 +    devs = (AudioDeviceID *) alloca(size);
   38.68 +    if (devs == NULL)
   38.69 +        return;
   38.70 +
   38.71 +    max = size / sizeof (AudioDeviceID);
   38.72 +    *devices = (COREAUDIO_DeviceList *) SDL_malloc(max * sizeof (**devices));
   38.73 +    if (*devices == NULL)
   38.74 +        return;
   38.75 +
   38.76 +    result = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
   38.77 +                                     &size, devs);
   38.78 +    if (result != kAudioHardwareNoError)
   38.79 +        return;
   38.80 +
   38.81 +    for (i = 0; i < max; i++) {
   38.82 +        CFStringRef cfstr = NULL;
   38.83 +        char *ptr = NULL;
   38.84 +        AudioDeviceID dev = devs[i];
   38.85 +        AudioBufferList *buflist = NULL;
   38.86 +        int usable = 0;
   38.87 +        CFIndex len = 0;
   38.88 +
   38.89 +        result = AudioDeviceGetPropertyInfo(dev, 0, iscapture,
   38.90 +                                      kAudioDevicePropertyStreamConfiguration,
   38.91 +                                      &size, &outWritable);
   38.92 +        if (result != noErr)
   38.93 +            continue;
   38.94 +
   38.95 +        buflist = (AudioBufferList *) SDL_malloc(size);
   38.96 +        if (buflist == NULL)
   38.97 +            continue;
   38.98 +
   38.99 +        result = AudioDeviceGetProperty(dev, 0, iscapture,
  38.100 +                                      kAudioDevicePropertyStreamConfiguration,
  38.101 +                                      &size, buflist);
  38.102 +
  38.103 +        if (result == noErr) {
  38.104 +            UInt32 j;
  38.105 +            for (j = 0; j < buflist->mNumberBuffers; j++) {
  38.106 +                if (buflist->mBuffers[j].mNumberChannels > 0) {
  38.107 +                    usable = 1;
  38.108 +                    break;
  38.109 +                }
  38.110 +            }
  38.111 +        }
  38.112 +
  38.113 +        SDL_free(buflist);
  38.114 +
  38.115 +        if (!usable)
  38.116 +            continue;
  38.117 +
  38.118 +        size = sizeof (CFStringRef);
  38.119 +        result = AudioDeviceGetProperty(dev, 0, iscapture,
  38.120 +                                        kAudioObjectPropertyName,
  38.121 +                                        &size, &cfstr);
  38.122 +
  38.123 +        if (result != kAudioHardwareNoError)
  38.124 +            continue;
  38.125 +
  38.126 +        len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr),
  38.127 +                                                kCFStringEncodingUTF8);
  38.128 +
  38.129 +        ptr = (char *) SDL_malloc(len + 1);
  38.130 +        usable = ( (ptr != NULL) &&
  38.131 +                (CFStringGetCString(cfstr,ptr,len+1,kCFStringEncodingUTF8)) );
  38.132 +
  38.133 +        CFRelease(cfstr);
  38.134 +
  38.135 +        if (usable) {
  38.136 +            len = strlen(ptr);
  38.137 +            /* Some devices have whitespace at the end...trim it. */
  38.138 +            while ((len > 0) && (ptr[len-1] == ' ')) {
  38.139 +                len--;
  38.140 +            }
  38.141 +            usable = (len > 0);
  38.142 +        }
  38.143 +
  38.144 +        if (!usable) {
  38.145 +            SDL_free(ptr);
  38.146 +        } else {
  38.147 +            ptr[len] = '\0';
  38.148 +
  38.149 +            #if DEBUG_COREAUDIO
  38.150 +            printf("COREAUDIO: Found %s device #%d: '%s' (devid %d)\n",
  38.151 +                    ((iscapture) ? "capture" : "output"),
  38.152 +                    (int) *devCount, ptr, (int) dev);
  38.153 +            #endif
  38.154 +
  38.155 +            (*devices)[*devCount].id = dev;
  38.156 +            (*devices)[*devCount].name = ptr;
  38.157 +            (*devCount)++;
  38.158 +        }
  38.159 +    }
  38.160 +}
  38.161 +
  38.162 +static inline void
  38.163 +build_device_lists(void)
  38.164 +{
  38.165 +    build_device_list(0, &outputDevices, &outputDeviceCount);
  38.166 +    build_device_list(1, &inputDevices, &inputDeviceCount);
  38.167 +}
  38.168 +
  38.169 +
  38.170 +static inline void
  38.171 +free_device_lists(void)
  38.172 +{
  38.173 +    free_device_list(&outputDevices, &outputDeviceCount);
  38.174 +    free_device_list(&inputDevices, &inputDeviceCount);
  38.175 +}
  38.176 +
  38.177  
  38.178  static int
  38.179 -Audio_Available(void)
  38.180 +find_device_id(const char *devname, int iscapture, AudioDeviceID *id)
  38.181  {
  38.182 -    return (1);
  38.183 +    int i = ((iscapture) ? inputDeviceCount : outputDeviceCount);
  38.184 +    COREAUDIO_DeviceList *devs = ((iscapture) ? inputDevices : outputDevices);
  38.185 +    while (i--) {
  38.186 +        if (SDL_strcmp(devname, devs->name) == 0) {
  38.187 +            *id = devs->id;
  38.188 +            return 1;
  38.189 +        }
  38.190 +        devs++;
  38.191 +    }
  38.192 +
  38.193 +    return 0;
  38.194  }
  38.195  
  38.196 -static void
  38.197 -Audio_DeleteDevice(SDL_AudioDevice * device)
  38.198 +
  38.199 +static int
  38.200 +COREAUDIO_DetectDevices(int iscapture)
  38.201  {
  38.202 -    SDL_free(device->hidden);
  38.203 -    SDL_free(device);
  38.204 +    if (iscapture) {
  38.205 +        build_device_list(1, &inputDevices, &inputDeviceCount);
  38.206 +        return inputDeviceCount;
  38.207 +    } else {
  38.208 +        build_device_list(0, &outputDevices, &outputDeviceCount);
  38.209 +        return outputDeviceCount;
  38.210 +    }
  38.211 +
  38.212 +    return 0;  /* shouldn't ever hit this. */
  38.213  }
  38.214  
  38.215 -static SDL_AudioDevice *
  38.216 -Audio_CreateDevice(int devindex)
  38.217 +
  38.218 +static const char *
  38.219 +COREAUDIO_GetDeviceName(int index, int iscapture)
  38.220  {
  38.221 -    SDL_AudioDevice *this;
  38.222 +    if ((iscapture) && (index < inputDeviceCount)) {
  38.223 +        return inputDevices[index].name;
  38.224 +    } else if ((!iscapture) && (index < outputDeviceCount)) {
  38.225 +        return outputDevices[index].name;
  38.226 +    }
  38.227  
  38.228 -    /* Initialize all variables that we clean on shutdown */
  38.229 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
  38.230 -    if (this) {
  38.231 -        SDL_memset(this, 0, (sizeof *this));
  38.232 -        this->hidden = (struct SDL_PrivateAudioData *)
  38.233 -            SDL_malloc((sizeof *this->hidden));
  38.234 -    }
  38.235 -    if ((this == NULL) || (this->hidden == NULL)) {
  38.236 -        SDL_OutOfMemory();
  38.237 -        if (this) {
  38.238 -            SDL_free(this);
  38.239 -        }
  38.240 -        return (0);
  38.241 -    }
  38.242 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
  38.243 -
  38.244 -    /* Set the function pointers */
  38.245 -    this->OpenAudio = Core_OpenAudio;
  38.246 -    this->WaitAudio = Core_WaitAudio;
  38.247 -    this->PlayAudio = Core_PlayAudio;
  38.248 -    this->GetAudioBuf = Core_GetAudioBuf;
  38.249 -    this->CloseAudio = Core_CloseAudio;
  38.250 -
  38.251 -    this->free = Audio_DeleteDevice;
  38.252 -
  38.253 -    return this;
  38.254 +    SDL_SetError("No such device");
  38.255 +    return NULL;
  38.256  }
  38.257  
  38.258 -AudioBootStrap COREAUDIO_bootstrap = {
  38.259 -    "coreaudio", "Mac OS X CoreAudio",
  38.260 -    Audio_Available, Audio_CreateDevice
  38.261 -};
  38.262 +
  38.263 +static void
  38.264 +COREAUDIO_Deinitialize(void)
  38.265 +{
  38.266 +    free_device_lists();
  38.267 +}
  38.268 +
  38.269  
  38.270  /* The CoreAudio callback */
  38.271  static OSStatus
  38.272 -audioCallback(void *inRefCon,
  38.273 -              AudioUnitRenderActionFlags inActionFlags,
  38.274 +outputCallback(void *inRefCon,
  38.275 +              AudioUnitRenderActionFlags *ioActionFlags,
  38.276                const AudioTimeStamp * inTimeStamp,
  38.277 -              UInt32 inBusNumber, AudioBuffer * ioData)
  38.278 +              UInt32 inBusNumber, UInt32 inNumberFrames,
  38.279 +              AudioBufferList *ioDataList)
  38.280  {
  38.281      SDL_AudioDevice *this = (SDL_AudioDevice *) inRefCon;
  38.282 +    AudioBuffer *ioData = &ioDataList->mBuffers[0];
  38.283      UInt32 remaining, len;
  38.284      void *ptr;
  38.285  
  38.286 +    /* Is there ever more than one buffer, and what do you do with it? */
  38.287 +    if (ioDataList->mNumberBuffers != 1) {
  38.288 +        return noErr;
  38.289 +    }
  38.290 +
  38.291      /* Only do anything if audio is enabled and not paused */
  38.292      if (!this->enabled || this->paused) {
  38.293          SDL_memset(ioData->mData, this->spec.silence, ioData->mDataByteSize);
  38.294 @@ -118,109 +273,251 @@
  38.295      remaining = ioData->mDataByteSize;
  38.296      ptr = ioData->mData;
  38.297      while (remaining > 0) {
  38.298 -        if (bufferOffset >= bufferSize) {
  38.299 +        if (this->hidden->bufferOffset >= this->hidden->bufferSize) {
  38.300              /* Generate the data */
  38.301 -            SDL_memset(buffer, this->spec.silence, bufferSize);
  38.302 +            SDL_memset(this->hidden->buffer, this->spec.silence,
  38.303 +                       this->hidden->bufferSize);
  38.304              SDL_mutexP(this->mixer_lock);
  38.305 -            (*this->spec.callback) (this->spec.userdata, buffer, bufferSize);
  38.306 +            (*this->spec.callback) (this->spec.userdata, this->hidden->buffer,
  38.307 +                                    this->hidden->bufferSize);
  38.308              SDL_mutexV(this->mixer_lock);
  38.309 -            bufferOffset = 0;
  38.310 +            this->hidden->bufferOffset = 0;
  38.311          }
  38.312  
  38.313 -        len = bufferSize - bufferOffset;
  38.314 +        len = this->hidden->bufferSize - this->hidden->bufferOffset;
  38.315          if (len > remaining)
  38.316              len = remaining;
  38.317 -        SDL_memcpy(ptr, (char *) buffer + bufferOffset, len);
  38.318 +        SDL_memcpy(ptr,
  38.319 +                    (char *) this->hidden->buffer + this->hidden->bufferOffset,
  38.320 +                    len);
  38.321          ptr = (char *) ptr + len;
  38.322          remaining -= len;
  38.323 -        bufferOffset += len;
  38.324 +        this->hidden->bufferOffset += len;
  38.325      }
  38.326  
  38.327      return 0;
  38.328  }
  38.329  
  38.330 -/* Dummy functions -- we don't use thread-based audio */
  38.331 -void
  38.332 -Core_WaitAudio(_THIS)
  38.333 +static OSStatus
  38.334 +inputCallback(void *inRefCon,
  38.335 +              AudioUnitRenderActionFlags *ioActionFlags,
  38.336 +              const AudioTimeStamp * inTimeStamp,
  38.337 +              UInt32 inBusNumber, UInt32 inNumberFrames,
  38.338 +              AudioBufferList *ioData)
  38.339  {
  38.340 -    return;
  38.341 +    //err = AudioUnitRender(afr->fAudioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, afr->fAudioBuffer);
  38.342 +    // !!! FIXME: write me!
  38.343 +    return noErr;
  38.344  }
  38.345  
  38.346 -void
  38.347 -Core_PlayAudio(_THIS)
  38.348 +
  38.349 +static void
  38.350 +COREAUDIO_CloseDevice(_THIS)
  38.351  {
  38.352 -    return;
  38.353 +    if (this->hidden != NULL) {
  38.354 +        OSStatus result = noErr;
  38.355 +        AURenderCallbackStruct callback;
  38.356 +        const AudioUnitElement output_bus = 0;
  38.357 +        const AudioUnitElement input_bus = 1;
  38.358 +        const int iscapture = this->iscapture;
  38.359 +        const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus);
  38.360 +        const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output :
  38.361 +                                                    kAudioUnitScope_Input);
  38.362 +
  38.363 +        /* stop processing the audio unit */
  38.364 +        result = AudioOutputUnitStop(this->hidden->audioUnit);
  38.365 +
  38.366 +        /* Remove the input callback */
  38.367 +        SDL_memset(&callback, '\0', sizeof (AURenderCallbackStruct));
  38.368 +        result = AudioUnitSetProperty(this->hidden->audioUnit,
  38.369 +                                      kAudioUnitProperty_SetRenderCallback,
  38.370 +                                      scope, bus, &callback, sizeof (callback));
  38.371 +
  38.372 +        CloseComponent(this->hidden->audioUnit);
  38.373 +
  38.374 +        SDL_free(this->hidden->buffer);
  38.375 +        SDL_free(this->hidden);
  38.376 +        this->hidden = NULL;
  38.377 +    }
  38.378  }
  38.379  
  38.380 -Uint8 *
  38.381 -Core_GetAudioBuf(_THIS)
  38.382 -{
  38.383 -    return (NULL);
  38.384 -}
  38.385 -
  38.386 -void
  38.387 -Core_CloseAudio(_THIS)
  38.388 -{
  38.389 -    OSStatus result;
  38.390 -    struct AudioUnitInputCallback callback;
  38.391 -
  38.392 -    /* stop processing the audio unit */
  38.393 -    result = AudioOutputUnitStop(outputAudioUnit);
  38.394 -    if (result != noErr) {
  38.395 -        SDL_SetError("Core_CloseAudio: AudioOutputUnitStop");
  38.396 -        return;
  38.397 -    }
  38.398 -
  38.399 -    /* Remove the input callback */
  38.400 -    callback.inputProc = 0;
  38.401 -    callback.inputProcRefCon = 0;
  38.402 -    result = AudioUnitSetProperty(outputAudioUnit,
  38.403 -                                  kAudioUnitProperty_SetInputCallback,
  38.404 -                                  kAudioUnitScope_Input,
  38.405 -                                  0, &callback, sizeof(callback));
  38.406 -    if (result != noErr) {
  38.407 -        SDL_SetError
  38.408 -            ("Core_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)");
  38.409 -        return;
  38.410 -    }
  38.411 -
  38.412 -    result = CloseComponent(outputAudioUnit);
  38.413 -    if (result != noErr) {
  38.414 -        SDL_SetError("Core_CloseAudio: CloseComponent");
  38.415 -        return;
  38.416 -    }
  38.417 -
  38.418 -    SDL_free(buffer);
  38.419 -}
  38.420  
  38.421  #define CHECK_RESULT(msg) \
  38.422      if (result != noErr) { \
  38.423 +        COREAUDIO_CloseDevice(this); \
  38.424          SDL_SetError("CoreAudio error (%s): %d", msg, (int) result); \
  38.425 -        return -1; \
  38.426 +        return 0; \
  38.427      }
  38.428  
  38.429 +static int
  38.430 +find_device_by_name(_THIS, const char *devname, int iscapture)
  38.431 +{
  38.432 +    AudioDeviceID devid = 0;
  38.433 +    OSStatus result = noErr;
  38.434 +    UInt32 size = 0;
  38.435 +    UInt32 alive = 0;
  38.436 +    pid_t pid = 0;
  38.437  
  38.438 -int
  38.439 -Core_OpenAudio(_THIS, SDL_AudioSpec * spec)
  38.440 +    if (devname == NULL) {
  38.441 +        size = sizeof (AudioDeviceID);
  38.442 +        const AudioHardwarePropertyID propid =
  38.443 +                    ((iscapture) ? kAudioHardwarePropertyDefaultInputDevice :
  38.444 +                                   kAudioHardwarePropertyDefaultOutputDevice);
  38.445 +
  38.446 +        result = AudioHardwareGetProperty(propid, &size, &devid);
  38.447 +        CHECK_RESULT("AudioHardwareGetProperty (default device)");
  38.448 +    } else {
  38.449 +        if (!find_device_id(devname, iscapture, &devid)) {
  38.450 +            SDL_SetError("CoreAudio: No such audio device.");
  38.451 +            return 0;
  38.452 +        }
  38.453 +    }
  38.454 +
  38.455 +    size = sizeof (alive);
  38.456 +    result = AudioDeviceGetProperty(devid, 0, iscapture,
  38.457 +                                    kAudioDevicePropertyDeviceIsAlive,
  38.458 +                                    &size, &alive);
  38.459 +    CHECK_RESULT("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)");
  38.460 +
  38.461 +    if (!alive) {
  38.462 +        SDL_SetError("CoreAudio: requested device exists, but isn't alive.");
  38.463 +        return 0;
  38.464 +    }
  38.465 +
  38.466 +    size = sizeof (pid);
  38.467 +    result = AudioDeviceGetProperty(devid, 0, iscapture,
  38.468 +                                    kAudioDevicePropertyHogMode, &size, &pid);
  38.469 +
  38.470 +    /* some devices don't support this property, so errors are fine here. */
  38.471 +    if ((result == noErr) && (pid != -1)) {
  38.472 +        SDL