mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-30 17:36:16 +01:00
32f2e9a85b
Allow constructing a GDBusProxy for well-known names as discussed here http://mail.gnome.org/archives/gtk-devel-list/2009-October/msg00075.html including test cases. Make it possible to create a GDBusProxy for a GBusType instead of a GDBusConnection. This requires G_BUS_TYPE_NONE so add that too. Nuke g_bus_watch_proxy() since one can now more or less use GDBusProxy for this. Port gdbus-example-watch-proxy to this new API and include this example in the GDBusProxy doc page. Also nuke the GType parameter from the GDBusProxy constructors as requested here: https://bugzilla.gnome.org/show_bug.cgi?id=621229 Also update the porting guide and other API docs for this change. Also fix a bug in the signal dispatching code so each subscriber only get notified once, not N times, for the same signal. Also add a test case for this. https://bugzilla.gnome.org/show_bug.cgi?id=621213 Signed-off-by: David Zeuthen <davidz@redhat.com>
233 lines
7.1 KiB
C
233 lines
7.1 KiB
C
#include <gio/gio.h>
|
|
|
|
static gchar *opt_name = NULL;
|
|
static gchar *opt_object_path = NULL;
|
|
static gchar *opt_interface = NULL;
|
|
static gboolean opt_system_bus = FALSE;
|
|
static gboolean opt_no_auto_start = FALSE;
|
|
static gboolean opt_no_properties = FALSE;
|
|
|
|
static GOptionEntry opt_entries[] =
|
|
{
|
|
{ "name", 'n', 0, G_OPTION_ARG_STRING, &opt_name, "Name of the remote object to watch", NULL },
|
|
{ "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_object_path, "Object path of the remote object", NULL },
|
|
{ "interface", 'i', 0, G_OPTION_ARG_STRING, &opt_interface, "D-Bus interface of remote object", NULL },
|
|
{ "system-bus", 's', 0, G_OPTION_ARG_NONE, &opt_system_bus, "Use the system-bus instead of the session-bus", NULL },
|
|
{ "no-auto-start", 'a', 0, G_OPTION_ARG_NONE, &opt_no_auto_start, "Don't instruct the bus to launch an owner for the name", NULL},
|
|
{ "no-properties", 'p', 0, G_OPTION_ARG_NONE, &opt_no_properties, "Do not load properties", NULL},
|
|
{ NULL}
|
|
};
|
|
|
|
static GMainLoop *loop = NULL;
|
|
|
|
static void
|
|
print_properties (GDBusProxy *proxy)
|
|
{
|
|
gchar **property_names;
|
|
guint n;
|
|
|
|
g_print (" properties:\n");
|
|
|
|
property_names = g_dbus_proxy_get_cached_property_names (proxy);
|
|
for (n = 0; property_names != NULL && property_names[n] != NULL; n++)
|
|
{
|
|
const gchar *key = property_names[n];
|
|
GVariant *value;
|
|
gchar *value_str;
|
|
value = g_dbus_proxy_get_cached_property (proxy, key);
|
|
value_str = g_variant_print (value, TRUE);
|
|
g_print (" %s -> %s\n", key, value_str);
|
|
g_variant_unref (value);
|
|
g_free (value_str);
|
|
}
|
|
g_strfreev (property_names);
|
|
}
|
|
|
|
static void
|
|
on_properties_changed (GDBusProxy *proxy,
|
|
GVariant *changed_properties,
|
|
const gchar* const *invalidated_properties,
|
|
gpointer user_data)
|
|
{
|
|
/* Note that we are guaranteed that changed_properties and
|
|
* invalidated_properties are never NULL
|
|
*/
|
|
|
|
if (g_variant_n_children (changed_properties) > 0)
|
|
{
|
|
GVariantIter *iter;
|
|
const gchar *key;
|
|
GVariant *value;
|
|
|
|
g_print (" *** Properties Changed:\n");
|
|
g_variant_get (changed_properties,
|
|
"a{sv}",
|
|
&iter);
|
|
while (g_variant_iter_loop (iter, "{&sv}", &key, &value))
|
|
{
|
|
gchar *value_str;
|
|
value_str = g_variant_print (value, TRUE);
|
|
g_print (" %s -> %s\n", key, value_str);
|
|
g_free (value_str);
|
|
}
|
|
g_variant_iter_free (iter);
|
|
}
|
|
|
|
if (g_strv_length ((GStrv) invalidated_properties) > 0)
|
|
{
|
|
guint n;
|
|
g_print (" *** Properties Invalidated:\n");
|
|
for (n = 0; invalidated_properties[n] != NULL; n++)
|
|
{
|
|
const gchar *key = invalidated_properties[n];
|
|
g_print (" %s\n", key);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
on_signal (GDBusProxy *proxy,
|
|
gchar *sender_name,
|
|
gchar *signal_name,
|
|
GVariant *parameters,
|
|
gpointer user_data)
|
|
{
|
|
gchar *parameters_str;
|
|
|
|
parameters_str = g_variant_print (parameters, TRUE);
|
|
g_print (" *** Received Signal: %s: %s\n",
|
|
signal_name,
|
|
parameters_str);
|
|
g_free (parameters_str);
|
|
}
|
|
|
|
static void
|
|
print_proxy (GDBusProxy *proxy)
|
|
{
|
|
gchar *name_owner;
|
|
|
|
name_owner = g_dbus_proxy_get_name_owner (proxy);
|
|
if (name_owner != NULL)
|
|
{
|
|
g_print ("+++ Proxy object points to remote object owned by %s\n"
|
|
" bus: %s\n"
|
|
" name: %s\n"
|
|
" object path: %s\n"
|
|
" interface: %s\n",
|
|
name_owner,
|
|
opt_system_bus ? "System Bus" : "Session Bus",
|
|
opt_name,
|
|
opt_object_path,
|
|
opt_interface);
|
|
print_properties (proxy);
|
|
}
|
|
else
|
|
{
|
|
g_print ("--- Proxy object is inert - there is no name owner for the name\n"
|
|
" bus: %s\n"
|
|
" name: %s\n"
|
|
" object path: %s\n"
|
|
" interface: %s\n",
|
|
opt_system_bus ? "System Bus" : "Session Bus",
|
|
opt_name,
|
|
opt_object_path,
|
|
opt_interface);
|
|
}
|
|
g_free (name_owner);
|
|
}
|
|
|
|
static void
|
|
on_name_owner_notify (GObject *object,
|
|
GParamSpec *pspec,
|
|
gpointer user_data)
|
|
{
|
|
GDBusProxy *proxy = G_DBUS_PROXY (object);
|
|
print_proxy (proxy);
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
GOptionContext *opt_context;
|
|
GError *error;
|
|
GDBusProxyFlags flags;
|
|
GDBusProxy *proxy;
|
|
|
|
g_type_init ();
|
|
|
|
loop = NULL;
|
|
proxy = NULL;
|
|
|
|
opt_context = g_option_context_new ("g_bus_watch_proxy() example");
|
|
g_option_context_set_summary (opt_context,
|
|
"Example: to watch the object of gdbus-example-server, use:\n"
|
|
"\n"
|
|
" ./gdbus-example-watch-proxy -n org.gtk.GDBus.TestServer \\\n"
|
|
" -o /org/gtk/GDBus/TestObject \\\n"
|
|
" -i org.gtk.GDBus.TestInterface");
|
|
g_option_context_add_main_entries (opt_context, opt_entries, NULL);
|
|
error = NULL;
|
|
if (!g_option_context_parse (opt_context, &argc, &argv, &error))
|
|
{
|
|
g_printerr ("Error parsing options: %s\n", error->message);
|
|
goto out;
|
|
}
|
|
if (opt_name == NULL || opt_object_path == NULL || opt_interface == NULL)
|
|
{
|
|
g_printerr ("Incorrect usage, try --help.\n");
|
|
goto out;
|
|
}
|
|
|
|
flags = G_DBUS_PROXY_FLAGS_NONE;
|
|
if (opt_no_properties)
|
|
flags |= G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES;
|
|
if (opt_no_auto_start)
|
|
flags |= G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START;
|
|
|
|
loop = g_main_loop_new (NULL, FALSE);
|
|
|
|
error = NULL;
|
|
proxy = g_dbus_proxy_new_for_bus_sync (opt_system_bus ? G_BUS_TYPE_SYSTEM : G_BUS_TYPE_SESSION,
|
|
flags,
|
|
NULL, /* GDBusInterfaceInfo */
|
|
opt_name,
|
|
opt_object_path,
|
|
opt_interface,
|
|
NULL, /* GCancellable */
|
|
&error);
|
|
if (proxy == NULL)
|
|
{
|
|
g_printerr ("Error creating proxy: %s\n", error->message);
|
|
g_error_free (error);
|
|
goto out;
|
|
}
|
|
|
|
g_signal_connect (proxy,
|
|
"g-properties-changed",
|
|
G_CALLBACK (on_properties_changed),
|
|
NULL);
|
|
g_signal_connect (proxy,
|
|
"g-signal",
|
|
G_CALLBACK (on_signal),
|
|
NULL);
|
|
g_signal_connect (proxy,
|
|
"notify::g-name-owner",
|
|
G_CALLBACK (on_name_owner_notify),
|
|
NULL);
|
|
print_proxy (proxy);
|
|
|
|
g_main_loop_run (loop);
|
|
|
|
out:
|
|
if (proxy != NULL)
|
|
g_object_unref (proxy);
|
|
if (loop != NULL)
|
|
g_main_loop_unref (loop);
|
|
g_option_context_free (opt_context);
|
|
g_free (opt_name);
|
|
g_free (opt_object_path);
|
|
g_free (opt_interface);
|
|
|
|
return 0;
|
|
}
|