mirror of
https://github.com/CTCaer/RetroArch.git
synced 2024-12-11 20:44:24 +00:00
(Android/General) Add preliminary sensor support to libretro API /
add accelerometer support to Android input driver
This commit is contained in:
parent
dcb6a13031
commit
c0e02d3957
@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include <android/keycodes.h>
|
||||
#include <android/sensor.h>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include "input_autodetect.h"
|
||||
@ -37,6 +38,13 @@ typedef struct
|
||||
int16_t rx, ry;
|
||||
} analog_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
} sensor_t;
|
||||
|
||||
struct input_pointer
|
||||
{
|
||||
int16_t x, y;
|
||||
@ -62,12 +70,19 @@ typedef struct android_input
|
||||
uint64_t state[MAX_PADS];
|
||||
uint64_t keycode_lut[LAST_KEYCODE];
|
||||
analog_t analog_state[MAX_PADS];
|
||||
sensor_t accelerometer_state;
|
||||
unsigned accelerometer_event_rate;
|
||||
unsigned dpad_emulation[MAX_PLAYERS];
|
||||
struct input_pointer pointer[MAX_TOUCH];
|
||||
unsigned pointer_count;
|
||||
ASensorManager* sensorManager;
|
||||
const ASensor* accelerometerSensor;
|
||||
ASensorEventQueue* sensorEventQueue;
|
||||
uint64_t sensor_state_mask;
|
||||
} android_input_t;
|
||||
|
||||
void (*engine_handle_dpad)(void *data, AInputEvent*, size_t, int, char*, size_t, int, bool, unsigned);
|
||||
static void android_input_set_sensor_state(void *data, unsigned port, unsigned action, unsigned event_rate);
|
||||
|
||||
extern float AMotionEvent_getAxisValue(const AInputEvent* motion_event,
|
||||
int32_t axis, size_t pointer_index);
|
||||
@ -79,6 +94,7 @@ static typeof(AMotionEvent_getAxisValue) *p_AMotionEvent_getAxisValue;
|
||||
void engine_handle_cmd(void)
|
||||
{
|
||||
struct android_app *android_app = (struct android_app*)g_android;
|
||||
android_input_t *android = (android_input_t*)driver.input_data;
|
||||
int8_t cmd;
|
||||
|
||||
if (read(android_app->msgread, &cmd, sizeof(cmd)) != sizeof(cmd))
|
||||
@ -170,9 +186,18 @@ void engine_handle_cmd(void)
|
||||
|
||||
case APP_CMD_GAINED_FOCUS:
|
||||
g_extern.lifecycle_state &= ~(1ULL << RARCH_PAUSE_TOGGLE);
|
||||
break;
|
||||
|
||||
if (android->sensor_state_mask & (1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE)
|
||||
&& android->accelerometerSensor == NULL)
|
||||
android_input_set_sensor_state(android, 0, RETRO_SENSOR_ACCELEROMETER_ENABLE,
|
||||
android->accelerometer_event_rate);
|
||||
break;
|
||||
case APP_CMD_LOST_FOCUS:
|
||||
// Avoid draining battery while app is not being used
|
||||
if (android->sensor_state_mask & (1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE)
|
||||
&& android->accelerometerSensor != NULL)
|
||||
android_input_set_sensor_state(android, 0, RETRO_SENSOR_ACCELEROMETER_DISABLE,
|
||||
android->accelerometer_event_rate);
|
||||
break;
|
||||
|
||||
case APP_CMD_DESTROY:
|
||||
@ -1899,6 +1924,19 @@ static void android_input_poll(void *data)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (ident == LOOPER_ID_USER)
|
||||
{
|
||||
if (android->sensor_state_mask & (1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE))
|
||||
{
|
||||
ASensorEvent event;
|
||||
while (ASensorEventQueue_getEvents(android->sensorEventQueue, &event, 1) > 0)
|
||||
{
|
||||
android->accelerometer_state.x = event.acceleration.x;
|
||||
android->accelerometer_state.y = event.acceleration.y;
|
||||
android->accelerometer_state.z = event.acceleration.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ident == LOOPER_ID_MAIN)
|
||||
engine_handle_cmd();
|
||||
}
|
||||
@ -1950,6 +1988,19 @@ static int16_t android_input_state(void *data, const struct retro_keybind **bind
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
case RETRO_DEVICE_SENSOR_ACCELEROMETER:
|
||||
switch (id)
|
||||
{
|
||||
case RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_X:
|
||||
return android->accelerometer_state.x;
|
||||
case RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Y:
|
||||
return android->accelerometer_state.y;
|
||||
case RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Z:
|
||||
return android->accelerometer_state.z;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -1972,10 +2023,64 @@ static uint64_t android_input_get_capabilities(void *data)
|
||||
caps |= (1 << RETRO_DEVICE_JOYPAD);
|
||||
caps |= (1 << RETRO_DEVICE_POINTER);
|
||||
caps |= (1 << RETRO_DEVICE_ANALOG);
|
||||
caps |= (1 << RETRO_DEVICE_SENSOR_ACCELEROMETER);
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
static void android_input_enable_sensor_manager(void *data)
|
||||
{
|
||||
android_input_t *android = (android_input_t*)data;
|
||||
struct android_app *android_app = (struct android_app*)g_android;
|
||||
|
||||
android->sensorManager = ASensorManager_getInstance();
|
||||
android->accelerometerSensor = ASensorManager_getDefaultSensor(android->sensorManager,
|
||||
ASENSOR_TYPE_ACCELEROMETER);
|
||||
android->sensorEventQueue = ASensorManager_createEventQueue(android->sensorManager,
|
||||
android_app->looper, LOOPER_ID_USER, NULL, NULL);
|
||||
}
|
||||
|
||||
static void android_input_set_sensor_state(void *data, unsigned port, unsigned action, unsigned event_rate)
|
||||
{
|
||||
android_input_t *android = (android_input_t*)data;
|
||||
|
||||
if (event_rate == 0)
|
||||
event_rate = 60;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case RETRO_SENSOR_ACCELEROMETER_ENABLE:
|
||||
if (android->sensor_state_mask &
|
||||
(1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE))
|
||||
return;
|
||||
|
||||
if (android->accelerometerSensor == NULL)
|
||||
android_input_enable_sensor_manager(android);
|
||||
|
||||
ASensorEventQueue_enableSensor(android->sensorEventQueue,
|
||||
android->accelerometerSensor);
|
||||
|
||||
// events per second (in us).
|
||||
ASensorEventQueue_setEventRate(android->sensorEventQueue,
|
||||
android->accelerometerSensor, (1000L / event_rate) * 1000);
|
||||
|
||||
android->sensor_state_mask &= ~(1ULL << RETRO_SENSOR_ACCELEROMETER_DISABLE);
|
||||
android->sensor_state_mask |= (1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE);
|
||||
break;
|
||||
case RETRO_SENSOR_ACCELEROMETER_DISABLE:
|
||||
if (android->sensor_state_mask &
|
||||
(1ULL << RETRO_SENSOR_ACCELEROMETER_DISABLE))
|
||||
return;
|
||||
|
||||
ASensorEventQueue_disableSensor(android->sensorEventQueue,
|
||||
android->accelerometerSensor);
|
||||
|
||||
android->sensor_state_mask &= ~(1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE);
|
||||
android->sensor_state_mask |= (1ULL << RETRO_SENSOR_ACCELEROMETER_DISABLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const input_driver_t input_android = {
|
||||
android_input_init,
|
||||
android_input_poll,
|
||||
@ -1983,6 +2088,7 @@ const input_driver_t input_android = {
|
||||
android_input_key_pressed,
|
||||
android_input_free_input,
|
||||
android_input_set_keybinds,
|
||||
android_input_set_sensor_state,
|
||||
android_input_get_capabilities,
|
||||
"android_input",
|
||||
};
|
||||
|
@ -329,6 +329,7 @@ const input_driver_t input_apple = {
|
||||
apple_bind_button_pressed,
|
||||
apple_input_free_input,
|
||||
apple_input_set_keybinds,
|
||||
NULL,
|
||||
apple_input_get_capabilities,
|
||||
"apple_input",
|
||||
NULL,
|
||||
|
@ -859,6 +859,7 @@ const input_driver_t input_qnx = {
|
||||
qnx_input_key_pressed,
|
||||
qnx_input_free_input,
|
||||
qnx_input_set_keybinds,
|
||||
NULL,
|
||||
qnx_input_get_capabilities,
|
||||
"qnx_input",
|
||||
};
|
||||
|
1
driver.h
1
driver.h
@ -322,6 +322,7 @@ typedef struct input_driver
|
||||
bool (*key_pressed)(void *data, int key);
|
||||
void (*free)(void *data);
|
||||
void (*set_keybinds)(void *data, unsigned device, unsigned port, unsigned id, unsigned keybind_action);
|
||||
void (*set_sensor_state)(void *data, unsigned port, unsigned action, unsigned event_rate);
|
||||
uint64_t (*get_capabilities)(void *data);
|
||||
const char *ident;
|
||||
|
||||
|
@ -30,24 +30,18 @@
|
||||
struct android_app
|
||||
{
|
||||
ANativeActivity* activity;
|
||||
|
||||
ALooper* looper;
|
||||
AInputQueue* inputQueue;
|
||||
|
||||
AInputQueue* pendingInputQueue;
|
||||
ANativeWindow* window;
|
||||
int activityState;
|
||||
|
||||
ANativeWindow* pendingWindow;
|
||||
slock_t *mutex;
|
||||
scond_t *cond;
|
||||
|
||||
int activityState;
|
||||
int msgread;
|
||||
int msgwrite;
|
||||
|
||||
sthread_t *thread;
|
||||
|
||||
int running;
|
||||
AInputQueue* pendingInputQueue;
|
||||
ANativeWindow* pendingWindow;
|
||||
sthread_t *thread;
|
||||
char current_ime[PATH_MAX];
|
||||
};
|
||||
|
||||
|
@ -519,6 +519,7 @@ const input_driver_t input_gx = {
|
||||
gx_input_key_pressed,
|
||||
gx_input_free_input,
|
||||
gx_input_set_keybinds,
|
||||
NULL,
|
||||
gx_input_get_capabilities,
|
||||
"gx",
|
||||
};
|
||||
|
@ -367,6 +367,7 @@ const input_driver_t input_dinput = {
|
||||
dinput_key_pressed,
|
||||
dinput_free,
|
||||
NULL,
|
||||
NULL,
|
||||
dinput_get_capabilities,
|
||||
"dinput",
|
||||
|
||||
|
@ -339,6 +339,7 @@ const input_driver_t input_linuxraw = {
|
||||
linuxraw_bind_button_pressed,
|
||||
linuxraw_input_free,
|
||||
NULL,
|
||||
NULL,
|
||||
linuxraw_get_capabilities,
|
||||
"linuxraw",
|
||||
NULL,
|
||||
|
@ -154,6 +154,7 @@ const input_driver_t input_rwebinput = {
|
||||
rwebinput_bind_button_pressed,
|
||||
rwebinput_input_free,
|
||||
NULL,
|
||||
NULL,
|
||||
rwebinput_get_capabilities,
|
||||
"rwebinput",
|
||||
rwebinput_grab_mouse,
|
||||
|
@ -265,6 +265,7 @@ const input_driver_t input_sdl = {
|
||||
sdl_bind_button_pressed,
|
||||
sdl_input_free,
|
||||
NULL,
|
||||
NULL,
|
||||
sdl_get_capabilities,
|
||||
"sdl",
|
||||
NULL,
|
||||
|
@ -302,6 +302,7 @@ const input_driver_t input_x = {
|
||||
x_bind_button_pressed,
|
||||
x_input_free,
|
||||
NULL,
|
||||
NULL,
|
||||
x_input_get_capabilities,
|
||||
"x",
|
||||
x_grab_mouse,
|
||||
|
15
libretro.h
15
libretro.h
@ -94,6 +94,8 @@ extern "C" {
|
||||
// Eventually _PRESSED will return false for an index. No further presses are registered at this point.
|
||||
#define RETRO_DEVICE_POINTER 6
|
||||
|
||||
#define RETRO_DEVICE_SENSOR_ACCELEROMETER 7
|
||||
|
||||
// These device types are specializations of the base types above.
|
||||
// They should only be used in retro_set_controller_type() to inform libretro implementations
|
||||
// about use of a very specific device type.
|
||||
@ -150,6 +152,11 @@ extern "C" {
|
||||
#define RETRO_DEVICE_ID_POINTER_Y 1
|
||||
#define RETRO_DEVICE_ID_POINTER_PRESSED 2
|
||||
|
||||
// Id values for SENSOR types.
|
||||
#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_X 0
|
||||
#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Y 1
|
||||
#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Z 2
|
||||
|
||||
// Returned from retro_get_region().
|
||||
#define RETRO_REGION_NTSC 0
|
||||
#define RETRO_REGION_PAL 1
|
||||
@ -536,6 +543,14 @@ enum retro_rumble_effect
|
||||
RETRO_RUMBLE_DUMMY = INT_MAX
|
||||
};
|
||||
|
||||
enum retro_sensor_action
|
||||
{
|
||||
RETRO_SENSOR_ACCELEROMETER_ENABLE = 0,
|
||||
RETRO_SENSOR_ACCELEROMETER_DISABLE,
|
||||
};
|
||||
|
||||
typedef bool (*retro_set_sensor_state_t)(unsigned port, enum retro_sensor_action action, unsigned event_rate);
|
||||
|
||||
// Sets rumble state for joypad plugged in port 'port'. Rumble effects are controlled independently,
|
||||
// and setting e.g. strong rumble does not override weak rumble.
|
||||
// Strength has a range of [0, 0xffff].
|
||||
|
@ -393,6 +393,7 @@ const input_driver_t input_ps3 = {
|
||||
ps3_input_key_pressed,
|
||||
ps3_input_free_input,
|
||||
ps3_input_set_keybinds,
|
||||
NULL,
|
||||
ps3_input_get_capabilities,
|
||||
"ps3",
|
||||
};
|
||||
|
@ -177,12 +177,23 @@ static bool psp_input_key_pressed(void *data, int key)
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t psp_input_get_capabilities(void *data)
|
||||
{
|
||||
uint64_t caps = 0;
|
||||
|
||||
caps |= (1 << RETRO_DEVICE_JOYPAD);
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
const input_driver_t input_psp = {
|
||||
.init = psp_input_initialize,
|
||||
.poll = psp_input_poll,
|
||||
.input_state = psp_input_state,
|
||||
.key_pressed = psp_input_key_pressed,
|
||||
.free = psp_input_free_input,
|
||||
.set_keybinds = psp_input_set_keybinds,
|
||||
.ident = "psp",
|
||||
psp_input_initialize,
|
||||
psp_input_poll,
|
||||
psp_input_state,
|
||||
psp_input_key_pressed,
|
||||
psp_input_free_input,
|
||||
psp_input_set_keybinds,
|
||||
NULL,
|
||||
psp_input_get_capabilities,
|
||||
"psp",
|
||||
};
|
||||
|
@ -284,6 +284,7 @@ const input_driver_t input_xinput =
|
||||
xdk_input_key_pressed,
|
||||
xdk_input_free_input,
|
||||
xdk_input_set_keybinds,
|
||||
NULL,
|
||||
xdk_input_get_capabilities,
|
||||
"xinput"
|
||||
};
|
||||
|
@ -125,6 +125,7 @@ const input_driver_t input_xenon360 = {
|
||||
xenon360_input_key_pressed,
|
||||
xenon360_input_free_input,
|
||||
xenon360_input_set_keybinds,
|
||||
NULL,
|
||||
xenon360_input_get_capabilities,
|
||||
"xenon360",
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user