aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Lund Steffensen <jonlst@gmail.com>2014-12-06 15:32:50 -0500
committerJon Lund Steffensen <jonlst@gmail.com>2014-12-15 20:36:35 -0500
commit8839dcd530cbc8f5c7ae45a61d86bed05d2a6e8a (patch)
tree3a3e69b2711bfbde5c557192bf10ea544a4617a7
parentAdd Quartz (OSX) gamma adjustment method (diff)
downloadredshift-ng-8839dcd530cbc8f5c7ae45a61d86bed05d2a6e8a.tar.gz
redshift-ng-8839dcd530cbc8f5c7ae45a61d86bed05d2a6e8a.tar.bz2
redshift-ng-8839dcd530cbc8f5c7ae45a61d86bed05d2a6e8a.tar.xz
Add CoreLocation (OSX) location provider
Similarly to the Geoclue provider, the CoreLocation provider only requests the location on startup.
-rw-r--r--configure.ac68
-rw-r--r--po/POTFILES.in1
-rw-r--r--src/Makefile.am15
-rw-r--r--src/location-corelocation.h38
-rw-r--r--src/location-corelocation.m163
-rw-r--r--src/redshift.c18
6 files changed, 303 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index b916ff6..3f46334 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index e9f1d82..ffaddb2 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -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
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 <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 */
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 <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;
+}
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 {
@@ -220,6 +224,20 @@ static const location_provider_t location_providers[] = {
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",
(location_provider_init_func *)location_manual_init,