diff --git a/Makefile b/Makefile index 930e4b0..f68eff9 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ VERBOSE := 0 LIBS := xcb-atom PREFIX := /usr/local -CFLAGS := -Ofast -I. -I$(INC_DIR) +CFLAGS := -Ofast -I. -I$(INC_DIR) -std=c99 CFLAGS += -DBINARY=\"$(BIN)\" -D_POSIX_C_SOURCE=200809L CFLAGS += -Wall -Wpedantic -Wextra -Wswitch-enum CFLAGS += $(shell pkg-config --cflags $(LIBS)) diff --git a/include/block.h b/include/block.h index 88e1956..1f2efe1 100644 --- a/include/block.h +++ b/include/block.h @@ -17,6 +17,8 @@ typedef struct { pid_t fork_pid; } block; +block block_new(const char *const command, const unsigned int interval, + const int signal); int block_init(block *const block); int block_deinit(block *const block); int block_execute(block *const block, const uint8_t button); diff --git a/include/main.h b/include/main.h index c6ad61b..d5d5bfb 100644 --- a/include/main.h +++ b/include/main.h @@ -2,13 +2,12 @@ #include -#include "block.h" #include "config.h" #include "util.h" +#define REFRESH_SIGNAL SIGUSR1 + // Utilise C's adjacent string concatenation to count the number of blocks. #define X(...) "." -extern block blocks[LEN(BLOCKS(X)) - 1]; +enum { BLOCK_COUNT = LEN(BLOCKS(X)) - 1 }; #undef X - -#define REFRESH_SIGNAL SIGUSR1 diff --git a/include/signal-handler.h b/include/signal-handler.h index d397f2b..cd7c877 100644 --- a/include/signal-handler.h +++ b/include/signal-handler.h @@ -2,19 +2,27 @@ #include +#include "block.h" #include "timer.h" typedef sigset_t signal_set; -typedef int (*signal_refresh_callback)(void); -typedef int (*signal_timer_callback)(timer* const timer); +typedef int (*signal_refresh_callback)(block* const blocks, + const unsigned short block_count); +typedef int (*signal_timer_callback)(block* const blocks, + const unsigned short block_code, + timer* const timer); typedef struct { int fd; const signal_refresh_callback refresh_callback; const signal_timer_callback timer_callback; + + block* const blocks; + const unsigned short block_count; } signal_handler; signal_handler signal_handler_new( + block* const blocks, const unsigned short block_count, const signal_refresh_callback refresh_callback, const signal_timer_callback timer_callback); int signal_handler_init(signal_handler* const handler); diff --git a/include/status.h b/include/status.h index 1d22388..08aba35 100644 --- a/include/status.h +++ b/include/status.h @@ -10,16 +10,19 @@ typedef struct { #define STATUS_LENGTH \ - ((LEN(blocks) * (MEMBER_LENGTH(block, output) - 1) + CLICKABLE_BLOCKS) + \ - (LEN(blocks) - 1 + LEADING_DELIMITER + TRAILING_DELIMITER) * \ + ((BLOCK_COUNT * (MEMBER_LENGTH(block, output) - 1) + CLICKABLE_BLOCKS) + \ + (BLOCK_COUNT - 1 + LEADING_DELIMITER + TRAILING_DELIMITER) * \ (LEN(DELIMITER) - 1) + \ 1) char current[STATUS_LENGTH]; char previous[STATUS_LENGTH]; #undef STATUS_LENGTH + + const block* const blocks; + const unsigned short block_count; } status; -status status_new(void); +status status_new(const block* const blocks, const unsigned short block_count); bool status_update(status* const status); int status_write(const status* const status, const bool is_debug_mode, x11_connection* const connection); diff --git a/include/timer.h b/include/timer.h index 9f0abf7..26a2c73 100644 --- a/include/timer.h +++ b/include/timer.h @@ -2,6 +2,8 @@ #include +#include "block.h" + #define TIMER_SIGNAL SIGALRM typedef struct { @@ -10,5 +12,5 @@ typedef struct { const unsigned int reset_value; } timer; -timer timer_new(void); +timer timer_new(const block *const blocks, const unsigned short block_count); int timer_arm(timer *const timer); diff --git a/include/watcher.h b/include/watcher.h index 23bc82d..af1dbaf 100644 --- a/include/watcher.h +++ b/include/watcher.h @@ -3,11 +3,11 @@ #include #include +#include "block.h" #include "main.h" -#include "util.h" typedef enum { - SIGNAL_FD = LEN(blocks), + SIGNAL_FD = BLOCK_COUNT, WATCHER_FD_COUNT, } watcher_fd_index; @@ -15,8 +15,13 @@ typedef struct pollfd watcher_fd; typedef struct { watcher_fd fds[WATCHER_FD_COUNT]; + + const block *const blocks; + const unsigned short block_count; } watcher; +watcher watcher_new(const block *const blocks, + const unsigned short block_count); int watcher_init(watcher *const watcher, const int signal_fd); int watcher_poll(watcher *const watcher, const int timeout_ms); bool watcher_fd_is_readable(const watcher_fd *const watcher_fd); diff --git a/src/block.c b/src/block.c index 7e2a809..1a1bb03 100644 --- a/src/block.c +++ b/src/block.c @@ -14,6 +14,20 @@ #include "config.h" #include "util.h" +block block_new(const char *const command, const unsigned int interval, + const int signal) { + block block = { + .command = command, + .interval = interval, + .signal = signal, + + .output = {[0] = '\0'}, + .fork_pid = -1, + }; + + return block; +} + int block_init(block *const block) { if (pipe(block->pipe) != 0) { (void)fprintf(stderr, @@ -22,8 +36,6 @@ int block_init(block *const block) { return 1; } - block->fork_pid = -1; - return 0; } diff --git a/src/main.c b/src/main.c index 629effd..7526416 100644 --- a/src/main.c +++ b/src/main.c @@ -13,18 +13,8 @@ #include "watcher.h" #include "x11.h" -#define BLOCK(cmd, period, sig) \ - { \ - .command = cmd, \ - .interval = period, \ - .signal = sig, \ - }, - -block blocks[] = {BLOCKS(BLOCK)}; -#undef BLOCK - -static int init_blocks(void) { - for (unsigned short i = 0; i < LEN(blocks); ++i) { +static int init_blocks(block *const blocks, const unsigned short block_count) { + for (unsigned short i = 0; i < block_count; ++i) { block *const block = &blocks[i]; if (block_init(block) != 0) { return 1; @@ -34,8 +24,9 @@ static int init_blocks(void) { return 0; } -static int deinit_blocks(void) { - for (unsigned short i = 0; i < LEN(blocks); ++i) { +static int deinit_blocks(block *const blocks, + const unsigned short block_count) { + for (unsigned short i = 0; i < block_count; ++i) { block *const block = &blocks[i]; if (block_deinit(block) != 0) { return 1; @@ -45,8 +36,10 @@ static int deinit_blocks(void) { return 0; } -static int execute_blocks(const unsigned int time) { - for (unsigned short i = 0; i < LEN(blocks); ++i) { +static int execute_blocks(block *const blocks, + const unsigned short block_count, + const unsigned int time) { + for (unsigned short i = 0; i < block_count; ++i) { block *const block = &blocks[i]; if (!block_must_run(block, time)) { continue; @@ -60,8 +53,9 @@ static int execute_blocks(const unsigned int time) { return 0; } -static int trigger_event(timer *const timer) { - if (execute_blocks(timer->time) != 0) { +static int trigger_event(block *const blocks, const unsigned short block_count, + timer *const timer) { + if (execute_blocks(blocks, block_count, timer->time) != 0) { return 1; } @@ -72,30 +66,32 @@ static int trigger_event(timer *const timer) { return 0; } -static int refresh_callback(void) { - if (execute_blocks(0) != 0) { +static int refresh_callback(block *const blocks, + const unsigned short block_count) { + if (execute_blocks(blocks, block_count, 0) != 0) { return 1; } return 0; } -static int event_loop(const bool is_debug_mode, +static int event_loop(block *const blocks, const unsigned short block_count, + const bool is_debug_mode, x11_connection *const connection, signal_handler *const signal_handler) { - timer timer = timer_new(); + timer timer = timer_new(blocks, block_count); // Kickstart the event loop with an initial execution. - if (trigger_event(&timer) != 0) { + if (trigger_event(blocks, block_count, &timer) != 0) { return 1; } - watcher watcher; + watcher watcher = watcher_new(blocks, block_count); if (watcher_init(&watcher, signal_handler->fd) != 0) { return 1; } - status status = status_new(); + status status = status_new(blocks, block_count); bool is_alive = true; while (is_alive) { const int event_count = watcher_poll(&watcher, -1); @@ -147,20 +143,26 @@ int main(const int argc, const char *const argv[]) { return 1; } +#define BLOCK(command, interval, signal) block_new(command, interval, signal), + block blocks[BLOCK_COUNT] = {BLOCKS(BLOCK)}; +#undef BLOCK + const unsigned short block_count = LEN(blocks); + int status = 0; - if (init_blocks() != 0) { + if (init_blocks(blocks, block_count) != 0) { status = 1; goto x11_close; } - signal_handler signal_handler = - signal_handler_new(refresh_callback, trigger_event); + signal_handler signal_handler = signal_handler_new( + blocks, block_count, refresh_callback, trigger_event); if (signal_handler_init(&signal_handler) != 0) { status = 1; goto deinit_blocks; } - if (event_loop(cli_args.is_debug_mode, connection, &signal_handler) != 0) { + if (event_loop(blocks, block_count, cli_args.is_debug_mode, connection, + &signal_handler) != 0) { status = 1; } @@ -169,7 +171,7 @@ int main(const int argc, const char *const argv[]) { } deinit_blocks: - if (deinit_blocks() != 0) { + if (deinit_blocks(blocks, block_count) != 0) { status = 1; } diff --git a/src/signal-handler.c b/src/signal-handler.c index 2a9c1ee..f4f5c86 100644 --- a/src/signal-handler.c +++ b/src/signal-handler.c @@ -11,16 +11,19 @@ #include "block.h" #include "main.h" #include "timer.h" -#include "util.h" typedef struct signalfd_siginfo signal_info; signal_handler signal_handler_new( + block *const blocks, const unsigned short block_count, const signal_refresh_callback refresh_callback, const signal_timer_callback timer_callback) { signal_handler handler = { .refresh_callback = refresh_callback, .timer_callback = timer_callback, + + .blocks = blocks, + .block_count = block_count, }; return handler; @@ -40,9 +43,9 @@ int signal_handler_init(signal_handler *const handler) { (void)sigaddset(&set, SIGINT); (void)sigaddset(&set, SIGTERM); - for (unsigned short i = 0; i < LEN(blocks); ++i) { - const block *const block = &blocks[i]; - if (blocks->signal > 0) { + for (unsigned short i = 0; i < handler->block_count; ++i) { + const block *const block = &handler->blocks[i]; + if (block->signal > 0) { if (sigaddset(&set, SIGRTMIN + block->signal) != 0) { (void)fprintf( stderr, @@ -75,6 +78,7 @@ int signal_handler_deinit(signal_handler *const handler) { if (close(handler->fd) != 0) { (void)fprintf(stderr, "error: could not close signal file descriptor\n"); + return 1; } return 0; @@ -91,12 +95,14 @@ int signal_handler_process(signal_handler *const handler, timer *const timer) { const int signal = (int)info.ssi_signo; switch (signal) { case TIMER_SIGNAL: - if (handler->timer_callback(timer) != 0) { + if (handler->timer_callback(handler->blocks, handler->block_count, + timer) != 0) { return 1; } return 0; case REFRESH_SIGNAL: - if (handler->refresh_callback() != 0) { + if (handler->refresh_callback(handler->blocks, + handler->block_count) != 0) { return 1; } return 0; @@ -106,8 +112,8 @@ int signal_handler_process(signal_handler *const handler, timer *const timer) { return 1; } - for (unsigned short i = 0; i < LEN(blocks); ++i) { - block *const block = blocks + i; + for (unsigned short i = 0; i < handler->block_count; ++i) { + block *const block = &handler->blocks[i]; if (block->signal == signal - SIGRTMIN) { const uint8_t button = (uint8_t)info.ssi_int; block_execute(block, button); diff --git a/src/status.c b/src/status.c index f540f56..c7561eb 100644 --- a/src/status.c +++ b/src/status.c @@ -6,18 +6,20 @@ #include "block.h" #include "config.h" -#include "main.h" -#include "util.h" #include "x11.h" static bool has_status_changed(const status *const status) { return strcmp(status->current, status->previous) != 0; } -status status_new(void) { +status status_new(const block *const blocks, + const unsigned short block_count) { status status = { .current = {[0] = '\0'}, .previous = {[0] = '\0'}, + + .blocks = blocks, + .block_count = block_count, }; return status; @@ -27,8 +29,8 @@ bool status_update(status *const status) { (void)strcpy(status->previous, status->current); status->current[0] = '\0'; - for (unsigned short i = 0; i < LEN(blocks); ++i) { - const block *const block = &blocks[i]; + for (unsigned short i = 0; i < status->block_count; ++i) { + const block *const block = &status->blocks[i]; if (strlen(block->output) > 0) { #if LEADING_DELIMITER diff --git a/src/timer.c b/src/timer.c index b50b946..a9a383c 100644 --- a/src/timer.c +++ b/src/timer.c @@ -5,13 +5,13 @@ #include #include "block.h" -#include "main.h" #include "util.h" -static unsigned int compute_tick(void) { +static unsigned int compute_tick(const block *const blocks, + const unsigned short block_count) { unsigned int tick = 0; - for (unsigned short i = 0; i < LEN(blocks); ++i) { + for (unsigned short i = 0; i < block_count; ++i) { const block *const block = &blocks[i]; tick = gcd(block->interval, tick); } @@ -19,10 +19,11 @@ static unsigned int compute_tick(void) { return tick; } -static unsigned int compute_reset_value(void) { +static unsigned int compute_reset_value(const block *const blocks, + const unsigned short block_count) { unsigned int reset_value = 1; - for (unsigned short i = 0; i < LEN(blocks); ++i) { + for (unsigned short i = 0; i < block_count; ++i) { const block *const block = &blocks[i]; reset_value = MAX(block->interval, reset_value); } @@ -30,11 +31,11 @@ static unsigned int compute_reset_value(void) { return reset_value; } -timer timer_new(void) { +timer timer_new(const block *const blocks, const unsigned short block_count) { timer timer = { .time = 0, - .tick = compute_tick(), - .reset_value = compute_reset_value(), + .tick = compute_tick(blocks, block_count), + .reset_value = compute_reset_value(blocks, block_count), }; return timer; diff --git a/src/watcher.c b/src/watcher.c index f544089..ade4a42 100644 --- a/src/watcher.c +++ b/src/watcher.c @@ -5,9 +5,19 @@ #include #include -#include "main.h" +#include "block.h" #include "util.h" +watcher watcher_new(const block* const blocks, + const unsigned short block_count) { + watcher watcher = { + .blocks = blocks, + .block_count = block_count, + }; + + return watcher; +} + int watcher_init(watcher* const watcher, const int signal_fd) { if (signal_fd == -1) { fprintf(stderr, @@ -19,8 +29,8 @@ int watcher_init(watcher* const watcher, const int signal_fd) { fd->fd = signal_fd; fd->events = POLLIN; - for (unsigned short i = 0; i < LEN(blocks); ++i) { - const int block_fd = blocks[i].pipe[READ_END]; + for (unsigned short i = 0; i < watcher->block_count; ++i) { + const int block_fd = watcher->blocks[i].pipe[READ_END]; if (block_fd == -1) { fprintf( stderr,