diff options
author | Chris Robinson <[email protected]> | 2020-01-12 07:48:11 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2020-01-12 07:48:11 -0800 |
commit | af08f68448b37a9c1a22f6d9721b5c2c0708c960 (patch) | |
tree | 3c7e2131666d0f9db0313ac036d585f789df061f /alc | |
parent | 6f1c853397ae7a29e064cebe4d8988f192a28946 (diff) |
Fix JACK process callback handling
The callback apparently can't be set after activation, but we can't allocate
the ring buffer until after activation when the callback is already getting
called. An ugly flag it is, then, I guess.
Diffstat (limited to 'alc')
-rw-r--r-- | alc/backends/jack.cpp | 98 |
1 files changed, 48 insertions, 50 deletions
diff --git a/alc/backends/jack.cpp b/alc/backends/jack.cpp index 9ec66cfe..485225e4 100644 --- a/alc/backends/jack.cpp +++ b/alc/backends/jack.cpp @@ -169,6 +169,7 @@ struct JackPlayback final : public BackendBase { jack_client_t *mClient{nullptr}; jack_port_t *mPort[MAX_OUTPUT_CHANNELS]{}; + std::atomic<bool> mPlaying{false}; RingBufferPtr mRing; al::semaphore mSem; @@ -196,68 +197,63 @@ JackPlayback::~JackPlayback() int JackPlayback::process(jack_nframes_t numframes) noexcept { jack_default_audio_sample_t *out[MAX_OUTPUT_CHANNELS]; - ALsizei numchans{0}; + size_t numchans{0}; for(auto port : mPort) { if(!port) break; out[numchans++] = static_cast<float*>(jack_port_get_buffer(port, numframes)); } - auto data = mRing->getReadVector(); - jack_nframes_t todo{minu(numframes, static_cast<ALuint>(data.first.len))}; - std::transform(out, out+numchans, out, - [&data,numchans,todo](ALfloat *outbuf) -> ALfloat* + jack_nframes_t total{0}; + if LIKELY(mPlaying.load(std::memory_order_acquire)) + { + auto data = mRing->getReadVector(); + jack_nframes_t todo{minu(numframes, static_cast<ALuint>(data.first.len))}; + auto write_first = [&data,numchans,todo](float *outbuf) -> float* + { + const float *RESTRICT in = reinterpret_cast<float*>(data.first.buf); + auto deinterlace_input = [&in,numchans]() noexcept -> float + { + float ret{*in}; + in += numchans; + return ret; + }; + std::generate_n(outbuf, todo, deinterlace_input); + data.first.buf += sizeof(float); + return outbuf + todo; + }; + std::transform(out, out+numchans, out, write_first); + total += todo; + + todo = minu(numframes-total, static_cast<ALuint>(data.second.len)); + if(todo > 0) { - const ALfloat *RESTRICT in = reinterpret_cast<ALfloat*>(data.first.buf); - std::generate_n(outbuf, todo, - [&in,numchans]() noexcept -> ALfloat + auto write_second = [&data,numchans,todo](float *outbuf) -> float* + { + const float *RESTRICT in = reinterpret_cast<float*>(data.second.buf); + auto deinterlace_input = [&in,numchans]() noexcept -> float { - ALfloat ret{*in}; + float ret{*in}; in += numchans; return ret; - } - ); - data.first.buf += sizeof(ALfloat); - return outbuf + todo; + }; + std::generate_n(outbuf, todo, deinterlace_input); + data.second.buf += sizeof(float); + return outbuf + todo; + }; + std::transform(out, out+numchans, out, write_second); + total += todo; } - ); - jack_nframes_t total{todo}; - todo = minu(numframes-total, static_cast<ALuint>(data.second.len)); - if(todo > 0) - { - std::transform(out, out+numchans, out, - [&data,numchans,todo](ALfloat *outbuf) -> ALfloat* - { - const ALfloat *RESTRICT in = reinterpret_cast<ALfloat*>(data.second.buf); - std::generate_n(outbuf, todo, - [&in,numchans]() noexcept -> ALfloat - { - ALfloat ret{*in}; - in += numchans; - return ret; - } - ); - data.second.buf += sizeof(ALfloat); - return outbuf + todo; - } - ); - total += todo; + mRing->readAdvance(total); + mSem.post(); } - mRing->readAdvance(total); - mSem.post(); - if(numframes > total) { - todo = numframes-total; - std::transform(out, out+numchans, out, - [todo](ALfloat *outbuf) -> ALfloat* - { - std::fill_n(outbuf, todo, 0.0f); - return outbuf + todo; - } - ); + jack_nframes_t todo{numframes - total}; + auto clear_buf = [todo](ALfloat *outbuf) -> void { std::fill_n(outbuf, todo, 0.0f); }; + std::for_each(out, out+numchans, clear_buf); } return 0; @@ -318,9 +314,11 @@ void JackPlayback::open(const ALCchar *name) if((status&JackNameNotUnique)) { client_name = jack_get_client_name(mClient); - TRACE("Client name not unique, got `%s' instead\n", client_name); + TRACE("Client name not unique, got '%s' instead\n", client_name); } + jack_set_process_callback(mClient, &JackPlayback::processC, this); + mDevice->DeviceName = name; } @@ -429,8 +427,8 @@ bool JackPlayback::start() mRing = nullptr; mRing = RingBuffer::Create(bufsize, mDevice->frameSizeFromFmt(), true); - jack_set_process_callback(mClient, &JackPlayback::processC, this); try { + mPlaying.store(true, std::memory_order_release); mKillNow.store(false, std::memory_order_release); mThread = std::thread{std::mem_fn(&JackPlayback::mixerProc), this}; return true; @@ -440,8 +438,8 @@ bool JackPlayback::start() } catch(...) { } - jack_set_process_callback(mClient, nullptr, nullptr); jack_deactivate(mClient); + mPlaying.store(false, std::memory_order_release); return false; } @@ -454,7 +452,7 @@ void JackPlayback::stop() mThread.join(); jack_deactivate(mClient); - jack_set_process_callback(mClient, nullptr, nullptr); + mPlaying.store(false, std::memory_order_release); } |