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
20 * Jürg Billeter <j@bitron.ch>
21 * Philip Van Hoof <pvanhoof@gnome.org>
24 public class Vala.GDBusClientModule : GDBusModule {
32 public CCodeConstant get_dbus_timeout (Symbol symbol) {
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 func = new CCodeFunction (get_ccode_name (method));
47 func.modifiers = CCodeModifiers.STATIC;
49 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
51 generate_cparameters (method, cfile, cparam_map, func);
55 if (method.dynamic_type.type_symbol == dbus_proxy_type) {
56 generate_marshalling (method, CallType.SYNC, null, method.name, -1);
58 Report.error (method.source_reference, "dynamic methods are not supported for `%s'", method.dynamic_type.to_string ());
63 cfile.add_function_declaration (func);
64 cfile.add_function (func);
67 void generate_proxy_interface_init (Interface main_iface, Interface iface) {
68 // also generate proxy for prerequisites
69 foreach (var prereq in iface.get_prerequisites ()) {
70 if (prereq.type_symbol is Interface) {
71 generate_proxy_interface_init (main_iface, (Interface) prereq.type_symbol);
75 string lower_cname = get_ccode_lower_case_prefix (main_iface) + "proxy";
77 var proxy_iface_init = new CCodeFunction (lower_cname + "_" + get_ccode_lower_case_prefix (iface) + "interface_init", "void");
78 proxy_iface_init.add_parameter (new CCodeParameter ("iface", get_ccode_name (iface) + "Iface*"));
80 push_function (proxy_iface_init);
82 foreach (Method m in iface.get_methods ()) {
87 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), get_ccode_vfunc_name (m));
89 ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_method (main_iface, iface, m)));
91 ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_async_dbus_proxy_method (main_iface, iface, m)));
92 vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), get_ccode_finish_vfunc_name (m));
93 ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_finish_dbus_proxy_method (main_iface, iface, m)));
97 foreach (Property prop in iface.get_properties ()) {
98 if (!prop.is_abstract) {
102 if (prop.get_accessor != null) {
103 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "get_" + prop.name);
104 ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_get (main_iface, iface, prop)));
106 if (prop.set_accessor != null) {
107 var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "set_" + prop.name);
108 ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_set (main_iface, iface, prop)));
112 proxy_iface_init.modifiers = CCodeModifiers.STATIC;
114 cfile.add_function_declaration (proxy_iface_init);
115 cfile.add_function (proxy_iface_init);
118 string implement_interface (CCodeFunctionCall define_type, Interface main_iface, Interface iface) {
121 // also implement prerequisites
122 foreach (var prereq in iface.get_prerequisites ()) {
123 if (prereq.type_symbol is Interface) {
124 result += implement_interface (define_type, main_iface, (Interface) prereq.type_symbol);
128 string interface_macro;
131 interface_macro = "G_IMPLEMENT_INTERFACE_DYNAMIC";
133 interface_macro = "G_IMPLEMENT_INTERFACE";
136 result += "%s (%s, %sproxy_%sinterface_init) ".printf (
138 get_ccode_upper_case_name (iface, "TYPE_"),
139 get_ccode_lower_case_prefix (main_iface),
140 get_ccode_lower_case_prefix (iface));
144 public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
145 base.generate_interface_declaration (iface, decl_space);
147 string dbus_iface_name = get_dbus_name (iface);
148 if (dbus_iface_name == null) {
152 string get_type_name = "%sproxy_get_type".printf (get_ccode_lower_case_prefix (iface));
154 if (add_symbol_declaration (decl_space, iface, get_type_name)) {
158 decl_space.add_type_declaration (new CCodeNewline ());
159 var macro = "(%s ())".printf (get_type_name);
160 decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_PROXY".printf (get_ccode_type_id (iface)), macro));
162 // declare proxy_get_type function
163 var proxy_get_type = new CCodeFunction (get_type_name, "GType");
164 proxy_get_type.modifiers = CCodeModifiers.CONST | CCodeModifiers.EXTERN;
165 requires_vala_extern = true;
167 decl_space.add_function_declaration (proxy_get_type);
170 var proxy_register_type = new CCodeFunction ("%sproxy_register_dynamic_type".printf (get_ccode_lower_case_prefix (iface)));
171 proxy_register_type.add_parameter (new CCodeParameter ("module", "GTypeModule*"));
172 proxy_register_type.modifiers |= CCodeModifiers.EXTERN;
173 requires_vala_extern = true;
175 decl_space.add_function_declaration (proxy_register_type);
179 public override void visit_interface (Interface iface) {
180 base.visit_interface (iface);
182 string dbus_iface_name = get_dbus_name (iface);
183 if (dbus_iface_name == null) {
187 cfile.add_include ("gio/gio.h");
189 // create proxy class
190 string cname = get_ccode_name (iface) + "Proxy";
191 string lower_cname = get_ccode_lower_case_prefix (iface) + "proxy";
193 cfile.add_type_declaration (new CCodeTypeDefinition ("GDBusProxy", new CCodeVariableDeclarator (cname)));
194 cfile.add_type_declaration (new CCodeTypeDefinition ("GDBusProxyClass", new CCodeVariableDeclarator (cname + "Class")));
199 type_macro = "G_DEFINE_DYNAMIC_TYPE_EXTENDED";
201 type_macro = "G_DEFINE_TYPE_EXTENDED";
204 var define_type = new CCodeFunctionCall (new CCodeIdentifier (type_macro));
205 define_type.add_argument (new CCodeIdentifier (cname));
206 define_type.add_argument (new CCodeIdentifier (lower_cname));
207 define_type.add_argument (new CCodeIdentifier ("G_TYPE_DBUS_PROXY"));
208 define_type.add_argument (new CCodeConstant ("0"));
209 define_type.add_argument (new CCodeIdentifier (implement_interface (define_type, iface, iface)));
211 cfile.add_type_member_definition (define_type);
213 var proxy_class_init = new CCodeFunction (lower_cname + "_class_init", "void");
214 proxy_class_init.add_parameter (new CCodeParameter ("klass", cname + "Class*"));
215 proxy_class_init.modifiers = CCodeModifiers.STATIC;
216 push_function (proxy_class_init);
217 var proxy_class = new CCodeFunctionCall (new CCodeIdentifier ("G_DBUS_PROXY_CLASS"));
218 proxy_class.add_argument (new CCodeIdentifier ("klass"));
219 ccode.add_assignment (new CCodeMemberAccess.pointer (proxy_class, "g_signal"), new CCodeIdentifier (lower_cname + "_g_signal"));
221 cfile.add_function (proxy_class_init);
223 generate_signal_handler_function (iface);
226 var proxy_class_finalize = new CCodeFunction (lower_cname + "_class_finalize", "void");
227 proxy_class_finalize.add_parameter (new CCodeParameter ("klass", cname + "Class*"));
228 proxy_class_finalize.modifiers = CCodeModifiers.STATIC;
229 cfile.add_function (proxy_class_finalize);
231 var proxy_type_init = new CCodeFunction (lower_cname + "_register_dynamic_type", "void");
232 proxy_type_init.add_parameter (new CCodeParameter ("module", "GTypeModule*"));
233 push_function (proxy_type_init);
234 var call_register_type = new CCodeFunctionCall (new CCodeIdentifier (lower_cname + "_register_type"));
235 call_register_type.add_argument (new CCodeIdentifier ("module"));
236 ccode.add_expression (call_register_type);
238 cfile.add_function(proxy_type_init);
241 var proxy_instance_init = new CCodeFunction (lower_cname + "_init", "void");
242 proxy_instance_init.add_parameter (new CCodeParameter ("self", cname + "*"));
243 proxy_instance_init.modifiers = CCodeModifiers.STATIC;
244 push_function (proxy_instance_init);
246 // TODO Replaces setting of "vala-dbus-interface-info"
247 var dbus_proxy_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_DBUS_PROXY"));
248 dbus_proxy_cast.add_argument (new CCodeIdentifier ("self"));
249 var set_interface_info = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_set_interface_info"));
250 set_interface_info.add_argument (dbus_proxy_cast);
251 set_interface_info.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (iface)), "GDBusInterfaceInfo *"));
252 ccode.add_expression (set_interface_info);
255 cfile.add_function (proxy_instance_init);
257 generate_proxy_interface_init (iface, iface);
260 public override void visit_method_call (MethodCall expr) {
261 var mtype = expr.call.value_type as MethodType;
262 bool bus_get_proxy_async = (mtype != null && get_ccode_name (mtype.method_symbol) == "g_bus_get_proxy");
263 bool bus_get_proxy_sync = (mtype != null && get_ccode_name (mtype.method_symbol) == "g_bus_get_proxy_sync");
264 bool conn_get_proxy_async = (mtype != null && get_ccode_name (mtype.method_symbol) == "g_dbus_connection_get_proxy");
265 bool conn_get_proxy_sync = (mtype != null && get_ccode_name (mtype.method_symbol) == "g_dbus_connection_get_proxy_sync");
266 if (!bus_get_proxy_async && !bus_get_proxy_sync && !conn_get_proxy_async && !conn_get_proxy_sync) {
267 base.visit_method_call (expr);
271 var ma = (MemberAccess) expr.call;
272 var type_arg = ma.get_type_arguments ().get (0);
274 CCodeExpression proxy_type;
275 CCodeExpression dbus_iface_name;
277 var object_type = type_arg as ObjectType;
278 if (object_type != null) {
279 var iface = (Interface) object_type.type_symbol;
281 if (get_dbus_name (iface) == null) {
282 Report.error (expr.source_reference, "`%s' is not a D-Bus interface", iface.get_full_name ());
286 proxy_type = new CCodeIdentifier ("%s_PROXY".printf (get_ccode_type_id (iface)));
287 dbus_iface_name = new CCodeConstant ("\"%s\"".printf (get_dbus_name (iface)));
289 // use runtime type information for generic methods
291 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
292 quark.add_argument (new CCodeConstant ("\"vala-dbus-proxy-type\""));
294 var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
295 get_qdata.add_argument (get_type_id_expression (type_arg));
296 get_qdata.add_argument (quark);
298 proxy_type = new CCodeFunctionCall (new CCodeCastExpression (get_qdata, "GType (*) (void)"));
300 quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
301 quark.add_argument (new CCodeConstant ("\"vala-dbus-interface-name\""));
303 get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
304 get_qdata.add_argument (get_type_id_expression (type_arg));
305 get_qdata.add_argument (quark);
307 dbus_iface_name = get_qdata;
310 if (bus_get_proxy_async || conn_get_proxy_async) {
311 if (ma.member_name == "end" && ma.inner.symbol_reference == ma.symbol_reference) {
313 current_method_inner_error = true;
315 var args = expr.get_argument_list ();
316 Expression res = args.get (0);
318 var source_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
319 var source_ref = get_variable_cexpression (source_var.name);
320 emit_temp_var (source_var);
321 var source = new CCodeFunctionCall (new CCodeIdentifier ("g_async_result_get_source_object"));
322 source.add_argument (get_cvalue (res));
323 ccode.add_assignment (source_ref, source);
325 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_async_initable_new_finish"));
326 ccall.add_argument (new CCodeCastExpression (source_ref, "GAsyncInitable *"));
327 ccall.add_argument (get_cvalue (res));
328 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ()));
330 var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
331 var temp_ref = get_variable_cexpression (temp_var.name);
332 emit_temp_var (temp_var);
333 ccode.add_assignment (temp_ref, new CCodeCastExpression (ccall, get_ccode_name (expr.value_type)));
335 // g_async_result_get_source_object transfers ownership, unref after use
336 var unref_proxy = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
337 unref_proxy.add_argument (source_ref);
338 ccode.add_expression (unref_proxy);
340 set_cvalue (expr, temp_ref);
346 var base_arg_index = 0;
347 if (bus_get_proxy_async || bus_get_proxy_sync)
350 var args = expr.get_argument_list ();
351 Expression name = args.get (base_arg_index + 0);
352 Expression object_path = args.get (base_arg_index + 1);
353 Expression flags = args.get (base_arg_index + 2);
354 Expression cancellable = args.get (base_arg_index + 3);
357 current_method_inner_error = true;
359 CCodeFunctionCall ccall;
360 if (bus_get_proxy_async || conn_get_proxy_async) {
361 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_async_initable_new_async"));
363 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_initable_new"));
365 ccall.add_argument (proxy_type);
366 if (bus_get_proxy_async || conn_get_proxy_async) {
368 ccall.add_argument (new CCodeConstant ("0"));
370 ccall.add_argument (get_cvalue (cancellable));
371 if (bus_get_proxy_async || conn_get_proxy_async) {
372 if (expr.is_yield_expression) {
374 ccall.add_argument (new CCodeIdentifier (generate_ready_function (current_method)));
375 ccall.add_argument (new CCodeIdentifier ("_data_"));
378 Expression callback = args.get (base_arg_index + 4);
379 ccall.add_argument (get_cvalue (callback));
380 ccall.add_argument (get_delegate_target (callback));
383 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ()));
385 ccall.add_argument (new CCodeConstant ("\"g-flags\""));
386 ccall.add_argument (get_cvalue (flags));
387 ccall.add_argument (new CCodeConstant ("\"g-name\""));
388 ccall.add_argument (get_cvalue (name));
389 if (bus_get_proxy_async || bus_get_proxy_sync) {
390 Expression bus_type = args.get (0);
391 ccall.add_argument (new CCodeConstant ("\"g-bus-type\""));
392 ccall.add_argument (get_cvalue (bus_type));
394 Expression connection = ma.inner;
395 if (ma.member_name == "begin" && ma.inner.symbol_reference == ma.symbol_reference) {
396 var inner_ma = (MemberAccess) ma.inner;
397 connection = inner_ma.inner;
399 ccall.add_argument (new CCodeConstant ("\"g-connection\""));
400 ccall.add_argument (get_cvalue (connection));
402 ccall.add_argument (new CCodeConstant ("\"g-object-path\""));
403 ccall.add_argument (get_cvalue (object_path));
404 ccall.add_argument (new CCodeConstant ("\"g-interface-name\""));
405 ccall.add_argument (dbus_iface_name);
406 ccall.add_argument (new CCodeConstant ("NULL"));
408 if (bus_get_proxy_async || conn_get_proxy_async) {
409 if (expr.is_yield_expression) {
410 int state = emit_context.next_coroutine_state++;
412 ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ()));
413 ccode.add_expression (ccall);
414 ccode.add_return (new CCodeConstant ("FALSE"));
415 ccode.add_label ("_state_%d".printf (state));
417 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_async_initable_new_finish"));
418 ccall.add_argument (new CCodeCastExpression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_source_object_"), "GAsyncInitable *"));
419 // pass GAsyncResult stored in closure to finish function
420 ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_res_"));
421 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ()));
424 ccode.add_expression (ccall);
429 var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
430 var temp_ref = get_variable_cexpression (temp_var.name);
432 emit_temp_var (temp_var);
434 ccode.add_assignment (temp_ref, new CCodeCastExpression (ccall, get_ccode_name (expr.value_type)));
435 set_cvalue (expr, temp_ref);
438 string generate_dbus_signal_handler (Signal sig, ObjectTypeSymbol sym) {
439 string wrapper_name = "_dbus_handle_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig));
441 var function = new CCodeFunction (wrapper_name);
442 function.modifiers = CCodeModifiers.STATIC;
443 function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
444 function.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
446 push_function (function);
448 ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_arguments_iter"));
450 var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
451 iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter")));
452 iter_init.add_argument (new CCodeIdentifier ("parameters"));
453 ccode.add_expression (iter_init);
455 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
456 ccall.add_argument (new CCodeIdentifier ("self"));
457 ccall.add_argument (get_signal_canonical_constant (sig));
459 foreach (Parameter param in sig.get_parameters ()) {
460 var param_name = get_variable_cname (param.name);
461 var owned_type = param.variable_type.copy ();
462 owned_type.value_owned = true;
464 ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
466 unowned Struct? st = param.variable_type.type_symbol as Struct;
467 if (st != null && !st.is_simple_type ()) {
468 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param_name)));
470 ccall.add_argument (new CCodeIdentifier (param_name));
473 if (param.variable_type is ArrayType) {
474 var array_type = (ArrayType) param.variable_type;
475 var length_ctype = get_ccode_array_length_type (array_type);
477 for (int dim = 1; dim <= array_type.rank; dim++) {
478 string length_cname = get_variable_array_length_cname (param, dim);
480 ccode.add_declaration (length_ctype, new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
481 ccall.add_argument (new CCodeIdentifier (length_cname));
485 read_expression (param.variable_type, new CCodeIdentifier ("_arguments_iter"), new CCodeIdentifier (param_name), param);
488 ccode.add_expression (ccall);
490 foreach (Parameter param in sig.get_parameters ()) {
491 var owned_type = param.variable_type.copy ();
492 owned_type.value_owned = true;
494 if (requires_destroy (owned_type)) {
495 // keep local alive (symbol_reference is weak)
496 var local = new LocalVariable (owned_type, param.name);
497 ccode.add_expression (destroy_local (local));
503 cfile.add_function_declaration (function);
504 cfile.add_function (function);
509 void generate_signal_handler_function (ObjectTypeSymbol sym) {
510 var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "proxy_g_signal", "void");
511 cfunc.add_parameter (new CCodeParameter ("proxy", "GDBusProxy*"));
512 cfunc.add_parameter (new CCodeParameter ("sender_name", "const gchar*"));
513 cfunc.add_parameter (new CCodeParameter ("signal_name", "const gchar*"));
514 cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
516 cfunc.modifiers |= CCodeModifiers.STATIC;
518 cfile.add_function_declaration (cfunc);
520 push_function (cfunc);
524 foreach (Signal sig in sym.get_signals ()) {
525 if (sig.access != SymbolAccessibility.PUBLIC) {
529 cfile.add_include ("string.h");
531 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
532 ccheck.add_argument (new CCodeIdentifier ("signal_name"));
533 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
535 var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
537 ccode.open_if (cond);
540 ccode.else_if (cond);
543 var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_signal_handler (sig, sym)));
544 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("proxy"), get_ccode_name (sym) + "*"));
545 ccall.add_argument (new CCodeIdentifier ("parameters"));
547 ccode.add_expression (ccall);
555 cfile.add_function (cfunc);
558 void generate_marshalling (Method m, CallType call_type, string? iface_name, string? method_name, int method_timeout) {
559 var gdbusproxy = new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *");
561 var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_connection"));
562 connection.add_argument (gdbusproxy);
564 bool uses_fd = dbus_method_uses_file_descriptor (m);
566 cfile.add_include ("gio/gunixfdlist.h");
567 ccode.add_declaration ("GUnixFDList*", new CCodeVariableDeclarator ("_fd_list"));
570 bool has_error_argument = m.tree_can_fail;
571 CCodeExpression error_argument;
572 if (has_error_argument) {
573 error_argument = new CCodeIdentifier ("error");
575 error_argument = new CCodeConstant ("NULL");
578 if (call_type != CallType.FINISH) {
579 var destination = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_name"));
580 destination.add_argument (gdbusproxy);
582 var interface_name = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_interface_name"));
583 interface_name.add_argument (gdbusproxy);
585 var object_path = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_object_path"));
586 object_path.add_argument (gdbusproxy);
588 CCodeExpression timeout;
589 if (method_timeout <= 0) {
590 timeout = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_default_timeout"));
591 ((CCodeFunctionCall) timeout).add_argument (gdbusproxy);
593 timeout = new CCodeConstant ("%d".printf (method_timeout));
597 var error_types = new ArrayList<DataType> ();
598 m.get_error_types (error_types);
599 foreach (var error_type in error_types) {
600 var errtype = (ErrorType) error_type;
601 if (errtype.error_domain != null) {
602 ccode.add_expression (new CCodeIdentifier (get_ccode_upper_case_name (errtype.error_domain)));
606 // build D-Bus message
608 ccode.add_declaration ("GDBusMessage", new CCodeVariableDeclarator ("*_message"));
610 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_call"));
611 ccall.add_argument (destination);
612 ccall.add_argument (object_path);
613 if (iface_name != null) {
614 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (iface_name)));
616 ccall.add_argument (interface_name);
618 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (method_name)));
619 ccode.add_assignment (new CCodeIdentifier ("_message"), ccall);
621 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
622 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
624 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
625 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
626 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
627 ccode.add_expression (builder_init);
630 ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new")));
633 CCodeExpression cancellable = new CCodeConstant ("NULL");
635 foreach (Parameter param in m.get_parameters ()) {
636 if (param.direction == ParameterDirection.IN) {
637 CCodeExpression expr = new CCodeIdentifier (get_variable_cname (param.name));
638 if (param.variable_type.is_real_struct_type ()) {
639 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
642 if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") {
647 if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") {
648 // ignore BusName sender parameters
652 send_dbus_value (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param);
656 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
657 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
658 ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
660 var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body"));
661 set_body.add_argument (new CCodeIdentifier ("_message"));
662 set_body.add_argument (new CCodeIdentifier ("_arguments"));
663 ccode.add_expression (set_body);
666 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
667 ccall.add_argument (new CCodeIdentifier ("_message"));
668 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
669 ccode.add_expression (ccall);
671 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
672 ccall.add_argument (new CCodeIdentifier ("_fd_list"));
673 ccode.add_expression (ccall);
676 // send D-Bus message
678 if (call_type == CallType.SYNC) {
679 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message_with_reply_sync"));
680 ccall.add_argument (connection);
681 ccall.add_argument (new CCodeIdentifier ("_message"));
682 ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
683 ccall.add_argument (timeout);
684 ccall.add_argument (new CCodeConstant ("NULL"));
685 ccall.add_argument (cancellable);
686 ccall.add_argument (error_argument);
687 ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
688 } else if (call_type == CallType.NO_REPLY) {
689 var set_flags = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_flags"));
690 set_flags.add_argument (new CCodeIdentifier ("_message"));
691 set_flags.add_argument (new CCodeConstant ("G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED"));
692 ccode.add_expression (set_flags);
694 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
695 ccall.add_argument (connection);
696 ccall.add_argument (new CCodeIdentifier ("_message"));
697 ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
698 ccall.add_argument (new CCodeConstant ("NULL"));
699 ccall.add_argument (error_argument);
700 ccode.add_expression (ccall);
701 } else if (call_type == CallType.ASYNC) {
702 var callback_specified = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("_callback_"), new CCodeConstant ("NULL"));
703 ccode.open_if (callback_specified);
705 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message_with_reply"));
706 ccall.add_argument (connection);
707 ccall.add_argument (new CCodeIdentifier ("_message"));
708 ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
709 ccall.add_argument (timeout);
710 ccall.add_argument (new CCodeConstant ("NULL"));
711 ccall.add_argument (cancellable);
713 CCodeFunctionCall res_wrapper = null;
715 // use wrapper as source_object wouldn't be correct otherwise
716 ccall.add_argument (new CCodeIdentifier (generate_async_callback_wrapper ()));
717 res_wrapper = new CCodeFunctionCall (new CCodeIdentifier ("g_task_new"));
718 res_wrapper.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *"));
719 res_wrapper.add_argument (new CCodeConstant ("NULL"));
720 res_wrapper.add_argument (new CCodeIdentifier ("_callback_"));
721 res_wrapper.add_argument (new CCodeIdentifier ("_user_data_"));
722 ccall.add_argument (res_wrapper);
724 ccode.add_expression (ccall);
728 var set_flags = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_flags"));
729 set_flags.add_argument (new CCodeIdentifier ("_message"));
730 set_flags.add_argument (new CCodeConstant ("G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED"));
731 ccode.add_expression (set_flags);
733 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
734 ccall.add_argument (connection);
735 ccall.add_argument (new CCodeIdentifier ("_message"));
736 ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
737 ccall.add_argument (new CCodeConstant ("NULL"));
738 ccall.add_argument (new CCodeConstant ("NULL"));
739 ccode.add_expression (ccall);
744 // free D-Bus message
746 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
747 ccall.add_argument (new CCodeIdentifier ("_message"));
748 ccode.add_expression (ccall);
750 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message_with_reply_finish"));
751 ccall.add_argument (connection);
753 // unwrap async result
754 ccode.add_declaration ("GAsyncResult", new CCodeVariableDeclarator ("*_inner_res"));
756 var inner_res = new CCodeFunctionCall (new CCodeIdentifier ("g_task_propagate_pointer"));
757 inner_res.add_argument (new CCodeCastExpression (new CCodeIdentifier ("_res_"), "GTask *"));
758 inner_res.add_argument (new CCodeConstant ("NULL"));
759 ccode.add_assignment (new CCodeIdentifier ("_inner_res"), inner_res);
761 ccall.add_argument (new CCodeIdentifier ("_inner_res"));
762 ccall.add_argument (error_argument);
763 ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
765 // _inner_res is guaranteed to be non-NULL, so just unref it
766 var unref_inner_res = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
767 unref_inner_res.add_argument (new CCodeIdentifier ("_inner_res"));
768 ccode.add_expression (unref_inner_res);
771 if (call_type == CallType.SYNC || call_type == CallType.FINISH) {
772 ccode.add_declaration ("GDBusMessage", new CCodeVariableDeclarator ("*_reply_message"));
774 var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
775 unref_reply.add_argument (new CCodeIdentifier ("_reply_message"));
777 // return on io error
778 var reply_is_null = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply_message"));
779 ccode.open_if (reply_is_null);
780 return_default_value (m.return_type);
783 // return on remote error
784 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_to_gerror"));
785 ccall.add_argument (new CCodeIdentifier ("_reply_message"));
786 ccall.add_argument (error_argument);
787 ccode.open_if (ccall);
788 ccode.add_expression (unref_reply);
789 return_default_value (m.return_type);
792 bool has_result = !(m.return_type is VoidType);
795 ccode.add_declaration ("gint", new CCodeVariableDeclarator.zero ("_fd_index", new CCodeConstant ("0")));
796 ccode.add_declaration ("gint", new CCodeVariableDeclarator ("_fd"));
799 foreach (Parameter param in m.get_parameters ()) {
800 if (param.direction == ParameterDirection.OUT) {
806 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply"));
807 ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_reply_iter"));
809 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_get_body"));
810 ccall.add_argument (new CCodeIdentifier ("_reply_message"));
811 ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall);
813 var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
814 iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_iter")));
815 iter_init.add_argument (new CCodeIdentifier ("_reply"));
816 ccode.add_expression (iter_init);
818 foreach (Parameter param in m.get_parameters ()) {
819 if (param.direction == ParameterDirection.OUT) {
820 ccode.add_declaration (get_ccode_name (param.variable_type), new CCodeVariableDeclarator.zero ("_vala_%s".printf (param.name), default_value_for_type (param.variable_type, true)));
822 var array_type = param.variable_type as ArrayType;
823 if (array_type != null) {
824 var length_ctype = get_ccode_array_length_type (array_type);
825 for (int dim = 1; dim <= array_type.rank; dim++) {
826 ccode.add_declaration (length_ctype, new CCodeVariableDeclarator ("_vala_%s_length%d".printf (param.name, dim), new CCodeConstant ("0")));
830 var target = new CCodeIdentifier ("_vala_%s".printf (param.name));
833 receive_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_message"), new CCodeIdentifier ("_reply_iter"), target, param, error_argument, out may_fail);
835 // TODO check that parameter is not NULL (out parameters are optional)
836 // free value if parameter is NULL
837 ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_variable_cname (param.name))), target);
839 if (array_type != null) {
840 for (int dim = 1; dim <= array_type.rank; dim++) {
841 // TODO check that parameter is not NULL (out parameters are optional)
842 ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("%s_length%d".printf (param.name, dim))), new CCodeIdentifier ("_vala_%s_length%d".printf (param.name, dim)));
846 if (may_fail && has_error_argument) {
847 ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("error"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error"))));
848 ccode.add_expression (unref_reply);
849 return_default_value (m.return_type);
855 if (!(m.return_type is VoidType)) {
856 if (m.return_type.is_real_non_null_struct_type ()) {
857 var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
858 receive_dbus_value (m.return_type, new CCodeIdentifier ("_reply_message"), new CCodeIdentifier ("_reply_iter"), target, m);
860 ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator.zero ("_result", default_value_for_type (m.return_type, true)));
862 var array_type = m.return_type as ArrayType;
863 if (array_type != null) {
864 var length_ctype = get_ccode_array_length_type (array_type);
865 for (int dim = 1; dim <= array_type.rank; dim++) {
866 ccode.add_declaration (length_ctype, new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
871 receive_dbus_value (m.return_type, new CCodeIdentifier ("_reply_message"), new CCodeIdentifier ("_reply_iter"), new CCodeIdentifier ("_result"), m, new CCodeIdentifier ("error"), out may_fail);
873 if (array_type != null) {
874 for (int dim = 1; dim <= array_type.rank; dim++) {
875 // TODO check that parameter is not NULL (out parameters are optional)
876 ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim)));
881 ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("error"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error"))));
882 ccode.add_expression (unref_reply);
883 return_default_value (m.return_type);
890 ccode.add_expression (unref_reply);
892 if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) {
893 ccode.add_return (new CCodeIdentifier ("_result"));
898 string generate_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
899 string proxy_name = "%sproxy_%s".printf (get_ccode_lower_case_prefix (main_iface), m.name);
901 string dbus_iface_name = get_dbus_name (iface);
903 bool no_reply = is_dbus_no_reply (m);
905 var function = new CCodeFunction (proxy_name);
906 function.modifiers = CCodeModifiers.STATIC;
908 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
910 generate_cparameters (m, cfile, cparam_map, function);
912 push_function (function);
914 generate_marshalling (m, no_reply ? CallType.NO_REPLY : CallType.SYNC, dbus_iface_name, get_dbus_name_for_member (m), get_dbus_timeout_for_member (m));
918 cfile.add_function_declaration (function);
919 cfile.add_function (function);
924 string generate_async_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
925 string proxy_name = "%sproxy_%s_async".printf (get_ccode_lower_case_prefix (main_iface), m.name);
927 string dbus_iface_name = get_dbus_name (iface);
929 var function = new CCodeFunction (proxy_name, "void");
930 function.modifiers = CCodeModifiers.STATIC;
932 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
934 cparam_map.set (get_param_pos (-1), new CCodeParameter ("_callback_", "GAsyncReadyCallback"));
935 cparam_map.set (get_param_pos (-0.9), new CCodeParameter ("_user_data_", "gpointer"));
937 generate_cparameters (m, cfile, cparam_map, function, null, null, null, 1);
939 push_function (function);
941 generate_marshalling (m, CallType.ASYNC, dbus_iface_name, get_dbus_name_for_member (m), get_dbus_timeout_for_member (m));
945 cfile.add_function_declaration (function);
946 cfile.add_function (function);
951 string generate_finish_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
952 string proxy_name = "%sproxy_%s_finish".printf (get_ccode_lower_case_prefix (main_iface), m.name);
954 var function = new CCodeFunction (proxy_name);
955 function.modifiers = CCodeModifiers.STATIC;
957 var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
959 cparam_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeParameter ("_res_", "GAsyncResult*"));
961 generate_cparameters (m, cfile, cparam_map, function, null, null, null, 2);
963 push_function (function);
965 generate_marshalling (m, CallType.FINISH, null, null, -1);
969 cfile.add_function_declaration (function);
970 cfile.add_function (function);
975 string generate_dbus_proxy_property_get (Interface main_iface, Interface iface, Property prop) {
976 string proxy_name = "%sdbus_proxy_get_%s".printf (get_ccode_lower_case_prefix (main_iface), prop.name);
978 string dbus_iface_name = get_dbus_name (iface);
980 var owned_type = prop.get_accessor.value_type.copy ();
981 owned_type.value_owned = true;
982 if (owned_type.is_disposable () && !prop.get_accessor.value_type.value_owned) {
983 Report.error (prop.get_accessor.value_type.source_reference, "Properties used in D-Bus clients require owned get accessor");
986 var array_type = prop.get_accessor.value_type as ArrayType;
988 var function = new CCodeFunction (proxy_name);
989 function.modifiers = CCodeModifiers.STATIC;
991 function.add_parameter (new CCodeParameter ("self", "%s*".printf (get_ccode_name (iface))));
993 if (prop.property_type.is_real_non_null_struct_type ()) {
994 function.add_parameter (new CCodeParameter ("result", "%s*".printf (get_ccode_name (prop.get_accessor.value_type))));
996 if (array_type != null) {
997 var length_ctype = get_ccode_array_length_type (array_type) + "*";
998 for (int dim = 1; dim <= array_type.rank; dim++) {
999 function.add_parameter (new CCodeParameter ("result_length%d".printf (dim), length_ctype));
1003 function.return_type = get_ccode_name (prop.get_accessor.value_type);
1006 push_function (function);
1008 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_inner_reply"));
1010 // first try cached value
1011 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_cached_property"));
1012 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
1013 ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
1014 ccode.add_assignment (new CCodeIdentifier ("_inner_reply"), ccall);
1016 // if not successful, retrieve value via D-Bus
1017 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_inner_reply")));
1019 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
1020 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply"));
1021 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
1023 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
1024 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1025 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
1026 ccode.add_expression (builder_init);
1029 write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)), null);
1031 write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))), null);
1033 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
1034 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1035 ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
1037 ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync"));
1038 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
1039 ccall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties.Get\""));
1040 ccall.add_argument (new CCodeIdentifier ("_arguments"));
1041 ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
1042 ccall.add_argument (get_dbus_timeout (prop));
1043 ccall.add_argument (new CCodeConstant ("NULL"));
1044 ccall.add_argument (new CCodeConstant ("NULL"));
1046 ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall);
1049 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply")));
1050 return_default_value (prop.property_type);
1053 var get_variant = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get"));
1054 get_variant.add_argument (new CCodeIdentifier ("_reply"));
1055 get_variant.add_argument (new CCodeConstant ("\"(v)\""));
1056 get_variant.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_inner_reply")));
1057 ccode.add_expression (get_variant);
1059 var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
1060 unref_reply.add_argument (new CCodeIdentifier ("_reply"));
1061 ccode.add_expression (unref_reply);
1065 if (prop.property_type.is_real_non_null_struct_type ()) {
1066 var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
1067 var result = deserialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("_inner_reply"), target);
1068 ccode.add_assignment (target, result);
1070 ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator ("_result"));
1072 if (get_dbus_signature (prop) != null) {
1074 ccode.add_assignment (new CCodeIdentifier ("_result"), new CCodeIdentifier("_inner_reply"));
1076 if (array_type != null) {
1077 var length_ctype = get_ccode_array_length_type (array_type);
1078 for (int dim = 1; dim <= array_type.rank; dim++) {
1079 ccode.add_declaration (length_ctype, new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
1083 var result = deserialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("_inner_reply"), new CCodeIdentifier ("_result"));
1084 ccode.add_assignment (new CCodeIdentifier ("_result"), result);
1086 if (array_type != null) {
1087 for (int dim = 1; dim <= array_type.rank; dim++) {
1088 // TODO check that parameter is not NULL (out parameters are optional)
1089 ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim)));
1095 if (prop.property_type.is_real_non_null_struct_type () || get_dbus_signature (prop) == null) {
1096 unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
1097 unref_reply.add_argument (new CCodeIdentifier ("_inner_reply"));
1098 ccode.add_expression (unref_reply);
1101 if (prop.property_type.is_real_non_null_struct_type ()) {
1102 ccode.add_return ();
1104 ccode.add_return (new CCodeIdentifier ("_result"));
1109 cfile.add_function_declaration (function);
1110 cfile.add_function (function);
1115 string generate_dbus_proxy_property_set (Interface main_iface, Interface iface, Property prop) {
1116 string proxy_name = "%sdbus_proxy_set_%s".printf (get_ccode_lower_case_prefix (main_iface), prop.name);
1118 string dbus_iface_name = get_dbus_name (iface);
1120 var array_type = prop.set_accessor.value_type as ArrayType;
1122 var function = new CCodeFunction (proxy_name);
1123 function.modifiers = CCodeModifiers.STATIC;
1125 function.add_parameter (new CCodeParameter ("self", "%s*".printf (get_ccode_name (iface))));
1127 if (prop.property_type.is_real_non_null_struct_type ()) {
1128 function.add_parameter (new CCodeParameter ("value", "%s*".printf (get_ccode_name (prop.set_accessor.value_type))));
1130 function.add_parameter (new CCodeParameter ("value", get_ccode_name (prop.set_accessor.value_type)));
1132 if (array_type != null) {
1133 var length_ctype = get_ccode_array_length_type (array_type);
1134 for (int dim = 1; dim <= array_type.rank; dim++) {
1135 function.add_parameter (new CCodeParameter ("value_length%d".printf (dim), length_ctype));
1140 push_function (function);
1142 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
1143 ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply"));
1145 ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
1147 var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
1148 builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1149 builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
1150 ccode.add_expression (builder_init);
1153 write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)), null);
1155 write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))), null);
1157 // property value (as variant)
1158 var builder_open = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_open"));
1159 builder_open.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1160 builder_open.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_VARIANT"));
1161 ccode.add_expression (builder_open);
1163 if (prop.property_type.is_real_non_null_struct_type ()) {
1164 write_expression (prop.set_accessor.value_type, new CCodeIdentifier ("_arguments_builder"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("value")), prop);
1166 write_expression (prop.set_accessor.value_type, new CCodeIdentifier ("_arguments_builder"), new CCodeIdentifier ("value"), prop);
1169 var builder_close = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_close"));
1170 builder_close.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1171 ccode.add_expression (builder_close);
1173 var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
1174 builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1175 ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
1177 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync"));
1178 ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
1179 ccall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties.Set\""));
1180 ccall.add_argument (new CCodeIdentifier ("_arguments"));
1181 ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
1182 ccall.add_argument (get_dbus_timeout (prop));
1183 ccall.add_argument (new CCodeConstant ("NULL"));
1184 ccall.add_argument (new CCodeConstant ("NULL"));
1186 ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall);
1189 ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply")));
1190 ccode.add_return ();
1193 var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
1194 unref_reply.add_argument (new CCodeIdentifier ("_reply"));
1195 ccode.add_expression (unref_reply);
1199 cfile.add_function_declaration (function);
1200 cfile.add_function (function);
1205 public override void register_dbus_info (CCodeBlock block, ObjectTypeSymbol sym) {
1206 if (!(sym is Interface)) {
1210 string dbus_iface_name = get_dbus_name (sym);
1211 if (dbus_iface_name == null) {
1215 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1216 quark.add_argument (new CCodeConstant ("\"vala-dbus-proxy-type\""));
1218 var proxy_type = new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "proxy_get_type");
1220 var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1221 set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null))));
1222 set_qdata.add_argument (quark);
1223 set_qdata.add_argument (new CCodeCastExpression (proxy_type, "void*"));
1225 block.add_statement (new CCodeExpressionStatement (set_qdata));
1227 quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1228 quark.add_argument (new CCodeConstant ("\"vala-dbus-interface-name\""));
1230 set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1231 set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null))));
1232 set_qdata.add_argument (quark);
1233 set_qdata.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1235 block.add_statement (new CCodeExpressionStatement (set_qdata));
1237 // TODO Replaced by g_dbus_proxy_set_interface_info() call in *_init
1238 quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1239 quark.add_argument (new CCodeConstant ("\"vala-dbus-interface-info\""));
1241 set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1242 set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null))));
1243 set_qdata.add_argument (quark);
1244 set_qdata.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (sym)), "void*"));
1246 block.add_statement (new CCodeExpressionStatement (set_qdata));