Browse Source

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.
Ryan C. Gordon 2 years ago
parent
commit
8ff738f234
1 changed files with 20 additions and 0 deletions
  1. 20 0
      src/audio/SDL_audio.c

+ 20 - 0
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);