aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Collignon <loic.collignon@iot.bzh>2018-12-13 09:46:10 +0100
committerLoïc Collignon <loic.collignon@iot.bzh>2018-12-13 11:35:50 +0100
commit1b8ad361e3955ee469a38486a715bc0dc615c59f (patch)
treef567b88733a40b41f497f316d3aa4ccc8a6fa10b
parent09f1cb780345b0e975fd4d74b32c38e5e9596f63 (diff)
Handle the volume_changed event
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>
-rw-r--r--app/main.cpp41
-rw-r--r--app/mixer.cpp140
-rw-r--r--app/mixer.h14
3 files changed, 118 insertions, 77 deletions
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>("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();
}
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 <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 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 <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);
};