Line data Source code
1 : /* valagdbusclientmodule.vala
2 : *
3 : * Copyright (C) 2010-2011 Jürg Billeter
4 : *
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.
9 :
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.
14 :
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
18 : *
19 : * Author:
20 : * Jürg Billeter <j@bitron.ch>
21 : * Philip Van Hoof <pvanhoof@gnome.org>
22 : */
23 :
24 2914 : public class Vala.GDBusClientModule : GDBusModule {
25 : enum CallType {
26 : SYNC,
27 : ASYNC,
28 : FINISH,
29 : NO_REPLY
30 : }
31 :
32 36 : public CCodeConstant get_dbus_timeout (Symbol symbol) {
33 36 : int timeout = -1;
34 :
35 16990 : var dbus = symbol.get_attribute ("DBus");
36 36 : if (dbus != null && dbus.has_argument ("timeout")) {
37 0 : timeout = dbus.get_integer ("timeout");
38 36 : } else if (symbol.parent_symbol != null) {
39 24 : return get_dbus_timeout (symbol.parent_symbol);
40 : }
41 :
42 12 : return new CCodeConstant (timeout.to_string ());
43 : }
44 :
45 2 : public override void generate_dynamic_method_wrapper (DynamicMethod method) {
46 1 : var func = new CCodeFunction (get_ccode_name (method));
47 1 : func.modifiers = CCodeModifiers.STATIC;
48 :
49 1 : var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
50 :
51 1 : generate_cparameters (method, cfile, cparam_map, func);
52 :
53 1 : push_function (func);
54 :
55 1 : if (method.dynamic_type.type_symbol == dbus_proxy_type) {
56 1 : generate_marshalling (method, CallType.SYNC, null, method.name, -1);
57 : } else {
58 0 : Report.error (method.source_reference, "dynamic methods are not supported for `%s'", method.dynamic_type.to_string ());
59 : }
60 :
61 1 : pop_function ();
62 :
63 1 : cfile.add_function_declaration (func);
64 1 : cfile.add_function (func);
65 : }
66 :
67 54 : void generate_proxy_interface_init (Interface main_iface, Interface iface) {
68 : // also generate proxy for prerequisites
69 81 : foreach (var prereq in iface.get_prerequisites ()) {
70 27 : if (prereq.type_symbol is Interface) {
71 0 : generate_proxy_interface_init (main_iface, (Interface) prereq.type_symbol);
72 : }
73 : }
74 :
75 27 : string lower_cname = get_ccode_lower_case_prefix (main_iface) + "proxy";
76 :
77 27 : var proxy_iface_init = new CCodeFunction (lower_cname + "_" + get_ccode_lower_case_prefix (iface) + "interface_init", "void");
78 27 : proxy_iface_init.add_parameter (new CCodeParameter ("iface", get_ccode_name (iface) + "Iface*"));
79 :
80 27 : push_function (proxy_iface_init);
81 :
82 127 : foreach (Method m in iface.get_methods ()) {
83 50 : if (!m.is_abstract) {
84 0 : continue;
85 : }
86 :
87 50 : var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), get_ccode_vfunc_name (m));
88 50 : if (!m.coroutine) {
89 37 : ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_method (main_iface, iface, m)));
90 : } else {
91 13 : ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_async_dbus_proxy_method (main_iface, iface, m)));
92 13 : vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), get_ccode_finish_vfunc_name (m));
93 13 : ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_finish_dbus_proxy_method (main_iface, iface, m)));
94 : }
95 : }
96 :
97 39 : foreach (Property prop in iface.get_properties ()) {
98 6 : if (!prop.is_abstract) {
99 0 : continue;
100 : }
101 :
102 12 : if (prop.get_accessor != null) {
103 6 : var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "get_" + prop.name);
104 6 : ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_get (main_iface, iface, prop)));
105 : }
106 12 : if (prop.set_accessor != null) {
107 6 : var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "set_" + prop.name);
108 6 : ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_set (main_iface, iface, prop)));
109 : }
110 : }
111 :
112 27 : proxy_iface_init.modifiers = CCodeModifiers.STATIC;
113 27 : pop_function ();
114 27 : cfile.add_function_declaration (proxy_iface_init);
115 27 : cfile.add_function (proxy_iface_init);
116 : }
117 :
118 27 : string implement_interface (CCodeFunctionCall define_type, Interface main_iface, Interface iface) {
119 27 : string result = "";
120 :
121 : // also implement prerequisites
122 81 : foreach (var prereq in iface.get_prerequisites ()) {
123 27 : if (prereq.type_symbol is Interface) {
124 0 : result += implement_interface (define_type, main_iface, (Interface) prereq.type_symbol);
125 : }
126 : }
127 :
128 : string interface_macro;
129 :
130 27 : if (in_plugin) {
131 0 : interface_macro = "G_IMPLEMENT_INTERFACE_DYNAMIC";
132 : } else {
133 27 : interface_macro = "G_IMPLEMENT_INTERFACE";
134 : }
135 :
136 27 : result += "%s (%s, %sproxy_%sinterface_init) ".printf (
137 : interface_macro,
138 : get_ccode_upper_case_name (iface, "TYPE_"),
139 : get_ccode_lower_case_prefix (main_iface),
140 : get_ccode_lower_case_prefix (iface));
141 27 : return result;
142 : }
143 :
144 4533 : public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
145 4474 : base.generate_interface_declaration (iface, decl_space);
146 :
147 4474 : string dbus_iface_name = get_dbus_name (iface);
148 4474 : if (dbus_iface_name == null) {
149 3803 : return;
150 : }
151 :
152 671 : string get_type_name = "%sproxy_get_type".printf (get_ccode_lower_case_prefix (iface));
153 :
154 671 : if (add_symbol_declaration (decl_space, iface, get_type_name)) {
155 612 : return;
156 : }
157 :
158 59 : decl_space.add_type_declaration (new CCodeNewline ());
159 59 : var macro = "(%s ())".printf (get_type_name);
160 59 : decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_PROXY".printf (get_ccode_type_id (iface)), macro));
161 :
162 : // declare proxy_get_type function
163 59 : var proxy_get_type = new CCodeFunction (get_type_name, "GType");
164 59 : proxy_get_type.modifiers = CCodeModifiers.CONST | CCodeModifiers.EXTERN;
165 59 : requires_vala_extern = true;
166 :
167 59 : decl_space.add_function_declaration (proxy_get_type);
168 :
169 59 : if (in_plugin) {
170 0 : var proxy_register_type = new CCodeFunction ("%sproxy_register_dynamic_type".printf (get_ccode_lower_case_prefix (iface)));
171 0 : proxy_register_type.add_parameter (new CCodeParameter ("module", "GTypeModule*"));
172 0 : proxy_register_type.modifiers |= CCodeModifiers.EXTERN;
173 0 : requires_vala_extern = true;
174 :
175 0 : decl_space.add_function_declaration (proxy_register_type);
176 : }
177 : }
178 :
179 145 : public override void visit_interface (Interface iface) {
180 118 : base.visit_interface (iface);
181 :
182 118 : string dbus_iface_name = get_dbus_name (iface);
183 118 : if (dbus_iface_name == null) {
184 91 : return;
185 : }
186 :
187 27 : cfile.add_include ("gio/gio.h");
188 :
189 : // create proxy class
190 27 : string cname = get_ccode_name (iface) + "Proxy";
191 27 : string lower_cname = get_ccode_lower_case_prefix (iface) + "proxy";
192 :
193 27 : cfile.add_type_declaration (new CCodeTypeDefinition ("GDBusProxy", new CCodeVariableDeclarator (cname)));
194 27 : cfile.add_type_declaration (new CCodeTypeDefinition ("GDBusProxyClass", new CCodeVariableDeclarator (cname + "Class")));
195 :
196 : string type_macro;
197 :
198 27 : if (in_plugin) {
199 0 : type_macro = "G_DEFINE_DYNAMIC_TYPE_EXTENDED";
200 : } else {
201 27 : type_macro = "G_DEFINE_TYPE_EXTENDED";
202 : }
203 :
204 27 : var define_type = new CCodeFunctionCall (new CCodeIdentifier (type_macro));
205 27 : define_type.add_argument (new CCodeIdentifier (cname));
206 27 : define_type.add_argument (new CCodeIdentifier (lower_cname));
207 27 : define_type.add_argument (new CCodeIdentifier ("G_TYPE_DBUS_PROXY"));
208 27 : define_type.add_argument (new CCodeConstant ("0"));
209 27 : define_type.add_argument (new CCodeIdentifier (implement_interface (define_type, iface, iface)));
210 :
211 27 : cfile.add_type_member_definition (define_type);
212 :
213 27 : var proxy_class_init = new CCodeFunction (lower_cname + "_class_init", "void");
214 27 : proxy_class_init.add_parameter (new CCodeParameter ("klass", cname + "Class*"));
215 27 : proxy_class_init.modifiers = CCodeModifiers.STATIC;
216 27 : push_function (proxy_class_init);
217 27 : var proxy_class = new CCodeFunctionCall (new CCodeIdentifier ("G_DBUS_PROXY_CLASS"));
218 27 : proxy_class.add_argument (new CCodeIdentifier ("klass"));
219 27 : ccode.add_assignment (new CCodeMemberAccess.pointer (proxy_class, "g_signal"), new CCodeIdentifier (lower_cname + "_g_signal"));
220 27 : pop_function ();
221 27 : cfile.add_function (proxy_class_init);
222 :
223 27 : generate_signal_handler_function (iface);
224 :
225 27 : if (in_plugin) {
226 0 : var proxy_class_finalize = new CCodeFunction (lower_cname + "_class_finalize", "void");
227 0 : proxy_class_finalize.add_parameter (new CCodeParameter ("klass", cname + "Class*"));
228 0 : proxy_class_finalize.modifiers = CCodeModifiers.STATIC;
229 0 : cfile.add_function (proxy_class_finalize);
230 :
231 0 : var proxy_type_init = new CCodeFunction (lower_cname + "_register_dynamic_type", "void");
232 0 : proxy_type_init.add_parameter (new CCodeParameter ("module", "GTypeModule*"));
233 0 : push_function (proxy_type_init);
234 0 : var call_register_type = new CCodeFunctionCall (new CCodeIdentifier (lower_cname + "_register_type"));
235 0 : call_register_type.add_argument (new CCodeIdentifier ("module"));
236 0 : ccode.add_expression (call_register_type);
237 0 : pop_function ();
238 0 : cfile.add_function(proxy_type_init);
239 : }
240 :
241 27 : var proxy_instance_init = new CCodeFunction (lower_cname + "_init", "void");
242 27 : proxy_instance_init.add_parameter (new CCodeParameter ("self", cname + "*"));
243 27 : proxy_instance_init.modifiers = CCodeModifiers.STATIC;
244 27 : push_function (proxy_instance_init);
245 :
246 : // TODO Replaces setting of "vala-dbus-interface-info"
247 27 : var dbus_proxy_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_DBUS_PROXY"));
248 27 : dbus_proxy_cast.add_argument (new CCodeIdentifier ("self"));
249 27 : var set_interface_info = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_set_interface_info"));
250 27 : set_interface_info.add_argument (dbus_proxy_cast);
251 27 : set_interface_info.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (iface)), "GDBusInterfaceInfo *"));
252 27 : ccode.add_expression (set_interface_info);
253 :
254 27 : pop_function ();
255 27 : cfile.add_function (proxy_instance_init);
256 :
257 27 : generate_proxy_interface_init (iface, iface);
258 : }
259 :
260 17596 : public override void visit_method_call (MethodCall expr) {
261 17573 : var mtype = expr.call.value_type as MethodType;
262 16800 : bool bus_get_proxy_async = (mtype != null && get_ccode_name (mtype.method_symbol) == "g_bus_get_proxy");
263 16800 : bool bus_get_proxy_sync = (mtype != null && get_ccode_name (mtype.method_symbol) == "g_bus_get_proxy_sync");
264 16800 : bool conn_get_proxy_async = (mtype != null && get_ccode_name (mtype.method_symbol) == "g_dbus_connection_get_proxy");
265 16800 : bool conn_get_proxy_sync = (mtype != null && get_ccode_name (mtype.method_symbol) == "g_dbus_connection_get_proxy_sync");
266 17573 : if (!bus_get_proxy_async && !bus_get_proxy_sync && !conn_get_proxy_async && !conn_get_proxy_sync) {
267 17546 : base.visit_method_call (expr);
268 17546 : return;
269 : }
270 :
271 27 : var ma = (MemberAccess) expr.call;
272 27 : var type_arg = ma.get_type_arguments ().get (0);
273 :
274 : CCodeExpression proxy_type;
275 : CCodeExpression dbus_iface_name;
276 :
277 27 : var object_type = type_arg as ObjectType;
278 54 : if (object_type != null) {
279 26 : var iface = (Interface) object_type.type_symbol;
280 :
281 26 : if (get_dbus_name (iface) == null) {
282 0 : Report.error (expr.source_reference, "`%s' is not a D-Bus interface", iface.get_full_name ());
283 0 : return;
284 : }
285 :
286 26 : proxy_type = new CCodeIdentifier ("%s_PROXY".printf (get_ccode_type_id (iface)));
287 26 : dbus_iface_name = new CCodeConstant ("\"%s\"".printf (get_dbus_name (iface)));
288 : } else {
289 : // use runtime type information for generic methods
290 :
291 1 : var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
292 1 : quark.add_argument (new CCodeConstant ("\"vala-dbus-proxy-type\""));
293 :
294 1 : var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
295 1 : get_qdata.add_argument (get_type_id_expression (type_arg));
296 1 : get_qdata.add_argument (quark);
297 :
298 1 : proxy_type = new CCodeFunctionCall (new CCodeCastExpression (get_qdata, "GType (*) (void)"));
299 :
300 1 : quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
301 1 : quark.add_argument (new CCodeConstant ("\"vala-dbus-interface-name\""));
302 :
303 1 : get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata"));
304 1 : get_qdata.add_argument (get_type_id_expression (type_arg));
305 1 : get_qdata.add_argument (quark);
306 :
307 3 : dbus_iface_name = get_qdata;
308 : }
309 :
310 27 : if (bus_get_proxy_async || conn_get_proxy_async) {
311 10 : if (ma.member_name == "end" && ma.inner.symbol_reference == ma.symbol_reference) {
312 : // method can fail
313 2 : current_method_inner_error = true;
314 :
315 27 : var args = expr.get_argument_list ();
316 2 : Expression res = args.get (0);
317 :
318 2 : var source_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
319 2 : var source_ref = get_variable_cexpression (source_var.name);
320 2 : emit_temp_var (source_var);
321 2 : var source = new CCodeFunctionCall (new CCodeIdentifier ("g_async_result_get_source_object"));
322 2 : source.add_argument (get_cvalue (res));
323 2 : ccode.add_assignment (source_ref, source);
324 :
325 2 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_async_initable_new_finish"));
326 2 : ccall.add_argument (new CCodeCastExpression (source_ref, "GAsyncInitable *"));
327 2 : ccall.add_argument (get_cvalue (res));
328 2 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ()));
329 :
330 2 : var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
331 2 : var temp_ref = get_variable_cexpression (temp_var.name);
332 2 : emit_temp_var (temp_var);
333 2 : ccode.add_assignment (temp_ref, new CCodeCastExpression (ccall, get_ccode_name (expr.value_type)));
334 :
335 : // g_async_result_get_source_object transfers ownership, unref after use
336 2 : var unref_proxy = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
337 2 : unref_proxy.add_argument (source_ref);
338 2 : ccode.add_expression (unref_proxy);
339 :
340 2 : set_cvalue (expr, temp_ref);
341 :
342 2 : return;
343 : }
344 : }
345 :
346 25 : var base_arg_index = 0;
347 25 : if (bus_get_proxy_async || bus_get_proxy_sync)
348 22 : base_arg_index = 1;
349 :
350 25 : var args = expr.get_argument_list ();
351 25 : Expression name = args.get (base_arg_index + 0);
352 25 : Expression object_path = args.get (base_arg_index + 1);
353 25 : Expression flags = args.get (base_arg_index + 2);
354 25 : Expression cancellable = args.get (base_arg_index + 3);
355 :
356 : // method can fail
357 25 : current_method_inner_error = true;
358 :
359 : CCodeFunctionCall ccall;
360 25 : if (bus_get_proxy_async || conn_get_proxy_async) {
361 8 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_async_initable_new_async"));
362 : } else {
363 17 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_initable_new"));
364 : }
365 25 : ccall.add_argument (proxy_type);
366 25 : if (bus_get_proxy_async || conn_get_proxy_async) {
367 : // I/O priority
368 8 : ccall.add_argument (new CCodeConstant ("0"));
369 : }
370 25 : ccall.add_argument (get_cvalue (cancellable));
371 25 : if (bus_get_proxy_async || conn_get_proxy_async) {
372 10 : if (expr.is_yield_expression) {
373 : // asynchronous call
374 6 : ccall.add_argument (new CCodeIdentifier (generate_ready_function (current_method)));
375 6 : ccall.add_argument (new CCodeIdentifier ("_data_"));
376 : } else {
377 : // begin
378 2 : Expression callback = args.get (base_arg_index + 4);
379 2 : ccall.add_argument (get_cvalue (callback));
380 2 : ccall.add_argument (get_delegate_target (callback));
381 : }
382 : } else {
383 17 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ()));
384 : }
385 25 : ccall.add_argument (new CCodeConstant ("\"g-flags\""));
386 25 : ccall.add_argument (get_cvalue (flags));
387 25 : ccall.add_argument (new CCodeConstant ("\"g-name\""));
388 25 : ccall.add_argument (get_cvalue (name));
389 50 : if (bus_get_proxy_async || bus_get_proxy_sync) {
390 22 : Expression bus_type = args.get (0);
391 22 : ccall.add_argument (new CCodeConstant ("\"g-bus-type\""));
392 22 : ccall.add_argument (get_cvalue (bus_type));
393 : } else {
394 3 : Expression connection = ma.inner;
395 4 : if (ma.member_name == "begin" && ma.inner.symbol_reference == ma.symbol_reference) {
396 1 : var inner_ma = (MemberAccess) ma.inner;
397 2 : connection = inner_ma.inner;
398 : }
399 3 : ccall.add_argument (new CCodeConstant ("\"g-connection\""));
400 3 : ccall.add_argument (get_cvalue (connection));
401 : }
402 25 : ccall.add_argument (new CCodeConstant ("\"g-object-path\""));
403 25 : ccall.add_argument (get_cvalue (object_path));
404 25 : ccall.add_argument (new CCodeConstant ("\"g-interface-name\""));
405 25 : ccall.add_argument (dbus_iface_name);
406 25 : ccall.add_argument (new CCodeConstant ("NULL"));
407 :
408 25 : if (bus_get_proxy_async || conn_get_proxy_async) {
409 8 : if (expr.is_yield_expression) {
410 6 : int state = emit_context.next_coroutine_state++;
411 :
412 6 : ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ()));
413 6 : ccode.add_expression (ccall);
414 6 : ccode.add_return (new CCodeConstant ("FALSE"));
415 6 : ccode.add_label ("_state_%d".printf (state));
416 :
417 6 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_async_initable_new_finish"));
418 6 : ccall.add_argument (new CCodeCastExpression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_source_object_"), "GAsyncInitable *"));
419 : // pass GAsyncResult stored in closure to finish function
420 6 : ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_res_"));
421 6 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ()));
422 : } else {
423 : // begin
424 2 : ccode.add_expression (ccall);
425 2 : return;
426 : }
427 : }
428 :
429 23 : var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned);
430 23 : var temp_ref = get_variable_cexpression (temp_var.name);
431 :
432 23 : emit_temp_var (temp_var);
433 :
434 23 : ccode.add_assignment (temp_ref, new CCodeCastExpression (ccall, get_ccode_name (expr.value_type)));
435 23 : set_cvalue (expr, temp_ref);
436 : }
437 :
438 5 : string generate_dbus_signal_handler (Signal sig, ObjectTypeSymbol sym) {
439 5 : string wrapper_name = "_dbus_handle_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig));
440 :
441 5 : var function = new CCodeFunction (wrapper_name);
442 5 : function.modifiers = CCodeModifiers.STATIC;
443 5 : function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
444 5 : function.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
445 :
446 5 : push_function (function);
447 :
448 5 : ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_arguments_iter"));
449 :
450 5 : var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
451 5 : iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter")));
452 5 : iter_init.add_argument (new CCodeIdentifier ("parameters"));
453 5 : ccode.add_expression (iter_init);
454 :
455 5 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
456 5 : ccall.add_argument (new CCodeIdentifier ("self"));
457 5 : ccall.add_argument (get_signal_canonical_constant (sig));
458 :
459 15 : foreach (Parameter param in sig.get_parameters ()) {
460 5 : var param_name = get_variable_cname (param.name);
461 5 : var owned_type = param.variable_type.copy ();
462 5 : owned_type.value_owned = true;
463 :
464 5 : ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true)));
465 :
466 5 : unowned Struct? st = param.variable_type.type_symbol as Struct;
467 5 : if (st != null && !st.is_simple_type ()) {
468 0 : ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param_name)));
469 : } else {
470 5 : ccall.add_argument (new CCodeIdentifier (param_name));
471 : }
472 :
473 6 : if (param.variable_type is ArrayType) {
474 1 : var array_type = (ArrayType) param.variable_type;
475 1 : var length_ctype = get_ccode_array_length_type (array_type);
476 :
477 2 : for (int dim = 1; dim <= array_type.rank; dim++) {
478 1 : string length_cname = get_variable_array_length_cname (param, dim);
479 :
480 1 : ccode.add_declaration (length_ctype, new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
481 1 : ccall.add_argument (new CCodeIdentifier (length_cname));
482 : }
483 : }
484 :
485 5 : read_expression (param.variable_type, new CCodeIdentifier ("_arguments_iter"), new CCodeIdentifier (param_name), param);
486 : }
487 :
488 5 : ccode.add_expression (ccall);
489 :
490 15 : foreach (Parameter param in sig.get_parameters ()) {
491 5 : var owned_type = param.variable_type.copy ();
492 5 : owned_type.value_owned = true;
493 :
494 8 : if (requires_destroy (owned_type)) {
495 : // keep local alive (symbol_reference is weak)
496 3 : var local = new LocalVariable (owned_type, param.name);
497 3 : ccode.add_expression (destroy_local (local));
498 : }
499 : }
500 :
501 5 : pop_function ();
502 :
503 5 : cfile.add_function_declaration (function);
504 5 : cfile.add_function (function);
505 :
506 5 : return wrapper_name;
507 : }
508 :
509 54 : void generate_signal_handler_function (ObjectTypeSymbol sym) {
510 27 : var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "proxy_g_signal", "void");
511 27 : cfunc.add_parameter (new CCodeParameter ("proxy", "GDBusProxy*"));
512 27 : cfunc.add_parameter (new CCodeParameter ("sender_name", "const gchar*"));
513 27 : cfunc.add_parameter (new CCodeParameter ("signal_name", "const gchar*"));
514 27 : cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
515 :
516 27 : cfunc.modifiers |= CCodeModifiers.STATIC;
517 :
518 27 : cfile.add_function_declaration (cfunc);
519 :
520 27 : push_function (cfunc);
521 :
522 27 : bool firstif = true;
523 :
524 38 : foreach (Signal sig in sym.get_signals ()) {
525 6 : if (sig.access != SymbolAccessibility.PUBLIC) {
526 1 : continue;
527 : }
528 :
529 5 : cfile.add_include ("string.h");
530 :
531 5 : var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
532 5 : ccheck.add_argument (new CCodeIdentifier ("signal_name"));
533 5 : ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
534 :
535 5 : var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"));
536 5 : if (firstif) {
537 4 : ccode.open_if (cond);
538 4 : firstif = false;
539 : } else {
540 1 : ccode.else_if (cond);
541 : }
542 :
543 5 : var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_signal_handler (sig, sym)));
544 5 : ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("proxy"), get_ccode_name (sym) + "*"));
545 5 : ccall.add_argument (new CCodeIdentifier ("parameters"));
546 :
547 5 : ccode.add_expression (ccall);
548 : }
549 27 : if (!firstif) {
550 4 : ccode.close ();
551 : }
552 :
553 27 : pop_function ();
554 :
555 27 : cfile.add_function (cfunc);
556 : }
557 :
558 128 : void generate_marshalling (Method m, CallType call_type, string? iface_name, string? method_name, int method_timeout) {
559 64 : var gdbusproxy = new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *");
560 :
561 64 : var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_connection"));
562 64 : connection.add_argument (gdbusproxy);
563 :
564 64 : bool uses_fd = dbus_method_uses_file_descriptor (m);
565 64 : if (uses_fd) {
566 4 : cfile.add_include ("gio/gunixfdlist.h");
567 4 : ccode.add_declaration ("GUnixFDList*", new CCodeVariableDeclarator ("_fd_list"));
568 : }
569 :
570 64 : bool has_error_argument = m.tree_can_fail;
571 : CCodeExpression error_argument;
572 64 : if (has_error_argument) {
573 60 : error_argument = new CCodeIdentifier ("error");
574 : } else {
575 4 : error_argument = new CCodeConstant ("NULL");
576 : }
577 :
578 128 : if (call_type != CallType.FINISH) {
579 51 : var destination = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_name"));
580 51 : destination.add_argument (gdbusproxy);
581 :
582 51 : var interface_name = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_interface_name"));
583 51 : interface_name.add_argument (gdbusproxy);
584 :
585 51 : var object_path = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_object_path"));
586 51 : object_path.add_argument (gdbusproxy);
587 :
588 : CCodeExpression timeout;
589 51 : if (method_timeout <= 0) {
590 51 : timeout = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_default_timeout"));
591 51 : ((CCodeFunctionCall) timeout).add_argument (gdbusproxy);
592 : } else {
593 0 : timeout = new CCodeConstant ("%d".printf (method_timeout));
594 : }
595 :
596 : // register errors
597 51 : var error_types = new ArrayList<DataType> ();
598 51 : m.get_error_types (error_types);
599 167 : foreach (var error_type in error_types) {
600 58 : var errtype = (ErrorType) error_type;
601 58 : if (errtype.error_domain != null) {
602 48 : ccode.add_expression (new CCodeIdentifier (get_ccode_upper_case_name (errtype.error_domain)));
603 : }
604 : }
605 :
606 : // build D-Bus message
607 :
608 51 : ccode.add_declaration ("GDBusMessage", new CCodeVariableDeclarator ("*_message"));
609 :
610 51 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_call"));
611 51 : ccall.add_argument (destination);
612 51 : ccall.add_argument (object_path);
613 51 : if (iface_name != null) {
614 50 : ccall.add_argument (new CCodeConstant ("\"%s\"".printf (iface_name)));
615 : } else {
616 1 : ccall.add_argument (interface_name);
617 : }
618 51 : ccall.add_argument (new CCodeConstant ("\"%s\"".printf (method_name)));
619 51 : ccode.add_assignment (new CCodeIdentifier ("_message"), ccall);
620 :
621 51 : ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
622 51 : ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
623 :
624 51 : var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
625 51 : builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
626 51 : builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
627 51 : ccode.add_expression (builder_init);
628 :
629 51 : if (uses_fd) {
630 3 : ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new")));
631 : }
632 :
633 51 : CCodeExpression cancellable = new CCodeConstant ("NULL");
634 :
635 145 : foreach (Parameter param in m.get_parameters ()) {
636 80 : if (param.direction == ParameterDirection.IN) {
637 34 : CCodeExpression expr = new CCodeIdentifier (get_variable_cname (param.name));
638 34 : if (param.variable_type.is_real_struct_type ()) {
639 1 : expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
640 : }
641 :
642 34 : if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") {
643 4 : cancellable = expr;
644 2 : continue;
645 : }
646 :
647 32 : if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") {
648 : // ignore BusName sender parameters
649 0 : continue;
650 : }
651 :
652 32 : send_dbus_value (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param);
653 : }
654 : }
655 :
656 51 : var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
657 51 : builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
658 51 : ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
659 :
660 51 : var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body"));
661 51 : set_body.add_argument (new CCodeIdentifier ("_message"));
662 51 : set_body.add_argument (new CCodeIdentifier ("_arguments"));
663 51 : ccode.add_expression (set_body);
664 :
665 51 : if (uses_fd) {
666 3 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list"));
667 3 : ccall.add_argument (new CCodeIdentifier ("_message"));
668 3 : ccall.add_argument (new CCodeIdentifier ("_fd_list"));
669 3 : ccode.add_expression (ccall);
670 :
671 3 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
672 3 : ccall.add_argument (new CCodeIdentifier ("_fd_list"));
673 3 : ccode.add_expression (ccall);
674 : }
675 :
676 : // send D-Bus message
677 :
678 51 : if (call_type == CallType.SYNC) {
679 37 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message_with_reply_sync"));
680 37 : ccall.add_argument (connection);
681 37 : ccall.add_argument (new CCodeIdentifier ("_message"));
682 37 : ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
683 37 : ccall.add_argument (timeout);
684 37 : ccall.add_argument (new CCodeConstant ("NULL"));
685 37 : ccall.add_argument (cancellable);
686 37 : ccall.add_argument (error_argument);
687 37 : ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
688 15 : } else if (call_type == CallType.NO_REPLY) {
689 1 : var set_flags = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_flags"));
690 1 : set_flags.add_argument (new CCodeIdentifier ("_message"));
691 1 : set_flags.add_argument (new CCodeConstant ("G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED"));
692 1 : ccode.add_expression (set_flags);
693 :
694 1 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
695 1 : ccall.add_argument (connection);
696 1 : ccall.add_argument (new CCodeIdentifier ("_message"));
697 1 : ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
698 1 : ccall.add_argument (new CCodeConstant ("NULL"));
699 1 : ccall.add_argument (error_argument);
700 1 : ccode.add_expression (ccall);
701 26 : } else if (call_type == CallType.ASYNC) {
702 13 : var callback_specified = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("_callback_"), new CCodeConstant ("NULL"));
703 13 : ccode.open_if (callback_specified);
704 :
705 13 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message_with_reply"));
706 13 : ccall.add_argument (connection);
707 13 : ccall.add_argument (new CCodeIdentifier ("_message"));
708 13 : ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
709 13 : ccall.add_argument (timeout);
710 13 : ccall.add_argument (new CCodeConstant ("NULL"));
711 13 : ccall.add_argument (cancellable);
712 :
713 13 : CCodeFunctionCall res_wrapper = null;
714 :
715 : // use wrapper as source_object wouldn't be correct otherwise
716 13 : ccall.add_argument (new CCodeIdentifier (generate_async_callback_wrapper ()));
717 13 : res_wrapper = new CCodeFunctionCall (new CCodeIdentifier ("g_task_new"));
718 13 : res_wrapper.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *"));
719 13 : res_wrapper.add_argument (new CCodeConstant ("NULL"));
720 13 : res_wrapper.add_argument (new CCodeIdentifier ("_callback_"));
721 13 : res_wrapper.add_argument (new CCodeIdentifier ("_user_data_"));
722 13 : ccall.add_argument (res_wrapper);
723 :
724 13 : ccode.add_expression (ccall);
725 :
726 13 : ccode.add_else ();
727 :
728 13 : var set_flags = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_flags"));
729 13 : set_flags.add_argument (new CCodeIdentifier ("_message"));
730 13 : set_flags.add_argument (new CCodeConstant ("G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED"));
731 13 : ccode.add_expression (set_flags);
732 :
733 13 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message"));
734 13 : ccall.add_argument (connection);
735 13 : ccall.add_argument (new CCodeIdentifier ("_message"));
736 13 : ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
737 13 : ccall.add_argument (new CCodeConstant ("NULL"));
738 13 : ccall.add_argument (new CCodeConstant ("NULL"));
739 13 : ccode.add_expression (ccall);
740 :
741 13 : ccode.close ();
742 : }
743 :
744 : // free D-Bus message
745 :
746 51 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
747 51 : ccall.add_argument (new CCodeIdentifier ("_message"));
748 51 : ccode.add_expression (ccall);
749 : } else {
750 13 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message_with_reply_finish"));
751 13 : ccall.add_argument (connection);
752 :
753 : // unwrap async result
754 13 : ccode.add_declaration ("GAsyncResult", new CCodeVariableDeclarator ("*_inner_res"));
755 :
756 13 : var inner_res = new CCodeFunctionCall (new CCodeIdentifier ("g_task_propagate_pointer"));
757 13 : inner_res.add_argument (new CCodeCastExpression (new CCodeIdentifier ("_res_"), "GTask *"));
758 13 : inner_res.add_argument (new CCodeConstant ("NULL"));
759 13 : ccode.add_assignment (new CCodeIdentifier ("_inner_res"), inner_res);
760 :
761 13 : ccall.add_argument (new CCodeIdentifier ("_inner_res"));
762 13 : ccall.add_argument (error_argument);
763 13 : ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
764 :
765 : // _inner_res is guaranteed to be non-NULL, so just unref it
766 13 : var unref_inner_res = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
767 13 : unref_inner_res.add_argument (new CCodeIdentifier ("_inner_res"));
768 13 : ccode.add_expression (unref_inner_res);
769 : }
770 :
771 114 : if (call_type == CallType.SYNC || call_type == CallType.FINISH) {
772 50 : ccode.add_declaration ("GDBusMessage", new CCodeVariableDeclarator ("*_reply_message"));
773 :
774 50 : var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
775 50 : unref_reply.add_argument (new CCodeIdentifier ("_reply_message"));
776 :
777 : // return on io error
778 50 : var reply_is_null = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply_message"));
779 50 : ccode.open_if (reply_is_null);
780 50 : return_default_value (m.return_type);
781 50 : ccode.close ();
782 :
783 : // return on remote error
784 50 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_to_gerror"));
785 50 : ccall.add_argument (new CCodeIdentifier ("_reply_message"));
786 50 : ccall.add_argument (error_argument);
787 50 : ccode.open_if (ccall);
788 50 : ccode.add_expression (unref_reply);
789 50 : return_default_value (m.return_type);
790 50 : ccode.close ();
791 :
792 50 : bool has_result = !(m.return_type is VoidType);
793 :
794 50 : if (uses_fd) {
795 3 : ccode.add_declaration ("gint", new CCodeVariableDeclarator.zero ("_fd_index", new CCodeConstant ("0")));
796 3 : ccode.add_declaration ("gint", new CCodeVariableDeclarator ("_fd"));
797 : }
798 :
799 144 : foreach (Parameter param in m.get_parameters ()) {
800 47 : if (param.direction == ParameterDirection.OUT) {
801 14 : has_result = true;
802 : }
803 : }
804 :
805 81 : if (has_result) {
806 31 : ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply"));
807 31 : ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_reply_iter"));
808 :
809 31 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_get_body"));
810 31 : ccall.add_argument (new CCodeIdentifier ("_reply_message"));
811 31 : ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall);
812 :
813 31 : var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
814 31 : iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_iter")));
815 31 : iter_init.add_argument (new CCodeIdentifier ("_reply"));
816 31 : ccode.add_expression (iter_init);
817 :
818 99 : foreach (Parameter param in m.get_parameters ()) {
819 48 : if (param.direction == ParameterDirection.OUT) {
820 14 : 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)));
821 :
822 14 : var array_type = param.variable_type as ArrayType;
823 4 : if (array_type != null) {
824 2 : var length_ctype = get_ccode_array_length_type (array_type);
825 4 : for (int dim = 1; dim <= array_type.rank; dim++) {
826 2 : ccode.add_declaration (length_ctype, new CCodeVariableDeclarator ("_vala_%s_length%d".printf (param.name, dim), new CCodeConstant ("0")));
827 : }
828 : }
829 :
830 14 : var target = new CCodeIdentifier ("_vala_%s".printf (param.name));
831 : bool may_fail;
832 :
833 14 : receive_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_message"), new CCodeIdentifier ("_reply_iter"), target, param, error_argument, out may_fail);
834 :
835 : // TODO check that parameter is not NULL (out parameters are optional)
836 : // free value if parameter is NULL
837 14 : ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_variable_cname (param.name))), target);
838 :
839 14 : if (array_type != null) {
840 4 : for (int dim = 1; dim <= array_type.rank; dim++) {
841 : // TODO check that parameter is not NULL (out parameters are optional)
842 2 : 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)));
843 : }
844 : }
845 :
846 14 : if (may_fail && has_error_argument) {
847 2 : ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("error"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error"))));
848 2 : ccode.add_expression (unref_reply);
849 2 : return_default_value (m.return_type);
850 2 : ccode.close ();
851 : }
852 : }
853 : }
854 :
855 31 : if (!(m.return_type is VoidType)) {
856 62 : if (m.return_type.is_real_non_null_struct_type ()) {
857 1 : var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
858 1 : receive_dbus_value (m.return_type, new CCodeIdentifier ("_reply_message"), new CCodeIdentifier ("_reply_iter"), target, m);
859 : } else {
860 30 : ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator.zero ("_result", default_value_for_type (m.return_type, true)));
861 :
862 30 : var array_type = m.return_type as ArrayType;
863 14 : if (array_type != null) {
864 7 : var length_ctype = get_ccode_array_length_type (array_type);
865 17 : for (int dim = 1; dim <= array_type.rank; dim++) {
866 10 : ccode.add_declaration (length_ctype, new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
867 : }
868 : }
869 :
870 : bool may_fail;
871 30 : receive_dbus_value (m.return_type, new CCodeIdentifier ("_reply_message"), new CCodeIdentifier ("_reply_iter"), new CCodeIdentifier ("_result"), m, new CCodeIdentifier ("error"), out may_fail);
872 :
873 30 : if (array_type != null) {
874 17 : for (int dim = 1; dim <= array_type.rank; dim++) {
875 : // TODO check that parameter is not NULL (out parameters are optional)
876 10 : ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim)));
877 : }
878 : }
879 :
880 30 : if (may_fail) {
881 2 : ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("error"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error"))));
882 2 : ccode.add_expression (unref_reply);
883 2 : return_default_value (m.return_type);
884 2 : ccode.close ();
885 : }
886 : }
887 : }
888 : }
889 :
890 50 : ccode.add_expression (unref_reply);
891 :
892 50 : if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) {
893 30 : ccode.add_return (new CCodeIdentifier ("_result"));
894 : }
895 : }
896 : }
897 :
898 37 : string generate_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
899 37 : string proxy_name = "%sproxy_%s".printf (get_ccode_lower_case_prefix (main_iface), m.name);
900 :
901 37 : string dbus_iface_name = get_dbus_name (iface);
902 :
903 37 : bool no_reply = is_dbus_no_reply (m);
904 :
905 37 : var function = new CCodeFunction (proxy_name);
906 37 : function.modifiers = CCodeModifiers.STATIC;
907 :
908 37 : var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
909 :
910 37 : generate_cparameters (m, cfile, cparam_map, function);
911 :
912 37 : push_function (function);
913 :
914 37 : 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));
915 :
916 37 : pop_function ();
917 :
918 37 : cfile.add_function_declaration (function);
919 37 : cfile.add_function (function);
920 :
921 37 : return proxy_name;
922 : }
923 :
924 13 : string generate_async_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
925 13 : string proxy_name = "%sproxy_%s_async".printf (get_ccode_lower_case_prefix (main_iface), m.name);
926 :
927 13 : string dbus_iface_name = get_dbus_name (iface);
928 :
929 13 : var function = new CCodeFunction (proxy_name, "void");
930 13 : function.modifiers = CCodeModifiers.STATIC;
931 :
932 13 : var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
933 :
934 13 : cparam_map.set (get_param_pos (-1), new CCodeParameter ("_callback_", "GAsyncReadyCallback"));
935 13 : cparam_map.set (get_param_pos (-0.9), new CCodeParameter ("_user_data_", "gpointer"));
936 :
937 13 : generate_cparameters (m, cfile, cparam_map, function, null, null, null, 1);
938 :
939 13 : push_function (function);
940 :
941 13 : generate_marshalling (m, CallType.ASYNC, dbus_iface_name, get_dbus_name_for_member (m), get_dbus_timeout_for_member (m));
942 :
943 13 : pop_function ();
944 :
945 13 : cfile.add_function_declaration (function);
946 13 : cfile.add_function (function);
947 :
948 13 : return proxy_name;
949 : }
950 :
951 13 : string generate_finish_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
952 13 : string proxy_name = "%sproxy_%s_finish".printf (get_ccode_lower_case_prefix (main_iface), m.name);
953 :
954 13 : var function = new CCodeFunction (proxy_name);
955 13 : function.modifiers = CCodeModifiers.STATIC;
956 :
957 13 : var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
958 :
959 13 : cparam_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeParameter ("_res_", "GAsyncResult*"));
960 :
961 13 : generate_cparameters (m, cfile, cparam_map, function, null, null, null, 2);
962 :
963 13 : push_function (function);
964 :
965 13 : generate_marshalling (m, CallType.FINISH, null, null, -1);
966 :
967 13 : pop_function ();
968 :
969 13 : cfile.add_function_declaration (function);
970 13 : cfile.add_function (function);
971 :
972 13 : return proxy_name;
973 : }
974 :
975 6 : string generate_dbus_proxy_property_get (Interface main_iface, Interface iface, Property prop) {
976 6 : string proxy_name = "%sdbus_proxy_get_%s".printf (get_ccode_lower_case_prefix (main_iface), prop.name);
977 :
978 6 : string dbus_iface_name = get_dbus_name (iface);
979 :
980 6 : var owned_type = prop.get_accessor.value_type.copy ();
981 6 : owned_type.value_owned = true;
982 6 : if (owned_type.is_disposable () && !prop.get_accessor.value_type.value_owned) {
983 0 : Report.error (prop.get_accessor.value_type.source_reference, "Properties used in D-Bus clients require owned get accessor");
984 : }
985 :
986 6 : var array_type = prop.get_accessor.value_type as ArrayType;
987 :
988 6 : var function = new CCodeFunction (proxy_name);
989 6 : function.modifiers = CCodeModifiers.STATIC;
990 :
991 6 : function.add_parameter (new CCodeParameter ("self", "%s*".printf (get_ccode_name (iface))));
992 :
993 6 : if (prop.property_type.is_real_non_null_struct_type ()) {
994 1 : function.add_parameter (new CCodeParameter ("result", "%s*".printf (get_ccode_name (prop.get_accessor.value_type))));
995 : } else {
996 6 : if (array_type != null) {
997 1 : var length_ctype = get_ccode_array_length_type (array_type) + "*";
998 2 : for (int dim = 1; dim <= array_type.rank; dim++) {
999 1 : function.add_parameter (new CCodeParameter ("result_length%d".printf (dim), length_ctype));
1000 : }
1001 : }
1002 :
1003 5 : function.return_type = get_ccode_name (prop.get_accessor.value_type);
1004 : }
1005 :
1006 6 : push_function (function);
1007 :
1008 6 : ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_inner_reply"));
1009 :
1010 : // first try cached value
1011 6 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_cached_property"));
1012 6 : ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
1013 6 : ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
1014 6 : ccode.add_assignment (new CCodeIdentifier ("_inner_reply"), ccall);
1015 :
1016 : // if not successful, retrieve value via D-Bus
1017 6 : ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_inner_reply")));
1018 :
1019 6 : ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
1020 6 : ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply"));
1021 6 : ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
1022 :
1023 6 : var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
1024 6 : builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1025 6 : builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
1026 6 : ccode.add_expression (builder_init);
1027 :
1028 : // interface name
1029 6 : write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)), null);
1030 : // property name
1031 6 : write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))), null);
1032 :
1033 6 : var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
1034 6 : builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1035 6 : ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
1036 :
1037 6 : ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync"));
1038 6 : ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
1039 6 : ccall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties.Get\""));
1040 6 : ccall.add_argument (new CCodeIdentifier ("_arguments"));
1041 6 : ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
1042 6 : ccall.add_argument (get_dbus_timeout (prop));
1043 6 : ccall.add_argument (new CCodeConstant ("NULL"));
1044 6 : ccall.add_argument (new CCodeConstant ("NULL"));
1045 :
1046 6 : ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall);
1047 :
1048 : // return on error
1049 6 : ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply")));
1050 6 : return_default_value (prop.property_type);
1051 6 : ccode.close ();
1052 :
1053 6 : var get_variant = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get"));
1054 6 : get_variant.add_argument (new CCodeIdentifier ("_reply"));
1055 6 : get_variant.add_argument (new CCodeConstant ("\"(v)\""));
1056 6 : get_variant.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_inner_reply")));
1057 6 : ccode.add_expression (get_variant);
1058 :
1059 6 : var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
1060 6 : unref_reply.add_argument (new CCodeIdentifier ("_reply"));
1061 6 : ccode.add_expression (unref_reply);
1062 :
1063 6 : ccode.close ();
1064 :
1065 7 : if (prop.property_type.is_real_non_null_struct_type ()) {
1066 1 : var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
1067 1 : var result = deserialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("_inner_reply"), target);
1068 1 : ccode.add_assignment (target, result);
1069 : } else {
1070 5 : ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator ("_result"));
1071 :
1072 9 : if (get_dbus_signature (prop) != null) {
1073 : // raw GVariant
1074 1 : ccode.add_assignment (new CCodeIdentifier ("_result"), new CCodeIdentifier("_inner_reply"));
1075 : } else {
1076 5 : if (array_type != null) {
1077 1 : var length_ctype = get_ccode_array_length_type (array_type);
1078 2 : for (int dim = 1; dim <= array_type.rank; dim++) {
1079 1 : ccode.add_declaration (length_ctype, new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
1080 : }
1081 : }
1082 :
1083 4 : var result = deserialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("_inner_reply"), new CCodeIdentifier ("_result"));
1084 4 : ccode.add_assignment (new CCodeIdentifier ("_result"), result);
1085 :
1086 4 : if (array_type != null) {
1087 2 : for (int dim = 1; dim <= array_type.rank; dim++) {
1088 : // TODO check that parameter is not NULL (out parameters are optional)
1089 1 : ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim)));
1090 : }
1091 : }
1092 : }
1093 : }
1094 :
1095 6 : if (prop.property_type.is_real_non_null_struct_type () || get_dbus_signature (prop) == null) {
1096 5 : unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
1097 5 : unref_reply.add_argument (new CCodeIdentifier ("_inner_reply"));
1098 5 : ccode.add_expression (unref_reply);
1099 : }
1100 :
1101 6 : if (prop.property_type.is_real_non_null_struct_type ()) {
1102 1 : ccode.add_return ();
1103 : } else {
1104 5 : ccode.add_return (new CCodeIdentifier ("_result"));
1105 : }
1106 :
1107 6 : pop_function ();
1108 :
1109 6 : cfile.add_function_declaration (function);
1110 6 : cfile.add_function (function);
1111 :
1112 6 : return proxy_name;
1113 : }
1114 :
1115 6 : string generate_dbus_proxy_property_set (Interface main_iface, Interface iface, Property prop) {
1116 6 : string proxy_name = "%sdbus_proxy_set_%s".printf (get_ccode_lower_case_prefix (main_iface), prop.name);
1117 :
1118 6 : string dbus_iface_name = get_dbus_name (iface);
1119 :
1120 6 : var array_type = prop.set_accessor.value_type as ArrayType;
1121 :
1122 6 : var function = new CCodeFunction (proxy_name);
1123 6 : function.modifiers = CCodeModifiers.STATIC;
1124 :
1125 6 : function.add_parameter (new CCodeParameter ("self", "%s*".printf (get_ccode_name (iface))));
1126 :
1127 6 : if (prop.property_type.is_real_non_null_struct_type ()) {
1128 1 : function.add_parameter (new CCodeParameter ("value", "%s*".printf (get_ccode_name (prop.set_accessor.value_type))));
1129 : } else {
1130 5 : function.add_parameter (new CCodeParameter ("value", get_ccode_name (prop.set_accessor.value_type)));
1131 :
1132 6 : if (array_type != null) {
1133 1 : var length_ctype = get_ccode_array_length_type (array_type);
1134 2 : for (int dim = 1; dim <= array_type.rank; dim++) {
1135 1 : function.add_parameter (new CCodeParameter ("value_length%d".printf (dim), length_ctype));
1136 : }
1137 : }
1138 : }
1139 :
1140 6 : push_function (function);
1141 :
1142 6 : ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
1143 6 : ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply"));
1144 :
1145 6 : ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
1146 :
1147 6 : var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
1148 6 : builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1149 6 : builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
1150 6 : ccode.add_expression (builder_init);
1151 :
1152 : // interface name
1153 6 : write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)), null);
1154 : // property name
1155 6 : write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))), null);
1156 :
1157 : // property value (as variant)
1158 6 : var builder_open = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_open"));
1159 6 : builder_open.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1160 6 : builder_open.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_VARIANT"));
1161 6 : ccode.add_expression (builder_open);
1162 :
1163 6 : if (prop.property_type.is_real_non_null_struct_type ()) {
1164 1 : write_expression (prop.set_accessor.value_type, new CCodeIdentifier ("_arguments_builder"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("value")), prop);
1165 : } else {
1166 5 : write_expression (prop.set_accessor.value_type, new CCodeIdentifier ("_arguments_builder"), new CCodeIdentifier ("value"), prop);
1167 : }
1168 :
1169 6 : var builder_close = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_close"));
1170 6 : builder_close.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1171 6 : ccode.add_expression (builder_close);
1172 :
1173 6 : var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
1174 6 : builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder")));
1175 6 : ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
1176 :
1177 6 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync"));
1178 6 : ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
1179 6 : ccall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties.Set\""));
1180 6 : ccall.add_argument (new CCodeIdentifier ("_arguments"));
1181 6 : ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
1182 6 : ccall.add_argument (get_dbus_timeout (prop));
1183 6 : ccall.add_argument (new CCodeConstant ("NULL"));
1184 6 : ccall.add_argument (new CCodeConstant ("NULL"));
1185 :
1186 6 : ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall);
1187 :
1188 : // return on error
1189 6 : ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply")));
1190 6 : ccode.add_return ();
1191 6 : ccode.close ();
1192 :
1193 6 : var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
1194 6 : unref_reply.add_argument (new CCodeIdentifier ("_reply"));
1195 6 : ccode.add_expression (unref_reply);
1196 :
1197 6 : pop_function ();
1198 :
1199 6 : cfile.add_function_declaration (function);
1200 6 : cfile.add_function (function);
1201 :
1202 6 : return proxy_name;
1203 : }
1204 :
1205 81 : public override void register_dbus_info (CCodeBlock block, ObjectTypeSymbol sym) {
1206 54 : if (!(sym is Interface)) {
1207 : return;
1208 : }
1209 :
1210 27 : string dbus_iface_name = get_dbus_name (sym);
1211 27 : if (dbus_iface_name == null) {
1212 0 : return;
1213 : }
1214 :
1215 27 : var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1216 27 : quark.add_argument (new CCodeConstant ("\"vala-dbus-proxy-type\""));
1217 :
1218 27 : var proxy_type = new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "proxy_get_type");
1219 :
1220 27 : var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1221 27 : set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null))));
1222 27 : set_qdata.add_argument (quark);
1223 27 : set_qdata.add_argument (new CCodeCastExpression (proxy_type, "void*"));
1224 :
1225 27 : block.add_statement (new CCodeExpressionStatement (set_qdata));
1226 :
1227 27 : quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1228 27 : quark.add_argument (new CCodeConstant ("\"vala-dbus-interface-name\""));
1229 :
1230 27 : set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1231 27 : set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null))));
1232 27 : set_qdata.add_argument (quark);
1233 27 : set_qdata.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1234 :
1235 27 : block.add_statement (new CCodeExpressionStatement (set_qdata));
1236 :
1237 : // TODO Replaced by g_dbus_proxy_set_interface_info() call in *_init
1238 27 : quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1239 27 : quark.add_argument (new CCodeConstant ("\"vala-dbus-interface-info\""));
1240 :
1241 27 : set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1242 27 : set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null))));
1243 27 : set_qdata.add_argument (quark);
1244 27 : set_qdata.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (sym)), "void*"));
1245 :
1246 27 : block.add_statement (new CCodeExpressionStatement (set_qdata));
1247 : }
1248 : }
|