Skip to content

Commit 9438d70

Browse files
authored
Add CoreLocation location driver for macOS and iOS (#17591)
Signed-off-by: Joseph Mattiello <[email protected]>
1 parent 73abadd commit 9438d70

File tree

4 files changed

+154
-1
lines changed

4 files changed

+154
-1
lines changed

configuration.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,8 @@ static const enum wifi_driver_enum WIFI_DEFAULT_DRIVER = WIFI_NULL;
746746

747747
#if defined(ANDROID)
748748
static const enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_ANDROID;
749+
#elif defined(HAVE_CORELOCATION)
750+
static const enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_CORELOCATION;
749751
#else
750752
static const enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_NULL;
751753
#endif

griffin/griffin.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,8 @@ LOCATION
839839
============================================================ */
840840
#if defined(ANDROID)
841841
#include "../location/drivers/android.c"
842+
#elif defined(HAVE_CORELOCATION)
843+
#include "../location/drivers/corelocation.m"
842844
#endif
843845

844846
/*============================================================
@@ -1695,4 +1697,4 @@ GAME AI
16951697
============================================================ */
16961698
#if defined(HAVE_GAME_AI)
16971699
#include "../ai/game_ai.c"
1698-
#endif
1700+
#endif

location/drivers/corelocation.m

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/* RetroArch - A frontend for libretro.
2+
* Copyright (C) 2025 - Joseph Mattiello
3+
*
4+
* RetroArch is free software: you can redistribute it and/or modify it under the terms
5+
* of the GNU General Public License as published by the Free Software Found-
6+
* ation, either version 3 of the License, or (at your option) any later version.
7+
*
8+
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9+
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10+
* PURPOSE. See the GNU General Public License for more details.
11+
*
12+
* You should have received a copy of the GNU General Public License along with RetroArch.
13+
* If not, see <http://www.gnu.org/licenses/>.
14+
*/
15+
16+
#import <CoreLocation/CoreLocation.h>
17+
#include "../../location_driver.h"
18+
#include "../../retroarch.h"
19+
#include "../../verbosity.h"
20+
@interface CoreLocationManager : NSObject <CLLocationManagerDelegate>
21+
@property (strong, nonatomic) CLLocationManager *locationManager;
22+
@property (assign) double latitude;
23+
@property (assign) double longitude;
24+
@property (assign) bool authorized;
25+
@end
26+
27+
@implementation CoreLocationManager
28+
29+
+ (instancetype)sharedInstance {
30+
static CoreLocationManager *sharedInstance = nil;
31+
static dispatch_once_t onceToken;
32+
dispatch_once(&onceToken, ^{
33+
sharedInstance = [[CoreLocationManager alloc] init];
34+
});
35+
return sharedInstance;
36+
}
37+
38+
- (instancetype)init {
39+
self = [super init];
40+
if (self) {
41+
_locationManager = [[CLLocationManager alloc] init];
42+
_locationManager.delegate = self;
43+
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
44+
_authorized = false;
45+
}
46+
return self;
47+
}
48+
49+
- (void)requestAuthorization {
50+
if (_locationManager.authorizationStatus == kCLAuthorizationStatusNotDetermined) {
51+
[_locationManager requestWhenInUseAuthorization];
52+
}
53+
}
54+
55+
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
56+
CLLocation *location = [locations lastObject];
57+
self.latitude = location.coordinate.latitude;
58+
self.longitude = location.coordinate.longitude;
59+
}
60+
61+
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
62+
RARCH_WARN("[LOCATION]: Location manager failed with error: %s\n", error.description.UTF8String);
63+
NSLog(@"Location manager failed with error: %@", error);
64+
}
65+
66+
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
67+
self.authorized = (status == kCLAuthorizationStatusAuthorizedWhenInUse ||
68+
status == kCLAuthorizationStatusAuthorizedAlways);
69+
}
70+
71+
@end
72+
73+
typedef struct corelocation {
74+
CoreLocationManager *manager;
75+
} corelocation_t;
76+
77+
static void *corelocation_init(void) {
78+
corelocation_t *corelocation = (corelocation_t*)calloc(1, sizeof(*corelocation));
79+
if (!corelocation)
80+
return NULL;
81+
82+
corelocation->manager = [CoreLocationManager sharedInstance];
83+
[corelocation->manager requestAuthorization];
84+
85+
return corelocation;
86+
}
87+
88+
static void corelocation_free(void *data) {
89+
corelocation_t *corelocation = (corelocation_t*)data;
90+
if (!corelocation)
91+
return;
92+
93+
free(corelocation);
94+
}
95+
96+
static bool corelocation_start(void *data) {
97+
corelocation_t *corelocation = (corelocation_t*)data;
98+
if (!corelocation || !corelocation->manager.authorized)
99+
return false;
100+
101+
#if !TARGET_OS_TV
102+
[corelocation->manager.locationManager startUpdatingLocation];
103+
#endif
104+
return true;
105+
}
106+
107+
static void corelocation_stop(void *data) {
108+
corelocation_t *corelocation = (corelocation_t*)data;
109+
if (!corelocation)
110+
return;
111+
112+
[corelocation->manager.locationManager stopUpdatingLocation];
113+
}
114+
115+
static bool corelocation_get_position(void *data, double *lat, double *lon,
116+
double *horiz_accuracy, double *vert_accuracy) {
117+
corelocation_t *corelocation = (corelocation_t*)data;
118+
if (!corelocation || !corelocation->manager.authorized)
119+
return false;
120+
121+
*lat = corelocation->manager.latitude;
122+
*lon = corelocation->manager.longitude;
123+
*horiz_accuracy = 0.0; // CoreLocation doesn't provide this directly
124+
*vert_accuracy = 0.0; // CoreLocation doesn't provide this directly
125+
return true;
126+
}
127+
128+
static void corelocation_set_interval(void *data, unsigned interval_ms,
129+
unsigned interval_distance) {
130+
corelocation_t *corelocation = (corelocation_t*)data;
131+
if (!corelocation)
132+
return;
133+
134+
corelocation->manager.locationManager.distanceFilter = interval_distance;
135+
corelocation->manager.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
136+
}
137+
138+
location_driver_t location_corelocation = {
139+
corelocation_init,
140+
corelocation_free,
141+
corelocation_start,
142+
corelocation_stop,
143+
corelocation_get_position,
144+
corelocation_set_interval,
145+
"corelocation",
146+
};

retroarch.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,9 @@ static location_driver_t location_null = {
360360
static const location_driver_t *location_drivers[] = {
361361
#ifdef ANDROID
362362
&location_android,
363+
#endif
364+
#ifdef HAVE_CORELOCATION
365+
&location_corelocation,
363366
#endif
364367
&location_null,
365368
NULL,

0 commit comments

Comments
 (0)