From b1503c6fc03e712cf9aaf86603f7de4f9b338eea Mon Sep 17 00:00:00 2001 From: Eric Warmenhoven Date: Sun, 21 May 2023 03:21:34 -0400 Subject: [PATCH] Add accelerometer and gyroscope sensors to iOS --- griffin/griffin.c | 2 - griffin/griffin_objc.m | 2 + .../drivers/{cocoa_input.c => cocoa_input.m} | 130 +++++++++++++++++- .../RetroArch_iOS13.xcodeproj/project.pbxproj | 6 +- ui/drivers/cocoa/cocoa_common.m | 15 +- ui/drivers/ui_cocoatouch.m | 4 +- 6 files changed, 146 insertions(+), 13 deletions(-) rename input/drivers/{cocoa_input.c => cocoa_input.m} (84%) diff --git a/griffin/griffin.c b/griffin/griffin.c index 9e7eb0bf65..466741ca01 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -710,8 +710,6 @@ INPUT #elif defined(ORBIS) #include "../input/drivers/ps4_input.c" #include "../input/drivers_joypad/ps4_joypad.c" -#elif defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL) -#include "../input/drivers/cocoa_input.c" #elif defined(_3DS) #include "../input/drivers/ctr_input.c" #include "../input/drivers_joypad/ctr_joypad.c" diff --git a/griffin/griffin_objc.m b/griffin/griffin_objc.m index 725204e24e..7bd6a385f6 100644 --- a/griffin/griffin_objc.m +++ b/griffin/griffin_objc.m @@ -43,6 +43,8 @@ #include "../ui/drivers/ui_cocoatouch.m" #endif +#include "../input/drivers/cocoa_input.m" + #endif #ifdef HAVE_MFI diff --git a/input/drivers/cocoa_input.c b/input/drivers/cocoa_input.m similarity index 84% rename from input/drivers/cocoa_input.c rename to input/drivers/cocoa_input.m index a9cabd5b45..fd0a9274ad 100644 --- a/input/drivers/cocoa_input.c +++ b/input/drivers/cocoa_input.m @@ -32,6 +32,14 @@ #include "../drivers_keyboard/keyboard_event_apple.h" +#ifdef HAVE_COREMOTION +#import +static CMMotionManager *motionManager; +#endif +#ifdef HAVE_MFI +#import +#endif + /* TODO/FIXME - * fix game focus toggle */ @@ -340,6 +348,12 @@ void apple_input_keyboard_event(bool down, static void *cocoa_input_init(const char *joypad_driver) { +#ifdef HAVE_COREMOTION + if (@available(macOS 10.15, *)) + if (!motionManager) + motionManager = [[CMMotionManager alloc] init]; +#endif + cocoa_input_data_t *apple = (cocoa_input_data_t*)calloc(1, sizeof(*apple)); if (!apple) return NULL; @@ -602,13 +616,125 @@ static uint64_t cocoa_input_get_capabilities(void *data) | (1 << RETRO_DEVICE_ANALOG); } +static bool cocoa_input_set_sensor_state(void *data, unsigned port, + enum retro_sensor_action action, unsigned rate) +{ + if (action != RETRO_SENSOR_ACCELEROMETER_ENABLE && + action != RETRO_SENSOR_ACCELEROMETER_DISABLE && + action != RETRO_SENSOR_GYROSCOPE_ENABLE && + action != RETRO_SENSOR_GYROSCOPE_DISABLE) + return false; + +#ifdef HAVE_MFI + if (@available(iOS 14.0, macOS 11.0, *)) { + for (GCController *controller in [GCController controllers]) + { + if (!controller || controller.playerIndex != port) + continue; + if (!controller.motion) + break; + if (controller.motion.sensorsRequireManualActivation) + { + // this is a bug, we assume if you turn on/off either you want both on/off + if (action == RETRO_SENSOR_ACCELEROMETER_ENABLE || action == RETRO_SENSOR_GYROSCOPE_ENABLE) + controller.motion.sensorsActive = YES; + else + controller.motion.sensorsActive = NO; + } + // no such thing as update interval for GCController? + return true; + } + } +#endif + +#ifdef HAVE_COREMOTION + if (port != 0) + return false; + + if (!motionManager || !motionManager.deviceMotionAvailable) + return false; + + if (action == RETRO_SENSOR_ACCELEROMETER_ENABLE || action == RETRO_SENSOR_GYROSCOPE_ENABLE) + { + if (!motionManager.deviceMotionActive) + [motionManager startDeviceMotionUpdates]; + motionManager.deviceMotionUpdateInterval = 1.0f / (float)rate; + } + else + { + if (motionManager.deviceMotionActive) + [motionManager stopDeviceMotionUpdates]; + } + + return true; +#else + return false; +#endif +} + +static float cocoa_input_get_sensor_input(void *data, unsigned port, unsigned id) +{ +#ifdef HAVE_MFI + if (@available(iOS 14.0, *)) { + for (GCController *controller in [GCController controllers]) + { + if (!controller || controller.playerIndex != port) + continue; + if (!controller.motion) + break; + switch (id) + { + case RETRO_SENSOR_ACCELEROMETER_X: + return controller.motion.userAcceleration.x; + case RETRO_SENSOR_ACCELEROMETER_Y: + return controller.motion.userAcceleration.y; + case RETRO_SENSOR_ACCELEROMETER_Z: + return controller.motion.userAcceleration.z; + case RETRO_SENSOR_GYROSCOPE_X: + return controller.motion.rotationRate.x; + case RETRO_SENSOR_GYROSCOPE_Y: + return controller.motion.rotationRate.y; + case RETRO_SENSOR_GYROSCOPE_Z: + return controller.motion.rotationRate.z; + } + } + } +#endif + +#ifdef HAVE_COREMOTION + if (port != 0) + return 0.0f; + + if (!motionManager || !motionManager.deviceMotionActive) + return 0.0f; + + switch (id) + { + case RETRO_SENSOR_ACCELEROMETER_X: + return motionManager.deviceMotion.userAcceleration.x; + case RETRO_SENSOR_ACCELEROMETER_Y: + return motionManager.deviceMotion.userAcceleration.y; + case RETRO_SENSOR_ACCELEROMETER_Z: + return motionManager.deviceMotion.userAcceleration.z; + case RETRO_SENSOR_GYROSCOPE_X: + return motionManager.deviceMotion.rotationRate.x; + case RETRO_SENSOR_GYROSCOPE_Y: + return motionManager.deviceMotion.rotationRate.y; + case RETRO_SENSOR_GYROSCOPE_Z: + return motionManager.deviceMotion.rotationRate.z; + } +#endif + + return 0.0f; +} + input_driver_t input_cocoa = { cocoa_input_init, cocoa_input_poll, cocoa_input_state, cocoa_input_free, - NULL, - NULL, + cocoa_input_set_sensor_state, + cocoa_input_get_sensor_input, cocoa_input_get_capabilities, "cocoa", NULL, /* grab_mouse */ diff --git a/pkg/apple/RetroArch_iOS13.xcodeproj/project.pbxproj b/pkg/apple/RetroArch_iOS13.xcodeproj/project.pbxproj index 5ee312d470..97e385521d 100644 --- a/pkg/apple/RetroArch_iOS13.xcodeproj/project.pbxproj +++ b/pkg/apple/RetroArch_iOS13.xcodeproj/project.pbxproj @@ -1601,6 +1601,7 @@ "-DHAVE_COCOA_METAL", "-DHAVE_CONFIGFILE", "-DHAVE_COREAUDIO", + "-DHAVE_COREMOTION", "-DHAVE_DSP_FILTER", "-DHAVE_DYNAMIC", "-DHAVE_FILTERS_BUILTIN", @@ -1743,6 +1744,7 @@ "-DHAVE_COCOA_METAL", "-DHAVE_CONFIGFILE", "-DHAVE_COREAUDIO", + "-DHAVE_COREMOTION", "-DHAVE_DSP_FILTER", "-DHAVE_DYNAMIC", "-DHAVE_FILTERS_BUILTIN", @@ -2197,9 +2199,9 @@ IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); + LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/iOS/modules"; MARKETING_VERSION = 1.15.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -2267,9 +2269,9 @@ IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", - "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); + LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/iOS/modules"; MARKETING_VERSION = 1.15.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; diff --git a/ui/drivers/cocoa/cocoa_common.m b/ui/drivers/cocoa/cocoa_common.m index ec1fa4bf6d..ad49007018 100644 --- a/ui/drivers/cocoa/cocoa_common.m +++ b/ui/drivers/cocoa/cocoa_common.m @@ -135,8 +135,9 @@ void *glkitview_init(void); return !controllers[0].extendedGamepad; // are these presses that controllers send? - if (type == UIPressTypePageUp || type == UIPressTypePageDown) - return true; + if (@available(tvOS 14.3, *)) + if (type == UIPressTypePageUp || type == UIPressTypePageDown) + return true; bool microPress = false; bool extendedPress = false; @@ -844,16 +845,20 @@ bool cocoa_get_metrics( } #endif -config_file_t *open_userdefaults_config_file() +config_file_t *open_userdefaults_config_file(void) { config_file_t *conf = NULL; NSString *backup = [NSUserDefaults.standardUserDefaults stringForKey:@FILE_PATH_MAIN_CONFIG]; if ([backup length] >= 0) - conf = config_file_new_from_string([backup cStringUsingEncoding:NSUTF8StringEncoding], path_get(RARCH_PATH_CONFIG)); + { + char *str = strdup(backup.UTF8String); + conf = config_file_new_from_string(str, path_get(RARCH_PATH_CONFIG)); + free(str); + } return conf; } -void write_userdefaults_config_file() +void write_userdefaults_config_file(void) { NSString *conf = [NSString stringWithContentsOfFile:[NSString stringWithUTF8String:path_get(RARCH_PATH_CONFIG)] encoding:NSUTF8StringEncoding diff --git a/ui/drivers/ui_cocoatouch.m b/ui/drivers/ui_cocoatouch.m index 4a6ee625d4..492997df25 100644 --- a/ui/drivers/ui_cocoatouch.m +++ b/ui/drivers/ui_cocoatouch.m @@ -73,7 +73,7 @@ static void rarch_draw_observer(CFRunLoopObserverRef observer, CFRunLoopWakeUp(CFRunLoopGetMain()); } -void rarch_start_draw_observer() +void rarch_start_draw_observer(void) { if (iterate_observer && CFRunLoopObserverIsValid(iterate_observer)) return; @@ -85,7 +85,7 @@ void rarch_start_draw_observer() CFRunLoopAddObserver(CFRunLoopGetMain(), iterate_observer, kCFRunLoopCommonModes); } -void rarch_stop_draw_observer() +void rarch_stop_draw_observer(void) { if (!iterate_observer || !CFRunLoopObserverIsValid(iterate_observer)) return;