You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
k9copy/k9devices/k9dbusdispatch.cpp

232 lines
6.9 KiB

//
// C++ Implementation: k9dbusdispatch
//
// Description:
//
//
// Author: Jean-Michel PETIT <k9copy@free.fr>, (C) 2007
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "k9dbusdispatch.h"
#ifdef HAVE_HAL
#include <dbus/dbus.h>
//==============================callbacks ========================================
static dbus_bool_t qDBusAddWatch(DBusWatch *watch, void *data)
{
int flags = dbus_watch_get_flags(watch);
int fd = dbus_watch_get_fd(watch);
K9DBusDispatch *d=(K9DBusDispatch*)data;
k9Watcher watcher;
if (flags & DBUS_WATCH_READABLE) {
bool enabled = dbus_watch_get_enabled(watch);
//tqDebug("addReadWatch %d %s", fd, (enabled ? "enabled" : "disabled"));
watcher.watch = watch;
watcher.read = new TQSocketNotifier(fd, TQSocketNotifier::Read, d);
if (!enabled) watcher.read->setEnabled(false);
d->connect(watcher.read, TQT_SIGNAL(activated(int)), TQT_SLOT(socketRead(int)));
}
if (flags & DBUS_WATCH_WRITABLE) {
bool enabled = dbus_watch_get_enabled(watch);
//tqDebug("addWriteWatch %d %s", fd, (enabled ? "enabled" : "disabled"));
watcher.watch = watch;
watcher.write = new TQSocketNotifier(fd, TQSocketNotifier::Write, d);
if (!enabled) watcher.write->setEnabled(false);
d->connect(watcher.write, TQT_SIGNAL(activated(int)), TQT_SLOT(socketWrite(int)));
}
// FIXME-QT4 d->watchers.insertMulti(fd, watcher);
K9DBusDispatch::WatcherHash::iterator it = d->watchers.find(fd);
if (it == d->watchers.end())
{
it = d->watchers.insert(fd, K9DBusDispatch::WatcherList());
}
it.data().append(watcher);
return true;
}
static void qDBusRemoveWatch(DBusWatch *watch, void *data)
{
K9DBusDispatch *d = (K9DBusDispatch*)data;
int fd = dbus_watch_get_fd(watch);
K9DBusDispatch::WatcherHash::iterator it = d->watchers.find(fd);
if (it != d->watchers.end())
{
K9DBusDispatch::WatcherList& list = *it;
for (K9DBusDispatch::WatcherList::iterator wit = list.begin();
wit != list.end(); ++wit)
{
if ((*wit).watch == watch)
{
// migth be called from a function triggered by a socket listener
// so just disconnect them and schedule their delayed deletion.
d->removedWatches.append(*wit);
if ((*wit).read)
{
(*wit).read->disconnect(d);
(*wit).read = 0;
}
if ((*wit).write)
{
(*wit).write->disconnect(d);
(*wit).write = 0;
}
(*wit).watch = 0;
}
}
}
if (d->removedWatches.count() > 0)
TQTimer::singleShot(0, d, TQT_SLOT(purgeRemovedWatches()));
}
static void qDBusToggleWatch(DBusWatch *watch, void *data)
{
K9DBusDispatch *d=(K9DBusDispatch*)data;
int fd = dbus_watch_get_fd(watch);
K9DBusDispatch::WatcherHash::iterator it = d->watchers.find(fd);
if (it != d->watchers.end()) {
K9DBusDispatch::WatcherList& list = *it;
for (K9DBusDispatch::WatcherList::iterator wit = list.begin(); wit != list.end();
++wit)
{
if ((*wit).watch == watch) {
bool enabled = dbus_watch_get_enabled(watch);
int flags = dbus_watch_get_flags(watch);
// tqDebug("toggle watch %d to %d (write: %d, read: %d)",
// dbus_watch_get_fd(watch), enabled,
// flags & DBUS_WATCH_WRITABLE, flags & DBUS_WATCH_READABLE);
if (flags & DBUS_WATCH_READABLE && (*wit).read)
(*wit).read->setEnabled(enabled);
if (flags & DBUS_WATCH_WRITABLE && (*wit).write)
(*wit).write->setEnabled(enabled);
return;
}
}
}
}
void K9DBusDispatch::purgeRemovedWatches()
{
if (removedWatches.isEmpty()) return;
WatcherList::iterator listIt = removedWatches.begin();
for (; listIt != removedWatches.end(); ++listIt)
{
delete (*listIt).read;
delete (*listIt).write;
}
removedWatches.clear();
uint count = 0;
WatcherHash::iterator it = watchers.begin();
while (it != watchers.end())
{
WatcherList& list = *it;
listIt = list.begin();
while (listIt != list.end())
{
if (!((*listIt).read) && !((*listIt).write))
{
listIt = list.erase(listIt);
++count;
}
}
if (list.isEmpty())
{
WatcherHash::iterator copyIt = it;
++it;
watchers.erase(copyIt);
}
else
++it;
}
}
//==============================================================================
void K9DBusDispatch::socketRead(int fd)
{
// FIXME-QT4 TQHashIterator<int, TQDBusConnectionPrivate::Watcher> it(watchers);
WatcherHash::const_iterator it = watchers.find(fd);
if (it != watchers.end()) {
const WatcherList& list = *it;
for (WatcherList::const_iterator wit = list.begin(); wit != list.end(); ++wit) {
if ((*wit).read && (*wit).read->isEnabled()) {
if (!dbus_watch_handle((*wit).watch, DBUS_WATCH_READABLE))
tqDebug("OUT OF MEM");
}
}
}
scheduleDispatch();
}
void K9DBusDispatch::socketWrite(int fd)
{
// FIXME-QT4 TQHashIterator<int, TQDBusConnectionPrivate::Watcher> it(watchers);
WatcherHash::const_iterator it = watchers.find(fd);
if (it != watchers.end()) {
const WatcherList& list = *it;
for (WatcherList::const_iterator wit = list.begin(); wit != list.end(); ++wit) {
if ((*wit).write && (*wit).write->isEnabled()) {
if (!dbus_watch_handle((*wit).watch, DBUS_WATCH_WRITABLE))
tqDebug("OUT OF MEM");
}
}
}
}
void K9DBusDispatch::scheduleDispatch()
{
m_dispatcher->start(0);
}
void K9DBusDispatch::dispatch()
{
if (dbus_connection_dispatch(m_connection) != DBUS_DISPATCH_DATA_REMAINS)
{
// stop dispatch timer
m_dispatcher->stop();
}
}
K9DBusDispatch::K9DBusDispatch(TQObject *parent, const char *name)
: TQObject(parent, name)
{
m_dispatcher = new TQTimer(this);
TQObject::connect(m_dispatcher, TQT_SIGNAL(timeout()), this, TQT_SLOT(dispatch()));
}
K9DBusDispatch::~K9DBusDispatch()
{
}
void K9DBusDispatch::setConnection(DBusConnection* _value) {
m_connection = _value;
dbus_connection_set_exit_on_disconnect(m_connection, false);
dbus_connection_set_watch_functions(m_connection, qDBusAddWatch, qDBusRemoveWatch,
qDBusToggleWatch, this, 0);
}
#include "k9dbusdispatch.moc"
#endif