vapigen: Remove misleading --metadata, each .gir must have its own .metadata.
[vala-lang.git] / codegen / valadbusclientmodule.vala
blob1e22c0646e065cfe98f0aff460115a066f647fd4
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 string get_dynamic_dbus_name (string vala_name) {
34 // TODO switch default to no transformation as soon as we have static D-Bus client support
35 // keep transformation by default for static D-Bus client and server support
36 if (context.dbus_transformation) {
37 return Symbol.lower_case_to_camel_case (vala_name);
38 } else {
39 return vala_name;
43 public CCodeConstant get_dbus_timeout (Symbol symbol) {
44 int timeout = -1;
46 var dbus = symbol.get_attribute ("DBus");
47 if (dbus != null && dbus.has_argument ("timeout")) {
48 timeout = dbus.get_integer ("timeout");
49 } else if (symbol.parent_symbol != null) {
50 return get_dbus_timeout (symbol.parent_symbol);
53 return new CCodeConstant (timeout.to_string ());
56 public static bool is_dbus_no_reply (CodeNode node) {
57 var dbus_attribute = node.get_attribute ("DBus");
58 if (dbus_attribute != null
59 && dbus_attribute.has_argument ("no_reply")
60 && dbus_attribute.get_bool ("no_reply")) {
61 return true;
64 return false;
67 bool has_dbus_error (List<DataType> error_types) {
68 foreach (DataType error_type in error_types) {
69 if (((ErrorType) error_type).error_domain.get_full_name () == "DBus.Error") {
70 return true;
73 return false;
76 public override void generate_dynamic_method_wrapper (DynamicMethod method) {
77 var dynamic_method = (DynamicMethod) method;
79 var func = new CCodeFunction (method.get_cname ());
80 func.modifiers = CCodeModifiers.STATIC;
82 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
84 generate_cparameters (method, cfile, cparam_map, func);
86 var block = new CCodeBlock ();
87 if (dynamic_method.dynamic_type.data_type == dbus_object_type) {
88 generate_dbus_method_wrapper (method, block);
89 } else {
90 Report.error (method.source_reference, "dynamic methods are not supported for `%s'".printf (dynamic_method.dynamic_type.to_string ()));
93 // append to C source file
94 cfile.add_function_declaration (func);
96 func.block = block;
97 cfile.add_function (func);
100 void generate_dbus_method_wrapper (Method method, CCodeBlock block) {
101 var dynamic_method = (DynamicMethod) method;
103 var expr = dynamic_method.invocation;
105 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_begin_call"));
107 ccall.add_argument (new CCodeIdentifier ("self"));
109 bool found_out = false;
110 Expression callback = null;
111 int callback_index = -1;
112 int arg_index = 1;
113 foreach (Expression arg in expr.get_argument_list ()) {
114 if (arg.symbol_reference is Method) {
115 // callback
116 if (callback != null) {
117 Report.error (expr.source_reference, "only one reply callback may be specified in invocation of DBus method");
118 expr.error = true;
119 return;
120 } else if (found_out) {
121 Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method");
122 expr.error = true;
123 return;
125 callback = arg;
126 callback_index = arg_index;
127 } else if (arg is UnaryExpression && ((UnaryExpression) arg).operator == UnaryOperator.OUT) {
128 // out arg
129 if (callback != null) {
130 Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method");
131 expr.error = true;
132 return;
134 found_out = true;
135 } else {
136 // in arg
137 if (callback != null || found_out) {
138 Report.error (expr.source_reference, "in argument must not follow out argument or reply callback in invocation of DBus method");
139 expr.error = true;
140 return;
143 arg_index++;
146 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (method.name))));
148 if (callback != null) {
149 var reply_method = (Method) callback.symbol_reference;
151 var cb_fun = new CCodeFunction ("_%s_cb".printf (reply_method.get_cname ()), "void");
152 cb_fun.modifiers = CCodeModifiers.STATIC;
153 cb_fun.add_parameter (new CCodeParameter ("proxy", "DBusGProxy*"));
154 cb_fun.add_parameter (new CCodeParameter ("call", "DBusGProxyCall*"));
155 cb_fun.add_parameter (new CCodeParameter ("user_data", "void*"));
156 cb_fun.block = new CCodeBlock ();
157 var cerrdecl = new CCodeDeclaration ("GError*");
158 cerrdecl.add_declarator (new CCodeVariableDeclarator ("error", new CCodeConstant ("NULL")));
159 cb_fun.block.add_statement (cerrdecl);
160 var cend_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_end_call"));
161 cend_call.add_argument (new CCodeIdentifier ("proxy"));
162 cend_call.add_argument (new CCodeIdentifier ("call"));
163 cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
164 var creply_call = new CCodeFunctionCall (get_cvalue (callback));
165 if (reply_method.binding != MemberBinding.STATIC) {
166 creply_call.add_argument (new CCodeIdentifier ("user_data"));
168 int param_count = reply_method.get_parameters ().size;
169 int i = 0;
170 foreach (Parameter param in reply_method.get_parameters ()) {
171 if ((++i) == param_count) {
172 if (!(param.variable_type is ErrorType)) {
173 Report.error (null, "DBus reply callbacks must end with GLib.Error argument");
174 return;
177 break;
179 if (param.variable_type is ArrayType && ((ArrayType) param.variable_type).element_type.data_type != string_type.data_type) {
180 var array_type = (ArrayType) param.variable_type;
181 CCodeDeclaration cdecl;
182 if (dbus_use_ptr_array (array_type)) {
183 cdecl = new CCodeDeclaration ("GPtrArray*");
184 } else {
185 cdecl = new CCodeDeclaration ("GArray*");
187 cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
188 cb_fun.block.add_statement (cdecl);
189 cend_call.add_argument (get_dbus_g_type (array_type));
190 cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
191 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 ()));
192 creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "len"));
193 } else {
194 var cdecl = new CCodeDeclaration (param.variable_type.get_cname ());
195 cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
196 cb_fun.block.add_statement (cdecl);
197 cend_call.add_argument (get_dbus_g_type (param.variable_type));
198 cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
199 creply_call.add_argument (new CCodeIdentifier (param.name));
201 if (param.variable_type is ArrayType && ((ArrayType) param.variable_type).element_type.data_type == string_type.data_type) {
202 var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
203 cstrvlen.add_argument (new CCodeIdentifier (param.name));
204 creply_call.add_argument (cstrvlen);
209 cend_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
210 cb_fun.block.add_statement (new CCodeExpressionStatement (cend_call));
211 creply_call.add_argument (new CCodeIdentifier ("error"));
212 cb_fun.block.add_statement (new CCodeExpressionStatement (creply_call));
214 CCodeExpression target = new CCodeConstant ("param%d_target".printf (callback_index));
215 var ma = (MemberAccess) callback;
216 if (reply_method.binding != MemberBinding.STATIC && ma.inner.value_type.data_type != null && ma.inner.value_type.data_type.is_reference_counting ()) {
217 // unref user_data after creply_call
218 var unref_call = new CCodeFunctionCall (get_destroy_func_expression (ma.inner.value_type));
219 unref_call.add_argument (new CCodeIdentifier ("user_data"));
220 cb_fun.block.add_statement (new CCodeExpressionStatement (unref_call));
222 // ref target for ccall
223 var ref_call = new CCodeFunctionCall (get_dup_func_expression (ma.inner.value_type, callback.source_reference));
224 ref_call.add_argument (target);
225 target = ref_call;
228 if (!cfile.add_declaration (cb_fun.name)) {
229 // avoid duplicate function definition
230 cfile.add_function (cb_fun);
233 ccall.add_argument (new CCodeIdentifier (cb_fun.name));
234 ccall.add_argument (target);
235 ccall.add_argument (new CCodeConstant ("NULL"));
236 } else {
237 ccall.call = new CCodeIdentifier ("dbus_g_proxy_call");
239 ccall.add_argument (new CCodeIdentifier ("error"));
242 foreach (Parameter param in method.get_parameters ()) {
243 if (param.variable_type is MethodType
244 || param.variable_type is DelegateType) {
245 // callback parameter
246 break;
249 if (param.direction != ParameterDirection.IN) {
250 continue;
253 var array_type = param.variable_type as ArrayType;
254 if (array_type != null) {
255 // array parameter
256 if (array_type.element_type.data_type != string_type.data_type) {
257 // non-string arrays (use GArray)
258 ccall.add_argument (get_dbus_g_type (array_type));
260 var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
261 sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
263 CCodeDeclaration cdecl;
264 CCodeFunctionCall array_construct;
265 if (dbus_use_ptr_array (array_type)) {
266 cdecl = new CCodeDeclaration ("GPtrArray*");
268 array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_ptr_array_sized_new"));
269 array_construct.add_argument (new CCodeIdentifier (get_parameter_array_length_cname (param, 1)));
270 } else {
271 cdecl = new CCodeDeclaration ("GArray*");
273 array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_array_new"));
274 array_construct.add_argument (new CCodeConstant ("TRUE"));
275 array_construct.add_argument (new CCodeConstant ("TRUE"));
276 array_construct.add_argument (sizeof_call);
279 cdecl.add_declarator (new CCodeVariableDeclarator ("dbus_%s".printf (param.name), array_construct));
280 block.add_statement (cdecl);
282 if (dbus_use_ptr_array (array_type)) {
283 cfile.add_include ("string.h");
285 var memcpy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
286 memcpy_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_%s".printf (param.name)), "pdata"));
287 memcpy_call.add_argument (new CCodeIdentifier (param.name));
288 memcpy_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeIdentifier (get_parameter_array_length_cname (param, 1)), sizeof_call));
289 block.add_statement (new CCodeExpressionStatement (memcpy_call));
291 var len_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_%s".printf (param.name)), "len"), new CCodeIdentifier (get_parameter_array_length_cname (param, 1)));
292 block.add_statement (new CCodeExpressionStatement (len_assignment));
293 } else {
294 var cappend_call = new CCodeFunctionCall (new CCodeIdentifier ("g_array_append_vals"));
295 cappend_call.add_argument (new CCodeIdentifier ("dbus_%s".printf (param.name)));
296 cappend_call.add_argument (new CCodeIdentifier (param.name));
297 cappend_call.add_argument (new CCodeIdentifier (get_parameter_array_length_cname (param, 1)));
298 block.add_statement (new CCodeExpressionStatement (cappend_call));
301 ccall.add_argument (new CCodeIdentifier ("dbus_%s".printf (param.name)));
302 } else {
303 // string arrays
304 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
305 ccall.add_argument (new CCodeIdentifier (param.name));
307 } else if (get_type_signature (param.variable_type).has_prefix ("(")) {
308 // struct parameter
309 var st = (Struct) param.variable_type.data_type;
311 var array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_new"));
312 array_construct.add_argument (new CCodeConstant ("0"));
314 var cdecl = new CCodeDeclaration ("GValueArray*");
315 cdecl.add_declarator (new CCodeVariableDeclarator ("dbus_%s".printf (param.name), array_construct));
316 block.add_statement (cdecl);
318 foreach (Field f in st.get_fields ()) {
319 if (f.binding != MemberBinding.INSTANCE) {
320 continue;
323 string val_name = "val_%s_%s".printf (param.name, f.name);
325 // 0-initialize struct with struct initializer { 0 }
326 var cvalinit = new CCodeInitializerList ();
327 cvalinit.append (new CCodeConstant ("0"));
329 var cval_decl = new CCodeDeclaration ("GValue");
330 cval_decl.add_declarator (new CCodeVariableDeclarator.zero (val_name, cvalinit));
331 block.add_statement (cval_decl);
333 var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (val_name));
335 var cinit_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init"));
336 cinit_call.add_argument (val_ptr);
337 cinit_call.add_argument (new CCodeIdentifier (f.variable_type.data_type.get_type_id ()));
338 block.add_statement (new CCodeExpressionStatement (cinit_call));
340 var cset_call = new CCodeFunctionCall (new CCodeIdentifier (f.variable_type.data_type.get_set_value_function ()));
341 cset_call.add_argument (val_ptr);
342 cset_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), f.name));
343 block.add_statement (new CCodeExpressionStatement (cset_call));
345 var cappend_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_append"));
346 cappend_call.add_argument (new CCodeIdentifier ("dbus_%s".printf (param.name)));
347 cappend_call.add_argument (val_ptr);
348 block.add_statement (new CCodeExpressionStatement (cappend_call));
351 ccall.add_argument (get_dbus_g_type (param.variable_type));
352 ccall.add_argument (new CCodeIdentifier ("dbus_%s".printf (param.name)));
353 } else {
354 ccall.add_argument (get_dbus_g_type (param.variable_type));
355 ccall.add_argument (new CCodeIdentifier (param.name));
359 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
361 var out_marshalling_fragment = new CCodeFragment ();
363 foreach (Parameter param in method.get_parameters ()) {
364 if (param.variable_type is MethodType) {
365 // callback parameter
366 break;
369 if (param.direction != ParameterDirection.OUT) {
370 continue;
373 if (get_type_signature (param.variable_type).has_prefix ("(")) {
374 // struct output parameter
375 var st = (Struct) param.variable_type.data_type;
377 var cdecl = new CCodeDeclaration ("GValueArray*");
378 cdecl.add_declarator (new CCodeVariableDeclarator ("dbus_%s".printf (param.name)));
379 block.add_statement (cdecl);
381 int i = 0;
382 foreach (Field f in st.get_fields ()) {
383 if (f.binding != MemberBinding.INSTANCE) {
384 continue;
387 var cget_call = new CCodeFunctionCall (new CCodeIdentifier (f.variable_type.data_type.get_get_value_function ()));
388 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 ()))));
390 var converted_value = cget_call;
392 if (requires_copy (f.variable_type)) {
393 var dupexpr = get_dup_func_expression (f.variable_type, expr.source_reference);
394 converted_value = new CCodeFunctionCall (dupexpr);
395 converted_value.add_argument (cget_call);
398 var assign = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), f.name), converted_value);
399 out_marshalling_fragment.append (new CCodeExpressionStatement (assign));
401 i++;
404 ccall.add_argument (get_dbus_g_type (param.variable_type));
405 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("dbus_%s".printf (param.name))));
406 } else {
407 ccall.add_argument (get_dbus_g_type (param.variable_type));
408 ccall.add_argument (new CCodeIdentifier (param.name));
412 if (!(method.return_type is VoidType)) {
413 // synchronous D-Bus method call with reply
414 ccall.add_argument (get_dbus_g_type (method.return_type));
416 var array_type = method.return_type as ArrayType;
417 if (array_type != null && array_type.element_type.data_type != string_type.data_type) {
418 // non-string arrays (use GArray)
419 CCodeDeclaration cdecl;
420 if (dbus_use_ptr_array (array_type)) {
421 cdecl = new CCodeDeclaration ("GPtrArray*");
422 } else {
423 cdecl = new CCodeDeclaration ("GArray*");
425 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
426 block.add_statement (cdecl);
428 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
429 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
431 block.add_statement (new CCodeExpressionStatement (ccall));
433 // don't access result when error occured
434 var creturnblock = new CCodeBlock ();
435 creturnblock.add_statement (new CCodeReturnStatement (default_value_for_type (method.return_type, false)));
436 var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
437 block.add_statement (cerrorif);
439 block.add_statement (out_marshalling_fragment);
441 // *result_length1 = result->len;
442 var garray_length = new CCodeMemberAccess.pointer (new CCodeIdentifier ("result"), "len");
443 var result_length = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length1"));
444 var assign = new CCodeAssignment (result_length, garray_length);
445 block.add_statement (new CCodeExpressionStatement (assign));
447 // return result->data;
448 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 ())));
449 } else if (method.return_type.is_real_non_null_struct_type ()) {
450 // structs are returned via out parameter
451 var st = (Struct) method.return_type.data_type;
453 if (st.get_full_name () == "GLib.Value") {
454 ccall.add_argument (new CCodeIdentifier ("result"));
455 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
457 block.add_statement (new CCodeExpressionStatement (ccall));
458 } else {
459 var cdecl = new CCodeDeclaration ("GValueArray*");
460 cdecl.add_declarator (new CCodeVariableDeclarator ("dbus_result"));
461 block.add_statement (cdecl);
463 int i = 0;
464 foreach (Field f in st.get_fields ()) {
465 if (f.binding != MemberBinding.INSTANCE) {
466 continue;
469 var cget_call = new CCodeFunctionCall (new CCodeIdentifier (f.variable_type.data_type.get_get_value_function ()));
470 cget_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeElementAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_result"), "values"), new CCodeConstant (i.to_string ()))));
472 var converted_value = cget_call;
474 if (requires_copy (f.variable_type)) {
475 var dupexpr = get_dup_func_expression (f.variable_type, expr.source_reference);
476 converted_value = new CCodeFunctionCall (dupexpr);
477 converted_value.add_argument (cget_call);
480 var assign = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("result"), f.name), converted_value);
481 out_marshalling_fragment.append (new CCodeExpressionStatement (assign));
483 i++;
486 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("dbus_result")));
487 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
489 block.add_statement (new CCodeExpressionStatement (ccall));
492 // don't access result when error occured
493 var creturnblock = new CCodeBlock ();
494 creturnblock.add_statement (new CCodeReturnStatement ());
495 var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
496 block.add_statement (cerrorif);
498 block.add_statement (out_marshalling_fragment);
499 } else {
500 // string arrays or other datatypes
501 var cdecl = new CCodeDeclaration (method.return_type.get_cname ());
502 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
503 block.add_statement (cdecl);
505 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
506 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
508 block.add_statement (new CCodeExpressionStatement (ccall));
510 // don't access result when error occured
511 var creturnblock = new CCodeBlock ();
512 creturnblock.add_statement (new CCodeReturnStatement (default_value_for_type (method.return_type, false)));
513 var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
514 block.add_statement (cerrorif);
516 block.add_statement (out_marshalling_fragment);
518 if (array_type != null) {
519 // special case string array
521 // *result_length1 = g_strv_length (result);
522 var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
523 cstrvlen.add_argument (new CCodeIdentifier ("result"));
524 var result_length = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length1"));
525 var assign = new CCodeAssignment (result_length, cstrvlen);
526 block.add_statement (new CCodeExpressionStatement (assign));
529 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
531 } else {
532 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
534 block.add_statement (new CCodeExpressionStatement (ccall));
536 // don't access result when error occured
537 var creturnblock = new CCodeBlock ();
538 creturnblock.add_statement (new CCodeReturnStatement ());
539 var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
540 block.add_statement (cerrorif);
542 block.add_statement (out_marshalling_fragment);
546 public override CCodeExpression get_dbus_g_type (DataType data_type) {
547 if (data_type is ArrayType) {
548 var array_type = data_type as ArrayType;
549 if (array_type.element_type.data_type == string_type.data_type) {
550 return new CCodeIdentifier ("G_TYPE_STRV");
553 var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection"));
554 if (dbus_use_ptr_array (array_type)) {
555 carray_type.add_argument (new CCodeConstant ("\"GPtrArray\""));
556 } else {
557 carray_type.add_argument (new CCodeConstant ("\"GArray\""));
559 carray_type.add_argument (get_dbus_g_type (array_type.element_type));
560 return carray_type;
561 } else if (data_type.data_type is Enum) {
562 var en = (Enum) data_type.data_type;
563 if (en.is_flags) {
564 return new CCodeIdentifier ("G_TYPE_UINT");
565 } else {
566 return new CCodeIdentifier ("G_TYPE_INT");
568 } else if (data_type.data_type == null) {
569 critical ("Internal error during DBus type generation with: %s", data_type.to_string ());
570 return new CCodeIdentifier ("G_TYPE_NONE");
571 } else if (data_type.data_type.get_full_name () == "GLib.HashTable") {
572 var cmap_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_map"));
573 var type_args = data_type.get_type_arguments ();
575 cmap_type.add_argument (new CCodeConstant ("\"GHashTable\""));
576 foreach (DataType type_arg in type_args) {
577 cmap_type.add_argument (get_dbus_g_type (type_arg));
580 return cmap_type;
581 } else if (get_type_signature (data_type).has_prefix ("(")) {
582 // struct parameter
583 var st = (Struct) data_type.data_type;
585 var type_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_struct"));
586 type_call.add_argument (new CCodeConstant ("\"GValueArray\""));
588 foreach (Field f in st.get_fields ()) {
589 if (f.binding != MemberBinding.INSTANCE) {
590 continue;
593 type_call.add_argument (get_dbus_g_type (f.variable_type));
596 type_call.add_argument (new CCodeConstant ("G_TYPE_INVALID"));
598 return type_call;
599 } else {
600 return new CCodeIdentifier (data_type.data_type.get_type_id ());
604 public bool dbus_use_ptr_array (ArrayType array_type) {
605 if (array_type.element_type.data_type == string_type.data_type) {
606 // use char**
607 return false;
608 } else if (array_type.element_type.data_type == bool_type.data_type
609 || array_type.element_type.data_type == char_type.data_type
610 || array_type.element_type.data_type == uchar_type.data_type
611 || array_type.element_type.data_type == int_type.data_type
612 || array_type.element_type.data_type == uint_type.data_type
613 || array_type.element_type.data_type == long_type.data_type
614 || array_type.element_type.data_type == ulong_type.data_type
615 || array_type.element_type.data_type == int8_type.data_type
616 || array_type.element_type.data_type == uint8_type.data_type
617 || array_type.element_type.data_type == int32_type.data_type
618 || array_type.element_type.data_type == uint32_type.data_type
619 || array_type.element_type.data_type == int64_type.data_type
620 || array_type.element_type.data_type == uint64_type.data_type
621 || array_type.element_type.data_type == double_type.data_type) {
622 // use GArray
623 return false;
624 } else {
625 // use GPtrArray
626 return true;
630 public override string get_dynamic_property_getter_cname (DynamicProperty prop) {
631 if (prop.dynamic_type.data_type != dbus_object_type) {
632 return base.get_dynamic_property_getter_cname (prop);
635 string getter_cname = "_dynamic_get_%s%d".printf (prop.name, dynamic_property_id++);
637 if (get_type_signature (prop.property_type) == null) {
638 Report.error (prop.property_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (prop.property_type.to_string ()));
639 return getter_cname;
642 var func = new CCodeFunction (getter_cname, prop.property_type.get_cname ());
643 func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
645 func.add_parameter (new CCodeParameter ("obj", prop.dynamic_type.get_cname ()));
647 var block = new CCodeBlock ();
648 generate_dbus_property_getter_wrapper (prop, block);
650 // append to C source file
651 cfile.add_function_declaration (func);
653 func.block = block;
654 cfile.add_function (func);
656 return getter_cname;
659 public override string get_dynamic_property_setter_cname (DynamicProperty prop) {
660 if (prop.dynamic_type.data_type != dbus_object_type) {
661 return base.get_dynamic_property_setter_cname (prop);
664 string setter_cname = "_dynamic_set_%s%d".printf (prop.name, dynamic_property_id++);
666 if (get_type_signature (prop.property_type) == null) {
667 Report.error (prop.property_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (prop.property_type.to_string ()));
668 return setter_cname;
671 var func = new CCodeFunction (setter_cname, "void");
672 func.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.INLINE;
674 func.add_parameter (new CCodeParameter ("obj", prop.dynamic_type.get_cname ()));
675 func.add_parameter (new CCodeParameter ("value", prop.property_type.get_cname ()));
677 var block = new CCodeBlock ();
678 generate_dbus_property_setter_wrapper (prop, block);
680 // append to C source file
681 cfile.add_function_declaration (func);
683 func.block = block;
684 cfile.add_function (func);
686 return setter_cname;
689 void create_dbus_property_proxy (DynamicProperty node, CCodeBlock block) {
690 var prop_proxy_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_new_from_proxy"));
691 prop_proxy_call.add_argument (new CCodeIdentifier ("obj"));
692 prop_proxy_call.add_argument (new CCodeConstant ("DBUS_INTERFACE_PROPERTIES"));
693 prop_proxy_call.add_argument (new CCodeConstant ("NULL"));
695 var prop_proxy_decl = new CCodeDeclaration ("DBusGProxy*");
696 prop_proxy_decl.add_declarator (new CCodeVariableDeclarator ("property_proxy", prop_proxy_call));
697 block.add_statement (prop_proxy_decl);
700 void generate_dbus_property_getter_wrapper (DynamicProperty node, CCodeBlock block) {
701 create_dbus_property_proxy (node, block);
703 // initialize GValue
704 var cvalinit = new CCodeInitializerList ();
705 cvalinit.append (new CCodeConstant ("0"));
707 var cval_decl = new CCodeDeclaration ("GValue");
708 cval_decl.add_declarator (new CCodeVariableDeclarator.zero ("gvalue", cvalinit));
709 block.add_statement (cval_decl);
711 var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("gvalue"));
713 // call Get method on property proxy
714 var cdecl = new CCodeDeclaration (node.property_type.get_cname ());
715 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
716 block.add_statement (cdecl);
718 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_call"));
719 ccall.add_argument (new CCodeIdentifier ("property_proxy"));
720 ccall.add_argument (new CCodeConstant ("\"Get\""));
721 ccall.add_argument (new CCodeConstant ("NULL"));
723 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
724 var get_iface = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_interface"));
725 get_iface.add_argument (new CCodeIdentifier ("obj"));
726 ccall.add_argument (get_iface);
728 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
729 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (node.name))));
731 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
733 ccall.add_argument (new CCodeIdentifier ("G_TYPE_VALUE"));
734 ccall.add_argument (val_ptr);
736 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
738 block.add_statement (new CCodeExpressionStatement (ccall));
740 // unref property proxy
741 var prop_proxy_unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
742 prop_proxy_unref.add_argument (new CCodeIdentifier ("property_proxy"));
743 block.add_statement (new CCodeExpressionStatement (prop_proxy_unref));
745 // assign value to result variable
746 var cget_call = new CCodeFunctionCall (new CCodeIdentifier (node.property_type.data_type.get_get_value_function ()));
747 cget_call.add_argument (val_ptr);
748 var assign = new CCodeAssignment (new CCodeIdentifier ("result"), cget_call);
749 block.add_statement (new CCodeExpressionStatement (assign));
751 // return result
752 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
755 void generate_dbus_property_setter_wrapper (DynamicProperty node, CCodeBlock block) {
756 create_dbus_property_proxy (node, block);
758 // initialize GValue
759 var cvalinit = new CCodeInitializerList ();
760 cvalinit.append (new CCodeConstant ("0"));
762 var cval_decl = new CCodeDeclaration ("GValue");
763 cval_decl.add_declarator (new CCodeVariableDeclarator.zero ("gvalue", cvalinit));
764 block.add_statement (cval_decl);
766 var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("gvalue"));
768 var cinit_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init"));
769 cinit_call.add_argument (val_ptr);
770 cinit_call.add_argument (new CCodeIdentifier (node.property_type.data_type.get_type_id ()));
771 block.add_statement (new CCodeExpressionStatement (cinit_call));
773 var cset_call = new CCodeFunctionCall (new CCodeIdentifier (node.property_type.data_type.get_set_value_function ()));
774 cset_call.add_argument (val_ptr);
775 cset_call.add_argument (new CCodeIdentifier ("value"));
776 block.add_statement (new CCodeExpressionStatement (cset_call));
778 // call Set method on property proxy
779 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_call"));
780 ccall.add_argument (new CCodeIdentifier ("property_proxy"));
781 ccall.add_argument (new CCodeConstant ("\"Set\""));
782 ccall.add_argument (new CCodeConstant ("NULL"));
784 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
785 var get_iface = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_interface"));
786 get_iface.add_argument (new CCodeIdentifier ("obj"));
787 ccall.add_argument (get_iface);
789 ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRING"));
790 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (node.name))));
792 ccall.add_argument (new CCodeIdentifier ("G_TYPE_VALUE"));
793 ccall.add_argument (val_ptr);
795 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
797 ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
799 block.add_statement (new CCodeExpressionStatement (ccall));
801 // unref property proxy
802 var prop_proxy_unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
803 prop_proxy_unref.add_argument (new CCodeIdentifier ("property_proxy"));
804 block.add_statement (new CCodeExpressionStatement (prop_proxy_unref));
807 public override string get_dynamic_signal_connect_wrapper_name (DynamicSignal sig) {
808 if (sig.dynamic_type.data_type != dbus_object_type) {
809 return base.get_dynamic_signal_connect_wrapper_name (sig);
812 string connect_wrapper_name = "_%sconnect".printf (get_dynamic_signal_cname (sig));
813 var func = new CCodeFunction (connect_wrapper_name, "void");
814 func.add_parameter (new CCodeParameter ("obj", "gpointer"));
815 func.add_parameter (new CCodeParameter ("signal_name", "const char *"));
816 func.add_parameter (new CCodeParameter ("handler", "GCallback"));
817 func.add_parameter (new CCodeParameter ("data", "gpointer"));
818 var block = new CCodeBlock ();
819 generate_dbus_connect_wrapper (sig, block);
821 // append to C source file
822 cfile.add_function_declaration (func);
824 func.block = block;
825 cfile.add_function (func);
827 return connect_wrapper_name;
830 public override string get_dynamic_signal_disconnect_wrapper_name (DynamicSignal sig) {
831 if (sig.dynamic_type.data_type != dbus_object_type) {
832 return base.get_dynamic_signal_disconnect_wrapper_name (sig);
835 string disconnect_wrapper_name = "_%sdisconnect".printf (get_dynamic_signal_cname (sig));
836 var func = new CCodeFunction (disconnect_wrapper_name, "void");
837 func.add_parameter (new CCodeParameter ("obj", "gpointer"));
838 func.add_parameter (new CCodeParameter ("signal_name", "const char *"));
839 func.add_parameter (new CCodeParameter ("handler", "GCallback"));
840 func.add_parameter (new CCodeParameter ("data", "gpointer"));
841 var block = new CCodeBlock ();
842 generate_dbus_disconnect_wrapper (sig, block);
844 // append to C source file
845 cfile.add_function_declaration (func);
847 func.block = block;
848 cfile.add_function (func);
850 return disconnect_wrapper_name;
853 void generate_dbus_connect_wrapper (DynamicSignal sig, CCodeBlock block) {
854 var m = (Method) sig.handler.symbol_reference;
856 sig.accept (this);
858 // FIXME should only be done once per marshaller
859 var register_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_register_marshaller"));
860 generate_marshaller (sig.get_parameters (), sig.return_type, true);
861 register_call.add_argument (new CCodeIdentifier (get_marshaller_function (sig.get_parameters (), sig.return_type, null, true)));
862 register_call.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
864 var add_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_add_signal"));
865 add_call.add_argument (new CCodeIdentifier ("obj"));
866 add_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (sig.name))));
868 bool first = true;
869 foreach (Parameter param in m.get_parameters ()) {
870 if (first) {
871 // skip sender parameter
872 first = false;
873 continue;
876 register_call.add_argument (get_dbus_g_type (param.variable_type));
877 add_call.add_argument (get_dbus_g_type (param.variable_type));
879 register_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
880 add_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
882 block.add_statement (new CCodeExpressionStatement (register_call));
883 block.add_statement (new CCodeExpressionStatement (add_call));
885 var call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_connect_signal"));
886 call.add_argument (new CCodeIdentifier ("obj"));
887 call.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (sig.name))));
888 call.add_argument (new CCodeIdentifier ("handler"));
889 call.add_argument (new CCodeIdentifier ("data"));
890 call.add_argument (new CCodeConstant ("NULL"));
891 block.add_statement (new CCodeExpressionStatement (call));
894 void generate_dbus_disconnect_wrapper (DynamicSignal sig, CCodeBlock block) {
895 var call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_disconnect_signal"));
896 call.add_argument (new CCodeIdentifier ("obj"));
897 call.add_argument (new CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (sig.name))));
898 call.add_argument (new CCodeIdentifier ("handler"));
899 call.add_argument (new CCodeIdentifier ("data"));
900 block.add_statement (new CCodeExpressionStatement (call));
903 public override void visit_cast_expression (CastExpression expr) {
904 // handles casting DBus.Object instances to DBus interfaces
906 var type = expr.type_reference as ObjectType;
907 var call = expr.inner as MethodCall;
908 if (type == null || !(type.type_symbol is Interface)
909 || type.type_symbol.get_attribute ("DBus") == null || call == null) {
910 base.visit_cast_expression (expr);
911 return;
914 var mtype = call.call.value_type as MethodType;
915 if (mtype == null || mtype.method_symbol.get_cname () != "dbus_g_proxy_new_for_name") {
916 base.visit_cast_expression (expr);
917 return;
920 var args = call.get_argument_list ();
921 Expression connection = ((MemberAccess) call.call).inner;
922 Expression bus_name = args.get (0);
923 Expression object_path = args.get (1);
925 var ccall = new CCodeFunctionCall (new CCodeIdentifier (type.type_symbol.get_lower_case_cprefix () + "dbus_proxy_new"));
926 connection.emit (this);
927 ccall.add_argument (get_cvalue (connection));
928 bus_name.emit (this);
929 ccall.add_argument (get_cvalue (bus_name));
930 object_path.emit (this);
931 ccall.add_argument (get_cvalue (object_path));
932 set_cvalue (expr, ccall);
935 void generate_proxy_interface_init (Interface main_iface, Interface iface) {
936 // also generate proxy for prerequisites
937 foreach (var prereq in iface.get_prerequisites ()) {
938 if (prereq.data_type is Interface) {
939 generate_proxy_interface_init (main_iface, (Interface) prereq.data_type);
943 string lower_cname = main_iface.get_lower_case_cprefix () + "dbus_proxy";
945 var proxy_iface_init = new CCodeFunction (lower_cname + "_" + iface.get_lower_case_cprefix () + "_interface_init", "void");
946 proxy_iface_init.add_parameter (new CCodeParameter ("iface", iface.get_cname () + "Iface*"));
948 var iface_block = new CCodeBlock ();
950 foreach (Method m in iface.get_methods ()) {
951 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), m.vfunc_name);
952 if (is_dbus_no_reply (m)) {
953 if (m.coroutine) {
954 Report.error (m.source_reference, "No-reply DBus methods must not be async");
956 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_noreply_dbus_proxy_method (main_iface, iface, m)))));
957 } else if (!m.coroutine) {
958 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_method (main_iface, iface, m)))));
959 } else {
960 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_async_dbus_proxy_method (main_iface, iface, m)))));
961 vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), m.get_finish_vfunc_name ());
962 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_finish_dbus_proxy_method (main_iface, iface, m)))));
966 foreach (Property prop in iface.get_properties ()) {
967 if (prop.get_accessor != null) {
968 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "get_" + prop.name);
969 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_get (main_iface, iface, prop)))));
971 if (prop.set_accessor != null) {
972 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "set_" + prop.name);
973 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_set (main_iface, iface, prop)))));
977 proxy_iface_init.modifiers = CCodeModifiers.STATIC;
978 cfile.add_function_declaration (proxy_iface_init);
979 proxy_iface_init.block = iface_block;
980 cfile.add_function (proxy_iface_init);
983 string implement_interface (CCodeFunctionCall define_type, Interface main_iface, Interface iface) {
984 string result = "";
986 // also implement prerequisites
987 foreach (var prereq in iface.get_prerequisites ()) {
988 if (prereq.data_type is Interface) {
989 result += implement_interface (define_type, main_iface, (Interface) prereq.data_type);
993 result += "G_IMPLEMENT_INTERFACE (%s, %sdbus_proxy_%s_interface_init) ".printf (
994 iface.get_upper_case_cname ("TYPE_"),
995 main_iface.get_lower_case_cprefix (),
996 iface.get_lower_case_cprefix ());
997 return result;
1000 void implement_property (CCodeBlock block, Interface main_iface, Interface iface) {
1001 // also implement prerequisites
1002 foreach (var prereq in iface.get_prerequisites ()) {
1003 if (prereq.data_type is Interface) {
1004 implement_property (block, main_iface, (Interface) prereq.data_type);
1008 var gobject_class = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
1009 gobject_class.add_argument (new CCodeIdentifier ("klass"));
1011 foreach (Property prop in iface.get_properties ()) {
1012 if (!prop.is_abstract) {
1013 continue;
1016 if (!is_gobject_property (prop)) {
1017 continue;
1020 string prop_ev = "%s_dbus_proxy_%s".printf (main_iface.get_lower_case_cname (null), Symbol.camel_case_to_lower_case (prop.name)).up ();
1022 var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_override_property"));
1023 cinst.add_argument (gobject_class);
1024 cinst.add_argument (new CCodeConstant (prop_ev));
1025 cinst.add_argument (prop.get_canonical_cconstant ());
1026 block.add_statement (new CCodeExpressionStatement (cinst));
1028 prop_enum.add_value (new CCodeEnumValue (prop_ev));
1032 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
1033 base.generate_interface_declaration (iface, decl_space);
1035 string dbus_iface_name = get_dbus_name (iface);
1036 if (dbus_iface_name == null) {
1037 return;
1040 string lower_cname = iface.get_lower_case_cprefix () + "dbus_proxy";
1042 if (add_symbol_declaration (decl_space, iface, lower_cname + "_new")) {
1043 return;
1046 decl_space.add_include ("dbus/dbus-glib.h");
1048 // declare proxy_new function
1049 var proxy_new = new CCodeFunction (lower_cname + "_new", iface.get_cname () + "*");
1050 proxy_new.add_parameter (new CCodeParameter ("connection", "DBusGConnection*"));
1051 proxy_new.add_parameter (new CCodeParameter ("name", "const char*"));
1052 proxy_new.add_parameter (new CCodeParameter ("path", "const char*"));
1054 decl_space.add_function_declaration (proxy_new);
1057 public override void visit_interface (Interface iface) {
1058 base.visit_interface (iface);
1060 string dbus_iface_name = get_dbus_name (iface);
1061 if (dbus_iface_name == null) {
1062 return;
1065 // strcmp
1066 cfile.add_include ("string.h");
1068 // create proxy class
1069 string cname = iface.get_cname () + "DBusProxy";
1070 string lower_cname = iface.get_lower_case_cprefix () + "dbus_proxy";
1072 add_dbus_helpers ();
1074 cfile.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (cname), new CCodeVariableDeclarator (cname)));
1075 cfile.add_type_declaration (new CCodeTypeDefinition ("DBusGProxyClass", new CCodeVariableDeclarator (cname + "Class")));
1077 var instance_struct = new CCodeStruct ("_%s".printf (cname));
1078 instance_struct.add_field ("DBusGProxy", "parent_instance");
1079 instance_struct.add_field ("gboolean", "disposed");
1081 cfile.add_type_definition (instance_struct);
1083 var type_fun = new CCodeFunction(lower_cname + "_get_type", "GType");
1084 type_fun.attributes = "G_GNUC_CONST";
1085 cfile.add_function_declaration (type_fun);
1087 var define_type = new CCodeFunctionCall (new CCodeIdentifier ("G_DEFINE_TYPE_EXTENDED"));
1088 define_type.add_argument (new CCodeIdentifier (cname));
1089 define_type.add_argument (new CCodeIdentifier (lower_cname));
1090 define_type.add_argument (new CCodeIdentifier ("DBUS_TYPE_G_PROXY"));
1091 define_type.add_argument (new CCodeConstant ("0"));
1092 define_type.add_argument (new CCodeIdentifier (implement_interface (define_type, iface, iface)));
1094 cfile.add_type_member_definition (new CCodeExpressionStatement (define_type));
1096 // generate proxy_new function
1097 var proxy_new = new CCodeFunction (lower_cname + "_new", iface.get_cname () + "*");
1098 proxy_new.add_parameter (new CCodeParameter ("connection", "DBusGConnection*"));
1099 proxy_new.add_parameter (new CCodeParameter ("name", "const char*"));
1100 proxy_new.add_parameter (new CCodeParameter ("path", "const char*"));
1102 var new_block = new CCodeBlock ();
1104 // create proxy object
1105 var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_new"));
1106 new_call.add_argument (new CCodeFunctionCall (new CCodeIdentifier (lower_cname + "_get_type")));
1107 new_call.add_argument (new CCodeConstant ("\"connection\""));
1108 new_call.add_argument (new CCodeIdentifier ("connection"));
1109 new_call.add_argument (new CCodeConstant ("\"name\""));
1110 new_call.add_argument (new CCodeIdentifier ("name"));
1111 new_call.add_argument (new CCodeConstant ("\"path\""));
1112 new_call.add_argument (new CCodeIdentifier ("path"));
1113 new_call.add_argument (new CCodeConstant ("\"interface\""));
1114 new_call.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1115 new_call.add_argument (new CCodeConstant ("NULL"));
1117 var cdecl = new CCodeDeclaration (iface.get_cname () + "*");
1118 cdecl.add_declarator (new CCodeVariableDeclarator ("self", new_call));
1119 new_block.add_statement (cdecl);
1120 new_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("self")));
1122 proxy_new.block = new_block;
1123 cfile.add_function (proxy_new);
1125 // dbus proxy construct
1126 var proxy_construct = new CCodeFunction (lower_cname + "_construct", "GObject*");
1127 proxy_construct.add_parameter (new CCodeParameter ("gtype", "GType"));
1128 proxy_construct.add_parameter (new CCodeParameter ("n_properties", "guint"));
1129 proxy_construct.add_parameter (new CCodeParameter ("properties", "GObjectConstructParam*"));
1130 proxy_construct.modifiers = CCodeModifiers.STATIC;
1131 proxy_construct.block = new CCodeBlock ();
1133 // chain up
1134 var parent_class = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
1135 parent_class.add_argument (new CCodeIdentifier (lower_cname + "_parent_class"));
1136 var chainup = new CCodeFunctionCall (new CCodeMemberAccess.pointer (parent_class, "constructor"));
1137 chainup.add_argument (new CCodeIdentifier ("gtype"));
1138 chainup.add_argument (new CCodeIdentifier ("n_properties"));
1139 chainup.add_argument (new CCodeIdentifier ("properties"));
1141 cdecl = new CCodeDeclaration ("GObject*");
1142 cdecl.add_declarator (new CCodeVariableDeclarator ("self", chainup));
1143 proxy_construct.block.add_statement (cdecl);
1145 cdecl = new CCodeDeclaration ("DBusGConnection");
1146 cdecl.add_declarator (new CCodeVariableDeclarator ("*connection"));
1147 proxy_construct.block.add_statement (cdecl);
1149 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1150 gconnection.add_argument (new CCodeIdentifier ("self"));
1151 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1152 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("connection")));
1153 gconnection.add_argument (new CCodeConstant ("NULL"));
1154 proxy_construct.block.add_statement (new CCodeExpressionStatement (gconnection));
1156 cdecl = new CCodeDeclaration ("char*");
1157 cdecl.add_declarator (new CCodeVariableDeclarator ("path"));
1158 proxy_construct.block.add_statement (cdecl);
1160 var path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1161 path.add_argument (new CCodeIdentifier ("self"));
1162 path.add_argument (new CCodeConstant ("\"path\""));
1163 path.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("path")));
1164 path.add_argument (new CCodeConstant ("NULL"));
1165 proxy_construct.block.add_statement (new CCodeExpressionStatement (path));
1167 var raw_connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1168 raw_connection.add_argument (new CCodeIdentifier ("connection"));
1170 // add filter to handle signals from the remote object
1171 var filter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_add_filter"));
1172 filter_call.add_argument (raw_connection);
1173 filter_call.add_argument (new CCodeIdentifier (lower_cname + "_filter"));
1174 filter_call.add_argument (new CCodeIdentifier ("self"));
1175 filter_call.add_argument (new CCodeConstant ("NULL"));
1176 proxy_construct.block.add_statement (new CCodeExpressionStatement (filter_call));
1178 var filter_printf = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup_printf"));
1179 filter_printf.add_argument (new CCodeConstant ("\"type='signal',path='%s'\""));
1180 filter_printf.add_argument (new CCodeIdentifier ("path"));
1182 cdecl = new CCodeDeclaration ("char*");
1183 cdecl.add_declarator (new CCodeVariableDeclarator ("filter", filter_printf));
1184 proxy_construct.block.add_statement (cdecl);
1186 // ensure we receive signals from the remote object
1187 var match_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_bus_add_match"));
1188 match_call.add_argument (raw_connection);
1189 match_call.add_argument (new CCodeIdentifier ("filter"));
1190 match_call.add_argument (new CCodeConstant ("NULL"));
1191 proxy_construct.block.add_statement (new CCodeExpressionStatement (match_call));
1193 var connection_free = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
1194 connection_free.add_argument (new CCodeIdentifier ("connection"));
1195 proxy_construct.block.add_statement (new CCodeExpressionStatement (connection_free));
1197 var path_free = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1198 path_free.add_argument (new CCodeIdentifier ("path"));
1199 proxy_construct.block.add_statement (new CCodeExpressionStatement (path_free));
1201 var filter_free = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1202 filter_free.add_argument (new CCodeIdentifier ("filter"));
1203 proxy_construct.block.add_statement (new CCodeExpressionStatement (filter_free));
1205 proxy_construct.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("self")));
1207 cfile.add_function (proxy_construct);
1209 // dbus proxy filter function
1210 generate_proxy_filter_function (iface);
1212 // dbus proxy dispose
1213 var proxy_dispose = new CCodeFunction (lower_cname + "_dispose", "void");
1214 proxy_dispose.add_parameter (new CCodeParameter ("self", "GObject*"));
1215 proxy_dispose.modifiers = CCodeModifiers.STATIC;
1216 proxy_dispose.block = new CCodeBlock ();
1218 cdecl = new CCodeDeclaration ("DBusGConnection");
1219 cdecl.add_declarator (new CCodeVariableDeclarator ("*connection"));
1220 proxy_dispose.block.add_statement (cdecl);
1222 // return if proxy is already disposed
1223 var dispose_return_block = new CCodeBlock ();
1224 dispose_return_block.add_statement (new CCodeReturnStatement ());
1225 proxy_dispose.block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), cname + "*"), "disposed"), dispose_return_block));
1227 // mark proxy as disposed
1228 proxy_dispose.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), cname + "*"), "disposed"), new CCodeConstant ("TRUE"))));
1230 gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1231 gconnection.add_argument (new CCodeIdentifier ("self"));
1232 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1233 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("connection")));
1234 gconnection.add_argument (new CCodeConstant ("NULL"));
1235 proxy_dispose.block.add_statement (new CCodeExpressionStatement (gconnection));
1237 // remove filter
1238 filter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_remove_filter"));
1239 filter_call.add_argument (raw_connection);
1240 filter_call.add_argument (new CCodeIdentifier (lower_cname + "_filter"));
1241 filter_call.add_argument (new CCodeIdentifier ("self"));
1242 proxy_dispose.block.add_statement (new CCodeExpressionStatement (filter_call));
1244 // chain up
1245 parent_class = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
1246 parent_class.add_argument (new CCodeIdentifier (lower_cname + "_parent_class"));
1247 chainup = new CCodeFunctionCall (new CCodeMemberAccess.pointer (parent_class, "dispose"));
1248 chainup.add_argument (new CCodeIdentifier ("self"));
1249 proxy_dispose.block.add_statement (new CCodeExpressionStatement (chainup));
1251 cfile.add_function (proxy_dispose);
1253 var proxy_class_init = new CCodeFunction (lower_cname + "_class_init", "void");
1254 proxy_class_init.add_parameter (new CCodeParameter ("klass", cname + "Class*"));
1255 proxy_class_init.modifiers = CCodeModifiers.STATIC;
1256 proxy_class_init.block = new CCodeBlock ();
1257 var gobject_class = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
1258 gobject_class.add_argument (new CCodeIdentifier ("klass"));
1259 proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (gobject_class, "constructor"), new CCodeIdentifier (lower_cname + "_construct"))));
1260 proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (gobject_class, "dispose"), new CCodeIdentifier (lower_cname + "_dispose"))));
1261 proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (gobject_class, "get_property"), new CCodeIdentifier ("_vala_%s_get_property".printf (lower_cname)))));
1262 proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (gobject_class, "set_property"), new CCodeIdentifier ("_vala_%s_set_property".printf (lower_cname)))));
1263 cfile.add_function (proxy_class_init);
1265 prop_enum = new CCodeEnum ();
1266 prop_enum.add_value (new CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (lower_cname.up ())));
1268 implement_property (proxy_class_init.block, iface, iface);
1270 cfile.add_type_member_declaration (prop_enum);
1272 var proxy_instance_init = new CCodeFunction (lower_cname + "_init", "void");
1273 proxy_instance_init.add_parameter (new CCodeParameter ("self", cname + "*"));
1274 proxy_instance_init.modifiers = CCodeModifiers.STATIC;
1275 proxy_instance_init.block = new CCodeBlock ();
1276 cfile.add_function (proxy_instance_init);
1278 generate_proxy_interface_init (iface, iface);
1280 // dbus proxy get/set_property stubs
1281 // TODO add actual implementation
1282 var get_prop = new CCodeFunction ("_vala_%s_get_property".printf (lower_cname), "void");
1283 get_prop.modifiers = CCodeModifiers.STATIC;
1284 get_prop.add_parameter (new CCodeParameter ("object", "GObject *"));
1285 get_prop.add_parameter (new CCodeParameter ("property_id", "guint"));
1286 get_prop.add_parameter (new CCodeParameter ("value", "GValue *"));
1287 get_prop.add_parameter (new CCodeParameter ("pspec", "GParamSpec *"));
1288 cfile.add_function_declaration (get_prop);
1289 get_prop.block = new CCodeBlock ();
1290 cfile.add_function (get_prop);
1292 var set_prop = new CCodeFunction ("_vala_%s_set_property".printf (lower_cname), "void");
1293 set_prop.modifiers = CCodeModifiers.STATIC;
1294 set_prop.add_parameter (new CCodeParameter ("object", "GObject *"));
1295 set_prop.add_parameter (new CCodeParameter ("property_id", "guint"));
1296 set_prop.add_parameter (new CCodeParameter ("value", "const GValue *"));
1297 set_prop.add_parameter (new CCodeParameter ("pspec", "GParamSpec *"));
1298 cfile.add_function_declaration (set_prop);
1299 set_prop.block = new CCodeBlock ();
1300 cfile.add_function (set_prop);
1303 public override TypeRegisterFunction create_interface_register_function (Interface iface) {
1304 string dbus_iface_name = get_dbus_name (iface);
1305 if (dbus_iface_name == null) {
1306 return new InterfaceRegisterFunction (iface, context);
1309 return new DBusInterfaceRegisterFunction (iface, context);
1312 string generate_get_all_function (Method m) {
1313 string get_all_func = "_dbus_g_proxy_get_all";
1315 if (!add_wrapper (get_all_func)) {
1316 // wrapper already defined
1317 return get_all_func;
1320 var function = new CCodeFunction (get_all_func, "GHashTable*");
1321 function.modifiers = CCodeModifiers.STATIC;
1323 function.add_parameter (new CCodeParameter ("self", "DBusGProxy*"));
1324 function.add_parameter (new CCodeParameter ("interface_name", "const gchar*"));
1325 function.add_parameter (new CCodeParameter ("error", "GError**"));
1327 var block = new CCodeBlock ();
1328 var prefragment = new CCodeFragment ();
1329 var postfragment = new CCodeFragment ();
1331 var cdecl = new CCodeDeclaration ("DBusError");
1332 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
1333 block.add_statement (cdecl);
1335 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
1337 cdecl = new CCodeDeclaration ("DBusGConnection");
1338 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
1339 block.add_statement (cdecl);
1341 cdecl = new CCodeDeclaration ("DBusMessage");
1342 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
1343 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
1344 block.add_statement (cdecl);
1346 cdecl = new CCodeDeclaration ("DBusMessageIter");
1347 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
1348 block.add_statement (cdecl);
1350 block.add_statement (prefragment);
1352 generate_marshalling (m, "org.freedesktop.DBus.Properties", prefragment, postfragment);
1354 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1355 gconnection.add_argument (new CCodeIdentifier ("self"));
1356 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1357 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
1358 gconnection.add_argument (new CCodeConstant ("NULL"));
1359 block.add_statement (new CCodeExpressionStatement (gconnection));
1361 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
1362 dbus_error_init.add_argument (dbus_error);
1363 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
1365 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1366 connection.add_argument (new CCodeIdentifier ("_connection"));
1368 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
1369 ccall.add_argument (connection);
1370 ccall.add_argument (new CCodeIdentifier ("_message"));
1371 ccall.add_argument (get_dbus_timeout (m));
1372 ccall.add_argument (dbus_error);
1373 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
1375 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
1376 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
1377 block.add_statement (new CCodeExpressionStatement (conn_unref));
1379 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1380 message_unref.add_argument (new CCodeIdentifier ("_message"));
1381 block.add_statement (new CCodeExpressionStatement (message_unref));
1383 check_error_reply (m, block);
1384 check_reply_signature (m, block);
1386 block.add_statement (postfragment);
1388 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1389 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
1390 block.add_statement (new CCodeExpressionStatement (reply_unref));
1392 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
1394 cfile.add_function_declaration (function);
1396 function.block = block;
1397 cfile.add_function (function);
1399 return get_all_func;
1402 public override void visit_method_call (MethodCall expr) {
1403 var mtype = expr.call.value_type as MethodType;
1404 bool proxy_new_from_type = (mtype != null && mtype.method_symbol.get_cname () == "dbus_g_proxy_new_from_type");
1405 bool proxy_get_all = (mtype != null && mtype.method_symbol.get_cname () == "dbus_g_proxy_get_all");
1406 if (!proxy_new_from_type && !proxy_get_all) {
1407 base.visit_method_call (expr);
1408 return;
1411 if (proxy_get_all) {
1412 var ma = expr.call as MemberAccess;
1413 var instance = ma.inner;
1414 instance.emit (this);
1416 var args = expr.get_argument_list ();
1417 Expression interface_name = args.get (0);
1418 interface_name.emit (this);
1420 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_get_all_function (mtype.method_symbol)));
1421 ccall.add_argument (get_cvalue (instance));
1422 ccall.add_argument (get_cvalue (interface_name));
1424 current_method_inner_error = true;
1425 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
1427 set_cvalue (expr, ccall);
1428 return;
1431 var args = expr.get_argument_list ();
1432 Expression connection = ((MemberAccess) expr.call).inner;
1433 Expression bus_name = args.get (0);
1434 Expression object_path = args.get (1);
1435 Expression interface_name = args.get (2);
1436 Expression type = args.get (3);
1438 var quark_call = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
1439 quark_call.add_argument (new CCodeConstant ("\"ValaDBusInterfaceProxyType\""));
1441 var qdata_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
1442 type.emit (this);
1443 qdata_call.add_argument (get_cvalue (type));
1444 qdata_call.add_argument (quark_call);
1446 var get_type_call = new CCodeFunctionCall (new CCodeCastExpression (qdata_call, "GType (*)(void)"));
1448 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_new"));
1449 ccall.add_argument (get_type_call);
1450 ccall.add_argument (new CCodeConstant ("\"connection\""));
1451 connection.emit (this);
1452 ccall.add_argument (get_cvalue (connection));
1453 ccall.add_argument (new CCodeConstant ("\"name\""));
1454 bus_name.emit (this);
1455 ccall.add_argument (get_cvalue (bus_name));
1456 ccall.add_argument (new CCodeConstant ("\"path\""));
1457 object_path.emit (this);
1458 ccall.add_argument (get_cvalue (object_path));
1459 ccall.add_argument (new CCodeConstant ("\"interface\""));
1460 interface_name.emit (this);
1461 ccall.add_argument (get_cvalue (interface_name));
1462 ccall.add_argument (new CCodeConstant ("NULL"));
1463 set_cvalue (expr, ccall);
1466 void generate_proxy_filter_function (Interface iface) {
1467 string lower_cname = iface.get_lower_case_cprefix () + "dbus_proxy";
1469 var proxy_filter = new CCodeFunction (lower_cname + "_filter", "DBusHandlerResult");
1470 proxy_filter.add_parameter (new CCodeParameter ("connection", "DBusConnection*"));
1471 proxy_filter.add_parameter (new CCodeParameter ("message", "DBusMessage*"));
1472 proxy_filter.add_parameter (new CCodeParameter ("user_data", "void*"));
1474 var filter_block = new CCodeBlock ();
1476 // only handle signals concering the object path
1477 var path = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_path"));
1478 path.add_argument (new CCodeIdentifier ("user_data"));
1480 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_has_path"));
1481 ccheck.add_argument (new CCodeIdentifier ("message"));
1482 ccheck.add_argument (path);
1484 var object_filter_block = new CCodeBlock ();
1485 filter_block.add_statement (new CCodeIfStatement (ccheck, object_filter_block));
1487 handle_signals (iface, object_filter_block);
1489 filter_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1491 cfile.add_function_declaration (proxy_filter);
1492 proxy_filter.block = filter_block;
1493 cfile.add_function (proxy_filter);
1496 string generate_dbus_signal_handler (Signal sig, ObjectTypeSymbol sym) {
1497 string wrapper_name = "_dbus_handle_%s_%s".printf (sym.get_lower_case_cname (), sig.get_cname ());
1499 // declaration
1501 CCodeDeclaration cdecl;
1503 var function = new CCodeFunction (wrapper_name, "void");
1504 function.modifiers = CCodeModifiers.STATIC;
1506 function.add_parameter (new CCodeParameter ("self", sym.get_cname () + "*"));
1507 function.add_parameter (new CCodeParameter ("connection", "DBusConnection*"));
1508 function.add_parameter (new CCodeParameter ("message", "DBusMessage*"));
1510 var block = new CCodeBlock ();
1511 var prefragment = new CCodeFragment ();
1512 var postfragment = new CCodeFragment ();
1514 cdecl = new CCodeDeclaration ("DBusMessageIter");
1515 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
1516 block.add_statement (cdecl);
1518 block.add_statement (prefragment);
1520 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
1521 message_signature.add_argument (new CCodeIdentifier ("message"));
1522 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1523 signature_check.add_argument (message_signature);
1524 var signature_error_block = new CCodeBlock ();
1525 signature_error_block.add_statement (new CCodeReturnStatement ());
1526 prefragment.append (new CCodeIfStatement (signature_check, signature_error_block));
1528 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
1529 iter_call.add_argument (new CCodeIdentifier ("message"));
1530 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1531 prefragment.append (new CCodeExpressionStatement (iter_call));
1533 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
1534 ccall.add_argument (new CCodeIdentifier ("self"));
1535 ccall.add_argument (sig.get_canonical_cconstant ());
1537 // expected type signature for input parameters
1538 string type_signature = "";
1540 foreach (Parameter param in sig.get_parameters ()) {
1541 var owned_type = param.variable_type.copy ();
1542 owned_type.value_owned = true;
1544 cdecl = new CCodeDeclaration (owned_type.get_cname ());
1545 cdecl.add_declarator (new CCodeVariableDeclarator.zero (param.name, default_value_for_type (param.variable_type, true)));
1546 prefragment.append (cdecl);
1548 if (get_type_signature (param.variable_type) == null) {
1549 Report.error (param.variable_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (param.variable_type.to_string ()));
1550 continue;
1553 var st = param.variable_type.data_type as Struct;
1554 if (st != null && !st.is_simple_type ()) {
1555 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
1556 } else {
1557 ccall.add_argument (new CCodeIdentifier (param.name));
1560 if (param.variable_type is ArrayType) {
1561 var array_type = (ArrayType) param.variable_type;
1563 for (int dim = 1; dim <= array_type.rank; dim++) {
1564 string length_cname = get_parameter_array_length_cname (param, dim);
1566 cdecl = new CCodeDeclaration ("int");
1567 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
1568 prefragment.append (cdecl);
1569 ccall.add_argument (new CCodeIdentifier (length_cname));
1573 type_signature += get_type_signature (param.variable_type);
1575 var target = new CCodeIdentifier (param.name);
1576 var expr = read_expression (prefragment, param.variable_type, new CCodeIdentifier ("iter"), target);
1577 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1579 if (requires_destroy (owned_type)) {
1580 // keep local alive (symbol_reference is weak)
1581 var local = new LocalVariable (owned_type, param.name);
1582 var ma = new MemberAccess.simple (param.name);
1583 ma.symbol_reference = local;
1584 ma.value_type = owned_type.copy ();
1585 visit_member_access (ma);
1586 var stmt = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (param.name), owned_type, ma));
1587 postfragment.append (stmt);
1591 signature_check.add_argument (new CCodeConstant ("\"%s\"".printf (type_signature)));
1593 block.add_statement (new CCodeExpressionStatement (ccall));
1595 block.add_statement (postfragment);
1597 cdecl = new CCodeDeclaration ("DBusMessage*");
1598 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
1599 block.add_statement (cdecl);
1601 cfile.add_function_declaration (function);
1603 function.block = block;
1604 cfile.add_function (function);
1606 return wrapper_name;
1609 void handle_signal (string dbus_iface_name, string dbus_signal_name, string handler_name, CCodeBlock block, ref CCodeIfStatement clastif) {
1610 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_is_signal"));
1611 ccheck.add_argument (new CCodeIdentifier ("message"));
1612 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1613 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_signal_name)));
1615 var callblock = new CCodeBlock ();
1617 var ccall = new CCodeFunctionCall (new CCodeIdentifier (handler_name));
1618 ccall.add_argument (new CCodeIdentifier ("user_data"));
1619 ccall.add_argument (new CCodeIdentifier ("connection"));
1620 ccall.add_argument (new CCodeIdentifier ("message"));
1622 callblock.add_statement (new CCodeExpressionStatement (ccall));
1624 var cif = new CCodeIfStatement (ccheck, callblock);
1625 if (clastif == null) {
1626 block.add_statement (cif);
1627 } else {
1628 clastif.false_statement = cif;
1631 clastif = cif;
1634 void handle_signals (Interface iface, CCodeBlock block) {
1635 string dbus_iface_name = get_dbus_name (iface);
1637 CCodeIfStatement clastif = null;
1638 foreach (Signal sig in iface.get_signals ()) {
1639 if (sig.access != SymbolAccessibility.PUBLIC) {
1640 continue;
1643 handle_signal (dbus_iface_name, get_dbus_name_for_member (sig), generate_dbus_signal_handler (sig, iface), block, ref clastif);
1647 void generate_marshalling (Method m, string dbus_iface_name, CCodeFragment prefragment, CCodeFragment postfragment) {
1648 CCodeDeclaration cdecl;
1650 var no_reply = is_dbus_no_reply (m);
1652 var destination = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_bus_name"));
1653 destination.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
1654 var path = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_path"));
1655 path.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
1657 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_call"));
1658 msgcall.add_argument (destination);
1659 msgcall.add_argument (path);
1660 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1661 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m))));
1662 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall)));
1664 if (no_reply) {
1665 var noreplycall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_set_no_reply"));
1666 noreplycall.add_argument (new CCodeIdentifier ("_message"));
1667 noreplycall.add_argument (new CCodeConstant ("TRUE"));
1668 prefragment.append (new CCodeExpressionStatement (noreplycall));
1671 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
1672 iter_call.add_argument (new CCodeIdentifier ("_message"));
1673 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
1674 prefragment.append (new CCodeExpressionStatement (iter_call));
1676 if (!no_reply) {
1677 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
1678 iter_call.add_argument (new CCodeIdentifier ("_reply"));
1679 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
1680 postfragment.append (new CCodeExpressionStatement (iter_call));
1683 foreach (Parameter param in m.get_parameters ()) {
1684 if (param.direction == ParameterDirection.IN) {
1685 if (param.variable_type.data_type != null
1686 && param.variable_type.data_type.get_full_name () == "DBus.BusName") {
1687 // ignore BusName sender parameters
1688 continue;
1690 CCodeExpression expr = new CCodeIdentifier (param.name);
1691 if (param.variable_type.is_real_struct_type ()) {
1692 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
1694 write_expression (prefragment, param.variable_type, new CCodeIdentifier ("_iter"), expr);
1695 } else {
1696 if (no_reply) {
1697 Report.error (param.source_reference, "No-reply DBus methods must not have out parameters");
1698 break;
1700 cdecl = new CCodeDeclaration (param.variable_type.get_cname ());
1701 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + param.name));
1702 postfragment.append (cdecl);
1704 var array_type = param.variable_type as ArrayType;
1706 if (array_type != null) {
1707 for (int dim = 1; dim <= array_type.rank; dim++) {
1708 cdecl = new CCodeDeclaration ("int");
1709 cdecl.add_declarator (new CCodeVariableDeclarator ("_%s_length%d".printf (param.name, dim), new CCodeConstant ("0")));
1710 postfragment.append (cdecl);
1714 var target = new CCodeIdentifier ("_" + param.name);
1715 var expr = read_expression (postfragment, param.variable_type, new CCodeIdentifier ("_iter"), target);
1716 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1718 // TODO check that parameter is not NULL (out parameters are optional)
1719 // free value if parameter is NULL
1720 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (param.name)), target)));
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 ("%s_length%d".printf (param.name, dim))), new CCodeIdentifier ("_%s_length%d".printf (param.name, dim)))));
1732 if (!(m.return_type is VoidType)) {
1733 if (no_reply) {
1734 Report.error (m.return_type.source_reference, "No-reply DBus methods must return void");
1736 if (m.return_type.is_real_non_null_struct_type ()) {
1737 var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
1738 var expr = read_expression (postfragment, m.return_type, new CCodeIdentifier ("_iter"), target);
1739 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1740 } else {
1741 cdecl = new CCodeDeclaration (m.return_type.get_cname ());
1742 cdecl.add_declarator (new CCodeVariableDeclarator ("_result"));
1743 postfragment.append (cdecl);
1745 var array_type = m.return_type as ArrayType;
1747 if (array_type != null) {
1748 for (int dim = 1; dim <= array_type.rank; dim++) {
1749 cdecl = new CCodeDeclaration ("int");
1750 cdecl.add_declarator (new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
1751 postfragment.append (cdecl);
1755 var target = new CCodeIdentifier ("_result");
1756 var expr = read_expression (postfragment, m.return_type, new CCodeIdentifier ("_iter"), target);
1757 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1759 if (array_type != null) {
1760 for (int dim = 1; dim <= array_type.rank; dim++) {
1761 // TODO check that parameter is not NULL (out parameters are optional)
1762 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)))));
1769 void check_error_reply (Method m, CCodeBlock block) {
1770 var error_types = m.get_error_types ();
1771 if (!has_dbus_error (error_types)) {
1772 Report.error (m.source_reference, "D-Bus methods must throw DBus.Error");
1773 return;
1775 if (is_dbus_no_reply (m)) {
1776 // no-reply messages throw no error
1777 return;
1780 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
1782 var error_block = new CCodeBlock ();
1784 var cdecl = new CCodeDeclaration ("GQuark");
1785 cdecl.add_declarator (new CCodeVariableDeclarator.zero ("_edomain", new CCodeConstant ("0")));
1786 error_block.add_statement (cdecl);
1788 cdecl = new CCodeDeclaration ("gint");
1789 cdecl.add_declarator (new CCodeVariableDeclarator.zero ("_ecode", new CCodeConstant ("0")));
1790 error_block.add_statement (cdecl);
1792 generate_client_error_cases (error_block, error_types, new CCodeMemberAccess (new CCodeIdentifier ("_dbus_error"), "name"), new CCodeIdentifier ("_edomain"), new CCodeIdentifier ("_ecode"));
1794 var g_set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
1795 g_set_error.add_argument (new CCodeIdentifier ("error"));
1796 g_set_error.add_argument (new CCodeIdentifier ("_edomain"));
1797 g_set_error.add_argument (new CCodeIdentifier ("_ecode"));
1798 g_set_error.add_argument (new CCodeConstant ("\"%s\""));
1799 g_set_error.add_argument (new CCodeMemberAccess (new CCodeIdentifier ("_dbus_error"), "message"));
1800 error_block.add_statement (new CCodeExpressionStatement (g_set_error));
1802 var dbus_error_free = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_free"));
1803 dbus_error_free.add_argument (dbus_error);
1804 error_block.add_statement (new CCodeExpressionStatement (dbus_error_free));
1806 if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
1807 error_block.add_statement (new CCodeReturnStatement ());
1808 } else {
1809 error_block.add_statement (new CCodeReturnStatement (default_value_for_type (m.return_type, false)));
1812 var dbus_error_is_set = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_is_set"));
1813 dbus_error_is_set.add_argument (dbus_error);
1814 block.add_statement (new CCodeIfStatement (dbus_error_is_set, error_block));
1817 string generate_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
1818 string proxy_name = "%sdbus_proxy_%s".printf (main_iface.get_lower_case_cprefix (), m.name);
1820 string dbus_iface_name = get_dbus_name (iface);
1822 CCodeDeclaration cdecl;
1824 var function = new CCodeFunction (proxy_name);
1825 function.modifiers = CCodeModifiers.STATIC;
1827 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
1829 generate_cparameters (m, cfile, cparam_map, function);
1831 var block = new CCodeBlock ();
1832 var prefragment = new CCodeFragment ();
1833 var postfragment = new CCodeFragment ();
1835 // throw error and return if proxy is disposed
1836 var dispose_return_block = new CCodeBlock ();
1837 if (m.get_error_types ().size > 0) {
1838 var set_error_call = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
1839 set_error_call.add_argument (new CCodeIdentifier ("error"));
1840 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR"));
1841 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR_DISCONNECTED"));
1842 set_error_call.add_argument (new CCodeConstant ("\"%s\""));
1843 set_error_call.add_argument (new CCodeConstant ("\"Connection is closed\""));
1844 dispose_return_block.add_statement (new CCodeExpressionStatement (set_error_call));
1846 if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) {
1847 dispose_return_block.add_statement (new CCodeReturnStatement ());
1848 } else {
1849 dispose_return_block.add_statement (new CCodeReturnStatement (default_value_for_type (m.return_type, false)));
1851 block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), iface.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block));
1853 cdecl = new CCodeDeclaration ("DBusError");
1854 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
1855 block.add_statement (cdecl);
1857 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
1859 cdecl = new CCodeDeclaration ("DBusGConnection");
1860 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
1861 block.add_statement (cdecl);
1863 cdecl = new CCodeDeclaration ("DBusMessage");
1864 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
1865 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
1866 block.add_statement (cdecl);
1868 cdecl = new CCodeDeclaration ("DBusMessageIter");
1869 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
1870 block.add_statement (cdecl);
1872 block.add_statement (prefragment);
1874 generate_marshalling (m, dbus_iface_name, prefragment, postfragment);
1876 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1877 gconnection.add_argument (new CCodeIdentifier ("self"));
1878 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1879 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
1880 gconnection.add_argument (new CCodeConstant ("NULL"));
1881 block.add_statement (new CCodeExpressionStatement (gconnection));
1883 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
1884 dbus_error_init.add_argument (dbus_error);
1885 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
1887 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1888 connection.add_argument (new CCodeIdentifier ("_connection"));
1890 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
1891 ccall.add_argument (connection);
1892 ccall.add_argument (new CCodeIdentifier ("_message"));
1893 ccall.add_argument (get_dbus_timeout (m));
1894 ccall.add_argument (dbus_error);
1895 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
1897 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
1898 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
1899 block.add_statement (new CCodeExpressionStatement (conn_unref));
1901 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1902 message_unref.add_argument (new CCodeIdentifier ("_message"));
1903 block.add_statement (new CCodeExpressionStatement (message_unref));
1905 check_error_reply (m, block);
1906 check_reply_signature (m, block);
1908 block.add_statement (postfragment);
1910 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1911 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
1912 block.add_statement (new CCodeExpressionStatement (reply_unref));
1914 if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) {
1915 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
1918 cfile.add_function_declaration (function);
1919 function.block = block;
1920 cfile.add_function (function);
1922 return proxy_name;
1925 string generate_noreply_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
1926 string proxy_name = "%sdbus_proxy_%s".printf (main_iface.get_lower_case_cprefix (), m.name);
1928 string dbus_iface_name = get_dbus_name (iface);
1930 CCodeDeclaration cdecl;
1932 var function = new CCodeFunction (proxy_name);
1933 function.modifiers = CCodeModifiers.STATIC;
1935 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
1937 generate_cparameters (m, cfile, cparam_map, function);
1939 var block = new CCodeBlock ();
1940 var prefragment = new CCodeFragment ();
1941 var postfragment = new CCodeFragment ();
1943 // throw error and return if proxy is disposed
1944 var dispose_return_block = new CCodeBlock ();
1945 if (m.get_error_types ().size > 0) {
1946 var set_error_call = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
1947 set_error_call.add_argument (new CCodeIdentifier ("error"));
1948 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR"));
1949 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR_DISCONNECTED"));
1950 set_error_call.add_argument (new CCodeConstant ("\"%s\""));
1951 set_error_call.add_argument (new CCodeConstant ("\"Connection is closed\""));
1952 dispose_return_block.add_statement (new CCodeExpressionStatement (set_error_call));
1953 dispose_return_block.add_statement (new CCodeReturnStatement ());
1955 block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), iface.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block));
1957 cdecl = new CCodeDeclaration ("DBusGConnection");
1958 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
1959 block.add_statement (cdecl);
1961 cdecl = new CCodeDeclaration ("DBusMessage");
1962 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
1963 block.add_statement (cdecl);
1965 cdecl = new CCodeDeclaration ("DBusMessageIter");
1966 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
1967 block.add_statement (cdecl);
1969 block.add_statement (prefragment);
1971 generate_marshalling (m, dbus_iface_name, prefragment, postfragment);
1973 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
1974 gconnection.add_argument (new CCodeIdentifier ("self"));
1975 gconnection.add_argument (new CCodeConstant ("\"connection\""));
1976 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
1977 gconnection.add_argument (new CCodeConstant ("NULL"));
1978 block.add_statement (new CCodeExpressionStatement (gconnection));
1980 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1981 connection.add_argument (new CCodeIdentifier ("_connection"));
1983 var oom_return_block = new CCodeBlock ();
1984 if (m.get_error_types ().size > 0) {
1985 var set_error_call = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
1986 set_error_call.add_argument (new CCodeIdentifier ("error"));
1987 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR"));
1988 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR_NO_MEMORY"));
1989 set_error_call.add_argument (new CCodeConstant ("\"%s\""));
1990 set_error_call.add_argument (new CCodeConstant ("\"Out of memory\""));
1991 oom_return_block.add_statement (new CCodeExpressionStatement (set_error_call));
1992 oom_return_block.add_statement (new CCodeReturnStatement ());
1995 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send"));
1996 ccall.add_argument (connection);
1997 ccall.add_argument (new CCodeIdentifier ("_message"));
1998 ccall.add_argument (new CCodeConstant ("NULL"));
1999 block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, ccall), oom_return_block));
2001 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
2002 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
2003 block.add_statement (new CCodeExpressionStatement (conn_unref));
2005 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2006 message_unref.add_argument (new CCodeIdentifier ("_message"));
2007 block.add_statement (new CCodeExpressionStatement (message_unref));
2009 check_error_reply (m, block);
2011 block.add_statement (postfragment);
2013 cfile.add_function_declaration (function);
2014 function.block = block;
2015 cfile.add_function (function);
2017 return proxy_name;
2020 void generate_client_error_cases (CCodeBlock error_block, List<DataType> error_types, CCodeExpression dbus_error_name, CCodeExpression result_edomain, CCodeExpression result_ecode) {
2021 CCodeStatement if_else_if = null;
2022 CCodeIfStatement last_statement = null;
2024 foreach (DataType error_type in error_types) {
2025 var edomain = ((ErrorType) error_type).error_domain;
2027 if (edomain == null) {
2028 Report.error (error_type.source_reference, "Generic errors cannot be serialized over DBus");
2029 continue;
2032 var edomain_dbus_name = get_dbus_name (edomain);
2033 if (edomain_dbus_name == null) {
2034 Report.error (edomain.source_reference, "Errordomain must have a DBus.name annotation to be serialized over DBus");
2037 var true_block = new CCodeBlock ();
2038 true_block.suppress_newline = true;
2040 string temp_name = "_tmp%d_".printf (next_temp_var_id++);
2042 var cdecl = new CCodeDeclaration ("const char*");
2043 cdecl.add_declarator (new CCodeVariableDeclarator (temp_name));
2044 true_block.add_statement (cdecl);
2046 true_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (result_edomain, new CCodeIdentifier (edomain.get_upper_case_cname ()))));
2048 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))))));
2050 CCodeStatement inner_if_else_if = null;
2051 CCodeIfStatement inner_last_statement = null;
2052 foreach (ErrorCode ecode in edomain.get_codes ()) {
2053 var inner_true_block = new CCodeBlock ();
2054 inner_true_block.suppress_newline = true;
2055 inner_true_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (result_ecode, new CCodeIdentifier (ecode.get_cname ()))));
2057 var ecode_dbus_name = get_dbus_name (ecode);
2058 if (ecode_dbus_name == null) {
2059 ecode_dbus_name = Symbol.lower_case_to_camel_case (ecode.name.down ());
2062 var string_comparison = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
2063 string_comparison.add_argument (new CCodeIdentifier (temp_name));
2064 string_comparison.add_argument (new CCodeConstant ("\"%s\"".printf (ecode_dbus_name)));
2065 var stmt = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, string_comparison, new CCodeConstant ("0")), inner_true_block);
2067 if (inner_last_statement != null) {
2068 inner_last_statement.false_statement = stmt;
2069 } else {
2070 inner_if_else_if = stmt;
2072 inner_last_statement = stmt;
2074 true_block.add_statement (inner_if_else_if);
2076 var string_comparison = new CCodeFunctionCall (new CCodeIdentifier ("strstr"));
2077 string_comparison.add_argument (dbus_error_name);
2078 string_comparison.add_argument (new CCodeConstant ("\"%s\"".printf (edomain_dbus_name)));
2079 var stmt = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, string_comparison, dbus_error_name), true_block);
2081 if (last_statement != null) {
2082 last_statement.false_statement = stmt;
2083 } else {
2084 if_else_if = stmt;
2086 last_statement = stmt;
2088 error_block.add_statement (if_else_if);
2091 string generate_async_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
2092 string proxy_name = "%sdbus_proxy_%s_async".printf (main_iface.get_lower_case_cprefix (), m.name);
2094 string dbus_iface_name = get_dbus_name (iface);
2096 CCodeDeclaration cdecl;
2099 // generate data struct
2101 string dataname = "%sDBusProxy%sData".printf (iface.get_cname (), Symbol.lower_case_to_camel_case (m.name));
2102 var datastruct = new CCodeStruct ("_" + dataname);
2104 datastruct.add_field ("GAsyncReadyCallback", "_callback_");
2105 datastruct.add_field ("gpointer", "_user_data_");
2106 datastruct.add_field ("DBusPendingCall*", "pending");
2108 cfile.add_type_definition (datastruct);
2109 cfile.add_type_declaration (new CCodeTypeDefinition ("struct _" + dataname, new CCodeVariableDeclarator (dataname)));
2112 // generate async function
2114 var function = new CCodeFunction (proxy_name, "void");
2115 function.modifiers = CCodeModifiers.STATIC;
2117 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
2119 cparam_map.set (get_param_pos (-1), new CCodeParameter ("_callback_", "GAsyncReadyCallback"));
2120 cparam_map.set (get_param_pos (-0.9), new CCodeParameter ("_user_data_", "gpointer"));
2122 generate_cparameters (m, cfile, cparam_map, function, null, null, null, 1);
2124 var block = new CCodeBlock ();
2125 var prefragment = new CCodeFragment ();
2126 var postfragment = new CCodeFragment ();
2128 cdecl = new CCodeDeclaration ("DBusGConnection");
2129 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
2130 block.add_statement (cdecl);
2132 cdecl = new CCodeDeclaration ("DBusMessage");
2133 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
2134 block.add_statement (cdecl);
2136 cdecl = new CCodeDeclaration ("DBusPendingCall");
2137 cdecl.add_declarator (new CCodeVariableDeclarator ("*_pending"));
2138 block.add_statement (cdecl);
2140 cdecl = new CCodeDeclaration ("DBusMessageIter");
2141 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
2142 block.add_statement (cdecl);
2144 block.add_statement (prefragment);
2146 generate_marshalling (m, dbus_iface_name, prefragment, postfragment);
2148 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
2149 gconnection.add_argument (new CCodeIdentifier ("self"));
2150 gconnection.add_argument (new CCodeConstant ("\"connection\""));
2151 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
2152 gconnection.add_argument (new CCodeConstant ("NULL"));
2153 block.add_statement (new CCodeExpressionStatement (gconnection));
2155 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
2156 connection.add_argument (new CCodeIdentifier ("_connection"));
2158 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply"));
2159 ccall.add_argument (connection);
2160 ccall.add_argument (new CCodeIdentifier ("_message"));
2161 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_pending")));
2162 ccall.add_argument (get_dbus_timeout (m));
2163 block.add_statement (new CCodeExpressionStatement (ccall));
2165 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
2166 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
2167 block.add_statement (new CCodeExpressionStatement (conn_unref));
2169 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2170 message_unref.add_argument (new CCodeIdentifier ("_message"));
2171 block.add_statement (new CCodeExpressionStatement (message_unref));
2173 var dataalloc = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
2174 dataalloc.add_argument (new CCodeIdentifier (dataname));
2176 var datadecl = new CCodeDeclaration (dataname + "*");
2177 datadecl.add_declarator (new CCodeVariableDeclarator ("_data_"));
2178 block.add_statement (datadecl);
2179 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_data_"), dataalloc)));
2181 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_callback_"), new CCodeIdentifier ("_callback_"))));
2182 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_user_data_"), new CCodeIdentifier ("_user_data_"))));
2183 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "pending"), new CCodeIdentifier ("_pending"))));
2185 var pending = new CCodeFunctionCall (new CCodeIdentifier ("dbus_pending_call_set_notify"));
2186 pending.add_argument (new CCodeIdentifier ("_pending"));
2187 pending.add_argument (new CCodeIdentifier ("%sdbus_proxy_%s_ready".printf (iface.get_lower_case_cprefix (), m.name)));
2188 pending.add_argument (new CCodeIdentifier ("_data_"));
2189 pending.add_argument (new CCodeConstant ("NULL"));
2190 block.add_statement (new CCodeExpressionStatement (pending));
2192 cfile.add_function_declaration (function);
2193 function.block = block;
2194 cfile.add_function (function);
2197 // generate ready function
2199 function = new CCodeFunction ("%sdbus_proxy_%s_ready".printf (iface.get_lower_case_cprefix (), m.name), "void");
2200 function.modifiers = CCodeModifiers.STATIC;
2202 function.add_parameter (new CCodeParameter ("pending", "DBusPendingCall*"));
2203 function.add_parameter (new CCodeParameter ("user_data", "void*"));
2205 block = new CCodeBlock ();
2207 datadecl = new CCodeDeclaration (dataname + "*");
2208 datadecl.add_declarator (new CCodeVariableDeclarator ("_data_"));
2209 block.add_statement (datadecl);
2210 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_data_"), new CCodeIdentifier ("user_data"))));
2212 // complete async call by invoking callback
2213 var obj_decl = new CCodeDeclaration ("GObject *");
2214 obj_decl.add_declarator (new CCodeVariableDeclarator ("_obj_"));
2215 block.add_statement (obj_decl);
2217 var object_creation = new CCodeFunctionCall (new CCodeIdentifier ("g_object_newv"));
2218 object_creation.add_argument (new CCodeConstant ("G_TYPE_OBJECT"));
2219 object_creation.add_argument (new CCodeConstant ("0"));
2220 object_creation.add_argument (new CCodeConstant ("NULL"));
2221 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_obj_"), object_creation)));
2223 var async_result_decl = new CCodeDeclaration ("GSimpleAsyncResult *");
2224 async_result_decl.add_declarator (new CCodeVariableDeclarator ("_res_"));
2225 block.add_statement (async_result_decl);
2227 var async_result_creation = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_new"));
2228 async_result_creation.add_argument (new CCodeIdentifier ("_obj_"));
2229 async_result_creation.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_callback_"));
2230 async_result_creation.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_user_data_"));
2231 async_result_creation.add_argument (new CCodeIdentifier ("_data_"));
2232 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_res_"), async_result_creation)));
2234 var completecall = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete"));
2235 completecall.add_argument (new CCodeIdentifier ("_res_"));
2236 block.add_statement (new CCodeExpressionStatement (completecall));
2238 var obj_free = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
2239 obj_free.add_argument (new CCodeIdentifier ("_obj_"));
2240 block.add_statement (new CCodeExpressionStatement (obj_free));
2242 var async_result_free = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
2243 async_result_free.add_argument (new CCodeIdentifier ("_res_"));
2244 block.add_statement (new CCodeExpressionStatement (async_result_free));
2246 var datafree = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
2247 datafree.add_argument (new CCodeIdentifier (dataname));
2248 datafree.add_argument (new CCodeIdentifier ("_data_"));
2249 block.add_statement (new CCodeExpressionStatement (datafree));
2251 var pendingfree = new CCodeFunctionCall (new CCodeIdentifier ("dbus_pending_call_unref"));
2252 pendingfree.add_argument (new CCodeIdentifier ("pending"));
2253 block.add_statement (new CCodeExpressionStatement (pendingfree));
2255 cfile.add_function_declaration (function);
2256 function.block = block;
2257 cfile.add_function (function);
2260 return proxy_name;
2263 CCodeConstant get_reply_signature (Method m) {
2264 // expected type signature for output parameters
2265 string type_signature = "";
2267 foreach (Parameter param in m.get_parameters ()) {
2268 if (param.direction == ParameterDirection.OUT) {
2269 type_signature += get_type_signature (param.variable_type);
2273 if (!(m.return_type is VoidType)) {
2274 type_signature += get_type_signature (m.return_type);
2277 return (new CCodeConstant ("\"%s\"".printf (type_signature)));
2280 void check_reply_signature (Method m, CCodeBlock block) {
2281 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2282 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2284 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
2285 message_signature.add_argument (new CCodeIdentifier ("_reply"));
2287 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
2288 signature_check.add_argument (message_signature);
2289 signature_check.add_argument (get_reply_signature (m));
2291 var signature_error_block = new CCodeBlock ();
2292 var set_error_call = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
2293 set_error_call.add_argument (new CCodeIdentifier ("error"));
2294 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR"));
2295 set_error_call.add_argument (new CCodeIdentifier ("DBUS_GERROR_INVALID_SIGNATURE"));
2296 set_error_call.add_argument (new CCodeConstant ("\"Invalid signature, expected \\\"%s\\\", got \\\"%s\\\"\""));
2297 set_error_call.add_argument (get_reply_signature (m));
2298 set_error_call.add_argument (message_signature);
2299 signature_error_block.add_statement (new CCodeExpressionStatement (set_error_call));
2300 signature_error_block.add_statement (new CCodeExpressionStatement (reply_unref));
2301 signature_error_block.add_statement (new CCodeReturnStatement (default_value_for_type (m.return_type, false)));
2303 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
2306 string generate_finish_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
2307 string proxy_name = "%sdbus_proxy_%s_finish".printf (main_iface.get_lower_case_cprefix (), m.name);
2309 string dbus_iface_name = get_dbus_name (iface);
2311 CCodeDeclaration cdecl;
2313 var function = new CCodeFunction (proxy_name);
2314 function.modifiers = CCodeModifiers.STATIC;
2316 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
2318 cparam_map.set (get_param_pos (0.1), new CCodeParameter ("_res_", "GAsyncResult*"));
2320 generate_cparameters (m, cfile, cparam_map, function, null, null, null, 2);
2322 var block = new CCodeBlock ();
2323 var prefragment = new CCodeFragment ();
2324 var postfragment = new CCodeFragment ();
2326 string dataname = "%sDBusProxy%sData".printf (iface.get_cname (), Symbol.lower_case_to_camel_case (m.name));
2327 cdecl = new CCodeDeclaration (dataname + "*");
2328 cdecl.add_declarator (new CCodeVariableDeclarator ("_data_"));
2329 block.add_statement (cdecl);
2331 cdecl = new CCodeDeclaration ("DBusError");
2332 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
2333 block.add_statement (cdecl);
2335 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
2337 cdecl = new CCodeDeclaration ("DBusMessage");
2338 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
2339 block.add_statement (cdecl);
2341 cdecl = new CCodeDeclaration ("DBusMessageIter");
2342 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
2343 block.add_statement (cdecl);
2345 var get_source_tag = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_get_source_tag"));
2346 get_source_tag.add_argument (new CCodeCastExpression (new CCodeIdentifier ("_res_"), "GSimpleAsyncResult *"));
2347 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_data_"), get_source_tag)));
2349 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
2350 dbus_error_init.add_argument (dbus_error);
2351 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
2353 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_pending_call_steal_reply"));
2354 ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "pending"));
2355 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
2357 var set_error_from_message = new CCodeFunctionCall (new CCodeIdentifier ("dbus_set_error_from_message"));
2358 set_error_from_message.add_argument (dbus_error);
2359 set_error_from_message.add_argument (new CCodeIdentifier ("_reply"));
2360 block.add_statement (new CCodeExpressionStatement (set_error_from_message));
2362 check_error_reply (m, block);
2363 check_reply_signature (m, block);
2365 generate_marshalling (m, dbus_iface_name, prefragment, postfragment);
2367 block.add_statement (postfragment);
2369 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2370 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2371 block.add_statement (new CCodeExpressionStatement (reply_unref));
2373 if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) {
2374 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
2377 cfile.add_function_declaration (function);
2378 function.block = block;
2379 cfile.add_function (function);
2381 return proxy_name;
2384 void check_property_error_reply (PropertyAccessor acc, CCodeBlock block) {
2385 var dbus_error = new CCodeIdentifier ("_dbus_error");
2386 var dbus_error_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, dbus_error);
2388 var error_block = new CCodeBlock ();
2390 var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
2391 ccritical.add_argument (new CCodeConstant ("\"file %s: line %d: uncaught error: %s (%s)\""));
2392 ccritical.add_argument (new CCodeConstant ("__FILE__"));
2393 ccritical.add_argument (new CCodeConstant ("__LINE__"));
2394 ccritical.add_argument (new CCodeMemberAccess (dbus_error, "message"));
2395 ccritical.add_argument (new CCodeMemberAccess (dbus_error, "name"));
2397 error_block.add_statement (new CCodeExpressionStatement (ccritical));
2399 var dbus_error_free = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_free"));
2400 dbus_error_free.add_argument (dbus_error_ptr);
2401 error_block.add_statement (new CCodeExpressionStatement (dbus_error_free));
2403 if (acc.readable && !acc.value_type.is_real_non_null_struct_type ()) {
2404 error_block.add_statement (new CCodeReturnStatement (default_value_for_type (acc.value_type, false)));
2405 } else {
2406 error_block.add_statement (new CCodeReturnStatement ());
2409 var dbus_error_is_set = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_is_set"));
2410 dbus_error_is_set.add_argument (dbus_error_ptr);
2411 block.add_statement (new CCodeIfStatement (dbus_error_is_set, error_block));
2414 CCodeConstant get_property_reply_signature (PropertyAccessor acc) {
2415 if (acc.readable) {
2416 return new CCodeConstant ("\"v\"");
2417 } else {
2418 return new CCodeConstant ("\"\"");
2422 CCodeConstant get_property_inner_signature (PropertyAccessor acc) {
2423 return new CCodeConstant ("\"%s\"".printf (get_type_signature (acc.value_type)));
2426 void check_property_reply_signature (PropertyAccessor acc, CCodeBlock block) {
2427 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2428 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2430 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
2431 message_signature.add_argument (new CCodeIdentifier ("_reply"));
2433 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
2434 signature_check.add_argument (message_signature);
2435 signature_check.add_argument (get_property_reply_signature (acc));
2437 var signature_error_block = new CCodeBlock ();
2439 var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
2440 ccritical.add_argument (new CCodeConstant ("\"file %s: line %d: Invalid signature, expected \\\"%s\\\", got \\\"%s\\\"\""));
2441 ccritical.add_argument (new CCodeConstant ("__FILE__"));
2442 ccritical.add_argument (new CCodeConstant ("__LINE__"));
2443 ccritical.add_argument (get_property_reply_signature (acc));
2444 ccritical.add_argument (message_signature);
2446 signature_error_block.add_statement (new CCodeExpressionStatement (ccritical));
2447 signature_error_block.add_statement (new CCodeExpressionStatement (reply_unref));
2449 if (acc.readable && !acc.value_type.is_real_non_null_struct_type ()) {
2450 signature_error_block.add_statement (new CCodeReturnStatement (default_value_for_type (acc.value_type, false)));
2451 } else {
2452 signature_error_block.add_statement (new CCodeReturnStatement ());
2455 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
2458 void check_property_inner_signature (PropertyAccessor acc, CCodeFragment fragment) {
2459 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2460 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2462 var iter_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_get_signature"));
2463 iter_signature.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter")));
2465 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
2466 signature_check.add_argument (iter_signature);
2467 signature_check.add_argument (get_property_inner_signature (acc));
2469 var signature_error_block = new CCodeBlock ();
2471 var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
2472 ccritical.add_argument (new CCodeConstant ("\"file %s: line %d: Invalid signature, expected \\\"%s\\\", got \\\"%s\\\"\""));
2473 ccritical.add_argument (new CCodeConstant ("__FILE__"));
2474 ccritical.add_argument (new CCodeConstant ("__LINE__"));
2475 ccritical.add_argument (get_property_inner_signature (acc));
2476 ccritical.add_argument (iter_signature);
2478 signature_error_block.add_statement (new CCodeExpressionStatement (ccritical));
2479 signature_error_block.add_statement (new CCodeExpressionStatement (reply_unref));
2481 if (!acc.value_type.is_real_non_null_struct_type ()) {
2482 signature_error_block.add_statement (new CCodeReturnStatement (default_value_for_type (acc.value_type, false)));
2483 } else {
2484 signature_error_block.add_statement (new CCodeReturnStatement ());
2487 fragment.append (new CCodeIfStatement (signature_check, signature_error_block));
2490 string generate_dbus_proxy_property_get (Interface main_iface, Interface iface, Property prop) {
2491 string proxy_name = "%sdbus_proxy_get_%s".printf (main_iface.get_lower_case_cprefix (), prop.name);
2493 string dbus_iface_name = get_dbus_name (iface);
2495 var owned_type = prop.get_accessor.value_type.copy ();
2496 owned_type.value_owned = true;
2497 if (owned_type.is_disposable () && !prop.get_accessor.value_type.value_owned) {
2498 Report.error (prop.get_accessor.value_type.source_reference, "Properties used in D-Bus clients require owned get accessor");
2501 var array_type = prop.get_accessor.value_type as ArrayType;
2503 CCodeDeclaration cdecl;
2505 var function = new CCodeFunction (proxy_name);
2506 function.modifiers = CCodeModifiers.STATIC;
2508 function.add_parameter (new CCodeParameter ("self", "%s*".printf (iface.get_cname ())));
2510 if (prop.property_type.is_real_non_null_struct_type ()) {
2511 function.add_parameter (new CCodeParameter ("result", "%s*".printf (prop.get_accessor.value_type.get_cname ())));
2512 } else {
2513 if (array_type != null) {
2514 for (int dim = 1; dim <= array_type.rank; dim++) {
2515 function.add_parameter (new CCodeParameter ("result_length%d".printf (dim), "int*"));
2519 function.return_type = prop.get_accessor.value_type.get_cname ();
2522 var block = new CCodeBlock ();
2523 var prefragment = new CCodeFragment ();
2524 var postfragment = new CCodeFragment ();
2526 var dispose_return_block = new CCodeBlock ();
2527 if (prop.property_type.is_real_non_null_struct_type ()) {
2528 dispose_return_block.add_statement (new CCodeReturnStatement ());
2529 } else {
2530 dispose_return_block.add_statement (new CCodeReturnStatement (default_value_for_type (prop.property_type, false)));
2532 block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), iface.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block));
2534 cdecl = new CCodeDeclaration ("DBusError");
2535 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
2536 block.add_statement (cdecl);
2538 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
2540 cdecl = new CCodeDeclaration ("DBusGConnection");
2541 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
2542 block.add_statement (cdecl);
2544 cdecl = new CCodeDeclaration ("DBusMessage");
2545 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
2546 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
2547 block.add_statement (cdecl);
2549 cdecl = new CCodeDeclaration ("DBusMessageIter");
2550 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
2551 cdecl.add_declarator (new CCodeVariableDeclarator ("_subiter"));
2552 block.add_statement (cdecl);
2554 block.add_statement (prefragment);
2556 var destination = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_bus_name"));
2557 destination.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
2558 var path = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_path"));
2559 path.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
2561 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_call"));
2562 msgcall.add_argument (destination);
2563 msgcall.add_argument (path);
2564 msgcall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties\""));
2565 msgcall.add_argument (new CCodeConstant ("\"Get\""));
2566 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall)));
2568 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
2569 iter_call.add_argument (new CCodeIdentifier ("_message"));
2570 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2571 prefragment.append (new CCodeExpressionStatement (iter_call));
2573 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
2574 iter_call.add_argument (new CCodeIdentifier ("_reply"));
2575 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2576 postfragment.append (new CCodeExpressionStatement (iter_call));
2578 // interface name
2579 write_expression (prefragment, string_type, new CCodeIdentifier ("_iter"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
2580 // property name
2581 write_expression (prefragment, string_type, new CCodeIdentifier ("_iter"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
2583 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_recurse"));
2584 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2585 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter")));
2586 postfragment.append (new CCodeExpressionStatement (iter_call));
2588 check_property_inner_signature (prop.get_accessor, postfragment);
2590 if (prop.property_type.is_real_non_null_struct_type ()) {
2591 var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
2592 var expr = read_expression (postfragment, prop.get_accessor.value_type, new CCodeIdentifier ("_subiter"), target);
2593 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
2594 } else {
2595 cdecl = new CCodeDeclaration (prop.get_accessor.value_type.get_cname ());
2596 cdecl.add_declarator (new CCodeVariableDeclarator ("_result"));
2597 postfragment.append (cdecl);
2599 if (array_type != null) {
2600 for (int dim = 1; dim <= array_type.rank; dim++) {
2601 cdecl = new CCodeDeclaration ("int");
2602 cdecl.add_declarator (new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
2603 postfragment.append (cdecl);
2607 var target = new CCodeIdentifier ("_result");
2608 var expr = read_expression (postfragment, prop.get_accessor.value_type, new CCodeIdentifier ("_subiter"), target);
2609 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
2611 if (array_type != null) {
2612 for (int dim = 1; dim <= array_type.rank; dim++) {
2613 // TODO check that parameter is not NULL (out parameters are optional)
2614 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)))));
2619 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
2620 gconnection.add_argument (new CCodeIdentifier ("self"));
2621 gconnection.add_argument (new CCodeConstant ("\"connection\""));
2622 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
2623 gconnection.add_argument (new CCodeConstant ("NULL"));
2624 block.add_statement (new CCodeExpressionStatement (gconnection));
2626 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
2627 dbus_error_init.add_argument (dbus_error);
2628 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
2630 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
2631 connection.add_argument (new CCodeIdentifier ("_connection"));
2633 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
2634 ccall.add_argument (connection);
2635 ccall.add_argument (new CCodeIdentifier ("_message"));
2636 ccall.add_argument (get_dbus_timeout (prop));
2637 ccall.add_argument (dbus_error);
2638 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
2640 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
2641 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
2642 block.add_statement (new CCodeExpressionStatement (conn_unref));
2644 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2645 message_unref.add_argument (new CCodeIdentifier ("_message"));
2646 block.add_statement (new CCodeExpressionStatement (message_unref));
2648 check_property_error_reply (prop.get_accessor, block);
2649 check_property_reply_signature (prop.get_accessor, block);
2651 block.add_statement (postfragment);
2653 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2654 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2655 block.add_statement (new CCodeExpressionStatement (reply_unref));
2657 if (prop.property_type.is_real_non_null_struct_type ()) {
2658 block.add_statement (new CCodeReturnStatement ());
2659 } else {
2660 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("_result")));
2663 cfile.add_function_declaration (function);
2664 function.block = block;
2665 cfile.add_function (function);
2667 return proxy_name;
2670 string generate_dbus_proxy_property_set (Interface main_iface, Interface iface, Property prop) {
2671 string proxy_name = "%sdbus_proxy_set_%s".printf (main_iface.get_lower_case_cprefix (), prop.name);
2673 string dbus_iface_name = get_dbus_name (iface);
2675 var array_type = prop.set_accessor.value_type as ArrayType;
2677 CCodeDeclaration cdecl;
2679 var function = new CCodeFunction (proxy_name);
2680 function.modifiers = CCodeModifiers.STATIC;
2682 function.add_parameter (new CCodeParameter ("self", "%s*".printf (iface.get_cname ())));
2684 if (prop.property_type.is_real_non_null_struct_type ()) {
2685 function.add_parameter (new CCodeParameter ("value", "%s*".printf (prop.set_accessor.value_type.get_cname ())));
2686 } else {
2687 function.add_parameter (new CCodeParameter ("value", prop.set_accessor.value_type.get_cname ()));
2689 if (array_type != null) {
2690 for (int dim = 1; dim <= array_type.rank; dim++) {
2691 function.add_parameter (new CCodeParameter ("value_length%d".printf (dim), "int"));
2696 var block = new CCodeBlock ();
2697 var prefragment = new CCodeFragment ();
2698 var postfragment = new CCodeFragment ();
2700 var dispose_return_block = new CCodeBlock ();
2701 dispose_return_block.add_statement (new CCodeReturnStatement ());
2702 block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeCastExpression (new CCodeIdentifier ("self"), iface.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block));
2704 cdecl = new CCodeDeclaration ("DBusError");
2705 cdecl.add_declarator (new CCodeVariableDeclarator ("_dbus_error"));
2706 block.add_statement (cdecl);
2708 var dbus_error = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_dbus_error"));
2710 cdecl = new CCodeDeclaration ("DBusGConnection");
2711 cdecl.add_declarator (new CCodeVariableDeclarator ("*_connection"));
2712 block.add_statement (cdecl);
2714 cdecl = new CCodeDeclaration ("DBusMessage");
2715 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
2716 cdecl.add_declarator (new CCodeVariableDeclarator ("*_reply"));
2717 block.add_statement (cdecl);
2719 cdecl = new CCodeDeclaration ("DBusMessageIter");
2720 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
2721 cdecl.add_declarator (new CCodeVariableDeclarator ("_subiter"));
2722 block.add_statement (cdecl);
2724 block.add_statement (prefragment);
2726 var destination = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_bus_name"));
2727 destination.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
2728 var path = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_get_path"));
2729 path.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "DBusGProxy*"));
2731 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_call"));
2732 msgcall.add_argument (destination);
2733 msgcall.add_argument (path);
2734 msgcall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties\""));
2735 msgcall.add_argument (new CCodeConstant ("\"Set\""));
2736 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall)));
2738 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
2739 iter_call.add_argument (new CCodeIdentifier ("_message"));
2740 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2741 prefragment.append (new CCodeExpressionStatement (iter_call));
2743 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
2744 iter_call.add_argument (new CCodeIdentifier ("_reply"));
2745 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2746 postfragment.append (new CCodeExpressionStatement (iter_call));
2748 // interface name
2749 write_expression (prefragment, string_type, new CCodeIdentifier ("_iter"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
2750 // property name
2751 write_expression (prefragment, string_type, new CCodeIdentifier ("_iter"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
2753 // property value (as variant)
2754 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
2755 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2756 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_VARIANT"));
2757 iter_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_signature (prop.property_type))));
2758 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter")));
2759 prefragment.append (new CCodeExpressionStatement (iter_call));
2761 if (prop.property_type.is_real_non_null_struct_type ()) {
2762 write_expression (prefragment, prop.set_accessor.value_type, new CCodeIdentifier ("_subiter"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("value")));
2763 } else {
2764 write_expression (prefragment, prop.set_accessor.value_type, new CCodeIdentifier ("_subiter"), new CCodeIdentifier ("value"));
2767 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
2768 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
2769 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_subiter")));
2770 prefragment.append (new CCodeExpressionStatement (iter_call));
2772 var gconnection = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get"));
2773 gconnection.add_argument (new CCodeIdentifier ("self"));
2774 gconnection.add_argument (new CCodeConstant ("\"connection\""));
2775 gconnection.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_connection")));
2776 gconnection.add_argument (new CCodeConstant ("NULL"));
2777 block.add_statement (new CCodeExpressionStatement (gconnection));
2779 var dbus_error_init = new CCodeFunctionCall (new CCodeIdentifier ("dbus_error_init"));
2780 dbus_error_init.add_argument (dbus_error);
2781 block.add_statement (new CCodeExpressionStatement (dbus_error_init));
2783 var connection = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
2784 connection.add_argument (new CCodeIdentifier ("_connection"));
2786 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
2787 ccall.add_argument (connection);
2788 ccall.add_argument (new CCodeIdentifier ("_message"));
2789 ccall.add_argument (get_dbus_timeout (prop));
2790 ccall.add_argument (dbus_error);
2791 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_reply"), ccall)));
2793 var conn_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_unref"));
2794 conn_unref.add_argument (new CCodeIdentifier ("_connection"));
2795 block.add_statement (new CCodeExpressionStatement (conn_unref));
2797 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2798 message_unref.add_argument (new CCodeIdentifier ("_message"));
2799 block.add_statement (new CCodeExpressionStatement (message_unref));
2801 check_property_error_reply (prop.set_accessor, block);
2802 check_property_reply_signature (prop.set_accessor, block);
2804 block.add_statement (postfragment);
2806 var reply_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
2807 reply_unref.add_argument (new CCodeIdentifier ("_reply"));
2808 block.add_statement (new CCodeExpressionStatement (reply_unref));
2810 cfile.add_function_declaration (function);
2811 function.block = block;
2812 cfile.add_function (function);
2814 return proxy_name;