aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO1
-rw-r--r--src/colour.c25
-rw-r--r--src/common.h384
-rw-r--r--src/config.c46
-rw-r--r--src/gamma-coopgamma.c36
-rw-r--r--src/gamma-drm.c40
-rw-r--r--src/gamma-dummy.c29
-rw-r--r--src/gamma-quartz.c27
-rw-r--r--src/gamma-randr.c65
-rw-r--r--src/gamma-vidmode.c34
-rw-r--r--src/gamma-w32gdi.c22
-rw-r--r--src/gamma.c42
-rw-r--r--src/location-corelocation.m122
-rw-r--r--src/location-geoclue2.c134
-rw-r--r--src/location-manual.c35
-rw-r--r--src/location.c86
-rw-r--r--src/redshift.c206
-rw-r--r--src/util.c49
18 files changed, 799 insertions, 584 deletions
diff --git a/TODO b/TODO
index cfffd88..8e19428 100644
--- a/TODO
+++ b/TODO
@@ -190,7 +190,6 @@ po/sv.po: gammaförfining[ar] -> gammatabell[er]; lost -> förlorat {wrong gende
po/de.po: lost -> verloren -> verschwunden
po/sv.po: felaktig -> ogiltig (?)
po/sv.po: NBSP before units (after ° which should also be added)
-Translate gamma-coopgamma.c
Previously unmarked for NLS: redshift.c: "Unable to load config file."
Optionally use METAR data adjust day-time colour temperature according the cloudiness
read the monitores chromas to determine it's colour space and correct the RGB multipliers according
diff --git a/src/colour.c b/src/colour.c
index d77c6ab..0138980 100644
--- a/src/colour.c
+++ b/src/colour.c
@@ -18,6 +18,31 @@
*/
#include "common.h"
+
+void
+interpolate_colour_settings(const struct colour_setting *a, const struct colour_setting *b,
+ double t, struct colour_setting *result)
+{
+ int i;
+ t = CLAMP(0.0, t, 1.0);
+ result->temperature = (1.0 - t) * a->temperature + t * b->temperature;
+ result->brightness = (1.0 - t) * a->brightness + t * b->brightness;
+ for (i = 0; i < 3; i++)
+ result->gamma[i] = (1.0 - t) * a->gamma[i] + t * b->gamma[i];
+}
+
+
+int
+colour_setting_diff_is_major(const struct colour_setting *a, const struct colour_setting *b)
+{
+ return MAX(a->temperature, b->temperature) - MIN(a->temperature, b->temperature) > 25UL ||
+ fabs(a->brightness - b->brightness) > 0.1 ||
+ fabs(a->gamma[0] - b->gamma[0]) > 0.1 ||
+ fabs(a->gamma[1] - b->gamma[1]) > 0.1 ||
+ fabs(a->gamma[2] - b->gamma[2]) > 0.1;
+}
+
+
#if defined(__GNUC__)
# pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
diff --git a/src/common.h b/src/common.h
index 704e64a..e3cc37b 100644
--- a/src/common.h
+++ b/src/common.h
@@ -282,19 +282,56 @@ typedef struct gamma_state GAMMA_STATE;
typedef struct location_state LOCATION_STATE;
+/**
+ * The time of the day: day, night, or twilight
+ */
enum period {
- PERIOD_NONE = 0,
+ /**
+ * None applied
+ */
+ PERIOD_NONE,
+
+ /**
+ * Full daytime
+ */
PERIOD_DAYTIME,
+
+ /**
+ * Full nighttime
+ */
PERIOD_NIGHT,
+
+ /**
+ * Transitioning between day and night
+ * (either direction) (twilight)
+ */
PERIOD_TRANSITION
};
+
+/**
+ * The mode the program is running in
+ */
enum program_mode {
+ /**
+ * Run in foreground continually update temperature
+ */
PROGRAM_MODE_CONTINUAL,
+
+ /**
+ * Update temperature once then exit
+ */
PROGRAM_MODE_ONE_SHOT,
+
+ /**
+ * Print setting and exit
+ */
PROGRAM_MODE_PRINT,
- PROGRAM_MODE_RESET,
- PROGRAM_MODE_MANUAL
+
+ /**
+ * Remove effects and exit
+ */
+ PROGRAM_MODE_RESET
};
@@ -413,35 +450,94 @@ struct colour_setting {
};
-/* Time range.
- Fields are offsets from midnight in seconds. */
-struct time_range {
- time_t start;
- time_t end;
-};
-
-
+/**
+ * Linked list of time periods for `CLOCK_SCHEME`
+ */
struct time_period {
+ /**
+ * The number of seconds after midnight the period starts
+ */
time_t start;
+
+ /**
+ * 1 if at daytime at the the time `.start`,
+ * 0 if at nighttime at the the time `.start`
+ */
double day_level;
+
+ /**
+ * `.next->day_level - .day_level` dividied by
+ * the duration of the period, in seconds
+ *
+ * `.day_level` is added to the number of seconds
+ * elapsed since `.start` multiplied by this number
+ * to get the dayness level at that time
+ */
double diff_over_duration;
+
+ /**
+ * The following time period
+ */
const struct time_period *next;
};
-/* Transition scheme.
- The solar elevations at which the transition begins/ends */
+/**
+ * Dayness level scheme
+ */
union scheme {
+ /**
+ * The scheme type
+ *
+ * If `STATIC_SCHEME`, the union contains no scheme data
+ */
enum scheme_type type;
- struct {
+
+ /**
+ * Used if `.type == SOLAR_SCHEME`
+ */
+ struct solar_scheme {
+ /**
+ * `SOLAR_SCHEME`
+ */
enum scheme_type type;
+
+ /**
+ * The lowest solar elevation of daytime
+ */
double high;
+
+ /**
+ * The highest solar elevation of nighttime
+ */
double low;
+
+ /**
+ * `.high - .low`
+ */
double range;
} elevation;
- struct {
+
+ /**
+ * Used if `.type == CLOCK_SCHEME`
+ */
+ struct clock_scheme {
+ /**
+ * `CLOCK_SCHEME`
+ */
enum scheme_type type;
+
+ /**
+ * Circularly linked list of time periods
+ *
+ * The application will update this to always
+ * point to the current time period
+ */
const struct time_period *periods;
+
+ /**
+ * The memory allocation for the nodes in `.periods`
+ */
struct time_period periods_array[4];
} time;
};
@@ -521,10 +617,6 @@ struct settings {
const struct location_provider *provider;
/* Arguments for location provider. */
char *provider_args;
-
- enum program_mode mode;
- int verbose;
- enum scheme_type scheme_type;
};
@@ -532,53 +624,202 @@ struct settings {
* Adjustment method information and interface
*/
struct gamma_method {
+ /**
+ * The name of the adjustment method
+ */
const char *name;
- /* If true, this method will be tried if none is explicitly chosen. */
+ /**
+ * 1 if the method should be tried if none is explicitly chosen,
+ * 0 otherwise
+ */
int autostart;
- /* Initialize state. Options can be set between init and start. */
- int (*init)(GAMMA_STATE **state);
- /* Allocate storage and make connections that depend on options. */
- int (*start)(GAMMA_STATE *state, enum program_mode mode);
- /* Free all allocated storage and close connections. */
- void (*free)(GAMMA_STATE *state);
+ /**
+ * Create an initialised state object
+ *
+ * @param state_out Output parameter for the state object
+ * @return 0 on success, -1 on failure
+ *
+ * `*state_out` is set (potentially to `NULL`) on failure
+ */
+ int (*create)(GAMMA_STATE **state_out);
- /* Print help on options for this adjustment method. */
- void (*print_help)(FILE *f);
- /* Set an option key, value-pair */
+ /**
+ * Configure the adjustment method
+ *
+ * @param state State object for the adjustment method
+ * @param key Option to configure
+ * @param value Option value to set
+ * @return 0 on success, -1 on failure
+ */
int (*set_option)(GAMMA_STATE *state, const char *key, const char *value);
- /* Restore the adjustment to the state before start was called. */
+ /**
+ * Print help on options for the adjustment method
+ *
+ * @param f Output sink
+ */
+ void (*print_help)(FILE *f);
+
+ /**
+ * Finalise option-dependent initialisation and connections
+ *
+ * @param state State object for the adjustment method
+ * @return 0 on success, -1 on failure
+ */
+ int (*start)(GAMMA_STATE *state);
+
+ /**
+ * Apply colour settings
+ *
+ * @param state State object for the adjustment method
+ * @param settings The colour settings to apply
+ * @param preserve Whether currently applied adjustments (assumed
+ * to be colour calibration) shall remain applied
+ * @return 0 on success, -1 on failure
+ */
+ int (*apply)(GAMMA_STATE *state, const struct colour_setting *setting, int preserve);
+
+ /**
+ * Restore the adjustments to the `.state` before start was called
+ *
+ * @param state State object for the adjustment method
+ */
void (*restore)(GAMMA_STATE *state);
- /* Set a specific colour temperature. */
- int (*set_temperature)(GAMMA_STATE *state, const struct colour_setting *setting, int preserve);
+
+ /**
+ * Close connections and deallocate all state resources
+ *
+ * @param state The state to terminate
+ *
+ * The pointer `state` will become invalid
+ */
+ void (*free)(GAMMA_STATE *state);
};
+/**
+ * Initialiser for `struct gamma_method`
+ *
+ * @param NAME:const char * Value for `.name`
+ * @param AUTOSTART:int Value for `.autostart`
+ * @param PREFIX:identifier The text, sans terminal underscore (_), prefixed to the
+ * names of each function implementing the adjustment method
+ */
+#define GAMMA_METHOD_INIT(NAME, AUTOSTART, PREFIX)\
+ {\
+ .name = (NAME),\
+ .autostart = (AUTOSTART),\
+ .create = &PREFIX##_create,\
+ .set_option = &PREFIX##_set_option,\
+ .print_help = &PREFIX##_print_help,\
+ .start = &PREFIX##_start,\
+ .free = &PREFIX##_free,\
+ .restore = &PREFIX##_restore,\
+ .apply = &PREFIX##_apply\
+ }
+
/**
* Location provider information and interface
*/
struct location_provider {
+ /**
+ * The name of the location provider
+ */
const char *name;
- /* Initialize state. Options can be set between init and start. */
- int (*init)(LOCATION_STATE **state);
- /* Allocate storage and make connections that depend on options. */
- int (*start)(LOCATION_STATE *state);
- /* Free all allocated storage and close connections. */
- void (*free)(LOCATION_STATE *state);
+ /**
+ * Create an initialised state object
+ *
+ * @param state_out Output parameter for the state object
+ * @return 0 on success, -1 on failure
+ *
+ * `*state_out` is set (potentially to `NULL`) on failure
+ */
+ int (*create)(LOCATION_STATE **state_out);
- /* Print help on options for this location provider. */
- void (*print_help)(FILE *f);
- /* Set an option key, value-pair. */
+ /**
+ * Configure the location provider
+ *
+ * @param state State object for the location provider
+ * @param key Option to configure
+ * @param value Option value to set
+ * @return 0 on success, -1 on failure
+ */
int (*set_option)(LOCATION_STATE *state, const char *key, const char *value);
- /* Listen and handle location updates. */
+ /**
+ * Print help on options for the location provider
+ *
+ * @param f Output sink
+ */
+ void (*print_help)(FILE *f);
+
+ /**
+ * Finalise option-dependent initialisation and connections
+ *
+ * @param state State object for the location provider
+ * @return 0 on success, -1 on failure
+ */
+ int (*start)(LOCATION_STATE *state);
+
+ /**
+ * Get the file descriptor used by the location provider
+ *
+ * The application may use it for detecting when there
+ * is data available for `.handle` to act upon
+ *
+ * @param state State object for the location provider
+ * @return The file descriptor used by location provider, -1 if none
+ */
int (*get_fd)(LOCATION_STATE *state);
- int (*handle)(LOCATION_STATE *state, struct location *location, int *available);
+
+ /**
+ * Get the current location
+ *
+ * This function shall only be caused if `.get_fd` returns -1
+ * or the file descriptor it returns has data available on it
+ * as indicated by input polling, otherwise `*location` and
+ * `*available` will not be set
+ *
+ * @param state State object for the location provider
+ * @param location_out Output parameter for the current location
+ * @param available_out Output parameter for whether the location provider
+ * is currently available
+ * @return 0 on success, -1 on unrecoverable failure
+ */
+ int (*fetch)(LOCATION_STATE *state, struct location *location, int *available);
+
+ /**
+ * Close connections and deallocate all state resources
+ *
+ * @param state The state to terminate
+ *
+ * The pointer `state` will become invalid
+ */
+ void (*free)(LOCATION_STATE *state);
};
+/**
+ * Initialiser for `struct location_provider`
+ *
+ * @param NAME:const char * Value for `.name`
+ * @param PREFIX:identifier The text, sans terminal underscore (_), prefixed to the
+ * names of each function implementing the location provider
+ */
+#define LOCATION_PROVIDER_INIT(NAME, PREFIX)\
+ {\
+ .name = (NAME),\
+ .create = &PREFIX##_create,\
+ .set_option = &PREFIX##_set_option,\
+ .print_help = &PREFIX##_print_help,\
+ .start = &PREFIX##_start,\
+ .get_fd = &PREFIX##_get_fd,\
+ .fetch = &PREFIX##_fetch,\
+ .free = &PREFIX##_free\
+ }
+
/**
* `NULL` terminated list of adjustment methods
@@ -615,9 +856,41 @@ extern struct colour_setting night_settings;
*/
extern union scheme scheme;
+/**
+ * Whether the application is in verbose mode
+ */
+extern int verbose;
+
+/**
+ * The mode the application is running in
+ */
+extern enum program_mode mode;
+
/* colour.c */
+/**
+ * Interpolate between two colour settings
+ *
+ * @param a The first colour setting, used wholly when `t` is 0
+ * @param b The second colour setting, used wholly when `t` is 1
+ * @param t The degree to which `second` second be applied
+ * @param result Output parameter for `(1 - t) * a + t * b`
+ */
+void interpolate_colour_settings(const struct colour_setting *a, const struct colour_setting *b,
+ double t, struct colour_setting *result);
+
+/**
+ * Check whether the differences between two colours settings
+ * are large enough to warrant fading between the two
+ *
+ * @param a The first colour setting
+ * @param b The second colour setting
+ * @return 1 if the difference between `a` and `b` is large, 0 otherwise
+ */
+GCC_ONLY(__attribute__((__pure__)))
+int colour_setting_diff_is_major(const struct colour_setting *a, const struct colour_setting *b);
+
#define LIST_RAMPS_STOP_VALUE_TYPES(X, D)\
X(u8, uint8_t, UINT8_MAX, 8) D\
X(u16, uint16_t, UINT16_MAX, 16) D\
@@ -699,6 +972,23 @@ int get_location(const struct location_provider *provider, LOCATION_STATE *state
void acquire_location_provider(struct settings *settings, LOCATION_STATE **location_state_out);
+/**
+ * Check whether location is valid
+ *
+ * If the message is invalid, and error message is printed
+ *
+ * @param location The location to check
+ * @return 1 if the location is valid, 0 otherwise
+ */
+int location_is_valid(const struct location *location);
+
+/**
+ * Print the current location to standard output
+ *
+ * @param location The current location
+ */
+void print_location(const struct location *location);
+
/* hooks.c */
@@ -772,15 +1062,19 @@ FILE *try_path_fopen(const struct env_path *path_spec, const char **path_out, ch
*/
DIR *try_path_opendir(const struct env_path *path_spec, const char **path_out, char **pathbuf_out);
+#ifndef WINDOWS
/**
- * Create a pipe(7) where both ends have `O_NONBLOCK` applied
+ * Create a pipe(7) where both ends have `O_CLOEXEC` and,
+ * if available for pipes, `O_DIRECT`, applied, the read-end
+ * will also have `O_NONBLOCK` applied
*
* @param pipefds Output parameter for the pipe's file descriptors:
* 0) reading file descriptor, and
* 1) writing file descriptor
* @return 0 on success, -1 on failure
*/
-int pipe_nonblock(int pipefds[2]);
+int pipe_rdnonblock(int pipefds[2]);
+#endif
extern const struct gamma_method dummy_gamma_method;
diff --git a/src/config.c b/src/config.c
index 443991d..1613770 100644
--- a/src/config.c
+++ b/src/config.c
@@ -26,7 +26,9 @@ USAGE("[-b day:night] [-c file] [-g r:g:b] [-l latitude:longitude | -l provider[
struct colour_setting day_settings;
struct colour_setting night_settings;
-union scheme scheme;
+union scheme scheme = {.type = SOLAR_SCHEME};
+enum program_mode mode = PROGRAM_MODE_CONTINUAL;
+int verbose = 0;
/**
@@ -569,9 +571,6 @@ load_defaults(struct settings *settings)
settings->provider = NULL;
settings->provider_args = NULL;
-
- settings->mode = PROGRAM_MODE_CONTINUAL;
- settings->scheme_type = SOLAR_SCHEME;
}
@@ -673,16 +672,16 @@ load_from_cmdline(struct settings *settings, int argc, char *argv[])
break;
case 'o':
- settings->mode = PROGRAM_MODE_ONE_SHOT;
+ mode = PROGRAM_MODE_ONE_SHOT;
break;
case 'O':
- settings->mode = PROGRAM_MODE_MANUAL;
+ mode = PROGRAM_MODE_ONE_SHOT;
set_temperature(ARG(), &settings->day.temperature, &settings->night.temperature, NULL);
break;
case 'p':
- settings->mode = PROGRAM_MODE_PRINT;
+ mode = PROGRAM_MODE_PRINT;
break;
case 'P':
@@ -700,7 +699,7 @@ load_from_cmdline(struct settings *settings, int argc, char *argv[])
break;
case 'v':
- settings->verbose = 1;
+ verbose = 1;
break;
case 'V':
@@ -709,7 +708,7 @@ load_from_cmdline(struct settings *settings, int argc, char *argv[])
break;
case 'x':
- settings->mode = PROGRAM_MODE_RESET;
+ mode = PROGRAM_MODE_RESET;
break;
default:
@@ -828,7 +827,7 @@ load_settings(struct settings *settings, int argc, char *argv[])
n = !settings->dawn.start.source + !settings->dawn.end.source;
n += !settings->dusk.start.source + !settings->dusk.end.source;
if (n) {
- settings->scheme_type = CLOCK_SCHEME;
+ scheme.type = CLOCK_SCHEME;
if (n != 4)
eprintf(_("Partial time-configuration not supported!"));
@@ -858,19 +857,26 @@ load_settings(struct settings *settings, int argc, char *argv[])
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wfloat-equal"
#endif
- if (settings->mode == PROGRAM_MODE_RESET) {
- settings->scheme_type = STATIC_SCHEME;
- } else if (settings->day.temperature.value == settings->night.temperature.value &&
- settings->day.brightness.value == settings->night.brightness.value &&
- settings->day.gamma.value[0] == settings->night.gamma.value[0] &&
- settings->day.gamma.value[1] == settings->night.gamma.value[1] &&
- settings->day.gamma.value[2] == settings->night.gamma.value[2]) {
- settings->scheme_type = STATIC_SCHEME;
+ if (settings->day.temperature.value == settings->night.temperature.value &&
+ settings->day.brightness.value == settings->night.brightness.value &&
+ settings->day.gamma.value[0] == settings->night.gamma.value[0] &&
+ settings->day.gamma.value[1] == settings->night.gamma.value[1] &&
+ settings->day.gamma.value[2] == settings->night.gamma.value[2]) {
+ scheme.type = STATIC_SCHEME;
}
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#endif
+ /* If reseting effects, use neutral colour settings (static scheme) and do not preserve gamma */
+ if (mode == PROGRAM_MODE_RESET) {
+ scheme.type = STATIC_SCHEME;
+ settings->preserve_gamma.value = 0;
+ day_settings = COLOUR_SETTING_NEUTRAL;
+ night_settings = COLOUR_SETTING_NEUTRAL;
+ goto settings_published;
+ }
+
/* Publish loaded settings */
day_settings.temperature = settings->day.temperature.value;
day_settings.brightness = settings->day.brightness.value;
@@ -882,7 +888,6 @@ load_settings(struct settings *settings, int argc, char *argv[])
night_settings.gamma[0] = settings->night.gamma.value[0];
night_settings.gamma[1] = settings->night.gamma.value[1];
night_settings.gamma[2] = settings->night.gamma.value[2];
- scheme.type = settings->scheme_type;
if (scheme.type == SOLAR_SCHEME) {
scheme.elevation.high = settings->elevation_high.value;
scheme.elevation.low = settings->elevation_low.value;
@@ -908,9 +913,10 @@ load_settings(struct settings *settings, int argc, char *argv[])
scheme.time.periods_array[i].diff_over_duration /= duration ? (double)duration : 1.0;
}
}
+settings_published:
/* Output settings */
- if (settings->verbose) {
+ if (verbose) {
if (scheme.type == SOLAR_SCHEME) {
/* TRANSLATORS: Append degree symbols if possible. */
printf(_("Solar elevations: day above %.1f, night below %.1f\n"),
diff --git a/src/gamma-coopgamma.c b/src/gamma-coopgamma.c
index 2f2b0d0..a4e08ef 100644
--- a/src/gamma-coopgamma.c
+++ b/src/gamma-coopgamma.c
@@ -115,14 +115,14 @@ print_error(struct gamma_state *state)
static int
-coopgamma_init(struct gamma_state **state)
+coopgamma_create(struct gamma_state **state_out)
{
- struct gamma_state *s;
+ struct gamma_state *state;
struct signal_blockage signal_blockage;
- s = *state = ecalloc(1, sizeof(**state));
+ state = *state_out = ecalloc(1, sizeof(**state_out));
- if (libcoopgamma_context_initialise(&s->ctx)) {
+ if (libcoopgamma_context_initialise(&state->ctx)) {
weprintf("libcoopgamma_context_initialise:");
return -1;
}
@@ -130,8 +130,8 @@ coopgamma_init(struct gamma_state **state)
/* This is done this early to check if coopgamma is available */
if (unblocked_signal(SIGCHLD, &signal_blockage) < 0)
return -1;
- s->methods = libcoopgamma_get_methods();
- if (s->methods == NULL) {
+ state->methods = libcoopgamma_get_methods();
+ if (state->methods == NULL) {
weprintf("libcoopgamma_get_methods:");
if (restore_signal_blockage(SIGCHLD, &signal_blockage) < 0)
exit(1);
@@ -140,13 +140,13 @@ coopgamma_init(struct gamma_state **state)
if (restore_signal_blockage(SIGCHLD, &signal_blockage) < 0)
return -1;
- s->priority = 0x0800000000000000LL;
+ state->priority = 0x0800000000000000LL;
return 0;
}
static int
-coopgamma_start(struct gamma_state *state, enum program_mode mode)
+coopgamma_start(struct gamma_state *state)
{
struct signal_blockage signal_blockage;
libcoopgamma_lifespan_t lifespan;
@@ -160,14 +160,15 @@ coopgamma_start(struct gamma_state *state, enum program_mode mode)
lifespan = LIBCOOPGAMMA_REMOVE;
break;
case PROGRAM_MODE_ONE_SHOT:
- case PROGRAM_MODE_MANUAL:
lifespan = LIBCOOPGAMMA_UNTIL_REMOVAL;
break;
case PROGRAM_MODE_CONTINUAL:
- case PROGRAM_MODE_PRINT: /* TODO ? */
- default:
lifespan = LIBCOOPGAMMA_UNTIL_DEATH;
break;
+ default:
+ case PROGRAM_MODE_PRINT:
+ abort();
+ break;
}
free(state->methods);
@@ -472,7 +473,7 @@ coopgamma_restore(struct gamma_state *state)
}
static int
-coopgamma_set_temperature(struct gamma_state *state, const struct colour_setting *setting, int perserve)
+coopgamma_apply(struct gamma_state *state, const struct colour_setting *setting, int perserve)
{
libcoopgamma_filter_t *filter;
libcoopgamma_filter_t *last_filter = NULL;
@@ -516,13 +517,4 @@ coopgamma_set_temperature(struct gamma_state *state, const struct colour_setting
}
-const struct gamma_method coopgamma_gamma_method = {
- "coopgamma", 1,
- &coopgamma_init,
- &coopgamma_start,
- &coopgamma_free,
- &coopgamma_print_help,
- &coopgamma_set_option,
- &coopgamma_restore,
- &coopgamma_set_temperature
-};
+const struct gamma_method coopgamma_gamma_method = GAMMA_METHOD_INIT("coopgamma", 1, coopgamma);
diff --git a/src/gamma-drm.c b/src/gamma-drm.c
index ea31367..03454ae 100644
--- a/src/gamma-drm.c
+++ b/src/gamma-drm.c
@@ -45,26 +45,20 @@ struct gamma_state {
static int
-drm_init(struct gamma_state **state)
+drm_create(struct gamma_state **state_out)
{
- struct gamma_state *s;
-
- /* Initialize state. */
- *state = malloc(sizeof(**state));
- if (*state == NULL) return -1;
-
- s = *state;
- s->card_num = 0;
- s->crtc_num = -1;
- s->fd = -1;
- s->res = NULL;
- s->crtcs = NULL;
-
+ struct gamma_state *state;
+ state = *state_out = emalloc(sizeof(**state_out));
+ state->card_num = 0;
+ state->crtc_num = -1;
+ state->fd = -1;
+ state->res = NULL;
+ state->crtcs = NULL;
return 0;
}
static int
-drm_start(struct gamma_state *state, enum program_mode mode)
+drm_start(struct gamma_state *state)
{
/* Acquire access to a graphics card. */
long maxlen = strlen(DRM_DIR_NAME) + strlen(DRM_DEV_NAME) + 10;
@@ -72,8 +66,6 @@ drm_start(struct gamma_state *state, enum program_mode mode)
int crtc_count;
struct drm_crtc_state *crtcs;
- (void) mode;
-
sprintf(pathname, DRM_DEV_NAME, DRM_DIR_NAME, state->card_num);
state->fd = open(pathname, O_RDWR | O_CLOEXEC);
@@ -248,8 +240,7 @@ drm_set_option(struct gamma_state *state, const char *key, const char *value)
}
static int
-drm_set_temperature(
- struct gamma_state *state, const struct colour_setting *setting, int preserve)
+drm_apply(struct gamma_state *state, const struct colour_setting *setting, int preserve)
{
struct drm_crtc_state *crtcs = state->crtcs;
uint32_t last_gamma_size = 0;
@@ -292,13 +283,4 @@ drm_set_temperature(
}
-const struct gamma_method drm_gamma_method = {
- "drm", 0,
- &drm_init,
- &drm_start,
- &drm_free,
- &drm_print_help,
- &drm_set_option,
- &drm_restore,
- &drm_set_temperature
-};
+const struct gamma_method drm_gamma_method = GAMMA_METHOD_INIT("drm", 0, drm);
diff --git a/src/gamma-dummy.c b/src/gamma-dummy.c
index abb5d22..1751bbd 100644
--- a/src/gamma-dummy.c
+++ b/src/gamma-dummy.c
@@ -20,42 +20,41 @@
static int
-gamma_dummy_init(struct gamma_state **state)
+dummy_create(struct gamma_state **state_out)
{
- *state = NULL;
+ *state_out = NULL;
return 0;
}
static int
-gamma_dummy_start(struct gamma_state *state, enum program_mode mode)
+dummy_start(struct gamma_state *state)
{
(void) state;
- (void) mode;
weprintf(_("WARNING: Using dummy gamma method! Display will not be affected by this gamma method.\n"));
return 0;
}
static void
-gamma_dummy_restore(struct gamma_state *state)
+dummy_restore(struct gamma_state *state)
{
(void) state;
}
static void
-gamma_dummy_free(struct gamma_state *state)
+dummy_free(struct gamma_state *state)
{
(void) state;
}
static void
-gamma_dummy_print_help(FILE *f)
+dummy_print_help(FILE *f)
{
fputs(_("Does not affect the display but prints the color temperature to the terminal.\n"), f);
fputs("\n", f);
}
static int
-gamma_dummy_set_option(struct gamma_state *state, const char *key, const char *value)
+dummy_set_option(struct gamma_state *state, const char *key, const char *value)
{
(void) state;
(void) value;
@@ -64,8 +63,7 @@ gamma_dummy_set_option(struct gamma_state *state, const char *key, const char *v
}
static int
-gamma_dummy_set_temperature(
- struct gamma_state *state, const struct colour_setting *setting, int preserve)
+dummy_apply(struct gamma_state *state, const struct colour_setting *setting, int preserve)
{
(void) state;
(void) preserve;
@@ -74,13 +72,4 @@ gamma_dummy_set_temperature(
}
-const struct gamma_method dummy_gamma_method = {
- "dummy", 0,
- &gamma_dummy_init,
- &gamma_dummy_start,
- &gamma_dummy_free,
- &gamma_dummy_print_help,
- &gamma_dummy_set_option,
- &gamma_dummy_restore,
- &gamma_dummy_set_temperature
-};
+const struct gamma_method dummy_gamma_method = GAMMA_METHOD_INIT("dummy", 0, dummy);
diff --git a/src/gamma-quartz.c b/src/gamma-quartz.c
index c708105..d323d33 100644
--- a/src/gamma-quartz.c
+++ b/src/gamma-quartz.c
@@ -34,15 +34,15 @@ struct gamma_state {
static int
-quartz_init(struct gamma_state **state)
+quartz_create(struct gamma_state **state_out)
{
- *state = emalloc(sizeof(**state));
- (*state)->displays = NULL;
+ *state_out = emalloc(sizeof(**state_out));
+ (*state_out)->displays = NULL;
return 0;
}
static int
-quartz_start(struct gamma_state *state, program_mode_t mode)
+quartz_start(struct gamma_state *state)
{
float *gamma_r, *gamma_g, *gamma_b;
uint32_t i, display_count, ramp_size, sample_count;
@@ -144,8 +144,7 @@ quartz_set_option(struct gamma_state *state, const char *key, const char *value)
}
static void
-quartz_set_temperature_for_display(struct gamma_state *state, int display_index,
- const colour_setting_t *setting, int preserve)
+quartz_apply_for_display(struct gamma_state *state, int display_index, const colour_setting_t *setting, int preserve)
{
float *gamma_ramps, *gamma_r, *gamma_g, *gamma_b, value;
CGDirectDisplayID display = state->displays[display_index].display;
@@ -185,25 +184,15 @@ quartz_set_temperature_for_display(struct gamma_state *state, int display_index,
}
static int
-quartz_set_temperature(
- struct gamma_state *state, const colour_setting_t *setting, int preserve)
+quartz_apply(struct gamma_state *state, const colour_setting_t *setting, int preserve)
{
uint32_t i;
for (i = 0; i < state->display_count; i++)
- quartz_set_temperature_for_display(state, i, setting, preserve);
+ quartz_apply_for_display(state, i, setting, preserve);
return 0;
}
-const struct gamma_method quartz_gamma_method = {
- "quartz", 1,
- &quartz_init,
- &quartz_start,
- &quartz_free,
- &quartz_print_help,
- &quartz_set_option,
- &quartz_restore,
- &quartz_set_temperature
-};
+const struct gamma_method quartz_gamma_method = GAMMA_METHOD_INIT("quartz", 1, quartz);
diff --git a/src/gamma-randr.c b/src/gamma-randr.c
index 6e5f154..561a243 100644
--- a/src/gamma-randr.c
+++ b/src/gamma-randr.c
@@ -48,58 +48,57 @@ struct gamma_state {
static int
-randr_init(struct gamma_state **state)
+randr_create(struct gamma_state **state_out)
{
xcb_randr_query_version_cookie_t ver_cookie;
xcb_randr_query_version_reply_t *ver_reply;
xcb_generic_error_t *error;
- struct gamma_state *s;
+ struct gamma_state *state;
int ec;
- /* Initialize state. */
- *state = emalloc(sizeof(**state));
-
- s = *state;
- s->screen_num = -1;
- s->crtc_num = NULL;
-
- s->crtc_num_count = 0;
- s->crtc_count = 0;
- s->crtcs = NULL;
+ /* Initialize state */
+ state = *state_out = emalloc(sizeof(**state_out));
+ state->screen_num = -1;
+ state->crtc_num = NULL;
+ state->crtc_num_count = 0;
+ state->crtc_count = 0;
+ state->crtcs = NULL;
/* Open X server connection */
- s->conn = xcb_connect(NULL, &s->preferred_screen);
+ state->conn = xcb_connect(NULL, &state->preferred_screen);
/* Query RandR version */
- ver_cookie = xcb_randr_query_version(s->conn, RANDR_VERSION_MAJOR, RANDR_VERSION_MINOR);
- ver_reply = xcb_randr_query_version_reply(s->conn, ver_cookie, &error);
+ ver_cookie = xcb_randr_query_version(state->conn, RANDR_VERSION_MAJOR, RANDR_VERSION_MINOR);
+ ver_reply = xcb_randr_query_version_reply(state->conn, ver_cookie, &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) {
ec = (error != 0) ? error->error_code : -1;
weprintf(_("`%s' returned error %i."), "RANDR Query Version", ec);
- xcb_disconnect(s->conn);
- free(s);
- return -1;
+ goto fail;
}
if (ver_reply->major_version != RANDR_VERSION_MAJOR ||
ver_reply->minor_version < RANDR_VERSION_MINOR) {
weprintf(_("Unsupported RANDR version (%u.%u)."), ver_reply->major_version, ver_reply->minor_version);
free(ver_reply);
- xcb_disconnect(s->conn);
- free(s);
- return -1;
+ goto fail;
}
free(ver_reply);
return 0;
+
+fail:
+ xcb_disconnect(state->conn);
+ free(state);
+ *state_out = NULL;
+ return -1;
}
static int
-randr_start(struct gamma_state *state, enum program_mode mode)
+randr_start(struct gamma_state *state)
{
xcb_generic_error_t *error;
const xcb_setup_t *setup;
@@ -109,8 +108,6 @@ randr_start(struct gamma_state *state, enum program_mode mode)
xcb_randr_get_screen_resources_current_reply_t *res_reply;
xcb_randr_crtc_t *crtcs;
- (void) mode;
-
screen_num = state->screen_num;
if (screen_num < 0)
screen_num = state->preferred_screen;
@@ -326,8 +323,7 @@ randr_set_option(struct gamma_state *state, const char *key, const char *value)
}
static int
-randr_set_temperature_for_crtc(struct gamma_state *state, int crtc_num,
- const struct colour_setting *setting, int preserve)
+randr_apply_for_crtc(struct gamma_state *state, int crtc_num, const struct colour_setting *setting, int preserve)
{
xcb_randr_crtc_t crtc;
xcb_void_cookie_t gamma_set_cookie;
@@ -386,18 +382,18 @@ randr_set_temperature_for_crtc(struct gamma_state *state, int crtc_num,
}
static int
-randr_set_temperature(struct gamma_state *state, const struct colour_setting *setting, int preserve)
+randr_apply(struct gamma_state *state, const struct colour_setting *setting, int preserve)
{
int i;
/* If no CRTC numbers have been specified, set temperature on all CRTCs. */
if (!state->crtc_num_count) {
for (i = 0; i < state->crtc_count; i++)
- if (randr_set_temperature_for_crtc(state, i, setting, preserve) < 0)
+ if (randr_apply_for_crtc(state, i, setting, preserve) < 0)
return -1;
} else {
for (i = 0; i < state->crtc_num_count; ++i)
- if (randr_set_temperature_for_crtc(state, state->crtc_num[i], setting, preserve) < 0)
+ if (randr_apply_for_crtc(state, state->crtc_num[i], setting, preserve) < 0)
return -1;
}
@@ -405,13 +401,4 @@ randr_set_temperature(struct gamma_state *state, const struct colour_setting *se
}
-const struct gamma_method randr_gamma_method = {
- "randr", 1,
- &randr_init,
- &randr_start,
- &randr_free,
- &randr_print_help,
- &randr_set_option,
- &randr_restore,
- &randr_set_temperature
-};
+const struct gamma_method randr_gamma_method = GAMMA_METHOD_INIT("randr", 1, randr);
diff --git a/src/gamma-vidmode.c b/src/gamma-vidmode.c
index 042f90c..a855914 100644
--- a/src/gamma-vidmode.c
+++ b/src/gamma-vidmode.c
@@ -31,18 +31,16 @@ struct gamma_state {
static int
-vidmode_init(struct gamma_state **state)
+vidmode_create(struct gamma_state **state_out)
{
- struct gamma_state *s;
+ struct gamma_state *state;
- s = *state = emalloc(sizeof(struct gamma_state));
+ state = *state_out = emalloc(sizeof(**state_out));
+ state->screen_num = -1;
+ state->saved_ramps = NULL;
- s->screen_num = -1;
- s->saved_ramps = NULL;
-
- /* Open display */
- s->display = XOpenDisplay(NULL);
- if (!s->display) {
+ state->display = XOpenDisplay(NULL);
+ if (!state->display) {
weprintf(_("X request failed: %s"), "XOpenDisplay");
return -1;
}
@@ -51,15 +49,13 @@ vidmode_init(struct gamma_state **state)
}
static int
-vidmode_start(struct gamma_state *state, enum program_mode mode)
+vidmode_start(struct gamma_state *state)
{
int r;
int screen_num = state->screen_num;
int major, minor;
uint16_t *gamma_r, *gamma_g, *gamma_b;
- (void) mode;
-
if (screen_num < 0)
screen_num = DefaultScreen(state->display);
state->screen_num = screen_num;
@@ -151,8 +147,7 @@ vidmode_restore(struct gamma_state *state)
}
static int
-vidmode_set_temperature(
- struct gamma_state *state, const struct colour_setting *setting, int preserve)
+vidmode_apply(struct gamma_state *state, const struct colour_setting *setting, int preserve)
{
uint16_t value, *gamma_ramps, *gamma_r, *gamma_g, *gamma_b;
int r, i;
@@ -194,13 +189,4 @@ vidmode_set_temperature(
}
-const struct gamma_method vidmode_gamma_method = {
- "vidmode", 1,
- &vidmode_init,
- &vidmode_start,
- &vidmode_free,
- &vidmode_print_help,
- &vidmode_set_option,
- &vidmode_restore,
- &vidmode_set_temperature
-};
+const struct gamma_method vidmode_gamma_method = GAMMA_METHOD_INIT("vidmode", 1, vidmode);
diff --git a/src/gamma-w32gdi.c b/src/gamma-w32gdi.c
index e216a23..533365d 100644
--- a/src/gamma-w32gdi.c
+++ b/src/gamma-w32gdi.c
@@ -33,15 +33,15 @@ struct gamma_state {
static int
-w32gdi_init(struct gamma_state **state)
+w32gdi_create(struct gamma_state **state_out)
{
- *state = emalloc(sizeof(**state));
- (*state)->saved_ramps = NULL;
+ *state_out = emalloc(sizeof(**state_out));
+ (*state_out)->saved_ramps = NULL;
return 0;
}
static int
-w32gdi_start(struct gamma_state *state, program_mode_t mode)
+w32gdi_start(struct gamma_state *state)
{
HDC hDC;
int cmcap;
@@ -133,8 +133,7 @@ done:
}
static int
-w32gdi_set_temperature(
- struct gamma_state *state, const colour_setting_t *setting, int preserve)
+w32gdi_apply(struct gamma_state *state, const colour_setting_t *setting, int preserve)
{
WORD *gamma_ramps, *gamma_r, *gamma_b, *gamma_g, value;
HDC hDC;
@@ -192,13 +191,4 @@ done:
}
-const struct gamma_method w32gdi_gamma_method = {
- "wingdi", 1,
- &w32gdi_init,
- &w32gdi_start,
- &w32gdi_free,
- &w32gdi_print_help,
- &w32gdi_set_option,
- &w32gdi_restore,
- &w32gdi_set_temperature
-};
+const struct gamma_method w32gdi_gamma_method = GAMMA_METHOD_INIT("winfdi", 1, w32gdi);
diff --git a/src/gamma.c b/src/gamma.c
index 508374b..628105b 100644
--- a/src/gamma.c
+++ b/src/gamma.c
@@ -44,26 +44,25 @@ const struct gamma_method *gamma_methods[] = {
static int
-try_start(const struct gamma_method *method, GAMMA_STATE **state,
- enum program_mode mode, struct config_ini_state *config, char *args)
+try_start(const struct gamma_method *method, GAMMA_STATE **state_out, struct config_ini_state *config, char *args)
{
struct config_ini_section *section;
struct config_ini_setting *setting;
char *next_arg, *value;
const char *key;
- if (method->init(state) < 0) {
+ if (method->create(state_out) < 0) {
weprintf(_("Initialization of %s failed."), method->name);
- return -1;
+ goto fail;
}
- /* Set method options from config file. */
+ /* Set method options from config file */
if ((section = config_ini_get_section(config, method->name)))
for (setting = section->settings; setting; setting = setting->next)
- if (method->set_option(*state, setting->name, setting->value) < 0)
+ if (method->set_option(*state_out, setting->name, setting->value) < 0)
goto set_option_fail;
- /* Set method options from command line. */
+ /* Set method options from command line */
while (args) {
next_arg = strchr(args, ':');
if (next_arg)
@@ -73,30 +72,33 @@ try_start(const struct gamma_method *method, GAMMA_STATE **state,
value = strchr(args, '=');
if (!value) {
weprintf(_("Failed to parse option `%s'."), args);
- return -1;
+ goto fail;
}
*value++ = '\0';
- if (method->set_option(*state, key, value) < 0)
+ if (method->set_option(*state_out, key, value) < 0)
goto set_option_fail;
args = next_arg;
}
- /* Start method. */
- if (method->start(*state, mode) < 0) {
- method->free(*state);
+ /* Start method */
+ if (method->start(*state_out) < 0) {
weprintf(_("Failed to start adjustment method %s."), method->name);
- return -1;
+ goto fail;
}
return 0;
set_option_fail:
- method->free(*state);
weprintf(_("Failed to set %s option."), method->name);
/* TRANSLATORS: `help' must not be translated. */
weprintf(_("Try `-m %s:help' for more information."), method->name);
+fail:
+ if (*state_out) {
+ method->free(*state_out);
+ *state_out = NULL;
+ }
return -1;
}
@@ -107,27 +109,27 @@ acquire_adjustment_method(struct settings *settings, GAMMA_STATE **method_state_
size_t i;
if (settings->method) {
- /* Use method specified on command line. */
- if (try_start(settings->method, method_state_out, settings->mode, &settings->config, settings->method_args) < 0)
+ /* Use method specified on command line */
+ if (try_start(settings->method, method_state_out, &settings->config, settings->method_args) < 0)
exit(1);
} else {
- /* Try all methods, use the first that works. */
+ /* Try all methods, use the first that works */
for (i = 0; gamma_methods[i]; i++) {
if (!gamma_methods[i]->autostart)
continue;
- if (try_start(gamma_methods[i], method_state_out, settings->mode, &settings->config, NULL) < 0) {
+ if (try_start(gamma_methods[i], method_state_out, &settings->config, NULL) < 0) {
weprintf(_("Trying next method..."));
continue;
}
- /* Found method that works. */
+ /* Found method that works */
printf(_("Using method `%s'.\n"), gamma_methods[i]->name);
settings->method = gamma_methods[i];
break;
}
- /* Failure if no methods were successful at this point. */
+ /* Failure if no methods were successful at this point */
if (!settings->method)
eprintf(_("No more methods to try."));
}
diff --git a/src/location-corelocation.m b/src/location-corelocation.m
index 435697d..9f45899 100644
--- a/src/location-corelocation.m
+++ b/src/location-corelocation.m
@@ -22,14 +22,18 @@
#import <CoreLocation/CoreLocation.h>
+struct location_data {
+ struct location location;
+ int available;
+ int error;
+};
+
struct location_state {
NSThread *thread;
- NSLock *lock;
int pipe_fd_read;
int pipe_fd_write;
- int available;
- int error;
- struct location location;
+ struct location_data data;
+ struct location_data saved_data;
};
@@ -38,6 +42,14 @@ struct location_state {
@property (nonatomic) struct location_state *state;
@end
+
+static void
+send_data(struct location_state *state)
+{
+ while (write(state->pipe_fd_write, &state->data, sizeof(state->data)) == -1 && errno == EINTR);
+}
+
+
@implementation LocationDelegate;
- (void)start
@@ -62,20 +74,14 @@ struct location_state {
- (void)markError
{
- [self.state->lock lock];
- self.state->error = 1;
- [self.state->lock unlock];
-
- write(self.state->pipe_fd_write, "", 1);
+ self.state->data.error = 1;
+ send_data(self.state);
}
- (void)markUnavailable
{
- [self.state->lock lock];
- self.state->available = 0;
- [self.state->lock unlock];
-
- write(self.state->pipe_fd_write, "", 1);
+ self.state->data.available = 0;
+ send_data(self.state);
}
- (void)locationManager:(CLLocationManager *)manager
@@ -83,15 +89,10 @@ struct location_state {
{
CLLocation *newLocation = [locations firstObject];
- [self.state->lock lock];
-
- self.state->location.lat = newLocation.coordinate.latitude;
- self.state->location.lon = newLocation.coordinate.longitude;
- self.state->available = 1;
-
- [self.state->lock unlock];
-
- write(self.state->pipe_fd_write, "", 1);
+ self.state->data.location.lat = newLocation.coordinate.latitude;
+ self.state->data.location.lon = newLocation.coordinate.longitude;
+ self.state->data.available = 1;
+ send_data(self.state);
}
- (void)locationManager:(CLLocationManager *)manager
@@ -170,14 +171,14 @@ pipe_close_callback(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void
static int
-location_corelocation_init(struct location_state **state)
+corelocation_create(struct location_state **state_out)
{
- *state = emalloc(sizeof(**state));
+ *state_out = emalloc(sizeof(**state_out));
return 0;
}
static int
-location_corelocation_start(struct location_state *state)
+corelocation_start(struct location_state *state)
{
LocationThread *thread;
int pipefds[2];
@@ -185,12 +186,13 @@ location_corelocation_start(struct location_state *state)
state->pipe_fd_read = -1;
state->pipe_fd_write = -1;
- state->available = 0;
- state->error = 0;
- state->location.lat = 0;
- state->location.lon = 0;
+ state->data.available = 0;
+ state->data.error = 0;
+ state->data.location.lat = 0;
+ state->data.location.lon = 0;
+ state->saved_data = state->data;
- if (pipe_nonblock(pipefds)) {
+ if (pipe_rdnonblock(pipefds)) {
weprintf(_("Failed to start CoreLocation provider!"));
return -1;
}
@@ -198,9 +200,7 @@ location_corelocation_start(struct location_state *state)
state->pipe_fd_read = pipefds[0];
state->pipe_fd_write = pipefds[1];
- write(state->pipe_fd_write, "", 1);
-
- state->lock = [[NSLock alloc] init];
+ send_data(state); /* TODO why? */
thread = [[LocationThread alloc] init];
thread.state = state;
@@ -211,7 +211,7 @@ location_corelocation_start(struct location_state *state)
}
static void
-location_corelocation_free(struct location_state *state)
+corelocation_free(struct location_state *state)
{
if (state->pipe_fd_read >= 0)
close(state->pipe_fd_read);
@@ -219,49 +219,53 @@ location_corelocation_free(struct location_state *state)
}
static void
-location_corelocation_print_help(FILE *f)
+corelocation_print_help(FILE *f)
{
fputs(_("Use the location as discovered by the Corelocation provider.\n"), f);
fputs("\n", f);
}
static int
-location_corelocation_set_option(struct location_state *state, const char *key, const char *value)
+corelocation_set_option(struct location_state *state, const char *key, const char *value)
{
+ (void) state;
+ (void) value;
weprintf(_("Unknown method parameter: `%s'."), key);
return -1;
}
static int
-location_corelocation_get_fd(struct location_state *state)
+corelocation_get_fd(struct location_state *state)
{
return state->pipe_fd_read;
}
static int
-location_corelocation_handle(struct location_state *state, location_t *location, int *available)
+corelocation_fetch(struct location_state *state, struct location *location_out, int *available_out)
{
- int error;
-
- read(state->pipe_fd_read, &(char){0}, 1);
-
- [state->lock lock];
- error = state->error;
- *location->lat = state->location;
- *available = state->available;
- [state->lock unlock];
+ struct location_data data;
+ ssize_t r;
+
+ for (;;) {
+ r = read(state->pipe_fd_read, &data, sizeof(data));
+ if (r == (ssize_t)sizeof(data)) {
+ state->saved_data = data;
+ } else if (r > 0) {
+ /* writes of 512 bytes or less are always atomic on pipes */
+ weprintf("read <pipe>: %s", _("Unexpected message size"));
+ } else if (!r || errno == EAGAIN) {
+ break;
+ } else if (errno != EINTR) {
+ weprintf("read <pipe>:");
+ state->saved_data.error = 1;
+ break;
+ }
+ }
- return error ? -1 : 0;
+ *location_out = state->saved_data.location;
+ *available_out = state->saved_data.available;
+ return state->saved_data.error ? -1 : 0;
}
-const location_provider_t corelocation_location_provider = {
- "corelocation",
- &location_corelocation_init,
- &location_corelocation_start,
- &location_corelocation_free,
- &location_corelocation_print_help,
- &location_corelocation_set_option,
- &location_corelocation_get_fd,
- &location_corelocation_handle
-};
+const location_provider_t corelocation_location_provider = LOCATION_PROVIDER_INIT("corelocation", corelocation);
diff --git a/src/location-geoclue2.c b/src/location-geoclue2.c
index b6238df..84ef6b4 100644
--- a/src/location-geoclue2.c
+++ b/src/location-geoclue2.c
@@ -36,19 +36,23 @@
#define DBUS_ACCESS_ERROR "org.freedesktop.DBus.Error.AccessDenied"
+struct location_data {
+ struct location location;
+ int available;
+ int error;
+};
+
struct location_state {
GMainLoop *loop;
GThread *thread;
- GMutex lock;
int pipe_fd_read;
int pipe_fd_write;
- int available;
- int error;
- struct location location;
+ struct location_data data;
+ struct location_data saved_data;
};
-/* Print the message explaining denial from GeoClue. */
+/* Print the message explaining denial from GeoClue */
static void
print_denial_message(void)
{
@@ -60,15 +64,18 @@ print_denial_message(void)
"information.\n"));
}
-/* Indicate an unrecoverable error during GeoClue2 communication. */
static void
-mark_error(struct location_state *state)
+send_data(struct location_state *state)
{
- g_mutex_lock(&state->lock);
- state->error = 1;
- g_mutex_unlock(&state->lock);
+ while (write(state->pipe_fd_write, &state->data, sizeof(state->data)) == -1 && errno == EINTR);
+}
- write(state->pipe_fd_write, "", 1);
+/* Indicate an unrecoverable error during GeoClue2 communication */
+static void
+mark_error(struct location_state *state)
+{
+ state->data.error = 1;
+ send_data(state);
}
/* Handle position change callbacks */
@@ -102,26 +109,19 @@ geoclue_client_signal_cb(GDBusProxy *client, gchar *sender_name, gchar *signal_n
return;
}
- g_mutex_lock(&state->lock);
-
/* Read location properties */
lat_v = g_dbus_proxy_get_cached_property(location, "Latitude");
- state->location.latitude = g_variant_get_double(lat_v);
-
+ state->data.location.latitude = g_variant_get_double(lat_v);
lon_v = g_dbus_proxy_get_cached_property(location, "Longitude");
- state->location.longitude = g_variant_get_double(lon_v);
+ state->data.location.longitude = g_variant_get_double(lon_v);
+ state->data.available = 1;
- state->available = 1;
-
- g_mutex_unlock(&state->lock);
-
- write(state->pipe_fd_write, "", 1);
+ send_data(state);
}
/* Callback when GeoClue name appears on the bus */
static void
-on_name_appeared(GDBusConnection *conn, const gchar *name,
- const gchar *name_owner, gpointer user_data)
+on_name_appeared(GDBusConnection *conn, const gchar *name, const gchar *name_owner, gpointer user_data)
{
struct location_state *state = user_data;
const gchar *client_path;
@@ -239,14 +239,11 @@ on_name_vanished(GDBusConnection *connection, const gchar *name, gpointer user_d
(void) connection;
(void) name;
- g_mutex_lock(&state->lock);
- state->available = 0;
- g_mutex_unlock(&state->lock);
-
- write(state->pipe_fd_write, "", 1);
+ state->data.available = 0;
+ send_data(state);
}
-/* Callback when the pipe to the main thread is closed. */
+/* Callback when the pipe to the main thread is closed */
static gboolean
on_pipe_closed(GIOChannel *channel, GIOCondition condition, gpointer user_data)
{
@@ -259,7 +256,7 @@ on_pipe_closed(GIOChannel *channel, GIOCondition condition, gpointer user_data)
}
-/* Run loop for location provider thread. */
+/* Run loop for location provider thread */
static void *
run_geoclue2_loop(void *state_)
{
@@ -298,29 +295,30 @@ run_geoclue2_loop(void *state_)
}
static int
-location_geoclue2_init(struct location_state **state)
+geoclue2_create(struct location_state **state_out)
{
#if !GLIB_CHECK_VERSION(2, 35, 0)
g_type_init();
#endif
- *state = emalloc(sizeof(**state));
+ *state_out = emalloc(sizeof(**state_out));
return 0;
}
static int
-location_geoclue2_start(struct location_state *state)
+geoclue2_start(struct location_state *state)
{
int pipefds[2];
state->pipe_fd_read = -1;
state->pipe_fd_write = -1;
- state->available = 0;
- state->error = 0;
- state->location.latitude = 0;
- state->location.longitude = 0;
+ state->data.available = 0;
+ state->data.error = 0;
+ state->data.location.latitude = 0;
+ state->data.location.longitude = 0;
+ state->saved_data = state->data;
- if (pipe_nonblock(pipefds)) {
+ if (pipe_rdnonblock(pipefds)) {
weprintf(_("Failed to start GeoClue2 provider!"));
return -1;
}
@@ -328,37 +326,35 @@ location_geoclue2_start(struct location_state *state)
state->pipe_fd_read = pipefds[0];
state->pipe_fd_write = pipefds[1];
- write(state->pipe_fd_write, "", 1);
+ send_data(state); /* TODO why? */
- g_mutex_init(&state->lock);
state->thread = g_thread_new("geoclue2", run_geoclue2_loop, state);
return 0;
}
static void
-location_geoclue2_free(struct location_state *state)
+geoclue2_free(struct location_state *state)
{
- if (state->pipe_fd_read != -1)
+ if (state->pipe_fd_read >= 0)
close(state->pipe_fd_read);
- /* Closing the pipe should cause the thread to exit. */
+ /* Closing the pipe should cause the thread to exit */
g_thread_join(state->thread);
state->thread = NULL;
- g_mutex_clear(&state->lock);
free(state);
}
static void
-location_geoclue2_print_help(FILE *f)
+geoclue2_print_help(FILE *f)
{
fputs(_("Use the location as discovered by a GeoClue2 provider.\n"), f);
fputs("\n", f);
}
static int
-location_geoclue2_set_option(struct location_state *state, const char *key, const char *value)
+geoclue2_set_option(struct location_state *state, const char *key, const char *value)
{
(void) state;
(void) value;
@@ -367,35 +363,37 @@ location_geoclue2_set_option(struct location_state *state, const char *key, cons
}
static int
-location_geoclue2_get_fd(struct location_state *state)
+geoclue2_get_fd(struct location_state *state)
{
return state->pipe_fd_read;
}
static int
-location_geoclue2_handle(struct location_state *state, struct location *location, int *available)
+geoclue2_fetch(struct location_state *state, struct location *location_out, int *available_out)
{
- int error;
-
- read(state->pipe_fd_read, &(char){0}, 1);
-
- g_mutex_lock(&state->lock);
- error = state->error;
- *location = state->location;
- *available = state->available;
- g_mutex_unlock(&state->lock);
+ struct location_data data;
+ ssize_t r;
+
+ for (;;) {
+ r = read(state->pipe_fd_read, &data, sizeof(data));
+ if (r == (ssize_t)sizeof(data)) {
+ state->saved_data = data;
+ } else if (r > 0) {
+ /* writes of 512 bytes or less are always atomic on pipes */
+ weprintf("read <pipe>: %s", _("Unexpected message size"));
+ } else if (!r || errno == EAGAIN) {
+ break;
+ } else if (errno != EINTR) {
+ weprintf("read <pipe>:");
+ state->saved_data.error = 1;
+ break;
+ }
+ }
- return error ? -1 : 0;
+ *location_out = state->saved_data.location;
+ *available_out = state->saved_data.available;
+ return state->saved_data.error ? -1 : 0;
}
-const struct location_provider geoclue2_location_provider = {
- "geoclue2",
- &location_geoclue2_init,
- &location_geoclue2_start,
- &location_geoclue2_free,
- &location_geoclue2_print_help,
- &location_geoclue2_set_option,
- &location_geoclue2_get_fd,
- &location_geoclue2_handle
-};
+const struct location_provider geoclue2_location_provider = LOCATION_PROVIDER_INIT("geoclue2", geoclue2);
diff --git a/src/location-manual.c b/src/location-manual.c
index 8df1874..a394f29 100644
--- a/src/location-manual.c
+++ b/src/location-manual.c
@@ -25,17 +25,17 @@ struct location_state {
static int
-location_manual_init(struct location_state **state)
+manual_create(struct location_state **state_out)
{
- *state = emalloc(sizeof(**state));
- (*state)->loc.latitude = NAN;
- (*state)->loc.longitude = NAN;
+ *state_out = emalloc(sizeof(**state_out));
+ (*state_out)->loc.latitude = NAN;
+ (*state_out)->loc.longitude = NAN;
return 0;
}
GCC_ONLY(__attribute__((__pure__)))
static int
-location_manual_start(struct location_state *state)
+manual_start(struct location_state *state)
{
if (isnan(state->loc.latitude) || isnan(state->loc.longitude))
eprintf(_("Latitude and longitude must be set."));
@@ -43,13 +43,13 @@ location_manual_start(struct location_state *state)
}
static void
-location_manual_free(struct location_state *state)
+manual_free(struct location_state *state)
{
free(state);
}
static void
-location_manual_print_help(FILE *f)
+manual_print_help(FILE *f)
{
fputs(_("Specify location manually.\n"), f);
fputs("\n", f);
@@ -65,7 +65,7 @@ location_manual_print_help(FILE *f)
}
static int
-location_manual_set_option(struct location_state *state, const char *key, const char *value)
+manual_set_option(struct location_state *state, const char *key, const char *value)
{
/* Parse float value */
char *end;
@@ -91,28 +91,19 @@ location_manual_set_option(struct location_state *state, const char *key, const
}
static int
-location_manual_get_fd(struct location_state *state)
+manual_get_fd(struct location_state *state)
{
(void) state;
return -1;
}
static int
-location_manual_handle(struct location_state *state, struct location *location, int *available)
+manual_fetch(struct location_state *state, struct location *location_out, int *available_out)
{
- *location = state->loc;
- *available = 1;
+ *location_out = state->loc;
+ *available_out = 1;
return 0;
}
-const struct location_provider manual_location_provider = {
- "manual",
- &location_manual_init,
- &location_manual_start,
- &location_manual_free,
- &location_manual_print_help,
- &location_manual_set_option,
- &location_manual_get_fd,
- &location_manual_handle
-};
+const struct location_provider manual_location_provider = LOCATION_PROVIDER_INIT("manual", manual);
diff --git a/src/location.c b/src/location.c
index 216b7a9..60a1ca0 100644
--- a/src/location.c
+++ b/src/location.c
@@ -31,9 +31,8 @@ const struct location_provider *location_providers[] = {
};
-
static int
-try_start(const struct location_provider *provider, LOCATION_STATE **state, struct config_ini_state *config, char *args)
+try_start(const struct location_provider *provider, LOCATION_STATE **state_out, struct config_ini_state *config, char *args)
{
const char *manual_keys[] = {"lat", "lon"};
struct config_ini_section *section;
@@ -42,18 +41,18 @@ try_start(const struct location_provider *provider, LOCATION_STATE **state, stru
const char *key;
int i;
- if (provider->init(state) < 0) {
+ if (provider->create(state_out) < 0) {
weprintf(_("Initialization of %s failed."), provider->name);
- return -1;
+ goto fail;
}
- /* Set provider options from config file. */
+ /* Set provider options from config file */
if ((section = config_ini_get_section(config, provider->name)))
for (setting = section->settings; setting; setting = setting->next)
- if (provider->set_option(*state, setting->name, setting->value) < 0)
+ if (provider->set_option(*state_out, setting->name, setting->value) < 0)
goto set_option_fail;
- /* Set provider options from command line. */
+ /* Set provider options from command line */
for (i = 0; args; i++) {
next_arg = strchr(args, ':');
if (next_arg)
@@ -63,40 +62,43 @@ try_start(const struct location_provider *provider, LOCATION_STATE **state, stru
value = strchr(args, '=');
if (!value) {
/* The options for the "manual" method can be set
- without keys on the command line for convencience
- and for backwards compatability. We add the proper
- keys here before calling set_option(). */
+ * without keys on the command line for convencience
+ * and for backwards compatability. We add the proper
+ * keys here before calling set_option(). */
if (!strcmp(provider->name, "manual") && i < ELEMSOF(manual_keys)) {
key = manual_keys[i];
value = args;
} else {
weprintf(_("Failed to parse option `%s'."), args);
- return -1;
+ goto fail;
}
} else {
*value++ = '\0';
}
- if (provider->set_option(*state, key, value) < 0)
+ if (provider->set_option(*state_out, key, value) < 0)
goto set_option_fail;
args = next_arg;
}
- /* Start provider. */
- if (provider->start(*state) < 0) {
- provider->free(*state);
+ /* Start provider */
+ if (provider->start(*state_out) < 0) {
weprintf(_("Failed to start provider %s."), provider->name);
- return -1;
+ goto fail;
}
return 0;
set_option_fail:
- provider->free(*state);
weprintf(_("Failed to set %s option."), provider->name);
/* TRANSLATORS: `help' must not be translated. */
weprintf(_("Try `-l %s:help' for more information."), provider->name);
+fail:
+ if (*state_out) {
+ provider->free(*state_out);
+ *state_out = NULL;
+ }
return -1;
}
@@ -130,7 +132,7 @@ get_location(const struct location_provider *provider, LOCATION_STATE *state, in
do {
pollfds[0].fd = provider->get_fd(state);
if (pollfds[0].fd >= 0) {
- /* Poll on file descriptor until ready. */
+ /* Poll on file descriptor until ready */
pollfds[0].events = POLLIN;
timeout = (int)MAX(end - now, 0);
r = poll(pollfds, 1, timeout);
@@ -148,7 +150,7 @@ get_location(const struct location_provider *provider, LOCATION_STATE *state, in
}
}
- if (provider->handle(state, loc, &available) < 0)
+ if (provider->fetch(state, loc, &available) < 0)
return -1;
} while (!available);
@@ -162,11 +164,11 @@ acquire_location_provider(struct settings *settings, LOCATION_STATE **location_s
size_t i;
if (settings->provider) {
- /* Use provider specified on command line. */
+ /* Use provider specified on command line */
if (try_start(settings->provider, location_state_out, &settings->config, settings->provider_args) < 0)
exit(1);
} else {
- /* Try all providers, use the first that works. */
+ /* Try all providers, use the first that works */
for (i = 0; location_providers[i]; i++) {
weprintf(_("Trying location provider `%s'..."), location_providers[i]->name);
if (try_start(location_providers[i], location_state_out, &settings->config, NULL) < 0) {
@@ -174,14 +176,52 @@ acquire_location_provider(struct settings *settings, LOCATION_STATE **location_s
continue;
}
- /* Found provider that works. */
+ /* Found provider that works */
printf(_("Using provider `%s'.\n"), location_providers[i]->name);
settings->provider = location_providers[i];
break;
}
- /* Failure if no providers were successful at this point. */
+ /* Failure if no providers were successful at this point */
if (!settings->provider)
eprintf(_("No more location providers to try."));
}
}
+
+
+int
+location_is_valid(const struct location *location)
+{
+ if (!WITHIN(MIN_LATITUDE, location->latitude, MAX_LATITUDE)) {
+ /* TRANSLATORS: Append degree symbols if possible. */
+ weprintf(_("Latitude must be between %.1f and %.1f."), MIN_LATITUDE, MAX_LATITUDE);
+ return 0;
+ }
+ if (!WITHIN(MIN_LONGITUDE, location->longitude, MAX_LONGITUDE)) {
+ /* TRANSLATORS: Append degree symbols if possible. */
+ weprintf(_("Longitude must be between %.1f and %.1f."), MIN_LONGITUDE, MAX_LONGITUDE);
+ return 0;
+ }
+ return 1;
+}
+
+
+void
+print_location(const struct location *location)
+{
+ /* TRANSLATORS: Abbreviation for `north' */
+ const char *north = _("N");
+ /* TRANSLATORS: Abbreviation for `south' */
+ const char *south = _("S");
+ /* TRANSLATORS: Abbreviation for `east' */
+ const char *east = _("E");
+ /* TRANSLATORS: Abbreviation for `west' */
+ const char *west = _("W");
+
+ /* TRANSLATORS: Append degree symbols after %f if possible.
+ * The string following each number is an abreviation for
+ * north, source, east or west (N, S, E, W). */
+ printf(_("Location: %.2f %s, %.2f %s\n"),
+ fabs(location->latitude), signbit(location->latitude) ? south : north,
+ fabs(location->longitude), signbit(location->longitude) ? west : east);
+}
diff --git a/src/redshift.c b/src/redshift.c
index 9a44b0b..04c6c77 100644
--- a/src/redshift.c
+++ b/src/redshift.c
@@ -24,7 +24,7 @@
#ifndef WINDOWS
# include <poll.h>
#else
-#define POLLIN 0
+# define POLLIN 0
struct pollfd {
int fd;
short events;
@@ -42,16 +42,6 @@ int poll(struct pollfd *fds, int nfds, int timeout) { abort(); }
#define FADE_LENGTH 40
-/* Names of periods of day */
-static const char *period_names[] = {
- /* TRANSLATORS: Name printed when period of day is unknown */
- N_("None"),
- N_("Daytime"),
- N_("Night"),
- N_("Transition")
-};
-
-
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wfloat-equal"
@@ -88,7 +78,11 @@ millisleep(unsigned int msecs)
}
-/* Return number of seconds since midnight from timestamp. */
+/**
+ * Get the number of seconds since midnight
+ *
+ * @return The number of seconds since midnight
+ */
static time_t
get_time_since_midnight(void)
{
@@ -101,61 +95,30 @@ get_time_since_midnight(void)
return t;
}
-/* Print verbose description of the given period. */
+
+/**
+ * Print the current period of the day
+ *
+ * @param period The current period of the day
+ * @param day_level The current dayness level
+ */
static void
print_period(enum period period, double day_level)
{
+ static const char *period_names[] = {
+ /* TRANSLATORS: Name printed when period of day is unknown */
+ [PERIOD_NONE] = N_("None"),
+ [PERIOD_DAYTIME] = N_("Daytime"),
+ [PERIOD_NIGHT] = N_("Night"),
+ [PERIOD_TRANSITION] = N_("Transition")
+ };
+
if (period == PERIOD_TRANSITION)
printf(_("Period: %s (%.2f%% day)\n"), gettext(period_names[period]), day_level * 100);
else
printf(_("Period: %s\n"), gettext(period_names[period]));
}
-/* Print location */
-static void
-print_location(const struct location *location)
-{
- /* TRANSLATORS: Abbreviation for `north' */
- const char *north = _("N");
- /* TRANSLATORS: Abbreviation for `south' */
- const char *south = _("S");
- /* TRANSLATORS: Abbreviation for `east' */
- const char *east = _("E");
- /* TRANSLATORS: Abbreviation for `west' */
- const char *west = _("W");
-
- /* TRANSLATORS: Append degree symbols after %f if possible.
- The string following each number is an abreviation for
- north, source, east or west (N, S, E, W). */
- printf(_("Location: %.2f %s, %.2f %s\n"),
- fabs(location->latitude), location->latitude >= 0.0 ? north : south,
- fabs(location->longitude), location->longitude >= 0.0 ? east : west);
-}
-
-/* Interpolate colour setting structs given alpha. */
-static void
-interpolate_colour_settings(const struct colour_setting *first, const struct colour_setting *second,
- double alpha, struct colour_setting *result)
-{
- int i;
- alpha = CLAMP(0.0, alpha, 1.0);
- result->temperature = (1.0 - alpha) * first->temperature + alpha * second->temperature;
- result->brightness = (1.0 - alpha) * first->brightness + alpha * second->brightness;
- for (i = 0; i < 3; i++)
- result->gamma[i] = (1.0 - alpha) * first->gamma[i] + alpha * second->gamma[i];
-}
-
-/* Return 1 if colour settings have major differences, otherwise 0.
- Used to determine if a fade should be applied in continual mode. */
-static int
-colour_setting_diff_is_major(const struct colour_setting *first, const struct colour_setting *second)
-{
- return MAX(first->temperature, second->temperature) - MIN(first->temperature, second->temperature) > 25UL ||
- fabs(first->brightness - second->brightness) > 0.1 ||
- fabs(first->gamma[0] - second->gamma[0]) > 0.1 ||
- fabs(first->gamma[1] - second->gamma[1]) > 0.1 ||
- fabs(first->gamma[2] - second->gamma[2]) > 0.1;
-}
/**
* Get the current period of day and the colour settings
@@ -165,11 +128,10 @@ colour_setting_diff_is_major(const struct colour_setting *first, const struct co
* @param colour_out Output parameter for the colour settings
* @param period_out Output parameter for the period of the day
* @param day_level_out Output parameter for the dayness level
- * @param verbose Whether the application is running in verbose mode
*/
static void
get_colour_settings(const struct location *location, struct colour_setting *colour_out,
- enum period *period_out, double *day_level_out, int verbose)
+ enum period *period_out, double *day_level_out)
{
time_t time_offset;
double t, elevation;
@@ -220,34 +182,21 @@ get_colour_settings(const struct location *location, struct colour_setting *colo
}
-/* Check whether location is valid.
- Prints error message on stderr and returns 0 if invalid, otherwise
- returns 1. */
-static int
-location_is_valid(const struct location *location)
-{
- if (!WITHIN(MIN_LATITUDE, location->latitude, MAX_LATITUDE)) {
- /* TRANSLATORS: Append degree symbols if possible. */
- weprintf(_("Latitude must be between %.1f and %.1f."), MIN_LATITUDE, MAX_LATITUDE);
- return 0;
- }
- if (!WITHIN(MIN_LONGITUDE, location->longitude, MAX_LONGITUDE)) {
- /* TRANSLATORS: Append degree symbols if possible. */
- weprintf(_("Longitude must be between %.1f and %.1f."), MIN_LONGITUDE, MAX_LONGITUDE);
- return 0;
- }
- return 1;
-}
-
-/* Easing function for fade.
- See https://github.com/mietek/ease-tween */
+/**
+ * Easing function used for fade effect
+ *
+ * See https://github.com/mietek/ease-tween
+ *
+ * @param t Raw fade progress
+ * @return Fade progress to apply
+ */
+GCC_ONLY(__attribute__((__const__)))
static double
ease_fade(double t)
{
if (t <= 0) return 0;
if (t >= 1) return 1;
- return 1.0042954579734844 * exp(
- -6.4041738958415664 * exp(-7.2908241330981340 * t));
+ return 1.0042954579734844 * exp(-6.4041738958415664 * exp(-7.2908241330981340 * t));
}
@@ -258,7 +207,7 @@ ease_fade(double t)
static void
run_continual_mode(const struct location_provider *provider, LOCATION_STATE *location_state,
const struct gamma_method *method, GAMMA_STATE *method_state, int use_fade,
- int preserve_gamma, int verbose)
+ int preserve_gamma)
{
int done = 0;
int prev_disabled = 1;
@@ -274,13 +223,13 @@ run_continual_mode(const struct location_provider *provider, LOCATION_STATE *loc
int fade_time = 0;
/* Save previous parameters so we can avoid printing status updates if
- the values did not change. */
+ * the values did not change. */
enum period prev_period = PERIOD_NONE;
install_signal_handlers();
/* Previous target colour setting and current actual colour setting.
- Actual colour setting takes into account the current colour fade. */
+ * Actual colour setting takes into account the current colour fade. */
prev_target_interp = COLOUR_SETTING_NEUTRAL;
interp = COLOUR_SETTING_NEUTRAL;
@@ -289,7 +238,6 @@ run_continual_mode(const struct location_provider *provider, LOCATION_STATE *loc
if (scheme.type == SOLAR_SCHEME) {
weprintf(_("Waiting for initial location to become available..."));
- /* Get initial location from provider */
if (get_location(provider, location_state, -1, &loc) < 0)
eprintf(_("Unable to get location from provider."));
@@ -320,7 +268,7 @@ run_continual_mode(const struct location_provider *provider, LOCATION_STATE *loc
/* Check to see if exit signal was caught */
if (exiting) {
if (done)
- break; /* On second signal stop the ongoing fade. */
+ break; /* On second signal stop the ongoing fade */
done = 1;
disabled = 1;
exiting = 0;
@@ -332,7 +280,7 @@ run_continual_mode(const struct location_provider *provider, LOCATION_STATE *loc
prev_disabled = disabled;
- get_colour_settings(&loc, &target_interp, &period, &day_level, verbose);
+ get_colour_settings(&loc, &target_interp, &period, &day_level);
if (disabled) {
period = PERIOD_NONE;
@@ -343,9 +291,9 @@ run_continual_mode(const struct location_provider *provider, LOCATION_STATE *loc
period = PERIOD_NONE;
/* Print period if it changed during this update,
- or if we are in the transition period. In transition we
- print the progress, so we always print it in
- that case. */
+ * or if we are in the transition period. In transition we
+ * print the progress, so we always print it in
+ * that case. */
if (verbose && (period != prev_period || period == PERIOD_TRANSITION))
print_period(period, day_level);
@@ -353,8 +301,7 @@ run_continual_mode(const struct location_provider *provider, LOCATION_STATE *loc
if (period != prev_period)
run_period_change_hooks(prev_period, period);
- /* Start fade if the parameter differences are too big to apply
- instantly. */
+ /* Start fade if the parameter differences are too big to apply instantly */
if (use_fade && colour_setting_diff_is_major(&target_interp, fade_length ? &prev_target_interp : &interp)) {
fade_length = FADE_LENGTH;
fade_time = 0;
@@ -388,17 +335,17 @@ run_continual_mode(const struct location_provider *provider, LOCATION_STATE *loc
}
/* Adjust temperature */
- if (method->set_temperature(method_state, &interp, preserve_gamma) < 0)
+ if (method->apply(method_state, &interp, preserve_gamma) < 0)
eprintf(_("Temperature adjustment failed."));
/* Save period and target colour setting as previous */
prev_period = period;
prev_target_interp = target_interp;
- /* Sleep length depends on whether a fade is ongoing. */
+ /* Sleep length depends on whether a fade is ongoing */
delay = fade_length ? SLEEP_DURATION_SHORT : SLEEP_DURATION;
- /* Update location. */
+ /* Update location */
loc_fd = scheme.type == SOLAR_SCHEME ? provider->get_fd(location_state) : -1;
if (loc_fd >= 0) {
@@ -406,7 +353,7 @@ run_continual_mode(const struct location_provider *provider, LOCATION_STATE *loc
struct location new_loc;
int r, new_available;
- /* Provider is dynamic. */
+ /* Provider is dynamic */
pollfds[0].fd = loc_fd;
pollfds[0].events = POLLIN;
r = poll(pollfds, 1, delay);
@@ -421,8 +368,8 @@ run_continual_mode(const struct location_provider *provider, LOCATION_STATE *loc
continue;
}
- /* Get new location and availability information. */
- if (provider->handle(location_state, &new_loc, &new_available) < 0)
+ /* Get new location and availability information */
+ if (provider->fetch(location_state, &new_loc, &new_available) < 0)
eprintf(_("Unable to get location from provider."));
if (!new_available && new_available != location_available) {
@@ -456,8 +403,8 @@ int
main(int argc, char *argv[])
{
struct settings settings;
- GAMMA_STATE *method_state;
- LOCATION_STATE *location_state;
+ GAMMA_STATE *method_state = NULL;
+ LOCATION_STATE *location_state = NULL;
struct location loc = {NAN, NAN};
double day_level;
enum period period;
@@ -473,30 +420,19 @@ main(int argc, char *argv[])
#endif
load_settings(&settings, argc, argv);
-
- /* Initialize location provider if needed. If provider is NULL
- try all providers until one that works is found. */
-
- /* Location is not needed for reset mode and manual mode. */
- if (settings.scheme_type == SOLAR_SCHEME)
+ if (scheme.type == SOLAR_SCHEME)
acquire_location_provider(&settings, &location_state);
-
- /* Initialize gamma adjustment method. If method is NULL
- try all methods until one that works is found. */
-
- /* Gamma adjustment not needed for print mode */
- if (settings.mode != PROGRAM_MODE_PRINT)
+ if (mode != PROGRAM_MODE_PRINT)
acquire_adjustment_method(&settings, &method_state);
-
config_ini_free(&settings.config);
- switch (settings.mode) {
+ switch (mode) {
case PROGRAM_MODE_ONE_SHOT:
case PROGRAM_MODE_PRINT:
- if (settings.scheme_type == SOLAR_SCHEME) {
+ case PROGRAM_MODE_RESET:
+ if (scheme.type == SOLAR_SCHEME) {
weprintf(_("Waiting for current location to become available..."));
- /* Wait for location provider. */
if (get_location(settings.provider, location_state, -1, &loc) < 0)
eprintf(_("Unable to get location from provider."));
@@ -506,25 +442,23 @@ main(int argc, char *argv[])
print_location(&loc);
}
- get_colour_settings(&loc, &colour, &period, &day_level, settings.verbose);
+ get_colour_settings(&loc, &colour, &period, &day_level);
- if (settings.verbose || settings.mode == PROGRAM_MODE_PRINT) {
- if (settings.scheme_type != STATIC_SCHEME)
+ if (verbose || mode == PROGRAM_MODE_PRINT) {
+ if (scheme.type != STATIC_SCHEME)
print_period(period, day_level);
printf(_("Color temperature: %luK\n"), colour.temperature);
printf(_("Brightness: %.2f\n"), colour.brightness);
+ if (mode == PROGRAM_MODE_PRINT)
+ break;
}
- if (settings.mode == PROGRAM_MODE_PRINT)
- break;
-
- apply:
- if (settings.method->set_temperature(method_state, &colour, settings.preserve_gamma.value) < 0)
+ if (settings.method->apply(method_state, &colour, settings.preserve_gamma.value) < 0)
eprintf(_("Temperature adjustment failed."));
#ifndef WINDOWS
/* In Quartz (OSX) the gamma adjustments will automatically revert when
- * the process exits. Therefore, we have to loop until CTRL-C is received. */
+ * the process exits. Therefore, we have to loop until Ctrl+C is received. */
if (!strcmp(settings.method->name, "quartz")) {
weprintf(_("Press ctrl-c to stop..."));
while (!exiting)
@@ -533,27 +467,15 @@ main(int argc, char *argv[])
#endif
break;
- case PROGRAM_MODE_MANUAL:
- /* TODO interpolate for current time if a value range has been specified */
- colour = day_settings;
- if (settings.verbose)
- printf(_("Color temperature: %luK\n"), colour.temperature);
- goto apply;
-
- case PROGRAM_MODE_RESET:
- colour = COLOUR_SETTING_NEUTRAL;
- settings.preserve_gamma.value = 0;
- goto apply;
-
case PROGRAM_MODE_CONTINUAL:
run_continual_mode(settings.provider, location_state, settings.method, method_state,
- settings.use_fade.value, settings.preserve_gamma.value, settings.verbose);
+ settings.use_fade.value, settings.preserve_gamma.value);
break;
}
- if (settings.mode != PROGRAM_MODE_PRINT)
+ if (method_state)
settings.method->free(method_state);
- if (scheme.type == SOLAR_SCHEME)
+ if (location_state)
settings.provider->free(location_state);
return 0;
}
diff --git a/src/util.c b/src/util.c
index fc6dc2c..a562fd2 100644
--- a/src/util.c
+++ b/src/util.c
@@ -186,47 +186,66 @@ try_path_opendir(const struct env_path *path_spec, const char **path_out, char *
}
+
+#ifndef WINDOWS
int
-pipe_nonblock(int pipefds[2])
+pipe_rdnonblock(int pipefds[2])
{
-#ifdef WINDOWS
- (void) pipefds;
- return -1;
-#else
-
int i, flags;
+ /* Try to use pipe2(2) create O_CLOEXEC pipe, preferably with O_DIRECT */
# if defined(__linux__) && !defined(MISSING_PIPE2)
- if (!pipe2(pipefds, O_NONBLOCK)) {
- return 0;
+ if (!pipe2(pipefds, O_CLOEXEC | O_DIRECT)) {
+ goto apply_nonblock;
+ } else if (errno == EINVAL) {
+ if (!pipe2(pipefds, O_CLOEXEC)) {
+ goto apply_nonblock;
+ } else if (errno != ENOSYS) {
+ weprintf("pipe2 <buffer> O_CLOEXEC:");
+ return -1;
+ }
} else if (errno != ENOSYS) {
- weprintf("pipe2 <buffer> O_NONBLOCK:");
+ weprintf("pipe2 <buffer> O_CLOEXEC|O_DIRECT:");
return -1;
}
# endif
+ /* Fallback for when pipe2(2) is not available (also indicates O_DIRECT cannot be used) */
if (pipe(pipefds)) {
weprintf("pipe:");
return -1;
}
-
for (i = 0; i < 2; i++) {
- flags = fcntl(pipefds[0], F_GETFL);
+ flags = fcntl(pipefds[i], F_GETFD);
if (flags == -1) {
- weprintf("fcntl <pipe> F_GETFL:");
+ weprintf("fcntl <pipe> F_GETFD:");
goto fail;
}
- if (fcntl(pipefds[0], F_SETFL, flags | O_NONBLOCK)) {
- weprintf("fcntl <pipe> F_SETFL +O_NONBLOCK:");
+ if (fcntl(pipefds[i], F_SETFD, flags | O_CLOEXEC)) {
+ weprintf("fcntl <pipe> F_SETFD +O_CLOEXEC:");
goto fail;
}
}
+ /* Make the read-end non-blocking */
+# if defined(__linux__) && !defined(MISSING_PIPE2)
+apply_nonblock:
+# endif
+ flags = fcntl(pipefds[0], F_GETFL);
+ if (flags == -1) {
+ weprintf("fcntl <pipe> F_GETFL:");
+ goto fail;
+ }
+ if (fcntl(pipefds[0], F_SETFL, flags | O_NONBLOCK)) {
+ weprintf("fcntl <pipe> F_SETFL +O_NONBLOCK:");
+ goto fail;
+ }
+
return 0;
fail:
close(pipefds[0]);
close(pipefds[1]);
return -1;
-#endif
}
+#endif