/****************************************************************************
**
** 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 "qgeopositioninfosource_s60_p.h"
#include "qgeosatelliteinfosource_s60_p.h"
#include "qmlbackendao_s60_p.h"
QTM_BEGIN_NAMESPACE
//The name of the requestor //Added by PM
//_LIT(KRequestor,"QTMobility Location");
// constructor
CQMLBackendAO::CQMLBackendAO() :
CActive(EPriorityStandard), // Standard priority
mPosInfo(NULL),
mRequester(NULL),
mRequesterSatellite(NULL),
mRequestType(RequestType(0))
{
}
//
//
//
CQMLBackendAO* CQMLBackendAO::NewLC(QObject *aRequester,
RequestType aRequestType, TPositionModuleId aModId)
{
CQMLBackendAO* self = new(ELeave) CQMLBackendAO();
CleanupStack::PushL(self);
self->ConstructL(aRequester, aRequestType, aModId);
return self;
}
//
//
//
CQMLBackendAO* CQMLBackendAO::NewL(QObject *aRequester,
RequestType aRequestType, TPositionModuleId aModId)
{
CQMLBackendAO* self = CQMLBackendAO::NewLC(aRequester, aRequestType, aModId);
CleanupStack::Pop(); // self;
return self;
}
//
//
//
TInt CQMLBackendAO::ConstructL(QObject *aRequester, RequestType aRequestType,
TPositionModuleId aModId)
{
TInt error = KErrNone;
RPositionServer PosServer;
if (aRequester->inherits("QGeoSatelliteInfoSource"))
mRequesterSatellite = static_cast<CQGeoSatelliteInfoSourceS60*>(aRequester);
else
mRequester = static_cast<CQGeoPositionInfoSourceS60*>(aRequester);
mRequestType = aRequestType;
if ((mRequestType == RegularUpdate) || (mRequestType == OnceUpdate)) {
if (aRequester->inherits("QGeoSatelliteInfoSource"))
PosServer = mRequesterSatellite->getPositionServer();
else
PosServer = mRequester->getPositionServer();
error = mPositioner.Open(PosServer, aModId);
if (error != KErrNone)
return error;
CleanupClosePushL(mPositioner);
error = mPositioner.SetRequestor(CRequestor::ERequestorService ,
CRequestor::EFormatApplication, _L("QTmobility_Location"));
CleanupStack::Pop(1);
if (error != KErrNone)
return error;
}
CActiveScheduler::Add(this); // Add to scheduler
return error;
}
//
CQMLBackendAO::~CQMLBackendAO()
{
Cancel();
if ((mRequestType == OnceUpdate) || (mRequestType == RegularUpdate)) {
//close the subsession
mPositioner.Close();
if (mPosInfo) {
mPosInfo->ClearRequestedFields();
mPosInfo->ClearPositionData();
//delete the HPositionGenericInfo
delete mPosInfo;
}
} else if (mRequestType == DeviceStatus) {
RPositionServer posServer;
//done only by the position server Active Object
if (mRequester)
posServer = mRequester->getPositionServer();
else
posServer = mRequesterSatellite->getPositionServer();
posServer.Close();
}
}
//
void CQMLBackendAO::DoCancel()
{
CancelAll();
}
//
void CQMLBackendAO::RunL()
{
switch (mRequestType) {
case DeviceStatus :
handleDeviceNotification(iStatus.Int());
break;
case RegularUpdate :
case OnceUpdate:
handlePosUpdateNotification(iStatus.Int());
break;
default :
break;
}
}
//
TInt CQMLBackendAO::RunError(TInt aError)
{
return aError;
}
// checks any pending request in activeobject
bool CQMLBackendAO::isRequestPending()
{
if (IsActive())
return true;
else
return false;
}
// Async call to get notifications about device status.
void CQMLBackendAO::notifyDeviceStatus(TPositionModuleStatusEventBase &aStatusEvent)
{
RPositionServer PosServ;
if (mRequester)
PosServ = mRequester->getPositionServer();
else
PosServ = mRequesterSatellite->getPositionServer();
//register for device status events
TPositionModuleStatusEventBase::TModuleEvent RequestedEvents(
TPositionModuleStatusEventBase::EEventDeviceStatus);
aStatusEvent.SetRequestedEvents(RequestedEvents);
PosServ.NotifyModuleStatusEvent(aStatusEvent, iStatus);
SetActive();
}
void CQMLBackendAO::CancelAll()
{
RPositionServer PosServer;
if (mRequestType == DeviceStatus) {
if (mRequester)
PosServer = mRequester->getPositionServer();
else
PosServer = mRequesterSatellite->getPositionServer();
PosServer.CancelRequest(EPositionServerNotifyModuleStatusEvent);
} else if ((mRequestType == OnceUpdate) || (mRequestType == RegularUpdate)) {
mPositioner.CancelRequest(EPositionerNotifyPositionUpdate);
}
}
//Initialize the posInfo with appropriate fields
bool CQMLBackendAO::initializePosInfo()
{
if (!mPosInfo) {
mPosInfo = HPositionGenericInfo::New();
if (mPosInfo == NULL)
return FALSE;
} else {
mPosInfo->ClearRequestedFields();
mPosInfo->ClearPositionData();
}
RPositionServer posServer;
TPositionModuleInfo moduleInfo;
TInt error = KErrNone;
//get the posiiton server
posServer = mRequester->getPositionServer();
//retrieve the module id used by the posiitoner
if (mRequestType == RegularUpdate)
error = posServer.GetModuleInfoById(mRequester->getCurrentPositonModuleID(), moduleInfo);
else
error = posServer.GetModuleInfoById(mRequester->getRequestUpdateModuleID(), moduleInfo);
if (error == KErrNone) {
//get capabilities of the module
TPositionModuleInfo::TCapabilities caps = moduleInfo.Capabilities();
if (caps & TPositionModuleInfo::ECapabilitySatellite) {
mPosInfo->SetRequestedField(EPositionFieldSatelliteNumInView);
mPosInfo->SetRequestedField(EPositionFieldSatelliteNumUsed);
}
if (caps & TPositionModuleInfo::ECapabilitySpeed) {
mPosInfo->SetRequestedField(EPositionFieldHorizontalSpeed);
mPosInfo->SetRequestedField(EPositionFieldVerticalSpeed);
}
if (caps & TPositionModuleInfo::ECapabilityCompass) {
mPosInfo->SetRequestedField(EPositionFieldMagneticCourseError);
mPosInfo->SetRequestedField(EPositionFieldHeading);
}
return TRUE;
}
return FALSE;
}
//requestUpdate : request for position update once
void CQMLBackendAO::requestUpdate(int aTimeout)
{
TPositionUpdateOptions aPosOption;
mPositioner.GetUpdateOptions(aPosOption);
aPosOption.SetUpdateInterval(TTimeIntervalMicroSeconds(0));
aPosOption.SetUpdateTimeOut(TTimeIntervalMicroSeconds(aTimeout * 1000));
mPositioner.SetUpdateOptions(aPosOption);
startUpdates();
}
//
void CQMLBackendAO::cancelUpdate()
{
Cancel();
}
//
void CQMLBackendAO::handleDeviceNotification(int aError)
{
switch (aError) {
//NotifyPositionModulestatusEvent successfully completed
case KErrNone :
//module not found
case KErrNotFound :
if (mRequester)
mRequester->updateDeviceStatus();
else
mRequesterSatellite->updateDeviceStatus();
break;
//request has been successfully cancelled
case KErrCancel :
break;
//unrecoverabe errors
default :
break;
}
}
//
void CQMLBackendAO::handlePosUpdateNotification(int aError)
{
HPositionGenericInfo *positionInfo = NULL;
TPositionSatelliteInfo satInfo;
switch (aError) {
//NotifyPositionUpdate successfully completed
case KErrNone :
//Posiiton Module is unable to return any position information
case KPositionQualityLoss :
//requested information could not be retrieved within the maximum peroid
case KErrTimedOut:
if (mRequester) {
positionInfo = HPositionGenericInfo::New();
if (positionInfo == NULL)
return;
//copy the buffer contents into a new HPositionGenericInfo buffer,to be used
//for creating QGeoPositionInfo object later
memcpy(positionInfo , mPosInfo , mPosInfo->BufferSize());
} else {
satInfo = mPosSatInfo;
}
//if regUpdateAO, request for the next update
if (mRequestType == RegularUpdate) {
if (mRequester) {
initializePosInfo();
mPositioner.NotifyPositionUpdate(*mPosInfo, iStatus);
} else
mPositioner.NotifyPositionUpdate(mPosSatInfo, iStatus);
SetActive();
}
if (mRequester) {
mRequester->updatePosition(positionInfo, aError);
delete positionInfo;
} else {
if ((aError != KErrTimedOut) || (mRequestType != RegularUpdate)) {
mRequesterSatellite->updatePosition(satInfo, aError, (mRequestType == RegularUpdate));
}
}
break;
//request was successfully cancelled
case KErrCancel :
break;
default :
break;
}
}
//////////////////////////////////////////////////////////////
// Sets the interval for getting the regular notification //
// the time interval set is in milli seconds //
//////////////////////////////////////////////////////////////
int CQMLBackendAO::setUpdateInterval(int aMilliSec)
{
int minimumUpdateInterval = 0;
TInt64 mUpdateInterval = 0 ;
if (mRequester)
minimumUpdateInterval = mRequester->minimumUpdateInterval();
else
minimumUpdateInterval = mRequesterSatellite->minimumUpdateInterval();
if (minimumUpdateInterval < 0)
minimumUpdateInterval = 100;
// if the current requesttype is regular updates
// then set the updateinterval otherwise ignore
//if(mRequestType != REQ_REG_UPDATE)
// return;
TPositionUpdateOptions aPosOption;
TInt error = mPositioner.GetUpdateOptions(aPosOption);
// TTimeIntervalMicroSeconds is converted seconds
TInt currentUpdateInterval = aPosOption.UpdateInterval().Int64() / 1000;
// If msec is not 0 and is less than the value returned by minimumUpdateInterval(),
// the interval will be set to the minimum interval.
if (aMilliSec != 0 && aMilliSec <= minimumUpdateInterval) {
mUpdateInterval = minimumUpdateInterval;
} else {
mUpdateInterval = aMilliSec;
}
// if the same value is being set then just ignore it.
if (currentUpdateInterval == mUpdateInterval) {
return mUpdateInterval;
}
// will set Either zero, minimum or +ve value
// seconds converted to TTimeIntervalMicroSeconds
aPosOption.SetUpdateInterval(TTimeIntervalMicroSeconds(mUpdateInterval * 1000));
// set the timeout to the smaller of 150% of interval or update interval + 10 seconds
TInt64 mUpdateTimeout = (mUpdateInterval * 3) / 2;
if (mUpdateTimeout > mUpdateInterval + 10000)
mUpdateTimeout = mUpdateInterval + 10000;
if (aMilliSec > 0)
aPosOption.SetUpdateTimeOut(TTimeIntervalMicroSeconds(mUpdateTimeout * 1000));
error = mPositioner.SetUpdateOptions(aPosOption);
return mUpdateInterval;
}
void CQMLBackendAO::startUpdates()
{
if (!IsActive()) {
if (mRequester) {
initializePosInfo();
mPositioner.NotifyPositionUpdate(*mPosInfo , iStatus);
} else
mPositioner.NotifyPositionUpdate(mPosSatInfo , iStatus);
SetActive();
}
}
QTM_END_NAMESPACE