~xavi-garcia-mena/ubuntu/vivid/upower/percentages-power-off

« back to all changes in this revision

Viewing changes to .pc/0001-up-client-Really-don-t-overwrite-retval-with-prop-va.patch/libupower-glib/up-client.c

  • Committer: Package Import Robot
  • Author(s): Iain Lane
  • Date: 2013-10-14 11:41:36 UTC
  • Revision ID: package-import@ubuntu.com-20131014114136-fyh80f8bw06jq7wf
Tags: 0.9.22-1ubuntu1
* Cherry-pick two fixes from upstream:
  - up-client: Really don't overwrite retval with prop values. Properties
    and property notification via libupower-glib got broken in 0.9.22.
    Incorrect values were being returned, meaning anything relying on these
    might do the wrong thing, such as in LP: #1238663
  - lib: Fix crasher calling _about_to_sleep_sync(). Crash fix.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 2008-2010 Richard Hughes <richard@hughsie.com>
 
4
 *
 
5
 * Licensed under the GNU General Public License Version 2
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
20
 */
 
21
 
 
22
/**
 
23
 * SECTION:up-client
 
24
 * @short_description: Main client object for accessing the UPower daemon
 
25
 *
 
26
 * A helper GObject to use for accessing UPower information, and to be notified
 
27
 * when it is changed.
 
28
 *
 
29
 * See also: #UpDevice
 
30
 */
 
31
 
 
32
#include "config.h"
 
33
 
 
34
#include <stdlib.h>
 
35
#include <stdio.h>
 
36
#include <glib.h>
 
37
#include <dbus/dbus-glib.h>
 
38
 
 
39
#include "up-client.h"
 
40
#include "up-device.h"
 
41
 
 
42
static void     up_client_class_init    (UpClientClass  *klass);
 
43
static void     up_client_init          (UpClient       *client);
 
44
static void     up_client_finalize      (GObject        *object);
 
45
 
 
46
#define UP_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), UP_TYPE_CLIENT, UpClientPrivate))
 
47
 
 
48
/**
 
49
 * UpClientPrivate:
 
50
 *
 
51
 * Private #UpClient data
 
52
 **/
 
53
struct _UpClientPrivate
 
54
{
 
55
        DBusGConnection         *bus;
 
56
        DBusGProxy              *proxy;
 
57
        DBusGProxy              *prop_proxy;
 
58
        GPtrArray               *array;
 
59
        gboolean                 have_properties;
 
60
        gchar                   *daemon_version;
 
61
        gboolean                 can_suspend;
 
62
        gboolean                 can_hibernate;
 
63
        gboolean                 lid_is_closed;
 
64
        gboolean                 on_battery;
 
65
        gboolean                 on_low_battery;
 
66
        gboolean                 lid_is_present;
 
67
        gboolean                 lid_force_sleep;
 
68
        gboolean                 is_docked;
 
69
        gboolean                 done_enumerate;
 
70
};
 
71
 
 
72
enum {
 
73
        UP_CLIENT_DEVICE_ADDED,
 
74
        UP_CLIENT_DEVICE_CHANGED,
 
75
        UP_CLIENT_DEVICE_REMOVED,
 
76
        UP_CLIENT_CHANGED,
 
77
        UP_CLIENT_NOTIFY_SLEEP,
 
78
        UP_CLIENT_NOTIFY_RESUME,
 
79
        UP_CLIENT_LAST_SIGNAL
 
80
};
 
81
 
 
82
enum {
 
83
        PROP_0,
 
84
        PROP_DAEMON_VERSION,
 
85
        PROP_CAN_SUSPEND,
 
86
        PROP_CAN_HIBERNATE,
 
87
        PROP_ON_BATTERY,
 
88
        PROP_ON_LOW_BATTERY,
 
89
        PROP_LID_IS_CLOSED,
 
90
        PROP_LID_IS_PRESENT,
 
91
        PROP_LID_FORCE_SLEEP,
 
92
        PROP_IS_DOCKED,
 
93
        PROP_LAST
 
94
};
 
95
 
 
96
static guint signals [UP_CLIENT_LAST_SIGNAL] = { 0 };
 
97
static gpointer up_client_object = NULL;
 
98
 
 
99
G_DEFINE_TYPE (UpClient, up_client, G_TYPE_OBJECT)
 
100
 
 
101
/*
 
102
 * up_client_get_device:
 
103
 */
 
104
static UpDevice *
 
105
up_client_get_device (UpClient *client, const gchar *object_path)
 
106
{
 
107
        guint i;
 
108
        const gchar *object_path_tmp;
 
109
        UpDevice *device;
 
110
        UpClientPrivate *priv = client->priv;
 
111
 
 
112
        for (i=0; i<priv->array->len; i++) {
 
113
                device = g_ptr_array_index (priv->array, i);
 
114
                object_path_tmp = up_device_get_object_path (device);
 
115
                if (g_strcmp0 (object_path_tmp, object_path) == 0)
 
116
                        return device;
 
117
        }
 
118
        return NULL;
 
119
}
 
120
 
 
121
/**
 
122
 * up_client_get_devices:
 
123
 * @client: a #UpClient instance.
 
124
 *
 
125
 * Get a copy of the device objects.
 
126
 * You must have called up_client_enumerate_devices_sync() before calling this
 
127
 * function.
 
128
 *
 
129
 * Return value: (transfer full): an array of #UpDevice objects, free with g_ptr_array_unref()
 
130
 *
 
131
 * Since: 0.9.0
 
132
 **/
 
133
GPtrArray *
 
134
up_client_get_devices (UpClient *client)
 
135
{
 
136
        g_return_val_if_fail (UP_IS_CLIENT (client), NULL);
 
137
        g_return_val_if_fail (client->priv->done_enumerate, NULL);
 
138
        return g_ptr_array_ref (client->priv->array);
 
139
}
 
140
 
 
141
/*
 
142
 * up_client_get_devices_private:
 
143
 */
 
144
static GPtrArray *
 
145
up_client_get_devices_private (UpClient *client, GError **error)
 
146
{
 
147
        gboolean ret;
 
148
        GError *error_local = NULL;
 
149
        GPtrArray *devices = NULL;
 
150
        GType g_type_array;
 
151
 
 
152
        if (!client->priv->proxy)
 
153
                return NULL;
 
154
        g_type_array = dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH);
 
155
        ret = dbus_g_proxy_call (client->priv->proxy, "EnumerateDevices", &error_local,
 
156
                                 G_TYPE_INVALID,
 
157
                                 g_type_array, &devices,
 
158
                                 G_TYPE_INVALID);
 
159
        if (!ret) {
 
160
                g_warning ("Couldn't enumerate devices: %s", error_local->message);
 
161
                g_set_error (error, 1, 0, "%s", error_local->message);
 
162
                g_error_free (error_local);
 
163
        }
 
164
        return devices;
 
165
}
 
166
 
 
167
/**
 
168
 * up_client_suspend_sync:
 
169
 * @client: a #UpClient instance.
 
170
 * @cancellable: a #GCancellable or %NULL
 
171
 * @error: a #GError, or %NULL.
 
172
 *
 
173
 * Puts the computer into a low power state, but state is not preserved if the
 
174
 * power is lost.
 
175
 *
 
176
 * NOTE: The system is still consuming a small amount of power
 
177
 *
 
178
 * Return value: TRUE if system suspended okay, FALSE other wise.
 
179
 *
 
180
 * Since: 0.9.0
 
181
 **/
 
182
gboolean
 
183
up_client_suspend_sync (UpClient *client, GCancellable *cancellable, GError **error)
 
184
{
 
185
        gboolean ret;
 
186
        GError *error_local = NULL;
 
187
 
 
188
        g_return_val_if_fail (UP_IS_CLIENT (client), FALSE);
 
189
        g_return_val_if_fail (client->priv->proxy != NULL, FALSE);
 
190
 
 
191
        ret = dbus_g_proxy_call (client->priv->proxy, "Suspend", &error_local,
 
192
                                 G_TYPE_INVALID, G_TYPE_INVALID);
 
193
        if (!ret) {
 
194
                /* DBus might time out, which is okay */
 
195
                if (g_error_matches (error_local, DBUS_GERROR, DBUS_GERROR_NO_REPLY)) {
 
196
                        g_debug ("DBUS timed out, but recovering");
 
197
                        ret = TRUE;
 
198
                        goto out;
 
199
                }
 
200
 
 
201
                /* an actual error */
 
202
                g_warning ("Couldn't suspend: %s", error_local->message);
 
203
                g_set_error (error, 1, 0, "%s", error_local->message);
 
204
        }
 
205
out:
 
206
        if (error_local != NULL)
 
207
                g_error_free (error_local);
 
208
        return ret;
 
209
}
 
210
 
 
211
/**
 
212
 * up_client_hibernate_sync:
 
213
 * @client: a #UpClient instance.
 
214
 * @cancellable: a #GCancellable or %NULL
 
215
 * @error: a #GError.
 
216
 *
 
217
 * Puts the computer into a low power state, where state is preserved if the
 
218
 * power is lost.
 
219
 *
 
220
 * Return value: TRUE if system suspended okay, FALSE other wise.
 
221
 *
 
222
 * Since: 0.9.0
 
223
 **/
 
224
gboolean
 
225
up_client_hibernate_sync (UpClient *client, GCancellable *cancellable, GError **error)
 
226
{
 
227
        gboolean ret;
 
228
        GError *error_local = NULL;
 
229
 
 
230
        g_return_val_if_fail (UP_IS_CLIENT (client), FALSE);
 
231
        g_return_val_if_fail (client->priv->proxy != NULL, FALSE);
 
232
 
 
233
        ret = dbus_g_proxy_call (client->priv->proxy, "Hibernate", &error_local,
 
234
                                 G_TYPE_INVALID, G_TYPE_INVALID);
 
235
        if (!ret) {
 
236
                /* DBus might time out, which is okay */
 
237
                if (g_error_matches (error_local, DBUS_GERROR, DBUS_GERROR_NO_REPLY)) {
 
238
                        g_debug ("DBUS timed out, but recovering");
 
239
                        ret = TRUE;
 
240
                        goto out;
 
241
                }
 
242
 
 
243
                /* an actual error */
 
244
                g_warning ("Couldn't hibernate: %s", error_local->message);
 
245
                g_set_error (error, 1, 0, "%s", error_local->message);
 
246
        }
 
247
out:
 
248
        if (error_local != NULL)
 
249
                g_error_free (error_local);
 
250
        return ret;
 
251
}
 
252
 
 
253
/**
 
254
 * up_client_about_to_sleep_sync:
 
255
 * @client: a #UpClient instance.
 
256
 * @sleep_kind: a sleep type, e.g. %UP_SLEEP_KIND_SUSPEND
 
257
 * @cancellable: a #GCancellable or %NULL
 
258
 * @error: a #GError, or %NULL.
 
259
 *
 
260
 * Tells UPower that we are soon to reqest either Suspend() or Hibernate()
 
261
 * and that session and system components should be notified of this.
 
262
 *
 
263
 * Return value: TRUE if system suspended okay, FALSE other wise.
 
264
 *
 
265
 * Since: 0.9.11
 
266
 **/
 
267
gboolean
 
268
up_client_about_to_sleep_sync (UpClient *client,
 
269
                               UpSleepKind sleep_kind,
 
270
                               GCancellable *cancellable,
 
271
                               GError **error)
 
272
{
 
273
        gboolean ret;
 
274
        GError *error_local = NULL;
 
275
 
 
276
        g_return_val_if_fail (UP_IS_CLIENT (client), FALSE);
 
277
        g_return_val_if_fail (client->priv->proxy != NULL, FALSE);
 
278
 
 
279
        ret = dbus_g_proxy_call (client->priv->proxy, "AboutToSleep", &error_local,
 
280
                                 G_TYPE_STRING, sleep_kind,
 
281
                                 G_TYPE_INVALID,
 
282
                                 G_TYPE_INVALID);
 
283
        if (!ret) {
 
284
                /* DBus might time out, which is okay */
 
285
                if (g_error_matches (error_local, DBUS_GERROR, DBUS_GERROR_NO_REPLY)) {
 
286
                        g_debug ("DBUS timed out, but recovering");
 
287
                        ret = TRUE;
 
288
                        goto out;
 
289
                }
 
290
 
 
291
                /* an actual error */
 
292
                g_warning ("Couldn't sent that we were about to sleep: %s", error_local->message);
 
293
                g_set_error (error, 1, 0, "%s", error_local->message);
 
294
        }
 
295
out:
 
296
        if (error_local != NULL)
 
297
                g_error_free (error_local);
 
298
        return ret;
 
299
}
 
300
 
 
301
/**
 
302
 * up_client_get_properties_sync:
 
303
 * @client: a #UpClient instance.
 
304
 * @cancellable: a #GCancellable or %NULL
 
305
 * @error: a #GError, or %NULL.
 
306
 *
 
307
 * Get all the properties from UPower daemon.
 
308
 *
 
309
 * Return value: %TRUE for success, else %FALSE.
 
310
 *
 
311
 * Since: 0.9.0
 
312
 **/
 
313
gboolean
 
314
up_client_get_properties_sync (UpClient *client, GCancellable *cancellable, GError **error)
 
315
{
 
316
        gboolean ret = TRUE;
 
317
        gboolean prop_val;
 
318
        GHashTable *props;
 
319
        GValue *value;
 
320
#ifdef ENABLE_DEPRECATED
 
321
        gboolean allowed = FALSE;
 
322
#endif
 
323
 
 
324
        props = NULL;
 
325
 
 
326
        if (client->priv->have_properties)
 
327
                goto out;
 
328
        if (!client->priv->prop_proxy)
 
329
                goto out;
 
330
 
 
331
        if (error != NULL)
 
332
                *error = NULL;
 
333
        ret = dbus_g_proxy_call (client->priv->prop_proxy, "GetAll", error,
 
334
                                 G_TYPE_STRING, "org.freedesktop.UPower",
 
335
                                 G_TYPE_INVALID,
 
336
                                 dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &props,
 
337
                                 G_TYPE_INVALID);
 
338
        if (!ret)
 
339
                goto out;
 
340
 
 
341
        value = g_hash_table_lookup (props, "DaemonVersion");
 
342
        if (value == NULL) {
 
343
                g_warning ("No 'DaemonVersion' property");
 
344
                goto out;
 
345
        }
 
346
        g_free (client->priv->daemon_version);
 
347
        client->priv->daemon_version = g_strdup (g_value_get_string (value));
 
348
 
 
349
#ifdef ENABLE_DEPRECATED
 
350
        value = g_hash_table_lookup (props, "CanSuspend");
 
351
        if (value == NULL) {
 
352
                g_warning ("No 'CanSuspend' property");
 
353
                goto out;
 
354
        }
 
355
        
 
356
        ret = dbus_g_proxy_call (client->priv->proxy, "SuspendAllowed", error,
 
357
                G_TYPE_INVALID, G_TYPE_BOOLEAN, &allowed, G_TYPE_INVALID);
 
358
        if (!ret)
 
359
                goto out;
 
360
 
 
361
        prop_val = g_value_get_boolean (value) && allowed;
 
362
        if (prop_val != client->priv->can_suspend) {
 
363
                client->priv->can_suspend = ret;
 
364
                g_object_notify (G_OBJECT(client), "can-suspend");
 
365
        }
 
366
 
 
367
        value = g_hash_table_lookup (props, "CanHibernate");
 
368
        if (value == NULL) {
 
369
                g_warning ("No 'CanHibernate' property");
 
370
                goto out;
 
371
        }
 
372
        ret = dbus_g_proxy_call (client->priv->proxy, "HibernateAllowed", error,
 
373
                G_TYPE_INVALID, G_TYPE_BOOLEAN, &allowed, G_TYPE_INVALID);
 
374
        if (!ret)
 
375
                goto out;
 
376
 
 
377
        prop_val = g_value_get_boolean (value) && allowed;
 
378
        if (prop_val != client->priv->can_hibernate) {
 
379
                client->priv->can_hibernate = ret;
 
380
                g_object_notify (G_OBJECT(client), "can-hibernate");
 
381
        }
 
382
#endif /* ENABLE_DEPRECATED */
 
383
 
 
384
        value = g_hash_table_lookup (props, "LidIsClosed");
 
385
        if (value == NULL) {
 
386
                g_warning ("No 'LidIsClosed' property");
 
387
                goto out;
 
388
        }
 
389
        prop_val = g_value_get_boolean (value);
 
390
        if (prop_val != client->priv->lid_is_closed) {
 
391
                client->priv->lid_is_closed = ret;
 
392
                g_object_notify (G_OBJECT(client), "lid-is-closed");
 
393
        }
 
394
 
 
395
        value = g_hash_table_lookup (props, "OnBattery");
 
396
        if (value == NULL) {
 
397
                g_warning ("No 'OnBattery' property");
 
398
                goto out;
 
399
        }
 
400
        prop_val = g_value_get_boolean (value);
 
401
        if (prop_val != client->priv->on_battery) {
 
402
                client->priv->on_battery = ret;
 
403
                g_object_notify (G_OBJECT(client), "on-battery");
 
404
        }
 
405
 
 
406
        value = g_hash_table_lookup (props, "OnLowBattery");
 
407
        if (value == NULL) {
 
408
                g_warning ("No 'OnLowBattery' property");
 
409
                goto out;
 
410
        }
 
411
        prop_val = g_value_get_boolean (value);
 
412
        if (prop_val != client->priv->on_low_battery) {
 
413
                client->priv->on_low_battery = ret;
 
414
                g_object_notify (G_OBJECT(client), "on-low-battery");
 
415
        }
 
416
 
 
417
        value = g_hash_table_lookup (props, "LidIsPresent");
 
418
        if (value == NULL) {
 
419
                g_warning ("No 'LidIsPresent' property");
 
420
                goto out;
 
421
        }
 
422
        prop_val = g_value_get_boolean (value);
 
423
        if (prop_val != client->priv->lid_is_present) {
 
424
                client->priv->lid_is_present = ret;
 
425
                g_object_notify (G_OBJECT(client), "lid-is-present");
 
426
        }
 
427
 
 
428
        value = g_hash_table_lookup (props, "IsDocked");
 
429
        if (value == NULL) {
 
430
                g_warning ("No 'IsDocked' property");
 
431
                goto out;
 
432
        }
 
433
        prop_val = g_value_get_boolean (value);
 
434
        if (ret != client->priv->is_docked) {
 
435
                client->priv->is_docked = ret;
 
436
                g_object_notify (G_OBJECT(client), "is-docked");
 
437
        }
 
438
 
 
439
        value = g_hash_table_lookup (props, "LidForceSleep");
 
440
        if (value == NULL) {
 
441
                g_warning ("No 'LidForceSleep' property");
 
442
                goto out;
 
443
        }
 
444
        prop_val = g_value_get_boolean (value);
 
445
        if (prop_val != client->priv->lid_force_sleep) {
 
446
                client->priv->lid_force_sleep = ret;
 
447
                g_object_notify (G_OBJECT(client), "lid-force-sleep");
 
448
        }
 
449
 
 
450
        /* cached */
 
451
        client->priv->have_properties = TRUE;
 
452
 
 
453
out:
 
454
        if (props != NULL)
 
455
                g_hash_table_unref (props);
 
456
        return ret;
 
457
}
 
458
 
 
459
/**
 
460
 * up_client_get_daemon_version:
 
461
 * @client: a #UpClient instance.
 
462
 *
 
463
 * Get UPower daemon version.
 
464
 *
 
465
 * Return value: string containing the daemon version, e.g. 008
 
466
 *
 
467
 * Since: 0.9.0
 
468
 **/
 
469
const gchar *
 
470
up_client_get_daemon_version (UpClient *client)
 
471
{
 
472
        g_return_val_if_fail (UP_IS_CLIENT (client), NULL);
 
473
        up_client_get_properties_sync (client, NULL, NULL);
 
474
        return client->priv->daemon_version;
 
475
}
 
476
 
 
477
/**
 
478
 * up_client_get_can_hibernate:
 
479
 * @client: a #UpClient instance.
 
480
 *
 
481
 * Get whether the system is able to hibernate.
 
482
 *
 
483
 * Return value: TRUE if system can hibernate, FALSE other wise.
 
484
 *
 
485
 * Since: 0.9.0
 
486
 **/
 
487
gboolean
 
488
up_client_get_can_hibernate (UpClient *client)
 
489
{
 
490
        g_return_val_if_fail (UP_IS_CLIENT (client), FALSE);
 
491
        up_client_get_properties_sync (client, NULL, NULL);
 
492
        return client->priv->can_hibernate;
 
493
}
 
494
 
 
495
/**
 
496
 * up_client_get_lid_is_closed:
 
497
 * @client: a #UpClient instance.
 
498
 *
 
499
 * Get whether the laptop lid is closed.
 
500
 *
 
501
 * Return value: %TRUE if lid is closed or %FALSE otherwise.
 
502
 *
 
503
 * Since: 0.9.0
 
504
 */
 
505
gboolean
 
506
up_client_get_lid_is_closed (UpClient *client)
 
507
{
 
508
        g_return_val_if_fail (UP_IS_CLIENT (client), FALSE);
 
509
        up_client_get_properties_sync (client, NULL, NULL);
 
510
        return client->priv->lid_is_closed;
 
511
}
 
512
 
 
513
/**
 
514
 * up_client_get_lid_is_present:
 
515
 * @client: a #UpClient instance.
 
516
 *
 
517
 * Get whether a laptop lid is present on this machine.
 
518
 *
 
519
 * Return value: %TRUE if the machine has a laptop lid
 
520
 *
 
521
 * Since: 0.9.2
 
522
 */
 
523
gboolean
 
524
up_client_get_lid_is_present (UpClient *client)
 
525
{
 
526
        g_return_val_if_fail (UP_IS_CLIENT (client), FALSE);
 
527
        up_client_get_properties_sync (client, NULL, NULL);
 
528
        return client->priv->lid_is_present;
 
529
}
 
530
 
 
531
/**
 
532
 * up_client_get_lid_force_sleep:
 
533
 * @client: a #UpClient instance.
 
534
 *
 
535
 * Get whether the laptop has to sleep when the lid is closed.
 
536
 *
 
537
 * Return value: %TRUE if the session has to suspend
 
538
 *
 
539
 * Since: 0.9.9
 
540
 */
 
541
gboolean
 
542
up_client_get_lid_force_sleep (UpClient *client)
 
543
{
 
544
        g_return_val_if_fail (UP_IS_CLIENT (client), FALSE);
 
545
        up_client_get_properties_sync (client, NULL, NULL);
 
546
        return client->priv->lid_force_sleep;
 
547
}
 
548
 
 
549
/**
 
550
 * up_client_get_is_docked:
 
551
 * @client: a #UpClient instance.
 
552
 *
 
553
 * Get whether the machine is docked into a docking station.
 
554
 *
 
555
 * Return value: %TRUE if the machine is docked
 
556
 *
 
557
 * Since: 0.9.2
 
558
 */
 
559
gboolean
 
560
up_client_get_is_docked (UpClient *client)
 
561
{
 
562
        g_return_val_if_fail (UP_IS_CLIENT (client), FALSE);
 
563
        up_client_get_properties_sync (client, NULL, NULL);
 
564
        return client->priv->is_docked;
 
565
}
 
566
 
 
567
/**
 
568
 * up_client_get_can_suspend:
 
569
 * @client: a #UpClient instance.
 
570
 *
 
571
 * Get whether the system is able to suspend.
 
572
 *
 
573
 * Return value: TRUE if system can suspend, FALSE other wise.
 
574
 *
 
575
 * Since: 0.9.0
 
576
 **/
 
577
gboolean
 
578
up_client_get_can_suspend (UpClient *client)
 
579
{
 
580
        g_return_val_if_fail (UP_IS_CLIENT (client), FALSE);
 
581
        up_client_get_properties_sync (client, NULL, NULL);
 
582
        return client->priv->can_suspend;
 
583
}
 
584
 
 
585
/**
 
586
 * up_client_get_on_battery:
 
587
 * @client: a #UpClient instance.
 
588
 *
 
589
 * Get whether the system is running on battery power.
 
590
 *
 
591
 * Return value: TRUE if the system is currently running on battery, FALSE other wise.
 
592
 *
 
593
 * Since: 0.9.0
 
594
 **/
 
595
gboolean
 
596
up_client_get_on_battery (UpClient *client)
 
597
{
 
598
        g_return_val_if_fail (UP_IS_CLIENT (client), FALSE);
 
599
        up_client_get_properties_sync (client, NULL, NULL);
 
600
        return client->priv->on_battery;
 
601
}
 
602
 
 
603
/**
 
604
 * up_client_get_on_low_battery:
 
605
 * @client: a #UpClient instance.
 
606
 *
 
607
 * Get whether the system is running on low battery power.
 
608
 *
 
609
 * Return value: TRUE if the system is currently on low battery power, FALSE other wise.
 
610
 *
 
611
 * Since: 0.9.0
 
612
 **/
 
613
gboolean
 
614
up_client_get_on_low_battery (UpClient *client)
 
615
{
 
616
        g_return_val_if_fail (UP_IS_CLIENT (client), FALSE);
 
617
        up_client_get_properties_sync (client, NULL, NULL);
 
618
        return client->priv->on_low_battery;
 
619
}
 
620
 
 
621
/*
 
622
 * up_client_add:
 
623
 */
 
624
static void
 
625
up_client_add (UpClient *client, const gchar *object_path)
 
626
{
 
627
        UpDevice *device = NULL;
 
628
        UpDevice *device_tmp;
 
629
        gboolean ret;
 
630
 
 
631
        /* check existing list for this object path */
 
632
        device_tmp = up_client_get_device (client, object_path);
 
633
        if (device_tmp != NULL) {
 
634
                g_warning ("already added: %s", object_path);
 
635
                goto out;
 
636
        }
 
637
 
 
638
        /* create new device */
 
639
        device = up_device_new ();
 
640
        ret = up_device_set_object_path_sync (device, object_path, NULL, NULL);
 
641
        if (!ret)
 
642
                goto out;
 
643
 
 
644
        /* add to array */
 
645
        g_ptr_array_add (client->priv->array, g_object_ref (device));
 
646
        g_signal_emit (client, signals [UP_CLIENT_DEVICE_ADDED], 0, device);
 
647
out:
 
648
        if (device != NULL)
 
649
                g_object_unref (device);
 
650
}
 
651
 
 
652
/*
 
653
 * up_client_added_cb:
 
654
 */
 
655
static void
 
656
up_device_added_cb (DBusGProxy *proxy, const gchar *object_path, UpClient *client)
 
657
{
 
658
        up_client_add (client, object_path);
 
659
}
 
660
 
 
661
/*
 
662
 * up_client_changed_cb:
 
663
 */
 
664
static void
 
665
up_device_changed_cb (DBusGProxy *proxy, const gchar *object_path, UpClient *client)
 
666
{
 
667
        UpDevice *device;
 
668
        device = up_client_get_device (client, object_path);
 
669
        if (device != NULL)
 
670
                g_signal_emit (client, signals [UP_CLIENT_DEVICE_CHANGED], 0, device);
 
671
}
 
672
 
 
673
/*
 
674
 * up_client_notify_sleep_cb:
 
675
 */
 
676
static void
 
677
up_client_notify_sleep_cb (DBusGProxy *proxy, const gchar *sleep_kind, UpClient *client)
 
678
{
 
679
        g_signal_emit (client, signals [UP_CLIENT_NOTIFY_SLEEP], 0,
 
680
                       up_sleep_kind_from_string (sleep_kind));
 
681
}
 
682
 
 
683
/*
 
684
 * up_client_notify_resume_cb:
 
685
 */
 
686
static void
 
687
up_client_notify_resume_cb (DBusGProxy *proxy, const gchar *sleep_kind, UpClient *client)
 
688
{
 
689
        g_signal_emit (client, signals [UP_CLIENT_NOTIFY_RESUME], 0,
 
690
                       up_sleep_kind_from_string (sleep_kind));
 
691
}
 
692
 
 
693
/*
 
694
 * up_client_removed_cb:
 
695
 */
 
696
static void
 
697
up_device_removed_cb (DBusGProxy *proxy, const gchar *object_path, UpClient *client)
 
698
{
 
699
        UpDevice *device;
 
700
        device = up_client_get_device (client, object_path);
 
701
        if (device != NULL) {
 
702
                g_signal_emit (client, signals [UP_CLIENT_DEVICE_REMOVED], 0, device);
 
703
                g_ptr_array_remove (client->priv->array, device);
 
704
        }
 
705
}
 
706
 
 
707
/*
 
708
 * up_client_changed_cb:
 
709
 */
 
710
static void
 
711
up_client_changed_cb (DBusGProxy *proxy, UpClient *client)
 
712
{
 
713
        client->priv->have_properties = FALSE;
 
714
        g_signal_emit (client, signals [UP_CLIENT_CHANGED], 0);
 
715
}
 
716
 
 
717
static void
 
718
up_client_get_property (GObject *object,
 
719
                         guint prop_id,
 
720
                         GValue *value,
 
721
                         GParamSpec *pspec)
 
722
{
 
723
        UpClient *client;
 
724
        client = UP_CLIENT (object);
 
725
 
 
726
        up_client_get_properties_sync (client, NULL, NULL);
 
727
 
 
728
        switch (prop_id) {
 
729
        case PROP_DAEMON_VERSION:
 
730
                g_value_set_string (value, client->priv->daemon_version);
 
731
                break;
 
732
        case PROP_CAN_SUSPEND:
 
733
                g_value_set_boolean (value, client->priv->can_suspend);
 
734
                break;
 
735
        case PROP_CAN_HIBERNATE:
 
736
                g_value_set_boolean (value, client->priv->can_hibernate);
 
737
                break;
 
738
        case PROP_ON_BATTERY:
 
739
                g_value_set_boolean (value, client->priv->on_battery);
 
740
                break;
 
741
        case PROP_ON_LOW_BATTERY:
 
742
                g_value_set_boolean (value, client->priv->on_low_battery);
 
743
                break;
 
744
        case PROP_LID_IS_CLOSED:
 
745
                g_value_set_boolean (value, client->priv->lid_is_closed);
 
746
                break;
 
747
        case PROP_LID_IS_PRESENT:
 
748
                g_value_set_boolean (value, client->priv->lid_is_present);
 
749
                break;
 
750
        case PROP_LID_FORCE_SLEEP:
 
751
                g_value_set_boolean (value, client->priv->lid_force_sleep);
 
752
                break;
 
753
        case PROP_IS_DOCKED:
 
754
                g_value_set_boolean (value, client->priv->is_docked);
 
755
                break;
 
756
        default:
 
757
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
758
                break;
 
759
        }
 
760
}
 
761
 
 
762
/*
 
763
 * up_client_class_init:
 
764
 * @klass: The UpClientClass
 
765
 */
 
766
static void
 
767
up_client_class_init (UpClientClass *klass)
 
768
{
 
769
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
770
 
 
771
        object_class->get_property = up_client_get_property;
 
772
        object_class->finalize = up_client_finalize;
 
773
 
 
774
        /**
 
775
         * UpClient:daemon-version:
 
776
         *
 
777
         * The daemon version.
 
778
         *
 
779
         * Since: 0.9.0
 
780
         */
 
781
        g_object_class_install_property (object_class,
 
782
                                         PROP_DAEMON_VERSION,
 
783
                                         g_param_spec_string ("daemon-version",
 
784
                                                              "Daemon version",
 
785
                                                              NULL,
 
786
                                                              NULL,
 
787
                                                              G_PARAM_READABLE));
 
788
        /**
 
789
         * UpClient:can-suspend:
 
790
         *
 
791
         * If the computer can suspend.
 
792
         *
 
793
         * Since: 0.9.0
 
794
         */
 
795
        g_object_class_install_property (object_class,
 
796
                                         PROP_CAN_SUSPEND,
 
797
                                         g_param_spec_boolean ("can-suspend",
 
798
                                                               "If the computer can suspend",
 
799
                                                               NULL,
 
800
                                                               FALSE,
 
801
                                                               G_PARAM_READABLE));
 
802
        /**
 
803
         * UpClient:can-hibernate:
 
804
         *
 
805
         * If the computer can hibernate.
 
806
         *
 
807
         * Since: 0.9.0
 
808
         */
 
809
        g_object_class_install_property (object_class,
 
810
                                         PROP_CAN_HIBERNATE,
 
811
                                         g_param_spec_boolean ("can-hibernate",
 
812
                                                               "If the computer can hibernate",
 
813
                                                               NULL,
 
814
                                                               FALSE,
 
815
                                                               G_PARAM_READABLE));
 
816
        /**
 
817
         * UpClient:on-battery:
 
818
         *
 
819
         * If the computer is on battery power.
 
820
         *
 
821
         * Since: 0.9.0
 
822
         */
 
823
        g_object_class_install_property (object_class,
 
824
                                         PROP_ON_BATTERY,
 
825
                                         g_param_spec_boolean ("on-battery",
 
826
                                                               "If the computer is on battery power",
 
827
                                                               NULL,
 
828
                                                               FALSE,
 
829
                                                               G_PARAM_READABLE));
 
830
        /**
 
831
         * UpClient:on-low-battery:
 
832
         *
 
833
         * If the computer is on low battery power.
 
834
         *
 
835
         * Since: 0.9.0
 
836
         */
 
837
        g_object_class_install_property (object_class,
 
838
                                         PROP_ON_LOW_BATTERY,
 
839
                                         g_param_spec_boolean ("on-low-battery",
 
840
                                                               "If the computer is on low battery power",
 
841
                                                               NULL,
 
842
                                                               FALSE,
 
843
                                                               G_PARAM_READABLE));
 
844
        /**
 
845
         * UpClient:lid-is-closed:
 
846
         *
 
847
         * If the laptop lid is closed.
 
848
         *
 
849
         * Since: 0.9.0
 
850
         */
 
851
        g_object_class_install_property (object_class,
 
852
                                         PROP_LID_IS_CLOSED,
 
853
                                         g_param_spec_boolean ("lid-is-closed",
 
854
                                                               "If the laptop lid is closed",
 
855
                                                               NULL,
 
856
                                                               FALSE,
 
857
                                                               G_PARAM_READABLE));
 
858
        /**
 
859
         * UpClient:lid-is-present:
 
860
         *
 
861
         * If a laptop lid is present.
 
862
         *
 
863
         * Since: 0.9.0
 
864
         */
 
865
        g_object_class_install_property (object_class,
 
866
                                         PROP_LID_IS_PRESENT,
 
867
                                         g_param_spec_boolean ("lid-is-present",
 
868
                                                               "If a laptop lid is present",
 
869
                                                               NULL,
 
870
                                                               FALSE,
 
871
                                                               G_PARAM_READABLE));
 
872
 
 
873
        /**
 
874
         * UpClient:lid-force-sleep:
 
875
         *
 
876
         * If a laptop has to sleep if the lid is closed.
 
877
         *
 
878
         * Since: 0.9.9
 
879
         */
 
880
        g_object_class_install_property (object_class,
 
881
                                         PROP_LID_FORCE_SLEEP,
 
882
                                         g_param_spec_boolean ("lid-force-sleep",
 
883
                                                               "If a laptop has to sleep on lid close",
 
884
                                                               NULL,
 
885
                                                               FALSE,
 
886
                                                               G_PARAM_READABLE));
 
887
 
 
888
        /**
 
889
         * UpClient:is-docked:
 
890
         *
 
891
         * If the laptop is docked
 
892
         *
 
893
         * Since: 0.9.8
 
894
         */
 
895
        g_object_class_install_property (object_class,
 
896
                                         PROP_IS_DOCKED,
 
897
                                         g_param_spec_boolean ("is-docked",
 
898
                                                               "If a laptop is docked",
 
899
                                                               NULL,
 
900
                                                               FALSE,
 
901
                                                               G_PARAM_READABLE));
 
902
 
 
903
        /**
 
904
         * UpClient::device-added:
 
905
         * @client: the #UpClient instance that emitted the signal
 
906
         * @device: the #UpDevice that was added.
 
907
         *
 
908
         * The ::device-added signal is emitted when a power device is added.
 
909
         *
 
910
         * Since: 0.9.0
 
911
         **/
 
912
        signals [UP_CLIENT_DEVICE_ADDED] =
 
913
                g_signal_new ("device-added",
 
914
                              G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
 
915
                              G_STRUCT_OFFSET (UpClientClass, device_added),
 
916
                              NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
 
917
                              G_TYPE_NONE, 1, UP_TYPE_DEVICE);
 
918
 
 
919
        /**
 
920
         * UpClient::device-removed:
 
921
         * @client: the #UpClient instance that emitted the signal
 
922
         * @device: the #UpDevice that was removed.
 
923
         *
 
924
         * The ::device-added signal is emitted when a power device is removed.
 
925
         *
 
926
         * Since: 0.9.0
 
927
         **/
 
928
        signals [UP_CLIENT_DEVICE_REMOVED] =
 
929
                g_signal_new ("device-removed",
 
930
                              G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
 
931
                              G_STRUCT_OFFSET (UpClientClass, device_removed),
 
932
                              NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
 
933
                              G_TYPE_NONE, 1, UP_TYPE_DEVICE);
 
934
 
 
935
        /**
 
936
         * UpClient::device-changed:
 
937
         * @client: the #UpClient instance that emitted the signal
 
938
         * @device: the #UpDevice that was changed.
 
939
         *
 
940
         * The ::device-changed signal is emitted when a power device is changed.
 
941
         *
 
942
         * Since: 0.9.0
 
943
         **/
 
944
        signals [UP_CLIENT_DEVICE_CHANGED] =
 
945
                g_signal_new ("device-changed",
 
946
                              G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
 
947
                              G_STRUCT_OFFSET (UpClientClass, device_changed),
 
948
                              NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
 
949
                              G_TYPE_NONE, 1, UP_TYPE_DEVICE);
 
950
 
 
951
        /**
 
952
         * UpClient::changed:
 
953
         * @client: the #UpClient instance that emitted the signal
 
954
         *
 
955
         * The ::changed signal is emitted when properties may have changed.
 
956
         *
 
957
         * Since: 0.9.0
 
958
         **/
 
959
        signals [UP_CLIENT_CHANGED] =
 
960
                g_signal_new ("changed",
 
961
                              G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
 
962
                              G_STRUCT_OFFSET (UpClientClass, changed),
 
963
                              NULL, NULL, g_cclosure_marshal_VOID__VOID,
 
964
                              G_TYPE_NONE, 0);
 
965
 
 
966
        /**
 
967
         * UpClient::notify-sleep:
 
968
         * @client: the #UpClient instance that emitted the signal
 
969
         * @sleep_kind: the #UpSleepKind
 
970
         *
 
971
         * The ::notify-sleep signal is emitted when system sleep is
 
972
         * about to occur. Applications have about 1 second to do
 
973
         * anything they need to do. There is no way to stop the sleep
 
974
         * process.
 
975
         *
 
976
         * Since: 0.9.11
 
977
         **/
 
978
        signals [UP_CLIENT_NOTIFY_SLEEP] =
 
979
                g_signal_new ("notify-sleep",
 
980
                              G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
 
981
                              G_STRUCT_OFFSET (UpClientClass, notify_sleep),
 
982
                              NULL, NULL, g_cclosure_marshal_VOID__UINT,
 
983
                              G_TYPE_NONE, 1, G_TYPE_UINT);
 
984
 
 
985
        /**
 
986
         * UpClient::notify-resume:
 
987
         * @client: the #UpClient instance that emitted the signal
 
988
         * @sleep_kind: the #UpSleepKind
 
989
         *
 
990
         * The ::notify-resume signal is emitted when the system has
 
991
         * resumed.
 
992
         *
 
993
         * Since: 0.9.11
 
994
         **/
 
995
        signals [UP_CLIENT_NOTIFY_RESUME] =
 
996
                g_signal_new ("notify-resume",
 
997
                              G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
 
998
                              G_STRUCT_OFFSET (UpClientClass, notify_resume),
 
999
                              NULL, NULL, g_cclosure_marshal_VOID__UINT,
 
1000
                              G_TYPE_NONE, 1, G_TYPE_UINT);
 
1001
 
 
1002
        g_type_class_add_private (klass, sizeof (UpClientPrivate));
 
1003
}
 
1004
 
 
1005
/**
 
1006
 * up_client_enumerate_devices_sync:
 
1007
 * @client: a #UpClient instance.
 
1008
 * @error: a #GError, or %NULL.
 
1009
 *
 
1010
 * Enumerates all the devices from the daemon.
 
1011
 *
 
1012
 * Return value: %TRUE for success, else %FALSE.
 
1013
 *
 
1014
 * Since: 0.9.0
 
1015
 **/
 
1016
gboolean
 
1017
up_client_enumerate_devices_sync (UpClient *client, GCancellable *cancellable, GError **error)
 
1018
{
 
1019
        const gchar *object_path;
 
1020
        GPtrArray *devices;
 
1021
        guint i;
 
1022
        gboolean ret = TRUE;
 
1023
 
 
1024
        /* already done */
 
1025
        if (client->priv->done_enumerate)
 
1026
                goto out;
 
1027
 
 
1028
        /* coldplug */
 
1029
        devices = up_client_get_devices_private (client, error);
 
1030
        if (devices == NULL) {
 
1031
                ret = FALSE;
 
1032
                goto out;
 
1033
        }
 
1034
        for (i=0; i<devices->len; i++) {
 
1035
                object_path = (const gchar *) g_ptr_array_index (devices, i);
 
1036
                up_client_add (client, object_path);
 
1037
        }
 
1038
 
 
1039
        /* only do this once per instance */
 
1040
        client->priv->done_enumerate = TRUE;
 
1041
out:
 
1042
        return ret;
 
1043
}
 
1044
 
 
1045
/*
 
1046
 * up_client_init:
 
1047
 * @client: This class instance
 
1048
 */
 
1049
static void
 
1050
up_client_init (UpClient *client)
 
1051
{
 
1052
        GError *error = NULL;
 
1053
 
 
1054
        client->priv = UP_CLIENT_GET_PRIVATE (client);
 
1055
        client->priv->array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
 
1056
        client->priv->have_properties = FALSE;
 
1057
        client->priv->done_enumerate = FALSE;
 
1058
 
 
1059
        /* get on the bus */
 
1060
        client->priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
 
1061
        if (client->priv->bus == NULL) {
 
1062
                g_warning ("Couldn't connect to system bus: %s", error->message);
 
1063
                g_error_free (error);
 
1064
                goto out;
 
1065
        }
 
1066
 
 
1067
        /* connect to main interface */
 
1068
        client->priv->proxy = dbus_g_proxy_new_for_name (client->priv->bus,
 
1069
                                                         "org.freedesktop.UPower",
 
1070
                                                         "/org/freedesktop/UPower",
 
1071
                                                         "org.freedesktop.UPower");
 
1072
        if (client->priv->proxy == NULL) {
 
1073
                g_warning ("Couldn't connect to proxy");
 
1074
                goto out;
 
1075
        }
 
1076
 
 
1077
        /* connect to properties interface */
 
1078
        client->priv->prop_proxy = dbus_g_proxy_new_for_name (client->priv->bus,
 
1079
                                                              "org.freedesktop.UPower",
 
1080
                                                              "/org/freedesktop/UPower",
 
1081
                                                              "org.freedesktop.DBus.Properties");
 
1082
        if (client->priv->prop_proxy == NULL) {
 
1083
                g_warning ("Couldn't connect to proxy");
 
1084
                goto out;
 
1085
        }
 
1086
 
 
1087
        dbus_g_proxy_add_signal (client->priv->proxy, "DeviceAdded", G_TYPE_STRING, G_TYPE_INVALID);
 
1088
        dbus_g_proxy_add_signal (client->priv->proxy, "DeviceRemoved", G_TYPE_STRING, G_TYPE_INVALID);
 
1089
        dbus_g_proxy_add_signal (client->priv->proxy, "DeviceChanged", G_TYPE_STRING, G_TYPE_INVALID);
 
1090
        dbus_g_proxy_add_signal (client->priv->proxy, "Changed", G_TYPE_INVALID);
 
1091
        dbus_g_proxy_add_signal (client->priv->proxy, "NotifySleep", G_TYPE_STRING, G_TYPE_INVALID);
 
1092
        dbus_g_proxy_add_signal (client->priv->proxy, "NotifyResume", G_TYPE_STRING, G_TYPE_INVALID);
 
1093
 
 
1094
        /* all callbacks */
 
1095
        dbus_g_proxy_connect_signal (client->priv->proxy, "DeviceAdded",
 
1096
                                     G_CALLBACK (up_device_added_cb), client, NULL);
 
1097
        dbus_g_proxy_connect_signal (client->priv->proxy, "DeviceRemoved",
 
1098
                                     G_CALLBACK (up_device_removed_cb), client, NULL);
 
1099
        dbus_g_proxy_connect_signal (client->priv->proxy, "DeviceChanged",
 
1100
                                     G_CALLBACK (up_device_changed_cb), client, NULL);
 
1101
        dbus_g_proxy_connect_signal (client->priv->proxy, "Changed",
 
1102
                                     G_CALLBACK (up_client_changed_cb), client, NULL);
 
1103
        dbus_g_proxy_connect_signal (client->priv->proxy, "NotifySleep",
 
1104
                                     G_CALLBACK (up_client_notify_sleep_cb), client, NULL);
 
1105
        dbus_g_proxy_connect_signal (client->priv->proxy, "NotifyResume",
 
1106
                                     G_CALLBACK (up_client_notify_resume_cb), client, NULL);
 
1107
out:
 
1108
        return;
 
1109
}
 
1110
 
 
1111
/*
 
1112
 * up_client_finalize:
 
1113
 */
 
1114
static void
 
1115
up_client_finalize (GObject *object)
 
1116
{
 
1117
        UpClient *client;
 
1118
 
 
1119
        g_return_if_fail (UP_IS_CLIENT (object));
 
1120
 
 
1121
        client = UP_CLIENT (object);
 
1122
 
 
1123
        g_ptr_array_unref (client->priv->array);
 
1124
 
 
1125
        if (client->priv->bus)
 
1126
                dbus_g_connection_unref (client->priv->bus);
 
1127
 
 
1128
        if (client->priv->proxy != NULL)
 
1129
                g_object_unref (client->priv->proxy);
 
1130
 
 
1131
        if (client->priv->prop_proxy != NULL)
 
1132
                g_object_unref (client->priv->prop_proxy);
 
1133
 
 
1134
        g_free (client->priv->daemon_version);
 
1135
 
 
1136
        G_OBJECT_CLASS (up_client_parent_class)->finalize (object);
 
1137
}
 
1138
 
 
1139
/**
 
1140
 * up_client_new:
 
1141
 *
 
1142
 * Creates a new #UpClient object.
 
1143
 *
 
1144
 * Return value: a new UpClient object.
 
1145
 *
 
1146
 * Since: 0.9.0
 
1147
 **/
 
1148
UpClient *
 
1149
up_client_new (void)
 
1150
{
 
1151
        if (up_client_object != NULL) {
 
1152
                g_object_ref (up_client_object);
 
1153
        } else {
 
1154
                up_client_object = g_object_new (UP_TYPE_CLIENT, NULL);
 
1155
                g_object_add_weak_pointer (up_client_object, &up_client_object);
 
1156
        }
 
1157
        return UP_CLIENT (up_client_object);
 
1158
}
 
1159