aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am45
-rw-r--r--src/gtk-redshift/Makefile.am19
-rw-r--r--src/gtk-redshift/__init__.py20
-rw-r--r--src/gtk-redshift/defs.py.in1
-rw-r--r--src/gtk-redshift/gtk-redshift23
-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.c93
-rw-r--r--src/randr.h3
-rw-r--r--src/redshift.c243
-rw-r--r--src/solar.c42
-rw-r--r--src/solar.h8
-rw-r--r--src/systemtime.c52
-rw-r--r--src/systemtime.h32
-rw-r--r--src/w32gdi.c127
-rw-r--r--src/w32gdi.h37
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 */