1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2014 Romain Chanoir <romain.chanoir@viacesi.fr>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Access Android sensors
19 # Sensors are to be enabled when `App` is created.
20 # The following example enables all sensors.
21 # The events (`SensorEvent`, `ASensorAccelerometer`, `ASensorMagneticField`...)
22 # are sent to the `input` callback of `App`
28 # sensors_support_enabled = true
29 # accelerometer.enabled = true
30 # accelerometer.eventrate = 10000
31 # magnetic_field.enabled = true
32 # gyroscope.enabled = true
33 # light.enabled = true
34 # proximity.enabled = true
45 #include <android/sensor.h>
48 extern class ASensorType `{int`}
49 new accelerometer: ASensorType `{return ASENSOR_TYPE_ACCELEROMETER;`}
50 fun is_accelerometer
: Bool `{return self == ASENSOR_TYPE_ACCELEROMETER;`}
51 new magnetic_field: ASensorType `{return ASENSOR_TYPE_MAGNETIC_FIELD;`}
52 fun is_magnetic_field
: Bool `{return self == ASENSOR_TYPE_MAGNETIC_FIELD;`}
53 new gyroscope:ASensorType `{return ASENSOR_TYPE_GYROSCOPE;`}
54 fun is_gyroscope
: Bool `{ return self == ASENSOR_TYPE_GYROSCOPE;`}
55 new light: ASensorType `{return ASENSOR_TYPE_LIGHT;`}
56 fun is_light
: Bool `{return self == ASENSOR_TYPE_LIGHT;`}
57 new proximity: ASensorType `{return ASENSOR_TYPE_PROXIMITY;`}
58 fun is_proximity
:Bool `{return self == ASENSOR_TYPE_PROXIMITY;`}
62 extern class ASensorManager `{ASensorManager*`}
64 new get_instance
: ASensorManager `{return ASensorManager_getInstance();`}
66 # Returns the list of available sensors
67 fun get_sensor_list: Pointer `{
69 ASensorManager_getSensorList(self, list
);
73 # Create a new sensor event queue and associate it with a looper
74 fun create_event_queue(app: NativeAppGlue): ASensorEventQueue `{
75 return ASensorManager_createEventQueue(self, app-
>looper
, LOOPER_ID_USER, NULL, NULL);
78 # Returns the default sensor of the given type
79 fun get_default_sensor(sensortype: ASensorType): ASensor `{
80 return ASensorManager_getDefaultSensor(self, sensortype
);
83 # Destroys the event queue and free all resources associated to it
84 fun destroy_event_queue(queue: ASensorEventQueue) `{
85 ASensorManager_destroyEventQueue(self, queue
);
89 # Manages the sensors events
90 extern class ASensorEventQueue `{ASensorEventQueue*`}
92 # Enable the selected sensor, returns a negative value on error
93 fun enable_sensor
(sensor
: ASensor): Int `{
94 return ASensorEventQueue_enableSensor(self, sensor);
97 # Disable the selected sensor, returns a negative value on error
98 fun disable_sensor
(sensor
: ASensor): Int `{
99 return ASensorEventQueue_disableSensor(self, sensor);
102 # Set the delivery rate of events in microseconds for the given sensor
103 fun set_event_rate
(sensor
: ASensor, usec
: Int): Int `{
104 return ASensorEventQueue_setEventRate(self, sensor, usec);
106 # Returns 1 if the queue has events, 0 if it does not have events,
107 # and a negative value if there is an error
108 fun has_events
: Int `{
109 return ASensorEventQueue_hasEvents(self);
112 # Returns the next available events from the queue.
113 # Returns a negative value if no events are available or an error has occured
114 # otherwise the number of events returned
115 fun get_events
(events
: ASensorEvents, count
: Int): Int `{
116 return ASensorEventQueue_getEvents(self, events, (size_t)count);
120 # Extern class referencing a ASensor
121 extern class ASensor `{ASensorRef`}
123 new `{return malloc(sizeof(ASensorRef));`}
124 fun name
: NativeString `{return (char*)ASensor_getName(self);`}
125 fun vendor: NativeString `{return (char*)ASensor_getVendor(self);`}
126 fun sensor_type
: ASensorType `{return ASensor_getType(self);`}
127 fun resolution: Float `{return ASensor_getResolution(self);`}
128 fun min_delay
: Int `{return ASensor_getMinDelay(self);`}
131 # NIT representation of an Android Sensor used in android_app to initialize sensors
134 var asensor = new ASensor is writable
135 var enabled = false is writable
136 var event_rate = 100000 is writable
138 fun name: String do return asensor.name.to_s
139 fun vendor: String do return asensor.vendor.to_s
140 fun sensor_type: ASensorType do return asensor.sensor_type
141 fun resolution: Float do return asensor.resolution
142 fun min_delay: Int do return asensor.min_delay
145 # Extern class referencing a ASensorEvent
146 extern class ASensorEvent `{ASensorEvent*`}
149 fun version
: Int `{return self->version;`}
150 fun sensor: ASensor `{return (ASensorRef)self->sensor;`}
151 fun sensor_type
: ASensorType `{return self->type;`}
152 fun timestamp: Int `{return self->timestamp;`}
155 extern class FullSensor `{ASensorEvent*`}
157 super ASensorProximity
159 fun temperature: Float `{return self->temperature;`}
160 fun pressure
: Float `{return self->pressure;`}
161 fun data: Pointer `{return self->data;`}
162 fun vector
: ASensorVector `{return &(self->vector);`}
163 fun acceleration: ASensorVector `{return &(self->acceleration);`}
164 fun magnetic
: ASensorVector `{return &(self->magnetic);`}
167 # Extern class referencing a ASensorVector, attribute of ASensorRef
168 extern class ASensorVector `{ASensorVector*`}
170 fun v
: Pointer `{return self->v;`}
171 fun x: Float `{ return self->x;`}
172 fun y
: Float `{return self->y;`}
173 fun z: Float `{return self->z;`}
174 fun azimuth
: Float `{return self->azimuth;`}
175 fun pitch: Float `{return self->pitch;`}
176 fun roll
: Float `{return self->roll;`}
177 fun status: Int `{return self->status;`}
178 fun reserved
: Pointer `{return self->reserved;`}
181 # Sensor event returned by the Accelerometer sensor
182 extern class ASensorAccelerometer `{ASensorEvent*`}
185 fun x
: Float `{return self->acceleration.x;`}
186 fun y: Float `{return self->acceleration.y;`}
187 fun z
: Float `{return self->acceleration.z;`}
190 # Sensor event returned by the Magnetic Field sensor
191 extern class ASensorMagneticField `{ASensorEvent*`}
194 fun x
: Float `{return self->magnetic.x;`}
195 fun y: Float `{return self->magnetic.y;`}
196 fun z
: Float `{ return self->magnetic.z;`}
199 # Sensor event returned by the gyroscope sensor
200 extern class ASensorGyroscope `{ASensorEvent*`}
203 fun x
: Float `{return self->vector.x;`}
204 fun y: Float `{return self->vector.y;`}
205 fun z
: Float `{return self->vector.y;`}
208 # Sensor event returned by the Light sensor
209 extern class ASensorLight `{ASensorEvent*`}
212 fun light
: Float `{return self->light;`}
215 # sensor event returned by the Proximity Sensor
216 extern class ASensorProximity `{ASensorEvent*`}
219 fun distance
: Float `{return self->distance;`}
222 # Array of SensorEvents
223 extern class ASensorEvents `{ASensorEvent*`}
225 new (length
: Int) `{return malloc(sizeof(ASensorEvent)*length);`}
227 fun [](index: Int): ASensorEvent `{
233 var accelerometer = new AndroidSensor
234 var magnetic_field = new AndroidSensor
235 var gyroscope = new AndroidSensor
236 var light = new AndroidSensor
237 var proximity = new AndroidSensor
238 var sensormanager: ASensorManager
239 var eventqueue: ASensorEventQueue
240 var sensors_support_enabled = false is writable
242 private fun extern_input_sensor_accelerometer(event: ASensorAccelerometer) do input(event)
243 private fun extern_input_sensor_magnetic_field(event: ASensorMagneticField) do input(event)
244 private fun extern_input_sensor_gyroscope(event: ASensorGyroscope) do input(event)
245 private fun extern_input_sensor_light(event: ASensorLight) do input(event)
246 private fun extern_input_sensor_proximity(event: ASensorProximity) do input(event)
249 # The user decides which sensors he wants to use by setting them enabled
250 private fun enable_sensors
252 if sensors_support_enabled then enable_sensors_management else return
253 if accelerometer.enabled then enable_accelerometer
254 if magnetic_field.enabled then enable_magnetic_field
255 if gyroscope.enabled then enable_gyroscope
256 if light.enabled then enable_light
257 if proximity.enabled then enable_proximity
260 private fun enable_sensors_management
262 sensormanager = new ASensorManager.get_instance
263 #eventqueue = sensormanager.create_event_queue(new NdkAndroidApp)
264 eventqueue = initialize_event_queue(sensormanager, native_app_glue.looper)
267 # HACK: need a nit method to get mnit_java_app, then we can use the appropriate sensormanager.create_event_queue method to initialize the event queue
268 private fun initialize_event_queue(sensormanager: ASensorManager, looper: ALooper): ASensorEventQueue `{
269 return ASensorManager_createEventQueue(sensormanager
, looper
, LOOPER_ID_USER, NULL, NULL);
272 private fun enable_accelerometer
274 accelerometer.asensor = sensormanager.get_default_sensor(new ASensorType.accelerometer)
275 if accelerometer.asensor.address_is_null then
276 print "Accelerometer sensor unavailable"
278 if eventqueue.enable_sensor(accelerometer.asensor) < 0 then print "Accelerometer enabling failed"
279 eventqueue.set_event_rate(accelerometer.asensor, accelerometer.event_rate)
283 private fun enable_magnetic_field
285 magnetic_field.asensor = sensormanager.get_default_sensor(new ASensorType.magnetic_field)
286 if magnetic_field.asensor.address_is_null then
287 print "Magnetic Field unavailable"
289 if eventqueue.enable_sensor(magnetic_field.asensor) < 0 then print "Magnetic Field enabling failed"
290 eventqueue.set_event_rate(magnetic_field.asensor, magnetic_field.event_rate)
294 private fun enable_gyroscope
296 gyroscope.asensor = sensormanager.get_default_sensor(new ASensorType.gyroscope)
297 if gyroscope.asensor.address_is_null then
298 print "Gyroscope sensor unavailable"
300 if eventqueue.enable_sensor(gyroscope.asensor) < 0 then print "Gyroscope enabling failed"
301 eventqueue.set_event_rate(gyroscope.asensor, gyroscope.event_rate)
305 private fun enable_light
307 light.asensor = sensormanager.get_default_sensor(new ASensorType.light)
308 if light.asensor.address_is_null then
309 print "Light sensor unavailable"
311 if eventqueue.enable_sensor(light.asensor) < 0 then print "Light enabling failed"
312 eventqueue.set_event_rate(light.asensor, light.event_rate)
316 private fun enable_proximity
318 proximity.asensor = sensormanager.get_default_sensor(new ASensorType.proximity)
319 if proximity.asensor.address_is_null then
320 print "Proximity sensor unavailable"
322 if eventqueue.enable_sensor(proximity.asensor) < 0 then print "Proximity enabling failed"
323 eventqueue.set_event_rate(light.asensor, light.event_rate)
334 redef fun handle_looper_event(ident, event, data)
337 handle_sensor_events(ident)
340 private fun handle_sensor_events(ident: Int) import extern_input_sensor_accelerometer, extern_input_sensor_magnetic_field, extern_input_sensor_gyroscope, extern_input_sensor_light, extern_input_sensor_proximity, eventqueue `{
341 //If a sensor has data
, process it
342 if(ident
== LOOPER_ID_USER) {
343 //maybe add a boolean to the app to know
if we want to use
Sensor API or ASensorEvent directly
...
344 ASensorEvent* events
= malloc
(sizeof
(ASensorEvent)*10);
346 ASensorEventQueue* queue
= App_eventqueue(self);
347 while((nbevents
= ASensorEventQueue_getEvents(queue
, events
, 10)) > 0) {
349 for(i
= 0; i
< nbevents
; i
++){
350 ASensorEvent event
= events
[i
];
351 switch
(event
.type) {
352 case
ASENSOR_TYPE_ACCELEROMETER:
353 App_extern_input_sensor_accelerometer(self, &event
);
355 case
ASENSOR_TYPE_MAGNETIC_FIELD:
356 App_extern_input_sensor_magnetic_field(self, &event
);
358 case
ASENSOR_TYPE_GYROSCOPE:
359 App_extern_input_sensor_gyroscope(self, &event
);
361 case
ASENSOR_TYPE_LIGHT:
362 App_extern_input_sensor_light(self, &event
);
364 case
ASENSOR_TYPE_PROXIMITY:
365 App_extern_input_sensor_proximity(self, &event
);