audio: Deal with device shutdown more carefully. This would cause problems in various ways, but specifically triggers an assert when you close a WASAPI capture device in an app running over RDP. Related to (but not the actual bug) in Bugzilla #3924.
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 43 44 45 46 47 48 49 50 51 52 53 54 55
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index 364e25e..23daf00 100644
--- a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -451,7 +451,11 @@ void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
SDL_assert(get_audio_device(device->id) == device);
if (!SDL_AtomicGet(&device->enabled)) {
- return;
+ return; /* don't report disconnects more than once. */
+ }
+
+ if (SDL_AtomicGet(&device->shutdown)) {
+ return; /* don't report disconnect if we're trying to close device. */
}
/* Ends the audio callback and mark the device as STOPPED, but the
@@ -1056,16 +1060,14 @@ close_audio_device(SDL_AudioDevice * device)
return;
}
- if (device->id > 0) {
- SDL_AudioDevice *opendev = open_devices[device->id - 1];
- SDL_assert((opendev == device) || (opendev == NULL));
- if (opendev == device) {
- open_devices[device->id - 1] = NULL;
- }
- }
-
+ /* make sure the device is paused before we do anything else, so the
+ audio callback definitely won't fire again. */
+ current_audio.impl.LockDevice(device);
+ SDL_AtomicSet(&device->paused, 1);
SDL_AtomicSet(&device->shutdown, 1);
SDL_AtomicSet(&device->enabled, 0);
+ current_audio.impl.UnlockDevice(device);
+
if (device->thread != NULL) {
SDL_WaitThread(device->thread, NULL);
}
@@ -1076,6 +1078,14 @@ close_audio_device(SDL_AudioDevice * device)
SDL_free(device->work_buffer);
SDL_FreeAudioStream(device->stream);
+ if (device->id > 0) {
+ SDL_AudioDevice *opendev = open_devices[device->id - 1];
+ SDL_assert((opendev == device) || (opendev == NULL));
+ if (opendev == device) {
+ open_devices[device->id - 1] = NULL;
+ }
+ }
+
if (device->hidden != NULL) {
current_audio.impl.CloseDevice(device);
}