diff -r 2b40d63a9c3d -r 90517678cc4f qtmobility/src/location/liblocationwrapper.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qtmobility/src/location/liblocationwrapper.cpp Mon May 03 13:18:40 2010 +0300 @@ -0,0 +1,385 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "liblocationwrapper_p.h" + +using namespace std; + +QTM_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC(LiblocationWrapper, LocationEngine) + +LiblocationWrapper *LiblocationWrapper::instance() +{ + return LocationEngine(); +} + +LiblocationWrapper::~LiblocationWrapper() +{ + if (locationDevice) + g_object_unref(locationDevice); + if (locationControl) + g_object_unref(locationControl); +} + +bool LiblocationWrapper::inited() +{ + int retval = false; + if (!(locationState & LiblocationWrapper::Inited)) { + g_type_init(); + + locationControl = location_gpsd_control_get_default(); + + if (locationControl) { + g_object_set(G_OBJECT(locationControl), + "preferred-method", LOCATION_METHOD_USER_SELECTED, + "preferred-interval", LOCATION_INTERVAL_1S, + NULL); + locationDevice = + (LocationGPSDevice*)g_object_new(LOCATION_TYPE_GPS_DEVICE, + NULL); + + if (locationDevice) { + errorHandlerId = + g_signal_connect(G_OBJECT(locationControl), "error-verbose", + G_CALLBACK(&locationError), + static_cast(this)); + posChangedId = + g_signal_connect(G_OBJECT(locationDevice), "changed", + G_CALLBACK(&locationChanged), + static_cast(this)); + locationState = LiblocationWrapper::Inited; + retval = true; + startcounter = 0; + } + } + } else { + retval = true; + } + return retval; +} + +void LiblocationWrapper::locationError(LocationGPSDevice *device, + gint errorCode, gpointer data) +{ + Q_UNUSED(device); + QString locationError; + + switch (errorCode) { + case LOCATION_ERROR_USER_REJECTED_DIALOG: + locationError = "User didn't enable requested methods"; + break; + case LOCATION_ERROR_USER_REJECTED_SETTINGS: + locationError = "User changed settings, which disabled location."; + break; + case LOCATION_ERROR_BT_GPS_NOT_AVAILABLE: + locationError = "Problems with BT GPS"; + break; + case LOCATION_ERROR_METHOD_NOT_ALLOWED_IN_OFFLINE_MODE: + locationError = "Requested method is not allowed in offline mode"; + break; + case LOCATION_ERROR_SYSTEM: + locationError = "System error."; + break; + default: + locationError = "Unknown error."; + } + + qDebug() << "Location error:" << locationError; + + LiblocationWrapper *object; + object = (LiblocationWrapper *)data; + emit object->error(); +} + +void LiblocationWrapper::locationChanged(LocationGPSDevice *device, + gpointer data) +{ + QGeoPositionInfo posInfo; + QGeoCoordinate coordinate; + QGeoSatelliteInfo satInfo; + int satellitesInUseCount = 0; + LiblocationWrapper *object; + + if (!data || !device) { + return; + } + + object = (LiblocationWrapper *)data; + + if (device) { + if (device->fix) { + if (device->fix->fields & LOCATION_GPS_DEVICE_TIME_SET) { + posInfo.setTimestamp(QDateTime::fromTime_t(device->fix->time)); + } + + if (device->fix->fields & LOCATION_GPS_DEVICE_LATLONG_SET) { + coordinate.setLatitude(device->fix->latitude); + coordinate.setLongitude(device->fix->longitude); + posInfo.setAttribute(QGeoPositionInfo::HorizontalAccuracy, + device->fix->eph); + posInfo.setAttribute(QGeoPositionInfo::VerticalAccuracy, + device->fix->epv); + } + + if (device->fix->fields & LOCATION_GPS_DEVICE_ALTITUDE_SET) { + coordinate.setAltitude(device->fix->altitude); + } + + if (device->fix->fields & LOCATION_GPS_DEVICE_SPEED_SET) { + posInfo.setAttribute(QGeoPositionInfo::GroundSpeed, + device->fix->speed); + } + + if (device->fix->fields & LOCATION_GPS_DEVICE_CLIMB_SET) { + posInfo.setAttribute(QGeoPositionInfo::VerticalSpeed, + device->fix->climb); + } + + if (device->fix->fields & LOCATION_GPS_DEVICE_TRACK_SET) { + posInfo.setAttribute(QGeoPositionInfo::Direction, + device->fix->track); + } + } + + if (device->satellites_in_view) { + QList satsInView; + QList satsInUse; + unsigned int i; + for (i=0;isatellites->len;i++) { + LocationGPSDeviceSatellite *satData = + (LocationGPSDeviceSatellite *)g_ptr_array_index(device->satellites, + i); + satInfo.setSignalStrength(satData->signal_strength); + satInfo.setPrnNumber(satData->prn); + satInfo.setAttribute(QGeoSatelliteInfo::Elevation, + satData->elevation); + satInfo.setAttribute(QGeoSatelliteInfo::Azimuth, + satData->azimuth); + + satsInView.append(satInfo); + if (satData->in_use) { + satellitesInUseCount++; + satsInUse.append(satInfo); + } + } + + if (!satsInView.isEmpty()) + object->satellitesInViewUpdated(satsInView); + + if (!satsInUse.isEmpty()) + object->satellitesInUseUpdated(satsInUse); + } + } + + posInfo.setCoordinate(coordinate); + + if ((device->fix->fields & LOCATION_GPS_DEVICE_TIME_SET) && + ((device->fix->mode == LOCATION_GPS_DEVICE_MODE_3D) || + (device->fix->mode == LOCATION_GPS_DEVICE_MODE_2D))) { + object->setLocation(posInfo, true); + } else { + object->setLocation(posInfo, false); + } +} + +void LiblocationWrapper::setLocation(const QGeoPositionInfo &update, + bool locationValid) +{ + validLastSatUpdate = locationValid; + lastSatUpdate = update; +} + +QGeoPositionInfo LiblocationWrapper::position() { + return lastSatUpdate; +} + +bool LiblocationWrapper::fixIsValid() +{ + return validLastSatUpdate; +} + +QGeoPositionInfo LiblocationWrapper::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const +{ + QGeoPositionInfo posInfo; + QGeoCoordinate coordinate; + double time; + double latitude; + double longitude; + double altitude; + double speed; + double track; + double climb; + + GConfItem lastKnownPositionTime("/system/nokia/location/lastknown/time"); + GConfItem lastKnownPositionLatitude("/system/nokia/location/lastknown/latitude"); + GConfItem lastKnownPositionLongitude("/system/nokia/location/lastknown/longitude"); + GConfItem lastKnownPositionAltitude("/system/nokia/location/lastknown/altitude"); + GConfItem lastKnownPositionSpeed("/system/nokia/location/lastknown/speed"); + GConfItem lastKnownPositionTrack("/system/nokia/location/lastknown/track"); + GConfItem lastKnownPositionClimb("/system/nokia/location/lastknown/climb"); + + if (validLastSatUpdate) + return lastSatUpdate; + + if (!fromSatellitePositioningMethodsOnly) + if (validLastUpdate) + return lastUpdate; + + time = lastKnownPositionTime.value().toDouble(); + latitude = lastKnownPositionLatitude.value().toDouble(); + longitude = lastKnownPositionLongitude.value().toDouble(); + altitude = lastKnownPositionAltitude.value().toDouble(); + speed = lastKnownPositionSpeed.value().toDouble(); + track = lastKnownPositionTrack.value().toDouble(); + climb = lastKnownPositionClimb.value().toDouble(); + + if (longitude && latitude) { + coordinate.setLongitude(longitude); + coordinate.setLatitude(latitude); + if (altitude) { + coordinate.setAltitude(altitude); + } + posInfo.setCoordinate(coordinate); + } + + if (speed) { + posInfo.setAttribute(QGeoPositionInfo::GroundSpeed, speed); + } + + if (track) { + posInfo.setAttribute(QGeoPositionInfo::Direction, track); + } + + if (climb) { + posInfo.setAttribute(QGeoPositionInfo::VerticalSpeed, climb); + } + + // Only positions with time (3D) are provided. + if (time) { + posInfo.setTimestamp(QDateTime::fromTime_t(time)); + return posInfo; + } + + return QGeoPositionInfo(); +} + +void LiblocationWrapper::satellitesInViewUpdated(const QList &satellites) +{ + satsInView = satellites; +} + +void LiblocationWrapper::satellitesInUseUpdated(const QList &satellites) +{ + satsInUse = satellites; +} + +QList LiblocationWrapper::satellitesInView() +{ + return satsInView; +} + +QList LiblocationWrapper::satellitesInUse() +{ + return satsInUse; +} + +void LiblocationWrapper::start() { + startcounter++; + + if ((locationState & LiblocationWrapper::Inited) && + !(locationState & LiblocationWrapper::Started)) { + if (!errorHandlerId) { + errorHandlerId = + g_signal_connect(G_OBJECT(locationControl), "error-verbose", + G_CALLBACK(&locationError), + static_cast(this)); + } + + if (!posChangedId) { + posChangedId = + g_signal_connect(G_OBJECT(locationDevice), "changed", + G_CALLBACK(&locationChanged), + static_cast(this)); + } + + location_gpsd_control_start(locationControl); + + locationState |= LiblocationWrapper::Started; + locationState &= ~LiblocationWrapper::Stopped; + } +} + +void LiblocationWrapper::stop() { + startcounter--; + + if (startcounter > 0) + return; + + if ((locationState & (LiblocationWrapper::Started | + LiblocationWrapper::Inited)) && + !(locationState & LiblocationWrapper::Stopped)) { + if (errorHandlerId) + g_signal_handler_disconnect(G_OBJECT(locationControl), + errorHandlerId); + if (posChangedId) + g_signal_handler_disconnect(G_OBJECT(locationDevice), + posChangedId); + errorHandlerId = 0; + posChangedId = 0; + startcounter = 0; + location_gpsd_control_stop(locationControl); + + locationState &= ~LiblocationWrapper::Started; + locationState |= LiblocationWrapper::Stopped; + } +} + +bool LiblocationWrapper::isActive() { + if (locationState & LiblocationWrapper::Started) + return true; + else + return false; +} + +#include "moc_liblocationwrapper_p.cpp" +QTM_END_NAMESPACE +