aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2021-04-27 18:49:19 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2021-04-27 18:49:19 +0000
commit278dc516a8b9fd4b6bd7b2d82654048b756ddfb6 (patch)
tree49902088a0063df77b980cda40848f56ca5b67a4
parenta4d2cd0cd112fd21bf757b2d6021cc19c739e780 (diff)
downloadqmmp-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.cpp98
-rw-r--r--src/plugins/Output/pipewire/outputpipewire.h27
-rw-r--r--src/plugins/Output/pipewire/outputpipewirefactory.cpp4
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);
}