diff options
author | Sebastien Bacher <seb128@ubuntu.com> | 2012-07-11 21:39:51 +0200 |
---|---|---|
committer | Sebastien Bacher <seb128@ubuntu.com> | 2012-07-11 21:39:51 +0200 |
commit | 4af0bd2bf3acca2dc08656ba0e7105a28e2d0d1b (patch) | |
tree | 403adab544ae9d295497f0c9d5eee5eb2d37c3a3 /src/dbus-listener.c | |
parent | 109d4fe4271cef7438273eb5a24b719a73e9a4fb (diff) | |
parent | 7bc1a483d52707854f6f813fbbbed4709fe38f34 (diff) | |
download | ayatana-indicator-power-4af0bd2bf3acca2dc08656ba0e7105a28e2d0d1b.tar.gz ayatana-indicator-power-4af0bd2bf3acca2dc08656ba0e7105a28e2d0d1b.tar.bz2 ayatana-indicator-power-4af0bd2bf3acca2dc08656ba0e7105a28e2d0d1b.zip |
Import upstream version 12.10.0
Diffstat (limited to 'src/dbus-listener.c')
-rw-r--r-- | src/dbus-listener.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/src/dbus-listener.c b/src/dbus-listener.c new file mode 100644 index 0000000..b1f64a7 --- /dev/null +++ b/src/dbus-listener.c @@ -0,0 +1,247 @@ +/* + +Listens on DBus for Power changes and passes them to an IndicatorPower + +Copyright 2012 Canonical Ltd. + +Authors: + Charles Kerr <charles.kerr@canonical.com> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 3.0 as published by the Free Software Foundation. + +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 General Public License version 3.0 for more details. + +You should have received a copy of the GNU General Public +License along with this library. If not, see +<http://www.gnu.org/licenses/>. +*/ + +#include "dbus-listener.h" +#include "device.h" + +struct _IndicatorPowerDbusListenerPrivate +{ + GCancellable * cancellable; + GDBusProxy * proxy; + guint watcher_id; +}; + +#define INDICATOR_POWER_DBUS_LISTENER_GET_PRIVATE(o) (INDICATOR_POWER_DBUS_LISTENER(o)->priv) + +/* Signals */ +enum { + SIGNAL_DEVICES, + SIGNAL_LAST +}; +static guint signals[SIGNAL_LAST] = { 0 }; + + +/* GObject stuff */ +static void indicator_power_dbus_listener_class_init (IndicatorPowerDbusListenerClass *klass); +static void indicator_power_dbus_listener_init (IndicatorPowerDbusListener *self); +static void indicator_power_dbus_listener_dispose (GObject *object); +static void indicator_power_dbus_listener_finalize (GObject *object); + +static void gsd_appeared_callback (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data); + +/* LCOV_EXCL_START */ +G_DEFINE_TYPE (IndicatorPowerDbusListener, indicator_power_dbus_listener, G_TYPE_OBJECT); +/* LCOV_EXCL_STOP */ + +static void +indicator_power_dbus_listener_class_init (IndicatorPowerDbusListenerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (IndicatorPowerDbusListenerPrivate)); + + /* methods */ + object_class->dispose = indicator_power_dbus_listener_dispose; + object_class->finalize = indicator_power_dbus_listener_finalize; + + /** + * IndicatorPowerDbusListener::devices-enumerated: + * + * @listener: the IndicatorPowerDbusListener + * @devices: a GSList of #IndicatorPowerDevice objects. (transfer none) + * + * This is emitted each time a new set of devices is enumerated over the bus. + */ + signals[SIGNAL_DEVICES] = g_signal_new (INDICATOR_POWER_DBUS_LISTENER_DEVICES_ENUMERATED, + G_TYPE_FROM_CLASS(klass), 0, + G_STRUCT_OFFSET (IndicatorPowerDbusListenerClass, devices_enumerated), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); +} + +/* Initialize an instance */ +static void +indicator_power_dbus_listener_init (IndicatorPowerDbusListener *self) +{ + IndicatorPowerDbusListenerPrivate * priv; + + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + INDICATOR_POWER_DBUS_LISTENER_TYPE, + IndicatorPowerDbusListenerPrivate); + + priv->cancellable = g_cancellable_new (); + + priv->watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION, + GSD_SERVICE, + G_BUS_NAME_WATCHER_FLAGS_NONE, + gsd_appeared_callback, + NULL, + self, + NULL); + + self->priv = priv; +} + +static void +indicator_power_dbus_listener_dispose (GObject *object) +{ + IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(object); + IndicatorPowerDbusListenerPrivate * priv = self->priv; + + g_clear_object (&priv->proxy); + + if (priv->cancellable != NULL) + { + g_cancellable_cancel (priv->cancellable); + g_clear_object (&priv->cancellable); + } + + if (priv->watcher_id) + { + g_bus_unwatch_name (priv->watcher_id); + priv->watcher_id = 0; + } + + G_OBJECT_CLASS (indicator_power_dbus_listener_parent_class)->dispose (object); +} + +static void +indicator_power_dbus_listener_finalize (GObject *object) +{ + G_OBJECT_CLASS (indicator_power_dbus_listener_parent_class)->finalize (object); +} + +/*** +**** +***/ + +static void +get_devices_cb (GObject * source_object, + GAsyncResult * res, + gpointer user_data) +{ + GError *error; + GSList * devices = NULL; + GVariant * devices_container; + IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER (user_data); + + /* build an array of IndicatorPowerDevices from the DBus response */ + error = NULL; + devices_container = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); + if (devices_container == NULL) + { + g_message ("Couldn't get devices: %s\n", error->message); + g_error_free (error); + } + else + { + gsize i; + GVariant * devices_variant = g_variant_get_child_value (devices_container, 0); + const int device_count = devices_variant ? g_variant_n_children (devices_variant) : 0; + + for (i=0; i<device_count; i++) + { + GVariant * v = g_variant_get_child_value (devices_variant, i); + devices = g_slist_prepend (devices, indicator_power_device_new_from_variant (v)); + g_variant_unref (v); + } + + devices = g_slist_reverse (devices); + + g_variant_unref (devices_variant); + g_variant_unref (devices_container); + } + + g_signal_emit (self, signals[SIGNAL_DEVICES], (GQuark)0, devices); + g_slist_free_full (devices, g_object_unref); +} + +static void +request_device_list (IndicatorPowerDbusListener * self) +{ + g_dbus_proxy_call (self->priv->proxy, + "GetDevices", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + self->priv->cancellable, + get_devices_cb, + self); +} + +static void +receive_properties_changed (GDBusProxy *proxy G_GNUC_UNUSED, + GVariant *changed_properties G_GNUC_UNUSED, + GStrv invalidated_properties G_GNUC_UNUSED, + gpointer user_data) +{ + request_device_list (INDICATOR_POWER_DBUS_LISTENER(user_data)); +} + + +static void +service_proxy_cb (GObject *object, + GAsyncResult *res, + gpointer user_data) +{ + GError * error = NULL; + IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(user_data); + IndicatorPowerDbusListenerPrivate * priv = self->priv; + + priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (error != NULL) + { + g_error ("Error creating proxy: %s", error->message); + g_error_free (error); + return; + } + + /* we want to change the primary device changes */ + g_signal_connect (priv->proxy, "g-properties-changed", + G_CALLBACK (receive_properties_changed), user_data); + + /* get the initial state */ + request_device_list (self); +} + +static void +gsd_appeared_callback (GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(user_data); + IndicatorPowerDbusListenerPrivate * priv = self->priv; + + g_dbus_proxy_new (connection, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + name, + GSD_POWER_DBUS_PATH, + GSD_POWER_DBUS_INTERFACE, + priv->cancellable, + service_proxy_cb, + self); +} |