From 80dde85a2e8ed96c1df1efc087056054f8001be7 Mon Sep 17 00:00:00 2001 From: Squibid Date: Tue, 23 Sep 2025 22:46:19 -0400 Subject: [PATCH] feat(config file): add a config file --- .gitmodules | 9 ++++ config.h | 11 ----- example_config.toml | 16 +++++++ include/config.h | 27 +++++++++++ lib/cargs | 1 + lib/tinyexpr | 1 + lib/tomlc99 | 1 + meson.build | 18 +++++++- src/battery.c | 2 +- src/config.c | 109 ++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 56 +++++++++++++++++++---- 11 files changed, 229 insertions(+), 22 deletions(-) delete mode 100644 config.h create mode 100644 example_config.toml create mode 100644 include/config.h create mode 160000 lib/cargs create mode 160000 lib/tinyexpr create mode 160000 lib/tomlc99 create mode 100644 src/config.c diff --git a/.gitmodules b/.gitmodules index f4618ee..4e9ac2c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,12 @@ [submodule "lib/log.c"] path = lib/log.c url = https://github.com/rxi/log.c +[submodule "lib/tomlc99"] + path = lib/tomlc99 + url = https://github.com/cktan/tomlc99 +[submodule "lib/tinyexpr"] + path = lib/tinyexpr + url = https://github.com/codeplea/tinyexpr +[submodule "lib/cargs"] + path = lib/cargs + url = https://github.com/likle/cargs diff --git a/config.h b/config.h deleted file mode 100644 index a983d46..0000000 --- a/config.h +++ /dev/null @@ -1,11 +0,0 @@ -#include - -static const char *notification_name = "Event Handler"; /* name to use in notifications */ -static const char *battery_dir = "/sys/class/power_supply/BAT1"; /* path to the batteries directory */ -static const char *linefile = "/sys/class/power_supply/ACAD/online"; /* path to the file which tells us if we are online (plugged in) */ -static const char *ledfile = "/sys/class/leds/input0::capslock/brightness"; /* path to the file which lights up the led */ -static const char *acpid_sock = "/run/acpid.socket"; /* acpid socket file */ -static const int blink_start = 15; /* percentage to start blinking at */ -const double blink_formula(int x) { /* formula used to set the blinking rate, this function takes in one argument: the battery percentage */ - return 1.7 + 18.5 * exp(-0.29 * x); -} diff --git a/example_config.toml b/example_config.toml new file mode 100644 index 0000000..51c8f27 --- /dev/null +++ b/example_config.toml @@ -0,0 +1,16 @@ +[battery] +status_path = "/sys/class/power_supply/BAT1" +power_source = "/sys/class/power_supply/ACAD/online" + +[led] +brightness_path = "/sys/class/leds/input0::capslock/brightness" + +[led.blink] +trigger_level = 15 +timing_formula = "1.7 + 18.5 * exp(-0.29 * p)" + +[acpi_daemon] +socket_path = "/run/acpid.socket" + +[log] +level = "INFO" diff --git a/include/config.h b/include/config.h new file mode 100644 index 0000000..77ba257 --- /dev/null +++ b/include/config.h @@ -0,0 +1,27 @@ +#pragma once + +#define LED_BLINK_TRIGGER_DISABLED 101 + +/** + * @brief parse the config file + * + * @param path the path to the config file + */ +void parse_config_file(char *path); + +/** + * @brief setup the led formula + */ +void setup_led_formula(void); + +extern char *battery_status_path; +extern char *battery_power_source; + +extern char *led_brightness_path; + +extern unsigned int led_blink_trigger_level; +extern char *led_blink_timing_formula; + +double led_blink_timing_func(int percent); + +extern char *acpi_daemon_socket_path; diff --git a/lib/cargs b/lib/cargs new file mode 160000 index 0000000..0698c3f --- /dev/null +++ b/lib/cargs @@ -0,0 +1 @@ +Subproject commit 0698c3f90333446d0fc2745c1e9ce10dd4a9497a diff --git a/lib/tinyexpr b/lib/tinyexpr new file mode 160000 index 0000000..9907207 --- /dev/null +++ b/lib/tinyexpr @@ -0,0 +1 @@ +Subproject commit 9907207e5def0fabdb60c443517b0d9e9d521393 diff --git a/lib/tomlc99 b/lib/tomlc99 new file mode 160000 index 0000000..26b9c1e --- /dev/null +++ b/lib/tomlc99 @@ -0,0 +1 @@ +Subproject commit 26b9c1ea770dab2378e5041b695d24ccebe58a7a diff --git a/meson.build b/meson.build index 9d55475..210fcab 100644 --- a/meson.build +++ b/meson.build @@ -9,7 +9,9 @@ srcfiles = files( 'src/led.c', 'src/wayland.c', 'src/acpi.c', - 'src/utils.c' + 'src/utils.c', + 'src/battery.c', + 'src/config.c' ) # wayland stuff @@ -55,10 +57,22 @@ executable('eh', srcfiles, ], include_directories: [ 'lib/log.c/src', + 'lib/tinyexpr', + 'lib/tomlc99', + 'lib/cargs/include', 'include' ], link_with: [ static_library('log.c', 'lib/log.c/src/log.c', - include_directories: 'lib/log.c/src') + include_directories: 'lib/log.c/src'), + + static_library('tinyexpr', 'lib/tinyexpr/tinyexpr.c', + include_directories: 'lib/tinyexpr'), + + static_library('tomlc99', 'lib/tomlc99/toml.c', + include_directories: 'lib/tomlc99'), + + static_library('cargs', 'lib/cargs/src/cargs.c', + include_directories: 'lib/cargs/include') ] ) diff --git a/src/battery.c b/src/battery.c index 19c5f98..3042de6 100644 --- a/src/battery.c +++ b/src/battery.c @@ -15,7 +15,7 @@ char FILE *f; /* open up the battery capacity for reading */ - d = concat(battery_dir, "/capacity"); + d = concat(battery_status_path, "/capacity"); f = fopen(d, "r"); free(d); diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..9871d6b --- /dev/null +++ b/src/config.c @@ -0,0 +1,109 @@ +#include +#include +#include + +#include +#include +#include + +#include "config.h" + +#define table(tt, v, vn) do { \ + v = toml_table_in(tt, vn); \ + if (!v) { \ + log_warn("missing [%s]", vn); \ + } \ + } while (0); + +#define set_str_conf(op, tt, v) do { \ + toml_datum_t val; \ + val = toml_string_in(tt, v); \ + if (val.ok) { \ + op = val.u.s; \ + } \ + } while (0); + +#define set_int_conf(op, tt, v) do { \ + toml_datum_t val; \ + val = toml_int_in(tt, v); \ + if (val.ok) { \ + op = val.u.i; \ + } \ + } while (0); + +static te_expr *expr; +static double percentage; + +char *battery_status_path = "/sys/class/power_supply/BAT1"; +char *battery_power_source = "/sys/class/power_supply/ACAD/online"; + +char *led_brightness_path = "/sys/class/leds/input0::capslock/brightness"; + +unsigned int led_blink_trigger_level = 15; +char *led_blink_timing_formula = "1.7 + 18.5 * exp(-0.29 * p)"; + +char *acpi_daemon_socket_path = "/run/acpid.socket"; + +double +led_blink_timing_func(int percent) +{ + percentage = percent; + return te_eval(expr); + + // return 1.7 + 18.5 * exp(-0.29 * percent); +} + +static void +free_eval(int sig) +{ + te_free(expr); + exit(sig); +} + +void +setup_led_formula(void) +{ + int err; + + te_variable vars[] = { { "p", &percentage } }; + expr = te_compile(led_blink_timing_formula, vars, 1, &err); + signal(SIGINT, free_eval); + if (!expr) { + log_fatal("%s", led_blink_timing_formula); + log_fatal("%*s^ Error near here", err - 1, ""); + + exit(1); + } +} + +void +parse_config_file(char *path) +{ + FILE *f; + toml_table_t *config, *battery, *led, *led_blink, *acpi_daemon; + char errbuf[200]; + + f = fopen(path, "r"); + if (!f) { + log_fatal("Failed to open config file: %s", path); + } + + config = toml_parse_file(f, errbuf, sizeof(errbuf)); + fclose(f); + + if (!config) { + log_fatal("error: %s", errbuf); + } + + table(config, battery, "battery"); + table(config, led, "led"); + table(led, led_blink, "blink"); + table(config, acpi_daemon, "acpi_daemon"); + + set_str_conf(battery_status_path, battery, "status_path"); + set_str_conf(battery_power_source, battery, "power_source"); + set_str_conf(led_brightness_path, led, "brightness_path"); + set_int_conf(led_blink_trigger_level, led_blink, "power_source"); + set_str_conf(led_blink_timing_formula, led_blink, "timing_formula"); + set_str_conf(acpi_daemon_socket_path, acpi_daemon, "socket_path"); +} diff --git a/src/main.c b/src/main.c index ee04163..9a358f6 100644 --- a/src/main.c +++ b/src/main.c @@ -11,7 +11,9 @@ #include #include -#include "log.h" +#include +#include + #include "led.h" #include "wayland.h" #include "acpi.h" @@ -22,6 +24,22 @@ #define MAX_BUFLEN 1024 +static struct cag_option options[] = { + { + .identifier = 'c', + .access_letters = "c", + .access_name = "config", + .value_name = "PATH", + .description = "Config file" + }, + { + .identifier = 'h', + .access_letters = "h", + .access_name = "help", + .description = "Shows the command help" + } +}; + void on_battery_event(char *percent, bool plugged) { @@ -33,8 +51,8 @@ on_battery_event(char *percent, bool plugged) /* convert battery percentage to an int */ res = strtol(percent, &ep, 10); - if (res <= blink_start) { - rate = blink_formula(res); + if (res <= led_blink_trigger_level) { + rate = led_blink_timing_func(res); if (rate >= 1) { led_set_rate(rate); } @@ -54,18 +72,40 @@ on_battery_event(char *percent, bool plugged) int main(int argc, char *argv[]) { - bool plugged = plugged_in((char *)linefile); - char buffer[MAX_BUFLEN], *out[4]; + cag_option_context context; + bool plugged = plugged_in(battery_power_source); + char buffer[MAX_BUFLEN], *out[4], *config_path; int sock_fd; + cag_option_init(&context, options, CAG_ARRAY_SIZE(options), argc, argv); + while (cag_option_fetch(&context)) { + switch (cag_option_get_identifier(&context)) { + case 'c': + config_path = (char *)cag_option_get_value(&context); + parse_config_file(config_path); + break; + case 'h': + printf("Usage: eh [OPTION]...\n"); + printf("Demonstrates the cargs library.\n\n"); + cag_option_print(options, CAG_ARRAY_SIZE(options), stdout); + return EXIT_SUCCESS; + case '?': + cag_option_print_error(&context, stdout); + break; + } + } + + /* configure the led blinking formula */ + setup_led_formula(); + /* set the logging level */ log_set_level(LOG_DEBUG); /* open up socket address */ - sock_fd = acpi_create_socket((char *)acpid_sock); + sock_fd = acpi_create_socket(acpi_daemon_socket_path); /* create the led thread */ - led_create_thread((char *)ledfile); + led_create_thread(led_brightness_path); /* create the wayland thread */ wayland_create_thread(); @@ -96,7 +136,7 @@ main(int argc, char *argv[]) char *s = get_substring(out[1], 0, 2); if (strcmp(s, "AC") == 0) { - plugged = plugged_in((char *)linefile); + plugged = plugged_in(battery_power_source); } free(s);