(Android/General) Add preliminary sensor support to libretro API /

add accelerometer support to Android input driver
This commit is contained in:
twinaphex 2013-11-03 00:27:58 +01:00
parent dcb6a13031
commit c0e02d3957
16 changed files with 156 additions and 18 deletions

View File

@ -16,6 +16,7 @@
*/ */
#include <android/keycodes.h> #include <android/keycodes.h>
#include <android/sensor.h>
#include <unistd.h> #include <unistd.h>
#include <dlfcn.h> #include <dlfcn.h>
#include "input_autodetect.h" #include "input_autodetect.h"
@ -37,6 +38,13 @@ typedef struct
int16_t rx, ry; int16_t rx, ry;
} analog_t; } analog_t;
typedef struct
{
float x;
float y;
float z;
} sensor_t;
struct input_pointer struct input_pointer
{ {
int16_t x, y; int16_t x, y;
@ -62,12 +70,19 @@ typedef struct android_input
uint64_t state[MAX_PADS]; uint64_t state[MAX_PADS];
uint64_t keycode_lut[LAST_KEYCODE]; uint64_t keycode_lut[LAST_KEYCODE];
analog_t analog_state[MAX_PADS]; analog_t analog_state[MAX_PADS];
sensor_t accelerometer_state;
unsigned accelerometer_event_rate;
unsigned dpad_emulation[MAX_PLAYERS]; unsigned dpad_emulation[MAX_PLAYERS];
struct input_pointer pointer[MAX_TOUCH]; struct input_pointer pointer[MAX_TOUCH];
unsigned pointer_count; unsigned pointer_count;
ASensorManager* sensorManager;
const ASensor* accelerometerSensor;
ASensorEventQueue* sensorEventQueue;
uint64_t sensor_state_mask;
} android_input_t; } android_input_t;
void (*engine_handle_dpad)(void *data, AInputEvent*, size_t, int, char*, size_t, int, bool, unsigned); 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, extern float AMotionEvent_getAxisValue(const AInputEvent* motion_event,
int32_t axis, size_t pointer_index); int32_t axis, size_t pointer_index);
@ -79,6 +94,7 @@ static typeof(AMotionEvent_getAxisValue) *p_AMotionEvent_getAxisValue;
void engine_handle_cmd(void) void engine_handle_cmd(void)
{ {
struct android_app *android_app = (struct android_app*)g_android; struct android_app *android_app = (struct android_app*)g_android;
android_input_t *android = (android_input_t*)driver.input_data;
int8_t cmd; int8_t cmd;
if (read(android_app->msgread, &cmd, sizeof(cmd)) != sizeof(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: case APP_CMD_GAINED_FOCUS:
g_extern.lifecycle_state &= ~(1ULL << RARCH_PAUSE_TOGGLE); 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: 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; break;
case APP_CMD_DESTROY: case APP_CMD_DESTROY:
@ -1899,6 +1924,19 @@ static void android_input_poll(void *data)
#endif #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) else if (ident == LOOPER_ID_MAIN)
engine_handle_cmd(); engine_handle_cmd();
} }
@ -1950,6 +1988,19 @@ static int16_t android_input_state(void *data, const struct retro_keybind **bind
default: default:
return 0; 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: default:
return 0; return 0;
} }
@ -1972,10 +2023,64 @@ static uint64_t android_input_get_capabilities(void *data)
caps |= (1 << RETRO_DEVICE_JOYPAD); caps |= (1 << RETRO_DEVICE_JOYPAD);
caps |= (1 << RETRO_DEVICE_POINTER); caps |= (1 << RETRO_DEVICE_POINTER);
caps |= (1 << RETRO_DEVICE_ANALOG); caps |= (1 << RETRO_DEVICE_ANALOG);
caps |= (1 << RETRO_DEVICE_SENSOR_ACCELEROMETER);
return caps; 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 = { const input_driver_t input_android = {
android_input_init, android_input_init,
android_input_poll, android_input_poll,
@ -1983,6 +2088,7 @@ const input_driver_t input_android = {
android_input_key_pressed, android_input_key_pressed,
android_input_free_input, android_input_free_input,
android_input_set_keybinds, android_input_set_keybinds,
android_input_set_sensor_state,
android_input_get_capabilities, android_input_get_capabilities,
"android_input", "android_input",
}; };

View File

@ -329,6 +329,7 @@ const input_driver_t input_apple = {
apple_bind_button_pressed, apple_bind_button_pressed,
apple_input_free_input, apple_input_free_input,
apple_input_set_keybinds, apple_input_set_keybinds,
NULL,
apple_input_get_capabilities, apple_input_get_capabilities,
"apple_input", "apple_input",
NULL, NULL,

View File

@ -859,6 +859,7 @@ const input_driver_t input_qnx = {
qnx_input_key_pressed, qnx_input_key_pressed,
qnx_input_free_input, qnx_input_free_input,
qnx_input_set_keybinds, qnx_input_set_keybinds,
NULL,
qnx_input_get_capabilities, qnx_input_get_capabilities,
"qnx_input", "qnx_input",
}; };

View File

@ -322,6 +322,7 @@ typedef struct input_driver
bool (*key_pressed)(void *data, int key); bool (*key_pressed)(void *data, int key);
void (*free)(void *data); void (*free)(void *data);
void (*set_keybinds)(void *data, unsigned device, unsigned port, unsigned id, unsigned keybind_action); 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); uint64_t (*get_capabilities)(void *data);
const char *ident; const char *ident;

View File

@ -30,24 +30,18 @@
struct android_app struct android_app
{ {
ANativeActivity* activity; ANativeActivity* activity;
ALooper* looper; ALooper* looper;
AInputQueue* inputQueue; AInputQueue* inputQueue;
AInputQueue* pendingInputQueue;
ANativeWindow* window; ANativeWindow* window;
int activityState; ANativeWindow* pendingWindow;
slock_t *mutex; slock_t *mutex;
scond_t *cond; scond_t *cond;
int activityState;
int msgread; int msgread;
int msgwrite; int msgwrite;
sthread_t *thread;
int running; int running;
AInputQueue* pendingInputQueue; sthread_t *thread;
ANativeWindow* pendingWindow;
char current_ime[PATH_MAX]; char current_ime[PATH_MAX];
}; };

View File

@ -519,6 +519,7 @@ const input_driver_t input_gx = {
gx_input_key_pressed, gx_input_key_pressed,
gx_input_free_input, gx_input_free_input,
gx_input_set_keybinds, gx_input_set_keybinds,
NULL,
gx_input_get_capabilities, gx_input_get_capabilities,
"gx", "gx",
}; };

View File

@ -367,6 +367,7 @@ const input_driver_t input_dinput = {
dinput_key_pressed, dinput_key_pressed,
dinput_free, dinput_free,
NULL, NULL,
NULL,
dinput_get_capabilities, dinput_get_capabilities,
"dinput", "dinput",

View File

@ -339,6 +339,7 @@ const input_driver_t input_linuxraw = {
linuxraw_bind_button_pressed, linuxraw_bind_button_pressed,
linuxraw_input_free, linuxraw_input_free,
NULL, NULL,
NULL,
linuxraw_get_capabilities, linuxraw_get_capabilities,
"linuxraw", "linuxraw",
NULL, NULL,

View File

@ -154,6 +154,7 @@ const input_driver_t input_rwebinput = {
rwebinput_bind_button_pressed, rwebinput_bind_button_pressed,
rwebinput_input_free, rwebinput_input_free,
NULL, NULL,
NULL,
rwebinput_get_capabilities, rwebinput_get_capabilities,
"rwebinput", "rwebinput",
rwebinput_grab_mouse, rwebinput_grab_mouse,

View File

@ -265,6 +265,7 @@ const input_driver_t input_sdl = {
sdl_bind_button_pressed, sdl_bind_button_pressed,
sdl_input_free, sdl_input_free,
NULL, NULL,
NULL,
sdl_get_capabilities, sdl_get_capabilities,
"sdl", "sdl",
NULL, NULL,

View File

@ -302,6 +302,7 @@ const input_driver_t input_x = {
x_bind_button_pressed, x_bind_button_pressed,
x_input_free, x_input_free,
NULL, NULL,
NULL,
x_input_get_capabilities, x_input_get_capabilities,
"x", "x",
x_grab_mouse, x_grab_mouse,

View File

@ -94,6 +94,8 @@ extern "C" {
// Eventually _PRESSED will return false for an index. No further presses are registered at this point. // Eventually _PRESSED will return false for an index. No further presses are registered at this point.
#define RETRO_DEVICE_POINTER 6 #define RETRO_DEVICE_POINTER 6
#define RETRO_DEVICE_SENSOR_ACCELEROMETER 7
// These device types are specializations of the base types above. // These device types are specializations of the base types above.
// They should only be used in retro_set_controller_type() to inform libretro implementations // They should only be used in retro_set_controller_type() to inform libretro implementations
// about use of a very specific device type. // 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_Y 1
#define RETRO_DEVICE_ID_POINTER_PRESSED 2 #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(). // Returned from retro_get_region().
#define RETRO_REGION_NTSC 0 #define RETRO_REGION_NTSC 0
#define RETRO_REGION_PAL 1 #define RETRO_REGION_PAL 1
@ -536,6 +543,14 @@ enum retro_rumble_effect
RETRO_RUMBLE_DUMMY = INT_MAX 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, // 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. // and setting e.g. strong rumble does not override weak rumble.
// Strength has a range of [0, 0xffff]. // Strength has a range of [0, 0xffff].

View File

@ -393,6 +393,7 @@ const input_driver_t input_ps3 = {
ps3_input_key_pressed, ps3_input_key_pressed,
ps3_input_free_input, ps3_input_free_input,
ps3_input_set_keybinds, ps3_input_set_keybinds,
NULL,
ps3_input_get_capabilities, ps3_input_get_capabilities,
"ps3", "ps3",
}; };

View File

@ -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 = { const input_driver_t input_psp = {
.init = psp_input_initialize, psp_input_initialize,
.poll = psp_input_poll, psp_input_poll,
.input_state = psp_input_state, psp_input_state,
.key_pressed = psp_input_key_pressed, psp_input_key_pressed,
.free = psp_input_free_input, psp_input_free_input,
.set_keybinds = psp_input_set_keybinds, psp_input_set_keybinds,
.ident = "psp", NULL,
psp_input_get_capabilities,
"psp",
}; };

View File

@ -284,6 +284,7 @@ const input_driver_t input_xinput =
xdk_input_key_pressed, xdk_input_key_pressed,
xdk_input_free_input, xdk_input_free_input,
xdk_input_set_keybinds, xdk_input_set_keybinds,
NULL,
xdk_input_get_capabilities, xdk_input_get_capabilities,
"xinput" "xinput"
}; };

View File

@ -125,6 +125,7 @@ const input_driver_t input_xenon360 = {
xenon360_input_key_pressed, xenon360_input_key_pressed,
xenon360_input_free_input, xenon360_input_free_input,
xenon360_input_set_keybinds, xenon360_input_set_keybinds,
NULL,
xenon360_input_get_capabilities, xenon360_input_get_capabilities,
"xenon360", "xenon360",
}; };