GAsync: Another temp variable fix
[vala-lang.git] / codegen / valadbusservermodule.vala
blobe81a395378c4f984b28497b2ed15a3907d2bab65
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;
26 using Gee;
28 /**
29 * The link between a dynamic method and generated code.
31 internal class Vala.DBusServerModule : DBusClientModule {
32 public DBusServerModule (CCodeGenerator codegen, CCodeModule? next) {
33 base (codegen, next);
36 bool is_dbus_visible (CodeNode node) {
37 var dbus_attribute = node.get_attribute ("DBus");
38 if (dbus_attribute != null
39 && dbus_attribute.has_argument ("visible")
40 && !dbus_attribute.get_bool ("visible")) {
41 return false;
44 return true;
47 string dbus_result_name (Method m) {
48 var dbus_attribute = m.get_attribute ("DBus");
49 if (dbus_attribute != null
50 && dbus_attribute.has_argument ("result")) {
51 var result_name = dbus_attribute.get_string ("result");
52 if (result_name != null && result_name != "") {
53 return result_name;
57 return "result";
60 void send_reply (CCodeBlock block) {
61 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send"));
62 ccall.add_argument (new CCodeIdentifier ("connection"));
63 ccall.add_argument (new CCodeIdentifier ("reply"));
64 ccall.add_argument (new CCodeConstant ("NULL"));
65 block.add_statement (new CCodeExpressionStatement (ccall));
66 ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
67 ccall.add_argument (new CCodeIdentifier ("reply"));
68 block.add_statement (new CCodeExpressionStatement (ccall));
71 void handle_reply (CCodeBlock block) {
72 var handled = new CCodeBlock ();
73 send_reply (handled);
74 handled.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
76 var not_handled = new CCodeBlock ();
77 not_handled.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
79 block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("reply"), handled, not_handled));
82 string generate_dbus_wrapper (Method m, ObjectTypeSymbol sym) {
83 string wrapper_name = "_dbus_%s".printf (m.get_cname ());
85 // declaration
87 CCodeDeclaration cdecl;
89 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
90 function.modifiers = CCodeModifiers.STATIC;
91 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
92 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
93 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
94 var block = new CCodeBlock ();
96 CCodeFunction ready_function = null;
97 CCodeBlock ready_block = null;
98 if (m.coroutine) {
99 // GAsyncResult
100 source_declarations.add_include ("gio/gio.h");
102 ready_function = new CCodeFunction (wrapper_name + "_ready", "void");
103 ready_function.modifiers = CCodeModifiers.STATIC;
104 ready_function.add_parameter (new CCodeFormalParameter ("source_object", "GObject *"));
105 ready_function.add_parameter (new CCodeFormalParameter ("res", "GAsyncResult *"));
106 ready_function.add_parameter (new CCodeFormalParameter ("user_data", "gpointer *"));
107 ready_block = new CCodeBlock ();
109 cdecl = new CCodeDeclaration ("DBusConnection *");
110 cdecl.add_declarator (new CCodeVariableDeclarator ("connection", new CCodeIdentifier ("user_data[0]")));
111 ready_block.add_statement (cdecl);
112 cdecl = new CCodeDeclaration ("DBusMessage *");
113 cdecl.add_declarator (new CCodeVariableDeclarator ("message", new CCodeIdentifier ("user_data[1]")));
114 ready_block.add_statement (cdecl);
117 var prefragment = new CCodeFragment ();
118 var in_postfragment = new CCodeFragment ();
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_postfragment = new CCodeFragment ();
126 ready_block.add_statement (cdecl);
129 cdecl = new CCodeDeclaration ("GError*");
130 cdecl.add_declarator (new CCodeVariableDeclarator ("error", new CCodeConstant ("NULL")));
131 if (m.coroutine) {
132 ready_block.add_statement (cdecl);
133 } else {
134 block.add_statement (cdecl);
137 block.add_statement (prefragment);
139 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
140 message_signature.add_argument (new CCodeIdentifier ("message"));
141 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
142 signature_check.add_argument (message_signature);
143 var signature_error_block = new CCodeBlock ();
144 signature_error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
145 prefragment.append (new CCodeIfStatement (signature_check, signature_error_block));
147 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
148 iter_call.add_argument (new CCodeIdentifier ("message"));
149 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
150 prefragment.append (new CCodeExpressionStatement (iter_call));
152 cdecl = new CCodeDeclaration ("DBusMessage*");
153 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
154 out_postfragment.append (cdecl);
156 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
157 msgcall.add_argument (new CCodeIdentifier ("message"));
158 out_postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
160 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
161 iter_call.add_argument (new CCodeIdentifier ("reply"));
162 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
163 out_postfragment.append (new CCodeExpressionStatement (iter_call));
165 var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
167 CCodeFunctionCall finish_ccall = null;
168 if (m.coroutine) {
169 finish_ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_finish_cname ()));
170 finish_ccall.add_argument (new CCodeIdentifier ("source_object"));
171 finish_ccall.add_argument (new CCodeIdentifier ("res"));
174 ccall.add_argument (new CCodeIdentifier ("self"));
176 // expected type signature for input parameters
177 string type_signature = "";
179 foreach (FormalParameter param in m.get_parameters ()) {
180 var owned_type = param.parameter_type.copy ();
181 owned_type.value_owned = true;
183 cdecl = new CCodeDeclaration (owned_type.get_cname ());
184 cdecl.add_declarator (new CCodeVariableDeclarator (param.name, default_value_for_type (param.parameter_type, true)));
185 prefragment.append (cdecl);
186 if (type_signature == ""
187 && param.direction == ParameterDirection.IN
188 && param.parameter_type.data_type != null
189 && param.parameter_type.data_type.get_full_name () == "DBus.BusName") {
190 // first parameter is a string parameter called 'sender'
191 // pass bus name of sender
192 var get_sender = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_sender"));
193 get_sender.add_argument (new CCodeIdentifier ("message"));
194 ccall.add_argument (get_sender);
195 continue;
198 if (get_type_signature (param.parameter_type) == null) {
199 Report.error (param.parameter_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (param.parameter_type.to_string ()));
200 continue;
203 if (!m.coroutine || param.direction == ParameterDirection.IN) {
204 var st = param.parameter_type.data_type as Struct;
205 if (param.direction != ParameterDirection.IN
206 || (st != null && !st.is_simple_type ())) {
207 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
208 } else {
209 ccall.add_argument (new CCodeIdentifier (param.name));
211 } else {
212 finish_ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
215 if (param.parameter_type is ArrayType) {
216 var array_type = (ArrayType) param.parameter_type;
218 for (int dim = 1; dim <= array_type.rank; dim++) {
219 string length_cname = get_array_length_cname (param.name, dim);
221 cdecl = new CCodeDeclaration ("int");
222 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
223 prefragment.append (cdecl);
224 if (param.direction != ParameterDirection.IN) {
225 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
226 } else {
227 ccall.add_argument (new CCodeIdentifier (length_cname));
232 if (param.direction == ParameterDirection.IN) {
233 type_signature += get_type_signature (param.parameter_type);
235 var target = new CCodeIdentifier (param.name);
236 var expr = read_expression (prefragment, param.parameter_type, new CCodeIdentifier ("iter"), target);
237 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
238 } else {
239 write_expression (out_postfragment, param.parameter_type, new CCodeIdentifier ("iter"), new CCodeIdentifier (param.name));
242 if (requires_destroy (owned_type)) {
243 // keep local alive (symbol_reference is weak)
244 var local = new LocalVariable (owned_type, param.name);
245 var ma = new MemberAccess.simple (param.name);
246 ma.symbol_reference = local;
247 var stmt = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (param.name), owned_type, ma));
248 if (param.direction == ParameterDirection.IN) {
249 in_postfragment.append (stmt);
250 } else {
251 out_postfragment.append (stmt);
256 signature_check.add_argument (new CCodeConstant ("\"%s\"".printf (type_signature)));
258 if (!(m.return_type is VoidType)) {
259 if (get_type_signature (m.return_type) == null) {
260 Report.error (m.return_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (m.return_type.to_string ()));
261 } else {
262 cdecl = new CCodeDeclaration (m.return_type.get_cname ());
263 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
264 out_postfragment.append (cdecl);
265 if (!m.coroutine) {
266 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
267 } else {
268 block.add_statement (new CCodeExpressionStatement (ccall));
269 ready_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), finish_ccall)));
272 if (m.return_type is ArrayType) {
273 var array_type = (ArrayType) m.return_type;
275 for (int dim = 1; dim <= array_type.rank; dim++) {
276 string length_cname = get_array_length_cname ("result", dim);
278 cdecl = new CCodeDeclaration ("int");
279 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
280 prefragment.append (cdecl);
281 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
285 write_expression (out_postfragment, m.return_type, new CCodeIdentifier ("iter"), new CCodeIdentifier ("result"));
287 if (requires_destroy (m.return_type)) {
288 // keep local alive (symbol_reference is weak)
289 // space before `result' is work around to not trigger
290 // variable renaming, we really mean C identifier `result' here
291 var local = new LocalVariable (m.return_type, " result");
292 var ma = new MemberAccess.simple ("result");
293 ma.symbol_reference = local;
294 out_postfragment.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("result"), m.return_type, ma)));
297 } else {
298 block.add_statement (new CCodeExpressionStatement (ccall));
299 if (m.coroutine) {
300 ready_block.add_statement (new CCodeExpressionStatement (finish_ccall));
304 if (m.coroutine) {
305 ccall.add_argument (new CCodeIdentifier (wrapper_name + "_ready"));
307 var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
308 new_call.add_argument (new CCodeIdentifier ("gpointer"));
309 new_call.add_argument (new CCodeConstant ("2"));
310 cdecl = new CCodeDeclaration ("gpointer *");
311 cdecl.add_declarator (new CCodeVariableDeclarator ("user_data", new_call));
312 prefragment.append (cdecl);
314 var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_ref"));
315 ref_call.add_argument (new CCodeIdentifier ("connection"));
316 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("user_data[0]"), ref_call)));
317 ref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_ref"));
318 ref_call.add_argument (new CCodeIdentifier ("message"));
319 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("user_data[1]"), ref_call)));
321 ccall.add_argument (new CCodeIdentifier ("user_data"));
324 if (m.get_error_types ().size > 0) {
325 if (m.coroutine) {
326 finish_ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
327 } else {
328 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
331 var error_block = new CCodeBlock ();
333 generate_server_error_cases (error_block, m.get_error_types (), new CCodeIdentifier ("error"), new CCodeIdentifier ("message"), new CCodeIdentifier ("reply"));
335 send_reply (error_block);
336 error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
338 if (m.coroutine) {
339 ready_block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("error"), error_block));
340 } else {
341 block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("error"), error_block));
345 block.add_statement (in_postfragment);
347 if (!m.coroutine) {
348 handle_reply (block);
349 } else {
350 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
352 ready_block.add_statement (out_postfragment);
354 send_reply (ready_block);
356 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_unref"));
357 unref_call.add_argument (new CCodeIdentifier ("connection"));
358 ready_block.add_statement (new CCodeExpressionStatement (unref_call));
359 unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
360 unref_call.add_argument (new CCodeIdentifier ("message"));
361 ready_block.add_statement (new CCodeExpressionStatement (unref_call));
362 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
363 free_call.add_argument (new CCodeIdentifier ("user_data"));
364 ready_block.add_statement (new CCodeExpressionStatement (free_call));
367 source_declarations.add_type_member_declaration (function.copy ());
369 function.block = block;
370 source_type_member_definition.append (function);
372 if (m.coroutine) {
373 source_declarations.add_type_member_declaration (ready_function.copy ());
375 ready_function.block = ready_block;
376 source_type_member_definition.append (ready_function);
379 return wrapper_name;
382 void generate_server_error_cases (CCodeBlock error_block, Gee.List<DataType> error_types, CCodeExpression error, CCodeExpression message, CCodeExpression reply) {
383 CCodeStatement if_else_if = null;
384 CCodeIfStatement last_statement = null;
386 foreach (DataType error_type in error_types) {
387 var edomain = ((ErrorType) error_type).error_domain;
389 var edomain_dbus_name = get_dbus_name (edomain);
390 if (edomain_dbus_name == null) {
391 Report.error (edomain.source_reference, "Errordomain must have a DBus.name annotation to be serialized over DBus");
394 var true_block = new CCodeBlock ();
395 true_block.suppress_newline = true;
397 var cswitch = new CCodeSwitchStatement (new CCodeMemberAccess.pointer (error, "code"));
398 foreach (ErrorCode ecode in edomain.get_codes ()) {
399 cswitch.add_statement (new CCodeCaseStatement (new CCodeIdentifier (ecode.get_cname ())));
401 var ecode_dbus_name = get_dbus_name (ecode);
402 if (ecode_dbus_name == null) {
403 ecode_dbus_name = Symbol.lower_case_to_camel_case (ecode.name.down ());
406 string dbus_name = "%s.%s".printf (edomain_dbus_name, ecode_dbus_name);
408 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_error"));
409 msgcall.add_argument (message);
410 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_name)));
411 msgcall.add_argument (new CCodeMemberAccess.pointer (error, "message"));
412 cswitch.add_statement (new CCodeExpressionStatement (new CCodeAssignment (reply, msgcall)));
414 cswitch.add_statement (new CCodeBreakStatement ());
416 true_block.add_statement (cswitch);
418 var equal_test = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeMemberAccess.pointer (error, "domain"), new CCodeIdentifier (edomain.get_upper_case_cname ()));
419 var stmt = new CCodeIfStatement (equal_test, true_block);
421 if (last_statement != null) {
422 last_statement.false_statement = stmt;
423 } else {
424 if_else_if = stmt;
426 last_statement = stmt;
428 error_block.add_statement (if_else_if);
431 string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
432 string wrapper_name = "_dbus_%s_%s".printf (sym.get_lower_case_cname (), sig.get_cname ());
434 // declaration
436 CCodeDeclaration cdecl;
438 var function = new CCodeFunction (wrapper_name, "void");
439 function.modifiers = CCodeModifiers.STATIC;
441 function.add_parameter (new CCodeFormalParameter ("_sender", "GObject*"));
443 foreach (var param in sig.get_parameters ()) {
444 // ensure ccodenode of parameter is set
445 generate_parameter (param, source_declarations, new HashMap<int,CCodeFormalParameter> (), null);
447 function.add_parameter ((CCodeFormalParameter) get_ccodenode (param));
448 if (param.parameter_type is ArrayType) {
449 var array_type = (ArrayType) param.parameter_type;
450 for (int dim = 1; dim <= array_type.rank; dim++) {
451 function.add_parameter (new CCodeFormalParameter (head.get_array_length_cname (param.name, dim), "int"));
456 function.add_parameter (new CCodeFormalParameter ("_connection", "DBusConnection*"));
458 var block = new CCodeBlock ();
459 var prefragment = new CCodeFragment ();
461 var path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get_data"));
462 path.add_argument (new CCodeIdentifier ("_sender"));
463 path.add_argument (new CCodeConstant ("\"dbus_object_path\""));
465 cdecl = new CCodeDeclaration ("const char *");
466 cdecl.add_declarator (new CCodeVariableDeclarator ("_path", path));
467 block.add_statement (cdecl);
469 cdecl = new CCodeDeclaration ("DBusMessage");
470 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
471 block.add_statement (cdecl);
473 cdecl = new CCodeDeclaration ("DBusMessageIter");
474 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
475 block.add_statement (cdecl);
477 block.add_statement (prefragment);
479 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_signal"));
480 msgcall.add_argument (new CCodeIdentifier ("_path"));
481 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
482 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (sig.name))));
483 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall)));
485 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
486 iter_call.add_argument (new CCodeIdentifier ("_message"));
487 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
488 prefragment.append (new CCodeExpressionStatement (iter_call));
490 foreach (FormalParameter param in sig.get_parameters ()) {
491 CCodeExpression expr = new CCodeIdentifier (param.name);
492 if (param.parameter_type.is_real_struct_type ()) {
493 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
495 write_expression (prefragment, param.parameter_type, new CCodeIdentifier ("_iter"), expr);
498 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send"));
499 ccall.add_argument (new CCodeIdentifier ("_connection"));
500 ccall.add_argument (new CCodeIdentifier ("_message"));
501 ccall.add_argument (new CCodeConstant ("NULL"));
502 block.add_statement (new CCodeExpressionStatement (ccall));
504 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
505 message_unref.add_argument (new CCodeIdentifier ("_message"));
506 block.add_statement (new CCodeExpressionStatement (message_unref));
508 source_declarations.add_type_member_declaration (function.copy ());
509 function.block = block;
510 source_type_member_definition.append (function);
512 return wrapper_name;
515 void generate_register_function (ObjectType object_type) {
516 var sym = object_type.type_symbol;
518 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_register_object", "void");
519 cfunc.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
520 cfunc.add_parameter (new CCodeFormalParameter ("path", "const char*"));
521 cfunc.add_parameter (new CCodeFormalParameter ("object", "void*"));
523 if (!sym.is_private_symbol ()) {
524 dbus_glib_h_needed_in_header = true;
525 } else {
526 dbus_glib_h_needed = true;
528 cfunc.modifiers |= CCodeModifiers.STATIC;
531 source_declarations.add_type_member_declaration (cfunc.copy ());
533 var block = new CCodeBlock ();
534 cfunc.block = block;
536 var get_path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get_data"));
537 get_path.add_argument (new CCodeIdentifier ("object"));
538 get_path.add_argument (new CCodeConstant ("\"dbus_object_path\""));
539 var register_check = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, get_path);
541 var register_block = new CCodeBlock ();
543 var path_dup = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup"));
544 path_dup.add_argument (new CCodeIdentifier ("path"));
546 var set_path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_set_data"));
547 set_path.add_argument (new CCodeIdentifier ("object"));
548 set_path.add_argument (new CCodeConstant ("\"dbus_object_path\""));
549 set_path.add_argument (path_dup);
550 register_block.add_statement (new CCodeExpressionStatement (set_path));
552 var cregister = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_register_object_path"));
553 cregister.add_argument (new CCodeIdentifier ("connection"));
554 cregister.add_argument (new CCodeIdentifier ("path"));
555 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_path_vtable (object_type)));
556 cregister.add_argument (new CCodeIdentifier ("object"));
557 register_block.add_statement (new CCodeExpressionStatement (cregister));
559 var weak_unregister = new CCodeFunctionCall (new CCodeIdentifier ("g_object_weak_ref"));
560 weak_unregister.add_argument (new CCodeIdentifier ("object"));
561 weak_unregister.add_argument (new CCodeIdentifier ("_vala_dbus_unregister_object"));
562 weak_unregister.add_argument (new CCodeIdentifier ("connection"));
563 register_block.add_statement (new CCodeExpressionStatement (weak_unregister));
565 block.add_statement (new CCodeIfStatement (register_check, register_block));
567 handle_signals (object_type.type_symbol, block);
569 var cl = sym as Class;
570 if (cl != null) {
571 foreach (DataType base_type in cl.get_base_types ()) {
572 var base_obj_type = base_type as ObjectType;
573 if (type_implements_dbus_interface (base_obj_type.type_symbol)) {
574 var base_register = new CCodeFunctionCall (new CCodeIdentifier (base_obj_type.type_symbol.get_lower_case_cprefix () + "dbus_register_object"));
575 base_register.add_argument (new CCodeIdentifier ("connection"));
576 base_register.add_argument (new CCodeIdentifier ("path"));
577 base_register.add_argument (new CCodeIdentifier ("object"));
578 block.add_statement (new CCodeExpressionStatement (base_register));
583 source_type_member_definition.append (cfunc);
586 void generate_unregister_function (ObjectType object_type) {
587 var sym = object_type.type_symbol;
589 var cfunc = new CCodeFunction ("_" + sym.get_lower_case_cprefix () + "dbus_unregister", "void");
590 cfunc.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
591 cfunc.add_parameter (new CCodeFormalParameter ("user_data", "void*"));
593 source_declarations.add_type_member_declaration (cfunc.copy ());
595 var block = new CCodeBlock ();
596 cfunc.block = block;
598 source_type_member_definition.append (cfunc);
601 void handle_method (string dbus_iface_name, string dbus_method_name, string handler_name, CCodeBlock block, ref CCodeIfStatement clastif) {
602 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_is_method_call"));
603 ccheck.add_argument (new CCodeIdentifier ("message"));
604 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
605 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_method_name)));
607 var callblock = new CCodeBlock ();
609 var ccall = new CCodeFunctionCall (new CCodeIdentifier (handler_name));
610 ccall.add_argument (new CCodeIdentifier ("object"));
611 ccall.add_argument (new CCodeIdentifier ("connection"));
612 ccall.add_argument (new CCodeIdentifier ("message"));
614 callblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
616 var cif = new CCodeIfStatement (ccheck, callblock);
617 if (clastif == null) {
618 block.add_statement (cif);
619 } else {
620 clastif.false_statement = cif;
623 clastif = cif;
626 void handle_methods (ObjectTypeSymbol sym, string dbus_iface_name, CCodeBlock block, ref CCodeIfStatement clastif) {
627 foreach (Method m in sym.get_methods ()) {
628 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
629 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
630 continue;
632 if (!is_dbus_visible (m)) {
633 continue;
636 handle_method (dbus_iface_name, Symbol.lower_case_to_camel_case (m.name), generate_dbus_wrapper (m, sym), block, ref clastif);
640 string generate_dbus_property_get_wrapper (ObjectTypeSymbol sym, string dbus_iface_name) {
641 string wrapper_name = "_dbus_%s_property_get".printf (sym.get_lower_case_cname ());
643 CCodeDeclaration cdecl;
645 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
646 function.modifiers = CCodeModifiers.STATIC;
648 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
649 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
650 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
652 var block = new CCodeBlock ();
653 var prefragment = new CCodeFragment ();
655 cdecl = new CCodeDeclaration ("DBusMessage*");
656 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
657 block.add_statement (cdecl);
659 cdecl = new CCodeDeclaration ("DBusMessageIter");
660 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
661 cdecl.add_declarator (new CCodeVariableDeclarator ("reply_iter"));
662 cdecl.add_declarator (new CCodeVariableDeclarator ("subiter"));
663 block.add_statement (cdecl);
665 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
666 message_signature.add_argument (new CCodeIdentifier ("message"));
667 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
668 signature_check.add_argument (message_signature);
669 signature_check.add_argument (new CCodeConstant ("\"ss\""));
670 var signature_error_block = new CCodeBlock ();
671 signature_error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
672 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
674 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
675 iter_call.add_argument (new CCodeIdentifier ("message"));
676 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
677 block.add_statement (new CCodeExpressionStatement (iter_call));
679 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
680 msgcall.add_argument (new CCodeIdentifier ("message"));
681 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
683 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
684 iter_call.add_argument (new CCodeIdentifier ("reply"));
685 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
686 block.add_statement (new CCodeExpressionStatement (iter_call));
688 block.add_statement (prefragment);
690 cdecl = new CCodeDeclaration ("char*");
691 cdecl.add_declarator (new CCodeVariableDeclarator ("interface_name"));
692 prefragment.append (cdecl);
693 var target = new CCodeIdentifier ("interface_name");
694 var expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
695 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
697 cdecl = new CCodeDeclaration ("char*");
698 cdecl.add_declarator (new CCodeVariableDeclarator ("property_name"));
699 prefragment.append (cdecl);
700 target = new CCodeIdentifier ("property_name");
701 expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
702 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
704 CCodeIfStatement clastif = null;
706 foreach (Property prop in sym.get_properties ()) {
707 if (prop.binding != MemberBinding.INSTANCE
708 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
709 continue;
711 if (!is_dbus_visible (prop)) {
712 continue;
714 if (prop.get_accessor == null) {
715 continue;
718 var prop_block = new CCodeBlock ();
719 var postfragment = new CCodeFragment ();
720 prop_block.add_statement (postfragment);
722 var ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
723 ccmp.add_argument (new CCodeIdentifier ("interface_name"));
724 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
725 var ccheck1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
727 ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
728 ccmp.add_argument (new CCodeIdentifier ("property_name"));
729 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (prop.name))));
730 var ccheck2 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
732 var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccheck1, ccheck2);
734 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
735 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
736 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_VARIANT"));
737 iter_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_signature (prop.property_type))));
738 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
739 postfragment.append (new CCodeExpressionStatement (iter_call));
741 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.get_accessor.get_cname ()));
742 ccall.add_argument (new CCodeIdentifier ("self"));
744 cdecl = new CCodeDeclaration (prop.property_type.get_cname ());
745 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
746 postfragment.append (cdecl);
747 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
749 var array_type = prop.property_type as ArrayType;
750 if (array_type != null) {
751 for (int dim = 1; dim <= array_type.rank; dim++) {
752 string length_cname = get_array_length_cname ("result", dim);
754 cdecl = new CCodeDeclaration ("int");
755 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname));
756 postfragment.append (cdecl);
758 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
762 write_expression (postfragment, prop.property_type, new CCodeIdentifier ("subiter"), new CCodeIdentifier ("result"));
764 if (requires_destroy (prop.get_accessor.value_type)) {
765 // keep local alive (symbol_reference is weak)
766 // space before `result' is work around to not trigger
767 // variable renaming, we really mean C identifier `result' here
768 var local = new LocalVariable (prop.get_accessor.value_type, " result");
769 var ma = new MemberAccess.simple ("result");
770 ma.symbol_reference = local;
771 postfragment.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("result"), prop.get_accessor.value_type, ma)));
774 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
775 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
776 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
777 postfragment.append (new CCodeExpressionStatement (iter_call));
779 var cif = new CCodeIfStatement (ccheck, prop_block);
780 if (clastif == null) {
781 block.add_statement (cif);
782 } else {
783 clastif.false_statement = cif;
786 clastif = cif;
789 // free interface_name and property_name
790 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
791 free_call.add_argument (new CCodeIdentifier ("interface_name"));
792 block.add_statement (new CCodeExpressionStatement (free_call));
794 free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
795 free_call.add_argument (new CCodeIdentifier ("property_name"));
796 block.add_statement (new CCodeExpressionStatement (free_call));
798 if (clastif == null) {
799 block = new CCodeBlock ();
800 block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
801 } else {
802 var else_block = new CCodeBlock ();
803 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
804 unref_call.add_argument (new CCodeIdentifier ("reply"));
805 else_block.add_statement (new CCodeExpressionStatement (unref_call));
806 else_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), new CCodeConstant ("NULL"))));
807 clastif.false_statement = else_block;
809 handle_reply (block);
812 source_declarations.add_type_member_declaration (function.copy ());
814 function.block = block;
815 source_type_member_definition.append (function);
817 return wrapper_name;
820 string generate_dbus_property_get_all_wrapper (ObjectTypeSymbol sym, string dbus_iface_name) {
821 string wrapper_name = "_dbus_%s_property_get_all".printf (sym.get_lower_case_cname ());
823 bool has_readable_properties = false;
824 foreach (Property prop in sym.get_properties ()) {
825 if (prop.binding != MemberBinding.INSTANCE
826 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
827 continue;
829 if (!is_dbus_visible (prop)) {
830 continue;
832 if (prop.get_accessor != null) {
833 has_readable_properties = true;
837 CCodeDeclaration cdecl;
839 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
840 function.modifiers = CCodeModifiers.STATIC;
842 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
843 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
844 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
846 var block = new CCodeBlock ();
847 var prefragment = new CCodeFragment ();
849 cdecl = new CCodeDeclaration ("DBusMessage*");
850 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
851 block.add_statement (cdecl);
853 cdecl = new CCodeDeclaration ("DBusMessageIter");
854 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
855 cdecl.add_declarator (new CCodeVariableDeclarator ("reply_iter"));
856 cdecl.add_declarator (new CCodeVariableDeclarator ("subiter"));
857 if (has_readable_properties) {
858 cdecl.add_declarator (new CCodeVariableDeclarator ("entry_iter"));
859 cdecl.add_declarator (new CCodeVariableDeclarator ("value_iter"));
861 block.add_statement (cdecl);
863 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
864 message_signature.add_argument (new CCodeIdentifier ("message"));
865 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
866 signature_check.add_argument (message_signature);
867 signature_check.add_argument (new CCodeConstant ("\"s\""));
868 var signature_error_block = new CCodeBlock ();
869 signature_error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
870 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
872 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
873 iter_call.add_argument (new CCodeIdentifier ("message"));
874 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
875 block.add_statement (new CCodeExpressionStatement (iter_call));
877 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
878 msgcall.add_argument (new CCodeIdentifier ("message"));
879 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
881 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
882 iter_call.add_argument (new CCodeIdentifier ("reply"));
883 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
884 block.add_statement (new CCodeExpressionStatement (iter_call));
886 block.add_statement (prefragment);
888 cdecl = new CCodeDeclaration ("char*");
889 cdecl.add_declarator (new CCodeVariableDeclarator ("interface_name"));
890 prefragment.append (cdecl);
891 var target = new CCodeIdentifier ("interface_name");
892 var expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
893 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
895 if (has_readable_properties) {
896 cdecl = new CCodeDeclaration ("const char*");
897 cdecl.add_declarator (new CCodeVariableDeclarator ("property_name"));
898 prefragment.append (cdecl);
901 var prop_block = new CCodeBlock ();
903 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
904 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
905 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_ARRAY"));
906 iter_call.add_argument (new CCodeConstant ("\"{sv}\""));
907 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
908 prop_block.add_statement (new CCodeExpressionStatement (iter_call));
910 foreach (Property prop in sym.get_properties ()) {
911 if (prop.binding != MemberBinding.INSTANCE
912 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
913 continue;
915 if (!is_dbus_visible (prop)) {
916 continue;
918 if (prop.get_accessor == null) {
919 continue;
922 var inner_block = new CCodeBlock ();
923 prop_block.add_statement (inner_block);
924 var postfragment = new CCodeFragment ();
925 inner_block.add_statement (postfragment);
927 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
928 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
929 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_DICT_ENTRY"));
930 iter_call.add_argument (new CCodeConstant ("NULL"));
931 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
932 postfragment.append (new CCodeExpressionStatement (iter_call));
934 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("property_name"), new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (prop.name))))));
936 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_append_basic"));
937 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
938 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_STRING"));
939 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("property_name")));
940 postfragment.append (new CCodeExpressionStatement (iter_call));
942 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
943 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
944 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_VARIANT"));
945 iter_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_signature (prop.property_type))));
946 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value_iter")));
947 postfragment.append (new CCodeExpressionStatement (iter_call));
949 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.get_accessor.get_cname ()));
950 ccall.add_argument (new CCodeIdentifier ("self"));
952 cdecl = new CCodeDeclaration (prop.property_type.get_cname ());
953 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
954 postfragment.append (cdecl);
955 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
957 var array_type = prop.property_type as ArrayType;
958 if (array_type != null) {
959 for (int dim = 1; dim <= array_type.rank; dim++) {
960 string length_cname = get_array_length_cname ("result", dim);
962 cdecl = new CCodeDeclaration ("int");
963 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname));
964 postfragment.append (cdecl);
966 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
970 write_expression (postfragment, prop.property_type, new CCodeIdentifier ("value_iter"), new CCodeIdentifier ("result"));
972 if (requires_destroy (prop.get_accessor.value_type)) {
973 // keep local alive (symbol_reference is weak)
974 // space before `result' is work around to not trigger
975 // variable renaming, we really mean C identifier `result' here
976 var local = new LocalVariable (prop.get_accessor.value_type, " result");
977 var ma = new MemberAccess.simple ("result");
978 ma.symbol_reference = local;
979 postfragment.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("result"), prop.get_accessor.value_type, ma)));
982 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
983 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
984 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value_iter")));
985 postfragment.append (new CCodeExpressionStatement (iter_call));
987 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
988 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
989 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
990 postfragment.append (new CCodeExpressionStatement (iter_call));
993 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
994 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
995 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
996 prop_block.add_statement (new CCodeExpressionStatement (iter_call));
998 var ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
999 ccmp.add_argument (new CCodeIdentifier ("interface_name"));
1000 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1001 var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
1003 var else_block = new CCodeBlock ();
1004 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1005 unref_call.add_argument (new CCodeIdentifier ("reply"));
1006 else_block.add_statement (new CCodeExpressionStatement (unref_call));
1007 else_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), new CCodeConstant ("NULL"))));
1009 block.add_statement (new CCodeIfStatement (ccheck, prop_block, else_block));
1011 // free interface_name
1012 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1013 free_call.add_argument (new CCodeIdentifier ("interface_name"));
1014 block.add_statement (new CCodeExpressionStatement (free_call));
1016 handle_reply (block);
1018 source_declarations.add_type_member_declaration (function.copy ());
1020 function.block = block;
1021 source_type_member_definition.append (function);
1023 return wrapper_name;
1026 string generate_dbus_property_set_wrapper (ObjectTypeSymbol sym, string dbus_iface_name) {
1027 string wrapper_name = "_dbus_%s_property_set".printf (sym.get_lower_case_cname ());
1029 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
1030 function.modifiers = CCodeModifiers.STATIC;
1032 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
1033 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
1034 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
1036 var block = new CCodeBlock ();
1037 var prefragment = new CCodeFragment ();
1039 var cdecl = new CCodeDeclaration ("DBusMessage*");
1040 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
1041 block.add_statement (cdecl);
1043 cdecl = new CCodeDeclaration ("DBusMessageIter");
1044 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
1045 cdecl.add_declarator (new CCodeVariableDeclarator ("subiter"));
1046 block.add_statement (cdecl);
1048 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
1049 message_signature.add_argument (new CCodeIdentifier ("message"));
1050 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1051 signature_check.add_argument (message_signature);
1052 signature_check.add_argument (new CCodeConstant ("\"ssv\""));
1053 var signature_error_block = new CCodeBlock ();
1054 signature_error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1055 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
1057 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
1058 iter_call.add_argument (new CCodeIdentifier ("message"));
1059 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1060 block.add_statement (new CCodeExpressionStatement (iter_call));
1062 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
1063 msgcall.add_argument (new CCodeIdentifier ("message"));
1064 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
1066 block.add_statement (prefragment);
1068 cdecl = new CCodeDeclaration ("char*");
1069 cdecl.add_declarator (new CCodeVariableDeclarator ("interface_name"));
1070 prefragment.append (cdecl);
1071 var target = new CCodeIdentifier ("interface_name");
1072 var expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
1073 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1075 cdecl = new CCodeDeclaration ("char*");
1076 cdecl.add_declarator (new CCodeVariableDeclarator ("property_name"));
1077 prefragment.append (cdecl);
1078 target = new CCodeIdentifier ("property_name");
1079 expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
1080 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1082 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_recurse"));
1083 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1084 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
1085 prefragment.append (new CCodeExpressionStatement (iter_call));
1087 CCodeIfStatement clastif = null;
1089 foreach (Property prop in sym.get_properties ()) {
1090 if (prop.binding != MemberBinding.INSTANCE
1091 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
1092 continue;
1094 if (!is_dbus_visible (prop)) {
1095 continue;
1097 if (prop.set_accessor == null) {
1098 continue;
1101 var prop_block = new CCodeBlock ();
1102 prefragment = new CCodeFragment ();
1103 prop_block.add_statement (prefragment);
1105 var ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1106 ccmp.add_argument (new CCodeIdentifier ("interface_name"));
1107 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1108 var ccheck1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
1110 ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1111 ccmp.add_argument (new CCodeIdentifier ("property_name"));
1112 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (prop.name))));
1113 var ccheck2 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
1115 var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccheck1, ccheck2);
1117 var owned_type = prop.property_type.copy ();
1118 owned_type.value_owned = true;
1120 cdecl = new CCodeDeclaration (owned_type.get_cname ());
1121 cdecl.add_declarator (new CCodeVariableDeclarator ("value"));
1122 prefragment.append (cdecl);
1124 target = new CCodeIdentifier ("value");
1125 expr = read_expression (prefragment, prop.property_type, new CCodeIdentifier ("subiter"), target);
1126 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1128 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.set_accessor.get_cname ()));
1129 ccall.add_argument (new CCodeIdentifier ("self"));
1130 ccall.add_argument (new CCodeIdentifier ("value"));
1132 var array_type = prop.property_type as ArrayType;
1133 if (array_type != null) {
1134 for (int dim = 1; dim <= array_type.rank; dim++) {
1135 cdecl = new CCodeDeclaration ("int");
1136 cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname ("value", dim)));
1137 prefragment.append (cdecl);
1139 ccall.add_argument (new CCodeIdentifier (head.get_array_length_cname ("value", dim)));
1143 prop_block.add_statement (new CCodeExpressionStatement (ccall));
1145 if (requires_destroy (owned_type)) {
1146 // keep local alive (symbol_reference is weak)
1147 var local = new LocalVariable (owned_type, "value");
1148 var ma = new MemberAccess.simple ("value");
1149 ma.symbol_reference = local;
1150 prop_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("value"), owned_type, ma)));
1153 var cif = new CCodeIfStatement (ccheck, prop_block);
1154 if (clastif == null) {
1155 block.add_statement (cif);
1156 } else {
1157 clastif.false_statement = cif;
1160 clastif = cif;
1163 // free interface_name and property_name
1164 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1165 free_call.add_argument (new CCodeIdentifier ("interface_name"));
1166 block.add_statement (new CCodeExpressionStatement (free_call));
1168 free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1169 free_call.add_argument (new CCodeIdentifier ("property_name"));
1170 block.add_statement (new CCodeExpressionStatement (free_call));
1172 if (clastif == null) {
1173 block = new CCodeBlock ();
1174 block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
1175 } else {
1176 var else_block = new CCodeBlock ();
1177 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1178 unref_call.add_argument (new CCodeIdentifier ("reply"));
1179 else_block.add_statement (new CCodeExpressionStatement (unref_call));
1180 else_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), new CCodeIdentifier ("NULL"))));
1181 clastif.false_statement = else_block;
1183 handle_reply (block);
1186 source_declarations.add_type_member_declaration (function.copy ());
1188 function.block = block;
1189 source_type_member_definition.append (function);
1191 return wrapper_name;
1194 string get_dbus_type_introspection (ObjectTypeSymbol sym) {
1195 string result = "";
1197 var cl = sym as Class;
1198 if (cl != null) {
1199 foreach (DataType base_type in cl.get_base_types ()) {
1200 var base_obj_type = base_type as ObjectType;
1201 result += get_dbus_type_introspection (base_obj_type.type_symbol);
1205 string dbus_iface_name = get_dbus_name (sym);
1206 if (dbus_iface_name == null) {
1207 return result;
1210 result += "<interface name=\"%s\">\n".printf (dbus_iface_name);
1212 foreach (var m in sym.get_methods ()) {
1213 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
1214 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
1215 continue;
1217 if (!is_dbus_visible (m)) {
1218 continue;
1221 result += " <method name=\"%s\">\n".printf (Symbol.lower_case_to_camel_case (m.name));
1223 foreach (var param in m.get_parameters ()) {
1224 if (param.parameter_type.data_type != null
1225 && param.parameter_type.data_type.get_full_name () == "DBus.BusName") {
1226 // skip sender parameter
1227 // (implicit in D-Bus)
1228 continue;
1231 string direction = param.direction == ParameterDirection.IN ? "in" : "out";
1232 result += " <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n".printf (param.name, get_type_signature (param.parameter_type), direction);
1234 if (!(m.return_type is VoidType)) {
1235 result += " <arg name=\"%s\" type=\"%s\" direction=\"out\"/>\n".printf (dbus_result_name (m), get_type_signature (m.return_type));
1238 result += " </method>\n";
1241 foreach (var prop in sym.get_properties ()) {
1242 if (prop.binding != MemberBinding.INSTANCE
1243 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
1244 continue;
1246 if (!is_dbus_visible (prop)) {
1247 continue;
1250 string access = (prop.get_accessor != null ? "read" : "") + (prop.set_accessor != null ? "write" : "");
1251 result += " <property name=\"%s\" type=\"%s\" access=\"%s\"/>\n".printf (Symbol.lower_case_to_camel_case (prop.name), get_type_signature (prop.property_type), access);
1254 foreach (var sig in sym.get_signals ()) {
1255 if (sig.access != SymbolAccessibility.PUBLIC) {
1256 continue;
1258 if (!is_dbus_visible (sig)) {
1259 continue;
1262 result += " <signal name=\"%s\">\n".printf (Symbol.lower_case_to_camel_case (sig.name));
1264 foreach (var param in sig.get_parameters ()) {
1265 result += " <arg name=\"%s\" type=\"%s\"/>\n".printf (param.name, get_type_signature (param.parameter_type));
1268 result += " </signal>\n";
1271 result += "</interface>\n";
1273 return result;
1276 string generate_dbus_introspect (ObjectTypeSymbol sym) {
1277 string wrapper_name = "_dbus_%s_introspect".printf (sym.get_lower_case_cname ());
1279 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
1280 function.modifiers = CCodeModifiers.STATIC;
1282 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
1283 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
1284 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
1286 var block = new CCodeBlock ();
1288 var cdecl = new CCodeDeclaration ("DBusMessage*");
1289 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
1290 block.add_statement (cdecl);
1292 cdecl = new CCodeDeclaration ("DBusMessageIter");
1293 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
1294 block.add_statement (cdecl);
1296 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
1297 msgcall.add_argument (new CCodeIdentifier ("message"));
1298 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
1300 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
1301 iter_call.add_argument (new CCodeIdentifier ("reply"));
1302 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1303 block.add_statement (new CCodeExpressionStatement (iter_call));
1305 cdecl = new CCodeDeclaration ("GString*");
1306 cdecl.add_declarator (new CCodeVariableDeclarator ("xml_data"));
1307 block.add_statement (cdecl);
1309 cdecl = new CCodeDeclaration ("char**");
1310 cdecl.add_declarator (new CCodeVariableDeclarator ("children"));
1311 block.add_statement (cdecl);
1313 cdecl = new CCodeDeclaration ("int");
1314 cdecl.add_declarator (new CCodeVariableDeclarator ("i"));
1315 block.add_statement (cdecl);
1317 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";
1318 var str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_new"));
1319 str_call.add_argument (new CCodeConstant ("\"%s\"".printf (xml_data.escape (""))));
1320 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("xml_data"), str_call)));
1322 xml_data = "<node>\n";
1323 xml_data +=
1324 """<interface name="org.freedesktop.DBus.Introspectable">
1325 <method name="Introspect">
1326 <arg name="data" direction="out" type="s"/>
1327 </method>
1328 </interface>
1329 <interface name="org.freedesktop.DBus.Properties">
1330 <method name="Get">
1331 <arg name="interface" direction="in" type="s"/>
1332 <arg name="propname" direction="in" type="s"/>
1333 <arg name="value" direction="out" type="v"/>
1334 </method>
1335 <method name="Set">
1336 <arg name="interface" direction="in" type="s"/>
1337 <arg name="propname" direction="in" type="s"/>
1338 <arg name="value" direction="in" type="v"/>
1339 </method>
1340 <method name="GetAll">
1341 <arg name="interface" direction="in" type="s"/>
1342 <arg name="props" direction="out" type="a{sv}"/>
1343 </method>
1344 </interface>
1345 """;
1346 xml_data += get_dbus_type_introspection (sym);
1347 str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_append"));
1348 str_call.add_argument (new CCodeIdentifier ("xml_data"));
1349 str_call.add_argument (new CCodeConstant ("\"%s\"".printf (xml_data.escape (""))));
1350 block.add_statement (new CCodeExpressionStatement (str_call));
1352 var get_path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get_data"));
1353 get_path.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *"));
1354 get_path.add_argument (new CCodeConstant ("\"dbus_object_path\""));
1356 var list_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_list_registered"));
1357 list_call.add_argument (new CCodeIdentifier ("connection"));
1358 list_call.add_argument (get_path);
1359 list_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("children")));
1360 block.add_statement (new CCodeExpressionStatement (list_call));
1362 // add child nodes
1363 var child_block = new CCodeBlock ();
1364 str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_append_printf"));
1365 str_call.add_argument (new CCodeIdentifier ("xml_data"));
1366 str_call.add_argument (new CCodeConstant ("\"%s\"".printf ("<node name=\"%s\"/>\n".escape (""))));
1367 str_call.add_argument (new CCodeElementAccess (new CCodeIdentifier ("children"), new CCodeIdentifier ("i")));
1368 child_block.add_statement (new CCodeExpressionStatement (str_call));
1369 var cfor = new CCodeForStatement (new CCodeElementAccess (new CCodeIdentifier ("children"), new CCodeIdentifier ("i")), child_block);
1370 cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
1371 cfor.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
1372 block.add_statement (cfor);
1374 var list_free_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_free_string_array"));
1375 list_free_call.add_argument (new CCodeIdentifier ("children"));
1376 block.add_statement (new CCodeExpressionStatement (list_free_call));
1378 xml_data = "</node>\n";
1379 str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_append"));
1380 str_call.add_argument (new CCodeIdentifier ("xml_data"));
1381 str_call.add_argument (new CCodeConstant ("\"%s\"".printf (xml_data.escape (""))));
1382 block.add_statement (new CCodeExpressionStatement (str_call));
1384 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_append_basic"));
1385 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1386 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_STRING"));
1387 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (new CCodeIdentifier ("xml_data"), "str")));
1388 block.add_statement (new CCodeExpressionStatement (iter_call));
1390 str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_free"));
1391 str_call.add_argument (new CCodeIdentifier ("xml_data"));
1392 str_call.add_argument (new CCodeConstant ("TRUE"));
1393 block.add_statement (new CCodeExpressionStatement (str_call));
1395 handle_reply (block);
1397 source_declarations.add_type_member_declaration (function.copy ());
1399 function.block = block;
1400 source_type_member_definition.append (function);
1402 return wrapper_name;
1405 void handle_signals (ObjectTypeSymbol sym, CCodeBlock block) {
1406 string dbus_iface_name = get_dbus_name (sym);
1407 if (dbus_iface_name == null) {
1408 return;
1411 foreach (Signal sig in sym.get_signals ()) {
1412 if (sig.access != SymbolAccessibility.PUBLIC) {
1413 continue;
1415 if (!is_dbus_visible (sig)) {
1416 continue;
1419 var connect = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
1420 connect.add_argument (new CCodeIdentifier ("object"));
1421 connect.add_argument (sig.get_canonical_cconstant (null));
1422 connect.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
1423 connect.add_argument (new CCodeIdentifier ("connection"));
1424 block.add_statement (new CCodeExpressionStatement (connect));
1428 void generate_message_function (ObjectType object_type) {
1429 var sym = object_type.type_symbol;
1431 dbus_glib_h_needed = true;
1433 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_message", "DBusHandlerResult");
1434 cfunc.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
1435 cfunc.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
1436 cfunc.add_parameter (new CCodeFormalParameter ("object", "void*"));
1438 if (sym.is_private_symbol ()) {
1439 cfunc.modifiers |= CCodeModifiers.STATIC;
1442 source_declarations.add_type_member_declaration (cfunc.copy ());
1444 var block = new CCodeBlock ();
1445 cfunc.block = block;
1447 var cdecl = new CCodeDeclaration ("DBusHandlerResult");
1448 cdecl.add_declarator (new CCodeVariableDeclarator ("result", new CCodeConstant ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1449 block.add_statement (cdecl);
1451 CCodeIfStatement clastif = null;
1453 handle_method ("org.freedesktop.DBus.Introspectable", "Introspect", generate_dbus_introspect (sym), block, ref clastif);
1455 string dbus_iface_name = get_dbus_name (sym);
1456 if (dbus_iface_name != null) {
1457 bool need_property_get = false;
1458 bool need_property_set = false;
1459 foreach (Property prop in sym.get_properties ()) {
1460 if (prop.binding != MemberBinding.INSTANCE
1461 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
1462 continue;
1464 if (!is_dbus_visible (prop)) {
1465 continue;
1467 if (prop.get_accessor != null) {
1468 need_property_get = true;
1470 if (prop.set_accessor != null) {
1471 need_property_set = true;
1475 if (need_property_get) {
1476 handle_method ("org.freedesktop.DBus.Properties", "Get", generate_dbus_property_get_wrapper (sym, dbus_iface_name), block, ref clastif);
1478 if (need_property_set) {
1479 handle_method ("org.freedesktop.DBus.Properties", "Set", generate_dbus_property_set_wrapper (sym, dbus_iface_name), block, ref clastif);
1481 handle_method ("org.freedesktop.DBus.Properties", "GetAll", generate_dbus_property_get_all_wrapper (sym, dbus_iface_name), block, ref clastif);
1483 handle_methods (sym, dbus_iface_name, block, ref clastif);
1486 var resultblock = new CCodeBlock ();
1487 resultblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
1488 var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("result"), new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")), resultblock);
1489 block.add_statement (cif);
1490 clastif = cif;
1492 var cl = sym as Class;
1493 if (cl != null) {
1494 foreach (DataType base_type in cl.get_base_types ()) {
1495 var base_obj_type = base_type as ObjectType;
1496 if (type_implements_dbus_interface (base_obj_type.type_symbol)) {
1497 var base_call = new CCodeFunctionCall (new CCodeIdentifier (base_obj_type.type_symbol.get_lower_case_cprefix () + "dbus_message"));
1498 base_call.add_argument (new CCodeIdentifier ("connection"));
1499 base_call.add_argument (new CCodeIdentifier ("message"));
1500 base_call.add_argument (new CCodeIdentifier ("object"));
1502 var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, base_call, new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED"));
1504 var base_block = new CCodeBlock ();
1505 base_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
1507 cif = new CCodeIfStatement (ccheck, base_block);
1508 clastif.false_statement = cif;
1510 clastif = cif;
1515 var retblock = new CCodeBlock ();
1516 retblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1517 clastif.false_statement = retblock;
1519 source_type_member_definition.append (cfunc);
1522 CCodeExpression get_vtable (ObjectType object_type) {
1523 var sym = object_type.type_symbol;
1525 var vtable = new CCodeInitializerList ();
1526 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_register_object"));
1528 generate_register_function (object_type);
1530 var cdecl = new CCodeDeclaration ("const _DBusObjectVTable");
1531 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_vtable", vtable));
1532 cdecl.modifiers = CCodeModifiers.STATIC;
1533 source_declarations.add_constant_declaration (cdecl);
1535 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_vtable");
1538 CCodeExpression get_path_vtable (ObjectType object_type) {
1539 var sym = object_type.type_symbol;
1541 var vtable = new CCodeInitializerList ();
1542 vtable.append (new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_unregister"));
1543 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_message"));
1545 generate_unregister_function (object_type);
1546 generate_message_function (object_type);
1548 var cdecl = new CCodeDeclaration ("const DBusObjectPathVTable");
1549 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_path_vtable", vtable));
1550 cdecl.modifiers = CCodeModifiers.STATIC;
1551 source_declarations.add_constant_declaration (cdecl);
1553 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_path_vtable");
1556 public override void visit_method_call (MethodCall expr) {
1557 var mtype = expr.call.value_type as MethodType;
1558 if (mtype == null || (mtype.method_symbol.get_cname () != "dbus_connection_register_g_object" &&
1559 mtype.method_symbol.get_cname () != "dbus_g_connection_register_g_object")) {
1560 base.visit_method_call (expr);
1561 return;
1564 dbus_glib_h_needed = true;
1566 expr.accept_children (codegen);
1568 var ma = (MemberAccess) expr.call;
1570 var raw_conn = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1571 raw_conn.add_argument ((CCodeExpression) ma.inner.ccodenode);
1573 var args_it = expr.get_argument_list ().iterator ();
1574 args_it.next ();
1575 var path_arg = args_it.get ();
1576 args_it.next ();
1577 var obj_arg = args_it.get ();
1579 var cregister = new CCodeFunctionCall (new CCodeIdentifier ("_vala_dbus_register_object"));
1580 if (mtype.method_symbol.get_cname () == "dbus_g_connection_register_g_object") {
1581 cregister.add_argument (raw_conn);
1582 } else {
1583 cregister.add_argument ((CCodeExpression) ma.inner.ccodenode);
1585 cregister.add_argument ((CCodeExpression) path_arg.ccodenode);
1586 cregister.add_argument ((CCodeExpression) obj_arg.ccodenode);
1587 expr.ccodenode = cregister;
1590 bool type_implements_dbus_interface (ObjectTypeSymbol sym) {
1591 var dbus = sym.get_attribute ("DBus");
1592 if (dbus != null) {
1593 return true;
1596 var cl = sym as Class;
1597 if (cl != null) {
1598 foreach (DataType base_type in cl.get_base_types ()) {
1599 var base_obj_type = base_type as ObjectType;
1600 if (type_implements_dbus_interface (base_obj_type.type_symbol)) {
1601 return true;
1606 return false;
1609 public override CCodeFragment register_dbus_info (ObjectTypeSymbol sym) {
1610 CCodeFragment fragment = new CCodeFragment ();
1612 if (!type_implements_dbus_interface (sym)) {
1613 return fragment;
1616 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1617 quark.add_argument (new CCodeConstant ("\"DBusObjectVTable\""));
1619 var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1620 set_qdata.add_argument (new CCodeIdentifier (sym.get_upper_case_cname ("TYPE_")));
1621 set_qdata.add_argument (quark);
1622 set_qdata.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_vtable (new ObjectType (sym))), "void*"));
1624 fragment.append (new CCodeExpressionStatement (set_qdata));
1626 return fragment;