libtelepathy/src/tp-conn.c
changeset 10 59927b2d3b75
parent 0 d0f3a028347a
equal deleted inserted replaced
0:d0f3a028347a 10:59927b2d3b75
     1 /* tp-conn.c
       
     2  *
       
     3  * Copyright (C) 2005 Collabora Ltd.
       
     4  * 
       
     5  *
       
     6  * This library is free software; you can redistribute it and/or
       
     7  * modify it under the terms of the GNU Lesser General Public
       
     8  * License as published by the Free Software Foundation; either
       
     9  * version 2.1 of the License, or (at your option) any later version.
       
    10  *
       
    11  * This library is distributed in the hope that it will be useful,
       
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
       
    14  * Lesser General Public License for more details.
       
    15  *
       
    16  * You should have received a copy of the GNU Lesser General Public
       
    17  * License along with this library; if not, write to the Free Software
       
    18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
       
    19  *
       
    20  */
       
    21 
       
    22 #include <string.h>
       
    23 #include "tp-conn.h"
       
    24 #include "tp-helpers.h"
       
    25 #include "tp-connmgr.h"
       
    26 #include "tp-props-iface.h"
       
    27 
       
    28 
       
    29 
       
    30 #ifdef EMULATOR
       
    31 #include "libtelepathy_wsd_solution.h"
       
    32 #endif
       
    33 
       
    34 #ifdef EMULATOR
       
    35 	
       
    36 	GET_STATIC_VAR_FROM_TLS(parent_class,tp_conn,GObjectClass *)
       
    37 	#define parent_class (*GET_WSD_VAR_NAME(parent_class,tp_conn,s)())
       
    38 	
       
    39 	GET_STATIC_VAR_FROM_TLS(type1,tp_conn,GType)
       
    40 	#define type1 (*GET_WSD_VAR_NAME(type1,tp_conn,s)())
       
    41 	
       
    42 	GET_STATIC_VAR_FROM_TLS(ret1,tp_conn,GQuark)
       
    43 	#define ret1 (*GET_WSD_VAR_NAME(ret1,tp_conn,s)())
       
    44 	
       
    45 	GET_STATIC_VAR_FROM_TLS(ret2,tp_conn,GQuark)
       
    46 	#define ret2 (*GET_WSD_VAR_NAME(ret2,tp_conn,s)())
       
    47 	
       
    48 	GET_STATIC_VAR_FROM_TLS(ret3,tp_conn,GQuark)
       
    49 	#define ret3 (*GET_WSD_VAR_NAME(ret3,tp_conn,s)())
       
    50 	
       
    51 	GET_STATIC_VAR_FROM_TLS(ret4,tp_conn,GQuark)
       
    52 	#define ret4 (*GET_WSD_VAR_NAME(ret4,tp_conn,s)())
       
    53 	
       
    54 	GET_STATIC_VAR_FROM_TLS(ret5,tp_conn,GQuark)
       
    55 	#define ret5 (*GET_WSD_VAR_NAME(ret5,tp_conn,s)())
       
    56 	
       
    57 	GET_STATIC_VAR_FROM_TLS(ret6,tp_conn,GQuark)
       
    58 	#define ret6 (*GET_WSD_VAR_NAME(ret6,tp_conn,s)())
       
    59 	
       
    60 	GET_STATIC_VAR_FROM_TLS(ret7,tp_conn,GQuark)
       
    61 	#define ret7 (*GET_WSD_VAR_NAME(ret7,tp_conn,s)())
       
    62 	
       
    63 	GET_STATIC_VAR_FROM_TLS(ret8,tp_conn,GQuark)
       
    64 	#define ret8 (*GET_WSD_VAR_NAME(ret8,tp_conn,s)())
       
    65 	
       
    66 	GET_STATIC_VAR_FROM_TLS(ret9,tp_conn,GQuark)
       
    67     #define ret9 (*GET_WSD_VAR_NAME(ret9,tp_conn,s)())
       
    68 	
       
    69 #else
       
    70 	static GObjectClass *parent_class = NULL;
       
    71 #endif
       
    72 
       
    73 
       
    74 
       
    75 static gboolean tp_conn_status_change_handler(DBusGProxy *proxy, 
       
    76  					      guint status, guint reason, 
       
    77  					      gpointer user_data); 
       
    78 
       
    79 static void _tp_conn_connect_req_handler(DBusGProxy *proxy,
       
    80                                         GError *error, gpointer user_data);
       
    81 
       
    82 static void _tp_conn_register_signal_marshallers()
       
    83 {
       
    84   /* Register marshaller for NewChannel signal */
       
    85   dbus_g_object_register_marshaller(tp_conn_signals_marshal_VOID__OBJECT_STRING_UINT_UINT_BOOLEAN, G_TYPE_NONE, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_BOOLEAN, G_TYPE_INVALID);
       
    86   /* Register marshaller for StatusChanged signal */
       
    87   dbus_g_object_register_marshaller(tp_conn_signals_marshal_VOID__UINT_UINT, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID);
       
    88 }
       
    89 
       
    90 static void _tp_conn_register_interface_signal_marshallers()
       
    91 {
       
    92   /* Register marshaller for Aliasing interface signal AliasUpdate and
       
    93      ContactInfo interface signal GotContactInfo*/
       
    94   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT_STRING, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
       
    95   /* Register marshaller for Forwarding interface signal ForwardingChanged */
       
    96   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_INVALID);
       
    97   /* Register marshaller for Presence interface signal PresenceUpdate */
       
    98   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__BOXED, G_TYPE_NONE, G_TYPE_BOXED, G_TYPE_INVALID);
       
    99   /* Register marshaller for Privacy interface signal PrivacyModeChanged */
       
   100   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__STRING, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_INVALID);
       
   101   /* Register marshaller for Renaming interface signal Renamed */
       
   102   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT_UINT, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID);
       
   103 }
       
   104 
       
   105 
       
   106 /* We initialize the list of signatures here, so that we can use
       
   107  * it to add them for new interface instances later.
       
   108  */
       
   109 
       
   110 /* FIXME: This should be replaced by a more automatic way of doing
       
   111  * this. The reason for using a set of function pointers is that there is no
       
   112  * apparent cleaner way of doing this, unless DBusGProxy gains a non-varargs
       
   113  * version of dbus_g_proxy_add_signal...
       
   114  */
       
   115 
       
   116 static void _tp_conn_init_interface_signal_signatures(GData **signal_sigs)
       
   117 {
       
   118   g_datalist_init(signal_sigs);
       
   119 
       
   120   /* Create and store aliasing iface signal signatures */
       
   121   g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_ALIASING_QUARK,
       
   122 			 (gpointer)&tp_conn_set_aliasing_signatures);
       
   123   /* Create and store capabilities iface signal signatures */
       
   124   g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_CAPABILITIES_QUARK,
       
   125 			 (gpointer)&tp_conn_set_capabilities_signatures);
       
   126   /* Create and store contactinfo iface signal signatures */
       
   127   g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_CONTACTINFO_QUARK,
       
   128 			 (gpointer)&tp_conn_set_contactinfo_signatures);
       
   129   /* Create and store forwarding iface signal signatures */
       
   130   g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_FORWARDING_QUARK,
       
   131 			 (gpointer)&tp_conn_set_forwarding_signatures);
       
   132   /* Create and store presence iface signal signatures */
       
   133   g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_PRESENCE_QUARK,
       
   134 			 (gpointer)&tp_conn_set_presence_signatures);
       
   135   /* Create and store privacy iface signal signatures */
       
   136   g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_PRIVACY_QUARK,
       
   137 			 (gpointer)&tp_conn_set_privacy_signatures);
       
   138   /* Create and store renaming iface signal signatures */
       
   139   g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_RENAMING_QUARK,
       
   140 			 (gpointer)&tp_conn_set_renaming_signatures);
       
   141   g_datalist_id_set_data(signal_sigs, TELEPATHY_CONN_IFACE_AVATAR_QUARK,
       
   142                (gpointer)&tp_conn_set_avatar_signatures);
       
   143 }
       
   144 
       
   145 static void synthesize_status_changed(TpConn *conn);
       
   146 
       
   147 static void tp_conn_init(GTypeInstance *instance, gpointer g_class)
       
   148 {
       
   149   TpConn *self = TELEPATHY_CONN(instance);
       
   150 
       
   151   self->first_run = TRUE;
       
   152 }
       
   153 
       
   154 
       
   155 static void tp_conn_dispose(GObject *obj)
       
   156 {
       
   157   TpConn *self = TELEPATHY_CONN(obj);
       
   158       
       
   159   if (self->first_run == TRUE)
       
   160   {
       
   161     self->first_run = FALSE;
       
   162     synthesize_status_changed(self);
       
   163     g_datalist_clear(&(self->interface_list));
       
   164   }
       
   165   
       
   166   /* Call parent class dispose method */
       
   167   if (G_OBJECT_CLASS(parent_class)->dispose)
       
   168   {
       
   169     G_OBJECT_CLASS(parent_class)->dispose(obj);
       
   170   }
       
   171 
       
   172 }
       
   173 
       
   174 
       
   175 static void tp_conn_finalize(GObject *obj)
       
   176 {
       
   177   if (G_OBJECT_CLASS(parent_class)->finalize)
       
   178     {
       
   179       G_OBJECT_CLASS(parent_class)->finalize(obj);
       
   180     }
       
   181 
       
   182 }
       
   183 
       
   184 
       
   185 static void tp_conn_class_init(TpConnClass *klass)
       
   186 {
       
   187   GObjectClass *obj = G_OBJECT_CLASS(klass);
       
   188   parent_class = g_type_class_peek_parent(klass);
       
   189 
       
   190   obj->set_property = parent_class->set_property;
       
   191   obj->get_property = parent_class->get_property;
       
   192 
       
   193   obj->dispose = tp_conn_dispose;
       
   194   obj->finalize = tp_conn_finalize;
       
   195   _tp_conn_register_signal_marshallers();
       
   196   _tp_conn_register_interface_signal_marshallers();
       
   197   _tp_conn_init_interface_signal_signatures(&(klass->iface_signal_sigs));
       
   198 }
       
   199 
       
   200 #ifdef SYMBIAN
       
   201 EXPORT_C
       
   202 #endif
       
   203 GType tp_conn_get_type(void)
       
   204 {
       
   205 #ifndef EMULATOR
       
   206   static GType type1 = 0;
       
   207 #endif
       
   208   
       
   209   if (type1 == 0)
       
   210     {
       
   211       static const GTypeInfo info = 
       
   212 	{
       
   213 	  sizeof(TpConnClass),
       
   214 	  NULL,
       
   215 	  NULL,
       
   216 	  (GClassInitFunc)tp_conn_class_init,
       
   217 	  NULL,
       
   218 	  NULL,
       
   219 	  sizeof(TpConn),
       
   220 	  0,
       
   221 	  (GInstanceInitFunc)tp_conn_init
       
   222 	  
       
   223 	};
       
   224       type1 = g_type_register_static(DBUS_TYPE_G_PROXY,
       
   225 				    "TpConn", &info, 0);
       
   226     }
       
   227   return type1;
       
   228 }
       
   229 
       
   230 /* The interface name getters */
       
   231 
       
   232 GQuark tp_get_conn_interface()
       
   233 {
       
   234 #ifndef EMULATOR
       
   235   static GQuark ret1 = 0;
       
   236 #endif
       
   237 
       
   238   if (ret1 == 0)
       
   239   {
       
   240     /* FIXME: The naming conventions should be unified */
       
   241     ret1 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE);
       
   242   }
       
   243 
       
   244   return ret1;
       
   245 }
       
   246 
       
   247 GQuark tp_get_conn_aliasing_interface()
       
   248 {
       
   249 #ifndef EMULATOR
       
   250   static GQuark ret2 = 0;
       
   251 #endif
       
   252 
       
   253   if (ret2 == 0)
       
   254   {
       
   255     ret2 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_ALIASING);
       
   256   }
       
   257 
       
   258   return ret2;
       
   259 }
       
   260 
       
   261 GQuark tp_get_conn_capabilities_interface()
       
   262 {
       
   263 #ifndef EMULATOR
       
   264   static GQuark ret3 = 0;
       
   265 #endif
       
   266 
       
   267   if (ret3 == 0)
       
   268   {
       
   269     ret3 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_CAPABILITIES);
       
   270   }
       
   271 
       
   272   return ret3;
       
   273 }
       
   274 
       
   275 GQuark tp_get_conn_contactinfo_interface()
       
   276 {
       
   277 #ifndef EMULATOR
       
   278   static GQuark ret4 = 0;
       
   279 #endif
       
   280 
       
   281   if (ret4 == 0)
       
   282   {
       
   283     ret4 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_CONTACT_INFO);
       
   284   }
       
   285 
       
   286   return ret4;
       
   287 }
       
   288 
       
   289 GQuark tp_get_conn_forwarding_interface()
       
   290 {
       
   291 #ifndef EMULATOR
       
   292   static GQuark ret5 = 0;
       
   293 #endif
       
   294 
       
   295   if (ret5 == 0)
       
   296   {
       
   297     ret5 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_FORWARDING);
       
   298   }
       
   299 
       
   300   return ret5;
       
   301 }
       
   302 
       
   303 #ifdef SYMBIAN
       
   304 EXPORT_C
       
   305 #endif
       
   306 GQuark tp_get_conn_presence_interface()
       
   307 {
       
   308 #ifndef EMULATOR
       
   309   static GQuark ret6 = 0;
       
   310 #endif
       
   311 
       
   312   if (ret6 == 0)
       
   313   {
       
   314     ret6 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_PRESENCE);
       
   315   }
       
   316 
       
   317   return ret6;
       
   318 }
       
   319 
       
   320 
       
   321 GQuark tp_get_conn_privacy_interface()
       
   322 {
       
   323 #ifndef EMULATOR
       
   324   static GQuark ret7 = 0;
       
   325 #endif
       
   326 
       
   327   if (ret7 == 0)
       
   328   {
       
   329     ret7 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_PRIVACY);
       
   330   }
       
   331 
       
   332   return ret7;
       
   333 }
       
   334 
       
   335 
       
   336 
       
   337 GQuark tp_get_conn_renaming_interface()
       
   338 {
       
   339 #ifndef EMULATOR
       
   340   static GQuark ret8 = 0;
       
   341 #endif
       
   342 
       
   343   if (ret8 == 0)
       
   344   {
       
   345     ret8 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_RENAMING);
       
   346   }
       
   347 
       
   348   return ret8;
       
   349 }
       
   350 
       
   351 #ifdef SYMBIAN
       
   352 EXPORT_C 
       
   353 #endif
       
   354 GQuark tp_get_conn_avatar_interface(void)
       
   355     {
       
   356 #ifndef EMULATOR
       
   357   static GQuark ret9 = 0;
       
   358 #endif
       
   359 
       
   360   if (ret9 == 0)
       
   361   {
       
   362     ret9 = g_quark_from_static_string(TP_IFACE_CONN_INTERFACE_AVATAR);
       
   363   }
       
   364 
       
   365   return ret9;    
       
   366     }
       
   367 
       
   368 TpConn *
       
   369 tp_conn_new_without_connect (DBusGConnection *connection,
       
   370                              const gchar *bus_name,
       
   371                              const gchar *object_path,
       
   372                              guint *status,
       
   373                              GError **error)
       
   374 {
       
   375   gchar *unique_name;
       
   376   gchar **interfaces;
       
   377   guint conn_status = TP_CONN_STATUS_DISCONNECTED;
       
   378   TpConn *obj;
       
   379   GError *err = NULL;
       
   380 
       
   381   g_return_val_if_fail (connection != NULL, NULL);
       
   382   g_return_val_if_fail (bus_name != NULL, NULL);
       
   383   g_return_val_if_fail (object_path, NULL);
       
   384 
       
   385   /* Create the proxy object for this connection. It will be used to
       
   386      perform the actual method calls over D-BUS. */
       
   387 
       
   388   if (!dbus_g_proxy_call (tp_get_bus_proxy (), "GetNameOwner", error,
       
   389         G_TYPE_STRING, bus_name, G_TYPE_INVALID,
       
   390         G_TYPE_STRING, &unique_name, G_TYPE_INVALID))
       
   391     {
       
   392       return NULL;
       
   393     }
       
   394 
       
   395   obj = g_object_new (TELEPATHY_CONN_TYPE,
       
   396       "name", unique_name,
       
   397       "path", object_path,
       
   398       "interface", TP_IFACE_CONN_INTERFACE,//TP_IFACE_CONNECTION,
       
   399       "connection", connection,
       
   400       NULL);
       
   401   g_free (unique_name);
       
   402 
       
   403   g_datalist_init (&(obj->interface_list));
       
   404 
       
   405   //ADD_SIGNALS_FOR_CONNECTION (DBUS_G_PROXY (obj)); //commenting this bcoz header file not found 
       
   406   //equivalent of above stmt
       
   407   dbus_g_proxy_add_signal (DBUS_G_PROXY (obj), "NewChannel",\
       
   408     DBUS_TYPE_G_OBJECT_PATH,\
       
   409     G_TYPE_STRING,\
       
   410     G_TYPE_UINT,\
       
   411     G_TYPE_UINT,\
       
   412     G_TYPE_BOOLEAN,\
       
   413     G_TYPE_INVALID);\
       
   414   dbus_g_proxy_add_signal (DBUS_G_PROXY (obj), "StatusChanged",\
       
   415     G_TYPE_UINT,\
       
   416     G_TYPE_UINT,\
       
   417     G_TYPE_INVALID);
       
   418 
       
   419   /* Check if the connection is already connected. If so, we can
       
   420    * already perform GetInterfaces(). */
       
   421 
       
   422   if (!tp_conn_get_status (DBUS_G_PROXY (obj), &conn_status, &err))
       
   423     {
       
   424       if (err != NULL)
       
   425         g_propagate_error (error, err);
       
   426 
       
   427       g_object_unref (obj);
       
   428       return NULL;
       
   429     }
       
   430 
       
   431   if (conn_status == TP_CONN_STATUS_CONNECTED)
       
   432     {
       
   433       if (!tp_conn_get_interfaces (DBUS_G_PROXY (obj), &interfaces, &err))
       
   434         {
       
   435           if (err != NULL)
       
   436             g_propagate_error (error, err);
       
   437 
       
   438           g_object_unref (obj);
       
   439           return NULL;
       
   440         }
       
   441 
       
   442       /* Initialize the interface objects for this TpConn object */
       
   443       tp_conn_local_set_interfaces (obj, interfaces);
       
   444 
       
   445       g_strfreev (interfaces);
       
   446     }
       
   447   else
       
   448     {
       
   449       /* Not connected yet, so this is really a new connection. Thus, we
       
   450          have to hook up to StatusChanged signal to perform the
       
   451          GetInterfaces when it goes Connected */
       
   452 
       
   453       dbus_g_proxy_connect_signal (DBUS_G_PROXY (obj), "StatusChanged",
       
   454           G_CALLBACK (tp_conn_status_change_handler), NULL, NULL);
       
   455     }
       
   456 
       
   457   if (status != NULL)
       
   458     *status = conn_status;
       
   459   return obj;
       
   460 }
       
   461 
       
   462 
       
   463 TpConn *
       
   464 tp_conn_new (DBusGConnection *connection,
       
   465              const gchar *bus_name,
       
   466              const gchar *object_path)
       
   467 {
       
   468   GError *error = NULL;
       
   469   guint status;
       
   470   TpConn *obj;
       
   471 
       
   472   g_return_val_if_fail (connection != NULL, NULL);
       
   473   g_return_val_if_fail (bus_name != NULL, NULL);
       
   474   g_return_val_if_fail (object_path, NULL);
       
   475 
       
   476   obj = tp_conn_new_without_connect (connection, bus_name, object_path,
       
   477       &status, &error);
       
   478 
       
   479   if (obj == NULL)
       
   480     {
       
   481       /* either GetNameOwner, GetStatus or GetInterfaces failed */
       
   482       if (error != NULL)
       
   483         {
       
   484           g_warning ("Failed to create connection for %s %s: %s", bus_name,
       
   485               object_path, error->message);
       
   486           g_error_free (error);
       
   487         }
       
   488       else
       
   489         {
       
   490           g_warning ("Failed to create connection for %s %s: error is NULL",
       
   491               bus_name, object_path);
       
   492         }
       
   493 
       
   494       return NULL;
       
   495     }
       
   496 
       
   497   if (status != TP_CONN_STATUS_CONNECTED)
       
   498     {
       
   499       tp_conn_connect_async (DBUS_G_PROXY (obj), _tp_conn_connect_req_handler,
       
   500           NULL);
       
   501     }
       
   502 
       
   503   return obj;
       
   504 }
       
   505 
       
   506 #ifdef SYMBIAN
       
   507 EXPORT_C
       
   508 #endif
       
   509 TpChan *tp_conn_new_channel(DBusGConnection *connection,
       
   510 			    TpConn *tp_conn, const gchar *bus_name,
       
   511 			    gchar *type, guint handle_type,
       
   512 			    guint handle, gboolean supress_handler)
       
   513 {
       
   514   GError *error = NULL;
       
   515   gchar *chan_object_path = NULL;
       
   516   TpChan *new_chan = NULL;
       
   517 
       
   518   g_return_val_if_fail(connection, NULL);
       
   519   g_return_val_if_fail(TELEPATHY_IS_CONN(tp_conn), NULL);
       
   520   g_return_val_if_fail(bus_name, NULL);
       
   521   g_return_val_if_fail(type, NULL);
       
   522 
       
   523   /* Request a new channel to be created by using the proxy object.
       
   524      We also retrieve the object path for it here. */
       
   525 
       
   526   if (!tp_conn_request_channel(DBUS_G_PROXY(tp_conn),
       
   527                                type, handle_type, handle, supress_handler,
       
   528                                &chan_object_path, &error))
       
   529   {
       
   530     g_warning("RequestChannel() failed: %s\n", error -> message);
       
   531     
       
   532     g_error_free(error);
       
   533     return NULL;
       
   534   }
       
   535 
       
   536 
       
   537   /* Create the object to represent the channel */
       
   538 
       
   539   new_chan = tp_chan_new(connection, bus_name, chan_object_path, type,
       
   540                          handle_type, handle);
       
   541                          
       
   542                     
       
   543   g_free(chan_object_path);
       
   544 
       
   545 
       
   546 
       
   547   return new_chan;
       
   548 }
       
   549 
       
   550 
       
   551 void tp_conn_local_set_interfaces(TpConn *self, gchar **interfaces)
       
   552 {
       
   553   gchar **temp_ifaces = NULL;
       
   554   const gchar *bus_name = dbus_g_proxy_get_bus_name(DBUS_G_PROXY(self));
       
   555   const gchar *object_path = dbus_g_proxy_get_path(DBUS_G_PROXY(self));
       
   556 
       
   557   DBusGConnection *connection = tp_get_bus ();
       
   558 
       
   559   if (interfaces == NULL || connection == NULL)
       
   560   {
       
   561     return;
       
   562   }
       
   563 
       
   564   /* Create and store the proxy objects for the connection interfaces. */
       
   565   for (temp_ifaces = interfaces; *temp_ifaces; temp_ifaces++)
       
   566   {
       
   567     DBusGProxy *if_proxy;
       
   568     GQuark key = g_quark_from_string(*temp_ifaces);
       
   569 
       
   570     if (key == TELEPATHY_PROPS_IFACE_QUARK)
       
   571       {
       
   572         if_proxy = DBUS_G_PROXY (tp_props_iface_new (connection,
       
   573                                                      bus_name, object_path));
       
   574       }
       
   575     else
       
   576       {
       
   577         if_proxy = dbus_g_proxy_new_for_name(connection, bus_name, object_path,
       
   578                                              *temp_ifaces);
       
   579         if (if_proxy != NULL)
       
   580         {
       
   581           GData *sig_list = TELEPATHY_CONN_GET_CLASS(self)->iface_signal_sigs;
       
   582           void (*signature_setter_func)();
       
   583 
       
   584           /* Does the interface have signals? If yes, add their signatures
       
   585              for the interface instance */
       
   586           signature_setter_func =
       
   587             g_datalist_id_get_data(&sig_list, key);
       
   588 
       
   589           if (signature_setter_func != NULL)
       
   590           {
       
   591             signature_setter_func(if_proxy);
       
   592           }
       
   593         }
       
   594       }
       
   595 
       
   596    if (if_proxy != NULL)
       
   597     {
       
   598       g_datalist_id_set_data_full(&(self->interface_list),
       
   599       key, if_proxy, g_object_unref);
       
   600     }
       
   601 
       
   602   }
       
   603 }
       
   604 
       
   605 #ifdef SYMBIAN
       
   606 EXPORT_C
       
   607 #endif
       
   608 DBusGProxy *
       
   609 tp_conn_get_interface (TpConn *self,
       
   610                        GQuark iface_quark)
       
   611 {
       
   612   DBusGProxy *iface_proxy = NULL;
       
   613 
       
   614   g_return_val_if_fail (self != NULL, NULL);
       
   615   g_return_val_if_fail (iface_quark != 0, NULL);
       
   616 
       
   617   iface_proxy = (DBusGProxy *) g_datalist_id_get_data (
       
   618       &(self->interface_list), iface_quark);
       
   619 
       
   620   return iface_proxy;
       
   621 }
       
   622 
       
   623 void
       
   624 _tp_conn_connect_req_handler (DBusGProxy *proxy,
       
   625                               GError *error,
       
   626                               gpointer user_data)
       
   627 {
       
   628   /* The interfaces for the TpConn are set on the StatusChanged
       
   629      handler when we get connected. Just print errors (if any)
       
   630      here. */
       
   631 
       
   632   if (error)
       
   633   {
       
   634     g_warning ("Could not perform Connect() for the connection, because: %s",
       
   635                error->message);
       
   636     g_error_free (error);
       
   637     return;
       
   638   }
       
   639 
       
   640 }
       
   641 
       
   642 static gboolean
       
   643 tp_conn_status_change_handler (DBusGProxy *proxy,
       
   644                                guint status,
       
   645                                guint reason,
       
   646                                gpointer user_data)
       
   647 {
       
   648   gchar **interfaces = NULL;
       
   649   GError *error = NULL;
       
   650   TpConn *tp_conn = (TpConn *) proxy;
       
   651 
       
   652   /* If the connection is up, we can get the list of interfaces */
       
   653   /* FIXME: At some point, we should switch to doing this asynchronously */
       
   654 
       
   655   if (status == TP_CONN_STATUS_CONNECTED)
       
   656     {
       
   657       if (!tp_conn_get_interfaces (DBUS_G_PROXY (proxy), &interfaces, &error))
       
   658         {
       
   659           g_warning ("GetInterfaces failed: %s\n", error->message);
       
   660           g_error_free (error);
       
   661           return TRUE;
       
   662         }
       
   663 
       
   664       /* Initialize the interface objects for this TpConn object */
       
   665 
       
   666       tp_conn_local_set_interfaces (tp_conn, interfaces);
       
   667 
       
   668       g_strfreev (interfaces);
       
   669 
       
   670       dbus_g_proxy_disconnect_signal (proxy, "StatusChanged",
       
   671           G_CALLBACK (tp_conn_status_change_handler), NULL);
       
   672     }
       
   673 
       
   674   return TRUE;
       
   675 }
       
   676 
       
   677 
       
   678 static void synthesize_status_changed(TpConn *conn)
       
   679 {
       
   680 
       
   681   DBusMessageIter iter;
       
   682   DBusMessage *msg = NULL;
       
   683   guint value;
       
   684   GType uint_type = G_TYPE_UINT;
       
   685   GArray *statuschanged_signal_types = g_array_new(FALSE, FALSE,
       
   686                                                   sizeof(GType));
       
   687                                                   
       
   688   
       
   689   if (!statuschanged_signal_types)
       
   690   {
       
   691     g_warning("%s: Could not allocate type array for StatusChanged",
       
   692               G_STRFUNC);
       
   693     return;
       
   694   }
       
   695 
       
   696   msg = dbus_message_new_signal(dbus_g_proxy_get_path(DBUS_G_PROXY(conn)),
       
   697                                 TP_IFACE_CONN_INTERFACE, "StatusChanged");
       
   698 
       
   699   if (!msg)
       
   700   {
       
   701     g_warning("%s: Could not allocate message for StatusChanged signal",
       
   702               G_STRFUNC);
       
   703     g_array_free(statuschanged_signal_types, FALSE);
       
   704     return;
       
   705   }
       
   706 
       
   707   dbus_message_iter_init_append(msg, &iter); 
       
   708   value = TP_CONN_STATUS_DISCONNECTED; 
       
   709   dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &value); 
       
   710   value = TP_CONN_STATUS_REASON_NONE_SPECIFIED; 
       
   711   dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &value);
       
   712 
       
   713   /* TODO: It might be worth considering to setup/remove the array in
       
   714      base_init/base_deinit to make it persist for the whole class */
       
   715   
       
   716   if (statuschanged_signal_types)
       
   717   {
       
   718     g_array_insert_val(statuschanged_signal_types, 0, uint_type);
       
   719     g_array_insert_val(statuschanged_signal_types, 1, uint_type);
       
   720   }
       
   721   else
       
   722   {
       
   723     g_warning("%s: Could not allocate array for StatusChanged types",
       
   724               G_STRFUNC);
       
   725     dbus_message_unref(msg);
       
   726     return;
       
   727   }
       
   728 
       
   729   g_signal_emit_by_name(DBUS_G_PROXY(conn), 
       
   730                         TP_IFACE_CONN_SIGNAL_STATUSCHANGED_SYNTHESIZED, msg,
       
   731                         statuschanged_signal_types);
       
   732   g_array_free(statuschanged_signal_types, TRUE);
       
   733   dbus_message_unref(msg);
       
   734 }