glib-integration.cpp
Go to the documentation of this file.
1/*
2 *
3 * D-Bus++ - C++ bindings for D-Bus
4 *
5 * Copyright (C) 2005-2007 Paolo Durante <shackan@gmail.com>
6 *
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
28
29#include <dbus/dbus.h> // for DBUS_WATCH_*
30
31using namespace DBus;
32
33Glib::BusTimeout::BusTimeout(Timeout::Internal *ti, GMainContext *ctx, int priority)
34 : Timeout(ti), _ctx(ctx), _priority(priority), _source(NULL)
35{
36 if (Timeout::enabled())
37 _enable();
38}
39
44
46{
47 debug_log("glib: timeout %p toggled (%s)", this, Timeout::enabled() ? "on" : "off");
48
50 else _disable();
51}
52
53gboolean Glib::BusTimeout::timeout_handler(gpointer data)
54{
55 Glib::BusTimeout *t = reinterpret_cast<Glib::BusTimeout *>(data);
56
57 t->handle();
58
59 return TRUE;
60}
61
63{
64 if (_source)
65 _disable(); // be sane
66
67 _source = g_timeout_source_new(Timeout::interval());
68 g_source_set_priority(_source, _priority);
69 g_source_set_callback(_source, timeout_handler, this, NULL);
70 g_source_attach(_source, _ctx);
71}
72
74{
75 if (_source)
76 {
77 g_source_destroy(_source);
78 _source = NULL;
79 }
80}
81
83{
84 GSource source;
85 GPollFD poll;
86};
87
88static gboolean watch_prepare(GSource *source, gint *timeout)
89{
90 debug_log("glib: watch_prepare");
91
92 *timeout = -1;
93 return FALSE;
94}
95
96static gboolean watch_check(GSource *source)
97{
98 debug_log("glib: watch_check");
99
100 BusSource *io = (BusSource *)source;
101 return io->poll.revents ? TRUE : FALSE;
102}
103
104static gboolean watch_dispatch(GSource *source, GSourceFunc callback, gpointer data)
105{
106 debug_log("glib: watch_dispatch");
107
108 gboolean cb = callback(data);
109 return cb;
110}
111
112static GSourceFuncs watch_funcs =
113{
117 NULL
118};
119
120Glib::BusWatch::BusWatch(Watch::Internal *wi, GMainContext *ctx, int priority)
121 : Watch(wi), _ctx(ctx), _priority(priority), _source(NULL)
122{
123 if (Watch::enabled())
124 _enable();
125}
126
131
133{
134 debug_log("glib: watch %p toggled (%s)", this, Watch::enabled() ? "on" : "off");
135
136 if (Watch::enabled()) _enable();
137 else _disable();
138}
139
140gboolean Glib::BusWatch::watch_handler(gpointer data)
141{
142 Glib::BusWatch *w = reinterpret_cast<Glib::BusWatch *>(data);
143
144 BusSource *io = (BusSource *)(w->_source);
145
146 int flags = 0;
147 if (io->poll.revents & G_IO_IN)
148 flags |= DBUS_WATCH_READABLE;
149 if (io->poll.revents & G_IO_OUT)
150 flags |= DBUS_WATCH_WRITABLE;
151 if (io->poll.revents & G_IO_ERR)
152 flags |= DBUS_WATCH_ERROR;
153 if (io->poll.revents & G_IO_HUP)
154 flags |= DBUS_WATCH_HANGUP;
155
156 w->handle(flags);
157
158 return TRUE;
159}
160
162{
163 if (_source)
164 _disable(); // be sane
165 _source = g_source_new(&watch_funcs, sizeof(BusSource));
166 g_source_set_priority(_source, _priority);
167 g_source_set_callback(_source, watch_handler, this, NULL);
168
169 int flags = Watch::flags();
170 int condition = 0;
171
172 if (flags & DBUS_WATCH_READABLE)
173 condition |= G_IO_IN;
174 if (flags & DBUS_WATCH_WRITABLE)
175 condition |= G_IO_OUT;
176 if (flags & DBUS_WATCH_ERROR)
177 condition |= G_IO_ERR;
178 if (flags & DBUS_WATCH_HANGUP)
179 condition |= G_IO_HUP;
180
181 GPollFD *poll = &(((BusSource *)_source)->poll);
182 poll->fd = Watch::descriptor();
183 poll->events = condition;
184 poll->revents = 0;
185
186 g_source_add_poll(_source, poll);
187 g_source_attach(_source, _ctx);
188}
189
191{
192 if (!_source)
193 return;
194 GPollFD *poll = &(((BusSource *)_source)->poll);
195 g_source_remove_poll(_source, poll);
196 g_source_destroy(_source);
197 _source = NULL;
198}
199
200/*
201 * We need this on top of the IO handlers, because sometimes
202 * there are messages to dispatch queued up but no IO pending.
203 * (fixes also a previous problem of code not working in case of multiple dispatchers)
204*/
210
211
212static gboolean dispatcher_prepare(GSource *source, gint *timeout)
213{
214 Dispatcher *dispatcher = ((DispatcherSource *)source)->dispatcher;
215
216 *timeout = -1;
217
218 return dispatcher->has_something_to_dispatch() ? TRUE : FALSE;
219}
220
221static gboolean dispatcher_check(GSource *source)
222{
223 return FALSE;
224}
225
226static gboolean
227dispatcher_dispatch(GSource *source,
228 GSourceFunc callback,
229 gpointer user_data)
230{
231 Dispatcher *dispatcher = ((DispatcherSource *)source)->dispatcher;
232
233 dispatcher->dispatch_pending();
234 return TRUE;
235}
236
237static const GSourceFuncs dispatcher_funcs =
238{
242 NULL
243};
244
246 : _ctx(NULL), _priority(G_PRIORITY_DEFAULT), _source(NULL)
247{
248}
249
251{
252 if (_source)
253 {
254 GSource *temp = _source;
255 _source = NULL;
256
257 g_source_destroy(temp);
258 g_source_unref(temp);
259 }
260
261 if (_ctx)
262 g_main_context_unref(_ctx);
263}
264
265void Glib::BusDispatcher::attach(GMainContext *ctx)
266{
267 g_assert(_ctx == NULL); // just to be sane
268
269 _ctx = ctx ? ctx : g_main_context_default();
270 g_main_context_ref(_ctx);
271
272 // create the source for dispatching messages
273 _source = g_source_new((GSourceFuncs *) &dispatcher_funcs,
274 sizeof(DispatcherSource));
275
276 ((DispatcherSource *)_source)->dispatcher = this;
277 g_source_attach(_source, _ctx);
278}
279
281{
282 Timeout *t = new Glib::BusTimeout(wi, _ctx, _priority);
283
284 debug_log("glib: added timeout %p (%s)", t, t->enabled() ? "on" : "off");
285
286 return t;
287}
288
290{
291 debug_log("glib: removed timeout %p", t);
292
293 delete t;
294}
295
297{
298 Watch *w = new Glib::BusWatch(wi, _ctx, _priority);
299
300 debug_log("glib: added watch %p (%s) fd=%d flags=%d",
301 w, w->enabled() ? "on" : "off", w->descriptor(), w->flags()
302 );
303 return w;
304}
305
307{
308 debug_log("glib: removed watch %p", w);
309
310 delete w;
311}
312
314{
315 _priority = priority;
316}
bool has_something_to_dispatch()
void set_priority(int priority)
Watch * add_watch(Watch::Internal *)
void attach(GMainContext *)
Timeout * add_timeout(Timeout::Internal *)
static gboolean timeout_handler(gpointer)
BusTimeout(Timeout::Internal *, GMainContext *, int)
BusWatch(Watch::Internal *, GMainContext *, int)
static gboolean watch_handler(gpointer)
bool enabled() const
int interval() const
Gets the timeout interval.
bool handle()
Calls the timeout handler for this timeout.
Timeout(Internal *i)
bool enabled() const
int flags() const
Gets flags from DBusWatchFlags indicating what conditions should be monitored on the file descriptor.
Watch(Internal *i)
bool handle(int flags)
Called to notify the D-Bus library when a previously-added watch is ready for reading or writing,...
int descriptor() const
A main loop could poll this descriptor to integrate dbus-c++.
static gboolean dispatcher_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
static GSourceFuncs watch_funcs
static gboolean watch_check(GSource *source)
static const GSourceFuncs dispatcher_funcs
static gboolean dispatcher_check(GSource *source)
static gboolean watch_prepare(GSource *source, gint *timeout)
static gboolean watch_dispatch(GSource *source, GSourceFunc callback, gpointer data)
static gboolean dispatcher_prepare(GSource *source, gint *timeout)
DXXAPI LogFunction debug_log
Definition debug.cpp:55