D-Bus: Fix signal name mangling in dynamic dbus-glib clients
[vala-lang.git] / codegen / valadbusclientmodule.vala
blobf6e39ee24819b7649dcca34cd8b3a13800a4f177
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 public 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 public CCodeConstant get_dbus_timeout (Symbol symbol) {
48 int timeout = -1;
50 var dbus = symbol.get_attribute ("DBus");
51 if (dbus != null && dbus.has_argument ("timeout")) {
52 timeout = dbus.get_integer ("timeout");
53 } else if (symbol.parent_symbol != null) {
54 return get_dbus_timeout (symbol.parent_symbol);
57 return new CCodeConstant (timeout.to_string ());
60 bool has_dbus_error (List<DataType> error_types) {
61 foreach (DataType error_type in error_types) {
62 if (((ErrorType) error_type).error_domain.get_full_name () == "DBus.Error") {
63 return true;
66 return false;
69 public override void generate_dynamic_method_wrapper (DynamicMethod method) {
70 var dynamic_method = (DynamicMethod) method;
72 var func = new CCodeFunction (method.get_cname ());
73 func.modifiers = CCodeModifiers.STATIC;
75 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
77 generate_cparameters (method, source_declarations, cparam_map, func);
79 var block = new CCodeBlock ();
80 if (dynamic_method.dynamic_type.data_type == dbus_object_type) {
81 generate_dbus_method_wrapper (method, block);
82 } else {
83 Report.error (method.source_reference, "dynamic methods are not supported for `%s'".printf (dynamic_method.dynamic_type.to_string ()));
86 // append to C source file
87 source_declarations.add_type_member_declaration (func.copy ());
89 func.block = block;
90 source_type_member_definition.append (func);
93 void generate_dbus_method_wrapper (Method method, CCodeBlock block) {
94 var dynamic_method = (DynamicMethod) method;
96 var expr = dynamic_method.invocation;
98 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_begin_call"));
100 ccall.add_argument (new CCodeIdentifier ("self"));
102 bool found_out = false;
103 Expression callback = null;
104 int callback_index = -1;
105 int arg_index = 1;
106 foreach (Expression arg in expr.get_argument_list ()) {
107 if (arg.symbol_reference is Method) {
108 // callback
109 if (callback != null) {
110 Report.error (expr.source_reference, "only one reply callback may be specified in invocation of DBus method");
111 expr.error = true;
112 return;
113 } else if (found_out) {
114 Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method");
115 expr.error = true;
116 return;
118 callback = arg;
119 callback_index = arg_index;
120 } else if (arg is UnaryExpression && ((UnaryExpression) arg).operator == UnaryOperator.OUT) {
121 // out arg
122 if (callback != null) {
123 Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method");
124 expr.error = true;
125 return;
127 found_out = true;
128 } else {
129 // in arg
130 if (callback != null || found_out) {
131 Report.error (expr.source_reference, "in argument must not follow out argument or reply callback in invocation of DBus method");
132 expr.error = true;
133 return;
136 arg_index++;
139 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (method.name))));
141 if (callback != null) {
142 var reply_method = (Method) callback.symbol_reference;
144 var cb_fun = new CCodeFunction ("_%s_cb".printf (reply_method.get_cname ()), "void");
145 cb_fun.modifiers = CCodeModifiers.STATIC;
146 cb_fun.add_parameter (new CCodeFormalParameter ("proxy", "DBusGProxy*"));
147 cb_fun.add_parameter (new CCodeFormalParameter ("call", "DBusGProxyCall*"));
148 cb_fun.add_parameter (new CCodeFormalParameter ("user_data", "void*"));
149 cb_fun.block = new CCodeBlock ();
150 var cerrdecl = new CCodeDeclaration ("GError*");
151 cerrdecl.add_declarator (new CCodeVariableDeclarator ("error", new CCodeConstant ("NULL")));
152 cb_fun.block.add_statement (cerrdecl);
153 var cend_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_end_call"));
154 cend_call.add_argument (new CCodeIdentifier ("proxy"));
155 cend_call.add_argument (new CCodeIdentifier ("call"));
156 cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
157 var creply_call = new CCodeFunctionCall ((CCodeExpression) callback.ccodenode);
158 if (reply_method.binding != MemberBinding.STATIC) {
159 creply_call.add_argument (new CCodeIdentifier ("user_data"));
161 int param_count = reply_method.get_parameters ().size;
162 int i = 0;
163 foreach (FormalParameter param in reply_method.get_parameters ()) {
164 if ((++i) == param_count) {
165 if (!(param.parameter_type is ErrorType)) {
166 Report.error (null, "DBus reply callbacks must end with GLib.Error argument");
167 return;
170 break;
172 if (param.parameter_type is ArrayType && ((ArrayType) param.parameter_type).element_type.data_type != string_type.data_type) {
173 var array_type = (ArrayType) param.parameter_type;
174 CCodeDeclaration cdecl;
175 if (dbus_use_ptr_array (array_type)) {
176 cdecl = new CCodeDeclaration ("GPtrArray*");
177 } else {
178 cdecl = new CCodeDeclaration ("GArray*");
180 cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
181 cb_fun.block.add_statement (cdecl);
182 cend_call.add_argument (get_dbus_g_type (array_type));
183 cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
184 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 ()));
185 creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "len"));
186 } else {
187 var cdecl = new CCodeDeclaration (param.parameter_type.get_cname ());
188 cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
189 cb_fun.block.add_statement (cdecl);
190 cend_call.add_argument (get_dbus_g_type (param.parameter_type));
191 cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
192 creply_call.add_argument (new CCodeIdentifier (param.name));
194 if (param.parameter_type is ArrayType && ((ArrayType) param.parameter_type).element_type.data_type == string_type.data_type) {
195 var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
196 cstrvlen.add_argument (new CCodeIdentifier (param.name));
197 creply_call.add_argument (cstrvlen);
202 cend_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
203 cb_fun.block.add_statement (new CCodeExpressionStatement (cend_call));
204 creply_call.add_argument (new CCodeIdentifier ("error"));
205 cb_fun.block.add_statement (new CCodeExpressionStatement (creply_call));
207 CCodeExpression target = new CCodeConstant ("param%d_target".printf (callback_index));
208 var ma = (MemberAccess) callback;
209 if (reply_method.binding != MemberBinding.STATIC && ma.inner.value_type.data_type != null && ma.inner.value_type.data_type.is_reference_counting ()) {
210 // unref user_data after creply_call
211 var unref_call = new CCodeFunctionCall (get_destroy_func_expression (ma.inner.value_type));
212 unref_call.add_argument (new CCodeIdentifier ("user_data"));
213 cb_fun.block.add_statement (new CCodeExpressionStatement (unref_call));
215 // ref target for ccall
216 var ref_call = new CCodeFunctionCall (get_dup_func_expression (ma.inner.value_type, callback.source_reference));
217 ref_call.add_argument (target);
218 target = ref_call;
221 if (!source_declarations.add_declaration (cb_fun.name)) {
222 // avoid duplicate function definition
223 source_type_member_definition.append (cb_fun);
226 ccall.add_argument (new CCodeIdentifier (cb_fun.name));
227 ccall.add_argument (target);
228 ccall.add_argument (new CCodeConstant ("NULL"));
229 } else {
230 ccall.call = new CCodeIdentifier ("dbus_g_proxy_call");
232 ccall.add_argument (new CCodeIdentifier ("error"));
235 foreach (FormalParameter param in method.get_parameters ()) {
236 if (param.parameter_type is MethodType
237 || param.parameter_type is DelegateType) {
238 // callback parameter
239 break;
242 if (param.direction != ParameterDirection.IN) {
243 continue;
246 var array_type = param.parameter_type as ArrayType;
247 if (array_type != null) {
248 // array parameter
249 if (array_type.element_type.data_type != string_type.data_type) {
250 // non-string arrays (use GArray)
251 ccall.add_argument (get_dbus_g_type (array_type));
253 var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
254 sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
256 CCodeDeclaration cdecl;
257 CCodeFunctionCall array_construct;
258 if (dbus_use_ptr_array (array_type)) {
259 cdecl = new CCodeDeclaration ("GPtrArray*");
261 array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_ptr_array_sized_new"));
262 array_construct.add_argument (new CCodeIdentifier (head.get_array_length_cname (param.name, 1)));
263 } else {
264 cdecl = new CCodeDeclaration ("GArray*");
266 array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_array_new"));
267 array_construct.add_argument (new CCodeConstant ("TRUE"));
268 array_construct.add_argument (new CCodeConstant ("TRUE"));
269 array_construct.add_argument (sizeof_call);
272 cdecl.add_declarator (new CCodeVariableDeclarator ("dbus_%s".printf (param.name), array_construct));
273 block.add_statement (cdecl);
275 if (dbus_use_ptr_array (array_type)) {
276 source_declarations.add_include ("string.h");
278 var memcpy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
279 memcpy_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_%s".printf (param.name)), "pdata"));
280 memcpy_call.add_argument (new CCodeIdentifier (param.name));
281 memcpy_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeIdentifier (head.get_array_length_cname (param.name, 1)), sizeof_call));
282 block.add_statement (new CCodeExpressionStatement (memcpy_call));
284 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)));
285 block.add_statement (new CCodeExpressionStatement (len_assignment));
286 } else {
287 var cappend_call = new CCodeFunctionCall (new CCodeIdentifier ("g_array_append_vals"));
288 cappend_call.add_argument (new CCodeIdentifier ("dbus_%s".printf (param.name)));
289 cappend_call.add_argument (new CCodeIdentifier (param.name));
290 cappend_call.add_argument (new CCodeIdentifier (head.get_array_length_cname (param.name, 1)));
291 block.add_statement (new CCodeExpressionStatement (cappend_call));
294 ccall.add_argument (new CCodeIdentifier ("dbus_%s".printf (param.name)));
295 } else {
296 // string arrays
297 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
298 ccall.add_argument (new CCodeIdentifier (param.name));
300 } else if (get_type_signature (param.parameter_type).has_prefix ("(")) {
301 // struct parameter
302 var st = (Struct) param.parameter_type.data_type;
304 var array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_new"));
305 array_construct.add_argument (new CCodeConstant ("0"));
307 var cdecl = new CCodeDeclaration ("GValueArray*");
308 cdecl.add_declarator (new CCodeVariableDeclarator ("dbus_%s".printf (param.name), array_construct));
309 block.add_statement (cdecl);
311 foreach (Field f in st.get_fields ()) {
312 if (f.binding != MemberBinding.INSTANCE) {
313 continue;
316 string val_name = "val_%s_%s".printf (param.name, f.name);
318 // 0-initialize struct with struct initializer { 0 }
319 var cvalinit = new CCodeInitializerList ();
320 cvalinit.append (new CCodeConstant ("0"));
322 var cval_decl = new CCodeDeclaration ("GValue");
323 cval_decl.add_declarator (new CCodeVariableDeclarator.zero (val_name, cvalinit));
324 block.add_statement (cval_decl);
326 var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (val_name));
328 var cinit_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init"));
329 cinit_call.add_argument (val_ptr);
330 cinit_call.add_argument (new CCodeIdentifier (f.field_type.data_type.get_type_id ()));
331 block.add_statement (new CCodeExpressionStatement (cinit_call));
333 var cset_call = new CCodeFunctionCall (new CCodeIdentifier (f.field_type.data_type.get_set_value_function ()));
334 cset_call.add_argument (val_ptr);
335 cset_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), f.name));
336 block.add_statement (new CCodeExpressionStatement (cset_call));
338 var cappend_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_append"));
339 cappend_call.add_argument (new CCodeIdentifier ("dbus_%s".printf (param.name)));
340 cappend_call.add_argument (val_ptr);
341 block.add_statement (new CCodeExpressionStatement (cappend_call));
344 ccall.add_argument (get_dbus_g_type (param.parameter_type));
345 ccall.add_argument (new CCodeIdentifier ("dbus_%s".printf (param.name)));
346 } else {
347 ccall.add_argument (get_dbus_g_type (param.parameter_type));
348 ccall.add_argument (new CCodeIdentifier (param.name));
352 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
354 var out_marshalling_fragment = new CCodeFragment ();
356 foreach (FormalParameter param in method.get_parameters ()) {
357 if (param.parameter_type is MethodType) {
358 // callback parameter
359 break;
362 if (param.direction != ParameterDirection.OUT) {
363 continue;
366 if (get_type_signature (param.parameter_type).has_prefix ("(")) {
367 // struct output parameter
368 var st = (Struct) param.parameter_type.data_type;
370 var cdecl = new CCodeDeclaration ("GValueArray*");
371 cdecl.add_declarator (new CCodeVariableDeclarator ("dbus_%s".printf (param.name)));
372 block.add_statement (cdecl);
374 int i = 0;
375 foreach (Field f in st.get_fields ()) {
376 if (f.binding != MemberBinding.INSTANCE) {
377 continue;
380 var cget_call = new CCodeFunctionCall (new CCodeIdentifier (f.field_type.data_type.get_get_value_function ()));
381 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 ()))));
383 var converted_value = cget_call;
385 if (requires_copy (f.field_type)) {
386 var dupexpr = get_dup_func_expression (f.field_type, expr.source_reference);
387 converted_value = new CCodeFunctionCall (dupexpr);
388 converted_value.add_argument (cget_call);
391 var assign = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), f.name), converted_value);
392 out_marshalling_fragment.append (new CCodeExpressionStatement (assign));
394 i++;
397 ccall.add_argument (get_dbus_g_type (param.parameter_type));
398 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("dbus_%s".printf (param.name))));
399 } else {
400 ccall.add_argument (get_dbus_g_type (param.parameter_type));
401 ccall.add_argument (new CCodeIdentifier (param.name));
405 if (!(method.return_type is VoidType)) {
406 // synchronous D-Bus method call with reply
407 ccall.add_argument (get_dbus_g_type (method.return_type));
409 var array_type = method.return_type as ArrayType;
410 if (array_type != null && array_type.element_type.data_type != string_type.data_type) {
411 // non-string arrays (use GArray)
412 CCodeDeclaration cdecl;
413 if (dbus_use_ptr_array (array_type)) {
414 cdecl = new CCodeDeclaration ("GPtrArray*");
415 } else {
416 cdecl = new CCodeDeclaration ("GArray*");
418 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
419 block.add_statement (cdecl);
421 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
422 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
424 block.add_statement (new CCodeExpressionStatement (ccall));
426 // don't access result when error occured
427 var creturnblock = new CCodeBlock ();
428 creturnblock.add_statement (new CCodeReturnStatement (default_value_for_type (method.return_type, false)));
429 var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
430 block.add_statement (cerrorif);
432 block.add_statement (out_marshalling_fragment);
434 // *result_length1 = result->len;
435 var garray_length = new CCodeMemberAccess.pointer (new CCodeIdentifier ("result"), "len");
436 var result_length = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length1"));
437 var assign = new CCodeAssignment (result_length, garray_length);
438 block.add_statement (new CCodeExpressionStatement (assign));
440 // return result->data;
441 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 ())));
442 } else if (method.return_type.is_real_non_null_struct_type ()) {
443 // structs are returned via out parameter
444 var st = (Struct) method.return_type.data_type;
446 if (st.get_full_name () == "GLib.Value") {
447 ccall.add_argument (new CCodeIdentifier ("result"));
448 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
450 block.add_statement (new CCodeExpressionStatement (ccall));
451 } else {
452 var cdecl = new CCodeDeclaration ("GValueArray*");
453 cdecl.add_declarator (new CCodeVariableDeclarator ("dbus_result"));
454 block.add_statement (cdecl);
456 int i = 0;
457 foreach (Field f in st.get_fields ()) {
458 if (f.binding != MemberBinding.INSTANCE) {
459 continue;
462 var cget_call = new CCodeFunctionCall (new CCodeIdentifier (f.field_type.data_type.get_get_value_function ()));
463 cget_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeElementAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_result"), "values"), new CCodeConstant (i.to_string ()))));
465 var converted_value = cget_call;
467 if (requires_copy (f.field_type)) {
468 var dupexpr = get_dup_func_expression (f.field_type, expr.source_reference);
469 converted_value = new CCodeFunctionCall (dupexpr);
470 converted_value.add_argument (cget_call);
473 var assign = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("result"), f.name), converted_value);
474 out_marshalling_fragment.append (new CCodeExpressionStatement (assign));
476 i++;
479 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("dbus_result")));
480 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
482 block.add_statement (new CCodeExpressionStatement (ccall));
485 // don't access result when error occured
486 var creturnblock = new CCodeBlock ();
487 creturnblock.add_statement (new CCodeReturnStatement ());
488 var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
489 block.add_statement (cerrorif);
491 block.add_statement (out_marshalling_fragment);
492 } else {
493 // string arrays or other datatypes
494 var cdecl = new CCodeDeclaration (method.return_type.get_cname ());
495 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
496 block.add_statement (cdecl);
498 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
499 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
501 block.add_statement (new CCodeExpressionStatement (ccall));
503 // don't access result when error occured
504 var creturnblock = new CCodeBlock ();
505 creturnblock.add_statement (new CCodeReturnStatement (default_value_for_type (method.return_type, false)));
506 var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
507 block.add_statement (cerrorif);
509 block.add_statement (out_marshalling_fragment);
511 if (array_type != null) {
512 // special case string array
514 // *result_length1 = g_strv_length (result);
515 var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
516 cstrvlen.add_argument (new CCodeIdentifier ("result"));
517 var result_length = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length1"));
518 var assign = new CCodeAssignment (result_length, cstrvlen);
519 block.add_statement (new CCodeExpressionStatement (assign));
522 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
524 } else {
525 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
527 block.add_statement (new CCodeExpressionStatement (ccall));
529 // don't access result when error occured
530 var creturnblock = new CCodeBlock ();
531 creturnblock.add_statement (new CCodeReturnStatement ());
532 var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
533 block.add_statement (cerrorif);
535 block.add_statement (out_marshalling_fragment);
539 public override CCodeExpression get_dbus_g_type (DataType data_type) {
540 if (data_type is ArrayType) {
541 var array_type = data_type as ArrayType;
542 if (array_type.element_type.data_type == string_type.data_type) {
543 return new CCodeIdentifier ("G_TYPE_STRV");
546 var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection"));
547 if (dbus_use_ptr_array (array_type)) {
548 carray_type.add_argument (new CCodeConstant ("\"GPtrArray\""));
549 } else {
550 carray_type.add_argument (new CCodeConstant ("\"GArray\""));
552 carray_type.add_argument (get_dbus_g_type (array_type.element_type));
553 return carray_type;
554 } else if (data_type.data_type is Enum) {
555 var en = (Enum) data_type.data_type;
556 if (en.is_flags) {
557 return new CCodeIdentifier ("G_TYPE_UINT");
558 } else {
559 return new CCodeIdentifier ("G_TYPE_INT");
561 } else if (data_type.data_type == null) {
562 critical ("Internal error during DBus type generation with: %s", data_type.to_string ());
563 return new CCodeIdentifier ("G_TYPE_NONE");
564 } else if (data_type.data_type.get_full_name () == "GLib.HashTable") {
565 var cmap_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_map"));
566 var type_args = data_type.get_type_arguments ();
568 cmap_type.add_argument (new CCodeConstant ("\"GHashTable\""));
569 foreach (DataType type_arg in type_args) {
570 cmap_type.add_argument (get_dbus_g_type (type_arg));
573 return cmap_type;
574 } else if (get_type_signature (data_type).has_prefix ("(")) {
575 // struct parameter
576 var st = (Struct) data_type.data_type;
578 var type_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_struct"));
579 type_call.add_argument (new CCodeConstant ("\"GValueArray\""));
581 foreach (Field f in st.get_fields ()) {
582 if (f.binding != MemberBinding.INSTANCE) {
583 continue;
586 type_call.add_argument (get_dbus_g_type (f.field_type));
589 type_call.add_argument (new CCodeConstant ("G_TYPE_INVALID"));
591 return type_call;
592 } else {
593 return new CCodeIdentifier (data_type.data_type.get_type_id ());
597 public bool dbus_use_ptr_array (ArrayType array_type) {
598 if (array_type.element_type.data_type == string_type.data_type) {
599 // use char**
600 return false;
601 } else if (array_type.element_type.data_type == bool_type.data_type
602 || array_type.element_type.data_type == char_type.data_type
603 || array_type.element_type.data_type == uchar_type.data_type
604 || array_type.element_type.data_type == int_type.data_type
605 || array_type.element_type.data_type == uint_type.data_type
606 || array_type.element_type.data_type == long_type.data_type
607 || array_type.element_type.data_type == ulong_type.data_type
608 || array_type.element_type.data_type == int8_type.data_type
609 || array_type.element_type.data_type == uint8_type.data_type
610 || array_type.element_type.data_type == int32_type.data_type
611 || array_type.element_type.data_type == uint32_type.data_type
612 || array_type.element_type.data_type == int64_type.data_type
613 || array_type.element_type.data_type == uint64_type.data_type
614 || array_type.element_type.data_type == double_type.data_type) {
615 // use GArray
616 return false;
617 } else {
618 // use GPtrArray
619 return true;
623 public override string get_dynamic_property_getter_cname (DynamicProperty prop) {
624 if (prop.dynamic_type.data_type != dbus_object_type) {
625 return base.get_dynamic_property_getter_cname (prop);
628 string getter_cname = "_dynamic_get_%s%d".printf (prop.name, dynamic_property_id++);
630 if (get_type_signature (prop.property_type) == null) {
631 Report.error (prop.property_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (prop.property_type.to_string ()));
632 return getter_cname;
635 var func = new CCodeFunction (getter_cname, prop.property_type.get_cname ());
636 func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
638 func.add_parameter (new CCodeFormalParameter ("obj", prop.dynamic_type.get_cname ()));
640 var block = new CCodeBlock ();
641 generate_dbus_property_getter_wrapper (prop, block);
643 // append to C source file
644 source_declarations.add_type_member_declaration (func.copy ());
646 func.block = block;
647 source_type_member_definition.append (func);
649 return getter_cname;
652 public override string get_dynamic_property_setter_cname (DynamicProperty prop) {
653 if (prop.dynamic_type.data_type != dbus_object_type) {
654 return base.get_dynamic_property_setter_cname (prop);
657 string setter_cname = "_dynamic_set_%s%d".printf (prop.name, dynamic_property_id++);
659 if (get_type_signature (prop.property_type) == null) {
660 Report.error (prop.property_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (prop.property_type.to_string ()));
661 return setter_cname;
664 var func = new CCodeFunction (setter_cname, "void");
665 func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
667 func.add_parameter (new CCodeFormalParameter ("obj", prop.dynamic_type.get_cname ()));
668 func.add_parameter (new CCodeFormalParameter ("value", prop.property_type.get_cname ()));
670 var block = new CCodeBlock ();
671 generate_dbus_property_setter_wrapper (prop, block);
673 // append to C source file
674 source_declarations.add_type_member_declaration (func.copy ());
676 func.block = block;
677 source_type_member_definition.append (func);
679 return setter_cname;
682 void create_dbus_property_proxy (DynamicProperty node, CCodeBlock block) {
683 var prop_proxy_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_new_from_proxy"));
684 prop_proxy_call.add_argument (new CCodeIdentifier ("obj"));
685 prop_proxy_call.add_argument (new CCodeConstant ("DBUS_INTERFACE_PROPERTIES"));
686 prop_proxy_call.add_argument (new CCodeConstant ("NULL"));
688 var prop_proxy_decl = new CCodeDeclaration ("DBusGProxy*");
689 prop_proxy_decl.add_declarator (new CCodeVariableDeclarator ("property_proxy", prop_proxy_call));
690 block.add_statement (prop_proxy_decl);
693 void generate_dbus_property_getter_wrapper (DynamicProperty node, CCodeBlock block) {
694 create_dbus_property_proxy (node, block);
696 // initialize GValue
697 var cvalinit = new CCodeInitializerList ();
698 cvalinit.append (new CCodeConstant ("0"));
700 var cval_decl = new CCodeDeclaration ("GValue");
701 cval_decl.add_declarator (new CCodeVariableDeclarator.zero ("gvalue", cvalinit));
702 block.add_statement (cval_decl);
704 var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("gvalue"));
706 // call Get method on property proxy
707 var cdecl = new CCodeDeclaration (node.property_type.get_cname ());
708 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
709 block.add_statement (cdecl);
711 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_call"));
712 ccall.add_argument (new CCodeIdentifier ("property_proxy"));
713 ccall.add_argument (new CCodeConstant ("\"Get\""));
714 ccall.add_argument (new CCodeConstant ("NULL"));
716 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
717 var get_iface = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_interface"));
718 get_iface.add_argument (new CCodeIdentifier ("obj"));
719 ccall.add_argument (get_iface);
721 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
722 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (node.name))));
724 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
726 ccall.add_argument (new CCodeIdentifier ("G_TYPE_VALUE"));
727 ccall.add_argument (val_ptr);
729 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
731 block.add_statement (new CCodeExpressionStatement (ccall));
733 // unref property proxy
734 var prop_proxy_unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
735 prop_proxy_unref.add_argument (new CCodeIdentifier ("property_proxy"));
736 block.add_statement (new CCodeExpressionStatement (prop_proxy_unref));
738 // assign value to result variable
739 var cget_call = new CCodeFunctionCall (new CCodeIdentifier (node.property_type.data_type.get_get_value_function ()));
740 cget_call.add_argument (val_ptr);
741 var assign = new CCodeAssignment (new CCodeIdentifier ("result"), cget_call);
742 block.add_statement (new CCodeExpressionStatement (assign));
744 // return result
745 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
748 void generate_dbus_property_setter_wrapper (DynamicProperty node, CCodeBlock block) {
749 create_dbus_property_proxy (node, block);
751 // initialize GValue
752 var cvalinit = new CCodeInitializerList ();
753 cvalinit.append (new CCodeConstant ("0"));
755 var cval_decl = new CCodeDeclaration ("GValue");
756 cval_decl.add_declarator (new CCodeVariableDeclarator.zero ("gvalue", cvalinit));
757 block.add_statement (cval_decl);
759 var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("gvalue"));
761 var cinit_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init"));
762 cinit_call.add_argument (val_ptr);
763 cinit_call.add_argument (new CCodeIdentifier (node.property_type.data_type.get_type_id ()));
764 block.add_statement (new CCodeExpressionStatement (cinit_call));
766 var cset_call = new CCodeFunctionCall (new CCodeIdentifier (node.property_type.data_type.get_set_value_function ()));
767 cset_call.add_argument (val_ptr);
768 cset_call.add_argument (new CCodeIdentifier ("value"));
769 block.add_statement (new CCodeExpressionStatement (cset_call));
771 // call Set method on property proxy
772 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_call"));
773 ccall.add_argument (new CCodeIdentifier ("property_proxy"));
774 ccall.add_argument (new CCodeConstant ("\"Set\""));
775 ccall.add_argument (new CCodeConstant ("NULL"));
777 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
778 var get_iface = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_interface"));
779 get_iface.add_argument (new CCodeIdentifier ("obj"));
780 ccall.add_argument (get_iface);
782 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
783 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (node.name))));
785 ccall.add_argument (new CCodeIdentifier ("G_TYPE_VALUE"));
786 ccall.add_argument (val_ptr);
788 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
790 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
792 block.add_statement (new CCodeExpressionStatement (ccall));
794 // unref property proxy
795 var prop_proxy_unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
796 prop_proxy_unref.add_argument (new CCodeIdentifier ("property_proxy"));
797 block.add_statement (new CCodeExpressionStatement (prop_proxy_unref));
800 public override string get_dynamic_signal_connect_wrapper_name (DynamicSignal sig) {
801 if (sig.dynamic_type.data_type != dbus_object_type) {
802 return base.get_dynamic_signal_connect_wrapper_name (sig);
805 string connect_wrapper_name = "_%sconnect".printf (get_dynamic_signal_cname (sig));
806 var func = new CCodeFunction (connect_wrapper_name, "void");
807 func.add_parameter (new CCodeFormalParameter ("obj", "gpointer"));
808 func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *"));
809 func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
810 func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
811 var block = new CCodeBlock ();
812 generate_dbus_connect_wrapper (sig, block);
814 // append to C source file
815 source_declarations.add_type_member_declaration (func.copy ());
817 func.block = block;
818 source_type_member_definition.append (func);
820 return connect_wrapper_name;
823 public override string get_dynamic_signal_disconnect_wrapper_name (DynamicSignal sig) {
824 if (sig.dynamic_type.data_type != dbus_object_type) {
825 return base.get_dynamic_signal_disconnect_wrapper_name (sig);
828 string disconnect_wrapper_name = "_%sdisconnect".printf (get_dynamic_signal_cname (sig));
829 var func = new CCodeFunction (disconnect_wrapper_name, "void");
830 func.add_parameter (new CCodeFormalParameter ("obj", "gpointer"));
831 func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *"));
832 func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
833 func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
834 var block = new CCodeBlock ();
835 generate_dbus_disconnect_wrapper (sig, block);
837 // append to C source file
838 source_declarations.add_type_member_declaration (func.copy ());
840 func.block = block;
841 source_type_member_definition.append (func);
843 return disconnect_wrapper_name;
846 void generate_dbus_connect_wrapper (DynamicSignal sig, CCodeBlock block) {
847 var m = (Method) sig.handler.symbol_reference;
849 sig.accept (codegen);
851 // FIXME should only be done once per marshaller
852 var register_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_register_marshaller"));
853 head.generate_marshaller (sig.get_parameters (), sig.return_type, true);
854 register_call.add_argument (new CCodeIdentifier (head.get_marshaller_function (sig.get_parameters (), sig.return_type, null, true)));
855 register_call.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
857 var add_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_add_signal"));
858 add_call.add_argument (new CCodeIdentifier ("obj"));
859 add_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (sig.name))));
861 bool first = true;
862 foreach (FormalParameter param in m.get_parameters ()) {
863 if (first) {
864 // skip sender parameter
865 first = false;
866 continue;
869 register_call.add_argument (get_dbus_g_type (param.parameter_type));
870 add_call.add_argument (get_dbus_g_type (param.parameter_type));
872 register_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
873 add_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
875 block.add_statement (new CCodeExpressionStatement (register_call));
876 block.add_statement (new CCodeExpressionStatement (add_call));
878 var call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_connect_signal"));
879 call.add_argument (new CCodeIdentifier ("obj"));
880 call.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (sig.name))));
881 call.add_argument (new CCodeIdentifier ("handler"));
882 call.add_argument (new CCodeIdentifier ("data"));
883 call.add_argument (new CCodeConstant ("NULL"));
884 block.add_statement (new CCodeExpressionStatement (call));
887 void generate_dbus_disconnect_wrapper (DynamicSignal sig, CCodeBlock block) {
888 var call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_disconnect_signal"));
889 call.add_argument (new CCodeIdentifier ("obj"));
890 call.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (sig.name))));
891 call.add_argument (new CCodeIdentifier ("handler"));
892 call.add_argument (new CCodeIdentifier ("data"));
893 block.add_statement (new CCodeExpressionStatement (call));
896 public override void visit_cast_expression (CastExpression expr) {
897 // handles casting DBus.Object instances to DBus interfaces
899 var type = expr.type_reference as ObjectType;
900 var call = expr.inner as MethodCall;
901 if (type == null || !(type.type_symbol is Interface)
902 || type.type_symbol.get_attribute ("DBus") == null || call == null) {
903 base.visit_cast_expression (expr);
904 return;
907 var mtype = call.call.value_type as MethodType;
908 if (mtype == null || mtype.method_symbol.get_cname () != "dbus_g_proxy_new_for_name") {
909 base.visit_cast_expression (expr);
910 return;
913 var args = call.get_argument_list ();
914 Expression connection = ((MemberAccess) call.call).inner;
915 Expression bus_name = args.get (0);
916 Expression object_path = args.get (1);
918 var ccall = new CCodeFunctionCall (new CCodeIdentifier (type.type_symbol.get_lower_case_cprefix () + "dbus_proxy_new"));
919 connection.accept (codegen);
920 ccall.add_argument ((CCodeExpression) connection.ccodenode);
921 bus_name.accept (codegen);
922 ccall.add_argument ((CCodeExpression) bus_name.ccodenode);
923 object_path.accept (codegen);
924 ccall.add_argument ((CCodeExpression) object_path.ccodenode);
925 expr.ccodenode = ccall;
928 void generate_proxy_interface_init (Interface main_iface, Interface iface) {
929 // also generate proxy for prerequisites
930 foreach (var prereq in iface.get_prerequisites ()) {
931 if (prereq.data_type is Interface) {
932 generate_proxy_interface_init (main_iface, (Interface) prereq.data_type);
936 string lower_cname = main_iface.get_lower_case_cprefix () + "dbus_proxy";
938 var proxy_iface_init = new CCodeFunction (lower_cname + "_" + iface.get_lower_case_cprefix () + "_interface_init", "void");
939 proxy_iface_init.add_parameter (new CCodeFormalParameter ("iface", iface.get_cname () + "Iface*"));
941 var iface_block = new CCodeBlock ();
943 foreach (Method m in iface.get_methods ()) {
944 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), m.vfunc_name);
945 if (!m.coroutine) {
946 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_method (main_iface, iface, m)))));
947 } else {
948 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_async_dbus_proxy_method (main_iface, iface, m)))));
949 vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), m.get_finish_vfunc_name ());
950 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_finish_dbus_proxy_method (main_iface, iface, m)))));
954 foreach (Property prop in iface.get_properties ()) {
955 if (prop.get_accessor != null) {
956 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "get_" + prop.name);
957 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_get (main_iface, iface, prop)))));
959 if (prop.set_accessor != null) {
960 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "set_" + prop.name);
961 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_set (main_iface, iface, prop)))));
965 proxy_iface_init.modifiers = CCodeModifiers.STATIC;
966 source_declarations.add_type_member_declaration (proxy_iface_init.copy ());
967 proxy_iface_init.block = iface_block;
968 source_type_member_definition.append (proxy_iface_init);
971 string implement_interface (CCodeFunctionCall define_type, Interface main_iface, Interface iface) {
972 string result = "";
974 // also implement prerequisites
975 foreach (var prereq in iface.get_prerequisites ()) {
976 if (prereq.data_type is Interface) {
977 result += implement_interface (define_type, main_iface, (Interface) prereq.data_type);
981 result += "G_IMPLEMENT_INTERFACE (%s, %sdbus_proxy_%s_interface_init) ".printf (
982 iface.get_upper_case_cname ("TYPE_"),
983 main_iface.get_lower_case_cprefix (),
984 iface.get_lower_case_cprefix ());
985 return result;
988 void implement_property (CCodeBlock block, Interface main_iface, Interface iface) {
989 // also implement prerequisites
990 foreach (var prereq in iface.get_prerequisites ()) {
991 if (prereq.data_type is Interface) {
992 implement_property (block, main_iface, (Interface) prereq.data_type);
996 var gobject_class = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
997 gobject_class.add_argument (new CCodeIdentifier ("klass"));
999 foreach (Property prop in iface.get_properties ()) {
1000 if (!prop.is_abstract) {
1001 continue;
1004 if (!is_gobject_property (prop)) {
1005 continue;
1008 string prop_ev = "%s_dbus_proxy_%s".printf (main_iface.get_lower_case_cname (null), Symbol.camel_case_to_lower_case (prop.name)).up ();
1010 var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_override_property"));
1011 cinst.add_argument (gobject_class);
1012 cinst.add_argument (new CCodeConstant (prop_ev));
1013 cinst.add_argument (prop.get_canonical_cconstant ());
1014 block.add_statement (new CCodeExpressionStatement (cinst));
1016 prop_enum.add_value (new CCodeEnumValue (prop_ev));
1020 public override void generate_interface_declaration (Interface iface, CCodeDeclarationSpace decl_space) {
1021 base.generate_interface_declaration (iface, decl_space);
1023 string dbus_iface_name = get_dbus_name (iface);
1024 if (dbus_iface_name == null) {
1025 return;
1028 string lower_cname = iface.get_lower_case_cprefix () + "dbus_proxy";
1030 if (decl_space.add_symbol_declaration (iface, lower_cname + "_new")) {
1031 return;
1034 // declare proxy_new function
1035 var proxy_new = new CCodeFunction (lower_cname + "_new", iface.get_cname () + "*");
1036 proxy_new.add_parameter (new CCodeFormalParameter ("connection", "DBusGConnection*"));
1037 proxy_new.add_parameter (new CCodeFormalParameter ("name", "const char*"));
1038 proxy_new.add_parameter (new CCodeFormalParameter ("path", "const char*"));
1040 decl_space.add_type_member_declaration (proxy_new);
1043 public override void visit_interface (Interface iface) {
1044 base.visit_interface (iface);
1046 string dbus_iface_name = get_dbus_name (iface);
1047 if (dbus_iface_name == null) {
1048 return;
1051 // strcmp
1052 source_declarations.add_include ("string.h");
1054 // create proxy class
1055 string cname = iface.get_cname () + "DBusProxy";
1056 string lower_cname = iface.get_lower_case_cprefix () + "dbus_proxy";
1058 add_dbus_helpers ();
1060 source_declarations.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (cname), new CCodeVariableDeclarator (cname)));
1061 source_declarations.add_type_declaration (new CCodeTypeDefinition ("DBusGProxyClass", new CCodeVariableDeclarator (cname + "Class")));
1063 var instance_struct = new CCodeStruct ("_%s".printf (cname));
1064 instance_struct.add_field ("DBusGProxy", "parent_instance");
1065 instance_struct.add_field ("gboolean", "disposed");
1067 source_declarations.add_type_definition (instance_struct);
1069 source_declarations.add_type_member_declaration (new CCodeFunction(lower_cname + "_get_type", "GType"));
1071 var define_type = new CCodeFunctionCall (new CCodeIdentifier ("G_DEFINE_TYPE_EXTENDED"));
1072 define_type.add_argument (new CCodeIdentifier (cname));
1073 define_type.add_argument (new CCodeIdentifier (lower_cname));
1074 define_type.add_argument (new CCodeIdentifier ("DBUS_TYPE_G_PROXY"));
1075 define_type.add_argument (new CCodeConstant ("0"));
1076 define_type.add_argument (new CCodeIdentifier (implement_interface (define_type, iface, iface)));
1078 source_type_member_definition.append (new CCodeExpressionStatement (define_type));
1080 // generate proxy_new function
1081 var proxy_new = new CCodeFunction (lower_cname + "_new", iface.get_cname () + "*");
1082 proxy_new.add_parameter (new CCodeFormalParameter ("connection", "DBusGConnection*"));
1083 proxy_new.add_parameter (new CCodeFormalParameter ("name", "const char*"));
1084 proxy_new.add_parameter (new CCodeFormalParameter ("path", "const char*"));
1086 var new_block = new CCodeBlock ();
1088 // create proxy object
1089 var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_new"));
1090 new_call.add_argument (new CCodeFunctionCall (new CCodeIdentifier (lower_cname + "_get_type")));
1091 new_call.add_argument (new CCodeConstant ("\"connection\""));
1092 new_call.add_argument (new CCodeIdentifier ("connection"));
1093 new_call.add_argument (new CCodeConstant ("\"name\""));
1094 new_call.add_argument (new CCodeIdentifier ("name"));
1095 new_call.add_argument (new CCodeConstant ("\"path\""));
1096 new_call.add_argument (new CCodeIdentifier ("path"));
1097 new_call.add_argument (new CCodeConstant ("\"interface\""));
1098 new_call.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1099 new_call.add_argument (new CCodeConstant ("NULL"));
1101 var cdecl = new CCodeDeclaration (iface.get_cname () + "*");
1102 cdecl.add_declarator (new CCodeVariableDeclarator ("self", new_call));
1103 new_block.add_statement (cdecl);
1104 new_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("self")));
1106 proxy_new.block = new_block;
1107 source_type_member_definition.append (proxy_new);
1109 // dbus proxy construct
1110 var proxy_construct = new CCodeFunction (lower_cname + "_construct", "GObject*");
1111 proxy_construct.add_parameter (new CCodeFormalParameter ("gtype", "GType"));
1112 proxy_construct.add_parameter (new CCodeFormalParameter ("n_properties", "guint"));
1113 proxy_construct.add_parameter (new CCodeFormalParameter ("properties", "GObjectConstructParam*"));
1114 proxy_construct.modifiers = CCodeModifiers.STATIC;
1115 proxy_construct.block = new CCodeBlock ();
1117 // chain up
1118 var parent_class = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
1119 parent_class.add_argument (new CCodeIdentifier (lower_cname + "_parent_class"));
1120 var chainup = new CCodeFunctionCall (new CCodeMemberAccess.pointer (parent_class, "constructor"));
1121 chainup.add_argument (new CCodeIdentifier ("gtype"));
1122 chainup.add_argument (new CCodeIdentifier ("n_properties"));
1123 chainup.add_argument (new CCodeIdentifier ("properties"));
1125 cdecl = new CCodeDeclaration ("GObject*");
1126 cdecl.add_declarator (new CCodeVariableDeclarator ("self", chainup));
1127 proxy_construct.block.add_statement (cdecl);
1129 cdecl = new CCodeDeclaration ("DBusGConnection");
1130 cdecl.add_declarator (new CCodeVariableDeclarator ("*connection"));
1131 proxy_construct.block.add_statement (cdecl);
1133 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1134 gconnection.add_argument (new CCodeIdentifier ("self"));
1135 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1136 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("connection")));
1137 gconnection.add_argument (new CCodeConstant ("NULL"));
1138 proxy_construct.block.add_statement (new CCodeExpressionStatement (gconnection));
1140 cdecl = new CCodeDeclaration ("char*");
1141 cdecl.add_declarator (new CCodeVariableDeclarator ("path"));
1142 proxy_construct.block.add_statement (cdecl);
1144 var path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1145 path.add_argument (new CCodeIdentifier ("self"));
1146 path.add_argument (new CCodeConstant ("\"path\""));
1147 path.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("path")));
1148 path.add_argument (new CCodeConstant ("NULL"));
1149 proxy_construct.block.add_statement (new CCodeExpressionStatement (path));
1151 var raw_connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1152 raw_connection.add_argument (new CCodeIdentifier ("connection"));
1154 // add filter to handle signals from the remote object
1155 var filter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_add_filter"));
1156 filter_call.add_argument (raw_connection);
1157 filter_call.add_argument (new CCodeIdentifier (lower_cname + "_filter"));
1158 filter_call.add_argument (new CCodeIdentifier ("self"));
1159 filter_call.add_argument (new CCodeConstant ("NULL"));
1160 proxy_construct.block.add_statement (new CCodeExpressionStatement (filter_call));
1162 var filter_printf = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup_printf"));
1163 filter_printf.add_argument (new CCodeConstant ("\"type='signal',path='%s'\""));
1164 filter_printf.add_argument (new CCodeIdentifier ("path"));
1166 cdecl = new CCodeDeclaration ("char*");
1167 cdecl.add_declarator (new CCodeVariableDeclarator ("filter", filter_printf));
1168 proxy_construct.block.add_statement (cdecl);
1170 // ensure we receive signals from the remote object
1171 var match_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_bus_add_match"));
1172 match_call.add_argument (raw_connection);
1173 match_call.add_argument (new CCodeIdentifier ("filter"));
1174 match_call.add_argument (new CCodeConstant ("NULL"));
1175 proxy_construct.block.add_statement (new CCodeExpressionStatement (match_call));
1177 var connection_free = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
1178 connection_free.add_argument (new CCodeIdentifier ("connection"));
1179 proxy_construct.block.add_statement (new CCodeExpressionStatement (connection_free));
1181 var path_free = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1182 path_free.add_argument (new CCodeIdentifier ("path"));
1183 proxy_construct.block.add_statement (new CCodeExpressionStatement (path_free));
1185 var filter_free = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1186 filter_free.add_argument (new CCodeIdentifier ("filter"));
1187 proxy_construct.block.add_statement (new CCodeExpressionStatement (filter_free));
1189 proxy_construct.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("self")));
1191 source_type_member_definition.append (proxy_construct);
1193 // dbus proxy filter function
1194 generate_proxy_filter_function (iface);
1196 // dbus proxy dispose
1197 var proxy_dispose = new CCodeFunction (lower_cname + "_dispose", "void");
1198 proxy_dispose.add_parameter (new CCodeFormalParameter ("self", "GObject*"));
1199 proxy_dispose.modifiers = CCodeModifiers.STATIC;
1200 proxy_dispose.block = new CCodeBlock ();
1202 cdecl = new CCodeDeclaration ("DBusGConnection");
1203 cdecl.add_declarator (new CCodeVariableDeclarator ("*connection"));
1204 proxy_dispose.block.add_statement (cdecl);
1206 // return if proxy is already disposed
1207 var dispose_return_block = new CCodeBlock ();
1208 dispose_return_block.add_statement (new CCodeReturnStatement ());
1209 proxy_dispose.block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), cname + "*"), "disposed"), dispose_return_block));
1211 // mark proxy as disposed
1212 proxy_dispose.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), cname + "*"), "disposed"), new CCodeConstant ("TRUE"))));
1214 gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1215 gconnection.add_argument (new CCodeIdentifier ("self"));
1216 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1217 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("connection")));
1218 gconnection.add_argument (new CCodeConstant ("NULL"));
1219 proxy_dispose.block.add_statement (new CCodeExpressionStatement (gconnection));
1221 // remove filter
1222 filter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_remove_filter"));
1223 filter_call.add_argument (raw_connection);
1224 filter_call.add_argument (new CCodeIdentifier (lower_cname + "_filter"));
1225 filter_call.add_argument (new CCodeIdentifier ("self"));
1226 proxy_dispose.block.add_statement (new CCodeExpressionStatement (filter_call));
1228 // chain up
1229 parent_class = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
1230 parent_class.add_argument (new CCodeIdentifier (lower_cname + "_parent_class"));
1231 chainup = new CCodeFunctionCall (new CCodeMemberAccess.pointer (parent_class, "dispose"));
1232 chainup.add_argument (new CCodeIdentifier ("self"));
1233 proxy_dispose.block.add_statement (new CCodeExpressionStatement (chainup));
1235 source_type_member_definition.append (proxy_dispose);
1237 var proxy_class_init = new CCodeFunction (lower_cname + "_class_init", "void");
1238 proxy_class_init.add_parameter (new CCodeFormalParameter ("klass", cname + "Class*"));
1239 proxy_class_init.modifiers = CCodeModifiers.STATIC;
1240 proxy_class_init.block = new CCodeBlock ();
1241 var gobject_class = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
1242 gobject_class.add_argument (new CCodeIdentifier ("klass"));
1243 proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (gobject_class, "constructor"), new CCodeIdentifier (lower_cname + "_construct"))));
1244 proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (gobject_class, "dispose"), new CCodeIdentifier (lower_cname + "_dispose"))));
1245 proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (gobject_class, "get_property"), new CCodeIdentifier (lower_cname + "_get_property"))));
1246 proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (gobject_class, "set_property"), new CCodeIdentifier (lower_cname + "_set_property"))));
1247 source_type_member_definition.append (proxy_class_init);
1249 prop_enum = new CCodeEnum ();
1250 prop_enum.add_value (new CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (lower_cname.up ())));
1252 implement_property (proxy_class_init.block, iface, iface);
1254 source_declarations.add_type_member_declaration (prop_enum);
1256 var proxy_instance_init = new CCodeFunction (lower_cname + "_init", "void");
1257 proxy_instance_init.add_parameter (new CCodeFormalParameter ("self", cname + "*"));
1258 proxy_instance_init.modifiers = CCodeModifiers.STATIC;
1259 proxy_instance_init.block = new CCodeBlock ();
1260 source_type_member_definition.append (proxy_instance_init);
1262 generate_proxy_interface_init (iface, iface);
1264 // dbus proxy get/set_property stubs
1265 // TODO add actual implementation
1266 var get_prop = new CCodeFunction ("%s_get_property".printf (lower_cname), "void");
1267 get_prop.modifiers = CCodeModifiers.STATIC;
1268 get_prop.add_parameter (new CCodeFormalParameter ("object", "GObject *"));
1269 get_prop.add_parameter (new CCodeFormalParameter ("property_id", "guint"));
1270 get_prop.add_parameter (new CCodeFormalParameter ("value", "GValue *"));
1271 get_prop.add_parameter (new CCodeFormalParameter ("pspec", "GParamSpec *"));
1272 source_declarations.add_type_member_declaration (get_prop.copy ());
1273 get_prop.block = new CCodeBlock ();
1274 source_type_member_definition.append (get_prop);
1276 var set_prop = new CCodeFunction ("%s_set_property".printf (lower_cname), "void");
1277 set_prop.modifiers = CCodeModifiers.STATIC;
1278 set_prop.add_parameter (new CCodeFormalParameter ("object", "GObject *"));
1279 set_prop.add_parameter (new CCodeFormalParameter ("property_id", "guint"));
1280 set_prop.add_parameter (new CCodeFormalParameter ("value", "const GValue *"));
1281 set_prop.add_parameter (new CCodeFormalParameter ("pspec", "GParamSpec *"));
1282 source_declarations.add_type_member_declaration (set_prop.copy ());
1283 set_prop.block = new CCodeBlock ();
1284 source_type_member_definition.append (set_prop);
1287 public override TypeRegisterFunction create_interface_register_function (Interface iface) {
1288 string dbus_iface_name = get_dbus_name (iface);
1289 if (dbus_iface_name == null) {
1290 return new InterfaceRegisterFunction (iface, context);
1293 return new DBusInterfaceRegisterFunction (iface, context);
1296 string generate_get_all_function (Method m) {
1297 string get_all_func = "_dbus_g_proxy_get_all";
1299 if (!add_wrapper (get_all_func)) {
1300 // wrapper already defined
1301 return get_all_func;
1304 var function = new CCodeFunction (get_all_func, "GHashTable*");
1305 function.modifiers = CCodeModifiers.STATIC;
1307 function.add_parameter (new CCodeFormalParameter ("self", "DBusGProxy*"));
1308 function.add_parameter (new CCodeFormalParameter ("interface_name", "const gchar*"));
1309 function.add_parameter (new CCodeFormalParameter ("error", "GError**"));
1311 var block = new CCodeBlock ();
1312 var prefragment = new CCodeFragment ();
1313 var postfragment = new CCodeFragment ();
1315 var cdecl = new CCodeDeclaration ("DBusError");
1316 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
1317 block.add_statement (cdecl);
1319 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
1321 cdecl = new CCodeDeclaration ("DBusGConnection");
1322 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
1323 block.add_statement (cdecl);
1325 cdecl = new CCodeDeclaration ("DBusMessage");
1326 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
1327 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
1328 block.add_statement (cdecl);
1330 cdecl = new CCodeDeclaration ("DBusMessageIter");
1331 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
1332 block.add_statement (cdecl);
1334 block.add_statement (prefragment);
1336 generate_marshalling (m, "org.freedesktop.DBus.Properties", prefragment, postfragment);
1338 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1339 gconnection.add_argument (new CCodeIdentifier ("self"));
1340 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1341 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
1342 gconnection.add_argument (new CCodeConstant ("NULL"));
1343 block.add_statement (new CCodeExpressionStatement (gconnection));
1345 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
1346 dbus_error_init.add_argument (dbus_error);
1347 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
1349 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1350 connection.add_argument (new CCodeIdentifier ("_connection"));
1352 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
1353 ccall.add_argument (connection);
1354 ccall.add_argument (new CCodeIdentifier ("_message"));
1355 ccall.add_argument (get_dbus_timeout (m));
1356 ccall.add_argument (dbus_error);
1357 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
1359 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
1360 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
1361 block.add_statement (new CCodeExpressionStatement (conn_unref));
1363 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1364 message_unref.add_argument (new CCodeIdentifier ("_message"));
1365 block.add_statement (new CCodeExpressionStatement (message_unref));
1367 check_error_reply (m, block);
1368 check_reply_signature (m, block);
1370 block.add_statement (postfragment);
1372 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1373 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
1374 block.add_statement (new CCodeExpressionStatement (reply_unref));
1376 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
1378 source_declarations.add_type_member_declaration (function.copy ());
1380 function.block = block;
1381 source_type_member_definition.append (function);
1383 return get_all_func;
1386 public override void visit_method_call (MethodCall expr) {
1387 var mtype = expr.call.value_type as MethodType;
1388 bool proxy_new_from_type = (mtype != null && mtype.method_symbol.get_cname () == "dbus_g_proxy_new_from_type");
1389 bool proxy_get_all = (mtype != null && mtype.method_symbol.get_cname () == "dbus_g_proxy_get_all");
1390 if (!proxy_new_from_type && !proxy_get_all) {
1391 base.visit_method_call (expr);
1392 return;
1395 if (proxy_get_all) {
1396 var ma = expr.call as MemberAccess;
1397 var instance = ma.inner;
1398 instance.accept (codegen);
1400 var args = expr.get_argument_list ();
1401 Expression interface_name = args.get (0);
1402 interface_name.accept (codegen);
1404 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_get_all_function (mtype.method_symbol)));
1405 ccall.add_argument ((CCodeExpression) instance.ccodenode);
1406 ccall.add_argument ((CCodeExpression) interface_name.ccodenode);
1408 current_method_inner_error = true;
1409 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
1411 expr.ccodenode = ccall;
1412 return;
1415 var args = expr.get_argument_list ();
1416 Expression connection = ((MemberAccess) expr.call).inner;
1417 Expression bus_name = args.get (0);
1418 Expression object_path = args.get (1);
1419 Expression interface_name = args.get (2);
1420 Expression type = args.get (3);
1422 var quark_call = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
1423 quark_call.add_argument (new CCodeConstant ("\"ValaDBusInterfaceProxyType\""));
1425 var qdata_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
1426 type.accept (codegen);
1427 qdata_call.add_argument ((CCodeExpression) type.ccodenode);
1428 qdata_call.add_argument (quark_call);
1430 var get_type_call = new CCodeFunctionCall (new CCodeCastExpression (qdata_call, "GType (*)(void)"));
1432 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_new"));
1433 ccall.add_argument (get_type_call);
1434 ccall.add_argument (new CCodeConstant ("\"connection\""));
1435 connection.accept (codegen);
1436 ccall.add_argument ((CCodeExpression) connection.ccodenode);
1437 ccall.add_argument (new CCodeConstant ("\"name\""));
1438 bus_name.accept (codegen);
1439 ccall.add_argument ((CCodeExpression) bus_name.ccodenode);
1440 ccall.add_argument (new CCodeConstant ("\"path\""));
1441 object_path.accept (codegen);
1442 ccall.add_argument ((CCodeExpression) object_path.ccodenode);
1443 ccall.add_argument (new CCodeConstant ("\"interface\""));
1444 interface_name.accept (codegen);
1445 ccall.add_argument ((CCodeExpression) interface_name.ccodenode);
1446 ccall.add_argument (new CCodeConstant ("NULL"));
1447 expr.ccodenode = ccall;
1450 void generate_proxy_filter_function (Interface iface) {
1451 string lower_cname = iface.get_lower_case_cprefix () + "dbus_proxy";
1453 var proxy_filter = new CCodeFunction (lower_cname + "_filter", "DBusHandlerResult");
1454 proxy_filter.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
1455 proxy_filter.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
1456 proxy_filter.add_parameter (new CCodeFormalParameter ("user_data", "void*"));
1458 var filter_block = new CCodeBlock ();
1460 // only handle signals concering the object path
1461 var path = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_path"));
1462 path.add_argument (new CCodeIdentifier ("user_data"));
1464 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_has_path"));
1465 ccheck.add_argument (new CCodeIdentifier ("message"));
1466 ccheck.add_argument (path);
1468 var object_filter_block = new CCodeBlock ();
1469 filter_block.add_statement (new CCodeIfStatement (ccheck, object_filter_block));
1471 handle_signals (iface, object_filter_block);
1473 filter_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1475 source_declarations.add_type_member_declaration (proxy_filter.copy ());
1476 proxy_filter.block = filter_block;
1477 source_type_member_definition.append (proxy_filter);
1480 string generate_dbus_signal_handler (Signal sig, ObjectTypeSymbol sym) {
1481 string wrapper_name = "_dbus_handle_%s_%s".printf (sym.get_lower_case_cname (), sig.get_cname ());
1483 // declaration
1485 CCodeDeclaration cdecl;
1487 var function = new CCodeFunction (wrapper_name, "void");
1488 function.modifiers = CCodeModifiers.STATIC;
1490 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
1491 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
1492 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
1494 var block = new CCodeBlock ();
1495 var prefragment = new CCodeFragment ();
1496 var postfragment = new CCodeFragment ();
1498 cdecl = new CCodeDeclaration ("DBusMessageIter");
1499 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
1500 block.add_statement (cdecl);
1502 block.add_statement (prefragment);
1504 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
1505 message_signature.add_argument (new CCodeIdentifier ("message"));
1506 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1507 signature_check.add_argument (message_signature);
1508 var signature_error_block = new CCodeBlock ();
1509 signature_error_block.add_statement (new CCodeReturnStatement ());
1510 prefragment.append (new CCodeIfStatement (signature_check, signature_error_block));
1512 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
1513 iter_call.add_argument (new CCodeIdentifier ("message"));
1514 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1515 prefragment.append (new CCodeExpressionStatement (iter_call));
1517 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
1518 ccall.add_argument (new CCodeIdentifier ("self"));
1519 ccall.add_argument (sig.get_canonical_cconstant ());
1521 // expected type signature for input parameters
1522 string type_signature = "";
1524 foreach (FormalParameter param in sig.get_parameters ()) {
1525 var owned_type = param.parameter_type.copy ();
1526 owned_type.value_owned = true;
1528 cdecl = new CCodeDeclaration (owned_type.get_cname ());
1529 cdecl.add_declarator (new CCodeVariableDeclarator.zero (param.name, default_value_for_type (param.parameter_type, true)));
1530 prefragment.append (cdecl);
1532 if (get_type_signature (param.parameter_type) == null) {
1533 Report.error (param.parameter_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (param.parameter_type.to_string ()));
1534 continue;
1537 var st = param.parameter_type.data_type as Struct;
1538 if (st != null && !st.is_simple_type ()) {
1539 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
1540 } else {
1541 ccall.add_argument (new CCodeIdentifier (param.name));
1544 if (param.parameter_type is ArrayType) {
1545 var array_type = (ArrayType) param.parameter_type;
1547 for (int dim = 1; dim <= array_type.rank; dim++) {
1548 string length_cname = get_array_length_cname (param.name, dim);
1550 cdecl = new CCodeDeclaration ("int");
1551 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
1552 prefragment.append (cdecl);
1553 ccall.add_argument (new CCodeIdentifier (length_cname));
1557 type_signature += get_type_signature (param.parameter_type);
1559 var target = new CCodeIdentifier (param.name);
1560 var expr = read_expression (prefragment, param.parameter_type, new CCodeIdentifier ("iter"), target);
1561 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1563 if (requires_destroy (owned_type)) {
1564 // keep local alive (symbol_reference is weak)
1565 var local = new LocalVariable (owned_type, param.name);
1566 var ma = new MemberAccess.simple (param.name);
1567 ma.symbol_reference = local;
1568 var stmt = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (param.name), owned_type, ma));
1569 postfragment.append (stmt);
1573 signature_check.add_argument (new CCodeConstant ("\"%s\"".printf (type_signature)));
1575 block.add_statement (new CCodeExpressionStatement (ccall));
1577 block.add_statement (postfragment);
1579 cdecl = new CCodeDeclaration ("DBusMessage*");
1580 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
1581 block.add_statement (cdecl);
1583 source_declarations.add_type_member_declaration (function.copy ());
1585 function.block = block;
1586 source_type_member_definition.append (function);
1588 return wrapper_name;
1591 void handle_signal (string dbus_iface_name, string dbus_signal_name, string handler_name, CCodeBlock block, ref CCodeIfStatement clastif) {
1592 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_is_signal"));
1593 ccheck.add_argument (new CCodeIdentifier ("message"));
1594 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1595 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_signal_name)));
1597 var callblock = new CCodeBlock ();
1599 var ccall = new CCodeFunctionCall (new CCodeIdentifier (handler_name));
1600 ccall.add_argument (new CCodeIdentifier ("user_data"));
1601 ccall.add_argument (new CCodeIdentifier ("connection"));
1602 ccall.add_argument (new CCodeIdentifier ("message"));
1604 callblock.add_statement (new CCodeExpressionStatement (ccall));
1606 var cif = new CCodeIfStatement (ccheck, callblock);
1607 if (clastif == null) {
1608 block.add_statement (cif);
1609 } else {
1610 clastif.false_statement = cif;
1613 clastif = cif;
1616 void handle_signals (Interface iface, CCodeBlock block) {
1617 string dbus_iface_name = get_dbus_name (iface);
1619 CCodeIfStatement clastif = null;
1620 foreach (Signal sig in iface.get_signals ()) {
1621 if (sig.access != SymbolAccessibility.PUBLIC) {
1622 continue;
1625 handle_signal (dbus_iface_name, get_dbus_name_for_member (sig), generate_dbus_signal_handler (sig, iface), block, ref clastif);
1629 void generate_marshalling (Method m, string dbus_iface_name, CCodeFragment prefragment, CCodeFragment postfragment) {
1630 CCodeDeclaration cdecl;
1632 var destination = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_bus_name"));
1633 destination.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
1634 var path = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_path"));
1635 path.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
1637 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_call"));
1638 msgcall.add_argument (destination);
1639 msgcall.add_argument (path);
1640 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1641 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
1642 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall)));
1644 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
1645 iter_call.add_argument (new CCodeIdentifier ("_message"));
1646 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
1647 prefragment.append (new CCodeExpressionStatement (iter_call));
1649 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
1650 iter_call.add_argument (new CCodeIdentifier ("_reply"));
1651 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
1652 postfragment.append (new CCodeExpressionStatement (iter_call));
1654 foreach (FormalParameter param in m.get_parameters ()) {
1655 if (param.direction == ParameterDirection.IN) {
1656 if (param.parameter_type.data_type != null
1657 && param.parameter_type.data_type.get_full_name () == "DBus.BusName") {
1658 // ignore BusName sender parameters
1659 continue;
1661 CCodeExpression expr = new CCodeIdentifier (param.name);
1662 if (param.parameter_type.is_real_struct_type ()) {
1663 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
1665 write_expression (prefragment, param.parameter_type, new CCodeIdentifier ("_iter"), expr);
1666 } else {
1667 cdecl = new CCodeDeclaration (param.parameter_type.get_cname ());
1668 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + param.name));
1669 postfragment.append (cdecl);
1671 var array_type = param.parameter_type as ArrayType;
1673 if (array_type != null) {
1674 for (int dim = 1; dim <= array_type.rank; dim++) {
1675 cdecl = new CCodeDeclaration ("int");
1676 cdecl.add_declarator (new CCodeVariableDeclarator ("_%s_length%d".printf (param.name, dim), new CCodeConstant ("0")));
1677 postfragment.append (cdecl);
1681 var target = new CCodeIdentifier ("_" + param.name);
1682 var expr = read_expression (postfragment, param.parameter_type, new CCodeIdentifier ("_iter"), target);
1683 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1685 // TODO check that parameter is not NULL (out parameters are optional)
1686 // free value if parameter is NULL
1687 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (param.name)), target)));
1690 if (array_type != null) {
1691 for (int dim = 1; dim <= array_type.rank; dim++) {
1692 // TODO check that parameter is not NULL (out parameters are optional)
1693 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)))));
1699 if (!(m.return_type is VoidType)) {
1700 if (m.return_type.is_real_non_null_struct_type ()) {
1701 var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
1702 var expr = read_expression (postfragment, m.return_type, new CCodeIdentifier ("_iter"), target);
1703 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1704 } else {
1705 cdecl = new CCodeDeclaration (m.return_type.get_cname ());
1706 cdecl.add_declarator (new CCodeVariableDeclarator ("_result"));
1707 postfragment.append (cdecl);
1709 var array_type = m.return_type as ArrayType;
1711 if (array_type != null) {
1712 for (int dim = 1; dim <= array_type.rank; dim++) {
1713 cdecl = new CCodeDeclaration ("int");
1714 cdecl.add_declarator (new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
1715 postfragment.append (cdecl);
1719 var target = new CCodeIdentifier ("_result");
1720 var expr = read_expression (postfragment, m.return_type, new CCodeIdentifier ("_iter"), target);
1721 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1723 if (array_type != null) {
1724 for (int dim = 1; dim <= array_type.rank; dim++) {
1725 // TODO check that parameter is not NULL (out parameters are optional)
1726 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)))));
1733 void check_error_reply (Method m, CCodeBlock block) {
1734 var error_types = m.get_error_types ();
1735 if (!has_dbus_error (error_types)) {
1736 Report.error (m.source_reference, "D-Bus methods must throw DBus.Error");
1737 return;
1740 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
1742 var error_block = new CCodeBlock ();
1744 var cdecl = new CCodeDeclaration ("GQuark");
1745 cdecl.add_declarator (new CCodeVariableDeclarator ("_edomain"));
1746 error_block.add_statement (cdecl);
1748 cdecl = new CCodeDeclaration ("gint");
1749 cdecl.add_declarator (new CCodeVariableDeclarator ("_ecode"));
1750 error_block.add_statement (cdecl);
1752 generate_client_error_cases (error_block, error_types, new CCodeMemberAccess (new CCodeIdentifier ("_dbus_error"), "name"), new CCodeIdentifier ("_edomain"), new CCodeIdentifier ("_ecode"));
1754 var g_set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
1755 g_set_error.add_argument (new CCodeIdentifier ("error"));
1756 g_set_error.add_argument (new CCodeIdentifier ("_edomain"));
1757 g_set_error.add_argument (new CCodeIdentifier ("_ecode"));
1758 g_set_error.add_argument (new CCodeConstant ("\"%s\""));
1759 g_set_error.add_argument (new CCodeMemberAccess (new CCodeIdentifier ("_dbus_error"), "message"));
1760 error_block.add_statement (new CCodeExpressionStatement (g_set_error));
1762 var dbus_error_free = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_free"));
1763 dbus_error_free.add_argument (dbus_error);
1764 error_block.add_statement (new CCodeExpressionStatement (dbus_error_free));
1766 if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
1767 error_block.add_statement (new CCodeReturnStatement ());
1768 } else {
1769 error_block.add_statement (new CCodeReturnStatement (default_value_for_type (m.return_type, false)));
1772 var dbus_error_is_set = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_is_set"));
1773 dbus_error_is_set.add_argument (dbus_error);
1774 block.add_statement (new CCodeIfStatement (dbus_error_is_set, error_block));
1777 string generate_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
1778 string proxy_name = "%sdbus_proxy_%s".printf (main_iface.get_lower_case_cprefix (), m.name);
1780 string dbus_iface_name = get_dbus_name (iface);
1782 CCodeDeclaration cdecl;
1784 var function = new CCodeFunction (proxy_name);
1785 function.modifiers = CCodeModifiers.STATIC;
1787 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
1789 generate_cparameters (m, source_declarations, cparam_map, function);
1791 var block = new CCodeBlock ();
1792 var prefragment = new CCodeFragment ();
1793 var postfragment = new CCodeFragment ();
1795 // throw error and return if proxy is disposed
1796 var dispose_return_block = new CCodeBlock ();
1797 if (m.get_error_types ().size > 0) {
1798 var set_error_call = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
1799 set_error_call.add_argument (new CCodeIdentifier ("error"));
1800 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR"));
1801 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR_DISCONNECTED"));
1802 set_error_call.add_argument (new CCodeConstant ("\"%s\""));
1803 set_error_call.add_argument (new CCodeConstant ("\"Connection is closed\""));
1804 dispose_return_block.add_statement (new CCodeExpressionStatement (set_error_call));
1806 if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
1807 dispose_return_block.add_statement (new CCodeReturnStatement ());
1808 } else {
1809 dispose_return_block.add_statement (new CCodeReturnStatement (default_value_for_type (m.return_type, false)));
1811 block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), iface.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block));
1813 cdecl = new CCodeDeclaration ("DBusError");
1814 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
1815 block.add_statement (cdecl);
1817 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
1819 cdecl = new CCodeDeclaration ("DBusGConnection");
1820 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
1821 block.add_statement (cdecl);
1823 cdecl = new CCodeDeclaration ("DBusMessage");
1824 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
1825 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
1826 block.add_statement (cdecl);
1828 cdecl = new CCodeDeclaration ("DBusMessageIter");
1829 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
1830 block.add_statement (cdecl);
1832 block.add_statement (prefragment);
1834 generate_marshalling (m, dbus_iface_name, prefragment, postfragment);
1836 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1837 gconnection.add_argument (new CCodeIdentifier ("self"));
1838 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1839 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
1840 gconnection.add_argument (new CCodeConstant ("NULL"));
1841 block.add_statement (new CCodeExpressionStatement (gconnection));
1843 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
1844 dbus_error_init.add_argument (dbus_error);
1845 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
1847 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1848 connection.add_argument (new CCodeIdentifier ("_connection"));
1850 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
1851 ccall.add_argument (connection);
1852 ccall.add_argument (new CCodeIdentifier ("_message"));
1853 ccall.add_argument (get_dbus_timeout (m));
1854 ccall.add_argument (dbus_error);
1855 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
1857 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
1858 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
1859 block.add_statement (new CCodeExpressionStatement (conn_unref));
1861 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1862 message_unref.add_argument (new CCodeIdentifier ("_message"));
1863 block.add_statement (new CCodeExpressionStatement (message_unref));
1865 check_error_reply (m, block);
1866 check_reply_signature (m, block);
1868 block.add_statement (postfragment);
1870 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1871 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
1872 block.add_statement (new CCodeExpressionStatement (reply_unref));
1874 if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) {
1875 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
1878 source_declarations.add_type_member_declaration (function.copy ());
1879 function.block = block;
1880 source_type_member_definition.append (function);
1882 return proxy_name;
1885 void generate_client_error_cases (CCodeBlock error_block, List<DataType> error_types, CCodeExpression dbus_error_name, CCodeExpression result_edomain, CCodeExpression result_ecode) {
1886 CCodeStatement if_else_if = null;
1887 CCodeIfStatement last_statement = null;
1889 foreach (DataType error_type in error_types) {
1890 var edomain = ((ErrorType) error_type).error_domain;
1892 if (edomain == null) {
1893 Report.error (error_type.source_reference, "Generic errors cannot be serialized over DBus");
1894 continue;
1897 var edomain_dbus_name = get_dbus_name (edomain);
1898 if (edomain_dbus_name == null) {
1899 Report.error (edomain.source_reference, "Errordomain must have a DBus.name annotation to be serialized over DBus");
1902 var true_block = new CCodeBlock ();
1903 true_block.suppress_newline = true;
1905 string temp_name = "_tmp%d_".printf (next_temp_var_id++);
1907 var cdecl = new CCodeDeclaration ("const char*");
1908 cdecl.add_declarator (new CCodeVariableDeclarator (temp_name));
1909 true_block.add_statement (cdecl);
1911 true_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (result_edomain, new CCodeIdentifier (edomain.get_upper_case_cname ()))));
1913 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))))));
1915 CCodeStatement inner_if_else_if = null;
1916 CCodeIfStatement inner_last_statement = null;
1917 foreach (ErrorCode ecode in edomain.get_codes ()) {
1918 var inner_true_block = new CCodeBlock ();
1919 inner_true_block.suppress_newline = true;
1920 inner_true_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (result_ecode, new CCodeIdentifier (ecode.get_cname ()))));
1922 var ecode_dbus_name = get_dbus_name (ecode);
1923 if (ecode_dbus_name == null) {
1924 ecode_dbus_name = Symbol.lower_case_to_camel_case (ecode.name.down ());
1927 var string_comparison = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1928 string_comparison.add_argument (new CCodeIdentifier (temp_name));
1929 string_comparison.add_argument (new CCodeConstant ("\"%s\"".printf (ecode_dbus_name)));
1930 var stmt = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, string_comparison, new CCodeConstant ("0")), inner_true_block);
1932 if (inner_last_statement != null) {
1933 inner_last_statement.false_statement = stmt;
1934 } else {
1935 inner_if_else_if = stmt;
1937 inner_last_statement = stmt;
1939 true_block.add_statement (inner_if_else_if);
1941 var string_comparison = new CCodeFunctionCall (new CCodeIdentifier ("strstr"));
1942 string_comparison.add_argument (dbus_error_name);
1943 string_comparison.add_argument (new CCodeConstant ("\"%s\"".printf (edomain_dbus_name)));
1944 var stmt = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, string_comparison, dbus_error_name), true_block);
1946 if (last_statement != null) {
1947 last_statement.false_statement = stmt;
1948 } else {
1949 if_else_if = stmt;
1951 last_statement = stmt;
1953 error_block.add_statement (if_else_if);
1956 string generate_async_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
1957 string proxy_name = "%sdbus_proxy_%s_async".printf (main_iface.get_lower_case_cprefix (), m.name);
1959 string dbus_iface_name = get_dbus_name (iface);
1961 CCodeDeclaration cdecl;
1964 // generate data struct
1966 string dataname = "%sDBusProxy%sData".printf (iface.get_cname (), Symbol.lower_case_to_camel_case (m.name));
1967 var datastruct = new CCodeStruct ("_" + dataname);
1969 datastruct.add_field ("GAsyncReadyCallback", "_callback_");
1970 datastruct.add_field ("gpointer", "_user_data_");
1971 datastruct.add_field ("DBusPendingCall*", "pending");
1973 source_declarations.add_type_definition (datastruct);
1974 source_declarations.add_type_declaration (new CCodeTypeDefinition ("struct _" + dataname, new CCodeVariableDeclarator (dataname)));
1977 // generate async function
1979 var function = new CCodeFunction (proxy_name, "void");
1980 function.modifiers = CCodeModifiers.STATIC;
1982 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
1984 cparam_map.set (get_param_pos (-1), new CCodeFormalParameter ("_callback_", "GAsyncReadyCallback"));
1985 cparam_map.set (get_param_pos (-0.9), new CCodeFormalParameter ("_user_data_", "gpointer"));
1987 generate_cparameters (m, source_declarations, cparam_map, function, null, null, null, 1);
1989 var block = new CCodeBlock ();
1990 var prefragment = new CCodeFragment ();
1991 var postfragment = new CCodeFragment ();
1993 cdecl = new CCodeDeclaration ("DBusGConnection");
1994 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
1995 block.add_statement (cdecl);
1997 cdecl = new CCodeDeclaration ("DBusMessage");
1998 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
1999 block.add_statement (cdecl);
2001 cdecl = new CCodeDeclaration ("DBusPendingCall");
2002 cdecl.add_declarator (new CCodeVariableDeclarator ("*_pending"));
2003 block.add_statement (cdecl);
2005 cdecl = new CCodeDeclaration ("DBusMessageIter");
2006 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
2007 block.add_statement (cdecl);
2009 block.add_statement (prefragment);
2011 generate_marshalling (m, dbus_iface_name, prefragment, postfragment);
2013 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
2014 gconnection.add_argument (new CCodeIdentifier ("self"));
2015 gconnection.add_argument (new CCodeConstant ("\"connection\""));
2016 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
2017 gconnection.add_argument (new CCodeConstant ("NULL"));
2018 block.add_statement (new CCodeExpressionStatement (gconnection));
2020 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
2021 connection.add_argument (new CCodeIdentifier ("_connection"));
2023 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply"));
2024 ccall.add_argument (connection);
2025 ccall.add_argument (new CCodeIdentifier ("_message"));
2026 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_pending")));
2027 ccall.add_argument (get_dbus_timeout (m));
2028 block.add_statement (new CCodeExpressionStatement (ccall));
2030 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
2031 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
2032 block.add_statement (new CCodeExpressionStatement (conn_unref));
2034 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2035 message_unref.add_argument (new CCodeIdentifier ("_message"));
2036 block.add_statement (new CCodeExpressionStatement (message_unref));
2038 var dataalloc = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
2039 dataalloc.add_argument (new CCodeIdentifier (dataname));
2041 var datadecl = new CCodeDeclaration (dataname + "*");
2042 datadecl.add_declarator (new CCodeVariableDeclarator ("_data_"));
2043 block.add_statement (datadecl);
2044 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_data_"), dataalloc)));
2046 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_callback_"), new CCodeIdentifier ("_callback_"))));
2047 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_user_data_"), new CCodeIdentifier ("_user_data_"))));
2048 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "pending"), new CCodeIdentifier ("_pending"))));
2050 var pending = new CCodeFunctionCall (new CCodeIdentifier ("dbus_pending_call_set_notify"));
2051 pending.add_argument (new CCodeIdentifier ("_pending"));
2052 pending.add_argument (new CCodeIdentifier ("%sdbus_proxy_%s_ready".printf (iface.get_lower_case_cprefix (), m.name)));
2053 pending.add_argument (new CCodeIdentifier ("_data_"));
2054 pending.add_argument (new CCodeConstant ("NULL"));
2055 block.add_statement (new CCodeExpressionStatement (pending));
2057 source_declarations.add_type_member_declaration (function.copy ());
2058 function.block = block;
2059 source_type_member_definition.append (function);
2062 // generate ready function
2064 function = new CCodeFunction ("%sdbus_proxy_%s_ready".printf (iface.get_lower_case_cprefix (), m.name), "void");
2065 function.modifiers = CCodeModifiers.STATIC;
2067 function.add_parameter (new CCodeFormalParameter ("pending", "DBusPendingCall*"));
2068 function.add_parameter (new CCodeFormalParameter ("user_data", "void*"));
2070 block = new CCodeBlock ();
2072 datadecl = new CCodeDeclaration (dataname + "*");
2073 datadecl.add_declarator (new CCodeVariableDeclarator ("_data_"));
2074 block.add_statement (datadecl);
2075 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_data_"), new CCodeIdentifier ("user_data"))));
2077 // complete async call by invoking callback
2078 var obj_decl = new CCodeDeclaration ("GObject *");
2079 obj_decl.add_declarator (new CCodeVariableDeclarator ("_obj_"));
2080 block.add_statement (obj_decl);
2082 var object_creation = new CCodeFunctionCall (new CCodeIdentifier ("g_object_newv"));
2083 object_creation.add_argument (new CCodeConstant ("G_TYPE_OBJECT"));
2084 object_creation.add_argument (new CCodeConstant ("0"));
2085 object_creation.add_argument (new CCodeConstant ("NULL"));
2086 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_obj_"), object_creation)));
2088 var async_result_decl = new CCodeDeclaration ("GSimpleAsyncResult *");
2089 async_result_decl.add_declarator (new CCodeVariableDeclarator ("_res_"));
2090 block.add_statement (async_result_decl);
2092 var async_result_creation = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_new"));
2093 async_result_creation.add_argument (new CCodeIdentifier ("_obj_"));
2094 async_result_creation.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_callback_"));
2095 async_result_creation.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_user_data_"));
2096 async_result_creation.add_argument (new CCodeIdentifier ("_data_"));
2097 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_res_"), async_result_creation)));
2099 var completecall = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete"));
2100 completecall.add_argument (new CCodeIdentifier ("_res_"));
2101 block.add_statement (new CCodeExpressionStatement (completecall));
2103 var obj_free = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
2104 obj_free.add_argument (new CCodeIdentifier ("_obj_"));
2105 block.add_statement (new CCodeExpressionStatement (obj_free));
2107 var async_result_free = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
2108 async_result_free.add_argument (new CCodeIdentifier ("_res_"));
2109 block.add_statement (new CCodeExpressionStatement (async_result_free));
2111 var datafree = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
2112 datafree.add_argument (new CCodeIdentifier (dataname));
2113 datafree.add_argument (new CCodeIdentifier ("_data_"));
2114 block.add_statement (new CCodeExpressionStatement (datafree));
2116 var pendingfree = new CCodeFunctionCall (new CCodeIdentifier ("dbus_pending_call_unref"));
2117 pendingfree.add_argument (new CCodeIdentifier ("pending"));
2118 block.add_statement (new CCodeExpressionStatement (pendingfree));
2120 source_declarations.add_type_member_declaration (function.copy ());
2121 function.block = block;
2122 source_type_member_definition.append (function);
2125 return proxy_name;
2128 CCodeConstant get_reply_signature (Method m) {
2129 // expected type signature for output parameters
2130 string type_signature = "";
2132 foreach (FormalParameter param in m.get_parameters ()) {
2133 if (param.direction == ParameterDirection.OUT) {
2134 type_signature += get_type_signature (param.parameter_type);
2138 if (!(m.return_type is VoidType)) {
2139 type_signature += get_type_signature (m.return_type);
2142 return (new CCodeConstant ("\"%s\"".printf (type_signature)));
2145 void check_reply_signature (Method m, CCodeBlock block) {
2146 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2147 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2149 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
2150 message_signature.add_argument (new CCodeIdentifier ("_reply"));
2152 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
2153 signature_check.add_argument (message_signature);
2154 signature_check.add_argument (get_reply_signature (m));
2156 var signature_error_block = new CCodeBlock ();
2157 var set_error_call = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
2158 set_error_call.add_argument (new CCodeIdentifier ("error"));
2159 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR"));
2160 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR_INVALID_SIGNATURE"));
2161 set_error_call.add_argument (new CCodeConstant ("\"Invalid signature, expected \\\"%s\\\", got \\\"%s\\\"\""));
2162 set_error_call.add_argument (get_reply_signature (m));
2163 set_error_call.add_argument (message_signature);
2164 signature_error_block.add_statement (new CCodeExpressionStatement (set_error_call));
2165 signature_error_block.add_statement (new CCodeExpressionStatement (reply_unref));
2166 signature_error_block.add_statement (new CCodeReturnStatement (default_value_for_type (m.return_type, false)));
2168 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
2171 string generate_finish_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
2172 string proxy_name = "%sdbus_proxy_%s_finish".printf (main_iface.get_lower_case_cprefix (), m.name);
2174 string dbus_iface_name = get_dbus_name (iface);
2176 CCodeDeclaration cdecl;
2178 var function = new CCodeFunction (proxy_name);
2179 function.modifiers = CCodeModifiers.STATIC;
2181 var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
2183 cparam_map.set (get_param_pos (0.1), new CCodeFormalParameter ("_res_", "GAsyncResult*"));
2185 generate_cparameters (m, source_declarations, cparam_map, function, null, null, null, 2);
2187 var block = new CCodeBlock ();
2188 var prefragment = new CCodeFragment ();
2189 var postfragment = new CCodeFragment ();
2191 string dataname = "%sDBusProxy%sData".printf (iface.get_cname (), Symbol.lower_case_to_camel_case (m.name));
2192 cdecl = new CCodeDeclaration (dataname + "*");
2193 cdecl.add_declarator (new CCodeVariableDeclarator ("_data_"));
2194 block.add_statement (cdecl);
2196 cdecl = new CCodeDeclaration ("DBusError");
2197 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
2198 block.add_statement (cdecl);
2200 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
2202 cdecl = new CCodeDeclaration ("DBusMessage");
2203 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
2204 block.add_statement (cdecl);
2206 cdecl = new CCodeDeclaration ("DBusMessageIter");
2207 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
2208 block.add_statement (cdecl);
2210 var get_source_tag = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_get_source_tag"));
2211 get_source_tag.add_argument (new CCodeCastExpression (new CCodeIdentifier ("_res_"), "GSimpleAsyncResult *"));
2212 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_data_"), get_source_tag)));
2214 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
2215 dbus_error_init.add_argument (dbus_error);
2216 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
2218 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_pending_call_steal_reply"));
2219 ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "pending"));
2220 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
2222 var set_error_from_message = new CCodeFunctionCall (new CCodeIdentifier ("dbus_set_error_from_message"));
2223 set_error_from_message.add_argument (dbus_error);
2224 set_error_from_message.add_argument (new CCodeIdentifier ("_reply"));
2225 block.add_statement (new CCodeExpressionStatement (set_error_from_message));
2227 check_error_reply (m, block);
2228 check_reply_signature (m, block);
2230 generate_marshalling (m, dbus_iface_name, prefragment, postfragment);
2232 block.add_statement (postfragment);
2234 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2235 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2236 block.add_statement (new CCodeExpressionStatement (reply_unref));
2238 if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) {
2239 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
2242 source_declarations.add_type_member_declaration (function.copy ());
2243 function.block = block;
2244 source_type_member_definition.append (function);
2246 return proxy_name;
2249 void check_property_error_reply (PropertyAccessor acc, CCodeBlock block) {
2250 var dbus_error = new CCodeIdentifier ("_dbus_error");
2251 var dbus_error_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, dbus_error);
2253 var error_block = new CCodeBlock ();
2255 var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
2256 ccritical.add_argument (new CCodeConstant ("\"file %s: line %d: uncaught error: %s (%s)\""));
2257 ccritical.add_argument (new CCodeConstant ("__FILE__"));
2258 ccritical.add_argument (new CCodeConstant ("__LINE__"));
2259 ccritical.add_argument (new CCodeMemberAccess (dbus_error, "message"));
2260 ccritical.add_argument (new CCodeMemberAccess (dbus_error, "name"));
2262 error_block.add_statement (new CCodeExpressionStatement (ccritical));
2264 var dbus_error_free = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_free"));
2265 dbus_error_free.add_argument (dbus_error_ptr);
2266 error_block.add_statement (new CCodeExpressionStatement (dbus_error_free));
2268 if (acc.readable && !acc.value_type.is_real_non_null_struct_type ()) {
2269 error_block.add_statement (new CCodeReturnStatement (default_value_for_type (acc.value_type, false)));
2270 } else {
2271 error_block.add_statement (new CCodeReturnStatement ());
2274 var dbus_error_is_set = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_is_set"));
2275 dbus_error_is_set.add_argument (dbus_error_ptr);
2276 block.add_statement (new CCodeIfStatement (dbus_error_is_set, error_block));
2279 CCodeConstant get_property_reply_signature (PropertyAccessor acc) {
2280 if (acc.readable) {
2281 return new CCodeConstant ("\"v\"");
2282 } else {
2283 return new CCodeConstant ("\"\"");
2287 CCodeConstant get_property_inner_signature (PropertyAccessor acc) {
2288 return new CCodeConstant ("\"%s\"".printf (get_type_signature (acc.value_type)));
2291 void check_property_reply_signature (PropertyAccessor acc, CCodeBlock block) {
2292 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2293 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2295 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
2296 message_signature.add_argument (new CCodeIdentifier ("_reply"));
2298 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
2299 signature_check.add_argument (message_signature);
2300 signature_check.add_argument (get_property_reply_signature (acc));
2302 var signature_error_block = new CCodeBlock ();
2304 var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
2305 ccritical.add_argument (new CCodeConstant ("\"file %s: line %d: Invalid signature, expected \\\"%s\\\", got \\\"%s\\\"\""));
2306 ccritical.add_argument (new CCodeConstant ("__FILE__"));
2307 ccritical.add_argument (new CCodeConstant ("__LINE__"));
2308 ccritical.add_argument (get_property_reply_signature (acc));
2309 ccritical.add_argument (message_signature);
2311 signature_error_block.add_statement (new CCodeExpressionStatement (ccritical));
2312 signature_error_block.add_statement (new CCodeExpressionStatement (reply_unref));
2314 if (acc.readable && !acc.value_type.is_real_non_null_struct_type ()) {
2315 signature_error_block.add_statement (new CCodeReturnStatement (default_value_for_type (acc.value_type, false)));
2316 } else {
2317 signature_error_block.add_statement (new CCodeReturnStatement ());
2320 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
2323 void check_property_inner_signature (PropertyAccessor acc, CCodeFragment fragment) {
2324 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2325 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2327 var iter_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_get_signature"));
2328 iter_signature.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter")));
2330 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
2331 signature_check.add_argument (iter_signature);
2332 signature_check.add_argument (get_property_inner_signature (acc));
2334 var signature_error_block = new CCodeBlock ();
2336 var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
2337 ccritical.add_argument (new CCodeConstant ("\"file %s: line %d: Invalid signature, expected \\\"%s\\\", got \\\"%s\\\"\""));
2338 ccritical.add_argument (new CCodeConstant ("__FILE__"));
2339 ccritical.add_argument (new CCodeConstant ("__LINE__"));
2340 ccritical.add_argument (get_property_inner_signature (acc));
2341 ccritical.add_argument (iter_signature);
2343 signature_error_block.add_statement (new CCodeExpressionStatement (ccritical));
2344 signature_error_block.add_statement (new CCodeExpressionStatement (reply_unref));
2346 if (!acc.value_type.is_real_non_null_struct_type ()) {
2347 signature_error_block.add_statement (new CCodeReturnStatement (default_value_for_type (acc.value_type, false)));
2348 } else {
2349 signature_error_block.add_statement (new CCodeReturnStatement ());
2352 fragment.append (new CCodeIfStatement (signature_check, signature_error_block));
2355 string generate_dbus_proxy_property_get (Interface main_iface, Interface iface, Property prop) {
2356 string proxy_name = "%sdbus_proxy_get_%s".printf (main_iface.get_lower_case_cprefix (), prop.name);
2358 string dbus_iface_name = get_dbus_name (iface);
2360 var owned_type = prop.get_accessor.value_type.copy ();
2361 owned_type.value_owned = true;
2362 if (owned_type.is_disposable () && !prop.get_accessor.value_type.value_owned) {
2363 Report.error (prop.get_accessor.value_type.source_reference, "Properties used in D-Bus clients require owned get accessor");
2366 var array_type = prop.get_accessor.value_type as ArrayType;
2368 CCodeDeclaration cdecl;
2370 var function = new CCodeFunction (proxy_name);
2371 function.modifiers = CCodeModifiers.STATIC;
2373 function.add_parameter (new CCodeFormalParameter ("self", "%s*".printf (iface.get_cname ())));
2375 if (prop.property_type.is_real_non_null_struct_type ()) {
2376 function.add_parameter (new CCodeFormalParameter ("result", "%s*".printf (prop.get_accessor.value_type.get_cname ())));
2377 } else {
2378 if (array_type != null) {
2379 for (int dim = 1; dim <= array_type.rank; dim++) {
2380 function.add_parameter (new CCodeFormalParameter ("result_length%d".printf (dim), "int*"));
2384 function.return_type = prop.get_accessor.value_type.get_cname ();
2387 var block = new CCodeBlock ();
2388 var prefragment = new CCodeFragment ();
2389 var postfragment = new CCodeFragment ();
2391 var dispose_return_block = new CCodeBlock ();
2392 if (prop.property_type.is_real_non_null_struct_type ()) {
2393 dispose_return_block.add_statement (new CCodeReturnStatement ());
2394 } else {
2395 dispose_return_block.add_statement (new CCodeReturnStatement (default_value_for_type (prop.property_type, false)));
2397 block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), iface.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block));
2399 cdecl = new CCodeDeclaration ("DBusError");
2400 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
2401 block.add_statement (cdecl);
2403 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
2405 cdecl = new CCodeDeclaration ("DBusGConnection");
2406 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
2407 block.add_statement (cdecl);
2409 cdecl = new CCodeDeclaration ("DBusMessage");
2410 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
2411 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
2412 block.add_statement (cdecl);
2414 cdecl = new CCodeDeclaration ("DBusMessageIter");
2415 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
2416 cdecl.add_declarator (new CCodeVariableDeclarator ("_subiter"));
2417 block.add_statement (cdecl);
2419 block.add_statement (prefragment);
2421 var destination = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_bus_name"));
2422 destination.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
2423 var path = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_path"));
2424 path.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
2426 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_call"));
2427 msgcall.add_argument (destination);
2428 msgcall.add_argument (path);
2429 msgcall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties\""));
2430 msgcall.add_argument (new CCodeConstant ("\"Get\""));
2431 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall)));
2433 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
2434 iter_call.add_argument (new CCodeIdentifier ("_message"));
2435 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2436 prefragment.append (new CCodeExpressionStatement (iter_call));
2438 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
2439 iter_call.add_argument (new CCodeIdentifier ("_reply"));
2440 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2441 postfragment.append (new CCodeExpressionStatement (iter_call));
2443 // interface name
2444 write_expression (prefragment, string_type, new CCodeIdentifier ("_iter"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
2445 // property name
2446 write_expression (prefragment, string_type, new CCodeIdentifier ("_iter"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
2448 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_recurse"));
2449 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2450 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter")));
2451 postfragment.append (new CCodeExpressionStatement (iter_call));
2453 check_property_inner_signature (prop.get_accessor, postfragment);
2455 if (prop.property_type.is_real_non_null_struct_type ()) {
2456 var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
2457 var expr = read_expression (postfragment, prop.get_accessor.value_type, new CCodeIdentifier ("_subiter"), target);
2458 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
2459 } else {
2460 cdecl = new CCodeDeclaration (prop.get_accessor.value_type.get_cname ());
2461 cdecl.add_declarator (new CCodeVariableDeclarator ("_result"));
2462 postfragment.append (cdecl);
2464 if (array_type != null) {
2465 for (int dim = 1; dim <= array_type.rank; dim++) {
2466 cdecl = new CCodeDeclaration ("int");
2467 cdecl.add_declarator (new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
2468 postfragment.append (cdecl);
2472 var target = new CCodeIdentifier ("_result");
2473 var expr = read_expression (postfragment, prop.get_accessor.value_type, new CCodeIdentifier ("_subiter"), target);
2474 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
2476 if (array_type != null) {
2477 for (int dim = 1; dim <= array_type.rank; dim++) {
2478 // TODO check that parameter is not NULL (out parameters are optional)
2479 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)))));
2484 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
2485 gconnection.add_argument (new CCodeIdentifier ("self"));
2486 gconnection.add_argument (new CCodeConstant ("\"connection\""));
2487 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
2488 gconnection.add_argument (new CCodeConstant ("NULL"));
2489 block.add_statement (new CCodeExpressionStatement (gconnection));
2491 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
2492 dbus_error_init.add_argument (dbus_error);
2493 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
2495 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
2496 connection.add_argument (new CCodeIdentifier ("_connection"));
2498 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
2499 ccall.add_argument (connection);
2500 ccall.add_argument (new CCodeIdentifier ("_message"));
2501 ccall.add_argument (get_dbus_timeout (prop));
2502 ccall.add_argument (dbus_error);
2503 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
2505 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
2506 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
2507 block.add_statement (new CCodeExpressionStatement (conn_unref));
2509 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2510 message_unref.add_argument (new CCodeIdentifier ("_message"));
2511 block.add_statement (new CCodeExpressionStatement (message_unref));
2513 check_property_error_reply (prop.get_accessor, block);
2514 check_property_reply_signature (prop.get_accessor, block);
2516 block.add_statement (postfragment);
2518 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2519 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2520 block.add_statement (new CCodeExpressionStatement (reply_unref));
2522 if (prop.property_type.is_real_non_null_struct_type ()) {
2523 block.add_statement (new CCodeReturnStatement ());
2524 } else {
2525 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
2528 source_declarations.add_type_member_declaration (function.copy ());
2529 function.block = block;
2530 source_type_member_definition.append (function);
2532 return proxy_name;
2535 string generate_dbus_proxy_property_set (Interface main_iface, Interface iface, Property prop) {
2536 string proxy_name = "%sdbus_proxy_set_%s".printf (main_iface.get_lower_case_cprefix (), prop.name);
2538 string dbus_iface_name = get_dbus_name (iface);
2540 var array_type = prop.set_accessor.value_type as ArrayType;
2542 CCodeDeclaration cdecl;
2544 var function = new CCodeFunction (proxy_name);
2545 function.modifiers = CCodeModifiers.STATIC;
2547 function.add_parameter (new CCodeFormalParameter ("self", "%s*".printf (iface.get_cname ())));
2549 if (prop.property_type.is_real_non_null_struct_type ()) {
2550 function.add_parameter (new CCodeFormalParameter ("value", "%s*".printf (prop.set_accessor.value_type.get_cname ())));
2551 } else {
2552 function.add_parameter (new CCodeFormalParameter ("value", prop.set_accessor.value_type.get_cname ()));
2554 if (array_type != null) {
2555 for (int dim = 1; dim <= array_type.rank; dim++) {
2556 function.add_parameter (new CCodeFormalParameter ("value_length%d".printf (dim), "int"));
2561 var block = new CCodeBlock ();
2562 var prefragment = new CCodeFragment ();
2563 var postfragment = new CCodeFragment ();
2565 var dispose_return_block = new CCodeBlock ();
2566 dispose_return_block.add_statement (new CCodeReturnStatement ());
2567 block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), iface.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block));
2569 cdecl = new CCodeDeclaration ("DBusError");
2570 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
2571 block.add_statement (cdecl);
2573 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
2575 cdecl = new CCodeDeclaration ("DBusGConnection");
2576 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
2577 block.add_statement (cdecl);
2579 cdecl = new CCodeDeclaration ("DBusMessage");
2580 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
2581 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
2582 block.add_statement (cdecl);
2584 cdecl = new CCodeDeclaration ("DBusMessageIter");
2585 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
2586 cdecl.add_declarator (new CCodeVariableDeclarator ("_subiter"));
2587 block.add_statement (cdecl);
2589 block.add_statement (prefragment);
2591 var destination = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_bus_name"));
2592 destination.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
2593 var path = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_path"));
2594 path.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
2596 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_call"));
2597 msgcall.add_argument (destination);
2598 msgcall.add_argument (path);
2599 msgcall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties\""));
2600 msgcall.add_argument (new CCodeConstant ("\"Set\""));
2601 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall)));
2603 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
2604 iter_call.add_argument (new CCodeIdentifier ("_message"));
2605 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2606 prefragment.append (new CCodeExpressionStatement (iter_call));
2608 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
2609 iter_call.add_argument (new CCodeIdentifier ("_reply"));
2610 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2611 postfragment.append (new CCodeExpressionStatement (iter_call));
2613 // interface name
2614 write_expression (prefragment, string_type, new CCodeIdentifier ("_iter"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
2615 // property name
2616 write_expression (prefragment, string_type, new CCodeIdentifier ("_iter"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
2618 // property value (as variant)
2619 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
2620 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2621 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_VARIANT"));
2622 iter_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_signature (prop.property_type))));
2623 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter")));
2624 prefragment.append (new CCodeExpressionStatement (iter_call));
2626 if (prop.property_type.is_real_non_null_struct_type ()) {
2627 write_expression (prefragment, prop.set_accessor.value_type, new CCodeIdentifier ("_subiter"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("value")));
2628 } else {
2629 write_expression (prefragment, prop.set_accessor.value_type, new CCodeIdentifier ("_subiter"), new CCodeIdentifier ("value"));
2632 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
2633 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2634 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter")));
2635 prefragment.append (new CCodeExpressionStatement (iter_call));
2637 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
2638 gconnection.add_argument (new CCodeIdentifier ("self"));
2639 gconnection.add_argument (new CCodeConstant ("\"connection\""));
2640 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
2641 gconnection.add_argument (new CCodeConstant ("NULL"));
2642 block.add_statement (new CCodeExpressionStatement (gconnection));
2644 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
2645 dbus_error_init.add_argument (dbus_error);
2646 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
2648 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
2649 connection.add_argument (new CCodeIdentifier ("_connection"));
2651 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
2652 ccall.add_argument (connection);
2653 ccall.add_argument (new CCodeIdentifier ("_message"));
2654 ccall.add_argument (get_dbus_timeout (prop));
2655 ccall.add_argument (dbus_error);
2656 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
2658 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
2659 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
2660 block.add_statement (new CCodeExpressionStatement (conn_unref));
2662 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2663 message_unref.add_argument (new CCodeIdentifier ("_message"));
2664 block.add_statement (new CCodeExpressionStatement (message_unref));
2666 check_property_error_reply (prop.set_accessor, block);
2667 check_property_reply_signature (prop.set_accessor, block);
2669 block.add_statement (postfragment);
2671 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2672 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2673 block.add_statement (new CCodeExpressionStatement (reply_unref));
2675 source_declarations.add_type_member_declaration (function.copy ());
2676 function.block = block;
2677 source_type_member_definition.append (function);
2679 return proxy_name;