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.
Ryan C. Gordon 2018-08-07 13:04:15 -04:00
parent e714f6590e
commit 56f44cfa0f
1 changed files with 19 additions and 9 deletions

View File

@ -451,7 +451,11 @@ void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
SDL_assert(get_audio_device(device->id) == device); SDL_assert(get_audio_device(device->id) == device);
if (!SDL_AtomicGet(&device->enabled)) { 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 /* Ends the audio callback and mark the device as STOPPED, but the
@ -1056,16 +1060,14 @@ close_audio_device(SDL_AudioDevice * device)
return; return;
} }
if (device->id > 0) { /* make sure the device is paused before we do anything else, so the
SDL_AudioDevice *opendev = open_devices[device->id - 1]; audio callback definitely won't fire again. */
SDL_assert((opendev == device) || (opendev == NULL)); current_audio.impl.LockDevice(device);
if (opendev == device) { SDL_AtomicSet(&device->paused, 1);
open_devices[device->id - 1] = NULL;
}
}
SDL_AtomicSet(&device->shutdown, 1); SDL_AtomicSet(&device->shutdown, 1);
SDL_AtomicSet(&device->enabled, 0); SDL_AtomicSet(&device->enabled, 0);
current_audio.impl.UnlockDevice(device);
if (device->thread != NULL) { if (device->thread != NULL) {
SDL_WaitThread(device->thread, NULL); SDL_WaitThread(device->thread, NULL);
} }
@ -1076,6 +1078,14 @@ close_audio_device(SDL_AudioDevice * device)
SDL_free(device->work_buffer); SDL_free(device->work_buffer);
SDL_FreeAudioStream(device->stream); 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) { if (device->hidden != NULL) {
current_audio.impl.CloseDevice(device); current_audio.impl.CloseDevice(device);
} }