From: Jürg Billeter Date: Sun, 14 Dec 2008 19:36:38 +0000 (+0000) Subject: Rewrite D-Bus server support to directly use libdbus without dbus-glib X-Git-Tag: VALA_0_5_3~47 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=73fcf58c7a360d8ab92233dc6068f59d772e6adc;p=thirdparty%2Fvala.git Rewrite D-Bus server support to directly use libdbus without dbus-glib 2008-12-14 Jürg Billeter * gobject/valaccodebasemodule.vala: * gobject/valadbusservermodule.vala: * gobject/valagsignalmodule.vala: * vapi/dbus-glib-1.vapi: Rewrite D-Bus server support to directly use libdbus without dbus-glib marshalling, fixes bug 560034 and bug 549980 Support BusName sender parameter in exported D-Bus methods svn path=/trunk/; revision=2147 --- diff --git a/ChangeLog b/ChangeLog index 67bb64f3f..43071c208 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2008-12-14 Jürg Billeter + + * gobject/valaccodebasemodule.vala: + * gobject/valadbusservermodule.vala: + * gobject/valagsignalmodule.vala: + * vapi/dbus-glib-1.vapi: + + Rewrite D-Bus server support to directly use libdbus without + dbus-glib marshalling, fixes bug 560034 and bug 549980 + + Support BusName sender parameter in exported D-Bus methods + 2008-12-14 Jürg Billeter * vapi/glib-2.0.vapi: diff --git a/gobject/valaccodebasemodule.vala b/gobject/valaccodebasemodule.vala index c17eb790a..fd41be5ec 100644 --- a/gobject/valaccodebasemodule.vala +++ b/gobject/valaccodebasemodule.vala @@ -395,6 +395,45 @@ public class Vala.CCodeBaseModule : CCodeModule { source_include_directives.append (new CCodeIncludeDirective ("dbus/dbus.h")); source_include_directives.append (new CCodeIncludeDirective ("dbus/dbus-glib.h")); } + if (dbus_glib_h_needed_in_header || dbus_glib_h_needed) { + var dbusvtable = new CCodeStruct ("_DBusObjectVTable"); + dbusvtable.add_field ("void", "(*register_object) (DBusConnection*, const char*, void*)"); + source_type_definition.append (dbusvtable); + + source_type_declaration.append (new CCodeTypeDefinition ("struct _DBusObjectVTable", new CCodeVariableDeclarator ("_DBusObjectVTable"))); + + var cfunc = new CCodeFunction ("_vala_dbus_register_object", "void"); + cfunc.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*")); + cfunc.add_parameter (new CCodeFormalParameter ("path", "const char*")); + cfunc.add_parameter (new CCodeFormalParameter ("object", "void*")); + + cfunc.modifiers |= CCodeModifiers.STATIC; + source_type_member_declaration.append (cfunc.copy ()); + + var block = new CCodeBlock (); + cfunc.block = block; + + var cdecl = new CCodeDeclaration ("const _DBusObjectVTable *"); + cdecl.add_declarator (new CCodeVariableDeclarator ("vtable")); + block.add_statement (cdecl); + + var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); + quark.add_argument (new CCodeConstant ("\"DBusObjectVTable\"")); + + var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata")); + get_qdata.add_argument (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE (object)")); + get_qdata.add_argument (quark); + + block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("vtable"), get_qdata))); + + var cregister = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier ("vtable"), "register_object")); + cregister.add_argument (new CCodeIdentifier ("connection")); + cregister.add_argument (new CCodeIdentifier ("path")); + cregister.add_argument (new CCodeIdentifier ("object")); + block.add_statement (new CCodeExpressionStatement (cregister)); + + source_type_member_definition.append (cfunc); + } CCodeComment comment = null; if (source_file.comment != null) { diff --git a/gobject/valadbusservermodule.vala b/gobject/valadbusservermodule.vala index 1c5b2265a..550e1d992 100644 --- a/gobject/valadbusservermodule.vala +++ b/gobject/valadbusservermodule.vala @@ -44,611 +44,1224 @@ public class Vala.DBusServerModule : DBusClientModule { return true; } - string dbus_result_name (CodeNode node) { - var dbus_attribute = node.get_attribute ("DBus"); + string dbus_result_name (Method m) { + var dbus_attribute = m.get_attribute ("DBus"); if (dbus_attribute != null && dbus_attribute.has_argument ("result")) { var result_name = dbus_attribute.get_string ("result"); - if (result_name != null && result_name != "") + if (result_name != null && result_name != "") { return result_name; + } } return "result"; } - public override CCodeFragment register_dbus_info (ObjectTypeSymbol bindable) { + string generate_dbus_wrapper (Method m, ObjectTypeSymbol sym) { + string wrapper_name = "_dbus_%s".printf (m.get_cname ()); - CCodeFragment fragment = new CCodeFragment (); + // declaration - var dbus = bindable.get_attribute ("DBus"); - if (dbus == null) { - return fragment; - } - var dbus_iface_name = dbus.get_string ("name"); - if (dbus_iface_name == null) { - return fragment; - } + CCodeDeclaration cdecl; - dbus_glib_h_needed = true; + var function = new CCodeFunction (wrapper_name, "DBusMessage*"); + function.modifiers = CCodeModifiers.STATIC; - var dbus_methods = new StringBuilder (); - dbus_methods.append ("{\n"); + function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*")); + function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*")); + function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*")); - var blob = new StringBuilder (); - blob.append_c ('"'); + var block = new CCodeBlock (); + var prefragment = new CCodeFragment (); + var postfragment = new CCodeFragment (); - int method_count = 0; - long blob_len = 0; - foreach (Method m in bindable.get_methods ()) { - if (m is CreationMethod || m.binding != MemberBinding.INSTANCE - || m.overrides || m.access != SymbolAccessibility.PUBLIC) { + cdecl = new CCodeDeclaration ("DBusMessageIter"); + cdecl.add_declarator (new CCodeVariableDeclarator ("iter")); + block.add_statement (cdecl); + + cdecl = new CCodeDeclaration ("GError*"); + cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("error", new CCodeConstant ("NULL"))); + block.add_statement (cdecl); + + block.add_statement (prefragment); + + var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature")); + message_signature.add_argument (new CCodeIdentifier ("message")); + var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); + signature_check.add_argument (message_signature); + var signature_error_block = new CCodeBlock (); + signature_error_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL"))); + prefragment.append (new CCodeIfStatement (signature_check, signature_error_block)); + + var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init")); + iter_call.add_argument (new CCodeIdentifier ("message")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter"))); + prefragment.append (new CCodeExpressionStatement (iter_call)); + + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append")); + iter_call.add_argument (new CCodeIdentifier ("reply")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter"))); + postfragment.append (new CCodeExpressionStatement (iter_call)); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ())); + + ccall.add_argument (new CCodeIdentifier ("self")); + + // expected type signature for input parameters + string type_signature = ""; + + foreach (FormalParameter param in m.get_parameters ()) { + cdecl = new CCodeDeclaration (param.parameter_type.get_cname ()); + cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (param.name, default_value_for_type (param.parameter_type, true))); + prefragment.append (cdecl); + if (type_signature == "" + && param.direction == ParameterDirection.IN + && param.parameter_type.data_type != null + && param.parameter_type.data_type.get_full_name () == "DBus.BusName") { + // first parameter is a string parameter called 'sender' + // pass bus name of sender + var get_sender = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_sender")); + get_sender.add_argument (new CCodeIdentifier ("message")); + ccall.add_argument (get_sender); continue; } - if (!is_dbus_visible (m)) { - continue; + var st = param.parameter_type.data_type as Struct; + if (param.direction != ParameterDirection.IN + || (st != null && !st.is_simple_type ())) { + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name))); + } else { + ccall.add_argument (new CCodeIdentifier (param.name)); + } + + if (param.parameter_type is ArrayType) { + var array_type = (ArrayType) param.parameter_type; + + for (int dim = 1; dim <= array_type.rank; dim++) { + string length_cname = get_array_length_cname (param.name, dim); + + cdecl = new CCodeDeclaration ("int"); + cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (length_cname, new CCodeConstant ("0"))); + prefragment.append (cdecl); + if (param.direction != ParameterDirection.IN) { + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname))); + } else { + ccall.add_argument (new CCodeIdentifier (length_cname)); + } + } } - var parameters = new Gee.ArrayList (); - foreach (FormalParameter param in m.get_parameters ()) { - parameters.add (param); + if (param.direction == ParameterDirection.IN) { + type_signature += param.parameter_type.get_type_signature (); + + var target = new CCodeIdentifier (param.name); + var expr = read_expression (prefragment, param.parameter_type, new CCodeIdentifier ("iter"), target); + prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr))); + } else { + write_expression (postfragment, param.parameter_type, new CCodeIdentifier ("iter"), new CCodeIdentifier (param.name)); } - if (!(m.return_type is VoidType)) { - parameters.add (new FormalParameter ("result", new PointerType (new VoidType ()))); - } - parameters.add (new FormalParameter ("error", gerror_type)); - - dbus_methods.append ("{ (GCallback) "); - dbus_methods.append (generate_dbus_wrapper (m, bindable)); - dbus_methods.append (", "); - dbus_methods.append (head.get_marshaller_function (parameters, bool_type, null, true)); - dbus_methods.append (", "); - dbus_methods.append (blob_len.to_string ()); - dbus_methods.append (" },\n"); - - head.generate_marshaller (parameters, bool_type, true); - - long start = blob.len; - - blob.append (dbus_iface_name); - blob.append ("\\0"); - start++; - - blob.append (Symbol.lower_case_to_camel_case (m.name)); - blob.append ("\\0"); - start++; - - // synchronous - blob.append ("S\\0"); - start++; - - foreach (FormalParameter param in m.get_parameters ()) { - blob.append (param.name); - blob.append ("\\0"); - start++; - - if (param.direction == ParameterDirection.IN) { - blob.append ("I\\0"); - start++; - } else if (param.direction == ParameterDirection.OUT) { - blob.append ("O\\0"); - start++; - blob.append ("F\\0"); - start++; - blob.append ("N\\0"); - start++; - } else { - Report.error (param.source_reference, "unsupported parameter direction for D-Bus method"); + } + + signature_check.add_argument (new CCodeConstant ("\"%s\"".printf (type_signature))); + + if (!(m.return_type is VoidType)) { + cdecl = new CCodeDeclaration (m.return_type.get_cname ()); + cdecl.add_declarator (new CCodeVariableDeclarator ("result")); + block.add_statement (cdecl); + block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), ccall))); + + if (m.return_type is ArrayType) { + var array_type = (ArrayType) m.return_type; + + for (int dim = 1; dim <= array_type.rank; dim++) { + string length_cname = get_array_length_cname ("result", dim); + + cdecl = new CCodeDeclaration ("int"); + cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (length_cname, new CCodeConstant ("0"))); + prefragment.append (cdecl); + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname))); } + } + + write_expression (postfragment, m.return_type, new CCodeIdentifier ("iter"), new CCodeIdentifier ("result")); + } else { + block.add_statement (new CCodeExpressionStatement (ccall)); + } + + cdecl = new CCodeDeclaration ("DBusMessage*"); + cdecl.add_declarator (new CCodeVariableDeclarator ("reply")); + block.add_statement (cdecl); + + if (m.get_error_types ().size > 0) { + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error"))); - blob.append (param.parameter_type.get_type_signature ()); - blob.append ("\\0"); - start++; + var error_block = new CCodeBlock (); + + var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_error")); + msgcall.add_argument (new CCodeIdentifier ("message")); + msgcall.add_argument (new CCodeIdentifier ("DBUS_ERROR_FAILED")); + msgcall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("error"), "message")); + error_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall))); + + error_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("reply"))); + + block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("error"), error_block)); + } + + var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return")); + msgcall.add_argument (new CCodeIdentifier ("message")); + block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall))); + + block.add_statement (postfragment); + + block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("reply"))); + + source_type_member_declaration.append (function.copy ()); + + function.block = block; + source_type_member_definition.append (function); + + return wrapper_name; + } + + string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) { + string wrapper_name = "_dbus_%s_%s".printf (sym.get_lower_case_cname (), sig.get_cname ()); + + // declaration + + CCodeDeclaration cdecl; + + var function = new CCodeFunction (wrapper_name, "void"); + function.modifiers = CCodeModifiers.STATIC; + + function.add_parameter (new CCodeFormalParameter ("_sender", "GObject*")); + + foreach (var param in sig.get_parameters ()) { + function.add_parameter ((CCodeFormalParameter) get_ccodenode (param)); + if (param.parameter_type is ArrayType) { + var array_type = (ArrayType) param.parameter_type; + for (int dim = 1; dim <= array_type.rank; dim++) { + function.add_parameter (new CCodeFormalParameter (head.get_array_length_cname (param.name, dim), "int")); + } } + } - if (!(m.return_type is VoidType)) { - blob.append (dbus_result_name (m)); - blob.append ("\\0"); - start++; + function.add_parameter (new CCodeFormalParameter ("_connection", "DBusConnection*")); + + var block = new CCodeBlock (); + var prefragment = new CCodeFragment (); + + var path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get_data")); + path.add_argument (new CCodeIdentifier ("_sender")); + path.add_argument (new CCodeConstant ("\"dbus_object_path\"")); + + cdecl = new CCodeDeclaration ("const char *"); + cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("_path", path)); + block.add_statement (cdecl); + + cdecl = new CCodeDeclaration ("DBusMessage"); + cdecl.add_declarator (new CCodeVariableDeclarator ("*_message")); + block.add_statement (cdecl); + + cdecl = new CCodeDeclaration ("DBusMessageIter"); + cdecl.add_declarator (new CCodeVariableDeclarator ("_iter")); + block.add_statement (cdecl); - blob.append ("O\\0"); - start++; - blob.append ("F\\0"); - start++; - blob.append ("N\\0"); - start++; + block.add_statement (prefragment); - blob.append (m.return_type.get_type_signature ()); - blob.append ("\\0"); - start++; + var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_signal")); + msgcall.add_argument (new CCodeIdentifier ("_path")); + msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name))); + msgcall.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (sig.name)))); + prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_message"), msgcall))); + + var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append")); + iter_call.add_argument (new CCodeIdentifier ("_message")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_iter"))); + prefragment.append (new CCodeExpressionStatement (iter_call)); + + foreach (FormalParameter param in sig.get_parameters ()) { + CCodeExpression expr = new CCodeIdentifier (param.name); + if (param.parameter_type.is_real_struct_type ()) { + expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr); } + write_expression (prefragment, param.parameter_type, new CCodeIdentifier ("_iter"), expr); + } + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send")); + ccall.add_argument (new CCodeIdentifier ("_connection")); + ccall.add_argument (new CCodeIdentifier ("_message")); + ccall.add_argument (new CCodeConstant ("NULL")); + block.add_statement (new CCodeExpressionStatement (ccall)); + + var message_unref = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref")); + message_unref.add_argument (new CCodeIdentifier ("_message")); + block.add_statement (new CCodeExpressionStatement (message_unref)); + + source_type_member_declaration.append (function.copy ()); + function.block = block; + source_type_member_definition.append (function); + + return wrapper_name; + } - blob.append ("\\0"); - start++; + void generate_register_function (ObjectType object_type) { + var sym = object_type.type_symbol; - blob_len += blob.len - start; + var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_register_object", "void"); + cfunc.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*")); + cfunc.add_parameter (new CCodeFormalParameter ("path", "const char*")); + cfunc.add_parameter (new CCodeFormalParameter ("object", "void*")); - method_count++; + if (!sym.is_internal_symbol ()) { + dbus_glib_h_needed_in_header = true; + + header_type_member_declaration.append (cfunc.copy ()); + } else { + dbus_glib_h_needed = true; + + cfunc.modifiers |= CCodeModifiers.STATIC; + source_type_member_declaration.append (cfunc.copy ()); + } + + var block = new CCodeBlock (); + cfunc.block = block; + + var get_path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get_data")); + get_path.add_argument (new CCodeIdentifier ("object")); + get_path.add_argument (new CCodeConstant ("\"dbus_object_path\"")); + var register_check = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, get_path); + + var register_block = new CCodeBlock (); + + var path_dup = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup")); + path_dup.add_argument (new CCodeIdentifier ("path")); + + var set_path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_set_data")); + set_path.add_argument (new CCodeIdentifier ("object")); + set_path.add_argument (new CCodeConstant ("\"dbus_object_path\"")); + set_path.add_argument (path_dup); + register_block.add_statement (new CCodeExpressionStatement (set_path)); + + var cregister = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_register_object_path")); + cregister.add_argument (new CCodeIdentifier ("connection")); + cregister.add_argument (new CCodeIdentifier ("path")); + cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_path_vtable (object_type))); + cregister.add_argument (new CCodeIdentifier ("object")); + register_block.add_statement (new CCodeExpressionStatement (cregister)); + + block.add_statement (new CCodeIfStatement (register_check, register_block)); + + handle_signals (object_type.type_symbol, block); + + var cl = sym as Class; + if (cl != null) { + foreach (DataType base_type in cl.get_base_types ()) { + var base_obj_type = base_type as ObjectType; + if (type_implements_dbus_interface (base_obj_type.type_symbol)) { + var base_register = new CCodeFunctionCall (new CCodeIdentifier (base_obj_type.type_symbol.get_lower_case_cprefix () + "dbus_register_object")); + base_register.add_argument (new CCodeIdentifier ("connection")); + base_register.add_argument (new CCodeIdentifier ("path")); + base_register.add_argument (new CCodeIdentifier ("object")); + block.add_statement (new CCodeExpressionStatement (base_register)); + } + } } - blob.append_c ('"'); + source_type_member_definition.append (cfunc); + } + + void generate_unregister_function (ObjectType object_type) { + var sym = object_type.type_symbol; - dbus_methods.append ("}\n"); + var cfunc = new CCodeFunction ("_" + sym.get_lower_case_cprefix () + "dbus_unregister", "void"); + cfunc.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*")); + cfunc.add_parameter (new CCodeFormalParameter ("user_data", "void*")); - var dbus_signals = new StringBuilder (); - dbus_signals.append_c ('"'); - foreach (Signal sig in bindable.get_signals ()) { - if (sig.access != SymbolAccessibility.PUBLIC) { + source_type_member_declaration.append (cfunc.copy ()); + + var block = new CCodeBlock (); + cfunc.block = block; + + source_type_member_definition.append (cfunc); + } + + void handle_method (string dbus_iface_name, string dbus_method_name, string handler_name, CCodeBlock block, ref CCodeIfStatement clastif) { + var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_is_method_call")); + ccheck.add_argument (new CCodeIdentifier ("message")); + ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name))); + ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_method_name))); + + var callblock = new CCodeBlock (); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier (handler_name)); + ccall.add_argument (new CCodeIdentifier ("object")); + ccall.add_argument (new CCodeIdentifier ("connection")); + ccall.add_argument (new CCodeIdentifier ("message")); + + callblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), ccall))); + + var cif = new CCodeIfStatement (ccheck, callblock); + if (clastif == null) { + block.add_statement (cif); + } else { + clastif.false_statement = cif; + } + + clastif = cif; + } + + void handle_methods (ObjectTypeSymbol sym, string dbus_iface_name, CCodeBlock block, ref CCodeIfStatement clastif) { + foreach (Method m in sym.get_methods ()) { + if (m is CreationMethod || m.binding != MemberBinding.INSTANCE + || m.overrides || m.access != SymbolAccessibility.PUBLIC) { continue; } - if (!is_dbus_visible (sig)) { + if (!is_dbus_visible (m)) { continue; } - dbus_signals.append (dbus_iface_name); - dbus_signals.append ("\\0"); - dbus_signals.append (Symbol.lower_case_to_camel_case (sig.name)); - dbus_signals.append ("\\0"); + handle_method (dbus_iface_name, Symbol.lower_case_to_camel_case (m.name), generate_dbus_wrapper (m, sym), block, ref clastif); } - dbus_signals.append_c('"'); + } + + string generate_dbus_property_get_wrapper (ObjectTypeSymbol sym, string dbus_iface_name) { + string wrapper_name = "_dbus_%s_property_get".printf (sym.get_lower_case_cname ()); + + CCodeDeclaration cdecl; + + var function = new CCodeFunction (wrapper_name, "DBusMessage*"); + function.modifiers = CCodeModifiers.STATIC; + + function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*")); + function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*")); + function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*")); - var dbus_props = new StringBuilder(); - dbus_props.append_c ('"'); - foreach (Property prop in bindable.get_properties ()) { - if (prop.access != SymbolAccessibility.PUBLIC) { + var block = new CCodeBlock (); + var prefragment = new CCodeFragment (); + + cdecl = new CCodeDeclaration ("DBusMessage*"); + cdecl.add_declarator (new CCodeVariableDeclarator ("reply")); + block.add_statement (cdecl); + + cdecl = new CCodeDeclaration ("DBusMessageIter"); + cdecl.add_declarator (new CCodeVariableDeclarator ("iter")); + cdecl.add_declarator (new CCodeVariableDeclarator ("reply_iter")); + cdecl.add_declarator (new CCodeVariableDeclarator ("subiter")); + block.add_statement (cdecl); + + var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature")); + message_signature.add_argument (new CCodeIdentifier ("message")); + var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); + signature_check.add_argument (message_signature); + signature_check.add_argument (new CCodeConstant ("\"ss\"")); + var signature_error_block = new CCodeBlock (); + signature_error_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL"))); + block.add_statement (new CCodeIfStatement (signature_check, signature_error_block)); + + var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init")); + iter_call.add_argument (new CCodeIdentifier ("message")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter"))); + block.add_statement (new CCodeExpressionStatement (iter_call)); + + var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return")); + msgcall.add_argument (new CCodeIdentifier ("message")); + block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall))); + + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append")); + iter_call.add_argument (new CCodeIdentifier ("reply")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter"))); + block.add_statement (new CCodeExpressionStatement (iter_call)); + + block.add_statement (prefragment); + + cdecl = new CCodeDeclaration ("char*"); + cdecl.add_declarator (new CCodeVariableDeclarator ("interface_name")); + prefragment.append (cdecl); + var target = new CCodeIdentifier ("interface_name"); + var expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target); + prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr))); + + cdecl = new CCodeDeclaration ("char*"); + cdecl.add_declarator (new CCodeVariableDeclarator ("property_name")); + prefragment.append (cdecl); + target = new CCodeIdentifier ("property_name"); + expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target); + prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr))); + + CCodeIfStatement clastif = null; + + foreach (Property prop in sym.get_properties ()) { + if (prop.binding != MemberBinding.INSTANCE + || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) { continue; } if (!is_dbus_visible (prop)) { continue; } + if (prop.get_accessor == null) { + continue; + } - dbus_props.append (dbus_iface_name); - dbus_props.append ("\\0"); - dbus_props.append (Symbol.lower_case_to_camel_case (prop.name)); - dbus_props.append ("\\0"); - } - dbus_props.append_c ('"'); + var prop_block = new CCodeBlock (); + var postfragment = new CCodeFragment (); + prop_block.add_statement (postfragment); - var dbus_methods_decl = new CCodeDeclaration ("const DBusGMethodInfo"); - dbus_methods_decl.modifiers = CCodeModifiers.STATIC; - dbus_methods_decl.add_declarator (new CCodeVariableDeclarator.with_initializer ("%s_dbus_methods[]".printf (bindable.get_lower_case_cname ()), new CCodeConstant (dbus_methods.str))); + var ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); + ccmp.add_argument (new CCodeIdentifier ("interface_name")); + ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name))); + var ccheck1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0")); - fragment.append (dbus_methods_decl); + ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); + ccmp.add_argument (new CCodeIdentifier ("property_name")); + ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (prop.name)))); + var ccheck2 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0")); - var dbus_object_info = new CCodeDeclaration ("const DBusGObjectInfo"); - dbus_object_info.modifiers = CCodeModifiers.STATIC; - dbus_object_info.add_declarator (new CCodeVariableDeclarator.with_initializer ("%s_dbus_object_info".printf (bindable.get_lower_case_cname ()), new CCodeConstant ("{ 0, %s_dbus_methods, %d, %s, %s, %s }".printf (bindable.get_lower_case_cname (), method_count, blob.str, dbus_signals.str, dbus_props.str)))); + var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccheck1, ccheck2); - fragment.append (dbus_object_info); + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter"))); + iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_VARIANT")); + iter_call.add_argument (new CCodeConstant ("\"%s\"".printf (prop.property_type.get_type_signature ()))); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter"))); + postfragment.append (new CCodeExpressionStatement (iter_call)); - var install_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_type_install_info")); - install_call.add_argument (new CCodeIdentifier (bindable.get_type_id ())); - install_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("%s_dbus_object_info".printf (bindable.get_lower_case_cname ())))); + var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.get_accessor.get_cname ())); + ccall.add_argument (new CCodeIdentifier ("self")); - fragment.append (new CCodeExpressionStatement (install_call)); + write_expression (postfragment, prop.property_type, new CCodeIdentifier ("subiter"), ccall); - return fragment; + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter"))); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter"))); + postfragment.append (new CCodeExpressionStatement (iter_call)); + + var cif = new CCodeIfStatement (ccheck, prop_block); + if (clastif == null) { + block.add_statement (cif); + } else { + clastif.false_statement = cif; + } + + clastif = cif; + } + + if (clastif == null) { + block = new CCodeBlock (); + block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL"))); + } else { + var else_block = new CCodeBlock (); + else_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL"))); + clastif.false_statement = else_block; + + block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("reply"))); + } + + source_type_member_declaration.append (function.copy ()); + + function.block = block; + source_type_member_definition.append (function); + + return wrapper_name; } - void transform_struct_to_value_array (CCodeBlock block, Struct st, CCodeExpression target, CCodeExpression st_expr, string name) { - var array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_new")); - array_construct.add_argument (new CCodeConstant ("0")); + string generate_dbus_property_get_all_wrapper (ObjectTypeSymbol sym, string dbus_iface_name) { + string wrapper_name = "_dbus_%s_property_get_all".printf (sym.get_lower_case_cname ()); + + CCodeDeclaration cdecl; + + var function = new CCodeFunction (wrapper_name, "DBusMessage*"); + function.modifiers = CCodeModifiers.STATIC; + + function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*")); + function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*")); + function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*")); - block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (target, array_construct))); + var block = new CCodeBlock (); + var prefragment = new CCodeFragment (); + + cdecl = new CCodeDeclaration ("DBusMessage*"); + cdecl.add_declarator (new CCodeVariableDeclarator ("reply")); + block.add_statement (cdecl); - var type_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_struct")); - type_call.add_argument (new CCodeConstant ("\"GValueArray\"")); + cdecl = new CCodeDeclaration ("DBusMessageIter"); + cdecl.add_declarator (new CCodeVariableDeclarator ("iter")); + cdecl.add_declarator (new CCodeVariableDeclarator ("reply_iter")); + cdecl.add_declarator (new CCodeVariableDeclarator ("subiter")); + cdecl.add_declarator (new CCodeVariableDeclarator ("entry_iter")); + cdecl.add_declarator (new CCodeVariableDeclarator ("value_iter")); + block.add_statement (cdecl); - foreach (Field f in st.get_fields ()) { - if (f.binding != MemberBinding.INSTANCE) { + var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature")); + message_signature.add_argument (new CCodeIdentifier ("message")); + var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); + signature_check.add_argument (message_signature); + signature_check.add_argument (new CCodeConstant ("\"s\"")); + var signature_error_block = new CCodeBlock (); + signature_error_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL"))); + block.add_statement (new CCodeIfStatement (signature_check, signature_error_block)); + + var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init")); + iter_call.add_argument (new CCodeIdentifier ("message")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter"))); + block.add_statement (new CCodeExpressionStatement (iter_call)); + + var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return")); + msgcall.add_argument (new CCodeIdentifier ("message")); + block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall))); + + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append")); + iter_call.add_argument (new CCodeIdentifier ("reply")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter"))); + block.add_statement (new CCodeExpressionStatement (iter_call)); + + block.add_statement (prefragment); + + cdecl = new CCodeDeclaration ("char*"); + cdecl.add_declarator (new CCodeVariableDeclarator ("interface_name")); + prefragment.append (cdecl); + var target = new CCodeIdentifier ("interface_name"); + var expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target); + prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr))); + + cdecl = new CCodeDeclaration ("const char*"); + cdecl.add_declarator (new CCodeVariableDeclarator ("property_name")); + prefragment.append (cdecl); + + var prop_block = new CCodeBlock (); + + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter"))); + iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_ARRAY")); + iter_call.add_argument (new CCodeConstant ("\"{sv}\"")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter"))); + prop_block.add_statement (new CCodeExpressionStatement (iter_call)); + + foreach (Property prop in sym.get_properties ()) { + if (prop.binding != MemberBinding.INSTANCE + || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) { + continue; + } + if (!is_dbus_visible (prop)) { + continue; + } + if (prop.get_accessor == null) { continue; } - string val_name = "val_%s_%s".printf (name, f.name); + var postfragment = new CCodeFragment (); + prop_block.add_statement (postfragment); + + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter"))); + iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_DICT_ENTRY")); + iter_call.add_argument (new CCodeConstant ("NULL")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter"))); + postfragment.append (new CCodeExpressionStatement (iter_call)); + + postfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("property_name"), new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (prop.name)))))); + + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_append_basic")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter"))); + iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_STRING")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("property_name"))); + postfragment.append (new CCodeExpressionStatement (iter_call)); + + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_open_container")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter"))); + iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_VARIANT")); + iter_call.add_argument (new CCodeConstant ("\"%s\"".printf (prop.property_type.get_type_signature ()))); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value_iter"))); + postfragment.append (new CCodeExpressionStatement (iter_call)); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.get_accessor.get_cname ())); + ccall.add_argument (new CCodeIdentifier ("self")); + + write_expression (postfragment, prop.property_type, new CCodeIdentifier ("value_iter"), ccall); + + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter"))); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value_iter"))); + postfragment.append (new CCodeExpressionStatement (iter_call)); + + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter"))); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("entry_iter"))); + postfragment.append (new CCodeExpressionStatement (iter_call)); + } - // 0-initialize struct with struct initializer { 0 } - var cvalinit = new CCodeInitializerList (); - cvalinit.append (new CCodeConstant ("0")); + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_close_container")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("reply_iter"))); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter"))); + prop_block.add_statement (new CCodeExpressionStatement (iter_call)); - var cval_decl = new CCodeDeclaration ("GValue"); - cval_decl.add_declarator (new CCodeVariableDeclarator.with_initializer (val_name, cvalinit)); - block.add_statement (cval_decl); + var ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); + ccmp.add_argument (new CCodeIdentifier ("interface_name")); + ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name))); + var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0")); - var val_ptr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (val_name)); + var else_block = new CCodeBlock (); + else_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL"))); + block.add_statement (new CCodeIfStatement (ccheck, prop_block, else_block)); - string type_id = f.field_type.data_type.get_type_id (); - string set_value_function = f.field_type.data_type.get_set_value_function (); + block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("reply"))); - if (f.field_type.data_type is Enum) { - // dbus-glib does not support enums - var en = (Enum) f.field_type.data_type; - if (!en.is_flags) { - type_id = "G_TYPE_INT"; - set_value_function = "g_value_set_int"; - } else { - type_id = "G_TYPE_UINT"; - set_value_function = "g_value_set_uint"; - } + source_type_member_declaration.append (function.copy ()); + + function.block = block; + source_type_member_definition.append (function); + + return wrapper_name; + } + + string generate_dbus_property_set_wrapper (ObjectTypeSymbol sym, string dbus_iface_name) { + string wrapper_name = "_dbus_%s_property_set".printf (sym.get_lower_case_cname ()); + + var function = new CCodeFunction (wrapper_name, "DBusMessage*"); + function.modifiers = CCodeModifiers.STATIC; + + function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*")); + function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*")); + function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*")); + + var block = new CCodeBlock (); + var prefragment = new CCodeFragment (); + + var cdecl = new CCodeDeclaration ("DBusMessage*"); + cdecl.add_declarator (new CCodeVariableDeclarator ("reply")); + block.add_statement (cdecl); + + cdecl = new CCodeDeclaration ("DBusMessageIter"); + cdecl.add_declarator (new CCodeVariableDeclarator ("iter")); + cdecl.add_declarator (new CCodeVariableDeclarator ("subiter")); + block.add_statement (cdecl); + + var message_signature = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_get_signature")); + message_signature.add_argument (new CCodeIdentifier ("message")); + var signature_check = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); + signature_check.add_argument (message_signature); + signature_check.add_argument (new CCodeConstant ("\"ssv\"")); + var signature_error_block = new CCodeBlock (); + signature_error_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL"))); + block.add_statement (new CCodeIfStatement (signature_check, signature_error_block)); + + var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init")); + iter_call.add_argument (new CCodeIdentifier ("message")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter"))); + block.add_statement (new CCodeExpressionStatement (iter_call)); + + var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return")); + msgcall.add_argument (new CCodeIdentifier ("message")); + block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall))); + + block.add_statement (prefragment); + + cdecl = new CCodeDeclaration ("char*"); + cdecl.add_declarator (new CCodeVariableDeclarator ("interface_name")); + prefragment.append (cdecl); + var target = new CCodeIdentifier ("interface_name"); + var expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target); + prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr))); + + cdecl = new CCodeDeclaration ("char*"); + cdecl.add_declarator (new CCodeVariableDeclarator ("property_name")); + prefragment.append (cdecl); + target = new CCodeIdentifier ("property_name"); + expr = read_expression (prefragment, string_type, new CCodeIdentifier ("iter"), target); + prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr))); + + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_recurse")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter"))); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("subiter"))); + prefragment.append (new CCodeExpressionStatement (iter_call)); + + CCodeIfStatement clastif = null; + + foreach (Property prop in sym.get_properties ()) { + if (prop.binding != MemberBinding.INSTANCE + || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) { + continue; + } + if (!is_dbus_visible (prop)) { + continue; + } + if (prop.set_accessor == null) { + continue; } - var cinit_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init")); - cinit_call.add_argument (val_ptr); - cinit_call.add_argument (new CCodeIdentifier (type_id)); - block.add_statement (new CCodeExpressionStatement (cinit_call)); + var prop_block = new CCodeBlock (); + prefragment = new CCodeFragment (); + prop_block.add_statement (prefragment); + + var ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); + ccmp.add_argument (new CCodeIdentifier ("interface_name")); + ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name))); + var ccheck1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0")); + + ccmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); + ccmp.add_argument (new CCodeIdentifier ("property_name")); + ccmp.add_argument (new CCodeConstant ("\"%s\"".printf (Symbol.lower_case_to_camel_case (prop.name)))); + var ccheck2 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccmp, new CCodeConstant ("0")); + + var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccheck1, ccheck2); + + cdecl = new CCodeDeclaration (prop.property_type.get_cname ()); + cdecl.add_declarator (new CCodeVariableDeclarator ("value")); + prefragment.append (cdecl); + + target = new CCodeIdentifier ("value"); + expr = read_expression (prefragment, prop.property_type, new CCodeIdentifier ("subiter"), target); + prefragment.append (new CCodeExpressionStatement (new CCodeAssignment (target, expr))); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier (prop.set_accessor.get_cname ())); + ccall.add_argument (new CCodeIdentifier ("self")); + ccall.add_argument (new CCodeIdentifier ("value")); - var cset_call = new CCodeFunctionCall (new CCodeIdentifier (set_value_function)); - cset_call.add_argument (val_ptr); - if (f.field_type.data_type is Struct) { - cset_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess (st_expr, f.name))); + prop_block.add_statement (new CCodeExpressionStatement (ccall)); + + var cif = new CCodeIfStatement (ccheck, prop_block); + if (clastif == null) { + block.add_statement (cif); } else { - cset_call.add_argument (new CCodeMemberAccess (st_expr, f.name)); + clastif.false_statement = cif; } - block.add_statement (new CCodeExpressionStatement (cset_call)); - var cappend_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_append")); - cappend_call.add_argument (target); - cappend_call.add_argument (val_ptr); - block.add_statement (new CCodeExpressionStatement (cappend_call)); + clastif = cif; + } + + if (clastif == null) { + block = new CCodeBlock (); + block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL"))); + } else { + var else_block = new CCodeBlock (); + else_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL"))); + clastif.false_statement = else_block; - type_call.add_argument (new CCodeIdentifier (f.field_type.data_type.get_type_id ())); + block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("reply"))); } - } - void transform_struct_hash_table_to_value_array_hash_table (CCodeBlock block, Struct st, CCodeExpression target, CCodeExpression table_expr, string name) { - // FIXME take care of memory management - var table_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_new")); - table_construct.add_argument (new CCodeIdentifier ("g_direct_hash")); - table_construct.add_argument (new CCodeIdentifier ("g_direct_equal")); - block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (target, table_construct))); - - var cdecl = new CCodeDeclaration ("GList"); - cdecl.add_declarator (new CCodeVariableDeclarator ("*%s_keys".printf (name))); - cdecl.add_declarator (new CCodeVariableDeclarator ("*%s_keys_it".printf (name))); - cdecl.add_declarator (new CCodeVariableDeclarator ("*%s_values".printf (name))); - cdecl.add_declarator (new CCodeVariableDeclarator ("*%s_values_it".printf (name))); - block.add_statement (cdecl); + source_type_member_declaration.append (function.copy ()); + + function.block = block; + source_type_member_definition.append (function); - var get_keys = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_get_keys")); - get_keys.add_argument (table_expr); - block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("%s_keys".printf (name)), get_keys))); - - var get_values = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_get_values")); - get_values.add_argument (table_expr); - block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("%s_values".printf (name)), get_values))); - - var loop_body = new CCodeBlock (); - var for_stmt = new CCodeForStatement (new CCodeIdentifier ("%s_keys_it".printf (name)), loop_body); - block.add_statement (for_stmt); - for_stmt.add_initializer (new CCodeAssignment (new CCodeIdentifier ("%s_keys_it".printf (name)), new CCodeIdentifier ("%s_keys".printf (name)))); - for_stmt.add_initializer (new CCodeAssignment (new CCodeIdentifier ("%s_values_it".printf (name)), new CCodeIdentifier ("%s_values".printf (name)))); - for_stmt.add_iterator (new CCodeAssignment (new CCodeIdentifier ("%s_keys_it".printf (name)), new CCodeMemberAccess.pointer (new CCodeIdentifier ("%s_keys_it".printf (name)), "next"))); - for_stmt.add_iterator (new CCodeAssignment (new CCodeIdentifier ("%s_values_it".printf (name)), new CCodeMemberAccess.pointer (new CCodeIdentifier ("%s_values_it".printf (name)), "next"))); - - cdecl = new CCodeDeclaration (st.get_cname () + "*"); - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("%s_value".printf (name), new CCodeMemberAccess.pointer (new CCodeIdentifier ("%s_values_it".printf (name)), "data"))); - loop_body.add_statement (cdecl); - - cdecl = new CCodeDeclaration ("GValueArray*"); - cdecl.add_declarator (new CCodeVariableDeclarator ("%s_value_array".printf (name))); - loop_body.add_statement (cdecl); - - transform_struct_to_value_array (loop_body, st, new CCodeIdentifier ("%s_value_array".printf (name)), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("%s_value".printf (name))), name); - - var insert_call = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_insert")); - insert_call.add_argument (target); - insert_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("%s_keys_it".printf (name)), "data")); - insert_call.add_argument (new CCodeIdentifier ("%s_value_array".printf (name))); - loop_body.add_statement (new CCodeExpressionStatement (insert_call)); + return wrapper_name; } - string generate_dbus_wrapper (Method m, ObjectTypeSymbol bindable) { - string wrapper_name = "_dbus_%s".printf (m.get_cname ()); + string get_dbus_type_introspection (ObjectTypeSymbol sym) { + string result = ""; - // declaration + var cl = sym as Class; + if (cl != null) { + foreach (DataType base_type in cl.get_base_types ()) { + var base_obj_type = base_type as ObjectType; + result += get_dbus_type_introspection (base_obj_type.type_symbol); + } + } - var function = new CCodeFunction (wrapper_name, "gboolean"); - function.modifiers = CCodeModifiers.STATIC; - m.ccodenode = function; + var dbus = sym.get_attribute ("DBus"); + if (dbus == null) { + return result; + } + string dbus_iface_name = dbus.get_string ("name"); + if (dbus_iface_name == null) { + return result; + } - function.add_parameter (new CCodeFormalParameter ("self", bindable.get_cname () + "*")); + result += "\n".printf (dbus_iface_name); - foreach (FormalParameter param in m.get_parameters ()) { - string ptr = (param.direction == ParameterDirection.OUT ? "*" : ""); - var array_type = param.parameter_type as ArrayType; - if (array_type != null && array_type.element_type.data_type != string_type.data_type) { - if (dbus_use_ptr_array (array_type)) { - function.add_parameter (new CCodeFormalParameter ("dbus_%s".printf (param.name), "GPtrArray*" + ptr)); - } else { - function.add_parameter (new CCodeFormalParameter ("dbus_%s".printf (param.name), "GArray*" + ptr)); - } - } else if (param.parameter_type.get_type_signature ().has_prefix ("(")) { - function.add_parameter (new CCodeFormalParameter ("dbus_%s".printf (param.name), "GValueArray*" + ptr)); - } else if (param.parameter_type.get_type_signature ().has_prefix ("a{")) { - // hash table output parameter - var type_args = param.parameter_type.get_type_arguments (); - var value_type = type_args.get (1); - if (value_type.get_type_signature ().has_prefix ("(")) { - // values are structs - function.add_parameter (new CCodeFormalParameter ("dbus_%s".printf (param.name), "GHashTable*" + ptr)); - } else { - function.add_parameter ((CCodeFormalParameter) param.ccodenode); - } - } else { - function.add_parameter ((CCodeFormalParameter) param.ccodenode); + foreach (var m in sym.get_methods ()) { + if (m is CreationMethod || m.binding != MemberBinding.INSTANCE + || m.overrides || m.access != SymbolAccessibility.PUBLIC) { + continue; + } + if (!is_dbus_visible (m)) { + continue; } + + result += " \n".printf (Symbol.lower_case_to_camel_case (m.name)); + + foreach (var param in m.get_parameters ()) { + string direction = param.direction == ParameterDirection.IN ? "in" : "out"; + result += " \n".printf (param.name, param.parameter_type.get_type_signature (), direction); + } + if (!(m.return_type is VoidType)) { + result += " \n".printf (dbus_result_name (m), m.return_type.get_type_signature ()); + } + + result += " \n"; } - if (!(m.return_type is VoidType)) { - var array_type = m.return_type as ArrayType; - if (array_type != null) { - if (array_type.element_type.data_type == string_type.data_type) { - function.add_parameter (new CCodeFormalParameter ("result", array_type.get_cname () + "*")); - } else if (dbus_use_ptr_array (array_type)) { - function.add_parameter (new CCodeFormalParameter ("dbus_result", "GPtrArray**")); - } else { - function.add_parameter (new CCodeFormalParameter ("dbus_result", "GArray**")); - } - } else if (m.return_type.get_type_signature ().has_prefix ("(")) { - function.add_parameter (new CCodeFormalParameter ("dbus_result", "GValueArray**")); - } else if (m.return_type.get_type_signature ().has_prefix ("a{")) { - // hash table output parameter - var type_args = m.return_type.get_type_arguments (); - var value_type = type_args.get (1); - if (value_type.get_type_signature ().has_prefix ("(")) { - // values are structs - function.add_parameter (new CCodeFormalParameter ("dbus_result", "GHashTable**")); - } else { - function.add_parameter (new CCodeFormalParameter ("result", m.return_type.get_cname () + "*")); - } - } else { - function.add_parameter (new CCodeFormalParameter ("result", m.return_type.get_cname () + "*")); + foreach (var prop in sym.get_properties ()) { + if (prop.binding != MemberBinding.INSTANCE + || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) { + continue; + } + if (!is_dbus_visible (prop)) { + continue; } + + string access = (prop.get_accessor != null ? "read" : "") + (prop.set_accessor != null ? "write" : ""); + result += " \n".printf (Symbol.lower_case_to_camel_case (prop.name), prop.property_type.get_type_signature (), access); } - function.add_parameter (new CCodeFormalParameter ("error", "GError**")); + foreach (var sig in sym.get_signals ()) { + if (sig.access != SymbolAccessibility.PUBLIC) { + continue; + } + if (!is_dbus_visible (sig)) { + continue; + } + + result += " \n".printf (Symbol.lower_case_to_camel_case (sig.name)); + + foreach (var param in sig.get_parameters ()) { + result += " \n".printf (param.name, param.parameter_type.get_type_signature ()); + } - // definition + result += " \n"; + } + + result += "\n"; + + return result; + } + + string generate_dbus_introspect (ObjectTypeSymbol sym) { + string wrapper_name = "_dbus_%s_introspect".printf (sym.get_lower_case_cname ()); + + var function = new CCodeFunction (wrapper_name, "DBusMessage*"); + function.modifiers = CCodeModifiers.STATIC; + + function.add_parameter (new CCodeFormalParameter ("self", sym.get_cname () + "*")); + function.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*")); + function.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*")); var block = new CCodeBlock (); - foreach (FormalParameter param in m.get_parameters ()) { - if (param.parameter_type.get_type_signature ().has_prefix ("(")) { - var st = (Struct) param.parameter_type.data_type; - - var cdecl = new CCodeDeclaration (st.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator (param.name)); - block.add_statement (cdecl); - - if (param.direction == ParameterDirection.IN) { - // struct input parameter - int i = 0; - foreach (Field f in st.get_fields ()) { - if (f.binding == MemberBinding.INSTANCE) { - var cget_call = new CCodeFunctionCall (new CCodeIdentifier (f.field_type.data_type.get_get_value_function ())); - 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 ())))); - var assign = new CCodeAssignment (new CCodeMemberAccess (new CCodeIdentifier (param.name), f.name), cget_call); - block.add_statement (new CCodeExpressionStatement (assign)); - i++; - } - } - } - } else if (param.parameter_type.get_type_signature ().has_prefix ("a{")) { - // hash table output parameter - var type_args = param.parameter_type.get_type_arguments (); - var value_type = type_args.get (1); - if (value_type.get_type_signature ().has_prefix ("(")) { - // values are structs - var cdecl = new CCodeDeclaration ("GHashTable*"); - cdecl.add_declarator (new CCodeVariableDeclarator (param.name)); - block.add_statement (cdecl); - } + var cdecl = new CCodeDeclaration ("DBusMessage*"); + cdecl.add_declarator (new CCodeVariableDeclarator ("reply")); + block.add_statement (cdecl); + + cdecl = new CCodeDeclaration ("DBusMessageIter"); + cdecl.add_declarator (new CCodeVariableDeclarator ("iter")); + block.add_statement (cdecl); + + var msgcall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_new_method_return")); + msgcall.add_argument (new CCodeIdentifier ("message")); + block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("reply"), msgcall))); + + var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_init_append")); + iter_call.add_argument (new CCodeIdentifier ("reply")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter"))); + block.add_statement (new CCodeExpressionStatement (iter_call)); + + cdecl = new CCodeDeclaration ("GString*"); + cdecl.add_declarator (new CCodeVariableDeclarator ("xml_data")); + block.add_statement (cdecl); + + cdecl = new CCodeDeclaration ("char**"); + cdecl.add_declarator (new CCodeVariableDeclarator ("children")); + block.add_statement (cdecl); + + cdecl = new CCodeDeclaration ("int"); + cdecl.add_declarator (new CCodeVariableDeclarator ("i")); + block.add_statement (cdecl); + + string xml_data = "\n"; + var str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_new")); + str_call.add_argument (new CCodeConstant ("\"%s\"".printf (xml_data.escape ("")))); + block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("xml_data"), str_call))); + + xml_data = "\n"; + xml_data += +""" + + + + + + + + + + + + + + + + + + + + +"""; + xml_data += get_dbus_type_introspection (sym); + str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_append")); + str_call.add_argument (new CCodeIdentifier ("xml_data")); + str_call.add_argument (new CCodeConstant ("\"%s\"".printf (xml_data.escape ("")))); + block.add_statement (new CCodeExpressionStatement (str_call)); + + var get_path = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get_data")); + get_path.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *")); + get_path.add_argument (new CCodeConstant ("\"dbus_object_path\"")); + + var list_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_list_registered")); + list_call.add_argument (new CCodeIdentifier ("connection")); + list_call.add_argument (get_path); + list_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("children"))); + block.add_statement (new CCodeExpressionStatement (list_call)); + + // add child nodes + var child_block = new CCodeBlock (); + str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_append_printf")); + str_call.add_argument (new CCodeIdentifier ("xml_data")); + str_call.add_argument (new CCodeConstant ("\"%s\"".printf ("\n".escape ("")))); + str_call.add_argument (new CCodeElementAccess (new CCodeIdentifier ("children"), new CCodeIdentifier ("i"))); + child_block.add_statement (new CCodeExpressionStatement (str_call)); + var cfor = new CCodeForStatement (new CCodeElementAccess (new CCodeIdentifier ("children"), new CCodeIdentifier ("i")), child_block); + cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0"))); + cfor.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i"))); + block.add_statement (cfor); + + xml_data = "\n"; + str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_append")); + str_call.add_argument (new CCodeIdentifier ("xml_data")); + str_call.add_argument (new CCodeConstant ("\"%s\"".printf (xml_data.escape ("")))); + block.add_statement (new CCodeExpressionStatement (str_call)); + + iter_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_iter_append_basic")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("iter"))); + iter_call.add_argument (new CCodeIdentifier ("DBUS_TYPE_STRING")); + iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (new CCodeIdentifier ("xml_data"), "str"))); + block.add_statement (new CCodeExpressionStatement (iter_call)); + + str_call = new CCodeFunctionCall (new CCodeIdentifier ("g_string_free")); + str_call.add_argument (new CCodeIdentifier ("xml_data")); + str_call.add_argument (new CCodeConstant ("TRUE")); + block.add_statement (new CCodeExpressionStatement (str_call)); + + block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("reply"))); + + source_type_member_declaration.append (function.copy ()); + + function.block = block; + source_type_member_definition.append (function); + + return wrapper_name; + } + + void handle_signals (ObjectTypeSymbol sym, CCodeBlock block) { + var dbus = sym.get_attribute ("DBus"); + if (dbus == null) { + return; + } + string dbus_iface_name = dbus.get_string ("name"); + if (dbus_iface_name == null) { + return; + } + + foreach (Signal sig in sym.get_signals ()) { + if (sig.access != SymbolAccessibility.PUBLIC) { + continue; } + if (!is_dbus_visible (sig)) { + continue; + } + + var connect = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect")); + connect.add_argument (new CCodeIdentifier ("object")); + connect.add_argument (sig.get_canonical_cconstant (null)); + connect.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback")); + connect.add_argument (new CCodeIdentifier ("connection")); + block.add_statement (new CCodeExpressionStatement (connect)); } + } - if (!(m.return_type is VoidType)) { - var array_type = m.return_type as ArrayType; - if (array_type != null) { - if (array_type.element_type.data_type != string_type.data_type) { - var cdecl = new CCodeDeclaration (m.return_type.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator ("result")); - block.add_statement (cdecl); - } + void generate_message_function (ObjectType object_type) { + var sym = object_type.type_symbol; - var len_cdecl = new CCodeDeclaration ("int"); - len_cdecl.add_declarator (new CCodeVariableDeclarator ("result_length1")); - block.add_statement (len_cdecl); - } else if (m.return_type.get_type_signature ().has_prefix ("a{")) { - // hash table return value - var type_args = m.return_type.get_type_arguments (); - var value_type = type_args.get (1); - if (value_type.get_type_signature ().has_prefix ("(")) { - // values are structs - var cdecl = new CCodeDeclaration ("GHashTable*"); - cdecl.add_declarator (new CCodeVariableDeclarator ("result")); - block.add_statement (cdecl); - } - } + dbus_glib_h_needed = true; + + var cfunc = new CCodeFunction (sym.get_lower_case_cprefix () + "dbus_message", "DBusHandlerResult"); + cfunc.add_parameter (new CCodeFormalParameter ("connection", "DBusConnection*")); + cfunc.add_parameter (new CCodeFormalParameter ("message", "DBusMessage*")); + cfunc.add_parameter (new CCodeFormalParameter ("object", "void*")); + + if (!sym.is_internal_symbol ()) { + header_type_member_declaration.append (cfunc.copy ()); + } else { + cfunc.modifiers |= CCodeModifiers.STATIC; + source_type_member_declaration.append (cfunc.copy ()); } - var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ())); + var block = new CCodeBlock (); + cfunc.block = block; - ccall.add_argument (new CCodeIdentifier ("self")); + var cdecl = new CCodeDeclaration ("DBusMessage*"); + cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("reply", new CCodeConstant ("NULL"))); + block.add_statement (cdecl); - foreach (FormalParameter param in m.get_parameters ()) { - var array_type = param.parameter_type as ArrayType; - if (array_type != null) { - if (param.direction == ParameterDirection.IN) { - if (array_type.element_type.data_type == string_type.data_type) { - ccall.add_argument (new CCodeIdentifier (param.name)); - if (!m.no_array_length) { - var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length")); - cstrvlen.add_argument (new CCodeIdentifier (param.name)); - ccall.add_argument (cstrvlen); - } - } else if (dbus_use_ptr_array (array_type)) { - ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_%s".printf (param.name)), "pdata")); - if (!m.no_array_length) { - ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_%s".printf (param.name)), "len")); - } - } else { - ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_%s".printf (param.name)), "data")); - if (!m.no_array_length) { - ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_%s".printf (param.name)), "len")); - } - } - } else { - if (array_type.element_type.data_type != string_type.data_type) { - var cdecl = new CCodeDeclaration (param.parameter_type.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator (param.name)); - block.add_statement (cdecl); + CCodeIfStatement clastif = null; - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name))); - } else { - ccall.add_argument (new CCodeIdentifier (param.name)); - } + handle_method ("org.freedesktop.DBus.Introspectable", "Introspect", generate_dbus_introspect (sym), block, ref clastif); - if (!m.no_array_length) { - var len_cdecl = new CCodeDeclaration ("int"); - len_cdecl.add_declarator (new CCodeVariableDeclarator ("%s_length1".printf (param.name))); - block.add_statement (len_cdecl); + var dbus = sym.get_attribute ("DBus"); + if (dbus != null) { + string dbus_iface_name = dbus.get_string ("name"); + if (dbus_iface_name != null) { + handle_method ("org.freedesktop.DBus.Properties", "Get", generate_dbus_property_get_wrapper (sym, dbus_iface_name), block, ref clastif); + handle_method ("org.freedesktop.DBus.Properties", "Set", generate_dbus_property_set_wrapper (sym, dbus_iface_name), block, ref clastif); + handle_method ("org.freedesktop.DBus.Properties", "GetAll", generate_dbus_property_get_all_wrapper (sym, dbus_iface_name), block, ref clastif); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("%s_length1".printf (param.name)))); - } - } - } else if (param.parameter_type.get_type_signature ().has_prefix ("(")) { - // struct input or output parameters - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name))); - } else if (param.parameter_type.get_type_signature ().has_prefix ("a{")) { - // hash table output parameter - var type_args = param.parameter_type.get_type_arguments (); - var value_type = type_args.get (1); - if (value_type.get_type_signature ().has_prefix ("(")) { - // values are structs - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name))); - } else { - ccall.add_argument (new CCodeIdentifier (param.name)); - } - } else { - ccall.add_argument (new CCodeIdentifier (param.name)); + handle_methods (sym, dbus_iface_name, block, ref clastif); } } - CCodeExpression expr; - if (m.return_type is VoidType) { - expr = ccall; - } else { - var array_type = m.return_type as ArrayType; - if (array_type != null) { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result_length1"))); - if (array_type.element_type.data_type != string_type.data_type) { - expr = new CCodeAssignment (new CCodeIdentifier ("result"), ccall); - } else { - expr = new CCodeAssignment (new CCodeIdentifier ("*result"), ccall); - } - } else if (m.return_type.get_type_signature ().has_prefix ("a{")) { - // hash table output parameter - var type_args = m.return_type.get_type_arguments (); - var value_type = type_args.get (1); - if (value_type.get_type_signature ().has_prefix ("(")) { - // values are structs - expr = new CCodeAssignment (new CCodeIdentifier ("result"), ccall); - } else { - expr = new CCodeAssignment (new CCodeIdentifier ("*result"), ccall); + var replyblock = new CCodeBlock (); + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_connection_send")); + ccall.add_argument (new CCodeIdentifier ("connection")); + ccall.add_argument (new CCodeIdentifier ("reply")); + ccall.add_argument (new CCodeConstant ("NULL")); + replyblock.add_statement (new CCodeExpressionStatement (ccall)); + ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_message_unref")); + ccall.add_argument (new CCodeIdentifier ("reply")); + replyblock.add_statement (new CCodeExpressionStatement (ccall)); + replyblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED"))); + + var cif = new CCodeIfStatement (new CCodeIdentifier ("reply"), replyblock); + block.add_statement (cif); + clastif = cif; + + var cl = sym as Class; + if (cl != null) { + foreach (DataType base_type in cl.get_base_types ()) { + var base_obj_type = base_type as ObjectType; + if (type_implements_dbus_interface (base_obj_type.type_symbol)) { + var base_call = new CCodeFunctionCall (new CCodeIdentifier (base_obj_type.type_symbol.get_lower_case_cprefix () + "dbus_message")); + base_call.add_argument (new CCodeIdentifier ("connection")); + base_call.add_argument (new CCodeIdentifier ("message")); + base_call.add_argument (new CCodeIdentifier ("object")); + + var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, base_call, new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED")); + + var base_block = new CCodeBlock (); + base_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_HANDLED"))); + + cif = new CCodeIfStatement (ccheck, base_block); + clastif.false_statement = cif; + + clastif = cif; } - } else { - expr = new CCodeAssignment (new CCodeIdentifier ("*result"), ccall); } } - if (m.get_error_types ().size > 0) { - ccall.add_argument (new CCodeIdentifier ("error")); + var retblock = new CCodeBlock (); + retblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("DBUS_HANDLER_RESULT_NOT_YET_HANDLED"))); + clastif.false_statement = retblock; + + source_type_member_definition.append (cfunc); + } + + CCodeExpression get_vtable (ObjectType object_type) { + var sym = object_type.type_symbol; + + var vtable = new CCodeInitializerList (); + vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_register_object")); + + generate_register_function (object_type); + + var cdecl = new CCodeDeclaration ("const _DBusObjectVTable"); + cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("_" + sym.get_lower_case_cprefix () + "dbus_vtable", vtable)); + cdecl.modifiers = CCodeModifiers.STATIC; + source_constant_declaration.append (cdecl); + + return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_vtable"); + } + + CCodeExpression get_path_vtable (ObjectType object_type) { + var sym = object_type.type_symbol; + + var vtable = new CCodeInitializerList (); + vtable.append (new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_unregister")); + vtable.append (new CCodeIdentifier (sym.get_lower_case_cprefix () + "dbus_message")); + + generate_unregister_function (object_type); + generate_message_function (object_type); + + var cdecl = new CCodeDeclaration ("const DBusObjectPathVTable"); + cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("_" + sym.get_lower_case_cprefix () + "dbus_path_vtable", vtable)); + cdecl.modifiers = CCodeModifiers.STATIC; + source_constant_declaration.append (cdecl); + + return new CCodeIdentifier ("_" + sym.get_lower_case_cprefix () + "dbus_path_vtable"); + } + + public override void visit_method_call (MethodCall expr) { + var mtype = expr.call.value_type as MethodType; + if (mtype == null || mtype.method_symbol.get_cname () != "dbus_g_connection_register_g_object") { + base.visit_method_call (expr); + return; } - block.add_statement (new CCodeExpressionStatement (expr)); + dbus_glib_h_needed = true; - foreach (FormalParameter param in m.get_parameters ()) { - if (param.direction == ParameterDirection.OUT) { - if (param.parameter_type.get_type_signature ().has_prefix ("(")) { - // struct output parameter - var st = (Struct) param.parameter_type.data_type; - var dbus_param = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("dbus_%s".printf (param.name))); - var st_expr = new CCodeIdentifier (param.name); - - transform_struct_to_value_array (block, st, dbus_param, st_expr, param.name); - } else if (param.parameter_type.get_type_signature ().has_prefix ("a{")) { - // hash table output parameter - var type_args = param.parameter_type.get_type_arguments (); - var value_type = type_args.get (1); - if (value_type.get_type_signature ().has_prefix ("(")) { - // values are structs - var st = (Struct) value_type.data_type; - var dbus_param = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("dbus_%s".printf (param.name))); - var table_expr = new CCodeIdentifier (param.name); - transform_struct_hash_table_to_value_array_hash_table (block, st, dbus_param, table_expr, param.name); - } - } - } + expr.accept_children (codegen); + + var ma = (MemberAccess) expr.call; + + var raw_conn = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_connection_get_connection")); + raw_conn.add_argument ((CCodeExpression) ma.inner.ccodenode); + + var args_it = expr.get_argument_list ().iterator (); + args_it.next (); + var path_arg = args_it.get (); + args_it.next (); + var obj_arg = args_it.get (); + + var cregister = new CCodeFunctionCall (new CCodeIdentifier ("_vala_dbus_register_object")); + cregister.add_argument (raw_conn); + cregister.add_argument ((CCodeExpression) path_arg.ccodenode); + cregister.add_argument ((CCodeExpression) obj_arg.ccodenode); + expr.ccodenode = cregister; + } + + bool type_implements_dbus_interface (ObjectTypeSymbol sym) { + var dbus = sym.get_attribute ("DBus"); + if (dbus != null) { + return true; } - if (!(m.return_type is VoidType)) { - var array_type = m.return_type as ArrayType; - if (array_type != null && array_type.element_type.data_type != string_type.data_type) { - var garray = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("dbus_result")); - - var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ())); - - if (dbus_use_ptr_array (array_type)) { - var array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_ptr_array_sized_new")); - array_construct.add_argument (new CCodeIdentifier ("result_length1")); - - block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (garray, array_construct))); - - var memcpy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy")); - memcpy_call.add_argument (new CCodeMemberAccess.pointer (garray, "pdata")); - memcpy_call.add_argument (new CCodeIdentifier ("result")); - memcpy_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeIdentifier ("result_length1"), sizeof_call)); - block.add_statement (new CCodeExpressionStatement (memcpy_call)); - - var len_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (garray, "len"), new CCodeIdentifier ("result_length1")); - block.add_statement (new CCodeExpressionStatement (len_assignment)); - } else { - var array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_array_new")); - array_construct.add_argument (new CCodeConstant ("TRUE")); - array_construct.add_argument (new CCodeConstant ("TRUE")); - array_construct.add_argument (sizeof_call); - - block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (garray, array_construct))); - - var cappend_call = new CCodeFunctionCall (new CCodeIdentifier ("g_array_append_vals")); - cappend_call.add_argument (garray); - cappend_call.add_argument (new CCodeIdentifier ("result")); - cappend_call.add_argument (new CCodeIdentifier ("result_length1")); - block.add_statement (new CCodeExpressionStatement (cappend_call)); - } - } else if (m.return_type.get_type_signature ().has_prefix ("a{")) { - // hash table output parameter - var type_args = m.return_type.get_type_arguments (); - var value_type = type_args.get (1); - if (value_type.get_type_signature ().has_prefix ("(")) { - // values are structs - var st = (Struct) value_type.data_type; - var dbus_param = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("dbus_result")); - var table_expr = new CCodeIdentifier ("result"); - transform_struct_hash_table_to_value_array_hash_table (block, st, dbus_param, table_expr, "result"); + var cl = sym as Class; + if (cl != null) { + foreach (DataType base_type in cl.get_base_types ()) { + var base_obj_type = base_type as ObjectType; + if (type_implements_dbus_interface (base_obj_type.type_symbol)) { + return true; } } } - var no_error = new CCodeBinaryExpression (CCodeBinaryOperator.OR, new CCodeIdentifier ("!error"), new CCodeIdentifier ("!*error")); - block.add_statement (new CCodeReturnStatement (no_error)); + return false; + } - // append to file + public override CCodeFragment register_dbus_info (ObjectTypeSymbol sym) { + CCodeFragment fragment = new CCodeFragment (); - source_type_member_declaration.append (function.copy ()); + if (!type_implements_dbus_interface (sym)) { + return fragment; + } - function.block = block; - source_type_member_definition.append (function); + var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); + quark.add_argument (new CCodeConstant ("\"DBusObjectVTable\"")); - return wrapper_name; + var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata")); + set_qdata.add_argument (new CCodeIdentifier (sym.get_upper_case_cname ("TYPE_"))); + set_qdata.add_argument (quark); + set_qdata.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_vtable (new ObjectType (sym))), "void*")); + + fragment.append (new CCodeExpressionStatement (set_qdata)); + + return fragment; } } diff --git a/gobject/valagsignalmodule.vala b/gobject/valagsignalmodule.vala index c4fc54b85..619ed2e09 100644 --- a/gobject/valagsignalmodule.vala +++ b/gobject/valagsignalmodule.vala @@ -382,11 +382,7 @@ public class Vala.GSignalModule : GObjectModule { csignew.add_argument (new CCodeConstant ("%d".printf (params_len))); foreach (FormalParameter param in params) { - if (type.get_attribute ("DBus") != null) { - // workaround for dbus-glib based D-Bus servers - // drop when bug 560034 has been fixed - csignew.add_argument (get_dbus_g_type (param.parameter_type)); - } else if (param.parameter_type.is_array ()) { + if (param.parameter_type.is_array ()) { if (((ArrayType) param.parameter_type).element_type.data_type == string_type.data_type) { csignew.add_argument (new CCodeConstant ("G_TYPE_STRV")); } else { diff --git a/vapi/dbus-glib-1.vapi b/vapi/dbus-glib-1.vapi index 00901344c..780045308 100644 --- a/vapi/dbus-glib-1.vapi +++ b/vapi/dbus-glib-1.vapi @@ -125,6 +125,12 @@ namespace DBus { public ObjectPath (string path); } + [CCode (cname = "char", const_cname = "const char", copy_function = "g_strdup", free_function = "g_free", cheader_filename = "stdlib.h,string.h,glib.h", type_id = "DBUS_TYPE_G_OBJECT_PATH", marshaller_type_name = "STRING", get_value_function = "g_value_get_string", set_value_function = "g_value_set_string")] + public class BusName : string { + [CCode (cname = "g_strdup")] + public BusName (string bus_name); + } + [CCode (cname = "DBusGProxyCallNotify")] public delegate void ProxyCallNotify (Object obj, ProxyCall call_id);