aboutsummaryrefslogtreecommitdiffstats
path: root/radharc.c
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2025-02-04 21:47:35 +0100
committerMattias Andrée <m@maandree.se>2025-02-04 21:47:35 +0100
commit8e6f8d4e24c0e0e95081bf61f7a55c4f85469950 (patch)
tree251ca8e47a2c53412e14484a790fbcfc83feb8c2 /radharc.c
parentUpdate TODO (diff)
downloadradharc-8e6f8d4e24c0e0e95081bf61f7a55c4f85469950.tar.gz
radharc-8e6f8d4e24c0e0e95081bf61f7a55c4f85469950.tar.bz2
radharc-8e6f8d4e24c0e0e95081bf61f7a55c4f85469950.tar.xz
Add support for SIGINT and SIGHUP
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to 'radharc.c')
-rw-r--r--radharc.c191
1 files changed, 179 insertions, 12 deletions
diff --git a/radharc.c b/radharc.c
index 37179b7..12f5ce8 100644
--- a/radharc.c
+++ b/radharc.c
@@ -3,6 +3,7 @@
#include <sys/timerfd.h>
#include <errno.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -91,6 +92,27 @@ static int dflag = 0;
*/
static int xflag = 0;
+
+/**
+ * If 0, SIGINT has not been received,
+ * if 1, SIGINT has been received once as the effect
+ * should be faded out and then the effect should
+ * be removed and the program terminated,
+ * if 2, SIGINT has been received at least twice and
+ * the effect should be removed immediately
+ * and the program terminated
+ */
+static volatile sig_atomic_t sigint_received = 0;
+
+/**
+ * If 0, SIGHUP has not been received,
+ * if 1, SIGHUP has been received and the effect
+ * shall be made `LIBCOOPGAMMA_UNTIL_REMOVAL` and
+ * the program terminated
+ */
+static volatile sig_atomic_t sighup_received = 0;
+
+
/**
* Print usage information and exit
*/
@@ -104,6 +126,7 @@ usage(void)
exit(1);
}
+
/**
* Parse a non-negative double encoded as a string
*
@@ -124,6 +147,7 @@ parse_double(double *out, const char *str)
return 0;
}
+
/**
* Handle a command line option
*
@@ -209,6 +233,7 @@ handle_opt(char *opt, char *arg)
return 0;
}
+
/**
* This function is called after the last
* call to `handle_opt`
@@ -228,6 +253,7 @@ handle_args(int argc, char *argv[], char *prio)
(void) prio;
}
+
/**
* Fill a filter
*
@@ -254,6 +280,7 @@ LIST_DEPTHS
}
}
+
/**
* Set the gamma ramps
*
@@ -273,15 +300,19 @@ set_ramps(double red, double green, double blue)
libclut_model_standard_to_linear(&red, &green, &blue);
for (i = 0, r = 1; i < filters_n; i++) {
- if (!(crtc_updates[i].master) || !(crtc_info[crtc_updates[i].crtc].supported))
+ if (!crtc_updates[i].master || !crtc_info[crtc_updates[i].crtc].supported)
continue;
- fill_filter(&(crtc_updates[i].filter), red, green, blue);
- r = update_filter(i, 0);
+ fill_filter(&crtc_updates[i].filter, red, green, blue);
+ do {
+ r = update_filter(i, 0);
+ } while (r == -1 && errno == EINTR);
if (r == -2 || (r == -1 && errno != EAGAIN))
return r;
if (crtc_updates[i].slaves) {
for (j = 0; crtc_updates[i].slaves[j] != 0; j++) {
- r = update_filter(crtc_updates[i].slaves[j], 0);
+ do {
+ r = update_filter(crtc_updates[i].slaves[j], 0);
+ } while (r == -1 && errno == EINTR);
if (r == -2 || (r == -1 && errno != EAGAIN))
return r;
}
@@ -290,11 +321,13 @@ set_ramps(double red, double green, double blue)
while (r != 1)
if ((r = synchronise(-1)) < 0)
- return r;
+ if (r != -1 || errno != EINTR)
+ return r;
return 0;
}
+
/**
* Get the colour temperature for the current time
*
@@ -321,6 +354,32 @@ get_temperature(double *tp)
/**
+ * Called when SIGINT is received
+ *
+ * @param sig Always `SIGINT`
+ */
+static void
+sigint_handler(int sig)
+{
+ (void) sig;
+ sigint_received = sigint_received ? 2 : 1;
+}
+
+
+/**
+ * Called when SIGHUP is received
+ *
+ * @param sig Always `SIGHUP`
+ */
+static void
+sighup_handler(int sig)
+{
+ (void) sig;
+ sighup_received = 1;
+}
+
+
+/**
* The main function for the program-specific code
*
* @return 0: Success
@@ -333,8 +392,20 @@ start(void)
{
int r, tfd;
size_t i;
- double temperature, red, green, blue;
+ double target_temperature;
+ long int original_temperature;
+ long int current_temperature = 6500;
+ double red = 1, green = 1, blue = 1;
uint64_t overrun;
+ struct sigaction sa;
+ struct timespec sleep_timeout;
+ const char *side;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = &sigint_handler;
+ sigaction(SIGINT, &sa, NULL);
+ sa.sa_handler = &sighup_handler;
+ sigaction(SIGHUP, &sa, NULL);
if (xflag)
for (i = 0; i < filters_n; i++)
@@ -366,16 +437,26 @@ start(void)
return -1;
for (i = 0; i < (size_t)fade_in_cs;) {
+ if (sigint_received) {
+ double cs = (double)i / fade_in_cs * fade_out_cs + 0.5;
+ fade_out_cs = (unsigned long int)cs;
+ goto fade_out_have_timer;
+ }
+
if (i % 600 == 0)
- if ((r = get_temperature(&temperature)) < 0)
+ if ((r = get_temperature(&target_temperature)) < 0)
return r;
- if (libred_get_colour((long int)(6500 - (6500 - temperature) * i / fade_in_cs), &red, &green, &blue))
+ current_temperature = (long int)(6500 - (6500 - target_temperature) * i / fade_in_cs);
+ if (libred_get_colour(current_temperature, &red, &green, &blue))
return -1;
if ((r = set_ramps(red, green, blue)) < 0)
return r;
- if (read(tfd, &overrun, sizeof(overrun)) != sizeof(overrun))
+ while (read(tfd, &overrun, sizeof(overrun)) != sizeof(overrun)) {
+ if (errno == EINTR)
+ continue;
return -1;
+ }
if (overrun > fade_in_cs - i)
overrun = fade_in_cs - i;
i += overrun;
@@ -385,9 +466,19 @@ start(void)
no_fade_in:
for (;;) {
- if ((r = get_temperature(&temperature)) < 0)
+ if (sigint_received)
+ goto fade_out;
+
+ if (sighup_received) {
+ for (i = 0; i < filters_n; i++)
+ crtc_updates[i].filter.lifespan = LIBCOOPGAMMA_UNTIL_REMOVAL;
+ return set_ramps(red, green, blue);
+ }
+
+ if ((r = get_temperature(&target_temperature)) < 0)
return r;
- if (libred_get_colour((long int)temperature, &red, &green, &blue))
+ current_temperature = (long int)target_temperature;
+ if (libred_get_colour(current_temperature, &red, &green, &blue))
return -1;
if ((r = set_ramps(red, green, blue)) < 0)
return r;
@@ -395,6 +486,82 @@ no_fade_in:
if (!dflag)
return 0;
- sleep(6);
+ sleep_timeout.tv_sec = 6;
+ sleep_timeout.tv_nsec = 0;
+ while ((errno = clock_nanosleep(CLOCK_BOOTTIME, 0, &sleep_timeout, &sleep_timeout))) {
+ if (errno == EINTR) {
+ if (sigint_received || sighup_received)
+ break;
+ continue;
+ }
+ return -1;
+ }
+ }
+
+fade_out:
+ tfd = timerfd_create(CLOCK_MONOTONIC, 0);
+ if (tfd < 0)
+ goto fade_out_fail;
+ if (timerfd_settime(tfd, 0, &(struct itimerspec){{0, 10000000L}, {0, 10000000L}}, NULL))
+ goto fade_out_fail;
+
+fade_out_have_timer:
+ original_temperature = current_temperature;
+ for (i = 0; i < (size_t)fade_out_cs;) {
+ if (sigint_received > 1)
+ break;
+
+ current_temperature = original_temperature + (double)(6500 - original_temperature) * i / fade_out_cs;
+ if (libred_get_colour(current_temperature, &red, &green, &blue))
+ goto fade_out_fail;
+ if ((r = set_ramps(red, green, blue)) < 0)
+ goto fade_out_fail_use_r;
+
+ while (read(tfd, &overrun, sizeof(overrun)) != sizeof(overrun)) {
+ if (errno == EINTR)
+ continue;
+ goto fade_out_fail;
+ }
+ if (overrun > fade_in_cs - i)
+ overrun = fade_in_cs - i;
+ i += overrun;
}
+
+ close(tfd);
+
+ for (i = 0; i < filters_n; i++)
+ crtc_updates[i].filter.lifespan = LIBCOOPGAMMA_REMOVE;
+ return set_ramps(1, 1, 1);
+
+fade_out_fail_use_r:
+ switch (r) {
+ case -1:
+ fade_out_fail:
+ perror(argv0);
+ break;
+ case -2:
+ side = cg.error.server_side ? "server" : "client";
+ if (cg.error.custom) {
+ if (cg.error.number && cg.error.description) {
+ fprintf(stderr, "%s: %s-side error number %" PRIu64 ": %s\n",
+ argv0, side, cg.error.number, cg.error.description);
+ } else if (cg.error.number) {
+ fprintf(stderr, "%s: %s-side error number %" PRIu64 "\n", argv0, side, cg.error.number);
+ } else if (cg.error.description) {
+ fprintf(stderr, "%s: %s-side error: %s\n", argv0, side, cg.error.description);
+ }
+ } else if (cg.error.description) {
+ fprintf(stderr, "%s: %s-side error: %s\n", argv0, side, cg.error.description);
+ } else {
+ fprintf(stderr, "%s: %s-side error: %s\n", argv0, side, strerror((int)cg.error.number));
+ }
+ break;
+ default:
+ break;
+ }
+
+ for (i = 0; i < filters_n; i++)
+ crtc_updates[i].filter.lifespan = LIBCOOPGAMMA_REMOVE;
+ r = set_ramps(1, 1, 1);
+ return r ? r : -3;
}