~ps-jenkins/indicator-power/latestsnapshot-12.10.6+13.10.20131008-0ubuntu1

« back to all changes in this revision

Viewing changes to src/dbus-listener.c

  • Committer: Tarmac
  • Author(s): Charles Kerr
  • Date: 2013-06-19 21:13:09 UTC
  • mfrom: (167.1.32 gmenuify)
  • Revision ID: tarmac-20130619211309-nj444ogmrhsi7r9f
Convert the power indicator into a service that exports GMenus and GActions in accordance with our indicator-ng design.

Approved by PS Jenkins bot, Ted Gould.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 
3
 
Listens on DBus for Power changes and passes them to an IndicatorPower
4
 
 
5
 
Copyright 2012 Canonical Ltd.
6
 
 
7
 
Authors:
8
 
    Charles Kerr <charles.kerr@canonical.com>
9
 
 
10
 
This library is free software; you can redistribute it and/or
11
 
modify it under the terms of the GNU General Public License
12
 
version 3.0 as published by the Free Software Foundation.
13
 
 
14
 
This library is distributed in the hope that it will be useful,
15
 
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 
GNU General Public License version 3.0 for more details.
18
 
 
19
 
You should have received a copy of the GNU General Public
20
 
License along with this library. If not, see
21
 
<http://www.gnu.org/licenses/>.
22
 
*/
23
 
 
24
 
#include "dbus-listener.h"
25
 
#include "device.h"
26
 
 
27
 
struct _IndicatorPowerDbusListenerPrivate
28
 
{
29
 
  GCancellable * cancellable;
30
 
  GDBusProxy * proxy;
31
 
  guint watcher_id;
32
 
};
33
 
 
34
 
#define INDICATOR_POWER_DBUS_LISTENER_GET_PRIVATE(o) (INDICATOR_POWER_DBUS_LISTENER(o)->priv)
35
 
 
36
 
/* Signals */
37
 
enum {
38
 
  SIGNAL_DEVICES,
39
 
  SIGNAL_LAST
40
 
};
41
 
static guint signals[SIGNAL_LAST] = { 0 };
42
 
 
43
 
 
44
 
/* GObject stuff */
45
 
static void indicator_power_dbus_listener_class_init (IndicatorPowerDbusListenerClass *klass);
46
 
static void indicator_power_dbus_listener_init       (IndicatorPowerDbusListener *self);
47
 
static void indicator_power_dbus_listener_dispose    (GObject *object);
48
 
static void indicator_power_dbus_listener_finalize   (GObject *object);
49
 
 
50
 
static void gsd_appeared_callback (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data);
51
 
 
52
 
/* LCOV_EXCL_START */
53
 
G_DEFINE_TYPE (IndicatorPowerDbusListener, indicator_power_dbus_listener, G_TYPE_OBJECT);
54
 
/* LCOV_EXCL_STOP */
55
 
 
56
 
static void
57
 
indicator_power_dbus_listener_class_init (IndicatorPowerDbusListenerClass *klass)
58
 
{
59
 
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
60
 
 
61
 
  g_type_class_add_private (klass, sizeof (IndicatorPowerDbusListenerPrivate));
62
 
 
63
 
  /* methods */
64
 
  object_class->dispose = indicator_power_dbus_listener_dispose;
65
 
  object_class->finalize = indicator_power_dbus_listener_finalize;
66
 
 
67
 
  /**
68
 
   * IndicatorPowerDbusListener::devices-enumerated:
69
 
   *
70
 
   * @listener: the IndicatorPowerDbusListener
71
 
   * @devices: a GSList of #IndicatorPowerDevice objects. (transfer none)
72
 
   *
73
 
   * This is emitted each time a new set of devices is enumerated over the bus.
74
 
   */
75
 
  signals[SIGNAL_DEVICES] = g_signal_new (INDICATOR_POWER_DBUS_LISTENER_DEVICES_ENUMERATED,
76
 
                                          G_TYPE_FROM_CLASS(klass), 0,
77
 
                                          G_STRUCT_OFFSET (IndicatorPowerDbusListenerClass, devices_enumerated),
78
 
                                          NULL, NULL,
79
 
                                          g_cclosure_marshal_VOID__POINTER,
80
 
                                          G_TYPE_NONE, 1, G_TYPE_POINTER);
81
 
}
82
 
 
83
 
/* Initialize an instance */
84
 
static void
85
 
indicator_power_dbus_listener_init (IndicatorPowerDbusListener *self)
86
 
{
87
 
  IndicatorPowerDbusListenerPrivate * priv;
88
 
 
89
 
  priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
90
 
                                      INDICATOR_POWER_DBUS_LISTENER_TYPE,
91
 
                                      IndicatorPowerDbusListenerPrivate);
92
 
 
93
 
  priv->cancellable = g_cancellable_new ();
94
 
 
95
 
  priv->watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
96
 
                                       GSD_SERVICE,
97
 
                                       G_BUS_NAME_WATCHER_FLAGS_NONE,
98
 
                                       gsd_appeared_callback,
99
 
                                       NULL,
100
 
                                       self,
101
 
                                       NULL);
102
 
 
103
 
  self->priv = priv;
104
 
}
105
 
 
106
 
static void
107
 
indicator_power_dbus_listener_dispose (GObject *object)
108
 
{
109
 
  IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(object);
110
 
  IndicatorPowerDbusListenerPrivate * priv = self->priv;
111
 
 
112
 
  g_clear_object (&priv->proxy);
113
 
 
114
 
  if (priv->cancellable != NULL)
115
 
    {
116
 
      g_cancellable_cancel (priv->cancellable);
117
 
      g_clear_object (&priv->cancellable);
118
 
    }
119
 
 
120
 
  if (priv->watcher_id)
121
 
    {
122
 
      g_bus_unwatch_name (priv->watcher_id);
123
 
      priv->watcher_id = 0;
124
 
    }
125
 
 
126
 
  G_OBJECT_CLASS (indicator_power_dbus_listener_parent_class)->dispose (object);
127
 
}
128
 
 
129
 
static void
130
 
indicator_power_dbus_listener_finalize (GObject *object)
131
 
{
132
 
  G_OBJECT_CLASS (indicator_power_dbus_listener_parent_class)->finalize (object);
133
 
}
134
 
 
135
 
/***
136
 
****
137
 
***/
138
 
 
139
 
static void
140
 
get_devices_cb (GObject      * source_object,
141
 
                GAsyncResult * res,
142
 
                gpointer       user_data)
143
 
{
144
 
  GError *error;
145
 
  GSList * devices = NULL;
146
 
  GVariant * devices_container;
147
 
  IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER (user_data);
148
 
 
149
 
  /* build an array of IndicatorPowerDevices from the DBus response */
150
 
  error = NULL;
151
 
  devices_container = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
152
 
  if (devices_container == NULL)
153
 
    {
154
 
      g_message ("Couldn't get devices: %s\n", error->message);
155
 
      g_error_free (error);
156
 
    }
157
 
  else
158
 
    {
159
 
      gsize i;
160
 
      GVariant * devices_variant = g_variant_get_child_value (devices_container, 0);
161
 
      const int device_count = devices_variant ? g_variant_n_children (devices_variant) : 0;
162
 
 
163
 
      for (i=0; i<device_count; i++)
164
 
        {
165
 
          GVariant * v = g_variant_get_child_value (devices_variant, i);
166
 
          devices = g_slist_prepend (devices, indicator_power_device_new_from_variant (v));
167
 
          g_variant_unref (v);
168
 
        }
169
 
 
170
 
      devices = g_slist_reverse (devices);
171
 
 
172
 
      g_variant_unref (devices_variant);
173
 
      g_variant_unref (devices_container);
174
 
    }
175
 
 
176
 
  g_signal_emit (self, signals[SIGNAL_DEVICES], (GQuark)0, devices);
177
 
  g_slist_free_full (devices, g_object_unref);
178
 
}
179
 
 
180
 
static void
181
 
request_device_list (IndicatorPowerDbusListener * self)
182
 
{
183
 
  g_dbus_proxy_call (self->priv->proxy,
184
 
                     "GetDevices",
185
 
                     NULL,
186
 
                     G_DBUS_CALL_FLAGS_NONE,
187
 
                     -1,
188
 
                     self->priv->cancellable,
189
 
                     get_devices_cb,
190
 
                     self);
191
 
}
192
 
 
193
 
static void
194
 
receive_properties_changed (GDBusProxy *proxy                  G_GNUC_UNUSED,
195
 
                            GVariant   *changed_properties     G_GNUC_UNUSED,
196
 
                            GStrv       invalidated_properties G_GNUC_UNUSED,
197
 
                            gpointer    user_data)
198
 
{
199
 
  request_device_list (INDICATOR_POWER_DBUS_LISTENER(user_data));
200
 
}
201
 
 
202
 
 
203
 
static void
204
 
service_proxy_cb (GObject      *object,
205
 
                  GAsyncResult *res,
206
 
                  gpointer      user_data)
207
 
{
208
 
  GError * error = NULL;
209
 
  IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(user_data);
210
 
  IndicatorPowerDbusListenerPrivate * priv = self->priv;
211
 
 
212
 
  priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
213
 
 
214
 
  if (error != NULL)
215
 
    {
216
 
      g_error ("Error creating proxy: %s", error->message);
217
 
      g_error_free (error);
218
 
      return;
219
 
    }
220
 
 
221
 
  /* we want to change the primary device changes */
222
 
  g_signal_connect (priv->proxy, "g-properties-changed",
223
 
                    G_CALLBACK (receive_properties_changed), user_data);
224
 
 
225
 
  /* get the initial state */
226
 
  request_device_list (self);
227
 
}
228
 
 
229
 
static void
230
 
gsd_appeared_callback (GDBusConnection *connection,
231
 
                       const gchar     *name,
232
 
                       const gchar     *name_owner,
233
 
                       gpointer         user_data)
234
 
{
235
 
  IndicatorPowerDbusListener * self = INDICATOR_POWER_DBUS_LISTENER(user_data);
236
 
  IndicatorPowerDbusListenerPrivate * priv = self->priv;
237
 
 
238
 
  g_dbus_proxy_new (connection,
239
 
                    G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
240
 
                    NULL,
241
 
                    name,
242
 
                    GSD_POWER_DBUS_PATH,
243
 
                    GSD_POWER_DBUS_INTERFACE,
244
 
                    priv->cancellable,
245
 
                    service_proxy_cb,
246
 
                    self);
247
 
}