aboutsummaryrefslogtreecommitdiffstats
path: root/src/redshift.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/redshift.c')
-rw-r--r--src/redshift.c243
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;
}