aboutsummaryrefslogtreecommitdiffstats
path: root/radharc.c
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2025-02-04 23:41:31 +0100
committerMattias Andrée <m@maandree.se>2025-02-04 23:41:31 +0100
commit5fd3d699e34dd386f0cbfc4ec8ca5ced211fcd1a (patch)
treea85640bfeaa27d95e4fc92509ce74ade985ac38c /radharc.c
parentAdd support for SIGINT and SIGHUP (diff)
downloadradharc-5fd3d699e34dd386f0cbfc4ec8ca5ced211fcd1a.tar.gz
radharc-5fd3d699e34dd386f0cbfc4ec8ca5ced211fcd1a.tar.bz2
radharc-5fd3d699e34dd386f0cbfc4ec8ca5ced211fcd1a.tar.xz
Add support for SIGUSR1 and SIGUSR21.1
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to 'radharc.c')
-rw-r--r--radharc.c144
1 files changed, 125 insertions, 19 deletions
diff --git a/radharc.c b/radharc.c
index 12f5ce8..c651b8f 100644
--- a/radharc.c
+++ b/radharc.c
@@ -112,6 +112,28 @@ static volatile sig_atomic_t sigint_received = 0;
*/
static volatile sig_atomic_t sighup_received = 0;
+/**
+ * If 0, SIGUSR1 has not been received,
+ * if 1, SIGUSR1 has been received once as the effect
+ * should be faded out and removed, but the
+ * the process shall not be terminated
+ * if 2, SIGUSR1 has been received at least twice and
+ * the effect be removed immediately, but the
+ * the process shall not be terminated
+ */
+static volatile sig_atomic_t sigusr1_received = 0;
+
+/**
+ * If 0, SIGUSR2 has not been received,
+ * if 1, SIGUSR2 has been received once as the effect
+ * should be faded back in (from SIGUSR1), or
+ * if during initial fade-in, the fade-in should
+ * be skipped over
+ * if 2, SIGUSR2 has been received at least twice and
+ * the effect be immediately restored
+ */
+static volatile sig_atomic_t sigusr2_received = 0;
+
/**
* Print usage information and exit
@@ -380,6 +402,30 @@ sighup_handler(int sig)
/**
+ * Called when SIGUSR1 is received
+ *
+ * @param sig Always `SIGUSR1`
+ */
+static void
+sigusr1_handler(int sig)
+{
+ sigusr1_received = sigusr1_received ? 2 : 1;
+}
+
+
+/**
+ * Called when SIGUSR2 is received
+ *
+ * @param sig Always `SIGUSR2`
+ */
+static void
+sigusr2_handler(int sig)
+{
+ sigusr2_received = sigusr2_received ? 2 : 1;
+}
+
+
+/**
* The main function for the program-specific code
*
* @return 0: Success
@@ -400,12 +446,21 @@ start(void)
struct sigaction sa;
struct timespec sleep_timeout;
const char *side;
+ size_t fade_cs;
+ double cs;
+ sigset_t empty_sigset;
+
+ sigemptyset(&empty_sigset);
memset(&sa, 0, sizeof(sa));
sa.sa_handler = &sigint_handler;
sigaction(SIGINT, &sa, NULL);
sa.sa_handler = &sighup_handler;
sigaction(SIGHUP, &sa, NULL);
+ sa.sa_handler = &sigusr1_handler;
+ sigaction(SIGUSR1, &sa, NULL);
+ sa.sa_handler = &sigusr2_handler;
+ sigaction(SIGUSR2, &sa, NULL);
if (xflag)
for (i = 0; i < filters_n; i++)
@@ -427,8 +482,10 @@ start(void)
if ((r = make_slaves()) < 0)
return r;
+
+fade_in:
if (!fade_in_cs)
- goto no_fade_in;
+ goto faded_in;
tfd = timerfd_create(CLOCK_MONOTONIC, 0);
if (tfd < 0)
@@ -436,17 +493,26 @@ start(void)
if (timerfd_settime(tfd, 0, &(struct itimerspec){{0, 10000000L}, {0, 10000000L}}, NULL))
return -1;
- for (i = 0; i < (size_t)fade_in_cs;) {
+ fade_cs = (size_t)fade_in_cs;
+fade_in_have_timer:
+ for (i = 0; i < fade_cs;) {
if (sigint_received) {
- double cs = (double)i / fade_in_cs * fade_out_cs + 0.5;
- fade_out_cs = (unsigned long int)cs;
+ goto reverse_fade_in;
+ } else if (sigusr2_received) {
+ sigusr2_received = 0;
+ goto skip_fade_in;
+ } else if (sigusr1_received) {
+ sigusr1_received -= 1;
+ reverse_fade_in:
+ cs = (double)i / fade_cs * fade_out_cs + 0.5;
+ fade_cs = (unsigned long int)cs;
goto fade_out_have_timer;
}
if (i % 600 == 0)
if ((r = get_temperature(&target_temperature)) < 0)
return r;
- current_temperature = (long int)(6500 - (6500 - target_temperature) * i / fade_in_cs);
+ current_temperature = (long int)(6500 - (6500 - target_temperature) * i / fade_cs);
if (libred_get_colour(current_temperature, &red, &green, &blue))
return -1;
if ((r = set_ramps(red, green, blue)) < 0)
@@ -457,23 +523,29 @@ start(void)
continue;
return -1;
}
- if (overrun > fade_in_cs - i)
- overrun = fade_in_cs - i;
+ if (overrun > fade_cs - i)
+ overrun = fade_cs - i;
i += overrun;
}
+skip_fade_in:
close(tfd);
-no_fade_in:
+
+faded_in:
for (;;) {
- if (sigint_received)
+ if (sigint_received) {
goto fade_out;
-
- if (sighup_received) {
+ } else if (sighup_received) {
for (i = 0; i < filters_n; i++)
crtc_updates[i].filter.lifespan = LIBCOOPGAMMA_UNTIL_REMOVAL;
return set_ramps(red, green, blue);
}
+ sigusr2_received = 0;
+ if (sigusr1_received) {
+ sigusr1_received -= 1;
+ goto fade_out;
+ }
if ((r = get_temperature(&target_temperature)) < 0)
return r;
@@ -490,7 +562,7 @@ no_fade_in:
sleep_timeout.tv_nsec = 0;
while ((errno = clock_nanosleep(CLOCK_BOOTTIME, 0, &sleep_timeout, &sleep_timeout))) {
if (errno == EINTR) {
- if (sigint_received || sighup_received)
+ if (sigint_received || sighup_received || sigusr1_received || sigusr2_received)
break;
continue;
}
@@ -498,20 +570,33 @@ no_fade_in:
}
}
+
fade_out:
+ if (!fade_out_cs)
+ goto faded_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_cs = (size_t)fade_out_cs;
fade_out_have_timer:
original_temperature = current_temperature;
- for (i = 0; i < (size_t)fade_out_cs;) {
- if (sigint_received > 1)
- break;
+ for (i = 0; i < fade_cs;) {
+ if (sigint_received > 1 || sigusr1_received) {
+ goto skip_fade_out;
+ } else if (!sigint_received && !sighup_received) {
+ if (sigusr2_received) {
+ sigusr2_received -= 1;
+ cs = (double)i / fade_cs * fade_in_cs + 0.5;
+ fade_cs = (unsigned long int)cs;
+ goto fade_in_have_timer;
+ }
+ }
- current_temperature = original_temperature + (double)(6500 - original_temperature) * i / fade_out_cs;
+ current_temperature = original_temperature + (double)(6500 - original_temperature) * i / fade_cs;
if (libred_get_colour(current_temperature, &red, &green, &blue))
goto fade_out_fail;
if ((r = set_ramps(red, green, blue)) < 0)
@@ -522,16 +607,37 @@ fade_out_have_timer:
continue;
goto fade_out_fail;
}
- if (overrun > fade_in_cs - i)
- overrun = fade_in_cs - i;
+ if (overrun > fade_cs - i)
+ overrun = fade_cs - i;
i += overrun;
}
+skip_fade_out:
close(tfd);
+
+faded_out:
for (i = 0; i < filters_n; i++)
crtc_updates[i].filter.lifespan = LIBCOOPGAMMA_REMOVE;
- return set_ramps(1, 1, 1);
+ if ((r = set_ramps(red, green, blue)) < 0)
+ return r;
+ for (i = 0; i < filters_n; i++)
+ crtc_updates[i].filter.lifespan = LIBCOOPGAMMA_UNTIL_REMOVAL;
+ for (;;) {
+ sigusr1_received = 0;
+ if (sigint_received || sighup_received) {
+ for (i = 0; i < filters_n; i++)
+ crtc_updates[i].filter.lifespan = LIBCOOPGAMMA_REMOVE;
+ return set_ramps(1, 1, 1);
+ } else if (sigusr2_received) {
+ sigusr2_received -= 1;
+ goto fade_in;
+ }
+
+ if (sigsuspend(&empty_sigset) && errno == EFAULT)
+ abort();
+ }
+
fade_out_fail_use_r:
switch (r) {