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
00091
00092 *timeout = -1;
00093 return FALSE;
00094 }
00095
00096 static gboolean watch_check(GSource *source)
00097 {
00098
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 watch_prepare,
00114 watch_check,
00115 watch_dispatch,
00116 NULL
00117 };
00118
00119 Glib::BusWatch::BusWatch(Watch::Internal *wi, GMainContext *ctx, int priority)
00120 : Watch(wi), _ctx(ctx), _priority(priority), _source(NULL)
00121 {
00122 if (Watch::enabled())
00123 _enable();
00124 }
00125
00126 Glib::BusWatch::~BusWatch()
00127 {
00128 _disable();
00129 }
00130
00131 void Glib::BusWatch::toggle()
00132 {
00133 debug_log("glib: watch %p toggled (%s)", this, Watch::enabled() ? "on":"off");
00134
00135 if (Watch::enabled()) _enable();
00136 else _disable();
00137 }
00138
00139 gboolean Glib::BusWatch::watch_handler(gpointer data)
00140 {
00141 Glib::BusWatch *w = reinterpret_cast<Glib::BusWatch *>(data);
00142
00143 BusSource *io = (BusSource *)(w->_source);
00144
00145 int flags = 0;
00146 if (io->poll.revents &G_IO_IN)
00147 flags |= DBUS_WATCH_READABLE;
00148 if (io->poll.revents &G_IO_OUT)
00149 flags |= DBUS_WATCH_WRITABLE;
00150 if (io->poll.revents &G_IO_ERR)
00151 flags |= DBUS_WATCH_ERROR;
00152 if (io->poll.revents &G_IO_HUP)
00153 flags |= DBUS_WATCH_HANGUP;
00154
00155 w->handle(flags);
00156
00157 return TRUE;
00158 }
00159
00160 void Glib::BusWatch::_enable()
00161 {
00162 if (_source)
00163 _disable();
00164 _source = g_source_new(&watch_funcs, sizeof(BusSource));
00165 g_source_set_priority(_source, _priority);
00166 g_source_set_callback(_source, watch_handler, this, NULL);
00167
00168 int flags = Watch::flags();
00169 int condition = 0;
00170
00171 if (flags &DBUS_WATCH_READABLE)
00172 condition |= G_IO_IN;
00173 if (flags &DBUS_WATCH_WRITABLE)
00174 condition |= G_IO_OUT;
00175 if (flags &DBUS_WATCH_ERROR)
00176 condition |= G_IO_ERR;
00177 if (flags &DBUS_WATCH_HANGUP)
00178 condition |= G_IO_HUP;
00179
00180 GPollFD *poll = &(((BusSource *)_source)->poll);
00181 poll->fd = Watch::descriptor();
00182 poll->events = condition;
00183 poll->revents = 0;
00184
00185 g_source_add_poll(_source, poll);
00186 g_source_attach(_source, _ctx);
00187 }
00188
00189 void Glib::BusWatch::_disable()
00190 {
00191 if (!_source)
00192 return;
00193 GPollFD *poll = &(((BusSource *)_source)->poll);
00194 g_source_remove_poll(_source, poll);
00195 g_source_destroy(_source);
00196 _source = NULL;
00197 }
00198
00199
00200
00201
00202
00203
00204 struct DispatcherSource
00205 {
00206 GSource source;
00207 Dispatcher *dispatcher;
00208 };
00209
00210
00211 static gboolean dispatcher_prepare(GSource *source, gint *timeout)
00212 {
00213 Dispatcher *dispatcher = ((DispatcherSource*)source)->dispatcher;
00214
00215 *timeout = -1;
00216
00217 return dispatcher->has_something_to_dispatch()? TRUE:FALSE;
00218 }
00219
00220 static gboolean dispatcher_check(GSource *source)
00221 {
00222 return FALSE;
00223 }
00224
00225 static gboolean
00226 dispatcher_dispatch(GSource *source,
00227 GSourceFunc callback,
00228 gpointer user_data)
00229 {
00230 Dispatcher *dispatcher = ((DispatcherSource*)source)->dispatcher;
00231
00232 dispatcher->dispatch_pending();
00233 return TRUE;
00234 }
00235
00236 static const GSourceFuncs dispatcher_funcs = {
00237 dispatcher_prepare,
00238 dispatcher_check,
00239 dispatcher_dispatch,
00240 NULL
00241 };
00242
00243 Glib::BusDispatcher::BusDispatcher()
00244 : _ctx(NULL), _priority(G_PRIORITY_DEFAULT), _source(NULL)
00245 {
00246 }
00247
00248 Glib::BusDispatcher::~BusDispatcher()
00249 {
00250 if (_source)
00251 {
00252 GSource *temp = _source;
00253 _source = NULL;
00254
00255 g_source_destroy (temp);
00256 g_source_unref (temp);
00257 }
00258
00259 if (_ctx)
00260 g_main_context_unref(_ctx);
00261 }
00262
00263 void Glib::BusDispatcher::attach(GMainContext *ctx)
00264 {
00265 g_assert(_ctx == NULL);
00266
00267 _ctx = ctx ? ctx : g_main_context_default();
00268 g_main_context_ref(_ctx);
00269
00270
00271 _source = g_source_new((GSourceFuncs *) &dispatcher_funcs,
00272 sizeof(DispatcherSource));
00273
00274 ((DispatcherSource*)_source)->dispatcher = this;
00275 g_source_attach (_source, _ctx);
00276 }
00277
00278 Timeout *Glib::BusDispatcher::add_timeout(Timeout::Internal *wi)
00279 {
00280 Timeout *t = new Glib::BusTimeout(wi, _ctx, _priority);
00281
00282 debug_log("glib: added timeout %p (%s)", t, t->enabled() ? "on":"off");
00283
00284 return t;
00285 }
00286
00287 void Glib::BusDispatcher::rem_timeout(Timeout *t)
00288 {
00289 debug_log("glib: removed timeout %p", t);
00290
00291 delete t;
00292 }
00293
00294 Watch *Glib::BusDispatcher::add_watch(Watch::Internal *wi)
00295 {
00296 Watch *w = new Glib::BusWatch(wi, _ctx, _priority);
00297
00298 debug_log("glib: added watch %p (%s) fd=%d flags=%d",
00299 w, w->enabled() ? "on":"off", w->descriptor(), w->flags()
00300 );
00301 return w;
00302 }
00303
00304 void Glib::BusDispatcher::rem_watch(Watch *w)
00305 {
00306 debug_log("glib: removed watch %p", w);
00307
00308 delete w;
00309 }
00310
00311 void Glib::BusDispatcher::set_priority(int priority)
00312 {
00313 _priority = priority;
00314 }