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.

--HG--
extra : rebase_source : 8d6cf4c4e88a98cc85558693aff30fac25a8ed7e
This commit is contained in:
Ryan C. Gordon 2017-02-26 00:12:33 -05:00
parent 80cffbfbb1
commit 0e1aaaeceb

View file

@ -672,18 +672,14 @@ SDL_RunAudio(void *devicep)
data = device->work_buffer; data = device->work_buffer;
} }
if ( SDL_AtomicGet(&device->enabled) ) { /* !!! FIXME: this should be LockDevice. */
/* !!! FIXME: this should be LockDevice. */ SDL_LockMutex(device->mixer_lock);
SDL_LockMutex(device->mixer_lock); if (SDL_AtomicGet(&device->paused)) {
if (SDL_AtomicGet(&device->paused)) {
SDL_memset(data, silence, data_len);
} else {
callback(udata, data, data_len);
}
SDL_UnlockMutex(device->mixer_lock);
} else {
SDL_memset(data, silence, data_len); SDL_memset(data, silence, data_len);
} else {
callback(udata, data, data_len);
} }
SDL_UnlockMutex(device->mixer_lock);
if (device->stream) { if (device->stream) {
/* Stream available audio to device, converting/resampling. */ /* Stream available audio to device, converting/resampling. */
@ -752,7 +748,7 @@ SDL_CaptureAudio(void *devicep)
int still_need; int still_need;
Uint8 *ptr; 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. */ SDL_Delay(delay); /* just so we don't cook the CPU. */
if (device->stream) { if (device->stream) {
SDL_AudioStreamClear(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. 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. */ 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); const int rc = current_audio.impl.CaptureFromDevice(device, ptr, still_need);
SDL_assert(rc <= still_need); /* device should not overflow buffer. :) */ SDL_assert(rc <= still_need); /* device should not overflow buffer. :) */
if (rc > 0) { if (rc > 0) {