Mercurial > sdl-ios-xcode
diff src/audio/esd/SDL_esdaudio.c @ 3815:3234d6eee011 SDL-ryan-multiple-audio-device
Updated esd audio driver for 1.3 API.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Fri, 06 Oct 2006 04:16:11 +0000 |
parents | 7852b5b78af5 |
children | 9d070c1a45fa |
line wrap: on
line diff
--- a/src/audio/esd/SDL_esdaudio.c Fri Oct 06 03:40:57 2006 +0000 +++ b/src/audio/esd/SDL_esdaudio.c Fri Oct 06 04:16:11 2006 +0000 @@ -46,39 +46,40 @@ #define ESD_DRIVER_NAME "esd" /* Audio driver functions */ -static int ESD_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void ESD_WaitAudio(_THIS); -static void ESD_PlayAudio(_THIS); -static Uint8 *ESD_GetAudioBuf(_THIS); -static void ESD_CloseAudio(_THIS); +static int ESD_OpenDevice(_THIS, const char *devname, int iscapture); +static void ESD_WaitDevice(_THIS); +static void ESD_PlayDevice(_THIS); +static Uint8 *ESD_GetDeviceBuf(_THIS); +static void ESD_CloseDevice(_THIS); #ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC static const char *esd_library = SDL_AUDIO_DRIVER_ESD_DYNAMIC; static void *esd_handle = NULL; -static int esd_loaded = 0; static int (*SDL_NAME(esd_open_sound)) (const char *host); static int (*SDL_NAME(esd_close)) (int esd); static int (*SDL_NAME(esd_play_stream)) (esd_format_t format, int rate, const char *host, const char *name); + +#define SDL_ESD_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) } static struct { const char *name; void **func; } esd_functions[] = { - { - "esd_open_sound", (void **) &SDL_NAME(esd_open_sound)}, { - "esd_close", (void **) &SDL_NAME(esd_close)}, { -"esd_play_stream", (void **) &SDL_NAME(esd_play_stream)},}; + SDL_ESD_SYM(esd_open_sound), + SDL_ESD_SYM(esd_close), + SDL_ESD_SYM(esd_play_stream), +}; +#undef SDL_ESD_SYM static void UnloadESDLibrary() { - if (esd_loaded) { + if (esd_handle != NULL) { SDL_UnloadObject(esd_handle); esd_handle = NULL; - esd_loaded = 0; } } @@ -87,17 +88,18 @@ { int i, retval = -1; - esd_handle = SDL_LoadObject(esd_library); - if (esd_handle) { - esd_loaded = 1; - retval = 0; - for (i = 0; i < SDL_arraysize(esd_functions); ++i) { - *esd_functions[i].func = - SDL_LoadFunction(esd_handle, esd_functions[i].name); - if (!*esd_functions[i].func) { - retval = -1; - UnloadESDLibrary(); - break; + if (esd_handle == NULL) { + esd_handle = SDL_LoadObject(esd_library); + if (esd_handle) { + retval = 0; + for (i = 0; i < SDL_arraysize(esd_functions); ++i) { + *esd_functions[i].func = + SDL_LoadFunction(esd_handle, esd_functions[i].name); + if (!*esd_functions[i].func) { + retval = -1; + UnloadESDLibrary(); + break; + } } } } @@ -123,79 +125,48 @@ /* Audio driver bootstrap functions */ static int -Audio_Available(void) +ESD_Available(void) { - const char *esd_no_spawn = SDL_getenv("ESD_NO_SPAWN"); - int connection = 0; int available = 0; - - if (esd_no_spawn == NULL) { - SDL_putenv("ESD_NO_SPAWN=1"); /* Don't start ESD if it's not running */ + if (LoadESDLibrary() == 0) { + int connection; + if (SDL_getenv("ESD_NO_SPAWN") == NULL) { + SDL_putenv("ESD_NO_SPAWN=1"); /* Don't start ESD if it's not running */ + } + connection = SDL_NAME(esd_open_sound) (NULL); + if (connection >= 0) { + available = 1; + SDL_NAME(esd_close) (connection); + } + UnloadESDLibrary(); } - - if (LoadESDLibrary() < 0) { - return available; - } - connection = SDL_NAME(esd_open_sound) (NULL); - if (connection >= 0) { - available = 1; - SDL_NAME(esd_close) (connection); - } - UnloadESDLibrary(); return available; } -static void -Audio_DeleteDevice(SDL_AudioDevice * device) + +static int +ESD_Init(SDL_AudioDriverImpl *impl) { - SDL_free(device->hidden); - SDL_free(device); - UnloadESDLibrary(); + /* Set the function pointers */ + impl->OpenDevice = ESD_OpenDevice; + impl->PlayDevice = ESD_PlayDevice; + impl->WaitDevice = ESD_WaitDevice; + impl->GetDeviceBuf = ESD_GetDeviceBuf; + impl->CloseDevice = ESD_CloseDevice; + impl->OnlyHasDefaultOutputDevice = 1; + + return 1; } -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - LoadESDLibrary(); - 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 = ESD_OpenAudio; - this->WaitAudio = ESD_WaitAudio; - this->PlayAudio = ESD_PlayAudio; - this->GetAudioBuf = ESD_GetAudioBuf; - this->CloseAudio = ESD_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; -} AudioBootStrap ESD_bootstrap = { ESD_DRIVER_NAME, "Enlightened Sound Daemon", - Audio_Available, Audio_CreateDevice, 0 + ESD_Available, ESD_Init, 0 }; /* This function waits until it is possible to write a full sound buffer */ static void -ESD_WaitAudio(_THIS) +ESD_WaitDevice(_THIS) { Sint32 ticks; @@ -205,28 +176,31 @@ /* 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) { + /* Check every 10 loops */ + if (this->hidden->parent && (((++cnt) % 10) == 0)) { + if (kill(this->hidden->parent, 0) < 0) { this->enabled = 0; } } } /* Use timer for general audio synchronization */ - ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS; + ticks = ((Sint32) (this->hidden->next_frame-SDL_GetTicks())) - FUDGE_TICKS; if (ticks > 0) { SDL_Delay(ticks); } } static void -ESD_PlayAudio(_THIS) +ESD_PlayDevice(_THIS) { - int written; + int written = 0; /* Write the audio data, checking for EAGAIN on broken audio drivers */ do { - written = write(audio_fd, mixbuf, mixlen); + written = write(this->hidden->audio_fd, + this->hidden->mixbuf, + this->hidden->mixlen); if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) { SDL_Delay(1); /* Let a little CPU time go by */ } @@ -235,7 +209,7 @@ ((errno == 0) || (errno == EAGAIN) || (errno == EINTR))); /* Set the next write frame */ - next_frame += frame_ticks; + this->hidden->next_frame += this->hidden->frame_ticks; /* If we couldn't write, assume fatal error for now */ if (written < 0) { @@ -244,22 +218,28 @@ } static Uint8 * -ESD_GetAudioBuf(_THIS) +ESD_GetDeviceBuf(_THIS) { - return (mixbuf); + return (this->hidden->mixbuf); } static void -ESD_CloseAudio(_THIS) +ESD_CloseDevice(_THIS) { - if (mixbuf != NULL) { - SDL_FreeAudioMem(mixbuf); - mixbuf = NULL; + if (this->hidden != NULL) { + if (this->hidden->mixbuf != NULL) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + if (this->hidden->audio_fd >= 0) { + SDL_NAME(esd_close) (this->hidden->audio_fd); + this->hidden->audio_fd = -1; + } + + SDL_free(this->hidden); + this->hidden = NULL; } - if (audio_fd >= 0) { - SDL_NAME(esd_close) (audio_fd); - audio_fd = -1; - } + UnloadESDLibrary(); } /* Try to get the name of the program */ @@ -288,59 +268,96 @@ return (progname); } + static int -ESD_OpenAudio(_THIS, SDL_AudioSpec * spec) +ESD_OpenDevice(_THIS, const char *devname, int iscapture) { - esd_format_t format; + esd_format_t format = (ESD_STREAM | ESD_PLAY); + SDL_AudioFormat test_format = 0; + int found = 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)); + this->hidden->audio_fd = -1; + + if (LoadESDLibrary() < 0) { + ESD_CloseDevice(this); + SDL_SetError("ESD: failed to load library: %s", SDL_GetError()); + return 0; + } /* Convert audio spec to the ESD audio format */ - format = (ESD_STREAM | ESD_PLAY); - switch (spec->format & 0xFF) { - case 8: - format |= ESD_BITS8; - break; - case 16: - format |= ESD_BITS16; - break; - default: - SDL_SetError("Unsupported ESD audio format"); - return (-1); + /* Try for a closest match on audio format */ + for (test_format = SDL_FirstAudioFormat(this->spec.format); + !found && test_format; test_format = SDL_NextAudioFormat()) { +#ifdef DEBUG_AUDIO + fprintf(stderr, "Trying format 0x%4.4x\n", test_format); +#endif + found = 1; + switch (test_format) { + case AUDIO_U8: + format |= ESD_BITS8; + break; + case AUDIO_S16SYS: + format |= ESD_BITS16; + break; + default: + found = 0; + break; + } } - if (spec->channels == 1) { + + if (!found) { + ESD_CloseDevice(this); + SDL_SetError("Couldn't find any hardware audio formats"); + return 0; + } + + if (this->spec.channels == 1) { format |= ESD_MONO; } else { format |= ESD_STEREO; } #if 0 - spec->samples = ESD_BUF_SIZE; /* Darn, no way to change this yet */ + this->spec.samples = ESD_BUF_SIZE; /* Darn, no way to change this yet */ #endif /* Open a connection to the ESD audio server */ - audio_fd = - SDL_NAME(esd_play_stream) (format, spec->freq, NULL, get_progname()); - if (audio_fd < 0) { + this->hidden->audio_fd = + SDL_NAME(esd_play_stream)(format,this->spec.freq,NULL,get_progname()); + + if (this->hidden->audio_fd < 0) { + ESD_CloseDevice(this); SDL_SetError("Couldn't open ESD connection"); - return (-1); + return 0; } /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(spec); - frame_ticks = (float) (spec->samples * 1000) / spec->freq; - next_frame = SDL_GetTicks() + frame_ticks; + SDL_CalculateAudioSpec(&this->spec); + this->hidden->frame_ticks = (float) (this->spec.samples*1000) / this->spec.freq; + this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks; /* Allocate mixing buffer */ - mixlen = spec->size; - mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen); - if (mixbuf == NULL) { - return (-1); + this->hidden->mixlen = this->spec.size; + this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); + if (this->hidden->mixbuf == NULL) { + ESD_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } - SDL_memset(mixbuf, spec->silence, spec->size); + SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); /* Get the parent process id (we're the parent of the audio thread) */ - parent = getpid(); + this->hidden->parent = getpid(); /* We're ready to rock and roll. :-) */ - return (0); + return 1; } /* vi: set ts=4 sw=4 expandtab: */