Commit a366c35f37dc62ed7f0fa2d8b494c5c99b307a04

Ryan C. Gordon 2017-02-26T00:12:33

audio: run the audio callback even if device was lost. We will throw away the data anyhow, but some apps depend on the callback firing to make progress; testmultiaudio.c, if nothing else, is an example of this. Capture also will now fire the callback in these conditions, offering nothing but silence. Apps can check SDL_GetAudioDeviceStatus() or listen for the SDL_AUDIODEVICEREMOVED event if they want to gracefully deal with an opened audio device that has been unexpectedly lost.

diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index f82014b..89499cd 100644
--- a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -672,18 +672,14 @@ SDL_RunAudio(void *devicep)
             data = device->work_buffer;
         }
 
-        if ( SDL_AtomicGet(&device->enabled) ) {
-            /* !!! FIXME: this should be LockDevice. */
-            SDL_LockMutex(device->mixer_lock);
-            if (SDL_AtomicGet(&device->paused)) {
-                SDL_memset(data, silence, data_len);
-            } else {
-                callback(udata, data, data_len);
-            }
-            SDL_UnlockMutex(device->mixer_lock);
-        } else {
+        /* !!! FIXME: this should be LockDevice. */
+        SDL_LockMutex(device->mixer_lock);
+        if (SDL_AtomicGet(&device->paused)) {
             SDL_memset(data, silence, data_len);
+        } else {
+            callback(udata, data, data_len);
         }
+        SDL_UnlockMutex(device->mixer_lock);
 
         if (device->stream) {
             /* Stream available audio to device, converting/resampling. */
@@ -752,7 +748,7 @@ SDL_CaptureAudio(void *devicep)
         int still_need;
         Uint8 *ptr;
 
-        if (!SDL_AtomicGet(&device->enabled) || SDL_AtomicGet(&device->paused)) {
+        if (SDL_AtomicGet(&device->paused)) {
             SDL_Delay(delay);  /* just so we don't cook the CPU. */
             if (device->stream) {
                 SDL_AudioStreamClear(device->stream);
@@ -774,7 +770,7 @@ SDL_CaptureAudio(void *devicep)
            and block when there isn't data so this thread isn't eating CPU.
            But we don't process it further or call the app's callback. */
 
-        while (still_need > 0) {
+        while (SDL_AtomicGet(&device->enabled) && (still_need > 0)) {
             const int rc = current_audio.impl.CaptureFromDevice(device, ptr, still_need);
             SDL_assert(rc <= still_need);  /* device should not overflow buffer. :) */
             if (rc > 0) {