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 :
23 # app.sensors_support_enabled = true
24 # app.accelerometer.enabled = true
25 # app.accelerometer.eventrate = 10000
26 # app.magnetic_field.enabled = true
27 # app.gyroscope.enabled = true
28 # app.light.enabled = true
29 # app.proximity.enabled = true
33 # In this example, we enable the sensor support, then enable all types of sensors supported, before running the app.
34 # The result is you get all type of SensorEvent (ASensorAccelerometer, ASensorMagneticField ...) in the input method of your app
42 #include <android/sensor.h>
45 extern class ASensorType `{int`}
46 new accelerometer: ASensorType `{return ASENSOR_TYPE_ACCELEROMETER;`}
47 fun is_accelerometer
: Bool `{return recv == ASENSOR_TYPE_ACCELEROMETER;`}
48 new magnetic_field: ASensorType `{return ASENSOR_TYPE_MAGNETIC_FIELD;`}
49 fun is_magnetic_field
: Bool `{return recv == ASENSOR_TYPE_MAGNETIC_FIELD;`}
50 new gyroscope:ASensorType `{return ASENSOR_TYPE_GYROSCOPE;`}
51 fun is_gyroscope
: Bool `{ return recv == ASENSOR_TYPE_GYROSCOPE;`}
52 new light: ASensorType `{return ASENSOR_TYPE_LIGHT;`}
53 fun is_light
: Bool `{return recv == ASENSOR_TYPE_LIGHT;`}
54 new proximity: ASensorType `{return ASENSOR_TYPE_PROXIMITY;`}
55 fun is_proximity
:Bool `{return recv == ASENSOR_TYPE_PROXIMITY;`}
59 extern class ASensorManager `{ASensorManager*`}
61 new get_instance
: ASensorManager `{return ASensorManager_getInstance();`}
63 # Returns the list of available sensors
64 fun get_sensor_list: Pointer `{
66 ASensorManager_getSensorList(recv
, list
);
70 # Create a new sensor event queue and associate it with a looper
71 fun create_event_queue(app: NativeAppGlue): ASensorEventQueue `{
72 return ASensorManager_createEventQueue(recv
, app-
>looper
, LOOPER_ID_USER, NULL, NULL);
75 # Returns the default sensor of the given type
76 fun get_default_sensor(sensortype: ASensorType): ASensor `{
77 return ASensorManager_getDefaultSensor(recv
, sensortype
);
80 # Destroys the event queue and free all resources associated to it
81 fun destroy_event_queue(queue: ASensorEventQueue) `{
82 ASensorManager_destroyEventQueue(recv
, queue
);
86 # Manages the sensors events
87 extern class ASensorEventQueue `{ASensorEventQueue*`}
89 # Enable the selected sensor, returns a negative value on error
90 fun enable_sensor
(sensor
: ASensor): Int `{
91 return ASensorEventQueue_enableSensor(recv, sensor);
94 # Disable the selected sensor, returns a negative value on error
95 fun disable_sensor
(sensor
: ASensor): Int `{
96 return ASensorEventQueue_disableSensor(recv, sensor);
99 # Set the delivery rate of events in microseconds for the given sensor
100 fun set_event_rate
(sensor
: ASensor, usec
: Int): Int `{
101 return ASensorEventQueue_setEventRate(recv, sensor, usec);
103 # Returns 1 if the queue has events, 0 if it does not have events,
104 # and a negative value if there is an error
105 fun has_events
: Int `{
106 return ASensorEventQueue_hasEvents(recv);
109 # Returns the next available events from the queue.
110 # Returns a negative value if no events are available or an error has occured
111 # otherwise the number of events returned
112 fun get_events
(events
: ASensorEvents, count
: Int): Int `{
113 return ASensorEventQueue_getEvents(recv, events, (size_t)count);
117 # Extern class referencing a ASensor
118 extern class ASensor `{ASensorRef`}
120 new `{return malloc(sizeof(ASensorRef));`}
121 fun name
: NativeString `{return (char*)ASensor_getName(recv);`}
122 fun vendor: NativeString `{return (char*)ASensor_getVendor(recv);`}
123 fun sensor_type
: ASensorType `{return ASensor_getType(recv);`}
124 fun resolution: Float `{return ASensor_getResolution(recv);`}
125 fun min_delay
: Int `{return ASensor_getMinDelay(recv);`}
128 # NIT representation of an Android Sensor used in android_app to initialize sensors
131 var asensor writable = new ASensor
132 var enabled writable = false
133 var event_rate writable = 100000
135 fun name: String do return asensor.name.to_s
136 fun vendor: String do return asensor.vendor.to_s
137 fun sensor_type: ASensorType do return asensor.sensor_type
138 fun resolution: Float do return asensor.resolution
139 fun min_delay: Int do return asensor.min_delay
142 # Extern class referencing a ASensorEvent
143 extern class ASensorEvent `{ASensorEvent*`}
146 fun version
: Int `{return recv->version;`}
147 fun sensor: ASensor `{return (ASensorRef)recv->sensor;`}
148 fun sensor_type
: ASensorType `{return recv->type;`}
149 fun timestamp: Int `{return recv->timestamp;`}
152 extern class FullSensor `{ASensorEvent*`}
154 super ASensorProximity
156 fun temperature: Float `{return recv->temperature;`}
157 fun pressure
: Float `{return recv->pressure;`}
158 fun data: Pointer `{return recv->data;`}
159 fun vector
: ASensorVector `{return &(recv->vector);`}
160 fun acceleration: ASensorVector `{return &(recv->acceleration);`}
161 fun magnetic
: ASensorVector `{return &(recv->magnetic);`}
164 # Extern class referencing a ASensorVector, attribute of ASensorRef
165 extern class ASensorVector `{ASensorVector*`}
167 fun v
: Pointer `{return recv->v;`}
168 fun x: Float `{ return recv->x;`}
169 fun y
: Float `{return recv->y;`}
170 fun z: Float `{return recv->z;`}
171 fun azimuth
: Float `{return recv->azimuth;`}
172 fun pitch: Float `{return recv->pitch;`}
173 fun roll
: Float `{return recv->roll;`}
174 fun status: Int `{return recv->status;`}
175 fun reserved
: Pointer `{return recv->reserved;`}
178 # Sensor event returned by the Accelerometer sensor
179 extern class ASensorAccelerometer `{ASensorEvent*`}
182 fun x
: Float `{return recv->acceleration.x;`}
183 fun y: Float `{return recv->acceleration.y;`}
184 fun z
: Float `{return recv->acceleration.z;`}
187 # Sensor event returned by the Magnetic Field sensor
188 extern class ASensorMagneticField `{ASensorEvent*`}
191 fun x
: Float `{return recv->magnetic.x;`}
192 fun y: Float `{return recv->magnetic.y;`}
193 fun z
: Float `{ return recv->magnetic.z;`}
196 # Sensor event returned by the gyroscope sensor
197 extern class ASensorGyroscope `{ASensorEvent*`}
200 fun x
: Float `{return recv->vector.x;`}
201 fun y: Float `{return recv->vector.y;`}
202 fun z
: Float `{return recv->vector.y;`}
205 # Sensor event returned by the Light sensor
206 extern class ASensorLight `{ASensorEvent*`}
209 fun light
: Float `{return recv->light;`}
212 # sensor event returned by the Proximity Sensor
213 extern class ASensorProximity `{ASensorEvent*`}
216 fun distance
: Float `{return recv->distance;`}
219 # Array of SensorEvents
220 extern class ASensorEvents `{ASensorEvent*`}
222 new (length
: Int) `{return malloc(sizeof(ASensorEvent)*length);`}
224 fun [](index: Int): ASensorEvent `{
230 var accelerometer = new AndroidSensor
231 var magnetic_field = new AndroidSensor
232 var gyroscope = new AndroidSensor
233 var light = new AndroidSensor
234 var proximity = new AndroidSensor
235 var sensormanager: ASensorManager
236 var eventqueue: ASensorEventQueue
237 var sensors_support_enabled writable = false
239 private fun extern_input_sensor_accelerometer(event: ASensorAccelerometer) do input(event)
240 private fun extern_input_sensor_magnetic_field(event: ASensorMagneticField) do input(event)
241 private fun extern_input_sensor_gyroscope(event: ASensorGyroscope) do input(event)
242 private fun extern_input_sensor_light(event: ASensorLight) do input(event)
243 private fun extern_input_sensor_proximity(event: ASensorProximity) do input(event)
246 # The user decides which sensors he wants to use by setting them enabled
247 private fun enable_sensors
249 if sensors_support_enabled then enable_sensors_management else return
250 if accelerometer.enabled then enable_accelerometer
251 if magnetic_field.enabled then enable_magnetic_field
252 if gyroscope.enabled then enable_gyroscope
253 if light.enabled then enable_light
254 if proximity.enabled then enable_proximity
257 private fun enable_sensors_management
259 sensormanager = new ASensorManager.get_instance
260 #eventqueue = sensormanager.create_event_queue(new NdkAndroidApp)
261 eventqueue = initialize_event_queue(sensormanager, native_app_glue.looper)
264 # 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
265 private fun initialize_event_queue(sensormanager: ASensorManager, looper: ALooper): ASensorEventQueue `{
266 return ASensorManager_createEventQueue(sensormanager
, looper
, LOOPER_ID_USER, NULL, NULL);
269 private fun enable_accelerometer
271 accelerometer.asensor = sensormanager.get_default_sensor(new ASensorType.accelerometer)
272 if accelerometer.asensor.address_is_null then
273 print "Accelerometer sensor unavailable"
275 if eventqueue.enable_sensor(accelerometer.asensor) < 0 then print "Accelerometer enabling failed"
276 eventqueue.set_event_rate(accelerometer.asensor, accelerometer.event_rate)
280 private fun enable_magnetic_field
282 magnetic_field.asensor = sensormanager.get_default_sensor(new ASensorType.magnetic_field)
283 if magnetic_field.asensor.address_is_null then
284 print "Magnetic Field unavailable"
286 if eventqueue.enable_sensor(magnetic_field.asensor) < 0 then print "Magnetic Field enabling failed"
287 eventqueue.set_event_rate(magnetic_field.asensor, magnetic_field.event_rate)
291 private fun enable_gyroscope
293 gyroscope.asensor = sensormanager.get_default_sensor(new ASensorType.gyroscope)
294 if gyroscope.asensor.address_is_null then
295 print "Gyroscope sensor unavailable"
297 if eventqueue.enable_sensor(gyroscope.asensor) < 0 then print "Gyroscope enabling failed"
298 eventqueue.set_event_rate(gyroscope.asensor, gyroscope.event_rate)
302 private fun enable_light
304 light.asensor = sensormanager.get_default_sensor(new ASensorType.light)
305 if light.asensor.address_is_null then
306 print "Light sensor unavailable"
308 if eventqueue.enable_sensor(light.asensor) < 0 then print "Light enabling failed"
309 eventqueue.set_event_rate(light.asensor, light.event_rate)
313 private fun enable_proximity
315 proximity.asensor = sensormanager.get_default_sensor(new ASensorType.proximity)
316 if proximity.asensor.address_is_null then
317 print "Proximity sensor unavailable"
319 if eventqueue.enable_sensor(proximity.asensor) < 0 then print "Proximity enabling failed"
320 eventqueue.set_event_rate(light.asensor, light.event_rate)
331 redef fun handle_looper_event(ident, event, data)
334 handle_sensor_events(ident)
337 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 `{
338 //If a sensor has data
, process it
339 if(ident
== LOOPER_ID_USER) {
340 //maybe add a boolean to the app to know
if we want to use
Sensor API or ASensorEvent directly
...
341 ASensorEvent* events
= malloc
(sizeof
(ASensorEvent)*10);
343 ASensorEventQueue* queue
= App_eventqueue(recv
);
344 while((nbevents
= ASensorEventQueue_getEvents(queue
, events
, 10)) > 0) {
346 for(i
= 0; i
< nbevents
; i
++){
347 ASensorEvent event
= events
[i
];
348 switch
(event
.type) {
349 case
ASENSOR_TYPE_ACCELEROMETER:
350 App_extern_input_sensor_accelerometer(recv
, &event
);
352 case
ASENSOR_TYPE_MAGNETIC_FIELD:
353 App_extern_input_sensor_magnetic_field(recv
, &event
);
355 case
ASENSOR_TYPE_GYROSCOPE:
356 App_extern_input_sensor_gyroscope(recv
, &event
);
358 case
ASENSOR_TYPE_LIGHT:
359 App_extern_input_sensor_light(recv
, &event
);
361 case
ASENSOR_TYPE_PROXIMITY:
362 App_extern_input_sensor_proximity(recv
, &event
);