00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 #include <dbus-c++/glib-integration.h>
00028
00029 #include <dbus/dbus.h>
00030
00031 using namespace DBus;
00032
00033 Glib::BusTimeout::BusTimeout(Timeout::Internal *ti, GMainContext *ctx, int priority)
00034 : Timeout(ti), _ctx(ctx), _priority(priority), _source(NULL)
00035 {
00036 if (Timeout::enabled())
00037 _enable();
00038 }
00039
00040 Glib::BusTimeout::~BusTimeout()
00041 {
00042 _disable();
00043 }
00044
00045 void Glib::BusTimeout::toggle()
00046 {
00047 debug_log("glib: timeout %p toggled (%s)", this, Timeout::enabled() ? "on" : "off");
00048
00049 if (Timeout::enabled()) _enable();
00050 else _disable();
00051 }
00052
00053 gboolean Glib::BusTimeout::timeout_handler(gpointer data)
00054 {
00055 Glib::BusTimeout *t = reinterpret_cast<Glib::BusTimeout *>(data);
00056
00057 t->handle();
00058
00059 return TRUE;
00060 }
00061
00062 void Glib::BusTimeout::_enable()
00063 {
00064 if (_source)
00065 _disable();
00066
00067 _source = g_timeout_source_new(Timeout::interval());
00068 g_source_set_priority(_source, _priority);
00069 g_source_set_callback(_source, timeout_handler, this, NULL);
00070 g_source_attach(_source, _ctx);
00071 }
00072
00073 void Glib::BusTimeout::_disable()
00074 {
00075 if (_source)
00076 {
00077 g_source_destroy(_source);
00078 _source = NULL;
00079 }
00080 }
00081
00082 struct BusSource
00083 {
00084 GSource source;
00085 GPollFD poll;
00086 };
00087
00088 static gboolean watch_prepare(GSource *source, gint *timeout)
00089 {
00090 debug_log("glib: watch_prepare");
00091
00092 *timeout = -1;
00093 return FALSE;
00094 }
00095
00096 static gboolean watch_check(GSource *source)
00097 {
00098 debug_log("glib: watch_check");
00099
00100 BusSource *io = (BusSource *)source;
00101 return io->poll.revents ? TRUE : FALSE;
00102 }
00103
00104 static gboolean watch_dispatch(GSource *source, GSourceFunc callback, gpointer data)
00105 {
00106 debug_log("glib: watch_dispatch");
00107
00108 gboolean cb = callback(data);
00109 return cb;
00110 }
00111
00112 static GSourceFuncs watch_funcs =
00113 {
00114 watch_prepare,
00115 watch_check,
00116 watch_dispatch,
00117 NULL
00118 };
00119
00120 Glib::BusWatch::BusWatch(Watch::Internal *wi, GMainContext *ctx, int priority)
00121 : Watch(wi), _ctx(ctx), _priority(priority), _source(NULL)
00122 {
00123 if (Watch::enabled())
00124 _enable();
00125 }
00126
00127 Glib::BusWatch::~BusWatch()
00128 {
00129 _disable();
00130 }
00131
00132 void Glib::BusWatch::toggle()
00133 {
00134 debug_log("glib: watch %p toggled (%s)", this, Watch::enabled() ? "on" : "off");
00135
00136 if (Watch::enabled()) _enable();
00137 else _disable();
00138 }
00139
00140 gboolean Glib::BusWatch::watch_handler(gpointer data)
00141 {
00142 Glib::BusWatch *w = reinterpret_cast<Glib::BusWatch *>(data);
00143
00144 BusSource *io = (BusSource *)(w->_source);
00145
00146 int flags = 0;
00147 if (io->poll.revents & G_IO_IN)
00148 flags |= DBUS_WATCH_READABLE;
00149 if (io->poll.revents & G_IO_OUT)
00150 flags |= DBUS_WATCH_WRITABLE;
00151 if (io->poll.revents & G_IO_ERR)
00152 flags |= DBUS_WATCH_ERROR;
00153 if (io->poll.revents & G_IO_HUP)
00154 flags |= DBUS_WATCH_HANGUP;
00155
00156 w->handle(flags);
00157
00158 return TRUE;
00159 }
00160
00161 void Glib::BusWatch::_enable()
00162 {
00163 if (_source)
00164 _disable();
00165 _source = g_source_new(&watch_funcs, sizeof(BusSource));
00166 g_source_set_priority(_source, _priority);
00167 g_source_set_callback(_source, watch_handler, this, NULL);
00168
00169 int flags = Watch::flags();
00170 int condition = 0;
00171
00172 if (flags & DBUS_WATCH_READABLE)
00173 condition |= G_IO_IN;
00174 if (flags & DBUS_WATCH_WRITABLE)
00175 condition |= G_IO_OUT;
00176 if (flags & DBUS_WATCH_ERROR)
00177 condition |= G_IO_ERR;
00178 if (flags & DBUS_WATCH_HANGUP)
00179 condition |= G_IO_HUP;
00180
00181 GPollFD *poll = &(((BusSource *)_source)->poll);
00182 poll->fd = Watch::descriptor();
00183 poll->events = condition;
00184 poll->revents = 0;
00185
00186 g_source_add_poll(_source, poll);
00187 g_source_attach(_source, _ctx);
00188 }
00189
00190 void Glib::BusWatch::_disable()
00191 {
00192 if (!_source)
00193 return;
00194 GPollFD *poll = &(((BusSource *)_source)->poll);
00195 g_source_remove_poll(_source, poll);
00196 g_source_destroy(_source);
00197 _source = NULL;
00198 }
00199
00200
00201
00202
00203
00204
00205 struct DispatcherSource
00206 {
00207 GSource source;
00208 Dispatcher *dispatcher;
00209 };
00210
00211
00212 static gboolean dispatcher_prepare(GSource *source, gint *timeout)
00213 {
00214 Dispatcher *dispatcher = ((DispatcherSource *)source)->dispatcher;
00215
00216 *timeout = -1;
00217
00218 return dispatcher->has_something_to_dispatch() ? TRUE : FALSE;
00219 }
00220
00221 static gboolean dispatcher_check(GSource *source)
00222 {
00223 return FALSE;
00224 }
00225
00226 static gboolean
00227 dispatcher_dispatch(GSource *source,
00228 GSourceFunc callback,
00229 gpointer user_data)
00230 {
00231 Dispatcher *dispatcher = ((DispatcherSource *)source)->dispatcher;
00232
00233 dispatcher->dispatch_pending();
00234 return TRUE;
00235 }
00236
00237 static const GSourceFuncs dispatcher_funcs =
00238 {
00239 dispatcher_prepare,
00240 dispatcher_check,
00241 dispatcher_dispatch,
00242 NULL
00243 };
00244
00245 Glib::BusDispatcher::BusDispatcher()
00246 : _ctx(NULL), _priority(G_PRIORITY_DEFAULT), _source(NULL)
00247 {
00248 }
00249
00250 Glib::BusDispatcher::~BusDispatcher()
00251 {
00252 if (_source)
00253 {
00254 GSource *temp = _source;
00255 _source = NULL;
00256
00257 g_source_destroy(temp);
00258 g_source_unref(temp);
00259 }
00260
00261 if (_ctx)
00262 g_main_context_unref(_ctx);
00263 }
00264
00265 void Glib::BusDispatcher::attach(GMainContext *ctx)
00266 {
00267 g_assert(_ctx == NULL);
00268
00269 _ctx = ctx ? ctx : g_main_context_default();
00270 g_main_context_ref(_ctx);
00271
00272
00273 _source = g_source_new((GSourceFuncs *) &dispatcher_funcs,
00274 sizeof(DispatcherSource));
00275
00276 ((DispatcherSource *)_source)->dispatcher = this;
00277 g_source_attach(_source, _ctx);
00278 }
00279
00280 Timeout *Glib::BusDispatcher::add_timeout(Timeout::Internal *wi)
00281 {
00282 Timeout *t = new Glib::BusTimeout(wi, _ctx, _priority);
00283
00284 debug_log("glib: added timeout %p (%s)", t, t->enabled() ? "on" : "off");
00285
00286 return t;
00287 }
00288
00289 void Glib::BusDispatcher::rem_timeout(Timeout *t)
00290 {
00291 debug_log("glib: removed timeout %p", t);
00292
00293 delete t;
00294 }
00295
00296 Watch *Glib::BusDispatcher::add_watch(Watch::Internal *wi)
00297 {
00298 Watch *w = new Glib::BusWatch(wi, _ctx, _priority);
00299
00300 debug_log("glib: added watch %p (%s) fd=%d flags=%d",
00301 w, w->enabled() ? "on" : "off", w->descriptor(), w->flags()
00302 );
00303 return w;
00304 }
00305
00306 void Glib::BusDispatcher::rem_watch(Watch *w)
00307 {
00308 debug_log("glib: removed watch %p", w);
00309
00310 delete w;
00311 }
00312
00313 void Glib::BusDispatcher::set_priority(int priority)
00314 {
00315 _priority = priority;
00316 }