commit 3821ae9d5cbd5936fe31a0819561379768424316 Author: radekchalupa Date: Mon Jan 27 18:12:49 2025 +0100 Nahrány soubory do „rcbar“ diff --git a/rcbar/Makefile b/rcbar/Makefile new file mode 100644 index 0000000..db52e67 --- /dev/null +++ b/rcbar/Makefile @@ -0,0 +1,22 @@ +CC = gcc +#CFLAGS = -Wall -pedantic -Werror -std=c99 +CFLAGS = -Wall -pedantic +target = rcbar +source = main.c +release = -O2 +debug = -g +valgrind = -ggdb3 + +$(target): Makefile $(source) +# @echo "sestavuji" + $(CC) -o $(target) $(source) $(release) $(CFLAGS) + +.PHONY : clean +clean: +# @echo "provadim clean" + rm -f $(target) + +install: $(target) + @echo "Instaluji" + cp -f $(target) /usr/local/bin + sync diff --git a/rcbar/main.c b/rcbar/main.c new file mode 100644 index 0000000..d6f60a4 --- /dev/null +++ b/rcbar/main.c @@ -0,0 +1,366 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_DATA_SIZE 64 +#define MODULE_BLOCK_SIZE 1024 + +#define BLOCK_CLOCK "clock" +#define BLOCK_VOLUME "volume" +#define BLOCK_MEMORY "memory" + +#define MODID_CLOCK 1 +#define MODID_VOLUME 2 +#define MODID_MEMORY 3 + +#define PARAM_CLOCK_LONG 1 + +typedef struct module_ { + timer_t timer; + int interval; + char bufdata[MODULE_DATA_SIZE]; + char bufblock[MODULE_BLOCK_SIZE]; + char colorbg[16]; + char colorfg[16]; + uint64_t id; + uint64_t params; +} module_t; + +typedef struct appdata_ +{ + module_t** modules; + size_t mod_count; + pthread_mutex_t mutex; +} appdata_t; + +static appdata_t* _data; + +static module_t* add_module(appdata_t* data); +static void init_modules(appdata_t* data); +static void module_start(module_t* module); +static void on_timer(union sigval timer_data); +static void module_stop(module_t* module); +static void cleanup(void); +static void fatal_exit(const char* msg); +static int update_module(module_t* m); +static void send_header(void); +static void send_data(void); +static void* thread_func_read(void* arg); +static int update_memory(module_t* mod); +static int update_clock(module_t* m); +static int update_volume(module_t* m); +static int_fast8_t get_button_number(const char* buff); +static module_t* find_first_module_type(appdata_t* data, uint64_t t); +static int command_to_buffer(const char* cmd, char* outbuff, size_t buffsize); + +static void cleanup(void) { + for (size_t i = 0; i < _data->mod_count; ++i) + module_stop(_data->modules[i]); +} + +static void fatal_exit(const char* msg) { + if (!msg) + perror(msg); + cleanup(); + exit(EXIT_FAILURE); +} + +static int_fast8_t get_button_number(const char* buff) { + char* pbut = strstr(buff, "\"button\":"); + if (NULL == pbut) + return -1; + pbut += 8; + while (0 != pbut) { + if (*pbut >= '0' && *pbut <= '9') { + return (int_fast8_t)(*pbut - '0'); + } + ++pbut; + } + return -1; +} + +static void on_click_clock(module_t* m, const char* buffer) { + int_fast8_t butn = get_button_number(buffer); + if (butn >= 2) + system("foot -e tty-clock"); + else + m->params ^= PARAM_CLOCK_LONG; + send_data(); +} + +static module_t* find_first_module_type(appdata_t* data, uint64_t t) { + for (size_t i = 0; i < data->mod_count; ++i) { + if (data->modules[i]->id == t) + return data->modules[i]; + } + return NULL; +} + +static int command_to_buffer(const char* cmd, char* outbuff, size_t buffsize) { + FILE* pf = popen(cmd, "r"); + if (!pf) { + strcpy(outbuff, "ERR"); + return -1; + } + int retval = 1; + if (!feof(pf)) { + if (fgets(outbuff, buffsize, pf) != NULL) { + if (strlen(outbuff) > 0) { + if (*(outbuff+strlen(outbuff)-1) == '\n') + *(outbuff+strlen(outbuff)-1) = 0; + } + else + retval = 0; + } + else + retval = -1; + } + pclose(pf); + return retval; +} + +static void* thread_func_read(void* arg) { + char buffer[1024]; + appdata_t* data = (appdata_t*)arg; + module_t* m; + while (1) { + if (fgets(buffer, sizeof(buffer), stdin) == NULL) + break; + if (strstr(buffer, BLOCK_CLOCK) != NULL) { + m = find_first_module_type(data, MODID_CLOCK); + if (m) + on_click_clock(m, buffer); + } + else if (strstr(buffer, BLOCK_MEMORY) != NULL) { + system("foot -e htop"); + } + else if (strstr(buffer, BLOCK_VOLUME) != NULL) { + system("pavucontrol"); + } + } + return NULL; +} + +static void get_module_block(module_t* module, const char* block_name) { + strcpy(module->bufblock, "{\"name\":\""); + strcat(module->bufblock, block_name); + strcat(module->bufblock, "\",\"full_text\":\""); + strcat(module->bufblock, module->bufdata); +/* strcat(data->clock->bufblock, "\",\"short_text\":\""); + strcat(data->clock->bufblock, data->clock->bufdata);*/ + strcat(module->bufblock, "\", \"background\":\""); + strcat(module->bufblock, module->colorbg); + strcat(module->bufblock, "\",\"color\":\""); + strcat(module->bufblock, module->colorfg); + strcat(module->bufblock, "\"}"); +} + +static int update_clock(module_t* m) { + if (NULL == m) + return 0; + char buff[MODULE_DATA_SIZE]; + time_t time_now = time(NULL); + if (m->params & PARAM_CLOCK_LONG) + strftime(buff, sizeof(buff), "%H:%M:%S, %a %d.%m.%Y", + localtime((const time_t*)&time_now)); + else + strftime(buff, sizeof(buff), "%H:%M:%S", + localtime((const time_t*)&time_now)); + if (strcmp(buff, m->bufdata) == 0) + return 0; + strcpy(m->bufdata, buff); + get_module_block(m, BLOCK_CLOCK); + return 1; +} + +static int update_volume(module_t* m) { + if (NULL == m) + return 0; + char buff[MODULE_DATA_SIZE]; + int retv = command_to_buffer("show-volume.sh", buff, sizeof(buff)); + if (retv <= 0) + return -1; + if (strcmp(buff, m->bufdata) == 0) + return 0; + strcpy(m->bufdata, buff); + get_module_block(m, BLOCK_VOLUME); + return 1; +} + +static int update_memory(module_t* mod) { + if (NULL == mod) + return 0; + FILE* pfile = fopen("/proc/meminfo", "r"); + if (NULL == pfile) { + return 0; + } + char line[256]; + unsigned int mem_total; + unsigned int mem_avail; + unsigned int swap_total; + unsigned int swap_free; + unsigned int end = 0; + while (fgets(line, sizeof(line), pfile)) { + if (sscanf(line, "MemTotal: %u kB", &mem_total) == 1) { + end |= 1; + continue; + } + if (sscanf(line, "MemAvailable: %u kB", &mem_avail) == 1) { + end |= 2; + continue; + } + if (sscanf(line, "SwapTotal: %u kB", &swap_total) == 1) { + end |= 4; + continue; + } + if (sscanf(line, "SwapFree: %u kB", &swap_free) == 1) { + end |= 8; + continue; + } + if (0xF == end) + break; + } + fclose(pfile); + char buff[MODULE_DATA_SIZE]; + sprintf(buff, "%.2f - %.2f GiB", + (double)(mem_total - mem_avail) / (1024 * 1024), + (double)(swap_total - swap_free) / (1024 * 1024)); + if (strcmp(buff, mod->bufdata) == 0) + return 0; + strcpy(mod->bufdata, buff); + get_module_block(mod, BLOCK_MEMORY); + return 1; +} + +static module_t* add_module(appdata_t* data) { + if (0 == data->mod_count) { + data->modules = (module_t**)malloc(sizeof(module_t*)); + } else { + data->modules = (module_t**)realloc(data->modules, + (data->mod_count + 1) * sizeof(module_t*)); + } + if (NULL == data->modules) + abort(); + data->modules[data->mod_count] = (module_t*)malloc(sizeof(module_t)); + if (NULL == data->modules[data->mod_count]) + abort(); + memset(data->modules[data->mod_count], 0, sizeof(module_t)); + ++data->mod_count; + return data->modules[data->mod_count - 1]; +} + +static int update_module(module_t* m) { + if (m->id == MODID_MEMORY) + return update_memory(m); + else if (m->id == MODID_CLOCK) { + return update_clock(m); + } + else if (m->id == MODID_VOLUME) { + return update_volume(m); + } + return 0; +} + +static void send_header(void) { + puts("{ \"version\": 1, \"click_events\":true }"); + puts("[ []"); +} + +static void send_data(void) { + pthread_mutex_lock(&(_data->mutex)); + printf(",["); + + for (size_t i = 0; i < _data->mod_count; ++i) { + if (i > 0) + printf(","); + printf(_data->modules[i]->bufblock); + } + printf("]\n"); + fflush(stdout); + pthread_mutex_unlock(&(_data->mutex)); +} + +static void on_timer(union sigval timer_data) { + int need_refresh = update_module((module_t*)timer_data.sival_ptr); + if (need_refresh) + send_data(); +} + +static void module_start(module_t* module) { + struct sigevent sev; + struct itimerspec its; + memset(&sev, 0, sizeof(sev)); + sev.sigev_notify = SIGEV_THREAD; + sev.sigev_notify_function = &on_timer; + sev.sigev_value.sival_ptr = module; + if (-1 == timer_create(CLOCK_REALTIME, &sev, &(module->timer))) { + fatal_exit("timer_create"); + } + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = 10; + its.it_interval.tv_sec = module->interval; + its.it_interval.tv_nsec = 0; + if (-1 == timer_settime(module->timer, 0, &its, NULL)) + fatal_exit("timer_settime"); +} + +static void module_stop(module_t* module) { + if (NULL == module) + return; + if (0 != timer_delete(module->timer)) + fatal_exit("timer_stop"); +} + +static void init_modules(appdata_t* data) { + module_t* module; + module = add_module(data); + module->id = MODID_MEMORY; + strcpy(module->colorbg, "#3c3c3cff"); + strcpy(module->colorfg, "#d0ffd0ff"); + module->interval = 2; + + module = add_module(data); + module->id = MODID_VOLUME; + strcpy(module->colorbg, "#3c3c3cff"); + strcpy(module->colorfg, "#e0e0ffff"); + module->interval = 1; + + module = add_module(data); + module->id = MODID_CLOCK; + strcpy(module->colorbg, "#3c3c3cff"); + strcpy(module->colorfg, "#f0f0f0ff"); + module->interval = 1; + +} + +int main(int argc, char** argv) { + int iret; + pthread_t thread_read; + appdata_t data; + _data = &data; + memset(&data, 0, sizeof(appdata_t)); + data.mod_count = 0; + init_modules(&data); + pthread_mutex_init(&data.mutex, NULL); + iret = pthread_create(&thread_read, NULL, &thread_func_read, (void*)&data); + if (0 != iret) + return EXIT_FAILURE; + send_header(); + for (size_t i = 0; i < data.mod_count; ++i) { + module_start(data.modules[i]); + update_module(data.modules[i]); + } + while (1) { + pause(); + } + return EXIT_SUCCESS; +}