Fix compatibility with GLib 2.16 for D-Bus and GAsync support
[vala-lang.git] / codegen / valadbusclientmodule.vala
blob7d4e4c11b4ff8153fb3c94e40a08514208d071e0
1 /* valadbusclientmodule.vala
3 * Copyright (C) 2007-2010 Jürg Billeter
4 * Copyright (C) 2008 Philip Van Hoof
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Author:
21 * Jürg Billeter <j@bitron.ch>
22 * Philip Van Hoof <pvanhoof@gnome.org>
25 using GLib;
27 /**
28 * The link between a dynamic method and generated code.
30 internal class Vala.DBusClientModule : DBusModule {
31 int dynamic_property_id;
33 public DBusClientModule (CCodeGenerator codegen, CCodeModule? next) {
34 base (codegen, next);
37 string get_dynamic_dbus_name (string vala_name) {
38 // TODO switch default to no transformation as soon as we have static D-Bus client support
39 // keep transformation by default for static D-Bus client and server support
40 if (context.dbus_transformation) {
41 return Symbol.lower_case_to_camel_case (vala_name);
42 } else {
43 return vala_name;
47 bool has_dbus_error (List<DataType> error_types) {
48 foreach (DataType error_type in error_types) {
49 if (((ErrorType) error_type).error_domain.get_full_name () == "DBus.Error") {
50 return true;
53 return false;
56 public override void generate_dynamic_method_wrapper (DynamicMethod method) {
57 var dynamic_method = (DynamicMethod) method;
59 var func = new CCodeFunction (method.get_cname ());
60 func.modifiers = CCodeModifiers.STATIC;
62 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
64 generate_cparameters (method, source_declarations, cparam_map, func);
66 var block = new CCodeBlock ();
67 if (dynamic_method.dynamic_type.data_type == dbus_object_type) {
68 generate_dbus_method_wrapper (method, block);
69 } else {
70 Report.error (method.source_reference, "dynamic methods are not supported for `%s'".printf (dynamic_method.dynamic_type.to_string ()));
73 // append to C source file
74 source_declarations.add_type_member_declaration (func.copy ());
76 func.block = block;
77 source_type_member_definition.append (func);
80 void generate_dbus_method_wrapper (Method method, CCodeBlock block) {
81 var dynamic_method = (DynamicMethod) method;
83 var expr = dynamic_method.invocation;
85 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_begin_call"));
87 ccall.add_argument (new CCodeIdentifier ("self"));
89 bool found_out = false;
90 Expression callback = null;
91 int callback_index = -1;
92 int arg_index = 1;
93 foreach (Expression arg in expr.get_argument_list ()) {
94 if (arg.symbol_reference is Method) {
95 // callback
96 if (callback != null) {
97 Report.error (expr.source_reference, "only one reply callback may be specified in invocation of DBus method");
98 expr.error = true;
99 return;
100 } else if (found_out) {
101 Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method");
102 expr.error = true;
103 return;
105 callback = arg;
106 callback_index = arg_index;
107 } else if (arg is UnaryExpression && ((UnaryExpression) arg).operator == UnaryOperator.OUT) {
108 // out arg
109 if (callback != null) {
110 Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method");
111 expr.error = true;
112 return;
114 found_out = true;
115 } else {
116 // in arg
117 if (callback != null || found_out) {
118 Report.error (expr.source_reference, "in argument must not follow out argument or reply callback in invocation of DBus method");
119 expr.error = true;
120 return;
123 arg_index++;
126 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (method.name))));
128 if (callback != null) {
129 var reply_method = (Method) callback.symbol_reference;
131 var cb_fun = new CCodeFunction ("_%s_cb".printf (reply_method.get_cname ()), "void");
132 cb_fun.modifiers = CCodeModifiers.STATIC;
133 cb_fun.add_parameter (new CCodeFormalParameter ("proxy", "DBusGProxy*"));
134 cb_fun.add_parameter (new CCodeFormalParameter ("call", "DBusGProxyCall*"));
135 cb_fun.add_parameter (new CCodeFormalParameter ("user_data", "void*"));
136 cb_fun.block = new CCodeBlock ();
137 var cerrdecl = new CCodeDeclaration ("GError*");
138 cerrdecl.add_declarator (new CCodeVariableDeclarator ("error", new CCodeConstant ("NULL")));
139 cb_fun.block.add_statement (cerrdecl);
140 var cend_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_end_call"));
141 cend_call.add_argument (new CCodeIdentifier ("proxy"));
142 cend_call.add_argument (new CCodeIdentifier ("call"));
143 cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
144 var creply_call = new CCodeFunctionCall ((CCodeExpression) callback.ccodenode);
145 if (reply_method.binding != MemberBinding.STATIC) {
146 creply_call.add_argument (new CCodeIdentifier ("user_data"));
148 int param_count = reply_method.get_parameters ().size;
149 int i = 0;
150 foreach (FormalParameter param in reply_method.get_parameters ()) {
151 if ((++i) == param_count) {
152 if (!(param.parameter_type is ErrorType)) {
153 Report.error (null, "DBus reply callbacks must end with GLib.Error argument");
154 return;
157 break;
159 if (param.parameter_type is ArrayType && ((ArrayType) param.parameter_type).element_type.data_type != string_type.data_type) {
160 var array_type = (ArrayType) param.parameter_type;
161 CCodeDeclaration cdecl;
162 if (dbus_use_ptr_array (array_type)) {
163 cdecl = new CCodeDeclaration ("GPtrArray*");
164 } else {
165 cdecl = new CCodeDeclaration ("GArray*");
167 cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
168 cb_fun.block.add_statement (cdecl);
169 cend_call.add_argument (get_dbus_g_type (array_type));
170 cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
171 creply_call.add_argument (new CCodeCastExpression (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), dbus_use_ptr_array (array_type) ? "pdata" : "data"), array_type.get_cname ()));
172 creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "len"));
173 } else {
174 var cdecl = new CCodeDeclaration (param.parameter_type.get_cname ());
175 cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
176 cb_fun.block.add_statement (cdecl);
177 cend_call.add_argument (get_dbus_g_type (param.parameter_type));
178 cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
179 creply_call.add_argument (new CCodeIdentifier (param.name));
181 if (param.parameter_type is ArrayType && ((ArrayType) param.parameter_type).element_type.data_type == string_type.data_type) {
182 var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
183 cstrvlen.add_argument (new CCodeIdentifier (param.name));
184 creply_call.add_argument (cstrvlen);
189 cend_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
190 cb_fun.block.add_statement (new CCodeExpressionStatement (cend_call));
191 creply_call.add_argument (new CCodeIdentifier ("error"));
192 cb_fun.block.add_statement (new CCodeExpressionStatement (creply_call));
194 if (!source_declarations.add_declaration (cb_fun.name)) {
195 // avoid duplicate function definition
196 source_type_member_definition.append (cb_fun);
199 ccall.add_argument (new CCodeIdentifier (cb_fun.name));
200 ccall.add_argument (new CCodeConstant ("param%d_target".printf (callback_index)));
201 ccall.add_argument (new CCodeConstant ("NULL"));
202 } else {
203 ccall.call = new CCodeIdentifier ("dbus_g_proxy_call");
205 ccall.add_argument (new CCodeIdentifier ("error"));
208 foreach (FormalParameter param in method.get_parameters ()) {
209 if (param.parameter_type is MethodType
210 || param.parameter_type is DelegateType) {
211 // callback parameter
212 break;
215 if (param.direction != ParameterDirection.IN) {
216 continue;
219 var array_type = param.parameter_type as ArrayType;
220 if (array_type != null) {
221 // array parameter
222 if (array_type.element_type.data_type != string_type.data_type) {
223 // non-string arrays (use GArray)
224 ccall.add_argument (get_dbus_g_type (array_type));
226 var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
227 sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
229 CCodeDeclaration cdecl;
230 CCodeFunctionCall array_construct;
231 if (dbus_use_ptr_array (array_type)) {
232 cdecl = new CCodeDeclaration ("GPtrArray*");
234 array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_ptr_array_sized_new"));
235 array_construct.add_argument (new CCodeIdentifier (head.get_array_length_cname (param.name, 1)));
236 } else {
237 cdecl = new CCodeDeclaration ("GArray*");
239 array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_array_new"));
240 array_construct.add_argument (new CCodeConstant ("TRUE"));
241 array_construct.add_argument (new CCodeConstant ("TRUE"));
242 array_construct.add_argument (sizeof_call);
245 cdecl.add_declarator (new CCodeVariableDeclarator ("dbus_%s".printf (param.name), array_construct));
246 block.add_statement (cdecl);
248 if (dbus_use_ptr_array (array_type)) {
249 source_declarations.add_include ("string.h");
251 var memcpy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
252 memcpy_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_%s".printf (param.name)), "pdata"));
253 memcpy_call.add_argument (new CCodeIdentifier (param.name));
254 memcpy_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeIdentifier (head.get_array_length_cname (param.name, 1)), sizeof_call));
255 block.add_statement (new CCodeExpressionStatement (memcpy_call));
257 var len_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_%s".printf (param.name)), "len"), new CCodeIdentifier (head.get_array_length_cname (param.name, 1)));
258 block.add_statement (new CCodeExpressionStatement (len_assignment));
259 } else {
260 var cappend_call = new CCodeFunctionCall (new CCodeIdentifier ("g_array_append_vals"));
261 cappend_call.add_argument (new CCodeIdentifier ("dbus_%s".printf (param.name)));
262 cappend_call.add_argument (new CCodeIdentifier (param.name));
263 cappend_call.add_argument (new CCodeIdentifier (head.get_array_length_cname (param.name, 1)));
264 block.add_statement (new CCodeExpressionStatement (cappend_call));
267 ccall.add_argument (new CCodeIdentifier ("dbus_%s".printf (param.name)));
268 } else {
269 // string arrays
270 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
271 ccall.add_argument (new CCodeIdentifier (param.name));
273 } else if (get_type_signature (param.parameter_type).has_prefix ("(")) {
274 // struct parameter
275 var st = (Struct) param.parameter_type.data_type;
277 var array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_new"));
278 array_construct.add_argument (new CCodeConstant ("0"));
280 var cdecl = new CCodeDeclaration ("GValueArray*");
281 cdecl.add_declarator (new CCodeVariableDeclarator ("dbus_%s".printf (param.name), array_construct));
282 block.add_statement (cdecl);
284 foreach (Field f in st.get_fields ()) {
285 if (f.binding != MemberBinding.INSTANCE) {
286 continue;
289 string val_name = "val_%s_%s".printf (param.name, f.name);
291 // 0-initialize struct with struct initializer { 0 }
292 var cvalinit = new CCodeInitializerList ();
293 cvalinit.append (new CCodeConstant ("0"));
295 var cval_decl = new CCodeDeclaration ("GValue");
296 cval_decl.add_declarator (new CCodeVariableDeclarator.zero (val_name, cvalinit));
297 block.add_statement (cval_decl);
299 var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (val_name));
301 var cinit_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init"));
302 cinit_call.add_argument (val_ptr);
303 cinit_call.add_argument (new CCodeIdentifier (f.field_type.data_type.get_type_id ()));
304 block.add_statement (new CCodeExpressionStatement (cinit_call));
306 var cset_call = new CCodeFunctionCall (new CCodeIdentifier (f.field_type.data_type.get_set_value_function ()));
307 cset_call.add_argument (val_ptr);
308 cset_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), f.name));
309 block.add_statement (new CCodeExpressionStatement (cset_call));
311 var cappend_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_append"));
312 cappend_call.add_argument (new CCodeIdentifier ("dbus_%s".printf (param.name)));
313 cappend_call.add_argument (val_ptr);
314 block.add_statement (new CCodeExpressionStatement (cappend_call));
317 ccall.add_argument (get_dbus_g_type (param.parameter_type));
318 ccall.add_argument (new CCodeIdentifier ("dbus_%s".printf (param.name)));
319 } else {
320 ccall.add_argument (get_dbus_g_type (param.parameter_type));
321 ccall.add_argument (new CCodeIdentifier (param.name));
325 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
327 var out_marshalling_fragment = new CCodeFragment ();
329 foreach (FormalParameter param in method.get_parameters ()) {
330 if (param.parameter_type is MethodType) {
331 // callback parameter
332 break;
335 if (param.direction != ParameterDirection.OUT) {
336 continue;
339 if (get_type_signature (param.parameter_type).has_prefix ("(")) {
340 // struct output parameter
341 var st = (Struct) param.parameter_type.data_type;
343 var cdecl = new CCodeDeclaration ("GValueArray*");
344 cdecl.add_declarator (new CCodeVariableDeclarator ("dbus_%s".printf (param.name)));
345 block.add_statement (cdecl);
347 int i = 0;
348 foreach (Field f in st.get_fields ()) {
349 if (f.binding != MemberBinding.INSTANCE) {
350 continue;
353 var cget_call = new CCodeFunctionCall (new CCodeIdentifier (f.field_type.data_type.get_get_value_function ()));
354 cget_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeElementAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_%s".printf (param.name)), "values"), new CCodeConstant (i.to_string ()))));
356 var converted_value = cget_call;
358 if (requires_copy (f.field_type)) {
359 var dupexpr = get_dup_func_expression (f.field_type, expr.source_reference);
360 converted_value = new CCodeFunctionCall (dupexpr);
361 converted_value.add_argument (cget_call);
364 var assign = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), f.name), converted_value);
365 out_marshalling_fragment.append (new CCodeExpressionStatement (assign));
367 i++;
370 ccall.add_argument (get_dbus_g_type (param.parameter_type));
371 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("dbus_%s".printf (param.name))));
372 } else {
373 ccall.add_argument (get_dbus_g_type (param.parameter_type));
374 ccall.add_argument (new CCodeIdentifier (param.name));
378 if (!(method.return_type is VoidType)) {
379 // synchronous D-Bus method call with reply
380 ccall.add_argument (get_dbus_g_type (method.return_type));
382 var array_type = method.return_type as ArrayType;
383 if (array_type != null && array_type.element_type.data_type != string_type.data_type) {
384 // non-string arrays (use GArray)
385 CCodeDeclaration cdecl;
386 if (dbus_use_ptr_array (array_type)) {
387 cdecl = new CCodeDeclaration ("GPtrArray*");
388 } else {
389 cdecl = new CCodeDeclaration ("GArray*");
391 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
392 block.add_statement (cdecl);
394 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
395 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
397 block.add_statement (new CCodeExpressionStatement (ccall));
399 // don't access result when error occured
400 var creturnblock = new CCodeBlock ();
401 creturnblock.add_statement (new CCodeReturnStatement (default_value_for_type (method.return_type, false)));
402 var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
403 block.add_statement (cerrorif);
405 block.add_statement (out_marshalling_fragment);
407 // *result_length1 = result->len;
408 var garray_length = new CCodeMemberAccess.pointer (new CCodeIdentifier ("result"), "len");
409 var result_length = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length1"));
410 var assign = new CCodeAssignment (result_length, garray_length);
411 block.add_statement (new CCodeExpressionStatement (assign));
413 // return result->data;
414 block.add_statement (new CCodeReturnStatement (new CCodeCastExpression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("result"), dbus_use_ptr_array (array_type) ? "pdata" : "data"), method.return_type.get_cname ())));
415 } else if (method.return_type.is_real_non_null_struct_type ()) {
416 // structs are returned via out parameter
417 var st = (Struct) method.return_type.data_type;
419 if (st.get_full_name () == "GLib.Value") {
420 ccall.add_argument (new CCodeIdentifier ("result"));
421 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
423 block.add_statement (new CCodeExpressionStatement (ccall));
424 } else {
425 var cdecl = new CCodeDeclaration ("GValueArray*");
426 cdecl.add_declarator (new CCodeVariableDeclarator ("dbus_result"));
427 block.add_statement (cdecl);
429 int i = 0;
430 foreach (Field f in st.get_fields ()) {
431 if (f.binding != MemberBinding.INSTANCE) {
432 continue;
435 var cget_call = new CCodeFunctionCall (new CCodeIdentifier (f.field_type.data_type.get_get_value_function ()));
436 cget_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeElementAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_result"), "values"), new CCodeConstant (i.to_string ()))));
438 var converted_value = cget_call;
440 if (requires_copy (f.field_type)) {
441 var dupexpr = get_dup_func_expression (f.field_type, expr.source_reference);
442 converted_value = new CCodeFunctionCall (dupexpr);
443 converted_value.add_argument (cget_call);
446 var assign = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("result"), f.name), converted_value);
447 out_marshalling_fragment.append (new CCodeExpressionStatement (assign));
449 i++;
452 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("dbus_result")));
453 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
455 block.add_statement (new CCodeExpressionStatement (ccall));
458 // don't access result when error occured
459 var creturnblock = new CCodeBlock ();
460 creturnblock.add_statement (new CCodeReturnStatement ());
461 var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
462 block.add_statement (cerrorif);
464 block.add_statement (out_marshalling_fragment);
465 } else {
466 // string arrays or other datatypes
467 var cdecl = new CCodeDeclaration (method.return_type.get_cname ());
468 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
469 block.add_statement (cdecl);
471 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
472 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
474 block.add_statement (new CCodeExpressionStatement (ccall));
476 // don't access result when error occured
477 var creturnblock = new CCodeBlock ();
478 creturnblock.add_statement (new CCodeReturnStatement (default_value_for_type (method.return_type, false)));
479 var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
480 block.add_statement (cerrorif);
482 block.add_statement (out_marshalling_fragment);
484 if (array_type != null) {
485 // special case string array
487 // *result_length1 = g_strv_length (result);
488 var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
489 cstrvlen.add_argument (new CCodeIdentifier ("result"));
490 var result_length = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length1"));
491 var assign = new CCodeAssignment (result_length, cstrvlen);
492 block.add_statement (new CCodeExpressionStatement (assign));
495 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
497 } else {
498 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
500 block.add_statement (new CCodeExpressionStatement (ccall));
502 // don't access result when error occured
503 var creturnblock = new CCodeBlock ();
504 creturnblock.add_statement (new CCodeReturnStatement ());
505 var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
506 block.add_statement (cerrorif);
508 block.add_statement (out_marshalling_fragment);
512 public override CCodeExpression get_dbus_g_type (DataType data_type) {
513 if (data_type is ArrayType) {
514 var array_type = data_type as ArrayType;
515 if (array_type.element_type.data_type == string_type.data_type) {
516 return new CCodeIdentifier ("G_TYPE_STRV");
519 var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection"));
520 if (dbus_use_ptr_array (array_type)) {
521 carray_type.add_argument (new CCodeConstant ("\"GPtrArray\""));
522 } else {
523 carray_type.add_argument (new CCodeConstant ("\"GArray\""));
525 carray_type.add_argument (get_dbus_g_type (array_type.element_type));
526 return carray_type;
527 } else if (data_type.data_type is Enum) {
528 var en = (Enum) data_type.data_type;
529 if (en.is_flags) {
530 return new CCodeIdentifier ("G_TYPE_UINT");
531 } else {
532 return new CCodeIdentifier ("G_TYPE_INT");
534 } else if (data_type.data_type == null) {
535 critical ("Internal error during DBus type generation with: %s", data_type.to_string ());
536 return new CCodeIdentifier ("G_TYPE_NONE");
537 } else if (data_type.data_type.get_full_name () == "GLib.HashTable") {
538 var cmap_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_map"));
539 var type_args = data_type.get_type_arguments ();
541 cmap_type.add_argument (new CCodeConstant ("\"GHashTable\""));
542 foreach (DataType type_arg in type_args) {
543 cmap_type.add_argument (get_dbus_g_type (type_arg));
546 return cmap_type;
547 } else if (get_type_signature (data_type).has_prefix ("(")) {
548 // struct parameter
549 var st = (Struct) data_type.data_type;
551 var type_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_struct"));
552 type_call.add_argument (new CCodeConstant ("\"GValueArray\""));
554 foreach (Field f in st.get_fields ()) {
555 if (f.binding != MemberBinding.INSTANCE) {
556 continue;
559 type_call.add_argument (get_dbus_g_type (f.field_type));
562 type_call.add_argument (new CCodeConstant ("G_TYPE_INVALID"));
564 return type_call;
565 } else {
566 return new CCodeIdentifier (data_type.data_type.get_type_id ());
570 public bool dbus_use_ptr_array (ArrayType array_type) {
571 if (array_type.element_type.data_type == string_type.data_type) {
572 // use char**
573 return false;
574 } else if (array_type.element_type.data_type == bool_type.data_type
575 || array_type.element_type.data_type == char_type.data_type
576 || array_type.element_type.data_type == uchar_type.data_type
577 || array_type.element_type.data_type == int_type.data_type
578 || array_type.element_type.data_type == uint_type.data_type
579 || array_type.element_type.data_type == long_type.data_type
580 || array_type.element_type.data_type == ulong_type.data_type
581 || array_type.element_type.data_type == int8_type.data_type
582 || array_type.element_type.data_type == uint8_type.data_type
583 || array_type.element_type.data_type == int32_type.data_type
584 || array_type.element_type.data_type == uint32_type.data_type
585 || array_type.element_type.data_type == int64_type.data_type
586 || array_type.element_type.data_type == uint64_type.data_type
587 || array_type.element_type.data_type == double_type.data_type) {
588 // use GArray
589 return false;
590 } else {
591 // use GPtrArray
592 return true;
596 public override string get_dynamic_property_getter_cname (DynamicProperty prop) {
597 if (prop.dynamic_type.data_type != dbus_object_type) {
598 return base.get_dynamic_property_getter_cname (prop);
601 string getter_cname = "_dynamic_get_%s%d".printf (prop.name, dynamic_property_id++);
603 if (get_type_signature (prop.property_type) == null) {
604 Report.error (prop.property_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (prop.property_type.to_string ()));
605 return getter_cname;
608 var func = new CCodeFunction (getter_cname, prop.property_type.get_cname ());
609 func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
611 func.add_parameter (new CCodeFormalParameter ("obj", prop.dynamic_type.get_cname ()));
613 var block = new CCodeBlock ();
614 generate_dbus_property_getter_wrapper (prop, block);
616 // append to C source file
617 source_declarations.add_type_member_declaration (func.copy ());
619 func.block = block;
620 source_type_member_definition.append (func);
622 return getter_cname;
625 public override string get_dynamic_property_setter_cname (DynamicProperty prop) {
626 if (prop.dynamic_type.data_type != dbus_object_type) {
627 return base.get_dynamic_property_setter_cname (prop);
630 string setter_cname = "_dynamic_set_%s%d".printf (prop.name, dynamic_property_id++);
632 if (get_type_signature (prop.property_type) == null) {
633 Report.error (prop.property_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (prop.property_type.to_string ()));
634 return setter_cname;
637 var func = new CCodeFunction (setter_cname, "void");
638 func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
640 func.add_parameter (new CCodeFormalParameter ("obj", prop.dynamic_type.get_cname ()));
641 func.add_parameter (new CCodeFormalParameter ("value", prop.property_type.get_cname ()));
643 var block = new CCodeBlock ();
644 generate_dbus_property_setter_wrapper (prop, block);
646 // append to C source file
647 source_declarations.add_type_member_declaration (func.copy ());
649 func.block = block;
650 source_type_member_definition.append (func);
652 return setter_cname;
655 void create_dbus_property_proxy (DynamicProperty node, CCodeBlock block) {
656 var prop_proxy_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_new_from_proxy"));
657 prop_proxy_call.add_argument (new CCodeIdentifier ("obj"));
658 prop_proxy_call.add_argument (new CCodeConstant ("DBUS_INTERFACE_PROPERTIES"));
659 prop_proxy_call.add_argument (new CCodeConstant ("NULL"));
661 var prop_proxy_decl = new CCodeDeclaration ("DBusGProxy*");
662 prop_proxy_decl.add_declarator (new CCodeVariableDeclarator ("property_proxy", prop_proxy_call));
663 block.add_statement (prop_proxy_decl);
666 void generate_dbus_property_getter_wrapper (DynamicProperty node, CCodeBlock block) {
667 create_dbus_property_proxy (node, block);
669 // initialize GValue
670 var cvalinit = new CCodeInitializerList ();
671 cvalinit.append (new CCodeConstant ("0"));
673 var cval_decl = new CCodeDeclaration ("GValue");
674 cval_decl.add_declarator (new CCodeVariableDeclarator.zero ("gvalue", cvalinit));
675 block.add_statement (cval_decl);
677 var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("gvalue"));
679 // call Get method on property proxy
680 var cdecl = new CCodeDeclaration (node.property_type.get_cname ());
681 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
682 block.add_statement (cdecl);
684 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_call"));
685 ccall.add_argument (new CCodeIdentifier ("property_proxy"));
686 ccall.add_argument (new CCodeConstant ("\"Get\""));
687 ccall.add_argument (new CCodeConstant ("NULL"));
689 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
690 var get_iface = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_interface"));
691 get_iface.add_argument (new CCodeIdentifier ("obj"));
692 ccall.add_argument (get_iface);
694 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
695 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (node.name))));
697 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
699 ccall.add_argument (new CCodeIdentifier ("G_TYPE_VALUE"));
700 ccall.add_argument (val_ptr);
702 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
704 block.add_statement (new CCodeExpressionStatement (ccall));
706 // unref property proxy
707 var prop_proxy_unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
708 prop_proxy_unref.add_argument (new CCodeIdentifier ("property_proxy"));
709 block.add_statement (new CCodeExpressionStatement (prop_proxy_unref));
711 // assign value to result variable
712 var cget_call = new CCodeFunctionCall (new CCodeIdentifier (node.property_type.data_type.get_get_value_function ()));
713 cget_call.add_argument (val_ptr);
714 var assign = new CCodeAssignment (new CCodeIdentifier ("result"), cget_call);
715 block.add_statement (new CCodeExpressionStatement (assign));
717 // return result
718 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
721 void generate_dbus_property_setter_wrapper (DynamicProperty node, CCodeBlock block) {
722 create_dbus_property_proxy (node, block);
724 // initialize GValue
725 var cvalinit = new CCodeInitializerList ();
726 cvalinit.append (new CCodeConstant ("0"));
728 var cval_decl = new CCodeDeclaration ("GValue");
729 cval_decl.add_declarator (new CCodeVariableDeclarator.zero ("gvalue", cvalinit));
730 block.add_statement (cval_decl);
732 var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("gvalue"));
734 var cinit_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init"));
735 cinit_call.add_argument (val_ptr);
736 cinit_call.add_argument (new CCodeIdentifier (node.property_type.data_type.get_type_id ()));
737 block.add_statement (new CCodeExpressionStatement (cinit_call));
739 var cset_call = new CCodeFunctionCall (new CCodeIdentifier (node.property_type.data_type.get_set_value_function ()));
740 cset_call.add_argument (val_ptr);
741 cset_call.add_argument (new CCodeIdentifier ("value"));
742 block.add_statement (new CCodeExpressionStatement (cset_call));
744 // call Set method on property proxy
745 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_call"));
746 ccall.add_argument (new CCodeIdentifier ("property_proxy"));
747 ccall.add_argument (new CCodeConstant ("\"Set\""));
748 ccall.add_argument (new CCodeConstant ("NULL"));
750 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
751 var get_iface = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_interface"));
752 get_iface.add_argument (new CCodeIdentifier ("obj"));
753 ccall.add_argument (get_iface);
755 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
756 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (node.name))));
758 ccall.add_argument (new CCodeIdentifier ("G_TYPE_VALUE"));
759 ccall.add_argument (val_ptr);
761 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
763 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
765 block.add_statement (new CCodeExpressionStatement (ccall));
767 // unref property proxy
768 var prop_proxy_unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
769 prop_proxy_unref.add_argument (new CCodeIdentifier ("property_proxy"));
770 block.add_statement (new CCodeExpressionStatement (prop_proxy_unref));
773 public override string get_dynamic_signal_connect_wrapper_name (DynamicSignal sig) {
774 if (sig.dynamic_type.data_type != dbus_object_type) {
775 return base.get_dynamic_signal_connect_wrapper_name (sig);
778 string connect_wrapper_name = "_%sconnect".printf (get_dynamic_signal_cname (sig));
779 var func = new CCodeFunction (connect_wrapper_name, "void");
780 func.add_parameter (new CCodeFormalParameter ("obj", "gpointer"));
781 func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *"));
782 func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
783 func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
784 var block = new CCodeBlock ();
785 generate_dbus_connect_wrapper (sig, block);
787 // append to C source file
788 source_declarations.add_type_member_declaration (func.copy ());
790 func.block = block;
791 source_type_member_definition.append (func);
793 return connect_wrapper_name;
796 public override string get_dynamic_signal_disconnect_wrapper_name (DynamicSignal sig) {
797 if (sig.dynamic_type.data_type != dbus_object_type) {
798 return base.get_dynamic_signal_disconnect_wrapper_name (sig);
801 string disconnect_wrapper_name = "_%sdisconnect".printf (get_dynamic_signal_cname (sig));
802 var func = new CCodeFunction (disconnect_wrapper_name, "void");
803 func.add_parameter (new CCodeFormalParameter ("obj", "gpointer"));
804 func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *"));
805 func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
806 func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
807 var block = new CCodeBlock ();
808 generate_dbus_disconnect_wrapper (sig, block);
810 // append to C source file
811 source_declarations.add_type_member_declaration (func.copy ());
813 func.block = block;
814 source_type_member_definition.append (func);
816 return disconnect_wrapper_name;
819 void generate_dbus_connect_wrapper (DynamicSignal sig, CCodeBlock block) {
820 var m = (Method) sig.handler.symbol_reference;
822 sig.accept (codegen);
824 // FIXME should only be done once per marshaller
825 var register_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_register_marshaller"));
826 head.generate_marshaller (sig.get_parameters (), sig.return_type, true);
827 register_call.add_argument (new CCodeIdentifier (head.get_marshaller_function (sig.get_parameters (), sig.return_type, null, true)));
828 register_call.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
830 var add_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_add_signal"));
831 add_call.add_argument (new CCodeIdentifier ("obj"));
832 add_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (sig.name))));
834 bool first = true;
835 foreach (FormalParameter param in m.get_parameters ()) {
836 if (first) {
837 // skip sender parameter
838 first = false;
839 continue;
842 register_call.add_argument (get_dbus_g_type (param.parameter_type));
843 add_call.add_argument (get_dbus_g_type (param.parameter_type));
845 register_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
846 add_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
848 block.add_statement (new CCodeExpressionStatement (register_call));
849 block.add_statement (new CCodeExpressionStatement (add_call));
851 var call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_connect_signal"));
852 call.add_argument (new CCodeIdentifier ("obj"));
853 call.add_argument (new CCodeIdentifier ("signal_name"));
854 call.add_argument (new CCodeIdentifier ("handler"));
855 call.add_argument (new CCodeIdentifier ("data"));
856 call.add_argument (new CCodeConstant ("NULL"));
857 block.add_statement (new CCodeExpressionStatement (call));
860 void generate_dbus_disconnect_wrapper (DynamicSignal sig, CCodeBlock block) {
861 var call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_disconnect_signal"));
862 call.add_argument (new CCodeIdentifier ("obj"));
863 call.add_argument (new CCodeIdentifier ("signal_name"));
864 call.add_argument (new CCodeIdentifier ("handler"));
865 call.add_argument (new CCodeIdentifier ("data"));
866 block.add_statement (new CCodeExpressionStatement (call));
869 public override void visit_cast_expression (CastExpression expr) {
870 // handles casting DBus.Object instances to DBus interfaces
872 var type = expr.type_reference as ObjectType;
873 var call = expr.inner as MethodCall;
874 if (type == null || !(type.type_symbol is Interface)
875 || type.type_symbol.get_attribute ("DBus") == null || call == null) {
876 base.visit_cast_expression (expr);
877 return;
880 var mtype = call.call.value_type as MethodType;
881 if (mtype == null || mtype.method_symbol.get_cname () != "dbus_g_proxy_new_for_name") {
882 base.visit_cast_expression (expr);
883 return;
886 var args = call.get_argument_list ();
887 Expression connection = ((MemberAccess) call.call).inner;
888 Expression bus_name = args.get (0);
889 Expression object_path = args.get (1);
891 var ccall = new CCodeFunctionCall (new CCodeIdentifier (type.type_symbol.get_lower_case_cprefix () + "dbus_proxy_new"));
892 connection.accept (codegen);
893 ccall.add_argument ((CCodeExpression) connection.ccodenode);
894 bus_name.accept (codegen);
895 ccall.add_argument ((CCodeExpression) bus_name.ccodenode);
896 object_path.accept (codegen);
897 ccall.add_argument ((CCodeExpression) object_path.ccodenode);
898 expr.ccodenode = ccall;
901 void generate_proxy_interface_init (Interface main_iface, Interface iface) {
902 // also generate proxy for prerequisites
903 foreach (var prereq in iface.get_prerequisites ()) {
904 if (prereq.data_type is Interface) {
905 generate_proxy_interface_init (main_iface, (Interface) prereq.data_type);
909 string lower_cname = main_iface.get_lower_case_cprefix () + "dbus_proxy";
911 var proxy_iface_init = new CCodeFunction (lower_cname + "_" + iface.get_lower_case_cprefix () + "_interface_init", "void");
912 proxy_iface_init.add_parameter (new CCodeFormalParameter ("iface", iface.get_cname () + "Iface*"));
914 var iface_block = new CCodeBlock ();
916 foreach (Method m in iface.get_methods ()) {
917 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), m.vfunc_name);
918 if (!m.coroutine) {
919 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_method (main_iface, iface, m)))));
920 } else {
921 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_async_dbus_proxy_method (main_iface, iface, m)))));
922 vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), m.get_finish_vfunc_name ());
923 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_finish_dbus_proxy_method (main_iface, iface, m)))));
927 foreach (Property prop in iface.get_properties ()) {
928 if (prop.get_accessor != null) {
929 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "get_" + prop.name);
930 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_get (main_iface, iface, prop)))));
932 if (prop.set_accessor != null) {
933 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "set_" + prop.name);
934 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_set (main_iface, iface, prop)))));
938 proxy_iface_init.modifiers = CCodeModifiers.STATIC;
939 source_declarations.add_type_member_declaration (proxy_iface_init.copy ());
940 proxy_iface_init.block = iface_block;
941 source_type_member_definition.append (proxy_iface_init);
944 string implement_interface (CCodeFunctionCall define_type, Interface main_iface, Interface iface) {
945 string result = "";
947 // also implement prerequisites
948 foreach (var prereq in iface.get_prerequisites ()) {
949 if (prereq.data_type is Interface) {
950 result += implement_interface (define_type, main_iface, (Interface) prereq.data_type);
954 result += "G_IMPLEMENT_INTERFACE (%s, %sdbus_proxy_%s_interface_init) ".printf (
955 iface.get_upper_case_cname ("TYPE_"),
956 main_iface.get_lower_case_cprefix (),
957 iface.get_lower_case_cprefix ());
958 return result;
961 void implement_property (CCodeBlock block, Interface main_iface, Interface iface) {
962 // also implement prerequisites
963 foreach (var prereq in iface.get_prerequisites ()) {
964 if (prereq.data_type is Interface) {
965 implement_property (block, main_iface, (Interface) prereq.data_type);
969 var gobject_class = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
970 gobject_class.add_argument (new CCodeIdentifier ("klass"));
972 foreach (Property prop in iface.get_properties ()) {
973 if (!prop.is_abstract) {
974 continue;
977 if (prop.property_type is ArrayType) {
978 continue;
981 string prop_ev = "%s_dbus_proxy_%s".printf (main_iface.get_lower_case_cname (null), Symbol.camel_case_to_lower_case (prop.name)).up ();
983 var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_override_property"));
984 cinst.add_argument (gobject_class);
985 cinst.add_argument (new CCodeConstant (prop_ev));
986 cinst.add_argument (prop.get_canonical_cconstant ());
987 block.add_statement (new CCodeExpressionStatement (cinst));
989 prop_enum.add_value (new CCodeEnumValue (prop_ev));
993 public override void visit_interface (Interface iface) {
994 base.visit_interface (iface);
996 string dbus_iface_name = get_dbus_name (iface);
997 if (dbus_iface_name == null) {
998 return;
1001 // create proxy class
1002 string cname = iface.get_cname () + "DBusProxy";
1003 string lower_cname = iface.get_lower_case_cprefix () + "dbus_proxy";
1005 if (iface.access != SymbolAccessibility.PRIVATE) {
1006 dbus_glib_h_needed_in_header = true;
1007 } else {
1008 dbus_glib_h_needed = true;
1011 source_declarations.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (cname), new CCodeVariableDeclarator (cname)));
1012 source_declarations.add_type_declaration (new CCodeTypeDefinition ("DBusGProxyClass", new CCodeVariableDeclarator (cname + "Class")));
1014 var instance_struct = new CCodeStruct ("_%s".printf (cname));
1015 instance_struct.add_field ("DBusGProxy", "parent_instance");
1016 instance_struct.add_field ("gboolean", "disposed");
1018 source_declarations.add_type_definition (instance_struct);
1020 source_declarations.add_type_member_declaration (new CCodeFunction(lower_cname + "_get_type", "GType"));
1022 var define_type = new CCodeFunctionCall (new CCodeIdentifier ("G_DEFINE_TYPE_EXTENDED"));
1023 define_type.add_argument (new CCodeIdentifier (cname));
1024 define_type.add_argument (new CCodeIdentifier (lower_cname));
1025 define_type.add_argument (new CCodeIdentifier ("DBUS_TYPE_G_PROXY"));
1026 define_type.add_argument (new CCodeConstant ("0"));
1027 define_type.add_argument (new CCodeIdentifier (implement_interface (define_type, iface, iface)));
1029 source_type_member_definition.append (new CCodeExpressionStatement (define_type));
1031 // generate proxy_new function
1032 var proxy_new = new CCodeFunction (lower_cname + "_new", iface.get_cname () + "*");
1033 proxy_new.add_parameter (new CCodeFormalParameter ("connection", "DBusGConnection*"));
1034 proxy_new.add_parameter (new CCodeFormalParameter ("name", "const char*"));
1035 proxy_new.add_parameter (new CCodeFormalParameter ("path", "const char*"));
1037 var new_block = new CCodeBlock ();
1039 // create proxy object
1040 var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_new"));
1041 new_call.add_argument (new CCodeFunctionCall (new CCodeIdentifier (lower_cname + "_get_type")));
1042 new_call.add_argument (new CCodeConstant ("\"connection\""));
1043 new_call.add_argument (new CCodeIdentifier ("connection"));
1044 new_call.add_argument (new CCodeConstant ("\"name\""));
1045 new_call.add_argument (new CCodeIdentifier ("name"));
1046 new_call.add_argument (new CCodeConstant ("\"path\""));
1047 new_call.add_argument (new CCodeIdentifier ("path"));
1048 new_call.add_argument (new CCodeConstant ("\"interface\""));
1049 new_call.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1050 new_call.add_argument (new CCodeConstant ("NULL"));
1052 var cdecl = new CCodeDeclaration (iface.get_cname () + "*");
1053 cdecl.add_declarator (new CCodeVariableDeclarator ("self", new_call));
1054 new_block.add_statement (cdecl);
1055 new_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("self")));
1057 source_declarations.add_type_member_declaration (proxy_new.copy ());
1058 proxy_new.block = new_block;
1059 source_type_member_definition.append (proxy_new);
1061 // dbus proxy construct
1062 var proxy_construct = new CCodeFunction (lower_cname + "_construct", "GObject*");
1063 proxy_construct.add_parameter (new CCodeFormalParameter ("gtype", "GType"));
1064 proxy_construct.add_parameter (new CCodeFormalParameter ("n_properties", "guint"));
1065 proxy_construct.add_parameter (new CCodeFormalParameter ("properties", "GObjectConstructParam*"));
1066 proxy_construct.modifiers = CCodeModifiers.STATIC;
1067 proxy_construct.block = new CCodeBlock ();
1069 // chain up
1070 var parent_class = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
1071 parent_class.add_argument (new CCodeIdentifier (lower_cname + "_parent_class"));
1072 var chainup = new CCodeFunctionCall (new CCodeMemberAccess.pointer (parent_class, "constructor"));
1073 chainup.add_argument (new CCodeIdentifier ("gtype"));
1074 chainup.add_argument (new CCodeIdentifier ("n_properties"));
1075 chainup.add_argument (new CCodeIdentifier ("properties"));
1077 cdecl = new CCodeDeclaration ("GObject*");
1078 cdecl.add_declarator (new CCodeVariableDeclarator ("self", chainup));
1079 proxy_construct.block.add_statement (cdecl);
1081 cdecl = new CCodeDeclaration ("DBusGConnection");
1082 cdecl.add_declarator (new CCodeVariableDeclarator ("*connection"));
1083 proxy_construct.block.add_statement (cdecl);
1085 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1086 gconnection.add_argument (new CCodeIdentifier ("self"));
1087 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1088 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("connection")));
1089 gconnection.add_argument (new CCodeConstant ("NULL"));
1090 proxy_construct.block.add_statement (new CCodeExpressionStatement (gconnection));
1092 cdecl = new CCodeDeclaration ("char*");
1093 cdecl.add_declarator (new CCodeVariableDeclarator ("path"));
1094 proxy_construct.block.add_statement (cdecl);
1096 var path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1097 path.add_argument (new CCodeIdentifier ("self"));
1098 path.add_argument (new CCodeConstant ("\"path\""));
1099 path.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("path")));
1100 path.add_argument (new CCodeConstant ("NULL"));
1101 proxy_construct.block.add_statement (new CCodeExpressionStatement (path));
1103 var raw_connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1104 raw_connection.add_argument (new CCodeIdentifier ("connection"));
1106 // add filter to handle signals from the remote object
1107 var filter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_add_filter"));
1108 filter_call.add_argument (raw_connection);
1109 filter_call.add_argument (new CCodeIdentifier (lower_cname + "_filter"));
1110 filter_call.add_argument (new CCodeIdentifier ("self"));
1111 filter_call.add_argument (new CCodeConstant ("NULL"));
1112 proxy_construct.block.add_statement (new CCodeExpressionStatement (filter_call));
1114 var filter_printf = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup_printf"));
1115 filter_printf.add_argument (new CCodeConstant ("\"type='signal',path='%s'\""));
1116 filter_printf.add_argument (new CCodeIdentifier ("path"));
1118 cdecl = new CCodeDeclaration ("char*");
1119 cdecl.add_declarator (new CCodeVariableDeclarator ("filter", filter_printf));
1120 proxy_construct.block.add_statement (cdecl);
1122 // ensure we receive signals from the remote object
1123 var match_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_bus_add_match"));
1124 match_call.add_argument (raw_connection);
1125 match_call.add_argument (new CCodeIdentifier ("filter"));
1126 match_call.add_argument (new CCodeConstant ("NULL"));
1127 proxy_construct.block.add_statement (new CCodeExpressionStatement (match_call));
1129 var connection_free = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
1130 connection_free.add_argument (new CCodeIdentifier ("connection"));
1131 proxy_construct.block.add_statement (new CCodeExpressionStatement (connection_free));
1133 var path_free = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1134 path_free.add_argument (new CCodeIdentifier ("path"));
1135 proxy_construct.block.add_statement (new CCodeExpressionStatement (path_free));
1137 var filter_free = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1138 filter_free.add_argument (new CCodeIdentifier ("filter"));
1139 proxy_construct.block.add_statement (new CCodeExpressionStatement (filter_free));
1141 proxy_construct.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("self")));
1143 source_type_member_definition.append (proxy_construct);
1145 // dbus proxy filter function
1146 generate_proxy_filter_function (iface);
1148 // dbus proxy dispose
1149 var proxy_dispose = new CCodeFunction (lower_cname + "_dispose", "void");
1150 proxy_dispose.add_parameter (new CCodeFormalParameter ("self", "GObject*"));
1151 proxy_dispose.modifiers = CCodeModifiers.STATIC;
1152 proxy_dispose.block = new CCodeBlock ();
1154 cdecl = new CCodeDeclaration ("DBusGConnection");
1155 cdecl.add_declarator (new CCodeVariableDeclarator ("*connection"));
1156 proxy_dispose.block.add_statement (cdecl);
1158 // return if proxy is already disposed
1159 var dispose_return_block = new CCodeBlock ();
1160 dispose_return_block.add_statement (new CCodeReturnStatement ());
1161 proxy_dispose.block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), cname + "*"), "disposed"), dispose_return_block));
1163 // mark proxy as disposed
1164 proxy_dispose.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), cname + "*"), "disposed"), new CCodeConstant ("TRUE"))));
1166 gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1167 gconnection.add_argument (new CCodeIdentifier ("self"));
1168 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1169 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("connection")));
1170 gconnection.add_argument (new CCodeConstant ("NULL"));
1171 proxy_dispose.block.add_statement (new CCodeExpressionStatement (gconnection));
1173 // remove filter
1174 filter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_remove_filter"));
1175 filter_call.add_argument (raw_connection);
1176 filter_call.add_argument (new CCodeIdentifier (lower_cname + "_filter"));
1177 filter_call.add_argument (new CCodeIdentifier ("self"));
1178 proxy_dispose.block.add_statement (new CCodeExpressionStatement (filter_call));
1180 // chain up
1181 parent_class = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
1182 parent_class.add_argument (new CCodeIdentifier (lower_cname + "_parent_class"));
1183 chainup = new CCodeFunctionCall (new CCodeMemberAccess.pointer (parent_class, "dispose"));
1184 chainup.add_argument (new CCodeIdentifier ("self"));
1185 proxy_dispose.block.add_statement (new CCodeExpressionStatement (chainup));
1187 source_type_member_definition.append (proxy_dispose);
1189 var proxy_class_init = new CCodeFunction (lower_cname + "_class_init", "void");
1190 proxy_class_init.add_parameter (new CCodeFormalParameter ("klass", cname + "Class*"));
1191 proxy_class_init.modifiers = CCodeModifiers.STATIC;
1192 proxy_class_init.block = new CCodeBlock ();
1193 var gobject_class = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
1194 gobject_class.add_argument (new CCodeIdentifier ("klass"));
1195 proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (gobject_class, "constructor"), new CCodeIdentifier (lower_cname + "_construct"))));
1196 proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (gobject_class, "dispose"), new CCodeIdentifier (lower_cname + "_dispose"))));
1197 proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (gobject_class, "get_property"), new CCodeIdentifier (lower_cname + "_get_property"))));
1198 proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (gobject_class, "set_property"), new CCodeIdentifier (lower_cname + "_set_property"))));
1199 source_type_member_definition.append (proxy_class_init);
1201 prop_enum = new CCodeEnum ();
1202 prop_enum.add_value (new CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (lower_cname.up ())));
1204 implement_property (proxy_class_init.block, iface, iface);
1206 source_declarations.add_type_member_declaration (prop_enum);
1208 var proxy_instance_init = new CCodeFunction (lower_cname + "_init", "void");
1209 proxy_instance_init.add_parameter (new CCodeFormalParameter ("self", cname + "*"));
1210 proxy_instance_init.modifiers = CCodeModifiers.STATIC;
1211 proxy_instance_init.block = new CCodeBlock ();
1212 source_type_member_definition.append (proxy_instance_init);
1214 generate_proxy_interface_init (iface, iface);
1216 // dbus proxy get/set_property stubs
1217 // TODO add actual implementation
1218 var get_prop = new CCodeFunction ("%s_get_property".printf (lower_cname), "void");
1219 get_prop.modifiers = CCodeModifiers.STATIC;
1220 get_prop.add_parameter (new CCodeFormalParameter ("object", "GObject *"));
1221 get_prop.add_parameter (new CCodeFormalParameter ("property_id", "guint"));
1222 get_prop.add_parameter (new CCodeFormalParameter ("value", "GValue *"));
1223 get_prop.add_parameter (new CCodeFormalParameter ("pspec", "GParamSpec *"));
1224 source_declarations.add_type_member_declaration (get_prop.copy ());
1225 get_prop.block = new CCodeBlock ();
1226 source_type_member_definition.append (get_prop);
1228 var set_prop = new CCodeFunction ("%s_set_property".printf (lower_cname), "void");
1229 set_prop.modifiers = CCodeModifiers.STATIC;
1230 set_prop.add_parameter (new CCodeFormalParameter ("object", "GObject *"));
1231 set_prop.add_parameter (new CCodeFormalParameter ("property_id", "guint"));
1232 set_prop.add_parameter (new CCodeFormalParameter ("value", "const GValue *"));
1233 set_prop.add_parameter (new CCodeFormalParameter ("pspec", "GParamSpec *"));
1234 source_declarations.add_type_member_declaration (set_prop.copy ());
1235 set_prop.block = new CCodeBlock ();
1236 source_type_member_definition.append (set_prop);
1239 public override TypeRegisterFunction create_interface_register_function (Interface iface) {
1240 string dbus_iface_name = get_dbus_name (iface);
1241 if (dbus_iface_name == null) {
1242 return new InterfaceRegisterFunction (iface, context);
1245 return new DBusInterfaceRegisterFunction (iface, context);
1248 string generate_get_all_function (Method m) {
1249 string get_all_func = "_dbus_g_proxy_get_all";
1251 if (!add_wrapper (get_all_func)) {
1252 // wrapper already defined
1253 return get_all_func;
1256 var function = new CCodeFunction (get_all_func, "GHashTable*");
1257 function.modifiers = CCodeModifiers.STATIC;
1259 function.add_parameter (new CCodeFormalParameter ("self", "DBusGProxy*"));
1260 function.add_parameter (new CCodeFormalParameter ("interface_name", "const gchar*"));
1261 function.add_parameter (new CCodeFormalParameter ("error", "GError**"));
1263 var block = new CCodeBlock ();
1264 var prefragment = new CCodeFragment ();
1265 var postfragment = new CCodeFragment ();
1267 var cdecl = new CCodeDeclaration ("DBusError");
1268 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
1269 block.add_statement (cdecl);
1271 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
1273 cdecl = new CCodeDeclaration ("DBusGConnection");
1274 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
1275 block.add_statement (cdecl);
1277 cdecl = new CCodeDeclaration ("DBusMessage");
1278 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
1279 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
1280 block.add_statement (cdecl);
1282 cdecl = new CCodeDeclaration ("DBusMessageIter");
1283 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
1284 block.add_statement (cdecl);
1286 block.add_statement (prefragment);
1288 generate_marshalling (m, "org.freedesktop.DBus.Properties", prefragment, postfragment);
1290 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1291 gconnection.add_argument (new CCodeIdentifier ("self"));
1292 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1293 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
1294 gconnection.add_argument (new CCodeConstant ("NULL"));
1295 block.add_statement (new CCodeExpressionStatement (gconnection));
1297 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
1298 dbus_error_init.add_argument (dbus_error);
1299 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
1301 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1302 connection.add_argument (new CCodeIdentifier ("_connection"));
1304 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
1305 ccall.add_argument (connection);
1306 ccall.add_argument (new CCodeIdentifier ("_message"));
1307 ccall.add_argument (new CCodeConstant ("-1"));
1308 ccall.add_argument (dbus_error);
1309 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
1311 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
1312 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
1313 block.add_statement (new CCodeExpressionStatement (conn_unref));
1315 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1316 message_unref.add_argument (new CCodeIdentifier ("_message"));
1317 block.add_statement (new CCodeExpressionStatement (message_unref));
1319 check_error_reply (m, block);
1320 check_reply_signature (m, block);
1322 block.add_statement (postfragment);
1324 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1325 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
1326 block.add_statement (new CCodeExpressionStatement (reply_unref));
1328 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
1330 source_declarations.add_type_member_declaration (function.copy ());
1332 function.block = block;
1333 source_type_member_definition.append (function);
1335 return get_all_func;
1338 public override void visit_method_call (MethodCall expr) {
1339 var mtype = expr.call.value_type as MethodType;
1340 bool proxy_new_from_type = (mtype != null && mtype.method_symbol.get_cname () == "dbus_g_proxy_new_from_type");
1341 bool proxy_get_all = (mtype != null && mtype.method_symbol.get_cname () == "dbus_g_proxy_get_all");
1342 if (!proxy_new_from_type && !proxy_get_all) {
1343 base.visit_method_call (expr);
1344 return;
1347 if (proxy_get_all) {
1348 var ma = expr.call as MemberAccess;
1349 var instance = ma.inner;
1350 instance.accept (codegen);
1352 var args = expr.get_argument_list ();
1353 Expression interface_name = args.get (0);
1354 interface_name.accept (codegen);
1356 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_get_all_function (mtype.method_symbol)));
1357 ccall.add_argument ((CCodeExpression) instance.ccodenode);
1358 ccall.add_argument ((CCodeExpression) interface_name.ccodenode);
1360 current_method_inner_error = true;
1361 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
1363 expr.ccodenode = ccall;
1364 return;
1367 var args = expr.get_argument_list ();
1368 Expression connection = ((MemberAccess) expr.call).inner;
1369 Expression bus_name = args.get (0);
1370 Expression object_path = args.get (1);
1371 Expression interface_name = args.get (2);
1372 Expression type = args.get (3);
1374 var quark_call = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
1375 quark_call.add_argument (new CCodeConstant ("\"ValaDBusInterfaceProxyType\""));
1377 var qdata_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
1378 type.accept (codegen);
1379 qdata_call.add_argument ((CCodeExpression) type.ccodenode);
1380 qdata_call.add_argument (quark_call);
1382 var get_type_call = new CCodeFunctionCall (new CCodeCastExpression (qdata_call, "GType (*)(void)"));
1384 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_new"));
1385 ccall.add_argument (get_type_call);
1386 ccall.add_argument (new CCodeConstant ("\"connection\""));
1387 connection.accept (codegen);
1388 ccall.add_argument ((CCodeExpression) connection.ccodenode);
1389 ccall.add_argument (new CCodeConstant ("\"name\""));
1390 bus_name.accept (codegen);
1391 ccall.add_argument ((CCodeExpression) bus_name.ccodenode);
1392 ccall.add_argument (new CCodeConstant ("\"path\""));
1393 object_path.accept (codegen);
1394 ccall.add_argument ((CCodeExpression) object_path.ccodenode);
1395 ccall.add_argument (new CCodeConstant ("\"interface\""));
1396 interface_name.accept (codegen);
1397 ccall.add_argument ((CCodeExpression) interface_name.ccodenode);
1398 ccall.add_argument (new CCodeConstant ("NULL"));
1399 expr.ccodenode = ccall;
1402 void generate_proxy_filter_function (Interface iface) {
1403 string lower_cname = iface.get_lower_case_cprefix () + "dbus_proxy";
1405 var proxy_filter = new CCodeFunction (lower_cname + "_filter", "DBusHandlerResult");
1406 proxy_filter.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
1407 proxy_filter.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
1408 proxy_filter.add_parameter (new CCodeFormalParameter ("user_data", "void*"));
1410 var filter_block = new CCodeBlock ();
1412 // only handle signals concering the object path
1413 var path = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_path"));
1414 path.add_argument (new CCodeIdentifier ("user_data"));
1416 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_has_path"));
1417 ccheck.add_argument (new CCodeIdentifier ("message"));
1418 ccheck.add_argument (path);
1420 var object_filter_block = new CCodeBlock ();
1421 filter_block.add_statement (new CCodeIfStatement (ccheck, object_filter_block));
1423 handle_signals (iface, object_filter_block);
1425 filter_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1427 source_declarations.add_type_member_declaration (proxy_filter.copy ());
1428 proxy_filter.block = filter_block;
1429 source_type_member_definition.append (proxy_filter);
1432 string generate_dbus_signal_handler (Signal sig, ObjectTypeSymbol sym) {
1433 string wrapper_name = "_dbus_handle_%s_%s".printf (sym.get_lower_case_cname (), sig.get_cname ());
1435 // declaration
1437 CCodeDeclaration cdecl;
1439 var function = new CCodeFunction (wrapper_name, "void");
1440 function.modifiers = CCodeModifiers.STATIC;
1442 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
1443 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
1444 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
1446 var block = new CCodeBlock ();
1447 var prefragment = new CCodeFragment ();
1448 var postfragment = new CCodeFragment ();
1450 cdecl = new CCodeDeclaration ("DBusMessageIter");
1451 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
1452 block.add_statement (cdecl);
1454 block.add_statement (prefragment);
1456 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
1457 message_signature.add_argument (new CCodeIdentifier ("message"));
1458 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1459 signature_check.add_argument (message_signature);
1460 var signature_error_block = new CCodeBlock ();
1461 signature_error_block.add_statement (new CCodeReturnStatement ());
1462 prefragment.append (new CCodeIfStatement (signature_check, signature_error_block));
1464 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
1465 iter_call.add_argument (new CCodeIdentifier ("message"));
1466 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1467 prefragment.append (new CCodeExpressionStatement (iter_call));
1469 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
1470 ccall.add_argument (new CCodeIdentifier ("self"));
1471 ccall.add_argument (sig.get_canonical_cconstant ());
1473 // expected type signature for input parameters
1474 string type_signature = "";
1476 foreach (FormalParameter param in sig.get_parameters ()) {
1477 var owned_type = param.parameter_type.copy ();
1478 owned_type.value_owned = true;
1480 cdecl = new CCodeDeclaration (owned_type.get_cname ());
1481 cdecl.add_declarator (new CCodeVariableDeclarator.zero (param.name, default_value_for_type (param.parameter_type, true)));
1482 prefragment.append (cdecl);
1484 if (get_type_signature (param.parameter_type) == null) {
1485 Report.error (param.parameter_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (param.parameter_type.to_string ()));
1486 continue;
1489 var st = param.parameter_type.data_type as Struct;
1490 if (st != null && !st.is_simple_type ()) {
1491 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
1492 } else {
1493 ccall.add_argument (new CCodeIdentifier (param.name));
1496 if (param.parameter_type is ArrayType) {
1497 var array_type = (ArrayType) param.parameter_type;
1499 for (int dim = 1; dim <= array_type.rank; dim++) {
1500 string length_cname = get_array_length_cname (param.name, dim);
1502 cdecl = new CCodeDeclaration ("int");
1503 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
1504 prefragment.append (cdecl);
1505 ccall.add_argument (new CCodeIdentifier (length_cname));
1509 type_signature += get_type_signature (param.parameter_type);
1511 var target = new CCodeIdentifier (param.name);
1512 var expr = read_expression (prefragment, param.parameter_type, new CCodeIdentifier ("iter"), target);
1513 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1515 if (requires_destroy (owned_type)) {
1516 // keep local alive (symbol_reference is weak)
1517 var local = new LocalVariable (owned_type, param.name);
1518 var ma = new MemberAccess.simple (param.name);
1519 ma.symbol_reference = local;
1520 var stmt = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (param.name), owned_type, ma));
1521 postfragment.append (stmt);
1525 signature_check.add_argument (new CCodeConstant ("\"%s\"".printf (type_signature)));
1527 block.add_statement (new CCodeExpressionStatement (ccall));
1529 block.add_statement (postfragment);
1531 cdecl = new CCodeDeclaration ("DBusMessage*");
1532 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
1533 block.add_statement (cdecl);
1535 source_declarations.add_type_member_declaration (function.copy ());
1537 function.block = block;
1538 source_type_member_definition.append (function);
1540 return wrapper_name;
1543 void handle_signal (string dbus_iface_name, string dbus_signal_name, string handler_name, CCodeBlock block, ref CCodeIfStatement clastif) {
1544 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_is_signal"));
1545 ccheck.add_argument (new CCodeIdentifier ("message"));
1546 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1547 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_signal_name)));
1549 var callblock = new CCodeBlock ();
1551 var ccall = new CCodeFunctionCall (new CCodeIdentifier (handler_name));
1552 ccall.add_argument (new CCodeIdentifier ("user_data"));
1553 ccall.add_argument (new CCodeIdentifier ("connection"));
1554 ccall.add_argument (new CCodeIdentifier ("message"));
1556 callblock.add_statement (new CCodeExpressionStatement (ccall));
1558 var cif = new CCodeIfStatement (ccheck, callblock);
1559 if (clastif == null) {
1560 block.add_statement (cif);
1561 } else {
1562 clastif.false_statement = cif;
1565 clastif = cif;
1568 void handle_signals (Interface iface, CCodeBlock block) {
1569 string dbus_iface_name = get_dbus_name (iface);
1571 CCodeIfStatement clastif = null;
1572 foreach (Signal sig in iface.get_signals ()) {
1573 if (sig.access != SymbolAccessibility.PUBLIC) {
1574 continue;
1577 handle_signal (dbus_iface_name, get_dbus_name_for_member (sig), generate_dbus_signal_handler (sig, iface), block, ref clastif);
1581 void generate_marshalling (Method m, string dbus_iface_name, CCodeFragment prefragment, CCodeFragment postfragment) {
1582 CCodeDeclaration cdecl;
1584 var destination = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_bus_name"));
1585 destination.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
1586 var path = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_path"));
1587 path.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
1589 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_call"));
1590 msgcall.add_argument (destination);
1591 msgcall.add_argument (path);
1592 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1593 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
1594 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall)));
1596 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
1597 iter_call.add_argument (new CCodeIdentifier ("_message"));
1598 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
1599 prefragment.append (new CCodeExpressionStatement (iter_call));
1601 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
1602 iter_call.add_argument (new CCodeIdentifier ("_reply"));
1603 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
1604 postfragment.append (new CCodeExpressionStatement (iter_call));
1606 foreach (FormalParameter param in m.get_parameters ()) {
1607 if (param.direction == ParameterDirection.IN) {
1608 if (param.parameter_type.data_type != null
1609 && param.parameter_type.data_type.get_full_name () == "DBus.BusName") {
1610 // ignore BusName sender parameters
1611 continue;
1613 CCodeExpression expr = new CCodeIdentifier (param.name);
1614 if (param.parameter_type.is_real_struct_type ()) {
1615 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
1617 write_expression (prefragment, param.parameter_type, new CCodeIdentifier ("_iter"), expr);
1618 } else {
1619 cdecl = new CCodeDeclaration (param.parameter_type.get_cname ());
1620 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + param.name));
1621 postfragment.append (cdecl);
1623 var array_type = param.parameter_type as ArrayType;
1625 if (array_type != null) {
1626 for (int dim = 1; dim <= array_type.rank; dim++) {
1627 cdecl = new CCodeDeclaration ("int");
1628 cdecl.add_declarator (new CCodeVariableDeclarator ("_%s_length%d".printf (param.name, dim), new CCodeConstant ("0")));
1629 postfragment.append (cdecl);
1633 var target = new CCodeIdentifier ("_" + param.name);
1634 var expr = read_expression (postfragment, param.parameter_type, new CCodeIdentifier ("_iter"), target);
1635 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1637 // TODO check that parameter is not NULL (out parameters are optional)
1638 // free value if parameter is NULL
1639 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (param.name)), target)));
1642 if (array_type != null) {
1643 for (int dim = 1; dim <= array_type.rank; dim++) {
1644 // TODO check that parameter is not NULL (out parameters are optional)
1645 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("%s_length%d".printf (param.name, dim))), new CCodeIdentifier ("_%s_length%d".printf (param.name, dim)))));
1651 if (!(m.return_type is VoidType)) {
1652 if (m.return_type.is_real_non_null_struct_type ()) {
1653 var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
1654 var expr = read_expression (postfragment, m.return_type, new CCodeIdentifier ("_iter"), target);
1655 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1656 } else {
1657 cdecl = new CCodeDeclaration (m.return_type.get_cname ());
1658 cdecl.add_declarator (new CCodeVariableDeclarator ("_result"));
1659 postfragment.append (cdecl);
1661 var array_type = m.return_type as ArrayType;
1663 if (array_type != null) {
1664 for (int dim = 1; dim <= array_type.rank; dim++) {
1665 cdecl = new CCodeDeclaration ("int");
1666 cdecl.add_declarator (new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
1667 postfragment.append (cdecl);
1671 var target = new CCodeIdentifier ("_result");
1672 var expr = read_expression (postfragment, m.return_type, new CCodeIdentifier ("_iter"), target);
1673 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1675 if (array_type != null) {
1676 for (int dim = 1; dim <= array_type.rank; dim++) {
1677 // TODO check that parameter is not NULL (out parameters are optional)
1678 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim)))));
1685 void check_error_reply (Method m, CCodeBlock block) {
1686 var error_types = m.get_error_types ();
1687 if (!has_dbus_error (error_types)) {
1688 Report.error (m.source_reference, "D-Bus methods must throw DBus.Error");
1689 return;
1692 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
1694 var error_block = new CCodeBlock ();
1696 var cdecl = new CCodeDeclaration ("GQuark");
1697 cdecl.add_declarator (new CCodeVariableDeclarator ("_edomain"));
1698 error_block.add_statement (cdecl);
1700 cdecl = new CCodeDeclaration ("gint");
1701 cdecl.add_declarator (new CCodeVariableDeclarator ("_ecode"));
1702 error_block.add_statement (cdecl);
1704 generate_client_error_cases (error_block, error_types, new CCodeMemberAccess (new CCodeIdentifier ("_dbus_error"), "name"), new CCodeIdentifier ("_edomain"), new CCodeIdentifier ("_ecode"));
1706 var g_set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
1707 g_set_error.add_argument (new CCodeIdentifier ("error"));
1708 g_set_error.add_argument (new CCodeIdentifier ("_edomain"));
1709 g_set_error.add_argument (new CCodeIdentifier ("_ecode"));
1710 g_set_error.add_argument (new CCodeConstant ("\"%s\""));
1711 g_set_error.add_argument (new CCodeMemberAccess (new CCodeIdentifier ("_dbus_error"), "message"));
1712 error_block.add_statement (new CCodeExpressionStatement (g_set_error));
1714 var dbus_error_free = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_free"));
1715 dbus_error_free.add_argument (dbus_error);
1716 error_block.add_statement (new CCodeExpressionStatement (dbus_error_free));
1718 if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
1719 error_block.add_statement (new CCodeReturnStatement ());
1720 } else {
1721 error_block.add_statement (new CCodeReturnStatement (default_value_for_type (m.return_type, false)));
1724 var dbus_error_is_set = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_is_set"));
1725 dbus_error_is_set.add_argument (dbus_error);
1726 block.add_statement (new CCodeIfStatement (dbus_error_is_set, error_block));
1729 string generate_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
1730 string proxy_name = "%sdbus_proxy_%s".printf (main_iface.get_lower_case_cprefix (), m.name);
1732 string dbus_iface_name = get_dbus_name (iface);
1734 CCodeDeclaration cdecl;
1736 var function = new CCodeFunction (proxy_name);
1737 function.modifiers = CCodeModifiers.STATIC;
1739 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
1741 generate_cparameters (m, source_declarations, cparam_map, function);
1743 var block = new CCodeBlock ();
1744 var prefragment = new CCodeFragment ();
1745 var postfragment = new CCodeFragment ();
1747 // throw error and return if proxy is disposed
1748 var dispose_return_block = new CCodeBlock ();
1749 if (m.get_error_types ().size > 0) {
1750 var set_error_call = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
1751 set_error_call.add_argument (new CCodeIdentifier ("error"));
1752 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR"));
1753 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR_DISCONNECTED"));
1754 set_error_call.add_argument (new CCodeConstant ("\"%s\""));
1755 set_error_call.add_argument (new CCodeConstant ("\"Connection is closed\""));
1756 dispose_return_block.add_statement (new CCodeExpressionStatement (set_error_call));
1758 if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
1759 dispose_return_block.add_statement (new CCodeReturnStatement ());
1760 } else {
1761 dispose_return_block.add_statement (new CCodeReturnStatement (default_value_for_type (m.return_type, false)));
1763 block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), iface.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block));
1765 cdecl = new CCodeDeclaration ("DBusError");
1766 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
1767 block.add_statement (cdecl);
1769 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
1771 cdecl = new CCodeDeclaration ("DBusGConnection");
1772 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
1773 block.add_statement (cdecl);
1775 cdecl = new CCodeDeclaration ("DBusMessage");
1776 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
1777 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
1778 block.add_statement (cdecl);
1780 cdecl = new CCodeDeclaration ("DBusMessageIter");
1781 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
1782 block.add_statement (cdecl);
1784 block.add_statement (prefragment);
1786 generate_marshalling (m, dbus_iface_name, prefragment, postfragment);
1788 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1789 gconnection.add_argument (new CCodeIdentifier ("self"));
1790 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1791 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
1792 gconnection.add_argument (new CCodeConstant ("NULL"));
1793 block.add_statement (new CCodeExpressionStatement (gconnection));
1795 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
1796 dbus_error_init.add_argument (dbus_error);
1797 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
1799 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1800 connection.add_argument (new CCodeIdentifier ("_connection"));
1802 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
1803 ccall.add_argument (connection);
1804 ccall.add_argument (new CCodeIdentifier ("_message"));
1805 ccall.add_argument (new CCodeConstant ("-1"));
1806 ccall.add_argument (dbus_error);
1807 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
1809 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
1810 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
1811 block.add_statement (new CCodeExpressionStatement (conn_unref));
1813 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1814 message_unref.add_argument (new CCodeIdentifier ("_message"));
1815 block.add_statement (new CCodeExpressionStatement (message_unref));
1817 check_error_reply (m, block);
1818 check_reply_signature (m, block);
1820 block.add_statement (postfragment);
1822 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1823 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
1824 block.add_statement (new CCodeExpressionStatement (reply_unref));
1826 if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) {
1827 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
1830 source_declarations.add_type_member_declaration (function.copy ());
1831 function.block = block;
1832 source_type_member_definition.append (function);
1834 return proxy_name;
1837 void generate_client_error_cases (CCodeBlock error_block, List<DataType> error_types, CCodeExpression dbus_error_name, CCodeExpression result_edomain, CCodeExpression result_ecode) {
1838 CCodeStatement if_else_if = null;
1839 CCodeIfStatement last_statement = null;
1841 foreach (DataType error_type in error_types) {
1842 var edomain = ((ErrorType) error_type).error_domain;
1844 var edomain_dbus_name = get_dbus_name (edomain);
1845 if (edomain_dbus_name == null) {
1846 Report.error (edomain.source_reference, "Errordomain must have a DBus.name annotation to be serialized over DBus");
1849 var true_block = new CCodeBlock ();
1850 true_block.suppress_newline = true;
1852 string temp_name = "_tmp%d_".printf (next_temp_var_id++);
1854 var cdecl = new CCodeDeclaration ("const char*");
1855 cdecl.add_declarator (new CCodeVariableDeclarator (temp_name));
1856 true_block.add_statement (cdecl);
1858 true_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (result_edomain, new CCodeIdentifier (edomain.get_upper_case_cname ()))));
1860 true_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (temp_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, dbus_error_name, new CCodeConstant ("%ld".printf (edomain_dbus_name.length + 1))))));
1862 CCodeStatement inner_if_else_if = null;
1863 CCodeIfStatement inner_last_statement = null;
1864 foreach (ErrorCode ecode in edomain.get_codes ()) {
1865 var inner_true_block = new CCodeBlock ();
1866 inner_true_block.suppress_newline = true;
1867 inner_true_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (result_ecode, new CCodeIdentifier (ecode.get_cname ()))));
1869 var ecode_dbus_name = get_dbus_name (ecode);
1870 if (ecode_dbus_name == null) {
1871 ecode_dbus_name = Symbol.lower_case_to_camel_case (ecode.name.down ());
1874 var string_comparison = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1875 string_comparison.add_argument (new CCodeIdentifier (temp_name));
1876 string_comparison.add_argument (new CCodeConstant ("\"%s\"".printf (ecode_dbus_name)));
1877 var stmt = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, string_comparison, new CCodeConstant ("0")), inner_true_block);
1879 if (inner_last_statement != null) {
1880 inner_last_statement.false_statement = stmt;
1881 } else {
1882 inner_if_else_if = stmt;
1884 inner_last_statement = stmt;
1886 true_block.add_statement (inner_if_else_if);
1888 var string_comparison = new CCodeFunctionCall (new CCodeIdentifier ("strstr"));
1889 string_comparison.add_argument (dbus_error_name);
1890 string_comparison.add_argument (new CCodeConstant ("\"%s\"".printf (edomain_dbus_name)));
1891 var stmt = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, string_comparison, dbus_error_name), true_block);
1893 if (last_statement != null) {
1894 last_statement.false_statement = stmt;
1895 } else {
1896 if_else_if = stmt;
1898 last_statement = stmt;
1900 error_block.add_statement (if_else_if);
1903 string generate_async_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
1904 string proxy_name = "%sdbus_proxy_%s_async".printf (main_iface.get_lower_case_cprefix (), m.name);
1906 string dbus_iface_name = get_dbus_name (iface);
1908 CCodeDeclaration cdecl;
1911 // generate data struct
1913 string dataname = "%sDBusProxy%sData".printf (iface.get_cname (), Symbol.lower_case_to_camel_case (m.name));
1914 var datastruct = new CCodeStruct ("_" + dataname);
1916 datastruct.add_field ("GAsyncReadyCallback", "_callback_");
1917 datastruct.add_field ("gpointer", "_user_data_");
1918 datastruct.add_field ("DBusPendingCall*", "pending");
1920 source_declarations.add_type_definition (datastruct);
1921 source_declarations.add_type_declaration (new CCodeTypeDefinition ("struct _" + dataname, new CCodeVariableDeclarator (dataname)));
1924 // generate async function
1926 var function = new CCodeFunction (proxy_name, "void");
1927 function.modifiers = CCodeModifiers.STATIC;
1929 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
1931 cparam_map.set (get_param_pos (-1), new CCodeFormalParameter ("_callback_", "GAsyncReadyCallback"));
1932 cparam_map.set (get_param_pos (-0.9), new CCodeFormalParameter ("_user_data_", "gpointer"));
1934 generate_cparameters (m, source_declarations, cparam_map, function, null, null, null, 1);
1936 var block = new CCodeBlock ();
1937 var prefragment = new CCodeFragment ();
1938 var postfragment = new CCodeFragment ();
1940 cdecl = new CCodeDeclaration ("DBusGConnection");
1941 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
1942 block.add_statement (cdecl);
1944 cdecl = new CCodeDeclaration ("DBusMessage");
1945 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
1946 block.add_statement (cdecl);
1948 cdecl = new CCodeDeclaration ("DBusPendingCall");
1949 cdecl.add_declarator (new CCodeVariableDeclarator ("*_pending"));
1950 block.add_statement (cdecl);
1952 cdecl = new CCodeDeclaration ("DBusMessageIter");
1953 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
1954 block.add_statement (cdecl);
1956 block.add_statement (prefragment);
1958 generate_marshalling (m, dbus_iface_name, prefragment, postfragment);
1960 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1961 gconnection.add_argument (new CCodeIdentifier ("self"));
1962 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1963 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
1964 gconnection.add_argument (new CCodeConstant ("NULL"));
1965 block.add_statement (new CCodeExpressionStatement (gconnection));
1967 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1968 connection.add_argument (new CCodeIdentifier ("_connection"));
1970 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply"));
1971 ccall.add_argument (connection);
1972 ccall.add_argument (new CCodeIdentifier ("_message"));
1973 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_pending")));
1974 ccall.add_argument (new CCodeConstant ("-1"));
1975 block.add_statement (new CCodeExpressionStatement (ccall));
1977 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
1978 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
1979 block.add_statement (new CCodeExpressionStatement (conn_unref));
1981 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1982 message_unref.add_argument (new CCodeIdentifier ("_message"));
1983 block.add_statement (new CCodeExpressionStatement (message_unref));
1985 var dataalloc = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
1986 dataalloc.add_argument (new CCodeIdentifier (dataname));
1988 var datadecl = new CCodeDeclaration (dataname + "*");
1989 datadecl.add_declarator (new CCodeVariableDeclarator ("_data_"));
1990 block.add_statement (datadecl);
1991 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_data_"), dataalloc)));
1993 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_callback_"), new CCodeIdentifier ("_callback_"))));
1994 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_user_data_"), new CCodeIdentifier ("_user_data_"))));
1995 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "pending"), new CCodeIdentifier ("_pending"))));
1997 var pending = new CCodeFunctionCall (new CCodeIdentifier ("dbus_pending_call_set_notify"));
1998 pending.add_argument (new CCodeIdentifier ("_pending"));
1999 pending.add_argument (new CCodeIdentifier ("%sdbus_proxy_%s_ready".printf (iface.get_lower_case_cprefix (), m.name)));
2000 pending.add_argument (new CCodeIdentifier ("_data_"));
2001 pending.add_argument (new CCodeConstant ("NULL"));
2002 block.add_statement (new CCodeExpressionStatement (pending));
2004 source_declarations.add_type_member_declaration (function.copy ());
2005 function.block = block;
2006 source_type_member_definition.append (function);
2009 // generate ready function
2011 function = new CCodeFunction ("%sdbus_proxy_%s_ready".printf (iface.get_lower_case_cprefix (), m.name), "void");
2012 function.modifiers = CCodeModifiers.STATIC;
2014 function.add_parameter (new CCodeFormalParameter ("pending", "DBusPendingCall*"));
2015 function.add_parameter (new CCodeFormalParameter ("user_data", "void*"));
2017 block = new CCodeBlock ();
2019 datadecl = new CCodeDeclaration (dataname + "*");
2020 datadecl.add_declarator (new CCodeVariableDeclarator ("_data_"));
2021 block.add_statement (datadecl);
2022 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_data_"), new CCodeIdentifier ("user_data"))));
2024 // complete async call by invoking callback
2025 var obj_decl = new CCodeDeclaration ("GObject *");
2026 obj_decl.add_declarator (new CCodeVariableDeclarator ("_obj_"));
2027 block.add_statement (obj_decl);
2029 var object_creation = new CCodeFunctionCall (new CCodeIdentifier ("g_object_newv"));
2030 object_creation.add_argument (new CCodeConstant ("G_TYPE_OBJECT"));
2031 object_creation.add_argument (new CCodeConstant ("0"));
2032 object_creation.add_argument (new CCodeConstant ("NULL"));
2033 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_obj_"), object_creation)));
2035 var async_result_decl = new CCodeDeclaration ("GSimpleAsyncResult *");
2036 async_result_decl.add_declarator (new CCodeVariableDeclarator ("_res_"));
2037 block.add_statement (async_result_decl);
2039 var async_result_creation = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_new"));
2040 async_result_creation.add_argument (new CCodeIdentifier ("_obj_"));
2041 async_result_creation.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_callback_"));
2042 async_result_creation.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_user_data_"));
2043 async_result_creation.add_argument (new CCodeIdentifier ("_data_"));
2044 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_res_"), async_result_creation)));
2046 var completecall = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete"));
2047 completecall.add_argument (new CCodeIdentifier ("_res_"));
2048 block.add_statement (new CCodeExpressionStatement (completecall));
2050 var obj_free = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
2051 obj_free.add_argument (new CCodeIdentifier ("_obj_"));
2052 block.add_statement (new CCodeExpressionStatement (obj_free));
2054 var async_result_free = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
2055 async_result_free.add_argument (new CCodeIdentifier ("_res_"));
2056 block.add_statement (new CCodeExpressionStatement (async_result_free));
2058 var datafree = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
2059 datafree.add_argument (new CCodeIdentifier (dataname));
2060 datafree.add_argument (new CCodeIdentifier ("_data_"));
2061 block.add_statement (new CCodeExpressionStatement (datafree));
2063 var pendingfree = new CCodeFunctionCall (new CCodeIdentifier ("dbus_pending_call_unref"));
2064 pendingfree.add_argument (new CCodeIdentifier ("pending"));
2065 block.add_statement (new CCodeExpressionStatement (pendingfree));
2067 source_declarations.add_type_member_declaration (function.copy ());
2068 function.block = block;
2069 source_type_member_definition.append (function);
2072 return proxy_name;
2075 CCodeConstant get_reply_signature (Method m) {
2076 // expected type signature for output parameters
2077 string type_signature = "";
2079 foreach (FormalParameter param in m.get_parameters ()) {
2080 if (param.direction == ParameterDirection.OUT) {
2081 type_signature += get_type_signature (param.parameter_type);
2085 if (!(m.return_type is VoidType)) {
2086 type_signature += get_type_signature (m.return_type);
2089 return (new CCodeConstant ("\"%s\"".printf (type_signature)));
2092 void check_reply_signature (Method m, CCodeBlock block) {
2093 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2094 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2096 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
2097 message_signature.add_argument (new CCodeIdentifier ("_reply"));
2099 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
2100 signature_check.add_argument (message_signature);
2101 signature_check.add_argument (get_reply_signature (m));
2103 var signature_error_block = new CCodeBlock ();
2104 var set_error_call = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
2105 set_error_call.add_argument (new CCodeIdentifier ("error"));
2106 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR"));
2107 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR_INVALID_SIGNATURE"));
2108 set_error_call.add_argument (new CCodeConstant ("\"Invalid signature, expected \\\"%s\\\", got \\\"%s\\\"\""));
2109 set_error_call.add_argument (get_reply_signature (m));
2110 set_error_call.add_argument (message_signature);
2111 signature_error_block.add_statement (new CCodeExpressionStatement (set_error_call));
2112 signature_error_block.add_statement (new CCodeExpressionStatement (reply_unref));
2113 signature_error_block.add_statement (new CCodeReturnStatement (default_value_for_type (m.return_type, false)));
2115 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
2118 string generate_finish_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
2119 string proxy_name = "%sdbus_proxy_%s_finish".printf (main_iface.get_lower_case_cprefix (), m.name);
2121 string dbus_iface_name = get_dbus_name (iface);
2123 CCodeDeclaration cdecl;
2125 var function = new CCodeFunction (proxy_name);
2126 function.modifiers = CCodeModifiers.STATIC;
2128 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
2130 cparam_map.set (get_param_pos (0.1), new CCodeFormalParameter ("_res_", "GAsyncResult*"));
2132 generate_cparameters (m, source_declarations, cparam_map, function, null, null, null, 2);
2134 var block = new CCodeBlock ();
2135 var prefragment = new CCodeFragment ();
2136 var postfragment = new CCodeFragment ();
2138 string dataname = "%sDBusProxy%sData".printf (iface.get_cname (), Symbol.lower_case_to_camel_case (m.name));
2139 cdecl = new CCodeDeclaration (dataname + "*");
2140 cdecl.add_declarator (new CCodeVariableDeclarator ("_data_"));
2141 block.add_statement (cdecl);
2143 cdecl = new CCodeDeclaration ("DBusError");
2144 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
2145 block.add_statement (cdecl);
2147 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
2149 cdecl = new CCodeDeclaration ("DBusMessage");
2150 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
2151 block.add_statement (cdecl);
2153 cdecl = new CCodeDeclaration ("DBusMessageIter");
2154 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
2155 block.add_statement (cdecl);
2157 var get_source_tag = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_get_source_tag"));
2158 get_source_tag.add_argument (new CCodeCastExpression (new CCodeIdentifier ("_res_"), "GSimpleAsyncResult *"));
2159 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_data_"), get_source_tag)));
2161 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
2162 dbus_error_init.add_argument (dbus_error);
2163 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
2165 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_pending_call_steal_reply"));
2166 ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "pending"));
2167 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
2169 var set_error_from_message = new CCodeFunctionCall (new CCodeIdentifier ("dbus_set_error_from_message"));
2170 set_error_from_message.add_argument (dbus_error);
2171 set_error_from_message.add_argument (new CCodeIdentifier ("_reply"));
2172 block.add_statement (new CCodeExpressionStatement (set_error_from_message));
2174 check_error_reply (m, block);
2175 check_reply_signature (m, block);
2177 generate_marshalling (m, dbus_iface_name, prefragment, postfragment);
2179 block.add_statement (postfragment);
2181 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2182 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2183 block.add_statement (new CCodeExpressionStatement (reply_unref));
2185 if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) {
2186 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
2189 source_declarations.add_type_member_declaration (function.copy ());
2190 function.block = block;
2191 source_type_member_definition.append (function);
2193 return proxy_name;
2196 void check_property_error_reply (PropertyAccessor acc, CCodeBlock block) {
2197 var dbus_error = new CCodeIdentifier ("_dbus_error");
2198 var dbus_error_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, dbus_error);
2200 var error_block = new CCodeBlock ();
2202 var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
2203 ccritical.add_argument (new CCodeConstant ("\"file %s: line %d: uncaught error: %s (%s)\""));
2204 ccritical.add_argument (new CCodeConstant ("__FILE__"));
2205 ccritical.add_argument (new CCodeConstant ("__LINE__"));
2206 ccritical.add_argument (new CCodeMemberAccess (dbus_error, "message"));
2207 ccritical.add_argument (new CCodeMemberAccess (dbus_error, "name"));
2209 error_block.add_statement (new CCodeExpressionStatement (ccritical));
2211 var dbus_error_free = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_free"));
2212 dbus_error_free.add_argument (dbus_error_ptr);
2213 error_block.add_statement (new CCodeExpressionStatement (dbus_error_free));
2215 if (acc.readable && !acc.value_type.is_real_non_null_struct_type ()) {
2216 error_block.add_statement (new CCodeReturnStatement (default_value_for_type (acc.value_type, false)));
2217 } else {
2218 error_block.add_statement (new CCodeReturnStatement ());
2221 var dbus_error_is_set = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_is_set"));
2222 dbus_error_is_set.add_argument (dbus_error_ptr);
2223 block.add_statement (new CCodeIfStatement (dbus_error_is_set, error_block));
2226 CCodeConstant get_property_reply_signature (PropertyAccessor acc) {
2227 if (acc.readable) {
2228 return new CCodeConstant ("\"v\"");
2229 } else {
2230 return new CCodeConstant ("\"\"");
2234 CCodeConstant get_property_inner_signature (PropertyAccessor acc) {
2235 return new CCodeConstant ("\"%s\"".printf (get_type_signature (acc.value_type)));
2238 void check_property_reply_signature (PropertyAccessor acc, CCodeBlock block) {
2239 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2240 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2242 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
2243 message_signature.add_argument (new CCodeIdentifier ("_reply"));
2245 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
2246 signature_check.add_argument (message_signature);
2247 signature_check.add_argument (get_property_reply_signature (acc));
2249 var signature_error_block = new CCodeBlock ();
2251 var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
2252 ccritical.add_argument (new CCodeConstant ("\"file %s: line %d: Invalid signature, expected \\\"%s\\\", got \\\"%s\\\"\""));
2253 ccritical.add_argument (new CCodeConstant ("__FILE__"));
2254 ccritical.add_argument (new CCodeConstant ("__LINE__"));
2255 ccritical.add_argument (get_property_reply_signature (acc));
2256 ccritical.add_argument (message_signature);
2258 signature_error_block.add_statement (new CCodeExpressionStatement (ccritical));
2259 signature_error_block.add_statement (new CCodeExpressionStatement (reply_unref));
2261 if (acc.readable && !acc.value_type.is_real_non_null_struct_type ()) {
2262 signature_error_block.add_statement (new CCodeReturnStatement (default_value_for_type (acc.value_type, false)));
2263 } else {
2264 signature_error_block.add_statement (new CCodeReturnStatement ());
2267 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
2270 void check_property_inner_signature (PropertyAccessor acc, CCodeFragment fragment) {
2271 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2272 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2274 var iter_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_get_signature"));
2275 iter_signature.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter")));
2277 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
2278 signature_check.add_argument (iter_signature);
2279 signature_check.add_argument (get_property_inner_signature (acc));
2281 var signature_error_block = new CCodeBlock ();
2283 var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
2284 ccritical.add_argument (new CCodeConstant ("\"file %s: line %d: Invalid signature, expected \\\"%s\\\", got \\\"%s\\\"\""));
2285 ccritical.add_argument (new CCodeConstant ("__FILE__"));
2286 ccritical.add_argument (new CCodeConstant ("__LINE__"));
2287 ccritical.add_argument (get_property_inner_signature (acc));
2288 ccritical.add_argument (iter_signature);
2290 signature_error_block.add_statement (new CCodeExpressionStatement (ccritical));
2291 signature_error_block.add_statement (new CCodeExpressionStatement (reply_unref));
2293 if (!acc.value_type.is_real_non_null_struct_type ()) {
2294 signature_error_block.add_statement (new CCodeReturnStatement (default_value_for_type (acc.value_type, false)));
2295 } else {
2296 signature_error_block.add_statement (new CCodeReturnStatement ());
2299 fragment.append (new CCodeIfStatement (signature_check, signature_error_block));
2302 string generate_dbus_proxy_property_get (Interface main_iface, Interface iface, Property prop) {
2303 string proxy_name = "%sdbus_proxy_get_%s".printf (main_iface.get_lower_case_cprefix (), prop.name);
2305 string dbus_iface_name = get_dbus_name (iface);
2307 var owned_type = prop.get_accessor.value_type.copy ();
2308 owned_type.value_owned = true;
2309 if (owned_type.is_disposable () && !prop.get_accessor.value_type.value_owned) {
2310 Report.error (prop.get_accessor.value_type.source_reference, "Properties used in D-Bus clients require owned get accessor");
2313 var array_type = prop.get_accessor.value_type as ArrayType;
2315 CCodeDeclaration cdecl;
2317 var function = new CCodeFunction (proxy_name);
2318 function.modifiers = CCodeModifiers.STATIC;
2320 function.add_parameter (new CCodeFormalParameter ("self", "%s*".printf (iface.get_cname ())));
2322 if (prop.property_type.is_real_non_null_struct_type ()) {
2323 function.add_parameter (new CCodeFormalParameter ("result", "%s*".printf (prop.get_accessor.value_type.get_cname ())));
2324 } else {
2325 if (array_type != null) {
2326 for (int dim = 1; dim <= array_type.rank; dim++) {
2327 function.add_parameter (new CCodeFormalParameter ("result_length%d".printf (dim), "int*"));
2331 function.return_type = prop.get_accessor.value_type.get_cname ();
2334 var block = new CCodeBlock ();
2335 var prefragment = new CCodeFragment ();
2336 var postfragment = new CCodeFragment ();
2338 var dispose_return_block = new CCodeBlock ();
2339 if (prop.property_type.is_real_non_null_struct_type ()) {
2340 dispose_return_block.add_statement (new CCodeReturnStatement ());
2341 } else {
2342 dispose_return_block.add_statement (new CCodeReturnStatement (default_value_for_type (prop.property_type, false)));
2344 block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), iface.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block));
2346 cdecl = new CCodeDeclaration ("DBusError");
2347 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
2348 block.add_statement (cdecl);
2350 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
2352 cdecl = new CCodeDeclaration ("DBusGConnection");
2353 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
2354 block.add_statement (cdecl);
2356 cdecl = new CCodeDeclaration ("DBusMessage");
2357 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
2358 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
2359 block.add_statement (cdecl);
2361 cdecl = new CCodeDeclaration ("DBusMessageIter");
2362 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
2363 cdecl.add_declarator (new CCodeVariableDeclarator ("_subiter"));
2364 block.add_statement (cdecl);
2366 block.add_statement (prefragment);
2368 var destination = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_bus_name"));
2369 destination.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
2370 var path = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_path"));
2371 path.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
2373 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_call"));
2374 msgcall.add_argument (destination);
2375 msgcall.add_argument (path);
2376 msgcall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties\""));
2377 msgcall.add_argument (new CCodeConstant ("\"Get\""));
2378 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall)));
2380 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
2381 iter_call.add_argument (new CCodeIdentifier ("_message"));
2382 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2383 prefragment.append (new CCodeExpressionStatement (iter_call));
2385 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
2386 iter_call.add_argument (new CCodeIdentifier ("_reply"));
2387 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2388 postfragment.append (new CCodeExpressionStatement (iter_call));
2390 // interface name
2391 write_expression (prefragment, string_type, new CCodeIdentifier ("_iter"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
2392 // property name
2393 write_expression (prefragment, string_type, new CCodeIdentifier ("_iter"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
2395 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_recurse"));
2396 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2397 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter")));
2398 postfragment.append (new CCodeExpressionStatement (iter_call));
2400 check_property_inner_signature (prop.get_accessor, postfragment);
2402 if (prop.property_type.is_real_non_null_struct_type ()) {
2403 var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
2404 var expr = read_expression (postfragment, prop.get_accessor.value_type, new CCodeIdentifier ("_subiter"), target);
2405 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
2406 } else {
2407 cdecl = new CCodeDeclaration (prop.get_accessor.value_type.get_cname ());
2408 cdecl.add_declarator (new CCodeVariableDeclarator ("_result"));
2409 postfragment.append (cdecl);
2411 if (array_type != null) {
2412 for (int dim = 1; dim <= array_type.rank; dim++) {
2413 cdecl = new CCodeDeclaration ("int");
2414 cdecl.add_declarator (new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
2415 postfragment.append (cdecl);
2419 var target = new CCodeIdentifier ("_result");
2420 var expr = read_expression (postfragment, prop.get_accessor.value_type, new CCodeIdentifier ("_subiter"), target);
2421 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
2423 if (array_type != null) {
2424 for (int dim = 1; dim <= array_type.rank; dim++) {
2425 // TODO check that parameter is not NULL (out parameters are optional)
2426 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim)))));
2431 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
2432 gconnection.add_argument (new CCodeIdentifier ("self"));
2433 gconnection.add_argument (new CCodeConstant ("\"connection\""));
2434 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
2435 gconnection.add_argument (new CCodeConstant ("NULL"));
2436 block.add_statement (new CCodeExpressionStatement (gconnection));
2438 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
2439 dbus_error_init.add_argument (dbus_error);
2440 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
2442 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
2443 connection.add_argument (new CCodeIdentifier ("_connection"));
2445 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
2446 ccall.add_argument (connection);
2447 ccall.add_argument (new CCodeIdentifier ("_message"));
2448 ccall.add_argument (new CCodeConstant ("-1"));
2449 ccall.add_argument (dbus_error);
2450 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
2452 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
2453 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
2454 block.add_statement (new CCodeExpressionStatement (conn_unref));
2456 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2457 message_unref.add_argument (new CCodeIdentifier ("_message"));
2458 block.add_statement (new CCodeExpressionStatement (message_unref));
2460 check_property_error_reply (prop.get_accessor, block);
2461 check_property_reply_signature (prop.get_accessor, block);
2463 block.add_statement (postfragment);
2465 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2466 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2467 block.add_statement (new CCodeExpressionStatement (reply_unref));
2469 if (prop.property_type.is_real_non_null_struct_type ()) {
2470 block.add_statement (new CCodeReturnStatement ());
2471 } else {
2472 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
2475 source_declarations.add_type_member_declaration (function.copy ());
2476 function.block = block;
2477 source_type_member_definition.append (function);
2479 return proxy_name;
2482 string generate_dbus_proxy_property_set (Interface main_iface, Interface iface, Property prop) {
2483 string proxy_name = "%sdbus_proxy_set_%s".printf (main_iface.get_lower_case_cprefix (), prop.name);
2485 string dbus_iface_name = get_dbus_name (iface);
2487 var array_type = prop.set_accessor.value_type as ArrayType;
2489 CCodeDeclaration cdecl;
2491 var function = new CCodeFunction (proxy_name);
2492 function.modifiers = CCodeModifiers.STATIC;
2494 function.add_parameter (new CCodeFormalParameter ("self", "%s*".printf (iface.get_cname ())));
2496 if (prop.property_type.is_real_non_null_struct_type ()) {
2497 function.add_parameter (new CCodeFormalParameter ("value", "%s*".printf (prop.set_accessor.value_type.get_cname ())));
2498 } else {
2499 function.add_parameter (new CCodeFormalParameter ("value", prop.set_accessor.value_type.get_cname ()));
2501 if (array_type != null) {
2502 for (int dim = 1; dim <= array_type.rank; dim++) {
2503 function.add_parameter (new CCodeFormalParameter ("value_length%d".printf (dim), "int"));
2508 var block = new CCodeBlock ();
2509 var prefragment = new CCodeFragment ();
2510 var postfragment = new CCodeFragment ();
2512 var dispose_return_block = new CCodeBlock ();
2513 dispose_return_block.add_statement (new CCodeReturnStatement ());
2514 block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), iface.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block));
2516 cdecl = new CCodeDeclaration ("DBusError");
2517 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
2518 block.add_statement (cdecl);
2520 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
2522 cdecl = new CCodeDeclaration ("DBusGConnection");
2523 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
2524 block.add_statement (cdecl);
2526 cdecl = new CCodeDeclaration ("DBusMessage");
2527 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
2528 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
2529 block.add_statement (cdecl);
2531 cdecl = new CCodeDeclaration ("DBusMessageIter");
2532 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
2533 cdecl.add_declarator (new CCodeVariableDeclarator ("_subiter"));
2534 block.add_statement (cdecl);
2536 block.add_statement (prefragment);
2538 var destination = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_bus_name"));
2539 destination.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
2540 var path = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_path"));
2541 path.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
2543 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_call"));
2544 msgcall.add_argument (destination);
2545 msgcall.add_argument (path);
2546 msgcall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties\""));
2547 msgcall.add_argument (new CCodeConstant ("\"Set\""));
2548 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall)));
2550 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
2551 iter_call.add_argument (new CCodeIdentifier ("_message"));
2552 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2553 prefragment.append (new CCodeExpressionStatement (iter_call));
2555 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
2556 iter_call.add_argument (new CCodeIdentifier ("_reply"));
2557 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2558 postfragment.append (new CCodeExpressionStatement (iter_call));
2560 // interface name
2561 write_expression (prefragment, string_type, new CCodeIdentifier ("_iter"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
2562 // property name
2563 write_expression (prefragment, string_type, new CCodeIdentifier ("_iter"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
2565 // property value (as variant)
2566 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
2567 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2568 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_VARIANT"));
2569 iter_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_signature (prop.property_type))));
2570 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter")));
2571 prefragment.append (new CCodeExpressionStatement (iter_call));
2573 if (prop.property_type.is_real_non_null_struct_type ()) {
2574 write_expression (prefragment, prop.set_accessor.value_type, new CCodeIdentifier ("_subiter"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("value")));
2575 } else {
2576 write_expression (prefragment, prop.set_accessor.value_type, new CCodeIdentifier ("_subiter"), new CCodeIdentifier ("value"));
2579 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
2580 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2581 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter")));
2582 prefragment.append (new CCodeExpressionStatement (iter_call));
2584 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
2585 gconnection.add_argument (new CCodeIdentifier ("self"));
2586 gconnection.add_argument (new CCodeConstant ("\"connection\""));
2587 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
2588 gconnection.add_argument (new CCodeConstant ("NULL"));
2589 block.add_statement (new CCodeExpressionStatement (gconnection));
2591 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
2592 dbus_error_init.add_argument (dbus_error);
2593 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
2595 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
2596 connection.add_argument (new CCodeIdentifier ("_connection"));
2598 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
2599 ccall.add_argument (connection);
2600 ccall.add_argument (new CCodeIdentifier ("_message"));
2601 ccall.add_argument (new CCodeConstant ("-1"));
2602 ccall.add_argument (dbus_error);
2603 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
2605 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
2606 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
2607 block.add_statement (new CCodeExpressionStatement (conn_unref));
2609 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2610 message_unref.add_argument (new CCodeIdentifier ("_message"));
2611 block.add_statement (new CCodeExpressionStatement (message_unref));
2613 check_property_error_reply (prop.set_accessor, block);
2614 check_property_reply_signature (prop.set_accessor, block);
2616 block.add_statement (postfragment);
2618 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2619 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2620 block.add_statement (new CCodeExpressionStatement (reply_unref));
2622 source_declarations.add_type_member_declaration (function.copy ());
2623 function.block = block;
2624 source_type_member_definition.append (function);
2626 return proxy_name;