mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
422 lines
9.3 KiB
C++
422 lines
9.3 KiB
C++
// Battery monitor for EDE / eworkpanel
|
|
//
|
|
// Copyright (c) 2005. EDE Authors
|
|
//
|
|
// Based in part on xbattbar
|
|
// Copyright (c) 1998-2001 Suguru Yamaguchi <suguru@wide.ad.jp>
|
|
// http://iplab.aist-nara.ac.jp/member/suguru/xbattbar.html
|
|
//
|
|
// This program is licenced under terms of the
|
|
// GNU General Public Licence version 2 or newer.
|
|
// See COPYING for details.
|
|
|
|
#include "batterymonitor.h"
|
|
|
|
#include "icons/poweron.xpm"
|
|
#include "icons/battery.xpm"
|
|
|
|
#define UPDATE_INTERVAL .5f
|
|
|
|
void bat_timeout_cb(void *d) {
|
|
((BatteryMonitor*)d)->update_status();
|
|
Fl::repeat_timeout(UPDATE_INTERVAL, bat_timeout_cb, d);
|
|
}
|
|
|
|
BatteryMonitor::BatteryMonitor(Dock*dock)
|
|
: Fl_Widget(0,0,16,0)
|
|
{
|
|
box(FL_FLAT_BOX);
|
|
//box(FL_BORDER_BOX);
|
|
|
|
// edit this to show/hide the icon when power is plugged
|
|
m_show_line_on = true;
|
|
|
|
// initial values
|
|
m_line_on = true;
|
|
m_undefined = false;
|
|
m_bat_percentage = m_bat_time = 0;
|
|
m_blink = false;
|
|
|
|
m_dock = dock;
|
|
|
|
m_colors[2] = FL_BLUE;
|
|
m_colors[1] = fl_darker(FL_YELLOW);
|
|
m_colors[0] = FL_RED;
|
|
|
|
this->color(this->button_color());
|
|
Fl::add_timeout(UPDATE_INTERVAL, bat_timeout_cb, this);
|
|
}
|
|
|
|
BatteryMonitor::~BatteryMonitor() {
|
|
// clear();
|
|
}
|
|
|
|
void BatteryMonitor::clear()
|
|
{
|
|
/* if(!cpu) return;
|
|
|
|
for (int i=0; i < samples(); i++) {
|
|
delete cpu[i]; cpu[i] = 0;
|
|
}
|
|
delete cpu;
|
|
cpu = 0;
|
|
|
|
m_old_samples = -1;*/
|
|
}
|
|
|
|
void BatteryMonitor::draw()
|
|
{
|
|
if (m_undefined) {
|
|
// We don't draw anything for undefined state
|
|
m_dock->remove_from_tray(this);
|
|
return;
|
|
}
|
|
|
|
if (m_line_on) {
|
|
if (m_show_line_on) {
|
|
this->image(Fl_Image::read_xpm(0, (const char**)poweron_xpm));
|
|
Fl_Widget::draw();
|
|
}
|
|
return;
|
|
}
|
|
|
|
this->image(Fl_Image::read_xpm(0, (const char**)battery_xpm));
|
|
int pixels = (int) m_bat_percentage / 10;
|
|
if (pixels > 9) pixels=9; // if it's really 100%
|
|
|
|
// Blinking battery
|
|
if (pixels < 1) {
|
|
if (m_blink) {
|
|
this->image(0);
|
|
m_blink = false;
|
|
} else {
|
|
m_blink = true;
|
|
}
|
|
Fl_Widget::draw();
|
|
return;
|
|
}
|
|
Fl_Widget::draw();
|
|
|
|
int color = (int)m_bat_percentage / 34;
|
|
fl_color(m_colors[color]);
|
|
|
|
// Some magic constants follow - this is based on design of battery.xpm
|
|
int ddx = box()->dx();
|
|
int ddy = box()->dy();
|
|
fl_line (ddx+7, ddy+15-pixels, ddx+7, ddy+14);
|
|
fl_line (ddx+8, ddy+15-pixels, ddx+8, ddy+14);
|
|
fl_line (ddx+9, ddy+15-pixels, ddx+9, ddy+14);
|
|
|
|
}
|
|
|
|
void BatteryMonitor::layout()
|
|
{
|
|
update_status();
|
|
Fl_Widget::layout();
|
|
}
|
|
|
|
void BatteryMonitor::update_status()
|
|
{
|
|
battery_check();
|
|
|
|
// Update tooltip
|
|
char load[255];
|
|
if (m_undefined)
|
|
snprintf(load, sizeof(load)-1, _("Power management not detected"));
|
|
else if (m_line_on)
|
|
snprintf(load, sizeof(load)-1, _("The power is plugged in"));
|
|
else
|
|
snprintf(load, sizeof(load)-1,
|
|
_("Battery is %d%% full (%d minutes remaining)"), m_bat_percentage, m_bat_time);
|
|
tooltip(load);
|
|
}
|
|
|
|
// -------------------------------
|
|
// xbattbar.c,v 1.16.2.4 2001/02/02 05:25:29 suguru
|
|
//
|
|
// The following code is copied from xbattbar, with small modifications
|
|
// These modifications include:
|
|
// - p is now bool instead of int
|
|
// - we try to monitor remaining time, but it only works on linux (for now)
|
|
// - in case of error, m_undefined is set and function isn't executed
|
|
// anymore, until eworkpanel restart
|
|
// - signal() is removed - only redraw() is necessary
|
|
// - elapsed_time is removed
|
|
// - in struct apm_info (linux), had to replace const char with char
|
|
// -------------------------------
|
|
|
|
#ifdef __bsdi__
|
|
|
|
#include <machine/apm.h>
|
|
#include <machine/apmioctl.h>
|
|
|
|
int first = 1;
|
|
void BatteryMonitor::battery_check(void)
|
|
{
|
|
int fd;
|
|
struct apmreq ar ;
|
|
|
|
|
|
// No need to display error too many times
|
|
if (m_undefined) return;
|
|
|
|
ar.func = APM_GET_POWER_STATUS ;
|
|
ar.dev = APM_DEV_ALL ;
|
|
|
|
if ((fd = open(_PATH_DEVAPM, O_RDONLY)) < 0) {
|
|
perror(_PATH_DEVAPM) ;
|
|
m_undefined = true;
|
|
return;
|
|
}
|
|
if (ioctl(fd, PIOCAPMREQ, &ar) < 0) {
|
|
fprintf(stderr, "xbattbar: PIOCAPMREQ: APM_GET_POWER_STATUS error 0x%x\n", ar.err);
|
|
}
|
|
close (fd);
|
|
|
|
/* if (first || ac_line != ((ar.bret >> 8) & 0xff)
|
|
|| battery_level != (ar.cret&0xff)) {
|
|
first = 0;
|
|
ac_line = (ar.bret >> 8) & 0xff;
|
|
battery_level = ar.cret&0xff;
|
|
redraw();
|
|
}*/
|
|
|
|
// Feeble attempt at fixing bsdi
|
|
if (first || battery_level != (ar.cret&0xff)) {
|
|
first = 0;
|
|
// ac_line = (ar.bret >> 8) & 0xff;
|
|
battery_level = ar.cret&0xff;
|
|
m_line_on = false;
|
|
m_bat_time = 0;
|
|
redraw();
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* __bsdi__ */
|
|
|
|
#ifdef __FreeBSD__
|
|
|
|
#include <machine/apm_bios.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#define APMDEV21 "/dev/apm0"
|
|
#define APMDEV22 "/dev/apm"
|
|
|
|
#define APM_STAT_UNKNOWN 255
|
|
|
|
#define APM_STAT_LINE_OFF 0
|
|
#define APM_STAT_LINE_ON 1
|
|
|
|
#define APM_STAT_BATT_HIGH 0
|
|
#define APM_STAT_BATT_LOW 1
|
|
#define APM_STAT_BATT_CRITICAL 2
|
|
#define APM_STAT_BATT_CHARGING 3
|
|
|
|
int first = 1;
|
|
void BatteryMonitor::battery_check(void)
|
|
{
|
|
int fd, r;
|
|
bool p;
|
|
struct apm_info info;
|
|
|
|
// No need to display error too many times
|
|
if (m_undefined) return;
|
|
|
|
if ((fd = open(APMDEV21, O_RDWR)) == -1 &&
|
|
(fd = open(APMDEV22, O_RDWR)) == -1) {
|
|
fprintf(stderr, "xbattbar: cannot open apm device\n");
|
|
m_undefined = true;
|
|
return;
|
|
}
|
|
if (ioctl(fd, APMIO_GETINFO, &info) == -1) {
|
|
fprintf(stderr, "xbattbar: ioctl APMIO_GETINFO failed\n");
|
|
m_undefined = true;
|
|
return;
|
|
}
|
|
close (fd);
|
|
|
|
/* get current status */
|
|
if (info.ai_batt_life == APM_STAT_UNKNOWN) {
|
|
switch (info.ai_batt_stat) {
|
|
case APM_STAT_BATT_HIGH:
|
|
r = 100;
|
|
break;
|
|
case APM_STAT_BATT_LOW:
|
|
r = 40;
|
|
break;
|
|
case APM_STAT_BATT_CRITICAL:
|
|
r = 10;
|
|
break;
|
|
default: /* expected to be APM_STAT_UNKNOWN */
|
|
r = 100;
|
|
}
|
|
} else if (info.ai_batt_life > 100) {
|
|
/* some APM BIOSes return values slightly > 100 */
|
|
r = 100;
|
|
} else {
|
|
r = info.ai_batt_life;
|
|
}
|
|
|
|
/* get AC-line status */
|
|
if (info.ai_acline == APM_STAT_LINE_ON) {
|
|
p = true;
|
|
} else {
|
|
p = false;
|
|
}
|
|
|
|
if (first || m_line_on != p || m_bat_percentage != r) {
|
|
first = 0;
|
|
m_line_on = p;
|
|
m_bat_percentage = r;
|
|
m_bat_time = 0; //FIXME: battery time on FreeBSD
|
|
redraw();
|
|
}
|
|
}
|
|
|
|
#endif /* __FreeBSD__ */
|
|
|
|
#ifdef __NetBSD__
|
|
|
|
#include <machine/apmvar.h>
|
|
|
|
#define _PATH_APM_SOCKET "/var/run/apmdev"
|
|
#define _PATH_APM_CTLDEV "/dev/apmctl"
|
|
#define _PATH_APM_NORMAL "/dev/apm"
|
|
|
|
int first = 1;
|
|
void BatteryMonitor::battery_check(void)
|
|
{
|
|
int fd, r;
|
|
bool p;
|
|
struct apm_power_info info;
|
|
|
|
// No need to display error too many times
|
|
if (m_undefined) return;
|
|
|
|
if ((fd = open(_PATH_APM_NORMAL, O_RDONLY)) == -1) {
|
|
fprintf(stderr, "xbattbar: cannot open apm device\n");
|
|
m_undefined = true;
|
|
return;
|
|
}
|
|
|
|
if (ioctl(fd, APM_IOC_GETPOWER, &info) != 0) {
|
|
fprintf(stderr, "xbattbar: ioctl APM_IOC_GETPOWER failed\n");
|
|
m_undefined = true;
|
|
return;
|
|
}
|
|
|
|
close(fd);
|
|
|
|
/* get current remoain */
|
|
if (info.battery_life > 100) {
|
|
/* some APM BIOSes return values slightly > 100 */
|
|
r = 100;
|
|
} else {
|
|
r = info.battery_life;
|
|
}
|
|
|
|
/* get AC-line status */
|
|
if (info.ac_state == APM_AC_ON) {
|
|
p = true;
|
|
} else {
|
|
p = false;
|
|
}
|
|
|
|
if (first || m_line_on != p || m_bat_percentage != r) {
|
|
first = 0;
|
|
m_line_on = p;
|
|
m_bat_percentage = r;
|
|
m_bat_time = 0; //FIXME: battery time on netbsd
|
|
redraw();
|
|
}
|
|
}
|
|
|
|
#endif /* __NetBSD__ */
|
|
|
|
|
|
#ifdef linux
|
|
|
|
#include <errno.h>
|
|
#include <linux/apm_bios.h>
|
|
|
|
#define APM_PROC "/proc/apm"
|
|
|
|
#define APM_STAT_LINE_OFF 0
|
|
#define APM_STAT_LINE_ON 1
|
|
|
|
typedef struct apm_info {
|
|
char driver_version[10];
|
|
int apm_version_major;
|
|
int apm_version_minor;
|
|
unsigned int apm_flags;
|
|
unsigned int ac_line_status;
|
|
unsigned int battery_status;
|
|
unsigned int battery_flags;
|
|
int battery_percentage;
|
|
int battery_time;
|
|
int using_minutes;
|
|
} apm_info;
|
|
|
|
|
|
int first = 1;
|
|
void BatteryMonitor::battery_check(void)
|
|
{
|
|
int r;
|
|
bool p;
|
|
FILE *pt;
|
|
struct apm_info i;
|
|
char buf[100];
|
|
|
|
// No need to display error too many times
|
|
if (m_undefined) return;
|
|
|
|
/* get current status */
|
|
errno = 0;
|
|
if ( (pt = fopen( APM_PROC, "r" )) == NULL) {
|
|
fprintf(stderr, "xbattbar: Can't read proc info: %s\n", strerror(errno));
|
|
m_undefined = true;
|
|
return;
|
|
}
|
|
|
|
fgets( buf, sizeof( buf ) - 1, pt );
|
|
buf[ sizeof( buf ) - 1 ] = '\0';
|
|
sscanf( buf, "%s %d.%d %x %x %x %x %d%% %d %d\n",
|
|
(char*)&i.driver_version,
|
|
&i.apm_version_major,
|
|
&i.apm_version_minor,
|
|
&i.apm_flags,
|
|
&i.ac_line_status,
|
|
&i.battery_status,
|
|
&i.battery_flags,
|
|
&i.battery_percentage,
|
|
&i.battery_time,
|
|
&i.using_minutes );
|
|
|
|
fclose (pt);
|
|
|
|
/* some APM BIOSes return values slightly > 100 */
|
|
if ( (r = i.battery_percentage) > 100 ){
|
|
r = 100;
|
|
}
|
|
|
|
/* get AC-line status */
|
|
if ( i.ac_line_status == APM_STAT_LINE_ON) {
|
|
p = true;
|
|
} else {
|
|
p = false;
|
|
}
|
|
|
|
if (first || m_line_on != p || m_bat_percentage != r) {
|
|
first = 0;
|
|
m_line_on = p;
|
|
m_bat_percentage = r;
|
|
m_bat_time = i.battery_time;
|
|
redraw();
|
|
}
|
|
}
|
|
|
|
#endif /* linux */
|
|
|