Provide fundament for more advanced location providers.

This commit is contained in:
Jon Lund Steffensen
2010-05-25 00:45:29 +02:00
parent 65dd76a221
commit cde909747c
5 changed files with 266 additions and 23 deletions
+2 -1
View File
@@ -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 \
+93
View File
@@ -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;
}
+36
View File
@@ -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
View File
@@ -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);
+15
View File
@@ -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 */