summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan C. Gordon <icculus@icculus.org>2006-10-04 06:00:10 +0000
committerRyan C. Gordon <icculus@icculus.org>2006-10-04 06:00:10 +0000
commite2ad8f5a1d1d2f183def93149c4f3e04df1278ef (patch)
treeb9d9bce5b07774cf147a6ae83233b09ccb70695f
parent7277c4d115f40e9e896226c30f53294ee361d734 (diff)
downloadsdl-e2ad8f5a1d1d2f183def93149c4f3e04df1278ef.tar.gz
More 1.3 audio work...moved dsp and dma drivers over to new model. Untested!
-rw-r--r--src/audio/SDL_audio.c14
-rw-r--r--src/audio/SDL_sysaudio.h1
-rw-r--r--src/audio/dma/SDL_dmaaudio.c397
-rw-r--r--src/audio/dsp/SDL_dspaudio.c266
-rw-r--r--src/audio/dsp/SDL_dspaudio.h11
-rw-r--r--src/audio/macosx/SDL_coreaudio.c10
-rw-r--r--test/testaudioinfo.c9
7 files changed, 377 insertions, 331 deletions
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index 62e2a1ed7..d7e497f78 100644
--- a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -132,6 +132,16 @@ static SDL_AudioDevice *get_audio_device(SDL_AudioDeviceID id)
}
+/* stubs for audio drivers that don't need a specific entry point... */
+/* !!! FIXME: fill in more of these. */
+
+static void SDL_DeinitializeAudio_Default(void)
+{
+ /* no-op. */
+}
+
+
+
/* The general mixing thread function */
int SDLCALL
SDL_RunAudio(void *devicep)
@@ -443,6 +453,10 @@ SDL_AudioInit(const char *driver_name)
current_audio.impl.UnlockDevice = SDL_UnlockDevice_Default;
}
+ if (!current_audio.impl.Deinitialize) {
+ current_audio.impl.Deinitialize = SDL_DeinitializeAudio_Default;
+ }
+
return (0);
}
diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h
index 0d006328a..bed2bd261 100644
--- a/src/audio/SDL_sysaudio.h
+++ b/src/audio/SDL_sysaudio.h
@@ -47,6 +47,7 @@ typedef struct SDL_AudioDriverImpl
void (*Deinitialize) (void);
} SDL_AudioDriverImpl;
+
typedef struct SDL_AudioDriver
{
/* * * */
diff --git a/src/audio/dma/SDL_dmaaudio.c b/src/audio/dma/SDL_dmaaudio.c
index f1d08cc03..272155f2e 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 <stdio.h>
@@ -60,17 +62,23 @@
#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);
+static int DMA_DetectDevices(int iscapture);
+static const char *DMA_GetDeviceName(int index, int iscapture);
+static int DMA_OpenDevice(_THIS, const char *devname, int iscapture);
+static void DMA_WaitDevice(_THIS);
+static void DMA_PlayDevice(_THIS);
+static Uint8 *DMA_GetDeviceBuf(_THIS);
+static void DMA_CloseDevice(_THIS);
/* Audio driver bootstrap functions */
static int
-Audio_Available(void)
+DMA_Available(void)
{
+ /*
+ * !!! FIXME: maybe change this to always available, and move this to
+ * !!! FIXME: to device enumeration and opening?
+ */
int available;
int fd;
@@ -91,174 +99,45 @@ Audio_Available(void)
return (available);
}
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
- SDL_free(device->hidden);
- SDL_free(device);
-}
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
+static int
+DMA_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));
- 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;
+ 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;
+
+ return 1;
}
AudioBootStrap DMA_bootstrap = {
DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio",
- Audio_Available, Audio_CreateDevice
+ DMA_Available, DMA_Init
};
-/* This function waits until it is possible to write a full sound buffer */
-static void
-DMA_WaitAudio(_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_PlayAudio(_THIS)
+static int
+DMA_DetectDevices(int iscapture)
{
- /* If timer synchronization is enabled, set the next write frame */
- if (frame_ticks) {
- next_frame += frame_ticks;
- }
- return;
+ return -1; /* !!! FIXME */
}
-static Uint8 *
-DMA_GetAudioBuf(_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 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;
- }
+ SDL_SetError("No such device"); /* !!! FIXME */
+ 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 +151,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 +174,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,19 +182,21 @@ 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 int
-DMA_OpenAudio(_THIS, SDL_AudioSpec * spec)
+open_device_internal(_THIS, const char *devname, int iscapture)
{
char audiodev[1024];
int format;
@@ -324,14 +205,23 @@ DMA_OpenAudio(_THIS, SDL_AudioSpec * spec)
SDL_AudioFormat test_format;
struct audio_buf_info info;
- /* 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));
+
+ /* !!! FIXME: handle devname */
+ /* !!! FIXME: handle iscapture */
/* 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);
+ return 0;
}
dma_buf = NULL;
ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
@@ -339,12 +229,12 @@ DMA_OpenAudio(_THIS, SDL_AudioSpec * spec)
/* Get a list of supported hardware formats */
if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
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);
@@ -390,60 +280,60 @@ DMA_OpenAudio(_THIS, SDL_AudioSpec * spec)
}
if (format == 0) {
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)) {
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, audiodev, format, stereo) < 0) {
/* Error is set by DMA_ReopenAudio() */
- return (-1);
+ return 0;
}
/* Memory map the audio buffer */
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
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) {
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;
}
}
@@ -454,14 +344,149 @@ DMA_OpenAudio(_THIS, SDL_AudioSpec * spec)
value = PCM_ENABLE_OUTPUT;
if (ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value) < 0) {
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;
+}
+
+static int
+DMA_OpenDevice(_THIS, const char *devname, int iscapture)
+{
+ int retval = open_device_internal(this, devname, iscapture);
+ if (!retval)
+ DMA_CloseDevice(this); /* !!! FIXME: do this at higher level. */
+ return retval;
+}
+
+
+
+
+/* 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 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;
+ }
}
/* 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..017b8b2c0 100644
--- a/src/audio/dsp/SDL_dspaudio.c
+++ b/src/audio/dsp/SDL_dspaudio.c
@@ -58,22 +58,25 @@
#define OPEN_FLAGS (O_WRONLY|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 int DSP_DetectDevices(int iscapture);
+static const char *DSP_GetDeviceName(int index, int iscapture);
+static int DSP_OpenDevice(_THIS, const char *devname, int iscapture);
+static void DSP_WaitDevice(_THIS);
+static void DSP_PlayDevice(_THIS);
+static Uint8 *DSP_GetDeviceBuf(_THIS);
+static void DSP_CloseDevice(_THIS);
/* Audio driver bootstrap functions */
static int
-Audio_Available(void)
+DSP_Available(void)
{
- int fd;
- int available;
-
- available = 0;
- fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
+ /*
+ * !!! FIXME: maybe change this to always available, and move this to
+ * !!! FIXME: to device enumeration and opening?
+ */
+ int fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
+ int available = 0;
if (fd >= 0) {
available = 1;
close(fd);
@@ -81,130 +84,97 @@ Audio_Available(void)
return (available);
}
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
- SDL_free(device->hidden);
- SDL_free(device);
-}
-static SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
+static int
+DSP_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));
- 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;
-
- this->free = Audio_DeleteDevice;
-
- return this;
+ impl->DetectDevices = DSP_DetectDevices;
+ impl->GetDeviceName = DSP_GetDeviceName;
+ impl->OpenDevice = DSP_OpenDevice;
+ impl->WaitDevice = DSP_WaitDevice;
+ impl->PlayDevice = DSP_PlayDevice;
+ impl->GetDeviceBuf = DSP_GetDeviceBuf;
+ impl->CloseDevice = DSP_CloseDevice;
+
+ return 1;
}
+
AudioBootStrap DSP_bootstrap = {
DSP_DRIVER_NAME, "OSS /dev/dsp standard audio",
- Audio_Available, Audio_CreateDevice
+ DSP_Available, DSP_Init
};
-/* This function waits until it is possible to write a full sound buffer */
-static void
-DSP_WaitAudio(_THIS)
-{
- /* Not needed at all since OSS handles waiting automagically */
-}
-static void
-DSP_PlayAudio(_THIS)
+static int
+DSP_DetectDevices(int iscapture)
{
- if (write(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
+ return -1; /* !!! FIXME */
}
-static Uint8 *
-DSP_GetAudioBuf(_THIS)
-{
- return (mixbuf);
-}
-static void
-DSP_CloseAudio(_THIS)
+static const char *
+DSP_GetDeviceName(int index, int iscapture)
{
- if (mixbuf != NULL) {
- SDL_FreeAudioMem(mixbuf);
- mixbuf = NULL;
- }
- if (audio_fd >= 0) {
- close(audio_fd);
- audio_fd = -1;
- }
+ SDL_SetError("No such device"); /* !!! FIXME */
+ return NULL;
}
+
static int
-DSP_OpenAudio(_THIS, SDL_AudioSpec * spec)
+DSP_OpenDevice(_THIS, const char *devname, int iscapture)
{
- char audiodev[1024];
+ char dev[1024];
int format;
int value;
int frag_spec;
SDL_AudioFormat test_format;
+ /* 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;
+
+ /* !!! FIXME: handle devname */
+ /* !!! FIXME: handle iscapture */
+
/* 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 = SDL_OpenAudioPath(dev, sizeof(dev), OPEN_FLAGS, 0);
+ if (this->hidden->audio_fd < 0) {
+ SDL_SetError("Couldn't open %s: %s", dev, 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 = fcntl(this->hidden->audio_fd, F_GETFL);
flags &= ~O_NONBLOCK;
- if (fcntl(audio_fd, F_SETFL, flags) < 0) {
+ if (fcntl(this->hidden->audio_fd, F_SETFL, flags) < 0) {
SDL_SetError("Couldn't set audio blocking mode");
- DSP_CloseAudio(this);
- return (-1);
+ DSP_CloseDevice(this);
+ 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");
SDL_SetError("Couldn't get audio format list");
- DSP_CloseAudio(this);
- return (-1);
+ DSP_CloseDevice(this);
+ 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);
@@ -256,49 +226,50 @@ DSP_OpenAudio(_THIS, SDL_AudioSpec * spec)
}
if (format == 0) {
SDL_SetError("Couldn't find any hardware audio formats");
- DSP_CloseAudio(this);
- return (-1);
+ DSP_CloseDevice(this);
+ 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");
SDL_SetError("Couldn't set audio format");
- DSP_CloseAudio(this);
- return (-1);
+ DSP_CloseDevice(this);
+ 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");
SDL_SetError("Cannot set the number of channels");
- DSP_CloseAudio(this);
- return (-1);
+ DSP_CloseDevice(this);
+ 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");
SDL_SetError("Couldn't set audio frequency");
- DSP_CloseAudio(this);
- return (-1);
+ DSP_CloseDevice(this);
+ 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) {
SDL_SetError("Fragment size must be a power of two");
- DSP_CloseAudio(this);
- return (-1);
+ DSP_CloseDevice(this);
+ return 0;
}
frag_spec |= 0x00020000; /* two fragments, for low latency */
@@ -307,13 +278,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 +293,62 @@ 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);
+ 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;
+}
+
+
+/* This function waits until it is possible to write a full sound buffer */
+static void
+DSP_WaitDevice(_THIS)
+{
+ /* Not needed at all since OSS handles waiting automagically */
+}
+
+
+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 void
+DSP_CloseDevice(_THIS)
+{
+ 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;
+ }
}
/* 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..bf71c12a0 100644
--- a/src/audio/dsp/SDL_dspaudio.h
+++ b/src/audio/dsp/SDL_dspaudio.h
@@ -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/macosx/SDL_coreaudio.c b/src/audio/macosx/SDL_coreaudio.c
index 4cb385e2d..df858bab1 100644
--- a/src/audio/macosx/SDL_coreaudio.c
+++ b/src/audio/macosx/SDL_coreaudio.c
@@ -356,25 +356,25 @@ inputCallback(void *inRefCon,
/* Dummy functions -- we don't use thread-based audio */
-void
+static void
COREAUDIO_WaitDevice(_THIS)
{
return;
}
-void
+static void
COREAUDIO_PlayDevice(_THIS)
{
return;
}
-Uint8 *
+static Uint8 *
COREAUDIO_GetDeviceBuf(_THIS)
{
return (NULL);
}
-void
+static void
COREAUDIO_CloseDevice(_THIS)
{
if (this->hidden != NULL) {
@@ -555,7 +555,7 @@ prepare_audiounit(_THIS, const char *devname, int iscapture,
}
-int
+static int
COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
{
AudioStreamBasicDescription strdesc;
diff --git a/test/testaudioinfo.c b/test/testaudioinfo.c
index 83b991cda..4c4eee1a8 100644
--- a/test/testaudioinfo.c
+++ b/test/testaudioinfo.c
@@ -5,12 +5,15 @@ static void print_devices(int iscapture)
const char *typestr = ((iscapture) ? "capture" : "output");
int n = SDL_GetNumAudioDevices(iscapture);
- if (n == 0)
- printf("No %s devices.\n\n", typestr);
+ 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;
- printf("%s devices:\n", typestr);
for (i = 0; i < n; i++) {
printf(" %s\n", SDL_GetAudioDeviceName(i, iscapture));
}