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