audio: Report SDL_AUDIODEVICEREMOVED for unopened devices. Unopened devices, if removed, now send SDL_AUDIODEVICEREMOVED events with a `which` field set to zero. Apps can use this to decide if they need to refresh a list of devices being shown in an options menu, etc. It's safe to call SDL_CloseAudioDevice(0), so even if they try to clean up this bogus id, it should be safe. Fixes #5199.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index 949d650..e2f7412 100644
--- a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -527,6 +527,7 @@ SDL_RemoveAudioDevice(const SDL_bool iscapture, void *handle)
{
int device_index;
SDL_AudioDevice *device = NULL;
+ SDL_bool device_was_opened = SDL_FALSE;
SDL_LockMutex(current_audio.detectionLock);
if (iscapture) {
@@ -539,10 +540,29 @@ SDL_RemoveAudioDevice(const SDL_bool iscapture, void *handle)
device = open_devices[device_index];
if (device != NULL && device->handle == handle)
{
+ device_was_opened = SDL_TRUE;
SDL_OpenedAudioDeviceDisconnected(device);
break;
}
}
+
+ /* Devices that aren't opened, as of 2.24.0, will post an
+ SDL_AUDIODEVICEREMOVED event with the `which` field set to zero.
+ Apps can use this to decide if they need to refresh a list of
+ available devices instead of closing an opened one.
+ Note that opened devices will send the non-zero event in
+ SDL_OpenedAudioDeviceDisconnected(). */
+ if (!device_was_opened) {
+ if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
+ SDL_Event event;
+ SDL_zero(event);
+ event.adevice.type = SDL_AUDIODEVICEREMOVED;
+ event.adevice.which = 0;
+ event.adevice.iscapture = iscapture ? 1 : 0;
+ SDL_PushEvent(&event);
+ }
+ }
+
SDL_UnlockMutex(current_audio.detectionLock);
current_audio.impl.FreeDeviceHandle(handle);