1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-gmain.c GLib main loop integration
4 * Copyright (C) 2002, 2003 CodeFactory AB
5 * Copyright (C) 2005 Red Hat, Inc.
7 * Licensed under the Academic Free License version 2.1
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * This file is based on dbus-gmain.c from dbus-glib with functions renamed
24 * and unnecessary code removed.
28 #include <dbus/dbus.h>
33 #define _(x) dgettext (GETTEXT_PACKAGE, x)
37 * @defgroup DBusGLibInternals GLib bindings implementation details
38 * @ingroup DBusInternals
39 * @brief Implementation details of GLib bindings
46 * A GSource subclass for dispatching DBusConnection messages.
47 * We need this on top of the IO handlers, because sometimes
48 * there are messages to dispatch queued up but no IO pending.
52 GSource source; /**< the parent GSource */
53 DBusConnection *connection; /**< the connection to dispatch */
56 static gboolean message_queue_prepare (GSource *source,
58 static gboolean message_queue_check (GSource *source);
59 static gboolean message_queue_dispatch (GSource *source,
63 static const GSourceFuncs message_queue_funcs = {
64 message_queue_prepare,
66 message_queue_dispatch,
71 message_queue_prepare (GSource *source,
74 DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
78 return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
82 message_queue_check (GSource *source)
88 message_queue_dispatch (GSource *source,
92 DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
94 dbus_connection_ref (connection);
96 /* Only dispatch once - we don't want to starve other GSource */
97 dbus_connection_dispatch (connection);
99 dbus_connection_unref (connection);
106 GMainContext *context; /**< the main context */
107 GSList *ios; /**< all IOHandler */
108 GSList *timeouts; /**< all TimeoutHandler */
109 DBusConnection *connection; /**< NULL if this is really for a server not a connection */
110 GSource *message_queue_source; /**< DBusGMessageQueue */
125 DBusTimeout *timeout;
128 dbus_int32_t _dbus_gmain_connection_slot = -1;
129 static dbus_int32_t server_slot = -1;
131 static ConnectionSetup*
132 connection_setup_new (GMainContext *context,
133 DBusConnection *connection)
137 cs = g_new0 (ConnectionSetup, 1);
139 g_assert (context != NULL);
141 cs->context = context;
142 g_main_context_ref (cs->context);
146 cs->connection = connection;
148 cs->message_queue_source = g_source_new ((GSourceFuncs *) &message_queue_funcs,
149 sizeof (DBusGMessageQueue));
150 ((DBusGMessageQueue*)cs->message_queue_source)->connection = connection;
151 g_source_attach (cs->message_queue_source, cs->context);
158 io_handler_source_finalized (gpointer data)
165 dbus_watch_set_data (handler->watch, NULL, NULL);
171 io_handler_destroy_source (void *data)
179 GSource *source = handler->source;
180 handler->source = NULL;
181 handler->cs->ios = g_slist_remove (handler->cs->ios, handler);
182 g_source_destroy (source);
183 g_source_unref (source);
188 io_handler_watch_freed (void *data)
194 handler->watch = NULL;
196 io_handler_destroy_source (handler);
200 io_handler_dispatch (GIOChannel *source,
201 GIOCondition condition,
205 guint dbus_condition = 0;
206 DBusConnection *connection;
210 connection = handler->cs->connection;
213 dbus_connection_ref (connection);
215 if (condition & G_IO_IN)
216 dbus_condition |= DBUS_WATCH_READABLE;
217 if (condition & G_IO_OUT)
218 dbus_condition |= DBUS_WATCH_WRITABLE;
219 if (condition & G_IO_ERR)
220 dbus_condition |= DBUS_WATCH_ERROR;
221 if (condition & G_IO_HUP)
222 dbus_condition |= DBUS_WATCH_HANGUP;
224 /* Note that we don't touch the handler after this, because
225 * dbus may have disabled the watch and thus killed the
228 dbus_watch_handle (handler->watch, dbus_condition);
232 dbus_connection_unref (connection);
237 /* Attach the connection setup to the given watch, removing any
238 * previously-attached connection setup.
241 connection_setup_add_watch (ConnectionSetup *cs,
245 GIOCondition condition;
249 if (!dbus_watch_get_enabled (watch))
252 flags = dbus_watch_get_flags (watch);
254 condition = G_IO_ERR | G_IO_HUP;
255 if (flags & DBUS_WATCH_READABLE)
256 condition |= G_IO_IN;
257 if (flags & DBUS_WATCH_WRITABLE)
258 condition |= G_IO_OUT;
260 handler = g_new0 (IOHandler, 1);
262 handler->watch = watch;
264 channel = g_io_channel_unix_new (dbus_watch_get_unix_fd (watch));
266 handler->source = g_io_create_watch (channel, condition);
267 g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler,
268 io_handler_source_finalized);
269 g_source_attach (handler->source, cs->context);
271 cs->ios = g_slist_prepend (cs->ios, handler);
273 dbus_watch_set_data (watch, handler, io_handler_watch_freed);
274 g_io_channel_unref (channel);
278 connection_setup_remove_watch (ConnectionSetup *cs,
283 handler = dbus_watch_get_data (watch);
285 if (handler == NULL || handler->cs != cs)
288 io_handler_destroy_source (handler);
292 timeout_handler_source_finalized (gpointer data)
294 TimeoutHandler *handler;
298 if (handler->timeout)
299 dbus_timeout_set_data (handler->timeout, NULL, NULL);
305 timeout_handler_destroy_source (void *data)
307 TimeoutHandler *handler;
313 GSource *source = handler->source;
314 handler->source = NULL;
315 handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler);
316 g_source_destroy (source);
317 g_source_unref (source);
322 timeout_handler_timeout_freed (void *data)
324 TimeoutHandler *handler;
328 handler->timeout = NULL;
330 timeout_handler_destroy_source (handler);
334 timeout_handler_dispatch (gpointer data)
336 TimeoutHandler *handler;
340 dbus_timeout_handle (handler->timeout);
346 connection_setup_add_timeout (ConnectionSetup *cs,
347 DBusTimeout *timeout)
349 TimeoutHandler *handler;
351 if (!dbus_timeout_get_enabled (timeout))
354 g_assert (dbus_timeout_get_data (timeout) == NULL);
356 handler = g_new0 (TimeoutHandler, 1);
358 handler->timeout = timeout;
360 handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
361 g_source_set_callback (handler->source, timeout_handler_dispatch, handler,
362 timeout_handler_source_finalized);
363 g_source_attach (handler->source, handler->cs->context);
365 cs->timeouts = g_slist_prepend (cs->timeouts, handler);
367 dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed);
371 connection_setup_remove_timeout (ConnectionSetup *cs,
372 DBusTimeout *timeout)
374 TimeoutHandler *handler;
376 handler = dbus_timeout_get_data (timeout);
381 timeout_handler_destroy_source (handler);
385 connection_setup_free (ConnectionSetup *cs)
388 io_handler_destroy_source (cs->ios->data);
391 timeout_handler_destroy_source (cs->timeouts->data);
393 if (cs->message_queue_source)
397 source = cs->message_queue_source;
398 cs->message_queue_source = NULL;
400 g_source_destroy (source);
401 g_source_unref (source);
404 g_main_context_unref (cs->context);
409 add_watch (DBusWatch *watch,
416 connection_setup_add_watch (cs, watch);
422 remove_watch (DBusWatch *watch,
429 connection_setup_remove_watch (cs, watch);
433 watch_toggled (DBusWatch *watch,
436 /* Because we just exit on OOM, enable/disable is
437 * no different from add/remove
439 if (dbus_watch_get_enabled (watch))
440 add_watch (watch, data);
442 remove_watch (watch, data);
446 add_timeout (DBusTimeout *timeout,
453 if (!dbus_timeout_get_enabled (timeout))
456 connection_setup_add_timeout (cs, timeout);
462 remove_timeout (DBusTimeout *timeout,
469 connection_setup_remove_timeout (cs, timeout);
473 timeout_toggled (DBusTimeout *timeout,
476 /* Because we just exit on OOM, enable/disable is
477 * no different from add/remove
479 if (dbus_timeout_get_enabled (timeout))
480 add_timeout (timeout, data);
482 remove_timeout (timeout, data);
486 wakeup_main (void *data)
488 ConnectionSetup *cs = data;
490 g_main_context_wakeup (cs->context);
494 /* Move to a new context */
495 static ConnectionSetup*
496 connection_setup_new_from_old (GMainContext *context,
497 ConnectionSetup *old)
501 g_assert (old->context != context);
503 cs = connection_setup_new (context, old->connection);
505 while (old->ios != NULL)
507 IOHandler *handler = old->ios->data;
509 connection_setup_add_watch (cs, handler->watch);
510 /* The old handler will be removed from old->ios as a side-effect */
513 while (old->timeouts != NULL)
515 TimeoutHandler *handler = old->timeouts->data;
517 connection_setup_add_timeout (cs, handler->timeout);
523 /** @} */ /* End of GLib bindings internals */
525 /** @addtogroup DBusGLib
530 * atspi_dbus_connection_setup_with_g_main:
531 * @connection: the connection
532 * @context: the #GMainContext or #NULL for default context
534 * Sets the watch and timeout functions of a #DBusConnection
535 * to integrate the connection with the GLib main loop.
536 * Pass in #NULL for the #GMainContext unless you're
537 * doing something specialized.
539 * If called twice for the same context, does nothing the second
540 * time. If called once with context A and once with context B,
541 * context B replaces context A as the context monitoring the
545 atspi_dbus_connection_setup_with_g_main (DBusConnection *connection,
546 GMainContext *context)
548 ConnectionSetup *old_setup;
551 /* FIXME we never free the slot, so its refcount just keeps growing,
552 * which is kind of broken.
554 dbus_connection_allocate_data_slot (&_dbus_gmain_connection_slot);
555 if (_dbus_gmain_connection_slot < 0)
559 context = g_main_context_default ();
563 old_setup = dbus_connection_get_data (connection, _dbus_gmain_connection_slot);
564 if (old_setup != NULL)
566 if (old_setup->context == context)
567 return; /* nothing to do */
569 cs = connection_setup_new_from_old (context, old_setup);
571 /* Nuke the old setup */
572 dbus_connection_set_data (connection, _dbus_gmain_connection_slot, NULL, NULL);
577 cs = connection_setup_new (context, connection);
579 if (!dbus_connection_set_data (connection, _dbus_gmain_connection_slot, cs,
580 (DBusFreeFunction)connection_setup_free))
583 if (!dbus_connection_set_watch_functions (connection,
590 if (!dbus_connection_set_timeout_functions (connection,
597 dbus_connection_set_wakeup_main_function (connection,
604 g_error ("Not enough memory to set up DBusConnection for use with GLib");
608 * atspi_dbus_server_setup_with_g_main:
609 * @server: the server
610 * @context: the #GMainContext or #NULL for default
612 * Sets the watch and timeout functions of a #DBusServer
613 * to integrate the server with the GLib main loop.
614 * In most cases the context argument should be #NULL.
616 * If called twice for the same context, does nothing the second
617 * time. If called once with context A and once with context B,
618 * context B replaces context A as the context monitoring the
622 atspi_dbus_server_setup_with_g_main (DBusServer *server,
623 GMainContext *context)
625 ConnectionSetup *old_setup;
628 /* FIXME we never free the slot, so its refcount just keeps growing,
629 * which is kind of broken.
631 dbus_server_allocate_data_slot (&server_slot);
636 context = g_main_context_default ();
640 old_setup = dbus_server_get_data (server, server_slot);
641 if (old_setup != NULL)
643 if (old_setup->context == context)
644 return; /* nothing to do */
646 cs = connection_setup_new_from_old (context, old_setup);
648 /* Nuke the old setup */
649 if (!dbus_server_set_data (server, server_slot, NULL, NULL))
655 cs = connection_setup_new (context, NULL);
657 if (!dbus_server_set_data (server, server_slot, cs,
658 (DBusFreeFunction)connection_setup_free))
661 if (!dbus_server_set_watch_functions (server,
668 if (!dbus_server_set_timeout_functions (server,
678 g_error ("Not enough memory to set up DBusServer for use with GLib");