41fb02c3b99815a9184cc23224890872b90a65a2
[platform/framework/web/wrt-plugins-common.git] / src / modules / tizen / DEPRACATED / Geolocation / Geolocation.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  * @author      Wojciech Bielawski (w.bielawski@samsung.com)
18  */
19
20 #include "Geolocation.h"
21 #include <cassert>
22 #include <API/Geolocation/EventGetCurrentPosition.h>
23 #include <commons/Exception.h>
24
25 using namespace WrtPlugins::Api::Geolocation;
26 using namespace DPL;
27
28 namespace WrtPlugins {
29 namespace Platform {
30 namespace Geolocation {
31 namespace {
32 static void positionChangedCallback(LocationObject *obj,
33                                     guint type,
34                                     gpointer data,
35                                     gpointer accuracy,
36                                     Geolocation* this_)
37 {
38     if (this_) {
39         this_->positionHasChanged(obj, type, data, accuracy);
40     } else {
41         LogError("Callback private data is NULL.");
42     }
43 }
44 } //private namespace
45
46 Geolocation::Geolocation() :
47     m_location(NULL),
48     m_currentLocationMethod(METHOD_GPS),
49     m_initialized(false)
50 {
51     LogDebug("Enter");
52 }
53
54 Geolocation::~Geolocation()
55 {
56     LogDebug("Enter");
57     stop();
58 }
59
60 void Geolocation::getCurrentPosition(const EventGetCurrentPositionPtr& event)
61 {
62     initialize();
63     EventRequestReceiver<EventGetCurrentPosition>::PostRequest(event);
64 }
65
66 void Geolocation::OnRequestReceived(const EventGetCurrentPositionPtr& event)
67 {
68     LogDebug("Entered");
69     gint ret;
70     LocationPosition* pos = NULL;
71     LocationAccuracy* acc = NULL;
72     ret = location_get_position(m_location, &pos, &acc);
73     if (LOCATION_ERROR_NONE != ret) {
74         event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
75         return;
76     } else if (LOCATION_ACCURACY_LEVEL_NONE != acc->level) {
77         location_position_free(pos);
78         location_accuracy_free(acc);
79         event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
80         return;
81     }
82     event->setTimestamp(static_cast<std::time_t>(pos->timestamp));
83     event->setLatitude(static_cast<double>(pos->latitude));
84     event->setLongitude(static_cast<double>(pos->longitude));
85     event->setAltitude(static_cast<double>(pos->altitude));
86     event->setAccuracy(static_cast<double>(acc->horizontal_accuracy));
87     event->setAltitudeAccuracy(static_cast<double>(acc->vertical_accuracy));
88     location_position_free(pos);
89     location_accuracy_free(acc);
90
91     LocationVelocity* velocity = NULL;
92     ret = location_get_velocity(m_location, &velocity, &acc);
93     if (LOCATION_ERROR_NONE != ret) {
94         event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
95         return;
96     } else if (LOCATION_ACCURACY_LEVEL_NONE != acc->level) {
97         location_velocity_free(velocity);
98         location_accuracy_free(acc);
99         event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
100         return;
101     }
102     event->setSpeed(static_cast<double>(velocity->speed));
103     event->setDirection(static_cast<double>(velocity->direction));
104     event->setAltitudeSpeed(static_cast<double>(velocity->climb));
105     event->setMethod(m_currentLocationMethod);
106     location_velocity_free(velocity);
107     location_accuracy_free(acc);
108 }
109
110 long Geolocation::watchPosition(const EventPositionChangedEmitterPtr& emitter,
111                                 long timeout,
112                                 long maximumAge,
113                                 bool highAccuracy)
114 {
115     initialize();
116     m_positionEmitters.attach(emitter);
117     return static_cast<long>(emitter->getId());
118 }
119
120 void Geolocation::clearWatch(EventPositionChangedEmitter::IdType id)
121 {
122     m_positionEmitters.detach(id);
123 }
124
125 void Geolocation::positionHasChanged(LocationObject *obj,
126                                      guint type,
127                                      gpointer data,
128                                      gpointer accuracy)
129 {
130     LogDebug("Enter");
131     if (POSITION_UPDATED != type) {
132         //nothing to do
133         return;
134     }
135
136     //convert data from platform to API form
137     LocationPosition *pos = static_cast<LocationPosition*>(data);
138     LocationAccuracy *acc = static_cast<LocationAccuracy*>(accuracy);
139     LocationVelocity* velocity = NULL;
140
141     EventPositionChangedPtr event(new EventPositionChanged());
142     PositionProperties props;
143     props.altitude = static_cast<double>(pos->altitude);
144     props.latitude = static_cast<double>(pos->latitude);
145     props.longitude = static_cast<double>(pos->longitude);
146     props.timestamp = static_cast<std::time_t>(pos->timestamp);
147     props.accuracy = static_cast<double>(acc->horizontal_accuracy);
148     props.altitudeAccuracy = static_cast<double>(acc->vertical_accuracy);
149
150     gint ret = location_get_velocity(m_location, &velocity, &acc);
151     if (LOCATION_ERROR_NONE != ret) {
152         event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
153         return;
154     } else if (LOCATION_ACCURACY_LEVEL_NONE != acc->level) {
155         location_velocity_free(velocity);
156         location_accuracy_free(acc);
157         event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
158         return;
159     }
160     props.speed = static_cast<double>(velocity->speed);
161     props.direction = static_cast<double>(velocity->direction);
162     props.altitudeSpeed = static_cast<double>(velocity->climb);
163     location_velocity_free(velocity);
164     location_accuracy_free(acc);
165
166     event->setPositionProperties(props);
167     m_positionEmitters.emit(event);
168 }
169
170 void Geolocation::changeLocationMethod(ApiLocationMethod method)
171 {
172     LogDebug("Enter");
173     if (method != m_currentLocationMethod) {
174         m_currentLocationMethod = method;
175         if (m_location) {
176             restart();
177         }
178     }
179 }
180
181 void Geolocation::initialize()
182 {
183     LogDebug("ENTER");
184     if (!m_initialized) {
185         DPL::Mutex::ScopedLock lock(&m_initializationMutex);
186         if (!m_initialized) {
187             if (LOCATION_ERROR_NONE != location_init()) {
188                 ThrowMsg(Commons::PlatformException,
189                          "Couldn't init location module.");
190             }
191             m_initialized = true;
192             start();
193         }
194     }
195 }
196
197 void Geolocation::restart()
198 {
199     stop();
200     start();
201 }
202
203 void Geolocation::start()
204 {
205     LogDebug("ENTER");
206     assert(m_initialized && "Geolocation has not been initialized.");
207     if (m_location) {
208         return;
209     }
210
211     //may return NULL
212     m_location = location_new(convertMethodToPlatform(m_currentLocationMethod));
213
214     if (NULL == m_location) {
215         ThrowMsg(Commons::PlatformException,
216                  "Couldn't create new location object.");
217     }
218
219     if (LOCATION_ERROR_NONE != location_start(m_location)) {
220         location_free(m_location);
221         m_location = NULL;
222         ThrowMsg(Commons::PlatformException, "Couldn't start localizing.");
223     }
224     m_signalId = g_signal_connect(m_location, "service-updated",
225                                   G_CALLBACK(positionChangedCallback), this);
226 }
227
228 void Geolocation::stop()
229 {
230     LogDebug("ENTER");
231     if (!m_initialized || !m_location) {
232         return;
233     }
234
235     g_signal_handler_disconnect(m_location, m_signalId);
236     if (LOCATION_ERROR_NONE != location_stop(m_location)) {
237         ThrowMsg(Commons::PlatformException, "Couldn't stop location object.");
238     }
239     if (LOCATION_ERROR_NONE != location_free(m_location)) {
240         ThrowMsg(Commons::PlatformException, "Couldn't free location module.");
241     }
242     m_location = NULL;
243 }
244
245 LocationMethod Geolocation::convertMethodToPlatform(ApiLocationMethod method)
246 const
247 {
248     switch (method) {
249     case METHOD_GPS:
250         return LOCATION_METHOD_GPS;
251     case METHOD_AGPS:
252         return LOCATION_METHOD_HYBRID;
253     case METHOD_CPS:
254         return LOCATION_METHOD_CPS;
255     case METHOD_IPS:
256         return LOCATION_METHOD_IPS;
257     case METHOD_WPS:
258         return LOCATION_METHOD_WPS;
259     case METHOD_BEST:
260         return LOCATION_METHOD_HYBRID;
261     }
262     LogError("Unknown location method");
263     return LOCATION_METHOD_HYBRID;
264 }
265 }
266 }
267 }