From 69f459682ac1e35314f64c9f38f63f240c87d0bd Mon Sep 17 00:00:00 2001
From: Jeff Mitchell <tomahawk@jefferai.org>
Date: Wed, 22 Jun 2011 13:47:16 -0400
Subject: [PATCH] Make notifications work on Linux, including icon.

---
 src/libtomahawk/CMakeLists.txt                |   6 +-
 .../infoplugins/unix/fdonotifyplugin.cpp      |  40 +++++--
 .../infoplugins/unix/fdonotifyplugin.h        |   7 +-
 .../infoplugins/unix/imageconverter.cpp       | 107 ++++++++++++++++++
 .../infoplugins/unix/imageconverter.h         |  36 ++++++
 5 files changed, 184 insertions(+), 12 deletions(-)
 create mode 100644 src/libtomahawk/infosystem/infoplugins/unix/imageconverter.cpp
 create mode 100644 src/libtomahawk/infosystem/infoplugins/unix/imageconverter.h

diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt
index 0a012d7b3..52ba39e66 100644
--- a/src/libtomahawk/CMakeLists.txt
+++ b/src/libtomahawk/CMakeLists.txt
@@ -378,10 +378,12 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.
 
 IF( UNIX AND NOT APPLE )
     SET( libSources ${libSources}
-      infosystem/infoplugins/unix/fdonotifyplugin.cpp )
+      infosystem/infoplugins/unix/fdonotifyplugin.cpp
+      infosystem/infoplugins/unix/imageconverter.cpp )
 
     SET( libHeaders ${libHeaders}
-      infosystem/infoplugins/unix/fdonotifyplugin.h )
+      infosystem/infoplugins/unix/fdonotifyplugin.h
+      infosystem/infoplugins/unix/imageconverter.h )
 ENDIF( UNIX AND NOT APPLE )
 
 IF( WIN32 )
diff --git a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp
index 01b0573eb..0bc778591 100644
--- a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp
+++ b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp
@@ -16,17 +16,39 @@
  *   along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "fdonotifyplugin.h"
+// Marked portions of this file are subject to the following copyright:
+/*
+ * Copyright (C) 2009 by Aurélien Gâteau <aurelien.gateau@canonical.com>
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
 
+#include "fdonotifyplugin.h"
 #include "utils/tomahawkutils.h"
+#include "imageconverter.h"
 
 #include <QtDBus/QDBusConnection>
 #include <QtDBus/QDBusMessage>
+#include <QImage>
 
 using namespace Tomahawk::InfoSystem;
 
 FdoNotifyPlugin::FdoNotifyPlugin()
     : InfoPlugin()
+    , m_arg()
 {
     qDebug() << Q_FUNC_INFO;
     m_supportedPushTypes << Tomahawk::InfoSystem::InfoNotifyUser;
@@ -38,15 +60,16 @@ FdoNotifyPlugin::~FdoNotifyPlugin()
 }
 
 void
-FdoNotifyPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant data )
+FdoNotifyPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant pushData )
 {
+    Q_UNUSED( caller );
     qDebug() << Q_FUNC_INFO;
-    if ( type != Tomahawk::InfoSystem::InfoNotifyUser || !data.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() )
+    if ( type != Tomahawk::InfoSystem::InfoNotifyUser || !pushData.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() )
     {
         qDebug() << Q_FUNC_INFO << " not the right type or could not convert the hash";
         return;
     }
-    Tomahawk::InfoSystem::InfoCriteriaHash hash = data.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
+    Tomahawk::InfoSystem::InfoCriteriaHash hash = pushData.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
     if ( !hash.contains( "message" ) )
     {
         qDebug() << Q_FUNC_INFO << " hash did not contain a message";
@@ -58,15 +81,14 @@ FdoNotifyPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::Inf
     arguments << QString( "Tomahawk" ); //app_name
     arguments << quint32( 0 ); //notification_id
     arguments << QString(); //app_icon
-    arguments << caller; //summary
+    arguments << QString( "Tomahawk" ); //summary
     arguments << hash["message"]; //body
-    QStringList actions;
-    actions << "dosomething" << "Do Something";
-    arguments << actions; //actions
+    arguments << QStringList(); //actions
     QVariantMap dict;
     dict["desktop-entry"] = QString( "tomahawk" );
+    dict["image_data"] = ImageConverter::variantForImage( QImage( RESPATH "icons/tomahawk-icon-128x128.png" ) );
     arguments << dict; //hints
-    arguments << quint32( -1 ); //expire_timeout
+    arguments << qint32( -1 ); //expire_timeout
     message.setArguments( arguments );
     QDBusConnection::sessionBus().send( message );
 }
diff --git a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h
index d222b251d..1778ccbcd 100644
--- a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h
+++ b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h
@@ -22,6 +22,8 @@
 #include "infosystem/infosystem.h"
 #include "infosystem/infosystemworker.h"
 
+#include <QtDBus/QDBusArgument>
+
 namespace Tomahawk
 {
 
@@ -47,7 +49,7 @@ protected slots:
         Q_UNUSED( customData );
     }
 
-    virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant data );
+    virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant pushData );
 
     virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData )
     {
@@ -57,6 +59,9 @@ protected slots:
         Q_UNUSED( input );
         Q_UNUSED( customData );
     }
+
+private:
+    QDBusArgument m_arg;
 };
 
 }
diff --git a/src/libtomahawk/infosystem/infoplugins/unix/imageconverter.cpp b/src/libtomahawk/infosystem/infoplugins/unix/imageconverter.cpp
new file mode 100644
index 000000000..1d08fcf43
--- /dev/null
+++ b/src/libtomahawk/infosystem/infoplugins/unix/imageconverter.cpp
@@ -0,0 +1,107 @@
+/*
+   Copyright (C) 2009 by Aurélien Gâteau <aurelien.gateau@canonical.com>
+
+   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, or (at your option)
+   any later version.
+
+   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, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ */
+#include "imageconverter.h"
+
+#include <QtDBus/QDBusArgument>
+#include <QtDBus/QDBusMetaType>
+#include <QImage>
+
+namespace ImageConverter
+{
+
+/**
+ * A structure representing an image which can be marshalled to fit the
+ * notification spec.
+ */
+struct SpecImage
+{
+	int width, height, rowStride;
+	bool hasAlpha;
+	int bitsPerSample, channels;
+	QByteArray data;
+};
+
+QDBusArgument &operator<<(QDBusArgument &argument, const SpecImage &image)
+{
+	argument.beginStructure();
+	argument << image.width << image.height << image.rowStride << image.hasAlpha;
+	argument << image.bitsPerSample << image.channels << image.data;
+	argument.endStructure();
+	return argument;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &argument, SpecImage &image)
+{
+	argument.beginStructure();
+	argument >> image.width >> image.height >> image.rowStride >> image.hasAlpha;
+	argument >> image.bitsPerSample >> image.channels >> image.data;
+	argument.endStructure();
+	return argument;
+}
+
+} // namespace
+
+// This must be before the QVariant::fromValue below (#211726)
+Q_DECLARE_METATYPE(ImageConverter::SpecImage)
+
+namespace ImageConverter
+{
+QVariant variantForImage(const QImage &_image)
+{
+	qDBusRegisterMetaType<SpecImage>();
+
+	QImage image = _image.convertToFormat(QImage::Format_ARGB32);
+
+	int rowStride = image.width() * 4;
+
+	// Notification spec stores pixels in R,G,B,A order, regardless of
+	// endianess
+	// Qt represents pixels as 32 bit unsigned int. So the order depend on
+	// endianess:
+	// - In big endian the order is A,R,G,B
+	// - In little endian the order is B,G,R,A
+	QByteArray data;
+	data.resize(rowStride * image.height());
+	char* dst = data.data();
+	for (int y=0; y<image.height(); ++y) {
+		QRgb* src = (QRgb*)image.scanLine(y);
+		QRgb* end = src + image.width();
+		for (;src != end; ++src) {
+			// Probably slow, but free of endianess issues
+			*dst++ = qRed(*src);
+			*dst++ = qGreen(*src);
+			*dst++ = qBlue(*src);
+			*dst++ = qAlpha(*src);
+		}
+	}
+
+	SpecImage specImage;
+	specImage.width = image.width();
+	specImage.height = image.height();
+	specImage.rowStride = rowStride;
+	specImage.hasAlpha = true;
+	specImage.bitsPerSample = 8;
+	specImage.channels = 4;
+	specImage.data = data;
+
+	return QVariant::fromValue(specImage);
+}
+
+} // namespace
+
diff --git a/src/libtomahawk/infosystem/infoplugins/unix/imageconverter.h b/src/libtomahawk/infosystem/infoplugins/unix/imageconverter.h
new file mode 100644
index 000000000..6467dea72
--- /dev/null
+++ b/src/libtomahawk/infosystem/infoplugins/unix/imageconverter.h
@@ -0,0 +1,36 @@
+/*
+   Copyright (C) 2009 by Aurélien Gâteau <aurelien.gateau@canonical.com>
+
+   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, or (at your option)
+   any later version.
+
+   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, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ */
+#ifndef IMAGECONVERTER_H
+#define IMAGECONVERTER_H
+
+class QVariant;
+class QImage;
+
+namespace ImageConverter
+{
+
+/**
+ * Returns a variant representing an image using the format describe in the
+ * galago spec
+ */
+QVariant variantForImage(const QImage &image);
+
+} // namespace
+
+#endif /* IMAGECONVERTER_H */