From 5202ee826abea85d069897bb64a9c2da83e3657a Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 4 Aug 2011 00:31:11 -0400 Subject: [PATCH] Cleaned up audio device detection. Cleared out a lot of cut-and-paste. --- src/audio/SDL_audio.c | 108 +++++++++++++++++--- src/audio/SDL_audiodev.c | 45 ++------ src/audio/SDL_audiodev_c.h | 18 +++- src/audio/SDL_sysaudio.h | 12 ++- src/audio/bsd/SDL_bsdaudio.c | 82 +-------------- src/audio/directsound/SDL_directsound.c | 95 +++-------------- src/audio/dsp/SDL_dspaudio.c | 73 +------------ src/audio/macosx/SDL_coreaudio.c | 130 +++++++----------------- src/audio/qsa/SDL_qsa_audio.c | 34 +------ src/audio/winmm/SDL_winmm.c | 101 ++++-------------- src/audio/xaudio2/SDL_xaudio2.c | 64 ++---------- 11 files changed, 217 insertions(+), 545 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 2df703486..a03115768 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -151,10 +151,9 @@ get_audio_device(SDL_AudioDeviceID 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_AudioDetectDevices_Default(int iscapture, SDL_AddAudioDevice addfn) +{ /* no-op. */ } static void @@ -199,13 +198,6 @@ 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) { @@ -238,7 +230,6 @@ finalize_audio_entry_points(void) current_audio.impl.x = SDL_Audio##x##_Default; \ } FILL_STUB(DetectDevices); - FILL_STUB(GetDeviceName); FILL_STUB(OpenDevice); FILL_STUB(ThreadInit); FILL_STUB(WaitDevice); @@ -641,13 +632,64 @@ SDL_GetCurrentAudioDriver() return current_audio.name; } +static void +free_device_list(char ***devices, int *devCount) +{ + int i = *devCount; + if ((i > 0) && (*devices != NULL)) { + while (i--) { + SDL_free((*devices)[i]); + } + } + + if (*devices != NULL) { + SDL_free(*devices); + } + + *devices = NULL; + *devCount = 0; +} + +static +void SDL_AddCaptureAudioDevice(const char *_name) +{ + char *name = NULL; + void *ptr = SDL_realloc(current_audio.inputDevices, + (current_audio.inputDeviceCount+1) * sizeof(char*)); + if (ptr == NULL) { + return; /* oh well. */ + } + + current_audio.inputDevices = (char **) ptr; + name = SDL_strdup(_name); /* if this returns NULL, that's okay. */ + current_audio.inputDevices[current_audio.inputDeviceCount++] = name; +} + +static +void SDL_AddOutputAudioDevice(const char *_name) +{ + char *name = NULL; + void *ptr = SDL_realloc(current_audio.outputDevices, + (current_audio.outputDeviceCount+1) * sizeof(char*)); + if (ptr == NULL) { + return; /* oh well. */ + } + + current_audio.outputDevices = (char **) ptr; + name = SDL_strdup(_name); /* if this returns NULL, that's okay. */ + current_audio.outputDevices[current_audio.outputDeviceCount++] = name; +} + int SDL_GetNumAudioDevices(int iscapture) { + int retval = 0; + if (!SDL_WasInit(SDL_INIT_AUDIO)) { return -1; } + if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) { return 0; } @@ -660,7 +702,19 @@ SDL_GetNumAudioDevices(int iscapture) return 1; } - return current_audio.impl.DetectDevices(iscapture); + if (iscapture) { + free_device_list(¤t_audio.inputDevices, + ¤t_audio.inputDeviceCount); + current_audio.impl.DetectDevices(iscapture, SDL_AddCaptureAudioDevice); + retval = current_audio.inputDeviceCount; + } else { + free_device_list(¤t_audio.outputDevices, + ¤t_audio.outputDeviceCount); + current_audio.impl.DetectDevices(iscapture, SDL_AddOutputAudioDevice); + retval = current_audio.outputDeviceCount; + } + + return retval; } @@ -678,8 +732,7 @@ SDL_GetAudioDeviceName(int index, int iscapture) } if (index < 0) { - SDL_SetError("No such device"); - return NULL; + goto no_such_device; } if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) { @@ -690,7 +743,21 @@ SDL_GetAudioDeviceName(int index, int iscapture) return DEFAULT_OUTPUT_DEVNAME; } - return current_audio.impl.GetDeviceName(index, iscapture); + if (iscapture) { + if (index >= current_audio.inputDeviceCount) { + goto no_such_device; + } + return current_audio.inputDevices[index]; + } else { + if (index >= current_audio.outputDeviceCount) { + goto no_such_device; + } + return current_audio.outputDevices[index]; + } + +no_such_device: + SDL_SetError("No such device"); + return NULL; } @@ -880,6 +947,11 @@ open_audio_device(const char *devname, int iscapture, } } + /* force a device detection if we haven't done one yet. */ + if ( ((iscapture) && (current_audio.inputDevices == NULL)) || + ((!iscapture) && (current_audio.outputDevices == NULL)) ) + SDL_GetNumAudioDevices(iscapture); + if (!current_audio.impl.OpenDevice(device, devname, iscapture)) { close_audio_device(device); return 0; @@ -1121,6 +1193,10 @@ SDL_AudioQuit(void) /* Free the driver data */ current_audio.impl.Deinitialize(); + free_device_list(¤t_audio.outputDevices, + ¤t_audio.outputDeviceCount); + free_device_list(¤t_audio.inputDevices, + ¤t_audio.inputDeviceCount); SDL_memset(¤t_audio, '\0', sizeof(current_audio)); SDL_memset(open_devices, '\0', sizeof(open_devices)); } diff --git a/src/audio/SDL_audiodev.c b/src/audio/SDL_audiodev.c index 2b1551ae6..2d8e3936a 100644 --- a/src/audio/SDL_audiodev.c +++ b/src/audio/SDL_audiodev.c @@ -48,46 +48,20 @@ static inline void test_device(const char *fname, int flags, int (*test) (int fd), - char ***devices, int *devCount) + SDL_AddAudioDevice addfn) { 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; - } + const int audio_fd = open(fname, flags, 0); + if (audio_fd >= 0) { + if (test(audio_fd)) { + addfn(fname); } close(audio_fd); } } } -void -SDL_FreeUnixAudioDevices(char ***devices, int *devCount) -{ - int i = *devCount; - if ((i > 0) && (*devices != NULL)) { - while (i--) { - SDL_free((*devices)[i]); - } - } - - if (*devices != NULL) { - SDL_free(*devices); - } - - *devices = NULL; - *devCount = 0; -} - static int test_stub(int fd) { @@ -95,9 +69,10 @@ test_stub(int fd) } void -SDL_EnumUnixAudioDevices(int flags, int classic, int (*test) (int fd), - char ***devices, int *devCount) +SDL_EnumUnixAudioDevices(int iscapture, int classic, int (*test)(int fd), + SDL_AddAudioDevice addfn) { + const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); const char *audiodev; char audiopath[1024]; @@ -122,14 +97,14 @@ SDL_EnumUnixAudioDevices(int flags, int classic, int (*test) (int fd), } } } - test_device(audiodev, flags, test, devices, devCount); + test_device(audiodev, flags, test, addfn); if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) { int instance = 0; while (instance++ <= 64) { SDL_snprintf(audiopath, SDL_arraysize(audiopath), "%s%d", audiodev, instance); - test_device(audiopath, flags, test, devices, devCount); + test_device(audiopath, flags, test, addfn); } } } diff --git a/src/audio/SDL_audiodev_c.h b/src/audio/SDL_audiodev_c.h index 7a4340044..919b3a855 100644 --- a/src/audio/SDL_audiodev_c.h +++ b/src/audio/SDL_audiodev_c.h @@ -18,10 +18,22 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +#include "SDL.h" #include "SDL_config.h" +#include "SDL_sysaudio.h" -void SDL_EnumUnixAudioDevices(int flags, int classic, int (*test) (int fd), - char ***devs, int *count); -void SDL_FreeUnixAudioDevices(char ***devices, int *devCount); +/* Open the audio device for playback, and don't block if busy */ +/* #define USE_BLOCKING_WRITES */ + +#ifdef USE_BLOCKING_WRITES +#define OPEN_FLAGS_OUTPUT O_WRONLY +#define OPEN_FLAGS_INPUT O_RDONLY +#else +#define OPEN_FLAGS_OUTPUT (O_WRONLY|O_NONBLOCK) +#define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK) +#endif + +void SDL_EnumUnixAudioDevices(int iscapture, int classic, + int (*test) (int fd), SDL_AddAudioDevice addfn); /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 027e3dbb8..14e22a8c1 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -30,10 +30,12 @@ typedef struct SDL_AudioDevice SDL_AudioDevice; #define _THIS SDL_AudioDevice *_this +/* Used by audio targets during DetectDevices() */ +typedef void (*SDL_AddAudioDevice)(const char *name); + typedef struct SDL_AudioDriverImpl { - int (*DetectDevices) (int iscapture); - const char *(*GetDeviceName) (int index, int iscapture); + void (*DetectDevices) (int iscapture, SDL_AddAudioDevice addfn); int (*OpenDevice) (_THIS, const char *devname, int iscapture); void (*ThreadInit) (_THIS); /* Called by audio thread at start */ void (*WaitDevice) (_THIS); @@ -67,6 +69,12 @@ typedef struct SDL_AudioDriver const char *desc; SDL_AudioDriverImpl impl; + + char **outputDevices; + int outputDeviceCount; + + char **inputDevices; + int inputDeviceCount; } SDL_AudioDriver; diff --git a/src/audio/bsd/SDL_bsdaudio.c b/src/audio/bsd/SDL_bsdaudio.c index 5f39935ea..ef881cfb8 100644 --- a/src/audio/bsd/SDL_bsdaudio.c +++ b/src/audio/bsd/SDL_bsdaudio.c @@ -50,91 +50,23 @@ #define BSD_AUDIO_DRIVER_DESC "Native OpenBSD audio" #endif -/* Open the audio device for playback, and don't block if busy */ -/* #define USE_BLOCKING_WRITES */ - /* Use timer for synchronization */ /* #define USE_TIMER_SYNC */ /* #define DEBUG_AUDIO */ /* #define DEBUG_AUDIO_STREAM */ -#ifdef USE_BLOCKING_WRITES -#define OPEN_FLAGS_OUTPUT O_WRONLY -#define OPEN_FLAGS_INPUT O_RDONLY -#else -#define OPEN_FLAGS_OUTPUT (O_WRONLY|O_NONBLOCK) -#define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK) -#endif - -/* !!! FIXME: so much cut and paste with dsp target... */ -static char **outputDevices = NULL; -static int outputDeviceCount = 0; -static char **inputDevices = NULL; -static int inputDeviceCount = 0; - -static inline void -free_device_list(char ***devs, int *count) -{ - SDL_FreeUnixAudioDevices(devs, count); -} - -static inline void -build_device_list(int iscapture, char ***devs, int *count) -{ - const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); - free_device_list(devs, count); - SDL_EnumUnixAudioDevices(flags, 0, NULL, devs, count); -} - -static inline void -build_device_lists(void) -{ - build_device_list(0, &outputDevices, &outputDeviceCount); - build_device_list(1, &inputDevices, &inputDeviceCount); -} - - -static inline void -free_device_lists(void) -{ - free_device_list(&outputDevices, &outputDeviceCount); - free_device_list(&inputDevices, &inputDeviceCount); -} - static void BSDAUDIO_Deinitialize(void) { - free_device_lists(); } -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; - } - - return 0; /* shouldn't ever hit this. */ -} - -static const char * -BSDAUDIO_GetDeviceName(int index, int iscapture) +static void +BSDAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) { - if ((iscapture) && (index < inputDeviceCount)) { - return inputDevices[index]; - } else if ((!iscapture) && (index < outputDeviceCount)) { - return outputDevices[index]; - } - - SDL_SetError("No such device"); - return NULL; + SDL_EnumUnixAudioDevices(iscapture, 0, NULL, addfn); } @@ -318,12 +250,11 @@ BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) /* 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))) { + devname = SDL_GetAudioDeviceName(0, iscapture); + if (devname == NULL) { SDL_SetError("No such audio device"); return 0; } - devname = ((iscapture) ? inputDevices[0] : outputDevices[0]); } /* Initialize all variables that we clean on shutdown */ @@ -434,7 +365,6 @@ 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; @@ -442,8 +372,6 @@ BSDAUDIO_Init(SDL_AudioDriverImpl * impl) impl->CloseDevice = BSDAUDIO_CloseDevice; impl->Deinitialize = BSDAUDIO_Deinitialize; - build_device_lists(); - return 1; /* this audio target is available. */ } diff --git a/src/audio/directsound/SDL_directsound.c b/src/audio/directsound/SDL_directsound.c index ac6fe15f3..03db0be4d 100644 --- a/src/audio/directsound/SDL_directsound.c +++ b/src/audio/directsound/SDL_directsound.c @@ -148,96 +148,28 @@ SetDSerror(const char *function, int code) } - -/* !!! FIXME: this is a cut and paste of SDL_FreeUnixAudioDevices(), - * !!! FIXME: which is more proof this needs to be managed in SDL_audio.c - * !!! FIXME: and not in drivers. - */ -static void -FreeDSoundAudioDevices(char ***devices, int *devCount) +static BOOL CALLBACK +FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data) { - int i = *devCount; - if ((i > 0) && (*devices != NULL)) { - while (i--) { - SDL_free((*devices)[i]); + SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data; + if (guid != NULL) { /* skip default device */ + char *str = utf16_to_utf8(desc); + if (str != NULL) { + addfn(str); + SDL_free(str); /* addfn() makes a copy of this string. */ } } - - if (*devices != NULL) { - SDL_free(*devices); - } - - *devices = NULL; - *devCount = 0; -} - - -typedef struct FindAllDevsData -{ - const char **devs; - unsigned int devcount; -} FindAllDevsData; - -static BOOL CALLBACK -FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID _data) -{ - FindAllDevsData *data = (FindAllDevsData *) _data; - void *ptr; - char *name; - - if (guid == NULL) - return TRUE; /* skip default device, go to the next one. */ - - ptr = SDL_realloc(data->devs, ((data->devcount) + 1) * sizeof(char *)); - if (ptr == NULL) - return TRUE; /* oh well. */ - - data->devs = (const char **) ptr; - name = utf16_to_utf8(desc); - if (name != NULL) - data->devs[data->devcount++] = name; - return TRUE; /* keep enumerating. */ } -static char **outputDevices = NULL; -static int outputDeviceCount = 0; -static char **inputDevices = NULL; -static int inputDeviceCount = 0; - -static int -DSOUND_DetectDevices(int iscapture) +static void +DSOUND_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) { - FindAllDevsData data; - data.devs = NULL; - data.devcount = 0; - if (iscapture) { - FreeDSoundAudioDevices(&inputDevices, &inputDeviceCount); - pDirectSoundCaptureEnumerateW(FindAllDevs, &devs); - inputDevices = data.devs; - inputDeviceCount = data.devcount; + pDirectSoundCaptureEnumerateW(FindAllDevs, addfn); } else { - FreeDSoundAudioDevices(&outputDevices, &outputDeviceCount); - pDirectSoundEnumerateW(FindAllDevs, &devs); - outputDevices = data.devs; - outputDeviceCount = data.devcount; + pDirectSoundEnumerateW(FindAllDevs, addfn); } - - return data.devcount; -} - -static const char * -DSOUND_GetDeviceName(int index, int iscapture) -{ - if ((iscapture) && (index < inputDeviceCount)) { - return inputDevices[index]; - } else if ((!iscapture) && (index < outputDeviceCount)) { - return outputDevices[index]; - } - - SDL_SetError("No such device"); - return NULL; } @@ -589,8 +521,6 @@ DSOUND_OpenDevice(_THIS, const char *devname, int iscapture) static void DSOUND_Deinitialize(void) { - FreeDSoundAudioDevices(&inputDevices, &inputDeviceCount); - FreeDSoundAudioDevices(&outputDevices, &outputDeviceCount); DSOUND_Unload(); } @@ -604,7 +534,6 @@ DSOUND_Init(SDL_AudioDriverImpl * impl) /* Set the function pointers */ impl->DetectDevices = DSOUND_DetectDevices; - impl->GetDeviceName = DSOUND_GetDeviceName; impl->OpenDevice = DSOUND_OpenDevice; impl->PlayDevice = DSOUND_PlayDevice; impl->WaitDevice = DSOUND_WaitDevice; diff --git a/src/audio/dsp/SDL_dspaudio.c b/src/audio/dsp/SDL_dspaudio.c index ef303ee7b..a621b7ba3 100644 --- a/src/audio/dsp/SDL_dspaudio.c +++ b/src/audio/dsp/SDL_dspaudio.c @@ -50,77 +50,16 @@ /* The tag name used by DSP audio */ #define DSP_DRIVER_NAME "dsp" -/* Open the audio device for playback, and don't block if busy */ -#define OPEN_FLAGS_OUTPUT (O_WRONLY|O_NONBLOCK) -#define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK) - -static char **outputDevices = NULL; -static int outputDeviceCount = 0; -static char **inputDevices = NULL; -static int inputDeviceCount = 0; - -static inline void -free_device_list(char ***devs, int *count) -{ - SDL_FreeUnixAudioDevices(devs, count); -} - -static inline void -build_device_list(int iscapture, char ***devs, int *count) -{ - const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); - free_device_list(devs, count); - SDL_EnumUnixAudioDevices(flags, 0, NULL, devs, count); -} - -static inline void -build_device_lists(void) -{ - build_device_list(0, &outputDevices, &outputDeviceCount); - build_device_list(1, &inputDevices, &inputDeviceCount); -} - - -static inline void -free_device_lists(void) -{ - free_device_list(&outputDevices, &outputDeviceCount); - free_device_list(&inputDevices, &inputDeviceCount); -} - - static void DSP_Deinitialize(void) { - free_device_lists(); } -static int +static void DSP_DetectDevices(int iscapture) { - if (iscapture) { - build_device_list(1, &inputDevices, &inputDeviceCount); - return inputDeviceCount; - } else { - build_device_list(0, &outputDevices, &outputDeviceCount); - return outputDeviceCount; - } - - return 0; /* shouldn't ever hit this. */ -} - -static const char * -DSP_GetDeviceName(int index, int iscapture) -{ - if ((iscapture) && (index < inputDeviceCount)) { - return inputDevices[index]; - } else if ((!iscapture) && (index < outputDeviceCount)) { - return outputDevices[index]; - } - - SDL_SetError("No such device"); - return NULL; + SDL_EnumUnixAudioDevices(iscapture, 0, NULL); } @@ -154,12 +93,11 @@ DSP_OpenDevice(_THIS, const char *devname, int iscapture) /* 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))) { + devname = SDL_GetAudioDeviceName(0, iscapture); + if (devname == NULL) { SDL_SetError("No such audio device"); return 0; } - devname = ((iscapture) ? inputDevices[0] : outputDevices[0]); } /* Make sure fragment size stays a power of 2, or OSS fails. */ @@ -369,15 +307,12 @@ 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; /* this audio target is available. */ } diff --git a/src/audio/macosx/SDL_coreaudio.c b/src/audio/macosx/SDL_coreaudio.c index e1f877d5e..d03176de0 100644 --- a/src/audio/macosx/SDL_coreaudio.c +++ b/src/audio/macosx/SDL_coreaudio.c @@ -34,34 +34,36 @@ #define DEBUG_COREAUDIO 0 -typedef struct COREAUDIO_DeviceList +typedef void (*addDevFn)(const char *name, AudioDeviceID devId, void *data); + +static void +addToDevList(const char *name, AudioDeviceID devId, void *data) { - AudioDeviceID id; - const char *name; -} COREAUDIO_DeviceList; + SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data; + addfn(name); +} -static COREAUDIO_DeviceList *inputDevices = NULL; -static int inputDeviceCount = 0; -static COREAUDIO_DeviceList *outputDevices = NULL; -static int outputDeviceCount = 0; +typedef struct +{ + const char *findname; + AudioDeviceID devId; + int found; +} FindDevIdData; static void -free_device_list(COREAUDIO_DeviceList ** devices, int *devCount) +findDevId(const char *name, AudioDeviceID devId, void *_data) { - if (*devices) { - int i = *devCount; - while (i--) - SDL_free((void *) (*devices)[i].name); - SDL_free(*devices); - *devices = NULL; + FindDevIdData *data = (FindDevIdData *) _data; + if (!data->found) { + if (SDL_strcmp(name, data->findname) == 0) { + data->found = 1; + data->devId = devId; + } } - *devCount = 0; } - static void -build_device_list(int iscapture, COREAUDIO_DeviceList ** devices, - int *devCount) +build_device_list(int iscapture, addDevFn addfn, void *addfndata) { Boolean outWritable = 0; OSStatus result = noErr; @@ -70,8 +72,6 @@ build_device_list(int iscapture, COREAUDIO_DeviceList ** devices, UInt32 i = 0; UInt32 max = 0; - free_device_list(devices, devCount); - result = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &outWritable); @@ -82,16 +82,12 @@ build_device_list(int iscapture, COREAUDIO_DeviceList ** devices, 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; + max = size / sizeof (AudioDeviceID); for (i = 0; i < max; i++) { CFStringRef cfstr = NULL; char *ptr = NULL; @@ -156,9 +152,7 @@ build_device_list(int iscapture, COREAUDIO_DeviceList ** devices, usable = (len > 0); } - if (!usable) { - SDL_free(ptr); - } else { + if (usable) { ptr[len] = '\0'; #if DEBUG_COREAUDIO @@ -166,80 +160,22 @@ build_device_list(int iscapture, COREAUDIO_DeviceList ** devices, ((iscapture) ? "capture" : "output"), (int) *devCount, ptr, (int) dev); #endif - - (*devices)[*devCount].id = dev; - (*devices)[*devCount].name = ptr; - (*devCount)++; - } - } -} - -static inline void -build_device_lists(void) -{ - build_device_list(0, &outputDevices, &outputDeviceCount); - build_device_list(1, &inputDevices, &inputDeviceCount); -} - - -static inline void -free_device_lists(void) -{ - free_device_list(&outputDevices, &outputDeviceCount); - free_device_list(&inputDevices, &inputDeviceCount); -} - - -static int -find_device_id(const char *devname, int iscapture, AudioDeviceID * id) -{ - int i = ((iscapture) ? inputDeviceCount : outputDeviceCount); - COREAUDIO_DeviceList *devs = ((iscapture) ? inputDevices : outputDevices); - while (i--) { - if (SDL_strcmp(devname, devs->name) == 0) { - *id = devs->id; - return 1; + addfn(ptr, dev, addfndata); } - devs++; - } - - return 0; -} - - -static int -COREAUDIO_DetectDevices(int iscapture) -{ - if (iscapture) { - build_device_list(1, &inputDevices, &inputDeviceCount); - return inputDeviceCount; - } else { - build_device_list(0, &outputDevices, &outputDeviceCount); - return outputDeviceCount; + SDL_free(ptr); /* addfn() would have copied the string. */ } - - return 0; /* shouldn't ever hit this. */ } - -static const char * -COREAUDIO_GetDeviceName(int index, int iscapture) +static void +COREAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) { - if ((iscapture) && (index < inputDeviceCount)) { - return inputDevices[index].name; - } else if ((!iscapture) && (index < outputDeviceCount)) { - return outputDevices[index].name; - } - - SDL_SetError("No such device"); - return NULL; + build_device_list(iscapture, addToDevList, addfn); } static void COREAUDIO_Deinitialize(void) { - free_device_lists(); } @@ -378,10 +314,15 @@ find_device_by_name(_THIS, const char *devname, int iscapture) result = AudioHardwareGetProperty(propid, &size, &devid); CHECK_RESULT("AudioHardwareGetProperty (default device)"); } else { - if (!find_device_id(devname, iscapture, &devid)) { + FindDevIdData data; + SDL_zero(data); + data.findname = devname; + build_device_list(iscapture, findDevId, &data); + if (!data.found) { SDL_SetError("CoreAudio: No such audio device."); return 0; } + devid = data.devId; } size = sizeof(alive); @@ -565,14 +506,11 @@ COREAUDIO_Init(SDL_AudioDriverImpl * impl) { /* Set the function pointers */ impl->DetectDevices = COREAUDIO_DetectDevices; - impl->GetDeviceName = COREAUDIO_GetDeviceName; impl->OpenDevice = COREAUDIO_OpenDevice; impl->CloseDevice = COREAUDIO_CloseDevice; impl->Deinitialize = COREAUDIO_Deinitialize; impl->ProvidesOwnCallbackThread = 1; - build_device_lists(); /* do an initial check for devices... */ - return 1; /* this audio target is available. */ } diff --git a/src/audio/qsa/SDL_qsa_audio.c b/src/audio/qsa/SDL_qsa_audio.c index c3588941d..4cfc2e7d0 100644 --- a/src/audio/qsa/SDL_qsa_audio.c +++ b/src/audio/qsa/SDL_qsa_audio.c @@ -651,8 +651,8 @@ QSA_OpenDevice(_THIS, const char *devname, int iscapture) return 1; } -static int -QSA_DetectDevices(int iscapture) +static void +QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) { uint32_t it; uint32_t cards; @@ -667,7 +667,7 @@ QSA_DetectDevices(int iscapture) /* of available audio devices */ if (cards == 0) { /* We have no any available audio devices */ - return 0; + return; } /* Find requested devices by type */ @@ -702,6 +702,7 @@ QSA_DetectDevices(int iscapture) devices; status = snd_pcm_close(handle); if (status == EOK) { + addfn(qsa_playback_device[qsa_playback_devices].name); qsa_playback_devices++; } } else { @@ -757,6 +758,7 @@ QSA_DetectDevices(int iscapture) devices; status = snd_pcm_close(handle); if (status == EOK) { + addfn(qsa_capture_device[qsa_capture_devices].name); qsa_capture_devices++; } } else { @@ -782,31 +784,6 @@ QSA_DetectDevices(int iscapture) } } } - - /* Return amount of available playback or capture devices */ - if (!iscapture) { - return qsa_playback_devices; - } else { - return qsa_capture_devices; - } -} - -static const char * -QSA_GetDeviceName(int index, int iscapture) -{ - if (!iscapture) { - if (index >= qsa_playback_devices) { - return "No such playback device"; - } - - return qsa_playback_device[index].name; - } else { - if (index >= qsa_capture_devices) { - return "No such capture device"; - } - - return qsa_capture_device[index].name; - } } static void @@ -857,7 +834,6 @@ QSA_Init(SDL_AudioDriverImpl * impl) /* DeviceLock and DeviceUnlock functions are used default, */ /* provided by SDL, which uses pthread_mutex for lock/unlock */ impl->DetectDevices = QSA_DetectDevices; - impl->GetDeviceName = QSA_GetDeviceName; impl->OpenDevice = QSA_OpenDevice; impl->ThreadInit = QSA_ThreadInit; impl->WaitDevice = QSA_WaitDevice; diff --git a/src/audio/winmm/SDL_winmm.c b/src/audio/winmm/SDL_winmm.c index 4a2c30a4e..de73f7118 100644 --- a/src/audio/winmm/SDL_winmm.c +++ b/src/audio/winmm/SDL_winmm.c @@ -33,89 +33,33 @@ #include "win_ce_semaphore.h" #endif - -/* !!! FIXME: this is a cut and paste of SDL_FreeUnixAudioDevices(), - * !!! FIXME: which is more proof this needs to be managed in SDL_audio.c - * !!! FIXME: and not in drivers. - */ -static void -FreeWaveOutAudioDevices(char ***devices, int *devCount) -{ - int i = *devCount; - if ((i > 0) && (*devices != NULL)) { - while (i--) { - SDL_free((*devices)[i]); - } - } - - if (*devices != NULL) { - SDL_free(*devices); - } - - *devices = NULL; - *devCount = 0; -} - -static char **outputDevices = NULL; -static int outputDeviceCount = 0; -static char **inputDevices = NULL; -static int inputDeviceCount = 0; - -static int -DetectWaveOutDevices(void) -{ - UINT i; - const UINT devcount = waveOutGetNumDevs(); - WAVEOUTCAPS caps; - FreeWaveOutAudioDevices(&outputDevices, &outputDeviceCount); - outputDevices = (const char **) SDL_malloc(sizeof (char *) * devcount); - for (i = 0; i < devcount; i++) { - if (waveOutGetDevCaps(i, &caps, sizeof (caps)) == MMSYSERR_NOERROR) { - outputDevices[outputDeviceCount] = WIN_StringToUTF8(caps.szPname); - if (outputDevices[outputDeviceCount] != NULL) { - outputDeviceCount++; - } - } - } - return outputDeviceCount; +#define DETECT_DEV_IMPL(typ, capstyp) \ +static void DetectWave##typ##Devs(SDL_AddAudioDevice addfn) { \ + const UINT devcount = wave##typ##GetNumDevs(); \ + capstyp caps; \ + UINT i; \ + for (i = 0; i < devcount; i++) { \ + if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \ + char *name = WIN_StringToUTF8(caps.szPname); \ + if (name != NULL) { \ + addfn(name); \ + SDL_free(name); \ + } \ + } \ + } \ } -static int -DetectWaveInDevices(void) -{ - UINT i; - const UINT devcount = waveInGetNumDevs(); - WAVEINCAPS caps; - FreeWaveInAudioDevices(&inputDevices, &inputDeviceCount); - inputDevices = (const char **) SDL_malloc(sizeof (char *) * devcount); - for (i = 0; i < devcount; i++) { - if (waveInGetDevCaps(i, &caps, sizeof (caps)) == MMSYSERR_NOERROR) { - inputDevices[inputDeviceCount] = WIN_StringToUTF8(caps.szPname); - if (inputDevices[inputDeviceCount] != NULL) { - inputDeviceCount++; - } - } - } - return inputDeviceCount; -} +DETECT_DEV_IMPL(Out, WAVEOUTCAPS) +DETECT_DEV_IMPL(In, WAVEINCAPS) -static int -WINMM_DetectDevices(int iscapture) -{ - return (iscapture) ? DetectWaveInDevices() : DetectWaveOutDevices(); -} - -static const char * -WINMM_GetDeviceName(int index, int iscapture) +static void +WINMM_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) { - if ((iscapture) && (index < inputDeviceCount)) { - return inputDevices[index]; - } else if ((!iscapture) && (index < outputDeviceCount)) { - return outputDevices[index]; + if (iscapture) { + DetectWaveInDevs(addfn); + } else { + DetectWaveOutDevs(addfn); } - - SDL_SetError("No such device"); - return NULL; } static void CALLBACK @@ -448,7 +392,6 @@ WINMM_Init(SDL_AudioDriverImpl * impl) { /* Set the function pointers */ impl->DetectDevices = WINMM_DetectDevices; - impl->GetDeviceName = WINMM_GetDeviceName; impl->OpenDevice = WINMM_OpenDevice; impl->PlayDevice = WINMM_PlayDevice; impl->WaitDevice = WINMM_WaitDevice; diff --git a/src/audio/xaudio2/SDL_xaudio2.c b/src/audio/xaudio2/SDL_xaudio2.c index 4c769474a..b28169d12 100644 --- a/src/audio/xaudio2/SDL_xaudio2.c +++ b/src/audio/xaudio2/SDL_xaudio2.c @@ -24,35 +24,9 @@ #include "../SDL_audio_c.h" #include "SDL_assert.h" -#define INITGUID 1 +#define INITGUID 1 #include "SDL_xaudio2.h" -/* !!! FIXME: this is a cut and paste of SDL_FreeUnixAudioDevices(), - * !!! FIXME: which is more proof this needs to be managed in SDL_audio.c - * !!! FIXME: and not in drivers. - */ -static void -FreeXAudio2AudioDevices(char ***devices, int *devCount) -{ - int i = *devCount; - if ((i > 0) && (*devices != NULL)) { - while (i--) { - SDL_free((*devices)[i]); - } - } - - if (*devices != NULL) { - SDL_free(*devices); - } - - *devices = NULL; - *devCount = 0; -} - - -static char **outputDevices = NULL; -static int outputDeviceCount = 0; - static __inline__ char * utf16_to_utf8(const WCHAR *S) { @@ -61,59 +35,38 @@ utf16_to_utf8(const WCHAR *S) (SDL_wcslen(S)+1)*sizeof(WCHAR)); } -static int -XAUDIO2_DetectDevices(int iscapture) +static void +XAUDIO2_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) { IXAudio2 *ixa2 = NULL; UINT32 devcount = 0; UINT32 i = 0; void *ptr = NULL; - if (!iscapture) { - FreeXAudio2AudioDevices(&outputDevices, &outputDeviceCount); - } - if (iscapture) { SDL_SetError("XAudio2: capture devices unsupported."); - return 0; + return; } else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) { SDL_SetError("XAudio2: XAudio2Create() failed."); - return 0; + return; } else if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) { SDL_SetError("XAudio2: IXAudio2::GetDeviceCount() failed."); IXAudio2_Release(ixa2); - return 0; - } else if ((ptr = SDL_malloc(sizeof (char *) * devcount)) == NULL) { - SDL_OutOfMemory(); - IXAudio2_Release(ixa2); - return 0; + return; } - outputDevices = (char **) ptr; for (i = 0; i < devcount; i++) { XAUDIO2_DEVICE_DETAILS details; if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) { char *str = utf16_to_utf8(details.DisplayName); if (str != NULL) { - outputDevices[outputDeviceCount++] = str; + addfn(str); + SDL_free(str); /* addfn() made a copy of the string. */ } } } IXAudio2_Release(ixa2); - - return outputDeviceCount; -} - -static const char * -XAUDIO2_GetDeviceName(int index, int iscapture) -{ - if ((!iscapture) && (index < outputDeviceCount)) { - return outputDevices[index]; - } - - SDL_SetError("XAudio2: No such device"); - return NULL; } static void STDMETHODCALLTYPE @@ -436,7 +389,6 @@ XAUDIO2_Init(SDL_AudioDriverImpl * impl) /* Set the function pointers */ impl->DetectDevices = XAUDIO2_DetectDevices; - impl->GetDeviceName = XAUDIO2_GetDeviceName; impl->OpenDevice = XAUDIO2_OpenDevice; impl->PlayDevice = XAUDIO2_PlayDevice; impl->WaitDevice = XAUDIO2_WaitDevice;