2011-04-08 21:14:47 +02:00
|
|
|
|
/* GDBus - GLib D-Bus Library
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2008-2010 Red Hat, Inc.
|
|
|
|
|
*
|
|
|
|
|
* 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
|
2017-05-27 18:21:30 +02:00
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*
|
|
|
|
|
* 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
|
2014-01-23 12:58:29 +01:00
|
|
|
|
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*
|
|
|
|
|
* Author: David Zeuthen <davidz@redhat.com>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
|
|
#include "gdbusobjectmanager.h"
|
|
|
|
|
#include "gdbusobjectmanagerclient.h"
|
|
|
|
|
#include "gdbusobject.h"
|
|
|
|
|
#include "gdbusprivate.h"
|
|
|
|
|
#include "gioenumtypes.h"
|
|
|
|
|
#include "ginitable.h"
|
|
|
|
|
#include "gasyncresult.h"
|
|
|
|
|
#include "gasyncinitable.h"
|
|
|
|
|
#include "gdbusconnection.h"
|
|
|
|
|
#include "gdbusutils.h"
|
|
|
|
|
#include "gdbusobject.h"
|
|
|
|
|
#include "gdbusobjectproxy.h"
|
|
|
|
|
#include "gdbusproxy.h"
|
|
|
|
|
#include "gdbusinterface.h"
|
|
|
|
|
|
|
|
|
|
#include "glibintl.h"
|
2019-05-31 04:29:18 +02:00
|
|
|
|
#include "gmarshal-internal.h"
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* SECTION:gdbusobjectmanagerclient
|
|
|
|
|
* @short_description: Client-side object manager
|
|
|
|
|
* @include: gio/gio.h
|
|
|
|
|
*
|
|
|
|
|
* #GDBusObjectManagerClient is used to create, monitor and delete object
|
|
|
|
|
* proxies for remote objects exported by a #GDBusObjectManagerServer (or any
|
2014-02-06 03:23:28 +01:00
|
|
|
|
* code implementing the
|
|
|
|
|
* [org.freedesktop.DBus.ObjectManager](http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager)
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* interface).
|
|
|
|
|
*
|
|
|
|
|
* Once an instance of this type has been created, you can connect to
|
|
|
|
|
* the #GDBusObjectManager::object-added and
|
|
|
|
|
* #GDBusObjectManager::object-removed signals and inspect the
|
|
|
|
|
* #GDBusObjectProxy objects returned by
|
|
|
|
|
* g_dbus_object_manager_get_objects().
|
|
|
|
|
*
|
|
|
|
|
* If the name for a #GDBusObjectManagerClient 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 %G_DBUS_OBJECT_MANAGER_CLIENT_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, #GDBusObjectManagerClient object construction still succeeds but
|
|
|
|
|
* there will be no object proxies
|
|
|
|
|
* (e.g. g_dbus_object_manager_get_objects() returns the empty list) and
|
|
|
|
|
* the #GDBusObjectManagerClient:name-owner property is %NULL.
|
|
|
|
|
*
|
|
|
|
|
* The owner of the requested name can come and go (for example
|
|
|
|
|
* consider a system service being restarted) – #GDBusObjectManagerClient
|
|
|
|
|
* handles this case too; simply connect to the #GObject::notify
|
|
|
|
|
* signal to watch for changes on the #GDBusObjectManagerClient:name-owner
|
|
|
|
|
* property. When the name owner vanishes, the behavior is that
|
|
|
|
|
* #GDBusObjectManagerClient:name-owner is set to %NULL (this includes
|
|
|
|
|
* emission of the #GObject::notify signal) and then
|
|
|
|
|
* #GDBusObjectManager::object-removed signals are synthesized
|
|
|
|
|
* for all currently existing object proxies. Since
|
|
|
|
|
* #GDBusObjectManagerClient:name-owner is %NULL when this happens, you can
|
|
|
|
|
* use this information to disambiguate a synthesized signal from a
|
|
|
|
|
* genuine signal caused by object removal on the remote
|
|
|
|
|
* #GDBusObjectManager. Similarly, when a new name owner appears,
|
|
|
|
|
* #GDBusObjectManager::object-added signals are synthesized
|
|
|
|
|
* while #GDBusObjectManagerClient:name-owner is still %NULL. Only when all
|
|
|
|
|
* object proxies have been added, the #GDBusObjectManagerClient:name-owner
|
|
|
|
|
* is set to the new name owner (this includes emission of the
|
|
|
|
|
* #GObject::notify signal). Furthermore, you are guaranteed that
|
|
|
|
|
* #GDBusObjectManagerClient:name-owner will alternate between a name owner
|
2014-02-06 14:04:52 +01:00
|
|
|
|
* (e.g. `:1.42`) and %NULL even in the case where
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* the name of interest is atomically replaced
|
|
|
|
|
*
|
|
|
|
|
* Ultimately, #GDBusObjectManagerClient is used to obtain #GDBusProxy
|
|
|
|
|
* instances. All signals (including the
|
2014-02-01 02:34:33 +01:00
|
|
|
|
* org.freedesktop.DBus.Properties::PropertiesChanged signal)
|
|
|
|
|
* delivered to #GDBusProxy 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.
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*
|
|
|
|
|
* To avoid having the application connect to signals on the returned
|
|
|
|
|
* #GDBusObjectProxy and #GDBusProxy objects, the
|
|
|
|
|
* #GDBusObject::interface-added,
|
|
|
|
|
* #GDBusObject::interface-removed,
|
|
|
|
|
* #GDBusProxy::g-properties-changed and
|
|
|
|
|
* #GDBusProxy::g-signal signals
|
|
|
|
|
* are also emitted on the #GDBusObjectManagerClient instance managing these
|
|
|
|
|
* objects. The signals emitted are
|
|
|
|
|
* #GDBusObjectManager::interface-added,
|
|
|
|
|
* #GDBusObjectManager::interface-removed,
|
|
|
|
|
* #GDBusObjectManagerClient::interface-proxy-properties-changed and
|
|
|
|
|
* #GDBusObjectManagerClient::interface-proxy-signal.
|
|
|
|
|
*
|
|
|
|
|
* Note that all callbacks and signals are emitted in the
|
2014-02-08 18:26:56 +01:00
|
|
|
|
* [thread-default main context][g-main-context-push-thread-default]
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* that the #GDBusObjectManagerClient object was constructed
|
|
|
|
|
* in. Additionally, the #GDBusObjectProxy and #GDBusProxy objects
|
|
|
|
|
* originating from the #GDBusObjectManagerClient object will be created in
|
|
|
|
|
* the same context and, consequently, will deliver signals in the
|
|
|
|
|
* same main loop.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
struct _GDBusObjectManagerClientPrivate
|
|
|
|
|
{
|
2011-10-04 05:26:55 +02:00
|
|
|
|
GMutex lock;
|
2011-08-29 22:20:50 +02:00
|
|
|
|
|
2011-04-08 21:14:47 +02:00
|
|
|
|
GBusType bus_type;
|
|
|
|
|
GDBusConnection *connection;
|
|
|
|
|
gchar *object_path;
|
|
|
|
|
gchar *name;
|
|
|
|
|
gchar *name_owner;
|
|
|
|
|
GDBusObjectManagerClientFlags flags;
|
|
|
|
|
|
|
|
|
|
GDBusProxy *control_proxy;
|
|
|
|
|
|
|
|
|
|
GHashTable *map_object_path_to_object_proxy;
|
|
|
|
|
|
|
|
|
|
guint signal_subscription_id;
|
|
|
|
|
gchar *match_rule;
|
|
|
|
|
|
|
|
|
|
GDBusProxyTypeFunc get_proxy_type_func;
|
|
|
|
|
gpointer get_proxy_type_user_data;
|
2011-04-16 21:24:42 +02:00
|
|
|
|
GDestroyNotify get_proxy_type_destroy_notify;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
PROP_0,
|
|
|
|
|
PROP_BUS_TYPE,
|
|
|
|
|
PROP_CONNECTION,
|
|
|
|
|
PROP_FLAGS,
|
|
|
|
|
PROP_OBJECT_PATH,
|
|
|
|
|
PROP_NAME,
|
|
|
|
|
PROP_NAME_OWNER,
|
|
|
|
|
PROP_GET_PROXY_TYPE_FUNC,
|
2011-04-16 21:24:42 +02:00
|
|
|
|
PROP_GET_PROXY_TYPE_USER_DATA,
|
|
|
|
|
PROP_GET_PROXY_TYPE_DESTROY_NOTIFY
|
2011-04-08 21:14:47 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
INTERFACE_PROXY_SIGNAL_SIGNAL,
|
|
|
|
|
INTERFACE_PROXY_PROPERTIES_CHANGED_SIGNAL,
|
|
|
|
|
LAST_SIGNAL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static guint signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
|
|
|
|
|
static void initable_iface_init (GInitableIface *initable_iface);
|
|
|
|
|
static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface);
|
|
|
|
|
static void dbus_object_manager_interface_init (GDBusObjectManagerIface *iface);
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (GDBusObjectManagerClient, g_dbus_object_manager_client, G_TYPE_OBJECT,
|
2013-06-11 01:29:58 +02:00
|
|
|
|
G_ADD_PRIVATE (GDBusObjectManagerClient)
|
2011-04-08 21:14:47 +02:00
|
|
|
|
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
|
|
|
|
|
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
|
2014-10-17 12:54:02 +02:00
|
|
|
|
G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT_MANAGER, dbus_object_manager_interface_init))
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
|
|
|
|
static void maybe_unsubscribe_signals (GDBusObjectManagerClient *manager);
|
|
|
|
|
|
|
|
|
|
static void on_control_proxy_g_signal (GDBusProxy *proxy,
|
|
|
|
|
const gchar *sender_name,
|
|
|
|
|
const gchar *signal_name,
|
|
|
|
|
GVariant *parameters,
|
|
|
|
|
gpointer user_data);
|
|
|
|
|
|
|
|
|
|
static void process_get_all_result (GDBusObjectManagerClient *manager,
|
|
|
|
|
GVariant *value,
|
|
|
|
|
const gchar *name_owner);
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
g_dbus_object_manager_client_finalize (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (object);
|
|
|
|
|
|
|
|
|
|
maybe_unsubscribe_signals (manager);
|
|
|
|
|
|
|
|
|
|
g_hash_table_unref (manager->priv->map_object_path_to_object_proxy);
|
|
|
|
|
|
|
|
|
|
if (manager->priv->control_proxy != NULL)
|
|
|
|
|
{
|
2011-10-27 16:54:02 +02:00
|
|
|
|
g_signal_handlers_disconnect_by_func (manager->priv->control_proxy,
|
|
|
|
|
on_control_proxy_g_signal,
|
|
|
|
|
manager);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
g_object_unref (manager->priv->control_proxy);
|
|
|
|
|
}
|
2014-07-10 11:52:26 +02:00
|
|
|
|
if (manager->priv->connection != NULL)
|
|
|
|
|
g_object_unref (manager->priv->connection);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
g_free (manager->priv->object_path);
|
|
|
|
|
g_free (manager->priv->name);
|
|
|
|
|
g_free (manager->priv->name_owner);
|
|
|
|
|
|
2011-04-16 21:24:42 +02:00
|
|
|
|
if (manager->priv->get_proxy_type_destroy_notify != NULL)
|
|
|
|
|
manager->priv->get_proxy_type_destroy_notify (manager->priv->get_proxy_type_user_data);
|
|
|
|
|
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_clear (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
|
2011-04-08 21:14:47 +02:00
|
|
|
|
if (G_OBJECT_CLASS (g_dbus_object_manager_client_parent_class)->finalize != NULL)
|
|
|
|
|
G_OBJECT_CLASS (g_dbus_object_manager_client_parent_class)->finalize (object);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
g_dbus_object_manager_client_get_property (GObject *_object,
|
2011-08-29 22:20:50 +02:00
|
|
|
|
guint prop_id,
|
|
|
|
|
GValue *value,
|
|
|
|
|
GParamSpec *pspec)
|
2011-04-08 21:14:47 +02:00
|
|
|
|
{
|
|
|
|
|
GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_object);
|
|
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
|
{
|
|
|
|
|
case PROP_CONNECTION:
|
|
|
|
|
g_value_set_object (value, g_dbus_object_manager_client_get_connection (manager));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_OBJECT_PATH:
|
|
|
|
|
g_value_set_string (value, g_dbus_object_manager_get_object_path (G_DBUS_OBJECT_MANAGER (manager)));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_NAME:
|
|
|
|
|
g_value_set_string (value, g_dbus_object_manager_client_get_name (manager));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_FLAGS:
|
|
|
|
|
g_value_set_flags (value, g_dbus_object_manager_client_get_flags (manager));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_NAME_OWNER:
|
|
|
|
|
g_value_take_string (value, g_dbus_object_manager_client_get_name_owner (manager));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2012-11-15 14:42:36 +01:00
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (manager, prop_id, pspec);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
g_dbus_object_manager_client_set_property (GObject *_object,
|
2011-08-29 22:20:50 +02:00
|
|
|
|
guint prop_id,
|
|
|
|
|
const GValue *value,
|
|
|
|
|
GParamSpec *pspec)
|
2011-04-08 21:14:47 +02:00
|
|
|
|
{
|
|
|
|
|
GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_object);
|
2012-10-26 10:30:29 +02:00
|
|
|
|
const gchar *name;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
|
{
|
|
|
|
|
case PROP_BUS_TYPE:
|
|
|
|
|
manager->priv->bus_type = g_value_get_enum (value);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_CONNECTION:
|
|
|
|
|
if (g_value_get_object (value) != NULL)
|
|
|
|
|
{
|
|
|
|
|
g_assert (manager->priv->connection == NULL);
|
|
|
|
|
g_assert (G_IS_DBUS_CONNECTION (g_value_get_object (value)));
|
|
|
|
|
manager->priv->connection = g_value_dup_object (value);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_OBJECT_PATH:
|
|
|
|
|
g_assert (manager->priv->object_path == NULL);
|
|
|
|
|
g_assert (g_variant_is_object_path (g_value_get_string (value)));
|
|
|
|
|
manager->priv->object_path = g_value_dup_string (value);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_NAME:
|
|
|
|
|
g_assert (manager->priv->name == NULL);
|
2012-10-26 10:30:29 +02:00
|
|
|
|
name = g_value_get_string (value);
|
|
|
|
|
g_assert (name == NULL || g_dbus_is_name (name));
|
|
|
|
|
manager->priv->name = g_strdup (name);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_FLAGS:
|
|
|
|
|
manager->priv->flags = g_value_get_flags (value);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_GET_PROXY_TYPE_FUNC:
|
|
|
|
|
manager->priv->get_proxy_type_func = g_value_get_pointer (value);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_GET_PROXY_TYPE_USER_DATA:
|
|
|
|
|
manager->priv->get_proxy_type_user_data = g_value_get_pointer (value);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-04-16 21:24:42 +02:00
|
|
|
|
case PROP_GET_PROXY_TYPE_DESTROY_NOTIFY:
|
|
|
|
|
manager->priv->get_proxy_type_destroy_notify = g_value_get_pointer (value);
|
|
|
|
|
break;
|
|
|
|
|
|
2011-04-08 21:14:47 +02:00
|
|
|
|
default:
|
2012-11-15 14:42:36 +01:00
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (manager, prop_id, pspec);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
g_dbus_object_manager_client_class_init (GDBusObjectManagerClientClass *klass)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
|
|
gobject_class->finalize = g_dbus_object_manager_client_finalize;
|
|
|
|
|
gobject_class->set_property = g_dbus_object_manager_client_set_property;
|
|
|
|
|
gobject_class->get_property = g_dbus_object_manager_client_get_property;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GDBusObjectManagerClient:connection:
|
|
|
|
|
*
|
|
|
|
|
* The #GDBusConnection to use.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
g_object_class_install_property (gobject_class,
|
|
|
|
|
PROP_CONNECTION,
|
|
|
|
|
g_param_spec_object ("connection",
|
|
|
|
|
"Connection",
|
|
|
|
|
"The connection to use",
|
|
|
|
|
G_TYPE_DBUS_CONNECTION,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS));
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GDBusObjectManagerClient:bus-type:
|
|
|
|
|
*
|
|
|
|
|
* If this property is not %G_BUS_TYPE_NONE, then
|
|
|
|
|
* #GDBusObjectManagerClient:connection must be %NULL and will be set to the
|
|
|
|
|
* #GDBusConnection obtained by calling g_bus_get() with the value
|
|
|
|
|
* of this property.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
g_object_class_install_property (gobject_class,
|
|
|
|
|
PROP_BUS_TYPE,
|
|
|
|
|
g_param_spec_enum ("bus-type",
|
|
|
|
|
"Bus Type",
|
|
|
|
|
"The bus to connect to, if any",
|
|
|
|
|
G_TYPE_BUS_TYPE,
|
|
|
|
|
G_BUS_TYPE_NONE,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_NAME |
|
|
|
|
|
G_PARAM_STATIC_BLURB |
|
|
|
|
|
G_PARAM_STATIC_NICK));
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GDBusObjectManagerClient:flags:
|
|
|
|
|
*
|
|
|
|
|
* Flags from the #GDBusObjectManagerClientFlags enumeration.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
g_object_class_install_property (gobject_class,
|
|
|
|
|
PROP_FLAGS,
|
|
|
|
|
g_param_spec_flags ("flags",
|
|
|
|
|
"Flags",
|
|
|
|
|
"Flags for the proxy manager",
|
|
|
|
|
G_TYPE_DBUS_OBJECT_MANAGER_CLIENT_FLAGS,
|
|
|
|
|
G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_NAME |
|
|
|
|
|
G_PARAM_STATIC_BLURB |
|
|
|
|
|
G_PARAM_STATIC_NICK));
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GDBusObjectManagerClient:object-path:
|
|
|
|
|
*
|
|
|
|
|
* The object path the manager is for.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
g_object_class_install_property (gobject_class,
|
|
|
|
|
PROP_OBJECT_PATH,
|
|
|
|
|
g_param_spec_string ("object-path",
|
|
|
|
|
"Object Path",
|
|
|
|
|
"The object path of the control object",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS));
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GDBusObjectManagerClient:name:
|
|
|
|
|
*
|
|
|
|
|
* The well-known name or unique name that the manager is for.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
g_object_class_install_property (gobject_class,
|
|
|
|
|
PROP_NAME,
|
|
|
|
|
g_param_spec_string ("name",
|
|
|
|
|
"Name",
|
|
|
|
|
"Name that the manager is for",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS));
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GDBusObjectManagerClient:name-owner:
|
|
|
|
|
*
|
|
|
|
|
* The unique name that owns #GDBusObjectManagerClient:name or %NULL if
|
|
|
|
|
* no-one is currently owning the name. Connect to the
|
|
|
|
|
* #GObject::notify signal to track changes to this property.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
g_object_class_install_property (gobject_class,
|
|
|
|
|
PROP_NAME_OWNER,
|
|
|
|
|
g_param_spec_string ("name-owner",
|
|
|
|
|
"Name Owner",
|
|
|
|
|
"The owner of the name we are watching",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS));
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GDBusObjectManagerClient:get-proxy-type-func:
|
|
|
|
|
*
|
|
|
|
|
* The #GDBusProxyTypeFunc to use when determining what #GType to
|
|
|
|
|
* use for interface proxies or %NULL.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
g_object_class_install_property (gobject_class,
|
|
|
|
|
PROP_GET_PROXY_TYPE_FUNC,
|
|
|
|
|
g_param_spec_pointer ("get-proxy-type-func",
|
|
|
|
|
"GDBusProxyTypeFunc Function Pointer",
|
|
|
|
|
"The GDBusProxyTypeFunc pointer to use",
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS));
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GDBusObjectManagerClient:get-proxy-type-user-data:
|
|
|
|
|
*
|
|
|
|
|
* The #gpointer user_data to pass to #GDBusObjectManagerClient:get-proxy-type-func.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
g_object_class_install_property (gobject_class,
|
|
|
|
|
PROP_GET_PROXY_TYPE_USER_DATA,
|
|
|
|
|
g_param_spec_pointer ("get-proxy-type-user-data",
|
|
|
|
|
"GDBusProxyTypeFunc User Data",
|
|
|
|
|
"The GDBusProxyTypeFunc user_data",
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS));
|
|
|
|
|
|
2011-04-16 21:24:42 +02:00
|
|
|
|
/**
|
|
|
|
|
* GDBusObjectManagerClient:get-proxy-type-destroy-notify:
|
|
|
|
|
*
|
|
|
|
|
* A #GDestroyNotify for the #gpointer user_data in #GDBusObjectManagerClient:get-proxy-type-user-data.
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
|
|
|
|
*/
|
|
|
|
|
g_object_class_install_property (gobject_class,
|
|
|
|
|
PROP_GET_PROXY_TYPE_DESTROY_NOTIFY,
|
|
|
|
|
g_param_spec_pointer ("get-proxy-type-destroy-notify",
|
|
|
|
|
"GDBusProxyTypeFunc user data free function",
|
|
|
|
|
"The GDBusProxyTypeFunc user data free function",
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS));
|
|
|
|
|
|
2011-04-08 21:14:47 +02:00
|
|
|
|
/**
|
|
|
|
|
* GDBusObjectManagerClient::interface-proxy-signal:
|
|
|
|
|
* @manager: The #GDBusObjectManagerClient emitting the signal.
|
|
|
|
|
* @object_proxy: The #GDBusObjectProxy on which an interface is emitting a D-Bus signal.
|
|
|
|
|
* @interface_proxy: The #GDBusProxy that is emitting a D-Bus signal.
|
|
|
|
|
* @sender_name: The sender of the signal or NULL if the connection is not a bus connection.
|
|
|
|
|
* @signal_name: The signal name.
|
|
|
|
|
* @parameters: A #GVariant tuple with parameters for the signal.
|
|
|
|
|
*
|
|
|
|
|
* Emitted when a D-Bus signal is received on @interface_proxy.
|
|
|
|
|
*
|
|
|
|
|
* This signal exists purely as a convenience to avoid having to
|
|
|
|
|
* connect signals to all interface proxies managed by @manager.
|
|
|
|
|
*
|
|
|
|
|
* This signal is emitted in the
|
2014-02-08 18:26:56 +01:00
|
|
|
|
* [thread-default main context][g-main-context-push-thread-default]
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* that @manager was constructed in.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
signals[INTERFACE_PROXY_SIGNAL_SIGNAL] =
|
2015-09-12 06:00:40 +02:00
|
|
|
|
g_signal_new (I_("interface-proxy-signal"),
|
2011-04-08 21:14:47 +02:00
|
|
|
|
G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
G_STRUCT_OFFSET (GDBusObjectManagerClientClass, interface_proxy_signal),
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
2019-05-31 04:29:18 +02:00
|
|
|
|
_g_cclosure_marshal_VOID__OBJECT_OBJECT_STRING_STRING_VARIANT,
|
2011-04-08 21:14:47 +02:00
|
|
|
|
G_TYPE_NONE,
|
|
|
|
|
5,
|
|
|
|
|
G_TYPE_DBUS_OBJECT_PROXY,
|
|
|
|
|
G_TYPE_DBUS_PROXY,
|
|
|
|
|
G_TYPE_STRING,
|
|
|
|
|
G_TYPE_STRING,
|
|
|
|
|
G_TYPE_VARIANT);
|
2019-05-31 04:29:18 +02:00
|
|
|
|
g_signal_set_va_marshaller (signals[INTERFACE_PROXY_SIGNAL_SIGNAL],
|
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
|
_g_cclosure_marshal_VOID__OBJECT_OBJECT_STRING_STRING_VARIANTv);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GDBusObjectManagerClient::interface-proxy-properties-changed:
|
|
|
|
|
* @manager: The #GDBusObjectManagerClient emitting the signal.
|
|
|
|
|
* @object_proxy: The #GDBusObjectProxy on which an interface has properties that are changing.
|
|
|
|
|
* @interface_proxy: The #GDBusProxy that has properties that are changing.
|
2018-04-25 16:30:46 +02:00
|
|
|
|
* @changed_properties: A #GVariant containing the properties that changed (type: `a{sv}`).
|
2017-05-04 23:16:37 +02:00
|
|
|
|
* @invalidated_properties: (array zero-terminated=1) (element-type utf8): A %NULL terminated
|
|
|
|
|
* array of properties that were invalidated.
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*
|
|
|
|
|
* Emitted when one or more D-Bus properties on proxy changes. The
|
|
|
|
|
* local cache has already been updated when this signal fires. Note
|
|
|
|
|
* that both @changed_properties and @invalidated_properties are
|
|
|
|
|
* guaranteed to never be %NULL (either may be empty though).
|
|
|
|
|
*
|
|
|
|
|
* This signal exists purely as a convenience to avoid having to
|
|
|
|
|
* connect signals to all interface proxies managed by @manager.
|
|
|
|
|
*
|
|
|
|
|
* This signal is emitted in the
|
2014-02-08 18:26:56 +01:00
|
|
|
|
* [thread-default main context][g-main-context-push-thread-default]
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* that @manager was constructed in.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
signals[INTERFACE_PROXY_PROPERTIES_CHANGED_SIGNAL] =
|
2015-09-12 06:00:40 +02:00
|
|
|
|
g_signal_new (I_("interface-proxy-properties-changed"),
|
2011-04-08 21:14:47 +02:00
|
|
|
|
G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
G_STRUCT_OFFSET (GDBusObjectManagerClientClass, interface_proxy_properties_changed),
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
2019-05-31 04:29:18 +02:00
|
|
|
|
_g_cclosure_marshal_VOID__OBJECT_OBJECT_VARIANT_BOXED,
|
2011-04-08 21:14:47 +02:00
|
|
|
|
G_TYPE_NONE,
|
|
|
|
|
4,
|
|
|
|
|
G_TYPE_DBUS_OBJECT_PROXY,
|
|
|
|
|
G_TYPE_DBUS_PROXY,
|
|
|
|
|
G_TYPE_VARIANT,
|
|
|
|
|
G_TYPE_STRV);
|
2019-05-31 04:29:18 +02:00
|
|
|
|
g_signal_set_va_marshaller (signals[INTERFACE_PROXY_PROPERTIES_CHANGED_SIGNAL],
|
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
|
_g_cclosure_marshal_VOID__OBJECT_OBJECT_VARIANT_BOXEDv);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
g_dbus_object_manager_client_init (GDBusObjectManagerClient *manager)
|
|
|
|
|
{
|
2013-06-24 16:43:04 +02:00
|
|
|
|
manager->priv = g_dbus_object_manager_client_get_instance_private (manager);
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_init (&manager->priv->lock);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
manager->priv->map_object_path_to_object_proxy = g_hash_table_new_full (g_str_hash,
|
|
|
|
|
g_str_equal,
|
|
|
|
|
g_free,
|
|
|
|
|
(GDestroyNotify) g_object_unref);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_dbus_object_manager_client_new_sync:
|
|
|
|
|
* @connection: A #GDBusConnection.
|
|
|
|
|
* @flags: Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
|
2016-10-29 03:29:02 +02:00
|
|
|
|
* @name: (nullable): The owner of the control object (unique or well-known name), or %NULL when not using a message bus connection.
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* @object_path: The object path of the control object.
|
2016-10-29 03:29:02 +02:00
|
|
|
|
* @get_proxy_type_func: (nullable): A #GDBusProxyTypeFunc function or %NULL to always construct #GDBusProxy proxies.
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* @get_proxy_type_user_data: User data to pass to @get_proxy_type_func.
|
2016-10-29 03:29:02 +02:00
|
|
|
|
* @get_proxy_type_destroy_notify: (nullable): Free function for @get_proxy_type_user_data or %NULL.
|
|
|
|
|
* @cancellable: (nullable): A #GCancellable or %NULL
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* @error: Return location for error or %NULL.
|
|
|
|
|
*
|
|
|
|
|
* Creates a new #GDBusObjectManagerClient object.
|
|
|
|
|
*
|
|
|
|
|
* This is a synchronous failable constructor - the calling thread is
|
|
|
|
|
* blocked until a reply is received. See g_dbus_object_manager_client_new()
|
|
|
|
|
* for the asynchronous version.
|
|
|
|
|
*
|
2011-04-16 20:42:21 +02:00
|
|
|
|
* Returns: (transfer full) (type GDBusObjectManagerClient): A
|
|
|
|
|
* #GDBusObjectManagerClient object or %NULL if @error is set. Free
|
|
|
|
|
* with g_object_unref().
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
GDBusObjectManager *
|
|
|
|
|
g_dbus_object_manager_client_new_sync (GDBusConnection *connection,
|
|
|
|
|
GDBusObjectManagerClientFlags flags,
|
|
|
|
|
const gchar *name,
|
|
|
|
|
const gchar *object_path,
|
|
|
|
|
GDBusProxyTypeFunc get_proxy_type_func,
|
|
|
|
|
gpointer get_proxy_type_user_data,
|
2011-04-16 21:24:42 +02:00
|
|
|
|
GDestroyNotify get_proxy_type_destroy_notify,
|
2011-04-08 21:14:47 +02:00
|
|
|
|
GCancellable *cancellable,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
GInitable *initable;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
|
|
|
|
|
g_return_val_if_fail ((name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) ||
|
|
|
|
|
g_dbus_is_name (name), NULL);
|
|
|
|
|
g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
|
|
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
|
|
|
|
|
|
|
|
initable = g_initable_new (G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
|
|
|
|
|
cancellable,
|
|
|
|
|
error,
|
|
|
|
|
"connection", connection,
|
|
|
|
|
"flags", flags,
|
|
|
|
|
"name", name,
|
|
|
|
|
"object-path", object_path,
|
|
|
|
|
"get-proxy-type-func", get_proxy_type_func,
|
|
|
|
|
"get-proxy-type-user-data", get_proxy_type_user_data,
|
2011-04-16 21:24:42 +02:00
|
|
|
|
"get-proxy-type-destroy-notify", get_proxy_type_destroy_notify,
|
2011-04-08 21:14:47 +02:00
|
|
|
|
NULL);
|
|
|
|
|
if (initable != NULL)
|
|
|
|
|
return G_DBUS_OBJECT_MANAGER (initable);
|
|
|
|
|
else
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_dbus_object_manager_client_new:
|
|
|
|
|
* @connection: A #GDBusConnection.
|
|
|
|
|
* @flags: Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
|
|
|
|
|
* @name: The owner of the control object (unique or well-known name).
|
|
|
|
|
* @object_path: The object path of the control object.
|
2016-10-29 03:29:02 +02:00
|
|
|
|
* @get_proxy_type_func: (nullable): A #GDBusProxyTypeFunc function or %NULL to always construct #GDBusProxy proxies.
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* @get_proxy_type_user_data: User data to pass to @get_proxy_type_func.
|
2016-10-29 03:29:02 +02:00
|
|
|
|
* @get_proxy_type_destroy_notify: (nullable): Free function for @get_proxy_type_user_data or %NULL.
|
|
|
|
|
* @cancellable: (nullable): A #GCancellable or %NULL
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* @callback: A #GAsyncReadyCallback to call when the request is satisfied.
|
|
|
|
|
* @user_data: The data to pass to @callback.
|
|
|
|
|
*
|
|
|
|
|
* Asynchronously creates a new #GDBusObjectManagerClient object.
|
|
|
|
|
*
|
|
|
|
|
* This is an asynchronous failable constructor. When the result is
|
|
|
|
|
* ready, @callback will be invoked in the
|
2014-02-08 18:26:56 +01:00
|
|
|
|
* [thread-default main context][g-main-context-push-thread-default]
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* of the thread you are calling this method from. You can
|
|
|
|
|
* then call g_dbus_object_manager_client_new_finish() to get the result. See
|
|
|
|
|
* g_dbus_object_manager_client_new_sync() for the synchronous version.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
g_dbus_object_manager_client_new (GDBusConnection *connection,
|
|
|
|
|
GDBusObjectManagerClientFlags flags,
|
|
|
|
|
const gchar *name,
|
|
|
|
|
const gchar *object_path,
|
|
|
|
|
GDBusProxyTypeFunc get_proxy_type_func,
|
|
|
|
|
gpointer get_proxy_type_user_data,
|
2011-04-16 21:24:42 +02:00
|
|
|
|
GDestroyNotify get_proxy_type_destroy_notify,
|
2011-04-08 21:14:47 +02:00
|
|
|
|
GCancellable *cancellable,
|
|
|
|
|
GAsyncReadyCallback callback,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
|
|
|
|
|
g_return_if_fail ((name == NULL && g_dbus_connection_get_unique_name (connection) == NULL) ||
|
|
|
|
|
g_dbus_is_name (name));
|
|
|
|
|
g_return_if_fail (g_variant_is_object_path (object_path));
|
|
|
|
|
|
|
|
|
|
g_async_initable_new_async (G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
|
|
|
|
|
G_PRIORITY_DEFAULT,
|
|
|
|
|
cancellable,
|
|
|
|
|
callback,
|
|
|
|
|
user_data,
|
|
|
|
|
"connection", connection,
|
|
|
|
|
"flags", flags,
|
|
|
|
|
"name", name,
|
|
|
|
|
"object-path", object_path,
|
|
|
|
|
"get-proxy-type-func", get_proxy_type_func,
|
|
|
|
|
"get-proxy-type-user-data", get_proxy_type_user_data,
|
2011-04-16 21:24:42 +02:00
|
|
|
|
"get-proxy-type-destroy-notify", get_proxy_type_destroy_notify,
|
2011-04-08 21:14:47 +02:00
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_dbus_object_manager_client_new_finish:
|
|
|
|
|
* @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_object_manager_client_new().
|
|
|
|
|
* @error: Return location for error or %NULL.
|
|
|
|
|
*
|
|
|
|
|
* Finishes an operation started with g_dbus_object_manager_client_new().
|
|
|
|
|
*
|
2011-04-16 20:42:21 +02:00
|
|
|
|
* Returns: (transfer full) (type GDBusObjectManagerClient): A
|
|
|
|
|
* #GDBusObjectManagerClient object or %NULL if @error is set. Free
|
|
|
|
|
* with g_object_unref().
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
GDBusObjectManager *
|
|
|
|
|
g_dbus_object_manager_client_new_finish (GAsyncResult *res,
|
2011-08-29 22:20:50 +02:00
|
|
|
|
GError **error)
|
2011-04-08 21:14:47 +02:00
|
|
|
|
{
|
|
|
|
|
GObject *object;
|
|
|
|
|
GObject *source_object;
|
|
|
|
|
|
|
|
|
|
source_object = g_async_result_get_source_object (res);
|
|
|
|
|
g_assert (source_object != NULL);
|
|
|
|
|
|
|
|
|
|
object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
|
|
|
|
|
res,
|
|
|
|
|
error);
|
|
|
|
|
g_object_unref (source_object);
|
|
|
|
|
|
|
|
|
|
if (object != NULL)
|
|
|
|
|
return G_DBUS_OBJECT_MANAGER (object);
|
|
|
|
|
else
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_dbus_object_manager_client_new_for_bus_sync:
|
|
|
|
|
* @bus_type: A #GBusType.
|
|
|
|
|
* @flags: Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
|
|
|
|
|
* @name: The owner of the control object (unique or well-known name).
|
|
|
|
|
* @object_path: The object path of the control object.
|
2016-10-29 03:29:02 +02:00
|
|
|
|
* @get_proxy_type_func: (nullable): A #GDBusProxyTypeFunc function or %NULL to always construct #GDBusProxy proxies.
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* @get_proxy_type_user_data: User data to pass to @get_proxy_type_func.
|
2016-10-29 03:29:02 +02:00
|
|
|
|
* @get_proxy_type_destroy_notify: (nullable): Free function for @get_proxy_type_user_data or %NULL.
|
|
|
|
|
* @cancellable: (nullable): A #GCancellable or %NULL
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* @error: Return location for error or %NULL.
|
|
|
|
|
*
|
|
|
|
|
* Like g_dbus_object_manager_client_new_sync() but takes a #GBusType instead
|
|
|
|
|
* of a #GDBusConnection.
|
|
|
|
|
*
|
|
|
|
|
* This is a synchronous failable constructor - the calling thread is
|
|
|
|
|
* blocked until a reply is received. See g_dbus_object_manager_client_new_for_bus()
|
|
|
|
|
* for the asynchronous version.
|
|
|
|
|
*
|
2011-04-16 20:42:21 +02:00
|
|
|
|
* Returns: (transfer full) (type GDBusObjectManagerClient): A
|
|
|
|
|
* #GDBusObjectManagerClient object or %NULL if @error is set. Free
|
|
|
|
|
* with g_object_unref().
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
GDBusObjectManager *
|
|
|
|
|
g_dbus_object_manager_client_new_for_bus_sync (GBusType bus_type,
|
|
|
|
|
GDBusObjectManagerClientFlags flags,
|
|
|
|
|
const gchar *name,
|
|
|
|
|
const gchar *object_path,
|
|
|
|
|
GDBusProxyTypeFunc get_proxy_type_func,
|
|
|
|
|
gpointer get_proxy_type_user_data,
|
2011-04-16 21:24:42 +02:00
|
|
|
|
GDestroyNotify get_proxy_type_destroy_notify,
|
2011-04-08 21:14:47 +02:00
|
|
|
|
GCancellable *cancellable,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
GInitable *initable;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (bus_type != G_BUS_TYPE_NONE, NULL);
|
|
|
|
|
g_return_val_if_fail (g_dbus_is_name (name), NULL);
|
|
|
|
|
g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
|
|
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
|
|
|
|
|
|
|
|
initable = g_initable_new (G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
|
|
|
|
|
cancellable,
|
|
|
|
|
error,
|
|
|
|
|
"bus-type", bus_type,
|
|
|
|
|
"flags", flags,
|
|
|
|
|
"name", name,
|
|
|
|
|
"object-path", object_path,
|
|
|
|
|
"get-proxy-type-func", get_proxy_type_func,
|
|
|
|
|
"get-proxy-type-user-data", get_proxy_type_user_data,
|
2011-04-16 21:24:42 +02:00
|
|
|
|
"get-proxy-type-destroy-notify", get_proxy_type_destroy_notify,
|
2011-04-08 21:14:47 +02:00
|
|
|
|
NULL);
|
|
|
|
|
if (initable != NULL)
|
|
|
|
|
return G_DBUS_OBJECT_MANAGER (initable);
|
|
|
|
|
else
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_dbus_object_manager_client_new_for_bus:
|
|
|
|
|
* @bus_type: A #GBusType.
|
|
|
|
|
* @flags: Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
|
|
|
|
|
* @name: The owner of the control object (unique or well-known name).
|
|
|
|
|
* @object_path: The object path of the control object.
|
2016-10-29 03:29:02 +02:00
|
|
|
|
* @get_proxy_type_func: (nullable): A #GDBusProxyTypeFunc function or %NULL to always construct #GDBusProxy proxies.
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* @get_proxy_type_user_data: User data to pass to @get_proxy_type_func.
|
2016-10-29 03:29:02 +02:00
|
|
|
|
* @get_proxy_type_destroy_notify: (nullable): Free function for @get_proxy_type_user_data or %NULL.
|
|
|
|
|
* @cancellable: (nullable): A #GCancellable or %NULL
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* @callback: A #GAsyncReadyCallback to call when the request is satisfied.
|
|
|
|
|
* @user_data: The data to pass to @callback.
|
|
|
|
|
*
|
|
|
|
|
* Like g_dbus_object_manager_client_new() but takes a #GBusType instead of a
|
|
|
|
|
* #GDBusConnection.
|
|
|
|
|
*
|
|
|
|
|
* This is an asynchronous failable constructor. When the result is
|
|
|
|
|
* ready, @callback will be invoked in the
|
2014-02-08 18:26:56 +01:00
|
|
|
|
* [thread-default main loop][g-main-context-push-thread-default]
|
2011-04-08 21:14:47 +02:00
|
|
|
|
* of the thread you are calling this method from. You can
|
|
|
|
|
* then call g_dbus_object_manager_client_new_for_bus_finish() to get the result. See
|
|
|
|
|
* g_dbus_object_manager_client_new_for_bus_sync() for the synchronous version.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
g_dbus_object_manager_client_new_for_bus (GBusType bus_type,
|
|
|
|
|
GDBusObjectManagerClientFlags flags,
|
|
|
|
|
const gchar *name,
|
|
|
|
|
const gchar *object_path,
|
|
|
|
|
GDBusProxyTypeFunc get_proxy_type_func,
|
|
|
|
|
gpointer get_proxy_type_user_data,
|
2011-04-16 21:24:42 +02:00
|
|
|
|
GDestroyNotify get_proxy_type_destroy_notify,
|
2011-04-08 21:14:47 +02:00
|
|
|
|
GCancellable *cancellable,
|
|
|
|
|
GAsyncReadyCallback callback,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (bus_type != G_BUS_TYPE_NONE);
|
|
|
|
|
g_return_if_fail (g_dbus_is_name (name));
|
|
|
|
|
g_return_if_fail (g_variant_is_object_path (object_path));
|
|
|
|
|
|
|
|
|
|
g_async_initable_new_async (G_TYPE_DBUS_OBJECT_MANAGER_CLIENT,
|
|
|
|
|
G_PRIORITY_DEFAULT,
|
|
|
|
|
cancellable,
|
|
|
|
|
callback,
|
|
|
|
|
user_data,
|
|
|
|
|
"bus-type", bus_type,
|
|
|
|
|
"flags", flags,
|
|
|
|
|
"name", name,
|
|
|
|
|
"object-path", object_path,
|
|
|
|
|
"get-proxy-type-func", get_proxy_type_func,
|
|
|
|
|
"get-proxy-type-user-data", get_proxy_type_user_data,
|
2011-04-16 21:24:42 +02:00
|
|
|
|
"get-proxy-type-destroy-notify", get_proxy_type_destroy_notify,
|
2011-04-08 21:14:47 +02:00
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_dbus_object_manager_client_new_for_bus_finish:
|
|
|
|
|
* @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_object_manager_client_new_for_bus().
|
|
|
|
|
* @error: Return location for error or %NULL.
|
|
|
|
|
*
|
|
|
|
|
* Finishes an operation started with g_dbus_object_manager_client_new_for_bus().
|
|
|
|
|
*
|
2011-04-16 20:42:21 +02:00
|
|
|
|
* Returns: (transfer full) (type GDBusObjectManagerClient): A
|
|
|
|
|
* #GDBusObjectManagerClient object or %NULL if @error is set. Free
|
|
|
|
|
* with g_object_unref().
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
GDBusObjectManager *
|
|
|
|
|
g_dbus_object_manager_client_new_for_bus_finish (GAsyncResult *res,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
GObject *object;
|
|
|
|
|
GObject *source_object;
|
|
|
|
|
|
|
|
|
|
source_object = g_async_result_get_source_object (res);
|
|
|
|
|
g_assert (source_object != NULL);
|
|
|
|
|
|
|
|
|
|
object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
|
|
|
|
|
res,
|
|
|
|
|
error);
|
|
|
|
|
g_object_unref (source_object);
|
|
|
|
|
|
|
|
|
|
if (object != NULL)
|
|
|
|
|
return G_DBUS_OBJECT_MANAGER (object);
|
|
|
|
|
else
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_dbus_object_manager_client_get_connection:
|
|
|
|
|
* @manager: A #GDBusObjectManagerClient
|
|
|
|
|
*
|
|
|
|
|
* Gets the #GDBusConnection used by @manager.
|
|
|
|
|
*
|
2011-04-16 20:42:21 +02:00
|
|
|
|
* Returns: (transfer none): A #GDBusConnection object. Do not free,
|
|
|
|
|
* the object belongs to @manager.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
GDBusConnection *
|
|
|
|
|
g_dbus_object_manager_client_get_connection (GDBusObjectManagerClient *manager)
|
|
|
|
|
{
|
2011-08-29 22:20:50 +02:00
|
|
|
|
GDBusConnection *ret;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_lock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
ret = manager->priv->connection;
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
return ret;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_dbus_object_manager_client_get_name:
|
|
|
|
|
* @manager: A #GDBusObjectManagerClient
|
|
|
|
|
*
|
2012-10-26 10:30:29 +02:00
|
|
|
|
* Gets the name that @manager is for, or %NULL if not a message bus
|
|
|
|
|
* connection.
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*
|
|
|
|
|
* Returns: A unique or well-known name. Do not free, the string
|
|
|
|
|
* belongs to @manager.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
const gchar *
|
|
|
|
|
g_dbus_object_manager_client_get_name (GDBusObjectManagerClient *manager)
|
|
|
|
|
{
|
2011-08-29 22:20:50 +02:00
|
|
|
|
const gchar *ret;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_lock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
ret = manager->priv->name;
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
return ret;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_dbus_object_manager_client_get_flags:
|
|
|
|
|
* @manager: A #GDBusObjectManagerClient
|
|
|
|
|
*
|
|
|
|
|
* Gets the flags that @manager was constructed with.
|
|
|
|
|
*
|
|
|
|
|
* Returns: Zero of more flags from the #GDBusObjectManagerClientFlags
|
|
|
|
|
* enumeration.
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
GDBusObjectManagerClientFlags
|
|
|
|
|
g_dbus_object_manager_client_get_flags (GDBusObjectManagerClient *manager)
|
|
|
|
|
{
|
2011-08-29 22:20:50 +02:00
|
|
|
|
GDBusObjectManagerClientFlags ret;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE);
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_lock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
ret = manager->priv->flags;
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
return ret;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* g_dbus_object_manager_client_get_name_owner:
|
|
|
|
|
* @manager: A #GDBusObjectManagerClient.
|
|
|
|
|
*
|
|
|
|
|
* The unique name that owns the name that @manager is for or %NULL if
|
|
|
|
|
* no-one currently owns that name. You can connect to the
|
|
|
|
|
* #GObject::notify signal to track changes to the
|
|
|
|
|
* #GDBusObjectManagerClient:name-owner property.
|
|
|
|
|
*
|
2014-05-21 09:27:36 +02:00
|
|
|
|
* Returns: (nullable): The name owner or %NULL if no name owner
|
|
|
|
|
* exists. Free with g_free().
|
2011-04-08 22:29:48 +02:00
|
|
|
|
*
|
|
|
|
|
* Since: 2.30
|
2011-04-08 21:14:47 +02:00
|
|
|
|
*/
|
|
|
|
|
gchar *
|
|
|
|
|
g_dbus_object_manager_client_get_name_owner (GDBusObjectManagerClient *manager)
|
|
|
|
|
{
|
2011-08-29 22:20:50 +02:00
|
|
|
|
gchar *ret;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_lock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
ret = g_strdup (manager->priv->name_owner);
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
return ret;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/* signal handler for all objects we manage - we dispatch signals
|
|
|
|
|
* from here to the objects
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
signal_cb (GDBusConnection *connection,
|
|
|
|
|
const gchar *sender_name,
|
|
|
|
|
const gchar *object_path,
|
|
|
|
|
const gchar *interface_name,
|
|
|
|
|
const gchar *signal_name,
|
|
|
|
|
GVariant *parameters,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (user_data);
|
|
|
|
|
GDBusObjectProxy *object_proxy;
|
|
|
|
|
GDBusInterface *interface;
|
|
|
|
|
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_lock (&manager->priv->lock);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
object_proxy = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
|
|
|
|
|
if (object_proxy == NULL)
|
2011-08-29 22:20:50 +02:00
|
|
|
|
{
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
g_object_ref (object_proxy);
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
|
|
|
|
//g_debug ("yay, signal_cb %s %s: %s\n", signal_name, object_path, g_variant_print (parameters, TRUE));
|
|
|
|
|
|
2013-11-27 14:32:05 +01:00
|
|
|
|
g_object_ref (manager);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
if (g_strcmp0 (interface_name, "org.freedesktop.DBus.Properties") == 0)
|
|
|
|
|
{
|
|
|
|
|
if (g_strcmp0 (signal_name, "PropertiesChanged") == 0)
|
|
|
|
|
{
|
|
|
|
|
const gchar *interface_name;
|
|
|
|
|
GVariant *changed_properties;
|
|
|
|
|
const gchar **invalidated_properties;
|
|
|
|
|
|
|
|
|
|
g_variant_get (parameters,
|
|
|
|
|
"(&s@a{sv}^a&s)",
|
|
|
|
|
&interface_name,
|
|
|
|
|
&changed_properties,
|
|
|
|
|
&invalidated_properties);
|
|
|
|
|
|
|
|
|
|
interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object_proxy), interface_name);
|
|
|
|
|
if (interface != NULL)
|
|
|
|
|
{
|
|
|
|
|
GVariantIter property_iter;
|
|
|
|
|
const gchar *property_name;
|
|
|
|
|
GVariant *property_value;
|
|
|
|
|
guint n;
|
|
|
|
|
|
|
|
|
|
/* update caches... */
|
|
|
|
|
g_variant_iter_init (&property_iter, changed_properties);
|
|
|
|
|
while (g_variant_iter_next (&property_iter,
|
|
|
|
|
"{&sv}",
|
|
|
|
|
&property_name,
|
|
|
|
|
&property_value))
|
|
|
|
|
{
|
|
|
|
|
g_dbus_proxy_set_cached_property (G_DBUS_PROXY (interface),
|
|
|
|
|
property_name,
|
|
|
|
|
property_value);
|
|
|
|
|
g_variant_unref (property_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (n = 0; invalidated_properties[n] != NULL; n++)
|
|
|
|
|
{
|
|
|
|
|
g_dbus_proxy_set_cached_property (G_DBUS_PROXY (interface),
|
|
|
|
|
invalidated_properties[n],
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
/* ... and then synthesize the signal */
|
2011-08-15 11:43:24 +02:00
|
|
|
|
g_signal_emit_by_name (interface,
|
|
|
|
|
"g-properties-changed",
|
|
|
|
|
changed_properties,
|
|
|
|
|
invalidated_properties);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
g_signal_emit (manager,
|
|
|
|
|
signals[INTERFACE_PROXY_PROPERTIES_CHANGED_SIGNAL],
|
|
|
|
|
0,
|
|
|
|
|
object_proxy,
|
|
|
|
|
interface,
|
|
|
|
|
changed_properties,
|
|
|
|
|
invalidated_properties);
|
|
|
|
|
g_object_unref (interface);
|
|
|
|
|
}
|
|
|
|
|
g_variant_unref (changed_properties);
|
|
|
|
|
g_free (invalidated_properties);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* regular signal - just dispatch it */
|
|
|
|
|
interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object_proxy), interface_name);
|
|
|
|
|
if (interface != NULL)
|
|
|
|
|
{
|
2011-08-15 11:43:24 +02:00
|
|
|
|
g_signal_emit_by_name (interface,
|
|
|
|
|
"g-signal",
|
|
|
|
|
sender_name,
|
|
|
|
|
signal_name,
|
|
|
|
|
parameters);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
g_signal_emit (manager,
|
|
|
|
|
signals[INTERFACE_PROXY_SIGNAL_SIGNAL],
|
|
|
|
|
0,
|
|
|
|
|
object_proxy,
|
|
|
|
|
interface,
|
|
|
|
|
sender_name,
|
|
|
|
|
signal_name,
|
|
|
|
|
parameters);
|
|
|
|
|
g_object_unref (interface);
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-11-27 14:32:05 +01:00
|
|
|
|
g_object_unref (manager);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
|
|
|
|
out:
|
2012-04-17 23:48:08 +02:00
|
|
|
|
g_clear_object (&object_proxy);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
subscribe_signals (GDBusObjectManagerClient *manager,
|
|
|
|
|
const gchar *name_owner)
|
|
|
|
|
{
|
2012-10-26 10:30:29 +02:00
|
|
|
|
GError *error = NULL;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
GVariant *ret;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager));
|
|
|
|
|
g_return_if_fail (manager->priv->signal_subscription_id == 0);
|
2012-10-26 10:30:29 +02:00
|
|
|
|
g_return_if_fail (name_owner == NULL || g_dbus_is_unique_name (name_owner));
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
2012-10-26 10:30:29 +02:00
|
|
|
|
if (name_owner != NULL)
|
2011-04-08 21:14:47 +02:00
|
|
|
|
{
|
2013-10-23 16:07:46 +02:00
|
|
|
|
/* Only add path_namespace if it's non-'/'. This removes a no-op key from
|
|
|
|
|
* the match rule, and also works around a D-Bus bug where
|
|
|
|
|
* path_namespace='/' matches nothing in D-Bus versions < 1.6.18.
|
|
|
|
|
*
|
|
|
|
|
* See: https://bugs.freedesktop.org/show_bug.cgi?id=70799 */
|
|
|
|
|
if (g_str_equal (manager->priv->object_path, "/"))
|
|
|
|
|
{
|
|
|
|
|
manager->priv->match_rule = g_strdup_printf ("type='signal',sender='%s'",
|
|
|
|
|
name_owner);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
manager->priv->match_rule = g_strdup_printf ("type='signal',sender='%s',path_namespace='%s'",
|
|
|
|
|
name_owner, manager->priv->object_path);
|
|
|
|
|
}
|
2012-10-26 10:30:29 +02:00
|
|
|
|
|
2013-10-23 16:07:46 +02:00
|
|
|
|
/* The bus daemon may not implement path_namespace so gracefully
|
|
|
|
|
* handle this by using a fallback triggered if @error is set. */
|
2012-10-26 10:30:29 +02:00
|
|
|
|
ret = g_dbus_connection_call_sync (manager->priv->connection,
|
|
|
|
|
"org.freedesktop.DBus",
|
2013-09-24 14:19:20 +02:00
|
|
|
|
"/org/freedesktop/DBus",
|
2012-10-26 10:30:29 +02:00
|
|
|
|
"org.freedesktop.DBus",
|
|
|
|
|
"AddMatch",
|
|
|
|
|
g_variant_new ("(s)",
|
|
|
|
|
manager->priv->match_rule),
|
|
|
|
|
NULL, /* reply_type */
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1, /* default timeout */
|
|
|
|
|
NULL, /* TODO: Cancellable */
|
|
|
|
|
&error);
|
|
|
|
|
|
2011-04-08 21:14:47 +02:00
|
|
|
|
/* yay, bus daemon supports path_namespace */
|
2012-10-26 10:30:29 +02:00
|
|
|
|
if (ret != NULL)
|
|
|
|
|
g_variant_unref (ret);
|
|
|
|
|
}
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
2012-10-26 10:30:29 +02:00
|
|
|
|
if (error == NULL)
|
|
|
|
|
{
|
2011-04-08 21:14:47 +02:00
|
|
|
|
/* still need to ask GDBusConnection for the callbacks */
|
|
|
|
|
manager->priv->signal_subscription_id =
|
|
|
|
|
g_dbus_connection_signal_subscribe (manager->priv->connection,
|
|
|
|
|
name_owner,
|
|
|
|
|
NULL, /* interface */
|
|
|
|
|
NULL, /* member */
|
|
|
|
|
NULL, /* path - TODO: really want wilcard support here */
|
|
|
|
|
NULL, /* arg0 */
|
|
|
|
|
G_DBUS_SIGNAL_FLAGS_NONE |
|
|
|
|
|
G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
|
|
|
|
|
signal_cb,
|
|
|
|
|
manager,
|
|
|
|
|
NULL); /* user_data_free_func */
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* TODO: we could report this to the user
|
|
|
|
|
g_warning ("Message bus daemon does not support path_namespace: %s (%s %d)",
|
|
|
|
|
error->message,
|
|
|
|
|
g_quark_to_string (error->domain),
|
|
|
|
|
error->code);
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
|
|
|
|
|
/* no need to call RemoveMatch when done since it didn't work */
|
|
|
|
|
g_free (manager->priv->match_rule);
|
|
|
|
|
manager->priv->match_rule = NULL;
|
|
|
|
|
|
|
|
|
|
/* Fallback is to subscribe to *all* signals from the name owner which
|
|
|
|
|
* is rather wasteful. It's probably not a big practical problem because
|
|
|
|
|
* users typically want all objects that the name owner supplies.
|
|
|
|
|
*/
|
|
|
|
|
manager->priv->signal_subscription_id =
|
|
|
|
|
g_dbus_connection_signal_subscribe (manager->priv->connection,
|
|
|
|
|
name_owner,
|
|
|
|
|
NULL, /* interface */
|
|
|
|
|
NULL, /* member */
|
|
|
|
|
NULL, /* path - TODO: really want wilcard support here */
|
|
|
|
|
NULL, /* arg0 */
|
|
|
|
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
|
|
|
signal_cb,
|
|
|
|
|
manager,
|
|
|
|
|
NULL); /* user_data_free_func */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
maybe_unsubscribe_signals (GDBusObjectManagerClient *manager)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager));
|
|
|
|
|
|
|
|
|
|
if (manager->priv->signal_subscription_id > 0)
|
|
|
|
|
{
|
|
|
|
|
g_dbus_connection_signal_unsubscribe (manager->priv->connection,
|
|
|
|
|
manager->priv->signal_subscription_id);
|
|
|
|
|
manager->priv->signal_subscription_id = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (manager->priv->match_rule != NULL)
|
|
|
|
|
{
|
|
|
|
|
/* Since the AddMatch call succeeded this is guaranteed to not
|
|
|
|
|
* fail - therefore, don't bother checking the return value
|
|
|
|
|
*/
|
|
|
|
|
g_dbus_connection_call (manager->priv->connection,
|
|
|
|
|
"org.freedesktop.DBus",
|
2013-09-24 14:19:20 +02:00
|
|
|
|
"/org/freedesktop/DBus",
|
2011-04-08 21:14:47 +02:00
|
|
|
|
"org.freedesktop.DBus",
|
|
|
|
|
"RemoveMatch",
|
|
|
|
|
g_variant_new ("(s)",
|
|
|
|
|
manager->priv->match_rule),
|
|
|
|
|
NULL, /* reply_type */
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1, /* default timeout */
|
|
|
|
|
NULL, /* GCancellable */
|
|
|
|
|
NULL, /* GAsyncReadyCallback */
|
|
|
|
|
NULL); /* user data */
|
|
|
|
|
g_free (manager->priv->match_rule);
|
|
|
|
|
manager->priv->match_rule = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
on_notify_g_name_owner (GObject *object,
|
|
|
|
|
GParamSpec *pspec,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (user_data);
|
|
|
|
|
gchar *old_name_owner;
|
|
|
|
|
gchar *new_name_owner;
|
|
|
|
|
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_lock (&manager->priv->lock);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
old_name_owner = manager->priv->name_owner;
|
|
|
|
|
new_name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy);
|
|
|
|
|
manager->priv->name_owner = NULL;
|
|
|
|
|
|
2013-11-27 14:32:05 +01:00
|
|
|
|
g_object_ref (manager);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
if (g_strcmp0 (old_name_owner, new_name_owner) != 0)
|
|
|
|
|
{
|
|
|
|
|
GList *l;
|
|
|
|
|
GList *proxies;
|
|
|
|
|
|
2011-08-29 22:20:50 +02:00
|
|
|
|
/* remote manager changed; nuke all local proxies */
|
|
|
|
|
proxies = g_hash_table_get_values (manager->priv->map_object_path_to_object_proxy);
|
|
|
|
|
g_list_foreach (proxies, (GFunc) g_object_ref, NULL);
|
|
|
|
|
g_hash_table_remove_all (manager->priv->map_object_path_to_object_proxy);
|
|
|
|
|
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
|
2011-04-08 21:14:47 +02:00
|
|
|
|
/* do the :name-owner notify with a NULL name - this way the user knows
|
|
|
|
|
* the ::object-proxy-removed following is because the name owner went
|
|
|
|
|
* away
|
|
|
|
|
*/
|
|
|
|
|
g_object_notify (G_OBJECT (manager), "name-owner");
|
|
|
|
|
|
|
|
|
|
for (l = proxies; l != NULL; l = l->next)
|
|
|
|
|
{
|
|
|
|
|
GDBusObjectProxy *object_proxy = G_DBUS_OBJECT_PROXY (l->data);
|
|
|
|
|
g_signal_emit_by_name (manager, "object-removed", object_proxy);
|
|
|
|
|
}
|
2012-01-02 16:30:11 +01:00
|
|
|
|
g_list_free_full (proxies, g_object_unref);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
|
|
|
|
/* nuke local filter */
|
|
|
|
|
maybe_unsubscribe_signals (manager);
|
|
|
|
|
}
|
2011-08-29 22:20:50 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
}
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
|
|
|
|
if (new_name_owner != NULL)
|
|
|
|
|
{
|
|
|
|
|
GError *error;
|
|
|
|
|
GVariant *value;
|
|
|
|
|
|
|
|
|
|
//g_debug ("repopulating for %s", new_name_owner);
|
|
|
|
|
|
|
|
|
|
/* TODO: do this async! */
|
|
|
|
|
subscribe_signals (manager,
|
|
|
|
|
new_name_owner);
|
|
|
|
|
error = NULL;
|
|
|
|
|
value = g_dbus_proxy_call_sync (manager->priv->control_proxy,
|
|
|
|
|
"GetManagedObjects",
|
|
|
|
|
NULL, /* parameters */
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
NULL,
|
|
|
|
|
&error);
|
|
|
|
|
if (value == NULL)
|
|
|
|
|
{
|
|
|
|
|
maybe_unsubscribe_signals (manager);
|
|
|
|
|
g_warning ("Error calling GetManagedObjects() when name owner %s for name %s came back: %s",
|
|
|
|
|
new_name_owner,
|
|
|
|
|
manager->priv->name,
|
|
|
|
|
error->message);
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
process_get_all_result (manager, value, new_name_owner);
|
|
|
|
|
g_variant_unref (value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* do the :name-owner notify *AFTER* emitting ::object-proxy-added signals - this
|
|
|
|
|
* way the user knows that the signals were emitted because the name owner came back
|
|
|
|
|
*/
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_lock (&manager->priv->lock);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
manager->priv->name_owner = new_name_owner;
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
g_object_notify (G_OBJECT (manager), "name-owner");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
g_free (old_name_owner);
|
2013-11-27 14:32:05 +01:00
|
|
|
|
g_object_unref (manager);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
initable_init (GInitable *initable,
|
|
|
|
|
GCancellable *cancellable,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (initable);
|
|
|
|
|
gboolean ret;
|
|
|
|
|
GVariant *value;
|
|
|
|
|
GDBusProxyFlags proxy_flags;
|
|
|
|
|
|
|
|
|
|
ret = FALSE;
|
|
|
|
|
|
|
|
|
|
if (manager->priv->bus_type != G_BUS_TYPE_NONE)
|
|
|
|
|
{
|
|
|
|
|
g_assert (manager->priv->connection == NULL);
|
|
|
|
|
manager->priv->connection = g_bus_get_sync (manager->priv->bus_type, cancellable, error);
|
|
|
|
|
if (manager->priv->connection == NULL)
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
proxy_flags = G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES;
|
|
|
|
|
if (manager->priv->flags & G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START)
|
2012-06-23 23:58:51 +02:00
|
|
|
|
proxy_flags |= G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
|
|
|
|
manager->priv->control_proxy = g_dbus_proxy_new_sync (manager->priv->connection,
|
|
|
|
|
proxy_flags,
|
|
|
|
|
NULL, /* GDBusInterfaceInfo* */
|
|
|
|
|
manager->priv->name,
|
|
|
|
|
manager->priv->object_path,
|
|
|
|
|
"org.freedesktop.DBus.ObjectManager",
|
|
|
|
|
cancellable,
|
|
|
|
|
error);
|
|
|
|
|
if (manager->priv->control_proxy == NULL)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
g_signal_connect (G_OBJECT (manager->priv->control_proxy),
|
|
|
|
|
"notify::g-name-owner",
|
|
|
|
|
G_CALLBACK (on_notify_g_name_owner),
|
|
|
|
|
manager);
|
|
|
|
|
|
2013-02-07 10:54:24 +01:00
|
|
|
|
g_signal_connect (manager->priv->control_proxy,
|
|
|
|
|
"g-signal",
|
|
|
|
|
G_CALLBACK (on_control_proxy_g_signal),
|
|
|
|
|
manager);
|
|
|
|
|
|
2011-04-08 21:14:47 +02:00
|
|
|
|
manager->priv->name_owner = g_dbus_proxy_get_name_owner (manager->priv->control_proxy);
|
2012-10-26 10:30:29 +02:00
|
|
|
|
if (manager->priv->name_owner == NULL && manager->priv->name != NULL)
|
2011-04-08 21:14:47 +02:00
|
|
|
|
{
|
|
|
|
|
/* it's perfectly fine if there's no name owner.. we're just going to
|
|
|
|
|
* wait until one is ready
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2012-10-26 10:30:29 +02:00
|
|
|
|
/* yay, we can get the objects */
|
2011-04-08 21:14:47 +02:00
|
|
|
|
subscribe_signals (manager,
|
|
|
|
|
manager->priv->name_owner);
|
|
|
|
|
value = g_dbus_proxy_call_sync (manager->priv->control_proxy,
|
|
|
|
|
"GetManagedObjects",
|
|
|
|
|
NULL, /* parameters */
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
cancellable,
|
|
|
|
|
error);
|
|
|
|
|
if (value == NULL)
|
|
|
|
|
{
|
|
|
|
|
maybe_unsubscribe_signals (manager);
|
|
|
|
|
g_warn_if_fail (g_signal_handlers_disconnect_by_func (manager->priv->control_proxy,
|
|
|
|
|
on_control_proxy_g_signal,
|
|
|
|
|
manager) == 1);
|
|
|
|
|
g_object_unref (manager->priv->control_proxy);
|
|
|
|
|
manager->priv->control_proxy = NULL;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
process_get_all_result (manager, value, manager->priv->name_owner);
|
|
|
|
|
g_variant_unref (value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = TRUE;
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
initable_iface_init (GInitableIface *initable_iface)
|
|
|
|
|
{
|
|
|
|
|
initable_iface->init = initable_init;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
|
|
|
|
|
{
|
|
|
|
|
/* for now, just use default: run GInitable code in thread */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
add_interfaces (GDBusObjectManagerClient *manager,
|
|
|
|
|
const gchar *object_path,
|
|
|
|
|
GVariant *ifaces_and_properties,
|
|
|
|
|
const gchar *name_owner)
|
|
|
|
|
{
|
|
|
|
|
GDBusObjectProxy *op;
|
|
|
|
|
gboolean added;
|
|
|
|
|
GVariantIter iter;
|
|
|
|
|
const gchar *interface_name;
|
|
|
|
|
GVariant *properties;
|
2011-08-29 22:20:50 +02:00
|
|
|
|
GList *interface_added_signals, *l;
|
|
|
|
|
GDBusProxy *interface_proxy;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
2012-10-26 10:30:29 +02:00
|
|
|
|
g_return_if_fail (name_owner == NULL || g_dbus_is_unique_name (name_owner));
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_lock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
|
|
|
|
|
interface_added_signals = NULL;
|
2011-04-08 21:14:47 +02:00
|
|
|
|
added = FALSE;
|
2011-08-29 22:20:50 +02:00
|
|
|
|
|
2011-04-08 21:14:47 +02:00
|
|
|
|
op = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
|
|
|
|
|
if (op == NULL)
|
|
|
|
|
{
|
2011-04-25 15:29:18 +02:00
|
|
|
|
GType object_proxy_type;
|
|
|
|
|
if (manager->priv->get_proxy_type_func != NULL)
|
|
|
|
|
{
|
|
|
|
|
object_proxy_type = manager->priv->get_proxy_type_func (manager,
|
|
|
|
|
object_path,
|
|
|
|
|
NULL,
|
|
|
|
|
manager->priv->get_proxy_type_user_data);
|
|
|
|
|
g_warn_if_fail (g_type_is_a (object_proxy_type, G_TYPE_DBUS_OBJECT_PROXY));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
object_proxy_type = G_TYPE_DBUS_OBJECT_PROXY;
|
|
|
|
|
}
|
|
|
|
|
op = g_object_new (object_proxy_type,
|
2011-09-21 14:16:43 +02:00
|
|
|
|
"g-connection", manager->priv->connection,
|
|
|
|
|
"g-object-path", object_path,
|
2011-04-25 15:29:18 +02:00
|
|
|
|
NULL);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
added = TRUE;
|
|
|
|
|
}
|
2011-08-29 22:20:50 +02:00
|
|
|
|
g_object_ref (op);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
|
|
|
|
g_variant_iter_init (&iter, ifaces_and_properties);
|
|
|
|
|
while (g_variant_iter_next (&iter,
|
|
|
|
|
"{&s@a{sv}}",
|
|
|
|
|
&interface_name,
|
|
|
|
|
&properties))
|
|
|
|
|
{
|
|
|
|
|
GError *error;
|
|
|
|
|
GType interface_proxy_type;
|
|
|
|
|
|
|
|
|
|
if (manager->priv->get_proxy_type_func != NULL)
|
|
|
|
|
{
|
|
|
|
|
interface_proxy_type = manager->priv->get_proxy_type_func (manager,
|
|
|
|
|
object_path,
|
|
|
|
|
interface_name,
|
|
|
|
|
manager->priv->get_proxy_type_user_data);
|
|
|
|
|
g_warn_if_fail (g_type_is_a (interface_proxy_type, G_TYPE_DBUS_PROXY));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
interface_proxy_type = G_TYPE_DBUS_PROXY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* this is fine - there is no blocking IO because we pass DO_NOT_LOAD_PROPERTIES and
|
|
|
|
|
* DO_NOT_CONNECT_SIGNALS and use a unique name
|
|
|
|
|
*/
|
|
|
|
|
error = NULL;
|
|
|
|
|
interface_proxy = g_initable_new (interface_proxy_type,
|
|
|
|
|
NULL, /* GCancellable */
|
|
|
|
|
&error,
|
|
|
|
|
"g-connection", manager->priv->connection,
|
|
|
|
|
"g-flags", G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
|
|
|
|
|
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
|
|
|
|
"g-name", name_owner,
|
|
|
|
|
"g-object-path", object_path,
|
|
|
|
|
"g-interface-name", interface_name,
|
|
|
|
|
NULL);
|
|
|
|
|
if (interface_proxy == NULL)
|
|
|
|
|
{
|
|
|
|
|
g_warning ("%s: Error constructing proxy for path %s and interface %s: %s",
|
|
|
|
|
G_STRLOC,
|
|
|
|
|
object_path,
|
|
|
|
|
interface_name,
|
|
|
|
|
error->message);
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GVariantIter property_iter;
|
|
|
|
|
const gchar *property_name;
|
|
|
|
|
GVariant *property_value;
|
|
|
|
|
|
|
|
|
|
/* associate the interface proxy with the object */
|
|
|
|
|
g_dbus_interface_set_object (G_DBUS_INTERFACE (interface_proxy),
|
|
|
|
|
G_DBUS_OBJECT (op));
|
|
|
|
|
|
|
|
|
|
g_variant_iter_init (&property_iter, properties);
|
|
|
|
|
while (g_variant_iter_next (&property_iter,
|
|
|
|
|
"{&sv}",
|
|
|
|
|
&property_name,
|
|
|
|
|
&property_value))
|
|
|
|
|
{
|
|
|
|
|
g_dbus_proxy_set_cached_property (interface_proxy,
|
|
|
|
|
property_name,
|
|
|
|
|
property_value);
|
|
|
|
|
g_variant_unref (property_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_g_dbus_object_proxy_add_interface (op, interface_proxy);
|
|
|
|
|
if (!added)
|
2011-08-29 22:20:50 +02:00
|
|
|
|
interface_added_signals = g_list_append (interface_added_signals, g_object_ref (interface_proxy));
|
2011-04-08 21:14:47 +02:00
|
|
|
|
g_object_unref (interface_proxy);
|
|
|
|
|
}
|
|
|
|
|
g_variant_unref (properties);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-30 11:26:29 +02:00
|
|
|
|
if (added)
|
|
|
|
|
{
|
|
|
|
|
g_hash_table_insert (manager->priv->map_object_path_to_object_proxy,
|
|
|
|
|
g_strdup (object_path),
|
|
|
|
|
op);
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
|
|
|
|
|
/* now that we don't hold the lock any more, emit signals */
|
2013-11-27 14:32:05 +01:00
|
|
|
|
g_object_ref (manager);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
for (l = interface_added_signals; l != NULL; l = l->next)
|
|
|
|
|
{
|
|
|
|
|
interface_proxy = G_DBUS_PROXY (l->data);
|
|
|
|
|
g_signal_emit_by_name (manager, "interface-added", op, interface_proxy);
|
|
|
|
|
g_object_unref (interface_proxy);
|
|
|
|
|
}
|
|
|
|
|
g_list_free (interface_added_signals);
|
|
|
|
|
|
2011-04-08 21:14:47 +02:00
|
|
|
|
if (added)
|
2017-09-30 11:26:29 +02:00
|
|
|
|
g_signal_emit_by_name (manager, "object-added", op);
|
|
|
|
|
|
2013-11-27 14:32:05 +01:00
|
|
|
|
g_object_unref (manager);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
g_object_unref (op);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
remove_interfaces (GDBusObjectManagerClient *manager,
|
|
|
|
|
const gchar *object_path,
|
|
|
|
|
const gchar *const *interface_names)
|
|
|
|
|
{
|
|
|
|
|
GDBusObjectProxy *op;
|
|
|
|
|
GList *interfaces;
|
|
|
|
|
guint n;
|
|
|
|
|
guint num_interfaces;
|
|
|
|
|
guint num_interfaces_to_remove;
|
|
|
|
|
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_lock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
|
2011-04-08 21:14:47 +02:00
|
|
|
|
op = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
|
|
|
|
|
if (op == NULL)
|
|
|
|
|
{
|
|
|
|
|
g_warning ("%s: Processing InterfaceRemoved signal for path %s but no object proxy exists",
|
|
|
|
|
G_STRLOC,
|
|
|
|
|
object_path);
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interfaces = g_dbus_object_get_interfaces (G_DBUS_OBJECT (op));
|
|
|
|
|
num_interfaces = g_list_length (interfaces);
|
2012-01-02 16:30:11 +01:00
|
|
|
|
g_list_free_full (interfaces, g_object_unref);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
|
|
|
|
num_interfaces_to_remove = g_strv_length ((gchar **) interface_names);
|
|
|
|
|
|
|
|
|
|
/* see if we are going to completety remove the object */
|
2013-11-27 14:32:05 +01:00
|
|
|
|
g_object_ref (manager);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
if (num_interfaces_to_remove == num_interfaces)
|
|
|
|
|
{
|
|
|
|
|
g_object_ref (op);
|
|
|
|
|
g_warn_if_fail (g_hash_table_remove (manager->priv->map_object_path_to_object_proxy, object_path));
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
g_signal_emit_by_name (manager, "object-removed", op);
|
|
|
|
|
g_object_unref (op);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2011-08-29 22:20:50 +02:00
|
|
|
|
g_object_ref (op);
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
for (n = 0; interface_names != NULL && interface_names[n] != NULL; n++)
|
|
|
|
|
{
|
|
|
|
|
GDBusInterface *interface;
|
|
|
|
|
interface = g_dbus_object_get_interface (G_DBUS_OBJECT (op), interface_names[n]);
|
|
|
|
|
_g_dbus_object_proxy_remove_interface (op, interface_names[n]);
|
|
|
|
|
if (interface != NULL)
|
|
|
|
|
{
|
|
|
|
|
g_signal_emit_by_name (manager, "interface-removed", op, interface);
|
|
|
|
|
g_object_unref (interface);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-08-29 22:20:50 +02:00
|
|
|
|
g_object_unref (op);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
}
|
2013-11-27 14:32:05 +01:00
|
|
|
|
g_object_unref (manager);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
out:
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
process_get_all_result (GDBusObjectManagerClient *manager,
|
|
|
|
|
GVariant *value,
|
|
|
|
|
const gchar *name_owner)
|
|
|
|
|
{
|
|
|
|
|
GVariant *arg0;
|
|
|
|
|
const gchar *object_path;
|
|
|
|
|
GVariant *ifaces_and_properties;
|
|
|
|
|
GVariantIter iter;
|
|
|
|
|
|
2012-10-26 10:30:29 +02:00
|
|
|
|
g_return_if_fail (name_owner == NULL || g_dbus_is_unique_name (name_owner));
|
2011-04-08 21:14:47 +02:00
|
|
|
|
|
|
|
|
|
arg0 = g_variant_get_child_value (value, 0);
|
|
|
|
|
g_variant_iter_init (&iter, arg0);
|
|
|
|
|
while (g_variant_iter_next (&iter,
|
|
|
|
|
"{&o@a{sa{sv}}}",
|
|
|
|
|
&object_path,
|
|
|
|
|
&ifaces_and_properties))
|
|
|
|
|
{
|
|
|
|
|
add_interfaces (manager, object_path, ifaces_and_properties, name_owner);
|
|
|
|
|
g_variant_unref (ifaces_and_properties);
|
|
|
|
|
}
|
|
|
|
|
g_variant_unref (arg0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
on_control_proxy_g_signal (GDBusProxy *proxy,
|
|
|
|
|
const gchar *sender_name,
|
|
|
|
|
const gchar *signal_name,
|
|
|
|
|
GVariant *parameters,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (user_data);
|
|
|
|
|
const gchar *object_path;
|
|
|
|
|
|
|
|
|
|
//g_debug ("yay, g_signal %s: %s\n", signal_name, g_variant_print (parameters, TRUE));
|
|
|
|
|
|
|
|
|
|
if (g_strcmp0 (signal_name, "InterfacesAdded") == 0)
|
|
|
|
|
{
|
|
|
|
|
GVariant *ifaces_and_properties;
|
|
|
|
|
g_variant_get (parameters,
|
|
|
|
|
"(&o@a{sa{sv}})",
|
|
|
|
|
&object_path,
|
|
|
|
|
&ifaces_and_properties);
|
|
|
|
|
add_interfaces (manager, object_path, ifaces_and_properties, manager->priv->name_owner);
|
|
|
|
|
g_variant_unref (ifaces_and_properties);
|
|
|
|
|
}
|
|
|
|
|
else if (g_strcmp0 (signal_name, "InterfacesRemoved") == 0)
|
|
|
|
|
{
|
|
|
|
|
const gchar **ifaces;
|
|
|
|
|
g_variant_get (parameters,
|
|
|
|
|
"(&o^a&s)",
|
|
|
|
|
&object_path,
|
|
|
|
|
&ifaces);
|
|
|
|
|
remove_interfaces (manager, object_path, ifaces);
|
|
|
|
|
g_free (ifaces);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
static const gchar *
|
|
|
|
|
g_dbus_object_manager_client_get_object_path (GDBusObjectManager *_manager)
|
|
|
|
|
{
|
|
|
|
|
GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_manager);
|
|
|
|
|
return manager->priv->object_path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GDBusObject *
|
|
|
|
|
g_dbus_object_manager_client_get_object (GDBusObjectManager *_manager,
|
|
|
|
|
const gchar *object_path)
|
|
|
|
|
{
|
|
|
|
|
GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_manager);
|
|
|
|
|
GDBusObject *ret;
|
|
|
|
|
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_lock (&manager->priv->lock);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
ret = g_hash_table_lookup (manager->priv->map_object_path_to_object_proxy, object_path);
|
|
|
|
|
if (ret != NULL)
|
|
|
|
|
g_object_ref (ret);
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GDBusInterface *
|
|
|
|
|
g_dbus_object_manager_client_get_interface (GDBusObjectManager *_manager,
|
|
|
|
|
const gchar *object_path,
|
|
|
|
|
const gchar *interface_name)
|
|
|
|
|
{
|
|
|
|
|
GDBusInterface *ret;
|
|
|
|
|
GDBusObject *object;
|
|
|
|
|
|
|
|
|
|
ret = NULL;
|
|
|
|
|
|
|
|
|
|
object = g_dbus_object_manager_get_object (_manager, object_path);
|
|
|
|
|
if (object == NULL)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
ret = g_dbus_object_get_interface (object, interface_name);
|
|
|
|
|
g_object_unref (object);
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GList *
|
|
|
|
|
g_dbus_object_manager_client_get_objects (GDBusObjectManager *_manager)
|
|
|
|
|
{
|
|
|
|
|
GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (_manager);
|
|
|
|
|
GList *ret;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager), NULL);
|
|
|
|
|
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_lock (&manager->priv->lock);
|
2011-04-08 21:14:47 +02:00
|
|
|
|
ret = g_hash_table_get_values (manager->priv->map_object_path_to_object_proxy);
|
|
|
|
|
g_list_foreach (ret, (GFunc) g_object_ref, NULL);
|
2011-10-04 05:26:55 +02:00
|
|
|
|
g_mutex_unlock (&manager->priv->lock);
|
2011-08-29 22:20:50 +02:00
|
|
|
|
|
2011-04-08 21:14:47 +02:00
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
dbus_object_manager_interface_init (GDBusObjectManagerIface *iface)
|
|
|
|
|
{
|
|
|
|
|
iface->get_object_path = g_dbus_object_manager_client_get_object_path;
|
|
|
|
|
iface->get_objects = g_dbus_object_manager_client_get_objects;
|
|
|
|
|
iface->get_object = g_dbus_object_manager_client_get_object;
|
|
|
|
|
iface->get_interface = g_dbus_object_manager_client_get_interface;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|