diff options
| author | Javier <dev.git@javispedro.com> | 2014-11-23 19:53:30 +0100 | 
|---|---|---|
| committer | Javier <dev.git@javispedro.com> | 2014-11-23 19:53:30 +0100 | 
| commit | 9949c02b0f814ad94a27864a5c39689f090299b6 (patch) | |
| tree | 90e2893d5aafc14a020754eaf72a2df99e373efb | |
| parent | 5244f7909e04b23fbd5706dc6bcadafba21f7600 (diff) | |
| download | sapd-9949c02b0f814ad94a27864a5c39689f090299b6.tar.gz sapd-9949c02b0f814ad94a27864a5c39689f090299b6.zip  | |
port to sailfish with qt 5.2
| -rw-r--r-- | endianhelpers.h | 2 | ||||
| -rw-r--r-- | main.cc | 23 | ||||
| -rw-r--r-- | notificationconn.cc | 61 | ||||
| -rw-r--r-- | notificationconn.h | 8 | ||||
| -rw-r--r-- | rpm/sapd.yaml | 27 | ||||
| -rw-r--r-- | sailfish/notificationmonitor.cpp | 79 | ||||
| -rw-r--r-- | sailfish/notificationmonitor.h | 28 | ||||
| -rw-r--r-- | sailfish/org.freedesktop.Notifications.xml | 17 | ||||
| -rw-r--r-- | sapbtlistener.cc | 22 | ||||
| -rw-r--r-- | sapbtlistener.h | 9 | ||||
| -rw-r--r-- | sapbtpeer.h | 4 | ||||
| -rw-r--r-- | sapd.pro | 31 | ||||
| -rw-r--r-- | saprotocol.h | 4 | 
13 files changed, 284 insertions, 31 deletions
diff --git a/endianhelpers.h b/endianhelpers.h index f11c669..3060382 100644 --- a/endianhelpers.h +++ b/endianhelpers.h @@ -10,7 +10,7 @@ template<typename T>  inline T read(const QByteArray &data, int &offset)  {  	T unswapped; -	qMemCopy(&unswapped, &data.constData()[offset], sizeof(T)); // Unaligned access warning! +	memcpy(&unswapped, &data.constData()[offset], sizeof(T)); // Unaligned access warning!  	offset += sizeof(T);  	return qFromBigEndian<T>(unswapped);  } @@ -1,5 +1,6 @@  #include <iostream>  #include <QtCore/QCoreApplication> +#include <QtCore/QSettings>  #include <QtCore/QStringList>  #include "sapmanager.h"  #include "sapbtlistener.h" @@ -18,8 +19,24 @@ int main(int argc, char *argv[])  	app.setOrganizationDomain("com.javispedro");  	app.setApplicationName("sapd"); -	if (app.arguments().size() != 2) { -		cerr << "Usage:: sapd <bt address>" << endl; +	QBluetoothAddress address; +	QSettings settings; +	QString address_from_settings = settings.value("device/address").toString(); +	if (!address_from_settings.isEmpty()) { +		address = QBluetoothAddress(address_from_settings); +	} + +	if (app.arguments().size() >= 2) { +		// Get the address from the command line. +		address = QBluetoothAddress(app.arguments().at(1)); +	} + +	if (address.isNull()) { +		cerr << "Usage: sapd <bt address>" << endl; +		cerr << "If you don't want to specify the BT address every time, put it in " +			 << qPrintable(settings.fileName()) +			 << endl; +		settings.setValue("device/address", QString());  		return EXIT_FAILURE;  	} @@ -31,8 +48,6 @@ int main(int argc, char *argv[])  	QScopedPointer<SAPBTListener> sap_listener(new SAPBTListener); -	QBluetoothAddress address = QBluetoothAddress(app.arguments().at(1)); -  	sap_listener->start();  	sap_listener->nudge(address); diff --git a/notificationconn.cc b/notificationconn.cc index fde3303..231427e 100644 --- a/notificationconn.cc +++ b/notificationconn.cc @@ -6,6 +6,10 @@  #include "endianhelpers.h"  #include "notificationconn.h" +#if SAILFISH +#include "sailfish/notificationmonitor.h" +#endif +  NotificationConn::Notification::Notification()      : type(NotificationPopup), sequenceNumber(0), urgent(false),        applicationId(0), category(0), @@ -44,7 +48,7 @@ QByteArray NotificationConn::packNotification(const Notification &n)  	if (!n.body.isEmpty()) attributeCount++;  	if (!n.thumbnail.isEmpty()) attributeCount++;  	if (!n.applicationName.isEmpty()) attributeCount++; -	//TODO if (n.openInHost) attributeCount++; +	// TODO if (n.openInHost) attributeCount++;  	//if (n.openInWatch) attributeCount++;  	if (n.notificationId != -1) attributeCount++; @@ -94,12 +98,27 @@ QByteArray NotificationConn::packNotification(const Notification &n)  	return data;  } +void NotificationConn::sendNotification(const Notification &n) +{ +	QByteArray packet = packNotification(n); +	packet.prepend('\0'); + +	qDebug() << packet.toHex(); + +	_socket->send(packet); +} +  void NotificationConn::handleConnected()  { -	qDebug() << "Manager socket now connected!"; +	qDebug() << "NotificationManager socket now connected!"; +#if SAILFISH +	NotificationMonitor *monitor = NotificationMonitor::instance(); +	connect(monitor, SIGNAL(incomingNotification(QString,QIcon,QString,int,QString,QDateTime)), +			this, SLOT(handleIncomingNotification(QString,QIcon,QString,int,QString,QDateTime))); +#else  	QTimer::singleShot(2000, this, SLOT(performTest())); - +#endif  }  void NotificationConn::handleMessageReceived() @@ -112,12 +131,37 @@ void NotificationConn::handleMessageReceived()  	// TODO Seems that we receive the notification ID that we should act upon.  } +void NotificationConn::handleIncomingNotification(const QString &sender, const QIcon &icon, const QString &summary, int count, const QString &body, const QDateTime &dateTime) +{ +	short applicationId = _knownSenders.value(sender, 0); +	if (!applicationId) { +		applicationId = _knownSenders.size() + 1; +		_knownSenders.insert(sender, applicationId); +	} + +	Notification n; +	n.sequenceNumber = ++_lastSeqNumber; +	n.type = NotificationPopup; +	n.time = dateTime; +	n.title = summary; +	n.packageName = sender; +	n.applicationName = sender; +	n.body = body; +	n.sender = 0; +	n.count = 0; // TODO figure this out +	n.category = 0; +	n.applicationId = applicationId; +	n.notificationId = ++_lastNotifId; + +	sendNotification(n); +} +  void NotificationConn::performTest()  {  	qDebug() << "Performing notif test";  	Notification n; -	n.sequenceNumber = 1; +	n.sequenceNumber = ++_lastSeqNumber;  	n.type = NotificationPopup;  	n.time = QDateTime::currentDateTime();  	n.title = "A title"; @@ -128,12 +172,7 @@ void NotificationConn::performTest()  	n.count = 13;  	n.category = 0;  	n.applicationId = 0xc2d7; -	n.notificationId = 1; +	n.notificationId = ++_lastNotifId; -	QByteArray packet = packNotification(n); -	packet.prepend('\0'); - -	qDebug() << packet.toHex(); - -	_socket->send(packet); +	sendNotification(n);  } diff --git a/notificationconn.h b/notificationconn.h index 9be3e20..da3e3c3 100644 --- a/notificationconn.h +++ b/notificationconn.h @@ -54,18 +54,20 @@ protected:  	};  	QByteArray packNotification(const Notification &n); - -private: - +	void sendNotification(const Notification &n);  private slots:  	void handleConnected();  	void handleMessageReceived(); +	void handleIncomingNotification(const QString &sender, const QIcon &icon, const QString &summary, int count, const QString &body, const QDateTime &dateTime);  	void performTest();  private:  	SAPConnection *_conn;  	SAPSocket *_socket; +	QHash<QString, short> _knownSenders; +	int _lastSeqNumber; +	int _lastNotifId;  };  #endif // NOTIFICATIONCONN_H diff --git a/rpm/sapd.yaml b/rpm/sapd.yaml new file mode 100644 index 0000000..212f735 --- /dev/null +++ b/rpm/sapd.yaml @@ -0,0 +1,27 @@ +Name: sapd +Summary: Accesory protocol daemon +Version: 0.1.0 +Release: 1 +Group: Communications/Bluetooth +URL: https://gitorious.org/javispedro-jolla-misc/sapd/ +License: GPLv3 +Sources: +- '%{name}-%{version}.tar.bz2' +Description: | +  A daemon that speaks accessory protocol. +Configure: none +Builder: qtc5 + +PkgConfigBR: +  - sailfishapp >= 1.0.2 +  - Qt5Core +  - Qt5DBus +  - Qt5Bluetooth +  - openssl + +PkgBR: +# Workaround current sailfish qt5connectivity packaging bug +  - qt5-qtconnectivity-qtbluetooth-devel + +Files: +  - '%{_bindir}' diff --git a/sailfish/notificationmonitor.cpp b/sailfish/notificationmonitor.cpp new file mode 100644 index 0000000..f22ce02 --- /dev/null +++ b/sailfish/notificationmonitor.cpp @@ -0,0 +1,79 @@ +#include <QtCore/QDebug> +#include <QtGui/QIcon> +#include <QtDBus/QDBusConnection> +#include <QtDBus/QDBusConnectionInterface> + +#include "notificationmonitor.h" +#include "notifications_adaptor.h" + +static NotificationMonitor *global_monitor = 0; + +NotificationMonitor::NotificationMonitor(QObject *parent) : +	QObject(parent) +{ +	QDBusConnection bus = QDBusConnection::sessionBus(); +	QDBusConnectionInterface *dbus = bus.interface(); +	dbus->call("AddMatch", +			   "interface='org.freedesktop.Notifications',member='Notify',type='method_call',eavesdrop='true'"); +	new NotificationsAdaptor(this); +	bus.registerObject("/org/freedesktop/Notifications", this); +} + +NotificationMonitor::~NotificationMonitor() +{ +	QDBusConnection bus = QDBusConnection::sessionBus(); +	QDBusConnectionInterface *dbus = bus.interface(); +	dbus->call("RemoveMatch", +			   "interface='org.freedesktop.Notifications',member='Notify',type='method_call',eavesdrop='true'"); +} + +NotificationMonitor *NotificationMonitor::instance() +{ +	if (!global_monitor) { +		global_monitor = new NotificationMonitor; +	} +	return global_monitor; +} + +uint NotificationMonitor::Notify(const QString &app_name, uint replaces_id, const QString &app_icon, const QString &summary, const QString &body, const QStringList &actions, const QVariantHash &hints, int expire_timeout) +{ +	QIcon icon; + +	qDebug() << "Got notification" << app_name << app_icon << summary << body; + +	// Avoid sending a reply for this method call, since we've received it +	// because we're eavesdropping. +	// The actual target of the method call will send the proper reply, not us. +	Q_ASSERT(calledFromDBus()); +	setDelayedReply(true); + +	// If the notification mentions a specific icon, then use it. +	// But otherwise let's prefer our builtin icons. +	if (app_icon.startsWith("/")) { +		icon = QIcon(app_icon); +	} else if (app_icon.startsWith("file:")) { +		QUrl url(app_icon); +		icon = QIcon(url.toLocalFile()); +	} else { +		QString category = hints.value("category").toString(); +		// Let's hardcode a few categories for now.. +		if (!category.isEmpty()) { +			qDebug() << "TODO: Category icons"; +		} +	} + +	int count = hints.value("x-nemo-item-count").toInt(); +	QDateTime dateTime = hints.value("x-nemo-timestamp").toDateTime(); +	if (!dateTime.isValid()) { +		dateTime = QDateTime::currentDateTime(); +	} + +	if (summary.isEmpty() && body.isEmpty()) { +		// Avoid sending empty notifications to watch. +		return 0; +	} + +	emit incomingNotification(app_name, icon, summary, count, body, dateTime); + +	return 0; +} diff --git a/sailfish/notificationmonitor.h b/sailfish/notificationmonitor.h new file mode 100644 index 0000000..c0f7691 --- /dev/null +++ b/sailfish/notificationmonitor.h @@ -0,0 +1,28 @@ +#ifndef NOTIFICATIONMONITOR_H +#define NOTIFICATIONMONITOR_H + +#include <QtCore/QObject> +#include <QtCore/QDateTime> +#include <QtDBus/QDBusContext> + +class NotificationMonitor : public QObject, protected QDBusContext +{ +	Q_OBJECT + +public: +	~NotificationMonitor(); + +	static NotificationMonitor *instance(); + +signals: +	void incomingNotification(const QString &sender, const QIcon &icon, const QString &summary, int count, const QString &body, const QDateTime &dateTime); + +private: +	explicit NotificationMonitor(QObject *parent = 0); + +private slots: +	friend class NotificationsAdaptor; +	uint Notify(const QString &app_name, uint replaces_id, const QString &app_icon, const QString &summary, const QString &body, const QStringList &actions, const QVariantHash &hints, int expire_timeout); +}; + +#endif // NOTIFICATIONMONITOR_H diff --git a/sailfish/org.freedesktop.Notifications.xml b/sailfish/org.freedesktop.Notifications.xml new file mode 100644 index 0000000..d3f8bef --- /dev/null +++ b/sailfish/org.freedesktop.Notifications.xml @@ -0,0 +1,17 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> +  <interface name="org.freedesktop.Notifications"> +    <!-- (Partial) Desktop Notification Specification interface --> +    <method name="Notify"> +      <arg name="app_name" type="s" direction="in"/> +      <arg name="replaces_id" type="u" direction="in"/> +      <arg name="app_icon" type="s" direction="in"/> +      <arg name="summary" type="s" direction="in"/> +      <arg name="body" type="s" direction="in"/> +      <arg name="actions" type="as" direction="in"/> +      <arg name="hints" type="a{sv}" direction="in"/> +      <arg name="expire_timeout" type="i" direction="in"/> +      <arg name="id" type="u" direction="out"/> +      <annotation name="org.qtproject.QtDBus.QtTypeName.In6" value="QVariantHash"/> +    </method> +</node> diff --git a/sapbtlistener.cc b/sapbtlistener.cc index 1b4550a..76ecb94 100644 --- a/sapbtlistener.cc +++ b/sapbtlistener.cc @@ -1,6 +1,9 @@  #include <QtCore/QDebug> + +#ifdef MANUAL_SDP  #include <bluetooth/sdp.h>  #include <bluetooth/sdp_lib.h> +#endif  #include "saprotocol.h"  #include "sapbtlistener.h" @@ -12,6 +15,10 @@  namespace  { + +#ifdef MANUAL_SDP +// Basically, QBluetoothServiceInfo is not yet compatible with Bluez5, +// so we hack around it by doing our own SDP connection.  void add_sdp_record(sdp_session_t *session, const QBluetoothUuid &btuuid, quint16 port)  {  	sdp_list_t *svclass_id, *apseq, *root; @@ -63,6 +70,7 @@ void add_sdp_records(quint16 port)  	add_sdp_record(sess, SAProtocol::dataServiceUuid, port);  } +#endif  } @@ -82,7 +90,11 @@ void SAPBTListener::start()  		return;  	} +#if QT_VERSION >= QT_VERSION_CHECK(5,2,0) +	_server = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this); +#else  	_server = new QRfcommServer(this); +#endif  	connect(_server, SIGNAL(newConnection()), this, SLOT(acceptConnection()));  	if (!_server->listen(QBluetoothAddress(), 0)) {  		qWarning() << "Failed to start Bluetooth listener socket"; @@ -92,7 +104,7 @@ void SAPBTListener::start()  	quint8 serverPort = _server->serverPort(); -#if 1 +#if MANUAL_SDP  	// Basically, QBluetoothServiceInfo is not yet compatible with Bluez5,  	// so we hack around it by doing our own SDP connection.  	add_sdp_records(serverPort); @@ -123,7 +135,7 @@ void SAPBTListener::start()  	_service.setServiceProvider("gearbtteest");  	QBluetoothServiceInfo::Sequence classIds; -	classIds.append(QVariant::fromValue(SAPProtocol::dataServiceUuid)); +	classIds.append(QVariant::fromValue(SAProtocol::dataServiceUuid));  	_service.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classIds);  	QBluetoothServiceInfo::Sequence browseGroupList; @@ -167,7 +179,11 @@ void SAPBTListener::stop()  void SAPBTListener::nudge(const QBluetoothAddress &address)  { +#if QT_VERSION >= QT_VERSION_CHECK(5,2,0) +	QBluetoothSocket *socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol, this); +#else  	QBluetoothSocket *socket = new QBluetoothSocket(QBluetoothSocket::RfcommSocket, this); +#endif  	connect(socket, SIGNAL(connected()), socket, SLOT(deleteLater()));  	connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), @@ -177,7 +193,7 @@ void SAPBTListener::nudge(const QBluetoothAddress &address)  	socket->connectToService(address, 2); //SAPProtocol::nudgeServiceUuid); -#if 1 +#if DESKTOP  	// At the same time set up and HFP connection to the watch.  	new HfpAg(address, this);  #endif diff --git a/sapbtlistener.h b/sapbtlistener.h index a59a5e1..3fe821d 100644 --- a/sapbtlistener.h +++ b/sapbtlistener.h @@ -3,7 +3,10 @@  #include <QtCore/QObject> -#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) +#if QT_VERSION >= QT_VERSION_CHECK(5,2,0) +#include <QtBluetooth/QBluetoothServer> +#include <QtBluetooth/QBluetoothServiceInfo> +#elif QT_VERSION >= QT_VERSION_CHECK(5,0,0)  #include <QtBluetooth/QRfcommServer>  #include <QtBluetooth/QBluetoothServiceInfo>  QT_USE_NAMESPACE_BLUETOOTH @@ -36,7 +39,11 @@ private slots:  private: +#if QT_VERSION >= QT_VERSION_CHECK(5,2,0) +	QBluetoothServer *_server; +#else  	QRfcommServer *_server; +#endif  	QBluetoothServiceInfo _service;  }; diff --git a/sapbtpeer.h b/sapbtpeer.h index cc060f8..da77f22 100644 --- a/sapbtpeer.h +++ b/sapbtpeer.h @@ -3,7 +3,9 @@  #include <QtCore/QObject> -#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) +#if QT_VERSION >= QT_VERSION_CHECK(5,2,0) +#include <QtBluetooth/QBluetoothSocket> +#elif QT_VERSION >= QT_VERSION_CHECK(5,0,0)  #include <QtBluetooth/QBluetoothSocket>  QT_USE_NAMESPACE_BLUETOOTH  #else @@ -1,21 +1,36 @@  TARGET = sapd  TEMPLATE = app -QT       += core dbus -QT       -= gui +QT       += core gui dbus  CONFIG   += console -greaterThan(QT_MAJOR_VERSION, 4) { +CONFIG    += link_pkgconfig +PKGCONFIG += openssl + +exists(/usr/lib/libsailfishapp.so) { +    # Building for Jolla Sailfish, Qt5, Bluez5 +    QT       += bluetooth +    DEFINES  += SAILFISH +    DBUS_ADAPTORS += sailfish/org.freedesktop.Notifications.xml +    SOURCES  += sailfish/notificationmonitor.cpp +    HEADERS  += sailfish/notificationmonitor.h +} else:greaterThan(QT_MAJOR_VERSION, 4) { +    # Building for desktop, Qt5, Bluez5      QT       += bluetooth +    DEFINES  += DESKTOP +    SOURCES  += hfpag.cc +    HEADERS  += hfpag.h  } else { +    # Building for desktop, Qt4, Bluez5      CONFIG   += mobility      MOBILITY += connectivity -    DEFINES  += DESKTOP +    DEFINES  += DESKTOP MANUAL_SDP      SOURCES  += hfpag.cc      HEADERS  += hfpag.h +    PKGCONFIG += bluez  } -CONFIG    += link_pkgconfig -PKGCONFIG += bluez openssl +target.path = /usr/bin +INSTALLS += target  SOURCES += main.cc \      sapbtlistener.cc \ @@ -76,3 +91,7 @@ HEADERS += \      notificationagent.h \      notificationconn.h \      endianhelpers.h + +OTHER_FILES += \ +    rpm/sapd.yaml \ +    sailfish/org.freedesktop.Notifications.xml diff --git a/saprotocol.h b/saprotocol.h index 469a293..3f38e05 100644 --- a/saprotocol.h +++ b/saprotocol.h @@ -3,7 +3,9 @@  #include <QtCore/QObject> -#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) +#if QT_VERSION >= QT_VERSION_CHECK(5,2,0) +#include <QtBluetooth/QBluetoothUuid> +#elif QT_VERSION >= QT_VERSION_CHECK(5,0,0)  #include <QtBluetooth/QBluetoothUuid>  QT_USE_NAMESPACE_BLUETOOTH  #else  | 
