From 1b8ad361e3955ee469a38486a715bc0dc615c59f Mon Sep 17 00:00:00 2001 From: Loïc Collignon Date: Thu, 13 Dec 2018 09:46:10 +0100 Subject: Handle the volume_changed event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- app/main.cpp | 41 ++++++++--------- app/mixer.cpp | 140 +++++++++++++++++++++++++++++++++++++--------------------- app/mixer.h | 14 +++--- 3 files changed, 118 insertions(+), 77 deletions(-) (limited to 'app') diff --git a/app/main.cpp b/app/main.cpp index bdc0c5f..c0d4b5b 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -54,7 +54,7 @@ int main(int argc, char *argv[]) parser.process(app); QStringList positionalArguments = parser.positionalArguments(); - qmlRegisterType("Mixer", 1, 0, "Mixer"); + qmlRegisterType("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 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(mobjs.first()); + QQuickWindow *window = qobject_cast(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(); } diff --git a/app/mixer.cpp b/app/mixer.cpp index ccb16d6..6627987 100644 --- a/app/mixer.cpp +++ b/app/mixer.cpp @@ -18,82 +18,120 @@ #include #include +#include #include #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 QUrl& url) { - 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); + } + }); } diff --git a/app/mixer.h b/app/mixer.h index 1eb6b76..5cbb819 100644 --- a/app/mixer.h +++ b/app/mixer.h @@ -23,7 +23,6 @@ #include #include #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 volumes_; + QUrl m_url; + QMap 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); }; -- cgit 1.2.3-korg