2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @author Wojciech Bielawski (w.bielawski@samsung.com)
20 #include "Geolocation.h"
22 #include <API/Geolocation/EventGetCurrentPosition.h>
23 #include <commons/Exception.h>
25 using namespace WrtPlugins::Api::Geolocation;
28 namespace WrtPlugins {
30 namespace Geolocation {
32 static void positionChangedCallback(LocationObject *obj,
39 this_->positionHasChanged(obj, type, data, accuracy);
41 LogError("Callback private data is NULL.");
46 Geolocation::Geolocation() :
48 m_currentLocationMethod(METHOD_GPS),
54 Geolocation::~Geolocation()
60 void Geolocation::getCurrentPosition(const EventGetCurrentPositionPtr& event)
63 EventRequestReceiver<EventGetCurrentPosition>::PostRequest(event);
66 void Geolocation::OnRequestReceived(const EventGetCurrentPositionPtr& event)
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);
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);
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);
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);
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);
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);
110 long Geolocation::watchPosition(const EventPositionChangedEmitterPtr& emitter,
116 m_positionEmitters.attach(emitter);
117 return static_cast<long>(emitter->getId());
120 void Geolocation::clearWatch(EventPositionChangedEmitter::IdType id)
122 m_positionEmitters.detach(id);
125 void Geolocation::positionHasChanged(LocationObject *obj,
131 if (POSITION_UPDATED != type) {
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;
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);
150 gint ret = location_get_velocity(m_location, &velocity, &acc);
151 if (LOCATION_ERROR_NONE != ret) {
152 event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
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);
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);
166 event->setPositionProperties(props);
167 m_positionEmitters.emit(event);
170 void Geolocation::changeLocationMethod(ApiLocationMethod method)
173 if (method != m_currentLocationMethod) {
174 m_currentLocationMethod = method;
181 void Geolocation::initialize()
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.");
191 m_initialized = true;
197 void Geolocation::restart()
203 void Geolocation::start()
206 assert(m_initialized && "Geolocation has not been initialized.");
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.");
217 if (LOCATION_ERROR_NONE != location_start(m_location)) {
218 location_free(m_location);
220 ThrowMsg(Commons::PlatformException, "Couldn't start localizing.");
222 m_signalId = g_signal_connect(m_location, "service-updated",
223 G_CALLBACK(positionChangedCallback), this);
226 void Geolocation::stop()
229 if (!m_initialized || !m_location) {
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.");
237 if (LOCATION_ERROR_NONE != location_free(m_location)) {
238 ThrowMsg(Commons::PlatformException, "Couldn't free location module.");
243 LocationMethod Geolocation::convertMethodToPlatform(ApiLocationMethod method)
248 return LOCATION_METHOD_GPS;
250 return LOCATION_METHOD_HYBRID;
252 return LOCATION_METHOD_CPS;
254 return LOCATION_METHOD_IPS;
256 return LOCATION_METHOD_WPS;
258 return LOCATION_METHOD_HYBRID;
260 LogError("Unknown location method");
261 return LOCATION_METHOD_HYBRID;