Modify mixer to use the new pipewire audiomixer binding 75/21575/4
authorGeorge Kiagiadakis <george.kiagiadakis@collabora.com>
Fri, 22 Feb 2019 17:01:22 +0000 (19:01 +0200)
committerGeorge Kiagiadakis <george.kiagiadakis@collabora.com>
Mon, 10 Jun 2019 13:04:20 +0000 (16:04 +0300)
Bug-AGL: SPEC-2473

Signed-off-by: George Kiagiadakis <george.kiagiadakis@collabora.com>
Change-Id: I45595d6bde1b710fb81216676c3f8a390f4e5737

app/audiorole.cpp
app/audiorole.hpp
app/mixer.cpp
app/mixer.hpp
conf.d/wgt/config.xml.in

index 5fad48f..7351d13 100644 (file)
@@ -37,8 +37,7 @@ void AudioRole::setValue(int value)
        if (m_Value != value)
        {
                m_Value = value;
-               if (m_Updating == 0)
-                       emit ValueChanged();
+               emit ValueChanged();
        }
 }
 
@@ -47,8 +46,11 @@ void AudioRole::BeginUpdate()
        m_Updating++;
 }
 
-void AudioRole::EndUpdate()
+bool AudioRole::EndUpdate()
 {
-       if (m_Updating > 0) m_Updating--;
-       //if (m_Updating == 0) emit ValueChanged();
+       if (m_Updating > 0) {
+               m_Updating--;
+               return true;
+       }
+       return false;
 }
index afc3665..75d9148 100644 (file)
@@ -26,7 +26,7 @@ public:
        void setValue(int value);
 
        void BeginUpdate();
-       void EndUpdate();
+       bool EndUpdate();
 
 signals:
        void NameChanged();
index d85a431..873f1be 100644 (file)
@@ -22,6 +22,7 @@
 #include <QtDebug>
 #include "mixer.hpp"
 
+
 Mixer::Mixer(QObject* parent)
        : QObject(parent)
 {
@@ -42,66 +43,54 @@ QList<QObject*> Mixer::roles() const
        return m_roles;
 }
 
-void Mixer::getRoleVolume(AudioRole* role)
+void Mixer::setRoleVolume(AudioRole* role)
 {
        if (role == nullptr) return;
 
        QJsonObject arg;
-       arg.insert("action", "volume");
-       arg.insert("value", QJsonValue("+0")); // FIXME: Hack to get volume: ask for a relative change with a delta of zero
-
-       m_client.call("ahl-4a", role->Name().toLocal8Bit().data(), arg, [role](bool r, const QJsonValue& v) {
-               if (r && v.isObject())
-               {
-                       qDebug() << role->Name() << " Volume changed: " << v;
-                       int newVolume = v.toObject()["response"].toObject()["volnew"].toInt();
-                       role->setValue(newVolume);
-               }
-       });
+       arg.insert("control", role->Name().toLocal8Bit().data());
+       arg.insert("value", QJsonValue(role->Value()));
+
+       m_client.call("audiomixer", "volume", arg);
 }
 
-void Mixer::setRoleVolume(AudioRole* role)
+void Mixer::parseControls(const QJsonValue & v)
 {
-       if (role == nullptr) return;
-       role->BeginUpdate();
+       qDebug() << "got controls: " << v;
 
-       QJsonObject arg;
-       arg.insert("action", "volume");
-       arg.insert("value", QJsonValue(role->Value()));
-       m_client.call("ahl-4a", role->Name().toLocal8Bit().data(), arg, [role](bool r, const QJsonValue& v) {
-               // Nothing to do, events will update sliders
-               role->EndUpdate();
-       });
+       for(QObject* role : m_roles) delete role;
+       m_roles.clear();
+
+       for (const QJsonValue & av : v.toArray()) {
+               QString name = av.toObject()["control"].toString();
+               int value = av.toObject()["volume"].toDouble() * 100;
+               value = qBound(0, value, 100);
+
+               AudioRole *ar = new AudioRole(name, value);
+               connect(ar, SIGNAL(ValueChanged()), this, SLOT(onRoleValueChanged()));
+               m_roles.append(ar);
+
+               qDebug() << "added role: " << ar->Name()
+                       << " value: " << ar->Value();
+       }
+
+       emit rolesChanged();
 }
 
 void Mixer::onClientConnected()
 {
-       // Subscribe to 4a events
-       m_client.call("ahl-4a", "subscribe", QJsonValue(), [this](bool r, const QJsonValue& val) {
-               if (r) qDebug() << "Mixer::onClientConnected - subscribed to 4a events!";
-               else qCritical () << "Mixer::onClientConnected - Failed to subscribe to 4a events!";
-       });
-
-       // Call HAL to populate list
-       m_client.call("ahl-4a", "get_roles", QJsonValue(), [this](bool r, const QJsonValue& val) {
-               if (r)
-               {
-                       for(QObject* role : m_roles) delete role;
-                       m_roles.clear();
-
-                       QJsonArray cards = val.toObject()["response"].toArray();
-                       foreach (const QJsonValue& card, cards)
-                       {
-                               AudioRole* ar = new AudioRole(card.toString(), 0);
-                               getRoleVolume(reinterpret_cast<AudioRole*>(ar));
-                               connect(ar, SIGNAL(ValueChanged()), this, SLOT(onRoleValueChanged()));
-                               m_roles.append(ar);
-                               qDebug() << "Mixer::onClientConnected - added this HAL: " << card.toString();
-                       }
-                       emit rolesChanged();
+       m_client.call("audiomixer", "list_controls", QJsonObject(), [this](bool r, const QJsonValue& v) {
+               if (r && v.isObject()) {
+                       parseControls(v.toObject()["response"]);
                }
-       });
 
+               QJsonObject arg;
+               arg.insert("event", "controls_changed");
+               m_client.call("audiomixer", "subscribe", arg);
+
+               arg.insert("event", "volume_changed");
+               m_client.call("audiomixer", "subscribe", arg);
+       });
 }
 
 void Mixer::onClientDisconnected()
@@ -118,16 +107,24 @@ void Mixer::onClientError(QAbstractSocket::SocketError se)
 void Mixer::onClientEventReceived(QString eventName, const QJsonValue& data)
 {
        qDebug() << "Mixer::onClientEventReceived[" << eventName << "]: " << data;
-       if (eventName == "ahl-4a/volume_changed")
-       {
-               QString role = data.toObject()["role"].toString();
-               int volume = data.toObject()["volume"].toInt();
-               for(QObject* o : m_roles)
-               {
-                       AudioRole* ar = reinterpret_cast<AudioRole*>(o);
-                       if (ar && ar->Name() == role)
-                       {
-                               ar->setValue(volume);
+
+       if (eventName == "audiomixer/controls_changed") {
+               m_client.call("audiomixer", "list_controls", QJsonObject(), [this](bool r, const QJsonValue& v) {
+                       if (r && v.isObject()) {
+                               parseControls(v.toObject()["response"]);
+                       }
+               });
+       }
+       else if (eventName == "audiomixer/volume_changed") {
+               QString name = data.toObject()["control"].toString();
+               int value = data.toObject()["value"].toDouble() * 100;
+               value = qBound(0, value, 100);
+
+               for (AudioRole *ar : m_roles) {
+                       if (ar->Name() == name) {
+                               ar->BeginUpdate();
+                               ar->setValue(value);
+                               break;
                        }
                }
        }
@@ -135,9 +132,13 @@ void Mixer::onClientEventReceived(QString eventName, const QJsonValue& data)
 
 void Mixer::onRoleValueChanged()
 {
-       AudioRole* role = reinterpret_cast<AudioRole*>(QObject::sender());
+       AudioRole* role = qobject_cast<AudioRole*>(QObject::sender());
        if (role == nullptr) return;
-       setRoleVolume(role);
+
+       /* if the role was not being updated by us, it was modified from the UI,
+          in which case we have to set it to the backend */
+       if (!role->EndUpdate())
+               setRoleVolume(role);
 }
 
 void Mixer::TryOpen()
index 73f31fc..545553d 100644 (file)
@@ -42,7 +42,6 @@ public:
 
        Q_INVOKABLE void open(const QUrl& url);
        Q_INVOKABLE QList<QObject*> roles() const;
-       Q_INVOKABLE void getRoleVolume(AudioRole* role);
        Q_INVOKABLE void setRoleVolume(AudioRole* role);
 
 signals:
@@ -50,6 +49,7 @@ signals:
        void volumeChanged(const QString& name, int value);
 
 private slots:
+       void parseControls(const QJsonValue & v);
        void onClientConnected();
        void onClientDisconnected();
        void onClientError(QAbstractSocket::SocketError se);
index 520342e..5688630 100644 (file)
   <feature name="urn:AGL:widget:required-api">
     <param name="windowmanager" value="ws" />
     <param name="homescreen" value="ws" />
-    <param name="ahl-4a" value="ws" />
+    <param name="audiomixer" value="ws" />
   </feature>
   <feature name="urn:AGL:widget:required-permission">
     <param name="urn:AGL:permission::public:no-htdocs" value="required" />
-    <param name="urn:AGL:permission::public:4a-audio-mixer" value="required" />
     <param name="urn:AGL:permission::public:display" value="required" />
   </feature>
 </widget>