tizen beta release
[framework/web/wrt-plugins-common.git] / src / modules / tizen / Orientation / Orientation.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 /*
17  * @file          Orientation.cpp
18  * @author      Qi Xiangguo (xiangguo.qi@samsung.com)
19  * @version     0.1
20  * @brief
21  */
22
23 #include <cassert>
24 #include <Orientation/EventGetCurrentOrientation.h>
25 #include <Commons/Exception.h>
26 #include "Orientation.h"
27
28 using namespace DPL;
29
30 namespace WrtDeviceApis {
31 namespace Orientation {
32
33 using namespace Api;
34
35 namespace {
36 /**
37  * Callback method called by platform as interval time.
38  * @param event_type Platform orientation evet type
39  * @param event Platform sensor event data
40  * @param this_ User data pointer.
41  */
42 static void OrientationChangedCallback(unsigned int event_type,
43         sensor_event_data_t *event,
44         void *watcher_ptr)
45 {
46     LogDebug("Callback OrientationChangedCallback.");
47     if (watcher_ptr) {
48         if (event_type == GEOMAGNETIC_EVENT_ATTITUDE_DATA_REPORT_ON_TIME &&
49             event != NULL) {
50             ((Orientation::Watcher*)watcher_ptr)->orientationHasChanged(event);
51         }
52     } else {
53         LogError("Callback private data is NULL.");
54     }
55 }
56 } //private namespace
57
58 Orientation::Orientation() :
59     m_handle(-1),
60     m_initialized(false),
61     m_isWatch(false)
62 {
63     LogDebug("Platform::Orientation Enter");
64 }
65
66 Orientation::~Orientation()
67 {
68     LogDebug("Enter");
69
70     if (m_initialized == true) {
71         stop(m_handle);
72     }
73
74     LogDebug("All watchers : (" << m_watchers.size() << ")");
75     std::vector<WatcherPtr>::iterator it;
76     for (it = m_watchers.begin(); it != m_watchers.end(); ++it) {
77         stop((*it)->getHandle(), true);
78     }
79     m_watchers.clear();
80     LogDebug("All watchers were cleared. (" << m_watchers.size() << ")");
81 }
82
83 void Orientation::getCurrentOrientation(
84         const EventGetCurrentOrientationPtr& event)
85 {
86     LogDebug("Entered");
87
88     if (m_initialized == false) {
89         m_handle = initialize();
90         start(m_handle);
91         m_initialized = true;
92     }
93     EventRequestReceiver<EventGetCurrentOrientation>::PostRequest(event);
94 }
95
96 void Orientation::OnRequestReceived(const EventGetCurrentOrientationPtr& event)
97 {
98     LogDebug("Entered");
99     sensor_data_t data;
100     memset(&data, 0, sizeof(sensor_data_t));
101     /**
102      * Invoke platform API sf_get_data gets raw data from a sensor with connecting the sensor-server.
103      * The type of sensor is supplied and return data is stored in the output parameter values [].
104      */
105     if ((sf_get_data(m_handle, GEOMAGNETIC_BASE_DATA_SET, &data) < 0) ||
106         (data.values_num < 3)) {
107         LogError("Can't get current Orientation. ");
108         Throw(Commons::PlatformException);
109     }
110
111     event->setAlpha(static_cast<double>(data.values[0]));
112     event->setBeta(static_cast<double>(data.values[1]));
113     event->setGamma(static_cast<double>(data.values[2]));
114 }
115
116 long Orientation::watchOrientation(
117         const EventOrientationChangedEmitterPtr& emitter,
118         long minNotificationInterval)
119 {
120     LogDebug("Entered");
121     int new_handle = initialize();
122     int sensor_state = 0;
123     event_condition_t condition;
124     condition.cond_op = CONDITION_EQUAL;
125     condition.cond_value1 = minNotificationInterval;
126     /**
127      * Invoke platform API sf_register_event registers a user defined callback function with a connected sensor for a particular event.
128      **This callback function will be called when there is a change in the state of respective sensor.
129      **cb_data will be the parameter used during the callback call.
130      **Callback interval can be adjusted using even_contion_t argument.
131      */
132     WatcherPtr watcher(new Watcher(new_handle, emitter));
133
134     sensor_state = sf_register_event(
135             watcher->getHandle(),
136             GEOMAGNETIC_EVENT_ATTITUDE_DATA_REPORT_ON_TIME, &condition,
137             OrientationChangedCallback, watcher.Get());
138     if (sensor_state < 0) {
139         stop(watcher->getHandle());
140         Throw(Commons::PlatformException);
141     }
142     m_isWatch = true;
143     start(watcher->getHandle());
144     m_watchers.push_back(watcher);
145     watcher->getCurrentOrientationForWatch();
146     return static_cast<long>(emitter->getId());
147 }
148
149 void Orientation::clearWatch(EventOrientationChangedEmitter::IdType id)
150 {
151     LogDebug("Entered");
152
153     std::vector<WatcherPtr>::iterator it;
154     for (it = m_watchers.begin(); it != m_watchers.end(); ++it) {
155         if (id == (*it)->getEmitter()->getId()) {
156             stop((*it)->getHandle(), true);
157
158             m_watchers.erase(it);
159             LogDebug("Watcher is removed. (" << m_watchers.size() << ")");
160
161             if (m_watchers.size() == 0) {
162                 m_isWatch = false;
163             }
164             break;
165         }
166     }
167 }
168
169 void Orientation::OrientationHasChanged(sensor_event_data_t *sensorEvent)
170 {
171     LogDebug("Entered");
172
173     sensor_data_t *sensor_data = NULL;
174     sensor_data = (sensor_data_t *)sensorEvent->event_data;
175     if (sensor_data == NULL ||
176         (sensor_data->values_num < 3)) {
177         LogError("Can't get current Acceleration. ");
178         Throw(Commons::PlatformException);
179         return;
180     }
181
182     EventOrientationChangedPtr event(new EventOrientationChanged());
183     OrientationProperties props;
184     props.alpha = static_cast<double>(sensor_data->values[0]);
185     props.beta = static_cast<double>(-(sensor_data->values[1]));
186     props.gamma = static_cast<double>(-(sensor_data->values[2]));
187
188     LogDebug(
189         "alpha" << props.alpha << ",beta" << props.beta << ",gamma" <<
190         props.gamma);
191
192     event->setOrientationProperties(props);
193
194     m_OrientationEmitters.emit(event);
195 }
196
197 void Orientation::getCurrentOrientationForWatch(void)
198 {
199     LogDebug("Entered");
200     sensor_data_t data;
201     memset(&data, 0, sizeof(sensor_data_t));
202     if ((sf_get_data(m_handle, GEOMAGNETIC_BASE_DATA_SET, &data) < 0) ||
203         (data.values_num < 3)) {
204         Throw(Commons::PlatformException);
205     }
206
207     EventOrientationChangedPtr event(new EventOrientationChanged());
208     OrientationProperties props;
209     props.alpha = static_cast<double>(data.values[0]);
210     props.beta = static_cast<double>(-(data.values[1]));
211     props.gamma = static_cast<double>(-(data.values[2]));
212
213     event->setOrientationProperties(props);
214
215     m_OrientationEmitters.emit(event);
216 }
217
218 int Orientation::initialize()
219 {
220     LogDebug("Entered");
221     DPL::Mutex::ScopedLock lock(&m_initializationMutex);
222     int handle = sf_connect(GEOMAGNETIC_SENSOR);
223     if (handle < 0) {
224         LogError("Could not connect with orientation sensor.");
225         Throw(Commons::UnsupportedException);
226     }
227     return handle;
228 }
229
230 void Orientation::restart(int& handle)
231 {
232     stop(handle);
233     start(handle);
234 }
235
236 void Orientation::start(int handle)
237 {
238     LogDebug("Entered");
239     if (sf_start(handle, 0) < 0) {
240         LogError("Could not start communication with sensor.");
241         if (handle >= 0) {
242             sf_disconnect(handle);
243             Throw(Commons::UnsupportedException);
244         }
245     } else {
246         // TODO: find the way to fix this
247         usleep(100000);
248     }
249 }
250
251 void Orientation::stop(int& handle,
252         bool isWatcherHandle)
253 {
254     LogDebug("Entered");
255
256     if (handle >= 0) {
257         if (isWatcherHandle == true) {
258             sf_unregister_event(handle,
259                                 GEOMAGNETIC_EVENT_ATTITUDE_DATA_REPORT_ON_TIME);
260         }
261         sf_stop(handle);
262         sf_disconnect(handle);
263         handle = -1;
264     }
265 }
266
267 //Watcher's
268 void Orientation::Watcher::getCurrentOrientationForWatch()
269 {
270     LogDebug("Enter");
271     sensor_data_t data;
272     memset(&data, 0, sizeof(sensor_data_t));
273     if ((sf_get_data(m_handle, GEOMAGNETIC_BASE_DATA_SET, &data) < 0) ||
274         (data.values_num < 3)) {
275         Throw(Commons::PlatformException);
276     }
277
278     EventOrientationChangedPtr event(new EventOrientationChanged());
279     OrientationProperties props;
280     props.alpha = static_cast<double>(data.values[0]);
281     props.beta = static_cast<double>(data.values[1]);
282     props.gamma = static_cast<double>(data.values[2]);
283
284     event->setOrientationProperties(props);
285
286     emit(event);
287 }
288
289 //Watcher's
290 void Orientation::Watcher::orientationHasChanged(
291         sensor_event_data_t *sensorEvent)
292 {
293     LogDebug("Enter");
294     sensor_data_t *sensor_data = NULL;
295     sensor_data = (sensor_data_t *)sensorEvent->event_data;
296     if (sensor_data == NULL ||
297         (sensor_data->values_num < 3)) {
298         LogError("Can't get current Orientation. ");
299         Throw(Commons::PlatformException);
300         return;
301     }
302
303     EventOrientationChangedPtr event(new EventOrientationChanged());
304     OrientationProperties props;
305     props.alpha = static_cast<double>(sensor_data->values[0]);
306     props.beta = static_cast<double>(sensor_data->values[1]);
307     props.gamma = static_cast<double>(sensor_data->values[2]);
308     LogDebug(
309         "alpha:" << sensor_data->values[0] << ",beta:" <<
310         sensor_data->values[1] << ",gamma:" << sensor_data->values[2]);
311
312     event->setOrientationProperties(props);
313
314     emit(event);
315 }
316
317 }
318 }