commit f6cba2c8a18e6f836a722ad6374a30a1892d5f53 Author: MCorange99 Date: Wed May 15 22:13:44 2024 +0300 modular dwmclocky diff --git a/dwmclocky/.gitignore b/dwmclocky/.gitignore new file mode 100644 index 0000000..dc0ae36 --- /dev/null +++ b/dwmclocky/.gitignore @@ -0,0 +1,3 @@ +modules/* +dim + diff --git a/dwmclocky/build.sh b/dwmclocky/build.sh new file mode 100755 index 0000000..610e962 --- /dev/null +++ b/dwmclocky/build.sh @@ -0,0 +1,11 @@ +#!/usr/bin/bash + +set -xe + +CCARGS="-Isrc/include -Wall -pedantic" + +cc -o dim src/main.c src/plug.c $CCARGS -lX11 -ldl +cc -o modules/clocky.dim src/modules/clock.c -rdynamic -shared -fPIC $CCARGS +cc -o modules/battery.dim src/modules/battery.c -rdynamic -shared -fPIC $CCARGS + + diff --git a/dwmclocky/src/include/plug.h b/dwmclocky/src/include/plug.h new file mode 100644 index 0000000..a685769 --- /dev/null +++ b/dwmclocky/src/include/plug.h @@ -0,0 +1,30 @@ + +#ifndef _H_PLUG +#define _H_PLUG + +#include + +typedef void (*plug_init_f) (); +typedef void (*plug_reload_f) (); +typedef void (*plug_poll_f) (char*, size_t); +typedef void (*plug_free_f) (); + +typedef struct plug_t { + char* name; + char* version; +} plug_t; + +typedef struct plug_int_t { + plug_init_f f_init; + plug_reload_f f_reload; + plug_poll_f f_poll; + plug_free_f f_free; + plug_t* s_plug_info; +} plug_int_t; + +void setup_plugins(char* plugin_path); +char* poll_plugins(); +void free_plugins(); + +#endif + diff --git a/dwmclocky/src/main.c b/dwmclocky/src/main.c new file mode 100644 index 0000000..8a240d4 --- /dev/null +++ b/dwmclocky/src/main.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include "plug.h" + +int main(void) { + setup_plugins("./modules"); + char* buffer; + + Display *display = XOpenDisplay(NULL); + Window window = DefaultRootWindow(display); + + while (1) { + buffer = poll_plugins("|"); + XStoreName(display, window, buffer); + XFlush(display); + sleep(1); + } + + + XCloseDisplay(display); + free_plugins(); + return 0; + +} diff --git a/dwmclocky/src/modules/battery.c b/dwmclocky/src/modules/battery.c new file mode 100644 index 0000000..4ba38d3 --- /dev/null +++ b/dwmclocky/src/modules/battery.c @@ -0,0 +1,42 @@ +#include "plug.h" +#include +#include +plug_t PLUG = {0}; + +static FILE* fp = NULL; + +char* batt_files[] = { + "/sys/class/power_supply/BAT0/capacity", + "/sys/class/power_supply/BAT1/capacity" +}; + +void plug_init(void) { + PLUG.name = "Battery"; + PLUG.version = "0.0.1"; + + for (size_t i = 0; i < sizeof(batt_files)/sizeof(batt_files[0]); i++) { + if (access(batt_files[i], F_OK) == 0) { + fp = fopen(batt_files[i], "r"); + if (fp) { + printf("Opened %s\n", batt_files[i]); + break; + } + } + } + + if (!fp) { + printf("MODULE: ERROR: Unable to find battery\n"); + return; + } +} + +void plug_reload(void) { /* Unused */ } + +void plug_poll(char* buf, size_t len) { + int perc = 0; + fseek(fp, 0, SEEK_SET); + fscanf(fp, "%d", &perc); + snprintf(buf, len, "Batt: %d%%", perc); +} + +void plug_free(void) {} diff --git a/dwmclocky/src/modules/clock.c b/dwmclocky/src/modules/clock.c new file mode 100644 index 0000000..032b35e --- /dev/null +++ b/dwmclocky/src/modules/clock.c @@ -0,0 +1,23 @@ +#include "plug.h" +#include +#include +plug_t PLUG = {0}; + +void plug_init(void) { + PLUG.name = "time"; + PLUG.version = "0.0.1"; +} + +void plug_reload(void) { /* Unused */ } + +void plug_poll(char* buf, size_t len) { + time_t rawtime; + struct tm *timeinfo; + + time(&rawtime); + timeinfo = localtime(&rawtime); + + strftime(buf, len, "Time: %H:%M (%Y-%m-%d)", timeinfo); +} + +void plug_free(void) {} diff --git a/dwmclocky/src/plug.c b/dwmclocky/src/plug.c new file mode 100644 index 0000000..b1be267 --- /dev/null +++ b/dwmclocky/src/plug.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include +#include "plug.h" + + +#define PLUG_PATH_MAX 255 +#define PLUG_MAX_COUNT (PLUG_PATH_MAX+255) +#define PLUG_POLL_BUF_SZ 1024 + +typedef struct PlugMan { + plug_int_t* plugs[PLUG_MAX_COUNT]; + size_t plug_count; + void* plug_objs[PLUG_MAX_COUNT]; + size_t plug_obj_count; +} plugman_t; + + +static plugman_t PLUGMAN = {0}; + +void* load_plug_sym(void* plug_f, char* fn_name); +plug_int_t* load_plugin(char* path); + +void load_plugins(const char* mod_dir_p) { + DIR* dir = {0}; + + dir = opendir(mod_dir_p); + + if (!dir) { + printf("ERROR: Failed to open dir %s\n", mod_dir_p); + } + + struct dirent* dir_entry; + + while ((dir_entry = readdir(dir)) != NULL) { + if (!(dir_entry->d_type == DT_REG || + dir_entry->d_type == DT_LNK)) { + continue; + } + + if (strcmp(dir_entry->d_name, ".") == 0 || + strcmp(dir_entry->d_name, "..") == 0) { + continue; + } + + char* dot = strchr(dir_entry->d_name, '.'); + + if (!dot || dot == dir_entry->d_name) { + continue; + } + + char* ext = dot+1; + if (strcmp(ext, "dim") != 0) continue; + + printf("INFO: Found plugin: %s/%s\n", mod_dir_p, dir_entry->d_name); + + char full_path[PLUG_MAX_COUNT] = {0}; + snprintf(full_path, PLUG_MAX_COUNT, "%s/%s", mod_dir_p, dir_entry->d_name); + plug_int_t* plug = load_plugin(full_path); + + if (!plug) { + printf("ERROR: Failed to load plugin %s, skipping\n", full_path); + continue; + } + PLUGMAN.plugs[PLUGMAN.plug_count++] = plug; + }; +} + + +plug_int_t* load_plugin(char* path) { + plug_int_t* plug = malloc(sizeof(plug_int_t)); + void* plug_f = dlopen(path, RTLD_NOW); + + if (!plug_f) { + printf("ERROR: Failed to load plugin %s\n", path); + return NULL; + } + + // "technically" couldnt run on very niche platforms but idc + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpedantic" + + plug->f_init = (plug_init_f)load_plug_sym(plug_f, "plug_init"); + plug->f_reload = (plug_reload_f)load_plug_sym(plug_f, "plug_reload"); + plug->f_poll = (plug_poll_f)load_plug_sym(plug_f, "plug_poll"); + plug->f_free = (plug_free_f)load_plug_sym(plug_f, "plug_free"); + plug->s_plug_info = (plug_t*)load_plug_sym(plug_f, "PLUG"); + + #pragma GCC diagnostic pop + + if (!plug->f_init || !plug->f_reload || + !plug->f_poll || !plug->f_free || + !plug->s_plug_info) { + dlclose(plug_f); + return NULL; + } + + PLUGMAN.plug_objs[PLUGMAN.plug_obj_count++] = plug_f; + return plug; +} + + +void* load_plug_sym(void* plug_f, char* fn_name) { + void* f = dlsym(plug_f, fn_name); + char* err = dlerror(); + + if (err){ + printf("ERROR: Could not load plug symbol '%s': %s\n", fn_name, err); + return NULL; + } + return f; +} + +void setup_plugins(char* plugin_path) { + load_plugins(plugin_path); + printf("INFO: Loaded %zu plugins:\n", PLUGMAN.plug_count); + for (size_t i = 0; i < PLUGMAN.plug_count; i++) { + plug_int_t* plug = PLUGMAN.plugs[i]; + + (plug->f_init)(); + printf(" - %s (%s)\n", plug->s_plug_info->name, plug->s_plug_info->version); + } +} + +void free_plugins() { + for (size_t i = 0; i < PLUGMAN.plug_count; i++) { + plug_int_t* plug = PLUGMAN.plugs[i]; + (plug->f_free)(); + } + + for (size_t i = 0; i < PLUGMAN.plug_obj_count; i++) { + dlclose(PLUGMAN.plug_objs[i]); + } +} + + + +char* poll_plugins(char* sep) { + char* buf = malloc(PLUG_POLL_BUF_SZ * sizeof(char)); + + if (!buf) { + printf("Unable to allocate buffer for polling\n"); + return NULL; + } + + for (size_t i = 0; i < PLUGMAN.plug_count; i++) { + plug_int_t* plug = PLUGMAN.plugs[i]; + + printf("Polling plug id %zu\n", i); + + size_t len = strlen(buf); + (plug->f_poll)(buf + len, PLUG_POLL_BUF_SZ - len); + + if (i < PLUGMAN.plug_count - 1) { + size_t len_post = strlen(buf); + snprintf(buf + len_post, PLUG_POLL_BUF_SZ - len_post, " %s ", sep); + } + } + + printf("Setting title: '%s'\n", buf); + + return buf; +} + + + diff --git a/dwmclocky/test.sh b/dwmclocky/test.sh new file mode 100644 index 0000000..9e31c8a --- /dev/null +++ b/dwmclocky/test.sh @@ -0,0 +1,6 @@ + +while true; do + clear -x + xprop -root | grep -Po "WM_NAME\(STRING\) = \"\K.*(?=\")" + sleep 0.5 +done