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 Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}