diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2021-04-27 18:49:19 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2021-04-27 18:49:19 +0000 |
| commit | 278dc516a8b9fd4b6bd7b2d82654048b756ddfb6 (patch) | |
| tree | 49902088a0063df77b980cda40848f56ca5b67a4 | |
| parent | a4d2cd0cd112fd21bf757b2d6021cc19c739e780 (diff) | |
| download | qmmp-278dc516a8b9fd4b6bd7b2d82654048b756ddfb6.tar.gz qmmp-278dc516a8b9fd4b6bd7b2d82654048b756ddfb6.tar.bz2 qmmp-278dc516a8b9fd4b6bd7b2d82654048b756ddfb6.zip | |
pipewire: added volume control
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@9843 90c681e8-e032-0410-971d-27865f9a5e38
| -rw-r--r-- | src/plugins/Output/pipewire/outputpipewire.cpp | 98 | ||||
| -rw-r--r-- | src/plugins/Output/pipewire/outputpipewire.h | 27 | ||||
| -rw-r--r-- | src/plugins/Output/pipewire/outputpipewirefactory.cpp | 4 |
3 files changed, 117 insertions, 12 deletions
diff --git a/src/plugins/Output/pipewire/outputpipewire.cpp b/src/plugins/Output/pipewire/outputpipewire.cpp index e4a043490..c1304afea 100644 --- a/src/plugins/Output/pipewire/outputpipewire.cpp +++ b/src/plugins/Output/pipewire/outputpipewire.cpp @@ -22,8 +22,12 @@ #include <QSettings> #include <QThread> #include <QtMath> +#include <spa/param/props.h> #include "outputpipewire.h" +OutputPipeWire *OutputPipeWire::instance = nullptr; +VolumePipeWire *OutputPipeWire::volumeControl = nullptr; + OutputPipeWire::OutputPipeWire(): Output() { m_pw_channels = { @@ -41,12 +45,14 @@ OutputPipeWire::OutputPipeWire(): Output() }; pw_init(nullptr, nullptr); + instance = this; } OutputPipeWire::~OutputPipeWire() { uninitialize(); pw_deinit(); + instance = nullptr; } void OutputPipeWire::onStateChanged (void *data, enum pw_stream_state old, @@ -70,6 +76,8 @@ void OutputPipeWire::onStateChanged (void *data, enum pw_stream_state old, case PW_STREAM_STATE_STREAMING: o->m_streamPaused = false; pw_thread_loop_signal(o->m_loop, false); + if(volumeControl) + instance->setMuted(volumeControl->isMuted()); break; default: break; @@ -94,6 +102,7 @@ bool OutputPipeWire::initialize(quint32 freq, ChannelMap map, Qmmp::AudioFormat .version = PW_VERSION_STREAM_EVENTS, .state_changed = OutputPipeWire::onStateChanged, .process = OutputPipeWire::onProcess, + .drained = OutputPipeWire::onDrained }; if(!(m_loop = pw_thread_loop_new("pipewire-main-loop", nullptr))) @@ -272,9 +281,11 @@ void OutputPipeWire::drain() { pw_thread_loop_lock(m_loop); if(m_buffer_at > 0) - pw_thread_loop_timed_wait(m_loop, 1); - pw_thread_loop_unlock(m_loop); + pw_thread_loop_timed_wait(m_loop, 2); + pw_stream_flush(m_stream, true); + pw_thread_loop_timed_wait(m_loop, 2); + pw_thread_loop_unlock(m_loop); } void OutputPipeWire::reset() @@ -287,8 +298,6 @@ void OutputPipeWire::reset() void OutputPipeWire::suspend() { - //pa_operation *op = pa_stream_cork(m_stream, 1, OutputPipeWire::stream_success_cb, nullptr); - //process(op); pw_thread_loop_lock(m_loop); pw_stream_set_active(m_stream, false); pw_thread_loop_unlock(m_loop); @@ -296,8 +305,6 @@ void OutputPipeWire::suspend() void OutputPipeWire::resume() { - //pa_operation *op = pa_stream_cork(m_stream, 0, OutputPipeWire::stream_success_cb, nullptr); - //process(op); pw_thread_loop_lock(m_loop); pw_stream_set_active(m_stream, true); pw_thread_loop_unlock(m_loop); @@ -305,9 +312,30 @@ void OutputPipeWire::resume() void OutputPipeWire::setMuted(bool mute) { - //pa_operation *op = pa_context_set_sink_input_mute(m_ctx, pa_stream_get_index(m_stream), mute, - // OutputPipeWire::context_success_cb, nullptr); - //pa_operation_unref(op); + setVolume(mute ? VolumeSettings() : volumeControl->volume()); +} + +void OutputPipeWire::setVolume(const VolumeSettings &v) +{ + qDebug() << Q_FUNC_INFO << v.left << v.right; + pw_thread_loop_lock(m_loop); + + float* values = new float[channels()]; + + if(channels() == 2) + { + values[0] = float(v.left) / 100.0; + values[1] = float(v.right) / 100.0; + } + else + { + for(int i = 0; i < channels(); ++i) + values[i] = float(qMax(v.left, v.right)) / 100.0; + } + + pw_stream_set_control(m_stream, SPA_PROP_channelVolumes, channels(), values, 0); + delete[] values; + pw_thread_loop_unlock(m_loop); } void OutputPipeWire::uninitialize() @@ -386,6 +414,13 @@ void OutputPipeWire::onProcess(void *data) pw_thread_loop_signal(o->m_loop, false); } +void OutputPipeWire::onDrained(void *data) +{ + OutputPipeWire *o = static_cast<OutputPipeWire *>(data); + pw_thread_loop_signal(o->m_loop, false); + qDebug("drained"); +} + void OutputPipeWire::onCoreEventDone(void *data, uint32_t id, int seq) { OutputPipeWire *o = static_cast<OutputPipeWire *>(data); @@ -422,3 +457,48 @@ void OutputPipeWire::onRegistryEventGlobal(void *data, uint32_t id, uint32_t per o->m_coreInitSeq = pw_core_sync(o->m_core, PW_ID_CORE, o->m_coreInitSeq); } + +VolumePipeWire::VolumePipeWire() +{ + QSettings settings(Qmmp::configFile(), QSettings::IniFormat); + m_volume.left = settings.value("OutputPipeWire/left_volume", 100).toInt(); + m_volume.right = settings.value("OutputPipeWire/right_volume", 100).toInt(); + OutputPipeWire::volumeControl = this; +} + +VolumePipeWire::~VolumePipeWire() +{ + QSettings settings(Qmmp::configFile(), QSettings::IniFormat); + settings.setValue("OutputPipeWire/left_volume", m_volume.left); + settings.setValue("OutputPipeWire/right_volume", m_volume.right); + OutputPipeWire::volumeControl = nullptr; +} + +void VolumePipeWire::setVolume(const VolumeSettings &vol) +{ + if(OutputPipeWire::instance) + OutputPipeWire::instance->setVolume(vol); + m_volume = vol; +} + +VolumeSettings VolumePipeWire::volume() const +{ + return m_volume; +} + +bool VolumePipeWire::isMuted() const +{ + return m_muted; +} + +void VolumePipeWire::setMuted(bool mute) +{ + if(OutputPipeWire::instance) + OutputPipeWire::instance->setMuted(mute); + m_muted = mute; +} + +Volume::VolumeFlags VolumePipeWire::flags() const +{ + return Volume::IsMuteSupported | Volume::HasNotifySignal; +} diff --git a/src/plugins/Output/pipewire/outputpipewire.h b/src/plugins/Output/pipewire/outputpipewire.h index 1b70a94d3..a53612005 100644 --- a/src/plugins/Output/pipewire/outputpipewire.h +++ b/src/plugins/Output/pipewire/outputpipewire.h @@ -29,7 +29,7 @@ #include <qmmp/output.h> #include <qmmp/volume.h> -class VolumePulseAudio; +class VolumePipeWire; /** @author Ilya Kotov <forkotov02@ya.ru> @@ -49,12 +49,17 @@ public: void suspend() override; void resume() override; void setMuted(bool mute); + void setVolume(const VolumeSettings &v); + + static OutputPipeWire *instance; + static VolumePipeWire *volumeControl; private: // helper functions void uninitialize(); //callbacks static void onProcess(void *data); + static void onDrained(void *data); static void onCoreEventDone(void *data, uint32_t id, int seq); static void onRegistryEventGlobal(void *data, uint32_t id, uint32_t permissions, const char *type, uint32_t version, @@ -97,4 +102,24 @@ private: QHash <Qmmp::ChannelPosition, spa_audio_channel> m_pw_channels; }; +class VolumePipeWire : public Volume +{ +public: + VolumePipeWire(); + ~VolumePipeWire(); + + //void updateVolume(const pa_cvolume &v, bool muted); + void setVolume(const VolumeSettings &vol) override; + VolumeSettings volume() const override; + bool isMuted() const override; + void setMuted(bool mute) override; + VolumeFlags flags() const override; + //static VolumeSettings cvolumeToVolumeSettings(const pa_cvolume &v); + //static pa_cvolume volumeSettingsToCvolume(const VolumeSettings &v, int channels); + +private: + VolumeSettings m_volume; + bool m_muted = false; +}; + #endif // OUTPUTPIPEWIRE_H diff --git a/src/plugins/Output/pipewire/outputpipewirefactory.cpp b/src/plugins/Output/pipewire/outputpipewirefactory.cpp index fa13c7d62..b12bf939c 100644 --- a/src/plugins/Output/pipewire/outputpipewirefactory.cpp +++ b/src/plugins/Output/pipewire/outputpipewirefactory.cpp @@ -41,10 +41,10 @@ Output* OutputPipeWireFactory::create() Volume *OutputPipeWireFactory::createVolume() { - return nullptr; + return new VolumePipeWire; } -void OutputPipeWireFactory::showSettings(QWidget* parent) +void OutputPipeWireFactory::showSettings(QWidget *parent) { Q_UNUSED(parent); } |
