From 09e4f2764b9d831e2b8d187cc84b72af679718e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20M=C3=BCller?= Date: Sat, 27 Mar 2021 12:05:02 +0100 Subject: [PATCH] Rewrite PulseAudioDevice to use ThreadedDevice. --- plugins/pulseaudio/PulseAudioDevice.cpp | 62 ++++++++++++------------- plugins/pulseaudio/PulseAudioDevice.h | 19 ++++---- plugins/pulseaudio/PulseAudioSymbols.h | 14 ++---- 3 files changed, 43 insertions(+), 52 deletions(-) diff --git a/plugins/pulseaudio/PulseAudioDevice.cpp b/plugins/pulseaudio/PulseAudioDevice.cpp index 0a50d5db..3ffe9766 100644 --- a/plugins/pulseaudio/PulseAudioDevice.cpp +++ b/plugins/pulseaudio/PulseAudioDevice.cpp @@ -27,9 +27,9 @@ void PulseAudioDevice::PulseAudio_state_callback(pa_context *context, void *data { PulseAudioDevice* device = (PulseAudioDevice*)data; - device->m_state = AUD_pa_context_get_state(context); + std::lock_guard lock(*device); - AUD_pa_threaded_mainloop_signal(device->m_mainloop, 0); + device->m_state = AUD_pa_context_get_state(context); } void PulseAudioDevice::PulseAudio_request(pa_stream *stream, size_t num_bytes, void *data) @@ -68,29 +68,40 @@ void PulseAudioDevice::PulseAudio_underflow(pa_stream *stream, void *data) } } -void PulseAudioDevice::playing(bool playing) +void PulseAudioDevice::runMixingThread() { - m_playback = playing; + for(;;) + { + { + std::lock_guard lock(*this); + + if(shouldStop()) + { + AUD_pa_stream_cork(m_stream, 1, nullptr, nullptr); + doStop(); + return; + } + } + + if(AUD_pa_stream_is_corked(m_stream)) + AUD_pa_stream_cork(m_stream, 0, nullptr, nullptr); - AUD_pa_stream_cork(m_stream, playing ? 0 : 1, nullptr, nullptr); + AUD_pa_mainloop_iterate(m_mainloop, true, nullptr); + } } PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buffersize) : - m_playback(false), m_state(PA_CONTEXT_UNCONNECTED), m_buffersize(buffersize), m_underflows(0) { - m_mainloop = AUD_pa_threaded_mainloop_new(); + m_mainloop = AUD_pa_mainloop_new(); - AUD_pa_threaded_mainloop_lock(m_mainloop); - - m_context = AUD_pa_context_new(AUD_pa_threaded_mainloop_get_api(m_mainloop), name.c_str()); + m_context = AUD_pa_context_new(AUD_pa_mainloop_get_api(m_mainloop), name.c_str()); if(!m_context) { - AUD_pa_threaded_mainloop_unlock(m_mainloop); - AUD_pa_threaded_mainloop_free(m_mainloop); + AUD_pa_mainloop_free(m_mainloop); AUD_THROW(DeviceException, "Could not connect to PulseAudio."); } @@ -99,26 +110,21 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff AUD_pa_context_connect(m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr); - AUD_pa_threaded_mainloop_start(m_mainloop); - while(m_state != PA_CONTEXT_READY) { switch(m_state) { case PA_CONTEXT_FAILED: case PA_CONTEXT_TERMINATED: - AUD_pa_threaded_mainloop_unlock(m_mainloop); - AUD_pa_threaded_mainloop_stop(m_mainloop); - AUD_pa_context_disconnect(m_context); AUD_pa_context_unref(m_context); - AUD_pa_threaded_mainloop_free(m_mainloop); + AUD_pa_mainloop_free(m_mainloop); AUD_THROW(DeviceException, "Could not connect to PulseAudio."); break; default: - AUD_pa_threaded_mainloop_wait(m_mainloop); + AUD_pa_mainloop_iterate(m_mainloop, true, nullptr); break; } } @@ -166,13 +172,10 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff if(!m_stream) { - AUD_pa_threaded_mainloop_unlock(m_mainloop); - AUD_pa_threaded_mainloop_stop(m_mainloop); - AUD_pa_context_disconnect(m_context); AUD_pa_context_unref(m_context); - AUD_pa_threaded_mainloop_free(m_mainloop); + AUD_pa_mainloop_free(m_mainloop); AUD_THROW(DeviceException, "Could not create PulseAudio stream."); } @@ -188,32 +191,27 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff buffer_attr.prebuf = -1U; buffer_attr.tlength = buffersize; - if(AUD_pa_stream_connect_playback(m_stream, nullptr, &buffer_attr, static_cast(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr) < 0) + if(AUD_pa_stream_connect_playback(m_stream, nullptr, &buffer_attr, static_cast(PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr) < 0) { - AUD_pa_threaded_mainloop_unlock(m_mainloop); - AUD_pa_threaded_mainloop_stop(m_mainloop); - AUD_pa_context_disconnect(m_context); AUD_pa_context_unref(m_context); - AUD_pa_threaded_mainloop_free(m_mainloop); + AUD_pa_mainloop_free(m_mainloop); AUD_THROW(DeviceException, "Could not connect PulseAudio stream."); } - AUD_pa_threaded_mainloop_unlock(m_mainloop); - create(); } PulseAudioDevice::~PulseAudioDevice() { - AUD_pa_threaded_mainloop_stop(m_mainloop); + stopMixingThread(); AUD_pa_context_disconnect(m_context); AUD_pa_context_unref(m_context); - AUD_pa_threaded_mainloop_free(m_mainloop); + AUD_pa_mainloop_free(m_mainloop); destroy(); } diff --git a/plugins/pulseaudio/PulseAudioDevice.h b/plugins/pulseaudio/PulseAudioDevice.h index 9efae512..be34cc90 100644 --- a/plugins/pulseaudio/PulseAudioDevice.h +++ b/plugins/pulseaudio/PulseAudioDevice.h @@ -26,7 +26,7 @@ * The PulseAudioDevice class. */ -#include "devices/SoftwareDevice.h" +#include "devices/ThreadedDevice.h" #include @@ -35,15 +35,10 @@ AUD_NAMESPACE_BEGIN /** * This device plays back through PulseAudio, the simple direct media layer. */ -class AUD_PLUGIN_API PulseAudioDevice : public SoftwareDevice +class AUD_PLUGIN_API PulseAudioDevice : public ThreadedDevice { private: - /** - * Whether there is currently playback. - */ - volatile bool m_playback; - - pa_threaded_mainloop* m_mainloop; + pa_mainloop* m_mainloop; pa_context* m_context; pa_stream* m_stream; pa_context_state_t m_state; @@ -74,13 +69,15 @@ class AUD_PLUGIN_API PulseAudioDevice : public SoftwareDevice */ AUD_LOCAL static void PulseAudio_underflow(pa_stream* stream, void* data); + /** + * Streaming thread main function. + */ + AUD_LOCAL void runMixingThread(); + // delete copy constructor and operator= PulseAudioDevice(const PulseAudioDevice&) = delete; PulseAudioDevice& operator=(const PulseAudioDevice&) = delete; -protected: - virtual void playing(bool playing); - public: /** * Opens the PulseAudio audio device for playback. diff --git a/plugins/pulseaudio/PulseAudioSymbols.h b/plugins/pulseaudio/PulseAudioSymbols.h index 9cefbc0c..4b9e1ffe 100644 --- a/plugins/pulseaudio/PulseAudioSymbols.h +++ b/plugins/pulseaudio/PulseAudioSymbols.h @@ -24,18 +24,14 @@ PULSEAUDIO_SYMBOL(pa_context_unref); PULSEAUDIO_SYMBOL(pa_stream_begin_write); PULSEAUDIO_SYMBOL(pa_stream_connect_playback); PULSEAUDIO_SYMBOL(pa_stream_cork); +PULSEAUDIO_SYMBOL(pa_stream_is_corked); PULSEAUDIO_SYMBOL(pa_stream_new); PULSEAUDIO_SYMBOL(pa_stream_set_buffer_attr); PULSEAUDIO_SYMBOL(pa_stream_set_underflow_callback); PULSEAUDIO_SYMBOL(pa_stream_set_write_callback); PULSEAUDIO_SYMBOL(pa_stream_write); -PULSEAUDIO_SYMBOL(pa_threaded_mainloop_free); -PULSEAUDIO_SYMBOL(pa_threaded_mainloop_get_api); -PULSEAUDIO_SYMBOL(pa_threaded_mainloop_lock); -PULSEAUDIO_SYMBOL(pa_threaded_mainloop_new); -PULSEAUDIO_SYMBOL(pa_threaded_mainloop_signal); -PULSEAUDIO_SYMBOL(pa_threaded_mainloop_start); -PULSEAUDIO_SYMBOL(pa_threaded_mainloop_stop); -PULSEAUDIO_SYMBOL(pa_threaded_mainloop_unlock); -PULSEAUDIO_SYMBOL(pa_threaded_mainloop_wait); +PULSEAUDIO_SYMBOL(pa_mainloop_free); +PULSEAUDIO_SYMBOL(pa_mainloop_get_api); +PULSEAUDIO_SYMBOL(pa_mainloop_new); +PULSEAUDIO_SYMBOL(pa_mainloop_iterate);