Handle the volume_changed event 65/18865/2
authorLoïc Collignon <loic.collignon@iot.bzh>
Thu, 13 Dec 2018 08:46:10 +0000 (09:46 +0100)
committerLoïc Collignon <loic.collignon@iot.bzh>
Thu, 13 Dec 2018 10:35:50 +0000 (11:35 +0100)
4A's High Level API now raises event when volume of a role is changed.
This handles it by subscribing to the event and update the corresponding
slider.

Bug: SPEC-2054

Change-Id: I137eaa461f0baa9206ee714c91e3ac998b9b2bf2
Signed-off-by: Loïc Collignon <loic.collignon@iot.bzh>
app/main.cpp
app/mixer.cpp
app/mixer.h

index bdc0c5f..c0d4b5b 100644 (file)
@@ -54,7 +54,7 @@ int main(int argc, char *argv[])
        parser.process(app);
        QStringList positionalArguments = parser.positionalArguments();
 
-        qmlRegisterType<Mixer>("Mixer", 1, 0, "Mixer");
+       qmlRegisterType<Mixer>("Mixer", 1, 0, "Mixer");
 
        QQmlApplicationEngine engine;
        if (positionalArguments.length() == 2) {
@@ -87,11 +87,11 @@ int main(int argc, char *argv[])
                if (qwm->requestSurface(graphic_role) != 0) {
                        exit(EXIT_FAILURE);
                }
-               // Create an event callbnewack against an event type. Here a lambda is called when SyncDraw event occurs
-            qwm->set_event_handler(QLibWindowmanager::Event_SyncDraw, [qwm, &graphic_role](json_object*) {
-                               fprintf(stderr, "Surface got syncDraw!\n");
-                               qwm->endDraw(graphic_role);
-                       });
+               // Create an event callbnewack against an event type. Here a lambda is called when SyncDraw event occurs
+               qwm->set_event_handler(QLibWindowmanager::Event_SyncDraw, [qwm, &graphic_role](json_object*) {
+                       fprintf(stderr, "Surface got syncDraw!\n");
+                       qwm->endDraw(graphic_role);
+               });
 
                // HomeScreen
                std::string token = secret.toStdString();
@@ -102,29 +102,30 @@ int main(int argc, char *argv[])
                        qwm->activateWindow(graphic_role);
                });
 #endif
+
                engine.load(QUrl(QStringLiteral("qrc:/Mixer.qml")));
 
                // Find the instantiated model QObject and connect the signals/slots
                QList<QObject*> mobjs = engine.rootObjects();
-                if (mobjs.empty())
-                {
-                    qDebug() << "[ERROR] Failed to load QML!";
-                    return -1;
-                }
+               if (mobjs.empty())
+               {
+                       qDebug() << "[ERROR] Failed to load QML!";
+                       return -1;
+               }
 
-                QQuickWindow *window = qobject_cast<QQuickWindow *>(mobjs.first());
+               QQuickWindow *window = qobject_cast<QQuickWindow *>(mobjs.first());
 #ifdef NATIVE_BUILD
-                window->setFlags(window->flags() & ~Qt::FramelessWindowHint); // Remove the borderless flag
-                window->setHeight(QGuiApplication::primaryScreen()->geometry().height());
+               window->setFlags(window->flags() & ~Qt::FramelessWindowHint); // Remove the borderless flag
+               window->setHeight(QGuiApplication::primaryScreen()->geometry().height());
 #else
-                QObject::connect(window, SIGNAL(frameSwapped()), qwm, SLOT(slotActivateWindow()));
+               QObject::connect(window, SIGNAL(frameSwapped()), qwm, SLOT(slotActivateWindow()));
 #endif
        }
-        else
-        {
-            qDebug() << "[ERROR] No port and token specified!";
-            return -1;
-        }
+       else
+       {
+               qDebug() << "[ERROR] No port and token specified!";
+               return -1;
+       }
 
        return app.exec();
 }
index ccb16d6..6627987 100644 (file)
 
 #include <QJsonArray>
 #include <QJsonObject>
+#include <QTimer>
 #include <QtDebug>
 #include "mixer.h"
 
 Mixer::Mixer(QObject* parent)
     : QObject(parent)
 {
-    connect(&m_client, SIGNAL(connected()), this, SLOT(onClientConnected()));
+       connect(&m_client, SIGNAL(connected()), this, SLOT(onClientConnected()));
+       connect(&m_client, SIGNAL(disconnected()), this, SLOT(onClientDisconnected()));
+       connect(&m_client, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onClientError(QAbstractSocket::SocketError)));
+       connect(&m_client, SIGNAL(eventReceived(QString, const QJsonValue&)), this, SLOT(onClientEventReceived(QString, const QJsonValue&)));
+
+       m_roles.append("Multimedia");
+       m_roles.append("Navigation");
+       m_roles.append("Emergency");
 }
 
 QStringList Mixer::roles() const
 {
-    return m_roles;
+       return m_roles;
 }
 
-void Mixer::open(const QUrl &url)
+void Mixer::open(const QUrlurl)
 {
-    m_client.open(url);
+       m_url = url;
+       m_client.open(m_url);
 }
 
 void Mixer::onClientConnected()
 {
-    // Call HAL to populate list
-    m_client.call("ahl-4a", "get_roles", QJsonValue(), [this](bool r, const QJsonValue& val) {
-        if (r)
-        {
-            m_roles.clear();
-            //BUG: should be able to add this, but not handled right now: m_roles.append("playback");
-            QJsonArray cards = val.toObject()["response"].toArray();
-            foreach (const QJsonValue& card, cards)
-            {
-                m_roles.append(card.toString());
-                qDebug() << "Mixer::onClientConnected - added this HAL: " << card.toString();
-            }
-            emit rolesChanged();
-        }
-    });
+       // 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)
+               {
+                       m_roles.clear();
+                       //BUG: should be able to add this, but not handled right now: m_roles.append("playback");
+                       QJsonArray cards = val.toObject()["response"].toArray();
+                       foreach (const QJsonValue& card, cards)
+                       {
+                               m_roles.append(card.toString());
+                               qDebug() << "Mixer::onClientConnected - added this HAL: " << card.toString();
+                       }
+                       emit rolesChanged();
+               }
+       });
+}
+
+void Mixer::onClientDisconnected()
+{
+       qDebug() << "Mixer::onClientDisconnected";
+       QTimer::singleShot(1000, this, SLOT(onRetryOpen()));
+}
+
+void Mixer::onClientError(QAbstractSocket::SocketError se)
+{
+       qDebug() << "Mixer::onClientError: " << se;
+}
+
+void Mixer::onRetryOpen()
+{
+       m_client.open(m_url);
+}
+
+void Mixer::onClientEventReceived(QString eventName, const QJsonValue& data)
+{
+       qDebug() << "Mixer::onClientEventReceived[" << eventName << "]: " << data;
+       if (eventName == "ahl-4a/volume_changed")
+       {
+               QString role = data["role"].toString();
+               int volume = data["volume"].toInt();
+               m_volumes[role] = volume;
+               emit volumeChanged(role, volume);
+       }
 }
 
 void Mixer::setVolume(const QString& name, int value)
 {
-    QJsonObject arg;
-    arg.insert("action", "volume");
-    arg.insert("value", QJsonValue(value));
-    m_client.call("ahl-4a", name, arg, [name](bool r, const QJsonValue& v) {
-        if (r && v.isObject())
-        {
-                       // TODO: Success, update the slider
-        }
-        else
-        {
-                       // TODO: Failed, reset the slider to previous value
-        }
-    });
+       auto currentVolume = m_volumes.find(name);
+       if (currentVolume != m_volumes.end() && *currentVolume == value)
+        return;
+
+       QJsonObject arg;
+       arg.insert("action", "volume");
+       arg.insert("value", QJsonValue(value));
+       m_client.call("ahl-4a", name, arg, [name](bool r, const QJsonValue& v) {
+               /* Nothing to do, events will update sliders*/
+       });
 }
 
 void Mixer::getVolume(const QString& name)
 {
-    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", name, arg, [this, name](bool r, const QJsonValue& v) {
-        if (r && v.isObject())
-        {
+       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", name, arg, [this, name](bool r, const QJsonValue& v) {
+               if (r && v.isObject())
+               {
                        // TODO: Success, update the slider
-            qDebug() << "Volume changed: " << v;
-            int newVolume = v.toObject()["response"].toObject()["volnew"].toInt();
-            auto currentVolume = volumes_.find(name);
-            if (currentVolume != volumes_.end() && *currentVolume == newVolume)
-                return;
+                       qDebug() << "Volume changed: " << v;
+                       int newVolume = v.toObject()["response"].toObject()["volnew"].toInt();
+                       auto currentVolume = m_volumes.find(name);
+                       if (currentVolume != m_volumes.end() && *currentVolume == newVolume)
+                               return;
 
-            volumes_[name] = newVolume;
-            emit volumeChanged(name, newVolume);
-        }
-        else
-        {
-                       // TODO: Failed, what to do ?
-        }
-    });
+                       m_volumes[name] = newVolume;
+                       emit volumeChanged(name, newVolume);
+               }
+       });
 }
index 1eb6b76..5cbb819 100644 (file)
@@ -23,7 +23,6 @@
 #include <QStringList>
 #include <QMap>
 #include "qafbwebsocketclient.h"
-//#include "volumeslider.h"
 
 class Mixer
     : public QObject
@@ -32,7 +31,10 @@ class Mixer
     Q_PROPERTY(QStringList roles READ roles NOTIFY rolesChanged)
 
 private:
-    QMap<QString, int> volumes_;
+    QUrl m_url;
+    QMap<QString, int> m_volumes;
+    QStringList m_roles;
+    QAfbWebsocketClient m_client;
 
 public:
     explicit Mixer(QObject* parent = nullptr);
@@ -49,8 +51,8 @@ signals:
 
 private slots:
     void onClientConnected();
-
-private:
-    QStringList m_roles;
-    QAfbWebsocketClient m_client;
+    void onClientDisconnected();
+    void onClientError(QAbstractSocket::SocketError se);
+    void onRetryOpen();
+    void onClientEventReceived(QString eventName, const QJsonValue& data);
 };