summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2014-03-18 18:24:01 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2014-03-24 18:07:25 +0000
commitf107fc5f2ec3bda4381f9a7c8ee647e24a4fd453 (patch)
tree16a0500a4b06fcc969c287cc29b6dbca22c772cd
parent7b7810b5f295b4d769f96b695b2e1eae82c6b476 (diff)
Sync tools from telepathy-glib next
-rw-r--r--tools/glib-ginterface-gen.py371
-rw-r--r--tools/libglibcodegen.py278
-rw-r--r--tools/libtpcodegen.py10
-rw-r--r--tools/telepathy.am2
4 files changed, 429 insertions, 232 deletions
diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py
index c0ce20dd..d5a786f3 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 6cd1a627..5cd00585 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)
@@ -170,3 +117,228 @@ def type_to_gtype(s):
# we just don't know ..
raise Exception("don't know the GType for " + s)
+
+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_get_uchar'
+ elif gtype == 'G_TYPE_BOOLEAN':
+ return 'g_value_get_boolean'
+ elif gtype == 'G_TYPE_UINT':
+ return 'g_value_get_uint'
+ elif gtype == 'G_TYPE_INT':
+ return 'g_value_get_int'
+ elif gtype == 'G_TYPE_UINT64':
+ return 'g_value_get_uint64'
+ elif gtype == 'G_TYPE_INT64':
+ return 'g_value_get_int64'
+ elif gtype == 'G_TYPE_DOUBLE':
+ return 'g_value_get_double'
+ else:
+ 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 99de6634..021a82be 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
diff --git a/tools/telepathy.am b/tools/telepathy.am
index 20ff0be1..c919995d 100644
--- a/tools/telepathy.am
+++ b/tools/telepathy.am
@@ -55,7 +55,7 @@ maintainer-prepare-release:
$(MAKE) all
$(MAKE) distcheck
$(MAKE) release-mail
- git tag -s @PACKAGE@-@VERSION@ -m @PACKAGE@' '@VERSION@
+ cd $(srcdir) && git tag -s @PACKAGE@-@VERSION@ -m @PACKAGE@' '@VERSION@
gpg --detach-sign --armor @PACKAGE@-@VERSION@.tar.gz
release-mail: NEWS