audio: Deal with device shutdown more carefully.
authorRyan C. Gordon <icculus@icculus.org>
Tue, 07 Aug 2018 13:04:15 -0400
changeset 1207816bb2e8488b8
parent 12077 ca1bbc8b04a1
child 12079 8ffd9de57415
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.
src/audio/SDL_audio.c
     1.1 --- a/src/audio/SDL_audio.c	Tue Aug 07 12:06:31 2018 -0400
     1.2 +++ b/src/audio/SDL_audio.c	Tue Aug 07 13:04:15 2018 -0400
     1.3 @@ -451,7 +451,11 @@
     1.4      SDL_assert(get_audio_device(device->id) == device);
     1.5  
     1.6      if (!SDL_AtomicGet(&device->enabled)) {
     1.7 -        return;
     1.8 +        return;  /* don't report disconnects more than once. */
     1.9 +    }
    1.10 +
    1.11 +    if (SDL_AtomicGet(&device->shutdown)) {
    1.12 +        return;  /* don't report disconnect if we're trying to close device. */
    1.13      }
    1.14  
    1.15      /* Ends the audio callback and mark the device as STOPPED, but the
    1.16 @@ -1056,16 +1060,14 @@
    1.17          return;
    1.18      }
    1.19  
    1.20 -    if (device->id > 0) {
    1.21 -        SDL_AudioDevice *opendev = open_devices[device->id - 1];
    1.22 -        SDL_assert((opendev == device) || (opendev == NULL));
    1.23 -        if (opendev == device) {
    1.24 -            open_devices[device->id - 1] = NULL;
    1.25 -        }
    1.26 -    }
    1.27 -
    1.28 +    /* make sure the device is paused before we do anything else, so the
    1.29 +       audio callback definitely won't fire again. */
    1.30 +    current_audio.impl.LockDevice(device);
    1.31 +    SDL_AtomicSet(&device->paused, 1);
    1.32      SDL_AtomicSet(&device->shutdown, 1);
    1.33      SDL_AtomicSet(&device->enabled, 0);
    1.34 +    current_audio.impl.UnlockDevice(device);
    1.35 +
    1.36      if (device->thread != NULL) {
    1.37          SDL_WaitThread(device->thread, NULL);
    1.38      }
    1.39 @@ -1076,6 +1078,14 @@
    1.40      SDL_free(device->work_buffer);
    1.41      SDL_FreeAudioStream(device->stream);
    1.42  
    1.43 +    if (device->id > 0) {
    1.44 +        SDL_AudioDevice *opendev = open_devices[device->id - 1];
    1.45 +        SDL_assert((opendev == device) || (opendev == NULL));
    1.46 +        if (opendev == device) {
    1.47 +            open_devices[device->id - 1] = NULL;
    1.48 +        }
    1.49 +    }
    1.50 +
    1.51      if (device->hidden != NULL) {
    1.52          current_audio.impl.CloseDevice(device);
    1.53      }