Commit | Line | Data |
---|---|---|
438d0d5f SK |
1 | #! /bin/bash |
2 | ||
61e5a351 SK |
3 | produce_volume() { |
4 | pactl list sinks \ | |
5 | | awk ' | |
6 | /^\tMute:/ { | |
7 | printf("%s,", $0); | |
8 | } | |
9 | /^\tVolume:/ { | |
10 | for (i=2; i<=NF; i++) printf(" %s", $i); | |
11 | }' \ | |
12 | | awk -v RS=',' ' | |
13 | /^[ \t]*Mute:/ {mute = $2} | |
14 | /^[ \t]*front-left:/ {left = $4} | |
15 | /^[ \t]*front-right:/ {right = $4} | |
16 | END { | |
17 | if (mute == "yes") { | |
18 | printf("x") | |
19 | } else { | |
20 | printf("%s %s", left, right) | |
21 | } | |
22 | } | |
23 | ' | |
24 | } | |
25 | ||
365549a9 SK |
26 | produce_mpd_state() { |
27 | echo 'status' \ | |
28 | | nc 127.0.0.1 6600 \ | |
29 | | awk ' | |
30 | { | |
31 | status[$1] = $2 | |
32 | } | |
33 | ||
34 | /^time: +[0-9]+:[0-9]+$/ { | |
35 | split($2, time, ":") | |
36 | seconds_current = time[1] | |
37 | seconds_total = time[2] | |
38 | ||
39 | hours = int(seconds_current / 60 / 60); | |
40 | secs_beyond_hours = seconds_current - (hours * 60 * 60); | |
41 | mins = int(secs_beyond_hours / 60); | |
42 | secs = secs_beyond_hours - (mins * 60); | |
43 | if (hours > 0) { | |
44 | current_time = sprintf("%d:%.2d:%.2d", hours, mins, secs) | |
45 | } else { | |
46 | current_time = sprintf("%.2d:%.2d", mins, secs) | |
47 | } | |
48 | ||
49 | if (seconds_total > 0) { | |
50 | time_percentage = (seconds_current / seconds_total) * 100 | |
51 | current_percentage = sprintf("%d%%", time_percentage) | |
52 | } else { | |
53 | current_percentage = "~" | |
54 | } | |
55 | } | |
56 | ||
57 | END { | |
58 | state = status["state:"] | |
59 | ||
60 | if (state == "play") { | |
61 | symbol = "▶" | |
62 | } else if (state == "pause") { | |
63 | symbol = "❚❚" | |
64 | } else if (state == "stop") { | |
65 | symbol = "⬛" | |
66 | } else { | |
67 | symbol = "--" | |
68 | } | |
69 | ||
70 | printf(\ | |
71 | "%s %s %s", | |
72 | status["state:"], current_time, current_percentage\ | |
73 | ) | |
74 | } | |
75 | ' | |
76 | } | |
77 | ||
78 | produce_mpd_song() { | |
79 | echo 'currentsong' \ | |
80 | | nc 127.0.0.1 6600 \ | |
81 | | awk ' | |
82 | /^OK/ { | |
83 | next | |
84 | } | |
85 | ||
86 | { | |
87 | key = $1 | |
88 | sub("^" key " +", "") | |
89 | val = $0 | |
90 | data[key] = val | |
91 | } | |
92 | ||
93 | END { | |
94 | name = data["Name:"] | |
95 | title = data["Title:"] | |
96 | file = data["file:"] | |
97 | ||
98 | if (name) { | |
99 | out = name | |
100 | } else if (title) { | |
101 | out = title | |
102 | } else if (file) { | |
103 | last = split(file, parts, "/") | |
104 | out = parts[last] | |
105 | } else { | |
106 | out = "" | |
107 | } | |
108 | print out | |
109 | } | |
110 | ' | |
111 | } | |
438d0d5f | 112 | |
6339a4f8 | 113 | produce_weather() { |
438d0d5f SK |
114 | metar -d "$WEATHER_STATION_ID" 2>&1 \ |
115 | | awk ' | |
116 | /METAR pattern not found in NOAA data/ { | |
117 | failures++ | |
118 | } | |
119 | ||
120 | /^Temperature/ { | |
121 | celsius = $3; | |
122 | fahrenheit = (celsius * (9 / 5)) + 32; | |
123 | temperature = fahrenheit | |
124 | } | |
125 | ||
126 | END { | |
127 | if (failures > 0) { | |
128 | temperature = "--" | |
129 | } | |
130 | print temperature "°F" | |
131 | }' | |
132 | } | |
133 | ||
6339a4f8 | 134 | produce_datetime() { |
438d0d5f SK |
135 | date +'%a %b %d %H:%M:%S' |
136 | } | |
137 | ||
6339a4f8 | 138 | consume() { |
438d0d5f SK |
139 | pipe="$1" |
140 | tail -f "$pipe" \ | |
141 | | stdbuf -o L awk \ | |
365549a9 SK |
142 | -v opt_debug=0 \ |
143 | -v opt_mpd_song_max_chars=10 \ | |
438d0d5f | 144 | ' |
61e5a351 SK |
145 | /^in:VOLUME/\ |
146 | { | |
147 | split_msg_parts() | |
148 | db["volume"] = msg_body | |
149 | } | |
150 | ||
365549a9 SK |
151 | /^in:MPD_STATE/\ |
152 | { | |
153 | split_msg_parts() | |
154 | db["mpd_state"] = $1 | |
155 | db["mpd_curr_song_time"] = $2 | |
156 | db["mpd_curr_song_percent"] = $3 | |
157 | } | |
158 | ||
159 | /^in:MPD_SONG/\ | |
438d0d5f | 160 | { |
365549a9 SK |
161 | split_msg_parts() |
162 | db["mpd_curr_song_name"] = msg_body | |
438d0d5f SK |
163 | } |
164 | ||
365549a9 | 165 | /^in:WEATHER/\ |
438d0d5f | 166 | { |
365549a9 SK |
167 | split_msg_parts() |
168 | db["weather_temperature"] = msg_body | |
438d0d5f SK |
169 | } |
170 | ||
365549a9 | 171 | /^in:DATE_TIME/\ |
438d0d5f | 172 | { |
365549a9 SK |
173 | split_msg_parts() |
174 | db["datetime"] = msg_body | |
175 | } | |
176 | ||
177 | /^out:BAR/\ | |
178 | { | |
179 | split_msg_parts() | |
438d0d5f SK |
180 | print make_bar() |
181 | } | |
182 | ||
365549a9 SK |
183 | |
184 | function split_msg_parts() { | |
185 | msg_head = $1 | |
186 | sub("^" msg_head " +", "") | |
187 | msg_body = $0 | |
188 | debug(msg_head, msg_body) | |
438d0d5f SK |
189 | } |
190 | ||
365549a9 | 191 | function make_bar( position, bar, sep, i, j) { |
61e5a351 | 192 | position[++i] = sprintf("(%s)", db["volume"]) |
365549a9 | 193 | position[++i] = make_status_mpd() |
438d0d5f SK |
194 | position[++i] = db["weather_temperature"] |
195 | position[++i] = db["datetime"] | |
196 | bar = "" | |
197 | sep = "" | |
198 | for (j = 1; j <= i; j++) { | |
199 | bar = bar sep position[j] | |
200 | sep = " " | |
201 | } | |
202 | return bar | |
203 | } | |
365549a9 SK |
204 | |
205 | function make_status_mpd( state, status) { | |
206 | state = db["mpd_state"] | |
207 | ||
208 | if (state == "play") { | |
209 | status = make_status_mpd_state_known("▶") | |
210 | } else if (state == "pause") { | |
211 | status = make_status_mpd_state_known("❚❚") | |
212 | } else if (state == "stop") { | |
213 | status = make_status_mpd_state_known("⬛") | |
214 | } else { | |
215 | status = make_status_mpd_state_unknown("--") | |
216 | } | |
217 | ||
218 | return sprintf("[%s]", status) | |
219 | } | |
220 | ||
221 | function make_status_mpd_state_known(symbol) { | |
222 | return sprintf(\ | |
223 | "%s %s %s %s", | |
224 | symbol, | |
225 | db["mpd_curr_song_time"], | |
226 | db["mpd_curr_song_percent"], | |
227 | substr(db["mpd_curr_song_name"], 1, opt_mpd_song_max_chars)\ | |
228 | ) | |
229 | } | |
230 | ||
231 | function make_status_mpd_state_unknown(symbol) { | |
232 | return sprintf("%s", symbol) | |
233 | } | |
234 | ||
235 | function debug(location, msg) { | |
236 | if (opt_debug) { | |
237 | print_error(location, msg) | |
238 | } | |
239 | } | |
240 | ||
241 | function print_error(location, msg) { | |
242 | print(location " ==> " msg) > "/dev/stderr" | |
243 | } | |
438d0d5f SK |
244 | ' |
245 | } | |
246 | ||
6339a4f8 | 247 | produce_bar_req() { |
438d0d5f SK |
248 | echo '' |
249 | } | |
250 | ||
251 | spawn() { | |
252 | cmd="$1" | |
253 | pipe="$2" | |
365549a9 | 254 | msg_head="$3" |
438d0d5f SK |
255 | interval="$4" |
256 | while true; do | |
365549a9 | 257 | echo "${msg_head} $($cmd)" > "$pipe" |
438d0d5f SK |
258 | sleep "$interval" |
259 | done & | |
260 | } | |
261 | ||
262 | main() { | |
263 | dir_bin="$1" | |
264 | dir_data="$2" | |
265 | pipe="$dir_data/pipe" | |
266 | ||
267 | WEATHER_STATION_ID='KJFK' | |
268 | ||
269 | rm -f "$pipe" | |
270 | mkfifo "$pipe" | |
271 | ||
6339a4f8 SK |
272 | spawn produce_datetime "$pipe" 'in:DATE_TIME' 1 |
273 | spawn produce_weather "$pipe" 'in:WEATHER' $(( 30 * 60 )) | |
365549a9 SK |
274 | spawn produce_mpd_state "$pipe" 'in:MPD_STATE' 1 |
275 | spawn produce_mpd_song "$pipe" 'in:MPD_SONG' 1 | |
61e5a351 | 276 | spawn produce_volume "$pipe" 'in:VOLUME' 1 |
6339a4f8 SK |
277 | spawn produce_bar_req "$pipe" 'out:BAR' 1 |
278 | consume "$pipe" | |
438d0d5f SK |
279 | } |
280 | ||
281 | main $@ |