|
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 } |