From 8839dcd530cbc8f5c7ae45a61d86bed05d2a6e8a Mon Sep 17 00:00:00 2001 From: Jon Lund Steffensen Date: Sat, 6 Dec 2014 15:32:50 -0500 Subject: Add CoreLocation (OSX) location provider Similarly to the Geoclue provider, the CoreLocation provider only requests the location on startup. --- src/Makefile.am | 15 ++++ src/location-corelocation.h | 38 +++++++++++ src/location-corelocation.m | 163 ++++++++++++++++++++++++++++++++++++++++++++ src/redshift.c | 18 +++++ 4 files changed, 234 insertions(+) create mode 100644 src/location-corelocation.h create mode 100644 src/location-corelocation.m (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index ba0406d..8d11a03 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -82,3 +82,18 @@ AM_CFLAGS += \ redshift_LDADD += \ $(GEOCLUE2_LIBS) $(GEOCLUE2_CFLAGS) endif + +# Build CoreLocation module as a separate convenience +# library since it is using a separate compiler +# (Objective C). + +if ENABLE_CORELOCATION +noinst_LTLIBRARIES = liblocation-corelocation.la +liblocation_corelocation_la_SOURCES = \ + location-corelocation.m location-corelocation.h +liblocation_corelocation_la_OBJCFLAGS = \ + $(CORELOCATION_CFLAGS) +liblocation_corelocation_la_LIBADD = \ + $(CORELOCATION_CFLAGS) $(CORELOCATION_LIBS) +redshift_LDADD += liblocation-corelocation.la +endif diff --git a/src/location-corelocation.h b/src/location-corelocation.h new file mode 100644 index 0000000..58dddd7 --- /dev/null +++ b/src/location-corelocation.h @@ -0,0 +1,38 @@ +/* location-corelocation.h -- CoreLocation (OSX) 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 . + + Copyright (c) 2014 Jon Lund Steffense +*/ + +#ifndef REDSHIFT_LOCATION_CORELOCATION_H +#define REDSHIFT_LOCATION_CORELOCATION_H + +#include + + +int location_corelocation_init(void *state); +int location_corelocation_start(void *state); +void location_corelocation_free(void *state); + +void location_corelocation_print_help(FILE *f); +int location_corelocation_set_option(void *state, + const char *key, const char *value); + +int location_corelocation_get_location(void *state, + float *lat, float *lon); + + +#endif /* ! REDSHIFT_LOCATION_CORELOCATION_H */ diff --git a/src/location-corelocation.m b/src/location-corelocation.m new file mode 100644 index 0000000..626949c --- /dev/null +++ b/src/location-corelocation.m @@ -0,0 +1,163 @@ +/* location-corelocation.m -- CoreLocation (OSX) 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 . + + Copyright (c) 2014 Jon Lund Steffensen +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#import +#import + +#include "location-corelocation.h" + +#include + +#ifdef ENABLE_NLS +# include +# define _(s) gettext(s) +#else +# define _(s) s +#endif + + +@interface Delegate : NSObject +@property (strong, nonatomic) CLLocationManager *locationManager; +@property (nonatomic) BOOL success; +@property (nonatomic) float latitude; +@property (nonatomic) float longitude; +@end + +@implementation Delegate; + +- (void)start +{ + self.locationManager = [[CLLocationManager alloc] init]; + self.locationManager.delegate = self; + + CLAuthorizationStatus authStatus = + [CLLocationManager authorizationStatus]; + + if (authStatus != kCLAuthorizationStatusNotDetermined && + authStatus != kCLAuthorizationStatusAuthorized) { + fputs(_("Not authorized to obtain location" + "from CoreLocation.\n"), stderr); + CFRunLoopStop(CFRunLoopGetCurrent()); + } + + [self.locationManager startUpdatingLocation]; +} + +- (void)stop +{ + [self.locationManager stopUpdatingLocation]; + CFRunLoopStop(CFRunLoopGetCurrent()); +} + +- (void)locationManager:(CLLocationManager *)manager + didUpdateLocations:(NSArray *)locations +{ + CLLocation *newLocation = [locations firstObject]; + self.latitude = newLocation.coordinate.latitude; + self.longitude = newLocation.coordinate.longitude; + self.success = YES; + + [self stop]; +} + +- (void)locationManager:(CLLocationManager *)manager + didFailWithError:(NSError *)error +{ + fprintf(stderr, _("Error obtaining location from CoreLocation: %s\n"), + [[error localizedDescription] UTF8String]); + [self stop]; +} + +- (void)locationManager:(CLLocationManager *)manager + didChangeAuthorizationStatus:(CLAuthorizationStatus)status +{ + if (status == kCLAuthorizationStatusNotDetermined) { + fputs(_("Waiting for authorization to obtain location...\n"), + stderr); + } else if (status != kCLAuthorizationStatusAuthorized) { + fputs(_("Request for location was not authorized!\n"), + stderr); + [self stop]; + } +} + +@end + + +int +location_corelocation_init(void *state) +{ + return 0; +} + +int +location_corelocation_start(void *state) +{ + return 0; +} + +void +location_corelocation_free(void *state) +{ +} + +void +location_corelocation_print_help(FILE *f) +{ + fputs(_("Use the location as discovered by the Corelocation provider.\n"), f); + fputs("\n", f); + + fputs(_("NOTE: currently redshift doesn't recheck CoreLocation once started,\n" + "which means it has to be restarted to take notice after travel.\n"), + f); + fputs("\n", f); +} + +int +location_corelocation_set_option(void *state, + const char *key, const char *value) +{ + fprintf(stderr, _("Unknown method parameter: `%s'.\n"), key); + return -1; +} + +int +location_corelocation_get_location(void *state, + float *lat, float *lon) +{ + int result = -1; + + @autoreleasepool { + Delegate *delegate = [[Delegate alloc] init]; + [delegate performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO]; + CFRunLoopRun(); + + if (delegate.success) { + *lat = delegate.latitude; + *lon = delegate.longitude; + result = 0; + } + } + + return result; +} diff --git a/src/redshift.c b/src/redshift.c index 8ff40f0..818db4e 100644 --- a/src/redshift.c +++ b/src/redshift.c @@ -84,6 +84,10 @@ # include "location-geoclue2.h" #endif +#ifdef ENABLE_CORELOCATION +# include "location-corelocation.h" +#endif + /* Union of state data for gamma adjustment methods */ typedef union { @@ -219,6 +223,20 @@ static const location_provider_t location_providers[] = { (location_provider_get_location_func *) location_geoclue2_get_location }, +#endif +#ifdef ENABLE_CORELOCATION + { + "corelocation", + (location_provider_init_func *)location_corelocation_init, + (location_provider_start_func *)location_corelocation_start, + (location_provider_free_func *)location_corelocation_free, + (location_provider_print_help_func *) + location_corelocation_print_help, + (location_provider_set_option_func *) + location_corelocation_set_option, + (location_provider_get_location_func *) + location_corelocation_get_location + }, #endif { "manual", -- cgit v1.2.3-70-g09d2