qtmobility/src/location/liblocationwrapper.cpp
changeset 4 90517678cc4f
child 11 06b8e2af4411
--- /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<void*>(this));
+                posChangedId =
+                    g_signal_connect(G_OBJECT(locationDevice), "changed",
+                                     G_CALLBACK(&locationChanged), 
+                                     static_cast<void*>(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<QGeoSatelliteInfo> satsInView;
+            QList<QGeoSatelliteInfo> satsInUse;
+            unsigned int i;
+            for (i=0;i<device->satellites->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<QGeoSatelliteInfo> &satellites)
+{
+    satsInView = satellites;
+}
+
+void LiblocationWrapper::satellitesInUseUpdated(const QList<QGeoSatelliteInfo> &satellites)
+{
+    satsInUse = satellites;
+}
+
+QList<QGeoSatelliteInfo> LiblocationWrapper::satellitesInView()
+{
+    return satsInView;
+}
+
+QList<QGeoSatelliteInfo> 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<void*>(this));
+        }
+
+        if (!posChangedId) {
+            posChangedId =
+                g_signal_connect(G_OBJECT(locationDevice), "changed",
+                                 G_CALLBACK(&locationChanged), 
+                                 static_cast<void*>(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
+