This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
quick-text-bar/modules/battery.c

154 lines
4.2 KiB
C
Raw Permalink Normal View History

2022-08-28 14:27:03 -07:00
#include "battery.h"
#include "../util.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ADAPTER_BASE_PATH "/sys/class/power_supply/"
#define BATTERY_PATH "/sys/class/power_supply/BAT0"
static const char *adapter_search_names[] = {"AC0", "ADP1"};
static size_t adapter_search_names_count =
sizeof(adapter_search_names) / sizeof(char *);
static char *adapter_status_path;
static int max_batery_charge;
static int show_notifiaction = TRUE;
static void find_max_battery_charge() {
FILE *max_file = fopen(BATTERY_PATH "/charge_full", "r");
fseeko(max_file, 0, SEEK_END);
off_t len = ftello(max_file);
rewind(max_file);
char text[len + 1];
text[len] = '\0';
fread(text, 1, len, max_file);
max_batery_charge = strtoul(text, NULL, 10);
fclose(max_file);
}
static int is_battery_full() {
FILE *status_file = fopen(BATTERY_PATH "/status", "r");
if (!status_file) {
return FALSE;
}
fseeko(status_file, 0, SEEK_END);
off_t len = ftello(status_file);
rewind(status_file);
char status_text[len + 1];
status_text[len] = '\0';
fread(status_text, 1, len, status_file);
fclose(status_file);
return strcmp(status_text, "Full\n") == 0;
}
static int get_battery_percent() {
if (is_battery_full()) {
return 100;
}
FILE *battery_file = fopen(BATTERY_PATH "/charge_now", "r");
if (!battery_file) {
return -1;
}
fseeko(battery_file, 0, SEEK_END);
off_t len = ftello(battery_file);
rewind(battery_file);
char charge_text[len + 1];
charge_text[len] = '\0';
fread(charge_text, 1, len, battery_file);
fclose(battery_file);
long charge = strtoul(charge_text, NULL, 10);
float scale = (float)charge / (float)max_batery_charge;
return round(scale * 100.0f);
}
static int is_adapter_connected() {
FILE *adapter_file = fopen(adapter_status_path, "r");
if (!adapter_file) {
return -1;
}
char text[2] = {'\0', '\0'};
fread(text, 1, 1, adapter_file);
fclose(adapter_file);
return text[0] == '1'; /* 1 means connected, anything else is not */
}
static void find_adapter_status_path() {
size_t i;
for (i = 0; i < adapter_search_names_count; ++i) {
size_t name_len = strlen(adapter_search_names[i]);
/* -1 is to compensate for '\0' at end of "/online" */
char *name = qtb_malloc(sizeof(ADAPTER_BASE_PATH) + name_len + sizeof("/online") - 1);
sprintf(name, "%s%s/online", ADAPTER_BASE_PATH, adapter_search_names[i]);
FILE *file = fopen(name, "r");
if (file) {
adapter_status_path = name;
} else {
qtb_free(name);
}
}
}
void battery_module_init(void) {
find_max_battery_charge();
find_adapter_status_path();
}
static const char *get_battery_icon(int percent, int adapter) {
if (adapter) {
return "";
} else if (percent <= 10) {
return "";
} else if (percent <= 20) {
return "";
} else if (percent <= 30) {
return "";
} else if (percent <= 40) {
return "";
} else if (percent <= 50) {
return "";
} else if (percent <= 60) {
return "";
} else if (percent <= 70) {
return "";
} else if (percent <= 90) {
return "";
} else if (percent < 100) {
return "";
} else {
return "";
}
}
static void warn_low_battery() {
#ifdef HAS_X11
if (qtb_get_x_display()) { /* if x is running */
system("notify-send -t 0 'Battery is less than 10%!'");
} else {
#endif
system("wall -t 0 'Battery is less than 10%!'");
#ifdef HAS_X11
}
#endif
}
char *battery_module_poll() {
char *output = qtb_calloc(16, 1);
int percent = get_battery_percent();
int adapter = is_adapter_connected();
if (percent == -1 || adapter == -1) {
sprintf(output, "N/A%%");
} else {
const char *icon = get_battery_icon(percent, adapter);
sprintf(output, "%s%3d%%", icon, percent);
if (show_notifiaction && percent <= 10) {
warn_low_battery();
show_notifiaction = FALSE;
} else if (percent > 10) {
show_notifiaction = TRUE;
}
}
return output;
}