Remove dependency on libnotify and use dbus directly.

This commit is contained in:
John Maguire 2010-03-25 17:52:28 +00:00
parent 2e71390acd
commit 7250587c03
6 changed files with 127 additions and 76 deletions

View File

@ -30,19 +30,12 @@ if(WIN32)
else(WIN32)
pkg_check_modules(TAGLIB taglib)
pkg_check_modules(XINE libxine)
pkg_check_modules(LIBNOTIFY libnotify)
endif(WIN32)
if (NOT Boost_FOUND)
message(FATAL_ERROR "Boost not found")
endif (NOT Boost_FOUND)
if (LIBNOTIFY_FOUND)
add_definitions(-DHAVE_LIBNOTIFY)
link_directories(${LIBNOTIFY_LIBRARY_DIRS})
include_directories(${LIBNOTIFY_INCLUDE_DIRS})
endif (LIBNOTIFY_FOUND)
if (TAGLIB_VERSION VERSION_LESS 1.6)
message(FATAL_ERROR "Taglib version 1.6 or greater is required")
endif (TAGLIB_VERSION VERSION_LESS 1.6)

View File

@ -0,0 +1,30 @@
<!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">
<method name="GetServerInformation">
<arg name="return_name" type="s" direction="out"/>
<arg name="return_vendor" type="s" direction="out"/>
<arg name="return_version" type="s" direction="out"/>
<arg name="return_spec_version" type="s" direction="out"/>
</method>
<method name="GetCapabilities">
<arg name="return_caps" type="as" direction="out"/>
</method>
<method name="CloseNotification">
<arg name="id" type="u" direction="in"/>
</method>
<method name="Notify">
<arg name="app_name" type="s" direction="in"/>
<arg name="id" type="u" direction="in"/>
<arg name="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"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In6" value="QVariantMap"/>
<arg name="timeout" type="i" direction="in"/>
<arg name="return_id" type="u" direction="out"/>
</method>
</interface>
</node>

View File

@ -184,6 +184,7 @@ else(APPLE)
set(CLEMENTINE-SOURCES ${CLEMENTINE-SOURCES} osd_win.cpp)
else(WIN32)
set(CLEMENTINE-SOURCES ${CLEMENTINE-SOURCES} osd_x11.cpp)
# MPRIS
qt4_add_dbus_adaptor(MPRIS-PLAYER-SOURCES
../data/org.freedesktop.MediaPlayer.player.xml
player.h Player mpris_player MprisPlayer)
@ -193,10 +194,16 @@ else(APPLE)
qt4_add_dbus_adaptor(MPRIS-TRACKLIST-SOURCES
../data/org.freedesktop.MediaPlayer.tracklist.xml
player.h Player mpris_tracklist MprisTrackList)
# org.freedesktop.Notifications
qt4_add_dbus_interface(NOTIFICATION-SOURCES
../data/org.freedesktop.Notifications.xml
notification)
set(CLEMENTINE-SOURCES ${CLEMENTINE-SOURCES}
${MPRIS-PLAYER-SOURCES}
${MPRIS-ROOT-SOURCES}
${MPRIS-TRACKLIST-SOURCES}
${NOTIFICATION-SOURCES}
mpris.cpp
)
set(CLEMENTINE-MOC-HEADERS ${CLEMENTINE-MOC-HEADERS} mpris.h)
@ -231,7 +238,6 @@ target_link_libraries(clementine_lib
qxt
lastfm
${XINE_LIBRARIES}
${LIBNOTIFY_LIBRARIES}
${TAGLIB_LIBRARIES}
${QT_LIBRARIES}
)

View File

@ -37,6 +37,7 @@
# include <QDBusConnection>
# include <QDBusMetaType>
# include "mpris.h"
# include "osd.h"
#endif
// Load sqlite plugin on windows
@ -100,6 +101,7 @@ int main(int argc, char *argv[]) {
#ifdef Q_WS_X11
qDBusRegisterMetaType<DBusStatus>();
qDBusRegisterMetaType<Version>();
qDBusRegisterMetaType<QImage>();
QDBusConnection::sessionBus().registerService("org.mpris.clementine");
MPRIS mpris;
#endif

View File

@ -25,10 +25,13 @@
#include "song.h"
#ifdef Q_WS_X11
# ifndef _NOTIFY_NOTIFICATION_H_
struct GdkPixbuf;
struct NotifyNotification;
# endif
#include <QDBusArgument>
#include <boost/scoped_ptr.hpp>
#include "notification.h"
QDBusArgument& operator<< (QDBusArgument& arg, const QImage& image);
const QDBusArgument& operator>> (const QDBusArgument& arg, QImage& image);
#endif
class OSD : public QObject {
@ -79,15 +82,16 @@ class OSD : public QObject {
bool show_on_volume_change_;
bool show_art_;
#ifdef Q_WS_X11
NotifyNotification* notification_;
GdkPixbuf* pixbuf_;
#endif
#ifdef Q_OS_DARWIN
class GrowlNotificationWrapper;
GrowlNotificationWrapper* wrapper_;
#endif // Q_OS_DARWIN
#ifdef Q_WS_X11
boost::scoped_ptr<org::freedesktop::Notifications> interface_;
private slots:
void CallFinished(QDBusPendingCallWatcher* watcher);
#endif
};
#endif // OSD_H

View File

@ -14,34 +14,55 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
// Libnotify headers need to go before Qt ones because they use "signals" as
// a variable name
#ifdef HAVE_LIBNOTIFY
# include <libnotify/notify.h>
# include <gdk-pixbuf/gdk-pixbuf.h>
# include <glib.h>
#endif // HAVE_LIBNOTIFY
#include "osd.h"
#include <QCoreApplication>
#include <QtDebug>
#include <QTextDocument>
using boost::scoped_ptr;
QDBusArgument& operator<< (QDBusArgument& arg, const QImage& image) {
if (image.isNull()) {
// Sometimes this gets called with a null QImage for no obvious reason.
arg.beginStructure();
arg << 0 << 0 << 0 << false << 0 << 0 << QByteArray();
arg.endStructure();
return arg;
}
QImage scaled = image.scaledToHeight(100, Qt::SmoothTransformation);
QImage i = scaled.convertToFormat(QImage::Format_ARGB32).rgbSwapped();
arg.beginStructure();
arg << i.width();
arg << i.height();
arg << i.bytesPerLine();
arg << i.hasAlphaChannel();
int channels = i.isGrayscale() ? 1 : (i.hasAlphaChannel() ? 4 : 3);
arg << i.depth() / channels;
arg << channels;
arg << QByteArray(reinterpret_cast<const char*>(i.bits()), i.numBytes());
arg.endStructure();
return arg;
}
const QDBusArgument& operator>> (const QDBusArgument& arg, QImage& image) {
// This is needed to link but shouldn't be called.
Q_ASSERT(0);
return arg;
}
void OSD::Init() {
notification_ = NULL;
pixbuf_ = NULL;
#ifdef HAVE_LIBNOTIFY
notify_init(QCoreApplication::applicationName().toUtf8().constData());
#endif
interface_.reset(new org::freedesktop::Notifications(
"org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
QDBusConnection::sessionBus()));
if (!interface_->isValid()) {
qWarning() << "Error connecting to notifications service.";
}
}
bool OSD::SupportsNativeNotifications() {
#ifdef HAVE_LIBNOTIFY
return true;
#else
return false;
#endif
}
bool OSD::SupportsTrayPopups() {
@ -50,50 +71,45 @@ bool OSD::SupportsTrayPopups() {
void OSD::ShowMessageNative(const QString& summary, const QString& message,
const QString& icon) {
#ifdef HAVE_LIBNOTIFY
if (summary.isNull())
return;
#define STR(x) (x.isNull() ? NULL : x.toUtf8().constData())
notification_ = notify_notification_new(
STR(summary), STR(Qt::escape(message)), STR(icon), NULL);
#undef STR
notify_notification_set_urgency(notification_, NOTIFY_URGENCY_LOW);
notify_notification_set_timeout(notification_, timeout_);
if (pixbuf_) {
notify_notification_set_icon_from_pixbuf(notification_, pixbuf_);
}
GError* error = NULL;
notify_notification_show(notification_, &error);
if (error) {
qDebug() << "Error from notify_notification_show:" << error->message;
g_error_free(error);
}
pixbuf_ = NULL;
#endif // HAVE_LIBNOTIFY
QDBusPendingReply<uint> reply = interface_->Notify(
QCoreApplication::applicationName(),
0,
icon,
summary,
message,
QStringList(),
QVariantMap(),
timeout_);
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
SLOT(CallFinished(QDBusPendingCallWatcher*)));
}
void OSD::ShowMessageNative(const QString& summary, const QString& message,
const QImage& image) {
#ifdef HAVE_LIBNOTIFY
QImage happy_gdk_image = image.scaledToHeight(100, Qt::SmoothTransformation)
.convertToFormat(QImage::Format_RGB888);
pixbuf_ = gdk_pixbuf_new_from_data(
happy_gdk_image.bits(),
GDK_COLORSPACE_RGB,
false, // has_alpha
8, // bits_per_sample
happy_gdk_image.width(),
happy_gdk_image.height(),
happy_gdk_image.bytesPerLine(),
NULL, NULL);
ShowMessageNative(summary, message, QString());
#endif // HAVE_LIBNOTIFY
QVariantMap hints;
if (!image.isNull()) {
hints["image_data"] = QVariant(image);
}
QDBusPendingReply<uint> reply = interface_->Notify(
QCoreApplication::applicationName(),
0,
QString(),
summary,
message,
QStringList(),
hints,
timeout_);
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
SLOT(CallFinished(QDBusPendingCallWatcher*)));
}
void OSD::CallFinished(QDBusPendingCallWatcher* watcher) {
scoped_ptr<QDBusPendingCallWatcher> w(watcher);
QDBusPendingReply<uint> reply = *watcher;
if (reply.isError()) {
qWarning() << "Error sending notification" << reply.error();
}
}