• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# -*- Mode: Python -*-
2# coding=utf-8
3
4# GDBus - GLib D-Bus Library
5#
6# Copyright (C) 2008-2018 Red Hat, Inc.
7# Copyright (C) 2018 Iñigo Martínez <inigomartinez@gmail.com>
8#
9# This library is free software; you can redistribute it and/or
10# modify it under the terms of the GNU Lesser General Public
11# License as published by the Free Software Foundation; either
12# version 2.1 of the License, or (at your option) any later version.
13#
14# This library is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17# Lesser General Public License for more details.
18#
19# You should have received a copy of the GNU Lesser General
20# Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
21#
22# Author: David Zeuthen <davidz@redhat.com>
23
24from . import config
25from . import utils
26from . import dbustypes
27from .utils import print_error
28
29LICENSE_STR = """/*
30 * This file is generated by gdbus-codegen, do not modify it.
31 *
32 * The license of this code is the same as for the D-Bus interface description
33 * it was derived from. Note that it links to GLib, so must comply with the
34 * LGPL linking clauses.
35 */\n"""
36
37
38# Disable line length warnings as wrapping the C code templates would be hard
39# flake8: noqa: E501
40
41
42def generate_namespace(namespace):
43    ns = namespace
44    if len(namespace) > 0:
45        if utils.is_ugly_case(namespace):
46            ns = namespace.replace("_", "")
47            ns_upper = namespace.upper() + "_"
48            ns_lower = namespace.lower() + "_"
49        else:
50            ns_upper = utils.camel_case_to_uscore(namespace).upper() + "_"
51            ns_lower = utils.camel_case_to_uscore(namespace).lower() + "_"
52    else:
53        ns_upper = ""
54        ns_lower = ""
55
56    return (ns, ns_upper, ns_lower)
57
58
59def generate_header_guard(header_name):
60    # There might be more characters that are safe to use than these, but lets
61    # stay conservative.
62    safe_valid_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
63    return "".join(
64        map(lambda c: c if c in safe_valid_chars else "_", header_name.upper())
65    )
66
67
68class HeaderCodeGenerator:
69    def __init__(
70        self,
71        ifaces,
72        namespace,
73        generate_objmanager,
74        generate_autocleanup,
75        header_name,
76        input_files_basenames,
77        use_pragma,
78        glib_min_required,
79        symbol_decorator,
80        symbol_decorator_header,
81        outfile,
82    ):
83        self.ifaces = ifaces
84        self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
85        self.generate_objmanager = generate_objmanager
86        self.generate_autocleanup = generate_autocleanup
87        self.header_guard = generate_header_guard(header_name)
88        self.input_files_basenames = input_files_basenames
89        self.use_pragma = use_pragma
90        self.glib_min_required = glib_min_required
91        self.symbol_decorator = symbol_decorator
92        self.symbol_decorator_header = symbol_decorator_header
93        self.outfile = outfile
94
95    # ----------------------------------------------------------------------------------------------------
96
97    def generate_header_preamble(self):
98        basenames = ", ".join(self.input_files_basenames)
99        self.outfile.write(LICENSE_STR.format(config.VERSION, basenames))
100        self.outfile.write("\n")
101
102        if self.use_pragma:
103            self.outfile.write("#pragma once\n")
104        else:
105            self.outfile.write("#ifndef __{!s}__\n".format(self.header_guard))
106            self.outfile.write("#define __{!s}__\n".format(self.header_guard))
107
108        if self.symbol_decorator_header is not None:
109            self.outfile.write("\n")
110            self.outfile.write('#include "%s"\n' % self.symbol_decorator_header)
111
112        self.outfile.write("\n")
113        self.outfile.write("#include <gio/gio.h>\n")
114        self.outfile.write("\n")
115        self.outfile.write("G_BEGIN_DECLS\n")
116        self.outfile.write("\n")
117
118    # ----------------------------------------------------------------------------------------------------
119
120    def declare_types(self):
121        for i in self.ifaces:
122            self.outfile.write("\n")
123            self.outfile.write(
124                "/* ------------------------------------------------------------------------ */\n"
125            )
126            self.outfile.write("/* Declarations for %s */\n" % i.name)
127            self.outfile.write("\n")
128
129            # First the GInterface
130            self.outfile.write(
131                "#define %sTYPE_%s (%s_get_type ())\n"
132                % (i.ns_upper, i.name_upper, i.name_lower)
133            )
134            self.outfile.write(
135                "#define %s%s(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_%s, %s))\n"
136                % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)
137            )
138            self.outfile.write(
139                "#define %sIS_%s(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_%s))\n"
140                % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)
141            )
142            self.outfile.write(
143                "#define %s%s_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), %sTYPE_%s, %sIface))\n"
144                % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)
145            )
146            self.outfile.write("\n")
147            self.outfile.write("struct _%s;\n" % (i.camel_name))
148            self.outfile.write(
149                "typedef struct _%s %s;\n" % (i.camel_name, i.camel_name)
150            )
151            self.outfile.write(
152                "typedef struct _%sIface %sIface;\n" % (i.camel_name, i.camel_name)
153            )
154            self.outfile.write("\n")
155            self.outfile.write("struct _%sIface\n" % (i.camel_name))
156            self.outfile.write("{\n")
157            self.outfile.write("  GTypeInterface parent_iface;\n")
158
159            function_pointers = {}
160
161            # vfuncs for methods
162            if len(i.methods) > 0:
163                self.outfile.write("\n")
164                for m in i.methods:
165                    key = (m.since, "_method_%s" % m.name_lower)
166                    value = "  gboolean (*handle_%s) (\n" % (m.name_lower)
167                    value += "    %s *object,\n" % (i.camel_name)
168                    value += "    GDBusMethodInvocation *invocation"
169                    if m.unix_fd:
170                        value += ",\n    GUnixFDList *fd_list"
171                    for a in m.in_args:
172                        value += ",\n    %sarg_%s" % (a.ctype_in, a.name)
173                    value += ");\n\n"
174                    function_pointers[key] = value
175
176            # vfuncs for signals
177            if len(i.signals) > 0:
178                self.outfile.write("\n")
179                for s in i.signals:
180                    key = (s.since, "_signal_%s" % s.name_lower)
181                    value = "  void (*%s) (\n" % (s.name_lower)
182                    value += "    %s *object" % (i.camel_name)
183                    for a in s.args:
184                        value += ",\n    %sarg_%s" % (a.ctype_in, a.name)
185                    value += ");\n\n"
186                    function_pointers[key] = value
187
188            # vfuncs for properties
189            if len(i.properties) > 0:
190                self.outfile.write("\n")
191                for p in i.properties:
192                    key = (p.since, "_prop_get_%s" % p.name_lower)
193                    value = "  %s (*get_%s) (%s *object);\n\n" % (
194                        p.arg.ctype_in,
195                        p.name_lower,
196                        i.camel_name,
197                    )
198                    function_pointers[key] = value
199
200            # Sort according to @since tag, then name.. this ensures
201            # that the function pointers don't change order assuming
202            # judicious use of @since
203            #
204            # Also use a proper version comparison function so e.g.
205            # 10.0 comes after 2.0.
206            #
207            # See https://bugzilla.gnome.org/show_bug.cgi?id=647577#c5
208            # for discussion
209            for key in sorted(function_pointers.keys(), key=utils.version_cmp_key):
210                self.outfile.write("%s" % function_pointers[key])
211
212            self.outfile.write("};\n")
213            self.outfile.write("\n")
214            if self.generate_autocleanup == "all":
215                self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n")
216                self.outfile.write(
217                    "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, g_object_unref)\n"
218                    % (i.camel_name)
219                )
220                self.outfile.write("#endif\n")
221                self.outfile.write("\n")
222            if self.symbol_decorator is not None:
223                self.outfile.write("%s\n" % self.symbol_decorator)
224            self.outfile.write(
225                "GType %s_get_type (void) G_GNUC_CONST;\n" % (i.name_lower)
226            )
227            self.outfile.write("\n")
228            if self.symbol_decorator is not None:
229                self.outfile.write("%s\n" % self.symbol_decorator)
230            self.outfile.write(
231                "GDBusInterfaceInfo *%s_interface_info (void);\n" % (i.name_lower)
232            )
233            if self.symbol_decorator is not None:
234                self.outfile.write("%s\n" % self.symbol_decorator)
235            self.outfile.write(
236                "guint %s_override_properties (GObjectClass *klass, guint property_id_begin);\n"
237                % (i.name_lower)
238            )
239            self.outfile.write("\n")
240
241            # Then method call completion functions
242            if len(i.methods) > 0:
243                self.outfile.write("\n")
244                self.outfile.write("/* D-Bus method call completion functions: */\n")
245                for m in i.methods:
246                    if self.symbol_decorator is not None:
247                        self.outfile.write("%s\n" % self.symbol_decorator)
248                    if m.deprecated:
249                        self.outfile.write("G_GNUC_DEPRECATED ")
250                    self.outfile.write(
251                        "void %s_complete_%s (\n"
252                        "    %s *object,\n"
253                        "    GDBusMethodInvocation *invocation"
254                        % (i.name_lower, m.name_lower, i.camel_name)
255                    )
256                    if m.unix_fd:
257                        self.outfile.write(",\n    GUnixFDList *fd_list")
258                    for a in m.out_args:
259                        self.outfile.write(",\n    %s%s" % (a.ctype_in, a.name))
260                    self.outfile.write(");\n")
261                    self.outfile.write("\n")
262                self.outfile.write("\n")
263
264            # Then signal emission functions
265            if len(i.signals) > 0:
266                self.outfile.write("\n")
267                self.outfile.write("/* D-Bus signal emissions functions: */\n")
268                for s in i.signals:
269                    if self.symbol_decorator is not None:
270                        self.outfile.write("%s\n" % self.symbol_decorator)
271                    if s.deprecated:
272                        self.outfile.write("G_GNUC_DEPRECATED ")
273                    self.outfile.write(
274                        "void %s_emit_%s (\n"
275                        "    %s *object" % (i.name_lower, s.name_lower, i.camel_name)
276                    )
277                    for a in s.args:
278                        self.outfile.write(",\n    %sarg_%s" % (a.ctype_in, a.name))
279                    self.outfile.write(");\n")
280                    self.outfile.write("\n")
281                self.outfile.write("\n")
282
283            # Then method call declarations
284            if len(i.methods) > 0:
285                self.outfile.write("\n")
286                self.outfile.write("/* D-Bus method calls: */\n")
287                for m in i.methods:
288                    # async begin
289                    if self.symbol_decorator is not None:
290                        self.outfile.write("%s\n" % self.symbol_decorator)
291                    if m.deprecated:
292                        self.outfile.write("G_GNUC_DEPRECATED ")
293                    self.outfile.write(
294                        "void %s_call_%s (\n"
295                        "    %s *proxy" % (i.name_lower, m.name_lower, i.camel_name)
296                    )
297                    for a in m.in_args:
298                        self.outfile.write(",\n    %sarg_%s" % (a.ctype_in, a.name))
299                    if self.glib_min_required >= (2, 64):
300                        self.outfile.write(
301                            ",\n    GDBusCallFlags call_flags"
302                            ",\n    gint timeout_msec"
303                        )
304                    if m.unix_fd:
305                        self.outfile.write(",\n    GUnixFDList *fd_list")
306                    self.outfile.write(
307                        ",\n"
308                        "    GCancellable *cancellable,\n"
309                        "    GAsyncReadyCallback callback,\n"
310                        "    gpointer user_data);\n"
311                    )
312                    self.outfile.write("\n")
313                    # async finish
314                    if self.symbol_decorator is not None:
315                        self.outfile.write("%s\n" % self.symbol_decorator)
316                    if m.deprecated:
317                        self.outfile.write("G_GNUC_DEPRECATED ")
318                    self.outfile.write(
319                        "gboolean %s_call_%s_finish (\n"
320                        "    %s *proxy" % (i.name_lower, m.name_lower, i.camel_name)
321                    )
322                    for a in m.out_args:
323                        self.outfile.write(",\n    %sout_%s" % (a.ctype_out, a.name))
324                    if m.unix_fd:
325                        self.outfile.write(",\n    GUnixFDList **out_fd_list")
326                    self.outfile.write(
327                        ",\n" "    GAsyncResult *res,\n" "    GError **error);\n"
328                    )
329                    self.outfile.write("\n")
330                    # sync
331                    if self.symbol_decorator is not None:
332                        self.outfile.write("%s\n" % self.symbol_decorator)
333                    if m.deprecated:
334                        self.outfile.write("G_GNUC_DEPRECATED ")
335                    self.outfile.write(
336                        "gboolean %s_call_%s_sync (\n"
337                        "    %s *proxy" % (i.name_lower, m.name_lower, i.camel_name)
338                    )
339                    for a in m.in_args:
340                        self.outfile.write(",\n    %sarg_%s" % (a.ctype_in, a.name))
341                    if self.glib_min_required >= (2, 64):
342                        self.outfile.write(
343                            ",\n    GDBusCallFlags call_flags"
344                            ",\n    gint timeout_msec"
345                        )
346                    if m.unix_fd:
347                        self.outfile.write(",\n    GUnixFDList  *fd_list")
348                    for a in m.out_args:
349                        self.outfile.write(",\n    %sout_%s" % (a.ctype_out, a.name))
350                    if m.unix_fd:
351                        self.outfile.write(",\n    GUnixFDList **out_fd_list")
352                    self.outfile.write(
353                        ",\n"
354                        "    GCancellable *cancellable,\n"
355                        "    GError **error);\n"
356                    )
357                    self.outfile.write("\n")
358                self.outfile.write("\n")
359
360            # Then the property accessor declarations
361            if len(i.properties) > 0:
362                self.outfile.write("\n")
363                self.outfile.write("/* D-Bus property accessors: */\n")
364                for p in i.properties:
365                    # getter
366                    if self.symbol_decorator is not None:
367                        self.outfile.write("%s\n" % self.symbol_decorator)
368                    if p.deprecated:
369                        self.outfile.write("G_GNUC_DEPRECATED ")
370                    self.outfile.write(
371                        "%s%s_get_%s (%s *object);\n"
372                        % (p.arg.ctype_in, i.name_lower, p.name_lower, i.camel_name)
373                    )
374                    if p.arg.free_func is not None:
375                        if self.symbol_decorator is not None:
376                            self.outfile.write("%s\n" % self.symbol_decorator)
377                        if p.deprecated:
378                            self.outfile.write("G_GNUC_DEPRECATED ")
379                        self.outfile.write(
380                            "%s%s_dup_%s (%s *object);\n"
381                            % (
382                                p.arg.ctype_in_dup,
383                                i.name_lower,
384                                p.name_lower,
385                                i.camel_name,
386                            )
387                        )
388                    # setter
389                    if self.symbol_decorator is not None:
390                        self.outfile.write("%s\n" % self.symbol_decorator)
391                    if p.deprecated:
392                        self.outfile.write("G_GNUC_DEPRECATED ")
393                    self.outfile.write(
394                        "void %s_set_%s (%s *object, %svalue);\n"
395                        % (i.name_lower, p.name_lower, i.camel_name, p.arg.ctype_in)
396                    )
397                    self.outfile.write("\n")
398
399            # Then the proxy
400            self.outfile.write("\n")
401            self.outfile.write("/* ---- */\n")
402            self.outfile.write("\n")
403            self.outfile.write(
404                "#define %sTYPE_%s_PROXY (%s_proxy_get_type ())\n"
405                % (i.ns_upper, i.name_upper, i.name_lower)
406            )
407            self.outfile.write(
408                "#define %s%s_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_%s_PROXY, %sProxy))\n"
409                % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)
410            )
411            self.outfile.write(
412                "#define %s%s_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_%s_PROXY, %sProxyClass))\n"
413                % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)
414            )
415            self.outfile.write(
416                "#define %s%s_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_%s_PROXY, %sProxyClass))\n"
417                % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)
418            )
419            self.outfile.write(
420                "#define %sIS_%s_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_%s_PROXY))\n"
421                % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)
422            )
423            self.outfile.write(
424                "#define %sIS_%s_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_%s_PROXY))\n"
425                % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)
426            )
427            self.outfile.write("\n")
428            self.outfile.write(
429                "typedef struct _%sProxy %sProxy;\n" % (i.camel_name, i.camel_name)
430            )
431            self.outfile.write(
432                "typedef struct _%sProxyClass %sProxyClass;\n"
433                % (i.camel_name, i.camel_name)
434            )
435            self.outfile.write(
436                "typedef struct _%sProxyPrivate %sProxyPrivate;\n"
437                % (i.camel_name, i.camel_name)
438            )
439            self.outfile.write("\n")
440            self.outfile.write("struct _%sProxy\n" % (i.camel_name))
441            self.outfile.write("{\n")
442            self.outfile.write("  /*< private >*/\n")
443            self.outfile.write("  GDBusProxy parent_instance;\n")
444            self.outfile.write("  %sProxyPrivate *priv;\n" % (i.camel_name))
445            self.outfile.write("};\n")
446            self.outfile.write("\n")
447            self.outfile.write("struct _%sProxyClass\n" % (i.camel_name))
448            self.outfile.write("{\n")
449            self.outfile.write("  GDBusProxyClass parent_class;\n")
450            self.outfile.write("};\n")
451            self.outfile.write("\n")
452            if self.symbol_decorator is not None:
453                self.outfile.write("%s\n" % self.symbol_decorator)
454            self.outfile.write(
455                "GType %s_proxy_get_type (void) G_GNUC_CONST;\n" % (i.name_lower)
456            )
457            self.outfile.write("\n")
458            if self.generate_autocleanup in ("objects", "all"):
459                self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n")
460                self.outfile.write(
461                    "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sProxy, g_object_unref)\n"
462                    % (i.camel_name)
463                )
464                self.outfile.write("#endif\n")
465                self.outfile.write("\n")
466            if self.symbol_decorator is not None:
467                self.outfile.write("%s\n" % self.symbol_decorator)
468            if i.deprecated:
469                self.outfile.write("G_GNUC_DEPRECATED ")
470            self.outfile.write(
471                "void %s_proxy_new (\n"
472                "    GDBusConnection     *connection,\n"
473                "    GDBusProxyFlags      flags,\n"
474                "    const gchar         *name,\n"
475                "    const gchar         *object_path,\n"
476                "    GCancellable        *cancellable,\n"
477                "    GAsyncReadyCallback  callback,\n"
478                "    gpointer             user_data);\n" % (i.name_lower)
479            )
480            if self.symbol_decorator is not None:
481                self.outfile.write("%s\n" % self.symbol_decorator)
482            if i.deprecated:
483                self.outfile.write("G_GNUC_DEPRECATED ")
484            self.outfile.write(
485                "%s *%s_proxy_new_finish (\n"
486                "    GAsyncResult        *res,\n"
487                "    GError             **error);\n" % (i.camel_name, i.name_lower)
488            )
489            if self.symbol_decorator is not None:
490                self.outfile.write("%s\n" % self.symbol_decorator)
491            if i.deprecated:
492                self.outfile.write("G_GNUC_DEPRECATED ")
493            self.outfile.write(
494                "%s *%s_proxy_new_sync (\n"
495                "    GDBusConnection     *connection,\n"
496                "    GDBusProxyFlags      flags,\n"
497                "    const gchar         *name,\n"
498                "    const gchar         *object_path,\n"
499                "    GCancellable        *cancellable,\n"
500                "    GError             **error);\n" % (i.camel_name, i.name_lower)
501            )
502            self.outfile.write("\n")
503            if self.symbol_decorator is not None:
504                self.outfile.write("%s\n" % self.symbol_decorator)
505            if i.deprecated:
506                self.outfile.write("G_GNUC_DEPRECATED ")
507            self.outfile.write(
508                "void %s_proxy_new_for_bus (\n"
509                "    GBusType             bus_type,\n"
510                "    GDBusProxyFlags      flags,\n"
511                "    const gchar         *name,\n"
512                "    const gchar         *object_path,\n"
513                "    GCancellable        *cancellable,\n"
514                "    GAsyncReadyCallback  callback,\n"
515                "    gpointer             user_data);\n" % (i.name_lower)
516            )
517            if self.symbol_decorator is not None:
518                self.outfile.write("%s\n" % self.symbol_decorator)
519            if i.deprecated:
520                self.outfile.write("G_GNUC_DEPRECATED ")
521            self.outfile.write(
522                "%s *%s_proxy_new_for_bus_finish (\n"
523                "    GAsyncResult        *res,\n"
524                "    GError             **error);\n" % (i.camel_name, i.name_lower)
525            )
526            if self.symbol_decorator is not None:
527                self.outfile.write("%s\n" % self.symbol_decorator)
528            if i.deprecated:
529                self.outfile.write("G_GNUC_DEPRECATED ")
530            self.outfile.write(
531                "%s *%s_proxy_new_for_bus_sync (\n"
532                "    GBusType             bus_type,\n"
533                "    GDBusProxyFlags      flags,\n"
534                "    const gchar         *name,\n"
535                "    const gchar         *object_path,\n"
536                "    GCancellable        *cancellable,\n"
537                "    GError             **error);\n" % (i.camel_name, i.name_lower)
538            )
539            self.outfile.write("\n")
540
541            # Then the skeleton
542            self.outfile.write("\n")
543            self.outfile.write("/* ---- */\n")
544            self.outfile.write("\n")
545            self.outfile.write(
546                "#define %sTYPE_%s_SKELETON (%s_skeleton_get_type ())\n"
547                % (i.ns_upper, i.name_upper, i.name_lower)
548            )
549            self.outfile.write(
550                "#define %s%s_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_%s_SKELETON, %sSkeleton))\n"
551                % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)
552            )
553            self.outfile.write(
554                "#define %s%s_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_%s_SKELETON, %sSkeletonClass))\n"
555                % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)
556            )
557            self.outfile.write(
558                "#define %s%s_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_%s_SKELETON, %sSkeletonClass))\n"
559                % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper, i.camel_name)
560            )
561            self.outfile.write(
562                "#define %sIS_%s_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_%s_SKELETON))\n"
563                % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)
564            )
565            self.outfile.write(
566                "#define %sIS_%s_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_%s_SKELETON))\n"
567                % (i.ns_upper, i.name_upper, i.ns_upper, i.name_upper)
568            )
569            self.outfile.write("\n")
570            self.outfile.write(
571                "typedef struct _%sSkeleton %sSkeleton;\n"
572                % (i.camel_name, i.camel_name)
573            )
574            self.outfile.write(
575                "typedef struct _%sSkeletonClass %sSkeletonClass;\n"
576                % (i.camel_name, i.camel_name)
577            )
578            self.outfile.write(
579                "typedef struct _%sSkeletonPrivate %sSkeletonPrivate;\n"
580                % (i.camel_name, i.camel_name)
581            )
582            self.outfile.write("\n")
583            self.outfile.write("struct _%sSkeleton\n" % (i.camel_name))
584            self.outfile.write("{\n")
585            self.outfile.write("  /*< private >*/\n")
586            self.outfile.write("  GDBusInterfaceSkeleton parent_instance;\n")
587            self.outfile.write("  %sSkeletonPrivate *priv;\n" % (i.camel_name))
588            self.outfile.write("};\n")
589            self.outfile.write("\n")
590            self.outfile.write("struct _%sSkeletonClass\n" % (i.camel_name))
591            self.outfile.write("{\n")
592            self.outfile.write("  GDBusInterfaceSkeletonClass parent_class;\n")
593            self.outfile.write("};\n")
594            self.outfile.write("\n")
595            if self.symbol_decorator is not None:
596                self.outfile.write("%s\n" % self.symbol_decorator)
597            self.outfile.write(
598                "GType %s_skeleton_get_type (void) G_GNUC_CONST;\n" % (i.name_lower)
599            )
600            self.outfile.write("\n")
601            if self.generate_autocleanup in ("objects", "all"):
602                self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n")
603                self.outfile.write(
604                    "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sSkeleton, g_object_unref)\n"
605                    % (i.camel_name)
606                )
607                self.outfile.write("#endif\n")
608                self.outfile.write("\n")
609            if self.symbol_decorator is not None:
610                self.outfile.write("%s\n" % self.symbol_decorator)
611            if i.deprecated:
612                self.outfile.write("G_GNUC_DEPRECATED ")
613            self.outfile.write(
614                "%s *%s_skeleton_new (void);\n" % (i.camel_name, i.name_lower)
615            )
616
617            self.outfile.write("\n")
618
619        # Finally, the Object, ObjectProxy, ObjectSkeleton and ObjectManagerClient
620        if self.generate_objmanager:
621            self.outfile.write("\n")
622            self.outfile.write("/* ---- */\n")
623            self.outfile.write("\n")
624            self.outfile.write(
625                "#define %sTYPE_OBJECT (%sobject_get_type ())\n"
626                % (self.ns_upper, self.ns_lower)
627            )
628            self.outfile.write(
629                "#define %sOBJECT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT, %sObject))\n"
630                % (self.ns_upper, self.ns_upper, self.namespace)
631            )
632            self.outfile.write(
633                "#define %sIS_OBJECT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT))\n"
634                % (self.ns_upper, self.ns_upper)
635            )
636            self.outfile.write(
637                "#define %sOBJECT_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), %sTYPE_OBJECT, %sObject))\n"
638                % (self.ns_upper, self.ns_upper, self.namespace)
639            )
640            self.outfile.write("\n")
641            self.outfile.write("struct _%sObject;\n" % (self.namespace))
642            self.outfile.write(
643                "typedef struct _%sObject %sObject;\n"
644                % (self.namespace, self.namespace)
645            )
646            self.outfile.write(
647                "typedef struct _%sObjectIface %sObjectIface;\n"
648                % (self.namespace, self.namespace)
649            )
650            self.outfile.write("\n")
651            self.outfile.write("struct _%sObjectIface\n" % (self.namespace))
652            self.outfile.write("{\n" "  GTypeInterface parent_iface;\n" "};\n" "\n")
653            if self.symbol_decorator is not None:
654                self.outfile.write("%s\n" % self.symbol_decorator)
655            self.outfile.write(
656                "GType %sobject_get_type (void) G_GNUC_CONST;\n" "\n" % (self.ns_lower)
657            )
658            if self.generate_autocleanup == "all":
659                self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n")
660                self.outfile.write(
661                    "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObject, g_object_unref)\n"
662                    % (self.namespace)
663                )
664                self.outfile.write("#endif\n")
665                self.outfile.write("\n")
666            for i in self.ifaces:
667                if self.symbol_decorator is not None:
668                    self.outfile.write("%s\n" % self.symbol_decorator)
669                if i.deprecated:
670                    self.outfile.write("G_GNUC_DEPRECATED ")
671                self.outfile.write(
672                    "%s *%sobject_get_%s (%sObject *object);\n"
673                    % (
674                        i.camel_name,
675                        self.ns_lower,
676                        i.name_upper.lower(),
677                        self.namespace,
678                    )
679                )
680            for i in self.ifaces:
681                if self.symbol_decorator is not None:
682                    self.outfile.write("%s\n" % self.symbol_decorator)
683                if i.deprecated:
684                    self.outfile.write("G_GNUC_DEPRECATED ")
685                self.outfile.write(
686                    "%s *%sobject_peek_%s (%sObject *object);\n"
687                    % (
688                        i.camel_name,
689                        self.ns_lower,
690                        i.name_upper.lower(),
691                        self.namespace,
692                    )
693                )
694            self.outfile.write("\n")
695            self.outfile.write(
696                "#define %sTYPE_OBJECT_PROXY (%sobject_proxy_get_type ())\n"
697                % (self.ns_upper, self.ns_lower)
698            )
699            self.outfile.write(
700                "#define %sOBJECT_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT_PROXY, %sObjectProxy))\n"
701                % (self.ns_upper, self.ns_upper, self.namespace)
702            )
703            self.outfile.write(
704                "#define %sOBJECT_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_OBJECT_PROXY, %sObjectProxyClass))\n"
705                % (self.ns_upper, self.ns_upper, self.namespace)
706            )
707            self.outfile.write(
708                "#define %sOBJECT_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_OBJECT_PROXY, %sObjectProxyClass))\n"
709                % (self.ns_upper, self.ns_upper, self.namespace)
710            )
711            self.outfile.write(
712                "#define %sIS_OBJECT_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT_PROXY))\n"
713                % (self.ns_upper, self.ns_upper)
714            )
715            self.outfile.write(
716                "#define %sIS_OBJECT_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_OBJECT_PROXY))\n"
717                % (self.ns_upper, self.ns_upper)
718            )
719            self.outfile.write("\n")
720            self.outfile.write(
721                "typedef struct _%sObjectProxy %sObjectProxy;\n"
722                % (self.namespace, self.namespace)
723            )
724            self.outfile.write(
725                "typedef struct _%sObjectProxyClass %sObjectProxyClass;\n"
726                % (self.namespace, self.namespace)
727            )
728            self.outfile.write(
729                "typedef struct _%sObjectProxyPrivate %sObjectProxyPrivate;\n"
730                % (self.namespace, self.namespace)
731            )
732            self.outfile.write("\n")
733            self.outfile.write("struct _%sObjectProxy\n" % (self.namespace))
734            self.outfile.write("{\n")
735            self.outfile.write("  /*< private >*/\n")
736            self.outfile.write("  GDBusObjectProxy parent_instance;\n")
737            self.outfile.write("  %sObjectProxyPrivate *priv;\n" % (self.namespace))
738            self.outfile.write("};\n")
739            self.outfile.write("\n")
740            self.outfile.write("struct _%sObjectProxyClass\n" % (self.namespace))
741            self.outfile.write("{\n")
742            self.outfile.write("  GDBusObjectProxyClass parent_class;\n")
743            self.outfile.write("};\n")
744            self.outfile.write("\n")
745            if self.symbol_decorator is not None:
746                self.outfile.write("%s\n" % self.symbol_decorator)
747            self.outfile.write(
748                "GType %sobject_proxy_get_type (void) G_GNUC_CONST;\n" % (self.ns_lower)
749            )
750            self.outfile.write("\n")
751            if self.generate_autocleanup in ("objects", "all"):
752                self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n")
753                self.outfile.write(
754                    "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObjectProxy, g_object_unref)\n"
755                    % (self.namespace)
756                )
757                self.outfile.write("#endif\n")
758                self.outfile.write("\n")
759            if self.symbol_decorator is not None:
760                self.outfile.write("%s\n" % self.symbol_decorator)
761            self.outfile.write(
762                "%sObjectProxy *%sobject_proxy_new (GDBusConnection *connection, const gchar *object_path);\n"
763                % (self.namespace, self.ns_lower)
764            )
765            self.outfile.write("\n")
766            self.outfile.write(
767                "#define %sTYPE_OBJECT_SKELETON (%sobject_skeleton_get_type ())\n"
768                % (self.ns_upper, self.ns_lower)
769            )
770            self.outfile.write(
771                "#define %sOBJECT_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT_SKELETON, %sObjectSkeleton))\n"
772                % (self.ns_upper, self.ns_upper, self.namespace)
773            )
774            self.outfile.write(
775                "#define %sOBJECT_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_OBJECT_SKELETON, %sObjectSkeletonClass))\n"
776                % (self.ns_upper, self.ns_upper, self.namespace)
777            )
778            self.outfile.write(
779                "#define %sOBJECT_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_OBJECT_SKELETON, %sObjectSkeletonClass))\n"
780                % (self.ns_upper, self.ns_upper, self.namespace)
781            )
782            self.outfile.write(
783                "#define %sIS_OBJECT_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT_SKELETON))\n"
784                % (self.ns_upper, self.ns_upper)
785            )
786            self.outfile.write(
787                "#define %sIS_OBJECT_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_OBJECT_SKELETON))\n"
788                % (self.ns_upper, self.ns_upper)
789            )
790            self.outfile.write("\n")
791            self.outfile.write(
792                "typedef struct _%sObjectSkeleton %sObjectSkeleton;\n"
793                % (self.namespace, self.namespace)
794            )
795            self.outfile.write(
796                "typedef struct _%sObjectSkeletonClass %sObjectSkeletonClass;\n"
797                % (self.namespace, self.namespace)
798            )
799            self.outfile.write(
800                "typedef struct _%sObjectSkeletonPrivate %sObjectSkeletonPrivate;\n"
801                % (self.namespace, self.namespace)
802            )
803            self.outfile.write("\n")
804            self.outfile.write("struct _%sObjectSkeleton\n" % (self.namespace))
805            self.outfile.write("{\n")
806            self.outfile.write("  /*< private >*/\n")
807            self.outfile.write("  GDBusObjectSkeleton parent_instance;\n")
808            self.outfile.write("  %sObjectSkeletonPrivate *priv;\n" % (self.namespace))
809            self.outfile.write("};\n")
810            self.outfile.write("\n")
811            self.outfile.write("struct _%sObjectSkeletonClass\n" % (self.namespace))
812            self.outfile.write("{\n")
813            self.outfile.write("  GDBusObjectSkeletonClass parent_class;\n")
814            self.outfile.write("};\n")
815            self.outfile.write("\n")
816            if self.symbol_decorator is not None:
817                self.outfile.write("%s\n" % self.symbol_decorator)
818            self.outfile.write(
819                "GType %sobject_skeleton_get_type (void) G_GNUC_CONST;\n"
820                % (self.ns_lower)
821            )
822            self.outfile.write("\n")
823            if self.generate_autocleanup in ("objects", "all"):
824                self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n")
825                self.outfile.write(
826                    "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObjectSkeleton, g_object_unref)\n"
827                    % (self.namespace)
828                )
829                self.outfile.write("#endif\n")
830                self.outfile.write("\n")
831            if self.symbol_decorator is not None:
832                self.outfile.write("%s\n" % self.symbol_decorator)
833            self.outfile.write(
834                "%sObjectSkeleton *%sobject_skeleton_new (const gchar *object_path);\n"
835                % (self.namespace, self.ns_lower)
836            )
837            for i in self.ifaces:
838                if self.symbol_decorator is not None:
839                    self.outfile.write("%s\n" % self.symbol_decorator)
840                if i.deprecated:
841                    self.outfile.write("G_GNUC_DEPRECATED ")
842                self.outfile.write(
843                    "void %sobject_skeleton_set_%s (%sObjectSkeleton *object, %s *interface_);\n"
844                    % (
845                        self.ns_lower,
846                        i.name_upper.lower(),
847                        self.namespace,
848                        i.camel_name,
849                    )
850                )
851            self.outfile.write("\n")
852
853            self.outfile.write("/* ---- */\n")
854            self.outfile.write("\n")
855            self.outfile.write(
856                "#define %sTYPE_OBJECT_MANAGER_CLIENT (%sobject_manager_client_get_type ())\n"
857                % (self.ns_upper, self.ns_lower)
858            )
859            self.outfile.write(
860                "#define %sOBJECT_MANAGER_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), %sTYPE_OBJECT_MANAGER_CLIENT, %sObjectManagerClient))\n"
861                % (self.ns_upper, self.ns_upper, self.namespace)
862            )
863            self.outfile.write(
864                "#define %sOBJECT_MANAGER_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), %sTYPE_OBJECT_MANAGER_CLIENT, %sObjectManagerClientClass))\n"
865                % (self.ns_upper, self.ns_upper, self.namespace)
866            )
867            self.outfile.write(
868                "#define %sOBJECT_MANAGER_CLIENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), %sTYPE_OBJECT_MANAGER_CLIENT, %sObjectManagerClientClass))\n"
869                % (self.ns_upper, self.ns_upper, self.namespace)
870            )
871            self.outfile.write(
872                "#define %sIS_OBJECT_MANAGER_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), %sTYPE_OBJECT_MANAGER_CLIENT))\n"
873                % (self.ns_upper, self.ns_upper)
874            )
875            self.outfile.write(
876                "#define %sIS_OBJECT_MANAGER_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), %sTYPE_OBJECT_MANAGER_CLIENT))\n"
877                % (self.ns_upper, self.ns_upper)
878            )
879            self.outfile.write("\n")
880            self.outfile.write(
881                "typedef struct _%sObjectManagerClient %sObjectManagerClient;\n"
882                % (self.namespace, self.namespace)
883            )
884            self.outfile.write(
885                "typedef struct _%sObjectManagerClientClass %sObjectManagerClientClass;\n"
886                % (self.namespace, self.namespace)
887            )
888            self.outfile.write(
889                "typedef struct _%sObjectManagerClientPrivate %sObjectManagerClientPrivate;\n"
890                % (self.namespace, self.namespace)
891            )
892            self.outfile.write("\n")
893            self.outfile.write("struct _%sObjectManagerClient\n" % (self.namespace))
894            self.outfile.write("{\n")
895            self.outfile.write("  /*< private >*/\n")
896            self.outfile.write("  GDBusObjectManagerClient parent_instance;\n")
897            self.outfile.write(
898                "  %sObjectManagerClientPrivate *priv;\n" % (self.namespace)
899            )
900            self.outfile.write("};\n")
901            self.outfile.write("\n")
902            self.outfile.write(
903                "struct _%sObjectManagerClientClass\n" % (self.namespace)
904            )
905            self.outfile.write("{\n")
906            self.outfile.write("  GDBusObjectManagerClientClass parent_class;\n")
907            self.outfile.write("};\n")
908            self.outfile.write("\n")
909            if self.generate_autocleanup in ("objects", "all"):
910                self.outfile.write("#if GLIB_CHECK_VERSION(2, 44, 0)\n")
911                self.outfile.write(
912                    "G_DEFINE_AUTOPTR_CLEANUP_FUNC (%sObjectManagerClient, g_object_unref)\n"
913                    % (self.namespace)
914                )
915                self.outfile.write("#endif\n")
916                self.outfile.write("\n")
917            if self.symbol_decorator is not None:
918                self.outfile.write("%s\n" % self.symbol_decorator)
919            self.outfile.write(
920                "GType %sobject_manager_client_get_type (void) G_GNUC_CONST;\n"
921                % (self.ns_lower)
922            )
923            self.outfile.write("\n")
924            if self.symbol_decorator is not None:
925                self.outfile.write("%s\n" % self.symbol_decorator)
926            self.outfile.write(
927                "GType %sobject_manager_client_get_proxy_type (GDBusObjectManagerClient *manager, const gchar *object_path, const gchar *interface_name, gpointer user_data);\n"
928                % (self.ns_lower)
929            )
930            self.outfile.write("\n")
931            if self.symbol_decorator is not None:
932                self.outfile.write("%s\n" % self.symbol_decorator)
933            self.outfile.write(
934                "void %sobject_manager_client_new (\n"
935                "    GDBusConnection        *connection,\n"
936                "    GDBusObjectManagerClientFlags  flags,\n"
937                "    const gchar            *name,\n"
938                "    const gchar            *object_path,\n"
939                "    GCancellable           *cancellable,\n"
940                "    GAsyncReadyCallback     callback,\n"
941                "    gpointer                user_data);\n" % (self.ns_lower)
942            )
943            if self.symbol_decorator is not None:
944                self.outfile.write("%s\n" % self.symbol_decorator)
945            self.outfile.write(
946                "GDBusObjectManager *%sobject_manager_client_new_finish (\n"
947                "    GAsyncResult        *res,\n"
948                "    GError             **error);\n" % (self.ns_lower)
949            )
950            if self.symbol_decorator is not None:
951                self.outfile.write("%s\n" % self.symbol_decorator)
952            self.outfile.write(
953                "GDBusObjectManager *%sobject_manager_client_new_sync (\n"
954                "    GDBusConnection        *connection,\n"
955                "    GDBusObjectManagerClientFlags  flags,\n"
956                "    const gchar            *name,\n"
957                "    const gchar            *object_path,\n"
958                "    GCancellable           *cancellable,\n"
959                "    GError                **error);\n" % (self.ns_lower)
960            )
961            self.outfile.write("\n")
962            if self.symbol_decorator is not None:
963                self.outfile.write("%s\n" % self.symbol_decorator)
964            self.outfile.write(
965                "void %sobject_manager_client_new_for_bus (\n"
966                "    GBusType                bus_type,\n"
967                "    GDBusObjectManagerClientFlags  flags,\n"
968                "    const gchar            *name,\n"
969                "    const gchar            *object_path,\n"
970                "    GCancellable           *cancellable,\n"
971                "    GAsyncReadyCallback     callback,\n"
972                "    gpointer                user_data);\n" % (self.ns_lower)
973            )
974            if self.symbol_decorator is not None:
975                self.outfile.write("%s\n" % self.symbol_decorator)
976            self.outfile.write(
977                "GDBusObjectManager *%sobject_manager_client_new_for_bus_finish (\n"
978                "    GAsyncResult        *res,\n"
979                "    GError             **error);\n" % (self.ns_lower)
980            )
981            if self.symbol_decorator is not None:
982                self.outfile.write("%s\n" % self.symbol_decorator)
983            self.outfile.write(
984                "GDBusObjectManager *%sobject_manager_client_new_for_bus_sync (\n"
985                "    GBusType                bus_type,\n"
986                "    GDBusObjectManagerClientFlags  flags,\n"
987                "    const gchar            *name,\n"
988                "    const gchar            *object_path,\n"
989                "    GCancellable           *cancellable,\n"
990                "    GError                **error);\n" % (self.ns_lower)
991            )
992            self.outfile.write("\n")
993
994    # ----------------------------------------------------------------------------------------------------
995
996    def generate_header_postamble(self):
997        self.outfile.write("\n")
998        self.outfile.write("G_END_DECLS\n")
999
1000        if not self.use_pragma:
1001            self.outfile.write("\n")
1002            self.outfile.write("#endif /* __{!s}__ */\n".format(self.header_guard))
1003
1004    # ----------------------------------------------------------------------------------------------------
1005
1006    def generate(self):
1007        self.generate_header_preamble()
1008        self.declare_types()
1009        self.generate_header_postamble()
1010
1011
1012# ----------------------------------------------------------------------------------------------------
1013
1014
1015class InterfaceInfoHeaderCodeGenerator:
1016    def __init__(
1017        self,
1018        ifaces,
1019        namespace,
1020        header_name,
1021        input_files_basenames,
1022        use_pragma,
1023        glib_min_required,
1024        symbol_decorator,
1025        symbol_decorator_header,
1026        outfile,
1027    ):
1028        self.ifaces = ifaces
1029        self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
1030        self.header_guard = generate_header_guard(header_name)
1031        self.input_files_basenames = input_files_basenames
1032        self.use_pragma = use_pragma
1033        self.glib_min_required = glib_min_required
1034        self.symbol_decorator = symbol_decorator
1035        if self.symbol_decorator is None:
1036            self.symbol_decorator = ""
1037        self.symbol_decorator_header = symbol_decorator_header
1038        self.outfile = outfile
1039
1040    # ----------------------------------------------------------------------------------------------------
1041
1042    def generate_header_preamble(self):
1043        basenames = ", ".join(self.input_files_basenames)
1044        self.outfile.write(LICENSE_STR.format(config.VERSION, basenames))
1045        self.outfile.write("\n")
1046
1047        if self.use_pragma:
1048            self.outfile.write("#pragma once\n")
1049        else:
1050            self.outfile.write("#ifndef __{!s}__\n".format(self.header_guard))
1051            self.outfile.write("#define __{!s}__\n".format(self.header_guard))
1052
1053        if self.symbol_decorator_header is not None:
1054            self.outfile.write("\n")
1055            self.outfile.write('#include "%s"\n' % self.symbol_decorator_header)
1056
1057        self.outfile.write("\n")
1058        self.outfile.write("#include <gio/gio.h>\n")
1059        self.outfile.write("\n")
1060        self.outfile.write("G_BEGIN_DECLS\n")
1061        self.outfile.write("\n")
1062
1063    # ----------------------------------------------------------------------------------------------------
1064
1065    def declare_infos(self):
1066        for i in self.ifaces:
1067            self.outfile.write(
1068                "extern %s const GDBusInterfaceInfo %s_interface;\n"
1069                % (self.symbol_decorator, i.name_lower)
1070            )
1071
1072    # ----------------------------------------------------------------------------------------------------
1073
1074    def generate_header_postamble(self):
1075        self.outfile.write("\n")
1076        self.outfile.write("G_END_DECLS\n")
1077
1078        if not self.use_pragma:
1079            self.outfile.write("\n")
1080            self.outfile.write("#endif /* __{!s}__ */\n".format(self.header_guard))
1081
1082    # ----------------------------------------------------------------------------------------------------
1083
1084    def generate(self):
1085        self.generate_header_preamble()
1086        self.declare_infos()
1087        self.generate_header_postamble()
1088
1089
1090# ----------------------------------------------------------------------------------------------------
1091
1092
1093class InterfaceInfoBodyCodeGenerator:
1094    def __init__(
1095        self,
1096        ifaces,
1097        namespace,
1098        header_name,
1099        input_files_basenames,
1100        glib_min_required,
1101        symbol_decoration_define,
1102        outfile,
1103    ):
1104        self.ifaces = ifaces
1105        self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
1106        self.header_name = header_name
1107        self.input_files_basenames = input_files_basenames
1108        self.glib_min_required = glib_min_required
1109        self.symbol_decoration_define = symbol_decoration_define
1110        self.outfile = outfile
1111
1112    # ----------------------------------------------------------------------------------------------------
1113
1114    def generate_body_preamble(self):
1115        basenames = ", ".join(self.input_files_basenames)
1116        self.outfile.write(LICENSE_STR.format(config.VERSION, basenames))
1117
1118        if self.symbol_decoration_define is not None:
1119            self.outfile.write("\n")
1120            self.outfile.write("#define %s\n" % self.symbol_decoration_define)
1121
1122        self.outfile.write("\n")
1123        self.outfile.write(
1124            "#ifdef HAVE_CONFIG_H\n"
1125            '#  include "config.h"\n'
1126            "#endif\n"
1127            "\n"
1128            '#include "%s"\n'
1129            "\n"
1130            "#include <string.h>\n" % (self.header_name)
1131        )
1132        self.outfile.write("\n")
1133
1134    # ----------------------------------------------------------------------------------------------------
1135
1136    def generate_array(self, array_name_lower, element_type, elements):
1137        self.outfile.write(
1138            "const %s * const %s[] =\n" % (element_type, array_name_lower)
1139        )
1140        self.outfile.write("{\n")
1141        for (_, name) in elements:
1142            self.outfile.write("  &%s,\n" % name)
1143        self.outfile.write("  NULL,\n")
1144        self.outfile.write("};\n")
1145        self.outfile.write("\n")
1146
1147    def define_annotations(self, array_name_lower, annotations):
1148        if len(annotations) == 0:
1149            return
1150
1151        annotation_pointers = []
1152
1153        for a in annotations:
1154            # Skip internal annotations.
1155            if a.key.startswith("org.gtk.GDBus"):
1156                continue
1157
1158            self.define_annotations(
1159                "%s__%s_annotations" % (array_name_lower, a.key_lower), a.annotations
1160            )
1161
1162            self.outfile.write(
1163                "const GDBusAnnotationInfo %s__%s_annotation =\n"
1164                % (array_name_lower, a.key_lower)
1165            )
1166            self.outfile.write("{\n")
1167            self.outfile.write("  -1,  /* ref count */\n")
1168            self.outfile.write('  (gchar *) "%s",\n' % a.key)
1169            self.outfile.write('  (gchar *) "%s",\n' % a.value)
1170            if len(a.annotations) > 0:
1171                self.outfile.write(
1172                    "  (GDBusAnnotationInfo **) %s__%s_annotations,\n"
1173                    % (array_name_lower, a.key_lower)
1174                )
1175            else:
1176                self.outfile.write("  NULL,  /* no annotations */\n")
1177            self.outfile.write("};\n")
1178            self.outfile.write("\n")
1179
1180            key = (a.since, "%s__%s_annotation" % (array_name_lower, a.key_lower))
1181            annotation_pointers.append(key)
1182
1183        self.generate_array(
1184            array_name_lower, "GDBusAnnotationInfo", annotation_pointers
1185        )
1186
1187    def define_args(self, array_name_lower, args):
1188        if len(args) == 0:
1189            return
1190
1191        arg_pointers = []
1192
1193        for a in args:
1194            self.define_annotations(
1195                "%s__%s_arg_annotations" % (array_name_lower, a.name), a.annotations
1196            )
1197
1198            self.outfile.write(
1199                "const GDBusArgInfo %s__%s_arg =\n" % (array_name_lower, a.name)
1200            )
1201            self.outfile.write("{\n")
1202            self.outfile.write("  -1,  /* ref count */\n")
1203            self.outfile.write('  (gchar *) "%s",\n' % a.name)
1204            self.outfile.write('  (gchar *) "%s",\n' % a.signature)
1205            if len(a.annotations) > 0:
1206                self.outfile.write(
1207                    "  (GDBusAnnotationInfo **) %s__%s_arg_annotations,\n"
1208                    % (array_name_lower, a.name)
1209                )
1210            else:
1211                self.outfile.write("  NULL,  /* no annotations */\n")
1212            self.outfile.write("};\n")
1213            self.outfile.write("\n")
1214
1215            key = (a.since, "%s__%s_arg" % (array_name_lower, a.name))
1216            arg_pointers.append(key)
1217
1218        self.generate_array(array_name_lower, "GDBusArgInfo", arg_pointers)
1219
1220    def define_infos(self):
1221        for i in self.ifaces:
1222            self.outfile.write(
1223                "/* ------------------------------------------------------------------------ */\n"
1224            )
1225            self.outfile.write("/* Definitions for %s */\n" % i.name)
1226            self.outfile.write("\n")
1227
1228            # GDBusMethodInfos.
1229            if len(i.methods) > 0:
1230                method_pointers = []
1231
1232                for m in i.methods:
1233                    self.define_args(
1234                        "%s_interface__%s_method_in_args"
1235                        % (i.name_lower, m.name_lower),
1236                        m.in_args,
1237                    )
1238                    self.define_args(
1239                        "%s_interface__%s_method_out_args"
1240                        % (i.name_lower, m.name_lower),
1241                        m.out_args,
1242                    )
1243                    self.define_annotations(
1244                        "%s_interface__%s_method_annotations"
1245                        % (i.name_lower, m.name_lower),
1246                        m.annotations,
1247                    )
1248
1249                    self.outfile.write(
1250                        "const GDBusMethodInfo %s_interface__%s_method =\n"
1251                        % (i.name_lower, m.name_lower)
1252                    )
1253                    self.outfile.write("{\n")
1254                    self.outfile.write("  -1,  /* ref count */\n")
1255                    self.outfile.write('  (gchar *) "%s",\n' % m.name)
1256                    if len(m.in_args) > 0:
1257                        self.outfile.write(
1258                            "  (GDBusArgInfo **) %s_interface__%s_method_in_args,\n"
1259                            % (i.name_lower, m.name_lower)
1260                        )
1261                    else:
1262                        self.outfile.write("  NULL,  /* no in args */\n")
1263                    if len(m.out_args) > 0:
1264                        self.outfile.write(
1265                            "  (GDBusArgInfo **) %s_interface__%s_method_out_args,\n"
1266                            % (i.name_lower, m.name_lower)
1267                        )
1268                    else:
1269                        self.outfile.write("  NULL,  /* no out args */\n")
1270                    if len(m.annotations) > 0:
1271                        self.outfile.write(
1272                            "  (GDBusAnnotationInfo **) %s_interface__%s_method_annotations,\n"
1273                            % (i.name_lower, m.name_lower)
1274                        )
1275                    else:
1276                        self.outfile.write("  NULL,  /* no annotations */\n")
1277                    self.outfile.write("};\n")
1278                    self.outfile.write("\n")
1279
1280                    key = (
1281                        m.since,
1282                        "%s_interface__%s_method" % (i.name_lower, m.name_lower),
1283                    )
1284                    method_pointers.append(key)
1285
1286                self.generate_array(
1287                    "%s_interface_methods" % i.name_lower,
1288                    "GDBusMethodInfo",
1289                    method_pointers,
1290                )
1291
1292            # GDBusSignalInfos.
1293            if len(i.signals) > 0:
1294                signal_pointers = []
1295
1296                for s in i.signals:
1297                    self.define_args(
1298                        "%s_interface__%s_signal_args" % (i.name_lower, s.name_lower),
1299                        s.args,
1300                    )
1301                    self.define_annotations(
1302                        "%s_interface__%s_signal_annotations"
1303                        % (i.name_lower, s.name_lower),
1304                        s.annotations,
1305                    )
1306
1307                    self.outfile.write(
1308                        "const GDBusSignalInfo %s_interface__%s_signal =\n"
1309                        % (i.name_lower, s.name_lower)
1310                    )
1311                    self.outfile.write("{\n")
1312                    self.outfile.write("  -1,  /* ref count */\n")
1313                    self.outfile.write('  (gchar *) "%s",\n' % s.name)
1314                    if len(s.args) > 0:
1315                        self.outfile.write(
1316                            "  (GDBusArgInfo **) %s_interface__%s_signal_args,\n"
1317                            % (i.name_lower, s.name_lower)
1318                        )
1319                    else:
1320                        self.outfile.write("  NULL,  /* no args */\n")
1321                    if len(s.annotations) > 0:
1322                        self.outfile.write(
1323                            "  (GDBusAnnotationInfo **) %s_interface__%s_signal_annotations,\n"
1324                            % (i.name_lower, s.name_lower)
1325                        )
1326                    else:
1327                        self.outfile.write("  NULL,  /* no annotations */\n")
1328                    self.outfile.write("};\n")
1329                    self.outfile.write("\n")
1330
1331                    key = (
1332                        s.since,
1333                        "%s_interface__%s_signal" % (i.name_lower, s.name_lower),
1334                    )
1335                    signal_pointers.append(key)
1336
1337                self.generate_array(
1338                    "%s_interface_signals" % i.name_lower,
1339                    "GDBusSignalInfo",
1340                    signal_pointers,
1341                )
1342
1343            # GDBusPropertyInfos.
1344            if len(i.properties) > 0:
1345                property_pointers = []
1346
1347                for p in i.properties:
1348                    if p.readable and p.writable:
1349                        flags = "G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"
1350                    elif p.readable:
1351                        flags = "G_DBUS_PROPERTY_INFO_FLAGS_READABLE"
1352                    elif p.writable:
1353                        flags = "G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"
1354                    else:
1355                        flags = "G_DBUS_PROPERTY_INFO_FLAGS_NONE"
1356
1357                    self.define_annotations(
1358                        "%s_interface__%s_property_annotations"
1359                        % (i.name_lower, p.name_lower),
1360                        p.annotations,
1361                    )
1362
1363                    self.outfile.write(
1364                        "const GDBusPropertyInfo %s_interface__%s_property =\n"
1365                        % (i.name_lower, p.name_lower)
1366                    )
1367                    self.outfile.write("{\n")
1368                    self.outfile.write("  -1,  /* ref count */\n")
1369                    self.outfile.write('  (gchar *) "%s",\n' % p.name)
1370                    self.outfile.write('  (gchar *) "%s",\n' % p.signature)
1371                    self.outfile.write("  %s,\n" % flags)
1372                    if len(p.annotations) > 0:
1373                        self.outfile.write(
1374                            "  (GDBusAnnotationInfo **) %s_interface__%s_property_annotations,\n"
1375                            % (i.name_lower, p.name_lower)
1376                        )
1377                    else:
1378                        self.outfile.write("  NULL,  /* no annotations */\n")
1379                    self.outfile.write("};\n")
1380                    self.outfile.write("\n")
1381
1382                    key = (
1383                        p.since,
1384                        "%s_interface__%s_property" % (i.name_lower, p.name_lower),
1385                    )
1386                    property_pointers.append(key)
1387
1388                self.generate_array(
1389                    "%s_interface_properties" % i.name_lower,
1390                    "GDBusPropertyInfo",
1391                    property_pointers,
1392                )
1393
1394            # Finally the GDBusInterfaceInfo.
1395            self.define_annotations(
1396                "%s_interface_annotations" % i.name_lower, i.annotations
1397            )
1398
1399            self.outfile.write(
1400                "const GDBusInterfaceInfo %s_interface =\n" % i.name_lower
1401            )
1402            self.outfile.write("{\n")
1403            self.outfile.write("  -1,  /* ref count */\n")
1404            self.outfile.write('  (gchar *) "%s",\n' % i.name)
1405            if len(i.methods) > 0:
1406                self.outfile.write(
1407                    "  (GDBusMethodInfo **) %s_interface_methods,\n" % i.name_lower
1408                )
1409            else:
1410                self.outfile.write("  NULL,  /* no methods */\n")
1411            if len(i.signals) > 0:
1412                self.outfile.write(
1413                    "  (GDBusSignalInfo **) %s_interface_signals,\n" % i.name_lower
1414                )
1415            else:
1416                self.outfile.write("  NULL,  /* no signals */\n")
1417            if len(i.properties) > 0:
1418                self.outfile.write(
1419                    "  (GDBusPropertyInfo **) %s_interface_properties,\n" % i.name_lower
1420                )
1421            else:
1422                self.outfile.write("NULL,  /* no properties */\n")
1423            if len(i.annotations) > 0:
1424                self.outfile.write(
1425                    "  (GDBusAnnotationInfo **) %s_interface_annotations,\n"
1426                    % i.name_lower
1427                )
1428            else:
1429                self.outfile.write("  NULL,  /* no annotations */\n")
1430            self.outfile.write("};\n")
1431            self.outfile.write("\n")
1432
1433    # ----------------------------------------------------------------------------------------------------
1434
1435    def generate(self):
1436        self.generate_body_preamble()
1437        self.define_infos()
1438
1439
1440# ----------------------------------------------------------------------------------------------------
1441
1442
1443class CodeGenerator:
1444    def __init__(
1445        self,
1446        ifaces,
1447        namespace,
1448        generate_objmanager,
1449        header_name,
1450        input_files_basenames,
1451        docbook_gen,
1452        glib_min_required,
1453        symbol_decoration_define,
1454        outfile,
1455    ):
1456        self.ifaces = ifaces
1457        self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
1458        self.generate_objmanager = generate_objmanager
1459        self.header_name = header_name
1460        self.input_files_basenames = input_files_basenames
1461        self.docbook_gen = docbook_gen
1462        self.glib_min_required = glib_min_required
1463        self.symbol_decoration_define = symbol_decoration_define
1464        self.outfile = outfile
1465
1466    # ----------------------------------------------------------------------------------------------------
1467
1468    def generate_body_preamble(self):
1469        basenames = ", ".join(self.input_files_basenames)
1470        self.outfile.write(LICENSE_STR.format(config.VERSION, basenames))
1471        if self.symbol_decoration_define is not None:
1472            self.outfile.write("\n")
1473            self.outfile.write("#define %s\n" % self.symbol_decoration_define)
1474        self.outfile.write("\n")
1475        self.outfile.write(
1476            "#ifdef HAVE_CONFIG_H\n"
1477            '#  include "config.h"\n'
1478            "#endif\n"
1479            "\n"
1480            '#include "%s"\n'
1481            "\n"
1482            "#include <string.h>\n" % (self.header_name)
1483        )
1484
1485        self.outfile.write(
1486            "#ifdef G_OS_UNIX\n" "#  include <gio/gunixfdlist.h>\n" "#endif\n" "\n"
1487        )
1488
1489        self.outfile.write(
1490            "typedef struct\n"
1491            "{\n"
1492            "  GDBusArgInfo parent_struct;\n"
1493            "  gboolean use_gvariant;\n"
1494            "} _ExtendedGDBusArgInfo;\n"
1495            "\n"
1496        )
1497
1498        self.outfile.write(
1499            "typedef struct\n"
1500            "{\n"
1501            "  GDBusMethodInfo parent_struct;\n"
1502            "  const gchar *signal_name;\n"
1503            "  gboolean pass_fdlist;\n"
1504            "} _ExtendedGDBusMethodInfo;\n"
1505            "\n"
1506        )
1507
1508        self.outfile.write(
1509            "typedef struct\n"
1510            "{\n"
1511            "  GDBusSignalInfo parent_struct;\n"
1512            "  const gchar *signal_name;\n"
1513            "} _ExtendedGDBusSignalInfo;\n"
1514            "\n"
1515        )
1516
1517        self.outfile.write(
1518            "typedef struct\n"
1519            "{\n"
1520            "  GDBusPropertyInfo parent_struct;\n"
1521            "  const gchar *hyphen_name;\n"
1522            "  guint use_gvariant : 1;\n"
1523            "  guint emits_changed_signal : 1;\n"
1524            "} _ExtendedGDBusPropertyInfo;\n"
1525            "\n"
1526        )
1527
1528        self.outfile.write(
1529            "typedef struct\n"
1530            "{\n"
1531            "  GDBusInterfaceInfo parent_struct;\n"
1532            "  const gchar *hyphen_name;\n"
1533            "} _ExtendedGDBusInterfaceInfo;\n"
1534            "\n"
1535        )
1536
1537        self.outfile.write(
1538            "typedef struct\n"
1539            "{\n"
1540            "  const _ExtendedGDBusPropertyInfo *info;\n"
1541            "  guint prop_id;\n"
1542            "  GValue orig_value; /* the value before the change */\n"
1543            "} ChangedProperty;\n"
1544            "\n"
1545            "static void\n"
1546            "_changed_property_free (ChangedProperty *data)\n"
1547            "{\n"
1548            "  g_value_unset (&data->orig_value);\n"
1549            "  g_free (data);\n"
1550            "}\n"
1551            "\n"
1552        )
1553
1554        self.outfile.write(
1555            "static gboolean\n"
1556            "_g_strv_equal0 (gchar **a, gchar **b)\n"
1557            "{\n"
1558            "  gboolean ret = FALSE;\n"
1559            "  guint n;\n"
1560            "  if (a == NULL && b == NULL)\n"
1561            "    {\n"
1562            "      ret = TRUE;\n"
1563            "      goto out;\n"
1564            "    }\n"
1565            "  if (a == NULL || b == NULL)\n"
1566            "    goto out;\n"
1567            "  if (g_strv_length (a) != g_strv_length (b))\n"
1568            "    goto out;\n"
1569            "  for (n = 0; a[n] != NULL; n++)\n"
1570            "    if (g_strcmp0 (a[n], b[n]) != 0)\n"
1571            "      goto out;\n"
1572            "  ret = TRUE;\n"
1573            "out:\n"
1574            "  return ret;\n"
1575            "}\n"
1576            "\n"
1577        )
1578
1579        self.outfile.write(
1580            "static gboolean\n"
1581            "_g_variant_equal0 (GVariant *a, GVariant *b)\n"
1582            "{\n"
1583            "  gboolean ret = FALSE;\n"
1584            "  if (a == NULL && b == NULL)\n"
1585            "    {\n"
1586            "      ret = TRUE;\n"
1587            "      goto out;\n"
1588            "    }\n"
1589            "  if (a == NULL || b == NULL)\n"
1590            "    goto out;\n"
1591            "  ret = g_variant_equal (a, b);\n"
1592            "out:\n"
1593            "  return ret;\n"
1594            "}\n"
1595            "\n"
1596        )
1597
1598        # simplified - only supports the types we use
1599        self.outfile.write(
1600            "G_GNUC_UNUSED static gboolean\n"
1601            "_g_value_equal (const GValue *a, const GValue *b)\n"
1602            "{\n"
1603            "  gboolean ret = FALSE;\n"
1604            "  g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));\n"
1605            "  switch (G_VALUE_TYPE (a))\n"
1606            "    {\n"
1607            "      case G_TYPE_BOOLEAN:\n"
1608            "        ret = (g_value_get_boolean (a) == g_value_get_boolean (b));\n"
1609            "        break;\n"
1610            "      case G_TYPE_UCHAR:\n"
1611            "        ret = (g_value_get_uchar (a) == g_value_get_uchar (b));\n"
1612            "        break;\n"
1613            "      case G_TYPE_INT:\n"
1614            "        ret = (g_value_get_int (a) == g_value_get_int (b));\n"
1615            "        break;\n"
1616            "      case G_TYPE_UINT:\n"
1617            "        ret = (g_value_get_uint (a) == g_value_get_uint (b));\n"
1618            "        break;\n"
1619            "      case G_TYPE_INT64:\n"
1620            "        ret = (g_value_get_int64 (a) == g_value_get_int64 (b));\n"
1621            "        break;\n"
1622            "      case G_TYPE_UINT64:\n"
1623            "        ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));\n"
1624            "        break;\n"
1625            "      case G_TYPE_DOUBLE:\n"
1626            "        {\n"
1627            "          /* Avoid -Wfloat-equal warnings by doing a direct bit compare */\n"
1628            "          gdouble da = g_value_get_double (a);\n"
1629            "          gdouble db = g_value_get_double (b);\n"
1630            "          ret = memcmp (&da, &db, sizeof (gdouble)) == 0;\n"
1631            "        }\n"
1632            "        break;\n"
1633            "      case G_TYPE_STRING:\n"
1634            "        ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);\n"
1635            "        break;\n"
1636            "      case G_TYPE_VARIANT:\n"
1637            "        ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b));\n"
1638            "        break;\n"
1639            "      default:\n"
1640            "        if (G_VALUE_TYPE (a) == G_TYPE_STRV)\n"
1641            "          ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b));\n"
1642            "        else\n"
1643            '          g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a)));\n'
1644            "        break;\n"
1645            "    }\n"
1646            "  return ret;\n"
1647            "}\n"
1648            "\n"
1649        )
1650
1651    def generate_annotations(self, prefix, annotations):
1652        if annotations is None:
1653            return
1654
1655        n = 0
1656        for a in annotations:
1657            # self.generate_annotations('%s_%d'%(prefix, n), a.get_annotations())
1658
1659            # skip internal annotations
1660            if a.key.startswith("org.gtk.GDBus"):
1661                continue
1662
1663            self.outfile.write(
1664                "static const GDBusAnnotationInfo %s_%d =\n"
1665                "{\n"
1666                "  -1,\n"
1667                '  (gchar *) "%s",\n'
1668                '  (gchar *) "%s",\n' % (prefix, n, a.key, a.value)
1669            )
1670            if len(a.annotations) == 0:
1671                self.outfile.write("  NULL\n")
1672            else:
1673                self.outfile.write(
1674                    "  (GDBusAnnotationInfo **) &%s_%d_pointers\n" % (prefix, n)
1675                )
1676            self.outfile.write("};\n" "\n")
1677            n += 1
1678
1679        if n > 0:
1680            self.outfile.write(
1681                "static const GDBusAnnotationInfo * const %s_pointers[] =\n"
1682                "{\n" % (prefix)
1683            )
1684            m = 0
1685            for a in annotations:
1686                if a.key.startswith("org.gtk.GDBus"):
1687                    continue
1688                self.outfile.write("  &%s_%d,\n" % (prefix, m))
1689                m += 1
1690            self.outfile.write("  NULL\n" "};\n" "\n")
1691        return n
1692
1693    def generate_args(self, prefix, args):
1694        for a in args:
1695            num_anno = self.generate_annotations(
1696                "%s_arg_%s_annotation_info" % (prefix, a.name), a.annotations
1697            )
1698
1699            self.outfile.write(
1700                "static const _ExtendedGDBusArgInfo %s_%s =\n"
1701                "{\n"
1702                "  {\n"
1703                "    -1,\n"
1704                '    (gchar *) "%s",\n'
1705                '    (gchar *) "%s",\n' % (prefix, a.name, a.name, a.signature)
1706            )
1707            if num_anno == 0:
1708                self.outfile.write("    NULL\n")
1709            else:
1710                self.outfile.write(
1711                    "    (GDBusAnnotationInfo **) &%s_arg_%s_annotation_info_pointers\n"
1712                    % (prefix, a.name)
1713                )
1714            self.outfile.write("  },\n")
1715            if not utils.lookup_annotation(
1716                a.annotations, "org.gtk.GDBus.C.ForceGVariant"
1717            ):
1718                self.outfile.write("  FALSE\n")
1719            else:
1720                self.outfile.write("  TRUE\n")
1721            self.outfile.write("};\n" "\n")
1722
1723        if len(args) > 0:
1724            self.outfile.write(
1725                "static const GDBusArgInfo * const %s_pointers[] =\n" "{\n" % (prefix)
1726            )
1727            for a in args:
1728                self.outfile.write("  &%s_%s.parent_struct,\n" % (prefix, a.name))
1729            self.outfile.write("  NULL\n" "};\n" "\n")
1730
1731    def generate_introspection_for_interface(self, i):
1732        self.outfile.write(
1733            "/* ---- Introspection data for %s ---- */\n" "\n" % (i.name)
1734        )
1735
1736        if len(i.methods) > 0:
1737            for m in i.methods:
1738                self.generate_args(
1739                    "_%s_method_info_%s_IN_ARG" % (i.name_lower, m.name_lower),
1740                    m.in_args,
1741                )
1742                self.generate_args(
1743                    "_%s_method_info_%s_OUT_ARG" % (i.name_lower, m.name_lower),
1744                    m.out_args,
1745                )
1746
1747                num_anno = self.generate_annotations(
1748                    "_%s_method_%s_annotation_info" % (i.name_lower, m.name_lower),
1749                    m.annotations,
1750                )
1751
1752                self.outfile.write(
1753                    "static const _ExtendedGDBusMethodInfo _%s_method_info_%s =\n"
1754                    "{\n"
1755                    "  {\n"
1756                    "    -1,\n"
1757                    '    (gchar *) "%s",\n' % (i.name_lower, m.name_lower, m.name)
1758                )
1759                if len(m.in_args) == 0:
1760                    self.outfile.write("    NULL,\n")
1761                else:
1762                    self.outfile.write(
1763                        "    (GDBusArgInfo **) &_%s_method_info_%s_IN_ARG_pointers,\n"
1764                        % (i.name_lower, m.name_lower)
1765                    )
1766                if len(m.out_args) == 0:
1767                    self.outfile.write("    NULL,\n")
1768                else:
1769                    self.outfile.write(
1770                        "    (GDBusArgInfo **) &_%s_method_info_%s_OUT_ARG_pointers,\n"
1771                        % (i.name_lower, m.name_lower)
1772                    )
1773                if num_anno == 0:
1774                    self.outfile.write("    NULL\n")
1775                else:
1776                    self.outfile.write(
1777                        "    (GDBusAnnotationInfo **) &_%s_method_%s_annotation_info_pointers\n"
1778                        % (i.name_lower, m.name_lower)
1779                    )
1780                self.outfile.write(
1781                    "  },\n"
1782                    '  "handle-%s",\n'
1783                    "  %s\n" % (m.name_hyphen, "TRUE" if m.unix_fd else "FALSE")
1784                )
1785                self.outfile.write("};\n" "\n")
1786
1787            self.outfile.write(
1788                "static const GDBusMethodInfo * const _%s_method_info_pointers[] =\n"
1789                "{\n" % (i.name_lower)
1790            )
1791            for m in i.methods:
1792                self.outfile.write(
1793                    "  &_%s_method_info_%s.parent_struct,\n"
1794                    % (i.name_lower, m.name_lower)
1795                )
1796            self.outfile.write("  NULL\n" "};\n" "\n")
1797
1798        # ---
1799
1800        if len(i.signals) > 0:
1801            for s in i.signals:
1802                self.generate_args(
1803                    "_%s_signal_info_%s_ARG" % (i.name_lower, s.name_lower), s.args
1804                )
1805
1806                num_anno = self.generate_annotations(
1807                    "_%s_signal_%s_annotation_info" % (i.name_lower, s.name_lower),
1808                    s.annotations,
1809                )
1810                self.outfile.write(
1811                    "static const _ExtendedGDBusSignalInfo _%s_signal_info_%s =\n"
1812                    "{\n"
1813                    "  {\n"
1814                    "    -1,\n"
1815                    '    (gchar *) "%s",\n' % (i.name_lower, s.name_lower, s.name)
1816                )
1817                if len(s.args) == 0:
1818                    self.outfile.write("    NULL,\n")
1819                else:
1820                    self.outfile.write(
1821                        "    (GDBusArgInfo **) &_%s_signal_info_%s_ARG_pointers,\n"
1822                        % (i.name_lower, s.name_lower)
1823                    )
1824                if num_anno == 0:
1825                    self.outfile.write("    NULL\n")
1826                else:
1827                    self.outfile.write(
1828                        "    (GDBusAnnotationInfo **) &_%s_signal_%s_annotation_info_pointers\n"
1829                        % (i.name_lower, s.name_lower)
1830                    )
1831                self.outfile.write("  },\n" '  "%s"\n' % (s.name_hyphen))
1832                self.outfile.write("};\n" "\n")
1833
1834            self.outfile.write(
1835                "static const GDBusSignalInfo * const _%s_signal_info_pointers[] =\n"
1836                "{\n" % (i.name_lower)
1837            )
1838            for s in i.signals:
1839                self.outfile.write(
1840                    "  &_%s_signal_info_%s.parent_struct,\n"
1841                    % (i.name_lower, s.name_lower)
1842                )
1843            self.outfile.write("  NULL\n" "};\n" "\n")
1844
1845        # ---
1846
1847        if len(i.properties) > 0:
1848            for p in i.properties:
1849                if p.readable and p.writable:
1850                    access = "G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"
1851                elif p.readable:
1852                    access = "G_DBUS_PROPERTY_INFO_FLAGS_READABLE"
1853                elif p.writable:
1854                    access = "G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE"
1855                else:
1856                    access = "G_DBUS_PROPERTY_INFO_FLAGS_NONE"
1857                num_anno = self.generate_annotations(
1858                    "_%s_property_%s_annotation_info" % (i.name_lower, p.name_lower),
1859                    p.annotations,
1860                )
1861                self.outfile.write(
1862                    "static const _ExtendedGDBusPropertyInfo _%s_property_info_%s =\n"
1863                    "{\n"
1864                    "  {\n"
1865                    "    -1,\n"
1866                    '    (gchar *) "%s",\n'
1867                    '    (gchar *) "%s",\n'
1868                    "    %s,\n"
1869                    % (i.name_lower, p.name_lower, p.name, p.arg.signature, access)
1870                )
1871                if num_anno == 0:
1872                    self.outfile.write("    NULL\n")
1873                else:
1874                    self.outfile.write(
1875                        "    (GDBusAnnotationInfo **) &_%s_property_%s_annotation_info_pointers\n"
1876                        % (i.name_lower, p.name_lower)
1877                    )
1878                self.outfile.write("  },\n" '  "%s",\n' % (p.name_hyphen))
1879                if not utils.lookup_annotation(
1880                    p.annotations, "org.gtk.GDBus.C.ForceGVariant"
1881                ):
1882                    self.outfile.write("  FALSE,\n")
1883                else:
1884                    self.outfile.write("  TRUE,\n")
1885                if p.emits_changed_signal:
1886                    self.outfile.write("  TRUE\n")
1887                else:
1888                    self.outfile.write("  FALSE\n")
1889                self.outfile.write("};\n" "\n")
1890
1891            self.outfile.write(
1892                "static const GDBusPropertyInfo * const _%s_property_info_pointers[] =\n"
1893                "{\n" % (i.name_lower)
1894            )
1895            for p in i.properties:
1896                self.outfile.write(
1897                    "  &_%s_property_info_%s.parent_struct,\n"
1898                    % (i.name_lower, p.name_lower)
1899                )
1900            self.outfile.write("  NULL\n" "};\n" "\n")
1901
1902        num_anno = self.generate_annotations(
1903            "_%s_annotation_info" % (i.name_lower), i.annotations
1904        )
1905        self.outfile.write(
1906            "static const _ExtendedGDBusInterfaceInfo _%s_interface_info =\n"
1907            "{\n"
1908            "  {\n"
1909            "    -1,\n"
1910            '    (gchar *) "%s",\n' % (i.name_lower, i.name)
1911        )
1912        if len(i.methods) == 0:
1913            self.outfile.write("    NULL,\n")
1914        else:
1915            self.outfile.write(
1916                "    (GDBusMethodInfo **) &_%s_method_info_pointers,\n" % (i.name_lower)
1917            )
1918        if len(i.signals) == 0:
1919            self.outfile.write("    NULL,\n")
1920        else:
1921            self.outfile.write(
1922                "    (GDBusSignalInfo **) &_%s_signal_info_pointers,\n" % (i.name_lower)
1923            )
1924        if len(i.properties) == 0:
1925            self.outfile.write("    NULL,\n")
1926        else:
1927            self.outfile.write(
1928                "    (GDBusPropertyInfo **) &_%s_property_info_pointers,\n"
1929                % (i.name_lower)
1930            )
1931        if num_anno == 0:
1932            self.outfile.write("    NULL\n")
1933        else:
1934            self.outfile.write(
1935                "    (GDBusAnnotationInfo **) &_%s_annotation_info_pointers\n"
1936                % (i.name_lower)
1937            )
1938        self.outfile.write("  },\n" '  "%s",\n' "};\n" "\n" % (i.name_hyphen))
1939        self.outfile.write("\n")
1940        self.outfile.write(
1941            self.docbook_gen.expand(
1942                "/**\n"
1943                " * %s_interface_info:\n"
1944                " *\n"
1945                " * Gets a machine-readable description of the #%s D-Bus interface.\n"
1946                " *\n"
1947                " * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free.\n"
1948                % (i.name_lower, i.name),
1949                False,
1950            )
1951        )
1952        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
1953        self.outfile.write(
1954            "GDBusInterfaceInfo *\n"
1955            "%s_interface_info (void)\n"
1956            "{\n"
1957            "  return (GDBusInterfaceInfo *) &_%s_interface_info.parent_struct;\n"
1958            "}\n"
1959            "\n" % (i.name_lower, i.name_lower)
1960        )
1961
1962        self.outfile.write(
1963            self.docbook_gen.expand(
1964                "/**\n"
1965                " * %s_override_properties:\n"
1966                " * @klass: The class structure for a #GObject derived class.\n"
1967                " * @property_id_begin: The property id to assign to the first overridden property.\n"
1968                " *\n"
1969                " * Overrides all #GObject properties in the #%s interface for a concrete class.\n"
1970                " * The properties are overridden in the order they are defined.\n"
1971                " *\n"
1972                " * Returns: The last property id.\n" % (i.name_lower, i.camel_name),
1973                False,
1974            )
1975        )
1976        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
1977        self.outfile.write(
1978            "guint\n" "%s_override_properties (GObjectClass *klass" % (i.name_lower)
1979        )
1980        if len(i.properties) == 0:
1981            self.outfile.write(" G_GNUC_UNUSED")
1982        self.outfile.write(", guint property_id_begin)\n" "{\n")
1983        for p in i.properties:
1984            self.outfile.write(
1985                '  g_object_class_override_property (klass, property_id_begin++, "%s");\n'
1986                % (p.name_hyphen)
1987            )
1988        self.outfile.write("  return property_id_begin - 1;\n" "}\n" "\n")
1989        self.outfile.write("\n")
1990
1991    # ----------------------------------------------------------------------------------------------------
1992
1993    def generate_interface(self, i):
1994        self.outfile.write("\n")
1995
1996        self.outfile.write(
1997            self.docbook_gen.expand(
1998                "/**\n"
1999                " * %s:\n"
2000                " *\n"
2001                " * Abstract interface type for the D-Bus interface #%s.\n"
2002                % (i.camel_name, i.name),
2003                False,
2004            )
2005        )
2006        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
2007        self.outfile.write("\n")
2008
2009        self.outfile.write(
2010            self.docbook_gen.expand(
2011                "/**\n"
2012                " * %sIface:\n"
2013                " * @parent_iface: The parent interface.\n" % (i.camel_name),
2014                False,
2015            )
2016        )
2017
2018        doc_bits = {}
2019        if len(i.methods) > 0:
2020            for m in i.methods:
2021                key = (m.since, "_method_%s" % m.name_lower)
2022                value = "@handle_%s: " % (m.name_lower)
2023                value += "Handler for the #%s::handle-%s signal." % (
2024                    i.camel_name,
2025                    m.name_hyphen,
2026                )
2027                doc_bits[key] = value
2028        if len(i.signals) > 0:
2029            for s in i.signals:
2030                key = (s.since, "_signal_%s" % s.name_lower)
2031                value = "@%s: " % (s.name_lower)
2032                value += "Handler for the #%s::%s signal." % (
2033                    i.camel_name,
2034                    s.name_hyphen,
2035                )
2036                doc_bits[key] = value
2037        if len(i.properties) > 0:
2038            for p in i.properties:
2039                key = (p.since, "_prop_get_%s" % p.name_lower)
2040                value = "@get_%s: " % (p.name_lower)
2041                value += "Getter for the #%s:%s property." % (
2042                    i.camel_name,
2043                    p.name_hyphen,
2044                )
2045                doc_bits[key] = value
2046        for key in sorted(doc_bits.keys(), key=utils.version_cmp_key):
2047            self.outfile.write(" * %s\n" % doc_bits[key])
2048
2049        self.outfile.write(
2050            self.docbook_gen.expand(
2051                " *\n" " * Virtual table for the D-Bus interface #%s.\n" % (i.name),
2052                False,
2053            )
2054        )
2055        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
2056        self.outfile.write("\n")
2057
2058        self.outfile.write(
2059            "typedef %sIface %sInterface;\n" % (i.camel_name, i.camel_name)
2060        )
2061        self.outfile.write(
2062            "G_DEFINE_INTERFACE (%s, %s, G_TYPE_OBJECT)\n"
2063            % (i.camel_name, i.name_lower)
2064        )
2065        self.outfile.write("\n")
2066
2067        self.outfile.write(
2068            "static void\n"
2069            "%s_default_init (%sIface *iface" % (i.name_lower, i.camel_name)
2070        )
2071        if len(i.methods) == 0 and len(i.signals) == 0 and len(i.properties) == 0:
2072            self.outfile.write(" G_GNUC_UNUSED)\n")
2073        else:
2074            self.outfile.write(")\n")
2075        self.outfile.write("{\n")
2076        if len(i.methods) > 0:
2077            self.outfile.write(
2078                "  /* GObject signals for incoming D-Bus method calls: */\n"
2079            )
2080            for m in i.methods:
2081                self.outfile.write(
2082                    self.docbook_gen.expand(
2083                        "  /**\n"
2084                        "   * %s::handle-%s:\n"
2085                        "   * @object: A #%s.\n"
2086                        "   * @invocation: A #GDBusMethodInvocation.\n"
2087                        % (i.camel_name, m.name_hyphen, i.camel_name),
2088                        False,
2089                    )
2090                )
2091                if m.unix_fd:
2092                    self.outfile.write(
2093                        "   * @fd_list: (nullable): A #GUnixFDList or %NULL.\n"
2094                    )
2095                for a in m.in_args:
2096                    self.outfile.write(
2097                        "   * @arg_%s: Argument passed by remote caller.\n" % (a.name)
2098                    )
2099                self.outfile.write(
2100                    self.docbook_gen.expand(
2101                        "   *\n"
2102                        "   * Signal emitted when a remote caller is invoking the %s.%s() D-Bus method.\n"
2103                        "   *\n"
2104                        "   * If a signal handler returns %%TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call %s_complete_%s() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %%G_DBUS_ERROR_UNKNOWN_METHOD error is returned.\n"
2105                        "   *\n"
2106                        "   * Returns: %%G_DBUS_METHOD_INVOCATION_HANDLED or %%TRUE if the invocation was handled, %%G_DBUS_METHOD_INVOCATION_UNHANDLED or %%FALSE to let other signal handlers run.\n"
2107                        % (i.name, m.name, i.name_lower, m.name_lower),
2108                        False,
2109                    )
2110                )
2111                self.write_gtkdoc_deprecated_and_since_and_close(m, self.outfile, 2)
2112                if m.unix_fd:
2113                    extra_args = 2
2114                else:
2115                    extra_args = 1
2116                self.outfile.write(
2117                    '  g_signal_new ("handle-%s",\n'
2118                    "    G_TYPE_FROM_INTERFACE (iface),\n"
2119                    "    G_SIGNAL_RUN_LAST,\n"
2120                    "    G_STRUCT_OFFSET (%sIface, handle_%s),\n"
2121                    "    g_signal_accumulator_true_handled,\n"
2122                    "    NULL,\n"  # accu_data
2123                    "    g_cclosure_marshal_generic,\n"
2124                    "    G_TYPE_BOOLEAN,\n"
2125                    "    %d,\n"
2126                    "    G_TYPE_DBUS_METHOD_INVOCATION"
2127                    % (
2128                        m.name_hyphen,
2129                        i.camel_name,
2130                        m.name_lower,
2131                        len(m.in_args) + extra_args,
2132                    )
2133                )
2134                if m.unix_fd:
2135                    self.outfile.write(", G_TYPE_UNIX_FD_LIST")
2136                for a in m.in_args:
2137                    self.outfile.write(", %s" % (a.gtype))
2138                self.outfile.write(");\n")
2139                self.outfile.write("\n")
2140
2141        if len(i.signals) > 0:
2142            self.outfile.write("  /* GObject signals for received D-Bus signals: */\n")
2143            for s in i.signals:
2144                self.outfile.write(
2145                    self.docbook_gen.expand(
2146                        "  /**\n"
2147                        "   * %s::%s:\n"
2148                        "   * @object: A #%s.\n"
2149                        % (i.camel_name, s.name_hyphen, i.camel_name),
2150                        False,
2151                    )
2152                )
2153                for a in s.args:
2154                    self.outfile.write("   * @arg_%s: Argument.\n" % (a.name))
2155                self.outfile.write(
2156                    self.docbook_gen.expand(
2157                        "   *\n"
2158                        "   * On the client-side, this signal is emitted whenever the D-Bus signal #%s::%s is received.\n"
2159                        "   *\n"
2160                        "   * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.\n"
2161                        % (i.name, s.name),
2162                        False,
2163                    )
2164                )
2165                self.write_gtkdoc_deprecated_and_since_and_close(s, self.outfile, 2)
2166                self.outfile.write(
2167                    '  g_signal_new ("%s",\n'
2168                    "    G_TYPE_FROM_INTERFACE (iface),\n"
2169                    "    G_SIGNAL_RUN_LAST,\n"
2170                    "    G_STRUCT_OFFSET (%sIface, %s),\n"
2171                    "    NULL,\n"  # accumulator
2172                    "    NULL,\n"  # accu_data
2173                    "    g_cclosure_marshal_generic,\n"
2174                    "    G_TYPE_NONE,\n"
2175                    "    %d" % (s.name_hyphen, i.camel_name, s.name_lower, len(s.args))
2176                )
2177                for a in s.args:
2178                    self.outfile.write(", %s" % (a.gtype))
2179                self.outfile.write(");\n")
2180                self.outfile.write("\n")
2181
2182        if len(i.properties) > 0:
2183            self.outfile.write("  /* GObject properties for D-Bus properties: */\n")
2184            for p in i.properties:
2185                if p.readable and p.writable:
2186                    hint = "Since the D-Bus property for this #GObject property is both readable and writable, it is meaningful to both read from it and write to it on both the service- and client-side."
2187                elif p.readable:
2188                    hint = "Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side."
2189                elif p.writable:
2190                    hint = "Since the D-Bus property for this #GObject property is writable but not readable, it is meaningful to write to it on both the client- and service-side. It is only meaningful, however, to read from it on the service-side."
2191                else:
2192                    print_error(
2193                        'Cannot handle property "{}" that neither readable nor writable'.format(
2194                            p.name
2195                        )
2196                    )
2197                self.outfile.write(
2198                    self.docbook_gen.expand(
2199                        "  /**\n"
2200                        "   * %s:%s:\n"
2201                        "   *\n"
2202                        "   * Represents the D-Bus property #%s:%s.\n"
2203                        "   *\n"
2204                        "   * %s\n"
2205                        % (i.camel_name, p.name_hyphen, i.name, p.name, hint),
2206                        False,
2207                    )
2208                )
2209                self.write_gtkdoc_deprecated_and_since_and_close(p, self.outfile, 2)
2210                self.outfile.write("  g_object_interface_install_property (iface,\n")
2211                if p.arg.gtype == "G_TYPE_VARIANT":
2212                    s = (
2213                        'g_param_spec_variant ("%s", "%s", "%s", G_VARIANT_TYPE ("%s"), NULL'
2214                        % (p.name_hyphen, p.name, p.name, p.arg.signature)
2215                    )
2216                elif p.arg.signature == "b":
2217                    s = 'g_param_spec_boolean ("%s", "%s", "%s", FALSE' % (
2218                        p.name_hyphen,
2219                        p.name,
2220                        p.name,
2221                    )
2222                elif p.arg.signature == "y":
2223                    s = 'g_param_spec_uchar ("%s", "%s", "%s", 0, 255, 0' % (
2224                        p.name_hyphen,
2225                        p.name,
2226                        p.name,
2227                    )
2228                elif p.arg.signature == "n":
2229                    s = (
2230                        'g_param_spec_int ("%s", "%s", "%s", G_MININT16, G_MAXINT16, 0'
2231                        % (p.name_hyphen, p.name, p.name)
2232                    )
2233                elif p.arg.signature == "q":
2234                    s = 'g_param_spec_uint ("%s", "%s", "%s", 0, G_MAXUINT16, 0' % (
2235                        p.name_hyphen,
2236                        p.name,
2237                        p.name,
2238                    )
2239                elif p.arg.signature == "i":
2240                    s = (
2241                        'g_param_spec_int ("%s", "%s", "%s", G_MININT32, G_MAXINT32, 0'
2242                        % (p.name_hyphen, p.name, p.name)
2243                    )
2244                elif p.arg.signature == "u":
2245                    s = 'g_param_spec_uint ("%s", "%s", "%s", 0, G_MAXUINT32, 0' % (
2246                        p.name_hyphen,
2247                        p.name,
2248                        p.name,
2249                    )
2250                elif p.arg.signature == "x":
2251                    s = (
2252                        'g_param_spec_int64 ("%s", "%s", "%s", G_MININT64, G_MAXINT64, 0'
2253                        % (p.name_hyphen, p.name, p.name)
2254                    )
2255                elif p.arg.signature == "t":
2256                    s = 'g_param_spec_uint64 ("%s", "%s", "%s", 0, G_MAXUINT64, 0' % (
2257                        p.name_hyphen,
2258                        p.name,
2259                        p.name,
2260                    )
2261                elif p.arg.signature == "d":
2262                    s = (
2263                        'g_param_spec_double ("%s", "%s", "%s", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0'
2264                        % (p.name_hyphen, p.name, p.name)
2265                    )
2266                elif p.arg.signature == "s":
2267                    s = 'g_param_spec_string ("%s", "%s", "%s", NULL' % (
2268                        p.name_hyphen,
2269                        p.name,
2270                        p.name,
2271                    )
2272                elif p.arg.signature == "o":
2273                    s = 'g_param_spec_string ("%s", "%s", "%s", NULL' % (
2274                        p.name_hyphen,
2275                        p.name,
2276                        p.name,
2277                    )
2278                elif p.arg.signature == "g":
2279                    s = 'g_param_spec_string ("%s", "%s", "%s", NULL' % (
2280                        p.name_hyphen,
2281                        p.name,
2282                        p.name,
2283                    )
2284                elif p.arg.signature == "ay":
2285                    s = 'g_param_spec_string ("%s", "%s", "%s", NULL' % (
2286                        p.name_hyphen,
2287                        p.name,
2288                        p.name,
2289                    )
2290                elif p.arg.signature == "as":
2291                    s = 'g_param_spec_boxed ("%s", "%s", "%s", G_TYPE_STRV' % (
2292                        p.name_hyphen,
2293                        p.name,
2294                        p.name,
2295                    )
2296                elif p.arg.signature == "ao":
2297                    s = 'g_param_spec_boxed ("%s", "%s", "%s", G_TYPE_STRV' % (
2298                        p.name_hyphen,
2299                        p.name,
2300                        p.name,
2301                    )
2302                elif p.arg.signature == "aay":
2303                    s = 'g_param_spec_boxed ("%s", "%s", "%s", G_TYPE_STRV' % (
2304                        p.name_hyphen,
2305                        p.name,
2306                        p.name,
2307                    )
2308                else:
2309                    print_error(
2310                        'Unsupported gtype "{}" for GParamSpec'.format(p.arg.gtype)
2311                    )
2312                flags = "G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS"
2313                if p.deprecated:
2314                    flags = "G_PARAM_DEPRECATED | " + flags
2315                self.outfile.write("    %s, %s));" % (s, flags))
2316                self.outfile.write("\n")
2317
2318        self.outfile.write("}\n" "\n")
2319
2320    # ----------------------------------------------------------------------------------------------------
2321
2322    def generate_property_accessors(self, i):
2323        for p in i.properties:
2324            # getter
2325            if p.readable and p.writable:
2326                hint = "Since this D-Bus property is both readable and writable, it is meaningful to use this function on both the client- and service-side."
2327            elif p.readable:
2328                hint = "Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side."
2329            elif p.writable:
2330                hint = "Since this D-Bus property is not readable, it is only meaningful to use this function on the service-side."
2331            else:
2332                print_error(
2333                    'Cannot handle property "{}" that neither readable nor writable'.format(
2334                        p.name
2335                    )
2336                )
2337            self.outfile.write(
2338                self.docbook_gen.expand(
2339                    "/**\n"
2340                    " * %s_get_%s: (skip)\n"
2341                    " * @object: A #%s.\n"
2342                    " *\n"
2343                    " * Gets the value of the #%s:%s D-Bus property.\n"
2344                    " *\n"
2345                    " * %s\n"
2346                    " *\n"
2347                    % (i.name_lower, p.name_lower, i.camel_name, i.name, p.name, hint),
2348                    False,
2349                )
2350            )
2351            if p.arg.free_func is not None:
2352                self.outfile.write(
2353                    " * The returned value is only valid until the property changes so on the client-side it is only safe to use this function on the thread where @object was constructed. Use %s_dup_%s() if on another thread.\n"
2354                    " *\n"
2355                    " * Returns: (transfer none) (nullable): The property value or %%NULL if the property is not set. Do not free the returned value, it belongs to @object.\n"
2356                    % (i.name_lower, p.name_lower)
2357                )
2358            else:
2359                self.outfile.write(" * Returns: The property value.\n")
2360            self.write_gtkdoc_deprecated_and_since_and_close(p, self.outfile, 0)
2361            self.outfile.write(
2362                "%s\n"
2363                "%s_get_%s (%s *object)\n"
2364                "{\n" % (p.arg.ctype_in, i.name_lower, p.name_lower, i.camel_name)
2365            )
2366            self.outfile.write(
2367                "  return %s%s_GET_IFACE (object)->get_%s (object);\n"
2368                % (i.ns_upper, i.name_upper, p.name_lower)
2369            )
2370            self.outfile.write("}\n")
2371            self.outfile.write("\n")
2372            if p.arg.free_func is not None:
2373
2374                self.outfile.write(
2375                    self.docbook_gen.expand(
2376                        "/**\n"
2377                        " * %s_dup_%s: (skip)\n"
2378                        " * @object: A #%s.\n"
2379                        " *\n"
2380                        " * Gets a copy of the #%s:%s D-Bus property.\n"
2381                        " *\n"
2382                        " * %s\n"
2383                        " *\n"
2384                        " * Returns: (transfer full) (nullable): The property value or %%NULL if the property is not set. The returned value should be freed with %s().\n"
2385                        % (
2386                            i.name_lower,
2387                            p.name_lower,
2388                            i.camel_name,
2389                            i.name,
2390                            p.name,
2391                            hint,
2392                            p.arg.free_func,
2393                        ),
2394                        False,
2395                    )
2396                )
2397                self.write_gtkdoc_deprecated_and_since_and_close(p, self.outfile, 0)
2398                self.outfile.write(
2399                    "%s\n"
2400                    "%s_dup_%s (%s *object)\n"
2401                    "{\n"
2402                    "  %svalue;\n"
2403                    % (
2404                        p.arg.ctype_in_dup,
2405                        i.name_lower,
2406                        p.name_lower,
2407                        i.camel_name,
2408                        p.arg.ctype_in_dup,
2409                    )
2410                )
2411                self.outfile.write(
2412                    '  g_object_get (G_OBJECT (object), "%s", &value, NULL);\n'
2413                    % (p.name_hyphen)
2414                )
2415                self.outfile.write("  return value;\n")
2416                self.outfile.write("}\n")
2417                self.outfile.write("\n")
2418
2419            # setter
2420            if p.readable and p.writable:
2421                hint = "Since this D-Bus property is both readable and writable, it is meaningful to use this function on both the client- and service-side."
2422            elif p.readable:
2423                hint = "Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side."
2424            elif p.writable:
2425                hint = "Since this D-Bus property is writable, it is meaningful to use this function on both the client- and service-side."
2426            else:
2427                print_error(
2428                    'Cannot handle property "{}" that neither readable nor writable'.format(
2429                        p.name
2430                    )
2431                )
2432            self.outfile.write(
2433                self.docbook_gen.expand(
2434                    "/**\n"
2435                    " * %s_set_%s: (skip)\n"
2436                    " * @object: A #%s.\n"
2437                    " * @value: The value to set.\n"
2438                    " *\n"
2439                    " * Sets the #%s:%s D-Bus property to @value.\n"
2440                    " *\n"
2441                    " * %s\n"
2442                    % (i.name_lower, p.name_lower, i.camel_name, i.name, p.name, hint),
2443                    False,
2444                )
2445            )
2446            self.write_gtkdoc_deprecated_and_since_and_close(p, self.outfile, 0)
2447            self.outfile.write(
2448                "void\n"
2449                "%s_set_%s (%s *object, %svalue)\n"
2450                "{\n" % (i.name_lower, p.name_lower, i.camel_name, p.arg.ctype_in)
2451            )
2452            self.outfile.write(
2453                '  g_object_set (G_OBJECT (object), "%s", value, NULL);\n'
2454                % (p.name_hyphen)
2455            )
2456            self.outfile.write("}\n")
2457            self.outfile.write("\n")
2458
2459    # ---------------------------------------------------------------------------------------------------
2460
2461    def generate_signal_emitters(self, i):
2462        for s in i.signals:
2463            self.outfile.write(
2464                self.docbook_gen.expand(
2465                    "/**\n"
2466                    " * %s_emit_%s:\n"
2467                    " * @object: A #%s.\n" % (i.name_lower, s.name_lower, i.camel_name),
2468                    False,
2469                )
2470            )
2471            for a in s.args:
2472                self.outfile.write(
2473                    " * @arg_%s: Argument to pass with the signal.\n" % (a.name)
2474                )
2475            self.outfile.write(
2476                self.docbook_gen.expand(
2477                    " *\n" " * Emits the #%s::%s D-Bus signal.\n" % (i.name, s.name),
2478                    False,
2479                )
2480            )
2481            self.write_gtkdoc_deprecated_and_since_and_close(s, self.outfile, 0)
2482            self.outfile.write(
2483                "void\n"
2484                "%s_emit_%s (\n"
2485                "    %s *object" % (i.name_lower, s.name_lower, i.camel_name)
2486            )
2487            for a in s.args:
2488                self.outfile.write(",\n    %sarg_%s" % (a.ctype_in, a.name))
2489            self.outfile.write(
2490                ")\n" "{\n" '  g_signal_emit_by_name (object, "%s"' % (s.name_hyphen)
2491            )
2492            for a in s.args:
2493                self.outfile.write(", arg_%s" % a.name)
2494            self.outfile.write(");\n")
2495            self.outfile.write("}\n" "\n")
2496
2497    # ---------------------------------------------------------------------------------------------------
2498
2499    def generate_method_calls(self, i):
2500        for m in i.methods:
2501            # async begin
2502            self.outfile.write(
2503                "/**\n"
2504                " * %s_call_%s:\n"
2505                " * @proxy: A #%sProxy.\n" % (i.name_lower, m.name_lower, i.camel_name)
2506            )
2507            for a in m.in_args:
2508                self.outfile.write(
2509                    " * @arg_%s: Argument to pass with the method invocation.\n"
2510                    % (a.name)
2511                )
2512            if self.glib_min_required >= (2, 64):
2513                self.outfile.write(
2514                    " * @call_flags: Flags from the #GDBusCallFlags enumeration. If you want to allow interactive\n"
2515                    "       authorization be sure to set %G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION.\n"
2516                    ' * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning "infinite") or\n'
2517                    "       -1 to use the proxy default timeout.\n"
2518                )
2519            if m.unix_fd:
2520                self.outfile.write(
2521                    " * @fd_list: (nullable): A #GUnixFDList or %NULL.\n"
2522                )
2523            self.outfile.write(
2524                self.docbook_gen.expand(
2525                    " * @cancellable: (nullable): A #GCancellable or %%NULL.\n"
2526                    " * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %%NULL.\n"
2527                    " * @user_data: User data to pass to @callback.\n"
2528                    " *\n"
2529                    " * Asynchronously invokes the %s.%s() D-Bus method on @proxy.\n"
2530                    " * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).\n"
2531                    " * You can then call %s_call_%s_finish() to get the result of the operation.\n"
2532                    " *\n"
2533                    " * See %s_call_%s_sync() for the synchronous, blocking version of this method.\n"
2534                    % (
2535                        i.name,
2536                        m.name,
2537                        i.name_lower,
2538                        m.name_lower,
2539                        i.name_lower,
2540                        m.name_lower,
2541                    ),
2542                    False,
2543                )
2544            )
2545            self.write_gtkdoc_deprecated_and_since_and_close(m, self.outfile, 0)
2546            self.outfile.write(
2547                "void\n"
2548                "%s_call_%s (\n"
2549                "    %s *proxy" % (i.name_lower, m.name_lower, i.camel_name)
2550            )
2551            for a in m.in_args:
2552                self.outfile.write(",\n    %sarg_%s" % (a.ctype_in, a.name))
2553            if self.glib_min_required >= (2, 64):
2554                self.outfile.write(
2555                    ",\n    GDBusCallFlags call_flags" ",\n    gint timeout_msec"
2556                )
2557            if m.unix_fd:
2558                self.outfile.write(",\n    GUnixFDList *fd_list")
2559            self.outfile.write(
2560                ",\n"
2561                "    GCancellable *cancellable,\n"
2562                "    GAsyncReadyCallback callback,\n"
2563                "    gpointer user_data)\n"
2564                "{\n"
2565            )
2566            if m.unix_fd:
2567                self.outfile.write(
2568                    "  g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy),\n"
2569                )
2570            else:
2571                self.outfile.write("  g_dbus_proxy_call (G_DBUS_PROXY (proxy),\n")
2572            self.outfile.write('    "%s",\n' '    g_variant_new ("(' % (m.name))
2573            for a in m.in_args:
2574                self.outfile.write("%s" % (a.format_in))
2575            self.outfile.write(')"')
2576            for a in m.in_args:
2577                self.outfile.write(",\n                   arg_%s" % (a.name))
2578            self.outfile.write("),\n")
2579            if self.glib_min_required >= (2, 64):
2580                self.outfile.write("    call_flags,\n" "    timeout_msec,\n")
2581            else:
2582                self.outfile.write("    G_DBUS_CALL_FLAGS_NONE,\n" "    -1,\n")
2583            if m.unix_fd:
2584                self.outfile.write("    fd_list,\n")
2585            self.outfile.write(
2586                "    cancellable,\n" "    callback,\n" "    user_data);\n"
2587            )
2588            self.outfile.write("}\n" "\n")
2589            # async finish
2590            self.outfile.write(
2591                "/**\n"
2592                " * %s_call_%s_finish:\n"
2593                " * @proxy: A #%sProxy.\n" % (i.name_lower, m.name_lower, i.camel_name)
2594            )
2595            for a in m.out_args:
2596                self.outfile.write(
2597                    " * @out_%s: (out) (optional)%s: Return location for return parameter or %%NULL to ignore.\n"
2598                    % (a.name, " " + a.array_annotation if a.array_annotation else "")
2599                )
2600            if m.unix_fd:
2601                self.outfile.write(
2602                    " * @out_fd_list: (out) (optional): Return location for a #GUnixFDList or %NULL to ignore.\n"
2603                )
2604            self.outfile.write(
2605                self.docbook_gen.expand(
2606                    " * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %s_call_%s().\n"
2607                    " * @error: Return location for error or %%NULL.\n"
2608                    " *\n"
2609                    " * Finishes an operation started with %s_call_%s().\n"
2610                    " *\n"
2611                    " * Returns: (skip): %%TRUE if the call succeeded, %%FALSE if @error is set.\n"
2612                    % (i.name_lower, m.name_lower, i.name_lower, m.name_lower),
2613                    False,
2614                )
2615            )
2616            self.write_gtkdoc_deprecated_and_since_and_close(m, self.outfile, 0)
2617            self.outfile.write(
2618                "gboolean\n"
2619                "%s_call_%s_finish (\n"
2620                "    %s *proxy" % (i.name_lower, m.name_lower, i.camel_name)
2621            )
2622            for a in m.out_args:
2623                self.outfile.write(",\n    %sout_%s" % (a.ctype_out, a.name))
2624            if m.unix_fd:
2625                self.outfile.write(",\n    GUnixFDList **out_fd_list")
2626            self.outfile.write(
2627                ",\n"
2628                "    GAsyncResult *res,\n"
2629                "    GError **error)\n"
2630                "{\n"
2631                "  GVariant *_ret;\n"
2632            )
2633            if m.unix_fd:
2634                self.outfile.write(
2635                    "  _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error);\n"
2636                )
2637            else:
2638                self.outfile.write(
2639                    "  _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);\n"
2640                )
2641            self.outfile.write("  if (_ret == NULL)\n" "    goto _out;\n")
2642            self.outfile.write("  g_variant_get (_ret,\n" '                 "(')
2643            for a in m.out_args:
2644                self.outfile.write("%s" % (a.format_out))
2645            self.outfile.write(')"')
2646            for a in m.out_args:
2647                self.outfile.write(",\n                 out_%s" % (a.name))
2648            self.outfile.write(");\n" "  g_variant_unref (_ret);\n")
2649            self.outfile.write("_out:\n" "  return _ret != NULL;\n" "}\n" "\n")
2650
2651            # sync
2652            self.outfile.write(
2653                "/**\n"
2654                " * %s_call_%s_sync:\n"
2655                " * @proxy: A #%sProxy.\n" % (i.name_lower, m.name_lower, i.camel_name)
2656            )
2657            for a in m.in_args:
2658                self.outfile.write(
2659                    " * @arg_%s: Argument to pass with the method invocation.\n"
2660                    % (a.name)
2661                )
2662            if self.glib_min_required >= (2, 64):
2663                self.outfile.write(
2664                    " * @call_flags: Flags from the #GDBusCallFlags enumeration. If you want to allow interactive\n"
2665                    "       authorization be sure to set %G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION.\n"
2666                    ' * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning "infinite") or\n'
2667                    "       -1 to use the proxy default timeout.\n"
2668                )
2669            if m.unix_fd:
2670                self.outfile.write(
2671                    " * @fd_list: (nullable): A #GUnixFDList or %NULL.\n"
2672                )
2673            for a in m.out_args:
2674                self.outfile.write(
2675                    " * @out_%s: (out) (optional)%s: Return location for return parameter or %%NULL to ignore.\n"
2676                    % (a.name, " " + a.array_annotation if a.array_annotation else "")
2677                )
2678            if m.unix_fd:
2679                self.outfile.write(
2680                    " * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL.\n"
2681                )
2682            self.outfile.write(
2683                self.docbook_gen.expand(
2684                    " * @cancellable: (nullable): A #GCancellable or %%NULL.\n"
2685                    " * @error: Return location for error or %%NULL.\n"
2686                    " *\n"
2687                    " * Synchronously invokes the %s.%s() D-Bus method on @proxy. The calling thread is blocked until a reply is received.\n"
2688                    " *\n"
2689                    " * See %s_call_%s() for the asynchronous version of this method.\n"
2690                    " *\n"
2691                    " * Returns: (skip): %%TRUE if the call succeeded, %%FALSE if @error is set.\n"
2692                    % (i.name, m.name, i.name_lower, m.name_lower),
2693                    False,
2694                )
2695            )
2696            self.write_gtkdoc_deprecated_and_since_and_close(m, self.outfile, 0)
2697            self.outfile.write(
2698                "gboolean\n"
2699                "%s_call_%s_sync (\n"
2700                "    %s *proxy" % (i.name_lower, m.name_lower, i.camel_name)
2701            )
2702            for a in m.in_args:
2703                self.outfile.write(",\n    %sarg_%s" % (a.ctype_in, a.name))
2704            if self.glib_min_required >= (2, 64):
2705                self.outfile.write(
2706                    ",\n    GDBusCallFlags call_flags" ",\n    gint timeout_msec"
2707                )
2708            if m.unix_fd:
2709                self.outfile.write(",\n    GUnixFDList  *fd_list")
2710            for a in m.out_args:
2711                self.outfile.write(",\n    %sout_%s" % (a.ctype_out, a.name))
2712            if m.unix_fd:
2713                self.outfile.write(",\n    GUnixFDList **out_fd_list")
2714            self.outfile.write(
2715                ",\n"
2716                "    GCancellable *cancellable,\n"
2717                "    GError **error)\n"
2718                "{\n"
2719                "  GVariant *_ret;\n"
2720            )
2721            if m.unix_fd:
2722                self.outfile.write(
2723                    "  _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy),\n"
2724                )
2725            else:
2726                self.outfile.write(
2727                    "  _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),\n"
2728                )
2729            self.outfile.write('    "%s",\n' '    g_variant_new ("(' % (m.name))
2730            for a in m.in_args:
2731                self.outfile.write("%s" % (a.format_in))
2732            self.outfile.write(')"')
2733            for a in m.in_args:
2734                self.outfile.write(",\n                   arg_%s" % (a.name))
2735            self.outfile.write("),\n")
2736            if self.glib_min_required >= (2, 64):
2737                self.outfile.write("    call_flags,\n" "    timeout_msec,\n")
2738            else:
2739                self.outfile.write("    G_DBUS_CALL_FLAGS_NONE,\n" "    -1,\n")
2740            if m.unix_fd:
2741                self.outfile.write("    fd_list,\n" "    out_fd_list,\n")
2742            self.outfile.write(
2743                "    cancellable,\n"
2744                "    error);\n"
2745                "  if (_ret == NULL)\n"
2746                "    goto _out;\n"
2747            )
2748            self.outfile.write("  g_variant_get (_ret,\n" '                 "(')
2749            for a in m.out_args:
2750                self.outfile.write("%s" % (a.format_out))
2751            self.outfile.write(')"')
2752            for a in m.out_args:
2753                self.outfile.write(",\n                 out_%s" % (a.name))
2754            self.outfile.write(");\n" "  g_variant_unref (_ret);\n")
2755            self.outfile.write("_out:\n" "  return _ret != NULL;\n" "}\n" "\n")
2756
2757    # ---------------------------------------------------------------------------------------------------
2758
2759    def generate_method_completers(self, i):
2760        for m in i.methods:
2761            self.outfile.write(
2762                "/**\n"
2763                " * %s_complete_%s:\n"
2764                " * @object: A #%s.\n"
2765                " * @invocation: (transfer full): A #GDBusMethodInvocation.\n"
2766                % (i.name_lower, m.name_lower, i.camel_name)
2767            )
2768            if m.unix_fd:
2769                self.outfile.write(
2770                    " * @fd_list: (nullable): A #GUnixFDList or %NULL.\n"
2771                )
2772            for a in m.out_args:
2773                self.outfile.write(" * @%s: Parameter to return.\n" % (a.name))
2774            self.outfile.write(
2775                self.docbook_gen.expand(
2776                    " *\n"
2777                    " * Helper function used in service implementations to finish handling invocations of the %s.%s() D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.\n"
2778                    " *\n"
2779                    " * This method will free @invocation, you cannot use it afterwards.\n"
2780                    % (i.name, m.name),
2781                    False,
2782                )
2783            )
2784            self.write_gtkdoc_deprecated_and_since_and_close(m, self.outfile, 0)
2785            self.outfile.write(
2786                "void\n"
2787                "%s_complete_%s (\n"
2788                "    %s *object G_GNUC_UNUSED,\n"
2789                "    GDBusMethodInvocation *invocation"
2790                % (i.name_lower, m.name_lower, i.camel_name)
2791            )
2792            if m.unix_fd:
2793                self.outfile.write(",\n    GUnixFDList *fd_list")
2794            for a in m.out_args:
2795                self.outfile.write(",\n    %s%s" % (a.ctype_in, a.name))
2796            self.outfile.write(")\n" "{\n")
2797
2798            if m.unix_fd:
2799                self.outfile.write(
2800                    "  g_dbus_method_invocation_return_value_with_unix_fd_list (invocation,\n"
2801                    '    g_variant_new ("('
2802                )
2803            else:
2804                self.outfile.write(
2805                    "  g_dbus_method_invocation_return_value (invocation,\n"
2806                    '    g_variant_new ("('
2807                )
2808            for a in m.out_args:
2809                self.outfile.write("%s" % (a.format_in))
2810            self.outfile.write(')"')
2811            for a in m.out_args:
2812                self.outfile.write(",\n                   %s" % (a.name))
2813            if m.unix_fd:
2814                self.outfile.write("),\n    fd_list);\n")
2815            else:
2816                self.outfile.write("));\n")
2817            self.outfile.write("}\n" "\n")
2818
2819    # ---------------------------------------------------------------------------------------------------
2820
2821    def generate_proxy(self, i):
2822        # class boilerplate
2823        self.outfile.write(
2824            "/* ------------------------------------------------------------------------ */\n"
2825            "\n"
2826        )
2827
2828        self.outfile.write(
2829            self.docbook_gen.expand(
2830                "/**\n"
2831                " * %sProxy:\n"
2832                " *\n"
2833                " * The #%sProxy structure contains only private data and should only be accessed using the provided API.\n"
2834                % (i.camel_name, i.camel_name),
2835                False,
2836            )
2837        )
2838        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
2839        self.outfile.write("\n")
2840
2841        self.outfile.write(
2842            self.docbook_gen.expand(
2843                "/**\n"
2844                " * %sProxyClass:\n"
2845                " * @parent_class: The parent class.\n"
2846                " *\n"
2847                " * Class structure for #%sProxy.\n" % (i.camel_name, i.camel_name),
2848                False,
2849            )
2850        )
2851        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
2852        self.outfile.write("\n")
2853
2854        self.outfile.write(
2855            "struct _%sProxyPrivate\n"
2856            "{\n"
2857            "  GData *qdata;\n"
2858            "};\n"
2859            "\n" % i.camel_name
2860        )
2861
2862        self.outfile.write(
2863            "static void %s_proxy_iface_init (%sIface *iface);\n"
2864            "\n" % (i.name_lower, i.camel_name)
2865        )
2866        self.outfile.write("#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38\n")
2867        self.outfile.write(
2868            "G_DEFINE_TYPE_WITH_CODE (%sProxy, %s_proxy, G_TYPE_DBUS_PROXY,\n"
2869            % (i.camel_name, i.name_lower)
2870        )
2871        self.outfile.write(
2872            "                         G_ADD_PRIVATE (%sProxy)\n" % (i.camel_name)
2873        )
2874        self.outfile.write(
2875            "                         G_IMPLEMENT_INTERFACE (%sTYPE_%s, %s_proxy_iface_init))\n\n"
2876            % (i.ns_upper, i.name_upper, i.name_lower)
2877        )
2878        self.outfile.write("#else\n")
2879        self.outfile.write(
2880            "G_DEFINE_TYPE_WITH_CODE (%sProxy, %s_proxy, G_TYPE_DBUS_PROXY,\n"
2881            % (i.camel_name, i.name_lower)
2882        )
2883        self.outfile.write(
2884            "                         G_IMPLEMENT_INTERFACE (%sTYPE_%s, %s_proxy_iface_init))\n\n"
2885            % (i.ns_upper, i.name_upper, i.name_lower)
2886        )
2887        self.outfile.write("#endif\n")
2888
2889        # finalize
2890        self.outfile.write(
2891            "static void\n"
2892            "%s_proxy_finalize (GObject *object)\n"
2893            "{\n" % (i.name_lower)
2894        )
2895        self.outfile.write(
2896            "  %sProxy *proxy = %s%s_PROXY (object);\n"
2897            % (i.camel_name, i.ns_upper, i.name_upper)
2898        )
2899        self.outfile.write("  g_datalist_clear (&proxy->priv->qdata);\n")
2900        self.outfile.write(
2901            "  G_OBJECT_CLASS (%s_proxy_parent_class)->finalize (object);\n"
2902            "}\n"
2903            "\n" % (i.name_lower)
2904        )
2905
2906        # property accessors
2907        #
2908        # Note that we are guaranteed that prop_id starts at 1 and is
2909        # laid out in the same order as introspection data pointers
2910        #
2911        self.outfile.write(
2912            "static void\n"
2913            "%s_proxy_get_property (GObject      *object" % (i.name_lower)
2914        )
2915        if len(i.properties) == 0:
2916            self.outfile.write(
2917                " G_GNUC_UNUSED,\n"
2918                "  guint         prop_id G_GNUC_UNUSED,\n"
2919                "  GValue       *value G_GNUC_UNUSED,\n"
2920            )
2921        else:
2922            self.outfile.write(
2923                ",\n" "  guint         prop_id,\n" "  GValue       *value,\n"
2924            )
2925        self.outfile.write("  GParamSpec   *pspec G_GNUC_UNUSED)\n" "{\n")
2926        if len(i.properties) > 0:
2927            self.outfile.write(
2928                "  const _ExtendedGDBusPropertyInfo *info;\n"
2929                "  GVariant *variant;\n"
2930                "  g_assert (prop_id != 0 && prop_id - 1 < %d);\n"
2931                "  info = (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1];\n"
2932                "  variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name);\n"
2933                "  if (info->use_gvariant)\n"
2934                "    {\n"
2935                "      g_value_set_variant (value, variant);\n"
2936                "    }\n"
2937                "  else\n"
2938                "    {\n"
2939                # could be that we don't have the value in cache - in that case, we do
2940                # nothing and the user gets the default value for the GType
2941                "      if (variant != NULL)\n"
2942                "        g_dbus_gvariant_to_gvalue (variant, value);\n"
2943                "    }\n"
2944                "  if (variant != NULL)\n"
2945                "    g_variant_unref (variant);\n" % (len(i.properties), i.name_lower)
2946            )
2947        self.outfile.write("}\n" "\n")
2948        if len(i.properties) > 0:
2949            self.outfile.write(
2950                "static void\n"
2951                "%s_proxy_set_property_cb (GDBusProxy *proxy,\n"
2952                "  GAsyncResult *res,\n"
2953                "  gpointer      user_data)\n"
2954                "{\n" % (i.name_lower)
2955            )
2956            self.outfile.write(
2957                "  const _ExtendedGDBusPropertyInfo *info = user_data;\n"
2958                "  GError *error;\n"
2959                "  GVariant *_ret;\n"
2960                "  error = NULL;\n"
2961                "  _ret = g_dbus_proxy_call_finish (proxy, res, &error);\n"
2962                "  if (!_ret)\n"
2963                "    {\n"
2964                "      g_warning (\"Error setting property '%%s' on interface %s: %%s (%%s, %%d)\",\n"
2965                "                 info->parent_struct.name, \n"
2966                "                 error->message, g_quark_to_string (error->domain), error->code);\n"
2967                "      g_error_free (error);\n"
2968                "    }\n"
2969                "  else\n"
2970                "    {\n"
2971                "      g_variant_unref (_ret);\n"
2972                "    }\n" % (i.name)
2973            )
2974            self.outfile.write("}\n" "\n")
2975        self.outfile.write("static void\n" "%s_proxy_set_property (" % (i.name_lower))
2976        if len(i.properties) == 0:
2977            self.outfile.write(
2978                "GObject      *object G_GNUC_UNUSED,\n"
2979                "  guint         prop_id G_GNUC_UNUSED,\n"
2980                "  const GValue *value G_GNUC_UNUSED,\n"
2981            )
2982        else:
2983            self.outfile.write(
2984                "GObject      *object,\n"
2985                "  guint         prop_id,\n"
2986                "  const GValue *value,\n"
2987            )
2988        self.outfile.write("  GParamSpec   *pspec G_GNUC_UNUSED)\n" "{\n")
2989        if len(i.properties) > 0:
2990            self.outfile.write(
2991                "  const _ExtendedGDBusPropertyInfo *info;\n"
2992                "  GVariant *variant;\n"
2993                "  g_assert (prop_id != 0 && prop_id - 1 < %d);\n"
2994                "  info = (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1];\n"
2995                "  variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature));\n"
2996                "  g_dbus_proxy_call (G_DBUS_PROXY (object),\n"
2997                '    "org.freedesktop.DBus.Properties.Set",\n'
2998                '    g_variant_new ("(ssv)", "%s", info->parent_struct.name, variant),\n'
2999                "    G_DBUS_CALL_FLAGS_NONE,\n"
3000                "    -1,\n"
3001                "    NULL, (GAsyncReadyCallback) %s_proxy_set_property_cb, (GDBusPropertyInfo *) &info->parent_struct);\n"
3002                "  g_variant_unref (variant);\n"
3003                % (len(i.properties), i.name_lower, i.name, i.name_lower)
3004            )
3005        self.outfile.write("}\n" "\n")
3006
3007        # signal received
3008        self.outfile.write(
3009            "static void\n"
3010            "%s_proxy_g_signal (GDBusProxy *proxy,\n"
3011            "  const gchar *sender_name G_GNUC_UNUSED,\n"
3012            "  const gchar *signal_name,\n"
3013            "  GVariant *parameters)\n"
3014            "{\n" % (i.name_lower)
3015        )
3016        self.outfile.write(
3017            "  _ExtendedGDBusSignalInfo *info;\n"
3018            "  GVariantIter iter;\n"
3019            "  GVariant *child;\n"
3020            "  GValue *paramv;\n"
3021            "  gsize num_params;\n"
3022            "  gsize n;\n"
3023            "  guint signal_id;\n"
3024        )
3025        # Note: info could be NULL if we are talking to a newer version of the interface
3026        self.outfile.write(
3027            "  info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, signal_name);\n"
3028            "  if (info == NULL)\n"
3029            "    return;\n" % (i.name_lower)
3030        )
3031        self.outfile.write(
3032            "  num_params = g_variant_n_children (parameters);\n"
3033            "  paramv = g_new0 (GValue, num_params + 1);\n"
3034            "  g_value_init (&paramv[0], %sTYPE_%s);\n"
3035            "  g_value_set_object (&paramv[0], proxy);\n" % (i.ns_upper, i.name_upper)
3036        )
3037        self.outfile.write(
3038            "  g_variant_iter_init (&iter, parameters);\n"
3039            "  n = 1;\n"
3040            "  while ((child = g_variant_iter_next_value (&iter)) != NULL)\n"
3041            "    {\n"
3042            "      _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1];\n"
3043            "      if (arg_info->use_gvariant)\n"
3044            "        {\n"
3045            "          g_value_init (&paramv[n], G_TYPE_VARIANT);\n"
3046            "          g_value_set_variant (&paramv[n], child);\n"
3047            "          n++;\n"
3048            "        }\n"
3049            "      else\n"
3050            "        g_dbus_gvariant_to_gvalue (child, &paramv[n++]);\n"
3051            "      g_variant_unref (child);\n"
3052            "    }\n"
3053        )
3054        self.outfile.write(
3055            "  signal_id = g_signal_lookup (info->signal_name, %sTYPE_%s);\n"
3056            % (i.ns_upper, i.name_upper)
3057        )
3058        self.outfile.write("  g_signal_emitv (paramv, signal_id, 0, NULL);\n")
3059        self.outfile.write(
3060            "  for (n = 0; n < num_params + 1; n++)\n"
3061            "    g_value_unset (&paramv[n]);\n"
3062            "  g_free (paramv);\n"
3063        )
3064        self.outfile.write("}\n" "\n")
3065
3066        # property changed
3067        self.outfile.write(
3068            "static void\n"
3069            "%s_proxy_g_properties_changed (GDBusProxy *_proxy,\n"
3070            "  GVariant *changed_properties,\n"
3071            "  const gchar *const *invalidated_properties)\n"
3072            "{\n" % (i.name_lower)
3073        )
3074        # Note: info could be NULL if we are talking to a newer version of the interface
3075        self.outfile.write(
3076            "  %sProxy *proxy = %s%s_PROXY (_proxy);\n"
3077            "  guint n;\n"
3078            "  const gchar *key;\n"
3079            "  GVariantIter *iter;\n"
3080            "  _ExtendedGDBusPropertyInfo *info;\n"
3081            '  g_variant_get (changed_properties, "a{sv}", &iter);\n'
3082            '  while (g_variant_iter_next (iter, "{&sv}", &key, NULL))\n'
3083            "    {\n"
3084            "      info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, key);\n"
3085            "      g_datalist_remove_data (&proxy->priv->qdata, key);\n"
3086            "      if (info != NULL)\n"
3087            "        g_object_notify (G_OBJECT (proxy), info->hyphen_name);\n"
3088            "    }\n"
3089            "  g_variant_iter_free (iter);\n"
3090            "  for (n = 0; invalidated_properties[n] != NULL; n++)\n"
3091            "    {\n"
3092            "      info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, invalidated_properties[n]);\n"
3093            "      g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]);\n"
3094            "      if (info != NULL)\n"
3095            "        g_object_notify (G_OBJECT (proxy), info->hyphen_name);\n"
3096            "    }\n"
3097            "}\n"
3098            "\n" % (i.camel_name, i.ns_upper, i.name_upper, i.name_lower, i.name_lower)
3099        )
3100
3101        # property vfuncs
3102        for p in i.properties:
3103            nul_value = "0"
3104            if p.arg.free_func is not None:
3105                nul_value = "NULL"
3106            self.outfile.write(
3107                "static %s\n"
3108                "%s_proxy_get_%s (%s *object)\n"
3109                "{\n"
3110                "  %sProxy *proxy = %s%s_PROXY (object);\n"
3111                "  GVariant *variant;\n"
3112                "  %svalue = %s;\n"
3113                % (
3114                    p.arg.ctype_in,
3115                    i.name_lower,
3116                    p.name_lower,
3117                    i.camel_name,
3118                    i.camel_name,
3119                    i.ns_upper,
3120                    i.name_upper,
3121                    p.arg.ctype_in,
3122                    nul_value,
3123                )
3124            )
3125            # For some property types, we have to free the returned
3126            # value (or part of it, e.g. the container) because of how
3127            # GVariant works.. see https://bugzilla.gnome.org/show_bug.cgi?id=657100
3128            # for details
3129            #
3130            free_container = False
3131            if (
3132                p.arg.gvariant_get == "g_variant_get_strv"
3133                or p.arg.gvariant_get == "g_variant_get_objv"
3134                or p.arg.gvariant_get == "g_variant_get_bytestring_array"
3135            ):
3136                free_container = True
3137            # If already using an old value for strv, objv, bytestring_array (see below),
3138            # then just return that... that way the result from multiple consecutive calls
3139            # to the getter are valid as long as they're freed
3140            #
3141            if free_container:
3142                self.outfile.write(
3143                    '  value = g_datalist_get_data (&proxy->priv->qdata, "%s");\n'
3144                    "  if (value != NULL)\n"
3145                    "    return value;\n" % (p.name)
3146                )
3147            self.outfile.write(
3148                '  variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "%s");\n'
3149                % (p.name)
3150            )
3151            if p.arg.gtype == "G_TYPE_VARIANT":
3152                self.outfile.write("  value = variant;\n")
3153                self.outfile.write("  if (variant != NULL)\n")
3154                self.outfile.write("    g_variant_unref (variant);\n")
3155            else:
3156                self.outfile.write("  if (variant != NULL)\n" "    {\n")
3157                extra_len = ""
3158                if (
3159                    p.arg.gvariant_get == "g_variant_get_string"
3160                    or p.arg.gvariant_get == "g_variant_get_strv"
3161                    or p.arg.gvariant_get == "g_variant_get_objv"
3162                    or p.arg.gvariant_get == "g_variant_get_bytestring_array"
3163                ):
3164                    extra_len = ", NULL"
3165                self.outfile.write(
3166                    "      value = %s (variant%s);\n" % (p.arg.gvariant_get, extra_len)
3167                )
3168                if free_container:
3169                    self.outfile.write(
3170                        '      g_datalist_set_data_full (&proxy->priv->qdata, "%s", (gpointer) value, g_free);\n'
3171                        % (p.name)
3172                    )
3173                self.outfile.write("      g_variant_unref (variant);\n")
3174                self.outfile.write("    }\n")
3175            self.outfile.write("  return value;\n")
3176            self.outfile.write("}\n")
3177            self.outfile.write("\n")
3178
3179        # class boilerplate
3180        self.outfile.write(
3181            "static void\n"
3182            "%s_proxy_init (%sProxy *proxy)\n"
3183            "{\n"
3184            "#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38\n"
3185            "  proxy->priv = %s_proxy_get_instance_private (proxy);\n"
3186            "#else\n"
3187            "  proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, %sTYPE_%s_PROXY, %sProxyPrivate);\n"
3188            "#endif\n\n"
3189            "  g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), %s_interface_info ());\n"
3190            "}\n"
3191            "\n"
3192            % (
3193                i.name_lower,
3194                i.camel_name,
3195                i.name_lower,
3196                i.ns_upper,
3197                i.name_upper,
3198                i.camel_name,
3199                i.name_lower,
3200            )
3201        )
3202        self.outfile.write(
3203            "static void\n"
3204            "%s_proxy_class_init (%sProxyClass *klass)\n"
3205            "{\n"
3206            "  GObjectClass *gobject_class;\n"
3207            "  GDBusProxyClass *proxy_class;\n"
3208            "\n"
3209            "  gobject_class = G_OBJECT_CLASS (klass);\n"
3210            "  gobject_class->finalize     = %s_proxy_finalize;\n"
3211            "  gobject_class->get_property = %s_proxy_get_property;\n"
3212            "  gobject_class->set_property = %s_proxy_set_property;\n"
3213            "\n"
3214            "  proxy_class = G_DBUS_PROXY_CLASS (klass);\n"
3215            "  proxy_class->g_signal = %s_proxy_g_signal;\n"
3216            "  proxy_class->g_properties_changed = %s_proxy_g_properties_changed;\n"
3217            "\n"
3218            % (
3219                i.name_lower,
3220                i.camel_name,
3221                i.name_lower,
3222                i.name_lower,
3223                i.name_lower,
3224                i.name_lower,
3225                i.name_lower,
3226            )
3227        )
3228        if len(i.properties) > 0:
3229            self.outfile.write(
3230                "  %s_override_properties (gobject_class, 1);\n\n" % (i.name_lower)
3231            )
3232        self.outfile.write(
3233            "#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38\n"
3234            "  g_type_class_add_private (klass, sizeof (%sProxyPrivate));\n"
3235            "#endif\n" % (i.camel_name)
3236        )
3237        self.outfile.write("}\n" "\n")
3238
3239        self.outfile.write(
3240            "static void\n"
3241            "%s_proxy_iface_init (%sIface *iface" % (i.name_lower, i.camel_name)
3242        )
3243        if len(i.properties) == 0:
3244            self.outfile.write(" G_GNUC_UNUSED)\n")
3245        else:
3246            self.outfile.write(")\n")
3247        self.outfile.write("{\n")
3248        for p in i.properties:
3249            self.outfile.write(
3250                "  iface->get_%s = %s_proxy_get_%s;\n"
3251                % (p.name_lower, i.name_lower, p.name_lower)
3252            )
3253        self.outfile.write("}\n" "\n")
3254
3255        # constructors
3256        self.outfile.write(
3257            self.docbook_gen.expand(
3258                "/**\n"
3259                " * %s_proxy_new:\n"
3260                " * @connection: A #GDBusConnection.\n"
3261                " * @flags: Flags from the #GDBusProxyFlags enumeration.\n"
3262                " * @name: (nullable): A bus name (well-known or unique) or %%NULL if @connection is not a message bus connection.\n"
3263                " * @object_path: An object path.\n"
3264                " * @cancellable: (nullable): A #GCancellable or %%NULL.\n"
3265                " * @callback: A #GAsyncReadyCallback to call when the request is satisfied.\n"
3266                " * @user_data: User data to pass to @callback.\n"
3267                " *\n"
3268                " * Asynchronously creates a proxy for the D-Bus interface #%s. See g_dbus_proxy_new() for more details.\n"
3269                " *\n"
3270                " * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).\n"
3271                " * You can then call %s_proxy_new_finish() to get the result of the operation.\n"
3272                " *\n"
3273                " * See %s_proxy_new_sync() for the synchronous, blocking version of this constructor.\n"
3274                % (i.name_lower, i.name, i.name_lower, i.name_lower),
3275                False,
3276            )
3277        )
3278        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
3279        self.outfile.write(
3280            "void\n"
3281            "%s_proxy_new (\n"
3282            "    GDBusConnection     *connection,\n"
3283            "    GDBusProxyFlags      flags,\n"
3284            "    const gchar         *name,\n"
3285            "    const gchar         *object_path,\n"
3286            "    GCancellable        *cancellable,\n"
3287            "    GAsyncReadyCallback  callback,\n"
3288            "    gpointer             user_data)\n"
3289            "{\n"
3290            '  g_async_initable_new_async (%sTYPE_%s_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "%s", NULL);\n'
3291            "}\n"
3292            "\n" % (i.name_lower, i.ns_upper, i.name_upper, i.name)
3293        )
3294        self.outfile.write(
3295            "/**\n"
3296            " * %s_proxy_new_finish:\n"
3297            " * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %s_proxy_new().\n"
3298            " * @error: Return location for error or %%NULL\n"
3299            " *\n"
3300            " * Finishes an operation started with %s_proxy_new().\n"
3301            " *\n"
3302            " * Returns: (transfer full) (type %sProxy): The constructed proxy object or %%NULL if @error is set.\n"
3303            % (i.name_lower, i.name_lower, i.name_lower, i.camel_name)
3304        )
3305        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
3306        self.outfile.write(
3307            "%s *\n"
3308            "%s_proxy_new_finish (\n"
3309            "    GAsyncResult        *res,\n"
3310            "    GError             **error)\n"
3311            "{\n"
3312            "  GObject *ret;\n"
3313            "  GObject *source_object;\n"
3314            "  source_object = g_async_result_get_source_object (res);\n"
3315            "  ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);\n"
3316            "  g_object_unref (source_object);\n"
3317            "  if (ret != NULL)\n"
3318            "    return %s%s (ret);\n"
3319            "  else\n"
3320            "    return NULL;\n"
3321            "}\n"
3322            "\n" % (i.camel_name, i.name_lower, i.ns_upper, i.name_upper)
3323        )
3324        self.outfile.write(
3325            self.docbook_gen.expand(
3326                "/**\n"
3327                " * %s_proxy_new_sync:\n"
3328                " * @connection: A #GDBusConnection.\n"
3329                " * @flags: Flags from the #GDBusProxyFlags enumeration.\n"
3330                " * @name: (nullable): A bus name (well-known or unique) or %%NULL if @connection is not a message bus connection.\n"
3331                " * @object_path: An object path.\n"
3332                " * @cancellable: (nullable): A #GCancellable or %%NULL.\n"
3333                " * @error: Return location for error or %%NULL\n"
3334                " *\n"
3335                " * Synchronously creates a proxy for the D-Bus interface #%s. See g_dbus_proxy_new_sync() for more details.\n"
3336                " *\n"
3337                " * The calling thread is blocked until a reply is received.\n"
3338                " *\n"
3339                " * See %s_proxy_new() for the asynchronous version of this constructor.\n"
3340                " *\n"
3341                " * Returns: (transfer full) (type %sProxy): The constructed proxy object or %%NULL if @error is set.\n"
3342                % (i.name_lower, i.name, i.name_lower, i.camel_name),
3343                False,
3344            )
3345        )
3346        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
3347        self.outfile.write(
3348            "%s *\n"
3349            "%s_proxy_new_sync (\n"
3350            "    GDBusConnection     *connection,\n"
3351            "    GDBusProxyFlags      flags,\n"
3352            "    const gchar         *name,\n"
3353            "    const gchar         *object_path,\n"
3354            "    GCancellable        *cancellable,\n"
3355            "    GError             **error)\n"
3356            "{\n"
3357            "  GInitable *ret;\n"
3358            '  ret = g_initable_new (%sTYPE_%s_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "%s", NULL);\n'
3359            "  if (ret != NULL)\n"
3360            "    return %s%s (ret);\n"
3361            "  else\n"
3362            "    return NULL;\n"
3363            "}\n"
3364            "\n"
3365            % (
3366                i.camel_name,
3367                i.name_lower,
3368                i.ns_upper,
3369                i.name_upper,
3370                i.name,
3371                i.ns_upper,
3372                i.name_upper,
3373            )
3374        )
3375        self.outfile.write("\n")
3376        self.outfile.write(
3377            self.docbook_gen.expand(
3378                "/**\n"
3379                " * %s_proxy_new_for_bus:\n"
3380                " * @bus_type: A #GBusType.\n"
3381                " * @flags: Flags from the #GDBusProxyFlags enumeration.\n"
3382                " * @name: A bus name (well-known or unique).\n"
3383                " * @object_path: An object path.\n"
3384                " * @cancellable: (nullable): A #GCancellable or %%NULL.\n"
3385                " * @callback: A #GAsyncReadyCallback to call when the request is satisfied.\n"
3386                " * @user_data: User data to pass to @callback.\n"
3387                " *\n"
3388                " * Like %s_proxy_new() but takes a #GBusType instead of a #GDBusConnection.\n"
3389                " *\n"
3390                " * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).\n"
3391                " * You can then call %s_proxy_new_for_bus_finish() to get the result of the operation.\n"
3392                " *\n"
3393                " * See %s_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor.\n"
3394                % (i.name_lower, i.name_lower, i.name_lower, i.name_lower),
3395                False,
3396            )
3397        )
3398        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
3399        self.outfile.write(
3400            "void\n"
3401            "%s_proxy_new_for_bus (\n"
3402            "    GBusType             bus_type,\n"
3403            "    GDBusProxyFlags      flags,\n"
3404            "    const gchar         *name,\n"
3405            "    const gchar         *object_path,\n"
3406            "    GCancellable        *cancellable,\n"
3407            "    GAsyncReadyCallback  callback,\n"
3408            "    gpointer             user_data)\n"
3409            "{\n"
3410            '  g_async_initable_new_async (%sTYPE_%s_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "%s", NULL);\n'
3411            "}\n"
3412            "\n" % (i.name_lower, i.ns_upper, i.name_upper, i.name)
3413        )
3414        self.outfile.write(
3415            "/**\n"
3416            " * %s_proxy_new_for_bus_finish:\n"
3417            " * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %s_proxy_new_for_bus().\n"
3418            " * @error: Return location for error or %%NULL\n"
3419            " *\n"
3420            " * Finishes an operation started with %s_proxy_new_for_bus().\n"
3421            " *\n"
3422            " * Returns: (transfer full) (type %sProxy): The constructed proxy object or %%NULL if @error is set.\n"
3423            % (i.name_lower, i.name_lower, i.name_lower, i.camel_name)
3424        )
3425        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
3426        self.outfile.write(
3427            "%s *\n"
3428            "%s_proxy_new_for_bus_finish (\n"
3429            "    GAsyncResult        *res,\n"
3430            "    GError             **error)\n"
3431            "{\n"
3432            "  GObject *ret;\n"
3433            "  GObject *source_object;\n"
3434            "  source_object = g_async_result_get_source_object (res);\n"
3435            "  ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);\n"
3436            "  g_object_unref (source_object);\n"
3437            "  if (ret != NULL)\n"
3438            "    return %s%s (ret);\n"
3439            "  else\n"
3440            "    return NULL;\n"
3441            "}\n"
3442            "\n" % (i.camel_name, i.name_lower, i.ns_upper, i.name_upper)
3443        )
3444        self.outfile.write(
3445            self.docbook_gen.expand(
3446                "/**\n"
3447                " * %s_proxy_new_for_bus_sync:\n"
3448                " * @bus_type: A #GBusType.\n"
3449                " * @flags: Flags from the #GDBusProxyFlags enumeration.\n"
3450                " * @name: A bus name (well-known or unique).\n"
3451                " * @object_path: An object path.\n"
3452                " * @cancellable: (nullable): A #GCancellable or %%NULL.\n"
3453                " * @error: Return location for error or %%NULL\n"
3454                " *\n"
3455                " * Like %s_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection.\n"
3456                " *\n"
3457                " * The calling thread is blocked until a reply is received.\n"
3458                " *\n"
3459                " * See %s_proxy_new_for_bus() for the asynchronous version of this constructor.\n"
3460                " *\n"
3461                " * Returns: (transfer full) (type %sProxy): The constructed proxy object or %%NULL if @error is set.\n"
3462                % (i.name_lower, i.name_lower, i.name_lower, i.camel_name),
3463                False,
3464            )
3465        )
3466        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
3467        self.outfile.write(
3468            "%s *\n"
3469            "%s_proxy_new_for_bus_sync (\n"
3470            "    GBusType             bus_type,\n"
3471            "    GDBusProxyFlags      flags,\n"
3472            "    const gchar         *name,\n"
3473            "    const gchar         *object_path,\n"
3474            "    GCancellable        *cancellable,\n"
3475            "    GError             **error)\n"
3476            "{\n"
3477            "  GInitable *ret;\n"
3478            '  ret = g_initable_new (%sTYPE_%s_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "%s", NULL);\n'
3479            "  if (ret != NULL)\n"
3480            "    return %s%s (ret);\n"
3481            "  else\n"
3482            "    return NULL;\n"
3483            "}\n"
3484            "\n"
3485            % (
3486                i.camel_name,
3487                i.name_lower,
3488                i.ns_upper,
3489                i.name_upper,
3490                i.name,
3491                i.ns_upper,
3492                i.name_upper,
3493            )
3494        )
3495        self.outfile.write("\n")
3496
3497    # ---------------------------------------------------------------------------------------------------
3498
3499    def generate_skeleton(self, i):
3500        # class boilerplate
3501        self.outfile.write(
3502            "/* ------------------------------------------------------------------------ */\n"
3503            "\n"
3504        )
3505
3506        self.outfile.write(
3507            self.docbook_gen.expand(
3508                "/**\n"
3509                " * %sSkeleton:\n"
3510                " *\n"
3511                " * The #%sSkeleton structure contains only private data and should only be accessed using the provided API.\n"
3512                % (i.camel_name, i.camel_name),
3513                False,
3514            )
3515        )
3516        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
3517        self.outfile.write("\n")
3518
3519        self.outfile.write(
3520            self.docbook_gen.expand(
3521                "/**\n"
3522                " * %sSkeletonClass:\n"
3523                " * @parent_class: The parent class.\n"
3524                " *\n"
3525                " * Class structure for #%sSkeleton.\n" % (i.camel_name, i.camel_name),
3526                False,
3527            )
3528        )
3529        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
3530        self.outfile.write("\n")
3531
3532        self.outfile.write(
3533            "struct _%sSkeletonPrivate\n"
3534            "{\n"
3535            "  GValue *properties;\n"
3536            "  GList *changed_properties;\n"
3537            "  GSource *changed_properties_idle_source;\n"
3538            "  GMainContext *context;\n"
3539            "  GMutex lock;\n"
3540            "};\n"
3541            "\n" % i.camel_name
3542        )
3543
3544        self.outfile.write(
3545            "static void\n"
3546            "_%s_skeleton_handle_method_call (\n"
3547            "  GDBusConnection *connection G_GNUC_UNUSED,\n"
3548            "  const gchar *sender G_GNUC_UNUSED,\n"
3549            "  const gchar *object_path G_GNUC_UNUSED,\n"
3550            "  const gchar *interface_name,\n"
3551            "  const gchar *method_name,\n"
3552            "  GVariant *parameters,\n"
3553            "  GDBusMethodInvocation *invocation,\n"
3554            "  gpointer user_data)\n"
3555            "{\n"
3556            "  %sSkeleton *skeleton = %s%s_SKELETON (user_data);\n"
3557            "  _ExtendedGDBusMethodInfo *info;\n"
3558            "  GVariantIter iter;\n"
3559            "  GVariant *child;\n"
3560            "  GValue *paramv;\n"
3561            "  gsize num_params;\n"
3562            "  guint num_extra;\n"
3563            "  gsize n;\n"
3564            "  guint signal_id;\n"
3565            "  GValue return_value = G_VALUE_INIT;\n"
3566            % (i.name_lower, i.camel_name, i.ns_upper, i.name_upper)
3567        )
3568        self.outfile.write(
3569            "  info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation);\n"
3570            "  g_assert (info != NULL);\n"
3571        )
3572        self.outfile.write(
3573            "  num_params = g_variant_n_children (parameters);\n"
3574            "  num_extra = info->pass_fdlist ? 3 : 2;"
3575            "  paramv = g_new0 (GValue, num_params + num_extra);\n"
3576            "  n = 0;\n"
3577            "  g_value_init (&paramv[n], %sTYPE_%s);\n"
3578            "  g_value_set_object (&paramv[n++], skeleton);\n"
3579            "  g_value_init (&paramv[n], G_TYPE_DBUS_METHOD_INVOCATION);\n"
3580            "  g_value_set_object (&paramv[n++], invocation);\n"
3581            "  if (info->pass_fdlist)\n"
3582            "    {\n"
3583            "#ifdef G_OS_UNIX\n"
3584            "      g_value_init (&paramv[n], G_TYPE_UNIX_FD_LIST);\n"
3585            "      g_value_set_object (&paramv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation)));\n"
3586            "#else\n"
3587            "      g_assert_not_reached ();\n"
3588            "#endif\n"
3589            "    }\n" % (i.ns_upper, i.name_upper)
3590        )
3591        self.outfile.write(
3592            "  g_variant_iter_init (&iter, parameters);\n"
3593            "  while ((child = g_variant_iter_next_value (&iter)) != NULL)\n"
3594            "    {\n"
3595            "      _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra];\n"
3596            "      if (arg_info->use_gvariant)\n"
3597            "        {\n"
3598            "          g_value_init (&paramv[n], G_TYPE_VARIANT);\n"
3599            "          g_value_set_variant (&paramv[n], child);\n"
3600            "          n++;\n"
3601            "        }\n"
3602            "      else\n"
3603            "        g_dbus_gvariant_to_gvalue (child, &paramv[n++]);\n"
3604            "      g_variant_unref (child);\n"
3605            "    }\n"
3606        )
3607        self.outfile.write(
3608            "  signal_id = g_signal_lookup (info->signal_name, %sTYPE_%s);\n"
3609            % (i.ns_upper, i.name_upper)
3610        )
3611        self.outfile.write(
3612            "  g_value_init (&return_value, G_TYPE_BOOLEAN);\n"
3613            "  g_signal_emitv (paramv, signal_id, 0, &return_value);\n"
3614            "  if (!g_value_get_boolean (&return_value))\n"
3615            '    g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name);\n'
3616            "  g_value_unset (&return_value);\n"
3617        )
3618        self.outfile.write(
3619            "  for (n = 0; n < num_params + num_extra; n++)\n"
3620            "    g_value_unset (&paramv[n]);\n"
3621            "  g_free (paramv);\n"
3622        )
3623        self.outfile.write("}\n" "\n")
3624
3625        self.outfile.write(
3626            "static GVariant *\n"
3627            "_%s_skeleton_handle_get_property (\n"
3628            "  GDBusConnection *connection G_GNUC_UNUSED,\n"
3629            "  const gchar *sender G_GNUC_UNUSED,\n"
3630            "  const gchar *object_path G_GNUC_UNUSED,\n"
3631            "  const gchar *interface_name G_GNUC_UNUSED,\n"
3632            "  const gchar *property_name,\n"
3633            "  GError **error,\n"
3634            "  gpointer user_data)\n"
3635            "{\n"
3636            "  %sSkeleton *skeleton = %s%s_SKELETON (user_data);\n"
3637            "  GValue value = G_VALUE_INIT;\n"
3638            "  GParamSpec *pspec;\n"
3639            "  _ExtendedGDBusPropertyInfo *info;\n"
3640            "  GVariant *ret;\n"
3641            % (i.name_lower, i.camel_name, i.ns_upper, i.name_upper)
3642        )
3643        self.outfile.write(
3644            "  ret = NULL;\n"
3645            "  info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, property_name);\n"
3646            "  g_assert (info != NULL);\n"
3647            "  pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);\n"
3648            "  if (pspec == NULL)\n"
3649            "    {\n"
3650            '      g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %%s", property_name);\n'
3651            "    }\n"
3652            "  else\n"
3653            "    {\n"
3654            "      g_value_init (&value, pspec->value_type);\n"
3655            "      g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value);\n"
3656            "      ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature));\n"
3657            "      g_value_unset (&value);\n"
3658            "    }\n"
3659            "  return ret;\n"
3660            "}\n"
3661            "\n" % (i.name_lower)
3662        )
3663
3664        self.outfile.write(
3665            "static gboolean\n"
3666            "_%s_skeleton_handle_set_property (\n"
3667            "  GDBusConnection *connection G_GNUC_UNUSED,\n"
3668            "  const gchar *sender G_GNUC_UNUSED,\n"
3669            "  const gchar *object_path G_GNUC_UNUSED,\n"
3670            "  const gchar *interface_name G_GNUC_UNUSED,\n"
3671            "  const gchar *property_name,\n"
3672            "  GVariant *variant,\n"
3673            "  GError **error,\n"
3674            "  gpointer user_data)\n"
3675            "{\n"
3676            "  %sSkeleton *skeleton = %s%s_SKELETON (user_data);\n"
3677            "  GValue value = G_VALUE_INIT;\n"
3678            "  GParamSpec *pspec;\n"
3679            "  _ExtendedGDBusPropertyInfo *info;\n"
3680            "  gboolean ret;\n" % (i.name_lower, i.camel_name, i.ns_upper, i.name_upper)
3681        )
3682        self.outfile.write(
3683            "  ret = FALSE;\n"
3684            "  info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_%s_interface_info.parent_struct, property_name);\n"
3685            "  g_assert (info != NULL);\n"
3686            "  pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);\n"
3687            "  if (pspec == NULL)\n"
3688            "    {\n"
3689            '      g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %%s", property_name);\n'
3690            "    }\n"
3691            "  else\n"
3692            "    {\n"
3693            "      if (info->use_gvariant)\n"
3694            "        g_value_set_variant (&value, variant);\n"
3695            "      else\n"
3696            "        g_dbus_gvariant_to_gvalue (variant, &value);\n"
3697            "      g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value);\n"
3698            "      g_value_unset (&value);\n"
3699            "      ret = TRUE;\n"
3700            "    }\n"
3701            "  return ret;\n"
3702            "}\n"
3703            "\n" % (i.name_lower)
3704        )
3705
3706        self.outfile.write(
3707            "static const GDBusInterfaceVTable _%s_skeleton_vtable =\n"
3708            "{\n"
3709            "  _%s_skeleton_handle_method_call,\n"
3710            "  _%s_skeleton_handle_get_property,\n"
3711            "  _%s_skeleton_handle_set_property,\n"
3712            "  {NULL}\n"
3713            "};\n"
3714            "\n" % (i.name_lower, i.name_lower, i.name_lower, i.name_lower)
3715        )
3716
3717        self.outfile.write(
3718            "static GDBusInterfaceInfo *\n"
3719            "%s_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED)\n"
3720            "{\n"
3721            "  return %s_interface_info ();\n" % (i.name_lower, i.name_lower)
3722        )
3723        self.outfile.write("}\n" "\n")
3724
3725        self.outfile.write(
3726            "static GDBusInterfaceVTable *\n"
3727            "%s_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED)\n"
3728            "{\n"
3729            "  return (GDBusInterfaceVTable *) &_%s_skeleton_vtable;\n"
3730            % (i.name_lower, i.name_lower)
3731        )
3732        self.outfile.write("}\n" "\n")
3733
3734        self.outfile.write(
3735            "static GVariant *\n"
3736            "%s_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton)\n"
3737            "{\n"
3738            "  %sSkeleton *skeleton = %s%s_SKELETON (_skeleton);\n"
3739            % (i.name_lower, i.camel_name, i.ns_upper, i.name_upper)
3740        )
3741        self.outfile.write(
3742            "\n"
3743            "  GVariantBuilder builder;\n"
3744            "  guint n;\n"
3745            '  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));\n'
3746            "  if (_%s_interface_info.parent_struct.properties == NULL)\n"
3747            "    goto out;\n"
3748            "  for (n = 0; _%s_interface_info.parent_struct.properties[n] != NULL; n++)\n"
3749            "    {\n"
3750            "      GDBusPropertyInfo *info = _%s_interface_info.parent_struct.properties[n];\n"
3751            "      if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)\n"
3752            "        {\n"
3753            "          GVariant *value;\n"
3754            '          value = _%s_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "%s", info->name, NULL, skeleton);\n'
3755            "          if (value != NULL)\n"
3756            "            {\n"
3757            "              g_variant_take_ref (value);\n"
3758            '              g_variant_builder_add (&builder, "{sv}", info->name, value);\n'
3759            "              g_variant_unref (value);\n"
3760            "            }\n"
3761            "        }\n"
3762            "    }\n"
3763            "out:\n"
3764            "  return g_variant_builder_end (&builder);\n"
3765            "}\n"
3766            "\n" % (i.name_lower, i.name_lower, i.name_lower, i.name_lower, i.name)
3767        )
3768
3769        if len(i.properties) > 0:
3770            self.outfile.write(
3771                "static gboolean _%s_emit_changed (gpointer user_data);\n"
3772                "\n" % (i.name_lower)
3773            )
3774
3775        self.outfile.write(
3776            "static void\n"
3777            "%s_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton"
3778            % (i.name_lower)
3779        )
3780        if len(i.properties) == 0:
3781            self.outfile.write(" G_GNUC_UNUSED)\n")
3782        else:
3783            self.outfile.write(")\n")
3784        self.outfile.write("{\n")
3785        if len(i.properties) > 0:
3786            self.outfile.write(
3787                "  %sSkeleton *skeleton = %s%s_SKELETON (_skeleton);\n"
3788                "  gboolean emit_changed = FALSE;\n"
3789                "\n"
3790                "  g_mutex_lock (&skeleton->priv->lock);\n"
3791                "  if (skeleton->priv->changed_properties_idle_source != NULL)\n"
3792                "    {\n"
3793                "      g_source_destroy (skeleton->priv->changed_properties_idle_source);\n"
3794                "      skeleton->priv->changed_properties_idle_source = NULL;\n"
3795                "      emit_changed = TRUE;\n"
3796                "    }\n"
3797                "  g_mutex_unlock (&skeleton->priv->lock);\n"
3798                "\n"
3799                "  if (emit_changed)\n"
3800                "    _%s_emit_changed (skeleton);\n"
3801                % (i.camel_name, i.ns_upper, i.name_upper, i.name_lower)
3802            )
3803        self.outfile.write("}\n" "\n")
3804
3805        for s in i.signals:
3806            self.outfile.write(
3807                "static void\n"
3808                "_%s_on_signal_%s (\n"
3809                "    %s *object" % (i.name_lower, s.name_lower, i.camel_name)
3810            )
3811            for a in s.args:
3812                self.outfile.write(",\n    %sarg_%s" % (a.ctype_in, a.name))
3813            self.outfile.write(
3814                ")\n"
3815                "{\n"
3816                "  %sSkeleton *skeleton = %s%s_SKELETON (object);\n\n"
3817                "  GList      *connections, *l;\n"
3818                "  GVariant   *signal_variant;\n"
3819                "  connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));\n"
3820                % (i.camel_name, i.ns_upper, i.name_upper)
3821            )
3822            self.outfile.write(
3823                "\n" '  signal_variant = g_variant_ref_sink (g_variant_new ("('
3824            )
3825            for a in s.args:
3826                self.outfile.write("%s" % (a.format_in))
3827            self.outfile.write(')"')
3828            for a in s.args:
3829                self.outfile.write(",\n                   arg_%s" % (a.name))
3830            self.outfile.write("));\n")
3831
3832            self.outfile.write(
3833                "  for (l = connections; l != NULL; l = l->next)\n"
3834                "    {\n"
3835                "      GDBusConnection *connection = l->data;\n"
3836                "      g_dbus_connection_emit_signal (connection,\n"
3837                '        NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "%s", "%s",\n'
3838                "        signal_variant, NULL);\n"
3839                "    }\n" % (i.name, s.name)
3840            )
3841            self.outfile.write("  g_variant_unref (signal_variant);\n")
3842            self.outfile.write("  g_list_free_full (connections, g_object_unref);\n")
3843            self.outfile.write("}\n" "\n")
3844
3845        self.outfile.write(
3846            "static void %s_skeleton_iface_init (%sIface *iface);\n"
3847            % (i.name_lower, i.camel_name)
3848        )
3849
3850        self.outfile.write("#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38\n")
3851        self.outfile.write(
3852            "G_DEFINE_TYPE_WITH_CODE (%sSkeleton, %s_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,\n"
3853            % (i.camel_name, i.name_lower)
3854        )
3855        self.outfile.write(
3856            "                         G_ADD_PRIVATE (%sSkeleton)\n" % (i.camel_name)
3857        )
3858        self.outfile.write(
3859            "                         G_IMPLEMENT_INTERFACE (%sTYPE_%s, %s_skeleton_iface_init))\n\n"
3860            % (i.ns_upper, i.name_upper, i.name_lower)
3861        )
3862        self.outfile.write("#else\n")
3863        self.outfile.write(
3864            "G_DEFINE_TYPE_WITH_CODE (%sSkeleton, %s_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,\n"
3865            % (i.camel_name, i.name_lower)
3866        )
3867        self.outfile.write(
3868            "                         G_IMPLEMENT_INTERFACE (%sTYPE_%s, %s_skeleton_iface_init))\n\n"
3869            % (i.ns_upper, i.name_upper, i.name_lower)
3870        )
3871        self.outfile.write("#endif\n")
3872
3873        # finalize
3874        self.outfile.write(
3875            "static void\n"
3876            "%s_skeleton_finalize (GObject *object)\n"
3877            "{\n" % (i.name_lower)
3878        )
3879        self.outfile.write(
3880            "  %sSkeleton *skeleton = %s%s_SKELETON (object);\n"
3881            % (i.camel_name, i.ns_upper, i.name_upper)
3882        )
3883        if len(i.properties) > 0:
3884            self.outfile.write(
3885                "  guint n;\n"
3886                "  for (n = 0; n < %d; n++)\n"
3887                "    g_value_unset (&skeleton->priv->properties[n]);\n"
3888                % (len(i.properties))
3889            )
3890            self.outfile.write("  g_free (skeleton->priv->properties);\n")
3891        self.outfile.write(
3892            "  g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);\n"
3893        )
3894        self.outfile.write(
3895            "  if (skeleton->priv->changed_properties_idle_source != NULL)\n"
3896        )
3897        self.outfile.write(
3898            "    g_source_destroy (skeleton->priv->changed_properties_idle_source);\n"
3899        )
3900        self.outfile.write("  g_main_context_unref (skeleton->priv->context);\n")
3901        self.outfile.write("  g_mutex_clear (&skeleton->priv->lock);\n")
3902        self.outfile.write(
3903            "  G_OBJECT_CLASS (%s_skeleton_parent_class)->finalize (object);\n"
3904            "}\n"
3905            "\n" % (i.name_lower)
3906        )
3907
3908        # property accessors (TODO: generate PropertiesChanged signals in setter)
3909        if len(i.properties) > 0:
3910            self.outfile.write(
3911                "static void\n"
3912                "%s_skeleton_get_property (GObject      *object,\n"
3913                "  guint         prop_id,\n"
3914                "  GValue       *value,\n"
3915                "  GParamSpec   *pspec G_GNUC_UNUSED)\n"
3916                "{\n" % (i.name_lower)
3917            )
3918            self.outfile.write(
3919                "  %sSkeleton *skeleton = %s%s_SKELETON (object);\n"
3920                "  g_assert (prop_id != 0 && prop_id - 1 < %d);\n"
3921                "  g_mutex_lock (&skeleton->priv->lock);\n"
3922                "  g_value_copy (&skeleton->priv->properties[prop_id - 1], value);\n"
3923                "  g_mutex_unlock (&skeleton->priv->lock);\n"
3924                % (i.camel_name, i.ns_upper, i.name_upper, len(i.properties))
3925            )
3926            self.outfile.write("}\n" "\n")
3927
3928            # if property is already scheduled then re-use entry.. though it could be
3929            # that the user did
3930            #
3931            #  foo_set_prop_bar (object, "");
3932            #  foo_set_prop_bar (object, "blah");
3933            #
3934            # say, every update... In this case, where nothing happens, we obviously
3935            # don't want a PropertiesChanged() event. We can easily check for this
3936            # by comparing against the _original value_ recorded before the first
3937            # change event. If the latest value is not different from the original
3938            # one, we can simply ignore the ChangedProperty
3939            #
3940            self.outfile.write(
3941                "static gboolean\n"
3942                "_%s_emit_changed (gpointer user_data)\n"
3943                "{\n"
3944                "  %sSkeleton *skeleton = %s%s_SKELETON (user_data);\n"
3945                % (i.name_lower, i.camel_name, i.ns_upper, i.name_upper)
3946            )
3947            self.outfile.write(
3948                "  GList *l;\n"
3949                "  GVariantBuilder builder;\n"
3950                "  GVariantBuilder invalidated_builder;\n"
3951                "  guint num_changes;\n"
3952                "\n"
3953                "  g_mutex_lock (&skeleton->priv->lock);\n"
3954                '  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));\n'
3955                '  g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));\n'
3956                "  for (l = skeleton->priv->changed_properties, num_changes = 0; l != NULL; l = l->next)\n"
3957                "    {\n"
3958                "      ChangedProperty *cp = l->data;\n"
3959                "      GVariant *variant;\n"
3960                "      const GValue *cur_value;\n"
3961                "\n"
3962                "      cur_value = &skeleton->priv->properties[cp->prop_id - 1];\n"
3963                "      if (!_g_value_equal (cur_value, &cp->orig_value))\n"
3964                "        {\n"
3965                "          variant = g_dbus_gvalue_to_gvariant (cur_value, G_VARIANT_TYPE (cp->info->parent_struct.signature));\n"
3966                '          g_variant_builder_add (&builder, "{sv}", cp->info->parent_struct.name, variant);\n'
3967                "          g_variant_unref (variant);\n"
3968                "          num_changes++;\n"
3969                "        }\n"
3970                "    }\n"
3971                "  if (num_changes > 0)\n"
3972                "    {\n"
3973                "      GList *connections, *ll;\n"
3974                "      GVariant *signal_variant;"
3975                "\n"
3976                '      signal_variant = g_variant_ref_sink (g_variant_new ("(sa{sv}as)", "%s",\n'
3977                "                                           &builder, &invalidated_builder));\n"
3978                "      connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));\n"
3979                "      for (ll = connections; ll != NULL; ll = ll->next)\n"
3980                "        {\n"
3981                "          GDBusConnection *connection = ll->data;\n"
3982                "\n"
3983                "          g_dbus_connection_emit_signal (connection,\n"
3984                "                                         NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)),\n"
3985                '                                         "org.freedesktop.DBus.Properties",\n'
3986                '                                         "PropertiesChanged",\n'
3987                "                                         signal_variant,\n"
3988                "                                         NULL);\n"
3989                "        }\n"
3990                "      g_variant_unref (signal_variant);\n"
3991                "      g_list_free_full (connections, g_object_unref);\n"
3992                "    }\n"
3993                "  else\n"
3994                "    {\n"
3995                "      g_variant_builder_clear (&builder);\n"
3996                "      g_variant_builder_clear (&invalidated_builder);\n"
3997                "    }\n" % (i.name)
3998            )
3999            self.outfile.write(
4000                "  g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);\n"
4001            )
4002            self.outfile.write("  skeleton->priv->changed_properties = NULL;\n")
4003            self.outfile.write(
4004                "  skeleton->priv->changed_properties_idle_source = NULL;\n"
4005            )
4006            self.outfile.write("  g_mutex_unlock (&skeleton->priv->lock);\n")
4007            self.outfile.write("  return FALSE;\n" "}\n" "\n")
4008            # holding lock while being called
4009            self.outfile.write(
4010                "static void\n"
4011                "_%s_schedule_emit_changed (%sSkeleton *skeleton, const _ExtendedGDBusPropertyInfo *info, guint prop_id, const GValue *orig_value)\n"
4012                "{\n"
4013                "  ChangedProperty *cp;\n"
4014                "  GList *l;\n"
4015                "  cp = NULL;\n"
4016                "  for (l = skeleton->priv->changed_properties; l != NULL; l = l->next)\n"
4017                "    {\n"
4018                "      ChangedProperty *i_cp = l->data;\n"
4019                "      if (i_cp->info == info)\n"
4020                "        {\n"
4021                "          cp = i_cp;\n"
4022                "          break;\n"
4023                "        }\n"
4024                "    }\n" % (i.name_lower, i.camel_name)
4025            )
4026            self.outfile.write(
4027                "  if (cp == NULL)\n"
4028                "    {\n"
4029                "      cp = g_new0 (ChangedProperty, 1);\n"
4030                "      cp->prop_id = prop_id;\n"
4031                "      cp->info = info;\n"
4032                "      skeleton->priv->changed_properties = g_list_prepend (skeleton->priv->changed_properties, cp);\n"
4033                "      g_value_init (&cp->orig_value, G_VALUE_TYPE (orig_value));\n"
4034                "      g_value_copy (orig_value, &cp->orig_value);\n"
4035                "    }\n"
4036                "}\n"
4037                "\n"
4038            )
4039
4040            # Postpone setting up the refresh source until the ::notify signal is emitted as
4041            # this allows use of g_object_freeze_notify()/g_object_thaw_notify() ...
4042            # This is useful when updating several properties from another thread than
4043            # where the idle will be emitted from
4044            self.outfile.write(
4045                "static void\n"
4046                "%s_skeleton_notify (GObject      *object,\n"
4047                "  GParamSpec *pspec G_GNUC_UNUSED)\n"
4048                "{\n"
4049                "  %sSkeleton *skeleton = %s%s_SKELETON (object);\n"
4050                "  g_mutex_lock (&skeleton->priv->lock);\n"
4051                "  if (skeleton->priv->changed_properties != NULL &&\n"
4052                "      skeleton->priv->changed_properties_idle_source == NULL)\n"
4053                "    {\n"
4054                "      skeleton->priv->changed_properties_idle_source = g_idle_source_new ();\n"
4055                "      g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);\n"
4056                "      g_source_set_callback (skeleton->priv->changed_properties_idle_source, _%s_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);\n"
4057                '      g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _%s_emit_changed");\n'
4058                "      g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);\n"
4059                "      g_source_unref (skeleton->priv->changed_properties_idle_source);\n"
4060                "    }\n"
4061                "  g_mutex_unlock (&skeleton->priv->lock);\n"
4062                "}\n"
4063                "\n"
4064                % (
4065                    i.name_lower,
4066                    i.camel_name,
4067                    i.ns_upper,
4068                    i.name_upper,
4069                    i.name_lower,
4070                    i.name_lower,
4071                )
4072            )
4073
4074            self.outfile.write(
4075                "static void\n"
4076                "%s_skeleton_set_property (GObject      *object,\n"
4077                "  guint         prop_id,\n"
4078                "  const GValue *value,\n"
4079                "  GParamSpec   *pspec)\n"
4080                "{\n" % (i.name_lower)
4081            )
4082            self.outfile.write(
4083                "  const _ExtendedGDBusPropertyInfo *info;\n"
4084                "  %sSkeleton *skeleton = %s%s_SKELETON (object);\n"
4085                "  g_assert (prop_id != 0 && prop_id - 1 < %d);\n"
4086                "  info = (const _ExtendedGDBusPropertyInfo *) _%s_property_info_pointers[prop_id - 1];\n"
4087                "  g_mutex_lock (&skeleton->priv->lock);\n"
4088                "  g_object_freeze_notify (object);\n"
4089                "  if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1]))\n"
4090                "    {\n"
4091                "      if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL &&\n"
4092                "          info->emits_changed_signal)\n"
4093                "        _%s_schedule_emit_changed (skeleton, info, prop_id, &skeleton->priv->properties[prop_id - 1]);\n"
4094                "      g_value_copy (value, &skeleton->priv->properties[prop_id - 1]);\n"
4095                "      g_object_notify_by_pspec (object, pspec);\n"
4096                "    }\n"
4097                "  g_mutex_unlock (&skeleton->priv->lock);\n"
4098                "  g_object_thaw_notify (object);\n"
4099                % (
4100                    i.camel_name,
4101                    i.ns_upper,
4102                    i.name_upper,
4103                    len(i.properties),
4104                    i.name_lower,
4105                    i.name_lower,
4106                )
4107            )
4108            self.outfile.write("}\n" "\n")
4109
4110        self.outfile.write(
4111            "static void\n"
4112            "%s_skeleton_init (%sSkeleton *skeleton)\n"
4113            "{\n"
4114            "#if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38\n"
4115            "  skeleton->priv = %s_skeleton_get_instance_private (skeleton);\n"
4116            "#else\n"
4117            "  skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, %sTYPE_%s_SKELETON, %sSkeletonPrivate);\n"
4118            "#endif\n\n"
4119            % (
4120                i.name_lower,
4121                i.camel_name,
4122                i.name_lower,
4123                i.ns_upper,
4124                i.name_upper,
4125                i.camel_name,
4126            )
4127        )
4128        self.outfile.write("  g_mutex_init (&skeleton->priv->lock);\n")
4129        self.outfile.write(
4130            "  skeleton->priv->context = g_main_context_ref_thread_default ();\n"
4131        )
4132        if len(i.properties) > 0:
4133            self.outfile.write(
4134                "  skeleton->priv->properties = g_new0 (GValue, %d);\n"
4135                % (len(i.properties))
4136            )
4137            n = 0
4138            for p in i.properties:
4139                self.outfile.write(
4140                    "  g_value_init (&skeleton->priv->properties[%d], %s);\n"
4141                    % (n, p.arg.gtype)
4142                )
4143                n += 1
4144        self.outfile.write("}\n" "\n")
4145
4146        # property vfuncs
4147        n = 0
4148        for p in i.properties:
4149            self.outfile.write(
4150                "static %s\n"
4151                "%s_skeleton_get_%s (%s *object)\n"
4152                "{\n" % (p.arg.ctype_in, i.name_lower, p.name_lower, i.camel_name)
4153            )
4154            self.outfile.write(
4155                "  %sSkeleton *skeleton = %s%s_SKELETON (object);\n"
4156                % (i.camel_name, i.ns_upper, i.name_upper)
4157            )
4158            self.outfile.write(
4159                "  %svalue;\n"
4160                "  g_mutex_lock (&skeleton->priv->lock);\n"
4161                "  value = %s (&(skeleton->priv->properties[%d]));\n"
4162                "  g_mutex_unlock (&skeleton->priv->lock);\n"
4163                % (p.arg.ctype_in_g, p.arg.gvalue_get, n)
4164            )
4165            self.outfile.write("  return value;\n")
4166            self.outfile.write("}\n")
4167            self.outfile.write("\n")
4168            n += 1
4169
4170        self.outfile.write(
4171            "static void\n"
4172            "%s_skeleton_class_init (%sSkeletonClass *klass)\n"
4173            "{\n"
4174            "  GObjectClass *gobject_class;\n"
4175            "  GDBusInterfaceSkeletonClass *skeleton_class;\n"
4176            "\n"
4177            "  gobject_class = G_OBJECT_CLASS (klass);\n"
4178            "  gobject_class->finalize = %s_skeleton_finalize;\n"
4179            % (i.name_lower, i.camel_name, i.name_lower)
4180        )
4181        if len(i.properties) > 0:
4182            self.outfile.write(
4183                "  gobject_class->get_property = %s_skeleton_get_property;\n"
4184                "  gobject_class->set_property = %s_skeleton_set_property;\n"
4185                "  gobject_class->notify       = %s_skeleton_notify;\n"
4186                "\n" % (i.name_lower, i.name_lower, i.name_lower)
4187            )
4188            self.outfile.write(
4189                "\n" "  %s_override_properties (gobject_class, 1);\n" % (i.name_lower)
4190            )
4191        self.outfile.write(
4192            "\n" "  skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);\n"
4193        )
4194        self.outfile.write(
4195            "  skeleton_class->get_info = %s_skeleton_dbus_interface_get_info;\n"
4196            % (i.name_lower)
4197        )
4198        self.outfile.write(
4199            "  skeleton_class->get_properties = %s_skeleton_dbus_interface_get_properties;\n"
4200            % (i.name_lower)
4201        )
4202        self.outfile.write(
4203            "  skeleton_class->flush = %s_skeleton_dbus_interface_flush;\n"
4204            % (i.name_lower)
4205        )
4206        self.outfile.write(
4207            "  skeleton_class->get_vtable = %s_skeleton_dbus_interface_get_vtable;\n"
4208            % (i.name_lower)
4209        )
4210
4211        self.outfile.write(
4212            "\n"
4213            "#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38\n"
4214            "  g_type_class_add_private (klass, sizeof (%sSkeletonPrivate));\n"
4215            "#endif\n" % (i.camel_name)
4216        )
4217
4218        self.outfile.write("}\n" "\n")
4219
4220        self.outfile.write(
4221            "static void\n"
4222            "%s_skeleton_iface_init (%sIface *iface" % (i.name_lower, i.camel_name)
4223        )
4224        if len(i.signals) == 0 and len(i.properties) == 0:
4225            self.outfile.write(" G_GNUC_UNUSED)\n")
4226        else:
4227            self.outfile.write(")\n")
4228        self.outfile.write("{\n")
4229        for s in i.signals:
4230            self.outfile.write(
4231                "  iface->%s = _%s_on_signal_%s;\n"
4232                % (s.name_lower, i.name_lower, s.name_lower)
4233            )
4234        for p in i.properties:
4235            self.outfile.write(
4236                "  iface->get_%s = %s_skeleton_get_%s;\n"
4237                % (p.name_lower, i.name_lower, p.name_lower)
4238            )
4239        self.outfile.write("}\n" "\n")
4240
4241        # constructors
4242        self.outfile.write(
4243            self.docbook_gen.expand(
4244                "/**\n"
4245                " * %s_skeleton_new:\n"
4246                " *\n"
4247                " * Creates a skeleton object for the D-Bus interface #%s.\n"
4248                " *\n"
4249                " * Returns: (transfer full) (type %sSkeleton): The skeleton object.\n"
4250                % (i.name_lower, i.name, i.camel_name),
4251                False,
4252            )
4253        )
4254        self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
4255        self.outfile.write(
4256            "%s *\n"
4257            "%s_skeleton_new (void)\n"
4258            "{\n"
4259            "  return %s%s (g_object_new (%sTYPE_%s_SKELETON, NULL));\n"
4260            "}\n"
4261            "\n"
4262            % (
4263                i.camel_name,
4264                i.name_lower,
4265                i.ns_upper,
4266                i.name_upper,
4267                i.ns_upper,
4268                i.name_upper,
4269            )
4270        )
4271
4272    # ---------------------------------------------------------------------------------------------------
4273
4274    def generate_object(self):
4275        self.outfile.write(
4276            "/* ------------------------------------------------------------------------\n"
4277            " * Code for Object, ObjectProxy and ObjectSkeleton\n"
4278            " * ------------------------------------------------------------------------\n"
4279            " */\n"
4280            "\n"
4281        )
4282
4283        self.outfile.write(
4284            self.docbook_gen.expand(
4285                "/**\n"
4286                " * SECTION:%sObject\n"
4287                " * @title: %sObject\n"
4288                " * @short_description: Specialized GDBusObject types\n"
4289                " *\n"
4290                " * This section contains the #%sObject, #%sObjectProxy, and #%sObjectSkeleton types which make it easier to work with objects implementing generated types for D-Bus interfaces.\n"
4291                " */\n"
4292                % (
4293                    self.namespace,
4294                    self.namespace,
4295                    self.namespace,
4296                    self.namespace,
4297                    self.namespace,
4298                ),
4299                False,
4300            )
4301        )
4302        self.outfile.write("\n")
4303
4304        self.outfile.write(
4305            self.docbook_gen.expand(
4306                "/**\n"
4307                " * %sObject:\n"
4308                " *\n"
4309                " * The #%sObject type is a specialized container of interfaces.\n"
4310                " */\n" % (self.namespace, self.namespace),
4311                False,
4312            )
4313        )
4314        self.outfile.write("\n")
4315
4316        self.outfile.write(
4317            self.docbook_gen.expand(
4318                "/**\n"
4319                " * %sObjectIface:\n"
4320                " * @parent_iface: The parent interface.\n"
4321                " *\n"
4322                " * Virtual table for the #%sObject interface.\n"
4323                " */\n" % (self.namespace, self.namespace),
4324                False,
4325            )
4326        )
4327        self.outfile.write("\n")
4328
4329        self.outfile.write(
4330            "typedef %sObjectIface %sObjectInterface;\n"
4331            % (self.namespace, self.namespace)
4332        )
4333        self.outfile.write(
4334            "G_DEFINE_INTERFACE_WITH_CODE (%sObject, %sobject, G_TYPE_OBJECT, g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_DBUS_OBJECT);)\n"
4335            % (self.namespace, self.ns_lower)
4336        )
4337        self.outfile.write("\n")
4338        self.outfile.write(
4339            "static void\n"
4340            "%sobject_default_init (%sObjectIface *iface)\n"
4341            "{\n" % (self.ns_lower, self.namespace)
4342        )
4343        for i in self.ifaces:
4344            self.outfile.write(
4345                self.docbook_gen.expand(
4346                    "  /**\n"
4347                    "   * %sObject:%s:\n"
4348                    "   *\n"
4349                    "   * The #%s instance corresponding to the D-Bus interface #%s, if any.\n"
4350                    "   *\n"
4351                    "   * Connect to the #GObject::notify signal to get informed of property changes.\n"
4352                    % (self.namespace, i.name_hyphen, i.camel_name, i.name),
4353                    False,
4354                )
4355            )
4356            self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 2)
4357            flags = "G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS"
4358            if i.deprecated:
4359                flags = "G_PARAM_DEPRECATED | " + flags
4360            self.outfile.write(
4361                '  g_object_interface_install_property (iface, g_param_spec_object ("%s", "%s", "%s", %sTYPE_%s, %s));\n'
4362                "\n"
4363                % (
4364                    i.name_hyphen,
4365                    i.name_hyphen,
4366                    i.name_hyphen,
4367                    self.ns_upper,
4368                    i.name_upper,
4369                    flags,
4370                )
4371            )
4372        self.outfile.write("}\n" "\n")
4373
4374        for i in self.ifaces:
4375            self.outfile.write(
4376                self.docbook_gen.expand(
4377                    "/**\n"
4378                    " * %sobject_get_%s:\n"
4379                    " * @object: A #%sObject.\n"
4380                    " *\n"
4381                    " * Gets the #%s instance for the D-Bus interface #%s on @object, if any.\n"
4382                    " *\n"
4383                    " * Returns: (transfer full) (nullable): A #%s that must be freed with g_object_unref() or %%NULL if @object does not implement the interface.\n"
4384                    % (
4385                        self.ns_lower,
4386                        i.name_upper.lower(),
4387                        self.namespace,
4388                        i.camel_name,
4389                        i.name,
4390                        i.camel_name,
4391                    ),
4392                    False,
4393                )
4394            )
4395            self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
4396            self.outfile.write(
4397                "%s *%sobject_get_%s (%sObject *object)\n"
4398                % (i.camel_name, self.ns_lower, i.name_upper.lower(), self.namespace)
4399            )
4400            self.outfile.write(
4401                "{\n"
4402                "  GDBusInterface *ret;\n"
4403                '  ret = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "%s");\n'
4404                "  if (ret == NULL)\n"
4405                "    return NULL;\n"
4406                "  return %s%s (ret);\n"
4407                "}\n"
4408                "\n" % (i.name, self.ns_upper, i.name_upper)
4409            )
4410        self.outfile.write("\n")
4411        for i in self.ifaces:
4412            self.outfile.write(
4413                self.docbook_gen.expand(
4414                    "/**\n"
4415                    " * %sobject_peek_%s: (skip)\n"
4416                    " * @object: A #%sObject.\n"
4417                    " *\n"
4418                    " * Like %sobject_get_%s() but doesn't increase the reference count on the returned object.\n"
4419                    " *\n"
4420                    " * It is not safe to use the returned object if you are on another thread than the one where the #GDBusObjectManagerClient or #GDBusObjectManagerServer for @object is running.\n"
4421                    " *\n"
4422                    " * Returns: (transfer none) (nullable): A #%s or %%NULL if @object does not implement the interface. Do not free the returned object, it is owned by @object.\n"
4423                    % (
4424                        self.ns_lower,
4425                        i.name_upper.lower(),
4426                        self.namespace,
4427                        self.ns_lower,
4428                        i.name_upper.lower(),
4429                        i.camel_name,
4430                    ),
4431                    False,
4432                )
4433            )
4434            self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
4435            self.outfile.write(
4436                "%s *%sobject_peek_%s (%sObject *object)\n"
4437                % (i.camel_name, self.ns_lower, i.name_upper.lower(), self.namespace)
4438            )
4439            self.outfile.write(
4440                "{\n"
4441                "  GDBusInterface *ret;\n"
4442                '  ret = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "%s");\n'
4443                "  if (ret == NULL)\n"
4444                "    return NULL;\n"
4445                "  g_object_unref (ret);\n"
4446                "  return %s%s (ret);\n"
4447                "}\n"
4448                "\n" % (i.name, self.ns_upper, i.name_upper)
4449            )
4450        self.outfile.write("\n")
4451        # shared by ObjectProxy and ObjectSkeleton classes
4452        self.outfile.write(
4453            "static void\n"
4454            "%sobject_notify (GDBusObject *object, GDBusInterface *interface)\n"
4455            "{\n"
4456            "  _ExtendedGDBusInterfaceInfo *info = (_ExtendedGDBusInterfaceInfo *) g_dbus_interface_get_info (interface);\n"
4457            "  /* info can be NULL if the other end is using a D-Bus interface we don't know\n"
4458            "   * anything about, for example old generated code in this process talking to\n"
4459            "   * newer generated code in the other process. */\n"
4460            "  if (info != NULL)\n"
4461            "    g_object_notify (G_OBJECT (object), info->hyphen_name);\n"
4462            "}\n"
4463            "\n" % (self.ns_lower)
4464        )
4465
4466        self.outfile.write(
4467            self.docbook_gen.expand(
4468                "/**\n"
4469                " * %sObjectProxy:\n"
4470                " *\n"
4471                " * The #%sObjectProxy structure contains only private data and should only be accessed using the provided API.\n"
4472                % (self.namespace, self.namespace),
4473                False,
4474            )
4475        )
4476        self.outfile.write(" */\n")
4477        self.outfile.write("\n")
4478        self.outfile.write(
4479            self.docbook_gen.expand(
4480                "/**\n"
4481                " * %sObjectProxyClass:\n"
4482                " * @parent_class: The parent class.\n"
4483                " *\n"
4484                " * Class structure for #%sObjectProxy.\n"
4485                % (self.namespace, self.namespace),
4486                False,
4487            )
4488        )
4489        self.outfile.write(" */\n")
4490        self.outfile.write("\n")
4491        # class boilerplate
4492        self.outfile.write(
4493            "static void\n"
4494            "%sobject_proxy__%sobject_iface_init (%sObjectIface *iface G_GNUC_UNUSED)\n"
4495            "{\n"
4496            "}\n"
4497            "\n" % (self.ns_lower, self.ns_lower, self.namespace)
4498        )
4499        self.outfile.write(
4500            "static void\n"
4501            "%sobject_proxy__g_dbus_object_iface_init (GDBusObjectIface *iface)\n"
4502            "{\n"
4503            "  iface->interface_added = %sobject_notify;\n"
4504            "  iface->interface_removed = %sobject_notify;\n"
4505            "}\n"
4506            "\n" % (self.ns_lower, self.ns_lower, self.ns_lower)
4507        )
4508        self.outfile.write("\n")
4509        self.outfile.write(
4510            "G_DEFINE_TYPE_WITH_CODE (%sObjectProxy, %sobject_proxy, G_TYPE_DBUS_OBJECT_PROXY,\n"
4511            "                         G_IMPLEMENT_INTERFACE (%sTYPE_OBJECT, %sobject_proxy__%sobject_iface_init)\n"
4512            "                         G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT, %sobject_proxy__g_dbus_object_iface_init))\n"
4513            "\n"
4514            % (
4515                self.namespace,
4516                self.ns_lower,
4517                self.ns_upper,
4518                self.ns_lower,
4519                self.ns_lower,
4520                self.ns_lower,
4521            )
4522        )
4523        # class boilerplate
4524        self.outfile.write(
4525            "static void\n"
4526            "%sobject_proxy_init (%sObjectProxy *object G_GNUC_UNUSED)\n"
4527            "{\n"
4528            "}\n"
4529            "\n" % (self.ns_lower, self.namespace)
4530        )
4531        self.outfile.write(
4532            "static void\n"
4533            "%sobject_proxy_set_property (GObject      *gobject,\n"
4534            "  guint         prop_id,\n"
4535            "  const GValue *value G_GNUC_UNUSED,\n"
4536            "  GParamSpec   *pspec)\n"
4537            "{\n"
4538            "  G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);\n"
4539            % (self.ns_lower)
4540        )
4541        self.outfile.write("}\n" "\n")
4542        self.outfile.write(
4543            "static void\n"
4544            "%sobject_proxy_get_property (GObject      *gobject,\n"
4545            "  guint         prop_id,\n"
4546            "  GValue       *value,\n"
4547            "  GParamSpec   *pspec)\n"
4548            "{\n"
4549            "  %sObjectProxy *object = %sOBJECT_PROXY (gobject);\n"
4550            "  GDBusInterface *interface;\n"
4551            "\n"
4552            "  switch (prop_id)\n"
4553            "    {\n" % (self.ns_lower, self.namespace, self.ns_upper)
4554        )
4555        n = 1
4556        for i in self.ifaces:
4557            self.outfile.write(
4558                "    case %d:\n"
4559                '      interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "%s");\n'
4560                "      g_value_take_object (value, interface);\n"
4561                "      break;\n"
4562                "\n" % (n, i.name)
4563            )
4564            n += 1
4565        self.outfile.write(
4566            "    default:\n"
4567            "      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);\n"
4568            "      break;\n"
4569            "  }\n"
4570            "}\n"
4571            "\n"
4572        )
4573        self.outfile.write(
4574            "static void\n"
4575            "%sobject_proxy_class_init (%sObjectProxyClass *klass)\n"
4576            "{\n"
4577            "  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);\n"
4578            "\n"
4579            "  gobject_class->set_property = %sobject_proxy_set_property;\n"
4580            "  gobject_class->get_property = %sobject_proxy_get_property;\n"
4581            "\n" % (self.ns_lower, self.namespace, self.ns_lower, self.ns_lower)
4582        )
4583        n = 1
4584        for i in self.ifaces:
4585            self.outfile.write(
4586                '  g_object_class_override_property (gobject_class, %d, "%s");'
4587                "\n" % (n, i.name_hyphen)
4588            )
4589            n += 1
4590        self.outfile.write("}\n" "\n")
4591
4592        self.outfile.write(
4593            self.docbook_gen.expand(
4594                "/**\n"
4595                " * %sobject_proxy_new:\n"
4596                " * @connection: A #GDBusConnection.\n"
4597                " * @object_path: An object path.\n"
4598                " *\n"
4599                " * Creates a new proxy object.\n"
4600                " *\n"
4601                " * Returns: (transfer full): The proxy object.\n"
4602                " */\n" % (self.ns_lower),
4603                False,
4604            )
4605        )
4606        self.outfile.write(
4607            "%sObjectProxy *\n"
4608            "%sobject_proxy_new (GDBusConnection *connection,\n"
4609            "  const gchar *object_path)\n"
4610            "{\n"
4611            "  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);\n"
4612            "  g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);\n"
4613            '  return %sOBJECT_PROXY (g_object_new (%sTYPE_OBJECT_PROXY, "g-connection", connection, "g-object-path", object_path, NULL));\n'
4614            "}\n"
4615            "\n" % (self.namespace, self.ns_lower, self.ns_upper, self.ns_upper)
4616        )
4617
4618        self.outfile.write(
4619            self.docbook_gen.expand(
4620                "/**\n"
4621                " * %sObjectSkeleton:\n"
4622                " *\n"
4623                " * The #%sObjectSkeleton structure contains only private data and should only be accessed using the provided API.\n"
4624                % (self.namespace, self.namespace),
4625                False,
4626            )
4627        )
4628        self.outfile.write(" */\n")
4629        self.outfile.write("\n")
4630        self.outfile.write(
4631            self.docbook_gen.expand(
4632                "/**\n"
4633                " * %sObjectSkeletonClass:\n"
4634                " * @parent_class: The parent class.\n"
4635                " *\n"
4636                " * Class structure for #%sObjectSkeleton.\n"
4637                % (self.namespace, self.namespace),
4638                False,
4639            )
4640        )
4641        self.outfile.write(" */\n")
4642        self.outfile.write("\n")
4643        # class boilerplate
4644        self.outfile.write(
4645            "static void\n"
4646            "%sobject_skeleton__%sobject_iface_init (%sObjectIface *iface G_GNUC_UNUSED)\n"
4647            "{\n"
4648            "}\n"
4649            "\n" % (self.ns_lower, self.ns_lower, self.namespace)
4650        )
4651        self.outfile.write("\n")
4652        self.outfile.write(
4653            "static void\n"
4654            "%sobject_skeleton__g_dbus_object_iface_init (GDBusObjectIface *iface)\n"
4655            "{\n"
4656            "  iface->interface_added = %sobject_notify;\n"
4657            "  iface->interface_removed = %sobject_notify;\n"
4658            "}\n"
4659            "\n" % (self.ns_lower, self.ns_lower, self.ns_lower)
4660        )
4661        self.outfile.write(
4662            "G_DEFINE_TYPE_WITH_CODE (%sObjectSkeleton, %sobject_skeleton, G_TYPE_DBUS_OBJECT_SKELETON,\n"
4663            "                         G_IMPLEMENT_INTERFACE (%sTYPE_OBJECT, %sobject_skeleton__%sobject_iface_init)\n"
4664            "                         G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT, %sobject_skeleton__g_dbus_object_iface_init))\n"
4665            "\n"
4666            % (
4667                self.namespace,
4668                self.ns_lower,
4669                self.ns_upper,
4670                self.ns_lower,
4671                self.ns_lower,
4672                self.ns_lower,
4673            )
4674        )
4675        # class boilerplate
4676        self.outfile.write(
4677            "static void\n"
4678            "%sobject_skeleton_init (%sObjectSkeleton *object G_GNUC_UNUSED)\n"
4679            "{\n"
4680            "}\n"
4681            "\n" % (self.ns_lower, self.namespace)
4682        )
4683        self.outfile.write(
4684            "static void\n"
4685            "%sobject_skeleton_set_property (GObject      *gobject,\n"
4686            "  guint         prop_id,\n"
4687            "  const GValue *value,\n"
4688            "  GParamSpec   *pspec)\n"
4689            "{\n"
4690            "  %sObjectSkeleton *object = %sOBJECT_SKELETON (gobject);\n"
4691            "  GDBusInterfaceSkeleton *interface;\n"
4692            "\n"
4693            "  switch (prop_id)\n"
4694            "    {\n" % (self.ns_lower, self.namespace, self.ns_upper)
4695        )
4696        n = 1
4697        for i in self.ifaces:
4698            self.outfile.write(
4699                "    case %d:\n"
4700                "      interface = g_value_get_object (value);\n"
4701                "      if (interface != NULL)\n"
4702                "        {\n"
4703                "          g_warn_if_fail (%sIS_%s (interface));\n"
4704                "          g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON (object), interface);\n"
4705                "        }\n"
4706                "      else\n"
4707                "        {\n"
4708                '          g_dbus_object_skeleton_remove_interface_by_name (G_DBUS_OBJECT_SKELETON (object), "%s");\n'
4709                "        }\n"
4710                "      break;\n"
4711                "\n" % (n, self.ns_upper, i.name_upper, i.name)
4712            )
4713            n += 1
4714        self.outfile.write(
4715            "    default:\n"
4716            "      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);\n"
4717            "      break;\n"
4718            "  }\n"
4719            "}\n"
4720            "\n"
4721        )
4722        self.outfile.write(
4723            "static void\n"
4724            "%sobject_skeleton_get_property (GObject      *gobject,\n"
4725            "  guint         prop_id,\n"
4726            "  GValue       *value,\n"
4727            "  GParamSpec   *pspec)\n"
4728            "{\n"
4729            "  %sObjectSkeleton *object = %sOBJECT_SKELETON (gobject);\n"
4730            "  GDBusInterface *interface;\n"
4731            "\n"
4732            "  switch (prop_id)\n"
4733            "    {\n" % (self.ns_lower, self.namespace, self.ns_upper)
4734        )
4735        n = 1
4736        for i in self.ifaces:
4737            self.outfile.write(
4738                "    case %d:\n"
4739                '      interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "%s");\n'
4740                "      g_value_take_object (value, interface);\n"
4741                "      break;\n"
4742                "\n" % (n, i.name)
4743            )
4744            n += 1
4745        self.outfile.write(
4746            "    default:\n"
4747            "      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);\n"
4748            "      break;\n"
4749            "  }\n"
4750            "}\n"
4751            "\n"
4752        )
4753        self.outfile.write(
4754            "static void\n"
4755            "%sobject_skeleton_class_init (%sObjectSkeletonClass *klass)\n"
4756            "{\n"
4757            "  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);\n"
4758            "\n"
4759            "  gobject_class->set_property = %sobject_skeleton_set_property;\n"
4760            "  gobject_class->get_property = %sobject_skeleton_get_property;\n"
4761            "\n" % (self.ns_lower, self.namespace, self.ns_lower, self.ns_lower)
4762        )
4763        n = 1
4764        for i in self.ifaces:
4765            self.outfile.write(
4766                '  g_object_class_override_property (gobject_class, %d, "%s");'
4767                "\n" % (n, i.name_hyphen)
4768            )
4769            n += 1
4770        self.outfile.write("}\n" "\n")
4771        self.outfile.write(
4772            self.docbook_gen.expand(
4773                "/**\n"
4774                " * %sobject_skeleton_new:\n"
4775                " * @object_path: An object path.\n"
4776                " *\n"
4777                " * Creates a new skeleton object.\n"
4778                " *\n"
4779                " * Returns: (transfer full): The skeleton object.\n"
4780                " */\n" % (self.ns_lower),
4781                False,
4782            )
4783        )
4784        self.outfile.write(
4785            "%sObjectSkeleton *\n"
4786            "%sobject_skeleton_new (const gchar *object_path)\n"
4787            "{\n"
4788            "  g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);\n"
4789            '  return %sOBJECT_SKELETON (g_object_new (%sTYPE_OBJECT_SKELETON, "g-object-path", object_path, NULL));\n'
4790            "}\n"
4791            "\n" % (self.namespace, self.ns_lower, self.ns_upper, self.ns_upper)
4792        )
4793        for i in self.ifaces:
4794            self.outfile.write(
4795                self.docbook_gen.expand(
4796                    "/**\n"
4797                    " * %sobject_skeleton_set_%s:\n"
4798                    " * @object: A #%sObjectSkeleton.\n"
4799                    " * @interface_: (nullable): A #%s or %%NULL to clear the interface.\n"
4800                    " *\n"
4801                    " * Sets the #%s instance for the D-Bus interface #%s on @object.\n"
4802                    % (
4803                        self.ns_lower,
4804                        i.name_upper.lower(),
4805                        self.namespace,
4806                        i.camel_name,
4807                        i.camel_name,
4808                        i.name,
4809                    ),
4810                    False,
4811                )
4812            )
4813            self.write_gtkdoc_deprecated_and_since_and_close(i, self.outfile, 0)
4814            self.outfile.write(
4815                "void %sobject_skeleton_set_%s (%sObjectSkeleton *object, %s *interface_)\n"
4816                % (self.ns_lower, i.name_upper.lower(), self.namespace, i.camel_name)
4817            )
4818            self.outfile.write(
4819                "{\n"
4820                '  g_object_set (G_OBJECT (object), "%s", interface_, NULL);\n'
4821                "}\n"
4822                "\n" % (i.name_hyphen)
4823            )
4824        self.outfile.write("\n")
4825
4826    def generate_object_manager_client(self):
4827        self.outfile.write(
4828            "/* ------------------------------------------------------------------------\n"
4829            " * Code for ObjectManager client\n"
4830            " * ------------------------------------------------------------------------\n"
4831            " */\n"
4832            "\n"
4833        )
4834
4835        self.outfile.write(
4836            self.docbook_gen.expand(
4837                "/**\n"
4838                " * SECTION:%sObjectManagerClient\n"
4839                " * @title: %sObjectManagerClient\n"
4840                " * @short_description: Generated GDBusObjectManagerClient type\n"
4841                " *\n"
4842                " * This section contains a #GDBusObjectManagerClient that uses %sobject_manager_client_get_proxy_type() as the #GDBusProxyTypeFunc.\n"
4843                " */\n" % (self.namespace, self.namespace, self.ns_lower),
4844                False,
4845            )
4846        )
4847        self.outfile.write("\n")
4848
4849        self.outfile.write(
4850            self.docbook_gen.expand(
4851                "/**\n"
4852                " * %sObjectManagerClient:\n"
4853                " *\n"
4854                " * The #%sObjectManagerClient structure contains only private data and should only be accessed using the provided API.\n"
4855                % (self.namespace, self.namespace),
4856                False,
4857            )
4858        )
4859        self.outfile.write(" */\n")
4860        self.outfile.write("\n")
4861
4862        self.outfile.write(
4863            self.docbook_gen.expand(
4864                "/**\n"
4865                " * %sObjectManagerClientClass:\n"
4866                " * @parent_class: The parent class.\n"
4867                " *\n"
4868                " * Class structure for #%sObjectManagerClient.\n"
4869                % (self.namespace, self.namespace),
4870                False,
4871            )
4872        )
4873        self.outfile.write(" */\n")
4874        self.outfile.write("\n")
4875
4876        # class boilerplate
4877        self.outfile.write(
4878            "G_DEFINE_TYPE (%sObjectManagerClient, %sobject_manager_client, G_TYPE_DBUS_OBJECT_MANAGER_CLIENT)\n"
4879            "\n" % (self.namespace, self.ns_lower)
4880        )
4881
4882        # class boilerplate
4883        self.outfile.write(
4884            "static void\n"
4885            "%sobject_manager_client_init (%sObjectManagerClient *manager G_GNUC_UNUSED)\n"
4886            "{\n"
4887            "}\n"
4888            "\n" % (self.ns_lower, self.namespace)
4889        )
4890        self.outfile.write(
4891            "static void\n"
4892            "%sobject_manager_client_class_init (%sObjectManagerClientClass *klass G_GNUC_UNUSED)\n"
4893            "{\n"
4894            "}\n"
4895            "\n" % (self.ns_lower, self.namespace)
4896        )
4897
4898        self.outfile.write(
4899            self.docbook_gen.expand(
4900                "/**\n"
4901                " * %sobject_manager_client_get_proxy_type:\n"
4902                " * @manager: A #GDBusObjectManagerClient.\n"
4903                " * @object_path: The object path of the remote object (unused).\n"
4904                " * @interface_name: (nullable): Interface name of the remote object or %%NULL to get the object proxy #GType.\n"
4905                " * @user_data: User data (unused).\n"
4906                " *\n"
4907                " * A #GDBusProxyTypeFunc that maps @interface_name to the generated #GDBusObjectProxy derived and #GDBusProxy derived types.\n"
4908                " *\n"
4909                " * Returns: A #GDBusProxy derived #GType if @interface_name is not %%NULL, otherwise the #GType for #%sObjectProxy.\n"
4910                % (self.ns_lower, self.namespace),
4911                False,
4912            )
4913        )
4914        self.outfile.write(" */\n")
4915        self.outfile.write(
4916            "GType\n"
4917            "%sobject_manager_client_get_proxy_type (GDBusObjectManagerClient *manager G_GNUC_UNUSED, const gchar *object_path G_GNUC_UNUSED, const gchar *interface_name, gpointer user_data G_GNUC_UNUSED)\n"
4918            "{\n" % (self.ns_lower)
4919        )
4920        self.outfile.write(
4921            "  static gsize once_init_value = 0;\n"
4922            "  static GHashTable *lookup_hash;\n"
4923            "  GType ret;\n"
4924            "\n"
4925            "  if (interface_name == NULL)\n"
4926            "    return %sTYPE_OBJECT_PROXY;\n"
4927            "  if (g_once_init_enter (&once_init_value))\n"
4928            "    {\n"
4929            "      lookup_hash = g_hash_table_new (g_str_hash, g_str_equal);\n"
4930            % (self.ns_upper)
4931        )
4932        for i in self.ifaces:
4933            self.outfile.write(
4934                '      g_hash_table_insert (lookup_hash, (gpointer) "%s", GSIZE_TO_POINTER (%sTYPE_%s_PROXY));\n'
4935                % (i.name, i.ns_upper, i.name_upper)
4936            )
4937        self.outfile.write("      g_once_init_leave (&once_init_value, 1);\n" "    }\n")
4938        self.outfile.write(
4939            "  ret = (GType) GPOINTER_TO_SIZE (g_hash_table_lookup (lookup_hash, interface_name));\n"
4940            "  if (ret == (GType) 0)\n"
4941            "    ret = G_TYPE_DBUS_PROXY;\n"
4942        )
4943        self.outfile.write("  return ret;\n" "}\n" "\n")
4944
4945        # constructors
4946        self.outfile.write(
4947            self.docbook_gen.expand(
4948                "/**\n"
4949                " * %sobject_manager_client_new:\n"
4950                " * @connection: A #GDBusConnection.\n"
4951                " * @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.\n"
4952                " * @name: (nullable): A bus name (well-known or unique) or %%NULL if @connection is not a message bus connection.\n"
4953                " * @object_path: An object path.\n"
4954                " * @cancellable: (nullable): A #GCancellable or %%NULL.\n"
4955                " * @callback: A #GAsyncReadyCallback to call when the request is satisfied.\n"
4956                " * @user_data: User data to pass to @callback.\n"
4957                " *\n"
4958                " * Asynchronously creates #GDBusObjectManagerClient using %sobject_manager_client_get_proxy_type() as the #GDBusProxyTypeFunc. See g_dbus_object_manager_client_new() for more details.\n"
4959                " *\n"
4960                " * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).\n"
4961                " * You can then call %sobject_manager_client_new_finish() to get the result of the operation.\n"
4962                " *\n"
4963                " * See %sobject_manager_client_new_sync() for the synchronous, blocking version of this constructor.\n"
4964                % (self.ns_lower, self.ns_lower, self.ns_lower, self.ns_lower),
4965                False,
4966            )
4967        )
4968        self.outfile.write(" */\n")
4969        self.outfile.write(
4970            "void\n"
4971            "%sobject_manager_client_new (\n"
4972            "    GDBusConnection        *connection,\n"
4973            "    GDBusObjectManagerClientFlags  flags,\n"
4974            "    const gchar            *name,\n"
4975            "    const gchar            *object_path,\n"
4976            "    GCancellable           *cancellable,\n"
4977            "    GAsyncReadyCallback     callback,\n"
4978            "    gpointer                user_data)\n"
4979            "{\n"
4980            '  g_async_initable_new_async (%sTYPE_OBJECT_MANAGER_CLIENT, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "flags", flags, "name", name, "connection", connection, "object-path", object_path, "get-proxy-type-func", %sobject_manager_client_get_proxy_type, NULL);\n'
4981            "}\n"
4982            "\n" % (self.ns_lower, self.ns_upper, self.ns_lower)
4983        )
4984        self.outfile.write(
4985            "/**\n"
4986            " * %sobject_manager_client_new_finish:\n"
4987            " * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %sobject_manager_client_new().\n"
4988            " * @error: Return location for error or %%NULL\n"
4989            " *\n"
4990            " * Finishes an operation started with %sobject_manager_client_new().\n"
4991            " *\n"
4992            " * Returns: (transfer full) (type %sObjectManagerClient): The constructed object manager client or %%NULL if @error is set.\n"
4993            % (self.ns_lower, self.ns_lower, self.ns_lower, self.namespace)
4994        )
4995        self.outfile.write(" */\n")
4996        self.outfile.write(
4997            "GDBusObjectManager *\n"
4998            "%sobject_manager_client_new_finish (\n"
4999            "    GAsyncResult        *res,\n"
5000            "    GError             **error)\n"
5001            "{\n"
5002            "  GObject *ret;\n"
5003            "  GObject *source_object;\n"
5004            "  source_object = g_async_result_get_source_object (res);\n"
5005            "  ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);\n"
5006            "  g_object_unref (source_object);\n"
5007            "  if (ret != NULL)\n"
5008            "    return G_DBUS_OBJECT_MANAGER (ret);\n"
5009            "  else\n"
5010            "    return NULL;\n"
5011            "}\n"
5012            "\n" % (self.ns_lower)
5013        )
5014        self.outfile.write(
5015            self.docbook_gen.expand(
5016                "/**\n"
5017                " * %sobject_manager_client_new_sync:\n"
5018                " * @connection: A #GDBusConnection.\n"
5019                " * @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.\n"
5020                " * @name: (nullable): A bus name (well-known or unique) or %%NULL if @connection is not a message bus connection.\n"
5021                " * @object_path: An object path.\n"
5022                " * @cancellable: (nullable): A #GCancellable or %%NULL.\n"
5023                " * @error: Return location for error or %%NULL\n"
5024                " *\n"
5025                " * Synchronously creates #GDBusObjectManagerClient using %sobject_manager_client_get_proxy_type() as the #GDBusProxyTypeFunc. See g_dbus_object_manager_client_new_sync() for more details.\n"
5026                " *\n"
5027                " * The calling thread is blocked until a reply is received.\n"
5028                " *\n"
5029                " * See %sobject_manager_client_new() for the asynchronous version of this constructor.\n"
5030                " *\n"
5031                " * Returns: (transfer full) (type %sObjectManagerClient): The constructed object manager client or %%NULL if @error is set.\n"
5032                % (self.ns_lower, self.ns_lower, self.ns_lower, self.namespace),
5033                False,
5034            )
5035        )
5036        self.outfile.write(" */\n")
5037        self.outfile.write(
5038            "GDBusObjectManager *\n"
5039            "%sobject_manager_client_new_sync (\n"
5040            "    GDBusConnection        *connection,\n"
5041            "    GDBusObjectManagerClientFlags  flags,\n"
5042            "    const gchar            *name,\n"
5043            "    const gchar            *object_path,\n"
5044            "    GCancellable           *cancellable,\n"
5045            "    GError                **error)\n"
5046            "{\n"
5047            "  GInitable *ret;\n"
5048            '  ret = g_initable_new (%sTYPE_OBJECT_MANAGER_CLIENT, cancellable, error, "flags", flags, "name", name, "connection", connection, "object-path", object_path, "get-proxy-type-func", %sobject_manager_client_get_proxy_type, NULL);\n'
5049            "  if (ret != NULL)\n"
5050            "    return G_DBUS_OBJECT_MANAGER (ret);\n"
5051            "  else\n"
5052            "    return NULL;\n"
5053            "}\n"
5054            "\n" % (self.ns_lower, self.ns_upper, self.ns_lower)
5055        )
5056        self.outfile.write("\n")
5057        self.outfile.write(
5058            self.docbook_gen.expand(
5059                "/**\n"
5060                " * %sobject_manager_client_new_for_bus:\n"
5061                " * @bus_type: A #GBusType.\n"
5062                " * @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.\n"
5063                " * @name: A bus name (well-known or unique).\n"
5064                " * @object_path: An object path.\n"
5065                " * @cancellable: (nullable): A #GCancellable or %%NULL.\n"
5066                " * @callback: A #GAsyncReadyCallback to call when the request is satisfied.\n"
5067                " * @user_data: User data to pass to @callback.\n"
5068                " *\n"
5069                " * Like %sobject_manager_client_new() but takes a #GBusType instead of a #GDBusConnection.\n"
5070                " *\n"
5071                " * When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).\n"
5072                " * You can then call %sobject_manager_client_new_for_bus_finish() to get the result of the operation.\n"
5073                " *\n"
5074                " * See %sobject_manager_client_new_for_bus_sync() for the synchronous, blocking version of this constructor.\n"
5075                % (self.ns_lower, self.ns_lower, self.ns_lower, self.ns_lower),
5076                False,
5077            )
5078        )
5079        self.outfile.write(" */\n")
5080        self.outfile.write(
5081            "void\n"
5082            "%sobject_manager_client_new_for_bus (\n"
5083            "    GBusType                bus_type,\n"
5084            "    GDBusObjectManagerClientFlags  flags,\n"
5085            "    const gchar            *name,\n"
5086            "    const gchar            *object_path,\n"
5087            "    GCancellable           *cancellable,\n"
5088            "    GAsyncReadyCallback     callback,\n"
5089            "    gpointer                user_data)\n"
5090            "{\n"
5091            '  g_async_initable_new_async (%sTYPE_OBJECT_MANAGER_CLIENT, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "flags", flags, "name", name, "bus-type", bus_type, "object-path", object_path, "get-proxy-type-func", %sobject_manager_client_get_proxy_type, NULL);\n'
5092            "}\n"
5093            "\n" % (self.ns_lower, self.ns_upper, self.ns_lower)
5094        )
5095        self.outfile.write(
5096            "/**\n"
5097            " * %sobject_manager_client_new_for_bus_finish:\n"
5098            " * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %sobject_manager_client_new_for_bus().\n"
5099            " * @error: Return location for error or %%NULL\n"
5100            " *\n"
5101            " * Finishes an operation started with %sobject_manager_client_new_for_bus().\n"
5102            " *\n"
5103            " * Returns: (transfer full) (type %sObjectManagerClient): The constructed object manager client or %%NULL if @error is set.\n"
5104            % (self.ns_lower, self.ns_lower, self.ns_lower, self.namespace)
5105        )
5106        self.outfile.write(" */\n")
5107        self.outfile.write(
5108            "GDBusObjectManager *\n"
5109            "%sobject_manager_client_new_for_bus_finish (\n"
5110            "    GAsyncResult        *res,\n"
5111            "    GError             **error)\n"
5112            "{\n"
5113            "  GObject *ret;\n"
5114            "  GObject *source_object;\n"
5115            "  source_object = g_async_result_get_source_object (res);\n"
5116            "  ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);\n"
5117            "  g_object_unref (source_object);\n"
5118            "  if (ret != NULL)\n"
5119            "    return G_DBUS_OBJECT_MANAGER (ret);\n"
5120            "  else\n"
5121            "    return NULL;\n"
5122            "}\n"
5123            "\n" % (self.ns_lower)
5124        )
5125        self.outfile.write(
5126            self.docbook_gen.expand(
5127                "/**\n"
5128                " * %sobject_manager_client_new_for_bus_sync:\n"
5129                " * @bus_type: A #GBusType.\n"
5130                " * @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.\n"
5131                " * @name: A bus name (well-known or unique).\n"
5132                " * @object_path: An object path.\n"
5133                " * @cancellable: (nullable): A #GCancellable or %%NULL.\n"
5134                " * @error: Return location for error or %%NULL\n"
5135                " *\n"
5136                " * Like %sobject_manager_client_new_sync() but takes a #GBusType instead of a #GDBusConnection.\n"
5137                " *\n"
5138                " * The calling thread is blocked until a reply is received.\n"
5139                " *\n"
5140                " * See %sobject_manager_client_new_for_bus() for the asynchronous version of this constructor.\n"
5141                " *\n"
5142                " * Returns: (transfer full) (type %sObjectManagerClient): The constructed object manager client or %%NULL if @error is set.\n"
5143                % (self.ns_lower, self.ns_lower, self.ns_lower, self.namespace),
5144                False,
5145            )
5146        )
5147        self.outfile.write(" */\n")
5148        self.outfile.write(
5149            "GDBusObjectManager *\n"
5150            "%sobject_manager_client_new_for_bus_sync (\n"
5151            "    GBusType                bus_type,\n"
5152            "    GDBusObjectManagerClientFlags  flags,\n"
5153            "    const gchar            *name,\n"
5154            "    const gchar            *object_path,\n"
5155            "    GCancellable           *cancellable,\n"
5156            "    GError                **error)\n"
5157            "{\n"
5158            "  GInitable *ret;\n"
5159            '  ret = g_initable_new (%sTYPE_OBJECT_MANAGER_CLIENT, cancellable, error, "flags", flags, "name", name, "bus-type", bus_type, "object-path", object_path, "get-proxy-type-func", %sobject_manager_client_get_proxy_type, NULL);\n'
5160            "  if (ret != NULL)\n"
5161            "    return G_DBUS_OBJECT_MANAGER (ret);\n"
5162            "  else\n"
5163            "    return NULL;\n"
5164            "}\n"
5165            "\n" % (self.ns_lower, self.ns_upper, self.ns_lower)
5166        )
5167        self.outfile.write("\n")
5168
5169    # ---------------------------------------------------------------------------------------------------
5170
5171    def write_gtkdoc_deprecated_and_since_and_close(self, obj, f, indent):
5172        if len(obj.since) > 0:
5173            f.write("%*s *\n" "%*s * Since: %s\n" % (indent, "", indent, "", obj.since))
5174        if obj.deprecated:
5175            if isinstance(obj, dbustypes.Interface):
5176                thing = "The D-Bus interface"
5177            elif isinstance(obj, dbustypes.Method):
5178                thing = "The D-Bus method"
5179            elif isinstance(obj, dbustypes.Signal):
5180                thing = "The D-Bus signal"
5181            elif isinstance(obj, dbustypes.Property):
5182                thing = "The D-Bus property"
5183            else:
5184                print_error('Cannot handle object "{}"'.format(obj))
5185            f.write(
5186                self.docbook_gen.expand(
5187                    "%*s *\n"
5188                    "%*s * Deprecated: %s has been deprecated.\n"
5189                    % (indent, "", indent, "", thing),
5190                    False,
5191                )
5192            )
5193        f.write("%*s */\n" % (indent, ""))
5194
5195    # ---------------------------------------------------------------------------------------------------
5196
5197    def generate_interface_intro(self, i):
5198        self.outfile.write(
5199            "/* ------------------------------------------------------------------------\n"
5200            " * Code for interface %s\n"
5201            " * ------------------------------------------------------------------------\n"
5202            " */\n"
5203            "\n" % (i.name)
5204        )
5205
5206        self.outfile.write(
5207            self.docbook_gen.expand(
5208                "/**\n"
5209                " * SECTION:%s\n"
5210                " * @title: %s\n"
5211                " * @short_description: Generated C code for the %s D-Bus interface\n"
5212                " *\n"
5213                " * This section contains code for working with the #%s D-Bus interface in C.\n"
5214                " */\n" % (i.camel_name, i.camel_name, i.name, i.name),
5215                False,
5216            )
5217        )
5218        self.outfile.write("\n")
5219
5220    def generate(self):
5221        self.generate_body_preamble()
5222        for i in self.ifaces:
5223            self.generate_interface_intro(i)
5224            self.generate_introspection_for_interface(i)
5225            self.generate_interface(i)
5226            self.generate_property_accessors(i)
5227            self.generate_signal_emitters(i)
5228            self.generate_method_calls(i)
5229            self.generate_method_completers(i)
5230            self.generate_proxy(i)
5231            self.generate_skeleton(i)
5232        if self.generate_objmanager:
5233            self.generate_object()
5234            self.generate_object_manager_client()
5235