diff --git a/devkit-power-gobject/Makefile.am b/devkit-power-gobject/Makefile.am index 588ebce..d3b5c92 100644 --- a/devkit-power-gobject/Makefile.am +++ b/devkit-power-gobject/Makefile.am @@ -16,6 +16,7 @@ libdevkit_power_include_HEADERS = \ devicekit-power.h \ dkp-version.h \ dkp-client.h \ + dkp-backlight.h \ dkp-device.h \ dkp-wakeups.h \ dkp-qos-obj.h \ @@ -31,6 +32,8 @@ libdevkit_power_gobject_la_SOURCES = \ dkp-client.h \ dkp-device.c \ dkp-device.h \ + dkp-backlight.c \ + dkp-backlight.h \ dkp-wakeups.c \ dkp-wakeups.h \ dkp-qos-obj.c \ diff --git a/devkit-power-gobject/devicekit-power.h b/devkit-power-gobject/devicekit-power.h index 6d173a9..019bf42 100644 --- a/devkit-power-gobject/devicekit-power.h +++ b/devkit-power-gobject/devicekit-power.h @@ -37,6 +37,7 @@ #include #include #include +#include #undef __DEVICEKIT_POWER_H_INSIDE__ diff --git a/devkit-power-gobject/dkp-backlight.c b/devkit-power-gobject/dkp-backlight.c new file mode 100644 index 0000000..cbd3a5b --- /dev/null +++ b/devkit-power-gobject/dkp-backlight.c @@ -0,0 +1,366 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2009 Richard Hughes + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "dkp-backlight.h" + +static void dkp_backlight_class_init (DkpBacklightClass *klass); +static void dkp_backlight_init (DkpBacklight *backlight); +static void dkp_backlight_finalize (GObject *object); + +#define DKP_BACKLIGHT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DKP_TYPE_BACKLIGHT, DkpBacklightPrivate)) + +struct DkpBacklightPrivate +{ + DBusGConnection *bus; + DBusGProxy *proxy; + DBusGProxy *prop_proxy; + gboolean have_interface; + gboolean have_properties; + gboolean action_in_hardware; + guint actual; + guint maximum; +}; + +enum +{ + BRIGHTNESS_CHANGED, + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_ACTUAL, + PROP_MAXIMUM, + PROP_ACTION_IN_HARDWARE, + PROP_LAST +}; + +static guint signals [LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (DkpBacklight, dkp_backlight, G_TYPE_OBJECT) + +/** + * dkp_backlight_set_brightness: + * + * Sets the backlight brightness + **/ +gboolean +dkp_backlight_set_brightness (DkpBacklight *backlight, guint value, GError **error) +{ + GError *error_local = NULL; + gboolean ret = FALSE; + + g_return_val_if_fail (DKP_IS_BACKLIGHT (backlight), FALSE); + g_return_val_if_fail (backlight->priv->proxy != NULL, FALSE); + + /* no device */ + if (!backlight->priv->have_interface) { + if (error != NULL) + *error = g_error_new (1, 0, "no device to control"); + goto out; + } + + /* set brightness */ + ret = dbus_g_proxy_call (backlight->priv->proxy, "SetBrightness", &error_local, + G_TYPE_UINT, value, + G_TYPE_INVALID, + G_TYPE_INVALID); + if (!ret) { + g_warning ("SetBrightness failed: %s", error_local->message); + if (error != NULL) + *error = g_error_new (1, 0, "%s", error_local->message); + g_error_free (error_local); + goto out; + } +out: + return ret; +} + +/** + * dkp_backlight_ensure_properties: + **/ +static void +dkp_backlight_ensure_properties (DkpBacklight *backlight) +{ + gboolean ret; + GError *error; + GHashTable *props; + GValue *value; + + props = NULL; + + if (backlight->priv->have_properties) + goto out; + + /* no device */ + if (!backlight->priv->have_interface) + goto out; + + error = NULL; + ret = dbus_g_proxy_call (backlight->priv->prop_proxy, "GetAll", &error, + G_TYPE_STRING, "org.freedesktop.DeviceKit.Power.Backlight", + G_TYPE_INVALID, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &props, + G_TYPE_INVALID); + if (!ret) { + g_debug ("Error invoking GetAll() to get properties: %s", error->message); + backlight->priv->have_interface = FALSE; + g_error_free (error); + goto out; + } + + value = g_hash_table_lookup (props, "action-in-hardware"); + if (value == NULL) { + g_warning ("No 'action-in-hardware' property"); + goto out; + } + backlight->priv->action_in_hardware = g_value_get_boolean (value); + + value = g_hash_table_lookup (props, "actual"); + if (value == NULL) { + g_warning ("No 'actual' property"); + goto out; + } + backlight->priv->actual = g_value_get_uint (value); + + value = g_hash_table_lookup (props, "maximum"); + if (value == NULL) { + g_warning ("No 'maximum' property"); + goto out; + } + backlight->priv->maximum = g_value_get_uint (value); + + /* cached */ + backlight->priv->have_properties = TRUE; + +out: + if (props != NULL) + g_hash_table_unref (props); +} + +/** + * dkp_backlight_brightness_changed_cb: + **/ +static void +dkp_backlight_brightness_changed_cb (DBusGProxy *proxy, guint value, DkpBacklight *backlight) +{ + backlight->priv->have_properties = FALSE; + g_signal_emit (backlight, signals [BRIGHTNESS_CHANGED], 0, value); +} + +/** + * dkp_backlight_get_property: + **/ +static void +dkp_backlight_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + DkpBacklight *backlight = DKP_BACKLIGHT (object); + + dkp_backlight_ensure_properties (backlight); + + switch (prop_id) { + case PROP_ACTUAL: + g_value_set_uint (value, backlight->priv->actual); + break; + case PROP_MAXIMUM: + g_value_set_uint (value, backlight->priv->maximum); + break; + case PROP_ACTION_IN_HARDWARE: + g_value_set_boolean (value, backlight->priv->action_in_hardware); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * dkp_backlight_set_property: + **/ +static void +dkp_backlight_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + DkpBacklight *backlight = DKP_BACKLIGHT (object); + + switch (prop_id) { + case PROP_ACTUAL: + backlight->priv->actual = g_value_get_uint (value); + break; + case PROP_MAXIMUM: + backlight->priv->maximum = g_value_get_uint (value); + break; + case PROP_ACTION_IN_HARDWARE: + backlight->priv->action_in_hardware = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * dkp_backlight_class_init: + * @klass: The DkpBacklightClass + **/ +static void +dkp_backlight_class_init (DkpBacklightClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = dkp_backlight_finalize; + object_class->get_property = dkp_backlight_get_property; + object_class->set_property = dkp_backlight_set_property; + + signals [BRIGHTNESS_CHANGED] = + g_signal_new ("brightness-changed", + G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (DkpBacklightClass, brightness_changed), + NULL, NULL, g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, G_TYPE_UINT); + + /** + * DkpBacklight:actual: + */ + g_object_class_install_property (object_class, + PROP_ACTUAL, + g_param_spec_uint ("actual", + NULL, NULL, + 0, + G_MAXUINT, + 0, + G_PARAM_READWRITE)); + + /** + * DkpBacklight:maximum: + */ + g_object_class_install_property (object_class, + PROP_MAXIMUM, + g_param_spec_uint ("maximum", + NULL, NULL, + 0, + G_MAXUINT, + 0, + G_PARAM_READWRITE)); + /** + * DkpBacklight:action-in-hardware: + */ + g_object_class_install_property (object_class, + PROP_ACTION_IN_HARDWARE, + g_param_spec_boolean ("action-in-hardware", + NULL, NULL, + FALSE, + G_PARAM_READWRITE)); + + g_type_class_add_private (klass, sizeof (DkpBacklightPrivate)); +} + +/** + * dkp_backlight_init: + * @backlight: This class instance + **/ +static void +dkp_backlight_init (DkpBacklight *backlight) +{ + GError *error = NULL; + + backlight->priv = DKP_BACKLIGHT_GET_PRIVATE (backlight); + backlight->priv->have_properties = FALSE; + backlight->priv->actual = 0; + backlight->priv->maximum = 0; + backlight->priv->action_in_hardware = FALSE; + backlight->priv->have_interface = TRUE; + + /* get on the bus */ + backlight->priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (backlight->priv->bus == NULL) { + g_warning ("Couldn't connect to system bus: %s", error->message); + g_error_free (error); + goto out; + } + + /* connect to properties interface */ + backlight->priv->prop_proxy = dbus_g_proxy_new_for_name (backlight->priv->bus, + "org.freedesktop.DeviceKit.Power", + "/org/freedesktop/DeviceKit/Power/Backlight", + "org.freedesktop.DBus.Properties"); + if (backlight->priv->prop_proxy == NULL) { + g_warning ("Couldn't connect to proxy"); + goto out; + } + + /* connect to main interface */ + backlight->priv->proxy = dbus_g_proxy_new_for_name (backlight->priv->bus, + "org.freedesktop.DeviceKit.Power", + "/org/freedesktop/DeviceKit/Power/Backlight", + "org.freedesktop.DeviceKit.Power.Backlight"); + if (backlight->priv->proxy == NULL) { + g_warning ("Couldn't connect to proxy"); + goto out; + } + dbus_g_proxy_add_signal (backlight->priv->proxy, "BrightnessChanged", G_TYPE_UINT, G_TYPE_INVALID); + + /* all callbacks */ + dbus_g_proxy_connect_signal (backlight->priv->proxy, "BrightnessChanged", + G_CALLBACK (dkp_backlight_brightness_changed_cb), backlight, NULL); +out: + return; +} + +/** + * dkp_backlight_finalize: + * @object: The object to finalize + **/ +static void +dkp_backlight_finalize (GObject *object) +{ + DkpBacklight *backlight; + + g_return_if_fail (DKP_IS_BACKLIGHT (object)); + + backlight = DKP_BACKLIGHT (object); + if (backlight->priv->proxy != NULL) + g_object_unref (backlight->priv->proxy); + if (backlight->priv->prop_proxy != NULL) + g_object_unref (backlight->priv->prop_proxy); + + G_OBJECT_CLASS (dkp_backlight_parent_class)->finalize (object); +} + +/** + * dkp_backlight_new: + * + * Return value: a new DkpBacklight object. + **/ +DkpBacklight * +dkp_backlight_new (void) +{ + DkpBacklight *backlight; + backlight = g_object_new (DKP_TYPE_BACKLIGHT, NULL); + return DKP_BACKLIGHT (backlight); +} + diff --git a/devkit-power-gobject/dkp-backlight.h b/devkit-power-gobject/dkp-backlight.h new file mode 100644 index 0000000..8fb879e --- /dev/null +++ b/devkit-power-gobject/dkp-backlight.h @@ -0,0 +1,64 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2009 Richard Hughes + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if !defined (__DEVICEKIT_POWER_H_INSIDE__) && !defined (DKP_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __DKP_BACKLIGHT_H +#define __DKP_BACKLIGHT_H + +#include + +G_BEGIN_DECLS + +#define DKP_TYPE_BACKLIGHT (dkp_backlight_get_type ()) +#define DKP_BACKLIGHT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DKP_TYPE_BACKLIGHT, DkpBacklight)) +#define DKP_BACKLIGHT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DKP_TYPE_BACKLIGHT, DkpBacklightClass)) +#define DKP_IS_BACKLIGHT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DKP_TYPE_BACKLIGHT)) +#define DKP_IS_BACKLIGHT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DKP_TYPE_BACKLIGHT)) +#define DKP_BACKLIGHT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DKP_TYPE_BACKLIGHT, DkpBacklightClass)) + +typedef struct DkpBacklightPrivate DkpBacklightPrivate; + +typedef struct +{ + GObject parent; + DkpBacklightPrivate *priv; +} DkpBacklight; + +typedef struct +{ + GObjectClass parent_class; + void (*brightness_changed) (DkpBacklight *backlight, + guint value); +} DkpBacklightClass; + +GType dkp_backlight_get_type (void); +DkpBacklight *dkp_backlight_new (void); +gboolean dkp_backlight_set_brightness (DkpBacklight *backlight, + guint value, + GError **error); + +G_END_DECLS + +#endif /* __DKP_BACKLIGHT_H */ + diff --git a/src/Makefile.am b/src/Makefile.am index 14f68de..7062a06 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,6 +31,7 @@ BUILT_SOURCES = \ dkp-device-glue.h \ dkp-qos-glue.h \ dkp-wakeups-glue.h \ + dkp-backlight-glue.h \ dkp-marshal.h \ dkp-marshal.c @@ -52,6 +53,9 @@ dkp-qos-glue.h: org.freedesktop.DeviceKit.Power.QoS.xml Makefile.am dkp-wakeups-glue.h: org.freedesktop.DeviceKit.Power.Wakeups.xml Makefile.am dbus-binding-tool --prefix=dkp_wakeups --mode=glib-server --output=dkp-wakeups-glue.h org.freedesktop.DeviceKit.Power.Wakeups.xml +dkp-backlight-glue.h: org.freedesktop.DeviceKit.Power.Backlight.xml Makefile.am + dbus-binding-tool --prefix=dkp_backlight --mode=glib-server --output=dkp-backlight-glue.h org.freedesktop.DeviceKit.Power.Backlight.xml + libexec_PROGRAMS = devkit-power-daemon dbusifdir = $(datadir)/dbus-1/interfaces @@ -59,6 +63,7 @@ dbusif_DATA = \ org.freedesktop.DeviceKit.Power.xml \ org.freedesktop.DeviceKit.Power.Device.xml \ org.freedesktop.DeviceKit.Power.QoS.xml \ + org.freedesktop.DeviceKit.Power.Backlight.xml \ org.freedesktop.DeviceKit.Power.Wakeups.xml devkit_power_daemon_SOURCES = \ @@ -75,6 +80,7 @@ devkit_power_daemon_SOURCES = \ dkp-input.h dkp-input.c \ dkp-qos.h dkp-qos.c \ dkp-wakeups.h dkp-wakeups.c \ + dkp-backlight.h dkp-backlight.c \ dkp-history.h dkp-history.c \ sysfs-utils.h sysfs-utils.c \ dkp-main.c \ @@ -120,6 +126,7 @@ EXTRA_DIST = \ org.freedesktop.DeviceKit.Power.xml \ org.freedesktop.DeviceKit.Power.Device.xml \ org.freedesktop.DeviceKit.Power.QoS.xml \ + org.freedesktop.DeviceKit.Power.Backlight.xml \ org.freedesktop.DeviceKit.Power.Wakeups.xml \ dkp-marshal.list \ $(service_in_files) \ diff --git a/src/dkp-backlight.c b/src/dkp-backlight.c new file mode 100644 index 0000000..8915447 --- /dev/null +++ b/src/dkp-backlight.c @@ -0,0 +1,363 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 Richard Hughes + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "egg-debug.h" +#include "sysfs-utils.h" + +#include "dkp-backlight.h" +#include "dkp-daemon.h" +#include "dkp-backlight-glue.h" + +static void dkp_backlight_class_init (DkpBacklightClass *klass); +static void dkp_backlight_init (DkpBacklight *backlight); +static void dkp_backlight_finalize (GObject *object); + +#define DKP_BACKLIGHT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DKP_TYPE_BACKLIGHT, DkpBacklightPrivate)) + +struct DkpBacklightPrivate +{ + DevkitDevice *device; + DBusGConnection *connection; + gboolean action_in_hardware; + guint actual; + guint maximum; +}; + +enum +{ + BRIGHTNESS_CHANGED, + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_ACTUAL, + PROP_MAXIMUM, + PROP_ACTION_IN_HARDWARE, + PROP_LAST +}; + +static guint signals [LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (DkpBacklight, dkp_backlight, G_TYPE_OBJECT) + +/** + * dkp_backlight_refresh_internal: + **/ +static gboolean +dkp_backlight_refresh_internal (DkpBacklight *backlight) +{ + const gchar *native_path; + + g_return_val_if_fail (DKP_IS_BACKLIGHT (backlight), FALSE); + + /* get new value */ + native_path = devkit_device_get_native_path (backlight->priv->device); + backlight->priv->actual = sysfs_get_int (native_path, "actual_brightness"); + + return TRUE; +} + +/** + * dkp_backlight_changed: + **/ +gboolean +dkp_backlight_changed (DkpBacklight *backlight) +{ + const gchar *native_path; + + g_return_val_if_fail (DKP_IS_BACKLIGHT (backlight), FALSE); + + /* get new value */ + native_path = devkit_device_get_native_path (backlight->priv->device); + backlight->priv->actual = sysfs_get_int (native_path, "actual_brightness"); + + egg_debug ("backlight device changed %s (%i/%i)", native_path, backlight->priv->actual, backlight->priv->maximum); + + /* emit */ + g_signal_emit (backlight, signals [BRIGHTNESS_CHANGED], 0, backlight->priv->actual); + + return TRUE; +} + +/** + * dkp_backlight_set_device: + **/ +gboolean +dkp_backlight_set_device (DkpBacklight *backlight, DevkitDevice *device) +{ + const gchar *native_path; + const gchar *value; + + g_return_val_if_fail (DKP_IS_BACKLIGHT (backlight), FALSE); + + backlight->priv->device = g_object_ref (device); + + /* coldplug */ + native_path = devkit_device_get_native_path (device); + backlight->priv->actual = sysfs_get_int (native_path, "actual_brightness"); + backlight->priv->maximum = sysfs_get_int (native_path, "max_brightness"); + + /* EC does it's own updates */ + value = devkit_device_get_property (device, "DKP_ACTION_IN_HARDWARE"); + if (value != NULL) + backlight->priv->action_in_hardware = TRUE; + + egg_debug ("adding backlight device %s (%i/%i)", native_path, backlight->priv->actual, backlight->priv->maximum); + + return TRUE; +} + +/** + * dkp_backlight_set_brightness: + **/ +void +dkp_backlight_set_brightness (DkpBacklight *backlight, guint value, DBusGMethodInvocation *context) +{ + GError *error; + gchar *value_text = NULL; + const gchar *native_path; + gchar *path = NULL; + gint fd = -1; + ssize_t wrote; + gint len; + + if (value > backlight->priv->maximum) { + error = g_error_new (DKP_DAEMON_ERROR, DKP_DAEMON_ERROR_GENERAL, "value too high: %i > %i", value, backlight->priv->maximum); + dbus_g_method_return_error (context, error); + goto out; + } + + + /* TODO: use GIO and async write */ + native_path = devkit_device_get_native_path (backlight->priv->device); + path = g_build_filename (native_path, "brightness", NULL); + + /* open file */ + fd = open (path, O_WRONLY); + if (fd < 0) { + error = g_error_new (DKP_DAEMON_ERROR, DKP_DAEMON_ERROR_GENERAL, "failed to open file"); + dbus_g_method_return_error (context, error); + goto out; + } + + /* write chunk */ + len = strlen (value_text); + value_text = g_strdup_printf ("%u", value); + egg_debug ("Writing '%s' to '%s'", value_text, path); + wrote = write (fd, value_text, len); + if (wrote < len) { + error = g_error_new (DKP_DAEMON_ERROR, DKP_DAEMON_ERROR_GENERAL, "failed to write %i/%i", wrote, len); + dbus_g_method_return_error (context, error); + goto out; + } + + /* emit */ + g_signal_emit (backlight, signals [BRIGHTNESS_CHANGED], 0, value); + + /* success */ + dbus_g_method_return (context, NULL); +out: + if (fd >= 0) + close (fd); + g_free (value_text); + g_free (path); +} + +/** + * dkp_backlight_get_property: + **/ +static void +dkp_backlight_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + DkpBacklight *backlight = DKP_BACKLIGHT (object); + switch (prop_id) { + case PROP_ACTUAL: + /* FIXME: for now do a hack to read the new value from sysfs + * as backlight devices do not issue uevents when they change */ + dkp_backlight_refresh_internal (backlight); + g_value_set_uint (value, backlight->priv->actual); + break; + case PROP_MAXIMUM: + g_value_set_uint (value, backlight->priv->maximum); + break; + case PROP_ACTION_IN_HARDWARE: + g_value_set_boolean (value, backlight->priv->action_in_hardware); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * dkp_backlight_set_property: + **/ +static void +dkp_backlight_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + DkpBacklight *backlight = DKP_BACKLIGHT (object); + + switch (prop_id) { + case PROP_ACTUAL: + backlight->priv->actual = g_value_get_uint (value); + break; + case PROP_MAXIMUM: + backlight->priv->maximum = g_value_get_uint (value); + break; + case PROP_ACTION_IN_HARDWARE: + backlight->priv->action_in_hardware = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * dkp_backlight_class_init: + **/ +static void +dkp_backlight_class_init (DkpBacklightClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = dkp_backlight_finalize; + object_class->get_property = dkp_backlight_get_property; + object_class->set_property = dkp_backlight_set_property; + + signals [BRIGHTNESS_CHANGED] = + g_signal_new ("brightness-changed", + G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (DkpBacklightClass, brightness_changed), + NULL, NULL, g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, G_TYPE_UINT); + + /** + * DkpBacklight:actual: + */ + g_object_class_install_property (object_class, + PROP_ACTUAL, + g_param_spec_uint ("actual", + NULL, NULL, + 0, + G_MAXUINT, + 0, + G_PARAM_READWRITE)); + + /** + * DkpBacklight:maximum: + */ + g_object_class_install_property (object_class, + PROP_MAXIMUM, + g_param_spec_uint ("maximum", + NULL, NULL, + 0, + G_MAXUINT, + 0, + G_PARAM_READWRITE)); + /** + * DkpBacklight:action-in-hardware: + */ + g_object_class_install_property (object_class, + PROP_ACTION_IN_HARDWARE, + g_param_spec_boolean ("action-in-hardware", + NULL, NULL, + FALSE, + G_PARAM_READWRITE)); + + /* introspection */ + dbus_g_object_type_install_info (DKP_TYPE_BACKLIGHT, &dbus_glib_dkp_backlight_object_info); + + g_type_class_add_private (klass, sizeof (DkpBacklightPrivate)); +} + +/** + * dkp_backlight_init: + **/ +static void +dkp_backlight_init (DkpBacklight *backlight) +{ + GError *error = NULL; + + backlight->priv = DKP_BACKLIGHT_GET_PRIVATE (backlight); + + backlight->priv->device = NULL; + backlight->priv->actual = 0; + backlight->priv->maximum = 0; + backlight->priv->action_in_hardware = FALSE; + + backlight->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (error != NULL) { + egg_warning ("Cannot connect to bus: %s", error->message); + g_error_free (error); + return; + } + + /* register on the bus */ + dbus_g_connection_register_g_object (backlight->priv->connection, "/org/freedesktop/DeviceKit/Power/Backlight", G_OBJECT (backlight)); +} + +/** + * dkp_backlight_finalize: + **/ +static void +dkp_backlight_finalize (GObject *object) +{ + DkpBacklight *backlight; + + g_return_if_fail (object != NULL); + g_return_if_fail (DKP_IS_BACKLIGHT (object)); + + backlight = DKP_BACKLIGHT (object); + backlight->priv = DKP_BACKLIGHT_GET_PRIVATE (backlight); + + if (backlight->priv->device != NULL) + g_object_unref (backlight->priv->device); + + G_OBJECT_CLASS (dkp_backlight_parent_class)->finalize (object); +} + +/** + * dkp_backlight_new: + **/ +DkpBacklight * +dkp_backlight_new (void) +{ + DkpBacklight *backlight; + backlight = g_object_new (DKP_TYPE_BACKLIGHT, NULL); + return DKP_BACKLIGHT (backlight); +} + diff --git a/src/dkp-backlight.h b/src/dkp-backlight.h new file mode 100644 index 0000000..5490e1b --- /dev/null +++ b/src/dkp-backlight.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2008-2009 Richard Hughes + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __DKP_BACKLIGHT_H +#define __DKP_BACKLIGHT_H + +#include +#include + +G_BEGIN_DECLS + +#define DKP_TYPE_BACKLIGHT (dkp_backlight_get_type ()) +#define DKP_BACKLIGHT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DKP_TYPE_BACKLIGHT, DkpBacklight)) +#define DKP_BACKLIGHT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DKP_TYPE_BACKLIGHT, DkpBacklightClass)) +#define DKP_IS_BACKLIGHT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DKP_TYPE_BACKLIGHT)) +#define DKP_IS_BACKLIGHT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DKP_TYPE_BACKLIGHT)) +#define DKP_BACKLIGHT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DKP_TYPE_BACKLIGHT, DkpBacklightClass)) + +typedef struct DkpBacklightPrivate DkpBacklightPrivate; + +typedef struct +{ + GObject parent; + DkpBacklightPrivate *priv; +} DkpBacklight; + +typedef struct +{ + GObjectClass parent_class; + void (* brightness_changed) (DkpBacklight *backlight, + guint value); +} DkpBacklightClass; + +DkpBacklight *dkp_backlight_new (void); +GType dkp_backlight_get_type (void); + +gboolean dkp_backlight_set_device (DkpBacklight *backlight, + DevkitDevice *d); +gboolean dkp_backlight_changed (DkpBacklight *backlight); + +/* exported methods */ +void dkp_backlight_set_brightness (DkpBacklight *backlight, + guint value, + DBusGMethodInvocation *context); + +G_END_DECLS + +#endif /* __DKP_BACKLIGHT_H */ diff --git a/src/dkp-daemon.c b/src/dkp-daemon.c index 895b769..a53ec5c 100644 --- a/src/dkp-daemon.c +++ b/src/dkp-daemon.c @@ -41,8 +41,9 @@ #include "dkp-device-csr.h" #include "dkp-device-wup.h" #include "dkp-device-hid.h" -#include "dkp-input.h" #include "dkp-device-list.h" +#include "dkp-input.h" +#include "dkp-backlight.h" #include "dkp-daemon-glue.h" #include "dkp-marshal.h" @@ -69,7 +70,7 @@ enum LAST_SIGNAL, }; -static const gchar *subsystems[] = {"power_supply", "usb", "tty", "input", NULL}; +static const gchar *subsystems[] = {"power_supply", "usb", "tty", "input", "backlight", NULL}; static guint signals[LAST_SIGNAL] = { 0 }; @@ -504,8 +505,27 @@ dkp_daemon_device_changed (DkpDaemon *daemon, DevkitDevice *d, gboolean synthesi { GObject *object; DkpDevice *device; + const gchar *subsys; gboolean ret; + /* certain types are treated specially */ + subsys = devkit_device_get_subsystem (d); + if (g_strcmp0 (subsys, "backlight") == 0) { + + /* does device exist in db? */ + object = dkp_device_list_lookup (daemon->priv->managed_devices, d); + if (object != NULL) { + egg_debug ("device brightness changed %s", devkit_device_get_native_path (d)); + dkp_backlight_changed (DKP_BACKLIGHT (object)); + } + + goto out; + } + if (g_strcmp0 (subsys, "input") == 0) { + egg_debug ("already handled by DkpInput"); + goto out; + } + /* first, change the device and add it if it doesn't exist */ object = dkp_device_list_lookup (daemon->priv->power_devices, d); if (object != NULL) { @@ -513,6 +533,7 @@ dkp_daemon_device_changed (DkpDaemon *daemon, DevkitDevice *d, gboolean synthesi egg_debug ("changed %s", dkp_device_get_object_path (device)); dkp_device_changed (device, d, synthesized); } else { + /* TODO: is managed device? */ egg_debug ("treating change event as add on %s", devkit_device_get_native_path (d)); dkp_daemon_device_add (daemon, d, TRUE); } @@ -533,6 +554,8 @@ dkp_daemon_device_changed (DkpDaemon *daemon, DevkitDevice *d, gboolean synthesi egg_debug ("now low_battery = %s", ret ? "yes" : "no"); g_signal_emit (daemon, signals[CHANGED_SIGNAL], 0); } +out: + return; } /** @@ -555,6 +578,7 @@ dkp_daemon_device_get (DkpDaemon *daemon, DevkitDevice *d) const gchar *native_path; DkpDevice *device = NULL; DkpInput *input; + DkpBacklight *backlight; gboolean ret; subsys = devkit_device_get_subsystem (d); @@ -617,8 +641,18 @@ dkp_daemon_device_get (DkpDaemon *daemon, DevkitDevice *d) /* not a power device */ dkp_device_list_insert (daemon->priv->managed_devices, d, G_OBJECT (input)); - /* no valid input object */ - device = NULL; + } else if (g_strcmp0 (subsys, "backlight") == 0) { + + /* check input device */ + backlight = dkp_backlight_new (); + ret = dkp_backlight_set_device (backlight, d); + if (!ret) { + g_object_unref (backlight); + goto out; + } + + /* not a power device */ + dkp_device_list_insert (daemon->priv->managed_devices, d, G_OBJECT (backlight)); } else { native_path = devkit_device_get_native_path (d); diff --git a/src/org.freedesktop.DeviceKit.Power.Backlight.xml b/src/org.freedesktop.DeviceKit.Power.Backlight.xml new file mode 100644 index 0000000..4f9ff17 --- /dev/null +++ b/src/org.freedesktop.DeviceKit.Power.Backlight.xml @@ -0,0 +1,92 @@ + +]> + + + + + + org.freedesktop.DeviceKit.Power.Backlight is a DBus interface implimented + by DeviceKit-power. + It allows applications to watch to change the system backlight brightness. + + + + + + + + + If the system does brightness updates in the embedded controller + when the brightness keys are pressed. + + + + + + + + + + The current brightness value. + + + + + + + + + + The number of maximum discrete value the hardware supports. + + + + + + + + + + + + The absolute brightness level. + + + + + + + Sets the current brightness value. + Value zero is the lowest brightness state, NOT display off. + + + + if an error occured while getting the latency + + + + + + + + + + The new absolute brightness level. + + + + + + + The brightness level has changed. + + + + + + + + diff --git a/src/org.freedesktop.DeviceKit.Power.conf.in b/src/org.freedesktop.DeviceKit.Power.conf.in index 855b4b5..3e22e50 100644 --- a/src/org.freedesktop.DeviceKit.Power.conf.in +++ b/src/org.freedesktop.DeviceKit.Power.conf.in @@ -21,6 +21,8 @@ send_interface="org.freedesktop.DBus.Properties"/> + @@ -30,5 +32,7 @@ send_interface="org.freedesktop.DeviceKit.Power.QoS"/> +