Nahrány soubory do „rcbar“

This commit is contained in:
radekchalupa 2025-01-27 18:12:49 +01:00
commit 3821ae9d5c
2 changed files with 388 additions and 0 deletions

22
rcbar/Makefile Normal file
View file

@ -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

366
rcbar/main.c Normal file
View file

@ -0,0 +1,366 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#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;
}