diff options
Diffstat (limited to 'src/xfpm-button.c')
-rw-r--r-- | src/xfpm-button.c | 657 |
1 files changed, 657 insertions, 0 deletions
diff --git a/src/xfpm-button.c b/src/xfpm-button.c new file mode 100644 index 00000000..f025282d --- /dev/null +++ b/src/xfpm-button.c @@ -0,0 +1,657 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- + * + * * Copyright (C) 2008 Ali <ali.slackware@gmail.com> + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <xfconf/xfconf.h> + +#include "xfpm-button.h" +#include "xfpm-hal.h" +#include "xfpm-debug.h" +#include "xfpm-common.h" +#include "xfpm-notify.h" +#include "xfpm-enums.h" +#include "xfpm-enum-types.h" +#include "xfpm-marshal.h" + +#define XFPM_BUTTON_GET_PRIVATE(o) \ +(G_TYPE_INSTANCE_GET_PRIVATE(o,XFPM_TYPE_BUTTON,XfpmButtonPrivate)) + +static void xfpm_button_init(XfpmButton *bt); +static void xfpm_button_class_init(XfpmButtonClass *klass); +static void xfpm_button_finalize(GObject *object); + +static void xfpm_button_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void xfpm_button_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void xfpm_button_do_suspend(XfpmButton *bt); +static void xfpm_button_do_hibernate(XfpmButton *bt); + +static void xfpm_button_lid_pressed(XfpmButton *bt,const gchar *udi); +static void xfpm_button_power_pressed(XfpmButton *bt,const gchar *udi); +static void xfpm_button_sleep_pressed(XfpmButton *bt,const gchar *udi); + +static void xfpm_button_handle_device_condition_cb(XfpmHal *hal, + const gchar *udi, + const gchar *condition_name, + const gchar *condition_detail, + XfpmButton *bt); + +static void xfpm_button_load_config(XfpmButton *bt); +static void xfpm_button_get_switches(XfpmButton *bt); + +struct XfpmButtonPrivate +{ + XfpmHal *hal; + gulong handler_id; + + gboolean have_lid_bt; + gboolean lid_button_has_state; + + gboolean have_power_bt; + gboolean power_button_has_state; + + gboolean have_sleep_bt; + gboolean sleep_button_has_state; + + gboolean device_found; + + guint8 sleep_info; + +}; + +G_DEFINE_TYPE(XfpmButton,xfpm_button,G_TYPE_OBJECT) + +enum +{ + XFPM_ACTION_REQUEST, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0,}; + +enum +{ + PROP_0, + PROP_LID_ACTION, + PROP_SLEEP_ACTION, + PROP_POWER_ACTION +}; + +static void xfpm_button_class_init(XfpmButtonClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->finalize = xfpm_button_finalize; + + gobject_class->set_property = xfpm_button_set_property; + gobject_class->get_property = xfpm_button_get_property; + + signals[XFPM_ACTION_REQUEST] = g_signal_new("xfpm-action-request", + XFPM_TYPE_BUTTON, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(XfpmButtonClass,button_action_request), + NULL,NULL, + _xfpm_marshal_VOID__ENUM_BOOLEAN , + G_TYPE_NONE,2, + XFPM_TYPE_ACTION_REQUEST,G_TYPE_BOOLEAN); + + g_object_class_install_property(gobject_class, + PROP_LID_ACTION, + g_param_spec_enum("lid-switch-action", + "lid switch action", + "lid switch action", + XFPM_TYPE_ACTION_REQUEST, + XFPM_DO_NOTHING, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, + PROP_SLEEP_ACTION, + g_param_spec_enum("sleep-switch-action", + "sleep switch action", + "sleep switch action", + XFPM_TYPE_ACTION_REQUEST, + XFPM_DO_NOTHING, + G_PARAM_READWRITE)); + g_object_class_install_property(gobject_class, + PROP_POWER_ACTION, + g_param_spec_enum("power-switch-action", + "power switch action", + "power switch action", + XFPM_TYPE_ACTION_REQUEST, + XFPM_DO_NOTHING, + G_PARAM_READWRITE)); + + g_type_class_add_private(klass,sizeof(XfpmButtonPrivate)); + +} + +static void xfpm_button_init(XfpmButton *bt) +{ + XfpmButtonPrivate *priv; + priv = XFPM_BUTTON_GET_PRIVATE(bt); + + priv->have_lid_bt = FALSE; + priv->lid_button_has_state = FALSE; + + priv->have_power_bt = FALSE; + priv->power_button_has_state= FALSE; + + priv->have_sleep_bt = FALSE; + priv->sleep_button_has_state= FALSE; + + priv->sleep_info = 0; + + priv->hal = xfpm_hal_new(); + + xfpm_button_load_config(bt); + xfpm_button_get_switches(bt); + + if ( priv->have_lid_bt || priv->have_power_bt || priv->have_sleep_bt ) + { + if (xfpm_hal_connect_to_signals(priv->hal,FALSE,FALSE,FALSE,TRUE) ) + { + priv->handler_id = + g_signal_connect(priv->hal,"xfpm-device-condition", + G_CALLBACK(xfpm_button_handle_device_condition_cb),bt); + } + } +} + +static void xfpm_button_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ +#ifdef DEBUG + gchar *content; + content = g_strdup_value_contents(value); + XFPM_DEBUG("param:%s value contents:%s\n",pspec->name,content); + g_free(content); +#endif + XfpmButton *bt; + bt = XFPM_BUTTON(object); + + switch (prop_id) + { + case PROP_LID_ACTION: + bt->lid_action = g_value_get_enum(value); + break; + case PROP_SLEEP_ACTION: + bt->sleep_action = g_value_get_enum(value); + break; + case PROP_POWER_ACTION: + bt->power_action = g_value_get_enum(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object,prop_id,pspec); + break; + } +} + +static void xfpm_button_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + XfpmButton *bt; + bt = XFPM_BUTTON(object); + + switch (prop_id) + { + case PROP_LID_ACTION: + g_value_set_enum(value,bt->lid_action); + break; + case PROP_SLEEP_ACTION: + g_value_set_enum(value,bt->sleep_action); + break; + case PROP_POWER_ACTION: + g_value_set_enum(value,bt->power_action); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object,prop_id,pspec); + break; + } + +#ifdef DEBUG + gchar *content; + content = g_strdup_value_contents(value); + XFPM_DEBUG("param:%s value contents:%s\n",pspec->name,content); + g_free(content); +#endif + +} + +static void xfpm_button_finalize(GObject *object) +{ + XfpmButton *bt; + bt = XFPM_BUTTON(object); + + bt->priv = XFPM_BUTTON_GET_PRIVATE(bt); + + if ( bt->priv->hal ) + { + g_object_unref(bt->priv->hal); + } + + G_OBJECT_CLASS(xfpm_button_parent_class)->finalize(object); +} + +static gboolean +_unblock_handler(XfpmButtonPrivate *priv) +{ + g_signal_handler_unblock(priv->hal,priv->handler_id); + return FALSE; +} + +static void +xfpm_button_do_hibernate(XfpmButton *bt) +{ + XfpmButtonPrivate *priv; + priv = XFPM_BUTTON_GET_PRIVATE(bt); + + g_signal_handler_block(priv->hal,priv->handler_id); + + g_signal_emit(G_OBJECT(bt),signals[XFPM_ACTION_REQUEST],0,XFPM_DO_HIBERNATE,FALSE); + + g_timeout_add(10,(GSourceFunc)_unblock_handler,priv); + +} + +static void +xfpm_button_do_suspend(XfpmButton *bt) +{ + XfpmButtonPrivate *priv; + priv = XFPM_BUTTON_GET_PRIVATE(bt); + + g_signal_handler_block(priv->hal,priv->handler_id); + + g_signal_emit(G_OBJECT(bt),signals[XFPM_ACTION_REQUEST],0,XFPM_DO_SUSPEND,FALSE); + + g_timeout_add(10,(GSourceFunc)_unblock_handler,priv); +} + +static void +_proccess_action(XfpmButton *bt,XfpmActionRequest action) +{ + XfpmButtonPrivate *priv; + priv = XFPM_BUTTON_GET_PRIVATE(bt); + + if ( action == XFPM_DO_SUSPEND ) + { + xfpm_button_do_suspend(bt); + } + else if ( action == XFPM_DO_HIBERNATE ) + { + xfpm_button_do_hibernate(bt); + } + else if ( action == XFPM_DO_SHUTDOWN ) + { + XfpmButtonPrivate *priv; + priv = XFPM_BUTTON_GET_PRIVATE(bt); + g_signal_handler_block(priv->hal,priv->handler_id); + + g_signal_emit(G_OBJECT(bt),signals[XFPM_ACTION_REQUEST],0,XFPM_DO_SHUTDOWN,FALSE); + + g_timeout_add(10,(GSourceFunc)_unblock_handler,priv); + + } + +} + +static void +xfpm_button_lid_pressed(XfpmButton *bt,const gchar *udi) +{ + if ( bt->lid_action == XFPM_DO_NOTHING ) + { + return; + } + + XfpmButtonPrivate *priv; + priv = XFPM_BUTTON_GET_PRIVATE(bt); + + if ( priv->have_lid_bt ) + { + if ( priv->lid_button_has_state ) + { + GError *error = NULL; + gboolean pressed = + xfpm_hal_get_bool_info(priv->hal,udi,"button.state.value",&error); + if ( error ) + { + XFPM_DEBUG("Error getting lid switch state: %s\n",error->message); + g_error_free(error); + return; + } + else if ( pressed == TRUE ) + { + _proccess_action(bt,bt->lid_action); + } + } + else + { + _proccess_action(bt,bt->lid_action); + } + } +} + +static void +xfpm_button_power_pressed(XfpmButton *bt,const gchar *udi) +{ + if ( bt->power_action == XFPM_DO_NOTHING ) + { + XFPM_DEBUG("Power action is do nothing\n"); + return; + } + + XfpmButtonPrivate *priv; + priv = XFPM_BUTTON_GET_PRIVATE(bt); + + if ( priv->have_power_bt ) + { + if ( priv->power_button_has_state ) + { + GError *error = NULL; + gboolean pressed = + xfpm_hal_get_bool_info(priv->hal,udi,"button.state.value",&error); + if ( error ) + { + XFPM_DEBUG("Error getting lid switch state: %s\n",error->message); + g_error_free(error); + return; + } + else if ( pressed == TRUE ) + { + _proccess_action(bt,bt->power_action); + } + } + else + { + _proccess_action(bt,bt->power_action); + } + } +} + +static void +xfpm_button_sleep_pressed(XfpmButton *bt,const gchar *udi) +{ + XfpmButtonPrivate *priv; + priv = XFPM_BUTTON_GET_PRIVATE(bt); + + if ( bt->sleep_action == XFPM_DO_NOTHING ) + { + return; + } + + if ( priv->have_sleep_bt ) + { + if ( priv->sleep_button_has_state ) + { + GError *error = NULL; + gboolean pressed = + xfpm_hal_get_bool_info(priv->hal,udi,"button.state.value",&error); + if ( error ) + { + XFPM_DEBUG("Error getting lid switch state: %s\n",error->message); + g_error_free(error); + return; + } + else if ( pressed == TRUE ) + { + _proccess_action(bt,bt->sleep_action); + } + } + else + { + _proccess_action(bt,bt->sleep_action); + } + } +} + +static void +xfpm_button_handle_device_condition_cb(XfpmHal *hal, + const gchar *udi, + const gchar *condition_name, + const gchar *condition_detail, + XfpmButton *bt) +{ + XfpmButtonPrivate *priv; + priv = XFPM_BUTTON_GET_PRIVATE(bt); + + if ( xfpm_hal_device_have_capability(priv->hal,udi,"button") ) + { + if ( strcmp(condition_name,"ButtonPressed") ) + { + XFPM_DEBUG("Not processing event with condition_name=%s\n",condition_name); + return; + } + XFPM_DEBUG("proccessing event: %s %s\n",condition_name,condition_detail); + if ( !strcmp(condition_detail,"lid") ) + { + xfpm_button_lid_pressed(bt,udi); + } + else if ( !strcmp(condition_detail,"power") ) + { + xfpm_button_power_pressed(bt,udi); + } + else if ( !strcmp(condition_detail,"sleep") ) + { + xfpm_button_sleep_pressed(bt,udi); + } + } +} + +static void +xfpm_button_load_config(XfpmButton *bt) +{ + XFPM_DEBUG("Loading configuration\n"); + + XfconfChannel *channel; + + channel = xfconf_channel_new(XFPM_CHANNEL_CFG); + + bt->lid_action = xfconf_channel_get_uint(channel,LID_SWITCH_CFG,XFPM_DO_NOTHING); + bt->sleep_action = xfconf_channel_get_uint(channel,SLEEP_SWITCH_CFG,XFPM_DO_NOTHING); + bt->power_action = xfconf_channel_get_uint(channel,POWER_SWITCH_CFG,XFPM_DO_NOTHING); + + g_object_unref(channel); +} + +static void +_check_button(XfpmButtonPrivate *priv,const gchar *button_type,const gchar *udi) +{ + if ( !strcmp(button_type,"lid")) + { + priv->have_lid_bt = TRUE; + priv->lid_button_has_state = xfpm_hal_get_bool_info(priv->hal,udi, + "button.has_state", + NULL); + + } + else if ( !strcmp(button_type,"power") ) + { + priv->have_power_bt = TRUE; + priv->power_button_has_state = xfpm_hal_get_bool_info(priv->hal,udi, + "button.has_state", + NULL); + } + else if ( !strcmp(button_type,"sleep")) + { + priv->have_sleep_bt = TRUE; + priv->sleep_button_has_state = xfpm_hal_get_bool_info(priv->hal,udi, + "button.has_state", + NULL); + } +} + +static void +xfpm_button_get_switches(XfpmButton *bt) +{ + XfpmButtonPrivate *priv; + priv = XFPM_BUTTON_GET_PRIVATE(bt); + + gchar **udi; + gint dummy; + GError *error = NULL; + + udi = xfpm_hal_get_device_udi_by_capability(priv->hal,"button",&dummy,&error); + + if ( error ) + { + XFPM_DEBUG("Unable to get button switches: %s\n",error->message); + g_error_free(error); + return; + } + + if ( !udi ) + { + XFPM_DEBUG("No buttons found\n"); + } + int i = 0 ; + for ( i = 0 ; udi[i] ; i++) + { + if ( xfpm_hal_device_have_key(priv->hal,udi[i],"button.type") && + xfpm_hal_device_have_key(priv->hal,udi[i],"button.has_state") ) + { + GError *error = NULL; + gchar *button_type = + xfpm_hal_get_string_info(priv->hal,udi[i],"button.type",&error); + if ( error ) + { + XFPM_DEBUG(":%s\n",error->message); + g_error_free(error); + continue; + } + if ( button_type) + { + _check_button(priv,button_type,udi[i]); + libhal_free_string(button_type); + } + } + } +#ifdef DEBUG + gchar *content1; + gchar *content2; + + GValue value = { 0, }; + g_value_init(&value,G_TYPE_BOOLEAN); + + g_value_set_boolean(&value,priv->have_lid_bt); + content1 = g_strdup_value_contents(&value); + + g_value_set_boolean(&value,priv->lid_button_has_state); + content2 = g_strdup_value_contents(&value); + + XFPM_DEBUG("LID Switch found = %s has_state = %s\n",content1,content2); + g_free(content1); + g_free(content2); + + g_value_set_boolean(&value,priv->have_power_bt); + content1 = g_strdup_value_contents(&value); + + g_value_set_boolean(&value,priv->power_button_has_state); + content2 = g_strdup_value_contents(&value); + + XFPM_DEBUG("Power Switch found = %s has_state = %s\n",content1,content2); + g_free(content1); + g_free(content2); + + g_value_set_boolean(&value,priv->have_sleep_bt); + content1 = g_strdup_value_contents(&value); + + g_value_set_boolean(&value,priv->sleep_button_has_state); + content2 = g_strdup_value_contents(&value); + + XFPM_DEBUG("Sleep Switch found = %s has_state = %s\n",content1,content2); + g_free(content1); + g_free(content2); +#endif + libhal_free_string_array(udi); +} + +XfpmButton * +xfpm_button_new(void) +{ + XfpmButton *bt; + bt = g_object_new(XFPM_TYPE_BUTTON,NULL); + return bt; +} + +guint8 +xfpm_button_get_available_buttons(XfpmButton *button) +{ + g_return_val_if_fail(XFPM_IS_BUTTON(button),0); + + XfpmButtonPrivate *priv; + priv = XFPM_BUTTON_GET_PRIVATE(button); + + guint8 buttons = 0; + + if ( priv->have_lid_bt ) + { + buttons |= LID_SWITCH; + } + if ( priv->have_power_bt ) + { + buttons |= POWER_SWITCH; + } + if ( priv->have_sleep_bt ) + { + buttons |= SLEEP_SWITCH; + } + + return buttons; +} + +void +xfpm_button_set_sleep_info (XfpmButton *button,guint8 sleep_info) +{ + g_return_if_fail(XFPM_IS_BUTTON(button)); + XfpmButtonPrivate *priv; + priv = XFPM_BUTTON_GET_PRIVATE(button); + + priv->sleep_info = sleep_info; +} |