From 273ad4c9ee4969945d4b1ee8dd892864642305fe Mon Sep 17 00:00:00 2001 From: Jonathan De Wachter Date: Sun, 20 Apr 2014 12:05:06 +0200 Subject: [PATCH] [Android] Adapted sensor implementation --- src/SFML/Window/Android/SensorImpl.cpp | 134 ++++++++++++++++++++++--- src/SFML/Window/Android/SensorImpl.hpp | 36 +++++++ 2 files changed, 157 insertions(+), 13 deletions(-) diff --git a/src/SFML/Window/Android/SensorImpl.cpp b/src/SFML/Window/Android/SensorImpl.cpp index be5e439c..11e53a8e 100644 --- a/src/SFML/Window/Android/SensorImpl.cpp +++ b/src/SFML/Window/Android/SensorImpl.cpp @@ -26,6 +26,16 @@ // Headers //////////////////////////////////////////////////////////// #include +#include +#include + +namespace +{ + ALooper* looper; + ASensorManager* sensorManager; + ASensorEventQueue* sensorEventQueue; + sf::Vector3f sensorData[sf::Sensor::Count]; +} namespace sf @@ -35,52 +45,150 @@ namespace priv //////////////////////////////////////////////////////////// void SensorImpl::initialize() { - // To be implemented + // Get the looper associated with this thread + looper = ALooper_forThread(); + + // Get the unique sensor manager + sensorManager = ASensorManager_getInstance(); + + // Create the sensor events queue and attach it to the looper + sensorEventQueue = ASensorManager_createEventQueue(sensorManager, looper, + 1, &processSensorEvents, NULL); } //////////////////////////////////////////////////////////// void SensorImpl::cleanup() { - // To be implemented + // Detach the sensor events queue from the looper and destroy it + ASensorManager_destroyEventQueue(sensorManager, sensorEventQueue); } //////////////////////////////////////////////////////////// -bool SensorImpl::isAvailable(Sensor::Type /*sensor*/) +bool SensorImpl::isAvailable(Sensor::Type sensor) { - // To be implemented - return false; + const ASensor* available = getDefaultSensor(sensor); + + return available? true : false; } //////////////////////////////////////////////////////////// -bool SensorImpl::open(Sensor::Type /*sensor*/) +bool SensorImpl::open(Sensor::Type sensor) { - // To be implemented - return false; + // Get the default sensor matching the type + m_sensor = getDefaultSensor(sensor); + + // Sensor not available, stop here + if (!m_sensor) + return false; + + // Get the minimum delay allowed between events + Time minimumDelay = microseconds(ASensor_getMinDelay(m_sensor)); + + // Set the event rate (not to consume too much battery) + ASensorEventQueue_setEventRate(sensorEventQueue, m_sensor, minimumDelay.asMicroseconds()); + + // Disable the sensor by default + setEnabled(true); + + // Save the index of the sensor + m_index = static_cast(sensor); + + return true; } //////////////////////////////////////////////////////////// void SensorImpl::close() { - // To be implemented + // Nothing to do } //////////////////////////////////////////////////////////// Vector3f SensorImpl::update() { - // To be implemented - return Vector3f(0, 0, 0); + // Update our sensor data list + ALooper_pollAll(0, NULL, NULL, NULL); + + return sensorData[m_index]; } //////////////////////////////////////////////////////////// -void SensorImpl::setEnabled(bool /*enabled*/) +void SensorImpl::setEnabled(bool enabled) { - // To be implemented + if (enabled) + ASensorEventQueue_enableSensor(sensorEventQueue, m_sensor); + else + ASensorEventQueue_disableSensor(sensorEventQueue, m_sensor); +} + + +//////////////////////////////////////////////////////////// +ASensor const* SensorImpl::getDefaultSensor(Sensor::Type sensor) +{ + // These sensors are unavailable from the Android C API + if ((sensor == Sensor::Gravity) || + (sensor == Sensor::UserAcceleration) || + (sensor == Sensor::Orientation)) + return NULL; + + // Find the Android sensor type + static int types[] = {ASENSOR_TYPE_ACCELEROMETER, + ASENSOR_TYPE_GYROSCOPE, ASENSOR_TYPE_MAGNETIC_FIELD}; + + int type = types[sensor]; + + // Retrive the default sensor matching this type + return ASensorManager_getDefaultSensor(sensorManager, type); +} + + +//////////////////////////////////////////////////////////// +int SensorImpl::processSensorEvents(int fd, int events, void* data) +{ + ASensorEvent event; + + while (ASensorEventQueue_getEvents(sensorEventQueue, &event, 1) > 0) + { + unsigned int type = Sensor::Count; + Vector3f data; + + switch (event.type) + { + case ASENSOR_TYPE_ACCELEROMETER: + type = Sensor::Accelerometer; + data.x = event.acceleration.x; + data.y = event.acceleration.y; + data.z = event.acceleration.z; + break; + + case ASENSOR_TYPE_GYROSCOPE: + type = Sensor::Gyroscope; + data.x = event.vector.x; + data.y = event.vector.y; + data.z = event.vector.z; + break; + + case ASENSOR_TYPE_MAGNETIC_FIELD: + type = Sensor::Magnetometer; + data.x = event.magnetic.x; + data.y = event.magnetic.y; + data.z = event.magnetic.z; + break; + } + + // An unknown sensor event has been detected, we don't know how to process it + if (type == Sensor::Count) + continue; + + sensorData[type] = data; + } + + return 1; } } // namespace priv diff --git a/src/SFML/Window/Android/SensorImpl.hpp b/src/SFML/Window/Android/SensorImpl.hpp index 49386dd0..4fdd791c 100644 --- a/src/SFML/Window/Android/SensorImpl.hpp +++ b/src/SFML/Window/Android/SensorImpl.hpp @@ -25,6 +25,12 @@ #ifndef SFML_SENSORIMPLANDROID_HPP #define SFML_SENSORIMPLANDROID_HPP +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + namespace sf { @@ -91,6 +97,36 @@ public : /// //////////////////////////////////////////////////////////// void setEnabled(bool enabled); + +private : + + //////////////////////////////////////////////////////////// + /// \brief Get the default Android sensor matching the sensor type + /// + /// \param type Type of the sensor + /// + /// \return The default Android sensor, NULL otherwise + /// + //////////////////////////////////////////////////////////// + static ASensor const* getDefaultSensor(Sensor::Type sensor); + + //////////////////////////////////////////////////////////// + /// \brief Process the pending sensor data available and add them to our lists + /// + /// \param fd File descriptor + /// \param events Bitmask of the poll events that were triggered + /// \param data Data pointer supplied + /// + /// \return Whether it should continue (1) or unregister the callback (0) + /// + //////////////////////////////////////////////////////////// + static int processSensorEvents(int fd, int events, void* data); + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + const ASensor* m_sensor; ///< Android sensor structure + unsigned int m_index; ///< Index of the sensor }; } // namespace priv