Re: ACPI support for battery_applet.
- From: jacob berkman <jacob ximian com>
- To: Justin Buist <jbuist tridenttechnology com>
- Cc: gnome-devel <gnome-devel-list gnome org>
- Subject: Re: ACPI support for battery_applet.
- Date: 11 Dec 2001 15:28:21 -0500
On Tue, 2001-12-11 at 14:21, Justin Buist wrote:
>
> Most every patch I've seen to put ACPI support into battery_applet only assumed
> that the user would have one battery, so I put together one that should
> accomodate as many batteries as possible. If APM is there it falls back
> to ACPI rather than have to pick APM or ACPI at compile time. It's working
> for me, though I admit the CPU usage seems a bit high on it right now.
i've got some acpi code for an applet i wrote over thanksgiving which i
haven't released yet.
the code is very simple; i've attached it in case you want to use it in
a patch to battstat.
jacob
--
"In fact, can you imagine anything more terrifying than a zombie clown?"
-- moby
/*
* acpi-battery.c: stuff for reading battery status from acpi
*
* Copyright 2001 jacob berkman
*
* Authors: jacob berkman <jacob ximian com>
*
*/
#define _GNU_SOURCE
#include <config.h>
#include "grungy-acpi-applet.h"
#include "thermometer-applet.h"
#include <glib.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#define BATTERY_DIR "/proc/acpi/battery"
typedef enum {
BATTERY_UNKNOWN,
BATTERY_DISCHARGING,
BATTERY_CHARGING,
BATTERY_CRITICALLY_LOW,
} BatteryState;
typedef struct {
gboolean present;
long design_capacity;
long last_full_capacity;
long remaining_capacity;
long present_rate;
long battery_voltage;
BatteryState state;
} BatteryInfo;
#if 0
static int battery_changed = 1;
static void
handler (int sig, siginfo_t *si, gpointer data)
{
battery_changed = 1;
}
#endif
#define BATT_BUFSIZE 8192
static GHashTable *
read_file (const char *bname, const char *fname, char *buf, int bufsize)
{
GHashTable *hash = NULL;
int fd, len, i;
char *file;
char *key, *value;
gboolean reading_key;
file = g_strdup_printf (BATTERY_DIR "/%s/%s", bname, fname);
fd = open (file, O_RDONLY);
if (fd == -1) {
g_message ("Couldn't open %s: %s", file, g_strerror (errno));
g_free (file);
return hash;
}
len = read (fd, buf, bufsize);
close (fd);
if (len < 0) {
g_message ("Error reading %s: %s", file, g_strerror (errno));
g_free (file);
return hash;
}
hash = g_hash_table_new (g_str_hash, g_str_equal);
for (i = 0, value = key = buf, reading_key = TRUE; i < len; i++) {
if (buf[i] == ':' && reading_key) {
reading_key = FALSE;
buf[i] = '\0';
value = buf + i + 1;
} else if (buf[i] == '\n') {
reading_key = TRUE;
buf[i] = '\0';
/* g_message ("Read: %s => %s\n", key, value); */
g_hash_table_insert (hash, key, g_strstrip (value));
key = buf + i + 1;
}
}
return hash;
}
static gboolean
read_bool (GHashTable *hash, const char *key)
{
char *s;
g_return_val_if_fail (hash, FALSE);
g_return_val_if_fail (key, FALSE);
s = g_hash_table_lookup (hash, key);
return s && (*s == 'y');
}
static long
read_long (GHashTable *hash, const char *key)
{
char *s;
g_return_val_if_fail (hash, FALSE);
g_return_val_if_fail (key, FALSE);
s = g_hash_table_lookup (hash, key);
return s ? strtol (s, NULL, 10) : 0;
}
static BatteryState
read_state (GHashTable *hash, const char *key)
{
BatteryState state;
char *s;
g_return_val_if_fail (hash, FALSE);
g_return_val_if_fail (key, FALSE);
s = g_hash_table_lookup (hash, key);
if (!s)
state = BATTERY_UNKNOWN;
else if (!strcmp (s, "charging"))
state = BATTERY_CHARGING;
else if (!strcmp (s, "discharging"))
state = BATTERY_DISCHARGING;
else if (!strcmp (s, "critically low"))
state = BATTERY_CRITICALLY_LOW;
else
state = BATTERY_UNKNOWN;
return state;
}
static BatteryInfo *
read_battery (const char *bname)
{
GHashTable *info, *status = NULL;
BatteryInfo *binfo = NULL;
char info_buf[BATT_BUFSIZE], status_buf[BATT_BUFSIZE];
/* g_print ("reading: %s\n", bname); */
info = read_file (bname, "info", info_buf, BATT_BUFSIZE);
if (!info)
goto read_battery_done;
status = read_file (bname, "status", status_buf, BATT_BUFSIZE);
if (!status)
goto read_battery_done;
binfo = g_new0 (BatteryInfo, 1);
binfo->present = read_bool (info, "Present");
binfo->design_capacity = read_long (info, "Design Capacity");
binfo->last_full_capacity = read_long (info, "Last Full Capacity");
binfo->remaining_capacity = read_long (status, "Remaining Capacity");
binfo->present_rate = read_long (status, "Present Rate");
binfo->battery_voltage = read_long (status, "Battery Voltage");
binfo->state = read_state (status, "State");
read_battery_done:
if (info)
g_hash_table_destroy (info);
if (status)
g_hash_table_destroy (status);
return binfo;
}
static void
print_battery (BatteryInfo *info)
{
static const char *state_name[] = { "Unknown", "Discharging", "Charging", "Critically Low" };
g_print ("Present: %s\n"
"Charge: %ld of %ld (%f%%)\n"
"State: %s\n",
info->present ? "Yes" : "No",
info->remaining_capacity, info->design_capacity,
(float)info->remaining_capacity / (float)info->design_capacity,
state_name[info->state]);
}
static void
battery_update (ThermometerApplet *applet, gpointer data)
{
DIR *dir;
struct dirent *dent;
BatteryInfo *info = NULL;
int percent;
char *s;
dir = opendir (BATTERY_DIR);
if (!dir) {
g_message ("error opending battery dir: %s\n",
g_strerror (errno));
return;
}
while ((dent = readdir (dir))) {
if (*dent->d_name == '.')
continue;
info = read_battery (dent->d_name);
if (info)
break;
}
closedir (dir);
if (!info)
return;
/* print_battery (info); */
if (info->present_rate) {
int minutes = 60 * info->remaining_capacity / info->present_rate;
s = g_strdup_printf ("%d:%.2d", minutes / 60, minutes % 60);
} else {
s = g_strdup (info->state == BATTERY_CHARGING
? "(AC)" : "");
}
percent = info->design_capacity ? 100.0 * ((float)info->remaining_capacity / info->design_capacity) : -1;
gtk_object_set (GTK_OBJECT (applet),
"text", s,
"percent", percent,
"color", info->state == BATTERY_CHARGING
? "black" : "red",
NULL);
}
GtkWidget *
grungy_acpi_battery_new (const char *goad_id)
{
GtkWidget *w;
w = thermometer_applet_new (goad_id);
if (!w) return NULL;
battery_update (THERMOMETER_APPLET (w), NULL);
gtk_object_set (GTK_OBJECT (w),
"timeout", 10000,
"timeout_cb", battery_update,
NULL);
return w;
}
#if 0
int
main (int argc, char *argv[])
{
GIOChannel *ioc;
struct sigaction act;
int fd;
act.sa_sigaction = handler;
sigemptyset (&act.sa_mask);
act.sa_flags = SA_SIGINFO;
sigaction (SIGRTMIN, &act, NULL);
fd = open (BATTERY_DIR, O_RDONLY);
if (fd == -1)
g_error ("No ACPI Support");
fcntl (fd, F_SETSIG, SIGRTMIN);
fcntl (fd, F_NOTIFY, DN_DELETE | DN_CREATE | DN_MULTISHOT);
reload_batteries ();
return 0;
while (1) {
if (battery_changed)
reload_batteries ();
pause ();
}
return 0;
}
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]