[gnome-settings-daemon] power: Add the engine functionality so that batteries are monitored
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon] power: Add the engine functionality so that batteries are monitored
- Date: Mon, 4 Jul 2011 16:55:37 +0000 (UTC)
commit 9147c8df3eed321f2f3cf29f6c077d70c5c4b323
Author: Richard Hughes <richard hughsie com>
Date: Fri Jul 1 12:32:37 2011 +0100
power: Add the engine functionality so that batteries are monitored
This also creates the composite device if required.
...settings-daemon.plugins.power.gschema.xml.in.in | 35 +
plugins/power/gsd-power-manager.c | 949 +++++++++++++++++++-
2 files changed, 974 insertions(+), 10 deletions(-)
---
diff --git a/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in.in b/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in.in
index ba1dca7..52c1b0c 100644
--- a/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in.in
+++ b/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in.in
@@ -106,5 +106,40 @@
<summary>Battery critical low action</summary>
<description>The action to take when the battery is critically low.</description>
</key>
+ <key name="percentage-low" type="i">
+ <default>10</default>
+ <_summary>Percentage considered low</_summary>
+ <_description>The percentage of the battery when it is considered low. Only valid when use-time-for-policy is false.</_description>
+ </key>
+ <key name="percentage-critical" type="i">
+ <default>3</default>
+ <_summary>Percentage considered critical</_summary>
+ <_description>The percentage of the battery when it is considered critical. Only valid when use-time-for-policy is false.</_description>
+ </key>
+ <key name="percentage-action" type="i">
+ <default>2</default>
+ <_summary>Percentage action is taken</_summary>
+ <_description>The percentage of the battery when the critical action is performed. Only valid when use-time-for-policy is false.</_description>
+ </key>
+ <key name="time-low" type="i">
+ <default>1200</default>
+ <_summary>The time remaining when low</_summary>
+ <_description>The time remaining in seconds of the battery when it is considered low. Only valid when use-time-for-policy is true.</_description>
+ </key>
+ <key name="time-critical" type="i">
+ <default>300</default>
+ <_summary>The time remaining when critical</_summary>
+ <_description>The time remaining in seconds of the battery when it is considered critical. Only valid when use-time-for-policy is true.</_description>
+ </key>
+ <key name="time-action" type="i">
+ <default>120</default>
+ <_summary>The time remaining when action is taken</_summary>
+ <_description>The time remaining in seconds of the battery when critical action is taken. Only valid when use-time-for-policy is true.</_description>
+ </key>
+ <key name="use-time-for-policy" type="b">
+ <default>true</default>
+ <_summary>Whether to use time-based notifications</_summary>
+ <_description>If time based notifications should be used. If set to false, then the percentage change is used instead, which may fix a broken ACPI BIOS.</_description>
+ </key>
</schema>
</schemalist>
diff --git a/plugins/power/gsd-power-manager.c b/plugins/power/gsd-power-manager.c
index 90af0da..4cd5adc 100644
--- a/plugins/power/gsd-power-manager.c
+++ b/plugins/power/gsd-power-manager.c
@@ -22,6 +22,7 @@
#include "config.h"
#include <stdlib.h>
+#include <string.h>
#include <stdio.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
@@ -32,6 +33,7 @@
#include <libgnome-desktop/gnome-rr.h>
#include "gpm-common.h"
+#include "gpm-phone.h"
#include "gnome-settings-profile.h"
#include "gsd-enums.h"
#include "gsd-power-manager.h"
@@ -50,6 +52,7 @@
#define GSD_POWER_SETTINGS_SCHEMA "org.gnome.settings-daemon.plugins.power"
+#define GSD_DBUS_SERVICE "org.gnome.SettingsDaemon"
#define GSD_DBUS_PATH "/org/gnome/SettingsDaemon"
#define GSD_POWER_DBUS_PATH GSD_DBUS_PATH "/Power"
#define GSD_POWER_DBUS_INTERFACE "org.gnome.SettingsDaemon.Power"
@@ -121,6 +124,18 @@ struct GsdPowerManagerPrivate
gint kbd_brightness_max;
gint kbd_brightness_old;
GnomeRRScreen *x11_screen;
+ gboolean use_time_primary;
+ gchar *previous_summary;
+ GIcon *previous_icon;
+ GpmPhone *phone;
+ GPtrArray *devices_array;
+ guint action_percentage;
+ guint action_time;
+ guint critical_percentage;
+ guint critical_time;
+ guint low_percentage;
+ guint low_time;
+ UpDevice *device_composite;
};
enum {
@@ -131,6 +146,9 @@ static void gsd_power_manager_class_init (GsdPowerManagerClass *klass);
static void gsd_power_manager_init (GsdPowerManager *power_manager);
static void gsd_power_manager_finalize (GObject *object);
+static UpDevice *engine_get_composite_device (GsdPowerManager *manager, UpDevice *original_device);
+static UpDevice *engine_update_composite_device (GsdPowerManager *manager, UpDevice *original_device);
+
G_DEFINE_TYPE (GsdPowerManager, gsd_power_manager, G_TYPE_OBJECT)
static gpointer manager_object = NULL;
@@ -144,6 +162,848 @@ gsd_power_manager_error_quark (void)
return quark;
}
+typedef enum {
+ WARNING_NONE = 0,
+ WARNING_DISCHARGING = 1,
+ WARNING_LOW = 2,
+ WARNING_CRITICAL = 3,
+ WARNING_ACTION = 4
+} GsdPowerManagerWarning;
+
+static void
+engine_emit_changed (GsdPowerManager *manager)
+{
+ gboolean ret;
+ GError *error = NULL;
+
+ /* not yet connected to the bus */
+ if (manager->priv->connection == NULL)
+ return;
+ ret = g_dbus_connection_emit_signal (manager->priv->connection,
+ GSD_DBUS_SERVICE,
+ GSD_POWER_DBUS_PATH,
+ GSD_POWER_DBUS_INTERFACE,
+ "Changed",
+ NULL,
+ &error);
+ if (!ret) {
+ g_warning ("failed to emit Changed: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static GsdPowerManagerWarning
+engine_get_warning_csr (GsdPowerManager *manager, UpDevice *device)
+{
+ gdouble percentage;
+
+ /* get device properties */
+ g_object_get (device, "percentage", &percentage, NULL);
+
+ if (percentage < 26.0f)
+ return WARNING_LOW;
+ else if (percentage < 13.0f)
+ return WARNING_CRITICAL;
+ return WARNING_NONE;
+}
+
+static GsdPowerManagerWarning
+engine_get_warning_percentage (GsdPowerManager *manager, UpDevice *device)
+{
+ gdouble percentage;
+
+ /* get device properties */
+ g_object_get (device, "percentage", &percentage, NULL);
+
+ if (percentage <= manager->priv->action_percentage)
+ return WARNING_ACTION;
+ if (percentage <= manager->priv->critical_percentage)
+ return WARNING_CRITICAL;
+ if (percentage <= manager->priv->low_percentage)
+ return WARNING_LOW;
+ return WARNING_NONE;
+}
+
+static GsdPowerManagerWarning
+engine_get_warning_time (GsdPowerManager *manager, UpDevice *device)
+{
+ UpDeviceKind kind;
+ gint64 time_to_empty;
+
+ /* get device properties */
+ g_object_get (device,
+ "kind", &kind,
+ "time-to-empty", &time_to_empty,
+ NULL);
+
+ /* this is probably an error condition */
+ if (time_to_empty == 0) {
+ g_debug ("time zero, falling back to percentage for %s",
+ up_device_kind_to_string (kind));
+ return engine_get_warning_percentage (manager, device);
+ }
+
+ if (time_to_empty <= manager->priv->action_time)
+ return WARNING_ACTION;
+ if (time_to_empty <= manager->priv->critical_time)
+ return WARNING_CRITICAL;
+ if (time_to_empty <= manager->priv->low_time)
+ return WARNING_LOW;
+ return WARNING_NONE;
+}
+
+/**
+ * This gets the possible engine state for the device according to the
+ * policy, which could be per-percent, or per-time.
+ **/
+static GsdPowerManagerWarning
+engine_get_warning (GsdPowerManager *manager, UpDevice *device)
+{
+ UpDeviceKind kind;
+ UpDeviceState state;
+ GsdPowerManagerWarning warning_type;
+
+ /* get device properties */
+ g_object_get (device,
+ "kind", &kind,
+ "state", &state,
+ NULL);
+
+ /* default to no engine */
+ warning_type = WARNING_NONE;
+
+ /* if the device in question is on ac, don't give a warning */
+ if (state == UP_DEVICE_STATE_CHARGING)
+ goto out;
+
+ if (kind == UP_DEVICE_KIND_MOUSE ||
+ kind == UP_DEVICE_KIND_KEYBOARD) {
+
+ warning_type = engine_get_warning_csr (manager, device);
+
+ } else if (kind == UP_DEVICE_KIND_UPS ||
+#if UP_CHECK_VERSION(0,9,5)
+ kind == UP_DEVICE_KIND_MEDIA_PLAYER ||
+ kind == UP_DEVICE_KIND_TABLET ||
+ kind == UP_DEVICE_KIND_COMPUTER ||
+#endif
+ kind == UP_DEVICE_KIND_PDA) {
+
+ warning_type = engine_get_warning_percentage (manager, device);
+
+ } else if (kind == UP_DEVICE_KIND_PHONE) {
+
+ warning_type = engine_get_warning_percentage (manager, device);
+
+ } else if (kind == UP_DEVICE_KIND_BATTERY) {
+ /* only use the time when it is accurate, and settings is not disabled */
+ if (manager->priv->use_time_primary)
+ warning_type = engine_get_warning_time (manager, device);
+ else
+ warning_type = engine_get_warning_percentage (manager, device);
+ }
+
+ /* If we have no important engines, we should test for discharging */
+ if (warning_type == WARNING_NONE) {
+ if (state == UP_DEVICE_STATE_DISCHARGING)
+ warning_type = WARNING_DISCHARGING;
+ }
+
+ out:
+ return warning_type;
+}
+
+static gchar *
+engine_get_summary (GsdPowerManager *manager)
+{
+ guint i;
+ GPtrArray *array;
+ UpDevice *device;
+ UpDeviceState state;
+ GString *tooltip = NULL;
+ gchar *part;
+ gboolean is_present;
+
+
+ /* need to get AC state */
+ tooltip = g_string_new ("");
+
+ /* do we have specific device types? */
+ array = manager->priv->devices_array;
+ for (i=0;i<array->len;i++) {
+ device = g_ptr_array_index (array, i);
+ g_object_get (device,
+ "is-present", &is_present,
+ "state", &state,
+ NULL);
+ if (!is_present)
+ continue;
+ if (state == UP_DEVICE_STATE_EMPTY)
+ continue;
+ part = gpm_upower_get_device_summary (device);
+ if (part != NULL)
+ g_string_append_printf (tooltip, "%s\n", part);
+ g_free (part);
+ }
+
+ /* remove the last \n */
+ g_string_truncate (tooltip, tooltip->len-1);
+
+ g_debug ("tooltip: %s", tooltip->str);
+
+ return g_string_free (tooltip, FALSE);
+}
+
+static GIcon *
+engine_get_icon_priv (GsdPowerManager *manager,
+ UpDeviceKind device_kind,
+ GsdPowerManagerWarning warning,
+ gboolean use_state)
+{
+ guint i;
+ GPtrArray *array;
+ UpDevice *device;
+ GsdPowerManagerWarning warning_temp;
+ UpDeviceKind kind;
+ UpDeviceState state;
+ gboolean is_present;
+
+ /* do we have specific device types? */
+ array = manager->priv->devices_array;
+ for (i=0;i<array->len;i++) {
+ device = g_ptr_array_index (array, i);
+
+ /* get device properties */
+ g_object_get (device,
+ "kind", &kind,
+ "state", &state,
+ "is-present", &is_present,
+ NULL);
+
+ /* if battery then use composite device to cope with multiple batteries */
+ if (kind == UP_DEVICE_KIND_BATTERY)
+ device = engine_get_composite_device (manager, device);
+
+ warning_temp = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(device),
+ "engine-warning-old"));
+ if (kind == device_kind && is_present) {
+ if (warning != WARNING_NONE) {
+ if (warning_temp == warning)
+ return gpm_upower_get_device_icon (device, TRUE);
+ continue;
+ }
+ if (use_state) {
+ if (state == UP_DEVICE_STATE_CHARGING ||
+ state == UP_DEVICE_STATE_DISCHARGING)
+ return gpm_upower_get_device_icon (device, TRUE);
+ continue;
+ }
+ return gpm_upower_get_device_icon (device, TRUE);
+ }
+ }
+ return NULL;
+}
+
+static GIcon *
+engine_get_icon (GsdPowerManager *manager)
+{
+ GIcon *icon = NULL;
+
+
+ /* we try CRITICAL: BATTERY, UPS, MOUSE, KEYBOARD */
+ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_BATTERY, WARNING_CRITICAL, FALSE);
+ if (icon != NULL)
+ return icon;
+ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_UPS, WARNING_CRITICAL, FALSE);
+ if (icon != NULL)
+ return icon;
+ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_MOUSE, WARNING_CRITICAL, FALSE);
+ if (icon != NULL)
+ return icon;
+ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_KEYBOARD, WARNING_CRITICAL, FALSE);
+ if (icon != NULL)
+ return icon;
+
+ /* we try CRITICAL: BATTERY, UPS, MOUSE, KEYBOARD */
+ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_BATTERY, WARNING_LOW, FALSE);
+ if (icon != NULL)
+ return icon;
+ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_UPS, WARNING_LOW, FALSE);
+ if (icon != NULL)
+ return icon;
+ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_MOUSE, WARNING_LOW, FALSE);
+ if (icon != NULL)
+ return icon;
+ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_KEYBOARD, WARNING_LOW, FALSE);
+ if (icon != NULL)
+ return icon;
+
+ /* we try (DIS)CHARGING: BATTERY, UPS */
+ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_BATTERY, WARNING_NONE, TRUE);
+ if (icon != NULL)
+ return icon;
+ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_UPS, WARNING_NONE, TRUE);
+ if (icon != NULL)
+ return icon;
+
+ /* we try PRESENT: BATTERY, UPS */
+ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_BATTERY, WARNING_NONE, FALSE);
+ if (icon != NULL)
+ return icon;
+ icon = engine_get_icon_priv (manager, UP_DEVICE_KIND_UPS, WARNING_NONE, FALSE);
+ if (icon != NULL)
+ return icon;
+
+ /* do not show an icon */
+ return NULL;
+}
+
+static gboolean
+engine_recalculate_state_icon (GsdPowerManager *manager)
+{
+ GIcon *icon;
+
+ /* show a different icon if we are disconnected */
+ icon = engine_get_icon (manager);
+ if (icon == NULL) {
+ /* none before, now none */
+ if (manager->priv->previous_icon == NULL)
+ return FALSE;
+
+ g_object_unref (manager->priv->previous_icon);
+ manager->priv->previous_icon = NULL;
+
+ /* icon before, now none */
+ engine_emit_changed (manager);
+
+ return TRUE;
+ }
+
+ /* no icon before, now icon */
+ if (manager->priv->previous_icon == NULL) {
+ engine_emit_changed (manager);
+ manager->priv->previous_icon = g_object_ref (icon);
+ return TRUE;
+ }
+
+ /* icon before, now different */
+ if (!g_icon_equal (manager->priv->previous_icon, icon)) {
+ g_object_unref (manager->priv->previous_icon);
+ manager->priv->previous_icon = g_object_ref (icon);
+ engine_emit_changed (manager);
+ return TRUE;
+ }
+
+ g_debug ("no change");
+ /* nothing to do */
+ g_object_unref (icon);
+ return FALSE;
+}
+
+static gboolean
+engine_recalculate_state_summary (GsdPowerManager *manager)
+{
+ gchar *summary;
+
+ summary = engine_get_summary (manager);
+ if (manager->priv->previous_summary == NULL) {
+ manager->priv->previous_summary = summary;
+ engine_emit_changed (manager);
+ return TRUE;
+ }
+
+ if (strcmp (manager->priv->previous_summary, summary) != 0) {
+ g_free (manager->priv->previous_summary);
+ manager->priv->previous_summary = summary;
+ engine_emit_changed (manager);
+ return TRUE;
+ }
+ g_debug ("no change");
+ /* nothing to do */
+ g_free (summary);
+ return FALSE;
+}
+
+static void
+engine_recalculate_state (GsdPowerManager *manager)
+{
+ engine_recalculate_state_icon (manager);
+ engine_recalculate_state_summary (manager);
+
+ engine_emit_changed (manager);
+}
+
+static void
+engine_settings_key_changed_cb (GSettings *settings,
+ const gchar *key,
+ GsdPowerManager *manager)
+{
+ if (g_strcmp0 (key, "use-time-for-policy") == 0) {
+ manager->priv->use_time_primary = g_settings_get_boolean (settings, key);
+ }
+}
+
+static UpDevice *
+engine_get_composite_device (GsdPowerManager *manager,
+ UpDevice *original_device)
+{
+ guint battery_devices = 0;
+ GPtrArray *array;
+ UpDevice *device;
+ UpDeviceKind kind;
+ UpDeviceKind original_kind;
+ guint i;
+
+ /* get the type of the original device */
+ g_object_get (original_device,
+ "kind", &original_kind,
+ NULL);
+
+ /* find out how many batteries in the system */
+ array = manager->priv->devices_array;
+ for (i=0;i<array->len;i++) {
+ device = g_ptr_array_index (array, i);
+ g_object_get (device,
+ "kind", &kind,
+ NULL);
+ if (kind == original_kind)
+ battery_devices++;
+ }
+
+ /* just use the original device if only one primary battery */
+ if (battery_devices <= 1) {
+ g_debug ("using original device as only one primary battery");
+ device = original_device;
+ goto out;
+ }
+
+ /* use the composite device */
+ device = manager->priv->device_composite;
+out:
+ /* return composite device or original device */
+ return device;
+}
+
+static UpDevice *
+engine_update_composite_device (GsdPowerManager *manager,
+ UpDevice *original_device)
+{
+ guint i;
+ gdouble percentage = 0.0;
+ gdouble energy = 0.0;
+ gdouble energy_full = 0.0;
+ gdouble energy_rate = 0.0;
+ gdouble energy_total = 0.0;
+ gdouble energy_full_total = 0.0;
+ gdouble energy_rate_total = 0.0;
+ gint64 time_to_empty = 0;
+ gint64 time_to_full = 0;
+ guint battery_devices = 0;
+ gboolean is_charging = FALSE;
+ gboolean is_discharging = FALSE;
+ gboolean is_fully_charged = TRUE;
+ GPtrArray *array;
+ UpDevice *device;
+ UpDeviceState state;
+ UpDeviceKind kind;
+ UpDeviceKind original_kind;
+
+ /* get the type of the original device */
+ g_object_get (original_device,
+ "kind", &original_kind,
+ NULL);
+
+ /* update the composite device */
+ array = manager->priv->devices_array;
+ for (i=0;i<array->len;i++) {
+ device = g_ptr_array_index (array, i);
+ g_object_get (device,
+ "kind", &kind,
+ "state", &state,
+ "energy", &energy,
+ "energy-full", &energy_full,
+ "energy-rate", &energy_rate,
+ NULL);
+ if (kind != original_kind)
+ continue;
+
+ /* one of these will be charging or discharging */
+ if (state == UP_DEVICE_STATE_CHARGING)
+ is_charging = TRUE;
+ if (state == UP_DEVICE_STATE_DISCHARGING)
+ is_discharging = TRUE;
+ if (state != UP_DEVICE_STATE_FULLY_CHARGED)
+ is_fully_charged = FALSE;
+
+ /* sum up composite */
+ energy_total += energy;
+ energy_full_total += energy_full;
+ energy_rate_total += energy_rate;
+ battery_devices++;
+ }
+
+ /* just use the original device if only one primary battery */
+ if (battery_devices == 1) {
+ g_debug ("using original device as only one primary battery");
+ device = original_device;
+ goto out;
+ }
+
+ /* use percentage weighted for each battery capacity */
+ percentage = 100.0 * energy_total / energy_full_total;
+
+ /* set composite state */
+ if (is_charging)
+ state = UP_DEVICE_STATE_CHARGING;
+ else if (is_discharging)
+ state = UP_DEVICE_STATE_DISCHARGING;
+ else if (is_fully_charged)
+ state = UP_DEVICE_STATE_FULLY_CHARGED;
+ else
+ state = UP_DEVICE_STATE_UNKNOWN;
+
+ /* calculate a quick and dirty time remaining value */
+ if (energy_rate_total > 0) {
+ if (state == UP_DEVICE_STATE_DISCHARGING)
+ time_to_empty = 3600 * (energy_total / energy_rate_total);
+ else if (state == UP_DEVICE_STATE_CHARGING)
+ time_to_full = 3600 * ((energy_full_total - energy_total) / energy_rate_total);
+ }
+
+ /* okay, we can use the composite device */
+ device = manager->priv->device_composite;
+
+ g_debug ("printing composite device");
+ g_object_set (device,
+ "energy", energy,
+ "energy-full", energy_full,
+ "energy-rate", energy_rate,
+ "time-to-empty", time_to_empty,
+ "time-to-full", time_to_full,
+ "percentage", percentage,
+ "state", state,
+ NULL);
+
+ /* force update of icon */
+ engine_recalculate_state_icon (manager);
+out:
+ /* return composite device or original device */
+ return device;
+}
+
+static void
+engine_device_add (GsdPowerManager *manager, UpDevice *device)
+{
+ GsdPowerManagerWarning warning;
+ UpDeviceState state;
+ UpDeviceKind kind;
+ UpDevice *composite;
+
+ /* assign warning */
+ warning = engine_get_warning (manager, device);
+ g_object_set_data (G_OBJECT(device),
+ "engine-warning-old",
+ GUINT_TO_POINTER(warning));
+
+ /* get device properties */
+ g_object_get (device,
+ "kind", &kind,
+ "state", &state,
+ NULL);
+
+ /* add old state for transitions */
+ g_debug ("adding %s with state %s",
+ up_device_get_object_path (device), up_device_state_to_string (state));
+ g_object_set_data (G_OBJECT(device),
+ "engine-state-old",
+ GUINT_TO_POINTER(state));
+
+ if (kind == UP_DEVICE_KIND_BATTERY) {
+ g_debug ("updating because we added a device");
+ composite = engine_update_composite_device (manager, device);
+
+ /* get the same values for the composite device */
+ warning = engine_get_warning (manager, composite);
+ g_object_set_data (G_OBJECT(composite),
+ "engine-warning-old",
+ GUINT_TO_POINTER(warning));
+ g_object_get (composite, "state", &state, NULL);
+ g_object_set_data (G_OBJECT(composite),
+ "engine-state-old",
+ GUINT_TO_POINTER(state));
+ }
+}
+
+static gboolean
+engine_check_recall (GsdPowerManager *manager, UpDevice *device)
+{
+ UpDeviceKind kind;
+ gboolean recall_notice = FALSE;
+ gchar *recall_vendor = NULL;
+ gchar *recall_url = NULL;
+
+ /* get device properties */
+ g_object_get (device,
+ "kind", &kind,
+ "recall-notice", &recall_notice,
+ "recall-vendor", &recall_vendor,
+ "recall-url", &recall_url,
+ NULL);
+
+ /* not battery */
+ if (kind != UP_DEVICE_KIND_BATTERY)
+ goto out;
+
+ /* no recall data */
+ if (!recall_notice)
+ goto out;
+
+ /* emit signal for manager */
+ g_debug ("** EMIT: perhaps-recall");
+ g_debug ("%s-%s", recall_vendor, recall_url);
+out:
+ g_free (recall_vendor);
+ g_free (recall_url);
+ return recall_notice;
+}
+
+static gboolean
+engine_coldplug (GsdPowerManager *manager)
+{
+ guint i;
+ GPtrArray *array = NULL;
+ UpDevice *device;
+ gboolean ret;
+ GError *error = NULL;
+
+ /* get devices from UPower */
+ ret = up_client_enumerate_devices_sync (manager->priv->up_client, NULL, &error);
+ if (!ret) {
+ g_error ("failed to get device list: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* connected mobile phones */
+ gpm_phone_coldplug (manager->priv->phone);
+
+ engine_recalculate_state (manager);
+
+ /* add to database */
+ array = up_client_get_devices (manager->priv->up_client);
+ for (i=0;i<array->len;i++) {
+ device = g_ptr_array_index (array, i);
+ engine_device_add (manager, device);
+ engine_check_recall (manager, device);
+ }
+out:
+ if (array != NULL)
+ g_ptr_array_unref (array);
+ /* never repeat */
+ return FALSE;
+}
+
+static void
+engine_device_added_cb (UpClient *client, UpDevice *device, GsdPowerManager *manager)
+{
+ /* add to list */
+ g_ptr_array_add (manager->priv->devices_array, g_object_ref (device));
+ engine_check_recall (manager, device);
+
+ engine_recalculate_state (manager);
+}
+
+static void
+engine_device_removed_cb (UpClient *client, UpDevice *device, GsdPowerManager *manager)
+{
+ gboolean ret;
+ ret = g_ptr_array_remove (manager->priv->devices_array, device);
+ if (!ret)
+ return;
+ engine_recalculate_state (manager);
+}
+
+static void
+engine_device_changed_cb (UpClient *client, UpDevice *device, GsdPowerManager *manager)
+{
+ UpDeviceKind kind;
+ UpDeviceState state;
+ UpDeviceState state_old;
+ GsdPowerManagerWarning warning_old;
+ GsdPowerManagerWarning warning;
+
+ /* get device properties */
+ g_object_get (device,
+ "kind", &kind,
+ NULL);
+
+ /* if battery then use composite device to cope with multiple batteries */
+ if (kind == UP_DEVICE_KIND_BATTERY) {
+ g_debug ("updating because %s changed", up_device_get_object_path (device));
+ device = engine_update_composite_device (manager, device);
+ }
+
+ /* get device properties (may be composite) */
+ g_object_get (device,
+ "state", &state,
+ NULL);
+
+ g_debug ("%s state is now %s", up_device_get_object_path (device), up_device_state_to_string (state));
+
+ /* see if any interesting state changes have happened */
+ state_old = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(device), "engine-state-old"));
+ if (state_old != state) {
+ if (state == UP_DEVICE_STATE_DISCHARGING) {
+ g_debug ("** EMIT: discharging");
+ } else if (state == UP_DEVICE_STATE_FULLY_CHARGED) {
+ g_debug ("** EMIT: fully charged");
+ }
+
+ /* save new state */
+ g_object_set_data (G_OBJECT(device), "engine-state-old", GUINT_TO_POINTER(state));
+ }
+
+ /* check the warning state has not changed */
+ warning_old = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(device), "engine-warning-old"));
+ warning = engine_get_warning (manager, device);
+ if (warning != warning_old) {
+ if (warning == WARNING_LOW) {
+ g_debug ("** EMIT: charge-low");
+ } else if (warning == WARNING_CRITICAL) {
+ g_debug ("** EMIT: charge-critical");
+ } else if (warning == WARNING_ACTION) {
+ g_debug ("** EMIT: charge-action");
+ }
+ /* save new state */
+ g_object_set_data (G_OBJECT(device), "engine-warning-old", GUINT_TO_POINTER(warning));
+ }
+
+ engine_recalculate_state (manager);
+}
+
+static UpDevice *
+engine_get_primary_device (GsdPowerManager *manager)
+{
+ guint i;
+ UpDevice *device = NULL;
+ UpDevice *device_tmp;
+ UpDeviceKind kind;
+ UpDeviceState state;
+ gboolean is_present;
+
+ for (i=0; i<manager->priv->devices_array->len; i++) {
+ device_tmp = g_ptr_array_index (manager->priv->devices_array, i);
+
+ /* get device properties */
+ g_object_get (device_tmp,
+ "kind", &kind,
+ "state", &state,
+ "is-present", &is_present,
+ NULL);
+
+ /* not present */
+ if (!is_present)
+ continue;
+
+ /* not discharging */
+ if (state != UP_DEVICE_STATE_DISCHARGING)
+ continue;
+
+ /* not battery */
+ if (kind != UP_DEVICE_KIND_BATTERY)
+ continue;
+
+ /* use composite device to cope with multiple batteries */
+ device = g_object_ref (engine_get_composite_device (manager, device_tmp));
+ break;
+ }
+ return device;
+}
+
+static void
+phone_device_added_cb (GpmPhone *phone, guint idx, GsdPowerManager *manager)
+{
+ UpDevice *device;
+ device = up_device_new ();
+
+ g_debug ("phone added %i", idx);
+
+ /* get device properties */
+ g_object_set (device,
+ "kind", UP_DEVICE_KIND_PHONE,
+ "is-rechargeable", TRUE,
+ "native-path", g_strdup_printf ("dummy:phone_%i", idx),
+ "is-present", TRUE,
+ NULL);
+
+ /* state changed */
+ engine_device_add (manager, device);
+ g_ptr_array_add (manager->priv->devices_array, g_object_ref (device));
+ engine_recalculate_state (manager);
+}
+
+static void
+phone_device_removed_cb (GpmPhone *phone, guint idx, GsdPowerManager *manager)
+{
+ guint i;
+ UpDevice *device;
+ UpDeviceKind kind;
+
+ g_debug ("phone removed %i", idx);
+
+ for (i=0; i<manager->priv->devices_array->len; i++) {
+ device = g_ptr_array_index (manager->priv->devices_array, i);
+
+ /* get device properties */
+ g_object_get (device,
+ "kind", &kind,
+ NULL);
+
+ if (kind == UP_DEVICE_KIND_PHONE) {
+ g_ptr_array_remove_index (manager->priv->devices_array, i);
+ break;
+ }
+ }
+
+ /* state changed */
+ engine_recalculate_state (manager);
+}
+
+static void
+phone_device_refresh_cb (GpmPhone *phone, guint idx, GsdPowerManager *manager)
+{
+ guint i;
+ UpDevice *device;
+ UpDeviceKind kind;
+ UpDeviceState state;
+ gboolean is_present;
+ gdouble percentage;
+
+ g_debug ("phone refresh %i", idx);
+
+ for (i=0; i<manager->priv->devices_array->len; i++) {
+ device = g_ptr_array_index (manager->priv->devices_array, i);
+
+ /* get device properties */
+ g_object_get (device,
+ "kind", &kind,
+ "state", &state,
+ "percentage", &percentage,
+ "is-present", &is_present,
+ NULL);
+
+ if (kind == UP_DEVICE_KIND_PHONE) {
+ is_present = gpm_phone_get_present (phone, idx);
+ state = gpm_phone_get_on_ac (phone, idx) ? UP_DEVICE_STATE_CHARGING : UP_DEVICE_STATE_DISCHARGING;
+ percentage = gpm_phone_get_percentage (phone, idx);
+ break;
+ }
+ }
+
+ /* state changed */
+ engine_recalculate_state (manager);
+}
+
static void
gnome_session_shutdown_cb (GObject *source_object,
GAsyncResult *res,
@@ -376,6 +1236,9 @@ gsd_power_manager_start (GsdPowerManager *manager,
if (manager->priv->x11_screen == NULL)
return FALSE;
+ /* coldplug the engine */
+ engine_coldplug (manager);
+
gnome_settings_profile_end (NULL);
return TRUE;
}
@@ -466,8 +1329,16 @@ gsd_power_manager_init (GsdPowerManager *manager)
manager->priv->kbd_brightness_old = -1;
manager->priv->settings = g_settings_new (GSD_POWER_SETTINGS_SCHEMA);
+ g_signal_connect (manager->priv->settings, "changed",
+ G_CALLBACK (engine_settings_key_changed_cb), manager);
manager->priv->up_client = up_client_new ();
manager->priv->lid_is_closed = up_client_get_lid_is_closed (manager->priv->up_client);
+ g_signal_connect (manager->priv->up_client, "device-added",
+ G_CALLBACK (engine_device_added_cb), manager);
+ g_signal_connect (manager->priv->up_client, "device-removed",
+ G_CALLBACK (engine_device_removed_cb), manager);
+ g_signal_connect (manager->priv->up_client, "device-changed",
+ G_CALLBACK (engine_device_changed_cb), manager);
g_signal_connect (manager->priv->up_client, "changed",
G_CALLBACK (up_client_changed_cb), manager);
@@ -481,6 +1352,46 @@ gsd_power_manager_init (GsdPowerManager *manager)
NULL,
power_keyboard_proxy_ready_cb,
manager);
+
+ manager->priv->devices_array = g_ptr_array_new_with_free_func (g_object_unref);
+
+ manager->priv->phone = gpm_phone_new ();
+ g_signal_connect (manager->priv->phone, "device-added",
+ G_CALLBACK (phone_device_added_cb), manager);
+ g_signal_connect (manager->priv->phone, "device-removed",
+ G_CALLBACK (phone_device_removed_cb), manager);
+ g_signal_connect (manager->priv->phone, "device-refresh",
+ G_CALLBACK (phone_device_refresh_cb), manager);
+
+ /* create a fake virtual composite battery */
+ manager->priv->device_composite = up_device_new ();
+ g_object_set (manager->priv->device_composite,
+ "kind", UP_DEVICE_KIND_BATTERY,
+ "is-rechargeable", TRUE,
+ "native-path", "dummy:composite_battery",
+ "power-supply", TRUE,
+ "is-present", TRUE,
+ NULL);
+
+ /* get percentage policy */
+ manager->priv->low_percentage = g_settings_get_int (manager->priv->settings,
+ "percentage-low");
+ manager->priv->critical_percentage = g_settings_get_int (manager->priv->settings,
+ "percentage-critical");
+ manager->priv->action_percentage = g_settings_get_int (manager->priv->settings,
+ "percentage-action");
+
+ /* get time policy */
+ manager->priv->low_time = g_settings_get_int (manager->priv->settings,
+ "time-low");
+ manager->priv->critical_time = g_settings_get_int (manager->priv->settings,
+ "time-critical");
+ manager->priv->action_time = g_settings_get_int (manager->priv->settings,
+ "time-action");
+
+ /* we can disable this if the time remaining is inaccurate or just plain wrong */
+ manager->priv->use_time_primary = g_settings_get_boolean (manager->priv->settings,
+ "use-time-for-policy");
}
static void
@@ -500,6 +1411,14 @@ gsd_power_manager_finalize (GObject *object)
if (manager->priv->x11_screen != NULL);
g_object_unref (manager->priv->x11_screen);
+ g_ptr_array_unref (manager->priv->devices_array);
+ g_object_unref (manager->priv->phone);
+ g_object_unref (manager->priv->device_composite);
+
+ if (manager->priv->previous_icon != NULL)
+ g_object_unref (manager->priv->previous_icon);
+ g_free (manager->priv->previous_summary);
+
G_OBJECT_CLASS (gsd_power_manager_parent_class)->finalize (object);
}
@@ -742,7 +1661,7 @@ handle_method_call_main (GsdPowerManager *manager,
GVariant *parameters,
GDBusMethodInvocation *invocation)
{
- GPtrArray *array = NULL;
+ GPtrArray *array;
guint i;
GVariantBuilder *builder;
GVariant *tuple = NULL;
@@ -753,19 +1672,19 @@ handle_method_call_main (GsdPowerManager *manager,
if (g_strcmp0 (method_name, "GetPrimaryDevice") == 0) {
/* get the virtual device */
- device = NULL;
+ device = engine_get_primary_device (manager);
if (device == NULL) {
g_dbus_method_invocation_return_dbus_error (invocation,
"org.gnome.SettingsDaemon.Power.Failed",
"There is no primary device.");
- goto out;
+ return;
}
/* return the value */
value = device_to_variant_blob (device);
tuple = g_variant_new_tuple (&value, 1);
g_dbus_method_invocation_return_value (invocation, tuple);
- goto out;
+ return;
}
/* return array */
@@ -775,7 +1694,7 @@ handle_method_call_main (GsdPowerManager *manager,
builder = g_variant_builder_new (G_VARIANT_TYPE("a(susdut)"));
/* add each tuple to the array */
- array = g_ptr_array_new ();
+ array = g_ptr_array_ref (manager->priv->devices_array);
for (i=0; i<array->len; i++) {
device = g_ptr_array_index (array, i);
value = device_to_variant_blob (device);
@@ -787,10 +1706,10 @@ handle_method_call_main (GsdPowerManager *manager,
tuple = g_variant_new_tuple (&value, 1);
g_dbus_method_invocation_return_value (invocation, tuple);
g_variant_builder_unref (builder);
+ return;
}
-out:
- if (array != NULL)
- g_ptr_array_unref (array);
+
+ g_assert_not_reached ();
}
static void
@@ -836,17 +1755,27 @@ handle_get_property (GDBusConnection *connection,
const gchar *property_name,
GError **error, gpointer user_data)
{
+ GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
+ gchar *tooltip = NULL;
+ GIcon *icon = NULL;
GVariant *retval = NULL;
if (g_strcmp0 (property_name, "Icon") == 0) {
- retval = g_variant_new_string ("");
+ icon = engine_get_icon (manager);
+ if (icon != NULL)
+ tooltip = g_icon_to_string (icon);
+ retval = g_variant_new_string (tooltip != NULL ? tooltip : "");
goto out;
}
if (g_strcmp0 (property_name, "Tooltip") == 0) {
- retval = g_variant_new_string ("");
+ tooltip = engine_get_summary (manager);
+ retval = g_variant_new_string (tooltip != NULL ? tooltip : "");
goto out;
}
out:
+ if (icon != NULL)
+ g_object_unref (icon);
+ g_free (tooltip);
return retval;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]