1 | #include <gio/gio.h> |
2 | #include <stdlib.h> |
3 | |
4 | static GDBusNodeInfo *introspection_data = NULL; |
5 | static GMainLoop *loop = NULL; |
6 | static GHashTable *properties = NULL; |
7 | |
8 | static const gchar introspection_xml[] = |
9 | "<node>" |
10 | " <interface name='com.example.Frob'>" |
11 | " <method name='Quit'>" |
12 | " </method>" |
13 | " <method name='TestArrayOfStringTypes'>" |
14 | " <arg direction='in' type='as' name='val_string' />" |
15 | " <arg direction='in' type='ao' name='val_objpath' />" |
16 | " <arg direction='in' type='ag' name='val_signature' />" |
17 | " <arg direction='out' type='as' />" |
18 | " <arg direction='out' type='ao' />" |
19 | " <arg direction='out' type='ag' />" |
20 | " </method>" |
21 | " <method name='TestPrimitiveTypes'>" |
22 | " <arg direction='in' type='y' name='val_byte' />" |
23 | " <arg direction='in' type='b' name='val_boolean' />" |
24 | " <arg direction='in' type='n' name='val_int16' />" |
25 | " <arg direction='in' type='q' name='val_uint16' />" |
26 | " <arg direction='in' type='i' name='val_int32' />" |
27 | " <arg direction='in' type='u' name='val_uint32' />" |
28 | " <arg direction='in' type='x' name='val_int64' />" |
29 | " <arg direction='in' type='t' name='val_uint64' />" |
30 | " <arg direction='in' type='d' name='val_double' />" |
31 | " <arg direction='in' type='s' name='val_string' />" |
32 | " <arg direction='in' type='o' name='val_objpath' />" |
33 | " <arg direction='in' type='g' name='val_signature' />" |
34 | " <arg direction='out' type='y' />" |
35 | " <arg direction='out' type='b' />" |
36 | " <arg direction='out' type='n' />" |
37 | " <arg direction='out' type='q' />" |
38 | " <arg direction='out' type='i' />" |
39 | " <arg direction='out' type='u' />" |
40 | " <arg direction='out' type='x' />" |
41 | " <arg direction='out' type='t' />" |
42 | " <arg direction='out' type='d' />" |
43 | " <arg direction='out' type='s' />" |
44 | " <arg direction='out' type='o' />" |
45 | " <arg direction='out' type='g' />" |
46 | " </method>" |
47 | " <method name='EmitSignal'>" |
48 | " <arg direction='in' type='s' name='str1' />" |
49 | " <arg direction='in' type='o' name='objpath1' />" |
50 | " </method>" |
51 | " <method name='TestArrayOfPrimitiveTypes'>" |
52 | " <arg direction='in' type='ay' name='val_byte' />" |
53 | " <arg direction='in' type='ab' name='val_boolean' />" |
54 | " <arg direction='in' type='an' name='val_int16' />" |
55 | " <arg direction='in' type='aq' name='val_uint16' />" |
56 | " <arg direction='in' type='ai' name='val_int32' />" |
57 | " <arg direction='in' type='au' name='val_uint32' />" |
58 | " <arg direction='in' type='ax' name='val_int64' />" |
59 | " <arg direction='in' type='at' name='val_uint64' />" |
60 | " <arg direction='in' type='ad' name='val_double' />" |
61 | " <arg direction='out' type='ay' />" |
62 | " <arg direction='out' type='ab' />" |
63 | " <arg direction='out' type='an' />" |
64 | " <arg direction='out' type='aq' />" |
65 | " <arg direction='out' type='ai' />" |
66 | " <arg direction='out' type='au' />" |
67 | " <arg direction='out' type='ax' />" |
68 | " <arg direction='out' type='at' />" |
69 | " <arg direction='out' type='ad' />" |
70 | " </method>" |
71 | " <method name='FrobSetProperty'>" |
72 | " <arg direction='in' type='s' name='prop_name' />" |
73 | " <arg direction='in' type='v' name='prop_value' />" |
74 | " </method>" |
75 | " <signal name='TestSignal'>" |
76 | " <arg type='s' name='str1' />" |
77 | " <arg type='o' name='objpath1' />" |
78 | " <arg type='v' name='variant1' />" |
79 | " </signal>" |
80 | " <method name='TestComplexArrays'>" |
81 | " <arg direction='in' type='a(ii)' name='aii' />" |
82 | " <arg direction='in' type='aa(ii)' name='aaii' />" |
83 | " <arg direction='in' type='aas' name='aas' />" |
84 | " <arg direction='in' type='aa{ss}' name='ahashes' />" |
85 | " <arg direction='in' type='aay' name='aay' />" |
86 | " <arg direction='in' type='av' name='av' />" |
87 | " <arg direction='in' type='aav' name='aav' />" |
88 | " <arg direction='out' type='a(ii)' />" |
89 | " <arg direction='out' type='aa(ii)' />" |
90 | " <arg direction='out' type='aas' />" |
91 | " <arg direction='out' type='aa{ss}' />" |
92 | " <arg direction='out' type='aay' />" |
93 | " <arg direction='out' type='av' />" |
94 | " <arg direction='out' type='aav' />" |
95 | " </method>" |
96 | " <method name='TestVariant'>" |
97 | " <arg direction='in' type='v' name='v' />" |
98 | " <arg direction='in' type='b' name='modify' />" |
99 | " <arg direction='out' type='v' />" |
100 | " </method>" |
101 | " <method name='FrobInvalidateProperty'>" |
102 | " <arg direction='in' type='s' name='new_value' />" |
103 | " </method>" |
104 | " <method name='HelloWorld'>" |
105 | " <arg direction='in' type='s' name='hello_message' />" |
106 | " <arg direction='out' type='s' />" |
107 | " </method>" |
108 | " <method name='PairReturn'>" |
109 | " <arg direction='out' type='s' />" |
110 | " <arg direction='out' type='u' />" |
111 | " </method>" |
112 | " <method name='TestStructureTypes'>" |
113 | " <arg direction='in' type='(ii)' name='s1' />" |
114 | " <arg direction='in' type='(s(ii)aya{ss})' name='s2' />" |
115 | " <arg direction='out' type='(ii)' />" |
116 | " <arg direction='out' type='(s(ii)aya{ss})' />" |
117 | " </method>" |
118 | " <method name='EmitSignal2'>" |
119 | " </method>" |
120 | " <method name='DoubleHelloWorld'>" |
121 | " <arg direction='in' type='s' name='hello1' />" |
122 | " <arg direction='in' type='s' name='hello2' />" |
123 | " <arg direction='out' type='s' />" |
124 | " <arg direction='out' type='s' />" |
125 | " </method>" |
126 | " <method name='Sleep'>" |
127 | " <arg direction='in' type='i' name='msec' />" |
128 | " </method>" |
129 | " <method name='TestHashTables'>" |
130 | " <arg direction='in' type='a{yy}' name='hyy' />" |
131 | " <arg direction='in' type='a{bb}' name='hbb' />" |
132 | " <arg direction='in' type='a{nn}' name='hnn' />" |
133 | " <arg direction='in' type='a{qq}' name='hqq' />" |
134 | " <arg direction='in' type='a{ii}' name='hii' />" |
135 | " <arg direction='in' type='a{uu}' name='huu' />" |
136 | " <arg direction='in' type='a{xx}' name='hxx' />" |
137 | " <arg direction='in' type='a{tt}' name='htt' />" |
138 | " <arg direction='in' type='a{dd}' name='hdd' />" |
139 | " <arg direction='in' type='a{ss}' name='hss' />" |
140 | " <arg direction='in' type='a{oo}' name='hoo' />" |
141 | " <arg direction='in' type='a{gg}' name='hgg' />" |
142 | " <arg direction='out' type='a{yy}' />" |
143 | " <arg direction='out' type='a{bb}' />" |
144 | " <arg direction='out' type='a{nn}' />" |
145 | " <arg direction='out' type='a{qq}' />" |
146 | " <arg direction='out' type='a{ii}' />" |
147 | " <arg direction='out' type='a{uu}' />" |
148 | " <arg direction='out' type='a{xx}' />" |
149 | " <arg direction='out' type='a{tt}' />" |
150 | " <arg direction='out' type='a{dd}' />" |
151 | " <arg direction='out' type='a{ss}' />" |
152 | " <arg direction='out' type='a{oo}' />" |
153 | " <arg direction='out' type='a{gg}' />" |
154 | " </method>" |
155 | " <signal name='TestSignal2'>" |
156 | " <arg type='i' name='int1' />" |
157 | " </signal>" |
158 | " <method name='TestComplexHashTables'>" |
159 | " <arg direction='in' type='a{s(ii)}' name='h_str_to_pair' />" |
160 | " <arg direction='in' type='a{sv}' name='h_str_to_variant' />" |
161 | " <arg direction='in' type='a{sav}' name='h_str_to_av' />" |
162 | " <arg direction='in' type='a{saav}' name='h_str_to_aav' />" |
163 | " <arg direction='in' type='a{sa(ii)}' name='h_str_to_array_of_pairs' />" |
164 | " <arg direction='in' type='a{sa{ss}}' name='hash_of_hashes' />" |
165 | " <arg direction='out' type='a{s(ii)}' />" |
166 | " <arg direction='out' type='a{sv}' />" |
167 | " <arg direction='out' type='a{sav}' />" |
168 | " <arg direction='out' type='a{saav}' />" |
169 | " <arg direction='out' type='a{sa(ii)}' />" |
170 | " <arg direction='out' type='a{sa{ss}}' />" |
171 | " </method>" |
172 | " <property type='y' name='y' access='readwrite' />" |
173 | " <property type='b' name='b' access='readwrite' />" |
174 | " <property type='n' name='n' access='readwrite' />" |
175 | " <property type='q' name='q' access='readwrite' />" |
176 | " <property type='i' name='i' access='readwrite' />" |
177 | " <property type='u' name='u' access='readwrite' />" |
178 | " <property type='x' name='x' access='readwrite' />" |
179 | " <property type='t' name='t' access='readwrite' />" |
180 | " <property type='d' name='d' access='readwrite' />" |
181 | " <property type='s' name='s' access='readwrite' />" |
182 | " <property type='o' name='o' access='readwrite' />" |
183 | " <property type='ay' name='ay' access='readwrite' />" |
184 | " <property type='ab' name='ab' access='readwrite' />" |
185 | " <property type='an' name='an' access='readwrite' />" |
186 | " <property type='aq' name='aq' access='readwrite' />" |
187 | " <property type='ai' name='ai' access='readwrite' />" |
188 | " <property type='au' name='au' access='readwrite' />" |
189 | " <property type='ax' name='ax' access='readwrite' />" |
190 | " <property type='at' name='at' access='readwrite' />" |
191 | " <property type='ad' name='ad' access='readwrite' />" |
192 | " <property type='as' name='as' access='readwrite' />" |
193 | " <property type='ao' name='ao' access='readwrite' />" |
194 | " <property type='s' name='foo' access='readwrite' />" |
195 | " <property type='s' name='PropertyThatWillBeInvalidated' access='readwrite' />" |
196 | " </interface>" |
197 | "</node>" ; |
198 | |
199 | static gboolean |
200 | end_sleep (gpointer data) |
201 | { |
202 | GDBusMethodInvocation *invocation = data; |
203 | |
204 | g_dbus_method_invocation_return_value (invocation, NULL); |
205 | g_object_unref (object: invocation); |
206 | |
207 | return G_SOURCE_REMOVE; |
208 | } |
209 | |
210 | static void |
211 | handle_method_call (GDBusConnection *connection, |
212 | const gchar *sender, |
213 | const gchar *object_path, |
214 | const gchar *interface_name, |
215 | const gchar *method_name, |
216 | GVariant *parameters, |
217 | GDBusMethodInvocation *invocation, |
218 | gpointer user_data) |
219 | { |
220 | if (g_strcmp0 (str1: method_name, str2: "HelloWorld" ) == 0) |
221 | { |
222 | const gchar *greeting; |
223 | |
224 | g_variant_get (value: parameters, format_string: "(&s)" , &greeting); |
225 | if (g_strcmp0 (str1: greeting, str2: "Yo" ) == 0) |
226 | { |
227 | g_dbus_method_invocation_return_dbus_error (invocation, |
228 | error_name: "com.example.TestException" , |
229 | error_message: "Yo is not a proper greeting" ); |
230 | } |
231 | else |
232 | { |
233 | gchar *response; |
234 | response = g_strdup_printf (format: "You greeted me with '%s'. Thanks!" , greeting); |
235 | g_dbus_method_invocation_return_value (invocation, |
236 | parameters: g_variant_new (format_string: "(s)" , response)); |
237 | g_free ( mem: response); |
238 | } |
239 | } |
240 | else if (g_strcmp0 (str1: method_name, str2: "DoubleHelloWorld" ) == 0) |
241 | { |
242 | const gchar *hello1, *hello2; |
243 | gchar *reply1, *reply2; |
244 | |
245 | g_variant_get (value: parameters, format_string: "(&s&s)" , &hello1, &hello2); |
246 | reply1 = g_strdup_printf (format: "You greeted me with '%s'. Thanks!" , hello1); |
247 | reply2 = g_strdup_printf (format: "Yo dawg, you uttered '%s'. Thanks!" , hello2); |
248 | g_dbus_method_invocation_return_value (invocation, |
249 | parameters: g_variant_new (format_string: "(ss)" , reply1, reply2)); |
250 | g_free (mem: reply1); |
251 | g_free (mem: reply2); |
252 | } |
253 | else if (g_strcmp0 (str1: method_name, str2: "PairReturn" ) == 0) |
254 | { |
255 | g_dbus_method_invocation_return_value (invocation, |
256 | parameters: g_variant_new (format_string: "(su)" , "foo" , 42)); |
257 | } |
258 | else if (g_strcmp0 (str1: method_name, str2: "TestPrimitiveTypes" ) == 0) |
259 | { |
260 | guchar val_byte; |
261 | gboolean val_boolean; |
262 | gint16 val_int16; |
263 | guint16 val_uint16; |
264 | gint32 val_int32; |
265 | guint32 val_uint32; |
266 | gint64 val_int64; |
267 | guint64 val_uint64; |
268 | gdouble val_double; |
269 | const gchar *val_string; |
270 | const gchar *val_objpath; |
271 | const gchar *val_signature; |
272 | gchar *ret_string; |
273 | gchar *ret_objpath; |
274 | gchar *ret_signature; |
275 | |
276 | g_variant_get (value: parameters, format_string: "(ybnqiuxtd&s&o&g)" , |
277 | &val_byte, |
278 | &val_boolean, |
279 | &val_int16, |
280 | &val_uint16, |
281 | &val_int32, |
282 | &val_uint32, |
283 | &val_int64, |
284 | &val_uint64, |
285 | &val_double, |
286 | &val_string, |
287 | &val_objpath, |
288 | &val_signature); |
289 | |
290 | ret_string = g_strconcat (string1: val_string, val_string, NULL); |
291 | ret_objpath = g_strconcat (string1: val_objpath, "/modified" , NULL); |
292 | ret_signature = g_strconcat (string1: val_signature, val_signature, NULL); |
293 | |
294 | g_dbus_method_invocation_return_value (invocation, |
295 | parameters: g_variant_new (format_string: "(ybnqiuxtdsog)" , |
296 | val_byte + 1, |
297 | !val_boolean, |
298 | val_int16 + 1, |
299 | val_uint16 + 1, |
300 | val_int32 + 1, |
301 | val_uint32 + 1, |
302 | val_int64 + 1, |
303 | val_uint64 + 1, |
304 | - val_double + 0.123, |
305 | ret_string, |
306 | ret_objpath, |
307 | ret_signature)); |
308 | |
309 | g_free (mem: ret_string); |
310 | g_free (mem: ret_objpath); |
311 | g_free (mem: ret_signature); |
312 | } |
313 | else if (g_strcmp0 (str1: method_name, str2: "TestArrayOfPrimitiveTypes" ) == 0) |
314 | { |
315 | GVariant *v; |
316 | const guchar *bytes; |
317 | const gint16 *int16s; |
318 | const guint16 *uint16s; |
319 | const gint32 *int32s; |
320 | const guint32 *uint32s; |
321 | const gint64 *int64s; |
322 | const guint64 *uint64s; |
323 | const gdouble *doubles; |
324 | gsize n_elts; |
325 | gint i, j; |
326 | GVariantBuilder ret; |
327 | |
328 | g_variant_builder_init (builder: &ret, G_VARIANT_TYPE ("(ayabanaqaiauaxatad)" )); |
329 | |
330 | v = g_variant_get_child_value (value: parameters, index_: 0); |
331 | bytes = g_variant_get_fixed_array (value: v, n_elements: &n_elts, element_size: 1); |
332 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("ay" )); |
333 | for (j = 0; j < 2; j++) |
334 | for (i = 0; i < n_elts; i++) |
335 | g_variant_builder_add (builder: &ret, format_string: "y" , bytes[i]); |
336 | g_variant_builder_close (builder: &ret); |
337 | g_variant_unref (value: v); |
338 | |
339 | v = g_variant_get_child_value (value: parameters, index_: 1); |
340 | bytes = g_variant_get_fixed_array (value: v, n_elements: &n_elts, element_size: 1); |
341 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("ab" )); |
342 | for (j = 0; j < 2; j++) |
343 | for (i = 0; i < n_elts; i++) |
344 | g_variant_builder_add (builder: &ret, format_string: "b" , (gboolean)bytes[i]); |
345 | g_variant_builder_close (builder: &ret); |
346 | g_variant_unref (value: v); |
347 | |
348 | v = g_variant_get_child_value (value: parameters, index_: 2); |
349 | int16s = g_variant_get_fixed_array (value: v, n_elements: &n_elts, element_size: 2); |
350 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("an" )); |
351 | for (j = 0; j < 2; j++) |
352 | for (i = 0; i < n_elts; i++) |
353 | g_variant_builder_add (builder: &ret, format_string: "n" , int16s[i]); |
354 | g_variant_builder_close (builder: &ret); |
355 | g_variant_unref (value: v); |
356 | |
357 | v = g_variant_get_child_value (value: parameters, index_: 3); |
358 | uint16s = g_variant_get_fixed_array (value: v, n_elements: &n_elts, element_size: 2); |
359 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("aq" )); |
360 | for (j = 0; j < 2; j++) |
361 | for (i = 0; i < n_elts; i++) |
362 | g_variant_builder_add (builder: &ret, format_string: "q" , uint16s[i]); |
363 | g_variant_builder_close (builder: &ret); |
364 | g_variant_unref (value: v); |
365 | |
366 | v = g_variant_get_child_value (value: parameters, index_: 4); |
367 | int32s = g_variant_get_fixed_array (value: v, n_elements: &n_elts, element_size: 4); |
368 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("ai" )); |
369 | for (j = 0; j < 2; j++) |
370 | for (i = 0; i < n_elts; i++) |
371 | g_variant_builder_add (builder: &ret, format_string: "i" , int32s[i]); |
372 | g_variant_builder_close (builder: &ret); |
373 | g_variant_unref (value: v); |
374 | |
375 | v = g_variant_get_child_value (value: parameters, index_: 5); |
376 | uint32s = g_variant_get_fixed_array (value: v, n_elements: &n_elts, element_size: 4); |
377 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("au" )); |
378 | for (j = 0; j < 2; j++) |
379 | for (i = 0; i < n_elts; i++) |
380 | g_variant_builder_add (builder: &ret, format_string: "u" , uint32s[i]); |
381 | g_variant_builder_close (builder: &ret); |
382 | g_variant_unref (value: v); |
383 | |
384 | v = g_variant_get_child_value (value: parameters, index_: 6); |
385 | int64s = g_variant_get_fixed_array (value: v, n_elements: &n_elts, element_size: 8); |
386 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("ax" )); |
387 | for (j = 0; j < 2; j++) |
388 | for (i = 0; i < n_elts; i++) |
389 | g_variant_builder_add (builder: &ret, format_string: "x" , int64s[i]); |
390 | g_variant_builder_close (builder: &ret); |
391 | g_variant_unref (value: v); |
392 | |
393 | v = g_variant_get_child_value (value: parameters, index_: 7); |
394 | uint64s = g_variant_get_fixed_array (value: v, n_elements: &n_elts, element_size: 8); |
395 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("at" )); |
396 | for (j = 0; j < 2; j++) |
397 | for (i = 0; i < n_elts; i++) |
398 | g_variant_builder_add (builder: &ret, format_string: "t" , uint64s[i]); |
399 | g_variant_builder_close (builder: &ret); |
400 | g_variant_unref (value: v); |
401 | |
402 | v = g_variant_get_child_value (value: parameters, index_: 8); |
403 | doubles = g_variant_get_fixed_array (value: v, n_elements: &n_elts, element_size: sizeof (gdouble)); |
404 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("ad" )); |
405 | for (j = 0; j < 2; j++) |
406 | for (i = 0; i < n_elts; i++) |
407 | g_variant_builder_add (builder: &ret, format_string: "d" , doubles[i]); |
408 | g_variant_builder_close (builder: &ret); |
409 | g_variant_unref (value: v); |
410 | |
411 | g_dbus_method_invocation_return_value (invocation, |
412 | parameters: g_variant_builder_end (builder: &ret)); |
413 | } |
414 | else if (g_strcmp0 (str1: method_name, str2: "TestArrayOfStringTypes" ) == 0) |
415 | { |
416 | GVariantIter *iter1; |
417 | GVariantIter *iter2; |
418 | GVariantIter *iter3; |
419 | GVariantIter *iter; |
420 | GVariantBuilder ret; |
421 | const gchar *s; |
422 | gint i; |
423 | |
424 | g_variant_builder_init (builder: &ret, G_VARIANT_TYPE ("(asaoag)" )); |
425 | g_variant_get (value: parameters, format_string: "(asaoag)" , &iter1, &iter2, &iter3); |
426 | |
427 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("as" )); |
428 | for (i = 0; i < 2; i++) |
429 | { |
430 | iter = g_variant_iter_copy (iter: iter1); |
431 | while (g_variant_iter_loop (iter, format_string: "s" , &s)) |
432 | g_variant_builder_add (builder: &ret, format_string: "s" , s); |
433 | g_variant_iter_free (iter); |
434 | } |
435 | g_variant_builder_close (builder: &ret); |
436 | |
437 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("ao" )); |
438 | for (i = 0; i < 2; i++) |
439 | { |
440 | iter = g_variant_iter_copy (iter: iter1); |
441 | while (g_variant_iter_loop (iter, format_string: "o" , &s)) |
442 | g_variant_builder_add (builder: &ret, format_string: "o" , s); |
443 | g_variant_iter_free (iter); |
444 | } |
445 | g_variant_builder_close (builder: &ret); |
446 | |
447 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("ag" )); |
448 | for (i = 0; i < 2; i++) |
449 | { |
450 | iter = g_variant_iter_copy (iter: iter1); |
451 | while (g_variant_iter_loop (iter, format_string: "g" , &s)) |
452 | g_variant_builder_add (builder: &ret, format_string: "g" , s); |
453 | g_variant_iter_free (iter); |
454 | } |
455 | g_variant_builder_close (builder: &ret); |
456 | |
457 | g_variant_iter_free (iter: iter1); |
458 | g_variant_iter_free (iter: iter2); |
459 | g_variant_iter_free (iter: iter3); |
460 | |
461 | g_dbus_method_invocation_return_value (invocation, |
462 | parameters: g_variant_builder_end (builder: &ret)); |
463 | } |
464 | else if (g_strcmp0 (str1: method_name, str2: "TestHashTables" ) == 0) |
465 | { |
466 | GVariant *v; |
467 | GVariantIter iter; |
468 | GVariantBuilder ret; |
469 | guint8 y1, y2; |
470 | gboolean b1, b2; |
471 | gint16 n1, n2; |
472 | guint16 q1, q2; |
473 | gint i1, i2; |
474 | guint u1, u2; |
475 | gint64 x1, x2; |
476 | guint64 t1, t2; |
477 | gdouble d1, d2; |
478 | gchar *s1, *s2; |
479 | |
480 | g_variant_builder_init (builder: &ret, G_VARIANT_TYPE ("(a{yy}a{bb}a{nn}a{qq}a{ii}a{uu}a{xx}a{tt}a{dd}a{ss}a{oo}a{gg})" )); |
481 | |
482 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("a{yy}" )); |
483 | v = g_variant_get_child_value (value: parameters, index_: 0); |
484 | g_variant_iter_init (iter: &iter, value: v); |
485 | while (g_variant_iter_loop (iter: &iter, format_string: "yy" , &y1, &y2)) |
486 | g_variant_builder_add (builder: &ret, format_string: "{yy}" , y1 * 2, (y2 * 3) & 255); |
487 | g_variant_unref (value: v); |
488 | g_variant_builder_close (builder: &ret); |
489 | |
490 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("a{bb}" )); |
491 | v = g_variant_get_child_value (value: parameters, index_: 1); |
492 | g_variant_iter_init (iter: &iter, value: v); |
493 | while (g_variant_iter_loop (iter: &iter, format_string: "bb" , &b1, &b2)) |
494 | g_variant_builder_add (builder: &ret, format_string: "{bb}" , b1, TRUE); |
495 | g_variant_unref (value: v); |
496 | g_variant_builder_close (builder: &ret); |
497 | |
498 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("a{nn}" )); |
499 | v = g_variant_get_child_value (value: parameters, index_: 2); |
500 | g_variant_iter_init (iter: &iter, value: v); |
501 | while (g_variant_iter_loop (iter: &iter, format_string: "nn" , &n1, &n2)) |
502 | g_variant_builder_add (builder: &ret, format_string: "{nn}" , n1 * 2, n2 * 3); |
503 | g_variant_unref (value: v); |
504 | g_variant_builder_close (builder: &ret); |
505 | |
506 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("a{qq}" )); |
507 | v = g_variant_get_child_value (value: parameters, index_: 3); |
508 | g_variant_iter_init (iter: &iter, value: v); |
509 | while (g_variant_iter_loop (iter: &iter, format_string: "qq" , &q1, &q2)) |
510 | g_variant_builder_add (builder: &ret, format_string: "{qq}" , q1 * 2, q2 * 3); |
511 | g_variant_unref (value: v); |
512 | g_variant_builder_close (builder: &ret); |
513 | |
514 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("a{ii}" )); |
515 | v = g_variant_get_child_value (value: parameters, index_: 4); |
516 | g_variant_iter_init (iter: &iter, value: v); |
517 | while (g_variant_iter_loop (iter: &iter, format_string: "ii" , &i1, &i2)) |
518 | g_variant_builder_add (builder: &ret, format_string: "{ii}" , i1 * 2, i2 * 3); |
519 | g_variant_unref (value: v); |
520 | g_variant_builder_close (builder: &ret); |
521 | |
522 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("a{uu}" )); |
523 | v = g_variant_get_child_value (value: parameters, index_: 5); |
524 | g_variant_iter_init (iter: &iter, value: v); |
525 | while (g_variant_iter_loop (iter: &iter, format_string: "uu" , &u1, &u2)) |
526 | g_variant_builder_add (builder: &ret, format_string: "{uu}" , u1 * 2, u2 * 3); |
527 | g_variant_unref (value: v); |
528 | g_variant_builder_close (builder: &ret); |
529 | |
530 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("a{xx}" )); |
531 | v = g_variant_get_child_value (value: parameters, index_: 6); |
532 | g_variant_iter_init (iter: &iter, value: v); |
533 | while (g_variant_iter_loop (iter: &iter, format_string: "xx" , &x1, &x2)) |
534 | g_variant_builder_add (builder: &ret, format_string: "{xx}" , x1 + 2, x2 + 1); |
535 | g_variant_unref (value: v); |
536 | g_variant_builder_close (builder: &ret); |
537 | |
538 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("a{tt}" )); |
539 | v = g_variant_get_child_value (value: parameters, index_: 7); |
540 | g_variant_iter_init (iter: &iter, value: v); |
541 | while (g_variant_iter_loop (iter: &iter, format_string: "tt" , &t1, &t2)) |
542 | g_variant_builder_add (builder: &ret, format_string: "{tt}" , t1 + 2, t2 + 1); |
543 | g_variant_unref (value: v); |
544 | g_variant_builder_close (builder: &ret); |
545 | |
546 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("a{dd}" )); |
547 | v = g_variant_get_child_value (value: parameters, index_: 8); |
548 | g_variant_iter_init (iter: &iter, value: v); |
549 | while (g_variant_iter_loop (iter: &iter, format_string: "dd" , &d1, &d2)) |
550 | g_variant_builder_add (builder: &ret, format_string: "{dd}" , d1 + 2.5, d2 + 5.0); |
551 | g_variant_unref (value: v); |
552 | g_variant_builder_close (builder: &ret); |
553 | |
554 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("a{ss}" )); |
555 | v = g_variant_get_child_value (value: parameters, index_: 9); |
556 | g_variant_iter_init (iter: &iter, value: v); |
557 | while (g_variant_iter_loop (iter: &iter, format_string: "ss" , &s1, &s2)) |
558 | { |
559 | gchar *tmp1, *tmp2; |
560 | tmp1 = g_strconcat (string1: s1, "mod" , NULL); |
561 | tmp2 = g_strconcat (string1: s2, s2, NULL); |
562 | g_variant_builder_add (builder: &ret, format_string: "{ss}" , tmp1, tmp2); |
563 | g_free (mem: tmp1); |
564 | g_free (mem: tmp2); |
565 | } |
566 | g_variant_unref (value: v); |
567 | g_variant_builder_close (builder: &ret); |
568 | |
569 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("a{oo}" )); |
570 | v = g_variant_get_child_value (value: parameters, index_: 10); |
571 | g_variant_iter_init (iter: &iter, value: v); |
572 | while (g_variant_iter_loop (iter: &iter, format_string: "oo" , &s1, &s2)) |
573 | { |
574 | gchar *tmp1, *tmp2; |
575 | tmp1 = g_strconcat (string1: s1, "/mod" , NULL); |
576 | tmp2 = g_strconcat (string1: s2, "/mod2" , NULL); |
577 | g_variant_builder_add (builder: &ret, format_string: "{oo}" , tmp1, tmp2); |
578 | g_free (mem: tmp1); |
579 | g_free (mem: tmp2); |
580 | } |
581 | g_variant_unref (value: v); |
582 | g_variant_builder_close (builder: &ret); |
583 | |
584 | g_variant_builder_open (builder: &ret, G_VARIANT_TYPE ("a{gg}" )); |
585 | v = g_variant_get_child_value (value: parameters, index_: 11); |
586 | g_variant_iter_init (iter: &iter, value: v); |
587 | while (g_variant_iter_loop (iter: &iter, format_string: "gg" , &s1, &s2)) |
588 | { |
589 | gchar *tmp1, *tmp2; |
590 | tmp1 = g_strconcat (string1: s1, "assgit" , NULL); |
591 | tmp2 = g_strconcat (string1: s2, s2, NULL); |
592 | g_variant_builder_add (builder: &ret, format_string: "{gg}" , tmp1, tmp2); |
593 | g_free (mem: tmp1); |
594 | g_free (mem: tmp2); |
595 | } |
596 | g_variant_unref (value: v); |
597 | g_variant_builder_close (builder: &ret); |
598 | |
599 | g_dbus_method_invocation_return_value (invocation, |
600 | parameters: g_variant_builder_end (builder: &ret)); |
601 | } |
602 | else if (g_strcmp0 (str1: method_name, str2: "TestStructureTypes" ) == 0) |
603 | { |
604 | gint x, y, x1, y1; |
605 | const gchar *desc; |
606 | GVariantIter *iter1, *iter2; |
607 | gchar *desc_ret; |
608 | GVariantBuilder ret1, ret2; |
609 | GVariantIter *iter; |
610 | GVariant *v; |
611 | gchar *s1, *s2; |
612 | |
613 | g_variant_get (value: parameters, format_string: "((ii)(&s(ii)aya{ss}))" , |
614 | &x, &y, &desc, &x1, &y1, &iter1, &iter2); |
615 | |
616 | desc_ret = g_strconcat (string1: desc, "... in bed!" , NULL); |
617 | |
618 | g_variant_builder_init (builder: &ret1, G_VARIANT_TYPE ("ay" )); |
619 | iter = g_variant_iter_copy (iter: iter1); |
620 | while (g_variant_iter_loop (iter: iter1, format_string: "y" , &v)) |
621 | g_variant_builder_add (builder: &ret1, format_string: "y" , v); |
622 | while (g_variant_iter_loop (iter, format_string: "y" , &v)) |
623 | g_variant_builder_add (builder: &ret1, format_string: "y" , v); |
624 | g_variant_iter_free (iter); |
625 | g_variant_iter_free (iter: iter1); |
626 | |
627 | g_variant_builder_init (builder: &ret2, G_VARIANT_TYPE ("a{ss}" )); |
628 | while (g_variant_iter_loop (iter: iter1, format_string: "ss" , &s1, &s2)) |
629 | { |
630 | gchar *tmp; |
631 | tmp = g_strconcat (string1: s2, " ... in bed!" , NULL); |
632 | g_variant_builder_add (builder: &ret1, format_string: "{ss}" , s1, tmp); |
633 | g_free (mem: tmp); |
634 | } |
635 | g_variant_iter_free (iter: iter2); |
636 | |
637 | g_dbus_method_invocation_return_value (invocation, |
638 | parameters: g_variant_new (format_string: "((ii)(&s(ii)aya{ss}))" , |
639 | x + 1, y + 1, desc_ret, x1 + 2, y1 + 2, |
640 | &ret1, &ret2)); |
641 | |
642 | g_free (mem: desc_ret); |
643 | } |
644 | else if (g_strcmp0 (str1: method_name, str2: "TestVariant" ) == 0) |
645 | { |
646 | GVariant *v; |
647 | gboolean modify; |
648 | GVariant *ret; |
649 | |
650 | g_variant_get (value: parameters, format_string: "(vb)" , &v, &modify); |
651 | |
652 | /* FIXME handle more cases */ |
653 | if (modify) |
654 | { |
655 | if (g_variant_is_of_type (value: v, G_VARIANT_TYPE_BOOLEAN)) |
656 | { |
657 | ret = g_variant_new_boolean (FALSE); |
658 | } |
659 | else if (g_variant_is_of_type (value: v, G_VARIANT_TYPE_TUPLE)) |
660 | { |
661 | ret = g_variant_new (format_string: "(si)" , "other struct" , 100); |
662 | } |
663 | else |
664 | g_assert_not_reached (); |
665 | } |
666 | else |
667 | ret = v; |
668 | |
669 | g_dbus_method_invocation_return_value (invocation, parameters: ret); |
670 | g_variant_unref (value: v); |
671 | } |
672 | else if (g_strcmp0 (str1: method_name, str2: "TestComplexArrays" ) == 0) |
673 | { |
674 | /* FIXME */ |
675 | g_dbus_method_invocation_return_value (invocation, parameters); |
676 | } |
677 | else if (g_strcmp0 (str1: method_name, str2: "TestComplexHashTables" ) == 0) |
678 | { |
679 | /* FIXME */ |
680 | g_dbus_method_invocation_return_value (invocation, parameters); |
681 | } |
682 | else if (g_strcmp0 (str1: method_name, str2: "FrobSetProperty" ) == 0) |
683 | { |
684 | gchar *name; |
685 | GVariant *value; |
686 | g_variant_get (value: parameters, format_string: "(sv)" , &name, &value); |
687 | g_hash_table_replace (hash_table: properties, key: name, value); |
688 | g_dbus_connection_emit_signal (connection, |
689 | NULL, |
690 | object_path: "/com/example/TestObject" , |
691 | interface_name: "org.freedesktop.DBus.Properties" , |
692 | signal_name: "PropertiesChanged" , |
693 | parameters: g_variant_new_parsed (format: "('com.example.Frob', [{%s, %v}], @as [])" , name, value), |
694 | NULL); |
695 | g_dbus_method_invocation_return_value (invocation, NULL); |
696 | } |
697 | else if (g_strcmp0 (str1: method_name, str2: "FrobInvalidateProperty" ) == 0) |
698 | { |
699 | const gchar *value; |
700 | g_variant_get (value: parameters, format_string: "(&s)" , &value); |
701 | g_hash_table_replace (hash_table: properties, key: g_strdup (str: "PropertyThatWillBeInvalidated" ), value: g_variant_ref_sink (value: g_variant_new_string (string: value))); |
702 | |
703 | g_dbus_connection_emit_signal (connection, |
704 | NULL, |
705 | object_path: "/com/example/TestObject" , |
706 | interface_name: "org.freedesktop.DBus.Properties" , |
707 | signal_name: "PropertiesChanged" , |
708 | parameters: g_variant_new_parsed (format: "('com.example.Frob', @a{sv} [], ['PropertyThatWillBeInvalidated'])" ), |
709 | NULL); |
710 | g_dbus_method_invocation_return_value (invocation, NULL); |
711 | } |
712 | else if (g_strcmp0 (str1: method_name, str2: "EmitSignal" ) == 0) |
713 | { |
714 | const gchar *str; |
715 | const gchar *path; |
716 | gchar *str_ret; |
717 | gchar *path_ret; |
718 | g_variant_get (value: parameters, format_string: "(&s&o)" , &str, &path); |
719 | str_ret = g_strconcat (string1: str, " .. in bed!" , NULL); |
720 | path_ret = g_strconcat (string1: path, "/in/bed" , NULL); |
721 | g_dbus_connection_emit_signal (connection, |
722 | NULL, |
723 | object_path: "/com/example/TestObject" , |
724 | interface_name: "com.example.Frob" , |
725 | signal_name: "TestSignal" , |
726 | parameters: g_variant_new_parsed (format: "(%s, %o, <'a variant'>)" , str_ret, path_ret), |
727 | NULL); |
728 | g_free (mem: str_ret); |
729 | g_free (mem: path_ret); |
730 | g_dbus_method_invocation_return_value (invocation, NULL); |
731 | } |
732 | else if (g_strcmp0 (str1: method_name, str2: "EmitSignal2" ) == 0) |
733 | { |
734 | g_dbus_connection_emit_signal (connection, |
735 | NULL, |
736 | object_path: "/com/example/TestObject" , |
737 | interface_name: "com.example.Frob" , |
738 | signal_name: "TestSignal2" , |
739 | parameters: g_variant_new_parsed (format: "(42, )" ), |
740 | NULL); |
741 | g_dbus_method_invocation_return_value (invocation, NULL); |
742 | } |
743 | else if (g_strcmp0 (str1: method_name, str2: "Sleep" ) == 0) |
744 | { |
745 | gint msec; |
746 | |
747 | g_variant_get (value: parameters, format_string: "(i)" , &msec); |
748 | |
749 | g_timeout_add (interval: (guint)msec, function: end_sleep, g_object_ref (invocation)); |
750 | } |
751 | else if (g_strcmp0 (str1: method_name, str2: "Quit" ) == 0) |
752 | { |
753 | g_dbus_method_invocation_return_value (invocation, NULL); |
754 | g_main_loop_quit (loop); |
755 | } |
756 | } |
757 | |
758 | static GVariant * |
759 | handle_get_property (GDBusConnection *connection, |
760 | const gchar *sender, |
761 | const gchar *object_path, |
762 | const gchar *interface_name, |
763 | const gchar *property_name, |
764 | GError **error, |
765 | gpointer user_data) |
766 | { |
767 | GVariant *ret; |
768 | |
769 | ret = g_hash_table_lookup (hash_table: properties, key: property_name); |
770 | if (ret) |
771 | { |
772 | g_assert (!g_variant_is_floating (ret)); |
773 | g_variant_ref (value: ret); |
774 | } |
775 | else |
776 | { |
777 | g_set_error (err: error, |
778 | G_DBUS_ERROR, code: G_DBUS_ERROR_FAILED, |
779 | format: "no such property: %s" , property_name); |
780 | } |
781 | |
782 | return ret; |
783 | } |
784 | |
785 | static gboolean |
786 | handle_set_property (GDBusConnection *connection, |
787 | const gchar *sender, |
788 | const gchar *object_path, |
789 | const gchar *interface_name, |
790 | const gchar *property_name, |
791 | GVariant *value, |
792 | GError **error, |
793 | gpointer user_data) |
794 | { |
795 | g_set_error (err: error, |
796 | G_DBUS_ERROR, code: G_DBUS_ERROR_FAILED, |
797 | format: "SetProperty not implemented" ); |
798 | return FALSE; |
799 | } |
800 | |
801 | static const GDBusInterfaceVTable interface_vtable = |
802 | { |
803 | handle_method_call, |
804 | handle_get_property, |
805 | handle_set_property |
806 | }; |
807 | |
808 | static void |
809 | on_bus_acquired (GDBusConnection *connection, |
810 | const gchar *name, |
811 | gpointer user_data) |
812 | { |
813 | guint id; |
814 | |
815 | id = g_dbus_connection_register_object (connection, |
816 | object_path: "/com/example/TestObject" , |
817 | interface_info: introspection_data->interfaces[0], |
818 | vtable: &interface_vtable, |
819 | NULL, |
820 | NULL, |
821 | NULL); |
822 | g_assert (id > 0); |
823 | } |
824 | |
825 | static void |
826 | on_name_acquired (GDBusConnection *connection, |
827 | const gchar *name, |
828 | gpointer user_data) |
829 | { |
830 | } |
831 | |
832 | static void |
833 | on_name_lost (GDBusConnection *connection, |
834 | const gchar *name, |
835 | gpointer user_data) |
836 | { |
837 | exit (status: 1); |
838 | } |
839 | |
840 | int |
841 | main (int argc, char *argv[]) |
842 | { |
843 | guint owner_id; |
844 | |
845 | introspection_data = g_dbus_node_info_new_for_xml (xml_data: introspection_xml, NULL); |
846 | properties = g_hash_table_new_full (hash_func: g_str_hash, key_equal_func: g_str_equal, key_destroy_func: g_free, value_destroy_func: (GDestroyNotify)g_variant_unref); |
847 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "y" ), value: g_variant_ref_sink (value: g_variant_new_byte (value: 1))); |
848 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "b" ), value: g_variant_ref_sink (value: g_variant_new_boolean (TRUE))); |
849 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "n" ), value: g_variant_ref_sink (value: g_variant_new_int16 (value: 2))); |
850 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "q" ), value: g_variant_ref_sink (value: g_variant_new_uint16 (value: 3))); |
851 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "i" ), value: g_variant_ref_sink (value: g_variant_new_int32 (value: 4))); |
852 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "u" ), value: g_variant_ref_sink (value: g_variant_new_uint32 (value: 5))); |
853 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "x" ), value: g_variant_ref_sink (value: g_variant_new_int64 (value: 6))); |
854 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "t" ), value: g_variant_ref_sink (value: g_variant_new_uint64 (value: 7))); |
855 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "d" ), value: g_variant_ref_sink (value: g_variant_new_double (value: 7.5))); |
856 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "s" ), value: g_variant_ref_sink (value: g_variant_new_string (string: "a string" ))); |
857 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "o" ), value: g_variant_ref_sink (value: g_variant_new_object_path (object_path: "/some/path" ))); |
858 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "ay" ), value: g_variant_ref_sink (value: g_variant_new_parsed (format: "[@y 1, @y 11]" ))); |
859 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "ab" ), value: g_variant_ref_sink (value: g_variant_new_parsed (format: "[true, false]" ))); |
860 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "an" ), value: g_variant_ref_sink (value: g_variant_new_parsed (format: "[@n 2, @n 12]" ))); |
861 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "aq" ), value: g_variant_ref_sink (value: g_variant_new_parsed (format: "[@q 3, @q 13]" ))); |
862 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "ai" ), value: g_variant_ref_sink (value: g_variant_new_parsed (format: "[@i 4, @i 14]" ))); |
863 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "au" ), value: g_variant_ref_sink (value: g_variant_new_parsed (format: "[@u 5, @u 15]" ))); |
864 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "ax" ), value: g_variant_ref_sink (value: g_variant_new_parsed (format: "[@x 6, @x 16]" ))); |
865 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "at" ), value: g_variant_ref_sink (value: g_variant_new_parsed (format: "[@t 7, @t 17]" ))); |
866 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "ad" ), value: g_variant_ref_sink (value: g_variant_new_parsed (format: "[7.5, 17.5]" ))); |
867 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "as" ), value: g_variant_ref_sink (value: g_variant_new_parsed (format: "['a string', 'another string']" ))); |
868 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "ao" ), value: g_variant_ref_sink (value: g_variant_new_parsed (format: "[@o '/some/path', @o '/another/path']" ))); |
869 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "foo" ), value: g_variant_ref_sink (value: g_variant_new_string (string: "a frobbed string" ))); |
870 | g_hash_table_insert (hash_table: properties, key: g_strdup (str: "PropertyThatWillBeInvalidated" ), value: g_variant_ref_sink (value: g_variant_new_string (string: "InitialValue" ))); |
871 | |
872 | owner_id = g_bus_own_name (bus_type: G_BUS_TYPE_SESSION, |
873 | name: "com.example.TestService" , |
874 | flags: G_BUS_NAME_OWNER_FLAGS_NONE, |
875 | bus_acquired_handler: on_bus_acquired, |
876 | name_acquired_handler: on_name_acquired, |
877 | name_lost_handler: on_name_lost, |
878 | NULL, |
879 | NULL); |
880 | |
881 | loop = g_main_loop_new (NULL, FALSE); |
882 | g_main_loop_run (loop); |
883 | |
884 | g_bus_unown_name (owner_id); |
885 | |
886 | g_dbus_node_info_unref (info: introspection_data); |
887 | g_hash_table_unref (hash_table: properties); |
888 | |
889 | return 0; |
890 | } |
891 | |