Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Cleaned up audio device detection. Cleared out a lot of cut-and-paste.
  • Loading branch information
icculus committed Aug 4, 2011
1 parent 524c503 commit 5202ee8
Show file tree
Hide file tree
Showing 11 changed files with 217 additions and 545 deletions.
108 changes: 92 additions & 16 deletions src/audio/SDL_audio.c
Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand All @@ -660,7 +702,19 @@ SDL_GetNumAudioDevices(int iscapture)
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;
}


Expand All @@ -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)) {
Expand All @@ -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;
}


Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1121,6 +1193,10 @@ SDL_AudioQuit(void)

/* Free the driver data */
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(open_devices, '\0', sizeof(open_devices));
}
Expand Down
45 changes: 10 additions & 35 deletions src/audio/SDL_audiodev.c
Expand Up @@ -48,56 +48,31 @@

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)
{
return 1;
}

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];

Expand All @@ -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);
}
}
}
Expand Down
18 changes: 15 additions & 3 deletions src/audio/SDL_audiodev_c.h
Expand Up @@ -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: */
12 changes: 10 additions & 2 deletions src/audio/SDL_sysaudio.h
Expand Up @@ -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);
Expand Down Expand Up @@ -67,6 +69,12 @@ typedef struct SDL_AudioDriver
const char *desc;

SDL_AudioDriverImpl impl;

char **outputDevices;
int outputDeviceCount;

char **inputDevices;
int inputDeviceCount;
} SDL_AudioDriver;


Expand Down

0 comments on commit 5202ee8

Please sign in to comment.