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.1 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)
38 * A GSource subclass for dispatching DBusConnection messages.
39 * We need this on top of the IO handlers, because sometimes
40 * there are messages to dispatch queued up but no IO pending.
44 GSource source; /* the parent GSource */
45 DBusConnection *connection; /* the connection to dispatch */
48 static gboolean message_queue_prepare (GSource *source,
50 static gboolean message_queue_check (GSource *source);
51 static gboolean message_queue_dispatch (GSource *source,
55 static const GSourceFuncs message_queue_funcs = {
56 message_queue_prepare,
58 message_queue_dispatch,
63 message_queue_prepare (GSource *source,
66 DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
70 return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
74 message_queue_check (GSource *source)
80 message_queue_dispatch (GSource *source,
84 DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
86 dbus_connection_ref (connection);
88 /* Only dispatch once - we don't want to starve other GSource */
89 dbus_connection_dispatch (connection);
91 dbus_connection_unref (connection);
98 GMainContext *context; /* the main context */
99 GSList *ios; /* all IOHandler */
100 GSList *timeouts; /* all TimeoutHandler */
101 DBusConnection *connection; /* NULL if this is really for a server not a connection */
102 GSource *message_queue_source; /* DBusGMessageQueue */
117 DBusTimeout *timeout;
120 dbus_int32_t _dbus_gmain_connection_slot = -1;
121 static dbus_int32_t server_slot = -1;
123 static ConnectionSetup*
124 connection_setup_new (GMainContext *context,
125 DBusConnection *connection)
129 cs = g_new0 (ConnectionSetup, 1);
131 g_assert (context != NULL);
133 cs->context = context;
134 g_main_context_ref (cs->context);
138 cs->connection = connection;
140 cs->message_queue_source = g_source_new ((GSourceFuncs *) &message_queue_funcs,
141 sizeof (DBusGMessageQueue));
143 g_assert (cs->message_queue_source != NULL);
145 ((DBusGMessageQueue*)cs->message_queue_source)->connection = connection;
146 g_source_attach (cs->message_queue_source, cs->context);
153 io_handler_source_finalized (gpointer data)
160 dbus_watch_set_data (handler->watch, NULL, NULL);
166 io_handler_destroy_source (void *data)
174 GSource *source = handler->source;
175 handler->source = NULL;
176 handler->cs->ios = g_slist_remove (handler->cs->ios, handler);
177 g_source_destroy (source);
178 g_source_unref (source);
183 io_handler_watch_freed (void *data)
189 handler->watch = NULL;
191 io_handler_destroy_source (handler);
195 io_handler_dispatch (GIOChannel *source,
196 GIOCondition condition,
200 guint dbus_condition = 0;
201 DBusConnection *connection;
205 connection = handler->cs->connection;
208 dbus_connection_ref (connection);
210 if (condition & G_IO_IN)
211 dbus_condition |= DBUS_WATCH_READABLE;
212 if (condition & G_IO_OUT)
213 dbus_condition |= DBUS_WATCH_WRITABLE;
214 if (condition & G_IO_ERR)
215 dbus_condition |= DBUS_WATCH_ERROR;
216 if (condition & G_IO_HUP)
217 dbus_condition |= DBUS_WATCH_HANGUP;
219 /* Note that we don't touch the handler after this, because
220 * dbus may have disabled the watch and thus killed the
223 dbus_watch_handle (handler->watch, dbus_condition);
227 dbus_connection_unref (connection);
232 /* Attach the connection setup to the given watch, removing any
233 * previously-attached connection setup.
236 connection_setup_add_watch (ConnectionSetup *cs,
240 GIOCondition condition;
244 if (!dbus_watch_get_enabled (watch))
247 flags = dbus_watch_get_flags (watch);
249 condition = G_IO_ERR | G_IO_HUP;
250 if (flags & DBUS_WATCH_READABLE)
251 condition |= G_IO_IN;
252 if (flags & DBUS_WATCH_WRITABLE)
253 condition |= G_IO_OUT;
255 handler = g_new0 (IOHandler, 1);
257 handler->watch = watch;
259 channel = g_io_channel_unix_new (dbus_watch_get_unix_fd (watch));
261 handler->source = g_io_create_watch (channel, condition);
262 g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler,
263 io_handler_source_finalized);
264 g_source_attach (handler->source, cs->context);
266 cs->ios = g_slist_prepend (cs->ios, handler);
268 dbus_watch_set_data (watch, handler, io_handler_watch_freed);
269 g_io_channel_unref (channel);
273 connection_setup_remove_watch (ConnectionSetup *cs,
278 handler = dbus_watch_get_data (watch);
280 if (handler == NULL || handler->cs != cs)
283 io_handler_destroy_source (handler);
287 timeout_handler_source_finalized (gpointer data)
289 TimeoutHandler *handler;
293 if (handler->timeout)
294 dbus_timeout_set_data (handler->timeout, NULL, NULL);
300 timeout_handler_destroy_source (void *data)
302 TimeoutHandler *handler;
308 GSource *source = handler->source;
309 handler->source = NULL;
310 handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler);
311 g_source_destroy (source);
312 g_source_unref (source);
317 timeout_handler_timeout_freed (void *data)
319 TimeoutHandler *handler;
323 handler->timeout = NULL;
325 timeout_handler_destroy_source (handler);
329 timeout_handler_dispatch (gpointer data)
331 TimeoutHandler *handler;
335 dbus_timeout_handle (handler->timeout);
341 connection_setup_add_timeout (ConnectionSetup *cs,
342 DBusTimeout *timeout)
344 TimeoutHandler *handler;
346 if (!dbus_timeout_get_enabled (timeout))
349 handler = g_new0 (TimeoutHandler, 1);
351 handler->timeout = timeout;
353 handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
354 g_source_set_callback (handler->source, timeout_handler_dispatch, handler,
355 timeout_handler_source_finalized);
356 g_source_attach (handler->source, handler->cs->context);
358 cs->timeouts = g_slist_prepend (cs->timeouts, handler);
360 dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed);
364 connection_setup_remove_timeout (ConnectionSetup *cs,
365 DBusTimeout *timeout)
367 TimeoutHandler *handler;
369 handler = dbus_timeout_get_data (timeout);
374 timeout_handler_destroy_source (handler);
378 connection_setup_free (ConnectionSetup *cs)
381 io_handler_destroy_source (cs->ios->data);
384 timeout_handler_destroy_source (cs->timeouts->data);
386 if (cs->message_queue_source)
390 source = cs->message_queue_source;
391 cs->message_queue_source = NULL;
393 g_source_destroy (source);
394 g_source_unref (source);
397 g_main_context_unref (cs->context);
402 add_watch (DBusWatch *watch,
409 connection_setup_add_watch (cs, watch);
415 remove_watch (DBusWatch *watch,
422 connection_setup_remove_watch (cs, watch);
426 watch_toggled (DBusWatch *watch,
429 /* Because we just exit on OOM, enable/disable is
430 * no different from add/remove
432 if (dbus_watch_get_enabled (watch))
433 add_watch (watch, data);
435 remove_watch (watch, data);
439 add_timeout (DBusTimeout *timeout,
446 if (!dbus_timeout_get_enabled (timeout))
449 connection_setup_add_timeout (cs, timeout);
455 remove_timeout (DBusTimeout *timeout,
462 connection_setup_remove_timeout (cs, timeout);
466 timeout_toggled (DBusTimeout *timeout,
469 /* Because we just exit on OOM, enable/disable is
470 * no different from add/remove
472 if (dbus_timeout_get_enabled (timeout))
473 add_timeout (timeout, data);
475 remove_timeout (timeout, data);
479 wakeup_main (void *data)
481 ConnectionSetup *cs = data;
483 g_main_context_wakeup (cs->context);
487 /* Move to a new context */
488 static ConnectionSetup*
489 connection_setup_new_from_old (GMainContext *context,
490 ConnectionSetup *old)
494 g_assert (old->context != context);
496 cs = connection_setup_new (context, old->connection);
498 while (old->ios != NULL)
500 IOHandler *handler = old->ios->data;
502 connection_setup_add_watch (cs, handler->watch);
503 /* The old handler will be removed from old->ios as a side-effect */
506 while (old->timeouts != NULL)
508 TimeoutHandler *handler = old->timeouts->data;
510 connection_setup_add_timeout (cs, handler->timeout);
516 /* @} */ /* End of GLib bindings internals */
519 * atspi_dbus_connection_setup_with_g_main: (skip)
520 * @connection: the connection
521 * @context: the #GMainContext or #NULL for default context
523 * Sets the watch and timeout functions of a #DBusConnection
524 * to integrate the connection with the GLib main loop.
525 * Pass in #NULL for the #GMainContext unless you're
526 * doing something specialized.
528 * If called twice for the same context, does nothing the second
529 * time. If called once with context A and once with context B,
530 * context B replaces context A as the context monitoring the
534 atspi_dbus_connection_setup_with_g_main (DBusConnection *connection,
535 GMainContext *context)
537 ConnectionSetup *old_setup;
540 /* FIXME we never free the slot, so its refcount just keeps growing,
541 * which is kind of broken.
543 dbus_connection_allocate_data_slot (&_dbus_gmain_connection_slot);
544 if (_dbus_gmain_connection_slot < 0)
548 context = g_main_context_default ();
552 old_setup = dbus_connection_get_data (connection, _dbus_gmain_connection_slot);
553 if (old_setup != NULL)
555 if (old_setup->context == context)
556 return; /* nothing to do */
558 cs = connection_setup_new_from_old (context, old_setup);
560 /* Nuke the old setup */
561 dbus_connection_set_data (connection, _dbus_gmain_connection_slot, NULL, NULL);
566 cs = connection_setup_new (context, connection);
568 if (!dbus_connection_set_data (connection, _dbus_gmain_connection_slot, cs,
569 (DBusFreeFunction)connection_setup_free))
572 if (!dbus_connection_set_watch_functions (connection,
579 if (!dbus_connection_set_timeout_functions (connection,
586 dbus_connection_set_wakeup_main_function (connection,
593 g_error ("Not enough memory to set up DBusConnection for use with GLib");
597 * atspi_dbus_server_setup_with_g_main: (skip)
598 * @server: the server
599 * @context: the #GMainContext or #NULL for default
601 * Sets the watch and timeout functions of a #DBusServer
602 * to integrate the server with the GLib main loop.
603 * In most cases the context argument should be #NULL.
605 * If called twice for the same context, does nothing the second
606 * time. If called once with context A and once with context B,
607 * context B replaces context A as the context monitoring the
611 atspi_dbus_server_setup_with_g_main (DBusServer *server,
612 GMainContext *context)
614 ConnectionSetup *old_setup;
617 /* FIXME we never free the slot, so its refcount just keeps growing,
618 * which is kind of broken.
620 dbus_server_allocate_data_slot (&server_slot);
625 context = g_main_context_default ();
629 old_setup = dbus_server_get_data (server, server_slot);
630 if (old_setup != NULL)
632 if (old_setup->context == context)
633 return; /* nothing to do */
635 cs = connection_setup_new_from_old (context, old_setup);
637 /* Nuke the old setup */
638 if (!dbus_server_set_data (server, server_slot, NULL, NULL))
644 cs = connection_setup_new (context, NULL);
646 if (!dbus_server_set_data (server, server_slot, cs,
647 (DBusFreeFunction)connection_setup_free))
650 if (!dbus_server_set_watch_functions (server,
657 if (!dbus_server_set_timeout_functions (server,
667 g_error ("Not enough memory to set up DBusServer for use with GLib");