enlightenment/src/modules/battery/e_mod_main.c

1069 lines
27 KiB
C

/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#include "e.h"
#include "e_mod_main.h"
/* TODO List:
*
* which options should be in main menu, and which in face menu?
*/
/* module private routines */
static Battery *_battery_new();
static void _battery_shutdown(Battery *e);
static void _battery_config_menu_new(Battery *e);
static int _battery_cb_check(void *data);
static Status *_battery_linux_acpi_check(Battery *ef);
static Status *_battery_linux_apm_check(Battery *ef);
static Battery_Face *_battery_face_new(E_Container *con);
static void _battery_face_free(Battery_Face *ef);
static void _battery_face_menu_new(Battery_Face *face);
static void _battery_face_enable(Battery_Face *face);
static void _battery_face_disable(Battery_Face *face);
static void _battery_face_cb_gmc_change(void *data, E_Gadman_Client *gmc, E_Gadman_Change change);
static void _battery_face_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
static void _battery_face_level_set(Battery_Face *ef, double level);
static void _battery_face_cb_menu_enabled(void *data, E_Menu *m, E_Menu_Item *mi);
static void _battery_face_cb_menu_edit(void *data, E_Menu *m, E_Menu_Item *mi);
static E_Config_DD *conf_edd;
static E_Config_DD *conf_face_edd;
static int battery_count;
/* public module routines. all modules must have these */
void *
e_modapi_init(E_Module *m)
{
Battery *e;
/* check module api version */
if (m->api->version < E_MODULE_API_VERSION)
{
e_error_dialog_show(_("Module API Error"),
_("Error initializing Module: Battery\n"
"It requires a minimum module API version of: %i.\n"
"The module API advertized by Enlightenment is: %i.\n"
"Aborting module."),
E_MODULE_API_VERSION,
m->api->version);
return NULL;
}
/* actually init battery */
e = _battery_new();
m->config_menu = e->config_menu;
return e;
}
int
e_modapi_shutdown(E_Module *m)
{
Battery *e;
if (m->config_menu)
m->config_menu = NULL;
e = m->data;
if (e)
_battery_shutdown(e);
return 1;
}
int
e_modapi_save(E_Module *m)
{
Battery *e;
e = m->data;
e_config_domain_save("module.battery", conf_edd, e->conf);
return 1;
}
int
e_modapi_info(E_Module *m)
{
char buf[4096];
m->label = strdup(_("Battery"));
snprintf(buf, sizeof(buf), "%s/module_icon.png", e_module_dir_get(m));
m->icon_file = strdup(buf);
return 1;
}
int
e_modapi_about(E_Module *m)
{
e_error_dialog_show(_("Enlightenment Battery Module"),
_("A basic battery meter that uses either ACPI or APM\n"
"on Linux to monitor your battery and AC power adaptor\n"
"status. This will only work under Linux and is only\n"
"as accurate as your BIOS or kernel drivers."));
return 1;
}
/* module private routines */
static Battery *
_battery_new()
{
Battery *e;
Evas_List *managers, *l, *l2, *cl;
E_Menu_Item *mi;
battery_count = 0;
e = E_NEW(Battery, 1);
if (!e) return NULL;
conf_face_edd = E_CONFIG_DD_NEW("Battery_Config_Face", Config_Face);
#undef T
#undef D
#define T Config_Face
#define D conf_face_edd
E_CONFIG_VAL(D, T, enabled, UCHAR);
conf_edd = E_CONFIG_DD_NEW("Battery_Config", Config);
#undef T
#undef D
#define T Config
#define D conf_edd
E_CONFIG_VAL(D, T, poll_time, DOUBLE);
E_CONFIG_VAL(D, T, alarm, INT);
E_CONFIG_LIST(D, T, faces, conf_face_edd);
e->conf = e_config_domain_load("module.battery", conf_edd);
if (!e->conf)
{
e->conf = E_NEW(Config, 1);
e->conf->poll_time = 30.0;
e->conf->alarm = 30;
}
E_CONFIG_LIMIT(e->conf->poll_time, 0.5, 1000.0);
E_CONFIG_LIMIT(e->conf->alarm, 0, 60);
_battery_config_menu_new(e);
e->battery_check_mode = CHECK_NONE;
e->battery_prev_drain = 1;
e->battery_prev_ac = -1;
e->battery_prev_battery = -1;
e->battery_check_timer = ecore_timer_add(e->conf->poll_time, _battery_cb_check, e);
managers = e_manager_list();
cl = e->conf->faces;
for (l = managers; l; l = l->next)
{
E_Manager *man;
man = l->data;
for (l2 = man->containers; l2; l2 = l2->next)
{
E_Container *con;
Battery_Face *ef;
con = l2->data;
ef = _battery_face_new(con);
if (ef)
{
e->faces = evas_list_append(e->faces, ef);
/* Config */
if (!cl)
{
ef->conf = E_NEW(Config_Face, 1);
ef->conf->enabled = 1;
e->conf->faces = evas_list_append(e->conf->faces, ef->conf);
}
else
{
ef->conf = cl->data;
cl = cl->next;
}
/* Menu */
/* This menu must be initialized after conf */
_battery_face_menu_new(ef);
/* Add main menu to face menu */
mi = e_menu_item_new(ef->menu);
e_menu_item_label_set(mi, _("Set Poll Time"));
e_menu_item_submenu_set(mi, e->config_menu_poll);
mi = e_menu_item_new(ef->menu);
e_menu_item_label_set(mi, _("Set Alarm"));
e_menu_item_submenu_set(mi, e->config_menu_alarm);
mi = e_menu_item_new(e->config_menu);
e_menu_item_label_set(mi, con->name);
e_menu_item_submenu_set(mi, ef->menu);
/* Setup */
if (!ef->conf->enabled)
_battery_face_disable(ef);
}
}
}
_battery_cb_check(e);
return e;
}
static void
_battery_shutdown(Battery *e)
{
Evas_List *l;
E_CONFIG_DD_FREE(conf_edd);
E_CONFIG_DD_FREE(conf_face_edd);
for (l = e->faces; l; l = l->next)
_battery_face_free(l->data);
evas_list_free(e->faces);
e_object_del(E_OBJECT(e->config_menu));
e_object_del(E_OBJECT(e->config_menu_poll));
e_object_del(E_OBJECT(e->config_menu_alarm));
ecore_timer_del(e->battery_check_timer);
evas_list_free(e->conf->faces);
free(e->conf);
free(e);
}
static void
_battery_menu_alarm_10(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery *e;
e = data;
e->conf->alarm = 10;
e_config_save_queue();
}
static void
_battery_menu_alarm_20(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery *e;
e = data;
e->conf->alarm = 20;
e_config_save_queue();
}
static void
_battery_menu_alarm_30(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery *e;
e = data;
e->conf->alarm = 30;
e_config_save_queue();
}
static void
_battery_menu_alarm_40(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery *e;
e = data;
e->conf->alarm = 40;
e_config_save_queue();
}
static void
_battery_menu_alarm_50(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery *e;
e = data;
e->conf->alarm = 50;
e_config_save_queue();
}
static void
_battery_menu_alarm_60(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery *e;
e = data;
e->conf->alarm = 60;
e_config_save_queue();
}
static void
_battery_menu_alarm_disable(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery *e;
e = data;
e->conf->alarm = 0;
e_config_save_queue();
}
static void
_battery_menu_fast(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery *e;
e = data;
e->conf->poll_time = 1.0;
ecore_timer_del(e->battery_check_timer);
e->battery_check_timer = ecore_timer_add(e->conf->poll_time, _battery_cb_check, e);
e_config_save_queue();
}
static void
_battery_menu_medium(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery *e;
e = data;
e->conf->poll_time = 5.0;
ecore_timer_del(e->battery_check_timer);
e->battery_check_timer = ecore_timer_add(e->conf->poll_time, _battery_cb_check, e);
e_config_save_queue();
}
static void
_battery_menu_normal(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery *e;
e = data;
e->conf->poll_time = 10.0;
ecore_timer_del(e->battery_check_timer);
e->battery_check_timer = ecore_timer_add(e->conf->poll_time, _battery_cb_check, e);
e_config_save_queue();
}
static void
_battery_menu_slow(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery *e;
e = data;
e->conf->poll_time = 30.0;
ecore_timer_del(e->battery_check_timer);
e->battery_check_timer = ecore_timer_add(e->conf->poll_time, _battery_cb_check, e);
e_config_save_queue();
}
static void
_battery_menu_very_slow(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery *e;
e = data;
e->conf->poll_time = 60.0;
ecore_timer_del(e->battery_check_timer);
e->battery_check_timer = ecore_timer_add(e->conf->poll_time, _battery_cb_check, e);
e_config_save_queue();
}
static void
_battery_config_menu_new(Battery *e)
{
E_Menu *mn;
E_Menu_Item *mi;
/* Alarm */
mn = e_menu_new();
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, "Disable");
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (e->conf->alarm == 0) e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _battery_menu_alarm_disable, e);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, "10 mins");
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (e->conf->alarm == 10) e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _battery_menu_alarm_10, e);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, "20 mins");
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (e->conf->alarm == 20) e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _battery_menu_alarm_20, e);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, "30 mins");
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (e->conf->alarm == 30) e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _battery_menu_alarm_30, e);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, "40 mins");
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (e->conf->alarm == 40) e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _battery_menu_alarm_40, e);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, "50 mins");
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (e->conf->alarm == 50) e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _battery_menu_alarm_50, e);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("1 hour"));
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (e->conf->alarm == 60) e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _battery_menu_alarm_60, e);
e->config_menu_alarm = mn;
/* Check interval */
mn = e_menu_new();
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Check Fast (1 sec)"));
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (e->conf->poll_time == 1.0) e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _battery_menu_fast, e);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Check Medium (5 sec)"));
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (e->conf->poll_time == 5.0) e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _battery_menu_medium, e);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Check Normal (10 sec)"));
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (e->conf->poll_time == 10.0) e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _battery_menu_normal, e);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Check Slow (30 sec)"));
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (e->conf->poll_time == 30.0) e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _battery_menu_slow, e);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Check Very Slow (60 sec)"));
e_menu_item_radio_set(mi, 1);
e_menu_item_radio_group_set(mi, 1);
if (e->conf->poll_time == 60.0) e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _battery_menu_very_slow, e);
e->config_menu_poll = mn;
mn = e_menu_new();
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Set Poll Time"));
e_menu_item_submenu_set(mi, e->config_menu_poll);
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Set Alarm"));
e_menu_item_submenu_set(mi, e->config_menu_alarm);
e->config_menu = mn;
}
static Battery_Face *
_battery_face_new(E_Container *con)
{
Evas_Object *o;
Battery_Face *ef;
ef = E_NEW(Battery_Face, 1);
if (!ef) return NULL;
ef->con = con;
e_object_ref(E_OBJECT(con));
evas_event_freeze(con->bg_evas);
o = edje_object_add(con->bg_evas);
ef->bat_object = o;
edje_object_file_set(o,
/* FIXME: "default.edj" needs to come from conf */
e_path_find(path_themes, "default.edj"),
"modules/battery/main");
evas_object_show(o);
o = evas_object_rectangle_add(con->bg_evas);
ef->event_object = o;
evas_object_layer_set(o, 2);
evas_object_repeat_events_set(o, 1);
evas_object_color_set(o, 0, 0, 0, 0);
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _battery_face_cb_mouse_down, ef);
evas_object_show(o);
ef->gmc = e_gadman_client_new(con->gadman);
e_gadman_client_domain_set(ef->gmc, "module.battery", battery_count++);
e_gadman_client_policy_set(ef->gmc,
E_GADMAN_POLICY_ANYWHERE |
E_GADMAN_POLICY_HMOVE |
E_GADMAN_POLICY_VMOVE |
E_GADMAN_POLICY_HSIZE |
E_GADMAN_POLICY_VSIZE);
e_gadman_client_min_size_set(ef->gmc, 4, 4);
e_gadman_client_max_size_set(ef->gmc, 128, 128);
e_gadman_client_auto_size_set(ef->gmc, 40, 40);
e_gadman_client_align_set(ef->gmc, 1.0, 1.0);
e_gadman_client_resize(ef->gmc, 40, 40);
e_gadman_client_change_func_set(ef->gmc, _battery_face_cb_gmc_change, ef);
e_gadman_client_load(ef->gmc);
evas_event_thaw(con->bg_evas);
return ef;
}
static void
_battery_face_free(Battery_Face *ef)
{
e_object_unref(E_OBJECT(ef->con));
e_object_del(E_OBJECT(ef->gmc));
e_object_del(E_OBJECT(ef->menu));
evas_object_del(ef->bat_object);
evas_object_del(ef->event_object);
free(ef->conf);
free(ef);
battery_count--;
}
static void
_battery_face_menu_new(Battery_Face *face)
{
E_Menu *mn;
E_Menu_Item *mi;
mn = e_menu_new();
face->menu = mn;
/* Enabled */
/*
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Enabled"));
e_menu_item_check_set(mi, 1);
if (face->conf->enabled) e_menu_item_toggle_set(mi, 1);
e_menu_item_callback_set(mi, _battery_face_cb_menu_enabled, face);
*/
/* Edit */
mi = e_menu_item_new(mn);
e_menu_item_label_set(mi, _("Edit Mode"));
e_menu_item_callback_set(mi, _battery_face_cb_menu_edit, face);
}
static void
_battery_face_enable(Battery_Face *face)
{
face->conf->enabled = 1;
evas_object_show(face->bat_object);
evas_object_show(face->event_object);
e_config_save_queue();
}
static void
_battery_face_disable(Battery_Face *face)
{
face->conf->enabled = 0;
evas_object_hide(face->bat_object);
evas_object_hide(face->event_object);
e_config_save_queue();
}
static void
_battery_face_cb_gmc_change(void *data, E_Gadman_Client *gmc, E_Gadman_Change change)
{
Battery_Face *ef;
Evas_Coord x, y, w, h;
ef = data;
switch (change)
{
case E_GADMAN_CHANGE_MOVE_RESIZE:
e_gadman_client_geometry_get(ef->gmc, &x, &y, &w, &h);
evas_object_move(ef->bat_object, x, y);
evas_object_move(ef->event_object, x, y);
evas_object_resize(ef->bat_object, w, h);
evas_object_resize(ef->event_object, w, h);
break;
case E_GADMAN_CHANGE_RAISE:
evas_object_raise(ef->bat_object);
evas_object_raise(ef->event_object);
break;
case E_GADMAN_CHANGE_EDGE:
case E_GADMAN_CHANGE_ZONE:
/* FIXME
* Must we do something here?
*/
break;
}
}
static void
_battery_face_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
Evas_Event_Mouse_Down *ev;
Battery_Face *ef;
ev = event_info;
ef = data;
if (ev->button == 3)
{
e_menu_activate_mouse(ef->menu, e_zone_current_get(ef->con),
ev->output.x, ev->output.y, 1, 1,
E_MENU_POP_DIRECTION_DOWN);
e_util_container_fake_mouse_up_all_later(ef->con);
}
}
static int
_battery_cb_check(void *data)
{
Battery *ef;
Battery_Face *face;
Evas_List *l;
Status *ret = NULL;
ef = data;
if (ef->battery_check_mode == 0)
{
if (ecore_file_is_dir("/proc/acpi"))
ef->battery_check_mode = CHECK_LINUX_ACPI;
else if (ecore_file_exists("/proc/apm"))
ef->battery_check_mode = CHECK_LINUX_APM;
}
switch (ef->battery_check_mode)
{
case CHECK_LINUX_ACPI:
ret = _battery_linux_acpi_check(ef);
break;
case CHECK_LINUX_APM:
ret = _battery_linux_apm_check(ef);
break;
default:
break;
}
if (ret)
{
if (ret->has_battery)
{
if (ret->state == BATTERY_STATE_CHARGING)
{
for (l = ef->faces; l; l = l->next)
{
face = l->data;
if (ef->battery_prev_ac != 1)
edje_object_signal_emit(face->bat_object, "charge", "");
edje_object_signal_emit(face->bat_object, "pulsestop", "");
edje_object_part_text_set(face->bat_object, "reading", ret->reading);
edje_object_part_text_set(face->bat_object, "time", ret->time);
_battery_face_level_set(face, ret->level);
}
ef->battery_prev_ac = 1;
}
else if (ret->state == BATTERY_STATE_DISCHARGING)
{
for (l = ef->faces; l; l = l->next)
{
face = l->data;
if (ef->battery_prev_ac != 0)
edje_object_signal_emit(face->bat_object, "discharge", "");
if (ret->alarm)
{
if (!ef->alarm_triggered)
{
e_error_dialog_show(_("Battery Running Low"),
_("Your battery is running low.\n"
"You may wish to switch to an AC source."));
}
edje_object_signal_emit(face->bat_object, "pulse", "");
}
edje_object_part_text_set(face->bat_object, "reading", ret->reading);
edje_object_part_text_set(face->bat_object, "time", ret->time);
_battery_face_level_set(face, ret->level);
}
ef->battery_prev_ac = 0;
if (ret->alarm)
ef->alarm_triggered = 1;
}
else
{
/* ret->state == BATTERY_STATE_NONE */
for (l = ef->faces; l; l = l->next)
{
face = l->data;
if (ef->battery_prev_ac != 1)
edje_object_signal_emit(face->bat_object, "charge", "");
if (ef->battery_prev_battery == 0)
edje_object_signal_emit(face->bat_object, "charge", "");
edje_object_part_text_set(face->bat_object, "reading", ret->reading);
edje_object_part_text_set(face->bat_object, "time", ret->time);
_battery_face_level_set(face, ret->level);
}
ef->battery_prev_ac = 1;
ef->battery_prev_battery = 1;
}
}
else
{
/* Hasn't battery */
for (l = ef->faces; l; l = l->next)
{
face = l->data;
if (ef->battery_prev_battery != 0)
edje_object_signal_emit(face->bat_object, "unknown", "");
edje_object_part_text_set(face->bat_object, "reading", ret->reading);
edje_object_part_text_set(face->bat_object, "time", ret->time);
_battery_face_level_set(face, ret->level);
}
ef->battery_prev_battery = 0;
}
free(ret->reading);
free(ret->time);
free(ret);
}
else
{
/* Error reading status */
for (l = ef->faces; l; l = l->next)
{
face = l->data;
if (ef->battery_prev_battery != -2)
edje_object_signal_emit(face->bat_object, "unknown", "");
edje_object_part_text_set(face->bat_object, "reading", _("NO INFO"));
edje_object_part_text_set(face->bat_object, "time", "--:--");
_battery_face_level_set(face, (double)(rand() & 0xff) / 255.0);
}
ef->battery_prev_battery = -2;
ef->battery_check_mode = CHECK_NONE;
}
return 1;
}
static Status *
_battery_linux_acpi_check(Battery *ef)
{
Evas_List *bats;
char buf[4096], buf2[4096];
int bat_max = 0;
int bat_filled = 0;
int bat_level = 0;
int bat_drain = 1;
int bat_val = 0;
int discharging = 0;
int charging = 0;
int battery = 0;
int design_cap_unknown = 0;
int last_full_unknown = 0;
int rate_unknown = 0;
int level_unknown = 0;
int hours, minutes;
Status *stat;
stat = E_NEW(Status, 1);
/* Read some information on first run. */
bats = ecore_file_ls("/proc/acpi/battery");
while (bats)
{
FILE *f;
char *name;
name = bats->data;
bats = evas_list_remove_list(bats, bats);
if ((!strcmp(name, ".")) || (!strcmp(name, "..")))
{
free(name);
continue;
}
snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/info", name);
f = fopen(buf, "r");
if (f)
{
int design_cap = 0;
int last_full = 0;
fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0;
fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0;
sscanf(buf2, "%*[^:]: %250s %*s", buf);
if (!strcmp(buf, "unknown")) design_cap_unknown = 1;
else sscanf(buf2, "%*[^:]: %i %*s", &design_cap);
fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0;
sscanf(buf2, "%*[^:]: %250s %*s", buf);
if (!strcmp(buf, "unknown")) last_full_unknown = 1;
else sscanf(buf2, "%*[^:]: %i %*s", &last_full);
fclose(f);
bat_max += design_cap;
bat_filled += last_full;
}
snprintf(buf, sizeof(buf), "/proc/acpi/battery/%s/state", name);
f = fopen(buf, "r");
if (f)
{
char present[256];
char capacity_state[256];
char charging_state[256];
int rate = 1;
int level = 0;
fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0;
sscanf(buf2, "%*[^:]: %250s", present);
fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0;
sscanf(buf2, "%*[^:]: %250s", capacity_state);
fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0;
sscanf(buf2, "%*[^:]: %250s", charging_state);
fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0;
sscanf(buf2, "%*[^:]: %250s %*s", buf);
if (!strcmp(buf, "unknown")) rate_unknown = 1;
else sscanf(buf2, "%*[^:]: %i %*s", &rate);
fgets(buf2, sizeof(buf2), f); buf2[sizeof(buf2) - 1] = 0;
sscanf(buf2, "%*[^:]: %250s %*s", buf);
if (!strcmp(buf, "unknown")) level_unknown = 1;
else sscanf(buf2, "%*[^:]: %i %*s", &level);
fclose(f);
if (!strcmp(present, "yes")) battery++;
if (!strcmp(charging_state, "discharging")) discharging++;
if (!strcmp(charging_state, "charging")) charging++;
if (!strcmp(charging_state, "charged")) rate_unknown = 0;
bat_drain += rate;
bat_level += level;
}
free(name);
}
if (ef->battery_prev_drain < 1) ef->battery_prev_drain = 1;
if (bat_drain < 1) bat_drain = ef->battery_prev_drain;
ef->battery_prev_drain = bat_drain;
if (bat_filled > 0) bat_val = (100 * bat_level) / bat_filled;
else bat_val = 100;
if (discharging) minutes = (60 * bat_level) / bat_drain;
else
{
if (bat_filled > 0)
minutes = (60 * (bat_filled - bat_level)) / bat_drain;
else
minutes = 0;
}
hours = minutes / 60;
minutes -= (hours * 60);
if (hours < 0) hours = 0;
if (minutes < 0) minutes = 0;
if (!battery)
{
stat->has_battery = 0;
stat->state = BATTERY_STATE_NONE;
stat->reading = strdup(_("NO BAT"));
stat->time = strdup("--:--");
stat->level = 1.0;
}
else if ((charging) || (discharging))
{
ef->battery_prev_battery = 1;
stat->has_battery = 1;
if (charging)
{
stat->state = BATTERY_STATE_CHARGING;
ef->alarm_triggered = 0;
}
else if (discharging)
{
stat->state = BATTERY_STATE_DISCHARGING;
if (stat->level < 0.1)
{
if (((hours * 60) + minutes) <= ef->conf->alarm)
stat->alarm = 1;
}
}
if (level_unknown)
{
stat->reading = strdup(_("BAD DRIVER"));
stat->time = strdup("--:--");
stat->level = 0.0;
}
else if (rate_unknown)
{
snprintf(buf, sizeof(buf), "%i%%", bat_val);
stat->reading = strdup(buf);
stat->time = strdup("--:--");
stat->level = (double)bat_val / 100.0;
}
else
{
snprintf(buf, sizeof(buf), "%i%%", bat_val);
stat->reading = strdup(buf);
snprintf(buf, sizeof(buf), "%i:%02i", hours, minutes);
stat->time = strdup(buf);
stat->level = (double)bat_val / 100.0;
}
}
else
{
stat->has_battery = 1;
stat->state = BATTERY_STATE_NONE;
stat->reading = strdup(_("FULL"));
stat->time = strdup("--:--");
stat->level = 1.0;
}
return stat;
}
static Status *
_battery_linux_apm_check(Battery *ef)
{
FILE *f;
char s[256], s1[32], s2[32], s3[32], buf[4096];
int apm_flags, ac_stat, bat_stat, bat_flags, bat_val, time_val;
int hours, minutes;
Status *stat;
f = fopen("/proc/apm", "r");
if (!f) return NULL;
fgets(s, sizeof(s), f); s[sizeof(s) - 1] = 0;
if (sscanf(s, "%*s %*s %x %x %x %x %s %s %s",
&apm_flags, &ac_stat, &bat_stat, &bat_flags, s1, s2, s3) != 7)
{
fclose(f);
return NULL;
}
s1[strlen(s1) - 1] = 0;
bat_val = atoi(s1);
if (!strcmp(s3, "sec")) time_val = atoi(s2);
else if (!strcmp(s3, "min")) time_val = atoi(s2) * 60;
fclose(f);
stat = E_NEW(Status, 1);
if ((bat_flags != 0xff) && (bat_flags & 0x80))
{
stat->has_battery = 0;
stat->state = BATTERY_STATE_NONE;
stat->reading = strdup("NO BAT");
stat->time = strdup("--:--");
stat->level = 1.0;
return stat;
}
ef->battery_prev_battery = 1;
stat->has_battery = 1;
if (bat_val >= 0)
{
if (bat_val > 100) bat_val = 100;
snprintf(buf, sizeof(buf), "%i%%", bat_val);
stat->reading = strdup(buf);
stat->level = (double)bat_val / 100.0;
}
else
{
switch (bat_stat)
{
case 0:
stat->reading = strdup(_("High"));
stat->level = 1.0;
break;
case 1:
stat->reading = strdup(_("Low"));
stat->level = 0.5;
break;
case 2:
stat->reading = strdup(_("Danger"));
stat->level = 0.25;
break;
case 3:
stat->reading = strdup(_("Charging"));
stat->level = 1.0;
break;
}
}
if (ac_stat == 1)
{
stat->state = BATTERY_STATE_CHARGING;
stat->time = strdup("--:--");
}
else
{
/* ac_stat == 0 */
stat->state = BATTERY_STATE_DISCHARGING;
hours = time_val / 3600;
minutes = (time_val / 60) % 60;
snprintf(buf, sizeof(buf), "%i:%02i", hours, minutes);
stat->time = strdup(buf);
if (stat->level < 0.1)
{
if (((hours * 60) + minutes) <= ef->conf->alarm)
stat->alarm = 1;
}
}
return stat;
}
static void
_battery_face_level_set(Battery_Face *ef, double level)
{
Edje_Message_Float msg;
if (level < 0.0) level = 0.0;
else if (level > 1.0) level = 1.0;
msg.val = level;
edje_object_message_send(ef->bat_object, EDJE_MESSAGE_FLOAT, 1, &msg);
}
static void
_battery_face_cb_menu_enabled(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery_Face *face;
unsigned char enabled;
face = data;
enabled = e_menu_item_toggle_get(mi);
if ((face->conf->enabled) && (!enabled))
{
_battery_face_disable(face);
}
else if ((!face->conf->enabled) && (enabled))
{
_battery_face_enable(face);
}
}
static void
_battery_face_cb_menu_edit(void *data, E_Menu *m, E_Menu_Item *mi)
{
Battery_Face *face;
face = data;
e_gadman_mode_set(face->gmc->gadman, E_GADMAN_MODE_EDIT);
}