Support explicit constructors for boolean, integer, and floating types
[vala-lang.git] / codegen / valadbusservermodule.vala
blob64de305af741ad56cbdadc77d2556930ce3cbc8d
1 /* valadbusservermodule.vala
3 * Copyright (C) 2007-2009 Jürg Billeter
4 * Copyright (C) 2008 Philip Van Hoof
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Author:
21 * Jürg Billeter <j@bitron.ch>
22 * Philip Van Hoof <pvanhoof@gnome.org>
25 using GLib;
27 /**
28 * The link between a dynamic method and generated code.
30 internal class Vala.DBusServerModule : DBusClientModule {
31 public DBusServerModule (CCodeGenerator codegen, CCodeModule? next) {
32 base (codegen, next);
35 bool is_dbus_visible (CodeNode node) {
36 var dbus_attribute = node.get_attribute ("DBus");
37 if (dbus_attribute != null
38 && dbus_attribute.has_argument ("visible")
39 && !dbus_attribute.get_bool ("visible")) {
40 return false;
43 return true;
46 string dbus_result_name (Method m) {
47 var dbus_attribute = m.get_attribute ("DBus");
48 if (dbus_attribute != null
49 && dbus_attribute.has_argument ("result")) {
50 var result_name = dbus_attribute.get_string ("result");
51 if (result_name != null && result_name != "") {
52 return result_name;
56 return "result";
59 void send_reply (CCodeBlock block) {
60 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send"));
61 ccall.add_argument (new CCodeIdentifier ("connection"));
62 ccall.add_argument (new CCodeIdentifier ("reply"));
63 ccall.add_argument (new CCodeConstant ("NULL"));
64 block.add_statement (new CCodeExpressionStatement (ccall));
65 ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
66 ccall.add_argument (new CCodeIdentifier ("reply"));
67 block.add_statement (new CCodeExpressionStatement (ccall));
70 void handle_reply (CCodeBlock block) {
71 var handled = new CCodeBlock ();
72 send_reply (handled);
73 handled.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
75 var not_handled = new CCodeBlock ();
76 not_handled.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
78 block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("reply"), handled, not_handled));
81 string generate_dbus_wrapper (Method m, ObjectTypeSymbol sym) {
82 string wrapper_name = "_dbus_%s".printf (m.get_cname ());
84 // declaration
86 CCodeDeclaration cdecl;
88 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
89 function.modifiers = CCodeModifiers.STATIC;
90 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
91 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
92 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
93 var block = new CCodeBlock ();
95 CCodeFunction ready_function = null;
96 CCodeBlock ready_block = null;
97 if (m.coroutine) {
98 // GAsyncResult
99 source_declarations.add_include ("gio/gio.h");
101 ready_function = new CCodeFunction (wrapper_name + "_ready", "void");
102 ready_function.modifiers = CCodeModifiers.STATIC;
103 ready_function.add_parameter (new CCodeFormalParameter ("source_object", "GObject *"));
104 ready_function.add_parameter (new CCodeFormalParameter ("_res_", "GAsyncResult *"));
105 ready_function.add_parameter (new CCodeFormalParameter ("_user_data_", "gpointer *"));
106 ready_block = new CCodeBlock ();
108 cdecl = new CCodeDeclaration ("DBusConnection *");
109 cdecl.add_declarator (new CCodeVariableDeclarator ("connection", new CCodeIdentifier ("_user_data_[0]")));
110 ready_block.add_statement (cdecl);
111 cdecl = new CCodeDeclaration ("DBusMessage *");
112 cdecl.add_declarator (new CCodeVariableDeclarator ("message", new CCodeIdentifier ("_user_data_[1]")));
113 ready_block.add_statement (cdecl);
116 var in_prefragment = new CCodeFragment ();
117 var in_postfragment = new CCodeFragment ();
118 var out_prefragment = in_prefragment;
119 var out_postfragment = in_postfragment;
121 cdecl = new CCodeDeclaration ("DBusMessageIter");
122 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
123 block.add_statement (cdecl);
124 if (m.coroutine) {
125 out_prefragment = new CCodeFragment ();
126 out_postfragment = new CCodeFragment ();
127 ready_block.add_statement (cdecl);
130 cdecl = new CCodeDeclaration ("GError*");
131 cdecl.add_declarator (new CCodeVariableDeclarator ("error", new CCodeConstant ("NULL")));
132 if (m.coroutine) {
133 ready_block.add_statement (cdecl);
134 } else {
135 block.add_statement (cdecl);
138 block.add_statement (in_prefragment);
139 if (m.coroutine) {
140 ready_block.add_statement (out_prefragment);
143 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
144 message_signature.add_argument (new CCodeIdentifier ("message"));
145 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
146 signature_check.add_argument (message_signature);
147 var signature_error_block = new CCodeBlock ();
148 signature_error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
149 in_prefragment.append (new CCodeIfStatement (signature_check, signature_error_block));
151 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
152 iter_call.add_argument (new CCodeIdentifier ("message"));
153 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
154 in_prefragment.append (new CCodeExpressionStatement (iter_call));
156 cdecl = new CCodeDeclaration ("DBusMessage*");
157 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
158 out_postfragment.append (cdecl);
160 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
161 msgcall.add_argument (new CCodeIdentifier ("message"));
162 out_postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
164 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
165 iter_call.add_argument (new CCodeIdentifier ("reply"));
166 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
167 out_postfragment.append (new CCodeExpressionStatement (iter_call));
169 var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
171 CCodeFunctionCall finish_ccall = null;
172 if (m.coroutine) {
173 finish_ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_finish_cname ()));
174 finish_ccall.add_argument (new CCodeIdentifier ("source_object"));
175 finish_ccall.add_argument (new CCodeIdentifier ("_res_"));
178 ccall.add_argument (new CCodeIdentifier ("self"));
180 // expected type signature for input parameters
181 string type_signature = "";
183 foreach (FormalParameter param in m.get_parameters ()) {
184 var owned_type = param.parameter_type.copy ();
185 owned_type.value_owned = true;
187 cdecl = new CCodeDeclaration (owned_type.get_cname ());
188 cdecl.add_declarator (new CCodeVariableDeclarator.zero (param.name, default_value_for_type (param.parameter_type, true)));
189 if (param.direction == ParameterDirection.IN) {
190 in_prefragment.append (cdecl);
191 } else {
192 out_prefragment.append (cdecl);
194 if (type_signature == ""
195 && param.direction == ParameterDirection.IN
196 && param.parameter_type.data_type != null
197 && param.parameter_type.data_type.get_full_name () == "DBus.BusName") {
198 // first parameter is a string parameter called 'sender'
199 // pass bus name of sender
200 var get_sender = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_sender"));
201 get_sender.add_argument (new CCodeIdentifier ("message"));
202 ccall.add_argument (get_sender);
203 continue;
206 if (get_type_signature (param.parameter_type) == null) {
207 Report.error (param.parameter_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (param.parameter_type.to_string ()));
208 continue;
211 if (!m.coroutine || param.direction == ParameterDirection.IN) {
212 var st = param.parameter_type.data_type as Struct;
213 if (param.direction != ParameterDirection.IN
214 || (st != null && !st.is_simple_type ())) {
215 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
216 } else {
217 ccall.add_argument (new CCodeIdentifier (param.name));
219 } else {
220 finish_ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
223 if (param.parameter_type is ArrayType) {
224 var array_type = (ArrayType) param.parameter_type;
226 for (int dim = 1; dim <= array_type.rank; dim++) {
227 string length_cname = get_array_length_cname (param.name, dim);
229 cdecl = new CCodeDeclaration ("int");
230 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
231 if (!m.coroutine || param.direction == ParameterDirection.IN) {
232 if (param.direction != ParameterDirection.IN) {
233 out_prefragment.append (cdecl);
234 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
235 } else {
236 in_prefragment.append (cdecl);
237 ccall.add_argument (new CCodeIdentifier (length_cname));
239 } else {
240 out_prefragment.append (cdecl);
241 finish_ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
246 if (param.direction == ParameterDirection.IN) {
247 type_signature += get_type_signature (param.parameter_type);
249 var target = new CCodeIdentifier (param.name);
250 var expr = read_expression (in_prefragment, param.parameter_type, new CCodeIdentifier ("iter"), target);
251 in_prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
252 } else {
253 write_expression (out_postfragment, param.parameter_type, new CCodeIdentifier ("iter"), new CCodeIdentifier (param.name));
256 if (requires_destroy (owned_type)) {
257 // keep local alive (symbol_reference is weak)
258 var local = new LocalVariable (owned_type, param.name);
259 var ma = new MemberAccess.simple (param.name);
260 ma.symbol_reference = local;
261 var stmt = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (param.name), owned_type, ma));
262 if (param.direction == ParameterDirection.IN) {
263 in_postfragment.append (stmt);
264 } else {
265 out_postfragment.append (stmt);
270 signature_check.add_argument (new CCodeConstant ("\"%s\"".printf (type_signature)));
272 if (!(m.return_type is VoidType)) {
273 if (get_type_signature (m.return_type) == null) {
274 Report.error (m.return_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (m.return_type.to_string ()));
275 } else if (m.return_type.is_real_non_null_struct_type ()) {
276 cdecl = new CCodeDeclaration (m.return_type.get_cname ());
277 cdecl.add_declarator (new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true)));
278 out_prefragment.append (cdecl);
280 if (!m.coroutine) {
281 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
282 } else {
283 finish_ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
286 write_expression (out_postfragment, m.return_type, new CCodeIdentifier ("iter"), new CCodeIdentifier ("result"));
288 if (requires_destroy (m.return_type)) {
289 // keep local alive (symbol_reference is weak)
290 // space before `result' is work around to not trigger
291 // variable renaming, we really mean C identifier `result' here
292 var local = new LocalVariable (m.return_type, " result");
293 var ma = new MemberAccess.simple ("result");
294 ma.symbol_reference = local;
295 out_postfragment.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("result"), m.return_type, ma)));
298 block.add_statement (new CCodeExpressionStatement (ccall));
299 if (m.coroutine) {
300 ready_block.add_statement (new CCodeExpressionStatement (finish_ccall));
302 } else {
303 cdecl = new CCodeDeclaration (m.return_type.get_cname ());
304 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
305 out_prefragment.append (cdecl);
306 if (!m.coroutine) {
307 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
308 } else {
309 block.add_statement (new CCodeExpressionStatement (ccall));
310 ready_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), finish_ccall)));
313 if (m.return_type is ArrayType) {
314 var array_type = (ArrayType) m.return_type;
316 for (int dim = 1; dim <= array_type.rank; dim++) {
317 string length_cname = get_array_length_cname ("result", dim);
319 cdecl = new CCodeDeclaration ("int");
320 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
321 out_prefragment.append (cdecl);
322 if (!m.coroutine) {
323 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
324 } else {
325 finish_ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
330 write_expression (out_postfragment, m.return_type, new CCodeIdentifier ("iter"), new CCodeIdentifier ("result"));
332 if (requires_destroy (m.return_type)) {
333 // keep local alive (symbol_reference is weak)
334 // space before `result' is work around to not trigger
335 // variable renaming, we really mean C identifier `result' here
336 var local = new LocalVariable (m.return_type, " result");
337 var ma = new MemberAccess.simple ("result");
338 ma.symbol_reference = local;
339 out_postfragment.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("result"), m.return_type, ma)));
342 } else {
343 block.add_statement (new CCodeExpressionStatement (ccall));
344 if (m.coroutine) {
345 ready_block.add_statement (new CCodeExpressionStatement (finish_ccall));
349 if (m.coroutine) {
350 ccall.add_argument (new CCodeIdentifier (wrapper_name + "_ready"));
352 var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
353 new_call.add_argument (new CCodeIdentifier ("gpointer"));
354 new_call.add_argument (new CCodeConstant ("2"));
355 cdecl = new CCodeDeclaration ("gpointer *");
356 cdecl.add_declarator (new CCodeVariableDeclarator ("_user_data_", new_call));
357 in_prefragment.append (cdecl);
359 var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_ref"));
360 ref_call.add_argument (new CCodeIdentifier ("connection"));
361 in_prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_user_data_[0]"), ref_call)));
362 ref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_ref"));
363 ref_call.add_argument (new CCodeIdentifier ("message"));
364 in_prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_user_data_[1]"), ref_call)));
366 ccall.add_argument (new CCodeIdentifier ("_user_data_"));
369 if (m.get_error_types ().size > 0) {
370 if (m.coroutine) {
371 finish_ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
372 } else {
373 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
376 var error_block = new CCodeBlock ();
378 generate_server_error_cases (error_block, m.get_error_types (), new CCodeIdentifier ("error"), new CCodeIdentifier ("message"), new CCodeIdentifier ("reply"));
380 send_reply (error_block);
382 if (m.coroutine) {
383 error_block.add_statement (new CCodeReturnStatement ());
384 ready_block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("error"), error_block));
385 } else {
386 error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
387 block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("error"), error_block));
391 block.add_statement (in_postfragment);
393 if (!m.coroutine) {
394 handle_reply (block);
395 } else {
396 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
398 ready_block.add_statement (out_postfragment);
400 send_reply (ready_block);
402 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_unref"));
403 unref_call.add_argument (new CCodeIdentifier ("connection"));
404 ready_block.add_statement (new CCodeExpressionStatement (unref_call));
405 unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
406 unref_call.add_argument (new CCodeIdentifier ("message"));
407 ready_block.add_statement (new CCodeExpressionStatement (unref_call));
408 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
409 free_call.add_argument (new CCodeIdentifier ("_user_data_"));
410 ready_block.add_statement (new CCodeExpressionStatement (free_call));
413 source_declarations.add_type_member_declaration (function.copy ());
415 function.block = block;
416 source_type_member_definition.append (function);
418 if (m.coroutine) {
419 source_declarations.add_type_member_declaration (ready_function.copy ());
421 ready_function.block = ready_block;
422 source_type_member_definition.append (ready_function);
425 return wrapper_name;
428 void generate_server_error_cases (CCodeBlock error_block, List<DataType> error_types, CCodeExpression error, CCodeExpression message, CCodeExpression reply) {
429 CCodeStatement if_else_if = null;
430 CCodeIfStatement last_statement = null;
432 foreach (DataType error_type in error_types) {
433 var edomain = ((ErrorType) error_type).error_domain;
435 var edomain_dbus_name = get_dbus_name (edomain);
436 if (edomain_dbus_name == null) {
437 Report.error (edomain.source_reference, "Errordomain must have a DBus.name annotation to be serialized over DBus");
440 var true_block = new CCodeBlock ();
441 true_block.suppress_newline = true;
443 var cswitch = new CCodeSwitchStatement (new CCodeMemberAccess.pointer (error, "code"));
444 foreach (ErrorCode ecode in edomain.get_codes ()) {
445 cswitch.add_statement (new CCodeCaseStatement (new CCodeIdentifier (ecode.get_cname ())));
447 var ecode_dbus_name = get_dbus_name (ecode);
448 if (ecode_dbus_name == null) {
449 ecode_dbus_name = Symbol.lower_case_to_camel_case (ecode.name.down ());
452 string dbus_name = "%s.%s".printf (edomain_dbus_name, ecode_dbus_name);
454 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_error"));
455 msgcall.add_argument (message);
456 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_name)));
457 msgcall.add_argument (new CCodeMemberAccess.pointer (error, "message"));
458 cswitch.add_statement (new CCodeExpressionStatement (new CCodeAssignment (reply, msgcall)));
460 cswitch.add_statement (new CCodeBreakStatement ());
462 true_block.add_statement (cswitch);
464 var equal_test = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeMemberAccess.pointer (error, "domain"), new CCodeIdentifier (edomain.get_upper_case_cname ()));
465 var stmt = new CCodeIfStatement (equal_test, true_block);
467 if (last_statement != null) {
468 last_statement.false_statement = stmt;
469 } else {
470 if_else_if = stmt;
472 last_statement = stmt;
474 error_block.add_statement (if_else_if);
477 string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
478 string wrapper_name = "_dbus_%s_%s".printf (sym.get_lower_case_cname (), sig.get_cname ());
480 // declaration
482 CCodeDeclaration cdecl;
484 var function = new CCodeFunction (wrapper_name, "void");
485 function.modifiers = CCodeModifiers.STATIC;
487 function.add_parameter (new CCodeFormalParameter ("_sender", "GObject*"));
489 foreach (var param in sig.get_parameters ()) {
490 // ensure ccodenode of parameter is set
491 generate_parameter (param, source_declarations, new HashMap<int,CCodeFormalParameter> (), null);
493 function.add_parameter ((CCodeFormalParameter) get_ccodenode (param));
494 if (param.parameter_type is ArrayType) {
495 var array_type = (ArrayType) param.parameter_type;
496 for (int dim = 1; dim <= array_type.rank; dim++) {
497 function.add_parameter (new CCodeFormalParameter (head.get_array_length_cname (param.name, dim), "int"));
502 function.add_parameter (new CCodeFormalParameter ("_connection", "DBusConnection*"));
504 var block = new CCodeBlock ();
505 var prefragment = new CCodeFragment ();
507 var path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get_data"));
508 path.add_argument (new CCodeIdentifier ("_sender"));
509 path.add_argument (new CCodeConstant ("\"dbus_object_path\""));
511 cdecl = new CCodeDeclaration ("const char *");
512 cdecl.add_declarator (new CCodeVariableDeclarator ("_path", path));
513 block.add_statement (cdecl);
515 cdecl = new CCodeDeclaration ("DBusMessage");
516 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
517 block.add_statement (cdecl);
519 cdecl = new CCodeDeclaration ("DBusMessageIter");
520 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
521 block.add_statement (cdecl);
523 block.add_statement (prefragment);
525 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_signal"));
526 msgcall.add_argument (new CCodeIdentifier ("_path"));
527 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
528 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig))));
529 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall)));
531 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
532 iter_call.add_argument (new CCodeIdentifier ("_message"));
533 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
534 prefragment.append (new CCodeExpressionStatement (iter_call));
536 foreach (FormalParameter param in sig.get_parameters ()) {
537 CCodeExpression expr = new CCodeIdentifier (param.name);
538 if (param.parameter_type.is_real_struct_type ()) {
539 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
541 write_expression (prefragment, param.parameter_type, new CCodeIdentifier ("_iter"), expr);
544 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send"));
545 ccall.add_argument (new CCodeIdentifier ("_connection"));
546 ccall.add_argument (new CCodeIdentifier ("_message"));
547 ccall.add_argument (new CCodeConstant ("NULL"));
548 block.add_statement (new CCodeExpressionStatement (ccall));
550 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
551 message_unref.add_argument (new CCodeIdentifier ("_message"));
552 block.add_statement (new CCodeExpressionStatement (message_unref));
554 source_declarations.add_type_member_declaration (function.copy ());
555 function.block = block;
556 source_type_member_definition.append (function);
558 return wrapper_name;
561 void generate_register_function (ObjectType object_type) {
562 var sym = object_type.type_symbol;
564 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_register_object", "void");
565 cfunc.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
566 cfunc.add_parameter (new CCodeFormalParameter ("path", "const char*"));
567 cfunc.add_parameter (new CCodeFormalParameter ("object", "void*"));
569 if (!sym.is_private_symbol ()) {
570 dbus_glib_h_needed_in_header = true;
571 } else {
572 dbus_glib_h_needed = true;
574 cfunc.modifiers |= CCodeModifiers.STATIC;
577 source_declarations.add_type_member_declaration (cfunc.copy ());
579 var block = new CCodeBlock ();
580 cfunc.block = block;
582 var get_path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get_data"));
583 get_path.add_argument (new CCodeIdentifier ("object"));
584 get_path.add_argument (new CCodeConstant ("\"dbus_object_path\""));
585 var register_check = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, get_path);
587 var register_block = new CCodeBlock ();
589 var path_dup = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup"));
590 path_dup.add_argument (new CCodeIdentifier ("path"));
592 var set_path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_set_data"));
593 set_path.add_argument (new CCodeIdentifier ("object"));
594 set_path.add_argument (new CCodeConstant ("\"dbus_object_path\""));
595 set_path.add_argument (path_dup);
596 register_block.add_statement (new CCodeExpressionStatement (set_path));
598 var cregister = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_register_object_path"));
599 cregister.add_argument (new CCodeIdentifier ("connection"));
600 cregister.add_argument (new CCodeIdentifier ("path"));
601 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_path_vtable (object_type)));
602 cregister.add_argument (new CCodeIdentifier ("object"));
603 register_block.add_statement (new CCodeExpressionStatement (cregister));
605 var weak_unregister = new CCodeFunctionCall (new CCodeIdentifier ("g_object_weak_ref"));
606 weak_unregister.add_argument (new CCodeIdentifier ("object"));
607 weak_unregister.add_argument (new CCodeIdentifier ("_vala_dbus_unregister_object"));
608 weak_unregister.add_argument (new CCodeIdentifier ("connection"));
609 register_block.add_statement (new CCodeExpressionStatement (weak_unregister));
611 block.add_statement (new CCodeIfStatement (register_check, register_block));
613 handle_signals (object_type.type_symbol, block);
615 var cl = sym as Class;
616 if (cl != null) {
617 foreach (DataType base_type in cl.get_base_types ()) {
618 var base_obj_type = base_type as ObjectType;
619 if (type_implements_dbus_interface (base_obj_type.type_symbol)) {
620 var base_register = new CCodeFunctionCall (new CCodeIdentifier (base_obj_type.type_symbol.get_lower_case_cprefix () + "dbus_register_object"));
621 base_register.add_argument (new CCodeIdentifier ("connection"));
622 base_register.add_argument (new CCodeIdentifier ("path"));
623 base_register.add_argument (new CCodeIdentifier ("object"));
624 block.add_statement (new CCodeExpressionStatement (base_register));
629 source_type_member_definition.append (cfunc);
632 void generate_unregister_function (ObjectType object_type) {
633 var sym = object_type.type_symbol;
635 var cfunc = new CCodeFunction ("_" + sym.get_lower_case_cprefix () + "dbus_unregister", "void");
636 cfunc.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
637 cfunc.add_parameter (new CCodeFormalParameter ("_user_data_", "void*"));
639 source_declarations.add_type_member_declaration (cfunc.copy ());
641 var block = new CCodeBlock ();
642 cfunc.block = block;
644 source_type_member_definition.append (cfunc);
647 void handle_method (string dbus_iface_name, string dbus_method_name, string handler_name, CCodeBlock block, ref CCodeIfStatement clastif) {
648 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_is_method_call"));
649 ccheck.add_argument (new CCodeIdentifier ("message"));
650 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
651 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_method_name)));
653 var callblock = new CCodeBlock ();
655 var ccall = new CCodeFunctionCall (new CCodeIdentifier (handler_name));
656 ccall.add_argument (new CCodeIdentifier ("object"));
657 ccall.add_argument (new CCodeIdentifier ("connection"));
658 ccall.add_argument (new CCodeIdentifier ("message"));
660 callblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
662 var cif = new CCodeIfStatement (ccheck, callblock);
663 if (clastif == null) {
664 block.add_statement (cif);
665 } else {
666 clastif.false_statement = cif;
669 clastif = cif;
672 void handle_methods (ObjectTypeSymbol sym, string dbus_iface_name, CCodeBlock block, ref CCodeIfStatement clastif) {
673 foreach (Method m in sym.get_methods ()) {
674 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
675 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
676 continue;
678 if (!is_dbus_visible (m)) {
679 continue;
682 handle_method (dbus_iface_name, get_dbus_name_for_member (m), generate_dbus_wrapper (m, sym), block, ref clastif);
686 string generate_dbus_property_get_wrapper (ObjectTypeSymbol sym, string dbus_iface_name) {
687 string wrapper_name = "_dbus_%s_property_get".printf (sym.get_lower_case_cname ());
689 CCodeDeclaration cdecl;
691 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
692 function.modifiers = CCodeModifiers.STATIC;
694 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
695 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
696 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
698 var block = new CCodeBlock ();
699 var prefragment = new CCodeFragment ();
701 cdecl = new CCodeDeclaration ("DBusMessage*");
702 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
703 block.add_statement (cdecl);
705 cdecl = new CCodeDeclaration ("DBusMessageIter");
706 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
707 cdecl.add_declarator (new CCodeVariableDeclarator ("reply_iter"));
708 cdecl.add_declarator (new CCodeVariableDeclarator ("subiter"));
709 block.add_statement (cdecl);
711 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
712 message_signature.add_argument (new CCodeIdentifier ("message"));
713 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
714 signature_check.add_argument (message_signature);
715 signature_check.add_argument (new CCodeConstant ("\"ss\""));
716 var signature_error_block = new CCodeBlock ();
717 signature_error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
718 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
720 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
721 iter_call.add_argument (new CCodeIdentifier ("message"));
722 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
723 block.add_statement (new CCodeExpressionStatement (iter_call));
725 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
726 msgcall.add_argument (new CCodeIdentifier ("message"));
727 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
729 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
730 iter_call.add_argument (new CCodeIdentifier ("reply"));
731 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
732 block.add_statement (new CCodeExpressionStatement (iter_call));
734 block.add_statement (prefragment);
736 cdecl = new CCodeDeclaration ("char*");
737 cdecl.add_declarator (new CCodeVariableDeclarator ("interface_name"));
738 prefragment.append (cdecl);
739 var target = new CCodeIdentifier ("interface_name");
740 var expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
741 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
743 cdecl = new CCodeDeclaration ("char*");
744 cdecl.add_declarator (new CCodeVariableDeclarator ("property_name"));
745 prefragment.append (cdecl);
746 target = new CCodeIdentifier ("property_name");
747 expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
748 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
750 CCodeIfStatement clastif = null;
752 foreach (Property prop in sym.get_properties ()) {
753 if (prop.binding != MemberBinding.INSTANCE
754 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
755 continue;
757 if (!is_dbus_visible (prop)) {
758 continue;
760 if (prop.get_accessor == null) {
761 continue;
764 var prop_block = new CCodeBlock ();
765 var postfragment = new CCodeFragment ();
766 prop_block.add_statement (postfragment);
768 var ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
769 ccmp.add_argument (new CCodeIdentifier ("interface_name"));
770 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
771 var ccheck1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
773 ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
774 ccmp.add_argument (new CCodeIdentifier ("property_name"));
775 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
776 var ccheck2 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
778 var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccheck1, ccheck2);
780 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
781 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
782 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_VARIANT"));
783 iter_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_signature (prop.property_type))));
784 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
785 postfragment.append (new CCodeExpressionStatement (iter_call));
787 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.get_accessor.get_cname ()));
788 ccall.add_argument (new CCodeIdentifier ("self"));
790 cdecl = new CCodeDeclaration (prop.property_type.get_cname ());
791 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
792 postfragment.append (cdecl);
794 if (prop.property_type.is_real_non_null_struct_type ()) {
795 // structs are returned via out parameter
796 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
798 postfragment.append (new CCodeExpressionStatement (ccall));
799 } else {
800 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
802 var array_type = prop.property_type as ArrayType;
803 if (array_type != null) {
804 for (int dim = 1; dim <= array_type.rank; dim++) {
805 string length_cname = get_array_length_cname ("result", dim);
807 cdecl = new CCodeDeclaration ("int");
808 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname));
809 postfragment.append (cdecl);
811 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
816 write_expression (postfragment, prop.property_type, new CCodeIdentifier ("subiter"), new CCodeIdentifier ("result"));
818 if (requires_destroy (prop.get_accessor.value_type)) {
819 // keep local alive (symbol_reference is weak)
820 // space before `result' is work around to not trigger
821 // variable renaming, we really mean C identifier `result' here
822 var local = new LocalVariable (prop.get_accessor.value_type, " result");
823 var ma = new MemberAccess.simple ("result");
824 ma.symbol_reference = local;
825 postfragment.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("result"), prop.get_accessor.value_type, ma)));
828 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
829 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
830 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
831 postfragment.append (new CCodeExpressionStatement (iter_call));
833 var cif = new CCodeIfStatement (ccheck, prop_block);
834 if (clastif == null) {
835 block.add_statement (cif);
836 } else {
837 clastif.false_statement = cif;
840 clastif = cif;
843 // free interface_name and property_name
844 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
845 free_call.add_argument (new CCodeIdentifier ("interface_name"));
846 block.add_statement (new CCodeExpressionStatement (free_call));
848 free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
849 free_call.add_argument (new CCodeIdentifier ("property_name"));
850 block.add_statement (new CCodeExpressionStatement (free_call));
852 if (clastif == null) {
853 block = new CCodeBlock ();
854 block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
855 } else {
856 var else_block = new CCodeBlock ();
857 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
858 unref_call.add_argument (new CCodeIdentifier ("reply"));
859 else_block.add_statement (new CCodeExpressionStatement (unref_call));
860 else_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), new CCodeConstant ("NULL"))));
861 clastif.false_statement = else_block;
863 handle_reply (block);
866 source_declarations.add_type_member_declaration (function.copy ());
868 function.block = block;
869 source_type_member_definition.append (function);
871 return wrapper_name;
874 string generate_dbus_property_get_all_wrapper (ObjectTypeSymbol sym, string dbus_iface_name) {
875 string wrapper_name = "_dbus_%s_property_get_all".printf (sym.get_lower_case_cname ());
877 bool has_readable_properties = false;
878 foreach (Property prop in sym.get_properties ()) {
879 if (prop.binding != MemberBinding.INSTANCE
880 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
881 continue;
883 if (!is_dbus_visible (prop)) {
884 continue;
886 if (prop.get_accessor != null) {
887 has_readable_properties = true;
891 CCodeDeclaration cdecl;
893 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
894 function.modifiers = CCodeModifiers.STATIC;
896 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
897 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
898 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
900 var block = new CCodeBlock ();
901 var prefragment = new CCodeFragment ();
903 cdecl = new CCodeDeclaration ("DBusMessage*");
904 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
905 block.add_statement (cdecl);
907 cdecl = new CCodeDeclaration ("DBusMessageIter");
908 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
909 cdecl.add_declarator (new CCodeVariableDeclarator ("reply_iter"));
910 cdecl.add_declarator (new CCodeVariableDeclarator ("subiter"));
911 if (has_readable_properties) {
912 cdecl.add_declarator (new CCodeVariableDeclarator ("entry_iter"));
913 cdecl.add_declarator (new CCodeVariableDeclarator ("value_iter"));
915 block.add_statement (cdecl);
917 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
918 message_signature.add_argument (new CCodeIdentifier ("message"));
919 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
920 signature_check.add_argument (message_signature);
921 signature_check.add_argument (new CCodeConstant ("\"s\""));
922 var signature_error_block = new CCodeBlock ();
923 signature_error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
924 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
926 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
927 iter_call.add_argument (new CCodeIdentifier ("message"));
928 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
929 block.add_statement (new CCodeExpressionStatement (iter_call));
931 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
932 msgcall.add_argument (new CCodeIdentifier ("message"));
933 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
935 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
936 iter_call.add_argument (new CCodeIdentifier ("reply"));
937 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
938 block.add_statement (new CCodeExpressionStatement (iter_call));
940 block.add_statement (prefragment);
942 cdecl = new CCodeDeclaration ("char*");
943 cdecl.add_declarator (new CCodeVariableDeclarator ("interface_name"));
944 prefragment.append (cdecl);
945 var target = new CCodeIdentifier ("interface_name");
946 var expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
947 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
949 if (has_readable_properties) {
950 cdecl = new CCodeDeclaration ("const char*");
951 cdecl.add_declarator (new CCodeVariableDeclarator ("property_name"));
952 prefragment.append (cdecl);
955 var prop_block = new CCodeBlock ();
957 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
958 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
959 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_ARRAY"));
960 iter_call.add_argument (new CCodeConstant ("\"{sv}\""));
961 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
962 prop_block.add_statement (new CCodeExpressionStatement (iter_call));
964 foreach (Property prop in sym.get_properties ()) {
965 if (prop.binding != MemberBinding.INSTANCE
966 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
967 continue;
969 if (!is_dbus_visible (prop)) {
970 continue;
972 if (prop.get_accessor == null) {
973 continue;
976 var inner_block = new CCodeBlock ();
977 prop_block.add_statement (inner_block);
978 var postfragment = new CCodeFragment ();
979 inner_block.add_statement (postfragment);
981 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
982 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
983 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_DICT_ENTRY"));
984 iter_call.add_argument (new CCodeConstant ("NULL"));
985 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
986 postfragment.append (new CCodeExpressionStatement (iter_call));
988 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("property_name"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))))));
990 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_append_basic"));
991 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
992 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_STRING"));
993 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("property_name")));
994 postfragment.append (new CCodeExpressionStatement (iter_call));
996 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
997 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
998 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_VARIANT"));
999 iter_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_signature (prop.property_type))));
1000 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value_iter")));
1001 postfragment.append (new CCodeExpressionStatement (iter_call));
1003 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.get_accessor.get_cname ()));
1004 ccall.add_argument (new CCodeIdentifier ("self"));
1006 cdecl = new CCodeDeclaration (prop.property_type.get_cname ());
1007 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
1008 postfragment.append (cdecl);
1010 if (prop.property_type.is_real_non_null_struct_type ()) {
1011 // structs are returned via out parameter
1012 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
1014 postfragment.append (new CCodeExpressionStatement (ccall));
1015 } else {
1016 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
1018 var array_type = prop.property_type as ArrayType;
1019 if (array_type != null) {
1020 for (int dim = 1; dim <= array_type.rank; dim++) {
1021 string length_cname = get_array_length_cname ("result", dim);
1023 cdecl = new CCodeDeclaration ("int");
1024 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname));
1025 postfragment.append (cdecl);
1027 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
1032 write_expression (postfragment, prop.property_type, new CCodeIdentifier ("value_iter"), new CCodeIdentifier ("result"));
1034 if (requires_destroy (prop.get_accessor.value_type)) {
1035 // keep local alive (symbol_reference is weak)
1036 // space before `result' is work around to not trigger
1037 // variable renaming, we really mean C identifier `result' here
1038 var local = new LocalVariable (prop.get_accessor.value_type, " result");
1039 var ma = new MemberAccess.simple ("result");
1040 ma.symbol_reference = local;
1041 postfragment.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("result"), prop.get_accessor.value_type, ma)));
1044 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
1045 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
1046 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value_iter")));
1047 postfragment.append (new CCodeExpressionStatement (iter_call));
1049 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
1050 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
1051 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
1052 postfragment.append (new CCodeExpressionStatement (iter_call));
1055 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
1056 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
1057 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
1058 prop_block.add_statement (new CCodeExpressionStatement (iter_call));
1060 var ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1061 ccmp.add_argument (new CCodeIdentifier ("interface_name"));
1062 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1063 var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
1065 var else_block = new CCodeBlock ();
1066 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1067 unref_call.add_argument (new CCodeIdentifier ("reply"));
1068 else_block.add_statement (new CCodeExpressionStatement (unref_call));
1069 else_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), new CCodeConstant ("NULL"))));
1071 block.add_statement (new CCodeIfStatement (ccheck, prop_block, else_block));
1073 // free interface_name
1074 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1075 free_call.add_argument (new CCodeIdentifier ("interface_name"));
1076 block.add_statement (new CCodeExpressionStatement (free_call));
1078 handle_reply (block);
1080 source_declarations.add_type_member_declaration (function.copy ());
1082 function.block = block;
1083 source_type_member_definition.append (function);
1085 return wrapper_name;
1088 string generate_dbus_property_set_wrapper (ObjectTypeSymbol sym, string dbus_iface_name) {
1089 string wrapper_name = "_dbus_%s_property_set".printf (sym.get_lower_case_cname ());
1091 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
1092 function.modifiers = CCodeModifiers.STATIC;
1094 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
1095 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
1096 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
1098 var block = new CCodeBlock ();
1099 var prefragment = new CCodeFragment ();
1101 var cdecl = new CCodeDeclaration ("DBusMessage*");
1102 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
1103 block.add_statement (cdecl);
1105 cdecl = new CCodeDeclaration ("DBusMessageIter");
1106 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
1107 cdecl.add_declarator (new CCodeVariableDeclarator ("subiter"));
1108 block.add_statement (cdecl);
1110 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
1111 message_signature.add_argument (new CCodeIdentifier ("message"));
1112 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1113 signature_check.add_argument (message_signature);
1114 signature_check.add_argument (new CCodeConstant ("\"ssv\""));
1115 var signature_error_block = new CCodeBlock ();
1116 signature_error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1117 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
1119 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
1120 iter_call.add_argument (new CCodeIdentifier ("message"));
1121 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1122 block.add_statement (new CCodeExpressionStatement (iter_call));
1124 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
1125 msgcall.add_argument (new CCodeIdentifier ("message"));
1126 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
1128 block.add_statement (prefragment);
1130 cdecl = new CCodeDeclaration ("char*");
1131 cdecl.add_declarator (new CCodeVariableDeclarator ("interface_name"));
1132 prefragment.append (cdecl);
1133 var target = new CCodeIdentifier ("interface_name");
1134 var expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
1135 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1137 cdecl = new CCodeDeclaration ("char*");
1138 cdecl.add_declarator (new CCodeVariableDeclarator ("property_name"));
1139 prefragment.append (cdecl);
1140 target = new CCodeIdentifier ("property_name");
1141 expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
1142 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1144 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_recurse"));
1145 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1146 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
1147 prefragment.append (new CCodeExpressionStatement (iter_call));
1149 CCodeIfStatement clastif = null;
1151 foreach (Property prop in sym.get_properties ()) {
1152 if (prop.binding != MemberBinding.INSTANCE
1153 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
1154 continue;
1156 if (!is_dbus_visible (prop)) {
1157 continue;
1159 if (prop.set_accessor == null) {
1160 continue;
1163 var prop_block = new CCodeBlock ();
1164 prefragment = new CCodeFragment ();
1165 prop_block.add_statement (prefragment);
1167 var ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1168 ccmp.add_argument (new CCodeIdentifier ("interface_name"));
1169 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1170 var ccheck1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
1172 ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1173 ccmp.add_argument (new CCodeIdentifier ("property_name"));
1174 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
1175 var ccheck2 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
1177 var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccheck1, ccheck2);
1179 var owned_type = prop.property_type.copy ();
1180 owned_type.value_owned = true;
1182 cdecl = new CCodeDeclaration (owned_type.get_cname ());
1183 cdecl.add_declarator (new CCodeVariableDeclarator ("value"));
1184 prefragment.append (cdecl);
1186 target = new CCodeIdentifier ("value");
1187 expr = read_expression (prefragment, prop.property_type, new CCodeIdentifier ("subiter"), target);
1188 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1190 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.set_accessor.get_cname ()));
1191 ccall.add_argument (new CCodeIdentifier ("self"));
1193 if (prop.property_type.is_real_non_null_struct_type ()) {
1194 // structs are passed by reference
1195 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value")));
1196 } else {
1197 ccall.add_argument (new CCodeIdentifier ("value"));
1199 var array_type = prop.property_type as ArrayType;
1200 if (array_type != null) {
1201 for (int dim = 1; dim <= array_type.rank; dim++) {
1202 cdecl = new CCodeDeclaration ("int");
1203 cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname ("value", dim)));
1204 prefragment.append (cdecl);
1206 ccall.add_argument (new CCodeIdentifier (head.get_array_length_cname ("value", dim)));
1211 prop_block.add_statement (new CCodeExpressionStatement (ccall));
1213 if (requires_destroy (owned_type)) {
1214 // keep local alive (symbol_reference is weak)
1215 var local = new LocalVariable (owned_type, "value");
1216 var ma = new MemberAccess.simple ("value");
1217 ma.symbol_reference = local;
1218 prop_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("value"), owned_type, ma)));
1221 var cif = new CCodeIfStatement (ccheck, prop_block);
1222 if (clastif == null) {
1223 block.add_statement (cif);
1224 } else {
1225 clastif.false_statement = cif;
1228 clastif = cif;
1231 // free interface_name and property_name
1232 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1233 free_call.add_argument (new CCodeIdentifier ("interface_name"));
1234 block.add_statement (new CCodeExpressionStatement (free_call));
1236 free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1237 free_call.add_argument (new CCodeIdentifier ("property_name"));
1238 block.add_statement (new CCodeExpressionStatement (free_call));
1240 if (clastif == null) {
1241 block = new CCodeBlock ();
1242 block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
1243 } else {
1244 var else_block = new CCodeBlock ();
1245 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1246 unref_call.add_argument (new CCodeIdentifier ("reply"));
1247 else_block.add_statement (new CCodeExpressionStatement (unref_call));
1248 else_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), new CCodeIdentifier ("NULL"))));
1249 clastif.false_statement = else_block;
1251 handle_reply (block);
1254 source_declarations.add_type_member_declaration (function.copy ());
1256 function.block = block;
1257 source_type_member_definition.append (function);
1259 return wrapper_name;
1262 string get_dbus_type_introspection (ObjectTypeSymbol sym) {
1263 string result = "";
1265 var cl = sym as Class;
1266 if (cl != null) {
1267 foreach (DataType base_type in cl.get_base_types ()) {
1268 var base_obj_type = base_type as ObjectType;
1269 result += get_dbus_type_introspection (base_obj_type.type_symbol);
1273 string dbus_iface_name = get_dbus_name (sym);
1274 if (dbus_iface_name == null) {
1275 return result;
1278 result += "<interface name=\"%s\">\n".printf (dbus_iface_name);
1280 foreach (var m in sym.get_methods ()) {
1281 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
1282 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
1283 continue;
1285 if (!is_dbus_visible (m)) {
1286 continue;
1289 result += " <method name=\"%s\">\n".printf (get_dbus_name_for_member (m));
1291 foreach (var param in m.get_parameters ()) {
1292 if (param.parameter_type.data_type != null
1293 && param.parameter_type.data_type.get_full_name () == "DBus.BusName") {
1294 // skip sender parameter
1295 // (implicit in D-Bus)
1296 continue;
1299 string direction = param.direction == ParameterDirection.IN ? "in" : "out";
1300 result += " <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n".printf (param.name, get_type_signature (param.parameter_type), direction);
1302 if (!(m.return_type is VoidType)) {
1303 result += " <arg name=\"%s\" type=\"%s\" direction=\"out\"/>\n".printf (dbus_result_name (m), get_type_signature (m.return_type));
1306 result += " </method>\n";
1309 foreach (var prop in sym.get_properties ()) {
1310 if (prop.binding != MemberBinding.INSTANCE
1311 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
1312 continue;
1314 if (!is_dbus_visible (prop)) {
1315 continue;
1318 string access = (prop.get_accessor != null ? "read" : "") + (prop.set_accessor != null ? "write" : "");
1319 result += " <property name=\"%s\" type=\"%s\" access=\"%s\"/>\n".printf (get_dbus_name_for_member (prop), get_type_signature (prop.property_type), access);
1322 foreach (var sig in sym.get_signals ()) {
1323 if (sig.access != SymbolAccessibility.PUBLIC) {
1324 continue;
1326 if (!is_dbus_visible (sig)) {
1327 continue;
1330 result += " <signal name=\"%s\">\n".printf (get_dbus_name_for_member (sig));
1332 foreach (var param in sig.get_parameters ()) {
1333 result += " <arg name=\"%s\" type=\"%s\"/>\n".printf (param.name, get_type_signature (param.parameter_type));
1336 result += " </signal>\n";
1339 result += "</interface>\n";
1341 return result;
1344 string generate_dbus_introspect (ObjectTypeSymbol sym) {
1345 string wrapper_name = "_dbus_%s_introspect".printf (sym.get_lower_case_cname ());
1347 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
1348 function.modifiers = CCodeModifiers.STATIC;
1350 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
1351 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
1352 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
1354 var block = new CCodeBlock ();
1356 var cdecl = new CCodeDeclaration ("DBusMessage*");
1357 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
1358 block.add_statement (cdecl);
1360 cdecl = new CCodeDeclaration ("DBusMessageIter");
1361 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
1362 block.add_statement (cdecl);
1364 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
1365 msgcall.add_argument (new CCodeIdentifier ("message"));
1366 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
1368 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
1369 iter_call.add_argument (new CCodeIdentifier ("reply"));
1370 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1371 block.add_statement (new CCodeExpressionStatement (iter_call));
1373 cdecl = new CCodeDeclaration ("GString*");
1374 cdecl.add_declarator (new CCodeVariableDeclarator ("xml_data"));
1375 block.add_statement (cdecl);
1377 cdecl = new CCodeDeclaration ("char**");
1378 cdecl.add_declarator (new CCodeVariableDeclarator ("children"));
1379 block.add_statement (cdecl);
1381 cdecl = new CCodeDeclaration ("int");
1382 cdecl.add_declarator (new CCodeVariableDeclarator ("i"));
1383 block.add_statement (cdecl);
1385 string xml_data = "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n";
1386 var str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_new"));
1387 str_call.add_argument (new CCodeConstant ("\"%s\"".printf (xml_data.escape (""))));
1388 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("xml_data"), str_call)));
1390 xml_data = "<node>\n";
1391 xml_data +=
1392 """<interface name="org.freedesktop.DBus.Introspectable">
1393 <method name="Introspect">
1394 <arg name="data" direction="out" type="s"/>
1395 </method>
1396 </interface>
1397 <interface name="org.freedesktop.DBus.Properties">
1398 <method name="Get">
1399 <arg name="interface" direction="in" type="s"/>
1400 <arg name="propname" direction="in" type="s"/>
1401 <arg name="value" direction="out" type="v"/>
1402 </method>
1403 <method name="Set">
1404 <arg name="interface" direction="in" type="s"/>
1405 <arg name="propname" direction="in" type="s"/>
1406 <arg name="value" direction="in" type="v"/>
1407 </method>
1408 <method name="GetAll">
1409 <arg name="interface" direction="in" type="s"/>
1410 <arg name="props" direction="out" type="a{sv}"/>
1411 </method>
1412 </interface>
1413 """;
1414 xml_data += get_dbus_type_introspection (sym);
1415 str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_append"));
1416 str_call.add_argument (new CCodeIdentifier ("xml_data"));
1417 str_call.add_argument (new CCodeConstant ("\"%s\"".printf (xml_data.escape (""))));
1418 block.add_statement (new CCodeExpressionStatement (str_call));
1420 var get_path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get_data"));
1421 get_path.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *"));
1422 get_path.add_argument (new CCodeConstant ("\"dbus_object_path\""));
1424 var list_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_list_registered"));
1425 list_call.add_argument (new CCodeIdentifier ("connection"));
1426 list_call.add_argument (get_path);
1427 list_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("children")));
1428 block.add_statement (new CCodeExpressionStatement (list_call));
1430 // add child nodes
1431 var child_block = new CCodeBlock ();
1432 str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_append_printf"));
1433 str_call.add_argument (new CCodeIdentifier ("xml_data"));
1434 str_call.add_argument (new CCodeConstant ("\"%s\"".printf ("<node name=\"%s\"/>\n".escape (""))));
1435 str_call.add_argument (new CCodeElementAccess (new CCodeIdentifier ("children"), new CCodeIdentifier ("i")));
1436 child_block.add_statement (new CCodeExpressionStatement (str_call));
1437 var cfor = new CCodeForStatement (new CCodeElementAccess (new CCodeIdentifier ("children"), new CCodeIdentifier ("i")), child_block);
1438 cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
1439 cfor.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
1440 block.add_statement (cfor);
1442 var list_free_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_free_string_array"));
1443 list_free_call.add_argument (new CCodeIdentifier ("children"));
1444 block.add_statement (new CCodeExpressionStatement (list_free_call));
1446 xml_data = "</node>\n";
1447 str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_append"));
1448 str_call.add_argument (new CCodeIdentifier ("xml_data"));
1449 str_call.add_argument (new CCodeConstant ("\"%s\"".printf (xml_data.escape (""))));
1450 block.add_statement (new CCodeExpressionStatement (str_call));
1452 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_append_basic"));
1453 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1454 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_STRING"));
1455 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (new CCodeIdentifier ("xml_data"), "str")));
1456 block.add_statement (new CCodeExpressionStatement (iter_call));
1458 str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_free"));
1459 str_call.add_argument (new CCodeIdentifier ("xml_data"));
1460 str_call.add_argument (new CCodeConstant ("TRUE"));
1461 block.add_statement (new CCodeExpressionStatement (str_call));
1463 handle_reply (block);
1465 source_declarations.add_type_member_declaration (function.copy ());
1467 function.block = block;
1468 source_type_member_definition.append (function);
1470 return wrapper_name;
1473 void handle_signals (ObjectTypeSymbol sym, CCodeBlock block) {
1474 string dbus_iface_name = get_dbus_name (sym);
1475 if (dbus_iface_name == null) {
1476 return;
1479 foreach (Signal sig in sym.get_signals ()) {
1480 if (sig.access != SymbolAccessibility.PUBLIC) {
1481 continue;
1483 if (!is_dbus_visible (sig)) {
1484 continue;
1487 var connect = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
1488 connect.add_argument (new CCodeIdentifier ("object"));
1489 connect.add_argument (sig.get_canonical_cconstant (null));
1490 connect.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
1491 connect.add_argument (new CCodeIdentifier ("connection"));
1492 block.add_statement (new CCodeExpressionStatement (connect));
1496 void generate_message_function (ObjectType object_type) {
1497 var sym = object_type.type_symbol;
1499 dbus_glib_h_needed = true;
1501 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_message", "DBusHandlerResult");
1502 cfunc.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
1503 cfunc.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
1504 cfunc.add_parameter (new CCodeFormalParameter ("object", "void*"));
1506 if (sym.is_private_symbol ()) {
1507 cfunc.modifiers |= CCodeModifiers.STATIC;
1510 source_declarations.add_type_member_declaration (cfunc.copy ());
1512 var block = new CCodeBlock ();
1513 cfunc.block = block;
1515 var cdecl = new CCodeDeclaration ("DBusHandlerResult");
1516 cdecl.add_declarator (new CCodeVariableDeclarator ("result", new CCodeConstant ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1517 block.add_statement (cdecl);
1519 CCodeIfStatement clastif = null;
1521 handle_method ("org.freedesktop.DBus.Introspectable", "Introspect", generate_dbus_introspect (sym), block, ref clastif);
1523 string dbus_iface_name = get_dbus_name (sym);
1524 if (dbus_iface_name != null) {
1525 bool need_property_get = false;
1526 bool need_property_set = false;
1527 foreach (Property prop in sym.get_properties ()) {
1528 if (prop.binding != MemberBinding.INSTANCE
1529 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
1530 continue;
1532 if (!is_dbus_visible (prop)) {
1533 continue;
1535 if (prop.get_accessor != null) {
1536 need_property_get = true;
1538 if (prop.set_accessor != null) {
1539 need_property_set = true;
1543 if (need_property_get) {
1544 handle_method ("org.freedesktop.DBus.Properties", "Get", generate_dbus_property_get_wrapper (sym, dbus_iface_name), block, ref clastif);
1546 if (need_property_set) {
1547 handle_method ("org.freedesktop.DBus.Properties", "Set", generate_dbus_property_set_wrapper (sym, dbus_iface_name), block, ref clastif);
1549 handle_method ("org.freedesktop.DBus.Properties", "GetAll", generate_dbus_property_get_all_wrapper (sym, dbus_iface_name), block, ref clastif);
1551 handle_methods (sym, dbus_iface_name, block, ref clastif);
1554 var resultblock = new CCodeBlock ();
1555 resultblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
1556 var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("result"), new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")), resultblock);
1557 block.add_statement (cif);
1558 clastif = cif;
1560 var cl = sym as Class;
1561 if (cl != null) {
1562 foreach (DataType base_type in cl.get_base_types ()) {
1563 var base_obj_type = base_type as ObjectType;
1564 if (type_implements_dbus_interface (base_obj_type.type_symbol)) {
1565 var base_call = new CCodeFunctionCall (new CCodeIdentifier (base_obj_type.type_symbol.get_lower_case_cprefix () + "dbus_message"));
1566 base_call.add_argument (new CCodeIdentifier ("connection"));
1567 base_call.add_argument (new CCodeIdentifier ("message"));
1568 base_call.add_argument (new CCodeIdentifier ("object"));
1570 var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, base_call, new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED"));
1572 var base_block = new CCodeBlock ();
1573 base_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
1575 cif = new CCodeIfStatement (ccheck, base_block);
1576 clastif.false_statement = cif;
1578 clastif = cif;
1583 var retblock = new CCodeBlock ();
1584 retblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1585 clastif.false_statement = retblock;
1587 source_type_member_definition.append (cfunc);
1590 CCodeExpression get_vtable (ObjectType object_type) {
1591 var sym = object_type.type_symbol;
1593 var vtable = new CCodeInitializerList ();
1594 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_register_object"));
1596 generate_register_function (object_type);
1598 var cdecl = new CCodeDeclaration ("const _DBusObjectVTable");
1599 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_vtable", vtable));
1600 cdecl.modifiers = CCodeModifiers.STATIC;
1601 source_declarations.add_constant_declaration (cdecl);
1603 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_vtable");
1606 CCodeExpression get_path_vtable (ObjectType object_type) {
1607 var sym = object_type.type_symbol;
1609 var vtable = new CCodeInitializerList ();
1610 vtable.append (new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_unregister"));
1611 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_message"));
1613 generate_unregister_function (object_type);
1614 generate_message_function (object_type);
1616 var cdecl = new CCodeDeclaration ("const DBusObjectPathVTable");
1617 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_path_vtable", vtable));
1618 cdecl.modifiers = CCodeModifiers.STATIC;
1619 source_declarations.add_constant_declaration (cdecl);
1621 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_path_vtable");
1624 public override void visit_method_call (MethodCall expr) {
1625 var mtype = expr.call.value_type as MethodType;
1626 if (mtype == null || (mtype.method_symbol.get_cname () != "dbus_connection_register_g_object" &&
1627 mtype.method_symbol.get_cname () != "dbus_g_connection_register_g_object")) {
1628 base.visit_method_call (expr);
1629 return;
1632 dbus_glib_h_needed = true;
1634 expr.accept_children (codegen);
1636 var ma = (MemberAccess) expr.call;
1638 var raw_conn = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1639 raw_conn.add_argument ((CCodeExpression) ma.inner.ccodenode);
1641 var args_it = expr.get_argument_list ().iterator ();
1642 args_it.next ();
1643 var path_arg = args_it.get ();
1644 args_it.next ();
1645 var obj_arg = args_it.get ();
1647 var cregister = new CCodeFunctionCall (new CCodeIdentifier ("_vala_dbus_register_object"));
1648 if (mtype.method_symbol.get_cname () == "dbus_g_connection_register_g_object") {
1649 cregister.add_argument (raw_conn);
1650 } else {
1651 cregister.add_argument ((CCodeExpression) ma.inner.ccodenode);
1653 cregister.add_argument ((CCodeExpression) path_arg.ccodenode);
1654 cregister.add_argument ((CCodeExpression) obj_arg.ccodenode);
1655 expr.ccodenode = cregister;
1658 bool type_implements_dbus_interface (ObjectTypeSymbol sym) {
1659 var dbus = sym.get_attribute ("DBus");
1660 if (dbus != null) {
1661 return true;
1664 var cl = sym as Class;
1665 if (cl != null) {
1666 foreach (DataType base_type in cl.get_base_types ()) {
1667 var base_obj_type = base_type as ObjectType;
1668 if (type_implements_dbus_interface (base_obj_type.type_symbol)) {
1669 return true;
1674 return false;
1677 public override CCodeFragment register_dbus_info (ObjectTypeSymbol sym) {
1678 CCodeFragment fragment = new CCodeFragment ();
1680 if (!type_implements_dbus_interface (sym)) {
1681 return fragment;
1684 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1685 quark.add_argument (new CCodeConstant ("\"DBusObjectVTable\""));
1687 var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1688 set_qdata.add_argument (new CCodeIdentifier (sym.get_upper_case_cname ("TYPE_")));
1689 set_qdata.add_argument (quark);
1690 set_qdata.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_vtable (new ObjectType (sym))), "void*"));
1692 fragment.append (new CCodeExpressionStatement (set_qdata));
1694 return fragment;