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 static const double PI = 3.141592;
44 struct SensorConnection {
58 JSObjectRef onsensordata;
59 JSObjectRef onstatuschange;
60 JSObjectRef oncalibneed;
62 map< int, vector<JSValueRef> > listeners;
67 SENSOR_LISTENER_ERROR,
69 SENSOR_LISTENER_STATUS,
74 struct SensorConnection* scon;
79 static void processEvent(JSContextRef ctx, struct SensorConnection* sc, int listenerType, JSObjectRef event)
81 if(listenerType < SENSOR_LISTENER_ERROR || listenerType > SENSOR_LISTENER_CALIB){
87 JSStringRef pname_target = JSStringCreateWithUTF8CString("target");
88 JSStringRef pname_currentTarget = JSStringCreateWithUTF8CString("currentTarget");
89 JSObjectSetProperty(ctx, event, pname_target, sc->jsobj, kJSPropertyAttributeNone, NULL);
90 JSObjectSetProperty(ctx, event, pname_currentTarget, sc->jsobj, kJSPropertyAttributeNone, NULL);
91 JSStringRelease(pname_target);
92 JSStringRelease(pname_currentTarget);
95 JSObjectRef pfunc = NULL;
97 case SENSOR_LISTENER_ERROR:
100 case SENSOR_LISTENER_DATA:
101 pfunc = sc->onsensordata;
103 case SENSOR_LISTENER_STATUS:
104 pfunc = sc->onstatuschange;
106 case SENSOR_LISTENER_CALIB:
107 pfunc = sc->oncalibneed;
115 JSObjectCallAsFunction(ctx, pfunc, sc->jsobj, 0, NULL, NULL);
118 JSValueRef args[] = {event};
119 JSObjectCallAsFunction(ctx, pfunc, sc->jsobj, 1, args, NULL);
124 for(unsigned int i=0; i<sc->listeners[listenerType].size(); i++){
125 JSValueRef jsv = sc->listeners[listenerType][i];
126 JSObjectRef func = JSValueToObject(ctx, jsv, NULL);
128 JSObjectCallAsFunction(ctx, func, sc->jsobj, 0, NULL, NULL);
133 JSValueRef args[] = {event};
134 for(unsigned int i=0; i<sc->listeners[listenerType].size(); i++){
135 JSValueRef jsv = sc->listeners[listenerType][i];
136 JSObjectRef func = JSValueToObject(ctx, jsv, NULL);
137 JSObjectCallAsFunction(ctx, func, sc->jsobj, 1, args, NULL);
143 static gboolean afterFireProcess(gpointer user_data)
145 struct FireArgs* args = (struct FireArgs*)user_data;
147 JSContextRef ctx = JSSensorManager::gCtx;
148 struct SensorConnection* sc = args->scon;
149 int listenerType = args->listenerType;
150 JSObjectRef event = args->event;
152 processEvent(ctx, sc, listenerType, event);
159 static void fireEvent(struct SensorConnection* sc, int listenerType, JSObjectRef event)
161 struct FireArgs* args = new FireArgs;
163 args->listenerType = listenerType;
166 g_idle_add_full(G_PRIORITY_HIGH_IDLE, afterFireProcess, args, NULL);
169 static void addListener(JSContextRef ctx, struct SensorConnection* sc, int listenerType, JSValueRef func)
172 for(unsigned int i=0; i<sc->listeners[listenerType].size(); i++){
173 if(JSValueIsEqual(ctx, sc->listeners[listenerType][i], func, NULL)){
177 JSValueProtect(ctx, func);
178 sc->listeners[listenerType].push_back(func);
181 static void removeListener(JSContextRef ctx, struct SensorConnection* sc, int listenerType, JSValueRef func)
184 for(unsigned int i=0; i<sc->listeners[listenerType].size(); i++){
185 if(JSValueIsEqual(ctx, sc->listeners[listenerType][i], func, NULL)){
186 sc->listeners[listenerType].erase(sc->listeners[listenerType].begin() + i);
187 JSValueUnprotect(ctx, func);
194 JSClassRef JSSensorConnection::m_jsClassRef = NULL;
196 JSClassDefinition JSSensorConnection::m_jsClassInfo = {
198 kJSClassAttributeNone,
206 JSSensorConnection::getProperty, //getProperty,
207 JSSensorConnection::setProperty, //setProperty,
208 NULL, //deleteProperty
209 NULL, //getPropertyNames,
211 JSSensorConnection::constructor, // constructor
216 JSStaticFunction JSSensorConnection::m_function[] = {
217 { "read",JSSensorConnection::read,kJSPropertyAttributeNone },
218 { "startWatch",JSSensorConnection::startWatch,kJSPropertyAttributeNone },
219 { "endWatch",JSSensorConnection::endWatch,kJSPropertyAttributeNone },
220 { "addEventListener",JSSensorConnection::addEventListener,kJSPropertyAttributeNone },
221 { "removeEventListener",JSSensorConnection::removeEventListener,kJSPropertyAttributeNone },
222 { "dispatchEvent",JSSensorConnection::dispatchEvent,kJSPropertyAttributeNone },
226 const JSClassRef JSSensorConnection::getClassRef()
229 m_jsClassRef = JSClassCreate(&m_jsClassInfo);
234 const JSClassDefinition* JSSensorConnection::getClassInfo()
236 return &m_jsClassInfo;
239 JSContextRef JSSensorConnection::m_globalCtx = NULL;
241 void JSSensorConnection::initialize(JSContextRef ctx, JSObjectRef object)
244 SensorTypeUtil::getInstance(ctx);
247 void JSSensorConnection::finalize(JSObjectRef object)
249 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(object);
252 if(scon->handle != NULL){
253 sensor_destroy(scon->handle);
258 bool JSSensorConnection::hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception)
260 return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
263 JSValueRef JSSensorConnection::getProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
265 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(object);
269 if(JSStringIsEqualToUTF8CString(propertyName, "status")) {
270 JSStringRef status = NULL;
274 status = JSStringCreateWithUTF8CString("new");
276 case SENSOR_CON_OPEN:
277 status = JSStringCreateWithUTF8CString("open");
279 case SENSOR_CON_WATCHING:
280 status = JSStringCreateWithUTF8CString("watching");
282 case SENSOR_CON_DISCONNECTED:
283 status = JSStringCreateWithUTF8CString("disconnected");
285 case SENSOR_CON_ERROR:
286 status = JSStringCreateWithUTF8CString("error");
290 JSValueRef jsv = JSValueMakeString(ctx, status);
291 JSStringRelease(status);
296 else if(JSStringIsEqualToUTF8CString(propertyName, "sensor")) {
297 if(scon->status == SENSOR_CON_NEW){
298 *exception = JSDOMExceptionFactory::InvalidStateException.make(ctx);
302 if(scon->sensor != NULL)
306 else if(JSStringIsEqualToUTF8CString(propertyName, "error")) {
307 if(scon->error == NULL){
308 return JSValueMakeNull(ctx);
313 else if(JSStringIsEqualToUTF8CString(propertyName, "onerror")) {
314 return scon->onerror;
316 else if(JSStringIsEqualToUTF8CString(propertyName, "onsensordata")) {
317 return scon->onsensordata;
319 else if(JSStringIsEqualToUTF8CString(propertyName, "onstatuschange")) {
320 return scon->onstatuschange;
322 else if(JSStringIsEqualToUTF8CString(propertyName, "oncalibneed")) {
323 return scon->oncalibneed;
329 bool JSSensorConnection::setProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
331 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(object);
336 if(JSStringIsEqualToUTF8CString(propertyName, "status")) {
339 else if(JSStringIsEqualToUTF8CString(propertyName, "sensor")) {
342 else if(JSStringIsEqualToUTF8CString(propertyName, "error")) {
345 else if(JSStringIsEqualToUTF8CString(propertyName, "onerror")) {
346 if(scon->onerror != NULL){
347 JSValueUnprotect(ctx, scon->onerror);
349 JSValueProtect(ctx, value);
350 return (scon->onerror = JSValueToObject(ctx, value, NULL)) != NULL;
352 else if(JSStringIsEqualToUTF8CString(propertyName, "onsensordata")) {
353 if(scon->onsensordata != NULL){
354 JSValueUnprotect(ctx, scon->onsensordata);
356 JSValueProtect(ctx, value);
357 return (scon->onsensordata = JSValueToObject(ctx, value, NULL)) != NULL;
359 else if(JSStringIsEqualToUTF8CString(propertyName, "onstatuschange")) {
360 if(scon->onstatuschange != NULL){
361 JSValueUnprotect(ctx, scon->onstatuschange);
363 JSValueProtect(ctx, value);
364 return (scon->onstatuschange = JSValueToObject(ctx, value, NULL)) != NULL;
366 else if(JSStringIsEqualToUTF8CString(propertyName, "oncalibneed")) {
367 if(scon->oncalibneed != NULL){
368 JSValueUnprotect(ctx, scon->oncalibneed);
370 JSValueProtect(ctx, value);
371 return (scon->oncalibneed = JSValueToObject(ctx, value, NULL)) != NULL;
377 static void throwError(struct SensorConnection* scon, const char* msg, int code)
379 JSContextRef ctx = JSSensorManager::gCtx;
380 scon->error = JSSensorError::makeSensorError(ctx, msg, code);
381 fireEvent(scon, SENSOR_LISTENER_ERROR, scon->error);
384 static gboolean connect_sensor(gpointer user_data)
386 JSContextRef ctx = JSSensorManager::gCtx;
387 struct SensorConnection* scon = (struct SensorConnection*) user_data;
390 throwError(scon, "Unknown error", JSSensorError::UNKNOWN_ERROR);
394 JSObjectRef sensor = SensorTypeUtil::getInstance(ctx)->getSensor(ctx, (sensor_type_e)scon->type);
395 JSStringRef pname_sensor = JSStringCreateWithUTF8CString("sensor");
396 JSObjectSetProperty(ctx, scon->jsobj, pname_sensor, sensor, kJSPropertyAttributeReadOnly, NULL);
397 JSStringRelease(pname_sensor);
400 int err = sensor_create(&scon->handle);
402 throwError(scon, "Connect fail", JSSensorError::CONNECT_ERROR);
405 scon->status = SENSOR_CON_OPEN;
406 scon->sensor = SensorTypeUtil::makeSensor(ctx, scon->type);
407 fireEvent( scon, SENSOR_LISTENER_STATUS, NULL);
412 JSObjectRef JSSensorConnection::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
417 if(argumentCount < 1){
418 *exception = JSDOMExceptionFactory::InvalidValuesException.make(ctx);
422 if(JSValueIsString(ctx, arguments[0])){
423 JSStringRef jss_type = JSValueToStringCopy(ctx, arguments[0], NULL);
424 JSStringGetUTF8CString(jss_type, buf, 64);
425 JSStringRelease(jss_type);
426 type = SensorTypeUtil::modifyType(buf);
428 else if(JSValueIsObject(ctx, arguments[0])){
429 JSObjectRef sensorOption = JSValueToObject(ctx, arguments[0], NULL);
430 JSStringRef pname_type = JSStringCreateWithUTF8CString("type");
431 JSStringRef pname_name = JSStringCreateWithUTF8CString("name");
432 JSValueRef jsv_type = JSObjectGetProperty(ctx, sensorOption, pname_type, NULL);
433 JSValueRef jsv_name = JSObjectGetProperty(ctx, sensorOption, pname_name, NULL);
434 JSStringRelease(pname_type);
435 JSStringRelease(pname_name);
437 if(jsv_type == NULL || jsv_name == NULL){
438 *exception = JSDOMExceptionFactory::InvalidValuesException.make(ctx);
442 JSStringRef jss_type = JSValueToStringCopy(ctx, jsv_type, NULL);
443 JSStringRef jss_name = JSValueToStringCopy(ctx, jsv_name, NULL);
444 JSStringGetUTF8CString(jss_type, buf, 64);
445 JSStringGetUTF8CString(jss_name, buf2, 64);
446 JSStringRelease(jss_type);
447 JSStringRelease(jss_name);
449 type = SensorTypeUtil::modifyType(buf, buf2);
452 *exception = JSDOMExceptionFactory::InvalidValuesException.make(ctx);
456 *exception = JSDOMExceptionFactory::InvalidValuesException.make(ctx);
461 JSClassRef jsCls = getClassRef();
463 struct SensorConnection* scon = new SensorConnection;
464 JSObjectRef obj = JSObjectMake(ctx, jsCls, scon);
466 scon->listeners[SENSOR_LISTENER_ERROR] = vector<JSValueRef>();
467 scon->listeners[SENSOR_LISTENER_STATUS] = vector<JSValueRef>();
468 scon->listeners[SENSOR_LISTENER_DATA] = vector<JSValueRef>();
469 scon->listeners[SENSOR_LISTENER_CALIB] = vector<JSValueRef>();
473 scon->status = SENSOR_CON_NEW;
474 scon->type = (sensor_type_e)type;
475 scon->started = false;
480 scon->onerror = NULL;
481 scon->onsensordata = NULL;
482 scon->onstatuschange = NULL;
483 scon->oncalibneed = NULL;
485 fireEvent( scon, SENSOR_LISTENER_STATUS, NULL);
487 g_idle_add_full(G_PRIORITY_HIGH_IDLE, connect_sensor, scon, NULL);
491 static void sensor_cb_accelerometer(sensor_data_accuracy_e accuracy, float x, float y, float z, void* ud)
493 JSContextRef ctx = JSSensorManager::gCtx;
494 struct SensorConnection* scon = (struct SensorConnection*) ud;
495 if(accuracy < SENSOR_DATA_ACCURACY_UNDEFINED || accuracy > SENSOR_DATA_ACCURACY_VERYGOOD){
496 accuracy = SENSOR_DATA_ACCURACY_UNDEFINED;
499 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
500 data->set(accuracy, g_get_monotonic_time(), x, y, z);
502 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
504 static void sensor_cb_magnetic(sensor_data_accuracy_e accuracy, float x, float y, float z, void* ud)
506 JSContextRef ctx = JSSensorManager::gCtx;
507 struct SensorConnection* scon = (struct SensorConnection*) ud;
508 if(accuracy < SENSOR_DATA_ACCURACY_UNDEFINED || accuracy > SENSOR_DATA_ACCURACY_VERYGOOD){
509 accuracy = SENSOR_DATA_ACCURACY_UNDEFINED;
512 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
513 data->set(accuracy, g_get_monotonic_time(), x, y, z);
514 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
516 static void sensor_cb_orientation(sensor_data_accuracy_e accuracy, float alpha, float beta, float gamma, void* ud)
518 JSContextRef ctx = JSSensorManager::gCtx;
519 struct SensorConnection* scon = (struct SensorConnection*) ud;
520 if(accuracy < SENSOR_DATA_ACCURACY_UNDEFINED || accuracy > SENSOR_DATA_ACCURACY_VERYGOOD){
521 accuracy = SENSOR_DATA_ACCURACY_UNDEFINED;
524 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
526 alpha = alpha * ( PI / 180 );
527 beta = beta * ( PI / 180 );
528 gamma = gamma * ( PI / 180 );
530 data->set(accuracy, g_get_monotonic_time(), alpha, beta, gamma);
531 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
533 static void sensor_cb_gyroscope(sensor_data_accuracy_e accuracy, float x, float y, float z, void* ud)
535 JSContextRef ctx = JSSensorManager::gCtx;
536 struct SensorConnection* scon = (struct SensorConnection*) ud;
537 if(accuracy < SENSOR_DATA_ACCURACY_UNDEFINED || accuracy > SENSOR_DATA_ACCURACY_VERYGOOD){
538 accuracy = SENSOR_DATA_ACCURACY_UNDEFINED;
541 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
542 data->set(accuracy, g_get_monotonic_time(), x, y, z);
543 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
545 static void sensor_cb_light(sensor_data_accuracy_e accuracy, float lux, void* ud)
547 JSContextRef ctx = JSSensorManager::gCtx;
548 struct SensorConnection* scon = (struct SensorConnection*) ud;
550 if(scon->threshold >= 0 && lux != scon->threshold){
554 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
555 data->set(accuracy, g_get_monotonic_time(), lux);
556 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
558 static void sensor_cb_proximity(sensor_data_accuracy_e accuracy, float distance, void *ud)
560 JSContextRef ctx = JSSensorManager::gCtx;
561 struct SensorConnection* scon = (struct SensorConnection*) ud;
563 if(scon->threshold >= 0 && distance != scon->threshold){
567 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
568 data->set(accuracy, g_get_monotonic_time(), distance);
569 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
571 static void sensor_cb_calibration(void* ud)
573 JSContextRef ctx = JSSensorManager::gCtx;
574 struct SensorConnection* scon = (struct SensorConnection*) ud;
575 processEvent(ctx, scon, SENSOR_LISTENER_CALIB, NULL);
578 JSValueRef JSSensorConnection::read(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
580 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
582 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
584 if(scon->status != SENSOR_CON_OPEN && scon->status != SENSOR_CON_WATCHING){
585 return JSDOMExceptionFactory::InvalidStateException.make(ctx, exception);
588 bool started = false;
591 sensor_data_accuracy_e acc;
592 JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_READ, scon->type);
593 if(scon->status != SENSOR_CON_WATCHING){
594 sensor_start(scon->handle, scon->type);
597 switch((int)scon->type)
599 case SENSOR_ACCELEROMETER:
600 sensor_accelerometer_read_data(scon->handle, &acc, &x, &y, &z);
601 data->set(acc, g_get_monotonic_time(), x, y, z);
603 case SENSOR_MAGNETIC:
604 sensor_magnetic_read_data(scon->handle, &acc, &x, &y, &z);
605 data->set(acc, g_get_monotonic_time(), x, y, z);
607 case SENSOR_ORIENTATION:
608 x = x * ( PI / 180 );
609 y = y * ( PI / 180 );
610 z = z * ( PI / 180 );
611 sensor_orientation_read_data(scon->handle, &acc, &x, &y, &z);
612 data->set(acc, g_get_monotonic_time(), x, y, z);
614 case SENSOR_GYROSCOPE:
615 sensor_gyroscope_read_data(scon->handle, &acc, &x, &y, &z);
616 data->set(acc, g_get_monotonic_time(), x, y, z);
619 sensor_light_read_data(scon->handle, &acc, &lux);
620 data->set(acc, g_get_monotonic_time(), lux);
622 case SENSOR_PROXIMITY:
623 sensor_proximity_read_data(scon->handle, &acc, &cm);
627 return JSDOMExceptionFactory::NotSupportedException.make(ctx, exception);
630 sensor_stop(scon->handle, scon->type);
633 processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
635 return JSValueMakeUndefined(ctx);
638 static gboolean registerAndStart(gpointer user_data)
640 struct SensorConnection* scon = (struct SensorConnection*) user_data;
644 case SENSOR_ACCELEROMETER:
645 err = sensor_accelerometer_set_cb(scon->handle, (int)scon->interval, sensor_cb_accelerometer, scon);
647 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
650 err = sensor_start(scon->handle, SENSOR_ACCELEROMETER);
652 sensor_accelerometer_unset_cb(scon->handle);
653 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
657 case SENSOR_MAGNETIC:
658 err = sensor_magnetic_set_cb(scon->handle, (int)scon->interval, sensor_cb_magnetic, scon);
660 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
663 err = sensor_magnetic_set_calibration_cb(scon->handle, sensor_cb_calibration, scon);
665 sensor_magnetic_unset_cb(scon->handle);
666 throwError(scon, "Calibration watching fail", JSSensorError::WATCH_ERROR);
669 err = sensor_start(scon->handle, SENSOR_MAGNETIC);
671 sensor_magnetic_unset_cb(scon->handle);
672 sensor_magnetic_unset_calibration_cb(scon->handle);
673 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
677 case SENSOR_ORIENTATION:
678 err = sensor_orientation_set_cb(scon->handle, (int)scon->interval, sensor_cb_orientation, scon);
680 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
683 err = sensor_start(scon->handle, SENSOR_ORIENTATION);
685 sensor_orientation_unset_cb(scon->handle);
686 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
690 case SENSOR_GYROSCOPE:
691 err = sensor_gyroscope_set_cb(scon->handle, (int)scon->interval, sensor_cb_gyroscope, scon);
693 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
696 err = sensor_start(scon->handle, SENSOR_GYROSCOPE);
698 sensor_gyroscope_unset_cb(scon->handle);
699 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
704 err = sensor_light_set_cb(scon->handle, (int)scon->interval, sensor_cb_light, scon);
706 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
709 err = sensor_start(scon->handle, SENSOR_LIGHT);
711 sensor_light_unset_cb(scon->handle);
712 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
716 case SENSOR_PROXIMITY:
717 err = sensor_proximity_set_cb(scon->handle, (int)scon->interval, sensor_cb_proximity, scon);
719 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
722 err = sensor_start(scon->handle, SENSOR_PROXIMITY);
724 sensor_proximity_unset_cb(scon->handle);
725 throwError(scon, "Calibration watching fail", JSSensorError::WATCH_ERROR);
730 throwError(scon, "Unknown error", JSSensorError::UNKNOWN_ERROR);
734 scon->status = SENSOR_CON_WATCHING;
735 fireEvent( scon, SENSOR_LISTENER_STATUS, NULL);
740 JSValueRef JSSensorConnection::startWatch(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
742 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
744 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
746 if(scon->status != SENSOR_CON_OPEN){
747 return JSDOMExceptionFactory::InvalidStateException.make(ctx, exception);
750 if(argumentCount > 0){
751 double threshold = -1, interval = 0;
752 if(!JSValueIsObject(ctx, arguments[0]))
753 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
755 JSObjectRef watchOption = JSValueToObject(ctx, arguments[0], NULL);
756 JSStringRef pname_threshold = JSStringCreateWithUTF8CString("threshold");
757 JSStringRef pname_interval = JSStringCreateWithUTF8CString("interval");
758 if(JSObjectHasProperty(ctx, watchOption, pname_threshold)){
759 JSValueRef jsv_threshold = JSObjectGetProperty(ctx, watchOption, pname_threshold, NULL);
760 threshold = JSValueToNumber(ctx, jsv_threshold, NULL);
762 if(JSObjectHasProperty(ctx, watchOption, pname_interval)){
763 JSValueRef jsv_interval = JSObjectGetProperty(ctx, watchOption, pname_interval, NULL);
764 interval = JSValueToNumber(ctx, jsv_interval, NULL);
766 JSStringRelease(pname_threshold);
767 JSStringRelease(pname_interval);
768 scon->threshold = threshold;
769 scon->interval = interval;
771 scon->threshold = -1;
775 // JSSensorDataEvent::setReason(ctx, scon->eventData, JSSENSOR_REASON_WATCH);
777 g_idle_add_full(G_PRIORITY_HIGH_IDLE, registerAndStart, scon, NULL);
779 return JSValueMakeUndefined(ctx);
783 static gboolean deregisterandstop(gpointer user_data)
785 struct SensorConnection* scon = (struct SensorConnection*) user_data;
788 case SENSOR_ACCELEROMETER:
789 err += sensor_stop(scon->handle, SENSOR_ACCELEROMETER);
790 err += sensor_accelerometer_unset_cb(scon->handle);
792 case SENSOR_MAGNETIC:
793 err += sensor_stop(scon->handle, SENSOR_MAGNETIC);
794 err += sensor_magnetic_unset_cb(scon->handle);
795 err += sensor_magnetic_unset_calibration_cb(scon->handle);
797 case SENSOR_ORIENTATION:
798 err += sensor_stop(scon->handle, SENSOR_ORIENTATION);
799 err += sensor_orientation_unset_cb(scon->handle);
801 case SENSOR_GYROSCOPE:
802 err += sensor_stop(scon->handle, SENSOR_GYROSCOPE);
803 err += sensor_gyroscope_unset_cb(scon->handle);
806 err += sensor_stop(scon->handle, SENSOR_LIGHT);
807 err += sensor_light_unset_cb(scon->handle);
809 case SENSOR_PROXIMITY:
810 err += sensor_stop(scon->handle, SENSOR_PROXIMITY);
811 err += sensor_proximity_unset_cb(scon->handle);
814 throwError(scon, "Unknown error", JSSensorError::UNKNOWN_ERROR);
818 throwError(scon, "End watching fail", JSSensorError::END_WATCH_ERROR);
822 scon->status = SENSOR_CON_OPEN;
823 fireEvent( scon, SENSOR_LISTENER_STATUS, NULL);
828 JSValueRef JSSensorConnection::endWatch(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
830 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
832 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
834 if(scon->status != SENSOR_CON_WATCHING){
835 return JSDOMExceptionFactory::InvalidStateException.make(ctx, exception);
838 g_idle_add_full(G_PRIORITY_HIGH_IDLE, deregisterandstop, scon, NULL);
840 return JSValueMakeUndefined(ctx);
843 static int detectListenerType(std::string& strType)
845 if(strType.compare("error") == 0){
846 return SENSOR_LISTENER_ERROR;
848 else if(strType.compare("sensordata") == 0){
849 return SENSOR_LISTENER_DATA;
851 else if(strType.compare("statuschange") == 0){
852 return SENSOR_LISTENER_STATUS;
854 else if(strType.compare("calibneed") == 0){
855 return SENSOR_LISTENER_CALIB;
860 JSValueRef JSSensorConnection::addEventListener(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
862 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
863 Converter converter(ctx);
865 if( argumentCount < 2 )
866 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
868 std::string typeStr = converter.toString(arguments[0]);
869 int type = detectListenerType(typeStr);
872 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
875 addListener(ctx, scon, type, arguments[1]);
877 return JSValueMakeUndefined(ctx);
880 JSValueRef JSSensorConnection::removeEventListener(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
882 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
883 Converter converter(ctx);
885 if( argumentCount < 2 )
886 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
888 std::string typeStr = converter.toString(arguments[0]);
889 int type = detectListenerType(typeStr);
892 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
895 removeListener(ctx, scon, type, arguments[1]);
896 return JSValueMakeUndefined(ctx);
899 JSValueRef JSSensorConnection::dispatchEvent(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
901 struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
902 Converter converter(ctx);
904 if( argumentCount < 1 )
905 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
907 JSObjectRef event = JSValueToObject(ctx, arguments[0], NULL);
908 JSStringRef jss_type = JSStringCreateWithUTF8CString("type");
909 JSValueRef jsv_type = JSObjectGetProperty(ctx, event, jss_type, NULL);
910 JSStringRelease(jss_type);
912 std::string typeStr = converter.toString(jsv_type);
913 int type = detectListenerType(typeStr);
916 return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
919 fireEvent( scon, type, event);
921 return JSValueMakeBoolean(ctx, true);