diff options
Diffstat (limited to 'src/redshift.c')
-rw-r--r-- | src/redshift.c | 243 |
1 files changed, 178 insertions, 65 deletions
diff --git a/src/redshift.c b/src/redshift.c index 9c3f404..59f7482 100644 --- a/src/redshift.c +++ b/src/redshift.c @@ -28,20 +28,30 @@ #include <time.h> #include <math.h> #include <locale.h> -#include <sys/signal.h> -#include <libintl.h> -#define _(s) gettext(s) +#ifdef HAVE_SYS_SIGNAL_H +# include <sys/signal.h> +#endif + +#ifdef ENABLE_NLS +# include <libintl.h> +# define _(s) gettext(s) +#else +# define _(s) s +#endif #include "solar.h" +#include "systemtime.h" #define MIN(x,y) ((x) < (y) ? (x) : (y)) #define MAX(x,y) ((x) > (y) ? (x) : (y)) -#if !(defined(ENABLE_RANDR) || defined(ENABLE_VIDMODE)) -# error "At least one of RANDR or VidMode must be enabled." +#if !(defined(ENABLE_RANDR) || \ + defined(ENABLE_VIDMODE) || \ + defined(ENABLE_WINGDI)) +# error "At least one of RANDR, VidMode or WinGDI must be enabled." #endif #ifdef ENABLE_RANDR @@ -52,6 +62,10 @@ # include "vidmode.h" #endif +#ifdef ENABLE_WINGDI +# include "w32gdi.h" +#endif + /* Union of state data for gamma adjustment methods */ typedef union { @@ -61,8 +75,19 @@ typedef union { #ifdef ENABLE_VIDMODE vidmode_state_t vidmode; #endif +#ifdef ENABLE_WINGDI + w32gdi_state_t w32gdi; +#endif } gamma_state_t; +/* Enum of gamma adjustment methods */ +typedef enum { + GAMMA_METHOD_RANDR, + GAMMA_METHOD_VIDMODE, + GAMMA_METHOD_WINGDI, + GAMMA_METHOD_MAX +} gamma_method_t; + /* Bounds for parameters. */ #define MIN_LAT -90.0 @@ -87,6 +112,8 @@ typedef union { #define TRANSITION_HIGH 3.0 +#ifdef HAVE_SYS_SIGNAL_H + static volatile sig_atomic_t exiting = 0; static volatile sig_atomic_t disable = 0; @@ -104,57 +131,84 @@ sigdisable(int signo) disable = 1; } +#else /* ! HAVE_SYS_SIGNAL_H */ + +static int exiting = 0; +static int disable = 0; + +#endif /* ! HAVE_SYS_SIGNAL_H */ + /* Restore saved gamma ramps with the appropriate adjustment method. */ static void -gamma_state_restore(gamma_state_t *state, int use_randr) +gamma_state_restore(gamma_state_t *state, gamma_method_t method) { - switch (use_randr) { + switch (method) { +#ifdef ENABLE_RANDR + case GAMMA_METHOD_RANDR: + randr_restore(&state->randr); + break; +#endif #ifdef ENABLE_VIDMODE - case 0: + case GAMMA_METHOD_VIDMODE: vidmode_restore(&state->vidmode); break; #endif -#ifdef ENABLE_RANDR - case 1: - randr_restore(&state->randr); +#ifdef ENABLE_WINGDI + case GAMMA_METHOD_WINGDI: + w32gdi_restore(&state->w32gdi); break; #endif + default: + break; } } /* Free the state associated with the appropriate adjustment method. */ static void -gamma_state_free(gamma_state_t *state, int use_randr) +gamma_state_free(gamma_state_t *state, gamma_method_t method) { - switch (use_randr) { + switch (method) { +#ifdef ENABLE_RANDR + case GAMMA_METHOD_RANDR: + randr_free(&state->randr); + break; +#endif #ifdef ENABLE_VIDMODE - case 0: + case GAMMA_METHOD_VIDMODE: vidmode_free(&state->vidmode); break; #endif -#ifdef ENABLE_RANDR - case 1: - randr_free(&state->randr); +#ifdef ENABLE_WINGDI + case GAMMA_METHOD_WINGDI: + w32gdi_free(&state->w32gdi); break; #endif + default: + break; } } /* Set temperature with the appropriate adjustment method. */ static int -gamma_state_set_temperature(gamma_state_t *state, int use_randr, +gamma_state_set_temperature(gamma_state_t *state, gamma_method_t method, int temp, float gamma[3]) { - switch (use_randr) { + switch (method) { +#ifdef ENABLE_RANDR + case GAMMA_METHOD_RANDR: + return randr_set_temperature(&state->randr, temp, gamma); +#endif #ifdef ENABLE_VIDMODE - case 0: + case GAMMA_METHOD_VIDMODE: return vidmode_set_temperature(&state->vidmode, temp, gamma); #endif -#ifdef ENABLE_RANDR - case 1: - return randr_set_temperature(&state->randr, temp, gamma); +#ifdef ENABLE_WINGDI + case GAMMA_METHOD_WINGDI: + return w32gdi_set_temperature(&state->w32gdi, temp, gamma); #endif + default: + break; } return -1; @@ -216,16 +270,25 @@ print_help(const char *program_name) fputs(_(" -g R:G:B\tAdditional gamma correction to apply\n" " -l LAT:LON\tYour current location\n" " -m METHOD\tMethod to use to set color temperature" - " (randr or vidmode)\n" + " (RANDR, VidMode or WinGDI)\n" " -o\t\tOne shot mode (do not continously adjust" " color temperature)\n" - " -r\t\tDisable initial temperature transition\n" + " -r\t\tDisable temperature transitions\n" " -s SCREEN\tX screen to apply adjustments to\n" + " -c CRTC\tCRTC to apply adjustments to (RANDR only)\n" " -t DAY:NIGHT\tColor temperature to set at daytime/night\n"), stdout); fputs("\n", stdout); /* TRANSLATORS: help output 5 */ + printf(_("Default values:\n\n" + " Daytime temperature: %uK\n" + " Night temperature: %uK\n"), + DEFAULT_DAY_TEMP, DEFAULT_NIGHT_TEMP); + + fputs("\n", stdout); + + /* TRANSLATORS: help output 6 */ printf("Please report bugs to <%s>\n", PACKAGE_BUGREPORT); } @@ -235,11 +298,11 @@ main(int argc, char *argv[]) { int r; +#ifdef ENABLE_NLS /* Init locale */ setlocale(LC_CTYPE, ""); setlocale(LC_MESSAGES, ""); -#ifdef ENABLE_NLS /* Internationalisation */ bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); @@ -251,8 +314,9 @@ 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 method = -1; int screen_num = -1; + int crtc_num = -1; int transition = 1; int one_shot = 0; int verbose = 0; @@ -260,8 +324,11 @@ main(int argc, char *argv[]) /* Parse arguments. */ int opt; - while ((opt = getopt(argc, argv, "g:hl:m:ors:t:v")) != -1) { + while ((opt = getopt(argc, argv, "c:g:hl:m:ors:t:v")) != -1) { switch (opt) { + case 'c': + crtc_num = atoi(optarg); + break; case 'g': s = strchr(optarg, ':'); if (s == NULL) { @@ -308,7 +375,7 @@ main(int argc, char *argv[]) if (strcmp(optarg, "randr") == 0 || strcmp(optarg, "RANDR") == 0) { #ifdef ENABLE_RANDR - use_randr = 1; + method = GAMMA_METHOD_RANDR; #else fputs(_("RANDR method was not" " enabled at compile time.\n"), @@ -318,13 +385,23 @@ main(int argc, char *argv[]) } else if (strcmp(optarg, "vidmode") == 0 || strcmp(optarg, "VidMode") == 0) { #ifdef ENABLE_VIDMODE - use_randr = 0; + method = GAMMA_METHOD_VIDMODE; #else fputs(_("VidMode method was not" " enabled at compile time.\n"), stderr); exit(EXIT_FAILURE); #endif + } else if (strcmp(optarg, "wingdi") == 0 || + strcmp(optarg, "WinGDI") == 0) { +#ifdef ENABLE_WINGDI + method = GAMMA_METHOD_WINGDI; +#else + fputs(_("WinGDI method was not" + " enabled at compile time.\n"), + stderr); + exit(EXIT_FAILURE); +#endif } else { /* TRANSLATORS: This refers to the method used to adjust colors e.g VidMode */ @@ -426,47 +503,82 @@ main(int argc, char *argv[]) gamma[0], gamma[1], gamma[2]); } - /* Initialize gamma adjustment method. If use_randr is negative + /* CRTC can only be selected for RANDR */ + if (crtc_num > -1 && method != GAMMA_METHOD_RANDR) { + fprintf(stderr, _("CRTC can only be selected" + " with the RANDR method.\n")); + exit(EXIT_FAILURE); + } + + /* Initialize gamma adjustment method. If method 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) { + if (method < 0 || method == GAMMA_METHOD_RANDR) { /* Initialize RANDR state */ - r = randr_init(&state.randr, screen_num); + r = randr_init(&state.randr, screen_num, crtc_num); if (r < 0) { fputs(_("Initialization of RANDR failed.\n"), stderr); - if (use_randr < 0) { + if (method < 0) { fputs(_("Trying other method...\n"), stderr); } else { exit(EXIT_FAILURE); } } else { - use_randr = 1; + method = GAMMA_METHOD_RANDR; } } #endif #ifdef ENABLE_VIDMODE - if (use_randr < 0 || use_randr == 0) { + if (method < 0 || method == GAMMA_METHOD_VIDMODE) { /* Initialize VidMode state */ r = vidmode_init(&state.vidmode, screen_num); if (r < 0) { fputs(_("Initialization of VidMode failed.\n"), stderr); - exit(EXIT_FAILURE); + if (method < 0) { + fputs(_("Trying other method...\n"), stderr); + } else { + exit(EXIT_FAILURE); + } } else { - use_randr = 0; + method = GAMMA_METHOD_VIDMODE; } } #endif +#ifdef ENABLE_WINGDI + if (method < 0 || method == GAMMA_METHOD_WINGDI) { + /* Initialize WinGDI state */ + r = w32gdi_init(&state.w32gdi); + if (r < 0) { + fputs(_("Initialization of WinGDI failed.\n"), + stderr); + if (method < 0) { + fputs(_("Trying other method...\n"), stderr); + } else { + exit(EXIT_FAILURE); + } + } else { + method = GAMMA_METHOD_WINGDI; + } + } +#endif + + /* Failure if no methods were successful at this point. */ + if (method < 0) { + fputs(_("No more methods to try.\n"), stderr); + exit(EXIT_FAILURE); + } + if (one_shot) { /* Current angular elevation of the sun */ - struct timespec now; - r = clock_gettime(CLOCK_REALTIME, &now); + double now; + r = systemtime_get_time(&now); if (r < 0) { - perror("clock_gettime"); - gamma_state_free(&state, use_randr); + fputs(_("Unable to read system time.\n"), stderr); + gamma_state_free(&state, method); exit(EXIT_FAILURE); } @@ -484,16 +596,15 @@ main(int argc, char *argv[]) if (verbose) printf(_("Color temperature: %uK\n"), temp); /* Adjust temperature */ - r = gamma_state_set_temperature(&state, use_randr, - temp, gamma); + r = gamma_state_set_temperature(&state, method, temp, gamma); if (r < 0) { fputs(_("Temperature adjustment failed.\n"), stderr); - gamma_state_free(&state, use_randr); + gamma_state_free(&state, method); exit(EXIT_FAILURE); } } else { /* Transition state */ - struct timespec short_trans_end; + double short_trans_end = 0; int short_trans = 0; int short_trans_done = 0; @@ -507,6 +618,7 @@ main(int argc, char *argv[]) will be exactly 6500K. */ float adjustment_alpha = 0.0; +#ifdef HAVE_SYS_SIGNAL_H struct sigaction sigact; sigset_t sigset; sigemptyset(&sigset); @@ -523,6 +635,7 @@ main(int argc, char *argv[]) sigact.sa_mask = sigset; sigact.sa_flags = 0; sigaction(SIGUSR1, &sigact, NULL); +#endif /* HAVE_SYS_SIGNAL_H */ /* Continously adjust color temperature */ int done = 0; @@ -568,22 +681,20 @@ main(int argc, char *argv[]) } /* Read timestamp */ - struct timespec now; - r = clock_gettime(CLOCK_REALTIME, &now); + double now; + r = systemtime_get_time(&now); if (r < 0) { - perror("clock_gettime"); - gamma_state_free(&state, use_randr); + fputs(_("Unable to read system time.\n"), + stderr); + gamma_state_free(&state, method); exit(EXIT_FAILURE); } /* Set up a new transition */ if (short_trans_create) { if (transition) { - memcpy(&short_trans_end, &now, - sizeof(struct timespec)); - short_trans_end.tv_sec += - short_trans_len; - + short_trans_end = now; + short_trans_end += short_trans_len; short_trans = 1; short_trans_create = 0; } else { @@ -600,11 +711,8 @@ main(int argc, char *argv[]) /* Ongoing short transition */ if (short_trans) { - double start = now.tv_sec + - now.tv_nsec / 1000000000.0; - double end = short_trans_end.tv_sec + - short_trans_end.tv_nsec / - 1000000000.0; + double start = now; + double end = short_trans_end; if (start > end) { /* Transisiton done */ @@ -629,7 +737,7 @@ main(int argc, char *argv[]) if (short_trans_done) { if (disabled) { /* Restore saved gamma ramps */ - gamma_state_restore(&state, use_randr); + gamma_state_restore(&state, method); } short_trans_done = 0; } @@ -649,27 +757,32 @@ main(int argc, char *argv[]) /* Adjust temperature */ if (!disabled || short_trans) { r = gamma_state_set_temperature(&state, - use_randr, + method, temp, gamma); if (r < 0) { fputs(_("Temperature adjustment" " failed.\n"), stderr); - gamma_state_free(&state, use_randr); + gamma_state_free(&state, method); exit(EXIT_FAILURE); } } /* Sleep for a while */ +#ifndef _WIN32 if (short_trans) usleep(100000); else usleep(5000000); +#else /* ! _WIN32 */ + if (short_trans) Sleep(100); + else Sleep(5000); +#endif /* ! _WIN32 */ } /* Restore saved gamma ramps */ - gamma_state_restore(&state, use_randr); + gamma_state_restore(&state, method); } /* Clean up gamma adjustment state */ - gamma_state_free(&state, use_randr); + gamma_state_free(&state, method); return EXIT_SUCCESS; } |