D-Bus: Add get_dbus_name helper method
[vala-lang.git] / codegen / valadbusservermodule.vala
blob46bf7bf12aac6e1f147ee29f3856e13dd3ec809d
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 block.add_statement (cdecl);
133 block.add_statement (prefragment);
135 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
136 message_signature.add_argument (new CCodeIdentifier ("message"));
137 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
138 signature_check.add_argument (message_signature);
139 var signature_error_block = new CCodeBlock ();
140 signature_error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
141 prefragment.append (new CCodeIfStatement (signature_check, signature_error_block));
143 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
144 iter_call.add_argument (new CCodeIdentifier ("message"));
145 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
146 prefragment.append (new CCodeExpressionStatement (iter_call));
148 cdecl = new CCodeDeclaration ("DBusMessage*");
149 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
150 out_postfragment.append (cdecl);
152 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
153 msgcall.add_argument (new CCodeIdentifier ("message"));
154 out_postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
156 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
157 iter_call.add_argument (new CCodeIdentifier ("reply"));
158 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
159 out_postfragment.append (new CCodeExpressionStatement (iter_call));
161 var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
163 CCodeFunctionCall finish_ccall = null;
164 if (m.coroutine) {
165 finish_ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_finish_cname ()));
166 finish_ccall.add_argument (new CCodeIdentifier ("source_object"));
167 finish_ccall.add_argument (new CCodeIdentifier ("res"));
170 ccall.add_argument (new CCodeIdentifier ("self"));
172 // expected type signature for input parameters
173 string type_signature = "";
175 foreach (FormalParameter param in m.get_parameters ()) {
176 var owned_type = param.parameter_type.copy ();
177 owned_type.value_owned = true;
179 cdecl = new CCodeDeclaration (owned_type.get_cname ());
180 cdecl.add_declarator (new CCodeVariableDeclarator (param.name, default_value_for_type (param.parameter_type, true)));
181 prefragment.append (cdecl);
182 if (type_signature == ""
183 && param.direction == ParameterDirection.IN
184 && param.parameter_type.data_type != null
185 && param.parameter_type.data_type.get_full_name () == "DBus.BusName") {
186 // first parameter is a string parameter called 'sender'
187 // pass bus name of sender
188 var get_sender = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_sender"));
189 get_sender.add_argument (new CCodeIdentifier ("message"));
190 ccall.add_argument (get_sender);
191 continue;
194 if (get_type_signature (param.parameter_type) == null) {
195 Report.error (param.parameter_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (param.parameter_type.to_string ()));
196 continue;
199 if (!m.coroutine || param.direction == ParameterDirection.IN) {
200 var st = param.parameter_type.data_type as Struct;
201 if (param.direction != ParameterDirection.IN
202 || (st != null && !st.is_simple_type ())) {
203 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
204 } else {
205 ccall.add_argument (new CCodeIdentifier (param.name));
207 } else {
208 finish_ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
211 if (param.parameter_type is ArrayType) {
212 var array_type = (ArrayType) param.parameter_type;
214 for (int dim = 1; dim <= array_type.rank; dim++) {
215 string length_cname = get_array_length_cname (param.name, dim);
217 cdecl = new CCodeDeclaration ("int");
218 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
219 prefragment.append (cdecl);
220 if (param.direction != ParameterDirection.IN) {
221 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
222 } else {
223 ccall.add_argument (new CCodeIdentifier (length_cname));
228 if (param.direction == ParameterDirection.IN) {
229 type_signature += get_type_signature (param.parameter_type);
231 var target = new CCodeIdentifier (param.name);
232 var expr = read_expression (prefragment, param.parameter_type, new CCodeIdentifier ("iter"), target);
233 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
234 } else {
235 write_expression (out_postfragment, param.parameter_type, new CCodeIdentifier ("iter"), new CCodeIdentifier (param.name));
238 if (requires_destroy (owned_type)) {
239 // keep local alive (symbol_reference is weak)
240 var local = new LocalVariable (owned_type, param.name);
241 var ma = new MemberAccess.simple (param.name);
242 ma.symbol_reference = local;
243 var stmt = new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (param.name), owned_type, ma));
244 if (param.direction == ParameterDirection.IN) {
245 in_postfragment.append (stmt);
246 } else {
247 out_postfragment.append (stmt);
252 signature_check.add_argument (new CCodeConstant ("\"%s\"".printf (type_signature)));
254 if (!(m.return_type is VoidType)) {
255 if (get_type_signature (m.return_type) == null) {
256 Report.error (m.return_type.source_reference, "D-Bus serialization of type `%s' is not supported".printf (m.return_type.to_string ()));
257 } else {
258 cdecl = new CCodeDeclaration (m.return_type.get_cname ());
259 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
260 out_postfragment.append (cdecl);
261 if (!m.coroutine) {
262 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
263 } else {
264 block.add_statement (new CCodeExpressionStatement (ccall));
265 ready_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), finish_ccall)));
268 if (m.return_type is ArrayType) {
269 var array_type = (ArrayType) m.return_type;
271 for (int dim = 1; dim <= array_type.rank; dim++) {
272 string length_cname = get_array_length_cname ("result", dim);
274 cdecl = new CCodeDeclaration ("int");
275 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0")));
276 prefragment.append (cdecl);
277 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
281 write_expression (out_postfragment, m.return_type, new CCodeIdentifier ("iter"), new CCodeIdentifier ("result"));
283 if (requires_destroy (m.return_type)) {
284 // keep local alive (symbol_reference is weak)
285 // space before `result' is work around to not trigger
286 // variable renaming, we really mean C identifier `result' here
287 var local = new LocalVariable (m.return_type, " result");
288 var ma = new MemberAccess.simple ("result");
289 ma.symbol_reference = local;
290 out_postfragment.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("result"), m.return_type, ma)));
293 } else {
294 block.add_statement (new CCodeExpressionStatement (ccall));
295 if (m.coroutine) {
296 ready_block.add_statement (new CCodeExpressionStatement (finish_ccall));
300 if (m.coroutine) {
301 ccall.add_argument (new CCodeIdentifier (wrapper_name + "_ready"));
303 var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
304 new_call.add_argument (new CCodeIdentifier ("gpointer"));
305 new_call.add_argument (new CCodeConstant ("2"));
306 cdecl = new CCodeDeclaration ("gpointer *");
307 cdecl.add_declarator (new CCodeVariableDeclarator ("user_data", new_call));
308 prefragment.append (cdecl);
310 var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_ref"));
311 ref_call.add_argument (new CCodeIdentifier ("connection"));
312 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("user_data[0]"), ref_call)));
313 ref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_ref"));
314 ref_call.add_argument (new CCodeIdentifier ("message"));
315 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("user_data[1]"), ref_call)));
317 ccall.add_argument (new CCodeIdentifier ("user_data"));
320 if (m.get_error_types ().size > 0 && !m.coroutine) {
321 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
323 var error_block = new CCodeBlock ();
325 msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_error"));
326 msgcall.add_argument (new CCodeIdentifier ("message"));
327 msgcall.add_argument (new CCodeIdentifier ("DBUS_ERROR_FAILED"));
328 msgcall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("error"), "message"));
329 error_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
331 send_reply (error_block);
332 error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
334 block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("error"), error_block));
337 block.add_statement (in_postfragment);
339 if (!m.coroutine) {
340 handle_reply (block);
341 } else {
342 block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
344 ready_block.add_statement (out_postfragment);
346 send_reply (ready_block);
348 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_unref"));
349 unref_call.add_argument (new CCodeIdentifier ("connection"));
350 ready_block.add_statement (new CCodeExpressionStatement (unref_call));
351 unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
352 unref_call.add_argument (new CCodeIdentifier ("message"));
353 ready_block.add_statement (new CCodeExpressionStatement (unref_call));
354 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
355 free_call.add_argument (new CCodeIdentifier ("user_data"));
356 ready_block.add_statement (new CCodeExpressionStatement (free_call));
359 source_declarations.add_type_member_declaration (function.copy ());
361 function.block = block;
362 source_type_member_definition.append (function);
364 if (m.coroutine) {
365 source_declarations.add_type_member_declaration (ready_function.copy ());
367 ready_function.block = ready_block;
368 source_type_member_definition.append (ready_function);
371 return wrapper_name;
374 string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) {
375 string wrapper_name = "_dbus_%s_%s".printf (sym.get_lower_case_cname (), sig.get_cname ());
377 // declaration
379 CCodeDeclaration cdecl;
381 var function = new CCodeFunction (wrapper_name, "void");
382 function.modifiers = CCodeModifiers.STATIC;
384 function.add_parameter (new CCodeFormalParameter ("_sender", "GObject*"));
386 foreach (var param in sig.get_parameters ()) {
387 // ensure ccodenode of parameter is set
388 generate_parameter (param, source_declarations, new HashMap<int,CCodeFormalParameter> (), null);
390 function.add_parameter ((CCodeFormalParameter) get_ccodenode (param));
391 if (param.parameter_type is ArrayType) {
392 var array_type = (ArrayType) param.parameter_type;
393 for (int dim = 1; dim <= array_type.rank; dim++) {
394 function.add_parameter (new CCodeFormalParameter (head.get_array_length_cname (param.name, dim), "int"));
399 function.add_parameter (new CCodeFormalParameter ("_connection", "DBusConnection*"));
401 var block = new CCodeBlock ();
402 var prefragment = new CCodeFragment ();
404 var path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get_data"));
405 path.add_argument (new CCodeIdentifier ("_sender"));
406 path.add_argument (new CCodeConstant ("\"dbus_object_path\""));
408 cdecl = new CCodeDeclaration ("const char *");
409 cdecl.add_declarator (new CCodeVariableDeclarator ("_path", path));
410 block.add_statement (cdecl);
412 cdecl = new CCodeDeclaration ("DBusMessage");
413 cdecl.add_declarator (new CCodeVariableDeclarator ("*_message"));
414 block.add_statement (cdecl);
416 cdecl = new CCodeDeclaration ("DBusMessageIter");
417 cdecl.add_declarator (new CCodeVariableDeclarator ("_iter"));
418 block.add_statement (cdecl);
420 block.add_statement (prefragment);
422 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_signal"));
423 msgcall.add_argument (new CCodeIdentifier ("_path"));
424 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
425 msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (sig.name))));
426 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall)));
428 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
429 iter_call.add_argument (new CCodeIdentifier ("_message"));
430 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter")));
431 prefragment.append (new CCodeExpressionStatement (iter_call));
433 foreach (FormalParameter param in sig.get_parameters ()) {
434 CCodeExpression expr = new CCodeIdentifier (param.name);
435 if (param.parameter_type.is_real_struct_type ()) {
436 expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr);
438 write_expression (prefragment, param.parameter_type, new CCodeIdentifier ("_iter"), expr);
441 var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send"));
442 ccall.add_argument (new CCodeIdentifier ("_connection"));
443 ccall.add_argument (new CCodeIdentifier ("_message"));
444 ccall.add_argument (new CCodeConstant ("NULL"));
445 block.add_statement (new CCodeExpressionStatement (ccall));
447 var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
448 message_unref.add_argument (new CCodeIdentifier ("_message"));
449 block.add_statement (new CCodeExpressionStatement (message_unref));
451 source_declarations.add_type_member_declaration (function.copy ());
452 function.block = block;
453 source_type_member_definition.append (function);
455 return wrapper_name;
458 void generate_register_function (ObjectType object_type) {
459 var sym = object_type.type_symbol;
461 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_register_object", "void");
462 cfunc.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
463 cfunc.add_parameter (new CCodeFormalParameter ("path", "const char*"));
464 cfunc.add_parameter (new CCodeFormalParameter ("object", "void*"));
466 if (!sym.is_private_symbol ()) {
467 dbus_glib_h_needed_in_header = true;
468 } else {
469 dbus_glib_h_needed = true;
471 cfunc.modifiers |= CCodeModifiers.STATIC;
474 source_declarations.add_type_member_declaration (cfunc.copy ());
476 var block = new CCodeBlock ();
477 cfunc.block = block;
479 var get_path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get_data"));
480 get_path.add_argument (new CCodeIdentifier ("object"));
481 get_path.add_argument (new CCodeConstant ("\"dbus_object_path\""));
482 var register_check = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, get_path);
484 var register_block = new CCodeBlock ();
486 var path_dup = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup"));
487 path_dup.add_argument (new CCodeIdentifier ("path"));
489 var set_path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_set_data"));
490 set_path.add_argument (new CCodeIdentifier ("object"));
491 set_path.add_argument (new CCodeConstant ("\"dbus_object_path\""));
492 set_path.add_argument (path_dup);
493 register_block.add_statement (new CCodeExpressionStatement (set_path));
495 var cregister = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_register_object_path"));
496 cregister.add_argument (new CCodeIdentifier ("connection"));
497 cregister.add_argument (new CCodeIdentifier ("path"));
498 cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_path_vtable (object_type)));
499 cregister.add_argument (new CCodeIdentifier ("object"));
500 register_block.add_statement (new CCodeExpressionStatement (cregister));
502 var weak_unregister = new CCodeFunctionCall (new CCodeIdentifier ("g_object_weak_ref"));
503 weak_unregister.add_argument (new CCodeIdentifier ("object"));
504 weak_unregister.add_argument (new CCodeIdentifier ("_vala_dbus_unregister_object"));
505 weak_unregister.add_argument (new CCodeIdentifier ("connection"));
506 register_block.add_statement (new CCodeExpressionStatement (weak_unregister));
508 block.add_statement (new CCodeIfStatement (register_check, register_block));
510 handle_signals (object_type.type_symbol, block);
512 var cl = sym as Class;
513 if (cl != null) {
514 foreach (DataType base_type in cl.get_base_types ()) {
515 var base_obj_type = base_type as ObjectType;
516 if (type_implements_dbus_interface (base_obj_type.type_symbol)) {
517 var base_register = new CCodeFunctionCall (new CCodeIdentifier (base_obj_type.type_symbol.get_lower_case_cprefix () + "dbus_register_object"));
518 base_register.add_argument (new CCodeIdentifier ("connection"));
519 base_register.add_argument (new CCodeIdentifier ("path"));
520 base_register.add_argument (new CCodeIdentifier ("object"));
521 block.add_statement (new CCodeExpressionStatement (base_register));
526 source_type_member_definition.append (cfunc);
529 void generate_unregister_function (ObjectType object_type) {
530 var sym = object_type.type_symbol;
532 var cfunc = new CCodeFunction ("_" + sym.get_lower_case_cprefix () + "dbus_unregister", "void");
533 cfunc.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
534 cfunc.add_parameter (new CCodeFormalParameter ("user_data", "void*"));
536 source_declarations.add_type_member_declaration (cfunc.copy ());
538 var block = new CCodeBlock ();
539 cfunc.block = block;
541 source_type_member_definition.append (cfunc);
544 void handle_method (string dbus_iface_name, string dbus_method_name, string handler_name, CCodeBlock block, ref CCodeIfStatement clastif) {
545 var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_is_method_call"));
546 ccheck.add_argument (new CCodeIdentifier ("message"));
547 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
548 ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_method_name)));
550 var callblock = new CCodeBlock ();
552 var ccall = new CCodeFunctionCall (new CCodeIdentifier (handler_name));
553 ccall.add_argument (new CCodeIdentifier ("object"));
554 ccall.add_argument (new CCodeIdentifier ("connection"));
555 ccall.add_argument (new CCodeIdentifier ("message"));
557 callblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
559 var cif = new CCodeIfStatement (ccheck, callblock);
560 if (clastif == null) {
561 block.add_statement (cif);
562 } else {
563 clastif.false_statement = cif;
566 clastif = cif;
569 void handle_methods (ObjectTypeSymbol sym, string dbus_iface_name, CCodeBlock block, ref CCodeIfStatement clastif) {
570 foreach (Method m in sym.get_methods ()) {
571 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
572 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
573 continue;
575 if (!is_dbus_visible (m)) {
576 continue;
579 handle_method (dbus_iface_name, Symbol.lower_case_to_camel_case (m.name), generate_dbus_wrapper (m, sym), block, ref clastif);
583 string generate_dbus_property_get_wrapper (ObjectTypeSymbol sym, string dbus_iface_name) {
584 string wrapper_name = "_dbus_%s_property_get".printf (sym.get_lower_case_cname ());
586 CCodeDeclaration cdecl;
588 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
589 function.modifiers = CCodeModifiers.STATIC;
591 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
592 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
593 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
595 var block = new CCodeBlock ();
596 var prefragment = new CCodeFragment ();
598 cdecl = new CCodeDeclaration ("DBusMessage*");
599 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
600 block.add_statement (cdecl);
602 cdecl = new CCodeDeclaration ("DBusMessageIter");
603 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
604 cdecl.add_declarator (new CCodeVariableDeclarator ("reply_iter"));
605 cdecl.add_declarator (new CCodeVariableDeclarator ("subiter"));
606 block.add_statement (cdecl);
608 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
609 message_signature.add_argument (new CCodeIdentifier ("message"));
610 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
611 signature_check.add_argument (message_signature);
612 signature_check.add_argument (new CCodeConstant ("\"ss\""));
613 var signature_error_block = new CCodeBlock ();
614 signature_error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
615 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
617 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
618 iter_call.add_argument (new CCodeIdentifier ("message"));
619 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
620 block.add_statement (new CCodeExpressionStatement (iter_call));
622 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
623 msgcall.add_argument (new CCodeIdentifier ("message"));
624 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
626 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
627 iter_call.add_argument (new CCodeIdentifier ("reply"));
628 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
629 block.add_statement (new CCodeExpressionStatement (iter_call));
631 block.add_statement (prefragment);
633 cdecl = new CCodeDeclaration ("char*");
634 cdecl.add_declarator (new CCodeVariableDeclarator ("interface_name"));
635 prefragment.append (cdecl);
636 var target = new CCodeIdentifier ("interface_name");
637 var expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
638 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
640 cdecl = new CCodeDeclaration ("char*");
641 cdecl.add_declarator (new CCodeVariableDeclarator ("property_name"));
642 prefragment.append (cdecl);
643 target = new CCodeIdentifier ("property_name");
644 expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
645 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
647 CCodeIfStatement clastif = null;
649 foreach (Property prop in sym.get_properties ()) {
650 if (prop.binding != MemberBinding.INSTANCE
651 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
652 continue;
654 if (!is_dbus_visible (prop)) {
655 continue;
657 if (prop.get_accessor == null) {
658 continue;
661 var prop_block = new CCodeBlock ();
662 var postfragment = new CCodeFragment ();
663 prop_block.add_statement (postfragment);
665 var ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
666 ccmp.add_argument (new CCodeIdentifier ("interface_name"));
667 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
668 var ccheck1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
670 ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
671 ccmp.add_argument (new CCodeIdentifier ("property_name"));
672 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (prop.name))));
673 var ccheck2 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
675 var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccheck1, ccheck2);
677 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
678 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
679 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_VARIANT"));
680 iter_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_signature (prop.property_type))));
681 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
682 postfragment.append (new CCodeExpressionStatement (iter_call));
684 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.get_accessor.get_cname ()));
685 ccall.add_argument (new CCodeIdentifier ("self"));
687 cdecl = new CCodeDeclaration (prop.property_type.get_cname ());
688 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
689 postfragment.append (cdecl);
690 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
692 var array_type = prop.property_type as ArrayType;
693 if (array_type != null) {
694 for (int dim = 1; dim <= array_type.rank; dim++) {
695 string length_cname = get_array_length_cname ("result", dim);
697 cdecl = new CCodeDeclaration ("int");
698 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname));
699 postfragment.append (cdecl);
701 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
705 write_expression (postfragment, prop.property_type, new CCodeIdentifier ("subiter"), new CCodeIdentifier ("result"));
707 if (requires_destroy (prop.get_accessor.value_type)) {
708 // keep local alive (symbol_reference is weak)
709 // space before `result' is work around to not trigger
710 // variable renaming, we really mean C identifier `result' here
711 var local = new LocalVariable (prop.get_accessor.value_type, " result");
712 var ma = new MemberAccess.simple ("result");
713 ma.symbol_reference = local;
714 postfragment.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("result"), prop.get_accessor.value_type, ma)));
717 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
718 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
719 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
720 postfragment.append (new CCodeExpressionStatement (iter_call));
722 var cif = new CCodeIfStatement (ccheck, prop_block);
723 if (clastif == null) {
724 block.add_statement (cif);
725 } else {
726 clastif.false_statement = cif;
729 clastif = cif;
732 // free interface_name and property_name
733 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
734 free_call.add_argument (new CCodeIdentifier ("interface_name"));
735 block.add_statement (new CCodeExpressionStatement (free_call));
737 free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
738 free_call.add_argument (new CCodeIdentifier ("property_name"));
739 block.add_statement (new CCodeExpressionStatement (free_call));
741 if (clastif == null) {
742 block = new CCodeBlock ();
743 block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
744 } else {
745 var else_block = new CCodeBlock ();
746 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
747 unref_call.add_argument (new CCodeIdentifier ("reply"));
748 else_block.add_statement (new CCodeExpressionStatement (unref_call));
749 else_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), new CCodeConstant ("NULL"))));
750 clastif.false_statement = else_block;
752 handle_reply (block);
755 source_declarations.add_type_member_declaration (function.copy ());
757 function.block = block;
758 source_type_member_definition.append (function);
760 return wrapper_name;
763 string generate_dbus_property_get_all_wrapper (ObjectTypeSymbol sym, string dbus_iface_name) {
764 string wrapper_name = "_dbus_%s_property_get_all".printf (sym.get_lower_case_cname ());
766 bool has_readable_properties = false;
767 foreach (Property prop in sym.get_properties ()) {
768 if (prop.binding != MemberBinding.INSTANCE
769 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
770 continue;
772 if (!is_dbus_visible (prop)) {
773 continue;
775 if (prop.get_accessor != null) {
776 has_readable_properties = true;
780 CCodeDeclaration cdecl;
782 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
783 function.modifiers = CCodeModifiers.STATIC;
785 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
786 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
787 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
789 var block = new CCodeBlock ();
790 var prefragment = new CCodeFragment ();
792 cdecl = new CCodeDeclaration ("DBusMessage*");
793 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
794 block.add_statement (cdecl);
796 cdecl = new CCodeDeclaration ("DBusMessageIter");
797 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
798 cdecl.add_declarator (new CCodeVariableDeclarator ("reply_iter"));
799 cdecl.add_declarator (new CCodeVariableDeclarator ("subiter"));
800 if (has_readable_properties) {
801 cdecl.add_declarator (new CCodeVariableDeclarator ("entry_iter"));
802 cdecl.add_declarator (new CCodeVariableDeclarator ("value_iter"));
804 block.add_statement (cdecl);
806 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
807 message_signature.add_argument (new CCodeIdentifier ("message"));
808 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
809 signature_check.add_argument (message_signature);
810 signature_check.add_argument (new CCodeConstant ("\"s\""));
811 var signature_error_block = new CCodeBlock ();
812 signature_error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
813 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
815 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
816 iter_call.add_argument (new CCodeIdentifier ("message"));
817 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
818 block.add_statement (new CCodeExpressionStatement (iter_call));
820 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
821 msgcall.add_argument (new CCodeIdentifier ("message"));
822 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
824 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
825 iter_call.add_argument (new CCodeIdentifier ("reply"));
826 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
827 block.add_statement (new CCodeExpressionStatement (iter_call));
829 block.add_statement (prefragment);
831 cdecl = new CCodeDeclaration ("char*");
832 cdecl.add_declarator (new CCodeVariableDeclarator ("interface_name"));
833 prefragment.append (cdecl);
834 var target = new CCodeIdentifier ("interface_name");
835 var expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
836 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
838 if (has_readable_properties) {
839 cdecl = new CCodeDeclaration ("const char*");
840 cdecl.add_declarator (new CCodeVariableDeclarator ("property_name"));
841 prefragment.append (cdecl);
844 var prop_block = new CCodeBlock ();
846 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
847 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
848 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_ARRAY"));
849 iter_call.add_argument (new CCodeConstant ("\"{sv}\""));
850 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
851 prop_block.add_statement (new CCodeExpressionStatement (iter_call));
853 foreach (Property prop in sym.get_properties ()) {
854 if (prop.binding != MemberBinding.INSTANCE
855 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
856 continue;
858 if (!is_dbus_visible (prop)) {
859 continue;
861 if (prop.get_accessor == null) {
862 continue;
865 var inner_block = new CCodeBlock ();
866 prop_block.add_statement (inner_block);
867 var postfragment = new CCodeFragment ();
868 inner_block.add_statement (postfragment);
870 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
871 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
872 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_DICT_ENTRY"));
873 iter_call.add_argument (new CCodeConstant ("NULL"));
874 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
875 postfragment.append (new CCodeExpressionStatement (iter_call));
877 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("property_name"), new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (prop.name))))));
879 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_append_basic"));
880 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
881 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_STRING"));
882 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("property_name")));
883 postfragment.append (new CCodeExpressionStatement (iter_call));
885 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container"));
886 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
887 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_VARIANT"));
888 iter_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_signature (prop.property_type))));
889 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value_iter")));
890 postfragment.append (new CCodeExpressionStatement (iter_call));
892 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.get_accessor.get_cname ()));
893 ccall.add_argument (new CCodeIdentifier ("self"));
895 cdecl = new CCodeDeclaration (prop.property_type.get_cname ());
896 cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
897 postfragment.append (cdecl);
898 postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall)));
900 var array_type = prop.property_type as ArrayType;
901 if (array_type != null) {
902 for (int dim = 1; dim <= array_type.rank; dim++) {
903 string length_cname = get_array_length_cname ("result", dim);
905 cdecl = new CCodeDeclaration ("int");
906 cdecl.add_declarator (new CCodeVariableDeclarator (length_cname));
907 postfragment.append (cdecl);
909 ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname)));
913 write_expression (postfragment, prop.property_type, new CCodeIdentifier ("value_iter"), new CCodeIdentifier ("result"));
915 if (requires_destroy (prop.get_accessor.value_type)) {
916 // keep local alive (symbol_reference is weak)
917 // space before `result' is work around to not trigger
918 // variable renaming, we really mean C identifier `result' here
919 var local = new LocalVariable (prop.get_accessor.value_type, " result");
920 var ma = new MemberAccess.simple ("result");
921 ma.symbol_reference = local;
922 postfragment.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("result"), prop.get_accessor.value_type, ma)));
925 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
926 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
927 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value_iter")));
928 postfragment.append (new CCodeExpressionStatement (iter_call));
930 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
931 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
932 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter")));
933 postfragment.append (new CCodeExpressionStatement (iter_call));
936 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container"));
937 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter")));
938 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
939 prop_block.add_statement (new CCodeExpressionStatement (iter_call));
941 var ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
942 ccmp.add_argument (new CCodeIdentifier ("interface_name"));
943 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
944 var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
946 var else_block = new CCodeBlock ();
947 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
948 unref_call.add_argument (new CCodeIdentifier ("reply"));
949 else_block.add_statement (new CCodeExpressionStatement (unref_call));
950 else_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), new CCodeConstant ("NULL"))));
952 block.add_statement (new CCodeIfStatement (ccheck, prop_block, else_block));
954 // free interface_name
955 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
956 free_call.add_argument (new CCodeIdentifier ("interface_name"));
957 block.add_statement (new CCodeExpressionStatement (free_call));
959 handle_reply (block);
961 source_declarations.add_type_member_declaration (function.copy ());
963 function.block = block;
964 source_type_member_definition.append (function);
966 return wrapper_name;
969 string generate_dbus_property_set_wrapper (ObjectTypeSymbol sym, string dbus_iface_name) {
970 string wrapper_name = "_dbus_%s_property_set".printf (sym.get_lower_case_cname ());
972 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
973 function.modifiers = CCodeModifiers.STATIC;
975 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
976 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
977 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
979 var block = new CCodeBlock ();
980 var prefragment = new CCodeFragment ();
982 var cdecl = new CCodeDeclaration ("DBusMessage*");
983 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
984 block.add_statement (cdecl);
986 cdecl = new CCodeDeclaration ("DBusMessageIter");
987 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
988 cdecl.add_declarator (new CCodeVariableDeclarator ("subiter"));
989 block.add_statement (cdecl);
991 var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature"));
992 message_signature.add_argument (new CCodeIdentifier ("message"));
993 var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
994 signature_check.add_argument (message_signature);
995 signature_check.add_argument (new CCodeConstant ("\"ssv\""));
996 var signature_error_block = new CCodeBlock ();
997 signature_error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
998 block.add_statement (new CCodeIfStatement (signature_check, signature_error_block));
1000 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init"));
1001 iter_call.add_argument (new CCodeIdentifier ("message"));
1002 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1003 block.add_statement (new CCodeExpressionStatement (iter_call));
1005 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
1006 msgcall.add_argument (new CCodeIdentifier ("message"));
1007 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
1009 block.add_statement (prefragment);
1011 cdecl = new CCodeDeclaration ("char*");
1012 cdecl.add_declarator (new CCodeVariableDeclarator ("interface_name"));
1013 prefragment.append (cdecl);
1014 var target = new CCodeIdentifier ("interface_name");
1015 var expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
1016 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1018 cdecl = new CCodeDeclaration ("char*");
1019 cdecl.add_declarator (new CCodeVariableDeclarator ("property_name"));
1020 prefragment.append (cdecl);
1021 target = new CCodeIdentifier ("property_name");
1022 expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target);
1023 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1025 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_recurse"));
1026 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1027 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter")));
1028 prefragment.append (new CCodeExpressionStatement (iter_call));
1030 CCodeIfStatement clastif = null;
1032 foreach (Property prop in sym.get_properties ()) {
1033 if (prop.binding != MemberBinding.INSTANCE
1034 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
1035 continue;
1037 if (!is_dbus_visible (prop)) {
1038 continue;
1040 if (prop.set_accessor == null) {
1041 continue;
1044 var prop_block = new CCodeBlock ();
1045 prefragment = new CCodeFragment ();
1046 prop_block.add_statement (prefragment);
1048 var ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1049 ccmp.add_argument (new CCodeIdentifier ("interface_name"));
1050 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name)));
1051 var ccheck1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
1053 ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
1054 ccmp.add_argument (new CCodeIdentifier ("property_name"));
1055 ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (prop.name))));
1056 var ccheck2 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0"));
1058 var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccheck1, ccheck2);
1060 var owned_type = prop.property_type.copy ();
1061 owned_type.value_owned = true;
1063 cdecl = new CCodeDeclaration (owned_type.get_cname ());
1064 cdecl.add_declarator (new CCodeVariableDeclarator ("value"));
1065 prefragment.append (cdecl);
1067 target = new CCodeIdentifier ("value");
1068 expr = read_expression (prefragment, prop.property_type, new CCodeIdentifier ("subiter"), target);
1069 prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr)));
1071 var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.set_accessor.get_cname ()));
1072 ccall.add_argument (new CCodeIdentifier ("self"));
1073 ccall.add_argument (new CCodeIdentifier ("value"));
1075 var array_type = prop.property_type as ArrayType;
1076 if (array_type != null) {
1077 for (int dim = 1; dim <= array_type.rank; dim++) {
1078 cdecl = new CCodeDeclaration ("int");
1079 cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname ("value", dim)));
1080 prefragment.append (cdecl);
1082 ccall.add_argument (new CCodeIdentifier (head.get_array_length_cname ("value", dim)));
1086 prop_block.add_statement (new CCodeExpressionStatement (ccall));
1088 if (requires_destroy (owned_type)) {
1089 // keep local alive (symbol_reference is weak)
1090 var local = new LocalVariable (owned_type, "value");
1091 var ma = new MemberAccess.simple ("value");
1092 ma.symbol_reference = local;
1093 prop_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier ("value"), owned_type, ma)));
1096 var cif = new CCodeIfStatement (ccheck, prop_block);
1097 if (clastif == null) {
1098 block.add_statement (cif);
1099 } else {
1100 clastif.false_statement = cif;
1103 clastif = cif;
1106 // free interface_name and property_name
1107 var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1108 free_call.add_argument (new CCodeIdentifier ("interface_name"));
1109 block.add_statement (new CCodeExpressionStatement (free_call));
1111 free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
1112 free_call.add_argument (new CCodeIdentifier ("property_name"));
1113 block.add_statement (new CCodeExpressionStatement (free_call));
1115 if (clastif == null) {
1116 block = new CCodeBlock ();
1117 block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
1118 } else {
1119 var else_block = new CCodeBlock ();
1120 var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref"));
1121 unref_call.add_argument (new CCodeIdentifier ("reply"));
1122 else_block.add_statement (new CCodeExpressionStatement (unref_call));
1123 else_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), new CCodeIdentifier ("NULL"))));
1124 clastif.false_statement = else_block;
1126 handle_reply (block);
1129 source_declarations.add_type_member_declaration (function.copy ());
1131 function.block = block;
1132 source_type_member_definition.append (function);
1134 return wrapper_name;
1137 string get_dbus_type_introspection (ObjectTypeSymbol sym) {
1138 string result = "";
1140 var cl = sym as Class;
1141 if (cl != null) {
1142 foreach (DataType base_type in cl.get_base_types ()) {
1143 var base_obj_type = base_type as ObjectType;
1144 result += get_dbus_type_introspection (base_obj_type.type_symbol);
1148 string dbus_iface_name = get_dbus_name (sym);
1149 if (dbus_iface_name == null) {
1150 return result;
1153 result += "<interface name=\"%s\">\n".printf (dbus_iface_name);
1155 foreach (var m in sym.get_methods ()) {
1156 if (m is CreationMethod || m.binding != MemberBinding.INSTANCE
1157 || m.overrides || m.access != SymbolAccessibility.PUBLIC) {
1158 continue;
1160 if (!is_dbus_visible (m)) {
1161 continue;
1164 result += " <method name=\"%s\">\n".printf (Symbol.lower_case_to_camel_case (m.name));
1166 foreach (var param in m.get_parameters ()) {
1167 if (param.parameter_type.data_type != null
1168 && param.parameter_type.data_type.get_full_name () == "DBus.BusName") {
1169 // skip sender parameter
1170 // (implicit in D-Bus)
1171 continue;
1174 string direction = param.direction == ParameterDirection.IN ? "in" : "out";
1175 result += " <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n".printf (param.name, get_type_signature (param.parameter_type), direction);
1177 if (!(m.return_type is VoidType)) {
1178 result += " <arg name=\"%s\" type=\"%s\" direction=\"out\"/>\n".printf (dbus_result_name (m), get_type_signature (m.return_type));
1181 result += " </method>\n";
1184 foreach (var prop in sym.get_properties ()) {
1185 if (prop.binding != MemberBinding.INSTANCE
1186 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
1187 continue;
1189 if (!is_dbus_visible (prop)) {
1190 continue;
1193 string access = (prop.get_accessor != null ? "read" : "") + (prop.set_accessor != null ? "write" : "");
1194 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);
1197 foreach (var sig in sym.get_signals ()) {
1198 if (sig.access != SymbolAccessibility.PUBLIC) {
1199 continue;
1201 if (!is_dbus_visible (sig)) {
1202 continue;
1205 result += " <signal name=\"%s\">\n".printf (Symbol.lower_case_to_camel_case (sig.name));
1207 foreach (var param in sig.get_parameters ()) {
1208 result += " <arg name=\"%s\" type=\"%s\"/>\n".printf (param.name, get_type_signature (param.parameter_type));
1211 result += " </signal>\n";
1214 result += "</interface>\n";
1216 return result;
1219 string generate_dbus_introspect (ObjectTypeSymbol sym) {
1220 string wrapper_name = "_dbus_%s_introspect".printf (sym.get_lower_case_cname ());
1222 var function = new CCodeFunction (wrapper_name, "DBusHandlerResult");
1223 function.modifiers = CCodeModifiers.STATIC;
1225 function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*"));
1226 function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
1227 function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
1229 var block = new CCodeBlock ();
1231 var cdecl = new CCodeDeclaration ("DBusMessage*");
1232 cdecl.add_declarator (new CCodeVariableDeclarator ("reply"));
1233 block.add_statement (cdecl);
1235 cdecl = new CCodeDeclaration ("DBusMessageIter");
1236 cdecl.add_declarator (new CCodeVariableDeclarator ("iter"));
1237 block.add_statement (cdecl);
1239 var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return"));
1240 msgcall.add_argument (new CCodeIdentifier ("message"));
1241 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall)));
1243 var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append"));
1244 iter_call.add_argument (new CCodeIdentifier ("reply"));
1245 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1246 block.add_statement (new CCodeExpressionStatement (iter_call));
1248 cdecl = new CCodeDeclaration ("GString*");
1249 cdecl.add_declarator (new CCodeVariableDeclarator ("xml_data"));
1250 block.add_statement (cdecl);
1252 cdecl = new CCodeDeclaration ("char**");
1253 cdecl.add_declarator (new CCodeVariableDeclarator ("children"));
1254 block.add_statement (cdecl);
1256 cdecl = new CCodeDeclaration ("int");
1257 cdecl.add_declarator (new CCodeVariableDeclarator ("i"));
1258 block.add_statement (cdecl);
1260 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";
1261 var str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_new"));
1262 str_call.add_argument (new CCodeConstant ("\"%s\"".printf (xml_data.escape (""))));
1263 block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("xml_data"), str_call)));
1265 xml_data = "<node>\n";
1266 xml_data +=
1267 """<interface name="org.freedesktop.DBus.Introspectable">
1268 <method name="Introspect">
1269 <arg name="data" direction="out" type="s"/>
1270 </method>
1271 </interface>
1272 <interface name="org.freedesktop.DBus.Properties">
1273 <method name="Get">
1274 <arg name="interface" direction="in" type="s"/>
1275 <arg name="propname" direction="in" type="s"/>
1276 <arg name="value" direction="out" type="v"/>
1277 </method>
1278 <method name="Set">
1279 <arg name="interface" direction="in" type="s"/>
1280 <arg name="propname" direction="in" type="s"/>
1281 <arg name="value" direction="in" type="v"/>
1282 </method>
1283 <method name="GetAll">
1284 <arg name="interface" direction="in" type="s"/>
1285 <arg name="props" direction="out" type="a{sv}"/>
1286 </method>
1287 </interface>
1288 """;
1289 xml_data += get_dbus_type_introspection (sym);
1290 str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_append"));
1291 str_call.add_argument (new CCodeIdentifier ("xml_data"));
1292 str_call.add_argument (new CCodeConstant ("\"%s\"".printf (xml_data.escape (""))));
1293 block.add_statement (new CCodeExpressionStatement (str_call));
1295 var get_path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get_data"));
1296 get_path.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *"));
1297 get_path.add_argument (new CCodeConstant ("\"dbus_object_path\""));
1299 var list_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_list_registered"));
1300 list_call.add_argument (new CCodeIdentifier ("connection"));
1301 list_call.add_argument (get_path);
1302 list_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("children")));
1303 block.add_statement (new CCodeExpressionStatement (list_call));
1305 // add child nodes
1306 var child_block = new CCodeBlock ();
1307 str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_append_printf"));
1308 str_call.add_argument (new CCodeIdentifier ("xml_data"));
1309 str_call.add_argument (new CCodeConstant ("\"%s\"".printf ("<node name=\"%s\"/>\n".escape (""))));
1310 str_call.add_argument (new CCodeElementAccess (new CCodeIdentifier ("children"), new CCodeIdentifier ("i")));
1311 child_block.add_statement (new CCodeExpressionStatement (str_call));
1312 var cfor = new CCodeForStatement (new CCodeElementAccess (new CCodeIdentifier ("children"), new CCodeIdentifier ("i")), child_block);
1313 cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
1314 cfor.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
1315 block.add_statement (cfor);
1317 var list_free_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_free_string_array"));
1318 list_free_call.add_argument (new CCodeIdentifier ("children"));
1319 block.add_statement (new CCodeExpressionStatement (list_free_call));
1321 xml_data = "</node>\n";
1322 str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_append"));
1323 str_call.add_argument (new CCodeIdentifier ("xml_data"));
1324 str_call.add_argument (new CCodeConstant ("\"%s\"".printf (xml_data.escape (""))));
1325 block.add_statement (new CCodeExpressionStatement (str_call));
1327 iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_append_basic"));
1328 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter")));
1329 iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_STRING"));
1330 iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (new CCodeIdentifier ("xml_data"), "str")));
1331 block.add_statement (new CCodeExpressionStatement (iter_call));
1333 str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_free"));
1334 str_call.add_argument (new CCodeIdentifier ("xml_data"));
1335 str_call.add_argument (new CCodeConstant ("TRUE"));
1336 block.add_statement (new CCodeExpressionStatement (str_call));
1338 handle_reply (block);
1340 source_declarations.add_type_member_declaration (function.copy ());
1342 function.block = block;
1343 source_type_member_definition.append (function);
1345 return wrapper_name;
1348 void handle_signals (ObjectTypeSymbol sym, CCodeBlock block) {
1349 string dbus_iface_name = get_dbus_name (sym);
1350 if (dbus_iface_name == null) {
1351 return;
1354 foreach (Signal sig in sym.get_signals ()) {
1355 if (sig.access != SymbolAccessibility.PUBLIC) {
1356 continue;
1358 if (!is_dbus_visible (sig)) {
1359 continue;
1362 var connect = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect"));
1363 connect.add_argument (new CCodeIdentifier ("object"));
1364 connect.add_argument (sig.get_canonical_cconstant (null));
1365 connect.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback"));
1366 connect.add_argument (new CCodeIdentifier ("connection"));
1367 block.add_statement (new CCodeExpressionStatement (connect));
1371 void generate_message_function (ObjectType object_type) {
1372 var sym = object_type.type_symbol;
1374 dbus_glib_h_needed = true;
1376 var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_message", "DBusHandlerResult");
1377 cfunc.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*"));
1378 cfunc.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*"));
1379 cfunc.add_parameter (new CCodeFormalParameter ("object", "void*"));
1381 if (sym.is_private_symbol ()) {
1382 cfunc.modifiers |= CCodeModifiers.STATIC;
1385 source_declarations.add_type_member_declaration (cfunc.copy ());
1387 var block = new CCodeBlock ();
1388 cfunc.block = block;
1390 var cdecl = new CCodeDeclaration ("DBusHandlerResult");
1391 cdecl.add_declarator (new CCodeVariableDeclarator ("result", new CCodeConstant ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1392 block.add_statement (cdecl);
1394 CCodeIfStatement clastif = null;
1396 handle_method ("org.freedesktop.DBus.Introspectable", "Introspect", generate_dbus_introspect (sym), block, ref clastif);
1398 string dbus_iface_name = get_dbus_name (sym);
1399 if (dbus_iface_name != null) {
1400 bool need_property_get = false;
1401 bool need_property_set = false;
1402 foreach (Property prop in sym.get_properties ()) {
1403 if (prop.binding != MemberBinding.INSTANCE
1404 || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) {
1405 continue;
1407 if (!is_dbus_visible (prop)) {
1408 continue;
1410 if (prop.get_accessor != null) {
1411 need_property_get = true;
1413 if (prop.set_accessor != null) {
1414 need_property_set = true;
1418 if (need_property_get) {
1419 handle_method ("org.freedesktop.DBus.Properties", "Get", generate_dbus_property_get_wrapper (sym, dbus_iface_name), block, ref clastif);
1421 if (need_property_set) {
1422 handle_method ("org.freedesktop.DBus.Properties", "Set", generate_dbus_property_set_wrapper (sym, dbus_iface_name), block, ref clastif);
1424 handle_method ("org.freedesktop.DBus.Properties", "GetAll", generate_dbus_property_get_all_wrapper (sym, dbus_iface_name), block, ref clastif);
1426 handle_methods (sym, dbus_iface_name, block, ref clastif);
1429 var resultblock = new CCodeBlock ();
1430 resultblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
1431 var cif = new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("result"), new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")), resultblock);
1432 block.add_statement (cif);
1433 clastif = cif;
1435 var cl = sym as Class;
1436 if (cl != null) {
1437 foreach (DataType base_type in cl.get_base_types ()) {
1438 var base_obj_type = base_type as ObjectType;
1439 if (type_implements_dbus_interface (base_obj_type.type_symbol)) {
1440 var base_call = new CCodeFunctionCall (new CCodeIdentifier (base_obj_type.type_symbol.get_lower_case_cprefix () + "dbus_message"));
1441 base_call.add_argument (new CCodeIdentifier ("connection"));
1442 base_call.add_argument (new CCodeIdentifier ("message"));
1443 base_call.add_argument (new CCodeIdentifier ("object"));
1445 var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, base_call, new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED"));
1447 var base_block = new CCodeBlock ();
1448 base_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
1450 cif = new CCodeIfStatement (ccheck, base_block);
1451 clastif.false_statement = cif;
1453 clastif = cif;
1458 var retblock = new CCodeBlock ();
1459 retblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1460 clastif.false_statement = retblock;
1462 source_type_member_definition.append (cfunc);
1465 CCodeExpression get_vtable (ObjectType object_type) {
1466 var sym = object_type.type_symbol;
1468 var vtable = new CCodeInitializerList ();
1469 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_register_object"));
1471 generate_register_function (object_type);
1473 var cdecl = new CCodeDeclaration ("const _DBusObjectVTable");
1474 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_vtable", vtable));
1475 cdecl.modifiers = CCodeModifiers.STATIC;
1476 source_declarations.add_constant_declaration (cdecl);
1478 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_vtable");
1481 CCodeExpression get_path_vtable (ObjectType object_type) {
1482 var sym = object_type.type_symbol;
1484 var vtable = new CCodeInitializerList ();
1485 vtable.append (new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_unregister"));
1486 vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_message"));
1488 generate_unregister_function (object_type);
1489 generate_message_function (object_type);
1491 var cdecl = new CCodeDeclaration ("const DBusObjectPathVTable");
1492 cdecl.add_declarator (new CCodeVariableDeclarator ("_" + sym.get_lower_case_cprefix () + "dbus_path_vtable", vtable));
1493 cdecl.modifiers = CCodeModifiers.STATIC;
1494 source_declarations.add_constant_declaration (cdecl);
1496 return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_path_vtable");
1499 public override void visit_method_call (MethodCall expr) {
1500 var mtype = expr.call.value_type as MethodType;
1501 if (mtype == null || (mtype.method_symbol.get_cname () != "dbus_connection_register_g_object" &&
1502 mtype.method_symbol.get_cname () != "dbus_g_connection_register_g_object")) {
1503 base.visit_method_call (expr);
1504 return;
1507 dbus_glib_h_needed = true;
1509 expr.accept_children (codegen);
1511 var ma = (MemberAccess) expr.call;
1513 var raw_conn = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection"));
1514 raw_conn.add_argument ((CCodeExpression) ma.inner.ccodenode);
1516 var args_it = expr.get_argument_list ().iterator ();
1517 args_it.next ();
1518 var path_arg = args_it.get ();
1519 args_it.next ();
1520 var obj_arg = args_it.get ();
1522 var cregister = new CCodeFunctionCall (new CCodeIdentifier ("_vala_dbus_register_object"));
1523 if (mtype.method_symbol.get_cname () == "dbus_g_connection_register_g_object") {
1524 cregister.add_argument (raw_conn);
1525 } else {
1526 cregister.add_argument ((CCodeExpression) ma.inner.ccodenode);
1528 cregister.add_argument ((CCodeExpression) path_arg.ccodenode);
1529 cregister.add_argument ((CCodeExpression) obj_arg.ccodenode);
1530 expr.ccodenode = cregister;
1533 bool type_implements_dbus_interface (ObjectTypeSymbol sym) {
1534 var dbus = sym.get_attribute ("DBus");
1535 if (dbus != null) {
1536 return true;
1539 var cl = sym as Class;
1540 if (cl != null) {
1541 foreach (DataType base_type in cl.get_base_types ()) {
1542 var base_obj_type = base_type as ObjectType;
1543 if (type_implements_dbus_interface (base_obj_type.type_symbol)) {
1544 return true;
1549 return false;
1552 public override CCodeFragment register_dbus_info (ObjectTypeSymbol sym) {
1553 CCodeFragment fragment = new CCodeFragment ();
1555 if (!type_implements_dbus_interface (sym)) {
1556 return fragment;
1559 var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
1560 quark.add_argument (new CCodeConstant ("\"DBusObjectVTable\""));
1562 var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
1563 set_qdata.add_argument (new CCodeIdentifier (sym.get_upper_case_cname ("TYPE_")));
1564 set_qdata.add_argument (quark);
1565 set_qdata.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_vtable (new ObjectType (sym))), "void*"));
1567 fragment.append (new CCodeExpressionStatement (set_qdata));
1569 return fragment;