#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <errno.h>
#include "config.h"
#ifdef USE_UDEV
#include <poll.h>
#include <libudev.h>
#endif
char *eights[] = { "ø", "▁", "▂", "▃", "▄", "▅", "▆","▇", "█" };
char *catfile(char *name) {
struct stat buffer;
int status;
int f;
char* resbuf;
f = open(name, O_RDONLY);
if (f == -1) return NULL;
status = fstat(f, &buffer);
if (status != 0) return NULL;
resbuf = malloc(buffer.st_size+1);
if (resbuf == NULL) return NULL;
status = read(f,resbuf,buffer.st_size);
if (status == -1) {
free(resbuf);
return NULL;
}
if ((status>0)&&(resbuf[status-1]=='\n'))
resbuf[status-1]='\0';
resbuf[status]='\0';
return resbuf;
}
int catint(char *name) {
char *cont = catfile(name);
assert (cont != NULL);
int res = atoi(cont);
free(cont);
return res;
}
char *color_stop;
char *color_red;
char *color_orange;
char *color_green;
char *color_none;
static char *down_arrow = "↓";
char *color(int low,int mid,int rev,int value) {
if (value>mid) {
return rev ? color_red : color_green;
} else if (value>low) {
return color_orange;
}
return rev ? color_green : color_red;
}
int main(int argc, char *argv[]) {
if (argc<=1) {
fprintf(stderr, "Usage: %s <BAT1> [term|pango]\n", argv[0]);
fflush(stderr);
return 1;
}
char *arrow_color;
char *eights_color;
char *percent_color;
char *remtimes_color;
if (argc>2 && !strcmp(argv[2],"term")) {
color_stop = "\x1b[0m";
color_red = "\x1b[1;31m";
color_green = "\x1b[1;32m";
color_orange = "\x1b[1;33m";
color_none = color_stop;
} else if (argc>2 && !strcmp(argv[2],"pango")) {
color_stop = "</span>";
color_red = "<span color='#f33'>";
color_green = "<span color='#0f0'>";
color_orange = "<span color='#fa0'>";
color_none = "<span>";
} else {
color_stop = color_red = color_green = color_orange = color_none = "";
}
#ifdef USE_UDEV
struct udev *udev;
struct udev_device *dev;
struct udev_monitor *mon;
int mon_fd;
udev = udev_new();
if (!udev) {
printf("Can't create udev\n");
exit(1);
}
mon = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(mon, "power_supply", NULL);
udev_monitor_enable_receiving(mon);
mon_fd = udev_monitor_get_fd(mon);
static struct pollfd fds[1];
fds[0].fd = mon_fd;
fds[0].events = POLLIN;
#endif
char filename[PATH_MAX+1];
snprintf(filename,PATH_MAX,"/sys/class/power_supply/%s/energy_now",argv[1]);
struct stat st;
int energy = 0==stat(filename, &st);
int sleeptime = UPDATE_PERIOD;
#ifdef DRAIN_THE_FUCK
int alertflash = 1;
#endif
while (1) {
snprintf(filename,PATH_MAX,"/sys/class/power_supply/%s/%s_now",argv[1], energy ? "energy" : "charge");
int charge_now = catint(filename);
snprintf(filename,PATH_MAX,"/sys/class/power_supply/%s/%s_now",argv[1], energy ? "power" : "current");
int current_now = catint(filename);
snprintf(filename,PATH_MAX,"/sys/class/power_supply/%s/%s_full",argv[1], energy ? "energy" : "charge");
int charge_full = catint(filename);
snprintf(filename,PATH_MAX,"/sys/class/power_supply/%s/status",argv[1]);
char *status = catfile(filename);
int remtime = 0;
char *arrow = "—";
arrow_color = color_none;
remtimes_color = color_green;
if (!strcmp(status,"Charging")) {
if (current_now != 0) {
remtime = (charge_full-charge_now) / (current_now/60);
arrow = "↑";
arrow_color = color_orange;
}
}
else if (!strcmp(status,"Discharging")) {
if (current_now != 0) {
remtime = charge_now / (current_now/60);
arrow = down_arrow;
arrow_color = color_none;
remtimes_color = color(20,120,0,remtime);
}
}
free(status);
int percent = charge_now/(charge_full/100);
eights_color = percent_color = color(15,40,0,percent);
printf("%s%s%s ",eights_color,eights[charge_now*8/charge_full],color_stop);
printf("%s%d%%%s ",percent_color,percent,color_stop);
printf("%s%s%s ",arrow_color,arrow,color_stop);
#ifdef DRAIN_THE_FUCK
if ((remtime < 20)&&(arrow == down_arrow)) {
sleeptime = 1;
alertflash = !alertflash;
} else {
sleeptime = UPDATE_PERIOD;
alertflash = 1;
}
if (alertflash) {
#endif
printf("%s%d:%02d%s\n",remtimes_color, remtime/60, remtime%60, color_stop);
#ifdef DRAIN_THE_FUCK
} else {
printf("%s·:··%s\n",remtimes_color, color_stop);
}
#endif
fflush(stdout);
#ifdef USE_UDEV
int poll_status = poll(fds,1, sleeptime*1000);
if (poll_status < 0) {
if (poll_status != EINTR) {
perror("poll");
exit(12);
}
}
if (fds[0].revents & POLLIN) {
dev = udev_monitor_receive_device(mon);
if (dev) {
udev_device_unref(dev);
} else {
printf("UDEV DC\n");
exit(13);
}
}
#else
sleep(sleeptime);
#endif
}
}