aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am17
-rw-r--r--src/colorramp.c10
-rw-r--r--src/colorramp.h2
-rw-r--r--src/config-ini.c243
-rw-r--r--src/config-ini.h49
-rw-r--r--src/gamma-randr.c19
-rw-r--r--src/gamma-randr.h3
-rw-r--r--src/gamma-vidmode.c10
-rw-r--r--src/gamma-vidmode.h3
-rw-r--r--src/gamma-w32gdi.c53
-rw-r--r--src/gamma-w32gdi.h4
-rw-r--r--src/gtk-redshift/Makefile.am29
-rw-r--r--src/gtk-redshift/__init__.py1
-rw-r--r--src/gtk-redshift/defs.py.in1
-rw-r--r--src/gtk-redshift/gtk-redshift (renamed from src/gtk-redshift/gtk-redshift.in)2
-rw-r--r--src/gtk-redshift/rsappindicator.py99
-rw-r--r--src/gtk-redshift/statusicon.py78
-rw-r--r--src/gtk-redshift/utils.py66
-rw-r--r--src/location-geoclue.c186
-rw-r--r--src/location-geoclue.h44
-rw-r--r--src/location-gnome-clock.c135
-rw-r--r--src/redshift.c477
-rw-r--r--src/redshift.h1
23 files changed, 1198 insertions, 334 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index c07aea3..6c4a613 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,17 +9,19 @@ INCLUDES = -DLOCALEDIR=\"$(localedir)\"
bin_PROGRAMS = redshift
redshift_SOURCES = \
- redshift.c \
+ redshift.c redshift.h \
colorramp.c colorramp.h \
+ config-ini.c config-ini.h \
+ location-manual.c location-manual.h \
solar.c solar.h \
- systemtime.c systemtime.h \
- location-manual.c location-manual.h
+ systemtime.c systemtime.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
+ location-gnome-clock.c location-gnome-clock.h \
+ location-geoclue.c location-geoclue.h
AM_CFLAGS =
redshift_LDADD = @LIBINTL@
@@ -53,3 +55,10 @@ redshift_LDADD += \
$(GLIB_LIBS) $(GLIB_CFLAGS) \
$(GCONF_LIBS) $(GCONF_CFLAGS)
endif
+
+if ENABLE_GEOCLUE
+redshift_SOURCES += location-geoclue.c location-geoclue.h
+AM_CFLAGS += $(GEOCLUE_CFLAGS) $(GEOCLUE_LIBS)
+redshift_LDADD += \
+ $(GEOCLUE_LIBS) $(GEOCLUE_CFLAGS)
+endif
diff --git a/src/colorramp.c b/src/colorramp.c
index a154a9e..ed399f8 100644
--- a/src/colorramp.c
+++ b/src/colorramp.c
@@ -128,9 +128,9 @@ interpolate_color(float a, const float *c1, const float *c2, float *c)
void
colorramp_fill(uint16_t *gamma_r, uint16_t *gamma_g, uint16_t *gamma_b,
- int size, int temp, float gamma[3])
+ int size, int temp, float brightness, float gamma[3])
{
- /* Calculate white point */
+ /* Approximate white point */
float white_point[3];
float alpha = (temp % 100) / 100.0;
int temp_index = ((temp - 1000) / 100)*3;
@@ -139,10 +139,10 @@ colorramp_fill(uint16_t *gamma_r, uint16_t *gamma_g, uint16_t *gamma_b,
for (int i = 0; i < size; i++) {
gamma_r[i] = pow((float)i/size, 1.0/gamma[0]) *
- UINT16_MAX * white_point[0];
+ UINT16_MAX * brightness * white_point[0];
gamma_g[i] = pow((float)i/size, 1.0/gamma[1]) *
- UINT16_MAX * white_point[1];
+ UINT16_MAX * brightness * white_point[1];
gamma_b[i] = pow((float)i/size, 1.0/gamma[2]) *
- UINT16_MAX * white_point[2];
+ UINT16_MAX * brightness * white_point[2];
}
}
diff --git a/src/colorramp.h b/src/colorramp.h
index 88aa984..326969e 100644
--- a/src/colorramp.h
+++ b/src/colorramp.h
@@ -23,6 +23,6 @@
#include <stdint.h>
void colorramp_fill(uint16_t *gamma_r, uint16_t *gamma_g, uint16_t *gamma_b,
- int size, int temp, float gamma[3]);
+ int size, int temp, float brightness, float gamma[3]);
#endif /* ! _REDSHIFT_COLORRAMP_H */
diff --git a/src/config-ini.c b/src/config-ini.c
new file mode 100644
index 0000000..eae19c7
--- /dev/null
+++ b/src/config-ini.c
@@ -0,0 +1,243 @@
+/* config-ini.c -- INI config file parser
+ 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 <string.h>
+#include <errno.h>
+
+#include "config-ini.h"
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(s) gettext(s)
+#else
+# define _(s) s
+#endif
+
+#define MAX_CONFIG_PATH 4096
+#define MAX_LINE_LENGTH 512
+
+
+static FILE *
+open_config_file(const char *filepath)
+{
+ FILE *f = NULL;
+
+ if (filepath == NULL) {
+ char cp[MAX_CONFIG_PATH];
+ char *env;
+
+ if ((env = getenv("XDG_CONFIG_HOME")) != NULL &&
+ env[0] != '\0') {
+ snprintf(cp, sizeof(cp), "%s/redshift.conf", env);
+ filepath = cp;
+#ifdef _WIN32
+ } else if ((env = getenv("userprofile")) != NULL && env[0] != '\0') {
+ snprintf(cp, sizeof(cp),
+ "%s/.config/redshift.conf", env);
+ filepath = cp;
+#endif
+ } else if ((env = getenv("HOME")) != NULL && env[0] != '\0') {
+ snprintf(cp, sizeof(cp),
+ "%s/.config/redshift.conf", env);
+ filepath = cp;
+ }
+
+ if (filepath != NULL) {
+ f = fopen(filepath, "r");
+ if (f != NULL) return f;
+ else if (f == NULL && errno != ENOENT) return NULL;
+ }
+
+ /* TODO look in getenv("XDG_CONFIG_DIRS") */
+ } else {
+ f = fopen(filepath, "r");
+ if (f == NULL) {
+ perror("fopen");
+ return NULL;
+ }
+ }
+
+ return f;
+}
+
+int
+config_ini_init(config_ini_state_t *state, const char *filepath)
+{
+ config_ini_section_t *section = NULL;
+ state->sections = NULL;
+
+ FILE *f = open_config_file(filepath);
+ if (f == NULL) {
+ /* Only a serious error if a file was explicitly requested. */
+ if (filepath != NULL) return -1;
+ return 0;
+ }
+
+ char line[MAX_LINE_LENGTH];
+ char *s;
+
+ while (1) {
+ /* Handle the file input linewise. */
+ char *r = fgets(line, sizeof(line), f);
+ if (r == NULL) break;
+
+ /* Strip leading blanks and trailing newline. */
+ s = line + strspn(line, " \t");
+ s[strcspn(s, "\r\n")] = '\0';
+
+ /* Skip comments and empty lines. */
+ if (s[0] == ';' || s[0] == '\0') continue;
+
+ if (s[0] == '[') {
+ /* Read name of section. */
+ const char *name = s+1;
+ char *end = strchr(s, ']');
+ if (end == NULL || end[1] != '\0' || end == name) {
+ fputs(_("Malformed section header in config"
+ " file.\n"), stderr);
+ fclose(f);
+ config_ini_free(state);
+ return -1;
+ }
+
+ *end = '\0';
+
+ /* Create section. */
+ section = malloc(sizeof(config_ini_section_t));
+ if (section == NULL) {
+ fclose(f);
+ config_ini_free(state);
+ return -1;
+ }
+
+ /* Insert into section list. */
+ section->name = NULL;
+ section->settings = NULL;
+ section->next = state->sections;
+ state->sections = section;
+
+ /* Copy section name. */
+ section->name = malloc(end - name + 1);
+ if (section->name == NULL) {
+ fclose(f);
+ config_ini_free(state);
+ return -1;
+ }
+
+ memcpy(section->name, name, end - name + 1);
+ } else {
+ /* Split assignment at equals character. */
+ char *end = strchr(s, '=');
+ if (end == NULL || end == s) {
+ fputs(_("Malformed assignment in config"
+ " file.\n"), stderr);
+ fclose(f);
+ config_ini_free(state);
+ return -1;
+ }
+
+ *end = '\0';
+ char *value = end + 1;
+
+ if (section == NULL) {
+ fputs(_("Assignment outside section in config"
+ " file.\n"), stderr);
+ fclose(f);
+ config_ini_free(state);
+ return -1;
+ }
+
+ /* Create section. */
+ config_ini_setting_t *setting =
+ malloc(sizeof(config_ini_setting_t));
+ if (setting == NULL) {
+ fclose(f);
+ config_ini_free(state);
+ return -1;
+ }
+
+ /* Insert into section list. */
+ setting->name = NULL;
+ setting->value = NULL;
+ setting->next = section->settings;
+ section->settings = setting;
+
+ /* Copy name of setting. */
+ setting->name = malloc(end - s + 1);
+ if (setting->name == NULL) {
+ fclose(f);
+ config_ini_free(state);
+ return -1;
+ }
+
+ memcpy(setting->name, s, end - s + 1);
+
+ /* Copy setting value. */
+ size_t value_len = strlen(value) + 1;
+ setting->value = malloc(value_len);
+ if (setting->value == NULL) {
+ fclose(f);
+ config_ini_free(state);
+ return -1;
+ }
+
+ memcpy(setting->value, value, value_len);
+ }
+ }
+
+ fclose(f);
+
+ return 0;
+}
+
+void
+config_ini_free(config_ini_state_t *state)
+{
+ config_ini_section_t *section = state->sections;
+
+ while (section != NULL) {
+ config_ini_setting_t *setting = section->settings;
+
+ while (setting != NULL) {
+ free(setting->name);
+ free(setting->value);
+ setting = setting->next;
+ }
+
+ free(section->name);
+ section = section->next;
+ }
+}
+
+config_ini_section_t *
+config_ini_get_section(config_ini_state_t *state, const char *name)
+{
+ config_ini_section_t *section = state->sections;
+ while (section != NULL) {
+ if (strcasecmp(section->name, name) == 0) {
+ return section;
+ }
+ section = section->next;
+ }
+
+ return NULL;
+}
diff --git a/src/config-ini.h b/src/config-ini.h
new file mode 100644
index 0000000..e1bff73
--- /dev/null
+++ b/src/config-ini.h
@@ -0,0 +1,49 @@
+/* config-ini.h -- INI config file parser 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_CONFIG_INI_H
+#define _REDSHIFT_CONFIG_INI_H
+
+typedef struct _config_ini_section config_ini_section_t;
+typedef struct _config_ini_setting config_ini_setting_t;
+
+struct _config_ini_setting {
+ config_ini_setting_t *next;
+ char *name;
+ char *value;
+};
+
+struct _config_ini_section {
+ config_ini_section_t *next;
+ char *name;
+ config_ini_setting_t *settings;
+};
+
+typedef struct {
+ config_ini_section_t *sections;
+} config_ini_state_t;
+
+
+int config_ini_init(config_ini_state_t *state, const char *filepath);
+void config_ini_free(config_ini_state_t *state);
+
+config_ini_section_t *config_ini_get_section(config_ini_state_t *state,
+ const char *name);
+
+#endif /* ! _REDSHIFT_CONFIG_INI_H */
diff --git a/src/gamma-randr.c b/src/gamma-randr.c
index 66d5c48..8781e92 100644
--- a/src/gamma-randr.c
+++ b/src/gamma-randr.c
@@ -62,9 +62,12 @@ randr_init(randr_state_t *state)
xcb_randr_query_version_reply_t *ver_reply =
xcb_randr_query_version_reply(state->conn, ver_cookie, &error);
- if (error) {
+ /* TODO What does it mean when both error and ver_reply is NULL?
+ Apparently, we have to check both to avoid seg faults. */
+ if (error || ver_reply == NULL) {
+ int ec = (error != 0) ? error->error_code : -1;
fprintf(stderr, _("`%s' returned error %d\n"),
- "RANDR Query Version", error->error_code);
+ "RANDR Query Version", ec);
xcb_disconnect(state->conn);
return -1;
}
@@ -298,7 +301,7 @@ randr_set_option(randr_state_t *state, const char *key, const char *value)
static int
randr_set_temperature_for_crtc(randr_state_t *state, int crtc_num, int temp,
- float gamma[3])
+ float brightness, float gamma[3])
{
xcb_generic_error_t *error;
@@ -330,7 +333,7 @@ randr_set_temperature_for_crtc(randr_state_t *state, int crtc_num, int temp,
uint16_t *gamma_b = &gamma_ramps[2*ramp_size];
colorramp_fill(gamma_r, gamma_g, gamma_b, ramp_size,
- temp, gamma);
+ temp, brightness, gamma);
/* Set new gamma ramps */
xcb_void_cookie_t gamma_set_cookie =
@@ -352,7 +355,8 @@ randr_set_temperature_for_crtc(randr_state_t *state, int crtc_num, int temp,
}
int
-randr_set_temperature(randr_state_t *state, int temp, float gamma[3])
+randr_set_temperature(randr_state_t *state, int temp, float brightness,
+ float gamma[3])
{
int r;
@@ -361,12 +365,13 @@ randr_set_temperature(randr_state_t *state, int temp, float gamma[3])
if (state->crtc_num < 0) {
for (int i = 0; i < state->crtc_count; i++) {
r = randr_set_temperature_for_crtc(state, i,
- temp, gamma);
+ temp, brightness,
+ gamma);
if (r < 0) return -1;
}
} else {
return randr_set_temperature_for_crtc(state, state->crtc_num,
- temp, gamma);
+ temp, brightness, gamma);
}
return 0;
diff --git a/src/gamma-randr.h b/src/gamma-randr.h
index 4ccad8f..11818fa 100644
--- a/src/gamma-randr.h
+++ b/src/gamma-randr.h
@@ -54,7 +54,8 @@ 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]);
+int randr_set_temperature(randr_state_t *state, int temp, float brightness,
+ float gamma[3]);
#endif /* ! _REDSHIFT_GAMMA_RANDR_H */
diff --git a/src/gamma-vidmode.c b/src/gamma-vidmode.c
index e6b9412..a083658 100644
--- a/src/gamma-vidmode.c
+++ b/src/gamma-vidmode.c
@@ -68,7 +68,6 @@ vidmode_start(vidmode_state_t *state)
if (!r) {
fprintf(stderr, _("X request failed: %s\n"),
"XF86VidModeQueryVersion");
- XCloseDisplay(state->display);
return -1;
}
@@ -78,14 +77,12 @@ vidmode_start(vidmode_state_t *state)
if (!r) {
fprintf(stderr, _("X request failed: %s\n"),
"XF86VidModeGetGammaRampSize");
- XCloseDisplay(state->display);
return -1;
}
if (state->ramp_size == 0) {
fprintf(stderr, _("Gamma ramp size too small: %i\n"),
state->ramp_size);
- XCloseDisplay(state->display);
return -1;
}
@@ -93,7 +90,6 @@ vidmode_start(vidmode_state_t *state)
state->saved_ramps = malloc(3*state->ramp_size*sizeof(uint16_t));
if (state->saved_ramps == NULL) {
perror("malloc");
- XCloseDisplay(state->display);
return -1;
}
@@ -108,7 +104,6 @@ vidmode_start(vidmode_state_t *state)
if (!r) {
fprintf(stderr, _("X request failed: %s\n"),
"XF86VidModeGetGammaRamp");
- XCloseDisplay(state->display);
return -1;
}
@@ -174,7 +169,8 @@ vidmode_restore(vidmode_state_t *state)
}
int
-vidmode_set_temperature(vidmode_state_t *state, int temp, float gamma[3])
+vidmode_set_temperature(vidmode_state_t *state, int temp, float brightness,
+ float gamma[3])
{
int r;
@@ -190,7 +186,7 @@ vidmode_set_temperature(vidmode_state_t *state, int temp, float gamma[3])
uint16_t *gamma_b = &gamma_ramps[2*state->ramp_size];
colorramp_fill(gamma_r, gamma_g, gamma_b, state->ramp_size,
- temp, gamma);
+ temp, brightness, gamma);
/* Set new gamma ramps */
r = XF86VidModeSetGammaRamp(state->display, state->screen_num,
diff --git a/src/gamma-vidmode.h b/src/gamma-vidmode.h
index 18a4a88..735ba1f 100644
--- a/src/gamma-vidmode.h
+++ b/src/gamma-vidmode.h
@@ -42,7 +42,8 @@ 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]);
+int vidmode_set_temperature(vidmode_state_t *state, int temp, float brightness,
+ float gamma[3]);
#endif /* ! _REDSHIFT_GAMMA_VIDMODE_H */
diff --git a/src/gamma-w32gdi.c b/src/gamma-w32gdi.c
index aa2474d..d23bf72 100644
--- a/src/gamma-w32gdi.c
+++ b/src/gamma-w32gdi.c
@@ -43,7 +43,6 @@ int
w32gdi_init(w32gdi_state_t *state)
{
state->saved_ramps = NULL;
- state->hDC = NULL;
return 0;
}
@@ -54,14 +53,14 @@ w32gdi_start(w32gdi_state_t *state)
BOOL r;
/* Open device context */
- state->hDC = GetDC(NULL);
- if (state->hDC == NULL) {
+ HDC hDC = GetDC(NULL);
+ if (hDC == NULL) {
fputs(_("Unable to open device context.\n"), stderr);
return -1;
}
/* Check support for gamma ramps */
- int cmcap = GetDeviceCaps(state->hDC, COLORMGMTCAPS);
+ int cmcap = GetDeviceCaps(hDC, COLORMGMTCAPS);
if (cmcap != CM_GAMMA_RAMP) {
fputs(_("Display device does not support gamma ramps.\n"),
stderr);
@@ -72,18 +71,21 @@ w32gdi_start(w32gdi_state_t *state)
state->saved_ramps = malloc(3*GAMMA_RAMP_SIZE*sizeof(WORD));
if (state->saved_ramps == NULL) {
perror("malloc");
- ReleaseDC(NULL, state->hDC);
+ ReleaseDC(NULL, hDC);
return -1;
}
/* Save current gamma ramps so we can restore them at program exit */
- r = GetDeviceGammaRamp(state->hDC, state->saved_ramps);
+ r = GetDeviceGammaRamp(hDC, state->saved_ramps);
if (!r) {
fputs(_("Unable to save current gamma ramp.\n"), stderr);
- ReleaseDC(NULL, state->hDC);
+ ReleaseDC(NULL, hDC);
return -1;
}
+ /* Release device context */
+ ReleaseDC(NULL, hDC);
+
return 0;
}
@@ -92,9 +94,6 @@ w32gdi_free(w32gdi_state_t *state)
{
/* Free saved ramps */
free(state->saved_ramps);
-
- /* Release device context */
- if (state->hDC != NULL) ReleaseDC(NULL, state->hDC);
}
@@ -114,20 +113,39 @@ w32gdi_set_option(w32gdi_state_t *state, const char *key, const char *value)
void
w32gdi_restore(w32gdi_state_t *state)
{
+ /* Open device context */
+ HDC hDC = GetDC(NULL);
+ if (hDC == NULL) {
+ fputs(_("Unable to open device context.\n"), stderr);
+ return;
+ }
+
/* Restore gamma ramps */
- BOOL r = SetDeviceGammaRamp(state->hDC, state->saved_ramps);
+ BOOL r = SetDeviceGammaRamp(hDC, state->saved_ramps);
if (!r) fputs(_("Unable to restore gamma ramps.\n"), stderr);
+
+ /* Release device context */
+ ReleaseDC(NULL, hDC);
}
int
-w32gdi_set_temperature(w32gdi_state_t *state, int temp, float gamma[3])
+w32gdi_set_temperature(w32gdi_state_t *state, int temp, float brightness,
+ float gamma[3])
{
BOOL r;
+ /* Open device context */
+ HDC hDC = GetDC(NULL);
+ if (hDC == NULL) {
+ fputs(_("Unable to open device context.\n"), stderr);
+ return -1;
+ }
+
/* Create new gamma ramps */
WORD *gamma_ramps = malloc(3*GAMMA_RAMP_SIZE*sizeof(WORD));
if (gamma_ramps == NULL) {
perror("malloc");
+ ReleaseDC(NULL, hDC);
return -1;
}
@@ -136,17 +154,24 @@ w32gdi_set_temperature(w32gdi_state_t *state, int temp, float gamma[3])
WORD *gamma_b = &gamma_ramps[2*GAMMA_RAMP_SIZE];
colorramp_fill(gamma_r, gamma_g, gamma_b, GAMMA_RAMP_SIZE,
- temp, gamma);
+ temp, brightness, gamma);
/* Set new gamma ramps */
- r = SetDeviceGammaRamp(state->hDC, gamma_ramps);
+ r = SetDeviceGammaRamp(hDC, gamma_ramps);
if (!r) {
+ /* TODO it happens that SetDeviceGammaRamp returns FALSE on
+ occasions where the adjustment seems to be successful.
+ Does this only happen with multiple monitors connected? */
fputs(_("Unable to set gamma ramps.\n"), stderr);
free(gamma_ramps);
+ ReleaseDC(NULL, hDC);
return -1;
}
free(gamma_ramps);
+ /* Release device context */
+ ReleaseDC(NULL, hDC);
+
return 0;
}
diff --git a/src/gamma-w32gdi.h b/src/gamma-w32gdi.h
index 6cb9799..57a604f 100644
--- a/src/gamma-w32gdi.h
+++ b/src/gamma-w32gdi.h
@@ -25,7 +25,6 @@
typedef struct {
- HDC hDC;
WORD *saved_ramps;
} w32gdi_state_t;
@@ -39,7 +38,8 @@ 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]);
+int w32gdi_set_temperature(w32gdi_state_t *state, int temp, float brightness,
+ float gamma[3]);
#endif /* ! _REDSHIFT_GAMMA_W32GDI_H */
diff --git a/src/gtk-redshift/Makefile.am b/src/gtk-redshift/Makefile.am
index ddeafd6..bb69459 100644
--- a/src/gtk-redshift/Makefile.am
+++ b/src/gtk-redshift/Makefile.am
@@ -1,38 +1,19 @@
-if ENABLE_STATUSICON
-gui_module=statusicon
+if ENABLE_GUI
gtk_redshift_PYTHON = \
__init__.py \
+ utils.py \
statusicon.py
nodist_gtk_redshift_PYTHON = \
defs.py
gtk_redshiftdir = $(pythondir)/gtk_redshift
-bin_SCRIPTS = gtk-redshift
+dist_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
-
+EXTRA_DIST = defs.py.in
+CLEANFILES = defs.py
-# Main GUI script
-gtk-redshift: gtk-redshift.in
- sed -e "s|\@gui_module\@|$(gui_module)|g" $< > $@
# Local python definitions
defs.py: defs.py.in
diff --git a/src/gtk-redshift/__init__.py b/src/gtk-redshift/__init__.py
index 51ab2ef..0e4f254 100644
--- a/src/gtk-redshift/__init__.py
+++ b/src/gtk-redshift/__init__.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# __init__.py -- gtk-redshift package __init__ file
# This file is part of Redshift.
diff --git a/src/gtk-redshift/defs.py.in b/src/gtk-redshift/defs.py.in
index d3ca5ed..026fefd 100644
--- a/src/gtk-redshift/defs.py.in
+++ b/src/gtk-redshift/defs.py.in
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# defs.py -- GTK+ redshift local definitions
# This file is part of Redshift.
diff --git a/src/gtk-redshift/gtk-redshift.in b/src/gtk-redshift/gtk-redshift
index 120e05c..56d940e 100644
--- a/src/gtk-redshift/gtk-redshift.in
+++ b/src/gtk-redshift/gtk-redshift
@@ -19,5 +19,5 @@
if __name__ == '__main__':
- from gtk_redshift.@gui_module@ import run
+ from gtk_redshift.statusicon import run
run()
diff --git a/src/gtk-redshift/rsappindicator.py b/src/gtk-redshift/rsappindicator.py
deleted file mode 100644
index 59fa725..0000000
--- a/src/gtk-redshift/rsappindicator.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/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/statusicon.py b/src/gtk-redshift/statusicon.py
index 2295963..9b80a6b 100644
--- a/src/gtk-redshift/statusicon.py
+++ b/src/gtk-redshift/statusicon.py
@@ -1,5 +1,4 @@
-#!/usr/bin/env python
-# statusicon.py -- GTK+ status icon source
+# statusicon.py -- GUI status icon source
# This file is part of Redshift.
# Redshift is free software: you can redistribute it and/or modify
@@ -18,6 +17,12 @@
# Copyright (c) 2010 Jon Lund Steffensen <jonlst@gmail.com>
+'''GUI status icon for Redshift.
+
+The run method will try to start an appindicator for Redshift. If the
+appindicator module isn't present it will fall back to a GTK status icon.
+'''
+
import sys, os
import subprocess, signal
import gettext
@@ -26,8 +31,13 @@ import pygtk
pygtk.require("2.0")
import gtk, glib
+try:
+ import appindicator
+except ImportError:
+ appindicator = None
import defs
+import utils
def run():
@@ -42,39 +52,77 @@ def run():
process = subprocess.Popen(args)
try:
- # Create status icon
- status_icon = gtk.StatusIcon()
- status_icon.set_from_icon_name('redshift')
- status_icon.set_tooltip('Redshift')
+ if appindicator:
+ # Create indicator
+ indicator = appindicator.Indicator('redshift',
+ 'redshift-status-on',
+ appindicator.CATEGORY_APPLICATION_STATUS)
+ indicator.set_status(appindicator.STATUS_ACTIVE)
+ else:
+ # Create status icon
+ status_icon = gtk.StatusIcon()
+ status_icon.set_from_icon_name('redshift-status-on')
+ status_icon.set_tooltip('Redshift')
def toggle_cb(widget, data=None):
process.send_signal(signal.SIGUSR1)
+ if appindicator:
+ if indicator.get_icon() == 'redshift-status-on':
+ indicator.set_icon('redshift-status-off')
+ else:
+ indicator.set_icon('redshift-status-on')
+ else:
+ if status_icon.get_icon_name() == 'redshift-status-on':
+ status_icon.set_from_icon_name('redshift-status-off')
+ else:
+ status_icon.set_from_icon_name('redshift-status-on')
+
+ def autostart_cb(widget, data=None):
+ utils.set_autostart(widget.get_active())
def destroy_cb(widget, data=None):
- status_icon.set_visible(False)
+ if not appindicator:
+ status_icon.set_visible(False)
gtk.main_quit()
return False
# Create popup menu
status_menu = gtk.Menu()
- toggle_item = gtk.ImageMenuItem(_('Toggle'))
+ toggle_item = gtk.MenuItem(_('Toggle'))
toggle_item.connect('activate', toggle_cb)
status_menu.append(toggle_item)
+ autostart_item = gtk.CheckMenuItem(_('Autostart'))
+ try:
+ autostart_item.set_active(utils.get_autostart())
+ except IOError as strerror:
+ print strerror
+ autostart_item.set_property('sensitive', False)
+ else:
+ autostart_item.connect('activate', autostart_cb)
+ finally:
+ status_menu.append(autostart_item)
+
quit_item = gtk.ImageMenuItem(gtk.STOCK_QUIT)
quit_item.connect('activate', destroy_cb)
status_menu.append(quit_item)
- def popup_menu_cb(widget, button, time, data=None):
+ if appindicator:
status_menu.show_all()
- status_menu.popup(None, None, gtk.status_icon_position_menu,
- button, time, status_icon)
- # Connect signals for status icon and show
- status_icon.connect('activate', toggle_cb)
- status_icon.connect('popup-menu', popup_menu_cb)
- status_icon.set_visible(True)
+ # Set the menu
+ indicator.set_menu(status_menu)
+ else:
+ def popup_menu_cb(widget, button, time, data=None):
+ status_menu.show_all()
+ status_menu.popup(None, None, gtk.status_icon_position_menu,
+ button, time, status_icon)
+
+ # Connect signals for status icon and show
+ status_icon.connect('activate', toggle_cb)
+ status_icon.connect('popup-menu', popup_menu_cb)
+ status_icon.set_visible(True)
def child_cb(pid, cond, data=None):
sys.exit(-1)
diff --git a/src/gtk-redshift/utils.py b/src/gtk-redshift/utils.py
new file mode 100644
index 0000000..93e0195
--- /dev/null
+++ b/src/gtk-redshift/utils.py
@@ -0,0 +1,66 @@
+# utils.py -- utility functions 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 Francesco Marella <francesco.marella@gmail.com>
+
+import os
+from xdg import BaseDirectory as base
+from xdg import DesktopEntry as desktop
+
+REDSHIFT_DESKTOP = 'gtk-redshift.desktop'
+
+
+def get_autostart():
+ AUTOSTART_KEY = "X-GNOME-Autostart-enabled"
+ autostart_dir = base.save_config_path("autostart")
+ autostart_file = os.path.join(autostart_dir, REDSHIFT_DESKTOP)
+ if not os.path.exists(autostart_file):
+ desktop_files = list(base.load_data_paths("applications",
+ REDSHIFT_DESKTOP))
+ if not desktop_files:
+ raise IOError("Installed redshift desktop file not found!")
+ desktop_file_path = desktop_files[0]
+ # Read installed file and modify it
+ dfile = desktop.DesktopEntry(desktop_file_path)
+ dfile.set(AUTOSTART_KEY, "false")
+ dfile.write(filename=autostart_file)
+ return False
+ else:
+ dfile = desktop.DesktopEntry(autostart_file)
+ if dfile.get(AUTOSTART_KEY) == 'false':
+ return False
+ else:
+ return True
+
+def set_autostart(active):
+ AUTOSTART_KEY = "X-GNOME-Autostart-enabled"
+ autostart_dir = base.save_config_path("autostart")
+ autostart_file = os.path.join(autostart_dir, REDSHIFT_DESKTOP)
+ if not os.path.exists(autostart_file):
+ desktop_files = list(base.load_data_paths("applications",
+ REDSHIFT_DESKTOP))
+ if not desktop_files:
+ raise IOError("Installed redshift desktop file not found!")
+ return
+ desktop_file_path = desktop_files[0]
+ # Read installed file and modify it
+ dfile = desktop.DesktopEntry(desktop_file_path)
+ else:
+ dfile = desktop.DesktopEntry(autostart_file)
+ activestr = str(bool(active)).lower()
+ # print "Setting autostart to %s" % activestr
+ dfile.set(AUTOSTART_KEY, activestr)
+ dfile.write(filename=autostart_file)
diff --git a/src/location-geoclue.c b/src/location-geoclue.c
new file mode 100644
index 0000000..6946dd8
--- /dev/null
+++ b/src/location-geoclue.c
@@ -0,0 +1,186 @@
+/* location-geoclue.c -- Geoclue 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 Mathieu Trudel-Lapierre <mathieu-tl@ubuntu.com>
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+#include <geoclue/geoclue-master.h>
+#include <geoclue/geoclue-position.h>
+
+#include "location-geoclue.h"
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(s) gettext(s)
+#else
+# define _(s) s
+#endif
+
+#define DEFAULT_PROVIDER "org.freedesktop.Geoclue.Providers.UbuntuGeoIP"
+#define DEFAULT_PROVIDER_PATH "/org/freedesktop/Geoclue/Providers/UbuntuGeoIP"
+
+int
+location_geoclue_init(location_geoclue_state_t *state)
+{
+ g_type_init();
+
+ state->position = NULL;
+ state->provider = NULL;
+ state->provider_path = NULL;
+
+ return 0;
+}
+
+int
+location_geoclue_start(location_geoclue_state_t *state)
+{
+ GeoclueMaster *master = NULL;
+ GeoclueMasterClient *client = NULL;
+ GError *error = NULL;
+ gchar *name = NULL;
+
+ if (!(state->provider && state->provider_path)) {
+ master = geoclue_master_get_default();
+ client = geoclue_master_create_client(master, NULL, NULL);
+
+ if (!geoclue_master_client_set_requirements(client,
+ GEOCLUE_ACCURACY_LEVEL_REGION,
+ 0, FALSE,
+ GEOCLUE_RESOURCE_NETWORK,
+ &error)) {
+ g_printerr(_("Can't set requirements for master: %s"),
+ error->message);
+ g_error_free(error);
+ g_object_unref(client);
+
+ return -1;
+ }
+
+ state->position = geoclue_master_client_create_position(client, NULL);
+ } else {
+ state->position = geoclue_position_new(state->provider,
+ state->provider_path);
+ }
+
+ if (geoclue_provider_get_provider_info(GEOCLUE_PROVIDER(state->position),
+ &name, NULL, NULL)) {
+ fprintf(stdout, _("Started Geoclue provider `%s'.\n"), name);
+ g_free(name);
+ } else {
+ fputs(_("Could not find a usable Geoclue provider.\n"), stderr);
+ fputs(_("Try setting name and path to specify which to use.\n"), stderr);
+ return -1;
+ }
+
+ return 0;
+}
+
+void
+location_geoclue_free(location_geoclue_state_t *state)
+{
+ if (state->position != NULL) g_object_unref(state->position);
+}
+
+void
+location_geoclue_print_help(FILE *f)
+{
+ fputs(_("Use the location as discovered by a Geoclue provider.\n"), f);
+ fputs("\n", f);
+
+ /* TRANSLATORS: Geoclue help output
+ left column must not be translated */
+ fputs(_(" name=N\tName of Geoclue provider (or `default')\n"
+ " path=N\tPath of Geoclue provider (or `default')\n"), f);
+ fputs("\n", f);
+}
+
+int
+location_geoclue_set_option(location_geoclue_state_t *state,
+ const char *key, const char *value)
+{
+ const char *provider = NULL;
+ const char *path = NULL;
+
+ /* Parse string value */
+ if (key != NULL && strcasecmp(key, "name") == 0) {
+ if (value != NULL && strcasecmp(value, "default") == 0) {
+ provider = DEFAULT_PROVIDER;
+ } else if (value != NULL) {
+ provider = value;
+ } else {
+ fputs(_("Must specify a provider `name' (or use `default').\n"), stderr);
+ return -1;
+ }
+
+ /* TODO I don't think we own the string here, should be copied. */
+ state->provider = provider;
+ } else if (key != NULL && strcasecmp(key, "path") == 0) {
+ if (value != NULL && strcasecmp(value, "default") == 0) {
+ path = DEFAULT_PROVIDER_PATH;
+ } else if (value != NULL) {
+ path = value;
+ } else {
+ fputs(_("Must specify a provider `path' (or use `default').\n"), stderr);
+ return -1;
+ }
+
+ /* TODO I don't think we own the string here, should be copied. */
+ state->provider_path = path;
+ } else if (key == NULL) {
+ return -1;
+ } else {
+ fprintf(stderr, _("Unknown method parameter: `%s'.\n"), key);
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+location_geoclue_get_location(location_geoclue_state_t *state,
+ float *lat, float *lon)
+{
+ GeocluePositionFields fields;
+ GError *error = NULL;
+ double latitude = 0, longitude = 0;
+
+ fields = geoclue_position_get_position(state->position, NULL,
+ &latitude, &longitude, NULL,
+ NULL, &error);
+ if (error) {
+ g_printerr(_("Could not get location: %s.\n"), error->message);
+ g_error_free(error);
+ return -1;
+ }
+
+ if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE &&
+ fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) {
+ fprintf(stdout, _("According to the geoclue provider"
+ " we're at: %.2f, %.2f\n"),
+ latitude, longitude);
+ } else {
+ g_warning(_("Provider does not have a valid location available."));
+ return -1;
+ }
+
+ *lat = latitude;
+ *lon = longitude;
+
+ return 0;
+}
diff --git a/src/location-geoclue.h b/src/location-geoclue.h
new file mode 100644
index 0000000..40ab22c
--- /dev/null
+++ b/src/location-geoclue.h
@@ -0,0 +1,44 @@
+/* location-geoclue.h -- Geoclue 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 Mathieu Trudel-Lapierre <mathieu-tl@ubuntu.com>
+*/
+
+#ifndef _REDSHIFT_LOCATION_GEOCLUE_H
+#define _REDSHIFT_LOCATION_GEOCLUE_H
+
+#include <stdio.h>
+#include <geoclue/geoclue-position.h>
+
+typedef struct {
+ GeocluePosition *position; /* main geoclue object */
+ const char *provider; /* name of a geoclue provider */
+ const char *provider_path; /* path of the geoclue provider */
+} location_geoclue_state_t;
+
+int location_geoclue_init(location_geoclue_state_t *state);
+int location_geoclue_start(location_geoclue_state_t *state);
+void location_geoclue_free(location_geoclue_state_t *state);
+
+void location_geoclue_print_help(FILE *f);
+int location_geoclue_set_option(location_geoclue_state_t *state,
+ const char *key, const char *value);
+
+int location_geoclue_get_location(location_geoclue_state_t *state,
+ float *lat, float *lon);
+
+
+#endif /* ! _REDSHIFT_LOCATION_GEOCLUE_H */
diff --git a/src/location-gnome-clock.c b/src/location-gnome-clock.c
index 10b95eb..2bb1949 100644
--- a/src/location-gnome-clock.c
+++ b/src/location-gnome-clock.c
@@ -32,88 +32,137 @@
#endif
+/* Find current selected city for the clock applet with the specified id.
+ Returns NULL if not found. */
+static char *
+find_current_city(GConfClient *client, const char *id)
+{
+ char *current_city = NULL;
+ char *cities_key = g_strdup_printf("/apps/panel/applets/%s"
+ "/prefs/cities", id);
+ GSList *cities = gconf_client_get_list(client,
+ cities_key,
+ GCONF_VALUE_STRING, NULL);
+
+ if (cities == NULL) {
+ fprintf(stderr, _("Error reading city list: `%s'.\n"),
+ cities_key);
+ g_free(cities_key);
+ return NULL;
+ }
+
+ g_free(cities_key);
+
+ 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);
+
+ return current_city;
+}
+
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);
+ /* Get a list of active applets in the panel. */
+ GSList *applets = gconf_client_get_list(client,
+ "/apps/panel/general/applet_id_list",
+ GCONF_VALUE_STRING, NULL);
+ if (applets == NULL) {
+ /* JDS has an alternate list of applets. */
+ applets = gconf_client_get_list(client,
+ "/apps/panel/general/applet_id_list_jds",
+ GCONF_VALUE_STRING, NULL);
+ }
+
+ if (applets == NULL) {
+ fputs(_("Cannot list GNOME panel applets.\n"), stderr);
+ g_slist_free(applets);
g_object_unref(client);
return -1;
}
- char *cities_key = NULL;
+ /* Go through each applet and check if it is a clock applet.
+ When a clock applet is found, check whether there is a
+ city selected as the current city. */
+ char *current_city = NULL;
+
+ /* Keep track of the number of clock applets found to be able to give
+ better error output if something fails. */
+ int clock_applet_count = 0;
+
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 *id = applet->data;
+ if (current_city == NULL) {
+ char *key = g_strdup_printf("/apps/panel/applets/%s"
+ "/bonobo_iid", id);
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);
+ NULL);
+
+ /* Try both gnome-panel 2.30.x and earlier bonobo_iid
+ key and newer applet_iid. */
+ if (bonobo_iid != NULL &&
+ !strcmp(bonobo_iid, "OAFIID:GNOME_ClockApplet")) {
+ clock_applet_count += 1;
+ current_city = find_current_city(client, id);
+ } else {
+ g_free(key);
+ key = g_strdup_printf("/apps/panel/applets/%s"
+ "/applet_iid", id);
+ char *applet_iid = gconf_client_get_string(client, key,
+ NULL);
+
+ if (applet_iid != NULL &&
+ !strcmp(applet_iid, "ClockAppletFactory::ClockApplet")) {
+ clock_applet_count += 1;
+ current_city = find_current_city(client, id);
}
- g_free(bonobo_iid);
+
+ g_free(applet_iid);
}
+ g_free(bonobo_iid);
g_free(key);
}
- g_free(path);
+ g_free(id);
}
g_slist_free(applets);
+ g_object_unref(client);
- if (cities_key == NULL) {
- fputs(_("No clock applet was found.\n"), stderr);
- g_object_unref(client);
- return -1;
- }
+ /* Check whether an applet and a current city was found. */
- 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);
+ if (clock_applet_count == 0) {
+ fputs(_("No clock applet was found.\n"), stderr);
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;
}
+ /* Find coords for selected city and parse as number. */
+
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);
+ g_free(current_city);
return -1;
}
+ g_free(current_city);
+
char *lat_num_str = lat_str + strlen("latitude=\"");
char *lon_num_str = lon_str + strlen("longitude=\"");
diff --git a/src/redshift.c b/src/redshift.c
index 18cc2c5..af154b8 100644
--- a/src/redshift.c
+++ b/src/redshift.c
@@ -30,8 +30,8 @@
#include <locale.h>
#include <errno.h>
-#ifdef HAVE_SYS_SIGNAL_H
-# include <sys/signal.h>
+#ifdef HAVE_SIGNAL_H
+# include <signal.h>
#endif
#ifdef ENABLE_NLS
@@ -42,6 +42,7 @@
#endif
#include "redshift.h"
+#include "config-ini.h"
#include "solar.h"
#include "systemtime.h"
@@ -75,6 +76,10 @@
# include "location-gnome-clock.h"
#endif
+#ifdef ENABLE_GEOCLUE
+# include "location-geoclue.h"
+#endif
+
/* Union of state data for gamma adjustment methods */
typedef union {
@@ -138,11 +143,28 @@ typedef union {
#ifdef ENABLE_GNOME_CLOCK
location_gnome_clock_state_t gnome_clock;
#endif
+#ifdef ENABLE_GEOCLUE
+ location_geoclue_state_t geoclue;
+#endif
} location_state_t;
/* Location provider method structs */
static const location_provider_t location_providers[] = {
+#ifdef ENABLE_GEOCLUE
+ {
+ "geoclue",
+ (location_provider_init_func *)location_geoclue_init,
+ (location_provider_start_func *)location_geoclue_start,
+ (location_provider_free_func *)location_geoclue_free,
+ (location_provider_print_help_func *)
+ location_geoclue_print_help,
+ (location_provider_set_option_func *)
+ location_geoclue_set_option,
+ (location_provider_get_location_func *)
+ location_geoclue_get_location
+ },
+#endif
#ifdef ENABLE_GNOME_CLOCK
{
"gnome-clock",
@@ -179,12 +201,15 @@ static const location_provider_t location_providers[] = {
#define MAX_LON 180.0
#define MIN_TEMP 1000
#define MAX_TEMP 10000
+#define MIN_BRIGHTNESS 0.1
+#define MAX_BRIGHTNESS 1.0
#define MIN_GAMMA 0.1
#define MAX_GAMMA 10.0
/* Default values for parameters. */
#define DEFAULT_DAY_TEMP 5500
#define DEFAULT_NIGHT_TEMP 3700
+#define DEFAULT_BRIGHTNESS 1.0
#define DEFAULT_GAMMA 1.0
/* The color temperature when no adjustment is applied. */
@@ -201,11 +226,12 @@ static const location_provider_t location_providers[] = {
typedef enum {
PROGRAM_MODE_CONTINUAL,
PROGRAM_MODE_ONE_SHOT,
- PROGRAM_MODE_RESET
+ PROGRAM_MODE_RESET,
+ PROGRAM_MODE_MANUAL
} program_mode_t;
-#ifdef HAVE_SYS_SIGNAL_H
+#ifdef HAVE_SIGNAL_H
static volatile sig_atomic_t exiting = 0;
static volatile sig_atomic_t disable = 0;
@@ -224,12 +250,12 @@ sigdisable(int signo)
disable = 1;
}
-#else /* ! HAVE_SYS_SIGNAL_H */
+#else /* ! HAVE_SIGNAL_H */
static int exiting = 0;
static int disable = 0;
-#endif /* ! HAVE_SYS_SIGNAL_H */
+#endif /* ! HAVE_SIGNAL_H */
/* Calculate color temperature for the specified solar elevation. */
@@ -285,7 +311,8 @@ print_help(const char *program_name)
/* TRANSLATORS: help output 4
`list' must not be translated
no-wrap */
- fputs(_(" -g R:G:B\tAdditional gamma correction to apply\n"
+ fputs(_(" -c FILE\tLoad settings from specified configuration file\n"
+ " -g R:G:B\tAdditional gamma correction to apply\n"
" -l LAT:LON\tYour current location\n"
" -l PROVIDER\tSelect provider for automatic"
" location updates\n"
@@ -294,6 +321,7 @@ print_help(const char *program_name)
" \t\t(Type `list' to see available methods)\n"
" -o\t\tOne shot mode (do not continously adjust"
" color temperature)\n"
+ " -O TEMP\tOne shot manual mode (set color temperature)\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"),
@@ -301,6 +329,16 @@ print_help(const char *program_name)
fputs("\n", stdout);
/* TRANSLATORS: help output 5 */
+ printf(_("The neutral temperature is %uK. Using this value will not\n"
+ "change the color temperature of the display. Setting the\n"
+ "color temperature to a value higher than this results in\n"
+ "more blue light, and setting a lower value will result in\n"
+ "more red light.\n"),
+ NEUTRAL_TEMP);
+
+ fputs("\n", stdout);
+
+ /* TRANSLATORS: help output 6 */
printf(_("Default values:\n\n"
" Daytime temperature: %uK\n"
" Night temperature: %uK\n"),
@@ -308,7 +346,7 @@ print_help(const char *program_name)
fputs("\n", stdout);
- /* TRANSLATORS: help output 6 */
+ /* TRANSLATORS: help output 7 */
printf(_("Please report bugs to <%s>\n"), PACKAGE_BUGREPORT);
}
@@ -345,7 +383,8 @@ print_provider_list()
static int
provider_try_start(const location_provider_t *provider,
- location_state_t *state, char *args)
+ location_state_t *state,
+ config_ini_state_t *config, char *args)
{
int r;
@@ -356,7 +395,31 @@ provider_try_start(const location_provider_t *provider,
return -1;
}
- /* Set provider options. */
+ /* Set provider options from config file. */
+ config_ini_section_t *section =
+ config_ini_get_section(config, provider->name);
+ if (section != NULL) {
+ config_ini_setting_t *setting = section->settings;
+ while (setting != NULL) {
+ r = provider->set_option(state, setting->name,
+ setting->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;
+ }
+ setting = setting->next;
+ }
+ }
+
+ /* Set provider options from command line. */
while (args != NULL) {
char *next_arg = strchr(args, ':');
if (next_arg != NULL) *(next_arg++) = '\0';
@@ -398,7 +461,8 @@ provider_try_start(const location_provider_t *provider,
static int
method_try_start(const gamma_method_t *method,
- gamma_state_t *state, char *args)
+ gamma_state_t *state,
+ config_ini_state_t *config, char *args)
{
int r;
@@ -409,7 +473,31 @@ method_try_start(const gamma_method_t *method,
return -1;
}
- /* Set method options. */
+ /* Set method options from config file. */
+ config_ini_section_t *section =
+ config_ini_get_section(config, method->name);
+ if (section != NULL) {
+ config_ini_setting_t *setting = section->settings;
+ while (setting != NULL) {
+ r = method->set_option(state, setting->name,
+ setting->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;
+ }
+ setting = setting->next;
+ }
+ }
+
+ /* Set method options from command line. */
while (args != NULL) {
char *next_arg = strchr(args, ':');
if (next_arg != NULL) *(next_arg++) = '\0';
@@ -449,6 +537,62 @@ method_try_start(const gamma_method_t *method,
return 0;
}
+/* A gamma string contains either one floating point value,
+ or three values separated by colon. */
+static int
+parse_gamma_string(const char *str, float gamma[])
+{
+ char *s = strchr(str, ':');
+ if (s == NULL) {
+ /* Use value for all channels */
+ float g = atof(str);
+ gamma[0] = gamma[1] = gamma[2] = g;
+ } else {
+ /* Parse separate value for each channel */
+ *(s++) = '\0';
+ char *g_s = s;
+ s = strchr(s, ':');
+ if (s == NULL) return -1;
+
+ *(s++) = '\0';
+ gamma[0] = atof(str); /* Red */
+ gamma[1] = atof(g_s); /* Blue */
+ gamma[2] = atof(s); /* Green */
+ }
+
+ return 0;
+}
+
+static const gamma_method_t *
+find_gamma_method(const char *name)
+{
+ const gamma_method_t *method = NULL;
+ for (int i = 0; gamma_methods[i].name != NULL; i++) {
+ const gamma_method_t *m = &gamma_methods[i];
+ if (strcasecmp(name, m->name) == 0) {
+ method = m;
+ break;
+ }
+ }
+
+ return method;
+}
+
+static const location_provider_t *
+find_location_provider(const char *name)
+{
+ const location_provider_t *provider = NULL;
+ for (int i = 0; location_providers[i].name != NULL; i++) {
+ const location_provider_t *p = &location_providers[i];
+ if (strcasecmp(name, p->name) == 0) {
+ provider = p;
+ break;
+ }
+ }
+
+ return provider;
+}
+
int
main(int argc, char *argv[])
@@ -465,10 +609,14 @@ main(int argc, char *argv[])
textdomain(PACKAGE);
#endif
- /* Initialize to defaults */
- int temp_day = DEFAULT_DAY_TEMP;
- int temp_night = DEFAULT_NIGHT_TEMP;
- float gamma[3] = { DEFAULT_GAMMA, DEFAULT_GAMMA, DEFAULT_GAMMA };
+ /* Initialize settings to NULL values. */
+ char *config_filepath = NULL;
+
+ int temp_set = -1;
+ int temp_day = -1;
+ int temp_night = -1;
+ float gamma[3] = { NAN, NAN, NAN };
+ float brightness = NAN;
const gamma_method_t *method = NULL;
char *method_args = NULL;
@@ -476,38 +624,30 @@ main(int argc, char *argv[])
const location_provider_t *provider = NULL;
char *provider_args = NULL;
- int transition = 1;
+ int transition = -1;
program_mode_t mode = PROGRAM_MODE_CONTINUAL;
int verbose = 0;
char *s;
- /* Parse arguments. */
+ /* Parse command line arguments. */
int opt;
- while ((opt = getopt(argc, argv, "g:hl:m:ort:vx")) != -1) {
+ while ((opt = getopt(argc, argv, "b:c:g:hl:m:oO:rt:vx")) != -1) {
switch (opt) {
+ case 'b':
+ brightness = atof(optarg);
+ break;
+ case 'c':
+ if (config_filepath != NULL) free(config_filepath);
+ config_filepath = strdup(optarg);
+ break;
case 'g':
- s = strchr(optarg, ':');
- if (s == NULL) {
- /* Use value for all channels */
- float g = atof(optarg);
- gamma[0] = gamma[1] = gamma[2] = g;
- } else {
- /* Parse separate value for each channel */
- *(s++) = '\0';
- gamma[0] = atof(optarg); /* Red */
- char *g_s = s;
- s = strchr(s, ':');
- if (s == NULL) {
- fputs(_("Malformed gamma argument.\n"),
- stderr);
- fputs(_("Try `-h' for more"
- " information.\n"), stderr);
- exit(EXIT_FAILURE);
- }
-
- *(s++) = '\0';
- gamma[1] = atof(g_s); /* Blue */
- gamma[2] = atof(s); /* Green */
+ r = parse_gamma_string(optarg, gamma);
+ if (r < 0) {
+ fputs(_("Malformed gamma argument.\n"),
+ stderr);
+ fputs(_("Try `-h' for more"
+ " information.\n"), stderr);
+ exit(EXIT_FAILURE);
}
break;
case 'h':
@@ -543,16 +683,8 @@ main(int argc, char *argv[])
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;
- }
- }
-
+ /* Lookup provider from name. */
+ provider = find_location_provider(provider_name);
if (provider == NULL) {
fprintf(stderr, _("Unknown location provider"
" `%s'.\n"), provider_name);
@@ -563,7 +695,7 @@ main(int argc, char *argv[])
if (provider_args != NULL &&
strcasecmp(provider_args, "help") == 0) {
provider->print_help(stdout);
- exit(EXIT_FAILURE);
+ exit(EXIT_SUCCESS);
}
break;
case 'm':
@@ -580,20 +712,13 @@ main(int argc, char *argv[])
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;
- }
- }
-
+ /* Find adjustment method by name. */
+ method = find_gamma_method(optarg);
if (method == NULL) {
/* TRANSLATORS: This refers to the method
used to adjust colors e.g VidMode */
- fprintf(stderr, _("Unknown method `%s'.\n"),
- optarg);
+ fprintf(stderr, _("Unknown adjustment method"
+ " `%s'.\n"), optarg);
exit(EXIT_FAILURE);
}
@@ -601,12 +726,16 @@ main(int argc, char *argv[])
if (method_args != NULL &&
strcasecmp(method_args, "help") == 0) {
method->print_help(stdout);
- exit(EXIT_FAILURE);
+ exit(EXIT_SUCCESS);
}
break;
case 'o':
mode = PROGRAM_MODE_ONE_SHOT;
break;
+ case 'O':
+ mode = PROGRAM_MODE_MANUAL;
+ temp_set = atoi(optarg);
+ break;
case 'r':
transition = 0;
break;
@@ -636,16 +765,111 @@ main(int argc, char *argv[])
}
}
+ /* Load settings from config file. */
+ config_ini_state_t config_state;
+ r = config_ini_init(&config_state, config_filepath);
+ if (r < 0) {
+ fputs("Unable to load config file.\n", stderr);
+ exit(EXIT_FAILURE);
+ }
+
+ if (config_filepath != NULL) free(config_filepath);
+
+ /* Read global config settings. */
+ config_ini_section_t *section = config_ini_get_section(&config_state,
+ "redshift");
+ if (section != NULL) {
+ config_ini_setting_t *setting = section->settings;
+ while (setting != NULL) {
+ if (strcasecmp(setting->name, "temp-day") == 0) {
+ if (temp_day < 0) {
+ temp_day = atoi(setting->value);
+ }
+ } else if (strcasecmp(setting->name,
+ "temp-night") == 0) {
+ if (temp_night < 0) {
+ temp_night = atoi(setting->value);
+ }
+ } else if (strcasecmp(setting->name,
+ "transition") == 0) {
+ if (transition < 0) {
+ transition = !!atoi(setting->value);
+ }
+ } else if (strcasecmp(setting->name,
+ "brightness") == 0) {
+ if (isnan(brightness)) {
+ brightness = atof(setting->value);
+ }
+ } else if (strcasecmp(setting->name, "gamma") == 0) {
+ if (isnan(gamma[0])) {
+ r = parse_gamma_string(setting->value,
+ gamma);
+ if (r < 0) {
+ fputs(_("Malformed gamma"
+ " setting.\n"),
+ stderr);
+ exit(EXIT_FAILURE);
+ }
+ }
+ } else if (strcasecmp(setting->name,
+ "adjustment-method") == 0) {
+ if (method == NULL) {
+ method = find_gamma_method(
+ setting->value);
+ if (method == NULL) {
+ fprintf(stderr, _("Unknown"
+ " adjustment"
+ " method"
+ " `%s'.\n"),
+ setting->value);
+ exit(EXIT_FAILURE);
+ }
+ }
+ } else if (strcasecmp(setting->name,
+ "location-provider") == 0) {
+ if (provider == NULL) {
+ provider = find_location_provider(
+ setting->value);
+ if (provider == NULL) {
+ fprintf(stderr, _("Unknown"
+ " location"
+ " provider"
+ " `%s'.\n"),
+ setting->value);
+ exit(EXIT_FAILURE);
+ }
+ }
+ } else {
+ fprintf(stderr, _("Unknown configuration"
+ " setting `%s'.\n"),
+ setting->name);
+ }
+ setting = setting->next;
+ }
+ }
+
+ /* Use default values for settings that were neither defined in
+ the config file nor on the command line. */
+ if (temp_day < 0) temp_day = DEFAULT_DAY_TEMP;
+ if (temp_night < 0) temp_night = DEFAULT_NIGHT_TEMP;
+ if (isnan(brightness)) brightness = DEFAULT_BRIGHTNESS;
+ if (isnan(gamma[0])) gamma[0] = gamma[1] = gamma[2] = DEFAULT_GAMMA;
+ if (transition < 0) transition = 1;
+
+ float lat = NAN;
+ float lon = NAN;
+
/* 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) {
+ /* Location is not needed for reset mode
+ or for manual temperature setting. */
+ if (mode != PROGRAM_MODE_RESET && mode != PROGRAM_MODE_MANUAL) {
if (provider != NULL) {
/* Use provider specified on command line. */
r = provider_try_start(provider, &location_state,
- provider_args);
+ &config_state, provider_args);
if (r < 0) exit(EXIT_FAILURE);
} else {
/* Try all providers, use the first that works. */
@@ -654,13 +878,15 @@ main(int argc, char *argv[])
const location_provider_t *p =
&location_providers[i];
r = provider_try_start(p, &location_state,
- NULL);
+ &config_state, NULL);
if (r < 0) {
- fputs(_("Trying other provider...\n"),
+ fputs(_("Trying next provider...\n"),
stderr);
continue;
}
+ /* Found provider that works. */
+ printf(_("Using provider `%s'.\n"), p->name);
provider = p;
break;
}
@@ -673,60 +899,77 @@ main(int argc, char *argv[])
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);
+ 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);
+ /* 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. */
+ /* 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 */
+ if (temp_day < MIN_TEMP || temp_day >= MAX_TEMP) {
+ fprintf(stderr,
+ _("Temperature must be between %uK and %uK.\n"),
+ MIN_TEMP, MAX_TEMP);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Color temperature at night */
+ if (temp_night < MIN_TEMP || temp_night >= MAX_TEMP) {
fprintf(stderr,
- _("Latitude must be between %.1f and %.1f.\n"),
- MIN_LAT, MAX_LAT);
+ _("Temperature must be between %uK and %uK.\n"),
+ MIN_TEMP, MAX_TEMP);
exit(EXIT_FAILURE);
}
+ }
- /* Longitude */
- if (lon < MIN_LON || lon > MAX_LON) {
- /* TRANSLATORS: Append degree symbols if possible. */
+ if (mode == PROGRAM_MODE_MANUAL) {
+ /* Check color temperature to be set */
+ if (temp_set < MIN_TEMP || temp_set >= MAX_TEMP) {
fprintf(stderr,
- _("Longitude must be between"
- " %.1f and %.1f.\n"), MIN_LON, MAX_LON);
+ _("Temperature must be between %uK and %uK.\n"),
+ MIN_TEMP, MAX_TEMP);
exit(EXIT_FAILURE);
}
}
- /* Color temperature at daytime */
- if (temp_day < MIN_TEMP || temp_day >= MAX_TEMP) {
+ /* Brightness */
+ if (brightness < MIN_BRIGHTNESS || brightness > MAX_BRIGHTNESS) {
fprintf(stderr,
- _("Temperature must be between %uK and %uK.\n"),
- MIN_TEMP, MAX_TEMP);
+ _("Brightness value must be between %.1f and %.1f.\n"),
+ MIN_BRIGHTNESS, MAX_BRIGHTNESS);
exit(EXIT_FAILURE);
}
- /* Color temperature at night */
- if (temp_night < MIN_TEMP || temp_night >= MAX_TEMP) {
- fprintf(stderr,
- _("Temperature must be between %uK and %uK.\n"),
- MIN_TEMP, MAX_TEMP);
- exit(EXIT_FAILURE);
+ if (verbose) {
+ printf(_("Brightness: %.2f\n"), brightness);
}
/* Gamma */
@@ -750,18 +993,21 @@ main(int argc, char *argv[])
if (method != NULL) {
/* Use method specified on command line. */
- r = method_try_start(method, &state, method_args);
+ r = method_try_start(method, &state, &config_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);
+ r = method_try_start(m, &state, &config_state, NULL);
if (r < 0) {
- fputs(_("Trying other method...\n"), stderr);
+ fputs(_("Trying next method...\n"), stderr);
continue;
}
+ /* Found method that works. */
+ printf(_("Using method `%s'.\n"), m->name);
method = m;
break;
}
@@ -799,18 +1045,32 @@ main(int argc, char *argv[])
if (verbose) printf(_("Color temperature: %uK\n"), temp);
/* Adjust temperature */
- r = method->set_temperature(&state, temp, gamma);
+ r = method->set_temperature(&state, temp, brightness, gamma);
+ if (r < 0) {
+ fputs(_("Temperature adjustment failed.\n"), stderr);
+ method->free(&state);
+ exit(EXIT_FAILURE);
+ }
+ }
+ break;
+ case PROGRAM_MODE_MANUAL:
+ {
+ if (verbose) printf(_("Color temperature: %uK\n"), temp_set);
+
+ /* Adjust temperature */
+ r = method->set_temperature(&state, temp_set, brightness, gamma);
if (r < 0) {
fputs(_("Temperature adjustment failed.\n"), stderr);
method->free(&state);
exit(EXIT_FAILURE);
}
+
}
break;
case PROGRAM_MODE_RESET:
{
/* Reset screen */
- r = method->set_temperature(&state, NEUTRAL_TEMP, gamma);
+ r = method->set_temperature(&state, NEUTRAL_TEMP, 1.0, gamma);
if (r < 0) {
fputs(_("Temperature adjustment failed.\n"), stderr);
method->free(&state);
@@ -835,7 +1095,7 @@ main(int argc, char *argv[])
will be exactly 6500K. */
float adjustment_alpha = 0.0;
-#ifdef HAVE_SYS_SIGNAL_H
+#ifdef HAVE_SIGNAL_H
struct sigaction sigact;
sigset_t sigset;
sigemptyset(&sigset);
@@ -852,7 +1112,7 @@ main(int argc, char *argv[])
sigact.sa_mask = sigset;
sigact.sa_flags = 0;
sigaction(SIGUSR1, &sigact, NULL);
-#endif /* HAVE_SYS_SIGNAL_H */
+#endif /* HAVE_SIGNAL_H */
/* Continously adjust color temperature */
int done = 0;
@@ -974,7 +1234,8 @@ main(int argc, char *argv[])
/* Adjust temperature */
if (!disabled || short_trans) {
r = method->set_temperature(&state,
- temp, gamma);
+ temp, brightness,
+ gamma);
if (r < 0) {
fputs(_("Temperature adjustment"
" failed.\n"), stderr);
diff --git a/src/redshift.h b/src/redshift.h
index 8f488f6..c3d1239 100644
--- a/src/redshift.h
+++ b/src/redshift.h
@@ -33,6 +33,7 @@ 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 brightness,
float gamma[3]);
typedef struct {