Files
_dotfiles/.config/i3blocks/brightness/main.c
2024-06-11 21:08:44 +02:00

200 lines
5.5 KiB
C

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <stdbool.h>
#include <dirent.h>
#include <stdint.h>
#include <errno.h>
#include <assert.h>
#include <stdarg.h>
#include <getopt.h>
#include <sys/select.h>
#include <sys/inotify.h>
#define INOTIFY_EVENT_SIZE (sizeof (struct inotify_event))
#define INOTIFY_BUFF_SIZE 64
static bool get_float_value_from_file(const char *path,
float *dst_val);
static void print_brightness_percent(const char *actual_path,
const char *max_path);
static void usage(void) {
fprintf(stderr, "brightness %s - read actual brightness value in non-blocking style.\n\n", VERSION);
fprintf(stderr,
"Usage: brightness [options]\n\
\n\
Options:\n\
-a, --actual_brightness_path \tpath to file with actual brightness string\n\
-m, --max_brightness_path \tpath to file with max brightness string\n\
-h, --help \tprint this help.\n\
-V, --version \tprint version and exit.\n\
\n");
}
//////////////////////////////////////////////////////////////
int
main(int argc, char *argv[]) {
static const char *default_abp = "/sys/class/backlight/intel_backlight/actual_brightness";
static const char *default_mbp = "/sys/class/backlight/intel_backlight/max_brightness";
char *actual_brightness_path = default_abp;
char *max_brightness_path = default_mbp;
char buff[INOTIFY_BUFF_SIZE] = {0};
fd_set read_descriptors;
struct timeval time_to_wait;
int ifd, wd, read_len, rc, opt_idx;
size_t opt_len;
// ifd - inotify_file_descriptor
// wd - inotify wait descriptor
// rc - result code
static const struct option lopts[] = {
{"actual_brightness_path", required_argument, NULL, 'a'},
{"max_brightness_path", required_argument, NULL, 'm'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{NULL, 0, NULL, 0},
};
while ((opt_idx = getopt_long(argc, argv, "a:m:hV", lopts, NULL)) != -1) {
switch (opt_idx) {
case 'a':
opt_len = strlen(optarg);
actual_brightness_path = malloc(opt_len + 1);
strcpy(actual_brightness_path, optarg);
break;
case 'm':
opt_len = strlen(optarg);
max_brightness_path = malloc(opt_len + 1);
strcpy(max_brightness_path, optarg);
break;
case 'h':
usage();
return 0;
case 'V':
printf("%s\n", VERSION);
return 0;
default:
printf("something bad is happened. option index is out of bounds (%d %c)\n", opt_idx, (char)opt_idx);
return -1;
}
}
print_brightness_percent(actual_brightness_path,
max_brightness_path);
ifd = inotify_init();
if (ifd == -1) {
perror("inotify init failed");
return -1;
}
wd = inotify_add_watch(ifd, actual_brightness_path, IN_MODIFY);
FD_ZERO (&read_descriptors);
FD_SET (ifd, &read_descriptors);
time_to_wait.tv_sec = 10;
time_to_wait.tv_usec = 0;
while (1) {
fd_set tmp_set = read_descriptors;
rc = select(ifd+1, &tmp_set, NULL, NULL, &time_to_wait);
if (rc < 0) {
perror("select failed");
break;
}
if (rc == 0) { //timeout
continue;
}
if (!FD_ISSET(ifd, &read_descriptors)) {
continue;
}
read_len = read(ifd, (void*)buff, INOTIFY_BUFF_SIZE);
if (read_len < 0) {
perror("read failed");
continue;
}
for (int eix = 0; eix < read_len; ) {
struct inotify_event *event = (struct inotify_event*) &buff[eix];
eix += INOTIFY_EVENT_SIZE + event->len;
if (!(event->mask & IN_MODIFY)) {
continue;
}
print_brightness_percent(actual_brightness_path,
max_brightness_path);
}
}
//actually when we receive some signal (like sigterm or something like that)
//we will be here.
inotify_rm_watch(ifd, wd);
close(ifd);
if (actual_brightness_path != default_abp)
free(actual_brightness_path);
if (max_brightness_path != default_mbp)
free(max_brightness_path);
return 0;
}
//////////////////////////////////////////////////////////////
bool
get_float_value_from_file(const char *path,
float *dst_val) {
#define BUFF_SIZE 16
char buff[BUFF_SIZE] = {0};
FILE *f = fopen(path, "r");
bool result = false;
if (f == NULL) {
perror("failed to open file");
return false;
}
do {
if (!(fread((void*) buff, 1, BUFF_SIZE, f))) {
perror("failed to read file");
break;
}
char *unused;
*dst_val = strtof(buff, &unused);
result = true;
} while (0);
fclose(f);
return result;
}
//////////////////////////////////////////////////////////////
void
print_brightness_percent(const char *actual_path,
const char *max_path) {
float curr, max;
const char *parr[] = {actual_path, max_path};
float *farr[] = {&curr, &max};
for (size_t i = 0; i < 2; ++i) {
bool success = get_float_value_from_file(parr[i], farr[i]);\
if (!success) {
printf("\xF0\x9F\x94\x86"); //brightness symbol 🔆
printf(": NA\n");
fflush(stdout); // because we use select(), ant it blocks stdout
return;
}
}
printf("\xF0\x9F\x94\x86"); //brightness symbol 🔆
printf(": %02.f%%\n", (curr / max) * 100.f);
fflush(stdout); // because we use select(), ant it blocks stdout
}
//////////////////////////////////////////////////////////////