1 /* valadbusservermodule.vala
3 * Copyright (C) 2007-2010 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 public class Vala
.DBusServerModule
: DBusClientModule
{
31 public static bool is_dbus_visible (CodeNode node
) {
32 var dbus_attribute
= node
.get_attribute ("DBus");
33 if (dbus_attribute
!= null
34 && dbus_attribute
.has_argument ("visible")
35 && !dbus_attribute
.get_bool ("visible")) {
42 public static string dbus_result_name (Method m
) {
43 var dbus_attribute
= m
.get_attribute ("DBus");
44 if (dbus_attribute
!= null
45 && dbus_attribute
.has_argument ("result")) {
46 var result_name
= dbus_attribute
.get_string ("result");
47 if (result_name
!= null && result_name
!= "") {
55 void send_reply (CCodeBlock block
) {
56 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_send"));
57 ccall
.add_argument (new
CCodeIdentifier ("connection"));
58 ccall
.add_argument (new
CCodeIdentifier ("reply"));
59 ccall
.add_argument (new
CCodeConstant ("NULL"));
60 block
.add_statement (new
CCodeExpressionStatement (ccall
));
61 ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
62 ccall
.add_argument (new
CCodeIdentifier ("reply"));
63 block
.add_statement (new
CCodeExpressionStatement (ccall
));
66 void handle_reply (CCodeBlock block
) {
67 var handled
= new
CCodeBlock ();
69 handled
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
71 var not_handled
= new
CCodeBlock ();
72 not_handled
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
74 block
.add_statement (new
CCodeIfStatement (new
CCodeIdentifier ("reply"), handled
, not_handled
));
77 string generate_dbus_wrapper (Method m
, ObjectTypeSymbol sym
) {
78 string wrapper_name
= "_dbus_%s".printf (m
.get_cname ());
82 CCodeDeclaration cdecl
;
84 var function
= new
CCodeFunction (wrapper_name
, "DBusHandlerResult");
85 function
.modifiers
= CCodeModifiers
.STATIC
;
86 function
.add_parameter (new
CCodeParameter ("self", sym
.get_cname () + "*"));
87 function
.add_parameter (new
CCodeParameter ("connection", "DBusConnection*"));
88 function
.add_parameter (new
CCodeParameter ("message", "DBusMessage*"));
89 var block
= new
CCodeBlock ();
91 CCodeFunction ready_function
= null;
92 CCodeBlock ready_block
= null;
95 cfile
.add_include ("gio/gio.h");
97 ready_function
= new
CCodeFunction (wrapper_name
+ "_ready", "void");
98 ready_function
.modifiers
= CCodeModifiers
.STATIC
;
99 ready_function
.add_parameter (new
CCodeParameter ("source_object", "GObject *"));
100 ready_function
.add_parameter (new
CCodeParameter ("_res_", "GAsyncResult *"));
101 ready_function
.add_parameter (new
CCodeParameter ("_user_data_", "gpointer *"));
102 ready_block
= new
CCodeBlock ();
104 cdecl
= new
CCodeDeclaration ("DBusConnection *");
105 cdecl
.add_declarator (new
CCodeVariableDeclarator ("connection", new
CCodeIdentifier ("_user_data_[0]")));
106 ready_block
.add_statement (cdecl
);
107 cdecl
= new
CCodeDeclaration ("DBusMessage *");
108 cdecl
.add_declarator (new
CCodeVariableDeclarator ("message", new
CCodeIdentifier ("_user_data_[1]")));
109 ready_block
.add_statement (cdecl
);
112 var in_prefragment
= new
CCodeFragment ();
113 var in_postfragment
= new
CCodeFragment ();
114 var out_prefragment
= in_prefragment
;
115 var out_postfragment
= in_postfragment
;
117 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
118 cdecl
.add_declarator (new
CCodeVariableDeclarator ("iter"));
119 block
.add_statement (cdecl
);
121 out_prefragment
= new
CCodeFragment ();
122 out_postfragment
= new
CCodeFragment ();
123 ready_block
.add_statement (cdecl
);
126 cdecl
= new
CCodeDeclaration ("GError*");
127 cdecl
.add_declarator (new
CCodeVariableDeclarator ("error", new
CCodeConstant ("NULL")));
129 ready_block
.add_statement (cdecl
);
131 block
.add_statement (cdecl
);
134 block
.add_statement (in_prefragment
);
136 ready_block
.add_statement (out_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 in_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 in_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
CCodeCastExpression (new
CCodeIdentifier ("source_object"), sym
.get_cname () + "*"));
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 (Parameter param
in m
.get_parameters ()) {
180 var owned_type
= param
.variable_type
.copy ();
181 owned_type
.value_owned
= true;
183 cdecl
= new
CCodeDeclaration (owned_type
.get_cname ());
184 cdecl
.add_declarator (new CCodeVariableDeclarator
.zero (param
.name
, default_value_for_type (param
.variable_type
, true)));
185 if (param
.direction
== ParameterDirection
.IN
) {
186 in_prefragment
.append (cdecl
);
188 out_prefragment
.append (cdecl
);
190 if (type_signature
== ""
191 && param
.direction
== ParameterDirection
.IN
192 && param
.variable_type
.data_type
!= null
193 && param
.variable_type
.data_type
.get_full_name () == "DBus.BusName") {
194 // first parameter is a string parameter called 'sender'
195 // pass bus name of sender
196 var get_sender
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_get_sender"));
197 get_sender
.add_argument (new
CCodeIdentifier ("message"));
198 ccall
.add_argument (get_sender
);
202 if (get_type_signature (param
.variable_type
) == null) {
203 Report
.error (param
.variable_type
.source_reference
, "D-Bus serialization of type `%s' is not supported".printf (param
.variable_type
.to_string ()));
207 if (!m
.coroutine
|| param
.direction
== ParameterDirection
.IN
) {
208 var st
= param
.variable_type
.data_type as Struct
;
209 if (param
.direction
!= ParameterDirection
.IN
210 || (st
!= null && !st
.is_simple_type ())) {
211 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (param
.name
)));
213 ccall
.add_argument (new
CCodeIdentifier (param
.name
));
216 finish_ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (param
.name
)));
219 if (param
.variable_type is ArrayType
) {
220 var array_type
= (ArrayType
) param
.variable_type
;
222 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
223 string length_cname
= get_parameter_array_length_cname (param
, dim
);
225 cdecl
= new
CCodeDeclaration ("int");
226 cdecl
.add_declarator (new
CCodeVariableDeclarator (length_cname
, new
CCodeConstant ("0")));
227 if (!m
.coroutine
|| param
.direction
== ParameterDirection
.IN
) {
228 if (param
.direction
!= ParameterDirection
.IN
) {
229 out_prefragment
.append (cdecl
);
230 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
232 in_prefragment
.append (cdecl
);
233 ccall
.add_argument (new
CCodeIdentifier (length_cname
));
236 out_prefragment
.append (cdecl
);
237 finish_ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
242 if (param
.direction
== ParameterDirection
.IN
) {
243 type_signature
+= get_type_signature (param
.variable_type
);
245 var target
= new
CCodeIdentifier (param
.name
);
246 var expr
= read_expression (in_prefragment
, param
.variable_type
, new
CCodeIdentifier ("iter"), target
);
247 in_prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
249 write_expression (out_postfragment
, param
.variable_type
, new
CCodeIdentifier ("iter"), new
CCodeIdentifier (param
.name
));
252 if (requires_destroy (owned_type
)) {
253 // keep local alive (symbol_reference is weak)
254 var local
= new
LocalVariable (owned_type
, param
.name
);
255 var stmt
= new
CCodeExpressionStatement (destroy_local (local
));
256 if (param
.direction
== ParameterDirection
.IN
) {
257 in_postfragment
.append (stmt
);
259 out_postfragment
.append (stmt
);
264 signature_check
.add_argument (new
CCodeConstant ("\"%s\"".printf (type_signature
)));
266 if (!(m
.return_type is VoidType
)) {
267 if (get_type_signature (m
.return_type
) == null) {
268 Report
.error (m
.return_type
.source_reference
, "D-Bus serialization of type `%s' is not supported".printf (m
.return_type
.to_string ()));
269 } else if (m
.return_type
.is_real_non_null_struct_type ()) {
270 cdecl
= new
CCodeDeclaration (m
.return_type
.get_cname ());
271 cdecl
.add_declarator (new CCodeVariableDeclarator
.zero ("result", default_value_for_type (m
.return_type
, true)));
272 out_prefragment
.append (cdecl
);
275 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
277 finish_ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
280 write_expression (out_postfragment
, m
.return_type
, new
CCodeIdentifier ("iter"), new
CCodeIdentifier ("result"));
282 if (requires_destroy (m
.return_type
)) {
283 // keep local alive (symbol_reference is weak)
284 // space before `result' is work around to not trigger
285 // variable renaming, we really mean C identifier `result' here
286 var local
= new
LocalVariable (m
.return_type
, " result");
287 var ma
= new MemberAccess
.simple ("result");
288 ma
.symbol_reference
= local
;
289 ma
.value_type
= m
.return_type
.copy ();
290 visit_member_access (ma
);
291 out_postfragment
.append (new
CCodeExpressionStatement (get_unref_expression (new
CCodeIdentifier ("result"), m
.return_type
, ma
)));
294 block
.add_statement (new
CCodeExpressionStatement (ccall
));
296 ready_block
.add_statement (new
CCodeExpressionStatement (finish_ccall
));
299 cdecl
= new
CCodeDeclaration (m
.return_type
.get_cname ());
300 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
301 out_prefragment
.append (cdecl
);
303 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("result"), ccall
)));
305 block
.add_statement (new
CCodeExpressionStatement (ccall
));
306 ready_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("result"), finish_ccall
)));
309 if (m
.return_type is ArrayType
) {
310 var array_type
= (ArrayType
) m
.return_type
;
312 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
313 string length_cname
= get_array_length_cname ("result", dim
);
315 cdecl
= new
CCodeDeclaration ("int");
316 cdecl
.add_declarator (new
CCodeVariableDeclarator (length_cname
, new
CCodeConstant ("0")));
317 out_prefragment
.append (cdecl
);
319 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
321 finish_ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
326 write_expression (out_postfragment
, m
.return_type
, new
CCodeIdentifier ("iter"), new
CCodeIdentifier ("result"));
328 if (requires_destroy (m
.return_type
)) {
329 // keep local alive (symbol_reference is weak)
330 // space before `result' is work around to not trigger
331 // variable renaming, we really mean C identifier `result' here
332 var local
= new
LocalVariable (m
.return_type
, " result");
333 var ma
= new MemberAccess
.simple ("result");
334 ma
.symbol_reference
= local
;
335 ma
.value_type
= m
.return_type
.copy ();
336 visit_member_access (ma
);
337 out_postfragment
.append (new
CCodeExpressionStatement (get_unref_expression (new
CCodeIdentifier ("result"), m
.return_type
, ma
)));
341 block
.add_statement (new
CCodeExpressionStatement (ccall
));
343 ready_block
.add_statement (new
CCodeExpressionStatement (finish_ccall
));
348 ccall
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (wrapper_name
+ "_ready"), "GAsyncReadyCallback"));
350 var new_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_new0"));
351 new_call
.add_argument (new
CCodeIdentifier ("gpointer"));
352 new_call
.add_argument (new
CCodeConstant ("2"));
353 cdecl
= new
CCodeDeclaration ("gpointer *");
354 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_user_data_", new_call
));
355 in_prefragment
.append (cdecl
);
357 var ref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_ref"));
358 ref_call
.add_argument (new
CCodeIdentifier ("connection"));
359 in_prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_user_data_[0]"), ref_call
)));
360 ref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_ref"));
361 ref_call
.add_argument (new
CCodeIdentifier ("message"));
362 in_prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_user_data_[1]"), ref_call
)));
364 ccall
.add_argument (new
CCodeIdentifier ("_user_data_"));
367 if (m
.get_error_types ().size
> 0) {
369 finish_ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("error")));
371 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("error")));
374 var error_block
= new
CCodeBlock ();
376 generate_server_error_cases (error_block
, m
.get_error_types (), new
CCodeIdentifier ("error"), new
CCodeIdentifier ("message"), new
CCodeIdentifier ("reply"));
378 send_reply (error_block
);
381 error_block
.add_statement (new
CCodeReturnStatement ());
382 ready_block
.add_statement (new
CCodeIfStatement (new
CCodeIdentifier ("error"), error_block
));
384 error_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
385 block
.add_statement (new
CCodeIfStatement (new
CCodeIdentifier ("error"), error_block
));
389 block
.add_statement (in_postfragment
);
392 handle_reply (block
);
394 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
396 ready_block
.add_statement (out_postfragment
);
398 send_reply (ready_block
);
400 var unref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_unref"));
401 unref_call
.add_argument (new
CCodeIdentifier ("connection"));
402 ready_block
.add_statement (new
CCodeExpressionStatement (unref_call
));
403 unref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
404 unref_call
.add_argument (new
CCodeIdentifier ("message"));
405 ready_block
.add_statement (new
CCodeExpressionStatement (unref_call
));
406 var free_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
407 free_call
.add_argument (new
CCodeIdentifier ("_user_data_"));
408 ready_block
.add_statement (new
CCodeExpressionStatement (free_call
));
411 cfile
.add_function_declaration (function
);
413 function
.block
= block
;
414 cfile
.add_function (function
);
417 cfile
.add_function_declaration (ready_function
);
419 ready_function
.block
= ready_block
;
420 cfile
.add_function (ready_function
);
426 void generate_server_error_cases (CCodeBlock error_block
, List
<DataType
> error_types
, CCodeExpression error
, CCodeExpression message
, CCodeExpression reply
) {
427 CCodeStatement if_else_if
= null;
428 CCodeIfStatement last_statement
= null;
430 foreach (DataType error_type
in error_types
) {
431 var edomain
= ((ErrorType
) error_type
).error_domain
;
433 if (edomain
== null) {
434 Report
.error (error_type
.source_reference
, "Generic errors cannot be serialized over DBus");
438 var edomain_dbus_name
= get_dbus_name (edomain
);
439 if (edomain_dbus_name
== null) {
440 Report
.error (edomain
.source_reference
, "Errordomain must have a DBus.name annotation to be serialized over DBus");
443 var true_block
= new
CCodeBlock ();
444 true_block
.suppress_newline
= true;
446 var cswitch
= new
CCodeSwitchStatement (new CCodeMemberAccess
.pointer (error
, "code"));
447 foreach (ErrorCode ecode
in edomain
.get_codes ()) {
448 cswitch
.add_statement (new
CCodeCaseStatement (new
CCodeIdentifier (ecode
.get_cname ())));
450 var ecode_dbus_name
= get_dbus_name (ecode
);
451 if (ecode_dbus_name
== null) {
452 ecode_dbus_name
= Symbol
.lower_case_to_camel_case (ecode
.name
.down ());
455 string dbus_name
= "%s.%s".printf (edomain_dbus_name
, ecode_dbus_name
);
457 var msgcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_new_error"));
458 msgcall
.add_argument (message
);
459 msgcall
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_name
)));
460 msgcall
.add_argument (new CCodeMemberAccess
.pointer (error
, "message"));
461 cswitch
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (reply
, msgcall
)));
463 cswitch
.add_statement (new
CCodeBreakStatement ());
465 true_block
.add_statement (cswitch
);
467 var equal_test
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, new CCodeMemberAccess
.pointer (error
, "domain"), new
CCodeIdentifier (edomain
.get_upper_case_cname ()));
468 var stmt
= new
CCodeIfStatement (equal_test
, true_block
);
470 if (last_statement
!= null) {
471 last_statement
.false_statement
= stmt
;
475 last_statement
= stmt
;
477 error_block
.add_statement (if_else_if
);
480 string generate_dbus_signal_wrapper (Signal sig
, ObjectTypeSymbol sym
, string dbus_iface_name
) {
481 string wrapper_name
= "_dbus_%s_%s".printf (sym
.get_lower_case_cname (), sig
.get_cname ());
485 CCodeDeclaration cdecl
;
487 var function
= new
CCodeFunction (wrapper_name
, "void");
488 function
.modifiers
= CCodeModifiers
.STATIC
;
490 function
.add_parameter (new
CCodeParameter ("_sender", "GObject*"));
492 foreach (var param
in sig
.get_parameters ()) {
493 // ensure ccodenode of parameter is set
494 var cparam
= generate_parameter (param
, cfile
, new HashMap
<int,CCodeParameter
> (), null);
496 function
.add_parameter (cparam
);
497 if (param
.variable_type is ArrayType
) {
498 var array_type
= (ArrayType
) param
.variable_type
;
499 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
500 function
.add_parameter (new
CCodeParameter (get_parameter_array_length_cname (param
, dim
), "int"));
505 function
.add_parameter (new
CCodeParameter ("_connection", "DBusConnection*"));
507 var block
= new
CCodeBlock ();
508 var prefragment
= new
CCodeFragment ();
510 var path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get_data"));
511 path
.add_argument (new
CCodeIdentifier ("_sender"));
512 path
.add_argument (new
CCodeConstant ("\"dbus_object_path\""));
514 cdecl
= new
CCodeDeclaration ("const char *");
515 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_path", path
));
516 block
.add_statement (cdecl
);
518 cdecl
= new
CCodeDeclaration ("DBusMessage");
519 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_message"));
520 block
.add_statement (cdecl
);
522 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
523 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_iter"));
524 block
.add_statement (cdecl
);
526 block
.add_statement (prefragment
);
528 var msgcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_new_signal"));
529 msgcall
.add_argument (new
CCodeIdentifier ("_path"));
530 msgcall
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
531 msgcall
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig
))));
532 prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_message"), msgcall
)));
534 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init_append"));
535 iter_call
.add_argument (new
CCodeIdentifier ("_message"));
536 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_iter")));
537 prefragment
.append (new
CCodeExpressionStatement (iter_call
));
539 foreach (Parameter param
in sig
.get_parameters ()) {
540 CCodeExpression expr
= new
CCodeIdentifier (param
.name
);
541 if (param
.variable_type
.is_real_struct_type ()) {
542 expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, expr
);
544 write_expression (prefragment
, param
.variable_type
, new
CCodeIdentifier ("_iter"), expr
);
547 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_send"));
548 ccall
.add_argument (new
CCodeIdentifier ("_connection"));
549 ccall
.add_argument (new
CCodeIdentifier ("_message"));
550 ccall
.add_argument (new
CCodeConstant ("NULL"));
551 block
.add_statement (new
CCodeExpressionStatement (ccall
));
553 var message_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
554 message_unref
.add_argument (new
CCodeIdentifier ("_message"));
555 block
.add_statement (new
CCodeExpressionStatement (message_unref
));
557 cfile
.add_function_declaration (function
);
558 function
.block
= block
;
559 cfile
.add_function (function
);
564 void generate_register_function (ObjectType object_type
) {
566 cfile
.add_include ("string.h");
568 var sym
= object_type
.type_symbol
;
570 var cfunc
= new
CCodeFunction (sym
.get_lower_case_cprefix () + "dbus_register_object", "void");
571 cfunc
.add_parameter (new
CCodeParameter ("connection", "DBusConnection*"));
572 cfunc
.add_parameter (new
CCodeParameter ("path", "const char*"));
573 cfunc
.add_parameter (new
CCodeParameter ("object", "void*"));
577 if (sym
.is_private_symbol ()) {
578 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
581 cfile
.add_function_declaration (cfunc
);
583 var block
= new
CCodeBlock ();
586 var get_path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get_data"));
587 get_path
.add_argument (new
CCodeIdentifier ("object"));
588 get_path
.add_argument (new
CCodeConstant ("\"dbus_object_path\""));
589 var register_check
= new
CCodeUnaryExpression (CCodeUnaryOperator
.LOGICAL_NEGATION
, get_path
);
591 var register_block
= new
CCodeBlock ();
593 var path_dup
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup"));
594 path_dup
.add_argument (new
CCodeIdentifier ("path"));
596 var set_path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_set_data"));
597 set_path
.add_argument (new
CCodeIdentifier ("object"));
598 set_path
.add_argument (new
CCodeConstant ("\"dbus_object_path\""));
599 set_path
.add_argument (path_dup
);
600 register_block
.add_statement (new
CCodeExpressionStatement (set_path
));
602 var cregister
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_register_object_path"));
603 cregister
.add_argument (new
CCodeIdentifier ("connection"));
604 cregister
.add_argument (new
CCodeIdentifier ("path"));
605 cregister
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_path_vtable (object_type
)));
606 cregister
.add_argument (new
CCodeIdentifier ("object"));
607 register_block
.add_statement (new
CCodeExpressionStatement (cregister
));
609 var weak_unregister
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_weak_ref"));
610 weak_unregister
.add_argument (new
CCodeIdentifier ("object"));
611 weak_unregister
.add_argument (new
CCodeIdentifier ("_vala_dbus_unregister_object"));
612 weak_unregister
.add_argument (new
CCodeIdentifier ("connection"));
613 register_block
.add_statement (new
CCodeExpressionStatement (weak_unregister
));
615 block
.add_statement (new
CCodeIfStatement (register_check
, register_block
));
617 handle_signals (object_type
.type_symbol
, block
);
619 var cl
= sym as Class
;
621 foreach (DataType base_type
in cl
.get_base_types ()) {
622 var base_obj_type
= base_type as ObjectType
;
623 if (type_implements_dbus_interface (base_obj_type
.type_symbol
)) {
624 var base_register
= new
CCodeFunctionCall (new
CCodeIdentifier (base_obj_type
.type_symbol
.get_lower_case_cprefix () + "dbus_register_object"));
625 base_register
.add_argument (new
CCodeIdentifier ("connection"));
626 base_register
.add_argument (new
CCodeIdentifier ("path"));
627 base_register
.add_argument (new
CCodeIdentifier ("object"));
628 block
.add_statement (new
CCodeExpressionStatement (base_register
));
633 cfile
.add_function (cfunc
);
636 void generate_unregister_function (ObjectType object_type
) {
637 var sym
= object_type
.type_symbol
;
639 var cfunc
= new
CCodeFunction ("_" + sym
.get_lower_case_cprefix () + "dbus_unregister", "void");
640 cfunc
.add_parameter (new
CCodeParameter ("connection", "DBusConnection*"));
641 cfunc
.add_parameter (new
CCodeParameter ("_user_data_", "void*"));
643 cfile
.add_function_declaration (cfunc
);
645 var block
= new
CCodeBlock ();
648 cfile
.add_function (cfunc
);
651 void handle_method (string dbus_iface_name
, string dbus_method_name
, string handler_name
, CCodeBlock block
, ref CCodeIfStatement clastif
) {
652 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_is_method_call"));
653 ccheck
.add_argument (new
CCodeIdentifier ("message"));
654 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
655 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_method_name
)));
657 var callblock
= new
CCodeBlock ();
659 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (handler_name
));
660 ccall
.add_argument (new
CCodeIdentifier ("object"));
661 ccall
.add_argument (new
CCodeIdentifier ("connection"));
662 ccall
.add_argument (new
CCodeIdentifier ("message"));
664 callblock
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("result"), ccall
)));
666 var cif
= new
CCodeIfStatement (ccheck
, callblock
);
667 if (clastif
== null) {
668 block
.add_statement (cif
);
670 clastif
.false_statement
= cif
;
676 void handle_methods (ObjectTypeSymbol sym
, string dbus_iface_name
, CCodeBlock block
, ref CCodeIfStatement clastif
) {
677 foreach (Method m
in sym
.get_methods ()) {
678 if (m is CreationMethod
|| m
.binding
!= MemberBinding
.INSTANCE
679 || m
.overrides
|| m
.access
!= SymbolAccessibility
.PUBLIC
) {
682 if (!is_dbus_visible (m
)) {
686 handle_method (dbus_iface_name
, get_dbus_name_for_member (m
), generate_dbus_wrapper (m
, sym
), block
, ref clastif
);
690 string generate_dbus_property_get_wrapper (ObjectTypeSymbol sym
, string dbus_iface_name
) {
691 string wrapper_name
= "_dbus_%s_property_get".printf (sym
.get_lower_case_cname ());
693 CCodeDeclaration cdecl
;
695 var function
= new
CCodeFunction (wrapper_name
, "DBusHandlerResult");
696 function
.modifiers
= CCodeModifiers
.STATIC
;
698 function
.add_parameter (new
CCodeParameter ("self", sym
.get_cname () + "*"));
699 function
.add_parameter (new
CCodeParameter ("connection", "DBusConnection*"));
700 function
.add_parameter (new
CCodeParameter ("message", "DBusMessage*"));
702 var block
= new
CCodeBlock ();
703 var prefragment
= new
CCodeFragment ();
705 cdecl
= new
CCodeDeclaration ("DBusMessage*");
706 cdecl
.add_declarator (new
CCodeVariableDeclarator ("reply"));
707 block
.add_statement (cdecl
);
709 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
710 cdecl
.add_declarator (new
CCodeVariableDeclarator ("iter"));
711 cdecl
.add_declarator (new
CCodeVariableDeclarator ("reply_iter"));
712 cdecl
.add_declarator (new
CCodeVariableDeclarator ("subiter"));
713 block
.add_statement (cdecl
);
715 var message_signature
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_get_signature"));
716 message_signature
.add_argument (new
CCodeIdentifier ("message"));
717 var signature_check
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
718 signature_check
.add_argument (message_signature
);
719 signature_check
.add_argument (new
CCodeConstant ("\"ss\""));
720 var signature_error_block
= new
CCodeBlock ();
721 signature_error_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
722 block
.add_statement (new
CCodeIfStatement (signature_check
, signature_error_block
));
724 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init"));
725 iter_call
.add_argument (new
CCodeIdentifier ("message"));
726 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("iter")));
727 block
.add_statement (new
CCodeExpressionStatement (iter_call
));
729 var msgcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_new_method_return"));
730 msgcall
.add_argument (new
CCodeIdentifier ("message"));
731 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("reply"), msgcall
)));
733 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init_append"));
734 iter_call
.add_argument (new
CCodeIdentifier ("reply"));
735 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("reply_iter")));
736 block
.add_statement (new
CCodeExpressionStatement (iter_call
));
738 block
.add_statement (prefragment
);
740 cdecl
= new
CCodeDeclaration ("char*");
741 cdecl
.add_declarator (new
CCodeVariableDeclarator ("interface_name"));
742 prefragment
.append (cdecl
);
743 var target
= new
CCodeIdentifier ("interface_name");
744 var expr
= read_expression (prefragment
, string_type
, new
CCodeIdentifier ("iter"), target
);
745 prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
747 cdecl
= new
CCodeDeclaration ("char*");
748 cdecl
.add_declarator (new
CCodeVariableDeclarator ("property_name"));
749 prefragment
.append (cdecl
);
750 target
= new
CCodeIdentifier ("property_name");
751 expr
= read_expression (prefragment
, string_type
, new
CCodeIdentifier ("iter"), target
);
752 prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
754 CCodeIfStatement clastif
= null;
756 foreach (Property prop
in sym
.get_properties ()) {
757 if (prop
.binding
!= MemberBinding
.INSTANCE
758 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
761 if (!is_dbus_visible (prop
)) {
764 if (prop
.get_accessor
== null) {
768 var prop_block
= new
CCodeBlock ();
769 var postfragment
= new
CCodeFragment ();
770 prop_block
.add_statement (postfragment
);
772 var ccmp
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
773 ccmp
.add_argument (new
CCodeIdentifier ("interface_name"));
774 ccmp
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
775 var ccheck1
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccmp
, new
CCodeConstant ("0"));
777 ccmp
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
778 ccmp
.add_argument (new
CCodeIdentifier ("property_name"));
779 ccmp
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
780 var ccheck2
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccmp
, new
CCodeConstant ("0"));
782 var ccheck
= new
CCodeBinaryExpression (CCodeBinaryOperator
.AND
, ccheck1
, ccheck2
);
784 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
785 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("reply_iter")));
786 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_VARIANT"));
787 iter_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_type_signature (prop
.property_type
))));
788 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("subiter")));
789 postfragment
.append (new
CCodeExpressionStatement (iter_call
));
791 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (prop
.get_accessor
.get_cname ()));
792 ccall
.add_argument (new
CCodeIdentifier ("self"));
794 cdecl
= new
CCodeDeclaration (prop
.property_type
.get_cname ());
795 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
796 postfragment
.append (cdecl
);
798 if (prop
.property_type
.is_real_non_null_struct_type ()) {
799 // structs are returned via out parameter
800 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
802 postfragment
.append (new
CCodeExpressionStatement (ccall
));
804 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("result"), ccall
)));
806 var array_type
= prop
.property_type as ArrayType
;
807 if (array_type
!= null) {
808 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
809 string length_cname
= get_array_length_cname ("result", dim
);
811 cdecl
= new
CCodeDeclaration ("int");
812 cdecl
.add_declarator (new
CCodeVariableDeclarator (length_cname
));
813 postfragment
.append (cdecl
);
815 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
820 write_expression (postfragment
, prop
.property_type
, new
CCodeIdentifier ("subiter"), new
CCodeIdentifier ("result"));
822 if (requires_destroy (prop
.get_accessor
.value_type
)) {
823 // keep local alive (symbol_reference is weak)
824 // space before `result' is work around to not trigger
825 // variable renaming, we really mean C identifier `result' here
826 var local
= new
LocalVariable (prop
.get_accessor
.value_type
, " result");
827 var ma
= new MemberAccess
.simple ("result");
828 ma
.symbol_reference
= local
;
829 ma
.value_type
= local
.variable_type
.copy ();
830 visit_member_access (ma
);
831 postfragment
.append (new
CCodeExpressionStatement (get_unref_expression (new
CCodeIdentifier ("result"), prop
.get_accessor
.value_type
, ma
)));
834 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
835 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("reply_iter")));
836 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("subiter")));
837 postfragment
.append (new
CCodeExpressionStatement (iter_call
));
839 var cif
= new
CCodeIfStatement (ccheck
, prop_block
);
840 if (clastif
== null) {
841 block
.add_statement (cif
);
843 clastif
.false_statement
= cif
;
849 // free interface_name and property_name
850 var free_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
851 free_call
.add_argument (new
CCodeIdentifier ("interface_name"));
852 block
.add_statement (new
CCodeExpressionStatement (free_call
));
854 free_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
855 free_call
.add_argument (new
CCodeIdentifier ("property_name"));
856 block
.add_statement (new
CCodeExpressionStatement (free_call
));
858 if (clastif
== null) {
859 block
= new
CCodeBlock ();
860 block
.add_statement (new
CCodeReturnStatement (new
CCodeConstant ("NULL")));
862 var else_block
= new
CCodeBlock ();
863 var unref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
864 unref_call
.add_argument (new
CCodeIdentifier ("reply"));
865 else_block
.add_statement (new
CCodeExpressionStatement (unref_call
));
866 else_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("reply"), new
CCodeConstant ("NULL"))));
867 clastif
.false_statement
= else_block
;
869 handle_reply (block
);
872 cfile
.add_function_declaration (function
);
874 function
.block
= block
;
875 cfile
.add_function (function
);
880 string generate_dbus_property_get_all_wrapper (ObjectTypeSymbol sym
, string dbus_iface_name
) {
881 string wrapper_name
= "_dbus_%s_property_get_all".printf (sym
.get_lower_case_cname ());
883 bool has_readable_properties
= false;
884 foreach (Property prop
in sym
.get_properties ()) {
885 if (prop
.binding
!= MemberBinding
.INSTANCE
886 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
889 if (!is_dbus_visible (prop
)) {
892 if (prop
.get_accessor
!= null) {
893 has_readable_properties
= true;
897 CCodeDeclaration cdecl
;
899 var function
= new
CCodeFunction (wrapper_name
, "DBusHandlerResult");
900 function
.modifiers
= CCodeModifiers
.STATIC
;
902 function
.add_parameter (new
CCodeParameter ("self", sym
.get_cname () + "*"));
903 function
.add_parameter (new
CCodeParameter ("connection", "DBusConnection*"));
904 function
.add_parameter (new
CCodeParameter ("message", "DBusMessage*"));
906 var block
= new
CCodeBlock ();
907 var prefragment
= new
CCodeFragment ();
909 cdecl
= new
CCodeDeclaration ("DBusMessage*");
910 cdecl
.add_declarator (new
CCodeVariableDeclarator ("reply"));
911 block
.add_statement (cdecl
);
913 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
914 cdecl
.add_declarator (new
CCodeVariableDeclarator ("iter"));
915 cdecl
.add_declarator (new
CCodeVariableDeclarator ("reply_iter"));
916 cdecl
.add_declarator (new
CCodeVariableDeclarator ("subiter"));
917 if (has_readable_properties
) {
918 cdecl
.add_declarator (new
CCodeVariableDeclarator ("entry_iter"));
919 cdecl
.add_declarator (new
CCodeVariableDeclarator ("value_iter"));
921 block
.add_statement (cdecl
);
923 var message_signature
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_get_signature"));
924 message_signature
.add_argument (new
CCodeIdentifier ("message"));
925 var signature_check
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
926 signature_check
.add_argument (message_signature
);
927 signature_check
.add_argument (new
CCodeConstant ("\"s\""));
928 var signature_error_block
= new
CCodeBlock ();
929 signature_error_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
930 block
.add_statement (new
CCodeIfStatement (signature_check
, signature_error_block
));
932 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init"));
933 iter_call
.add_argument (new
CCodeIdentifier ("message"));
934 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("iter")));
935 block
.add_statement (new
CCodeExpressionStatement (iter_call
));
937 var msgcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_new_method_return"));
938 msgcall
.add_argument (new
CCodeIdentifier ("message"));
939 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("reply"), msgcall
)));
941 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init_append"));
942 iter_call
.add_argument (new
CCodeIdentifier ("reply"));
943 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("reply_iter")));
944 block
.add_statement (new
CCodeExpressionStatement (iter_call
));
946 block
.add_statement (prefragment
);
948 cdecl
= new
CCodeDeclaration ("char*");
949 cdecl
.add_declarator (new
CCodeVariableDeclarator ("interface_name"));
950 prefragment
.append (cdecl
);
951 var target
= new
CCodeIdentifier ("interface_name");
952 var expr
= read_expression (prefragment
, string_type
, new
CCodeIdentifier ("iter"), target
);
953 prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
955 if (has_readable_properties
) {
956 cdecl
= new
CCodeDeclaration ("const char*");
957 cdecl
.add_declarator (new
CCodeVariableDeclarator ("property_name"));
958 prefragment
.append (cdecl
);
961 var prop_block
= new
CCodeBlock ();
963 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
964 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("reply_iter")));
965 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_ARRAY"));
966 iter_call
.add_argument (new
CCodeConstant ("\"{sv}\""));
967 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("subiter")));
968 prop_block
.add_statement (new
CCodeExpressionStatement (iter_call
));
970 foreach (Property prop
in sym
.get_properties ()) {
971 if (prop
.binding
!= MemberBinding
.INSTANCE
972 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
975 if (!is_dbus_visible (prop
)) {
978 if (prop
.get_accessor
== null) {
982 var inner_block
= new
CCodeBlock ();
983 prop_block
.add_statement (inner_block
);
984 var postfragment
= new
CCodeFragment ();
985 inner_block
.add_statement (postfragment
);
987 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
988 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("subiter")));
989 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_DICT_ENTRY"));
990 iter_call
.add_argument (new
CCodeConstant ("NULL"));
991 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("entry_iter")));
992 postfragment
.append (new
CCodeExpressionStatement (iter_call
));
994 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("property_name"), new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))))));
996 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_append_basic"));
997 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("entry_iter")));
998 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_STRING"));
999 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("property_name")));
1000 postfragment
.append (new
CCodeExpressionStatement (iter_call
));
1002 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
1003 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("entry_iter")));
1004 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_VARIANT"));
1005 iter_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_type_signature (prop
.property_type
))));
1006 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("value_iter")));
1007 postfragment
.append (new
CCodeExpressionStatement (iter_call
));
1009 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (prop
.get_accessor
.get_cname ()));
1010 ccall
.add_argument (new
CCodeIdentifier ("self"));
1012 cdecl
= new
CCodeDeclaration (prop
.property_type
.get_cname ());
1013 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
1014 postfragment
.append (cdecl
);
1016 if (prop
.property_type
.is_real_non_null_struct_type ()) {
1017 // structs are returned via out parameter
1018 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
1020 postfragment
.append (new
CCodeExpressionStatement (ccall
));
1022 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("result"), ccall
)));
1024 var array_type
= prop
.property_type as ArrayType
;
1025 if (array_type
!= null) {
1026 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1027 string length_cname
= get_array_length_cname ("result", dim
);
1029 cdecl
= new
CCodeDeclaration ("int");
1030 cdecl
.add_declarator (new
CCodeVariableDeclarator (length_cname
));
1031 postfragment
.append (cdecl
);
1033 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (length_cname
)));
1038 write_expression (postfragment
, prop
.property_type
, new
CCodeIdentifier ("value_iter"), new
CCodeIdentifier ("result"));
1040 if (requires_destroy (prop
.get_accessor
.value_type
)) {
1041 // keep local alive (symbol_reference is weak)
1042 // space before `result' is work around to not trigger
1043 // variable renaming, we really mean C identifier `result' here
1044 var local
= new
LocalVariable (prop
.get_accessor
.value_type
, " result");
1045 var ma
= new MemberAccess
.simple ("result");
1046 ma
.symbol_reference
= local
;
1047 ma
.value_type
= local
.variable_type
.copy ();
1048 visit_member_access (ma
);
1049 postfragment
.append (new
CCodeExpressionStatement (get_unref_expression (new
CCodeIdentifier ("result"), prop
.get_accessor
.value_type
, ma
)));
1052 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
1053 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("entry_iter")));
1054 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("value_iter")));
1055 postfragment
.append (new
CCodeExpressionStatement (iter_call
));
1057 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
1058 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("subiter")));
1059 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("entry_iter")));
1060 postfragment
.append (new
CCodeExpressionStatement (iter_call
));
1063 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
1064 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("reply_iter")));
1065 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("subiter")));
1066 prop_block
.add_statement (new
CCodeExpressionStatement (iter_call
));
1068 var ccmp
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
1069 ccmp
.add_argument (new
CCodeIdentifier ("interface_name"));
1070 ccmp
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
1071 var ccheck
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccmp
, new
CCodeConstant ("0"));
1073 var else_block
= new
CCodeBlock ();
1074 var unref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
1075 unref_call
.add_argument (new
CCodeIdentifier ("reply"));
1076 else_block
.add_statement (new
CCodeExpressionStatement (unref_call
));
1077 else_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("reply"), new
CCodeConstant ("NULL"))));
1079 block
.add_statement (new
CCodeIfStatement (ccheck
, prop_block
, else_block
));
1081 // free interface_name
1082 var free_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1083 free_call
.add_argument (new
CCodeIdentifier ("interface_name"));
1084 block
.add_statement (new
CCodeExpressionStatement (free_call
));
1086 handle_reply (block
);
1088 cfile
.add_function_declaration (function
);
1090 function
.block
= block
;
1091 cfile
.add_function (function
);
1093 return wrapper_name
;
1096 string generate_dbus_property_set_wrapper (ObjectTypeSymbol sym
, string dbus_iface_name
) {
1097 string wrapper_name
= "_dbus_%s_property_set".printf (sym
.get_lower_case_cname ());
1099 var function
= new
CCodeFunction (wrapper_name
, "DBusHandlerResult");
1100 function
.modifiers
= CCodeModifiers
.STATIC
;
1102 function
.add_parameter (new
CCodeParameter ("self", sym
.get_cname () + "*"));
1103 function
.add_parameter (new
CCodeParameter ("connection", "DBusConnection*"));
1104 function
.add_parameter (new
CCodeParameter ("message", "DBusMessage*"));
1106 var block
= new
CCodeBlock ();
1107 var prefragment
= new
CCodeFragment ();
1109 var cdecl
= new
CCodeDeclaration ("DBusMessage*");
1110 cdecl
.add_declarator (new
CCodeVariableDeclarator ("reply"));
1111 block
.add_statement (cdecl
);
1113 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
1114 cdecl
.add_declarator (new
CCodeVariableDeclarator ("iter"));
1115 cdecl
.add_declarator (new
CCodeVariableDeclarator ("subiter"));
1116 block
.add_statement (cdecl
);
1118 var message_signature
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_get_signature"));
1119 message_signature
.add_argument (new
CCodeIdentifier ("message"));
1120 var signature_check
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
1121 signature_check
.add_argument (message_signature
);
1122 signature_check
.add_argument (new
CCodeConstant ("\"ssv\""));
1123 var signature_error_block
= new
CCodeBlock ();
1124 signature_error_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1125 block
.add_statement (new
CCodeIfStatement (signature_check
, signature_error_block
));
1127 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init"));
1128 iter_call
.add_argument (new
CCodeIdentifier ("message"));
1129 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("iter")));
1130 block
.add_statement (new
CCodeExpressionStatement (iter_call
));
1132 var msgcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_new_method_return"));
1133 msgcall
.add_argument (new
CCodeIdentifier ("message"));
1134 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("reply"), msgcall
)));
1136 block
.add_statement (prefragment
);
1138 cdecl
= new
CCodeDeclaration ("char*");
1139 cdecl
.add_declarator (new
CCodeVariableDeclarator ("interface_name"));
1140 prefragment
.append (cdecl
);
1141 var target
= new
CCodeIdentifier ("interface_name");
1142 var expr
= read_expression (prefragment
, string_type
, new
CCodeIdentifier ("iter"), target
);
1143 prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
1145 cdecl
= new
CCodeDeclaration ("char*");
1146 cdecl
.add_declarator (new
CCodeVariableDeclarator ("property_name"));
1147 prefragment
.append (cdecl
);
1148 target
= new
CCodeIdentifier ("property_name");
1149 expr
= read_expression (prefragment
, string_type
, new
CCodeIdentifier ("iter"), target
);
1150 prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
1152 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
1153 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("iter")));
1154 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("subiter")));
1155 prefragment
.append (new
CCodeExpressionStatement (iter_call
));
1157 CCodeIfStatement clastif
= null;
1159 foreach (Property prop
in sym
.get_properties ()) {
1160 if (prop
.binding
!= MemberBinding
.INSTANCE
1161 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
1164 if (!is_dbus_visible (prop
)) {
1167 if (prop
.set_accessor
== null) {
1171 var prop_block
= new
CCodeBlock ();
1172 prefragment
= new
CCodeFragment ();
1173 prop_block
.add_statement (prefragment
);
1175 var ccmp
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
1176 ccmp
.add_argument (new
CCodeIdentifier ("interface_name"));
1177 ccmp
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
1178 var ccheck1
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccmp
, new
CCodeConstant ("0"));
1180 ccmp
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
1181 ccmp
.add_argument (new
CCodeIdentifier ("property_name"));
1182 ccmp
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
1183 var ccheck2
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, ccmp
, new
CCodeConstant ("0"));
1185 var ccheck
= new
CCodeBinaryExpression (CCodeBinaryOperator
.AND
, ccheck1
, ccheck2
);
1187 var owned_type
= prop
.property_type
.copy ();
1188 owned_type
.value_owned
= true;
1190 cdecl
= new
CCodeDeclaration (owned_type
.get_cname ());
1191 cdecl
.add_declarator (new
CCodeVariableDeclarator ("value"));
1192 prefragment
.append (cdecl
);
1194 target
= new
CCodeIdentifier ("value");
1195 expr
= read_expression (prefragment
, prop
.property_type
, new
CCodeIdentifier ("subiter"), target
);
1196 prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
1198 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (prop
.set_accessor
.get_cname ()));
1199 ccall
.add_argument (new
CCodeIdentifier ("self"));
1201 if (prop
.property_type
.is_real_non_null_struct_type ()) {
1202 // structs are passed by reference
1203 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("value")));
1205 ccall
.add_argument (new
CCodeIdentifier ("value"));
1207 var array_type
= prop
.property_type as ArrayType
;
1208 if (array_type
!= null) {
1209 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1210 cdecl
= new
CCodeDeclaration ("int");
1211 cdecl
.add_declarator (new
CCodeVariableDeclarator (get_array_length_cname ("value", dim
)));
1212 prefragment
.append (cdecl
);
1214 ccall
.add_argument (new
CCodeIdentifier (get_array_length_cname ("value", dim
)));
1219 prop_block
.add_statement (new
CCodeExpressionStatement (ccall
));
1221 if (requires_destroy (owned_type
)) {
1222 // keep local alive (symbol_reference is weak)
1223 var local
= new
LocalVariable (owned_type
, "value");
1224 var ma
= new MemberAccess
.simple ("value");
1225 ma
.symbol_reference
= local
;
1226 ma
.value_type
= local
.variable_type
.copy ();
1227 visit_member_access (ma
);
1228 prop_block
.add_statement (new
CCodeExpressionStatement (get_unref_expression (new
CCodeIdentifier ("value"), owned_type
, ma
)));
1231 var cif
= new
CCodeIfStatement (ccheck
, prop_block
);
1232 if (clastif
== null) {
1233 block
.add_statement (cif
);
1235 clastif
.false_statement
= cif
;
1241 // free interface_name and property_name
1242 var free_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1243 free_call
.add_argument (new
CCodeIdentifier ("interface_name"));
1244 block
.add_statement (new
CCodeExpressionStatement (free_call
));
1246 free_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1247 free_call
.add_argument (new
CCodeIdentifier ("property_name"));
1248 block
.add_statement (new
CCodeExpressionStatement (free_call
));
1250 if (clastif
== null) {
1251 block
= new
CCodeBlock ();
1252 block
.add_statement (new
CCodeReturnStatement (new
CCodeConstant ("NULL")));
1254 var else_block
= new
CCodeBlock ();
1255 var unref_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
1256 unref_call
.add_argument (new
CCodeIdentifier ("reply"));
1257 else_block
.add_statement (new
CCodeExpressionStatement (unref_call
));
1258 else_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("reply"), new
CCodeIdentifier ("NULL"))));
1259 clastif
.false_statement
= else_block
;
1261 handle_reply (block
);
1264 cfile
.add_function_declaration (function
);
1266 function
.block
= block
;
1267 cfile
.add_function (function
);
1269 return wrapper_name
;
1272 string get_dbus_type_introspection (ObjectTypeSymbol sym
) {
1275 var cl
= sym as Class
;
1277 foreach (DataType base_type
in cl
.get_base_types ()) {
1278 var base_obj_type
= base_type as ObjectType
;
1279 result
+= get_dbus_type_introspection (base_obj_type
.type_symbol
);
1283 string dbus_iface_name
= get_dbus_name (sym
);
1284 if (dbus_iface_name
== null) {
1288 result
+= "<interface name=\"%s\">\n".printf (dbus_iface_name
);
1290 foreach (var m
in sym
.get_methods ()) {
1291 if (m is CreationMethod
|| m
.binding
!= MemberBinding
.INSTANCE
1292 || m
.overrides
|| m
.access
!= SymbolAccessibility
.PUBLIC
) {
1295 if (!is_dbus_visible (m
)) {
1299 result
+= " <method name=\"%s\">\n".printf (get_dbus_name_for_member (m
));
1301 foreach (var param
in m
.get_parameters ()) {
1302 if (param
.variable_type
.data_type
!= null
1303 && param
.variable_type
.data_type
.get_full_name () == "DBus.BusName") {
1304 // skip sender parameter
1305 // (implicit in D-Bus)
1309 string direction
= param
.direction
== ParameterDirection
.IN ?
"in" : "out";
1310 result
+= " <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n".printf (param
.name
, get_type_signature (param
.variable_type
), direction
);
1312 if (!(m
.return_type is VoidType
)) {
1313 result
+= " <arg name=\"%s\" type=\"%s\" direction=\"out\"/>\n".printf (dbus_result_name (m
), get_type_signature (m
.return_type
));
1316 result
+= " </method>\n";
1319 foreach (var prop
in sym
.get_properties ()) {
1320 if (prop
.binding
!= MemberBinding
.INSTANCE
1321 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
1324 if (!is_dbus_visible (prop
)) {
1328 string access
= (prop
.get_accessor
!= null ?
"read" : "") + (prop
.set_accessor
!= null ?
"write" : "");
1329 result
+= " <property name=\"%s\" type=\"%s\" access=\"%s\"/>\n".printf (get_dbus_name_for_member (prop
), get_type_signature (prop
.property_type
), access
);
1332 foreach (var sig
in sym
.get_signals ()) {
1333 if (sig
.access
!= SymbolAccessibility
.PUBLIC
) {
1336 if (!is_dbus_visible (sig
)) {
1340 result
+= " <signal name=\"%s\">\n".printf (get_dbus_name_for_member (sig
));
1342 foreach (var param
in sig
.get_parameters ()) {
1343 result
+= " <arg name=\"%s\" type=\"%s\"/>\n".printf (param
.name
, get_type_signature (param
.variable_type
));
1346 result
+= " </signal>\n";
1349 result
+= "</interface>\n";
1354 string generate_dbus_introspect (ObjectTypeSymbol sym
) {
1355 string wrapper_name
= "_dbus_%s_introspect".printf (sym
.get_lower_case_cname ());
1357 var function
= new
CCodeFunction (wrapper_name
, "DBusHandlerResult");
1358 function
.modifiers
= CCodeModifiers
.STATIC
;
1360 function
.add_parameter (new
CCodeParameter ("self", sym
.get_cname () + "*"));
1361 function
.add_parameter (new
CCodeParameter ("connection", "DBusConnection*"));
1362 function
.add_parameter (new
CCodeParameter ("message", "DBusMessage*"));
1364 var block
= new
CCodeBlock ();
1366 var cdecl
= new
CCodeDeclaration ("DBusMessage*");
1367 cdecl
.add_declarator (new
CCodeVariableDeclarator ("reply"));
1368 block
.add_statement (cdecl
);
1370 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
1371 cdecl
.add_declarator (new
CCodeVariableDeclarator ("iter"));
1372 block
.add_statement (cdecl
);
1374 var msgcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_new_method_return"));
1375 msgcall
.add_argument (new
CCodeIdentifier ("message"));
1376 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("reply"), msgcall
)));
1378 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init_append"));
1379 iter_call
.add_argument (new
CCodeIdentifier ("reply"));
1380 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("iter")));
1381 block
.add_statement (new
CCodeExpressionStatement (iter_call
));
1383 cdecl
= new
CCodeDeclaration ("GString*");
1384 cdecl
.add_declarator (new
CCodeVariableDeclarator ("xml_data"));
1385 block
.add_statement (cdecl
);
1387 cdecl
= new
CCodeDeclaration ("char**");
1388 cdecl
.add_declarator (new
CCodeVariableDeclarator ("children"));
1389 block
.add_statement (cdecl
);
1391 cdecl
= new
CCodeDeclaration ("int");
1392 cdecl
.add_declarator (new
CCodeVariableDeclarator ("i"));
1393 block
.add_statement (cdecl
);
1395 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";
1396 var str_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_string_new"));
1397 str_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (xml_data
.escape (""))));
1398 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("xml_data"), str_call
)));
1400 xml_data
= "<node>\n";
1402 """<interface name="org
.freedesktop
.DBus
.Introspectable
">
1403 <method name="Introspect
">
1404 <arg name="data
" direction="out" type="s
"/>
1407 <interface name="org
.freedesktop
.DBus
.Properties
">
1409 <arg name="interface" direction="in" type="s
"/>
1410 <arg name="propname
" direction="in" type="s
"/>
1411 <arg name="value
" direction="out" type="v
"/>
1414 <arg name="interface" direction="in" type="s
"/>
1415 <arg name="propname
" direction="in" type="s
"/>
1416 <arg name="value
" direction="in" type="v
"/>
1418 <method name="GetAll
">
1419 <arg name="interface" direction="in" type="s
"/>
1420 <arg name="props
" direction="out" type="a
{sv
}"/>
1424 xml_data
+= get_dbus_type_introspection (sym
);
1425 str_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_string_append"));
1426 str_call
.add_argument (new
CCodeIdentifier ("xml_data"));
1427 str_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (xml_data
.escape (""))));
1428 block
.add_statement (new
CCodeExpressionStatement (str_call
));
1430 var get_path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get_data"));
1431 get_path
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "GObject *"));
1432 get_path
.add_argument (new
CCodeConstant ("\"dbus_object_path\""));
1434 var list_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_list_registered"));
1435 list_call
.add_argument (new
CCodeIdentifier ("connection"));
1436 list_call
.add_argument (get_path
);
1437 list_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("children")));
1438 block
.add_statement (new
CCodeExpressionStatement (list_call
));
1441 var child_block
= new
CCodeBlock ();
1442 str_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_string_append_printf"));
1443 str_call
.add_argument (new
CCodeIdentifier ("xml_data"));
1444 str_call
.add_argument (new
CCodeConstant ("\"%s\"".printf ("<node name=\"%s\"/>\n".escape (""))));
1445 str_call
.add_argument (new
CCodeElementAccess (new
CCodeIdentifier ("children"), new
CCodeIdentifier ("i")));
1446 child_block
.add_statement (new
CCodeExpressionStatement (str_call
));
1447 var cfor
= new
CCodeForStatement (new
CCodeElementAccess (new
CCodeIdentifier ("children"), new
CCodeIdentifier ("i")), child_block
);
1448 cfor
.add_initializer (new
CCodeAssignment (new
CCodeIdentifier ("i"), new
CCodeConstant ("0")));
1449 cfor
.add_iterator (new
CCodeUnaryExpression (CCodeUnaryOperator
.POSTFIX_INCREMENT
, new
CCodeIdentifier ("i")));
1450 block
.add_statement (cfor
);
1452 var list_free_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_free_string_array"));
1453 list_free_call
.add_argument (new
CCodeIdentifier ("children"));
1454 block
.add_statement (new
CCodeExpressionStatement (list_free_call
));
1456 xml_data
= "</node>\n";
1457 str_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_string_append"));
1458 str_call
.add_argument (new
CCodeIdentifier ("xml_data"));
1459 str_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (xml_data
.escape (""))));
1460 block
.add_statement (new
CCodeExpressionStatement (str_call
));
1462 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_append_basic"));
1463 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("iter")));
1464 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_STRING"));
1465 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("xml_data"), "str")));
1466 block
.add_statement (new
CCodeExpressionStatement (iter_call
));
1468 str_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_string_free"));
1469 str_call
.add_argument (new
CCodeIdentifier ("xml_data"));
1470 str_call
.add_argument (new
CCodeConstant ("TRUE"));
1471 block
.add_statement (new
CCodeExpressionStatement (str_call
));
1473 handle_reply (block
);
1475 cfile
.add_function_declaration (function
);
1477 function
.block
= block
;
1478 cfile
.add_function (function
);
1480 return wrapper_name
;
1483 void handle_signals (ObjectTypeSymbol sym
, CCodeBlock block
) {
1484 string dbus_iface_name
= get_dbus_name (sym
);
1485 if (dbus_iface_name
== null) {
1489 foreach (Signal sig
in sym
.get_signals ()) {
1490 if (sig
.access
!= SymbolAccessibility
.PUBLIC
) {
1493 if (!is_dbus_visible (sig
)) {
1497 var connect
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_connect"));
1498 connect
.add_argument (new
CCodeIdentifier ("object"));
1499 connect
.add_argument (sig
.get_canonical_cconstant ());
1500 connect
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier (generate_dbus_signal_wrapper (sig
, sym
, dbus_iface_name
)), "GCallback"));
1501 connect
.add_argument (new
CCodeIdentifier ("connection"));
1502 block
.add_statement (new
CCodeExpressionStatement (connect
));
1506 void generate_message_function (ObjectType object_type
) {
1507 var sym
= object_type
.type_symbol
;
1509 add_dbus_helpers ();
1511 var cfunc
= new
CCodeFunction (sym
.get_lower_case_cprefix () + "dbus_message", "DBusHandlerResult");
1512 cfunc
.add_parameter (new
CCodeParameter ("connection", "DBusConnection*"));
1513 cfunc
.add_parameter (new
CCodeParameter ("message", "DBusMessage*"));
1514 cfunc
.add_parameter (new
CCodeParameter ("object", "void*"));
1516 if (sym
.is_private_symbol ()) {
1517 cfunc
.modifiers
|= CCodeModifiers
.STATIC
;
1520 cfile
.add_function_declaration (cfunc
);
1522 var block
= new
CCodeBlock ();
1523 cfunc
.block
= block
;
1525 var cdecl
= new
CCodeDeclaration ("DBusHandlerResult");
1526 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result", new
CCodeConstant ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1527 block
.add_statement (cdecl
);
1529 CCodeIfStatement clastif
= null;
1531 handle_method ("org.freedesktop.DBus.Introspectable", "Introspect", generate_dbus_introspect (sym
), block
, ref clastif
);
1533 string dbus_iface_name
= get_dbus_name (sym
);
1534 if (dbus_iface_name
!= null) {
1535 bool need_property_get
= false;
1536 bool need_property_set
= false;
1537 foreach (Property prop
in sym
.get_properties ()) {
1538 if (prop
.binding
!= MemberBinding
.INSTANCE
1539 || prop
.overrides
|| prop
.access
!= SymbolAccessibility
.PUBLIC
) {
1542 if (!is_dbus_visible (prop
)) {
1545 if (prop
.get_accessor
!= null) {
1546 need_property_get
= true;
1548 if (prop
.set_accessor
!= null) {
1549 need_property_set
= true;
1553 if (need_property_get
) {
1554 handle_method ("org.freedesktop.DBus.Properties", "Get", generate_dbus_property_get_wrapper (sym
, dbus_iface_name
), block
, ref clastif
);
1556 if (need_property_set
) {
1557 handle_method ("org.freedesktop.DBus.Properties", "Set", generate_dbus_property_set_wrapper (sym
, dbus_iface_name
), block
, ref clastif
);
1559 handle_method ("org.freedesktop.DBus.Properties", "GetAll", generate_dbus_property_get_all_wrapper (sym
, dbus_iface_name
), block
, ref clastif
);
1561 handle_methods (sym
, dbus_iface_name
, block
, ref clastif
);
1564 var resultblock
= new
CCodeBlock ();
1565 resultblock
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("result")));
1566 var cif
= new
CCodeIfStatement (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, new
CCodeIdentifier ("result"), new
CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")), resultblock
);
1567 block
.add_statement (cif
);
1570 var cl
= sym as Class
;
1572 foreach (DataType base_type
in cl
.get_base_types ()) {
1573 var base_obj_type
= base_type as ObjectType
;
1574 if (type_implements_dbus_interface (base_obj_type
.type_symbol
)) {
1575 var base_call
= new
CCodeFunctionCall (new
CCodeIdentifier (base_obj_type
.type_symbol
.get_lower_case_cprefix () + "dbus_message"));
1576 base_call
.add_argument (new
CCodeIdentifier ("connection"));
1577 base_call
.add_argument (new
CCodeIdentifier ("message"));
1578 base_call
.add_argument (new
CCodeIdentifier ("object"));
1580 var ccheck
= new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, base_call
, new
CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED"));
1582 var base_block
= new
CCodeBlock ();
1583 base_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")));
1585 cif
= new
CCodeIfStatement (ccheck
, base_block
);
1586 clastif
.false_statement
= cif
;
1593 var retblock
= new
CCodeBlock ();
1594 retblock
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1595 clastif
.false_statement
= retblock
;
1597 cfile
.add_function (cfunc
);
1600 CCodeExpression
get_vtable (ObjectType object_type
) {
1601 var sym
= object_type
.type_symbol
;
1603 if (add_wrapper ("_" + sym
.get_lower_case_cprefix () + "dbus_vtable")) {
1604 var vtable
= new
CCodeInitializerList ();
1605 vtable
.append (new
CCodeIdentifier (sym
.get_lower_case_cprefix () + "dbus_register_object"));
1607 generate_register_function (object_type
);
1609 var cdecl
= new
CCodeDeclaration ("const _DBusObjectVTable");
1610 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_vtable", vtable
));
1611 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
1612 cfile
.add_constant_declaration (cdecl
);
1615 return new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_vtable");
1618 CCodeExpression
get_path_vtable (ObjectType object_type
) {
1619 var sym
= object_type
.type_symbol
;
1621 var vtable
= new
CCodeInitializerList ();
1622 vtable
.append (new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_unregister"));
1623 vtable
.append (new
CCodeIdentifier (sym
.get_lower_case_cprefix () + "dbus_message"));
1625 generate_unregister_function (object_type
);
1626 generate_message_function (object_type
);
1628 var cdecl
= new
CCodeDeclaration ("const DBusObjectPathVTable");
1629 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + sym
.get_lower_case_cprefix () + "dbus_path_vtable", vtable
));
1630 cdecl
.modifiers
= CCodeModifiers
.STATIC
;
1631 cfile
.add_constant_declaration (cdecl
);
1633 return new
CCodeIdentifier ("_" + sym
.get_lower_case_cprefix () + "dbus_path_vtable");
1636 public override void visit_method_call (MethodCall expr
) {
1637 var mtype
= expr
.call
.value_type as MethodType
;
1638 if (mtype
== null || (mtype
.method_symbol
.get_cname () != "dbus_connection_register_g_object" &&
1639 mtype
.method_symbol
.get_cname () != "dbus_g_connection_register_g_object")) {
1640 base.visit_method_call (expr
);
1644 add_dbus_helpers ();
1646 var ma
= (MemberAccess
) expr
.call
;
1648 var raw_conn
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_get_connection"));
1649 raw_conn
.add_argument (get_cvalue (ma
.inner
));
1651 var args_it
= expr
.get_argument_list ().iterator ();
1653 var path_arg
= args_it
.get ();
1655 var obj_arg
= args_it
.get ();
1657 var cregister
= new
CCodeFunctionCall (new
CCodeIdentifier ("_vala_dbus_register_object"));
1658 if (mtype
.method_symbol
.get_cname () == "dbus_g_connection_register_g_object") {
1659 cregister
.add_argument (raw_conn
);
1661 cregister
.add_argument (get_cvalue (ma
.inner
));
1663 cregister
.add_argument (get_cvalue (path_arg
));
1664 cregister
.add_argument (get_cvalue (obj_arg
));
1666 ccode
.add_expression (cregister
);
1669 bool type_implements_dbus_interface (ObjectTypeSymbol sym
) {
1670 var dbus
= sym
.get_attribute ("DBus");
1675 var cl
= sym as Class
;
1677 foreach (DataType base_type
in cl
.get_base_types ()) {
1678 var base_obj_type
= base_type as ObjectType
;
1679 if (type_implements_dbus_interface (base_obj_type
.type_symbol
)) {
1688 public override void register_dbus_info (CCodeBlock block
, ObjectTypeSymbol sym
) {
1689 if (!type_implements_dbus_interface (sym
)) {
1693 base.register_dbus_info (block
, sym
);
1695 var quark
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_static_string"));
1696 quark
.add_argument (new
CCodeConstant ("\"DBusObjectVTable\""));
1698 var set_qdata
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_set_qdata"));
1699 set_qdata
.add_argument (new
CCodeIdentifier ("%s_type_id".printf (sym
.get_lower_case_cname (null))));
1700 set_qdata
.add_argument (quark
);
1701 set_qdata
.add_argument (new
CCodeCastExpression (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_vtable (new
ObjectType (sym
))), "void*"));
1703 block
.add_statement (new
CCodeExpressionStatement (set_qdata
));