diff options
Diffstat (limited to 'panels/thunderbolt/bolt-proxy.c')
-rw-r--r-- | panels/thunderbolt/bolt-proxy.c | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/panels/thunderbolt/bolt-proxy.c b/panels/thunderbolt/bolt-proxy.c new file mode 100644 index 0000000..e044c87 --- /dev/null +++ b/panels/thunderbolt/bolt-proxy.c @@ -0,0 +1,514 @@ +/* + * Copyright © 2017 Red Hat, Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Christian J. Kellner <christian@kellner.me> + */ + +#include "bolt-proxy.h" + +#include "bolt-enums.h" +#include "bolt-error.h" +#include "bolt-names.h" +#include "bolt-str.h" + +static void bolt_proxy_handle_props_changed (GDBusProxy *proxy, + GVariant *changed_properties, + GStrv invalidated_properties, + gpointer user_data); + +static void bolt_proxy_handle_dbus_signal (GDBusProxy *proxy, + const gchar *sender_name, + const gchar *signal_name, + GVariant *params, + gpointer user_data); + +G_DEFINE_TYPE (BoltProxy, bolt_proxy, G_TYPE_DBUS_PROXY); + + +static void +bolt_proxy_constructed (GObject *object) +{ + G_OBJECT_CLASS (bolt_proxy_parent_class)->constructed (object); + + g_signal_connect (object, "g-properties-changed", + G_CALLBACK (bolt_proxy_handle_props_changed), object); + + g_signal_connect (object, "g-signal", + G_CALLBACK (bolt_proxy_handle_dbus_signal), object); +} + +static const BoltProxySignal * +bolt_proxy_get_dbus_signals (guint *n) +{ + *n = 0; + return NULL; +} + +static void +bolt_proxy_class_init (BoltProxyClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->constructed = bolt_proxy_constructed; + + klass->get_dbus_signals = bolt_proxy_get_dbus_signals; + +} + +static void +bolt_proxy_init (BoltProxy *object) +{ +} + +static void +bolt_proxy_handle_props_changed (GDBusProxy *proxy, + GVariant *changed_properties, + GStrv invalidated_properties, + gpointer user_data) +{ + g_autoptr(GVariantIter) iter = NULL; + gboolean handled; + GParamSpec **pp; + const char *key; + guint n; + + pp = g_object_class_list_properties (G_OBJECT_GET_CLASS (proxy), &n); + + g_variant_get (changed_properties, "a{sv}", &iter); + while (g_variant_iter_next (iter, "{&sv}", &key, NULL)) + { + handled = FALSE; + for (guint i = 0; !handled && i < n; i++) + { + GParamSpec *pspec = pp[i]; + const char *nick; + const char *name; + + nick = g_param_spec_get_nick (pspec); + name = g_param_spec_get_name (pspec); + + handled = bolt_streq (nick, key); + + if (handled) + g_object_notify (G_OBJECT (user_data), name); + } + } + + g_free (pp); +} + +static void +bolt_proxy_handle_dbus_signal (GDBusProxy *proxy, + const gchar *sender_name, + const gchar *signal_name, + GVariant *params, + gpointer user_data) +{ + const BoltProxySignal *ps; + guint n; + + if (signal_name == NULL) + return; + + ps = BOLT_PROXY_GET_CLASS (proxy)->get_dbus_signals (&n); + + for (guint i = 0; i < n; i++) + { + const BoltProxySignal *sig = &ps[i]; + + if (g_str_equal (sig->theirs, signal_name)) + { + sig->handle (G_OBJECT (proxy), proxy, params); + break; + } + } + +} + +/* public methods */ + +gboolean +bolt_proxy_get_dbus_property (GObject *proxy, + GParamSpec *spec, + GValue *value) +{ + g_autoptr(GVariant) val = NULL; + const GVariantType *vt; + gboolean handled = FALSE; + const char *nick; + + nick = g_param_spec_get_nick (spec); + val = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), nick); + + if (val == NULL) + return FALSE; + + vt = g_variant_get_type (val); + + if (g_variant_type_equal (vt, G_VARIANT_TYPE_STRING) && + G_IS_PARAM_SPEC_ENUM (spec)) + { + GParamSpecEnum *enum_spec = G_PARAM_SPEC_ENUM (spec); + GEnumValue *ev; + const char *str; + + str = g_variant_get_string (val, NULL); + ev = g_enum_get_value_by_nick (enum_spec->enum_class, str); + + handled = ev != NULL; + + if (handled) + g_value_set_enum (value, ev->value); + else + g_value_set_enum (value, enum_spec->default_value); + } + else if (g_variant_type_equal (vt, G_VARIANT_TYPE_STRING) && + G_IS_PARAM_SPEC_FLAGS (spec)) + { + GParamSpecFlags *flags_spec = G_PARAM_SPEC_FLAGS (spec); + GFlagsClass *flags_class = flags_spec->flags_class; + const char *str; + guint v; + + str = g_variant_get_string (val, NULL); + handled = bolt_flags_class_from_string (flags_class, str, &v, NULL); + + if (handled) + g_value_set_flags (value, v); + else + g_value_set_flags (value, flags_spec->default_value); + } + else + { + g_dbus_gvariant_to_gvalue (val, value); + } + + return handled; +} + +gboolean +bolt_proxy_has_name_owner (BoltProxy *proxy) +{ + const char *name_owner; + + g_return_val_if_fail (proxy != NULL, FALSE); + g_return_val_if_fail (BOLT_IS_PROXY (proxy), FALSE); + + name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (proxy)); + + return name_owner != NULL; +} + +static GParamSpec * +find_property (BoltProxy *proxy, + const char *name, + GError **error) +{ + GParamSpec *res = NULL; + GParamSpec **pp; + guint n; + + pp = g_object_class_list_properties (G_OBJECT_GET_CLASS (proxy), &n); + + for (guint i = 0; i < n; i++) + { + GParamSpec *pspec = pp[i]; + + if (bolt_streq (pspec->name, name)) + { + res = pspec; + break; + } + } + + if (pp == NULL) + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_PROPERTY, + "could not find property '%s'", name); + + g_free (pp); + return res; +} + +static GVariant * +bolt_proxy_get_cached_property (BoltProxy *proxy, + const char *name) +{ + const char *bus_name = NULL; + GParamSpec *pspec; + GVariant *var; + + g_return_val_if_fail (BOLT_IS_PROXY (proxy), NULL); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (proxy), name); + + if (pspec == NULL) + return NULL; + + bus_name = g_param_spec_get_nick (pspec); + var = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), bus_name); + + return var; +} + +gboolean +bolt_proxy_get_property_bool (BoltProxy *proxy, + const char *name, + gboolean *value) +{ + g_autoptr(GVariant) var = NULL; + + var = bolt_proxy_get_cached_property (proxy, name); + + if (var == NULL) + return FALSE; + else if (value) + *value = g_variant_get_boolean (var); + + return TRUE; +} + +gboolean +bolt_proxy_get_property_enum (BoltProxy *proxy, + const char *name, + gint *value) +{ + g_autoptr(GVariant) var = NULL; + const char *str = NULL; + const char *bus_name = NULL; + GParamSpec *pspec; + GEnumValue *ev; + + g_return_val_if_fail (BOLT_IS_PROXY (proxy), FALSE); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (proxy), name); + + if (pspec == NULL) + return FALSE; + + bus_name = g_param_spec_get_nick (pspec); + var = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), bus_name); + if (var == NULL) + return FALSE; + + str = g_variant_get_string (var, NULL); + + if (str == NULL) + return FALSE; + + ev = g_enum_get_value_by_nick (G_PARAM_SPEC_ENUM (pspec)->enum_class, str); + + if (ev == NULL) + return FALSE; + + if (value) + *value = ev->value; + + return TRUE; +} + +gboolean +bolt_proxy_get_property_flags (BoltProxy *proxy, + const char *name, + guint *value) +{ + g_autoptr(GVariant) var = NULL; + const char *str = NULL; + const char *bus_name = NULL; + GFlagsClass *flags_class; + GParamSpec *pspec; + guint v; + gboolean ok; + + g_return_val_if_fail (BOLT_IS_PROXY (proxy), FALSE); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (proxy), name); + + if (pspec == NULL || !G_IS_PARAM_SPEC_FLAGS (pspec)) + return FALSE; + + bus_name = g_param_spec_get_nick (pspec); + var = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), bus_name); + if (var == NULL) + return FALSE; + + str = g_variant_get_string (var, NULL); + + if (str == NULL) + return FALSE; + + flags_class = G_PARAM_SPEC_FLAGS (pspec)->flags_class; + ok = bolt_flags_class_from_string (flags_class, str, &v, NULL); + + if (ok && value) + *value = v; + + return ok; +} + +gboolean +bolt_proxy_get_property_uint32 (BoltProxy *proxy, + const char *name, + guint *value) +{ + g_autoptr(GVariant) var = NULL; + + var = bolt_proxy_get_cached_property (proxy, name); + + if (var == NULL) + return FALSE; + else if (value) + *value = g_variant_get_uint32 (var); + + return TRUE; +} + +gboolean +bolt_proxy_get_property_int64 (BoltProxy *proxy, + const char *name, + gint64 *value) +{ + g_autoptr(GVariant) var = NULL; + + var = bolt_proxy_get_cached_property (proxy, name); + + if (var == NULL) + return FALSE; + else if (value) + *value = g_variant_get_int64 (var); + + return TRUE; +} + +gboolean +bolt_proxy_get_property_uint64 (BoltProxy *proxy, + const char *name, + guint64 *value) +{ + g_autoptr(GVariant) var = NULL; + + var = bolt_proxy_get_cached_property (proxy, name); + + if (var == NULL) + return FALSE; + else if (value) + *value = g_variant_get_uint64 (var); + + return TRUE; +} + +const char * +bolt_proxy_get_property_string (BoltProxy *proxy, + const char *name) +{ + g_autoptr(GVariant) var = NULL; + const char *val = NULL; + + var = bolt_proxy_get_cached_property (proxy, name); + + if (var != NULL) + val = g_variant_get_string (var, NULL); + + if (val && *val == '\0') + val = NULL; + + return val; +} + +gboolean +bolt_proxy_set_property (BoltProxy *proxy, + const char *name, + GVariant *value, + GCancellable *cancellable, + GError **error) +{ + GParamSpec *pp; + const char *iface; + gboolean ok = FALSE; + GVariant *res; + + pp = find_property (proxy, name, NULL); + if (pp != NULL) + name = g_param_spec_get_nick (pp); + + iface = g_dbus_proxy_get_interface_name (G_DBUS_PROXY (proxy)); + + res = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy), + "org.freedesktop.DBus.Properties.Set", + g_variant_new ("(ssv)", + iface, + name, + value), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + + if (res) + { + g_variant_unref (res); + ok = TRUE; + } + + return ok; +} + +void +bolt_proxy_set_property_async (BoltProxy *proxy, + const char *name, + GVariant *value, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GParamSpec *pp; + const char *iface; + + pp = find_property (proxy, name, NULL); + + if (pp != NULL) + name = g_param_spec_get_nick (pp); + + iface = g_dbus_proxy_get_interface_name (G_DBUS_PROXY (proxy)); + + g_dbus_proxy_call (G_DBUS_PROXY (proxy), + "org.freedesktop.DBus.Properties.Set", + g_variant_new ("(ssv)", + iface, + name, + value), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + callback, + user_data); +} + +gboolean +bolt_proxy_set_property_finish (GAsyncResult *res, + GError **error) +{ + BoltProxy *proxy; + GVariant *val = NULL; + + proxy = (BoltProxy *) g_async_result_get_source_object (res); + val = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error); + + if (val == NULL) + return FALSE; + + g_variant_unref (val); + return TRUE; +} |