libtelepathy/src/tp-chan.c
changeset 10 59927b2d3b75
parent 0 d0f3a028347a
equal deleted inserted replaced
0:d0f3a028347a 10:59927b2d3b75
     1 /* tp-chan.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-chan.h"
       
    24 #include "tp-chan-signals-marshal.h"
       
    25 #include "tp-props-iface.h"
       
    26 #include "tp-helpers.h"
       
    27 
       
    28 #ifdef EMULATOR
       
    29 #include "libtelepathy_wsd_solution.h"
       
    30 #endif
       
    31 
       
    32 #ifdef EMULATOR
       
    33 	
       
    34 	GET_STATIC_VAR_FROM_TLS(parent_class,tp_chan,GObjectClass *)
       
    35 	#define parent_class (*GET_WSD_VAR_NAME(parent_class,tp_chan,s)())
       
    36 	
       
    37 	GET_STATIC_VAR_FROM_TLS(type1,tp_chan,GType)
       
    38 	#define type1 (*GET_WSD_VAR_NAME(type1,tp_chan,s)())
       
    39 	
       
    40 	GET_STATIC_VAR_FROM_TLS(ret1,tp_chan,GQuark)
       
    41 	#define ret1 (*GET_WSD_VAR_NAME(ret1,tp_chan,s)())
       
    42 	
       
    43 	GET_STATIC_VAR_FROM_TLS(ret2,tp_chan,GQuark)
       
    44 	#define ret2 (*GET_WSD_VAR_NAME(ret2,tp_chan,s)())
       
    45 	
       
    46 	GET_STATIC_VAR_FROM_TLS(ret3,tp_chan,GQuark)
       
    47 	#define ret3 (*GET_WSD_VAR_NAME(ret3,tp_chan,s)())
       
    48 	
       
    49 	GET_STATIC_VAR_FROM_TLS(ret4,tp_chan,GQuark)
       
    50 	#define ret4 (*GET_WSD_VAR_NAME(ret4,tp_chan,s)())
       
    51 	
       
    52 	GET_STATIC_VAR_FROM_TLS(ret5,tp_chan,GQuark)
       
    53 	#define ret5 (*GET_WSD_VAR_NAME(ret5,tp_chan,s)())
       
    54 	
       
    55 	GET_STATIC_VAR_FROM_TLS(ret6,tp_chan,GQuark)
       
    56 	#define ret6 (*GET_WSD_VAR_NAME(ret6,tp_chan,s)())
       
    57 	
       
    58 	GET_STATIC_VAR_FROM_TLS(ret7,tp_chan,GQuark)
       
    59 	#define ret7 (*GET_WSD_VAR_NAME(ret7,tp_chan,s)())
       
    60 	
       
    61 	GET_STATIC_VAR_FROM_TLS(ret8,tp_chan,GQuark)
       
    62 	#define ret8 (*GET_WSD_VAR_NAME(ret8,tp_chan,s)())
       
    63 	
       
    64 	GET_STATIC_VAR_FROM_TLS(ret9,tp_chan,GQuark)
       
    65 	#define ret9 (*GET_WSD_VAR_NAME(ret9,tp_chan,s)())
       
    66 	
       
    67 	GET_STATIC_VAR_FROM_TLS(ret10,tp_chan,GQuark)
       
    68 	#define ret10 (*GET_WSD_VAR_NAME(ret10,tp_chan,s)())
       
    69 	
       
    70 	GET_STATIC_VAR_FROM_TLS(ret11,tp_chan,GQuark)
       
    71 	#define ret11 (*GET_WSD_VAR_NAME(ret11,tp_chan,s)())
       
    72 	
       
    73 	
       
    74 #else
       
    75 	static GObjectClass *parent_class = NULL;
       
    76 #endif
       
    77 
       
    78 static void synthesize_closed(TpChan *chan);
       
    79 
       
    80 static void _tp_chan_register_signal_marshallers()
       
    81 {
       
    82   /* Register marshaller for the Close signal */
       
    83   dbus_g_object_register_marshaller(tp_chan_signals_marshal_VOID__VOID,
       
    84 				    G_TYPE_NONE, G_TYPE_INVALID);
       
    85 }
       
    86 
       
    87 static void _tp_chan_register_interface_signal_marshallers()
       
    88 {
       
    89   
       
    90   /* Register marshaller for ContactSearch interface signal
       
    91      SearchResultReceived*/
       
    92  
       
    93   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT_BOXED, 
       
    94   					G_TYPE_NONE, G_TYPE_UINT, G_TYPE_BOXED, G_TYPE_INVALID);
       
    95 
       
    96   /* Register marshaller for ContactSearch interface signal
       
    97    * SearchStateChanged */
       
    98   
       
    99   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT,
       
   100 				    G_TYPE_NONE, G_TYPE_UINT, G_TYPE_INVALID);
       
   101 
       
   102   /* Register marshaller for StreamedMedia interface signal
       
   103      ReceivedMediaParameters */
       
   104   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT_STRING_STRING, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
       
   105   /* Register marshaller for StreamedMedia interface signal
       
   106      StreamStateChanged */
       
   107 
       
   108   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT_UINT_UINT, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID);
       
   109 
       
   110   /* Register marshaller for RoomList interface signal GotRooms */
       
   111 
       
   112   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__BOXED,
       
   113 				    G_TYPE_NONE, G_TYPE_BOXED, G_TYPE_INVALID);
       
   114 
       
   115   /* Register marshaller for RoomList interface signal ListingRooms */
       
   116   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__BOOLEAN,
       
   117 				    G_TYPE_NONE, G_TYPE_BOOLEAN,
       
   118 				    G_TYPE_INVALID);
       
   119 
       
   120   /* Register marshaller for channel type Text interface signal Received */
       
   121   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT_UINT_UINT_UINT_UINT_STRING, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT,
       
   122 				    G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING,
       
   123 				    G_TYPE_INVALID);
       
   124 
       
   125   /* Register marshaller for channel type Text interface Sent */
       
   126   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT_UINT_STRING, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
       
   127 
       
   128   /* Register marshaller used by the following iface/signal pairs:
       
   129    * DTFM/ReceivedDTMF, Group/GroupFlagsChanged, Hold/HoldStateChanged,
       
   130    * Password/PasswordFlagsChanged, Subject/SubjectFlagsChanged */
       
   131   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT_UINT,
       
   132 				    G_TYPE_NONE, G_TYPE_UINT, G_TYPE_UINT,
       
   133 				    G_TYPE_INVALID);
       
   134   /* Register marshaller for Group interface signal MembersChanged */
       
   135   
       
   136   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__STRING_BOXED_BOXED_BOXED_BOXED_UINT_UINT, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_BOXED,
       
   137                                     G_TYPE_BOXED, G_TYPE_BOXED, G_TYPE_BOXED,
       
   138                                     G_TYPE_UINT, G_TYPE_UINT,G_TYPE_INVALID);
       
   139 
       
   140   /* Register marshaller for Text Channel interface signal SendError */
       
   141   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__UINT_UINT_UINT_STRING, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
       
   142 
       
   143   /* Register marshaller for IceSignalling interface signal
       
   144      NewIceSessionHandler */
       
   145 
       
   146   dbus_g_object_register_marshaller(tp_ifaces_signals_marshal_VOID__OBJECT_STRING, G_TYPE_NONE, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_STRING, G_TYPE_INVALID);
       
   147 
       
   148 }
       
   149 
       
   150 
       
   151 /* We initialize the list of signatures here, so that we can use
       
   152  * it to add them for new interface instances later.*/
       
   153 
       
   154 /* FIXME: This should be replaced by a more automatic way of doing
       
   155  * this. The reason for using a set of function pointers is that there is no
       
   156  * apparent cleaner way of doing this, unless DBusGProxy gains a non-varargs
       
   157  * version of dbus_g_proxy_add_signal...
       
   158  */
       
   159 
       
   160 
       
   161 static void _tp_chan_init_interface_signal_signatures(GData **signal_sigs)
       
   162 {
       
   163   g_datalist_init(signal_sigs);
       
   164   
       
   165   
       
   166   /* Create and store contact search iface signal signatures */
       
   167   g_datalist_id_set_data(signal_sigs, TELEPATHY_CHAN_IFACE_CONTACTSEARCH_QUARK,
       
   168 			 (gpointer)tp_chan_set_contactsearch_signatures);
       
   169 
       
   170   /* Store streamed media iface signal signatures */
       
   171   g_datalist_id_set_data(signal_sigs,
       
   172 			 TELEPATHY_CHAN_IFACE_STREAMED_QUARK,
       
   173 			 (gpointer)tp_chan_set_streamedmedia_signatures);
       
   174   /* Store roomlist signal iface signal parameters */
       
   175   g_datalist_id_set_data(signal_sigs, TELEPATHY_CHAN_IFACE_ROOMLIST_QUARK,
       
   176 			 (gpointer)tp_chan_set_roomlist_signatures);
       
   177   /* Store text iface signal signatures */
       
   178   g_datalist_id_set_data(signal_sigs, TELEPATHY_CHAN_IFACE_TEXT_QUARK,
       
   179 			 (gpointer)tp_chan_set_text_signatures);
       
   180   /* Store DTMF iface signal signatures */
       
   181   g_datalist_id_set_data(signal_sigs, TELEPATHY_CHAN_IFACE_DTMF_QUARK,
       
   182 			 (gpointer)tp_chan_set_dtmf_signatures);
       
   183   /* Store group iface signal signatures */
       
   184   g_datalist_id_set_data(signal_sigs, TELEPATHY_CHAN_IFACE_GROUP_QUARK,
       
   185 			 (gpointer)tp_chan_set_group_signatures);
       
   186   /* Store hold iface signatures */
       
   187   g_datalist_id_set_data(signal_sigs, TELEPATHY_CHAN_IFACE_HOLD_QUARK,
       
   188 			 (gpointer)tp_chan_set_hold_signatures);
       
   189   /* Store password iface signatures */
       
   190   g_datalist_id_set_data(signal_sigs, TELEPATHY_CHAN_IFACE_PASSWORD_QUARK,
       
   191 			 (gpointer)tp_chan_set_password_signatures);
       
   192 }
       
   193 
       
   194 static void tp_chan_init(GTypeInstance *instance, gpointer g_class)
       
   195 {
       
   196   TpChan *self = TELEPATHY_CHAN(instance);
       
   197   self->type = NULL;
       
   198   self->first_run = TRUE;
       
   199 }
       
   200 
       
   201 
       
   202 static void tp_chan_dispose(GObject *obj)
       
   203 {
       
   204   TpChan *self = TELEPATHY_CHAN(obj);
       
   205 
       
   206   if (self->first_run)
       
   207   {
       
   208     self->first_run = FALSE;
       
   209     synthesize_closed(self);
       
   210     g_datalist_clear(&(self->interface_list));
       
   211   }
       
   212   
       
   213   /* Chain up to the parent class dispose */
       
   214   if (G_OBJECT_CLASS(parent_class)->dispose)
       
   215   {
       
   216     G_OBJECT_CLASS(parent_class)->dispose(obj);
       
   217   }
       
   218 
       
   219 }
       
   220 
       
   221 
       
   222 static void tp_chan_finalize(GObject *obj)
       
   223 {
       
   224   TpChan *self = TELEPATHY_CHAN(obj);
       
   225 
       
   226   if (self->type)
       
   227   {
       
   228     g_free(self->type);
       
   229   }
       
   230 
       
   231   if (G_OBJECT_CLASS(parent_class)->finalize)
       
   232   {
       
   233     G_OBJECT_CLASS(parent_class)->finalize(obj);
       
   234   }
       
   235 }
       
   236 
       
   237 
       
   238 static void tp_chan_class_init(TpChanClass *klass)
       
   239 {
       
   240   GObjectClass *obj = G_OBJECT_CLASS(klass);
       
   241   parent_class = g_type_class_peek_parent(klass);
       
   242 
       
   243   obj->set_property = parent_class->set_property;
       
   244   obj->get_property = parent_class->get_property;
       
   245   obj->dispose = tp_chan_dispose;
       
   246   obj->finalize = tp_chan_finalize;
       
   247   _tp_chan_register_signal_marshallers();
       
   248   _tp_chan_register_interface_signal_marshallers();
       
   249   _tp_chan_init_interface_signal_signatures(&(klass->iface_signal_sigs));
       
   250 }
       
   251 
       
   252 
       
   253 GType tp_chan_get_type(void)
       
   254 {
       
   255 #ifndef EMULATOR
       
   256   static GType type1 = 0;
       
   257 #endif
       
   258   
       
   259   if (type1 == 0)
       
   260   {
       
   261     static const GTypeInfo info =
       
   262     {
       
   263       sizeof(TpChanClass),
       
   264       NULL,
       
   265       NULL,
       
   266       (GClassInitFunc)tp_chan_class_init,
       
   267       NULL,
       
   268       NULL,
       
   269       sizeof(TpChan),
       
   270       0,
       
   271       (GInstanceInitFunc)tp_chan_init
       
   272     };
       
   273     type1 = g_type_register_static(DBUS_TYPE_G_PROXY,
       
   274         "TpChan", &info, 0);
       
   275   }
       
   276   return type1;
       
   277 }
       
   278 
       
   279 
       
   280 
       
   281 /* Public functions begin */
       
   282 
       
   283 GQuark tp_get_chan_interface()
       
   284 {
       
   285 #ifndef EMULATOR
       
   286   static GQuark ret1 = 0;
       
   287 #endif
       
   288 
       
   289   if (ret1 == 0)
       
   290   {
       
   291     ret1 = g_quark_from_static_string(TP_IFACE_CHANNEL_INTERFACE);
       
   292   }
       
   293 
       
   294   return ret1;
       
   295 }
       
   296 
       
   297 GQuark tp_get_chan_contactlist_interface()
       
   298 {
       
   299 #ifndef EMULATOR  
       
   300   static GQuark ret2 = 0;
       
   301 #endif
       
   302 
       
   303   if (ret2 == 0)
       
   304   {
       
   305     ret2 = g_quark_from_static_string(TP_IFACE_CHANNEL_TYPE_CONTACT_LIST);
       
   306   }
       
   307 
       
   308   return ret2;
       
   309 }
       
   310 
       
   311 
       
   312 #ifdef SYMBIAN
       
   313 EXPORT_C 
       
   314 #endif
       
   315 GQuark tp_get_chan_contactsearch_interface()
       
   316 {
       
   317 #ifndef EMULATOR
       
   318   static GQuark ret3 = 0;
       
   319 #endif
       
   320 
       
   321   if (ret3 == 0)
       
   322   {
       
   323     ret3 = g_quark_from_static_string(TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH);
       
   324   }
       
   325 
       
   326   return ret3;
       
   327 }
       
   328 
       
   329 
       
   330 GQuark tp_get_chan_streamed_interface()
       
   331 {
       
   332 #ifndef EMULATOR
       
   333   static GQuark ret4 = 0;
       
   334 #endif
       
   335 
       
   336   if (ret4 == 0)
       
   337   {
       
   338     ret4 = g_quark_from_static_string(TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA);
       
   339   }
       
   340 
       
   341   return ret4;
       
   342 }
       
   343 
       
   344 
       
   345 GQuark tp_get_chan_roomlist_interface()
       
   346 {
       
   347 #ifndef EMULATOR
       
   348   static GQuark ret5 = 0;
       
   349 #endif
       
   350 
       
   351   if (ret5 == 0)
       
   352   {
       
   353     ret5 = g_quark_from_static_string(TP_IFACE_CHANNEL_TYPE_ROOM_LIST);
       
   354   }
       
   355 
       
   356   return ret5;
       
   357 }
       
   358 
       
   359 #ifdef SYMBIAN
       
   360 EXPORT_C 
       
   361 #endif
       
   362 GQuark tp_get_chan_text_interface()
       
   363 {
       
   364 #ifndef EMULATOR
       
   365   static GQuark ret6 = 0;
       
   366 #endif
       
   367 
       
   368   if (ret6 == 0)
       
   369   {
       
   370     ret6 = g_quark_from_static_string(TP_IFACE_CHANNEL_TYPE_TEXT);
       
   371   }
       
   372 
       
   373   return ret6;
       
   374 }
       
   375 
       
   376 
       
   377 GQuark tp_get_chan_dtmf_interface()
       
   378 {
       
   379 #ifndef EMULATOR
       
   380   static GQuark ret7 = 0;
       
   381 #endif
       
   382   
       
   383   if (ret7 == 0)
       
   384   {
       
   385     ret7 = g_quark_from_static_string(TP_IFACE_CHANNEL_INTERFACE_DTMF);
       
   386   }
       
   387 
       
   388   return ret7;
       
   389 }
       
   390 
       
   391 
       
   392 #ifdef SYMBIAN
       
   393 EXPORT_C 
       
   394 #endif
       
   395 GQuark tp_get_chan_group_interface()
       
   396 {
       
   397 #ifndef EMULATOR
       
   398   static GQuark ret8 = 0;
       
   399 #endif
       
   400 
       
   401   if (ret8 == 0)
       
   402   {
       
   403     ret8 = g_quark_from_static_string(TP_IFACE_CHANNEL_INTERFACE_GROUP);
       
   404   }
       
   405 
       
   406   return ret8;
       
   407 }
       
   408 
       
   409 
       
   410 GQuark tp_get_chan_hold_interface()
       
   411 {
       
   412 #ifndef EMULATOR
       
   413   static GQuark ret9 = 0;
       
   414 #endif
       
   415 
       
   416   if (ret9 == 0)
       
   417   {
       
   418     ret9 = g_quark_from_static_string(TP_IFACE_CHANNEL_INTERFACE_HOLD);
       
   419   }
       
   420 
       
   421   return ret9;
       
   422 }
       
   423 
       
   424 
       
   425 GQuark tp_get_chan_password_interface()
       
   426 {
       
   427 #ifndef EMULATOR
       
   428   static GQuark ret10 = 0;
       
   429 #endif
       
   430 
       
   431   if (ret10 == 0)
       
   432   {
       
   433     ret10 = g_quark_from_static_string(TP_IFACE_CHANNEL_INTERFACE_PASSWORD);
       
   434   }
       
   435 
       
   436   return ret10;
       
   437 }
       
   438 
       
   439 GQuark tp_get_chan_transfer_interface()
       
   440 {
       
   441 #ifndef EMULATOR
       
   442   static GQuark ret11 = 0;
       
   443 #endif
       
   444 
       
   445   if (ret11 == 0)
       
   446   {
       
   447     ret11 = g_quark_from_static_string(TP_IFACE_CHANNEL_INTERFACE_TRANSFER);
       
   448   }
       
   449 
       
   450   return ret11;
       
   451 }
       
   452 
       
   453 
       
   454 #ifdef SYMBIAN
       
   455 EXPORT_C 
       
   456 #endif
       
   457 TpChan *tp_chan_new(DBusGConnection *connection, const gchar *bus_name,
       
   458                     const gchar *object_path, const gchar *type,
       
   459                     guint handle_type, guint handle)
       
   460 {
       
   461   GError *error = NULL;
       
   462   gchar *unique_name;
       
   463   gchar **interfaces;
       
   464   TpChan *chan;
       
   465   g_return_val_if_fail(connection != NULL, NULL);
       
   466   g_return_val_if_fail(bus_name != NULL, NULL);
       
   467   g_return_val_if_fail(object_path != NULL, NULL);
       
   468   g_return_val_if_fail(type != NULL, NULL);
       
   469 
       
   470   if (!dbus_g_proxy_call (tp_get_bus_proxy (), 
       
   471                           "GetNameOwner", &error, G_TYPE_STRING, bus_name, 
       
   472                           G_TYPE_INVALID, G_TYPE_STRING, &unique_name, 
       
   473                           G_TYPE_INVALID))
       
   474   {
       
   475     g_warning("tp_chan_new: getting unique name failed: %s", error->message);
       
   476     g_error_free(error);
       
   477     return NULL;
       
   478   }
       
   479 
       
   480   /* Create the channel object */
       
   481   chan = g_object_new(TELEPATHY_CHAN_TYPE,
       
   482                       "name", unique_name, "path", object_path,
       
   483                       "interface", TP_IFACE_CHANNEL_INTERFACE,
       
   484                       "connection", connection, NULL);
       
   485 
       
   486   g_free(unique_name);
       
   487 
       
   488   dbus_g_proxy_add_signal(DBUS_G_PROXY(chan), "Closed", G_TYPE_INVALID);
       
   489 
       
   490   g_datalist_init(&(chan->interface_list));
       
   491 
       
   492   /* Store interface information for the channel */
       
   493   if (tp_chan_get_interfaces(DBUS_G_PROXY(chan), &interfaces, &error))
       
   494   {
       
   495     tp_chan_local_set_interfaces(chan, interfaces);
       
   496 
       
   497     /* Free the strings used for interface object creation */
       
   498     g_strfreev(interfaces);
       
   499   }
       
   500   else
       
   501   {
       
   502     g_warning("GetInterfaces for channel failed: %s\n", error->message);
       
   503     g_error_free(error);
       
   504   }
       
   505 
       
   506   /* Store necessary information for this object */
       
   507   chan->type = g_strdup(type);
       
   508   chan->handle_type = handle_type;
       
   509   chan->handle = handle;
       
   510 
       
   511   return chan;
       
   512 }
       
   513 
       
   514 
       
   515 void tp_chan_local_set_interfaces(TpChan *self, gchar **interfaces)
       
   516 {
       
   517   gchar **temp_ifaces;
       
   518   gchar *chan_type = NULL;
       
   519   GError *error = NULL;
       
   520   GData **sig_list = &(TELEPATHY_CHAN_GET_CLASS(self)->iface_signal_sigs);
       
   521   void (*signature_setter_func)(DBusGProxy *proxy);
       
   522   DBusGConnection *connection;
       
   523   /*const*/ gchar *name, *path;
       
   524 
       
   525   if (interfaces == NULL)
       
   526   {
       
   527     return;
       
   528   }
       
   529 
       
   530   /* Create and store proxy objects corresponding to the
       
   531      interfaces */
       
   532 
       
   533   g_object_get (G_OBJECT(self),
       
   534                 "connection", &connection,
       
   535                 "name", &name,
       
   536                 "path", &path,
       
   537                 NULL);
       
   538 
       
   539   g_debug ("%s: %p, %s, %s", G_STRFUNC, connection, name, path);
       
   540 
       
   541   for (temp_ifaces = interfaces; *temp_ifaces; temp_ifaces++)
       
   542     {
       
   543       GQuark key = g_quark_from_string(*temp_ifaces);
       
   544       DBusGProxy *if_proxy;
       
   545 
       
   546       if (key == TELEPATHY_PROPS_IFACE_QUARK)
       
   547         {
       
   548           if_proxy = DBUS_G_PROXY (tp_props_iface_new (connection, name, path));
       
   549         }
       
   550       else
       
   551         {
       
   552           if_proxy = dbus_g_proxy_new_for_name (connection, name,
       
   553                                                 path, *temp_ifaces);
       
   554 
       
   555           if (if_proxy != NULL)
       
   556             {
       
   557               /* Does the interface have signals? If yes, add their signatures
       
   558                  for the interface instance by calling the
       
   559                  corresponding setter function */
       
   560 
       
   561               signature_setter_func =
       
   562                 g_datalist_id_get_data(sig_list, key);
       
   563 
       
   564               if (signature_setter_func != NULL)
       
   565                 {
       
   566                   (*signature_setter_func)(if_proxy);
       
   567                 }
       
   568             }
       
   569         }
       
   570       if (if_proxy != NULL)
       
   571         {
       
   572           g_datalist_id_set_data_full(&(self->interface_list), key,
       
   573               if_proxy, g_object_unref);
       
   574         }
       
   575     }
       
   576 
       
   577   /* Finally, add the channel type interface */
       
   578 
       
   579   if (!tp_chan_get_channel_type(DBUS_G_PROXY(self), &chan_type, &error))
       
   580   {
       
   581     g_warning("GetChannelType failed: %s\n", error->message);
       
   582     g_error_free(error);
       
   583   }
       
   584   else
       
   585   {
       
   586     DBusGProxy *chan_proxy =
       
   587       dbus_g_proxy_new_from_proxy(DBUS_G_PROXY(self), chan_type, NULL);
       
   588 
       
   589     g_datalist_id_set_data(&(self->interface_list),
       
   590         g_quark_from_string(chan_type), chan_proxy);
       
   591 
       
   592     /* If the particular channel type interface has signals defined,
       
   593        call the corresponding setter function */
       
   594 
       
   595     signature_setter_func =
       
   596       g_datalist_id_get_data(sig_list, g_quark_from_string(chan_type));
       
   597 
       
   598     if (signature_setter_func != NULL)
       
   599     {
       
   600       (*signature_setter_func)(chan_proxy);
       
   601     }
       
   602 
       
   603     g_free(chan_type);
       
   604   }
       
   605 
       
   606   g_free (name);
       
   607   g_free (path);
       
   608   dbus_g_connection_unref (connection);
       
   609 }
       
   610 
       
   611 #ifdef SYMBIAN
       
   612 EXPORT_C 
       
   613 #endif
       
   614 DBusGProxy *tp_chan_get_interface(TpChan *self, GQuark iface_quark)
       
   615 {
       
   616   DBusGProxy *iface_proxy = NULL;
       
   617 
       
   618   iface_proxy = (DBusGProxy *)g_datalist_id_get_data(&(self->interface_list),
       
   619 						     iface_quark);
       
   620   return iface_proxy;
       
   621 }
       
   622 
       
   623 static void synthesize_closed(TpChan *chan)
       
   624 {
       
   625   DBusMessage *msg = NULL;
       
   626   GArray *closed_signal_types = g_array_new(FALSE, FALSE, sizeof(GType));
       
   627 
       
   628   if (!closed_signal_types)
       
   629   {
       
   630     g_warning("%s: Could not allocate the type array for Closed signal",
       
   631               G_STRFUNC);
       
   632     return;
       
   633   }
       
   634 
       
   635   msg = dbus_message_new_signal(dbus_g_proxy_get_path(DBUS_G_PROXY(chan)),
       
   636                             TP_IFACE_CHANNEL_INTERFACE, "Closed");
       
   637   if (!msg)
       
   638   {
       
   639     g_warning("%s: Could not create the synthetic Closed signal message.",
       
   640               G_STRFUNC);
       
   641     g_array_free(closed_signal_types, FALSE);
       
   642     return;
       
   643   }
       
   644   g_signal_emit_by_name(DBUS_G_PROXY(chan),
       
   645                         TP_IFACE_CHAN_SIGNAL_CLOSED_SYNTHESIZED, msg,
       
   646                         closed_signal_types);
       
   647   g_array_free(closed_signal_types, FALSE);
       
   648   dbus_message_unref(msg);
       
   649 }