summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2014-03-18 18:44:13 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2014-03-27 15:59:19 +0000
commit63e329ee90820f9d75bd9d2ecf3335cdbd4681bc (patch)
treef10cae669cf84e9a37c1d09f1b00a4d76d6c0b5a
parent1c94485115cf0f71dbfa0d5d44cb66c6b776007d (diff)
Sync codegen from telepathy-glib gdbus branch
-rw-r--r--tools/c-constants-gen.py8
-rw-r--r--tools/doc-generator.xsl2
-rw-r--r--tools/glib-client-gen.py830
-rw-r--r--tools/glib-errors-check-gen.py1
-rw-r--r--tools/glib-ginterface-gen.py371
-rw-r--r--tools/libglibcodegen.py287
-rw-r--r--tools/libtpcodegen.py10
7 files changed, 734 insertions, 775 deletions
diff --git a/tools/c-constants-gen.py b/tools/c-constants-gen.py
index a08afee06..2b92dc6d9 100644
--- a/tools/c-constants-gen.py
+++ b/tools/c-constants-gen.py
@@ -130,13 +130,6 @@ extern "C" {
*
* 1 higher than the highest valid value of #%(mixed-name)s.
*/
-
-/**
- * NUM_%(upper-prefix)s%(upper-plural)s: (skip)
- *
- * 1 higher than the highest valid value of #%(mixed-name)s.
- * In new code, use %(upper-prefix)sNUM_%(upper-plural)s instead.
- */
""" % {'mixed-name' : (self.prefix + name).replace('_', ''),
'upper-prefix' : self.prefix.upper(),
'upper-plural' : name_plural.upper(),
@@ -144,7 +137,6 @@ extern "C" {
self.write("""\
#define %(upper-prefix)sNUM_%(upper-plural)s (%(last-val)s+1)
-#define NUM_%(upper-prefix)s%(upper-plural)s %(upper-prefix)sNUM_%(upper-plural)s
""" % {'mixed-name' : (self.prefix + name).replace('_', ''),
'upper-prefix' : self.prefix.upper(),
diff --git a/tools/doc-generator.xsl b/tools/doc-generator.xsl
index 90090d290..76fc96964 100644
--- a/tools/doc-generator.xsl
+++ b/tools/doc-generator.xsl
@@ -276,7 +276,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
<xsl:when test="tp:property">
<h2 xmlns="http://www.w3.org/1999/xhtml">Telepathy Properties:</h2>
<p xmlns="http://www.w3.org/1999/xhtml">Accessed using the
- <a href="#im.telepathy1.Properties">Telepathy
+ <a href="#org.freedesktop.Telepathy.Properties">Telepathy
Properties</a> interface.</p>
<dl xmlns="http://www.w3.org/1999/xhtml">
<xsl:apply-templates select="tp:property"/>
diff --git a/tools/glib-client-gen.py b/tools/glib-client-gen.py
index a0fecf083..bc117c5d8 100644
--- a/tools/glib-client-gen.py
+++ b/tools/glib-client-gen.py
@@ -29,8 +29,8 @@ from getopt import gnu_getopt
from libtpcodegen import file_set_contents, key_by_name, u
from libglibcodegen import (Signature, type_to_gtype,
- get_docstring, xml_escape, get_deprecated, copy_into_gvalue)
-
+ get_docstring, xml_escape, get_deprecated,
+ value_getter)
NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
@@ -41,6 +41,8 @@ class Generator(object):
self.__header = []
self.__body = []
self.__docs = []
+ self.__reentrant_header = []
+ self.__reentrant_body = []
self.prefix_lc = prefix.lower()
self.prefix_uc = prefix.upper()
@@ -71,6 +73,8 @@ class Generator(object):
self.deprecation_attribute = opts.get('--deprecation-attribute',
'G_GNUC_DEPRECATED')
+ self.split_reentrants = opts.get('--split-reentrants', False)
+
self.guard = opts.get('--guard', None)
def h(self, s):
@@ -79,6 +83,12 @@ class Generator(object):
def b(self, s):
self.__body.append(s)
+ def rh(self, s):
+ self.__reentrant_header.append(s)
+
+ def rb(self, s):
+ self.__reentrant_body.append(s)
+
def d(self, s):
self.__docs.append(s)
@@ -103,7 +113,7 @@ class Generator(object):
arg_count = 0
args = []
- out_args = []
+ arg_sig = []
for arg in signal.getElementsByTagName('arg'):
name = arg.getAttribute('name')
@@ -118,11 +128,10 @@ class Generator(object):
info = type_to_gtype(type)
args.append((name, info, tp_type, arg))
+ arg_sig.append(type)
callback_name = ('%s_%s_signal_callback_%s'
% (self.prefix_lc, iface_lc, member_lc))
- collect_name = ('_%s_%s_collect_args_of_%s'
- % (self.prefix_lc, iface_lc, member_lc))
invoke_name = ('_%s_%s_invoke_callback_for_%s'
% (self.prefix_lc, iface_lc, member_lc))
@@ -172,98 +181,41 @@ class Generator(object):
self.h(' gpointer user_data, GObject *weak_object);')
- if args:
- self.b('static void')
- self.b('%s (DBusGProxy *proxy G_GNUC_UNUSED,' % collect_name)
-
- for arg in args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.b(' %s%s%s,' % (const, ctype, name))
-
- self.b(' TpProxySignalConnection *sc)')
- self.b('{')
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- self.b(' GValueArray *args = g_value_array_new (%d);' % len(args))
- self.b(' GValue blank = { 0 };')
- self.b(' guint i;')
- self.b('')
- self.b(' g_value_init (&blank, G_TYPE_INT);')
- self.b('')
- self.b(' for (i = 0; i < %d; i++)' % len(args))
- self.b(' g_value_array_append (args, &blank);')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
- self.b('')
-
- for i, arg in enumerate(args):
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' g_value_unset (args->values + %d);' % i)
- self.b(' g_value_init (args->values + %d, %s);' % (i, gtype))
-
- self.b(' ' + copy_into_gvalue('args->values + %d' % i,
- gtype, marshaller, name))
- self.b('')
-
- self.b(' tp_proxy_signal_connection_v0_take_results (sc, args);')
- self.b('}')
-
self.b('static void')
self.b('%s (TpProxy *tpproxy,' % invoke_name)
- self.b(' GError *error G_GNUC_UNUSED,')
- self.b(' GValueArray *args,')
+ self.b(' const GError *error G_GNUC_UNUSED,')
+ self.b(' GVariant *variant,')
self.b(' GCallback generic_callback,')
self.b(' gpointer user_data,')
self.b(' GObject *weak_object)')
self.b('{')
self.b(' %s callback =' % callback_name)
self.b(' (%s) generic_callback;' % callback_name)
+
+ if args:
+ self.b(' GValue args_val = G_VALUE_INIT;')
+ self.b(' GValueArray *args_va;')
+ self.b('')
+ self.b(' dbus_g_value_parse_g_variant (variant, &args_val);')
+ self.b(' args_va = g_value_get_boxed (&args_val);')
+
self.b('')
self.b(' if (callback != NULL)')
self.b(' callback (g_object_ref (tpproxy),')
- # FIXME: factor out into a function
for i, arg in enumerate(args):
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
- if marshaller == 'BOXED':
- self.b(' g_value_get_boxed (args->values + %d),' % i)
- elif gtype == 'G_TYPE_STRING':
- self.b(' g_value_get_string (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UCHAR':
- self.b(' g_value_get_uchar (args->values + %d),' % i)
- elif gtype == 'G_TYPE_BOOLEAN':
- self.b(' g_value_get_boolean (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT':
- self.b(' g_value_get_uint (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT':
- self.b(' g_value_get_int (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT64':
- self.b(' g_value_get_uint64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT64':
- self.b(' g_value_get_int64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_DOUBLE':
- self.b(' g_value_get_double (args->values + %d),' % i)
- else:
- assert False, "Don't know how to get %s from a GValue" % gtype
+ getter = value_getter(gtype, marshaller)
+ self.b(' %s (args_va->values + %d),' % (getter, i))
self.b(' user_data,')
self.b(' weak_object);')
self.b('')
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- if len(args) > 0:
- self.b(' g_value_array_free (args);')
- else:
- self.b(' if (args != NULL)')
- self.b(' g_value_array_free (args);')
- self.b('')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
+ if args:
+ self.b(' g_value_unset (&args_val);')
self.b(' g_object_unref (tpproxy);')
self.b('}')
@@ -283,9 +235,11 @@ class Generator(object):
# emitted the 'invalidated' signal, or because the weakly referenced
# object has gone away.
- self.d('/**')
- self.d(' * %s_%s_connect_to_%s:'
+ connect_to = ('%s_%s_connect_to_%s'
% (self.prefix_lc, iface_lc, member_lc))
+
+ self.d('/**')
+ self.d(' * %s:' % connect_to)
self.d(' * @proxy: %s' % self.proxy_doc)
self.d(' * @callback: Callback to be called when the signal is')
self.d(' * received')
@@ -310,8 +264,8 @@ class Generator(object):
self.d(' */')
self.d('')
- self.h('TpProxySignalConnection *%s_%s_connect_to_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
+ self.h('TpProxySignalConnection *%s (%sproxy,'
+ % (connect_to, self.proxy_arg))
self.h(' %s callback,' % callback_name)
self.h(' gpointer user_data,')
self.h(' GDestroyNotify destroy,')
@@ -320,43 +274,44 @@ class Generator(object):
self.h('')
self.b('TpProxySignalConnection *')
- self.b('%s_%s_connect_to_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
+ self.b('(%s) (%sproxy,' % (connect_to, self.proxy_arg))
self.b(' %s callback,' % callback_name)
self.b(' gpointer user_data,')
self.b(' GDestroyNotify destroy,')
self.b(' GObject *weak_object,')
self.b(' GError **error)')
self.b('{')
- self.b(' GType expected_types[%d] = {' % (len(args) + 1))
-
- for arg in args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' %s,' % gtype)
-
- self.b(' G_TYPE_INVALID };')
- self.b('')
- self.b(' g_return_val_if_fail (%s (proxy), NULL);'
- % self.proxy_assert)
self.b(' g_return_val_if_fail (callback != NULL, NULL);')
self.b('')
- self.b(' return tp_proxy_signal_connection_v0_new ((TpProxy *) proxy,')
+ self.b(' return tp_proxy_signal_connection_v1_new ((TpProxy *) proxy,')
self.b(' %s, \"%s\",' % (self.get_iface_quark(), member))
- self.b(' expected_types,')
-
- if args:
- self.b(' G_CALLBACK (%s),' % collect_name)
- else:
- self.b(' NULL, /* no args => no collector function */')
-
+ self.b(' G_VARIANT_TYPE ("(%s)"),' % ''.join(arg_sig))
self.b(' %s,' % invoke_name)
self.b(' G_CALLBACK (callback), user_data, destroy,')
self.b(' weak_object, error);')
self.b('}')
self.b('')
+ # Inline the type-check into the header file, so the object code
+ # doesn't depend on tp_channel_get_type() or whatever
+ self.h('#ifndef __GTK_DOC_IGNORE__')
+ self.h('static inline TpProxySignalConnection *')
+ self.h('_%s (%sproxy,' % (connect_to, self.proxy_arg))
+ self.h(' %s callback,' % callback_name)
+ self.h(' gpointer user_data,')
+ self.h(' GDestroyNotify destroy,')
+ self.h(' GObject *weak_object,')
+ self.h(' GError **error)')
+ self.h('{')
+ self.h(' g_return_val_if_fail (%s (proxy), NULL);'
+ % self.proxy_assert)
+ self.h(' return %s (proxy, callback, user_data,' % connect_to)
+ self.h(' destroy, weak_object, error);')
+ self.h('}')
+ self.h('#define %s(...) _%s (__VA_ARGS__)'
+ % (connect_to, connect_to))
+ self.h('#endif /* __GTK_DOC_IGNORE__ */')
+
def do_method(self, iface, method):
iface_lc = iface.lower()
@@ -372,6 +327,8 @@ class Generator(object):
ret_count = 0
in_args = []
out_args = []
+ in_sig = []
+ out_sig = []
for arg in method.getElementsByTagName('arg'):
name = arg.getAttribute('name')
@@ -396,6 +353,7 @@ class Generator(object):
if direction != 'out':
in_args.append((name, info, tp_type, arg))
else:
+ out_sig.append(type)
out_args.append((name, info, tp_type, arg))
# Async reply callback type
@@ -466,101 +424,19 @@ class Generator(object):
iface_lc,
member_lc)
- collect_callback = '_%s_%s_collect_callback_%s' % (self.prefix_lc,
- iface_lc,
- member_lc)
-
- # The callback called by dbus-glib; this ends the call and collects
- # the results into a GValueArray.
- self.b('static void')
- self.b('%s (DBusGProxy *proxy,' % collect_callback)
- self.b(' DBusGProxyCall *call,')
- self.b(' gpointer user_data)')
- self.b('{')
- self.b(' GError *error = NULL;')
-
- if len(out_args) > 0:
- self.b(' GValueArray *args;')
- self.b(' GValue blank = { 0 };')
- self.b(' guint i;')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- # "We handle variants specially; the caller is expected to
- # have already allocated storage for them". Thanks,
- # dbus-glib...
- if gtype == 'G_TYPE_VALUE':
- self.b(' GValue *%s = g_new0 (GValue, 1);' % name)
- else:
- self.b(' %s%s;' % (ctype, name))
-
- self.b('')
- self.b(' dbus_g_proxy_end_call (proxy, call, &error,')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- if gtype == 'G_TYPE_VALUE':
- self.b(' %s, %s,' % (gtype, name))
- else:
- self.b(' %s, &%s,' % (gtype, name))
-
- self.b(' G_TYPE_INVALID);')
-
- if len(out_args) == 0:
- self.b(' tp_proxy_pending_call_v0_take_results (user_data, error,'
- 'NULL);')
- else:
- self.b('')
- self.b(' if (error != NULL)')
- self.b(' {')
- self.b(' tp_proxy_pending_call_v0_take_results (user_data, error,')
- self.b(' NULL);')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
- if gtype == 'G_TYPE_VALUE':
- self.b(' g_free (%s);' % name)
-
- self.b(' return;')
- self.b(' }')
- self.b('')
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- self.b(' args = g_value_array_new (%d);' % len(out_args))
- self.b(' g_value_init (&blank, G_TYPE_INT);')
- self.b('')
- self.b(' for (i = 0; i < %d; i++)' % len(out_args))
- self.b(' g_value_array_append (args, &blank);')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
-
- for i, arg in enumerate(out_args):
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b('')
- self.b(' g_value_unset (args->values + %d);' % i)
- self.b(' g_value_init (args->values + %d, %s);' % (i, gtype))
-
- self.b(' ' + copy_into_gvalue('args->values + %d' % i,
- gtype, marshaller, name))
-
- self.b(' tp_proxy_pending_call_v0_take_results (user_data, '
- 'NULL, args);')
-
- self.b('}')
-
self.b('static void')
self.b('%s (TpProxy *self,' % invoke_callback)
- self.b(' GError *error,')
- self.b(' GValueArray *args,')
+ self.b(' const GError *error,')
+ self.b(' GVariant *args,')
self.b(' GCallback generic_callback,')
self.b(' gpointer user_data,')
self.b(' GObject *weak_object)')
self.b('{')
+
+ if out_args:
+ self.b(' GValue args_val = G_VALUE_INIT;')
+ self.b(' GValueArray *args_va;')
+
self.b(' %s callback = (%s) generic_callback;'
% (callback_name, callback_name))
self.b('')
@@ -580,48 +456,29 @@ class Generator(object):
self.b(' 0,')
self.b(' error, user_data, weak_object);')
- self.b(' g_error_free (error);')
self.b(' return;')
self.b(' }')
+ self.b('')
+
+ if out_args:
+ self.b(' dbus_g_value_parse_g_variant (args, &args_val);')
+ self.b(' args_va = g_value_get_boxed (&args_val);')
+ self.b('')
self.b(' callback ((%s) self,' % self.proxy_cls)
- # FIXME: factor out into a function
for i, arg in enumerate(out_args):
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
- if marshaller == 'BOXED':
- self.b(' g_value_get_boxed (args->values + %d),' % i)
- elif gtype == 'G_TYPE_STRING':
- self.b(' g_value_get_string (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UCHAR':
- self.b(' g_value_get_uchar (args->values + %d),' % i)
- elif gtype == 'G_TYPE_BOOLEAN':
- self.b(' g_value_get_boolean (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT':
- self.b(' g_value_get_uint (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT':
- self.b(' g_value_get_int (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT64':
- self.b(' g_value_get_uint64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT64':
- self.b(' g_value_get_int64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_DOUBLE':
- self.b(' g_value_get_double (args->values + %d),' % i)
- else:
- assert False, "Don't know how to get %s from a GValue" % gtype
+ getter = value_getter(gtype, marshaller)
+ self.b(' %s (args_va->values + %d),' % (getter, i))
self.b(' error, user_data, weak_object);')
- self.b('')
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- if len(out_args) > 0:
- self.b(' g_value_array_free (args);')
- else:
- self.b(' if (args != NULL)')
- self.b(' g_value_array_free (args);')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
+ if out_args:
+ self.b('')
+ self.b(' g_value_unset (&args_val);')
self.b('}')
self.b('')
@@ -638,13 +495,15 @@ class Generator(object):
# gpointer user_data,
# GDestroyNotify *destructor);
- self.h('TpProxyPendingCall *%s_%s_call_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
+ caller_name = ('%s_%s_call_%s'
+ % (self.prefix_lc, iface_lc, member_lc))
+
+ self.h('TpProxyPendingCall *%s (%sproxy,'
+ % (caller_name, self.proxy_arg))
self.h(' gint timeout_ms,')
self.d('/**')
- self.d(' * %s_%s_call_%s:'
- % (self.prefix_lc, iface_lc, member_lc))
+ self.d(' * %s:' % caller_name)
self.d(' * @proxy: the #TpProxy')
self.d(' * @timeout_ms: the timeout in milliseconds, or -1 to use the')
self.d(' * default')
@@ -692,8 +551,8 @@ class Generator(object):
self.d(' */')
self.d('')
- self.b('TpProxyPendingCall *\n%s_%s_call_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
+ self.b('TpProxyPendingCall *\n(%s) (%sproxy,'
+ % (caller_name, self.proxy_arg))
self.b(' gint timeout_ms,')
for arg in in_args:
@@ -716,97 +575,79 @@ class Generator(object):
self.b(' GDestroyNotify destroy,')
self.b(' GObject *weak_object)')
self.b('{')
- self.b(' GError *error = NULL;')
- self.b(' GQuark interface = %s;' % self.get_iface_quark())
- self.b(' DBusGProxy *iface;')
- self.b('')
- self.b(' g_return_val_if_fail (%s (proxy), NULL);'
- % self.proxy_assert)
- self.b(' g_return_val_if_fail (callback != NULL || '
- 'user_data == NULL, NULL);')
- self.b(' g_return_val_if_fail (callback != NULL || '
- 'destroy == NULL, NULL);')
- self.b(' g_return_val_if_fail (callback != NULL || '
- 'weak_object == NULL, NULL);')
- self.b('')
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- self.b(' iface = tp_proxy_borrow_interface_by_id (')
- self.b(' (TpProxy *) proxy,')
- self.b(' interface, &error);')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
+ self.b(' TpProxyPendingCall *ret;')
+ self.b(' GValue args_val = G_VALUE_INIT;')
self.b('')
- self.b(' if (iface == NULL)')
- self.b(' {')
- self.b(' if (callback != NULL)')
- self.b(' callback (proxy,')
+ self.b(' g_value_init (&args_val, '
+ 'dbus_g_type_get_struct ("GValueArray",')
- for arg in out_args:
+ for arg in in_args:
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
+ self.b(' %s,' % gtype)
- if pointer:
- self.b(' NULL,')
- else:
- self.b(' 0,')
-
- self.b(' error, user_data, weak_object);')
- self.b('')
- self.b(' if (destroy != NULL)')
- self.b(' destroy (user_data);')
- self.b('')
- self.b(' g_error_free (error);')
- self.b(' return NULL;')
- self.b(' }')
- self.b('')
- self.b(' if (callback == NULL)')
- self.b(' {')
- self.b(' dbus_g_proxy_call_no_reply (iface, "%s",' % member)
+ self.b(' G_TYPE_INVALID));')
+ self.b(' g_value_take_boxed (&args_val,')
+ self.b(' tp_value_array_build (%d,' % len(in_args))
for arg in in_args:
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
self.b(' %s, %s,' % (gtype, name))
- self.b(' G_TYPE_INVALID);')
- self.b(' return NULL;')
- self.b(' }')
- self.b(' else')
- self.b(' {')
- self.b(' TpProxyPendingCall *data;')
+ self.b(' G_TYPE_INVALID));')
self.b('')
- self.b(' data = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,')
- self.b(' interface, "%s", iface,' % member)
- self.b(' %s,' % invoke_callback)
- self.b(' G_CALLBACK (callback), user_data, destroy,')
- self.b(' weak_object, FALSE);')
- self.b(' tp_proxy_pending_call_v0_take_pending_call (data,')
- self.b(' dbus_g_proxy_begin_call_with_timeout (iface,')
- self.b(' "%s",' % member)
- self.b(' %s,' % collect_callback)
- self.b(' data,')
- self.b(' tp_proxy_pending_call_v0_completed,')
- self.b(' timeout_ms,')
+ self.b(' ret = tp_proxy_pending_call_v1_new ((TpProxy *) proxy,')
+ self.b(' timeout_ms,')
+ self.b(' %s,' % self.get_iface_quark())
+ self.b(' "%s",' % member)
+ self.b(' /* consume floating ref */')
+ self.b(' dbus_g_value_build_g_variant (&args_val),')
+ self.b(' G_VARIANT_TYPE ("(%s)"),' % (''.join(out_sig)))
+ self.b(' %s,' % invoke_callback)
+ self.b(' G_CALLBACK (callback),')
+ self.b(' user_data,')
+ self.b(' destroy,')
+ self.b(' weak_object);')
+ self.b(' g_value_unset (&args_val);')
+ self.b(' return ret;')
+ self.b('}')
+ self.b('')
+
+ # Inline the type-check into the header file, so the object code
+ # doesn't depend on tp_channel_get_type() or whatever
+ self.h('#ifndef __GTK_DOC_IGNORE__')
+ self.h('static inline TpProxyPendingCall *')
+ self.h('_%s (%sproxy,' % (caller_name, self.proxy_arg))
+ self.h(' gint timeout_ms,')
for arg in in_args:
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
-
const = pointer and 'const ' or ''
+ self.h(' %s%s%s,' % (const, ctype, name))
- self.b(' %s, %s,' % (gtype, name))
+ self.h(' %s callback,' % callback_name)
+ self.h(' gpointer user_data,')
+ self.h(' GDestroyNotify destroy,')
+ self.h(' GObject *weak_object)')
+ self.h('{')
+ self.h(' g_return_val_if_fail (%s (proxy), NULL);'
+ % self.proxy_assert)
+ self.h(' return %s (proxy, timeout_ms,' % caller_name)
- self.b(' G_TYPE_INVALID));')
- self.b('')
- self.b(' return data;')
- self.b(' }')
- self.b('}')
- self.b('')
+ for arg in in_args:
+ name, info, tp_type, elt = arg
+ self.h(' %s,' % name)
+
+ self.h(' callback, user_data, destroy, weak_object);')
+ self.h('}')
+ self.h('#define %s(...) _%s (__VA_ARGS__)'
+ % (caller_name, caller_name))
+ self.h('#endif /* __GTK_DOC_IGNORE__ */')
self.do_method_reentrant(method, iface_lc, member, member_lc,
- in_args, out_args, collect_callback)
+ in_args, out_args, out_sig)
# leave a gap for the end of the method
self.d('')
@@ -814,7 +655,7 @@ class Generator(object):
self.h('')
def do_method_reentrant(self, method, iface_lc, member, member_lc, in_args,
- out_args, collect_callback):
+ out_args, out_sig):
# Reentrant blocking calls
# Example:
# gboolean tp_cli_properties_interface_run_get_properties
@@ -826,96 +667,110 @@ class Generator(object):
# GMainLoop **loop);
run_method_name = '%s_%s_run_%s' % (self.prefix_lc, iface_lc, member_lc)
- if run_method_name not in self.reentrant_symbols:
+
+ b = h = d = None
+
+ if run_method_name in self.reentrant_symbols:
+ b = self.b
+ h = self.h
+ d = self.d
+ elif self.split_reentrants:
+ b = self.rb
+ h = self.rh
+ d = self.rb
+ else:
return
- self.b('typedef struct {')
- self.b(' GMainLoop *loop;')
- self.b(' GError **error;')
+ b('typedef struct {')
+ b(' GMainLoop *loop;')
+ b(' GError **error;')
for arg in out_args:
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
- self.b(' %s*%s;' % (ctype, name))
+ b(' %s*%s;' % (ctype, name))
- self.b(' unsigned success:1;')
- self.b(' unsigned completed:1;')
- self.b('} _%s_%s_run_state_%s;'
+ b(' unsigned success:1;')
+ b(' unsigned completed:1;')
+ b('} _%s_%s_run_state_%s;'
% (self.prefix_lc, iface_lc, member_lc))
reentrant_invoke = '_%s_%s_finish_running_%s' % (self.prefix_lc,
iface_lc,
member_lc)
- self.b('static void')
- self.b('%s (TpProxy *self G_GNUC_UNUSED,' % reentrant_invoke)
- self.b(' GError *error,')
- self.b(' GValueArray *args,')
- self.b(' GCallback unused G_GNUC_UNUSED,')
- self.b(' gpointer user_data G_GNUC_UNUSED,')
- self.b(' GObject *unused2 G_GNUC_UNUSED)')
- self.b('{')
- self.b(' _%s_%s_run_state_%s *state = user_data;'
+ b('static void')
+ b('%s (TpProxy *self G_GNUC_UNUSED,' % reentrant_invoke)
+ b(' const GError *error,')
+ b(' GVariant *args_variant,')
+ b(' GCallback dummy G_GNUC_UNUSED,')
+ b(' gpointer user_data,')
+ b(' GObject *weak_object G_GNUC_UNUSED)')
+ b('{')
+
+ if out_args:
+ b(' GValue args_val = G_VALUE_INIT;')
+ b(' GValueArray *args;')
+ b('')
+
+ b(' _%s_%s_run_state_%s *state = user_data;'
% (self.prefix_lc, iface_lc, member_lc))
- self.b('')
- self.b(' state->success = (error == NULL);')
- self.b(' state->completed = TRUE;')
- self.b(' g_main_loop_quit (state->loop);')
- self.b('')
- self.b(' if (error != NULL)')
- self.b(' {')
- self.b(' if (state->error != NULL)')
- self.b(' *state->error = error;')
- self.b(' else')
- self.b(' g_error_free (error);')
- self.b('')
- self.b(' return;')
- self.b(' }')
- self.b('')
+ b('')
+ b(' state->success = (error == NULL);')
+ b(' state->completed = TRUE;')
+ b(' g_main_loop_quit (state->loop);')
+ b('')
+ b(' if (error != NULL)')
+ b(' {')
+ b(' if (state->error != NULL)')
+ b(' *state->error = g_error_copy (error);')
+ b('')
+ b(' return;')
+ b(' }')
+ b('')
+
+ if out_args:
+ b(' dbus_g_value_parse_g_variant (args_variant, &args_val);')
+ b(' args = g_value_get_boxed (&args_val);')
for i, arg in enumerate(out_args):
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
- self.b(' if (state->%s != NULL)' % name)
+ b(' if (state->%s != NULL)' % name)
if marshaller == 'BOXED':
- self.b(' *state->%s = g_value_dup_boxed ('
+ b(' *state->%s = g_value_dup_boxed ('
'args->values + %d);' % (name, i))
elif marshaller == 'STRING':
- self.b(' *state->%s = g_value_dup_string '
+ b(' *state->%s = g_value_dup_string '
'(args->values + %d);' % (name, i))
elif marshaller in ('UCHAR', 'BOOLEAN', 'INT', 'UINT',
'INT64', 'UINT64', 'DOUBLE'):
- self.b(' *state->%s = g_value_get_%s (args->values + %d);'
+ b(' *state->%s = g_value_get_%s (args->values + %d);'
% (name, marshaller.lower(), i))
else:
assert False, "Don't know how to copy %s" % gtype
- self.b('')
+ b('')
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- if len(out_args) > 0:
- self.b(' g_value_array_free (args);')
- else:
- self.b(' if (args != NULL)')
- self.b(' g_value_array_free (args);')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
+ if out_args:
+ b(' g_value_unset (&args_val);')
- self.b('}')
- self.b('')
+ b('}')
+ b('')
if self.deprecate_reentrant:
- self.h('#ifndef %s' % self.deprecate_reentrant)
+ h('#ifndef %s' % self.deprecate_reentrant)
- self.h('gboolean %s (%sproxy,'
+ h('gboolean %s (%sproxy,'
% (run_method_name, self.proxy_arg))
- self.h(' gint timeout_ms,')
+ h(' gint timeout_ms,')
- self.d('/**')
- self.d(' * %s:' % run_method_name)
- self.d(' * @proxy: %s' % self.proxy_doc)
- self.d(' * @timeout_ms: Timeout in milliseconds, or -1 for default')
+ d('/**')
+ d(' * %s:' % run_method_name)
+ d(' * @proxy: %s' % self.proxy_doc)
+ d(' * @timeout_ms: Timeout in milliseconds, or -1 for default')
for arg in in_args:
name, info, tp_type, elt = arg
@@ -926,47 +781,47 @@ class Generator(object):
if ctype == 'guint ' and tp_type != '':
docs += ' (#%s)' % ('Tp' + tp_type.replace('_', ''))
- self.d(' * @%s: Used to pass an \'in\' argument: %s'
+ d(' * @%s: Used to pass an \'in\' argument: %s'
% (name, docs))
for arg in out_args:
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
- self.d(' * @%s: Used to return an \'out\' argument if %%TRUE is '
+ d(' * @%s: Used to return an \'out\' argument if %%TRUE is '
'returned: %s'
% (name, xml_escape(get_docstring(elt) or '(Undocumented)')))
- self.d(' * @error: If not %NULL, used to return errors if %FALSE ')
- self.d(' * is returned')
- self.d(' * @loop: If not %NULL, set before re-entering ')
- self.d(' * the main loop, to point to a #GMainLoop ')
- self.d(' * which can be used to cancel this call with ')
- self.d(' * g_main_loop_quit(), causing a return of ')
- self.d(' * %FALSE with @error set to %TP_DBUS_ERROR_CANCELLED')
- self.d(' *')
- self.d(' * Call the method %s and run the main loop' % member)
- self.d(' * until it returns. Before calling this method, you must')
- self.d(' * add a reference to any borrowed objects you need to keep,')
- self.d(' * and generally ensure that everything is in a consistent')
- self.d(' * state.')
- self.d(' *')
- self.d(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)'))
- self.d(' *')
- self.d(' * Returns: TRUE on success, FALSE and sets @error on error')
+ d(' * @error: If not %NULL, used to return errors if %FALSE ')
+ d(' * is returned')
+ d(' * @loop: If not %NULL, set before re-entering ')
+ d(' * the main loop, to point to a #GMainLoop ')
+ d(' * which can be used to cancel this call with ')
+ d(' * g_main_loop_quit(), causing a return of ')
+ d(' * %FALSE with @error set to %TP_DBUS_ERROR_CANCELLED')
+ d(' *')
+ d(' * Call the method %s and run the main loop' % member)
+ d(' * until it returns. Before calling this method, you must')
+ d(' * add a reference to any borrowed objects you need to keep,')
+ d(' * and generally ensure that everything is in a consistent')
+ d(' * state.')
+ d(' *')
+ d(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)'))
+ d(' *')
+ d(' * Returns: TRUE on success, FALSE and sets @error on error')
deprecated = method.getElementsByTagName('tp:deprecated')
if deprecated:
d = deprecated[0]
- self.d(' *')
- self.d(' * Deprecated: %s' % xml_escape(get_deprecated(d)))
+ d(' *')
+ d(' * Deprecated: %s' % xml_escape(get_deprecated(d)))
- self.d(' */')
- self.d('')
+ d(' */')
+ d('')
- self.b('gboolean\n%s (%sproxy,'
+ b('gboolean\n%s (%sproxy,'
% (run_method_name, self.proxy_arg))
- self.b(' gint timeout_ms,')
+ b(' gint timeout_ms,')
for arg in in_args:
name, info, tp_type, elt = arg
@@ -974,113 +829,102 @@ class Generator(object):
const = pointer and 'const ' or ''
- self.h(' %s%s%s,' % (const, ctype, name))
- self.b(' %s%s%s,' % (const, ctype, name))
+ h(' %s%s%s,' % (const, ctype, name))
+ b(' %s%s%s,' % (const, ctype, name))
for arg in out_args:
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
- self.h(' %s*%s,' % (ctype, name))
- self.b(' %s*%s,' % (ctype, name))
+ h(' %s*%s,' % (ctype, name))
+ b(' %s*%s,' % (ctype, name))
- self.h(' GError **error,')
+ h(' GError **error,')
if self.deprecate_reentrant:
- self.h(' GMainLoop **loop) %s;' % self.deprecation_attribute)
- self.h('#endif /* not %s */' % self.deprecate_reentrant)
+ h(' GMainLoop **loop) %s;' % self.deprecation_attribute)
+ h('#endif /* not %s */' % self.deprecate_reentrant)
else:
- self.h(' GMainLoop **loop);')
+ h(' GMainLoop **loop);')
- self.h('')
+ h('')
- self.b(' GError **error,')
- self.b(' GMainLoop **loop)')
- self.b('{')
- self.b(' DBusGProxy *iface;')
- self.b(' GQuark interface = %s;' % self.get_iface_quark())
- self.b(' TpProxyPendingCall *pc;')
- self.b(' _%s_%s_run_state_%s state = {'
+ b(' GError **error,')
+ b(' GMainLoop **loop)')
+ b('{')
+ b(' GQuark interface = %s;' % self.get_iface_quark())
+ b(' TpProxyPendingCall *pc;')
+ b(' _%s_%s_run_state_%s state = {'
% (self.prefix_lc, iface_lc, member_lc))
- self.b(' NULL /* loop */, error,')
+ b(' NULL /* loop */, error,')
for arg in out_args:
name, info, tp_type, elt = arg
- self.b(' %s,' % name)
+ b(' %s,' % name)
- self.b(' FALSE /* completed */, FALSE /* success */ };')
- self.b('')
- self.b(' g_return_val_if_fail (%s (proxy), FALSE);'
- % self.proxy_assert)
- self.b('')
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- self.b(' iface = tp_proxy_borrow_interface_by_id')
- self.b(' ((TpProxy *) proxy, interface, error);')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
- self.b('')
- self.b(' if (iface == NULL)')
- self.b(' return FALSE;')
- self.b('')
- self.b(' state.loop = g_main_loop_new (NULL, FALSE);')
- self.b('')
- self.b(' pc = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,')
- self.b(' interface, "%s", iface,' % member)
- self.b(' %s,' % reentrant_invoke)
- self.b(' NULL, &state, NULL, NULL, TRUE);')
- self.b('')
- self.b(' if (loop != NULL)')
- self.b(' *loop = state.loop;')
- self.b('')
- self.b(' tp_proxy_pending_call_v0_take_pending_call (pc,')
- self.b(' dbus_g_proxy_begin_call_with_timeout (iface,')
- self.b(' "%s",' % member)
- self.b(' %s,' % collect_callback)
- self.b(' pc,')
- self.b(' tp_proxy_pending_call_v0_completed,')
- self.b(' timeout_ms,')
+ b(' FALSE /* completed */, FALSE /* success */ };')
+ b(' GValue args_val = G_VALUE_INIT;')
+ b('')
+ b(' g_value_init (&args_val, dbus_g_type_get_struct ("GValueArray",')
for arg in in_args:
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
+ b(' %s,' % gtype)
- const = pointer and 'const ' or ''
+ b(' G_TYPE_INVALID));')
- self.b(' %s, %s,' % (gtype, name))
+ b(' g_value_take_boxed (&args_val,')
+ b(' tp_value_array_build (%d,' % len(in_args))
- self.b(' G_TYPE_INVALID));')
- self.b('')
- self.b(' if (!state.completed)')
- self.b(' g_main_loop_run (state.loop);')
- self.b('')
- self.b(' if (!state.completed)')
- self.b(' tp_proxy_pending_call_cancel (pc);')
- self.b('')
- self.b(' if (loop != NULL)')
- self.b(' *loop = NULL;')
- self.b('')
- self.b(' g_main_loop_unref (state.loop);')
- self.b('')
- self.b(' return state.success;')
- self.b('}')
- self.b('')
-
- def do_signal_add(self, signal):
- marshaller_items = []
- gtypes = []
-
- for i in signal.getElementsByTagName('arg'):
- name = i.getAttribute('name')
- type = i.getAttribute('type')
- info = type_to_gtype(type)
- # type, GType, STRING, is a pointer
- gtypes.append(info[1])
+ for arg in in_args:
+ name, info, tp_type, elt = arg
+ ctype, gtype, marshaller, pointer = info
+ b(' %s, %s,' % (gtype, name))
- self.b(' dbus_g_proxy_add_signal (proxy, "%s",'
- % signal.getAttribute('name'))
- for gtype in gtypes:
- self.b(' %s,' % gtype)
- self.b(' G_TYPE_INVALID);')
+ b(' G_TYPE_INVALID));')
+ b('')
+ b(' g_return_val_if_fail (%s (proxy), FALSE);'
+ % self.proxy_assert)
+ b('')
+ b(' if (!tp_proxy_check_interface_by_id')
+ b(' ((TpProxy *) proxy, interface, error))')
+ b(' return FALSE;')
+ b('')
+ b(' state.loop = g_main_loop_new (NULL, FALSE);')
+ b('')
+ b(' if (loop != NULL)')
+ b(' *loop = state.loop;')
+ b('')
+ b(' pc = tp_proxy_pending_call_v1_new ((TpProxy *) proxy,')
+ b(' timeout_ms,')
+ b(' interface,')
+ b(' "%s",' % member)
+ b(' /* consume floating ref */')
+ b(' dbus_g_value_build_g_variant (&args_val),')
+ b(' G_VARIANT_TYPE ("(%s)"),' % (''.join(out_sig)))
+ b(' %s,' % reentrant_invoke)
+ b(' (void *) 1, /* any non-NULL pointer */')
+ b(' &state,')
+ b(' NULL,')
+ b(' NULL);')
+ b(' g_value_unset (&args_val);')
+ b('')
+ b(' if (!state.completed)')
+ b(' g_main_loop_run (state.loop);')
+ b('')
+ b(' if (!state.completed)')
+ b(' tp_proxy_pending_call_cancel (pc);')
+ b('')
+ b(' if (loop != NULL)')
+ b(' *loop = NULL;')
+ b('')
+ b(' g_main_loop_unref (state.loop);')
+ b('')
+ b(' return state.success;')
+ b('}')
+ b('')
def do_interface(self, node):
ifaces = node.getElementsByTagName('interface')
@@ -1097,24 +941,6 @@ class Generator(object):
signals = node.getElementsByTagName('signal')
methods = node.getElementsByTagName('method')
- if signals:
- self.b('static inline void')
- self.b('%s_add_signals_for_%s (DBusGProxy *proxy)'
- % (self.prefix_lc, name.lower()))
- self.b('{')
-
- if self.tp_proxy_api >= (0, 7, 6):
- self.b(' if (!tp_proxy_dbus_g_proxy_claim_for_signal_adding '
- '(proxy))')
- self.b(' return;')
-
- for signal in signals:
- self.do_signal_add(signal)
-
- self.b('}')
- self.b('')
- self.b('')
-
for signal in signals:
self.do_signal(name, signal)
@@ -1137,6 +963,10 @@ class Generator(object):
self.b(' * confused by seeing function definitions, so mark it as: */')
self.b('/*<private_header>*/')
self.b('')
+ # if we're splitting out re-entrant things, we want them marked
+ # private too
+ self.rh('/*<private_header>*/')
+ self.rb('/*<private_header>*/')
nodes = self.dom.getElementsByTagName('node')
nodes.sort(key=key_by_name)
@@ -1144,47 +974,6 @@ class Generator(object):
for node in nodes:
self.do_interface(node)
- if self.group is not None:
-
- self.b('/*')
- self.b(' * %s_%s_add_signals:' % (self.prefix_lc, self.group))
- self.b(' * @self: the #TpProxy')
- self.b(' * @quark: a quark whose string value is the interface')
- self.b(' * name whose signals should be added')
- self.b(' * @proxy: the D-Bus proxy to which to add the signals')
- self.b(' * @unused: not used for anything')
- self.b(' *')
- self.b(' * Tell dbus-glib that @proxy has the signatures of all')
- self.b(' * signals on the given interface, if it\'s one we')
- self.b(' * support.')
- self.b(' *')
- self.b(' * This function should be used as a signal handler for')
- self.b(' * #TpProxy::interface-added.')
- self.b(' */')
- self.b('static void')
- self.b('%s_%s_add_signals (TpProxy *self G_GNUC_UNUSED,'
- % (self.prefix_lc, self.group))
- self.b(' guint quark,')
- self.b(' DBusGProxy *proxy,')
- self.b(' gpointer unused G_GNUC_UNUSED)')
-
- self.b('{')
-
- for node in nodes:
- iface = node.getElementsByTagName('interface')[0]
- self.iface_dbus = iface.getAttribute('name')
- signals = node.getElementsByTagName('signal')
- if not signals:
- continue
- name = node.getAttribute('name').replace('/', '').lower()
- self.iface_uc = name.upper()
- self.b(' if (quark == %s)' % self.get_iface_quark())
- self.b(' %s_add_signals_for_%s (proxy);'
- % (self.prefix_lc, name))
-
- self.b('}')
- self.b('')
-
self.h('G_END_DECLS')
self.h('')
@@ -1192,6 +981,10 @@ class Generator(object):
self.h('#endif /* defined (%s) */' % self.guard)
self.h('')
+ if self.split_reentrants:
+ file_set_contents(self.basename + '-reentrant-body.h', u('\n').join(self.__reentrant_body).encode('utf-8'))
+ file_set_contents(self.basename + '-reentrant.h', u('\n').join(self.__reentrant_header).encode('utf-8'))
+
file_set_contents(self.basename + '.h', u('\n').join(self.__header).encode('utf-8'))
file_set_contents(self.basename + '-body.h', u('\n').join(self.__body).encode('utf-8'))
file_set_contents(self.basename + '-gtk-doc.h', u('\n').join(self.__docs).encode('utf-8'))
@@ -1205,7 +998,8 @@ if __name__ == '__main__':
['group=', 'subclass=', 'subclass-assert=',
'iface-quark-prefix=', 'tp-proxy-api=',
'generate-reentrant=', 'deprecate-reentrant=',
- 'deprecation-attribute=', 'guard='])
+ 'deprecation-attribute=', 'guard=',
+ 'split-reentrants='])
opts = {}
diff --git a/tools/glib-errors-check-gen.py b/tools/glib-errors-check-gen.py
index fad261ece..3cc8a5afb 100644
--- a/tools/glib-errors-check-gen.py
+++ b/tools/glib-errors-check-gen.py
@@ -17,7 +17,6 @@ class Generator(object):
print(' GEnumValue *value_by_name;')
print(' GEnumValue *value_by_nick;')
print('')
- print(' g_type_init ();')
print(' klass = g_type_class_ref (TP_TYPE_ERROR);')
for error in self.errors.getElementsByTagNameNS(NS_TP, 'error'):
diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py
index c0ce20ddc..d5a786f35 100644
--- a/tools/glib-ginterface-gen.py
+++ b/tools/glib-ginterface-gen.py
@@ -26,28 +26,19 @@ import sys
import os.path
import xml.dom.minidom
-from libtpcodegen import file_set_contents, key_by_name, u
-from libglibcodegen import Signature, type_to_gtype, \
- NS_TP, dbus_gutils_wincaps_to_uscore
+from libtpcodegen import file_set_contents, key_by_name, u, get_emits_changed
+from libglibcodegen import (Signature, type_to_gtype,
+ NS_TP, dbus_gutils_wincaps_to_uscore, value_getter,
+ GDBusInterfaceInfo)
NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
-def get_emits_changed(node):
- try:
- return [
- annotation.getAttribute('value')
- for annotation in node.getElementsByTagName('annotation')
- if annotation.getAttribute('name') == 'org.freedesktop.DBus.Property.EmitsChangedSignal'
- ][0]
- except IndexError:
- return None
-
class Generator(object):
def __init__(self, dom, prefix, basename, signal_marshal_prefix,
headers, end_headers, not_implemented_func,
- allow_havoc):
+ allow_havoc, allow_single_include):
self.dom = dom
self.__header = []
self.__body = []
@@ -83,6 +74,7 @@ class Generator(object):
self.end_headers = end_headers
self.not_implemented_func = not_implemented_func
self.allow_havoc = allow_havoc
+ self.allow_single_include = allow_single_include
def h(self, s):
self.__header.append(s)
@@ -114,15 +106,9 @@ class Generator(object):
iface_emits_changed = get_emits_changed(interface)
- self.b('static const DBusGObjectInfo _%s%s_object_info;'
- % (self.prefix_, node_name_lc))
- self.b('')
-
methods = interface.getElementsByTagName('method')
signals = interface.getElementsByTagName('signal')
properties = interface.getElementsByTagName('property')
- # Don't put properties in dbus-glib glue
- glue_properties = []
self.b('struct _%s%sClass {' % (self.Prefix, node_name_mixed))
self.b(' GTypeInterface parent_class;')
@@ -245,16 +231,75 @@ class Generator(object):
' (G_TYPE_INSTANCE_GET_INTERFACE((obj), %s, %sClass))'
% (self.PREFIX_, node_name_uc, gtype, classname))
self.h('')
- self.h('')
base_init_code = []
+ method_call_code = []
for method in methods:
- self.do_method(method)
+ self.do_method(method, method_call_code)
+
+ signal_table = [
+ 'static const gchar * const _gsignals_%s[] = {' %
+ self.node_name_lc
+ ]
for signal in signals:
- base_init_code.extend(self.do_signal(signal))
+ # we rely on this being in the same order as the interface info
+ self.do_signal(signal, in_base_init=base_init_code,
+ in_signal_table=signal_table)
+
+ signal_table.append(' NULL')
+ signal_table.append('};')
+ signal_table.append('')
+ for line in signal_table:
+ self.b(line)
+
+ # e.g. _interface_info_connection_interface_contact_info1
+ for line in GDBusInterfaceInfo(node_name, interface,
+ '_interface_info_%s' % node_name_lc).to_lines(linkage='static'):
+ self.b(line)
+ self.b('')
+ self.b('static void')
+ self.b('_method_call_%s (GDBusConnection *connection,' % node_name_lc)
+ self.b(' const gchar *sender,')
+ self.b(' const gchar *object_path,')
+ self.b(' const gchar *interface_name,')
+ self.b(' const gchar *method_name,')
+ self.b(' GVariant *parameters,')
+ self.b(' GDBusMethodInvocation *invocation,')
+ self.b(' gpointer user_data)')
+ self.b('{')
+
+ for line in method_call_code:
+ self.b(line)
+
+ # Deliberately not using self.not_implemented_func here so that callers
+ # can distinguish between "you called Protocol.NormalizeContact() but
+ # that isn't implemented here" and "you called Protocol.Badger()
+ # which isn't even in the spec" if required.
+ self.b(' g_dbus_method_invocation_return_error (invocation,')
+ self.b(' G_DBUS_ERROR,')
+ self.b(' G_DBUS_ERROR_UNKNOWN_METHOD,')
+ self.b(' "Method not implemented");')
+ self.b('}')
+ self.b('')
+ self.b('static const GDBusInterfaceVTable _vtable_%s = {' %
+ node_name_lc)
+ self.b(' _method_call_%s,' % node_name_lc)
+ self.b(' NULL, /* get property */')
+ self.b(' NULL /* set property */')
+ self.b('};')
+ self.b('')
+ self.b('static const TpSvcInterfaceInfo _tp_interface_info_%s = {' %
+ node_name_lc)
+ self.b(' -1,')
+ self.b(' (GDBusInterfaceInfo *) &_interface_info_%s,' % node_name_lc)
+ self.b(' (GDBusInterfaceVTable *) &_vtable_%s,' % node_name_lc)
+ self.b(' (gchar **) _gsignals_%s' % node_name_lc)
+ self.b(' /* _future is implicitly zero-filled */')
+ self.b('};')
+ self.b('')
self.b('static inline void')
self.b('%s%s_base_init_once (gpointer klass G_GNUC_UNUSED)'
% (self.prefix_, node_name_lc))
@@ -295,13 +340,6 @@ class Generator(object):
self.b(' { 0, properties, NULL, NULL };')
self.b('')
-
- self.b(' dbus_g_object_type_install_info (%s%s_get_type (),'
- % (self.prefix_, node_name_lc))
- self.b(' &_%s%s_object_info);'
- % (self.prefix_, node_name_lc))
- self.b('')
-
if properties:
self.b(' interface.dbus_interface = g_quark_from_static_string '
'("%s");' % self.iface_name)
@@ -317,6 +355,10 @@ class Generator(object):
self.b('')
+ self.b(' tp_svc_interface_set_dbus_interface_info (%s,'
+ % (self.current_gtype))
+ self.b(' &_tp_interface_info_%s);' % node_name_lc)
+
for s in base_init_code:
self.b(s)
self.b('}')
@@ -338,100 +380,10 @@ class Generator(object):
self.h('')
- self.b('static const DBusGMethodInfo _%s%s_methods[] = {'
- % (self.prefix_, node_name_lc))
-
- method_blob, offsets = self.get_method_glue(methods)
-
- for method, offset in zip(methods, offsets):
- self.do_method_glue(method, offset)
-
- if len(methods) == 0:
- # empty arrays are a gcc extension, so put in a dummy member
- self.b(" { NULL, NULL, 0 }")
-
- self.b('};')
- self.b('')
-
- self.b('static const DBusGObjectInfo _%s%s_object_info = {'
- % (self.prefix_, node_name_lc))
- self.b(' 0,') # version
- self.b(' _%s%s_methods,' % (self.prefix_, node_name_lc))
- self.b(' %d,' % len(methods))
- self.b('"' + method_blob.replace('\0', '\\0') + '",')
- self.b('"' + self.get_signal_glue(signals).replace('\0', '\\0') + '",')
- self.b('"' +
- self.get_property_glue(glue_properties).replace('\0', '\\0') +
- '",')
- self.b('};')
- self.b('')
-
self.node_name_mixed = None
self.node_name_lc = None
self.node_name_uc = None
- def get_method_glue(self, methods):
- info = []
- offsets = []
-
- for method in methods:
- offsets.append(len(''.join(info)))
-
- info.append(self.iface_name + '\0')
- info.append(method.getAttribute('name') + '\0')
-
- info.append('A\0') # async
-
- counter = 0
- for arg in method.getElementsByTagName('arg'):
- out = arg.getAttribute('direction') == 'out'
-
- name = arg.getAttribute('name')
- if not name:
- assert out
- name = 'arg%u' % counter
- counter += 1
-
- info.append(name + '\0')
-
- if out:
- info.append('O\0')
- else:
- info.append('I\0')
-
- if out:
- info.append('F\0') # not const
- info.append('N\0') # not error or return
- info.append(arg.getAttribute('type') + '\0')
-
- info.append('\0')
-
- return ''.join(info) + '\0', offsets
-
- def do_method_glue(self, method, offset):
- lc_name = method.getAttribute('tp:name-for-bindings')
- if method.getAttribute('name') != lc_name.replace('_', ''):
- raise AssertionError('Method %s tp:name-for-bindings (%s) does '
- 'not match' % (method.getAttribute('name'), lc_name))
- lc_name = lc_name.lower()
-
- marshaller = 'g_cclosure_marshal_generic'
- wrapper = self.prefix_ + self.node_name_lc + '_' + lc_name
-
- self.b(" { (GCallback) %s, %s, %d }," % (wrapper, marshaller, offset))
-
- def get_signal_glue(self, signals):
- info = []
-
- for signal in signals:
- info.append(self.iface_name)
- info.append(signal.getAttribute('name'))
-
- return '\0'.join(info) + '\0\0'
-
- # the implementation can be the same
- get_property_glue = get_signal_glue
-
def get_method_impl_names(self, method):
dbus_method_name = method.getAttribute('name')
@@ -445,11 +397,9 @@ class Generator(object):
class_member_name)
return (stub_name + '_impl', class_member_name + '_cb')
- def do_method(self, method):
+ def do_method(self, method, method_call_code):
assert self.node_name_mixed is not None
- in_class = []
-
# Examples refer to Thing.DoStuff (su) -> ii
# DoStuff
@@ -461,20 +411,20 @@ class Generator(object):
'not match' % (dbus_method_name, class_member_name))
class_member_name = class_member_name.lower()
- # void tp_svc_thing_do_stuff (TpSvcThing *, const char *, guint,
- # DBusGMethodInvocation *);
+ # tp_svc_thing_do_stuff (signature of GDBusInterfaceMethodCallFunc)
stub_name = (self.prefix_ + self.node_name_lc + '_' +
class_member_name)
# typedef void (*tp_svc_thing_do_stuff_impl) (TpSvcThing *,
- # const char *, guint, DBusGMethodInvocation);
+ # const char *, guint, GDBusMethodInvocation);
impl_name = stub_name + '_impl'
- # void tp_svc_thing_return_from_do_stuff (DBusGMethodInvocation *,
+ # void tp_svc_thing_return_from_do_stuff (GDBusMethodInvocation *,
# gint, gint);
ret_name = (self.prefix_ + self.node_name_lc + '_return_from_' +
class_member_name)
# Gather arguments
in_args = []
+ in_arg_value_getters = []
out_args = []
for i in method.getElementsByTagName('arg'):
name = i.getAttribute('name')
@@ -498,9 +448,22 @@ class Generator(object):
struct = (ctype, name)
if direction == 'in':
- in_args.append(struct)
+ in_args.append((ctype, name))
+ in_arg_value_getters.append(value_getter(gtype, marshaller))
else:
- out_args.append(struct)
+ out_args.append((gtype, ctype, name))
+
+ # bits of _method_call_myiface
+ method_call_code.extend([
+ ' if (g_strcmp0 (method_name, "%s") == 0)' % dbus_method_name,
+ ' {',
+ ' %s (connection, sender, object_path, interface_name, ' %
+ stub_name,
+ ' method_name, parameters, invocation, user_data);',
+ ' return;',
+ ' }',
+ ''
+ ])
# Implementation type declaration (in header, docs separated)
self.d('/**')
@@ -509,7 +472,7 @@ class Generator(object):
for (ctype, name) in in_args:
self.d(' * @%s: %s (FIXME, generate documentation)'
% (name, ctype))
- self.d(' * @context: Used to return values or throw an error')
+ self.d(' * @invocation: Used to return values or throw an error')
self.d(' *')
self.d(' * The signature of an implementation of the D-Bus method')
self.d(' * %s on interface %s.' % (dbus_method_name, self.iface_name))
@@ -519,37 +482,59 @@ class Generator(object):
% (impl_name, self.Prefix, self.node_name_mixed))
for (ctype, name) in in_args:
self.h(' %s%s,' % (ctype, name))
- self.h(' DBusGMethodInvocation *context);')
-
- # Class member (in class definition)
- in_class.append(' %s %s;' % (impl_name, class_member_name))
+ self.h(' GDBusMethodInvocation *invocation);')
# Stub definition (in body only - it's static)
self.b('static void')
- self.b('%s (%s%s *self,'
- % (stub_name, self.Prefix, self.node_name_mixed))
- for (ctype, name) in in_args:
- self.b(' %s%s,' % (ctype, name))
- self.b(' DBusGMethodInvocation *context)')
+ self.b('%s (GDBusConnection *connection,' % stub_name)
+ self.b(' const gchar *sender,')
+ self.b(' const gchar *object_path,')
+ self.b(' const gchar *interface_name,')
+ self.b(' const gchar *method_name,')
+ self.b(' GVariant *parameters,')
+ self.b(' GDBusMethodInvocation *invocation,')
+ self.b(' gpointer user_data)')
self.b('{')
- self.b(' %s impl = (%s%s_GET_CLASS (self)->%s_cb);'
- % (impl_name, self.PREFIX_, self.node_name_uc, class_member_name))
+ self.b(' %s%s *self = %s%s (user_data);'
+ % (self.Prefix, self.node_name_mixed, self.PREFIX_,
+ self.node_name_uc))
+ self.b(' %s%sClass *cls = %s%s_GET_CLASS (self);'
+ % (self.Prefix, self.node_name_mixed, self.PREFIX_,
+ self.node_name_uc))
+ self.b(' %s impl = cls->%s_cb;' % (impl_name, class_member_name))
self.b('')
self.b(' if (impl != NULL)')
- tmp = ['self'] + [name for (ctype, name) in in_args] + ['context']
+ tmp = ['self'] + [name for (ctype, name) in in_args] + ['invocation']
self.b(' {')
- self.b(' (impl) (%s);' % ',\n '.join(tmp))
+
+ if in_args:
+ self.b(' GValue args_val = G_VALUE_INIT;')
+ self.b(' GValueArray *va;')
+ self.b('')
+ self.b(' dbus_g_value_parse_g_variant (parameters, &args_val);')
+ self.b(' va = g_value_get_boxed (&args_val);')
+ self.b('')
+
+ self.b(' (impl) (self,')
+
+ for i, getter in enumerate(in_arg_value_getters):
+ self.b(' %s (va->values + %d),' % (getter, i))
+
+ self.b(' invocation);')
+
+ if in_args:
+ self.b(' g_value_unset (&args_val);')
+
self.b(' }')
self.b(' else')
self.b(' {')
if self.not_implemented_func:
- self.b(' %s (context);' % self.not_implemented_func)
+ self.b(' %s (invocation);' % self.not_implemented_func)
else:
- self.b(' GError e = { DBUS_GERROR, ')
- self.b(' DBUS_GERROR_UNKNOWN_METHOD,')
- self.b(' "Method not implemented" };')
- self.b('')
- self.b(' dbus_g_method_return_error (context, &e);')
+ self.b(' g_dbus_method_invocation_return_error (invocation,')
+ self.b(' G_DBUS_ERROR,')
+ self.b(' G_DBUS_ERROR_UNKNOWN_METHOD,')
+ self.b(' "Method not implemented");')
self.b(' }')
self.b('}')
self.b('')
@@ -581,44 +566,59 @@ class Generator(object):
self.b('}')
self.b('')
- # Return convenience function (static inline, in header)
+ # Return convenience function
self.d('/**')
self.d(' * %s:' % ret_name)
- self.d(' * @context: The D-Bus method invocation context')
- for (ctype, name) in out_args:
+ self.d(' * @invocation: The D-Bus method invocation context')
+ for (gtype, ctype, name) in out_args:
self.d(' * @%s: %s (FIXME, generate documentation)'
% (name, ctype))
self.d(' *')
- self.d(' * Return successfully by calling dbus_g_method_return().')
- self.d(' * This inline function exists only to provide type-safety.')
+ self.d(' * Return successfully by calling g_dbus_method_invocation_return_value().')
self.d(' */')
self.d('')
- tmp = (['DBusGMethodInvocation *context'] +
- [ctype + name for (ctype, name) in out_args])
- self.h('static inline')
- self.h('/* this comment is to stop gtkdoc realising this is static */')
+ tmp = (['GDBusMethodInvocation *invocation'] +
+ [ctype + name for (gtype, ctype, name) in out_args])
self.h(('void %s (' % ret_name) + (',\n '.join(tmp)) + ');')
- self.h('static inline void')
- self.h(('%s (' % ret_name) + (',\n '.join(tmp)) + ')')
- self.h('{')
- tmp = ['context'] + [name for (ctype, name) in out_args]
- self.h(' dbus_g_method_return (' + ',\n '.join(tmp) + ');')
- self.h('}')
- self.h('')
- return in_class
+ self.b('void')
+ self.b(('%s (' % ret_name) + (',\n '.join(tmp)) + ')')
+ self.b('{')
+ self.b(' GValueArray *tmp = tp_value_array_build (%d,' % len(out_args))
+
+ for (gtype, ctype, name) in out_args:
+ self.b(' %s, %s,' % (gtype, name))
+
+ self.b(' G_TYPE_INVALID);')
+ self.b(' GValue args_val = G_VALUE_INIT;')
+ self.b('')
+
+ self.b(' g_value_init (&args_val, '
+ 'dbus_g_type_get_struct ("GValueArray",')
+
+ for (gtype, ctype, name) in out_args:
+ self.b(' %s,' % gtype)
+
+ self.b(' G_TYPE_INVALID));')
+
+ self.b(' g_value_take_boxed (&args_val, tmp);')
+
+ self.b(' g_dbus_method_invocation_return_value (invocation,')
+ self.b(' /* consume floating ref */')
+ self.b(' dbus_g_value_build_g_variant (&args_val));')
+ self.b(' g_value_unset (&args_val);')
+ self.b('}')
+ self.b('')
def get_signal_const_entry(self, signal):
assert self.node_name_uc is not None
return ('SIGNAL_%s_%s'
% (self.node_name_uc, signal.getAttribute('name')))
- def do_signal(self, signal):
+ def do_signal(self, signal, in_base_init, in_signal_table):
assert self.node_name_mixed is not None
- in_base_init = []
-
# for signal: Thing::StuffHappened (s, u)
# we want to emit:
# void tp_svc_thing_emit_stuff_happened (gpointer instance,
@@ -716,7 +716,7 @@ class Generator(object):
in_base_init.append(' %s);' % ',\n '.join(tmp))
in_base_init.append('')
- return in_base_init
+ in_signal_table.append(' "%s",' % signal_name)
def have_properties(self, nodes):
for node in nodes:
@@ -730,12 +730,9 @@ class Generator(object):
nodes.sort(key=key_by_name)
self.h('#include <glib-object.h>')
+ self.h('#include <gio/gio.h>')
self.h('#include <dbus/dbus-glib.h>')
- for header in self.headers:
- self.h('#include %s' % header)
- self.h('')
-
self.h('')
self.h('G_BEGIN_DECLS')
self.h('')
@@ -743,6 +740,19 @@ class Generator(object):
self.b('#include "%s.h"' % self.basename)
self.b('')
+ if self.allow_single_include:
+ self.b('#include <telepathy-glib/core-svc-interface.h>')
+ self.b('#include <telepathy-glib/dbus.h>')
+ self.b('#include <telepathy-glib/dbus-properties-mixin.h>')
+ self.b('#include <telepathy-glib/util.h>')
+ else:
+ self.b('#include <telepathy-glib/telepathy-glib.h>')
+ self.b('')
+
+ for header in self.headers:
+ self.b('#include %s' % header)
+ self.b('')
+
for node in nodes:
self.do_node(node)
@@ -777,9 +787,9 @@ options:
--not-implemented-func='symbol'
Set action when methods not implemented in the interface vtable are
called. symbol must have signature
- void symbol (DBusGMethodInvocation *context)
+ void symbol (GDBusMethodInvocation *invocation)
and return some sort of "not implemented" error via
- dbus_g_method_return_error (context, ...)
+ e.g. g_dbus_method_invocation_return_error
""")
sys.exit(1)
@@ -791,7 +801,8 @@ if __name__ == '__main__':
['filename=', 'signal-marshal-prefix=',
'include=', 'include-end=',
'allow-unstable',
- 'not-implemented-func='])
+ 'not-implemented-func=',
+ "allow-single-include"])
try:
prefix = argv[1]
@@ -804,6 +815,7 @@ if __name__ == '__main__':
end_headers = []
not_implemented_func = ''
allow_havoc = False
+ allow_single_include = False
for option, value in options:
if option == '--filename':
@@ -822,6 +834,8 @@ if __name__ == '__main__':
not_implemented_func = value
elif option == '--allow-unstable':
allow_havoc = True
+ elif option == '--allow-single-include':
+ allow_single_include = True
try:
dom = xml.dom.minidom.parse(argv[0])
@@ -829,4 +843,5 @@ if __name__ == '__main__':
cmdline_error()
Generator(dom, prefix, basename, signal_marshal_prefix, headers,
- end_headers, not_implemented_func, allow_havoc)()
+ end_headers, not_implemented_func, allow_havoc,
+ allow_single_include)()
diff --git a/tools/libglibcodegen.py b/tools/libglibcodegen.py
index 0b703a5a8..5cd005853 100644
--- a/tools/libglibcodegen.py
+++ b/tools/libglibcodegen.py
@@ -47,59 +47,6 @@ def dbus_gutils_wincaps_to_uscore(s):
ret += c
return ret
-
-def signal_to_marshal_type(signal):
- """
- return a list of strings indicating the marshalling type for this signal.
- """
-
- mtype=[]
- for i in signal.getElementsByTagName("arg"):
- name =i.getAttribute("name")
- type = i.getAttribute("type")
- mtype.append(type_to_gtype(type)[2])
-
- return mtype
-
-
-_glib_marshallers = ['VOID', 'BOOLEAN', 'CHAR', 'UCHAR', 'INT',
- 'STRING', 'UINT', 'LONG', 'ULONG', 'ENUM', 'FLAGS', 'FLOAT',
- 'DOUBLE', 'STRING', 'PARAM', 'BOXED', 'POINTER', 'OBJECT',
- 'UINT_POINTER']
-
-
-def signal_to_marshal_name(signal, prefix):
-
- mtype = signal_to_marshal_type(signal)
- if len(mtype):
- name = '_'.join(mtype)
- else:
- name = 'VOID'
-
- if name in _glib_marshallers:
- return 'g_cclosure_marshal_VOID__' + name
- else:
- return prefix + '_marshal_VOID__' + name
-
-
-def method_to_glue_marshal_name(method, prefix):
-
- mtype = []
- for i in method.getElementsByTagName("arg"):
- if i.getAttribute("direction") != "out":
- type = i.getAttribute("type")
- mtype.append(type_to_gtype(type)[2])
-
- mtype.append('POINTER')
-
- name = '_'.join(mtype)
-
- if name in _glib_marshallers:
- return 'g_cclosure_marshal_VOID__' + name
- else:
- return prefix + '_marshal_VOID__' + name
-
-
def type_to_gtype(s):
if s == 'y': #byte
return ("guchar ", "G_TYPE_UCHAR","UCHAR", False)
@@ -171,25 +118,227 @@ def type_to_gtype(s):
# we just don't know ..
raise Exception("don't know the GType for " + s)
-
-def copy_into_gvalue(gvaluep, gtype, marshaller, name):
- if gtype == 'G_TYPE_STRING':
- return 'g_value_set_string (%s, %s);' % (gvaluep, name)
- elif marshaller == 'BOXED':
- return 'g_value_set_boxed (%s, %s);' % (gvaluep, name)
+def value_getter(gtype, marshaller):
+ if marshaller == 'BOXED':
+ return 'g_value_get_boxed'
+ elif gtype == 'G_TYPE_STRING':
+ return 'g_value_get_string'
elif gtype == 'G_TYPE_UCHAR':
- return 'g_value_set_uchar (%s, %s);' % (gvaluep, name)
+ return 'g_value_get_uchar'
elif gtype == 'G_TYPE_BOOLEAN':
- return 'g_value_set_boolean (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_INT':
- return 'g_value_set_int (%s, %s);' % (gvaluep, name)
+ return 'g_value_get_boolean'
elif gtype == 'G_TYPE_UINT':
- return 'g_value_set_uint (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_INT64':
- return 'g_value_set_int (%s, %s);' % (gvaluep, name)
+ return 'g_value_get_uint'
+ elif gtype == 'G_TYPE_INT':
+ return 'g_value_get_int'
elif gtype == 'G_TYPE_UINT64':
- return 'g_value_set_uint64 (%s, %s);' % (gvaluep, name)
+ return 'g_value_get_uint64'
+ elif gtype == 'G_TYPE_INT64':
+ return 'g_value_get_int64'
elif gtype == 'G_TYPE_DOUBLE':
- return 'g_value_set_double (%s, %s);' % (gvaluep, name)
+ return 'g_value_get_double'
else:
- raise AssertionError("Don't know how to put %s in a GValue" % gtype)
+ raise AssertionError("Don't know how to get %s from a GValue" % marshaller)
+
+class GDBusInterfaceInfo(object):
+ def __init__(self, ugly_name, iface_element, c_name):
+ self.ugly_name = ugly_name
+ self.mixed_name = ugly_name.replace('_', '')
+ self.lc_name = ugly_name.lower()
+ self.uc_name = ugly_name.upper()
+ self.c_name = c_name
+ self.iface_element = iface_element
+
+ self.method_elements = iface_element.getElementsByTagName('method')
+ self.signal_elements = iface_element.getElementsByTagName('signal')
+ self.property_elements = iface_element.getElementsByTagName('property')
+
+ def do_methods(self):
+ method_args = [
+ ]
+ method_in_arg_pointers = [
+ ]
+ method_out_arg_pointers = [
+ ]
+ methods = [
+ ]
+ method_pointers = [
+ 'static const GDBusMethodInfo *const method_pointers_%s[] = {'
+ % self.c_name,
+ ]
+
+ for meth in self.method_elements:
+ lc_name = meth.getAttribute('tp:name-for-bindings')
+ if meth.getAttribute('name') != lc_name.replace('_', ''):
+ raise AssertionError('Method %s tp:name-for-bindings (%s) '
+ 'does not match' %
+ (meth.getAttribute('name'), lc_name))
+ lc_name = lc_name.lower()
+
+ c_name = 'method_%s_%s' % (self.c_name, lc_name)
+
+ method_in_arg_pointers.append('static const GDBusArgInfo *const '
+ 'method_in_arg_pointers_%s_%s[] = {' %
+ (self.c_name, lc_name))
+ method_out_arg_pointers.append('static const GDBusArgInfo *const '
+ 'method_out_arg_pointers_%s_%s[] = {'
+ % (self.c_name, lc_name))
+
+ for i, arg in enumerate(meth.getElementsByTagName('arg')):
+ name = arg.getAttribute('name')
+ if not name:
+ name = 'arg%d' % i
+
+ method_args.append('static const GDBusArgInfo '
+ 'method_arg_%s_%s_%d = {' % (self.c_name, lc_name, i))
+ method_args.append(' -1, /* refcount */')
+ method_args.append(' "%s",' % name)
+ method_args.append(' "%s",' % arg.getAttribute('type'))
+ method_args.append(' NULL /* annotations */')
+ method_args.append('};')
+
+ if arg.getAttribute('direction') == 'out':
+ method_out_arg_pointers.append(' &method_arg_%s_%s_%d,' %
+ (self.c_name, lc_name, i))
+ else:
+ method_in_arg_pointers.append(' &method_arg_%s_%s_%d,' %
+ (self.c_name, lc_name, i))
+
+ method_in_arg_pointers.append(' NULL')
+ method_in_arg_pointers.append('};')
+ method_out_arg_pointers.append(' NULL')
+ method_out_arg_pointers.append('};')
+
+ methods.append('static const GDBusMethodInfo %s = {' % c_name)
+ methods.append(' -1, /* refcount */')
+ methods.append(' "%s",' % meth.getAttribute("name"))
+ methods.append(' (GDBusArgInfo **) method_in_arg_pointers_%s_%s,'
+ % (self.c_name, lc_name))
+ methods.append(' (GDBusArgInfo **) method_out_arg_pointers_%s_%s,'
+ % (self.c_name, lc_name))
+ methods.append(' NULL /* annotations */')
+ methods.append('};')
+
+ method_pointers.append(' &%s,' % c_name)
+
+ method_pointers.append(' NULL')
+ method_pointers.append('};')
+
+ return (method_args + method_in_arg_pointers +
+ method_out_arg_pointers + methods + method_pointers)
+
+ def do_signals(self):
+ signal_args = [
+ ]
+ signal_arg_pointers = [
+ ]
+ signals = [
+ ]
+ signal_pointers = [
+ 'static const GDBusSignalInfo *const signal_pointers_%s[] = {'
+ % self.c_name,
+ ]
+
+ for sig in self.signal_elements:
+ lc_name = sig.getAttribute('tp:name-for-bindings')
+ if sig.getAttribute('name') != lc_name.replace('_', ''):
+ raise AssertionError('Signal %s tp:name-for-bindings (%s) '
+ 'does not match' %
+ (sig.getAttribute('name'), lc_name))
+ lc_name = lc_name.lower()
+
+ c_name = 'signal_%s_%s' % (self.c_name, lc_name)
+
+ signal_arg_pointers.append('static const GDBusArgInfo *const '
+ 'signal_arg_pointers_%s_%s[] = {' % (self.c_name, lc_name))
+
+ for i, arg in enumerate(sig.getElementsByTagName('arg')):
+ name = arg.getAttribute('name')
+ if not name:
+ name = 'arg%d' % i
+
+ signal_args.append('static const GDBusArgInfo '
+ 'signal_arg_%s_%s_%d = {' % (self.c_name, lc_name, i))
+ signal_args.append(' -1, /* refcount */')
+ signal_args.append(' "%s",' % name)
+ signal_args.append(' "%s",' % arg.getAttribute('type'))
+ signal_args.append(' NULL /* annotations */')
+ signal_args.append('};')
+
+ signal_arg_pointers.append(' &signal_arg_%s_%s_%d,' %
+ (self.c_name, lc_name, i))
+
+ signal_arg_pointers.append(' NULL')
+ signal_arg_pointers.append('};')
+
+ signals.append('static const GDBusSignalInfo %s = {' % c_name)
+ signals.append(' -1, /* refcount */')
+ signals.append(' "%s",' % sig.getAttribute("name"))
+ signals.append(' (GDBusArgInfo **) signal_arg_pointers_%s_%s,'
+ % (self.c_name, lc_name))
+ signals.append(' NULL /* annotations */')
+ signals.append('};')
+
+ signal_pointers.append(' &%s,' % c_name)
+
+ signal_pointers.append(' NULL')
+ signal_pointers.append('};')
+
+ return signal_args + signal_arg_pointers + signals + signal_pointers
+
+ def do_properties(self):
+ properties = [
+ ]
+ property_pointers = [
+ 'static const GDBusPropertyInfo *const property_pointers_%s[] = {'
+ % self.c_name,
+ ]
+
+ for prop in self.property_elements:
+ access = prop.getAttribute('access')
+ flags = {
+ 'read': 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE',
+ 'write': 'G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE',
+ 'readwrite':
+ 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE | '
+ 'G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE',
+ }[access]
+
+ lc_name = prop.getAttribute('tp:name-for-bindings')
+ if prop.getAttribute('name') != lc_name.replace('_', ''):
+ raise AssertionError('Property %s tp:name-for-bindings (%s) '
+ 'does not match' %
+ (prop.getAttribute('name'), lc_name))
+ lc_name = lc_name.lower()
+
+ c_name = 'property_%s_%s' % (self.c_name, lc_name)
+
+ properties.append('static const GDBusPropertyInfo %s = {' % c_name)
+ properties.append(' -1, /* refcount */')
+ properties.append(' "%s",' % prop.getAttribute("name"))
+ properties.append(' "%s",' % prop.getAttribute("type"))
+ properties.append(' %s,' % flags)
+ # FIXME: add annotations?
+ properties.append(' NULL /* annotations */')
+ properties.append('};')
+
+ property_pointers.append(' &%s,' % c_name)
+
+ property_pointers.append(' NULL')
+ property_pointers.append('};')
+
+ return properties + property_pointers
+
+ def to_lines(self, linkage='static'):
+ return (self.do_methods() +
+ self.do_signals() +
+ self.do_properties() + [
+ '%s const GDBusInterfaceInfo %s = {' % (linkage, self.c_name),
+ ' -1, /* refcount */',
+ ' "%s",' % self.iface_element.getAttribute('name'),
+ ' (GDBusMethodInfo **) method_pointers_%s,' % self.c_name,
+ ' (GDBusSignalInfo **) signal_pointers_%s,' % self.c_name,
+ ' (GDBusPropertyInfo **) property_pointers_%s,' % self.c_name,
+ ' NULL /* annotations */',
+ '};'
+ ])
diff --git a/tools/libtpcodegen.py b/tools/libtpcodegen.py
index 99de66340..021a82be4 100644
--- a/tools/libtpcodegen.py
+++ b/tools/libtpcodegen.py
@@ -245,3 +245,13 @@ class Signature(str):
def xml_escape(s):
s = s.replace('&', '&amp;').replace("'", '&apos;').replace('"', '&quot;')
return s.replace('<', '&lt;').replace('>', '&gt;')
+
+def get_emits_changed(node):
+ try:
+ return [
+ annotation.getAttribute('value')
+ for annotation in node.getElementsByTagName('annotation')
+ if annotation.getAttribute('name') == 'org.freedesktop.DBus.Property.EmitsChangedSignal'
+ ][0]
+ except IndexError:
+ return None