From b1e4e2d83692bf9ebd6bc10fce6dadccdf6ac061 Mon Sep 17 00:00:00 2001 From: Albert Vaca Date: Thu, 4 Jul 2013 01:09:49 +0200 Subject: [PATCH] New networkpackage format and serialization using qjson and qvariantmap (and templates fun) --- daemon/CMakeLists.txt | 1 + daemon/announcers/avahiannouncer.cpp | 19 +++-- daemon/default_args.h | 61 ++++++++++++++ daemon/device.cpp | 16 ++-- daemon/device.h | 2 +- daemon/devicelinks/devicelink.h | 2 +- daemon/devicelinks/echodevicelink.h | 3 +- daemon/devicelinks/udpdevicelink.cpp | 15 ++-- daemon/devicelinks/udpdevicelink.h | 8 +- daemon/networkpackage.cpp | 81 ++++++++----------- daemon/networkpackage.h | 47 ++++++----- .../notificationpackagereceiver.cpp | 9 +-- .../pausemusicpackagereceiver.cpp | 6 +- kcm/devicesmodel.h | 4 +- kcm/kcm.cpp | 4 +- 15 files changed, 171 insertions(+), 107 deletions(-) create mode 100644 daemon/default_args.h diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt index 83e1bcc26..cc20a9ad7 100644 --- a/daemon/CMakeLists.txt +++ b/daemon/CMakeLists.txt @@ -26,6 +26,7 @@ target_link_libraries(kded_kdeconnect ${KDE4_KDECORE_LIBS} ${KDE4_KDEUI_LIBS} kdnssd + qjson ${QT_QTNETWORK_LIBRARY} ${QJSON_LIBRARIES} ${QJSON_LIBRARY} diff --git a/daemon/announcers/avahiannouncer.cpp b/daemon/announcers/avahiannouncer.cpp index 46979660a..8542fbb2f 100644 --- a/daemon/announcers/avahiannouncer.cpp +++ b/daemon/announcers/avahiannouncer.cpp @@ -58,18 +58,23 @@ void AvahiAnnouncer::readPendingNotifications() //log.write(datagram); qDebug() << "AvahiAnnouncer incomming udp datagram: " << datagram; - NetworkPackage np = NetworkPackage::fromString(datagram); + NetworkPackage np; + NetworkPackage::unserialize(datagram,&np); - QString id = np.deviceId(); - QString name = np.body(); + if (np.type() == "kdeconnect.identity") { - qDebug() << "AvahiAnnouncer creating link to device" << id; + QString id = np.get("deviceId"); + QString name = np.get("deviceName"); - DeviceLink* dl = new UdpDeviceLink(id, this, sender, 10600); - links.append(dl); + qDebug() << "AvahiAnnouncer creating link to device" << id; - emit onNewDeviceLink(id, name, dl); + DeviceLink* dl = new UdpDeviceLink(id, this, sender, 10600); + links.append(dl); + emit onNewDeviceLink(id, name, dl); + } else { + qDebug() << "Not an identification package (wuh?)"; + } } } diff --git a/daemon/default_args.h b/daemon/default_args.h new file mode 100644 index 000000000..4cf0fce1d --- /dev/null +++ b/daemon/default_args.h @@ -0,0 +1,61 @@ +/** + * Copyright 2013 Albert Vaca + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License or (at your option) version 3 or any later version + * accepted by the membership of KDE e.V. (or its successor approved + * by the membership of KDE e.V.), which shall act as a proxy + * defined in Section 14 of version 3 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef DEFAULTARG_H +#define DEFAULTARG_H + +#include + +template +struct default_arg { + static T get(); //Not defined for any other value +}; + +//bool -> false +template<> +struct default_arg { + static bool get() { return false; } +}; + +//int -> -1 +template<> +struct default_arg { + static int get() { return -1; } +}; + +//Pointer types -> NULL (partial specialization) +/*template +struct default_arg { + static T* get() { NULL; } +}; +*/ +//QStrings -> empty string +template<> +struct default_arg { + static QString get() { return QString(); } +}; + +template +struct default_arg { + static T* get() { return NULL;} +}; + + +#endif // DEFAULTARG_H diff --git a/daemon/device.cpp b/daemon/device.cpp index d03973f9a..53883fe94 100644 --- a/daemon/device.cpp +++ b/daemon/device.cpp @@ -78,15 +78,16 @@ void Device::removeLink(DeviceLink* link) m_deviceLinks.remove(m_deviceLinks.indexOf(link)); } -void Device::sendPackage(const NetworkPackage& np) +bool Device::sendPackage(const NetworkPackage& np) { - m_deviceLinks.first()->sendPackage(np); + if (m_deviceLinks.empty()) return false; + return m_deviceLinks.first()->sendPackage(np); } void Device::privateReceivedPackage(const NetworkPackage& np) { - if (np.type() == "IDENTITY" && !m_knownIdentiy) { - m_deviceName = np.body(); + if (np.type() == "kdeconnect.identity" && !m_knownIdentiy) { + m_deviceName = np.get("deviceName"); } else if (m_paired) { qDebug() << "package received from paired device"; emit receivedPackage(np); @@ -97,10 +98,9 @@ void Device::privateReceivedPackage(const NetworkPackage& np) void Device::sendPing() { - qDebug() << "sendPing"; - NetworkPackage np; - np.setType("PING"); - sendPackage(np); + NetworkPackage np("kdeconnect.ping"); + bool success = sendPackage(np); + qDebug() << "sendPing:" << success; } diff --git a/daemon/device.h b/daemon/device.h index 2517c6fb7..8055e4803 100644 --- a/daemon/device.h +++ b/daemon/device.h @@ -49,7 +49,7 @@ public: void addLink(DeviceLink*); void removeLink(DeviceLink*); - void sendPackage(const NetworkPackage& np); + bool sendPackage(const NetworkPackage& np); Q_SIGNALS: void receivedPackage(const NetworkPackage& np); diff --git a/daemon/devicelinks/devicelink.h b/daemon/devicelinks/devicelink.h index d1f659dfe..b690caf2a 100644 --- a/daemon/devicelinks/devicelink.h +++ b/daemon/devicelinks/devicelink.h @@ -40,7 +40,7 @@ public: const QString& deviceId() { return mDeviceId; } Announcer* announcer() { return mAnnouncer; } - virtual void sendPackage(const NetworkPackage& np) = 0; + virtual bool sendPackage(const NetworkPackage& np) = 0; signals: void receivedPackage(const NetworkPackage& np); diff --git a/daemon/devicelinks/echodevicelink.h b/daemon/devicelinks/echodevicelink.h index 53bcb7800..f3e5648bc 100644 --- a/daemon/devicelinks/echodevicelink.h +++ b/daemon/devicelinks/echodevicelink.h @@ -30,8 +30,9 @@ class EchoDeviceLink : public DeviceLink public: EchoDeviceLink(const QString& d, FakeAnnouncer* a); - void sendPackage(const NetworkPackage& np) { + bool sendPackage(const NetworkPackage& np) { emit receivedPackage(np); + return true; } }; diff --git a/daemon/devicelinks/udpdevicelink.cpp b/daemon/devicelinks/udpdevicelink.cpp index 0a577651e..e5aabb12f 100644 --- a/daemon/devicelinks/udpdevicelink.cpp +++ b/daemon/devicelinks/udpdevicelink.cpp @@ -28,9 +28,9 @@ UdpDeviceLink::UdpDeviceLink(const QString& d, AvahiAnnouncer* a, QHostAddress i mIp = ip; mPort = port; - mUdpSocket = new QUdpSocket(); - mUdpSocket->bind(port); - connect(mUdpSocket, SIGNAL(readyRead()), this, SLOT(readPendingNotifications())); + mSocket = new QUdpSocket(); + mSocket->bind(port); + connect(mSocket, SIGNAL(readyRead()), this, SLOT(readPendingNotifications())); } @@ -39,18 +39,19 @@ void UdpDeviceLink::readPendingNotifications() qDebug() << "UdpDeviceLink readPendingNotifications"; - while (mUdpSocket->hasPendingDatagrams()) { + while (mSocket->hasPendingDatagrams()) { QByteArray datagram; - datagram.resize(mUdpSocket->pendingDatagramSize()); + datagram.resize(mSocket->pendingDatagramSize()); QHostAddress sender; quint16 senderPort; - mUdpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); + mSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); //log.write(datagram); qDebug() << datagram; - NetworkPackage np = NetworkPackage::fromString(datagram); + NetworkPackage np; + NetworkPackage::unserialize(datagram,&np); emit receivedPackage(np); diff --git a/daemon/devicelinks/udpdevicelink.h b/daemon/devicelinks/udpdevicelink.h index e1819796a..0e9d47f5c 100644 --- a/daemon/devicelinks/udpdevicelink.h +++ b/daemon/devicelinks/udpdevicelink.h @@ -26,6 +26,7 @@ #include "devicelink.h" #include +#include class AvahiAnnouncer; @@ -36,15 +37,16 @@ class UdpDeviceLink : public DeviceLink public: UdpDeviceLink(const QString& d, AvahiAnnouncer* a, QHostAddress ip, quint16 port); - void sendPackage(const NetworkPackage& np) { - mUdpSocket->writeDatagram(np.toString(), mIp, mPort); + bool sendPackage(const NetworkPackage& np) { + mSocket->writeDatagram(np.serialize(),mIp,mPort); + return true; } private Q_SLOTS: void readPendingNotifications(); private: - QUdpSocket* mUdpSocket; + QUdpSocket* mSocket; QHostAddress mIp; quint16 mPort; diff --git a/daemon/networkpackage.cpp b/daemon/networkpackage.cpp index a5b5b547e..32c420191 100644 --- a/daemon/networkpackage.cpp +++ b/daemon/networkpackage.cpp @@ -24,64 +24,47 @@ #include #include #include +#include #include +#include +#include - -static QString decodeNextString(std::stringstream& ss) { - int length; - ss >> length; - char c[length]; - ss.get(); //Skip ws - ss.read(c,length); - return QString::fromAscii(c,length); -} - -NetworkPackage NetworkPackage::fromString(QByteArray s) +NetworkPackage::NetworkPackage(QString type) { - //FIXME: Find a better way of serialization - std::string stds(std::string(s.data())); - std::cout << stds << std::endl; - - std::stringstream ss(stds); - - NetworkPackage pp; - - long id; - ss >> id; - pp.mId = id; - - //qDebug() << "Decoding package with id:" << id; - - pp.mDeviceId = decodeNextString(ss); - - ss >> pp.mTime; - - std::string type; - ss >> type; - pp.mType = QString::fromStdString(type); - - pp.mBody = decodeNextString(ss); - - ss >> pp.mIsCancel; - - qDebug() << "Decoded package with id:" << id; - - return pp; - + mId = time(NULL); + mType = type; } - -QByteArray NetworkPackage::toString() const +QByteArray NetworkPackage::serialize() const { + //Object -> QVariant + //QVariantMap variant; + //variant["id"] = mId; + //variant["type"] = mType; + //variant["body"] = mBody; + QVariantMap variant = QJson::QObjectHelper::qobject2qvariant(this); - QByteArray s; - - //TODO - s += "HOLA"; - - return s; + //QVariant -> json + bool ok; + QJson::Serializer serializer; + QByteArray json = serializer.serialize(variant,&ok); + if (!ok) qDebug() << "D'oh!"; + return json; } +void NetworkPackage::unserialize(QByteArray a, NetworkPackage* np) +{ + //Json -> QVariant + QJson::Parser parser; + QVariantMap variant = parser.parse(a).toMap(); + //QVariant -> Object + //NetworkPackage np; + //QJSon json(a); + //np.mId = json["id"]; + //np.mType = json["type"]; + //np.mBody = json["body"]; + QJson::QObjectHelper::qvariant2qobject(variant,np); +} diff --git a/daemon/networkpackage.h b/daemon/networkpackage.h index b25219ed8..a31d42c82 100644 --- a/daemon/networkpackage.h +++ b/daemon/networkpackage.h @@ -21,44 +21,51 @@ #ifndef NETWORKPACKAGE_H #define NETWORKPACKAGE_H +#include #include #include +#include +#include "default_args.h" -class NetworkPackage +class NetworkPackage : public QObject { + Q_OBJECT + Q_PROPERTY( long id READ id WRITE setId ) + Q_PROPERTY( QString type READ type WRITE setType ) + Q_PROPERTY( QVariantMap body READ body WRITE setBody ) + Q_PROPERTY( int version READ version WRITE setVersion ) public: - NetworkPackage() { - mId = 3; - //TODO - } + NetworkPackage() {}; + NetworkPackage(QString type); - static NetworkPackage fromString(QByteArray); - QByteArray toString() const; + static void unserialize(QByteArray, NetworkPackage*); + QByteArray serialize() const; long id() const { return mId; } - const QString& deviceId() const { return mDeviceId; } const QString& type() const { return mType; } - const QString& body() const { return mBody; } - bool isCancel() const { return mIsCancel; } + QVariantMap& body() { return mBody; } + int version() const { return mVersion; } - void setId(long id) { mId = id; } - void setDeviceId(const QString& id) { mDeviceId = id; } - void setType(const QString& t) { mType = t; } - void setBody(const QString& b) { mBody = b; } - void setCancel(bool b) { mIsCancel = b; } + //Get and set info from body. Note that id, type and version can not be accessed through these. + template T get(const QString& property, const T& defaultValue = default_arg::get()) const { + return mBody.value(property,defaultValue).template value(); //Important note: Awesome template syntax is awesome + } + template void set(const QString& property, const T& value) const { return mBody[property].setValue(value); } private: + void setId(long id) { mId = id; } + void setType(const QString& t) { mType = t; } + void setBody(const QVariantMap& b) { mBody = b; } + void setVersion(int v) { mVersion = v; } long mId; - long mTime; - QString mDeviceId; QString mType; - QString mBody; - QVariant mExtra; - bool mIsCancel; + QVariantMap mBody; //json in the Android side + int mVersion; }; + #endif // NETWORKPACKAGE_H diff --git a/daemon/packagereceivers/notificationpackagereceiver.cpp b/daemon/packagereceivers/notificationpackagereceiver.cpp index aad15d8fd..b0da06db3 100644 --- a/daemon/packagereceivers/notificationpackagereceiver.cpp +++ b/daemon/packagereceivers/notificationpackagereceiver.cpp @@ -64,7 +64,7 @@ KNotification* NotificationPackageReceiver::createNotification(const NetworkPack notification->setPixmap(KIcon(icon).pixmap(48, 48)); notification->setComponentData(KComponentData("kdeconnect", "kdeconnect")); notification->setTitle(title); - notification->setText(np.body()); + notification->setText(np.get(QString("content"))); return notification; @@ -72,19 +72,18 @@ KNotification* NotificationPackageReceiver::createNotification(const NetworkPack bool NotificationPackageReceiver::receivePackage(const NetworkPackage& np) { - if (np.isCancel()) { + //if (np.get("isCancel")) { //It would be awesome to remove the old notification from the system tray here, but there is no way to do it :( //Now I realize why at the end of the day I have hundreds of notifications from facebook messages that I HAVE ALREADY READ, //...it's just because the telepathy client has no way to remove them! even when it knows that I have read those messages lol - //Here we have our awesome KDE notifications system, unusable and meant to fuck the user. - } else { + //} else { KNotification* n = createNotification(np); n->sendEvent(); - } + //} return true; diff --git a/daemon/packagereceivers/pausemusicpackagereceiver.cpp b/daemon/packagereceivers/pausemusicpackagereceiver.cpp index 74fa80059..7a85d6f05 100644 --- a/daemon/packagereceivers/pausemusicpackagereceiver.cpp +++ b/daemon/packagereceivers/pausemusicpackagereceiver.cpp @@ -30,11 +30,11 @@ PauseMusicPackageReceiver::PauseMusicPackageReceiver() bool PauseMusicPackageReceiver::receivePackage ( const NetworkPackage& np ) { - if (np.type() != "RINGING") return false; //TODO: Consider pauseOnlyAfterAnswering + if (np.get("eventType","") != "ring") return false; //TODO: Consider pauseOnlyAfterAnswering //TODO: Use KDE DBUS API - if (np.isCancel()) { - system("qdbus org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause"); + if (np.get("eventDetails") == "hang") { + system("qdbus org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Play"); } else { system("qdbus org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Pause"); } diff --git a/kcm/devicesmodel.h b/kcm/devicesmodel.h index ac8b44b24..cabdc24f6 100644 --- a/kcm/devicesmodel.h +++ b/kcm/devicesmodel.h @@ -50,8 +50,10 @@ public: DeviceDbusInterface* getDevice(const QModelIndex& index); -private Q_SLOTS: +public Q_SLOTS: void deviceStatusChanged(const QString& id); + +private Q_SLOTS: void deviceAdded(const QString& id); private: diff --git a/kcm/kcm.cpp b/kcm/kcm.cpp index 82568378e..fc909b470 100644 --- a/kcm/kcm.cpp +++ b/kcm/kcm.cpp @@ -75,7 +75,9 @@ void KdeConnectKcm::deviceSelected(const QModelIndex& current) void KdeConnectKcm::trustedStateChanged(bool b) { if (!selectedIndex.isValid()) return; - pairedDevicesList->getDevice(selectedIndex)->setPair(b); + DeviceDbusInterface* device = pairedDevicesList->getDevice(selectedIndex); + device->setPair(b); + pairedDevicesList->deviceStatusChanged(device->id()); }