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