Mercurial > sdl-ios-xcode
diff src/audio/dsp/SDL_dspaudio.c @ 3795:589bc3d060cd SDL-ryan-multiple-audio-device
More 1.3 audio work...moved dsp and dma drivers over to new model. Untested!
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Wed, 04 Oct 2006 06:00:10 +0000 |
parents | 3b4ce57c6215 |
children | c8b3d3d13ed1 |
line wrap: on
line diff
--- a/src/audio/dsp/SDL_dspaudio.c Tue Oct 03 23:45:36 2006 +0000 +++ b/src/audio/dsp/SDL_dspaudio.c Wed Oct 04 06:00:10 2006 +0000 @@ -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 @@ return (available); } -static void -Audio_DeleteDevice(SDL_AudioDevice * device) + +static int +DSP_Init(SDL_AudioDriverImpl *impl) { - SDL_free(device->hidden); - SDL_free(device); + /* Set the function pointers */ + 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; } -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (this) { - SDL_memset(this, 0, (sizeof *this)); - this->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *this->hidden)); - } - if ((this == NULL) || (this->hidden == NULL)) { - SDL_OutOfMemory(); - if (this) { - SDL_free(this); - } - return (0); - } - SDL_memset(this->hidden, 0, (sizeof *this->hidden)); - 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; -} 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) + +static int +DSP_DetectDevices(int iscapture) { - /* Not needed at all since OSS handles waiting automagically */ -} - -static void -DSP_PlayAudio(_THIS) -{ - 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) + +static const char * +DSP_GetDeviceName(int index, int iscapture) { - return (mixbuf); + SDL_SetError("No such device"); /* !!! FIXME */ + return NULL; } -static void -DSP_CloseAudio(_THIS) -{ - if (mixbuf != NULL) { - SDL_FreeAudioMem(mixbuf); - mixbuf = NULL; - } - if (audio_fd >= 0) { - close(audio_fd); - audio_fd = -1; - } -} 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 @@ } 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 @@ 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 @@ #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: */