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 dynamic_method
= (DynamicMethod
) method
;
48 var func
= new
CCodeFunction (get_ccode_name (method
));
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
);
57 if (dynamic_method
.dynamic_type
.data_type
== dbus_proxy_type
) {
58 generate_marshalling (method
, CallType
.SYNC
, null, method
.name
, -1);
60 Report
.error (method
.source_reference
, "dynamic methods are not supported for `%s'".printf (dynamic_method
.dynamic_type
.to_string ()));
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
= get_ccode_lower_case_prefix (main_iface
) + "proxy";
79 var proxy_iface_init
= new
CCodeFunction (lower_cname
+ "_" + get_ccode_lower_case_prefix (iface
) + "interface_init", "void");
80 proxy_iface_init
.add_parameter (new
CCodeParameter ("iface", get_ccode_name (iface
) + "Iface*"));
82 push_function (proxy_iface_init
);
84 foreach (Method m
in iface
.get_methods ()) {
89 var vfunc_entry
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("iface"), get_ccode_vfunc_name (m
));
91 ccode
.add_assignment (vfunc_entry
, new
CCodeIdentifier (generate_dbus_proxy_method (main_iface
, iface
, m
)));
93 ccode
.add_assignment (vfunc_entry
, new
CCodeIdentifier (generate_async_dbus_proxy_method (main_iface
, iface
, m
)));
94 vfunc_entry
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("iface"), get_ccode_finish_vfunc_name (m
));
95 ccode
.add_assignment (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
) {
104 if (prop
.get_accessor
!= null) {
105 var vfunc_entry
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("iface"), "get_" + prop
.name
);
106 ccode
.add_assignment (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 ccode
.add_assignment (vfunc_entry
, new
CCodeIdentifier (generate_dbus_proxy_property_set (main_iface
, iface
, prop
)));
114 proxy_iface_init
.modifiers
= CCodeModifiers
.STATIC
;
116 cfile
.add_function_declaration (proxy_iface_init
);
117 cfile
.add_function (proxy_iface_init
);
120 string implement_interface (CCodeFunctionCall define_type
, Interface main_iface
, Interface iface
) {
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 string interface_macro
;
133 interface_macro
= "G_IMPLEMENT_INTERFACE_DYNAMIC";
135 interface_macro
= "G_IMPLEMENT_INTERFACE";
138 result
+= "%s (%s, %sproxy_%sinterface_init) ".printf (
140 get_ccode_upper_case_name (iface
, "TYPE_"),
141 get_ccode_lower_case_prefix (main_iface
),
142 get_ccode_lower_case_prefix (iface
));
146 public override void generate_interface_declaration (Interface iface
, CCodeFile decl_space
) {
147 base.generate_interface_declaration (iface
, decl_space
);
149 string dbus_iface_name
= get_dbus_name (iface
);
150 if (dbus_iface_name
== null) {
154 string get_type_name
= "%sproxy_get_type".printf (get_ccode_lower_case_prefix (iface
));
156 if (add_symbol_declaration (decl_space
, iface
, get_type_name
)) {
160 decl_space
.add_type_declaration (new
CCodeNewline ());
161 var macro
= "(%s ())".printf (get_type_name
);
162 decl_space
.add_type_declaration (new
CCodeMacroReplacement ("%s_PROXY".printf (get_ccode_type_id (iface
)), macro
));
164 // declare proxy_get_type function
165 var proxy_get_type
= new
CCodeFunction (get_type_name
, "GType");
166 proxy_get_type
.modifiers
= CCodeModifiers
.CONST
;
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 decl_space
.add_function_declaration (proxy_register_type
);
176 public override void visit_interface (Interface iface
) {
177 base.visit_interface (iface
);
179 string dbus_iface_name
= get_dbus_name (iface
);
180 if (dbus_iface_name
== null) {
184 cfile
.add_include ("gio/gio.h");
186 // create proxy class
187 string cname
= get_ccode_name (iface
) + "Proxy";
188 string lower_cname
= get_ccode_lower_case_prefix (iface
) + "proxy";
190 cfile
.add_type_declaration (new
CCodeTypeDefinition ("GDBusProxy", new
CCodeVariableDeclarator (cname
)));
191 cfile
.add_type_declaration (new
CCodeTypeDefinition ("GDBusProxyClass", new
CCodeVariableDeclarator (cname
+ "Class")));
196 type_macro
= "G_DEFINE_DYNAMIC_TYPE_EXTENDED";
198 type_macro
= "G_DEFINE_TYPE_EXTENDED";
201 var define_type
= new
CCodeFunctionCall (new
CCodeIdentifier (type_macro
));
202 define_type
.add_argument (new
CCodeIdentifier (cname
));
203 define_type
.add_argument (new
CCodeIdentifier (lower_cname
));
204 define_type
.add_argument (new
CCodeIdentifier ("G_TYPE_DBUS_PROXY"));
205 define_type
.add_argument (new
CCodeConstant ("0"));
206 define_type
.add_argument (new
CCodeIdentifier (implement_interface (define_type
, iface
, iface
)));
208 cfile
.add_type_member_definition (define_type
);
210 var proxy_class_init
= new
CCodeFunction (lower_cname
+ "_class_init", "void");
211 proxy_class_init
.add_parameter (new
CCodeParameter ("klass", cname
+ "Class*"));
212 proxy_class_init
.modifiers
= CCodeModifiers
.STATIC
;
213 push_function (proxy_class_init
);
214 var proxy_class
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_DBUS_PROXY_CLASS"));
215 proxy_class
.add_argument (new
CCodeIdentifier ("klass"));
216 ccode
.add_assignment (new CCodeMemberAccess
.pointer (proxy_class
, "g_signal"), new
CCodeIdentifier (lower_cname
+ "_g_signal"));
218 cfile
.add_function (proxy_class_init
);
220 generate_signal_handler_function (iface
);
223 var proxy_class_finalize
= new
CCodeFunction (lower_cname
+ "_class_finalize", "void");
224 proxy_class_finalize
.add_parameter (new
CCodeParameter ("klass", cname
+ "Class*"));
225 proxy_class_finalize
.modifiers
= CCodeModifiers
.STATIC
;
226 cfile
.add_function (proxy_class_finalize
);
228 var proxy_type_init
= new
CCodeFunction (lower_cname
+ "_register_dynamic_type", "void");
229 proxy_type_init
.add_parameter (new
CCodeParameter ("module", "GTypeModule*"));
230 push_function (proxy_type_init
);
231 var call_register_type
= new
CCodeFunctionCall (new
CCodeIdentifier (lower_cname
+ "_register_type"));
232 call_register_type
.add_argument (new
CCodeIdentifier ("module"));
233 ccode
.add_expression (call_register_type
);
235 cfile
.add_function(proxy_type_init
);
238 var proxy_instance_init
= new
CCodeFunction (lower_cname
+ "_init", "void");
239 proxy_instance_init
.add_parameter (new
CCodeParameter ("self", cname
+ "*"));
240 proxy_instance_init
.modifiers
= CCodeModifiers
.STATIC
;
241 cfile
.add_function (proxy_instance_init
);
243 generate_proxy_interface_init (iface
, iface
);
246 public override void visit_method_call (MethodCall expr
) {
247 var mtype
= expr
.call
.value_type as MethodType
;
248 bool bus_get_proxy_async
= (mtype
!= null && get_ccode_name (mtype
.method_symbol
) == "g_bus_get_proxy");
249 bool bus_get_proxy_sync
= (mtype
!= null && get_ccode_name (mtype
.method_symbol
) == "g_bus_get_proxy_sync");
250 bool conn_get_proxy_async
= (mtype
!= null && get_ccode_name (mtype
.method_symbol
) == "g_dbus_connection_get_proxy");
251 bool conn_get_proxy_sync
= (mtype
!= null && get_ccode_name (mtype
.method_symbol
) == "g_dbus_connection_get_proxy_sync");
252 if (!bus_get_proxy_async
&& !bus_get_proxy_sync
&& !conn_get_proxy_async
&& !conn_get_proxy_sync
) {
253 base.visit_method_call (expr
);
257 var ma
= (MemberAccess
) expr
.call
;
258 var type_arg
= ma
.get_type_arguments ().get (0);
260 CCodeExpression proxy_type
;
261 CCodeExpression dbus_iface_name
;
262 CCodeExpression dbus_iface_info
;
264 var object_type
= type_arg as ObjectType
;
265 if (object_type
!= null) {
266 var iface
= (Interface
) object_type
.type_symbol
;
268 if (get_dbus_name (iface
) == null) {
269 Report
.error (expr
.source_reference
, "`%s' is not a D-Bus interface".printf (iface
.get_full_name ()));
273 proxy_type
= new
CCodeIdentifier ("%s_PROXY".printf (get_ccode_type_id (iface
)));
274 dbus_iface_name
= new
CCodeConstant ("\"%s\"".printf (get_dbus_name (iface
)));
276 // use runtime type information for generic methods
278 var quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
279 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-proxy-type\""));
281 var get_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_get_qdata"));
282 get_qdata
.add_argument (get_type_id_expression (type_arg
));
283 get_qdata
.add_argument (quark
);
285 proxy_type
= new
CCodeFunctionCall (new
CCodeCastExpression (get_qdata
, "GType (*) (void)"));
287 quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
288 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-interface-name\""));
290 get_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_get_qdata"));
291 get_qdata
.add_argument (get_type_id_expression (type_arg
));
292 get_qdata
.add_argument (quark
);
294 dbus_iface_name
= get_qdata
;
297 var quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
298 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-interface-info\""));
300 var get_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_get_qdata"));
301 get_qdata
.add_argument (get_type_id_expression (type_arg
));
302 get_qdata
.add_argument (quark
);
304 dbus_iface_info
= get_qdata
;
306 if (bus_get_proxy_async
|| conn_get_proxy_async
) {
307 if (ma
.member_name
== "end" && ma
.inner
.symbol_reference
== ma
.symbol_reference
) {
309 current_method_inner_error
= true;
311 var args
= expr
.get_argument_list ();
312 Expression res
= args
.get (0);
314 var source_var
= get_temp_variable (expr
.value_type
, expr
.value_type
.value_owned
);
315 var source_ref
= get_variable_cexpression (source_var
.name
);
316 emit_temp_var (source_var
);
317 var source
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_async_result_get_source_object"));
318 source
.add_argument (get_cvalue (res
));
319 ccode
.add_assignment (source_ref
, source
);
321 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_async_initable_new_finish"));
322 ccall
.add_argument (source_ref
);
323 ccall
.add_argument (get_cvalue (res
));
324 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_variable_cexpression ("_inner_error_")));
326 var temp_var
= get_temp_variable (expr
.value_type
, expr
.value_type
.value_owned
);
327 var temp_ref
= get_variable_cexpression (temp_var
.name
);
328 emit_temp_var (temp_var
);
329 ccode
.add_assignment (temp_ref
, ccall
);
331 // g_async_result_get_source_object transfers ownership, unref after use
332 var unref_proxy
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
333 unref_proxy
.add_argument (source_ref
);
334 ccode
.add_expression (unref_proxy
);
336 set_cvalue (expr
, temp_ref
);
342 var base_arg_index
= 0;
343 if (bus_get_proxy_async
|| bus_get_proxy_sync
)
346 var args
= expr
.get_argument_list ();
347 Expression name
= args
.get (base_arg_index
+ 0);
348 Expression object_path
= args
.get (base_arg_index
+ 1);
349 Expression flags
= args
.get (base_arg_index
+ 2);
350 Expression cancellable
= args
.get (base_arg_index
+ 3);
353 current_method_inner_error
= true;
355 CCodeFunctionCall ccall
;
356 if (bus_get_proxy_async
|| conn_get_proxy_async
) {
357 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_async_initable_new_async"));
359 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_initable_new"));
361 ccall
.add_argument (proxy_type
);
362 if (bus_get_proxy_async
|| conn_get_proxy_async
) {
364 ccall
.add_argument (new
CCodeConstant ("0"));
366 ccall
.add_argument (get_cvalue (cancellable
));
367 if (bus_get_proxy_async
|| conn_get_proxy_async
) {
368 if (expr
.is_yield_expression
) {
370 ccall
.add_argument (new
CCodeIdentifier (generate_ready_function (current_method
)));
371 ccall
.add_argument (new
CCodeIdentifier ("_data_"));
374 Expression
callback = args
.get (base_arg_index
+ 4);
375 ccall
.add_argument (get_cvalue (callback));
376 ccall
.add_argument (get_delegate_target (callback));
379 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_variable_cexpression ("_inner_error_")));
381 ccall
.add_argument (new
CCodeConstant ("\"g-flags\""));
382 ccall
.add_argument (get_cvalue (flags
));
383 ccall
.add_argument (new
CCodeConstant ("\"g-name\""));
384 ccall
.add_argument (get_cvalue (name
));
385 if (bus_get_proxy_async
|| bus_get_proxy_sync
) {
386 Expression bus_type
= args
.get (0);
387 ccall
.add_argument (new
CCodeConstant ("\"g-bus-type\""));
388 ccall
.add_argument (get_cvalue (bus_type
));
390 Expression connection
= ma
.inner
;
391 if (ma
.member_name
== "begin" && ma
.inner
.symbol_reference
== ma
.symbol_reference
) {
392 var inner_ma
= (MemberAccess
) ma
.inner
;
393 connection
= inner_ma
.inner
;
395 ccall
.add_argument (new
CCodeConstant ("\"g-connection\""));
396 ccall
.add_argument (get_cvalue (connection
));
398 ccall
.add_argument (new
CCodeConstant ("\"g-object-path\""));
399 ccall
.add_argument (get_cvalue (object_path
));
400 ccall
.add_argument (new
CCodeConstant ("\"g-interface-name\""));
401 ccall
.add_argument (dbus_iface_name
);
402 if (dbus_iface_info
!= null) {
403 ccall
.add_argument (new
CCodeConstant ("\"g-interface-info\""));
404 ccall
.add_argument (dbus_iface_info
);
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 CCodeMemberAccess
.pointer (new
CCodeIdentifier ("_data_"), "_source_object_"));
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_variable_cexpression ("_inner_error_")));
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
, ccall
);
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 var st
= param
.variable_type
.data_type 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
;
476 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
477 string length_cname
= get_parameter_array_length_cname (param
, dim
);
479 ccode
.add_declaration ("int", new
CCodeVariableDeclarator (length_cname
, new
CCodeConstant ("0")));
480 ccall
.add_argument (new
CCodeIdentifier (length_cname
));
484 read_expression (param
.variable_type
, new
CCodeIdentifier ("_arguments_iter"), new
CCodeIdentifier (param_name
), param
);
487 ccode
.add_expression (ccall
);
489 foreach (Parameter param
in sig
.get_parameters ()) {
490 var owned_type
= param
.variable_type
.copy ();
491 owned_type
.value_owned
= true;
493 if (requires_destroy (owned_type
)) {
494 // keep local alive (symbol_reference is weak)
495 var local
= new
LocalVariable (owned_type
, param
.name
);
496 ccode
.add_expression (destroy_local (local
));
502 cfile
.add_function_declaration (function
);
503 cfile
.add_function (function
);
508 void generate_signal_handler_function (ObjectTypeSymbol sym
) {
509 var cfunc
= new
CCodeFunction (get_ccode_lower_case_prefix (sym
) + "proxy_g_signal", "void");
510 cfunc
.add_parameter (new
CCodeParameter ("proxy", "GDBusProxy*"));
511 cfunc
.add_parameter (new
CCodeParameter ("sender_name", "const gchar*"));
512 cfunc
.add_parameter (new
CCodeParameter ("signal_name", "const gchar*"));
513 cfunc
.add_parameter (new
CCodeParameter ("parameters", "GVariant*"));
515 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
517 cfile
.add_function_declaration (cfunc
);
519 push_function (cfunc
);
523 foreach (Signal sig
in sym
.get_signals ()) {
524 if (sig
.access
!= SymbolAccessibility
.PUBLIC
) {
528 cfile
.add_include ("string.h");
530 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
531 ccheck
.add_argument (new
CCodeIdentifier ("signal_name"));
532 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig
))));
534 var cond
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccheck
, new
CCodeConstant ("0"));
536 ccode
.open_if (cond
);
539 ccode
.else_if (cond
);
542 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_dbus_signal_handler (sig
, sym
)));
543 ccall
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("proxy"), get_ccode_name (sym
) + "*"));
544 ccall
.add_argument (new
CCodeIdentifier ("parameters"));
546 ccode
.add_expression (ccall
);
554 cfile
.add_function (cfunc
);
557 void generate_marshalling (Method m
, CallType call_type
, string? iface_name
, string? method_name
, int method_timeout
) {
558 var gdbusproxy
= new
CCodeCastExpression (new
CCodeIdentifier ("self"), "GDBusProxy *");
560 var connection
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_proxy_get_connection"));
561 connection
.add_argument (gdbusproxy
);
563 bool uses_fd
= dbus_method_uses_file_descriptor (m
);
565 cfile
.add_include ("gio/gunixfdlist.h");
566 ccode
.add_declaration ("GUnixFDList*", new
CCodeVariableDeclarator ("_fd_list"));
569 bool has_error_argument
= (m
.get_error_types ().size
> 0);
570 CCodeExpression error_argument
;
571 if (has_error_argument
) {
572 error_argument
= new
CCodeIdentifier ("error");
574 error_argument
= new
CCodeConstant ("NULL");
577 if (call_type
!= CallType
.FINISH
) {
578 var destination
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_proxy_get_name"));
579 destination
.add_argument (gdbusproxy
);
581 var interface_name
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_proxy_get_interface_name"));
582 interface_name
.add_argument (gdbusproxy
);
584 var object_path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_proxy_get_object_path"));
585 object_path
.add_argument (gdbusproxy
);
587 CCodeExpression timeout
;
588 if (method_timeout
<= 0) {
589 timeout
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_proxy_get_default_timeout"));
590 ((CCodeFunctionCall
) timeout
).add_argument (gdbusproxy
);
592 timeout
= new
CCodeConstant ("%d".printf (method_timeout
));
596 foreach (var error_type
in m
.get_error_types ()) {
597 var errtype
= (ErrorType
) error_type
;
598 if (errtype
.error_domain
!= null) {
599 ccode
.add_expression (new
CCodeIdentifier (get_ccode_upper_case_name (errtype
.error_domain
)));
603 // build D-Bus message
605 ccode
.add_declaration ("GDBusMessage", new
CCodeVariableDeclarator ("*_message"));
607 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_new_method_call"));
608 ccall
.add_argument (destination
);
609 ccall
.add_argument (object_path
);
610 if (iface_name
!= null) {
611 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (iface_name
)));
613 ccall
.add_argument (interface_name
);
615 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (method_name
)));
616 ccode
.add_assignment (new
CCodeIdentifier ("_message"), ccall
);
618 ccode
.add_declaration ("GVariant", new
CCodeVariableDeclarator ("*_arguments"));
619 ccode
.add_declaration ("GVariantBuilder", new
CCodeVariableDeclarator ("_arguments_builder"));
621 var builder_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_init"));
622 builder_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
623 builder_init
.add_argument (new
CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
624 ccode
.add_expression (builder_init
);
627 ccode
.add_assignment (new
CCodeIdentifier ("_fd_list"), new
CCodeFunctionCall (new
CCodeIdentifier ("g_unix_fd_list_new")));
630 CCodeExpression cancellable
= new
CCodeConstant ("NULL");
632 foreach (Parameter param
in m
.get_parameters ()) {
633 if (param
.direction
== ParameterDirection
.IN
) {
634 CCodeExpression expr
= new
CCodeIdentifier (get_variable_cname (param
.name
));
635 if (param
.variable_type
.is_real_struct_type ()) {
636 expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, expr
);
639 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.Cancellable") {
644 if (param
.variable_type is ObjectType
&& param
.variable_type
.data_type
.get_full_name () == "GLib.BusName") {
645 // ignore BusName sender parameters
649 send_dbus_value (param
.variable_type
, new
CCodeIdentifier ("_arguments_builder"), expr
, param
);
653 var builder_end
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_end"));
654 builder_end
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
655 ccode
.add_assignment (new
CCodeIdentifier ("_arguments"), builder_end
);
657 var set_body
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_set_body"));
658 set_body
.add_argument (new
CCodeIdentifier ("_message"));
659 set_body
.add_argument (new
CCodeIdentifier ("_arguments"));
660 ccode
.add_expression (set_body
);
663 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
664 ccall
.add_argument (new
CCodeIdentifier ("_message"));
665 ccall
.add_argument (new
CCodeIdentifier ("_fd_list"));
666 ccode
.add_expression (ccall
);
668 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
669 ccall
.add_argument (new
CCodeIdentifier ("_fd_list"));
670 ccode
.add_expression (ccall
);
673 // send D-Bus message
675 if (call_type
== CallType
.SYNC
) {
676 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_send_message_with_reply_sync"));
677 ccall
.add_argument (connection
);
678 ccall
.add_argument (new
CCodeIdentifier ("_message"));
679 ccall
.add_argument (new
CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
680 ccall
.add_argument (timeout
);
681 ccall
.add_argument (new
CCodeConstant ("NULL"));
682 ccall
.add_argument (cancellable
);
683 ccall
.add_argument (error_argument
);
684 ccode
.add_assignment (new
CCodeIdentifier ("_reply_message"), ccall
);
685 } else if (call_type
== CallType
.NO_REPLY
) {
686 var set_flags
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_set_flags"));
687 set_flags
.add_argument (new
CCodeIdentifier ("_message"));
688 set_flags
.add_argument (new
CCodeConstant ("G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED"));
689 ccode
.add_expression (set_flags
);
691 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_send_message"));
692 ccall
.add_argument (connection
);
693 ccall
.add_argument (new
CCodeIdentifier ("_message"));
694 ccall
.add_argument (new
CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
695 ccall
.add_argument (new
CCodeConstant ("NULL"));
696 ccall
.add_argument (error_argument
);
697 ccode
.add_expression (ccall
);
698 } else if (call_type
== CallType
.ASYNC
) {
699 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_send_message_with_reply"));
700 ccall
.add_argument (connection
);
701 ccall
.add_argument (new
CCodeIdentifier ("_message"));
702 ccall
.add_argument (new
CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
703 ccall
.add_argument (timeout
);
704 ccall
.add_argument (new
CCodeConstant ("NULL"));
705 ccall
.add_argument (cancellable
);
707 CCodeFunctionCall res_wrapper
= null;
709 // use wrapper as source_object wouldn't be correct otherwise
710 ccall
.add_argument (new
CCodeIdentifier (generate_async_callback_wrapper ()));
711 res_wrapper
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_task_new"));
712 res_wrapper
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "GObject *"));
713 res_wrapper
.add_argument (new
CCodeConstant ("NULL"));
714 res_wrapper
.add_argument (new
CCodeIdentifier ("_callback_"));
715 res_wrapper
.add_argument (new
CCodeIdentifier ("_user_data_"));
716 ccall
.add_argument (res_wrapper
);
718 ccode
.add_expression (ccall
);
721 // free D-Bus message
723 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
724 ccall
.add_argument (new
CCodeIdentifier ("_message"));
725 ccode
.add_expression (ccall
);
727 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_connection_send_message_with_reply_finish"));
728 ccall
.add_argument (connection
);
730 // unwrap async result
731 ccode
.add_declaration ("GAsyncResult", new
CCodeVariableDeclarator ("*_inner_res"));
733 var inner_res
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_task_propagate_pointer"));
734 inner_res
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("_res_"), "GTask *"));
735 inner_res
.add_argument (new
CCodeConstant ("NULL"));
736 ccode
.add_assignment (new
CCodeIdentifier ("_inner_res"), inner_res
);
738 ccall
.add_argument (new
CCodeIdentifier ("_inner_res"));
739 ccall
.add_argument (error_argument
);
740 ccode
.add_assignment (new
CCodeIdentifier ("_reply_message"), ccall
);
742 // _inner_res is guaranteed to be non-NULL, so just unref it
743 var unref_inner_res
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
744 unref_inner_res
.add_argument (new
CCodeIdentifier ("_inner_res"));
745 ccode
.add_expression (unref_inner_res
);
748 if (call_type
== CallType
.SYNC
|| call_type
== CallType
.FINISH
) {
749 ccode
.add_declaration ("GDBusMessage", new
CCodeVariableDeclarator ("*_reply_message"));
751 var unref_reply
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
752 unref_reply
.add_argument (new
CCodeIdentifier ("_reply_message"));
754 // return on io error
755 var reply_is_null
= new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("_reply_message"));
756 ccode
.open_if (reply_is_null
);
757 return_default_value (m
.return_type
);
760 // return on remote error
761 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_to_gerror"));
762 ccall
.add_argument (new
CCodeIdentifier ("_reply_message"));
763 ccall
.add_argument (error_argument
);
764 ccode
.open_if (ccall
);
765 ccode
.add_expression (unref_reply
);
766 return_default_value (m
.return_type
);
769 bool has_result
= !(m
.return_type is VoidType
);
772 ccode
.add_declaration ("gint", new CCodeVariableDeclarator
.zero ("_fd_index", new
CCodeConstant ("0")));
773 ccode
.add_declaration ("gint", new
CCodeVariableDeclarator ("_fd"));
776 foreach (Parameter param
in m
.get_parameters ()) {
777 if (param
.direction
== ParameterDirection
.OUT
) {
783 ccode
.add_declaration ("GVariant", new
CCodeVariableDeclarator ("*_reply"));
784 ccode
.add_declaration ("GVariantIter", new
CCodeVariableDeclarator ("_reply_iter"));
786 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_message_get_body"));
787 ccall
.add_argument (new
CCodeIdentifier ("_reply_message"));
788 ccode
.add_assignment (new
CCodeIdentifier ("_reply"), ccall
);
790 var iter_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_iter_init"));
791 iter_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_reply_iter")));
792 iter_init
.add_argument (new
CCodeIdentifier ("_reply"));
793 ccode
.add_expression (iter_init
);
795 foreach (Parameter param
in m
.get_parameters ()) {
796 if (param
.direction
== ParameterDirection
.OUT
) {
797 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)));
799 var array_type
= param
.variable_type as ArrayType
;
801 if (array_type
!= null) {
802 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
803 ccode
.add_declaration ("int", new
CCodeVariableDeclarator ("_vala_%s_length%d".printf (param
.name
, dim
), new
CCodeConstant ("0")));
807 var target
= new
CCodeIdentifier ("_vala_%s".printf (param
.name
));
810 receive_dbus_value (param
.variable_type
, new
CCodeIdentifier ("_reply_message"), new
CCodeIdentifier ("_reply_iter"), target
, param
, error_argument
, out may_fail
);
812 // TODO check that parameter is not NULL (out parameters are optional)
813 // free value if parameter is NULL
814 ccode
.add_assignment (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier (get_variable_cname (param
.name
))), target
);
816 if (array_type
!= null) {
817 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
818 // TODO check that parameter is not NULL (out parameters are optional)
819 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
)));
823 if (may_fail
&& has_error_argument
) {
824 ccode
.open_if (new
CCodeBinaryExpression (CCodeBinaryOperator
.AND
, new
CCodeIdentifier ("error"), new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("error"))));
825 ccode
.add_expression (unref_reply
);
826 return_default_value (m
.return_type
);
832 if (!(m
.return_type is VoidType
)) {
833 if (m
.return_type
.is_real_non_null_struct_type ()) {
834 var target
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result"));
835 receive_dbus_value (m
.return_type
, new
CCodeIdentifier ("_reply_message"), new
CCodeIdentifier ("_reply_iter"), target
, m
);
837 ccode
.add_declaration (get_ccode_name (m
.return_type
), new CCodeVariableDeclarator
.zero ("_result", default_value_for_type (m
.return_type
, true)));
839 var array_type
= m
.return_type as ArrayType
;
841 if (array_type
!= null) {
842 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
843 ccode
.add_declaration ("int", new
CCodeVariableDeclarator ("_result_length%d".printf (dim
), new
CCodeConstant ("0")));
848 receive_dbus_value (m
.return_type
, new
CCodeIdentifier ("_reply_message"), new
CCodeIdentifier ("_reply_iter"), new
CCodeIdentifier ("_result"), m
, new
CCodeIdentifier ("error"), out may_fail
);
850 if (array_type
!= null) {
851 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
852 // TODO check that parameter is not NULL (out parameters are optional)
853 ccode
.add_assignment (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result_length%d".printf (dim
))), new
CCodeIdentifier ("_result_length%d".printf (dim
)));
858 ccode
.open_if (new
CCodeBinaryExpression (CCodeBinaryOperator
.AND
, new
CCodeIdentifier ("error"), new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("error"))));
859 ccode
.add_expression (unref_reply
);
860 return_default_value (m
.return_type
);
867 ccode
.add_expression (unref_reply
);
869 if (!(m
.return_type is VoidType
|| m
.return_type
.is_real_non_null_struct_type ())) {
870 ccode
.add_return (new
CCodeIdentifier ("_result"));
875 string generate_dbus_proxy_method (Interface main_iface
, Interface iface
, Method m
) {
876 string proxy_name
= "%sproxy_%s".printf (get_ccode_lower_case_prefix (main_iface
), m
.name
);
878 string dbus_iface_name
= get_dbus_name (iface
);
880 bool no_reply
= is_dbus_no_reply (m
);
882 var function
= new
CCodeFunction (proxy_name
);
883 function
.modifiers
= CCodeModifiers
.STATIC
;
885 var cparam_map
= new HashMap
<int,CCodeParameter
> (direct_hash
, direct_equal
);
887 generate_cparameters (m
, cfile
, cparam_map
, function
);
889 push_function (function
);
891 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
));
895 cfile
.add_function_declaration (function
);
896 cfile
.add_function (function
);
901 string generate_async_dbus_proxy_method (Interface main_iface
, Interface iface
, Method m
) {
902 string proxy_name
= "%sproxy_%s_async".printf (get_ccode_lower_case_prefix (main_iface
), m
.name
);
904 string dbus_iface_name
= get_dbus_name (iface
);
906 var function
= new
CCodeFunction (proxy_name
, "void");
907 function
.modifiers
= CCodeModifiers
.STATIC
;
909 var cparam_map
= new HashMap
<int,CCodeParameter
> (direct_hash
, direct_equal
);
911 cparam_map
.set (get_param_pos (-1), new
CCodeParameter ("_callback_", "GAsyncReadyCallback"));
912 cparam_map
.set (get_param_pos (-0.9), new
CCodeParameter ("_user_data_", "gpointer"));
914 generate_cparameters (m
, cfile
, cparam_map
, function
, null, null, null, 1);
916 push_function (function
);
918 generate_marshalling (m
, CallType
.ASYNC
, dbus_iface_name
, get_dbus_name_for_member (m
), get_dbus_timeout_for_member (m
));
922 cfile
.add_function_declaration (function
);
923 cfile
.add_function (function
);
928 string generate_finish_dbus_proxy_method (Interface main_iface
, Interface iface
, Method m
) {
929 string proxy_name
= "%sproxy_%s_finish".printf (get_ccode_lower_case_prefix (main_iface
), m
.name
);
931 var function
= new
CCodeFunction (proxy_name
);
932 function
.modifiers
= CCodeModifiers
.STATIC
;
934 var cparam_map
= new HashMap
<int,CCodeParameter
> (direct_hash
, direct_equal
);
936 cparam_map
.set (get_param_pos (0.1), new
CCodeParameter ("_res_", "GAsyncResult*"));
938 generate_cparameters (m
, cfile
, cparam_map
, function
, null, null, null, 2);
940 push_function (function
);
942 generate_marshalling (m
, CallType
.FINISH
, null, null, -1);
946 cfile
.add_function_declaration (function
);
947 cfile
.add_function (function
);
952 string generate_dbus_proxy_property_get (Interface main_iface
, Interface iface
, Property prop
) {
953 string proxy_name
= "%sdbus_proxy_get_%s".printf (get_ccode_lower_case_prefix (main_iface
), prop
.name
);
955 string dbus_iface_name
= get_dbus_name (iface
);
957 var owned_type
= prop
.get_accessor
.value_type
.copy ();
958 owned_type
.value_owned
= true;
959 if (owned_type
.is_disposable () && !prop
.get_accessor
.value_type
.value_owned
) {
960 Report
.error (prop
.get_accessor
.value_type
.source_reference
, "Properties used in D-Bus clients require owned get accessor");
963 var array_type
= prop
.get_accessor
.value_type as ArrayType
;
965 var function
= new
CCodeFunction (proxy_name
);
966 function
.modifiers
= CCodeModifiers
.STATIC
;
968 function
.add_parameter (new
CCodeParameter ("self", "%s*".printf (get_ccode_name (iface
))));
970 if (prop
.property_type
.is_real_non_null_struct_type ()) {
971 function
.add_parameter (new
CCodeParameter ("result", "%s*".printf (get_ccode_name (prop
.get_accessor
.value_type
))));
973 if (array_type
!= null) {
974 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
975 function
.add_parameter (new
CCodeParameter ("result_length%d".printf (dim
), "int*"));
979 function
.return_type
= get_ccode_name (prop
.get_accessor
.value_type
);
982 push_function (function
);
984 ccode
.add_declaration ("GVariant", new
CCodeVariableDeclarator ("*_inner_reply"));
986 // first try cached value
987 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_proxy_get_cached_property"));
988 ccall
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "GDBusProxy *"));
989 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
990 ccode
.add_assignment (new
CCodeIdentifier ("_inner_reply"), ccall
);
992 // if not successful, retrieve value via D-Bus
993 ccode
.open_if (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("_inner_reply")));
995 ccode
.add_declaration ("GVariant", new
CCodeVariableDeclarator ("*_arguments"));
996 ccode
.add_declaration ("GVariant", new
CCodeVariableDeclarator ("*_reply"));
997 ccode
.add_declaration ("GVariantBuilder", new
CCodeVariableDeclarator ("_arguments_builder"));
999 var builder_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_init"));
1000 builder_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
1001 builder_init
.add_argument (new
CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
1002 ccode
.add_expression (builder_init
);
1005 write_expression (string_type
, new
CCodeIdentifier ("_arguments_builder"), new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)), null);
1007 write_expression (string_type
, new
CCodeIdentifier ("_arguments_builder"), new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))), null);
1009 var builder_end
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_end"));
1010 builder_end
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
1011 ccode
.add_assignment (new
CCodeIdentifier ("_arguments"), builder_end
);
1013 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_proxy_call_sync"));
1014 ccall
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "GDBusProxy *"));
1015 ccall
.add_argument (new
CCodeConstant ("\"org.freedesktop.DBus.Properties.Get\""));
1016 ccall
.add_argument (new
CCodeIdentifier ("_arguments"));
1017 ccall
.add_argument (new
CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
1018 ccall
.add_argument (get_dbus_timeout (prop
));
1019 ccall
.add_argument (new
CCodeConstant ("NULL"));
1020 ccall
.add_argument (new
CCodeConstant ("NULL"));
1022 ccode
.add_assignment (new
CCodeIdentifier ("_reply"), ccall
);
1025 ccode
.open_if (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("_reply")));
1026 return_default_value (prop
.property_type
);
1029 var get_variant
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_get"));
1030 get_variant
.add_argument (new
CCodeIdentifier ("_reply"));
1031 get_variant
.add_argument (new
CCodeConstant ("\"(v)\""));
1032 get_variant
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_inner_reply")));
1033 ccode
.add_expression (get_variant
);
1035 var unref_reply
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_unref"));
1036 unref_reply
.add_argument (new
CCodeIdentifier ("_reply"));
1037 ccode
.add_expression (unref_reply
);
1041 if (prop
.property_type
.is_real_non_null_struct_type ()) {
1042 var target
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result"));
1043 var result
= deserialize_expression (prop
.get_accessor
.value_type
, new
CCodeIdentifier ("_inner_reply"), target
);
1044 ccode
.add_assignment (target
, result
);
1046 ccode
.add_declaration (get_ccode_name (prop
.get_accessor
.value_type
), new
CCodeVariableDeclarator ("_result"));
1048 if (get_dbus_signature (prop
) != null) {
1050 ccode
.add_assignment (new
CCodeIdentifier ("_result"), new
CCodeIdentifier("_inner_reply"));
1052 if (array_type
!= null) {
1053 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1054 ccode
.add_declaration ("int", new
CCodeVariableDeclarator ("_result_length%d".printf (dim
), new
CCodeConstant ("0")));
1058 var result
= deserialize_expression (prop
.get_accessor
.value_type
, new
CCodeIdentifier ("_inner_reply"), new
CCodeIdentifier ("_result"));
1059 ccode
.add_assignment (new
CCodeIdentifier ("_result"), result
);
1061 if (array_type
!= null) {
1062 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1063 // TODO check that parameter is not NULL (out parameters are optional)
1064 ccode
.add_assignment (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result_length%d".printf (dim
))), new
CCodeIdentifier ("_result_length%d".printf (dim
)));
1070 if (prop
.property_type
.is_real_non_null_struct_type () || get_dbus_signature (prop
) == null) {
1071 unref_reply
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_unref"));
1072 unref_reply
.add_argument (new
CCodeIdentifier ("_inner_reply"));
1073 ccode
.add_expression (unref_reply
);
1076 if (prop
.property_type
.is_real_non_null_struct_type ()) {
1077 ccode
.add_return ();
1079 ccode
.add_return (new
CCodeIdentifier ("_result"));
1084 cfile
.add_function_declaration (function
);
1085 cfile
.add_function (function
);
1090 string generate_dbus_proxy_property_set (Interface main_iface
, Interface iface
, Property prop
) {
1091 string proxy_name
= "%sdbus_proxy_set_%s".printf (get_ccode_lower_case_prefix (main_iface
), prop
.name
);
1093 string dbus_iface_name
= get_dbus_name (iface
);
1095 var array_type
= prop
.set_accessor
.value_type as ArrayType
;
1097 var function
= new
CCodeFunction (proxy_name
);
1098 function
.modifiers
= CCodeModifiers
.STATIC
;
1100 function
.add_parameter (new
CCodeParameter ("self", "%s*".printf (get_ccode_name (iface
))));
1102 if (prop
.property_type
.is_real_non_null_struct_type ()) {
1103 function
.add_parameter (new
CCodeParameter ("value", "%s*".printf (get_ccode_name (prop
.set_accessor
.value_type
))));
1105 function
.add_parameter (new
CCodeParameter ("value", get_ccode_name (prop
.set_accessor
.value_type
)));
1107 if (array_type
!= null) {
1108 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1109 function
.add_parameter (new
CCodeParameter ("value_length%d".printf (dim
), "int"));
1114 push_function (function
);
1116 ccode
.add_declaration ("GVariant", new
CCodeVariableDeclarator ("*_arguments"));
1117 ccode
.add_declaration ("GVariant", new
CCodeVariableDeclarator ("*_reply"));
1119 ccode
.add_declaration ("GVariantBuilder", new
CCodeVariableDeclarator ("_arguments_builder"));
1121 var builder_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_init"));
1122 builder_init
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
1123 builder_init
.add_argument (new
CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
1124 ccode
.add_expression (builder_init
);
1127 write_expression (string_type
, new
CCodeIdentifier ("_arguments_builder"), new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)), null);
1129 write_expression (string_type
, new
CCodeIdentifier ("_arguments_builder"), new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))), null);
1131 // property value (as variant)
1132 var builder_open
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_open"));
1133 builder_open
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
1134 builder_open
.add_argument (new
CCodeIdentifier ("G_VARIANT_TYPE_VARIANT"));
1135 ccode
.add_expression (builder_open
);
1137 if (prop
.property_type
.is_real_non_null_struct_type ()) {
1138 write_expression (prop
.set_accessor
.value_type
, new
CCodeIdentifier ("_arguments_builder"), new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("value")), prop
);
1140 write_expression (prop
.set_accessor
.value_type
, new
CCodeIdentifier ("_arguments_builder"), new
CCodeIdentifier ("value"), prop
);
1143 var builder_close
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_close"));
1144 builder_close
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
1145 ccode
.add_expression (builder_close
);
1147 var builder_end
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_builder_end"));
1148 builder_end
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_arguments_builder")));
1149 ccode
.add_assignment (new
CCodeIdentifier ("_arguments"), builder_end
);
1151 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_dbus_proxy_call_sync"));
1152 ccall
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "GDBusProxy *"));
1153 ccall
.add_argument (new
CCodeConstant ("\"org.freedesktop.DBus.Properties.Set\""));
1154 ccall
.add_argument (new
CCodeIdentifier ("_arguments"));
1155 ccall
.add_argument (new
CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
1156 ccall
.add_argument (get_dbus_timeout (prop
));
1157 ccall
.add_argument (new
CCodeConstant ("NULL"));
1158 ccall
.add_argument (new
CCodeConstant ("NULL"));
1160 ccode
.add_assignment (new
CCodeIdentifier ("_reply"), ccall
);
1163 ccode
.open_if (new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, new
CCodeIdentifier ("_reply")));
1164 ccode
.add_return ();
1167 var unref_reply
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_variant_unref"));
1168 unref_reply
.add_argument (new
CCodeIdentifier ("_reply"));
1169 ccode
.add_expression (unref_reply
);
1173 cfile
.add_function_declaration (function
);
1174 cfile
.add_function (function
);
1179 public override void register_dbus_info (CCodeBlock block
, ObjectTypeSymbol sym
) {
1180 if (!(sym is Interface
)) {
1184 string dbus_iface_name
= get_dbus_name (sym
);
1185 if (dbus_iface_name
== null) {
1189 var quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
1190 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-proxy-type\""));
1192 var proxy_type
= new
CCodeIdentifier (get_ccode_lower_case_prefix (sym
) + "proxy_get_type");
1194 var set_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_set_qdata"));
1195 set_qdata
.add_argument (new
CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym
, null))));
1196 set_qdata
.add_argument (quark
);
1197 set_qdata
.add_argument (new
CCodeCastExpression (proxy_type
, "void*"));
1199 block
.add_statement (new
CCodeExpressionStatement (set_qdata
));
1201 quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
1202 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-interface-name\""));
1204 set_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_set_qdata"));
1205 set_qdata
.add_argument (new
CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym
, null))));
1206 set_qdata
.add_argument (quark
);
1207 set_qdata
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
1209 block
.add_statement (new
CCodeExpressionStatement (set_qdata
));
1211 quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
1212 quark
.add_argument (new
CCodeConstant ("\"vala-dbus-interface-info\""));
1214 set_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_set_qdata"));
1215 set_qdata
.add_argument (new
CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym
, null))));
1216 set_qdata
.add_argument (quark
);
1217 set_qdata
.add_argument (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_interface_info (sym
)), "void*"));
1219 block
.add_statement (new
CCodeExpressionStatement (set_qdata
));