From d14723bc3ec4c96ed02a08d1ff74c25e88225ef6 Mon Sep 17 00:00:00 2001 From: Javier Date: Sun, 27 Dec 2015 21:57:50 +0100 Subject: implement the music agent --- hostmanagerconn.cc | 1 + hostmanagerconn.h | 1 - libwatchfish | 2 +- musicconn.cc | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++--- musicconn.h | 10 +++- sapbtpeer.cc | 2 +- sapsocket.cc | 2 - 7 files changed, 159 insertions(+), 12 deletions(-) diff --git a/hostmanagerconn.cc b/hostmanagerconn.cc index 18c61c9..1f87ef2 100644 --- a/hostmanagerconn.cc +++ b/hostmanagerconn.cc @@ -3,6 +3,7 @@ #include #include #include +#include #if SAILFISH #include diff --git a/hostmanagerconn.h b/hostmanagerconn.h index 1361d21..6b89add 100644 --- a/hostmanagerconn.h +++ b/hostmanagerconn.h @@ -2,7 +2,6 @@ #define HOSTMANAGERPEER_H #include -#include #include "sapconnection.h" #include "sapsocket.h" diff --git a/libwatchfish b/libwatchfish index ffeca2b..41677b5 160000 --- a/libwatchfish +++ b/libwatchfish @@ -1 +1 @@ -Subproject commit ffeca2b8740fba10e916fe04e89ef2fd5c606a90 +Subproject commit 41677b58d971ab57a79514d972f10acb04797130 diff --git a/musicconn.cc b/musicconn.cc index 45a00fb..cfc375d 100644 --- a/musicconn.cc +++ b/musicconn.cc @@ -1,5 +1,8 @@ #include +#include #include +#include +#include #include "sappeer.h" #include "musicconn.h" @@ -20,21 +23,159 @@ MusicConn::MusicConn(SAPConnection *conn, QObject *parent) connect(_socket, SIGNAL(messageReceived()), SLOT(handleMessageReceived())); } -MusicConn::~MusicConn() +QString MusicConn::encodeAlbumArt(const QString &albumArt) { - qDebug() << "Music terminated"; + QImage image; + + if (image.load(albumArt)) { + QByteArray imgData; + QBuffer buf(&imgData); + buf.open(QIODevice::WriteOnly); + image = image.scaled(160, 160, Qt::KeepAspectRatio); + image.save(&buf, "JPEG", 60); + buf.close(); + + return QString::fromLatin1(imgData.toBase64()); + } else { + return QString(); + } +} + +void MusicConn::sendMessage(const QJsonObject &msg) +{ + QJsonDocument doc(msg); + QByteArray data = doc.toJson(QJsonDocument::Compact); + + qDebug() << data; + + _socket->send(data); +} + +void MusicConn::handleMessage(const QJsonObject &msg) +{ + const QString msgId = msg["msgId"].toString(); + if (msgId == "music-mediachanged-req") { + sendResponse("music-mediachanged-rsp", "success", 0); + sendMediaChangedInd(); + } else if (msgId == "music-getattribute-req") { + QJsonObject rsp; + rsp.insert("msgId", QLatin1String("music-getattribute-rsp")); + rsp.insert("result", QLatin1String("success")); + rsp.insert("reason", 0); + QString repeat("repeatoff"), shuffle("off"); + int volume = 100; +#if SAILFISH + switch (controller->repeat()) { + case watchfish::MusicController::RepeatNone: + repeat = "repeatoff"; + break; + case watchfish::MusicController::RepeatTrack: + repeat = "repeatone"; + break; + case watchfish::MusicController::RepeatPlaylist: + repeat = "repeatall"; + break; + } + + if (controller->shuffle()) { + shuffle = "on"; + } +#endif + rsp.insert("repeat", repeat); + rsp.insert("shuffle", shuffle); + rsp.insert("volume", volume); + + sendMessage(rsp); + } else if (msgId == "music-remotecontrol-req") { + QString action = msg["action"].toString(); + QString status = msg["status"].toString(); + bool pressed = status == "pressed"; + +#if SAILFISH + if (action == "playpause" && pressed) { + controller->playPause(); + } else if (action == "forward" && pressed) { + controller->next(); + } else if (action == "rewind" && pressed) { + controller->previous(); + } +#endif + } +} + +void MusicConn::sendResponse(const QString &id, const QString &result, int reason) +{ + QJsonObject obj; + obj.insert("msgId", id); + obj.insert("result", result); + obj.insert("reason", reason); + sendMessage(obj); +} + +void MusicConn::sendMediaChangedInd() +{ + QJsonObject obj; + obj.insert("msgId", QLatin1String("music-mediachanged-ind")); + +#if SAILFISH + obj.insert("artist", controller->artist()); + obj.insert("album", controller->album()); + obj.insert("title", controller->title()); + obj.insert("duration", QString::number(controller->duration())); + obj.insert("audioId", QString()); + obj.insert("artistId", QString()); + obj.insert("albumId", QString()); + obj.insert("albumArt", QString()); + if (controller->status() == watchfish::MusicController::StatusPlaying) { + obj.insert("playStatus", QLatin1String("true")); + } else { + obj.insert("playStatus", QLatin1String("false")); + } + QString albumArtPath = controller->albumArt(); + if (!albumArtPath.isEmpty()) { + obj.insert("image", encodeAlbumArt(albumArtPath)); + } else { + obj.insert("image", QString()); + } + obj.insert("favoriteStatus", QLatin1String("false")); +#endif + + sendMessage(obj); } void MusicConn::handleConnected() { qDebug() << "Music connected"; +#if SAILFISH + if (!controller) { + controller = new watchfish::MusicController; + } + connect(controller, &watchfish::MusicController::metadataChanged, + this, &MusicConn::handleMetadataChanged); + connect(controller, &watchfish::MusicController::statusChanged, + this, &MusicConn::handleMetadataChanged); +#endif } void MusicConn::handleMessageReceived() { - qDebug() << "Music msg received"; QByteArray data = _socket->receive(); - qDebug() << data.toHex(); - qDebug() << QString::fromLatin1(data); - qDebug() << "Fini"; + + qDebug() << "Music msg received" << data; + + QJsonParseError error; + QJsonDocument json = QJsonDocument::fromJson(data, &error); + + if (json.isObject()) { + handleMessage(json.object()); + } else { + qWarning() << "Cannot parse JSON msg:" << error.errorString(); + } +} + +void MusicConn::handleMetadataChanged() +{ + if (_socket->isOpen()) { + sendMediaChangedInd(); + } } diff --git a/musicconn.h b/musicconn.h index 7b0934d..3cee914 100644 --- a/musicconn.h +++ b/musicconn.h @@ -11,13 +11,21 @@ class MusicConn : public QObject public: MusicConn(SAPConnection *conn, QObject *parent = 0); - ~MusicConn(); protected: + static QString encodeAlbumArt(const QString &albumArt); + +private: + void sendMessage(const QJsonObject &msg); + void handleMessage(const QJsonObject &msg); + + void sendResponse(const QString &id, const QString &result, int reason); + void sendMediaChangedInd(); private slots: void handleConnected(); void handleMessageReceived(); + void handleMetadataChanged(); private: SAPConnection *_conn; diff --git a/sapbtpeer.cc b/sapbtpeer.cc index 94f370a..188c37b 100644 --- a/sapbtpeer.cc +++ b/sapbtpeer.cc @@ -5,7 +5,7 @@ #include "sapsocket.h" #include "sapbtpeer.h" -#define PROTO_DEBUG 1 +#define PROTO_DEBUG 0 SAPBTPeer::SAPBTPeer(SAProtocol::Role role, QBluetoothSocket *socket, QObject *parent) : SAPPeer(role, socket->localAddress().toString(), socket->peerAddress().toString(), parent), diff --git a/sapsocket.cc b/sapsocket.cc index c8219a9..390aef0 100644 --- a/sapsocket.cc +++ b/sapsocket.cc @@ -95,8 +95,6 @@ void SAPSocket::acceptIncomingData(const QByteArray &data) SAProtocol::DataFrame frame = SAProtocol::unpackDataFrame(data, isReliable(), supportsFragmentation()); - qDebug() << data.mid(0, 6).toHex() << frame.data.mid(0, 6).toHex(); - if (isReliable()) { quint16 expectedSeqNum = _inLastSeqNum + 1; if (frame.seqNum != expectedSeqNum) { -- cgit v1.2.3