Move everything DBus related back to the main thread and use synchronous method calls everywhere

This commit is contained in:
David Sansome 2011-01-22 12:47:19 +00:00
parent 7880026767
commit 2ecf61a57e
15 changed files with 152 additions and 163 deletions

View File

@ -607,6 +607,12 @@ if(HAVE_DBUS)
dbus/org.freedesktop.Notifications.xml dbus/org.freedesktop.Notifications.xml
dbus/notification) dbus/notification)
# org.gnome.SettingsDaemon interface
qt4_add_dbus_interface(SOURCES
dbus/org.gnome.SettingsDaemon.MediaKeys.xml
dbus/gnomesettingsdaemon)
# DeviceKit DBUS interfaces # DeviceKit DBUS interfaces
if(HAVE_DEVICEKIT) if(HAVE_DEVICEKIT)
qt4_add_dbus_interface(SOURCES qt4_add_dbus_interface(SOURCES
@ -785,6 +791,7 @@ if(HAVE_REMOTE)
if(HAVE_DBUS) if(HAVE_DBUS)
list(APPEND SOURCES remote/avahi.cpp) list(APPEND SOURCES remote/avahi.cpp)
list(APPEND HEADERS remote/avahi.h)
endif(HAVE_DBUS) endif(HAVE_DBUS)
endif(HAVE_REMOTE) endif(HAVE_REMOTE)

View File

@ -25,56 +25,18 @@
GlobalShortcutBackend::GlobalShortcutBackend(GlobalShortcuts *parent) GlobalShortcutBackend::GlobalShortcutBackend(GlobalShortcuts *parent)
: QObject(parent), : QObject(parent),
manager_(parent), manager_(parent),
active_(false), active_(false)
register_in_progress_(false),
should_unregister_(false)
{ {
} }
void GlobalShortcutBackend::Register() { bool GlobalShortcutBackend::Register() {
if (register_in_progress_) { bool ret = DoRegister();
should_unregister_ = false; if (ret)
return; active_ = true;
} return ret;
if (RegisterInNewThread()) {
register_in_progress_ = true;
QFuture<bool> future = QtConcurrent::run(this, &GlobalShortcutBackend::DoRegister);
QFutureWatcher<bool>* watcher = new QFutureWatcher<bool>(this);
watcher->setFuture(future);
connect(watcher, SIGNAL(finished()), SLOT(RegisterFinishedSlot()));
} else {
bool ret = DoRegister();
if (ret)
active_ = true;
emit RegisterFinished(ret);
}
} }
void GlobalShortcutBackend::Unregister() { void GlobalShortcutBackend::Unregister() {
if (register_in_progress_) {
should_unregister_ = true;
return;
}
DoUnregister(); DoUnregister();
active_ = false; active_ = false;
} }
void GlobalShortcutBackend::RegisterFinishedSlot() {
QFutureWatcher<bool>* watcher = dynamic_cast<QFutureWatcher<bool>*>(sender());
const bool success = watcher->result();
watcher->deleteLater();
register_in_progress_ = false;
if (success)
active_ = true;
if (should_unregister_) {
Unregister();
should_unregister_ = false;
} else {
emit RegisterFinished(success);
}
}

View File

@ -31,26 +31,18 @@ public:
bool is_active() const { return active_; } bool is_active() const { return active_; }
void Register(); bool Register();
void Unregister(); void Unregister();
signals: signals:
void RegisterFinished(bool success); void RegisterFinished(bool success);
protected: protected:
virtual bool RegisterInNewThread() const { return false; }
virtual bool DoRegister() = 0; virtual bool DoRegister() = 0;
virtual void DoUnregister() = 0; virtual void DoUnregister() = 0;
GlobalShortcuts* manager_; GlobalShortcuts* manager_;
bool active_; bool active_;
private slots:
void RegisterFinishedSlot();
private:
bool register_in_progress_;
bool should_unregister_;
}; };
#endif // GLOBALSHORTCUTBACKEND_H #endif // GLOBALSHORTCUTBACKEND_H

View File

@ -75,9 +75,6 @@ GlobalShortcuts::GlobalShortcuts(QObject *parent)
system_backend_ = new MacGlobalShortcutBackend(this); system_backend_ = new MacGlobalShortcutBackend(this);
#endif #endif
connect(gnome_backend_, SIGNAL(RegisterFinished(bool)), SLOT(RegisterFinished(bool)));
connect(system_backend_, SIGNAL(RegisterFinished(bool)), SLOT(RegisterFinished(bool)));
ReloadSettings(); ReloadSettings();
} }
@ -136,18 +133,9 @@ void GlobalShortcuts::Unregister() {
} }
void GlobalShortcuts::Register() { void GlobalShortcuts::Register() {
if (use_gnome_) if (use_gnome_ && gnome_backend_->Register())
gnome_backend_->Register(); return;
else system_backend_->Register();
system_backend_->Register();
}
void GlobalShortcuts::RegisterFinished(bool success) {
GlobalShortcutBackend* backend = qobject_cast<GlobalShortcutBackend*>(sender());
if (backend == gnome_backend_ && !success) {
system_backend_->Register();
}
} }
bool GlobalShortcuts::IsMacAccessibilityEnabled() const { bool GlobalShortcuts::IsMacAccessibilityEnabled() const {

View File

@ -77,9 +77,6 @@ private:
int rating, const QKeySequence& default_key = QKeySequence(0)); int rating, const QKeySequence& default_key = QKeySequence(0));
Shortcut AddShortcut(const QString& id, const QString& name, const QKeySequence& default_key); Shortcut AddShortcut(const QString& id, const QString& name, const QKeySequence& default_key);
private slots:
void RegisterFinished(bool success);
private: private:
GlobalShortcutBackend* gnome_backend_; GlobalShortcutBackend* gnome_backend_;
GlobalShortcutBackend* system_backend_; GlobalShortcutBackend* system_backend_;

View File

@ -17,6 +17,7 @@
#include "gnomeglobalshortcutbackend.h" #include "gnomeglobalshortcutbackend.h"
#include "globalshortcuts.h" #include "globalshortcuts.h"
#include "dbus/gnomesettingsdaemon.h"
#include <QAction> #include <QAction>
#include <QtDebug> #include <QtDebug>
@ -45,10 +46,8 @@ bool GnomeGlobalShortcutBackend::DoRegister() {
} }
if (!interface_) { if (!interface_) {
interface_ = new QDBusInterface( interface_ = new OrgGnomeSettingsDaemonMediaKeysInterface(
kGsdService, kGsdPath, kGsdInterface, QDBusConnection::sessionBus()); kGsdService, kGsdPath, QDBusConnection::sessionBus(), this);
interface_->moveToThread(thread());
interface_->setParent(this);
} }
connect(interface_, SIGNAL(MediaPlayerKeyPressed(QString,QString)), connect(interface_, SIGNAL(MediaPlayerKeyPressed(QString,QString)),

View File

@ -20,7 +20,7 @@
#include "globalshortcutbackend.h" #include "globalshortcutbackend.h"
class QDBusInterface; class OrgGnomeSettingsDaemonMediaKeysInterface;
class GnomeGlobalShortcutBackend : public GlobalShortcutBackend { class GnomeGlobalShortcutBackend : public GlobalShortcutBackend {
Q_OBJECT Q_OBJECT
@ -41,7 +41,7 @@ private slots:
void GnomeMediaKeyPressed(const QString& application, const QString& key); void GnomeMediaKeyPressed(const QString& application, const QString& key);
private: private:
QDBusInterface* interface_; OrgGnomeSettingsDaemonMediaKeysInterface* interface_;
}; };
#endif // GNOMEGLOBALSHORTCUTBACKEND_H #endif // GNOMEGLOBALSHORTCUTBACKEND_H

View File

@ -27,41 +27,10 @@ namespace mpris {
Mpris::Mpris(Player* player, ArtLoader* art_loader, QObject* parent) Mpris::Mpris(Player* player, ArtLoader* art_loader, QObject* parent)
: QObject(parent), : QObject(parent),
player_(player), mpris1_(new mpris::Mpris1(player, art_loader, this)),
art_loader_(art_loader), mpris2_(new mpris::Mpris2(player, art_loader, mpris1_, this))
mpris1_(NULL),
mpris2_(NULL)
{ {
qDebug() << __PRETTY_FUNCTION__;
QFuture<void> future = QtConcurrent::run(this, &Mpris::Init);
QFutureWatcher<void>* watcher = new QFutureWatcher<void>(this);
watcher->setFuture(future);
connect(watcher, SIGNAL(finished()), SLOT(Initialised()));
}
void Mpris::Init() {
qDebug() << __PRETTY_FUNCTION__ << "- starting";
qDebug() << __PRETTY_FUNCTION__ << "- registering MPRIS1";
mpris1_ = new mpris::Mpris1(player_, art_loader_);
qDebug() << __PRETTY_FUNCTION__ << "- registering MPRIS2";
mpris2_ = new mpris::Mpris2(player_, art_loader_, mpris1_);
mpris1_->moveToThread(thread());
mpris2_->moveToThread(thread());
mpris1_->setParent(this);
mpris2_->setParent(this);
connect(mpris2_, SIGNAL(RaiseMainWindow()), SIGNAL(RaiseMainWindow())); connect(mpris2_, SIGNAL(RaiseMainWindow()), SIGNAL(RaiseMainWindow()));
qDebug() << __PRETTY_FUNCTION__ << "- complete";
}
void Mpris::Initialised() {
qDebug() << __PRETTY_FUNCTION__;
mpris2_->InitLibIndicate(); mpris2_->InitLibIndicate();
} }

View File

@ -37,16 +37,7 @@ public:
signals: signals:
void RaiseMainWindow(); void RaiseMainWindow();
private slots:
void Initialised();
private: private:
void Init();
private:
Player* player_;
ArtLoader* art_loader_;
Mpris1* mpris1_; Mpris1* mpris1_;
Mpris2* mpris2_; Mpris2* mpris2_;
}; };

View File

@ -0,0 +1,18 @@
<!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.gnome.SettingsDaemon.MediaKeys">
<method name="ReleaseMediaPlayerKeys">
<arg name="application" type="s" direction="in"/>
</method>
<method name="GrabMediaPlayerKeys">
<arg name="application" type="s" direction="in"/>
<arg name="time" type="u" direction="in"/>
</method>
<signal name="MediaPlayerKeyPressed">
<arg type="s"/>
<arg type="s"/>
</signal>
</interface>
</node>
"

View File

@ -313,9 +313,6 @@ int main(int argc, char *argv[]) {
qDBusRegisterMetaType<TrackIds>(); qDBusRegisterMetaType<TrackIds>();
qDBusRegisterMetaType<QList<QByteArray> >(); qDBusRegisterMetaType<QList<QByteArray> >();
// Create the session bus here so it's sure to live in the main thread.
QDBusConnection::sessionBus();
mpris::ArtLoader art_loader; mpris::ArtLoader art_loader;
mpris::Mpris mpris(&player, &art_loader); mpris::Mpris mpris(&player, &art_loader);
@ -325,10 +322,6 @@ int main(int argc, char *argv[]) {
#endif #endif
#ifdef HAVE_REMOTE #ifdef HAVE_REMOTE
#ifdef HAVE_DBUS
// Create the system bus here so it's sure to live in the main thread.
QDBusConnection::systemBus();
#endif
Zeroconf* zeroconf = Zeroconf::GetZeroconf(); Zeroconf* zeroconf = Zeroconf::GetZeroconf();
if (zeroconf) { if (zeroconf) {
HttpServer* server = new HttpServer(&player); HttpServer* server = new HttpServer(&player);

View File

@ -2,47 +2,94 @@
#include <QDBusConnection> #include <QDBusConnection>
#include <QHostInfo> #include <QHostInfo>
#include <QtConcurrentRun>
#include <QtDebug> #include <QtDebug>
#include "dbus/avahientrygroup.h" #include "dbus/avahientrygroup.h"
#include "dbus/avahiserver.h" #include "dbus/avahiserver.h"
void Avahi::Publish( Avahi::Avahi()
const QString& domain, const QString& type, const QString& name, quint16 port) { : server_(NULL),
QtConcurrent::run(Avahi::SyncPublish, domain, type, name, port); entry_group_(NULL)
{
} }
void Avahi::SyncPublish(const QString& domain, const QString& type, const QString& name, quint16 port) { void Avahi::Publish(const QString& domain,
OrgFreedesktopAvahiServerInterface server_interface( const QString& type,
const QString& name,
quint16 port) {
if (server_) {
// Already published
return;
}
domain_ = domain;
type_ = type;
name_ = name;
port_ = port;
server_ = new OrgFreedesktopAvahiServerInterface(
"org.freedesktop.Avahi", "org.freedesktop.Avahi",
"/", "/",
QDBusConnection::systemBus()); QDBusConnection::systemBus(),
this);
QDBusPendingReply<QDBusObjectPath> reply = server_interface.EntryGroupNew(); QDBusPendingReply<QDBusObjectPath> reply = server_->EntryGroupNew();
reply.waitForFinished(); QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply);
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
SLOT(EntryGroupNewFinished(QDBusPendingCallWatcher*)));
}
OrgFreedesktopAvahiEntryGroupInterface entry_group_interface( void Avahi::EntryGroupNewFinished(QDBusPendingCallWatcher* call) {
call->deleteLater();
QDBusPendingReply<QDBusObjectPath> reply = *call;
if (reply.isError()) {
qWarning() << "Failed to create new Avahi entry group:" << call->error();
return;
}
entry_group_ = new OrgFreedesktopAvahiEntryGroupInterface(
"org.freedesktop.Avahi", "org.freedesktop.Avahi",
reply.value().path(), reply.value().path(),
QDBusConnection::systemBus()); QDBusConnection::systemBus(),
this);
QDBusPendingReply<> add_reply = entry_group_interface.AddService( QDBusPendingReply<> add_reply = entry_group_->AddService(
-1, // Interface (Unspecified, ie. all interfaces) -1, // Interface (Unspecified, ie. all interfaces)
-1, // Protocol (Unspecified, ie. IPv4 & IPv6) -1, // Protocol (Unspecified, ie. IPv4 & IPv6)
0, // Flags 0, // Flags
name, // Service name name_, // Service name
type, // Service type type_, // Service type
domain, // Domain, ie. local domain_, // Domain, ie. local
QString::null, // Hostname (Avahi fills it if it's null) QString::null, // Hostname (Avahi fills it if it's null)
port, // Port port_, // Port
QList<QByteArray>()); // TXT record QList<QByteArray>()); // TXT record
add_reply.waitForFinished(); QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(add_reply);
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
SLOT(AddServiceFinished(QDBusPendingCallWatcher*)));
}
QDBusPendingReply<> commit_reply = entry_group_interface.Commit(); void Avahi::AddServiceFinished(QDBusPendingCallWatcher* call) {
commit_reply.waitForFinished(); call->deleteLater();
if (commit_reply.isValid()) {
if (call->isError()) {
qWarning() << "Failed to add Avahi service:" << call->error();
return;
}
QDBusPendingReply<> commit_reply = entry_group_->Commit();
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(commit_reply);
connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
SLOT(CommitFinished(QDBusPendingCallWatcher*)));
}
void Avahi::CommitFinished(QDBusPendingCallWatcher* call) {
call->deleteLater();
if (call->isError()) {
qDebug() << "Remote interface published on Avahi"; qDebug() << "Remote interface published on Avahi";
} else {
qWarning() << "Failed to commit Avahi changes:" << call->error();
} }
} }

View File

@ -3,13 +3,37 @@
#include "zeroconf.h" #include "zeroconf.h"
class Avahi : public Zeroconf { #include <QObject>
public:
virtual void Publish(
const QString& domain, const QString& type, const QString& name, quint16 port);
private: class OrgFreedesktopAvahiEntryGroupInterface;
static void SyncPublish(const QString& domain, const QString& type, const QString& name, quint16 port); class OrgFreedesktopAvahiServerInterface;
class QDBusPendingCallWatcher;
class Avahi : public QObject, public Zeroconf {
Q_OBJECT
public:
Avahi();
virtual void Publish(const QString& domain,
const QString& type,
const QString& name,
quint16 port);
private slots:
void EntryGroupNewFinished(QDBusPendingCallWatcher* call);
void AddServiceFinished(QDBusPendingCallWatcher* call);
void CommitFinished(QDBusPendingCallWatcher* call);
private:
OrgFreedesktopAvahiServerInterface* server_;
OrgFreedesktopAvahiEntryGroupInterface* entry_group_;
QString domain_;
QString type_;
QString name_;
quint16 port_;
}; };
#endif #endif

View File

@ -14,13 +14,11 @@ Zeroconf* Zeroconf::instance_ = NULL;
Zeroconf* Zeroconf::GetZeroconf() { Zeroconf* Zeroconf::GetZeroconf() {
if (!instance_) { if (!instance_) {
#ifdef Q_OS_DARWIN #if defined(Q_OS_DARWIN)
return new Bonjour(); instance_ = new Bonjour();
#endif #elif defined(HAVE_DBUS)
instance_ = new Avahi();
#ifdef HAVE_DBUS #endif
return new Avahi();
#endif
} }
return instance_; return instance_;

View File

@ -4,13 +4,17 @@
#include <QString> #include <QString>
class Zeroconf { class Zeroconf {
public: public:
virtual void Publish( virtual ~Zeroconf() {}
const QString& domain, const QString& type, const QString& name, quint16 port) = 0;
virtual void Publish(const QString& domain,
const QString& type,
const QString& name,
quint16 port) = 0;
static Zeroconf* GetZeroconf(); static Zeroconf* GetZeroconf();
private: private:
static Zeroconf* instance_; static Zeroconf* instance_;
}; };