/
setup_loop.c
190 lines (159 loc) · 4.83 KB
/
setup_loop.c
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "setup_loop.h"
#define BUFSIZE 1024
// TODO we could instead start prepare_display in each callback
// (would it be necessary to check if had already been activated?)
// and prepare_display would then cancel itself on call.
// Pros:
// - Not constantly calling prepare only to have it blank
// - No need for global static variable
// Cons:
// - More repetition?
static FILE* out_fp;
static ev_io bspwm_watcher;
static ev_timer wifi_timer;
static ev_timer battery_watcher;
static ev_timer sound_watcher;
static ev_timer packages_timer;
static ev_io packages_io_watcher;
static ev_periodic clock_watcher;
static ev_signal signal_watcher;
static ev_prepare prepare_display;
static void
bspwm_cb(struct ev_loop *loop, ev_io *w, int revents)
{
(void) revents;
(void) loop;
//TODO: Find a way to close the fd? Can't always assume it'll be stdin.
// Given we set it in main(), we can close it in main as well.
FILE *file = fdopen(w->fd, "r");
char line[BUFSIZE];
BspwmInfo *info = (BspwmInfo *) w->data;
if (fgets(line, BUFSIZE, file) != NULL)
{
bspwm_update(info, line);
}
}
static void
wifi_cb(struct ev_loop *loop, ev_timer *w, int revents)
{
(void) loop;
(void) revents;
WifiInfo *info = (WifiInfo *) w->data;
wifi_update(info);
}
static void
battery_cb(struct ev_loop *loop, ev_timer *w, int revents)
{
(void) loop;
(void) revents;
BatteryInfo *info = (BatteryInfo *)w->data;
battery_update(info);
}
static void
sound_cb(struct ev_loop *loop, ev_timer *w, int revents)
{
(void) loop;
(void) revents;
SoundInfo *info = (SoundInfo *) w->data;
sound_update(info);
}
static void
packages_io_cb(struct ev_loop *loop, ev_io *w, int revents)
{
(void) revents;
ev_io_stop(loop, w);
FILE *packages_file = fdopen(w->fd, "r");
PackagesInfo *info = (PackagesInfo *) w->data;
packages_update(info, packages_file);
pclose(packages_file);
ev_timer_again(loop, &packages_timer);
}
static void
packages_cb(struct ev_loop *loop, ev_timer *w, int revents)
{
(void) revents;
// We need to stop the timer in case our repeat interval is smaller than the
// time taken for our command to yield results.
ev_timer_stop(loop, w);
FILE *packages_file = popen("checkupdates", "r");
ev_io_set(&packages_io_watcher, fileno(packages_file), EV_READ);
ev_io_start(loop, &packages_io_watcher);
}
static void
clock_cb(struct ev_loop *loop, ev_periodic *w, int revents)
{
(void) loop;
(void) revents;
ClockInfo *info = (ClockInfo *) w->data;
clock_update(info);
}
static void
shutdown_cb(struct ev_loop *loop, ev_signal *w, int revents)
{
(void) revents;
fprintf(stderr, "Caught signal, shutting down bar...\n");
Bar *bar = (Bar *)w->data;
ev_unloop(loop, EVUNLOOP_ALL);
ev_break(loop, EVBREAK_ALL);
// Consider putting this in the cleanup watcher.
//close(0); // close stdin.
bar_free(bar);
}
static void
display_cb(struct ev_loop *loop, ev_prepare *w, int revents)
{
(void) revents;
(void) loop;
Bar const * const bar = (Bar *) w->data;
bar_print(out_fp, bar);
}
// TODO: How to close off the things?
// Pass them through?
void add_callbacks(Bar * const bar, FILE *in, FILE *out)
{
bspwm_watcher.data = &bar->bspwm;
ev_io_init(&bspwm_watcher, bspwm_cb, fileno(in), EV_READ);
wifi_timer.data = &bar->wifi;
ev_init(&wifi_timer, wifi_cb);
wifi_timer.repeat = 3.;
battery_watcher.data = &bar->battery;
ev_init(&battery_watcher, battery_cb);
battery_watcher.repeat = 1.;
sound_watcher.data = &bar->sound;
ev_init(&sound_watcher, sound_cb);
sound_watcher.repeat = 1.;
packages_io_watcher.data = &bar->packages;
FILE *packages_file = get_packages_file();
ev_io_init(&packages_io_watcher, packages_io_cb, fileno(packages_file), EV_READ);
ev_init(&packages_timer, packages_cb);
packages_timer.repeat = 5 * 60.;
// include an offset so that we don't get the time before it changes.
// TODO Maybe separate into date watcher and time watcher?
clock_update(&bar->clock);
clock_watcher.data = &bar->clock;
ev_periodic_init(&clock_watcher, clock_cb, 1., 60., 0);
// Easy way to shut down.
signal_watcher.data = bar;
ev_signal_init(&signal_watcher, shutdown_cb, SIGINT);
// An ev prepare runs before ev_run collects events;
// in other words, it's (almost) like it's after all the events that have been called.
// So we add an update
out_fp = out;
prepare_display.data = bar;
ev_prepare_init(&prepare_display, display_cb);
}
void start_watchers(struct ev_loop *loop)
{
ev_io_start(loop, &bspwm_watcher);
ev_timer_again(loop, &wifi_timer);
ev_timer_again(loop, &battery_watcher);
ev_timer_again(loop, &sound_watcher);
ev_io_start(loop, &packages_io_watcher);
ev_periodic_start(loop, &clock_watcher);
ev_signal_start(loop, &signal_watcher);
ev_prepare_start(loop, &prepare_display);
}