Merge lp:~psusi/ubuntu/natty/gnome-power-manager/fix-duplicate-battery into lp:ubuntu/natty/gnome-power-manager

Proposed by Phillip Susi
Status: Merged
Merge reported by: Phillip Susi
Merged at revision: not available
Proposed branch: lp:~psusi/ubuntu/natty/gnome-power-manager/fix-duplicate-battery
Merge into: lp:ubuntu/natty/gnome-power-manager
Diff against target: 1358 lines (+1308/-3)
6 files modified
.pc/16-fix-duplicate-battery.patch/src/gpm-engine.c (+1277/-0)
.pc/applied-patches (+1/-0)
debian/changelog (+8/-0)
debian/patches/16-fix-duplicate-battery.patch (+20/-0)
debian/patches/series (+2/-0)
src/gpm-engine.c (+0/-3)
To merge this branch: bzr merge lp:~psusi/ubuntu/natty/gnome-power-manager/fix-duplicate-battery
Reviewer Review Type Date Requested Status
Marc Deslauriers Approve
Michele Damiano Torelli (community) Approve
Luke Yelavich Pending
Ubuntu branches Pending
Review via email: mp+67466@code.launchpad.net

This proposal supersedes a proposal from 2011-06-26.

To post a comment you must log in.
Revision history for this message
Luke Yelavich (themuso) wrote : Posted in a previous version of this proposal

See comments in above referenced bug re SRU paperwork and oneiric fix.

review: Needs Fixing
Revision history for this message
Michele Damiano Torelli (s3th) :
review: Approve
Revision history for this message
Marc Deslauriers (mdeslaur) wrote :

This looks good. I've uploaded it to -proposed with a simple change to debian/changelog to use a better version number, and to specify the right pocket.
Thanks!

review: Approve
Revision history for this message
Scott Moser (smoser) wrote :

If you are able to, please mark this as Merged.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory '.pc/16-fix-duplicate-battery.patch'
2=== added file '.pc/16-fix-duplicate-battery.patch/.timestamp'
3=== added directory '.pc/16-fix-duplicate-battery.patch/src'
4=== added file '.pc/16-fix-duplicate-battery.patch/src/gpm-engine.c'
5--- .pc/16-fix-duplicate-battery.patch/src/gpm-engine.c 1970-01-01 00:00:00 +0000
6+++ .pc/16-fix-duplicate-battery.patch/src/gpm-engine.c 2011-07-10 20:29:23 +0000
7@@ -0,0 +1,1277 @@
8+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
9+ *
10+ * Copyright (C) 2007-2008 Richard Hughes <richard@hughsie.com>
11+ *
12+ * Licensed under the GNU General Public License Version 2
13+ *
14+ * This program is free software; you can redistribute it and/or modify
15+ * it under the terms of the GNU General Public License as published by
16+ * the Free Software Foundation; either version 2 of the License, or
17+ * (at your option) any later version.
18+ *
19+ * This program is distributed in the hope that it will be useful,
20+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22+ * GNU General Public License for more details.
23+ *
24+ * You should have received a copy of the GNU General Public License
25+ * along with this program; if not, write to the Free Software
26+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27+ */
28+
29+#include "config.h"
30+
31+#include <string.h>
32+#include <glib.h>
33+#include <glib/gi18n.h>
34+#include <gconf/gconf-client.h>
35+#include <libupower-glib/upower.h>
36+
37+#include "egg-debug.h"
38+
39+#include "gpm-common.h"
40+#include "gpm-upower.h"
41+#include "gpm-marshal.h"
42+#include "gpm-engine.h"
43+#include "gpm-stock-icons.h"
44+#include "gpm-prefs-server.h"
45+#include "gpm-phone.h"
46+
47+static void gpm_engine_finalize (GObject *object);
48+
49+#define GPM_ENGINE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPM_TYPE_ENGINE, GpmEnginePrivate))
50+#define GPM_ENGINE_RESUME_DELAY 2*1000
51+#define GPM_ENGINE_WARN_ACCURACY 20
52+
53+struct GpmEnginePrivate
54+{
55+ GConfClient *conf;
56+ UpClient *client;
57+ UpDevice *battery_composite;
58+ GPtrArray *array;
59+ GpmPhone *phone;
60+ GpmIconPolicy icon_policy;
61+ gchar *previous_icon;
62+ gchar *previous_summary;
63+
64+ gboolean use_time_primary;
65+ gboolean time_is_accurate;
66+
67+ guint low_percentage;
68+ guint critical_percentage;
69+ guint action_percentage;
70+ guint low_time;
71+ guint critical_time;
72+ guint action_time;
73+};
74+
75+enum {
76+ ICON_CHANGED,
77+ SUMMARY_CHANGED,
78+ FULLY_CHARGED,
79+ CHARGE_LOW,
80+ CHARGE_CRITICAL,
81+ CHARGE_ACTION,
82+ DISCHARGING,
83+ LOW_CAPACITY,
84+ PERHAPS_RECALL,
85+ DEVICES_CHANGED,
86+ LAST_SIGNAL
87+};
88+
89+static guint signals [LAST_SIGNAL] = { 0 };
90+static gpointer gpm_engine_object = NULL;
91+
92+G_DEFINE_TYPE (GpmEngine, gpm_engine, G_TYPE_OBJECT)
93+
94+static UpDevice *gpm_engine_get_composite_device (GpmEngine *engine, UpDevice *original_device);
95+static UpDevice *gpm_engine_update_composite_device (GpmEngine *engine, UpDevice *original_device);
96+
97+typedef enum {
98+ GPM_ENGINE_WARNING_NONE = 0,
99+ GPM_ENGINE_WARNING_DISCHARGING = 1,
100+ GPM_ENGINE_WARNING_LOW = 2,
101+ GPM_ENGINE_WARNING_CRITICAL = 3,
102+ GPM_ENGINE_WARNING_ACTION = 4
103+} GpmEngineWarning;
104+
105+/**
106+ * gpm_engine_get_warning_csr:
107+ **/
108+static GpmEngineWarning
109+gpm_engine_get_warning_csr (GpmEngine *engine, UpDevice *device)
110+{
111+ gdouble percentage;
112+
113+ /* get device properties */
114+ g_object_get (device, "percentage", &percentage, NULL);
115+
116+ if (percentage < 26.0f)
117+ return GPM_ENGINE_WARNING_LOW;
118+ else if (percentage < 13.0f)
119+ return GPM_ENGINE_WARNING_CRITICAL;
120+ return GPM_ENGINE_WARNING_NONE;
121+}
122+
123+/**
124+ * gpm_engine_get_warning_percentage:
125+ **/
126+static GpmEngineWarning
127+gpm_engine_get_warning_percentage (GpmEngine *engine, UpDevice *device)
128+{
129+ gdouble percentage;
130+
131+ /* get device properties */
132+ g_object_get (device, "percentage", &percentage, NULL);
133+
134+ if (percentage <= engine->priv->action_percentage)
135+ return GPM_ENGINE_WARNING_ACTION;
136+ if (percentage <= engine->priv->critical_percentage)
137+ return GPM_ENGINE_WARNING_CRITICAL;
138+ if (percentage <= engine->priv->low_percentage)
139+ return GPM_ENGINE_WARNING_LOW;
140+ return GPM_ENGINE_WARNING_NONE;
141+}
142+
143+/**
144+ * gpm_engine_get_warning_time:
145+ **/
146+static GpmEngineWarning
147+gpm_engine_get_warning_time (GpmEngine *engine, UpDevice *device)
148+{
149+ UpDeviceKind kind;
150+ gint64 time_to_empty;
151+
152+ /* get device properties */
153+ g_object_get (device,
154+ "kind", &kind,
155+ "time-to-empty", &time_to_empty,
156+ NULL);
157+
158+ /* this is probably an error condition */
159+ if (time_to_empty == 0) {
160+ egg_debug ("time zero, falling back to percentage for %s", up_device_kind_to_string (kind));
161+ return gpm_engine_get_warning_percentage (engine, device);
162+ }
163+
164+ if (time_to_empty <= engine->priv->action_time)
165+ return GPM_ENGINE_WARNING_ACTION;
166+ if (time_to_empty <= engine->priv->critical_time)
167+ return GPM_ENGINE_WARNING_CRITICAL;
168+ if (time_to_empty <= engine->priv->low_time)
169+ return GPM_ENGINE_WARNING_LOW;
170+ return GPM_ENGINE_WARNING_NONE;
171+}
172+
173+/**
174+ * gpm_engine_get_warning:
175+ *
176+ * This gets the possible engine state for the device according to the
177+ * policy, which could be per-percent, or per-time.
178+ *
179+ * Return value: A GpmEngine state, e.g. GPM_ENGINE_WARNING_DISCHARGING
180+ **/
181+static GpmEngineWarning
182+gpm_engine_get_warning (GpmEngine *engine, UpDevice *device)
183+{
184+ UpDeviceKind kind;
185+ UpDeviceState state;
186+ GpmEngineWarning warning_type;
187+
188+ /* get device properties */
189+ g_object_get (device,
190+ "kind", &kind,
191+ "state", &state,
192+ NULL);
193+
194+ /* default to no engine */
195+ warning_type = GPM_ENGINE_WARNING_NONE;
196+
197+ /* if the device in question is on ac, don't give a warning */
198+ if (state == UP_DEVICE_STATE_CHARGING)
199+ goto out;
200+
201+ if (kind == UP_DEVICE_KIND_MOUSE ||
202+ kind == UP_DEVICE_KIND_KEYBOARD) {
203+
204+ warning_type = gpm_engine_get_warning_csr (engine, device);
205+
206+ } else if (kind == UP_DEVICE_KIND_UPS ||
207+#if UP_CHECK_VERSION(0,9,5)
208+ kind == UP_DEVICE_KIND_MEDIA_PLAYER ||
209+ kind == UP_DEVICE_KIND_TABLET ||
210+ kind == UP_DEVICE_KIND_COMPUTER ||
211+#endif
212+ kind == UP_DEVICE_KIND_PDA) {
213+
214+ warning_type = gpm_engine_get_warning_percentage (engine, device);
215+
216+ } else if (kind == UP_DEVICE_KIND_PHONE) {
217+
218+ warning_type = gpm_engine_get_warning_percentage (engine, device);
219+
220+ } else if (kind == UP_DEVICE_KIND_BATTERY) {
221+ /* only use the time when it is accurate, and GConf is not disabled */
222+ if (engine->priv->use_time_primary)
223+ warning_type = gpm_engine_get_warning_time (engine, device);
224+ else
225+ warning_type = gpm_engine_get_warning_percentage (engine, device);
226+ }
227+
228+ /* If we have no important engines, we should test for discharging */
229+ if (warning_type == GPM_ENGINE_WARNING_NONE) {
230+ if (state == UP_DEVICE_STATE_DISCHARGING)
231+ warning_type = GPM_ENGINE_WARNING_DISCHARGING;
232+ }
233+
234+ out:
235+ return warning_type;
236+}
237+
238+/**
239+ * gpm_engine_get_summary:
240+ * @engine: This engine class instance
241+ * @string: The returned string
242+ *
243+ * Returns the complete tooltip ready for display
244+ **/
245+gchar *
246+gpm_engine_get_summary (GpmEngine *engine)
247+{
248+ guint i;
249+ GPtrArray *array;
250+ UpDevice *device;
251+ UpDeviceState state;
252+ GString *tooltip = NULL;
253+ gchar *part;
254+ gboolean is_present;
255+
256+ g_return_val_if_fail (GPM_IS_ENGINE (engine), NULL);
257+
258+ /* need to get AC state */
259+ tooltip = g_string_new ("");
260+
261+ /* do we have specific device types? */
262+ array = engine->priv->array;
263+ for (i=0;i<array->len;i++) {
264+ device = g_ptr_array_index (engine->priv->array, i);
265+ g_object_get (device,
266+ "is-present", &is_present,
267+ "state", &state,
268+ NULL);
269+ if (!is_present)
270+ continue;
271+ if (state == UP_DEVICE_STATE_EMPTY)
272+ continue;
273+ part = gpm_upower_get_device_summary (device);
274+ if (part != NULL)
275+ g_string_append_printf (tooltip, "%s\n", part);
276+ g_free (part);
277+ }
278+
279+ /* remove the last \n */
280+ g_string_truncate (tooltip, tooltip->len-1);
281+
282+ egg_debug ("tooltip: %s", tooltip->str);
283+
284+ return g_string_free (tooltip, FALSE);
285+}
286+
287+/**
288+ * gpm_engine_get_icon_priv:
289+ *
290+ * Returns the icon
291+ **/
292+static gchar *
293+gpm_engine_get_icon_priv (GpmEngine *engine, UpDeviceKind device_kind, GpmEngineWarning warning, gboolean use_state)
294+{
295+ guint i;
296+ GPtrArray *array;
297+ UpDevice *device;
298+ GpmEngineWarning warning_temp;
299+ UpDeviceKind kind;
300+ UpDeviceState state;
301+ gboolean is_present;
302+
303+ /* do we have specific device types? */
304+ array = engine->priv->array;
305+ for (i=0;i<array->len;i++) {
306+ device = g_ptr_array_index (engine->priv->array, i);
307+
308+ /* get device properties */
309+ g_object_get (device,
310+ "kind", &kind,
311+ "state", &state,
312+ "is-present", &is_present,
313+ NULL);
314+
315+ /* if battery then use composite device to cope with multiple batteries */
316+ if (kind == UP_DEVICE_KIND_BATTERY)
317+ device = gpm_engine_get_composite_device (engine, device);
318+
319+ warning_temp = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(device), "engine-warning-old"));
320+ if (kind == device_kind && is_present) {
321+ if (warning != GPM_ENGINE_WARNING_NONE) {
322+ if (warning_temp == warning)
323+ return gpm_upower_get_device_icon (device);
324+ continue;
325+ }
326+ if (use_state) {
327+ if (state == UP_DEVICE_STATE_CHARGING || state == UP_DEVICE_STATE_DISCHARGING)
328+ return gpm_upower_get_device_icon (device);
329+ continue;
330+ }
331+ return gpm_upower_get_device_icon (device);
332+ }
333+ }
334+ return NULL;
335+}
336+
337+/**
338+ * gpm_engine_get_icon:
339+ *
340+ * Returns the icon
341+ **/
342+gchar *
343+gpm_engine_get_icon (GpmEngine *engine)
344+{
345+ gchar *icon = NULL;
346+
347+ g_return_val_if_fail (GPM_IS_ENGINE (engine), NULL);
348+
349+ /* policy */
350+ if (engine->priv->icon_policy == GPM_ICON_POLICY_NEVER) {
351+ egg_debug ("no icon allowed, so no icon will be displayed.");
352+ return NULL;
353+ }
354+
355+ /* we try CRITICAL: BATTERY, UPS, MOUSE, KEYBOARD */
356+ icon = gpm_engine_get_icon_priv (engine, UP_DEVICE_KIND_BATTERY, GPM_ENGINE_WARNING_CRITICAL, FALSE);
357+ if (icon != NULL)
358+ return icon;
359+ icon = gpm_engine_get_icon_priv (engine, UP_DEVICE_KIND_UPS, GPM_ENGINE_WARNING_CRITICAL, FALSE);
360+ if (icon != NULL)
361+ return icon;
362+ icon = gpm_engine_get_icon_priv (engine, UP_DEVICE_KIND_MOUSE, GPM_ENGINE_WARNING_CRITICAL, FALSE);
363+ if (icon != NULL)
364+ return icon;
365+ icon = gpm_engine_get_icon_priv (engine, UP_DEVICE_KIND_KEYBOARD, GPM_ENGINE_WARNING_CRITICAL, FALSE);
366+ if (icon != NULL)
367+ return icon;
368+
369+ /* policy */
370+ if (engine->priv->icon_policy == GPM_ICON_POLICY_CRITICAL) {
371+ egg_debug ("no devices critical, so no icon will be displayed.");
372+ return NULL;
373+ }
374+
375+ /* we try CRITICAL: BATTERY, UPS, MOUSE, KEYBOARD */
376+ icon = gpm_engine_get_icon_priv (engine, UP_DEVICE_KIND_BATTERY, GPM_ENGINE_WARNING_LOW, FALSE);
377+ if (icon != NULL)
378+ return icon;
379+ icon = gpm_engine_get_icon_priv (engine, UP_DEVICE_KIND_UPS, GPM_ENGINE_WARNING_LOW, FALSE);
380+ if (icon != NULL)
381+ return icon;
382+ icon = gpm_engine_get_icon_priv (engine, UP_DEVICE_KIND_MOUSE, GPM_ENGINE_WARNING_LOW, FALSE);
383+ if (icon != NULL)
384+ return icon;
385+ icon = gpm_engine_get_icon_priv (engine, UP_DEVICE_KIND_KEYBOARD, GPM_ENGINE_WARNING_LOW, FALSE);
386+ if (icon != NULL)
387+ return icon;
388+
389+ /* policy */
390+ if (engine->priv->icon_policy == GPM_ICON_POLICY_LOW) {
391+ egg_debug ("no devices low, so no icon will be displayed.");
392+ return NULL;
393+ }
394+
395+ /* we try (DIS)CHARGING: BATTERY, UPS */
396+ icon = gpm_engine_get_icon_priv (engine, UP_DEVICE_KIND_BATTERY, GPM_ENGINE_WARNING_NONE, TRUE);
397+ if (icon != NULL)
398+ return icon;
399+ icon = gpm_engine_get_icon_priv (engine, UP_DEVICE_KIND_UPS, GPM_ENGINE_WARNING_NONE, TRUE);
400+ if (icon != NULL)
401+ return icon;
402+
403+ /* policy */
404+ if (engine->priv->icon_policy == GPM_ICON_POLICY_CHARGE) {
405+ egg_debug ("no devices (dis)charging, so no icon will be displayed.");
406+ return NULL;
407+ }
408+
409+ /* we try PRESENT: BATTERY, UPS */
410+ icon = gpm_engine_get_icon_priv (engine, UP_DEVICE_KIND_BATTERY, GPM_ENGINE_WARNING_NONE, FALSE);
411+ if (icon != NULL)
412+ return icon;
413+ icon = gpm_engine_get_icon_priv (engine, UP_DEVICE_KIND_UPS, GPM_ENGINE_WARNING_NONE, FALSE);
414+ if (icon != NULL)
415+ return icon;
416+
417+ /* policy */
418+ if (engine->priv->icon_policy == GPM_ICON_POLICY_PRESENT) {
419+ egg_debug ("no devices present, so no icon will be displayed.");
420+ return NULL;
421+ }
422+
423+ /* we fallback to the ac_adapter icon */
424+ egg_debug ("Using fallback");
425+ return g_strdup (GPM_STOCK_AC_ADAPTER);
426+}
427+
428+/**
429+ * gpm_engine_recalculate_state_icon:
430+ */
431+static gboolean
432+gpm_engine_recalculate_state_icon (GpmEngine *engine)
433+{
434+ gchar *icon;
435+
436+ g_return_val_if_fail (engine != NULL, FALSE);
437+ g_return_val_if_fail (GPM_IS_ENGINE (engine), FALSE);
438+
439+ /* show a different icon if we are disconnected */
440+ icon = gpm_engine_get_icon (engine);
441+ if (icon == NULL) {
442+ /* none before, now none */
443+ if (engine->priv->previous_icon == NULL)
444+ return FALSE;
445+ /* icon before, now none */
446+ egg_debug ("** EMIT: icon-changed: none");
447+ g_signal_emit (engine, signals [ICON_CHANGED], 0, NULL);
448+
449+ g_free (engine->priv->previous_icon);
450+ engine->priv->previous_icon = NULL;
451+ return TRUE;
452+ }
453+
454+ /* no icon before, now icon */
455+ if (engine->priv->previous_icon == NULL) {
456+ egg_debug ("** EMIT: icon-changed: %s", icon);
457+ g_signal_emit (engine, signals [ICON_CHANGED], 0, icon);
458+ engine->priv->previous_icon = icon;
459+ return TRUE;
460+ }
461+
462+ /* icon before, now different */
463+ if (strcmp (engine->priv->previous_icon, icon) != 0) {
464+ g_free (engine->priv->previous_icon);
465+ engine->priv->previous_icon = icon;
466+ egg_debug ("** EMIT: icon-changed: %s", icon);
467+ g_signal_emit (engine, signals [ICON_CHANGED], 0, icon);
468+ return TRUE;
469+ }
470+
471+ egg_debug ("no change");
472+ /* nothing to do */
473+ g_free (icon);
474+ return FALSE;
475+}
476+
477+/**
478+ * gpm_engine_recalculate_state_summary:
479+ */
480+static gboolean
481+gpm_engine_recalculate_state_summary (GpmEngine *engine)
482+{
483+ gchar *summary;
484+
485+ summary = gpm_engine_get_summary (engine);
486+ if (engine->priv->previous_summary == NULL) {
487+ engine->priv->previous_summary = summary;
488+ egg_debug ("** EMIT: summary-changed(1): %s", summary);
489+ g_signal_emit (engine, signals [SUMMARY_CHANGED], 0, summary);
490+ return TRUE;
491+ }
492+
493+ if (strcmp (engine->priv->previous_summary, summary) != 0) {
494+ g_free (engine->priv->previous_summary);
495+ engine->priv->previous_summary = summary;
496+ egg_debug ("** EMIT: summary-changed(2): %s", summary);
497+ g_signal_emit (engine, signals [SUMMARY_CHANGED], 0, summary);
498+ return TRUE;
499+ }
500+ egg_debug ("no change");
501+ /* nothing to do */
502+ g_free (summary);
503+ return FALSE;
504+}
505+
506+/**
507+ * gpm_engine_recalculate_state:
508+ */
509+static void
510+gpm_engine_recalculate_state (GpmEngine *engine)
511+{
512+
513+ g_return_if_fail (engine != NULL);
514+ g_return_if_fail (GPM_IS_ENGINE (engine));
515+
516+ gpm_engine_recalculate_state_icon (engine);
517+ gpm_engine_recalculate_state_summary (engine);
518+
519+ g_signal_emit (engine, signals [DEVICES_CHANGED], 0);
520+}
521+
522+/**
523+ * gpm_engine_conf_key_changed_cb:
524+ **/
525+static void
526+gpm_engine_conf_key_changed_cb (GConfClient *conf, guint cnxn_id, GConfEntry *entry, GpmEngine *engine)
527+{
528+ GConfValue *value;
529+ gchar *icon_policy;
530+
531+ if (entry == NULL)
532+ return;
533+ value = gconf_entry_get_value (entry);
534+ if (value == NULL)
535+ return;
536+
537+ if (strcmp (entry->key, GPM_CONF_USE_TIME_POLICY) == 0) {
538+
539+ engine->priv->use_time_primary = gconf_value_get_bool (value);
540+
541+ } else if (strcmp (entry->key, GPM_CONF_UI_ICON_POLICY) == 0) {
542+
543+ /* do we want to display the icon in the tray */
544+ icon_policy = gconf_client_get_string (conf, GPM_CONF_UI_ICON_POLICY, NULL);
545+ engine->priv->icon_policy = gpm_icon_policy_from_string (icon_policy);
546+ g_free (icon_policy);
547+
548+ /* perhaps change icon */
549+ gpm_engine_recalculate_state_icon (engine);
550+ }
551+}
552+
553+/**
554+ * gpm_engine_device_check_capacity:
555+ **/
556+static gboolean
557+gpm_engine_device_check_capacity (GpmEngine *engine, UpDevice *device)
558+{
559+ gboolean ret;
560+ UpDeviceKind kind;
561+ gdouble capacity;
562+
563+ /* get device properties */
564+ g_object_get (device,
565+ "kind", &kind,
566+ "capacity", &capacity,
567+ NULL);
568+
569+ /* not laptop battery */
570+ if (kind != UP_DEVICE_KIND_BATTERY)
571+ return FALSE;
572+
573+ /* capacity okay */
574+ if (capacity > 50.0f)
575+ return FALSE;
576+
577+ /* capacity invalid */
578+ if (capacity < 1.0f)
579+ return FALSE;
580+
581+ /* only emit this if specified in gconf */
582+ ret = gconf_client_get_bool (engine->priv->conf, GPM_CONF_NOTIFY_LOW_CAPACITY, NULL);
583+ if (ret) {
584+ egg_debug ("** EMIT: low-capacity");
585+ g_signal_emit (engine, signals [LOW_CAPACITY], 0, device);
586+ }
587+ return TRUE;
588+}
589+
590+/**
591+ * gpm_engine_get_composite_device:
592+ **/
593+static UpDevice *
594+gpm_engine_get_composite_device (GpmEngine *engine, UpDevice *original_device)
595+{
596+ guint battery_devices = 0;
597+ GPtrArray *array;
598+ UpDevice *device;
599+ UpDeviceKind kind;
600+ guint i;
601+
602+ /* find out how many batteries in the system */
603+ array = engine->priv->array;
604+ for (i=0;i<array->len;i++) {
605+ device = g_ptr_array_index (engine->priv->array, i);
606+ g_object_get (device,
607+ "kind", &kind,
608+ NULL);
609+ if (kind == UP_DEVICE_KIND_BATTERY)
610+ battery_devices++;
611+ }
612+
613+ /* just use the original device if only one primary battery */
614+ if (battery_devices <= 1) {
615+ egg_debug ("using original device as only one primary battery");
616+ device = original_device;
617+ goto out;
618+ }
619+
620+ /* use the composite device */
621+ device = engine->priv->battery_composite;
622+out:
623+ /* return composite device or original device */
624+ return device;
625+}
626+
627+/**
628+ * gpm_engine_update_composite_device:
629+ **/
630+static UpDevice *
631+gpm_engine_update_composite_device (GpmEngine *engine, UpDevice *original_device)
632+{
633+ guint i;
634+ gdouble percentage = 0.0;
635+ gdouble energy = 0.0;
636+ gdouble energy_full = 0.0;
637+ gdouble energy_rate = 0.0;
638+ gdouble energy_total = 0.0;
639+ gdouble energy_full_total = 0.0;
640+ gdouble energy_rate_total = 0.0;
641+ gint64 time_to_empty = 0;
642+ gint64 time_to_full = 0;
643+ guint battery_devices = 0;
644+ gboolean is_charging = FALSE;
645+ gboolean is_discharging = FALSE;
646+ gboolean is_fully_charged = TRUE;
647+ GPtrArray *array;
648+ UpDevice *device;
649+ UpDeviceState state;
650+ UpDeviceKind kind;
651+ gboolean debug;
652+ gchar *text;
653+
654+ /* are we printing to console? */
655+ debug = egg_debug_enabled ();
656+
657+ /* update the composite device */
658+ array = engine->priv->array;
659+ for (i=0;i<array->len;i++) {
660+ device = g_ptr_array_index (engine->priv->array, i);
661+ g_object_get (device,
662+ "kind", &kind,
663+ "state", &state,
664+ "energy", &energy,
665+ "energy-full", &energy_full,
666+ "energy-rate", &energy_rate,
667+ NULL);
668+ if (kind != UP_DEVICE_KIND_BATTERY)
669+ continue;
670+
671+ if (debug) {
672+ text = up_device_to_text (device);
673+ egg_debug ("printing device %i:\n%s", i, text);
674+ g_free (text);
675+ }
676+
677+ /* one of these will be charging or discharging */
678+ if (state == UP_DEVICE_STATE_CHARGING)
679+ is_charging = TRUE;
680+ if (state == UP_DEVICE_STATE_DISCHARGING)
681+ is_discharging = TRUE;
682+ if (state != UP_DEVICE_STATE_FULLY_CHARGED)
683+ is_fully_charged = FALSE;
684+
685+ /* sum up composite */
686+ energy_total += energy;
687+ energy_full_total += energy_full;
688+ energy_rate_total += energy_rate;
689+ battery_devices++;
690+ }
691+
692+ /* just use the original device if only one primary battery */
693+ if (battery_devices == 1) {
694+ egg_debug ("using original device as only one primary battery");
695+ device = original_device;
696+ goto out;
697+ }
698+
699+ /* use percentage weighted for each battery capacity */
700+ percentage = 100.0 * energy_total / energy_full_total;
701+
702+ /* set composite state */
703+ if (is_charging)
704+ state = UP_DEVICE_STATE_CHARGING;
705+ else if (is_discharging)
706+ state = UP_DEVICE_STATE_DISCHARGING;
707+ else if (is_fully_charged)
708+ state = UP_DEVICE_STATE_FULLY_CHARGED;
709+ else
710+ state = UP_DEVICE_STATE_UNKNOWN;
711+
712+ /* calculate a quick and dirty time remaining value */
713+ if (energy_rate_total > 0) {
714+ if (state == UP_DEVICE_STATE_DISCHARGING)
715+ time_to_empty = 3600 * (energy_total / energy_rate_total);
716+ else if (state == UP_DEVICE_STATE_CHARGING)
717+ time_to_full = 3600 * ((energy_full_total - energy_total) / energy_rate_total);
718+ }
719+
720+ /* okay, we can use the composite device */
721+ device = engine->priv->battery_composite;
722+
723+ egg_debug ("printing composite device");
724+ g_object_set (device,
725+ "energy", energy,
726+ "energy-full", energy_full,
727+ "energy-rate", energy_rate,
728+ "time-to-empty", time_to_empty,
729+ "time-to-full", time_to_full,
730+ "percentage", percentage,
731+ "state", state,
732+ NULL);
733+ if (debug) {
734+ text = up_device_to_text (device);
735+ egg_debug ("composite:\n%s", text);
736+ g_free (text);
737+ }
738+
739+ /* force update of icon */
740+ gpm_engine_recalculate_state_icon (engine);
741+out:
742+ /* return composite device or original device */
743+ return device;
744+}
745+
746+/**
747+ * gpm_engine_device_add:
748+ **/
749+static void
750+gpm_engine_device_add (GpmEngine *engine, UpDevice *device)
751+{
752+ GpmEngineWarning warning;
753+ UpDeviceState state;
754+ UpDeviceKind kind;
755+ UpDevice *composite;
756+
757+ /* assign warning */
758+ warning = gpm_engine_get_warning (engine, device);
759+ g_object_set_data (G_OBJECT(device), "engine-warning-old", GUINT_TO_POINTER(warning));
760+
761+ /* check capacity */
762+ gpm_engine_device_check_capacity (engine, device);
763+
764+ /* get device properties */
765+ g_object_get (device,
766+ "kind", &kind,
767+ "state", &state,
768+ NULL);
769+
770+ /* add old state for transitions */
771+ egg_debug ("adding %s with state %s", up_device_get_object_path (device), up_device_state_to_string (state));
772+ g_object_set_data (G_OBJECT(device), "engine-state-old", GUINT_TO_POINTER(state));
773+
774+ if (kind == UP_DEVICE_KIND_BATTERY) {
775+ egg_debug ("updating because we added a device");
776+ composite = gpm_engine_update_composite_device (engine, device);
777+
778+ /* get the same values for the composite device */
779+ warning = gpm_engine_get_warning (engine, composite);
780+ g_object_set_data (G_OBJECT(composite), "engine-warning-old", GUINT_TO_POINTER(warning));
781+ g_object_get (composite, "state", &state, NULL);
782+ g_object_set_data (G_OBJECT(composite), "engine-state-old", GUINT_TO_POINTER(state));
783+ }
784+}
785+
786+/**
787+ * gpm_engine_check_recall:
788+ **/
789+static gboolean
790+gpm_engine_check_recall (GpmEngine *engine, UpDevice *device)
791+{
792+ UpDeviceKind kind;
793+ gboolean recall_notice = FALSE;
794+ gchar *recall_vendor = NULL;
795+ gchar *recall_url = NULL;
796+
797+ /* get device properties */
798+ g_object_get (device,
799+ "kind", &kind,
800+ "recall-notice", &recall_notice,
801+ "recall-vendor", &recall_vendor,
802+ "recall-url", &recall_url,
803+ NULL);
804+
805+ /* not battery */
806+ if (kind != UP_DEVICE_KIND_BATTERY)
807+ goto out;
808+
809+ /* no recall data */
810+ if (!recall_notice)
811+ goto out;
812+
813+ /* emit signal for manager */
814+ egg_debug ("** EMIT: perhaps-recall");
815+ g_signal_emit (engine, signals [PERHAPS_RECALL], 0, device, recall_vendor, recall_url);
816+out:
817+ g_free (recall_vendor);
818+ g_free (recall_url);
819+ return recall_notice;
820+}
821+
822+/**
823+ * gpm_engine_coldplug_idle_cb:
824+ **/
825+static gboolean
826+gpm_engine_coldplug_idle_cb (GpmEngine *engine)
827+{
828+ guint i;
829+ GPtrArray *array;
830+ gboolean has_battery = FALSE;
831+ gboolean has_ups = FALSE;
832+ GpmPrefsServer *prefs_server;
833+ UpDevice *device;
834+ UpDeviceKind kind;
835+ gboolean ret;
836+ GError *error = NULL;
837+
838+ g_return_val_if_fail (engine != NULL, FALSE);
839+ g_return_val_if_fail (GPM_IS_ENGINE (engine), FALSE);
840+
841+ /* get devices from UPower */
842+ ret = up_client_enumerate_devices_sync (engine->priv->client, NULL, &error);
843+ if (!ret) {
844+ egg_error ("failed to get device list: %s", error->message);
845+ g_error_free (error);
846+ goto out;
847+ }
848+ engine->priv->array = up_client_get_devices (engine->priv->client);
849+
850+ /* do we have specific device types? */
851+ array = engine->priv->array;
852+ for (i=0;i<array->len;i++) {
853+ device = g_ptr_array_index (engine->priv->array, i);
854+
855+ /* get device properties */
856+ g_object_get (device,
857+ "kind", &kind,
858+ NULL);
859+
860+ if (kind == UP_DEVICE_KIND_BATTERY)
861+ has_battery = TRUE;
862+ else if (kind == UP_DEVICE_KIND_UPS)
863+ has_ups = TRUE;
864+ }
865+
866+ /* only show the battery prefs section if we have batteries */
867+ prefs_server = gpm_prefs_server_new ();
868+ if (has_battery)
869+ gpm_prefs_server_set_capability (prefs_server, GPM_PREFS_SERVER_BATTERY);
870+ if (has_ups)
871+ gpm_prefs_server_set_capability (prefs_server, GPM_PREFS_SERVER_UPS);
872+ g_object_unref (prefs_server);
873+
874+ /* connected mobile phones */
875+ gpm_phone_coldplug (engine->priv->phone);
876+
877+ gpm_engine_recalculate_state (engine);
878+
879+ /* add to database */
880+ for (i=0;i<array->len;i++) {
881+ device = g_ptr_array_index (engine->priv->array, i);
882+ gpm_engine_device_add (engine, device);
883+ gpm_engine_check_recall (engine, device);
884+ }
885+out:
886+ /* never repeat */
887+ return FALSE;
888+}
889+
890+/**
891+ * gpm_engine_device_added_cb:
892+ **/
893+static void
894+gpm_engine_device_added_cb (UpClient *client, UpDevice *device, GpmEngine *engine)
895+{
896+ /* add to list */
897+ g_ptr_array_add (engine->priv->array, g_object_ref (device));
898+ gpm_engine_check_recall (engine, device);
899+
900+ gpm_engine_recalculate_state (engine);
901+}
902+
903+/**
904+ * gpm_engine_device_removed_cb:
905+ **/
906+static void
907+gpm_engine_device_removed_cb (UpClient *client, UpDevice *device, GpmEngine *engine)
908+{
909+ gboolean ret;
910+ ret = g_ptr_array_remove (engine->priv->array, device);
911+ if (!ret)
912+ return;
913+ gpm_engine_recalculate_state (engine);
914+}
915+
916+
917+/**
918+ * gpm_engine_device_changed_cb:
919+ **/
920+static void
921+gpm_engine_device_changed_cb (UpClient *client, UpDevice *device, GpmEngine *engine)
922+{
923+ UpDeviceKind kind;
924+ UpDeviceState state;
925+ UpDeviceState state_old;
926+ GpmEngineWarning warning_old;
927+ GpmEngineWarning warning;
928+
929+ /* get device properties */
930+ g_object_get (device,
931+ "kind", &kind,
932+ NULL);
933+
934+ /* if battery then use composite device to cope with multiple batteries */
935+ if (kind == UP_DEVICE_KIND_BATTERY) {
936+ egg_debug ("updating because %s changed", up_device_get_object_path (device));
937+ device = gpm_engine_update_composite_device (engine, device);
938+ }
939+
940+ /* get device properties (may be composite) */
941+ g_object_get (device,
942+ "state", &state,
943+ NULL);
944+
945+ egg_debug ("%s state is now %s", up_device_get_object_path (device), up_device_state_to_string (state));
946+
947+ /* see if any interesting state changes have happened */
948+ state_old = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(device), "engine-state-old"));
949+ if (state_old != state) {
950+ if (state == UP_DEVICE_STATE_DISCHARGING) {
951+ egg_debug ("** EMIT: discharging");
952+ g_signal_emit (engine, signals [DISCHARGING], 0, device);
953+ } else if (state == UP_DEVICE_STATE_FULLY_CHARGED) {
954+ egg_debug ("** EMIT: fully charged");
955+ g_signal_emit (engine, signals [FULLY_CHARGED], 0, device);
956+ }
957+
958+ /* save new state */
959+ g_object_set_data (G_OBJECT(device), "engine-state-old", GUINT_TO_POINTER(state));
960+ }
961+
962+ /* check the warning state has not changed */
963+ warning_old = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(device), "engine-warning-old"));
964+ warning = gpm_engine_get_warning (engine, device);
965+ if (warning != warning_old) {
966+ if (warning == GPM_ENGINE_WARNING_LOW) {
967+ egg_debug ("** EMIT: charge-low");
968+ g_signal_emit (engine, signals [CHARGE_LOW], 0, device);
969+ } else if (warning == GPM_ENGINE_WARNING_CRITICAL) {
970+ egg_debug ("** EMIT: charge-critical");
971+ g_signal_emit (engine, signals [CHARGE_CRITICAL], 0, device);
972+ } else if (warning == GPM_ENGINE_WARNING_ACTION) {
973+ egg_debug ("** EMIT: charge-action");
974+ g_signal_emit (engine, signals [CHARGE_ACTION], 0, device);
975+ }
976+ /* save new state */
977+ g_object_set_data (G_OBJECT(device), "engine-warning-old", GUINT_TO_POINTER(warning));
978+ }
979+
980+ gpm_engine_recalculate_state (engine);
981+}
982+
983+/**
984+ * gpm_engine_get_devices:
985+ *
986+ * Return value: the UpDevice array, free with g_ptr_array_unref()
987+ **/
988+GPtrArray *
989+gpm_engine_get_devices (GpmEngine *engine)
990+{
991+ return g_ptr_array_ref (engine->priv->array);
992+}
993+
994+/**
995+ * phone_device_added_cb:
996+ **/
997+static void
998+phone_device_added_cb (GpmPhone *phone, guint idx, GpmEngine *engine)
999+{
1000+ UpDevice *device;
1001+ device = up_device_new ();
1002+
1003+ egg_debug ("phone added %i", idx);
1004+
1005+ /* get device properties */
1006+ g_object_set (device,
1007+ "kind", UP_DEVICE_KIND_PHONE,
1008+ "is-rechargeable", TRUE,
1009+ "native-path", g_strdup_printf ("dummy:phone_%i", idx),
1010+ "is-present", TRUE,
1011+ NULL);
1012+
1013+ /* state changed */
1014+ gpm_engine_device_add (engine, device);
1015+ g_ptr_array_add (engine->priv->array, g_object_ref (device));
1016+ gpm_engine_recalculate_state (engine);
1017+}
1018+
1019+/**
1020+ * phone_device_removed_cb:
1021+ **/
1022+static void
1023+phone_device_removed_cb (GpmPhone *phone, guint idx, GpmEngine *engine)
1024+{
1025+ guint i;
1026+ UpDevice *device;
1027+ UpDeviceKind kind;
1028+
1029+ egg_debug ("phone removed %i", idx);
1030+
1031+ for (i=0; i<engine->priv->array->len; i++) {
1032+ device = g_ptr_array_index (engine->priv->array, i);
1033+
1034+ /* get device properties */
1035+ g_object_get (device,
1036+ "kind", &kind,
1037+ NULL);
1038+
1039+ if (kind == UP_DEVICE_KIND_PHONE) {
1040+ g_ptr_array_remove_index (engine->priv->array, i);
1041+ break;
1042+ }
1043+ }
1044+
1045+ /* state changed */
1046+ gpm_engine_recalculate_state (engine);
1047+}
1048+
1049+/**
1050+ * phone_device_refresh_cb:
1051+ **/
1052+static void
1053+phone_device_refresh_cb (GpmPhone *phone, guint idx, GpmEngine *engine)
1054+{
1055+ guint i;
1056+ UpDevice *device;
1057+ UpDeviceKind kind;
1058+ UpDeviceState state;
1059+ gboolean is_present;
1060+ gdouble percentage;
1061+
1062+ egg_debug ("phone refresh %i", idx);
1063+
1064+ for (i=0; i<engine->priv->array->len; i++) {
1065+ device = g_ptr_array_index (engine->priv->array, i);
1066+
1067+ /* get device properties */
1068+ g_object_get (device,
1069+ "kind", &kind,
1070+ "state", &state,
1071+ "percentage", &percentage,
1072+ "is-present", &is_present,
1073+ NULL);
1074+
1075+ if (kind == UP_DEVICE_KIND_PHONE) {
1076+ is_present = gpm_phone_get_present (phone, idx);
1077+ state = gpm_phone_get_on_ac (phone, idx) ? UP_DEVICE_STATE_CHARGING : UP_DEVICE_STATE_DISCHARGING;
1078+ percentage = gpm_phone_get_percentage (phone, idx);
1079+ break;
1080+ }
1081+ }
1082+
1083+ /* state changed */
1084+ gpm_engine_recalculate_state (engine);
1085+}
1086+
1087+/**
1088+ * gpm_engine_init:
1089+ * @engine: This class instance
1090+ **/
1091+static void
1092+gpm_engine_init (GpmEngine *engine)
1093+{
1094+ gchar *icon_policy;
1095+
1096+ engine->priv = GPM_ENGINE_GET_PRIVATE (engine);
1097+
1098+ engine->priv->array = g_ptr_array_new_with_free_func (g_object_unref);
1099+ engine->priv->client = up_client_new ();
1100+ g_signal_connect (engine->priv->client, "device-added",
1101+ G_CALLBACK (gpm_engine_device_added_cb), engine);
1102+ g_signal_connect (engine->priv->client, "device-removed",
1103+ G_CALLBACK (gpm_engine_device_removed_cb), engine);
1104+ g_signal_connect (engine->priv->client, "device-changed",
1105+ G_CALLBACK (gpm_engine_device_changed_cb), engine);
1106+
1107+ engine->priv->conf = gconf_client_get_default ();
1108+ gconf_client_notify_add (engine->priv->conf, GPM_CONF_DIR,
1109+ (GConfClientNotifyFunc) gpm_engine_conf_key_changed_cb,
1110+ engine, NULL, NULL);
1111+
1112+ engine->priv->phone = gpm_phone_new ();
1113+ g_signal_connect (engine->priv->phone, "device-added",
1114+ G_CALLBACK (phone_device_added_cb), engine);
1115+ g_signal_connect (engine->priv->phone, "device-removed",
1116+ G_CALLBACK (phone_device_removed_cb), engine);
1117+ g_signal_connect (engine->priv->phone, "device-refresh",
1118+ G_CALLBACK (phone_device_refresh_cb), engine);
1119+
1120+ /* create a fake virtual composite battery */
1121+ engine->priv->battery_composite = up_device_new ();
1122+ g_object_set (engine->priv->battery_composite,
1123+ "kind", UP_DEVICE_KIND_BATTERY,
1124+ "is-rechargeable", TRUE,
1125+ "native-path", "dummy:composite_battery",
1126+ "power-supply", TRUE,
1127+ "is-present", TRUE,
1128+ NULL);
1129+
1130+ engine->priv->previous_icon = NULL;
1131+ engine->priv->previous_summary = NULL;
1132+
1133+ /* do we want to display the icon in the tray */
1134+ icon_policy = gconf_client_get_string (engine->priv->conf, GPM_CONF_UI_ICON_POLICY, NULL);
1135+ engine->priv->icon_policy = gpm_icon_policy_from_string (icon_policy);
1136+ g_free (icon_policy);
1137+
1138+ /* get percentage policy */
1139+ engine->priv->low_percentage = gconf_client_get_int (engine->priv->conf, GPM_CONF_THRESH_PERCENTAGE_LOW, NULL);
1140+ engine->priv->critical_percentage = gconf_client_get_int (engine->priv->conf, GPM_CONF_THRESH_PERCENTAGE_CRITICAL, NULL);
1141+ engine->priv->action_percentage = gconf_client_get_int (engine->priv->conf, GPM_CONF_THRESH_PERCENTAGE_ACTION, NULL);
1142+
1143+ /* get time policy */
1144+ engine->priv->low_time = gconf_client_get_int (engine->priv->conf, GPM_CONF_THRESH_TIME_LOW, NULL);
1145+ engine->priv->critical_time = gconf_client_get_int (engine->priv->conf, GPM_CONF_THRESH_TIME_CRITICAL, NULL);
1146+ engine->priv->action_time = gconf_client_get_int (engine->priv->conf, GPM_CONF_THRESH_TIME_ACTION, NULL);
1147+
1148+ /* we can disable this if the time remaining is inaccurate or just plain wrong */
1149+ engine->priv->use_time_primary = gconf_client_get_bool (engine->priv->conf, GPM_CONF_USE_TIME_POLICY, NULL);
1150+ if (engine->priv->use_time_primary)
1151+ egg_debug ("Using per-time notification policy");
1152+ else
1153+ egg_debug ("Using percentage notification policy");
1154+
1155+ g_idle_add ((GSourceFunc) gpm_engine_coldplug_idle_cb, engine);
1156+}
1157+
1158+/**
1159+ * gpm_engine_class_init:
1160+ * @engine: This class instance
1161+ **/
1162+static void
1163+gpm_engine_class_init (GpmEngineClass *klass)
1164+{
1165+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
1166+ object_class->finalize = gpm_engine_finalize;
1167+ g_type_class_add_private (klass, sizeof (GpmEnginePrivate));
1168+
1169+ signals [ICON_CHANGED] =
1170+ g_signal_new ("icon-changed",
1171+ G_TYPE_FROM_CLASS (object_class),
1172+ G_SIGNAL_RUN_LAST,
1173+ G_STRUCT_OFFSET (GpmEngineClass, icon_changed),
1174+ NULL, NULL, g_cclosure_marshal_VOID__STRING,
1175+ G_TYPE_NONE, 1, G_TYPE_STRING);
1176+ signals [SUMMARY_CHANGED] =
1177+ g_signal_new ("summary-changed",
1178+ G_TYPE_FROM_CLASS (object_class),
1179+ G_SIGNAL_RUN_LAST,
1180+ G_STRUCT_OFFSET (GpmEngineClass, summary_changed),
1181+ NULL, NULL, g_cclosure_marshal_VOID__STRING,
1182+ G_TYPE_NONE, 1, G_TYPE_STRING);
1183+ signals [LOW_CAPACITY] =
1184+ g_signal_new ("low-capacity",
1185+ G_TYPE_FROM_CLASS (object_class),
1186+ G_SIGNAL_RUN_LAST,
1187+ G_STRUCT_OFFSET (GpmEngineClass, low_capacity),
1188+ NULL, NULL, g_cclosure_marshal_VOID__POINTER,
1189+ G_TYPE_NONE, 1, G_TYPE_POINTER);
1190+ signals [PERHAPS_RECALL] =
1191+ g_signal_new ("perhaps-recall",
1192+ G_TYPE_FROM_CLASS (object_class),
1193+ G_SIGNAL_RUN_LAST,
1194+ G_STRUCT_OFFSET (GpmEngineClass, perhaps_recall),
1195+ NULL, NULL, gpm_marshal_VOID__POINTER_STRING_STRING,
1196+ G_TYPE_NONE,
1197+ 3, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
1198+ signals [FULLY_CHARGED] =
1199+ g_signal_new ("fully-charged",
1200+ G_TYPE_FROM_CLASS (object_class),
1201+ G_SIGNAL_RUN_LAST,
1202+ G_STRUCT_OFFSET (GpmEngineClass, fully_charged),
1203+ NULL, NULL, g_cclosure_marshal_VOID__POINTER,
1204+ G_TYPE_NONE, 1, G_TYPE_POINTER);
1205+ signals [DISCHARGING] =
1206+ g_signal_new ("discharging",
1207+ G_TYPE_FROM_CLASS (object_class),
1208+ G_SIGNAL_RUN_LAST,
1209+ G_STRUCT_OFFSET (GpmEngineClass, discharging),
1210+ NULL, NULL, g_cclosure_marshal_VOID__POINTER,
1211+ G_TYPE_NONE, 1, G_TYPE_POINTER);
1212+ signals [CHARGE_ACTION] =
1213+ g_signal_new ("charge-action",
1214+ G_TYPE_FROM_CLASS (object_class),
1215+ G_SIGNAL_RUN_LAST,
1216+ G_STRUCT_OFFSET (GpmEngineClass, charge_action),
1217+ NULL, NULL, g_cclosure_marshal_VOID__POINTER,
1218+ G_TYPE_NONE, 1, G_TYPE_POINTER);
1219+ signals [CHARGE_LOW] =
1220+ g_signal_new ("charge-low",
1221+ G_TYPE_FROM_CLASS (object_class),
1222+ G_SIGNAL_RUN_LAST,
1223+ G_STRUCT_OFFSET (GpmEngineClass, charge_low),
1224+ NULL, NULL, g_cclosure_marshal_VOID__POINTER,
1225+ G_TYPE_NONE, 1, G_TYPE_POINTER);
1226+ signals [CHARGE_CRITICAL] =
1227+ g_signal_new ("charge-critical",
1228+ G_TYPE_FROM_CLASS (object_class),
1229+ G_SIGNAL_RUN_LAST,
1230+ G_STRUCT_OFFSET (GpmEngineClass, charge_critical),
1231+ NULL, NULL, g_cclosure_marshal_VOID__POINTER,
1232+ G_TYPE_NONE, 1, G_TYPE_POINTER);
1233+ signals [DEVICES_CHANGED] =
1234+ g_signal_new ("devices-changed",
1235+ G_TYPE_FROM_CLASS (object_class),
1236+ G_SIGNAL_RUN_LAST,
1237+ G_STRUCT_OFFSET (GpmEngineClass, devices_changed),
1238+ NULL, NULL, g_cclosure_marshal_VOID__VOID,
1239+ G_TYPE_NONE, 0);
1240+}
1241+
1242+/**
1243+ * gpm_engine_finalize:
1244+ * @object: This class instance
1245+ **/
1246+static void
1247+gpm_engine_finalize (GObject *object)
1248+{
1249+ GpmEngine *engine;
1250+
1251+ g_return_if_fail (object != NULL);
1252+ g_return_if_fail (GPM_IS_ENGINE (object));
1253+
1254+ engine = GPM_ENGINE (object);
1255+ engine->priv = GPM_ENGINE_GET_PRIVATE (engine);
1256+
1257+ g_ptr_array_unref (engine->priv->array);
1258+ g_object_unref (engine->priv->client);
1259+ g_object_unref (engine->priv->phone);
1260+ g_object_unref (engine->priv->battery_composite);
1261+
1262+ g_free (engine->priv->previous_icon);
1263+ g_free (engine->priv->previous_summary);
1264+
1265+ G_OBJECT_CLASS (gpm_engine_parent_class)->finalize (object);
1266+}
1267+
1268+/**
1269+ * gpm_engine_new:
1270+ * Return value: new class instance.
1271+ **/
1272+GpmEngine *
1273+gpm_engine_new (void)
1274+{
1275+ if (gpm_engine_object != NULL) {
1276+ g_object_ref (gpm_engine_object);
1277+ } else {
1278+ gpm_engine_object = g_object_new (GPM_TYPE_ENGINE, NULL);
1279+ g_object_add_weak_pointer (gpm_engine_object, &gpm_engine_object);
1280+ }
1281+ return GPM_ENGINE (gpm_engine_object);
1282+
1283+}
1284+
1285
1286=== modified file '.pc/applied-patches'
1287--- .pc/applied-patches 2011-03-15 01:04:40 +0000
1288+++ .pc/applied-patches 2011-07-10 20:29:23 +0000
1289@@ -6,3 +6,4 @@
1290 14_fix_no_xbacklight_crash.patch
1291 14-critical-message-timeout.patch
1292 15-keyboard-backlight-support.patch
1293+16-fix-duplicate-battery.patch
1294
1295=== modified file 'debian/changelog'
1296--- debian/changelog 2011-03-15 01:04:40 +0000
1297+++ debian/changelog 2011-07-10 20:29:23 +0000
1298@@ -1,3 +1,11 @@
1299+gnome-power-manager (2.32.0-2ubuntu3) natty; urgency=low
1300+
1301+ * 16-fix-duplicate-battery.patch: Don't add hot-added battery to device
1302+ list, because libupower-glib already does that (LP: #675108)
1303+ [ Maxim Levitsky <maximlevitsky@gmail.com> ]
1304+
1305+ -- Phillip Susi <psusi@ubuntu.com> Mon, 13 Jun 2011 14:04:01 -0400
1306+
1307 gnome-power-manager (2.32.0-2ubuntu2) natty; urgency=low
1308
1309 [ Alex Murray <murray.alex@gmail.com> ]
1310
1311=== added file 'debian/patches/16-fix-duplicate-battery.patch'
1312--- debian/patches/16-fix-duplicate-battery.patch 1970-01-01 00:00:00 +0000
1313+++ debian/patches/16-fix-duplicate-battery.patch 2011-07-10 20:29:23 +0000
1314@@ -0,0 +1,20 @@
1315+Description: Don't add hot-added battery to device list, because libupower-glib
1316+ already does that (LP: #616443)
1317+Author: Maxim Levitsky <maximlevitsky@gmail.com>
1318+Bug-Ubuntu: https://launchpad.net/bugs/616443
1319+Forwarded: no
1320+Last-Update: <2011-06-13>
1321+
1322+--- gnome-power-manager-2.32.0.orig/src/gpm-engine.c
1323++++ gnome-power-manager-2.32.0/src/gpm-engine.c
1324+@@ -886,10 +886,7 @@ out:
1325+ static void
1326+ gpm_engine_device_added_cb (UpClient *client, UpDevice *device, GpmEngine *engine)
1327+ {
1328+- /* add to list */
1329+- g_ptr_array_add (engine->priv->array, g_object_ref (device));
1330+ gpm_engine_check_recall (engine, device);
1331+-
1332+ gpm_engine_recalculate_state (engine);
1333+ }
1334+
1335
1336=== modified file 'debian/patches/series'
1337--- debian/patches/series 2011-03-15 01:04:40 +0000
1338+++ debian/patches/series 2011-07-10 20:29:23 +0000
1339@@ -6,3 +6,5 @@
1340 14_fix_no_xbacklight_crash.patch
1341 14-critical-message-timeout.patch
1342 15-keyboard-backlight-support.patch
1343+16-fix-duplicate-battery.patch
1344+
1345
1346=== modified file 'src/gpm-engine.c'
1347--- src/gpm-engine.c 2011-01-26 17:20:06 +0000
1348+++ src/gpm-engine.c 2011-07-10 20:29:23 +0000
1349@@ -886,10 +886,7 @@
1350 static void
1351 gpm_engine_device_added_cb (UpClient *client, UpDevice *device, GpmEngine *engine)
1352 {
1353- /* add to list */
1354- g_ptr_array_add (engine->priv->array, g_object_ref (device));
1355 gpm_engine_check_recall (engine, device);
1356-
1357 gpm_engine_recalculate_state (engine);
1358 }
1359

Subscribers

People subscribed via source and target branches

to all changes: