Add CoreLocation (OSX) location provider

Similarly to the Geoclue provider, the CoreLocation provider only
requests the location on startup.
This commit is contained in:
Jon Lund Steffensen
2014-12-15 20:36:35 -05:00
parent 980a993c98
commit 8839dcd530
6 changed files with 303 additions and 0 deletions
+68
View File
@@ -5,14 +5,31 @@ AC_PREREQ([2.69])
AC_INIT([redshift], [1.9.1], [https://github.com/jonls/redshift/issues])
AC_CONFIG_SRCDIR([src/redshift.c])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([foreign subdir-objects dist-xz])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
# Checks for programs.
AC_PROG_CC_C99
AC_PROG_LIBTOOL
AC_PROG_OBJC # For OSX support modules
AC_LANG([C])
AC_PROG_INTLTOOL([0.50])
# Test whether Objective C compiler works
AC_MSG_CHECKING([whether Objective C compiler works])
AC_LANG_PUSH([Objective C])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], [
AC_MSG_RESULT([yes])
have_objc_compiler=yes
], [
AC_MSG_RESULT([no])
have_objc_compiler=no
])
AC_LANG_POP([Objective C])
# Checks for libraries.
AM_GNU_GETTEXT_VERSION([0.17])
AM_GNU_GETTEXT([external])
@@ -34,8 +51,30 @@ PKG_CHECK_MODULES([GLIB], [glib-2.0 gobject-2.0], [have_glib=yes], [have_glib=no
PKG_CHECK_MODULES([GEOCLUE], [geoclue], [have_geoclue=yes], [have_geoclue=no])
PKG_CHECK_MODULES([GEOCLUE2], [glib-2.0 gio-2.0 >= 2.26], [have_geoclue2=yes], [have_geoclue2=no])
# OSX headers
AC_CHECK_HEADER([ApplicationServices/ApplicationServices.h], [have_appserv_h=yes], [have_appserv_h=no])
# CoreLocation.h is an Objective C header. Only test if
# Objective C compiler works. AC_CHECK_HEADER does not
# appear to work if the Ojective C compiler is not
# available so we need a custom test.
AC_MSG_CHECKING([whether CoreLocation/CoreLocation.h is usable])
AS_IF([test "x$have_objc_compiler" = xyes], [
AC_LANG_PUSH([Objective C])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#import <CoreLocation/CoreLocation.h>]],[[]])], [
AC_MSG_RESULT([yes])
have_corelocation_h=yes
], [
AC_MSG_RESULT([no])
have_corelocation_h=no
])
AC_LANG_POP([Objective C])
], [
AC_MSG_RESULT([no Objective C compiler available])
have_corelocation_h=no
])
# Windows header
AC_CHECK_HEADER([windows.h], [have_windows_h=yes], [have_windows_h=no])
# Check for Python
@@ -214,6 +253,34 @@ AS_IF([test "x$enable_geoclue2" != xno], [
])
AM_CONDITIONAL([ENABLE_GEOCLUE2], [test "x$enable_geoclue2" = xyes])
# Check CoreLocation (OSX) provider
AC_MSG_CHECKING([whether to enable CoreLocation method])
AC_ARG_ENABLE([corelocation], [AC_HELP_STRING([--enable-corelocation],
[enable CoreLocation (OSX) provider])],
[enable_corelocation=$enableval],[enable_corelocation=maybe])
AS_IF([test "x$enable_corelocation" != xno], [
AS_IF([test "x$have_corelocation_h" = xyes], [
CORELOCATION_CFLAGS=""
CORELOCATION_LIBS="-framework Foundation -framework CoreLocation"
AC_DEFINE([ENABLE_CORELOCATION], 1,
[Define to 1 to enable CoreLocation provider])
AC_MSG_RESULT([yes])
enable_corelocation=yes
], [
AC_MSG_RESULT([missing dependencies])
AS_IF([test "x$enable_corelocation" = xyes], [
AC_MSG_ERROR([missing CoreLocation headers])
])
enable_corelocation=no
])
], [
AC_MSG_RESULT([no])
enable_corelocation=no
])
AM_CONDITIONAL([ENABLE_CORELOCATION], [test "x$enable_corelocation" = xyes])
AC_SUBST([CORELOCATION_CFLAGS])
AC_SUBST([CORELOCATION_LIBS])
# Check for GUI status icon
AC_MSG_CHECKING([whether to enable GUI status icon])
@@ -306,6 +373,7 @@ echo "
Location providers:
Geoclue: ${enable_geoclue}
Geoclue2: ${enable_geoclue2}
CoreLocation (OSX) ${enable_corelocation}
GUI: ${enable_gui}
Ubuntu icons: ${enable_ubuntu}
+1
View File
@@ -16,6 +16,7 @@ src/gamma-dummy.c
src/location-geoclue.c
src/location-geoclue2.c
src/location-corelocation.m
src/location-manual.c
src/redshift-gtk/statusicon.py
+15
View File
@@ -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
+38
View File
@@ -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 <http://www.gnu.org/licenses/>.
Copyright (c) 2014 Jon Lund Steffense <jonlst@gmail.com>
*/
#ifndef REDSHIFT_LOCATION_CORELOCATION_H
#define REDSHIFT_LOCATION_CORELOCATION_H
#include <stdio.h>
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 */
+163
View File
@@ -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 <http://www.gnu.org/licenses/>.
Copyright (c) 2014 Jon Lund Steffensen <jonlst@gmail.com>
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#include "location-corelocation.h"
#include <stdio.h>
#ifdef ENABLE_NLS
# include <libintl.h>
# define _(s) gettext(s)
#else
# define _(s) s
#endif
@interface Delegate : NSObject <CLLocationManagerDelegate>
@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;
}
+18
View File
@@ -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",