Beta merge 2
[profile/ivi/wrt-plugins-tizen.git] / src / standards / Tizen / Sensors / JSSensorConnection.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 #include <map>
17 #include <vector>
18 #include <algorithm>
19 #include <CommonsJavaScript/Converter.h>
20 #include <CommonsJavaScript/Validator.h>
21 #include <CommonsJavaScript/JSUtils.h>
22 #include <CommonsJavaScript/JSDOMExceptionFactory.h>
23 #include <glib.h>
24 #include "JSSensorManager.h"
25 #include "JSSensorConnection.h"
26 #include "JSSensorDataEvent.h"
27 #include "JSSensorError.h"
28 #include "SensorType.h"
29
30 #include <dlog.h>
31
32 #undef LOG_TAG
33 #define LOG_TAG "TIZEN_SENSOR"
34
35 using namespace std;
36 using namespace DPL;
37 using namespace WrtDeviceApis::CommonsJavaScript;
38
39 namespace TizenApis {
40 namespace Tizen1_0 {
41
42 static const double PI = 3.141592;
43
44 struct SensorConnection {
45     sensor_type_e type;
46     int status;
47     sensor_h handle;
48     bool started;
49     JSContextRef ctx;
50
51     double interval;
52     double threshold;
53
54     JSObjectRef sensor;
55     JSObjectRef error;
56
57     JSObjectRef onerror;
58     JSObjectRef onsensordata;
59     JSObjectRef onstatuschange;
60     JSObjectRef oncalibneed;
61
62     map< int, vector<JSValueRef> > listeners;
63     JSObjectRef jsobj;
64 };
65
66 enum {
67     SENSOR_LISTENER_ERROR,
68     SENSOR_LISTENER_DATA,
69     SENSOR_LISTENER_STATUS,
70     SENSOR_LISTENER_CALIB
71 };
72
73 struct FireArgs {
74     struct SensorConnection* scon;
75     int listenerType;
76     JSObjectRef event;
77 };
78
79 static void processEvent(JSContextRef ctx, struct SensorConnection* sc, int listenerType, JSObjectRef event)
80 {
81     if(listenerType < SENSOR_LISTENER_ERROR || listenerType > SENSOR_LISTENER_CALIB){
82         return;
83     }
84     if(sc != NULL){
85
86         if(event != NULL){
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);
93         }
94
95         JSObjectRef pfunc = NULL;
96         switch(listenerType){
97             case SENSOR_LISTENER_ERROR:
98                 pfunc = sc->onerror;
99                 break;
100             case SENSOR_LISTENER_DATA:
101                 pfunc = sc->onsensordata;
102                 break;
103             case SENSOR_LISTENER_STATUS:
104                 pfunc = sc->onstatuschange;
105                 break;
106             case SENSOR_LISTENER_CALIB:
107                 pfunc = sc->oncalibneed;
108                 break;
109             default:
110                                 break;
111         }
112
113         if(pfunc != NULL){
114             if(event == NULL){
115                 JSObjectCallAsFunction(ctx, pfunc, sc->jsobj, 0, NULL, NULL);
116             }
117             else{
118                 JSValueRef args[] = {event};
119                 JSObjectCallAsFunction(ctx, pfunc, sc->jsobj, 1, args, NULL);
120             }
121         }
122
123         if(event == 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);
127                 if(func != NULL)
128                     JSObjectCallAsFunction(ctx, func, sc->jsobj, 0, NULL, NULL);
129             }
130
131         }
132         else{
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);
138             }
139         }
140     }
141 }
142
143 static gboolean afterFireProcess(gpointer user_data)
144 {
145     struct FireArgs* args = (struct FireArgs*)user_data;
146
147     JSContextRef ctx = JSSensorManager::gCtx;
148     struct SensorConnection* sc = args->scon;
149     int listenerType = args->listenerType;
150     JSObjectRef event = args->event;
151
152     processEvent(ctx, sc, listenerType, event);
153
154     delete args;
155
156     return false;
157 }
158
159 static void fireEvent(struct SensorConnection* sc, int listenerType, JSObjectRef event)
160 {
161     struct FireArgs* args = new FireArgs;
162     args->scon = sc;
163     args->listenerType = listenerType;
164     args->event = event;
165
166     g_idle_add_full(G_PRIORITY_HIGH_IDLE, afterFireProcess, args, NULL);
167 }
168
169 static void addListener(JSContextRef ctx, struct SensorConnection* sc, int listenerType, JSValueRef func)
170 {
171     if(sc != NULL){
172         for(unsigned int i=0; i<sc->listeners[listenerType].size(); i++){
173             if(JSValueIsEqual(ctx, sc->listeners[listenerType][i], func, NULL)){
174                 return;
175             }
176         }
177         JSValueProtect(ctx, func);
178         sc->listeners[listenerType].push_back(func);
179     }
180 }
181 static void removeListener(JSContextRef ctx, struct SensorConnection* sc, int listenerType, JSValueRef func)
182 {
183     if(sc != NULL){
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);
188                 break;
189             }
190         }
191     }
192 }
193
194 JSClassRef JSSensorConnection::m_jsClassRef = NULL;
195
196 JSClassDefinition JSSensorConnection::m_jsClassInfo = {
197                 0,
198                 kJSClassAttributeNone,
199                 "SensorConnection",
200                 NULL,
201                 NULL,
202                 m_function,
203                 initialize,
204                 finalize,
205                 NULL, //hasProperty,
206                 JSSensorConnection::getProperty, //getProperty,
207                 JSSensorConnection::setProperty, //setProperty,
208                 NULL, //deleteProperty
209                 NULL, //getPropertyNames,
210                 NULL,
211                 JSSensorConnection::constructor, // constructor
212                 hasInstance,
213                 NULL
214 };
215
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 },
223                 { 0, 0, 0 }
224 };
225
226 const JSClassRef JSSensorConnection::getClassRef()
227 {
228         if (!m_jsClassRef) {
229                 m_jsClassRef = JSClassCreate(&m_jsClassInfo);
230         }
231         return m_jsClassRef;
232 }
233
234 const JSClassDefinition* JSSensorConnection::getClassInfo()
235 {
236         return &m_jsClassInfo;
237 }
238
239 JSContextRef JSSensorConnection::m_globalCtx = NULL;
240
241 void JSSensorConnection::initialize(JSContextRef ctx, JSObjectRef object)
242 {
243     m_globalCtx = ctx;
244     SensorTypeUtil::getInstance(ctx);
245 }
246
247 void JSSensorConnection::finalize(JSObjectRef object)
248 {
249     struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(object);
250
251     if(scon != NULL){
252         if(scon->handle != NULL){
253             sensor_destroy(scon->handle);
254         }
255     }
256 }
257
258 bool JSSensorConnection::hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception)
259 {
260         return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
261 }
262
263 JSValueRef JSSensorConnection::getProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
264 {
265     struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(object);
266     if(scon == NULL)
267         return NULL;
268
269     if(JSStringIsEqualToUTF8CString(propertyName, "status")) {
270         JSStringRef status = NULL;
271         switch(scon->status)
272         {
273             case SENSOR_CON_NEW:
274                 status = JSStringCreateWithUTF8CString("new");
275                 break;
276             case SENSOR_CON_OPEN:
277                 status = JSStringCreateWithUTF8CString("open");
278                 break;
279             case SENSOR_CON_WATCHING:
280                 status = JSStringCreateWithUTF8CString("watching");
281                 break;
282             case SENSOR_CON_DISCONNECTED:
283                 status = JSStringCreateWithUTF8CString("disconnected");
284                 break;
285             case SENSOR_CON_ERROR:
286                 status = JSStringCreateWithUTF8CString("error");
287                 break;
288         }
289         if(status != NULL){
290             JSValueRef jsv = JSValueMakeString(ctx, status);
291             JSStringRelease(status);
292             return jsv;
293         }
294         return NULL;
295     }
296     else if(JSStringIsEqualToUTF8CString(propertyName, "sensor")) {
297         if(scon->status == SENSOR_CON_NEW){
298             *exception = JSDOMExceptionFactory::InvalidStateException.make(ctx);
299             return NULL;
300         }
301
302         if(scon->sensor != NULL)
303             return scon->sensor;
304         return NULL;
305     }
306     else if(JSStringIsEqualToUTF8CString(propertyName, "error")) {
307         if(scon->error == NULL){
308             return JSValueMakeNull(ctx);
309         }else{
310             return scon->error;
311         }
312     }
313     else if(JSStringIsEqualToUTF8CString(propertyName, "onerror")) {
314         return scon->onerror;
315     }
316     else if(JSStringIsEqualToUTF8CString(propertyName, "onsensordata")) {
317         return scon->onsensordata;
318     }
319     else if(JSStringIsEqualToUTF8CString(propertyName, "onstatuschange")) {
320         return scon->onstatuschange;
321     }
322     else if(JSStringIsEqualToUTF8CString(propertyName, "oncalibneed")) {
323         return scon->oncalibneed;
324     }
325
326     return NULL;
327 }
328
329 bool JSSensorConnection::setProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
330 {
331     struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(object);
332     if(scon == NULL){
333         return false;
334     }
335
336     if(JSStringIsEqualToUTF8CString(propertyName, "status")) {
337         return true;
338     }
339     else if(JSStringIsEqualToUTF8CString(propertyName, "sensor")) {
340         return true;
341     }
342     else if(JSStringIsEqualToUTF8CString(propertyName, "error")) {
343         return true;
344     }
345     else if(JSStringIsEqualToUTF8CString(propertyName, "onerror")) {
346         if(scon->onerror != NULL){
347             JSValueUnprotect(ctx, scon->onerror);
348         }
349         JSValueProtect(ctx, value);
350         return (scon->onerror = JSValueToObject(ctx, value, NULL)) != NULL;
351     }
352     else if(JSStringIsEqualToUTF8CString(propertyName, "onsensordata")) {
353         if(scon->onsensordata != NULL){
354             JSValueUnprotect(ctx, scon->onsensordata);
355         }
356         JSValueProtect(ctx, value);
357         return (scon->onsensordata = JSValueToObject(ctx, value, NULL)) != NULL;
358     }
359     else if(JSStringIsEqualToUTF8CString(propertyName, "onstatuschange")) {
360         if(scon->onstatuschange != NULL){
361             JSValueUnprotect(ctx, scon->onstatuschange);
362         }
363         JSValueProtect(ctx, value);
364         return (scon->onstatuschange = JSValueToObject(ctx, value, NULL)) != NULL;
365     }
366     else if(JSStringIsEqualToUTF8CString(propertyName, "oncalibneed")) {
367         if(scon->oncalibneed != NULL){
368             JSValueUnprotect(ctx, scon->oncalibneed);
369         }
370         JSValueProtect(ctx, value);
371         return (scon->oncalibneed = JSValueToObject(ctx, value, NULL)) != NULL;
372     }
373
374     return false;
375 }
376
377 static void throwError(struct SensorConnection* scon, const char* msg, int code)
378 {
379     JSContextRef ctx = JSSensorManager::gCtx;
380     scon->error = JSSensorError::makeSensorError(ctx, msg, code);
381     fireEvent(scon, SENSOR_LISTENER_ERROR, scon->error);
382 }
383
384 static gboolean connect_sensor(gpointer user_data)
385 {
386     JSContextRef ctx = JSSensorManager::gCtx;
387     struct SensorConnection* scon = (struct SensorConnection*) user_data;
388
389     if(scon == NULL){
390         throwError(scon, "Unknown error", JSSensorError::UNKNOWN_ERROR);
391         return false;
392     }
393
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);
398
399
400     int err = sensor_create(&scon->handle);
401     if(err < 0) {
402         throwError(scon, "Connect fail", JSSensorError::CONNECT_ERROR);
403         return false;
404     }
405     scon->status = SENSOR_CON_OPEN;
406     scon->sensor = SensorTypeUtil::makeSensor(ctx, scon->type);
407     fireEvent( scon, SENSOR_LISTENER_STATUS, NULL);
408
409     return false;
410 }
411
412 JSObjectRef JSSensorConnection::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
413 {
414     char buf[64];
415     char buf2[64];
416     int type;
417     if(argumentCount < 1){
418         *exception = JSDOMExceptionFactory::InvalidValuesException.make(ctx);
419         return NULL;
420     }
421
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);
427     }
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);
436
437         if(jsv_type == NULL  || jsv_name == NULL){
438             *exception = JSDOMExceptionFactory::InvalidValuesException.make(ctx);
439             return NULL;
440         }
441
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);
448
449         type = SensorTypeUtil::modifyType(buf, buf2);
450     }
451     else{
452         *exception = JSDOMExceptionFactory::InvalidValuesException.make(ctx);
453         return NULL;
454     }
455     if(type < 0){
456         *exception = JSDOMExceptionFactory::InvalidValuesException.make(ctx);
457         return NULL;
458     }
459
460
461     JSClassRef jsCls = getClassRef();
462
463     struct SensorConnection* scon = new SensorConnection;
464     JSObjectRef obj = JSObjectMake(ctx, jsCls, scon);
465
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>();
470
471     scon->handle = NULL;
472     scon->ctx = ctx;
473     scon->status = SENSOR_CON_NEW;
474     scon->type = (sensor_type_e)type;
475     scon->started = false;
476     scon->interval = 0;
477     scon->threshold = 0;
478     scon->jsobj = obj;
479     scon->error = NULL;
480     scon->onerror = NULL;
481     scon->onsensordata = NULL;
482     scon->onstatuschange = NULL;
483     scon->oncalibneed = NULL;
484
485     fireEvent( scon, SENSOR_LISTENER_STATUS, NULL);
486
487     g_idle_add_full(G_PRIORITY_HIGH_IDLE, connect_sensor, scon, NULL);
488     return obj;
489 }
490
491 static void sensor_cb_accelerometer(sensor_data_accuracy_e accuracy, float x, float y, float z, void* ud)
492 {
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;
497     }
498
499     JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
500     data->set(accuracy, g_get_monotonic_time(), x, y, z);
501
502     processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
503 }
504 static void sensor_cb_magnetic(sensor_data_accuracy_e accuracy, float x, float y, float z, void* ud)
505 {
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;
510     }
511
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());
515 }
516 static void sensor_cb_orientation(sensor_data_accuracy_e accuracy, float alpha, float beta, float gamma, void* ud)
517 {
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;
522     }
523
524     JSSensorDataEvent* data = new JSSensorDataEvent(ctx, JSSENSOR_REASON_WATCH, scon->type);
525
526     alpha = alpha * ( PI / 180 );
527     beta = beta * ( PI / 180 );
528     gamma = gamma * ( PI / 180 );
529
530     data->set(accuracy, g_get_monotonic_time(), alpha, beta, gamma);
531     processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
532 }
533 static void sensor_cb_gyroscope(sensor_data_accuracy_e accuracy, float x, float y, float z, void* ud)
534 {
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;
539     }
540
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());
544 }
545 static void sensor_cb_light(sensor_data_accuracy_e accuracy, float lux, void* ud)
546 {
547     JSContextRef ctx = JSSensorManager::gCtx;
548     struct SensorConnection* scon = (struct SensorConnection*) ud;
549
550     if(scon->threshold >= 0 && lux != scon->threshold){
551         return;
552     }
553
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());
557 }
558 static void sensor_cb_proximity(sensor_data_accuracy_e accuracy, float distance, void *ud)
559 {
560     JSContextRef ctx = JSSensorManager::gCtx;
561     struct SensorConnection* scon = (struct SensorConnection*) ud;
562
563     if(scon->threshold >= 0 && distance != scon->threshold){
564         return;
565     }
566
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());
570 }
571 static void sensor_cb_calibration(void* ud)
572 {
573     JSContextRef ctx = JSSensorManager::gCtx;
574     struct SensorConnection* scon = (struct SensorConnection*) ud;
575     processEvent(ctx, scon, SENSOR_LISTENER_CALIB, NULL);
576 }
577
578 JSValueRef JSSensorConnection::read(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
579 {
580     struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
581     if(scon == NULL)
582         return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
583
584     if(scon->status != SENSOR_CON_OPEN && scon->status != SENSOR_CON_WATCHING){
585         return JSDOMExceptionFactory::InvalidStateException.make(ctx, exception);
586     }
587
588     bool started = false;
589     float x, y, z;
590     float lux, cm;
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);
595         started = true;
596     }
597     switch((int)scon->type)
598     {
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);
602             break;
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);
606             break;
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);
613             break;
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);
617             break;
618         case SENSOR_LIGHT:
619             sensor_light_read_data(scon->handle, &acc, &lux);
620             data->set(acc, g_get_monotonic_time(), lux);
621             break;
622         case SENSOR_PROXIMITY:
623             sensor_proximity_read_data(scon->handle, &acc, &cm);
624             break;
625
626         default:
627             return JSDOMExceptionFactory::NotSupportedException.make(ctx, exception);
628     }
629     if(started){
630         sensor_stop(scon->handle, scon->type);
631         started = false;
632     }
633     processEvent(ctx, scon, SENSOR_LISTENER_DATA, data->makeJSObj());
634
635     return JSValueMakeUndefined(ctx);
636 }
637
638 static gboolean registerAndStart(gpointer user_data)
639 {
640     struct SensorConnection* scon = (struct SensorConnection*) user_data;
641
642     int err;
643     switch(scon->type){
644         case SENSOR_ACCELEROMETER:
645             err = sensor_accelerometer_set_cb(scon->handle, (int)scon->interval, sensor_cb_accelerometer, scon);
646             if(err <0) {
647                 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
648                 return false;
649             }
650             err = sensor_start(scon->handle, SENSOR_ACCELEROMETER);
651             if(err <0) {
652                 sensor_accelerometer_unset_cb(scon->handle);
653                 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
654                 return false;
655             }
656             break;
657         case SENSOR_MAGNETIC:
658             err = sensor_magnetic_set_cb(scon->handle, (int)scon->interval, sensor_cb_magnetic, scon);
659             if(err <0) {
660                 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
661                 return false;
662             }
663             err = sensor_magnetic_set_calibration_cb(scon->handle, sensor_cb_calibration, scon);
664             if(err <0) {
665                 sensor_magnetic_unset_cb(scon->handle);
666                 throwError(scon, "Calibration watching fail", JSSensorError::WATCH_ERROR);
667                 return false;
668             }
669             err = sensor_start(scon->handle, SENSOR_MAGNETIC);
670             if(err <0) {
671                 sensor_magnetic_unset_cb(scon->handle);
672                 sensor_magnetic_unset_calibration_cb(scon->handle);
673                 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
674                 return false;
675             }
676             break;
677         case SENSOR_ORIENTATION:
678             err = sensor_orientation_set_cb(scon->handle, (int)scon->interval, sensor_cb_orientation, scon);
679             if(err <0) {
680                 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
681                 return false;
682             }
683             err = sensor_start(scon->handle, SENSOR_ORIENTATION);
684             if(err <0) {
685                 sensor_orientation_unset_cb(scon->handle);
686                 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
687                 return false;
688             }
689             break;
690         case SENSOR_GYROSCOPE:
691             err = sensor_gyroscope_set_cb(scon->handle, (int)scon->interval, sensor_cb_gyroscope, scon);
692             if(err <0) {
693                 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
694                 return false;
695             }
696             err = sensor_start(scon->handle, SENSOR_GYROSCOPE);
697             if(err <0) {
698                 sensor_gyroscope_unset_cb(scon->handle);
699                 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
700                 return false;
701             }
702             break;
703         case SENSOR_LIGHT:
704             err = sensor_light_set_cb(scon->handle, (int)scon->interval, sensor_cb_light, scon);
705             if(err <0) {
706                 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
707                 return false;
708             }
709             err = sensor_start(scon->handle, SENSOR_LIGHT);
710             if(err <0) {
711                 sensor_light_unset_cb(scon->handle);
712                 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
713                 return false;
714             }
715             break;
716         case SENSOR_PROXIMITY:
717             err = sensor_proximity_set_cb(scon->handle, (int)scon->interval, sensor_cb_proximity, scon);
718             if(err <0) {
719                 throwError(scon, "Watching fail", JSSensorError::WATCH_ERROR);
720                 return false;
721             }
722             err = sensor_start(scon->handle, SENSOR_PROXIMITY);
723             if(err <0) {
724                 sensor_proximity_unset_cb(scon->handle);
725                 throwError(scon, "Calibration watching fail", JSSensorError::WATCH_ERROR);
726                 return false;
727             }
728             break;
729         default:
730             throwError(scon, "Unknown error", JSSensorError::UNKNOWN_ERROR);
731             return false;
732     }
733
734     scon->status = SENSOR_CON_WATCHING;
735     fireEvent( scon, SENSOR_LISTENER_STATUS, NULL);
736
737     return false;
738 }
739
740 JSValueRef JSSensorConnection::startWatch(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
741 {
742     struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
743     if(scon == NULL)
744         return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
745
746     if(scon->status != SENSOR_CON_OPEN){
747         return JSDOMExceptionFactory::InvalidStateException.make(ctx, exception);
748     }
749
750     if(argumentCount > 0){
751         double threshold = -1, interval = 0;
752         if(!JSValueIsObject(ctx, arguments[0]))
753             return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
754
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);
761         }
762         if(JSObjectHasProperty(ctx, watchOption, pname_interval)){
763             JSValueRef jsv_interval = JSObjectGetProperty(ctx, watchOption, pname_interval, NULL);
764             interval = JSValueToNumber(ctx, jsv_interval, NULL);
765         }
766         JSStringRelease(pname_threshold);
767         JSStringRelease(pname_interval);
768         scon->threshold = threshold;
769         scon->interval = interval;
770     }else{
771         scon->threshold = -1;
772         scon->interval = 0;
773     }
774
775 //    JSSensorDataEvent::setReason(ctx, scon->eventData, JSSENSOR_REASON_WATCH);
776
777     g_idle_add_full(G_PRIORITY_HIGH_IDLE, registerAndStart, scon, NULL);
778
779     return JSValueMakeUndefined(ctx);
780 }
781
782
783 static gboolean deregisterandstop(gpointer user_data)
784 {
785     struct SensorConnection* scon = (struct SensorConnection*) user_data;
786     int err = 0;
787     switch(scon->type){
788         case SENSOR_ACCELEROMETER:
789             err += sensor_stop(scon->handle, SENSOR_ACCELEROMETER);
790             err += sensor_accelerometer_unset_cb(scon->handle);
791             break;
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);
796             break;
797         case SENSOR_ORIENTATION:
798             err += sensor_stop(scon->handle, SENSOR_ORIENTATION);
799             err += sensor_orientation_unset_cb(scon->handle);
800             break;
801         case SENSOR_GYROSCOPE:
802             err += sensor_stop(scon->handle, SENSOR_GYROSCOPE);
803             err += sensor_gyroscope_unset_cb(scon->handle);
804             break;
805         case SENSOR_LIGHT:
806             err += sensor_stop(scon->handle, SENSOR_LIGHT);
807             err += sensor_light_unset_cb(scon->handle);
808             break;
809         case SENSOR_PROXIMITY:
810             err += sensor_stop(scon->handle, SENSOR_PROXIMITY);
811             err += sensor_proximity_unset_cb(scon->handle);
812             break;
813         default:
814             throwError(scon, "Unknown error", JSSensorError::UNKNOWN_ERROR);
815             return false;
816     }
817     if(err <0) {
818         throwError(scon, "End watching fail", JSSensorError::END_WATCH_ERROR);
819         return false;
820     }
821
822     scon->status = SENSOR_CON_OPEN;
823     fireEvent( scon, SENSOR_LISTENER_STATUS, NULL);
824
825     return false;
826 }
827
828 JSValueRef JSSensorConnection::endWatch(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
829 {
830     struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
831     if(scon == NULL)
832         return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
833
834     if(scon->status != SENSOR_CON_WATCHING){
835         return JSDOMExceptionFactory::InvalidStateException.make(ctx, exception);
836     }
837
838     g_idle_add_full(G_PRIORITY_HIGH_IDLE, deregisterandstop, scon, NULL);
839
840     return JSValueMakeUndefined(ctx);
841 }
842
843 static int detectListenerType(std::string& strType)
844 {
845     if(strType.compare("error") == 0){
846         return SENSOR_LISTENER_ERROR;
847     }
848     else if(strType.compare("sensordata") == 0){
849         return SENSOR_LISTENER_DATA;
850     }
851     else if(strType.compare("statuschange") == 0){
852         return SENSOR_LISTENER_STATUS;
853     }
854     else if(strType.compare("calibneed") == 0){
855         return SENSOR_LISTENER_CALIB;
856     }
857     return -1;
858 }
859
860 JSValueRef JSSensorConnection::addEventListener(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
861 {
862     struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
863     Converter converter(ctx);
864
865     if( argumentCount < 2 )
866         return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
867
868     std::string typeStr = converter.toString(arguments[0]);
869     int type = detectListenerType(typeStr);
870
871     if(type < 0){
872         return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
873     }
874
875     addListener(ctx, scon, type, arguments[1]);
876
877     return JSValueMakeUndefined(ctx);
878 }
879
880 JSValueRef JSSensorConnection::removeEventListener(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
881 {
882     struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
883     Converter converter(ctx);
884
885     if( argumentCount < 2 )
886         return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
887
888     std::string typeStr = converter.toString(arguments[0]);
889     int type = detectListenerType(typeStr);
890
891     if(type < 0){
892         return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
893     }
894
895     removeListener(ctx, scon, type, arguments[1]);
896     return JSValueMakeUndefined(ctx);
897 }
898
899 JSValueRef JSSensorConnection::dispatchEvent(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
900 {
901     struct SensorConnection* scon = (struct SensorConnection*) JSObjectGetPrivate(thisObject);
902     Converter converter(ctx);
903
904     if( argumentCount < 1 )
905         return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
906
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);
911
912     std::string typeStr = converter.toString(jsv_type);
913     int type = detectListenerType(typeStr);
914
915     if(type < 0){
916         return JSDOMExceptionFactory::InvalidValuesException.make(ctx, exception);
917     }
918
919     fireEvent( scon, type, event);
920
921     return JSValueMakeBoolean(ctx, true);
922 }
923
924 } // Tizen1_0
925 } // TizenApis
926