Provide fundament for more advanced location providers.
This commit is contained in:
+2
-1
@@ -12,7 +12,8 @@ redshift_SOURCES = \
|
||||
redshift.c \
|
||||
colorramp.c colorramp.h \
|
||||
solar.c solar.h \
|
||||
systemtime.c systemtime.h
|
||||
systemtime.c systemtime.h \
|
||||
location-manual.c location-manual.h
|
||||
|
||||
EXTRA_redshift_SOURCES = \
|
||||
gamma-randr.c gamma-randr.h \
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/* location-manual.c -- Manual location provider source
|
||||
This file is part of Redshift.
|
||||
|
||||
Redshift is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Redshift is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Redshift. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright (c) 2010 Jon Lund Steffensen <jonlst@gmail.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "location-manual.h"
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
# include <libintl.h>
|
||||
# define _(s) gettext(s)
|
||||
#else
|
||||
# define _(s) s
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
location_manual_init(location_manual_state_t *state, char *args)
|
||||
{
|
||||
state->lat = NAN;
|
||||
state->lon = NAN;
|
||||
|
||||
/* Parse arguments. */
|
||||
int count = 0;
|
||||
while (args != NULL) {
|
||||
if (count > 1) {
|
||||
fputs(_("Too many arguments.\n"), stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *next_arg = strchr(args, ':');
|
||||
if (next_arg != NULL) *(next_arg++) = '\0';
|
||||
|
||||
/* Parse float value */
|
||||
char *end;
|
||||
errno = 0;
|
||||
float value = strtof(args, &end);
|
||||
if (errno != 0 || *end != '\0') {
|
||||
fputs(_("Malformed argument.\n"), stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (count) {
|
||||
case 0: state->lat = value; break;
|
||||
case 1: state->lon = value; break;
|
||||
}
|
||||
|
||||
args = next_arg;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
/* Latitude and longitude must be set */
|
||||
if (isnan(state->lat) || isnan(state->lon)) {
|
||||
fputs(_("Latitude and longitude must be set.\n"), stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
location_manual_free(location_manual_state_t *state)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
location_manual_get_location(location_manual_state_t *state, float *lat,
|
||||
float *lon)
|
||||
{
|
||||
*lat = state->lat;
|
||||
*lon = state->lon;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/* location-manual.h -- Manual location provider header
|
||||
This file is part of Redshift.
|
||||
|
||||
Redshift is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Redshift is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Redshift. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright (c) 2010 Jon Lund Steffensen <jonlst@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _REDSHIFT_LOCATION_MANUAL_H
|
||||
#define _REDSHIFT_LOCATION_MANUAL_H
|
||||
|
||||
|
||||
typedef struct {
|
||||
float lat;
|
||||
float lon;
|
||||
} location_manual_state_t;
|
||||
|
||||
|
||||
int location_manual_init(location_manual_state_t *state, char *args);
|
||||
void location_manual_free(location_manual_state_t *state);
|
||||
int location_manual_get_location(location_manual_state_t *state, float *lat,
|
||||
float *lon);
|
||||
|
||||
|
||||
#endif /* ! _REDSHIFT_LOCATION_MANUAL_H */
|
||||
+120
-22
@@ -28,6 +28,7 @@
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_SYS_SIGNAL_H
|
||||
# include <sys/signal.h>
|
||||
@@ -67,6 +68,9 @@
|
||||
#endif
|
||||
|
||||
|
||||
#include "location-manual.h"
|
||||
|
||||
|
||||
/* Union of state data for gamma adjustment methods */
|
||||
typedef union {
|
||||
#ifdef ENABLE_RANDR
|
||||
@@ -114,6 +118,24 @@ static const gamma_method_t gamma_methods[] = {
|
||||
};
|
||||
|
||||
|
||||
/* Union of state data for location providers */
|
||||
typedef union {
|
||||
location_manual_state_t manual;
|
||||
} location_state_t;
|
||||
|
||||
|
||||
/* Location provider method structs */
|
||||
static const location_provider_t location_providers[] = {
|
||||
{
|
||||
"Manual",
|
||||
(location_provider_init_func *)location_manual_init,
|
||||
(location_provider_free_func *)location_manual_free,
|
||||
(location_provider_get_location_func *)
|
||||
location_manual_get_location
|
||||
},
|
||||
{ NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
/* Bounds for parameters. */
|
||||
#define MIN_LAT -90.0
|
||||
#define MAX_LAT 90.0
|
||||
@@ -218,6 +240,9 @@ print_help(const char *program_name)
|
||||
no-wrap */
|
||||
fputs(_(" -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"
|
||||
" \t\t(Type `list' to see available providers)\n"
|
||||
" -m METHOD\tMethod to use to set color temperature\n"
|
||||
" \t\t(Type `list' to see available methods)\n"
|
||||
" -o\t\tOne shot mode (do not continously adjust"
|
||||
@@ -250,6 +275,15 @@ print_method_list()
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_provider_list()
|
||||
{
|
||||
fputs(_("Available location providers:\n"), stdout);
|
||||
for (int i = 0; location_providers[i].name != NULL; i++) {
|
||||
printf(" %s\n", location_providers[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
@@ -267,8 +301,6 @@ main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
/* Initialize to defaults */
|
||||
float lat = NAN;
|
||||
float lon = NAN;
|
||||
int temp_day = DEFAULT_DAY_TEMP;
|
||||
int temp_night = DEFAULT_NIGHT_TEMP;
|
||||
float gamma[3] = { DEFAULT_GAMMA, DEFAULT_GAMMA, DEFAULT_GAMMA };
|
||||
@@ -276,6 +308,9 @@ main(int argc, char *argv[])
|
||||
const gamma_method_t *method = NULL;
|
||||
char *method_args = NULL;
|
||||
|
||||
const location_provider_t *provider = NULL;
|
||||
char *provider_args = NULL;
|
||||
|
||||
int transition = 1;
|
||||
int one_shot = 0;
|
||||
int verbose = 0;
|
||||
@@ -315,17 +350,47 @@ main(int argc, char *argv[])
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'l':
|
||||
s = strchr(optarg, ':');
|
||||
if (s == NULL) {
|
||||
fputs(_("Malformed location argument.\n"),
|
||||
stderr);
|
||||
fputs(_("Try `-h' for more information.\n"),
|
||||
stderr);
|
||||
/* Print list of providers if argument is `list' */
|
||||
if (strcasecmp(optarg, "list") == 0) {
|
||||
print_provider_list();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
char *provider_name = NULL;
|
||||
|
||||
/* Try to parse provider name as float */
|
||||
errno = 0;
|
||||
char *end;
|
||||
float lat = strtof(optarg, &end);
|
||||
if (errno == 0 && *end == ':') {
|
||||
provider_name = "Manual";
|
||||
provider_args = optarg;
|
||||
} else {
|
||||
/* Split off provider arguments. */
|
||||
s = strchr(optarg, ':');
|
||||
if (s != NULL) {
|
||||
*(s++) = '\0';
|
||||
provider_args = s;
|
||||
}
|
||||
|
||||
provider_name = optarg;
|
||||
}
|
||||
|
||||
/* Lookup argument in location provider table */
|
||||
for (int i = 0; location_providers[i].name != NULL;
|
||||
i++) {
|
||||
const location_provider_t *p =
|
||||
&location_providers[i];
|
||||
if (strcasecmp(provider_name, p->name) == 0) {
|
||||
provider = p;
|
||||
}
|
||||
}
|
||||
|
||||
if (provider == NULL) {
|
||||
fprintf(stderr, _("Unknown location provider"
|
||||
" `%s'.\n"), provider_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
*(s++) = '\0';
|
||||
lat = atof(optarg);
|
||||
lon = atof(s);
|
||||
break;
|
||||
case 'm':
|
||||
/* Print list of methods if argument is `list' */
|
||||
@@ -334,13 +399,6 @@ main(int argc, char *argv[])
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* Split off method arguments. */
|
||||
s = strchr(optarg, ':');
|
||||
if (s != NULL) {
|
||||
*(s++) = '\0';
|
||||
method_args = s;
|
||||
}
|
||||
|
||||
/* Lookup argument in gamma methods table */
|
||||
for (int i = 0; gamma_methods[i].name != NULL; i++) {
|
||||
const gamma_method_t *m =
|
||||
@@ -387,13 +445,53 @@ main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
/* Latitude and longitude must be set */
|
||||
if (isnan(lat) || isnan(lon)) {
|
||||
fputs(_("Latitude and longitude must be set.\n"), stderr);
|
||||
fputs(_("Try `-h' for more information.\n"), stderr);
|
||||
/* Initialize location provider. If provider is NULL
|
||||
try all providers until one that works is found. */
|
||||
location_state_t location_state;
|
||||
|
||||
if (provider != NULL) {
|
||||
/* Use provider specified on command line. */
|
||||
r = provider->init(&location_state, provider_args);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, _("Initialization of %s failed.\n"),
|
||||
provider->name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
/* Try all providers, use the first that works. */
|
||||
for (int i = 0; location_providers[i].name != NULL; i++) {
|
||||
const location_provider_t *p = &location_providers[i];
|
||||
r = p->init(&location_state, provider_args);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, _("Initialization of %s"
|
||||
" failed.\n"), p->name);
|
||||
fputs(_("Trying other provider...\n"), stderr);
|
||||
} else {
|
||||
provider = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Failure if no providers were successful at this point. */
|
||||
if (provider == NULL) {
|
||||
fputs(_("No more location providers to try.\n"),
|
||||
stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
float lat = NAN;
|
||||
float lon = NAN;
|
||||
|
||||
/* Get current location. */
|
||||
r = provider->get_location(&location_state, &lat, &lon);
|
||||
if (r < 0) {
|
||||
fputs(_("Unable to get location from provider.\n"), stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
provider->free(&location_state);
|
||||
|
||||
if (verbose) {
|
||||
/* TRANSLATORS: Append degree symbols if possible. */
|
||||
printf(_("Location: %f, %f\n"), lat, lon);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define _REDSHIFT_REDSHIFT_H
|
||||
|
||||
|
||||
/* Gamma adjustment method */
|
||||
typedef int gamma_method_init_func(void *state, char *args);
|
||||
typedef void gamma_method_free_func(void *state);
|
||||
typedef void gamma_method_restore_func(void *state);
|
||||
@@ -36,4 +37,18 @@ typedef struct {
|
||||
} gamma_method_t;
|
||||
|
||||
|
||||
/* Location provider */
|
||||
typedef int location_provider_init_func(void *state, char *args);
|
||||
typedef void location_provider_free_func(void *state);
|
||||
typedef int location_provider_get_location_func(void *state, float *lat,
|
||||
float *lon);
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
location_provider_init_func *init;
|
||||
location_provider_free_func *free;
|
||||
location_provider_get_location_func *get_location;
|
||||
} location_provider_t;
|
||||
|
||||
|
||||
#endif /* ! _REDSHIFT_REDSHIFT_H */
|
||||
|
||||
Reference in New Issue
Block a user