diff options
author | Jon Lund Steffensen <jonlst@gmail.com> | 2010-01-01 19:24:01 +0100 |
---|---|---|
committer | Jon Lund Steffensen <jonlst@gmail.com> | 2010-01-01 19:24:01 +0100 |
commit | b61c9d59d7456dc5a4106e5f1e6b767df290d7be (patch) | |
tree | 8ab315b9dac34adbf6ea3aae02c4b2ed43940932 /src/redshift.c | |
parent | Update README, NEWS and ChangeLog for 0.3 release. (diff) | |
download | redshift-ng-b61c9d59d7456dc5a4106e5f1e6b767df290d7be.tar.gz redshift-ng-b61c9d59d7456dc5a4106e5f1e6b767df290d7be.tar.bz2 redshift-ng-b61c9d59d7456dc5a4106e5f1e6b767df290d7be.tar.xz |
Reuse X connection when adjusting gamma ramps.
Save gamma ramps when program starts and restore them on exit (only RANDR).
Try both RANDR and VidMode if nothing was specified, otherwise try only the
specified method.
Diffstat (limited to 'src/redshift.c')
-rw-r--r-- | src/redshift.c | 191 |
1 files changed, 127 insertions, 64 deletions
diff --git a/src/redshift.c b/src/redshift.c index c9904d2..d34009f 100644 --- a/src/redshift.c +++ b/src/redshift.c @@ -28,9 +28,14 @@ #include <time.h> #include <math.h> #include <locale.h> +#include <sys/signal.h> #include "solar.h" +#if !(defined(ENABLE_RANDR) || defined(ENABLE_VIDMODE)) +# error "At least one of RANDR or VidMode must be enabled." +#endif + #ifdef ENABLE_RANDR # include "randr.h" #endif @@ -39,9 +44,16 @@ # include "vidmode.h" #endif -#if !(defined(ENABLE_RANDR) || defined(ENABLE_VIDMODE)) -# error "Either RANDR or VidMode must be enabled." + +/* Union of state data for gamma adjustment methods */ +typedef union { +#ifdef ENABLE_RANDR + randr_state_t randr; #endif +#ifdef ENABLE_VIDMODE + vidmode_state_t vidmode; +#endif +} gamma_state_t; /* Bounds for parameters. */ @@ -88,6 +100,60 @@ #define DEG_CHAR 0xb0 +static volatile sig_atomic_t exiting = 0; + +/* Signal handler for exit signals */ +static void +sigexit(int signo) +{ + exiting = 1; +} + +static void +gamma_state_restore(gamma_state_t *state, int use_randr) +{ +#ifdef ENABLE_RANDR + if (use_randr == 1) randr_restore(&state->randr); +#endif + +#ifdef ENABLE_VIDMODE + if (use_randr == 0) vidmode_restore(&state->vidmode); +#endif +} + +static void +gamma_state_free(gamma_state_t *state, int use_randr) +{ +#ifdef ENABLE_RANDR + if (use_randr == 1) randr_free(&state->randr); +#endif + +#ifdef ENABLE_VIDMODE + if (use_randr == 0) vidmode_free(&state->vidmode); +#endif +} + +static int +gamma_state_set_temperature(gamma_state_t *state, int use_randr, + int temp, float gamma[3]) +{ +#ifdef ENABLE_RANDR + if (use_randr == 1) { + return randr_set_temperature(&state->randr, temp, gamma); + } +#endif + +#ifdef ENABLE_VIDMODE + if (use_randr == 0) { + return vidmode_set_temperature(&state->vidmode, temp, gamma); + } +#endif + + return -1; +} + + +/* Calculate color temperature for the specified solar elevation. */ static int calculate_temp(double elevation, int temp_day, int temp_night, int verbose) @@ -112,58 +178,6 @@ calculate_temp(double elevation, int temp_day, int temp_night, return temp; } -static int -adjust_temperature(int screen_num, int use_randr, int temp, float gamma[3]) -{ - /* Set color temperature */ - int failed = 0; -#ifdef ENABLE_RANDR - if (use_randr) { - /* Check RANDR extension. */ - int r = randr_check_extension(); - if (r < 0) { - fprintf(stderr, "RANDR 1.3 extension is" - " not available.\n"); - failed = 1; - } else { - r = randr_set_temperature(screen_num, temp, gamma); - if (r < 0) { - fprintf(stderr, "Unable to set color" - " temperature with RANDR.\n"); - failed = 1; - } - } - } -#endif - -#ifdef ENABLE_VIDMODE - if (!use_randr || failed) { - failed = 0; - /* Check VidMode extension */ - int r = vidmode_check_extension(); - if (r < 0) { - fprintf(stderr, "VidMode extension is" - " not available.\n"); - failed = 1; - } else { - r = vidmode_set_temperature(screen_num, temp, gamma); - if (r < 0) { - fprintf(stderr, "Unable to set color" - " temperature with VidMode.\n"); - failed = 1; - } - } - } -#endif - - if (failed) { - fprintf(stderr, "Color temperature adjustment failed.\n"); - return -1; - } - - return 0; -} - int main(int argc, char *argv[]) @@ -183,18 +197,13 @@ main(int argc, char *argv[]) int temp_day = DEFAULT_DAY_TEMP; int temp_night = DEFAULT_NIGHT_TEMP; float gamma[3] = { DEFAULT_GAMMA, DEFAULT_GAMMA, DEFAULT_GAMMA }; - int use_randr = 1; + int use_randr = -1; int screen_num = -1; int init_trans = 1; int one_shot = 0; int verbose = 0; char *s; -#ifndef ENABLE_RANDR - /* Don't use RANDR if it has been disabled. */ - use_randr = 0; -#endif - /* Parse arguments. */ int opt; while ((opt = getopt(argc, argv, "g:hl:m:ors:t:v")) != -1) { @@ -345,12 +354,46 @@ main(int argc, char *argv[]) gamma[0], gamma[1], gamma[2]); } + /* Initialize gamma adjustment method. If use_randr is negative + try all methods until one that works is found. */ + gamma_state_t state; +#ifdef ENABLE_RANDR + if (use_randr < 0 || use_randr == 1) { + /* Initialize RANDR state */ + r = randr_init(&state.randr, screen_num); + if (r < 0) { + fprintf(stderr, "Initialization of RANDR failed.\n"); + if (use_randr < 0) { + fprintf(stderr, "Trying other method...\n"); + } else { + exit(EXIT_FAILURE); + } + } else { + use_randr = 1; + } + } +#endif + +#ifdef ENABLE_VIDMODE + if (use_randr < 0 || use_randr == 0) { + /* Initialize VidMode state */ + r = vidmode_init(&state.vidmode, screen_num); + if (r < 0) { + fprintf(stderr, "Initialization of VidMode failed.\n"); + exit(EXIT_FAILURE); + } else { + use_randr = 0; + } + } +#endif + if (one_shot) { /* Current angular elevation of the sun */ struct timespec now; r = clock_gettime(CLOCK_REALTIME, &now); if (r < 0) { perror("clock_gettime"); + gamma_state_free(&state, use_randr); exit(EXIT_FAILURE); } @@ -368,9 +411,11 @@ main(int argc, char *argv[]) if (verbose) printf("Color temperature: %uK\n", temp); /* Adjust temperature */ - r = adjust_temperature(screen_num, use_randr, temp, gamma); + r = gamma_state_set_temperature(&state, use_randr, + temp, gamma); if (r < 0) { fprintf(stderr, "Temperature adjustment failed.\n"); + gamma_state_free(&state, use_randr); exit(EXIT_FAILURE); } } else { @@ -379,18 +424,31 @@ main(int argc, char *argv[]) r = clock_gettime(CLOCK_REALTIME, &short_trans_end); if (r < 0) { perror("clock_gettime"); + gamma_state_free(&state, use_randr); exit(EXIT_FAILURE); } int short_trans_len = 10; short_trans_end.tv_sec += short_trans_len; - while (1) { + /* Install signal handler for SIGINT */ + struct sigaction sigact; + sigset_t sigset; + + sigemptyset(&sigset); + sigact.sa_handler = sigexit; + sigact.sa_mask = sigset; + sigact.sa_flags = 0; + sigaction(SIGINT, &sigact, NULL); + + /* Continously adjust color temperature */ + while (!exiting) { /* Current angular elevation of the sun */ struct timespec now; r = clock_gettime(CLOCK_REALTIME, &now); if (r < 0) { perror("clock_gettime"); + gamma_state_free(&state, use_randr); exit(EXIT_FAILURE); } @@ -417,18 +475,23 @@ main(int argc, char *argv[]) } /* Adjust temperature */ - r = adjust_temperature(screen_num, use_randr, - temp, gamma); + r = gamma_state_set_temperature(&state, use_randr, + temp, gamma); if (r < 0) { fprintf(stderr, "Temperature adjustment" " failed.\n"); + gamma_state_free(&state, use_randr); exit(EXIT_FAILURE); } if (init_trans) usleep(100000); else usleep(5000000); } + + gamma_state_restore(&state, use_randr); } + gamma_state_free(&state, use_randr); + return EXIT_SUCCESS; } |