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 
31 using namespace DBus;
32 
33 Glib::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 
53 gboolean 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 
82 struct BusSource
83 {
84  GSource source;
85  GPollFD poll;
86 };
87 
88 static gboolean watch_prepare(GSource *source, gint *timeout)
89 {
90  debug_log("glib: watch_prepare");
91 
92  *timeout = -1;
93  return FALSE;
94 }
95 
96 static 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 
104 static 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 
112 static GSourceFuncs watch_funcs =
113 {
115  watch_check,
117  NULL
118 };
119 
120 Glib::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 
140 gboolean 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 */
206 {
207  GSource source;
209 };
210 
211 
212 static 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 
221 static gboolean dispatcher_check(GSource *source)
222 {
223  return FALSE;
224 }
225 
226 static gboolean
227 dispatcher_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 
237 static 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 
265 void 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 enabled() const
Definition: dispatcher.cpp:51
void attach(GMainContext *)
Timeout * add_timeout(Timeout::Internal *)
static gboolean dispatcher_check(GSource *source)
Watch * add_watch(Watch::Internal *)
Dispatcher * dispatcher
static GSourceFuncs watch_funcs
void dispatch_pending()
Definition: dispatcher.cpp:182
bool enabled() const
Definition: dispatcher.cpp:91
void set_priority(int priority)
static gboolean timeout_handler(gpointer)
static gboolean dispatcher_prepare(GSource *source, gint *timeout)
static const GSourceFuncs dispatcher_funcs
BusWatch(Watch::Internal *, GMainContext *, int)
static gboolean watch_dispatch(GSource *source, GSourceFunc callback, gpointer data)
bool handle(int flags)
Called to notify the D-Bus library when a previously-added watch is ready for reading or writing,...
Definition: dispatcher.cpp:96
int flags() const
Gets flags from DBusWatchFlags indicating what conditions should be monitored on the file descriptor.
Definition: dispatcher.cpp:86
static gboolean watch_handler(gpointer)
static gboolean watch_check(GSource *source)
static gboolean watch_prepare(GSource *source, gint *timeout)
DXXAPI LogFunction debug_log
Definition: debug.cpp:55
bool has_something_to_dispatch()
Definition: dispatcher.cpp:166
static gboolean dispatcher_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
bool handle()
Calls the timeout handler for this timeout.
Definition: dispatcher.cpp:56
int descriptor() const
A main loop could poll this descriptor to integrate dbus-c++.
Definition: dispatcher.cpp:70
BusTimeout(Timeout::Internal *, GMainContext *, int)
int interval() const
Gets the timeout interval.
Definition: dispatcher.cpp:46