diff options
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | debian/control | 3 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/ib-brightness-control.c | 155 | ||||
-rw-r--r-- | src/ib-brightness-control.h | 33 | ||||
-rw-r--r-- | src/service.c | 99 |
6 files changed, 289 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac index 81b6f9f..ba39dec 100644 --- a/configure.ac +++ b/configure.ac @@ -35,11 +35,12 @@ LT_INIT GLIB_REQUIRED_VERSION=2.35.4 GIO_REQUIRED_VERSION=2.26 GIO_UNIX_REQUIRED_VERSION=2.26 -GSD_REQUIRED_VERSION=3.1.4 +GUDEV_REQUIRED_VERSION=204 PKG_CHECK_MODULES([SERVICE_DEPS],[glib-2.0 >= $GLIB_REQUIRED_VERSION gio-2.0 >= $GIO_REQUIRED_VERSION - gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION]) + gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION + gudev-1.0 >= $GUDEV_REQUIRED_VERSION]) ########################### # GSETTINGS diff --git a/debian/control b/debian/control index 1a81e88..fc1c924 100644 --- a/debian/control +++ b/debian/control @@ -7,7 +7,8 @@ Build-Depends: debhelper (>= 9), autopoint, intltool, libgtest-dev, - libglib2.0-dev (>= 2.35.4), + libglib2.0-dev (>= 2.36), + libgudev-1.0-dev, python, Standards-Version: 3.9.2 Homepage: https://launchpad.net/indicator-power diff --git a/src/Makefile.am b/src/Makefile.am index 0bd4dc3..92117fc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -63,6 +63,8 @@ libindicatorpower_upower_a_CFLAGS = \ libindciatorpower_upower_a_LDFLAGS = $(COVERAGE_LDFLAGS) libindicatorpower_service_a_SOURCES = \ + ib-brightness-control.c \ + ib-brightness-control.h \ device-provider.c \ device-provider.h \ device.c \ diff --git a/src/ib-brightness-control.c b/src/ib-brightness-control.c new file mode 100644 index 0000000..2b9b79d --- /dev/null +++ b/src/ib-brightness-control.c @@ -0,0 +1,155 @@ +/* + * Copyright 2012 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Renato Araujo Oliveira Filho <renato@canonical.com> + */ + +#include <gudev/gudev.h> + +#include <errno.h> +#include <stdlib.h> +#include <fcntl.h> +#include <string.h> + +#include "ib-brightness-control.h" + +struct _IbBrightnessControl +{ + gchar *path; +}; + +IbBrightnessControl* +ib_brightness_control_new (void) +{ + IbBrightnessControl *control; + GUdevClient *client; + gchar *path = NULL; + GList *devices; + + // detect device + client = g_udev_client_new (NULL); + devices = g_udev_client_query_by_subsystem (client, "backlight"); + if (devices != NULL) { + GList *device; + const gchar *device_type; + + for (device = devices; device != NULL; device = device->next) { + device_type = g_udev_device_get_sysfs_attr (device->data, "type"); + if ((g_strcmp0 (device_type, "firmware") == 0) || + (g_strcmp0 (device_type, "platform") == 0) || + (g_strcmp0 (device_type, "raw") == 0)) { + path = g_strdup (g_udev_device_get_sysfs_path (device->data)); + g_print ("found: %s\n", path); + break; + } + } + + g_list_free_full (devices, g_object_unref); + } + else { + g_warning ("Fail to query backlight devices."); + } + + control = g_new0 (IbBrightnessControl, 1); + control->path = path; + + g_object_unref (client); + return control; +} + +void +ib_brightness_control_set_value (IbBrightnessControl* self, gint value) +{ + gint fd; + gchar *filename; + gchar *svalue; + gint length; + gint err; + + if (self->path == NULL) + return; + + filename = g_build_filename (self->path, "brightness", NULL); + fd = open(filename, O_WRONLY); + if (fd < 0) { + g_warning ("Fail to set brightness."); + g_free (filename); + return; + } + + svalue = g_strdup_printf ("%i", value); + length = strlen (svalue); + + err = errno; + errno = 0; + if (write (fd, svalue, length) != length) { + g_warning ("Fail to write brightness information: %s", g_strerror(errno)); + } + errno = err; + + close (fd); + g_free (svalue); + g_free (filename); +} + +gint +ib_brightness_control_get_value_from_file (IbBrightnessControl *self, const gchar *file) +{ + GError *error; + gchar *svalue; + gint value; + gchar *filename; + + if (self->path == NULL) + return 0; + + svalue = NULL; + error = NULL; + filename = g_build_filename (self->path, file, NULL); + g_file_get_contents (filename, &svalue, NULL, &error); + if (error) { + g_warning ("Fail to get brightness value: %s", error->message); + value = -1; + g_error_free (error); + } else { + value = atoi (svalue); + } + + g_free (filename); + + return value; + +} + +gint +ib_brightness_control_get_value (IbBrightnessControl* self) +{ + return ib_brightness_control_get_value_from_file (self, "brightness"); +} + +gint +ib_brightness_control_get_max_value (IbBrightnessControl* self) +{ + return ib_brightness_control_get_value_from_file (self, "max_brightness"); +} + +void +ib_brightness_control_free (IbBrightnessControl *self) +{ + g_free (self->path); + g_free (self); +} + diff --git a/src/ib-brightness-control.h b/src/ib-brightness-control.h new file mode 100644 index 0000000..87711e4 --- /dev/null +++ b/src/ib-brightness-control.h @@ -0,0 +1,33 @@ +/* + * Copyright 2012 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Renato Araujo Oliveira Filho <renato@canonical.com> + */ + +#ifndef __IB_BRIGHTNESS_CONTROL_H__ +#define __IB_BRIGHTNESS_CONTROL_H__ + +#include <gio/gio.h> + +typedef struct _IbBrightnessControl IbBrightnessControl; + +IbBrightnessControl* ib_brightness_control_new (void); +void ib_brightness_control_set_value (IbBrightnessControl* self, gint value); +gint ib_brightness_control_get_value (IbBrightnessControl* self); +gint ib_brightness_control_get_max_value (IbBrightnessControl* self); +void ib_brightness_control_free (IbBrightnessControl *self); + +#endif diff --git a/src/service.c b/src/service.c index 6c9a9c6..b59bce3 100644 --- a/src/service.c +++ b/src/service.c @@ -25,6 +25,7 @@ #include "device.h" #include "device-provider.h" +#include "ib-brightness-control.h" #include "service.h" #define BUS_NAME "com.canonical.indicator.power" @@ -100,6 +101,8 @@ struct _IndicatorPowerServicePrivate GSettings * settings; + IbBrightnessControl * brightness_control; + guint own_id; guint actions_export_id; GDBusConnection * conn; @@ -110,6 +113,7 @@ struct _IndicatorPowerServicePrivate GSimpleAction * header_action; GSimpleAction * show_time_action; GSimpleAction * battery_level_action; + GSimpleAction * brightness_action; IndicatorPowerDevice * primary_device; GList * devices; /* IndicatorPowerDevice */ @@ -441,6 +445,72 @@ create_phone_devices_section (IndicatorPowerService * self G_GNUC_UNUSED) **** ***/ +static void +get_brightness_range (IndicatorPowerService * self, gint * low, gint * high) +{ + const int max = ib_brightness_control_get_max_value (self->priv->brightness_control); + *low = max * 0.05; /* 5% minimum -- don't let the screen go completely dark */ + *high = max; +} + +static gdouble +brightness_to_percentage (IndicatorPowerService * self, int brightness) +{ + int lo, hi; + get_brightness_range (self, &lo, &hi); + return (brightness-lo) / (double)(hi-lo); +} + +static int +percentage_to_brightness (IndicatorPowerService * self, double percentage) +{ + int lo, hi; + get_brightness_range (self, &lo, &hi); + return (int)(lo + (percentage*(hi-lo))); +} + +static GMenuItem * +create_brightness_menuitem (IndicatorPowerService * self) +{ + int lo, hi; + GMenuItem * item; + + get_brightness_range (self, &lo, &hi); + + item = g_menu_item_new ("Brightness", "indicator.brightness"); + g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.unity.slider"); + g_menu_item_set_attribute (item, "min-value", "d", brightness_to_percentage (self, lo)); + g_menu_item_set_attribute (item, "max-value", "d", brightness_to_percentage (self, hi)); + return item; +} + +static GVariant * +action_state_for_brightness (IndicatorPowerService * self) +{ + priv_t * p = self->priv; + const gint brightness = ib_brightness_control_get_value (p->brightness_control); + return g_variant_new_double (brightness_to_percentage (self, brightness)); +} + +static void +update_brightness_action_state (IndicatorPowerService * self) +{ + g_simple_action_set_state (self->priv->brightness_action, + action_state_for_brightness (self)); +} + +static void +on_brightness_change_requested (GSimpleAction * action G_GNUC_UNUSED, + GVariant * parameter, + gpointer gself) +{ + IndicatorPowerService * self = INDICATOR_POWER_SERVICE (gself); + const gdouble percentage = g_variant_get_double (parameter); + const int brightness = percentage_to_brightness (self, percentage); + ib_brightness_control_set_value (self->priv->brightness_control, brightness); + update_brightness_action_state (self); +} + static GMenuModel * create_desktop_settings_section (IndicatorPowerService * self G_GNUC_UNUSED) { @@ -460,13 +530,19 @@ create_desktop_settings_section (IndicatorPowerService * self G_GNUC_UNUSED) static GMenuModel * create_phone_settings_section (IndicatorPowerService * self G_GNUC_UNUSED) { - GMenu * menu = g_menu_new (); + GMenu * section; + GMenuItem * item; - g_menu_append (menu, - _("Battery settingsā¦"), - "indicator.activate-settings"); + section = g_menu_new (); - return G_MENU_MODEL (menu); + item = create_brightness_menuitem (self); + g_menu_append_item (section, item); + update_brightness_action_state (self); + g_object_unref (item); + + g_menu_append (section, _("Battery settingsā¦"), "indicator.activate-settings"); + + return G_MENU_MODEL (section); } /*** @@ -492,6 +568,7 @@ static void rebuild_now (IndicatorPowerService * self, guint sections) { priv_t * p = self->priv; + struct ProfileMenuInfo * phone = &p->menus[PROFILE_PHONE]; struct ProfileMenuInfo * desktop = &p->menus[PROFILE_DESKTOP]; struct ProfileMenuInfo * greeter = &p->menus[PROFILE_DESKTOP_GREETER]; @@ -512,6 +589,7 @@ rebuild_now (IndicatorPowerService * self, guint sections) if (sections & SECTION_SETTINGS) { rebuild_section (desktop->submenu, 1, create_desktop_settings_section (self)); + rebuild_section (phone->submenu, 1, create_desktop_settings_section (self)); } } @@ -708,6 +786,12 @@ init_gactions (IndicatorPowerService * self) g_simple_action_group_insert (p->actions, G_ACTION(a)); p->battery_level_action = a; + /* add the brightness action */ + a = g_simple_action_new_stateful ("brightness", NULL, action_state_for_brightness (self)); + g_simple_action_group_insert (p->actions, G_ACTION(a)); + g_signal_connect (a, "change-state", G_CALLBACK(on_brightness_change_requested), self); + p->brightness_action = a; + /* add the show-time action */ show_time = g_settings_get_boolean (p->settings, SETTINGS_SHOW_TIME_S); a = g_simple_action_new_stateful ("show-time", @@ -930,6 +1014,7 @@ my_dispose (GObject * o) g_clear_object (&p->show_time_action); } + g_clear_object (&p->brightness_action); g_clear_object (&p->battery_level_action); g_clear_object (&p->header_action); g_clear_object (&p->show_time_action); @@ -937,6 +1022,8 @@ my_dispose (GObject * o) g_clear_object (&p->conn); + g_clear_pointer (&p->brightness_control, ib_brightness_control_free); + indicator_power_service_set_device_provider (self, NULL); G_OBJECT_CLASS (indicator_power_service_parent_class)->dispose (o); @@ -958,6 +1045,8 @@ indicator_power_service_init (IndicatorPowerService * self) p->settings = g_settings_new ("com.canonical.indicator.power"); + p->brightness_control = ib_brightness_control_new (); + init_gactions (self); g_signal_connect_swapped (p->settings, "changed::" SETTINGS_ICON_POLICY_S, |