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