diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 45 | ||||
-rw-r--r-- | src/gtk-redshift/Makefile.am | 19 | ||||
-rw-r--r-- | src/gtk-redshift/__init__.py | 20 | ||||
-rw-r--r-- | src/gtk-redshift/defs.py.in | 1 | ||||
-rw-r--r-- | src/gtk-redshift/gtk-redshift | 23 | ||||
-rw-r--r--[-rwxr-xr-x] | src/gtk-redshift/statusicon.py (renamed from src/gtk-redshift/gtk-redshift.py) | 8 | ||||
-rw-r--r-- | src/randr.c | 93 | ||||
-rw-r--r-- | src/randr.h | 3 | ||||
-rw-r--r-- | src/redshift.c | 243 | ||||
-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 |
15 files changed, 629 insertions, 124 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..c46c9ba --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,45 @@ + +SUBDIRS = gtk-redshift + +# I18n +localedir = $(datadir)/locale +INCLUDES = -DLOCALEDIR=\"$(localedir)\" + +# redshift Program +bin_PROGRAMS = redshift + +redshift_SOURCES = \ + redshift.c \ + colorramp.c colorramp.h \ + solar.c solar.h \ + systemtime.c systemtime.h + +EXTRA_redshift_SOURCES = \ + randr.c randr.h \ + vidmode.c vidmode.h \ + w32gdi.c w32gdi.h + +AM_CFLAGS = +redshift_LDADD = @LIBINTL@ +EXTRA_DIST = + +if ENABLE_RANDR +redshift_SOURCES += randr.c randr.h +AM_CFLAGS += $(XCB_CFLAGS) $(XCB_RANDR_CFLAGS) +redshift_LDADD += \ + $(XCB_LIBS) $(XCB_CFLAGS) \ + $(XCB_RANDR_LIBS) $(XCB_RANDR_CFLAGS) +endif + +if ENABLE_VIDMODE +redshift_SOURCES += vidmode.c vidmode.h +AM_CFLAGS += $(X11_CFLAGS) $(XF86VM_CFLAGS) +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/gtk-redshift/Makefile.am b/src/gtk-redshift/Makefile.am new file mode 100644 index 0000000..d0d8695 --- /dev/null +++ b/src/gtk-redshift/Makefile.am @@ -0,0 +1,19 @@ + +if ENABLE_GTK +gtk_redshift_PYTHON = \ + __init__.py \ + statusicon.py +nodist_gtk_redshift_PYTHON = \ + defs.py +gtk_redshiftdir = $(pythondir)/gtk_redshift + +dist_bin_SCRIPTS = gtk-redshift +EXTRA_DIST = defs.py.in +endif + +CLEANFILES = defs.py + +# Local python definitions +defs.py: defs.py.in + sed -e "s|\@bindir\@|$(bindir)|g" \ + -e "s|\@localedir\@|$(localedir)|g" $< > $@ diff --git a/src/gtk-redshift/__init__.py b/src/gtk-redshift/__init__.py new file mode 100644 index 0000000..30205ca --- /dev/null +++ b/src/gtk-redshift/__init__.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# __init__.py -- gtk-redshift package __init__ file +# 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> + +__all__ = ['statusicon'] diff --git a/src/gtk-redshift/defs.py.in b/src/gtk-redshift/defs.py.in index 91eccf9..d3ca5ed 100644 --- a/src/gtk-redshift/defs.py.in +++ b/src/gtk-redshift/defs.py.in @@ -19,3 +19,4 @@ LOCALEDIR = '@localedir@' +BINDIR = '@bindir@' diff --git a/src/gtk-redshift/gtk-redshift b/src/gtk-redshift/gtk-redshift new file mode 100644 index 0000000..f62c6f1 --- /dev/null +++ b/src/gtk-redshift/gtk-redshift @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# gtk-redshift -- GTK+ Redshift launcher script +# 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> + + +if __name__ == '__main__': + from gtk_redshift.statusicon import run_statusicon + run_statusicon() diff --git a/src/gtk-redshift/gtk-redshift.py b/src/gtk-redshift/statusicon.py index a737154..9925c35 100755..100644 --- a/src/gtk-redshift/gtk-redshift.py +++ b/src/gtk-redshift/statusicon.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# gtk-redshift -- GTK+ status icon source +# statusicon.py -- GTK+ status icon source # This file is part of Redshift. # Redshift is free software: you can redistribute it and/or modify @@ -18,7 +18,7 @@ # Copyright (c) 2010 Jon Lund Steffensen <jonlst@gmail.com> -import sys +import sys, os import subprocess, signal import gettext @@ -30,7 +30,7 @@ import gtk, glib import defs -if __name__ == '__main__': +def run_statusicon(): # Internationalisation gettext.bindtextdomain('redshift', defs.LOCALEDIR) gettext.textdomain('redshift') @@ -38,7 +38,7 @@ if __name__ == '__main__': # Start redshift with arguments from the command line args = sys.argv[1:] - args.insert(0, 'redshift') + args.insert(0, os.path.join(defs.BINDIR, 'redshift')) process = subprocess.Popen(args) try: diff --git a/src/randr.c b/src/randr.c index 7c05b26..f401190 100644 --- a/src/randr.c +++ b/src/randr.c @@ -36,7 +36,7 @@ int -randr_init(randr_state_t *state, int screen_num) +randr_init(randr_state_t *state, int screen_num, int crtc_num) { xcb_generic_error_t *error; @@ -108,6 +108,7 @@ randr_init(randr_state_t *state, int screen_num) return -1; } + state->crtc_num = crtc_num; state->crtc_count = res_reply->num_crtcs; state->crtcs = malloc(state->crtc_count * sizeof(randr_crtc_state_t)); if (state->crtcs == NULL) { @@ -248,45 +249,77 @@ randr_free(randr_state_t *state) xcb_disconnect(state->conn); } -int -randr_set_temperature(randr_state_t *state, int temp, float gamma[3]) +static int +randr_set_temperature_for_crtc(randr_state_t *state, int crtc_num, int temp, + float gamma[3]) { xcb_generic_error_t *error; + + if (crtc_num >= state->crtc_count || crtc_num < 0) { + fprintf(stderr, _("CRTC %d does not exist. "), + state->crtc_num); + if (state->crtc_count > 1) { + fprintf(stderr, _("Valid CRTCs are [0-%d].\n"), + state->crtc_count-1); + } else { + fprintf(stderr, _("Only CRTC 0 exists.\n")); + } - /* Set temperature on all CRTCs */ - for (int i = 0; i < state->crtc_count; i++) { - xcb_randr_crtc_t crtc = state->crtcs[i].crtc; - unsigned int ramp_size = state->crtcs[i].ramp_size; + return -1; + } - /* Create new gamma ramps */ - uint16_t *gamma_ramps = malloc(3*ramp_size*sizeof(uint16_t)); - if (gamma_ramps == NULL) { - perror("malloc"); - return -1; - } + xcb_randr_crtc_t crtc = state->crtcs[crtc_num].crtc; + unsigned int ramp_size = state->crtcs[crtc_num].ramp_size; - uint16_t *gamma_r = &gamma_ramps[0*ramp_size]; - uint16_t *gamma_g = &gamma_ramps[1*ramp_size]; - uint16_t *gamma_b = &gamma_ramps[2*ramp_size]; + /* Create new gamma ramps */ + uint16_t *gamma_ramps = malloc(3*ramp_size*sizeof(uint16_t)); + if (gamma_ramps == NULL) { + perror("malloc"); + return -1; + } - colorramp_fill(gamma_r, gamma_g, gamma_b, ramp_size, - temp, gamma); + uint16_t *gamma_r = &gamma_ramps[0*ramp_size]; + uint16_t *gamma_g = &gamma_ramps[1*ramp_size]; + uint16_t *gamma_b = &gamma_ramps[2*ramp_size]; - /* Set new gamma ramps */ - xcb_void_cookie_t gamma_set_cookie = - xcb_randr_set_crtc_gamma_checked(state->conn, crtc, - ramp_size, gamma_r, - gamma_g, gamma_b); - error = xcb_request_check(state->conn, gamma_set_cookie); + colorramp_fill(gamma_r, gamma_g, gamma_b, ramp_size, + temp, gamma); - if (error) { - fprintf(stderr, _("`%s' returned error %d\n"), - "RANDR Set CRTC Gamma", error->error_code); - free(gamma_ramps); - return -1; - } + /* Set new gamma ramps */ + xcb_void_cookie_t gamma_set_cookie = + xcb_randr_set_crtc_gamma_checked(state->conn, crtc, + ramp_size, gamma_r, + gamma_g, gamma_b); + error = xcb_request_check(state->conn, gamma_set_cookie); + if (error) { + fprintf(stderr, _("`%s' returned error %d\n"), + "RANDR Set CRTC Gamma", error->error_code); free(gamma_ramps); + return -1; + } + + free(gamma_ramps); + + return 0; +} + +int +randr_set_temperature(randr_state_t *state, int temp, float gamma[3]) +{ + int r; + + /* If no CRTC number has been specified, + set temperature on all CRTCs. */ + if (state->crtc_num < 0) { + for (int i = 0; i < state->crtc_count; i++) { + r = randr_set_temperature_for_crtc(state, i, + temp, gamma); + if (r < 0) return -1; + } + } else { + return randr_set_temperature_for_crtc(state, state->crtc_num, + temp, gamma); } return 0; diff --git a/src/randr.h b/src/randr.h index 94d653f..6e11274 100644 --- a/src/randr.h +++ b/src/randr.h @@ -34,12 +34,13 @@ typedef struct { typedef struct { xcb_connection_t *conn; xcb_screen_t *screen; + int crtc_num; unsigned int crtc_count; randr_crtc_state_t *crtcs; } randr_state_t; -int randr_init(randr_state_t *state, int screen_num); +int randr_init(randr_state_t *state, int screen_num, int crtc_num); void randr_free(randr_state_t *state); void randr_restore(randr_state_t *state); int randr_set_temperature(randr_state_t *state, int temp, float gamma[3]); 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; } 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 */ |