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) {  | 
