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
21 * Jürg Billeter <j@bitron.ch>
22 * Philip Van Hoof <pvanhoof@gnome.org>
29 * The link between a dynamic method and generated code.
31 internal class Vala
.DBusServerModule
: DBusClientModule
{
32 public DBusServerModule (CCodeGenerator codegen
, CCodeModule? 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")) {
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
!= "") {
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 ();
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 ());
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;
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
);
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;
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
);
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 ()));
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
)));
205 ccall
.add_argument (new
CCodeIdentifier (param
.name
));
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
)));
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
)));
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
);
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 ()));
258 cdecl
= new
CCodeDeclaration (m
.return_type
.get_cname ());
259 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
260 out_postfragment
.append (cdecl
);
262 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("result"), ccall
)));
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
)));
294 block
.add_statement (new
CCodeExpressionStatement (ccall
));
296 ready_block
.add_statement (new
CCodeExpressionStatement (finish_ccall
));
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
);
340 handle_reply (block
);
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
);
365 source_declarations
.add_type_member_declaration (ready_function
.copy ());
367 ready_function
.block
= ready_block
;
368 source_type_member_definition
.append (ready_function
);
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 ());
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
);
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;
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 ();
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
;
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 ();
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
);
563 clastif
.false_statement
= 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
) {
575 if (!is_dbus_visible (m
)) {
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
) {
654 if (!is_dbus_visible (prop
)) {
657 if (prop
.get_accessor
== null) {
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
);
726 clastif
.false_statement
= 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")));
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
);
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
) {
772 if (!is_dbus_visible (prop
)) {
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
) {
858 if (!is_dbus_visible (prop
)) {
861 if (prop
.get_accessor
== null) {
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
);
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
) {
1037 if (!is_dbus_visible (prop
)) {
1040 if (prop
.set_accessor
== null) {
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
);
1100 clastif
.false_statement
= 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")));
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
) {
1140 var cl
= sym as Class
;
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) {
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
) {
1160 if (!is_dbus_visible (m
)) {
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)
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
) {
1189 if (!is_dbus_visible (prop
)) {
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
) {
1201 if (!is_dbus_visible (sig
)) {
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";
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";
1267 """<interface name="org
.freedesktop
.DBus
.Introspectable
">
1268 <method name="Introspect
">
1269 <arg name="data
" direction="out" type="s
"/>
1272 <interface name="org
.freedesktop
.DBus
.Properties
">
1274 <arg name="interface" direction="in" type="s
"/>
1275 <arg name="propname
" direction="in" type="s
"/>
1276 <arg name="value
" direction="out" type="v
"/>
1279 <arg name="interface" direction="in" type="s
"/>
1280 <arg name="propname
" direction="in" type="s
"/>
1281 <arg name="value
" direction="in" type="v
"/>
1283 <method name="GetAll
">
1284 <arg name="interface" direction="in" type="s
"/>
1285 <arg name="props
" direction="out" type="a
{sv
}"/>
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
));
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) {
1354 foreach (Signal sig
in sym
.get_signals ()) {
1355 if (sig
.access
!= SymbolAccessibility
.PUBLIC
) {
1358 if (!is_dbus_visible (sig
)) {
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
) {
1407 if (!is_dbus_visible (prop
)) {
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
);
1435 var cl
= sym as Class
;
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
;
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
);
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 ();
1518 var path_arg
= args_it
.get ();
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
);
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");
1539 var cl
= sym as Class
;
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
)) {
1552 public override CCodeFragment
register_dbus_info (ObjectTypeSymbol sym
) {
1553 CCodeFragment fragment
= new
CCodeFragment ();
1555 if (!type_implements_dbus_interface (sym
)) {
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
));