1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: David Zeuthen <davidz@redhat.com>
25 #include "gdbusobjectmanager.h"
26 #include "gdbusobjectmanagerclient.h"
27 #include "gdbusobject.h"
28 #include "gdbusprivate.h"
29 #include "gioenumtypes.h"
30 #include "ginitable.h"
31 #include "gasyncresult.h"
32 #include "gsimpleasyncresult.h"
33 #include "gasyncinitable.h"
34 #include "gdbusconnection.h"
35 #include "gdbusutils.h"
36 #include "gdbusobject.h"
37 #include "gdbusobjectproxy.h"
38 #include "gdbusproxy.h"
39 #include "gdbusinterface.h"
44 * SECTION:gdbusobjectmanagerclient
45 * @short_description: Client-side object manager
48 * #GDBusObjectManagerClient is used to create, monitor and delete object
49 * proxies for remote objects exported by a #GDBusObjectManagerServer (or any
50 * code implementing the <ulink
51 * url="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">org.freedesktop.DBus.ObjectManager</ulink>
54 * Once an instance of this type has been created, you can connect to
55 * the #GDBusObjectManager::object-added and
56 * #GDBusObjectManager::object-removed signals and inspect the
57 * #GDBusObjectProxy objects returned by
58 * g_dbus_object_manager_get_objects().
60 * If the name for a #GDBusObjectManagerClient is not owned by anyone at
61 * object construction time, the default behavior is to request the
62 * message bus to launch an owner for the name. This behavior can be
63 * disabled using the %G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START
64 * flag. It's also worth noting that this only works if the name of
65 * interest is activatable in the first place. E.g. in some cases it
66 * is not possible to launch an owner for the requested name. In this
67 * case, #GDBusObjectManagerClient object construction still succeeds but
68 * there will be no object proxies
69 * (e.g. g_dbus_object_manager_get_objects() returns the empty list) and
70 * the #GDBusObjectManagerClient:name-owner property is %NULL.
72 * The owner of the requested name can come and go (for example
73 * consider a system service being restarted) – #GDBusObjectManagerClient
74 * handles this case too; simply connect to the #GObject::notify
75 * signal to watch for changes on the #GDBusObjectManagerClient:name-owner
76 * property. When the name owner vanishes, the behavior is that
77 * #GDBusObjectManagerClient:name-owner is set to %NULL (this includes
78 * emission of the #GObject::notify signal) and then
79 * #GDBusObjectManager::object-removed signals are synthesized
80 * for all currently existing object proxies. Since
81 * #GDBusObjectManagerClient:name-owner is %NULL when this happens, you can
82 * use this information to disambiguate a synthesized signal from a
83 * genuine signal caused by object removal on the remote
84 * #GDBusObjectManager. Similarly, when a new name owner appears,
85 * #GDBusObjectManager::object-added signals are synthesized
86 * while #GDBusObjectManagerClient:name-owner is still %NULL. Only when all
87 * object proxies have been added, the #GDBusObjectManagerClient:name-owner
88 * is set to the new name owner (this includes emission of the
89 * #GObject::notify signal). Furthermore, you are guaranteed that
90 * #GDBusObjectManagerClient:name-owner will alternate between a name owner
91 * (e.g. <literal>:1.42</literal>) and %NULL even in the case where
92 * the name of interest is atomically replaced
94 * Ultimately, #GDBusObjectManagerClient is used to obtain #GDBusProxy
95 * instances. All signals (including the
96 * <literal>org.freedesktop.DBus.Properties::PropertiesChanged</literal>
97 * signal) delivered to #GDBusProxy instances are guaranteed to
98 * originate from the name owner. This guarantee along with the
99 * behavior described above, means that certain race conditions
100 * including the <emphasis><quote>half the proxy is from the old owner
101 * and the other half is from the new owner</quote></emphasis> problem
104 * To avoid having the application connect to signals on the returned
105 * #GDBusObjectProxy and #GDBusProxy objects, the
106 * #GDBusObject::interface-added,
107 * #GDBusObject::interface-removed,
108 * #GDBusProxy::g-properties-changed and
109 * #GDBusProxy::g-signal signals
110 * are also emitted on the #GDBusObjectManagerClient instance managing these
111 * objects. The signals emitted are
112 * #GDBusObjectManager::interface-added,
113 * #GDBusObjectManager::interface-removed,
114 * #GDBusObjectManagerClient::interface-proxy-properties-changed and
115 * #GDBusObjectManagerClient::interface-proxy-signal.
117 * Note that all callbacks and signals are emitted in the
118 * <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
119 * that the #GDBusObjectManagerClient object was constructed
120 * in. Additionally, the #GDBusObjectProxy and #GDBusProxy objects
121 * originating from the #GDBusObjectManagerClient object will be created in
122 * the same context and, consequently, will deliver signals in the
126 struct _GDBusObjectManagerClientPrivate
131 GDBusConnection *connection;
135 GDBusObjectManagerClientFlags flags;
137 GDBusProxy *control_proxy;
139 GHashTable *map_object_path_to_object_proxy;
141 guint signal_subscription_id;
144 GDBusProxyTypeFunc get_proxy_type_func;
145 gpointer get_proxy_type_user_data;
146 GDestroyNotify get_proxy_type_destroy_notify;
158 PROP_GET_PROXY_TYPE_FUNC,
159 PROP_GET_PROXY_TYPE_USER_DATA,
160 PROP_GET_PROXY_TYPE_DESTROY_NOTIFY
165 INTERFACE_PROXY_SIGNAL_SIGNAL,
166 INTERFACE_PROXY_PROPERTIES_CHANGED_SIGNAL,
170 static guint signals[LAST_SIGNAL] = { 0 };
172 static void initable_iface_init (GInitableIface *initable_iface);
173 static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface);
174 static void dbus_object_manager_interface_init (GDBusObjectManagerIface *iface);
176 G_DEFINE_TYPE_WITH_CODE (GDBusObjectManagerClient, g_dbus_object_manager_client, G_TYPE_OBJECT,
177 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
178 G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
179 G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT_MANAGER, dbus_object_manager_interface_init));
181 static void maybe_unsubscribe_signals (GDBusObjectManagerClient *manager);
183 static void on_control_proxy_g_signal (GDBusProxy *proxy,
184 const gchar *sender_name,
185 const gchar *signal_name,
186 GVariant *parameters,
189 static void process_get_all_result (GDBusObjectManagerClient *manager,
191 const gchar *name_owner);
194 g_dbus_object_manager_client_finalize (GObject *object)
196 GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (object);
198 maybe_unsubscribe_signals (manager);
200 g_hash_table_unref (manager->priv->map_object_path_to_object_proxy);
202 if (manager->priv->control_proxy != NULL)
204 g_signal_handlers_disconnect_by_func (manager->priv->control_proxy,
205 on_control_proxy_g_signal,
207 g_object_unref (manager->priv->control_proxy);
209 g_object_unref (manager->priv->connection);
210 g_free (manager->priv->object_path);
211 g_free (manager->priv->name);
212 g_free (manager->priv->name_owner);
214 if (manager->priv->get_proxy_type_destroy_notify != NULL)
215 manager->priv->get_proxy_type_destroy_notify (manager->priv->get_proxy_type_user_data);
217 g_mutex_clear (&manager->priv->lock);
219 if (G_OBJECT_CLASS (g_dbus_object_manager_client_parent_class)->finalize != NULL)
220 G_OBJECT_CLASS (g_dbus_object_manager_client_parent_class)->finalize (object);
224 g_dbus_object_manager_client_get_property (GObject *_object,
229 GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_object);
233 case PROP_CONNECTION:
234 g_value_set_object (value, g_dbus_object_manager_client_get_connection (manager));
237 case PROP_OBJECT_PATH:
238 g_value_set_string (value, g_dbus_object_manager_get_object_path (G_DBUS_OBJECT_MANAGER (manager)));
242 g_value_set_string (value, g_dbus_object_manager_client_get_name (manager));
246 g_value_set_flags (value, g_dbus_object_manager_client_get_flags (manager));
249 case PROP_NAME_OWNER:
250 g_value_take_string (value, g_dbus_object_manager_client_get_name_owner (manager));
254 G_OBJECT_WARN_INVALID_PROPERTY_ID (_object, prop_id, pspec);
260 g_dbus_object_manager_client_set_property (GObject *_object,
265 GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_object);
271 manager->priv->bus_type = g_value_get_enum (value);
274 case PROP_CONNECTION:
275 if (g_value_get_object (value) != NULL)
277 g_assert (manager->priv->connection == NULL);
278 g_assert (G_IS_DBUS_CONNECTION (g_value_get_object (value)));
279 manager->priv->connection = g_value_dup_object (value);
283 case PROP_OBJECT_PATH:
284 g_assert (manager->priv->object_path == NULL);
285 g_assert (g_variant_is_object_path (g_value_get_string (value)));
286 manager->priv->object_path = g_value_dup_string (value);
290 g_assert (manager->priv->name == NULL);
291 name = g_value_get_string (value);
292 g_assert (name == NULL || g_dbus_is_name (name));
293 manager->priv->name = g_strdup (name);
297 manager->priv->flags = g_value_get_flags (value);
300 case PROP_GET_PROXY_TYPE_FUNC:
301 manager->priv->get_proxy_type_func = g_value_get_pointer (value);
304 case PROP_GET_PROXY_TYPE_USER_DATA:
305 manager->priv->get_proxy_type_user_data = g_value_get_pointer (value);
308 case PROP_GET_PROXY_TYPE_DESTROY_NOTIFY:
309 manager->priv->get_proxy_type_destroy_notify = g_value_get_pointer (value);
313 G_OBJECT_WARN_INVALID_PROPERTY_ID (_object, prop_id, pspec);
319 g_dbus_object_manager_client_class_init (GDBusObjectManagerClientClass *klass)
321 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
323 gobject_class->finalize = g_dbus_object_manager_client_finalize;
324 gobject_class->set_property = g_dbus_object_manager_client_set_property;
325 gobject_class->get_property = g_dbus_object_manager_client_get_property;
328 * GDBusObjectManagerClient:connection:
330 * The #GDBusConnection to use.
334 g_object_class_install_property (gobject_class,
336 g_param_spec_object ("connection",
338 "The connection to use",
339 G_TYPE_DBUS_CONNECTION,
342 G_PARAM_CONSTRUCT_ONLY |
343 G_PARAM_STATIC_STRINGS));
346 * GDBusObjectManagerClient:bus-type:
348 * If this property is not %G_BUS_TYPE_NONE, then
349 * #GDBusObjectManagerClient:connection must be %NULL and will be set to the
350 * #GDBusConnection obtained by calling g_bus_get() with the value
355 g_object_class_install_property (gobject_class,
357 g_param_spec_enum ("bus-type",
359 "The bus to connect to, if any",
363 G_PARAM_CONSTRUCT_ONLY |
364 G_PARAM_STATIC_NAME |
365 G_PARAM_STATIC_BLURB |
366 G_PARAM_STATIC_NICK));
369 * GDBusObjectManagerClient:flags:
371 * Flags from the #GDBusObjectManagerClientFlags enumeration.
375 g_object_class_install_property (gobject_class,
377 g_param_spec_flags ("flags",
379 "Flags for the proxy manager",
380 G_TYPE_DBUS_OBJECT_MANAGER_CLIENT_FLAGS,
381 G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
384 G_PARAM_CONSTRUCT_ONLY |
385 G_PARAM_STATIC_NAME |
386 G_PARAM_STATIC_BLURB |
387 G_PARAM_STATIC_NICK));
390 * GDBusObjectManagerClient:object-path:
392 * The object path the manager is for.
396 g_object_class_install_property (gobject_class,
398 g_param_spec_string ("object-path",
400 "The object path of the control object",
404 G_PARAM_CONSTRUCT_ONLY |
405 G_PARAM_STATIC_STRINGS));
408 * GDBusObjectManagerClient:name:
410 * The well-known name or unique name that the manager is for.
414 g_object_class_install_property (gobject_class,
416 g_param_spec_string ("name",
418 "Name that the manager is for",
422 G_PARAM_CONSTRUCT_ONLY |
423 G_PARAM_STATIC_STRINGS));
426 * GDBusObjectManagerClient:name-owner:
428 * The unique name that owns #GDBusObjectManagerClient:name or %NULL if
429 * no-one is currently owning the name. Connect to the
430 * #GObject::notify signal to track changes to this property.
434 g_object_class_install_property (gobject_class,
436 g_param_spec_string ("name-owner",
438 "The owner of the name we are watching",
441 G_PARAM_STATIC_STRINGS));
444 * GDBusObjectManagerClient:get-proxy-type-func:
446 * The #GDBusProxyTypeFunc to use when determining what #GType to
447 * use for interface proxies or %NULL.
451 g_object_class_install_property (gobject_class,
452 PROP_GET_PROXY_TYPE_FUNC,
453 g_param_spec_pointer ("get-proxy-type-func",
454 "GDBusProxyTypeFunc Function Pointer",
455 "The GDBusProxyTypeFunc pointer to use",
458 G_PARAM_CONSTRUCT_ONLY |
459 G_PARAM_STATIC_STRINGS));
462 * GDBusObjectManagerClient:get-proxy-type-user-data:
464 * The #gpointer user_data to pass to #GDBusObjectManagerClient:get-proxy-type-func.
468 g_object_class_install_property (gobject_class,
469 PROP_GET_PROXY_TYPE_USER_DATA,
470 g_param_spec_pointer ("get-proxy-type-user-data",
471 "GDBusProxyTypeFunc User Data",
472 "The GDBusProxyTypeFunc user_data",
475 G_PARAM_CONSTRUCT_ONLY |
476 G_PARAM_STATIC_STRINGS));
479 * GDBusObjectManagerClient:get-proxy-type-destroy-notify:
481 * A #GDestroyNotify for the #gpointer user_data in #GDBusObjectManagerClient:get-proxy-type-user-data.
485 g_object_class_install_property (gobject_class,
486 PROP_GET_PROXY_TYPE_DESTROY_NOTIFY,
487 g_param_spec_pointer ("get-proxy-type-destroy-notify",
488 "GDBusProxyTypeFunc user data free function",
489 "The GDBusProxyTypeFunc user data free function",
492 G_PARAM_CONSTRUCT_ONLY |
493 G_PARAM_STATIC_STRINGS));
496 * GDBusObjectManagerClient::interface-proxy-signal:
497 * @manager: The #GDBusObjectManagerClient emitting the signal.
498 * @object_proxy: The #GDBusObjectProxy on which an interface is emitting a D-Bus signal.
499 * @interface_proxy: The #GDBusProxy that is emitting a D-Bus signal.
500 * @sender_name: The sender of the signal or NULL if the connection is not a bus connection.
501 * @signal_name: The signal name.
502 * @parameters: A #GVariant tuple with parameters for the signal.
504 * Emitted when a D-Bus signal is received on @interface_proxy.
506 * This signal exists purely as a convenience to avoid having to
507 * connect signals to all interface proxies managed by @manager.
509 * This signal is emitted in the
510 * <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
511 * that @manager was constructed in.
515 signals[INTERFACE_PROXY_SIGNAL_SIGNAL] =
516 g_signal_new ("interface-proxy-signal",
517 G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
519 G_STRUCT_OFFSET (GDBusObjectManagerClientClass, interface_proxy_signal),
525 G_TYPE_DBUS_OBJECT_PROXY,
532 * GDBusObjectManagerClient::interface-proxy-properties-changed:
533 * @manager: The #GDBusObjectManagerClient emitting the signal.
534 * @object_proxy: The #GDBusObjectProxy on which an interface has properties that are changing.
535 * @interface_proxy: The #GDBusProxy that has properties that are changing.
536 * @changed_properties: A #GVariant containing the properties that changed.
537 * @invalidated_properties: A %NULL terminated array of properties that was invalidated.
539 * Emitted when one or more D-Bus properties on proxy changes. The
540 * local cache has already been updated when this signal fires. Note
541 * that both @changed_properties and @invalidated_properties are
542 * guaranteed to never be %NULL (either may be empty though).
544 * This signal exists purely as a convenience to avoid having to
545 * connect signals to all interface proxies managed by @manager.
547 * This signal is emitted in the
548 * <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
549 * that @manager was constructed in.
553 signals[INTERFACE_PROXY_PROPERTIES_CHANGED_SIGNAL] =
554 g_signal_new ("interface-proxy-properties-changed",
555 G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
557 G_STRUCT_OFFSET (GDBusObjectManagerClientClass, interface_proxy_properties_changed),
563 G_TYPE_DBUS_OBJECT_PROXY,
568 g_type_class_add_private (klass, sizeof (GDBusObjectManagerClientPrivate));
572 g_dbus_object_manager_client_init (GDBusObjectManagerClient *manager)
574 manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
575 G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
576 GDBusObjectManagerClientPrivate);
577 g_mutex_init (&manager->priv->lock);
578 manager->priv->map_object_path_to_object_proxy = g_hash_table_new_full (g_str_hash,
581 (GDestroyNotify) g_object_unref);
584 /* ---------------------------------------------------------------------------------------------------- */
587 * g_dbus_object_manager_client_new_sync:
588 * @connection: A #GDBusConnection.
589 * @flags: Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
590 * @name: (allow-none): The owner of the control object (unique or well-known name), or %NULL when not using a message bus connection.
591 * @object_path: The object path of the control object.
592 * @get_proxy_type_func: (allow-none): A #GDBusProxyTypeFunc function or %NULL to always construct #GDBusProxy proxies.
593 * @get_proxy_type_user_data: User data to pass to @get_proxy_type_func.
594 * @get_proxy_type_destroy_notify: (allow-none): Free function for @get_proxy_type_user_data or %NULL.
595 * @cancellable: (allow-none): A #GCancellable or %NULL
596 * @error: Return location for error or %NULL.
598 * Creates a new #GDBusObjectManagerClient object.
600 * This is a synchronous failable constructor - the calling thread is
601 * blocked until a reply is received. See g_dbus_object_manager_client_new()
602 * for the asynchronous version.
604 * Returns: (transfer full) (type GDBusObjectManagerClient): A
605 * #GDBusObjectManagerClient object or %NULL if @error is set. Free
606 * with g_object_unref().
611 g_dbus_object_manager_client_new_sync (GDBusConnection *connection,
612 GDBusObjectManagerClientFlags flags,
614 const gchar *object_path,
615 GDBusProxyTypeFunc get_proxy_type_func,
616 gpointer get_proxy_type_user_data,
617 GDestroyNotify get_proxy_type_destroy_notify,
618 GCancellable *cancellable,
623 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
624 g_return_val_if_fail ((name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) ||
625 g_dbus_is_name (name), NULL);
626 g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
627 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
629 initable = g_initable_new (G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
632 "connection", connection,
635 "object-path", object_path,
636 "get-proxy-type-func", get_proxy_type_func,
637 "get-proxy-type-user-data", get_proxy_type_user_data,
638 "get-proxy-type-destroy-notify", get_proxy_type_destroy_notify,
640 if (initable != NULL)
641 return G_DBUS_OBJECT_MANAGER (initable);
647 * g_dbus_object_manager_client_new:
648 * @connection: A #GDBusConnection.
649 * @flags: Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
650 * @name: The owner of the control object (unique or well-known name).
651 * @object_path: The object path of the control object.
652 * @get_proxy_type_func: (allow-none): A #GDBusProxyTypeFunc function or %NULL to always construct #GDBusProxy proxies.
653 * @get_proxy_type_user_data: User data to pass to @get_proxy_type_func.
654 * @get_proxy_type_destroy_notify: (allow-none): Free function for @get_proxy_type_user_data or %NULL.
655 * @cancellable: (allow-none): A #GCancellable or %NULL
656 * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
657 * @user_data: The data to pass to @callback.
659 * Asynchronously creates a new #GDBusObjectManagerClient object.
661 * This is an asynchronous failable constructor. When the result is
662 * ready, @callback will be invoked in the
663 * <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
664 * of the thread you are calling this method from. You can
665 * then call g_dbus_object_manager_client_new_finish() to get the result. See
666 * g_dbus_object_manager_client_new_sync() for the synchronous version.
671 g_dbus_object_manager_client_new (GDBusConnection *connection,
672 GDBusObjectManagerClientFlags flags,
674 const gchar *object_path,
675 GDBusProxyTypeFunc get_proxy_type_func,
676 gpointer get_proxy_type_user_data,
677 GDestroyNotify get_proxy_type_destroy_notify,
678 GCancellable *cancellable,
679 GAsyncReadyCallback callback,
682 g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
683 g_return_if_fail ((name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) ||
684 g_dbus_is_name (name));
685 g_return_if_fail (g_variant_is_object_path (object_path));
687 g_async_initable_new_async (G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
692 "connection", connection,
695 "object-path", object_path,
696 "get-proxy-type-func", get_proxy_type_func,
697 "get-proxy-type-user-data", get_proxy_type_user_data,
698 "get-proxy-type-destroy-notify", get_proxy_type_destroy_notify,
703 * g_dbus_object_manager_client_new_finish:
704 * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_object_manager_client_new().
705 * @error: Return location for error or %NULL.
707 * Finishes an operation started with g_dbus_object_manager_client_new().
709 * Returns: (transfer full) (type GDBusObjectManagerClient): A
710 * #GDBusObjectManagerClient object or %NULL if @error is set. Free
711 * with g_object_unref().
716 g_dbus_object_manager_client_new_finish (GAsyncResult *res,
720 GObject *source_object;
722 source_object = g_async_result_get_source_object (res);
723 g_assert (source_object != NULL);
725 object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
728 g_object_unref (source_object);
731 return G_DBUS_OBJECT_MANAGER (object);
736 /* ---------------------------------------------------------------------------------------------------- */
739 * g_dbus_object_manager_client_new_for_bus_sync:
740 * @bus_type: A #GBusType.
741 * @flags: Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
742 * @name: The owner of the control object (unique or well-known name).
743 * @object_path: The object path of the control object.
744 * @get_proxy_type_func: (allow-none): A #GDBusProxyTypeFunc function or %NULL to always construct #GDBusProxy proxies.
745 * @get_proxy_type_user_data: User data to pass to @get_proxy_type_func.
746 * @get_proxy_type_destroy_notify: (allow-none): Free function for @get_proxy_type_user_data or %NULL.
747 * @cancellable: (allow-none): A #GCancellable or %NULL
748 * @error: Return location for error or %NULL.
750 * Like g_dbus_object_manager_client_new_sync() but takes a #GBusType instead
751 * of a #GDBusConnection.
753 * This is a synchronous failable constructor - the calling thread is
754 * blocked until a reply is received. See g_dbus_object_manager_client_new_for_bus()
755 * for the asynchronous version.
757 * Returns: (transfer full) (type GDBusObjectManagerClient): A
758 * #GDBusObjectManagerClient object or %NULL if @error is set. Free
759 * with g_object_unref().
764 g_dbus_object_manager_client_new_for_bus_sync (GBusType bus_type,
765 GDBusObjectManagerClientFlags flags,
767 const gchar *object_path,
768 GDBusProxyTypeFunc get_proxy_type_func,
769 gpointer get_proxy_type_user_data,
770 GDestroyNotify get_proxy_type_destroy_notify,
771 GCancellable *cancellable,
776 g_return_val_if_fail (bus_type != G_BUS_TYPE_NONE, NULL);
777 g_return_val_if_fail (g_dbus_is_name (name), NULL);
778 g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
779 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
781 initable = g_initable_new (G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
784 "bus-type", bus_type,
787 "object-path", object_path,
788 "get-proxy-type-func", get_proxy_type_func,
789 "get-proxy-type-user-data", get_proxy_type_user_data,
790 "get-proxy-type-destroy-notify", get_proxy_type_destroy_notify,
792 if (initable != NULL)
793 return G_DBUS_OBJECT_MANAGER (initable);
799 * g_dbus_object_manager_client_new_for_bus:
800 * @bus_type: A #GBusType.
801 * @flags: Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
802 * @name: The owner of the control object (unique or well-known name).
803 * @object_path: The object path of the control object.
804 * @get_proxy_type_func: (allow-none): A #GDBusProxyTypeFunc function or %NULL to always construct #GDBusProxy proxies.
805 * @get_proxy_type_user_data: User data to pass to @get_proxy_type_func.
806 * @get_proxy_type_destroy_notify: (allow-none): Free function for @get_proxy_type_user_data or %NULL.
807 * @cancellable: (allow-none): A #GCancellable or %NULL
808 * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
809 * @user_data: The data to pass to @callback.
811 * Like g_dbus_object_manager_client_new() but takes a #GBusType instead of a
814 * This is an asynchronous failable constructor. When the result is
815 * ready, @callback will be invoked in the
816 * <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
817 * of the thread you are calling this method from. You can
818 * then call g_dbus_object_manager_client_new_for_bus_finish() to get the result. See
819 * g_dbus_object_manager_client_new_for_bus_sync() for the synchronous version.
824 g_dbus_object_manager_client_new_for_bus (GBusType bus_type,
825 GDBusObjectManagerClientFlags flags,
827 const gchar *object_path,
828 GDBusProxyTypeFunc get_proxy_type_func,
829 gpointer get_proxy_type_user_data,
830 GDestroyNotify get_proxy_type_destroy_notify,
831 GCancellable *cancellable,
832 GAsyncReadyCallback callback,
835 g_return_if_fail (bus_type != G_BUS_TYPE_NONE);
836 g_return_if_fail (g_dbus_is_name (name));
837 g_return_if_fail (g_variant_is_object_path (object_path));
839 g_async_initable_new_async (G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
844 "bus-type", bus_type,
847 "object-path", object_path,
848 "get-proxy-type-func", get_proxy_type_func,
849 "get-proxy-type-user-data", get_proxy_type_user_data,
850 "get-proxy-type-destroy-notify", get_proxy_type_destroy_notify,
855 * g_dbus_object_manager_client_new_for_bus_finish:
856 * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_object_manager_client_new_for_bus().
857 * @error: Return location for error or %NULL.
859 * Finishes an operation started with g_dbus_object_manager_client_new_for_bus().
861 * Returns: (transfer full) (type GDBusObjectManagerClient): A
862 * #GDBusObjectManagerClient object or %NULL if @error is set. Free
863 * with g_object_unref().
868 g_dbus_object_manager_client_new_for_bus_finish (GAsyncResult *res,
872 GObject *source_object;
874 source_object = g_async_result_get_source_object (res);
875 g_assert (source_object != NULL);
877 object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
880 g_object_unref (source_object);
883 return G_DBUS_OBJECT_MANAGER (object);
888 /* ---------------------------------------------------------------------------------------------------- */
891 * g_dbus_object_manager_client_get_connection:
892 * @manager: A #GDBusObjectManagerClient
894 * Gets the #GDBusConnection used by @manager.
896 * Returns: (transfer none): A #GDBusConnection object. Do not free,
897 * the object belongs to @manager.
902 g_dbus_object_manager_client_get_connection (GDBusObjectManagerClient *manager)
904 GDBusConnection *ret;
905 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
906 g_mutex_lock (&manager->priv->lock);
907 ret = manager->priv->connection;
908 g_mutex_unlock (&manager->priv->lock);
913 * g_dbus_object_manager_client_get_name:
914 * @manager: A #GDBusObjectManagerClient
916 * Gets the name that @manager is for, or %NULL if not a message bus
919 * Returns: A unique or well-known name. Do not free, the string
920 * belongs to @manager.
925 g_dbus_object_manager_client_get_name (GDBusObjectManagerClient *manager)
928 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
929 g_mutex_lock (&manager->priv->lock);
930 ret = manager->priv->name;
931 g_mutex_unlock (&manager->priv->lock);
936 * g_dbus_object_manager_client_get_flags:
937 * @manager: A #GDBusObjectManagerClient
939 * Gets the flags that @manager was constructed with.
941 * Returns: Zero of more flags from the #GDBusObjectManagerClientFlags
946 GDBusObjectManagerClientFlags
947 g_dbus_object_manager_client_get_flags (GDBusObjectManagerClient *manager)
949 GDBusObjectManagerClientFlags ret;
950 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE);
951 g_mutex_lock (&manager->priv->lock);
952 ret = manager->priv->flags;
953 g_mutex_unlock (&manager->priv->lock);
958 * g_dbus_object_manager_client_get_name_owner:
959 * @manager: A #GDBusObjectManagerClient.
961 * The unique name that owns the name that @manager is for or %NULL if
962 * no-one currently owns that name. You can connect to the
963 * #GObject::notify signal to track changes to the
964 * #GDBusObjectManagerClient:name-owner property.
966 * Returns: The name owner or %NULL if no name owner exists. Free with
972 g_dbus_object_manager_client_get_name_owner (GDBusObjectManagerClient *manager)
975 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
976 g_mutex_lock (&manager->priv->lock);
977 ret = g_strdup (manager->priv->name_owner);
978 g_mutex_unlock (&manager->priv->lock);
982 /* ---------------------------------------------------------------------------------------------------- */
984 /* signal handler for all objects we manage - we dispatch signals
985 * from here to the objects
988 signal_cb (GDBusConnection *connection,
989 const gchar *sender_name,
990 const gchar *object_path,
991 const gchar *interface_name,
992 const gchar *signal_name,
993 GVariant *parameters,
996 GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (user_data);
997 GDBusObjectProxy *object_proxy;
998 GDBusInterface *interface;
1000 g_mutex_lock (&manager->priv->lock);
1001 object_proxy = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
1002 if (object_proxy == NULL)
1004 g_mutex_unlock (&manager->priv->lock);
1007 g_object_ref (object_proxy);
1008 g_mutex_unlock (&manager->priv->lock);
1010 //g_debug ("yay, signal_cb %s %s: %s\n", signal_name, object_path, g_variant_print (parameters, TRUE));
1012 if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0)
1014 if (g_strcmp0 (signal_name, "PropertiesChanged") == 0)
1016 const gchar *interface_name;
1017 GVariant *changed_properties;
1018 const gchar **invalidated_properties;
1020 g_variant_get (parameters,
1023 &changed_properties,
1024 &invalidated_properties);
1026 interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object_proxy), interface_name);
1027 if (interface != NULL)
1029 GVariantIter property_iter;
1030 const gchar *property_name;
1031 GVariant *property_value;
1034 /* update caches... */
1035 g_variant_iter_init (&property_iter, changed_properties);
1036 while (g_variant_iter_next (&property_iter,
1041 g_dbus_proxy_set_cached_property (G_DBUS_PROXY (interface),
1044 g_variant_unref (property_value);
1047 for (n = 0; invalidated_properties[n] != NULL; n++)
1049 g_dbus_proxy_set_cached_property (G_DBUS_PROXY (interface),
1050 invalidated_properties[n],
1053 /* ... and then synthesize the signal */
1054 g_signal_emit_by_name (interface,
1055 "g-properties-changed",
1057 invalidated_properties);
1058 g_signal_emit (manager,
1059 signals[INTERFACE_PROXY_PROPERTIES_CHANGED_SIGNAL],
1064 invalidated_properties);
1065 g_object_unref (interface);
1067 g_variant_unref (changed_properties);
1068 g_free (invalidated_properties);
1073 /* regular signal - just dispatch it */
1074 interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object_proxy), interface_name);
1075 if (interface != NULL)
1077 g_signal_emit_by_name (interface,
1082 g_signal_emit (manager,
1083 signals[INTERFACE_PROXY_SIGNAL_SIGNAL],
1090 g_object_unref (interface);
1095 g_clear_object (&object_proxy);
1099 subscribe_signals (GDBusObjectManagerClient *manager,
1100 const gchar *name_owner)
1102 GError *error = NULL;
1105 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager));
1106 g_return_if_fail (manager->priv->signal_subscription_id == 0);
1107 g_return_if_fail (name_owner == NULL || g_dbus_is_unique_name (name_owner));
1109 if (name_owner != NULL)
1111 /* the bus daemon may not implement path_prefix so gracefully
1112 * handle this by using a fallback
1114 manager->priv->match_rule = g_strdup_printf ("type='signal',sender='%s',path_namespace='%s'",
1115 name_owner, manager->priv->object_path);
1117 ret = g_dbus_connection_call_sync (manager->priv->connection,
1118 "org.freedesktop.DBus",
1119 "/org/freedeskop/DBus",
1120 "org.freedesktop.DBus",
1122 g_variant_new ("(s)",
1123 manager->priv->match_rule),
1124 NULL, /* reply_type */
1125 G_DBUS_CALL_FLAGS_NONE,
1126 -1, /* default timeout */
1127 NULL, /* TODO: Cancellable */
1130 /* yay, bus daemon supports path_namespace */
1132 g_variant_unref (ret);
1137 /* still need to ask GDBusConnection for the callbacks */
1138 manager->priv->signal_subscription_id =
1139 g_dbus_connection_signal_subscribe (manager->priv->connection,
1141 NULL, /* interface */
1143 NULL, /* path - TODO: really want wilcard support here */
1145 G_DBUS_SIGNAL_FLAGS_NONE |
1146 G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
1149 NULL); /* user_data_free_func */
1154 /* TODO: we could report this to the user
1155 g_warning ("Message bus daemon does not support path_namespace: %s (%s %d)",
1157 g_quark_to_string (error->domain),
1161 g_error_free (error);
1163 /* no need to call RemoveMatch when done since it didn't work */
1164 g_free (manager->priv->match_rule);
1165 manager->priv->match_rule = NULL;
1167 /* Fallback is to subscribe to *all* signals from the name owner which
1168 * is rather wasteful. It's probably not a big practical problem because
1169 * users typically want all objects that the name owner supplies.
1171 manager->priv->signal_subscription_id =
1172 g_dbus_connection_signal_subscribe (manager->priv->connection,
1174 NULL, /* interface */
1176 NULL, /* path - TODO: really want wilcard support here */
1178 G_DBUS_SIGNAL_FLAGS_NONE,
1181 NULL); /* user_data_free_func */
1186 maybe_unsubscribe_signals (GDBusObjectManagerClient *manager)
1188 g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager));
1190 if (manager->priv->signal_subscription_id > 0)
1192 g_dbus_connection_signal_unsubscribe (manager->priv->connection,
1193 manager->priv->signal_subscription_id);
1194 manager->priv->signal_subscription_id = 0;
1197 if (manager->priv->match_rule != NULL)
1199 /* Since the AddMatch call succeeded this is guaranteed to not
1200 * fail - therefore, don't bother checking the return value
1202 g_dbus_connection_call (manager->priv->connection,
1203 "org.freedesktop.DBus",
1204 "/org/freedeskop/DBus",
1205 "org.freedesktop.DBus",
1207 g_variant_new ("(s)",
1208 manager->priv->match_rule),
1209 NULL, /* reply_type */
1210 G_DBUS_CALL_FLAGS_NONE,
1211 -1, /* default timeout */
1212 NULL, /* GCancellable */
1213 NULL, /* GAsyncReadyCallback */
1214 NULL); /* user data */
1215 g_free (manager->priv->match_rule);
1216 manager->priv->match_rule = NULL;
1221 /* ---------------------------------------------------------------------------------------------------- */
1224 on_notify_g_name_owner (GObject *object,
1228 GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (user_data);
1229 gchar *old_name_owner;
1230 gchar *new_name_owner;
1232 g_mutex_lock (&manager->priv->lock);
1233 old_name_owner = manager->priv->name_owner;
1234 new_name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy);
1235 manager->priv->name_owner = NULL;
1237 if (g_strcmp0 (old_name_owner, new_name_owner) != 0)
1242 /* remote manager changed; nuke all local proxies */
1243 proxies = g_hash_table_get_values (manager->priv->map_object_path_to_object_proxy);
1244 g_list_foreach (proxies, (GFunc) g_object_ref, NULL);
1245 g_hash_table_remove_all (manager->priv->map_object_path_to_object_proxy);
1247 g_mutex_unlock (&manager->priv->lock);
1249 /* do the :name-owner notify with a NULL name - this way the user knows
1250 * the ::object-proxy-removed following is because the name owner went
1253 g_object_notify (G_OBJECT (manager), "name-owner");
1255 for (l = proxies; l != NULL; l = l->next)
1257 GDBusObjectProxy *object_proxy = G_DBUS_OBJECT_PROXY (l->data);
1258 g_signal_emit_by_name (manager, "object-removed", object_proxy);
1260 g_list_free_full (proxies, g_object_unref);
1262 /* nuke local filter */
1263 maybe_unsubscribe_signals (manager);
1267 g_mutex_unlock (&manager->priv->lock);
1270 if (new_name_owner != NULL)
1275 //g_debug ("repopulating for %s", new_name_owner);
1277 /* TODO: do this async! */
1278 subscribe_signals (manager,
1281 value = g_dbus_proxy_call_sync (manager->priv->control_proxy,
1282 "GetManagedObjects",
1283 NULL, /* parameters */
1284 G_DBUS_CALL_FLAGS_NONE,
1290 maybe_unsubscribe_signals (manager);
1291 g_warning ("Error calling GetManagedObjects() when name owner %s for name %s came back: %s",
1293 manager->priv->name,
1295 g_error_free (error);
1299 process_get_all_result (manager, value, new_name_owner);
1300 g_variant_unref (value);
1303 /* do the :name-owner notify *AFTER* emitting ::object-proxy-added signals - this
1304 * way the user knows that the signals were emitted because the name owner came back
1306 g_mutex_lock (&manager->priv->lock);
1307 manager->priv->name_owner = new_name_owner;
1308 g_mutex_unlock (&manager->priv->lock);
1309 g_object_notify (G_OBJECT (manager), "name-owner");
1312 g_free (old_name_owner);
1316 initable_init (GInitable *initable,
1317 GCancellable *cancellable,
1320 GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (initable);
1323 GDBusProxyFlags proxy_flags;
1327 if (manager->priv->bus_type != G_BUS_TYPE_NONE)
1329 g_assert (manager->priv->connection == NULL);
1330 manager->priv->connection = g_bus_get_sync (manager->priv->bus_type, cancellable, error);
1331 if (manager->priv->connection == NULL)
1335 proxy_flags = G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES;
1336 if (manager->priv->flags & G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START)
1337 proxy_flags |= G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START;
1339 manager->priv->control_proxy = g_dbus_proxy_new_sync (manager->priv->connection,
1341 NULL, /* GDBusInterfaceInfo* */
1342 manager->priv->name,
1343 manager->priv->object_path,
1344 "org.freedesktop.DBus.ObjectManager",
1347 if (manager->priv->control_proxy == NULL)
1350 g_signal_connect (G_OBJECT (manager->priv->control_proxy),
1351 "notify::g-name-owner",
1352 G_CALLBACK (on_notify_g_name_owner),
1355 manager->priv->name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy);
1356 if (manager->priv->name_owner == NULL && manager->priv->name != NULL)
1358 /* it's perfectly fine if there's no name owner.. we're just going to
1359 * wait until one is ready
1364 /* yay, we can get the objects */
1365 g_signal_connect (manager->priv->control_proxy,
1367 G_CALLBACK (on_control_proxy_g_signal),
1369 subscribe_signals (manager,
1370 manager->priv->name_owner);
1371 value = g_dbus_proxy_call_sync (manager->priv->control_proxy,
1372 "GetManagedObjects",
1373 NULL, /* parameters */
1374 G_DBUS_CALL_FLAGS_NONE,
1380 maybe_unsubscribe_signals (manager);
1381 g_warn_if_fail (g_signal_handlers_disconnect_by_func (manager->priv->control_proxy,
1382 on_control_proxy_g_signal,
1384 g_object_unref (manager->priv->control_proxy);
1385 manager->priv->control_proxy = NULL;
1389 process_get_all_result (manager, value, manager->priv->name_owner);
1390 g_variant_unref (value);
1400 initable_iface_init (GInitableIface *initable_iface)
1402 initable_iface->init = initable_init;
1406 async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
1408 /* for now, just use default: run GInitable code in thread */
1411 /* ---------------------------------------------------------------------------------------------------- */
1414 add_interfaces (GDBusObjectManagerClient *manager,
1415 const gchar *object_path,
1416 GVariant *ifaces_and_properties,
1417 const gchar *name_owner)
1419 GDBusObjectProxy *op;
1422 const gchar *interface_name;
1423 GVariant *properties;
1424 GList *interface_added_signals, *l;
1425 GDBusProxy *interface_proxy;
1427 g_return_if_fail (name_owner == NULL || g_dbus_is_unique_name (name_owner));
1429 g_mutex_lock (&manager->priv->lock);
1431 interface_added_signals = NULL;
1434 op = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
1437 GType object_proxy_type;
1438 if (manager->priv->get_proxy_type_func != NULL)
1440 object_proxy_type = manager->priv->get_proxy_type_func (manager,
1443 manager->priv->get_proxy_type_user_data);
1444 g_warn_if_fail (g_type_is_a (object_proxy_type, G_TYPE_DBUS_OBJECT_PROXY));
1448 object_proxy_type = G_TYPE_DBUS_OBJECT_PROXY;
1450 op = g_object_new (object_proxy_type,
1451 "g-connection", manager->priv->connection,
1452 "g-object-path", object_path,
1458 g_variant_iter_init (&iter, ifaces_and_properties);
1459 while (g_variant_iter_next (&iter,
1465 GType interface_proxy_type;
1467 if (manager->priv->get_proxy_type_func != NULL)
1469 interface_proxy_type = manager->priv->get_proxy_type_func (manager,
1472 manager->priv->get_proxy_type_user_data);
1473 g_warn_if_fail (g_type_is_a (interface_proxy_type, G_TYPE_DBUS_PROXY));
1477 interface_proxy_type = G_TYPE_DBUS_PROXY;
1480 /* this is fine - there is no blocking IO because we pass DO_NOT_LOAD_PROPERTIES and
1481 * DO_NOT_CONNECT_SIGNALS and use a unique name
1484 interface_proxy = g_initable_new (interface_proxy_type,
1485 NULL, /* GCancellable */
1487 "g-connection", manager->priv->connection,
1488 "g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
1489 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
1490 "g-name", name_owner,
1491 "g-object-path", object_path,
1492 "g-interface-name", interface_name,
1494 if (interface_proxy == NULL)
1496 g_warning ("%s: Error constructing proxy for path %s and interface %s: %s",
1501 g_error_free (error);
1505 GVariantIter property_iter;
1506 const gchar *property_name;
1507 GVariant *property_value;
1509 /* associate the interface proxy with the object */
1510 g_dbus_interface_set_object (G_DBUS_INTERFACE (interface_proxy),
1511 G_DBUS_OBJECT (op));
1513 g_variant_iter_init (&property_iter, properties);
1514 while (g_variant_iter_next (&property_iter,
1519 g_dbus_proxy_set_cached_property (interface_proxy,
1522 g_variant_unref (property_value);
1525 _g_dbus_object_proxy_add_interface (op, interface_proxy);
1527 interface_added_signals = g_list_append (interface_added_signals, g_object_ref (interface_proxy));
1528 g_object_unref (interface_proxy);
1530 g_variant_unref (properties);
1533 g_mutex_unlock (&manager->priv->lock);
1535 /* now that we don't hold the lock any more, emit signals */
1536 for (l = interface_added_signals; l != NULL; l = l->next)
1538 interface_proxy = G_DBUS_PROXY (l->data);
1539 g_signal_emit_by_name (manager, "interface-added", op, interface_proxy);
1540 g_object_unref (interface_proxy);
1542 g_list_free (interface_added_signals);
1546 g_hash_table_insert (manager->priv->map_object_path_to_object_proxy,
1547 g_strdup (object_path),
1549 g_signal_emit_by_name (manager, "object-added", op);
1551 g_object_unref (op);
1556 remove_interfaces (GDBusObjectManagerClient *manager,
1557 const gchar *object_path,
1558 const gchar *const *interface_names)
1560 GDBusObjectProxy *op;
1563 guint num_interfaces;
1564 guint num_interfaces_to_remove;
1566 g_mutex_lock (&manager->priv->lock);
1568 op = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
1571 g_warning ("%s: Processing InterfaceRemoved signal for path %s but no object proxy exists",
1574 g_mutex_unlock (&manager->priv->lock);
1578 interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (op));
1579 num_interfaces = g_list_length (interfaces);
1580 g_list_free_full (interfaces, g_object_unref);
1582 num_interfaces_to_remove = g_strv_length ((gchar **) interface_names);
1584 /* see if we are going to completety remove the object */
1585 if (num_interfaces_to_remove == num_interfaces)
1588 g_warn_if_fail (g_hash_table_remove (manager->priv->map_object_path_to_object_proxy, object_path));
1589 g_mutex_unlock (&manager->priv->lock);
1590 g_signal_emit_by_name (manager, "object-removed", op);
1591 g_object_unref (op);
1596 g_mutex_unlock (&manager->priv->lock);
1597 for (n = 0; interface_names != NULL && interface_names[n] != NULL; n++)
1599 GDBusInterface *interface;
1600 interface = g_dbus_object_get_interface (G_DBUS_OBJECT (op), interface_names[n]);
1601 _g_dbus_object_proxy_remove_interface (op, interface_names[n]);
1602 if (interface != NULL)
1604 g_signal_emit_by_name (manager, "interface-removed", op, interface);
1605 g_object_unref (interface);
1608 g_object_unref (op);
1615 process_get_all_result (GDBusObjectManagerClient *manager,
1617 const gchar *name_owner)
1620 const gchar *object_path;
1621 GVariant *ifaces_and_properties;
1624 g_return_if_fail (name_owner == NULL || g_dbus_is_unique_name (name_owner));
1626 arg0 = g_variant_get_child_value (value, 0);
1627 g_variant_iter_init (&iter, arg0);
1628 while (g_variant_iter_next (&iter,
1631 &ifaces_and_properties))
1633 add_interfaces (manager, object_path, ifaces_and_properties, name_owner);
1634 g_variant_unref (ifaces_and_properties);
1636 g_variant_unref (arg0);
1640 on_control_proxy_g_signal (GDBusProxy *proxy,
1641 const gchar *sender_name,
1642 const gchar *signal_name,
1643 GVariant *parameters,
1646 GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (user_data);
1647 const gchar *object_path;
1649 //g_debug ("yay, g_signal %s: %s\n", signal_name, g_variant_print (parameters, TRUE));
1651 if (g_strcmp0 (signal_name, "InterfacesAdded") == 0)
1653 GVariant *ifaces_and_properties;
1654 g_variant_get (parameters,
1657 &ifaces_and_properties);
1658 add_interfaces (manager, object_path, ifaces_and_properties, manager->priv->name_owner);
1659 g_variant_unref (ifaces_and_properties);
1661 else if (g_strcmp0 (signal_name, "InterfacesRemoved") == 0)
1663 const gchar **ifaces;
1664 g_variant_get (parameters,
1668 remove_interfaces (manager, object_path, ifaces);
1673 /* ---------------------------------------------------------------------------------------------------- */
1675 static const gchar *
1676 g_dbus_object_manager_client_get_object_path (GDBusObjectManager *_manager)
1678 GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_manager);
1679 return manager->priv->object_path;
1682 static GDBusObject *
1683 g_dbus_object_manager_client_get_object (GDBusObjectManager *_manager,
1684 const gchar *object_path)
1686 GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_manager);
1689 g_mutex_lock (&manager->priv->lock);
1690 ret = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
1693 g_mutex_unlock (&manager->priv->lock);
1697 static GDBusInterface *
1698 g_dbus_object_manager_client_get_interface (GDBusObjectManager *_manager,
1699 const gchar *object_path,
1700 const gchar *interface_name)
1702 GDBusInterface *ret;
1703 GDBusObject *object;
1707 object = g_dbus_object_manager_get_object (_manager, object_path);
1711 ret = g_dbus_object_get_interface (object, interface_name);
1712 g_object_unref (object);
1719 g_dbus_object_manager_client_get_objects (GDBusObjectManager *_manager)
1721 GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_manager);
1724 g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
1726 g_mutex_lock (&manager->priv->lock);
1727 ret = g_hash_table_get_values (manager->priv->map_object_path_to_object_proxy);
1728 g_list_foreach (ret, (GFunc) g_object_ref, NULL);
1729 g_mutex_unlock (&manager->priv->lock);
1736 dbus_object_manager_interface_init (GDBusObjectManagerIface *iface)
1738 iface->get_object_path = g_dbus_object_manager_client_get_object_path;
1739 iface->get_objects = g_dbus_object_manager_client_get_objects;
1740 iface->get_object = g_dbus_object_manager_client_get_object;
1741 iface->get_interface = g_dbus_object_manager_client_get_interface;
1744 /* ---------------------------------------------------------------------------------------------------- */