aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--TODO2
-rw-r--r--radharc.116
-rw-r--r--radharc.c144
3 files changed, 141 insertions, 21 deletions
diff --git a/TODO b/TODO
index 0cf04b5..f187ecb 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,4 @@
On fade in, query active setting and start from there. (requires libred>=1.1)
Use bus for changing settings and CRTCs online.
Add "-t ?" and "-t get" for getting the current temperature. (requires libred>=1.1)
-On SIGUSR1, fade out without terminating
-On SIGUSR2, fade in
Add PF_UNIX SOCK_DGRAM socket with abstract address @/proc/<pid>/radharc for IPC
diff --git a/radharc.1 b/radharc.1
index df9fb8d..1f4e030 100644
--- a/radharc.1
+++ b/radharc.1
@@ -172,6 +172,22 @@ sent twice, the effect is removed immediately.
.B SIGHUP
Terminate the process after any current fade in or fade
out action, but leaf the effect in place.
+.TP
+.B SIGUSR1
+Gradually fade out the effect but do not terminate the process.
+
+If the fade out time is 0 (default) or if the signal is
+sent twice, the effect is removed immediately.
+.TP
+.B SIGUSR2
+Gradually fade the effect back in (from
+.IR SIGUSR1 ).
+
+If the fade in time is 0 (default) or if the signal is
+sent twice, the effect is restored immediately.
+
+If sent during the initial fade in, the fade in is cancelled
+and the full effect is immediately applied
.SH SEE ALSO
.BR coopgammad (1),
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) {