diff options
Diffstat (limited to 'src/plugins/pulseaudio')
-rw-r--r-- | src/plugins/pulseaudio/qaudioinput_pulse.cpp | 99 | ||||
-rw-r--r-- | src/plugins/pulseaudio/qaudioinput_pulse.h | 8 | ||||
-rw-r--r-- | src/plugins/pulseaudio/qaudiooutput_pulse.cpp | 84 | ||||
-rw-r--r-- | src/plugins/pulseaudio/qaudiooutput_pulse.h | 2 |
4 files changed, 56 insertions, 137 deletions
diff --git a/src/plugins/pulseaudio/qaudioinput_pulse.cpp b/src/plugins/pulseaudio/qaudioinput_pulse.cpp index ebf6f0a4b..050731071 100644 --- a/src/plugins/pulseaudio/qaudioinput_pulse.cpp +++ b/src/plugins/pulseaudio/qaudioinput_pulse.cpp @@ -40,6 +40,7 @@ #include <QtCore/qcoreapplication.h> #include <QtCore/qdebug.h> #include <QtCore/qmath.h> +#include <private/qaudiohelpers_p.h> #include "qaudioinput_pulse.h" #include "qaudiodeviceinfo_pulse.h" @@ -124,39 +125,12 @@ static void inputStreamSuccessCallback(pa_stream *stream, int success, void *use pa_threaded_mainloop_signal(pulseEngine->mainloop(), 0); } -void QPulseAudioInput::sourceInfoCallback(pa_context *context, const pa_source_info *i, int eol, void *userdata) -{ - Q_UNUSED(context); - Q_UNUSED(eol); - - Q_ASSERT(userdata); - if (i) { - QPulseAudioInput *that = reinterpret_cast<QPulseAudioInput*>(userdata); - that->m_volume = pa_sw_volume_to_linear(pa_cvolume_avg(&i->volume)); - } -} - -void QPulseAudioInput::inputVolumeCallback(pa_context *context, int success, void *userdata) -{ - Q_UNUSED(success); - - if (!success) - qWarning() << "QAudioInput: failed to set input volume"; - - QPulseAudioInput *that = reinterpret_cast<QPulseAudioInput*>(userdata); - - // Regardless of success or failure, we update the volume property - if (that->m_stream) - pa_context_get_source_info_by_index(context, pa_stream_get_device_index(that->m_stream), sourceInfoCallback, userdata); -} - QPulseAudioInput::QPulseAudioInput(const QByteArray &device) : m_totalTimeValue(0) , m_audioSource(0) , m_errorState(QAudio::NoError) , m_deviceState(QAudio::StoppedState) , m_volume(qreal(1.0f)) - , m_customVolumeRequired(false) , m_pullMode(true) , m_opened(false) , m_bytesAvailable(0) @@ -362,9 +336,6 @@ bool QPulseAudioInput::open() if (actualBufferAttr->tlength != (uint32_t)-1) m_bufferSize = actualBufferAttr->tlength; - if (m_customVolumeRequired) - setPulseVolume(); - pulseEngine->unlock(); connect(pulseEngine, &QPulseAudioEngine::contextFailed, this, &QPulseAudioInput::onPulseContextFailed); @@ -413,32 +384,6 @@ void QPulseAudioInput::close() m_opened = false; } -/* Call this with the stream opened and the mainloop locked */ -void QPulseAudioInput::setPulseVolume() -{ - QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); - Q_ASSERT(pulseEngine->context() != 0); - - pa_cvolume cvolume; - - if (qFuzzyCompare(m_volume, 0.0)) { - pa_cvolume_mute(&cvolume, m_spec.channels); - } else { - pa_cvolume_set(&cvolume, m_spec.channels, pa_sw_volume_from_linear(m_volume)); - } - - pa_operation *op = pa_context_set_source_volume_by_index(pulseEngine->context(), - pa_stream_get_device_index(m_stream), - &cvolume, - inputVolumeCallback, - this); - - if (op == NULL) - qWarning() << "QAudioInput: Failed to set volume"; - else - pa_operation_unref(op); -} - int QPulseAudioInput::checkBytesReady() { if (m_deviceState != QAudio::ActiveState && m_deviceState != QAudio::IdleState) { @@ -500,7 +445,9 @@ qint64 QPulseAudioInput::read(char *data, qint64 len) qint64 actualLength = 0; if (m_pullMode) { - actualLength = m_audioSource->write(static_cast<const char *>(audioBuffer), readLength); + QByteArray adjusted(readLength, Qt::Uninitialized); + applyVolume(audioBuffer, adjusted.data(), readLength); + actualLength = m_audioSource->write(adjusted); if (actualLength < qint64(readLength)) { pulseEngine->unlock(); @@ -512,7 +459,7 @@ qint64 QPulseAudioInput::read(char *data, qint64 len) } } else { actualLength = qMin(static_cast<int>(len - readBytes), static_cast<int>(readLength)); - memcpy(data + readBytes, audioBuffer, actualLength); + applyVolume(audioBuffer, data + readBytes, actualLength); } #ifdef DEBUG_PULSE @@ -523,7 +470,10 @@ qint64 QPulseAudioInput::read(char *data, qint64 len) #ifdef DEBUG_PULSE qDebug() << "QPulseAudioInput::read -- appending " << readLength - actualLength << " bytes of data to temp buffer"; #endif - m_tempBuffer.append(static_cast<const char *>(audioBuffer) + actualLength, readLength - actualLength); + int diff = readLength - actualLength; + int oldSize = m_tempBuffer.size(); + m_tempBuffer.resize(m_tempBuffer.size() + diff); + applyVolume(static_cast<const char *>(audioBuffer) + actualLength, m_tempBuffer.data() + oldSize, diff); QMetaObject::invokeMethod(this, "userFeed", Qt::QueuedConnection); } @@ -550,6 +500,14 @@ qint64 QPulseAudioInput::read(char *data, qint64 len) return readBytes; } +void QPulseAudioInput::applyVolume(const void *src, void *dest, int len) +{ + if (m_volume < 1.f) + QAudioHelperInternal::qMultiplySamples(m_volume, m_format, src, dest, len); + else + memcpy(dest, src, len); +} + void QPulseAudioInput::resume() { if (m_deviceState == QAudio::SuspendedState || m_deviceState == QAudio::IdleState) { @@ -573,30 +531,17 @@ void QPulseAudioInput::resume() void QPulseAudioInput::setVolume(qreal vol) { - if (vol >= 0.0 && vol <= 1.0) { - QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); - pulseEngine->lock(); - m_customVolumeRequired = true; - if (!qFuzzyCompare(m_volume, vol)) { - m_volume = vol; - if (m_opened) { - setPulseVolume(); - } - } - pulseEngine->unlock(); - } + if (qFuzzyCompare(m_volume, vol)) + return; + + m_volume = qBound(qreal(0), vol, qreal(1)); } qreal QPulseAudioInput::volume() const { - QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); - pulseEngine->lock(); - qreal vol = m_volume; - pulseEngine->unlock(); - return vol; + return m_volume; } - void QPulseAudioInput::setBufferSize(int value) { m_bufferSize = value; diff --git a/src/plugins/pulseaudio/qaudioinput_pulse.h b/src/plugins/pulseaudio/qaudioinput_pulse.h index c04cd1299..32a2c031c 100644 --- a/src/plugins/pulseaudio/qaudioinput_pulse.h +++ b/src/plugins/pulseaudio/qaudioinput_pulse.h @@ -106,8 +106,6 @@ public: QAudio::Error m_errorState; QAudio::State m_deviceState; qreal m_volume; - bool m_customVolumeRequired; - pa_cvolume m_chVolume; private slots: void userFeed(); @@ -118,13 +116,11 @@ private: void setState(QAudio::State state); void setError(QAudio::Error error); + void applyVolume(const void *src, void *dest, int len); + int checkBytesReady(); bool open(); void close(); - void setPulseVolume(); - - static void sourceInfoCallback(pa_context *c, const pa_source_info *i, int eol, void *userdata); - static void inputVolumeCallback(pa_context *context, int success, void *userdata); bool m_pullMode; bool m_opened; diff --git a/src/plugins/pulseaudio/qaudiooutput_pulse.cpp b/src/plugins/pulseaudio/qaudiooutput_pulse.cpp index f905e69ee..0c7dc270a 100644 --- a/src/plugins/pulseaudio/qaudiooutput_pulse.cpp +++ b/src/plugins/pulseaudio/qaudiooutput_pulse.cpp @@ -40,6 +40,7 @@ #include <QtCore/qcoreapplication.h> #include <QtCore/qdebug.h> #include <QtCore/qmath.h> +#include <private/qaudiohelpers_p.h> #include "qaudiooutput_pulse.h" #include "qaudiodeviceinfo_pulse.h" @@ -168,7 +169,6 @@ QPulseAudioOutput::QPulseAudioOutput(const QByteArray &device) , m_audioBuffer(0) , m_resuming(false) , m_volume(1.0) - , m_customVolumeRequired(false) { connect(m_tickTimer, SIGNAL(timeout()), SLOT(userFeed())); } @@ -318,27 +318,6 @@ bool QPulseAudioOutput::open() pa_stream_set_overflow_callback(m_stream, outputStreamOverflowCallback, this); pa_stream_set_latency_update_callback(m_stream, outputStreamLatencyCallback, this); - pa_volume_t paVolume; - - /* streams without a custom volume set are expected to already have a - * sensible volume set by Pulse, so we don't set it explicitly. - * - * explicit setting also breaks volume handling on sailfish, where each - * stream's volume is set separately inside pulseaudio, with the - * exception of streams that already have a volume set (i.e. if we set - * it here, we'd ignore system volume). - */ - if (m_customVolumeRequired) { - if (qFuzzyCompare(m_volume, 0.0)) { - paVolume = PA_VOLUME_MUTED; - m_volume = 0.0; - } else { - paVolume = qFloor(m_volume * PA_VOLUME_NORM + 0.5); - } - - pa_cvolume_set(&m_chVolume, m_spec.channels, paVolume); - } - if (m_bufferSize <= 0 && m_category == LOW_LATENCY_CATEGORY_NAME) { m_bufferSize = bytesPerSecond * LowLatencyBufferSizeMs / qint64(1000); } @@ -350,7 +329,7 @@ bool QPulseAudioOutput::open() requestedBuffer.prebuf = (uint32_t)-1; requestedBuffer.tlength = m_bufferSize; - if (pa_stream_connect_playback(m_stream, m_device.data(), (m_bufferSize > 0) ? &requestedBuffer : NULL, (pa_stream_flags_t)0, m_customVolumeRequired ? &m_chVolume : NULL, NULL) < 0) { + if (pa_stream_connect_playback(m_stream, m_device.data(), (m_bufferSize > 0) ? &requestedBuffer : NULL, (pa_stream_flags_t)0, NULL, NULL) < 0) { qWarning() << "pa_stream_connect_playback() failed!"; pa_stream_unref(m_stream); m_stream = 0; @@ -497,8 +476,33 @@ qint64 QPulseAudioOutput::write(const char *data, qint64 len) QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); pulseEngine->lock(); + len = qMin(len, static_cast<qint64>(pa_stream_writable_size(m_stream))); - pa_stream_write(m_stream, data, len, 0, 0, PA_SEEK_RELATIVE); + + if (m_volume < 1.0f) { + // Don't use PulseAudio volume, as it might affect all other streams of the same category + // or even affect the system volume if flat volumes are enabled + void *dest = NULL; + size_t nbytes = len; + if (pa_stream_begin_write(m_stream, &dest, &nbytes) < 0) { + qWarning("QAudioOutput(pulseaudio): pa_stream_begin_write, error = %s", + pa_strerror(pa_context_errno(pulseEngine->context()))); + setError(QAudio::IOError); + return 0; + } + + len = int(nbytes); + QAudioHelperInternal::qMultiplySamples(m_volume, m_format, data, dest, len); + data = reinterpret_cast<char *>(dest); + } + + if (pa_stream_write(m_stream, data, len, NULL, 0, PA_SEEK_RELATIVE) < 0) { + qWarning("QAudioOutput(pulseaudio): pa_stream_write, error = %s", + pa_strerror(pa_context_errno(pulseEngine->context()))); + setError(QAudio::IOError); + return 0; + } + pulseEngine->unlock(); m_totalTimeValue += len; @@ -670,34 +674,10 @@ qint64 PulseOutputPrivate::writeData(const char *data, qint64 len) void QPulseAudioOutput::setVolume(qreal vol) { - if (vol >= 0.0 && vol <= 1.0) { - if (!qFuzzyCompare(m_volume, vol)) { - m_customVolumeRequired = true; - m_volume = vol; - if (m_opened) { - QPulseAudioEngine *pulseEngine = QPulseAudioEngine::instance(); - pulseEngine->lock(); - pa_volume_t paVolume; - if (qFuzzyCompare(vol, 0.0)) { - pa_cvolume_mute(&m_chVolume, m_spec.channels); - m_volume = 0.0; - } else { - paVolume = qFloor(m_volume * PA_VOLUME_NORM + 0.5); - pa_cvolume_set(&m_chVolume, m_spec.channels, paVolume); - } - pa_operation *op = pa_context_set_sink_input_volume(pulseEngine->context(), - pa_stream_get_index(m_stream), - &m_chVolume, - NULL, - NULL); - if (op == NULL) - qWarning()<<"QAudioOutput: Failed to set volume"; - else - pa_operation_unref(op); - pulseEngine->unlock(); - } - } - } + if (qFuzzyCompare(m_volume, vol)) + return; + + m_volume = qBound(qreal(0), vol, qreal(1)); } qreal QPulseAudioOutput::volume() const diff --git a/src/plugins/pulseaudio/qaudiooutput_pulse.h b/src/plugins/pulseaudio/qaudiooutput_pulse.h index a628c6bae..58f175e18 100644 --- a/src/plugins/pulseaudio/qaudiooutput_pulse.h +++ b/src/plugins/pulseaudio/qaudiooutput_pulse.h @@ -141,8 +141,6 @@ private: QString m_category; qreal m_volume; - bool m_customVolumeRequired; - pa_cvolume m_chVolume; pa_sample_spec m_spec; }; |