diff options
author | Chris Robinson <[email protected]> | 2019-04-27 21:25:42 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-04-27 21:25:42 -0700 |
commit | 014936ceff04dbc5075213d0e3002ebbc57524fb (patch) | |
tree | 50f28907acf18ac23655586ba94fd48795fee485 /Alc/backends | |
parent | 0577028b65656f6994d4a13d2c1ee9abc1a006da (diff) |
Be more robust with PulseAudio capture
Particularly, handle "holes" in the record stream and premature end-of-buffer.
Also don't bail out when capturing while disconnected (the extension says it
should provide anything it previously reported available, going to silence for
anything no longer readable).
Diffstat (limited to 'Alc/backends')
-rw-r--r-- | Alc/backends/pulseaudio.cpp | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/Alc/backends/pulseaudio.cpp b/Alc/backends/pulseaudio.cpp index 3e6bf160..f3d5d453 100644 --- a/Alc/backends/pulseaudio.cpp +++ b/Alc/backends/pulseaudio.cpp @@ -1290,34 +1290,37 @@ ALCenum PulseCapture::captureSamples(ALCvoid *buffer, ALCuint samples) std::lock_guard<std::mutex> _{pulse_lock}; while(todo > 0) { - size_t rem{todo}; - if(mCapLen == 0) { - pa_stream_state_t state{pa_stream_get_state(mStream)}; - if(!PA_STREAM_IS_GOOD(state)) + if(UNLIKELY(!mDevice->Connected.load(std::memory_order_acquire))) + break; + const pa_stream_state_t state{pa_stream_get_state(mStream)}; + if(UNLIKELY(!PA_STREAM_IS_GOOD(state))) { aluHandleDisconnect(mDevice, "Bad capture state: %u", state); - return ALC_INVALID_DEVICE; + break; } - if(pa_stream_peek(mStream, &mCapStore, &mCapLen) < 0) + if(UNLIKELY(pa_stream_peek(mStream, &mCapStore, &mCapLen) < 0)) { - ERR("pa_stream_peek() failed: %s\n", - pa_strerror(pa_context_errno(mContext))); aluHandleDisconnect(mDevice, "Failed retrieving capture samples: %s", pa_strerror(pa_context_errno(mContext))); - return ALC_INVALID_DEVICE; + break; } + if(mCapLen == 0) break; mCapRemain = mCapLen; } - rem = minz(rem, mCapRemain); - memcpy(buffer, mCapStore, rem); + const size_t rem{minz(todo, mCapRemain)}; + if(LIKELY(mCapStore)) + memcpy(buffer, mCapStore, rem); + else + memset(buffer, ((mDevice->FmtType==DevFmtUByte) ? 0x80 : 0), rem); buffer = static_cast<ALbyte*>(buffer) + rem; todo -= rem; - mCapStore = reinterpret_cast<const ALbyte*>(mCapStore) + rem; + if(LIKELY(mCapStore)) + mCapStore = reinterpret_cast<const ALbyte*>(mCapStore) + rem; mCapRemain -= rem; if(mCapRemain == 0) { |