diff options
Diffstat (limited to '')
-rw-r--r-- | src/Makefile.am | 55 | ||||
-rw-r--r-- | src/colorramp.c | 2 | ||||
-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.c | 152 | ||||
-rw-r--r-- | src/gamma-w32gdi.h | 45 | ||||
-rw-r--r-- | src/gtk-redshift/Makefile.am | 40 | ||||
-rw-r--r-- | src/gtk-redshift/__init__.py | 18 | ||||
-rw-r--r-- | src/gtk-redshift/defs.py.in | 1 | ||||
-rw-r--r-- | src/gtk-redshift/gtk-redshift.in | 23 | ||||
-rw-r--r-- | src/gtk-redshift/rsappindicator.py | 99 | ||||
-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.c | 159 | ||||
-rw-r--r-- | src/location-gnome-clock.h | 44 | ||||
-rw-r--r-- | src/location-manual.c | 113 | ||||
-rw-r--r-- | src/location-manual.h | 44 | ||||
-rw-r--r-- | src/redshift.c | 701 | ||||
-rw-r--r-- | src/redshift.h | 90 | ||||
-rw-r--r-- | src/solar.c | 42 | ||||
-rw-r--r-- | src/solar.h | 8 | ||||
-rw-r--r-- | src/systemtime.c | 52 | ||||
-rw-r--r-- | src/systemtime.h | 32 |
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 */ |