[gnome-settings-daemon] Add support for ambient light devices supported by iio-sensor-proxy
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon] Add support for ambient light devices supported by iio-sensor-proxy
- Date: Fri, 22 May 2015 13:24:13 +0000 (UTC)
commit afd1ec179f8f497a8068fc413102c2ba1b42a26f
Author: Richard Hughes <richard hughsie com>
Date: Thu May 21 11:19:35 2015 +0100
Add support for ambient light devices supported by iio-sensor-proxy
Resolves: https://bugzilla.gnome.org/show_bug.cgi?id=745181
...settings-daemon.plugins.power.gschema.xml.in.in | 5 +
plugins/power/gsd-power-manager.c | 182 +++++++++++++++++++-
2 files changed, 183 insertions(+), 4 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 51d017b..deec1f0 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
@@ -61,5 +61,10 @@
<summary>Power button action</summary>
<description>The action to take when the system power button is pressed.</description>
</key>
+ <key name="ambient-enabled" type="b">
+ <default>true</default>
+ <summary>Enable the ALS sensor</summary>
+ <description>If the ambient light sensor functionality is enabled.</description>
+ </key>
</schema>
</schemalist>
diff --git a/plugins/power/gsd-power-manager.c b/plugins/power/gsd-power-manager.c
index afe9405..1215f8b 100644
--- a/plugins/power/gsd-power-manager.c
+++ b/plugins/power/gsd-power-manager.c
@@ -1,7 +1,7 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann <mccann jhu edu>
- * Copyright (C) 2011-2012 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2011-2012, 2015 Richard Hughes <richard hughsie com>
* Copyright (C) 2011 Ritesh Khadgaray <khadgaray gmail com>
* Copyright (C) 2012-2013 Red Hat Inc.
*
@@ -77,6 +77,11 @@
/* And the time before we stop the warning sound */
#define GSD_STOP_SOUND_DELAY GSD_ACTION_DELAY - 2
+/* the amount of smoothing done to the the ambient light readings; a lower
+ * number means the backlight changes slower in response to changing ambient
+ * conditions, a hugher number may lead to noticable jitteryness */
+#define GSD_AMBIENT_SMOOTH 0.3f
+
static const gchar introspection_xml[] =
"<node>"
" <interface name='org.gnome.SettingsDaemon.Power.Screen'>"
@@ -157,6 +162,15 @@ struct GsdPowerManagerPrivate
gint kbd_brightness_old;
gint kbd_brightness_pre_dim;
+ /* Ambient */
+ GDBusProxy *iio_proxy;
+ guint iio_proxy_watch_id;
+ gboolean ambient_norm_required;
+ gdouble ambient_accumulator;
+ gdouble ambient_norm_value;
+ gdouble ambient_percentage_old;
+ gdouble ambient_last_absolute;
+
/* Sound */
guint32 critical_alert_timeout_id;
@@ -975,11 +989,33 @@ screen_devices_enable (GsdPowerManager *manager)
}
static void
+iio_proxy_claim_light (GsdPowerManager *manager, gboolean active)
+{
+ GError *error = NULL;
+ if (manager->priv->iio_proxy == NULL)
+ return;
+ if (!manager->priv->backlight_available)
+ return;
+
+ if (!g_dbus_proxy_call_sync (manager->priv->iio_proxy,
+ active ? "ClaimLight" : "ReleaseLight",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error)) {
+ g_warning ("Call to ii-proxy failed: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
backlight_enable (GsdPowerManager *manager)
{
gboolean ret;
GError *error = NULL;
+ iio_proxy_claim_light (manager, TRUE);
ret = gnome_rr_screen_set_dpms_mode (manager->priv->rr_screen,
GNOME_RR_DPMS_ON,
&error);
@@ -1000,6 +1036,7 @@ backlight_disable (GsdPowerManager *manager)
gboolean ret;
GError *error = NULL;
+ iio_proxy_claim_light (manager, FALSE);
ret = gnome_rr_screen_set_dpms_mode (manager->priv->rr_screen,
GNOME_RR_DPMS_OFF,
&error);
@@ -1855,6 +1892,10 @@ gsd_power_manager_finalize (GObject *object)
if (manager->priv->name_id != 0)
g_bus_unown_name (manager->priv->name_id);
+ if (manager->priv->iio_proxy_watch_id != 0)
+ g_bus_unwatch_name (manager->priv->iio_proxy_watch_id);
+ manager->priv->iio_proxy_watch_id = 0;
+
G_OBJECT_CLASS (gsd_power_manager_parent_class)->finalize (object);
}
@@ -2079,6 +2120,19 @@ idle_became_active_cb (GnomeIdleMonitor *monitor,
}
static void
+ch_backlight_renormalize (GsdPowerManager *manager)
+{
+ if (manager->priv->ambient_percentage_old < 0)
+ return;
+ if (manager->priv->ambient_last_absolute < 0)
+ return;
+ manager->priv->ambient_norm_value = manager->priv->ambient_last_absolute /
+ (gdouble) manager->priv->ambient_percentage_old;
+ manager->priv->ambient_norm_value *= 100.f;
+ manager->priv->ambient_norm_required = FALSE;
+}
+
+static void
engine_settings_key_changed_cb (GSettings *settings,
const gchar *key,
GsdPowerManager *manager)
@@ -2420,15 +2474,110 @@ on_rr_screen_acquired (GObject *object,
/* queue a signal in case the proxy from gnome-shell was created before we got here
(likely, considering that to get here we need a reply from gnome-shell)
*/
- if (manager->priv->backlight_available)
+ if (manager->priv->backlight_available) {
+ manager->priv->ambient_percentage_old = backlight_get_percentage (manager->priv->rr_screen,
NULL);
backlight_iface_emit_changed (manager, GSD_POWER_DBUS_INTERFACE_SCREEN,
- backlight_get_percentage (manager->priv->rr_screen, NULL));
- else
+ manager->priv->ambient_percentage_old);
+ } else {
backlight_iface_emit_changed (manager, GSD_POWER_DBUS_INTERFACE_SCREEN, -1);
+ }
gnome_settings_profile_end (NULL);
}
+static void
+iio_proxy_changed_cb (GDBusProxy *proxy,
+ GVariant *changed_properties,
+ GStrv invalidated_properties,
+ gpointer user_data)
+{
+ GsdPowerManager *manager = (GsdPowerManager *) user_data;
+ GError *error = NULL;
+ GVariant *val_has = NULL;
+ GVariant *val_als = NULL;
+ gdouble brightness;
+ gint pc;
+
+ /* no display hardware */
+ if (!manager->priv->backlight_available)
+ return;
+
+ /* disabled */
+ if (!g_settings_get_boolean (manager->priv->settings, "ambient-enabled"))
+ return;
+
+ /* get latest results, which do not have to be Lux */
+ val_has = g_dbus_proxy_get_cached_property (proxy, "HasAmbientLight");
+ if (val_has == NULL || !g_variant_get_boolean (val_has))
+ goto out;
+ val_als = g_dbus_proxy_get_cached_property (proxy, "LightLevel");
+ if (val_als == NULL)
+ goto out;
+ manager->priv->ambient_last_absolute = g_variant_get_double (val_als);
+
+ /* the user has asked to renormalize */
+ if (manager->priv->ambient_norm_required) {
+ manager->priv->ambient_accumulator = manager->priv->ambient_percentage_old;
+ ch_backlight_renormalize (manager);
+ }
+
+ /* calculate exponential moving average */
+ brightness = manager->priv->ambient_last_absolute * 100.f / manager->priv->ambient_norm_value;
+ brightness = MIN (brightness, 100.f);
+ brightness = MAX (brightness, 0.f);
+ manager->priv->ambient_accumulator = (GSD_AMBIENT_SMOOTH * brightness) +
+ (1.0 - GSD_AMBIENT_SMOOTH) * manager->priv->ambient_accumulator;
+
+ /* no valid readings yet */
+ if (manager->priv->ambient_accumulator < 0.f)
+ goto out;
+
+ /* set new value */
+ g_debug ("set brightness from ambient %.1f%%",
+ manager->priv->ambient_accumulator);
+ pc = manager->priv->ambient_accumulator;
+ if (!backlight_set_percentage (manager->priv->rr_screen, &pc, &error)) {
+ g_warning ("failed to set brightness: %s", error->message);
+ g_error_free (error);
+ }
+ manager->priv->ambient_percentage_old = pc;
+out:
+ if (val_has != NULL)
+ g_variant_unref (val_has);
+ if (val_als != NULL)
+ g_variant_unref (val_als);
+}
+
+static void
+iio_proxy_appeared_cb (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
+ manager->priv->iio_proxy =
+ g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ 0,
+ NULL,
+ "net.hadess.SensorProxy",
+ "/net/hadess/SensorProxy",
+ "net.hadess.SensorProxy",
+ NULL,
+ NULL);
+ g_signal_connect (manager->priv->iio_proxy, "g-properties-changed",
+ G_CALLBACK (iio_proxy_changed_cb), manager);
+ iio_proxy_claim_light (manager, TRUE);
+}
+
+static void
+iio_proxy_vanished_cb (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GsdPowerManager *manager = GSD_POWER_MANAGER (user_data);
+ g_clear_object (&manager->priv->iio_proxy);
+}
+
gboolean
gsd_power_manager_start (GsdPowerManager *manager,
GError **error)
@@ -2472,6 +2621,20 @@ gsd_power_manager_start (GsdPowerManager *manager,
manager->priv->settings_bus = g_settings_new ("org.gnome.desktop.session");
manager->priv->settings_xrandr = g_settings_new (GSD_XRANDR_SETTINGS_SCHEMA);
+ /* setup ambient light support */
+ manager->priv->iio_proxy_watch_id =
+ g_bus_watch_name (G_BUS_TYPE_SYSTEM,
+ "net.hadess.SensorProxy",
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ iio_proxy_appeared_cb,
+ iio_proxy_vanished_cb,
+ manager, NULL);
+ manager->priv->ambient_norm_required = TRUE;
+ manager->priv->ambient_accumulator = -1.f;
+ manager->priv->ambient_norm_value = -1.f;
+ manager->priv->ambient_percentage_old = -1.f;
+ manager->priv->ambient_last_absolute = -1.f;
+
gnome_settings_profile_end (NULL);
return TRUE;
}
@@ -2508,6 +2671,9 @@ gsd_power_manager_stop (GsdPowerManager *manager)
g_clear_object (&manager->priv->settings_bus);
g_clear_object (&manager->priv->up_client);
+ iio_proxy_claim_light (manager, FALSE);
+ g_clear_object (&manager->priv->iio_proxy);
+
if (manager->priv->inhibit_lid_switch_fd != -1) {
close (manager->priv->inhibit_lid_switch_fd);
manager->priv->inhibit_lid_switch_fd = -1;
@@ -2629,6 +2795,10 @@ handle_method_call_screen (GsdPowerManager *manager,
g_assert_not_reached ();
}
+ /* ambient brightness no longer valid */
+ manager->priv->ambient_percentage_old = value;
+ manager->priv->ambient_norm_required = TRUE;
+
out:
/* return value */
if (value < 0) {
@@ -2755,6 +2925,10 @@ handle_set_property_other (GsdPowerManager *manager,
g_variant_get (value, "i", &brightness_value);
if (backlight_set_percentage (manager->priv->rr_screen, &brightness_value, error)) {
backlight_iface_emit_changed (manager, GSD_POWER_DBUS_INTERFACE_SCREEN,
brightness_value);
+
+ /* ambient brightness no longer valid */
+ manager->priv->ambient_percentage_old = brightness_value;
+ manager->priv->ambient_norm_required = TRUE;
return TRUE;
} else {
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]