main.c (4252B)
1 #include "main.h" 2 3 #include <errno.h> 4 #include <stdbool.h> 5 #include <stddef.h> 6 7 #include "block.h" 8 #include "cli.h" 9 #include "config.h" 10 #include "signal-handler.h" 11 #include "status.h" 12 #include "timer.h" 13 #include "util.h" 14 #include "watcher.h" 15 #include "x11.h" 16 17 static int init_blocks(block *const blocks, const unsigned short block_count) { 18 for (unsigned short i = 0; i < block_count; ++i) { 19 block *const block = &blocks[i]; 20 if (block_init(block) != 0) { 21 return 1; 22 } 23 } 24 25 return 0; 26 } 27 28 static int deinit_blocks(block *const blocks, 29 const unsigned short block_count) { 30 for (unsigned short i = 0; i < block_count; ++i) { 31 block *const block = &blocks[i]; 32 if (block_deinit(block) != 0) { 33 return 1; 34 } 35 } 36 37 return 0; 38 } 39 40 static int execute_blocks(block *const blocks, 41 const unsigned short block_count, 42 const timer *const timer) { 43 for (unsigned short i = 0; i < block_count; ++i) { 44 block *const block = &blocks[i]; 45 if (!timer_must_run_block(timer, block)) { 46 continue; 47 } 48 49 if (block_execute(&blocks[i], 0) != 0) { 50 return 1; 51 } 52 } 53 54 return 0; 55 } 56 57 static int trigger_event(block *const blocks, const unsigned short block_count, 58 timer *const timer) { 59 if (execute_blocks(blocks, block_count, timer) != 0) { 60 return 1; 61 } 62 63 if (timer_arm(timer) != 0) { 64 return 1; 65 } 66 67 return 0; 68 } 69 70 static int refresh_callback(block *const blocks, 71 const unsigned short block_count) { 72 if (execute_blocks(blocks, block_count, NULL) != 0) { 73 return 1; 74 } 75 76 return 0; 77 } 78 79 static int event_loop(block *const blocks, const unsigned short block_count, 80 const bool is_debug_mode, 81 x11_connection *const connection, 82 signal_handler *const signal_handler) { 83 timer timer = timer_new(blocks, block_count); 84 85 // Kickstart the event loop with an initial execution. 86 if (trigger_event(blocks, block_count, &timer) != 0) { 87 return 1; 88 } 89 90 watcher watcher; 91 if (watcher_init(&watcher, blocks, block_count, signal_handler->fd) != 0) { 92 return 1; 93 } 94 95 status status = status_new(blocks, block_count); 96 bool is_alive = true; 97 while (is_alive) { 98 if (watcher_poll(&watcher, -1) != 0) { 99 return 1; 100 } 101 102 if (watcher.got_signal) { 103 is_alive = signal_handler_process(signal_handler, &timer) == 0; 104 } 105 106 for (unsigned short i = 0; i < watcher.active_block_count; ++i) { 107 (void)block_update(&blocks[watcher.active_blocks[i]]); 108 } 109 110 const bool has_status_changed = status_update(&status); 111 if (has_status_changed && 112 status_write(&status, is_debug_mode, connection) != 0) { 113 return 1; 114 } 115 } 116 117 return 0; 118 } 119 120 int main(const int argc, const char *const argv[]) { 121 const cli_arguments cli_args = cli_parse_arguments(argv, argc); 122 if (errno != 0) { 123 return 1; 124 } 125 126 x11_connection *const connection = x11_connection_open(); 127 if (connection == NULL) { 128 return 1; 129 } 130 131 #define BLOCK(icon, command, interval, signal) \ 132 block_new(icon, command, interval, signal), 133 block blocks[BLOCK_COUNT] = {BLOCKS(BLOCK)}; 134 #undef BLOCK 135 const unsigned short block_count = LEN(blocks); 136 137 int status = 0; 138 if (init_blocks(blocks, block_count) != 0) { 139 status = 1; 140 goto x11_close; 141 } 142 143 signal_handler signal_handler = signal_handler_new( 144 blocks, block_count, refresh_callback, trigger_event); 145 if (signal_handler_init(&signal_handler) != 0) { 146 status = 1; 147 goto deinit_blocks; 148 } 149 150 if (event_loop(blocks, block_count, cli_args.is_debug_mode, connection, 151 &signal_handler) != 0) { 152 status = 1; 153 } 154 155 if (signal_handler_deinit(&signal_handler) != 0) { 156 status = 1; 157 } 158 159 deinit_blocks: 160 if (deinit_blocks(blocks, block_count) != 0) { 161 status = 1; 162 } 163 164 x11_close: 165 x11_connection_close(connection); 166 167 return status; 168 }