[glibmm] Add Gio::DBus::ObjectManager*



commit d9ebdec1ed23dfbe583b712314b792a2f0093196
Author: Kjell Ahlstedt <kjellahlstedt gmail com>
Date:   Thu Jul 18 15:58:33 2019 +0200

    Add Gio::DBus::ObjectManager*
    
    Add Gio::DBus::ObjectManager, Gio::DBus::ObjectManagerClient and
    Gio::DBus::ObjectManagerServer. Fixes #43

 gio/giomm.h                         |   3 +
 gio/src/dbusobjectmanager.ccg       |  42 +++++
 gio/src/dbusobjectmanager.hg        | 107 ++++++++++++
 gio/src/dbusobjectmanagerclient.ccg | 154 ++++++++++++++++
 gio/src/dbusobjectmanagerclient.hg  | 337 ++++++++++++++++++++++++++++++++++++
 gio/src/dbusobjectmanagerserver.ccg |  17 ++
 gio/src/dbusobjectmanagerserver.hg  | 103 +++++++++++
 gio/src/filelist.am                 |   3 +
 gio/src/gio_docs_override.xml       |   1 +
 gio/src/gio_vfuncs.defs             |  29 ++++
 tools/m4/convert_gio.m4             |   6 +-
 11 files changed, 801 insertions(+), 1 deletion(-)
---
diff --git a/gio/giomm.h b/gio/giomm.h
index a72ef3fc..30ba71d7 100644
--- a/gio/giomm.h
+++ b/gio/giomm.h
@@ -55,6 +55,9 @@
 #include <giomm/dbusmessage.h>
 #include <giomm/dbusmethodinvocation.h>
 #include <giomm/dbusobject.h>
+#include <giomm/dbusobjectmanager.h>
+#include <giomm/dbusobjectmanagerclient.h>
+#include <giomm/dbusobjectmanagerserver.h>
 #include <giomm/dbusobjectproxy.h>
 #include <giomm/dbusobjectskeleton.h>
 #include <giomm/dbusownname.h>
diff --git a/gio/src/dbusobjectmanager.ccg b/gio/src/dbusobjectmanager.ccg
new file mode 100644
index 00000000..ace8282f
--- /dev/null
+++ b/gio/src/dbusobjectmanager.ccg
@@ -0,0 +1,42 @@
+/* Copyright (C) 2019 The giomm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gio/gio.h>
+#include <giomm/dbusobject.h>
+#include <giomm/dbusinterface.h>
+
+namespace
+{
+// Used in call to g_list_copy_deep().
+void* list_copy_ref(const void* src, void* /* data */)
+{
+  return g_object_ref(const_cast<void*>(src));
+}
+
+// Define some replacements for Glib::unwrap_copy().
+// Can't use the template function in glibmm/wrap.h, because interface classes
+// don't override Glib::ObjectBase::gobj_copy(), which returns a GObject*.
+GDBusObject* local_unwrap_copy(const Glib::RefPtr<Gio::DBus::Object>& ptr)
+{
+  return ptr ? reinterpret_cast<GDBusObject*>(ptr->gobj_copy()) : nullptr;
+}
+
+GDBusInterface* local_unwrap_copy(const Glib::RefPtr<Gio::DBus::Interface>& ptr)
+{
+  return ptr ? reinterpret_cast<GDBusInterface*>(ptr->gobj_copy()) : nullptr;
+}
+
+} // anonymous namespace
diff --git a/gio/src/dbusobjectmanager.hg b/gio/src/dbusobjectmanager.hg
new file mode 100644
index 00000000..00f60cab
--- /dev/null
+++ b/gio/src/dbusobjectmanager.hg
@@ -0,0 +1,107 @@
+/* Copyright (C) 2019 The giomm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glibmm/interface.h>
+#include <glibmm/ustring.h>
+#include <vector>
+
+_DEFS(giomm,gio)
+_PINCLUDE(glibmm/private/interface_p.h)
+_PINCLUDE(gio/gio.h)
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+typedef struct _GDBusObjectManagerIface GDBusObjectManagerIface;
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+namespace Gio
+{
+
+namespace DBus
+{
+class Interface;
+class Object;
+
+_GMMPROC_EXTRA_NAMESPACE(DBus)
+
+/** Base type for D-Bus object managers.
+ *
+ * The %Gio::DBus::ObjectManager type is the base type for service- and
+ * client-side implementations of the standardized
+ * <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager";>
+ * org.freedesktop.DBus.ObjectManager</a> interface.
+ *
+ * See Gio::DBus::ObjectManagerClient for the client-side implementation
+ * and Gio::DBus::ObjectManagerServer for the service-side implementation.
+ *
+ * @newin{2,62}
+ * @ingroup DBus
+ */
+class ObjectManager : public Glib::Interface
+{
+  _CLASS_INTERFACE(ObjectManager, GDBusObjectManager, G_DBUS_OBJECT_MANAGER, GDBusObjectManagerIface)
+
+public:
+  _WRAP_METHOD(Glib::ustring get_object_path() const, g_dbus_object_manager_get_object_path)
+
+#m4 _CONVERSION(`GList*',`std::vector<Glib::RefPtr<Gio::DBus::Object>>',
+#m4   `Glib::ListHandler<Glib::RefPtr<Gio::DBus::Object>>::list_to_vector($3, Glib::OWNERSHIP_DEEP)')
+  _WRAP_METHOD(std::vector<Glib::RefPtr<Gio::DBus::Object>> get_objects(), g_dbus_object_manager_get_objects)
+#m4 _CONVERSION(`GList*',`std::vector<Glib::RefPtr<const Gio::DBus::Object>>',
+#m4   `Glib::ListHandler<Glib::RefPtr<const Gio::DBus::Object>>::list_to_vector($3, Glib::OWNERSHIP_DEEP)')
+  _WRAP_METHOD(std::vector<Glib::RefPtr<const Gio::DBus::Object>> get_objects() const, 
g_dbus_object_manager_get_objects)
+
+  _WRAP_METHOD(Glib::RefPtr<Gio::DBus::Object> get_object(const Glib::ustring& object_path), 
g_dbus_object_manager_get_object)
+  _WRAP_METHOD(Glib::RefPtr<const Gio::DBus::Object> get_object(const Glib::ustring& object_path) const,
+    g_dbus_object_manager_get_object, constversion)
+
+  _WRAP_METHOD(Glib::RefPtr<Gio::DBus::Interface> get_interface(const Glib::ustring& object_path,
+    const Glib::ustring& interface_name), g_dbus_object_manager_get_interface)
+  _WRAP_METHOD(Glib::RefPtr<const Gio::DBus::Interface> get_interface(const Glib::ustring& object_path,
+    const Glib::ustring& interface_name) const, g_dbus_object_manager_get_interface, constversion)
+
+#m4 _CONVERSION(`GDBusObject*',`const Glib::RefPtr<Gio::DBus::Object>&',`Glib::wrap($3, true)')
+  _WRAP_SIGNAL(void object_added(const Glib::RefPtr<Gio::DBus::Object>& object), "object-added")
+  _WRAP_SIGNAL(void object_removed(const Glib::RefPtr<Gio::DBus::Object>& object), "object-removed")
+
+  // The parameter name 'interface' can cause compilation errors with MinGW.
+  // See https://bugzilla.gnome.org/show_bug.cgi?id=735137
+  // The parameter name in glib is 'interface'.
+#m4 _CONVERSION(`GDBusInterface*',`const Glib::RefPtr<Gio::DBus::Interface>&',`Glib::wrap($3, true)')
+  _WRAP_SIGNAL(void interface_added(const Glib::RefPtr<Gio::DBus::Object>& object,
+    const Glib::RefPtr<Gio::DBus::Interface>& iface), "interface-added")
+  _WRAP_SIGNAL(void interface_removed(const Glib::RefPtr<Gio::DBus::Object>& object,
+    const Glib::RefPtr<Gio::DBus::Interface>& iface), "interface-removed")
+
+protected:
+#m4 _CONVERSION(`Glib::ustring', `const gchar*', `$3.c_str()')
+  _WRAP_VFUNC(Glib::ustring get_object_path() const, "get_object_path", keep_return)
+
+#m4 _CONVERSION(`std::vector<Glib::RefPtr<Gio::DBus::Object>>',`GList*',
+#m4   `g_list_copy_deep(Glib::ListHandler<Glib::RefPtr<Gio::DBus::Object>>::vector_to_list($3).data(), 
list_copy_ref, nullptr)')
+  _WRAP_VFUNC(std::vector<Glib::RefPtr<Gio::DBus::Object>> get_objects() const, "get_objects")
+
+  // Can't use refreturn_ctype here. It generates a call to Glib::unwrap_copy(), which
+  // can't be used for Glib::Interface classes. They have no gobj_copy() method.
+#m4 _CONVERSION(`Glib::RefPtr<Gio::DBus::Object>',`GDBusObject*',`local_unwrap_copy($3)')
+  _WRAP_VFUNC(Glib::RefPtr<Gio::DBus::Object> get_object(const Glib::ustring& object_path) const, 
"get_object")
+#m4 _CONVERSION(`Glib::RefPtr<Gio::DBus::Interface>',`GDBusInterface*',`local_unwrap_copy($3)')
+  _WRAP_VFUNC(Glib::RefPtr<Gio::DBus::Interface> get_interface(const Glib::ustring& object_path,
+    const Glib::ustring& interface_name) const, "get_interface")
+};
+
+} // namespace DBus
+
+} // namespace Gio
diff --git a/gio/src/dbusobjectmanagerclient.ccg b/gio/src/dbusobjectmanagerclient.ccg
new file mode 100644
index 00000000..76cc808e
--- /dev/null
+++ b/gio/src/dbusobjectmanagerclient.ccg
@@ -0,0 +1,154 @@
+/* Copyright (C) 2019 The giomm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gio/gio.h>
+
+namespace
+{
+GType get_proxy_type_callback(GDBusObjectManagerClient* manager,
+  const gchar* object_path, const gchar* interface_name, gpointer user_data)
+{
+  auto slot_proxy_type = static_cast<Gio::DBus::ObjectManagerClient::SlotProxyType*>(user_data);
+  try
+  {
+    return (*slot_proxy_type)(Glib::wrap(manager, true),
+           Glib::convert_const_gchar_ptr_to_ustring(object_path),
+           Glib::convert_const_gchar_ptr_to_ustring(interface_name));
+  }
+  catch (...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+  return 0;
+}
+
+} // anonymous namespace
+
+namespace Gio
+{
+
+namespace DBus
+{
+using MapChangedProperties = ObjectManagerClient::MapChangedProperties;
+using Flags = ObjectManagerClient::Flags;
+
+ObjectManagerClient::ObjectManagerClient(const Glib::RefPtr<Connection>& connection,
+  const Glib::ustring& name, const Glib::ustring& object_path,
+  const SlotAsyncReady& slot_async_ready,
+  const Glib::RefPtr<Cancellable>& cancellable,
+  const SlotProxyType& slot_proxy_type, Flags flags)
+: _CONSTRUCT("connection", Glib::unwrap(connection),
+  "flags", static_cast<GDBusObjectManagerClientFlags>(flags),
+  "name", Glib::c_str_or_nullptr(name),
+  "object-path", Glib::c_str_or_nullptr(object_path),
+  "get-proxy-type-func", slot_proxy_type ? get_proxy_type_callback : nullptr,
+  "get-proxy-type-user-data",  slot_proxy_type ? new SlotProxyType(slot_proxy_type) : nullptr,
+  "get-proxy-type-destroy-notify", slot_proxy_type ? Glib::destroy_notify_delete<SlotProxyType> : nullptr
+)
+{
+  if (slot_async_ready)
+  {
+    // Asynchronous construction
+    if (cancellable)
+      init_async(slot_async_ready, cancellable);
+    else
+      init_async(slot_async_ready);
+  }
+  else
+  {
+    // Synchronous construction
+    if (cancellable)
+      init(cancellable);
+    else
+      init();
+  }
+}
+
+ObjectManagerClient::ObjectManagerClient(BusType bus_type,
+  const Glib::ustring& name, const Glib::ustring& object_path,
+  const SlotAsyncReady& slot_async_ready,
+  const Glib::RefPtr<Cancellable>& cancellable,
+  const SlotProxyType& slot_proxy_type, Flags flags)
+: _CONSTRUCT("bus-type", bus_type,
+  "flags", static_cast<GDBusObjectManagerClientFlags>(flags),
+  "name", Glib::c_str_or_nullptr(name),
+  "object-path", Glib::c_str_or_nullptr(object_path),
+  "get-proxy-type-func", slot_proxy_type ? get_proxy_type_callback : nullptr,
+  "get-proxy-type-user-data",  slot_proxy_type ? new SlotProxyType(slot_proxy_type) : nullptr,
+  "get-proxy-type-destroy-notify", slot_proxy_type ? Glib::destroy_notify_delete<SlotProxyType> : nullptr
+)
+{
+  if (slot_async_ready)
+  {
+    // Asynchronous construction
+    if (cancellable)
+      init_async(slot_async_ready, cancellable);
+    else
+      init_async(slot_async_ready);
+  }
+  else
+  {
+    // Synchronous construction
+    if (cancellable)
+      init(cancellable);
+    else
+      init();
+  }
+}
+
+void ObjectManagerClient::create(const Glib::RefPtr<Connection>& connection,
+  const Glib::ustring& name, const Glib::ustring& object_path,
+  const SlotAsyncReady& slot_async_ready,
+  const Glib::RefPtr<Cancellable>& cancellable,
+  const SlotProxyType& slot_proxy_type, Flags flags)
+{
+  // This does not return anything, because it is async - see create_finish().
+  ObjectManagerClient(connection, name, object_path, slot_async_ready, cancellable, slot_proxy_type, flags);
+}
+
+Glib::RefPtr<Gio::DBus::ObjectManagerClient> ObjectManagerClient::create_sync(
+  const Glib::RefPtr<Connection>& connection,
+  const Glib::ustring& name, const Glib::ustring& object_path,
+  const Glib::RefPtr<Cancellable>& cancellable,
+  const SlotProxyType& slot_proxy_type, Flags flags)
+{
+  return Glib::make_refptr_for_instance<ObjectManagerClient>(
+    new ObjectManagerClient(connection, name, object_path, {}, cancellable, slot_proxy_type, flags));
+}
+
+void ObjectManagerClient::create_for_bus(BusType bus_type,
+  const Glib::ustring& name, const Glib::ustring& object_path,
+  const SlotAsyncReady& slot_async_ready,
+  const Glib::RefPtr<Cancellable>& cancellable,
+  const SlotProxyType& slot_proxy_type, Flags flags)
+{
+  // This does not return anything, because it is async - see create_for_bus_finish().
+  ObjectManagerClient(bus_type, name, object_path, slot_async_ready, cancellable, slot_proxy_type, flags);
+}
+
+Glib::RefPtr<Gio::DBus::ObjectManagerClient> ObjectManagerClient::create_for_bus_sync(
+  BusType bus_type,
+  const Glib::ustring& name, const Glib::ustring& object_path,
+  const Glib::RefPtr<Cancellable>& cancellable,
+  const SlotProxyType& slot_proxy_type, Flags flags)
+{
+  return Glib::make_refptr_for_instance<ObjectManagerClient>(
+    new ObjectManagerClient(bus_type, name, object_path, {}, cancellable, slot_proxy_type, flags));
+}
+
+} // namespace DBus
+
+} // namespace Gio
diff --git a/gio/src/dbusobjectmanagerclient.hg b/gio/src/dbusobjectmanagerclient.hg
new file mode 100644
index 00000000..94e6c55a
--- /dev/null
+++ b/gio/src/dbusobjectmanagerclient.hg
@@ -0,0 +1,337 @@
+/* Copyright (C) 2019 The giomm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glibmm/object.h>
+#include <giomm/asyncresult.h>
+#include <giomm/dbusobjectmanager.h>
+#include <giomm/initable.h>
+#include <giomm/asyncinitable.h>
+#include <giomm/dbusconnection.h>
+#include <giomm/dbusobjectproxy.h>
+#include <giomm/dbusproxy.h>
+
+_DEFS(giomm,gio)
+_PINCLUDE(glibmm/private/object_p.h)
+
+namespace Gio
+{
+
+namespace DBus
+{
+//The GMMPROC_EXTRA_NAMESPACE() macro is a hint to generate_wrap_init.pl to put it in the DBus sub-namespace
+_GMMPROC_EXTRA_NAMESPACE(DBus)
+
+/** Client-side object manager.
+ *
+ * %Gio::DBus::ObjectManagerClient is used to create, monitor and delete object
+ * proxies for remote objects exported by a Gio::DBus::ObjectManagerServer (or any
+ * code implementing the
+ * <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager";>
+ * org.freedesktop.DBus.ObjectManager</a> interface.
+ *
+ * Once an instance of this type has been created, you can connect to
+ * Gio::DBus::ObjectManager::signal_object_added() and
+ * Gio::DBus::ObjectManager::signal_object_removed() and inspect the
+ * Gio::DBus::Object objects returned by Gio::DBus::ObjectManager::get_objects().
+ *
+ * If the name for a %Gio::DBus::ObjectManagerClient is not owned by anyone at
+ * object construction time, the default behavior is to request the
+ * message bus to launch an owner for the name. This behavior can be
+ * disabled using the Gio::DBus::ObjectManagerClient::Flags::DO_NOT_AUTO_START
+ * flag. It's also worth noting that this only works if the name of
+ * interest is activatable in the first place. E.g. in some cases it
+ * is not possible to launch an owner for the requested name. In this
+ * case, %ObjectManagerClient object construction still succeeds but
+ * there will be no object proxies
+ * (e.g. get_objects() returns an empty vector) and
+ * property_name_owner() is an empty string.
+ *
+ * The owner of the requested name can come and go (for example
+ * consider a system service being restarted) – %ObjectManagerClient
+ * handles this case too; simply connect to property_name_owner().signal_changed()
+ * to watch for changes on property_name_owner().
+ * When the name owner vanishes, the behavior is that
+ * property_name_owner() is set to an empty string (this includes
+ * emission of signal_changed()) and then
+ * signal_object_removed() signals are synthesized
+ * for all currently existing object proxies. Since
+ * property_name_owner() is an empty string when this happens, you can
+ * use this information to disambiguate a synthesized signal from a
+ * genuine signal caused by object removal on the remote
+ * Gio::DBus::ObjectManager. Similarly, when a new name owner appears,
+ * signal_object_added() signals are synthesized
+ * while property_namename_owner() is still an empty string. Only when all
+ * object proxies have been added, property_name_owner()
+ * is set to the new name owner (this includes emission of the
+ * signal_changed()). Furthermore, you are guaranteed that
+ * property_name_owner() will alternate between a name owner
+ * (e.g. `:1.42`) and an empty string even in the case where
+ * the name of interest is atomically replaced.
+ *
+ * Ultimately, %ObjectManagerClient is used to obtain Gio::DBus::Proxy
+ * instances. All signals (including the
+ * org.freedesktop.DBus.Properties::PropertiesChanged signal)
+ * delivered to Gio::DBus::Proxy instances are guaranteed to originate
+ * from the name owner. This guarantee along with the behavior
+ * described above, means that certain race conditions including the
+ * "half the proxy is from the old owner and the other half is from
+ * the new owner" problem cannot happen.
+ *
+ * To avoid having the application connect to signals on the returned
+ * Gio::DBus::Object and Gio::DBus::Proxy objects,
+ * Gio::DBus::Object::signal_interface_added(),
+ * Gio::DBus::Object::signal_interface_removed(),
+ * Gio::DBus::Proxy::signal_properties_changed() and
+ * Gio::DBus::Proxy::signal_signal()
+ * are also emitted on the %ObjectManagerClient instance managing these
+ * objects. The signals emitted are
+ * signal_interface_added(), signal_interface_removed(),
+ * signal_interface_proxy_properties_changed() and
+ * signal_interface_proxy_signal().
+ *
+ * Note that all callbacks and signals are emitted in the
+ * thread-default main context
+ * that the %ObjectManagerClient object was constructed
+ * in. Additionally, the Gio::DBus::ObjectProxy and Gio::DBus::Proxy objects
+ * originating from the %ObjectManagerClient object will be created in
+ * the same context and, consequently, will deliver signals in the
+ * same main loop.
+ *
+ * @newin{2,62}
+ * @ingroup DBus
+ */
+class ObjectManagerClient
+: public Glib::Object,
+  public Initable,
+  public AsyncInitable,
+  public ObjectManager
+{
+  _CLASS_GOBJECT(ObjectManagerClient, GDBusObjectManagerClient, G_DBUS_OBJECT_MANAGER_CLIENT, Glib::Object, 
GObject)
+  _IMPLEMENTS_INTERFACE(Initable)
+  _IMPLEMENTS_INTERFACE(AsyncInitable)
+  _IMPLEMENTS_INTERFACE(DBus::ObjectManager)
+
+public:
+  _WRAP_ENUM(Flags, GDBusObjectManagerClientFlags, gtype_func g_dbus_object_manager_client_flags_get_type)
+
+  /** A slot that will be called to determine the GType to use for an interface proxy
+   * (if interface_name is not an empty string) or object proxy (if interface_name is
+   * an empty string).
+   *
+   * This function is called in the thread-default main loop that @a manager was constructed in.
+   *
+   * For instance:
+   * @code
+   * GType on_proxy_type(const Glib::RefPtr<Gio::DBus::ObjectManagerClient>& manager,
+   *       const Glib::ustring& object_path, const Glib::ustring& interface_name);
+   * @endcode
+   *
+   * @param manager A Gio::DBus::ObjectManagerClient.
+   * @param object_path The object path of the remote object.
+   * @param interface_name The interface name of the remote object, or an empty
+   *        string if a GDBusObjectProxy GType is requested.
+   * @returns A GType to use for the remote object. The returned type must be
+   *          a GDBusProxy or GDBusObjectProxy-derived type.
+   */
+  using SlotProxyType = sigc::slot<GType(const Glib::RefPtr<Gio::DBus::ObjectManagerClient>&,
+        const Glib::ustring&, const Glib::ustring&)>;
+
+protected:
+  ObjectManagerClient(const Glib::RefPtr<Connection>& connection,
+    const Glib::ustring& name,
+    const Glib::ustring& object_path,
+    const SlotAsyncReady& slot_async_ready,
+    const Glib::RefPtr<Cancellable>& cancellable,
+    const SlotProxyType& slot_proxy_type, Flags flags);
+
+  ObjectManagerClient(BusType bus_type,
+    const Glib::ustring& name,
+    const Glib::ustring& object_path,
+    const SlotAsyncReady& slot_async_ready,
+    const Glib::RefPtr<Cancellable>& cancellable,
+    const SlotProxyType& slot_proxy_type, Flags flags);
+  _IGNORE(g_dbus_object_manager_client_new, g_dbus_object_manager_client_new_for_bus,
+          g_dbus_object_manager_client_new_sync, g_dbus_object_manager_client_new_for_bus_sync)
+
+public:
+  /** Creates a new %Gio::DBus::ObjectManagerClient object.
+   *
+   * This is an asynchronous failable constructor. When the result is
+   * ready, @a slot_async_ready will be invoked in the
+   * thread-default main context of the thread you are calling this method from.
+   * You can then call create_finish() to get the result.
+   * See create_sync() for the synchronous version.
+   *
+   * @param connection A Gio::DBus::Connection.
+   * @param name The owner of the control object (unique or well-known name).
+   * @param object_path The object path of the control object.
+   * @param slot_async_ready A SlotAsyncReady slot to call when the request is satisfied.
+   * @param cancellable A Cancellable or an empty Glib::RefPtr.
+   * @param slot_proxy_type A SlotProxyType slot, or an empty slot to always construct
+   *        GDBusProxy or GDBusObjectProxy proxies.
+   * @param flags Zero or more flags from the Gio::DBus::ObjectManagerClient::Flags enumeration.
+   */
+  static void create(const Glib::RefPtr<Connection>& connection,
+    const Glib::ustring& name,
+    const Glib::ustring& object_path,
+    const SlotAsyncReady& slot_async_ready,
+    const Glib::RefPtr<Cancellable>& cancellable = {},
+    const SlotProxyType& slot_proxy_type = {},
+    Flags flags = Flags::NONE);
+
+  // g_dbus_object_manager_client_new_finish() and g_dbus_object_manager_client_new_for_bus_finish()
+  // return GDBusObjectManager pointers, although they are GDBusObjectManagerClient pointers.
+#m4 
_CONVERSION(`GDBusObjectManager*',`Glib::RefPtr<Gio::DBus::ObjectManagerClient>',`Glib::wrap((GDBusObjectManagerClient*)($3))')
+  /** Finishes an operation started with create().
+   *
+   * @param res An AsyncResult obtained from the SlotAsyncReady passed to create().
+   * @return A %Gio::DBus::ObjectManagerClient object. If an error has occurred,
+   *         a Glib::Error is thrown and nothing is returned.
+   * @throw Glib::Error.
+   */
+  _WRAP_METHOD(static Glib::RefPtr<Gio::DBus::ObjectManagerClient> create_finish(const 
Glib::RefPtr<AsyncResult>& res),
+    g_dbus_object_manager_client_new_finish, errthrow)
+
+  /** Creates a new %Gio::DBus::ObjectManagerClient object.
+   *
+   * This is a synchronous failable constructor - the calling thread is
+   * blocked until a reply is received. See create() for the asynchronous version.
+   *
+   * @param connection A Gio::DBus::Connection.
+   * @param name The owner of the control object (unique or well-known name).
+   * @param object_path The object path of the control object.
+   * @param cancellable A Cancellable or an empty Glib::RefPtr.
+   * @param slot_proxy_type A SlotProxyType slot, or an empty slot to always construct
+   *        GDBusProxy or GDBusObjectProxy proxies.
+   * @param flags Zero or more flags from the Gio::DBus::ObjectManagerClient::Flags enumeration.
+   * @throw Glib::Error
+   */
+  static Glib::RefPtr<Gio::DBus::ObjectManagerClient> create_sync(
+    const Glib::RefPtr<Connection>& connection,
+    const Glib::ustring& name,
+    const Glib::ustring& object_path,
+    const Glib::RefPtr<Cancellable>& cancellable = {},
+    const SlotProxyType& slot_proxy_type = {},
+    Flags flags = Flags::NONE);
+
+  /** Creates a new %Gio::DBus::ObjectManagerClient object.
+   *
+   * Like create() but takes a Gio::DBus::BusType instead of a Gio::DBus::Connection.
+   *
+   * This is an asynchronous failable constructor. When the result is
+   * ready, @a slot_async_ready will be invoked in the
+   * thread-default main context of the thread you are calling this method from.
+   * You can then call create_for_bus_finish() to get the result.
+   * See create_for_bus_sync() for the synchronous version.
+   *
+   * @param bus_type A Gio::DBus::BusType.
+   * @param name The owner of the control object (unique or well-known name).
+   * @param object_path The object path of the control object.
+   * @param slot_async_ready A SlotAsyncReady slot to call when the request is satisfied.
+   * @param cancellable A Cancellable or an empty Glib::RefPtr.
+   * @param slot_proxy_type A SlotProxyType slot, or an empty slot to always construct
+   *        GDBusProxy or GDBusObjectProxy proxies.
+   * @param flags Zero or more flags from the Gio::DBus::ObjectManagerClient::Flags enumeration.
+   */
+  static void create_for_bus(BusType bus_type,
+    const Glib::ustring& name,
+    const Glib::ustring& object_path,
+    const SlotAsyncReady& slot_async_ready,
+    const Glib::RefPtr<Cancellable>& cancellable = {},
+    const SlotProxyType& slot_proxy_type = {},
+    Flags flags = Flags::NONE);
+
+  /** Finishes an operation started with create_for_bus().
+   * 
+   * @param res An AsyncResult obtained from the SlotAsyncReady passed to create_for_bus().
+   * @return A %Gio::DBus::ObjectManagerClient object. If an error has occurred,
+   *         a Glib::Error is thrown and nothing is returned.
+   * @throw Glib::Error.
+   */
+  _WRAP_METHOD(static Glib::RefPtr<Gio::DBus::ObjectManagerClient> create_for_bus_finish(const 
Glib::RefPtr<AsyncResult>& res),
+    g_dbus_object_manager_client_new_for_bus_finish, errthrow)
+
+  /** Creates a new %Gio::DBus::ObjectManagerClient object.
+   *
+   * Like create_sync() but takes a Gio::DBus::BusType instead of a
+   * Gio::DBus::Connection.
+   *
+   * This is a synchronous failable constructor - the calling thread is
+   * blocked until a reply is received. See create_for_bus()
+   * for the asynchronous version.
+   *
+   * @param bus_type A Gio::DBus::BusType.
+   * @param name The owner of the control object (unique or well-known name).
+   * @param object_path The object path of the control object.
+   * @param cancellable A Cancellable or an empty Glib::RefPtr.
+   * @param slot_proxy_type A SlotProxyType slot, or an empty slot to always construct
+   *        GDBusProxy or GDBusObjectProxy proxies.
+   * @param flags Zero or more flags from the Gio::DBus::ObjectManagerClient::Flags enumeration.
+   * @throw Glib::Error
+   */
+  static Glib::RefPtr<Gio::DBus::ObjectManagerClient> create_for_bus_sync(
+    BusType bus_type,
+    const Glib::ustring& name,
+    const Glib::ustring& object_path,
+    const Glib::RefPtr<Cancellable>& cancellable = {},
+    const SlotProxyType& slot_proxy_type = {},
+    Flags flags = Flags::NONE);
+
+  _WRAP_METHOD(Glib::RefPtr<Connection> get_connection(), g_dbus_object_manager_client_get_connection, 
refreturn)
+  _WRAP_METHOD(Glib::RefPtr<const Connection> get_connection() const, 
g_dbus_object_manager_client_get_connection, refreturn, constversion)
+
+  _WRAP_METHOD(Flags get_flags() const, g_dbus_object_manager_client_get_flags)
+
+  _WRAP_METHOD(Glib::ustring get_name() const, g_dbus_object_manager_client_get_name)
+  _WRAP_METHOD(Glib::ustring get_name_owner() const, g_dbus_object_manager_client_get_name_owner)
+
+ _WRAP_PROPERTY("connection", Glib::RefPtr<Connection>)
+ _WRAP_PROPERTY("flags", Flags)
+ _WRAP_PROPERTY("object-path", Glib::ustring)
+ _WRAP_PROPERTY("name", Glib::ustring)
+ _WRAP_PROPERTY("name-owner", Glib::ustring)
+ //_WRAP_PROPERTY("bus-type", BusType) // write-only construct-only
+ // The get-proxy-type-func, get-proxy-type-user-data and get-proxy-type-destroy-notify properties
+ // can't be wrapped individually. Perhaps add set_slot_proxy_type() and get_slot_proxy_type() methods?
+
+#m4 _CONVERSION(`GDBusObjectProxy*',`const Glib::RefPtr<Gio::DBus::ObjectProxy>&',`Glib::wrap($3, true)')
+#m4 _CONVERSION(`GDBusProxy*',`const Glib::RefPtr<Gio::DBus::Proxy>&',`Glib::wrap($3, true)')
+#m4 _CONVERSION(`GVariant*', `const Glib::VariantContainerBase&', `Glib::VariantContainerBase($3, true)')
+#m4 _CONVERSION(`const Glib::VariantContainerBase&', `GVariant*', `const_cast<GVariant*>(($3).gobj())')
+  _WRAP_SIGNAL(void interface_proxy_signal(
+    const Glib::RefPtr<Gio::DBus::ObjectProxy>& object_proxy,
+    const Glib::RefPtr<Gio::DBus::Proxy>& interface_proxy,
+    const Glib::ustring& sender_name, const Glib::ustring& signal_name,
+    const Glib::VariantContainerBase& parameters), "interface-proxy-signal")
+
+  using MapChangedProperties = std::map<Glib::ustring, Glib::VariantBase>;
+
+  // The DBus API ensures that the variant changed_properties is of type "DICT<STRING,VARIANT>"
+#m4 _CONVERSION(`GVariant*', `const MapChangedProperties&', `Glib::Variant<MapChangedProperties>($3, 
true).get()')
+#m4 _CONVERSION(`const MapChangedProperties&', `GVariant*', 
`const_cast<GVariant*>(Glib::Variant<MapChangedProperties>::create($3).gobj())')
+#m4 _CONVERSION(`const std::vector<Glib::ustring>&', `const 
gchar*const*',`Glib::ArrayHandler<Glib::ustring>::vector_to_array($3).data()')
+#m4 _CONVERSION(`const gchar*const*', `const std::vector<Glib::ustring>&', 
`Glib::ArrayHandler<Glib::ustring>::array_to_vector($3, Glib::OWNERSHIP_NONE)')
+  _WRAP_SIGNAL(void interface_proxy_properties_changed(
+    const Glib::RefPtr<Gio::DBus::ObjectProxy>& object_proxy,
+    const Glib::RefPtr<Gio::DBus::Proxy>& interface_proxy,
+    const MapChangedProperties& changed_properties,
+    const std::vector<Glib::ustring>& invalidated_properties),
+    "interface-proxy-properties-changed")
+};
+
+} //namespace
+
+} // namespace Gio
diff --git a/gio/src/dbusobjectmanagerserver.ccg b/gio/src/dbusobjectmanagerserver.ccg
new file mode 100644
index 00000000..eb1c2b1c
--- /dev/null
+++ b/gio/src/dbusobjectmanagerserver.ccg
@@ -0,0 +1,17 @@
+/* Copyright (C) 2019 The giomm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gio/gio.h>
diff --git a/gio/src/dbusobjectmanagerserver.hg b/gio/src/dbusobjectmanagerserver.hg
new file mode 100644
index 00000000..1497d4b7
--- /dev/null
+++ b/gio/src/dbusobjectmanagerserver.hg
@@ -0,0 +1,103 @@
+/* Copyright (C) 2019 The giomm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glibmm/object.h>
+#include <giomm/dbusobjectmanager.h>
+#include <giomm/dbusconnection.h>
+#include <giomm/dbusobjectskeleton.h>
+
+_DEFS(giomm,gio)
+_PINCLUDE(glibmm/private/object_p.h)
+
+namespace Gio
+{
+
+namespace DBus
+{
+//The GMMPROC_EXTRA_NAMESPACE() macro is a hint to generate_wrap_init.pl to put it in the DBus sub-namespace
+_GMMPROC_EXTRA_NAMESPACE(DBus)
+
+/** Service-side object manager.
+ *
+ * %Gio::DBus::ObjectManagerServer is used to export Gio::DBus::Object instances using
+ * the standardized
+ * <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager";>
+ * org.freedesktop.DBus.ObjectManager</a> interface.
+ * For example, remote D-Bus clients can get all objects
+ * and properties in a single call. Additionally, any change in the
+ * object hierarchy is broadcast using signals. This means that D-Bus
+ * clients can keep caches up to date by only listening to D-Bus signals.
+ *
+ * The recommended path to export an object manager at is the path form of the
+ * well-known name of a D-Bus service, or below. For example, if a D-Bus service
+ * is available at the well-known name `net.example.ExampleService1`, the object
+ * manager should typically be exported at `/net/example/ExampleService1`, or
+ * below (to allow for multiple object managers in a service).
+ *
+ * It is supported, but not recommended, to export an object manager at the root
+ * path, `/`.
+ *
+ * See Gio::DBus::ObjectManagerClient for the client-side code that is
+ * intended to be used with %ObjectManagerServer or any D-Bus
+ * object implementing the org.freedesktop.DBus.ObjectManager interface.
+ *
+ * @newin{2,62}
+ * @ingroup DBus
+ */
+class ObjectManagerServer : public Glib::Object, public ObjectManager
+{
+  _CLASS_GOBJECT(ObjectManagerServer, GDBusObjectManagerServer, G_DBUS_OBJECT_MANAGER_SERVER, Glib::Object, 
GObject)
+  _IMPLEMENTS_INTERFACE(DBus::ObjectManager)
+
+protected:
+  _WRAP_CTOR(ObjectManagerServer(const Glib::ustring& object_path), g_dbus_object_manager_server_new)
+
+public:
+  /** Creates a new %Gio::DBus::ObjectManagerServer object.
+   *
+   * The returned server isn't yet exported on any connection. To do so,
+   * use set_connection(). Normally you want to export all of your objects
+   * before doing so to avoid Gio::DBus::ObjectManager::signal_interface_added()
+   * signals being emitted.
+   *
+   * @param object_path The object path to export the manager object at.
+   * @return A new %Gio::DBus::ObjectManagerServer object.
+   */
+  _WRAP_CREATE(const Glib::ustring& object_path)
+
+  _WRAP_METHOD(Glib::RefPtr<Connection> get_connection(), g_dbus_object_manager_server_get_connection)
+  _WRAP_METHOD(Glib::RefPtr<const Connection> get_connection() const,
+    g_dbus_object_manager_server_get_connection, constversion)
+  _WRAP_METHOD(void set_connection(const Glib::RefPtr<Connection>& connection),
+    g_dbus_object_manager_server_set_connection)
+
+  // The method can't be called export(). 'export' is a keyword in C++.
+  _WRAP_METHOD(void export_object(const Glib::RefPtr<Gio::DBus::ObjectSkeleton>& object),
+    g_dbus_object_manager_server_export)
+  _WRAP_METHOD(void export_uniquely(const Glib::RefPtr<Gio::DBus::ObjectSkeleton>& object),
+    g_dbus_object_manager_server_export_uniquely)
+  _WRAP_METHOD(bool is_exported(const Glib::RefPtr<Gio::DBus::ObjectSkeleton>& object) const,
+    g_dbus_object_manager_server_is_exported)
+  _WRAP_METHOD(bool unexport(const Glib::ustring& object_path),
+    g_dbus_object_manager_server_unexport)
+
+ _WRAP_PROPERTY("connection", Glib::RefPtr<Connection>)
+ _WRAP_PROPERTY("object-path", Glib::ustring)
+};
+
+} //namespace
+
+} // namespace Gio
diff --git a/gio/src/filelist.am b/gio/src/filelist.am
index 18a0eaf2..38f92d85 100644
--- a/gio/src/filelist.am
+++ b/gio/src/filelist.am
@@ -44,6 +44,9 @@ giomm_files_any_hg =                  \
        dbusmessage.hg                  \
        dbusmethodinvocation.hg         \
        dbusobject.hg                   \
+       dbusobjectmanager.hg \
+       dbusobjectmanagerclient.hg \
+       dbusobjectmanagerserver.hg \
        dbusobjectproxy.hg \
        dbusobjectskeleton.hg \
        dbusownname.hg                  \
diff --git a/gio/src/gio_docs_override.xml b/gio/src/gio_docs_override.xml
index f6cbe635..1df08d91 100644
--- a/gio/src/gio_docs_override.xml
+++ b/gio/src/gio_docs_override.xml
@@ -59,6 +59,7 @@
 <substitute_enumerator_name from_prefix="G_DBUS_ERROR_" to_prefix="Gio::DBus::Error::" />
 <substitute_enumerator_name from_prefix="G_DBUS_MESSAGE_HEADER_FIELD_" 
to_prefix="Gio::DBus::MessageHeaderField::" />
 <substitute_enumerator_name from_prefix="G_DBUS_MESSAGE_FLAGS_" to_prefix="Gio::DBus::MessageFlags::" />
+<substitute_enumerator_name from_prefix="G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_" 
to_prefix="Gio::DBus::ObjectManagerClient::Flags::" />
 <substitute_enumerator_name from_prefix="G_DBUS_PROXY_FLAGS_" to_prefix="Gio::DBus::ProxyFlags::" />
 <substitute_enumerator_name from_prefix="G_DBUS_INTERFACE_SKELETON_FLAGS_" 
to_prefix="Gio::DBus::InterfaceSkeleton::Flags::" />
 <substitute_enumerator_name from_prefix="G_BUS_NAME_OWNER_FLAGS_" to_prefix="Gio::DBus::BusNameOwnerFlags::" 
/>
diff --git a/gio/src/gio_vfuncs.defs b/gio/src/gio_vfuncs.defs
index 8dfac734..8ba65e1d 100644
--- a/gio/src/gio_vfuncs.defs
+++ b/gio/src/gio_vfuncs.defs
@@ -467,6 +467,35 @@
   )
 )
 
+; GDBusObjectManager
+
+(define-vfunc get_object_path
+  (of-object "GDBusObjectManager")
+  (return-type "const-gchar*")
+)
+
+(define-vfunc get_objects
+  (of-object "GDBusObjectManager")
+  (return-type "GList*")
+)
+
+(define-vfunc get_object
+  (of-object "GDBusObjectManager")
+  (return-type "GDBusObject*")
+  (parameters
+   '("const-gchar*" "object_path")
+  )
+)
+
+(define-vfunc get_interface
+  (of-object "GDBusObjectManager")
+  (return-type "GDBusInterface*")
+  (parameters
+   '("const-gchar*" "object_path")
+   '("const-gchar*" "interface_name")
+  )
+)
+
 ; GDrive
 
 (define-vfunc get_name
diff --git a/tools/m4/convert_gio.m4 b/tools/m4/convert_gio.m4
index 7ee92379..36bf193d 100644
--- a/tools/m4/convert_gio.m4
+++ b/tools/m4/convert_gio.m4
@@ -41,6 +41,7 @@ _CONV_GIO_DBUS_INCLASS_ENUM(Message,ByteOrder)
 _CONV_GIO_DBUS_ENUM(MessageFlags)
 _CONV_GIO_DBUS_ENUM(MessageHeaderField)
 _CONV_GIO_DBUS_ENUM(MessageType)
+_CONV_GIO_DBUS_INCLASS_ENUM(ObjectManagerClient,Flags)
 _CONV_GIO_DBUS_ENUM(ProxyFlags)
 _CONV_GIO_DBUS_ENUM(ConnectionFlags)
 _CONV_GIO_DBUS_ENUM(SendMessageFlags)
@@ -162,13 +163,16 @@ _CONVERSION(`const Glib::RefPtr<Gio::DBus::InterfaceSkeleton>&',`GDBusInterfaceS
 _CONVERSION(`const Glib::RefPtr<MethodInvocation>&',`GDBusMethodInvocation*',`Glib::unwrap($3)')
 _CONVERSION(`const Glib::RefPtr<Gio::DBus::MethodInvocation>&',`GDBusMethodInvocation*',`Glib::unwrap($3)')
 
-# DBusObject
+# DBusObject, DBusObjectProxy, DBusObjectSkeleton
 _CONVERSION(`GDBusObject*',`Glib::RefPtr<Gio::DBus::Object>',`Glib::wrap($3)')
 _CONVERSION(`const Glib::RefPtr<Gio::DBus::Object>&',`GDBusObject*',`Glib::unwrap($3)')
 _CONVERSION(`Glib::RefPtr<Gio::DBus::Object>',`GDBusObject*',`Glib::unwrap($3)')
+_CONVERSION(`const Glib::RefPtr<Gio::DBus::ObjectProxy>&',`GDBusObjectProxy*',__CONVERT_REFPTR_TO_P)
+_CONVERSION(`const Glib::RefPtr<Gio::DBus::ObjectSkeleton>&',`GDBusObjectSkeleton*',__CONVERT_REFPTR_TO_P)
 
 # DBusProxy
 _CONVERSION(`GDBusProxy*',`Glib::RefPtr<Gio::DBus::Proxy>',`Glib::wrap($3)')
+_CONVERSION(`const Glib::RefPtr<Gio::DBus::Proxy>&',`GDBusProxy*',__CONVERT_REFPTR_TO_P)
 
 # DesktopAppInfo
 _CONVERSION(`GDesktopAppInfo*', `Glib::RefPtr<DesktopAppInfo>', `Glib::wrap($3)')



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]