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 # This module is used to manipulate android sensors
18 # The sensor support is implemented in android_app module, so the user can enable the type of sensor he wants to use.
19 # There is an example of how you can use the android sensors in nit/examples/mnit_ballz :
22 # #FIXME rewrite the example
24 # app.sensors_support_enabled = true
25 # app.accelerometer.enabled = true
26 # app.accelerometer.eventrate = 10000
27 # app.magnetic_field.enabled = true
28 # app.gyroscope.enabled = true
29 # app.light.enabled = true
30 # app.proximity.enabled = true
34 # In this example, we enable the sensor support, then enable all types of sensors supported, before running the app.
35 # The result is you get all type of SensorEvent (ASensorAccelerometer, ASensorMagneticField ...) in the input method of your app
43 #include <android/sensor.h>
46 extern class ASensorType `{int`}
47 new accelerometer: ASensorType `{return ASENSOR_TYPE_ACCELEROMETER;`}
48 fun is_accelerometer
: Bool `{return self == ASENSOR_TYPE_ACCELEROMETER;`}
49 new magnetic_field: ASensorType `{return ASENSOR_TYPE_MAGNETIC_FIELD;`}
50 fun is_magnetic_field
: Bool `{return self == ASENSOR_TYPE_MAGNETIC_FIELD;`}
51 new gyroscope:ASensorType `{return ASENSOR_TYPE_GYROSCOPE;`}
52 fun is_gyroscope
: Bool `{ return self == ASENSOR_TYPE_GYROSCOPE;`}
53 new light: ASensorType `{return ASENSOR_TYPE_LIGHT;`}
54 fun is_light
: Bool `{return self == ASENSOR_TYPE_LIGHT;`}
55 new proximity: ASensorType `{return ASENSOR_TYPE_PROXIMITY;`}
56 fun is_proximity
:Bool `{return self == ASENSOR_TYPE_PROXIMITY;`}
60 extern class ASensorManager `{ASensorManager*`}
62 new get_instance
: ASensorManager `{return ASensorManager_getInstance();`}
64 # Returns the list of available sensors
65 fun get_sensor_list: Pointer `{
67 ASensorManager_getSensorList(self, list
);
71 # Create a new sensor event queue and associate it with a looper
72 fun create_event_queue(app: NativeAppGlue): ASensorEventQueue `{
73 return ASensorManager_createEventQueue(self, app-
>looper
, LOOPER_ID_USER, NULL, NULL);
76 # Returns the default sensor of the given type
77 fun get_default_sensor(sensortype: ASensorType): ASensor `{
78 return ASensorManager_getDefaultSensor(self, sensortype
);
81 # Destroys the event queue and free all resources associated to it
82 fun destroy_event_queue(queue: ASensorEventQueue) `{
83 ASensorManager_destroyEventQueue(self, queue
);
87 # Manages the sensors events
88 extern class ASensorEventQueue `{ASensorEventQueue*`}
90 # Enable the selected sensor, returns a negative value on error
91 fun enable_sensor
(sensor
: ASensor): Int `{
92 return ASensorEventQueue_enableSensor(self, sensor);
95 # Disable the selected sensor, returns a negative value on error
96 fun disable_sensor
(sensor
: ASensor): Int `{
97 return ASensorEventQueue_disableSensor(self, sensor);
100 # Set the delivery rate of events in microseconds for the given sensor
101 fun set_event_rate
(sensor
: ASensor, usec
: Int): Int `{
102 return ASensorEventQueue_setEventRate(self, sensor, usec);
104 # Returns 1 if the queue has events, 0 if it does not have events,
105 # and a negative value if there is an error
106 fun has_events
: Int `{
107 return ASensorEventQueue_hasEvents(self);
110 # Returns the next available events from the queue.
111 # Returns a negative value if no events are available or an error has occured
112 # otherwise the number of events returned
113 fun get_events
(events
: ASensorEvents, count
: Int): Int `{
114 return ASensorEventQueue_getEvents(self, events, (size_t)count);
118 # Extern class referencing a ASensor
119 extern class ASensor `{ASensorRef`}
121 new `{return malloc(sizeof(ASensorRef));`}
122 fun name
: NativeString `{return (char*)ASensor_getName(self);`}
123 fun vendor: NativeString `{return (char*)ASensor_getVendor(self);`}
124 fun sensor_type
: ASensorType `{return ASensor_getType(self);`}
125 fun resolution: Float `{return ASensor_getResolution(self);`}
126 fun min_delay
: Int `{return ASensor_getMinDelay(self);`}
129 # NIT representation of an Android Sensor used in android_app to initialize sensors
132 var asensor = new ASensor is writable
133 var enabled = false is writable
134 var event_rate = 100000 is writable
136 fun name: String do return asensor.name.to_s
137 fun vendor: String do return asensor.vendor.to_s
138 fun sensor_type: ASensorType do return asensor.sensor_type
139 fun resolution: Float do return asensor.resolution
140 fun min_delay: Int do return asensor.min_delay
143 # Extern class referencing a ASensorEvent
144 extern class ASensorEvent `{ASensorEvent*`}
147 fun version
: Int `{return self->version;`}
148 fun sensor: ASensor `{return (ASensorRef)self->sensor;`}
149 fun sensor_type
: ASensorType `{return self->type;`}
150 fun timestamp: Int `{return self->timestamp;`}
153 extern class FullSensor `{ASensorEvent*`}
155 super ASensorProximity
157 fun temperature: Float `{return self->temperature;`}
158 fun pressure
: Float `{return self->pressure;`}
159 fun data: Pointer `{return self->data;`}
160 fun vector
: ASensorVector `{return &(self->vector);`}
161 fun acceleration: ASensorVector `{return &(self->acceleration);`}
162 fun magnetic
: ASensorVector `{return &(self->magnetic);`}
165 # Extern class referencing a ASensorVector, attribute of ASensorRef
166 extern class ASensorVector `{ASensorVector*`}
168 fun v
: Pointer `{return self->v;`}
169 fun x: Float `{ return self->x;`}
170 fun y
: Float `{return self->y;`}
171 fun z: Float `{return self->z;`}
172 fun azimuth
: Float `{return self->azimuth;`}
173 fun pitch: Float `{return self->pitch;`}
174 fun roll
: Float `{return self->roll;`}
175 fun status: Int `{return self->status;`}
176 fun reserved
: Pointer `{return self->reserved;`}
179 # Sensor event returned by the Accelerometer sensor
180 extern class ASensorAccelerometer `{ASensorEvent*`}
183 fun x
: Float `{return self->acceleration.x;`}
184 fun y: Float `{return self->acceleration.y;`}
185 fun z
: Float `{return self->acceleration.z;`}
188 # Sensor event returned by the Magnetic Field sensor
189 extern class ASensorMagneticField `{ASensorEvent*`}
192 fun x
: Float `{return self->magnetic.x;`}
193 fun y: Float `{return self->magnetic.y;`}
194 fun z
: Float `{ return self->magnetic.z;`}
197 # Sensor event returned by the gyroscope sensor
198 extern class ASensorGyroscope `{ASensorEvent*`}
201 fun x
: Float `{return self->vector.x;`}
202 fun y: Float `{return self->vector.y;`}
203 fun z
: Float `{return self->vector.y;`}
206 # Sensor event returned by the Light sensor
207 extern class ASensorLight `{ASensorEvent*`}
210 fun light
: Float `{return self->light;`}
213 # sensor event returned by the Proximity Sensor
214 extern class ASensorProximity `{ASensorEvent*`}
217 fun distance
: Float `{return self->distance;`}
220 # Array of SensorEvents
221 extern class ASensorEvents `{ASensorEvent*`}
223 new (length
: Int) `{return malloc(sizeof(ASensorEvent)*length);`}
225 fun [](index: Int): ASensorEvent `{
231 var accelerometer = new AndroidSensor
232 var magnetic_field = new AndroidSensor
233 var gyroscope = new AndroidSensor
234 var light = new AndroidSensor
235 var proximity = new AndroidSensor
236 var sensormanager: ASensorManager
237 var eventqueue: ASensorEventQueue
238 var sensors_support_enabled = false is writable
240 private fun extern_input_sensor_accelerometer(event: ASensorAccelerometer) do input(event)
241 private fun extern_input_sensor_magnetic_field(event: ASensorMagneticField) do input(event)
242 private fun extern_input_sensor_gyroscope(event: ASensorGyroscope) do input(event)
243 private fun extern_input_sensor_light(event: ASensorLight) do input(event)
244 private fun extern_input_sensor_proximity(event: ASensorProximity) do input(event)
247 # The user decides which sensors he wants to use by setting them enabled
248 private fun enable_sensors
250 if sensors_support_enabled then enable_sensors_management else return
251 if accelerometer.enabled then enable_accelerometer
252 if magnetic_field.enabled then enable_magnetic_field
253 if gyroscope.enabled then enable_gyroscope
254 if light.enabled then enable_light
255 if proximity.enabled then enable_proximity
258 private fun enable_sensors_management
260 sensormanager = new ASensorManager.get_instance
261 #eventqueue = sensormanager.create_event_queue(new NdkAndroidApp)
262 eventqueue = initialize_event_queue(sensormanager, native_app_glue.looper)
265 # 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
266 private fun initialize_event_queue(sensormanager: ASensorManager, looper: ALooper): ASensorEventQueue `{
267 return ASensorManager_createEventQueue(sensormanager
, looper
, LOOPER_ID_USER, NULL, NULL);
270 private fun enable_accelerometer
272 accelerometer.asensor = sensormanager.get_default_sensor(new ASensorType.accelerometer)
273 if accelerometer.asensor.address_is_null then
274 print "Accelerometer sensor unavailable"
276 if eventqueue.enable_sensor(accelerometer.asensor) < 0 then print "Accelerometer enabling failed"
277 eventqueue.set_event_rate(accelerometer.asensor, accelerometer.event_rate)
281 private fun enable_magnetic_field
283 magnetic_field.asensor = sensormanager.get_default_sensor(new ASensorType.magnetic_field)
284 if magnetic_field.asensor.address_is_null then
285 print "Magnetic Field unavailable"
287 if eventqueue.enable_sensor(magnetic_field.asensor) < 0 then print "Magnetic Field enabling failed"
288 eventqueue.set_event_rate(magnetic_field.asensor, magnetic_field.event_rate)
292 private fun enable_gyroscope
294 gyroscope.asensor = sensormanager.get_default_sensor(new ASensorType.gyroscope)
295 if gyroscope.asensor.address_is_null then
296 print "Gyroscope sensor unavailable"
298 if eventqueue.enable_sensor(gyroscope.asensor) < 0 then print "Gyroscope enabling failed"
299 eventqueue.set_event_rate(gyroscope.asensor, gyroscope.event_rate)
303 private fun enable_light
305 light.asensor = sensormanager.get_default_sensor(new ASensorType.light)
306 if light.asensor.address_is_null then
307 print "Light sensor unavailable"
309 if eventqueue.enable_sensor(light.asensor) < 0 then print "Light enabling failed"
310 eventqueue.set_event_rate(light.asensor, light.event_rate)
314 private fun enable_proximity
316 proximity.asensor = sensormanager.get_default_sensor(new ASensorType.proximity)
317 if proximity.asensor.address_is_null then
318 print "Proximity sensor unavailable"
320 if eventqueue.enable_sensor(proximity.asensor) < 0 then print "Proximity enabling failed"
321 eventqueue.set_event_rate(light.asensor, light.event_rate)
332 redef fun handle_looper_event(ident, event, data)
335 handle_sensor_events(ident)
338 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 `{
339 //If a sensor has data
, process it
340 if(ident
== LOOPER_ID_USER) {
341 //maybe add a boolean to the app to know
if we want to use
Sensor API or ASensorEvent directly
...
342 ASensorEvent* events
= malloc
(sizeof
(ASensorEvent)*10);
344 ASensorEventQueue* queue
= App_eventqueue(self);
345 while((nbevents
= ASensorEventQueue_getEvents(queue
, events
, 10)) > 0) {
347 for(i
= 0; i
< nbevents
; i
++){
348 ASensorEvent event
= events
[i
];
349 switch
(event
.type) {
350 case
ASENSOR_TYPE_ACCELEROMETER:
351 App_extern_input_sensor_accelerometer(self, &event
);
353 case
ASENSOR_TYPE_MAGNETIC_FIELD:
354 App_extern_input_sensor_magnetic_field(self, &event
);
356 case
ASENSOR_TYPE_GYROSCOPE:
357 App_extern_input_sensor_gyroscope(self, &event
);
359 case
ASENSOR_TYPE_LIGHT:
360 App_extern_input_sensor_light(self, &event
);
362 case
ASENSOR_TYPE_PROXIMITY:
363 App_extern_input_sensor_proximity(self, &event
);