From e7b3b5e4cbfc21bcd7829738881b7108bee9eda9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com> Date: Tue, 3 Nov 2020 12:38:58 -0500 Subject: [PATCH] pulseaudio: avoid creating duplicated streams Change-Id: Idec4c34eae9cb5204c28d5b1599686f50011680c --- src/media/audio/audio_input.cpp | 1 - src/media/audio/audiolayer.cpp | 2 +- src/media/audio/pulseaudio/audiostream.cpp | 117 +++++---- src/media/audio/pulseaudio/audiostream.h | 14 +- src/media/audio/pulseaudio/pulselayer.cpp | 273 +++++++++------------ src/media/audio/pulseaudio/pulselayer.h | 39 ++- src/preferences.h | 14 +- 7 files changed, 221 insertions(+), 239 deletions(-) diff --git a/src/media/audio/audio_input.cpp b/src/media/audio/audio_input.cpp index c5b427342a..bc1669055c 100644 --- a/src/media/audio/audio_input.cpp +++ b/src/media/audio/audio_input.cpp @@ -179,7 +179,6 @@ AudioInput::readFromFile() bool AudioInput::initDevice(const std::string& device) { - JAMI_WARN("AudioInput::initDevice %s", device.c_str()); devOpts_ = {}; devOpts_.input = device; devOpts_.channel = format_.nb_channels; diff --git a/src/media/audio/audiolayer.cpp b/src/media/audio/audiolayer.cpp index b4ed1e4eb8..dddd552bd1 100644 --- a/src/media/audio/audiolayer.cpp +++ b/src/media/audio/audiolayer.cpp @@ -130,6 +130,7 @@ void AudioLayer::hardwareFormatAvailable(AudioFormat playback, size_t bufSize) { JAMI_DBG("Hardware audio format available : %s %zu", playback.toString().c_str(), bufSize); + std::unique_lock<std::mutex> lk(mutex_); audioFormat_ = Manager::instance().hardwareAudioFormatChanged(playback); urgentRingBuffer_.setFormat(audioFormat_); nativeFrameSize_ = bufSize; @@ -150,7 +151,6 @@ AudioLayer::devicesChanged() void AudioLayer::flushMain() { - std::lock_guard<std::mutex> lock(mutex_); Manager::instance().getRingBufferPool().flushAllBuffers(); } diff --git a/src/media/audio/pulseaudio/audiostream.cpp b/src/media/audio/pulseaudio/audiostream.cpp index 576da07c8d..ac1f1b571c 100644 --- a/src/media/audio/pulseaudio/audiostream.cpp +++ b/src/media/audio/pulseaudio/audiostream.cpp @@ -31,29 +31,28 @@ namespace jami { AudioStream::AudioStream(pa_context* c, pa_threaded_mainloop* m, const char* desc, - StreamType type, + AudioDeviceType type, unsigned samplrate, - const PaDeviceInfos* infos, + const PaDeviceInfos& infos, bool ec, - OnReady onReady) + OnReady onReady, OnData onData) : onReady_(std::move(onReady)) - , audiostream_(0) + , onData_(std::move(onData)) + , audiostream_(nullptr) , mainloop_(m) { - const pa_channel_map channel_map = infos->channel_map; - pa_sample_spec sample_spec = {PA_SAMPLE_S16LE, // PA_SAMPLE_FLOAT32LE, samplrate, - channel_map.channels}; + infos.channel_map.channels}; - JAMI_DBG("%s: trying to create stream with device %s (%dHz, %d channels)", + JAMI_DBG("%s: Creating stream with device %s (%dHz, %d channels)", desc, - infos->name.c_str(), + infos.name.c_str(), samplrate, - channel_map.channels); + infos.channel_map.channels); assert(pa_sample_spec_valid(&sample_spec)); - assert(pa_channel_map_valid(&channel_map)); + assert(pa_channel_map_valid(&infos.channel_map)); std::unique_ptr<pa_proplist, decltype(pa_proplist_free)&> pl(pa_proplist_new(), pa_proplist_free); @@ -62,7 +61,7 @@ AudioStream::AudioStream(pa_context* c, audiostream_ = pa_stream_new_with_proplist(c, desc, &sample_spec, - &channel_map, + &infos.channel_map, ec ? pl.get() : nullptr); if (!audiostream_) { JAMI_ERR("%s: pa_stream_new() failed : %s", desc, pa_strerror(pa_context_errno(c))); @@ -85,44 +84,53 @@ AudioStream::AudioStream(pa_context* c, [](pa_stream* s, void* user_data) { static_cast<AudioStream*>(user_data)->moved(s); }, this); - { - PulseMainLoopLock lock(mainloop_); - const pa_stream_flags_t flags = static_cast<pa_stream_flags_t>( - PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_START_CORKED); - - if (type == StreamType::Playback || type == StreamType::Ringtone) { - pa_stream_connect_playback(audiostream_, - infos->name.empty() ? nullptr : infos->name.c_str(), - &attributes, - flags, - nullptr, - nullptr); - } else if (type == StreamType::Capture) { - pa_stream_connect_record(audiostream_, - infos->name.empty() ? nullptr : infos->name.c_str(), - &attributes, - flags); - } + constexpr pa_stream_flags_t flags = static_cast<pa_stream_flags_t>( + PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_START_CORKED); + + if (type == AudioDeviceType::PLAYBACK || type == AudioDeviceType::RINGTONE) { + pa_stream_set_write_callback(audiostream_, [](pa_stream* /*s*/, size_t bytes, void* userdata) { + static_cast<AudioStream*>(userdata)->onData_(bytes); + }, this); + + pa_stream_connect_playback(audiostream_, + infos.name.empty() ? nullptr : infos.name.c_str(), + &attributes, + flags, + nullptr, + nullptr); + } else if (type == AudioDeviceType::CAPTURE) { + pa_stream_set_read_callback(audiostream_, [](pa_stream* /*s*/, size_t bytes, void* userdata) { + static_cast<AudioStream*>(userdata)->onData_(bytes); + }, this); + + pa_stream_connect_record(audiostream_, + infos.name.empty() ? nullptr : infos.name.c_str(), + &attributes, + flags); } } -AudioStream::~AudioStream() -{ - PulseMainLoopLock lock(mainloop_); +void disconnectStream(pa_stream* s) { + // make sure we don't get any further callback + pa_stream_set_write_callback(s, nullptr, nullptr); + pa_stream_set_read_callback(s, nullptr, nullptr); + pa_stream_set_moved_callback(s, nullptr, nullptr); + pa_stream_set_underflow_callback(s, nullptr, nullptr); + pa_stream_set_overflow_callback(s, nullptr, nullptr); + pa_stream_set_suspended_callback(s, nullptr, nullptr); + pa_stream_set_started_callback(s, nullptr, nullptr); +} - pa_stream_disconnect(audiostream_); +void destroyStream(pa_stream* s) { + pa_stream_disconnect(s); + pa_stream_set_state_callback(s, nullptr, nullptr); + disconnectStream(s); + pa_stream_unref(s); +} - // make sure we don't get any further callback - pa_stream_set_state_callback(audiostream_, nullptr, nullptr); - pa_stream_set_write_callback(audiostream_, nullptr, nullptr); - pa_stream_set_read_callback(audiostream_, nullptr, nullptr); - pa_stream_set_moved_callback(audiostream_, nullptr, nullptr); - pa_stream_set_underflow_callback(audiostream_, nullptr, nullptr); - pa_stream_set_overflow_callback(audiostream_, nullptr, nullptr); - pa_stream_set_suspended_callback(audiostream_, nullptr, nullptr); - pa_stream_set_started_callback(audiostream_, nullptr, nullptr); - - pa_stream_unref(audiostream_); +AudioStream::~AudioStream() +{ + stop(); } void @@ -131,6 +139,23 @@ AudioStream::start() pa_stream_cork(audiostream_, 0, nullptr, nullptr); } +void +AudioStream::stop() +{ + if (not audiostream_) + return; + JAMI_DBG("Destroying stream with device %s", pa_stream_get_device_name(audiostream_)); + if (pa_stream_get_state(audiostream_) == PA_STREAM_CREATING) { + disconnectStream(audiostream_); + pa_stream_set_state_callback(audiostream_, [](pa_stream* s, void*){ + destroyStream(s); + }, nullptr); + } else { + destroyStream(audiostream_); + } + audiostream_ = nullptr; +} + void AudioStream::moved(pa_stream* s) { @@ -141,7 +166,7 @@ AudioStream::moved(pa_stream* s) void AudioStream::stateChanged(pa_stream* s) { - UNUSED char str[PA_SAMPLE_SPEC_SNPRINT_MAX]; + //UNUSED char str[PA_SAMPLE_SPEC_SNPRINT_MAX]; switch (pa_stream_get_state(s)) { case PA_STREAM_CREATING: diff --git a/src/media/audio/pulseaudio/audiostream.h b/src/media/audio/pulseaudio/audiostream.h index 2f8e8ff4e7..f8aaadbf83 100644 --- a/src/media/audio/pulseaudio/audiostream.h +++ b/src/media/audio/pulseaudio/audiostream.h @@ -28,15 +28,11 @@ namespace jami { -/** - * This data structure contains the different king of audio streams available - */ -enum class StreamType { Playback, Capture, Ringtone }; - class AudioStream { public: using OnReady = std::function<void()>; + using OnData = std::function<void(size_t)>; /** * Constructor @@ -52,15 +48,16 @@ public: AudioStream(pa_context*, pa_threaded_mainloop*, const char*, - StreamType, + AudioDeviceType, unsigned, - const PaDeviceInfos*, + const PaDeviceInfos&, bool, - OnReady onReady); + OnReady onReady, OnData onData); ~AudioStream(); void start(); + void stop(); /** * Accessor: Get the pulseaudio stream object @@ -95,6 +92,7 @@ private: NON_COPYABLE(AudioStream); OnReady onReady_; + OnData onData_; /** * Mandatory asynchronous callback on the audio stream state diff --git a/src/media/audio/pulseaudio/pulselayer.cpp b/src/media/audio/pulseaudio/pulselayer.cpp index b54fa31130..c3908747f9 100644 --- a/src/media/audio/pulseaudio/pulselayer.cpp +++ b/src/media/audio/pulseaudio/pulselayer.cpp @@ -359,141 +359,97 @@ PulseLayer::getAudioDeviceName(int index, AudioDeviceType type) const } void -PulseLayer::createStreams(pa_context* c) -{ - hardwareFormatAvailable(defaultAudioFormat_); - - auto onReady = [this] { - bool playbackReady = not playback_ or playback_->isReady(); - bool ringtoneReady = not ringtone_ or ringtone_->isReady(); - bool recordReady = not record_ or record_->isReady(); - if (playbackReady and recordReady and ringtoneReady) { - JAMI_DBG("All streams ready, starting !"); - if (playback_) - playback_->start(); - if (ringtone_) - ringtone_->start(); - if (record_) - record_->start(); - } - }; - - // Create playback stream - if (auto dev_infos = getDeviceInfos(sinkList_, getPreferredPlaybackDevice())) { - bool ec = preference_.getEchoCanceller() == "system"; - playback_.reset(new AudioStream(c, - mainloop_.get(), - "Playback", - StreamType::Playback, - audioFormat_.sample_rate, - dev_infos, - ec, - onReady)); - pa_stream_set_write_callback( - playback_->stream(), - [](pa_stream* /*s*/, size_t /*bytes*/, void* userdata) { - static_cast<PulseLayer*>(userdata)->writeToSpeaker(); - }, - this); - } - - // Create ringtone stream - // Echo canceling is not enabled for ringtone, because PA can only cancel a single output source - // with an input source - if (auto dev_infos = getDeviceInfos(sinkList_, getPreferredRingtoneDevice())) { - ringtone_.reset(new AudioStream(c, - mainloop_.get(), - "Ringtone", - StreamType::Ringtone, - audioFormat_.sample_rate, - dev_infos, - false, - onReady)); - pa_stream_set_write_callback( - ringtone_->stream(), - [](pa_stream* /*s*/, size_t /*bytes*/, void* userdata) { - static_cast<PulseLayer*>(userdata)->ringtoneToSpeaker(); - }, - this); +PulseLayer::onStreamReady() { + if (--pendingStreams == 0) { + JAMI_DBG("All streams ready, starting audio"); + // Flush outside the if statement: every time start stream is + // called is to notify a new event + flushUrgent(); + flushMain(); + if (playback_) + playback_->start(); + if (ringtone_) + ringtone_->start(); + if (record_) + record_->start(); } +} - // Create capture stream - if (auto dev_infos = getDeviceInfos(sourceList_, getPreferredCaptureDevice())) { - record_.reset(new AudioStream(c, - mainloop_.get(), - "Capture", - StreamType::Capture, - audioFormat_.sample_rate, - dev_infos, - true, - onReady)); - pa_stream_set_read_callback( - record_->stream(), - [](pa_stream* /*s*/, size_t /*bytes*/, void* userdata) { - static_cast<PulseLayer*>(userdata)->readFromMic(); - }, - this); +void +PulseLayer::createStream(std::unique_ptr<AudioStream>& stream, AudioDeviceType type, const PaDeviceInfos& dev_infos, bool ec, std::function<void(size_t)>&& onData) +{ + if (stream) { + JAMI_WARN("Stream already exists"); + return; } - - pa_threaded_mainloop_signal(mainloop_.get(), 0); - - flushMain(); - flushUrgent(); + pendingStreams++; + const char* name = type == AudioDeviceType::PLAYBACK ? "Playback" : + (type == AudioDeviceType::CAPTURE ? "Record" : + (type == AudioDeviceType::RINGTONE ? "Ringtone" : "?")); + stream.reset(new AudioStream(context_, mainloop_.get(), + name, + type, + audioFormat_.sample_rate, + dev_infos, + ec, + std::bind(&PulseLayer::onStreamReady, this), std::move(onData))); } void PulseLayer::disconnectAudioStream() { + PulseMainLoopLock lock(mainloop_.get()); playback_.reset(); ringtone_.reset(); record_.reset(); + pendingStreams = 0; + status_ = Status::Idle; + startedCv_.notify_all(); } -void PulseLayer::startStream(AudioDeviceType) +void PulseLayer::startStream(AudioDeviceType type) { - std::unique_lock<std::mutex> lk(readyMtx_); - readyCv_.wait(lk, [this] { - return !(enumeratingSinks_ or enumeratingSources_ or gettingServerInfo_); - }); - if (status_ != Status::Idle) - return; - status_ = Status::Starting; + waitForDevices(); + PulseMainLoopLock lock(mainloop_.get()); // Create Streams - if (!playback_ or !record_) - createStreams(context_); - - // Flush outside the if statement: every time start stream is - // called is to notify a new event - flushUrgent(); - flushMain(); + if (type == AudioDeviceType::PLAYBACK) { + if (auto dev_infos = getDeviceInfos(sinkList_, getPreferredPlaybackDevice())) + createStream(playback_, type, *dev_infos, true, std::bind(&PulseLayer::writeToSpeaker, this)); + } else if (type == AudioDeviceType::RINGTONE) { + if (auto dev_infos = getDeviceInfos(sinkList_, getPreferredRingtoneDevice())) + createStream(ringtone_, type, *dev_infos, false, std::bind(&PulseLayer::ringtoneToSpeaker, this)); + } else if (type == AudioDeviceType::CAPTURE) { + if (auto dev_infos = getDeviceInfos(sourceList_, getPreferredCaptureDevice())) + createStream(record_, type, *dev_infos, true, std::bind(&PulseLayer::readFromMic, this)); + } + pa_threaded_mainloop_signal(mainloop_.get(), 0); + std::lock_guard<std::mutex> lk(mutex_); status_ = Status::Started; startedCv_.notify_all(); } void -PulseLayer::stopStream(AudioDeviceType stream) +PulseLayer::stopStream(AudioDeviceType type) { - std::unique_lock<std::mutex> lk(readyMtx_); - readyCv_.wait(lk, [this] { - return !(enumeratingSinks_ or enumeratingSources_ or gettingServerInfo_); - }); - - { - PulseMainLoopLock lock(mainloop_.get()); + waitForDevices(); + PulseMainLoopLock lock(mainloop_.get()); + auto& stream(getStream(type)); + if (not stream) + return; - if (playback_) - pa_stream_flush(playback_->stream(), nullptr, nullptr); + if (not stream->isReady()) + pendingStreams--; + stream->stop(); + stream.reset(); - if (record_) - pa_stream_flush(record_->stream(), nullptr, nullptr); + std::unique_lock<std::mutex> lk(mutex_); + if (not playback_ and not ringtone_ and not record_) { + pendingStreams = 0; + status_ = Status::Idle; + startedCv_.notify_all(); } - - disconnectAudioStream(); - - status_ = Status::Idle; - startedCv_.notify_all(); } void @@ -628,50 +584,52 @@ PulseLayer::contextChanged(pa_context* c UNUSED, } } +void +PulseLayer::waitForDevices() +{ + std::unique_lock<std::mutex> lk(readyMtx_); + readyCv_.wait(lk, [this] { + return !(enumeratingSinks_ or enumeratingSources_ or gettingServerInfo_); + }); +} + void PulseLayer::waitForDeviceList() { std::unique_lock<std::mutex> lock(readyMtx_); - if (waitingDeviceList_) + if (waitingDeviceList_.exchange(true)) return; - waitingDeviceList_ = true; if (streamStarter_.joinable()) streamStarter_.join(); streamStarter_ = std::thread([this]() mutable { - { - std::unique_lock<std::mutex> lock(readyMtx_); - readyCv_.wait(lock, [&]() { - return not enumeratingSources_ and not enumeratingSinks_ and not gettingServerInfo_; - }); - } - devicesChanged(); + bool playbackDeviceChanged, recordDeviceChanged; + + waitForDevices(); waitingDeviceList_ = false; - if (status_ != Status::Started) - return; // If a current device changed, restart streams + devicesChanged(); auto playbackInfo = getDeviceInfos(sinkList_, getPreferredPlaybackDevice()); - bool playbackDeviceChanged = !playback_ - or (!playbackInfo->name.empty() - and playbackInfo->name - != stripEchoSufix(playback_->getDeviceName())); + playbackDeviceChanged = playback_ + and (!playbackInfo->name.empty() and playbackInfo->name + != stripEchoSufix(playback_->getDeviceName())); auto recordInfo = getDeviceInfos(sourceList_, getPreferredCaptureDevice()); - bool recordDeviceChanged = !record_ - or (!recordInfo->name.empty() - and recordInfo->name - != stripEchoSufix(record_->getDeviceName())); - - if (playbackDeviceChanged or recordDeviceChanged) { - JAMI_WARN("Audio devices changed, restarting streams."); - stopStream(); - startStream(); - } else { - JAMI_WARN("Staying on \n %s \n %s", - playback_->getDeviceName().c_str(), - record_->getDeviceName().c_str()); - status_ = Status::Started; - startedCv_.notify_all(); + recordDeviceChanged = record_ + and (!recordInfo->name.empty() and recordInfo->name + != stripEchoSufix(record_->getDeviceName())); + + if (status_ != Status::Started) + return; + if (playbackDeviceChanged) { + JAMI_WARN("Playback devices changed, restarting streams."); + stopStream(AudioDeviceType::PLAYBACK); + startStream(AudioDeviceType::PLAYBACK); + } + if (recordDeviceChanged) { + JAMI_WARN("Record devices changed, restarting streams."); + stopStream(AudioDeviceType::CAPTURE); + startStream(AudioDeviceType::CAPTURE); } }); } @@ -697,19 +655,18 @@ PulseLayer::server_info_callback(pa_context*, const pa_server_info* i, void* use pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map)); PulseLayer* context = static_cast<PulseLayer*>(userdata); + std::lock_guard<std::mutex> lk(context->readyMtx_); context->defaultSink_ = {}; context->defaultSource_ = {}; context->defaultAudioFormat_ = {i->sample_spec.rate, i->sample_spec.channels}; + context->hardwareFormatAvailable(context->defaultAudioFormat_); if (not context->sinkList_.empty()) context->sinkList_.front().channel_map.channels = std::min(i->sample_spec.channels, (uint8_t) 2); if (not context->sourceList_.empty()) context->sourceList_.front().channel_map.channels = std::min(i->sample_spec.channels, (uint8_t) 2); - { - std::lock_guard<std::mutex> lk(context->readyMtx_); - context->gettingServerInfo_ = false; - } + context->gettingServerInfo_ = false; context->readyCv_.notify_all(); } @@ -722,10 +679,8 @@ PulseLayer::source_input_info_callback(pa_context* c UNUSED, PulseLayer* context = static_cast<PulseLayer*>(userdata); if (eol) { - { - std::lock_guard<std::mutex> lk(context->readyMtx_); - context->enumeratingSources_ = false; - } + std::lock_guard<std::mutex> lk(context->readyMtx_); + context->enumeratingSources_ = false; context->readyCv_.notify_all(); return; } @@ -768,12 +723,10 @@ PulseLayer::sink_input_info_callback(pa_context* c UNUSED, void* userdata) { PulseLayer* context = static_cast<PulseLayer*>(userdata); + std::lock_guard<std::mutex> lk(context->readyMtx_); if (eol) { - { - std::lock_guard<std::mutex> lk(context->readyMtx_); - context->enumeratingSinks_ = false; - } + context->enumeratingSinks_ = false; context->readyCv_.notify_all(); return; } @@ -858,28 +811,22 @@ PulseLayer::getIndexRingtone() const std::string PulseLayer::getPreferredPlaybackDevice() const { - std::string playbackDevice(preference_.getPulseDevicePlayback()); - if (playbackDevice.empty()) - playbackDevice = defaultSink_; - return stripEchoSufix(playbackDevice); + const std::string& device(preference_.getPulseDevicePlayback()); + return stripEchoSufix(device.empty() ? defaultSink_ : device); } std::string PulseLayer::getPreferredRingtoneDevice() const { - std::string ringtoneDevice(preference_.getPulseDeviceRingtone()); - if (ringtoneDevice.empty()) - ringtoneDevice = defaultSink_; - return stripEchoSufix(ringtoneDevice); + const std::string& device(preference_.getPulseDeviceRingtone()); + return stripEchoSufix(device.empty() ? defaultSink_ : device); } std::string PulseLayer::getPreferredCaptureDevice() const { - std::string captureDevice(preference_.getPulseDeviceRecord()); - if (captureDevice.empty()) - captureDevice = defaultSource_; - return stripEchoSufix(captureDevice); + const std::string& device(preference_.getPulseDeviceRecord()); + return stripEchoSufix(device.empty() ? defaultSource_ : device); } } // namespace jami diff --git a/src/media/audio/pulseaudio/pulselayer.h b/src/media/audio/pulseaudio/pulselayer.h index 903b8a2fa1..fe0c95599f 100644 --- a/src/media/audio/pulseaudio/pulselayer.h +++ b/src/media/audio/pulseaudio/pulselayer.h @@ -22,17 +22,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef PULSE_LAYER_H_ -#define PULSE_LAYER_H_ +#pragma once -#include <list> -#include <string> -#include <pulse/pulseaudio.h> -#include <pulse/stream.h> -#include "audio/audiolayer.h" #include "noncopyable.h" #include "logger.h" +#include "audio/audiolayer.h" +#include <pulse/pulseaudio.h> +#include <pulse/stream.h> + +#include <list> +#include <string> #include <memory> #include <thread> @@ -167,6 +167,7 @@ private: virtual int getIndexPlayback() const; virtual int getIndexRingtone() const; + void waitForDevices(); void waitForDeviceList(); std::string getPreferredPlaybackDevice() const; @@ -176,15 +177,27 @@ private: NON_COPYABLE(PulseLayer); /** - * Create the audio streams into the given context - * @param c The pulseaudio context + * Create the audio stream */ - void createStreams(pa_context* c); + void createStream(std::unique_ptr<AudioStream>& stream, AudioDeviceType type, const PaDeviceInfos& dev_infos, bool ec, std::function<void(size_t)>&& onData); + + std::unique_ptr<AudioStream>& getStream(AudioDeviceType type) + { + if (type == AudioDeviceType::PLAYBACK) + return playback_; + else if (type == AudioDeviceType::RINGTONE) + return ringtone_; + else if (type == AudioDeviceType::CAPTURE) + return record_; + else + return playback_; + } /** * Close the connection with the local pulseaudio server */ void disconnectAudioStream(); + void onStreamReady(); /** * Returns a pointer to the PaEndpointInfos with the given name in sourceList_, or nullptr if @@ -193,6 +206,8 @@ private: const PaDeviceInfos* getDeviceInfos(const std::vector<PaDeviceInfos>&, const std::string& name) const; + std::atomic_uint pendingStreams {0}; + /** * A stream object to handle the pulseaudio playback stream */ @@ -229,7 +244,7 @@ private: bool enumeratingSinks_ {false}; bool enumeratingSources_ {false}; bool gettingServerInfo_ {false}; - bool waitingDeviceList_ {false}; + std::atomic_bool waitingDeviceList_ {false}; std::mutex readyMtx_ {}; std::condition_variable readyCv_ {}; std::thread streamStarter_ {}; @@ -241,5 +256,3 @@ private: }; } // namespace jami - -#endif // PULSE_LAYER_H_ diff --git a/src/preferences.h b/src/preferences.h index 6ef611226d..7d1d1e8a60 100644 --- a/src/preferences.h +++ b/src/preferences.h @@ -156,7 +156,7 @@ public: static std::vector<std::string> getSupportedAudioManagers(); - std::string getAudioApi() const { return audioApi_; } + const std::string& getAudioApi() const { return audioApi_; } void setAudioApi(const std::string& api) { audioApi_ = api; } @@ -175,7 +175,7 @@ public: void setAlsaCardring(int c) { alsaCardring_ = c; } - std::string getAlsaPlugin() const { return alsaPlugin_; } + const std::string& getAlsaPlugin() const { return alsaPlugin_; } void setAlsaPlugin(const std::string& p) { alsaPlugin_ = p; } @@ -183,19 +183,19 @@ public: void setAlsaSmplrate(int r) { alsaSmplrate_ = r; } // pulseaudio preference - std::string getPulseDevicePlayback() const { return pulseDevicePlayback_; } + const std::string& getPulseDevicePlayback() const { return pulseDevicePlayback_; } void setPulseDevicePlayback(const std::string& p) { pulseDevicePlayback_ = p; } - std::string getPulseDeviceRecord() const { return pulseDeviceRecord_; } + const std::string& getPulseDeviceRecord() const { return pulseDeviceRecord_; } void setPulseDeviceRecord(const std::string& r) { pulseDeviceRecord_ = r; } - std::string getPulseDeviceRingtone() const { return pulseDeviceRingtone_; } + const std::string& getPulseDeviceRingtone() const { return pulseDeviceRingtone_; } void setPulseDeviceRingtone(const std::string& r) { pulseDeviceRingtone_ = r; } // general preference - std::string getRecordPath() const { return recordpath_; } + const std::string& getRecordPath() const { return recordpath_; } // Returns true if directory is writeable bool setRecordPath(const std::string& r); @@ -226,7 +226,7 @@ public: void setPlaybackMuted(bool muted) { playbackMuted_ = muted; } - std::string getEchoCanceller() const { return echoCanceller_; } + const std::string& getEchoCanceller() const { return echoCanceller_; } void setEchoCanceller(const std::string& ec) { echoCanceller_ = ec; } -- GitLab