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
41{
42 _disable();
43}
44
46{
47 debug_log("glib: timeout %p toggled (%s)", this, Timeout::enabled() ? "on" : "off");
48
49 if (Timeout::enabled()) _enable();
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
128{
129 _disable();
130}
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.
bool enabled() const
int flags() const
Gets flags from DBusWatchFlags indicating what conditions should be monitored on the file descriptor.
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