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