summaryrefslogtreecommitdiff
path: root/libdbus-qeventloop/dbusconnectioneventloop.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libdbus-qeventloop/dbusconnectioneventloop.cpp')
-rw-r--r--libdbus-qeventloop/dbusconnectioneventloop.cpp259
1 files changed, 259 insertions, 0 deletions
diff --git a/libdbus-qeventloop/dbusconnectioneventloop.cpp b/libdbus-qeventloop/dbusconnectioneventloop.cpp
new file mode 100644
index 0000000..16f4a24
--- /dev/null
+++ b/libdbus-qeventloop/dbusconnectioneventloop.cpp
@@ -0,0 +1,259 @@
+#include <QCoreApplication>
+#include <QSocketNotifier>
+#include <QTimer>
+#include <QTimerEvent>
+
+#include "dbusconnectioneventloop.h"
+#include <stdio.h>
+
+DBUSConnectionEventLoop::DBUSConnectionEventLoop() : QObject()
+{
+}
+
+DBUSConnectionEventLoop::~DBUSConnectionEventLoop()
+{
+}
+
+// Handle a socket being ready to read.
+void DBUSConnectionEventLoop::readSocket(int fd)
+{
+ Watchers::const_iterator it = watchers.find(fd);
+
+ while( it != watchers.end() && it.key() == fd )
+ {
+ const Watcher &watcher = it.value();
+
+ if( watcher.read && watcher.read->isEnabled() )
+ {
+ watcher.read->setEnabled(false);
+ dbus_watch_handle(watcher.watch, DBUS_WATCH_READABLE);
+ watcher.read->setEnabled(true);
+ break;
+ }
+
+ ++it;
+ }
+
+ dispatch();
+}
+
+// Handle a socket being ready to write.
+void DBUSConnectionEventLoop::writeSocket(int fd)
+{
+ Watchers::const_iterator it = watchers.find(fd);
+
+ while( it != watchers.end() && it.key() == fd )
+ {
+ const Watcher &watcher = it.value();
+
+ if( watcher.write && watcher.write->isEnabled() )
+ {
+ watcher.write->setEnabled(false);
+ dbus_watch_handle(watcher.watch, DBUS_WATCH_WRITABLE);
+ watcher.write->setEnabled(true);
+ break;
+ }
+
+ ++it;
+ }
+}
+
+void DBUSConnectionEventLoop::dispatch()
+{
+ for( Connections::const_iterator it = connections.constBegin(); it != connections.constEnd(); ++it )
+ while( dbus_connection_dispatch(*it) == DBUS_DISPATCH_DATA_REMAINS )
+ ;
+}
+
+// Handle timer events.
+void DBUSConnectionEventLoop::timerEvent(QTimerEvent *e)
+{
+ DBusTimeout *timeout = timeouts.value(e->timerId());
+
+ if( timeout )
+ dbus_timeout_handle(timeout);
+}
+
+dbus_bool_t DBUSConnectionEventLoop::addWatch(DBusWatch *watch, void *data)
+{
+ DBUSConnectionEventLoop *loop = reinterpret_cast<DBUSConnectionEventLoop *>(data);
+
+ int fd = dbus_watch_get_unix_fd(watch);
+ unsigned int flags = dbus_watch_get_flags(watch);
+ dbus_bool_t enabled = dbus_watch_get_enabled(watch);
+
+ DBUSConnectionEventLoop::Watcher watcher;
+ watcher.watch = watch;
+
+ if( flags & DBUS_WATCH_READABLE )
+ {
+ watcher.read = new QSocketNotifier(fd, QSocketNotifier::Read, loop);
+ watcher.read->setEnabled(enabled);
+ loop->connect(watcher.read, SIGNAL(activated(int)), SLOT(readSocket(int)));
+ }
+
+ if( flags & DBUS_WATCH_WRITABLE )
+ {
+ watcher.write = new QSocketNotifier(fd, QSocketNotifier::Write, loop);
+ watcher.write->setEnabled(enabled);
+ loop->connect(watcher.write, SIGNAL(activated(int)), SLOT(writeSocket(int)));
+ }
+
+ loop->watchers.insertMulti(fd, watcher);
+
+ return true;
+}
+
+void DBUSConnectionEventLoop::removeWatch(DBusWatch *watch, void *data)
+{
+ DBUSConnectionEventLoop *loop = reinterpret_cast<DBUSConnectionEventLoop *>(data);
+
+ int fd = dbus_watch_get_unix_fd(watch);
+
+ DBUSConnectionEventLoop::Watchers::iterator it = loop->watchers.find(fd);
+
+ while( it != loop->watchers.end() && it.key() == fd )
+ {
+ DBUSConnectionEventLoop::Watcher &watcher = it.value();
+
+ if( watcher.watch == watch )
+ {
+ if( watcher.read )
+ delete watcher.read;
+
+ if( watcher.write )
+ delete watcher.write;
+
+ loop->watchers.erase(it);
+
+ return;
+ }
+
+ ++it;
+ }
+}
+
+void DBUSConnectionEventLoop::toggleWatch(DBusWatch *watch, void *data)
+{
+ DBUSConnectionEventLoop *loop = reinterpret_cast<DBUSConnectionEventLoop *>(data);
+
+ int fd = dbus_watch_get_unix_fd(watch);
+ unsigned int flags = dbus_watch_get_flags(watch);
+ dbus_bool_t enabled = dbus_watch_get_enabled(watch);
+
+ DBUSConnectionEventLoop::Watchers::const_iterator it = loop->watchers.find(fd);
+
+ while( it != loop->watchers.end() && it.key() == fd )
+ {
+ const DBUSConnectionEventLoop::Watcher &watcher = it.value();
+
+ if( watcher.watch == watch )
+ {
+ if( flags & DBUS_WATCH_READABLE && watcher.read )
+ watcher.read->setEnabled(enabled);
+
+ if( flags & DBUS_WATCH_WRITABLE && watcher.write )
+ watcher.write->setEnabled(enabled);
+
+ return;
+ }
+
+ ++it;
+ }
+}
+
+dbus_bool_t DBUSConnectionEventLoop::addTimeout(DBusTimeout *timeout, void *data)
+{
+ // Nothing to do if the timeout is disabled.
+ if( !dbus_timeout_get_enabled(timeout) )
+ return true;
+
+ // Pretend it is successful if there is no application instance.
+ if( !QCoreApplication::instance() )
+ return true;
+
+ DBUSConnectionEventLoop *loop = reinterpret_cast<DBUSConnectionEventLoop *>(data);
+
+ int id = loop->startTimer(dbus_timeout_get_interval(timeout));
+
+ if( !id )
+ return false;
+
+ loop->timeouts[id] = timeout;
+
+ return true;
+}
+
+void DBUSConnectionEventLoop::removeTimeout(DBusTimeout *timeout, void *data)
+{
+ DBUSConnectionEventLoop *loop = reinterpret_cast<DBUSConnectionEventLoop *>(data);
+
+ DBUSConnectionEventLoop::Timeouts::iterator it = loop->timeouts.begin();
+
+ while( it != loop->timeouts.end() )
+ {
+ if( it.value() == timeout )
+ {
+ loop->killTimer(it.key());
+ it = loop->timeouts.erase(it);
+ }
+ else
+ ++it;
+ }
+}
+
+void DBUSConnectionEventLoop::toggleTimeout(DBusTimeout *timeout, void *data)
+{
+ DBUSConnectionEventLoop::removeTimeout(timeout, data);
+ DBUSConnectionEventLoop::addTimeout(timeout, data);
+}
+
+void DBUSConnectionEventLoop::wakeupMain(void *data)
+{
+ DBUSConnectionEventLoop *loop = reinterpret_cast<DBUSConnectionEventLoop *>(data);
+
+ QTimer::singleShot(0, loop, SLOT(dispatch()));
+}
+
+// The initialization point
+bool DBUSConnectionEventLoop::initConnection(DBusConnection* conn)
+{
+ bool rc;
+
+ if( conn == NULL )
+ {
+ return false;
+ }
+
+ connections.append(conn);
+
+ if(
+ !dbus_connection_set_watch_functions(conn,
+ DBUSConnectionEventLoop::addWatch,
+ DBUSConnectionEventLoop::removeWatch,
+ DBUSConnectionEventLoop::toggleWatch,
+ this, 0)
+ )
+ {
+ rc = false;
+ }
+ else if(
+ !dbus_connection_set_timeout_functions(conn,
+ DBUSConnectionEventLoop::addTimeout,
+ DBUSConnectionEventLoop::removeTimeout,
+ DBUSConnectionEventLoop::toggleTimeout,
+ this, 0)
+ )
+ {
+ rc = false;
+ }
+ else
+ {
+ rc = true;
+ }
+
+ dbus_connection_set_wakeup_main_function(conn, DBUSConnectionEventLoop::wakeupMain, this, 0);
+
+ return rc;
+}
+