ensure SDL_AUDIODEVICEREMOVED gets sent when hotplug removes a device

James Zipperer

The problem I was seeing was that the the ALSA hotplug thread would call SDL_RemoveAudioDevice, but my application code was not seeing an SDL_AUDIODEVICEREMOVED event to go along with it.   To fix it, I added some code into SDL_RemoveAudioDevice to call SDL_OpenedAudioDeviceDisconnected on the corresponding open audio device.  There didn't appear to be a way to cross reference the handle that SDL_RemoveAudioDevice gets and the SDL_AudioDevice pointer that SDL_OpenedAudioDeviceDisconnected needs, so I ended up adding a void *handle field to struct SDL_AudioDevice so that I could do the cross reference.

Is there some other way beside adding a void *handle field to the struct to get the proper information for SDL_OpenedAudioDeviceDisconnected?
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index f9cd736..9749a2d 100644
--- a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -408,13 +408,26 @@
 void
 SDL_RemoveAudioDevice(const int iscapture, void *handle)
 {
+    int device_index;
+    SDL_AudioDevice *device = NULL;
+
     SDL_LockMutex(current_audio.detectionLock);
     if (iscapture) {
         mark_device_removed(handle, current_audio.inputDevices, &current_audio.captureDevicesRemoved);
     } else {
         mark_device_removed(handle, current_audio.outputDevices, &current_audio.outputDevicesRemoved);
     }
+    for (device_index = 0; device_index < SDL_arraysize(open_devices); device_index++)
+    {
+        device = open_devices[device_index];
+        if (device != NULL && device->handle == handle)
+        {
+            SDL_OpenedAudioDeviceDisconnected(device);
+            break;
+        }
+    }
     SDL_UnlockMutex(current_audio.detectionLock);
+
     current_audio.impl.FreeDeviceHandle(handle);
 }
 
@@ -1254,6 +1267,7 @@
     device->id = id + 1;
     device->spec = *obtained;
     device->iscapture = iscapture ? SDL_TRUE : SDL_FALSE;
+    device->handle = handle;
 
     SDL_AtomicSet(&device->shutdown, 0);  /* just in case. */
     SDL_AtomicSet(&device->paused, 1);
diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h
index 1bb1324..73a2cfb 100644
--- a/src/audio/SDL_sysaudio.h
+++ b/src/audio/SDL_sysaudio.h
@@ -187,6 +187,8 @@
     /* * * */
     /* Data private to this driver */
     struct SDL_PrivateAudioData *hidden;
+
+    void *handle;
 };
 #undef _THIS