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.
This commit is contained in:
Ryan C. Gordon 2022-07-26 12:40:47 -04:00
parent 5d85c7d300
commit 8ff738f234
No known key found for this signature in database
GPG key ID: FA148B892AB48044

View file

@ -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);