2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <CommonsJavaScript/Converter.h>
20 #include <CommonsJavaScript/Validator.h>
21 #include <CommonsJavaScript/JSUtils.h>
22 #include <CommonsJavaScript/JSDOMExceptionFactory.h>
24 #include "JSSensorManager.h"
25 #include "JSSensorConnection.h"
26 #include "JSSensorDataEvent.h"
27 #include "JSSensorError.h"
28 #include "SensorType.h"
33 #define LOG_TAG "TIZEN_SENSOR"
37 using namespace WrtDeviceApis::CommonsJavaScript;
42 struct SensorConnection {
56 JSObjectRef onsensordata;
57 JSObjectRef onstatuschange;
58 JSObjectRef oncalibneed;
60 map< int, vector<JSValueRef> > listeners;
65 SENSOR_LISTENER_ERROR,
67 SENSOR_LISTENER_STATUS,
72 struct SensorConnection* scon;
77 static void processEvent(JSContextRef ctx, struct SensorConnection* sc, int listenerType, JSObjectRef event)
79 if(listenerType < SENSOR_LISTENER_ERROR || listenerType > SENSOR_LISTENER_CALIB){
85 JSStringRef pname_target = JSStringCreateWithUTF8CString("target");
86 JSStringRef pname_currentTarget = JSStringCreateWithUTF8CString("currentTarget");
87 JSObjectSetProperty(ctx, event, pname_target, sc->jsobj, kJSPropertyAttributeNone, NULL);
88 JSObjectSetProperty(ctx, event, pname_currentTarget, sc->jsobj, kJSPropertyAttributeNone, NULL);
89 JSStringRelease(pname_target);
90 JSStringRelease(pname_currentTarget);
93 JSObjectRef pfunc = NULL;
95 case SENSOR_LISTENER_ERROR:
98 case SENSOR_LISTENER_DATA:
99 pfunc = sc->onsensordata;
101 case SENSOR_LISTENER_STATUS:
102 pfunc = sc->onstatuschange;
104 case SENSOR_LISTENER_CALIB:
105 pfunc = sc->oncalibneed;
113 JSObjectCallAsFunction(ctx, pfunc, sc->jsobj, 0, NULL, NULL);
116 JSValueRef args[] = {event};
117 JSObjectCallAsFunction(ctx, pfunc, sc->jsobj, 1, args, NULL);
122 for(unsigned int i=0; i<sc->listeners[listenerType].size(); i++){
123 JSValueRef jsv = sc->listeners[listenerType][i];
124 JSObjectRef func = JSValueToObject(ctx, jsv, NULL);
126 JSObjectCallAsFunction(ctx, func, sc->jsobj, 0, NULL, NULL);
131 JSValueRef args[] = {event};
132 for(unsigned int i=0; i<sc->listeners[listenerType].size(); i++){
133 JSValueRef jsv = sc->listeners[listenerType][i];
134 JSObjectRef func = JSValueToObject(ctx, jsv, NULL);
135 JSObjectCallAsFunction(ctx, func, sc->jsobj, 1, args, NULL);
141 static gboolean afterFireProcess(gpointer user_data)
143 struct FireArgs* args = (struct FireArgs*)user_data;
145 JSContextRef ctx = JSSensorManager::gCtx;
146 struct SensorConnection* sc = args->scon;
147 int listenerType = args->listenerType;
148 JSObjectRef event = args->event;
150 processEvent(ctx, sc, listenerType, event);
157 static void fireEvent(struct SensorConnection* sc, int listenerType, JSObjectRef event)
159 struct FireArgs* args = new FireArgs;
161 args->listenerType = listenerType;
164 g_idle_add_full(G_PRIORITY_HIGH_IDLE, afterFireProcess, args, NULL);
167 static void addListener(JSContextRef ctx, struct SensorConnection* sc, int listenerType, JSValueRef func)
170 for(unsigned int i=0; i<sc->listeners[listenerType].size(); i++){
171 if(JSValueIsEqual(ctx, sc->listeners[listenerType][i], func, NULL)){
175 JSValueProtect(ctx, func);
176 sc->listeners[listenerType].push_back(func);
179 static void removeListener(JSContextRef ctx, struct SensorConnection* sc, int listenerType, JSValueRef func)
182 for(unsigned int i=0; i<sc->listeners[listenerType].size(); i++){
183 if(JSValueIsEqual(ctx, sc->listeners[listenerType][i], func, NULL)){
184 sc->listeners[listenerType].erase(sc->listeners[listenerType].begin() + i);
185 JSValueUnprotect(ctx, func);
192 JSClassRef JSSensorConnection::m_jsClassRef = NULL;
194 JSClassDefinition JSSensorConnection::m_jsClassInfo = {
196 kJSClassAttributeNone,
204 JSSensorConnection::getProperty, //getProperty,
205 JSSensorConnection::setProperty, //setProperty,
206 NULL, //deleteProperty
207 NULL, //getPropertyNames,
209 JSSensorConnection::constructor, // constructor
214 JSStaticFunction JSSensorConnection::m_function[] = {
215 { "read",JSSensorConnection::read,kJSPropertyAttributeNone },
216 { "startWatch",JSSensorConnection::startWatch,kJSPropertyAttributeNone },
217 { "endWatch",JSSensorConnection::endWatch,kJSPropertyAttributeNone },
218 { "addEventListener",JSSensorConnection::addEventListener,kJSPropertyAttributeNone },
219 { "removeEventListener",JSSensorConnection::removeEventListener,kJSPropertyAttributeNone },
220 { "dispatchEvent",JSSensorConnection::dispatchEvent,kJSPropertyAttributeNone },
224 const JSClassRef JSSensorConnection::getClassRef()
227 m_jsClassRef = JSClassCreate(&m_jsClassInfo);
232 const JSClassDefinition* JSSensorConnection::getClassInfo()
234 return &m_jsClassInfo;
237 JSContextRef JSSensorConnection::m_globalCtx = NULL;
239 void JSSensorConnection::initialize(JSContextRef ctx, JSObjectRef object)
242 SensorTypeUtil::getInstance(ctx);
245 void JSSensorConnection::finalize(JSObjectRef object)
247 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(object);
250 if(scon->handle != NULL){
251 sensor_destroy(scon->handle);
256 bool JSSensorConnection::hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception)
258 return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
261 JSValueRef JSSensorConnection::getProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
263 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(object);
267 if(JSStringIsEqualToUTF8CString(propertyName, "status")) {
268 JSStringRef status = NULL;
272 status = JSStringCreateWithUTF8CString("new");
274 case SENSOR_CON_OPEN:
275 status = JSStringCreateWithUTF8CString("open");
277 case SENSOR_CON_WATCHING:
278 status = JSStringCreateWithUTF8CString("watching");
280 case SENSOR_CON_DISCONNECTED:
281 status = JSStringCreateWithUTF8CString("disconnected");
283 case SENSOR_CON_ERROR:
284 status = JSStringCreateWithUTF8CString("error");
288 JSValueRef jsv = JSValueMakeString(ctx, status);
289 JSStringRelease(status);
294 else if(JSStringIsEqualToUTF8CString(propertyName, "sensor")) {
295 if(scon->status == SENSOR_CON_NEW){
296 *exception = JSDOMExceptionFactory::InvalidStateException.make(ctx);
300 if(scon->sensor != NULL)
304 else if(JSStringIsEqualToUTF8CString(propertyName, "error")) {
305 if(scon->error == NULL){
306 return JSValueMakeNull(ctx);
311 else if(JSStringIsEqualToUTF8CString(propertyName, "onerror")) {
312 return scon->onerror;
314 else if(JSStringIsEqualToUTF8CString(propertyName, "onsensordata")) {
315 return scon->onsensordata;
317 else if(JSStringIsEqualToUTF8CString(propertyName, "onstatuschange")) {
318 return scon->onstatuschange;
320 else if(JSStringIsEqualToUTF8CString(propertyName, "oncalibneed")) {
321 return scon->oncalibneed;
327 bool JSSensorConnection::setProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
329 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(object);
334 if(JSStringIsEqualToUTF8CString(propertyName, "status")) {
337 else if(JSStringIsEqualToUTF8CString(propertyName, "sensor")) {
340 else if(JSStringIsEqualToUTF8CString(propertyName, "error")) {
343 else if(JSStringIsEqualToUTF8CString(propertyName, "onerror")) {
344 if(scon->onerror != NULL){
345 JSValueUnprotect(ctx, scon->onerror);
347 JSValueProtect(ctx, value);
348 return (scon->onerror = JSValueToObject(ctx, value, NULL)) != NULL;
350 else if(JSStringIsEqualToUTF8CString(propertyName, "onsensordata")) {
351 if(scon->onsensordata != NULL){
352 JSValueUnprotect(ctx, scon->onsensordata);
354 JSValueProtect(ctx, value);
355 return (scon->onsensordata = JSValueToObject(ctx, value, NULL)) != NULL;
357 else if(JSStringIsEqualToUTF8CString(propertyName, "onstatuschange")) {
358 if(scon->onstatuschange != NULL){
359 JSValueUnprotect(ctx, scon->onstatuschange);
361 JSValueProtect(ctx, value);
362 return (scon->onstatuschange = JSValueToObject(ctx, value, NULL)) != NULL;
364 else if(JSStringIsEqualToUTF8CString(propertyName, "oncalibneed")) {
365 if(scon->oncalibneed != NULL){
366 JSValueUnprotect(ctx, scon->oncalibneed);
368 JSValueProtect(ctx, value);
369 return (scon->oncalibneed = JSValueToObject(ctx, value, NULL)) != NULL;
375 static void throwError(struct SensorConnection* scon, const char* msg, int code)
377 JSContextRef ctx = JSSensorManager::gCtx;
378 scon->error = JSSensorError::makeSensorError(ctx, msg, code);
379 fireEvent(scon, SENSOR_LISTENER_ERROR, scon->error);
382 static gboolean connect_sensor(gpointer user_data)
384 JSContextRef ctx = JSSensorManager::gCtx;
385 struct SensorConnection* scon = (struct SensorConnection*) user_data;
388 throwError(scon, "Unknown error", JSSensorError::UNKNOWN_ERROR);
392 JSObjectRef sensor = SensorTypeUtil::getInstance(ctx)->getSensor(ctx, (sensor_type_e)scon->type);
393 JSStringRef pname_sensor = JSStringCreateWithUTF8CString("sensor");
394 JSObjectSetProperty(ctx, scon->jsobj, pname_sensor, sensor, kJSPropertyAttributeReadOnly, NULL);
395 JSStringRelease(pname_sensor);
398 int err = sensor_create(&scon->handle);
400 throwError(scon, "Connect fail", JSSensorError::CONNECT_ERROR);
403 scon->status = SENSOR_CON_OPEN;
404 scon->sensor = SensorTypeUtil::makeSensor(ctx, scon->type);
405 fireEvent( scon, SENSOR_LISTENER_STATUS, NULL);
410 JSObjectRef JSSensorConnection::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
415 if(argumentCount < 1){
416 *exception = JSDOMExceptionFactory::InvalidValuesException.make(ctx);
420 if(JSValueIsString(ctx, arguments[0])){
421 JSStringRef jss_type = JSValueToStringCopy(ctx, arguments[0], NULL);
422 JSStringGetUTF8CString(jss_type, buf, 64);
423 JSStringRelease(jss_type);
424 type = SensorTypeUtil::modifyType(buf);
426 else if(JSValueIsObject(ctx, arguments[0])){
427 JSObjectRef sensorOption = JSValueToObject(ctx, arguments[0], NULL);
428 JSStringRef pname_type = JSStringCreateWithUTF8CString("type");
429 JSStringRef pname_name = JSStringCreateWithUTF8CString("name");
430 JSValueRef jsv_type = JSObjectGetProperty(ctx, sensorOption, pname_type, NULL);
431 JSValueRef jsv_name = JSObjectGetProperty(ctx, sensorOption, pname_name, NULL);
432 JSStringRelease(pname_type);
433 JSStringRelease(pname_name);
435 if(jsv_type == NULL || jsv_name == NULL){
436 *exception = JSDOMExceptionFactory::InvalidValuesException.make(ctx);
440 JSStringRef jss_type = JSValueToStringCopy(ctx, jsv_type, NULL);
441 JSStringRef jss_name = JSValueToStringCopy(ctx, jsv_name, NULL);
442 JSStringGetUTF8CString(jss_type, buf, 64);
443 JSStringGetUTF8CString(jss_name, buf2, 64);
444 JSStringRelease(jss_type);
445 JSStringRelease(jss_name);
447 type = SensorTypeUtil::modifyType(buf, buf2);
450 *exception = JSDOMExceptionFactory::InvalidValuesException.make(ctx);
454 *exception = JSDOMExceptionFactory::InvalidValuesException.make(ctx);
459 JSClassRef jsCls = getClassRef();
461 struct SensorConnection* scon = new SensorConnection;
462 JSObjectRef obj = JSObjectMake(ctx, jsCls, scon);
464 scon->listeners[SENSOR_LISTENER_ERROR] = vector<JSValueRef>();
465 scon->listeners[SENSOR_LISTENER_STATUS] = vector<JSValueRef>();
466 scon->listeners[SENSOR_LISTENER_DATA] = vector<JSValueRef>();
467 scon->listeners[SENSOR_LISTENER_CALIB] = vector<JSValueRef>();
471 scon->status = SENSOR_CON_NEW;
472 scon->type = (sensor_type_e)type;
473 scon->started = false;
478 scon->onerror = NULL;
479 scon->onsensordata = NULL;
480 scon->onstatuschange = NULL;
481 scon->oncalibneed = NULL;
483 fireEvent( scon, SENSOR_LISTENER_STATUS, NULL);
485 g_idle_add_full(G_PRIORITY_HIGH_IDLE, connect_sensor, scon, NULL);
489 static void sensor_cb_accelerometer(sensor_data_accuracy_e accuracy, float x, float y, float z, void* ud)
491 JSContextRef ctx = JSSensorManager::gCtx;
492 struct SensorConnection* scon = (struct SensorConnection*) ud;
493 if(accuracy < SENSOR_DATA_ACCURACY_UNDEFINED || accuracy > SENSOR_DATA_ACCURACY_VERYGOOD){
494 accuracy = SENSOR_DATA_ACCURACY_UNDEFINED;
497 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
498 data->set(accuracy, g_get_monotonic_time(), x, y, z);
500 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
502 static void sensor_cb_magnetic(sensor_data_accuracy_e accuracy, float x, float y, float z, void* ud)
504 JSContextRef ctx = JSSensorManager::gCtx;
505 struct SensorConnection* scon = (struct SensorConnection*) ud;
506 if(accuracy < SENSOR_DATA_ACCURACY_UNDEFINED || accuracy > SENSOR_DATA_ACCURACY_VERYGOOD){
507 accuracy = SENSOR_DATA_ACCURACY_UNDEFINED;
510 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
511 data->set(accuracy, g_get_monotonic_time(), x, y, z);
512 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
514 static void sensor_cb_orientation(sensor_data_accuracy_e accuracy, float alpha, float beta, float gamma, void* ud)
516 JSContextRef ctx = JSSensorManager::gCtx;
517 struct SensorConnection* scon = (struct SensorConnection*) ud;
518 if(accuracy < SENSOR_DATA_ACCURACY_UNDEFINED || accuracy > SENSOR_DATA_ACCURACY_VERYGOOD){
519 accuracy = SENSOR_DATA_ACCURACY_UNDEFINED;
522 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
523 data->set(accuracy, g_get_monotonic_time(), alpha, beta, gamma);
524 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
526 static void sensor_cb_gyroscope(sensor_data_accuracy_e accuracy, float x, float y, float z, void* ud)
528 JSContextRef ctx = JSSensorManager::gCtx;
529 struct SensorConnection* scon = (struct SensorConnection*) ud;
530 if(accuracy < SENSOR_DATA_ACCURACY_UNDEFINED || accuracy > SENSOR_DATA_ACCURACY_VERYGOOD){
531 accuracy = SENSOR_DATA_ACCURACY_UNDEFINED;
534 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
535 data->set(accuracy, g_get_monotonic_time(), x, y, z);
536 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
538 static void sensor_cb_light(sensor_data_accuracy_e accuracy, float lux, void* ud)
540 JSContextRef ctx = JSSensorManager::gCtx;
541 struct SensorConnection* scon = (struct SensorConnection*) ud;
543 if(scon->threshold >= 0 && lux != scon->threshold){
547 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
548 data->set(accuracy, g_get_monotonic_time(), lux);
549 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
551 static void sensor_cb_proximity(sensor_data_accuracy_e accuracy, float distance, void *ud)
553 JSContextRef ctx = JSSensorManager::gCtx;
554 struct SensorConnection* scon = (struct SensorConnection*) ud;
556 if(scon->threshold >= 0 && distance != scon->threshold){
560 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
561 data->set(accuracy, g_get_monotonic_time(), distance);
562 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
564 static void sensor_cb_calibration(void* ud)
566 JSContextRef ctx = JSSensorManager::gCtx;
567 struct SensorConnection* scon = (struct SensorConnection*) ud;
568 processEvent(ctx, scon, SENSOR_LISTENER_CALIB, NULL);
571 JSValueRef JSSensorConnection::read(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
573 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
575 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
577 if(scon->status != SENSOR_CON_OPEN && scon->status != SENSOR_CON_WATCHING){
578 return JSDOMExceptionFactory::InvalidStateException.make(ctx, exception);
581 bool started = false;
584 sensor_data_accuracy_e acc;
585 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_READ, scon->type);
586 if(scon->status != SENSOR_CON_WATCHING){
587 sensor_start(scon->handle, scon->type);
590 switch((int)scon->type)
592 case SENSOR_ACCELEROMETER:
593 sensor_accelerometer_read_data(scon->handle, &acc, &x, &y, &z);
594 data->set(acc, g_get_monotonic_time(), x, y, z);
596 case SENSOR_MAGNETIC:
597 sensor_magnetic_read_data(scon->handle, &acc, &x, &y, &z);
598 data->set(acc, g_get_monotonic_time(), x, y, z);
600 case SENSOR_ORIENTATION:
601 sensor_orientation_read_data(scon->handle, &acc, &x, &y, &z);
602 data->set(acc, g_get_monotonic_time(), x, y, z);
604 case SENSOR_GYROSCOPE:
605 sensor_gyroscope_read_data(scon->handle, &acc, &x, &y, &z);
606 data->set(acc, g_get_monotonic_time(), x, y, z);
609 sensor_light_read_data(scon->handle, &acc, &lux);
610 data->set(acc, g_get_monotonic_time(), lux);
612 case SENSOR_PROXIMITY:
613 sensor_proximity_read_data(scon->handle, &acc, &cm);
617 return JSDOMExceptionFactory::NotSupportedException.make(ctx, exception);
620 sensor_stop(scon->handle, scon->type);
623 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
625 return JSValueMakeUndefined(ctx);
628 static gboolean registerAndStart(gpointer user_data)
630 struct SensorConnection* scon = (struct SensorConnection*) user_data;
634 case SENSOR_ACCELEROMETER:
635 err = sensor_accelerometer_set_cb(scon->handle, (int)scon->interval, sensor_cb_accelerometer, scon);
637 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
640 err = sensor_start(scon->handle, SENSOR_ACCELEROMETER);
642 sensor_accelerometer_unset_cb(scon->handle);
643 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
647 case SENSOR_MAGNETIC:
648 err = sensor_magnetic_set_cb(scon->handle, (int)scon->interval, sensor_cb_magnetic, scon);
650 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
653 err = sensor_magnetic_set_calibration_cb(scon->handle, sensor_cb_calibration, scon);
655 sensor_magnetic_unset_cb(scon->handle);
656 throwError(scon, "Calibration watching fail", JSSensorError::WATCH_ERROR);
659 err = sensor_start(scon->handle, SENSOR_MAGNETIC);
661 sensor_magnetic_unset_cb(scon->handle);
662 sensor_magnetic_unset_calibration_cb(scon->handle);
663 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
667 case SENSOR_ORIENTATION:
668 err = sensor_orientation_set_cb(scon->handle, (int)scon->interval, sensor_cb_orientation, scon);
670 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
673 err = sensor_start(scon->handle, SENSOR_ORIENTATION);
675 sensor_orientation_unset_cb(scon->handle);
676 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
680 case SENSOR_GYROSCOPE:
681 err = sensor_gyroscope_set_cb(scon->handle, (int)scon->interval, sensor_cb_gyroscope, scon);
683 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
686 err = sensor_start(scon->handle, SENSOR_GYROSCOPE);
688 sensor_gyroscope_unset_cb(scon->handle);
689 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
694 err = sensor_light_set_cb(scon->handle, (int)scon->interval, sensor_cb_light, scon);
696 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
699 err = sensor_start(scon->handle, SENSOR_LIGHT);
701 sensor_light_unset_cb(scon->handle);
702 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
706 case SENSOR_PROXIMITY:
707 err = sensor_proximity_set_cb(scon->handle, (int)scon->interval, sensor_cb_proximity, scon);
709 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
712 err = sensor_start(scon->handle, SENSOR_PROXIMITY);
714 sensor_proximity_unset_cb(scon->handle);
715 throwError(scon, "Calibration watching fail", JSSensorError::WATCH_ERROR);
720 throwError(scon, "Unknown error", JSSensorError::UNKNOWN_ERROR);
724 scon->status = SENSOR_CON_WATCHING;
725 fireEvent( scon, SENSOR_LISTENER_STATUS, NULL);
730 JSValueRef JSSensorConnection::startWatch(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
732 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
734 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
736 if(scon->status != SENSOR_CON_OPEN){
737 return JSDOMExceptionFactory::InvalidStateException.make(ctx, exception);
740 if(argumentCount > 0){
741 double threshold = -1, interval = 0;
742 if(!JSValueIsObject(ctx, arguments[0]))
743 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
745 JSObjectRef watchOption = JSValueToObject(ctx, arguments[0], NULL);
746 JSStringRef pname_threshold = JSStringCreateWithUTF8CString("threshold");
747 JSStringRef pname_interval = JSStringCreateWithUTF8CString("interval");
748 if(JSObjectHasProperty(ctx, watchOption, pname_threshold)){
749 JSValueRef jsv_threshold = JSObjectGetProperty(ctx, watchOption, pname_threshold, NULL);
750 threshold = JSValueToNumber(ctx, jsv_threshold, NULL);
752 if(JSObjectHasProperty(ctx, watchOption, pname_interval)){
753 JSValueRef jsv_interval = JSObjectGetProperty(ctx, watchOption, pname_interval, NULL);
754 interval = JSValueToNumber(ctx, jsv_interval, NULL);
756 JSStringRelease(pname_threshold);
757 JSStringRelease(pname_interval);
758 scon->threshold = threshold;
759 scon->interval = interval;
761 scon->threshold = -1;
765 // JSSensorDataEvent::setReason(ctx, scon->eventData, JSSENSOR_REASON_WATCH);
767 g_idle_add_full(G_PRIORITY_HIGH_IDLE, registerAndStart, scon, NULL);
769 return JSValueMakeUndefined(ctx);
773 static gboolean deregisterandstop(gpointer user_data)
775 struct SensorConnection* scon = (struct SensorConnection*) user_data;
778 case SENSOR_ACCELEROMETER:
779 err += sensor_stop(scon->handle, SENSOR_ACCELEROMETER);
780 err += sensor_accelerometer_unset_cb(scon->handle);
782 case SENSOR_MAGNETIC:
783 err += sensor_stop(scon->handle, SENSOR_MAGNETIC);
784 err += sensor_magnetic_unset_cb(scon->handle);
785 err += sensor_magnetic_unset_calibration_cb(scon->handle);
787 case SENSOR_ORIENTATION:
788 err += sensor_stop(scon->handle, SENSOR_ORIENTATION);
789 err += sensor_orientation_unset_cb(scon->handle);
791 case SENSOR_GYROSCOPE:
792 err += sensor_stop(scon->handle, SENSOR_GYROSCOPE);
793 err += sensor_gyroscope_unset_cb(scon->handle);
796 err += sensor_stop(scon->handle, SENSOR_LIGHT);
797 err += sensor_light_unset_cb(scon->handle);
799 case SENSOR_PROXIMITY:
800 err += sensor_stop(scon->handle, SENSOR_PROXIMITY);
801 err += sensor_proximity_unset_cb(scon->handle);
804 throwError(scon, "Unknown error", JSSensorError::UNKNOWN_ERROR);
808 throwError(scon, "End watching fail", JSSensorError::END_WATCH_ERROR);
812 scon->status = SENSOR_CON_OPEN;
813 fireEvent( scon, SENSOR_LISTENER_STATUS, NULL);
818 JSValueRef JSSensorConnection::endWatch(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
820 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
822 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
824 if(scon->status != SENSOR_CON_WATCHING){
825 return JSDOMExceptionFactory::InvalidStateException.make(ctx, exception);
828 g_idle_add_full(G_PRIORITY_HIGH_IDLE, deregisterandstop, scon, NULL);
830 return JSValueMakeUndefined(ctx);
833 static int detectListenerType(std::string& strType)
835 if(strType.compare("error") == 0){
836 return SENSOR_LISTENER_ERROR;
838 else if(strType.compare("sensordata") == 0){
839 return SENSOR_LISTENER_DATA;
841 else if(strType.compare("statuschange") == 0){
842 return SENSOR_LISTENER_STATUS;
844 else if(strType.compare("calibneed") == 0){
845 return SENSOR_LISTENER_CALIB;
850 JSValueRef JSSensorConnection::addEventListener(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
852 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
853 Converter converter(ctx);
855 if( argumentCount < 2 )
856 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
858 std::string typeStr = converter.toString(arguments[0]);
859 int type = detectListenerType(typeStr);
862 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
865 addListener(ctx, scon, type, arguments[1]);
867 return JSValueMakeUndefined(ctx);
870 JSValueRef JSSensorConnection::removeEventListener(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
872 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
873 Converter converter(ctx);
875 if( argumentCount < 2 )
876 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
878 std::string typeStr = converter.toString(arguments[0]);
879 int type = detectListenerType(typeStr);
882 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
885 removeListener(ctx, scon, type, arguments[1]);
886 return JSValueMakeUndefined(ctx);
889 JSValueRef JSSensorConnection::dispatchEvent(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
891 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
892 Converter converter(ctx);
894 if( argumentCount < 1 )
895 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
897 JSObjectRef event = JSValueToObject(ctx, arguments[0], NULL);
898 JSStringRef jss_type = JSStringCreateWithUTF8CString("type");
899 JSValueRef jsv_type = JSObjectGetProperty(ctx, event, jss_type, NULL);
900 JSStringRelease(jss_type);
902 std::string typeStr = converter.toString(jsv_type);
903 int type = detectListenerType(typeStr);
906 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
909 fireEvent( scon, type, event);
911 return JSValueMakeBoolean(ctx, true);