1 /* valadbusclientmodule.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 internal class Vala
.DBusClientModule
: DBusModule
{
31 int dynamic_property_id
;
33 public DBusClientModule (CCodeGenerator codegen
, CCodeModule? next
) {
37 string get_dynamic_dbus_name (string vala_name
) {
38 // TODO switch default to no transformation as soon as we have static D-Bus client support
39 // keep transformation by default for static D-Bus client and server support
40 if (context
.dbus_transformation
) {
41 return Symbol
.lower_case_to_camel_case (vala_name
);
47 bool has_dbus_error (List
<DataType
> error_types
) {
48 foreach (DataType error_type
in error_types
) {
49 if (((ErrorType
) error_type
).error_domain
.get_full_name () == "DBus.Error") {
56 public override void generate_dynamic_method_wrapper (DynamicMethod method
) {
57 var dynamic_method
= (DynamicMethod
) method
;
59 var func
= new
CCodeFunction (method
.get_cname ());
60 func
.modifiers
= CCodeModifiers
.STATIC
;
62 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
64 generate_cparameters (method
, source_declarations
, cparam_map
, func
);
66 var block
= new
CCodeBlock ();
67 if (dynamic_method
.dynamic_type
.data_type
== dbus_object_type
) {
68 generate_dbus_method_wrapper (method
, block
);
70 Report
.error (method
.source_reference
, "dynamic methods are not supported for `%s'".printf (dynamic_method
.dynamic_type
.to_string ()));
73 // append to C source file
74 source_declarations
.add_type_member_declaration (func
.copy ());
77 source_type_member_definition
.append (func
);
80 void generate_dbus_method_wrapper (Method method
, CCodeBlock block
) {
81 var dynamic_method
= (DynamicMethod
) method
;
83 var expr
= dynamic_method
.invocation
;
85 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_begin_call"));
87 ccall
.add_argument (new
CCodeIdentifier ("self"));
89 bool found_out
= false;
90 Expression
callback = null;
91 int callback_index
= -1;
93 foreach (Expression arg
in expr
.get_argument_list ()) {
94 if (arg
.symbol_reference is Method
) {
96 if (callback != null) {
97 Report
.error (expr
.source_reference
, "only one reply callback may be specified in invocation of DBus method");
100 } else if (found_out
) {
101 Report
.error (expr
.source_reference
, "out argument and reply callback conflict in invocation of DBus method");
106 callback_index
= arg_index
;
107 } else if (arg is UnaryExpression
&& ((UnaryExpression
) arg
).operator
== UnaryOperator
.OUT
) {
109 if (callback != null) {
110 Report
.error (expr
.source_reference
, "out argument and reply callback conflict in invocation of DBus method");
117 if (callback != null || found_out
) {
118 Report
.error (expr
.source_reference
, "in argument must not follow out argument or reply callback in invocation of DBus method");
126 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (method
.name
))));
128 if (callback != null) {
129 var reply_method
= (Method
) callback.symbol_reference
;
131 var cb_fun
= new
CCodeFunction ("_%s_cb".printf (reply_method
.get_cname ()), "void");
132 cb_fun
.modifiers
= CCodeModifiers
.STATIC
;
133 cb_fun
.add_parameter (new
CCodeFormalParameter ("proxy", "DBusGProxy*"));
134 cb_fun
.add_parameter (new
CCodeFormalParameter ("call", "DBusGProxyCall*"));
135 cb_fun
.add_parameter (new
CCodeFormalParameter ("user_data", "void*"));
136 cb_fun
.block
= new
CCodeBlock ();
137 var cerrdecl
= new
CCodeDeclaration ("GError*");
138 cerrdecl
.add_declarator (new
CCodeVariableDeclarator ("error", new
CCodeConstant ("NULL")));
139 cb_fun
.block
.add_statement (cerrdecl
);
140 var cend_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_end_call"));
141 cend_call
.add_argument (new
CCodeIdentifier ("proxy"));
142 cend_call
.add_argument (new
CCodeIdentifier ("call"));
143 cend_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("error")));
144 var creply_call
= new
CCodeFunctionCall ((CCodeExpression
) callback.ccodenode
);
145 if (reply_method
.binding
!= MemberBinding
.STATIC
) {
146 creply_call
.add_argument (new
CCodeIdentifier ("user_data"));
148 int param_count
= reply_method
.get_parameters ().size
;
150 foreach (FormalParameter param
in reply_method
.get_parameters ()) {
151 if ((++i
) == param_count
) {
152 if (!(param
.parameter_type is ErrorType
)) {
153 Report
.error (null, "DBus reply callbacks must end with GLib.Error argument");
159 if (param
.parameter_type is ArrayType
&& ((ArrayType
) param
.parameter_type
).element_type
.data_type
!= string_type
.data_type
) {
160 var array_type
= (ArrayType
) param
.parameter_type
;
161 CCodeDeclaration cdecl
;
162 if (dbus_use_ptr_array (array_type
)) {
163 cdecl
= new
CCodeDeclaration ("GPtrArray*");
165 cdecl
= new
CCodeDeclaration ("GArray*");
167 cdecl
.add_declarator (new
CCodeVariableDeclarator (param
.name
));
168 cb_fun
.block
.add_statement (cdecl
);
169 cend_call
.add_argument (get_dbus_g_type (array_type
));
170 cend_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (param
.name
)));
171 creply_call
.add_argument (new
CCodeCastExpression (new CCodeMemberAccess
.pointer (new
CCodeIdentifier (param
.name
), dbus_use_ptr_array (array_type
) ?
"pdata" : "data"), array_type
.get_cname ()));
172 creply_call
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier (param
.name
), "len"));
174 var cdecl
= new
CCodeDeclaration (param
.parameter_type
.get_cname ());
175 cdecl
.add_declarator (new
CCodeVariableDeclarator (param
.name
));
176 cb_fun
.block
.add_statement (cdecl
);
177 cend_call
.add_argument (get_dbus_g_type (param
.parameter_type
));
178 cend_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (param
.name
)));
179 creply_call
.add_argument (new
CCodeIdentifier (param
.name
));
181 if (param
.parameter_type is ArrayType
&& ((ArrayType
) param
.parameter_type
).element_type
.data_type
== string_type
.data_type
) {
182 var cstrvlen
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strv_length"));
183 cstrvlen
.add_argument (new
CCodeIdentifier (param
.name
));
184 creply_call
.add_argument (cstrvlen
);
189 cend_call
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
190 cb_fun
.block
.add_statement (new
CCodeExpressionStatement (cend_call
));
191 creply_call
.add_argument (new
CCodeIdentifier ("error"));
192 cb_fun
.block
.add_statement (new
CCodeExpressionStatement (creply_call
));
194 if (!source_declarations
.add_declaration (cb_fun
.name
)) {
195 // avoid duplicate function definition
196 source_type_member_definition
.append (cb_fun
);
199 ccall
.add_argument (new
CCodeIdentifier (cb_fun
.name
));
200 ccall
.add_argument (new
CCodeConstant ("param%d_target".printf (callback_index
)));
201 ccall
.add_argument (new
CCodeConstant ("NULL"));
203 ccall
.call
= new
CCodeIdentifier ("dbus_g_proxy_call");
205 ccall
.add_argument (new
CCodeIdentifier ("error"));
208 foreach (FormalParameter param
in method
.get_parameters ()) {
209 if (param
.parameter_type is MethodType
210 || param
.parameter_type is DelegateType
) {
211 // callback parameter
215 if (param
.direction
!= ParameterDirection
.IN
) {
219 var array_type
= param
.parameter_type as ArrayType
;
220 if (array_type
!= null) {
222 if (array_type
.element_type
.data_type
!= string_type
.data_type
) {
223 // non-string arrays (use GArray)
224 ccall
.add_argument (get_dbus_g_type (array_type
));
226 var sizeof_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
227 sizeof_call
.add_argument (new
CCodeIdentifier (array_type
.element_type
.get_cname ()));
229 CCodeDeclaration cdecl
;
230 CCodeFunctionCall array_construct
;
231 if (dbus_use_ptr_array (array_type
)) {
232 cdecl
= new
CCodeDeclaration ("GPtrArray*");
234 array_construct
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_ptr_array_sized_new"));
235 array_construct
.add_argument (new
CCodeIdentifier (head
.get_array_length_cname (param
.name
, 1)));
237 cdecl
= new
CCodeDeclaration ("GArray*");
239 array_construct
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_array_new"));
240 array_construct
.add_argument (new
CCodeConstant ("TRUE"));
241 array_construct
.add_argument (new
CCodeConstant ("TRUE"));
242 array_construct
.add_argument (sizeof_call
);
245 cdecl
.add_declarator (new
CCodeVariableDeclarator ("dbus_%s".printf (param
.name
), array_construct
));
246 block
.add_statement (cdecl
);
248 if (dbus_use_ptr_array (array_type
)) {
249 source_declarations
.add_include ("string.h");
251 var memcpy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("memcpy"));
252 memcpy_call
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)), "pdata"));
253 memcpy_call
.add_argument (new
CCodeIdentifier (param
.name
));
254 memcpy_call
.add_argument (new
CCodeBinaryExpression (CCodeBinaryOperator
.MUL
, new
CCodeIdentifier (head
.get_array_length_cname (param
.name
, 1)), sizeof_call
));
255 block
.add_statement (new
CCodeExpressionStatement (memcpy_call
));
257 var len_assignment
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)), "len"), new
CCodeIdentifier (head
.get_array_length_cname (param
.name
, 1)));
258 block
.add_statement (new
CCodeExpressionStatement (len_assignment
));
260 var cappend_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_array_append_vals"));
261 cappend_call
.add_argument (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)));
262 cappend_call
.add_argument (new
CCodeIdentifier (param
.name
));
263 cappend_call
.add_argument (new
CCodeIdentifier (head
.get_array_length_cname (param
.name
, 1)));
264 block
.add_statement (new
CCodeExpressionStatement (cappend_call
));
267 ccall
.add_argument (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)));
270 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_STRV"));
271 ccall
.add_argument (new
CCodeIdentifier (param
.name
));
273 } else if (get_type_signature (param
.parameter_type
).has_prefix ("(")) {
275 var st
= (Struct
) param
.parameter_type
.data_type
;
277 var array_construct
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_array_new"));
278 array_construct
.add_argument (new
CCodeConstant ("0"));
280 var cdecl
= new
CCodeDeclaration ("GValueArray*");
281 cdecl
.add_declarator (new
CCodeVariableDeclarator ("dbus_%s".printf (param
.name
), array_construct
));
282 block
.add_statement (cdecl
);
284 foreach (Field f
in st
.get_fields ()) {
285 if (f
.binding
!= MemberBinding
.INSTANCE
) {
289 string val_name
= "val_%s_%s".printf (param
.name
, f
.name
);
291 // 0-initialize struct with struct initializer { 0 }
292 var cvalinit
= new
CCodeInitializerList ();
293 cvalinit
.append (new
CCodeConstant ("0"));
295 var cval_decl
= new
CCodeDeclaration ("GValue");
296 cval_decl
.add_declarator (new CCodeVariableDeclarator
.zero (val_name
, cvalinit
));
297 block
.add_statement (cval_decl
);
299 var val_ptr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (val_name
));
301 var cinit_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_init"));
302 cinit_call
.add_argument (val_ptr
);
303 cinit_call
.add_argument (new
CCodeIdentifier (f
.field_type
.data_type
.get_type_id ()));
304 block
.add_statement (new
CCodeExpressionStatement (cinit_call
));
306 var cset_call
= new
CCodeFunctionCall (new
CCodeIdentifier (f
.field_type
.data_type
.get_set_value_function ()));
307 cset_call
.add_argument (val_ptr
);
308 cset_call
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier (param
.name
), f
.name
));
309 block
.add_statement (new
CCodeExpressionStatement (cset_call
));
311 var cappend_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_array_append"));
312 cappend_call
.add_argument (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)));
313 cappend_call
.add_argument (val_ptr
);
314 block
.add_statement (new
CCodeExpressionStatement (cappend_call
));
317 ccall
.add_argument (get_dbus_g_type (param
.parameter_type
));
318 ccall
.add_argument (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)));
320 ccall
.add_argument (get_dbus_g_type (param
.parameter_type
));
321 ccall
.add_argument (new
CCodeIdentifier (param
.name
));
325 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
327 var out_marshalling_fragment
= new
CCodeFragment ();
329 foreach (FormalParameter param
in method
.get_parameters ()) {
330 if (param
.parameter_type is MethodType
) {
331 // callback parameter
335 if (param
.direction
!= ParameterDirection
.OUT
) {
339 if (get_type_signature (param
.parameter_type
).has_prefix ("(")) {
340 // struct output parameter
341 var st
= (Struct
) param
.parameter_type
.data_type
;
343 var cdecl
= new
CCodeDeclaration ("GValueArray*");
344 cdecl
.add_declarator (new
CCodeVariableDeclarator ("dbus_%s".printf (param
.name
)));
345 block
.add_statement (cdecl
);
348 foreach (Field f
in st
.get_fields ()) {
349 if (f
.binding
!= MemberBinding
.INSTANCE
) {
353 var cget_call
= new
CCodeFunctionCall (new
CCodeIdentifier (f
.field_type
.data_type
.get_get_value_function ()));
354 cget_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeElementAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dbus_%s".printf (param
.name
)), "values"), new
CCodeConstant (i
.to_string ()))));
356 var converted_value
= cget_call
;
358 if (requires_copy (f
.field_type
)) {
359 var dupexpr
= get_dup_func_expression (f
.field_type
, expr
.source_reference
);
360 converted_value
= new
CCodeFunctionCall (dupexpr
);
361 converted_value
.add_argument (cget_call
);
364 var assign
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier (param
.name
), f
.name
), converted_value
);
365 out_marshalling_fragment
.append (new
CCodeExpressionStatement (assign
));
370 ccall
.add_argument (get_dbus_g_type (param
.parameter_type
));
371 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("dbus_%s".printf (param
.name
))));
373 ccall
.add_argument (get_dbus_g_type (param
.parameter_type
));
374 ccall
.add_argument (new
CCodeIdentifier (param
.name
));
378 if (!(method
.return_type is VoidType
)) {
379 // synchronous D-Bus method call with reply
380 ccall
.add_argument (get_dbus_g_type (method
.return_type
));
382 var array_type
= method
.return_type as ArrayType
;
383 if (array_type
!= null && array_type
.element_type
.data_type
!= string_type
.data_type
) {
384 // non-string arrays (use GArray)
385 CCodeDeclaration cdecl
;
386 if (dbus_use_ptr_array (array_type
)) {
387 cdecl
= new
CCodeDeclaration ("GPtrArray*");
389 cdecl
= new
CCodeDeclaration ("GArray*");
391 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
392 block
.add_statement (cdecl
);
394 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
395 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
397 block
.add_statement (new
CCodeExpressionStatement (ccall
));
399 // don't access result when error occured
400 var creturnblock
= new
CCodeBlock ();
401 creturnblock
.add_statement (new
CCodeReturnStatement (default_value_for_type (method
.return_type
, false)));
402 var cerrorif
= new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("error")), creturnblock
);
403 block
.add_statement (cerrorif
);
405 block
.add_statement (out_marshalling_fragment
);
407 // *result_length1 = result->len;
408 var garray_length
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("result"), "len");
409 var result_length
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result_length1"));
410 var assign
= new
CCodeAssignment (result_length
, garray_length
);
411 block
.add_statement (new
CCodeExpressionStatement (assign
));
413 // return result->data;
414 block
.add_statement (new
CCodeReturnStatement (new
CCodeCastExpression (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("result"), dbus_use_ptr_array (array_type
) ?
"pdata" : "data"), method
.return_type
.get_cname ())));
415 } else if (method
.return_type
.is_real_non_null_struct_type ()) {
416 // structs are returned via out parameter
417 var st
= (Struct
) method
.return_type
.data_type
;
419 if (st
.get_full_name () == "GLib.Value") {
420 ccall
.add_argument (new
CCodeIdentifier ("result"));
421 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
423 block
.add_statement (new
CCodeExpressionStatement (ccall
));
425 var cdecl
= new
CCodeDeclaration ("GValueArray*");
426 cdecl
.add_declarator (new
CCodeVariableDeclarator ("dbus_result"));
427 block
.add_statement (cdecl
);
430 foreach (Field f
in st
.get_fields ()) {
431 if (f
.binding
!= MemberBinding
.INSTANCE
) {
435 var cget_call
= new
CCodeFunctionCall (new
CCodeIdentifier (f
.field_type
.data_type
.get_get_value_function ()));
436 cget_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeElementAccess (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("dbus_result"), "values"), new
CCodeConstant (i
.to_string ()))));
438 var converted_value
= cget_call
;
440 if (requires_copy (f
.field_type
)) {
441 var dupexpr
= get_dup_func_expression (f
.field_type
, expr
.source_reference
);
442 converted_value
= new
CCodeFunctionCall (dupexpr
);
443 converted_value
.add_argument (cget_call
);
446 var assign
= new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("result"), f
.name
), converted_value
);
447 out_marshalling_fragment
.append (new
CCodeExpressionStatement (assign
));
452 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("dbus_result")));
453 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
455 block
.add_statement (new
CCodeExpressionStatement (ccall
));
458 // don't access result when error occured
459 var creturnblock
= new
CCodeBlock ();
460 creturnblock
.add_statement (new
CCodeReturnStatement ());
461 var cerrorif
= new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("error")), creturnblock
);
462 block
.add_statement (cerrorif
);
464 block
.add_statement (out_marshalling_fragment
);
466 // string arrays or other datatypes
467 var cdecl
= new
CCodeDeclaration (method
.return_type
.get_cname ());
468 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
469 block
.add_statement (cdecl
);
471 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("result")));
472 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
474 block
.add_statement (new
CCodeExpressionStatement (ccall
));
476 // don't access result when error occured
477 var creturnblock
= new
CCodeBlock ();
478 creturnblock
.add_statement (new
CCodeReturnStatement (default_value_for_type (method
.return_type
, false)));
479 var cerrorif
= new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("error")), creturnblock
);
480 block
.add_statement (cerrorif
);
482 block
.add_statement (out_marshalling_fragment
);
484 if (array_type
!= null) {
485 // special case string array
487 // *result_length1 = g_strv_length (result);
488 var cstrvlen
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strv_length"));
489 cstrvlen
.add_argument (new
CCodeIdentifier ("result"));
490 var result_length
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result_length1"));
491 var assign
= new
CCodeAssignment (result_length
, cstrvlen
);
492 block
.add_statement (new
CCodeExpressionStatement (assign
));
495 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("result")));
498 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
500 block
.add_statement (new
CCodeExpressionStatement (ccall
));
502 // don't access result when error occured
503 var creturnblock
= new
CCodeBlock ();
504 creturnblock
.add_statement (new
CCodeReturnStatement ());
505 var cerrorif
= new
CCodeIfStatement (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("error")), creturnblock
);
506 block
.add_statement (cerrorif
);
508 block
.add_statement (out_marshalling_fragment
);
512 public override CCodeExpression
get_dbus_g_type (DataType data_type
) {
513 if (data_type is ArrayType
) {
514 var array_type
= data_type as ArrayType
;
515 if (array_type
.element_type
.data_type
== string_type
.data_type
) {
516 return new
CCodeIdentifier ("G_TYPE_STRV");
519 var carray_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_type_get_collection"));
520 if (dbus_use_ptr_array (array_type
)) {
521 carray_type
.add_argument (new
CCodeConstant ("\"GPtrArray\""));
523 carray_type
.add_argument (new
CCodeConstant ("\"GArray\""));
525 carray_type
.add_argument (get_dbus_g_type (array_type
.element_type
));
527 } else if (data_type
.data_type is Enum
) {
528 var en
= (Enum
) data_type
.data_type
;
530 return new
CCodeIdentifier ("G_TYPE_UINT");
532 return new
CCodeIdentifier ("G_TYPE_INT");
534 } else if (data_type
.data_type
== null) {
535 critical ("Internal error during DBus type generation with: %s", data_type
.to_string ());
536 return new
CCodeIdentifier ("G_TYPE_NONE");
537 } else if (data_type
.data_type
.get_full_name () == "GLib.HashTable") {
538 var cmap_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_type_get_map"));
539 var type_args
= data_type
.get_type_arguments ();
541 cmap_type
.add_argument (new
CCodeConstant ("\"GHashTable\""));
542 foreach (DataType type_arg
in type_args
) {
543 cmap_type
.add_argument (get_dbus_g_type (type_arg
));
547 } else if (get_type_signature (data_type
).has_prefix ("(")) {
549 var st
= (Struct
) data_type
.data_type
;
551 var type_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_type_get_struct"));
552 type_call
.add_argument (new
CCodeConstant ("\"GValueArray\""));
554 foreach (Field f
in st
.get_fields ()) {
555 if (f
.binding
!= MemberBinding
.INSTANCE
) {
559 type_call
.add_argument (get_dbus_g_type (f
.field_type
));
562 type_call
.add_argument (new
CCodeConstant ("G_TYPE_INVALID"));
566 return new
CCodeIdentifier (data_type
.data_type
.get_type_id ());
570 public bool dbus_use_ptr_array (ArrayType array_type
) {
571 if (array_type
.element_type
.data_type
== string_type
.data_type
) {
574 } else if (array_type
.element_type
.data_type
== bool_type
.data_type
575 || array_type
.element_type
.data_type
== char_type
.data_type
576 || array_type
.element_type
.data_type
== uchar_type
.data_type
577 || array_type
.element_type
.data_type
== int_type
.data_type
578 || array_type
.element_type
.data_type
== uint_type
.data_type
579 || array_type
.element_type
.data_type
== long_type
.data_type
580 || array_type
.element_type
.data_type
== ulong_type
.data_type
581 || array_type
.element_type
.data_type
== int8_type
.data_type
582 || array_type
.element_type
.data_type
== uint8_type
.data_type
583 || array_type
.element_type
.data_type
== int32_type
.data_type
584 || array_type
.element_type
.data_type
== uint32_type
.data_type
585 || array_type
.element_type
.data_type
== int64_type
.data_type
586 || array_type
.element_type
.data_type
== uint64_type
.data_type
587 || array_type
.element_type
.data_type
== double_type
.data_type
) {
596 public override string get_dynamic_property_getter_cname (DynamicProperty prop
) {
597 if (prop
.dynamic_type
.data_type
!= dbus_object_type
) {
598 return base.get_dynamic_property_getter_cname (prop
);
601 string getter_cname
= "_dynamic_get_%s%d".printf (prop
.name
, dynamic_property_id
++);
603 if (get_type_signature (prop
.property_type
) == null) {
604 Report
.error (prop
.property_type
.source_reference
, "D-Bus serialization of type `%s' is not supported".printf (prop
.property_type
.to_string ()));
608 var func
= new
CCodeFunction (getter_cname
, prop
.property_type
.get_cname ());
609 func
.modifiers
|= CCodeModifiers
.STATIC
| CCodeModifiers
.INLINE
;
611 func
.add_parameter (new
CCodeFormalParameter ("obj", prop
.dynamic_type
.get_cname ()));
613 var block
= new
CCodeBlock ();
614 generate_dbus_property_getter_wrapper (prop
, block
);
616 // append to C source file
617 source_declarations
.add_type_member_declaration (func
.copy ());
620 source_type_member_definition
.append (func
);
625 public override string get_dynamic_property_setter_cname (DynamicProperty prop
) {
626 if (prop
.dynamic_type
.data_type
!= dbus_object_type
) {
627 return base.get_dynamic_property_setter_cname (prop
);
630 string setter_cname
= "_dynamic_set_%s%d".printf (prop
.name
, dynamic_property_id
++);
632 if (get_type_signature (prop
.property_type
) == null) {
633 Report
.error (prop
.property_type
.source_reference
, "D-Bus serialization of type `%s' is not supported".printf (prop
.property_type
.to_string ()));
637 var func
= new
CCodeFunction (setter_cname
, "void");
638 func
.modifiers
|= CCodeModifiers
.STATIC
| CCodeModifiers
.INLINE
;
640 func
.add_parameter (new
CCodeFormalParameter ("obj", prop
.dynamic_type
.get_cname ()));
641 func
.add_parameter (new
CCodeFormalParameter ("value", prop
.property_type
.get_cname ()));
643 var block
= new
CCodeBlock ();
644 generate_dbus_property_setter_wrapper (prop
, block
);
646 // append to C source file
647 source_declarations
.add_type_member_declaration (func
.copy ());
650 source_type_member_definition
.append (func
);
655 void create_dbus_property_proxy (DynamicProperty node
, CCodeBlock block
) {
656 var prop_proxy_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_new_from_proxy"));
657 prop_proxy_call
.add_argument (new
CCodeIdentifier ("obj"));
658 prop_proxy_call
.add_argument (new
CCodeConstant ("DBUS_INTERFACE_PROPERTIES"));
659 prop_proxy_call
.add_argument (new
CCodeConstant ("NULL"));
661 var prop_proxy_decl
= new
CCodeDeclaration ("DBusGProxy*");
662 prop_proxy_decl
.add_declarator (new
CCodeVariableDeclarator ("property_proxy", prop_proxy_call
));
663 block
.add_statement (prop_proxy_decl
);
666 void generate_dbus_property_getter_wrapper (DynamicProperty node
, CCodeBlock block
) {
667 create_dbus_property_proxy (node
, block
);
670 var cvalinit
= new
CCodeInitializerList ();
671 cvalinit
.append (new
CCodeConstant ("0"));
673 var cval_decl
= new
CCodeDeclaration ("GValue");
674 cval_decl
.add_declarator (new CCodeVariableDeclarator
.zero ("gvalue", cvalinit
));
675 block
.add_statement (cval_decl
);
677 var val_ptr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("gvalue"));
679 // call Get method on property proxy
680 var cdecl
= new
CCodeDeclaration (node
.property_type
.get_cname ());
681 cdecl
.add_declarator (new
CCodeVariableDeclarator ("result"));
682 block
.add_statement (cdecl
);
684 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_call"));
685 ccall
.add_argument (new
CCodeIdentifier ("property_proxy"));
686 ccall
.add_argument (new
CCodeConstant ("\"Get\""));
687 ccall
.add_argument (new
CCodeConstant ("NULL"));
689 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_STRING"));
690 var get_iface
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_get_interface"));
691 get_iface
.add_argument (new
CCodeIdentifier ("obj"));
692 ccall
.add_argument (get_iface
);
694 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_STRING"));
695 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (node
.name
))));
697 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
699 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_VALUE"));
700 ccall
.add_argument (val_ptr
);
702 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
704 block
.add_statement (new
CCodeExpressionStatement (ccall
));
706 // unref property proxy
707 var prop_proxy_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
708 prop_proxy_unref
.add_argument (new
CCodeIdentifier ("property_proxy"));
709 block
.add_statement (new
CCodeExpressionStatement (prop_proxy_unref
));
711 // assign value to result variable
712 var cget_call
= new
CCodeFunctionCall (new
CCodeIdentifier (node
.property_type
.data_type
.get_get_value_function ()));
713 cget_call
.add_argument (val_ptr
);
714 var assign
= new
CCodeAssignment (new
CCodeIdentifier ("result"), cget_call
);
715 block
.add_statement (new
CCodeExpressionStatement (assign
));
718 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("result")));
721 void generate_dbus_property_setter_wrapper (DynamicProperty node
, CCodeBlock block
) {
722 create_dbus_property_proxy (node
, block
);
725 var cvalinit
= new
CCodeInitializerList ();
726 cvalinit
.append (new
CCodeConstant ("0"));
728 var cval_decl
= new
CCodeDeclaration ("GValue");
729 cval_decl
.add_declarator (new CCodeVariableDeclarator
.zero ("gvalue", cvalinit
));
730 block
.add_statement (cval_decl
);
732 var val_ptr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("gvalue"));
734 var cinit_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_value_init"));
735 cinit_call
.add_argument (val_ptr
);
736 cinit_call
.add_argument (new
CCodeIdentifier (node
.property_type
.data_type
.get_type_id ()));
737 block
.add_statement (new
CCodeExpressionStatement (cinit_call
));
739 var cset_call
= new
CCodeFunctionCall (new
CCodeIdentifier (node
.property_type
.data_type
.get_set_value_function ()));
740 cset_call
.add_argument (val_ptr
);
741 cset_call
.add_argument (new
CCodeIdentifier ("value"));
742 block
.add_statement (new
CCodeExpressionStatement (cset_call
));
744 // call Set method on property proxy
745 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_call"));
746 ccall
.add_argument (new
CCodeIdentifier ("property_proxy"));
747 ccall
.add_argument (new
CCodeConstant ("\"Set\""));
748 ccall
.add_argument (new
CCodeConstant ("NULL"));
750 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_STRING"));
751 var get_iface
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_get_interface"));
752 get_iface
.add_argument (new
CCodeIdentifier ("obj"));
753 ccall
.add_argument (get_iface
);
755 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_STRING"));
756 ccall
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (node
.name
))));
758 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_VALUE"));
759 ccall
.add_argument (val_ptr
);
761 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
763 ccall
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
765 block
.add_statement (new
CCodeExpressionStatement (ccall
));
767 // unref property proxy
768 var prop_proxy_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
769 prop_proxy_unref
.add_argument (new
CCodeIdentifier ("property_proxy"));
770 block
.add_statement (new
CCodeExpressionStatement (prop_proxy_unref
));
773 public override string get_dynamic_signal_connect_wrapper_name (DynamicSignal sig
) {
774 if (sig
.dynamic_type
.data_type
!= dbus_object_type
) {
775 return base.get_dynamic_signal_connect_wrapper_name (sig
);
778 string connect_wrapper_name
= "_%sconnect".printf (get_dynamic_signal_cname (sig
));
779 var func
= new
CCodeFunction (connect_wrapper_name
, "void");
780 func
.add_parameter (new
CCodeFormalParameter ("obj", "gpointer"));
781 func
.add_parameter (new
CCodeFormalParameter ("signal_name", "const char *"));
782 func
.add_parameter (new
CCodeFormalParameter ("handler", "GCallback"));
783 func
.add_parameter (new
CCodeFormalParameter ("data", "gpointer"));
784 var block
= new
CCodeBlock ();
785 generate_dbus_connect_wrapper (sig
, block
);
787 // append to C source file
788 source_declarations
.add_type_member_declaration (func
.copy ());
791 source_type_member_definition
.append (func
);
793 return connect_wrapper_name
;
796 public override string get_dynamic_signal_disconnect_wrapper_name (DynamicSignal sig
) {
797 if (sig
.dynamic_type
.data_type
!= dbus_object_type
) {
798 return base.get_dynamic_signal_disconnect_wrapper_name (sig
);
801 string disconnect_wrapper_name
= "_%sdisconnect".printf (get_dynamic_signal_cname (sig
));
802 var func
= new
CCodeFunction (disconnect_wrapper_name
, "void");
803 func
.add_parameter (new
CCodeFormalParameter ("obj", "gpointer"));
804 func
.add_parameter (new
CCodeFormalParameter ("signal_name", "const char *"));
805 func
.add_parameter (new
CCodeFormalParameter ("handler", "GCallback"));
806 func
.add_parameter (new
CCodeFormalParameter ("data", "gpointer"));
807 var block
= new
CCodeBlock ();
808 generate_dbus_disconnect_wrapper (sig
, block
);
810 // append to C source file
811 source_declarations
.add_type_member_declaration (func
.copy ());
814 source_type_member_definition
.append (func
);
816 return disconnect_wrapper_name
;
819 void generate_dbus_connect_wrapper (DynamicSignal sig
, CCodeBlock block
) {
820 var m
= (Method
) sig
.handler
.symbol_reference
;
822 sig
.accept (codegen
);
824 // FIXME should only be done once per marshaller
825 var register_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_object_register_marshaller"));
826 head
.generate_marshaller (sig
.get_parameters (), sig
.return_type
, true);
827 register_call
.add_argument (new
CCodeIdentifier (head
.get_marshaller_function (sig
.get_parameters (), sig
.return_type
, null, true)));
828 register_call
.add_argument (new
CCodeIdentifier ("G_TYPE_NONE"));
830 var add_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_add_signal"));
831 add_call
.add_argument (new
CCodeIdentifier ("obj"));
832 add_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dynamic_dbus_name (sig
.name
))));
835 foreach (FormalParameter param
in m
.get_parameters ()) {
837 // skip sender parameter
842 register_call
.add_argument (get_dbus_g_type (param
.parameter_type
));
843 add_call
.add_argument (get_dbus_g_type (param
.parameter_type
));
845 register_call
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
846 add_call
.add_argument (new
CCodeIdentifier ("G_TYPE_INVALID"));
848 block
.add_statement (new
CCodeExpressionStatement (register_call
));
849 block
.add_statement (new
CCodeExpressionStatement (add_call
));
851 var call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_connect_signal"));
852 call
.add_argument (new
CCodeIdentifier ("obj"));
853 call
.add_argument (new
CCodeIdentifier ("signal_name"));
854 call
.add_argument (new
CCodeIdentifier ("handler"));
855 call
.add_argument (new
CCodeIdentifier ("data"));
856 call
.add_argument (new
CCodeConstant ("NULL"));
857 block
.add_statement (new
CCodeExpressionStatement (call
));
860 void generate_dbus_disconnect_wrapper (DynamicSignal sig
, CCodeBlock block
) {
861 var call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_disconnect_signal"));
862 call
.add_argument (new
CCodeIdentifier ("obj"));
863 call
.add_argument (new
CCodeIdentifier ("signal_name"));
864 call
.add_argument (new
CCodeIdentifier ("handler"));
865 call
.add_argument (new
CCodeIdentifier ("data"));
866 block
.add_statement (new
CCodeExpressionStatement (call
));
869 public override void visit_cast_expression (CastExpression expr
) {
870 // handles casting DBus.Object instances to DBus interfaces
872 var type
= expr
.type_reference as ObjectType
;
873 var call
= expr
.inner as MethodCall
;
874 if (type
== null || !(type
.type_symbol is Interface
)
875 || type
.type_symbol
.get_attribute ("DBus") == null || call
== null) {
876 base.visit_cast_expression (expr
);
880 var mtype
= call
.call
.value_type as MethodType
;
881 if (mtype
== null || mtype
.method_symbol
.get_cname () != "dbus_g_proxy_new_for_name") {
882 base.visit_cast_expression (expr
);
886 var args
= call
.get_argument_list ();
887 Expression connection
= ((MemberAccess
) call
.call
).inner
;
888 Expression bus_name
= args
.get (0);
889 Expression object_path
= args
.get (1);
891 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (type
.type_symbol
.get_lower_case_cprefix () + "dbus_proxy_new"));
892 connection
.accept (codegen
);
893 ccall
.add_argument ((CCodeExpression
) connection
.ccodenode
);
894 bus_name
.accept (codegen
);
895 ccall
.add_argument ((CCodeExpression
) bus_name
.ccodenode
);
896 object_path
.accept (codegen
);
897 ccall
.add_argument ((CCodeExpression
) object_path
.ccodenode
);
898 expr
.ccodenode
= ccall
;
901 void generate_proxy_interface_init (Interface main_iface
, Interface iface
) {
902 // also generate proxy for prerequisites
903 foreach (var prereq
in iface
.get_prerequisites ()) {
904 if (prereq
.data_type is Interface
) {
905 generate_proxy_interface_init (main_iface
, (Interface
) prereq
.data_type
);
909 string lower_cname
= main_iface
.get_lower_case_cprefix () + "dbus_proxy";
911 var proxy_iface_init
= new
CCodeFunction (lower_cname
+ "_" + iface
.get_lower_case_cprefix () + "_interface_init", "void");
912 proxy_iface_init
.add_parameter (new
CCodeFormalParameter ("iface", iface
.get_cname () + "Iface*"));
914 var iface_block
= new
CCodeBlock ();
916 foreach (Method m
in iface
.get_methods ()) {
917 var vfunc_entry
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("iface"), m
.vfunc_name
);
919 iface_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (vfunc_entry
, new
CCodeIdentifier (generate_dbus_proxy_method (main_iface
, iface
, m
)))));
921 iface_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (vfunc_entry
, new
CCodeIdentifier (generate_async_dbus_proxy_method (main_iface
, iface
, m
)))));
922 vfunc_entry
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("iface"), m
.get_finish_vfunc_name ());
923 iface_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (vfunc_entry
, new
CCodeIdentifier (generate_finish_dbus_proxy_method (main_iface
, iface
, m
)))));
927 foreach (Property prop
in iface
.get_properties ()) {
928 if (prop
.get_accessor
!= null) {
929 var vfunc_entry
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("iface"), "get_" + prop
.name
);
930 iface_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (vfunc_entry
, new
CCodeIdentifier (generate_dbus_proxy_property_get (main_iface
, iface
, prop
)))));
932 if (prop
.set_accessor
!= null) {
933 var vfunc_entry
= new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("iface"), "set_" + prop
.name
);
934 iface_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (vfunc_entry
, new
CCodeIdentifier (generate_dbus_proxy_property_set (main_iface
, iface
, prop
)))));
938 proxy_iface_init
.modifiers
= CCodeModifiers
.STATIC
;
939 source_declarations
.add_type_member_declaration (proxy_iface_init
.copy ());
940 proxy_iface_init
.block
= iface_block
;
941 source_type_member_definition
.append (proxy_iface_init
);
944 string implement_interface (CCodeFunctionCall define_type
, Interface main_iface
, Interface iface
) {
947 // also implement prerequisites
948 foreach (var prereq
in iface
.get_prerequisites ()) {
949 if (prereq
.data_type is Interface
) {
950 result
+= implement_interface (define_type
, main_iface
, (Interface
) prereq
.data_type
);
954 result
+= "G_IMPLEMENT_INTERFACE (%s, %sdbus_proxy_%s_interface_init) ".printf (
955 iface
.get_upper_case_cname ("TYPE_"),
956 main_iface
.get_lower_case_cprefix (),
957 iface
.get_lower_case_cprefix ());
961 void implement_property (CCodeBlock block
, Interface main_iface
, Interface iface
) {
962 // also implement prerequisites
963 foreach (var prereq
in iface
.get_prerequisites ()) {
964 if (prereq
.data_type is Interface
) {
965 implement_property (block
, main_iface
, (Interface
) prereq
.data_type
);
969 var gobject_class
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_CLASS"));
970 gobject_class
.add_argument (new
CCodeIdentifier ("klass"));
972 foreach (Property prop
in iface
.get_properties ()) {
973 if (!prop
.is_abstract
) {
977 if (prop
.property_type is ArrayType
) {
981 string prop_ev
= "%s_dbus_proxy_%s".printf (main_iface
.get_lower_case_cname (null), Symbol
.camel_case_to_lower_case (prop
.name
)).up ();
983 var cinst
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_class_override_property"));
984 cinst
.add_argument (gobject_class
);
985 cinst
.add_argument (new
CCodeConstant (prop_ev
));
986 cinst
.add_argument (prop
.get_canonical_cconstant ());
987 block
.add_statement (new
CCodeExpressionStatement (cinst
));
989 prop_enum
.add_value (new
CCodeEnumValue (prop_ev
));
993 public override void visit_interface (Interface iface
) {
994 base.visit_interface (iface
);
996 string dbus_iface_name
= get_dbus_name (iface
);
997 if (dbus_iface_name
== null) {
1001 // create proxy class
1002 string cname
= iface
.get_cname () + "DBusProxy";
1003 string lower_cname
= iface
.get_lower_case_cprefix () + "dbus_proxy";
1005 if (iface
.access
!= SymbolAccessibility
.PRIVATE
) {
1006 dbus_glib_h_needed_in_header
= true;
1008 dbus_glib_h_needed
= true;
1011 source_declarations
.add_type_declaration (new
CCodeTypeDefinition ("struct _%s".printf (cname
), new
CCodeVariableDeclarator (cname
)));
1012 source_declarations
.add_type_declaration (new
CCodeTypeDefinition ("DBusGProxyClass", new
CCodeVariableDeclarator (cname
+ "Class")));
1014 var instance_struct
= new
CCodeStruct ("_%s".printf (cname
));
1015 instance_struct
.add_field ("DBusGProxy", "parent_instance");
1016 instance_struct
.add_field ("gboolean", "disposed");
1018 source_declarations
.add_type_definition (instance_struct
);
1020 source_declarations
.add_type_member_declaration (new
CCodeFunction(lower_cname
+ "_get_type", "GType"));
1022 var define_type
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_DEFINE_TYPE_EXTENDED"));
1023 define_type
.add_argument (new
CCodeIdentifier (cname
));
1024 define_type
.add_argument (new
CCodeIdentifier (lower_cname
));
1025 define_type
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_G_PROXY"));
1026 define_type
.add_argument (new
CCodeConstant ("0"));
1027 define_type
.add_argument (new
CCodeIdentifier (implement_interface (define_type
, iface
, iface
)));
1029 source_type_member_definition
.append (new
CCodeExpressionStatement (define_type
));
1031 // generate proxy_new function
1032 var proxy_new
= new
CCodeFunction (lower_cname
+ "_new", iface
.get_cname () + "*");
1033 proxy_new
.add_parameter (new
CCodeFormalParameter ("connection", "DBusGConnection*"));
1034 proxy_new
.add_parameter (new
CCodeFormalParameter ("name", "const char*"));
1035 proxy_new
.add_parameter (new
CCodeFormalParameter ("path", "const char*"));
1037 var new_block
= new
CCodeBlock ();
1039 // create proxy object
1040 var new_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_new"));
1041 new_call
.add_argument (new
CCodeFunctionCall (new
CCodeIdentifier (lower_cname
+ "_get_type")));
1042 new_call
.add_argument (new
CCodeConstant ("\"connection\""));
1043 new_call
.add_argument (new
CCodeIdentifier ("connection"));
1044 new_call
.add_argument (new
CCodeConstant ("\"name\""));
1045 new_call
.add_argument (new
CCodeIdentifier ("name"));
1046 new_call
.add_argument (new
CCodeConstant ("\"path\""));
1047 new_call
.add_argument (new
CCodeIdentifier ("path"));
1048 new_call
.add_argument (new
CCodeConstant ("\"interface\""));
1049 new_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
1050 new_call
.add_argument (new
CCodeConstant ("NULL"));
1052 var cdecl
= new
CCodeDeclaration (iface
.get_cname () + "*");
1053 cdecl
.add_declarator (new
CCodeVariableDeclarator ("self", new_call
));
1054 new_block
.add_statement (cdecl
);
1055 new_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("self")));
1057 source_declarations
.add_type_member_declaration (proxy_new
.copy ());
1058 proxy_new
.block
= new_block
;
1059 source_type_member_definition
.append (proxy_new
);
1061 // dbus proxy construct
1062 var proxy_construct
= new
CCodeFunction (lower_cname
+ "_construct", "GObject*");
1063 proxy_construct
.add_parameter (new
CCodeFormalParameter ("gtype", "GType"));
1064 proxy_construct
.add_parameter (new
CCodeFormalParameter ("n_properties", "guint"));
1065 proxy_construct
.add_parameter (new
CCodeFormalParameter ("properties", "GObjectConstructParam*"));
1066 proxy_construct
.modifiers
= CCodeModifiers
.STATIC
;
1067 proxy_construct
.block
= new
CCodeBlock ();
1070 var parent_class
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_CLASS"));
1071 parent_class
.add_argument (new
CCodeIdentifier (lower_cname
+ "_parent_class"));
1072 var chainup
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (parent_class
, "constructor"));
1073 chainup
.add_argument (new
CCodeIdentifier ("gtype"));
1074 chainup
.add_argument (new
CCodeIdentifier ("n_properties"));
1075 chainup
.add_argument (new
CCodeIdentifier ("properties"));
1077 cdecl
= new
CCodeDeclaration ("GObject*");
1078 cdecl
.add_declarator (new
CCodeVariableDeclarator ("self", chainup
));
1079 proxy_construct
.block
.add_statement (cdecl
);
1081 cdecl
= new
CCodeDeclaration ("DBusGConnection");
1082 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*connection"));
1083 proxy_construct
.block
.add_statement (cdecl
);
1085 var gconnection
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get"));
1086 gconnection
.add_argument (new
CCodeIdentifier ("self"));
1087 gconnection
.add_argument (new
CCodeConstant ("\"connection\""));
1088 gconnection
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("connection")));
1089 gconnection
.add_argument (new
CCodeConstant ("NULL"));
1090 proxy_construct
.block
.add_statement (new
CCodeExpressionStatement (gconnection
));
1092 cdecl
= new
CCodeDeclaration ("char*");
1093 cdecl
.add_declarator (new
CCodeVariableDeclarator ("path"));
1094 proxy_construct
.block
.add_statement (cdecl
);
1096 var path
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get"));
1097 path
.add_argument (new
CCodeIdentifier ("self"));
1098 path
.add_argument (new
CCodeConstant ("\"path\""));
1099 path
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("path")));
1100 path
.add_argument (new
CCodeConstant ("NULL"));
1101 proxy_construct
.block
.add_statement (new
CCodeExpressionStatement (path
));
1103 var raw_connection
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_get_connection"));
1104 raw_connection
.add_argument (new
CCodeIdentifier ("connection"));
1106 // add filter to handle signals from the remote object
1107 var filter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_add_filter"));
1108 filter_call
.add_argument (raw_connection
);
1109 filter_call
.add_argument (new
CCodeIdentifier (lower_cname
+ "_filter"));
1110 filter_call
.add_argument (new
CCodeIdentifier ("self"));
1111 filter_call
.add_argument (new
CCodeConstant ("NULL"));
1112 proxy_construct
.block
.add_statement (new
CCodeExpressionStatement (filter_call
));
1114 var filter_printf
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_strdup_printf"));
1115 filter_printf
.add_argument (new
CCodeConstant ("\"type='signal',path='%s'\""));
1116 filter_printf
.add_argument (new
CCodeIdentifier ("path"));
1118 cdecl
= new
CCodeDeclaration ("char*");
1119 cdecl
.add_declarator (new
CCodeVariableDeclarator ("filter", filter_printf
));
1120 proxy_construct
.block
.add_statement (cdecl
);
1122 // ensure we receive signals from the remote object
1123 var match_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_bus_add_match"));
1124 match_call
.add_argument (raw_connection
);
1125 match_call
.add_argument (new
CCodeIdentifier ("filter"));
1126 match_call
.add_argument (new
CCodeConstant ("NULL"));
1127 proxy_construct
.block
.add_statement (new
CCodeExpressionStatement (match_call
));
1129 var connection_free
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_unref"));
1130 connection_free
.add_argument (new
CCodeIdentifier ("connection"));
1131 proxy_construct
.block
.add_statement (new
CCodeExpressionStatement (connection_free
));
1133 var path_free
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1134 path_free
.add_argument (new
CCodeIdentifier ("path"));
1135 proxy_construct
.block
.add_statement (new
CCodeExpressionStatement (path_free
));
1137 var filter_free
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_free"));
1138 filter_free
.add_argument (new
CCodeIdentifier ("filter"));
1139 proxy_construct
.block
.add_statement (new
CCodeExpressionStatement (filter_free
));
1141 proxy_construct
.block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("self")));
1143 source_type_member_definition
.append (proxy_construct
);
1145 // dbus proxy filter function
1146 generate_proxy_filter_function (iface
);
1148 // dbus proxy dispose
1149 var proxy_dispose
= new
CCodeFunction (lower_cname
+ "_dispose", "void");
1150 proxy_dispose
.add_parameter (new
CCodeFormalParameter ("self", "GObject*"));
1151 proxy_dispose
.modifiers
= CCodeModifiers
.STATIC
;
1152 proxy_dispose
.block
= new
CCodeBlock ();
1154 cdecl
= new
CCodeDeclaration ("DBusGConnection");
1155 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*connection"));
1156 proxy_dispose
.block
.add_statement (cdecl
);
1158 // return if proxy is already disposed
1159 var dispose_return_block
= new
CCodeBlock ();
1160 dispose_return_block
.add_statement (new
CCodeReturnStatement ());
1161 proxy_dispose
.block
.add_statement (new
CCodeIfStatement (new CCodeMemberAccess
.pointer (new
CCodeCastExpression (new
CCodeIdentifier ("self"), cname
+ "*"), "disposed"), dispose_return_block
));
1163 // mark proxy as disposed
1164 proxy_dispose
.block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeCastExpression (new
CCodeIdentifier ("self"), cname
+ "*"), "disposed"), new
CCodeConstant ("TRUE"))));
1166 gconnection
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get"));
1167 gconnection
.add_argument (new
CCodeIdentifier ("self"));
1168 gconnection
.add_argument (new
CCodeConstant ("\"connection\""));
1169 gconnection
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("connection")));
1170 gconnection
.add_argument (new
CCodeConstant ("NULL"));
1171 proxy_dispose
.block
.add_statement (new
CCodeExpressionStatement (gconnection
));
1174 filter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_remove_filter"));
1175 filter_call
.add_argument (raw_connection
);
1176 filter_call
.add_argument (new
CCodeIdentifier (lower_cname
+ "_filter"));
1177 filter_call
.add_argument (new
CCodeIdentifier ("self"));
1178 proxy_dispose
.block
.add_statement (new
CCodeExpressionStatement (filter_call
));
1181 parent_class
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_CLASS"));
1182 parent_class
.add_argument (new
CCodeIdentifier (lower_cname
+ "_parent_class"));
1183 chainup
= new
CCodeFunctionCall (new CCodeMemberAccess
.pointer (parent_class
, "dispose"));
1184 chainup
.add_argument (new
CCodeIdentifier ("self"));
1185 proxy_dispose
.block
.add_statement (new
CCodeExpressionStatement (chainup
));
1187 source_type_member_definition
.append (proxy_dispose
);
1189 var proxy_class_init
= new
CCodeFunction (lower_cname
+ "_class_init", "void");
1190 proxy_class_init
.add_parameter (new
CCodeFormalParameter ("klass", cname
+ "Class*"));
1191 proxy_class_init
.modifiers
= CCodeModifiers
.STATIC
;
1192 proxy_class_init
.block
= new
CCodeBlock ();
1193 var gobject_class
= new
CCodeFunctionCall (new
CCodeIdentifier ("G_OBJECT_CLASS"));
1194 gobject_class
.add_argument (new
CCodeIdentifier ("klass"));
1195 proxy_class_init
.block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (gobject_class
, "constructor"), new
CCodeIdentifier (lower_cname
+ "_construct"))));
1196 proxy_class_init
.block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (gobject_class
, "dispose"), new
CCodeIdentifier (lower_cname
+ "_dispose"))));
1197 proxy_class_init
.block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (gobject_class
, "get_property"), new
CCodeIdentifier (lower_cname
+ "_get_property"))));
1198 proxy_class_init
.block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (gobject_class
, "set_property"), new
CCodeIdentifier (lower_cname
+ "_set_property"))));
1199 source_type_member_definition
.append (proxy_class_init
);
1201 prop_enum
= new
CCodeEnum ();
1202 prop_enum
.add_value (new
CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (lower_cname
.up ())));
1204 implement_property (proxy_class_init
.block
, iface
, iface
);
1206 source_declarations
.add_type_member_declaration (prop_enum
);
1208 var proxy_instance_init
= new
CCodeFunction (lower_cname
+ "_init", "void");
1209 proxy_instance_init
.add_parameter (new
CCodeFormalParameter ("self", cname
+ "*"));
1210 proxy_instance_init
.modifiers
= CCodeModifiers
.STATIC
;
1211 proxy_instance_init
.block
= new
CCodeBlock ();
1212 source_type_member_definition
.append (proxy_instance_init
);
1214 generate_proxy_interface_init (iface
, iface
);
1216 // dbus proxy get/set_property stubs
1217 // TODO add actual implementation
1218 var get_prop
= new
CCodeFunction ("%s_get_property".printf (lower_cname
), "void");
1219 get_prop
.modifiers
= CCodeModifiers
.STATIC
;
1220 get_prop
.add_parameter (new
CCodeFormalParameter ("object", "GObject *"));
1221 get_prop
.add_parameter (new
CCodeFormalParameter ("property_id", "guint"));
1222 get_prop
.add_parameter (new
CCodeFormalParameter ("value", "GValue *"));
1223 get_prop
.add_parameter (new
CCodeFormalParameter ("pspec", "GParamSpec *"));
1224 source_declarations
.add_type_member_declaration (get_prop
.copy ());
1225 get_prop
.block
= new
CCodeBlock ();
1226 source_type_member_definition
.append (get_prop
);
1228 var set_prop
= new
CCodeFunction ("%s_set_property".printf (lower_cname
), "void");
1229 set_prop
.modifiers
= CCodeModifiers
.STATIC
;
1230 set_prop
.add_parameter (new
CCodeFormalParameter ("object", "GObject *"));
1231 set_prop
.add_parameter (new
CCodeFormalParameter ("property_id", "guint"));
1232 set_prop
.add_parameter (new
CCodeFormalParameter ("value", "const GValue *"));
1233 set_prop
.add_parameter (new
CCodeFormalParameter ("pspec", "GParamSpec *"));
1234 source_declarations
.add_type_member_declaration (set_prop
.copy ());
1235 set_prop
.block
= new
CCodeBlock ();
1236 source_type_member_definition
.append (set_prop
);
1239 public override TypeRegisterFunction
create_interface_register_function (Interface iface
) {
1240 string dbus_iface_name
= get_dbus_name (iface
);
1241 if (dbus_iface_name
== null) {
1242 return new
InterfaceRegisterFunction (iface
, context
);
1245 return new
DBusInterfaceRegisterFunction (iface
, context
);
1248 string generate_get_all_function (Method m
) {
1249 string get_all_func
= "_dbus_g_proxy_get_all";
1251 if (!add_wrapper (get_all_func
)) {
1252 // wrapper already defined
1253 return get_all_func
;
1256 var function
= new
CCodeFunction (get_all_func
, "GHashTable*");
1257 function
.modifiers
= CCodeModifiers
.STATIC
;
1259 function
.add_parameter (new
CCodeFormalParameter ("self", "DBusGProxy*"));
1260 function
.add_parameter (new
CCodeFormalParameter ("interface_name", "const gchar*"));
1261 function
.add_parameter (new
CCodeFormalParameter ("error", "GError**"));
1263 var block
= new
CCodeBlock ();
1264 var prefragment
= new
CCodeFragment ();
1265 var postfragment
= new
CCodeFragment ();
1267 var cdecl
= new
CCodeDeclaration ("DBusError");
1268 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_dbus_error"));
1269 block
.add_statement (cdecl
);
1271 var dbus_error
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_dbus_error"));
1273 cdecl
= new
CCodeDeclaration ("DBusGConnection");
1274 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_connection"));
1275 block
.add_statement (cdecl
);
1277 cdecl
= new
CCodeDeclaration ("DBusMessage");
1278 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_message"));
1279 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_reply"));
1280 block
.add_statement (cdecl
);
1282 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
1283 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_iter"));
1284 block
.add_statement (cdecl
);
1286 block
.add_statement (prefragment
);
1288 generate_marshalling (m
, "org.freedesktop.DBus.Properties", prefragment
, postfragment
);
1290 var gconnection
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get"));
1291 gconnection
.add_argument (new
CCodeIdentifier ("self"));
1292 gconnection
.add_argument (new
CCodeConstant ("\"connection\""));
1293 gconnection
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_connection")));
1294 gconnection
.add_argument (new
CCodeConstant ("NULL"));
1295 block
.add_statement (new
CCodeExpressionStatement (gconnection
));
1297 var dbus_error_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_error_init"));
1298 dbus_error_init
.add_argument (dbus_error
);
1299 block
.add_statement (new
CCodeExpressionStatement (dbus_error_init
));
1301 var connection
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_get_connection"));
1302 connection
.add_argument (new
CCodeIdentifier ("_connection"));
1304 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
1305 ccall
.add_argument (connection
);
1306 ccall
.add_argument (new
CCodeIdentifier ("_message"));
1307 ccall
.add_argument (new
CCodeConstant ("-1"));
1308 ccall
.add_argument (dbus_error
);
1309 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_reply"), ccall
)));
1311 var conn_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_unref"));
1312 conn_unref
.add_argument (new
CCodeIdentifier ("_connection"));
1313 block
.add_statement (new
CCodeExpressionStatement (conn_unref
));
1315 var message_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
1316 message_unref
.add_argument (new
CCodeIdentifier ("_message"));
1317 block
.add_statement (new
CCodeExpressionStatement (message_unref
));
1319 check_error_reply (m
, block
);
1320 check_reply_signature (m
, block
);
1322 block
.add_statement (postfragment
);
1324 var reply_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
1325 reply_unref
.add_argument (new
CCodeIdentifier ("_reply"));
1326 block
.add_statement (new
CCodeExpressionStatement (reply_unref
));
1328 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("_result")));
1330 source_declarations
.add_type_member_declaration (function
.copy ());
1332 function
.block
= block
;
1333 source_type_member_definition
.append (function
);
1335 return get_all_func
;
1338 public override void visit_method_call (MethodCall expr
) {
1339 var mtype
= expr
.call
.value_type as MethodType
;
1340 bool proxy_new_from_type
= (mtype
!= null && mtype
.method_symbol
.get_cname () == "dbus_g_proxy_new_from_type");
1341 bool proxy_get_all
= (mtype
!= null && mtype
.method_symbol
.get_cname () == "dbus_g_proxy_get_all");
1342 if (!proxy_new_from_type
&& !proxy_get_all
) {
1343 base.visit_method_call (expr
);
1347 if (proxy_get_all
) {
1348 var ma
= expr
.call as MemberAccess
;
1349 var instance
= ma
.inner
;
1350 instance
.accept (codegen
);
1352 var args
= expr
.get_argument_list ();
1353 Expression interface_name
= args
.get (0);
1354 interface_name
.accept (codegen
);
1356 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (generate_get_all_function (mtype
.method_symbol
)));
1357 ccall
.add_argument ((CCodeExpression
) instance
.ccodenode
);
1358 ccall
.add_argument ((CCodeExpression
) interface_name
.ccodenode
);
1360 current_method_inner_error
= true;
1361 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, get_variable_cexpression ("_inner_error_")));
1363 expr
.ccodenode
= ccall
;
1367 var args
= expr
.get_argument_list ();
1368 Expression connection
= ((MemberAccess
) expr
.call
).inner
;
1369 Expression bus_name
= args
.get (0);
1370 Expression object_path
= args
.get (1);
1371 Expression interface_name
= args
.get (2);
1372 Expression type
= args
.get (3);
1374 var quark_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_quark_from_string"));
1375 quark_call
.add_argument (new
CCodeConstant ("\"ValaDBusInterfaceProxyType\""));
1377 var qdata_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_type_get_qdata"));
1378 type
.accept (codegen
);
1379 qdata_call
.add_argument ((CCodeExpression
) type
.ccodenode
);
1380 qdata_call
.add_argument (quark_call
);
1382 var get_type_call
= new
CCodeFunctionCall (new
CCodeCastExpression (qdata_call
, "GType (*)(void)"));
1384 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_new"));
1385 ccall
.add_argument (get_type_call
);
1386 ccall
.add_argument (new
CCodeConstant ("\"connection\""));
1387 connection
.accept (codegen
);
1388 ccall
.add_argument ((CCodeExpression
) connection
.ccodenode
);
1389 ccall
.add_argument (new
CCodeConstant ("\"name\""));
1390 bus_name
.accept (codegen
);
1391 ccall
.add_argument ((CCodeExpression
) bus_name
.ccodenode
);
1392 ccall
.add_argument (new
CCodeConstant ("\"path\""));
1393 object_path
.accept (codegen
);
1394 ccall
.add_argument ((CCodeExpression
) object_path
.ccodenode
);
1395 ccall
.add_argument (new
CCodeConstant ("\"interface\""));
1396 interface_name
.accept (codegen
);
1397 ccall
.add_argument ((CCodeExpression
) interface_name
.ccodenode
);
1398 ccall
.add_argument (new
CCodeConstant ("NULL"));
1399 expr
.ccodenode
= ccall
;
1402 void generate_proxy_filter_function (Interface iface
) {
1403 string lower_cname
= iface
.get_lower_case_cprefix () + "dbus_proxy";
1405 var proxy_filter
= new
CCodeFunction (lower_cname
+ "_filter", "DBusHandlerResult");
1406 proxy_filter
.add_parameter (new
CCodeFormalParameter ("connection", "DBusConnection*"));
1407 proxy_filter
.add_parameter (new
CCodeFormalParameter ("message", "DBusMessage*"));
1408 proxy_filter
.add_parameter (new
CCodeFormalParameter ("user_data", "void*"));
1410 var filter_block
= new
CCodeBlock ();
1412 // only handle signals concering the object path
1413 var path
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_get_path"));
1414 path
.add_argument (new
CCodeIdentifier ("user_data"));
1416 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_has_path"));
1417 ccheck
.add_argument (new
CCodeIdentifier ("message"));
1418 ccheck
.add_argument (path
);
1420 var object_filter_block
= new
CCodeBlock ();
1421 filter_block
.add_statement (new
CCodeIfStatement (ccheck
, object_filter_block
));
1423 handle_signals (iface
, object_filter_block
);
1425 filter_block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED")));
1427 source_declarations
.add_type_member_declaration (proxy_filter
.copy ());
1428 proxy_filter
.block
= filter_block
;
1429 source_type_member_definition
.append (proxy_filter
);
1432 string generate_dbus_signal_handler (Signal sig
, ObjectTypeSymbol sym
) {
1433 string wrapper_name
= "_dbus_handle_%s_%s".printf (sym
.get_lower_case_cname (), sig
.get_cname ());
1437 CCodeDeclaration cdecl
;
1439 var function
= new
CCodeFunction (wrapper_name
, "void");
1440 function
.modifiers
= CCodeModifiers
.STATIC
;
1442 function
.add_parameter (new
CCodeFormalParameter ("self", sym
.get_cname () + "*"));
1443 function
.add_parameter (new
CCodeFormalParameter ("connection", "DBusConnection*"));
1444 function
.add_parameter (new
CCodeFormalParameter ("message", "DBusMessage*"));
1446 var block
= new
CCodeBlock ();
1447 var prefragment
= new
CCodeFragment ();
1448 var postfragment
= new
CCodeFragment ();
1450 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
1451 cdecl
.add_declarator (new
CCodeVariableDeclarator ("iter"));
1452 block
.add_statement (cdecl
);
1454 block
.add_statement (prefragment
);
1456 var message_signature
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_get_signature"));
1457 message_signature
.add_argument (new
CCodeIdentifier ("message"));
1458 var signature_check
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
1459 signature_check
.add_argument (message_signature
);
1460 var signature_error_block
= new
CCodeBlock ();
1461 signature_error_block
.add_statement (new
CCodeReturnStatement ());
1462 prefragment
.append (new
CCodeIfStatement (signature_check
, signature_error_block
));
1464 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init"));
1465 iter_call
.add_argument (new
CCodeIdentifier ("message"));
1466 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("iter")));
1467 prefragment
.append (new
CCodeExpressionStatement (iter_call
));
1469 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_signal_emit_by_name"));
1470 ccall
.add_argument (new
CCodeIdentifier ("self"));
1471 ccall
.add_argument (sig
.get_canonical_cconstant ());
1473 // expected type signature for input parameters
1474 string type_signature
= "";
1476 foreach (FormalParameter param
in sig
.get_parameters ()) {
1477 var owned_type
= param
.parameter_type
.copy ();
1478 owned_type
.value_owned
= true;
1480 cdecl
= new
CCodeDeclaration (owned_type
.get_cname ());
1481 cdecl
.add_declarator (new CCodeVariableDeclarator
.zero (param
.name
, default_value_for_type (param
.parameter_type
, true)));
1482 prefragment
.append (cdecl
);
1484 if (get_type_signature (param
.parameter_type
) == null) {
1485 Report
.error (param
.parameter_type
.source_reference
, "D-Bus serialization of type `%s' is not supported".printf (param
.parameter_type
.to_string ()));
1489 var st
= param
.parameter_type
.data_type as Struct
;
1490 if (st
!= null && !st
.is_simple_type ()) {
1491 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier (param
.name
)));
1493 ccall
.add_argument (new
CCodeIdentifier (param
.name
));
1496 if (param
.parameter_type is ArrayType
) {
1497 var array_type
= (ArrayType
) param
.parameter_type
;
1499 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1500 string length_cname
= get_array_length_cname (param
.name
, dim
);
1502 cdecl
= new
CCodeDeclaration ("int");
1503 cdecl
.add_declarator (new
CCodeVariableDeclarator (length_cname
, new
CCodeConstant ("0")));
1504 prefragment
.append (cdecl
);
1505 ccall
.add_argument (new
CCodeIdentifier (length_cname
));
1509 type_signature
+= get_type_signature (param
.parameter_type
);
1511 var target
= new
CCodeIdentifier (param
.name
);
1512 var expr
= read_expression (prefragment
, param
.parameter_type
, new
CCodeIdentifier ("iter"), target
);
1513 prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
1515 if (requires_destroy (owned_type
)) {
1516 // keep local alive (symbol_reference is weak)
1517 var local
= new
LocalVariable (owned_type
, param
.name
);
1518 var ma
= new MemberAccess
.simple (param
.name
);
1519 ma
.symbol_reference
= local
;
1520 var stmt
= new
CCodeExpressionStatement (get_unref_expression (new
CCodeIdentifier (param
.name
), owned_type
, ma
));
1521 postfragment
.append (stmt
);
1525 signature_check
.add_argument (new
CCodeConstant ("\"%s\"".printf (type_signature
)));
1527 block
.add_statement (new
CCodeExpressionStatement (ccall
));
1529 block
.add_statement (postfragment
);
1531 cdecl
= new
CCodeDeclaration ("DBusMessage*");
1532 cdecl
.add_declarator (new
CCodeVariableDeclarator ("reply"));
1533 block
.add_statement (cdecl
);
1535 source_declarations
.add_type_member_declaration (function
.copy ());
1537 function
.block
= block
;
1538 source_type_member_definition
.append (function
);
1540 return wrapper_name
;
1543 void handle_signal (string dbus_iface_name
, string dbus_signal_name
, string handler_name
, CCodeBlock block
, ref CCodeIfStatement clastif
) {
1544 var ccheck
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_is_signal"));
1545 ccheck
.add_argument (new
CCodeIdentifier ("message"));
1546 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
1547 ccheck
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_signal_name
)));
1549 var callblock
= new
CCodeBlock ();
1551 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier (handler_name
));
1552 ccall
.add_argument (new
CCodeIdentifier ("user_data"));
1553 ccall
.add_argument (new
CCodeIdentifier ("connection"));
1554 ccall
.add_argument (new
CCodeIdentifier ("message"));
1556 callblock
.add_statement (new
CCodeExpressionStatement (ccall
));
1558 var cif
= new
CCodeIfStatement (ccheck
, callblock
);
1559 if (clastif
== null) {
1560 block
.add_statement (cif
);
1562 clastif
.false_statement
= cif
;
1568 void handle_signals (Interface iface
, CCodeBlock block
) {
1569 string dbus_iface_name
= get_dbus_name (iface
);
1571 CCodeIfStatement clastif
= null;
1572 foreach (Signal sig
in iface
.get_signals ()) {
1573 if (sig
.access
!= SymbolAccessibility
.PUBLIC
) {
1577 handle_signal (dbus_iface_name
, get_dbus_name_for_member (sig
), generate_dbus_signal_handler (sig
, iface
), block
, ref clastif
);
1581 void generate_marshalling (Method m
, string dbus_iface_name
, CCodeFragment prefragment
, CCodeFragment postfragment
) {
1582 CCodeDeclaration cdecl
;
1584 var destination
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_get_bus_name"));
1585 destination
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "DBusGProxy*"));
1586 var path
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_get_path"));
1587 path
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "DBusGProxy*"));
1589 var msgcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_new_method_call"));
1590 msgcall
.add_argument (destination
);
1591 msgcall
.add_argument (path
);
1592 msgcall
.add_argument (new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
1593 msgcall
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m
))));
1594 prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_message"), msgcall
)));
1596 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init_append"));
1597 iter_call
.add_argument (new
CCodeIdentifier ("_message"));
1598 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_iter")));
1599 prefragment
.append (new
CCodeExpressionStatement (iter_call
));
1601 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init"));
1602 iter_call
.add_argument (new
CCodeIdentifier ("_reply"));
1603 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_iter")));
1604 postfragment
.append (new
CCodeExpressionStatement (iter_call
));
1606 foreach (FormalParameter param
in m
.get_parameters ()) {
1607 if (param
.direction
== ParameterDirection
.IN
) {
1608 if (param
.parameter_type
.data_type
!= null
1609 && param
.parameter_type
.data_type
.get_full_name () == "DBus.BusName") {
1610 // ignore BusName sender parameters
1613 CCodeExpression expr
= new
CCodeIdentifier (param
.name
);
1614 if (param
.parameter_type
.is_real_struct_type ()) {
1615 expr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, expr
);
1617 write_expression (prefragment
, param
.parameter_type
, new
CCodeIdentifier ("_iter"), expr
);
1619 cdecl
= new
CCodeDeclaration (param
.parameter_type
.get_cname ());
1620 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_" + param
.name
));
1621 postfragment
.append (cdecl
);
1623 var array_type
= param
.parameter_type as ArrayType
;
1625 if (array_type
!= null) {
1626 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1627 cdecl
= new
CCodeDeclaration ("int");
1628 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_%s_length%d".printf (param
.name
, dim
), new
CCodeConstant ("0")));
1629 postfragment
.append (cdecl
);
1633 var target
= new
CCodeIdentifier ("_" + param
.name
);
1634 var expr
= read_expression (postfragment
, param
.parameter_type
, new
CCodeIdentifier ("_iter"), target
);
1635 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
1637 // TODO check that parameter is not NULL (out parameters are optional)
1638 // free value if parameter is NULL
1639 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier (param
.name
)), target
)));
1642 if (array_type
!= null) {
1643 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1644 // TODO check that parameter is not NULL (out parameters are optional)
1645 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("%s_length%d".printf (param
.name
, dim
))), new
CCodeIdentifier ("_%s_length%d".printf (param
.name
, dim
)))));
1651 if (!(m
.return_type is VoidType
)) {
1652 if (m
.return_type
.is_real_non_null_struct_type ()) {
1653 var target
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result"));
1654 var expr
= read_expression (postfragment
, m
.return_type
, new
CCodeIdentifier ("_iter"), target
);
1655 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
1657 cdecl
= new
CCodeDeclaration (m
.return_type
.get_cname ());
1658 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_result"));
1659 postfragment
.append (cdecl
);
1661 var array_type
= m
.return_type as ArrayType
;
1663 if (array_type
!= null) {
1664 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1665 cdecl
= new
CCodeDeclaration ("int");
1666 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_result_length%d".printf (dim
), new
CCodeConstant ("0")));
1667 postfragment
.append (cdecl
);
1671 var target
= new
CCodeIdentifier ("_result");
1672 var expr
= read_expression (postfragment
, m
.return_type
, new
CCodeIdentifier ("_iter"), target
);
1673 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
1675 if (array_type
!= null) {
1676 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
1677 // TODO check that parameter is not NULL (out parameters are optional)
1678 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result_length%d".printf (dim
))), new
CCodeIdentifier ("_result_length%d".printf (dim
)))));
1685 void check_error_reply (Method m
, CCodeBlock block
) {
1686 var error_types
= m
.get_error_types ();
1687 if (!has_dbus_error (error_types
)) {
1688 Report
.error (m
.source_reference
, "D-Bus methods must throw DBus.Error");
1692 var dbus_error
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_dbus_error"));
1694 var error_block
= new
CCodeBlock ();
1696 var cdecl
= new
CCodeDeclaration ("GQuark");
1697 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_edomain"));
1698 error_block
.add_statement (cdecl
);
1700 cdecl
= new
CCodeDeclaration ("gint");
1701 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_ecode"));
1702 error_block
.add_statement (cdecl
);
1704 generate_client_error_cases (error_block
, error_types
, new
CCodeMemberAccess (new
CCodeIdentifier ("_dbus_error"), "name"), new
CCodeIdentifier ("_edomain"), new
CCodeIdentifier ("_ecode"));
1706 var g_set_error
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_set_error"));
1707 g_set_error
.add_argument (new
CCodeIdentifier ("error"));
1708 g_set_error
.add_argument (new
CCodeIdentifier ("_edomain"));
1709 g_set_error
.add_argument (new
CCodeIdentifier ("_ecode"));
1710 g_set_error
.add_argument (new
CCodeConstant ("\"%s\""));
1711 g_set_error
.add_argument (new
CCodeMemberAccess (new
CCodeIdentifier ("_dbus_error"), "message"));
1712 error_block
.add_statement (new
CCodeExpressionStatement (g_set_error
));
1714 var dbus_error_free
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_error_free"));
1715 dbus_error_free
.add_argument (dbus_error
);
1716 error_block
.add_statement (new
CCodeExpressionStatement (dbus_error_free
));
1718 if (m
.return_type is VoidType
|| m
.return_type
.is_real_non_null_struct_type ()) {
1719 error_block
.add_statement (new
CCodeReturnStatement ());
1721 error_block
.add_statement (new
CCodeReturnStatement (default_value_for_type (m
.return_type
, false)));
1724 var dbus_error_is_set
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_error_is_set"));
1725 dbus_error_is_set
.add_argument (dbus_error
);
1726 block
.add_statement (new
CCodeIfStatement (dbus_error_is_set
, error_block
));
1729 string generate_dbus_proxy_method (Interface main_iface
, Interface iface
, Method m
) {
1730 string proxy_name
= "%sdbus_proxy_%s".printf (main_iface
.get_lower_case_cprefix (), m
.name
);
1732 string dbus_iface_name
= get_dbus_name (iface
);
1734 CCodeDeclaration cdecl
;
1736 var function
= new
CCodeFunction (proxy_name
);
1737 function
.modifiers
= CCodeModifiers
.STATIC
;
1739 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
1741 generate_cparameters (m
, source_declarations
, cparam_map
, function
);
1743 var block
= new
CCodeBlock ();
1744 var prefragment
= new
CCodeFragment ();
1745 var postfragment
= new
CCodeFragment ();
1747 // throw error and return if proxy is disposed
1748 var dispose_return_block
= new
CCodeBlock ();
1749 if (m
.get_error_types ().size
> 0) {
1750 var set_error_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_set_error"));
1751 set_error_call
.add_argument (new
CCodeIdentifier ("error"));
1752 set_error_call
.add_argument (new
CCodeIdentifier ("DBUS_GERROR"));
1753 set_error_call
.add_argument (new
CCodeIdentifier ("DBUS_GERROR_DISCONNECTED"));
1754 set_error_call
.add_argument (new
CCodeConstant ("\"%s\""));
1755 set_error_call
.add_argument (new
CCodeConstant ("\"Connection is closed\""));
1756 dispose_return_block
.add_statement (new
CCodeExpressionStatement (set_error_call
));
1758 if (m
.return_type is VoidType
|| m
.return_type
.is_real_non_null_struct_type ()) {
1759 dispose_return_block
.add_statement (new
CCodeReturnStatement ());
1761 dispose_return_block
.add_statement (new
CCodeReturnStatement (default_value_for_type (m
.return_type
, false)));
1763 block
.add_statement (new
CCodeIfStatement (new CCodeMemberAccess
.pointer (new
CCodeCastExpression (new
CCodeIdentifier ("self"), iface
.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block
));
1765 cdecl
= new
CCodeDeclaration ("DBusError");
1766 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_dbus_error"));
1767 block
.add_statement (cdecl
);
1769 var dbus_error
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_dbus_error"));
1771 cdecl
= new
CCodeDeclaration ("DBusGConnection");
1772 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_connection"));
1773 block
.add_statement (cdecl
);
1775 cdecl
= new
CCodeDeclaration ("DBusMessage");
1776 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_message"));
1777 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_reply"));
1778 block
.add_statement (cdecl
);
1780 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
1781 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_iter"));
1782 block
.add_statement (cdecl
);
1784 block
.add_statement (prefragment
);
1786 generate_marshalling (m
, dbus_iface_name
, prefragment
, postfragment
);
1788 var gconnection
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get"));
1789 gconnection
.add_argument (new
CCodeIdentifier ("self"));
1790 gconnection
.add_argument (new
CCodeConstant ("\"connection\""));
1791 gconnection
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_connection")));
1792 gconnection
.add_argument (new
CCodeConstant ("NULL"));
1793 block
.add_statement (new
CCodeExpressionStatement (gconnection
));
1795 var dbus_error_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_error_init"));
1796 dbus_error_init
.add_argument (dbus_error
);
1797 block
.add_statement (new
CCodeExpressionStatement (dbus_error_init
));
1799 var connection
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_get_connection"));
1800 connection
.add_argument (new
CCodeIdentifier ("_connection"));
1802 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
1803 ccall
.add_argument (connection
);
1804 ccall
.add_argument (new
CCodeIdentifier ("_message"));
1805 ccall
.add_argument (new
CCodeConstant ("-1"));
1806 ccall
.add_argument (dbus_error
);
1807 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_reply"), ccall
)));
1809 var conn_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_unref"));
1810 conn_unref
.add_argument (new
CCodeIdentifier ("_connection"));
1811 block
.add_statement (new
CCodeExpressionStatement (conn_unref
));
1813 var message_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
1814 message_unref
.add_argument (new
CCodeIdentifier ("_message"));
1815 block
.add_statement (new
CCodeExpressionStatement (message_unref
));
1817 check_error_reply (m
, block
);
1818 check_reply_signature (m
, block
);
1820 block
.add_statement (postfragment
);
1822 var reply_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
1823 reply_unref
.add_argument (new
CCodeIdentifier ("_reply"));
1824 block
.add_statement (new
CCodeExpressionStatement (reply_unref
));
1826 if (!(m
.return_type is VoidType
|| m
.return_type
.is_real_non_null_struct_type ())) {
1827 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("_result")));
1830 source_declarations
.add_type_member_declaration (function
.copy ());
1831 function
.block
= block
;
1832 source_type_member_definition
.append (function
);
1837 void generate_client_error_cases (CCodeBlock error_block
, List
<DataType
> error_types
, CCodeExpression dbus_error_name
, CCodeExpression result_edomain
, CCodeExpression result_ecode
) {
1838 CCodeStatement if_else_if
= null;
1839 CCodeIfStatement last_statement
= null;
1841 foreach (DataType error_type
in error_types
) {
1842 var edomain
= ((ErrorType
) error_type
).error_domain
;
1844 var edomain_dbus_name
= get_dbus_name (edomain
);
1845 if (edomain_dbus_name
== null) {
1846 Report
.error (edomain
.source_reference
, "Errordomain must have a DBus.name annotation to be serialized over DBus");
1849 var true_block
= new
CCodeBlock ();
1850 true_block
.suppress_newline
= true;
1852 string temp_name
= "_tmp%d_".printf (next_temp_var_id
++);
1854 var cdecl
= new
CCodeDeclaration ("const char*");
1855 cdecl
.add_declarator (new
CCodeVariableDeclarator (temp_name
));
1856 true_block
.add_statement (cdecl
);
1858 true_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (result_edomain
, new
CCodeIdentifier (edomain
.get_upper_case_cname ()))));
1860 true_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier (temp_name
), new
CCodeBinaryExpression (CCodeBinaryOperator
.PLUS
, dbus_error_name
, new
CCodeConstant ("%ld".printf (edomain_dbus_name
.length
+ 1))))));
1862 CCodeStatement inner_if_else_if
= null;
1863 CCodeIfStatement inner_last_statement
= null;
1864 foreach (ErrorCode ecode
in edomain
.get_codes ()) {
1865 var inner_true_block
= new
CCodeBlock ();
1866 inner_true_block
.suppress_newline
= true;
1867 inner_true_block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (result_ecode
, new
CCodeIdentifier (ecode
.get_cname ()))));
1869 var ecode_dbus_name
= get_dbus_name (ecode
);
1870 if (ecode_dbus_name
== null) {
1871 ecode_dbus_name
= Symbol
.lower_case_to_camel_case (ecode
.name
.down ());
1874 var string_comparison
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
1875 string_comparison
.add_argument (new
CCodeIdentifier (temp_name
));
1876 string_comparison
.add_argument (new
CCodeConstant ("\"%s\"".printf (ecode_dbus_name
)));
1877 var stmt
= new
CCodeIfStatement (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, string_comparison
, new
CCodeConstant ("0")), inner_true_block
);
1879 if (inner_last_statement
!= null) {
1880 inner_last_statement
.false_statement
= stmt
;
1882 inner_if_else_if
= stmt
;
1884 inner_last_statement
= stmt
;
1886 true_block
.add_statement (inner_if_else_if
);
1888 var string_comparison
= new
CCodeFunctionCall (new
CCodeIdentifier ("strstr"));
1889 string_comparison
.add_argument (dbus_error_name
);
1890 string_comparison
.add_argument (new
CCodeConstant ("\"%s\"".printf (edomain_dbus_name
)));
1891 var stmt
= new
CCodeIfStatement (new
CCodeBinaryExpression (CCodeBinaryOperator
.EQUALITY
, string_comparison
, dbus_error_name
), true_block
);
1893 if (last_statement
!= null) {
1894 last_statement
.false_statement
= stmt
;
1898 last_statement
= stmt
;
1900 error_block
.add_statement (if_else_if
);
1903 string generate_async_dbus_proxy_method (Interface main_iface
, Interface iface
, Method m
) {
1904 string proxy_name
= "%sdbus_proxy_%s_async".printf (main_iface
.get_lower_case_cprefix (), m
.name
);
1906 string dbus_iface_name
= get_dbus_name (iface
);
1908 CCodeDeclaration cdecl
;
1911 // generate data struct
1913 string dataname
= "%sDBusProxy%sData".printf (iface
.get_cname (), Symbol
.lower_case_to_camel_case (m
.name
));
1914 var datastruct
= new
CCodeStruct ("_" + dataname
);
1916 datastruct
.add_field ("GAsyncReadyCallback", "_callback_");
1917 datastruct
.add_field ("gpointer", "_user_data_");
1918 datastruct
.add_field ("DBusPendingCall*", "pending");
1920 source_declarations
.add_type_definition (datastruct
);
1921 source_declarations
.add_type_declaration (new
CCodeTypeDefinition ("struct _" + dataname
, new
CCodeVariableDeclarator (dataname
)));
1924 // generate async function
1926 var function
= new
CCodeFunction (proxy_name
, "void");
1927 function
.modifiers
= CCodeModifiers
.STATIC
;
1929 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
1931 cparam_map
.set (get_param_pos (-1), new
CCodeFormalParameter ("_callback_", "GAsyncReadyCallback"));
1932 cparam_map
.set (get_param_pos (-0.9), new
CCodeFormalParameter ("_user_data_", "gpointer"));
1934 generate_cparameters (m
, source_declarations
, cparam_map
, function
, null, null, null, 1);
1936 var block
= new
CCodeBlock ();
1937 var prefragment
= new
CCodeFragment ();
1938 var postfragment
= new
CCodeFragment ();
1940 cdecl
= new
CCodeDeclaration ("DBusGConnection");
1941 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_connection"));
1942 block
.add_statement (cdecl
);
1944 cdecl
= new
CCodeDeclaration ("DBusMessage");
1945 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_message"));
1946 block
.add_statement (cdecl
);
1948 cdecl
= new
CCodeDeclaration ("DBusPendingCall");
1949 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_pending"));
1950 block
.add_statement (cdecl
);
1952 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
1953 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_iter"));
1954 block
.add_statement (cdecl
);
1956 block
.add_statement (prefragment
);
1958 generate_marshalling (m
, dbus_iface_name
, prefragment
, postfragment
);
1960 var gconnection
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get"));
1961 gconnection
.add_argument (new
CCodeIdentifier ("self"));
1962 gconnection
.add_argument (new
CCodeConstant ("\"connection\""));
1963 gconnection
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_connection")));
1964 gconnection
.add_argument (new
CCodeConstant ("NULL"));
1965 block
.add_statement (new
CCodeExpressionStatement (gconnection
));
1967 var connection
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_get_connection"));
1968 connection
.add_argument (new
CCodeIdentifier ("_connection"));
1970 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_send_with_reply"));
1971 ccall
.add_argument (connection
);
1972 ccall
.add_argument (new
CCodeIdentifier ("_message"));
1973 ccall
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_pending")));
1974 ccall
.add_argument (new
CCodeConstant ("-1"));
1975 block
.add_statement (new
CCodeExpressionStatement (ccall
));
1977 var conn_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_unref"));
1978 conn_unref
.add_argument (new
CCodeIdentifier ("_connection"));
1979 block
.add_statement (new
CCodeExpressionStatement (conn_unref
));
1981 var message_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
1982 message_unref
.add_argument (new
CCodeIdentifier ("_message"));
1983 block
.add_statement (new
CCodeExpressionStatement (message_unref
));
1985 var dataalloc
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_new0"));
1986 dataalloc
.add_argument (new
CCodeIdentifier (dataname
));
1988 var datadecl
= new
CCodeDeclaration (dataname
+ "*");
1989 datadecl
.add_declarator (new
CCodeVariableDeclarator ("_data_"));
1990 block
.add_statement (datadecl
);
1991 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_data_"), dataalloc
)));
1993 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("_data_"), "_callback_"), new
CCodeIdentifier ("_callback_"))));
1994 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("_data_"), "_user_data_"), new
CCodeIdentifier ("_user_data_"))));
1995 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("_data_"), "pending"), new
CCodeIdentifier ("_pending"))));
1997 var pending
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_pending_call_set_notify"));
1998 pending
.add_argument (new
CCodeIdentifier ("_pending"));
1999 pending
.add_argument (new
CCodeIdentifier ("%sdbus_proxy_%s_ready".printf (iface
.get_lower_case_cprefix (), m
.name
)));
2000 pending
.add_argument (new
CCodeIdentifier ("_data_"));
2001 pending
.add_argument (new
CCodeConstant ("NULL"));
2002 block
.add_statement (new
CCodeExpressionStatement (pending
));
2004 source_declarations
.add_type_member_declaration (function
.copy ());
2005 function
.block
= block
;
2006 source_type_member_definition
.append (function
);
2009 // generate ready function
2011 function
= new
CCodeFunction ("%sdbus_proxy_%s_ready".printf (iface
.get_lower_case_cprefix (), m
.name
), "void");
2012 function
.modifiers
= CCodeModifiers
.STATIC
;
2014 function
.add_parameter (new
CCodeFormalParameter ("pending", "DBusPendingCall*"));
2015 function
.add_parameter (new
CCodeFormalParameter ("user_data", "void*"));
2017 block
= new
CCodeBlock ();
2019 datadecl
= new
CCodeDeclaration (dataname
+ "*");
2020 datadecl
.add_declarator (new
CCodeVariableDeclarator ("_data_"));
2021 block
.add_statement (datadecl
);
2022 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_data_"), new
CCodeIdentifier ("user_data"))));
2024 // complete async call by invoking callback
2025 var obj_decl
= new
CCodeDeclaration ("GObject *");
2026 obj_decl
.add_declarator (new
CCodeVariableDeclarator ("_obj_"));
2027 block
.add_statement (obj_decl
);
2029 var object_creation
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_newv"));
2030 object_creation
.add_argument (new
CCodeConstant ("G_TYPE_OBJECT"));
2031 object_creation
.add_argument (new
CCodeConstant ("0"));
2032 object_creation
.add_argument (new
CCodeConstant ("NULL"));
2033 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_obj_"), object_creation
)));
2035 var async_result_decl
= new
CCodeDeclaration ("GSimpleAsyncResult *");
2036 async_result_decl
.add_declarator (new
CCodeVariableDeclarator ("_res_"));
2037 block
.add_statement (async_result_decl
);
2039 var async_result_creation
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_simple_async_result_new"));
2040 async_result_creation
.add_argument (new
CCodeIdentifier ("_obj_"));
2041 async_result_creation
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("_data_"), "_callback_"));
2042 async_result_creation
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("_data_"), "_user_data_"));
2043 async_result_creation
.add_argument (new
CCodeIdentifier ("_data_"));
2044 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_res_"), async_result_creation
)));
2046 var completecall
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_simple_async_result_complete"));
2047 completecall
.add_argument (new
CCodeIdentifier ("_res_"));
2048 block
.add_statement (new
CCodeExpressionStatement (completecall
));
2050 var obj_free
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
2051 obj_free
.add_argument (new
CCodeIdentifier ("_obj_"));
2052 block
.add_statement (new
CCodeExpressionStatement (obj_free
));
2054 var async_result_free
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_unref"));
2055 async_result_free
.add_argument (new
CCodeIdentifier ("_res_"));
2056 block
.add_statement (new
CCodeExpressionStatement (async_result_free
));
2058 var datafree
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_slice_free"));
2059 datafree
.add_argument (new
CCodeIdentifier (dataname
));
2060 datafree
.add_argument (new
CCodeIdentifier ("_data_"));
2061 block
.add_statement (new
CCodeExpressionStatement (datafree
));
2063 var pendingfree
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_pending_call_unref"));
2064 pendingfree
.add_argument (new
CCodeIdentifier ("pending"));
2065 block
.add_statement (new
CCodeExpressionStatement (pendingfree
));
2067 source_declarations
.add_type_member_declaration (function
.copy ());
2068 function
.block
= block
;
2069 source_type_member_definition
.append (function
);
2075 CCodeConstant
get_reply_signature (Method m
) {
2076 // expected type signature for output parameters
2077 string type_signature
= "";
2079 foreach (FormalParameter param
in m
.get_parameters ()) {
2080 if (param
.direction
== ParameterDirection
.OUT
) {
2081 type_signature
+= get_type_signature (param
.parameter_type
);
2085 if (!(m
.return_type is VoidType
)) {
2086 type_signature
+= get_type_signature (m
.return_type
);
2089 return (new
CCodeConstant ("\"%s\"".printf (type_signature
)));
2092 void check_reply_signature (Method m
, CCodeBlock block
) {
2093 var reply_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
2094 reply_unref
.add_argument (new
CCodeIdentifier ("_reply"));
2096 var message_signature
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_get_signature"));
2097 message_signature
.add_argument (new
CCodeIdentifier ("_reply"));
2099 var signature_check
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
2100 signature_check
.add_argument (message_signature
);
2101 signature_check
.add_argument (get_reply_signature (m
));
2103 var signature_error_block
= new
CCodeBlock ();
2104 var set_error_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_set_error"));
2105 set_error_call
.add_argument (new
CCodeIdentifier ("error"));
2106 set_error_call
.add_argument (new
CCodeIdentifier ("DBUS_GERROR"));
2107 set_error_call
.add_argument (new
CCodeIdentifier ("DBUS_GERROR_INVALID_SIGNATURE"));
2108 set_error_call
.add_argument (new
CCodeConstant ("\"Invalid signature, expected \\\"%s\\\", got \\\"%s\\\"\""));
2109 set_error_call
.add_argument (get_reply_signature (m
));
2110 set_error_call
.add_argument (message_signature
);
2111 signature_error_block
.add_statement (new
CCodeExpressionStatement (set_error_call
));
2112 signature_error_block
.add_statement (new
CCodeExpressionStatement (reply_unref
));
2113 signature_error_block
.add_statement (new
CCodeReturnStatement (default_value_for_type (m
.return_type
, false)));
2115 block
.add_statement (new
CCodeIfStatement (signature_check
, signature_error_block
));
2118 string generate_finish_dbus_proxy_method (Interface main_iface
, Interface iface
, Method m
) {
2119 string proxy_name
= "%sdbus_proxy_%s_finish".printf (main_iface
.get_lower_case_cprefix (), m
.name
);
2121 string dbus_iface_name
= get_dbus_name (iface
);
2123 CCodeDeclaration cdecl
;
2125 var function
= new
CCodeFunction (proxy_name
);
2126 function
.modifiers
= CCodeModifiers
.STATIC
;
2128 var cparam_map
= new HashMap
<int,CCodeFormalParameter
> (direct_hash
, direct_equal
);
2130 cparam_map
.set (get_param_pos (0.1), new
CCodeFormalParameter ("_res_", "GAsyncResult*"));
2132 generate_cparameters (m
, source_declarations
, cparam_map
, function
, null, null, null, 2);
2134 var block
= new
CCodeBlock ();
2135 var prefragment
= new
CCodeFragment ();
2136 var postfragment
= new
CCodeFragment ();
2138 string dataname
= "%sDBusProxy%sData".printf (iface
.get_cname (), Symbol
.lower_case_to_camel_case (m
.name
));
2139 cdecl
= new
CCodeDeclaration (dataname
+ "*");
2140 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_data_"));
2141 block
.add_statement (cdecl
);
2143 cdecl
= new
CCodeDeclaration ("DBusError");
2144 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_dbus_error"));
2145 block
.add_statement (cdecl
);
2147 var dbus_error
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_dbus_error"));
2149 cdecl
= new
CCodeDeclaration ("DBusMessage");
2150 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_reply"));
2151 block
.add_statement (cdecl
);
2153 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
2154 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_iter"));
2155 block
.add_statement (cdecl
);
2157 var get_source_tag
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_simple_async_result_get_source_tag"));
2158 get_source_tag
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("_res_"), "GSimpleAsyncResult *"));
2159 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_data_"), get_source_tag
)));
2161 var dbus_error_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_error_init"));
2162 dbus_error_init
.add_argument (dbus_error
);
2163 block
.add_statement (new
CCodeExpressionStatement (dbus_error_init
));
2165 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_pending_call_steal_reply"));
2166 ccall
.add_argument (new CCodeMemberAccess
.pointer (new
CCodeIdentifier ("_data_"), "pending"));
2167 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_reply"), ccall
)));
2169 var set_error_from_message
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_set_error_from_message"));
2170 set_error_from_message
.add_argument (dbus_error
);
2171 set_error_from_message
.add_argument (new
CCodeIdentifier ("_reply"));
2172 block
.add_statement (new
CCodeExpressionStatement (set_error_from_message
));
2174 check_error_reply (m
, block
);
2175 check_reply_signature (m
, block
);
2177 generate_marshalling (m
, dbus_iface_name
, prefragment
, postfragment
);
2179 block
.add_statement (postfragment
);
2181 var reply_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
2182 reply_unref
.add_argument (new
CCodeIdentifier ("_reply"));
2183 block
.add_statement (new
CCodeExpressionStatement (reply_unref
));
2185 if (!(m
.return_type is VoidType
|| m
.return_type
.is_real_non_null_struct_type ())) {
2186 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("_result")));
2189 source_declarations
.add_type_member_declaration (function
.copy ());
2190 function
.block
= block
;
2191 source_type_member_definition
.append (function
);
2196 void check_property_error_reply (PropertyAccessor acc
, CCodeBlock block
) {
2197 var dbus_error
= new
CCodeIdentifier ("_dbus_error");
2198 var dbus_error_ptr
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, dbus_error
);
2200 var error_block
= new
CCodeBlock ();
2202 var ccritical
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_critical"));
2203 ccritical
.add_argument (new
CCodeConstant ("\"file %s: line %d: uncaught error: %s (%s)\""));
2204 ccritical
.add_argument (new
CCodeConstant ("__FILE__"));
2205 ccritical
.add_argument (new
CCodeConstant ("__LINE__"));
2206 ccritical
.add_argument (new
CCodeMemberAccess (dbus_error
, "message"));
2207 ccritical
.add_argument (new
CCodeMemberAccess (dbus_error
, "name"));
2209 error_block
.add_statement (new
CCodeExpressionStatement (ccritical
));
2211 var dbus_error_free
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_error_free"));
2212 dbus_error_free
.add_argument (dbus_error_ptr
);
2213 error_block
.add_statement (new
CCodeExpressionStatement (dbus_error_free
));
2215 if (acc
.readable
&& !acc
.value_type
.is_real_non_null_struct_type ()) {
2216 error_block
.add_statement (new
CCodeReturnStatement (default_value_for_type (acc
.value_type
, false)));
2218 error_block
.add_statement (new
CCodeReturnStatement ());
2221 var dbus_error_is_set
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_error_is_set"));
2222 dbus_error_is_set
.add_argument (dbus_error_ptr
);
2223 block
.add_statement (new
CCodeIfStatement (dbus_error_is_set
, error_block
));
2226 CCodeConstant
get_property_reply_signature (PropertyAccessor acc
) {
2228 return new
CCodeConstant ("\"v\"");
2230 return new
CCodeConstant ("\"\"");
2234 CCodeConstant
get_property_inner_signature (PropertyAccessor acc
) {
2235 return new
CCodeConstant ("\"%s\"".printf (get_type_signature (acc
.value_type
)));
2238 void check_property_reply_signature (PropertyAccessor acc
, CCodeBlock block
) {
2239 var reply_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
2240 reply_unref
.add_argument (new
CCodeIdentifier ("_reply"));
2242 var message_signature
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_get_signature"));
2243 message_signature
.add_argument (new
CCodeIdentifier ("_reply"));
2245 var signature_check
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
2246 signature_check
.add_argument (message_signature
);
2247 signature_check
.add_argument (get_property_reply_signature (acc
));
2249 var signature_error_block
= new
CCodeBlock ();
2251 var ccritical
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_critical"));
2252 ccritical
.add_argument (new
CCodeConstant ("\"file %s: line %d: Invalid signature, expected \\\"%s\\\", got \\\"%s\\\"\""));
2253 ccritical
.add_argument (new
CCodeConstant ("__FILE__"));
2254 ccritical
.add_argument (new
CCodeConstant ("__LINE__"));
2255 ccritical
.add_argument (get_property_reply_signature (acc
));
2256 ccritical
.add_argument (message_signature
);
2258 signature_error_block
.add_statement (new
CCodeExpressionStatement (ccritical
));
2259 signature_error_block
.add_statement (new
CCodeExpressionStatement (reply_unref
));
2261 if (acc
.readable
&& !acc
.value_type
.is_real_non_null_struct_type ()) {
2262 signature_error_block
.add_statement (new
CCodeReturnStatement (default_value_for_type (acc
.value_type
, false)));
2264 signature_error_block
.add_statement (new
CCodeReturnStatement ());
2267 block
.add_statement (new
CCodeIfStatement (signature_check
, signature_error_block
));
2270 void check_property_inner_signature (PropertyAccessor acc
, CCodeFragment fragment
) {
2271 var reply_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
2272 reply_unref
.add_argument (new
CCodeIdentifier ("_reply"));
2274 var iter_signature
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_get_signature"));
2275 iter_signature
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_subiter")));
2277 var signature_check
= new
CCodeFunctionCall (new
CCodeIdentifier ("strcmp"));
2278 signature_check
.add_argument (iter_signature
);
2279 signature_check
.add_argument (get_property_inner_signature (acc
));
2281 var signature_error_block
= new
CCodeBlock ();
2283 var ccritical
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_critical"));
2284 ccritical
.add_argument (new
CCodeConstant ("\"file %s: line %d: Invalid signature, expected \\\"%s\\\", got \\\"%s\\\"\""));
2285 ccritical
.add_argument (new
CCodeConstant ("__FILE__"));
2286 ccritical
.add_argument (new
CCodeConstant ("__LINE__"));
2287 ccritical
.add_argument (get_property_inner_signature (acc
));
2288 ccritical
.add_argument (iter_signature
);
2290 signature_error_block
.add_statement (new
CCodeExpressionStatement (ccritical
));
2291 signature_error_block
.add_statement (new
CCodeExpressionStatement (reply_unref
));
2293 if (!acc
.value_type
.is_real_non_null_struct_type ()) {
2294 signature_error_block
.add_statement (new
CCodeReturnStatement (default_value_for_type (acc
.value_type
, false)));
2296 signature_error_block
.add_statement (new
CCodeReturnStatement ());
2299 fragment
.append (new
CCodeIfStatement (signature_check
, signature_error_block
));
2302 string generate_dbus_proxy_property_get (Interface main_iface
, Interface iface
, Property prop
) {
2303 string proxy_name
= "%sdbus_proxy_get_%s".printf (main_iface
.get_lower_case_cprefix (), prop
.name
);
2305 string dbus_iface_name
= get_dbus_name (iface
);
2307 var owned_type
= prop
.get_accessor
.value_type
.copy ();
2308 owned_type
.value_owned
= true;
2309 if (owned_type
.is_disposable () && !prop
.get_accessor
.value_type
.value_owned
) {
2310 Report
.error (prop
.get_accessor
.value_type
.source_reference
, "Properties used in D-Bus clients require owned get accessor");
2313 var array_type
= prop
.get_accessor
.value_type as ArrayType
;
2315 CCodeDeclaration cdecl
;
2317 var function
= new
CCodeFunction (proxy_name
);
2318 function
.modifiers
= CCodeModifiers
.STATIC
;
2320 function
.add_parameter (new
CCodeFormalParameter ("self", "%s*".printf (iface
.get_cname ())));
2322 if (prop
.property_type
.is_real_non_null_struct_type ()) {
2323 function
.add_parameter (new
CCodeFormalParameter ("result", "%s*".printf (prop
.get_accessor
.value_type
.get_cname ())));
2325 if (array_type
!= null) {
2326 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
2327 function
.add_parameter (new
CCodeFormalParameter ("result_length%d".printf (dim
), "int*"));
2331 function
.return_type
= prop
.get_accessor
.value_type
.get_cname ();
2334 var block
= new
CCodeBlock ();
2335 var prefragment
= new
CCodeFragment ();
2336 var postfragment
= new
CCodeFragment ();
2338 var dispose_return_block
= new
CCodeBlock ();
2339 if (prop
.property_type
.is_real_non_null_struct_type ()) {
2340 dispose_return_block
.add_statement (new
CCodeReturnStatement ());
2342 dispose_return_block
.add_statement (new
CCodeReturnStatement (default_value_for_type (prop
.property_type
, false)));
2344 block
.add_statement (new
CCodeIfStatement (new CCodeMemberAccess
.pointer (new
CCodeCastExpression (new
CCodeIdentifier ("self"), iface
.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block
));
2346 cdecl
= new
CCodeDeclaration ("DBusError");
2347 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_dbus_error"));
2348 block
.add_statement (cdecl
);
2350 var dbus_error
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_dbus_error"));
2352 cdecl
= new
CCodeDeclaration ("DBusGConnection");
2353 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_connection"));
2354 block
.add_statement (cdecl
);
2356 cdecl
= new
CCodeDeclaration ("DBusMessage");
2357 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_message"));
2358 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_reply"));
2359 block
.add_statement (cdecl
);
2361 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
2362 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_iter"));
2363 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_subiter"));
2364 block
.add_statement (cdecl
);
2366 block
.add_statement (prefragment
);
2368 var destination
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_get_bus_name"));
2369 destination
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "DBusGProxy*"));
2370 var path
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_get_path"));
2371 path
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "DBusGProxy*"));
2373 var msgcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_new_method_call"));
2374 msgcall
.add_argument (destination
);
2375 msgcall
.add_argument (path
);
2376 msgcall
.add_argument (new
CCodeConstant ("\"org.freedesktop.DBus.Properties\""));
2377 msgcall
.add_argument (new
CCodeConstant ("\"Get\""));
2378 prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_message"), msgcall
)));
2380 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init_append"));
2381 iter_call
.add_argument (new
CCodeIdentifier ("_message"));
2382 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_iter")));
2383 prefragment
.append (new
CCodeExpressionStatement (iter_call
));
2385 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init"));
2386 iter_call
.add_argument (new
CCodeIdentifier ("_reply"));
2387 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_iter")));
2388 postfragment
.append (new
CCodeExpressionStatement (iter_call
));
2391 write_expression (prefragment
, string_type
, new
CCodeIdentifier ("_iter"), new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
2393 write_expression (prefragment
, string_type
, new
CCodeIdentifier ("_iter"), new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
2395 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_recurse"));
2396 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_iter")));
2397 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_subiter")));
2398 postfragment
.append (new
CCodeExpressionStatement (iter_call
));
2400 check_property_inner_signature (prop
.get_accessor
, postfragment
);
2402 if (prop
.property_type
.is_real_non_null_struct_type ()) {
2403 var target
= new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result"));
2404 var expr
= read_expression (postfragment
, prop
.get_accessor
.value_type
, new
CCodeIdentifier ("_subiter"), target
);
2405 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
2407 cdecl
= new
CCodeDeclaration (prop
.get_accessor
.value_type
.get_cname ());
2408 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_result"));
2409 postfragment
.append (cdecl
);
2411 if (array_type
!= null) {
2412 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
2413 cdecl
= new
CCodeDeclaration ("int");
2414 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_result_length%d".printf (dim
), new
CCodeConstant ("0")));
2415 postfragment
.append (cdecl
);
2419 var target
= new
CCodeIdentifier ("_result");
2420 var expr
= read_expression (postfragment
, prop
.get_accessor
.value_type
, new
CCodeIdentifier ("_subiter"), target
);
2421 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (target
, expr
)));
2423 if (array_type
!= null) {
2424 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
2425 // TODO check that parameter is not NULL (out parameters are optional)
2426 postfragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("result_length%d".printf (dim
))), new
CCodeIdentifier ("_result_length%d".printf (dim
)))));
2431 var gconnection
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get"));
2432 gconnection
.add_argument (new
CCodeIdentifier ("self"));
2433 gconnection
.add_argument (new
CCodeConstant ("\"connection\""));
2434 gconnection
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_connection")));
2435 gconnection
.add_argument (new
CCodeConstant ("NULL"));
2436 block
.add_statement (new
CCodeExpressionStatement (gconnection
));
2438 var dbus_error_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_error_init"));
2439 dbus_error_init
.add_argument (dbus_error
);
2440 block
.add_statement (new
CCodeExpressionStatement (dbus_error_init
));
2442 var connection
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_get_connection"));
2443 connection
.add_argument (new
CCodeIdentifier ("_connection"));
2445 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
2446 ccall
.add_argument (connection
);
2447 ccall
.add_argument (new
CCodeIdentifier ("_message"));
2448 ccall
.add_argument (new
CCodeConstant ("-1"));
2449 ccall
.add_argument (dbus_error
);
2450 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_reply"), ccall
)));
2452 var conn_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_unref"));
2453 conn_unref
.add_argument (new
CCodeIdentifier ("_connection"));
2454 block
.add_statement (new
CCodeExpressionStatement (conn_unref
));
2456 var message_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
2457 message_unref
.add_argument (new
CCodeIdentifier ("_message"));
2458 block
.add_statement (new
CCodeExpressionStatement (message_unref
));
2460 check_property_error_reply (prop
.get_accessor
, block
);
2461 check_property_reply_signature (prop
.get_accessor
, block
);
2463 block
.add_statement (postfragment
);
2465 var reply_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
2466 reply_unref
.add_argument (new
CCodeIdentifier ("_reply"));
2467 block
.add_statement (new
CCodeExpressionStatement (reply_unref
));
2469 if (prop
.property_type
.is_real_non_null_struct_type ()) {
2470 block
.add_statement (new
CCodeReturnStatement ());
2472 block
.add_statement (new
CCodeReturnStatement (new
CCodeIdentifier ("_result")));
2475 source_declarations
.add_type_member_declaration (function
.copy ());
2476 function
.block
= block
;
2477 source_type_member_definition
.append (function
);
2482 string generate_dbus_proxy_property_set (Interface main_iface
, Interface iface
, Property prop
) {
2483 string proxy_name
= "%sdbus_proxy_set_%s".printf (main_iface
.get_lower_case_cprefix (), prop
.name
);
2485 string dbus_iface_name
= get_dbus_name (iface
);
2487 var array_type
= prop
.set_accessor
.value_type as ArrayType
;
2489 CCodeDeclaration cdecl
;
2491 var function
= new
CCodeFunction (proxy_name
);
2492 function
.modifiers
= CCodeModifiers
.STATIC
;
2494 function
.add_parameter (new
CCodeFormalParameter ("self", "%s*".printf (iface
.get_cname ())));
2496 if (prop
.property_type
.is_real_non_null_struct_type ()) {
2497 function
.add_parameter (new
CCodeFormalParameter ("value", "%s*".printf (prop
.set_accessor
.value_type
.get_cname ())));
2499 function
.add_parameter (new
CCodeFormalParameter ("value", prop
.set_accessor
.value_type
.get_cname ()));
2501 if (array_type
!= null) {
2502 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
2503 function
.add_parameter (new
CCodeFormalParameter ("value_length%d".printf (dim
), "int"));
2508 var block
= new
CCodeBlock ();
2509 var prefragment
= new
CCodeFragment ();
2510 var postfragment
= new
CCodeFragment ();
2512 var dispose_return_block
= new
CCodeBlock ();
2513 dispose_return_block
.add_statement (new
CCodeReturnStatement ());
2514 block
.add_statement (new
CCodeIfStatement (new CCodeMemberAccess
.pointer (new
CCodeCastExpression (new
CCodeIdentifier ("self"), iface
.get_cname () + "DBusProxy*"), "disposed"), dispose_return_block
));
2516 cdecl
= new
CCodeDeclaration ("DBusError");
2517 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_dbus_error"));
2518 block
.add_statement (cdecl
);
2520 var dbus_error
= new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_dbus_error"));
2522 cdecl
= new
CCodeDeclaration ("DBusGConnection");
2523 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_connection"));
2524 block
.add_statement (cdecl
);
2526 cdecl
= new
CCodeDeclaration ("DBusMessage");
2527 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_message"));
2528 cdecl
.add_declarator (new
CCodeVariableDeclarator ("*_reply"));
2529 block
.add_statement (cdecl
);
2531 cdecl
= new
CCodeDeclaration ("DBusMessageIter");
2532 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_iter"));
2533 cdecl
.add_declarator (new
CCodeVariableDeclarator ("_subiter"));
2534 block
.add_statement (cdecl
);
2536 block
.add_statement (prefragment
);
2538 var destination
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_get_bus_name"));
2539 destination
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "DBusGProxy*"));
2540 var path
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_proxy_get_path"));
2541 path
.add_argument (new
CCodeCastExpression (new
CCodeIdentifier ("self"), "DBusGProxy*"));
2543 var msgcall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_new_method_call"));
2544 msgcall
.add_argument (destination
);
2545 msgcall
.add_argument (path
);
2546 msgcall
.add_argument (new
CCodeConstant ("\"org.freedesktop.DBus.Properties\""));
2547 msgcall
.add_argument (new
CCodeConstant ("\"Set\""));
2548 prefragment
.append (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_message"), msgcall
)));
2550 var iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init_append"));
2551 iter_call
.add_argument (new
CCodeIdentifier ("_message"));
2552 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_iter")));
2553 prefragment
.append (new
CCodeExpressionStatement (iter_call
));
2555 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_init"));
2556 iter_call
.add_argument (new
CCodeIdentifier ("_reply"));
2557 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_iter")));
2558 postfragment
.append (new
CCodeExpressionStatement (iter_call
));
2561 write_expression (prefragment
, string_type
, new
CCodeIdentifier ("_iter"), new
CCodeConstant ("\"%s\"".printf (dbus_iface_name
)));
2563 write_expression (prefragment
, string_type
, new
CCodeIdentifier ("_iter"), new
CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop
))));
2565 // property value (as variant)
2566 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_open_container"));
2567 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_iter")));
2568 iter_call
.add_argument (new
CCodeIdentifier ("DBUS_TYPE_VARIANT"));
2569 iter_call
.add_argument (new
CCodeConstant ("\"%s\"".printf (get_type_signature (prop
.property_type
))));
2570 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_subiter")));
2571 prefragment
.append (new
CCodeExpressionStatement (iter_call
));
2573 if (prop
.property_type
.is_real_non_null_struct_type ()) {
2574 write_expression (prefragment
, prop
.set_accessor
.value_type
, new
CCodeIdentifier ("_subiter"), new
CCodeUnaryExpression (CCodeUnaryOperator
.POINTER_INDIRECTION
, new
CCodeIdentifier ("value")));
2576 write_expression (prefragment
, prop
.set_accessor
.value_type
, new
CCodeIdentifier ("_subiter"), new
CCodeIdentifier ("value"));
2579 iter_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_iter_close_container"));
2580 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_iter")));
2581 iter_call
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_subiter")));
2582 prefragment
.append (new
CCodeExpressionStatement (iter_call
));
2584 var gconnection
= new
CCodeFunctionCall (new
CCodeIdentifier ("g_object_get"));
2585 gconnection
.add_argument (new
CCodeIdentifier ("self"));
2586 gconnection
.add_argument (new
CCodeConstant ("\"connection\""));
2587 gconnection
.add_argument (new
CCodeUnaryExpression (CCodeUnaryOperator
.ADDRESS_OF
, new
CCodeIdentifier ("_connection")));
2588 gconnection
.add_argument (new
CCodeConstant ("NULL"));
2589 block
.add_statement (new
CCodeExpressionStatement (gconnection
));
2591 var dbus_error_init
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_error_init"));
2592 dbus_error_init
.add_argument (dbus_error
);
2593 block
.add_statement (new
CCodeExpressionStatement (dbus_error_init
));
2595 var connection
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_get_connection"));
2596 connection
.add_argument (new
CCodeIdentifier ("_connection"));
2598 var ccall
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_connection_send_with_reply_and_block"));
2599 ccall
.add_argument (connection
);
2600 ccall
.add_argument (new
CCodeIdentifier ("_message"));
2601 ccall
.add_argument (new
CCodeConstant ("-1"));
2602 ccall
.add_argument (dbus_error
);
2603 block
.add_statement (new
CCodeExpressionStatement (new
CCodeAssignment (new
CCodeIdentifier ("_reply"), ccall
)));
2605 var conn_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_g_connection_unref"));
2606 conn_unref
.add_argument (new
CCodeIdentifier ("_connection"));
2607 block
.add_statement (new
CCodeExpressionStatement (conn_unref
));
2609 var message_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
2610 message_unref
.add_argument (new
CCodeIdentifier ("_message"));
2611 block
.add_statement (new
CCodeExpressionStatement (message_unref
));
2613 check_property_error_reply (prop
.set_accessor
, block
);
2614 check_property_reply_signature (prop
.set_accessor
, block
);
2616 block
.add_statement (postfragment
);
2618 var reply_unref
= new
CCodeFunctionCall (new
CCodeIdentifier ("dbus_message_unref"));
2619 reply_unref
.add_argument (new
CCodeIdentifier ("_reply"));
2620 block
.add_statement (new
CCodeExpressionStatement (reply_unref
));
2622 source_declarations
.add_type_member_declaration (function
.copy ());
2623 function
.block
= block
;
2624 source_type_member_definition
.append (function
);