haikuaudio: Updated for SDL3 audio API.

This commit is contained in:
Ryan C. Gordon
2023-07-05 15:23:03 -04:00
parent fc7ed18ca1
commit 51ae78c0af
2 changed files with 70 additions and 84 deletions

View File

@@ -22,7 +22,7 @@
#ifdef SDL_AUDIO_DRIVER_HAIKU #ifdef SDL_AUDIO_DRIVER_HAIKU
/* Allow access to the audio stream on Haiku */ // Allow access to the audio stream on Haiku
#include <SoundPlayer.h> #include <SoundPlayer.h>
#include <signal.h> #include <signal.h>
@@ -38,58 +38,45 @@ extern "C"
} }
static Uint8 *HAIKUAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
/* !!! FIXME: have the callback call the higher level to avoid code dupe. */
/* The Haiku 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; SDL_assert(device->hidden->current_buffer != NULL);
SDL_AudioCallback callback = audio->callbackspec.callback; SDL_assert(device->hidden->current_buffer_len > 0);
*buffer_size = device->hidden->current_buffer_len;
SDL_LockMutex(audio->mixer_lock); return device->hidden->current_buffer;
/* Only do something if audio is enabled */
if (!SDL_AtomicGet(&audio->enabled) || SDL_AtomicGet(&audio->paused)) {
if (audio->stream) {
SDL_ClearAudioStream(audio->stream);
}
SDL_memset(stream, audio->spec.silence, len);
} else {
SDL_assert(audio->spec.size == len);
if (audio->stream == NULL) { /* no conversion necessary. */
callback(audio->callbackspec.userdata, (Uint8 *) stream, len);
} else { /* streaming/converting */
const int stream_len = audio->callbackspec.size;
const int ilen = (int) len;
while (SDL_GetAudioStreamAvailable(audio->stream) < ilen) {
callback(audio->callbackspec.userdata, audio->work_buffer, stream_len);
if (SDL_PutAudioStreamData(audio->stream, audio->work_buffer, stream_len) == -1) {
SDL_ClearAudioStream(audio->stream);
SDL_AtomicSet(&audio->enabled, 0);
break;
}
} }
const int got = SDL_GetAudioStreamData(audio->stream, stream, ilen); static void HAIKUAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size)
SDL_assert((got < 0) || (got == ilen));
if (got != ilen) {
SDL_memset(stream, audio->spec.silence, len);
}
}
}
SDL_UnlockMutex(audio->mixer_lock);
}
static void HAIKUAUDIO_CloseDevice(SDL_AudioDevice *_this)
{ {
if (_this->hidden->audio_obj) { // We already wrote our output right into the BSoundPlayer's callback's stream. Just clean up our stuff.
_this->hidden->audio_obj->Stop(); SDL_assert(device->hidden->current_buffer != NULL);
delete _this->hidden->audio_obj; SDL_assert(device->hidden->current_buffer_len > 0);
device->hidden->current_buffer = NULL;
device->hidden->current_buffer_len = 0;
}
// The Haiku callback for handling the audio buffer
static void FillSound(void *data, void *stream, size_t len, const media_raw_audio_format & format)
{
SDL_AudioDevice *device = (SDL_AudioDevice *)data;
SDL_assert(device->hidden->current_buffer == NULL);
SDL_assert(device->hidden->current_buffer_len == 0);
device->hidden->current_buffer = (Uint8 *) stream;
device->hidden->current_buffer_len = (int) len;
SDL_OutputAudioThreadIterate(device);
}
static void HAIKUAUDIO_CloseDevice(SDL_AudioDevice *device)
{
if (device->hidden) {
if (device->hidden->audio_obj) {
device->hidden->audio_obj->Stop();
delete device->hidden->audio_obj;
}
delete device->hidden;
device->hidden = NULL;
SDL_AudioThreadFinalize(device);
} }
delete _this->hidden;
} }
@@ -115,26 +102,24 @@ static inline void UnmaskSignals(sigset_t * omask)
} }
static int HAIKUAUDIO_OpenDevice(SDL_AudioDevice *_this, const char *devname) static int HAIKUAUDIO_OpenDevice(SDL_AudioDevice *device)
{ {
media_raw_audio_format format; // Initialize all variables that we clean on shutdown
SDL_AudioFormat test_format; device->hidden = new SDL_PrivateAudioData;
const SDL_AudioFormat *closefmts; if (device->hidden == NULL) {
/* Initialize all variables that we clean on shutdown */
_this->hidden = new SDL_PrivateAudioData;
if (_this->hidden == NULL) {
return SDL_OutOfMemory(); return SDL_OutOfMemory();
} }
SDL_zerop(_this->hidden); SDL_zerop(device->hidden);
/* Parse the audio format and fill the Be raw audio format */ // Parse the audio format and fill the Be raw audio format
media_raw_audio_format format;
SDL_zero(format); SDL_zero(format);
format.byte_order = B_MEDIA_LITTLE_ENDIAN; format.byte_order = B_MEDIA_LITTLE_ENDIAN;
format.frame_rate = (float) _this->spec.freq; format.frame_rate = (float) device->spec.freq;
format.channel_count = _this->spec.channels; /* !!! FIXME: support > 2? */ format.channel_count = device->spec.channels; // !!! FIXME: support > 2?
closefmts = SDL_ClosestAudioFormats(_this->spec.format); SDL_AudioFormat test_format;
const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format);
while ((test_format = *(closefmts++)) != 0) { while ((test_format = *(closefmts++)) != 0) {
switch (test_format) { switch (test_format) {
case SDL_AUDIO_S8: case SDL_AUDIO_S8:
@@ -178,31 +163,30 @@ static int HAIKUAUDIO_OpenDevice(SDL_AudioDevice *_this, const char *devname)
break; break;
} }
if (!test_format) { /* shouldn't happen, but just in case... */ if (!test_format) { // shouldn't happen, but just in case...
return SDL_SetError("%s: Unsupported audio format", "haiku"); return SDL_SetError("HAIKU: Unsupported audio format");
} }
_this->spec.format = test_format; device->spec.format = test_format;
/* Calculate the final parameters for this audio specification */ // Calculate the final parameters for this audio specification
SDL_CalculateAudioSpec(&_this->spec); SDL_UpdatedAudioDeviceFormat(device);
format.buffer_size = _this->spec.size; format.buffer_size = device->buffer_size;
/* Subscribe to the audio stream (creates a new thread) */ // Subscribe to the audio stream (creates a new thread)
sigset_t omask; sigset_t omask;
MaskSignals(&omask); MaskSignals(&omask);
_this->hidden->audio_obj = new BSoundPlayer(&format, "SDL Audio", device->hidden->audio_obj = new BSoundPlayer(&format, "SDL Audio",
FillSound, NULL, _this); FillSound, NULL, device);
UnmaskSignals(&omask); UnmaskSignals(&omask);
if (_this->hidden->audio_obj->Start() == B_NO_ERROR) { if (device->hidden->audio_obj->Start() == B_NO_ERROR) {
_this->hidden->audio_obj->SetHasData(true); device->hidden->audio_obj->SetHasData(true);
} else { } else {
return SDL_SetError("Unable to start Be audio"); return SDL_SetError("Unable to start Haiku audio");
} }
/* We're running! */ return 0; // We're running!
return 0;
} }
static void HAIKUAUDIO_Deinitialize(void) static void HAIKUAUDIO_Deinitialize(void)
@@ -212,27 +196,27 @@ static void HAIKUAUDIO_Deinitialize(void)
static SDL_bool HAIKUAUDIO_Init(SDL_AudioDriverImpl *impl) static SDL_bool HAIKUAUDIO_Init(SDL_AudioDriverImpl *impl)
{ {
/* Initialize the Be Application, if it's not already started */
if (SDL_InitBeApp() < 0) { if (SDL_InitBeApp() < 0) {
return SDL_FALSE; return SDL_FALSE;
} }
/* Set the function pointers */ // Set the function pointers
impl->OpenDevice = HAIKUAUDIO_OpenDevice; impl->OpenDevice = HAIKUAUDIO_OpenDevice;
impl->GetDeviceBuf = HAIKUAUDIO_GetDeviceBuf;
impl->PlayDevice = HAIKUAUDIO_PlayDevice;
impl->CloseDevice = HAIKUAUDIO_CloseDevice; impl->CloseDevice = HAIKUAUDIO_CloseDevice;
impl->Deinitialize = HAIKUAUDIO_Deinitialize; impl->Deinitialize = HAIKUAUDIO_Deinitialize;
impl->ProvidesOwnCallbackThread = SDL_TRUE; impl->ProvidesOwnCallbackThread = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = SDL_TRUE; impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */ return SDL_TRUE;
} }
extern "C"
{ extern "C" { extern AudioBootStrap HAIKUAUDIO_bootstrap; }
extern AudioBootStrap HAIKUAUDIO_bootstrap;
}
AudioBootStrap HAIKUAUDIO_bootstrap = { AudioBootStrap HAIKUAUDIO_bootstrap = {
"haiku", "Haiku BSoundPlayer", HAIKUAUDIO_Init, SDL_FALSE "haiku", "Haiku BSoundPlayer", HAIKUAUDIO_Init, SDL_FALSE
}; };
#endif /* SDL_AUDIO_DRIVER_HAIKU */ #endif // SDL_AUDIO_DRIVER_HAIKU

View File

@@ -28,6 +28,8 @@
struct SDL_PrivateAudioData struct SDL_PrivateAudioData
{ {
BSoundPlayer *audio_obj; BSoundPlayer *audio_obj;
Uint8 *current_buffer;
int current_buffer_len;
}; };
#endif /* SDL_haikuaudio_h_ */ #endif /* SDL_haikuaudio_h_ */