tizen beta release
[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     m_location = location_new(convertMethodToPlatform(m_currentLocationMethod)); //may return NULL
212     if (NULL == m_location) {
213         ThrowMsg(Commons::PlatformException,
214                  "Couldn't create new location object.");
215     }
216
217     if (LOCATION_ERROR_NONE != location_start(m_location)) {
218         location_free(m_location);
219         m_location = NULL;
220         ThrowMsg(Commons::PlatformException, "Couldn't start localizing.");
221     }
222     m_signalId = g_signal_connect(m_location, "service-updated",
223                                   G_CALLBACK(positionChangedCallback), this);
224 }
225
226 void Geolocation::stop()
227 {
228     LogDebug("ENTER");
229     if (!m_initialized || !m_location) {
230         return;
231     }
232
233     g_signal_handler_disconnect(m_location, m_signalId);
234     if (LOCATION_ERROR_NONE != location_stop(m_location)) {
235         ThrowMsg(Commons::PlatformException, "Couldn't stop location object.");
236     }
237     if (LOCATION_ERROR_NONE != location_free(m_location)) {
238         ThrowMsg(Commons::PlatformException, "Couldn't free location module.");
239     }
240     m_location = NULL;
241 }
242
243 LocationMethod Geolocation::convertMethodToPlatform(ApiLocationMethod method)
244 const
245 {
246     switch (method) {
247     case METHOD_GPS:
248         return LOCATION_METHOD_GPS;
249     case METHOD_AGPS:
250         return LOCATION_METHOD_HYBRID;
251     case METHOD_CPS:
252         return LOCATION_METHOD_CPS;
253     case METHOD_IPS:
254         return LOCATION_METHOD_IPS;
255     case METHOD_WPS:
256         return LOCATION_METHOD_WPS;
257     case METHOD_BEST:
258         return LOCATION_METHOD_HYBRID;
259     }
260     LogError("Unknown location method");
261     return LOCATION_METHOD_HYBRID;
262 }
263 }
264 }
265 }