~ubuntu-branches/ubuntu/precise/telepathy-mission-control-5/precise

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Simon McVittie
  • Date: 2009-07-30 12:11:55 UTC
  • mto: (0.4.1 upstream) (7.1.1 lucid) (1.1.6 upstream)
  • mto: This revision was merged to the branch mainline in revision 6.
  • Revision ID: james.westby@ubuntu.com-20090730121155-6745f645s3fg1mpk
ImportĀ upstreamĀ versionĀ 5.2.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
 
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: <![CDATA[%s]]>' % (name,
 
122
                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(' * <![CDATA[%s]]>'
 
297
                % (get_docstring(signal) or '(Undocumented)'))
 
298
        self.b(' *')
 
299
        self.b(' * Returns: a #TpProxySignalConnection containing all of the')
 
300
        self.b(' * above, which can be used to disconnect the signal; or')
 
301
        self.b(' * %NULL if the proxy does not have the desired interface')
 
302
        self.b(' * or has become invalid.')
 
303
        self.b(' */')
 
304
        self.h('TpProxySignalConnection *%s_%s_connect_to_%s (%sproxy,'
 
305
               % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
 
306
        self.h('    %s callback,' % callback_name)
 
307
        self.h('    gpointer user_data,')
 
308
        self.h('    GDestroyNotify destroy,')
 
309
        self.h('    GObject *weak_object,')
 
310
        self.h('    GError **error);')
 
311
 
 
312
        self.b('TpProxySignalConnection *')
 
313
        self.b('%s_%s_connect_to_%s (%sproxy,'
 
314
               % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
 
315
        self.b('    %s callback,' % callback_name)
 
316
        self.b('    gpointer user_data,')
 
317
        self.b('    GDestroyNotify destroy,')
 
318
        self.b('    GObject *weak_object,')
 
319
        self.b('    GError **error)')
 
320
        self.b('{')
 
321
        self.b('  GType expected_types[%d] = {' % (len(args) + 1))
 
322
 
 
323
        for arg in args:
 
324
            name, info, tp_type, elt = arg
 
325
            ctype, gtype, marshaller, pointer = info
 
326
 
 
327
            self.b('      %s,' % gtype)
 
328
 
 
329
        self.b('      G_TYPE_INVALID };')
 
330
        self.b('')
 
331
        self.b('  g_return_val_if_fail (%s (proxy), NULL);'
 
332
               % self.proxy_assert)
 
333
        self.b('  g_return_val_if_fail (callback != NULL, NULL);')
 
334
        self.b('')
 
335
        self.b('  return tp_proxy_signal_connection_v0_new ((TpProxy *) proxy,')
 
336
        self.b('      %s, \"%s\",' % (self.get_iface_quark(), member))
 
337
        self.b('      expected_types,')
 
338
 
 
339
        if args:
 
340
            self.b('      G_CALLBACK (%s),' % collect_name)
 
341
        else:
 
342
            self.b('      NULL, /* no args => no collector function */')
 
343
 
 
344
        self.b('      %s,' % invoke_name)
 
345
        self.b('      G_CALLBACK (callback), user_data, destroy,')
 
346
        self.b('      weak_object, error);')
 
347
        self.b('}')
 
348
        self.b('')
 
349
 
 
350
        self.h('')
 
351
 
 
352
    def do_method(self, iface, method):
 
353
        iface_lc = iface.lower()
 
354
 
 
355
        member = method.getAttribute('name')
 
356
        member_lc = camelcase_to_lower(member)
 
357
        member_uc = member_lc.upper()
 
358
 
 
359
        in_count = 0
 
360
        ret_count = 0
 
361
        in_args = []
 
362
        out_args = []
 
363
 
 
364
        for arg in method.getElementsByTagName('arg'):
 
365
            name = arg.getAttribute('name')
 
366
            direction = arg.getAttribute('direction')
 
367
            type = arg.getAttribute('type')
 
368
            tp_type = arg.getAttribute('tp:type')
 
369
 
 
370
            if direction != 'out':
 
371
                if not name:
 
372
                    name = 'in%u' % in_count
 
373
                    in_count += 1
 
374
                else:
 
375
                    name = 'in_%s' % name
 
376
            else:
 
377
                if not name:
 
378
                    name = 'out%u' % ret_count
 
379
                    ret_count += 1
 
380
                else:
 
381
                    name = 'out_%s' % name
 
382
 
 
383
            info = type_to_gtype(type)
 
384
            if direction != 'out':
 
385
                in_args.append((name, info, tp_type, arg))
 
386
            else:
 
387
                out_args.append((name, info, tp_type, arg))
 
388
 
 
389
        # Async reply callback type
 
390
 
 
391
        # Example:
 
392
        # void (*tp_cli_properties_interface_callback_for_get_properties)
 
393
        #   (TpProxy *proxy,
 
394
        #       const GPtrArray *out0,
 
395
        #       const GError *error,
 
396
        #       gpointer user_data,
 
397
        #       GObject *weak_object);
 
398
 
 
399
        self.b('/**')
 
400
        self.b(' * %s_%s_callback_for_%s:'
 
401
               % (self.prefix_lc, iface_lc, member_lc))
 
402
        self.b(' * @proxy: the proxy on which the call was made')
 
403
 
 
404
        for arg in out_args:
 
405
            name, info, tp_type, elt = arg
 
406
            ctype, gtype, marshaller, pointer = info
 
407
 
 
408
            self.b(' * @%s: Used to return an \'out\' argument if @error is '
 
409
                   '%%NULL: <![CDATA[%s]]>'
 
410
                   % (name, get_docstring(elt) or '(Undocumented)'))
 
411
 
 
412
        self.b(' * @error: %NULL on success, or an error on failure')
 
413
        self.b(' * @user_data: user-supplied data')
 
414
        self.b(' * @weak_object: user-supplied object')
 
415
        self.b(' *')
 
416
        self.b(' * Signature of the callback called when a %s method call'
 
417
               % member)
 
418
        self.b(' * succeeds or fails.')
 
419
        self.b(' */')
 
420
 
 
421
        callback_name = '%s_%s_callback_for_%s' % (self.prefix_lc, iface_lc,
 
422
                                                   member_lc)
 
423
 
 
424
        self.h('typedef void (*%s) (%sproxy,'
 
425
               % (callback_name, self.proxy_cls))
 
426
 
 
427
        for arg in out_args:
 
428
            name, info, tp_type, elt = arg
 
429
            ctype, gtype, marshaller, pointer = info
 
430
            const = pointer and 'const ' or ''
 
431
 
 
432
            self.h('    %s%s%s,' % (const, ctype, name))
 
433
 
 
434
        self.h('    const GError *error, gpointer user_data,')
 
435
        self.h('    GObject *weak_object);')
 
436
        self.h('')
 
437
 
 
438
        # Async callback implementation
 
439
 
 
440
        invoke_callback = '_%s_%s_invoke_callback_%s' % (self.prefix_lc,
 
441
                                                         iface_lc,
 
442
                                                         member_lc)
 
443
 
 
444
        collect_callback = '_%s_%s_collect_callback_%s' % (self.prefix_lc,
 
445
                                                           iface_lc,
 
446
                                                           member_lc)
 
447
 
 
448
        # The callback called by dbus-glib; this ends the call and collects
 
449
        # the results into a GValueArray.
 
450
        self.b('static void')
 
451
        self.b('%s (DBusGProxy *proxy,' % collect_callback)
 
452
        self.b('    DBusGProxyCall *call,')
 
453
        self.b('    gpointer user_data)')
 
454
        self.b('{')
 
455
        self.b('  GError *error = NULL;')
 
456
 
 
457
        if len(out_args) > 0:
 
458
            self.b('  GValueArray *args;')
 
459
            self.b('  GValue blank = { 0 };')
 
460
            self.b('  guint i;')
 
461
 
 
462
            for arg in out_args:
 
463
                name, info, tp_type, elt = arg
 
464
                ctype, gtype, marshaller, pointer = info
 
465
 
 
466
                self.b('  %s%s;' % (ctype, name))
 
467
 
 
468
        self.b('')
 
469
        self.b('  dbus_g_proxy_end_call (proxy, call, &error,')
 
470
 
 
471
        for arg in out_args:
 
472
            name, info, tp_type, elt = arg
 
473
            ctype, gtype, marshaller, pointer = info
 
474
 
 
475
            self.b('      %s, &%s,' % (gtype, name))
 
476
 
 
477
        self.b('      G_TYPE_INVALID);')
 
478
 
 
479
        if len(out_args) == 0:
 
480
            self.b('  tp_proxy_pending_call_v0_take_results (user_data, error,'
 
481
                   'NULL);')
 
482
        else:
 
483
            self.b('')
 
484
            self.b('  if (error != NULL)')
 
485
            self.b('    {')
 
486
            self.b('      tp_proxy_pending_call_v0_take_results (user_data, error,')
 
487
            self.b('          NULL);')
 
488
            self.b('      return;')
 
489
            self.b('    }')
 
490
            self.b('')
 
491
            self.b('  args = g_value_array_new (%d);' % len(out_args))
 
492
            self.b('  g_value_init (&blank, G_TYPE_INT);')
 
493
            self.b('')
 
494
            self.b('  for (i = 0; i < %d; i++)' % len(out_args))
 
495
            self.b('    g_value_array_append (args, &blank);')
 
496
 
 
497
            for i, arg in enumerate(out_args):
 
498
                name, info, tp_type, elt = arg
 
499
                ctype, gtype, marshaller, pointer = info
 
500
 
 
501
                self.b('')
 
502
                self.b('  g_value_unset (args->values + %d);' % i)
 
503
                self.b('  g_value_init (args->values + %d, %s);' % (i, gtype))
 
504
 
 
505
                if gtype == 'G_TYPE_STRING':
 
506
                    self.b('  g_value_take_string (args->values + %d, %s);'
 
507
                           % (i, name))
 
508
                elif marshaller == 'BOXED':
 
509
                    self.b('  g_value_take_boxed (args->values + %d, %s);'
 
510
                            % (i, name))
 
511
                elif gtype == 'G_TYPE_UCHAR':
 
512
                    self.b('  g_value_set_uchar (args->values + %d, %s);'
 
513
                            % (i, name))
 
514
                elif gtype == 'G_TYPE_BOOLEAN':
 
515
                    self.b('  g_value_set_boolean (args->values + %d, %s);'
 
516
                            % (i, name))
 
517
                elif gtype == 'G_TYPE_INT':
 
518
                    self.b('  g_value_set_int (args->values + %d, %s);'
 
519
                            % (i, name))
 
520
                elif gtype == 'G_TYPE_UINT':
 
521
                    self.b('  g_value_set_uint (args->values + %d, %s);'
 
522
                            % (i, name))
 
523
                elif gtype == 'G_TYPE_INT64':
 
524
                    self.b('  g_value_set_int (args->values + %d, %s);'
 
525
                            % (i, name))
 
526
                elif gtype == 'G_TYPE_UINT64':
 
527
                    self.b('  g_value_set_uint (args->values + %d, %s);'
 
528
                            % (i, name))
 
529
                elif gtype == 'G_TYPE_DOUBLE':
 
530
                    self.b('  g_value_set_double (args->values + %d, %s);'
 
531
                            % (i, name))
 
532
                else:
 
533
                    assert False, ("Don't know how to put %s in a GValue"
 
534
                                   % gtype)
 
535
 
 
536
            self.b('  tp_proxy_pending_call_v0_take_results (user_data, '
 
537
                   'NULL, args);')
 
538
 
 
539
        self.b('}')
 
540
 
 
541
        self.b('static void')
 
542
        self.b('%s (TpProxy *self,' % invoke_callback)
 
543
        self.b('    GError *error,')
 
544
        self.b('    GValueArray *args,')
 
545
        self.b('    GCallback generic_callback,')
 
546
        self.b('    gpointer user_data,')
 
547
        self.b('    GObject *weak_object)')
 
548
        self.b('{')
 
549
        self.b('  %s callback = (%s) generic_callback;'
 
550
               % (callback_name, callback_name))
 
551
        self.b('')
 
552
        self.b('  if (error != NULL)')
 
553
        self.b('    {')
 
554
        self.b('      callback ((%s) self,' % self.proxy_cls)
 
555
 
 
556
        for arg in out_args:
 
557
            name, info, tp_type, elt = arg
 
558
            ctype, gtype, marshaller, pointer = info
 
559
 
 
560
            if marshaller == 'BOXED' or pointer:
 
561
                self.b('          NULL,')
 
562
            elif gtype == 'G_TYPE_DOUBLE':
 
563
                self.b('          0.0,')
 
564
            else:
 
565
                self.b('          0,')
 
566
 
 
567
        self.b('          error, user_data, weak_object);')
 
568
        self.b('      g_error_free (error);')
 
569
        self.b('      return;')
 
570
        self.b('    }')
 
571
 
 
572
        self.b('  callback ((%s) self,' % self.proxy_cls)
 
573
 
 
574
        # FIXME: factor out into a function
 
575
        for i, arg in enumerate(out_args):
 
576
            name, info, tp_type, elt = arg
 
577
            ctype, gtype, marshaller, pointer = info
 
578
 
 
579
            if marshaller == 'BOXED':
 
580
                self.b('      g_value_get_boxed (args->values + %d),' % i)
 
581
            elif gtype == 'G_TYPE_STRING':
 
582
                self.b('      g_value_get_string (args->values + %d),' % i)
 
583
            elif gtype == 'G_TYPE_UCHAR':
 
584
                self.b('      g_value_get_uchar (args->values + %d),' % i)
 
585
            elif gtype == 'G_TYPE_BOOLEAN':
 
586
                self.b('      g_value_get_boolean (args->values + %d),' % i)
 
587
            elif gtype == 'G_TYPE_UINT':
 
588
                self.b('      g_value_get_uint (args->values + %d),' % i)
 
589
            elif gtype == 'G_TYPE_INT':
 
590
                self.b('      g_value_get_int (args->values + %d),' % i)
 
591
            elif gtype == 'G_TYPE_UINT64':
 
592
                self.b('      g_value_get_uint64 (args->values + %d),' % i)
 
593
            elif gtype == 'G_TYPE_INT64':
 
594
                self.b('      g_value_get_int64 (args->values + %d),' % i)
 
595
            elif gtype == 'G_TYPE_DOUBLE':
 
596
                self.b('      g_value_get_double (args->values + %d),' % i)
 
597
            else:
 
598
                assert False, "Don't know how to get %s from a GValue" % gtype
 
599
 
 
600
        self.b('      error, user_data, weak_object);')
 
601
        self.b('')
 
602
 
 
603
        if len(out_args) > 0:
 
604
            self.b('  g_value_array_free (args);')
 
605
        else:
 
606
            self.b('  if (args != NULL)')
 
607
            self.b('    g_value_array_free (args);')
 
608
 
 
609
        self.b('}')
 
610
        self.b('')
 
611
 
 
612
        # Async stub
 
613
 
 
614
        # Example:
 
615
        # TpProxyPendingCall *
 
616
        #   tp_cli_properties_interface_call_get_properties
 
617
        #   (gpointer proxy,
 
618
        #   gint timeout_ms,
 
619
        #   const GArray *in_properties,
 
620
        #   tp_cli_properties_interface_callback_for_get_properties callback,
 
621
        #   gpointer user_data,
 
622
        #   GDestroyNotify *destructor);
 
623
 
 
624
        self.h('TpProxyPendingCall *%s_%s_call_%s (%sproxy,'
 
625
               % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
 
626
        self.h('    gint timeout_ms,')
 
627
 
 
628
        self.b('/**')
 
629
        self.b(' * %s_%s_call_%s:'
 
630
               % (self.prefix_lc, iface_lc, member_lc))
 
631
        self.b(' * @proxy: the #TpProxy')
 
632
        self.b(' * @timeout_ms: the timeout in milliseconds, or -1 to use the')
 
633
        self.b(' *   default')
 
634
 
 
635
        for arg in in_args:
 
636
            name, info, tp_type, elt = arg
 
637
            ctype, gtype, marshaller, pointer = info
 
638
 
 
639
            self.b(' * @%s: Used to pass an \'in\' argument: <![CDATA[%s]]>'
 
640
                   % (name, get_docstring(elt) or '(Undocumented)'))
 
641
 
 
642
        self.b(' * @callback: called when the method call succeeds or fails')
 
643
        self.b(' * @user_data: user-supplied data passed to the callback')
 
644
        self.b(' * @destroy: called with the user_data as argument, after the')
 
645
        self.b(' *   call has succeeded, failed or been cancelled')
 
646
        self.b(' * @weak_object: A #GObject which will be weakly referenced; ')
 
647
        self.b(' *   if it is destroyed, this callback will automatically be')
 
648
        self.b(' *   disconnected')
 
649
        self.b(' *')
 
650
        self.b(' * Start a %s method call.' % member)
 
651
        self.b(' *')
 
652
        self.b(' * <![CDATA[%s]]>'
 
653
                % (get_docstring(method) or '(Undocumented)'))
 
654
        self.b(' *')
 
655
        self.b(' * Returns: a #TpProxyPendingCall representing the call in')
 
656
        self.b(' *  progress. It is borrowed from the object, and will become')
 
657
        self.b(' *  invalid when the callback is called, the call is')
 
658
        self.b(' *  cancelled or the #TpProxy becomes invalid.')
 
659
        self.b(' */')
 
660
        self.b('TpProxyPendingCall *\n%s_%s_call_%s (%sproxy,'
 
661
               % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
 
662
        self.b('    gint timeout_ms,')
 
663
 
 
664
        for arg in in_args:
 
665
            name, info, tp_type, elt = arg
 
666
            ctype, gtype, marshaller, pointer = info
 
667
 
 
668
            const = pointer and 'const ' or ''
 
669
 
 
670
            self.h('    %s%s%s,' % (const, ctype, name))
 
671
            self.b('    %s%s%s,' % (const, ctype, name))
 
672
 
 
673
        self.h('    %s callback,' % callback_name)
 
674
        self.h('    gpointer user_data,')
 
675
        self.h('    GDestroyNotify destroy,')
 
676
        self.h('    GObject *weak_object);')
 
677
        self.h('')
 
678
 
 
679
        self.b('    %s callback,' % callback_name)
 
680
        self.b('    gpointer user_data,')
 
681
        self.b('    GDestroyNotify destroy,')
 
682
        self.b('    GObject *weak_object)')
 
683
        self.b('{')
 
684
        self.b('  GError *error = NULL;')
 
685
        self.b('  GQuark interface = %s;' % self.get_iface_quark())
 
686
        self.b('  DBusGProxy *iface;')
 
687
        self.b('')
 
688
        self.b('  g_return_val_if_fail (%s (proxy), NULL);'
 
689
               % self.proxy_assert)
 
690
        self.b('')
 
691
        self.b('  iface = tp_proxy_borrow_interface_by_id (')
 
692
        self.b('      (TpProxy *) proxy,')
 
693
        self.b('      interface, &error);')
 
694
        self.b('')
 
695
        self.b('  if (iface == NULL)')
 
696
        self.b('    {')
 
697
        self.b('      if (callback != NULL)')
 
698
        self.b('        callback (proxy,')
 
699
 
 
700
        for arg in out_args:
 
701
            name, info, tp_type, elt = arg
 
702
            ctype, gtype, marshaller, pointer = info
 
703
 
 
704
            if pointer:
 
705
                self.b('            NULL,')
 
706
            else:
 
707
                self.b('            0,')
 
708
 
 
709
        self.b('            error, user_data, weak_object);')
 
710
        self.b('      g_error_free (error);')
 
711
        self.b('      return NULL;')
 
712
        self.b('    }')
 
713
        self.b('')
 
714
        self.b('  if (callback == NULL)')
 
715
        self.b('    {')
 
716
        self.b('      dbus_g_proxy_call_no_reply (iface, "%s",' % member)
 
717
 
 
718
        for arg in in_args:
 
719
            name, info, tp_type, elt = arg
 
720
            ctype, gtype, marshaller, pointer = info
 
721
 
 
722
            const = pointer and 'const ' or ''
 
723
 
 
724
            self.b('          %s, %s,' % (gtype, name))
 
725
 
 
726
        self.b('          G_TYPE_INVALID);')
 
727
        self.b('      return NULL;')
 
728
        self.b('    }')
 
729
        self.b('  else')
 
730
        self.b('    {')
 
731
        self.b('      TpProxyPendingCall *data;')
 
732
        self.b('')
 
733
        self.b('      data = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,')
 
734
        self.b('          interface, "%s", iface,' % member)
 
735
        self.b('          %s,' % invoke_callback)
 
736
        self.b('          G_CALLBACK (callback), user_data, destroy,')
 
737
        self.b('          weak_object, FALSE);')
 
738
        self.b('      tp_proxy_pending_call_v0_take_pending_call (data,')
 
739
        self.b('          dbus_g_proxy_begin_call_with_timeout (iface,')
 
740
        self.b('              "%s",' % member)
 
741
        self.b('              %s,' % collect_callback)
 
742
        self.b('              data,')
 
743
        self.b('              tp_proxy_pending_call_v0_completed,')
 
744
        self.b('              timeout_ms,')
 
745
 
 
746
        for arg in in_args:
 
747
            name, info, tp_type, elt = arg
 
748
            ctype, gtype, marshaller, pointer = info
 
749
 
 
750
            const = pointer and 'const ' or ''
 
751
 
 
752
            self.b('              %s, %s,' % (gtype, name))
 
753
 
 
754
        self.b('              G_TYPE_INVALID));')
 
755
        self.b('')
 
756
        self.b('      return data;')
 
757
        self.b('    }')
 
758
        self.b('}')
 
759
        self.b('')
 
760
 
 
761
        # Non reentrant blocking calls
 
762
        # Example:
 
763
        # gboolean tp_cli_properties_interface_do_get_properties
 
764
        #   (gpointer proxy,
 
765
        #       gint timeout_ms,
 
766
        #       const GArray *in_properties,
 
767
        #       GPtrArray **out0,
 
768
        #       GError **error);
 
769
 
 
770
        self.h('gboolean %s_%s_do_%s (%sproxy,'
 
771
               % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
 
772
        self.h('    gint timeout_ms,')
 
773
 
 
774
        self.b('/**')
 
775
        self.b(' * %s_%s_do_%s:' % (self.prefix_lc, iface_lc, member_lc))
 
776
        self.b(' * @proxy: %s' % self.proxy_doc)
 
777
        self.b(' * @timeout_ms: Timeout in milliseconds, or -1 for default')
 
778
 
 
779
        for arg in in_args:
 
780
            name, info, tp_type, elt = arg
 
781
            ctype, gtype, marshaller, pointer = info
 
782
 
 
783
            self.b(' * @%s: Used to pass an \'in\' argument: <![CDATA[%s]]>'
 
784
                   % (name, get_docstring(elt) or '(Undocumented)'))
 
785
 
 
786
        for arg in out_args:
 
787
            name, info, tp_type, elt = arg
 
788
            ctype, gtype, marshaller, pointer = info
 
789
 
 
790
            self.b(' * @%s: Used to return an \'out\' argument if %%TRUE is '
 
791
                   'returned: <![CDATA[%s]]>'
 
792
                   % (name, get_docstring(elt) or '(Undocumented)'))
 
793
 
 
794
        self.b(' * @error: If not %NULL, used to return errors if %FALSE ')
 
795
        self.b(' *  is returned')
 
796
        self.b(' *')
 
797
        self.b(' * Call the method %s and block' % member)
 
798
        self.b(' * until it returns.')
 
799
        self.b(' *')
 
800
        self.b(' * <![CDATA[%s]]>'
 
801
                % (get_docstring(method) or '(Undocumented)'))
 
802
        self.b(' *')
 
803
        self.b(' * Returns: TRUE on success, FALSE and sets @error on error')
 
804
        self.b(' */')
 
805
        self.b('gboolean\n%s_%s_do_%s (%sproxy,'
 
806
               % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
 
807
        self.b('    gint timeout_ms,')
 
808
 
 
809
        for arg in in_args:
 
810
            name, info, tp_type, elt = arg
 
811
            ctype, gtype, marshaller, pointer = info
 
812
 
 
813
            const = pointer and 'const ' or ''
 
814
 
 
815
            self.h('    %s%s%s,' % (const, ctype, name))
 
816
            self.b('    %s%s%s,' % (const, ctype, name))
 
817
 
 
818
        for arg in out_args:
 
819
            name, info, tp_type, elt = arg
 
820
            ctype, gtype, marshaller, pointer = info
 
821
 
 
822
            self.h('    %s*%s,' % (ctype, name))
 
823
            self.b('    %s*%s,' % (ctype, name))
 
824
 
 
825
        self.h('    GError **error);')
 
826
        self.h('')
 
827
 
 
828
        self.b('    GError **error)')
 
829
        self.b('{')
 
830
        self.b('  DBusGProxy *iface;')
 
831
        self.b('  GQuark interface = %s;' % self.get_iface_quark())
 
832
        for arg in out_args:
 
833
            name, info, tp_type, elt = arg
 
834
            ctype, gtype, marshaller, pointer = info
 
835
 
 
836
            self.b('  %si_%s;' % (ctype, name))
 
837
        self.b('')
 
838
        self.b('  g_return_val_if_fail (%s (proxy), FALSE);'
 
839
               % self.proxy_assert)
 
840
        self.b('')
 
841
        self.b('  iface = tp_proxy_borrow_interface_by_id')
 
842
        self.b('       ((TpProxy *) proxy, interface, error);')
 
843
        self.b('')
 
844
        self.b('  if (iface == NULL)')
 
845
        self.b('    return FALSE;')
 
846
        self.b('')
 
847
        self.b('  if (dbus_g_proxy_call_with_timeout (iface,')
 
848
        self.b('      "%s",' % member)
 
849
        self.b('      timeout_ms,')
 
850
        self.b('      error,')
 
851
 
 
852
        for arg in in_args:
 
853
            name, info, tp_type, elt = arg
 
854
            ctype, gtype, marshaller, pointer = info
 
855
 
 
856
            const = pointer and 'const ' or ''
 
857
 
 
858
            self.b('      %s, %s,' % (gtype, name))
 
859
 
 
860
        self.b('      G_TYPE_INVALID,')
 
861
 
 
862
        for arg in out_args:
 
863
            name, info, tp_type, elt = arg
 
864
            ctype, gtype, marshaller, pointer = info
 
865
 
 
866
            self.b('      %s, &i_%s,' % (gtype, name))
 
867
        self.b('      G_TYPE_INVALID))')
 
868
        self.b('  {')
 
869
        for arg in out_args:
 
870
            name, info, tp_type, elt = arg
 
871
            ctype, gtype, marshaller, pointer = info
 
872
 
 
873
            self.b('      *%s = i_%s;' % (name, name))
 
874
        self.b('      return TRUE;')
 
875
        self.b('  }')
 
876
        self.b('  else')
 
877
        self.b('      return FALSE;')
 
878
        self.b('}')
 
879
        self.b('')
 
880
 
 
881
        # leave a gap for the end of the method
 
882
        self.b('')
 
883
        self.h('')
 
884
 
 
885
    def do_signal_add(self, signal):
 
886
        marshaller_items = []
 
887
        gtypes = []
 
888
 
 
889
        for i in signal.getElementsByTagName('arg'):
 
890
            name = i.getAttribute('name')
 
891
            type = i.getAttribute('type')
 
892
            info = type_to_gtype(type)
 
893
            # type, GType, STRING, is a pointer
 
894
            gtypes.append(info[1])
 
895
 
 
896
        self.b('  dbus_g_proxy_add_signal (proxy, "%s",'
 
897
               % signal.getAttribute('name'))
 
898
        for gtype in gtypes:
 
899
            self.b('      %s,' % gtype)
 
900
        self.b('      G_TYPE_INVALID);')
 
901
 
 
902
    def do_interface(self, node):
 
903
        ifaces = node.getElementsByTagName('interface')
 
904
        assert len(ifaces) == 1
 
905
        iface = ifaces[0]
 
906
        name = node.getAttribute('name').replace('/', '')
 
907
 
 
908
        self.iface = name
 
909
        self.iface_lc = name.lower()
 
910
        self.iface_uc = name.upper()
 
911
        self.iface_mc = name.replace('_', '')
 
912
        self.iface_dbus = iface.getAttribute('name')
 
913
 
 
914
        signals = node.getElementsByTagName('signal')
 
915
        methods = node.getElementsByTagName('method')
 
916
 
 
917
        self.b('static inline void')
 
918
        self.b('%s_add_signals_for_%s (DBusGProxy *proxy)'
 
919
                % (self.prefix_lc, name.lower()))
 
920
        self.b('{')
 
921
 
 
922
        for signal in signals:
 
923
            self.do_signal_add(signal)
 
924
 
 
925
        self.b('}')
 
926
        self.b('')
 
927
        self.b('')
 
928
 
 
929
        for signal in signals:
 
930
            self.do_signal(name, signal)
 
931
 
 
932
        for method in methods:
 
933
            self.do_method(name, method)
 
934
 
 
935
        self.iface_dbus = None
 
936
 
 
937
    def __call__(self):
 
938
 
 
939
        self.h('G_BEGIN_DECLS')
 
940
        self.h('')
 
941
 
 
942
        self.b('/* We don\'t want gtkdoc scanning this file, it\'ll get')
 
943
        self.b(' * confused by seeing function definitions, so mark it as: */')
 
944
        self.b('/*<private_header>*/')
 
945
        self.b('')
 
946
 
 
947
        nodes = self.dom.getElementsByTagName('node')
 
948
        nodes.sort(cmp_by_name)
 
949
 
 
950
        for node in nodes:
 
951
            self.do_interface(node)
 
952
 
 
953
        if self.group is not None:
 
954
 
 
955
            self.b('/*')
 
956
            self.b(' * %s_%s_add_signals:' % (self.prefix_lc, self.group))
 
957
            self.b(' * @self: the #TpProxy')
 
958
            self.b(' * @quark: a quark whose string value is the interface')
 
959
            self.b(' *   name whose signals should be added')
 
960
            self.b(' * @proxy: the D-Bus proxy to which to add the signals')
 
961
            self.b(' * @unused: not used for anything')
 
962
            self.b(' *')
 
963
            self.b(' * Tell dbus-glib that @proxy has the signatures of all')
 
964
            self.b(' * signals on the given interface, if it\'s one we')
 
965
            self.b(' * support.')
 
966
            self.b(' *')
 
967
            self.b(' * This function should be used as a signal handler for')
 
968
            self.b(' * #TpProxy::interface-added.')
 
969
            self.b(' */')
 
970
            self.b('static void')
 
971
            self.b('%s_%s_add_signals (TpProxy *self,'
 
972
                    % (self.prefix_lc, self.group))
 
973
            self.b('    guint quark,')
 
974
            self.b('    DBusGProxy *proxy,')
 
975
            self.b('    gpointer unused)')
 
976
 
 
977
            self.b('{')
 
978
 
 
979
            for node in nodes:
 
980
                iface = node.getElementsByTagName('interface')[0]
 
981
                self.iface_dbus = iface.getAttribute('name')
 
982
                name = node.getAttribute('name').replace('/', '').lower()
 
983
                self.iface_uc = name.upper()
 
984
                self.b('  if (quark == %s)' % self.get_iface_quark())
 
985
                self.b('    %s_add_signals_for_%s (proxy);'
 
986
                       % (self.prefix_lc, name))
 
987
 
 
988
            self.b('}')
 
989
            self.b('')
 
990
 
 
991
        self.h('G_END_DECLS')
 
992
        self.h('')
 
993
 
 
994
        open(self.basename + '.h', 'w').write('\n'.join(self.__header))
 
995
        open(self.basename + '-body.h', 'w').write('\n'.join(self.__body))
 
996
 
 
997
 
 
998
def types_to_gtypes(types):
 
999
    return [type_to_gtype(t)[1] for t in types]
 
1000
 
 
1001
 
 
1002
if __name__ == '__main__':
 
1003
    options, argv = gnu_getopt(sys.argv[1:], '',
 
1004
                               ['group=', 'subclass=', 'subclass-assert=',
 
1005
                                'iface-quark-prefix='])
 
1006
 
 
1007
    opts = {}
 
1008
 
 
1009
    for option, value in options:
 
1010
        opts[option] = value
 
1011
 
 
1012
    dom = xml.dom.minidom.parse(argv[0])
 
1013
 
 
1014
    Generator(dom, argv[1], argv[2], opts)()