2 # I, Ian Kelling, follow the GNU license recommendations at
3 # https://www.gnu.org/licenses/license-recommendations.en.html. They
4 # recommend that small programs, < 300 lines, be licensed under the
5 # Apache License 2.0. This file contains or is part of one or more small
6 # programs. If a small program grows beyond 300 lines, I plan to switch
9 # Copyright 2024 Ian Kelling
11 # Licensed under the Apache License, Version 2.0 (the "License");
12 # you may not use this file except in compliance with the License.
13 # You may obtain a copy of the License at
15 # http://www.apache.org/licenses/LICENSE-2.0
17 # Unless required by applicable law or agreed to in writing, software
18 # distributed under the License is distributed on an "AS IS" BASIS,
19 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 # See the License for the specific language governing permissions and
21 # limitations under the License.
26 # * left click seconds to reset & enable main timer which shows 30
27 # minutes in blue and half hours in orange.
29 # * right click seconds to disable minutes & half hours of main timer
31 # * left click minutes to reset & enable 2nd timer.
33 # * right click minutes to disable 2nd timer
37 # Sections from right to left.
39 # section #1, labeled day_percent
41 # 1. Thousandths of a 16 hour day left. 1 = 57.6 seconds.
42 # 2. Bar of one thousand of a day which gets shorter by ninths. One ninth is 6.4 seconds.
43 # 3. Start of the day (only the non-zero numbers). Set this with the ds command.
44 # 4. The time right now.
45 # 5. Ten thousands of the year left. 1 = 52:34 minutes (leap year = 52:42)
46 # 6. Bar of 1/10,000 of a year shrinking by ninths. 1 ninth = 5:50 minutes (leap year = 5:51 mins).
48 # section #2, labeled seconds
50 # block characters, ▉, are added every 3 seconds, a total of 20 for 1
51 # minute. The groups of 5 blocks = 15 seconds each.
53 # section #3, labeled mins
55 # Only enabled by clicking on seconds, see usage.
57 # Block characters are added every minute until 30, then reset. There
58 # are 6 groups of 5 minutes.
62 # Half hours in orange, grouped into groups of 2. This will grow until
63 # it fills the screen.
67 # Only enabled by clicking on mins section, see usage.
69 # These repeat sections 3 and 4 in violet and some other color.
72 if [ -z "$BASH_VERSION" ]; then echo "error: shell is not bash" >&2; exit 1; fi
74 source /a
/bin
/bash-bear-trap
/bash-bear
87 if date -d 'february 29' &>/dev
/null
; then
95 if [[ /b
/data
/daystart
-ot /b
/data
/daystart-generated
&& $day_start_24h ]]; then
98 day_start_24h
=$
(cat /b
/data
/daystart
)
99 day_start_sig_digits
=${day_start_24h%?}
100 day_start_sig_digits
=${day_start_sig_digits%0}
101 day_start_hour
=${day_start_24h%??}
102 day_start_min
=${day_start_24h: -2}
103 echo $day_start_hour > /b
/data
/daystart-generated
104 echo $day_start_min >> /b
/data
/daystart-generated
105 day_start
=$
(date -d $day_start_hour:$day_start_min +%s
)
106 # for after midnight but before the day start.
107 if (( day_start
> EPOCHSECONDS
)); then
108 day_start
=$
(date -d "$day_start_hour:$day_start_min yesterday" +%s
)
117 # if [[ $line ]]; then
118 # echo "line=$line" >>/tmp/t
124 case $
(echo "$json" | jq
-r .name
) in
126 case $
(echo "$json" | jq
-r .button
) in
139 case $
(echo "$json" | jq
-r .button
) in
152 time=$
((EPOCHSECONDS
- start
))
153 total_mins
=$
(( time / 60 ))
154 mins
=$
(( total_mins
% 30 ))
155 half_hours
=$
(( total_mins
/ 30 ))
161 if [[ -e /dev
/shm
/iank-status
&& ! -e /tmp
/quiet-status
]]; then
163 eval "$(< /dev/shm/iank-status)"
166 touch --date="10 minutes ago" $tmp_focus1
167 touch --date="30 minutes ago" $tmp_focus2
168 f
=/tmp
/focus-last-input
170 # We output a reminder to do input to the focus app if we haven't done
171 # it less 10 minutes ago (but dont bother if its been more than 30
172 # minutes, maybe we aren't running it anymore.)
173 if [[ -e $f && $tmp_focus2 -ot $f && $tmp_focus1 -nt $f ]]; then
174 ps_char
="=======FOCUS====== $ps_char"
177 if [[ -e /tmp
/iank-i3-no-auto
]]; then
181 # not using currently
182 # if [[ -e /tmp/no-obs-auto-scene-switch ]]; then
183 # ps_char="$ps_char O"
186 if pgrep
-fc '^ffmpeg.*icecast://source.*/fsf' &>/dev
/null
; then
187 if [[ -e /tmp
/iank-ffmpeg-interlude-toggle
]]; then
188 ps_char
="= BRB = $ps_char"
190 ps_char
="=|=|= STREAMING =|=|= $ps_char"
193 muted
=$
(cat $HOME/.iank-stream-muted
) ||
:
197 if find $HOME/.iank-stream-muted
-mmin +2 |
grep .
&>/dev
/null
; then
198 toggle-mute mute notify
200 ps_char
="# UNMUTED # $ps_char"
204 ps_char
="!!!!! FAILED GETTING MUTE STATUS !!!!! $ps_char"
209 # fyi: to check system mute:
210 # if pactl get-source-mute @DEFAULT_SOURCE@ 2>/dev/null | awk '{print $2}' | grep no &>/dev/null; then
214 printf '{ "name":"status", "color":"#ED297D", "full_text": "%s' "$ps_char"
218 if [[ $start2 ]]; then
219 time2
=$
((EPOCHSECONDS
- start2
))
220 total_mins2
=$
(( time2
/ 60 ))
221 mins2
=$
(( total_mins2
% 30 ))
222 half_hours2
=$
(( total_mins2
/ 30 ))
223 # this is duplicate of mins and half hours except for different
224 # colors and looking at vars above.
227 printf '{ "color": "#EFC93E", "full_text": "'
228 for ((i
=half_hours2-1
; i
>= 0 ; i--
)); do
230 if (( i
> 0 && i
% 2 == 0 )); then
238 printf '{ "name":"mins2", "color":"#ED297D", "full_text": "'
239 for ((i
=29; i
>= 0 ; i--
)); do
240 if (( i
< mins2
)); then
245 if (( i
> 0 && i
% 5 == 0 )); then
255 printf '{ "color": "#FFB542", "full_text": "'
256 for ((i
=half_hours-1
; i
>= 0 ; i--
)); do
258 if (( i
> 0 && i
% 2 == 0 )); then
266 printf '{ "name":"mins", "color":"#0D6BDD", "full_text": "'
267 for ((i
=29; i
>= 0 ; i--
)); do
268 if (( i
< mins
)); then
273 if (( i
> 0 && i
% 5 == 0 )); then
281 printf '{ "name": "seconds", "full_text": "'
283 for ((i
=0; i
< 20; i
++)); do
284 # This first condition is to make the transition from full to empty
285 # be less jarring. We are filling a bucket of space with ticks of
286 # time, we would have to choose to show full or empty, but never
287 # both. Or we could have a half/tick to show full then empty real
288 # quick. I decided to try having it work like a snake, empty out the
289 # 1st quarter as we fill up the last quarter.
291 if (( i
> 0 && i
% 5 == 0 )); then
294 i_end
=$
(( time % 60 / 3 + 1 ))
295 if (( i_end
- i
> 15 )); then
297 elif (( i_end
== 1 && i
== 0 )); then
299 elif (( i
< i_end
)); then
307 ## begin day percent, in thousandths, plus a spark block for ten_thousandth.
308 printf '{ "name": "day_percent", "full_text": "'
311 # after 24 hours, reset the day start
312 if (( day_start
+ 24 * 60 * 60 < EPOCHSECONDS
)); then
313 day_start
=$
(date -d $day_start_hour:$day_start_min +%s
)
316 # there are 9 spark levels, 1/9 = .111.... In order to keep it in bash math, we upscale
317 # the number and divide by 111, 3 digits is good enough accuracy.
318 spark_index
="$(( (1000000 -(EPOCHSECONDS - day_start)*1000000 / (16*60*60) ) % 1000 / 111 ))"
320 # note: 960 minutes, so 10 minutes is about 1%
321 day_thousandth
=$
(( 1000 - (EPOCHSECONDS
- day_start
)*1000 / (16*60*60) ))
322 printf %s
"$day_thousandth${spark:spark_index:1}$day_start_sig_digits $(date "+%l
:%M
")"
324 # .1% of a waking year is ~5.75 hours, or 365 thousandths of a day.
325 # 1% of a waking year is 3.7 days
326 # A spark line of a thousandth of a waking year is 39 minutes.
327 year_start
=$
(date +%s
-d 'january 1 6am')
328 year_days
=$
(( (EPOCHSECONDS
- year_start
) / (24*60*60) ))
329 year_start
=$
(( year_start
+ year_days
* 8*60*60 ))
330 year_spark_index
=$
(( ( 1000000 - (EPOCHSECONDS
- year_start
)*1000000 / (days_in_this_year
*16*60*60) ) % 1000 / 111 ))
331 year_tenthousandth
=$
(( 10000 - (EPOCHSECONDS
- year_start
)*10000 / (days_in_this_year
*16*60*60) ))
332 printf %s
" $year_tenthousandth${spark:year_spark_index:1}"
341 # pass any arg and we just run once. mainly for debugging
346 #echo date -d $day_start_hour:$day_start_min +%s
347 #echo day_start=$day_start now=$EPOCHSECONDS
350 printf '{ "version": 1, "click_events": true }\n['
352 if [[ -e /tmp
/noi3bar
]]; then
357 read -r -t 3 line ||
:
362 rm -f $tmp_focus1 $tmp_focus2