diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 11 | ||||
-rw-r--r-- | src/redshift.c | 117 | ||||
-rw-r--r-- | src/solar.c | 42 | ||||
-rw-r--r-- | src/solar.h | 8 | ||||
-rw-r--r-- | src/systemtime.c | 52 | ||||
-rw-r--r-- | src/systemtime.h | 32 | ||||
-rw-r--r-- | src/w32gdi.c | 127 | ||||
-rw-r--r-- | src/w32gdi.h | 37 |
8 files changed, 376 insertions, 50 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index f23ab0b..c46c9ba 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,11 +11,13 @@ bin_PROGRAMS = redshift redshift_SOURCES = \ redshift.c \ colorramp.c colorramp.h \ - solar.c solar.h + solar.c solar.h \ + systemtime.c systemtime.h EXTRA_redshift_SOURCES = \ randr.c randr.h \ - vidmode.c vidmode.h + vidmode.c vidmode.h \ + w32gdi.c w32gdi.h AM_CFLAGS = redshift_LDADD = @LIBINTL@ @@ -36,3 +38,8 @@ redshift_LDADD += \ $(X11_LIBS) $(X11_CFLAGS) \ $(XF86VM_LIBS) $(XF86VM_CFLAGS) endif + +if ENABLE_WINGDI +redshift_SOURCES += w32gdi.c w32gdi.h +redshift_LDADD += -lgdi32 +endif diff --git a/src/redshift.c b/src/redshift.c index f95c376..781af78 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,6 +75,9 @@ typedef union { #ifdef ENABLE_VIDMODE vidmode_state_t vidmode; #endif +#ifdef ENABLE_WINGDI + w32gdi_state_t w32gdi; +#endif } gamma_state_t; @@ -129,6 +146,11 @@ gamma_state_restore(gamma_state_t *state, int use_randr) randr_restore(&state->randr); break; #endif +#ifdef ENABLE_WINGDI + case 2: + w32gdi_restore(&state->w32gdi); + break; +#endif } } @@ -147,6 +169,11 @@ gamma_state_free(gamma_state_t *state, int use_randr) randr_free(&state->randr); break; #endif +#ifdef ENABLE_WINGDI + case 2: + w32gdi_free(&state->w32gdi); + break; +#endif } } @@ -164,6 +191,10 @@ gamma_state_set_temperature(gamma_state_t *state, int use_randr, case 1: return randr_set_temperature(&state->randr, temp, gamma); #endif +#ifdef ENABLE_WINGDI + case 2: + return w32gdi_set_temperature(&state->w32gdi, temp, gamma); +#endif } return -1; @@ -225,7 +256,7 @@ 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 temperature transitions\n" @@ -347,6 +378,16 @@ main(int argc, char *argv[]) stderr); exit(EXIT_FAILURE); #endif + } else if (strcmp(optarg, "wingdi") == 0 || + strcmp(optarg, "WinGDI") == 0) { +#ifdef ENABLE_WINGDI + use_randr = 2; +#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 */ @@ -482,19 +523,47 @@ main(int argc, char *argv[]) if (r < 0) { fputs(_("Initialization of VidMode failed.\n"), stderr); - exit(EXIT_FAILURE); + if (use_randr < 0) { + fputs(_("Trying other method...\n"), stderr); + } else { + exit(EXIT_FAILURE); + } } else { use_randr = 0; } } #endif +#ifdef ENABLE_WINGDI + if (use_randr < 0 || use_randr == 2) { + /* Initialize WinGDI state */ + r = w32gdi_init(&state.w32gdi); + if (r < 0) { + fputs(_("Initialization of WinGDI failed.\n"), + stderr); + if (use_randr < 0) { + fputs(_("Trying other method...\n"), stderr); + } else { + exit(EXIT_FAILURE); + } + } else { + use_randr = 2; + } + } +#endif + + /* Failure if no methods were successful at this point. */ + if (use_randr < 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"); + fputs(_("Unable to read system time.\n"), stderr); gamma_state_free(&state, use_randr); exit(EXIT_FAILURE); } @@ -522,7 +591,7 @@ main(int argc, char *argv[]) } } else { /* Transition state */ - struct timespec short_trans_end; + double short_trans_end = 0; int short_trans = 0; int short_trans_done = 0; @@ -599,10 +668,11 @@ 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"); + fputs(_("Unable to read system time.\n"), + stderr); gamma_state_free(&state, use_randr); exit(EXIT_FAILURE); } @@ -610,11 +680,8 @@ main(int argc, char *argv[]) /* 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 { @@ -631,11 +698,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 */ @@ -691,8 +755,13 @@ main(int argc, char *argv[]) } /* 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 */ diff --git a/src/solar.c b/src/solar.c index 9b63c40..9b2b59d 100644 --- a/src/solar.c +++ b/src/solar.c @@ -24,9 +24,9 @@ Jean Meeus. */ #include <math.h> -#include <time.h> #include "solar.h" +#include "time.h" #define RAD(x) ((x)*(M_PI/180)) #define DEG(x) ((x)*(180/M_PI)) @@ -46,23 +46,20 @@ static const double time_angle[] = { }; -/* Unix time from Julian day */ -static struct timespec -timespec_from_jd(double jd) +/* Unix epoch from Julian day */ +static double +epoch_from_jd(double jd) { - struct timespec t; - double secs = 86400.0*(jd - 2440587.5); - t.tv_sec = floor(secs); - t.tv_nsec = (secs - t.tv_sec) * 1000000000.0; - return t; + return 86400.0*(jd - 2440587.5); } -/* Julian day from unix time */ + + +/* Julian day from unix epoch */ static double -jd_from_timespec(struct timespec t) +jd_from_epoch(double t) { - return (t.tv_sec / 86400.0) + - (t.tv_nsec / 86400000000000.0) + 2440587.5; + return (t / 86400.0) + 2440587.5; } /* Julian centuries since J2000.0 from Julian day */ @@ -287,18 +284,23 @@ solar_elevation_from_time(double t, double lat, double lon) return elevation_from_hour_angle(lat, decl, ha); } +/* Solar angular elevation at the given location and time. + date: Seconds since unix epoch + lat: Latitude of location + lon: Longitude of location + Return: Solar angular elevation in degrees */ double -solar_elevation(struct timespec date, double lat, double lon) +solar_elevation(double date, double lat, double lon) { - double jd = jd_from_timespec(date); + double jd = jd_from_epoch(date); return DEG(solar_elevation_from_time(jcent_from_jd(jd), lat, lon)); } void -solar_table_fill(struct timespec date, double lat, double lon, time_t *table) +solar_table_fill(double date, double lat, double lon, double *table) { /* Calculate Julian day */ - double jd = jd_from_timespec(date); + double jd = jd_from_epoch(date); /* Calculate Julian day number */ double jdn = round(jd); @@ -308,16 +310,16 @@ solar_table_fill(struct timespec date, double lat, double lon, time_t *table) double sol_noon = time_of_solar_noon(t, lon); double j_noon = jdn - 0.5 + sol_noon/1440.0; double t_noon = jcent_from_jd(j_noon); - table[SOLAR_TIME_NOON] = timespec_from_jd(j_noon).tv_sec; + table[SOLAR_TIME_NOON] = epoch_from_jd(j_noon); /* Calculate solar midnight */ - table[SOLAR_TIME_MIDNIGHT] = timespec_from_jd(j_noon + 0.5).tv_sec; + table[SOLAR_TIME_MIDNIGHT] = epoch_from_jd(j_noon + 0.5); /* Calulate absoute time of other phenomena */ for (int i = 2; i < SOLAR_TIME_MAX; i++) { double angle = time_angle[i]; double offset = time_of_solar_elevation(t, t_noon, lat, lon, angle); - table[i] = timespec_from_jd(jdn - 0.5 + offset/1440.0).tv_sec; + table[i] = epoch_from_jd(jdn - 0.5 + offset/1440.0); } } diff --git a/src/solar.h b/src/solar.h index a55c83a..b5554ef 100644 --- a/src/solar.h +++ b/src/solar.h @@ -20,7 +20,7 @@ #ifndef _SOLAR_H #define _SOLAR_H -#include <time.h> +#include "time.h" /* Model of atmospheric refraction near horizon (in degrees). */ #define SOLAR_ATM_REFRAC 0.833 @@ -44,8 +44,8 @@ typedef enum { SOLAR_TIME_MAX } solar_time_t; -double solar_elevation(struct timespec date, double lat, double lon); -void solar_table_fill(struct timespec date, double lat, double lon, - time_t *table); + +double solar_elevation(double date, double lat, double lon); +void solar_table_fill(double date, double lat, double lon, double *table); #endif /* ! _SOLAR_H */ diff --git a/src/systemtime.c b/src/systemtime.c new file mode 100644 index 0000000..abbb5ae --- /dev/null +++ b/src/systemtime.c @@ -0,0 +1,52 @@ +/* systemtime.c -- Portable system time source + This file is part of Redshift. + + Redshift is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Redshift is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Redshift. If not, see <http://www.gnu.org/licenses/>. + + Copyright (c) 2010 Jon Lund Steffensen <jonlst@gmail.com> +*/ + +#include <stdio.h> + +#ifndef _WIN32 +# include <time.h> +#endif + +#include "systemtime.h" + +int +systemtime_get_time(double *t) +{ +#ifndef _WIN32 + struct timespec now; + int r = clock_gettime(CLOCK_REALTIME, &now); + if (r < 0) { + perror("clock_gettime"); + return -1; + } + + *t = now.tv_sec + (now.tv_nsec / 1000000000.0); +#else /* _WIN32 */ + FILETIME now; + ULARGE_INTEGER i; + GetSystemTimeAsFileTime(&now); + i.LowPart = now.dwLowDateTime; + i.HighPart = now.dwHighDateTime; + + /* FILETIME is tenths of microseconds since 1601-01-01 UTC */ + *t = (i.QuadPart / 10000000.0) - 11644473600.0; +#endif /* _WIN32 */ + + return 0; +} diff --git a/src/systemtime.h b/src/systemtime.h new file mode 100644 index 0000000..1d51217 --- /dev/null +++ b/src/systemtime.h @@ -0,0 +1,32 @@ +/* systemtime.h -- Portable system time header + This file is part of Redshift. + + Redshift is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Redshift is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Redshift. If not, see <http://www.gnu.org/licenses/>. + + Copyright (c) 2010 Jon Lund Steffensen <jonlst@gmail.com> +*/ + +#ifndef _REDSHIFT_SYSTEMTIME_H +#define _REDSHIFT_SYSTEMTIME_H + +#ifndef _WIN32 +# include <time.h> +#else +# include <windows.h> +#endif + + +int systemtime_get_time(double *now); + +#endif /* ! _REDSHIFT_SYSTEMTIME_H */ diff --git a/src/w32gdi.c b/src/w32gdi.c new file mode 100644 index 0000000..9d1f143 --- /dev/null +++ b/src/w32gdi.c @@ -0,0 +1,127 @@ +/* w32gdi.c -- Windows GDI gamma adjustment source + This file is part of Redshift. + + Redshift is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Redshift is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Redshift. If not, see <http://www.gnu.org/licenses/>. + + Copyright (c) 2010 Jon Lund Steffensen <jonlst@gmail.com> +*/ + +#include <stdlib.h> +#include <stdio.h> + +#define WINVER 0x0500 +#include <windows.h> +#include <wingdi.h> + +#ifdef ENABLE_NLS +# include <libintl.h> +# define _(s) gettext(s) +#else +# define _(s) s +#endif + +#include "w32gdi.h" +#include "colorramp.h" + +#define GAMMA_RAMP_SIZE 256 + + +int +w32gdi_init(w32gdi_state_t *state) +{ + BOOL r; + + /* Open device context */ + state->hDC = GetDC(NULL); + if (state->hDC == NULL) { + fputs(_("Unable to open device context.\n"), stderr); + return -1; + } + + /* Check support for gamma ramps */ + int cmcap = GetDeviceCaps(state->hDC, COLORMGMTCAPS); + if (cmcap != CM_GAMMA_RAMP) { + fputs(_("Display device does not support gamma ramps.\n"), + stderr); + return -1; + } + + /* Allocate space for saved gamma ramps */ + state->saved_ramps = malloc(3*GAMMA_RAMP_SIZE*sizeof(WORD)); + if (state->saved_ramps == NULL) { + perror("malloc"); + ReleaseDC(NULL, state->hDC); + return -1; + } + + /* Save current gamma ramps so we can restore them at program exit */ + r = GetDeviceGammaRamp(state->hDC, state->saved_ramps); + if (!r) { + fputs(_("Unable to save current gamma ramp.\n"), stderr); + ReleaseDC(NULL, state->hDC); + return -1; + } + + return 0; +} + +void +w32gdi_free(w32gdi_state_t *state) +{ + /* Free saved ramps */ + free(state->saved_ramps); + + /* Release device context */ + ReleaseDC(NULL, state->hDC); +} + +void +w32gdi_restore(w32gdi_state_t *state) +{ + /* Restore gamma ramps */ + BOOL r = SetDeviceGammaRamp(state->hDC, state->saved_ramps); + if (!r) fputs(_("Unable to restore gamma ramps.\n"), stderr); +} + +int +w32gdi_set_temperature(w32gdi_state_t *state, int temp, float gamma[3]) +{ + BOOL r; + + /* Create new gamma ramps */ + WORD *gamma_ramps = malloc(3*GAMMA_RAMP_SIZE*sizeof(WORD)); + if (gamma_ramps == NULL) { + perror("malloc"); + return -1; + } + + WORD *gamma_r = &gamma_ramps[0*GAMMA_RAMP_SIZE]; + WORD *gamma_g = &gamma_ramps[1*GAMMA_RAMP_SIZE]; + WORD *gamma_b = &gamma_ramps[2*GAMMA_RAMP_SIZE]; + + colorramp_fill(gamma_r, gamma_g, gamma_b, GAMMA_RAMP_SIZE, + temp, gamma); + + /* Set new gamma ramps */ + r = SetDeviceGammaRamp(state->hDC, gamma_ramps); + if (!r) { + fputs(_("Unable to set gamma ramps.\n"), stderr); + free(gamma_ramps); + return -1; + } + + free(gamma_ramps); + + return 0; +} diff --git a/src/w32gdi.h b/src/w32gdi.h new file mode 100644 index 0000000..e658699 --- /dev/null +++ b/src/w32gdi.h @@ -0,0 +1,37 @@ +/* w32gdi.h -- Windows GDI gamma adjustment header + This file is part of Redshift. + + Redshift is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Redshift is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Redshift. If not, see <http://www.gnu.org/licenses/>. + + Copyright (c) 2010 Jon Lund Steffensen <jonlst@gmail.com> +*/ + +#ifndef _REDSHIFT_W32GDI_H +#define _REDSHIFT_W32GDI_H + +#include <windows.h> +#include <wingdi.h> + + +typedef struct { + HDC hDC; + WORD *saved_ramps; +} w32gdi_state_t; + +int w32gdi_init(w32gdi_state_t *state); +void w32gdi_free(w32gdi_state_t *state); +void w32gdi_restore(w32gdi_state_t *state); +int w32gdi_set_temperature(w32gdi_state_t *state, int temp, float gamma[3]); + +#endif /* ! _REDSHIFT_W32GDI_H */ |