Back to index

indicator-power  12.10.0
dbus-listener.c
Go to the documentation of this file.
00001 /*
00002 
00003 Listens on DBus for Power changes and passes them to an IndicatorPower
00004 
00005 Copyright 2012 Canonical Ltd.
00006 
00007 Authors:
00008     Charles Kerr <charles.kerr@canonical.com>
00009 
00010 This library is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 version 3.0 as published by the Free Software Foundation.
00013 
00014 This library is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 GNU General Public License version 3.0 for more details.
00018 
00019 You should have received a copy of the GNU General Public
00020 License along with this library. If not, see
00021 <http://www.gnu.org/licenses/>.
00022 */
00023 
00024 #include "dbus-listener.h"
00025 #include "device.h"
00026 
00027 struct _IndicatorPowerDbusListenerPrivate
00028 {
00029   GCancellable * cancellable;
00030   GDBusProxy * proxy;
00031   guint watcher_id;
00032 };
00033 
00034 #define INDICATOR_POWER_DBUS_LISTENER_GET_PRIVATE(o) (INDICATOR_POWER_DBUS_LISTENER(o)->priv)
00035 
00036 /* Signals */
00037 enum {
00038   SIGNAL_DEVICES,
00039   SIGNAL_LAST
00040 };
00041 static guint signals[SIGNAL_LAST] = { 0 };
00042 
00043 
00044 /* GObject stuff */
00045 static void indicator_power_dbus_listener_class_init (IndicatorPowerDbusListenerClass *klass);
00046 static void indicator_power_dbus_listener_init       (IndicatorPowerDbusListener *self);
00047 static void indicator_power_dbus_listener_dispose    (GObject *object);
00048 static void indicator_power_dbus_listener_finalize   (GObject *object);
00049 
00050 static void gsd_appeared_callback (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data);
00051 
00052 /* LCOV_EXCL_START */
00053 G_DEFINE_TYPE (IndicatorPowerDbusListener, indicator_power_dbus_listener, G_TYPE_OBJECT);
00054 /* LCOV_EXCL_STOP */
00055 
00056 static void
00057 indicator_power_dbus_listener_class_init (IndicatorPowerDbusListenerClass *klass)
00058 {
00059   GObjectClass *object_class = G_OBJECT_CLASS (klass);
00060 
00061   g_type_class_add_private (klass, sizeof (IndicatorPowerDbusListenerPrivate));
00062 
00063   /* methods */
00064   object_class->dispose = indicator_power_dbus_listener_dispose;
00065   object_class->finalize = indicator_power_dbus_listener_finalize;
00066 
00075   signals[SIGNAL_DEVICES] = g_signal_new (INDICATOR_POWER_DBUS_LISTENER_DEVICES_ENUMERATED,
00076                                           G_TYPE_FROM_CLASS(klass), 0,
00077                                           G_STRUCT_OFFSET (IndicatorPowerDbusListenerClass, devices_enumerated),
00078                                           NULL, NULL,
00079                                           g_cclosure_marshal_VOID__POINTER,
00080                                           G_TYPE_NONE, 1, G_TYPE_POINTER);
00081 }
00082 
00083 /* Initialize an instance */
00084 static void
00085 indicator_power_dbus_listener_init (IndicatorPowerDbusListener *self)
00086 {
00087   IndicatorPowerDbusListenerPrivate * priv;
00088 
00089   priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
00090                                       INDICATOR_POWER_DBUS_LISTENER_TYPE,
00091                                       IndicatorPowerDbusListenerPrivate);
00092 
00093   priv->cancellable = g_cancellable_new ();
00094 
00095   priv->watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
00096                                        GSD_SERVICE,
00097                                        G_BUS_NAME_WATCHER_FLAGS_NONE,
00098                                        gsd_appeared_callback,
00099                                        NULL,
00100                                        self,
00101                                        NULL);
00102 
00103   self->priv = priv;
00104 }
00105 
00106 static void
00107 indicator_power_dbus_listener_dispose (GObject *object)
00108 {
00109   IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(object);
00110   IndicatorPowerDbusListenerPrivate * priv = self->priv;
00111 
00112   g_clear_object (&priv->proxy);
00113 
00114   if (priv->cancellable != NULL)
00115     {
00116       g_cancellable_cancel (priv->cancellable);
00117       g_clear_object (&priv->cancellable);
00118     }
00119 
00120   if (priv->watcher_id)
00121     {
00122       g_bus_unwatch_name (priv->watcher_id);
00123       priv->watcher_id = 0;
00124     }
00125 
00126   G_OBJECT_CLASS (indicator_power_dbus_listener_parent_class)->dispose (object);
00127 }
00128 
00129 static void
00130 indicator_power_dbus_listener_finalize (GObject *object)
00131 {
00132   G_OBJECT_CLASS (indicator_power_dbus_listener_parent_class)->finalize (object);
00133 }
00134 
00135 /***
00136 ****
00137 ***/
00138 
00139 static void
00140 get_devices_cb (GObject      * source_object,
00141                 GAsyncResult * res,
00142                 gpointer       user_data)
00143 {
00144   GError *error;
00145   GSList * devices = NULL;
00146   GVariant * devices_container;
00147   IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER (user_data);
00148 
00149   /* build an array of IndicatorPowerDevices from the DBus response */
00150   error = NULL;
00151   devices_container = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
00152   if (devices_container == NULL)
00153     {
00154       g_message ("Couldn't get devices: %s\n", error->message);
00155       g_error_free (error);
00156     }
00157   else
00158     {
00159       gsize i;
00160       GVariant * devices_variant = g_variant_get_child_value (devices_container, 0);
00161       const int device_count = devices_variant ? g_variant_n_children (devices_variant) : 0;
00162 
00163       for (i=0; i<device_count; i++)
00164         {
00165           GVariant * v = g_variant_get_child_value (devices_variant, i);
00166           devices = g_slist_prepend (devices, indicator_power_device_new_from_variant (v));
00167           g_variant_unref (v);
00168         }
00169 
00170       devices = g_slist_reverse (devices);
00171 
00172       g_variant_unref (devices_variant);
00173       g_variant_unref (devices_container);
00174     }
00175 
00176   g_signal_emit (self, signals[SIGNAL_DEVICES], (GQuark)0, devices);
00177   g_slist_free_full (devices, g_object_unref);
00178 }
00179 
00180 static void
00181 request_device_list (IndicatorPowerDbusListener * self)
00182 {
00183   g_dbus_proxy_call (self->priv->proxy,
00184                      "GetDevices",
00185                      NULL,
00186                      G_DBUS_CALL_FLAGS_NONE,
00187                      -1,
00188                      self->priv->cancellable,
00189                      get_devices_cb,
00190                      self);
00191 }
00192 
00193 static void
00194 receive_properties_changed (GDBusProxy *proxy                  G_GNUC_UNUSED,
00195                             GVariant   *changed_properties     G_GNUC_UNUSED,
00196                             GStrv       invalidated_properties G_GNUC_UNUSED,
00197                             gpointer    user_data)
00198 {
00199   request_device_list (INDICATOR_POWER_DBUS_LISTENER(user_data));
00200 }
00201 
00202 
00203 static void
00204 service_proxy_cb (GObject      *object,
00205                   GAsyncResult *res,
00206                   gpointer      user_data)
00207 {
00208   GError * error = NULL;
00209   IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(user_data);
00210   IndicatorPowerDbusListenerPrivate * priv = self->priv;
00211 
00212   priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
00213 
00214   if (error != NULL)
00215     {
00216       g_error ("Error creating proxy: %s", error->message);
00217       g_error_free (error);
00218       return;
00219     }
00220 
00221   /* we want to change the primary device changes */
00222   g_signal_connect (priv->proxy, "g-properties-changed",
00223                     G_CALLBACK (receive_properties_changed), user_data);
00224 
00225   /* get the initial state */
00226   request_device_list (self);
00227 }
00228 
00229 static void
00230 gsd_appeared_callback (GDBusConnection *connection,
00231                        const gchar     *name,
00232                        const gchar     *name_owner,
00233                        gpointer         user_data)
00234 {
00235   IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(user_data);
00236   IndicatorPowerDbusListenerPrivate * priv = self->priv;
00237 
00238   g_dbus_proxy_new (connection,
00239                     G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
00240                     NULL,
00241                     name,
00242                     GSD_POWER_DBUS_PATH,
00243                     GSD_POWER_DBUS_INTERFACE,
00244                     priv->cancellable,
00245                     service_proxy_cb,
00246                     self);
00247 }