|
1 /* tp-props-iface.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 <dbus/dbus-glib.h> |
|
23 #include <string.h> |
|
24 #include "tp-interfaces.h" |
|
25 #include "tp-ifaces-signals-marshal.h" |
|
26 #include "tp-props-iface-gen.h" |
|
27 #include "tp-props-iface.h" |
|
28 |
|
29 #ifdef EMULATOR |
|
30 #include "libtelepathy_wsd_solution.h" |
|
31 #endif |
|
32 |
|
33 |
|
34 #define TP_TYPE_PROPERTY_DESCRIPTION (dbus_g_type_get_struct ("GValueArray", \ |
|
35 G_TYPE_UINT, \ |
|
36 G_TYPE_STRING, \ |
|
37 G_TYPE_STRING, \ |
|
38 G_TYPE_UINT, \ |
|
39 G_TYPE_INVALID)) |
|
40 |
|
41 #define TP_TYPE_PROPERTY_CHANGE (dbus_g_type_get_struct ("GValueArray", \ |
|
42 G_TYPE_UINT, \ |
|
43 G_TYPE_VALUE, \ |
|
44 G_TYPE_INVALID)) |
|
45 |
|
46 #define TP_TYPE_PROPERTY_FLAGS_CHANGE (dbus_g_type_get_struct ("GValueArray", \ |
|
47 G_TYPE_UINT, \ |
|
48 G_TYPE_UINT, \ |
|
49 G_TYPE_INVALID)) |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 /*signal enum*/ |
|
55 enum |
|
56 { |
|
57 PROPERTIES_READY, |
|
58 PROPERTY_CHANGED, |
|
59 LAST_SIGNAL |
|
60 #ifdef EMULATOR |
|
61 = LAST_SIGNAL_TP_PROPS_IFACE |
|
62 #endif |
|
63 |
|
64 }; |
|
65 |
|
66 #ifndef EMULATOR |
|
67 static guint signals[LAST_SIGNAL] = {0}; |
|
68 #endif |
|
69 |
|
70 /* looking up properties is linear time on the grounds that number of properties |
|
71 * will always be small, so this will be more cache-friendly |
|
72 */ |
|
73 typedef struct _PropertyMapping PropertyMapping; |
|
74 struct _PropertyMapping |
|
75 { |
|
76 guint user_id; |
|
77 guint32 server_id; |
|
78 gchar *name; |
|
79 GValue *value; |
|
80 guint32 flags; |
|
81 }; |
|
82 |
|
83 typedef struct _TpPropsPrivate TpPropsPrivate; |
|
84 |
|
85 struct _TpPropsPrivate |
|
86 { |
|
87 gboolean properties_ready; |
|
88 |
|
89 int mappings_len; |
|
90 PropertyMapping *mappings; |
|
91 }; |
|
92 |
|
93 #ifndef EMULATOR |
|
94 static GObjectClass *parent_class = NULL; |
|
95 #endif |
|
96 |
|
97 |
|
98 #ifdef EMULATOR |
|
99 |
|
100 GET_STATIC_ARRAY_FROM_TLS(signals,tp_props_iface,guint) |
|
101 #define signals (GET_WSD_VAR_NAME(signals,tp_props_iface, s)()) |
|
102 |
|
103 GET_STATIC_VAR_FROM_TLS(parent_class,tp_props_iface,GObjectClass *) |
|
104 #define parent_class (*GET_WSD_VAR_NAME(parent_class,tp_props_iface,s)()) |
|
105 |
|
106 GET_STATIC_VAR_FROM_TLS(type1,tp_props_iface,GType) |
|
107 #define type1 (*GET_WSD_VAR_NAME(type1,tp_props_iface,s)()) |
|
108 |
|
109 GET_STATIC_VAR_FROM_TLS(ret,tp_props_iface,GQuark) |
|
110 #define ret (*GET_WSD_VAR_NAME(ret,tp_props_iface,s)()) |
|
111 |
|
112 #endif |
|
113 |
|
114 |
|
115 #define PRIV(o) ((TpPropsPrivate*)(o->priv)) |
|
116 |
|
117 static void properties_listed_cb (DBusGProxy *proxy, GPtrArray *properties, GError *error, gpointer user_data); |
|
118 |
|
119 static void tp_props_iface_init(GTypeInstance *instance, gpointer g_class) |
|
120 { |
|
121 TpPropsIface *self = TELEPATHY_PROPS_IFACE(instance); |
|
122 |
|
123 self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), |
|
124 TELEPATHY_PROPS_IFACE_TYPE, TpPropsPrivate); |
|
125 |
|
126 } |
|
127 |
|
128 static GObject * |
|
129 tp_props_iface_constructor (GType type, guint n_props, |
|
130 GObjectConstructParam *props) |
|
131 { |
|
132 GObject *obj; |
|
133 |
|
134 obj = G_OBJECT_CLASS (parent_class)-> |
|
135 constructor (type, n_props, props); |
|
136 |
|
137 dbus_g_proxy_add_signal(DBUS_G_PROXY(obj), "PropertiesChanged", |
|
138 dbus_g_type_get_collection ("GPtrArray", TP_TYPE_PROPERTY_CHANGE), |
|
139 G_TYPE_INVALID); |
|
140 dbus_g_proxy_add_signal(DBUS_G_PROXY(obj), "PropertyFlagsChanged", |
|
141 dbus_g_type_get_collection ("GPtrArray", TP_TYPE_PROPERTY_FLAGS_CHANGE), |
|
142 G_TYPE_INVALID); |
|
143 |
|
144 return obj; |
|
145 } |
|
146 |
|
147 static void tp_props_iface_dispose(GObject *obj) |
|
148 { |
|
149 |
|
150 /* Call parent class dispose method */ |
|
151 if (G_OBJECT_CLASS(parent_class)->dispose) |
|
152 { |
|
153 G_OBJECT_CLASS(parent_class)->dispose(obj); |
|
154 } |
|
155 |
|
156 } |
|
157 |
|
158 |
|
159 static void tp_props_iface_finalize(GObject *obj) |
|
160 { |
|
161 TpPropsIface *self = TELEPATHY_PROPS_IFACE(obj); |
|
162 int i; |
|
163 for (i=0; i < PRIV(self)->mappings_len; i++) |
|
164 { |
|
165 if (PRIV(self)->mappings[i].value) |
|
166 { |
|
167 g_value_unset (PRIV(self)->mappings[i].value); |
|
168 g_free (PRIV(self)->mappings[i].value); |
|
169 } |
|
170 if (PRIV(self)->mappings[i].name) |
|
171 g_free (PRIV(self)->mappings[i].name); |
|
172 } |
|
173 |
|
174 g_free (PRIV(self)->mappings); |
|
175 |
|
176 if (G_OBJECT_CLASS(parent_class)->finalize) |
|
177 { |
|
178 G_OBJECT_CLASS(parent_class)->finalize(obj); |
|
179 } |
|
180 } |
|
181 |
|
182 |
|
183 static void tp_props_iface_class_init(TpPropsIfaceClass *klass) |
|
184 { |
|
185 GObjectClass *obj = G_OBJECT_CLASS(klass); |
|
186 parent_class = g_type_class_peek_parent(klass); |
|
187 |
|
188 obj->set_property = parent_class->set_property; |
|
189 obj->get_property = parent_class->get_property; |
|
190 |
|
191 obj->constructor = tp_props_iface_constructor; |
|
192 obj->dispose = tp_props_iface_dispose; |
|
193 obj->finalize = tp_props_iface_finalize; |
|
194 |
|
195 g_type_class_add_private (klass, sizeof (TpPropsPrivate)); |
|
196 /** |
|
197 * TpPropsIface::properties-ready: |
|
198 * @self: #TpPropsIface that emmitted the signal |
|
199 * @property_id: property that changed |
|
200 * @change_flags: #TpPropsChanged for what changed on the property |
|
201 * |
|
202 * This signal is emitted when the properties 1st become avaible for |
|
203 * reading or writing. |
|
204 */ |
|
205 |
|
206 signals[PROPERTIES_READY] = |
|
207 g_signal_new ("properties-ready", |
|
208 G_OBJECT_CLASS_TYPE (klass), |
|
209 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, |
|
210 0, |
|
211 NULL, NULL, |
|
212 g_cclosure_marshal_VOID__VOID, |
|
213 G_TYPE_NONE, 0); |
|
214 |
|
215 |
|
216 |
|
217 /** |
|
218 * TpPropsIface::properties-changed: |
|
219 * @self: #TpPropsIface that emmitted the signal |
|
220 * @property_id: property that changed |
|
221 * @change_flags: #TpPropsChanged for what changed on the property |
|
222 * |
|
223 * This signal is emitted when a property changes. |
|
224 */ |
|
225 |
|
226 signals[PROPERTY_CHANGED] = |
|
227 g_signal_new ("properties-changed", |
|
228 G_OBJECT_CLASS_TYPE (klass), |
|
229 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, |
|
230 0, |
|
231 NULL, NULL, |
|
232 tp_ifaces_signals_marshal_VOID__UINT_UINT, |
|
233 G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); |
|
234 |
|
235 |
|
236 /* register marshaller for PropertiesChanged and PropertyFlagsChanged*/ |
|
237 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); |
|
238 |
|
239 } |
|
240 |
|
241 #ifdef SYMBIAN |
|
242 EXPORT_C |
|
243 #endif |
|
244 GType tp_props_iface_get_type(void) |
|
245 { |
|
246 #ifndef EMULATOR |
|
247 static GType type1 = 0; |
|
248 #endif |
|
249 |
|
250 if (type1 == 0) |
|
251 { |
|
252 static const GTypeInfo info = |
|
253 { |
|
254 sizeof(TpPropsIfaceClass), |
|
255 NULL, |
|
256 NULL, |
|
257 (GClassInitFunc)tp_props_iface_class_init, |
|
258 NULL, |
|
259 NULL, |
|
260 sizeof(TpPropsIface), |
|
261 0, |
|
262 (GInstanceInitFunc)tp_props_iface_init |
|
263 }; |
|
264 type1 = g_type_register_static(DBUS_TYPE_G_PROXY, |
|
265 "TpPropsIface", &info, 0); |
|
266 } |
|
267 return type1; |
|
268 } |
|
269 |
|
270 /* The interface name getters */ |
|
271 #ifdef SYMBIAN |
|
272 EXPORT_C |
|
273 #endif |
|
274 GQuark |
|
275 tp_get_props_interface (void) |
|
276 { |
|
277 #ifndef EMULATOR |
|
278 static GQuark ret = 0; |
|
279 #endif |
|
280 |
|
281 if (ret == 0) |
|
282 { |
|
283 ret = g_quark_from_static_string(TP_IFACE_PROPERTIES); |
|
284 } |
|
285 |
|
286 return ret; |
|
287 } |
|
288 |
|
289 TpPropsIface * |
|
290 tp_props_iface_new (DBusGConnection *connection, |
|
291 const char *name, |
|
292 const char *path_name) |
|
293 { |
|
294 /* The properties are order dependant in dbus <= 0.61. Thanks dbus*/ |
|
295 return g_object_new (TELEPATHY_PROPS_IFACE_TYPE, |
|
296 "name", name, |
|
297 "path", path_name, |
|
298 "interface",TP_IFACE_PROPERTIES, |
|
299 "connection", connection, |
|
300 NULL); |
|
301 } |
|
302 |
|
303 static void properties_changed_cb (DBusGProxy *proxy, GPtrArray *properties, gpointer user_data); |
|
304 static void property_flags_changed_cb (DBusGProxy *proxy, GPtrArray *properties, gpointer user_data); |
|
305 |
|
306 /** |
|
307 * tp_props_iface_set_mapping: |
|
308 * @iface: #TpPropsIface on which to set mapping |
|
309 * @first_name: First name in list to set a mapping for |
|
310 * |
|
311 * Set a mapping between propery names and your chosen ID's for these |
|
312 * names. Takes a list of property name, id pairs, terminated by NULL. |
|
313 * |
|
314 * Typically the user will define an enum of properties that they're |
|
315 * interested in, and set a mapping like: |
|
316 * tp_props_iface_set_mapping (props, "foo", FOO, |
|
317 * "bar", BAR, |
|
318 * "baz", BAZ, |
|
319 * NULL); |
|
320 * the user should bind to the |
|
321 * <link linkend="TpPropsIface-properties-ready">properties-ready signal</link> |
|
322 * before calling this. Property queries will only be possible *after* this |
|
323 * signal has been emitted. |
|
324 */ |
|
325 void tp_props_iface_set_mapping (TpPropsIface *self, |
|
326 const gchar *first_property_name, |
|
327 ...) |
|
328 { |
|
329 va_list var_args; |
|
330 const gchar *name = first_property_name; |
|
331 guint id; |
|
332 GArray *array; |
|
333 PropertyMapping map = {0,0,NULL,NULL,0}; |
|
334 |
|
335 g_return_if_fail (TELEPATHY_IS_PROPS_IFACE (self)); |
|
336 g_return_if_fail (PRIV(self)->mappings == NULL); |
|
337 |
|
338 va_start (var_args, first_property_name); |
|
339 |
|
340 array = g_array_new (FALSE, FALSE, sizeof (PropertyMapping)); |
|
341 |
|
342 while (name) |
|
343 { |
|
344 id = va_arg (var_args, guint); |
|
345 map.user_id = id; |
|
346 map.name = g_strdup (name); |
|
347 g_array_append_val (array, map); |
|
348 name = va_arg (var_args, gchar *); |
|
349 } |
|
350 |
|
351 va_end (var_args); |
|
352 |
|
353 PRIV (self)->mappings_len = array->len; |
|
354 PRIV (self)->mappings = (PropertyMapping*) g_array_free (array, FALSE); |
|
355 |
|
356 dbus_g_proxy_connect_signal (DBUS_G_PROXY (self), "PropertiesChanged", |
|
357 G_CALLBACK(properties_changed_cb), self, NULL); |
|
358 dbus_g_proxy_connect_signal (DBUS_G_PROXY (self), "PropertyFlagsChanged", |
|
359 G_CALLBACK(property_flags_changed_cb), |
|
360 self, NULL); |
|
361 |
|
362 tp_props_iface_list_properties_async (DBUS_G_PROXY (self), |
|
363 properties_listed_cb, self); |
|
364 } |
|
365 |
|
366 /** |
|
367 * tp_props_iface_get_value: |
|
368 * @self: #TpPropsIface on which to get a property value |
|
369 * @prop_id: Identifier for property as set in #tp_props_iface_set_mapping |
|
370 * @value: GValue to return the property's value in. |
|
371 * |
|
372 * Get the value of a property on this interface |
|
373 */ |
|
374 gboolean tp_props_iface_get_value (TpPropsIface* self, guint prop_id, |
|
375 GValue *return_value) |
|
376 { |
|
377 int i; |
|
378 |
|
379 if (!PRIV (self)->properties_ready) |
|
380 return FALSE; |
|
381 |
|
382 for (i = 0; i < PRIV (self)->mappings_len; i++) |
|
383 { |
|
384 if (PRIV (self)->mappings[i].user_id == prop_id) |
|
385 { |
|
386 if (PRIV (self)->mappings[i].value) |
|
387 { |
|
388 g_value_copy (PRIV (self)->mappings[i].value, return_value); |
|
389 return TRUE; |
|
390 } |
|
391 else |
|
392 { |
|
393 return FALSE; |
|
394 } |
|
395 } |
|
396 } |
|
397 |
|
398 return FALSE; |
|
399 } |
|
400 |
|
401 /* dummy callback handler for async calling calls with no return values */ |
|
402 static void |
|
403 dummy_callback (DBusGProxy *proxy, GError *error, gpointer user_data) |
|
404 { |
|
405 if (error) |
|
406 { |
|
407 g_warning ("%s calling %s", error->message, (char*)user_data); |
|
408 g_error_free (error); |
|
409 } |
|
410 } |
|
411 |
|
412 /** |
|
413 * tp_props_iface_set_value: |
|
414 * @self: #TpPropsIface on which to set a property value |
|
415 * @prop_id: Identifier for property as set in #tp_props_iface_set_mapping |
|
416 * @value: GValue to use to set the property's value |
|
417 * |
|
418 * Set the value of a property on this interface |
|
419 */ |
|
420 gboolean tp_props_iface_set_value (TpPropsIface* self, guint prop_id, |
|
421 const GValue *value) |
|
422 { |
|
423 /*TODO add option for an error callback*/ |
|
424 int i; |
|
425 GPtrArray *props; |
|
426 |
|
427 if (!PRIV(self)->properties_ready) |
|
428 return FALSE; |
|
429 |
|
430 for (i=0; i < PRIV(self)->mappings_len; i++) |
|
431 { |
|
432 if (PRIV(self)->mappings[i].user_id == prop_id) |
|
433 { |
|
434 GValue prop = {0,}; |
|
435 g_value_init (&prop, TP_TYPE_PROPERTY_CHANGE); |
|
436 g_value_take_boxed (&prop, |
|
437 dbus_g_type_specialized_construct (TP_TYPE_PROPERTY_CHANGE)); |
|
438 |
|
439 dbus_g_type_struct_set (&prop, |
|
440 0, PRIV(self)->mappings[i].server_id, |
|
441 1, value, |
|
442 G_MAXUINT); |
|
443 |
|
444 props = g_ptr_array_sized_new (1); |
|
445 g_ptr_array_add (props, g_value_get_boxed (&prop)); |
|
446 tp_props_iface_set_properties_async (DBUS_G_PROXY(self), props, |
|
447 dummy_callback, "SetProperties"); |
|
448 g_value_unset (&prop); |
|
449 g_ptr_array_free (props, TRUE); |
|
450 return TRUE; |
|
451 } |
|
452 } |
|
453 return FALSE; |
|
454 } |
|
455 |
|
456 |
|
457 static void |
|
458 set_properties_values (TpPropsIface *self, GPtrArray *properties) |
|
459 { |
|
460 int i,j; |
|
461 |
|
462 for (i = 0; i < properties->len; i++) |
|
463 { |
|
464 GValue property = {0}; |
|
465 guint32 id; |
|
466 GValue *value; |
|
467 |
|
468 g_value_init (&property, TP_TYPE_PROPERTY_CHANGE); |
|
469 g_value_set_static_boxed (&property, g_ptr_array_index (properties, i)); |
|
470 dbus_g_type_struct_get (&property, 0, &id, G_MAXUINT); |
|
471 |
|
472 for (j = 0; j < PRIV(self)->mappings_len; j++) |
|
473 { |
|
474 PropertyMapping *mapping = &(PRIV (self)->mappings[j]); |
|
475 |
|
476 if (mapping->server_id == id) |
|
477 { |
|
478 dbus_g_type_struct_get (&property, 1, &value, G_MAXUINT); |
|
479 g_assert (value); |
|
480 |
|
481 if (mapping->value) |
|
482 { |
|
483 g_value_unset (mapping->value); |
|
484 g_free (mapping->value); |
|
485 } |
|
486 |
|
487 mapping->value = value; |
|
488 value = NULL; /* just to be on the safe side... */ |
|
489 |
|
490 if (PRIV (self)->properties_ready) |
|
491 g_signal_emit (self, signals[PROPERTY_CHANGED], 0, |
|
492 mapping->user_id, TP_PROPS_CHANGED_VALUE); |
|
493 |
|
494 break; |
|
495 } |
|
496 } |
|
497 } |
|
498 |
|
499 } |
|
500 |
|
501 static void |
|
502 properties_changed_cb (DBusGProxy *proxy, GPtrArray *properties, |
|
503 gpointer user_data) |
|
504 { |
|
505 TpPropsIface *self = TELEPATHY_PROPS_IFACE (user_data); |
|
506 if (!PRIV(self)->properties_ready) |
|
507 return; |
|
508 set_properties_values (self, properties); |
|
509 } |
|
510 |
|
511 static void |
|
512 properties_got_cb (DBusGProxy *proxy, GPtrArray *properties, GError *error, gpointer user_data) |
|
513 { |
|
514 TpPropsIface *self = TELEPATHY_PROPS_IFACE (user_data); |
|
515 |
|
516 if (error) |
|
517 { |
|
518 g_debug ("getting properties failed: %s (%s)", error->message, |
|
519 dbus_g_error_get_name (error)); |
|
520 g_error_free (error); |
|
521 return; |
|
522 } |
|
523 |
|
524 set_properties_values (self, properties); |
|
525 |
|
526 if (!PRIV (self)->properties_ready) |
|
527 { |
|
528 PRIV (self)->properties_ready = TRUE; |
|
529 g_signal_emit (self, signals[PROPERTIES_READY], 0); |
|
530 } |
|
531 } |
|
532 |
|
533 static void |
|
534 property_flags_changed_cb (DBusGProxy *proxy, GPtrArray *properties, |
|
535 gpointer user_data) |
|
536 { |
|
537 TpPropsIface *self = TELEPATHY_PROPS_IFACE (user_data); |
|
538 GArray *get_props; |
|
539 int i, j; |
|
540 |
|
541 if (!PRIV(self)->properties_ready) |
|
542 return; |
|
543 |
|
544 get_props = g_array_sized_new (FALSE, FALSE, sizeof (guint32), |
|
545 properties->len); |
|
546 |
|
547 for (i = 0; i < properties->len; i++) |
|
548 { |
|
549 GValue property = {0}; |
|
550 guint32 id, flags; |
|
551 |
|
552 g_value_init (&property, TP_TYPE_PROPERTY_CHANGE); |
|
553 g_value_set_static_boxed (&property, g_ptr_array_index (properties, i)); |
|
554 dbus_g_type_struct_get (&property, 0, &id, G_MAXUINT); |
|
555 |
|
556 for (j = 0; j < PRIV (self)->mappings_len; j++) |
|
557 { |
|
558 PropertyMapping *mapping = &(PRIV (self)->mappings[j]); |
|
559 |
|
560 if (mapping->server_id == id) |
|
561 { |
|
562 dbus_g_type_struct_get (&property, 1, &flags, G_MAXUINT); |
|
563 |
|
564 if (!(mapping->flags & TP_PROPERTY_FLAG_READ) && |
|
565 flags & TP_PROPERTY_FLAG_READ) |
|
566 /* property has become readable; fetch it */ |
|
567 g_array_append_val (get_props, mapping->server_id); |
|
568 |
|
569 mapping->flags = flags; |
|
570 g_signal_emit (self, signals[PROPERTY_CHANGED], 0, |
|
571 mapping->user_id, TP_PROPS_CHANGED_FLAGS); |
|
572 break; |
|
573 } |
|
574 } |
|
575 } |
|
576 |
|
577 tp_props_iface_get_properties_async (DBUS_G_PROXY (self), get_props, |
|
578 properties_got_cb, self); |
|
579 g_array_free (get_props, TRUE); |
|
580 } |
|
581 |
|
582 static void |
|
583 properties_listed_cb (DBusGProxy *proxy, GPtrArray *properties, GError *error, gpointer user_data) |
|
584 { |
|
585 TpPropsIface *self = TELEPATHY_PROPS_IFACE (user_data); |
|
586 int i,j; |
|
587 guint32 id, flags; |
|
588 gchar *name; |
|
589 GArray *get_props; |
|
590 |
|
591 if (error) |
|
592 { |
|
593 g_debug ("listing properties failed: %s (%s)", error->message, |
|
594 dbus_g_error_get_name (error)); |
|
595 g_error_free (error); |
|
596 return; |
|
597 } |
|
598 |
|
599 for (i = 0; i < properties->len; i++) |
|
600 { |
|
601 GValue property = {0}; |
|
602 g_value_init (&property, TP_TYPE_PROPERTY_DESCRIPTION); |
|
603 g_value_set_static_boxed (&property, g_ptr_array_index (properties, i)); |
|
604 |
|
605 dbus_g_type_struct_get (&property, |
|
606 0, &id, |
|
607 1, &name, |
|
608 3, &flags, |
|
609 G_MAXUINT); |
|
610 |
|
611 for (j = 0; j < PRIV (self)->mappings_len; j++) |
|
612 { |
|
613 if (0 == strcmp (PRIV (self)->mappings[j].name, name)) |
|
614 { |
|
615 PRIV (self)->mappings[j].server_id = id; |
|
616 PRIV (self)->mappings[j].flags = flags; |
|
617 } |
|
618 } |
|
619 |
|
620 g_free (name); |
|
621 } |
|
622 |
|
623 get_props = g_array_sized_new (FALSE, FALSE, sizeof (guint32), |
|
624 properties->len); |
|
625 |
|
626 for (i = 0; i < PRIV(self)->mappings_len; i++) |
|
627 { |
|
628 PropertyMapping *mapping = &(PRIV(self)->mappings[i]); |
|
629 |
|
630 if (mapping->flags & TP_PROPERTY_FLAG_READ) |
|
631 g_array_append_val (get_props, mapping->server_id); |
|
632 } |
|
633 |
|
634 tp_props_iface_get_properties_async (DBUS_G_PROXY (self), get_props, |
|
635 properties_got_cb, self); |
|
636 g_array_free (get_props, TRUE); |
|
637 } |
|
638 |
|
639 void |
|
640 tp_props_interface_set_signatures (DBusGProxy *proxy) |
|
641 { |
|
642 dbus_g_proxy_add_signal(proxy, "PropertiesChanged", |
|
643 dbus_g_type_get_collection ("GPtrArray", |
|
644 dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, |
|
645 G_TYPE_VALUE, G_TYPE_INVALID)), |
|
646 G_TYPE_INVALID); |
|
647 dbus_g_proxy_add_signal(proxy, "PropertyFlagsChanged", |
|
648 dbus_g_type_get_collection ("GPtrArray", |
|
649 dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, |
|
650 G_TYPE_UINT, G_TYPE_INVALID)), |
|
651 G_TYPE_INVALID); |
|
652 } |
|
653 |