~ubuntu-branches/ubuntu/natty/empathy/natty-updates

« back to all changes in this revision

Viewing changes to tools/glib-client-gen.py

Tags: upstream-0.22.0
ImportĀ upstreamĀ versionĀ 0.22.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
 
3
# glib-client-gen.py: "I Can't Believe It's Not dbus-binding-tool"
 
4
#
 
5
# Generate GLib client wrappers from the Telepathy specification.
 
6
# The master copy of this program is in the telepathy-glib repository -
 
7
# please make any changes there.
 
8
#
 
9
# Copyright (C) 2006-2008 Collabora Ltd. <http://www.collabora.co.uk/>
 
10
#
 
11
# This library is free software; you can redistribute it and/or
 
12
# modify it under the terms of the GNU Lesser General Public
 
13
# License as published by the Free Software Foundation; either
 
14
# version 2.1 of the License, or (at your option) any later version.
 
15
#
 
16
# This library is distributed in the hope that it will be useful,
 
17
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
19
# Lesser General Public License for more details.
 
20
#
 
21
# You should have received a copy of the GNU Lesser General Public
 
22
# License along with this library; if not, write to the Free Software
 
23
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
24
 
 
25
import sys
 
26
import os.path
 
27
import xml.dom.minidom
 
28
from getopt import gnu_getopt
 
29
 
 
30
from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \
 
31
        camelcase_to_lower, get_docstring, xml_escape
 
32
 
 
33
 
 
34
NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
 
35
 
 
36
class Generator(object):
 
37
 
 
38
    def __init__(self, dom, prefix, basename, opts):
 
39
        self.dom = dom
 
40
        self.__header = []
 
41
        self.__body = []
 
42
 
 
43
        self.prefix_lc = prefix.lower()
 
44
        self.prefix_uc = prefix.upper()
 
45
        self.prefix_mc = prefix.replace('_', '')
 
46
        self.basename = basename
 
47
        self.group = opts.get('--group', None)
 
48
        self.iface_quark_prefix = opts.get('--iface-quark-prefix', None)
 
49
        self.proxy_cls = opts.get('--subclass', 'TpProxy') + ' *'
 
50
        self.proxy_arg = opts.get('--subclass', 'void') + ' *'
 
51
        self.proxy_assert = opts.get('--subclass-assert', 'TP_IS_PROXY')
 
52
        self.proxy_doc = ('A #%s or subclass'
 
53
            % opts.get('--subclass', 'TpProxy'))
 
54
        if self.proxy_arg == 'void *':
 
55
            self.proxy_arg = 'gpointer '
 
56
 
 
57
    def h(self, s):
 
58
        self.__header.append(s)
 
59
 
 
60
    def b(self, s):
 
61
        self.__body.append(s)
 
62
 
 
63
    def get_iface_quark(self):
 
64
        assert self.iface_dbus is not None
 
65
        assert self.iface_uc is not None
 
66
        if self.iface_quark_prefix is None:
 
67
            return 'g_quark_from_static_string (\"%s\")' % self.iface_dbus
 
68
        else:
 
69
            return '%s_%s' % (self.iface_quark_prefix, self.iface_uc)
 
70
 
 
71
    def do_signal(self, iface, signal):
 
72
        iface_lc = iface.lower()
 
73
 
 
74
        member = signal.getAttribute('name')
 
75
        member_lc = camelcase_to_lower(member)
 
76
        member_uc = member_lc.upper()
 
77
 
 
78
        arg_count = 0
 
79
        args = []
 
80
        out_args = []
 
81
 
 
82
        for arg in signal.getElementsByTagName('arg'):
 
83
            name = arg.getAttribute('name')
 
84
            type = arg.getAttribute('type')
 
85
            tp_type = arg.getAttribute('tp:type')
 
86
 
 
87
            if not name:
 
88
                name = 'arg%u' % arg_count
 
89
                arg_count += 1
 
90
            else:
 
91
                name = 'arg_%s' % name
 
92
 
 
93
            info = type_to_gtype(type)
 
94
            args.append((name, info, tp_type, arg))
 
95
 
 
96
        callback_name = ('%s_%s_signal_callback_%s'
 
97
                         % (self.prefix_lc, iface_lc, member_lc))
 
98
        collect_name = ('_%s_%s_collect_args_of_%s'
 
99
                        % (self.prefix_lc, iface_lc, member_lc))
 
100
        invoke_name = ('_%s_%s_invoke_callback_for_%s'
 
101
                       % (self.prefix_lc, iface_lc, member_lc))
 
102
 
 
103
        # Example:
 
104
        #
 
105
        # typedef void (*tp_cli_connection_signal_callback_new_channel)
 
106
        #   (TpConnection *proxy, const gchar *arg_object_path,
 
107
        #   const gchar *arg_channel_type, guint arg_handle_type,
 
108
        #   guint arg_handle, gboolean arg_suppress_handler,
 
109
        #   gpointer user_data, GObject *weak_object);
 
110
 
 
111
        self.b('/**')
 
112
        self.b(' * %s:' % callback_name)
 
113
        self.b(' * @proxy: The proxy on which %s_%s_connect_to_%s ()'
 
114
               % (self.prefix_lc, iface_lc, member_lc))
 
115
        self.b(' *  was called')
 
116
 
 
117
        for arg in args:
 
118
            name, info, tp_type, elt = arg
 
119
            ctype, gtype, marshaller, pointer = info
 
120
 
 
121
            self.b(' * @%s: %s' % (name,
 
122
                xml_escape(get_docstring(elt) or '(Undocumented)')))
 
123
 
 
124
        self.b(' * @user_data: User-supplied data')
 
125
        self.b(' * @weak_object: User-supplied weakly referenced object')
 
126
        self.b(' *')
 
127
        self.b(' * Represents the signature of a callback for the signal %s.'
 
128
               % member)
 
129
        self.b(' */')
 
130
        self.h('typedef void (*%s) (%sproxy,'
 
131
               % (callback_name, self.proxy_cls))
 
132
 
 
133
        for arg in args:
 
134
            name, info, tp_type, elt = arg
 
135
            ctype, gtype, marshaller, pointer = info
 
136
 
 
137
            const = pointer and 'const ' or ''
 
138
 
 
139
            self.h('    %s%s%s,' % (const, ctype, name))
 
140
 
 
141
        self.h('    gpointer user_data, GObject *weak_object);')
 
142
 
 
143
        if args:
 
144
            self.b('static void')
 
145
            self.b('%s (DBusGProxy *proxy,' % collect_name)
 
146
 
 
147
            for arg in args:
 
148
                name, info, tp_type, elt = arg
 
149
                ctype, gtype, marshaller, pointer = info
 
150
 
 
151
                const = pointer and 'const ' or ''
 
152
 
 
153
                self.b('    %s%s%s,' % (const, ctype, name))
 
154
 
 
155
            self.b('    TpProxySignalConnection *sc)')
 
156
            self.b('{')
 
157
            self.b('  GValueArray *args = g_value_array_new (%d);' % len(args))
 
158
            self.b('  GValue blank = { 0 };')
 
159
            self.b('  guint i;')
 
160
            self.b('')
 
161
            self.b('  g_value_init (&blank, G_TYPE_INT);')
 
162
            self.b('')
 
163
            self.b('  for (i = 0; i < %d; i++)' % len(args))
 
164
            self.b('    g_value_array_append (args, &blank);')
 
165
            self.b('')
 
166
 
 
167
            for i, arg in enumerate(args):
 
168
                name, info, tp_type, elt = arg
 
169
                ctype, gtype, marshaller, pointer = info
 
170
 
 
171
                self.b('  g_value_unset (args->values + %d);' % i)
 
172
                self.b('  g_value_init (args->values + %d, %s);' % (i, gtype))
 
173
 
 
174
                if gtype == 'G_TYPE_STRING':
 
175
                    self.b('  g_value_set_string (args->values + %d, %s);'
 
176
                           % (i, name))
 
177
                elif marshaller == 'BOXED':
 
178
                    self.b('  g_value_set_boxed (args->values + %d, %s);'
 
179
                           % (i, name))
 
180
                elif gtype == 'G_TYPE_UCHAR':
 
181
                    self.b('  g_value_set_uchar (args->values + %d, %s);'
 
182
                           % (i, name))
 
183
                elif gtype == 'G_TYPE_BOOLEAN':
 
184
                    self.b('  g_value_set_boolean (args->values + %d, %s);'
 
185
                           % (i, name))
 
186
                elif gtype == 'G_TYPE_INT':
 
187
                    self.b('  g_value_set_int (args->values + %d, %s);'
 
188
                           % (i, name))
 
189
                elif gtype == 'G_TYPE_UINT':
 
190
                    self.b('  g_value_set_uint (args->values + %d, %s);'
 
191
                           % (i, name))
 
192
                elif gtype == 'G_TYPE_INT64':
 
193
                    self.b('  g_value_set_int (args->values + %d, %s);'
 
194
                           % (i, name))
 
195
                elif gtype == 'G_TYPE_UINT64':
 
196
                    self.b('  g_value_set_uint (args->values + %d, %s);'
 
197
                           % (i, name))
 
198
                elif gtype == 'G_TYPE_DOUBLE':
 
199
                    self.b('  g_value_set_double (args->values + %d, %s);'
 
200
                           % (i, name))
 
201
                else:
 
202
                    assert False, ("Don't know how to put %s in a GValue"
 
203
                                   % gtype)
 
204
                self.b('')
 
205
 
 
206
            self.b('  tp_proxy_signal_connection_v0_take_results (sc, args);')
 
207
            self.b('}')
 
208
 
 
209
        self.b('static void')
 
210
        self.b('%s (TpProxy *tpproxy,' % invoke_name)
 
211
        self.b('    GError *error,')
 
212
        self.b('    GValueArray *args,')
 
213
        self.b('    GCallback generic_callback,')
 
214
        self.b('    gpointer user_data,')
 
215
        self.b('    GObject *weak_object)')
 
216
        self.b('{')
 
217
        self.b('  %s callback =' % callback_name)
 
218
        self.b('      (%s) generic_callback;' % callback_name)
 
219
        self.b('')
 
220
        self.b('  if (callback != NULL)')
 
221
        self.b('    callback (g_object_ref (tpproxy),')
 
222
 
 
223
        # FIXME: factor out into a function
 
224
        for i, arg in enumerate(args):
 
225
            name, info, tp_type, elt = arg
 
226
            ctype, gtype, marshaller, pointer = info
 
227
 
 
228
            if marshaller == 'BOXED':
 
229
                self.b('      g_value_get_boxed (args->values + %d),' % i)
 
230
            elif gtype == 'G_TYPE_STRING':
 
231
                self.b('      g_value_get_string (args->values + %d),' % i)
 
232
            elif gtype == 'G_TYPE_UCHAR':
 
233
                self.b('      g_value_get_uchar (args->values + %d),' % i)
 
234
            elif gtype == 'G_TYPE_BOOLEAN':
 
235
                self.b('      g_value_get_boolean (args->values + %d),' % i)
 
236
            elif gtype == 'G_TYPE_UINT':
 
237
                self.b('      g_value_get_uint (args->values + %d),' % i)
 
238
            elif gtype == 'G_TYPE_INT':
 
239
                self.b('      g_value_get_int (args->values + %d),' % i)
 
240
            elif gtype == 'G_TYPE_UINT64':
 
241
                self.b('      g_value_get_uint64 (args->values + %d),' % i)
 
242
            elif gtype == 'G_TYPE_INT64':
 
243
                self.b('      g_value_get_int64 (args->values + %d),' % i)
 
244
            elif gtype == 'G_TYPE_DOUBLE':
 
245
                self.b('      g_value_get_double (args->values + %d),' % i)
 
246
            else:
 
247
                assert False, "Don't know how to get %s from a GValue" % gtype
 
248
 
 
249
        self.b('      user_data,')
 
250
        self.b('      weak_object);')
 
251
        self.b('')
 
252
 
 
253
        if len(args) > 0:
 
254
            self.b('  g_value_array_free (args);')
 
255
        else:
 
256
            self.b('  if (args != NULL)')
 
257
            self.b('    g_value_array_free (args);')
 
258
            self.b('')
 
259
 
 
260
        self.b('  g_object_unref (tpproxy);')
 
261
        self.b('}')
 
262
 
 
263
        # Example:
 
264
        #
 
265
        # TpProxySignalConnection *
 
266
        #   tp_cli_connection_connect_to_new_channel
 
267
        #   (TpConnection *proxy,
 
268
        #   tp_cli_connection_signal_callback_new_channel callback,
 
269
        #   gpointer user_data,
 
270
        #   GDestroyNotify destroy);
 
271
        #
 
272
        # destroy is invoked when the signal becomes disconnected. This
 
273
        # is either because the signal has been disconnected explicitly
 
274
        # by the user, because the TpProxy has become invalid and
 
275
        # emitted the 'invalidated' signal, or because the weakly referenced
 
276
        # object has gone away.
 
277
 
 
278
        self.b('/**')
 
279
        self.b(' * %s_%s_connect_to_%s:'
 
280
               % (self.prefix_lc, iface_lc, member_lc))
 
281
        self.b(' * @proxy: %s' % self.proxy_doc)
 
282
        self.b(' * @callback: Callback to be called when the signal is')
 
283
        self.b(' *   received')
 
284
        self.b(' * @user_data: User-supplied data for the callback')
 
285
        self.b(' * @destroy: Destructor for the user-supplied data, which')
 
286
        self.b(' *   will be called when this signal is disconnected, or')
 
287
        self.b(' *   before this function returns %NULL')
 
288
        self.b(' * @weak_object: A #GObject which will be weakly referenced; ')
 
289
        self.b(' *   if it is destroyed, this callback will automatically be')
 
290
        self.b(' *   disconnected')
 
291
        self.b(' * @error: If not %NULL, used to raise an error if %NULL is')
 
292
        self.b(' *   returned')
 
293
        self.b(' *')
 
294
        self.b(' * Connect a handler to the signal %s.' % member)
 
295
        self.b(' *')
 
296
        self.b(' * %s' % xml_escape(get_docstring(signal) or '(Undocumented)'))
 
297
        self.b(' *')
 
298
        self.b(' * Returns: a #TpProxySignalConnection containing all of the')
 
299
        self.b(' * above, which can be used to disconnect the signal; or')
 
300
        self.b(' * %NULL if the proxy does not have the desired interface')
 
301
        self.b(' * or has become invalid.')
 
302
        self.b(' */')
 
303
        self.h('TpProxySignalConnection *%s_%s_connect_to_%s (%sproxy,'
 
304
               % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
 
305
        self.h('    %s callback,' % callback_name)
 
306
        self.h('    gpointer user_data,')
 
307
        self.h('    GDestroyNotify destroy,')
 
308
        self.h('    GObject *weak_object,')
 
309
        self.h('    GError **error);')
 
310
 
 
311
        self.b('TpProxySignalConnection *')
 
312
        self.b('%s_%s_connect_to_%s (%sproxy,'
 
313
               % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
 
314
        self.b('    %s callback,' % callback_name)
 
315
        self.b('    gpointer user_data,')
 
316
        self.b('    GDestroyNotify destroy,')
 
317
        self.b('    GObject *weak_object,')
 
318
        self.b('    GError **error)')
 
319
        self.b('{')
 
320
        self.b('  GType expected_types[%d] = {' % (len(args) + 1))
 
321
 
 
322
        for arg in args:
 
323
            name, info, tp_type, elt = arg
 
324
            ctype, gtype, marshaller, pointer = info
 
325
 
 
326
            self.b('      %s,' % gtype)
 
327
 
 
328
        self.b('      G_TYPE_INVALID };')
 
329
        self.b('')
 
330
        self.b('  g_return_val_if_fail (%s (proxy), NULL);'
 
331
               % self.proxy_assert)
 
332
        self.b('  g_return_val_if_fail (callback != NULL, NULL);')
 
333
        self.b('')
 
334
        self.b('  return tp_proxy_signal_connection_v0_new ((TpProxy *) proxy,')
 
335
        self.b('      %s, \"%s\",' % (self.get_iface_quark(), member))
 
336
        self.b('      expected_types,')
 
337
 
 
338
        if args:
 
339
            self.b('      G_CALLBACK (%s),' % collect_name)
 
340
        else:
 
341
            self.b('      NULL, /* no args => no collector function */')
 
342
 
 
343
        self.b('      %s,' % invoke_name)
 
344
        self.b('      G_CALLBACK (callback), user_data, destroy,')
 
345
        self.b('      weak_object, error);')
 
346
        self.b('}')
 
347
        self.b('')
 
348
 
 
349
        self.h('')
 
350
 
 
351
    def do_method(self, iface, method):
 
352
        iface_lc = iface.lower()
 
353
 
 
354
        member = method.getAttribute('name')
 
355
        member_lc = camelcase_to_lower(member)
 
356
        member_uc = member_lc.upper()
 
357
 
 
358
        in_count = 0
 
359
        ret_count = 0
 
360
        in_args = []
 
361
        out_args = []
 
362
 
 
363
        for arg in method.getElementsByTagName('arg'):
 
364
            name = arg.getAttribute('name')
 
365
            direction = arg.getAttribute('direction')
 
366
            type = arg.getAttribute('type')
 
367
            tp_type = arg.getAttribute('tp:type')
 
368
 
 
369
            if direction != 'out':
 
370
                if not name:
 
371
                    name = 'in%u' % in_count
 
372
                    in_count += 1
 
373
                else:
 
374
                    name = 'in_%s' % name
 
375
            else:
 
376
                if not name:
 
377
                    name = 'out%u' % ret_count
 
378
                    ret_count += 1
 
379
                else:
 
380
                    name = 'out_%s' % name
 
381
 
 
382
            info = type_to_gtype(type)
 
383
            if direction != 'out':
 
384
                in_args.append((name, info, tp_type, arg))
 
385
            else:
 
386
                out_args.append((name, info, tp_type, arg))
 
387
 
 
388
        # Async reply callback type
 
389
 
 
390
        # Example:
 
391
        # void (*tp_cli_properties_interface_callback_for_get_properties)
 
392
        #   (TpProxy *proxy,
 
393
        #       const GPtrArray *out0,
 
394
        #       const GError *error,
 
395
        #       gpointer user_data,
 
396
        #       GObject *weak_object);
 
397
 
 
398
        self.b('/**')
 
399
        self.b(' * %s_%s_callback_for_%s:'
 
400
               % (self.prefix_lc, iface_lc, member_lc))
 
401
        self.b(' * @proxy: the proxy on which the call was made')
 
402
 
 
403
        for arg in out_args:
 
404
            name, info, tp_type, elt = arg
 
405
            ctype, gtype, marshaller, pointer = info
 
406
 
 
407
            self.b(' * @%s: Used to return an \'out\' argument if @error is '
 
408
                   '%%NULL: %s'
 
409
                   % (name, xml_escape(get_docstring(elt) or '(Undocumented)')))
 
410
 
 
411
        self.b(' * @error: %NULL on success, or an error on failure')
 
412
        self.b(' * @user_data: user-supplied data')
 
413
        self.b(' * @weak_object: user-supplied object')
 
414
        self.b(' *')
 
415
        self.b(' * Signature of the callback called when a %s method call'
 
416
               % member)
 
417
        self.b(' * succeeds or fails.')
 
418
        self.b(' */')
 
419
 
 
420
        callback_name = '%s_%s_callback_for_%s' % (self.prefix_lc, iface_lc,
 
421
                                                   member_lc)
 
422
 
 
423
        self.h('typedef void (*%s) (%sproxy,'
 
424
               % (callback_name, self.proxy_cls))
 
425
 
 
426
        for arg in out_args:
 
427
            name, info, tp_type, elt = arg
 
428
            ctype, gtype, marshaller, pointer = info
 
429
            const = pointer and 'const ' or ''
 
430
 
 
431
            self.h('    %s%s%s,' % (const, ctype, name))
 
432
 
 
433
        self.h('    const GError *error, gpointer user_data,')
 
434
        self.h('    GObject *weak_object);')
 
435
        self.h('')
 
436
 
 
437
        # Async callback implementation
 
438
 
 
439
        invoke_callback = '_%s_%s_invoke_callback_%s' % (self.prefix_lc,
 
440
                                                         iface_lc,
 
441
                                                         member_lc)
 
442
 
 
443
        collect_callback = '_%s_%s_collect_callback_%s' % (self.prefix_lc,
 
444
                                                           iface_lc,
 
445
                                                           member_lc)
 
446
 
 
447
        # The callback called by dbus-glib; this ends the call and collects
 
448
        # the results into a GValueArray.
 
449
        self.b('static void')
 
450
        self.b('%s (DBusGProxy *proxy,' % collect_callback)
 
451
        self.b('    DBusGProxyCall *call,')
 
452
        self.b('    gpointer user_data)')
 
453
        self.b('{')
 
454
        self.b('  GError *error = NULL;')
 
455
 
 
456
        if len(out_args) > 0:
 
457
            self.b('  GValueArray *args;')
 
458
            self.b('  GValue blank = { 0 };')
 
459
            self.b('  guint i;')
 
460
 
 
461
            for arg in out_args:
 
462
                name, info, tp_type, elt = arg
 
463
                ctype, gtype, marshaller, pointer = info
 
464
 
 
465
                # "We handle variants specially; the caller is expected to
 
466
                # have already allocated storage for them". Thanks,
 
467
                # dbus-glib...
 
468
                if gtype == 'G_TYPE_VALUE':
 
469
                    self.b('  GValue *%s = g_new0 (GValue, 1);' % name)
 
470
                else:
 
471
                    self.b('  %s%s;' % (ctype, name))
 
472
 
 
473
        self.b('')
 
474
        self.b('  dbus_g_proxy_end_call (proxy, call, &error,')
 
475
 
 
476
        for arg in out_args:
 
477
            name, info, tp_type, elt = arg
 
478
            ctype, gtype, marshaller, pointer = info
 
479
 
 
480
            if gtype == 'G_TYPE_VALUE':
 
481
                self.b('      %s, %s,' % (gtype, name))
 
482
            else:
 
483
                self.b('      %s, &%s,' % (gtype, name))
 
484
 
 
485
        self.b('      G_TYPE_INVALID);')
 
486
 
 
487
        if len(out_args) == 0:
 
488
            self.b('  tp_proxy_pending_call_v0_take_results (user_data, error,'
 
489
                   'NULL);')
 
490
        else:
 
491
            self.b('')
 
492
            self.b('  if (error != NULL)')
 
493
            self.b('    {')
 
494
            self.b('      tp_proxy_pending_call_v0_take_results (user_data, error,')
 
495
            self.b('          NULL);')
 
496
 
 
497
            for arg in out_args:
 
498
                name, info, tp_type, elt = arg
 
499
                ctype, gtype, marshaller, pointer = info
 
500
                if gtype == 'G_TYPE_VALUE':
 
501
                    self.b('      g_free (%s);' % name)
 
502
 
 
503
            self.b('      return;')
 
504
            self.b('    }')
 
505
            self.b('')
 
506
            self.b('  args = g_value_array_new (%d);' % len(out_args))
 
507
            self.b('  g_value_init (&blank, G_TYPE_INT);')
 
508
            self.b('')
 
509
            self.b('  for (i = 0; i < %d; i++)' % len(out_args))
 
510
            self.b('    g_value_array_append (args, &blank);')
 
511
 
 
512
            for i, arg in enumerate(out_args):
 
513
                name, info, tp_type, elt = arg
 
514
                ctype, gtype, marshaller, pointer = info
 
515
 
 
516
                self.b('')
 
517
                self.b('  g_value_unset (args->values + %d);' % i)
 
518
                self.b('  g_value_init (args->values + %d, %s);' % (i, gtype))
 
519
 
 
520
                if gtype == 'G_TYPE_STRING':
 
521
                    self.b('  g_value_take_string (args->values + %d, %s);'
 
522
                           % (i, name))
 
523
                elif marshaller == 'BOXED':
 
524
                    self.b('  g_value_take_boxed (args->values + %d, %s);'
 
525
                            % (i, name))
 
526
                elif gtype == 'G_TYPE_UCHAR':
 
527
                    self.b('  g_value_set_uchar (args->values + %d, %s);'
 
528
                            % (i, name))
 
529
                elif gtype == 'G_TYPE_BOOLEAN':
 
530
                    self.b('  g_value_set_boolean (args->values + %d, %s);'
 
531
                            % (i, name))
 
532
                elif gtype == 'G_TYPE_INT':
 
533
                    self.b('  g_value_set_int (args->values + %d, %s);'
 
534
                            % (i, name))
 
535
                elif gtype == 'G_TYPE_UINT':
 
536
                    self.b('  g_value_set_uint (args->values + %d, %s);'
 
537
                            % (i, name))
 
538
                elif gtype == 'G_TYPE_INT64':
 
539
                    self.b('  g_value_set_int (args->values + %d, %s);'
 
540
                            % (i, name))
 
541
                elif gtype == 'G_TYPE_UINT64':
 
542
                    self.b('  g_value_set_uint (args->values + %d, %s);'
 
543
                            % (i, name))
 
544
                elif gtype == 'G_TYPE_DOUBLE':
 
545
                    self.b('  g_value_set_double (args->values + %d, %s);'
 
546
                            % (i, name))
 
547
                else:
 
548
                    assert False, ("Don't know how to put %s in a GValue"
 
549
                                   % gtype)
 
550
 
 
551
            self.b('  tp_proxy_pending_call_v0_take_results (user_data, '
 
552
                   'NULL, args);')
 
553
 
 
554
        self.b('}')
 
555
 
 
556
        self.b('static void')
 
557
        self.b('%s (TpProxy *self,' % invoke_callback)
 
558
        self.b('    GError *error,')
 
559
        self.b('    GValueArray *args,')
 
560
        self.b('    GCallback generic_callback,')
 
561
        self.b('    gpointer user_data,')
 
562
        self.b('    GObject *weak_object)')
 
563
        self.b('{')
 
564
        self.b('  %s callback = (%s) generic_callback;'
 
565
               % (callback_name, callback_name))
 
566
        self.b('')
 
567
        self.b('  if (error != NULL)')
 
568
        self.b('    {')
 
569
        self.b('      callback ((%s) self,' % self.proxy_cls)
 
570
 
 
571
        for arg in out_args:
 
572
            name, info, tp_type, elt = arg
 
573
            ctype, gtype, marshaller, pointer = info
 
574
 
 
575
            if marshaller == 'BOXED' or pointer:
 
576
                self.b('          NULL,')
 
577
            elif gtype == 'G_TYPE_DOUBLE':
 
578
                self.b('          0.0,')
 
579
            else:
 
580
                self.b('          0,')
 
581
 
 
582
        self.b('          error, user_data, weak_object);')
 
583
        self.b('      g_error_free (error);')
 
584
        self.b('      return;')
 
585
        self.b('    }')
 
586
 
 
587
        self.b('  callback ((%s) self,' % self.proxy_cls)
 
588
 
 
589
        # FIXME: factor out into a function
 
590
        for i, arg in enumerate(out_args):
 
591
            name, info, tp_type, elt = arg
 
592
            ctype, gtype, marshaller, pointer = info
 
593
 
 
594
            if marshaller == 'BOXED':
 
595
                self.b('      g_value_get_boxed (args->values + %d),' % i)
 
596
            elif gtype == 'G_TYPE_STRING':
 
597
                self.b('      g_value_get_string (args->values + %d),' % i)
 
598
            elif gtype == 'G_TYPE_UCHAR':
 
599
                self.b('      g_value_get_uchar (args->values + %d),' % i)
 
600
            elif gtype == 'G_TYPE_BOOLEAN':
 
601
                self.b('      g_value_get_boolean (args->values + %d),' % i)
 
602
            elif gtype == 'G_TYPE_UINT':
 
603
                self.b('      g_value_get_uint (args->values + %d),' % i)
 
604
            elif gtype == 'G_TYPE_INT':
 
605
                self.b('      g_value_get_int (args->values + %d),' % i)
 
606
            elif gtype == 'G_TYPE_UINT64':
 
607
                self.b('      g_value_get_uint64 (args->values + %d),' % i)
 
608
            elif gtype == 'G_TYPE_INT64':
 
609
                self.b('      g_value_get_int64 (args->values + %d),' % i)
 
610
            elif gtype == 'G_TYPE_DOUBLE':
 
611
                self.b('      g_value_get_double (args->values + %d),' % i)
 
612
            else:
 
613
                assert False, "Don't know how to get %s from a GValue" % gtype
 
614
 
 
615
        self.b('      error, user_data, weak_object);')
 
616
        self.b('')
 
617
 
 
618
        if len(out_args) > 0:
 
619
            self.b('  g_value_array_free (args);')
 
620
        else:
 
621
            self.b('  if (args != NULL)')
 
622
            self.b('    g_value_array_free (args);')
 
623
 
 
624
        self.b('}')
 
625
        self.b('')
 
626
 
 
627
        # Async stub
 
628
 
 
629
        # Example:
 
630
        # TpProxyPendingCall *
 
631
        #   tp_cli_properties_interface_call_get_properties
 
632
        #   (gpointer proxy,
 
633
        #   gint timeout_ms,
 
634
        #   const GArray *in_properties,
 
635
        #   tp_cli_properties_interface_callback_for_get_properties callback,
 
636
        #   gpointer user_data,
 
637
        #   GDestroyNotify *destructor);
 
638
 
 
639
        self.h('TpProxyPendingCall *%s_%s_call_%s (%sproxy,'
 
640
               % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
 
641
        self.h('    gint timeout_ms,')
 
642
 
 
643
        self.b('/**')
 
644
        self.b(' * %s_%s_call_%s:'
 
645
               % (self.prefix_lc, iface_lc, member_lc))
 
646
        self.b(' * @proxy: the #TpProxy')
 
647
        self.b(' * @timeout_ms: the timeout in milliseconds, or -1 to use the')
 
648
        self.b(' *   default')
 
649
 
 
650
        for arg in in_args:
 
651
            name, info, tp_type, elt = arg
 
652
            ctype, gtype, marshaller, pointer = info
 
653
 
 
654
            self.b(' * @%s: Used to pass an \'in\' argument: %s'
 
655
                   % (name, xml_escape(get_docstring(elt) or '(Undocumented)')))
 
656
 
 
657
        self.b(' * @callback: called when the method call succeeds or fails')
 
658
        self.b(' * @user_data: user-supplied data passed to the callback')
 
659
        self.b(' * @destroy: called with the user_data as argument, after the')
 
660
        self.b(' *   call has succeeded, failed or been cancelled')
 
661
        self.b(' * @weak_object: A #GObject which will be weakly referenced; ')
 
662
        self.b(' *   if it is destroyed, this callback will automatically be')
 
663
        self.b(' *   disconnected')
 
664
        self.b(' *')
 
665
        self.b(' * Start a %s method call.' % member)
 
666
        self.b(' *')
 
667
        self.b(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)'))
 
668
        self.b(' *')
 
669
        self.b(' * Returns: a #TpProxyPendingCall representing the call in')
 
670
        self.b(' *  progress. It is borrowed from the object, and will become')
 
671
        self.b(' *  invalid when the callback is called, the call is')
 
672
        self.b(' *  cancelled or the #TpProxy becomes invalid.')
 
673
        self.b(' */')
 
674
        self.b('TpProxyPendingCall *\n%s_%s_call_%s (%sproxy,'
 
675
               % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
 
676
        self.b('    gint timeout_ms,')
 
677
 
 
678
        for arg in in_args:
 
679
            name, info, tp_type, elt = arg
 
680
            ctype, gtype, marshaller, pointer = info
 
681
 
 
682
            const = pointer and 'const ' or ''
 
683
 
 
684
            self.h('    %s%s%s,' % (const, ctype, name))
 
685
            self.b('    %s%s%s,' % (const, ctype, name))
 
686
 
 
687
        self.h('    %s callback,' % callback_name)
 
688
        self.h('    gpointer user_data,')
 
689
        self.h('    GDestroyNotify destroy,')
 
690
        self.h('    GObject *weak_object);')
 
691
        self.h('')
 
692
 
 
693
        self.b('    %s callback,' % callback_name)
 
694
        self.b('    gpointer user_data,')
 
695
        self.b('    GDestroyNotify destroy,')
 
696
        self.b('    GObject *weak_object)')
 
697
        self.b('{')
 
698
        self.b('  GError *error = NULL;')
 
699
        self.b('  GQuark interface = %s;' % self.get_iface_quark())
 
700
        self.b('  DBusGProxy *iface;')
 
701
        self.b('')
 
702
        self.b('  g_return_val_if_fail (%s (proxy), NULL);'
 
703
               % self.proxy_assert)
 
704
        self.b('')
 
705
        self.b('  iface = tp_proxy_borrow_interface_by_id (')
 
706
        self.b('      (TpProxy *) proxy,')
 
707
        self.b('      interface, &error);')
 
708
        self.b('')
 
709
        self.b('  if (iface == NULL)')
 
710
        self.b('    {')
 
711
        self.b('      if (callback != NULL)')
 
712
        self.b('        callback (proxy,')
 
713
 
 
714
        for arg in out_args:
 
715
            name, info, tp_type, elt = arg
 
716
            ctype, gtype, marshaller, pointer = info
 
717
 
 
718
            if pointer:
 
719
                self.b('            NULL,')
 
720
            else:
 
721
                self.b('            0,')
 
722
 
 
723
        self.b('            error, user_data, weak_object);')
 
724
        self.b('      return NULL;')
 
725
        self.b('    }')
 
726
        self.b('')
 
727
        self.b('  if (callback == NULL)')
 
728
        self.b('    {')
 
729
        self.b('      dbus_g_proxy_call_no_reply (iface, "%s",' % member)
 
730
 
 
731
        for arg in in_args:
 
732
            name, info, tp_type, elt = arg
 
733
            ctype, gtype, marshaller, pointer = info
 
734
 
 
735
            const = pointer and 'const ' or ''
 
736
 
 
737
            self.b('          %s, %s,' % (gtype, name))
 
738
 
 
739
        self.b('          G_TYPE_INVALID);')
 
740
        self.b('      return NULL;')
 
741
        self.b('    }')
 
742
        self.b('  else')
 
743
        self.b('    {')
 
744
        self.b('      TpProxyPendingCall *data;')
 
745
        self.b('')
 
746
        self.b('      data = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,')
 
747
        self.b('          interface, "%s", iface,' % member)
 
748
        self.b('          %s,' % invoke_callback)
 
749
        self.b('          G_CALLBACK (callback), user_data, destroy,')
 
750
        self.b('          weak_object, FALSE);')
 
751
        self.b('      tp_proxy_pending_call_v0_take_pending_call (data,')
 
752
        self.b('          dbus_g_proxy_begin_call_with_timeout (iface,')
 
753
        self.b('              "%s",' % member)
 
754
        self.b('              %s,' % collect_callback)
 
755
        self.b('              data,')
 
756
        self.b('              tp_proxy_pending_call_v0_completed,')
 
757
        self.b('              timeout_ms,')
 
758
 
 
759
        for arg in in_args:
 
760
            name, info, tp_type, elt = arg
 
761
            ctype, gtype, marshaller, pointer = info
 
762
 
 
763
            const = pointer and 'const ' or ''
 
764
 
 
765
            self.b('              %s, %s,' % (gtype, name))
 
766
 
 
767
        self.b('              G_TYPE_INVALID));')
 
768
        self.b('')
 
769
        self.b('      return data;')
 
770
        self.b('    }')
 
771
        self.b('}')
 
772
        self.b('')
 
773
 
 
774
        # Reentrant blocking calls
 
775
        # Example:
 
776
        # gboolean tp_cli_properties_interface_run_get_properties
 
777
        #   (gpointer proxy,
 
778
        #       gint timeout_ms,
 
779
        #       const GArray *in_properties,
 
780
        #       GPtrArray **out0,
 
781
        #       GError **error,
 
782
        #       GMainLoop **loop);
 
783
 
 
784
        self.b('typedef struct {')
 
785
        self.b('    GMainLoop *loop;')
 
786
        self.b('    GError **error;')
 
787
 
 
788
        for arg in out_args:
 
789
            name, info, tp_type, elt = arg
 
790
            ctype, gtype, marshaller, pointer = info
 
791
 
 
792
            self.b('    %s*%s;' % (ctype, name))
 
793
 
 
794
        self.b('    gboolean success:1;')
 
795
        self.b('    gboolean completed:1;')
 
796
        self.b('} _%s_%s_run_state_%s;'
 
797
               % (self.prefix_lc, iface_lc, member_lc))
 
798
 
 
799
        reentrant_invoke = '_%s_%s_finish_running_%s' % (self.prefix_lc,
 
800
                                                         iface_lc,
 
801
                                                         member_lc)
 
802
 
 
803
        self.b('static void')
 
804
        self.b('%s (TpProxy *self,' % reentrant_invoke)
 
805
        self.b('    GError *error,')
 
806
        self.b('    GValueArray *args,')
 
807
        self.b('    GCallback unused,')
 
808
        self.b('    gpointer user_data,')
 
809
        self.b('    GObject *unused2)')
 
810
        self.b('{')
 
811
        self.b('  _%s_%s_run_state_%s *state = user_data;'
 
812
               % (self.prefix_lc, iface_lc, member_lc))
 
813
        self.b('')
 
814
        self.b('  state->success = (error == NULL);')
 
815
        self.b('  state->completed = TRUE;')
 
816
        self.b('  g_main_loop_quit (state->loop);')
 
817
        self.b('')
 
818
        self.b('  if (error != NULL)')
 
819
        self.b('    {')
 
820
        self.b('      if (state->error != NULL)')
 
821
        self.b('        *state->error = error;')
 
822
        self.b('      else')
 
823
        self.b('        g_error_free (error);')
 
824
        self.b('')
 
825
        self.b('      return;')
 
826
        self.b('    }')
 
827
        self.b('')
 
828
 
 
829
        for i, arg in enumerate(out_args):
 
830
            name, info, tp_type, elt = arg
 
831
            ctype, gtype, marshaller, pointer = info
 
832
 
 
833
            self.b('  if (state->%s != NULL)' % name)
 
834
            if marshaller == 'BOXED':
 
835
                self.b('    *state->%s = g_value_dup_boxed ('
 
836
                       'args->values + %d);' % (name, i))
 
837
            elif marshaller == 'STRING':
 
838
                self.b('    *state->%s = g_value_dup_string '
 
839
                       '(args->values + %d);' % (name, i))
 
840
            elif marshaller in ('UCHAR', 'BOOLEAN', 'INT', 'UINT',
 
841
                    'INT64', 'UINT64', 'DOUBLE'):
 
842
                self.b('    *state->%s = g_value_get_%s (args->values + %d);'
 
843
                       % (name, marshaller.lower(), i))
 
844
            else:
 
845
                assert False, "Don't know how to copy %s" % gtype
 
846
 
 
847
            self.b('')
 
848
 
 
849
        if len(out_args) > 0:
 
850
            self.b('  g_value_array_free (args);')
 
851
        else:
 
852
            self.b('  if (args != NULL)')
 
853
            self.b('    g_value_array_free (args);')
 
854
 
 
855
        self.b('}')
 
856
        self.b('')
 
857
 
 
858
        self.h('gboolean %s_%s_run_%s (%sproxy,'
 
859
               % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
 
860
        self.h('    gint timeout_ms,')
 
861
 
 
862
        self.b('/**')
 
863
        self.b(' * %s_%s_run_%s:' % (self.prefix_lc, iface_lc, member_lc))
 
864
        self.b(' * @proxy: %s' % self.proxy_doc)
 
865
        self.b(' * @timeout_ms: Timeout in milliseconds, or -1 for default')
 
866
 
 
867
        for arg in in_args:
 
868
            name, info, tp_type, elt = arg
 
869
            ctype, gtype, marshaller, pointer = info
 
870
 
 
871
            self.b(' * @%s: Used to pass an \'in\' argument: %s'
 
872
                   % (name, xml_escape(get_docstring(elt) or '(Undocumented)')))
 
873
 
 
874
        for arg in out_args:
 
875
            name, info, tp_type, elt = arg
 
876
            ctype, gtype, marshaller, pointer = info
 
877
 
 
878
            self.b(' * @%s: Used to return an \'out\' argument if %%TRUE is '
 
879
                   'returned: %s'
 
880
                   % (name, xml_escape(get_docstring(elt) or '(Undocumented)')))
 
881
 
 
882
        self.b(' * @error: If not %NULL, used to return errors if %FALSE ')
 
883
        self.b(' *  is returned')
 
884
        self.b(' * @loop: If not %NULL, set before re-entering ')
 
885
        self.b(' *  the main loop, to point to a #GMainLoop ')
 
886
        self.b(' *  which can be used to cancel this call with ')
 
887
        self.b(' *  g_main_loop_quit(), causing a return of ')
 
888
        self.b(' *  %FALSE with @error set to %TP_DBUS_ERROR_CANCELLED')
 
889
        self.b(' *')
 
890
        self.b(' * Call the method %s and run the main loop' % member)
 
891
        self.b(' * until it returns. Before calling this method, you must')
 
892
        self.b(' * add a reference to any borrowed objects you need to keep,')
 
893
        self.b(' * and generally ensure that everything is in a consistent')
 
894
        self.b(' * state.')
 
895
        self.b(' *')
 
896
        self.b(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)'))
 
897
        self.b(' *')
 
898
        self.b(' * Returns: TRUE on success, FALSE and sets @error on error')
 
899
        self.b(' */')
 
900
        self.b('gboolean\n%s_%s_run_%s (%sproxy,'
 
901
               % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
 
902
        self.b('    gint timeout_ms,')
 
903
 
 
904
        for arg in in_args:
 
905
            name, info, tp_type, elt = arg
 
906
            ctype, gtype, marshaller, pointer = info
 
907
 
 
908
            const = pointer and 'const ' or ''
 
909
 
 
910
            self.h('    %s%s%s,' % (const, ctype, name))
 
911
            self.b('    %s%s%s,' % (const, ctype, name))
 
912
 
 
913
        for arg in out_args:
 
914
            name, info, tp_type, elt = arg
 
915
            ctype, gtype, marshaller, pointer = info
 
916
 
 
917
            self.h('    %s*%s,' % (ctype, name))
 
918
            self.b('    %s*%s,' % (ctype, name))
 
919
 
 
920
        self.h('    GError **error,')
 
921
        self.h('    GMainLoop **loop);')
 
922
        self.h('')
 
923
 
 
924
        self.b('    GError **error,')
 
925
        self.b('    GMainLoop **loop)')
 
926
        self.b('{')
 
927
        self.b('  DBusGProxy *iface;')
 
928
        self.b('  GQuark interface = %s;' % self.get_iface_quark())
 
929
        self.b('  TpProxyPendingCall *pc;')
 
930
        self.b('  _%s_%s_run_state_%s state = {'
 
931
               % (self.prefix_lc, iface_lc, member_lc))
 
932
        self.b('      NULL /* loop */, error,')
 
933
 
 
934
        for arg in out_args:
 
935
            name, info, tp_type, elt = arg
 
936
 
 
937
            self.b('    %s,' % name)
 
938
 
 
939
        self.b('      FALSE /* completed */, FALSE /* success */ };')
 
940
        self.b('')
 
941
        self.b('  g_return_val_if_fail (%s (proxy), FALSE);'
 
942
               % self.proxy_assert)
 
943
        self.b('')
 
944
        self.b('  iface = tp_proxy_borrow_interface_by_id')
 
945
        self.b('       ((TpProxy *) proxy, interface, error);')
 
946
        self.b('')
 
947
        self.b('  if (iface == NULL)')
 
948
        self.b('    return FALSE;')
 
949
        self.b('')
 
950
        self.b('  state.loop = g_main_loop_new (NULL, FALSE);')
 
951
        self.b('')
 
952
        self.b('  pc = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,')
 
953
        self.b('      interface, "%s", iface,' % member)
 
954
        self.b('      %s,' % reentrant_invoke)
 
955
        self.b('      NULL, &state, NULL, NULL, TRUE);')
 
956
        self.b('')
 
957
        self.b('  if (loop != NULL)')
 
958
        self.b('    *loop = state.loop;')
 
959
        self.b('')
 
960
        self.b('  tp_proxy_pending_call_v0_take_pending_call (pc,')
 
961
        self.b('      dbus_g_proxy_begin_call_with_timeout (iface,')
 
962
        self.b('          "%s",' % member)
 
963
        self.b('          %s,' % collect_callback)
 
964
        self.b('          pc,')
 
965
        self.b('          tp_proxy_pending_call_v0_completed,')
 
966
        self.b('          timeout_ms,')
 
967
 
 
968
        for arg in in_args:
 
969
            name, info, tp_type, elt = arg
 
970
            ctype, gtype, marshaller, pointer = info
 
971
 
 
972
            const = pointer and 'const ' or ''
 
973
 
 
974
            self.b('              %s, %s,' % (gtype, name))
 
975
 
 
976
        self.b('          G_TYPE_INVALID));')
 
977
        self.b('')
 
978
        self.b('  if (!state.completed)')
 
979
        self.b('    g_main_loop_run (state.loop);')
 
980
        self.b('')
 
981
        self.b('  if (!state.completed)')
 
982
        self.b('    tp_proxy_pending_call_cancel (pc);')
 
983
        self.b('')
 
984
        self.b('  if (loop != NULL)')
 
985
        self.b('    *loop = NULL;')
 
986
        self.b('')
 
987
        self.b('  g_main_loop_unref (state.loop);')
 
988
        self.b('')
 
989
        self.b('  return state.success;')
 
990
        self.b('}')
 
991
        self.b('')
 
992
 
 
993
        # leave a gap for the end of the method
 
994
        self.b('')
 
995
        self.h('')
 
996
 
 
997
    def do_signal_add(self, signal):
 
998
        marshaller_items = []
 
999
        gtypes = []
 
1000
 
 
1001
        for i in signal.getElementsByTagName('arg'):
 
1002
            name = i.getAttribute('name')
 
1003
            type = i.getAttribute('type')
 
1004
            info = type_to_gtype(type)
 
1005
            # type, GType, STRING, is a pointer
 
1006
            gtypes.append(info[1])
 
1007
 
 
1008
        self.b('  dbus_g_proxy_add_signal (proxy, "%s",'
 
1009
               % signal.getAttribute('name'))
 
1010
        for gtype in gtypes:
 
1011
            self.b('      %s,' % gtype)
 
1012
        self.b('      G_TYPE_INVALID);')
 
1013
 
 
1014
    def do_interface(self, node):
 
1015
        ifaces = node.getElementsByTagName('interface')
 
1016
        assert len(ifaces) == 1
 
1017
        iface = ifaces[0]
 
1018
        name = node.getAttribute('name').replace('/', '')
 
1019
 
 
1020
        self.iface = name
 
1021
        self.iface_lc = name.lower()
 
1022
        self.iface_uc = name.upper()
 
1023
        self.iface_mc = name.replace('_', '')
 
1024
        self.iface_dbus = iface.getAttribute('name')
 
1025
 
 
1026
        signals = node.getElementsByTagName('signal')
 
1027
        methods = node.getElementsByTagName('method')
 
1028
 
 
1029
        self.b('static inline void')
 
1030
        self.b('%s_add_signals_for_%s (DBusGProxy *proxy)'
 
1031
                % (self.prefix_lc, name.lower()))
 
1032
        self.b('{')
 
1033
 
 
1034
        for signal in signals:
 
1035
            self.do_signal_add(signal)
 
1036
 
 
1037
        self.b('}')
 
1038
        self.b('')
 
1039
        self.b('')
 
1040
 
 
1041
        for signal in signals:
 
1042
            self.do_signal(name, signal)
 
1043
 
 
1044
        for method in methods:
 
1045
            self.do_method(name, method)
 
1046
 
 
1047
        self.iface_dbus = None
 
1048
 
 
1049
    def __call__(self):
 
1050
 
 
1051
        self.h('G_BEGIN_DECLS')
 
1052
        self.h('')
 
1053
 
 
1054
        self.b('/* We don\'t want gtkdoc scanning this file, it\'ll get')
 
1055
        self.b(' * confused by seeing function definitions, so mark it as: */')
 
1056
        self.b('/*<private_header>*/')
 
1057
        self.b('')
 
1058
 
 
1059
        nodes = self.dom.getElementsByTagName('node')
 
1060
        nodes.sort(cmp_by_name)
 
1061
 
 
1062
        for node in nodes:
 
1063
            self.do_interface(node)
 
1064
 
 
1065
        if self.group is not None:
 
1066
 
 
1067
            self.b('/*')
 
1068
            self.b(' * %s_%s_add_signals:' % (self.prefix_lc, self.group))
 
1069
            self.b(' * @self: the #TpProxy')
 
1070
            self.b(' * @quark: a quark whose string value is the interface')
 
1071
            self.b(' *   name whose signals should be added')
 
1072
            self.b(' * @proxy: the D-Bus proxy to which to add the signals')
 
1073
            self.b(' * @unused: not used for anything')
 
1074
            self.b(' *')
 
1075
            self.b(' * Tell dbus-glib that @proxy has the signatures of all')
 
1076
            self.b(' * signals on the given interface, if it\'s one we')
 
1077
            self.b(' * support.')
 
1078
            self.b(' *')
 
1079
            self.b(' * This function should be used as a signal handler for')
 
1080
            self.b(' * #TpProxy::interface-added.')
 
1081
            self.b(' */')
 
1082
            self.b('static void')
 
1083
            self.b('%s_%s_add_signals (TpProxy *self,'
 
1084
                    % (self.prefix_lc, self.group))
 
1085
            self.b('    guint quark,')
 
1086
            self.b('    DBusGProxy *proxy,')
 
1087
            self.b('    gpointer unused)')
 
1088
 
 
1089
            self.b('{')
 
1090
 
 
1091
            for node in nodes:
 
1092
                iface = node.getElementsByTagName('interface')[0]
 
1093
                self.iface_dbus = iface.getAttribute('name')
 
1094
                name = node.getAttribute('name').replace('/', '').lower()
 
1095
                self.iface_uc = name.upper()
 
1096
                self.b('  if (quark == %s)' % self.get_iface_quark())
 
1097
                self.b('    %s_add_signals_for_%s (proxy);'
 
1098
                       % (self.prefix_lc, name))
 
1099
 
 
1100
            self.b('}')
 
1101
            self.b('')
 
1102
 
 
1103
        self.h('G_END_DECLS')
 
1104
        self.h('')
 
1105
 
 
1106
        open(self.basename + '.h', 'w').write('\n'.join(self.__header))
 
1107
        open(self.basename + '-body.h', 'w').write('\n'.join(self.__body))
 
1108
 
 
1109
 
 
1110
def types_to_gtypes(types):
 
1111
    return [type_to_gtype(t)[1] for t in types]
 
1112
 
 
1113
 
 
1114
if __name__ == '__main__':
 
1115
    options, argv = gnu_getopt(sys.argv[1:], '',
 
1116
                               ['group=', 'subclass=', 'subclass-assert=',
 
1117
                                'iface-quark-prefix='])
 
1118
 
 
1119
    opts = {}
 
1120
 
 
1121
    for option, value in options:
 
1122
        opts[option] = value
 
1123
 
 
1124
    dom = xml.dom.minidom.parse(argv[0])
 
1125
 
 
1126
    Generator(dom, argv[1], argv[2], opts)()