aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Makefile.am55
-rw-r--r--src/colorramp.c2
-rw-r--r--src/gamma-randr.c (renamed from src/randr.c)170
-rw-r--r--src/gamma-randr.h (renamed from src/randr.h)23
-rw-r--r--src/gamma-vidmode.c (renamed from src/vidmode.c)58
-rw-r--r--src/gamma-vidmode.h (renamed from src/vidmode.h)19
-rw-r--r--src/gamma-w32gdi.c152
-rw-r--r--src/gamma-w32gdi.h45
-rw-r--r--src/gtk-redshift/Makefile.am40
-rw-r--r--src/gtk-redshift/__init__.py18
-rw-r--r--src/gtk-redshift/defs.py.in1
-rw-r--r--src/gtk-redshift/gtk-redshift.in23
-rw-r--r--src/gtk-redshift/rsappindicator.py99
-rw-r--r--[-rwxr-xr-x]src/gtk-redshift/statusicon.py (renamed from src/gtk-redshift/gtk-redshift.py)8
-rw-r--r--src/location-gnome-clock.c159
-rw-r--r--src/location-gnome-clock.h44
-rw-r--r--src/location-manual.c113
-rw-r--r--src/location-manual.h44
-rw-r--r--src/redshift.c701
-rw-r--r--src/redshift.h90
-rw-r--r--src/solar.c42
-rw-r--r--src/solar.h8
-rw-r--r--src/systemtime.c52
-rw-r--r--src/systemtime.h32
24 files changed, 1722 insertions, 276 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..c07aea3
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,55 @@
+
+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 \
+ location-manual.c location-manual.h
+
+EXTRA_redshift_SOURCES = \
+ gamma-randr.c gamma-randr.h \
+ gamma-vidmode.c gamma-vidmode.h \
+ gamma-w32gdi.c gamma-w32gdi.h \
+ location-gnome-clock.c location-gnome-clock.h
+
+AM_CFLAGS =
+redshift_LDADD = @LIBINTL@
+EXTRA_DIST =
+
+if ENABLE_RANDR
+redshift_SOURCES += gamma-randr.c gamma-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 += gamma-vidmode.c gamma-vidmode.h
+AM_CFLAGS += $(X11_CFLAGS) $(XF86VM_CFLAGS)
+redshift_LDADD += \
+ $(X11_LIBS) $(X11_CFLAGS) \
+ $(XF86VM_LIBS) $(XF86VM_CFLAGS)
+endif
+
+if ENABLE_WINGDI
+redshift_SOURCES += gamma-w32gdi.c gamma-w32gdi.h
+redshift_LDADD += -lgdi32
+endif
+
+if ENABLE_GNOME_CLOCK
+redshift_SOURCES += location-gnome-clock.c location-gnome-clock.h
+AM_CFLAGS += $(GLIB_CFLAGS) $(GCONF_CFLAGS)
+redshift_LDADD += \
+ $(GLIB_LIBS) $(GLIB_CFLAGS) \
+ $(GCONF_LIBS) $(GCONF_CFLAGS)
+endif
diff --git a/src/colorramp.c b/src/colorramp.c
index 9bc3b94..a154a9e 100644
--- a/src/colorramp.c
+++ b/src/colorramp.c
@@ -17,8 +17,6 @@
Copyright (c) 2010 Jon Lund Steffensen <jonlst@gmail.com>
*/
-#include <stdio.h>
-#include <stdlib.h>
#include <stdint.h>
#include <math.h>
diff --git a/src/randr.c b/src/gamma-randr.c
index 7c05b26..66d5c48 100644
--- a/src/randr.c
+++ b/src/gamma-randr.c
@@ -1,4 +1,4 @@
-/* randr.c -- X RandR gamma adjustment source
+/* gamma-randr.c -- X RANDR gamma adjustment source
This file is part of Redshift.
Redshift is free software: you can redistribute it and/or modify
@@ -19,15 +19,20 @@
#include <stdio.h>
#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
-#include <libintl.h>
-#define _(s) gettext(s)
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(s) gettext(s)
+#else
+# define _(s) s
+#endif
#include <xcb/xcb.h>
#include <xcb/randr.h>
-#include "randr.h"
+#include "gamma-randr.h"
#include "colorramp.h"
@@ -36,15 +41,19 @@
int
-randr_init(randr_state_t *state, int screen_num)
+randr_init(randr_state_t *state)
{
+ /* Initialize state. */
+ state->screen_num = -1;
+ state->crtc_num = -1;
+
+ state->crtc_count = 0;
+ state->crtcs = NULL;
+
xcb_generic_error_t *error;
/* Open X server connection */
- int preferred_screen;
- state->conn = xcb_connect(NULL, &preferred_screen);
-
- if (screen_num < 0) screen_num = preferred_screen;
+ state->conn = xcb_connect(NULL, &state->preferred_screen);
/* Query RandR version */
xcb_randr_query_version_cookie_t ver_cookie =
@@ -71,6 +80,17 @@ randr_init(randr_state_t *state, int screen_num)
free(ver_reply);
+ return 0;
+}
+
+int
+randr_start(randr_state_t *state)
+{
+ xcb_generic_error_t *error;
+
+ int screen_num = state->screen_num;
+ if (screen_num < 0) screen_num = state->preferred_screen;
+
/* Get screen */
const xcb_setup_t *setup = xcb_get_setup(state->conn);
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
@@ -87,7 +107,6 @@ randr_init(randr_state_t *state, int screen_num)
if (state->screen == NULL) {
fprintf(stderr, _("Screen %i could not be found.\n"),
screen_num);
- xcb_disconnect(state->conn);
return -1;
}
@@ -104,15 +123,14 @@ randr_init(randr_state_t *state, int screen_num)
fprintf(stderr, _("`%s' returned error %d\n"),
"RANDR Get Screen Resources Current",
error->error_code);
- xcb_disconnect(state->conn);
return -1;
}
state->crtc_count = res_reply->num_crtcs;
- state->crtcs = malloc(state->crtc_count * sizeof(randr_crtc_state_t));
+ state->crtcs = calloc(state->crtc_count, sizeof(randr_crtc_state_t));
if (state->crtcs == NULL) {
perror("malloc");
- xcb_disconnect(state->conn);
+ state->crtc_count = 0;
return -1;
}
@@ -144,7 +162,6 @@ randr_init(randr_state_t *state, int screen_num)
fprintf(stderr, _("`%s' returned error %d\n"),
"RANDR Get CRTC Gamma Size",
error->error_code);
- xcb_disconnect(state->conn);
return -1;
}
@@ -156,7 +173,6 @@ randr_init(randr_state_t *state, int screen_num)
if (ramp_size == 0) {
fprintf(stderr, _("Gamma ramp size too small: %i\n"),
ramp_size);
- xcb_disconnect(state->conn);
return -1;
}
@@ -171,7 +187,6 @@ randr_init(randr_state_t *state, int screen_num)
if (error) {
fprintf(stderr, _("`%s' returned error %d\n"),
"RANDR Get CRTC Gamma", error->error_code);
- xcb_disconnect(state->conn);
return -1;
}
@@ -188,7 +203,6 @@ randr_init(randr_state_t *state, int screen_num)
if (state->crtcs[i].saved_ramps == NULL) {
perror("malloc");
free(gamma_get_reply);
- xcb_disconnect(state->conn);
return -1;
}
@@ -248,45 +262,111 @@ randr_free(randr_state_t *state)
xcb_disconnect(state->conn);
}
+void
+randr_print_help(FILE *f)
+{
+ fputs(_("Adjust gamma ramps with the X RANDR extension.\n"), f);
+ fputs("\n", f);
+
+ /* TRANSLATORS: RANDR help output
+ left column must not be translated */
+ fputs(_(" screen=N\tX screen to apply adjustments to\n"
+ " crtc=N\tCRTC to apply adjustments to\n"), f);
+ fputs("\n", f);
+}
+
int
-randr_set_temperature(randr_state_t *state, int temp, float gamma[3])
+randr_set_option(randr_state_t *state, const char *key, const char *value)
{
- xcb_generic_error_t *error;
+ if (key == NULL) {
+ fprintf(stderr, _("Missing value for parameter: `%s'.\n"),
+ value);
+ return -1;
+ }
- /* 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;
+ if (strcasecmp(key, "screen") == 0) {
+ state->screen_num = atoi(value);
+ } else if (strcasecmp(key, "crtc") == 0) {
+ state->crtc_num = atoi(value);
+ } else {
+ fprintf(stderr, _("Unknown method parameter: `%s'.\n"), key);
+ 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;
+ return 0;
+}
+
+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"));
}
- 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];
+ return -1;
+ }
- colorramp_fill(gamma_r, gamma_g, gamma_b, ramp_size,
- temp, gamma);
+ xcb_randr_crtc_t crtc = state->crtcs[crtc_num].crtc;
+ unsigned int ramp_size = state->crtcs[crtc_num].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);
+ /* Create new gamma ramps */
+ uint16_t *gamma_ramps = malloc(3*ramp_size*sizeof(uint16_t));
+ if (gamma_ramps == NULL) {
+ perror("malloc");
+ return -1;
+ }
- if (error) {
- fprintf(stderr, _("`%s' returned error %d\n"),
- "RANDR Set CRTC Gamma", error->error_code);
- free(gamma_ramps);
- return -1;
- }
+ 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];
+
+ colorramp_fill(gamma_r, gamma_g, gamma_b, ramp_size,
+ temp, gamma);
+ /* 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/gamma-randr.h
index 94d653f..4ccad8f 100644
--- a/src/randr.h
+++ b/src/gamma-randr.h
@@ -1,4 +1,4 @@
-/* randr.h -- X RandR gamma adjustment header
+/* gamma-randr.h -- X RANDR gamma adjustment header
This file is part of Redshift.
Redshift is free software: you can redistribute it and/or modify
@@ -17,14 +17,18 @@
Copyright (c) 2010 Jon Lund Steffensen <jonlst@gmail.com>
*/
-#ifndef _REDSHIFT_RANDR_H
-#define _REDSHIFT_RANDR_H
+#ifndef _REDSHIFT_GAMMA_RANDR_H
+#define _REDSHIFT_GAMMA_RANDR_H
+#include <stdio.h>
#include <stdint.h>
#include <xcb/xcb.h>
#include <xcb/randr.h>
+#include "redshift.h"
+
+
typedef struct {
xcb_randr_crtc_t crtc;
unsigned int ramp_size;
@@ -34,14 +38,23 @@ typedef struct {
typedef struct {
xcb_connection_t *conn;
xcb_screen_t *screen;
+ int preferred_screen;
+ int screen_num;
+ 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 randr_start(randr_state_t *state);
void randr_free(randr_state_t *state);
+
+void randr_print_help(FILE *f);
+int randr_set_option(randr_state_t *state, const char *key, const char *value);
+
void randr_restore(randr_state_t *state);
int randr_set_temperature(randr_state_t *state, int temp, float gamma[3]);
-#endif /* ! _REDSHIFT_RANDR_H */
+
+#endif /* ! _REDSHIFT_GAMMA_RANDR_H */
diff --git a/src/vidmode.c b/src/gamma-vidmode.c
index 4da1831..e6b9412 100644
--- a/src/vidmode.c
+++ b/src/gamma-vidmode.c
@@ -1,4 +1,4 @@
-/* vidmode.c -- X VidMode gamma adjustment source
+/* gamma-vidmode.c -- X VidMode gamma adjustment source
This file is part of Redshift.
Redshift is free software: you can redistribute it and/or modify
@@ -20,21 +20,27 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
+#include <string.h>
-#include <libintl.h>
-#define _(s) gettext(s)
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(s) gettext(s)
+#else
+# define _(s) s
+#endif
#include <X11/Xlib.h>
#include <X11/extensions/xf86vmode.h>
-#include "vidmode.h"
+#include "gamma-vidmode.h"
#include "colorramp.h"
int
-vidmode_init(vidmode_state_t *state, int screen_num)
+vidmode_init(vidmode_state_t *state)
{
- int r;
+ state->screen_num = -1;
+ state->saved_ramps = NULL;
/* Open display */
state->display = XOpenDisplay(NULL);
@@ -44,6 +50,15 @@ vidmode_init(vidmode_state_t *state, int screen_num)
return -1;
}
+ return 0;
+}
+
+int
+vidmode_start(vidmode_state_t *state)
+{
+ int r;
+ int screen_num = state->screen_num;
+
if (screen_num < 0) screen_num = DefaultScreen(state->display);
state->screen_num = screen_num;
@@ -111,6 +126,37 @@ vidmode_free(vidmode_state_t *state)
}
void
+vidmode_print_help(FILE *f)
+{
+ fputs(_("Adjust gamma ramps with the X VidMode extension.\n"), f);
+ fputs("\n", f);
+
+ /* TRANSLATORS: VidMode help output
+ left column must not be translated */
+ fputs(_(" screen=N\tX screen to apply adjustments to\n"), f);
+ fputs("\n", f);
+}
+
+int
+vidmode_set_option(vidmode_state_t *state, const char *key, const char *value)
+{
+ if (key == NULL) {
+ fprintf(stderr, _("Missing value for parameter: `%s'.\n"),
+ key);
+ return -1;
+ }
+
+ if (strcasecmp(key, "screen") == 0) {
+ state->screen_num = atoi(value);
+ } else {
+ fprintf(stderr, _("Unknown method parameter: `%s'.\n"), key);
+ return -1;
+ }
+
+ return 0;
+}
+
+void
vidmode_restore(vidmode_state_t *state)
{
uint16_t *gamma_r = &state->saved_ramps[0*state->ramp_size];
diff --git a/src/vidmode.h b/src/gamma-vidmode.h
index 9503441..18a4a88 100644
--- a/src/vidmode.h
+++ b/src/gamma-vidmode.h
@@ -1,4 +1,4 @@
-/* vidmode.h -- X VidMode gamma adjustment header
+/* gamma-vidmode.h -- X VidMode gamma adjustment header
This file is part of Redshift.
Redshift is free software: you can redistribute it and/or modify
@@ -17,9 +17,10 @@
Copyright (c) 2010 Jon Lund Steffensen <jonlst@gmail.com>
*/
-#ifndef _REDSHIFT_VIDMODE_H
-#define _REDSHIFT_VIDMODE_H
+#ifndef _REDSHIFT_GAMMA_VIDMODE_H
+#define _REDSHIFT_GAMMA_VIDMODE_H
+#include <stdio.h>
#include <stdint.h>
#include <X11/Xlib.h>
@@ -31,9 +32,17 @@ typedef struct {
uint16_t *saved_ramps;
} vidmode_state_t;
-int vidmode_init(vidmode_state_t *state, int screen_num);
+
+int vidmode_init(vidmode_state_t *state);
+int vidmode_start(vidmode_state_t *state);
void vidmode_free(vidmode_state_t *state);
+
+void vidmode_print_help(FILE *f);
+int vidmode_set_option(vidmode_state_t *state, const char *key,
+ const char *value);
+
void vidmode_restore(vidmode_state_t *state);
int vidmode_set_temperature(vidmode_state_t *state, int temp, float gamma[3]);
-#endif /* ! _REDSHIFT_VIDMODE_H */
+
+#endif /* ! _REDSHIFT_GAMMA_VIDMODE_H */
diff --git a/src/gamma-w32gdi.c b/src/gamma-w32gdi.c
new file mode 100644
index 0000000..aa2474d
--- /dev/null
+++ b/src/gamma-w32gdi.c
@@ -0,0 +1,152 @@
+/* gamma-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 <stdio.h>
+#include <stdlib.h>
+
+#ifndef WINVER
+# define WINVER 0x0500
+#endif
+#include <windows.h>
+#include <wingdi.h>
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(s) gettext(s)
+#else
+# define _(s) s
+#endif
+
+#include "gamma-w32gdi.h"
+#include "colorramp.h"
+
+#define GAMMA_RAMP_SIZE 256
+
+
+int
+w32gdi_init(w32gdi_state_t *state)
+{
+ state->saved_ramps = NULL;
+ state->hDC = NULL;
+
+ return 0;
+}
+
+int
+w32gdi_start(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 */
+ if (state->hDC != NULL) ReleaseDC(NULL, state->hDC);
+}
+
+
+void
+w32gdi_print_help(FILE *f)
+{
+ fputs(_("Adjust gamma ramps with the Windows GDI.\n"), f);
+ fputs("\n", f);
+}
+
+int
+w32gdi_set_option(w32gdi_state_t *state, const char *key, const char *value)
+{
+ return -1;
+}
+
+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/gamma-w32gdi.h b/src/gamma-w32gdi.h
new file mode 100644
index 0000000..6cb9799
--- /dev/null
+++ b/src/gamma-w32gdi.h
@@ -0,0 +1,45 @@
+/* gamma-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_GAMMA_W32GDI_H
+#define _REDSHIFT_GAMMA_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);
+int w32gdi_start(w32gdi_state_t *state);
+void w32gdi_free(w32gdi_state_t *state);
+
+void w32gdi_print_help(FILE *f);
+int w32gdi_set_option(w32gdi_state_t *state, const char *key,
+ const char *value);
+
+void w32gdi_restore(w32gdi_state_t *state);
+int w32gdi_set_temperature(w32gdi_state_t *state, int temp, float gamma[3]);
+
+
+#endif /* ! _REDSHIFT_GAMMA_W32GDI_H */
diff --git a/src/gtk-redshift/Makefile.am b/src/gtk-redshift/Makefile.am
new file mode 100644
index 0000000..ddeafd6
--- /dev/null
+++ b/src/gtk-redshift/Makefile.am
@@ -0,0 +1,40 @@
+
+if ENABLE_STATUSICON
+gui_module=statusicon
+gtk_redshift_PYTHON = \
+ __init__.py \
+ statusicon.py
+nodist_gtk_redshift_PYTHON = \
+ defs.py
+gtk_redshiftdir = $(pythondir)/gtk_redshift
+
+bin_SCRIPTS = gtk-redshift
+endif
+
+if ENABLE_APPINDICATOR
+gui_module=rsappindicator
+gtk_redshift_PYTHON = \
+ __init__.py \
+ rsappindicator.py
+nodist_gtk_redshift_PYTHON = \
+ defs.py
+gtk_redshiftdir = $(pythondir)/gtk_redshift
+
+bin_SCRIPTS = gtk-redshift
+endif
+
+EXTRA_DIST = gtk-redshift.in \
+ defs.py.in
+
+CLEANFILES = defs.py \
+ gtk-redshift
+
+
+# Main GUI script
+gtk-redshift: gtk-redshift.in
+ sed -e "s|\@gui_module\@|$(gui_module)|g" $< > $@
+
+# 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..51ab2ef
--- /dev/null
+++ b/src/gtk-redshift/__init__.py
@@ -0,0 +1,18 @@
+#!/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>
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.in b/src/gtk-redshift/gtk-redshift.in
new file mode 100644
index 0000000..120e05c
--- /dev/null
+++ b/src/gtk-redshift/gtk-redshift.in
@@ -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.@gui_module@ import run
+ run()
diff --git a/src/gtk-redshift/rsappindicator.py b/src/gtk-redshift/rsappindicator.py
new file mode 100644
index 0000000..59fa725
--- /dev/null
+++ b/src/gtk-redshift/rsappindicator.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+# rsappindicator.py -- Application Panel Indicator 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>
+
+
+import sys, os
+import subprocess, signal
+import gettext
+
+import pygtk
+pygtk.require("2.0")
+
+import gtk, glib
+try:
+ import appindicator
+except ImportError as ie:
+ # No module named appindicator
+ sys.exit(str(ie))
+
+import defs
+
+
+def run():
+ # Internationalisation
+ gettext.bindtextdomain('redshift', defs.LOCALEDIR)
+ gettext.textdomain('redshift')
+ _ = gettext.gettext
+
+ # Start redshift with arguments from the command line
+ args = sys.argv[1:]
+ args.insert(0, os.path.join(defs.BINDIR, 'redshift'))
+ process = subprocess.Popen(args)
+
+ try:
+ # Create status icon
+ indicator = appindicator.Indicator ("redshift",
+ "redshift",
+ appindicator.CATEGORY_APPLICATION_STATUS)
+ indicator.set_status (appindicator.STATUS_ACTIVE)
+
+ def toggle_cb(widget, data=None):
+ if indicator.get_icon() == 'redshift':
+ indicator.set_icon('redshift-idle')
+ else:
+ indicator.set_icon('redshift')
+ process.send_signal(signal.SIGUSR1)
+
+ def destroy_cb(widget, data=None):
+ gtk.main_quit()
+ return False
+
+ # Create popup menu
+ status_menu = gtk.Menu()
+
+ toggle_item = gtk.ImageMenuItem(_('Toggle'))
+ toggle_item.connect('activate', toggle_cb)
+ status_menu.append(toggle_item)
+
+ quit_item = gtk.ImageMenuItem(gtk.STOCK_QUIT)
+ quit_item.connect('activate', destroy_cb)
+ status_menu.append(quit_item)
+
+ status_menu.show_all()
+
+ # Set the menu
+ indicator.set_menu(status_menu)
+
+ def child_cb(pid, cond, data=None):
+ sys.exit(-1)
+
+ # Add watch on child process
+ glib.child_watch_add(process.pid, child_cb)
+
+ # Run main loop
+ gtk.main()
+
+ except KeyboardInterrupt:
+ # Ignore user interruption
+ pass
+
+ finally:
+ # Always terminate redshift
+ process.terminate()
+ process.wait()
diff --git a/src/gtk-redshift/gtk-redshift.py b/src/gtk-redshift/statusicon.py
index a737154..2295963 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():
# 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/location-gnome-clock.c b/src/location-gnome-clock.c
new file mode 100644
index 0000000..10b95eb
--- /dev/null
+++ b/src/location-gnome-clock.c
@@ -0,0 +1,159 @@
+/* location-gnome-clock.c -- GNOME Panel Clock location provider 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>
+#include <string.h>
+
+#include <gconf/gconf-client.h>
+
+#include "location-gnome-clock.h"
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(s) gettext(s)
+#else
+# define _(s) s
+#endif
+
+
+int
+location_gnome_clock_init(location_gnome_clock_state_t *state)
+{
+ g_type_init();
+
+ GError *error = NULL;
+ GConfClient *client = gconf_client_get_default();
+
+ GSList *applets = gconf_client_all_dirs(client, "/apps/panel/applets",
+ &error);
+ if (error) {
+ fputs(_("Cannot list dirs in `/apps/panel/applets'.\n"),
+ stderr);
+ g_object_unref(client);
+ return -1;
+ }
+
+ char *cities_key = NULL;
+ for (GSList *applet = applets; applet != NULL;
+ applet = g_slist_next(applet)) {
+ char *path = applet->data;
+ if (cities_key == NULL) {
+ char *key = g_strdup_printf("%s/bonobo_iid", path);
+ char *bonobo_iid = gconf_client_get_string(client, key,
+ &error);
+
+ if (!error && bonobo_iid != NULL) {
+ if (!strcmp(bonobo_iid,
+ "OAFIID:GNOME_ClockApplet")) {
+ cities_key = g_strdup_printf(
+ "%s/prefs/cities", path);
+ }
+ g_free(bonobo_iid);
+ }
+
+ g_free(key);
+ }
+ g_free(path);
+ }
+
+ g_slist_free(applets);
+
+ if (cities_key == NULL) {
+ fputs(_("No clock applet was found.\n"), stderr);
+ g_object_unref(client);
+ return -1;
+ }
+
+ GSList *cities = gconf_client_get_list(client, cities_key,
+ GCONF_VALUE_STRING, &error);
+ if (error) {
+ fprintf(stderr, _("Error reading city list: `%s'.\n"),
+ cities_key);
+ g_free(cities_key);
+ g_object_unref(client);
+ return -1;
+ }
+
+ g_free(cities_key);
+
+ char *current_city = NULL;
+ for (GSList *city = cities; city != NULL;
+ city = g_slist_next(city)) {
+ char *city_spec = city->data;
+ char *c = strstr(city_spec, "current=\"true\"");
+ if (c) current_city = g_strdup(city_spec);
+ g_free(city->data);
+ }
+ g_slist_free(cities);
+
+ if (current_city == NULL) {
+ fputs(_("No city selected as current city.\n"), stderr);
+ return -1;
+ }
+
+ char *lat_str = strstr(current_city, "latitude=\"");
+ char *lon_str = strstr(current_city, "longitude=\"");
+ if (lat_str == NULL || lon_str == NULL) {
+ fputs(_("Location not specified for city.\n"), stderr);
+ return -1;
+ }
+
+ char *lat_num_str = lat_str + strlen("latitude=\"");
+ char *lon_num_str = lon_str + strlen("longitude=\"");
+
+ state->lat = g_ascii_strtod(lat_num_str, NULL);
+ state->lon = g_ascii_strtod(lon_num_str, NULL);
+
+ return 0;
+}
+
+int
+location_gnome_clock_start(location_gnome_clock_state_t *state)
+{
+ return 0;
+}
+
+void
+location_gnome_clock_free(location_gnome_clock_state_t *state)
+{
+}
+
+void
+location_gnome_clock_print_help(FILE *f)
+{
+ fputs(_("Use the location as set in the GNOME Clock applet.\n"), f);
+ fputs("\n", f);
+}
+
+int
+location_gnome_clock_set_option(location_gnome_clock_state_t *state,
+ const char *key, const char *value)
+{
+ return -1;
+}
+
+int
+location_gnome_clock_get_location(location_gnome_clock_state_t *state,
+ float *lat, float *lon)
+{
+ *lat = state->lat;
+ *lon = state->lon;
+
+ return 0;
+}
diff --git a/src/location-gnome-clock.h b/src/location-gnome-clock.h
new file mode 100644
index 0000000..052ce91
--- /dev/null
+++ b/src/location-gnome-clock.h
@@ -0,0 +1,44 @@
+/* location-gnome-clock.h -- GNOME Panel Clock location provider 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_LOCATION_GNOME_CLOCK_H
+#define _REDSHIFT_LOCATION_GNOME_CLOCK_H
+
+#include <stdio.h>
+
+
+typedef struct {
+ float lat;
+ float lon;
+} location_gnome_clock_state_t;
+
+
+int location_gnome_clock_init(location_gnome_clock_state_t *state);
+int location_gnome_clock_start(location_gnome_clock_state_t *state);
+void location_gnome_clock_free(location_gnome_clock_state_t *state);
+
+void location_gnome_clock_print_help(FILE *f);
+int location_gnome_clock_set_option(location_gnome_clock_state_t *state,
+ const char *key, const char *value);
+
+int location_gnome_clock_get_location(location_gnome_clock_state_t *state,
+ float *lat, float *lon);
+
+
+#endif /* ! _REDSHIFT_LOCATION_GNOME_CLOCK_H */
diff --git a/src/location-manual.c b/src/location-manual.c
new file mode 100644
index 0000000..1f68b6c
--- /dev/null
+++ b/src/location-manual.c
@@ -0,0 +1,113 @@
+/* location-manual.c -- Manual location provider 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>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <errno.h>
+
+#include "location-manual.h"
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(s) gettext(s)
+#else
+# define _(s) s
+#endif
+
+
+int
+location_manual_init(location_manual_state_t *state)
+{
+ state->lat = NAN;
+ state->lon = NAN;
+
+ return 0;
+}
+
+int
+location_manual_start(location_manual_state_t *state)
+{
+ /* Latitude and longitude must be set */
+ if (isnan(state->lat) || isnan(state->lon)) {
+ fputs(_("Latitude and longitude must be set.\n"), stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ return 0;
+}
+
+void
+location_manual_free(location_manual_state_t *state)
+{
+}
+
+void
+location_manual_print_help(FILE *f)
+{
+ fputs(_("Specify location manually.\n"), f);
+ fputs("\n", f);
+
+ /* TRANSLATORS: Manual location help output
+ left column must not be translated */
+ fputs(_(" lat=N\t\tLatitude\n"
+ " lon=N\t\tLongitude\n"), f);
+ fputs("\n", f);
+}
+
+int
+location_manual_set_option(location_manual_state_t *state, const char *key,
+ const char *value)
+{
+ /* Parse float value */
+ char *end;
+ errno = 0;
+ float v = strtof(value, &end);
+ if (errno != 0 || *end != '\0') {
+ fputs(_("Malformed argument.\n"), stderr);
+ return -1;
+ }
+
+ if ((key == NULL && isnan(state->lat)) ||
+ (key != NULL && strcasecmp(key, "lat") == 0)) {
+ state->lat = v;
+ } else if ((key == NULL && isnan(state->lon)) ||
+ (key != NULL && strcasecmp(key, "lon") == 0)) {
+ state->lon = v;
+ } else if (key == NULL) {
+ fputs(_("Too many arguments.\n"), stderr);
+ return -1;
+ } else {
+ fprintf(stderr, _("Unknown method parameter: `%s'.\n"), key);
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+location_manual_get_location(location_manual_state_t *state, float *lat,
+ float *lon)
+{
+ *lat = state->lat;
+ *lon = state->lon;
+
+ return 0;
+}
diff --git a/src/location-manual.h b/src/location-manual.h
new file mode 100644
index 0000000..13c77da
--- /dev/null
+++ b/src/location-manual.h
@@ -0,0 +1,44 @@
+/* location-manual.h -- Manual location provider 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_LOCATION_MANUAL_H
+#define _REDSHIFT_LOCATION_MANUAL_H
+
+#include <stdio.h>
+
+
+typedef struct {
+ float lat;
+ float lon;
+} location_manual_state_t;
+
+
+int location_manual_init(location_manual_state_t *state);
+int location_manual_start(location_manual_state_t *state);
+void location_manual_free(location_manual_state_t *state);
+
+void location_manual_print_help(FILE *f);
+int location_manual_set_option(location_manual_state_t *state,
+ const char *key, const char *value);
+
+int location_manual_get_location(location_manual_state_t *state, float *lat,
+ float *lon);
+
+
+#endif /* ! _REDSHIFT_LOCATION_MANUAL_H */
diff --git a/src/redshift.c b/src/redshift.c
index 9c3f404..18cc2c5 100644
--- a/src/redshift.c
+++ b/src/redshift.c
@@ -28,28 +28,51 @@
#include <time.h>
#include <math.h>
#include <locale.h>
-#include <sys/signal.h>
+#include <errno.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 "redshift.h"
#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
-# include "randr.h"
+# include "gamma-randr.h"
#endif
#ifdef ENABLE_VIDMODE
-# include "vidmode.h"
+# include "gamma-vidmode.h"
+#endif
+
+#ifdef ENABLE_WINGDI
+# include "gamma-w32gdi.h"
+#endif
+
+
+#include "location-manual.h"
+
+#ifdef ENABLE_GNOME_CLOCK
+# include "location-gnome-clock.h"
#endif
@@ -61,9 +84,94 @@ typedef union {
#ifdef ENABLE_VIDMODE
vidmode_state_t vidmode;
#endif
+#ifdef ENABLE_WINGDI
+ w32gdi_state_t w32gdi;
+#endif
} gamma_state_t;
+/* Gamma adjustment method structs */
+static const gamma_method_t gamma_methods[] = {
+#ifdef ENABLE_RANDR
+ {
+ "randr",
+ (gamma_method_init_func *)randr_init,
+ (gamma_method_start_func *)randr_start,
+ (gamma_method_free_func *)randr_free,
+ (gamma_method_print_help_func *)randr_print_help,
+ (gamma_method_set_option_func *)randr_set_option,
+ (gamma_method_restore_func *)randr_restore,
+ (gamma_method_set_temperature_func *)randr_set_temperature
+ },
+#endif
+#ifdef ENABLE_VIDMODE
+ {
+ "vidmode",
+ (gamma_method_init_func *)vidmode_init,
+ (gamma_method_start_func *)vidmode_start,
+ (gamma_method_free_func *)vidmode_free,
+ (gamma_method_print_help_func *)vidmode_print_help,
+ (gamma_method_set_option_func *)vidmode_set_option,
+ (gamma_method_restore_func *)vidmode_restore,
+ (gamma_method_set_temperature_func *)vidmode_set_temperature
+ },
+#endif
+#ifdef ENABLE_WINGDI
+ {
+ "wingdi",
+ (gamma_method_init_func *)w32gdi_init,
+ (gamma_method_start_func *)w32gdi_start,
+ (gamma_method_free_func *)w32gdi_free,
+ (gamma_method_print_help_func *)w32gdi_print_help,
+ (gamma_method_set_option_func *)w32gdi_set_option,
+ (gamma_method_restore_func *)w32gdi_restore,
+ (gamma_method_set_temperature_func *)w32gdi_set_temperature
+ },
+#endif
+ { NULL }
+};
+
+
+/* Union of state data for location providers */
+typedef union {
+ location_manual_state_t manual;
+#ifdef ENABLE_GNOME_CLOCK
+ location_gnome_clock_state_t gnome_clock;
+#endif
+} location_state_t;
+
+
+/* Location provider method structs */
+static const location_provider_t location_providers[] = {
+#ifdef ENABLE_GNOME_CLOCK
+ {
+ "gnome-clock",
+ (location_provider_init_func *)location_gnome_clock_init,
+ (location_provider_start_func *)location_gnome_clock_start,
+ (location_provider_free_func *)location_gnome_clock_free,
+ (location_provider_print_help_func *)
+ location_gnome_clock_print_help,
+ (location_provider_set_option_func *)
+ location_gnome_clock_set_option,
+ (location_provider_get_location_func *)
+ location_gnome_clock_get_location
+ },
+#endif
+ {
+ "manual",
+ (location_provider_init_func *)location_manual_init,
+ (location_provider_start_func *)location_manual_start,
+ (location_provider_free_func *)location_manual_free,
+ (location_provider_print_help_func *)
+ location_manual_print_help,
+ (location_provider_set_option_func *)
+ location_manual_set_option,
+ (location_provider_get_location_func *)
+ location_manual_get_location
+ },
+ { NULL }
+};
+
/* Bounds for parameters. */
#define MIN_LAT -90.0
#define MAX_LAT 90.0
@@ -79,6 +187,9 @@ typedef union {
#define DEFAULT_NIGHT_TEMP 3700
#define DEFAULT_GAMMA 1.0
+/* The color temperature when no adjustment is applied. */
+#define NEUTRAL_TEMP 6500
+
/* Angular elevation of the sun at which the color temperature
transition period starts and ends (in degress).
Transition during twilight, and while the sun is lower than
@@ -86,6 +197,15 @@ typedef union {
#define TRANSITION_LOW SOLAR_CIVIL_TWILIGHT_ELEV
#define TRANSITION_HIGH 3.0
+/* Program modes. */
+typedef enum {
+ PROGRAM_MODE_CONTINUAL,
+ PROGRAM_MODE_ONE_SHOT,
+ PROGRAM_MODE_RESET
+} program_mode_t;
+
+
+#ifdef HAVE_SYS_SIGNAL_H
static volatile sig_atomic_t exiting = 0;
static volatile sig_atomic_t disable = 0;
@@ -104,61 +224,12 @@ sigdisable(int signo)
disable = 1;
}
+#else /* ! 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)
-{
- switch (use_randr) {
-#ifdef ENABLE_VIDMODE
- case 0:
- vidmode_restore(&state->vidmode);
- break;
-#endif
-#ifdef ENABLE_RANDR
- case 1:
- randr_restore(&state->randr);
- break;
-#endif
- }
-}
+static int exiting = 0;
+static int disable = 0;
-/* Free the state associated with the appropriate adjustment method. */
-static void
-gamma_state_free(gamma_state_t *state, int use_randr)
-{
- switch (use_randr) {
-#ifdef ENABLE_VIDMODE
- case 0:
- vidmode_free(&state->vidmode);
- break;
-#endif
-#ifdef ENABLE_RANDR
- case 1:
- randr_free(&state->randr);
- break;
-#endif
- }
-}
-
-/* Set temperature with the appropriate adjustment method. */
-static int
-gamma_state_set_temperature(gamma_state_t *state, int use_randr,
- int temp, float gamma[3])
-{
- switch (use_randr) {
-#ifdef ENABLE_VIDMODE
- case 0:
- return vidmode_set_temperature(&state->vidmode, temp, gamma);
-#endif
-#ifdef ENABLE_RANDR
- case 1:
- return randr_set_temperature(&state->randr, temp, gamma);
-#endif
- }
-
- return -1;
-}
+#endif /* ! HAVE_SYS_SIGNAL_H */
/* Calculate color temperature for the specified solar elevation. */
@@ -212,21 +283,170 @@ print_help(const char *program_name)
fputs("\n", stdout);
/* TRANSLATORS: help output 4
+ `list' must not be translated
no-wrap */
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"
+ " -l PROVIDER\tSelect provider for automatic"
+ " location updates\n"
+ " \t\t(Type `list' to see available providers)\n"
+ " -m METHOD\tMethod to use to set color temperature\n"
+ " \t\t(Type `list' to see available methods)\n"
" -o\t\tOne shot mode (do not continously adjust"
" color temperature)\n"
- " -r\t\tDisable initial temperature transition\n"
- " -s SCREEN\tX screen to apply adjustments to\n"
+ " -x\t\tReset mode (remove adjustment from screen)\n"
+ " -r\t\tDisable temperature transitions\n"
" -t DAY:NIGHT\tColor temperature to set at daytime/night\n"),
stdout);
fputs("\n", stdout);
/* TRANSLATORS: help output 5 */
- printf("Please report bugs to <%s>\n", PACKAGE_BUGREPORT);
+ 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);
+}
+
+static void
+print_method_list()
+{
+ fputs(_("Available adjustment methods:\n"), stdout);
+ for (int i = 0; gamma_methods[i].name != NULL; i++) {
+ printf(" %s\n", gamma_methods[i].name);
+ }
+
+ fputs("\n", stdout);
+ fputs(_("Specify colon-separated options with"
+ " `-m METHOD:OPTIONS'.\n"), stdout);
+ /* TRANSLATORS: `help' must not be translated. */
+ fputs(_("Try `-m METHOD:help' for help.\n"), stdout);
+}
+
+static void
+print_provider_list()
+{
+ fputs(_("Available location providers:\n"), stdout);
+ for (int i = 0; location_providers[i].name != NULL; i++) {
+ printf(" %s\n", location_providers[i].name);
+ }
+
+ fputs("\n", stdout);
+ fputs(_("Specify colon-separated options with"
+ "`-l PROVIDER:OPTIONS'.\n"), stdout);
+ /* TRANSLATORS: `help' must not be translated. */
+ fputs(_("Try `-l PROVIDER:help' for help.\n"), stdout);
+}
+
+
+static int
+provider_try_start(const location_provider_t *provider,
+ location_state_t *state, char *args)
+{
+ int r;
+
+ r = provider->init(state);
+ if (r < 0) {
+ fprintf(stderr, _("Initialization of %s failed.\n"),
+ provider->name);
+ return -1;
+ }
+
+ /* Set provider options. */
+ while (args != NULL) {
+ char *next_arg = strchr(args, ':');
+ if (next_arg != NULL) *(next_arg++) = '\0';
+
+ char *key = NULL;
+ char *value = strchr(args, '=');
+ if (value != NULL) {
+ key = args;
+ *(value++) = '\0';
+ } else {
+ value = args;
+ }
+
+ r = provider->set_option(state, key, value);
+ if (r < 0) {
+ provider->free(state);
+ fprintf(stderr, _("Failed to set %s option.\n"),
+ provider->name);
+ /* TRANSLATORS: `help' must not be translated. */
+ fprintf(stderr, _("Try `-l %s:help' for more"
+ " information.\n"), provider->name);
+ return -1;
+ }
+
+ args = next_arg;
+ }
+
+ /* Start provider. */
+ r = provider->start(state);
+ if (r < 0) {
+ provider->free(state);
+ fprintf(stderr, _("Failed to start provider %s.\n"),
+ provider->name);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+method_try_start(const gamma_method_t *method,
+ gamma_state_t *state, char *args)
+{
+ int r;
+
+ r = method->init(state);
+ if (r < 0) {
+ fprintf(stderr, _("Initialization of %s failed.\n"),
+ method->name);
+ return -1;
+ }
+
+ /* Set method options. */
+ while (args != NULL) {
+ char *next_arg = strchr(args, ':');
+ if (next_arg != NULL) *(next_arg++) = '\0';
+
+ char *key = NULL;
+ char *value = strchr(args, '=');
+ if (value != NULL) {
+ key = args;
+ *(value++) = '\0';
+ } else {
+ value = args;
+ }
+
+ r = method->set_option(state, key, value);
+ if (r < 0) {
+ method->free(state);
+ fprintf(stderr, _("Failed to set %s option.\n"),
+ method->name);
+ /* TRANSLATORS: `help' must not be translated. */
+ fprintf(stderr, _("Try -m %s:help' for more"
+ " information.\n"), method->name);
+ return -1;
+ }
+
+ args = next_arg;
+ }
+
+ /* Start method. */
+ r = method->start(state);
+ if (r < 0) {
+ method->free(state);
+ fprintf(stderr, _("Failed to start adjustment method %s.\n"),
+ method->name);
+ return -1;
+ }
+
+ return 0;
}
@@ -235,32 +455,35 @@ 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);
#endif
/* Initialize to defaults */
- float lat = NAN;
- float lon = NAN;
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 screen_num = -1;
+
+ const gamma_method_t *method = NULL;
+ char *method_args = NULL;
+
+ const location_provider_t *provider = NULL;
+ char *provider_args = NULL;
+
int transition = 1;
- int one_shot = 0;
+ program_mode_t mode = PROGRAM_MODE_CONTINUAL;
int verbose = 0;
char *s;
/* Parse arguments. */
int opt;
- while ((opt = getopt(argc, argv, "g:hl:m:ors:t:v")) != -1) {
+ while ((opt = getopt(argc, argv, "g:hl:m:ort:vx")) != -1) {
switch (opt) {
case 'g':
s = strchr(optarg, ':');
@@ -292,56 +515,101 @@ main(int argc, char *argv[])
exit(EXIT_SUCCESS);
break;
case 'l':
- s = strchr(optarg, ':');
- if (s == NULL) {
- fputs(_("Malformed location argument.\n"),
- stderr);
- fputs(_("Try `-h' for more information.\n"),
- stderr);
+ /* Print list of providers if argument is `list' */
+ if (strcasecmp(optarg, "list") == 0) {
+ print_provider_list();
+ exit(EXIT_SUCCESS);
+ }
+
+ char *provider_name = NULL;
+
+ /* Don't save the result of strtof(); we simply want
+ to know if optarg can be parsed as a float. */
+ errno = 0;
+ char *end;
+ strtof(optarg, &end);
+ if (errno == 0 && *end == ':') {
+ /* Use instead as arguments to `manual'. */
+ provider_name = "manual";
+ provider_args = optarg;
+ } else {
+ /* Split off provider arguments. */
+ s = strchr(optarg, ':');
+ if (s != NULL) {
+ *(s++) = '\0';
+ provider_args = s;
+ }
+
+ provider_name = optarg;
+ }
+
+ /* Lookup argument in location provider table */
+ for (int i = 0; location_providers[i].name != NULL;
+ i++) {
+ const location_provider_t *p =
+ &location_providers[i];
+ if (strcasecmp(provider_name, p->name) == 0) {
+ provider = p;
+ }
+ }
+
+ if (provider == NULL) {
+ fprintf(stderr, _("Unknown location provider"
+ " `%s'.\n"), provider_name);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Print provider help if arg is `help'. */
+ if (provider_args != NULL &&
+ strcasecmp(provider_args, "help") == 0) {
+ provider->print_help(stdout);
exit(EXIT_FAILURE);
}
- *(s++) = '\0';
- lat = atof(optarg);
- lon = atof(s);
break;
case 'm':
- if (strcmp(optarg, "randr") == 0 ||
- strcmp(optarg, "RANDR") == 0) {
-#ifdef ENABLE_RANDR
- use_randr = 1;
-#else
- fputs(_("RANDR method was not"
- " enabled at compile time.\n"),
- stderr);
- exit(EXIT_FAILURE);
-#endif
- } else if (strcmp(optarg, "vidmode") == 0 ||
- strcmp(optarg, "VidMode") == 0) {
-#ifdef ENABLE_VIDMODE
- use_randr = 0;
-#else
- fputs(_("VidMode method was not"
- " enabled at compile time.\n"),
- stderr);
- exit(EXIT_FAILURE);
-#endif
- } else {
+ /* Print list of methods if argument is `list' */
+ if (strcasecmp(optarg, "list") == 0) {
+ print_method_list();
+ exit(EXIT_SUCCESS);
+ }
+
+ /* Split off method arguments. */
+ s = strchr(optarg, ':');
+ if (s != NULL) {
+ *(s++) = '\0';
+ method_args = s;
+ }
+
+ /* Lookup argument in gamma methods table */
+ for (int i = 0; gamma_methods[i].name != NULL; i++) {
+ const gamma_method_t *m =
+ &gamma_methods[i];
+ if (strcasecmp(optarg, m->name) == 0) {
+ method = m;
+ }
+ }
+
+ if (method == NULL) {
/* TRANSLATORS: This refers to the method
used to adjust colors e.g VidMode */
fprintf(stderr, _("Unknown method `%s'.\n"),
optarg);
exit(EXIT_FAILURE);
}
+
+ /* Print method help if arg is `help'. */
+ if (method_args != NULL &&
+ strcasecmp(method_args, "help") == 0) {
+ method->print_help(stdout);
+ exit(EXIT_FAILURE);
+ }
break;
case 'o':
- one_shot = 1;
+ mode = PROGRAM_MODE_ONE_SHOT;
break;
case 'r':
transition = 0;
break;
- case 's':
- screen_num = atoi(optarg);
- break;
case 't':
s = strchr(optarg, ':');
if (s == NULL) {
@@ -358,6 +626,9 @@ main(int argc, char *argv[])
case 'v':
verbose = 1;
break;
+ case 'x':
+ mode = PROGRAM_MODE_RESET;
+ break;
case '?':
fputs(_("Try `-h' for more information.\n"), stderr);
exit(EXIT_FAILURE);
@@ -365,34 +636,81 @@ main(int argc, char *argv[])
}
}
- /* Latitude and longitude must be set */
- if (isnan(lat) || isnan(lon)) {
- fputs(_("Latitude and longitude must be set.\n"), stderr);
- fputs(_("Try `-h' for more information.\n"), stderr);
- exit(EXIT_FAILURE);
- }
+ /* Initialize location provider. If provider is NULL
+ try all providers until one that works is found. */
+ location_state_t location_state;
+
+ /* Location is not needed for reset mode. */
+ if (mode != PROGRAM_MODE_RESET) {
+ if (provider != NULL) {
+ /* Use provider specified on command line. */
+ r = provider_try_start(provider, &location_state,
+ provider_args);
+ if (r < 0) exit(EXIT_FAILURE);
+ } else {
+ /* Try all providers, use the first that works. */
+ for (int i = 0;
+ location_providers[i].name != NULL; i++) {
+ const location_provider_t *p =
+ &location_providers[i];
+ r = provider_try_start(p, &location_state,
+ NULL);
+ if (r < 0) {
+ fputs(_("Trying other provider...\n"),
+ stderr);
+ continue;
+ }
- if (verbose) {
- /* TRANSLATORS: Append degree symbols if possible. */
- printf(_("Location: %f, %f\n"), lat, lon);
- }
+ provider = p;
+ break;
+ }
- /* Latitude */
- if (lat < MIN_LAT || lat > MAX_LAT) {
- /* TRANSLATORS: Append degree symbols if possible. */
- fprintf(stderr,
- _("Latitude must be between %.1f and %.1f.\n"),
- MIN_LAT, MAX_LAT);
- exit(EXIT_FAILURE);
+ /* Failure if no providers were successful at this
+ point. */
+ if (provider == NULL) {
+ fputs(_("No more location providers"
+ " to try.\n"), stderr);
+ exit(EXIT_FAILURE);
+ }
+ }
}
- /* Longitude */
- if (lon < MIN_LON || lon > MAX_LON) {
- /* TRANSLATORS: Append degree symbols if possible. */
- fprintf(stderr,
- _("Longitude must be between %.1f and %.1f.\n"),
- MIN_LON, MAX_LON);
- exit(EXIT_FAILURE);
+ float lat = NAN;
+ float lon = NAN;
+
+ if (mode != PROGRAM_MODE_RESET) {
+ /* Get current location. */
+ r = provider->get_location(&location_state, &lat, &lon);
+ if (r < 0) {
+ fputs(_("Unable to get location from provider.\n"),
+ stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ provider->free(&location_state);
+
+ if (verbose) {
+ /* TRANSLATORS: Append degree symbols if possible. */
+ printf(_("Location: %f, %f\n"), lat, lon);
+ }
+
+ /* Latitude */
+ if (lat < MIN_LAT || lat > MAX_LAT) {
+ /* TRANSLATORS: Append degree symbols if possible. */
+ fprintf(stderr,
+ _("Latitude must be between %.1f and %.1f.\n"),
+ MIN_LAT, MAX_LAT);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Longitude */
+ if (lon < MIN_LON || lon > MAX_LON) {
+ /* TRANSLATORS: Append degree symbols if possible. */
+ fprintf(stderr,
+ _("Longitude must be between"
+ " %.1f and %.1f.\n"), MIN_LON, MAX_LON);
+ exit(EXIT_FAILURE);
+ }
}
/* Color temperature at daytime */
@@ -426,47 +744,44 @@ main(int argc, char *argv[])
gamma[0], gamma[1], gamma[2]);
}
- /* Initialize gamma adjustment method. If use_randr is negative
+ /* Initialize gamma adjustment method. If method is NULL
try all methods until one that works is found. */
gamma_state_t state;
-#ifdef ENABLE_RANDR
- if (use_randr < 0 || use_randr == 1) {
- /* Initialize RANDR state */
- r = randr_init(&state.randr, screen_num);
- if (r < 0) {
- fputs(_("Initialization of RANDR failed.\n"), stderr);
- if (use_randr < 0) {
+
+ if (method != NULL) {
+ /* Use method specified on command line. */
+ r = method_try_start(method, &state, method_args);
+ if (r < 0) exit(EXIT_FAILURE);
+ } else {
+ /* Try all methods, use the first that works. */
+ for (int i = 0; gamma_methods[i].name != NULL; i++) {
+ const gamma_method_t *m = &gamma_methods[i];
+ r = method_try_start(m, &state, NULL);
+ if (r < 0) {
fputs(_("Trying other method...\n"), stderr);
- } else {
- exit(EXIT_FAILURE);
+ continue;
}
- } else {
- use_randr = 1;
+
+ method = m;
+ break;
}
- }
-#endif
-#ifdef ENABLE_VIDMODE
- if (use_randr < 0 || use_randr == 0) {
- /* Initialize VidMode state */
- r = vidmode_init(&state.vidmode, screen_num);
- if (r < 0) {
- fputs(_("Initialization of VidMode failed.\n"),
- stderr);
+ /* Failure if no methods were successful at this point. */
+ if (method == NULL) {
+ fputs(_("No more methods to try.\n"), stderr);
exit(EXIT_FAILURE);
- } else {
- use_randr = 0;
}
}
-#endif
- if (one_shot) {
+ switch (mode) {
+ case PROGRAM_MODE_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);
+ method->free(&state);
exit(EXIT_FAILURE);
}
@@ -484,16 +799,29 @@ 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 = method->set_temperature(&state, temp, gamma);
if (r < 0) {
fputs(_("Temperature adjustment failed.\n"), stderr);
- gamma_state_free(&state, use_randr);
+ method->free(&state);
exit(EXIT_FAILURE);
}
- } else {
+ }
+ break;
+ case PROGRAM_MODE_RESET:
+ {
+ /* Reset screen */
+ r = method->set_temperature(&state, NEUTRAL_TEMP, gamma);
+ if (r < 0) {
+ fputs(_("Temperature adjustment failed.\n"), stderr);
+ method->free(&state);
+ exit(EXIT_FAILURE);
+ }
+ }
+ break;
+ case PROGRAM_MODE_CONTINUAL:
+ {
/* Transition state */
- struct timespec short_trans_end;
+ double short_trans_end = 0;
int short_trans = 0;
int short_trans_done = 0;
@@ -507,6 +835,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 +852,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 +898,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);
+ method->free(&state);
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 +928,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 +954,7 @@ main(int argc, char *argv[])
if (short_trans_done) {
if (disabled) {
/* Restore saved gamma ramps */
- gamma_state_restore(&state, use_randr);
+ method->restore(&state);
}
short_trans_done = 0;
}
@@ -648,28 +973,34 @@ main(int argc, char *argv[])
/* Adjust temperature */
if (!disabled || short_trans) {
- r = gamma_state_set_temperature(&state,
- use_randr,
- temp, gamma);
+ r = method->set_temperature(&state,
+ temp, gamma);
if (r < 0) {
fputs(_("Temperature adjustment"
" failed.\n"), stderr);
- gamma_state_free(&state, use_randr);
+ method->free(&state);
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);
+ method->restore(&state);
+ }
+ break;
}
/* Clean up gamma adjustment state */
- gamma_state_free(&state, use_randr);
+ method->free(&state);
return EXIT_SUCCESS;
}
diff --git a/src/redshift.h b/src/redshift.h
new file mode 100644
index 0000000..8f488f6
--- /dev/null
+++ b/src/redshift.h
@@ -0,0 +1,90 @@
+/* redshift.h -- Main program 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_REDSHIFT_H
+#define _REDSHIFT_REDSHIFT_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/* Gamma adjustment method */
+typedef int gamma_method_init_func(void *state);
+typedef int gamma_method_start_func(void *state);
+typedef void gamma_method_free_func(void *state);
+typedef void gamma_method_print_help_func(FILE *f);
+typedef int gamma_method_set_option_func(void *state, const char *key,
+ const char *value);
+typedef void gamma_method_restore_func(void *state);
+typedef int gamma_method_set_temperature_func(void *state, int temp,
+ float gamma[3]);
+
+typedef struct {
+ char *name;
+
+ /* Initialize state. Options can be set between init and start. */
+ gamma_method_init_func *init;
+ /* Allocate storage and make connections that depend on options. */
+ gamma_method_start_func *start;
+ /* Free all allocated storage and close connections. */
+ gamma_method_free_func *free;
+
+ /* Print help on options for this adjustment method. */
+ gamma_method_print_help_func *print_help;
+ /* Set an option key, value-pair */
+ gamma_method_set_option_func *set_option;
+
+ /* Restore the adjustment to the state before start was called. */
+ gamma_method_restore_func *restore;
+ /* Set a specific color temperature. */
+ gamma_method_set_temperature_func *set_temperature;
+} gamma_method_t;
+
+
+/* Location provider */
+typedef int location_provider_init_func(void *state);
+typedef int location_provider_start_func(void *state);
+typedef void location_provider_free_func(void *state);
+typedef void location_provider_print_help_func(FILE *f);
+typedef int location_provider_set_option_func(void *state, const char *key,
+ const char *value);
+typedef int location_provider_get_location_func(void *state, float *lat,
+ float *lon);
+
+typedef struct {
+ char *name;
+
+ /* Initialize state. Options can be set between init and start. */
+ location_provider_init_func *init;
+ /* Allocate storage and make connections that depend on options. */
+ location_provider_start_func *start;
+ /* Free all allocated storage and close connections. */
+ location_provider_free_func *free;
+
+ /* Print help on options for this location provider. */
+ location_provider_print_help_func *print_help;
+ /* Set an option key, value-pair. */
+ location_provider_set_option_func *set_option;
+
+ /* Get current location. */
+ location_provider_get_location_func *get_location;
+} location_provider_t;
+
+
+#endif /* ! _REDSHIFT_REDSHIFT_H */
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 */