3 # glib-client-gen.py: "I Can't Believe It's Not dbus-binding-tool"
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.
9 # Copyright (C) 2006-2008 Collabora Ltd. <http://www.collabora.co.uk/>
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.
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.
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
27 import xml
.dom
.minidom
28 from getopt
import gnu_getopt
30 from libglibcodegen
import Signature
, type_to_gtype
, cmp_by_name
, \
31 camelcase_to_lower
, get_docstring
, xml_escape
34 NS_TP
= "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
36 class Generator(object):
38 def __init__(self
, dom
, prefix
, basename
, opts
):
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
.tp_proxy_api
= tuple(map(int,
50 opts
.get('--tp-proxy-api', '0').split('.')))
51 self
.proxy_cls
= opts
.get('--subclass', 'TpProxy') + ' *'
52 self
.proxy_arg
= opts
.get('--subclass', 'void') + ' *'
53 self
.proxy_assert
= opts
.get('--subclass-assert', 'TP_IS_PROXY')
54 self
.proxy_doc
= ('A #%s or subclass'
55 % opts
.get('--subclass', 'TpProxy'))
56 if self
.proxy_arg
== 'void *':
57 self
.proxy_arg
= 'gpointer '
60 if isinstance(s
, unicode):
62 self
.__header
.append(s
)
65 if isinstance(s
, unicode):
69 def get_iface_quark(self
):
70 assert self
.iface_dbus
is not None
71 assert self
.iface_uc
is not None
72 if self
.iface_quark_prefix
is None:
73 return 'g_quark_from_static_string (\"%s\")' % self
.iface_dbus
75 return '%s_%s' % (self
.iface_quark_prefix
, self
.iface_uc
)
77 def do_signal(self
, iface
, signal
):
78 iface_lc
= iface
.lower()
80 member
= signal
.getAttribute('name')
81 member_lc
= camelcase_to_lower(member
)
82 member_uc
= member_lc
.upper()
88 for arg
in signal
.getElementsByTagName('arg'):
89 name
= arg
.getAttribute('name')
90 type = arg
.getAttribute('type')
91 tp_type
= arg
.getAttribute('tp:type')
94 name
= 'arg%u' % arg_count
97 name
= 'arg_%s' % name
99 info
= type_to_gtype(type)
100 args
.append((name
, info
, tp_type
, arg
))
102 callback_name
= ('%s_%s_signal_callback_%s'
103 % (self
.prefix_lc
, iface_lc
, member_lc
))
104 collect_name
= ('_%s_%s_collect_args_of_%s'
105 % (self
.prefix_lc
, iface_lc
, member_lc
))
106 invoke_name
= ('_%s_%s_invoke_callback_for_%s'
107 % (self
.prefix_lc
, iface_lc
, member_lc
))
111 # typedef void (*tp_cli_connection_signal_callback_new_channel)
112 # (TpConnection *proxy, const gchar *arg_object_path,
113 # const gchar *arg_channel_type, guint arg_handle_type,
114 # guint arg_handle, gboolean arg_suppress_handler,
115 # gpointer user_data, GObject *weak_object);
118 self
.b(' * %s:' % callback_name
)
119 self
.b(' * @proxy: The proxy on which %s_%s_connect_to_%s ()'
120 % (self
.prefix_lc
, iface_lc
, member_lc
))
121 self
.b(' * was called')
124 name
, info
, tp_type
, elt
= arg
125 ctype
, gtype
, marshaller
, pointer
= info
127 self
.b(' * @%s: %s' % (name
,
128 xml_escape(get_docstring(elt
) or '(Undocumented)')))
130 self
.b(' * @user_data: User-supplied data')
131 self
.b(' * @weak_object: User-supplied weakly referenced object')
133 self
.b(' * Represents the signature of a callback for the signal %s.'
136 self
.h('typedef void (*%s) (%sproxy,'
137 % (callback_name
, self
.proxy_cls
))
140 name
, info
, tp_type
, elt
= arg
141 ctype
, gtype
, marshaller
, pointer
= info
143 const
= pointer
and 'const ' or ''
145 self
.h(' %s%s%s,' % (const
, ctype
, name
))
147 self
.h(' gpointer user_data, GObject *weak_object);')
150 self
.b('static void')
151 self
.b('%s (DBusGProxy *proxy G_GNUC_UNUSED,' % collect_name
)
154 name
, info
, tp_type
, elt
= arg
155 ctype
, gtype
, marshaller
, pointer
= info
157 const
= pointer
and 'const ' or ''
159 self
.b(' %s%s%s,' % (const
, ctype
, name
))
161 self
.b(' TpProxySignalConnection *sc)')
163 self
.b(' GValueArray *args = g_value_array_new (%d);' % len(args
))
164 self
.b(' GValue blank = { 0 };')
167 self
.b(' g_value_init (&blank, G_TYPE_INT);')
169 self
.b(' for (i = 0; i < %d; i++)' % len(args
))
170 self
.b(' g_value_array_append (args, &blank);')
173 for i
, arg
in enumerate(args
):
174 name
, info
, tp_type
, elt
= arg
175 ctype
, gtype
, marshaller
, pointer
= info
177 self
.b(' g_value_unset (args->values + %d);' % i
)
178 self
.b(' g_value_init (args->values + %d, %s);' % (i
, gtype
))
180 if gtype
== 'G_TYPE_STRING':
181 self
.b(' g_value_set_string (args->values + %d, %s);'
183 elif marshaller
== 'BOXED':
184 self
.b(' g_value_set_boxed (args->values + %d, %s);'
186 elif gtype
== 'G_TYPE_UCHAR':
187 self
.b(' g_value_set_uchar (args->values + %d, %s);'
189 elif gtype
== 'G_TYPE_BOOLEAN':
190 self
.b(' g_value_set_boolean (args->values + %d, %s);'
192 elif gtype
== 'G_TYPE_INT':
193 self
.b(' g_value_set_int (args->values + %d, %s);'
195 elif gtype
== 'G_TYPE_UINT':
196 self
.b(' g_value_set_uint (args->values + %d, %s);'
198 elif gtype
== 'G_TYPE_INT64':
199 self
.b(' g_value_set_int (args->values + %d, %s);'
201 elif gtype
== 'G_TYPE_UINT64':
202 self
.b(' g_value_set_uint64 (args->values + %d, %s);'
204 elif gtype
== 'G_TYPE_DOUBLE':
205 self
.b(' g_value_set_double (args->values + %d, %s);'
208 assert False, ("Don't know how to put %s in a GValue"
212 self
.b(' tp_proxy_signal_connection_v0_take_results (sc, args);')
215 self
.b('static void')
216 self
.b('%s (TpProxy *tpproxy,' % invoke_name
)
217 self
.b(' GError *error G_GNUC_UNUSED,')
218 self
.b(' GValueArray *args,')
219 self
.b(' GCallback generic_callback,')
220 self
.b(' gpointer user_data,')
221 self
.b(' GObject *weak_object)')
223 self
.b(' %s callback =' % callback_name
)
224 self
.b(' (%s) generic_callback;' % callback_name
)
226 self
.b(' if (callback != NULL)')
227 self
.b(' callback (g_object_ref (tpproxy),')
229 # FIXME: factor out into a function
230 for i
, arg
in enumerate(args
):
231 name
, info
, tp_type
, elt
= arg
232 ctype
, gtype
, marshaller
, pointer
= info
234 if marshaller
== 'BOXED':
235 self
.b(' g_value_get_boxed (args->values + %d),' % i
)
236 elif gtype
== 'G_TYPE_STRING':
237 self
.b(' g_value_get_string (args->values + %d),' % i
)
238 elif gtype
== 'G_TYPE_UCHAR':
239 self
.b(' g_value_get_uchar (args->values + %d),' % i
)
240 elif gtype
== 'G_TYPE_BOOLEAN':
241 self
.b(' g_value_get_boolean (args->values + %d),' % i
)
242 elif gtype
== 'G_TYPE_UINT':
243 self
.b(' g_value_get_uint (args->values + %d),' % i
)
244 elif gtype
== 'G_TYPE_INT':
245 self
.b(' g_value_get_int (args->values + %d),' % i
)
246 elif gtype
== 'G_TYPE_UINT64':
247 self
.b(' g_value_get_uint64 (args->values + %d),' % i
)
248 elif gtype
== 'G_TYPE_INT64':
249 self
.b(' g_value_get_int64 (args->values + %d),' % i
)
250 elif gtype
== 'G_TYPE_DOUBLE':
251 self
.b(' g_value_get_double (args->values + %d),' % i
)
253 assert False, "Don't know how to get %s from a GValue" % gtype
255 self
.b(' user_data,')
256 self
.b(' weak_object);')
260 self
.b(' g_value_array_free (args);')
262 self
.b(' if (args != NULL)')
263 self
.b(' g_value_array_free (args);')
266 self
.b(' g_object_unref (tpproxy);')
271 # TpProxySignalConnection *
272 # tp_cli_connection_connect_to_new_channel
273 # (TpConnection *proxy,
274 # tp_cli_connection_signal_callback_new_channel callback,
275 # gpointer user_data,
276 # GDestroyNotify destroy);
278 # destroy is invoked when the signal becomes disconnected. This
279 # is either because the signal has been disconnected explicitly
280 # by the user, because the TpProxy has become invalid and
281 # emitted the 'invalidated' signal, or because the weakly referenced
282 # object has gone away.
285 self
.b(' * %s_%s_connect_to_%s:'
286 % (self
.prefix_lc
, iface_lc
, member_lc
))
287 self
.b(' * @proxy: %s' % self
.proxy_doc
)
288 self
.b(' * @callback: Callback to be called when the signal is')
289 self
.b(' * received')
290 self
.b(' * @user_data: User-supplied data for the callback')
291 self
.b(' * @destroy: Destructor for the user-supplied data, which')
292 self
.b(' * will be called when this signal is disconnected, or')
293 self
.b(' * before this function returns %NULL')
294 self
.b(' * @weak_object: A #GObject which will be weakly referenced; ')
295 self
.b(' * if it is destroyed, this callback will automatically be')
296 self
.b(' * disconnected')
297 self
.b(' * @error: If not %NULL, used to raise an error if %NULL is')
298 self
.b(' * returned')
300 self
.b(' * Connect a handler to the signal %s.' % member
)
302 self
.b(' * %s' % xml_escape(get_docstring(signal
) or '(Undocumented)'))
304 self
.b(' * Returns: a #TpProxySignalConnection containing all of the')
305 self
.b(' * above, which can be used to disconnect the signal; or')
306 self
.b(' * %NULL if the proxy does not have the desired interface')
307 self
.b(' * or has become invalid.')
309 self
.h('TpProxySignalConnection *%s_%s_connect_to_%s (%sproxy,'
310 % (self
.prefix_lc
, iface_lc
, member_lc
, self
.proxy_arg
))
311 self
.h(' %s callback,' % callback_name
)
312 self
.h(' gpointer user_data,')
313 self
.h(' GDestroyNotify destroy,')
314 self
.h(' GObject *weak_object,')
315 self
.h(' GError **error);')
317 self
.b('TpProxySignalConnection *')
318 self
.b('%s_%s_connect_to_%s (%sproxy,'
319 % (self
.prefix_lc
, iface_lc
, member_lc
, self
.proxy_arg
))
320 self
.b(' %s callback,' % callback_name
)
321 self
.b(' gpointer user_data,')
322 self
.b(' GDestroyNotify destroy,')
323 self
.b(' GObject *weak_object,')
324 self
.b(' GError **error)')
326 self
.b(' GType expected_types[%d] = {' % (len(args
) + 1))
329 name
, info
, tp_type
, elt
= arg
330 ctype
, gtype
, marshaller
, pointer
= info
332 self
.b(' %s,' % gtype
)
334 self
.b(' G_TYPE_INVALID };')
336 self
.b(' g_return_val_if_fail (%s (proxy), NULL);'
338 self
.b(' g_return_val_if_fail (callback != NULL, NULL);')
340 self
.b(' return tp_proxy_signal_connection_v0_new ((TpProxy *) proxy,')
341 self
.b(' %s, \"%s\",' % (self
.get_iface_quark(), member
))
342 self
.b(' expected_types,')
345 self
.b(' G_CALLBACK (%s),' % collect_name
)
347 self
.b(' NULL, /* no args => no collector function */')
349 self
.b(' %s,' % invoke_name
)
350 self
.b(' G_CALLBACK (callback), user_data, destroy,')
351 self
.b(' weak_object, error);')
357 def do_method(self
, iface
, method
):
358 iface_lc
= iface
.lower()
360 member
= method
.getAttribute('name')
361 member_lc
= camelcase_to_lower(member
)
362 member_uc
= member_lc
.upper()
369 for arg
in method
.getElementsByTagName('arg'):
370 name
= arg
.getAttribute('name')
371 direction
= arg
.getAttribute('direction')
372 type = arg
.getAttribute('type')
373 tp_type
= arg
.getAttribute('tp:type')
375 if direction
!= 'out':
377 name
= 'in%u' % in_count
380 name
= 'in_%s' % name
383 name
= 'out%u' % ret_count
386 name
= 'out_%s' % name
388 info
= type_to_gtype(type)
389 if direction
!= 'out':
390 in_args
.append((name
, info
, tp_type
, arg
))
392 out_args
.append((name
, info
, tp_type
, arg
))
394 # Async reply callback type
397 # void (*tp_cli_properties_interface_callback_for_get_properties)
399 # const GPtrArray *out0,
400 # const GError *error,
401 # gpointer user_data,
402 # GObject *weak_object);
405 self
.b(' * %s_%s_callback_for_%s:'
406 % (self
.prefix_lc
, iface_lc
, member_lc
))
407 self
.b(' * @proxy: the proxy on which the call was made')
410 name
, info
, tp_type
, elt
= arg
411 ctype
, gtype
, marshaller
, pointer
= info
413 self
.b(' * @%s: Used to return an \'out\' argument if @error is '
415 % (name
, xml_escape(get_docstring(elt
) or '(Undocumented)')))
417 self
.b(' * @error: %NULL on success, or an error on failure')
418 self
.b(' * @user_data: user-supplied data')
419 self
.b(' * @weak_object: user-supplied object')
421 self
.b(' * Signature of the callback called when a %s method call'
423 self
.b(' * succeeds or fails.')
426 callback_name
= '%s_%s_callback_for_%s' % (self
.prefix_lc
, iface_lc
,
429 self
.h('typedef void (*%s) (%sproxy,'
430 % (callback_name
, self
.proxy_cls
))
433 name
, info
, tp_type
, elt
= arg
434 ctype
, gtype
, marshaller
, pointer
= info
435 const
= pointer
and 'const ' or ''
437 self
.h(' %s%s%s,' % (const
, ctype
, name
))
439 self
.h(' const GError *error, gpointer user_data,')
440 self
.h(' GObject *weak_object);')
443 # Async callback implementation
445 invoke_callback
= '_%s_%s_invoke_callback_%s' % (self
.prefix_lc
,
449 collect_callback
= '_%s_%s_collect_callback_%s' % (self
.prefix_lc
,
453 # The callback called by dbus-glib; this ends the call and collects
454 # the results into a GValueArray.
455 self
.b('static void')
456 self
.b('%s (DBusGProxy *proxy,' % collect_callback
)
457 self
.b(' DBusGProxyCall *call,')
458 self
.b(' gpointer user_data)')
460 self
.b(' GError *error = NULL;')
462 if len(out_args
) > 0:
463 self
.b(' GValueArray *args;')
464 self
.b(' GValue blank = { 0 };')
468 name
, info
, tp_type
, elt
= arg
469 ctype
, gtype
, marshaller
, pointer
= info
471 # "We handle variants specially; the caller is expected to
472 # have already allocated storage for them". Thanks,
474 if gtype
== 'G_TYPE_VALUE':
475 self
.b(' GValue *%s = g_new0 (GValue, 1);' % name
)
477 self
.b(' %s%s;' % (ctype
, name
))
480 self
.b(' dbus_g_proxy_end_call (proxy, call, &error,')
483 name
, info
, tp_type
, elt
= arg
484 ctype
, gtype
, marshaller
, pointer
= info
486 if gtype
== 'G_TYPE_VALUE':
487 self
.b(' %s, %s,' % (gtype
, name
))
489 self
.b(' %s, &%s,' % (gtype
, name
))
491 self
.b(' G_TYPE_INVALID);')
493 if len(out_args
) == 0:
494 self
.b(' tp_proxy_pending_call_v0_take_results (user_data, error,'
498 self
.b(' if (error != NULL)')
500 self
.b(' tp_proxy_pending_call_v0_take_results (user_data, error,')
504 name
, info
, tp_type
, elt
= arg
505 ctype
, gtype
, marshaller
, pointer
= info
506 if gtype
== 'G_TYPE_VALUE':
507 self
.b(' g_free (%s);' % name
)
512 self
.b(' args = g_value_array_new (%d);' % len(out_args
))
513 self
.b(' g_value_init (&blank, G_TYPE_INT);')
515 self
.b(' for (i = 0; i < %d; i++)' % len(out_args
))
516 self
.b(' g_value_array_append (args, &blank);')
518 for i
, arg
in enumerate(out_args
):
519 name
, info
, tp_type
, elt
= arg
520 ctype
, gtype
, marshaller
, pointer
= info
523 self
.b(' g_value_unset (args->values + %d);' % i
)
524 self
.b(' g_value_init (args->values + %d, %s);' % (i
, gtype
))
526 if gtype
== 'G_TYPE_STRING':
527 self
.b(' g_value_take_string (args->values + %d, %s);'
529 elif marshaller
== 'BOXED':
530 self
.b(' g_value_take_boxed (args->values + %d, %s);'
532 elif gtype
== 'G_TYPE_UCHAR':
533 self
.b(' g_value_set_uchar (args->values + %d, %s);'
535 elif gtype
== 'G_TYPE_BOOLEAN':
536 self
.b(' g_value_set_boolean (args->values + %d, %s);'
538 elif gtype
== 'G_TYPE_INT':
539 self
.b(' g_value_set_int (args->values + %d, %s);'
541 elif gtype
== 'G_TYPE_UINT':
542 self
.b(' g_value_set_uint (args->values + %d, %s);'
544 elif gtype
== 'G_TYPE_INT64':
545 self
.b(' g_value_set_int (args->values + %d, %s);'
547 elif gtype
== 'G_TYPE_UINT64':
548 self
.b(' g_value_set_uint (args->values + %d, %s);'
550 elif gtype
== 'G_TYPE_DOUBLE':
551 self
.b(' g_value_set_double (args->values + %d, %s);'
554 assert False, ("Don't know how to put %s in a GValue"
557 self
.b(' tp_proxy_pending_call_v0_take_results (user_data, '
562 self
.b('static void')
563 self
.b('%s (TpProxy *self,' % invoke_callback
)
564 self
.b(' GError *error,')
565 self
.b(' GValueArray *args,')
566 self
.b(' GCallback generic_callback,')
567 self
.b(' gpointer user_data,')
568 self
.b(' GObject *weak_object)')
570 self
.b(' %s callback = (%s) generic_callback;'
571 % (callback_name
, callback_name
))
573 self
.b(' if (error != NULL)')
575 self
.b(' callback ((%s) self,' % self
.proxy_cls
)
578 name
, info
, tp_type
, elt
= arg
579 ctype
, gtype
, marshaller
, pointer
= info
581 if marshaller
== 'BOXED' or pointer
:
583 elif gtype
== 'G_TYPE_DOUBLE':
588 self
.b(' error, user_data, weak_object);')
589 self
.b(' g_error_free (error);')
593 self
.b(' callback ((%s) self,' % self
.proxy_cls
)
595 # FIXME: factor out into a function
596 for i
, arg
in enumerate(out_args
):
597 name
, info
, tp_type
, elt
= arg
598 ctype
, gtype
, marshaller
, pointer
= info
600 if marshaller
== 'BOXED':
601 self
.b(' g_value_get_boxed (args->values + %d),' % i
)
602 elif gtype
== 'G_TYPE_STRING':
603 self
.b(' g_value_get_string (args->values + %d),' % i
)
604 elif gtype
== 'G_TYPE_UCHAR':
605 self
.b(' g_value_get_uchar (args->values + %d),' % i
)
606 elif gtype
== 'G_TYPE_BOOLEAN':
607 self
.b(' g_value_get_boolean (args->values + %d),' % i
)
608 elif gtype
== 'G_TYPE_UINT':
609 self
.b(' g_value_get_uint (args->values + %d),' % i
)
610 elif gtype
== 'G_TYPE_INT':
611 self
.b(' g_value_get_int (args->values + %d),' % i
)
612 elif gtype
== 'G_TYPE_UINT64':
613 self
.b(' g_value_get_uint64 (args->values + %d),' % i
)
614 elif gtype
== 'G_TYPE_INT64':
615 self
.b(' g_value_get_int64 (args->values + %d),' % i
)
616 elif gtype
== 'G_TYPE_DOUBLE':
617 self
.b(' g_value_get_double (args->values + %d),' % i
)
619 assert False, "Don't know how to get %s from a GValue" % gtype
621 self
.b(' error, user_data, weak_object);')
624 if len(out_args
) > 0:
625 self
.b(' g_value_array_free (args);')
627 self
.b(' if (args != NULL)')
628 self
.b(' g_value_array_free (args);')
636 # TpProxyPendingCall *
637 # tp_cli_properties_interface_call_get_properties
640 # const GArray *in_properties,
641 # tp_cli_properties_interface_callback_for_get_properties callback,
642 # gpointer user_data,
643 # GDestroyNotify *destructor);
645 self
.h('TpProxyPendingCall *%s_%s_call_%s (%sproxy,'
646 % (self
.prefix_lc
, iface_lc
, member_lc
, self
.proxy_arg
))
647 self
.h(' gint timeout_ms,')
650 self
.b(' * %s_%s_call_%s:'
651 % (self
.prefix_lc
, iface_lc
, member_lc
))
652 self
.b(' * @proxy: the #TpProxy')
653 self
.b(' * @timeout_ms: the timeout in milliseconds, or -1 to use the')
657 name
, info
, tp_type
, elt
= arg
658 ctype
, gtype
, marshaller
, pointer
= info
660 self
.b(' * @%s: Used to pass an \'in\' argument: %s'
661 % (name
, xml_escape(get_docstring(elt
) or '(Undocumented)')))
663 self
.b(' * @callback: called when the method call succeeds or fails;')
664 self
.b(' * may be %NULL to make a "fire and forget" call with no ')
665 self
.b(' * reply tracking')
666 self
.b(' * @user_data: user-supplied data passed to the callback;')
667 self
.b(' * must be %NULL if @callback is %NULL')
668 self
.b(' * @destroy: called with the user_data as argument, after the')
669 self
.b(' * call has succeeded, failed or been cancelled;')
670 self
.b(' * must be %NULL if @callback is %NULL')
671 self
.b(' * @weak_object: If not %NULL, a #GObject which will be ')
672 self
.b(' * weakly referenced; if it is destroyed, this call ')
673 self
.b(' * will automatically be cancelled. Must be %NULL if ')
674 self
.b(' * @callback is %NULL')
676 self
.b(' * Start a %s method call.' % member
)
678 self
.b(' * %s' % xml_escape(get_docstring(method
) or '(Undocumented)'))
680 self
.b(' * Returns: a #TpProxyPendingCall representing the call in')
681 self
.b(' * progress. It is borrowed from the object, and will become')
682 self
.b(' * invalid when the callback is called, the call is')
683 self
.b(' * cancelled or the #TpProxy becomes invalid.')
685 self
.b('TpProxyPendingCall *\n%s_%s_call_%s (%sproxy,'
686 % (self
.prefix_lc
, iface_lc
, member_lc
, self
.proxy_arg
))
687 self
.b(' gint timeout_ms,')
690 name
, info
, tp_type
, elt
= arg
691 ctype
, gtype
, marshaller
, pointer
= info
693 const
= pointer
and 'const ' or ''
695 self
.h(' %s%s%s,' % (const
, ctype
, name
))
696 self
.b(' %s%s%s,' % (const
, ctype
, name
))
698 self
.h(' %s callback,' % callback_name
)
699 self
.h(' gpointer user_data,')
700 self
.h(' GDestroyNotify destroy,')
701 self
.h(' GObject *weak_object);')
704 self
.b(' %s callback,' % callback_name
)
705 self
.b(' gpointer user_data,')
706 self
.b(' GDestroyNotify destroy,')
707 self
.b(' GObject *weak_object)')
709 self
.b(' GError *error = NULL;')
710 self
.b(' GQuark interface = %s;' % self
.get_iface_quark())
711 self
.b(' DBusGProxy *iface;')
713 self
.b(' g_return_val_if_fail (%s (proxy), NULL);'
715 self
.b(' g_return_val_if_fail (callback != NULL || '
716 'user_data == NULL, NULL);')
717 self
.b(' g_return_val_if_fail (callback != NULL || '
718 'destroy == NULL, NULL);')
719 self
.b(' g_return_val_if_fail (callback != NULL || '
720 'weak_object == NULL, NULL);')
722 self
.b(' iface = tp_proxy_borrow_interface_by_id (')
723 self
.b(' (TpProxy *) proxy,')
724 self
.b(' interface, &error);')
726 self
.b(' if (iface == NULL)')
728 self
.b(' if (callback != NULL)')
729 self
.b(' callback (proxy,')
732 name
, info
, tp_type
, elt
= arg
733 ctype
, gtype
, marshaller
, pointer
= info
740 self
.b(' error, user_data, weak_object);')
742 self
.b(' if (destroy != NULL)')
743 self
.b(' destroy (user_data);')
745 self
.b(' g_error_free (error);')
746 self
.b(' return NULL;')
749 self
.b(' if (callback == NULL)')
751 self
.b(' dbus_g_proxy_call_no_reply (iface, "%s",' % member
)
754 name
, info
, tp_type
, elt
= arg
755 ctype
, gtype
, marshaller
, pointer
= info
757 const
= pointer
and 'const ' or ''
759 self
.b(' %s, %s,' % (gtype
, name
))
761 self
.b(' G_TYPE_INVALID);')
762 self
.b(' return NULL;')
766 self
.b(' TpProxyPendingCall *data;')
768 self
.b(' data = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,')
769 self
.b(' interface, "%s", iface,' % member
)
770 self
.b(' %s,' % invoke_callback
)
771 self
.b(' G_CALLBACK (callback), user_data, destroy,')
772 self
.b(' weak_object, FALSE);')
773 self
.b(' tp_proxy_pending_call_v0_take_pending_call (data,')
774 self
.b(' dbus_g_proxy_begin_call_with_timeout (iface,')
775 self
.b(' "%s",' % member
)
776 self
.b(' %s,' % collect_callback
)
778 self
.b(' tp_proxy_pending_call_v0_completed,')
779 self
.b(' timeout_ms,')
782 name
, info
, tp_type
, elt
= arg
783 ctype
, gtype
, marshaller
, pointer
= info
785 const
= pointer
and 'const ' or ''
787 self
.b(' %s, %s,' % (gtype
, name
))
789 self
.b(' G_TYPE_INVALID));')
791 self
.b(' return data;')
796 # Reentrant blocking calls
798 # gboolean tp_cli_properties_interface_run_get_properties
801 # const GArray *in_properties,
806 self
.b('typedef struct {')
807 self
.b(' GMainLoop *loop;')
808 self
.b(' GError **error;')
811 name
, info
, tp_type
, elt
= arg
812 ctype
, gtype
, marshaller
, pointer
= info
814 self
.b(' %s*%s;' % (ctype
, name
))
816 self
.b(' unsigned success:1;')
817 self
.b(' unsigned completed:1;')
818 self
.b('} _%s_%s_run_state_%s;'
819 % (self
.prefix_lc
, iface_lc
, member_lc
))
821 reentrant_invoke
= '_%s_%s_finish_running_%s' % (self
.prefix_lc
,
825 self
.b('static void')
826 self
.b('%s (TpProxy *self G_GNUC_UNUSED,' % reentrant_invoke
)
827 self
.b(' GError *error,')
828 self
.b(' GValueArray *args,')
829 self
.b(' GCallback unused G_GNUC_UNUSED,')
830 self
.b(' gpointer user_data G_GNUC_UNUSED,')
831 self
.b(' GObject *unused2 G_GNUC_UNUSED)')
833 self
.b(' _%s_%s_run_state_%s *state = user_data;'
834 % (self
.prefix_lc
, iface_lc
, member_lc
))
836 self
.b(' state->success = (error == NULL);')
837 self
.b(' state->completed = TRUE;')
838 self
.b(' g_main_loop_quit (state->loop);')
840 self
.b(' if (error != NULL)')
842 self
.b(' if (state->error != NULL)')
843 self
.b(' *state->error = error;')
845 self
.b(' g_error_free (error);')
851 for i
, arg
in enumerate(out_args
):
852 name
, info
, tp_type
, elt
= arg
853 ctype
, gtype
, marshaller
, pointer
= info
855 self
.b(' if (state->%s != NULL)' % name
)
856 if marshaller
== 'BOXED':
857 self
.b(' *state->%s = g_value_dup_boxed ('
858 'args->values + %d);' % (name
, i
))
859 elif marshaller
== 'STRING':
860 self
.b(' *state->%s = g_value_dup_string '
861 '(args->values + %d);' % (name
, i
))
862 elif marshaller
in ('UCHAR', 'BOOLEAN', 'INT', 'UINT',
863 'INT64', 'UINT64', 'DOUBLE'):
864 self
.b(' *state->%s = g_value_get_%s (args->values + %d);'
865 % (name
, marshaller
.lower(), i
))
867 assert False, "Don't know how to copy %s" % gtype
871 if len(out_args
) > 0:
872 self
.b(' g_value_array_free (args);')
874 self
.b(' if (args != NULL)')
875 self
.b(' g_value_array_free (args);')
880 self
.h('gboolean %s_%s_run_%s (%sproxy,'
881 % (self
.prefix_lc
, iface_lc
, member_lc
, self
.proxy_arg
))
882 self
.h(' gint timeout_ms,')
885 self
.b(' * %s_%s_run_%s:' % (self
.prefix_lc
, iface_lc
, member_lc
))
886 self
.b(' * @proxy: %s' % self
.proxy_doc
)
887 self
.b(' * @timeout_ms: Timeout in milliseconds, or -1 for default')
890 name
, info
, tp_type
, elt
= arg
891 ctype
, gtype
, marshaller
, pointer
= info
893 self
.b(' * @%s: Used to pass an \'in\' argument: %s'
894 % (name
, xml_escape(get_docstring(elt
) or '(Undocumented)')))
897 name
, info
, tp_type
, elt
= arg
898 ctype
, gtype
, marshaller
, pointer
= info
900 self
.b(' * @%s: Used to return an \'out\' argument if %%TRUE is '
902 % (name
, xml_escape(get_docstring(elt
) or '(Undocumented)')))
904 self
.b(' * @error: If not %NULL, used to return errors if %FALSE ')
905 self
.b(' * is returned')
906 self
.b(' * @loop: If not %NULL, set before re-entering ')
907 self
.b(' * the main loop, to point to a #GMainLoop ')
908 self
.b(' * which can be used to cancel this call with ')
909 self
.b(' * g_main_loop_quit(), causing a return of ')
910 self
.b(' * %FALSE with @error set to %TP_DBUS_ERROR_CANCELLED')
912 self
.b(' * Call the method %s and run the main loop' % member
)
913 self
.b(' * until it returns. Before calling this method, you must')
914 self
.b(' * add a reference to any borrowed objects you need to keep,')
915 self
.b(' * and generally ensure that everything is in a consistent')
918 self
.b(' * %s' % xml_escape(get_docstring(method
) or '(Undocumented)'))
920 self
.b(' * Returns: TRUE on success, FALSE and sets @error on error')
922 self
.b('gboolean\n%s_%s_run_%s (%sproxy,'
923 % (self
.prefix_lc
, iface_lc
, member_lc
, self
.proxy_arg
))
924 self
.b(' gint timeout_ms,')
927 name
, info
, tp_type
, elt
= arg
928 ctype
, gtype
, marshaller
, pointer
= info
930 const
= pointer
and 'const ' or ''
932 self
.h(' %s%s%s,' % (const
, ctype
, name
))
933 self
.b(' %s%s%s,' % (const
, ctype
, name
))
936 name
, info
, tp_type
, elt
= arg
937 ctype
, gtype
, marshaller
, pointer
= info
939 self
.h(' %s*%s,' % (ctype
, name
))
940 self
.b(' %s*%s,' % (ctype
, name
))
942 self
.h(' GError **error,')
943 self
.h(' GMainLoop **loop);')
946 self
.b(' GError **error,')
947 self
.b(' GMainLoop **loop)')
949 self
.b(' DBusGProxy *iface;')
950 self
.b(' GQuark interface = %s;' % self
.get_iface_quark())
951 self
.b(' TpProxyPendingCall *pc;')
952 self
.b(' _%s_%s_run_state_%s state = {'
953 % (self
.prefix_lc
, iface_lc
, member_lc
))
954 self
.b(' NULL /* loop */, error,')
957 name
, info
, tp_type
, elt
= arg
959 self
.b(' %s,' % name
)
961 self
.b(' FALSE /* completed */, FALSE /* success */ };')
963 self
.b(' g_return_val_if_fail (%s (proxy), FALSE);'
966 self
.b(' iface = tp_proxy_borrow_interface_by_id')
967 self
.b(' ((TpProxy *) proxy, interface, error);')
969 self
.b(' if (iface == NULL)')
970 self
.b(' return FALSE;')
972 self
.b(' state.loop = g_main_loop_new (NULL, FALSE);')
974 self
.b(' pc = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,')
975 self
.b(' interface, "%s", iface,' % member
)
976 self
.b(' %s,' % reentrant_invoke
)
977 self
.b(' NULL, &state, NULL, NULL, TRUE);')
979 self
.b(' if (loop != NULL)')
980 self
.b(' *loop = state.loop;')
982 self
.b(' tp_proxy_pending_call_v0_take_pending_call (pc,')
983 self
.b(' dbus_g_proxy_begin_call_with_timeout (iface,')
984 self
.b(' "%s",' % member
)
985 self
.b(' %s,' % collect_callback
)
987 self
.b(' tp_proxy_pending_call_v0_completed,')
988 self
.b(' timeout_ms,')
991 name
, info
, tp_type
, elt
= arg
992 ctype
, gtype
, marshaller
, pointer
= info
994 const
= pointer
and 'const ' or ''
996 self
.b(' %s, %s,' % (gtype
, name
))
998 self
.b(' G_TYPE_INVALID));')
1000 self
.b(' if (!state.completed)')
1001 self
.b(' g_main_loop_run (state.loop);')
1003 self
.b(' if (!state.completed)')
1004 self
.b(' tp_proxy_pending_call_cancel (pc);')
1006 self
.b(' if (loop != NULL)')
1007 self
.b(' *loop = NULL;')
1009 self
.b(' g_main_loop_unref (state.loop);')
1011 self
.b(' return state.success;')
1015 # leave a gap for the end of the method
1019 def do_signal_add(self
, signal
):
1020 marshaller_items
= []
1023 for i
in signal
.getElementsByTagName('arg'):
1024 name
= i
.getAttribute('name')
1025 type = i
.getAttribute('type')
1026 info
= type_to_gtype(type)
1027 # type, GType, STRING, is a pointer
1028 gtypes
.append(info
[1])
1030 self
.b(' dbus_g_proxy_add_signal (proxy, "%s",'
1031 % signal
.getAttribute('name'))
1032 for gtype
in gtypes
:
1033 self
.b(' %s,' % gtype
)
1034 self
.b(' G_TYPE_INVALID);')
1036 def do_interface(self
, node
):
1037 ifaces
= node
.getElementsByTagName('interface')
1038 assert len(ifaces
) == 1
1040 name
= node
.getAttribute('name').replace('/', '')
1043 self
.iface_lc
= name
.lower()
1044 self
.iface_uc
= name
.upper()
1045 self
.iface_mc
= name
.replace('_', '')
1046 self
.iface_dbus
= iface
.getAttribute('name')
1048 signals
= node
.getElementsByTagName('signal')
1049 methods
= node
.getElementsByTagName('method')
1052 self
.b('static inline void')
1053 self
.b('%s_add_signals_for_%s (DBusGProxy *proxy)'
1054 % (self
.prefix_lc
, name
.lower()))
1057 if self
.tp_proxy_api
>= (0, 7, 6):
1058 self
.b(' if (!tp_proxy_dbus_g_proxy_claim_for_signal_adding '
1062 for signal
in signals
:
1063 self
.do_signal_add(signal
)
1069 for signal
in signals
:
1070 self
.do_signal(name
, signal
)
1072 for method
in methods
:
1073 self
.do_method(name
, method
)
1075 self
.iface_dbus
= None
1079 self
.h('G_BEGIN_DECLS')
1082 self
.b('/* We don\'t want gtkdoc scanning this file, it\'ll get')
1083 self
.b(' * confused by seeing function definitions, so mark it as: */')
1084 self
.b('/*<private_header>*/')
1087 nodes
= self
.dom
.getElementsByTagName('node')
1088 nodes
.sort(cmp_by_name
)
1091 self
.do_interface(node
)
1093 if self
.group
is not None:
1096 self
.b(' * %s_%s_add_signals:' % (self
.prefix_lc
, self
.group
))
1097 self
.b(' * @self: the #TpProxy')
1098 self
.b(' * @quark: a quark whose string value is the interface')
1099 self
.b(' * name whose signals should be added')
1100 self
.b(' * @proxy: the D-Bus proxy to which to add the signals')
1101 self
.b(' * @unused: not used for anything')
1103 self
.b(' * Tell dbus-glib that @proxy has the signatures of all')
1104 self
.b(' * signals on the given interface, if it\'s one we')
1105 self
.b(' * support.')
1107 self
.b(' * This function should be used as a signal handler for')
1108 self
.b(' * #TpProxy::interface-added.')
1110 self
.b('static void')
1111 self
.b('%s_%s_add_signals (TpProxy *self G_GNUC_UNUSED,'
1112 % (self
.prefix_lc
, self
.group
))
1113 self
.b(' guint quark,')
1114 self
.b(' DBusGProxy *proxy,')
1115 self
.b(' gpointer unused G_GNUC_UNUSED)')
1120 iface
= node
.getElementsByTagName('interface')[0]
1121 self
.iface_dbus
= iface
.getAttribute('name')
1122 signals
= node
.getElementsByTagName('signal')
1125 name
= node
.getAttribute('name').replace('/', '').lower()
1126 self
.iface_uc
= name
.upper()
1127 self
.b(' if (quark == %s)' % self
.get_iface_quark())
1128 self
.b(' %s_add_signals_for_%s (proxy);'
1129 % (self
.prefix_lc
, name
))
1134 self
.h('G_END_DECLS')
1137 open(self
.basename
+ '.h', 'w').write('\n'.join(self
.__header
))
1138 open(self
.basename
+ '-body.h', 'w').write('\n'.join(self
.__body
))
1141 def types_to_gtypes(types
):
1142 return [type_to_gtype(t
)[1] for t
in types
]
1145 if __name__
== '__main__':
1146 options
, argv
= gnu_getopt(sys
.argv
[1:], '',
1147 ['group=', 'subclass=', 'subclass-assert=',
1148 'iface-quark-prefix=', 'tp-proxy-api='])
1152 for option
, value
in options
:
1153 opts
[option
] = value
1155 dom
= xml
.dom
.minidom
.parse(argv
[0])
1157 Generator(dom
, argv
[1], argv
[2], opts
)()