# HG changeset patch # User Ryan C. Gordon # Date 1160166983 0 # Node ID b225d9820ee343c79c5ace8411b6ef4b78425bc6 # Parent 49eadd6e8962247a87f5c59042d86316a218f804 Updated a bunch of audio backends to 1.3 API (Dreamcast, OS/2, ALSA, and BeOS). None are tested, so anyu could fail to compile. diff -r 49eadd6e8962 -r b225d9820ee3 src/audio/alsa/SDL_alsa_audio.c --- a/src/audio/alsa/SDL_alsa_audio.c Fri Oct 06 19:45:11 2006 +0000 +++ b/src/audio/alsa/SDL_alsa_audio.c Fri Oct 06 20:36:23 2006 +0000 @@ -42,13 +42,6 @@ /* The default ALSA audio driver */ #define DEFAULT_DEVICE "default" -/* Audio driver functions */ -static int ALSA_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void ALSA_WaitAudio(_THIS); -static void ALSA_PlayAudio(_THIS); -static Uint8 *ALSA_GetAudioBuf(_THIS); -static void ALSA_CloseAudio(_THIS); - static int (*ALSA_snd_pcm_open) (snd_pcm_t **, const char *, snd_pcm_stream_t, int); static int (*ALSA_snd_pcm_close)(snd_pcm_t * pcm); @@ -148,10 +141,14 @@ return 0; } +#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC + +static int library_load_count = 0; + static void UnloadALSALibrary(void) { - if (alsa_handle != NULL) { + if ((alsa_handle != NULL) && (--library_load_count == 0)) { dlclose(alsa_handle); alsa_handle = NULL; } @@ -160,16 +157,19 @@ static int LoadALSALibrary(void) { - int i, retval = -1; - - alsa_handle = dlopen(alsa_library, RTLD_NOW); - if (alsa_handle == NULL) { - SDL_SetError("ALSA: dlopen('%s') failed: %s\n", - alsa_library, strerror(errno)); - } else { - retval = load_alsa_syms(); - if (retval < 0) { - UnloadALSALibrary(); + int retval = 0; + if (library_load_count++ == 0) { + alsa_handle = dlopen(alsa_library, RTLD_NOW); + if (alsa_handle == NULL) { + library_load_count--; + retval = -1; + SDL_SetError("ALSA: dlopen('%s') failed: %s\n", + alsa_library, strerror(errno)); + } else { + retval = load_alsa_syms(); + if (retval < 0) { + UnloadALSALibrary(); + } } } return retval; @@ -180,7 +180,6 @@ static void UnloadALSALibrary(void) { - return; } static int @@ -209,79 +208,32 @@ return device; } -/* Audio driver bootstrap functions */ static int -Audio_Available(void) +ALSA_Available(void) { - int available; + int available = 0; int status; snd_pcm_t *handle; - available = 0; - if (LoadALSALibrary() < 0) { - return available; + if (LoadALSALibrary() >= 0) { + int status = ALSA_snd_pcm_open(&handle, get_audio_device(2), + SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK); + if (status >= 0) { + available = 1; + ALSA_snd_pcm_close(handle); + } + UnloadALSALibrary(); } - status = ALSA_snd_pcm_open(&handle, get_audio_device(2), - SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); - if (status >= 0) { - available = 1; - ALSA_snd_pcm_close(handle); - } - UnloadALSALibrary(); return (available); } -static void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); - UnloadALSALibrary(); -} -static SDL_AudioDevice * -Audio_CreateDevice(int devindex) -{ - SDL_AudioDevice *this; - - /* Initialize all variables that we clean on shutdown */ - LoadALSALibrary(); - 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)); - - /* Set the function pointers */ - this->OpenAudio = ALSA_OpenAudio; - this->WaitAudio = ALSA_WaitAudio; - this->PlayAudio = ALSA_PlayAudio; - this->GetAudioBuf = ALSA_GetAudioBuf; - this->CloseAudio = ALSA_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; -} - -AudioBootStrap ALSA_bootstrap = { - DRIVER_NAME, "ALSA 0.9 PCM audio", - Audio_Available, Audio_CreateDevice, 0 -}; /* This function waits until it is possible to write a full sound buffer */ static void -ALSA_WaitAudio(_THIS) +ALSA_WaitDevice(_THIS) { /* Check to see if the thread-parent process is still alive */ { @@ -289,8 +241,9 @@ /* 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; } } @@ -298,13 +251,14 @@ } +/* !!! FIXME: is there a channel swizzler in alsalib instead? */ /* * http://bugzilla.libsdl.org/show_bug.cgi?id=110 * "For Linux ALSA, this is FL-FR-RL-RR-C-LFE * and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-RL-RR" */ #define SWIZ6(T) \ - T *ptr = (T *) mixbuf; \ + T *ptr = (T *) this->hidden->mixbuf; \ const Uint32 count = (this->spec.samples / 6); \ Uint32 i; \ for (i = 0; i < count; i++, ptr += 6) { \ @@ -338,8 +292,8 @@ /* - * Called right before feeding this->mixbuf to the hardware. Swizzle channels - * from Windows/Mac order to the format alsalib will want. + * Called right before feeding this->hidden->mixbuf to the hardware. Swizzle + * channels from Windows/Mac order to the format alsalib will want. */ static __inline__ void swizzle_alsa_channels(_THIS) @@ -361,7 +315,7 @@ static void -ALSA_PlayAudio(_THIS) +ALSA_PlayDevice(_THIS) { int status; int sample_len; @@ -370,10 +324,12 @@ swizzle_alsa_channels(this); sample_len = this->spec.samples; - sample_buf = (signed short *) mixbuf; + sample_buf = (signed short *) this->hidden->mixbuf; while (sample_len > 0) { - status = ALSA_snd_pcm_writei(pcm_handle, sample_buf, sample_len); + status = ALSA_snd_pcm_writei(this->hidden->pcm_handle, + sample_buf, sample_len); + if (status < 0) { if (status == -EAGAIN) { SDL_Delay(1); @@ -382,11 +338,11 @@ if (status == -ESTRPIPE) { do { SDL_Delay(1); - status = ALSA_snd_pcm_resume(pcm_handle); + status = ALSA_snd_pcm_resume(this->hidden->pcm_handle); } while (status == -EAGAIN); } if (status < 0) { - status = ALSA_snd_pcm_prepare(pcm_handle); + status = ALSA_snd_pcm_prepare(this->hidden->pcm_handle); } if (status < 0) { /* Hmm, not much we can do - abort */ @@ -401,72 +357,89 @@ } static Uint8 * -ALSA_GetAudioBuf(_THIS) +ALSA_GetDeviceBuf(_THIS) { - return (mixbuf); + return (this->hidden->mixbuf); } static void -ALSA_CloseAudio(_THIS) +ALSA_CloseDevice(_THIS) { - if (mixbuf != NULL) { - SDL_FreeAudioMem(mixbuf); - mixbuf = NULL; - } - if (pcm_handle) { - ALSA_snd_pcm_drain(pcm_handle); - ALSA_snd_pcm_close(pcm_handle); - pcm_handle = NULL; + if (this->hidden != NULL) { + if (this->hidden->mixbuf != NULL) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + if (this->hidden->pcm_handle) { + ALSA_snd_pcm_drain(this->hidden->pcm_handle); + ALSA_snd_pcm_close(this->hidden->pcm_handle); + this->hidden->pcm_handle = NULL; + } + SDL_free(this->hidden); + this->hidden = NULL; } } static int -ALSA_OpenAudio(_THIS, SDL_AudioSpec * spec) +ALSA_OpenDevice(_THIS, const char *devname, int iscapture) { - int status; - snd_pcm_hw_params_t *hwparams; - snd_pcm_sw_params_t *swparams; - snd_pcm_format_t format; - snd_pcm_uframes_t frames; - SDL_AudioFormat test_format; + int status = 0; + snd_pcm_t *pcm_handle = NULL; + snd_pcm_hw_params_t *hwparams = NULL; + snd_pcm_sw_params_t *swparams = NULL; + snd_pcm_format_t format = 0; + snd_pcm_uframes_t frames = 0; + SDL_AudioFormat test_format = 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)); /* Open the audio device */ /* Name of device should depend on # channels in spec */ status = ALSA_snd_pcm_open(&pcm_handle, - get_audio_device(spec->channels), + get_audio_device(this->spec.channels), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (status < 0) { - SDL_SetError("Couldn't open audio device: %s", + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't open audio device: %s", ALSA_snd_strerror(status)); - return (-1); + return 0; } + this->hidden->pcm_handle = pcm_handle; + /* Figure out what the hardware is capable of */ snd_pcm_hw_params_alloca(&hwparams); status = ALSA_snd_pcm_hw_params_any(pcm_handle, hwparams); if (status < 0) { - SDL_SetError("Couldn't get hardware config: %s", + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't get hardware config: %s", ALSA_snd_strerror(status)); - ALSA_CloseAudio(this); - return (-1); + return 0; } /* SDL only uses interleaved sample output */ status = ALSA_snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); if (status < 0) { - SDL_SetError("Couldn't set interleaved access: %s", + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't set interleaved access: %s", ALSA_snd_strerror(status)); - ALSA_CloseAudio(this); - return (-1); + return 0; } /* Try for a closest match on audio format */ status = -1; - for (test_format = SDL_FirstAudioFormat(spec->format); + for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format && (status < 0);) { - status = 0; /* if we can't support a format, it'll become -1. */ + status = 0; /* if we can't support a format, it'll become -1. */ switch (test_format) { case AUDIO_U8: format = SND_PCM_FORMAT_U8; @@ -511,112 +484,133 @@ } } if (status < 0) { - SDL_SetError("Couldn't find any hardware audio formats"); - ALSA_CloseAudio(this); - return (-1); + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't find any hardware audio formats"); + return 0; } - spec->format = test_format; + this->spec.format = test_format; /* Set the number of channels */ status = ALSA_snd_pcm_hw_params_set_channels(pcm_handle, hwparams, - spec->channels); + this->spec.channels); if (status < 0) { status = ALSA_snd_pcm_hw_params_get_channels(hwparams); if ((status <= 0) || (status > 2)) { - SDL_SetError("Couldn't set audio channels"); - ALSA_CloseAudio(this); - return (-1); + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't set audio channels"); + return 0; } - spec->channels = status; + this->spec.channels = status; } /* Set the audio rate */ status = ALSA_snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, - spec->freq, NULL); + this->spec.freq, NULL); if (status < 0) { - ALSA_CloseAudio(this); - SDL_SetError("Couldn't set audio frequency: %s", + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't set audio frequency: %s", ALSA_snd_strerror(status)); - return (-1); + return 0; } - spec->freq = status; + this->spec.freq = status; /* Set the buffer size, in samples */ - frames = spec->samples; + frames = this->spec.samples; frames = ALSA_snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, frames, NULL); - spec->samples = frames; + this->spec.samples = frames; ALSA_snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, 2, NULL); /* "set" the hardware with the desired parameters */ status = ALSA_snd_pcm_hw_params(pcm_handle, hwparams); if (status < 0) { - ALSA_CloseAudio(this); - SDL_SetError("Couldn't set hardware audio parameters: %s", + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't set hardware audio parameters: %s", ALSA_snd_strerror(status)); - return (-1); + return 0; } -/* This is useful for debugging... */ -/* -{ snd_pcm_sframes_t bufsize; int fragments; - bufsize = ALSA_snd_pcm_hw_params_get_period_size(hwparams); - fragments = ALSA_snd_pcm_hw_params_get_periods(hwparams); - - fprintf(stderr, "ALSA: bufsize = %ld, fragments = %d\n", bufsize, fragments); +#if AUDIO_DEBUG +{ + snd_pcm_sframes_t bufsize; + int fragments; + bufsize = ALSA_snd_pcm_hw_params_get_period_size(hwparams); + fragments = ALSA_snd_pcm_hw_params_get_periods(hwparams); + fprintf(stderr,"ALSA: bufsize = %ld, fragments = %d\n",bufsize,fragments); } -*/ +#endif /* Set the software parameters */ snd_pcm_sw_params_alloca(&swparams); status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams); if (status < 0) { - SDL_SetError("Couldn't get software config: %s", + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't get software config: %s", ALSA_snd_strerror(status)); - ALSA_CloseAudio(this); - return (-1); + return 0; } status = ALSA_snd_pcm_sw_params_set_start_threshold(pcm_handle,swparams,0); if (status < 0) { - SDL_SetError("Couldn't set start threshold: %s", + ALSA_CloseDevice(this); + SDL_SetError("ALSA: Couldn't set start threshold: %s", ALSA_snd_strerror(status)); - ALSA_CloseAudio(this); - return (-1); + return 0; } status = ALSA_snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, frames); if (status < 0) { + ALSA_CloseDevice(this); SDL_SetError("Couldn't set avail min: %s", ALSA_snd_strerror(status)); - ALSA_CloseAudio(this); - return (-1); + return 0; } status = ALSA_snd_pcm_sw_params(pcm_handle, swparams); if (status < 0) { + ALSA_CloseDevice(this); SDL_SetError("Couldn't set software audio parameters: %s", ALSA_snd_strerror(status)); - ALSA_CloseAudio(this); - return (-1); + return 0; } /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(spec); + SDL_CalculateAudioSpec(&this->spec); /* Allocate mixing buffer */ - mixlen = spec->size; - mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen); - if (mixbuf == NULL) { - ALSA_CloseAudio(this); - return (-1); + this->hidden->mixlen = this->spec.size; + this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); + if (this->hidden->mixbuf == NULL) { + ALSA_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(); /* Switch to blocking mode for playback */ ALSA_snd_pcm_nonblock(pcm_handle, 0); /* We're ready to rock and roll. :-) */ - return (0); + return 1; } +static int +ALSA_Init(SDL_AudioDriverImpl *impl) +{ + /* Set the function pointers */ + impl->OpenDevice = ALSA_OpenDevice; + impl->WaitDevice = ALSA_WaitDevice; + impl->GetDeviceBuf = ALSA_GetDeviceBuf; + impl->PlayDevice = ALSA_PlayDevice; + impl->CloseDevice = ALSA_CloseDevice; + impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: Add device enum! */ + + return 1; +} + + +AudioBootStrap ALSA_bootstrap = { + DRIVER_NAME, "ALSA 0.9 PCM audio", + ALSA_Available, ALSA_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */ diff -r 49eadd6e8962 -r b225d9820ee3 src/audio/alsa/SDL_alsa_audio.h --- a/src/audio/alsa/SDL_alsa_audio.h Fri Oct 06 19:45:11 2006 +0000 +++ b/src/audio/alsa/SDL_alsa_audio.h Fri Oct 06 20:36:23 2006 +0000 @@ -46,11 +46,5 @@ int mixlen; }; -/* Old variable names */ -#define pcm_handle (this->hidden->pcm_handle) -#define parent (this->hidden->parent) -#define mixbuf (this->hidden->mixbuf) -#define mixlen (this->hidden->mixlen) - #endif /* _ALSA_PCM_audio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff -r 49eadd6e8962 -r b225d9820ee3 src/audio/baudio/SDL_beaudio.cc --- a/src/audio/baudio/SDL_beaudio.cc Fri Oct 06 19:45:11 2006 +0000 +++ b/src/audio/baudio/SDL_beaudio.cc Fri Oct 06 20:36:23 2006 +0000 @@ -36,138 +36,95 @@ #include "../../thread/beos/SDL_systhread_c.h" #include "SDL_beaudio.h" +} -/* Audio driver functions */ - static int BE_OpenAudio(_THIS, SDL_AudioSpec * spec); - static void BE_WaitAudio(_THIS); - static void BE_PlayAudio(_THIS); - static Uint8 *BE_GetAudioBuf(_THIS); - static void BE_CloseAudio(_THIS); - -/* Audio driver bootstrap functions */ - static int Audio_Available(void) - { - return (1); - } +static int BEAUDIO_Available(void) +{ + return 1; /* Always available on BeOS. */ +} - static void Audio_DeleteDevice(SDL_AudioDevice * device) - { - SDL_free(device->hidden); - SDL_free(device); - } - - static SDL_AudioDevice *Audio_CreateDevice(int devindex) - { - SDL_AudioDevice *device; - /* Initialize all variables that we clean on shutdown */ - device = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); - if (device) { - SDL_memset(device, 0, (sizeof *device)); - device->hidden = (struct SDL_PrivateAudioData *) - SDL_malloc((sizeof *device->hidden)); - } - if ((device == NULL) || (device->hidden == NULL)) { - SDL_OutOfMemory(); - if (device) { - SDL_free(device); - } - return (0); - } - SDL_memset(device->hidden, 0, (sizeof *device->hidden)); - - /* Set the function pointers */ - device->OpenAudio = BE_OpenAudio; - device->WaitAudio = BE_WaitAudio; - device->PlayAudio = BE_PlayAudio; - device->GetAudioBuf = BE_GetAudioBuf; - device->CloseAudio = BE_CloseAudio; - - device->free = Audio_DeleteDevice; +/* !!! FIXME: have the callback call the higher level to avoid code dupe. */ +/* The BeOS callback for handling the audio buffer */ +static void +FillSound(void *device, void *stream, size_t len, + const media_raw_audio_format & format) +{ + SDL_AudioDevice *audio = (SDL_AudioDevice *) device; - return device; - } - - AudioBootStrap BAUDIO_bootstrap = { - "baudio", "BeOS BSoundPlayer", - Audio_Available, Audio_CreateDevice - }; + /* Silence the buffer, since it's ours */ + SDL_memset(stream, audio->spec.silence, len); -/* The BeOS callback for handling the audio buffer */ - static void FillSound(void *device, void *stream, size_t len, - const media_raw_audio_format & format) - { - SDL_AudioDevice *audio = (SDL_AudioDevice *) device; - - /* Silence the buffer, since it's ours */ - SDL_memset(stream, audio->spec.silence, len); + /* Only do soemthing if audio is enabled */ + if (!audio->enabled) + return; - /* Only do soemthing if audio is enabled */ - if (!audio->enabled) - return; - - if (!audio->paused) { - if (audio->convert.needed) { - SDL_mutexP(audio->mixer_lock); - (*audio->spec.callback) (audio->spec.userdata, + if (!audio->paused) { + if (audio->convert.needed) { + SDL_mutexP(audio->mixer_lock); + (*audio->spec.callback) (audio->spec.userdata, (Uint8 *) audio->convert.buf, audio->convert.len); - SDL_mutexV(audio->mixer_lock); - SDL_ConvertAudio(&audio->convert); - SDL_memcpy(stream, audio->convert.buf, - audio->convert.len_cvt); - } else { - SDL_mutexP(audio->mixer_lock); - (*audio->spec.callback) (audio->spec.userdata, - (Uint8 *) stream, len); - SDL_mutexV(audio->mixer_lock); - } + SDL_mutexV(audio->mixer_lock); + SDL_ConvertAudio(&audio->convert); + SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt); + } else { + SDL_mutexP(audio->mixer_lock); + (*audio->spec.callback) (audio->spec.userdata, + (Uint8 *) stream, len); + SDL_mutexV(audio->mixer_lock); } - return; } +} -/* Dummy functions -- we don't use thread-based audio */ - void BE_WaitAudio(_THIS) - { - return; - } - void BE_PlayAudio(_THIS) - { - return; - } - Uint8 *BE_GetAudioBuf(_THIS) - { - return (NULL); - } +static void +BEAUDIO_CloseDevice(_THIS) +{ + if (_this->hidden != NULL) { + if (_this->hidden->audio_obj) { + _this->hidden->audio_obj->Stop(); + delete _this->hidden->audio_obj; + _this->hidden->audio_obj = NULL; + } - void BE_CloseAudio(_THIS) - { - if (audio_obj) { - audio_obj->Stop(); - delete audio_obj; - audio_obj = NULL; - } + delete _this->hidden; + _this->hidden = NULL; /* Quit the Be Application, if there's nothing left to do */ SDL_QuitBeApp(); } +} - int BE_OpenAudio(_THIS, SDL_AudioSpec * spec) - { - int valid_datatype = 0; - media_raw_audio_format format; - SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format); +static int +BEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) +{ + int valid_datatype = 0; + media_raw_audio_format format; + SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); - /* Parse the audio format and fill the Be raw audio format */ - memset(&format, '\0', sizeof(media_raw_audio_format)); - format.byte_order = B_MEDIA_LITTLE_ENDIAN; - format.frame_rate = (float) spec->freq; - format.channel_count = spec->channels; /* !!! FIXME: support > 2? */ - while ((!valid_datatype) && (test_format)) { - valid_datatype = 1; - spec->format = test_format; - switch (test_format) { + /* Initialize all variables that we clean on shutdown */ + _this->hidden = new SDL_PrivateAudioData; + if (_this->hidden == NULL) { + SDL_OutOfMemory(); + return 0; + } + SDL_memset(_this->hidden, 0, (sizeof *_this->hidden)); + + /* Initialize the Be Application, if it's not already started */ + if (SDL_InitBeApp() < 0) { + return 0; + } + + /* Parse the audio format and fill the Be raw audio format */ + memset(&format, '\0', sizeof(media_raw_audio_format)); + format.byte_order = B_MEDIA_LITTLE_ENDIAN; + format.frame_rate = (float) this->spec.freq; + format.channel_count = this->spec.channels; /* !!! FIXME: support > 2? */ + while ((!valid_datatype) && (test_format)) { + valid_datatype = 1; + this->spec.format = test_format; + switch (test_format) { case AUDIO_S8: format.format = media_raw_audio_format::B_AUDIO_CHAR; break; @@ -207,43 +164,53 @@ valid_datatype = 0; test_format = SDL_NextAudioFormat(); break; - } } - - format.buffer_size = spec->samples; - - if (!valid_datatype) { /* shouldn't happen, but just in case... */ - SDL_SetError("Unsupported audio format"); - return (-1); - } - - /* Initialize the Be Application, if it's not already started */ - if (SDL_InitBeApp() < 0) { - return (-1); - } - - /* Calculate the final parameters for this audio specification */ - SDL_CalculateAudioSpec(spec); + } - /* Subscribe to the audio stream (creates a new thread) */ - { - sigset_t omask; - SDL_MaskSignals(&omask); - audio_obj = new BSoundPlayer(&format, "SDL Audio", FillSound, - NULL, _this); - SDL_UnmaskSignals(&omask); - } - if (audio_obj->Start() == B_NO_ERROR) { - audio_obj->SetHasData(true); - } else { - SDL_SetError("Unable to start Be audio"); - return (-1); - } + format.buffer_size = this->spec.samples; - /* We're running! */ - return (1); + if (!valid_datatype) { /* shouldn't happen, but just in case... */ + SDL_SetError("Unsupported audio format"); + return 0; } -}; /* Extern C */ + /* Calculate the final parameters for this audio specification */ + SDL_CalculateAudioSpec(&this->spec); + + /* Subscribe to the audio stream (creates a new thread) */ + sigset_t omask; + SDL_MaskSignals(&omask); + _this->hidden->audio_obj = new BSoundPlayer(&format, "SDL Audio", + FillSound, NULL, _this); + SDL_UnmaskSignals(&omask); + + if (_this->hidden->audio_obj->Start() == B_NO_ERROR) { + _this->hidden->audio_obj->SetHasData(true); + } else { + SDL_SetError("Unable to start Be audio"); + return 0; + } + + /* We're running! */ + return 1; +} + +static int +BEAUDIO_Init(SDL_AudioDriverImpl *impl) +{ + /* Set the function pointers */ + impl->OpenDevice = DSP_OpenDevice; + impl->CloseDevice = DSP_CloseDevice; + impl->ProvidesOwnCallbackThread = 1; + impl->OnlyHasDefaultOutputDevice = 1; + + return 1; +} + + +AudioBootStrap BEAUDIO_bootstrap = { + "baudio", "BeOS BSoundPlayer", + BEAUDIO_Available, BEAUDIO_Init, 0 +}; /* vi: set ts=4 sw=4 expandtab: */ diff -r 49eadd6e8962 -r b225d9820ee3 src/audio/baudio/SDL_beaudio.h --- a/src/audio/baudio/SDL_beaudio.h Fri Oct 06 19:45:11 2006 +0000 +++ b/src/audio/baudio/SDL_beaudio.h Fri Oct 06 20:36:23 2006 +0000 @@ -34,8 +34,5 @@ BSoundPlayer *audio_obj; }; -/* Old variable names */ -#define audio_obj (_this->hidden->audio_obj) - #endif /* _SDL_lowaudio_h */ /* vi: set ts=4 sw=4 expandtab: */ diff -r 49eadd6e8962 -r b225d9820ee3 src/audio/dart/SDL_dart.c --- a/src/audio/dart/SDL_dart.c Fri Oct 06 19:45:11 2006 +0000 +++ b/src/audio/dart/SDL_dart.c Fri Oct 06 20:36:23 2006 +0000 @@ -42,10 +42,10 @@ //--------------------------------------------------------------------- // DARTEventFunc // -// This function is called by DART, when an event occures, like end of +// This function is called by DART, when an event occurs, like end of // playback of a buffer, etc... //--------------------------------------------------------------------- -LONG APIENTRY +static LONG APIENTRY DARTEventFunc(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags) { if (ulFlags && MIX_WRITE_COMPLETE) { // Playback of buffer completed! @@ -71,10 +71,10 @@ } -int -DART_OpenAudio(_THIS, SDL_AudioSpec * spec) +static int +DART_OpenDevice(_THIS, const char *devname, int iscapture) { - SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format); + SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); int valid_datatype = 0; MCI_AMP_OPEN_PARMS AmpOpenParms; MCI_GENERIC_PARMS GenericParms; @@ -89,6 +89,15 @@ int iSilence; int rc; + /* 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)); + // First thing is to try to open a given DART device! SDL_memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS)); // pszDeviceType should contain the device type in low word, and device ordinal in high word! @@ -100,30 +109,33 @@ iOpenMode |= MCI_OPEN_SHAREABLE; rc = mciSendCommand(0, MCI_OPEN, iOpenMode, (PVOID) & AmpOpenParms, 0); - if (rc != MCIERR_SUCCESS) // No audio available?? - return (-1); + if (rc != MCIERR_SUCCESS) { // No audio available?? + DART_CloseDevice(this); + return 0; + } + // Save the device ID we got from DART! // We will use this in the next calls! - iDeviceOrd = AmpOpenParms.usDeviceID; + _this->hidden->iCurrDeviceOrd = iDeviceOrd = AmpOpenParms.usDeviceID; // Determine the audio parameters from the AudioSpec - if (spec->channels > 4) - spec->channels = 4; + if (this->spec.channels > 4) + this->spec.channels = 4; while ((!valid_datatype) && (test_format)) { - spec->format = test_format; + this->spec.format = test_format; valid_datatype = 1; switch (test_format) { case AUDIO_U8: // Unsigned 8 bit audio data iSilence = 0x80; - iBits = 8; + _this->hidden->iCurrBits = iBits = 8; break; case AUDIO_S16LSB: // Signed 16 bit audio data iSilence = 0x00; - iBits = 16; + _this->hidden->iCurrBits = iBits = 16; break; // !!! FIXME: int32? @@ -137,16 +149,16 @@ if (!valid_datatype) { // shouldn't happen, but just in case... // Close DART, and exit with error code! - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + DART_CloseDevice(this); SDL_SetError("Unsupported audio format"); - return (-1); + return 0; } - iFreq = spec->freq; - iChannels = spec->channels; + _this->hidden->iCurrFreq = iFreq = this->spec.freq; + _this->hidden->iCurrChannels = iChannels = this->spec.channels; /* Update the fragment size as size in bytes */ - SDL_CalculateAudioSpec(spec); - iBufSize = spec->size; + SDL_CalculateAudioSpec(&this->spec); + _this->hidden->iCurrBufSize = iBufSize = this->spec.size; // Now query this device if it supports the given freq/bits/channels! SDL_memset(&(_this->hidden->MixSetupParms), 0, @@ -163,9 +175,9 @@ &(_this->hidden->MixSetupParms), 0); if (rc != MCIERR_SUCCESS) { // The device cannot handle this format! // Close DART, and exit with error code! - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + DART_CloseDevice(this); SDL_SetError("Audio device doesn't support requested audio format"); - return (-1); + return 0; } // The device can handle this format, so initialize! rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP, @@ -173,9 +185,9 @@ &(_this->hidden->MixSetupParms), 0); if (rc != MCIERR_SUCCESS) { // The device could not be opened! // Close DART, and exit with error code! - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + DART_CloseDevice(this); SDL_SetError("Audio device could not be set up"); - return (-1); + return 0; } // Ok, the device is initialized. // Now we should allocate buffers. For this, we need a place where @@ -184,9 +196,9 @@ (MCI_MIX_BUFFER *) SDL_malloc(sizeof(MCI_MIX_BUFFER) * iNumBufs); if (!(_this->hidden->pMixBuffers)) { // Not enough memory! // Close DART, and exit with error code! - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); - SDL_SetError("Not enough memory for audio buffer descriptors"); - return (-1); + DART_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } // Now that we have the place for buffer list, we can ask DART for the // buffers! @@ -201,12 +213,12 @@ || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers) || (_this->hidden->BufferParms.ulBufferSize == 0)) { // Could not allocate memory! // Close DART, and exit with error code! - SDL_free(_this->hidden->pMixBuffers); - _this->hidden->pMixBuffers = NULL; - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + DART_CloseDevice(this); SDL_SetError("DART could not allocate buffers"); - return (-1); + return 0; } + _this->hidden->iCurrNumBufs = iNumBufs; + // Ok, we have all the buffers allocated, let's mark them! { int i; @@ -216,24 +228,9 @@ // Check if this buffer was really allocated by DART if ((!(_this->hidden->pMixBuffers[i].pBuffer)) || (!pBufferDesc)) { // Wrong buffer! - // Close DART, and exit with error code! - // Free buffer descriptions - { - int j; - for (j = 0; j < i; j++) - SDL_free((void *) (_this->hidden->pMixBuffers[j]. - ulUserParm)); - } - // and cleanup - mciSendCommand(iDeviceOrd, MCI_BUFFER, - MCI_WAIT | MCI_DEALLOCATE_MEMORY, - &(_this->hidden->BufferParms), 0); - SDL_free(_this->hidden->pMixBuffers); - _this->hidden->pMixBuffers = NULL; - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, - &GenericParms, 0); + DART_CloseDevice(this); SDL_SetError("Error at internal buffer check"); - return (-1); + return 0; } pBufferDesc->iBufferUsage = BUFFER_EMPTY; pBufferDesc->pSDLAudioDevice = _this; @@ -254,35 +251,15 @@ if (DosCreateEventSem (NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE) != NO_ERROR) { - // Could not create event semaphore! - { - int i; - for (i = 0; i < iNumBufs; i++) - SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm)); - } - mciSendCommand(iDeviceOrd, MCI_BUFFER, - MCI_WAIT | MCI_DEALLOCATE_MEMORY, - &(_this->hidden->BufferParms), 0); - SDL_free(_this->hidden->pMixBuffers); - _this->hidden->pMixBuffers = NULL; - mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0); + DART_CloseDevice(this); SDL_SetError("Could not create event semaphore"); - return (-1); + return 0; } - // Store the new settings in global variables - _this->hidden->iCurrDeviceOrd = iDeviceOrd; - _this->hidden->iCurrFreq = iFreq; - _this->hidden->iCurrBits = iBits; - _this->hidden->iCurrChannels = iChannels; - _this->hidden->iCurrNumBufs = iNumBufs; - _this->hidden->iCurrBufSize = iBufSize; - return (0); + return 1; } - - -void +static void DART_ThreadInit(_THIS) { /* Increase the priority of this thread to make sure that @@ -291,14 +268,14 @@ if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) { #ifdef DEBUG_BUILD printf - ("[SDL_RunAudio] : Setting priority to TimeCritical+0! (TID%d)\n", + ("[DART_ThreadInit] : Setting priority to TimeCritical+0! (TID%d)\n", SDL_ThreadID()); #endif DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0); } else { #ifdef DEBUG_BUILD printf - ("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n", + ("[DART_ThreadInit] : Setting priority to ForegroundServer+0! (TID%d)\n", SDL_ThreadID()); #endif DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0); @@ -307,8 +284,8 @@ } /* This function waits until it is possible to write a full sound buffer */ -void -DART_WaitAudio(_THIS) +static void +DART_WaitDevice(_THIS) { int i; pMixBufferDesc pBufDesc; @@ -326,8 +303,8 @@ return; } -void -DART_PlayAudio(_THIS) +static void +DART_PlayDevice(_THIS) { int iFreeBuf = _this->hidden->iNextFreeBuffer; pMixBufferDesc pBufDesc; @@ -346,8 +323,8 @@ _this->hidden->iNextFreeBuffer = iFreeBuf; } -Uint8 * -DART_GetAudioBuf(_THIS) +static Uint8 * +DART_GetDeviceBuf(_THIS) { int iFreeBuf; Uint8 *pResult; @@ -366,125 +343,116 @@ return pResult; } } else - printf("[DART_GetAudioBuf] : ERROR! pBufDesc = %p\n", + printf("[DART_GetDeviceBuf] : ERROR! pBufDesc = %p\n", pBufDesc); } else - printf("[DART_GetAudioBuf] : ERROR! _this->hidden = %p\n", + printf("[DART_GetDeviceBuf] : ERROR! _this->hidden = %p\n", _this->hidden); } else - printf("[DART_GetAudioBuf] : ERROR! _this = %p\n", _this); + printf("[DART_GetDeviceBuf] : ERROR! _this = %p\n", _this); return NULL; } -void +static void DART_WaitDone(_THIS) { pMixBufferDesc pBufDesc; - ULONG ulPostCount; - APIRET rc; + ULONG ulPostCount = 0; + APIRET rc = NO_ERROR; - pBufDesc = - (pMixBufferDesc) _this->hidden->pMixBuffers[_this->hidden-> - iLastPlayedBuf]. - ulUserParm; - rc = NO_ERROR; + pBufDesc = (pMixBufferDesc) + _this->hidden->pMixBuffers[_this->hidden->iLastPlayedBuf].ulUserParm; + while ((pBufDesc->iBufferUsage != BUFFER_EMPTY) && (rc == NO_ERROR)) { DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount); rc = DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000); // 1 sec timeout! Important! } } -void -DART_CloseAudio(_THIS) +static void +DART_CloseDevice(_THIS) { MCI_GENERIC_PARMS GenericParms; int rc; + int i; - // Stop DART playback - rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP, MCI_WAIT, - &GenericParms, 0); - if (rc != MCIERR_SUCCESS) { + if (_this->hidden != NULL) { + // Stop DART playback + if (_this->hidden->iCurrDeviceOrd) { + rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP, + MCI_WAIT, &GenericParms, 0); #ifdef SFX_DEBUG_BUILD - printf("Could not stop DART playback!\n"); - fflush(stdout); + if (rc != MCIERR_SUCCESS) { + printf("Could not stop DART playback!\n"); + fflush(stdout); + } #endif - } - // Close event semaphore - DosCloseEventSem(_this->hidden->hevAudioBufferPlayed); + } + + // Close event semaphore + if (_this->hidden->hevAudioBufferPlayed) { + DosCloseEventSem(_this->hidden->hevAudioBufferPlayed); + _this->hidden->hevAudioBufferPlayed = 0; + } - // Free memory of buffer descriptions - { - int i; - for (i = 0; i < _this->hidden->iCurrNumBufs; i++) + // Free memory of buffer descriptions + for (i = 0; i < _this->hidden->iCurrNumBufs; i++) { SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm)); - } + _this->hidden->pMixBuffers[i].ulUserParm = 0; + } + _this->hidden->iCurrNumBufs = 0; + + // Deallocate buffers + if (_this->hidden->iCurrDeviceOrd) { + rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER, + MCI_WAIT | MCI_DEALLOCATE_MEMORY, + &(_this->hidden->BufferParms), 0); + } - // Deallocate buffers - rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER, - MCI_WAIT | MCI_DEALLOCATE_MEMORY, - &(_this->hidden->BufferParms), 0); + // Free bufferlist + if (_this->hidden->pMixBuffers != NULL) { + SDL_free(_this->hidden->pMixBuffers); + _this->hidden->pMixBuffers = NULL; + } - // Free bufferlist - SDL_free(_this->hidden->pMixBuffers); - _this->hidden->pMixBuffers = NULL; + // Close dart + if (_this->hidden->iCurrDeviceOrd) { + rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE, + MCI_WAIT, &(GenericParms), 0); + } + _this->hidden->iCurrDeviceOrd = 0; - // Close dart - rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE, MCI_WAIT, - &(GenericParms), 0); + SDL_free(_this->hidden); + _this->hidden = NULL; + } } -/* Audio driver bootstrap functions */ - -int -Audio_Available(void) +static int +DART_Available(void) { - return (1); -} - -void -Audio_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); + return 1; /* Always available on OS/2 Warp */ } -SDL_AudioDevice * -Audio_CreateDevice(int devindex) +static int +DART_Init(SDL_AudioDriverImpl *impl) { - SDL_AudioDevice *this; + /* Set the function pointers */ + impl->OpenDevice = DART_OpenDevice; + impl->ThreadInit = DART_ThreadInit; + impl->WaitDevice = DART_WaitDevice; + impl->GetDeviceBuf = DART_GetDeviceBuf; + impl->PlayDevice = DART_PlayDevice; + impl->WaitDone = DART_WaitDone; + impl->CloseDevice = DART_CloseDevice; + impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: is this right? */ - /* 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)); + return 1; +} - /* Set the function pointers */ - this->OpenAudio = DART_OpenAudio; - this->ThreadInit = DART_ThreadInit; - this->WaitAudio = DART_WaitAudio; - this->PlayAudio = DART_PlayAudio; - this->GetAudioBuf = DART_GetAudioBuf; - this->WaitDone = DART_WaitDone; - this->CloseAudio = DART_CloseAudio; - - this->free = Audio_DeleteDevice; - - return this; -} AudioBootStrap DART_bootstrap = { "dart", "OS/2 Direct Audio RouTines (DART)", - Audio_Available, Audio_CreateDevice, 0 + DART_Available, DART_Init, 0 }; /* vi: set ts=4 sw=4 expandtab: */ diff -r 49eadd6e8962 -r b225d9820ee3 src/audio/dart/SDL_dart.h --- a/src/audio/dart/SDL_dart.h Fri Oct 06 19:45:11 2006 +0000 +++ b/src/audio/dart/SDL_dart.h Fri Oct 06 20:36:23 2006 +0000 @@ -21,8 +21,8 @@ */ #include "SDL_config.h" -#ifndef _SDL_lowaudio_h -#define _SDL_lowaudio_h +#ifndef _SDL_dart_h +#define _SDL_dart_h #define INCL_TYPES #define INCL_DOSSEMAPHORES @@ -61,5 +61,6 @@ HEV hevAudioBufferPlayed; // Event semaphore to indicate that an audio buffer has been played by DART }; -#endif /* _SDL_lowaudio_h */ +#endif /* _SDL_dart_h */ + /* vi: set ts=4 sw=4 expandtab: */ diff -r 49eadd6e8962 -r b225d9820ee3 src/audio/dc/SDL_dcaudio.c --- a/src/audio/dc/SDL_dcaudio.c Fri Oct 06 19:45:11 2006 +0000 +++ b/src/audio/dc/SDL_dcaudio.c Fri Oct 06 20:36:23 2006 +0000 @@ -33,79 +33,6 @@ #include "aica.h" #include -/* Audio driver functions */ -static int DCAUD_OpenAudio(_THIS, SDL_AudioSpec * spec); -static void DCAUD_WaitAudio(_THIS); -static void DCAUD_PlayAudio(_THIS); -static Uint8 *DCAUD_GetAudioBuf(_THIS); -static void DCAUD_CloseAudio(_THIS); - -/* Audio driver bootstrap functions */ -static int -DCAUD_Available(void) -{ - return 1; -} - -static void -DCAUD_DeleteDevice(SDL_AudioDevice * device) -{ - SDL_free(device->hidden); - SDL_free(device); -} - -static SDL_AudioDevice * -DCAUD_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)); - - /* Set the function pointers */ - this->OpenAudio = DCAUD_OpenAudio; - this->WaitAudio = DCAUD_WaitAudio; - this->PlayAudio = DCAUD_PlayAudio; - this->GetAudioBuf = DCAUD_GetAudioBuf; - this->CloseAudio = DCAUD_CloseAudio; - - this->free = DCAUD_DeleteDevice; - - spu_init(); - - return this; -} - -AudioBootStrap DCAUD_bootstrap = { - "dcaudio", "Dreamcast AICA audio", - DCAUD_Available, DCAUD_CreateDevice, 0 -}; - -/* This function waits until it is possible to write a full sound buffer */ -static void -DCAUD_WaitAudio(_THIS) -{ - if (this->hidden->playing) { - /* wait */ - while (aica_get_pos(0) / this->spec.samples == this->hidden->nextbuf) { - thd_pass(); - } - } -} - #define SPU_RAM_BASE 0xa0800000 static void @@ -151,7 +78,7 @@ } static void -DCAUD_PlayAudio(_THIS) +DCAUD_PlayDevice(_THIS) { SDL_AudioSpec *spec = &this->spec; unsigned int offset; @@ -199,28 +126,59 @@ } static Uint8 * -DCAUD_GetAudioBuf(_THIS) +DCAUD_GetDeviceBuf(_THIS) { return (this->hidden->mixbuf); } +/* This function waits until it is possible to write a full sound buffer */ static void -DCAUD_CloseAudio(_THIS) +DCAUD_WaitDevice(_THIS) { - aica_stop(0); - if (this->spec.channels == 2) - aica_stop(1); - if (this->hidden->mixbuf != NULL) { - SDL_FreeAudioMem(this->hidden->mixbuf); - this->hidden->mixbuf = NULL; + if (this->hidden->playing) { + /* wait */ + while (aica_get_pos(0) / this->spec.samples == this->hidden->nextbuf) { + thd_pass(); + } + } +} + +static void +DCAUD_CloseDevice(_THIS) +{ + if (this->hidden != NULL) { + aica_stop(0); + if (this->spec.channels == 2) { + aica_stop(1); + } + if (this->hidden->mixbuf != NULL) { + SDL_FreeAudioMem(this->hidden->mixbuf); + this->hidden->mixbuf = NULL; + } + SDL_free(this->hidden); + this->hidden = NULL; + + /* !!! FIXME: is there a reverse of spu_init()? */ } } static int -DCAUD_OpenAudio(_THIS, SDL_AudioSpec * spec) +DCAUD_OpenDevice(_THIS, SDL_AudioSpec * spec) { SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format); int valid_datatype = 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)); + + spu_init(); + while ((!valid_datatype) && (test_format)) { spec->format = test_format; switch (test_format) { @@ -237,8 +195,9 @@ } if (!valid_datatype) { /* shouldn't happen, but just in case... */ + DCAUD_CloseDevice(this); SDL_SetError("Unsupported audio format"); - return (-1); + return 0; } if (spec->channels > 2) @@ -251,7 +210,9 @@ this->hidden->mixlen = spec->size; this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); if (this->hidden->mixbuf == NULL) { - return (-1); + DCAUD_CloseDevice(this); + SDL_OutOfMemory(); + return 0; } SDL_memset(this->hidden->mixbuf, spec->silence, spec->size); this->hidden->leftpos = 0x11000; @@ -260,7 +221,32 @@ this->hidden->nextbuf = 0; /* We're ready to rock and roll. :-) */ - return (0); + return 1; +} + +static int +DCAUD_Available(void) +{ + return 1; /* Dreamcast hardware is always available. :) */ } +static int +DCAUD_Init(SDL_AudioDriverImpl *impl) +{ + /* Set the function pointers */ + impl->OpenDevice = DCAUD_OpenDevice; + impl->PlayDevice = DCAUD_PlayDevice; + impl->WaitDevice = DCAUD_WaitDevice; + impl->GetDeviceBuf = DCAUD_GetDeviceBuf; + impl->CloseDevice = DCAUD_CloseDevice; + impl->OnlyHasDefaultOutputDevice = 1; + + return 1; +} + +AudioBootStrap DCAUD_bootstrap = { + "dcaudio", "Dreamcast AICA audio", + DCAUD_Available, DCAUD_Init, 0 +}; + /* vi: set ts=4 sw=4 expandtab: */