codegen: Use temporary variable for string concatenation
[vala-lang.git] / codegen / valagdbusclientmodule.vala
blob054047ae20e7ee4310a930a7a905e614809c7be2
1 /* valagdbusclientmodule.vala
3 * Copyright (C) 2010-2011 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
21 * Philip Van Hoof <pvanhoof@gnome.org>
24 public class Vala.GDBusClientModule : GDBusModule {
25 enum CallType {
26 SYNC,
27 ASYNC,
28 FINISH,
29 NO_REPLY
32 public CCodeConstant get_dbus_timeout (Symbol symbol) {
33 int timeout = -1;
35 var dbus = symbol.get_attribute ("DBus");
36 if (dbus != null && dbus.has_argument ("timeout")) {
37 timeout = dbus.get_integer ("timeout");
38 } else if (symbol.parent_symbol != null) {
39 return get_dbus_timeout (symbol.parent_symbol);
42 return new CCodeConstant (timeout.to_string ());
45 public override void generate_dynamic_method_wrapper (DynamicMethod method) {
46 var dynamic_method = (DynamicMethod) method;
48 var func = new CCodeFunction (method.get_cname ());
49 func.modifiers = CCodeModifiers.STATIC;
51 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
53 generate_cparameters (method, cfile, cparam_map, func);
55 push_function (func);
57 if (dynamic_method.dynamic_type.data_type == dbus_proxy_type) {
58 generate_marshalling (method, CallType.SYNC, null, method.name);
59 } else {
60 Report.error (method.source_reference, "dynamic methods are not supported for `%s'".printf (dynamic_method.dynamic_type.to_string ()));
63 pop_function ();
65 cfile.add_function_declaration (func);
66 cfile.add_function (func);
69 void generate_proxy_interface_init (Interface main_iface, Interface iface) {
70 // also generate proxy for prerequisites
71 foreach (var prereq in iface.get_prerequisites ()) {
72 if (prereq.data_type is Interface) {
73 generate_proxy_interface_init (main_iface, (Interface) prereq.data_type);
77 string lower_cname = main_iface.get_lower_case_cprefix () + "proxy";
79 var proxy_iface_init = new CCodeFunction (lower_cname + "_" + iface.get_lower_case_cprefix () + "interface_init", "void");
80 proxy_iface_init.add_parameter (new CCodeParameter ("iface", iface.get_cname () + "Iface*"));
82 var iface_block = new CCodeBlock ();
84 foreach (Method m in iface.get_methods ()) {
85 if (!m.is_abstract) {
86 continue;
89 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), m.vfunc_name);
90 if (!m.coroutine) {
91 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_method (main_iface, iface, m)))));
92 } else {
93 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_async_dbus_proxy_method (main_iface, iface, m)))));
94 vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), m.get_finish_vfunc_name ());
95 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_finish_dbus_proxy_method (main_iface, iface, m)))));
99 foreach (Property prop in iface.get_properties ()) {
100 if (!prop.is_abstract) {
101 continue;
104 if (prop.get_accessor != null) {
105 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "get_" + prop.name);
106 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_get (main_iface, iface, prop)))));
108 if (prop.set_accessor != null) {
109 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "set_" + prop.name);
110 iface_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_set (main_iface, iface, prop)))));
114 proxy_iface_init.modifiers = CCodeModifiers.STATIC;
115 cfile.add_function_declaration (proxy_iface_init);
116 proxy_iface_init.block = iface_block;
117 cfile.add_function (proxy_iface_init);
120 string implement_interface (CCodeFunctionCall define_type, Interface main_iface, Interface iface) {
121 string result = "";
123 // also implement prerequisites
124 foreach (var prereq in iface.get_prerequisites ()) {
125 if (prereq.data_type is Interface) {
126 result += implement_interface (define_type, main_iface, (Interface) prereq.data_type);
130 result += "G_IMPLEMENT_INTERFACE (%s, %sproxy_%sinterface_init) ".printf (
131 iface.get_upper_case_cname ("TYPE_"),
132 main_iface.get_lower_case_cprefix (),
133 iface.get_lower_case_cprefix ());
134 return result;
137 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
138 base.generate_interface_declaration (iface, decl_space);
140 string dbus_iface_name = get_dbus_name (iface);
141 if (dbus_iface_name == null) {
142 return;
145 string get_type_name = "%sproxy_get_type".printf (iface.get_lower_case_cprefix ());
147 if (add_symbol_declaration (decl_space, iface, get_type_name)) {
148 return;
151 decl_space.add_type_declaration (new CCodeNewline ());
152 var macro = "(%s ())".printf (get_type_name);
153 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_PROXY".printf (iface.get_type_id ()), macro));
155 // declare proxy_get_type function
156 var proxy_get_type = new CCodeFunction (get_type_name, "GType");
157 proxy_get_type.attributes = "G_GNUC_CONST";
158 decl_space.add_function_declaration (proxy_get_type);
161 public override void visit_interface (Interface iface) {
162 base.visit_interface (iface);
164 string dbus_iface_name = get_dbus_name (iface);
165 if (dbus_iface_name == null) {
166 return;
169 cfile.add_include ("gio/gio.h");
171 // create proxy class
172 string cname = iface.get_cname () + "Proxy";
173 string lower_cname = iface.get_lower_case_cprefix () + "proxy";
175 cfile.add_type_declaration (new CCodeTypeDefinition ("GDBusProxy", new CCodeVariableDeclarator (cname)));
176 cfile.add_type_declaration (new CCodeTypeDefinition ("GDBusProxyClass", new CCodeVariableDeclarator (cname + "Class")));
178 var define_type = new CCodeFunctionCall (new CCodeIdentifier ("G_DEFINE_TYPE_EXTENDED"));
179 define_type.add_argument (new CCodeIdentifier (cname));
180 define_type.add_argument (new CCodeIdentifier (lower_cname));
181 define_type.add_argument (new CCodeIdentifier ("G_TYPE_DBUS_PROXY"));
182 define_type.add_argument (new CCodeConstant ("0"));
183 define_type.add_argument (new CCodeIdentifier (implement_interface (define_type, iface, iface)));
185 cfile.add_type_member_definition (new CCodeExpressionStatement (define_type));
187 var proxy_class_init = new CCodeFunction (lower_cname + "_class_init", "void");
188 proxy_class_init.add_parameter (new CCodeParameter ("klass", cname + "Class*"));
189 proxy_class_init.modifiers = CCodeModifiers.STATIC;
190 proxy_class_init.block = new CCodeBlock ();
191 var proxy_class = new CCodeFunctionCall (new CCodeIdentifier ("G_DBUS_PROXY_CLASS"));
192 proxy_class.add_argument (new CCodeIdentifier ("klass"));
193 proxy_class_init.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (proxy_class, "g_signal"), new CCodeIdentifier (lower_cname + "_g_signal"))));
194 cfile.add_function (proxy_class_init);
196 generate_signal_handler_function (iface);
198 var proxy_instance_init = new CCodeFunction (lower_cname + "_init", "void");
199 proxy_instance_init.add_parameter (new CCodeParameter ("self", cname + "*"));
200 proxy_instance_init.modifiers = CCodeModifiers.STATIC;
201 proxy_instance_init.block = new CCodeBlock ();
202 cfile.add_function (proxy_instance_init);
204 generate_proxy_interface_init (iface, iface);
207 public override void visit_method_call (MethodCall expr) {
208 var mtype = expr.call.value_type as MethodType;
209 bool bus_get_proxy_async = (mtype != null && mtype.method_symbol.get_cname () == "g_bus_get_proxy");
210 bool bus_get_proxy_sync = (mtype != null && mtype.method_symbol.get_cname () == "g_bus_get_proxy_sync");
211 bool conn_get_proxy_async = (mtype != null && mtype.method_symbol.get_cname () == "g_dbus_connection_get_proxy");
212 bool conn_get_proxy_sync = (mtype != null && mtype.method_symbol.get_cname () == "g_dbus_connection_get_proxy_sync");
213 if (!bus_get_proxy_async && !bus_get_proxy_sync && !conn_get_proxy_async && !conn_get_proxy_sync) {
214 base.visit_method_call (expr);
215 return;
218 var ma = (MemberAccess) expr.call;
219 var type_arg = ma.get_type_arguments ().get (0);
221 CCodeExpression proxy_type;
222 CCodeExpression dbus_iface_name;
224 var object_type = type_arg as ObjectType;
225 if (object_type != null) {
226 var iface = (Interface) object_type.type_symbol;
228 if (get_dbus_name (iface) == null) {
229 Report.error (expr.source_reference, "`%s' is not a D-Bus interface".printf (iface.get_full_name ()));
230 return;
233 proxy_type = new CCodeIdentifier ("%s_PROXY".printf (iface.get_type_id ()));
234 dbus_iface_name = new CCodeConstant ("\"%s\"".printf (get_dbus_name (iface)));
235 } else {
236 // use runtime type information for generic methods
238 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
239 quark.add_argument (new CCodeConstant ("\"vala-dbus-proxy-type\""));
241 var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
242 get_qdata.add_argument (get_type_id_expression (type_arg));
243 get_qdata.add_argument (quark);
245 proxy_type = new CCodeFunctionCall (new CCodeCastExpression (get_qdata, "GType (*) (void)"));
247 quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
248 quark.add_argument (new CCodeConstant ("\"vala-dbus-interface-name\""));
250 get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
251 get_qdata.add_argument (get_type_id_expression (type_arg));
252 get_qdata.add_argument (quark);
254 dbus_iface_name = get_qdata;
257 var base_arg_index = 0;
258 if (bus_get_proxy_async || bus_get_proxy_sync)
259 base_arg_index = 1;
261 var args = expr.get_argument_list ();
262 Expression name = args.get (base_arg_index + 0);
263 Expression object_path = args.get (base_arg_index + 1);
264 Expression flags = args.get (base_arg_index + 2);
265 Expression cancellable = args.get (base_arg_index + 3);
267 // method can fail
268 current_method_inner_error = true;
270 CCodeFunctionCall ccall;
271 if (bus_get_proxy_async || conn_get_proxy_async) {
272 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_async_initable_new_async"));
273 } else {
274 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_initable_new"));
276 ccall.add_argument (proxy_type);
277 if (bus_get_proxy_async || conn_get_proxy_async) {
278 // I/O priority
279 ccall.add_argument (new CCodeConstant ("0"));
281 cancellable.emit (this);
282 ccall.add_argument (get_cvalue (cancellable));
283 if (bus_get_proxy_async || conn_get_proxy_async) {
284 if (expr.is_yield_expression) {
285 // asynchronous call
286 ccall.add_argument (new CCodeIdentifier (generate_ready_function (current_method)));
287 ccall.add_argument (new CCodeIdentifier ("data"));
289 } else {
290 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
292 ccall.add_argument (new CCodeConstant ("\"g-flags\""));
293 ccall.add_argument (get_cvalue (flags));
294 ccall.add_argument (new CCodeConstant ("\"g-name\""));
295 name.emit (this);
296 ccall.add_argument (get_cvalue (name));
297 if (bus_get_proxy_async || bus_get_proxy_sync) {
298 Expression bus_type = args.get (0);
299 ccall.add_argument (new CCodeConstant ("\"g-bus-type\""));
300 bus_type.emit (this);
301 ccall.add_argument (get_cvalue (bus_type));
302 } else {
303 Expression connection = ((MemberAccess) expr.call).inner;
304 ccall.add_argument (new CCodeConstant ("\"g-connection\""));
305 connection.emit (this);
306 ccall.add_argument (get_cvalue (connection));
308 ccall.add_argument (new CCodeConstant ("\"g-object-path\""));
309 object_path.emit (this);
310 ccall.add_argument (get_cvalue (object_path));
311 ccall.add_argument (new CCodeConstant ("\"g-interface-name\""));
312 ccall.add_argument (dbus_iface_name);
313 ccall.add_argument (new CCodeConstant ("NULL"));
315 if (bus_get_proxy_async || conn_get_proxy_async) {
316 if (expr.is_yield_expression) {
317 int state = next_coroutine_state++;
319 ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ()));
320 ccode.add_expression (ccall);
321 ccode.add_return (new CCodeConstant ("FALSE"));
322 ccode.add_label ("_state_%d".printf (state));
324 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_async_initable_new_finish"));
325 ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_source_object_"));
326 // pass GAsyncResult stored in closure to finish function
327 ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_res_"));
328 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
332 var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
333 var temp_ref = get_variable_cexpression (temp_var.name);
335 emit_temp_var (temp_var);
337 ccode.add_assignment (temp_ref, ccall);
338 set_cvalue (expr, temp_ref);
341 string generate_dbus_signal_handler (Signal sig, ObjectTypeSymbol sym) {
342 string wrapper_name = "_dbus_handle_%s_%s".printf (sym.get_lower_case_cname (), sig.get_cname ());
344 var function = new CCodeFunction (wrapper_name);
345 function.modifiers = CCodeModifiers.STATIC;
346 function.add_parameter (new CCodeParameter ("self", sym.get_cname () + "*"));
347 function.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
349 push_function (function);
351 ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_arguments_iter"));
353 var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
354 iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter")));
355 iter_init.add_argument (new CCodeIdentifier ("parameters"));
356 ccode.add_expression (iter_init);
358 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
359 ccall.add_argument (new CCodeIdentifier ("self"));
360 ccall.add_argument (sig.get_canonical_cconstant ());
362 foreach (Parameter param in sig.get_parameters ()) {
363 var owned_type = param.variable_type.copy ();
364 owned_type.value_owned = true;
366 ccode.add_declaration (owned_type.get_cname (), new CCodeVariableDeclarator.zero (param.name, default_value_for_type (param.variable_type, true)));
368 var st = param.variable_type.data_type as Struct;
369 if (st != null && !st.is_simple_type ()) {
370 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
371 } else {
372 ccall.add_argument (new CCodeIdentifier (param.name));
375 if (param.variable_type is ArrayType) {
376 var array_type = (ArrayType) param.variable_type;
378 for (int dim = 1; dim <= array_type.rank; dim++) {
379 string length_cname = get_parameter_array_length_cname (param, dim);
381 ccode.add_declaration ("int", new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
382 ccall.add_argument (new CCodeIdentifier (length_cname));
386 read_expression (param.variable_type, new CCodeIdentifier ("_arguments_iter"), new CCodeIdentifier (param.name), param);
389 ccode.add_expression (ccall);
391 foreach (Parameter param in sig.get_parameters ()) {
392 var owned_type = param.variable_type.copy ();
393 owned_type.value_owned = true;
395 if (requires_destroy (owned_type)) {
396 // keep local alive (symbol_reference is weak)
397 var local = new LocalVariable (owned_type, param.name);
398 ccode.add_expression (destroy_variable (local));
402 pop_function ();
404 cfile.add_function_declaration (function);
405 cfile.add_function (function);
407 return wrapper_name;
410 void generate_signal_handler_function (ObjectTypeSymbol sym) {
411 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "proxy_g_signal", "void");
412 cfunc.add_parameter (new CCodeParameter ("proxy", "GDBusProxy*"));
413 cfunc.add_parameter (new CCodeParameter ("sender_name", "const gchar*"));
414 cfunc.add_parameter (new CCodeParameter ("signal_name", "const gchar*"));
415 cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
417 cfunc.modifiers |= CCodeModifiers.STATIC;
419 cfile.add_function_declaration (cfunc);
421 var block = new CCodeBlock ();
422 cfunc.block = block;
424 CCodeIfStatement clastif = null;
426 foreach (Signal sig in sym.get_signals ()) {
427 if (sig.access != SymbolAccessibility.PUBLIC) {
428 continue;
431 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
432 ccheck.add_argument (new CCodeIdentifier ("signal_name"));
433 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
435 var callblock = new CCodeBlock ();
437 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_signal_handler (sig, sym)));
438 ccall.add_argument (new CCodeIdentifier ("proxy"));
439 ccall.add_argument (new CCodeIdentifier ("parameters"));
441 callblock.add_statement (new CCodeExpressionStatement (ccall));
443 var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")), callblock);
444 if (clastif == null) {
445 block.add_statement (cif);
446 } else {
447 clastif.false_statement = cif;
450 clastif = cif;
453 cfile.add_function (cfunc);
456 void generate_marshalling (Method m, CallType call_type, string? iface_name, string? method_name) {
457 var gdbusproxy = new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *");
459 var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_connection"));
460 connection.add_argument (gdbusproxy);
462 bool uses_fd = dbus_method_uses_file_descriptor (m);
463 if (uses_fd) {
464 cfile.add_include ("gio/gunixfdlist.h");
467 if (call_type != CallType.FINISH) {
468 var destination = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_name"));
469 destination.add_argument (gdbusproxy);
471 var interface_name = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_interface_name"));
472 interface_name.add_argument (gdbusproxy);
474 var object_path = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_object_path"));
475 object_path.add_argument (gdbusproxy);
477 var timeout = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_default_timeout"));
478 timeout.add_argument (gdbusproxy);
480 // register errors
481 foreach (var error_type in m.get_error_types ()) {
482 var errtype = (ErrorType) error_type;
483 if (errtype.error_domain != null) {
484 ccode.add_expression (new CCodeIdentifier (errtype.error_domain.get_upper_case_cname ()));
488 // build D-Bus message
490 ccode.add_declaration ("GDBusMessage", new CCodeVariableDeclarator ("*_message"));
492 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_call"));
493 ccall.add_argument (destination);
494 ccall.add_argument (object_path);
495 if (iface_name != null) {
496 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (iface_name)));
497 } else {
498 ccall.add_argument (interface_name);
500 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (method_name)));
501 ccode.add_assignment (new CCodeIdentifier ("_message"), ccall);
503 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
504 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
506 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
507 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
508 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
509 ccode.add_expression (builder_init);
511 if (uses_fd) {
512 ccode.add_declaration ("GUnixFDList", new CCodeVariableDeclarator ("*_fd_list"));
513 ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new")));
516 CCodeExpression cancellable = new CCodeConstant ("NULL");
518 foreach (Parameter param in m.get_parameters ()) {
519 if (param.direction == ParameterDirection.IN) {
520 CCodeExpression expr = new CCodeIdentifier (param.name);
521 if (param.variable_type.is_real_struct_type ()) {
522 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
525 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
526 cancellable = expr;
527 continue;
530 if (param.variable_type is ObjectType && param.variable_type.data_type.get_full_name () == "GLib.BusName") {
531 // ignore BusName sender parameters
532 continue;
535 send_dbus_value (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param);
539 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
540 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
541 ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
543 var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body"));
544 set_body.add_argument (new CCodeIdentifier ("_message"));
545 set_body.add_argument (new CCodeIdentifier ("_arguments"));
546 ccode.add_expression (set_body);
548 if (uses_fd) {
549 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
550 ccall.add_argument (new CCodeIdentifier ("_message"));
551 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
552 ccode.add_expression (ccall);
554 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
555 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
556 ccode.add_expression (ccall);
559 // send D-Bus message
561 if (call_type == CallType.SYNC) {
562 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message_with_reply_sync"));
563 ccall.add_argument (connection);
564 ccall.add_argument (new CCodeIdentifier ("_message"));
565 ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
566 ccall.add_argument (timeout);
567 ccall.add_argument (new CCodeConstant ("NULL"));
568 ccall.add_argument (cancellable);
569 ccall.add_argument (new CCodeIdentifier ("error"));
570 ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
571 } else if (call_type == CallType.NO_REPLY) {
572 var set_flags = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_flags"));
573 set_flags.add_argument (new CCodeIdentifier ("_message"));
574 set_flags.add_argument (new CCodeConstant ("G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED"));
575 ccode.add_expression (set_flags);
577 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
578 ccall.add_argument (connection);
579 ccall.add_argument (new CCodeIdentifier ("_message"));
580 ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
581 ccall.add_argument (new CCodeConstant ("NULL"));
582 ccall.add_argument (new CCodeIdentifier ("error"));
583 ccode.add_expression (ccall);
584 } else if (call_type == CallType.ASYNC) {
585 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message_with_reply"));
586 ccall.add_argument (connection);
587 ccall.add_argument (new CCodeIdentifier ("_message"));
588 ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
589 ccall.add_argument (timeout);
590 ccall.add_argument (new CCodeConstant ("NULL"));
591 ccall.add_argument (cancellable);
593 // use wrapper as source_object wouldn't be correct otherwise
594 ccall.add_argument (new CCodeIdentifier (generate_async_callback_wrapper ()));
595 var res_wrapper = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_new"));
596 res_wrapper.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *"));
597 res_wrapper.add_argument (new CCodeIdentifier ("_callback_"));
598 res_wrapper.add_argument (new CCodeIdentifier ("_user_data_"));
599 res_wrapper.add_argument (new CCodeConstant ("NULL"));
600 ccall.add_argument (res_wrapper);
602 ccode.add_expression (ccall);
605 // free D-Bus message
607 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
608 ccall.add_argument (new CCodeIdentifier ("_message"));
609 ccode.add_expression (ccall);
610 } else {
611 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message_with_reply_finish"));
612 ccall.add_argument (connection);
614 // unwrap async result
615 var inner_res = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_get_op_res_gpointer"));
616 inner_res.add_argument (new CCodeCastExpression (new CCodeIdentifier ("_res_"), "GSimpleAsyncResult *"));
617 ccall.add_argument (inner_res);
619 ccall.add_argument (new CCodeConstant ("error"));
620 ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
623 if (call_type == CallType.SYNC || call_type == CallType.FINISH) {
624 ccode.add_declaration ("GDBusMessage", new CCodeVariableDeclarator ("*_reply_message"));
626 var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
627 unref_reply.add_argument (new CCodeIdentifier ("_reply_message"));
629 // return on io error
630 var reply_is_null = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply_message"));
631 ccode.open_if (reply_is_null);
632 return_default_value (m.return_type);
633 ccode.close ();
635 // return on remote error
636 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_to_gerror"));
637 ccall.add_argument (new CCodeIdentifier ("_reply_message"));
638 ccall.add_argument (new CCodeIdentifier ("error"));
639 ccode.open_if (ccall);
640 ccode.add_expression (unref_reply);
641 return_default_value (m.return_type);
642 ccode.close ();
644 bool has_result = !(m.return_type is VoidType);
646 if (uses_fd) {
647 ccode.add_declaration ("gint", new CCodeVariableDeclarator.zero ("_fd_index", new CCodeConstant ("0")));
650 foreach (Parameter param in m.get_parameters ()) {
651 if (param.direction == ParameterDirection.OUT) {
652 has_result = true;
656 if (has_result) {
657 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply"));
658 ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_reply_iter"));
660 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_get_body"));
661 ccall.add_argument (new CCodeIdentifier ("_reply_message"));
662 ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall);
664 var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
665 iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_iter")));
666 iter_init.add_argument (new CCodeIdentifier ("_reply"));
667 ccode.add_expression (iter_init);
669 foreach (Parameter param in m.get_parameters ()) {
670 if (param.direction == ParameterDirection.OUT) {
671 ccode.add_declaration (param.variable_type.get_cname (), new CCodeVariableDeclarator ("_" + param.name));
673 var array_type = param.variable_type as ArrayType;
675 if (array_type != null) {
676 for (int dim = 1; dim <= array_type.rank; dim++) {
677 ccode.add_declaration ("int", new CCodeVariableDeclarator ("_%s_length%d".printf (param.name, dim), new CCodeConstant ("0")));
681 var target = new CCodeIdentifier ("_" + param.name);
682 bool may_fail;
683 receive_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_message"), new CCodeIdentifier ("_reply_iter"), target, param, new CCodeIdentifier ("error"), out may_fail);
685 // TODO check that parameter is not NULL (out parameters are optional)
686 // free value if parameter is NULL
687 ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (param.name)), target);
689 if (array_type != null) {
690 for (int dim = 1; dim <= array_type.rank; dim++) {
691 // TODO check that parameter is not NULL (out parameters are optional)
692 ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("%s_length%d".printf (param.name, dim))), new CCodeIdentifier ("_%s_length%d".printf (param.name, dim)));
696 if (may_fail) {
697 ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("error"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error"))));
698 ccode.add_expression (unref_reply);
699 return_default_value (m.return_type);
700 ccode.close ();
705 if (!(m.return_type is VoidType)) {
706 if (m.return_type.is_real_non_null_struct_type ()) {
707 var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
708 receive_dbus_value (m.return_type, new CCodeIdentifier ("_reply_message"), new CCodeIdentifier ("_reply_iter"), target, m);
709 } else {
710 ccode.add_declaration (m.return_type.get_cname (), new CCodeVariableDeclarator ("_result"));
712 var array_type = m.return_type as ArrayType;
714 if (array_type != null) {
715 for (int dim = 1; dim <= array_type.rank; dim++) {
716 ccode.add_declaration ("int", new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
720 bool may_fail;
721 receive_dbus_value (m.return_type, new CCodeIdentifier ("_reply_message"), new CCodeIdentifier ("_reply_iter"), new CCodeIdentifier ("_result"), m, new CCodeIdentifier ("error"), out may_fail);
723 if (array_type != null) {
724 for (int dim = 1; dim <= array_type.rank; dim++) {
725 // TODO check that parameter is not NULL (out parameters are optional)
726 ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim)));
730 if (may_fail) {
731 ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("error"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error"))));
732 ccode.add_expression (unref_reply);
733 return_default_value (m.return_type);
734 ccode.close ();
740 ccode.add_expression (unref_reply);
742 if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) {
743 ccode.add_return (new CCodeIdentifier ("_result"));
748 string generate_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
749 string proxy_name = "%sproxy_%s".printf (main_iface.get_lower_case_cprefix (), m.name);
751 string dbus_iface_name = get_dbus_name (iface);
753 bool no_reply = is_dbus_no_reply (m);
755 var function = new CCodeFunction (proxy_name);
756 function.modifiers = CCodeModifiers.STATIC;
758 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
760 generate_cparameters (m, cfile, cparam_map, function);
762 push_function (function);
764 generate_marshalling (m, no_reply ? CallType.NO_REPLY : CallType.SYNC, dbus_iface_name, get_dbus_name_for_member (m));
766 pop_function ();
768 cfile.add_function_declaration (function);
769 cfile.add_function (function);
771 return proxy_name;
774 string generate_async_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
775 string proxy_name = "%sproxy_%s_async".printf (main_iface.get_lower_case_cprefix (), m.name);
777 string dbus_iface_name = get_dbus_name (iface);
779 var function = new CCodeFunction (proxy_name, "void");
780 function.modifiers = CCodeModifiers.STATIC;
782 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
784 cparam_map.set (get_param_pos (-1), new CCodeParameter ("_callback_", "GAsyncReadyCallback"));
785 cparam_map.set (get_param_pos (-0.9), new CCodeParameter ("_user_data_", "gpointer"));
787 generate_cparameters (m, cfile, cparam_map, function, null, null, null, 1);
789 push_function (function);
791 generate_marshalling (m, CallType.ASYNC, dbus_iface_name, get_dbus_name_for_member (m));
793 pop_function ();
795 cfile.add_function_declaration (function);
796 cfile.add_function (function);
798 return proxy_name;
801 string generate_finish_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
802 string proxy_name = "%sproxy_%s_finish".printf (main_iface.get_lower_case_cprefix (), m.name);
804 var function = new CCodeFunction (proxy_name);
805 function.modifiers = CCodeModifiers.STATIC;
807 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
809 cparam_map.set (get_param_pos (0.1), new CCodeParameter ("_res_", "GAsyncResult*"));
811 generate_cparameters (m, cfile, cparam_map, function, null, null, null, 2);
813 push_function (function);
815 generate_marshalling (m, CallType.FINISH, null, null);
817 pop_function ();
819 cfile.add_function_declaration (function);
820 cfile.add_function (function);
822 return proxy_name;
825 string generate_dbus_proxy_property_get (Interface main_iface, Interface iface, Property prop) {
826 string proxy_name = "%sdbus_proxy_get_%s".printf (main_iface.get_lower_case_cprefix (), prop.name);
828 string dbus_iface_name = get_dbus_name (iface);
830 var owned_type = prop.get_accessor.value_type.copy ();
831 owned_type.value_owned = true;
832 if (owned_type.is_disposable () && !prop.get_accessor.value_type.value_owned) {
833 Report.error (prop.get_accessor.value_type.source_reference, "Properties used in D-Bus clients require owned get accessor");
836 var array_type = prop.get_accessor.value_type as ArrayType;
838 var function = new CCodeFunction (proxy_name);
839 function.modifiers = CCodeModifiers.STATIC;
841 function.add_parameter (new CCodeParameter ("self", "%s*".printf (iface.get_cname ())));
843 if (prop.property_type.is_real_non_null_struct_type ()) {
844 function.add_parameter (new CCodeParameter ("result", "%s*".printf (prop.get_accessor.value_type.get_cname ())));
845 } else {
846 if (array_type != null) {
847 for (int dim = 1; dim <= array_type.rank; dim++) {
848 function.add_parameter (new CCodeParameter ("result_length%d".printf (dim), "int*"));
852 function.return_type = prop.get_accessor.value_type.get_cname ();
855 push_function (function);
857 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_inner_reply"));
859 // first try cached value
860 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_cached_property"));
861 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
862 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
863 ccode.add_assignment (new CCodeIdentifier ("_inner_reply"), ccall);
865 // if not successful, retrieve value via D-Bus
866 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_inner_reply")));
868 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
869 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply"));
870 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
872 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
873 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
874 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
875 ccode.add_expression (builder_init);
877 // interface name
878 write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)), null);
879 // property name
880 write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))), null);
882 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
883 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
884 ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
886 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync"));
887 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
888 ccall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties.Get\""));
889 ccall.add_argument (new CCodeIdentifier ("_arguments"));
890 ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
891 ccall.add_argument (get_dbus_timeout (prop));
892 ccall.add_argument (new CCodeConstant ("NULL"));
893 ccall.add_argument (new CCodeConstant ("NULL"));
895 ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall);
897 // return on error
898 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply")));
899 return_default_value (prop.property_type);
900 ccode.close ();
902 var get_variant = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get"));
903 get_variant.add_argument (new CCodeIdentifier ("_reply"));
904 get_variant.add_argument (new CCodeConstant ("\"(v)\""));
905 get_variant.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_inner_reply")));
906 ccode.add_expression (get_variant);
908 var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
909 unref_reply.add_argument (new CCodeIdentifier ("_reply"));
910 ccode.add_expression (unref_reply);
912 ccode.close ();
914 if (prop.property_type.is_real_non_null_struct_type ()) {
915 var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
916 var result = deserialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("_inner_reply"), target);
917 ccode.add_assignment (target, result);
918 } else {
919 ccode.add_declaration (prop.get_accessor.value_type.get_cname (), new CCodeVariableDeclarator ("_result"));
921 if (array_type != null) {
922 for (int dim = 1; dim <= array_type.rank; dim++) {
923 ccode.add_declaration ("int", new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
927 var result = deserialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("_inner_reply"), new CCodeIdentifier ("_result"));
928 ccode.add_assignment (new CCodeIdentifier ("_result"), result);
930 if (array_type != null) {
931 for (int dim = 1; dim <= array_type.rank; dim++) {
932 // TODO check that parameter is not NULL (out parameters are optional)
933 ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim)));
938 unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
939 unref_reply.add_argument (new CCodeIdentifier ("_inner_reply"));
940 ccode.add_expression (unref_reply);
942 if (prop.property_type.is_real_non_null_struct_type ()) {
943 ccode.add_return ();
944 } else {
945 ccode.add_return (new CCodeIdentifier ("_result"));
948 pop_function ();
950 cfile.add_function_declaration (function);
951 cfile.add_function (function);
953 return proxy_name;
956 string generate_dbus_proxy_property_set (Interface main_iface, Interface iface, Property prop) {
957 string proxy_name = "%sdbus_proxy_set_%s".printf (main_iface.get_lower_case_cprefix (), prop.name);
959 string dbus_iface_name = get_dbus_name (iface);
961 var array_type = prop.set_accessor.value_type as ArrayType;
963 var function = new CCodeFunction (proxy_name);
964 function.modifiers = CCodeModifiers.STATIC;
966 function.add_parameter (new CCodeParameter ("self", "%s*".printf (iface.get_cname ())));
968 if (prop.property_type.is_real_non_null_struct_type ()) {
969 function.add_parameter (new CCodeParameter ("value", "%s*".printf (prop.set_accessor.value_type.get_cname ())));
970 } else {
971 function.add_parameter (new CCodeParameter ("value", prop.set_accessor.value_type.get_cname ()));
973 if (array_type != null) {
974 for (int dim = 1; dim <= array_type.rank; dim++) {
975 function.add_parameter (new CCodeParameter ("value_length%d".printf (dim), "int"));
980 push_function (function);
982 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
983 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply"));
985 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
987 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
988 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
989 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
990 ccode.add_expression (builder_init);
992 // interface name
993 write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)), null);
994 // property name
995 write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))), null);
997 // property value (as variant)
998 var builder_open = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_open"));
999 builder_open.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1000 builder_open.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_VARIANT"));
1001 ccode.add_expression (builder_open);
1003 if (prop.property_type.is_real_non_null_struct_type ()) {
1004 write_expression (prop.set_accessor.value_type, new CCodeIdentifier ("_arguments_builder"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("value")), prop);
1005 } else {
1006 write_expression (prop.set_accessor.value_type, new CCodeIdentifier ("_arguments_builder"), new CCodeIdentifier ("value"), prop);
1009 var builder_close = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_close"));
1010 builder_close.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1011 ccode.add_expression (builder_close);
1013 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
1014 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1015 ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
1017 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync"));
1018 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
1019 ccall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties.Set\""));
1020 ccall.add_argument (new CCodeIdentifier ("_arguments"));
1021 ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
1022 ccall.add_argument (get_dbus_timeout (prop));
1023 ccall.add_argument (new CCodeConstant ("NULL"));
1024 ccall.add_argument (new CCodeConstant ("NULL"));
1026 ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall);
1028 // return on error
1029 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply")));
1030 ccode.add_return ();
1031 ccode.close ();
1033 var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
1034 unref_reply.add_argument (new CCodeIdentifier ("_reply"));
1035 ccode.add_expression (unref_reply);
1037 pop_function ();
1039 cfile.add_function_declaration (function);
1040 cfile.add_function (function);
1042 return proxy_name;
1045 public override void register_dbus_info (CCodeBlock block, ObjectTypeSymbol sym) {
1046 if (!(sym is Interface)) {
1047 return;
1050 string dbus_iface_name = get_dbus_name (sym);
1051 if (dbus_iface_name == null) {
1052 return;
1055 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1056 quark.add_argument (new CCodeConstant ("\"vala-dbus-proxy-type\""));
1058 var proxy_type = new CCodeIdentifier (sym.get_lower_case_cprefix () + "proxy_get_type");
1060 var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1061 set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (sym.get_lower_case_cname (null))));
1062 set_qdata.add_argument (quark);
1063 set_qdata.add_argument (new CCodeCastExpression (proxy_type, "void*"));
1065 block.add_statement (new CCodeExpressionStatement (set_qdata));
1067 quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1068 quark.add_argument (new CCodeConstant ("\"vala-dbus-interface-name\""));
1070 set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1071 set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (sym.get_lower_case_cname (null))));
1072 set_qdata.add_argument (quark);
1073 set_qdata.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1075 block.add_statement (new CCodeExpressionStatement (set_qdata));