Merge commit '3a7f96fd99528968c39b5be81db067ca018d432b' into dev

This commit is contained in:
SimoneN64
2024-09-18 20:42:08 +02:00
641 changed files with 31269 additions and 30646 deletions

View File

@@ -280,7 +280,7 @@ bool SDL_AudioSpecsEqual(const SDL_AudioSpec *a, const SDL_AudioSpec *b, const i
// consumed and apps relying on audio callbacks don't stop making progress.
static bool ZombieWaitDevice(SDL_AudioDevice *device)
{
if (!SDL_AtomicGet(&device->shutdown)) {
if (!SDL_GetAtomicInt(&device->shutdown)) {
const int frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec);
SDL_Delay((frames * 1000) / device->spec.freq);
}
@@ -390,7 +390,7 @@ static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid,
// to make sure the correct physical device gets locked, in case we're in a race with the default changing.
while (true) {
SDL_LockMutex(device->lock);
SDL_AudioDevice *recheck_device = (SDL_AudioDevice *) SDL_AtomicGetPointer((void **) &logdev->physical_device);
SDL_AudioDevice *recheck_device = (SDL_AudioDevice *) SDL_GetAtomicPointer((void **) &logdev->physical_device);
if (device == recheck_device) {
break;
}
@@ -559,7 +559,7 @@ void UnrefPhysicalAudioDevice(SDL_AudioDevice *device)
// take it out of the device list.
SDL_LockRWLockForWriting(current_audio.device_hash_lock);
if (SDL_RemoveFromHashTable(current_audio.device_hash, (const void *) (uintptr_t) device->instance_id)) {
SDL_AtomicAdd(device->recording ? &current_audio.recording_device_count : &current_audio.playback_device_count, -1);
SDL_AddAtomicInt(device->recording ? &current_audio.recording_device_count : &current_audio.playback_device_count, -1);
}
SDL_UnlockRWLock(current_audio.device_hash_lock);
DestroyPhysicalAudioDevice(device); // ...and nuke it.
@@ -576,7 +576,7 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, bool recordi
SDL_assert(name != NULL);
SDL_LockRWLockForReading(current_audio.device_hash_lock);
const int shutting_down = SDL_AtomicGet(&current_audio.shutting_down);
const int shutting_down = SDL_GetAtomicInt(&current_audio.shutting_down);
SDL_UnlockRWLock(current_audio.device_hash_lock);
if (shutting_down) {
return NULL; // we're shutting down, don't add any devices that are hotplugged at the last possible moment.
@@ -608,8 +608,8 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, bool recordi
return NULL;
}
SDL_AtomicSet(&device->shutdown, 0);
SDL_AtomicSet(&device->zombie, 0);
SDL_SetAtomicInt(&device->shutdown, 0);
SDL_SetAtomicInt(&device->zombie, 0);
device->recording = recording;
SDL_copyp(&device->spec, spec);
SDL_copyp(&device->default_spec, spec);
@@ -621,7 +621,7 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, bool recordi
SDL_LockRWLockForWriting(current_audio.device_hash_lock);
if (SDL_InsertIntoHashTable(current_audio.device_hash, (const void *) (uintptr_t) device->instance_id, device)) {
SDL_AtomicAdd(device_count, 1);
SDL_AddAtomicInt(device_count, 1);
} else {
SDL_DestroyCondition(device->close_cond);
SDL_DestroyMutex(device->lock);
@@ -711,7 +711,7 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device)
const bool is_default_device = ((devid == current_audio.default_playback_device_id) || (devid == current_audio.default_recording_device_id));
SDL_UnlockRWLock(current_audio.device_hash_lock);
const bool first_disconnect = SDL_AtomicCompareAndSwap(&device->zombie, 0, 1);
const bool first_disconnect = SDL_CompareAndSwapAtomicInt(&device->zombie, 0, 1);
if (first_disconnect) { // if already disconnected this device, don't do it twice.
// Swap in "Zombie" versions of the usual platform interfaces, so the device will keep
// making progress until the app closes it. Otherwise, streams might continue to
@@ -886,7 +886,7 @@ bool SDL_InitAudio(const char *driver_name)
}
// make sure device IDs start at 2 (because of SDL2 legacy interface), but don't reset the counter on each init, in case the app is holding an old device ID somewhere.
SDL_AtomicCompareAndSwap(&last_device_instance_id, 0, 2);
SDL_CompareAndSwapAtomicInt(&last_device_instance_id, 0, 2);
SDL_ChooseAudioConverters();
SDL_SetupAudioResampler();
@@ -1031,13 +1031,13 @@ void SDL_QuitAudio(void)
}
SDL_LockRWLockForWriting(current_audio.device_hash_lock);
SDL_AtomicSet(&current_audio.shutting_down, 1);
SDL_SetAtomicInt(&current_audio.shutting_down, 1);
SDL_HashTable *device_hash = current_audio.device_hash;
current_audio.device_hash = NULL;
SDL_PendingAudioDeviceEvent *pending_events = current_audio.pending_events.next;
current_audio.pending_events.next = NULL;
SDL_AtomicSet(&current_audio.playback_device_count, 0);
SDL_AtomicSet(&current_audio.recording_device_count, 0);
SDL_SetAtomicInt(&current_audio.playback_device_count, 0);
SDL_SetAtomicInt(&current_audio.recording_device_count, 0);
SDL_UnlockRWLock(current_audio.device_hash_lock);
SDL_PendingAudioDeviceEvent *pending_next = NULL;
@@ -1094,7 +1094,7 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
SDL_LockMutex(device->lock);
if (SDL_AtomicGet(&device->shutdown)) {
if (SDL_GetAtomicInt(&device->shutdown)) {
SDL_UnlockMutex(device->lock);
return false; // we're done, shut it down.
}
@@ -1118,7 +1118,7 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
// We should have updated this elsewhere if the format changed!
SDL_assert(SDL_AudioSpecsEqual(&stream->dst_spec, &device->spec, stream->dst_chmap, device->chmap));
const int br = SDL_AtomicGet(&logdev->paused) ? 0 : SDL_GetAudioStreamDataAdjustGain(stream, device_buffer, buffer_size, logdev->gain);
const int br = SDL_GetAtomicInt(&logdev->paused) ? 0 : SDL_GetAudioStreamDataAdjustGain(stream, device_buffer, buffer_size, logdev->gain);
if (br < 0) { // Probably OOM. Kill the audio device; the whole thing is likely dying soon anyhow.
failed = true;
SDL_memset(device_buffer, device->silence_value, buffer_size); // just supply silence to the device before we die.
@@ -1139,7 +1139,7 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
SDL_memset(final_mix_buffer, '\0', work_buffer_size); // start with silence.
for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev; logdev = logdev->next) {
if (SDL_AtomicGet(&logdev->paused)) {
if (SDL_GetAtomicInt(&logdev->paused)) {
continue; // paused? Skip this logical device.
}
@@ -1202,7 +1202,7 @@ void SDL_PlaybackAudioThreadShutdown(SDL_AudioDevice *device)
SDL_assert(!device->recording);
const int frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec);
// Wait for the audio to drain if device didn't die.
if (!SDL_AtomicGet(&device->zombie)) {
if (!SDL_GetAtomicInt(&device->zombie)) {
SDL_Delay(((frames * 1000) / device->spec.freq) * 2);
}
current_audio.impl.ThreadDeinit(device);
@@ -1242,7 +1242,7 @@ bool SDL_RecordingAudioThreadIterate(SDL_AudioDevice *device)
SDL_LockMutex(device->lock);
if (SDL_AtomicGet(&device->shutdown)) {
if (SDL_GetAtomicInt(&device->shutdown)) {
SDL_UnlockMutex(device->lock);
return false; // we're done, shut it down.
}
@@ -1258,7 +1258,7 @@ bool SDL_RecordingAudioThreadIterate(SDL_AudioDevice *device)
failed = true;
} else if (br > 0) { // queue the new data to each bound stream.
for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev; logdev = logdev->next) {
if (SDL_AtomicGet(&logdev->paused)) {
if (SDL_GetAtomicInt(&logdev->paused)) {
continue; // paused? Skip this logical device.
}
@@ -1342,7 +1342,7 @@ static SDL_AudioDeviceID *GetAudioDevices(int *count, bool recording)
if (SDL_GetCurrentAudioDriver()) {
SDL_LockRWLockForReading(current_audio.device_hash_lock);
{
num_devices = SDL_AtomicGet(recording ? &current_audio.recording_device_count : &current_audio.playback_device_count);
num_devices = SDL_GetAtomicInt(recording ? &current_audio.recording_device_count : &current_audio.playback_device_count);
result = (SDL_AudioDeviceID *) SDL_malloc((num_devices + 1) * sizeof (SDL_AudioDeviceID));
if (result) {
int devs_seen = 0;
@@ -1443,7 +1443,7 @@ const char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)
return result;
}
SDL_bool SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int *sample_frames)
bool SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int *sample_frames)
{
if (!spec) {
return SDL_InvalidParamError("spec");
@@ -1490,7 +1490,7 @@ int *SDL_GetAudioDeviceChannelMap(SDL_AudioDeviceID devid, int *count)
// BE CAREFUL WITH THIS.
static void SerializePhysicalDeviceClose(SDL_AudioDevice *device)
{
while (SDL_AtomicGet(&device->shutdown)) {
while (SDL_GetAtomicInt(&device->shutdown)) {
SDL_WaitCondition(device->close_cond, device->lock);
}
}
@@ -1500,7 +1500,7 @@ static void ClosePhysicalAudioDevice(SDL_AudioDevice *device)
{
SerializePhysicalDeviceClose(device);
SDL_AtomicSet(&device->shutdown, 1);
SDL_SetAtomicInt(&device->shutdown, 1);
// YOU MUST PROTECT KEY POINTS WITH SerializePhysicalDeviceClose() WHILE THE THREAD JOINS
SDL_UnlockMutex(device->lock);
@@ -1517,7 +1517,7 @@ static void ClosePhysicalAudioDevice(SDL_AudioDevice *device)
}
SDL_LockMutex(device->lock);
SDL_AtomicSet(&device->shutdown, 0); // ready to go again.
SDL_SetAtomicInt(&device->shutdown, 0); // ready to go again.
SDL_BroadcastCondition(device->close_cond); // release anyone waiting in SerializePhysicalDeviceClose; they'll still block until we release device->lock, though.
SDL_aligned_free(device->work_buffer);
@@ -1630,7 +1630,7 @@ static bool OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec
}
// Just pretend to open a zombie device. It can still collect logical devices on a default device under the assumption they will all migrate when the default device is officially changed.
if (SDL_AtomicGet(&device->zombie)) {
if (SDL_GetAtomicInt(&device->zombie)) {
return true; // Braaaaaaaaains.
}
@@ -1719,7 +1719,7 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp
if (device) {
SDL_LogicalAudioDevice *logdev = NULL;
if (!wants_default && SDL_AtomicGet(&device->zombie)) {
if (!wants_default && SDL_GetAtomicInt(&device->zombie)) {
// uhoh, this device is undead, and just waiting to be cleaned up. Refuse explicit opens.
SDL_SetError("Device was already lost and can't accept new opens");
} else if ((logdev = (SDL_LogicalAudioDevice *) SDL_calloc(1, sizeof (SDL_LogicalAudioDevice))) == NULL) {
@@ -1728,7 +1728,7 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp
SDL_free(logdev);
} else {
RefPhysicalAudioDevice(device); // unref'd on successful SDL_CloseAudioDevice
SDL_AtomicSet(&logdev->paused, 0);
SDL_SetAtomicInt(&logdev->paused, 0);
result = logdev->instance_id = AssignAudioDeviceInstanceId(device->recording, /*islogical=*/true);
logdev->physical_device = device;
logdev->gain = 1.0f;
@@ -1761,28 +1761,28 @@ static bool SetLogicalAudioDevicePauseState(SDL_AudioDeviceID devid, int value)
SDL_AudioDevice *device = NULL;
SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device);
if (logdev) {
SDL_AtomicSet(&logdev->paused, value);
SDL_SetAtomicInt(&logdev->paused, value);
}
ReleaseAudioDevice(device);
return logdev ? true : false; // ObtainLogicalAudioDevice will have set an error.
}
SDL_bool SDL_PauseAudioDevice(SDL_AudioDeviceID devid)
bool SDL_PauseAudioDevice(SDL_AudioDeviceID devid)
{
return SetLogicalAudioDevicePauseState(devid, 1);
}
SDL_bool SDLCALL SDL_ResumeAudioDevice(SDL_AudioDeviceID devid)
bool SDLCALL SDL_ResumeAudioDevice(SDL_AudioDeviceID devid)
{
return SetLogicalAudioDevicePauseState(devid, 0);
}
SDL_bool SDL_AudioDevicePaused(SDL_AudioDeviceID devid)
bool SDL_AudioDevicePaused(SDL_AudioDeviceID devid)
{
SDL_AudioDevice *device = NULL;
SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device);
bool result = false;
if (logdev && SDL_AtomicGet(&logdev->paused)) {
if (logdev && SDL_GetAtomicInt(&logdev->paused)) {
result = true;
}
ReleaseAudioDevice(device);
@@ -1798,7 +1798,7 @@ float SDL_GetAudioDeviceGain(SDL_AudioDeviceID devid)
return result;
}
SDL_bool SDL_SetAudioDeviceGain(SDL_AudioDeviceID devid, float gain)
bool SDL_SetAudioDeviceGain(SDL_AudioDeviceID devid, float gain)
{
if (gain < 0.0f) {
return SDL_InvalidParamError("gain");
@@ -1827,7 +1827,7 @@ SDL_bool SDL_SetAudioDeviceGain(SDL_AudioDeviceID devid, float gain)
return result;
}
SDL_bool SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallback callback, void *userdata)
bool SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallback callback, void *userdata)
{
SDL_AudioDevice *device = NULL;
SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device);
@@ -1862,7 +1862,7 @@ SDL_bool SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCa
return result;
}
SDL_bool SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int num_streams)
bool SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int num_streams)
{
const bool islogical = !(devid & (1<<1));
SDL_AudioDevice *device = NULL;
@@ -1955,7 +1955,7 @@ SDL_bool SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams
return result;
}
SDL_bool SDL_BindAudioStream(SDL_AudioDeviceID devid, SDL_AudioStream *stream)
bool SDL_BindAudioStream(SDL_AudioDeviceID devid, SDL_AudioStream *stream)
{
return SDL_BindAudioStreams(devid, &stream, 1);
}
@@ -2067,7 +2067,7 @@ SDL_AudioStream *SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_Au
if (!logdev) { // this shouldn't happen, but just in case.
failed = true;
} else {
SDL_AtomicSet(&logdev->paused, 1); // start the device paused, to match SDL2.
SDL_SetAtomicInt(&logdev->paused, 1); // start the device paused, to match SDL2.
SDL_assert(device != NULL);
const bool recording = device->recording;
@@ -2120,7 +2120,7 @@ SDL_AudioStream *SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_Au
return stream;
}
SDL_bool SDL_PauseAudioStreamDevice(SDL_AudioStream *stream)
bool SDL_PauseAudioStreamDevice(SDL_AudioStream *stream)
{
SDL_AudioDeviceID devid = SDL_GetAudioStreamDevice(stream);
if (!devid) {
@@ -2130,7 +2130,7 @@ SDL_bool SDL_PauseAudioStreamDevice(SDL_AudioStream *stream)
return SDL_PauseAudioDevice(devid);
}
SDL_bool SDL_ResumeAudioStreamDevice(SDL_AudioStream *stream)
bool SDL_ResumeAudioStreamDevice(SDL_AudioStream *stream)
{
SDL_AudioDeviceID devid = SDL_GetAudioStreamDevice(stream);
if (!devid) {
@@ -2302,7 +2302,7 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device)
new_default_device->logical_devices = logdev;
SDL_UnlockRWLock(current_audio.device_hash_lock);
SDL_assert(SDL_AtomicGet(&current_default_device->refcount) > 1); // we should hold at least one extra reference to this device, beyond logical devices, during this phase...
SDL_assert(SDL_GetAtomicInt(&current_default_device->refcount) > 1); // we should hold at least one extra reference to this device, beyond logical devices, during this phase...
RefPhysicalAudioDevice(new_default_device);
UnrefPhysicalAudioDevice(current_default_device);
@@ -2474,7 +2474,7 @@ void SDL_UpdateAudio(void)
SDL_zero(event);
event.type = i->type;
event.adevice.which = (Uint32) i->devid;
event.adevice.recording = (i->devid & (1<<0)) ? 0 : 1; // bit #0 of devid is set for playback devices and unset for recording.
event.adevice.recording = ((i->devid & (1<<0)) == 0); // bit #0 of devid is set for playback devices and unset for recording.
SDL_PushEvent(&event);
}
SDL_free(i);

View File

@@ -448,7 +448,7 @@ SDL_PropertiesID SDL_GetAudioStreamProperties(SDL_AudioStream *stream)
return stream->props;
}
SDL_bool SDL_SetAudioStreamGetCallback(SDL_AudioStream *stream, SDL_AudioStreamCallback callback, void *userdata)
bool SDL_SetAudioStreamGetCallback(SDL_AudioStream *stream, SDL_AudioStreamCallback callback, void *userdata)
{
if (!stream) {
return SDL_InvalidParamError("stream");
@@ -460,7 +460,7 @@ SDL_bool SDL_SetAudioStreamGetCallback(SDL_AudioStream *stream, SDL_AudioStreamC
return true;
}
SDL_bool SDL_SetAudioStreamPutCallback(SDL_AudioStream *stream, SDL_AudioStreamCallback callback, void *userdata)
bool SDL_SetAudioStreamPutCallback(SDL_AudioStream *stream, SDL_AudioStreamCallback callback, void *userdata)
{
if (!stream) {
return SDL_InvalidParamError("stream");
@@ -472,7 +472,7 @@ SDL_bool SDL_SetAudioStreamPutCallback(SDL_AudioStream *stream, SDL_AudioStreamC
return true;
}
SDL_bool SDL_LockAudioStream(SDL_AudioStream *stream)
bool SDL_LockAudioStream(SDL_AudioStream *stream)
{
if (!stream) {
return SDL_InvalidParamError("stream");
@@ -481,7 +481,7 @@ SDL_bool SDL_LockAudioStream(SDL_AudioStream *stream)
return true;
}
SDL_bool SDL_UnlockAudioStream(SDL_AudioStream *stream)
bool SDL_UnlockAudioStream(SDL_AudioStream *stream)
{
if (!stream) {
return SDL_InvalidParamError("stream");
@@ -490,7 +490,7 @@ SDL_bool SDL_UnlockAudioStream(SDL_AudioStream *stream)
return true;
}
SDL_bool SDL_GetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioSpec *src_spec, SDL_AudioSpec *dst_spec)
bool SDL_GetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioSpec *src_spec, SDL_AudioSpec *dst_spec)
{
if (!stream) {
return SDL_InvalidParamError("stream");
@@ -514,7 +514,7 @@ SDL_bool SDL_GetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioSpec *src_sp
return true;
}
SDL_bool SDL_SetAudioStreamFormat(SDL_AudioStream *stream, const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec)
bool SDL_SetAudioStreamFormat(SDL_AudioStream *stream, const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec)
{
if (!stream) {
return SDL_InvalidParamError("stream");
@@ -626,12 +626,12 @@ bool SetAudioStreamChannelMap(SDL_AudioStream *stream, const SDL_AudioSpec *spec
return result;
}
SDL_bool SDL_SetAudioStreamInputChannelMap(SDL_AudioStream *stream, const int *chmap, int channels)
bool SDL_SetAudioStreamInputChannelMap(SDL_AudioStream *stream, const int *chmap, int channels)
{
return SetAudioStreamChannelMap(stream, &stream->src_spec, &stream->src_chmap, chmap, channels, true);
}
SDL_bool SDL_SetAudioStreamOutputChannelMap(SDL_AudioStream *stream, const int *chmap, int channels)
bool SDL_SetAudioStreamOutputChannelMap(SDL_AudioStream *stream, const int *chmap, int channels)
{
return SetAudioStreamChannelMap(stream, &stream->dst_spec, &stream->dst_chmap, chmap, channels, false);
}
@@ -686,7 +686,7 @@ float SDL_GetAudioStreamFrequencyRatio(SDL_AudioStream *stream)
return freq_ratio;
}
SDL_bool SDL_SetAudioStreamFrequencyRatio(SDL_AudioStream *stream, float freq_ratio)
bool SDL_SetAudioStreamFrequencyRatio(SDL_AudioStream *stream, float freq_ratio)
{
if (!stream) {
return SDL_InvalidParamError("stream");
@@ -723,7 +723,7 @@ float SDL_GetAudioStreamGain(SDL_AudioStream *stream)
return gain;
}
SDL_bool SDL_SetAudioStreamGain(SDL_AudioStream *stream, float gain)
bool SDL_SetAudioStreamGain(SDL_AudioStream *stream, float gain)
{
if (!stream) {
return SDL_InvalidParamError("stream");
@@ -805,7 +805,7 @@ static void SDLCALL FreeAllocatedAudioBuffer(void *userdata, const void *buf, in
SDL_free((void*) buf);
}
SDL_bool SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len)
bool SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len)
{
if (!stream) {
return SDL_InvalidParamError("stream");
@@ -841,7 +841,7 @@ SDL_bool SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int le
return PutAudioStreamBuffer(stream, buf, len, NULL, NULL);
}
SDL_bool SDL_FlushAudioStream(SDL_AudioStream *stream)
bool SDL_FlushAudioStream(SDL_AudioStream *stream)
{
if (!stream) {
return SDL_InvalidParamError("stream");
@@ -1013,7 +1013,7 @@ static bool GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int o
// Calculate the number of input frames necessary for this request.
// Because resampling happens "between" frames, The same number of output_frames
// can require a different number of input_frames, depending on the resample_offset.
// Infact, input_frames can sometimes even be zero when upsampling.
// In fact, input_frames can sometimes even be zero when upsampling.
const int input_frames = (int) SDL_GetResamplerInputFrames(output_frames, resample_rate, stream->resample_offset);
const int padding_frames = SDL_GetResamplerPaddingFrames(resample_rate);
@@ -1254,7 +1254,7 @@ int SDL_GetAudioStreamQueued(SDL_AudioStream *stream)
return (int) SDL_min(total, SDL_INT_MAX);
}
SDL_bool SDL_ClearAudioStream(SDL_AudioStream *stream)
bool SDL_ClearAudioStream(SDL_AudioStream *stream)
{
if (!stream) {
return SDL_InvalidParamError("stream");
@@ -1303,7 +1303,7 @@ static void SDLCALL DontFreeThisAudioBuffer(void *userdata, const void *buf, int
// We don't own the buffer, but know it will outlive the stream
}
SDL_bool SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data, int src_len, const SDL_AudioSpec *dst_spec, Uint8 **dst_data, int *dst_len)
bool SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data, int src_len, const SDL_AudioSpec *dst_spec, Uint8 **dst_data, int *dst_len)
{
if (dst_data) {
*dst_data = NULL;

View File

@@ -574,16 +574,11 @@ static void SetupAudioResampler(void)
void SDL_SetupAudioResampler(void)
{
static SDL_SpinLock running = 0;
static SDL_InitState init;
if (!ResampleFrame[0]) {
SDL_LockSpinlock(&running);
if (!ResampleFrame[0]) {
SetupAudioResampler();
}
SDL_UnlockSpinlock(&running);
if (SDL_ShouldInit(&init)) {
SetupAudioResampler();
SDL_SetInitialized(&init, true);
}
}

View File

@@ -86,7 +86,7 @@ static const Uint8 mix8[] = {
// !!! FIXME: Add fast-path for volume = 1
// !!! FIXME: Use larger scales for 16-bit/32-bit integers
SDL_bool SDL_MixAudio(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, Uint32 len, float fvolume)
bool SDL_MixAudio(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, Uint32 len, float fvolume)
{
int volume = (int)SDL_roundf(fvolume * MIX_MAXVOLUME);

View File

@@ -24,7 +24,7 @@
#include <limits.h>
#endif
#ifndef INT_MAX
// Make a lucky guess.
SDL_COMPILE_TIME_ASSERT(int_size, sizeof(int) == sizeof(Sint32));
#define INT_MAX SDL_MAX_SINT32
#endif
#ifndef SIZE_MAX
@@ -2076,7 +2076,7 @@ static bool WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uin
return true;
}
SDL_bool SDL_LoadWAV_IO(SDL_IOStream *src, SDL_bool closeio, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
bool SDL_LoadWAV_IO(SDL_IOStream *src, bool closeio, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
{
bool result = false;
WaveFile file;
@@ -2130,7 +2130,7 @@ done:
return result;
}
SDL_bool SDL_LoadWAV(const char *path, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
bool SDL_LoadWAV(const char *path, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len)
{
return SDL_LoadWAV_IO(SDL_IOFromFile(path, "rb"), 1, spec, audio_buf, audio_len);
}

View File

@@ -82,7 +82,7 @@ static void AAUDIO_errorCallback(AAudioStream *stream, void *userData, aaudio_re
// You MUST NOT close the audio stream from this callback, so we cannot call SDL_AudioDeviceDisconnected here.
// Just flag the device so we can kill it in PlayDevice instead.
SDL_AudioDevice *device = (SDL_AudioDevice *) userData;
SDL_AtomicSet(&device->hidden->error_callback_triggered, (int) error); // AAUDIO_OK is zero, so !triggered means no error.
SDL_SetAtomicInt(&device->hidden->error_callback_triggered, (int) error); // AAUDIO_OK is zero, so !triggered means no error.
SDL_SignalSemaphore(device->hidden->semaphore); // in case we're blocking in WaitDevice.
}
@@ -163,7 +163,7 @@ static Uint8 *AAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *bufsize)
static bool AAUDIO_WaitDevice(SDL_AudioDevice *device)
{
while (!SDL_AtomicGet(&device->shutdown)) {
while (!SDL_GetAtomicInt(&device->shutdown)) {
// this semaphore won't fire when the app is in the background (AAUDIO_PauseDevices was called).
if (SDL_WaitSemaphoreTimeout(device->hidden->semaphore, 100)) {
return true; // semaphore was signaled, let's go!
@@ -218,7 +218,7 @@ static bool AAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int
struct SDL_PrivateAudioData *hidden = device->hidden;
// AAUDIO_dataCallback picks up our work and unblocks AAUDIO_WaitDevice. But make sure we didn't fail here.
const aaudio_result_t err = (aaudio_result_t) SDL_AtomicGet(&hidden->error_callback_triggered);
const aaudio_result_t err = (aaudio_result_t) SDL_GetAtomicInt(&hidden->error_callback_triggered);
if (err) {
SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "aaudio: Audio device triggered error %d (%s)", (int) err, ctx.AAudio_convertResultToText(err));
@@ -237,8 +237,8 @@ static int AAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen
struct SDL_PrivateAudioData *hidden = device->hidden;
// AAUDIO_dataCallback picks up our work and unblocks AAUDIO_WaitDevice. But make sure we didn't fail here.
if (SDL_AtomicGet(&hidden->error_callback_triggered)) {
SDL_AtomicSet(&hidden->error_callback_triggered, 0);
if (SDL_GetAtomicInt(&hidden->error_callback_triggered)) {
SDL_SetAtomicInt(&hidden->error_callback_triggered, 0);
return -1;
}
@@ -279,7 +279,7 @@ static bool BuildAAudioStream(SDL_AudioDevice *device)
const bool recording = device->recording;
aaudio_result_t res;
SDL_AtomicSet(&hidden->error_callback_triggered, 0);
SDL_SetAtomicInt(&hidden->error_callback_triggered, 0);
AAudioStreamBuilder *builder = NULL;
res = ctx.AAudio_createStreamBuilder(&builder);
@@ -308,8 +308,8 @@ static bool BuildAAudioStream(SDL_AudioDevice *device)
}
ctx.AAudioStreamBuilder_setFormat(builder, format);
ctx.AAudioStreamBuilder_setSampleRate(builder, device->spec.freq);
ctx.AAudioStreamBuilder_setChannelCount(builder, device->spec.channels);
#endif
ctx.AAudioStreamBuilder_setChannelCount(builder, device->spec.channels);
const aaudio_direction_t direction = (recording ? AAUDIO_DIRECTION_INPUT : AAUDIO_DIRECTION_OUTPUT);
ctx.AAudioStreamBuilder_setDirection(builder, direction);
@@ -320,7 +320,7 @@ static bool BuildAAudioStream(SDL_AudioDevice *device)
ctx.AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
}
LOGI("AAudio Try to open %u hz %u bit chan %u %s samples %u",
LOGI("AAudio Try to open %u hz %u bit %u channels %s samples %u",
device->spec.freq, SDL_AUDIO_BITSIZE(device->spec.format),
device->spec.channels, SDL_AUDIO_ISBIGENDIAN(device->spec.format) ? "BE" : "LE", device->sample_frames);
@@ -370,7 +370,7 @@ static bool BuildAAudioStream(SDL_AudioDevice *device)
return false;
}
LOGI("AAudio Actually opened %u hz %u bit chan %u %s samples %u, buffers %d",
LOGI("AAudio Actually opened %u hz %u bit %u channels %s samples %u, buffers %d",
device->spec.freq, SDL_AUDIO_BITSIZE(device->spec.format),
device->spec.channels, SDL_AUDIO_ISBIGENDIAN(device->spec.format) ? "BE" : "LE", device->sample_frames, hidden->num_buffers);
@@ -386,9 +386,9 @@ static bool BuildAAudioStream(SDL_AudioDevice *device)
}
// !!! FIXME: make this non-blocking!
static void SDLCALL RequestAndroidPermissionBlockingCallback(void *userdata, const char *permission, SDL_bool granted)
static void SDLCALL RequestAndroidPermissionBlockingCallback(void *userdata, const char *permission, bool granted)
{
SDL_AtomicSet((SDL_AtomicInt *) userdata, granted ? 1 : -1);
SDL_SetAtomicInt((SDL_AtomicInt *) userdata, granted ? 1 : -1);
}
static bool AAUDIO_OpenDevice(SDL_AudioDevice *device)
@@ -402,16 +402,16 @@ static bool AAUDIO_OpenDevice(SDL_AudioDevice *device)
if (device->recording) {
// !!! FIXME: make this non-blocking!
SDL_AtomicInt permission_response;
SDL_AtomicSet(&permission_response, 0);
SDL_SetAtomicInt(&permission_response, 0);
if (!SDL_RequestAndroidPermission("android.permission.RECORD_AUDIO", RequestAndroidPermissionBlockingCallback, &permission_response)) {
return false;
}
while (SDL_AtomicGet(&permission_response) == 0) {
while (SDL_GetAtomicInt(&permission_response) == 0) {
SDL_Delay(10);
}
if (SDL_AtomicGet(&permission_response) < 0) {
if (SDL_GetAtomicInt(&permission_response) < 0) {
LOGI("This app doesn't have RECORD_AUDIO permission");
return SDL_SetError("This app doesn't have RECORD_AUDIO permission");
}

View File

@@ -265,7 +265,7 @@ static bool ALSA_WaitDevice(SDL_AudioDevice *device)
const int fulldelay = (int) ((((Uint64) device->sample_frames) * 1000) / device->spec.freq);
const int delay = SDL_max(fulldelay, 10);
while (!SDL_AtomicGet(&device->shutdown)) {
while (!SDL_GetAtomicInt(&device->shutdown)) {
const int rc = ALSA_snd_pcm_wait(device->hidden->pcm_handle, delay);
if (rc < 0 && (rc != -EAGAIN)) {
const int status = ALSA_snd_pcm_recover(device->hidden->pcm_handle, rc, 0);
@@ -294,7 +294,7 @@ static bool ALSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int bu
const int frame_size = SDL_AUDIO_FRAMESIZE(device->spec);
snd_pcm_uframes_t frames_left = (snd_pcm_uframes_t) (buflen / frame_size);
while ((frames_left > 0) && !SDL_AtomicGet(&device->shutdown)) {
while ((frames_left > 0) && !SDL_GetAtomicInt(&device->shutdown)) {
const int rc = ALSA_snd_pcm_writei(device->hidden->pcm_handle, sample_buf, frames_left);
//SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA PLAYDEVICE: WROTE %d of %d bytes", (rc >= 0) ? ((int) (rc * frame_size)) : rc, (int) (frames_left * frame_size));
SDL_assert(rc != 0); // assuming this can't happen if we used snd_pcm_wait and queried for available space.
@@ -825,10 +825,10 @@ static int SDLCALL ALSA_HotplugThread(void *arg)
{
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW);
while (!SDL_AtomicGet(&ALSA_hotplug_shutdown)) {
while (!SDL_GetAtomicInt(&ALSA_hotplug_shutdown)) {
// Block awhile before checking again, unless we're told to stop.
const Uint64 ticks = SDL_GetTicks() + 5000;
while (!SDL_AtomicGet(&ALSA_hotplug_shutdown) && SDL_GetTicks() < ticks) {
while (!SDL_GetAtomicInt(&ALSA_hotplug_shutdown) && SDL_GetTicks() < ticks) {
SDL_Delay(100);
}
@@ -853,7 +853,7 @@ static void ALSA_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevi
}
#if SDL_ALSA_HOTPLUG_THREAD
SDL_AtomicSet(&ALSA_hotplug_shutdown, 0);
SDL_SetAtomicInt(&ALSA_hotplug_shutdown, 0);
ALSA_hotplug_thread = SDL_CreateThread(ALSA_HotplugThread, "SDLHotplugALSA", NULL);
// if the thread doesn't spin, oh well, you just don't get further hotplug events.
#endif
@@ -866,7 +866,7 @@ static void ALSA_DeinitializeStart(void)
#if SDL_ALSA_HOTPLUG_THREAD
if (ALSA_hotplug_thread) {
SDL_AtomicSet(&ALSA_hotplug_shutdown, 1);
SDL_SetAtomicInt(&ALSA_hotplug_shutdown, 1);
SDL_WaitThread(ALSA_hotplug_thread, NULL);
ALSA_hotplug_thread = NULL;
}

View File

@@ -622,7 +622,7 @@ static void RecordingBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, A
// buffer is unexpectedly here? We're probably dying, but try to requeue this buffer anyhow.
if (device->hidden->current_buffer != NULL) {
SDL_assert(SDL_AtomicGet(&device->shutdown) != 0);
SDL_assert(SDL_GetAtomicInt(&device->shutdown) != 0);
COREAUDIO_FlushRecording(device); // just flush it manually, which will requeue it.
}
}
@@ -641,7 +641,7 @@ static void COREAUDIO_CloseDevice(SDL_AudioDevice *device)
}
if (device->hidden->thread) {
SDL_assert(SDL_AtomicGet(&device->shutdown) != 0); // should have been set by SDL_audio.c
SDL_assert(SDL_GetAtomicInt(&device->shutdown) != 0); // should have been set by SDL_audio.c
SDL_WaitThread(device->hidden->thread, NULL);
}
@@ -839,7 +839,7 @@ static int AudioQueueThreadEntry(void *arg)
SDL_SignalSemaphore(device->hidden->ready_semaphore);
// This would be WaitDevice/WaitRecordingDevice in the normal SDL audio thread, but we get *BufferReadyCallback calls here to know when to iterate.
while (!SDL_AtomicGet(&device->shutdown)) {
while (!SDL_GetAtomicInt(&device->shutdown)) {
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.10, 1);
}

View File

@@ -234,7 +234,7 @@ static bool DSOUND_WaitDevice(SDL_AudioDevice *device)
/* Semi-busy wait, since we have no way of getting play notification
on a primary mixing buffer located in hardware (DirectX 5.0)
*/
while (!SDL_AtomicGet(&device->shutdown)) {
while (!SDL_GetAtomicInt(&device->shutdown)) {
DWORD status = 0;
DWORD cursor = 0;
DWORD junk = 0;
@@ -336,7 +336,7 @@ static Uint8 *DSOUND_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size)
static bool DSOUND_WaitRecordingDevice(SDL_AudioDevice *device)
{
struct SDL_PrivateAudioData *h = device->hidden;
while (!SDL_AtomicGet(&device->shutdown)) {
while (!SDL_GetAtomicInt(&device->shutdown)) {
DWORD junk, cursor;
if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->capturebuf, &junk, &cursor) != DS_OK) {
return false;

View File

@@ -204,7 +204,7 @@ static bool DSP_WaitDevice(SDL_AudioDevice *device)
const unsigned long ioctlreq = device->recording ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE;
struct SDL_PrivateAudioData *h = device->hidden;
while (!SDL_AtomicGet(&device->shutdown)) {
while (!SDL_GetAtomicInt(&device->shutdown)) {
audio_buf_info info;
const int rc = ioctl(h->audio_fd, ioctlreq, &info);
if (rc < 0) {

View File

@@ -28,7 +28,7 @@
struct SDL_PrivateAudioData
{
Uint8 *mixbuf; // The file descriptor for the audio device
Uint32 io_delay; // miliseconds to sleep in WaitDevice.
Uint32 io_delay; // milliseconds to sleep in WaitDevice.
};
#endif // SDL_dummyaudio_h_

View File

@@ -203,7 +203,7 @@ static bool N3DSAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, i
static bool N3DSAUDIO_WaitDevice(SDL_AudioDevice *device)
{
contextLock(device);
while (!device->hidden->isCancelled && !SDL_AtomicGet(&device->shutdown) &&
while (!device->hidden->isCancelled && !SDL_GetAtomicInt(&device->shutdown) &&
device->hidden->waveBuf[device->hidden->nextbuf].status != NDSP_WBUF_FREE) {
CondVar_Wait(&device->hidden->cv, &device->hidden->lock);
}

View File

@@ -117,7 +117,7 @@ static void NETBSDAUDIO_Status(SDL_AudioDevice *device)
static bool NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device)
{
const bool recording = device->recording;
while (!SDL_AtomicGet(&device->shutdown)) {
while (!SDL_GetAtomicInt(&device->shutdown)) {
audio_info_t info;
const int rc = ioctl(device->hidden->audio_fd, AUDIO_GETINFO, &info);
if (rc < 0) {

View File

@@ -229,9 +229,9 @@ static void OPENSLES_DestroyPCMRecorder(SDL_AudioDevice *device)
}
// !!! FIXME: make this non-blocking!
static void SDLCALL RequestAndroidPermissionBlockingCallback(void *userdata, const char *permission, SDL_bool granted)
static void SDLCALL RequestAndroidPermissionBlockingCallback(void *userdata, const char *permission, bool granted)
{
SDL_AtomicSet((SDL_AtomicInt *) userdata, granted ? 1 : -1);
SDL_SetAtomicInt((SDL_AtomicInt *) userdata, granted ? 1 : -1);
}
static bool OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device)
@@ -250,16 +250,16 @@ static bool OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device)
// !!! FIXME: make this non-blocking!
{
SDL_AtomicInt permission_response;
SDL_AtomicSet(&permission_response, 0);
SDL_SetAtomicInt(&permission_response, 0);
if (!SDL_RequestAndroidPermission("android.permission.RECORD_AUDIO", RequestAndroidPermissionBlockingCallback, &permission_response)) {
return false;
}
while (SDL_AtomicGet(&permission_response) == 0) {
while (SDL_GetAtomicInt(&permission_response) == 0) {
SDL_Delay(10);
}
if (SDL_AtomicGet(&permission_response) < 0) {
if (SDL_GetAtomicInt(&permission_response) < 0) {
LOGE("This app doesn't have RECORD_AUDIO permission");
return SDL_SetError("This app doesn't have RECORD_AUDIO permission");
}
@@ -273,7 +273,7 @@ static bool OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device)
// Update the fragment size as size in bytes
SDL_UpdatedAudioDeviceFormat(device);
LOGI("Try to open %u hz %u bit chan %u %s samples %u",
LOGI("Try to open %u hz %u bit %u channels %s samples %u",
device->spec.freq, SDL_AUDIO_BITSIZE(device->spec.format),
device->spec.channels, (device->spec.format & 0x1000) ? "BE" : "LE", device->sample_frames);
@@ -453,7 +453,7 @@ static bool OPENSLES_CreatePCMPlayer(SDL_AudioDevice *device)
// Update the fragment size as size in bytes
SDL_UpdatedAudioDeviceFormat(device);
LOGI("Try to open %u hz %s %u bit chan %u %s samples %u",
LOGI("Try to open %u hz %s %u bit %u channels %s samples %u",
device->spec.freq, SDL_AUDIO_ISFLOAT(device->spec.format) ? "float" : "pcm", SDL_AUDIO_BITSIZE(device->spec.format),
device->spec.channels, (device->spec.format & 0x1000) ? "BE" : "LE", device->sample_frames);
@@ -652,7 +652,7 @@ static bool OPENSLES_WaitDevice(SDL_AudioDevice *device)
LOGV("OPENSLES_WaitDevice()");
while (!SDL_AtomicGet(&device->shutdown)) {
while (!SDL_GetAtomicInt(&device->shutdown)) {
// this semaphore won't fire when the app is in the background (OPENSLES_PauseDevices was called).
if (SDL_WaitSemaphoreTimeout(audiodata->playsem, 100)) {
return true; // semaphore was signaled, let's go!

View File

@@ -711,7 +711,7 @@ static bool hotplug_loop_init(void)
spa_list_init(&hotplug_pending_list);
spa_list_init(&hotplug_io_list);
hotplug_loop = PIPEWIRE_pw_thread_loop_new("SDLAudioHotplug", NULL);
hotplug_loop = PIPEWIRE_pw_thread_loop_new("SDLPwAudioPlug", NULL);
if (!hotplug_loop) {
return SDL_SetError("Pipewire: Failed to create hotplug detection loop (%i)", errno);
}
@@ -1215,6 +1215,7 @@ static void PIPEWIRE_DeinitializeStart(void)
static void PIPEWIRE_Deinitialize(void)
{
if (pipewire_initialized) {
hotplug_loop_destroy();
deinit_pipewire_library();
pipewire_initialized = false;
}
@@ -1270,7 +1271,6 @@ static bool PIPEWIRE_PREFERRED_Init(SDL_AudioDriverImpl *impl)
PIPEWIRE_pw_thread_loop_unlock(hotplug_loop);
if (no_devices || !pipewire_core_version_at_least(1, 0, 0)) {
hotplug_loop_destroy();
PIPEWIRE_Deinitialize();
return false;
}

View File

@@ -413,7 +413,7 @@ static bool PULSEAUDIO_WaitDevice(SDL_AudioDevice *device)
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
while (!SDL_AtomicGet(&device->shutdown) && (h->bytes_requested == 0)) {
while (!SDL_GetAtomicInt(&device->shutdown) && (h->bytes_requested == 0)) {
//SDL_Log("PULSEAUDIO WAIT IN WAITDEVICE!");
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop);
@@ -486,7 +486,7 @@ static bool PULSEAUDIO_WaitRecordingDevice(SDL_AudioDevice *device)
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
while (!SDL_AtomicGet(&device->shutdown)) {
while (!SDL_GetAtomicInt(&device->shutdown)) {
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop);
if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) {
//SDL_Log("PULSEAUDIO DEVICE FAILURE IN WAITRECORDINGDEVICE!");
@@ -553,7 +553,7 @@ static void PULSEAUDIO_FlushRecording(SDL_AudioDevice *device)
h->recordinglen = 0;
}
while (!SDL_AtomicGet(&device->shutdown) && (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0)) {
while (!SDL_GetAtomicInt(&device->shutdown) && (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0)) {
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop);
if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) {
//SDL_Log("PULSEAUDIO DEVICE FAILURE IN FLUSHRECORDING!");
@@ -901,7 +901,7 @@ static int SDLCALL HotplugThread(void *data)
SDL_SignalSemaphore((SDL_Semaphore *) data);
while (SDL_AtomicGet(&pulseaudio_hotplug_thread_active)) {
while (SDL_GetAtomicInt(&pulseaudio_hotplug_thread_active)) {
PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop);
if (op && PULSEAUDIO_pa_operation_get_state(op) != PA_OPERATION_RUNNING) {
PULSEAUDIO_pa_operation_unref(op);
@@ -956,9 +956,14 @@ static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_playback, SDL_Aud
}
// ok, we have a sane list, let's set up hotplug notifications now...
SDL_AtomicSet(&pulseaudio_hotplug_thread_active, 1);
pulseaudio_hotplug_thread = SDL_CreateThreadWithStackSize(HotplugThread, "PulseHotplug", 256 * 1024, ready_sem); // !!! FIXME: this can probably survive in significantly less stack space.
SDL_WaitSemaphore(ready_sem);
SDL_SetAtomicInt(&pulseaudio_hotplug_thread_active, 1);
pulseaudio_hotplug_thread = SDL_CreateThread(HotplugThread, "PulseHotplug", ready_sem);
if (pulseaudio_hotplug_thread) {
SDL_WaitSemaphore(ready_sem); // wait until the thread hits it's main loop.
} else {
SDL_SetAtomicInt(&pulseaudio_hotplug_thread_active, 0); // thread failed to start, we'll go on without hotplug.
}
SDL_DestroySemaphore(ready_sem);
}
@@ -973,7 +978,7 @@ static void PULSEAUDIO_DeinitializeStart(void)
{
if (pulseaudio_hotplug_thread) {
PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop);
SDL_AtomicSet(&pulseaudio_hotplug_thread_active, 0);
SDL_SetAtomicInt(&pulseaudio_hotplug_thread_active, 0);
PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0);
PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop);
SDL_WaitThread(pulseaudio_hotplug_thread, NULL);

View File

@@ -112,14 +112,14 @@ static bool QSA_WaitDevice(SDL_AudioDevice *device)
static bool QSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen)
{
if (SDL_AtomicGet(&device->shutdown) || !device->hidden) {
if (SDL_GetAtomicInt(&device->shutdown) || !device->hidden) {
return true;
}
int towrite = buflen;
// Write the audio data, checking for EAGAIN (buffer full) and underrun
while ((towrite > 0) && !SDL_AtomicGet(&device->shutdown));
while ((towrite > 0) && !SDL_GetAtomicInt(&device->shutdown));
const int bw = snd_pcm_plugin_write(device->hidden->audio_handle, buffer, towrite);
if (bw != towrite) {
// Check if samples playback got stuck somewhere in hardware or in the audio device driver

View File

@@ -151,7 +151,7 @@ static bool SNDIO_WaitDevice(SDL_AudioDevice *device)
{
const bool recording = device->recording;
while (!SDL_AtomicGet(&device->shutdown)) {
while (!SDL_GetAtomicInt(&device->shutdown)) {
if (SNDIO_sio_eof(device->hidden->dev)) {
return false;
}
@@ -200,7 +200,7 @@ static int SNDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen)
static void SNDIO_FlushRecording(SDL_AudioDevice *device)
{
char buf[512];
while (!SDL_AtomicGet(&device->shutdown) && (SNDIO_sio_read(device->hidden->dev, buf, sizeof(buf)) > 0)) {
while (!SDL_GetAtomicInt(&device->shutdown) && (SNDIO_sio_read(device->hidden->dev, buf, sizeof(buf)) > 0)) {
// do nothing
}
}

View File

@@ -137,7 +137,7 @@ static bool VITAAUD_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int
static bool VITAAUD_WaitDevice(SDL_AudioDevice *device)
{
// !!! FIXME: we might just need to sleep roughly as long as playback buffers take to process, based on sample rate, etc.
while (!SDL_AtomicGet(&device->shutdown) && (sceAudioOutGetRestSample(device->hidden->port) >= device->buffer_size)) {
while (!SDL_GetAtomicInt(&device->shutdown) && (sceAudioOutGetRestSample(device->hidden->port) >= device->buffer_size)) {
SDL_Delay(1);
}
return true;
@@ -176,7 +176,7 @@ static bool VITAAUD_WaitRecordingDevice(SDL_AudioDevice *device)
// there's only a blocking call to obtain more data, so we'll just sleep as
// long as a buffer would run.
const Uint64 endticks = SDL_GetTicks() + ((device->sample_frames * 1000) / device->spec.freq);
while (!SDL_AtomicGet(&device->shutdown) && (SDL_GetTicks() < endticks)) {
while (!SDL_GetAtomicInt(&device->shutdown) && (SDL_GetTicks() < endticks)) {
SDL_Delay(1);
}
return true;

View File

@@ -74,11 +74,11 @@ static void ManagementThreadMainloop(void)
{
SDL_LockMutex(ManagementThreadLock);
ManagementThreadPendingTask *task;
while (((task = (ManagementThreadPendingTask *)SDL_AtomicGetPointer((void **)&ManagementThreadPendingTasks)) != NULL) || !SDL_AtomicGet(&ManagementThreadShutdown)) {
while (((task = (ManagementThreadPendingTask *)SDL_GetAtomicPointer((void **)&ManagementThreadPendingTasks)) != NULL) || !SDL_GetAtomicInt(&ManagementThreadShutdown)) {
if (!task) {
SDL_WaitCondition(ManagementThreadCondition, ManagementThreadLock); // block until there's something to do.
} else {
SDL_AtomicSetPointer((void **) &ManagementThreadPendingTasks, task->next); // take task off the pending list.
SDL_SetAtomicPointer((void **) &ManagementThreadPendingTasks, task->next); // take task off the pending list.
SDL_UnlockMutex(ManagementThreadLock); // let other things add to the list while we chew on this task.
task->result = task->fn(task->userdata); // run this task.
if (task->task_complete_sem) { // something waiting on result?
@@ -101,7 +101,7 @@ bool WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, b
return true; // completed!
}
if (SDL_AtomicGet(&ManagementThreadShutdown)) {
if (SDL_GetAtomicInt(&ManagementThreadShutdown)) {
return SDL_SetError("Can't add task, we're shutting down");
}
@@ -127,14 +127,14 @@ bool WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, b
// add to end of task list.
ManagementThreadPendingTask *prev = NULL;
for (ManagementThreadPendingTask *i = (ManagementThreadPendingTask *)SDL_AtomicGetPointer((void **)&ManagementThreadPendingTasks); i; i = i->next) {
for (ManagementThreadPendingTask *i = (ManagementThreadPendingTask *)SDL_GetAtomicPointer((void **)&ManagementThreadPendingTasks); i; i = i->next) {
prev = i;
}
if (prev) {
prev->next = pending;
} else {
SDL_AtomicSetPointer((void **) &ManagementThreadPendingTasks, pending);
SDL_SetAtomicPointer((void **) &ManagementThreadPendingTasks, pending);
}
// task is added to the end of the pending list, let management thread rip!
@@ -210,8 +210,8 @@ static bool InitManagementThread(void)
return false;
}
SDL_AtomicSetPointer((void **) &ManagementThreadPendingTasks, NULL);
SDL_AtomicSet(&ManagementThreadShutdown, 0);
SDL_SetAtomicPointer((void **) &ManagementThreadPendingTasks, NULL);
SDL_SetAtomicInt(&ManagementThreadShutdown, 0);
ManagementThread = SDL_CreateThreadWithStackSize(ManagementThreadEntry, "SDLWASAPIMgmt", 256 * 1024, &mgmtdata); // !!! FIXME: maybe even smaller stack size?
if (!ManagementThread) {
return false;
@@ -234,7 +234,7 @@ static bool InitManagementThread(void)
static void DeinitManagementThread(void)
{
if (ManagementThread) {
SDL_AtomicSet(&ManagementThreadShutdown, 1);
SDL_SetAtomicInt(&ManagementThreadShutdown, 1);
SDL_LockMutex(ManagementThreadLock);
SDL_SignalCondition(ManagementThreadCondition);
SDL_UnlockMutex(ManagementThreadLock);
@@ -242,13 +242,13 @@ static void DeinitManagementThread(void)
ManagementThread = NULL;
}
SDL_assert(SDL_AtomicGetPointer((void **) &ManagementThreadPendingTasks) == NULL);
SDL_assert(SDL_GetAtomicPointer((void **) &ManagementThreadPendingTasks) == NULL);
SDL_DestroyCondition(ManagementThreadCondition);
SDL_DestroyMutex(ManagementThreadLock);
ManagementThreadCondition = NULL;
ManagementThreadLock = NULL;
SDL_AtomicSet(&ManagementThreadShutdown, 0);
SDL_SetAtomicInt(&ManagementThreadShutdown, 0);
}
typedef struct
@@ -325,12 +325,6 @@ static bool mgmtthrtask_CoTaskMemFree(void *userdata)
return true;
}
static bool mgmtthrtask_PlatformDeleteActivationHandler(void *userdata)
{
WASAPI_PlatformDeleteActivationHandler(userdata);
return true;
}
static bool mgmtthrtask_CloseHandle(void *userdata)
{
CloseHandle((HANDLE) userdata);
@@ -370,12 +364,6 @@ static void ResetWasapiDevice(SDL_AudioDevice *device)
WASAPI_ProxyToManagementThread(mgmtthrtask_CoTaskMemFree, ptr, NULL);
}
if (device->hidden->activation_handler) {
void *activation_handler = device->hidden->activation_handler;
device->hidden->activation_handler = NULL;
WASAPI_ProxyToManagementThread(mgmtthrtask_PlatformDeleteActivationHandler, activation_handler, NULL);
}
if (device->hidden->event) {
HANDLE event = device->hidden->event;
device->hidden->event = NULL;
@@ -415,14 +403,14 @@ static bool RecoverWasapiDevice(SDL_AudioDevice *device)
// do not call when holding the device lock!
static bool RecoverWasapiIfLost(SDL_AudioDevice *device)
{
if (SDL_AtomicGet(&device->shutdown)) {
if (SDL_GetAtomicInt(&device->shutdown)) {
return false; // already failed.
} else if (device->hidden->device_dead) { // had a fatal error elsewhere, clean up and quit
IAudioClient_Stop(device->hidden->client);
WASAPI_DisconnectDevice(device);
SDL_assert(SDL_AtomicGet(&device->shutdown)); // so we don't come back through here.
SDL_assert(SDL_GetAtomicInt(&device->shutdown)); // so we don't come back through here.
return false; // already failed.
} else if (SDL_AtomicGet(&device->zombie)) {
} else if (SDL_GetAtomicInt(&device->zombie)) {
return false; // we're already dead, so just leave and let the Zombie implementations take over.
} else if (!device->hidden->client) {
return true; // still waiting for activation.
@@ -550,7 +538,7 @@ static void WASAPI_FlushRecording(SDL_AudioDevice *device)
DWORD flags = 0;
// just read until we stop getting packets, throwing them away.
while (!SDL_AtomicGet(&device->shutdown) && device->hidden->capture) {
while (!SDL_GetAtomicInt(&device->shutdown) && device->hidden->capture) {
const HRESULT ret = IAudioCaptureClient_GetBuffer(device->hidden->capture, &ptr, &frames, &flags, NULL, NULL);
if (ret == AUDCLNT_S_BUFFER_EMPTY) {
break; // no more buffered data; we're done.
@@ -592,7 +580,7 @@ static bool mgmtthrtask_PrepDevice(void *userdata)
IAudioClient *client = device->hidden->client;
SDL_assert(client != NULL);
#if defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) // CreateEventEx() arrived in Vista, so we need an #ifdef for XP.
#if defined(SDL_PLATFORM_GDK) // CreateEventEx() arrived in Vista, so we need an #ifdef for XP.
device->hidden->event = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS);
#else
device->hidden->event = CreateEventW(NULL, 0, 0, NULL);

View File

@@ -42,10 +42,9 @@ struct SDL_PrivateAudioData
int framesize;
bool device_lost;
bool device_dead;
void *activation_handler;
};
// win32 and winrt implementations call into these.
// win32 implementation calls into these.
bool WASAPI_PrepDevice(SDL_AudioDevice *device);
void WASAPI_DisconnectDevice(SDL_AudioDevice *device); // don't hold the device lock when calling this!
@@ -54,7 +53,7 @@ void WASAPI_DisconnectDevice(SDL_AudioDevice *device); // don't hold the device
typedef bool (*ManagementThreadTask)(void *userdata);
bool WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, bool *wait_until_complete);
// These are functions that are implemented differently for Windows vs WinRT.
// These are functions that are (were...?) implemented differently for various Windows versions.
// UNLESS OTHERWISE NOTED THESE ALL HAPPEN ON THE MANAGEMENT THREAD.
bool WASAPI_PlatformInit(void);
void WASAPI_PlatformDeinit(void);
@@ -63,7 +62,6 @@ void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevi
bool WASAPI_ActivateDevice(SDL_AudioDevice *device);
void WASAPI_PlatformThreadInit(SDL_AudioDevice *device); // this happens on the audio device thread, not the management thread.
void WASAPI_PlatformThreadDeinit(SDL_AudioDevice *device); // this happens on the audio device thread, not the management thread.
void WASAPI_PlatformDeleteActivationHandler(void *handler);
void WASAPI_PlatformFreeDeviceHandle(SDL_AudioDevice *device);
#ifdef __cplusplus

View File

@@ -20,13 +20,14 @@
*/
#include "SDL_internal.h"
/* This is code that Windows uses to talk to WASAPI-related system APIs.
/* !!! FIXME: merge this all into SDL_wasapi.c, now that WinRT is gone.
This is code that Windows uses to talk to WASAPI-related system APIs.
This is for non-WinRT desktop apps. The C++/CX implementation of these
functions, exclusive to WinRT, are in SDL_wasapi_winrt.cpp.
The code in SDL_wasapi.c is used by both standard Windows and WinRT builds
to deal with audio and calls into these functions. */
#if defined(SDL_AUDIO_DRIVER_WASAPI) && !defined(SDL_PLATFORM_WINRT)
#if defined(SDL_AUDIO_DRIVER_WASAPI)
#include "../../core/windows/SDL_windows.h"
#include "../../core/windows/SDL_immdevice.h"
@@ -191,15 +192,9 @@ void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevi
SDL_IMMDevice_EnumerateEndpoints(default_playback, default_recording);
}
void WASAPI_PlatformDeleteActivationHandler(void *handler)
{
// not asynchronous.
SDL_assert(!"This function should have only been called on WinRT.");
}
void WASAPI_PlatformFreeDeviceHandle(SDL_AudioDevice *device)
{
SDL_IMMDevice_FreeDeviceHandle(device);
}
#endif // SDL_AUDIO_DRIVER_WASAPI && !defined(SDL_PLATFORM_WINRT)
#endif // SDL_AUDIO_DRIVER_WASAPI

View File

@@ -1,360 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
// This is C++/CX code that the WinRT port uses to talk to WASAPI-related
// system APIs. The C implementation of these functions, for non-WinRT apps,
// is in SDL_wasapi_win32.c. The code in SDL_wasapi.c is used by both standard
// Windows and WinRT builds to deal with audio and calls into these functions.
#if defined(SDL_AUDIO_DRIVER_WASAPI) && defined(SDL_PLATFORM_WINRT)
#include <Windows.h>
#include <windows.ui.core.h>
#include <windows.devices.enumeration.h>
#include <windows.media.devices.h>
#include <wrl/implements.h>
#include <collection.h>
extern "C" {
#include "../../core/windows/SDL_windows.h"
#include "../SDL_sysaudio.h"
}
#define COBJMACROS
#include <mmdeviceapi.h>
#include <audioclient.h>
#include "SDL_wasapi.h"
using namespace Windows::Devices::Enumeration;
using namespace Windows::Media::Devices;
using namespace Windows::Foundation;
using namespace Microsoft::WRL;
static Platform::String ^ SDL_PKEY_AudioEngine_DeviceFormat = L"{f19f064d-082c-4e27-bc73-6882a1bb8e4c} 0";
static bool FindWinRTAudioDeviceCallback(SDL_AudioDevice *device, void *userdata)
{
return (SDL_wcscmp((LPCWSTR) device->handle, (LPCWSTR) userdata) == 0);
}
static SDL_AudioDevice *FindWinRTAudioDevice(LPCWSTR devid)
{
return SDL_FindPhysicalAudioDeviceByCallback(FindWinRTAudioDeviceCallback, (void *) devid);
}
class SDL_WasapiDeviceEventHandler
{
public:
SDL_WasapiDeviceEventHandler(const bool _recording);
~SDL_WasapiDeviceEventHandler();
void OnDeviceAdded(DeviceWatcher ^ sender, DeviceInformation ^ args);
void OnDeviceRemoved(DeviceWatcher ^ sender, DeviceInformationUpdate ^ args);
void OnDeviceUpdated(DeviceWatcher ^ sender, DeviceInformationUpdate ^ args);
void OnEnumerationCompleted(DeviceWatcher ^ sender, Platform::Object ^ args);
void OnDefaultRenderDeviceChanged(Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args);
void OnDefaultCaptureDeviceChanged(Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args);
void WaitForCompletion();
private:
SDL_Semaphore *completed_semaphore;
const bool recording;
DeviceWatcher ^ watcher;
Windows::Foundation::EventRegistrationToken added_handler;
Windows::Foundation::EventRegistrationToken removed_handler;
Windows::Foundation::EventRegistrationToken updated_handler;
Windows::Foundation::EventRegistrationToken completed_handler;
Windows::Foundation::EventRegistrationToken default_changed_handler;
};
SDL_WasapiDeviceEventHandler::SDL_WasapiDeviceEventHandler(const bool _recording)
: recording(_recording), completed_semaphore(SDL_CreateSemaphore(0))
{
if (!completed_semaphore) {
return; // uhoh.
}
Platform::String ^ selector = _recording ? MediaDevice::GetAudioCaptureSelector() : MediaDevice::GetAudioRenderSelector();
Platform::Collections::Vector<Platform::String ^> properties;
properties.Append(SDL_PKEY_AudioEngine_DeviceFormat);
watcher = DeviceInformation::CreateWatcher(selector, properties.GetView());
if (!watcher)
return; // uhoh.
// !!! FIXME: this doesn't need a lambda here, I think, if I make SDL_WasapiDeviceEventHandler a proper C++/CX class. --ryan.
added_handler = watcher->Added += ref new TypedEventHandler<DeviceWatcher ^, DeviceInformation ^>([this](DeviceWatcher ^ sender, DeviceInformation ^ args) { OnDeviceAdded(sender, args); });
removed_handler = watcher->Removed += ref new TypedEventHandler<DeviceWatcher ^, DeviceInformationUpdate ^>([this](DeviceWatcher ^ sender, DeviceInformationUpdate ^ args) { OnDeviceRemoved(sender, args); });
updated_handler = watcher->Updated += ref new TypedEventHandler<DeviceWatcher ^, DeviceInformationUpdate ^>([this](DeviceWatcher ^ sender, DeviceInformationUpdate ^ args) { OnDeviceUpdated(sender, args); });
completed_handler = watcher->EnumerationCompleted += ref new TypedEventHandler<DeviceWatcher ^, Platform::Object ^>([this](DeviceWatcher ^ sender, Platform::Object ^ args) { OnEnumerationCompleted(sender, args); });
if (recording) {
default_changed_handler = MediaDevice::DefaultAudioCaptureDeviceChanged += ref new TypedEventHandler<Platform::Object ^, DefaultAudioCaptureDeviceChangedEventArgs ^>([this](Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) { OnDefaultCaptureDeviceChanged(sender, args); });
} else {
default_changed_handler = MediaDevice::DefaultAudioRenderDeviceChanged += ref new TypedEventHandler<Platform::Object ^, DefaultAudioRenderDeviceChangedEventArgs ^>([this](Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) { OnDefaultRenderDeviceChanged(sender, args); });
}
watcher->Start();
}
SDL_WasapiDeviceEventHandler::~SDL_WasapiDeviceEventHandler()
{
if (watcher) {
watcher->Added -= added_handler;
watcher->Removed -= removed_handler;
watcher->Updated -= updated_handler;
watcher->EnumerationCompleted -= completed_handler;
watcher->Stop();
watcher = nullptr;
}
if (completed_semaphore) {
SDL_DestroySemaphore(completed_semaphore);
completed_semaphore = nullptr;
}
if (recording) {
MediaDevice::DefaultAudioCaptureDeviceChanged -= default_changed_handler;
} else {
MediaDevice::DefaultAudioRenderDeviceChanged -= default_changed_handler;
}
}
void SDL_WasapiDeviceEventHandler::OnDeviceAdded(DeviceWatcher ^ sender, DeviceInformation ^ info)
{
/* You can have multiple endpoints on a device that are mutually exclusive ("Speakers" vs "Line Out" or whatever).
In a perfect world, things that are unplugged won't be in this collection. The only gotcha is probably for
phones and tablets, where you might have an internal speaker and a headphone jack and expect both to be
available and switch automatically. (!!! FIXME...?) */
SDL_assert(sender == this->watcher);
char *utf8dev = WIN_StringToUTF8W(info->Name->Data());
if (utf8dev) {
SDL_AudioSpec spec;
SDL_zero(spec);
Platform::Object ^ obj = info->Properties->Lookup(SDL_PKEY_AudioEngine_DeviceFormat);
if (obj) {
IPropertyValue ^ property = (IPropertyValue ^) obj;
Platform::Array<unsigned char> ^ data;
property->GetUInt8Array(&data);
WAVEFORMATEXTENSIBLE fmt;
SDL_zero(fmt);
SDL_memcpy(&fmt, data->Data, SDL_min(data->Length, sizeof(WAVEFORMATEXTENSIBLE)));
spec.channels = (Uint8)fmt.Format.nChannels;
spec.freq = fmt.Format.nSamplesPerSec;
spec.format = SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)&fmt);
}
LPWSTR devid = SDL_wcsdup(info->Id->Data());
if (devid) {
SDL_AddAudioDevice(this->recording, utf8dev, spec.channels ? &spec : NULL, devid);
}
SDL_free(utf8dev);
}
}
void SDL_WasapiDeviceEventHandler::OnDeviceRemoved(DeviceWatcher ^ sender, DeviceInformationUpdate ^ info)
{
SDL_assert(sender == this->watcher);
WASAPI_DisconnectDevice(FindWinRTAudioDevice(info->Id->Data()));
}
void SDL_WasapiDeviceEventHandler::OnDeviceUpdated(DeviceWatcher ^ sender, DeviceInformationUpdate ^ args)
{
SDL_assert(sender == this->watcher);
}
void SDL_WasapiDeviceEventHandler::OnEnumerationCompleted(DeviceWatcher ^ sender, Platform::Object ^ args)
{
SDL_assert(sender == this->watcher);
if (this->completed_semaphore) {
SDL_SignalSemaphore(this->completed_semaphore);
}
}
void SDL_WasapiDeviceEventHandler::OnDefaultRenderDeviceChanged(Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args)
{
SDL_assert(!this->recording);
SDL_DefaultAudioDeviceChanged(FindWinRTAudioDevice(args->Id->Data()));
}
void SDL_WasapiDeviceEventHandler::OnDefaultCaptureDeviceChanged(Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args)
{
SDL_assert(this->recording);
SDL_DefaultAudioDeviceChanged(FindWinRTAudioDevice(args->Id->Data()));
}
void SDL_WasapiDeviceEventHandler::WaitForCompletion()
{
if (this->completed_semaphore) {
SDL_WaitSemaphore(this->completed_semaphore);
SDL_DestroySemaphore(this->completed_semaphore);
this->completed_semaphore = nullptr;
}
}
static SDL_WasapiDeviceEventHandler *playback_device_event_handler;
static SDL_WasapiDeviceEventHandler *recording_device_event_handler;
bool WASAPI_PlatformInit(void)
{
return true;
}
static void StopWasapiHotplug(void)
{
delete playback_device_event_handler;
playback_device_event_handler = nullptr;
delete recording_device_event_handler;
recording_device_event_handler = nullptr;
}
void WASAPI_PlatformDeinit(void)
{
StopWasapiHotplug();
}
void WASAPI_PlatformDeinitializeStart(void)
{
StopWasapiHotplug();
}
void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
{
Platform::String ^ defdevid;
// DeviceWatchers will fire an Added event for each existing device at
// startup, so we don't need to enumerate them separately before
// listening for updates.
playback_device_event_handler = new SDL_WasapiDeviceEventHandler(false);
playback_device_event_handler->WaitForCompletion();
defdevid = MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default);
if (defdevid) {
*default_playback = FindWinRTAudioDevice(defdevid->Data());
}
recording_device_event_handler = new SDL_WasapiDeviceEventHandler(true);
recording_device_event_handler->WaitForCompletion();
defdevid = MediaDevice::GetDefaultAudioCaptureId(AudioDeviceRole::Default);
if (defdevid) {
*default_recording = FindWinRTAudioDevice(defdevid->Data());
}
}
class SDL_WasapiActivationHandler : public RuntimeClass<RuntimeClassFlags<ClassicCom>, FtmBase, IActivateAudioInterfaceCompletionHandler>
{
public:
SDL_WasapiActivationHandler() : completion_semaphore(SDL_CreateSemaphore(0)) { SDL_assert(completion_semaphore != NULL); }
STDMETHOD(ActivateCompleted)(IActivateAudioInterfaceAsyncOperation *operation);
void WaitForCompletion();
private:
SDL_Semaphore *completion_semaphore;
};
void SDL_WasapiActivationHandler::WaitForCompletion()
{
if (completion_semaphore) {
SDL_WaitSemaphore(completion_semaphore);
SDL_DestroySemaphore(completion_semaphore);
completion_semaphore = NULL;
}
}
HRESULT
SDL_WasapiActivationHandler::ActivateCompleted(IActivateAudioInterfaceAsyncOperation *async)
{
// Just set a flag, since we're probably in a different thread. We'll pick it up and init everything on our own thread to prevent races.
SDL_SignalSemaphore(completion_semaphore);
return S_OK;
}
void WASAPI_PlatformDeleteActivationHandler(void *handler)
{
((SDL_WasapiActivationHandler *)handler)->Release();
}
bool WASAPI_ActivateDevice(SDL_AudioDevice *device)
{
LPCWSTR devid = (LPCWSTR) device->handle;
SDL_assert(devid != NULL);
ComPtr<SDL_WasapiActivationHandler> handler = Make<SDL_WasapiActivationHandler>();
if (handler == nullptr) {
return SDL_SetError("Failed to allocate WASAPI activation handler");
}
handler.Get()->AddRef(); // we hold a reference after ComPtr destructs on return, causing a Release, and Release ourselves in WASAPI_PlatformDeleteActivationHandler(), etc.
device->hidden->activation_handler = handler.Get();
IActivateAudioInterfaceAsyncOperation *async = nullptr;
const HRESULT ret = ActivateAudioInterfaceAsync(devid, __uuidof(IAudioClient), nullptr, handler.Get(), &async);
if (FAILED(ret) || async == nullptr) {
if (async != nullptr) {
async->Release();
}
handler.Get()->Release();
return WIN_SetErrorFromHRESULT("WASAPI can't activate requested audio endpoint", ret);
}
// !!! FIXME: the problems in SDL2 that needed this to be synchronous are _probably_ solved by SDL3, and this can block indefinitely if a user prompt is shown to get permission to use a microphone.
handler.Get()->WaitForCompletion(); // block here until we have an answer, so this is synchronous to us after all.
HRESULT activateRes = S_OK;
IUnknown *iunknown = nullptr;
const HRESULT getActivateRes = async->GetActivateResult(&activateRes, &iunknown);
async->Release();
if (FAILED(getActivateRes)) {
return WIN_SetErrorFromHRESULT("Failed to get WASAPI activate result", getActivateRes);
} else if (FAILED(activateRes)) {
return WIN_SetErrorFromHRESULT("Failed to activate WASAPI device", activateRes);
}
iunknown->QueryInterface(IID_PPV_ARGS(&device->hidden->client));
if (!device->hidden->client) {
return SDL_SetError("Failed to query WASAPI client interface");
}
if (!WASAPI_PrepDevice(device)) {
return false;
}
return true;
}
void WASAPI_PlatformThreadInit(SDL_AudioDevice *device)
{
// !!! FIXME: set this thread to "Pro Audio" priority.
SDL_SetThreadPriority(device->recording ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL);
}
void WASAPI_PlatformThreadDeinit(SDL_AudioDevice *device)
{
// !!! FIXME: set this thread to "Pro Audio" priority.
}
void WASAPI_PlatformFreeDeviceHandle(SDL_AudioDevice *device)
{
SDL_free(device->handle);
}
#endif // SDL_AUDIO_DRIVER_WASAPI && defined(SDL_PLATFORM_WINRT)