diff options
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | radharc.1 | 16 | ||||
-rw-r--r-- | radharc.c | 144 |
3 files changed, 141 insertions, 21 deletions
@@ -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 @@ -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), @@ -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) { |