From 11a25eb79159c17677453616c1a4b596fe07dcac Mon Sep 17 00:00:00 2001 From: pdurante Date: Sun, 29 Apr 2007 01:50:19 +0000 Subject: [PATCH] * Initial integration with the glib main loop (configure with --enable-glib) git-svn-id: http://dev.openwengo.org/svn/openwengo/wengophone-ng/branches/wengophone-dbus-api/libs/dbus@10949 30a43799-04e7-0310-8b2b-ea0d24f86d0e --- include/dbus-c++/glib-integration.h | 118 +++++++++++++++ src/glib-integration.cpp | 218 ++++++++++++++++++++++++++++ 2 files changed, 336 insertions(+) create mode 100644 include/dbus-c++/glib-integration.h create mode 100644 src/glib-integration.cpp diff --git a/include/dbus-c++/glib-integration.h b/include/dbus-c++/glib-integration.h new file mode 100644 index 0000000..a78d7ec --- /dev/null +++ b/include/dbus-c++/glib-integration.h @@ -0,0 +1,118 @@ +/* + * + * D-Bus++ - C++ bindings for D-Bus + * + * Copyright (C) 2005-2007 Paolo Durante + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + + +#ifndef __DBUSXX_GLIB_INTEGRATION_H +#define __DBUSXX_GLIB_INTEGRATION_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "eventloop.h" + +namespace DBus { + +namespace Glib { + +class BusDispatcher; + +class BusTimeout : public Timeout +{ +private: + + BusTimeout( Timeout::Internal*, GMainContext* ); + + ~BusTimeout(); + + void toggle(); + + static gboolean timeout_handler( gpointer ); + + void _enable(); + + void _disable(); + +private: + + GSource* _source; + GMainContext* _ctx; + +friend class BusDispatcher; +}; + +class BusWatch : public Watch +{ +private: + + BusWatch( Watch::Internal*, GMainContext* ); + + ~BusWatch(); + + void toggle(); + + static gboolean watch_handler( gpointer ); + + void _enable(); + + void _disable(); + +private: + + GSource* _source; + GMainContext* _ctx; + +friend class BusDispatcher; +}; + +class BusDispatcher : public Dispatcher +{ +public: + BusDispatcher() : _ctx(NULL) {} + + void attach( GMainContext* ); + + void enter() {} + + void leave() {} + + Timeout* add_timeout( Timeout::Internal* ); + + void rem_timeout( Timeout* ); + + Watch* add_watch( Watch::Internal* ); + + void rem_watch( Watch* ); + +private: + + GMainContext* _ctx; +}; + +} /* namespace Glib */ + +} /* namespace DBus */ + +#endif//__DBUSXX_GLIB_INTEGRATION_H diff --git a/src/glib-integration.cpp b/src/glib-integration.cpp new file mode 100644 index 0000000..42c31ea --- /dev/null +++ b/src/glib-integration.cpp @@ -0,0 +1,218 @@ +/* + * + * D-Bus++ - C++ bindings for D-Bus + * + * Copyright (C) 2005-2007 Paolo Durante + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + + +#include + +#include // for DBUS_WATCH_* + +using namespace DBus; + +Glib::BusTimeout::BusTimeout( Timeout::Internal* ti, GMainContext* ctx ) +: Timeout(ti), _ctx(ctx) +{ + _enable(); +} + +Glib::BusTimeout::~BusTimeout() +{ + _disable(); +} + +void Glib::BusTimeout::toggle() +{ + debug_log("glib: timeout %p toggled (%s)", this, Timeout::enabled() ? "on":"off"); + + if(Timeout::enabled()) _enable(); + else _disable(); +} + +gboolean Glib::BusTimeout::timeout_handler( gpointer data ) +{ + Glib::BusTimeout* t = reinterpret_cast(data); + + t->handle(); + + return TRUE; +} + +void Glib::BusTimeout::_enable() +{ + _source = g_timeout_source_new(Timeout::interval()); + g_source_set_callback(_source, timeout_handler, this, NULL); + g_source_attach(_source, _ctx); +} + +void Glib::BusTimeout::_disable() +{ + g_source_destroy(_source); +} + +struct BusSource +{ + GSource source; + GPollFD poll; +}; + +static gboolean watch_prepare( GSource *source, gint *timeout ) +{ +// debug_log("glib: watch_prepare"); + + *timeout = -1; + return FALSE; +} + +static gboolean watch_check( GSource *source ) +{ +// debug_log("glib: watch_check"); + + BusSource* io = (BusSource*)source; + return io->poll.revents ? TRUE : FALSE; +} + +static gboolean watch_dispatch( GSource *source, GSourceFunc callback, gpointer data ) +{ + debug_log("glib: watch_dispatch"); + + gboolean cb = callback(data); + DBus::default_dispatcher->dispatch_pending(); //TODO: won't work in case of multiple dispatchers + return cb; +} + +static GSourceFuncs watch_funcs = { + watch_prepare, + watch_check, + watch_dispatch, + NULL +}; + +Glib::BusWatch::BusWatch( Watch::Internal* wi, GMainContext* ctx ) +: Watch(wi), _ctx(ctx) +{ + _enable(); +} + +Glib::BusWatch::~BusWatch() +{ + _disable(); +} + +void Glib::BusWatch::toggle() +{ + debug_log("glib: watch %p toggled (%s)", this, Watch::enabled() ? "on":"off"); + + if(Watch::enabled()) _enable(); + else _disable(); +} + +gboolean Glib::BusWatch::watch_handler( gpointer data ) +{ + Glib::BusWatch* w = reinterpret_cast(data); + + BusSource* io = (BusSource*)(w->_source); + + int flags = 0; + if(io->poll.revents & G_IO_IN) + flags |= DBUS_WATCH_READABLE; + if(io->poll.revents & G_IO_OUT) + flags |= DBUS_WATCH_WRITABLE; + if(io->poll.revents & G_IO_ERR) + flags |= DBUS_WATCH_ERROR; + if(io->poll.revents & G_IO_HUP) + flags |= DBUS_WATCH_HANGUP; + + w->handle(flags); + + return TRUE; +} + +void Glib::BusWatch::_enable() +{ + _source = g_source_new(&watch_funcs, sizeof(BusSource)); + g_source_set_callback(_source, watch_handler, this, NULL); + + int flags = Watch::flags(); + int condition = 0; + + if(flags & DBUS_WATCH_READABLE) + condition |= G_IO_IN; +// if(flags & DBUS_WATCH_WRITABLE) +// condition |= G_IO_OUT; + if(flags & DBUS_WATCH_ERROR) + condition |= G_IO_ERR; + if(flags & DBUS_WATCH_HANGUP) + condition |= G_IO_HUP; + + GPollFD* poll = &(((BusSource*)_source)->poll); + poll->fd = Watch::descriptor(); + poll->events = condition; + poll->revents = 0; + + g_source_add_poll(_source, poll); + g_source_attach(_source, _ctx); +} + +void Glib::BusWatch::_disable() +{ + GPollFD* poll = &(((BusSource*)_source)->poll); + g_source_remove_poll(_source, poll); + g_source_destroy(_source); +} + +void Glib::BusDispatcher::attach( GMainContext* ctx ) +{ + _ctx = ctx ? ctx : g_main_context_default(); +} + +Timeout* Glib::BusDispatcher::add_timeout( Timeout::Internal* wi ) +{ + Timeout* t = new Glib::BusTimeout(wi, _ctx); + + debug_log("glib: added timeout %p (%s)", t, t->enabled() ? "on":"off"); + + return t; +} + +void Glib::BusDispatcher::rem_timeout( Timeout* t ) +{ + debug_log("glib: removed timeout %p", t); + + delete t; +} + +Watch* Glib::BusDispatcher::add_watch( Watch::Internal* wi ) +{ + Watch* w = new Glib::BusWatch(wi, _ctx); + + debug_log("glib: added watch %p (%s) fd=%d flags=%d", + w, w->enabled() ? "on":"off", w->descriptor(), w->flags() + ); + return w; +} + +void Glib::BusDispatcher::rem_watch( Watch* w ) +{ + debug_log("glib: removed watch %p", w); + + delete w; +}