Commit 8e6153c3 authored by Ryan C. Gordon's avatar Ryan C. Gordon

Cleaned up audio device detection. Cleared out a lot of cut-and-paste.

parent 46bb3d87
...@@ -151,10 +151,9 @@ get_audio_device(SDL_AudioDeviceID id) ...@@ -151,10 +151,9 @@ get_audio_device(SDL_AudioDeviceID id)
/* stubs for audio drivers that don't need a specific entry point... */ /* stubs for audio drivers that don't need a specific entry point... */
static int static void
SDL_AudioDetectDevices_Default(int iscapture) SDL_AudioDetectDevices_Default(int iscapture, SDL_AddAudioDevice addfn)
{ { /* no-op. */
return -1;
} }
static void static void
...@@ -199,13 +198,6 @@ SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture) ...@@ -199,13 +198,6 @@ SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
return 0; return 0;
} }
static const char *
SDL_AudioGetDeviceName_Default(int index, int iscapture)
{
SDL_SetError("No such device");
return NULL;
}
static void static void
SDL_AudioLockDevice_Default(SDL_AudioDevice * device) SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
{ {
...@@ -238,7 +230,6 @@ finalize_audio_entry_points(void) ...@@ -238,7 +230,6 @@ finalize_audio_entry_points(void)
current_audio.impl.x = SDL_Audio##x##_Default; \ current_audio.impl.x = SDL_Audio##x##_Default; \
} }
FILL_STUB(DetectDevices); FILL_STUB(DetectDevices);
FILL_STUB(GetDeviceName);
FILL_STUB(OpenDevice); FILL_STUB(OpenDevice);
FILL_STUB(ThreadInit); FILL_STUB(ThreadInit);
FILL_STUB(WaitDevice); FILL_STUB(WaitDevice);
...@@ -641,13 +632,64 @@ SDL_GetCurrentAudioDriver() ...@@ -641,13 +632,64 @@ SDL_GetCurrentAudioDriver()
return current_audio.name; 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 int
SDL_GetNumAudioDevices(int iscapture) SDL_GetNumAudioDevices(int iscapture)
{ {
int retval = 0;
if (!SDL_WasInit(SDL_INIT_AUDIO)) { if (!SDL_WasInit(SDL_INIT_AUDIO)) {
return -1; return -1;
} }
if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) { if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
return 0; return 0;
} }
...@@ -660,7 +702,19 @@ SDL_GetNumAudioDevices(int iscapture) ...@@ -660,7 +702,19 @@ SDL_GetNumAudioDevices(int iscapture)
return 1; return 1;
} }
return current_audio.impl.DetectDevices(iscapture); if (iscapture) {
free_device_list(&current_audio.inputDevices,
&current_audio.inputDeviceCount);
current_audio.impl.DetectDevices(iscapture, SDL_AddCaptureAudioDevice);
retval = current_audio.inputDeviceCount;
} else {
free_device_list(&current_audio.outputDevices,
&current_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) ...@@ -678,8 +732,7 @@ SDL_GetAudioDeviceName(int index, int iscapture)
} }
if (index < 0) { if (index < 0) {
SDL_SetError("No such device"); goto no_such_device;
return NULL;
} }
if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) { if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
...@@ -690,7 +743,21 @@ SDL_GetAudioDeviceName(int index, int iscapture) ...@@ -690,7 +743,21 @@ SDL_GetAudioDeviceName(int index, int iscapture)
return DEFAULT_OUTPUT_DEVNAME; 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, ...@@ -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)) { if (!current_audio.impl.OpenDevice(device, devname, iscapture)) {
close_audio_device(device); close_audio_device(device);
return 0; return 0;
...@@ -1121,6 +1193,10 @@ SDL_AudioQuit(void) ...@@ -1121,6 +1193,10 @@ SDL_AudioQuit(void)
/* Free the driver data */ /* Free the driver data */
current_audio.impl.Deinitialize(); current_audio.impl.Deinitialize();
free_device_list(&current_audio.outputDevices,
&current_audio.outputDeviceCount);
free_device_list(&current_audio.inputDevices,
&current_audio.inputDeviceCount);
SDL_memset(&current_audio, '\0', sizeof(current_audio)); SDL_memset(&current_audio, '\0', sizeof(current_audio));
SDL_memset(open_devices, '\0', sizeof(open_devices)); SDL_memset(open_devices, '\0', sizeof(open_devices));
} }
......
...@@ -48,46 +48,20 @@ ...@@ -48,46 +48,20 @@
static inline void static inline void
test_device(const char *fname, int flags, int (*test) (int fd), test_device(const char *fname, int flags, int (*test) (int fd),
char ***devices, int *devCount) SDL_AddAudioDevice addfn)
{ {
struct stat sb; struct stat sb;
if ((stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode))) { if ((stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode))) {
int audio_fd = open(fname, flags, 0); const int audio_fd = open(fname, flags, 0);
if ((audio_fd >= 0) && (test(audio_fd))) { if (audio_fd >= 0) {
void *p = if (test(audio_fd)) {
SDL_realloc(*devices, ((*devCount) + 1) * sizeof(char *)); addfn(fname);
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); 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 static int
test_stub(int fd) test_stub(int fd)
{ {
...@@ -95,9 +69,10 @@ test_stub(int fd) ...@@ -95,9 +69,10 @@ test_stub(int fd)
} }
void void
SDL_EnumUnixAudioDevices(int flags, int classic, int (*test) (int fd), SDL_EnumUnixAudioDevices(int iscapture, int classic, int (*test)(int fd),
char ***devices, int *devCount) SDL_AddAudioDevice addfn)
{ {
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
const char *audiodev; const char *audiodev;
char audiopath[1024]; char audiopath[1024];
...@@ -122,14 +97,14 @@ SDL_EnumUnixAudioDevices(int flags, int classic, int (*test) (int fd), ...@@ -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)) { if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) {
int instance = 0; int instance = 0;
while (instance++ <= 64) { while (instance++ <= 64) {
SDL_snprintf(audiopath, SDL_arraysize(audiopath), SDL_snprintf(audiopath, SDL_arraysize(audiopath),
"%s%d", audiodev, instance); "%s%d", audiodev, instance);
test_device(audiopath, flags, test, devices, devCount); test_device(audiopath, flags, test, addfn);
} }
} }
} }
......
...@@ -18,10 +18,22 @@ ...@@ -18,10 +18,22 @@
misrepresented as being the original software. misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.
*/ */
#include "SDL.h"
#include "SDL_config.h" #include "SDL_config.h"
#include "SDL_sysaudio.h"
void SDL_EnumUnixAudioDevices(int flags, int classic, int (*test) (int fd), /* Open the audio device for playback, and don't block if busy */
char ***devs, int *count); /* #define USE_BLOCKING_WRITES */
void SDL_FreeUnixAudioDevices(char ***devices, int *devCount);
#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: */ /* vi: set ts=4 sw=4 expandtab: */
...@@ -30,10 +30,12 @@ ...@@ -30,10 +30,12 @@
typedef struct SDL_AudioDevice SDL_AudioDevice; typedef struct SDL_AudioDevice SDL_AudioDevice;
#define _THIS SDL_AudioDevice *_this #define _THIS SDL_AudioDevice *_this
/* Used by audio targets during DetectDevices() */
typedef void (*SDL_AddAudioDevice)(const char *name);
typedef struct SDL_AudioDriverImpl typedef struct SDL_AudioDriverImpl
{ {
int (*DetectDevices) (int iscapture); void (*DetectDevices) (int iscapture, SDL_AddAudioDevice addfn);
const char *(*GetDeviceName) (int index, int iscapture);
int (*OpenDevice) (_THIS, const char *devname, int iscapture); int (*OpenDevice) (_THIS, const char *devname, int iscapture);
void (*ThreadInit) (_THIS); /* Called by audio thread at start */ void (*ThreadInit) (_THIS); /* Called by audio thread at start */
void (*WaitDevice) (_THIS); void (*WaitDevice) (_THIS);
...@@ -67,6 +69,12 @@ typedef struct SDL_AudioDriver ...@@ -67,6 +69,12 @@ typedef struct SDL_AudioDriver
const char *desc; const char *desc;
SDL_AudioDriverImpl impl; SDL_AudioDriverImpl impl;
char **outputDevices;
int outputDeviceCount;
char **inputDevices;
int inputDeviceCount;
} SDL_AudioDriver; } SDL_AudioDriver;
......
...@@ -50,91 +50,23 @@ ...@@ -50,91 +50,23 @@
#define BSD_AUDIO_DRIVER_DESC "Native OpenBSD audio" #define BSD_AUDIO_DRIVER_DESC "Native OpenBSD audio"
#endif #endif
/* Open the audio device for playback, and don't block if busy */
/* #define USE_BLOCKING_WRITES */
/* Use timer for synchronization */ /* Use timer for synchronization */
/* #define USE_TIMER_SYNC */ /* #define USE_TIMER_SYNC */
/* #define DEBUG_AUDIO */ /* #define DEBUG_AUDIO */
/* #define DEBUG_AUDIO_STREAM */ /* #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 static void
BSDAUDIO_Deinitialize(void) BSDAUDIO_Deinitialize(void)
{ {
free_device_lists();
} }
static int static void
BSDAUDIO_DetectDevices(int iscapture) BSDAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
{
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)
{ {
if ((iscapture) && (index < inputDeviceCount)) { SDL_EnumUnixAudioDevices(iscapture, 0, NULL, addfn);
return inputDevices[index];
} else if ((!iscapture) && (index < outputDeviceCount)) {
return outputDevices[index];
}
SDL_SetError("No such device");
return NULL;
} }
...@@ -318,12 +250,11 @@ BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) ...@@ -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. */ /* We don't care what the devname is...we'll try to open anything. */
/* ...but default to first name in the list... */ /* ...but default to first name in the list... */
if (devname == NULL) { if (devname == NULL) {
if (((iscapture) && (inputDeviceCount == 0)) || devname = SDL_GetAudioDeviceName(0, iscapture);
((!iscapture) && (outputDeviceCount == 0))) { if (devname == NULL) {
SDL_SetError("No such audio device"); SDL_SetError("No such audio device");
return 0; return 0;
} }
devname = ((iscapture) ? inputDevices[0] : outputDevices[0]);
} }
/* Initialize all variables that we clean on shutdown */ /* Initialize all variables that we clean on shutdown */
...@@ -434,7 +365,6 @@ BSDAUDIO_Init(SDL_AudioDriverImpl * impl) ...@@ -434,7 +365,6 @@ BSDAUDIO_Init(SDL_AudioDriverImpl * impl)
{ {
/* Set the function pointers */ /* Set the function pointers */
impl->DetectDevices = BSDAUDIO_DetectDevices; impl->DetectDevices = BSDAUDIO_DetectDevices;
impl->GetDeviceName = BSDAUDIO_GetDeviceName;
impl->OpenDevice = BSDAUDIO_OpenDevice; impl->OpenDevice = BSDAUDIO_OpenDevice;
impl->PlayDevice = BSDAUDIO_PlayDevice; impl->PlayDevice = BSDAUDIO_PlayDevice;
impl->WaitDevice = BSDAUDIO_WaitDevice; impl->WaitDevice = BSDAUDIO_WaitDevice;
...@@ -442,8 +372,6 @@ BSDAUDIO_Init(SDL_AudioDriverImpl * impl) ...@@ -442,8 +372,6 @@ BSDAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->CloseDevice = BSDAUDIO_CloseDevice; impl->CloseDevice = BSDAUDIO_CloseDevice;
impl->Deinitialize = BSDAUDIO_Deinitialize; impl->Deinitialize = BSDAUDIO_Deinitialize;
build_device_lists();
return 1; /* this audio target is available. */ return 1; /* this audio target is available. */
} }
......
...@@ -148,96 +148,28 @@ SetDSerror(const char *function, int code) ...@@ -148,96 +148,28 @@ SetDSerror(const char *function, int code)
} }
static BOOL CALLBACK
/* !!! FIXME: this is a cut and paste of SDL_FreeUnixAudioDevices(), FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data)
* !!! 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)
{ {
int i = *devCount; SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data;
if ((i > 0) && (*devices != NULL)) { if (guid != NULL) { /* skip default device */
while (i--) { char *str = utf16_to_utf8(desc);
SDL_free((*devices)[i]); 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. */ return TRUE; /* keep enumerating. */
} }
static char **outputDevices = NULL; static void
static int outputDeviceCount = 0; DSOUND_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
static char **inputDevices = NULL;
static int inputDeviceCount = 0;
static int
DSOUND_DetectDevices(int iscapture)
{ {
FindAllDevsData data;
data.devs = NULL;
data.devcount = 0;
if (iscapture) { if (iscapture) {
FreeDSoundAudioDevices(&inputDevices, &inputDeviceCount); pDirectSoundCaptureEnumerateW(FindAllDevs, addfn);
pDirectSoundCaptureEnumerateW(FindAllDevs, &devs);
inputDevices = data.devs;
inputDeviceCount = data.devcount;
} else { } else {
FreeDSoundAudioDevices(&outputDevices, &outputDeviceCount); pDirectSoundEnumerateW(FindAllDevs, addfn);
pDirectSoundEnumerateW(FindAllDevs, &devs);
outputDevices = data.devs;
outputDeviceCount = data.devcount;
} }
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) ...@@ -589,8 +521,6 @@ DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
static void static void
DSOUND_Deinitialize(void) DSOUND_Deinitialize(void)
{ {
FreeDSoundAudioDevices(&inputDevices, &inputDeviceCount);
FreeDSoundAudioDevices(&outputDevices, &outputDeviceCount);
DSOUND_Unload(); DSOUND_Unload();
} }
...@@ -604,7 +534,6 @@ DSOUND_Init(SDL_AudioDriverImpl * impl) ...@@ -604,7 +534,6 @@ DSOUND_Init(SDL_AudioDriverImpl * impl)
/* Set the function pointers */ /* Set the function pointers */
impl->DetectDevices = DSOUND_DetectDevices; impl->DetectDevices = DSOUND_DetectDevices;
impl->GetDeviceName = DSOUND_GetDeviceName;
impl->OpenDevice = DSOUND_OpenDevice; impl->OpenDevice = DSOUND_OpenDevice;
impl->PlayDevice = DSOUND_PlayDevice; impl->PlayDevice = DSOUND_PlayDevice;
impl->WaitDevice = DSOUND_WaitDevice; impl->WaitDevice = DSOUND_WaitDevice;
......
...@@ -50,77 +50,16 @@ ...@@ -50,77 +50,16 @@
/* The tag name used by DSP audio */ /* The tag name used by DSP audio */
#define DSP_DRIVER_NAME "dsp" #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 static void
DSP_Deinitialize(void) DSP_Deinitialize(void)
{ {
free_device_lists();
} }
static int static void
DSP_DetectDevices(int iscapture) DSP_DetectDevices(int iscapture)
{ {
if (iscapture) { SDL_EnumUnixAudioDevices(iscapture, 0, NULL);
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;
} }
...@@ -154,12 +93,11 @@ DSP_OpenDevice(_THIS, const char *devname, int iscapture) ...@@ -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. */ /* We don't care what the devname is...we'll try to open anything. */
/* ...but default to first name in the list... */ /* ...but default to first name in the list... */
if (devname == NULL) { if (devname == NULL) {
if (((iscapture) && (inputDeviceCount == 0)) || devname = SDL_GetAudioDeviceName(0, iscapture);
((!iscapture) && (outputDeviceCount == 0))) { if (devname == NULL) {
SDL_SetError("No such audio device"); SDL_SetError("No such audio device");
return 0; return 0;
} }
devname = ((iscapture) ? inputDevices[0] : outputDevices[0]);
} }
/* Make sure fragment size stays a power of 2, or OSS fails. */ /* Make sure fragment size stays a power of 2, or OSS fails. */
...@@ -369,15 +307,12 @@ DSP_Init(SDL_AudioDriverImpl * impl) ...@@ -369,15 +307,12 @@ DSP_Init(SDL_AudioDriverImpl * impl)
{ {
/* Set the function pointers */ /* Set the function pointers */
impl->DetectDevices = DSP_DetectDevices; impl->DetectDevices = DSP_DetectDevices;
impl->GetDeviceName = DSP_GetDeviceName;
impl->OpenDevice = DSP_OpenDevice; impl->OpenDevice = DSP_OpenDevice;
impl->PlayDevice = DSP_PlayDevice; impl->PlayDevice = DSP_PlayDevice;
impl->GetDeviceBuf = DSP_GetDeviceBuf; impl->GetDeviceBuf = DSP_GetDeviceBuf;
impl->CloseDevice = DSP_CloseDevice; impl->CloseDevice = DSP_CloseDevice;
impl->Deinitialize = DSP_Deinitialize; impl->Deinitialize = DSP_Deinitialize;
build_device_lists();
return 1; /* this audio target is available. */ return 1; /* this audio target is available. */
} }
......
...@@ -34,34 +34,36 @@ ...@@ -34,34 +34,36 @@
#define DEBUG_COREAUDIO 0 #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; SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data;
const char *name; addfn(name);
} COREAUDIO_DeviceList; }
static COREAUDIO_DeviceList *inputDevices = NULL; typedef struct
static int inputDeviceCount = 0; {
static COREAUDIO_DeviceList *outputDevices = NULL; const char *findname;
static int outputDeviceCount = 0; AudioDeviceID devId;
int found;
} FindDevIdData;
static void static void
free_device_list(COREAUDIO_DeviceList ** devices, int *devCount) findDevId(const char *name, AudioDeviceID devId, void *_data)
{ {
if (*devices) { FindDevIdData *data = (FindDevIdData *) _data;
int i = *devCount; if (!data->found) {
while (i--) if (SDL_strcmp(name, data->findname) == 0) {
SDL_free((void *) (*devices)[i].name); data->found = 1;
SDL_free(*devices); data->devId = devId;
*devices = NULL; }
} }
*devCount = 0;
} }
static void static void
build_device_list(int iscapture, COREAUDIO_DeviceList ** devices, build_device_list(int iscapture, addDevFn addfn, void *addfndata)
int *devCount)
{ {
Boolean outWritable = 0; Boolean outWritable = 0;
OSStatus result = noErr; OSStatus result = noErr;
...@@ -70,8 +72,6 @@ build_device_list(int iscapture, COREAUDIO_DeviceList ** devices, ...@@ -70,8 +72,6 @@ build_device_list(int iscapture, COREAUDIO_DeviceList ** devices,
UInt32 i = 0; UInt32 i = 0;
UInt32 max = 0; UInt32 max = 0;
free_device_list(devices, devCount);
result = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, result = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,
&size, &outWritable); &size, &outWritable);
...@@ -82,16 +82,12 @@ build_device_list(int iscapture, COREAUDIO_DeviceList ** devices, ...@@ -82,16 +82,12 @@ build_device_list(int iscapture, COREAUDIO_DeviceList ** devices,
if (devs == NULL) if (devs == NULL)
return; return;
max = size / sizeof(AudioDeviceID);
*devices = (COREAUDIO_DeviceList *) SDL_malloc(max * sizeof(**devices));
if (*devices == NULL)
return;
result = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, result = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
&size, devs); &size, devs);
if (result != kAudioHardwareNoError) if (result != kAudioHardwareNoError)
return; return;
max = size / sizeof (AudioDeviceID);
for (i = 0; i < max; i++) { for (i = 0; i < max; i++) {
CFStringRef cfstr = NULL; CFStringRef cfstr = NULL;
char *ptr = NULL; char *ptr = NULL;
...@@ -156,9 +152,7 @@ build_device_list(int iscapture, COREAUDIO_DeviceList ** devices, ...@@ -156,9 +152,7 @@ build_device_list(int iscapture, COREAUDIO_DeviceList ** devices,
usable = (len > 0); usable = (len > 0);
} }
if (!usable) { if (usable) {
SDL_free(ptr);
} else {
ptr[len] = '\0'; ptr[len] = '\0';
#if DEBUG_COREAUDIO #if DEBUG_COREAUDIO
...@@ -166,80 +160,22 @@ build_device_list(int iscapture, COREAUDIO_DeviceList ** devices, ...@@ -166,80 +160,22 @@ build_device_list(int iscapture, COREAUDIO_DeviceList ** devices,
((iscapture) ? "capture" : "output"), ((iscapture) ? "capture" : "output"),
(int) *devCount, ptr, (int) dev); (int) *devCount, ptr, (int) dev);
#endif #endif
addfn(ptr, dev, addfndata);
(*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;
} }
devs++; SDL_free(ptr); /* addfn() would have copied the string. */
}
return 0;
}
static int
COREAUDIO_DetectDevices(int iscapture)
{
if (iscapture) {
build_device_list(1, &inputDevices, &inputDeviceCount);
return inputDeviceCount;
} else {
build_device_list(0, &outputDevices, &outputDeviceCount);
return outputDeviceCount;
} }
return 0; /* shouldn't ever hit this. */
} }
static void
static const char * COREAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
COREAUDIO_GetDeviceName(int index, int iscapture)
{ {
if ((iscapture) && (index < inputDeviceCount)) { build_device_list(iscapture, addToDevList, addfn);
return inputDevices[index].name;
} else if ((!iscapture) && (index < outputDeviceCount)) {
return outputDevices[index].name;
}
SDL_SetError("No such device");
return NULL;
} }
static void static void
COREAUDIO_Deinitialize(void) COREAUDIO_Deinitialize(void)
{ {
free_device_lists();
} }
...@@ -378,10 +314,15 @@ find_device_by_name(_THIS, const char *devname, int iscapture) ...@@ -378,10 +314,15 @@ find_device_by_name(_THIS, const char *devname, int iscapture)
result = AudioHardwareGetProperty(propid, &size, &devid); result = AudioHardwareGetProperty(propid, &size, &devid);
CHECK_RESULT("AudioHardwareGetProperty (default device)"); CHECK_RESULT("AudioHardwareGetProperty (default device)");
} else { } 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."); SDL_SetError("CoreAudio: No such audio device.");
return 0; return 0;
} }
devid = data.devId;
} }
size = sizeof(alive); size = sizeof(alive);
...@@ -565,14 +506,11 @@ COREAUDIO_Init(SDL_AudioDriverImpl * impl) ...@@ -565,14 +506,11 @@ COREAUDIO_Init(SDL_AudioDriverImpl * impl)
{ {
/* Set the function pointers */ /* Set the function pointers */
impl->DetectDevices = COREAUDIO_DetectDevices; impl->DetectDevices = COREAUDIO_DetectDevices;
impl->GetDeviceName = COREAUDIO_GetDeviceName;
impl->OpenDevice = COREAUDIO_OpenDevice; impl->OpenDevice = COREAUDIO_OpenDevice;
impl->CloseDevice = COREAUDIO_CloseDevice; impl->CloseDevice = COREAUDIO_CloseDevice;
impl->Deinitialize = COREAUDIO_Deinitialize; impl->Deinitialize = COREAUDIO_Deinitialize;
impl->ProvidesOwnCallbackThread = 1; impl->ProvidesOwnCallbackThread = 1;
build_device_lists(); /* do an initial check for devices... */
return 1; /* this audio target is available. */ return 1; /* this audio target is available. */
} }
......
...@@ -651,8 +651,8 @@ QSA_OpenDevice(_THIS, const char *devname, int iscapture) ...@@ -651,8 +651,8 @@ QSA_OpenDevice(_THIS, const char *devname, int iscapture)
return 1; return 1;
} }
static int static void
QSA_DetectDevices(int iscapture) QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
{ {
uint32_t it; uint32_t it;
uint32_t cards; uint32_t cards;
...@@ -667,7 +667,7 @@ QSA_DetectDevices(int iscapture) ...@@ -667,7 +667,7 @@ QSA_DetectDevices(int iscapture)
/* of available audio devices */ /* of available audio devices */
if (cards == 0) { if (cards == 0) {
/* We have no any available audio devices */ /* We have no any available audio devices */
return 0; return;
} }
/* Find requested devices by type */ /* Find requested devices by type */
...@@ -702,6 +702,7 @@ QSA_DetectDevices(int iscapture) ...@@ -702,6 +702,7 @@ QSA_DetectDevices(int iscapture)
devices; devices;
status = snd_pcm_close(handle); status = snd_pcm_close(handle);
if (status == EOK) { if (status == EOK) {
addfn(qsa_playback_device[qsa_playback_devices].name);
qsa_playback_devices++; qsa_playback_devices++;
} }
} else { } else {
...@@ -757,6 +758,7 @@ QSA_DetectDevices(int iscapture) ...@@ -757,6 +758,7 @@ QSA_DetectDevices(int iscapture)
devices; devices;
status = snd_pcm_close(handle); status = snd_pcm_close(handle);
if (status == EOK) { if (status == EOK) {
addfn(qsa_capture_device[qsa_capture_devices].name);
qsa_capture_devices++; qsa_capture_devices++;
} }
} else { } else {
...@@ -782,31 +784,6 @@ QSA_DetectDevices(int iscapture) ...@@ -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 static void
...@@ -857,7 +834,6 @@ QSA_Init(SDL_AudioDriverImpl * impl) ...@@ -857,7 +834,6 @@ QSA_Init(SDL_AudioDriverImpl * impl)
/* DeviceLock and DeviceUnlock functions are used default, */ /* DeviceLock and DeviceUnlock functions are used default, */
/* provided by SDL, which uses pthread_mutex for lock/unlock */ /* provided by SDL, which uses pthread_mutex for lock/unlock */
impl->DetectDevices = QSA_DetectDevices; impl->DetectDevices = QSA_DetectDevices;
impl->GetDeviceName = QSA_GetDeviceName;
impl->OpenDevice = QSA_OpenDevice; impl->OpenDevice = QSA_OpenDevice;
impl->ThreadInit = QSA_ThreadInit; impl->ThreadInit = QSA_ThreadInit;
impl->WaitDevice = QSA_WaitDevice; impl->WaitDevice = QSA_WaitDevice;
......
...@@ -33,89 +33,33 @@ ...@@ -33,89 +33,33 @@
#include "win_ce_semaphore.h" #include "win_ce_semaphore.h"
#endif #endif
#define DETECT_DEV_IMPL(typ, capstyp) \
/* !!! FIXME: this is a cut and paste of SDL_FreeUnixAudioDevices(), static void DetectWave##typ##Devs(SDL_AddAudioDevice addfn) { \
* !!! FIXME: which is more proof this needs to be managed in SDL_audio.c const UINT devcount = wave##typ##GetNumDevs(); \
* !!! FIXME: and not in drivers. capstyp caps; \
*/ UINT i; \
static void for (i = 0; i < devcount; i++) { \
FreeWaveOutAudioDevices(char ***devices, int *devCount) if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
{ char *name = WIN_StringToUTF8(caps.szPname); \
int i = *devCount; if (name != NULL) { \
if ((i > 0) && (*devices != NULL)) { addfn(name); \
while (i--) { SDL_free(name); \
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;
} }
static int DETECT_DEV_IMPL(Out, WAVEOUTCAPS)
DetectWaveInDevices(void) DETECT_DEV_IMPL(In, WAVEINCAPS)
{
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;
}
static int static void
WINMM_DetectDevices(int iscapture) WINMM_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
{
return (iscapture) ? DetectWaveInDevices() : DetectWaveOutDevices();
}
static const char *
WINMM_GetDeviceName(int index, int iscapture)
{ {
if ((iscapture) && (index < inputDeviceCount)) { if (iscapture) {
return inputDevices[index]; DetectWaveInDevs(addfn);
} else if ((!iscapture) && (index < outputDeviceCount)) { } else {
return outputDevices[index]; DetectWaveOutDevs(addfn);
} }
SDL_SetError("No such device");
return NULL;
} }
static void CALLBACK static void CALLBACK
...@@ -448,7 +392,6 @@ WINMM_Init(SDL_AudioDriverImpl * impl) ...@@ -448,7 +392,6 @@ WINMM_Init(SDL_AudioDriverImpl * impl)
{ {
/* Set the function pointers */ /* Set the function pointers */
impl->DetectDevices = WINMM_DetectDevices; impl->DetectDevices = WINMM_DetectDevices;
impl->GetDeviceName = WINMM_GetDeviceName;
impl->OpenDevice = WINMM_OpenDevice; impl->OpenDevice = WINMM_OpenDevice;
impl->PlayDevice = WINMM_PlayDevice; impl->PlayDevice = WINMM_PlayDevice;
impl->WaitDevice = WINMM_WaitDevice; impl->WaitDevice = WINMM_WaitDevice;
......
...@@ -24,35 +24,9 @@ ...@@ -24,35 +24,9 @@
#include "../SDL_audio_c.h" #include "../SDL_audio_c.h"
#include "SDL_assert.h" #include "SDL_assert.h"
#define INITGUID 1 #define INITGUID 1
#include "SDL_xaudio2.h" #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 * static __inline__ char *
utf16_to_utf8(const WCHAR *S) utf16_to_utf8(const WCHAR *S)
{ {
...@@ -61,59 +35,38 @@ utf16_to_utf8(const WCHAR *S) ...@@ -61,59 +35,38 @@ utf16_to_utf8(const WCHAR *S)
(SDL_wcslen(S)+1)*sizeof(WCHAR)); (SDL_wcslen(S)+1)*sizeof(WCHAR));
} }
static int static void
XAUDIO2_DetectDevices(int iscapture) XAUDIO2_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
{ {
IXAudio2 *ixa2 = NULL; IXAudio2 *ixa2 = NULL;
UINT32 devcount = 0; UINT32 devcount = 0;
UINT32 i = 0; UINT32 i = 0;
void *ptr = NULL; void *ptr = NULL;
if (!iscapture) {
FreeXAudio2AudioDevices(&outputDevices, &outputDeviceCount);
}
if (iscapture) { if (iscapture) {
SDL_SetError("XAudio2: capture devices unsupported."); SDL_SetError("XAudio2: capture devices unsupported.");
return 0; return;
} else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) { } else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
SDL_SetError("XAudio2: XAudio2Create() failed."); SDL_SetError("XAudio2: XAudio2Create() failed.");
return 0; return;
} else if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) { } else if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) {
SDL_SetError("XAudio2: IXAudio2::GetDeviceCount() failed."); SDL_SetError("XAudio2: IXAudio2::GetDeviceCount() failed.");
IXAudio2_Release(ixa2); IXAudio2_Release(ixa2);
return 0; return;
} else if ((ptr = SDL_malloc(sizeof (char *) * devcount)) == NULL) {
SDL_OutOfMemory();
IXAudio2_Release(ixa2);
return 0;
} }
outputDevices = (char **) ptr;
for (i = 0; i < devcount; i++) { for (i = 0; i < devcount; i++) {
XAUDIO2_DEVICE_DETAILS details; XAUDIO2_DEVICE_DETAILS details;
if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) { if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) {
char *str = utf16_to_utf8(details.DisplayName); char *str = utf16_to_utf8(details.DisplayName);
if (str != NULL) { if (str != NULL) {
outputDevices[outputDeviceCount++] = str; addfn(str);
SDL_free(str); /* addfn() made a copy of the string. */
} }
} }
} }
IXAudio2_Release(ixa2); 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 static void STDMETHODCALLTYPE
...@@ -436,7 +389,6 @@ XAUDIO2_Init(SDL_AudioDriverImpl * impl) ...@@ -436,7 +389,6 @@ XAUDIO2_Init(SDL_AudioDriverImpl * impl)
/* Set the function pointers */ /* Set the function pointers */
impl->DetectDevices = XAUDIO2_DetectDevices; impl->DetectDevices = XAUDIO2_DetectDevices;
impl->GetDeviceName = XAUDIO2_GetDeviceName;
impl->OpenDevice = XAUDIO2_OpenDevice; impl->OpenDevice = XAUDIO2_OpenDevice;
impl->PlayDevice = XAUDIO2_PlayDevice; impl->PlayDevice = XAUDIO2_PlayDevice;
impl->WaitDevice = XAUDIO2_WaitDevice; impl->WaitDevice = XAUDIO2_WaitDevice;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment