ofdbus/dbus-glib/dbus/dbus-gmain.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* -*- mode: C; c-file-style: "gnu" -*- */
       
     2 /* dbus-gmain.c GLib main loop integration
       
     3  *
       
     4  * Copyright (C) 2002, 2003 CodeFactory AB
       
     5  * Copyright (C) 2005 Red Hat, Inc.
       
     6  * Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
       
     7  * Licensed under the Academic Free License version 2.1
       
     8  * 
       
     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.
       
    13  *
       
    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.
       
    18  * 
       
    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    22  *
       
    23  */
       
    24 
       
    25 #ifndef __SYMBIAN32__
       
    26 #include <config.h>
       
    27 #else
       
    28 #include "config.h"
       
    29 #endif //__SYMBIAN32__
       
    30 #include <dbus/dbus-glib.h>
       
    31 #include <dbus/dbus-glib-lowlevel.h>
       
    32 #include "dbus-gtest.h"
       
    33 #include "dbus-gutils.h"
       
    34 #include "dbus-gvalue.h"
       
    35 #include "dbus-gobject.h"
       
    36 #include "dbus-gvalue-utils.h"
       
    37 #include "dbus-gsignature.h"
       
    38 #include <string.h>
       
    39 #ifndef __SYMBIAN32__
       
    40 #include <libintl.h>
       
    41 #define _(x) dgettext (GETTEXT_PACKAGE, x)
       
    42 #define N_(x) x
       
    43 #else
       
    44 
       
    45 #define _(x) x
       
    46 #define N_(x) x
       
    47 #endif
       
    48 
       
    49 #ifdef __SYMBIAN32__
       
    50 #include "libdbus_glib_wsd_solution.h"
       
    51 #endif
       
    52 /**
       
    53  * @defgroup DBusGLibInternals GLib bindings implementation details
       
    54  * @ingroup  DBusInternals
       
    55  * @brief Implementation details of GLib bindings
       
    56  *
       
    57  * @{
       
    58  */
       
    59 
       
    60 /**
       
    61  * DBusGMessageQueue:
       
    62  * A GSource subclass for dispatching DBusConnection messages.
       
    63  * We need this on top of the IO handlers, because sometimes
       
    64  * there are messages to dispatch queued up but no IO pending.
       
    65  */
       
    66 typedef struct
       
    67 {
       
    68   GSource source; /**< the parent GSource */
       
    69   DBusConnection *connection; /**< the connection to dispatch */
       
    70 } DBusGMessageQueue;
       
    71 
       
    72 static gboolean message_queue_prepare  (GSource     *source,
       
    73                                         gint        *timeout);
       
    74 static gboolean message_queue_check    (GSource     *source);
       
    75 static gboolean message_queue_dispatch (GSource     *source,
       
    76                                         GSourceFunc  callback,
       
    77                                         gpointer     user_data);
       
    78 
       
    79 static const GSourceFuncs message_queue_funcs = {
       
    80   message_queue_prepare,
       
    81   message_queue_check,
       
    82   message_queue_dispatch,
       
    83   NULL
       
    84 };
       
    85 
       
    86 static gboolean
       
    87 message_queue_prepare (GSource *source,
       
    88                        gint    *timeout)
       
    89 {
       
    90   DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
       
    91   
       
    92   *timeout = -1;
       
    93 
       
    94   return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);  
       
    95 }
       
    96 
       
    97 static gboolean
       
    98 message_queue_check (GSource *source)
       
    99 {
       
   100   return FALSE;
       
   101 }
       
   102 
       
   103 static gboolean
       
   104 message_queue_dispatch (GSource     *source,
       
   105                         GSourceFunc  callback,
       
   106                         gpointer     user_data)
       
   107 {
       
   108   DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
       
   109 
       
   110   dbus_connection_ref (connection);
       
   111 
       
   112   /* Only dispatch once - we don't want to starve other GSource */
       
   113   dbus_connection_dispatch (connection);
       
   114   
       
   115   dbus_connection_unref (connection);
       
   116 
       
   117   return TRUE;
       
   118 }
       
   119 
       
   120 typedef struct
       
   121 {
       
   122   GMainContext *context;      /**< the main context */
       
   123   GSList *ios;                /**< all IOHandler */
       
   124   GSList *timeouts;           /**< all TimeoutHandler */
       
   125   DBusConnection *connection; /**< NULL if this is really for a server not a connection */
       
   126   GSource *message_queue_source; /**< DBusGMessageQueue */
       
   127 } ConnectionSetup;
       
   128 
       
   129 
       
   130 typedef struct
       
   131 {
       
   132   ConnectionSetup *cs;
       
   133   GSource *source;
       
   134   DBusWatch *watch;
       
   135 } IOHandler;
       
   136 
       
   137 typedef struct
       
   138 {
       
   139   ConnectionSetup *cs;
       
   140   GSource *source;
       
   141   DBusTimeout *timeout;
       
   142 } TimeoutHandler;
       
   143 
       
   144 
       
   145 #if EMULATOR
       
   146 GET_GLOBAL_VAR_FROM_TLS(_dbus_gmain_connection_slot,dbus_gmain,dbus_int32_t)
       
   147 #define _dbus_gmain_connection_slot (*GET_DBUS_WSD_VAR_NAME(_dbus_gmain_connection_slot,dbus_gmain,g)())
       
   148 
       
   149 GET_STATIC_VAR_FROM_TLS(server_slot,dbus_gmain,dbus_int32_t)
       
   150 #define server_slot (*GET_DBUS_WSD_VAR_NAME(server_slot,dbus_gmain,s)())
       
   151 
       
   152 #else
       
   153 
       
   154 dbus_int32_t _dbus_gmain_connection_slot = -1;
       
   155 
       
   156 static dbus_int32_t server_slot = -1;
       
   157 #endif
       
   158 
       
   159 
       
   160 
       
   161 static ConnectionSetup*
       
   162 connection_setup_new (GMainContext   *context,
       
   163                       DBusConnection *connection)
       
   164 {
       
   165   ConnectionSetup *cs;
       
   166 
       
   167   cs = g_new0 (ConnectionSetup, 1);
       
   168 
       
   169   g_assert (context != NULL);
       
   170   
       
   171   cs->context = context;
       
   172   g_main_context_ref (cs->context);  
       
   173 
       
   174   if (connection)
       
   175     {
       
   176       cs->connection = connection;
       
   177 
       
   178       cs->message_queue_source = g_source_new ((GSourceFuncs *) &message_queue_funcs,
       
   179                                                sizeof (DBusGMessageQueue));
       
   180       ((DBusGMessageQueue*)cs->message_queue_source)->connection = connection;
       
   181       g_source_attach (cs->message_queue_source, cs->context);
       
   182     }
       
   183   
       
   184   return cs;
       
   185 }
       
   186 
       
   187 static void
       
   188 io_handler_source_finalized (gpointer data)
       
   189 {
       
   190   IOHandler *handler;
       
   191 
       
   192   handler = data;
       
   193 
       
   194   if (handler->watch)
       
   195     dbus_watch_set_data (handler->watch, NULL, NULL);
       
   196   
       
   197   g_free (handler);
       
   198 }
       
   199 
       
   200 static void
       
   201 io_handler_destroy_source (void *data)
       
   202 {
       
   203   IOHandler *handler;
       
   204 
       
   205   handler = data;
       
   206 
       
   207   if (handler->source)
       
   208     {
       
   209       GSource *source = handler->source;
       
   210       handler->source = NULL;
       
   211       handler->cs->ios = g_slist_remove (handler->cs->ios, handler);
       
   212       g_source_destroy (source);
       
   213       g_source_unref (source);
       
   214     }
       
   215 }
       
   216 
       
   217 static void
       
   218 io_handler_watch_freed (void *data)
       
   219 {
       
   220   IOHandler *handler;
       
   221 
       
   222   handler = data;
       
   223 
       
   224   handler->watch = NULL;
       
   225 
       
   226   io_handler_destroy_source (handler);
       
   227 }
       
   228 
       
   229 static gboolean
       
   230 io_handler_dispatch (GIOChannel   *source,
       
   231                      GIOCondition  condition,
       
   232                      gpointer      data)
       
   233 {
       
   234   IOHandler *handler;
       
   235   guint dbus_condition = 0;
       
   236   DBusConnection *connection;
       
   237 
       
   238   handler = data;
       
   239 
       
   240   connection = handler->cs->connection;
       
   241   
       
   242   if (connection)
       
   243     dbus_connection_ref (connection);
       
   244   
       
   245   if (condition & G_IO_IN)
       
   246     dbus_condition |= DBUS_WATCH_READABLE;
       
   247   if (condition & G_IO_OUT)
       
   248     dbus_condition |= DBUS_WATCH_WRITABLE;
       
   249   if (condition & G_IO_ERR)
       
   250     dbus_condition |= DBUS_WATCH_ERROR;
       
   251   if (condition & G_IO_HUP)
       
   252     dbus_condition |= DBUS_WATCH_HANGUP;
       
   253 
       
   254   /* Note that we don't touch the handler after this, because
       
   255    * dbus may have disabled the watch and thus killed the
       
   256    * handler.
       
   257    */
       
   258   dbus_watch_handle (handler->watch, dbus_condition);
       
   259   handler = NULL;
       
   260 
       
   261   if (connection)
       
   262     dbus_connection_unref (connection);
       
   263   
       
   264   return TRUE;
       
   265 }
       
   266 
       
   267 static void
       
   268 connection_setup_add_watch (ConnectionSetup *cs,
       
   269                             DBusWatch       *watch)
       
   270 {
       
   271   guint flags;
       
   272   GIOCondition condition;
       
   273   GIOChannel *channel;
       
   274   IOHandler *handler;
       
   275   
       
   276   if (!dbus_watch_get_enabled (watch))
       
   277     return;
       
   278   
       
   279   g_assert (dbus_watch_get_data (watch) == NULL);
       
   280   
       
   281   flags = dbus_watch_get_flags (watch);
       
   282 
       
   283   condition = G_IO_ERR | G_IO_HUP;
       
   284   if (flags & DBUS_WATCH_READABLE)
       
   285     condition |= G_IO_IN;
       
   286   if (flags & DBUS_WATCH_WRITABLE)
       
   287     condition |= G_IO_OUT;
       
   288 
       
   289   handler = g_new0 (IOHandler, 1);
       
   290   handler->cs = cs;
       
   291   handler->watch = watch;
       
   292   
       
   293   channel = g_io_channel_unix_new (dbus_watch_get_fd (watch));
       
   294   
       
   295   handler->source = g_io_create_watch (channel, condition);
       
   296   g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler,
       
   297                          io_handler_source_finalized);
       
   298   g_source_attach (handler->source, cs->context);
       
   299 
       
   300   cs->ios = g_slist_prepend (cs->ios, handler);
       
   301   
       
   302   dbus_watch_set_data (watch, handler, io_handler_watch_freed);
       
   303   g_io_channel_unref (channel);
       
   304 }
       
   305 
       
   306 static void
       
   307 connection_setup_remove_watch (ConnectionSetup *cs,
       
   308                                DBusWatch       *watch)
       
   309 {
       
   310   IOHandler *handler;
       
   311 
       
   312   handler = dbus_watch_get_data (watch);
       
   313 
       
   314   if (handler == NULL)
       
   315     return;
       
   316   
       
   317   io_handler_destroy_source (handler);
       
   318 }
       
   319 
       
   320 static void
       
   321 timeout_handler_source_finalized (gpointer data)
       
   322 {
       
   323   TimeoutHandler *handler;
       
   324 
       
   325   handler = data;
       
   326 
       
   327   if (handler->timeout)
       
   328     dbus_timeout_set_data (handler->timeout, NULL, NULL);
       
   329   
       
   330   g_free (handler);
       
   331 }
       
   332 
       
   333 static void
       
   334 timeout_handler_destroy_source (void *data)
       
   335 {
       
   336   TimeoutHandler *handler;
       
   337 
       
   338   handler = data;
       
   339 
       
   340   if (handler->source)
       
   341     {
       
   342       GSource *source = handler->source;
       
   343       handler->source = NULL;
       
   344       handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler);
       
   345       g_source_destroy (source);
       
   346       g_source_unref (source);
       
   347     }
       
   348 }
       
   349 
       
   350 static void
       
   351 timeout_handler_timeout_freed (void *data)
       
   352 {
       
   353   TimeoutHandler *handler;
       
   354 
       
   355   handler = data;
       
   356 
       
   357   handler->timeout = NULL;
       
   358 
       
   359   timeout_handler_destroy_source (handler);
       
   360 }
       
   361 
       
   362 static gboolean
       
   363 timeout_handler_dispatch (gpointer      data)
       
   364 {
       
   365   TimeoutHandler *handler;
       
   366 
       
   367   handler = data;
       
   368 
       
   369   dbus_timeout_handle (handler->timeout);
       
   370   
       
   371   return TRUE;
       
   372 }
       
   373 
       
   374 static void
       
   375 connection_setup_add_timeout (ConnectionSetup *cs,
       
   376                               DBusTimeout     *timeout)
       
   377 {
       
   378   TimeoutHandler *handler;
       
   379   
       
   380   if (!dbus_timeout_get_enabled (timeout))
       
   381     return;
       
   382   
       
   383   g_assert (dbus_timeout_get_data (timeout) == NULL);
       
   384 
       
   385   handler = g_new0 (TimeoutHandler, 1);
       
   386   handler->cs = cs;
       
   387   handler->timeout = timeout;
       
   388 
       
   389   handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
       
   390   g_source_set_callback (handler->source, timeout_handler_dispatch, handler,
       
   391                          timeout_handler_source_finalized);
       
   392   g_source_attach (handler->source, handler->cs->context);
       
   393 
       
   394   cs->timeouts = g_slist_prepend (cs->timeouts, handler);
       
   395 
       
   396   dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed);
       
   397 }
       
   398 
       
   399 static void
       
   400 connection_setup_remove_timeout (ConnectionSetup *cs,
       
   401                                  DBusTimeout       *timeout)
       
   402 {
       
   403   TimeoutHandler *handler;
       
   404   
       
   405   handler = dbus_timeout_get_data (timeout);
       
   406 
       
   407   if (handler == NULL)
       
   408     return;
       
   409   
       
   410   timeout_handler_destroy_source (handler);
       
   411 }
       
   412 
       
   413 static void
       
   414 connection_setup_free (ConnectionSetup *cs)
       
   415 {
       
   416   while (cs->ios)
       
   417     io_handler_destroy_source (cs->ios->data);
       
   418 
       
   419   while (cs->timeouts)
       
   420     timeout_handler_destroy_source (cs->timeouts->data);
       
   421 
       
   422   if (cs->message_queue_source)
       
   423     {
       
   424       GSource *source;
       
   425 
       
   426       source = cs->message_queue_source;
       
   427       cs->message_queue_source = NULL;
       
   428 
       
   429       g_source_destroy (source);
       
   430       g_source_unref (source);
       
   431     }
       
   432   
       
   433   g_main_context_unref (cs->context);
       
   434   g_free (cs);
       
   435 }
       
   436 
       
   437 static dbus_bool_t
       
   438 add_watch (DBusWatch *watch,
       
   439 	   gpointer   data)
       
   440 {
       
   441   ConnectionSetup *cs;
       
   442 
       
   443   cs = data;
       
   444 
       
   445   connection_setup_add_watch (cs, watch);
       
   446   
       
   447   return TRUE;
       
   448 }
       
   449 
       
   450 static void
       
   451 remove_watch (DBusWatch *watch,
       
   452 	      gpointer   data)
       
   453 {
       
   454   ConnectionSetup *cs;
       
   455 
       
   456   cs = data;
       
   457 
       
   458   connection_setup_remove_watch (cs, watch);
       
   459 }
       
   460 
       
   461 static void
       
   462 watch_toggled (DBusWatch *watch,
       
   463                void      *data)
       
   464 {
       
   465   /* Because we just exit on OOM, enable/disable is
       
   466    * no different from add/remove
       
   467    */
       
   468   if (dbus_watch_get_enabled (watch))
       
   469     add_watch (watch, data);
       
   470   else
       
   471     remove_watch (watch, data);
       
   472 }
       
   473 
       
   474 static dbus_bool_t
       
   475 add_timeout (DBusTimeout *timeout,
       
   476 	     void        *data)
       
   477 {
       
   478   ConnectionSetup *cs;
       
   479 
       
   480   cs = data;
       
   481   
       
   482   if (!dbus_timeout_get_enabled (timeout))
       
   483     return TRUE;
       
   484 
       
   485   connection_setup_add_timeout (cs, timeout);
       
   486 
       
   487   return TRUE;
       
   488 }
       
   489 
       
   490 static void
       
   491 remove_timeout (DBusTimeout *timeout,
       
   492 		void        *data)
       
   493 {
       
   494   ConnectionSetup *cs;
       
   495 
       
   496   cs = data;
       
   497 
       
   498   connection_setup_remove_timeout (cs, timeout);
       
   499 }
       
   500 
       
   501 static void
       
   502 timeout_toggled (DBusTimeout *timeout,
       
   503                  void        *data)
       
   504 {
       
   505   /* Because we just exit on OOM, enable/disable is
       
   506    * no different from add/remove
       
   507    */
       
   508   if (dbus_timeout_get_enabled (timeout))
       
   509     add_timeout (timeout, data);
       
   510   else
       
   511     remove_timeout (timeout, data);
       
   512 }
       
   513 
       
   514 static void
       
   515 wakeup_main (void *data)
       
   516 {
       
   517   ConnectionSetup *cs = data;
       
   518 
       
   519   g_main_context_wakeup (cs->context);
       
   520 }
       
   521 
       
   522 
       
   523 /* Move to a new context */
       
   524 static ConnectionSetup*
       
   525 connection_setup_new_from_old (GMainContext    *context,
       
   526                                ConnectionSetup *old)
       
   527 {
       
   528   GSList *tmp;
       
   529   ConnectionSetup *cs;
       
   530 
       
   531   g_assert (old->context != context);
       
   532   
       
   533   cs = connection_setup_new (context, old->connection);
       
   534   
       
   535   tmp = old->ios;
       
   536   while (tmp != NULL)
       
   537     {
       
   538       IOHandler *handler = tmp->data;
       
   539 
       
   540       connection_setup_add_watch (cs, handler->watch);
       
   541       
       
   542       tmp = tmp->next;
       
   543     }
       
   544 
       
   545   tmp = old->timeouts;
       
   546   while (tmp != NULL)
       
   547     {
       
   548       TimeoutHandler *handler = tmp->data;
       
   549 
       
   550       connection_setup_add_timeout (cs, handler->timeout);
       
   551       
       
   552       tmp = tmp->next;
       
   553     }
       
   554 
       
   555   return cs;
       
   556 }
       
   557 
       
   558 /** @} */ /* End of GLib bindings internals */
       
   559 
       
   560 /** @addtogroup DBusGLib
       
   561  * @{
       
   562  */
       
   563 
       
   564 /**
       
   565  * dbus_connection_setup_with_g_main:
       
   566  * @connection: the connection
       
   567  * @context: the #GMainContext or #NULL for default context
       
   568  *
       
   569  * Sets the watch and timeout functions of a #DBusConnection
       
   570  * to integrate the connection with the GLib main loop.
       
   571  * Pass in #NULL for the #GMainContext unless you're
       
   572  * doing something specialized.
       
   573  *
       
   574  * If called twice for the same context, does nothing the second
       
   575  * time. If called once with context A and once with context B,
       
   576  * context B replaces context A as the context monitoring the
       
   577  * connection.
       
   578  */
       
   579  #ifdef __SYMBIAN32__
       
   580 EXPORT_C
       
   581 #endif
       
   582 void
       
   583 dbus_connection_setup_with_g_main (DBusConnection *connection,
       
   584 				   GMainContext   *context)
       
   585 {
       
   586   ConnectionSetup *old_setup;
       
   587   ConnectionSetup *cs;
       
   588   
       
   589   /* FIXME we never free the slot, so its refcount just keeps growing,
       
   590    * which is kind of broken.
       
   591    */
       
   592   dbus_connection_allocate_data_slot (&_dbus_gmain_connection_slot);
       
   593   if (_dbus_gmain_connection_slot < 0)
       
   594     goto nomem;
       
   595 
       
   596   if (context == NULL)
       
   597     context = g_main_context_default ();
       
   598 
       
   599   cs = NULL;
       
   600   
       
   601   old_setup = dbus_connection_get_data (connection, _dbus_gmain_connection_slot);
       
   602   if (old_setup != NULL)
       
   603     {
       
   604       if (old_setup->context == context)
       
   605         return; /* nothing to do */
       
   606 
       
   607       cs = connection_setup_new_from_old (context, old_setup);
       
   608       
       
   609       /* Nuke the old setup */
       
   610       dbus_connection_set_data (connection, _dbus_gmain_connection_slot, NULL, NULL);
       
   611       old_setup = NULL;
       
   612     }
       
   613 
       
   614   if (cs == NULL)
       
   615     cs = connection_setup_new (context, connection);
       
   616 
       
   617   if (!dbus_connection_set_data (connection, _dbus_gmain_connection_slot, cs,
       
   618                                  (DBusFreeFunction)connection_setup_free))
       
   619     goto nomem;
       
   620   
       
   621   if (!dbus_connection_set_watch_functions (connection,
       
   622                                             add_watch,
       
   623                                             remove_watch,
       
   624                                             watch_toggled,
       
   625                                             cs, NULL))
       
   626     goto nomem;
       
   627 
       
   628   if (!dbus_connection_set_timeout_functions (connection,
       
   629                                               add_timeout,
       
   630                                               remove_timeout,
       
   631                                               timeout_toggled,
       
   632                                               cs, NULL))
       
   633     goto nomem;
       
   634     
       
   635   dbus_connection_set_wakeup_main_function (connection,
       
   636 					    wakeup_main,
       
   637 					    cs, NULL);
       
   638       
       
   639   return;
       
   640 
       
   641  nomem:
       
   642   g_error ("Not enough memory to set up DBusConnection for use with GLib");
       
   643 }
       
   644 
       
   645 /**
       
   646  * dbus_server_setup_with_g_main:
       
   647  * @server: the server
       
   648  * @context: the #GMainContext or #NULL for default
       
   649  *
       
   650  * Sets the watch and timeout functions of a #DBusServer
       
   651  * to integrate the server with the GLib main loop.
       
   652  * In most cases the context argument should be #NULL.
       
   653  *
       
   654  * If called twice for the same context, does nothing the second
       
   655  * time. If called once with context A and once with context B,
       
   656  * context B replaces context A as the context monitoring the
       
   657  * connection.
       
   658  */
       
   659  	#ifdef __SYMBIAN32__
       
   660 	EXPORT_C
       
   661 	#endif
       
   662 void
       
   663 dbus_server_setup_with_g_main (DBusServer   *server,
       
   664                                GMainContext *context)
       
   665 {
       
   666   ConnectionSetup *old_setup;
       
   667   ConnectionSetup *cs;
       
   668   
       
   669   /* FIXME we never free the slot, so its refcount just keeps growing,
       
   670    * which is kind of broken.
       
   671    */
       
   672   dbus_server_allocate_data_slot (&server_slot);
       
   673   if (server_slot < 0)
       
   674     goto nomem;
       
   675 
       
   676   if (context == NULL)
       
   677     context = g_main_context_default ();
       
   678 
       
   679   cs = NULL;
       
   680   
       
   681   old_setup = dbus_server_get_data (server, server_slot);
       
   682   if (old_setup != NULL)
       
   683     {
       
   684       if (old_setup->context == context)
       
   685         return; /* nothing to do */
       
   686 
       
   687       cs = connection_setup_new_from_old (context, old_setup);
       
   688       
       
   689       /* Nuke the old setup */
       
   690       dbus_server_set_data (server, server_slot, NULL, NULL);
       
   691       old_setup = NULL;
       
   692     }
       
   693 
       
   694   if (cs == NULL)
       
   695     cs = connection_setup_new (context, NULL);
       
   696 
       
   697   if (!dbus_server_set_data (server, server_slot, cs,
       
   698                              (DBusFreeFunction)connection_setup_free))
       
   699     goto nomem;
       
   700   
       
   701   if (!dbus_server_set_watch_functions (server,
       
   702                                         add_watch,
       
   703                                         remove_watch,
       
   704                                         watch_toggled,
       
   705                                         cs, NULL))
       
   706     goto nomem;
       
   707 
       
   708   if (!dbus_server_set_timeout_functions (server,
       
   709                                           add_timeout,
       
   710                                           remove_timeout,
       
   711                                           timeout_toggled,
       
   712                                           cs, NULL))
       
   713     goto nomem;
       
   714       
       
   715   return;
       
   716 
       
   717  nomem:
       
   718   g_error ("Not enough memory to set up DBusServer for use with GLib");
       
   719 }
       
   720 
       
   721 /**
       
   722  * dbus_g_connection_open:
       
   723  * @address: address of the connection to open
       
   724  * @error: address where an error can be returned.
       
   725  *
       
   726  * Returns a connection to the given address.
       
   727  *
       
   728  * (Internally, calls dbus_connection_open() then calls
       
   729  * dbus_connection_setup_with_g_main() on the result.)
       
   730  *
       
   731  * Returns: a DBusConnection
       
   732  */
       
   733  	#ifdef __SYMBIAN32__
       
   734 	EXPORT_C
       
   735 	#endif
       
   736 DBusGConnection*
       
   737 dbus_g_connection_open (const gchar  *address,
       
   738                         GError      **error)
       
   739 {
       
   740   DBusConnection *connection;
       
   741   DBusError derror;
       
   742 
       
   743   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
       
   744 
       
   745   _dbus_g_value_types_init ();
       
   746 
       
   747   dbus_error_init (&derror);
       
   748 
       
   749   connection = dbus_connection_open (address, &derror);
       
   750   if (connection == NULL)
       
   751     {
       
   752       dbus_set_g_error (error, &derror);
       
   753       dbus_error_free (&derror);
       
   754       return NULL;
       
   755     }
       
   756 
       
   757   /* does nothing if it's already been done */
       
   758   dbus_connection_setup_with_g_main (connection, NULL);
       
   759 
       
   760   return DBUS_G_CONNECTION_FROM_CONNECTION (connection);
       
   761 }
       
   762 
       
   763 /**
       
   764  * dbus_g_bus_get:
       
   765  * @type: bus type
       
   766  * @error: address where an error can be returned.
       
   767  *
       
   768  * Returns a connection to the given bus. The connection is a global variable
       
   769  * shared with other callers of this function.
       
   770  * 
       
   771  * (Internally, calls dbus_bus_get() then calls
       
   772  * dbus_connection_setup_with_g_main() on the result.)
       
   773  *
       
   774  * Returns: a DBusConnection
       
   775  */
       
   776  #ifdef __SYMBIAN32__
       
   777 EXPORT_C
       
   778 #endif
       
   779 DBusGConnection*
       
   780 dbus_g_bus_get (DBusBusType     type,
       
   781                 GError        **error)
       
   782 {
       
   783   DBusConnection *connection;
       
   784   DBusError derror;
       
   785 
       
   786   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
       
   787 
       
   788   _dbus_g_value_types_init ();
       
   789   
       
   790   dbus_error_init (&derror);
       
   791 
       
   792   connection = dbus_bus_get (type, &derror);
       
   793   if (connection == NULL)
       
   794     {
       
   795       dbus_set_g_error (error, &derror);
       
   796       dbus_error_free (&derror);
       
   797       return NULL;
       
   798     }
       
   799 
       
   800   /* does nothing if it's already been done */
       
   801   dbus_connection_setup_with_g_main (connection, NULL);
       
   802 
       
   803   return DBUS_G_CONNECTION_FROM_CONNECTION (connection);
       
   804 }
       
   805 
       
   806 /** @} */ /* end of public API */
       
   807 
       
   808 #ifdef DBUS_BUILD_TESTS
       
   809 
       
   810 /**
       
   811  * @ingroup DBusGLibInternals
       
   812  * Unit test for GLib main loop integration
       
   813  * Returns: #TRUE on success.
       
   814  */
       
   815   	#ifdef __SYMBIAN32__
       
   816 	EXPORT_C
       
   817 	#endif
       
   818 gboolean
       
   819 _dbus_gmain_test (const char *test_data_dir)
       
   820 {
       
   821   GType type;
       
   822   GType rectype;
       
   823 
       
   824   g_type_init ();
       
   825   _dbus_g_value_types_init ();
       
   826 
       
   827   rectype = dbus_g_type_get_collection ("GArray", G_TYPE_UINT);
       
   828   g_assert (rectype != G_TYPE_INVALID);
       
   829   g_assert (!strcmp (g_type_name (rectype), "GArray_guint_"));
       
   830 
       
   831   type = _dbus_gtype_from_signature ("au", TRUE);
       
   832   g_assert (type == rectype);
       
   833 
       
   834   rectype = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING);
       
   835   g_assert (rectype != G_TYPE_INVALID);
       
   836   g_assert (!strcmp (g_type_name (rectype), "GHashTable_gchararray+gchararray_"));
       
   837 
       
   838   type = _dbus_gtype_from_signature ("a{ss}", TRUE);
       
   839   g_assert (type == rectype);
       
   840 
       
   841   type = _dbus_gtype_from_signature ("o", FALSE);
       
   842   g_assert (type == DBUS_TYPE_G_OBJECT_PATH);
       
   843   type = _dbus_gtype_from_signature ("o", TRUE);
       
   844   g_assert (type == DBUS_TYPE_G_OBJECT_PATH);
       
   845   
       
   846   return TRUE;
       
   847 }
       
   848 
       
   849 #endif /* DBUS_BUILD_TESTS */