chiark / gitweb /
Add an option to specify the current displayed time at startup.
authorBen Harris <bjh21@bjh21.me.uk>
Sat, 3 Nov 2018 22:25:48 +0000 (22:25 +0000)
committerBen Harris <bjh21@bjh21.me.uk>
Sat, 3 Nov 2018 22:25:48 +0000 (22:25 +0000)
clunk.c

diff --git a/clunk.c b/clunk.c
index f7e7271975a79b1c1c83ed8131a373d8d9cb02ff..6e6e19194337da71d04a20c7631d0e4e0fec7ade 100644 (file)
--- a/clunk.c
+++ b/clunk.c
@@ -2,6 +2,7 @@
 #include <stdbool.h>
 #include <stdio.h>
 #include <time.h>
+#include <unistd.h>
 
 static long const pulsewidth = 250000000; /* nanoseconds */
 
@@ -26,15 +27,16 @@ pulse()
                displayed.tm_min -= 60;
        }
        displayed.tm_hour %= 12;
-       printf(" (%02d:%02d:%02d)\n",
+       printf(" (%d:%02d:%02d)\n",
               displayed.tm_hour, displayed.tm_min, displayed.tm_sec);
        fflush(stdout);
 }
 
 static void
-init()
+init(int argc, char **argv)
 {
        struct timespec ts;
+       int opt;
 
        tzset();
        if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
@@ -42,30 +44,76 @@ init()
        if (localtime_r(&ts.tv_sec, &displayed) == NULL)
                err(1, "localtime_r");
        displayed.tm_sec = (displayed.tm_sec >= 30) ? 30 : 0;
+       while ((opt = getopt(argc, argv, "s:")) != -1) {
+               switch (opt) {
+               case 's':
+                       if (sscanf(optarg, "%d:%d:%d", &displayed.tm_hour,
+                                  &displayed.tm_min, &displayed.tm_sec) != 3)
+                               errx(1, "usage");
+                       break;
+               }
+       }
+}
+
+enum need_adjust { STOP, TICK, ADVANCE };
+
+static enum need_adjust
+need_adjust(struct tm const *now)
+{
+       long diff;
+
+       diff = now->tm_sec - displayed.tm_sec +
+               60 * (now->tm_min - displayed.tm_min) +
+               3600 * (now->tm_hour - displayed.tm_hour);
+       if (diff < 0) diff += 3600 * 12;
+       diff %= 3600 * 12;
+       printf("diff = %ld\n", diff);
+       if (diff < 30 || diff >= (10 * 3600)) return STOP;
+       if (diff < 60) return TICK;
+       if (diff < (10 * 3600)) return ADVANCE;
+}
+
+static void
+ts_advance(struct timespec *tp, long nsec)
+{
+
+       tp->tv_nsec += nsec;
+       if (tp->tv_nsec >= 1000000000) tp->tv_sec++;
 }
-       
 
 static void
 run()
 {
        struct timespec ts;
        struct tm tm;
+       int tick;
 
        while (true) {
                if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
                        err(1, "clock_gettime");
+               ts_advance(&ts, pulsewidth);
                if (localtime_r(&ts.tv_sec, &tm) == NULL)
                        err(1, "localtime_r");
-               /* Round down to the last 30 s. */
+               tick = 30;
+               switch (need_adjust(&tm)) {
+               case ADVANCE:
+                       tick = 2;
+                       /* FALLTHROUGH */
+               case TICK:
+                       pulse();
+                       /* FALLTHROUGH */
+               case STOP:
+                       /* nothing */ ;
+               }
+               /* Round down to the last tick. */
                ts.tv_nsec = 0;
-               ts.tv_sec -= tm.tm_sec % 30;
+               ts.tv_sec -= tm.tm_sec % tick;
                /* Choose when next tick will be. */
                ts.tv_nsec = 1000000000 - pulsewidth;
-               ts.tv_sec += 29;
+               ts.tv_sec += tick - 1;
                if (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &ts, NULL)
                    != 0)
                        err(1, "clock_nanosleep");
-               pulse();
        }
 }
 
@@ -73,7 +121,7 @@ int
 main(int argc, char **argv)
 {
 
-       init();
+       init(argc, argv);
        run();
        return 0;
 }