From bf035a46b4476e083d539009f63e993ed2d33403 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 17 Oct 2006 09:15:21 +0000 Subject: [PATCH] Merged SDL-ryan-multiple-audio-device branch r2803:2871 into the trunk. --- configure.in | 46 +- include/SDL_audio.h | 34 +- include/SDL_config.h.in | 5 +- include/SDL_thread.h | 2 +- src/SDL_error.c | 1 + src/audio/SDL_audio.c | 1006 +++++++++++++++----------- src/audio/SDL_audiocvt.c | 18 +- src/audio/SDL_audiodev.c | 162 ++--- src/audio/SDL_audiodev_c.h | 6 +- src/audio/SDL_mixer.c | 15 - src/audio/SDL_sysaudio.h | 135 +--- src/audio/alsa/SDL_alsa_audio.c | 643 +++++++--------- src/audio/alsa/SDL_alsa_audio.h | 8 +- src/audio/amigaos/SDL_ahiaudio.c | 360 --------- src/audio/amigaos/SDL_ahiaudio.h | 62 -- src/audio/arts/SDL_artsaudio.c | 315 ++++---- src/audio/arts/SDL_artsaudio.h | 10 +- src/audio/baudio/SDL_beaudio.cc | 261 +++---- src/audio/baudio/SDL_beaudio.h | 10 +- src/audio/bsd/SDL_bsdaudio.c | 417 ++++++----- src/audio/bsd/SDL_bsdaudio.h | 13 +- src/audio/dart/SDL_dart.c | 302 ++++---- src/audio/dart/SDL_dart.h | 8 +- src/audio/dc/SDL_dcaudio.c | 152 ++-- src/audio/dc/SDL_dcaudio.h | 2 +- src/audio/disk/SDL_diskaudio.c | 157 ++-- src/audio/disk/SDL_diskaudio.h | 2 +- src/audio/dma/SDL_dmaaudio.c | 475 ++++++------ src/audio/dma/SDL_dmaaudio.h | 10 +- src/audio/dmedia/SDL_irixaudio.c | 175 ++--- src/audio/dmedia/SDL_irixaudio.h | 15 +- src/audio/dsp/SDL_dspaudio.c | 303 ++++---- src/audio/dsp/SDL_dspaudio.h | 13 +- src/audio/dummy/SDL_dummyaudio.c | 130 +--- src/audio/dummy/SDL_dummyaudio.h | 2 +- src/audio/esd/SDL_esdaudio.c | 292 ++++---- src/audio/esd/SDL_esdaudio.h | 10 +- src/audio/macosx/SDL_coreaudio.c | 578 +++++++++++---- src/audio/macosx/SDL_coreaudio.h | 11 +- src/audio/macrom/SDL_romaudio.c | 322 ++------- src/audio/macrom/SDL_romaudio.h | 15 +- src/audio/mint/SDL_mintaudio_dma8.c | 269 +++---- src/audio/mint/SDL_mintaudio_gsxb.c | 303 ++++---- src/audio/mint/SDL_mintaudio_mcsn.c | 329 ++++----- src/audio/mint/SDL_mintaudio_stfa.c | 275 +++---- src/audio/mint/SDL_mintaudio_xbios.c | 291 ++++---- src/audio/mme/SDL_mmeaudio.c | 274 ++++--- src/audio/mme/SDL_mmeaudio.h | 13 +- src/audio/nas/SDL_nasaudio.c | 286 +++++--- src/audio/nas/SDL_nasaudio.h | 6 +- src/audio/nto/SDL_nto_audio.c | 371 ++++------ src/audio/nto/SDL_nto_audio.h | 16 - src/audio/paudio/SDL_paudio.c | 328 +++++---- src/audio/paudio/SDL_paudio.h | 13 +- src/audio/sun/SDL_sunaudio.c | 7 +- src/audio/sun/SDL_sunaudio.h | 9 +- src/audio/ums/SDL_umsaudio.c | 8 +- src/audio/ums/SDL_umsaudio.h | 2 +- src/audio/windib/SDL_dibaudio.c | 303 ++++---- src/audio/windib/SDL_dibaudio.h | 14 +- src/audio/windx5/SDL_dx5audio.c | 627 ++++++---------- src/audio/windx5/SDL_dx5audio.h | 23 +- src/events/SDL_mouse.c | 2 +- src/timer/os2/SDL_systimer.c | 42 +- src/video/SDL_rendercopy.h | 6 +- test/Makefile.in | 8 +- test/loopwave.c | 17 +- test/testaudioinfo.c | 53 ++ test/testmultiaudio.c | 136 ++++ 69 files changed, 4899 insertions(+), 5635 deletions(-) delete mode 100644 src/audio/amigaos/SDL_ahiaudio.c delete mode 100644 src/audio/amigaos/SDL_ahiaudio.h create mode 100644 test/testaudioinfo.c create mode 100644 test/testmultiaudio.c diff --git a/configure.in b/configure.in index 4fc57dfc8..fd9952b67 100644 --- a/configure.in +++ b/configure.in @@ -511,9 +511,17 @@ CheckNAS() AC_HELP_STRING([--enable-nas], [support the NAS audio API [[default=yes]]]), , enable_nas=yes) if test x$enable_audio = xyes -a x$enable_nas = xyes; then + AC_CHECK_HEADER(audio/audiolib.h, have_nas_hdr=yes) + AC_CHECK_LIB(audio, AuOpenServer, have_nas_lib=yes) + AC_MSG_CHECKING(for NAS audio support) have_nas=no - if test -r /usr/X11R6/include/audio/audiolib.h; then + + if test x$have_nas_hdr = xyes -a x$have_nas_lib = xyes; then + have_nas=yes + NAS_LIBS="-laudio" + + elif test -r /usr/X11R6/include/audio/audiolib.h; then have_nas=yes NAS_CFLAGS="-I/usr/X11R6/include/" NAS_LIBS="-L/usr/X11R6/lib -laudio -lXt" @@ -525,12 +533,40 @@ AC_HELP_STRING([--enable-nas], [support the NAS audio API [[default=yes]]]), have_nas=yes NAS_LIBS="-lnas -lXt" fi + AC_MSG_RESULT($have_nas) + if test x$have_nas = xyes; then + AC_ARG_ENABLE(nas-shared, +AC_HELP_STRING([--enable-nas-shared], [dynamically load NAS audio support [[default=yes]]]), + , enable_nas_shared=yes) + if test "x`echo $NAS_LIBS | grep -- -L`" = "x"; then + if test "x`ls /lib/libaudio.so.* 2> /dev/null`" != "x"; then + NAS_LIBS="-L/lib $NAS_LIBS" + elif test "x`ls /usr/lib/libaudio.so.* 2> /dev/null`" != "x"; then + NAS_LIBS="-L/usr/lib $NAS_LIBS" + elif test "x`ls /usr/local/lib/libaudio.so.* 2> /dev/null`" != "x"; then + NAS_LIBS="-L/usr/local/lib $NAS_LIBS" + fi + fi + nas_lib_spec=`echo $NAS_LIBS | sed 's/.*-L\([[^ ]]*\).*/\1\/libaudio.so.*/'` + nas_lib=`ls -- $nas_lib_spec | sed 's/.*\/\(.*\)/\1/; q'` + echo "-- $nas_lib_spec -> $nas_lib" + + if test x$have_loadso != xyes && \ + test x$enable_nas_shared = xyes; then + AC_MSG_WARN([You must have SDL_LoadObject() support for dynamic NAS loading]) + fi + if test x$have_loadso = xyes && \ + test x$enable_nas_shared = xyes && test x$alsa_lib != x; then + AC_DEFINE_UNQUOTED(SDL_AUDIO_DRIVER_NAS_DYNAMIC, "$nas_lib") + else + EXTRA_LDFLAGS="$EXTRA_LDFLAGS $NAS_LIBS" + fi + AC_DEFINE(SDL_AUDIO_DRIVER_NAS) SOURCES="$SOURCES $srcdir/src/audio/nas/*.c" EXTRA_CFLAGS="$EXTRA_CFLAGS $NAS_CFLAGS" - EXTRA_LDFLAGS="$EXTRA_LDFLAGS $NAS_LIBS" have_audio=yes fi fi @@ -2006,7 +2042,7 @@ case "$host" in have_audio=yes ;; aix) - AC_DEFINE(SDL_AUDIO_DRIVER_PAUD) + AC_DEFINE(SDL_AUDIO_DRIVER_PAUDIO) SOURCES="$SOURCES $srcdir/src/audio/paudio/*.c" have_audio=yes ;; @@ -2206,7 +2242,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau CheckBeGL # Set up files for the audio library if test x$enable_audio = xyes; then - AC_DEFINE(SDL_AUDIO_DRIVER_BAUDIO) + AC_DEFINE(SDL_AUDIO_DRIVER_BEOSAUDIO) SOURCES="$SOURCES $srcdir/src/audio/baudio/*.cc" have_audio=yes fi @@ -2323,7 +2359,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon" # If either the audio or CD driver is used, add the AudioUnit framework if test x$enable_audio = xyes -o x$enable_cdrom = xyes; then - EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit" + EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreAudio -framework,AudioToolbox -Wl,-framework,AudioUnit" fi ;; *-*-mint*) diff --git a/include/SDL_audio.h b/include/SDL_audio.h index a53cb3dd7..64c356111 100644 --- a/include/SDL_audio.h +++ b/include/SDL_audio.h @@ -153,7 +153,7 @@ typedef struct SDL_AudioCVT /* Function prototypes */ -/* These functions return the list of built in video drivers, in the +/* These functions return the list of built in audio drivers, in the * order that they are normally initialized by default. */ extern DECLSPEC int SDLCALL SDL_GetNumAudioDrivers(void); @@ -212,7 +212,7 @@ extern DECLSPEC const char *SDLCALL SDL_GetCurrentAudioDriver(void); * may modify the requested size of the audio buffer, you should allocate * any local mixing buffers after you open the audio device. */ -extern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired, +extern DECLSPEC int SDLCALL SDL_OpenAudio(const SDL_AudioSpec * desired, SDL_AudioSpec * obtained); /* @@ -228,6 +228,13 @@ typedef Uint32 SDL_AudioDeviceID; /* * Get the number of available devices exposed by the current driver. * Only valid after a successfully initializing the audio subsystem. + * Returns -1 if an explicit list of devices can't be determined; this is + * not an error. For example, if SDL is set up to talk to a remote audio + * server, it can't list every one available on the Internet, but it will + * still allow a specific host to be specified to SDL_OpenAudioDevice(). + * In many common cases, when this function returns a value <= 0, it can still + * successfully open the default device (NULL for first argument of + * SDL_OpenAudioDevice()). */ extern DECLSPEC int SDLCALL SDL_GetNumAudioDevices(int iscapture); @@ -235,15 +242,28 @@ extern DECLSPEC int SDLCALL SDL_GetNumAudioDevices(int iscapture); * Get the human-readable name of a specific audio device. * Must be a value between 0 and (number of audio devices-1). * Only valid after a successfully initializing the audio subsystem. + * The values returned by this function reflect the latest call to + * SDL_GetNumAudioDevices(); recall that function to redetect available + * hardware. + * + * The string returned by this function is UTF-8 encoded, read-only, and + * managed internally. You are not to free it. If you need to keep the + * string for any length of time, you should make your own copy of it, as it + * will be invalid next time any of several other SDL functions is called. */ -extern DECLSPEC const char *SDLCALL SDL_GetAudioDevice(int index, - int iscapture); +extern DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(int index, + int iscapture); /* - * Open a specific audio device. Passing in a device name of NULL is - * equivalent to SDL_OpenAudio(). Returns 0 on error, a valid device ID - * on success. + * Open a specific audio device. Passing in a device name of NULL requests + * the most reasonable default (and is equivalent to calling SDL_OpenAudio()). + * The device name is a UTF-8 string reported by SDL_GetAudioDevice(), but + * some drivers allow arbitrary and driver-specific strings, such as a + * hostname/IP address for a remote audio server, or a filename in the + * diskaudio driver. + * Returns 0 on error, a valid device ID that is >= 2 on success. + * SDL_OpenAudio(), unlike this function, always acts on device ID 1. */ extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(const char *device, diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index b636a3ff0..72b245523 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -154,7 +154,7 @@ #undef SDL_AUDIO_DRIVER_ALSA_DYNAMIC #undef SDL_AUDIO_DRIVER_ARTS #undef SDL_AUDIO_DRIVER_ARTS_DYNAMIC -#undef SDL_AUDIO_DRIVER_BAUDIO +#undef SDL_AUDIO_DRIVER_BEOSAUDIO #undef SDL_AUDIO_DRIVER_BSD #undef SDL_AUDIO_DRIVER_COREAUDIO #undef SDL_AUDIO_DRIVER_DART @@ -168,9 +168,10 @@ #undef SDL_AUDIO_DRIVER_MINT #undef SDL_AUDIO_DRIVER_MMEAUDIO #undef SDL_AUDIO_DRIVER_NAS +#undef SDL_AUDIO_DRIVER_NAS_DYNAMIC #undef SDL_AUDIO_DRIVER_OSS #undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H -#undef SDL_AUDIO_DRIVER_PAUD +#undef SDL_AUDIO_DRIVER_PAUDIO #undef SDL_AUDIO_DRIVER_QNXNTO #undef SDL_AUDIO_DRIVER_SNDMGR #undef SDL_AUDIO_DRIVER_SUNAUDIO diff --git a/include/SDL_thread.h b/include/SDL_thread.h index e0731b5e2..c89a7b533 100644 --- a/include/SDL_thread.h +++ b/include/SDL_thread.h @@ -91,7 +91,7 @@ typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned, typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code); #endif -extern DECLSPEC SDL_Thread *SDLCALL SDL_CreateThread(int (*fn) (void *), +extern DECLSPEC SDL_Thread *SDLCALL SDL_CreateThread(int (SDLCALL * f) (void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, diff --git a/src/SDL_error.c b/src/SDL_error.c index bb1b2555a..a447a125d 100644 --- a/src/SDL_error.c +++ b/src/SDL_error.c @@ -28,6 +28,7 @@ /* Routine to get the thread-specific error variable */ #if SDL_THREADS_DISABLED +/* !!! FIXME: what does this comment mean? Victim of Search and Replace? */ /* The SDL_arraysize(The ),default (non-thread-safe) global error variable */ static SDL_error SDL_global_error; #define SDL_GetErrBuf() (&SDL_global_error) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 20b9882ab..6d7217278 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -28,11 +28,48 @@ #include "SDL_audiomem.h" #include "SDL_sysaudio.h" -#ifdef __OS2__ -/* We'll need the DosSetPriority() API! */ -#define INCL_DOSPROCESS -#include -#endif +#define _THIS SDL_AudioDevice *this + +static SDL_AudioDriver current_audio; +static SDL_AudioDevice *open_devices[16]; + +/* !!! FIXME: These are wordy and unlocalized... */ +#define DEFAULT_OUTPUT_DEVNAME "System audio output device" +#define DEFAULT_INPUT_DEVNAME "System audio capture device" + + +/* + * Not all of these will be compiled and linked in, but it's convenient + * to have a complete list here and saves yet-another block of #ifdefs... + * Please see bootstrap[], below, for the actual #ifdef mess. + */ +extern AudioBootStrap BSD_AUDIO_bootstrap; +extern AudioBootStrap DSP_bootstrap; +extern AudioBootStrap DMA_bootstrap; +extern AudioBootStrap ALSA_bootstrap; +extern AudioBootStrap QNXNTOAUDIO_bootstrap; +extern AudioBootStrap SUNAUDIO_bootstrap; +extern AudioBootStrap DMEDIA_bootstrap; +extern AudioBootStrap ARTS_bootstrap; +extern AudioBootStrap ESD_bootstrap; +extern AudioBootStrap NAS_bootstrap; +extern AudioBootStrap DSOUND_bootstrap; +extern AudioBootStrap WAVEOUT_bootstrap; +extern AudioBootStrap PAUDIO_bootstrap; +extern AudioBootStrap BEOSAUDIO_bootstrap; +extern AudioBootStrap COREAUDIO_bootstrap; +extern AudioBootStrap SNDMGR_bootstrap; +extern AudioBootStrap MINTAUDIO_GSXB_bootstrap; +extern AudioBootStrap MINTAUDIO_MCSN_bootstrap; +extern AudioBootStrap MINTAUDIO_STFA_bootstrap; +extern AudioBootStrap MINTAUDIO_XBIOS_bootstrap; +extern AudioBootStrap MINTAUDIO_DMA8_bootstrap; +extern AudioBootStrap DISKAUD_bootstrap; +extern AudioBootStrap DUMMYAUD_bootstrap; +extern AudioBootStrap DCAUD_bootstrap; +extern AudioBootStrap MMEAUDIO_bootstrap; +extern AudioBootStrap DART_bootstrap; + /* Available audio drivers */ static AudioBootStrap *bootstrap[] = { @@ -70,11 +107,11 @@ static AudioBootStrap *bootstrap[] = { #if SDL_AUDIO_DRIVER_WAVEOUT &WAVEOUT_bootstrap, #endif -#if SDL_AUDIO_DRIVER_PAUD - &Paud_bootstrap, +#if SDL_AUDIO_DRIVER_PAUDIO + &PAUDIO_bootstrap, #endif -#if SDL_AUDIO_DRIVER_BAUDIO - &BAUDIO_bootstrap, +#if SDL_AUDIO_DRIVER_BEOSAUDIO + &BEOSAUDIO_bootstrap, #endif #if SDL_AUDIO_DRIVER_COREAUDIO &COREAUDIO_bootstrap, @@ -82,9 +119,6 @@ static AudioBootStrap *bootstrap[] = { #if SDL_AUDIO_DRIVER_SNDMGR &SNDMGR_bootstrap, #endif -#if SDL_AUDIO_DRIVER_AHI - &AHI_bootstrap, -#endif #if SDL_AUDIO_DRIVER_MINT &MINTAUDIO_GSXB_bootstrap, &MINTAUDIO_MCSN_bootstrap, @@ -109,227 +143,201 @@ static AudioBootStrap *bootstrap[] = { #endif NULL }; -SDL_AudioDevice *current_audio = NULL; -/* Various local functions */ -int SDL_AudioInit(const char *driver_name); -void SDL_AudioQuit(void); +static SDL_AudioDevice *get_audio_device(SDL_AudioDeviceID id) +{ + id--; + if ( (id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL) ) { + SDL_SetError("Invalid audio device ID"); + return NULL; + } + + return open_devices[id]; +} + + +/* stubs for audio drivers that don't need a specific entry point... */ +static int SDL_AudioDetectDevices_Default(int iscapture) { return -1; } +static void SDL_AudioThreadInit_Default(_THIS) { /* no-op. */ } +static void SDL_AudioWaitDevice_Default(_THIS) { /* no-op. */ } +static void SDL_AudioPlayDevice_Default(_THIS) { /* no-op. */ } +static Uint8 *SDL_AudioGetDeviceBuf_Default(_THIS) { return NULL; } +static void SDL_AudioWaitDone_Default(_THIS) { /* no-op. */ } +static void SDL_AudioCloseDevice_Default(_THIS) { /* no-op. */ } +static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ } + +static int +SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture) +{ + return 0; +} + +static const char *SDL_AudioGetDeviceName_Default(int index, int iscapture) +{ + SDL_SetError("No such device"); + return NULL; +} + +static void +SDL_AudioLockDevice_Default(SDL_AudioDevice * device) +{ + if (device->thread && (SDL_ThreadID() == device->threadid)) { + return; + } + SDL_mutexP(device->mixer_lock); +} + +static void +SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device) +{ + if (device->thread && (SDL_ThreadID() == device->threadid)) { + return; + } + SDL_mutexV(device->mixer_lock); +} + + +static void finalize_audio_entry_points(void) +{ + /* + * Fill in stub functions for unused driver entry points. This lets us + * blindly call them without having to check for validity first. + */ + + #define FILL_STUB(x) \ + if (current_audio.impl.x == NULL) { \ + current_audio.impl.x = SDL_Audio##x##_Default; \ + } + FILL_STUB(DetectDevices); + FILL_STUB(GetDeviceName); + FILL_STUB(OpenDevice); + FILL_STUB(ThreadInit); + FILL_STUB(WaitDevice); + FILL_STUB(PlayDevice); + FILL_STUB(GetDeviceBuf); + FILL_STUB(WaitDone); + FILL_STUB(CloseDevice); + FILL_STUB(LockDevice); + FILL_STUB(UnlockDevice); + FILL_STUB(Deinitialize); + #undef FILL_STUB +} -#if SDL_AUDIO_DRIVER_AHI -static int audio_configured = 0; -#endif /* The general mixing thread function */ int SDLCALL -SDL_RunAudio(void *audiop) +SDL_RunAudio(void *devicep) { - SDL_AudioDevice *audio = (SDL_AudioDevice *) audiop; + SDL_AudioDevice *device = (SDL_AudioDevice *) devicep; + const int legacy_device = (device == open_devices[0]); Uint8 *stream; int stream_len; void *udata; void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len); int silence; -#if SDL_AUDIO_DRIVER_AHI - int started = 0; - -/* AmigaOS NEEDS that the audio driver is opened in the thread that uses it! */ - - D(bug("Task audio started audio struct:<%lx>...\n", audiop)); - - D(bug("Before Openaudio...")); - if (audio->OpenAudio(audio, &audio->spec) == -1) { - D(bug("Open audio failed...\n")); - return (-1); - } - D(bug("OpenAudio...OK\n")); -#endif /* Perform any thread setup */ - if (audio->ThreadInit) { - audio->ThreadInit(audio); - } - audio->threadid = SDL_ThreadID(); + device->threadid = SDL_ThreadID(); + current_audio.impl.ThreadInit(device); /* Set up the mixing function */ - fill = audio->spec.callback; - udata = audio->spec.userdata; - -#if SDL_AUDIO_DRIVER_AHI - audio_configured = 1; + fill = device->spec.callback; + udata = device->spec.userdata; - D(bug("Audio configured... Checking for conversion\n")); - SDL_mutexP(audio->mixer_lock); - D(bug("Semaphore obtained...\n")); -#endif - - if (audio->convert.needed) { - if (audio->convert.src_format == AUDIO_U8) { + if (device->convert.needed) { + if (device->convert.src_format == AUDIO_U8) { silence = 0x80; } else { silence = 0; } - stream_len = audio->convert.len; + stream_len = device->convert.len; } else { - silence = audio->spec.silence; - stream_len = audio->spec.size; + silence = device->spec.silence; + stream_len = device->spec.size; } -#if SDL_AUDIO_DRIVER_AHI - SDL_mutexV(audio->mixer_lock); - D(bug("Entering audio loop...\n")); -#endif - -#ifdef __OS2__ - /* Increase the priority of this thread to make sure that - the audio will be continuous all the time! */ -#ifdef USE_DOSSETPRIORITY - if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) { -#ifdef DEBUG_BUILD - printf - ("[SDL_RunAudio] : Setting priority to TimeCritical+0! (TID%d)\n", - SDL_ThreadID()); -#endif - DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0); - } else { -#ifdef DEBUG_BUILD - printf - ("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n", - SDL_ThreadID()); -#endif - DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0); - } -#endif -#endif - /* Loop, filling the audio buffers */ - while (audio->enabled) { + while (device->enabled) { /* Fill the current buffer with sound */ - if (audio->convert.needed) { - if (audio->convert.buf) { - stream = audio->convert.buf; + if (device->convert.needed) { + if (device->convert.buf) { + stream = device->convert.buf; } else { continue; } } else { - stream = audio->GetAudioBuf(audio); + stream = current_audio.impl.GetDeviceBuf(device); if (stream == NULL) { - stream = audio->fake_stream; + stream = device->fake_stream; } } - SDL_memset(stream, silence, stream_len); - if (!audio->paused) { - SDL_mutexP(audio->mixer_lock); + /* New code should fill buffer or set it to silence themselves. */ + if (legacy_device) { + SDL_memset(stream, silence, stream_len); + } + + if (!device->paused) { + SDL_mutexP(device->mixer_lock); (*fill) (udata, stream, stream_len); - SDL_mutexV(audio->mixer_lock); + SDL_mutexV(device->mixer_lock); } /* Convert the audio if necessary */ - if (audio->convert.needed) { - SDL_ConvertAudio(&audio->convert); - stream = audio->GetAudioBuf(audio); + if (device->convert.needed) { + SDL_ConvertAudio(&device->convert); + stream = current_audio.impl.GetDeviceBuf(device); if (stream == NULL) { - stream = audio->fake_stream; + stream = device->fake_stream; } - SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt); + SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt); } /* Ready current buffer for play and change current buffer */ - if (stream != audio->fake_stream) { - audio->PlayAudio(audio); + if (stream != device->fake_stream) { + current_audio.impl.PlayDevice(device); } /* Wait for an audio buffer to become available */ - if (stream == audio->fake_stream) { - SDL_Delay((audio->spec.samples * 1000) / audio->spec.freq); + if (stream == device->fake_stream) { + SDL_Delay((device->spec.samples * 1000) / device->spec.freq); } else { - audio->WaitAudio(audio); + current_audio.impl.WaitDevice(device); } } /* Wait for the audio to drain.. */ - if (audio->WaitDone) { - audio->WaitDone(audio); - } -#if SDL_AUDIO_DRIVER_AHI - D(bug("WaitAudio...Done\n")); + current_audio.impl.WaitDone(device); - audio->CloseAudio(audio); - - D(bug("CloseAudio..Done, subtask exiting...\n")); - audio_configured = 0; -#endif -#ifdef __OS2__ -#ifdef DEBUG_BUILD - printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID()); -#endif -#endif return (0); } -static void -SDL_LockAudio_Default(SDL_AudioDevice * audio) -{ - if (audio->thread && (SDL_ThreadID() == audio->threadid)) { - return; - } - SDL_mutexP(audio->mixer_lock); -} - -static void -SDL_UnlockAudio_Default(SDL_AudioDevice * audio) -{ - if (audio->thread && (SDL_ThreadID() == audio->threadid)) { - return; - } - SDL_mutexV(audio->mixer_lock); -} static SDL_AudioFormat SDL_ParseAudioFormat(const char *string) { - SDL_AudioFormat format = 0; - - switch (*string) { - case 'U': - ++string; - format |= 0x0000; - break; - case 'S': - ++string; - format |= 0x8000; - break; - default: - return 0; - } - switch (SDL_atoi(string)) { - case 8: - string += 1; - format |= 8; - break; - case 16: - string += 2; - format |= 16; - if (SDL_strcmp(string, "LSB") == 0 -#if SDL_BYTEORDER == SDL_LIL_ENDIAN - || SDL_strcmp(string, "SYS") == 0 -#endif - ) { - format |= 0x0000; - } - if (SDL_strcmp(string, "MSB") == 0 -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - || SDL_strcmp(string, "SYS") == 0 -#endif - ) { - format |= 0x1000; - } - break; - default: - return 0; - } - return format; + #define CHECK_FMT_STRING(x) if (strcmp(string, #x) == 0) return AUDIO_##x + CHECK_FMT_STRING(U8); + CHECK_FMT_STRING(S8); + CHECK_FMT_STRING(U16LSB); + CHECK_FMT_STRING(S16LSB); + CHECK_FMT_STRING(U16MSB); + CHECK_FMT_STRING(S16MSB); + CHECK_FMT_STRING(U16SYS); + CHECK_FMT_STRING(S16SYS); + CHECK_FMT_STRING(U16); + CHECK_FMT_STRING(S16); + CHECK_FMT_STRING(S32LSB); + CHECK_FMT_STRING(S32MSB); + CHECK_FMT_STRING(S32SYS); + CHECK_FMT_STRING(S32); + CHECK_FMT_STRING(F32LSB); + CHECK_FMT_STRING(F32MSB); + CHECK_FMT_STRING(F32SYS); + CHECK_FMT_STRING(F32); + #undef CHECK_FMT_STRING + return 0; } int @@ -350,92 +358,53 @@ SDL_GetAudioDriver(int index) int SDL_AudioInit(const char *driver_name) { - SDL_AudioDevice *audio; - int i = 0, idx; + int i = 0; + int initialized = 0; + int tried_to_init = 0; - /* Check to make sure we don't overwrite 'current_audio' */ - if (current_audio != NULL) { - SDL_AudioQuit(); + if (SDL_WasInit(SDL_INIT_AUDIO)) { + SDL_AudioQuit(); /* shutdown driver if already running. */ } + SDL_memset(¤t_audio, '\0', sizeof (current_audio)); + SDL_memset(open_devices, '\0', sizeof (open_devices)); + /* Select the proper audio driver */ - audio = NULL; - idx = 0; if (driver_name == NULL) { driver_name = SDL_getenv("SDL_AUDIODRIVER"); } -#if SDL_AUDIO_DRIVER_ESD - if ((driver_name == NULL) && (SDL_getenv("ESPEAKER") != NULL)) { - /* Ahem, we know that if ESPEAKER is set, user probably wants - to use ESD, but don't start it if it's not already running. - This probably isn't the place to do this, but... Shh! :) - */ - for (i = 0; bootstrap[i]; ++i) { - if (SDL_strcasecmp(bootstrap[i]->name, "esd") == 0) { -#ifdef HAVE_PUTENV - const char *esd_no_spawn; - - /* Don't start ESD if it's not running */ - esd_no_spawn = getenv("ESD_NO_SPAWN"); - if (esd_no_spawn == NULL) { - putenv("ESD_NO_SPAWN=1"); - } -#endif - if (bootstrap[i]->available()) { - audio = bootstrap[i]->create(0); - break; - } -#ifdef HAVE_UNSETENV - if (esd_no_spawn == NULL) { - unsetenv("ESD_NO_SPAWN"); - } -#endif - } + + for (i = 0; (!initialized) && (bootstrap[i]); ++i) { + /* make sure we should even try this driver before doing so... */ + const AudioBootStrap *backend = bootstrap[i]; + if ( ((driver_name) && (SDL_strcasecmp(backend->name, driver_name))) || + ((!driver_name) && (backend->demand_only)) ) { + continue; } + + tried_to_init = 1; + SDL_memset(¤t_audio, 0, sizeof (current_audio)); + current_audio.name = backend->name; + current_audio.desc = backend->desc; + initialized = backend->init(¤t_audio.impl); } -#endif /* SDL_AUDIO_DRIVER_ESD */ - if (audio == NULL) { - if (driver_name != NULL) { - for (i = 0; bootstrap[i]; ++i) { - if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) { - if (bootstrap[i]->available()) { - audio = bootstrap[i]->create(idx); - } - break; - } - } - } else { - for (i = 0; bootstrap[i]; ++i) { - if (bootstrap[i]->available()) { - audio = bootstrap[i]->create(idx); - if (audio != NULL) { - break; - } - } - } - } - if (audio == NULL) { + + if (!initialized) { + /* specific drivers will set the error message if they fail... */ + if (!tried_to_init) { if (driver_name) { SDL_SetError("%s not available", driver_name); } else { SDL_SetError("No available audio device"); } -#if 0 - /* Don't fail SDL_Init() if audio isn't available. - SDL_OpenAudio() will handle it at that point. *sigh* - */ - return (-1); -#endif - } - } - current_audio = audio; - if (current_audio) { - current_audio->name = bootstrap[i]->name; - if (!current_audio->LockAudio && !current_audio->UnlockAudio) { - current_audio->LockAudio = SDL_LockAudio_Default; - current_audio->UnlockAudio = SDL_UnlockAudio_Default; } + + SDL_memset(¤t_audio, 0, sizeof (current_audio)); + return (-1); /* No driver was available, so fail. */ } + + finalize_audio_entry_points(); + return (0); } @@ -445,222 +414,369 @@ SDL_AudioInit(const char *driver_name) const char * SDL_GetCurrentAudioDriver() { - if (current_audio) { - return current_audio->name; - } - return (NULL); + return current_audio.name; } + int -SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained) +SDL_GetNumAudioDevices(int iscapture) { - SDL_AudioDevice *audio; - const char *env; + if (!SDL_WasInit(SDL_INIT_AUDIO)) { + return -1; + } + if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) { + return 0; + } - /* Start up the audio driver, if necessary */ - if (!current_audio) { - if ((SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) || - (current_audio == NULL)) { - return (-1); - } + if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) { + return 1; } - audio = current_audio; - if (audio->opened) { - SDL_SetError("Audio device is already opened"); - return (-1); + if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { + return 1; } - /* Verify some parameters */ - if (desired->freq == 0) { - env = SDL_getenv("SDL_AUDIO_FREQUENCY"); - if (env) { - desired->freq = SDL_atoi(env); - } + return current_audio.impl.DetectDevices(iscapture); +} + + +const char * +SDL_GetAudioDeviceName(int index, int iscapture) +{ + if (!SDL_WasInit(SDL_INIT_AUDIO)) { + SDL_SetError("Audio subsystem is not initialized"); + return NULL; } - if (desired->freq == 0) { - /* Pick some default audio frequency */ - desired->freq = 22050; + + if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) { + SDL_SetError("No capture support"); + return NULL; } - if (desired->format == 0) { - env = SDL_getenv("SDL_AUDIO_FORMAT"); - if (env) { - desired->format = SDL_ParseAudioFormat(env); - } + + if (index < 0) { + SDL_SetError("No such device"); + return NULL; + } + + if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) { + return DEFAULT_INPUT_DEVNAME; + } + + if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { + return DEFAULT_OUTPUT_DEVNAME; + } + + return current_audio.impl.GetDeviceName(index, iscapture); +} + + +static void +close_audio_device(SDL_AudioDevice *device) +{ + device->enabled = 0; + if (device->thread != NULL) { + SDL_WaitThread(device->thread, NULL); + } + if (device->mixer_lock != NULL) { + SDL_DestroyMutex(device->mixer_lock); } - if (desired->format == 0) { - /* Pick some default audio format */ - desired->format = AUDIO_S16; + if (device->fake_stream != NULL) { + SDL_FreeAudioMem(device->fake_stream); } - if (desired->channels == 0) { - env = SDL_getenv("SDL_AUDIO_CHANNELS"); - if (env) { - desired->channels = (Uint8) SDL_atoi(env); + if (device->convert.needed) { + SDL_FreeAudioMem(device->convert.buf); + } + if (device->opened) { + current_audio.impl.CloseDevice(device); + device->opened = 0; + } + SDL_FreeAudioMem(device); +} + + +/* + * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig). + * Fills in a sanitized copy in (prepared). + * Returns non-zero if okay, zero on fatal parameters in (orig). + */ +static int +prepare_audiospec(const SDL_AudioSpec *orig, SDL_AudioSpec *prepared) +{ + SDL_memcpy(prepared, orig, sizeof (SDL_AudioSpec)); + + if (orig->callback == NULL) { + SDL_SetError("SDL_OpenAudio() passed a NULL callback"); + return 0; + } + + if (orig->freq == 0) { + const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY"); + if ( (!env) || ((prepared->freq = SDL_atoi(env)) == 0) ) { + prepared->freq = 22050; /* a reasonable default */ } } - if (desired->channels == 0) { - /* Pick a default number of channels */ - desired->channels = 2; + + if (orig->format == 0) { + const char *env = SDL_getenv("SDL_AUDIO_FORMAT"); + if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) { + prepared->format = AUDIO_S16; /* a reasonable default */ + } + } + + switch (orig->channels) { + case 0: { + const char *env = SDL_getenv("SDL_AUDIO_CHANNELS"); + if ( (!env) || ((prepared->channels = SDL_atoi(env)) == 0) ) { + prepared->channels = 2; /* a reasonable default */ + } + break; } - switch (desired->channels) { case 1: /* Mono */ case 2: /* Stereo */ case 4: /* surround */ case 6: /* surround with center and lfe */ break; default: - SDL_SetError("1 (mono) and 2 (stereo) channels supported"); - return (-1); - } - if (desired->samples == 0) { - env = SDL_getenv("SDL_AUDIO_SAMPLES"); - if (env) { - desired->samples = (Uint16) SDL_atoi(env); - } + SDL_SetError("Unsupported number of audio channels."); + return 0; } - if (desired->samples == 0) { - /* Pick a default of ~46 ms at desired frequency */ - int samples = (desired->freq / 1000) * 46; - int power2 = 1; - while (power2 < samples) { - power2 *= 2; + + if (orig->samples == 0) { + const char *env = SDL_getenv("SDL_AUDIO_SAMPLES"); + if ( (!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0) ) { + /* Pick a default of ~46 ms at desired frequency */ + /* !!! FIXME: remove this when the non-Po2 resampling is in. */ + const int samples = (prepared->freq / 1000) * 46; + int power2 = 1; + while (power2 < samples) { + power2 *= 2; + } + prepared->samples = power2; } - desired->samples = power2; } - if (desired->callback == NULL) { - SDL_SetError("SDL_OpenAudio() passed a NULL callback"); - return (-1); + + /* Calculate the silence and size of the audio specification */ + SDL_CalculateAudioSpec(prepared); + + return 1; +} + + +static SDL_AudioDeviceID +open_audio_device(const char *devname, int iscapture, + const SDL_AudioSpec *_desired, SDL_AudioSpec *obtained, + int min_id) +{ + SDL_AudioDeviceID id = 0; + SDL_AudioSpec desired; + SDL_AudioDevice *device; + int i = 0; + + if (!SDL_WasInit(SDL_INIT_AUDIO)) { + SDL_SetError("Audio subsystem is not initialized"); + return 0; } -#if defined(__MINT__) && SDL_THREADS_DISABLED - /* Uses interrupt driven audio, without thread */ -#else - /* Create a semaphore for locking the sound buffers */ - audio->mixer_lock = SDL_CreateMutex(); - if (audio->mixer_lock == NULL) { - SDL_SetError("Couldn't create mixer lock"); - SDL_CloseAudio(); - return (-1); + + if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) { + SDL_SetError("No capture support"); + return 0; } -#endif /* __MINT__ */ - /* Calculate the silence and size of the audio specification */ - SDL_CalculateAudioSpec(desired); + if (!prepare_audiospec(_desired, &desired)) { + return 0; + } - /* Open the audio subsystem */ - SDL_memcpy(&audio->spec, desired, sizeof(audio->spec)); - audio->convert.needed = 0; - audio->enabled = 1; - audio->paused = 1; + /* If app doesn't care about a specific device, let the user override. */ + if (devname == NULL) { + devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME"); + } -#if !SDL_AUDIO_DRIVER_AHI + /* + * Catch device names at the high level for the simple case... + * This lets us have a basic "device enumeration" for systems that + * don't have multiple devices, but makes sure the device name is + * always NULL when it hits the low level. + * + * Also make sure that the simple case prevents multiple simultaneous + * opens of the default system device. + */ -/* AmigaOS opens audio inside the main loop */ - audio->opened = audio->OpenAudio(audio, &audio->spec) + 1; + if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) { + if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) { + SDL_SetError("No such device"); + return 0; + } + devname = NULL; - if (!audio->opened) { - SDL_CloseAudio(); - return (-1); + for (i = 0; i < SDL_arraysize(open_devices); i++) { + if ((open_devices[i]) && (open_devices[i]->iscapture)) { + SDL_SetError("Audio device already open"); + return 0; + } + } } -#else - D(bug("Locking semaphore...")); - SDL_mutexP(audio->mixer_lock); + if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { + if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) { + SDL_SetError("No such device"); + return 0; + } + devname = NULL; - audio->thread = SDL_CreateThread(SDL_RunAudio, audio); - D(bug("Created thread...\n")); + for (i = 0; i < SDL_arraysize(open_devices); i++) { + if ((open_devices[i]) && (!open_devices[i]->iscapture)) { + SDL_SetError("Audio device already open"); + return 0; + } + } + } - if (audio->thread == NULL) { - SDL_mutexV(audio->mixer_lock); - SDL_CloseAudio(); - SDL_SetError("Couldn't create audio thread"); - return (-1); + device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof (SDL_AudioDevice)); + if (device == NULL) { + SDL_OutOfMemory(); + return 0; } + SDL_memset(device, '\0', sizeof (SDL_AudioDevice)); + SDL_memcpy(&device->spec, &desired, sizeof (SDL_AudioSpec)); + device->enabled = 1; + device->paused = 1; + device->iscapture = iscapture; - while (!audio_configured) - SDL_Delay(100); -#endif + /* Create a semaphore for locking the sound buffers */ + if (!current_audio.impl.SkipMixerLock) { + device->mixer_lock = SDL_CreateMutex(); + if (device->mixer_lock == NULL) { + close_audio_device(device); + SDL_SetError("Couldn't create mixer lock"); + return 0; + } + } + + if (!current_audio.impl.OpenDevice(device, devname, iscapture)) { + close_audio_device(device); + return 0; + } + device->opened = 1; /* If the audio driver changes the buffer size, accept it */ - if (audio->spec.samples != desired->samples) { - desired->samples = audio->spec.samples; - SDL_CalculateAudioSpec(desired); + if (device->spec.samples != desired.samples) { + desired.samples = device->spec.samples; + SDL_CalculateAudioSpec(&device->spec); } /* Allocate a fake audio memory buffer */ - audio->fake_stream = SDL_AllocAudioMem(audio->spec.size); - if (audio->fake_stream == NULL) { - SDL_CloseAudio(); + device->fake_stream = SDL_AllocAudioMem(device->spec.size); + if (device->fake_stream == NULL) { + close_audio_device(device); SDL_OutOfMemory(); - return (-1); + return 0; } /* See if we need to do any conversion */ if (obtained != NULL) { - SDL_memcpy(obtained, &audio->spec, sizeof(audio->spec)); - } else if (desired->freq != audio->spec.freq || - desired->format != audio->spec.format || - desired->channels != audio->spec.channels) { + SDL_memcpy(obtained, &device->spec, sizeof(SDL_AudioSpec)); + } else if (desired.freq != device->spec.freq || + desired.format != device->spec.format || + desired.channels != device->spec.channels) { /* Build an audio conversion block */ - if (SDL_BuildAudioCVT(&audio->convert, - desired->format, desired->channels, - desired->freq, - audio->spec.format, audio->spec.channels, - audio->spec.freq) < 0) { - SDL_CloseAudio(); - return (-1); + if (SDL_BuildAudioCVT(&device->convert, + desired.format, desired.channels, + desired.freq, + device->spec.format, device->spec.channels, + device->spec.freq) < 0) { + close_audio_device(device); + return 0; } - if (audio->convert.needed) { - audio->convert.len = desired->size; - audio->convert.buf = - (Uint8 *) SDL_AllocAudioMem(audio->convert.len * - audio->convert.len_mult); - if (audio->convert.buf == NULL) { - SDL_CloseAudio(); + if (device->convert.needed) { + device->convert.len = desired.size; + device->convert.buf = + (Uint8 *) SDL_AllocAudioMem(device->convert.len * + device->convert.len_mult); + if (device->convert.buf == NULL) { + close_audio_device(device); SDL_OutOfMemory(); - return (-1); + return 0; } } } -#if !SDL_AUDIO_DRIVER_AHI + + /* Find an available device ID and store the structure... */ + for (id = min_id-1; id < SDL_arraysize(open_devices); id++) { + if (open_devices[id] == NULL) { + open_devices[id] = device; + break; + } + } + + if (id == SDL_arraysize(open_devices)) { + SDL_SetError("Too many open audio devices"); + close_audio_device(device); + return 0; + } + /* Start the audio thread if necessary */ - switch (audio->opened) { - case 1: + if (!current_audio.impl.ProvidesOwnCallbackThread) { /* Start the audio thread */ +/* !!! FIXME: this is nasty. */ #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) #undef SDL_CreateThread - audio->thread = SDL_CreateThread(SDL_RunAudio, audio, NULL, NULL); + device->thread = SDL_CreateThread(SDL_RunAudio, device, NULL, NULL); #else - audio->thread = SDL_CreateThread(SDL_RunAudio, audio); + device->thread = SDL_CreateThread(SDL_RunAudio, device); #endif - if (audio->thread == NULL) { - SDL_CloseAudio(); + if (device->thread == NULL) { + SDL_CloseAudioDevice(id+1); SDL_SetError("Couldn't create audio thread"); + return 0; + } + } + + return id+1; +} + + +int +SDL_OpenAudio(const SDL_AudioSpec * desired, SDL_AudioSpec * obtained) +{ + SDL_AudioDeviceID id = 0; + + /* Start up the audio driver, if necessary. This is legacy behaviour! */ + if (!SDL_WasInit(SDL_INIT_AUDIO)) { + if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { return (-1); } - break; + } - default: - /* The audio is now playing */ - break; + /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */ + if (open_devices[0] != NULL) { + SDL_SetError("Audio device is already opened"); + return (-1); } -#else - SDL_mutexV(audio->mixer_lock); - D(bug("SDL_OpenAudio USCITA...\n")); -#endif + id = open_audio_device(NULL, 0, desired, obtained, 1); + if (id > 1) { /* this should never happen in theory... */ + SDL_CloseAudioDevice(id); + SDL_SetError("Internal error"); /* MUST be Device ID #1! */ + return (-1); + } - return (0); + return ((id == 0) ? -1 : 0); } -SDL_audiostatus -SDL_GetAudioStatus(void) +SDL_AudioDeviceID +SDL_OpenAudioDevice(const char *device, int iscapture, + const SDL_AudioSpec *desired, SDL_AudioSpec *obtained) { - SDL_AudioDevice *audio = current_audio; - SDL_audiostatus status; + return open_audio_device(device, iscapture, desired, obtained, 2); +} - status = SDL_AUDIO_STOPPED; - if (audio && audio->enabled) { - if (audio->paused) { +SDL_audiostatus +SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid) +{ + SDL_AudioDevice *device = get_audio_device(devid); + SDL_audiostatus status = SDL_AUDIO_STOPPED; + if (device && device->enabled) { + if (device->paused) { status = SDL_AUDIO_PAUSED; } else { status = SDL_AUDIO_PLAYING; @@ -669,74 +785,89 @@ SDL_GetAudioStatus(void) return (status); } + +SDL_audiostatus +SDL_GetAudioStatus(void) +{ + return SDL_GetAudioDeviceStatus(1); +} + +void +SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on) +{ + SDL_AudioDevice *device = get_audio_device(devid); + if (device) { + device->paused = pause_on; + } +} + void SDL_PauseAudio(int pause_on) { - SDL_AudioDevice *audio = current_audio; + SDL_PauseAudioDevice(1, pause_on); +} + - if (audio) { - audio->paused = pause_on; +void +SDL_LockAudioDevice(SDL_AudioDeviceID devid) +{ + /* Obtain a lock on the mixing buffers */ + SDL_AudioDevice *device = get_audio_device(devid); + if (device) { + current_audio.impl.LockDevice(device); } } void SDL_LockAudio(void) { - SDL_AudioDevice *audio = current_audio; + SDL_LockAudioDevice(1); +} +void +SDL_UnlockAudioDevice(SDL_AudioDeviceID devid) +{ /* Obtain a lock on the mixing buffers */ - if (audio && audio->LockAudio) { - audio->LockAudio(audio); + SDL_AudioDevice *device = get_audio_device(devid); + if (device) { + current_audio.impl.UnlockDevice(device); } } void SDL_UnlockAudio(void) { - SDL_AudioDevice *audio = current_audio; + SDL_UnlockAudioDevice(1); +} - /* Release lock on the mixing buffers */ - if (audio && audio->UnlockAudio) { - audio->UnlockAudio(audio); +void +SDL_CloseAudioDevice(SDL_AudioDeviceID devid) +{ + SDL_AudioDevice *device = get_audio_device(devid); + if (device) { + close_audio_device(device); + open_devices[devid-1] = NULL; } } void SDL_CloseAudio(void) { - SDL_QuitSubSystem(SDL_INIT_AUDIO); + SDL_CloseAudioDevice(1); } void SDL_AudioQuit(void) { - SDL_AudioDevice *audio = current_audio; - - if (audio) { - audio->enabled = 0; - if (audio->thread != NULL) { - SDL_WaitThread(audio->thread, NULL); - } - if (audio->mixer_lock != NULL) { - SDL_DestroyMutex(audio->mixer_lock); - } - if (audio->fake_stream != NULL) { - SDL_FreeAudioMem(audio->fake_stream); - } - if (audio->convert.needed) { - SDL_FreeAudioMem(audio->convert.buf); - - } -#if !SDL_AUDIO_DRIVER_AHI - if (audio->opened) { - audio->CloseAudio(audio); - audio->opened = 0; - } -#endif - /* Free the driver data */ - audio->free(audio); - current_audio = NULL; + SDL_AudioDeviceID i; + for (i = 0; i < SDL_arraysize(open_devices); i++) { + SDL_CloseAudioDevice(i); } + + /* Free the driver data */ + current_audio.impl.Deinitialize(); + SDL_memset(¤t_audio, '\0', sizeof (current_audio)); + SDL_memset(open_devices, '\0', sizeof (open_devices)); } #define NUM_FORMATS 10 @@ -797,9 +928,30 @@ SDL_CalculateAudioSpec(SDL_AudioSpec * spec) spec->silence = 0x00; break; } - spec->size = (spec->format & 0xFF) / 8; + spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8; spec->size *= spec->channels; spec->size *= spec->samples; } + +/* + * Moved here from SDL_mixer.c, since it relies on internals of an opened + * audio device (and is deprecated, by the way!). + */ +void +SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume) +{ + /* Mix the user-level audio format */ + SDL_AudioDevice *device = get_audio_device(1); + if (device != NULL) { + SDL_AudioFormat format; + if (device->convert.needed) { + format = device->convert.src_format; + } else { + format = device->spec.format; + } + SDL_MixAudioFormat(dst, src, format, len, volume); + } +} + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c index 97acf41f1..f77fea45b 100644 --- a/src/audio/SDL_audiocvt.c +++ b/src/audio/SDL_audiocvt.c @@ -159,21 +159,19 @@ SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format) float *dst = (float *) cvt->buf; if (SDL_AUDIO_ISBIGENDIAN(format)) { for (i = cvt->len_cvt / 8; i; --i, src += 2) { - float src1, src2; - src1 = SDL_SwapFloatBE(src[0]); - src2 = SDL_SwapFloatBE(src[1]); + const float src1 = SDL_SwapFloatBE(src[0]); + const float src2 = SDL_SwapFloatBE(src[1]); const double added = ((double) src1) + ((double) src2); - src1 = (float) (added * 0.5); - *(dst++) = SDL_SwapFloatBE(src1); + const float halved = (float) (added * 0.5); + *(dst++) = SDL_SwapFloatBE(halved); } } else { for (i = cvt->len_cvt / 8; i; --i, src += 2) { - float src1, src2; - src1 = SDL_SwapFloatLE(src[0]); - src2 = SDL_SwapFloatLE(src[1]); + const float src1 = SDL_SwapFloatLE(src[0]); + const float src2 = SDL_SwapFloatLE(src[1]); const double added = ((double) src1) + ((double) src2); - src1 = (float) (added * 0.5); - *(dst++) = SDL_SwapFloatLE(src1); + const float halved = (float) (added * 0.5); + *(dst++) = SDL_SwapFloatLE(halved); } } } diff --git a/src/audio/SDL_audiodev.c b/src/audio/SDL_audiodev.c index 4db9ff47e..b4d7a2466 100644 --- a/src/audio/SDL_audiodev.c +++ b/src/audio/SDL_audiodev.c @@ -46,14 +46,63 @@ #define _PATH_DEV_AUDIO "/dev/audio" #endif +static inline void +test_device(const char *fname, int flags, int (*test)(int fd), + char ***devices, int *devCount) +{ + struct stat sb; + if ( (stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode)) ) { + int audio_fd = open(fname, flags, 0); + if ( (audio_fd >= 0) && (test(audio_fd)) ) { + void *p = SDL_realloc(*devices, ((*devCount)+1) * sizeof (char *)); + if (p != NULL) { + size_t len = strlen(fname) + 1; + char *str = (char *) SDL_malloc(len); + *devices = (char **) p; + if (str != NULL) { + SDL_strlcpy(str, fname, len); + (*devices)[(*devCount)++] = str; + } + } + close(audio_fd); + } + } +} -int -SDL_OpenAudioPath(char *path, int maxlen, int flags, int classic) +void +SDL_FreeUnixAudioDevices(char ***devices, int *devCount) +{ + int i = *devCount; + if ((i > 0) && (*devices != NULL)) { + while (i--) { + SDL_free( (*devices)[*devCount] ); + } + } + + if (*devices != NULL) { + SDL_free(*devices); + } + + *devices = NULL; + *devCount = 0; +} + +static int +test_stub(int fd) +{ + return 1; +} + +void +SDL_EnumUnixAudioDevices(int flags, int classic, int (*test)(int fd), + char ***devices, int *devCount) { const char *audiodev; - int audio_fd; char audiopath[1024]; + if (test == NULL) + test = test_stub; + /* Figure out what our audio device is */ if (((audiodev = SDL_getenv("SDL_PATH_DSP")) == NULL) && ((audiodev = SDL_getenv("AUDIODEV")) == NULL)) { @@ -72,111 +121,16 @@ SDL_OpenAudioPath(char *path, int maxlen, int flags, int classic) } } } - audio_fd = open(audiodev, flags, 0); - - /* If the first open fails, look for other devices */ - if ((audio_fd < 0) && (SDL_strlen(audiodev) < (sizeof(audiopath) - 3))) { - int exists, instance; - struct stat sb; + test_device(audiodev, flags, test, devices, devCount); - instance = 1; - do { /* Don't use errno ENOENT - it may not be thread-safe */ + if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) { + int instance = 0; + while (instance++ <= 64) { SDL_snprintf(audiopath, SDL_arraysize(audiopath), - "%s%d", audiodev, instance++); - exists = 0; - if (stat(audiopath, &sb) == 0) { - exists = 1; - audio_fd = open(audiopath, flags, 0); - } - } - while (exists && (audio_fd < 0)); - audiodev = audiopath; - } - if (path != NULL) { - SDL_strlcpy(path, audiodev, maxlen); - path[maxlen - 1] = '\0'; - } - return (audio_fd); -} - -#elif SDL_AUDIO_DRIVER_PAUD - -/* Get the name of the audio device we use for output */ - -#include -#include - -#include "SDL_stdinc.h" -#include "SDL_audiodev_c.h" - -#ifndef _PATH_DEV_DSP -#define _PATH_DEV_DSP "/dev/%caud%c/%c" -#endif - -char devsettings[][3] = { - {'p', '0', '1'}, {'p', '0', '2'}, {'p', '0', '3'}, {'p', '0', '4'}, - {'p', '1', '1'}, {'p', '1', '2'}, {'p', '1', '3'}, {'p', '1', '4'}, - {'p', '2', '1'}, {'p', '2', '2'}, {'p', '2', '3'}, {'p', '2', '4'}, - {'p', '3', '1'}, {'p', '3', '2'}, {'p', '3', '3'}, {'p', '3', '4'}, - {'b', '0', '1'}, {'b', '0', '2'}, {'b', '0', '3'}, {'b', '0', '4'}, - {'b', '1', '1'}, {'b', '1', '2'}, {'b', '1', '3'}, {'b', '1', '4'}, - {'b', '2', '1'}, {'b', '2', '2'}, {'b', '2', '3'}, {'b', '2', '4'}, - {'b', '3', '1'}, {'b', '3', '2'}, {'b', '3', '3'}, {'b', '3', '4'}, - {'\0', '\0', '\0'} -}; - -static int -OpenUserDefinedDevice(char *path, int maxlen, int flags) -{ - const char *audiodev; - int audio_fd; - - /* Figure out what our audio device is */ - if ((audiodev = SDL_getenv("SDL_PATH_DSP")) == NULL) { - audiodev = SDL_getenv("AUDIODEV"); - } - if (audiodev == NULL) { - return -1; - } - audio_fd = open(audiodev, flags, 0); - if (path != NULL) { - SDL_strlcpy(path, audiodev, maxlen); - path[maxlen - 1] = '\0'; - } - return audio_fd; -} - -int -SDL_OpenAudioPath(char *path, int maxlen, int flags, int classic) -{ - struct stat sb; - int audio_fd; - char audiopath[1024]; - int cycle; - - audio_fd = OpenUserDefinedDevice(path, maxlen, flags); - if (audio_fd != -1) { - return audio_fd; - } - - cycle = 0; - while (devsettings[cycle][0] != '\0') { - SDL_snprintf(audiopath, SDL_arraysize(audiopath), - _PATH_DEV_DSP, - devsettings[cycle][0], - devsettings[cycle][1], devsettings[cycle][2]); - - if (stat(audiopath, &sb) == 0) { - audio_fd = open(audiopath, flags, 0); - if (audio_fd > 0) { - if (path != NULL) { - SDL_strlcpy(path, audiopath, maxlen); - } - return audio_fd; - } + "%s%d", audiodev, instance); + test_device(audiopath, flags, test, devices, devCount); } } - return -1; } #endif /* Audio driver selection */ diff --git a/src/audio/SDL_audiodev_c.h b/src/audio/SDL_audiodev_c.h index 8e4809408..6092b40a7 100644 --- a/src/audio/SDL_audiodev_c.h +++ b/src/audio/SDL_audiodev_c.h @@ -21,6 +21,8 @@ */ #include "SDL_config.h" -/* Open the audio device, storing the pathname in 'path' */ -extern int SDL_OpenAudioPath(char *path, int maxlen, int flags, int classic); +void SDL_EnumUnixAudioDevices(int flags, int classic, int (*test)(int fd), + char ***devs, int *count); +void SDL_FreeUnixAudioDevices(char ***devices, int *devCount); + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/SDL_mixer.c b/src/audio/SDL_mixer.c index 6ca24f0ac..64257b6a7 100644 --- a/src/audio/SDL_mixer.c +++ b/src/audio/SDL_mixer.c @@ -89,21 +89,6 @@ static const Uint8 mix8[] = { #define ADJUST_VOLUME(s, v) (s = (s*v)/SDL_MIX_MAXVOLUME) #define ADJUST_VOLUME_U8(s, v) (s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128) -void -SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume) -{ - /* Mix the user-level audio format */ - if (current_audio) { - SDL_AudioFormat format; - if (current_audio->convert.needed) { - format = current_audio->convert.src_format; - } else { - format = current_audio->spec.format; - } - SDL_MixAudioFormat(dst, src, format, len, volume); - } -} - void SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format, diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 00d814b4a..ec64dba23 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -29,13 +29,33 @@ /* The SDL audio driver */ typedef struct SDL_AudioDevice SDL_AudioDevice; - -/* Define the SDL audio driver structure */ #define _THIS SDL_AudioDevice *_this -#ifndef _STATUS -#define _STATUS SDL_status *status -#endif -struct SDL_AudioDevice + +typedef struct SDL_AudioDriverImpl +{ + int (*DetectDevices)(int iscapture); + const char *(*GetDeviceName)(int index, int iscapture); + int (*OpenDevice) (_THIS, const char *devname, int iscapture); + void (*ThreadInit) (_THIS); /* Called by audio thread at start */ + void (*WaitDevice) (_THIS); + void (*PlayDevice) (_THIS); + Uint8 *(*GetDeviceBuf) (_THIS); + void (*WaitDone) (_THIS); + void (*CloseDevice) (_THIS); + void (*LockDevice) (_THIS); + void (*UnlockDevice) (_THIS); + void (*Deinitialize) (void); + + /* Some flags to push duplicate code into the core and reduce #ifdefs. */ + int ProvidesOwnCallbackThread:1; + int SkipMixerLock:1; + int HasCaptureSupport:1; + int OnlyHasDefaultOutputDevice:1; + int OnlyHasDefaultInputDevice:1; +} SDL_AudioDriverImpl; + + +typedef struct SDL_AudioDriver { /* * * */ /* The name of this audio driver */ @@ -45,21 +65,13 @@ struct SDL_AudioDevice /* The description of this audio driver */ const char *desc; - /* * * */ - /* Public driver functions */ - int (*OpenAudio) (_THIS, SDL_AudioSpec * spec); - void (*ThreadInit) (_THIS); /* Called by audio thread at start */ - void (*WaitAudio) (_THIS); - void (*PlayAudio) (_THIS); - Uint8 *(*GetAudioBuf) (_THIS); - void (*WaitDone) (_THIS); - void (*CloseAudio) (_THIS); + SDL_AudioDriverImpl impl; +} SDL_AudioDriver; - /* * * */ - /* Lock / Unlock functions added for the Mac port */ - void (*LockAudio) (_THIS); - void (*UnlockAudio) (_THIS); +/* Define the SDL audio driver structure */ +struct SDL_AudioDevice +{ /* * * */ /* Data common to all devices */ @@ -70,6 +82,7 @@ struct SDL_AudioDevice SDL_AudioCVT convert; /* Current state flags */ + int iscapture; int enabled; int paused; int opened; @@ -87,10 +100,6 @@ struct SDL_AudioDevice /* * * */ /* Data private to this driver */ struct SDL_PrivateAudioData *hidden; - - /* * * */ - /* The function used to dispose of this structure */ - void (*free) (_THIS); }; #undef _THIS @@ -98,84 +107,10 @@ typedef struct AudioBootStrap { const char *name; const char *desc; - int (*available) (void); - SDL_AudioDevice *(*create) (int devindex); + int (*init) (SDL_AudioDriverImpl *impl); + int demand_only:1; /* 1==request explicitly, or it won't be available. */ } AudioBootStrap; -#if SDL_AUDIO_DRIVER_BSD -extern AudioBootStrap BSD_AUDIO_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_OSS -extern AudioBootStrap DSP_bootstrap; -extern AudioBootStrap DMA_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_ALSA -extern AudioBootStrap ALSA_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_QNXNTO -extern AudioBootStrap QNXNTOAUDIO_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_SUNAUDIO -extern AudioBootStrap SUNAUDIO_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_DMEDIA -extern AudioBootStrap DMEDIA_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_ARTS -extern AudioBootStrap ARTS_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_ESD -extern AudioBootStrap ESD_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_NAS -extern AudioBootStrap NAS_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_DSOUND -extern AudioBootStrap DSOUND_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_WAVEOUT -extern AudioBootStrap WAVEOUT_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_PAUD -extern AudioBootStrap Paud_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_BAUDIO -extern AudioBootStrap BAUDIO_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_COREAUDIO -extern AudioBootStrap COREAUDIO_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_SNDMGR -extern AudioBootStrap SNDMGR_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_AHI -extern AudioBootStrap AHI_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_MINT -extern AudioBootStrap MINTAUDIO_GSXB_bootstrap; -extern AudioBootStrap MINTAUDIO_MCSN_bootstrap; -extern AudioBootStrap MINTAUDIO_STFA_bootstrap; -extern AudioBootStrap MINTAUDIO_XBIOS_bootstrap; -extern AudioBootStrap MINTAUDIO_DMA8_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_DISK -extern AudioBootStrap DISKAUD_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_DUMMY -extern AudioBootStrap DUMMYAUD_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_DC -extern AudioBootStrap DCAUD_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_MMEAUDIO -extern AudioBootStrap MMEAUDIO_bootstrap; -#endif -#if SDL_AUDIO_DRIVER_DART -extern AudioBootStrap DART_bootstrap; -#endif - -/* This is the current audio device */ -extern SDL_AudioDevice *current_audio; - #endif /* _SDL_sysaudio_h */ + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 5afd12937..88e7e1eab 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -25,6 +25,9 @@ #include #include /* For kill() */ +#include +#include +#include #include "SDL_timer.h" #include "SDL_audio.h" @@ -32,14 +35,6 @@ #include "../SDL_audio_c.h" #include "SDL_alsa_audio.h" -#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC -#include -#include "SDL_name.h" -#include "SDL_loadso.h" -#else -#define SDL_NAME(X) X -#endif - /* The tag name used by ALSA audio */ #define DRIVER_NAME "alsa" @@ -47,182 +42,138 @@ /* The default ALSA audio driver */ #define DEFAULT_DEVICE "default" -/* Audio driver functions */ -static int ALSA_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void ALSA_WaitAudio(_THIS); -static void ALSA_PlayAudio(_THIS); -static Uint8 *ALSA_GetAudioBuf(_THIS); -static void ALSA_CloseAudio(_THIS); +static int (*ALSA_snd_pcm_open) + (snd_pcm_t **, const char *, snd_pcm_stream_t, int); +static int (*ALSA_snd_pcm_close)(snd_pcm_t * pcm); +static snd_pcm_sframes_t(*ALSA_snd_pcm_writei) + (snd_pcm_t *,const void *, snd_pcm_uframes_t); +static int (*ALSA_snd_pcm_resume)(snd_pcm_t *); +static int (*ALSA_snd_pcm_prepare)(snd_pcm_t *); +static int (*ALSA_snd_pcm_drain)(snd_pcm_t *); +static const char *(*ALSA_snd_strerror)(int); +static size_t(*ALSA_snd_pcm_hw_params_sizeof)(void); +static size_t(*ALSA_snd_pcm_sw_params_sizeof)(void); +static int (*ALSA_snd_pcm_hw_params_any)(snd_pcm_t *, snd_pcm_hw_params_t *); +static int (*ALSA_snd_pcm_hw_params_set_access) + (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_access_t); +static int (*ALSA_snd_pcm_hw_params_set_format) + (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_format_t); +static int (*ALSA_snd_pcm_hw_params_set_channels) + (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int); +static int (*ALSA_snd_pcm_hw_params_get_channels)(const snd_pcm_hw_params_t *); +static unsigned int (*ALSA_snd_pcm_hw_params_set_rate_near) + (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int, int *); +static snd_pcm_uframes_t (*ALSA_snd_pcm_hw_params_set_period_size_near) + (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_uframes_t, int *); +static snd_pcm_sframes_t (*ALSA_snd_pcm_hw_params_get_period_size) + (const snd_pcm_hw_params_t *); +static unsigned int (*ALSA_snd_pcm_hw_params_set_periods_near) + (snd_pcm_t *,snd_pcm_hw_params_t *, unsigned int, int *); +static int (*ALSA_snd_pcm_hw_params_get_periods)(snd_pcm_hw_params_t *); +static int (*ALSA_snd_pcm_hw_params)(snd_pcm_t *, snd_pcm_hw_params_t *); +static int (*ALSA_snd_pcm_sw_params_current)(snd_pcm_t*, snd_pcm_sw_params_t*); +static int (*ALSA_snd_pcm_sw_params_set_start_threshold) + (snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t); +static int (*ALSA_snd_pcm_sw_params_set_avail_min) + (snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t); +static int (*ALSA_snd_pcm_sw_params)(snd_pcm_t *, snd_pcm_sw_params_t *); +static int (*ALSA_snd_pcm_nonblock)(snd_pcm_t *, int); +#define snd_pcm_hw_params_sizeof ALSA_snd_pcm_hw_params_sizeof +#define snd_pcm_sw_params_sizeof ALSA_snd_pcm_sw_params_sizeof + #ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC static const char *alsa_library = SDL_AUDIO_DRIVER_ALSA_DYNAMIC; static void *alsa_handle = NULL; -static int alsa_loaded = 0; - -static int (*SDL_snd_pcm_open) (snd_pcm_t ** pcm, const char *name, - snd_pcm_stream_t stream, int mode); -static int (*SDL_NAME(snd_pcm_open)) (snd_pcm_t ** pcm, const char *name, - snd_pcm_stream_t stream, int mode); -static int (*SDL_NAME(snd_pcm_close)) (snd_pcm_t * pcm); -static snd_pcm_sframes_t(*SDL_NAME(snd_pcm_writei)) (snd_pcm_t * pcm, - const void *buffer, - snd_pcm_uframes_t size); -static int (*SDL_NAME(snd_pcm_resume)) (snd_pcm_t * pcm); -static int (*SDL_NAME(snd_pcm_prepare)) (snd_pcm_t * pcm); -static int (*SDL_NAME(snd_pcm_drain)) (snd_pcm_t * pcm); -static const char *(*SDL_NAME(snd_strerror)) (int errnum); -static size_t(*SDL_NAME(snd_pcm_hw_params_sizeof)) (void); -static size_t(*SDL_NAME(snd_pcm_sw_params_sizeof)) (void); -static int (*SDL_NAME(snd_pcm_hw_params_any)) (snd_pcm_t * pcm, - snd_pcm_hw_params_t * params); -static int (*SDL_NAME(snd_pcm_hw_params_set_access)) (snd_pcm_t * pcm, - snd_pcm_hw_params_t * - params, - snd_pcm_access_t - access); -static int (*SDL_NAME(snd_pcm_hw_params_set_format)) (snd_pcm_t * pcm, - snd_pcm_hw_params_t * - params, - snd_pcm_format_t val); -static int (*SDL_NAME(snd_pcm_hw_params_set_channels)) (snd_pcm_t * pcm, - snd_pcm_hw_params_t * - params, - unsigned int val); -static int (*SDL_NAME(snd_pcm_hw_params_get_channels)) (const - snd_pcm_hw_params_t * - params); -static unsigned int - (*SDL_NAME(snd_pcm_hw_params_set_rate_near)) (snd_pcm_t * - pcm, - snd_pcm_hw_params_t - * params, - unsigned int val, int *dir); -static snd_pcm_uframes_t - (*SDL_NAME(snd_pcm_hw_params_set_period_size_near)) (snd_pcm_t * pcm, - snd_pcm_hw_params_t - * params, - snd_pcm_uframes_t - val, int *dir); -static snd_pcm_sframes_t - (*SDL_NAME(snd_pcm_hw_params_get_period_size)) (const - snd_pcm_hw_params_t - * params); -static unsigned int - (*SDL_NAME(snd_pcm_hw_params_set_periods_near)) (snd_pcm_t * pcm, - snd_pcm_hw_params_t - * params, - unsigned int val, - int *dir); -static int (*SDL_NAME(snd_pcm_hw_params_get_periods)) (snd_pcm_hw_params_t * - params); -static int (*SDL_NAME(snd_pcm_hw_params)) (snd_pcm_t * pcm, - snd_pcm_hw_params_t * params); -/* -*/ -static int (*SDL_NAME(snd_pcm_sw_params_current)) (snd_pcm_t * pcm, - snd_pcm_sw_params_t * - swparams); -static int (*SDL_NAME(snd_pcm_sw_params_set_start_threshold)) (snd_pcm_t * - pcm, - snd_pcm_sw_params_t - * params, - snd_pcm_uframes_t - val); -static int (*SDL_NAME(snd_pcm_sw_params_set_avail_min)) (snd_pcm_t * pcm, - snd_pcm_sw_params_t - * params, - snd_pcm_uframes_t - val); -static int (*SDL_NAME(snd_pcm_sw_params)) (snd_pcm_t * pcm, - snd_pcm_sw_params_t * params); -static int (*SDL_NAME(snd_pcm_nonblock)) (snd_pcm_t * pcm, int nonblock); -#define snd_pcm_hw_params_sizeof SDL_NAME(snd_pcm_hw_params_sizeof) -#define snd_pcm_sw_params_sizeof SDL_NAME(snd_pcm_sw_params_sizeof) -/* cast funcs to char* first, to please GCC's strict aliasing rules. */ -static struct +static int +load_alsa_sym(const char *fn, void **addr) { - const char *name; - void **func; -} alsa_functions[] = { - { - "snd_pcm_open", (void **) (char *) &SDL_NAME(snd_pcm_open)}, { - "snd_pcm_close", (void **) (char *) &SDL_NAME(snd_pcm_close)}, { - "snd_pcm_writei", (void **) (char *) &SDL_NAME(snd_pcm_writei)}, { - "snd_pcm_resume", (void **) (char *) &SDL_NAME(snd_pcm_resume)}, { - "snd_pcm_prepare", (void **) (char *) &SDL_NAME(snd_pcm_prepare)}, { - "snd_pcm_drain", (void **) (char *) &SDL_NAME(snd_pcm_drain)}, { - "snd_strerror", (void **) (char *) &SDL_NAME(snd_strerror)}, { - "snd_pcm_hw_params_sizeof", - (void **) (char *) &SDL_NAME(snd_pcm_hw_params_sizeof)}, { - "snd_pcm_sw_params_sizeof", - (void **) (char *) &SDL_NAME(snd_pcm_sw_params_sizeof)}, { - "snd_pcm_hw_params_any", - (void **) (char *) &SDL_NAME(snd_pcm_hw_params_any)}, { - "snd_pcm_hw_params_set_access", - (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_access)}, { - "snd_pcm_hw_params_set_format", - (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_format)}, { - "snd_pcm_hw_params_set_channels", - (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_channels)}, { - "snd_pcm_hw_params_get_channels", - (void **) (char *) &SDL_NAME(snd_pcm_hw_params_get_channels)}, { - "snd_pcm_hw_params_set_rate_near", - (void **) (char *) &SDL_NAME(snd_pcm_hw_params_set_rate_near)}, { - "snd_pcm_hw_params_set_period_size_near", (void **) (char *) - &SDL_NAME(snd_pcm_hw_params_set_period_size_near)}, { - "snd_pcm_hw_params_get_period_size", - (void **) (char *) &SDL_NAME(snd_pcm_hw_params_get_period_size)}, + /* + * !!! FIXME: + * Eventually, this will deal with fallbacks, version changes, and + * missing symbols we can workaround. But for now, it doesn't. + */ + +#if HAVE_DLVSYM + *addr = dlvsym(alsa_handle, fn, "ALSA_0.9"); + if (*addr == NULL) +#endif { - "snd_pcm_hw_params_set_periods_near", (void **) (char *) - &SDL_NAME(snd_pcm_hw_params_set_periods_near)}, { - "snd_pcm_hw_params_get_periods", - (void **) (char *) &SDL_NAME(snd_pcm_hw_params_get_periods)}, { - "snd_pcm_hw_params", (void **) (char *) &SDL_NAME(snd_pcm_hw_params)}, { - "snd_pcm_sw_params_current", - (void **) (char *) &SDL_NAME(snd_pcm_sw_params_current)}, { - "snd_pcm_sw_params_set_start_threshold", (void **) (char *) - &SDL_NAME(snd_pcm_sw_params_set_start_threshold)}, { - "snd_pcm_sw_params_set_avail_min", - (void **) (char *) &SDL_NAME(snd_pcm_sw_params_set_avail_min)}, { - "snd_pcm_sw_params", (void **) (char *) &SDL_NAME(snd_pcm_sw_params)}, { -"snd_pcm_nonblock", (void **) (char *) &SDL_NAME(snd_pcm_nonblock)},}; + *addr = dlsym(alsa_handle, fn); + if (*addr == NULL) { + SDL_SetError("dlsym('%s') failed: %s", fn, strerror(errno)); + return 0; + } + } + + return 1; +} + +/* cast funcs to char* first, to please GCC's strict aliasing rules. */ +#define SDL_ALSA_SYM(x) \ + if (!load_alsa_sym(#x, (void **) (char *) &ALSA_##x)) return -1 +#else +#define SDL_ALSA_SYM(x) ALSA_##x = x +#endif + +static int load_alsa_syms(void) +{ + SDL_ALSA_SYM(snd_pcm_open); + SDL_ALSA_SYM(snd_pcm_close); + SDL_ALSA_SYM(snd_pcm_writei); + SDL_ALSA_SYM(snd_pcm_resume); + SDL_ALSA_SYM(snd_pcm_prepare); + SDL_ALSA_SYM(snd_pcm_drain); + SDL_ALSA_SYM(snd_strerror); + SDL_ALSA_SYM(snd_pcm_hw_params_sizeof); + SDL_ALSA_SYM(snd_pcm_sw_params_sizeof); + SDL_ALSA_SYM(snd_pcm_hw_params_any); + SDL_ALSA_SYM(snd_pcm_hw_params_set_access); + SDL_ALSA_SYM(snd_pcm_hw_params_set_format); + SDL_ALSA_SYM(snd_pcm_hw_params_set_channels); + SDL_ALSA_SYM(snd_pcm_hw_params_get_channels); + SDL_ALSA_SYM(snd_pcm_hw_params_set_rate_near); + SDL_ALSA_SYM(snd_pcm_hw_params_set_period_size_near); + SDL_ALSA_SYM(snd_pcm_hw_params_get_period_size); + SDL_ALSA_SYM(snd_pcm_hw_params_set_periods_near); + SDL_ALSA_SYM(snd_pcm_hw_params_get_periods); + SDL_ALSA_SYM(snd_pcm_hw_params); + SDL_ALSA_SYM(snd_pcm_sw_params_current); + SDL_ALSA_SYM(snd_pcm_sw_params_set_start_threshold); + SDL_ALSA_SYM(snd_pcm_sw_params_set_avail_min); + SDL_ALSA_SYM(snd_pcm_sw_params); + SDL_ALSA_SYM(snd_pcm_nonblock); + return 0; +} +#undef SDL_ALSA_SYM + +#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC static void UnloadALSALibrary(void) { - if (alsa_loaded) { -/* SDL_UnloadObject(alsa_handle);*/ + if (alsa_handle != NULL) { dlclose(alsa_handle); alsa_handle = NULL; - alsa_loaded = 0; } } static int LoadALSALibrary(void) { - int i, retval = -1; - -/* alsa_handle = SDL_LoadObject(alsa_library);*/ - alsa_handle = dlopen(alsa_library, RTLD_NOW); - if (alsa_handle) { - alsa_loaded = 1; - retval = 0; - for (i = 0; i < SDL_arraysize(alsa_functions); i++) { -/* *alsa_functions[i].func = SDL_LoadFunction(alsa_handle,alsa_functions[i].name);*/ -#if HAVE_DLVSYM - *alsa_functions[i].func = - dlvsym(alsa_handle, alsa_functions[i].name, "ALSA_0.9"); - if (!*alsa_functions[i].func) -#endif - *alsa_functions[i].func = - dlsym(alsa_handle, alsa_functions[i].name); - if (!*alsa_functions[i].func) { - retval = -1; + int retval = 0; + if (alsa_handle == NULL) { + alsa_handle = dlopen(alsa_library, RTLD_NOW); + if (alsa_handle == NULL) { + retval = -1; + SDL_SetError("ALSA: dlopen('%s') failed: %s\n", + alsa_library, strerror(errno)); + } else { + retval = load_alsa_syms(); + if (retval < 0) { UnloadALSALibrary(); - break; } } } @@ -234,12 +185,12 @@ LoadALSALibrary(void) static void UnloadALSALibrary(void) { - return; } static int LoadALSALibrary(void) { + load_alsa_syms(); return 0; } @@ -262,80 +213,10 @@ get_audio_device(int channels) return device; } -/* Audio driver bootstrap functions */ - -static int -Audio_Available(void) -{ - int available; - int status; - snd_pcm_t *handle; - - available = 0; - if (LoadALSALibrary() < 0) { - return available; - } - status = - SDL_NAME(snd_pcm_open) (&handle, get_audio_device(2), - SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); - if (status >= 0) { - available = 1; - SDL_NAME(snd_pcm_close) (handle); - } - UnloadALSALibrary(); - return (available); -} - -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); - UnloadALSALibrary(); -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - LoadALSALibrary(); - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - /* Set the function pointers */ - this->OpenAudio = ALSA_OpenAudio; - this->WaitAudio = ALSA_WaitAudio; - this->PlayAudio = ALSA_PlayAudio; - this->GetAudioBuf = ALSA_GetAudioBuf; - this->CloseAudio = ALSA_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap ALSA_bootstrap = { - DRIVER_NAME, "ALSA 0.9 PCM audio", - Audio_Available, Audio_CreateDevice -}; /* This function waits until it is possible to write a full sound buffer */ static void -ALSA_WaitAudio(_THIS) +ALSA_WaitDevice(_THIS) { /* Check to see if the thread-parent process is still alive */ { @@ -343,8 +224,9 @@ ALSA_WaitAudio(_THIS) /* Note that this only works with thread implementations that use a different process id for each thread. */ - if (parent && (((++cnt) % 10) == 0)) { /* Check every 10 loops */ - if (kill(parent, 0) < 0) { + /* Check every 10 loops */ + if (this->hidden->parent && (((++cnt) % 10) == 0)) { + if (kill(this->hidden->parent, 0) < 0) { this->enabled = 0; } } @@ -352,13 +234,14 @@ ALSA_WaitAudio(_THIS) } +/* !!! FIXME: is there a channel swizzler in alsalib instead? */ /* * http://bugzilla.libsdl.org/show_bug.cgi?id=110 * "For Linux ALSA, this is FL-FR-RL-RR-C-LFE * and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-RL-RR" */ #define SWIZ6(T) \ - T *ptr = (T *) mixbuf; \ + T *ptr = (T *) this->hidden->mixbuf; \ const Uint32 count = (this->spec.samples / 6); \ Uint32 i; \ for (i = 0; i < count; i++, ptr += 6) { \ @@ -392,8 +275,8 @@ swizzle_alsa_channels_6_8bit(_THIS) /* - * Called right before feeding this->mixbuf to the hardware. Swizzle channels - * from Windows/Mac order to the format alsalib will want. + * Called right before feeding this->hidden->mixbuf to the hardware. Swizzle + * channels from Windows/Mac order to the format alsalib will want. */ static __inline__ void swizzle_alsa_channels(_THIS) @@ -415,7 +298,7 @@ swizzle_alsa_channels(_THIS) static void -ALSA_PlayAudio(_THIS) +ALSA_PlayDevice(_THIS) { int status; int sample_len; @@ -424,11 +307,12 @@ ALSA_PlayAudio(_THIS) swizzle_alsa_channels(this); sample_len = this->spec.samples; - sample_buf = (signed short *) mixbuf; + sample_buf = (signed short *) this->hidden->mixbuf; while (sample_len > 0) { - status = - SDL_NAME(snd_pcm_writei) (pcm_handle, sample_buf, sample_len); + status = ALSA_snd_pcm_writei(this->hidden->pcm_handle, + sample_buf, sample_len); + if (status < 0) { if (status == -EAGAIN) { SDL_Delay(1); @@ -437,11 +321,11 @@ ALSA_PlayAudio(_THIS) if (status == -ESTRPIPE) { do { SDL_Delay(1); - status = SDL_NAME(snd_pcm_resume) (pcm_handle); + status = ALSA_snd_pcm_resume(this->hidden->pcm_handle); } while (status == -EAGAIN); } if (status < 0) { - status = SDL_NAME(snd_pcm_prepare) (pcm_handle); + status = ALSA_snd_pcm_prepare(this->hidden->pcm_handle); } if (status < 0) { /* Hmm, not much we can do - abort */ @@ -456,74 +340,89 @@ ALSA_PlayAudio(_THIS) } static Uint8 * -ALSA_GetAudioBuf(_THIS) +ALSA_GetDeviceBuf(_THIS) { - return (mixbuf); + return (this->hidden->mixbuf); } static void -ALSA_CloseAudio(_THIS) +ALSA_CloseDevice(_THIS) { - if (mixbuf != NULL) { - SDL_FreeAudioMem(mixbuf); - mixbuf = NULL; - } - if (pcm_handle) { - SDL_NAME(snd_pcm_drain) (pcm_handle); - SDL_NAME(snd_pcm_close) (pcm_handle); - pcm_handle = NULL; + if (this->hidden != NULL) { + if (this->hidden->mixbuf != NULL) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + if (this->hidden->pcm_handle) { + ALSA_snd_pcm_drain(this->hidden->pcm_handle); + ALSA_snd_pcm_close(this->hidden->pcm_handle); + this->hidden->pcm_handle = NULL; + } + SDL_free(this->hidden); + this->hidden = NULL; } } static int -ALSA_OpenAudio(_THIS, SDL_AudioSpec * spec) +ALSA_OpenDevice(_THIS, const char *devname, int iscapture) { - int status; - snd_pcm_hw_params_t *hwparams; - snd_pcm_sw_params_t *swparams; - snd_pcm_format_t format; - snd_pcm_uframes_t frames; - SDL_AudioFormat test_format; + int status = 0; + snd_pcm_t *pcm_handle = NULL; + snd_pcm_hw_params_t *hwparams = NULL; + snd_pcm_sw_params_t *swparams = NULL; + snd_pcm_format_t format = 0; + snd_pcm_uframes_t frames = 0; + SDL_AudioFormat test_format = 0; + + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); /* Open the audio device */ /* Name of device should depend on # channels in spec */ - status = - SDL_NAME(snd_pcm_open) (&pcm_handle, - get_audio_device(spec->channels), - SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); + status = ALSA_snd_pcm_open(&pcm_handle, + get_audio_device(this->spec.channels), + SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (status < 0) { - SDL_SetError("Couldn't open audio device: %s", - SDL_NAME(snd_strerror) (status)); - return (-1); + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't open audio device: %s", + ALSA_snd_strerror(status)); + return 0; } + this->hidden->pcm_handle = pcm_handle; + /* Figure out what the hardware is capable of */ snd_pcm_hw_params_alloca(&hwparams); - status = SDL_NAME(snd_pcm_hw_params_any) (pcm_handle, hwparams); + status = ALSA_snd_pcm_hw_params_any(pcm_handle, hwparams); if (status < 0) { - SDL_SetError("Couldn't get hardware config: %s", - SDL_NAME(snd_strerror) (status)); - ALSA_CloseAudio(this); - return (-1); + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't get hardware config: %s", + ALSA_snd_strerror(status)); + return 0; } /* SDL only uses interleaved sample output */ - status = - SDL_NAME(snd_pcm_hw_params_set_access) (pcm_handle, hwparams, - SND_PCM_ACCESS_RW_INTERLEAVED); + status = ALSA_snd_pcm_hw_params_set_access(pcm_handle, hwparams, + SND_PCM_ACCESS_RW_INTERLEAVED); if (status < 0) { - SDL_SetError("Couldn't set interleaved access: %s", - SDL_NAME(snd_strerror) (status)); - ALSA_CloseAudio(this); - return (-1); + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't set interleaved access: %s", + ALSA_snd_strerror(status)); + return 0; } /* Try for a closest match on audio format */ status = -1; - for (test_format = SDL_FirstAudioFormat(spec->format); + for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format && (status < 0);) { - status = 0; /* if we can't support a format, it'll become -1. */ + status = 0; /* if we can't support a format, it'll become -1. */ switch (test_format) { case AUDIO_U8: format = SND_PCM_FORMAT_U8; @@ -560,131 +459,151 @@ ALSA_OpenAudio(_THIS, SDL_AudioSpec * spec) break; } if (status >= 0) { - status = - SDL_NAME(snd_pcm_hw_params_set_format) (pcm_handle, - hwparams, format); + status = ALSA_snd_pcm_hw_params_set_format(pcm_handle, + hwparams, format); } if (status < 0) { test_format = SDL_NextAudioFormat(); } } if (status < 0) { - SDL_SetError("Couldn't find any hardware audio formats"); - ALSA_CloseAudio(this); - return (-1); + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't find any hardware audio formats"); + return 0; } - spec->format = test_format; + this->spec.format = test_format; /* Set the number of channels */ - status = - SDL_NAME(snd_pcm_hw_params_set_channels) (pcm_handle, hwparams, - spec->channels); + status = ALSA_snd_pcm_hw_params_set_channels(pcm_handle, hwparams, + this->spec.channels); if (status < 0) { - status = SDL_NAME(snd_pcm_hw_params_get_channels) (hwparams); + status = ALSA_snd_pcm_hw_params_get_channels(hwparams); if ((status <= 0) || (status > 2)) { - SDL_SetError("Couldn't set audio channels"); - ALSA_CloseAudio(this); - return (-1); + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't set audio channels"); + return 0; } - spec->channels = status; + this->spec.channels = status; } /* Set the audio rate */ - status = - SDL_NAME(snd_pcm_hw_params_set_rate_near) (pcm_handle, hwparams, - spec->freq, NULL); + status = ALSA_snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, + this->spec.freq, NULL); if (status < 0) { - SDL_SetError("Couldn't set audio frequency: %s", - SDL_NAME(snd_strerror) (status)); - ALSA_CloseAudio(this); - return (-1); + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't set audio frequency: %s", + ALSA_snd_strerror(status)); + return 0; } - spec->freq = status; + this->spec.freq = status; /* Set the buffer size, in samples */ - frames = spec->samples; - frames = - SDL_NAME(snd_pcm_hw_params_set_period_size_near) (pcm_handle, - hwparams, frames, - NULL); - spec->samples = frames; - SDL_NAME(snd_pcm_hw_params_set_periods_near) (pcm_handle, hwparams, 2, - NULL); + frames = this->spec.samples; + frames = ALSA_snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, + frames, NULL); + this->spec.samples = frames; + ALSA_snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, 2, NULL); /* "set" the hardware with the desired parameters */ - status = SDL_NAME(snd_pcm_hw_params) (pcm_handle, hwparams); + status = ALSA_snd_pcm_hw_params(pcm_handle, hwparams); if (status < 0) { - SDL_SetError("Couldn't set hardware audio parameters: %s", - SDL_NAME(snd_strerror) (status)); - ALSA_CloseAudio(this); - return (-1); + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't set hardware audio parameters: %s", + ALSA_snd_strerror(status)); + return 0; } -/* This is useful for debugging... */ -/* -{ snd_pcm_sframes_t bufsize; int fragments; - bufsize = SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams); - fragments = SDL_NAME(snd_pcm_hw_params_get_periods)(hwparams); - - fprintf(stderr, "ALSA: bufsize = %ld, fragments = %d\n", bufsize, fragments); +#if AUDIO_DEBUG +{ + snd_pcm_sframes_t bufsize; + int fragments; + bufsize = ALSA_snd_pcm_hw_params_get_period_size(hwparams); + fragments = ALSA_snd_pcm_hw_params_get_periods(hwparams); + fprintf(stderr,"ALSA: bufsize = %ld, fragments = %d\n",bufsize,fragments); } -*/ +#endif /* Set the software parameters */ snd_pcm_sw_params_alloca(&swparams); - status = SDL_NAME(snd_pcm_sw_params_current) (pcm_handle, swparams); + status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams); if (status < 0) { - SDL_SetError("Couldn't get software config: %s", - SDL_NAME(snd_strerror) (status)); - ALSA_CloseAudio(this); - return (-1); + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't get software config: %s", + ALSA_snd_strerror(status)); + return 0; } - status = - SDL_NAME(snd_pcm_sw_params_set_start_threshold) (pcm_handle, - swparams, 0); + status = ALSA_snd_pcm_sw_params_set_start_threshold(pcm_handle,swparams,0); if (status < 0) { - SDL_SetError("Couldn't set start threshold: %s", - SDL_NAME(snd_strerror) (status)); - ALSA_CloseAudio(this); - return (-1); + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't set start threshold: %s", + ALSA_snd_strerror(status)); + return 0; } - status = - SDL_NAME(snd_pcm_sw_params_set_avail_min) (pcm_handle, swparams, - frames); + status = ALSA_snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, frames); if (status < 0) { - SDL_SetError("Couldn't set avail min: %s", - SDL_NAME(snd_strerror) (status)); - ALSA_CloseAudio(this); - return (-1); + ALSA_CloseDevice(this); + SDL_SetError("Couldn't set avail min: %s", ALSA_snd_strerror(status)); + return 0; } - status = SDL_NAME(snd_pcm_sw_params) (pcm_handle, swparams); + status = ALSA_snd_pcm_sw_params(pcm_handle, swparams); if (status < 0) { + ALSA_CloseDevice(this); SDL_SetError("Couldn't set software audio parameters: %s", - SDL_NAME(snd_strerror) (status)); - ALSA_CloseAudio(this); - return (-1); + ALSA_snd_strerror(status)); + return 0; } /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Allocate mixing buffer */ - mixlen = spec->size; - mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen); - if (mixbuf == NULL) { - ALSA_CloseAudio(this); - return (-1); + this->hidden->mixlen = this->spec.size; + this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); + if (this->hidden->mixbuf == NULL) { + ALSA_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } - SDL_memset(mixbuf, spec->silence, spec->size); + SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); /* Get the parent process id (we're the parent of the audio thread) */ - parent = getpid(); + this->hidden->parent = getpid(); /* Switch to blocking mode for playback */ - SDL_NAME(snd_pcm_nonblock) (pcm_handle, 0); + ALSA_snd_pcm_nonblock(pcm_handle, 0); /* We're ready to rock and roll. :-) */ - return (0); + return 1; +} + +static void +ALSA_Deinitialize(void) +{ + UnloadALSALibrary(); } +static int +ALSA_Init(SDL_AudioDriverImpl *impl) +{ + if (LoadALSALibrary() < 0) { + return 0; + } + + /* Set the function pointers */ + impl->OpenDevice = ALSA_OpenDevice; + impl->WaitDevice = ALSA_WaitDevice; + impl->GetDeviceBuf = ALSA_GetDeviceBuf; + impl->PlayDevice = ALSA_PlayDevice; + impl->CloseDevice = ALSA_CloseDevice; + impl->Deinitialize = ALSA_Deinitialize; + impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: Add device enum! */ + + return 1; +} + + +AudioBootStrap ALSA_bootstrap = { + DRIVER_NAME, "ALSA 0.9 PCM audio", ALSA_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/alsa/SDL_alsa_audio.h b/src/audio/alsa/SDL_alsa_audio.h index aa2eb786a..396514705 100644 --- a/src/audio/alsa/SDL_alsa_audio.h +++ b/src/audio/alsa/SDL_alsa_audio.h @@ -30,7 +30,7 @@ #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData @@ -46,11 +46,5 @@ struct SDL_PrivateAudioData int mixlen; }; -/* Old variable names */ -#define pcm_handle (this->hidden->pcm_handle) -#define parent (this->hidden->parent) -#define mixbuf (this->hidden->mixbuf) -#define mixlen (this->hidden->mixlen) - #endif /* _ALSA_PCM_audio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/amigaos/SDL_ahiaudio.c b/src/audio/amigaos/SDL_ahiaudio.c deleted file mode 100644 index 7368d0739..000000000 --- a/src/audio/amigaos/SDL_ahiaudio.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2006 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Sam Lantinga - slouken@libsdl.org -*/ -#include "SDL_config.h" - -/* Allow access to a raw mixing buffer (for AmigaOS) */ - -#include "SDL_audio.h" -#include "../SDL_audio_c.h" -#include "SDL_ahiaudio.h" - -/* Audio driver functions */ -static int AHI_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void AHI_WaitAudio(_THIS); -static void AHI_PlayAudio(_THIS); -static Uint8 *AHI_GetAudioBuf(_THIS); -static void AHI_CloseAudio(_THIS); - -#ifndef __SASC -#define mymalloc(x) AllocVec(x,MEMF_PUBLIC) -#define myfree FreeVec -#else -#define mymalloc malloc -#define myfree free -#endif - -/* Audio driver bootstrap functions */ - -static int -Audio_Available(void) -{ - int ok = 0; - struct MsgPort *p; - struct AHIRequest *req; - - if (p = CreateMsgPort()) { - if (req = - (struct AHIRequest *) CreateIORequest(p, - sizeof(struct - AHIRequest))) { - req->ahir_Version = 4; - - if (!OpenDevice(AHINAME, 0, (struct IORequest *) req, NULL)) { - D(bug("AHI available.\n")); - ok = 1; - CloseDevice((struct IORequest *) req); - } - DeleteIORequest((struct IORequest *) req); - } - DeleteMsgPort(p); - } - - D(if (!ok) bug("AHI not available\n")); - return ok; -} - -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - -#ifndef NO_AMIGADEBUG - D(bug("AHI created...\n")); -#endif - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - /* Set the function pointers */ - this->OpenAudio = AHI_OpenAudio; - this->WaitAudio = AHI_WaitAudio; - this->PlayAudio = AHI_PlayAudio; - this->GetAudioBuf = AHI_GetAudioBuf; - this->CloseAudio = AHI_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap AHI_bootstrap = { - "AHI", Audio_Available, Audio_CreateDevice -}; - - -void static -AHI_WaitAudio(_THIS) -{ - if (!CheckIO((struct IORequest *) audio_req[current_buffer])) { - WaitIO((struct IORequest *) audio_req[current_buffer]); -// AbortIO((struct IORequest *)audio_req[current_buffer]); - } -} - -static void -AHI_PlayAudio(_THIS) -{ - if (playing > 1) - WaitIO((struct IORequest *) audio_req[current_buffer]); - - /* Write the audio data out */ - audio_req[current_buffer]->ahir_Std.io_Message.mn_Node.ln_Pri = 60; - audio_req[current_buffer]->ahir_Std.io_Data = mixbuf[current_buffer]; - audio_req[current_buffer]->ahir_Std.io_Length = this->hidden->size; - audio_req[current_buffer]->ahir_Std.io_Offset = 0; - audio_req[current_buffer]->ahir_Std.io_Command = CMD_WRITE; - audio_req[current_buffer]->ahir_Frequency = this->hidden->freq; - audio_req[current_buffer]->ahir_Volume = 0x10000; - audio_req[current_buffer]->ahir_Type = this->hidden->type; - audio_req[current_buffer]->ahir_Position = 0x8000; - audio_req[current_buffer]->ahir_Link = - (playing > 0 ? audio_req[current_buffer ^ 1] : NULL); - - SendIO((struct IORequest *) audio_req[current_buffer]); - current_buffer ^= 1; - - playing++; -} - -static Uint8 * -AHI_GetAudioBuf(_THIS) -{ - return (mixbuf[current_buffer]); -} - -static void -AHI_CloseAudio(_THIS) -{ - D(bug("Closing audio...\n")); - - playing = 0; - - if (audio_req[0]) { - if (audio_req[1]) { - D(bug("Break req[1]...\n")); - - AbortIO((struct IORequest *) audio_req[1]); - WaitIO((struct IORequest *) audio_req[1]); - } - - D(bug("Break req[0]...\n")); - - AbortIO((struct IORequest *) audio_req[0]); - WaitIO((struct IORequest *) audio_req[0]); - - if (audio_req[1]) { - D(bug("Break AGAIN req[1]...\n")); - AbortIO((struct IORequest *) audio_req[1]); - WaitIO((struct IORequest *) audio_req[1]); - } -// Double abort to be sure to break the dbuffering process. - - SDL_Delay(200); - - D(bug("Reqs breaked, closing device...\n")); - CloseDevice((struct IORequest *) audio_req[0]); - D(bug("Device closed, freeing memory...\n")); - myfree(audio_req[1]); - D(bug("Memory freed, deleting IOReq...\n")); - DeleteIORequest((struct IORequest *) audio_req[0]); - audio_req[0] = audio_req[1] = NULL; - } - - D(bug("Freeing mixbuf[0]...\n")); - if (mixbuf[0] != NULL) { - myfree(mixbuf[0]); -// SDL_FreeAudioMem(mixbuf[0]); - mixbuf[0] = NULL; - } - - D(bug("Freeing mixbuf[1]...\n")); - if (mixbuf[1] != NULL) { - myfree(mixbuf[1]); -// SDL_FreeAudioMem(mixbuf[1]); - mixbuf[1] = NULL; - } - - D(bug("Freeing audio_port...\n")); - - if (audio_port != NULL) { - DeleteMsgPort(audio_port); - audio_port = NULL; - } - D(bug("...done!\n")); -} - -static int -AHI_OpenAudio(_THIS, SDL_AudioSpec * spec) -{ -// int width; - SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format); - int valid_datatype = 1; - - D(bug("AHI opening...\n")); - - /* Determine the audio parameters from the AudioSpec */ - while ((!valid_datatype) && (test_format)) { - valid_datatype = 1; - switch (test_format) { - case AUDIO_S8: - D(bug("AUDIO_S8...\n")); - spec->format = AUDIO_S8; - this->hidden->bytespersample = 1; - if (spec->channels < 2) - this->hidden->type = AHIST_M8S; - else - this->hidden->type = AHIST_S8S; - break; - - case AUDIO_S16MSB: - D(bug("AUDIO_S16MSB...\n")); - spec->format = AUDIO_S16MSB; - this->hidden->bytespersample = 2; - if (spec->channels < 2) - this->hidden->type = AHIST_M16S; - else - this->hidden->type = AHIST_S16S; - break; - - case AUDIO_S32MSB: - D(bug("AUDIO_S32MSB...\n")); - spec->format = AUDIO_S32MSB; - this->hidden->bytespersample = 4; - if (spec->channels < 2) - this->hidden->type = AHIST_M32S; - else - this->hidden->type = AHIST_S32S; - break; - - default: - valid_datatype = 0; - test_format = SDL_NextAudioFormat(); - break; - } - } - - if (!valid_datatype) { /* shouldn't happen, but just in case... */ - SDL_SetError("Unsupported audio format"); - return (-1); - } - - if (spec->channels > 2) { - spec->channels = 2; /* will convert at higher level. */ - } - - D(bug("Before CalculateAudioSpec\n")); - /* Update the fragment size as size in bytes */ - SDL_CalculateAudioSpec(spec); - - D(bug("Before CreateMsgPort\n")); - - if (!(audio_port = CreateMsgPort())) { - SDL_SetError("Unable to create a MsgPort"); - return -1; - } - - D(bug("Before CreateIORequest\n")); - - if (! - (audio_req[0] = - (struct AHIRequest *) CreateIORequest(audio_port, - sizeof(struct AHIRequest)))) { - SDL_SetError("Unable to create an AHIRequest"); - DeleteMsgPort(audio_port); - return -1; - } - - audio_req[0]->ahir_Version = 4; - - if (OpenDevice(AHINAME, 0, (struct IORequest *) audio_req[0], NULL)) { - SDL_SetError("Unable to open AHI device!\n"); - DeleteIORequest((struct IORequest *) audio_req[0]); - DeleteMsgPort(audio_port); - return -1; - } - - D(bug("AFTER opendevice\n")); - - /* Set output frequency and size */ - this->hidden->freq = spec->freq; - this->hidden->size = spec->size; - - D(bug("Before buffer allocation\n")); - - /* Allocate mixing buffer */ - mixbuf[0] = (Uint8 *) mymalloc(spec->size); - mixbuf[1] = (Uint8 *) mymalloc(spec->size); - - D(bug("Before audio_req allocation\n")); - - if (!(audio_req[1] = mymalloc(sizeof(struct AHIRequest)))) { - SDL_OutOfMemory(); - return (-1); - } - - D(bug("Before audio_req memcpy\n")); - - SDL_memcpy(audio_req[1], audio_req[0], sizeof(struct AHIRequest)); - - if (mixbuf[0] == NULL || mixbuf[1] == NULL) { - SDL_OutOfMemory(); - return (-1); - } - - D(bug("Before mixbuf memset\n")); - - SDL_memset(mixbuf[0], spec->silence, spec->size); - SDL_memset(mixbuf[1], spec->silence, spec->size); - - current_buffer = 0; - playing = 0; - - D(bug - ("AHI opened: freq:%ld mixbuf:%lx/%lx buflen:%ld bits:%ld channels:%ld\n", - spec->freq, mixbuf[0], mixbuf[1], spec->size, - this->hidden->bytespersample * 8, spec->channels)); - - /* We're ready to rock and roll. :-) */ - return (0); -} - -/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/amigaos/SDL_ahiaudio.h b/src/audio/amigaos/SDL_ahiaudio.h deleted file mode 100644 index 7e311daa6..000000000 --- a/src/audio/amigaos/SDL_ahiaudio.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2006 Sam Lantinga - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Sam Lantinga - slouken@libsdl.org -*/ -#include "SDL_config.h" - -#ifndef _SDL_ahiaudio_h -#define _SDL_ahiaudio_h - -#include -#include -#ifdef __SASC -#include -#else -#include -#endif - -#include -#include "mydebug.h" - -#include "../SDL_sysaudio.h" - -/* Hidden "this" pointer for the audio functions */ -#define _THIS SDL_AudioDevice *this - -struct SDL_PrivateAudioData -{ - /* The handle for the audio device */ - struct AHIRequest *audio_req[2]; - struct MsgPort *audio_port; - Sint32 freq, type, bytespersample, size; - Uint8 *mixbuf[2]; /* The app mixing buffer */ - int current_buffer; - Uint32 playing; -}; - -/* Old variable names */ -#define audio_port (this->hidden->audio_port) -#define audio_req (this->hidden->audio_req) -#define mixbuf (this->hidden->mixbuf) -#define current_buffer (this->hidden->current_buffer) -#define playing (this->hidden->playing) - -#endif /* _SDL_ahiaudio_h */ -/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/arts/SDL_artsaudio.c b/src/audio/arts/SDL_artsaudio.c index 038d4de60..5fb803959 100644 --- a/src/audio/arts/SDL_artsaudio.c +++ b/src/audio/arts/SDL_artsaudio.c @@ -27,7 +27,6 @@ #include "SDL_audio.h" #include "../SDL_audiomem.h" #include "../SDL_audio_c.h" -#include "../SDL_audiodev_c.h" #include "SDL_artsaudio.h" #ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC @@ -40,19 +39,12 @@ /* The tag name used by artsc audio */ #define ARTS_DRIVER_NAME "arts" -/* Audio driver functions */ -static int ARTS_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void ARTS_WaitAudio(_THIS); -static void ARTS_PlayAudio(_THIS); -static Uint8 *ARTS_GetAudioBuf(_THIS); -static void ARTS_CloseAudio(_THIS); - #ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC static const char *arts_library = SDL_AUDIO_DRIVER_ARTS_DYNAMIC; static void *arts_handle = NULL; -static int arts_loaded = 0; +/* !!! FIXME: I hate this SDL_NAME clutter...it makes everything so messy! */ static int (*SDL_NAME(arts_init)) (void); static void (*SDL_NAME(arts_free)) (void); static arts_stream_t(*SDL_NAME(arts_play_stream)) (int rate, int bits, @@ -65,28 +57,32 @@ static int (*SDL_NAME(arts_stream_get)) (arts_stream_t s, static int (*SDL_NAME(arts_write)) (arts_stream_t s, const void *buffer, int count); static void (*SDL_NAME(arts_close_stream)) (arts_stream_t s); +static void (*SDL_NAME(arts_close_stream)) (arts_stream_t s); +static const char *(*SDL_NAME(arts_error_text)) (int errorcode); +#define SDL_ARTS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) } static struct { const char *name; void **func; } arts_functions[] = { - { - "arts_init", (void **) &SDL_NAME(arts_init)}, { - "arts_free", (void **) &SDL_NAME(arts_free)}, { - "arts_play_stream", (void **) &SDL_NAME(arts_play_stream)}, { - "arts_stream_set", (void **) &SDL_NAME(arts_stream_set)}, { - "arts_stream_get", (void **) &SDL_NAME(arts_stream_get)}, { - "arts_write", (void **) &SDL_NAME(arts_write)}, { -"arts_close_stream", (void **) &SDL_NAME(arts_close_stream)},}; + SDL_ARTS_SYM(arts_init), + SDL_ARTS_SYM(arts_free), + SDL_ARTS_SYM(arts_play_stream), + SDL_ARTS_SYM(arts_stream_set), + SDL_ARTS_SYM(arts_stream_get), + SDL_ARTS_SYM(arts_write), + SDL_ARTS_SYM(arts_close_stream), + SDL_ARTS_SYM(arts_error_text), +}; +#undef SDL_ARTS_SYM static void UnloadARTSLibrary() { - if (arts_loaded) { + if (arts_handle != NULL) { SDL_UnloadObject(arts_handle); arts_handle = NULL; - arts_loaded = 0; } } @@ -95,20 +91,22 @@ LoadARTSLibrary(void) { int i, retval = -1; - arts_handle = SDL_LoadObject(arts_library); - if (arts_handle) { - arts_loaded = 1; - retval = 0; - for (i = 0; i < SDL_arraysize(arts_functions); ++i) { - *arts_functions[i].func = - SDL_LoadFunction(arts_handle, arts_functions[i].name); - if (!*arts_functions[i].func) { - retval = -1; - UnloadARTSLibrary(); - break; + if (arts_handle == NULL) { + arts_handle = SDL_LoadObject(arts_library); + if (arts_handle != NULL) { + retval = 0; + for (i = 0; i < SDL_arraysize(arts_functions); ++i) { + *arts_functions[i].func = + SDL_LoadFunction(arts_handle, arts_functions[i].name); + if (!*arts_functions[i].func) { + retval = -1; + UnloadARTSLibrary(); + break; + } } } } + return retval; } @@ -128,117 +126,45 @@ LoadARTSLibrary(void) #endif /* SDL_AUDIO_DRIVER_ARTS_DYNAMIC */ -/* Audio driver bootstrap functions */ - -static int -Audio_Available(void) -{ - int available = 0; - - if (LoadARTSLibrary() < 0) { - return available; - } - if (SDL_NAME(arts_init) () == 0) { -#define ARTS_CRASH_HACK /* Play a stream so aRts doesn't crash */ -#ifdef ARTS_CRASH_HACK - arts_stream_t stream2; - stream2 = SDL_NAME(arts_play_stream) (44100, 16, 2, "SDL"); - SDL_NAME(arts_write) (stream2, "", 0); - SDL_NAME(arts_close_stream) (stream2); -#endif - available = 1; - SDL_NAME(arts_free) (); - } - UnloadARTSLibrary(); - - return available; -} - -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); - UnloadARTSLibrary(); -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - LoadARTSLibrary(); - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - stream = 0; - - /* Set the function pointers */ - this->OpenAudio = ARTS_OpenAudio; - this->WaitAudio = ARTS_WaitAudio; - this->PlayAudio = ARTS_PlayAudio; - this->GetAudioBuf = ARTS_GetAudioBuf; - this->CloseAudio = ARTS_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap ARTS_bootstrap = { - ARTS_DRIVER_NAME, "Analog Realtime Synthesizer", - Audio_Available, Audio_CreateDevice -}; - /* This function waits until it is possible to write a full sound buffer */ static void -ARTS_WaitAudio(_THIS) +ARTS_WaitDevice(_THIS) { Sint32 ticks; /* Check to see if the thread-parent process is still alive */ { static int cnt = 0; - /* Note that this only works with thread implementations + /* Note that this only works with thread implementations that use a different process id for each thread. */ - if (parent && (((++cnt) % 10) == 0)) { /* Check every 10 loops */ - if (kill(parent, 0) < 0) { + /* Check every 10 loops */ + if (this->hidden->parent && (((++cnt) % 10) == 0)) { + if (kill(this->hidden->parent, 0) < 0) { this->enabled = 0; } } } /* Use timer for general audio synchronization */ - ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS; + ticks = ((Sint32) (this->hidden->next_frame-SDL_GetTicks())) - FUDGE_TICKS; if (ticks > 0) { SDL_Delay(ticks); } } static void -ARTS_PlayAudio(_THIS) +ARTS_PlayDevice(_THIS) { - int written; - /* Write the audio data */ - written = SDL_NAME(arts_write) (stream, mixbuf, mixlen); + int written = SDL_NAME(arts_write) ( + this->hidden->stream, + this->hidden->mixbuf, + this->hidden->mixlen); /* If timer synchronization is enabled, set the next write frame */ - if (frame_ticks) { - next_frame += frame_ticks; + if (this->hidden->frame_ticks) { + this->hidden->next_frame += this->hidden->frame_ticks; } /* If we couldn't write, assume fatal error for now */ @@ -250,41 +176,57 @@ ARTS_PlayAudio(_THIS) #endif } +static void +ARTS_WaitDone(_THIS) +{ + /* !!! FIXME: camp here until buffer drains... SDL_Delay(???); */ +} + + static Uint8 * -ARTS_GetAudioBuf(_THIS) +ARTS_GetDeviceBuf(_THIS) { - return (mixbuf); + return (this->hidden->mixbuf); } + static void -ARTS_CloseAudio(_THIS) +ARTS_CloseDevice(_THIS) { - if (mixbuf != NULL) { - SDL_FreeAudioMem(mixbuf); - mixbuf = NULL; - } - if (stream) { - SDL_NAME(arts_close_stream) (stream); - stream = 0; + if (this->hidden != NULL) { + if (this->hidden->mixbuf != NULL) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + if (this->hidden->stream) { + SDL_NAME(arts_close_stream) (this->hidden->stream); + this->hidden->stream = 0; + } + SDL_NAME(arts_free) (); + SDL_free(this->hidden); + this->hidden = NULL; } - SDL_NAME(arts_free) (); } + static int -ARTS_OpenAudio(_THIS, SDL_AudioSpec * spec) +ARTS_OpenDevice(_THIS, const char *devname, int iscapture) { - int bits, frag_spec; - SDL_AudioFormat test_format, format; - - /* Reset the timer synchronization flag */ - frame_ticks = 0.0; + int rc = 0; + int bits = 0, frag_spec = 0; + SDL_AudioFormat test_format = 0, format = 0; - mixbuf = NULL; + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); /* Try for a closest match on audio format */ - format = 0; - bits = 0; - for (test_format = SDL_FirstAudioFormat(spec->format); + for (test_format = SDL_FirstAudioFormat(this->spec.format); !format && test_format;) { #ifdef DEBUG_AUDIO fprintf(stderr, "Trying format 0x%4.4x\n", test_format); @@ -307,51 +249,108 @@ ARTS_OpenAudio(_THIS, SDL_AudioSpec * spec) } } if (format == 0) { + ARTS_CloseDevice(this); SDL_SetError("Couldn't find any hardware audio formats"); - return (-1); + return 0; } - spec->format = test_format; + this->spec.format = test_format; - if (SDL_NAME(arts_init) () != 0) { - SDL_SetError("Unable to initialize ARTS"); - return (-1); + if ((rc = SDL_NAME(arts_init) ()) != 0) { + ARTS_CloseDevice(this); + SDL_SetError( "Unable to initialize ARTS: %s", + SDL_NAME(arts_error_text)(rc) ); + return 0; } - stream = - SDL_NAME(arts_play_stream) (spec->freq, bits, spec->channels, "SDL"); + this->hidden->stream = SDL_NAME(arts_play_stream) ( + this->spec.freq, + bits, this->spec.channels, + "SDL"); /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Determine the power of two of the fragment size */ - for (frag_spec = 0; (0x01 << frag_spec) < spec->size; ++frag_spec); - if ((0x01 << frag_spec) != spec->size) { + for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec); + if ((0x01 << frag_spec) != this->spec.size) { + ARTS_CloseDevice(this); SDL_SetError("Fragment size must be a power of two"); - return (-1); + return 0; } frag_spec |= 0x00020000; /* two fragments, for low latency */ #ifdef ARTS_P_PACKET_SETTINGS - SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_SETTINGS, frag_spec); + SDL_NAME(arts_stream_set) (this->hidden->stream, + ARTS_P_PACKET_SETTINGS, frag_spec); #else - SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_SIZE, + SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_SIZE, frag_spec & 0xffff); - SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_COUNT, frag_spec >> 16); + SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_COUNT, + frag_spec >> 16); #endif - spec->size = SDL_NAME(arts_stream_get) (stream, ARTS_P_PACKET_SIZE); + this->spec.size = SDL_NAME(arts_stream_get) (this->hidden->stream, + ARTS_P_PACKET_SIZE); /* Allocate mixing buffer */ - mixlen = spec->size; - mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen); - if (mixbuf == NULL) { - return (-1); + this->hidden->mixlen = this->spec.size; + this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); + if (this->hidden->mixbuf == NULL) { + ARTS_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } - SDL_memset(mixbuf, spec->silence, spec->size); + SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); /* Get the parent process id (we're the parent of the audio thread) */ - parent = getpid(); + this->hidden->parent = getpid(); /* We're ready to rock and roll. :-) */ - return (0); + return 1; } + +static void +ARTS_Deinitialize(void) +{ + UnloadARTSLibrary(); +} + + +static int +ARTS_Init(SDL_AudioDriverImpl *impl) +{ + if (LoadARTSLibrary() < 0) { + return 0; + } else { + if (SDL_NAME(arts_init) () != 0) { + UnloadARTSLibrary(); + SDL_SetError("ARTS: arts_init failed (no audio server?)"); + return 0; + } + + /* Play a stream so aRts doesn't crash */ + arts_stream_t stream; + stream = SDL_NAME(arts_play_stream) (44100, 16, 2, "SDL"); + SDL_NAME(arts_write) (stream, "", 0); + SDL_NAME(arts_close_stream) (stream); + SDL_NAME(arts_free) (); + } + + /* Set the function pointers */ + impl->OpenDevice = ARTS_OpenDevice; + impl->PlayDevice = ARTS_PlayDevice; + impl->WaitDevice = ARTS_WaitDevice; + impl->GetDeviceBuf = ARTS_GetDeviceBuf; + impl->CloseDevice = ARTS_CloseDevice; + impl->WaitDone = ARTS_WaitDone; + impl->Deinitialize = ARTS_Deinitialize; + impl->OnlyHasDefaultOutputDevice = 1; + + return 1; +} + + +AudioBootStrap ARTS_bootstrap = { + ARTS_DRIVER_NAME, "Analog RealTime Synthesizer", ARTS_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/arts/SDL_artsaudio.h b/src/audio/arts/SDL_artsaudio.h index 3f0c68c63..828c98a2f 100644 --- a/src/audio/arts/SDL_artsaudio.h +++ b/src/audio/arts/SDL_artsaudio.h @@ -28,7 +28,7 @@ #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData @@ -49,13 +49,5 @@ struct SDL_PrivateAudioData }; #define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */ -/* Old variable names */ -#define stream (this->hidden->stream) -#define parent (this->hidden->parent) -#define mixbuf (this->hidden->mixbuf) -#define mixlen (this->hidden->mixlen) -#define frame_ticks (this->hidden->frame_ticks) -#define next_frame (this->hidden->next_frame) - #endif /* _SDL_artscaudio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/baudio/SDL_beaudio.cc b/src/audio/baudio/SDL_beaudio.cc index ed14100b1..5e2ba647b 100644 --- a/src/audio/baudio/SDL_beaudio.cc +++ b/src/audio/baudio/SDL_beaudio.cc @@ -36,138 +36,81 @@ extern "C" #include "../../thread/beos/SDL_systhread_c.h" #include "SDL_beaudio.h" +} -/* Audio driver functions */ - static int BE_OpenAudio(_THIS, SDL_AudioSpec * spec); - static void BE_WaitAudio(_THIS); - static void BE_PlayAudio(_THIS); - static Uint8 *BE_GetAudioBuf(_THIS); - static void BE_CloseAudio(_THIS); -/* Audio driver bootstrap functions */ - - static int Audio_Available(void) - { - return (1); - } - - static void Audio_DeleteDevice(SDL_AudioDevice * device) - { - SDL_free(device->hidden); - SDL_free(device); - } - - static SDL_AudioDevice *Audio_CreateDevice(int devindex) - { - SDL_AudioDevice *device; - - /* Initialize all variables that we clean on shutdown */ - device = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (device) { - SDL_memset(device, 0, (sizeof *device)); - device->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *device->hidden)); - } - if ((device == NULL) || (device->hidden == NULL)) { - SDL_OutOfMemory(); - if (device) { - SDL_free(device); - } - return (0); - } - SDL_memset(device->hidden, 0, (sizeof *device->hidden)); - - /* Set the function pointers */ - device->OpenAudio = BE_OpenAudio; - device->WaitAudio = BE_WaitAudio; - device->PlayAudio = BE_PlayAudio; - device->GetAudioBuf = BE_GetAudioBuf; - device->CloseAudio = BE_CloseAudio; - - device->free = Audio_DeleteDevice; +/* !!! FIXME: have the callback call the higher level to avoid code dupe. */ +/* The BeOS callback for handling the audio buffer */ +static void +FillSound(void *device, void *stream, size_t len, + const media_raw_audio_format & format) +{ + SDL_AudioDevice *audio = (SDL_AudioDevice *) device; - return device; - } + /* Silence the buffer, since it's ours */ + SDL_memset(stream, audio->spec.silence, len); - AudioBootStrap BAUDIO_bootstrap = { - "baudio", "BeOS BSoundPlayer", - Audio_Available, Audio_CreateDevice - }; + /* Only do soemthing if audio is enabled */ + if (!audio->enabled) + return; -/* The BeOS callback for handling the audio buffer */ - static void FillSound(void *device, void *stream, size_t len, - const media_raw_audio_format & format) - { - SDL_AudioDevice *audio = (SDL_AudioDevice *) device; - - /* Silence the buffer, since it's ours */ - SDL_memset(stream, audio->spec.silence, len); - - /* Only do soemthing if audio is enabled */ - if (!audio->enabled) - return; - - if (!audio->paused) { - if (audio->convert.needed) { - SDL_mutexP(audio->mixer_lock); - (*audio->spec.callback) (audio->spec.userdata, + if (!audio->paused) { + if (audio->convert.needed) { + SDL_mutexP(audio->mixer_lock); + (*audio->spec.callback) (audio->spec.userdata, (Uint8 *) audio->convert.buf, audio->convert.len); - SDL_mutexV(audio->mixer_lock); - SDL_ConvertAudio(&audio->convert); - SDL_memcpy(stream, audio->convert.buf, - audio->convert.len_cvt); - } else { - SDL_mutexP(audio->mixer_lock); - (*audio->spec.callback) (audio->spec.userdata, - (Uint8 *) stream, len); - SDL_mutexV(audio->mixer_lock); - } + SDL_mutexV(audio->mixer_lock); + SDL_ConvertAudio(&audio->convert); + SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt); + } else { + SDL_mutexP(audio->mixer_lock); + (*audio->spec.callback) (audio->spec.userdata, + (Uint8 *) stream, len); + SDL_mutexV(audio->mixer_lock); } - return; } +} -/* Dummy functions -- we don't use thread-based audio */ - void BE_WaitAudio(_THIS) - { - return; - } - void BE_PlayAudio(_THIS) - { - return; - } - Uint8 *BE_GetAudioBuf(_THIS) - { - return (NULL); - } - - void BE_CloseAudio(_THIS) - { - if (audio_obj) { - audio_obj->Stop(); - delete audio_obj; - audio_obj = NULL; +static void +BEOSAUDIO_CloseDevice(_THIS) +{ + if (_this->hidden != NULL) { + if (_this->hidden->audio_obj) { + _this->hidden->audio_obj->Stop(); + delete _this->hidden->audio_obj; + _this->hidden->audio_obj = NULL; } - /* Quit the Be Application, if there's nothing left to do */ - SDL_QuitBeApp(); + delete _this->hidden; + _this->hidden = NULL; } +} - int BE_OpenAudio(_THIS, SDL_AudioSpec * spec) - { - int valid_datatype = 0; - media_raw_audio_format format; - SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format); - - /* Parse the audio format and fill the Be raw audio format */ - memset(&format, '\0', sizeof(media_raw_audio_format)); - format.byte_order = B_MEDIA_LITTLE_ENDIAN; - format.frame_rate = (float) spec->freq; - format.channel_count = spec->channels; /* !!! FIXME: support > 2? */ - while ((!valid_datatype) && (test_format)) { - valid_datatype = 1; - spec->format = test_format; - switch (test_format) { +static int +BEOSAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) +{ + int valid_datatype = 0; + media_raw_audio_format format; + SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format); + + /* Initialize all variables that we clean on shutdown */ + _this->hidden = new SDL_PrivateAudioData; + if (_this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(_this->hidden, 0, (sizeof *_this->hidden)); + + /* Parse the audio format and fill the Be raw audio format */ + SDL_memset(&format, '\0', sizeof(media_raw_audio_format)); + format.byte_order = B_MEDIA_LITTLE_ENDIAN; + format.frame_rate = (float) _this->spec.freq; + format.channel_count = _this->spec.channels; /* !!! FIXME: support > 2? */ + while ((!valid_datatype) && (test_format)) { + valid_datatype = 1; + _this->spec.format = test_format; + switch (test_format) { case AUDIO_S8: format.format = media_raw_audio_format::B_AUDIO_CHAR; break; @@ -207,43 +150,67 @@ extern "C" valid_datatype = 0; test_format = SDL_NextAudioFormat(); break; - } } + } - format.buffer_size = spec->samples; + format.buffer_size = _this->spec.samples; - if (!valid_datatype) { /* shouldn't happen, but just in case... */ - SDL_SetError("Unsupported audio format"); - return (-1); - } + if (!valid_datatype) { /* shouldn't happen, but just in case... */ + BEOSAUDIO_CloseDevice(_this); + SDL_SetError("Unsupported audio format"); + return 0; + } - /* Initialize the Be Application, if it's not already started */ - if (SDL_InitBeApp() < 0) { - return (-1); - } + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(&_this->spec); + + /* Subscribe to the audio stream (creates a new thread) */ + sigset_t omask; + SDL_MaskSignals(&omask); + _this->hidden->audio_obj = new BSoundPlayer(&format, "SDL Audio", + FillSound, NULL, _this); + SDL_UnmaskSignals(&omask); + + if (_this->hidden->audio_obj->Start() == B_NO_ERROR) { + _this->hidden->audio_obj->SetHasData(true); + } else { + BEOSAUDIO_CloseDevice(_this); + SDL_SetError("Unable to start Be audio"); + return 0; + } - /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(spec); + /* We're running! */ + return 1; +} - /* Subscribe to the audio stream (creates a new thread) */ - { - sigset_t omask; - SDL_MaskSignals(&omask); - audio_obj = new BSoundPlayer(&format, "SDL Audio", FillSound, - NULL, _this); - SDL_UnmaskSignals(&omask); - } - if (audio_obj->Start() == B_NO_ERROR) { - audio_obj->SetHasData(true); - } else { - SDL_SetError("Unable to start Be audio"); - return (-1); - } +static void +BEOSAUDIO_Deinitialize(void) +{ + SDL_QuitBeApp(); +} - /* We're running! */ - return (1); +static int +BEOSAUDIO_Init(SDL_AudioDriverImpl *impl) +{ + /* Initialize the Be Application, if it's not already started */ + if (SDL_InitBeApp() < 0) { + return 0; } -}; /* Extern C */ + /* Set the function pointers */ + impl->OpenDevice = BEOSAUDIO_OpenDevice; + impl->CloseDevice = BEOSAUDIO_CloseDevice; + impl->Deinitialize = BEOSAUDIO_Deinitialize; + impl->ProvidesOwnCallbackThread = 1; + impl->OnlyHasDefaultOutputDevice = 1; + + return 1; +} + +extern "C" { extern AudioBootStrap BEOSAUDIO_bootstrap; } +AudioBootStrap BEOSAUDIO_bootstrap = { + "baudio", "BeOS BSoundPlayer", BEOSAUDIO_Init, 0 +}; /* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/audio/baudio/SDL_beaudio.h b/src/audio/baudio/SDL_beaudio.h index fc8d52bb4..eae6fecdc 100644 --- a/src/audio/baudio/SDL_beaudio.h +++ b/src/audio/baudio/SDL_beaudio.h @@ -21,12 +21,12 @@ */ #include "SDL_config.h" -#ifndef _SDL_lowaudio_h -#define _SDL_lowaudio_h +#ifndef _SDL_beaudio_h +#define _SDL_beaudio_h #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *_this struct SDL_PrivateAudioData @@ -34,8 +34,6 @@ struct SDL_PrivateAudioData BSoundPlayer *audio_obj; }; -/* Old variable names */ -#define audio_obj (_this->hidden->audio_obj) +#endif /* _SDL_beaudio_h */ -#endif /* _SDL_lowaudio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/bsd/SDL_bsdaudio.c b/src/audio/bsd/SDL_bsdaudio.c index 762d0b27c..71fc2a90b 100644 --- a/src/audio/bsd/SDL_bsdaudio.c +++ b/src/audio/bsd/SDL_bsdaudio.c @@ -61,95 +61,152 @@ /* #define DEBUG_AUDIO_STREAM */ #ifdef USE_BLOCKING_WRITES -#define OPEN_FLAGS O_WRONLY +#define OPEN_FLAGS_OUTPUT O_WRONLY +#define OPEN_FLAGS_INPUT O_RDONLY #else -#define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) +#define OPEN_FLAGS_OUTPUT (O_WRONLY|O_NONBLOCK) +#define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK) #endif -/* Audio driver functions */ -static void OBSD_WaitAudio(_THIS); -static int OBSD_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void OBSD_PlayAudio(_THIS); -static Uint8 *OBSD_GetAudioBuf(_THIS); -static void OBSD_CloseAudio(_THIS); +/* !!! FIXME: so much cut and paste with dsp/dma drivers... */ +static char **outputDevices = NULL; +static int outputDeviceCount = 0; +static char **inputDevices = NULL; +static int inputDeviceCount = 0; -#ifdef DEBUG_AUDIO -static void OBSD_Status(_THIS); -#endif +static inline void +free_device_list(char ***devs, int *count) +{ + SDL_FreeUnixAudioDevices(devs, count); +} -/* Audio driver bootstrap functions */ +static inline void +build_device_list(int iscapture, char ***devs, int *count) +{ + const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); + free_device_list(devs, count); + SDL_EnumUnixAudioDevices(flags, 0, NULL, devs, count); +} -static int -Audio_Available(void) +static inline void +build_device_lists(void) { - int fd; - int available; - - available = 0; - fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); - if (fd >= 0) { - available = 1; - close(fd); - } - return (available); + build_device_list(0, &outputDevices, &outputDeviceCount); + build_device_list(1, &inputDevices, &inputDeviceCount); } -static void -Audio_DeleteDevice(SDL_AudioDevice * device) + +static inline void +free_device_lists(void) { - SDL_free(device->hidden); - SDL_free(device); + free_device_list(&outputDevices, &outputDeviceCount); + free_device_list(&inputDevices, &inputDeviceCount); } -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) + +static void +BSDAUDIO_Deinitialize(void) { - SDL_AudioDevice *this; + free_device_lists(); +} - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); + +static int +BSDAUDIO_DetectDevices(int iscapture) +{ + if (iscapture) { + build_device_list(1, &inputDevices, &inputDeviceCount); + return inputDeviceCount; + } else { + build_device_list(0, &outputDevices, &outputDeviceCount); + return outputDeviceCount; } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) - SDL_free(this); - return (0); + + return 0; /* shouldn't ever hit this. */ +} + +static const char * +BSDAUDIO_GetDeviceName(int index, int iscapture) +{ + if ((iscapture) && (index < inputDeviceCount)) { + return inputDevices[index]; + } else if ((!iscapture) && (index < outputDeviceCount)) { + return outputDevices[index]; } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - audio_fd = -1; - /* Set the function pointers */ - this->OpenAudio = OBSD_OpenAudio; - this->WaitAudio = OBSD_WaitAudio; - this->PlayAudio = OBSD_PlayAudio; - this->GetAudioBuf = OBSD_GetAudioBuf; - this->CloseAudio = OBSD_CloseAudio; + SDL_SetError("No such device"); + return NULL; +} + + +static void +BSDAUDIO_Status(_THIS) +{ +#ifdef DEBUG_AUDIO + audio_info_t info; + + if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) { + fprintf(stderr, "AUDIO_GETINFO failed.\n"); + return; + } - this->free = Audio_DeleteDevice; + fprintf(stderr, "\n" + "[play/record info]\n" + "buffer size : %d bytes\n" + "sample rate : %i Hz\n" + "channels : %i\n" + "precision : %i-bit\n" + "encoding : 0x%x\n" + "seek : %i\n" + "sample count : %i\n" + "EOF count : %i\n" + "paused : %s\n" + "error occured : %s\n" + "waiting : %s\n" + "active : %s\n" + "", + info.play.buffer_size, + info.play.sample_rate, + info.play.channels, + info.play.precision, + info.play.encoding, + info.play.seek, + info.play.samples, + info.play.eof, + info.play.pause ? "yes" : "no", + info.play.error ? "yes" : "no", + info.play.waiting ? "yes" : "no", + info.play.active ? "yes" : "no"); - return this; + fprintf(stderr, "\n" + "[audio info]\n" + "monitor_gain : %i\n" + "hw block size : %d bytes\n" + "hi watermark : %i\n" + "lo watermark : %i\n" + "audio mode : %s\n" + "", + info.monitor_gain, + info.blocksize, + info.hiwat, info.lowat, + (info.mode == AUMODE_PLAY) ? "PLAY" + : (info.mode = AUMODE_RECORD) ? "RECORD" + : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?")); +#endif /* DEBUG_AUDIO */ } -AudioBootStrap BSD_AUDIO_bootstrap = { - BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC, - Audio_Available, Audio_CreateDevice -}; /* This function waits until it is possible to write a full sound buffer */ static void -OBSD_WaitAudio(_THIS) +BSDAUDIO_WaitDevice(_THIS) { #ifndef USE_BLOCKING_WRITES /* Not necessary when using blocking writes */ /* See if we need to use timed audio synchronization */ - if (frame_ticks) { + if (this->hidden->frame_ticks) { /* Use timer for general audio synchronization */ Sint32 ticks; - ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS; + ticks = ((Sint32)(this->hidden->next_frame-SDL_GetTicks()))-FUDGE_TICKS; if (ticks > 0) { SDL_Delay(ticks); } @@ -159,13 +216,13 @@ OBSD_WaitAudio(_THIS) struct timeval timeout; FD_ZERO(&fdset); - FD_SET(audio_fd, &fdset); + FD_SET(this->hidden->audio_fd, &fdset); timeout.tv_sec = 10; timeout.tv_usec = 0; #ifdef DEBUG_AUDIO fprintf(stderr, "Waiting for audio to get ready\n"); #endif - if (select(audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) { + if (select(this->hidden->audio_fd+1,NULL,&fdset,NULL,&timeout) <= 0) { const char *message = "Audio timeout - buggy audio driver? (disabled)"; /* In general we should never print to the screen, @@ -175,7 +232,7 @@ OBSD_WaitAudio(_THIS) fprintf(stderr, "SDL: %s\n", message); this->enabled = 0; /* Don't try to close - may hang */ - audio_fd = -1; + this->hidden->audio_fd = -1; #ifdef DEBUG_AUDIO fprintf(stderr, "Done disabling audio\n"); #endif @@ -188,13 +245,16 @@ OBSD_WaitAudio(_THIS) } static void -OBSD_PlayAudio(_THIS) +BSDAUDIO_PlayDevice(_THIS) { int written, p = 0; /* Write the audio data, checking for EAGAIN on broken audio drivers */ do { - written = write(audio_fd, &mixbuf[p], mixlen - p); + written = write(this->hidden->audio_fd, + &this->hidden->mixbuf[p], + this->hidden->mixlen - p); + if (written > 0) p += written; if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) { @@ -211,8 +271,8 @@ OBSD_PlayAudio(_THIS) while (p < written); /* If timer synchronization is enabled, set the next write frame */ - if (frame_ticks) { - next_frame += frame_ticks; + if (this->hidden->frame_ticks) { + this->hidden->next_frame += this->hidden->frame_ticks; } /* If we couldn't write, assume fatal error for now */ @@ -225,141 +285,77 @@ OBSD_PlayAudio(_THIS) } static Uint8 * -OBSD_GetAudioBuf(_THIS) +BSDAUDIO_GetDeviceBuf(_THIS) { - return (mixbuf); + return (this->hidden->mixbuf); } static void -OBSD_CloseAudio(_THIS) +BSDAUDIO_CloseDevice(_THIS) { - if (mixbuf != NULL) { - SDL_FreeAudioMem(mixbuf); - mixbuf = NULL; - } - if (audio_fd >= 0) { - close(audio_fd); - audio_fd = -1; + if (this->hidden != NULL) { + if (this->hidden->mixbuf != NULL) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + if (this->hidden->audio_fd >= 0) { + close(this->hidden->audio_fd); + this->hidden->audio_fd = -1; + } + SDL_free(this->hidden); + this->hidden = NULL; } } -#ifdef DEBUG_AUDIO -void -OBSD_Status(_THIS) +static int +BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) { + const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); + SDL_AudioFormat format = 0; audio_info_t info; - if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) { - fprintf(stderr, "AUDIO_GETINFO failed.\n"); - return; + /* We don't care what the devname is...we'll try to open anything. */ + /* ...but default to first name in the list... */ + if (devname == NULL) { + if ( ((iscapture) && (inputDeviceCount == 0)) || + ((!iscapture) && (outputDeviceCount == 0)) ) { + SDL_SetError("No such audio device"); + return 0; + } + devname = ((iscapture) ? inputDevices[0] : outputDevices[0]); } - fprintf(stderr, "\n" - "[play/record info]\n" - "buffer size : %d bytes\n" - "sample rate : %i Hz\n" - "channels : %i\n" - "precision : %i-bit\n" - "encoding : 0x%x\n" - "seek : %i\n" - "sample count : %i\n" - "EOF count : %i\n" - "paused : %s\n" - "error occured : %s\n" - "waiting : %s\n" - "active : %s\n" - "", - info. - play. - buffer_size, - info. - play. - sample_rate, - info. - play. - channels, - info. - play. - precision, - info. - play. - encoding, - info. - play. - seek, - info. - play. - samples, - info. - play. - eof, - info. - play. - pause - ? - "yes" - : - "no", - info. - play. - error - ? - "yes" - : - "no", - info. - play.waiting ? "yes" : "no", info.play.active ? "yes" : "no"); - - fprintf(stderr, "\n" - "[audio info]\n" - "monitor_gain : %i\n" - "hw block size : %d bytes\n" - "hi watermark : %i\n" - "lo watermark : %i\n" - "audio mode : %s\n" - "", - info.monitor_gain, - info.blocksize, - info.hiwat, info.lowat, - (info.mode == AUMODE_PLAY) ? "PLAY" - : (info.mode = AUMODE_RECORD) ? "RECORD" - : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?")); -} -#endif /* DEBUG_AUDIO */ + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); -static int -OBSD_OpenAudio(_THIS, SDL_AudioSpec * spec) -{ - char audiodev[64]; - SDL_AudioFormat format; - audio_info_t info; + /* Open the audio device */ + this->hidden->audio_fd = open(devname, flags, 0); + if (this->hidden->audio_fd < 0) { + SDL_SetError("Couldn't open %s: %s", devname, strerror(errno)); + return 0; + } AUDIO_INITINFO(&info); /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(spec); - -#ifdef USE_TIMER_SYNC - frame_ticks = 0.0; -#endif - - /* Open the audio device */ - audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); - if (audio_fd < 0) { - SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); - return (-1); - } + SDL_CalculateAudioSpec(&this->spec); /* Set to play mode */ info.mode = AUMODE_PLAY; - if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) { + if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) { + BSDAUDIO_CloseDevice(this); SDL_SetError("Couldn't put device into play mode"); - return (-1); + return 0; } - mixbuf = NULL; AUDIO_INITINFO(&info); - for (format = SDL_FirstAudioFormat(spec->format); + for (format = SDL_FirstAudioFormat(this->spec.format); format; format = SDL_NextAudioFormat()) { switch (format) { case AUDIO_U8: @@ -389,46 +385,69 @@ OBSD_OpenAudio(_THIS, SDL_AudioSpec * spec) default: continue; } - if (ioctl(audio_fd, AUDIO_SETINFO, &info) == 0) + + if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) { break; + } } if (!format) { - SDL_SetError("No supported encoding for 0x%x", spec->format); - return (-1); + BSDAUDIO_CloseDevice(this); + SDL_SetError("No supported encoding for 0x%x", this->spec.format); + return 0; } - spec->format = format; + this->spec.format = format; AUDIO_INITINFO(&info); - info.play.channels = spec->channels; - if (ioctl(audio_fd, AUDIO_SETINFO, &info) == -1) - spec->channels = 1; + info.play.channels = this->spec.channels; + if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) { + this->spec.channels = 1; + } AUDIO_INITINFO(&info); - info.play.sample_rate = spec->freq; - info.blocksize = spec->size; + info.play.sample_rate = this->spec.freq; + info.blocksize = this->spec.size; info.hiwat = 5; info.lowat = 3; - (void) ioctl(audio_fd, AUDIO_SETINFO, &info); - (void) ioctl(audio_fd, AUDIO_GETINFO, &info); - spec->freq = info.play.sample_rate; + (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info); + (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info); + this->spec.freq = info.play.sample_rate; /* Allocate mixing buffer */ - mixlen = spec->size; - mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen); - if (mixbuf == NULL) { - return (-1); + this->hidden->mixlen = this->spec.size; + this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); + if (this->hidden->mixbuf == NULL) { + BSDAUDIO_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } - SDL_memset(mixbuf, spec->silence, spec->size); + SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); - /* Get the parent process id (we're the parent of the audio thread) */ - parent = getpid(); - -#ifdef DEBUG_AUDIO - OBSD_Status(this); -#endif + BSDAUDIO_Status(this); /* We're ready to rock and roll. :-) */ return (0); } +static int +BSDAUDIO_Init(SDL_AudioDriverImpl *impl) +{ + /* Set the function pointers */ + impl->DetectDevices = BSDAUDIO_DetectDevices; + impl->GetDeviceName = BSDAUDIO_GetDeviceName; + impl->OpenDevice = BSDAUDIO_OpenDevice; + impl->PlayDevice = BSDAUDIO_PlayDevice; + impl->WaitDevice = BSDAUDIO_WaitDevice; + impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf; + impl->CloseDevice = BSDAUDIO_CloseDevice; + impl->Deinitialize = BSDAUDIO_Deinitialize; + + build_device_lists(); + return 1; +} + + +AudioBootStrap BSD_AUDIO_bootstrap = { + BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC, BSDAUDIO_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/bsd/SDL_bsdaudio.h b/src/audio/bsd/SDL_bsdaudio.h index 618401d90..e2ff5e58e 100644 --- a/src/audio/bsd/SDL_bsdaudio.h +++ b/src/audio/bsd/SDL_bsdaudio.h @@ -21,8 +21,8 @@ */ #include "SDL_config.h" -#ifndef _SDL_openbsdaudio_h -#define _SDL_openbsdaudio_h +#ifndef _SDL_bsdaudio_h +#define _SDL_bsdaudio_h #include "../SDL_sysaudio.h" @@ -47,13 +47,6 @@ struct SDL_PrivateAudioData #define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */ -/* Old variable names */ -#define audio_fd (this->hidden->audio_fd) -#define parent (this->hidden->parent) -#define mixbuf (this->hidden->mixbuf) -#define mixlen (this->hidden->mixlen) -#define frame_ticks (this->hidden->frame_ticks) -#define next_frame (this->hidden->next_frame) +#endif /* _SDL_bsdaudio_h */ -#endif /* _SDL_openbsdaudio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/dart/SDL_dart.c b/src/audio/dart/SDL_dart.c index dde73db33..ede038990 100644 --- a/src/audio/dart/SDL_dart.c +++ b/src/audio/dart/SDL_dart.c @@ -42,10 +42,10 @@ typedef struct _tMixBufferDesc //--------------------------------------------------------------------- // DARTEventFunc // -// This function is called by DART, when an event occures, like end of +// This function is called by DART, when an event occurs, like end of // playback of a buffer, etc... //--------------------------------------------------------------------- -LONG APIENTRY +static LONG APIENTRY DARTEventFunc(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags) { if (ulFlags && MIX_WRITE_COMPLETE) { // Playback of buffer completed! @@ -71,13 +71,12 @@ DARTEventFunc(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags) } -int -DART_OpenAudio(_THIS, SDL_AudioSpec * spec) +static int +DART_OpenDevice(_THIS, const char *devname, int iscapture) { - SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format); + SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format); int valid_datatype = 0; MCI_AMP_OPEN_PARMS AmpOpenParms; - MCI_GENERIC_PARMS GenericParms; int iDeviceOrd = 0; // Default device to be used int bOpenShared = 1; // Try opening it shared int iBits = 16; // Default is 16 bits signed @@ -89,6 +88,15 @@ DART_OpenAudio(_THIS, SDL_AudioSpec * spec) int iSilence; int rc; + /* Initialize all variables that we clean on shutdown */ + _this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *_this->hidden)); + if (_this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(_this->hidden, 0, (sizeof *_this->hidden)); + // First thing is to try to open a given DART device! SDL_memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS)); // pszDeviceType should contain the device type in low word, and device ordinal in high word! @@ -100,30 +108,34 @@ DART_OpenAudio(_THIS, SDL_AudioSpec * spec) iOpenMode |= MCI_OPEN_SHAREABLE; rc = mciSendCommand(0, MCI_OPEN, iOpenMode, (PVOID) & AmpOpenParms, 0); - if (rc != MCIERR_SUCCESS) // No audio available?? - return (-1); + if (rc != MCIERR_SUCCESS) { // No audio available?? + DART_CloseDevice(_this); + SDL_SetError("DART: Couldn't open audio device."); + return 0; + } + // Save the device ID we got from DART! // We will use this in the next calls! - iDeviceOrd = AmpOpenParms.usDeviceID; + _this->hidden->iCurrDeviceOrd = iDeviceOrd = AmpOpenParms.usDeviceID; // Determine the audio parameters from the AudioSpec - if (spec->channels > 2) - spec->channels = 2; // !!! FIXME: more than stereo support in OS/2? + if (_this->spec.channels > 4) + _this->spec.channels = 4; while ((!valid_datatype) && (test_format)) { - spec->format = test_format; + _this->spec.format = test_format; valid_datatype = 1; switch (test_format) { case AUDIO_U8: // Unsigned 8 bit audio data iSilence = 0x80; - iBits = 8; + _this->hidden->iCurrBits = iBits = 8; break; case AUDIO_S16LSB: // Signed 16 bit audio data iSilence = 0x00; - iBits = 16; + _this->hidden->iCurrBits = iBits = 16; break; // !!! FIXME: int32? @@ -137,16 +149,16 @@ DART_OpenAudio(_THIS, SDL_AudioSpec * spec) if (!valid_datatype) { // shouldn't happen, but just in case... // Close DART, and exit with error code! - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + DART_CloseDevice(_this); SDL_SetError("Unsupported audio format"); - return (-1); + return 0; } - iFreq = spec->freq; - iChannels = spec->channels; + _this->hidden->iCurrFreq = iFreq = _this->spec.freq; + _this->hidden->iCurrChannels = iChannels = _this->spec.channels; /* Update the fragment size as size in bytes */ - SDL_CalculateAudioSpec(spec); - iBufSize = spec->size; + SDL_CalculateAudioSpec(&_this->spec); + _this->hidden->iCurrBufSize = iBufSize = _this->spec.size; // Now query this device if it supports the given freq/bits/channels! SDL_memset(&(_this->hidden->MixSetupParms), 0, @@ -163,9 +175,9 @@ DART_OpenAudio(_THIS, SDL_AudioSpec * spec) &(_this->hidden->MixSetupParms), 0); if (rc != MCIERR_SUCCESS) { // The device cannot handle this format! // Close DART, and exit with error code! - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + DART_CloseDevice(_this); SDL_SetError("Audio device doesn't support requested audio format"); - return (-1); + return 0; } // The device can handle this format, so initialize! rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP, @@ -173,9 +185,9 @@ DART_OpenAudio(_THIS, SDL_AudioSpec * spec) &(_this->hidden->MixSetupParms), 0); if (rc != MCIERR_SUCCESS) { // The device could not be opened! // Close DART, and exit with error code! - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + DART_CloseDevice(_this); SDL_SetError("Audio device could not be set up"); - return (-1); + return 0; } // Ok, the device is initialized. // Now we should allocate buffers. For this, we need a place where @@ -184,9 +196,9 @@ DART_OpenAudio(_THIS, SDL_AudioSpec * spec) (MCI_MIX_BUFFER *) SDL_malloc(sizeof(MCI_MIX_BUFFER) * iNumBufs); if (!(_this->hidden->pMixBuffers)) { // Not enough memory! // Close DART, and exit with error code! - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); - SDL_SetError("Not enough memory for audio buffer descriptors"); - return (-1); + DART_CloseDevice(_this); + SDL_OutOfMemory(); + return 0; } // Now that we have the place for buffer list, we can ask DART for the // buffers! @@ -201,12 +213,12 @@ DART_OpenAudio(_THIS, SDL_AudioSpec * spec) || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers) || (_this->hidden->BufferParms.ulBufferSize == 0)) { // Could not allocate memory! // Close DART, and exit with error code! - SDL_free(_this->hidden->pMixBuffers); - _this->hidden->pMixBuffers = NULL; - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + DART_CloseDevice(_this); SDL_SetError("DART could not allocate buffers"); - return (-1); + return 0; } + _this->hidden->iCurrNumBufs = iNumBufs; + // Ok, we have all the buffers allocated, let's mark them! { int i; @@ -216,24 +228,9 @@ DART_OpenAudio(_THIS, SDL_AudioSpec * spec) // Check if this buffer was really allocated by DART if ((!(_this->hidden->pMixBuffers[i].pBuffer)) || (!pBufferDesc)) { // Wrong buffer! - // Close DART, and exit with error code! - // Free buffer descriptions - { - int j; - for (j = 0; j < i; j++) - SDL_free((void *) (_this->hidden->pMixBuffers[j]. - ulUserParm)); - } - // and cleanup - mciSendCommand(iDeviceOrd, MCI_BUFFER, - MCI_WAIT | MCI_DEALLOCATE_MEMORY, - &(_this->hidden->BufferParms), 0); - SDL_free(_this->hidden->pMixBuffers); - _this->hidden->pMixBuffers = NULL; - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, - &GenericParms, 0); + DART_CloseDevice(_this); SDL_SetError("Error at internal buffer check"); - return (-1); + return 0; } pBufferDesc->iBufferUsage = BUFFER_EMPTY; pBufferDesc->pSDLAudioDevice = _this; @@ -254,43 +251,41 @@ DART_OpenAudio(_THIS, SDL_AudioSpec * spec) if (DosCreateEventSem (NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE) != NO_ERROR) { - // Could not create event semaphore! - { - int i; - for (i = 0; i < iNumBufs; i++) - SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm)); - } - mciSendCommand(iDeviceOrd, MCI_BUFFER, - MCI_WAIT | MCI_DEALLOCATE_MEMORY, - &(_this->hidden->BufferParms), 0); - SDL_free(_this->hidden->pMixBuffers); - _this->hidden->pMixBuffers = NULL; - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + DART_CloseDevice(_this); SDL_SetError("Could not create event semaphore"); - return (-1); + return 0; } - // Store the new settings in global variables - _this->hidden->iCurrDeviceOrd = iDeviceOrd; - _this->hidden->iCurrFreq = iFreq; - _this->hidden->iCurrBits = iBits; - _this->hidden->iCurrChannels = iChannels; - _this->hidden->iCurrNumBufs = iNumBufs; - _this->hidden->iCurrBufSize = iBufSize; - return (0); + return 1; } - - -void +static void DART_ThreadInit(_THIS) { - return; + /* Increase the priority of this thread to make sure that + the audio will be continuous all the time! */ +#ifdef USE_DOSSETPRIORITY + if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) { +#ifdef DEBUG_BUILD + printf + ("[DART_ThreadInit] : Setting priority to TimeCritical+0! (TID%d)\n", + SDL_ThreadID()); +#endif + DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0); + } else { +#ifdef DEBUG_BUILD + printf + ("[DART_ThreadInit] : Setting priority to ForegroundServer+0! (TID%d)\n", + SDL_ThreadID()); +#endif + DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0); + } +#endif } /* This function waits until it is possible to write a full sound buffer */ -void -DART_WaitAudio(_THIS) +static void +DART_WaitDevice(_THIS) { int i; pMixBufferDesc pBufDesc; @@ -308,8 +303,8 @@ DART_WaitAudio(_THIS) return; } -void -DART_PlayAudio(_THIS) +static void +DART_PlayDevice(_THIS) { int iFreeBuf = _this->hidden->iNextFreeBuffer; pMixBufferDesc pBufDesc; @@ -328,8 +323,8 @@ DART_PlayAudio(_THIS) _this->hidden->iNextFreeBuffer = iFreeBuf; } -Uint8 * -DART_GetAudioBuf(_THIS) +static Uint8 * +DART_GetDeviceBuf(_THIS) { int iFreeBuf; Uint8 *pResult; @@ -348,125 +343,110 @@ DART_GetAudioBuf(_THIS) return pResult; } } else - printf("[DART_GetAudioBuf] : ERROR! pBufDesc = %p\n", + printf("[DART_GetDeviceBuf] : ERROR! pBufDesc = %p\n", pBufDesc); } else - printf("[DART_GetAudioBuf] : ERROR! _this->hidden = %p\n", + printf("[DART_GetDeviceBuf] : ERROR! _this->hidden = %p\n", _this->hidden); } else - printf("[DART_GetAudioBuf] : ERROR! _this = %p\n", _this); + printf("[DART_GetDeviceBuf] : ERROR! _this = %p\n", _this); return NULL; } -void +static void DART_WaitDone(_THIS) { pMixBufferDesc pBufDesc; - ULONG ulPostCount; - APIRET rc; + ULONG ulPostCount = 0; + APIRET rc = NO_ERROR; + + pBufDesc = (pMixBufferDesc) + _this->hidden->pMixBuffers[_this->hidden->iLastPlayedBuf].ulUserParm; - pBufDesc = - (pMixBufferDesc) _this->hidden->pMixBuffers[_this->hidden-> - iLastPlayedBuf]. - ulUserParm; - rc = NO_ERROR; while ((pBufDesc->iBufferUsage != BUFFER_EMPTY) && (rc == NO_ERROR)) { DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount); rc = DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // 1 sec timeout! Important! } } -void -DART_CloseAudio(_THIS) +static void +DART_CloseDevice(_THIS) { MCI_GENERIC_PARMS GenericParms; int rc; + int i; - // Stop DART playback - rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP, MCI_WAIT, - &GenericParms, 0); - if (rc != MCIERR_SUCCESS) { + if (_this->hidden != NULL) { + // Stop DART playback + if (_this->hidden->iCurrDeviceOrd) { + rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP, + MCI_WAIT, &GenericParms, 0); #ifdef SFX_DEBUG_BUILD - printf("Could not stop DART playback!\n"); - fflush(stdout); + if (rc != MCIERR_SUCCESS) { + printf("Could not stop DART playback!\n"); + fflush(stdout); + } #endif - } - // Close event semaphore - DosCloseEventSem(_this->hidden->hevAudioBufferPlayed); + } - // Free memory of buffer descriptions - { - int i; - for (i = 0; i < _this->hidden->iCurrNumBufs; i++) - SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm)); - } + // Close event semaphore + if (_this->hidden->hevAudioBufferPlayed) { + DosCloseEventSem(_this->hidden->hevAudioBufferPlayed); + _this->hidden->hevAudioBufferPlayed = 0; + } - // Deallocate buffers - rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER, - MCI_WAIT | MCI_DEALLOCATE_MEMORY, - &(_this->hidden->BufferParms), 0); + // Free memory of buffer descriptions + for (i = 0; i < _this->hidden->iCurrNumBufs; i++) { + SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm)); + _this->hidden->pMixBuffers[i].ulUserParm = 0; + } + _this->hidden->iCurrNumBufs = 0; - // Free bufferlist - SDL_free(_this->hidden->pMixBuffers); - _this->hidden->pMixBuffers = NULL; + // Deallocate buffers + if (_this->hidden->iCurrDeviceOrd) { + rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER, + MCI_WAIT | MCI_DEALLOCATE_MEMORY, + &(_this->hidden->BufferParms), 0); + } - // Close dart - rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE, MCI_WAIT, - &(GenericParms), 0); -} + // Free bufferlist + if (_this->hidden->pMixBuffers != NULL) { + SDL_free(_this->hidden->pMixBuffers); + _this->hidden->pMixBuffers = NULL; + } -/* Audio driver bootstrap functions */ + // Close dart + if (_this->hidden->iCurrDeviceOrd) { + rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE, + MCI_WAIT, &(GenericParms), 0); + } + _this->hidden->iCurrDeviceOrd = 0; -int -Audio_Available(void) -{ - return (1); + SDL_free(_this->hidden); + _this->hidden = NULL; + } } -void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); -} -SDL_AudioDevice * -Audio_CreateDevice(int devindex) +static int +DART_Init(SDL_AudioDriverImpl *impl) { - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) - SDL_free(this); - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - /* Set the function pointers */ - this->OpenAudio = DART_OpenAudio; - this->ThreadInit = DART_ThreadInit; - this->WaitAudio = DART_WaitAudio; - this->PlayAudio = DART_PlayAudio; - this->GetAudioBuf = DART_GetAudioBuf; - this->WaitDone = DART_WaitDone; - this->CloseAudio = DART_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; + impl->OpenDevice = DART_OpenDevice; + impl->ThreadInit = DART_ThreadInit; + impl->WaitDevice = DART_WaitDevice; + impl->GetDeviceBuf = DART_GetDeviceBuf; + impl->PlayDevice = DART_PlayDevice; + impl->WaitDone = DART_WaitDone; + impl->CloseDevice = DART_CloseDevice; + impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: is this right? */ + + return 1; } + AudioBootStrap DART_bootstrap = { - "dart", "OS/2 Direct Audio RouTines (DART)", - Audio_Available, Audio_CreateDevice + "dart", "OS/2 Direct Audio RouTines (DART)", DART_Init, 0 }; /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/dart/SDL_dart.h b/src/audio/dart/SDL_dart.h index a58eda3f0..7b740feca 100644 --- a/src/audio/dart/SDL_dart.h +++ b/src/audio/dart/SDL_dart.h @@ -21,14 +21,15 @@ */ #include "SDL_config.h" -#ifndef _SDL_lowaudio_h -#define _SDL_lowaudio_h +#ifndef _SDL_dart_h +#define _SDL_dart_h #define INCL_TYPES #define INCL_DOSSEMAPHORES #define INCL_DOSRESOURCES #define INCL_DOSMISC #define INCL_DOSERRORS +#define INCL_DOSPROCESS #define INCL_OS2MM #define INCL_MMIOOS2 @@ -60,5 +61,6 @@ struct SDL_PrivateAudioData HEV hevAudioBufferPlayed; // Event semaphore to indicate that an audio buffer has been played by DART }; -#endif /* _SDL_lowaudio_h */ +#endif /* _SDL_dart_h */ + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/dc/SDL_dcaudio.c b/src/audio/dc/SDL_dcaudio.c index d470222a1..af72f7e6b 100644 --- a/src/audio/dc/SDL_dcaudio.c +++ b/src/audio/dc/SDL_dcaudio.c @@ -28,85 +28,11 @@ #include "SDL_audio.h" #include "../SDL_audiomem.h" #include "../SDL_audio_c.h" -#include "../SDL_audiodev_c.h" #include "SDL_dcaudio.h" #include "aica.h" #include -/* Audio driver functions */ -static int DCAUD_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void DCAUD_WaitAudio(_THIS); -static void DCAUD_PlayAudio(_THIS); -static Uint8 *DCAUD_GetAudioBuf(_THIS); -static void DCAUD_CloseAudio(_THIS); - -/* Audio driver bootstrap functions */ -static int -DCAUD_Available(void) -{ - return 1; -} - -static void -DCAUD_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); -} - -static SDL_AudioDevice * -DCAUD_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - /* Set the function pointers */ - this->OpenAudio = DCAUD_OpenAudio; - this->WaitAudio = DCAUD_WaitAudio; - this->PlayAudio = DCAUD_PlayAudio; - this->GetAudioBuf = DCAUD_GetAudioBuf; - this->CloseAudio = DCAUD_CloseAudio; - - this->free = DCAUD_DeleteDevice; - - spu_init(); - - return this; -} - -AudioBootStrap DCAUD_bootstrap = { - "dcaudio", "Dreamcast AICA audio", - DCAUD_Available, DCAUD_CreateDevice -}; - -/* This function waits until it is possible to write a full sound buffer */ -static void -DCAUD_WaitAudio(_THIS) -{ - if (this->hidden->playing) { - /* wait */ - while (aica_get_pos(0) / this->spec.samples == this->hidden->nextbuf) { - thd_pass(); - } - } -} - #define SPU_RAM_BASE 0xa0800000 static void @@ -152,7 +78,7 @@ spu_memload_stereo16(int leftpos, int rightpos, void *src0, size_t size) } static void -DCAUD_PlayAudio(_THIS) +DCAUD_PlayDevice(_THIS) { SDL_AudioSpec *spec = &this->spec; unsigned int offset; @@ -200,28 +126,59 @@ DCAUD_PlayAudio(_THIS) } static Uint8 * -DCAUD_GetAudioBuf(_THIS) +DCAUD_GetDeviceBuf(_THIS) { return (this->hidden->mixbuf); } +/* This function waits until it is possible to write a full sound buffer */ static void -DCAUD_CloseAudio(_THIS) +DCAUD_WaitDevice(_THIS) { - aica_stop(0); - if (this->spec.channels == 2) - aica_stop(1); - if (this->hidden->mixbuf != NULL) { - SDL_FreeAudioMem(this->hidden->mixbuf); - this->hidden->mixbuf = NULL; + if (this->hidden->playing) { + /* wait */ + while (aica_get_pos(0) / this->spec.samples == this->hidden->nextbuf) { + thd_pass(); + } + } +} + +static void +DCAUD_CloseDevice(_THIS) +{ + if (this->hidden != NULL) { + aica_stop(0); + if (this->spec.channels == 2) { + aica_stop(1); + } + if (this->hidden->mixbuf != NULL) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + SDL_free(this->hidden); + this->hidden = NULL; + + /* !!! FIXME: is there a reverse of spu_init()? */ } } static int -DCAUD_OpenAudio(_THIS, SDL_AudioSpec * spec) +DCAUD_OpenDevice(_THIS, SDL_AudioSpec * spec) { SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format); int valid_datatype = 0; + + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + spu_init(); + while ((!valid_datatype) && (test_format)) { spec->format = test_format; switch (test_format) { @@ -238,8 +195,9 @@ DCAUD_OpenAudio(_THIS, SDL_AudioSpec * spec) } if (!valid_datatype) { /* shouldn't happen, but just in case... */ + DCAUD_CloseDevice(this); SDL_SetError("Unsupported audio format"); - return (-1); + return 0; } if (spec->channels > 2) @@ -252,7 +210,9 @@ DCAUD_OpenAudio(_THIS, SDL_AudioSpec * spec) this->hidden->mixlen = spec->size; this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); if (this->hidden->mixbuf == NULL) { - return (-1); + DCAUD_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } SDL_memset(this->hidden->mixbuf, spec->silence, spec->size); this->hidden->leftpos = 0x11000; @@ -261,7 +221,25 @@ DCAUD_OpenAudio(_THIS, SDL_AudioSpec * spec) this->hidden->nextbuf = 0; /* We're ready to rock and roll. :-) */ - return (0); + return 1; +} + +static int +DCAUD_Init(SDL_AudioDriverImpl *impl) +{ + /* Set the function pointers */ + impl->OpenDevice = DCAUD_OpenDevice; + impl->PlayDevice = DCAUD_PlayDevice; + impl->WaitDevice = DCAUD_WaitDevice; + impl->GetDeviceBuf = DCAUD_GetDeviceBuf; + impl->CloseDevice = DCAUD_CloseDevice; + impl->OnlyHasDefaultOutputDevice = 1; + + return 1; } +AudioBootStrap DCAUD_bootstrap = { + "dcaudio", "Dreamcast AICA audio", DCAUD_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/dc/SDL_dcaudio.h b/src/audio/dc/SDL_dcaudio.h index 4020f5119..2f0133a71 100644 --- a/src/audio/dc/SDL_dcaudio.h +++ b/src/audio/dc/SDL_dcaudio.h @@ -26,7 +26,7 @@ #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData diff --git a/src/audio/disk/SDL_diskaudio.c b/src/audio/disk/SDL_diskaudio.c index 52e237555..e01848b11 100644 --- a/src/audio/disk/SDL_diskaudio.c +++ b/src/audio/disk/SDL_diskaudio.c @@ -34,7 +34,6 @@ #include "SDL_audio.h" #include "../SDL_audiomem.h" #include "../SDL_audio_c.h" -#include "../SDL_audiodev_c.h" #include "SDL_diskaudio.h" /* The tag name used by DISK audio */ @@ -46,90 +45,27 @@ #define DISKENVR_WRITEDELAY "SDL_DISKAUDIODELAY" #define DISKDEFAULT_WRITEDELAY 150 -/* Audio driver functions */ -static int DISKAUD_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void DISKAUD_WaitAudio(_THIS); -static void DISKAUD_PlayAudio(_THIS); -static Uint8 *DISKAUD_GetAudioBuf(_THIS); -static void DISKAUD_CloseAudio(_THIS); - static const char * -DISKAUD_GetOutputFilename(void) -{ - const char *envr = SDL_getenv(DISKENVR_OUTFILE); - return ((envr != NULL) ? envr : DISKDEFAULT_OUTFILE); -} - -/* Audio driver bootstrap functions */ -static int -DISKAUD_Available(void) -{ - const char *envr = SDL_getenv("SDL_AUDIODRIVER"); - if (envr && (SDL_strcmp(envr, DISKAUD_DRIVER_NAME) == 0)) { - return (1); - } - return (0); -} - -static void -DISKAUD_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); -} - -static SDL_AudioDevice * -DISKAUD_CreateDevice(int devindex) +DISKAUD_GetOutputFilename(const char *devname) { - SDL_AudioDevice *this; - const char *envr; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); + if (devname == NULL) { + devname = SDL_getenv(DISKENVR_OUTFILE); + if (devname == NULL) { + devname = DISKDEFAULT_OUTFILE; } - return (0); } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - envr = SDL_getenv(DISKENVR_WRITEDELAY); - this->hidden->write_delay = - (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY; - - /* Set the function pointers */ - this->OpenAudio = DISKAUD_OpenAudio; - this->WaitAudio = DISKAUD_WaitAudio; - this->PlayAudio = DISKAUD_PlayAudio; - this->GetAudioBuf = DISKAUD_GetAudioBuf; - this->CloseAudio = DISKAUD_CloseAudio; - - this->free = DISKAUD_DeleteDevice; - - return this; + return devname; } -AudioBootStrap DISKAUD_bootstrap = { - DISKAUD_DRIVER_NAME, "direct-to-disk audio", - DISKAUD_Available, DISKAUD_CreateDevice -}; - /* This function waits until it is possible to write a full sound buffer */ static void -DISKAUD_WaitAudio(_THIS) +DISKAUD_WaitDevice(_THIS) { SDL_Delay(this->hidden->write_delay); } static void -DISKAUD_PlayAudio(_THIS) +DISKAUD_PlayDevice(_THIS) { int written; @@ -147,49 +83,86 @@ DISKAUD_PlayAudio(_THIS) } static Uint8 * -DISKAUD_GetAudioBuf(_THIS) +DISKAUD_GetDeviceBuf(_THIS) { return (this->hidden->mixbuf); } static void -DISKAUD_CloseAudio(_THIS) +DISKAUD_CloseDevice(_THIS) { - if (this->hidden->mixbuf != NULL) { - SDL_FreeAudioMem(this->hidden->mixbuf); - this->hidden->mixbuf = NULL; - } - if (this->hidden->output != NULL) { - SDL_RWclose(this->hidden->output); - this->hidden->output = NULL; + if (this->hidden != NULL) { + if (this->hidden->mixbuf != NULL) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + if (this->hidden->output != NULL) { + SDL_RWclose(this->hidden->output); + this->hidden->output = NULL; + } + SDL_free(this->hidden); + this->hidden = NULL; } } static int -DISKAUD_OpenAudio(_THIS, SDL_AudioSpec * spec) +DISKAUD_OpenDevice(_THIS, const char *devname, int iscapture) { - const char *fname = DISKAUD_GetOutputFilename(); + const char *envr = SDL_getenv(DISKENVR_WRITEDELAY); + const char *fname = DISKAUD_GetOutputFilename(devname); + + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc(sizeof (*this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, sizeof (*this->hidden)); /* Open the audio device */ this->hidden->output = SDL_RWFromFile(fname, "wb"); if (this->hidden->output == NULL) { - return (-1); + DISKAUD_CloseDevice(this); + return 0; } -#if HAVE_STDIO_H - fprintf(stderr, "WARNING: You are using the SDL disk writer" - " audio driver!\n Writing to file [%s].\n", fname); -#endif /* Allocate mixing buffer */ - this->hidden->mixlen = spec->size; this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); if (this->hidden->mixbuf == NULL) { - return (-1); + DISKAUD_CloseDevice(this); + return 0; } - SDL_memset(this->hidden->mixbuf, spec->silence, spec->size); + SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); + + this->hidden->mixlen = this->spec.size; + this->hidden->write_delay = + (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY; + +#if HAVE_STDIO_H + fprintf(stderr, + "WARNING: You are using the SDL disk writer audio driver!\n" + " Writing to file [%s].\n", fname); +#endif /* We're ready to rock and roll. :-) */ - return (0); + return 1; +} + +static int +DISKAUD_Init(SDL_AudioDriverImpl *impl) +{ + /* Set the function pointers */ + impl->OpenDevice = DISKAUD_OpenDevice; + impl->WaitDevice = DISKAUD_WaitDevice; + impl->PlayDevice = DISKAUD_PlayDevice; + impl->GetDeviceBuf = DISKAUD_GetDeviceBuf; + impl->CloseDevice = DISKAUD_CloseDevice; + + return 1; } +AudioBootStrap DISKAUD_bootstrap = { + DISKAUD_DRIVER_NAME, "direct-to-disk audio", DISKAUD_Init, 1 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/disk/SDL_diskaudio.h b/src/audio/disk/SDL_diskaudio.h index 231c55337..c870d96f5 100644 --- a/src/audio/disk/SDL_diskaudio.h +++ b/src/audio/disk/SDL_diskaudio.h @@ -27,7 +27,7 @@ #include "SDL_rwops.h" #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData diff --git a/src/audio/dma/SDL_dmaaudio.c b/src/audio/dma/SDL_dmaaudio.c index f1d08cc03..5ee264730 100644 --- a/src/audio/dma/SDL_dmaaudio.c +++ b/src/audio/dma/SDL_dmaaudio.c @@ -21,6 +21,8 @@ */ #include "SDL_config.h" +/* !!! FIXME: merge this driver with "dsp". */ + /* Allow access to a raw mixing buffer */ #include @@ -57,208 +59,100 @@ #define DMA_DRIVER_NAME "dma" /* Open the audio device for playback, and don't block if busy */ -#define OPEN_FLAGS (O_RDWR|O_NONBLOCK) - -/* Audio driver functions */ -static int DMA_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void DMA_WaitAudio(_THIS); -static void DMA_PlayAudio(_THIS); -static Uint8 *DMA_GetAudioBuf(_THIS); -static void DMA_CloseAudio(_THIS); +#define OPEN_FLAGS_INPUT (O_RDWR|O_NONBLOCK) +#define OPEN_FLAGS_OUTPUT (O_RDWR|O_NONBLOCK) -/* Audio driver bootstrap functions */ +static char **outputDevices = NULL; +static int outputDeviceCount = 0; +static char **inputDevices = NULL; +static int inputDeviceCount = 0; static int -Audio_Available(void) +test_for_mmap(int fd) { - int available; - int fd; - - available = 0; - - fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); - if (fd >= 0) { - int caps; - struct audio_buf_info info; - - if ((ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) == 0) && - (caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) && - (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) == 0)) { - available = 1; + int caps = 0; + struct audio_buf_info info; + if ((ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) == 0) && + (caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) && + (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) == 0)) + { + size_t len = info.fragstotal * info.fragsize; + Uint8 *buf = (Uint8 *) mmap(NULL, len, PROT_WRITE, MAP_SHARED, fd, 0); + if (buf != MAP_FAILED) { + munmap(buf, len); + return 1; } - close(fd); } - return (available); + return 0; } -static void -Audio_DeleteDevice(SDL_AudioDevice * device) + +static inline void +free_device_list(char ***devs, int *count) { - SDL_free(device->hidden); - SDL_free(device); + SDL_FreeUnixAudioDevices(devs, count); } -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) +static inline void +build_device_list(int iscapture, char ***devs, int *count) { - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - audio_fd = -1; - - /* Set the function pointers */ - this->OpenAudio = DMA_OpenAudio; - this->WaitAudio = DMA_WaitAudio; - this->PlayAudio = DMA_PlayAudio; - this->GetAudioBuf = DMA_GetAudioBuf; - this->CloseAudio = DMA_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; + const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); + free_device_list(devs, count); + SDL_EnumUnixAudioDevices(flags, 0, test_for_mmap, devs, count); } -AudioBootStrap DMA_bootstrap = { - DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio", - Audio_Available, Audio_CreateDevice -}; - -/* This function waits until it is possible to write a full sound buffer */ -static void -DMA_WaitAudio(_THIS) +static inline void +build_device_lists(void) { - fd_set fdset; - - /* Check to see if the thread-parent process is still alive */ - { - static int cnt = 0; - /* Note that this only works with thread implementations - that use a different process id for each thread. - */ - if (parent && (((++cnt) % 10) == 0)) { /* Check every 10 loops */ - if (kill(parent, 0) < 0) { - this->enabled = 0; - } - } - } + build_device_list(0, &outputDevices, &outputDeviceCount); + build_device_list(1, &inputDevices, &inputDeviceCount); +} - /* See if we need to use timed audio synchronization */ - if (frame_ticks) { - /* Use timer for general audio synchronization */ - Sint32 ticks; - ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS; - if (ticks > 0) { - SDL_Delay(ticks); - } - } else { - /* Use select() for audio synchronization */ - struct timeval timeout; - FD_ZERO(&fdset); - FD_SET(audio_fd, &fdset); - timeout.tv_sec = 10; - timeout.tv_usec = 0; -#ifdef DEBUG_AUDIO - fprintf(stderr, "Waiting for audio to get ready\n"); -#endif - if (select(audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) { - const char *message = -#ifdef AUDIO_OSPACE_HACK - "Audio timeout - buggy audio driver? (trying ospace)"; -#else - "Audio timeout - buggy audio driver? (disabled)"; -#endif - /* In general we should never print to the screen, - but in this case we have no other way of letting - the user know what happened. - */ - fprintf(stderr, "SDL: %s\n", message); -#ifdef AUDIO_OSPACE_HACK - /* We may be able to use GET_OSPACE trick */ - frame_ticks = (float) (this->spec->samples * 1000) / - this->spec->freq; - next_frame = SDL_GetTicks() + frame_ticks; -#else - this->enabled = 0; - /* Don't try to close - may hang */ - audio_fd = -1; -#ifdef DEBUG_AUDIO - fprintf(stderr, "Done disabling audio\n"); -#endif -#endif /* AUDIO_OSPACE_HACK */ - } -#ifdef DEBUG_AUDIO - fprintf(stderr, "Ready!\n"); -#endif - } +static inline void +free_device_lists(void) +{ + free_device_list(&outputDevices, &outputDeviceCount); + free_device_list(&inputDevices, &inputDeviceCount); } -static void -DMA_PlayAudio(_THIS) + +static void DMA_Deinitialize(void) { - /* If timer synchronization is enabled, set the next write frame */ - if (frame_ticks) { - next_frame += frame_ticks; - } - return; + free_device_lists(); } -static Uint8 * -DMA_GetAudioBuf(_THIS) +static int +DMA_DetectDevices(int iscapture) { - count_info info; - int playing; - int filling; - - /* Get number of blocks, looping if we're not using select() */ - do { - if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info) < 0) { - /* Uh oh... */ - this->enabled = 0; - return (NULL); - } - } - while (frame_ticks && (info.blocks < 1)); -#ifdef DEBUG_AUDIO - if (info.blocks > 1) { - printf("Warning: audio underflow (%d frags)\n", info.blocks - 1); + if (iscapture) { + build_device_list(1, &inputDevices, &inputDeviceCount); + return inputDeviceCount; + } else { + build_device_list(0, &outputDevices, &outputDeviceCount); + return outputDeviceCount; } -#endif - playing = info.ptr / this->spec.size; - filling = (playing + 1) % num_buffers; - return (dma_buf + (filling * this->spec.size)); + + return 0; /* shouldn't ever hit this. */ } -static void -DMA_CloseAudio(_THIS) + +static const char * +DMA_GetDeviceName(int index, int iscapture) { - if (dma_buf != NULL) { - munmap(dma_buf, dma_len); - dma_buf = NULL; - } - if (audio_fd >= 0) { - close(audio_fd); - audio_fd = -1; + if ((iscapture) && (index < inputDeviceCount)) { + return inputDevices[index]; + } else if ((!iscapture) && (index < outputDeviceCount)) { + return outputDevices[index]; } + + SDL_SetError("No such device"); + return NULL; } + static int -DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo, - SDL_AudioSpec * spec) +DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo) { int frag_spec; int value; @@ -272,11 +166,11 @@ DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo, } /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Determine the power of two of the fragment size */ - for (frag_spec = 0; (0x01 << frag_spec) < spec->size; ++frag_spec); - if ((0x01 << frag_spec) != spec->size) { + for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec); + if ((0x01 << frag_spec) != this->spec.size) { SDL_SetError("Fragment size must be a power of two"); return (-1); } @@ -295,7 +189,7 @@ DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo, } /* Set mono or stereo audio */ - value = (spec->channels > 1); + value = (this->spec.channels > 1); if ((ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) < 0) || (value != stereo)) { SDL_SetError("Couldn't set audio channels"); @@ -303,48 +197,86 @@ DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo, } /* Set the DSP frequency */ - value = spec->freq; + value = this->spec.freq; if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0) { SDL_SetError("Couldn't set audio frequency"); return (-1); } - spec->freq = value; + this->spec.freq = value; /* We successfully re-opened the audio */ return (0); } + +static void +DMA_CloseDevice(_THIS) +{ + if (this->hidden != NULL) { + if (dma_buf != NULL) { + munmap(dma_buf, dma_len); + dma_buf = NULL; + } + if (audio_fd >= 0) { + close(audio_fd); + audio_fd = -1; + } + SDL_free(this->hidden); + this->hidden = NULL; + } +} + + static int -DMA_OpenAudio(_THIS, SDL_AudioSpec * spec) +DMA_OpenDevice(_THIS, const char *devname, int iscapture) { - char audiodev[1024]; + const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); int format; int stereo; int value; SDL_AudioFormat test_format; struct audio_buf_info info; - /* Reset the timer synchronization flag */ - frame_ticks = 0.0; + /* We don't care what the devname is...we'll try to open anything. */ + /* ...but default to first name in the list... */ + if (devname == NULL) { + if ( ((iscapture) && (inputDeviceCount == 0)) || + ((!iscapture) && (outputDeviceCount == 0)) ) { + SDL_SetError("No such audio device"); + return 0; + } + devname = ((iscapture) ? inputDevices[0] : outputDevices[0]); + } + + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); /* Open the audio device */ - audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); + audio_fd = open(devname, flags, 0); if (audio_fd < 0) { - SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); - return (-1); + DMA_CloseDevice(this); + SDL_SetError("Couldn't open %s: %s", devname, strerror(errno)); + return 0; } dma_buf = NULL; ioctl(audio_fd, SNDCTL_DSP_RESET, 0); /* Get a list of supported hardware formats */ if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) { + DMA_CloseDevice(this); SDL_SetError("Couldn't get audio format list"); - return (-1); + return 0; } /* Try for a closest match on audio format */ format = 0; - for (test_format = SDL_FirstAudioFormat(spec->format); + for (test_format = SDL_FirstAudioFormat(this->spec.format); !format && test_format;) { #ifdef DEBUG_AUDIO fprintf(stderr, "Trying format 0x%4.4x\n", test_format); @@ -389,61 +321,66 @@ DMA_OpenAudio(_THIS, SDL_AudioSpec * spec) } } if (format == 0) { + DMA_CloseDevice(this); SDL_SetError("Couldn't find any hardware audio formats"); - return (-1); + return 0; } - spec->format = test_format; + this->spec.format = test_format; /* Set the audio format */ value = format; if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) { + DMA_CloseDevice(this); SDL_SetError("Couldn't set audio format"); - return (-1); + return 0; } /* Set mono or stereo audio (currently only two channels supported) */ - stereo = (spec->channels > 1); + stereo = (this->spec.channels > 1); ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo); if (stereo) { - spec->channels = 2; + this->spec.channels = 2; } else { - spec->channels = 1; + this->spec.channels = 1; } /* Because some drivers don't allow setting the buffer size after setting the format, we must re-open the audio device once we know what format and channels are supported */ - if (DMA_ReopenAudio(this, audiodev, format, stereo, spec) < 0) { + if (DMA_ReopenAudio(this, devname, format, stereo) < 0) { + DMA_CloseDevice(this); /* Error is set by DMA_ReopenAudio() */ - return (-1); + return 0; } /* Memory map the audio buffer */ if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) < 0) { + DMA_CloseDevice(this); SDL_SetError("Couldn't get OSPACE parameters"); - return (-1); + return 0; } - spec->size = info.fragsize; - spec->samples = spec->size / ((spec->format & 0xFF) / 8); - spec->samples /= spec->channels; + this->spec.size = info.fragsize; + this->spec.samples = this->spec.size / ((this->spec.format & 0xFF) / 8); + this->spec.samples /= this->spec.channels; num_buffers = info.fragstotal; - dma_len = num_buffers * spec->size; + dma_len = num_buffers * this->spec.size; dma_buf = (Uint8 *) mmap(NULL, dma_len, PROT_WRITE, MAP_SHARED, audio_fd, 0); if (dma_buf == MAP_FAILED) { + DMA_CloseDevice(this); SDL_SetError("DMA memory map failed"); dma_buf = NULL; - return (-1); + return 0; } - SDL_memset(dma_buf, spec->silence, dma_len); + SDL_memset(dma_buf, this->spec.silence, dma_len); /* Check to see if we need to use select() workaround */ { char *workaround; workaround = SDL_getenv("SDL_DSP_NOSELECT"); if (workaround) { - frame_ticks = (float) (spec->samples * 1000) / spec->freq; + frame_ticks = (float) (this->spec.samples*1000) / this->spec.freq; next_frame = SDL_GetTicks() + frame_ticks; } } @@ -453,15 +390,145 @@ DMA_OpenAudio(_THIS, SDL_AudioSpec * spec) ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value); value = PCM_ENABLE_OUTPUT; if (ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value) < 0) { + DMA_CloseDevice(this); SDL_SetError("Couldn't trigger audio output"); - return (-1); + return 0; } /* Get the parent process id (we're the parent of the audio thread) */ parent = getpid(); /* We're ready to rock and roll. :-) */ - return (0); + return 1; } + +/* This function waits until it is possible to write a full sound buffer */ +static void +DMA_WaitDevice(_THIS) +{ + fd_set fdset; + + /* Check to see if the thread-parent process is still alive */ + { + static int cnt = 0; + /* Note that this only works with thread implementations + that use a different process id for each thread. + */ + if (parent && (((++cnt) % 10) == 0)) { /* Check every 10 loops */ + if (kill(parent, 0) < 0) { + this->enabled = 0; + } + } + } + + /* See if we need to use timed audio synchronization */ + if (frame_ticks) { + /* Use timer for general audio synchronization */ + Sint32 ticks; + + ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS; + if (ticks > 0) { + SDL_Delay(ticks); + } + } else { + /* Use select() for audio synchronization */ + struct timeval timeout; + FD_ZERO(&fdset); + FD_SET(audio_fd, &fdset); + timeout.tv_sec = 10; + timeout.tv_usec = 0; +#ifdef DEBUG_AUDIO + fprintf(stderr, "Waiting for audio to get ready\n"); +#endif + if (select(audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) { + const char *message = +#ifdef AUDIO_OSPACE_HACK + "Audio timeout - buggy audio driver? (trying ospace)"; +#else + "Audio timeout - buggy audio driver? (disabled)"; +#endif + /* In general we should never print to the screen, + but in this case we have no other way of letting + the user know what happened. + */ + fprintf(stderr, "SDL: %s\n", message); +#ifdef AUDIO_OSPACE_HACK + /* We may be able to use GET_OSPACE trick */ + frame_ticks = (float) (this->spec.samples * 1000) / + this->spec.freq; + next_frame = SDL_GetTicks() + frame_ticks; +#else + this->enabled = 0; + /* Don't try to close - may hang */ + audio_fd = -1; +#ifdef DEBUG_AUDIO + fprintf(stderr, "Done disabling audio\n"); +#endif +#endif /* AUDIO_OSPACE_HACK */ + } +#ifdef DEBUG_AUDIO + fprintf(stderr, "Ready!\n"); +#endif + } +} + +static void +DMA_PlayDevice(_THIS) +{ + /* If timer synchronization is enabled, set the next write frame */ + if (frame_ticks) { + next_frame += frame_ticks; + } + return; +} + +static Uint8 * +DMA_GetDeviceBuf(_THIS) +{ + count_info info; + int playing; + int filling; + + /* Get number of blocks, looping if we're not using select() */ + do { + if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info) < 0) { + /* Uh oh... */ + this->enabled = 0; + return (NULL); + } + } + while (frame_ticks && (info.blocks < 1)); +#ifdef DEBUG_AUDIO + if (info.blocks > 1) { + printf("Warning: audio underflow (%d frags)\n", info.blocks - 1); + } +#endif + playing = info.ptr / this->spec.size; + filling = (playing + 1) % num_buffers; + return (dma_buf + (filling * this->spec.size)); +} + + +static int +DMA_Init(SDL_AudioDriverImpl *impl) +{ + /* Set the function pointers */ + impl->DetectDevices = DMA_DetectDevices; + impl->GetDeviceName = DMA_GetDeviceName; + impl->OpenDevice = DMA_OpenDevice; + impl->WaitDevice = DMA_WaitDevice; + impl->PlayDevice = DMA_PlayDevice; + impl->GetDeviceBuf = DMA_GetDeviceBuf; + impl->CloseDevice = DMA_CloseDevice; + impl->Deinitialize = DMA_Deinitialize; + + build_device_lists(); + return 1; +} + +AudioBootStrap DMA_bootstrap = { + DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio", DMA_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/dma/SDL_dmaaudio.h b/src/audio/dma/SDL_dmaaudio.h index 1d851bd9f..a14c2e940 100644 --- a/src/audio/dma/SDL_dmaaudio.h +++ b/src/audio/dma/SDL_dmaaudio.h @@ -21,12 +21,12 @@ */ #include "SDL_config.h" -#ifndef _SDL_dspaudio_h -#define _SDL_dspaudio_h +#ifndef _SDL_dmaaudio_h +#define _SDL_dmaaudio_h #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData @@ -49,6 +49,7 @@ struct SDL_PrivateAudioData #define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */ /* Old variable names */ +/* !!! FIXME: remove these. */ #define audio_fd (this->hidden->audio_fd) #define parent (this->hidden->parent) #define dma_buf (this->hidden->dma_buf) @@ -57,5 +58,6 @@ struct SDL_PrivateAudioData #define frame_ticks (this->hidden->frame_ticks) #define next_frame (this->hidden->next_frame) -#endif /* _SDL_dspaudio_h */ +#endif /* _SDL_dmaaudio_h */ + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/dmedia/SDL_irixaudio.c b/src/audio/dmedia/SDL_irixaudio.c index c7164efda..bc33a500b 100644 --- a/src/audio/dmedia/SDL_irixaudio.c +++ b/src/audio/dmedia/SDL_irixaudio.c @@ -45,73 +45,12 @@ #define alSetWidth(x,y) ALsetwidth(x,y) #endif -/* Audio driver functions */ -static int AL_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void AL_WaitAudio(_THIS); -static void AL_PlayAudio(_THIS); -static Uint8 *AL_GetAudioBuf(_THIS); -static void AL_CloseAudio(_THIS); - -/* Audio driver bootstrap functions */ - -static int -Audio_Available(void) -{ - return 1; -} - -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - /* Set the function pointers */ - this->OpenAudio = AL_OpenAudio; - this->WaitAudio = AL_WaitAudio; - this->PlayAudio = AL_PlayAudio; - this->GetAudioBuf = AL_GetAudioBuf; - this->CloseAudio = AL_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap DMEDIA_bootstrap = { - "AL", "IRIX DMedia audio", - Audio_Available, Audio_CreateDevice -}; - - void static -AL_WaitAudio(_THIS) +IRIXAUDIO_WaitDevice(_THIS) { Sint32 timeleft; - timeleft = this->spec.samples - alGetFillable(audio_port); + timeleft = this->spec.samples - alGetFillable(this->hidden->audio_port); if (timeleft > 0) { timeleft /= (this->spec.freq / 1000); SDL_Delay((Uint32) timeleft); @@ -119,61 +58,78 @@ AL_WaitAudio(_THIS) } static void -AL_PlayAudio(_THIS) +IRIXAUDIO_PlayDevice(_THIS) { /* Write the audio data out */ - if (alWriteFrames(audio_port, mixbuf, this->spec.samples) < 0) { + ALport port = this->hidden->audio_port; + Uint8 *mixbuf = this->hidden->mixbuf; + if (alWriteFrames(port, mixbuf, this->spec.samples) < 0) { /* Assume fatal error, for now */ this->enabled = 0; } } static Uint8 * -AL_GetAudioBuf(_THIS) +IRIXAUDIO_GetDeviceBuf(_THIS) { - return (mixbuf); + return (this->hidden->mixbuf); } static void -AL_CloseAudio(_THIS) +IRIXAUDIO_CloseDevice(_THIS) { - if (mixbuf != NULL) { - SDL_FreeAudioMem(mixbuf); - mixbuf = NULL; - } - if (audio_port != NULL) { - alClosePort(audio_port); - audio_port = NULL; + if (this->hidden != NULL) { + if (this->hidden->mixbuf != NULL) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + if (this->hidden->audio_port != NULL) { + alClosePort(this->hidden->audio_port); + this->hidden->audio_port = NULL; + } + SDL_free(this->hidden); + this->hidden = NULL; } } static int -AL_OpenAudio(_THIS, SDL_AudioSpec * spec) +IRIXAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) { - SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format); + SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); long width = 0; long fmt = 0; int valid = 0; + /* !!! FIXME: Handle multiple devices and capture? */ + + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + #ifdef OLD_IRIX_AUDIO { long audio_param[2]; audio_param[0] = AL_OUTPUT_RATE; - audio_param[1] = spec->freq; + audio_param[1] = this->spec.freq; valid = (ALsetparams(AL_DEFAULT_DEVICE, audio_param, 2) < 0); } #else { ALpv audio_param; audio_param.param = AL_RATE; - audio_param.value.i = spec->freq; + audio_param.value.i = this->spec.freq; valid = (alSetParams(AL_DEFAULT_OUTPUT, &audio_param, 1) < 0); } #endif while ((!valid) && (test_format)) { valid = 1; - spec->format = test_format; + this->spec.format = test_format; switch (test_format) { case AUDIO_S8: @@ -203,30 +159,31 @@ AL_OpenAudio(_THIS, SDL_AudioSpec * spec) ALconfig audio_config = alNewConfig(); valid = 0; if (audio_config) { - if (alSetChannels(audio_config, spec->channels) < 0) { - if (spec->channels > 2) { /* can't handle > stereo? */ - spec->channels = 2; /* try again below. */ + if (alSetChannels(audio_config, this->spec.channels) < 0) { + if (this->spec.channels > 2) { /* can't handle > stereo? */ + this->spec.channels = 2; /* try again below. */ } } if ((alSetSampFmt(audio_config, fmt) >= 0) && ((!width) || (alSetWidth(audio_config, width) >= 0)) && - (alSetQueueSize(audio_config, spec->samples * 2) >= 0) && - (alSetChannels(audio_config, spec->channels) >= 0)) { + (alSetQueueSize(audio_config,this->spec.samples*2) >= 0) && + (alSetChannels(audio_config, this->spec.channels) >= 0)) { - audio_port = alOpenPort("SDL audio", "w", audio_config); - if (audio_port == NULL) { + this->hidden->audio_port = alOpenPort("SDL audio", "w", + audio_config); + if (this->hidden->audio_port == NULL) { /* docs say AL_BAD_CHANNELS happens here, too. */ int err = oserror(); if (err == AL_BAD_CHANNELS) { - spec->channels = 2; - alSetChannels(audio_config, spec->channels); - audio_port = alOpenPort("SDL audio", "w", - audio_config); + this->spec.channels = 2; + alSetChannels(audio_config, this->spec.channels); + this->hidden->audio_port = alOpenPort("SDL audio", "w", + audio_config); } } - if (audio_port != NULL) { + if (this->hidden->audio_port != NULL) { valid = 1; } } @@ -237,23 +194,43 @@ AL_OpenAudio(_THIS, SDL_AudioSpec * spec) } if (!valid) { + IRIXAUDIO_CloseDevice(this); SDL_SetError("Unsupported audio format"); - return (-1); + return 0; } /* Update the fragment size as size in bytes */ - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Allocate mixing buffer */ - mixbuf = (Uint8 *) SDL_AllocAudioMem(spec->size); - if (mixbuf == NULL) { + this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->spec.size); + if (this->hidden->mixbuf == NULL) { + IRIXAUDIO_CloseDevice(this); SDL_OutOfMemory(); - return (-1); + return 0; } - SDL_memset(mixbuf, spec->silence, spec->size); + SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); /* We're ready to rock and roll. :-) */ - return (0); + return 1; } +static int +IRIXAUDIO_Init(SDL_AudioDriverImpl *impl) +{ + /* Set the function pointers */ + impl->OpenDevice = DSP_OpenDevice; + impl->PlayDevice = DSP_PlayDevice; + impl->WaitDevice = DSP_WaitDevice; + impl->GetDeviceBuf = DSP_GetDeviceBuf; + impl->CloseDevice = DSP_CloseDevice; + impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: not true, I think. */ + + return 1; +} + +AudioBootStrap IRIXAUDIO_bootstrap = { + "AL", "IRIX DMedia audio", IRIXAUDIO_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/dmedia/SDL_irixaudio.h b/src/audio/dmedia/SDL_irixaudio.h index 41d6b31cb..56c92076d 100644 --- a/src/audio/dmedia/SDL_irixaudio.h +++ b/src/audio/dmedia/SDL_irixaudio.h @@ -21,8 +21,8 @@ */ #include "SDL_config.h" -#ifndef _SDL_lowaudio_h -#define _SDL_lowaudio_h +#ifndef _SDL_irixaudio_h +#define _SDL_irixaudio_h #include @@ -33,15 +33,10 @@ struct SDL_PrivateAudioData { - /* The handle for the audio device */ - ALport audio_port; - - Uint8 *mixbuf; /* The app mixing buffer */ + ALport audio_port; /* The handle for the audio device */ + Uint8 *mixbuf; /* The app mixing buffer */ }; -/* Old variable names */ -#define audio_port (this->hidden->audio_port) -#define mixbuf (this->hidden->mixbuf) +#endif /* _SDL_irixaudio_h */ -#endif /* _SDL_lowaudio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/dsp/SDL_dspaudio.c b/src/audio/dsp/SDL_dspaudio.c index 7fd3f06a4..d5a389723 100644 --- a/src/audio/dsp/SDL_dspaudio.c +++ b/src/audio/dsp/SDL_dspaudio.c @@ -55,156 +55,158 @@ #define DSP_DRIVER_NAME "dsp" /* Open the audio device for playback, and don't block if busy */ -#define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) +#define OPEN_FLAGS_OUTPUT (O_WRONLY|O_NONBLOCK) +#define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK) -/* Audio driver functions */ -static int DSP_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void DSP_WaitAudio(_THIS); -static void DSP_PlayAudio(_THIS); -static Uint8 *DSP_GetAudioBuf(_THIS); -static void DSP_CloseAudio(_THIS); +static char **outputDevices = NULL; +static int outputDeviceCount = 0; +static char **inputDevices = NULL; +static int inputDeviceCount = 0; -/* Audio driver bootstrap functions */ - -static int -Audio_Available(void) +static inline void +free_device_list(char ***devs, int *count) { - int fd; - int available; - - available = 0; - fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); - if (fd >= 0) { - available = 1; - close(fd); - } - return (available); + SDL_FreeUnixAudioDevices(devs, count); } -static void -Audio_DeleteDevice(SDL_AudioDevice * device) +static inline void +build_device_list(int iscapture, char ***devs, int *count) { - SDL_free(device->hidden); - SDL_free(device); + const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); + free_device_list(devs, count); + SDL_EnumUnixAudioDevices(flags, 0, NULL, devs, count); } -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) +static inline void +build_device_lists(void) { - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - audio_fd = -1; - - /* Set the function pointers */ - this->OpenAudio = DSP_OpenAudio; - this->WaitAudio = DSP_WaitAudio; - this->PlayAudio = DSP_PlayAudio; - this->GetAudioBuf = DSP_GetAudioBuf; - this->CloseAudio = DSP_CloseAudio; + build_device_list(0, &outputDevices, &outputDeviceCount); + build_device_list(1, &inputDevices, &inputDeviceCount); +} - this->free = Audio_DeleteDevice; - return this; +static inline void +free_device_lists(void) +{ + free_device_list(&outputDevices, &outputDeviceCount); + free_device_list(&inputDevices, &inputDeviceCount); } -AudioBootStrap DSP_bootstrap = { - DSP_DRIVER_NAME, "OSS /dev/dsp standard audio", - Audio_Available, Audio_CreateDevice -}; -/* This function waits until it is possible to write a full sound buffer */ static void -DSP_WaitAudio(_THIS) +DSP_Deinitialize(void) { - /* Not needed at all since OSS handles waiting automagically */ + free_device_lists(); } -static void -DSP_PlayAudio(_THIS) + +static int +DSP_DetectDevices(int iscapture) { - if (write(audio_fd, mixbuf, mixlen) == -1) { - perror("Audio write"); - this->enabled = 0; + if (iscapture) { + build_device_list(1, &inputDevices, &inputDeviceCount); + return inputDeviceCount; + } else { + build_device_list(0, &outputDevices, &outputDeviceCount); + return outputDeviceCount; } -#ifdef DEBUG_AUDIO - fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen); -#endif + + return 0; /* shouldn't ever hit this. */ } -static Uint8 * -DSP_GetAudioBuf(_THIS) +static const char * +DSP_GetDeviceName(int index, int iscapture) { - return (mixbuf); + if ((iscapture) && (index < inputDeviceCount)) { + return inputDevices[index]; + } else if ((!iscapture) && (index < outputDeviceCount)) { + return outputDevices[index]; + } + + SDL_SetError("No such device"); + return NULL; } + static void -DSP_CloseAudio(_THIS) +DSP_CloseDevice(_THIS) { - if (mixbuf != NULL) { - SDL_FreeAudioMem(mixbuf); - mixbuf = NULL; - } - if (audio_fd >= 0) { - close(audio_fd); - audio_fd = -1; + if (this->hidden != NULL) { + if (this->hidden->mixbuf != NULL) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + if (this->hidden->audio_fd >= 0) { + close(this->hidden->audio_fd); + this->hidden->audio_fd = -1; + } + SDL_free(this->hidden); + this->hidden = NULL; } } + static int -DSP_OpenAudio(_THIS, SDL_AudioSpec * spec) +DSP_OpenDevice(_THIS, const char *devname, int iscapture) { - char audiodev[1024]; + const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); int format; int value; int frag_spec; SDL_AudioFormat test_format; + /* We don't care what the devname is...we'll try to open anything. */ + /* ...but default to first name in the list... */ + if (devname == NULL) { + if ( ((iscapture) && (inputDeviceCount == 0)) || + ((!iscapture) && (outputDeviceCount == 0)) ) { + SDL_SetError("No such audio device"); + return 0; + } + devname = ((iscapture) ? inputDevices[0] : outputDevices[0]); + } + + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + /* Open the audio device */ - audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); - if (audio_fd < 0) { - SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); - return (-1); + this->hidden->audio_fd = open(devname, flags, 0); + if (this->hidden->audio_fd < 0) { + DSP_CloseDevice(this); + SDL_SetError("Couldn't open %s: %s", devname, strerror(errno)); + return 0; } - mixbuf = NULL; + this->hidden->mixbuf = NULL; /* Make the file descriptor use blocking writes with fcntl() */ { - long flags; - flags = fcntl(audio_fd, F_GETFL); - flags &= ~O_NONBLOCK; - if (fcntl(audio_fd, F_SETFL, flags) < 0) { + long ctlflags; + ctlflags = fcntl(this->hidden->audio_fd, F_GETFL); + ctlflags &= ~O_NONBLOCK; + if (fcntl(this->hidden->audio_fd, F_SETFL, ctlflags) < 0) { + DSP_CloseDevice(this); SDL_SetError("Couldn't set audio blocking mode"); - DSP_CloseAudio(this); - return (-1); + return 0; } } /* Get a list of supported hardware formats */ - if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) { + if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) { perror("SNDCTL_DSP_GETFMTS"); + DSP_CloseDevice(this); SDL_SetError("Couldn't get audio format list"); - DSP_CloseAudio(this); - return (-1); + return 0; } /* Try for a closest match on audio format */ format = 0; - for (test_format = SDL_FirstAudioFormat(spec->format); + for (test_format = SDL_FirstAudioFormat(this->spec.format); !format && test_format;) { #ifdef DEBUG_AUDIO fprintf(stderr, "Trying format 0x%4.4x\n", test_format); @@ -255,50 +257,51 @@ DSP_OpenAudio(_THIS, SDL_AudioSpec * spec) } } if (format == 0) { + DSP_CloseDevice(this); SDL_SetError("Couldn't find any hardware audio formats"); - DSP_CloseAudio(this); - return (-1); + return 0; } - spec->format = test_format; + this->spec.format = test_format; /* Set the audio format */ value = format; - if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) { + if ( (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || + (value != format) ) { perror("SNDCTL_DSP_SETFMT"); + DSP_CloseDevice(this); SDL_SetError("Couldn't set audio format"); - DSP_CloseAudio(this); - return (-1); + return 0; } /* Set the number of channels of output */ - value = spec->channels; - if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0) { + value = this->spec.channels; + if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0) { perror("SNDCTL_DSP_CHANNELS"); + DSP_CloseDevice(this); SDL_SetError("Cannot set the number of channels"); - DSP_CloseAudio(this); - return (-1); + return 0; } - spec->channels = value; + this->spec.channels = value; /* Set the DSP frequency */ - value = spec->freq; - if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0) { + value = this->spec.freq; + if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SPEED, &value) < 0) { perror("SNDCTL_DSP_SPEED"); + DSP_CloseDevice(this); SDL_SetError("Couldn't set audio frequency"); - DSP_CloseAudio(this); - return (-1); + return 0; } - spec->freq = value; + this->spec.freq = value; /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Determine the power of two of the fragment size */ - for (frag_spec = 0; (0x01U << frag_spec) < spec->size; ++frag_spec); - if ((0x01U << frag_spec) != spec->size) { + for (frag_spec = 0; (0x01U << frag_spec) < this->spec.size; ++frag_spec); + if ((0x01U << frag_spec) != this->spec.size) { + DSP_CloseDevice(this); SDL_SetError("Fragment size must be a power of two"); - DSP_CloseAudio(this); - return (-1); + return 0; } frag_spec |= 0x00020000; /* two fragments, for low latency */ @@ -307,13 +310,13 @@ DSP_OpenAudio(_THIS, SDL_AudioSpec * spec) fprintf(stderr, "Requesting %d fragments of size %d\n", (frag_spec >> 16), 1 << (frag_spec & 0xFFFF)); #endif - if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) { + if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) { perror("SNDCTL_DSP_SETFRAGMENT"); } #ifdef DEBUG_AUDIO { audio_buf_info info; - ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info); + ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETOSPACE, &info); fprintf(stderr, "fragments = %d\n", info.fragments); fprintf(stderr, "fragstotal = %d\n", info.fragstotal); fprintf(stderr, "fragsize = %d\n", info.fragsize); @@ -322,19 +325,59 @@ DSP_OpenAudio(_THIS, SDL_AudioSpec * spec) #endif /* Allocate mixing buffer */ - mixlen = spec->size; - mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen); - if (mixbuf == NULL) { - DSP_CloseAudio(this); - return (-1); + this->hidden->mixlen = this->spec.size; + this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); + if (this->hidden->mixbuf == NULL) { + DSP_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } - SDL_memset(mixbuf, spec->silence, spec->size); - - /* Get the parent process id (we're the parent of the audio thread) */ - parent = getpid(); + SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); /* We're ready to rock and roll. :-) */ - return (0); + return 1; +} + + +static void +DSP_PlayDevice(_THIS) +{ + const Uint8 *mixbuf = this->hidden->mixbuf; + const int mixlen = this->hidden->mixlen; + if (write(this->hidden->audio_fd, mixbuf, mixlen) == -1) { + perror("Audio write"); + this->enabled = 0; + } +#ifdef DEBUG_AUDIO + fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen); +#endif } +static Uint8 * +DSP_GetDeviceBuf(_THIS) +{ + return (this->hidden->mixbuf); +} + +static int +DSP_Init(SDL_AudioDriverImpl *impl) +{ + /* Set the function pointers */ + impl->DetectDevices = DSP_DetectDevices; + impl->GetDeviceName = DSP_GetDeviceName; + impl->OpenDevice = DSP_OpenDevice; + impl->PlayDevice = DSP_PlayDevice; + impl->GetDeviceBuf = DSP_GetDeviceBuf; + impl->CloseDevice = DSP_CloseDevice; + impl->Deinitialize = DSP_Deinitialize; + + build_device_lists(); + return 1; +} + + +AudioBootStrap DSP_bootstrap = { + DSP_DRIVER_NAME, "OSS /dev/dsp standard audio", DSP_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/dsp/SDL_dspaudio.h b/src/audio/dsp/SDL_dspaudio.h index 3f1af967b..30eafad62 100644 --- a/src/audio/dsp/SDL_dspaudio.h +++ b/src/audio/dsp/SDL_dspaudio.h @@ -26,7 +26,7 @@ #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData @@ -34,22 +34,11 @@ struct SDL_PrivateAudioData /* The file descriptor for the audio device */ int audio_fd; - /* The parent process id, to detect when application quits */ - pid_t parent; - /* Raw mixing buffer */ Uint8 *mixbuf; int mixlen; }; #define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */ -/* Old variable names */ -#define audio_fd (this->hidden->audio_fd) -#define parent (this->hidden->parent) -#define mixbuf (this->hidden->mixbuf) -#define mixlen (this->hidden->mixlen) -#define frame_ticks (this->hidden->frame_ticks) -#define next_frame (this->hidden->next_frame) - #endif /* _SDL_dspaudio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/dummy/SDL_dummyaudio.c b/src/audio/dummy/SDL_dummyaudio.c index b8b9c96bf..f6b51122d 100644 --- a/src/audio/dummy/SDL_dummyaudio.c +++ b/src/audio/dummy/SDL_dummyaudio.c @@ -25,141 +25,27 @@ /* Output audio to nowhere... */ -#include "SDL_rwops.h" -#include "SDL_timer.h" #include "SDL_audio.h" -#include "../SDL_audiomem.h" #include "../SDL_audio_c.h" -#include "../SDL_audiodev_c.h" #include "SDL_dummyaudio.h" -/* The tag name used by DUMMY audio */ -#define DUMMYAUD_DRIVER_NAME "dummy" - -/* Audio driver functions */ -static int DUMMYAUD_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void DUMMYAUD_WaitAudio(_THIS); -static void DUMMYAUD_PlayAudio(_THIS); -static Uint8 *DUMMYAUD_GetAudioBuf(_THIS); -static void DUMMYAUD_CloseAudio(_THIS); - -/* Audio driver bootstrap functions */ static int -DUMMYAUD_Available(void) -{ - const char *envr = SDL_getenv("SDL_AUDIODRIVER"); - if (envr && (SDL_strcmp(envr, DUMMYAUD_DRIVER_NAME) == 0)) { - return (1); - } - return (0); -} - -static void -DUMMYAUD_DeleteDevice(SDL_AudioDevice * device) +DUMMYAUD_OpenDevice(_THIS, const char *devname, int iscapture) { - SDL_free(device->hidden); - SDL_free(device); + return 1; /* always succeeds. */ } -static SDL_AudioDevice * -DUMMYAUD_CreateDevice(int devindex) +static int +DUMMYAUD_Init(SDL_AudioDriverImpl *impl) { - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - /* Set the function pointers */ - this->OpenAudio = DUMMYAUD_OpenAudio; - this->WaitAudio = DUMMYAUD_WaitAudio; - this->PlayAudio = DUMMYAUD_PlayAudio; - this->GetAudioBuf = DUMMYAUD_GetAudioBuf; - this->CloseAudio = DUMMYAUD_CloseAudio; - - this->free = DUMMYAUD_DeleteDevice; - - return this; + impl->OpenDevice = DUMMYAUD_OpenDevice; + impl->OnlyHasDefaultOutputDevice = 1; + return 1; } AudioBootStrap DUMMYAUD_bootstrap = { - DUMMYAUD_DRIVER_NAME, "SDL dummy audio driver", - DUMMYAUD_Available, DUMMYAUD_CreateDevice + "dummy", "SDL dummy audio driver", DUMMYAUD_Init, 1 }; -/* This function waits until it is possible to write a full sound buffer */ -static void -DUMMYAUD_WaitAudio(_THIS) -{ - /* Don't block on first calls to simulate initial fragment filling. */ - if (this->hidden->initial_calls) - this->hidden->initial_calls--; - else - SDL_Delay(this->hidden->write_delay); -} - -static void -DUMMYAUD_PlayAudio(_THIS) -{ - /* no-op...this is a null driver. */ -} - -static Uint8 * -DUMMYAUD_GetAudioBuf(_THIS) -{ - return (this->hidden->mixbuf); -} - -static void -DUMMYAUD_CloseAudio(_THIS) -{ - if (this->hidden->mixbuf != NULL) { - SDL_FreeAudioMem(this->hidden->mixbuf); - this->hidden->mixbuf = NULL; - } -} - -static int -DUMMYAUD_OpenAudio(_THIS, SDL_AudioSpec * spec) -{ - float bytes_per_sec = 0.0f; - - /* Allocate mixing buffer */ - this->hidden->mixlen = spec->size; - this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); - if (this->hidden->mixbuf == NULL) { - return (-1); - } - SDL_memset(this->hidden->mixbuf, spec->silence, spec->size); - - bytes_per_sec = (float) (((spec->format & 0xFF) / 8) * - spec->channels * spec->freq); - - /* - * We try to make this request more audio at the correct rate for - * a given audio spec, so timing stays fairly faithful. - * Also, we have it not block at all for the first two calls, so - * it seems like we're filling two audio fragments right out of the - * gate, like other SDL drivers tend to do. - */ - this->hidden->initial_calls = 2; - this->hidden->write_delay = - (Uint32) ((((float) spec->size) / bytes_per_sec) * 1000.0f); - - /* We're ready to rock and roll. :-) */ - return (0); -} - /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/dummy/SDL_dummyaudio.h b/src/audio/dummy/SDL_dummyaudio.h index 58adcf802..c9ef8c4f5 100644 --- a/src/audio/dummy/SDL_dummyaudio.h +++ b/src/audio/dummy/SDL_dummyaudio.h @@ -26,7 +26,7 @@ #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData diff --git a/src/audio/esd/SDL_esdaudio.c b/src/audio/esd/SDL_esdaudio.c index ade0e47e8..927cabb31 100644 --- a/src/audio/esd/SDL_esdaudio.c +++ b/src/audio/esd/SDL_esdaudio.c @@ -33,7 +33,6 @@ #include "SDL_audio.h" #include "../SDL_audiomem.h" #include "../SDL_audio_c.h" -#include "../SDL_audiodev_c.h" #include "SDL_esdaudio.h" #ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC @@ -46,40 +45,34 @@ /* The tag name used by ESD audio */ #define ESD_DRIVER_NAME "esd" -/* Audio driver functions */ -static int ESD_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void ESD_WaitAudio(_THIS); -static void ESD_PlayAudio(_THIS); -static Uint8 *ESD_GetAudioBuf(_THIS); -static void ESD_CloseAudio(_THIS); - #ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC static const char *esd_library = SDL_AUDIO_DRIVER_ESD_DYNAMIC; static void *esd_handle = NULL; -static int esd_loaded = 0; static int (*SDL_NAME(esd_open_sound)) (const char *host); static int (*SDL_NAME(esd_close)) (int esd); static int (*SDL_NAME(esd_play_stream)) (esd_format_t format, int rate, const char *host, const char *name); + +#define SDL_ESD_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) } static struct { const char *name; void **func; } esd_functions[] = { - { - "esd_open_sound", (void **) &SDL_NAME(esd_open_sound)}, { - "esd_close", (void **) &SDL_NAME(esd_close)}, { -"esd_play_stream", (void **) &SDL_NAME(esd_play_stream)},}; + SDL_ESD_SYM(esd_open_sound), + SDL_ESD_SYM(esd_close), + SDL_ESD_SYM(esd_play_stream), +}; +#undef SDL_ESD_SYM static void UnloadESDLibrary() { - if (esd_loaded) { + if (esd_handle != NULL) { SDL_UnloadObject(esd_handle); esd_handle = NULL; - esd_loaded = 0; } } @@ -88,17 +81,18 @@ LoadESDLibrary(void) { int i, retval = -1; - esd_handle = SDL_LoadObject(esd_library); - if (esd_handle) { - esd_loaded = 1; - retval = 0; - for (i = 0; i < SDL_arraysize(esd_functions); ++i) { - *esd_functions[i].func = - SDL_LoadFunction(esd_handle, esd_functions[i].name); - if (!*esd_functions[i].func) { - retval = -1; - UnloadESDLibrary(); - break; + if (esd_handle == NULL) { + esd_handle = SDL_LoadObject(esd_library); + if (esd_handle) { + retval = 0; + for (i = 0; i < SDL_arraysize(esd_functions); ++i) { + *esd_functions[i].func = + SDL_LoadFunction(esd_handle, esd_functions[i].name); + if (!*esd_functions[i].func) { + retval = -1; + UnloadESDLibrary(); + break; + } } } } @@ -121,78 +115,10 @@ LoadESDLibrary(void) #endif /* SDL_AUDIO_DRIVER_ESD_DYNAMIC */ -/* Audio driver bootstrap functions */ - -static int -Audio_Available(void) -{ - int connection; - int available; - - available = 0; - if (LoadESDLibrary() < 0) { - return available; - } - connection = SDL_NAME(esd_open_sound) (NULL); - if (connection >= 0) { - available = 1; - SDL_NAME(esd_close) (connection); - } - UnloadESDLibrary(); - return (available); -} - -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); - UnloadESDLibrary(); -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - LoadESDLibrary(); - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - audio_fd = -1; - - /* Set the function pointers */ - this->OpenAudio = ESD_OpenAudio; - this->WaitAudio = ESD_WaitAudio; - this->PlayAudio = ESD_PlayAudio; - this->GetAudioBuf = ESD_GetAudioBuf; - this->CloseAudio = ESD_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap ESD_bootstrap = { - ESD_DRIVER_NAME, "Enlightened Sound Daemon", - Audio_Available, Audio_CreateDevice -}; /* This function waits until it is possible to write a full sound buffer */ static void -ESD_WaitAudio(_THIS) +ESD_WaitDevice(_THIS) { Sint32 ticks; @@ -202,28 +128,31 @@ ESD_WaitAudio(_THIS) /* Note that this only works with thread implementations that use a different process id for each thread. */ - if (parent && (((++cnt) % 10) == 0)) { /* Check every 10 loops */ - if (kill(parent, 0) < 0) { + /* Check every 10 loops */ + if (this->hidden->parent && (((++cnt) % 10) == 0)) { + if (kill(this->hidden->parent, 0) < 0) { this->enabled = 0; } } } /* Use timer for general audio synchronization */ - ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS; + ticks = ((Sint32) (this->hidden->next_frame-SDL_GetTicks())) - FUDGE_TICKS; if (ticks > 0) { SDL_Delay(ticks); } } static void -ESD_PlayAudio(_THIS) +ESD_PlayDevice(_THIS) { - int written; + int written = 0; /* Write the audio data, checking for EAGAIN on broken audio drivers */ do { - written = write(audio_fd, mixbuf, mixlen); + written = write(this->hidden->audio_fd, + this->hidden->mixbuf, + this->hidden->mixlen); if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) { SDL_Delay(1); /* Let a little CPU time go by */ } @@ -232,7 +161,7 @@ ESD_PlayAudio(_THIS) ((errno == 0) || (errno == EAGAIN) || (errno == EINTR))); /* Set the next write frame */ - next_frame += frame_ticks; + this->hidden->next_frame += this->hidden->frame_ticks; /* If we couldn't write, assume fatal error for now */ if (written < 0) { @@ -241,21 +170,26 @@ ESD_PlayAudio(_THIS) } static Uint8 * -ESD_GetAudioBuf(_THIS) +ESD_GetDeviceBuf(_THIS) { - return (mixbuf); + return (this->hidden->mixbuf); } static void -ESD_CloseAudio(_THIS) +ESD_CloseDevice(_THIS) { - if (mixbuf != NULL) { - SDL_FreeAudioMem(mixbuf); - mixbuf = NULL; - } - if (audio_fd >= 0) { - SDL_NAME(esd_close) (audio_fd); - audio_fd = -1; + if (this->hidden != NULL) { + if (this->hidden->mixbuf != NULL) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + if (this->hidden->audio_fd >= 0) { + SDL_NAME(esd_close) (this->hidden->audio_fd); + this->hidden->audio_fd = -1; + } + + SDL_free(this->hidden); + this->hidden = NULL; } } @@ -285,59 +219,135 @@ get_progname(void) return (progname); } + static int -ESD_OpenAudio(_THIS, SDL_AudioSpec * spec) +ESD_OpenDevice(_THIS, const char *devname, int iscapture) { - esd_format_t format; + esd_format_t format = (ESD_STREAM | ESD_PLAY); + SDL_AudioFormat test_format = 0; + int found = 0; + + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + this->hidden->audio_fd = -1; /* Convert audio spec to the ESD audio format */ - format = (ESD_STREAM | ESD_PLAY); - switch (spec->format & 0xFF) { - case 8: - format |= ESD_BITS8; - break; - case 16: - format |= ESD_BITS16; - break; - default: - SDL_SetError("Unsupported ESD audio format"); - return (-1); + /* Try for a closest match on audio format */ + for (test_format = SDL_FirstAudioFormat(this->spec.format); + !found && test_format; test_format = SDL_NextAudioFormat()) { +#ifdef DEBUG_AUDIO + fprintf(stderr, "Trying format 0x%4.4x\n", test_format); +#endif + found = 1; + switch (test_format) { + case AUDIO_U8: + format |= ESD_BITS8; + break; + case AUDIO_S16SYS: + format |= ESD_BITS16; + break; + default: + found = 0; + break; + } } - if (spec->channels == 1) { + + if (!found) { + ESD_CloseDevice(this); + SDL_SetError("Couldn't find any hardware audio formats"); + return 0; + } + + if (this->spec.channels == 1) { format |= ESD_MONO; } else { format |= ESD_STEREO; } #if 0 - spec->samples = ESD_BUF_SIZE; /* Darn, no way to change this yet */ + this->spec.samples = ESD_BUF_SIZE; /* Darn, no way to change this yet */ #endif /* Open a connection to the ESD audio server */ - audio_fd = - SDL_NAME(esd_play_stream) (format, spec->freq, NULL, get_progname()); - if (audio_fd < 0) { + this->hidden->audio_fd = + SDL_NAME(esd_play_stream)(format,this->spec.freq,NULL,get_progname()); + + if (this->hidden->audio_fd < 0) { + ESD_CloseDevice(this); SDL_SetError("Couldn't open ESD connection"); - return (-1); + return 0; } /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(spec); - frame_ticks = (float) (spec->samples * 1000) / spec->freq; - next_frame = SDL_GetTicks() + frame_ticks; + SDL_CalculateAudioSpec(&this->spec); + this->hidden->frame_ticks = (float) (this->spec.samples*1000) / this->spec.freq; + this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks; /* Allocate mixing buffer */ - mixlen = spec->size; - mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen); - if (mixbuf == NULL) { - return (-1); + this->hidden->mixlen = this->spec.size; + this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); + if (this->hidden->mixbuf == NULL) { + ESD_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } - SDL_memset(mixbuf, spec->silence, spec->size); + SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); /* Get the parent process id (we're the parent of the audio thread) */ - parent = getpid(); + this->hidden->parent = getpid(); /* We're ready to rock and roll. :-) */ - return (0); + return 1; +} + +static void +ESD_Deinitialize(void) +{ + UnloadESDLibrary(); +} + +static int +ESD_Init(SDL_AudioDriverImpl *impl) +{ + if (LoadESDLibrary() < 0) { + return 0; + } else { + int connection = 0; + + /* Don't start ESD if it's not running */ + if (SDL_getenv("ESD_NO_SPAWN") == NULL) { + SDL_putenv("ESD_NO_SPAWN=1"); + } + + connection = SDL_NAME(esd_open_sound) (NULL); + if (connection < 0) { + UnloadESDLibrary(); + SDL_SetError("ESD: esd_open_sound failed (no audio server?)"); + return 0; + } + SDL_NAME(esd_close) (connection); + } + + /* Set the function pointers */ + impl->OpenDevice = ESD_OpenDevice; + impl->PlayDevice = ESD_PlayDevice; + impl->WaitDevice = ESD_WaitDevice; + impl->GetDeviceBuf = ESD_GetDeviceBuf; + impl->CloseDevice = ESD_CloseDevice; + impl->Deinitialize = ESD_Deinitialize; + impl->OnlyHasDefaultOutputDevice = 1; + + return 1; } + +AudioBootStrap ESD_bootstrap = { + ESD_DRIVER_NAME, "Enlightened Sound Daemon", ESD_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/esd/SDL_esdaudio.h b/src/audio/esd/SDL_esdaudio.h index b3abeca7d..010ed6294 100644 --- a/src/audio/esd/SDL_esdaudio.h +++ b/src/audio/esd/SDL_esdaudio.h @@ -26,7 +26,7 @@ #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData @@ -47,13 +47,5 @@ struct SDL_PrivateAudioData }; #define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */ -/* Old variable names */ -#define audio_fd (this->hidden->audio_fd) -#define parent (this->hidden->parent) -#define mixbuf (this->hidden->mixbuf) -#define mixlen (this->hidden->mixlen) -#define frame_ticks (this->hidden->frame_ticks) -#define next_frame (this->hidden->next_frame) - #endif /* _SDL_esdaudio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/macosx/SDL_coreaudio.c b/src/audio/macosx/SDL_coreaudio.c index 4dd9002e9..729aca00d 100644 --- a/src/audio/macosx/SDL_coreaudio.c +++ b/src/audio/macosx/SDL_coreaudio.c @@ -21,6 +21,7 @@ */ #include "SDL_config.h" +#include #include #include "SDL_audio.h" @@ -28,79 +29,233 @@ #include "../SDL_sysaudio.h" #include "SDL_coreaudio.h" +#define DEBUG_COREAUDIO 0 -/* Audio driver functions */ - -static int Core_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void Core_WaitAudio(_THIS); -static void Core_PlayAudio(_THIS); -static Uint8 *Core_GetAudioBuf(_THIS); -static void Core_CloseAudio(_THIS); +typedef struct COREAUDIO_DeviceList +{ + AudioDeviceID id; + const char *name; +} COREAUDIO_DeviceList; -/* Audio driver bootstrap functions */ +static COREAUDIO_DeviceList *inputDevices = NULL; +static int inputDeviceCount = 0; +static COREAUDIO_DeviceList *outputDevices = NULL; +static int outputDeviceCount = 0; -static int -Audio_Available(void) +static void +free_device_list(COREAUDIO_DeviceList **devices, int *devCount) { - return (1); + if (*devices) { + int i = *devCount; + while (i--) + SDL_free((void *) (*devices)[i].name); + SDL_free(*devices); + *devices = NULL; + } + *devCount = 0; } + static void -Audio_DeleteDevice(SDL_AudioDevice * device) +build_device_list(int iscapture, COREAUDIO_DeviceList **devices, int *devCount) { - SDL_free(device->hidden); - SDL_free(device); + Boolean outWritable = 0; + OSStatus result = noErr; + UInt32 size = 0; + AudioDeviceID *devs = NULL; + UInt32 i = 0; + UInt32 max = 0; + + free_device_list(devices, devCount); + + result = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, + &size, &outWritable); + + if (result != kAudioHardwareNoError) + return; + + devs = (AudioDeviceID *) alloca(size); + if (devs == NULL) + return; + + max = size / sizeof (AudioDeviceID); + *devices = (COREAUDIO_DeviceList *) SDL_malloc(max * sizeof (**devices)); + if (*devices == NULL) + return; + + result = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, + &size, devs); + if (result != kAudioHardwareNoError) + return; + + for (i = 0; i < max; i++) { + CFStringRef cfstr = NULL; + char *ptr = NULL; + AudioDeviceID dev = devs[i]; + AudioBufferList *buflist = NULL; + int usable = 0; + CFIndex len = 0; + + result = AudioDeviceGetPropertyInfo(dev, 0, iscapture, + kAudioDevicePropertyStreamConfiguration, + &size, &outWritable); + if (result != noErr) + continue; + + buflist = (AudioBufferList *) SDL_malloc(size); + if (buflist == NULL) + continue; + + result = AudioDeviceGetProperty(dev, 0, iscapture, + kAudioDevicePropertyStreamConfiguration, + &size, buflist); + + if (result == noErr) { + UInt32 j; + for (j = 0; j < buflist->mNumberBuffers; j++) { + if (buflist->mBuffers[j].mNumberChannels > 0) { + usable = 1; + break; + } + } + } + + SDL_free(buflist); + + if (!usable) + continue; + + size = sizeof (CFStringRef); + result = AudioDeviceGetProperty(dev, 0, iscapture, + kAudioObjectPropertyName, + &size, &cfstr); + + if (result != kAudioHardwareNoError) + continue; + + len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr), + kCFStringEncodingUTF8); + + ptr = (char *) SDL_malloc(len + 1); + usable = ( (ptr != NULL) && + (CFStringGetCString(cfstr,ptr,len+1,kCFStringEncodingUTF8)) ); + + CFRelease(cfstr); + + if (usable) { + len = strlen(ptr); + /* Some devices have whitespace at the end...trim it. */ + while ((len > 0) && (ptr[len-1] == ' ')) { + len--; + } + usable = (len > 0); + } + + if (!usable) { + SDL_free(ptr); + } else { + ptr[len] = '\0'; + + #if DEBUG_COREAUDIO + printf("COREAUDIO: Found %s device #%d: '%s' (devid %d)\n", + ((iscapture) ? "capture" : "output"), + (int) *devCount, ptr, (int) dev); + #endif + + (*devices)[*devCount].id = dev; + (*devices)[*devCount].name = ptr; + (*devCount)++; + } + } } -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) +static inline void +build_device_lists(void) { - SDL_AudioDevice *this; + build_device_list(0, &outputDevices, &outputDeviceCount); + build_device_list(1, &inputDevices, &inputDeviceCount); +} - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); + +static inline void +free_device_lists(void) +{ + free_device_list(&outputDevices, &outputDeviceCount); + free_device_list(&inputDevices, &inputDeviceCount); +} + + +static int +find_device_id(const char *devname, int iscapture, AudioDeviceID *id) +{ + int i = ((iscapture) ? inputDeviceCount : outputDeviceCount); + COREAUDIO_DeviceList *devs = ((iscapture) ? inputDevices : outputDevices); + while (i--) { + if (SDL_strcmp(devname, devs->name) == 0) { + *id = devs->id; + return 1; } - return (0); + devs++; } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - /* Set the function pointers */ - this->OpenAudio = Core_OpenAudio; - this->WaitAudio = Core_WaitAudio; - this->PlayAudio = Core_PlayAudio; - this->GetAudioBuf = Core_GetAudioBuf; - this->CloseAudio = Core_CloseAudio; + return 0; +} + + +static int +COREAUDIO_DetectDevices(int iscapture) +{ + if (iscapture) { + build_device_list(1, &inputDevices, &inputDeviceCount); + return inputDeviceCount; + } else { + build_device_list(0, &outputDevices, &outputDeviceCount); + return outputDeviceCount; + } - this->free = Audio_DeleteDevice; + return 0; /* shouldn't ever hit this. */ +} - return this; + +static const char * +COREAUDIO_GetDeviceName(int index, int iscapture) +{ + if ((iscapture) && (index < inputDeviceCount)) { + return inputDevices[index].name; + } else if ((!iscapture) && (index < outputDeviceCount)) { + return outputDevices[index].name; + } + + SDL_SetError("No such device"); + return NULL; +} + + +static void +COREAUDIO_Deinitialize(void) +{ + free_device_lists(); } -AudioBootStrap COREAUDIO_bootstrap = { - "coreaudio", "Mac OS X CoreAudio", - Audio_Available, Audio_CreateDevice -}; /* The CoreAudio callback */ static OSStatus -audioCallback(void *inRefCon, - AudioUnitRenderActionFlags inActionFlags, +outputCallback(void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp * inTimeStamp, - UInt32 inBusNumber, AudioBuffer * ioData) + UInt32 inBusNumber, UInt32 inNumberFrames, + AudioBufferList *ioDataList) { SDL_AudioDevice *this = (SDL_AudioDevice *) inRefCon; + AudioBuffer *ioData = &ioDataList->mBuffers[0]; UInt32 remaining, len; void *ptr; + /* Is there ever more than one buffer, and what do you do with it? */ + if (ioDataList->mNumberBuffers != 1) { + return noErr; + } + /* Only do anything if audio is enabled and not paused */ if (!this->enabled || this->paused) { SDL_memset(ioData->mData, this->spec.silence, ioData->mDataByteSize); @@ -118,109 +273,251 @@ audioCallback(void *inRefCon, remaining = ioData->mDataByteSize; ptr = ioData->mData; while (remaining > 0) { - if (bufferOffset >= bufferSize) { + if (this->hidden->bufferOffset >= this->hidden->bufferSize) { /* Generate the data */ - SDL_memset(buffer, this->spec.silence, bufferSize); + SDL_memset(this->hidden->buffer, this->spec.silence, + this->hidden->bufferSize); SDL_mutexP(this->mixer_lock); - (*this->spec.callback) (this->spec.userdata, buffer, bufferSize); + (*this->spec.callback) (this->spec.userdata, this->hidden->buffer, + this->hidden->bufferSize); SDL_mutexV(this->mixer_lock); - bufferOffset = 0; + this->hidden->bufferOffset = 0; } - len = bufferSize - bufferOffset; + len = this->hidden->bufferSize - this->hidden->bufferOffset; if (len > remaining) len = remaining; - SDL_memcpy(ptr, (char *) buffer + bufferOffset, len); + SDL_memcpy(ptr, + (char *) this->hidden->buffer + this->hidden->bufferOffset, + len); ptr = (char *) ptr + len; remaining -= len; - bufferOffset += len; + this->hidden->bufferOffset += len; } return 0; } -/* Dummy functions -- we don't use thread-based audio */ -void -Core_WaitAudio(_THIS) +static OSStatus +inputCallback(void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp * inTimeStamp, + UInt32 inBusNumber, UInt32 inNumberFrames, + AudioBufferList *ioData) { - return; + //err = AudioUnitRender(afr->fAudioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, afr->fAudioBuffer); + // !!! FIXME: write me! + return noErr; } -void -Core_PlayAudio(_THIS) -{ - return; -} -Uint8 * -Core_GetAudioBuf(_THIS) +static void +COREAUDIO_CloseDevice(_THIS) { - return (NULL); + if (this->hidden != NULL) { + OSStatus result = noErr; + AURenderCallbackStruct callback; + const AudioUnitElement output_bus = 0; + const AudioUnitElement input_bus = 1; + const int iscapture = this->iscapture; + const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus); + const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output : + kAudioUnitScope_Input); + + /* stop processing the audio unit */ + result = AudioOutputUnitStop(this->hidden->audioUnit); + + /* Remove the input callback */ + SDL_memset(&callback, '\0', sizeof (AURenderCallbackStruct)); + result = AudioUnitSetProperty(this->hidden->audioUnit, + kAudioUnitProperty_SetRenderCallback, + scope, bus, &callback, sizeof (callback)); + + CloseComponent(this->hidden->audioUnit); + + SDL_free(this->hidden->buffer); + SDL_free(this->hidden); + this->hidden = NULL; + } } -void -Core_CloseAudio(_THIS) -{ - OSStatus result; - struct AudioUnitInputCallback callback; - /* stop processing the audio unit */ - result = AudioOutputUnitStop(outputAudioUnit); - if (result != noErr) { - SDL_SetError("Core_CloseAudio: AudioOutputUnitStop"); - return; +#define CHECK_RESULT(msg) \ + if (result != noErr) { \ + COREAUDIO_CloseDevice(this); \ + SDL_SetError("CoreAudio error (%s): %d", msg, (int) result); \ + return 0; \ } - /* Remove the input callback */ - callback.inputProc = 0; - callback.inputProcRefCon = 0; - result = AudioUnitSetProperty(outputAudioUnit, - kAudioUnitProperty_SetInputCallback, - kAudioUnitScope_Input, - 0, &callback, sizeof(callback)); - if (result != noErr) { - SDL_SetError - ("Core_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)"); - return; +static int +find_device_by_name(_THIS, const char *devname, int iscapture) +{ + AudioDeviceID devid = 0; + OSStatus result = noErr; + UInt32 size = 0; + UInt32 alive = 0; + pid_t pid = 0; + + if (devname == NULL) { + size = sizeof (AudioDeviceID); + const AudioHardwarePropertyID propid = + ((iscapture) ? kAudioHardwarePropertyDefaultInputDevice : + kAudioHardwarePropertyDefaultOutputDevice); + + result = AudioHardwareGetProperty(propid, &size, &devid); + CHECK_RESULT("AudioHardwareGetProperty (default device)"); + } else { + if (!find_device_id(devname, iscapture, &devid)) { + SDL_SetError("CoreAudio: No such audio device."); + return 0; + } } - result = CloseComponent(outputAudioUnit); - if (result != noErr) { - SDL_SetError("Core_CloseAudio: CloseComponent"); - return; + size = sizeof (alive); + result = AudioDeviceGetProperty(devid, 0, iscapture, + kAudioDevicePropertyDeviceIsAlive, + &size, &alive); + CHECK_RESULT("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)"); + + if (!alive) { + SDL_SetError("CoreAudio: requested device exists, but isn't alive."); + return 0; } - SDL_free(buffer); -} + size = sizeof (pid); + result = AudioDeviceGetProperty(devid, 0, iscapture, + kAudioDevicePropertyHogMode, &size, &pid); -#define CHECK_RESULT(msg) \ - if (result != noErr) { \ - SDL_SetError("CoreAudio error (%s): %d", msg, (int) result); \ - return -1; \ + /* some devices don't support this property, so errors are fine here. */ + if ((result == noErr) && (pid != -1)) { + SDL_SetError("CoreAudio: requested device is being hogged."); + return 0; } + this->hidden->deviceID = devid; + return 1; +} + -int -Core_OpenAudio(_THIS, SDL_AudioSpec * spec) +static int +prepare_audiounit(_THIS, const char *devname, int iscapture, + const AudioStreamBasicDescription *strdesc) { OSStatus result = noErr; - Component comp; + AURenderCallbackStruct callback; ComponentDescription desc; - struct AudioUnitInputCallback callback; + Component comp = NULL; + int use_system_device = 0; + UInt32 enableIO = 0; + const AudioUnitElement output_bus = 0; + const AudioUnitElement input_bus = 1; + const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus); + const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output : + kAudioUnitScope_Input); + + if (!find_device_by_name(this, devname, iscapture)) { + SDL_SetError("Couldn't find requested CoreAudio device"); + return 0; + } + + SDL_memset(&desc, '\0', sizeof(ComponentDescription)); + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_HALOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + + comp = FindNextComponent(NULL, &desc); + if (comp == NULL) { + SDL_SetError("Couldn't find requested CoreAudio component"); + return 0; + } + + /* Open & initialize the audio unit */ + result = OpenAComponent(comp, &this->hidden->audioUnit); + CHECK_RESULT("OpenAComponent"); + + // !!! FIXME: this is wrong? + enableIO = ((iscapture) ? 1 : 0); + result = AudioUnitSetProperty(this->hidden->audioUnit, + kAudioOutputUnitProperty_EnableIO, + kAudioUnitScope_Input, input_bus, + &enableIO, sizeof (enableIO)); + CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_EnableIO input)"); + + // !!! FIXME: this is wrong? + enableIO = ((iscapture) ? 0 : 1); + result = AudioUnitSetProperty(this->hidden->audioUnit, + kAudioOutputUnitProperty_EnableIO, + kAudioUnitScope_Output, output_bus, + &enableIO, sizeof (enableIO)); + CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_EnableIO output)"); + + result = AudioUnitSetProperty(this->hidden->audioUnit, + kAudioOutputUnitProperty_CurrentDevice, + kAudioUnitScope_Global, 0, + &this->hidden->deviceID, + sizeof (AudioDeviceID)); + CHECK_RESULT("AudioUnitSetProperty (kAudioOutputUnitProperty_CurrentDevice)"); + + /* Set the data format of the audio unit. */ + result = AudioUnitSetProperty(this->hidden->audioUnit, + kAudioUnitProperty_StreamFormat, + scope, bus, strdesc, sizeof (*strdesc)); + CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)"); + + /* Set the audio callback */ + SDL_memset(&callback, '\0', sizeof (AURenderCallbackStruct)); + callback.inputProc = ((iscapture) ? inputCallback : outputCallback); + callback.inputProcRefCon = this; + result = AudioUnitSetProperty(this->hidden->audioUnit, + kAudioUnitProperty_SetRenderCallback, + scope, bus, &callback, sizeof (callback)); + CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)"); + + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(&this->spec); + + /* Allocate a sample buffer */ + this->hidden->bufferOffset = this->hidden->bufferSize = this->spec.size; + this->hidden->buffer = SDL_malloc(this->hidden->bufferSize); + + result = AudioUnitInitialize(this->hidden->audioUnit); + CHECK_RESULT("AudioUnitInitialize"); + + /* Finally, start processing of the audio unit */ + result = AudioOutputUnitStart(this->hidden->audioUnit); + CHECK_RESULT("AudioOutputUnitStart"); + + /* We're running! */ + return 1; +} + + +static int +COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) +{ AudioStreamBasicDescription strdesc; - SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format); + SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); int valid_datatype = 0; + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return (0); + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + /* Setup a AudioStreamBasicDescription with the requested format */ - memset(&strdesc, '\0', sizeof(AudioStreamBasicDescription)); + SDL_memset(&strdesc, '\0', sizeof(AudioStreamBasicDescription)); strdesc.mFormatID = kAudioFormatLinearPCM; strdesc.mFormatFlags = kLinearPCMFormatFlagIsPacked; - strdesc.mChannelsPerFrame = spec->channels; - strdesc.mSampleRate = spec->freq; + strdesc.mChannelsPerFrame = this->spec.channels; + strdesc.mSampleRate = this->spec.freq; strdesc.mFramesPerPacket = 1; while ((!valid_datatype) && (test_format)) { - spec->format = test_format; + this->spec.format = test_format; /* Just a list of valid SDL formats, so people don't pass junk here. */ switch (test_format) { case AUDIO_U8: @@ -234,13 +531,13 @@ Core_OpenAudio(_THIS, SDL_AudioSpec * spec) case AUDIO_F32LSB: case AUDIO_F32MSB: valid_datatype = 1; - strdesc.mBitsPerChannel = SDL_AUDIO_BITSIZE(spec->format); - if (SDL_AUDIO_ISBIGENDIAN(spec->format)) + strdesc.mBitsPerChannel = SDL_AUDIO_BITSIZE(this->spec.format); + if (SDL_AUDIO_ISBIGENDIAN(this->spec.format)) strdesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; - if (SDL_AUDIO_ISFLOAT(spec->format)) + if (SDL_AUDIO_ISFLOAT(this->spec.format)) strdesc.mFormatFlags |= kLinearPCMFormatFlagIsFloat; - else if (SDL_AUDIO_ISSIGNED(spec->format)) + else if (SDL_AUDIO_ISSIGNED(this->spec.format)) strdesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger; break; } @@ -248,7 +545,7 @@ Core_OpenAudio(_THIS, SDL_AudioSpec * spec) if (!valid_datatype) { /* shouldn't happen, but just in case... */ SDL_SetError("Unsupported audio format"); - return (-1); + return 0; } strdesc.mBytesPerFrame = @@ -256,52 +553,31 @@ Core_OpenAudio(_THIS, SDL_AudioSpec * spec) strdesc.mBytesPerPacket = strdesc.mBytesPerFrame * strdesc.mFramesPerPacket; - /* Locate the default output audio unit */ - memset(&desc, '\0', sizeof(ComponentDescription)); - desc.componentType = kAudioUnitComponentType; - desc.componentSubType = kAudioUnitSubType_Output; - desc.componentManufacturer = kAudioUnitID_DefaultOutput; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - - comp = FindNextComponent(NULL, &desc); - if (comp == NULL) { - SDL_SetError - ("Failed to start CoreAudio: FindNextComponent returned NULL"); - return -1; + if (!prepare_audiounit(this, devname, iscapture, &strdesc)) { + return 0; /* prepare_audiounit() will call SDL_SetError()... */ } - /* Open & initialize the default output audio unit */ - result = OpenAComponent(comp, &outputAudioUnit); - CHECK_RESULT("OpenAComponent") - result = AudioUnitInitialize(outputAudioUnit); - CHECK_RESULT("AudioUnitInitialize") - /* Set the input format of the audio unit. */ - result = AudioUnitSetProperty(outputAudioUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, - 0, &strdesc, sizeof(strdesc)); - CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)") - /* Set the audio callback */ - callback.inputProc = audioCallback; - callback.inputProcRefCon = this; - result = AudioUnitSetProperty(outputAudioUnit, - kAudioUnitProperty_SetInputCallback, - kAudioUnitScope_Input, - 0, &callback, sizeof(callback)); - CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)") - /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(spec); + return 1; /* good to go. */ +} - /* Allocate a sample buffer */ - bufferOffset = bufferSize = this->spec.size; - buffer = SDL_malloc(bufferSize); +static int +COREAUDIO_Init(SDL_AudioDriverImpl *impl) +{ + /* Set the function pointers */ + impl->DetectDevices = COREAUDIO_DetectDevices; + impl->GetDeviceName = COREAUDIO_GetDeviceName; + impl->OpenDevice = COREAUDIO_OpenDevice; + impl->CloseDevice = COREAUDIO_CloseDevice; + impl->Deinitialize = COREAUDIO_Deinitialize; + impl->ProvidesOwnCallbackThread = 1; - /* Finally, start processing of the audio unit */ - result = AudioOutputUnitStart(outputAudioUnit); - CHECK_RESULT("AudioOutputUnitStart") - /* We're running! */ - return (1); + build_device_lists(); /* do an initial check for devices... */ + + return 1; } +AudioBootStrap COREAUDIO_bootstrap = { + "coreaudio", "Mac OS X CoreAudio", COREAUDIO_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/macosx/SDL_coreaudio.h b/src/audio/macosx/SDL_coreaudio.h index 8167ace1e..25aa9c217 100644 --- a/src/audio/macosx/SDL_coreaudio.h +++ b/src/audio/macosx/SDL_coreaudio.h @@ -26,22 +26,17 @@ #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData { - AudioUnit outputAudioUnit; + AudioUnit audioUnit; void *buffer; UInt32 bufferOffset; UInt32 bufferSize; + AudioDeviceID deviceID; }; -/* Old variable names */ -#define outputAudioUnit (this->hidden->outputAudioUnit) -#define buffer (this->hidden->buffer) -#define bufferOffset (this->hidden->bufferOffset) -#define bufferSize (this->hidden->bufferSize) - #endif /* _SDL_coreaudio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/macrom/SDL_romaudio.c b/src/audio/macrom/SDL_romaudio.c index cc106bd45..5b16c75a1 100644 --- a/src/audio/macrom/SDL_romaudio.c +++ b/src/audio/macrom/SDL_romaudio.c @@ -21,11 +21,16 @@ */ #include "SDL_config.h" +/* This should work on PowerPC and Intel Mac OS X, and Carbonized Mac OS 9. */ + #if defined(__APPLE__) && defined(__MACH__) +# define SDL_MACOS_NAME "Mac OS X" # include #elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) +# define SDL_MACOS_NAME "Mac OS 9" # include #else +# define SDL_MACOS_NAME "Mac OS 9" # include /* SoundManager interface */ # include # include @@ -45,72 +50,6 @@ #include "../SDL_sysaudio.h" #include "SDL_romaudio.h" -/* Audio driver functions */ - -static void Mac_CloseAudio(_THIS); -static int Mac_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void Mac_LockAudio(_THIS); -static void Mac_UnlockAudio(_THIS); - -/* Audio driver bootstrap functions */ - - -static int -Audio_Available(void) -{ - return (1); -} - -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - /* Set the function pointers */ - this->OpenAudio = Mac_OpenAudio; - this->CloseAudio = Mac_CloseAudio; - this->LockAudio = Mac_LockAudio; - this->UnlockAudio = Mac_UnlockAudio; - this->free = Audio_DeleteDevice; - -#ifdef __MACOSX__ /* Mac OS X uses threaded audio, so normal thread code is okay */ - this->LockAudio = NULL; - this->UnlockAudio = NULL; -#endif - return this; -} - -AudioBootStrap SNDMGR_bootstrap = { - "sndmgr", "MacOS SoundManager 3.0", - Audio_Available, Audio_CreateDevice -}; - -#if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE) -/* This works correctly on Mac OS X */ - #pragma options align=power static volatile SInt32 audio_is_locked = 0; @@ -121,6 +60,7 @@ static volatile UInt32 running = 0; static CmpSoundHeader header; static volatile Uint32 fill_me = 0; + static void mix_buffer(SDL_AudioDevice * audio, UInt8 * buffer) { @@ -150,13 +90,13 @@ mix_buffer(SDL_AudioDevice * audio, UInt8 * buffer) } static void -Mac_LockAudio(_THIS) +SNDMGR_LockDevice(_THIS) { IncrementAtomic((SInt32 *) & audio_is_locked); } static void -Mac_UnlockAudio(_THIS) +SNDMGR_UnlockDevice(_THIS) { SInt32 oldval; @@ -198,7 +138,7 @@ callBackProc(SndChannel * chan, SndCommand * cmd_passed) cmd.param2 = (long) &header; SndDoCommand(chan, &cmd, 0); - memset(buffer[fill_me], 0, audio->spec.size); + SDL_memset(buffer[fill_me], 0, audio->spec.size); /* * if audio device isn't locked, mix the next buffer to be queued in @@ -219,14 +159,25 @@ callBackProc(SndChannel * chan, SndCommand * cmd_passed) } static int -Mac_OpenAudio(_THIS, SDL_AudioSpec * spec) +SNDMGR_OpenDevice(_THIS, const char *devname, int iscapture) { - + SDL_AudioSpec *spec = &this->spec; + SndChannelPtr channel = NULL; SndCallBackUPP callback; int sample_bits; int i; long initOptions; + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + /* !!! FIXME: iterate through format matrix... */ /* Very few conversions are required, but... */ switch (spec->format) { case AUDIO_S8: @@ -242,10 +193,10 @@ Mac_OpenAudio(_THIS, SDL_AudioSpec * spec) spec->format = AUDIO_F32MSB; break; } - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* initialize bufferCmd header */ - memset(&header, 0, sizeof(header)); + SDL_memset(&header, 0, sizeof(header)); callback = (SndCallBackUPP) NewSndCallBackUPP(callBackProc); sample_bits = spec->size / spec->samples / spec->channels * 8; @@ -278,20 +229,23 @@ Mac_OpenAudio(_THIS, SDL_AudioSpec * spec) /* allocate 2 buffers */ for (i = 0; i < 2; i++) { - buffer[i] = (UInt8 *) malloc(sizeof(UInt8) * spec->size); + buffer[i] = (UInt8 *) SDL_malloc(sizeof(UInt8) * spec->size); if (buffer[i] == NULL) { + SNDMGR_CloseDevice(this); SDL_OutOfMemory(); - return (-1); + return 0; } - memset(buffer[i], 0, spec->size); + SDL_memset(buffer[i], 0, spec->size); } /* Create the sound manager channel */ channel = (SndChannelPtr) SDL_malloc(sizeof(*channel)); if (channel == NULL) { + SNDMGR_CloseDevice(this); SDL_OutOfMemory(); - return (-1); + return 0; } + this->hidden->channel = channel; if (spec->channels >= 2) { initOptions = initStereo; } else { @@ -300,10 +254,9 @@ Mac_OpenAudio(_THIS, SDL_AudioSpec * spec) channel->userInfo = (long) this; channel->qLength = 128; if (SndNewChannel(&channel, sampledSynth, initOptions, callback) != noErr) { + SNDMGR_CloseDevice(this); SDL_SetError("Unable to create audio channel"); - SDL_free(channel); - channel = NULL; - return (-1); + return 0; } /* start playback */ @@ -319,16 +272,15 @@ Mac_OpenAudio(_THIS, SDL_AudioSpec * spec) } static void -Mac_CloseAudio(_THIS) +SNDMGR_CloseDevice(_THIS) { - int i; running = 0; - if (channel) { - SndDisposeChannel(channel, true); - channel = NULL; + if (this->hidden->channel) { + SndDisposeChannel(this->hidden->channel, true); + this->hidden->channel = NULL; } for (i = 0; i < 2; ++i) { @@ -337,193 +289,31 @@ Mac_CloseAudio(_THIS) buffer[i] = NULL; } } -} - -#else /* !TARGET_API_MAC_CARBON && !USE_RYANS_SOUNDCODE */ - -static void -Mac_LockAudio(_THIS) -{ - /* no-op. */ -} - -static void -Mac_UnlockAudio(_THIS) -{ - /* no-op. */ -} - - -/* This function is called by Sound Manager when it has exhausted one of - the buffers, so we'll zero it to silence and fill it with audio if - we're not paused. -*/ -static pascal void -sndDoubleBackProc(SndChannelPtr chan, SndDoubleBufferPtr newbuf) -{ - SDL_AudioDevice *audio = (SDL_AudioDevice *) newbuf->dbUserInfo[0]; - - /* If audio is quitting, don't do anything */ - if (!audio->enabled) { - return; - } - memset(newbuf->dbSoundData, 0, audio->spec.size); - newbuf->dbNumFrames = audio->spec.samples; - if (!audio->paused) { - if (audio->convert.needed) { - audio->spec.callback(audio->spec.userdata, - (Uint8 *) audio->convert.buf, - audio->convert.len); - SDL_ConvertAudio(&audio->convert); -#if 0 - if (audio->convert.len_cvt != audio->spec.size) { - /* Uh oh... probably crashes here */ ; - } -#endif - SDL_memcpy(newbuf->dbSoundData, audio->convert.buf, - audio->convert.len_cvt); - } else { - audio->spec.callback(audio->spec.userdata, - (Uint8 *) newbuf->dbSoundData, - audio->spec.size); - } - } - newbuf->dbFlags |= dbBufferReady; + SDL_free(this->hidden); + this->hidden = NULL; } static int -DoubleBufferAudio_Available(void) +SNDMGR_Init(SDL_AudioDriverImpl *impl) { - int available; - NumVersion sndversion; - long response; - - available = 0; - sndversion = SndSoundManagerVersion(); - if (sndversion.majorRev >= 3) { - if (Gestalt(gestaltSoundAttr, &response) == noErr) { - if ((response & (1 << gestaltSndPlayDoubleBuffer))) { - available = 1; - } - } - } else { - if (Gestalt(gestaltSoundAttr, &response) == noErr) { - if ((response & (1 << gestaltHasASC))) { - available = 1; - } - } - } - return (available); -} - -static void -Mac_CloseAudio(_THIS) -{ - int i; - - if (channel != NULL) { - /* Clean up the audio channel */ - SndDisposeChannel(channel, true); - channel = NULL; - } - for (i = 0; i < 2; ++i) { - if (audio_buf[i]) { - SDL_free(audio_buf[i]); - audio_buf[i] = NULL; - } - } -} - -static int -Mac_OpenAudio(_THIS, SDL_AudioSpec * spec) -{ - SndDoubleBufferHeader2 audio_dbh; - int i; - long initOptions; - int sample_bits; - SndDoubleBackUPP doubleBackProc; - - /* Check to make sure double-buffered audio is available */ - if (!DoubleBufferAudio_Available()) { - SDL_SetError("Sound manager doesn't support double-buffering"); - return (-1); - } - - /* Very few conversions are required, but... */ - switch (spec->format) { - case AUDIO_S8: - spec->format = AUDIO_U8; - break; - case AUDIO_U16LSB: - spec->format = AUDIO_S16LSB; - break; - case AUDIO_U16MSB: - spec->format = AUDIO_S16MSB; - break; - } - SDL_CalculateAudioSpec(spec); - - /* initialize the double-back header */ - SDL_memset(&audio_dbh, 0, sizeof(audio_dbh)); - doubleBackProc = NewSndDoubleBackProc(sndDoubleBackProc); - sample_bits = spec->size / spec->samples / spec->channels * 8; - - audio_dbh.dbhNumChannels = spec->channels; - audio_dbh.dbhSampleSize = sample_bits; - audio_dbh.dbhCompressionID = 0; - audio_dbh.dbhPacketSize = 0; - audio_dbh.dbhSampleRate = spec->freq << 16; - audio_dbh.dbhDoubleBack = doubleBackProc; - audio_dbh.dbhFormat = 0; - - /* Note that we install the 16bitLittleEndian Converter if needed. */ - if (spec->format == 0x8010) { - audio_dbh.dbhCompressionID = fixedCompression; - audio_dbh.dbhFormat = k16BitLittleEndianFormat; - } - - /* allocate the 2 double-back buffers */ - for (i = 0; i < 2; ++i) { - audio_buf[i] = SDL_calloc(1, sizeof(SndDoubleBuffer) + spec->size); - if (audio_buf[i] == NULL) { - SDL_OutOfMemory(); - return (-1); - } - audio_buf[i]->dbNumFrames = spec->samples; - audio_buf[i]->dbFlags = dbBufferReady; - audio_buf[i]->dbUserInfo[0] = (long) this; - audio_dbh.dbhBufferPtr[i] = audio_buf[i]; - } - - /* Create the sound manager channel */ - channel = (SndChannelPtr) SDL_malloc(sizeof(*channel)); - if (channel == NULL) { - SDL_OutOfMemory(); - return (-1); - } - if (spec->channels >= 2) { - initOptions = initStereo; - } else { - initOptions = initMono; - } - channel->userInfo = 0; - channel->qLength = 128; - if (SndNewChannel(&channel, sampledSynth, initOptions, 0L) != noErr) { - SDL_SetError("Unable to create audio channel"); - SDL_free(channel); - channel = NULL; - return (-1); - } - - /* Start playback */ - if (SndPlayDoubleBuffer(channel, (SndDoubleBufferHeaderPtr) & audio_dbh) - != noErr) { - SDL_SetError("Unable to play double buffered audio"); - return (-1); - } + /* Set the function pointers */ + impl->OpenDevice = SNDMGR_OpenDevice; + impl->CloseDevice = SNDMGR_CloseDevice; + impl->ProvidesOwnCallbackThread = 1; + impl->OnlyHasDefaultOutputDevice = 1; + +/* Mac OS X uses threaded audio, so normal thread code is okay */ +#ifndef __MACOSX__ + impl->LockDevice = SNDMGR_LockDevice; + impl->UnlockDevice = SNDMGR_UnlockDevice; + impl->SkipMixerLock = 1; +#endif return 1; } -#endif /* TARGET_API_MAC_CARBON || USE_RYANS_SOUNDCODE */ +AudioBootStrap SNDMGR_bootstrap = { + "sndmgr", SDL_MACOS_NAME " SoundManager", SNDMGR_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/macrom/SDL_romaudio.h b/src/audio/macrom/SDL_romaudio.h index 23633182f..633328061 100644 --- a/src/audio/macrom/SDL_romaudio.h +++ b/src/audio/macrom/SDL_romaudio.h @@ -26,27 +26,14 @@ #include "../SDL_sysaudio.h" -/* This is Ryan's improved MacOS sound code, with locking support */ -#define USE_RYANS_SOUNDCODE - -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData { /* Sound manager audio channel */ SndChannelPtr channel; -#if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE) - /* FIXME: Add Ryan's static data here */ -#else - /* Double buffering variables */ - SndDoubleBufferPtr audio_buf[2]; -#endif }; -/* Old variable names */ -#define channel (this->hidden->channel) -#define audio_buf (this->hidden->audio_buf) - #endif /* _SDL_romaudio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/mint/SDL_mintaudio_dma8.c b/src/audio/mint/SDL_mintaudio_dma8.c index 97270df6f..60d91e940 100644 --- a/src/audio/mint/SDL_mintaudio_dma8.c +++ b/src/audio/mint/SDL_mintaudio_dma8.c @@ -61,105 +61,8 @@ static unsigned long cookie_snd, cookie_mch; -/*--- Audio driver functions ---*/ - -static void Mint_CloseAudio(_THIS); -static int Mint_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void Mint_LockAudio(_THIS); -static void Mint_UnlockAudio(_THIS); - -/* To check/init hardware audio */ -static int Mint_CheckAudio(_THIS, SDL_AudioSpec * spec); -static void Mint_InitAudio(_THIS, SDL_AudioSpec * spec); - -/*--- Audio driver bootstrap functions ---*/ - -static int -Audio_Available(void) -{ - const char *envr = SDL_getenv("SDL_AUDIODRIVER"); - - /* Check if user asked a different audio driver */ - if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME) != 0)) { - DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n")); - return 0; - } - - /* Cookie _MCH present ? if not, assume ST machine */ - if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) { - cookie_mch = MCH_ST; - } - - /* Cookie _SND present ? if not, assume ST machine */ - if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { - cookie_snd = SND_PSG; - } - - /* Check if we have 8 bits audio */ - if ((cookie_snd & SND_8BIT) == 0) { - DEBUG_PRINT((DEBUG_NAME "no 8 bits sound\n")); - return (0); - } - - /* Check if audio is lockable */ - if (cookie_snd & SND_16BIT) { - if (Locksnd() != 1) { - DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n")); - return (0); - } - - Unlocksnd(); - } - - DEBUG_PRINT((DEBUG_NAME "8 bits audio available!\n")); - return (1); -} - static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - /* Set the function pointers */ - this->OpenAudio = Mint_OpenAudio; - this->CloseAudio = Mint_CloseAudio; - this->LockAudio = Mint_LockAudio; - this->UnlockAudio = Mint_UnlockAudio; - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap MINTAUDIO_DMA8_bootstrap = { - MINT_AUDIO_DRIVER_NAME, "MiNT DMA 8 bits audio driver", - Audio_Available, Audio_CreateDevice -}; - -static void -Mint_LockAudio(_THIS) +MINTDMA8_LockDevice(_THIS) { void *oldpile; @@ -170,7 +73,7 @@ Mint_LockAudio(_THIS) } static void -Mint_UnlockAudio(_THIS) +MINTDMA8_UnlockDevice(_THIS) { void *oldpile; @@ -181,57 +84,59 @@ Mint_UnlockAudio(_THIS) } static void -Mint_CloseAudio(_THIS) +MINTDMA8_CloseDevice(_THIS) { - void *oldpile; + if (this->hidden != NULL) { + /* Stop replay */ + void *oldpile = (void *) Super(0); - /* Stop replay */ - oldpile = (void *) Super(0); - DMAAUDIO_IO.control = 0; - Super(oldpile); + DMAAUDIO_IO.control = 0; + Super(oldpile); - DEBUG_PRINT((DEBUG_NAME "closeaudio: replay stopped\n")); + DEBUG_PRINT((DEBUG_NAME "closeaudio: replay stopped\n")); - /* Disable interrupt */ - Jdisint(MFP_DMASOUND); + /* Disable interrupt */ + Jdisint(MFP_DMASOUND); - DEBUG_PRINT((DEBUG_NAME "closeaudio: interrupt disabled\n")); + DEBUG_PRINT((DEBUG_NAME "closeaudio: interrupt disabled\n")); - /* Wait if currently playing sound */ - while (SDL_MintAudio_mutex != 0) { - } + /* Wait if currently playing sound */ + while (SDL_MintAudio_mutex != 0) {} - DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n")); + DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n")); - /* Clear buffers */ - if (SDL_MintAudio_audiobuf[0]) { - Mfree(SDL_MintAudio_audiobuf[0]); - SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; - } + /* Clear buffers */ + if (SDL_MintAudio_audiobuf[0]) { + Mfree(SDL_MintAudio_audiobuf[0]); + SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; + } - DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n")); + DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n")); + SDL_free(this->buffer); + this->buffer = NULL; + } } static int -Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) +MINTDMA8_CheckAudio(_THIS) { int i, masterprediv, sfreq; unsigned long masterclock; DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ", - SDL_AUDIO_BITSIZE(spec->format))); - DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); - DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); - DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); - DEBUG_PRINT(("channels=%d, ", spec->channels)); - DEBUG_PRINT(("freq=%d\n", spec->freq)); - - if (spec->channels > 2) { - spec->channels = 2; /* no more than stereo! */ + SDL_AUDIO_BITSIZE(this->spec.format))); + DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format))); + DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format))); + DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format))); + DEBUG_PRINT(("channels=%d, ", this->spec.channels)); + DEBUG_PRINT(("freq=%d\n", this->spec.freq)); + + if (this->spec.channels > 2) { + this->spec.channels = 2; /* no more than stereo! */ } /* Check formats available */ - spec->format = AUDIO_S8; + this->spec.format = AUDIO_S8; /* Calculate and select the closest frequency */ sfreq = 0; @@ -272,22 +177,22 @@ Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) } #endif - MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, spec->freq); - spec->freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; + MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq); + this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ", - SDL_AUDIO_BITSIZE(spec->format))); - DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); - DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); - DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); - DEBUG_PRINT(("channels=%d, ", spec->channels)); - DEBUG_PRINT(("freq=%d\n", spec->freq)); + SDL_AUDIO_BITSIZE(this->spec.format))); + DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format))); + DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format))); + DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format))); + DEBUG_PRINT(("channels=%d, ", this->spec.channels)); + DEBUG_PRINT(("freq=%d\n", this->spec.freq)); return 0; } static void -Mint_InitAudio(_THIS, SDL_AudioSpec * spec) +MINTDMA8_InitAudio(_THIS) { void *oldpile; unsigned long buffer; @@ -316,7 +221,7 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) DMAAUDIO_IO.end_low = buffer & 255; mode = 3 - MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor; - if (spec->channels == 1) { + if (this->spec.channels == 1) { mode |= 1 << 7; } DMAAUDIO_IO.sound_ctrl = mode; @@ -339,29 +244,40 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) } static int -Mint_OpenAudio(_THIS, SDL_AudioSpec * spec) +MINTDMA8_OpenDevice(_THIS, const char *devname, int iscapture) { SDL_MintAudio_device = this; /* Check audio capabilities */ - if (Mint_CheckAudio(this, spec) == -1) { - return -1; + if (MINTDMA8_CheckAudio(this) == -1) { + return 0; } - SDL_CalculateAudioSpec(spec); + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + SDL_CalculateAudioSpec(&this->spec); /* Allocate memory for audio buffers in DMA-able RAM */ - DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size)); + DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size)); - SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size * 2, MX_STRAM); + SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(this->spec.size * 2, MX_STRAM); if (SDL_MintAudio_audiobuf[0] == NULL) { - SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); - return (-1); + SDL_free(this->hidden); + this->hidden = NULL; + SDL_OutOfMemory(); + return 0; } - SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size; + SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size; SDL_MintAudio_numbuf = 0; - SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size * 2); - SDL_MintAudio_audiosize = spec->size; + SDL_memset(SDL_MintAudio_audiobuf[0],this->spec.silence,this->spec.size*2); + SDL_MintAudio_audiosize = this->spec.size; SDL_MintAudio_mutex = 0; DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", @@ -372,9 +288,56 @@ Mint_OpenAudio(_THIS, SDL_AudioSpec * spec) SDL_MintAudio_CheckFpu(); /* Setup audio hardware */ - Mint_InitAudio(this, spec); + MINTDMA8_InitAudio(this); - return (1); /* We don't use threaded audio */ + return 1; /* good to go. */ } +static int +MINTDMA8_Init(SDL_AudioDriverImpl *impl) +{ + /* Cookie _MCH present ? if not, assume ST machine */ + if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) { + cookie_mch = MCH_ST; + } + + /* Cookie _SND present ? if not, assume ST machine */ + if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { + cookie_snd = SND_PSG; + } + + /* Check if we have 8 bits audio */ + if ((cookie_snd & SND_8BIT) == 0) { + SDL_SetError(DEBUG_NAME "no 8 bits sound"); + return 0; + } + + /* Check if audio is lockable */ + if (cookie_snd & SND_16BIT) { + if (Locksnd() != 1) { + SDL_SetError(DEBUG_NAME "audio locked by other application"); + return 0; + } + + Unlocksnd(); + } + + DEBUG_PRINT((DEBUG_NAME "8 bits audio available!\n")); + + /* Set the function pointers */ + impl->OpenDevice = MINTDMA8_OpenDevice; + impl->CloseDevice = MINTDMA8_CloseDevice; + impl->LockAudio = MINTDMA8_LockAudio; + impl->UnlockAudio = MINTDMA8_UnlockAudio; + impl->OnlyHasDefaultOutputDevice = 1; + impl->ProvidesOwnCallbackThread = 1; + impl->SkipMixerLock = 1; + + return 1; +} + +AudioBootStrap MINTAUDIO_DMA8_bootstrap = { + MINT_AUDIO_DRIVER_NAME, "MiNT DMA 8 bits audio driver", MINTDMA8_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/mint/SDL_mintaudio_gsxb.c b/src/audio/mint/SDL_mintaudio_gsxb.c index d7b3847a0..0b0f2841a 100644 --- a/src/audio/mint/SDL_mintaudio_gsxb.c +++ b/src/audio/mint/SDL_mintaudio_gsxb.c @@ -63,176 +63,83 @@ static unsigned long cookie_snd, cookie_gsxb; /*--- Audio driver functions ---*/ -static void Mint_CloseAudio(_THIS); -static int Mint_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void Mint_LockAudio(_THIS); -static void Mint_UnlockAudio(_THIS); - -/* To check/init hardware audio */ -static int Mint_CheckAudio(_THIS, SDL_AudioSpec * spec); -static void Mint_InitAudio(_THIS, SDL_AudioSpec * spec); - /* GSXB callbacks */ -static void Mint_GsxbInterrupt(void); -static void Mint_GsxbNullInterrupt(void); - -/*--- Audio driver bootstrap functions ---*/ - -static int -Audio_Available(void) -{ - const char *envr = SDL_getenv("SDL_AUDIODRIVER"); - - /* Check if user asked a different audio driver */ - if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME) != 0)) { - DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n")); - return (0); - } - - /* Cookie _SND present ? if not, assume ST machine */ - if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { - cookie_snd = SND_PSG; - } - - /* Check if we have 16 bits audio */ - if ((cookie_snd & SND_16BIT) == 0) { - DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n")); - return (0); - } - - /* Cookie GSXB present ? */ - cookie_gsxb = (Getcookie(C_GSXB, &cookie_gsxb) == C_FOUND); - - /* Is it GSXB ? */ - if (((cookie_snd & SND_GSXB) == 0) || (cookie_gsxb == 0)) { - DEBUG_PRINT((DEBUG_NAME "no GSXB audio\n")); - return (0); - } - - /* Check if audio is lockable */ - if (Locksnd() != 1) { - DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n")); - return (0); - } - - Unlocksnd(); - - DEBUG_PRINT((DEBUG_NAME "GSXB audio available!\n")); - return (1); -} +static void MINTGSXB_GsxbInterrupt(void); +static void MINTGSXB_GsxbNullInterrupt(void); static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - /* Set the function pointers */ - this->OpenAudio = Mint_OpenAudio; - this->CloseAudio = Mint_CloseAudio; - this->LockAudio = Mint_LockAudio; - this->UnlockAudio = Mint_UnlockAudio; - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap MINTAUDIO_GSXB_bootstrap = { - MINT_AUDIO_DRIVER_NAME, "MiNT GSXB audio driver", - Audio_Available, Audio_CreateDevice -}; - -static void -Mint_LockAudio(_THIS) +MINTGSXB_LockDevice(_THIS) { /* Stop replay */ Buffoper(0); } static void -Mint_UnlockAudio(_THIS) +MINTGSXB_UnlockDevice(_THIS) { /* Restart replay */ Buffoper(SB_PLA_ENA | SB_PLA_RPT); } static void -Mint_CloseAudio(_THIS) +MINTGSXB_CloseDevice(_THIS) { - /* Stop replay */ - Buffoper(0); + if (this->hidden != NULL) { + /* Stop replay */ + Buffoper(0); - /* Uninstall interrupt */ - if (NSetinterrupt(2, SI_NONE, Mint_GsxbNullInterrupt) < 0) { - DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed in close\n")); - } + /* Uninstall interrupt */ + if (NSetinterrupt(2, SI_NONE, MINTGSXB_GsxbNullInterrupt) < 0) { + DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed in close\n")); + } - /* Wait if currently playing sound */ - while (SDL_MintAudio_mutex != 0) { - } + /* Wait if currently playing sound */ + while (SDL_MintAudio_mutex != 0) {} - /* Clear buffers */ - if (SDL_MintAudio_audiobuf[0]) { - Mfree(SDL_MintAudio_audiobuf[0]); - SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; - } + /* Clear buffers */ + if (SDL_MintAudio_audiobuf[0]) { + Mfree(SDL_MintAudio_audiobuf[0]); + SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; + } - /* Unlock sound system */ - Unlocksnd(); + /* Unlock sound system */ + Unlocksnd(); + + SDL_free(this->hidden); + this->hidden = NULL; + } } static int -Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) +MINTGSXB_CheckAudio(_THIS) { long snd_format; int i, resolution, format_signed, format_bigendian; - SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format); + SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); int valid_datatype = 0; - resolution = SDL_AUDIO_BITSIZE(spec->format); - format_signed = SDL_AUDIO_ISSIGNED(spec->format); - format_bigendian = SDL_AUDIO_ISBIGENDIAN(spec->format); + resolution = SDL_AUDIO_BITSIZE(this->spec.format); + format_signed = SDL_AUDIO_ISSIGNED(this->spec.format); + format_bigendian = SDL_AUDIO_ISBIGENDIAN(this->spec.format); DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ", resolution)); - DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); + DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format))); DEBUG_PRINT(("signed=%d, ", format_signed)); DEBUG_PRINT(("big endian=%d, ", format_bigendian)); - DEBUG_PRINT(("channels=%d, ", spec->channels)); - DEBUG_PRINT(("freq=%d\n", spec->freq)); + DEBUG_PRINT(("channels=%d, ", this->spec.channels)); + DEBUG_PRINT(("freq=%d\n", this->spec.freq)); - if (spec->channels > 2) { - spec->channels = 2; /* no more than stereo! */ + if (this->spec.channels > 2) { + this->spec.channels = 2; /* no more than stereo! */ } while ((!valid_datatype) && (test_format)) { /* Check formats available */ snd_format = Sndstatus(SND_QUERYFORMATS); - spec->format = test_format; - resolution = SDL_AUDIO_BITSIZE(spec->format); - format_signed = SDL_AUDIO_ISSIGNED(spec->format); - format_bigendian = SDL_AUDIO_ISBIGENDIAN(spec->format); + this->spec.format = test_format; + resolution = SDL_AUDIO_BITSIZE(this->spec.format); + format_signed = SDL_AUDIO_ISSIGNED(this->spec.format); + format_bigendian = SDL_AUDIO_ISBIGENDIAN(this->spec.format); switch (test_format) { case AUDIO_U8: case AUDIO_S8: @@ -279,14 +186,14 @@ Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) /* Ok */ } else if (snd_format & SND_FORMATUNSIGNED) { /* Give unsigned format */ - spec->format = spec->format & (~SDL_AUDIO_MASK_SIGNED); + this->spec.format = this->spec.format & (~SDL_AUDIO_MASK_SIGNED); } } else { if (snd_format & SND_FORMATUNSIGNED) { /* Ok */ } else if (snd_format & SND_FORMATSIGNED) { /* Give signed format */ - spec->format |= SDL_AUDIO_MASK_SIGNED; + this->spec.format |= SDL_AUDIO_MASK_SIGNED; } } @@ -295,14 +202,14 @@ Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) /* Ok */ } else if (snd_format & SND_FORMATLITTLEENDIAN) { /* Give little endian format */ - spec->format = spec->format & (~SDL_AUDIO_MASK_ENDIAN); + this->spec.format = this->spec.format & (~SDL_AUDIO_MASK_ENDIAN); } } else { if (snd_format & SND_FORMATLITTLEENDIAN) { /* Ok */ } else if (snd_format & SND_FORMATBIGENDIAN) { /* Give big endian format */ - spec->format |= SDL_AUDIO_MASK_ENDIAN; + this->spec.format |= SDL_AUDIO_MASK_ENDIAN; } } @@ -324,22 +231,22 @@ Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) } #endif - MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, spec->freq); - spec->freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; + MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq); + this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ", - SDL_AUDIO_BITSIZE(spec->format))); - DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); - DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); - DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); - DEBUG_PRINT(("channels=%d, ", spec->channels)); - DEBUG_PRINT(("freq=%d\n", spec->freq)); + SDL_AUDIO_BITSIZE(this->spec.format))); + DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format))); + DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format))); + DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format))); + DEBUG_PRINT(("channels=%d, ", this->spec.channels)); + DEBUG_PRINT(("freq=%d\n", this->spec.freq)); return 0; } static void -Mint_InitAudio(_THIS, SDL_AudioSpec * spec) +MINTGSXB_InitAudio(_THIS) { int channels_mode, prediv; void *buffer; @@ -352,23 +259,23 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) Setmontracks(0); /* Select replay format */ - switch (SDL_AUDIO_BITSIZE(spec->format)) { + switch (SDL_AUDIO_BITSIZE(this->spec.format)) { case 8: - if (spec->channels == 2) { + if (this->spec.channels == 2) { channels_mode = STEREO8; } else { channels_mode = MONO8; } break; case 16: - if (spec->channels == 2) { + if (this->spec.channels == 2) { channels_mode = STEREO16; } else { channels_mode = MONO16; } break; case 32: - if (spec->channels == 2) { + if (this->spec.channels == 2) { channels_mode = STEREO32; } else { channels_mode = MONO32; @@ -387,12 +294,12 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) /* Set buffer */ buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; - if (Setbuffer(0, buffer, buffer + spec->size) < 0) { + if (Setbuffer(0, buffer, buffer + this->spec.size) < 0) { DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n")); } /* Install interrupt */ - if (NSetinterrupt(2, SI_PLAY, Mint_GsxbInterrupt) < 0) { + if (NSetinterrupt(2, SI_PLAY, MINTGSXB_GsxbInterrupt) < 0) { DEBUG_PRINT((DEBUG_NAME "NSetinterrupt() failed\n")); } @@ -402,35 +309,46 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) } static int -Mint_OpenAudio(_THIS, SDL_AudioSpec * spec) +MINTGSXB_OpenDevice(_THIS, const char *devname, int iscapture) { /* Lock sound system */ if (Locksnd() != 1) { - SDL_SetError("Mint_OpenAudio: Audio system already in use"); - return (-1); + SDL_SetError("MINTGSXB_OpenDevice: Audio system already in use"); + return 0; } SDL_MintAudio_device = this; /* Check audio capabilities */ - if (Mint_CheckAudio(this, spec) == -1) { - return -1; + if (MINTGSXB_CheckAudio(this) == -1) { + return 0; + } + + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Allocate memory for audio buffers in DMA-able RAM */ - DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size)); + DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size)); - SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size * 2, MX_STRAM); + SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(this->spec.size * 2, MX_STRAM); if (SDL_MintAudio_audiobuf[0] == NULL) { - SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); - return (-1); + SDL_free(this->hidden); + this->hidden = NULL; + SDL_OutOfMemory(); + return 0; } - SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size; + SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size; SDL_MintAudio_numbuf = 0; - SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size * 2); - SDL_MintAudio_audiosize = spec->size; + SDL_memset(SDL_MintAudio_audiobuf[0],this->spec.silence,this->spec.size*2); + SDL_MintAudio_audiosize = this->spec.size; SDL_MintAudio_mutex = 0; DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", @@ -441,13 +359,13 @@ Mint_OpenAudio(_THIS, SDL_AudioSpec * spec) SDL_MintAudio_CheckFpu(); /* Setup audio hardware */ - Mint_InitAudio(this, spec); + MINTGSXB_InitAudio(this); - return (1); /* We don't use threaded audio */ + return 1; /* good to go. */ } static void -Mint_GsxbInterrupt(void) +MINTGSXB_GsxbInterrupt(void) { Uint8 *newbuf; @@ -465,8 +383,57 @@ Mint_GsxbInterrupt(void) } static void -Mint_GsxbNullInterrupt(void) +MINTGSXB_GsxbNullInterrupt(void) { } +static int +MINTGSXB_Init(SDL_AudioDriverImpl *impl) +{ + /* Cookie _SND present ? if not, assume ST machine */ + if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { + cookie_snd = SND_PSG; + } + + /* Check if we have 16 bits audio */ + if ((cookie_snd & SND_16BIT) == 0) { + SDL_SetError(DEBUG_NAME "no 16-bit sound"); + return 0; + } + + /* Cookie GSXB present ? */ + cookie_gsxb = (Getcookie(C_GSXB, &cookie_gsxb) == C_FOUND); + + /* Is it GSXB ? */ + if (((cookie_snd & SND_GSXB) == 0) || (cookie_gsxb == 0)) { + SDL_SetError(DEBUG_NAME "no GSXB audio"); + return 0; + } + + /* Check if audio is lockable */ + if (Locksnd() != 1) { + SDL_SetError(DEBUG_NAME "audio locked by other application"); + return 0; + } + + Unlocksnd(); + + DEBUG_PRINT((DEBUG_NAME "GSXB audio available!\n")); + + /* Set the function pointers */ + impl->OpenDevice = MINTGSXB_OpenDevice; + impl->CloseDevice = MINTGSXB_CloseDevice; + impl->LockAudio = MINTGSXB_LockAudio; + impl->UnlockAudio = MINTGSXB_UnlockAudio; + impl->OnlyHasDefaultOutputDevice = 1; + impl->ProvidesOwnCallbackThread = 1; + impl->SkipMixerLock = 1; + + return 1; +} + +AudioBootStrap MINTAUDIO_GSXB_bootstrap = { + MINT_AUDIO_DRIVER_NAME, "MiNT GSXB audio driver", MINTGSXB_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/mint/SDL_mintaudio_mcsn.c b/src/audio/mint/SDL_mintaudio_mcsn.c index d548f37ea..6dd35f438 100644 --- a/src/audio/mint/SDL_mintaudio_mcsn.c +++ b/src/audio/mint/SDL_mintaudio_mcsn.c @@ -61,192 +61,82 @@ /*--- Static variables ---*/ -static unsigned long cookie_snd, cookie_mch; -static cookie_mcsn_t *cookie_mcsn; - -/*--- Audio driver functions ---*/ - -static void Mint_CloseAudio(_THIS); -static int Mint_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void Mint_LockAudio(_THIS); -static void Mint_UnlockAudio(_THIS); - -/* To check/init hardware audio */ -static int Mint_CheckAudio(_THIS, SDL_AudioSpec * spec); -static void Mint_InitAudio(_THIS, SDL_AudioSpec * spec); - -/*--- Audio driver bootstrap functions ---*/ - -static int -Audio_Available(void) -{ - unsigned long dummy; - const char *envr = SDL_getenv("SDL_AUDIODRIVER"); - - SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND); - - /* We can't use XBIOS in interrupt with Magic, don't know about thread */ - if (Getcookie(C_MagX, &dummy) == C_FOUND) { - return (0); - } - - /* Check if user asked a different audio driver */ - if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME) != 0)) { - DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n")); - return (0); - } - - /* Cookie _MCH present ? if not, assume ST machine */ - if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) { - cookie_mch = MCH_ST; - } - - /* Cookie _SND present ? if not, assume ST machine */ - if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { - cookie_snd = SND_PSG; - } - - /* Check if we have 16 bits audio */ - if ((cookie_snd & SND_16BIT) == 0) { - DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n")); - return (0); - } - - /* Cookie MCSN present ? */ - if (Getcookie(C_McSn, (long *) &cookie_mcsn) != C_FOUND) { - DEBUG_PRINT((DEBUG_NAME "no MCSN audio\n")); - return (0); - } - - /* Check if interrupt at end of replay */ - if (cookie_mcsn->pint == 0) { - DEBUG_PRINT((DEBUG_NAME "no interrupt at end of replay\n")); - return (0); - } - - /* Check if audio is lockable */ - if (Locksnd() != 1) { - DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n")); - return (0); - } - - Unlocksnd(); - - DEBUG_PRINT((DEBUG_NAME "MCSN audio available!\n")); - return (1); -} - -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - /* Set the function pointers */ - this->OpenAudio = Mint_OpenAudio; - this->CloseAudio = Mint_CloseAudio; - this->LockAudio = Mint_LockAudio; - this->UnlockAudio = Mint_UnlockAudio; - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap MINTAUDIO_MCSN_bootstrap = { - MINT_AUDIO_DRIVER_NAME, "MiNT MCSN audio driver", - Audio_Available, Audio_CreateDevice -}; +static unsigned long cookie_snd = 0; +static unsigned long cookie_mch = 0; +static cookie_mcsn_t *cookie_mcsn = NULL; static void -Mint_LockAudio(_THIS) +MINTMCSN_LockDevice(_THIS) { /* Stop replay */ Buffoper(0); } static void -Mint_UnlockAudio(_THIS) +MINTMCSN_UnlockDevice(_THIS) { /* Restart replay */ Buffoper(SB_PLA_ENA | SB_PLA_RPT); } static void -Mint_CloseAudio(_THIS) +MINTMCSN_CloseDevice(_THIS) { - /* Stop replay */ - SDL_MintAudio_WaitThread(); - Buffoper(0); + if (this->hidden != NULL) { + /* Stop replay */ + SDL_MintAudio_WaitThread(); + Buffoper(0); + + if (!SDL_MintAudio_mint_present) { + /* Uninstall interrupt */ + Jdisint(MFP_DMASOUND); + } - if (!SDL_MintAudio_mint_present) { - /* Uninstall interrupt */ - Jdisint(MFP_DMASOUND); - } + /* Wait if currently playing sound */ + while (SDL_MintAudio_mutex != 0) {} - /* Wait if currently playing sound */ - while (SDL_MintAudio_mutex != 0) { - } + /* Clear buffers */ + if (SDL_MintAudio_audiobuf[0]) { + Mfree(SDL_MintAudio_audiobuf[0]); + SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; + } - /* Clear buffers */ - if (SDL_MintAudio_audiobuf[0]) { - Mfree(SDL_MintAudio_audiobuf[0]); - SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; - } + /* Unlock sound system */ + Unlocksnd(); - /* Unlock sound system */ - Unlocksnd(); + SDL_free(this->hidden); + this->hidden = NULL; + } } static int -Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) +MINTMCSN_CheckAudio(_THIS) { int i; unsigned long masterclock, masterprediv; DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ", - SDL_AUDIO_BITSIZE(spec->format))); - DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); - DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); - DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); - DEBUG_PRINT(("channels=%d, ", spec->channels)); - DEBUG_PRINT(("freq=%d\n", spec->freq)); - - if (spec->channels > 2) { - spec->channels = 2; /* no more than stereo! */ + SDL_AUDIO_BITSIZE(this->spec.format))); + DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format))); + DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format))); + DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format))); + DEBUG_PRINT(("channels=%d, ", this->spec.channels)); + DEBUG_PRINT(("freq=%d\n", this->spec.freq)); + + if (this->spec.channels > 2) { + this->spec.channels = 2; /* no more than stereo! */ } /* Check formats available */ MINTAUDIO_freqcount = 0; switch (cookie_mcsn->play) { case MCSN_ST: - spec->channels = 1; - spec->format = AUDIO_S8; /* FIXME: is it signed or unsigned ? */ + this->spec.channels = 1; + this->spec.format = AUDIO_S8; /* FIXME: is it signed or unsigned ? */ SDL_MintAudio_AddFrequency(this, 12500, 0, 0, -1); break; case MCSN_TT: /* Also STE, Mega STE */ - spec->format = AUDIO_S8; + this->spec.format = AUDIO_S8; masterclock = MASTERCLOCK_STE; masterprediv = MASTERPREDIV_STE; if ((cookie_mch >> 16) == MCH_TT) { @@ -280,10 +170,10 @@ Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) (1 << i) - 1, -1); } } - spec->format |= SDL_AUDIO_MASK_SIGNED; /* Audio is always signed */ - if ((SDL_AUDIO_BITSIZE(spec->format)) == 16) { - spec->format |= SDL_AUDIO_MASK_ENDIAN; /* Audio is always big endian */ - spec->channels = 2; /* 16 bits always stereo */ + this->spec.format |= SDL_AUDIO_MASK_SIGNED; /* Audio is always signed */ + if ((SDL_AUDIO_BITSIZE(this->spec.format)) == 16) { + this->spec.format |= SDL_AUDIO_MASK_ENDIAN; /* Audio is always big endian */ + this->spec.channels = 2; /* 16 bits always stereo */ } break; } @@ -297,22 +187,22 @@ Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) } #endif - MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, spec->freq); - spec->freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; + MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq); + this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ", - SDL_AUDIO_BITSIZE(spec->format))); - DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); - DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); - DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); - DEBUG_PRINT(("channels=%d, ", spec->channels)); - DEBUG_PRINT(("freq=%d\n", spec->freq)); + SDL_AUDIO_BITSIZE(this->spec.format))); + DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format))); + DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format))); + DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format))); + DEBUG_PRINT(("channels=%d, ", this->spec.channels)); + DEBUG_PRINT(("freq=%d\n", this->spec.freq)); return 0; } static void -Mint_InitAudio(_THIS, SDL_AudioSpec * spec) +MINTMCSN_InitAudio(_THIS) { int channels_mode, prediv, dmaclock; void *buffer; @@ -329,9 +219,9 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) /* Select replay format */ channels_mode = STEREO16; - switch (SDL_AUDIO_BITSIZE(spec->format)) { + switch (SDL_AUDIO_BITSIZE(this->spec.format)) { case 8: - if (spec->channels == 2) { + if (this->spec.channels == 2) { channels_mode = STEREO8; } else { channels_mode = MONO8; @@ -358,7 +248,7 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) /* Set buffer */ buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; - if (Setbuffer(0, buffer, buffer + spec->size) < 0) { + if (Setbuffer(0, buffer, buffer + this->spec.size) < 0) { DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n")); } @@ -381,35 +271,46 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) } static int -Mint_OpenAudio(_THIS, SDL_AudioSpec * spec) +MINTMCSN_OpenDevice(_THIS, const char *devname, int iscapture) { /* Lock sound system */ if (Locksnd() != 1) { - SDL_SetError("Mint_OpenAudio: Audio system already in use"); - return (-1); + SDL_SetError("MINTMCSN_OpenDevice: Audio system already in use"); + return 0; } SDL_MintAudio_device = this; /* Check audio capabilities */ - if (Mint_CheckAudio(this, spec) == -1) { - return -1; + if (MINTMCSN_CheckAudio(this) == -1) { + return 0; + } + + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Allocate memory for audio buffers in DMA-able RAM */ - DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size)); + DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size)); - SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size * 2, MX_STRAM); + SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(this->spec.size * 2, MX_STRAM); if (SDL_MintAudio_audiobuf[0] == NULL) { - SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); - return (-1); + SDL_free(this->hidden); + this->hidden = NULL; + SDL_OutOfMemory(); + return 0; } - SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size; + SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size; SDL_MintAudio_numbuf = 0; - SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size * 2); - SDL_MintAudio_audiosize = spec->size; + SDL_memset(SDL_MintAudio_audiobuf[0],this->spec.silence,this->spec.size*2); + SDL_MintAudio_audiosize = this->spec.size; SDL_MintAudio_mutex = 0; DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", @@ -420,9 +321,75 @@ Mint_OpenAudio(_THIS, SDL_AudioSpec * spec) SDL_MintAudio_CheckFpu(); /* Setup audio hardware */ - Mint_InitAudio(this, spec); + MINTMCSN_InitAudio(this); + + return 1; /* good to go. */ +} + +static int +MINTMCSN_Init(SDL_AudioDriverImpl *impl) +{ + unsigned long dummy = 0; + + SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND); + + /* We can't use XBIOS in interrupt with Magic, don't know about thread */ + if (Getcookie(C_MagX, &dummy) == C_FOUND) { + return 0; + } + + /* Cookie _MCH present ? if not, assume ST machine */ + if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) { + cookie_mch = MCH_ST; + } + + /* Cookie _SND present ? if not, assume ST machine */ + if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { + cookie_snd = SND_PSG; + } + + /* Check if we have 16 bits audio */ + if ((cookie_snd & SND_16BIT) == 0) { + SDL_SetError(DEBUG_NAME "no 16-bit sound"); + return 0; + } + + /* Cookie MCSN present ? */ + if (Getcookie(C_McSn, (long *) &cookie_mcsn) != C_FOUND) { + SDL_SetError(DEBUG_NAME "no MCSN audio"); + return 0; + } - return (1); /* We don't use SDL threaded audio */ + /* Check if interrupt at end of replay */ + if (cookie_mcsn->pint == 0) { + SDL_SetError(DEBUG_NAME "no interrupt at end of replay"); + return 0; + } + + /* Check if audio is lockable */ + if (Locksnd() != 1) { + SDL_SetError(DEBUG_NAME "audio locked by other application"); + return 0; + } + + Unlocksnd(); + + DEBUG_PRINT((DEBUG_NAME "MCSN audio available!\n")); + + /* Set the function pointers */ + impl->OpenDevice = MINTMCSN_OpenDevice; + impl->CloseDevice = MINTMCSN_CloseDevice; + impl->LockAudio = MINTMCSN_LockAudio; + impl->UnlockAudio = MINTMCSN_UnlockAudio; + impl->OnlyHasDefaultOutputDevice = 1; + impl->ProvidesOwnCallbackThread = 1; + impl->SkipMixerLock = 1; + + return 1; } +AudioBootStrap MINTAUDIO_MCSN_bootstrap = { + MINT_AUDIO_DRIVER_NAME, "MiNT MCSN audio driver", MINTMCSN_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/mint/SDL_mintaudio_stfa.c b/src/audio/mint/SDL_mintaudio_stfa.c index 664165014..27ec1f279 100644 --- a/src/audio/mint/SDL_mintaudio_stfa.c +++ b/src/audio/mint/SDL_mintaudio_stfa.c @@ -59,8 +59,9 @@ /*--- Static variables ---*/ -static unsigned long cookie_snd, cookie_mch; -static cookie_stfa_t *cookie_stfa; +static unsigned long cookie_snd = 0; +static unsigned long cookie_mch = 0; +static cookie_stfa_t *cookie_stfa = NULL; static const int freqs[16] = { 4995, 6269, 7493, 8192, @@ -69,157 +70,66 @@ static const int freqs[16] = { 30720, 32336, 43885, 49152 }; -/*--- Audio driver functions ---*/ - -static void Mint_CloseAudio(_THIS); -static int Mint_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void Mint_LockAudio(_THIS); -static void Mint_UnlockAudio(_THIS); - -/* To check/init hardware audio */ -static int Mint_CheckAudio(_THIS, SDL_AudioSpec * spec); -static void Mint_InitAudio(_THIS, SDL_AudioSpec * spec); - -/*--- Audio driver bootstrap functions ---*/ - -static int -Audio_Available(void) -{ - const char *envr = SDL_getenv("SDL_AUDIODRIVER"); - - /* Check if user asked a different audio driver */ - if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME) != 0)) { - DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n")); - return (0); - } - - /* Cookie _MCH present ? if not, assume ST machine */ - if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) { - cookie_mch = MCH_ST; - } - - /* Cookie _SND present ? if not, assume ST machine */ - if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { - cookie_snd = SND_PSG; - } - - /* Cookie STFA present ? */ - if (Getcookie(C_STFA, (long *) &cookie_stfa) != C_FOUND) { - DEBUG_PRINT((DEBUG_NAME "no STFA audio\n")); - return (0); - } - - SDL_MintAudio_stfa = cookie_stfa; - - DEBUG_PRINT((DEBUG_NAME "STFA audio available!\n")); - return (1); -} - static void -Audio_DeleteDevice(SDL_AudioDevice * device) +MINTSTFA_LockDevice(_THIS) { - SDL_free(device->hidden); - SDL_free(device); -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - /* Set the function pointers */ - this->OpenAudio = Mint_OpenAudio; - this->CloseAudio = Mint_CloseAudio; - this->LockAudio = Mint_LockAudio; - this->UnlockAudio = Mint_UnlockAudio; - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap MINTAUDIO_STFA_bootstrap = { - MINT_AUDIO_DRIVER_NAME, "MiNT STFA audio driver", - Audio_Available, Audio_CreateDevice -}; - -static void -Mint_LockAudio(_THIS) -{ - void *oldpile; - /* Stop replay */ - oldpile = (void *) Super(0); + void *oldpile = (void *) Super(0); cookie_stfa->sound_enable = STFA_PLAY_DISABLE; Super(oldpile); } static void -Mint_UnlockAudio(_THIS) +MINTSTFA_UnlockDevice(_THIS) { - void *oldpile; - /* Restart replay */ - oldpile = (void *) Super(0); + void *oldpile = (void *) Super(0); cookie_stfa->sound_enable = STFA_PLAY_ENABLE | STFA_PLAY_REPEAT; Super(oldpile); } static void -Mint_CloseAudio(_THIS) +MINTSTFA_CloseDevice(_THIS) { - void *oldpile; - - /* Stop replay */ - oldpile = (void *) Super(0); - cookie_stfa->sound_enable = STFA_PLAY_DISABLE; - Super(oldpile); - - /* Wait if currently playing sound */ - while (SDL_MintAudio_mutex != 0) { - } + if (this->hidden != NULL) { + /* Stop replay */ + void *oldpile = (void *) Super(0); + cookie_stfa->sound_enable = STFA_PLAY_DISABLE; + Super(oldpile); + + /* Wait if currently playing sound */ + while (SDL_MintAudio_mutex != 0) {} + + /* Clear buffers */ + if (SDL_MintAudio_audiobuf[0]) { + Mfree(SDL_MintAudio_audiobuf[0]); + SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; + } - /* Clear buffers */ - if (SDL_MintAudio_audiobuf[0]) { - Mfree(SDL_MintAudio_audiobuf[0]); - SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; + SDL_free(this->hidden); + this->hidden = NULL; } } static int -Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) +MINTSTFA_CheckAudio(_THIS) { int i; DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ", - SDL_AUDIO_BITSIZE(spec->format))); - DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); - DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); - DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); - DEBUG_PRINT(("channels=%d, ", spec->channels)); - DEBUG_PRINT(("freq=%d\n", spec->freq)); - - if (SDL_AUDIO_BITSIZE(spec->format) > 16) { - spec->format = AUDIO_S16SYS; /* clamp out int32/float32 ... */ + SDL_AUDIO_BITSIZE(this->spec.format))); + DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format))); + DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format))); + DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format))); + DEBUG_PRINT(("channels=%d, ", this->spec.channels)); + DEBUG_PRINT(("freq=%d\n", this->spec.freq)); + + if (SDL_AUDIO_BITSIZE(this->spec.format) > 16) { + this->spec.format = AUDIO_S16SYS; /* clamp out int32/float32 ... */ } - if (spec->channels > 2) { - spec->channels = 2; /* no more than stereo! */ + if (this->spec.channels > 2) { + this->spec.channels = 2; /* no more than stereo! */ } /* Check formats available */ @@ -237,29 +147,25 @@ Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) } #endif - MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, spec->freq); - spec->freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; + MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq); + this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ", - SDL_AUDIO_BITSIZE(spec->format))); - DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); - DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); - DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); - DEBUG_PRINT(("channels=%d, ", spec->channels)); - DEBUG_PRINT(("freq=%d\n", spec->freq)); + SDL_AUDIO_BITSIZE(this->spec.format))); + DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format))); + DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format))); + DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format))); + DEBUG_PRINT(("channels=%d, ", this->spec.channels)); + DEBUG_PRINT(("freq=%d\n", this->spec.freq)); return 0; } static void -Mint_InitAudio(_THIS, SDL_AudioSpec * spec) +MINTSTFA_InitAudio(_THIS) { - void *buffer; - void *oldpile; - - buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; - - oldpile = (void *) Super(0); + void *buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; + void *oldpile = (void *) Super(0); /* Stop replay */ cookie_stfa->sound_enable = STFA_PLAY_DISABLE; @@ -267,22 +173,22 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) /* Select replay format */ cookie_stfa->sound_control = MINTAUDIO_frequencies[MINTAUDIO_numfreq].predivisor; - if (SDL_AUDIO_BITSIZE(spec->format) == 8) { + if (SDL_AUDIO_BITSIZE(this->spec.format) == 8) { cookie_stfa->sound_control |= STFA_FORMAT_8BIT; } else { cookie_stfa->sound_control |= STFA_FORMAT_16BIT; } - if (spec->channels == 2) { + if (this->spec.channels == 2) { cookie_stfa->sound_control |= STFA_FORMAT_STEREO; } else { cookie_stfa->sound_control |= STFA_FORMAT_MONO; } - if (SDL_AUDIO_ISSIGNED(spec->format) != 0) { + if (SDL_AUDIO_ISSIGNED(this->spec.format) != 0) { cookie_stfa->sound_control |= STFA_FORMAT_SIGNED; } else { cookie_stfa->sound_control |= STFA_FORMAT_UNSIGNED; } - if (SDL_AUDIO_ISBIGENDIAN(spec->format) != 0) { + if (SDL_AUDIO_ISBIGENDIAN(this->spec.format) != 0) { cookie_stfa->sound_control |= STFA_FORMAT_BIGENDIAN; } else { cookie_stfa->sound_control |= STFA_FORMAT_LITENDIAN; @@ -290,7 +196,7 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) /* Set buffer */ cookie_stfa->sound_start = (unsigned long) buffer; - cookie_stfa->sound_end = (unsigned long) (buffer + spec->size); + cookie_stfa->sound_end = (unsigned long) (buffer + this->spec.size); /* Set interrupt */ cookie_stfa->stfa_it = SDL_MintAudio_StfaInterrupt; @@ -304,29 +210,40 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) } static int -Mint_OpenAudio(_THIS, SDL_AudioSpec * spec) +MINTSTFA_OpenDevice(_THIS, const char *devname, int iscapture) { SDL_MintAudio_device = this; /* Check audio capabilities */ - if (Mint_CheckAudio(this, spec) == -1) { - return -1; + if (MINTSTFA_CheckAudio(this) == -1) { + return 0; + } + + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Allocate memory for audio buffers in DMA-able RAM */ - DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size)); + DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size)); - SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size * 2, MX_STRAM); + SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(this->spec.size * 2, MX_STRAM); if (SDL_MintAudio_audiobuf[0] == NULL) { - SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); - return (-1); + SDL_OutOfMemory() + SDL_free(this->hidden); + this->hidden = NULL; + return 0; } - SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size; + SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size; SDL_MintAudio_numbuf = 0; - SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size * 2); - SDL_MintAudio_audiosize = spec->size; + SDL_memset(SDL_MintAudio_audiobuf[0],this->spec.silence,this->spec.size*2); + SDL_MintAudio_audiosize = this->spec.size; SDL_MintAudio_mutex = 0; DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", @@ -337,9 +254,49 @@ Mint_OpenAudio(_THIS, SDL_AudioSpec * spec) SDL_MintAudio_CheckFpu(); /* Setup audio hardware */ - Mint_InitAudio(this, spec); + MINTSTFA_InitAudio(this); - return (1); /* We don't use threaded audio */ + return 1; /* good to go. */ } + +static int +MINTSTFA_Init(SDL_AudioDriverImpl *impl) +{ + /* Cookie _MCH present ? if not, assume ST machine */ + if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) { + cookie_mch = MCH_ST; + } + + /* Cookie _SND present ? if not, assume ST machine */ + if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { + cookie_snd = SND_PSG; + } + + /* Cookie STFA present ? */ + if (Getcookie(C_STFA, (long *) &cookie_stfa) != C_FOUND) { + SDL_SetError(DEBUG_NAME "no STFA audio"); + return (0); + } + + SDL_MintAudio_stfa = cookie_stfa; + + DEBUG_PRINT((DEBUG_NAME "STFA audio available!\n")); + + /* Set the function pointers */ + impl->OpenDevice = MINTSTFA_OpenDevice; + impl->CloseDevice = MINTSTFA_CloseDevice; + impl->LockAudio = MINTSTFA_LockAudio; + impl->UnlockAudio = MINTSTFA_UnlockAudio; + impl->OnlyHasDefaultOutputDevice = 1; + impl->ProvidesOwnCallbackThread = 1; + impl->SkipMixerLock = 1; + + return 1; +} + +AudioBootStrap MINTAUDIO_STFA_bootstrap = { + MINT_AUDIO_DRIVER_NAME, "MiNT STFA audio driver", MINTSTFA_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/mint/SDL_mintaudio_xbios.c b/src/audio/mint/SDL_mintaudio_xbios.c index 8696fc1b9..1edb76c01 100644 --- a/src/audio/mint/SDL_mintaudio_xbios.c +++ b/src/audio/mint/SDL_mintaudio_xbios.c @@ -60,147 +60,50 @@ #define DEBUG_PRINT(what) #endif -/*--- Static variables ---*/ - -static unsigned long cookie_snd; - -/*--- Audio driver functions ---*/ - -static void Mint_CloseAudio(_THIS); -static int Mint_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void Mint_LockAudio(_THIS); -static void Mint_UnlockAudio(_THIS); - -/* To check/init hardware audio */ -static int Mint_CheckAudio(_THIS, SDL_AudioSpec * spec); -static void Mint_InitAudio(_THIS, SDL_AudioSpec * spec); - -/*--- Audio driver bootstrap functions ---*/ - -static int -Audio_Available(void) -{ - unsigned long dummy; - const char *envr = SDL_getenv("SDL_AUDIODRIVER"); - - /*SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND); */ - SDL_MintAudio_mint_present = SDL_FALSE; - - /* We can't use XBIOS in interrupt with Magic, don't know about thread */ - if (Getcookie(C_MagX, &dummy) == C_FOUND) { - return (0); - } - - /* Check if user asked a different audio driver */ - if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME) != 0)) { - DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n")); - return (0); - } - - /* Cookie _SND present ? if not, assume ST machine */ - if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { - cookie_snd = SND_PSG; - } - - /* Check if we have 16 bits audio */ - if ((cookie_snd & SND_16BIT) == 0) { - DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n")); - return (0); - } - - /* Check if audio is lockable */ - if (Locksnd() != 1) { - DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n")); - return (0); - } - - Unlocksnd(); - - DEBUG_PRINT((DEBUG_NAME "XBIOS audio available!\n")); - return (1); -} - -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - /* Set the function pointers */ - this->OpenAudio = Mint_OpenAudio; - this->CloseAudio = Mint_CloseAudio; - this->LockAudio = Mint_LockAudio; - this->UnlockAudio = Mint_UnlockAudio; - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap MINTAUDIO_XBIOS_bootstrap = { - MINT_AUDIO_DRIVER_NAME, "MiNT XBIOS audio driver", - Audio_Available, Audio_CreateDevice -}; +static unsigned long cookie_snd = 0; static void -Mint_LockAudio(_THIS) +MINTXBIOS_LockDevice(_THIS) { /* Stop replay */ Buffoper(0); } static void -Mint_UnlockAudio(_THIS) +MINTXBIOS_UnlockDevice(_THIS) { /* Restart replay */ Buffoper(SB_PLA_ENA | SB_PLA_RPT); } static void -Mint_CloseAudio(_THIS) +MINTXBIOS_CloseDevice(_THIS) { - /* Stop replay */ - SDL_MintAudio_WaitThread(); - Buffoper(0); + if (this->hidden != NULL) { + /* Stop replay */ + SDL_MintAudio_WaitThread(); + Buffoper(0); + + if (!SDL_MintAudio_mint_present) { + /* Uninstall interrupt */ + Jdisint(MFP_DMASOUND); + } - if (!SDL_MintAudio_mint_present) { - /* Uninstall interrupt */ - Jdisint(MFP_DMASOUND); - } + /* Wait if currently playing sound */ + while (SDL_MintAudio_mutex != 0) {} - /* Wait if currently playing sound */ - while (SDL_MintAudio_mutex != 0) { - } + /* Clear buffers */ + if (SDL_MintAudio_audiobuf[0]) { + Mfree(SDL_MintAudio_audiobuf[0]); + SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; + } - /* Clear buffers */ - if (SDL_MintAudio_audiobuf[0]) { - Mfree(SDL_MintAudio_audiobuf[0]); - SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; - } + /* Unlock sound system */ + Unlocksnd(); - /* Unlock sound system */ - Unlocksnd(); + SDL_free(this->hidden); + this->hidden = NULL; + } } /* Falcon XBIOS implementation of Devconnect() is buggy with external clock */ @@ -269,7 +172,7 @@ Devconnect2(int src, int dst, int sclk, int pre) } static void -Mint_CheckExternalClock(_THIS) +MINTXBIOS_CheckExternalClock(_THIS) { #define SIZE_BUF_CLOCK_MEASURE (44100/10) @@ -355,33 +258,33 @@ Mint_CheckExternalClock(_THIS) } static int -Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) +MINTXBIOS_CheckAudio(_THIS) { int i; Uint32 extclock; DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ", - SDL_AUDIO_BITSIZE(spec->format))); - DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); - DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); - DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); - DEBUG_PRINT(("channels=%d, ", spec->channels)); - DEBUG_PRINT(("freq=%d\n", spec->freq)); + SDL_AUDIO_BITSIZE(this->spec.format))); + DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format))); + DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format))); + DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format))); + DEBUG_PRINT(("channels=%d, ", this->spec.channels)); + DEBUG_PRINT(("freq=%d\n", this->spec.freq)); - spec->format |= SDL_AUDIO_MASK_SIGNED; /* Audio is always signed */ + this->spec.format |= SDL_AUDIO_MASK_SIGNED; /* Audio is always signed */ /* clamp out int32/float32 */ - if (SDL_AUDIO_BITSIZE(spec->format) >= 16) { - spec->format = AUDIO_S16MSB; /* Audio is always big endian */ - spec->channels = 2; /* 16 bits always stereo */ - } else if (spec->channels > 2) { - spec->channels = 2; /* no more than stereo! */ + if (SDL_AUDIO_BITSIZE(this->spec.format) >= 16) { + this->spec.format = AUDIO_S16MSB; /* Audio is always big endian */ + this->spec.channels = 2; /* 16 bits always stereo */ + } else if (this->spec.channels > 2) { + this->spec.channels = 2; /* no more than stereo! */ } MINTAUDIO_freqcount = 0; /* Add external clocks if present */ - Mint_CheckExternalClock(this); + MINTXBIOS_CheckExternalClock(this); /* Standard clocks */ for (i = 1; i < 12; i++) { @@ -404,22 +307,22 @@ Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) } #endif - MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, spec->freq); - spec->freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; + MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq); + this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ", - SDL_AUDIO_BITSIZE(spec->format))); - DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); - DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); - DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); - DEBUG_PRINT(("channels=%d, ", spec->channels)); - DEBUG_PRINT(("freq=%d\n", spec->freq)); + SDL_AUDIO_BITSIZE(this->spec.format))); + DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format))); + DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format))); + DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format))); + DEBUG_PRINT(("channels=%d, ", this->spec.channels)); + DEBUG_PRINT(("freq=%d\n", this->spec.freq)); return 0; } static void -Mint_InitAudio(_THIS, SDL_AudioSpec * spec) +MINTXBIOS_InitAudio(_THIS) { int channels_mode, dmaclock, prediv; void *buffer; @@ -436,9 +339,9 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) /* Select replay format */ channels_mode = STEREO16; - switch (SDL_AUDIO_BITSIZE(spec->format)) { + switch (SDL_AUDIO_BITSIZE(this->spec.format)) { case 8: - if (spec->channels == 2) { + if (this->spec.channels == 2) { channels_mode = STEREO8; } else { channels_mode = MONO8; @@ -461,7 +364,7 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) /* Set buffer */ buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; - if (Setbuffer(0, buffer, buffer + spec->size) < 0) { + if (Setbuffer(0, buffer, buffer + this->spec.size) < 0) { DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n")); } @@ -485,35 +388,46 @@ Mint_InitAudio(_THIS, SDL_AudioSpec * spec) } static int -Mint_OpenAudio(_THIS, SDL_AudioSpec * spec) +MINTXBIOS_OpenDevice(_THIS, const char *devname, int iscapture) { /* Lock sound system */ if (Locksnd() != 1) { - SDL_SetError("Mint_OpenAudio: Audio system already in use"); - return (-1); + SDL_SetError("MINTXBIOS_OpenAudio: Audio system already in use"); + return 0; } SDL_MintAudio_device = this; /* Check audio capabilities */ - if (Mint_CheckAudio(this, spec) == -1) { - return -1; + if (MINTXBIOS_CheckAudio(this) == -1) { + return 0; } - SDL_CalculateAudioSpec(spec); + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + + SDL_CalculateAudioSpec(&this->spec); /* Allocate memory for audio buffers in DMA-able RAM */ - DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size)); + DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size)); - SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size * 2, MX_STRAM); + SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(this->spec.size * 2, MX_STRAM); if (SDL_MintAudio_audiobuf[0] == NULL) { - SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); - return (-1); + SDL_free(this->hidden); + this->hidden = NULL; + SDL_OutOfMemory(); + return 0; } - SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size; + SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size; SDL_MintAudio_numbuf = 0; - SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size * 2); - SDL_MintAudio_audiosize = spec->size; + SDL_memset(SDL_MintAudio_audiobuf[0],this->spec.silence,this->spec.size*2); + SDL_MintAudio_audiosize = this->spec.size; SDL_MintAudio_mutex = 0; DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", @@ -524,9 +438,58 @@ Mint_OpenAudio(_THIS, SDL_AudioSpec * spec) SDL_MintAudio_CheckFpu(); /* Setup audio hardware */ - Mint_InitAudio(this, spec); + MINTXBIOS_InitAudio(this); + + return 1; /* good to go. */ +} + +static int +MINTXBIOS_Init(SDL_AudioDriverImpl *impl) +{ + unsigned long dummy = 0; + /*SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND); */ + SDL_MintAudio_mint_present = SDL_FALSE; - return (1); /* We don't use SDL threaded audio */ + /* We can't use XBIOS in interrupt with Magic, don't know about thread */ + if (Getcookie(C_MagX, &dummy) == C_FOUND) { + return (0); + } + + /* Cookie _SND present ? if not, assume ST machine */ + if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) { + cookie_snd = SND_PSG; + } + + /* Check if we have 16 bits audio */ + if ((cookie_snd & SND_16BIT) == 0) { + SDL_SetError(DEBUG_NAME "no 16-bit sound"); + return (0); + } + + /* Check if audio is lockable */ + if (Locksnd() != 1) { + SDL_SetError(DEBUG_NAME "audio locked by other application"); + return (0); + } + + Unlocksnd(); + + DEBUG_PRINT((DEBUG_NAME "XBIOS audio available!\n")); + + /* Set the function pointers */ + impl->OpenDevice = MINTXBIOS_OpenDevice; + impl->CloseDevice = MINTXBIOS_CloseDevice; + impl->LockAudio = MINTXBIOS_LockAudio; + impl->UnlockAudio = MINTXBIOS_UnlockAudio; + impl->OnlyHasDefaultOutputDevice = 1; + impl->ProvidesOwnCallbackThread = 1; + impl->SkipMixerLock = 1; + + return 1; } +AudioBootStrap MINTAUDIO_XBIOS_bootstrap = { + MINT_AUDIO_DRIVER_NAME, "MiNT XBIOS audio driver", MINTXBIOS_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/mme/SDL_mmeaudio.c b/src/audio/mme/SDL_mmeaudio.c index 5f1d94182..f4a7d646c 100644 --- a/src/audio/mme/SDL_mmeaudio.c +++ b/src/audio/mme/SDL_mmeaudio.c @@ -31,70 +31,6 @@ static BOOL inUse[NUM_BUFFERS]; -/* Audio driver functions */ -static int MME_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void MME_WaitAudio(_THIS); -static Uint8 *MME_GetAudioBuf(_THIS); -static void MME_PlayAudio(_THIS); -static void MME_WaitDone(_THIS); -static void MME_CloseAudio(_THIS); - -/* Audio driver bootstrap functions */ -static int -Audio_Available(void) -{ - return (1); -} - -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - if (device) { - if (device->hidden) { - SDL_free(device->hidden); - device->hidden = NULL; - } - SDL_free(device); - device = NULL; - } -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - -/* Initialize all variables that we clean on shutdown */ - this = SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - /* Set the function pointers */ - this->OpenAudio = MME_OpenAudio; - this->WaitAudio = MME_WaitAudio; - this->PlayAudio = MME_PlayAudio; - this->GetAudioBuf = MME_GetAudioBuf; - this->WaitDone = MME_WaitDone; - this->CloseAudio = MME_CloseAudio; - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap MMEAUDIO_bootstrap = { - "waveout", "Tru64 MME WaveOut", - Audio_Available, Audio_CreateDevice -}; - static void SetMMerror(char *function, MMRESULT code) { @@ -108,7 +44,7 @@ SetMMerror(char *function, MMRESULT code) } static void CALLBACK -MME_CALLBACK(HWAVEOUT hwo, +MME_Callback(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, LPARAM dwParam1, LPARAM dwParam2) { WAVEHDR *wp = (WAVEHDR *) dwParam1; @@ -118,116 +54,137 @@ MME_CALLBACK(HWAVEOUT hwo, } static int -MME_OpenAudio(_THIS, SDL_AudioSpec * spec) +MME_OpenDevice(_THIS, const char *devname, int iscapture) { + int valid_format = 0; MMRESULT result; + Uint8 *mixbuf = NULL; int i; - mixbuf = NULL; + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); /* Set basic WAVE format parameters */ - shm = mmeAllocMem(sizeof(*shm)); - if (shm == NULL) { - SDL_SetError("Out of memory: shm"); - return (-1); + this->hidden->shm = mmeAllocMem(sizeof(*this->hidden->shm)); + if (this->hidden->shm == NULL) { + MME_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } - shm->sound = 0; - shm->wFmt.wf.wFormatTag = WAVE_FORMAT_PCM; + + SDL_memset(this->hidden->shm, '\0', sizeof (*this->hidden->shm)); + this->hidden->shm->sound = 0; + this->hidden->shm->wFmt.wf.wFormatTag = WAVE_FORMAT_PCM; /* Determine the audio parameters from the AudioSpec */ - switch (SDL_AUDIO_BITSIZE(spec->format)) { - case 8: - /* Unsigned 8 bit audio data */ - spec->format = AUDIO_U8; - shm->wFmt.wBitsPerSample = 8; - break; - case 16: - /* Signed 16 bit audio data */ - spec->format = AUDIO_S16; - shm->wFmt.wBitsPerSample = 16; - break; - case 32: - /* Signed 32 bit audio data */ - spec->format = AUDIO_S32; - shm->wFmt.wBitsPerSample = 32; - break; - default: + /* Try for a closest match on audio format */ + for (test_format = SDL_FirstAudioFormat(this->spec.format); + !valid_format && test_format;) { + valid_format = 1; + switch (test_format) { + case AUDIO_U8: + case AUDIO_S16: + case AUDIO_S32: + break; + default: + valid_format = 0; + test_format = SDL_NextAudioFormat(); + } + } + + if (!valid_format) { + MME_CloseDevice(this); SDL_SetError("Unsupported audio format"); - return (-1); + return 0; } + this->spec.format = test_format; + this->hidden->shm->wFmt.wBitsPerSample = SDL_AUDIO_BITSIZE(test_format); + /* !!! FIXME: Can this handle more than stereo? */ - shm->wFmt.wf.nChannels = spec->channels; - shm->wFmt.wf.nSamplesPerSec = spec->freq; - shm->wFmt.wf.nBlockAlign = - shm->wFmt.wf.nChannels * shm->wFmt.wBitsPerSample / 8; - shm->wFmt.wf.nAvgBytesPerSec = - shm->wFmt.wf.nSamplesPerSec * shm->wFmt.wf.nBlockAlign; + this->hidden->shm->wFmt.wf.nChannels = this->spec.channels; + this->hidden->shm->wFmt.wf.nSamplesPerSec = this->spec.freq; + this->hidden->shm->wFmt.wf.nBlockAlign = + this->hidden->shm->wFmt.wf.nChannels * + this->hidden->shm->wFmt.wBitsPerSample / 8; + this->hidden->shm->wFmt.wf.nAvgBytesPerSec = + this->hidden->shm->wFmt.wf.nSamplesPerSec * + this->hidden->shm->wFmt.wf.nBlockAlign; /* Check the buffer size -- minimum of 1/4 second (word aligned) */ - if (spec->samples < (spec->freq / 4)) - spec->samples = ((spec->freq / 4) + 3) & ~3; + if (this->spec.samples < (this->spec.freq / 4)) + this->spec.samples = ((this->spec.freq / 4) + 3) & ~3; /* Update the fragment size as size in bytes */ - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Open the audio device */ - result = waveOutOpen(&(shm->sound), + result = waveOutOpen(&(this->hidden->shm->sound), WAVE_MAPPER, - &(shm->wFmt.wf), - MME_CALLBACK, + &(this->hidden->shm->wFmt.wf), + MME_Callback, NULL, (CALLBACK_FUNCTION | WAVE_OPEN_SHAREABLE)); if (result != MMSYSERR_NOERROR) { + MME_CloseDevice(this); SetMMerror("waveOutOpen()", result); - return (-1); + return 0; } /* Create the sound buffers */ - mixbuf = (Uint8 *) mmeAllocBuffer(NUM_BUFFERS * (spec->size)); + mixbuf = (Uint8 *) mmeAllocBuffer(NUM_BUFFERS * (this->spec.size)); if (mixbuf == NULL) { - SDL_SetError("Out of memory: mixbuf"); - return (-1); + MME_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } + this->hidden->mixbuf = mixbuf; for (i = 0; i < NUM_BUFFERS; i++) { - shm->wHdr[i].lpData = &mixbuf[i * (spec->size)]; - shm->wHdr[i].dwBufferLength = spec->size; - shm->wHdr[i].dwFlags = 0; - shm->wHdr[i].dwUser = i; - shm->wHdr[i].dwLoops = 0; /* loop control counter */ - shm->wHdr[i].lpNext = NULL; /* reserved for driver */ - shm->wHdr[i].reserved = 0; + this->hidden->shm->wHdr[i].lpData = &mixbuf[i * (this->spec.size)]; + this->hidden->shm->wHdr[i].dwBufferLength = this->spec.size; + this->hidden->shm->wHdr[i].dwFlags = 0; + this->hidden->shm->wHdr[i].dwUser = i; + this->hidden->shm->wHdr[i].dwLoops = 0; /* loop control counter */ + this->hidden->shm->wHdr[i].lpNext = NULL; /* reserved for driver */ + this->hidden->shm->wHdr[i].reserved = 0; inUse[i] = FALSE; } - next_buffer = 0; - return 0; + this->hidden->next_buffer = 0; + + return 1; } static void -MME_WaitAudio(_THIS) +MME_WaitDevice(_THIS) { - while (inUse[next_buffer]) { + while (inUse[this->hidden->next_buffer]) { mmeWaitForCallbacks(); mmeProcessCallbacks(); } } static Uint8 * -MME_GetAudioBuf(_THIS) +MME_GetDeviceBuf(_THIS) { - Uint8 *retval; - - inUse[next_buffer] = TRUE; - retval = (Uint8 *) (shm->wHdr[next_buffer].lpData); - return retval; + void *retval = this->hidden->shm->wHdr[this->hidden->next_buffer].lpData; + inUse[this->hidden->next_buffer] = TRUE; + return (Uint8 *) retval; } static void -MME_PlayAudio(_THIS) +MME_PlayDevice(_THIS) { /* Queue it up */ - waveOutWrite(shm->sound, &(shm->wHdr[next_buffer]), sizeof(WAVEHDR)); - next_buffer = (next_buffer + 1) % NUM_BUFFERS; + waveOutWrite(this->hidden->shm->sound, + &(this->hidden->shm->wHdr[this->hidden->next_buffer]), + sizeof (WAVEHDR)); + this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS; } static void @@ -236,13 +193,13 @@ MME_WaitDone(_THIS) MMRESULT result; int i; - if (shm->sound) { + if (this->hidden->shm->sound) { for (i = 0; i < NUM_BUFFERS; i++) while (inUse[i]) { mmeWaitForCallbacks(); mmeProcessCallbacks(); } - result = waveOutReset(shm->sound); + result = waveOutReset(this->hidden->shm->sound); if (result != MMSYSERR_NOERROR) SetMMerror("waveOutReset()", result); mmeProcessCallbacks(); @@ -250,29 +207,54 @@ MME_WaitDone(_THIS) } static void -MME_CloseAudio(_THIS) +MME_CloseDevice(_THIS) { - MMRESULT result; + if (this->hidden != NULL) { + MMRESULT result; - if (mixbuf) { - result = mmeFreeBuffer(mixbuf); - if (result != MMSYSERR_NOERROR) - SetMMerror("mmeFreeBuffer", result); - mixbuf = NULL; - } + if (this->hidden->mixbuf) { + result = mmeFreeBuffer(this->hidden->mixbuf); + if (result != MMSYSERR_NOERROR) + SetMMerror("mmeFreeBuffer", result); + this->hidden->mixbuf = NULL; + } - if (shm) { - if (shm->sound) { - result = waveOutClose(shm->sound); + if (this->hidden->shm) { + if (this->hidden->shm->sound) { + result = waveOutClose(this->hidden->shm->sound); + if (result != MMSYSERR_NOERROR) + SetMMerror("waveOutClose()", result); + mmeProcessCallbacks(); + } + result = mmeFreeMem(this->hidden->shm); if (result != MMSYSERR_NOERROR) - SetMMerror("waveOutClose()", result); - mmeProcessCallbacks(); + SetMMerror("mmeFreeMem()", result); + this->hidden->shm = NULL; } - result = mmeFreeMem(shm); - if (result != MMSYSERR_NOERROR) - SetMMerror("mmeFreeMem()", result); - shm = NULL; + + SDL_free(this->hidden); + this->hidden = NULL; } } +static int +MME_Init(SDL_AudioDriverImpl *impl) +{ + /* Set the function pointers */ + impl->OpenDevice = MME_OpenDevice; + impl->WaitDevice = MME_WaitDevice; + impl->WaitDone = MME_WaitDone; + impl->PlayDevice = MME_PlayDevice; + impl->GetDeviceBuf = MME_GetDeviceBuf; + impl->CloseDevice = MME_CloseDevice; + impl->OnlyHasDefaultOutputDevice = 1; + + return 1; +} + +/* !!! FIXME: Windows "windib" driver is called waveout, too */ +AudioBootStrap MMEAUDIO_bootstrap = { + "waveout", "Tru64 MME WaveOut", MME_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/mme/SDL_mmeaudio.h b/src/audio/mme/SDL_mmeaudio.h index 3d6d86b5e..d37cb02a6 100644 --- a/src/audio/mme/SDL_mmeaudio.h +++ b/src/audio/mme/SDL_mmeaudio.h @@ -23,12 +23,12 @@ /* Allow access to a raw mixing buffer */ -#ifndef _SDL_lowaudio_h -#define _SDL_lowaudio_h +#ifndef _SDL_mmeaudio_h +#define _SDL_mmeaudio_h #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this #define NUM_BUFFERS 2 @@ -46,9 +46,6 @@ struct SDL_PrivateAudioData int next_buffer; }; -#define shm (this->hidden->shm) -#define mixbuf (this->hidden->mixbuf) -#define next_buffer (this->hidden->next_buffer) -/* Old variable names */ -#endif /* _SDL_lowaudio_h */ +#endif /* _SDL_mmeaudio_h */ + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/nas/SDL_nasaudio.c b/src/audio/nas/SDL_nasaudio.c index fca8df78a..b82fe94bf 100644 --- a/src/audio/nas/SDL_nasaudio.c +++ b/src/audio/nas/SDL_nasaudio.c @@ -32,106 +32,149 @@ #include "SDL_timer.h" #include "SDL_audio.h" +#include "SDL_loadso.h" #include "../SDL_audiomem.h" #include "../SDL_audio_c.h" -#include "../SDL_audiodev_c.h" #include "SDL_nasaudio.h" -/* The tag name used by artsc audio */ +/* The tag name used by nas audio */ #define NAS_DRIVER_NAME "nas" static struct SDL_PrivateAudioData *this2 = NULL; -/* Audio driver functions */ -static int NAS_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void NAS_WaitAudio(_THIS); -static void NAS_PlayAudio(_THIS); -static Uint8 *NAS_GetAudioBuf(_THIS); -static void NAS_CloseAudio(_THIS); -/* Audio driver bootstrap functions */ +static void (*NAS_AuCloseServer)(AuServer *); +static void (*NAS_AuNextEvent)(AuServer *, AuBool, AuEvent *); +static AuBool (*NAS_AuDispatchEvent)(AuServer *, AuEvent *); +static AuFlowID (*NAS_AuCreateFlow)(AuServer *, AuStatus *); +static void (*NAS_AuStartFlow)(AuServer *, AuFlowID, AuStatus *); +static void (*NAS_AuSetElements) + (AuServer *, AuFlowID, AuBool, int, AuElement *, AuStatus *); +static void (*NAS_AuWriteElement) + (AuServer *, AuFlowID, int, AuUint32, AuPointer, AuBool, AuStatus *); +static AuServer *(*NAS_AuOpenServer) + (_AuConst char *, int, _AuConst char *, int, _AuConst char *, char **); +static AuEventHandlerRec *(*NAS_AuRegisterEventHandler) + (AuServer *, AuMask, int, AuID, AuEventHandlerCallback, AuPointer); + + +#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC + +static const char *nas_library = SDL_AUDIO_DRIVER_NAS_DYNAMIC; +static void *nas_handle = NULL; static int -Audio_Available(void) +load_nas_sym(const char *fn, void **addr) { - AuServer *aud = AuOpenServer("", 0, NULL, 0, NULL, NULL); - if (!aud) + *addr = SDL_LoadFunction(nas_handle, fn); + if (*addr == NULL) { return 0; - - AuCloseServer(aud); + } return 1; } -static void -Audio_DeleteDevice(SDL_AudioDevice * device) +/* cast funcs to char* first, to please GCC's strict aliasing rules. */ +#define SDL_NAS_SYM(x) \ + if (!load_nas_sym(#x, (void **) (char *) &NAS_##x)) return -1 +#else +#define SDL_NAS_SYM(x) NAS_##x = x +#endif + +static int load_nas_syms(void) { - SDL_free(device->hidden); - SDL_free(device); + SDL_NAS_SYM(AuCloseServer); + SDL_NAS_SYM(AuNextEvent); + SDL_NAS_SYM(AuDispatchEvent); + SDL_NAS_SYM(AuCreateFlow); + SDL_NAS_SYM(AuStartFlow); + SDL_NAS_SYM(AuSetElements); + SDL_NAS_SYM(AuWriteElement); + SDL_NAS_SYM(AuOpenServer); + SDL_NAS_SYM(AuRegisterEventHandler); + return 0; } +#undef SDL_NAS_SYM -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; +#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); +static void +UnloadNASLibrary(void) +{ + if (nas_handle != NULL) { + SDL_UnloadObject(nas_handle); + nas_handle = NULL; } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); +} + +static int +LoadNASLibrary(void) +{ + int retval = 0; + if (nas_handle == NULL) { + nas_handle = SDL_LoadObject(nas_library); + if (nas_handle == NULL) { + /* Copy error string so we can use it in a new SDL_SetError(). */ + char *origerr = SDL_GetError(); + size_t len = SDL_strlen(origerr) + 1; + char *err = (char *) alloca(len); + SDL_strlcpy(err, origerr, len); + retval = -1; + SDL_SetError("NAS: SDL_LoadObject('%s') failed: %s\n", + nas_library, err); + } else { + retval = load_nas_syms(); + if (retval < 0) { + UnloadNASLibrary(); + } } - return (0); } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); + return retval; +} - /* Set the function pointers */ - this->OpenAudio = NAS_OpenAudio; - this->WaitAudio = NAS_WaitAudio; - this->PlayAudio = NAS_PlayAudio; - this->GetAudioBuf = NAS_GetAudioBuf; - this->CloseAudio = NAS_CloseAudio; +#else - this->free = Audio_DeleteDevice; +static void +UnloadNASLibrary(void) +{ +} - return this; +static int +LoadNASLibrary(void) +{ + load_nas_syms(); + return 0; } -AudioBootStrap NAS_bootstrap = { - NAS_DRIVER_NAME, "Network Audio System", - Audio_Available, Audio_CreateDevice -}; +#endif /* SDL_AUDIO_DRIVER_NAS_DYNAMIC */ /* This function waits until it is possible to write a full sound buffer */ static void -NAS_WaitAudio(_THIS) +NAS_WaitDevice(_THIS) { while (this->hidden->buf_free < this->hidden->mixlen) { AuEvent ev; - AuNextEvent(this->hidden->aud, AuTrue, &ev); - AuDispatchEvent(this->hidden->aud, &ev); + NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev); + NAS_AuDispatchEvent(this->hidden->aud, &ev); } } static void -NAS_PlayAudio(_THIS) +NAS_PlayDevice(_THIS) { - while (this->hidden->mixlen > this->hidden->buf_free) { /* We think the buffer is full? Yikes! Ask the server for events, - in the hope that some of them is LowWater events telling us more - of the buffer is free now than what we think. */ + while (this->hidden->mixlen > this->hidden->buf_free) { + /* + * We think the buffer is full? Yikes! Ask the server for events, + * in the hope that some of them is LowWater events telling us more + * of the buffer is free now than what we think. + */ AuEvent ev; - AuNextEvent(this->hidden->aud, AuTrue, &ev); - AuDispatchEvent(this->hidden->aud, &ev); + NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev); + NAS_AuDispatchEvent(this->hidden->aud, &ev); } this->hidden->buf_free -= this->hidden->mixlen; /* Write the audio data */ - AuWriteElement(this->hidden->aud, this->hidden->flow, 0, + NAS_AuWriteElement(this->hidden->aud, this->hidden->flow, 0, this->hidden->mixlen, this->hidden->mixbuf, AuFalse, NULL); this->hidden->written += this->hidden->mixlen; @@ -142,21 +185,25 @@ NAS_PlayAudio(_THIS) } static Uint8 * -NAS_GetAudioBuf(_THIS) +NAS_GetDeviceBuf(_THIS) { return (this->hidden->mixbuf); } static void -NAS_CloseAudio(_THIS) +NAS_CloseDevice(_THIS) { - if (this->hidden->mixbuf != NULL) { - SDL_FreeAudioMem(this->hidden->mixbuf); - this->hidden->mixbuf = NULL; - } - if (this->hidden->aud) { - AuCloseServer(this->hidden->aud); - this->hidden->aud = 0; + if (this->hidden != NULL) { + if (this->hidden->mixbuf != NULL) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + if (this->hidden->aud) { + NAS_AuCloseServer(this->hidden->aud); + this->hidden->aud = 0; + } + SDL_free(this->hidden); + this2 = this->hidden = NULL; } } @@ -221,6 +268,7 @@ event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd) static AuDeviceID find_device(_THIS, int nch) { + /* These "Au" things are all macros, not functions... */ int i; for (i = 0; i < AuServerNumDevices(this->hidden->aud); i++) { if ((AuDeviceKind(AuServerDevice(this->hidden->aud, i)) == @@ -233,46 +281,53 @@ find_device(_THIS, int nch) } static int -NAS_OpenAudio(_THIS, SDL_AudioSpec * spec) +NAS_OpenDevice(_THIS, const char *devname, int iscapture) { AuElement elms[3]; int buffer_size; SDL_AudioFormat test_format, format; - this->hidden->mixbuf = NULL; + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); /* Try for a closest match on audio format */ format = 0; - for (test_format = SDL_FirstAudioFormat(spec->format); + for (test_format = SDL_FirstAudioFormat(this->spec.format); !format && test_format;) { format = sdlformat_to_auformat(test_format); - if (format == AuNone) { test_format = SDL_NextAudioFormat(); } } if (format == 0) { - SDL_SetError("Couldn't find any hardware audio formats"); - return (-1); + NAS_CloseDevice(this); + SDL_SetError("NAS: Couldn't find any hardware audio formats"); + return 0; } - spec->format = test_format; + this->spec.format = test_format; - this->hidden->aud = AuOpenServer("", 0, NULL, 0, NULL, NULL); + this->hidden->aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL); if (this->hidden->aud == 0) { - SDL_SetError("Couldn't open connection to NAS server"); - return (-1); + NAS_CloseDevice(this); + SDL_SetError("NAS: Couldn't open connection to NAS server"); + return 0; } - this->hidden->dev = find_device(this, spec->channels); + this->hidden->dev = find_device(this, this->spec.channels); if ((this->hidden->dev == AuNone) - || (!(this->hidden->flow = AuCreateFlow(this->hidden->aud, NULL)))) { - AuCloseServer(this->hidden->aud); - this->hidden->aud = 0; - SDL_SetError("Couldn't find a fitting playback device on NAS server"); - return (-1); + || (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, 0)))) { + NAS_CloseDevice(this); + SDL_SetError("NAS: Couldn't find a fitting device on NAS server"); + return 0; } - buffer_size = spec->freq; + buffer_size = this->spec.freq; if (buffer_size < 4096) buffer_size = 4096; @@ -280,35 +335,70 @@ NAS_OpenAudio(_THIS, SDL_AudioSpec * spec) buffer_size = 32768; /* So that the buffer won't get unmanageably big. */ /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); this2 = this->hidden; - AuMakeElementImportClient(elms, spec->freq, format, spec->channels, + AuMakeElementImportClient(elms,this->spec.freq,format,this->spec.channels, AuTrue, buffer_size, buffer_size / 4, 0, NULL); - AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, spec->freq, + AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq, AuUnlimitedSamples, 0, NULL); - AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms, - NULL); - AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0, - this->hidden->flow, event_handler, - (AuPointer) NULL); + NAS_AuSetElements(this->hidden->aud, this->hidden->flow, + AuTrue, 2, elms, NULL); + NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0, + this->hidden->flow, event_handler, + (AuPointer) NULL); - AuStartFlow(this->hidden->aud, this->hidden->flow, NULL); + NAS_AuStartFlow(this->hidden->aud, this->hidden->flow, NULL); /* Allocate mixing buffer */ - this->hidden->mixlen = spec->size; + this->hidden->mixlen = this->spec.size; this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); if (this->hidden->mixbuf == NULL) { - return (-1); + NAS_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } - SDL_memset(this->hidden->mixbuf, spec->silence, spec->size); - - /* Get the parent process id (we're the parent of the audio thread) */ - this->hidden->parent = getpid(); + SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); /* We're ready to rock and roll. :-) */ - return (0); + return 1; } +static void +NAS_Deinitialize(void) +{ + UnloadNASLibrary(); +} + +static int +NAS_Init(SDL_AudioDriverImpl *impl) +{ + if (LoadNASLibrary() < 0) { + return 0; + } else { + AuServer *aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL); + if (aud == NULL) { + SDL_SetError("NAS: AuOpenServer() failed (no audio server?)"); + return 0; + } + NAS_AuCloseServer(aud); + } + + /* Set the function pointers */ + impl->OpenDevice = NAS_OpenDevice; + impl->PlayDevice = NAS_PlayDevice; + impl->WaitDevice = NAS_WaitDevice; + impl->GetDeviceBuf = NAS_GetDeviceBuf; + impl->CloseDevice = NAS_CloseDevice; + impl->Deinitialize = NAS_Deinitialize; + impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: is this true? */ + + return 1; +} + +AudioBootStrap NAS_bootstrap = { + NAS_DRIVER_NAME, "Network Audio System", NAS_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/nas/SDL_nasaudio.h b/src/audio/nas/SDL_nasaudio.h index fc1c73d92..8e435bb71 100644 --- a/src/audio/nas/SDL_nasaudio.h +++ b/src/audio/nas/SDL_nasaudio.h @@ -37,7 +37,7 @@ #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData @@ -46,9 +46,6 @@ struct SDL_PrivateAudioData AuFlowID flow; AuDeviceID dev; - /* The parent process id, to detect when application quits */ - pid_t parent; - /* Raw mixing buffer */ Uint8 *mixbuf; int mixlen; @@ -60,4 +57,5 @@ struct SDL_PrivateAudioData int buf_free; }; #endif /* _SDL_nasaudio_h */ + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/nto/SDL_nto_audio.c b/src/audio/nto/SDL_nto_audio.c index ccdcfafff..be676c47b 100644 --- a/src/audio/nto/SDL_nto_audio.c +++ b/src/audio/nto/SDL_nto_audio.c @@ -69,13 +69,13 @@ struct BuggyCards buggycards[QSA_WA_CARDS] = { {"Vortex 8830", QSA_MMAP_WORKAROUND}, }; -/* Audio driver functions */ -static void NTO_ThreadInit(_THIS); -static int NTO_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void NTO_WaitAudio(_THIS); -static void NTO_PlayAudio(_THIS); -static Uint8 *NTO_GetAudioBuf(_THIS); -static void NTO_CloseAudio(_THIS); + +static inline void +NTO_SetError(const char *fn, int rval) +{ + SDL_SetError("NTO: %s failed: %s", fn, snd_strerror(rval)); +} + /* card names check to apply the workarounds */ static int @@ -84,7 +84,7 @@ NTO_CheckBuggyCards(_THIS, unsigned long checkfor) char scardname[33]; int it; - if (snd_card_get_name(cardno, scardname, 32) < 0) { + if (snd_card_get_name(this->hidden->cardno, scardname, 32) < 0) { return 0; } @@ -102,11 +102,10 @@ NTO_CheckBuggyCards(_THIS, unsigned long checkfor) static void NTO_ThreadInit(_THIS) { - int status; struct sched_param param; + int status = SchedGet(0, 0, ¶m); /* increasing default 10 priority to 25 to avoid jerky sound */ - status = SchedGet(0, 0, ¶m); param.sched_priority = param.sched_curpriority + 15; status = SchedSet(0, 0, SCHED_NOCHANGE, ¶m); } @@ -130,111 +129,26 @@ NTO_InitAudioParams(snd_pcm_channel_params_t * cpars) cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX; } -static int -NTO_AudioAvailable(void) -{ - /* See if we can open a nonblocking channel. - Return value '1' means we can. - Return value '0' means we cannot. */ - - int available; - int rval; - snd_pcm_t *handle; - - available = 0; - handle = NULL; - - rval = snd_pcm_open_preferred(&handle, NULL, NULL, OPEN_FLAGS); - - if (rval >= 0) { - available = 1; - - if ((rval = snd_pcm_close(handle)) < 0) { - SDL_SetError - ("NTO_AudioAvailable(): snd_pcm_close failed: %s\n", - snd_strerror(rval)); - available = 0; - } - } else { - SDL_SetError - ("NTO_AudioAvailable(): there are no available audio devices.\n"); - } - - return (available); -} - -static void -NTO_DeleteAudioDevice(SDL_AudioDevice * device) -{ - if ((device) && (device->hidden)) { - SDL_free(device->hidden); - } - if (device) { - SDL_free(device); - } -} - -static SDL_AudioDevice * -NTO_CreateAudioDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, sizeof(SDL_AudioDevice)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc(sizeof(struct SDL_PrivateAudioData)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData)); - audio_handle = NULL; - - /* Set the function pointers */ - this->ThreadInit = NTO_ThreadInit; - this->OpenAudio = NTO_OpenAudio; - this->WaitAudio = NTO_WaitAudio; - this->PlayAudio = NTO_PlayAudio; - this->GetAudioBuf = NTO_GetAudioBuf; - this->CloseAudio = NTO_CloseAudio; - - this->free = NTO_DeleteAudioDevice; - - return this; -} - -AudioBootStrap QNXNTOAUDIO_bootstrap = { - DRIVER_NAME, "QNX6 QSA-NTO Audio", - NTO_AudioAvailable, - NTO_CreateAudioDevice -}; /* This function waits until it is possible to write a full sound buffer */ static void -NTO_WaitAudio(_THIS) +NTO_WaitDevice(_THIS) { fd_set wfds; int selectret; FD_ZERO(&wfds); - FD_SET(audio_fd, &wfds); + FD_SET(this->hidden->audio_fd, &wfds); do { - selectret = select(audio_fd + 1, NULL, &wfds, NULL, NULL); + selectret = select(this->hidden->audio_fd+1, NULL, &wfds, NULL, NULL); switch (selectret) { case -1: case 0: - SDL_SetError("NTO_WaitAudio(): select() failed: %s\n", - strerror(errno)); + SDL_SetError("NTO: select() failed: %s\n", strerror(errno)); return; default: - if (FD_ISSET(audio_fd, &wfds)) { + if (FD_ISSET(this->hidden->audio_fd, &wfds)) { return; } break; @@ -244,22 +158,24 @@ NTO_WaitAudio(_THIS) } static void -NTO_PlayAudio(_THIS) +NTO_PlayDevice(_THIS) { + snd_pcm_channel_status_t cstatus; int written, rval; int towrite; void *pcmbuffer; - if (!this->enabled) { + if ((!this->enabled) || (!this->hidden)) { return; } towrite = this->spec.size; - pcmbuffer = pcm_buf; + pcmbuffer = this->hidden->pcm_buf; /* Write the audio data, checking for EAGAIN (buffer full) and underrun */ do { - written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite); + written = snd_pcm_plugin_write(this->hidden->audio_handle, + pcmbuffer, towrite); if (written != towrite) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { /* Let a little CPU time go by and try to write again */ @@ -268,33 +184,28 @@ NTO_PlayAudio(_THIS) towrite -= written; pcmbuffer += written * this->spec.channels; continue; - } else { - if ((errno == EINVAL) || (errno == EIO)) { - SDL_memset(&cstatus, 0, sizeof(cstatus)); - cstatus.channel = SND_PCM_CHANNEL_PLAYBACK; - if ((rval = - snd_pcm_plugin_status(audio_handle, &cstatus)) < 0) { - SDL_SetError - ("NTO_PlayAudio(): snd_pcm_plugin_status failed: %s\n", - snd_strerror(rval)); + } else if ((errno == EINVAL) || (errno == EIO)) { + SDL_memset(&cstatus, 0, sizeof (cstatus)); + cstatus.channel = SND_PCM_CHANNEL_PLAYBACK; + rval = snd_pcm_plugin_status(this->hidden->audio_handle, + &cstatus); + if (rval < 0) { + NTO_SetError("snd_pcm_plugin_status", rval); + return; + } + + if ( (cstatus.status == SND_PCM_STATUS_UNDERRUN) || + (cstatus.status == SND_PCM_STATUS_READY)) { + rval = snd_pcm_plugin_prepare(this->hidden->audio_handle, + SND_PCM_CHANNEL_PLAYBACK); + if (rval < 0) { + NTO_SetError("snd_pcm_plugin_prepare", rval); return; } - if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) - || (cstatus.status == SND_PCM_STATUS_READY)) { - if ((rval = - snd_pcm_plugin_prepare(audio_handle, - SND_PCM_CHANNEL_PLAYBACK)) - < 0) { - SDL_SetError - ("NTO_PlayAudio(): snd_pcm_plugin_prepare failed: %s\n", - snd_strerror(rval)); - return; - } - } - continue; - } else { - return; } + continue; + } else { + return; } } else { /* we wrote all remaining data */ @@ -308,77 +219,74 @@ NTO_PlayAudio(_THIS) if (towrite != 0) { this->enabled = 0; } - - return; } static Uint8 * -NTO_GetAudioBuf(_THIS) +NTO_GetDeviceBuf(_THIS) { - return pcm_buf; + return this->hidden->pcm_buf; } static void -NTO_CloseAudio(_THIS) +NTO_CloseDevice(_THIS) { - int rval; - - this->enabled = 0; - - if (audio_handle != NULL) { - if ((rval = - snd_pcm_plugin_flush(audio_handle, - SND_PCM_CHANNEL_PLAYBACK)) < 0) { - SDL_SetError - ("NTO_CloseAudio(): snd_pcm_plugin_flush failed: %s\n", - snd_strerror(rval)); - return; + if (this->hidden != NULL) { + if (this->hidden->audio_handle != NULL) { + snd_pcm_plugin_flush(this->hidden->audio_handle, + SND_PCM_CHANNEL_PLAYBACK); + snd_pcm_close(this->hidden->audio_handle); + this->hidden->audio_handle = NULL; } - if ((rval = snd_pcm_close(audio_handle)) < 0) { - SDL_SetError("NTO_CloseAudio(): snd_pcm_close failed: %s\n", - snd_strerror(rval)); - return; + if (this->hidden->pcm_buf != NULL) { + SDL_FreeAudioMem(this->hidden->pcm_buf); + this->hidden->pcm_buf = NULL; } - audio_handle = NULL; + SDL_free(this->hidden); + this->hidden = NULL; } } static int -NTO_OpenAudio(_THIS, SDL_AudioSpec * spec) +NTO_OpenDevice(_THIS, const char *devname, int iscapture) { - int rval; - int format; - SDL_AudioFormat test_format; - int found; - - audio_handle = NULL; - this->enabled = 0; + int rval = 0; + int format = 0; + SDL_AudioFormat test_format = 0; + int found = 0; + snd_pcm_channel_setup_t csetup; + snd_pcm_channel_params_t cparams; - if (pcm_buf != NULL) { - SDL_FreeAudioMem(pcm_buf); - pcm_buf = NULL; + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); /* initialize channel transfer parameters to default */ NTO_InitAudioParams(&cparams); /* Open the audio device */ - rval = - snd_pcm_open_preferred(&audio_handle, &cardno, &deviceno, OPEN_FLAGS); + rval = snd_pcm_open_preferred(&this->hidden->audio_handle, + &this->hidden->cardno, + &this->hidden->deviceno, OPEN_FLAGS); + if (rval < 0) { - SDL_SetError("NTO_OpenAudio(): snd_pcm_open failed: %s\n", - snd_strerror(rval)); - return (-1); + NTO_CloseDevice(this); + NTO_SetError("snd_pcm_open", rval); + return 0; } if (!NTO_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) { /* enable count status parameter */ - if ((rval = - snd_pcm_plugin_set_disable(audio_handle, - PLUGIN_DISABLE_MMAP)) < 0) { - SDL_SetError("snd_pcm_plugin_set_disable failed: %s\n", - snd_strerror(rval)); - return (-1); + rval = snd_pcm_plugin_set_disable(this->hidden->audio_handle, + PLUGIN_DISABLE_MMAP); + if (rval < 0) { + NTO_CloseDevice(this); + NTO_SetError("snd_pcm_plugin_set_disable", rval); + return 0; } } @@ -387,7 +295,7 @@ NTO_OpenAudio(_THIS, SDL_AudioSpec * spec) /* can't use format as SND_PCM_SFMT_U8 = 0 in nto */ found = 0; - for (test_format = SDL_FirstAudioFormat(spec->format); !found;) { + for (test_format = SDL_FirstAudioFormat(this->spec.format); !found;) { /* if match found set format to equivalent ALSA format */ switch (test_format) { case AUDIO_U8: @@ -441,86 +349,115 @@ NTO_OpenAudio(_THIS, SDL_AudioSpec * spec) /* assumes test_format not 0 on success */ if (test_format == 0) { - SDL_SetError - ("NTO_OpenAudio(): Couldn't find any hardware audio formats"); - return (-1); + NTO_CloseDevice(this); + SDL_SetError("NTO: Couldn't find any hardware audio formats"); + return 0; } - spec->format = test_format; + this->spec.format = test_format; /* Set the audio format */ cparams.format.format = format; /* Set mono or stereo audio (currently only two channels supported) */ - cparams.format.voices = spec->channels; + cparams.format.voices = this->spec.channels; /* Set rate */ - cparams.format.rate = spec->freq; + cparams.format.rate = this->spec.freq; /* Setup the transfer parameters according to cparams */ - rval = snd_pcm_plugin_params(audio_handle, &cparams); + rval = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams); if (rval < 0) { - SDL_SetError - ("NTO_OpenAudio(): snd_pcm_channel_params failed: %s\n", - snd_strerror(rval)); - return (-1); + NTO_CloseDevice(this); + NTO_SetError("snd_pcm_channel_params", rval); + return 0; } /* Make sure channel is setup right one last time */ - SDL_memset(&csetup, 0x00, sizeof(csetup)); + SDL_memset(&csetup, '\0', sizeof (csetup)); csetup.channel = SND_PCM_CHANNEL_PLAYBACK; - if (snd_pcm_plugin_setup(audio_handle, &csetup) < 0) { - SDL_SetError("NTO_OpenAudio(): Unable to setup playback channel\n"); - return -1; + if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) { + NTO_CloseDevice(this); + SDL_SetError("NTO: Unable to setup playback channel\n"); + return 0; } - /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); - pcm_len = spec->size; + this->hidden->pcm_len = this->spec.size; - if (pcm_len == 0) { - pcm_len = - csetup.buf.block.frag_size * spec->channels * + if (this->hidden->pcm_len == 0) { + this->hidden->pcm_len = + csetup.buf.block.frag_size * this->spec.channels * (snd_pcm_format_width(format) / 8); } - /* Allocate memory to the audio buffer and initialize with silence (Note that - buffer size must be a multiple of fragment size, so find closest multiple) + /* + * Allocate memory to the audio buffer and initialize with silence + * (Note that buffer size must be a multiple of fragment size, so find + * closest multiple) */ - pcm_buf = (Uint8 *) SDL_AllocAudioMem(pcm_len); - if (pcm_buf == NULL) { - SDL_SetError("NTO_OpenAudio(): pcm buffer allocation failed\n"); - return (-1); + this->hidden->pcm_buf = (Uint8 *) SDL_AllocAudioMem(this->hidden->pcm_len); + if (this->hidden->pcm_buf == NULL) { + NTO_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } - SDL_memset(pcm_buf, spec->silence, pcm_len); + SDL_memset(this->hidden->pcm_buf,this->spec.silence,this->hidden->pcm_len); /* get the file descriptor */ - if ((audio_fd = - snd_pcm_file_descriptor(audio_handle, - SND_PCM_CHANNEL_PLAYBACK)) < 0) { - SDL_SetError - ("NTO_OpenAudio(): snd_pcm_file_descriptor failed with error code: %s\n", - snd_strerror(rval)); - return (-1); + this->hidden->audio_fd = snd_pcm_file_descriptor(this->hidden->audio_handle, + SND_PCM_CHANNEL_PLAYBACK); + if (this->hidden->audio_fd < 0) { + NTO_CloseDevice(this); + NTO_SetError("snd_pcm_file_descriptor", rval); + return 0; } /* Trigger audio playback */ - rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK); + rval = snd_pcm_plugin_prepare(this->hidden->audio_handle, + SND_PCM_CHANNEL_PLAYBACK); if (rval < 0) { - SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", - snd_strerror(rval)); - return (-1); + NTO_CloseDevice(this); + NTO_SetError("snd_pcm_plugin_prepare", rval); + return 0; } - this->enabled = 1; + /* We're really ready to rock and roll. :-) */ + return 1; +} - /* Get the parent process id (we're the parent of the audio thread) */ - parent = getpid(); - /* We're really ready to rock and roll. :-) */ - return (0); +static int +NTO_Init(SDL_AudioDriverImpl *impl) +{ + /* See if we can open a nonblocking channel. */ + snd_pcm_t *handle = NULL; + int rval = snd_pcm_open_preferred(&handle, NULL, NULL, OPEN_FLAGS); + if (rval < 0) { + SDL_SetError("NTO: couldn't open preferred audio device"); + return 0; + } + if ((rval = snd_pcm_close(handle)) < 0) { + SDL_SetError("NTO: couldn't close test audio device"); + return 0; + } + + /* Set the function pointers */ + impl->OpenDevice = NTO_OpenDevice; + impl->ThreadInit = NTO_ThreadInit; + impl->WaitDevice = NTO_WaitDevice; + impl->PlayDevice = NTO_PlayDevice; + impl->GetDeviceBuf = NTO_GetDeviceBuf; + impl->CloseDevice = NTO_CloseDevice; + impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: add device enum! */ + + return 1; } +AudioBootStrap QNXNTOAUDIO_bootstrap = { + DRIVER_NAME, "QNX6 QSA-NTO Audio", NTO_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/nto/SDL_nto_audio.h b/src/audio/nto/SDL_nto_audio.h index ed4a8b25b..75dff4743 100644 --- a/src/audio/nto/SDL_nto_audio.h +++ b/src/audio/nto/SDL_nto_audio.h @@ -47,23 +47,7 @@ struct SDL_PrivateAudioData /* Raw mixing buffer */ Uint8 *pcm_buf; Uint32 pcm_len; - - /* QSA parameters */ - snd_pcm_channel_status_t cstatus; - snd_pcm_channel_params_t cparams; - snd_pcm_channel_setup_t csetup; }; -#define cardno (this->hidden->cardno) -#define deviceno (this->hidden->deviceno) -#define audio_handle (this->hidden->audio_handle) -#define audio_fd (this->hidden->audio_fd) -#define parent (this->hidden->parent) -#define pcm_buf (this->hidden->pcm_buf) -#define pcm_len (this->hidden->pcm_len) -#define cstatus (this->hidden->cstatus) -#define cparams (this->hidden->cparams) -#define csetup (this->hidden->csetup) - #endif /* __SDL_NTO_AUDIO_H__ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/paudio/SDL_paudio.c b/src/audio/paudio/SDL_paudio.c index 81f26d9f6..b467c6d83 100644 --- a/src/audio/paudio/SDL_paudio.c +++ b/src/audio/paudio/SDL_paudio.c @@ -30,16 +30,17 @@ #include #include #include +#include #include #include "SDL_timer.h" #include "SDL_audio.h" +#include "SDL_stdinc.h" #include "../SDL_audiomem.h" #include "../SDL_audio_c.h" -#include "../SDL_audiodev_c.h" #include "SDL_paudio.h" -#define DEBUG_AUDIO 1 +#define DEBUG_AUDIO 0 /* A conflict within AIX 4.3.3 headers and probably others as well. * I guess nobody ever uses audio... Shame over AIX header files. */ @@ -48,94 +49,95 @@ #include /* The tag name used by paud audio */ -#define Paud_DRIVER_NAME "paud" +#define PAUDIO_DRIVER_NAME "paud" /* Open the audio device for playback, and don't block if busy */ /* #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) */ #define OPEN_FLAGS O_WRONLY -/* Audio driver functions */ -static int Paud_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void Paud_WaitAudio(_THIS); -static void Paud_PlayAudio(_THIS); -static Uint8 *Paud_GetAudioBuf(_THIS); -static void Paud_CloseAudio(_THIS); +/* Get the name of the audio device we use for output */ -/* Audio driver bootstrap functions */ +#ifndef _PATH_DEV_DSP +#define _PATH_DEV_DSP "/dev/%caud%c/%c" +#endif + +static char devsettings[][3] = { + {'p', '0', '1'}, {'p', '0', '2'}, {'p', '0', '3'}, {'p', '0', '4'}, + {'p', '1', '1'}, {'p', '1', '2'}, {'p', '1', '3'}, {'p', '1', '4'}, + {'p', '2', '1'}, {'p', '2', '2'}, {'p', '2', '3'}, {'p', '2', '4'}, + {'p', '3', '1'}, {'p', '3', '2'}, {'p', '3', '3'}, {'p', '3', '4'}, + {'b', '0', '1'}, {'b', '0', '2'}, {'b', '0', '3'}, {'b', '0', '4'}, + {'b', '1', '1'}, {'b', '1', '2'}, {'b', '1', '3'}, {'b', '1', '4'}, + {'b', '2', '1'}, {'b', '2', '2'}, {'b', '2', '3'}, {'b', '2', '4'}, + {'b', '3', '1'}, {'b', '3', '2'}, {'b', '3', '3'}, {'b', '3', '4'}, + {'\0', '\0', '\0'} +}; static int -Audio_Available(void) +OpenUserDefinedDevice(char *path, int maxlen, int flags) { + const char *audiodev; int fd; - int available; - available = 0; - fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); - if (fd >= 0) { - available = 1; - close(fd); + /* Figure out what our audio device is */ + if ((audiodev = SDL_getenv("SDL_PATH_DSP")) == NULL) { + audiodev = SDL_getenv("AUDIODEV"); } - return (available); -} - -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); + if (audiodev == NULL) { + return -1; + } + fd = open(audiodev, flags, 0); + if (path != NULL) { + SDL_strlcpy(path, audiodev, maxlen); + path[maxlen - 1] = '\0'; + } + return fd; } -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) +static int +OpenAudioPath(char *path, int maxlen, int flags, int classic) { - SDL_AudioDevice *this; + struct stat sb; + int cycle = 0; + int fd = OpenUserDefinedDevice(path, maxlen, flags); - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); + if (fd != -1) { + return fd; } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); + + /* !!! FIXME: do we really need a table here? */ + while (devsettings[cycle][0] != '\0') { + char audiopath[1024]; + SDL_snprintf(audiopath, SDL_arraysize(audiopath), + _PATH_DEV_DSP, + devsettings[cycle][0], + devsettings[cycle][1], devsettings[cycle][2]); + + if (stat(audiopath, &sb) == 0) { + fd = open(audiopath, flags, 0); + if (fd > 0) { + if (path != NULL) { + SDL_strlcpy(path, audiopath, maxlen); + } + return fd; + } } - return (0); } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - audio_fd = -1; - - /* Set the function pointers */ - this->OpenAudio = Paud_OpenAudio; - this->WaitAudio = Paud_WaitAudio; - this->PlayAudio = Paud_PlayAudio; - this->GetAudioBuf = Paud_GetAudioBuf; - this->CloseAudio = Paud_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; + return -1; } -AudioBootStrap Paud_bootstrap = { - Paud_DRIVER_NAME, "AIX Paudio", - Audio_Available, Audio_CreateDevice -}; - /* This function waits until it is possible to write a full sound buffer */ static void -Paud_WaitAudio(_THIS) +PAUDIO_WaitDevice(_THIS) { fd_set fdset; /* See if we need to use timed audio synchronization */ - if (frame_ticks) { + if (this->hidden->frame_ticks) { /* Use timer for general audio synchronization */ Sint32 ticks; - ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS; + ticks = ((Sint32)(this->hidden->next_frame-SDL_GetTicks()))-FUDGE_TICKS; if (ticks > 0) { SDL_Delay(ticks); } @@ -145,9 +147,9 @@ Paud_WaitAudio(_THIS) /* Use select() for audio synchronization */ struct timeval timeout; FD_ZERO(&fdset); - FD_SET(audio_fd, &fdset); + FD_SET(this->hidden->audio_fd, &fdset); - if (ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0) { + if (ioctl(this->hidden->audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0) { #ifdef DEBUG_AUDIO fprintf(stderr, "Couldn't get audio buffer information\n"); #endif @@ -168,7 +170,7 @@ Paud_WaitAudio(_THIS) #ifdef DEBUG_AUDIO fprintf(stderr, "Waiting for audio to get ready\n"); #endif - if (select(audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) { + if (select(this->hidden->audio_fd+1,NULL,&fdset,NULL,&timeout) <= 0) { const char *message = "Audio timeout - buggy audio driver? (disabled)"; /* @@ -179,7 +181,7 @@ Paud_WaitAudio(_THIS) fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message); this->enabled = 0; /* Don't try to close - may hang */ - audio_fd = -1; + this->hidden->audio_fd = -1; #ifdef DEBUG_AUDIO fprintf(stderr, "Done disabling audio\n"); #endif @@ -191,13 +193,15 @@ Paud_WaitAudio(_THIS) } static void -Paud_PlayAudio(_THIS) +PAUDIO_PlayDevice(_THIS) { - int written; + int written = 0; + const Uint8 *mixbuf = this->hidden->mixbuf; + const size_t mixlen = this->hidden->mixlen; /* Write the audio data, checking for EAGAIN on broken audio drivers */ do { - written = write(audio_fd, mixbuf, mixlen); + written = write(this->hidden->audio_fd, mixbuf, mixlen); if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) { SDL_Delay(1); /* Let a little CPU time go by */ } @@ -206,8 +210,8 @@ Paud_PlayAudio(_THIS) ((errno == 0) || (errno == EAGAIN) || (errno == EINTR))); /* If timer synchronization is enabled, set the next write frame */ - if (frame_ticks) { - next_frame += frame_ticks; + if (this->hidden->frame_ticks) { + this->hidden->next_frame += this->hidden->frame_ticks; } /* If we couldn't write, assume fatal error for now */ @@ -220,28 +224,34 @@ Paud_PlayAudio(_THIS) } static Uint8 * -Paud_GetAudioBuf(_THIS) +PAUDIO_GetDeviceBuf(_THIS) { - return mixbuf; + return this->hidden->mixbuf; } static void -Paud_CloseAudio(_THIS) +PAUDIO_CloseDevice(_THIS) { - if (mixbuf != NULL) { - SDL_FreeAudioMem(mixbuf); - mixbuf = NULL; - } - if (audio_fd >= 0) { - close(audio_fd); - audio_fd = -1; + if (this->hidden != NULL) { + if (this->hidden->mixbuf != NULL) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + if (this->hidden->audio_fd >= 0) { + close(this->hidden->audio_fd); + this->hidden->audio_fd = -1; + } + SDL_free(this->hidden); + this->hidden = NULL; } } static int -Paud_OpenAudio(_THIS, SDL_AudioSpec * spec) +PAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) { + const char *workaround = SDL_getenv("SDL_DSP_NOSELECT"); char audiodev[1024]; + const char *err = NULL; int format; int bytes_per_sample; SDL_AudioFormat test_format; @@ -250,32 +260,40 @@ Paud_OpenAudio(_THIS, SDL_AudioSpec * spec) audio_status paud_status; audio_control paud_control; audio_change paud_change; + int fd = -1; - /* Reset the timer synchronization flag */ - frame_ticks = 0.0; + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); /* Open the audio device */ - audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); - if (audio_fd < 0) { + fd = OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); + this->hidden->audio_fd = fd; + if (fd < 0) { + PAUDIO_CloseDevice(this); SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); - return -1; + return 0; } /* * We can't set the buffer size - just ask the device for the maximum * that we can have. */ - if (ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0) { + if (ioctl(fd, AUDIO_BUFFER, &paud_bufinfo) < 0) { + PAUDIO_CloseDevice(this); SDL_SetError("Couldn't get audio buffer information"); - return -1; + return 0; } - mixbuf = NULL; - - if (spec->channels > 1) - spec->channels = 2; + if (this->spec.channels > 1) + this->spec.channels = 2; else - spec->channels = 1; + this->spec.channels = 1; /* * Fields in the audio_init structure: @@ -322,14 +340,14 @@ Paud_OpenAudio(_THIS, SDL_AudioSpec * spec) * paud.position_resolution; * smallest increment for position */ - paud_init.srate = spec->freq; + paud_init.srate = this->spec.freq; paud_init.mode = PCM; paud_init.operation = PLAY; - paud_init.channels = spec->channels; + paud_init.channels = this->spec.channels; /* Try for a closest match on audio format */ format = 0; - for (test_format = SDL_FirstAudioFormat(spec->format); + for (test_format = SDL_FirstAudioFormat(this->spec.format); !format && test_format;) { #ifdef DEBUG_AUDIO fprintf(stderr, "Trying format 0x%4.4x\n", test_format); @@ -382,31 +400,32 @@ Paud_OpenAudio(_THIS, SDL_AudioSpec * spec) #ifdef DEBUG_AUDIO fprintf(stderr, "Couldn't find any hardware audio formats\n"); #endif + PAUDIO_CloseDevice(this); SDL_SetError("Couldn't find any hardware audio formats"); - return -1; + return 0; } - spec->format = test_format; + this->spec.format = test_format; /* * We know the buffer size and the max number of subsequent writes - * that can be pending. If more than one can pend, allow the application - * to do something like double buffering between our write buffer and - * the device's own buffer that we are filling with write() anyway. + * that can be pending. If more than one can pend, allow the application + * to do something like double buffering between our write buffer and + * the device's own buffer that we are filling with write() anyway. * - * We calculate spec->samples like this because SDL_CalculateAudioSpec() - * will give put paud_bufinfo.write_buf_cap (or paud_bufinfo.write_buf_cap/2) - * into spec->size in return. + * We calculate this->spec.samples like this because + * SDL_CalculateAudioSpec() will give put paud_bufinfo.write_buf_cap + * (or paud_bufinfo.write_buf_cap/2) into this->spec.size in return. */ if (paud_bufinfo.request_buf_cap == 1) { - spec->samples = paud_bufinfo.write_buf_cap - / bytes_per_sample / spec->channels; + this->spec.samples = paud_bufinfo.write_buf_cap + / bytes_per_sample / this->spec.channels; } else { - spec->samples = paud_bufinfo.write_buf_cap - / bytes_per_sample / spec->channels / 2; + this->spec.samples = paud_bufinfo.write_buf_cap + / bytes_per_sample / this->spec.channels / 2; } - paud_init.bsize = bytes_per_sample * spec->channels; + paud_init.bsize = bytes_per_sample * this->spec.channels; - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* * The AIX paud device init can't modify the values of the audio_init @@ -416,47 +435,44 @@ Paud_OpenAudio(_THIS, SDL_AudioSpec * spec) * /dev/paud supports all of the encoding formats, so we don't need * to do anything like reopening the device, either. */ - if (ioctl(audio_fd, AUDIO_INIT, &paud_init) < 0) { + if (ioctl(fd, AUDIO_INIT, &paud_init) < 0) { switch (paud_init.rc) { case 1: - SDL_SetError - ("Couldn't set audio format: DSP can't do play requests"); - return -1; + err = "Couldn't set audio format: DSP can't do play requests"; break; case 2: - SDL_SetError - ("Couldn't set audio format: DSP can't do record requests"); - return -1; + err = "Couldn't set audio format: DSP can't do record requests"; break; case 4: - SDL_SetError("Couldn't set audio format: request was invalid"); - return -1; + err = "Couldn't set audio format: request was invalid"; break; case 5: - SDL_SetError - ("Couldn't set audio format: conflict with open's flags"); - return -1; + err = "Couldn't set audio format: conflict with open's flags"; break; case 6: - SDL_SetError - ("Couldn't set audio format: out of DSP MIPS or memory"); - return -1; + err = "Couldn't set audio format: out of DSP MIPS or memory"; break; default: - SDL_SetError - ("Couldn't set audio format: not documented in sys/audio.h"); - return -1; + err = "Couldn't set audio format: not documented in sys/audio.h"; break; } } + if (err != NULL) { + PAUDIO_CloseDevice(this); + SDL_SetError("Paudio: %s", err); + return 0; + } + /* Allocate mixing buffer */ - mixlen = spec->size; - mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen); - if (mixbuf == NULL) { - return -1; + this->hidden->mixlen = this->spec.size; + this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); + if (this->hidden->mixbuf == NULL) { + PAUDIO_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } - SDL_memset(mixbuf, spec->silence, spec->size); + SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); /* * Set some paramters: full volume, first speaker that we can find. @@ -475,7 +491,7 @@ Paud_OpenAudio(_THIS, SDL_AudioSpec * spec) paud_control.ioctl_request = AUDIO_CHANGE; paud_control.request_info = (char *) &paud_change; - if (ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0) { + if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) { #ifdef DEBUG_AUDIO fprintf(stderr, "Can't change audio display settings\n"); #endif @@ -487,29 +503,49 @@ Paud_OpenAudio(_THIS, SDL_AudioSpec * spec) */ paud_control.ioctl_request = AUDIO_START; paud_control.position = 0; - if (ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0) { + if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) { + PAUDIO_CloseDevice(this); #ifdef DEBUG_AUDIO fprintf(stderr, "Can't start audio play\n"); #endif SDL_SetError("Can't start audio play"); - return -1; + return 0; } /* Check to see if we need to use select() workaround */ - { - char *workaround; - workaround = SDL_getenv("SDL_DSP_NOSELECT"); - if (workaround) { - frame_ticks = (float) (spec->samples * 1000) / spec->freq; - next_frame = SDL_GetTicks() + frame_ticks; - } + if (workaround != NULL) { + this->hidden->frame_ticks = (float) (this->spec.samples * 1000) / + this->spec.freq; + this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks; } - /* Get the parent process id (we're the parent of the audio thread) */ - parent = getpid(); - /* We're ready to rock and roll. :-) */ - return 0; + return 1; +} + +static int +PAUDIO_Init(SDL_AudioDriverImpl *impl) +{ + int fd = OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); + if (fd < 0) { + SDL_SetError("PAUDIO: Couldn't open audio device"); + return 0; + } + close(fd); + + /* Set the function pointers */ + impl->OpenDevice = DSP_OpenDevice; + impl->PlayDevice = DSP_PlayDevice; + impl->PlayDevice = DSP_WaitDevice; + impl->GetDeviceBuf = DSP_GetDeviceBuf; + impl->CloseDevice = DSP_CloseDevice; + impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: add device enum! */ + + return 1; } +AudioBootStrap PAUDIO_bootstrap = { + PAUDIO_DRIVER_NAME, "AIX Paudio", PAUDIO_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/paudio/SDL_paudio.h b/src/audio/paudio/SDL_paudio.h index 757dadd55..99d0a1b99 100644 --- a/src/audio/paudio/SDL_paudio.h +++ b/src/audio/paudio/SDL_paudio.h @@ -26,7 +26,7 @@ #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData @@ -34,9 +34,6 @@ struct SDL_PrivateAudioData /* The file descriptor for the audio device */ int audio_fd; - /* The parent process id, to detect when application quits */ - pid_t parent; - /* Raw mixing buffer */ Uint8 *mixbuf; int mixlen; @@ -47,13 +44,5 @@ struct SDL_PrivateAudioData }; #define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */ -/* Old variable names */ -#define audio_fd (this->hidden->audio_fd) -#define parent (this->hidden->parent) -#define mixbuf (this->hidden->mixbuf) -#define mixlen (this->hidden->mixlen) -#define frame_ticks (this->hidden->frame_ticks) -#define next_frame (this->hidden->next_frame) - #endif /* _SDL_paudaudio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/sun/SDL_sunaudio.c b/src/audio/sun/SDL_sunaudio.c index 0389e7a1a..7124b0c71 100644 --- a/src/audio/sun/SDL_sunaudio.c +++ b/src/audio/sun/SDL_sunaudio.c @@ -1,3 +1,8 @@ +/* I'm gambling no one uses this audio backend...we'll see who emails. :) */ +#error this code has not been updated for SDL 1.3. +#error if no one emails icculus at icculus.org and tells him that this +#error code is needed, this audio backend will eventually be removed from SDL. + /* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga @@ -116,7 +121,7 @@ Audio_CreateDevice(int devindex) AudioBootStrap SUNAUDIO_bootstrap = { "audio", "UNIX /dev/audio interface", - Audio_Available, Audio_CreateDevice + Audio_Available, Audio_CreateDevice, 0 }; #ifdef DEBUG_AUDIO diff --git a/src/audio/sun/SDL_sunaudio.h b/src/audio/sun/SDL_sunaudio.h index 1780ab1ce..b813a0fe3 100644 --- a/src/audio/sun/SDL_sunaudio.h +++ b/src/audio/sun/SDL_sunaudio.h @@ -21,12 +21,12 @@ */ #include "SDL_config.h" -#ifndef _SDL_lowaudio_h -#define _SDL_lowaudio_h +#ifndef _SDL_sunaudio_h +#define _SDL_sunaudio_h #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData @@ -53,5 +53,6 @@ struct SDL_PrivateAudioData #define fragsize (this->hidden->fragsize) #define frequency (this->hidden->frequency) -#endif /* _SDL_lowaudio_h */ +#endif /* _SDL_sunaudio_h */ + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/ums/SDL_umsaudio.c b/src/audio/ums/SDL_umsaudio.c index 2e5183371..3bdb414b5 100644 --- a/src/audio/ums/SDL_umsaudio.c +++ b/src/audio/ums/SDL_umsaudio.c @@ -1,3 +1,8 @@ +/* I'm gambling no one uses this audio backend...we'll see who emails. :) */ +#error this code has not been updated for SDL 1.3. +#error if no one emails icculus at icculus.org and tells him that this +#error code is needed, this audio backend will eventually be removed from SDL. + /* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga @@ -36,7 +41,6 @@ #include "SDL_audio.h" #include "../SDL_audio_c.h" -#include "../SDL_audiodev_c.h" #include "SDL_umsaudio.h" /* The tag name used by UMS audio */ @@ -152,7 +156,7 @@ Audio_CreateDevice(int devindex) AudioBootStrap UMS_bootstrap = { UMS_DRIVER_NAME, "AIX UMS audio", - Audio_Available, Audio_CreateDevice + Audio_Available, Audio_CreateDevice, 0 }; static Uint8 * diff --git a/src/audio/ums/SDL_umsaudio.h b/src/audio/ums/SDL_umsaudio.h index e7c95d444..0fc20e75c 100644 --- a/src/audio/ums/SDL_umsaudio.h +++ b/src/audio/ums/SDL_umsaudio.h @@ -30,7 +30,7 @@ #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this struct SDL_PrivateAudioData diff --git a/src/audio/windib/SDL_dibaudio.c b/src/audio/windib/SDL_dibaudio.c index 19eb005cb..633bdc354 100644 --- a/src/audio/windib/SDL_dibaudio.c +++ b/src/audio/windib/SDL_dibaudio.c @@ -35,71 +35,13 @@ #include "win_ce_semaphore.h" #endif - -/* Audio driver functions */ -static int DIB_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void DIB_ThreadInit(_THIS); -static void DIB_WaitAudio(_THIS); -static Uint8 *DIB_GetAudioBuf(_THIS); -static void DIB_PlayAudio(_THIS); -static void DIB_WaitDone(_THIS); -static void DIB_CloseAudio(_THIS); - -/* Audio driver bootstrap functions */ - -static int -Audio_Available(void) -{ - return (1); -} - -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); -} - -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - - /* Set the function pointers */ - this->OpenAudio = DIB_OpenAudio; - this->ThreadInit = DIB_ThreadInit; - this->WaitAudio = DIB_WaitAudio; - this->PlayAudio = DIB_PlayAudio; - this->GetAudioBuf = DIB_GetAudioBuf; - this->WaitDone = DIB_WaitDone; - this->CloseAudio = DIB_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap WAVEOUT_bootstrap = { - "waveout", "Win95/98/NT/2000 WaveOut", - Audio_Available, Audio_CreateDevice -}; - +#if defined(_WIN32_WCE) +#define WINDOWS_OS_NAME "Windows CE/PocketPC" +#elif defined(WIN64) +#define WINDOWS_OS_NAME "Win64" +#else +#define WINDOWS_OS_NAME "Win32" +#endif /* The Win32 callback for filling the WAVE device */ static void CALLBACK @@ -114,9 +56,9 @@ FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, /* Signal that we are done playing a buffer */ #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) - ReleaseSemaphoreCE(audio_sem, 1, NULL); + ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL); #else - ReleaseSemaphore(audio_sem, 1, NULL); + ReleaseSemaphore(this->hidden->audio_sem, 1, NULL); #endif } @@ -146,48 +88,47 @@ SetMMerror(char *function, MMRESULT code) /* Set high priority for the audio thread */ static void -DIB_ThreadInit(_THIS) +WINWAVEOUT_ThreadInit(_THIS) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); } void -DIB_WaitAudio(_THIS) +WINWAVEOUT_WaitDevice(_THIS) { /* Wait for an audio chunk to finish */ #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) - WaitForSemaphoreCE(audio_sem, INFINITE); + WaitForSemaphoreCE(this->hidden->audio_sem, INFINITE); #else - WaitForSingleObject(audio_sem, INFINITE); + WaitForSingleObject(this->hidden->audio_sem, INFINITE); #endif } Uint8 * -DIB_GetAudioBuf(_THIS) +WINWAVEOUT_GetDeviceBuf(_THIS) { - Uint8 *retval; - - retval = (Uint8 *) (wavebuf[next_buffer].lpData); - return retval; + return (Uint8 *) (this->hidden->wavebuf[this->hidden->next_buffer].lpData); } void -DIB_PlayAudio(_THIS) +WINWAVEOUT_PlayDevice(_THIS) { /* Queue it up */ - waveOutWrite(sound, &wavebuf[next_buffer], sizeof(wavebuf[0])); - next_buffer = (next_buffer + 1) % NUM_BUFFERS; + waveOutWrite(this->hidden->sound, + &this->hidden->wavebuf[this->hidden->next_buffer], + sizeof (this->hidden->wavebuf[0])); + this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS; } void -DIB_WaitDone(_THIS) +WINWAVEOUT_WaitDone(_THIS) { int i, left; do { left = NUM_BUFFERS; for (i = 0; i < NUM_BUFFERS; ++i) { - if (wavebuf[i].dwFlags & WHDR_DONE) { + if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) { --left; } } @@ -199,143 +140,197 @@ DIB_WaitDone(_THIS) } void -DIB_CloseAudio(_THIS) +WINWAVEOUT_CloseDevice(_THIS) { - int i; - /* Close up audio */ - if (audio_sem) { + if (this->hidden != NULL) { + int i; + + if (this->hidden->audio_sem) { #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) - CloseSynchHandle(audio_sem); + CloseSynchHandle(this->hidden->audio_sem); #else - CloseHandle(audio_sem); + CloseHandle(this->hidden->audio_sem); #endif - } - if (sound) { - waveOutClose(sound); - } + this->hidden->audio_sem = 0; + } - /* Clean up mixing buffers */ - for (i = 0; i < NUM_BUFFERS; ++i) { - if (wavebuf[i].dwUser != 0xFFFF) { - waveOutUnprepareHeader(sound, &wavebuf[i], sizeof(wavebuf[i])); - wavebuf[i].dwUser = 0xFFFF; + if (this->hidden->sound) { + waveOutClose(this->hidden->sound); + this->hidden->sound = 0; } - } - /* Free raw mixing buffer */ - if (mixbuf != NULL) { - SDL_free(mixbuf); - mixbuf = NULL; + + /* Clean up mixing buffers */ + for (i = 0; i < NUM_BUFFERS; ++i) { + if (this->hidden->wavebuf[i].dwUser != 0xFFFF) { + waveOutUnprepareHeader(this->hidden->sound, + &this->hidden->wavebuf[i], + sizeof (this->hidden->wavebuf[i])); + this->hidden->wavebuf[i].dwUser = 0xFFFF; + } + } + + if (this->hidden->mixbuf != NULL) { + /* Free raw mixing buffer */ + SDL_free(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + + SDL_free(this->hidden); + this->hidden = NULL; } } int -DIB_OpenAudio(_THIS, SDL_AudioSpec * spec) +WINWAVEOUT_OpenDevice(_THIS, const char *devname, int iscapture) { + SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); + int valid_datatype = 0; MMRESULT result; - int i; WAVEFORMATEX waveformat; + int i; + + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); /* Initialize the wavebuf structures for closing */ - sound = NULL; - audio_sem = NULL; for (i = 0; i < NUM_BUFFERS; ++i) - wavebuf[i].dwUser = 0xFFFF; - mixbuf = NULL; + this->hidden->wavebuf[i].dwUser = 0xFFFF; + + while ((!valid_datatype) && (test_format)) { + valid_datatype = 1; + _this->spec.format = test_format; + switch (test_format) { + case AUDIO_U8: + case AUDIO_S16: + case AUDIO_S32: + break; /* valid. */ + + default: + valid_datatype = 0; + test_format = SDL_NextAudioFormat(); + break; + } + } + + if (!valid_datatype) { + WINWAVEOUT_CloseDevice(this); + SDL_SetError("Unsupported audio format"); + return 0; + } /* Set basic WAVE format parameters */ - SDL_memset(&waveformat, 0, sizeof(waveformat)); + SDL_memset(&waveformat, '\0', sizeof (waveformat)); waveformat.wFormatTag = WAVE_FORMAT_PCM; + waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format); - /* Determine the audio parameters from the AudioSpec */ - switch (SDL_AUDIO_BITSIZE(spec->format)) { - case 8: - /* Unsigned 8 bit audio data */ - spec->format = AUDIO_U8; - waveformat.wBitsPerSample = 8; - break; - case 16: - /* Signed 16 bit audio data */ - spec->format = AUDIO_S16; - waveformat.wBitsPerSample = 16; - break; - case 32: - /* Signed 32 bit audio data */ - spec->format = AUDIO_S32; - waveformat.wBitsPerSample = 32; - break; - default: - SDL_SetError("Unsupported audio format"); - return (-1); - } - waveformat.nChannels = spec->channels; - waveformat.nSamplesPerSec = spec->freq; + if (this->spec.channels > 2) + this->spec.channels = 2; /* !!! FIXME: is this right? */ + + waveformat.nChannels = this->spec.channels; + waveformat.nSamplesPerSec = this->spec.freq; waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample / 8); waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign; /* Check the buffer size -- minimum of 1/4 second (word aligned) */ - if (spec->samples < (spec->freq / 4)) - spec->samples = ((spec->freq / 4) + 3) & ~3; + if (this->spec.samples < (this->spec.freq / 4)) + this->spec.samples = ((this->spec.freq / 4) + 3) & ~3; /* Update the fragment size as size in bytes */ - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Open the audio device */ - result = waveOutOpen(&sound, WAVE_MAPPER, &waveformat, + result = waveOutOpen(&this->hidden->sound, WAVE_MAPPER, &waveformat, (DWORD_PTR) FillSound, (DWORD_PTR) this, CALLBACK_FUNCTION); if (result != MMSYSERR_NOERROR) { + WINWAVEOUT_CloseDevice(this); SetMMerror("waveOutOpen()", result); - return (-1); + return 0; } #ifdef SOUND_DEBUG /* Check the sound device we retrieved */ { WAVEOUTCAPS caps; - result = waveOutGetDevCaps((UINT) sound, &caps, sizeof(caps)); + result = waveOutGetDevCaps((UINT) this->hidden->sound, + &caps, sizeof(caps)); if (result != MMSYSERR_NOERROR) { + WINWAVEOUT_CloseDevice(this); SetMMerror("waveOutGetDevCaps()", result); - return (-1); + return 0; } printf("Audio device: %s\n", caps.szPname); } #endif /* Create the audio buffer semaphore */ + this->hidden->audio_sem = #if defined(_WIN32_WCE) && (_WIN32_WCE < 300) - audio_sem = CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL); + CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL); #else - audio_sem = CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL); + CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL); #endif - if (audio_sem == NULL) { + if (this->hidden->audio_sem == NULL) { + WINWAVEOUT_CloseDevice(this); SDL_SetError("Couldn't create semaphore"); - return (-1); + return 0; } /* Create the sound buffers */ - mixbuf = (Uint8 *) SDL_malloc(NUM_BUFFERS * spec->size); + this->hidden->mixbuf = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size); if (mixbuf == NULL) { - SDL_SetError("Out of memory"); - return (-1); + WINWAVEOUT_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } for (i = 0; i < NUM_BUFFERS; ++i) { - SDL_memset(&wavebuf[i], 0, sizeof(wavebuf[i])); - wavebuf[i].lpData = (LPSTR) & mixbuf[i * spec->size]; - wavebuf[i].dwBufferLength = spec->size; - wavebuf[i].dwFlags = WHDR_DONE; - result = waveOutPrepareHeader(sound, &wavebuf[i], sizeof(wavebuf[i])); + SDL_memset(&this->hidden->wavebuf[i], '\0', + sizeof (this->hidden->wavebuf[i])); + this->hidden->wavebuf[i].dwBufferLength = this->spec.size; + this->hidden->wavebuf[i].dwFlags = WHDR_DONE; + this->hidden->wavebuf[i].lpData = + (LPSTR) &this->hidden->mixbuf[i * this->spec.size]; + result = waveOutPrepareHeader(this->hidden->sound, + &this->hidden->wavebuf[i], + sizeof (this->hidden->wavebuf[i])); if (result != MMSYSERR_NOERROR) { + WINWAVEOUT_CloseDevice(this); SetMMerror("waveOutPrepareHeader()", result); - return (-1); + return 0; } } - /* Ready to go! */ - next_buffer = 0; - return (0); + return 1; /* Ready to go! */ } + +static int +WINWAVEOUT_Init(SDL_AudioDriverImpl *impl) +{ + /* Set the function pointers */ + impl->OpenDevice = WINWAVEOUT_OpenDevice; + impl->ThreadInit = WINWAVEOUT_ThreadInit; + impl->PlayDevice = WINWAVEOUT_PlayDevice; + impl->WaitDevice = WINWAVEOUT_WaitDevice; + impl->WaitDone = WINWAVEOUT_WaitDone; + impl->GetDeviceBuf = WINWAVEOUT_GetDeviceBuf; + impl->CloseDevice = WINWAVEOUT_CloseDevice; + impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: Is this true? */ + + return 1; +} + +AudioBootStrap WINWAVEOUT_bootstrap = { + "waveout", WINDOWS_OS_NAME " WaveOut", WINWAVEOUT_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/windib/SDL_dibaudio.h b/src/audio/windib/SDL_dibaudio.h index c5e7d1468..c29e57c59 100644 --- a/src/audio/windib/SDL_dibaudio.h +++ b/src/audio/windib/SDL_dibaudio.h @@ -21,12 +21,12 @@ */ #include "SDL_config.h" -#ifndef _SDL_lowaudio_h -#define _SDL_lowaudio_h +#ifndef _SDL_dibaudio_h +#define _SDL_dibaudio_h #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this #define NUM_BUFFERS 2 /* -- Don't lower this! */ @@ -40,12 +40,6 @@ struct SDL_PrivateAudioData int next_buffer; }; -/* Old variable names */ -#define sound (this->hidden->sound) -#define audio_sem (this->hidden->audio_sem) -#define mixbuf (this->hidden->mixbuf) -#define wavebuf (this->hidden->wavebuf) -#define next_buffer (this->hidden->next_buffer) +#endif /* _SDL_dibaudio_h */ -#endif /* _SDL_lowaudio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/windx5/SDL_dx5audio.c b/src/audio/windx5/SDL_dx5audio.c index 4188b60f6..65a0195d4 100644 --- a/src/audio/windx5/SDL_dx5audio.c +++ b/src/audio/windx5/SDL_dx5audio.c @@ -28,160 +28,65 @@ #include "../SDL_audio_c.h" #include "SDL_dx5audio.h" -/* Define this if you want to use DirectX 6 DirectSoundNotify interface */ -//#define USE_POSITION_NOTIFY - -/* DirectX function pointers for audio */ -HRESULT(WINAPI * DSoundCreate) (LPGUID, LPDIRECTSOUND *, LPUNKNOWN); - -/* Audio driver functions */ -static int DX5_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void DX5_ThreadInit(_THIS); -static void DX5_WaitAudio_BusyWait(_THIS); -#ifdef USE_POSITION_NOTIFY -static void DX6_WaitAudio_EventWait(_THIS); +/* !!! FIXME: move this somewhere that other drivers can use it... */ +#if defined(_WIN32_WCE) +#define WINDOWS_OS_NAME "Windows CE/PocketPC" +#elif defined(WIN64) +#define WINDOWS_OS_NAME "Win64" +#else +#define WINDOWS_OS_NAME "Win32" #endif -static void DX5_PlayAudio(_THIS); -static Uint8 *DX5_GetAudioBuf(_THIS); -static void DX5_WaitDone(_THIS); -static void DX5_CloseAudio(_THIS); - -/* Audio driver bootstrap functions */ - -static int -Audio_Available(void) -{ - HINSTANCE DSoundDLL; - int dsound_ok; - - /* Version check DSOUND.DLL (Is DirectX okay?) */ - dsound_ok = 0; - DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL")); - if (DSoundDLL != NULL) { - /* We just use basic DirectSound, we're okay */ - /* Yay! */ - /* Unfortunately, the sound drivers on NT have - higher latencies than the audio buffers used - by many SDL applications, so there are gaps - in the audio - it sounds terrible. Punt for now. - */ - OSVERSIONINFO ver; - ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&ver); - switch (ver.dwPlatformId) { - case VER_PLATFORM_WIN32_NT: - if (ver.dwMajorVersion > 4) { - /* Win2K */ - dsound_ok = 1; - } else { - /* WinNT */ - dsound_ok = 0; - } - break; - default: - /* Win95 or Win98 */ - dsound_ok = 1; - break; - } - /* Now check for DirectX 5 or better - otherwise - * we will fail later in DX5_OpenAudio without a chance - * to fall back to the DIB driver. */ - if (dsound_ok) { - /* DirectSoundCaptureCreate was added in DX5 */ - if (!GetProcAddress(DSoundDLL, TEXT("DirectSoundCaptureCreate"))) - dsound_ok = 0; - } - /* Clean up.. */ - FreeLibrary(DSoundDLL); - } - return (dsound_ok); -} - -/* Functions for loading the DirectX functions dynamically */ +/* DirectX function pointers for audio */ static HINSTANCE DSoundDLL = NULL; +static HRESULT (WINAPI *DSoundCreate)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN) = NULL; static void -DX5_Unload(void) +DSOUND_Unload(void) { if (DSoundDLL != NULL) { FreeLibrary(DSoundDLL); - DSoundCreate = NULL; - DSoundDLL = NULL; } -} -static int -DX5_Load(void) -{ - int status; - DX5_Unload(); - DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL")); - if (DSoundDLL != NULL) { - DSoundCreate = (void *) GetProcAddress(DSoundDLL, - TEXT("DirectSoundCreate")); - } - if (DSoundDLL && DSoundCreate) { - status = 0; - } else { - DX5_Unload(); - status = -1; - } - return status; + DSoundCreate = NULL; + DSoundDLL = NULL; } -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - DX5_Unload(); - SDL_free(device->hidden); - SDL_free(device); -} -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) +static int +DSOUND_Load(void) { - SDL_AudioDevice *this; + int loaded = 0; - /* Load DirectX */ - if (DX5_Load() < 0) { - return (NULL); - } + DSOUND_Unload(); - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); + DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL")); + if (DSoundDLL == NULL) { + SDL_SetError("DirectSound: failed to load DSOUND.DLL"); + } else { + /* Now make sure we have DirectX 5 or better... */ + /* (DirectSoundCaptureCreate was added in DX5) */ + if (!GetProcAddress(DSoundDLL, TEXT("DirectSoundCaptureCreate"))) { + SDL_SetError("DirectSound: System doesn't appear to have DX5."); + } else { + DSoundCreate = (void *) GetProcAddress(DSoundDLL, + TEXT("DirectSoundCreate")); } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - /* Set the function pointers */ - this->OpenAudio = DX5_OpenAudio; - this->ThreadInit = DX5_ThreadInit; - this->WaitAudio = DX5_WaitAudio_BusyWait; - this->PlayAudio = DX5_PlayAudio; - this->GetAudioBuf = DX5_GetAudioBuf; - this->WaitDone = DX5_WaitDone; - this->CloseAudio = DX5_CloseAudio; + if (!DSoundCreate) { + SDL_SetError("DirectSound: Failed to find DirectSoundCreate"); + } else { + loaded = 1; + } + } - this->free = Audio_DeleteDevice; + if (!loaded) { + DSOUND_Unload(); + } - return this; + return loaded; } -AudioBootStrap DSOUND_bootstrap = { - "dsound", "Win95/98/2000 DirectSound", - Audio_Available, Audio_CreateDevice -}; static void SetDSerror(const char *function, int code) @@ -192,8 +97,7 @@ SetDSerror(const char *function, int code) errbuf[0] = 0; switch (code) { case E_NOINTERFACE: - error = - "Unsupported interface\n-- Is DirectX 5.0 or later installed?"; + error = "Unsupported interface -- Is DirectX 5.0 or later installed?"; break; case DSERR_ALLOCATED: error = "Audio device in use"; @@ -241,32 +145,36 @@ SetDSerror(const char *function, int code) /* DirectSound needs to be associated with a window */ static HWND mainwin = NULL; /* */ + void -DX5_SoundFocus(HWND hwnd) +DSOUND_SoundFocus(HWND hwnd) { + /* !!! FIXME: probably broken with multi-window support in SDL 1.3 ... */ mainwin = hwnd; } static void -DX5_ThreadInit(_THIS) +DSOUND_ThreadInit(_THIS) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); } static void -DX5_WaitAudio_BusyWait(_THIS) +DSOUND_WaitDevice(_THIS) { - DWORD status; - DWORD cursor, junk; - HRESULT result; + DWORD status = 0; + DWORD cursor = 0; + DWORD junk = 0; + HRESULT result = DS_OK; /* Semi-busy wait, since we have no way of getting play notification on a primary mixing buffer located in hardware (DirectX 5.0) */ - result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor); + result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf, + &junk, &cursor); if (result != DS_OK) { if (result == DSERR_BUFFERLOST) { - IDirectSoundBuffer_Restore(mixbuf); + IDirectSoundBuffer_Restore(this->hidden->mixbuf); } #ifdef DEBUG_SOUND SetDSerror("DirectSound GetCurrentPosition", result); @@ -274,21 +182,22 @@ DX5_WaitAudio_BusyWait(_THIS) return; } - while ((cursor / mixlen) == lastchunk) { + while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) { /* FIXME: find out how much time is left and sleep that long */ SDL_Delay(1); /* Try to restore a lost sound buffer */ - IDirectSoundBuffer_GetStatus(mixbuf, &status); + IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status); if ((status & DSBSTATUS_BUFFERLOST)) { - IDirectSoundBuffer_Restore(mixbuf); - IDirectSoundBuffer_GetStatus(mixbuf, &status); + IDirectSoundBuffer_Restore(this->hidden->mixbuf); + IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status); if ((status & DSBSTATUS_BUFFERLOST)) { break; } } if (!(status & DSBSTATUS_PLAYING)) { - result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); + result = IDirectSoundBuffer_Play(this->hidden->mixbuf, 0, 0, + DSBPLAY_LOOPING); if (result == DS_OK) { continue; } @@ -299,7 +208,7 @@ DX5_WaitAudio_BusyWait(_THIS) } /* Find out where we are playing */ - result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, + result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf, &junk, &cursor); if (result != DS_OK) { SetDSerror("DirectSound GetCurrentPosition", result); @@ -308,222 +217,122 @@ DX5_WaitAudio_BusyWait(_THIS) } } -#ifdef USE_POSITION_NOTIFY -static void -DX6_WaitAudio_EventWait(_THIS) -{ - DWORD status; - HRESULT result; - - /* Try to restore a lost sound buffer */ - IDirectSoundBuffer_GetStatus(mixbuf, &status); - if ((status & DSBSTATUS_BUFFERLOST)) { - IDirectSoundBuffer_Restore(mixbuf); - IDirectSoundBuffer_GetStatus(mixbuf, &status); - if ((status & DSBSTATUS_BUFFERLOST)) { - return; - } - } - if (!(status & DSBSTATUS_PLAYING)) { - result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING); - if (result != DS_OK) { -#ifdef DEBUG_SOUND - SetDSerror("DirectSound Play", result); -#endif - return; - } - } - WaitForSingleObject(audio_event, INFINITE); -} -#endif /* USE_POSITION_NOTIFY */ - static void -DX5_PlayAudio(_THIS) +DSOUND_PlayDevice(_THIS) { /* Unlock the buffer, allowing it to play */ - if (locked_buf) { - IDirectSoundBuffer_Unlock(mixbuf, locked_buf, mixlen, NULL, 0); + if (this->hidden->locked_buf) { + IDirectSoundBuffer_Unlock(this->hidden->mixbuf, + this->hidden->locked_buf, + this->hidden->mixlen, NULL, 0); } } static Uint8 * -DX5_GetAudioBuf(_THIS) +DSOUND_GetDeviceBuf(_THIS) { - DWORD cursor, junk; - HRESULT result; - DWORD rawlen; + DWORD cursor = 0; + DWORD junk = 0; + HRESULT result = DS_OK; + DWORD rawlen = 0; /* Figure out which blocks to fill next */ - locked_buf = NULL; - result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor); + this->hidden->locked_buf = NULL; + result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf, + &junk, &cursor); if (result == DSERR_BUFFERLOST) { - IDirectSoundBuffer_Restore(mixbuf); - result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, + IDirectSoundBuffer_Restore(this->hidden->mixbuf); + result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf, &junk, &cursor); } if (result != DS_OK) { SetDSerror("DirectSound GetCurrentPosition", result); return (NULL); } - cursor /= mixlen; + cursor /= this->hidden->mixlen; #ifdef DEBUG_SOUND /* Detect audio dropouts */ { DWORD spot = cursor; - if (spot < lastchunk) { - spot += NUM_BUFFERS; + if (spot < this->hidden->lastchunk) { + spot += this->hidden->num_buffers; } - if (spot > lastchunk + 1) { + if (spot > this->hidden->lastchunk + 1) { fprintf(stderr, "Audio dropout, missed %d fragments\n", - (spot - (lastchunk + 1))); + (spot - (this->hidden->lastchunk + 1))); } } #endif - lastchunk = cursor; - cursor = (cursor + 1) % NUM_BUFFERS; - cursor *= mixlen; + this->hidden->lastchunk = cursor; + cursor = (cursor + 1) % this->hidden->num_buffers; + cursor *= this->hidden->mixlen; /* Lock the audio buffer */ - result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, - (LPVOID *) & locked_buf, &rawlen, NULL, - &junk, 0); + result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor, + this->hidden->mixlen, + (LPVOID *) &this->hidden->locked_buf, + &rawlen, NULL, &junk, 0); if (result == DSERR_BUFFERLOST) { - IDirectSoundBuffer_Restore(mixbuf); - result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen, - (LPVOID *) & locked_buf, &rawlen, - NULL, &junk, 0); + IDirectSoundBuffer_Restore(this->hidden->mixbuf); + result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor, + this->hidden->mixlen, + (LPVOID *) &this->hidden->locked_buf, + &rawlen, NULL, &junk, 0); } if (result != DS_OK) { SetDSerror("DirectSound Lock", result); return (NULL); } - return (locked_buf); + return (this->hidden->locked_buf); } static void -DX5_WaitDone(_THIS) +DSOUND_WaitDone(_THIS) { - Uint8 *stream; + Uint8 *stream = DSOUND_GetDeviceBuf(this); /* Wait for the playing chunk to finish */ - stream = this->GetAudioBuf(this); if (stream != NULL) { - SDL_memset(stream, silence, mixlen); - this->PlayAudio(this); + SDL_memset(stream, this->spec.silence, this->hidden->mixlen); + DSOUND_PlayDevice(this); } - this->WaitAudio(this); + DSOUND_WaitDevice(this); /* Stop the looping sound buffer */ - IDirectSoundBuffer_Stop(mixbuf); + IDirectSoundBuffer_Stop(this->hidden->mixbuf); } static void -DX5_CloseAudio(_THIS) +DSOUND_CloseDevice(_THIS) { - if (sound != NULL) { - if (mixbuf != NULL) { - /* Clean up the audio buffer */ - IDirectSoundBuffer_Release(mixbuf); - mixbuf = NULL; - } - if (audio_event != NULL) { - CloseHandle(audio_event); - audio_event = NULL; + if (this->hidden != NULL) { + if (this->hidden->sound != NULL) { + if (this->hidden->mixbuf != NULL) { + /* Clean up the audio buffer */ + IDirectSoundBuffer_Release(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + IDirectSound_Release(this->hidden->sound); + this->hidden->sound = NULL; } - IDirectSound_Release(sound); - sound = NULL; - } -} -#ifdef USE_PRIMARY_BUFFER -/* This function tries to create a primary audio buffer, and returns the - number of audio chunks available in the created buffer. -*/ -static int -CreatePrimary(LPDIRECTSOUND sndObj, HWND focus, - LPDIRECTSOUNDBUFFER * sndbuf, WAVEFORMATEX * wavefmt, - Uint32 chunksize) -{ - HRESULT result; - DSBUFFERDESC format; - DSBCAPS caps; - int numchunks; - - /* Try to set primary mixing privileges */ - result = IDirectSound_SetCooperativeLevel(sndObj, focus, - DSSCL_WRITEPRIMARY); - if (result != DS_OK) { -#ifdef DEBUG_SOUND - SetDSerror("DirectSound SetCooperativeLevel", result); -#endif - return (-1); + SDL_free(this->hidden); + this->hidden = NULL; } - - /* Try to create the primary buffer */ - SDL_memset(&format, 0, sizeof(format)); - format.dwSize = sizeof(format); - format.dwFlags = (DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2); - format.dwFlags |= DSBCAPS_STICKYFOCUS; -#ifdef USE_POSITION_NOTIFY - format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; -#endif - result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); - if (result != DS_OK) { -#ifdef DEBUG_SOUND - SetDSerror("DirectSound CreateSoundBuffer", result); -#endif - return (-1); - } - - /* Check the size of the fragment buffer */ - SDL_memset(&caps, 0, sizeof(caps)); - caps.dwSize = sizeof(caps); - result = IDirectSoundBuffer_GetCaps(*sndbuf, &caps); - if (result != DS_OK) { -#ifdef DEBUG_SOUND - SetDSerror("DirectSound GetCaps", result); -#endif - IDirectSoundBuffer_Release(*sndbuf); - return (-1); - } - if ((chunksize > caps.dwBufferBytes) || - ((caps.dwBufferBytes % chunksize) != 0)) { - /* The primary buffer size is not a multiple of 'chunksize' - -- this hopefully doesn't happen when 'chunksize' is a - power of 2. - */ - IDirectSoundBuffer_Release(*sndbuf); - SDL_SetError - ("Primary buffer size is: %d, cannot break it into chunks of %d bytes\n", - caps.dwBufferBytes, chunksize); - return (-1); - } - numchunks = (caps.dwBufferBytes / chunksize); - - /* Set the primary audio format */ - result = IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); - if (result != DS_OK) { -#ifdef DEBUG_SOUND - SetDSerror("DirectSound SetFormat", result); -#endif - IDirectSoundBuffer_Release(*sndbuf); - return (-1); - } - return (numchunks); } -#endif /* USE_PRIMARY_BUFFER */ /* This function tries to create a secondary audio buffer, and returns the number of audio chunks available in the created buffer. */ static int -CreateSecondary(LPDIRECTSOUND sndObj, HWND focus, - LPDIRECTSOUNDBUFFER * sndbuf, WAVEFORMATEX * wavefmt, - Uint32 chunksize) +CreateSecondary(_THIS, HWND focus, WAVEFORMATEX *wavefmt) { + LPDIRECTSOUND sndObj = this->hidden->sound; + LPDIRECTSOUNDBUFFER *sndbuf = this->hidden->mixbuf; + Uint32 chunksize = this->spec.size; const int numchunks = 8; - HRESULT result; + HRESULT result = DS_OK; DSBUFFERDESC format; LPVOID pvAudioPtr1, pvAudioPtr2; DWORD dwAudioBytes1, dwAudioBytes2; @@ -538,9 +347,7 @@ CreateSecondary(LPDIRECTSOUND sndObj, HWND focus, DSSCL_NORMAL); } if (result != DS_OK) { -#ifdef DEBUG_SOUND SetDSerror("DirectSound SetCooperativeLevel", result); -#endif return (-1); } @@ -548,9 +355,6 @@ CreateSecondary(LPDIRECTSOUND sndObj, HWND focus, SDL_memset(&format, 0, sizeof(format)); format.dwSize = sizeof(format); format.dwFlags = DSBCAPS_GETCURRENTPOSITION2; -#ifdef USE_POSITION_NOTIFY - format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; -#endif if (!focus) { format.dwFlags |= DSBCAPS_GLOBALFOCUS; } else { @@ -578,11 +382,7 @@ CreateSecondary(LPDIRECTSOUND sndObj, HWND focus, (LPVOID *) & pvAudioPtr2, &dwAudioBytes2, DSBLOCK_ENTIREBUFFER); if (result == DS_OK) { - if (wavefmt->wBitsPerSample == 8) { - SDL_memset(pvAudioPtr1, 0x80, dwAudioBytes1); - } else { - SDL_memset(pvAudioPtr1, 0x00, dwAudioBytes1); - } + SDL_memset(pvAudioPtr1, this->spec.silence, dwAudioBytes1); IDirectSoundBuffer_Unlock(*sndbuf, (LPVOID) pvAudioPtr1, dwAudioBytes1, (LPVOID) pvAudioPtr2, dwAudioBytes2); @@ -592,148 +392,125 @@ CreateSecondary(LPDIRECTSOUND sndObj, HWND focus, return (numchunks); } -/* This function tries to set position notify events on the mixing buffer */ -#ifdef USE_POSITION_NOTIFY static int -CreateAudioEvent(_THIS) +DSOUND_OpenDevice(_THIS, const char *devname, int iscapture) { - LPDIRECTSOUNDNOTIFY notify; - DSBPOSITIONNOTIFY *notify_positions; - int i, retval; HRESULT result; + WAVEFORMATEX waveformat; + int valid_format = 0; + SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); - /* Default to fail on exit */ - retval = -1; - notify = NULL; + /* !!! FIXME: handle devname */ + /* !!! FIXME: handle iscapture */ - /* Query for the interface */ - result = IDirectSoundBuffer_QueryInterface(mixbuf, - &IID_IDirectSoundNotify, - (void *) ¬ify); - if (result != DS_OK) { - goto done; - } - - /* Allocate the notify structures */ - notify_positions = (DSBPOSITIONNOTIFY *) SDL_malloc(NUM_BUFFERS * - sizeof - (*notify_positions)); - if (notify_positions == NULL) { - goto done; + /* Initialize all variables that we clean on shutdown */ + this->hidden = (struct SDL_PrivateAudioData *) + SDL_malloc((sizeof *this->hidden)); + if (this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; } + SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - /* Create the notify event */ - audio_event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (audio_event == NULL) { - goto done; + while ((!valid_format) && (test_format)) { + switch (test_format) { + case AUDIO_U8: + case AUDIO_S16: + case AUDIO_S32: + this->spec.format = test_format; + valid_format = 1; + break; + } + test_format = SDL_NextAudioFormat(); } - /* Set up the notify structures */ - for (i = 0; i < NUM_BUFFERS; ++i) { - notify_positions[i].dwOffset = i * mixlen; - notify_positions[i].hEventNotify = audio_event; - } - result = IDirectSoundNotify_SetNotificationPositions(notify, - NUM_BUFFERS, - notify_positions); - if (result == DS_OK) { - retval = 0; - } - done: - if (notify != NULL) { - IDirectSoundNotify_Release(notify); + if (!valid_format) { + DSOUND_CloseDevice(this); + SDL_SetError("DirectSound: Unsupported audio format"); + return 0; } - return (retval); -} -#endif /* USE_POSITION_NOTIFY */ -static int -DX5_OpenAudio(_THIS, SDL_AudioSpec * spec) -{ - HRESULT result; - WAVEFORMATEX waveformat; - - /* Set basic WAVE format parameters */ SDL_memset(&waveformat, 0, sizeof(waveformat)); waveformat.wFormatTag = WAVE_FORMAT_PCM; - - /* Determine the audio parameters from the AudioSpec */ - switch (SDL_AUDIO_BITSIZE(spec->format)) { - case 8: - /* Unsigned 8 bit audio data */ - spec->format = AUDIO_U8; - silence = 0x80; - waveformat.wBitsPerSample = 8; - break; - case 16: - /* Signed 16 bit audio data */ - spec->format = AUDIO_S16; - silence = 0x00; - waveformat.wBitsPerSample = 16; - break; - case 32: - /* Signed 32 bit audio data */ - spec->format = AUDIO_S32; - silence = 0x00; - waveformat.wBitsPerSample = 32; - break; - default: - SDL_SetError("Unsupported audio format"); - return (-1); - } - waveformat.nChannels = spec->channels; - waveformat.nSamplesPerSec = spec->freq; + waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format); + waveformat.nChannels = this->spec.channels; + waveformat.nSamplesPerSec = this->spec.freq; waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample / 8); waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign; /* Update the fragment size as size in bytes */ - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Open the audio device */ - result = DSoundCreate(NULL, &sound, NULL); + result = DSoundCreate(NULL, &this->hidden->sound, NULL); if (result != DS_OK) { + DSOUND_CloseDevice(this); SetDSerror("DirectSoundCreate", result); - return (-1); + return 0; } /* Create the audio buffer to which we write */ - NUM_BUFFERS = -1; -#ifdef USE_PRIMARY_BUFFER - if (mainwin) { - NUM_BUFFERS = CreatePrimary(sound, mainwin, &mixbuf, - &waveformat, spec->size); + this->hidden->num_buffers = CreateSecondary(this, mainwin, &waveformat); + if (this->hidden->num_buffers < 0) { + DSOUND_CloseDevice(this); + return 0; } -#endif /* USE_PRIMARY_BUFFER */ - if (NUM_BUFFERS < 0) { - NUM_BUFFERS = CreateSecondary(sound, mainwin, &mixbuf, - &waveformat, spec->size); - if (NUM_BUFFERS < 0) { - return (-1); + + /* The buffer will auto-start playing in DSOUND_WaitDevice() */ + this->hidden->mixlen = this->spec.size; + + return 1; /* good to go. */ +} + + +static void +DSOUND_Deinitialize(void) +{ + DSOUND_Unload(); +} + + +static int +DSOUND_Init(SDL_AudioDriverImpl *impl) +{ + OSVERSIONINFO ver; + + /* + * Unfortunately, the sound drivers on NT have higher latencies than the + * audio buffers used by many SDL applications, so there are gaps in the + * audio - it sounds terrible. Punt for now. + */ + SDL_memset(&ver, '\0', sizeof (OSVERSIONINFO)); + ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&ver); + if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) + if (ver.dwMajorVersion <= 4) { + return 0; /* NT4.0 or earlier. Disable dsound support. */ } -#ifdef DEBUG_SOUND - fprintf(stderr, "Using secondary audio buffer\n"); -#endif } -#ifdef DEBUG_SOUND - else - fprintf(stderr, "Using primary audio buffer\n"); -#endif - - /* The buffer will auto-start playing in DX5_WaitAudio() */ - lastchunk = 0; - mixlen = spec->size; -#ifdef USE_POSITION_NOTIFY - /* See if we can use DirectX 6 event notification */ - if (CreateAudioEvent(this) == 0) { - this->WaitAudio = DX6_WaitAudio_EventWait; - } else { - this->WaitAudio = DX5_WaitAudio_BusyWait; + if (!DSOUND_Load()) { + return 0; } -#endif - return (0); + + /* Set the function pointers */ + impl->OpenDevice = DSOUND_OpenDevice; + impl->PlayDevice = DSOUND_PlayDevice; + impl->WaitDevice = DSOUND_WaitDevice; + impl->WaitDone = DSOUND_WaitDone; + impl->ThreadInit = DSOUND_ThreadInit; + impl->GetDeviceBuf = DSOUND_GetDeviceBuf; + impl->CloseDevice = DSOUND_CloseDevice; + impl->Deinitialize = DSOUND_Deinitialize; + impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME */ + + return 1; } +AudioBootStrap DSOUND_bootstrap = { + "dsound", WINDOWS_OS_NAME "DirectSound", DSOUND_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/windx5/SDL_dx5audio.h b/src/audio/windx5/SDL_dx5audio.h index 93ecb60e3..c32172eff 100644 --- a/src/audio/windx5/SDL_dx5audio.h +++ b/src/audio/windx5/SDL_dx5audio.h @@ -21,14 +21,14 @@ */ #include "SDL_config.h" -#ifndef _SDL_lowaudio_h -#define _SDL_lowaudio_h +#ifndef _SDL_dx5audio_h +#define _SDL_dx5audio_h #include "directx.h" #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this /* The DirectSound objects */ @@ -36,23 +36,12 @@ struct SDL_PrivateAudioData { LPDIRECTSOUND sound; LPDIRECTSOUNDBUFFER mixbuf; - int NUM_BUFFERS; - int mixlen, silence; + int num_buffers; + int mixlen; DWORD lastchunk; Uint8 *locked_buf; - HANDLE audio_event; }; -/* Old variable names */ -#define sound (this->hidden->sound) -#define mixbuf (this->hidden->mixbuf) -#define NUM_BUFFERS (this->hidden->NUM_BUFFERS) -#define mixlen (this->hidden->mixlen) -#define silence (this->hidden->silence) -#define lastchunk (this->hidden->lastchunk) -#define locked_buf (this->hidden->locked_buf) -#define audio_event (this->hidden->audio_event) - -#endif /* _SDL_lowaudio_h */ +#endif /* _SDL_dx5audio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 0236d204b..c66e80ecb 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -165,7 +165,7 @@ SDL_GetMouseFocusWindow() return mouse->focus; } -static int +static int SDLCALL FlushMouseMotion(void *param, SDL_Event * event) { if (event->type == SDL_MOUSEMOTION diff --git a/src/timer/os2/SDL_systimer.c b/src/timer/os2/SDL_systimer.c index a2cf48adc..02721e01d 100644 --- a/src/timer/os2/SDL_systimer.c +++ b/src/timer/os2/SDL_systimer.c @@ -65,24 +65,28 @@ SDL_GetTicks(void) */ /* inline asm to avoid runtime inclusion */ _asm { - push edx - push eax - mov eax, dword ptr hires_now - mov edx, dword ptr hires_now + 4 - sub eax, dword ptr hires_start_ticks - sbb edx, dword ptr hires_start_ticks + 4 - mov ebx, 1000 - mov ecx, edx - mul ebx - push eax - push edx - mov eax, ecx - mul ebx - pop eax - add edx, eax - pop eax - mov ebx, dword ptr hires_ticks_per_second - div ebx mov dword ptr ticks, eax pop edx pop eax} + push edx + push eax + mov eax, dword ptr hires_now + mov edx, dword ptr hires_now + 4 + sub eax, dword ptr hires_start_ticks + sbb edx, dword ptr hires_start_ticks + 4 + mov ebx, 1000 + mov ecx, edx + mul ebx + push eax + push edx + mov eax, ecx + mul ebx + pop eax + add edx, eax + pop eax + mov ebx, dword ptr hires_ticks_per_second + div ebx + mov dword ptr ticks, eax + pop edx + pop eax + } return ticks; @@ -178,7 +182,7 @@ SDL_Delay(Uint32 ms) static int timer_alive = 0; static SDL_Thread *timer = NULL; -static int +static int SDLCALL RunTimer(void *unused) { DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0); diff --git a/src/video/SDL_rendercopy.h b/src/video/SDL_rendercopy.h index a442e905d..85ae996cc 100644 --- a/src/video/SDL_rendercopy.h +++ b/src/video/SDL_rendercopy.h @@ -33,10 +33,10 @@ #define SDL_RENDERCOPY_NEAREST 0x0100 typedef struct { - void *src; + Uint8 *src; int src_w, src_h; int src_pitch; - void *dst; + Uint8 *dst; int dst_w, dst_h; int dst_pitch; void *aux_data; @@ -44,7 +44,7 @@ typedef struct { Uint8 r, g, b, a; } SDL_RenderCopyData; -typedef int (*SDL_RenderCopyFunc)(SDL_RenderCopyData *data); +typedef int (SDLCALL * SDL_RenderCopyFunc)(SDL_RenderCopyData *data); extern SDL_RenderCopyFunc SDLCALL SDL_GetRenderCopyFunc(Uint32 src_format, Uint32 dst_format, int modMode, int blendMode, int scaleMode); diff --git a/test/Makefile.in b/test/Makefile.in index cf4dc5375..1a06095b2 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -7,7 +7,7 @@ EXE = @EXE@ CFLAGS = @CFLAGS@ LIBS = @LIBS@ -TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testcursor$(EXE) testdyngl$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE) +TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testaudioinfo$(EXE) testmultiaudio$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testcursor$(EXE) testdyngl$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE) all: Makefile $(TARGETS) @@ -23,6 +23,12 @@ graywin$(EXE): $(srcdir)/graywin.c loopwave$(EXE): $(srcdir)/loopwave.c $(CC) -o $@ $? $(CFLAGS) $(LIBS) +testaudioinfo$(EXE): $(srcdir)/testaudioinfo.c + $(CC) -o $@ $? $(CFLAGS) $(LIBS) + +testmultiaudio$(EXE): $(srcdir)/testmultiaudio.c + $(CC) -o $@ $? $(CFLAGS) $(LIBS) + testalpha$(EXE): $(srcdir)/testalpha.c $(CC) -o $@ $? $(CFLAGS) $(LIBS) @MATHLIB@ diff --git a/test/loopwave.c b/test/loopwave.c index 2965ce50f..d49572e25 100644 --- a/test/loopwave.c +++ b/test/loopwave.c @@ -69,26 +69,12 @@ main(int argc, char *argv[]) { int i, n; - /* Print available audio drivers */ - n = SDL_GetNumAudioDrivers(); - if (n == 0) { - printf("No built-in audio drivers\n"); - } else { - printf("Built-in audio drivers:"); - for (i = 0; i < n; ++i) { - if (i > 0) { - printf(","); - } - printf(" %s", SDL_GetAudioDriver(i)); - } - printf("\n"); - } - /* Load the SDL library */ if (SDL_Init(SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); return (1); } + if (argv[1] == NULL) { argv[1] = "sample.wav"; } @@ -120,7 +106,6 @@ main(int argc, char *argv[]) SDL_PauseAudio(0); /* Let the audio run */ - printf("Using audio driver: %s\n", SDL_GetCurrentAudioDriver()); while (!done && (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING)) SDL_Delay(1000); diff --git a/test/testaudioinfo.c b/test/testaudioinfo.c new file mode 100644 index 000000000..3b9283c05 --- /dev/null +++ b/test/testaudioinfo.c @@ -0,0 +1,53 @@ +#include "SDL.h" + +static void print_devices(int iscapture) +{ + const char *typestr = ((iscapture) ? "capture" : "output"); + int n = SDL_GetNumAudioDevices(iscapture); + + printf("%s devices:\n", typestr); + + if (n == -1) + printf(" Driver can't detect specific devices.\n\n", typestr); + else if (n == 0) + printf(" No %s devices found.\n\n", typestr); + else + { + int i; + for (i = 0; i < n; i++) { + printf(" %s\n", SDL_GetAudioDeviceName(i, iscapture)); + } + printf("\n"); + } +} + +int main(int argc, char **argv) +{ + /* Print available audio drivers */ + int n = SDL_GetNumAudioDrivers(); + if (n == 0) { + printf("No built-in audio drivers\n\n"); + } else { + int i; + printf("Built-in audio drivers:\n"); + for (i = 0; i < n; ++i) { + printf(" %s\n", SDL_GetAudioDriver(i)); + } + printf("\n"); + } + + /* Load the SDL library */ + if (SDL_Init(SDL_INIT_AUDIO) < 0) { + fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); + return (1); + } + + printf("Using audio driver: %s\n\n", SDL_GetCurrentAudioDriver()); + + print_devices(0); + print_devices(1); + + SDL_Quit(); + return 0; +} + diff --git a/test/testmultiaudio.c b/test/testmultiaudio.c new file mode 100644 index 000000000..d93723037 --- /dev/null +++ b/test/testmultiaudio.c @@ -0,0 +1,136 @@ +#include "SDL.h" + +static SDL_AudioSpec spec; +static Uint8 *sound = NULL; /* Pointer to wave data */ +static Uint32 soundlen = 0; /* Length of wave data */ + +typedef struct +{ + SDL_AudioDeviceID dev; + int soundpos; + volatile int done; +} callback_data; + +void SDLCALL play_through_once(void *arg, Uint8 * stream, int len) +{ + callback_data *cbd = (callback_data *) arg; + Uint8 *waveptr = sound + cbd->soundpos; + int waveleft = soundlen - cbd->soundpos; + int cpy = len; + if (cpy > waveleft) + cpy = waveleft; + + memcpy(stream, waveptr, cpy); + len -= cpy; + cbd->soundpos += cpy; + if (len > 0) { + stream += cpy; + memset(stream, spec.silence, len); + cbd->done++; + } +} + +static void test_multi_audio(int devcount) +{ + callback_data cbd[64]; + int keep_going = 1; + int i; + + if (devcount > 64) { + fprintf(stderr, "Too many devices (%d), clamping to 64...\n", devcount); + devcount = 64; + } + + spec.callback = play_through_once; + + for (i = 0; i < devcount; i++) { + const char *devname = SDL_GetAudioDeviceName(i, 0); + printf("playing on device #%d: ('%s')...", i, devname); + fflush(stdout); + + memset(&cbd[0], '\0', sizeof (callback_data)); + spec.userdata = &cbd[0]; + cbd[0].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL); + if (cbd[0].dev == 0) { + printf("Open device failed: %s\n", SDL_GetError()); + } else { + SDL_PauseAudioDevice(cbd[0].dev, 0); + while (!cbd[0].done) + SDL_Delay(100); + SDL_PauseAudioDevice(cbd[0].dev, 1); + printf("done.\n"); + SDL_CloseAudioDevice(cbd[0].dev); + } + } + + memset(cbd, '\0', sizeof (cbd)); + + printf("playing on all devices...\n"); + for (i = 0; i < devcount; i++) { + const char *devname = SDL_GetAudioDeviceName(i, 0); + spec.userdata = &cbd[i]; + cbd[i].dev = SDL_OpenAudioDevice(devname, 0, &spec, NULL); + if (cbd[i].dev == 0) { + printf("Open device %d failed: %s\n", i, SDL_GetError()); + } + } + + for (i = 0; i < devcount; i++) { + if (cbd[i].dev) { + SDL_PauseAudioDevice(cbd[i].dev, 0); + } + } + + while (keep_going) { + keep_going = 0; + for (i = 0; i < devcount; i++) { + if ((cbd[i].dev) && (!cbd[i].done)) { + keep_going = 1; + } + } + SDL_Delay(100); + } + + for (i = 0; i < devcount; i++) { + if (cbd[i].dev) { + SDL_PauseAudioDevice(cbd[i].dev, 1); + SDL_CloseAudioDevice(cbd[i].dev); + } + } + + printf("All done!\n"); +} + + +int main(int argc, char **argv) +{ + int devcount = 0; + + /* Load the SDL library */ + if (SDL_Init(SDL_INIT_AUDIO) < 0) { + fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); + return (1); + } + + printf("Using audio driver: %s\n", SDL_GetCurrentAudioDriver()); + + devcount = SDL_GetNumAudioDevices(0); + if (devcount < 1) { + fprintf(stderr, "Don't see any specific audio devices!\n"); + } else { + if (argv[1] == NULL) { + argv[1] = "sample.wav"; + } + + /* Load the wave file into memory */ + if (SDL_LoadWAV(argv[1], &spec, &sound, &soundlen) == NULL) { + fprintf(stderr, "Couldn't load %s: %s\n", argv[1], SDL_GetError()); + } else { + test_multi_audio(devcount); + SDL_FreeWAV(sound); + } + } + + SDL_Quit(); + return 0; +}