locationmanager/locationtrail/src/cgpxconverterao.cpp
changeset 0 c53acadfccc6
child 1 acef663c1218
equal deleted inserted replaced
-1:000000000000 0:c53acadfccc6
       
     1 /*
       
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Active object for converting internal fileformat to GPX
       
    15 *
       
    16 */
       
    17 
       
    18 #include <f32file.h>
       
    19 #include <s32file.h>
       
    20 #include <PathInfo.h>
       
    21 #include "cgpxconverterao.h"
       
    22 #include "locationmanagerdebug.h"
       
    23 
       
    24 // ---------------------------------------------------------------------------
       
    25 // Default constructor.
       
    26 // ---------------------------------------------------------------------------
       
    27 //
       
    28 CGpxConverterAO::CGpxConverterAO() : CActive( CActive::EPriorityStandard )
       
    29     {
       
    30     }
       
    31 
       
    32 // ---------------------------------------------------------------------------
       
    33 // Standard NewL for first phase construction.
       
    34 // ---------------------------------------------------------------------------
       
    35 //
       
    36 CGpxConverterAO* CGpxConverterAO::NewL()
       
    37     {
       
    38     LOG( "CGpxConverterAO::NewL" );
       
    39     CGpxConverterAO* self = new (ELeave) CGpxConverterAO();
       
    40     CleanupStack::PushL( self );
       
    41     self->ConstructL();
       
    42     CleanupStack::Pop( self );
       
    43     return self;
       
    44     }
       
    45 
       
    46 // ---------------------------------------------------------------------------
       
    47 // 2nd phase construction.
       
    48 // ---------------------------------------------------------------------------
       
    49 //
       
    50 void CGpxConverterAO::ConstructL()
       
    51     {
       
    52     LOG( "CGpxConverterAO::ConstructL" );
       
    53     CActiveScheduler::Add( this );
       
    54 	User::LeaveIfError( iFs.Connect() );
       
    55 	
       
    56 	iWriteBuf = HBufC8::NewL( KWriteBufSize );
       
    57 	iFormatBuf = HBufC::NewL( KWriteBufSize );
       
    58 	
       
    59     }
       
    60 
       
    61 // ---------------------------------------------------------------------------
       
    62 // Destructor.
       
    63 // ---------------------------------------------------------------------------
       
    64 //
       
    65 CGpxConverterAO::~CGpxConverterAO()
       
    66     {
       
    67     LOG( "CGpxConverterAO::~CGpxConverterAO" ); // DEBUG INFO
       
    68     Cancel();
       
    69     iFs.Close();
       
    70     
       
    71     iObservers.Reset();
       
    72     
       
    73     delete iWriteBuf;
       
    74     delete iFormatBuf;
       
    75     }
       
    76 
       
    77 // ---------------------------------------------------------------------------
       
    78 // From CActive.
       
    79 // ---------------------------------------------------------------------------
       
    80 //
       
    81 #ifdef _DEBUG
       
    82 TInt CGpxConverterAO::RunError( TInt aError )
       
    83 #else
       
    84 TInt CGpxConverterAO::RunError( TInt )
       
    85 #endif
       
    86     {
       
    87     LOG1( "CGpxConverterAO::RunError with error code: %d", aError );
       
    88     return KErrNone;
       
    89     }
       
    90 
       
    91 // ---------------------------------------------------------------------------
       
    92 // From CActive. 
       
    93 // ---------------------------------------------------------------------------
       
    94 //
       
    95 void CGpxConverterAO::DoCancel()
       
    96     {
       
    97     LOG( "CGpxConverterAO::DoCancel" );
       
    98     }
       
    99 
       
   100 /**
       
   101  * Adds temp-file and possible pre-calculated boundaries
       
   102  * into processing queue
       
   103  */
       
   104 void CGpxConverterAO::AddToQueueL( const TDesC& aFileName, TBoundaries* aBoundaries )
       
   105 	{
       
   106 	LOG("CGpxConverterAO::AddToQueueL");
       
   107 	TFileName *filename = new (ELeave) TFileName(aFileName);
       
   108 	iFileQueue.Append(filename);
       
   109 	iBoundQueue.Append( aBoundaries );
       
   110 	
       
   111 	if ( iState == EIdle )
       
   112 		{
       
   113 		SetState( ENextFile );
       
   114 		}
       
   115 	}
       
   116 
       
   117 /**
       
   118  * Set next state for RunL
       
   119  */
       
   120 void CGpxConverterAO::SetState( TProcessingState aState )
       
   121 	{
       
   122     LOG1( "CGpxConverterAO::SetState: %d", aState );
       
   123 	iState = aState;
       
   124 	if ( !IsActive() )
       
   125 		{
       
   126 		iStatus = KRequestPending;
       
   127 		SetActive();
       
   128 		TRequestStatus* ptrStatus = &iStatus;
       
   129 		User::RequestComplete( ptrStatus, KErrNone );
       
   130 		}
       
   131 	}
       
   132 
       
   133 /**
       
   134  * RunL
       
   135  */
       
   136 void CGpxConverterAO::RunL()
       
   137 	{
       
   138 	switch( iState )
       
   139 		{
       
   140 		case( EIdle ):
       
   141 			{
       
   142 			LOG("CGpxConverterAO::RunL - EIdle");
       
   143 			// nothing to do here
       
   144 			break;
       
   145 			}
       
   146 		case( ENextFile ):
       
   147 			{
       
   148 			LOG("CGpxConverterAO::RunL - ENextFile");
       
   149 			if( iFileQueue.Count() > 0 )
       
   150 				{
       
   151 				TInt err;
       
   152 				iFixLost = ETrue;
       
   153 				// get next temp-file from queue
       
   154 				iTempFile = *iFileQueue[0];
       
   155 				iBoundaries = iBoundQueue[0];
       
   156 				err = iReader.Open( iFs, iTempFile, EFileRead );				
       
   157 				// remove from queue				
       
   158 				iFileQueue.Remove( 0 );
       
   159 				iBoundQueue.Remove( 0 );
       
   160 				if ( err != KErrNone )
       
   161 					{
       
   162 					SetState( ENextFile );
       
   163 					}
       
   164 				TRAP( err, ReadTagIdL() );
       
   165 				
       
   166 				if ( !iBoundaries )
       
   167 					{
       
   168 					SetState( ECrashRecovery );
       
   169 					}
       
   170 				else
       
   171 					{
       
   172 					SetState( EStartFile );
       
   173 					}
       
   174 				}
       
   175 			else
       
   176 				{
       
   177 				// everything done
       
   178 				SetState( EIdle );
       
   179 				}
       
   180 			
       
   181 			break;
       
   182 			}
       
   183 		case( ECrashRecovery ):
       
   184 			{
       
   185 			LOG("CGpxConverterAO::RunL - ECrashRecovery");
       
   186 			TRAPD( readErr, iReader >> iTempItem );
       
   187 			if ( readErr == KErrNone )
       
   188 				{
       
   189 				CalculateBoundaries();
       
   190 				SetState( ECrashRecovery );
       
   191 				}
       
   192 			else
       
   193 				{
       
   194 				TInt err;
       
   195 				iReader.Close();
       
   196 				err = iReader.Open( iFs, iTempFile, EFileRead );
       
   197 				if( err != KErrNone )
       
   198 					{
       
   199 					SetState( ENextFile );
       
   200 					}
       
   201 				TRAP( err, ReadTagIdL() );
       
   202 				SetState( EStartFile );
       
   203 				}
       
   204 			
       
   205 			break;
       
   206 			}
       
   207 		case( EStartFile ):
       
   208 			{
       
   209 			LOG("CGpxConverterAO::RunL - EStartFile");
       
   210 			_LIT( KExtGPX, ".gpx" );
       
   211 			TParsePtrC parse( iTempFile );
       
   212 			
       
   213 			TRAPD(err, GetTrackLogPathL( iGpxPath ));
       
   214 			
       
   215 			iGpxFileName.Copy( parse.Name() );
       
   216 			iGpxFileName.Append( KExtGPX );
       
   217 			iGpxPath.Append( iGpxFileName );
       
   218 			
       
   219 			err = iFs.MkDirAll( iGpxPath );
       
   220 			if ( err != KErrAlreadyExists && err != KErrNone )
       
   221 				{
       
   222 				User::Leave( err );
       
   223 				}
       
   224 			
       
   225 			err = iGpxFile.Create(iFs, iGpxPath, EFileWrite);
       
   226 			if ( err != KErrNone )
       
   227 				{
       
   228 				err = iGpxFile.Open(iFs, iGpxPath, EFileWrite);
       
   229 				if ( err != KErrNone )
       
   230 					{
       
   231 					User::Leave( err );
       
   232 					}
       
   233 				}
       
   234 
       
   235 			WriteStartingTags();
       
   236 			iStartTime = 0;
       
   237 			iEndTime = 0;
       
   238 			
       
   239 			SetState( EProcessing );
       
   240 			break;
       
   241 			}
       
   242 		
       
   243 		case( EProcessing ):
       
   244 			{
       
   245 			LOG("CGpxConverterAO::RunL - EProcessing");
       
   246 			
       
   247 			TRAPD( readError, iReader >> iTempItem );
       
   248 			if ( readError == KErrNone )
       
   249 				{
       
   250 				if ( iStartTime == 0 )
       
   251 					{
       
   252 					iStartTime = iTempItem.iTimeStamp;
       
   253 					}
       
   254 				iEndTime = iTempItem.iTimeStamp;
       
   255 				WriteItemToFile();				
       
   256 				SetState( EProcessing );
       
   257 				}
       
   258 			else
       
   259 				{
       
   260 				// no items left in file
       
   261 				iReader.Close();
       
   262 				SetState( ECloseFile );
       
   263 				}
       
   264 			break;
       
   265 			}
       
   266 		case( ECloseFile ):
       
   267 			{
       
   268 			LOG("CGpxConverterAO::RunL - ECloseFile");
       
   269 			WriteClosingTags();
       
   270 			iGpxFile.Close();
       
   271 
       
   272 			TReal distance( 0 );
       
   273 			if( iBoundaries )
       
   274 				{
       
   275 				distance = iBoundaries->distance;
       
   276 				}
       
   277 			
       
   278 			TInt count = iObservers.Count();
       
   279 			for( TInt i = 0; i < count; i++ )
       
   280 				{
       
   281 				iObservers[i]->GpxFileCreated( iGpxPath, iTagId, distance, iStartTime, iEndTime );
       
   282 				}
       
   283 			
       
   284 			delete iBoundaries;
       
   285 			iFs.Delete( iTempFile );
       
   286 			SetState( ENextFile );
       
   287 			break;
       
   288 			}
       
   289 		}
       
   290 	}
       
   291 
       
   292 /**
       
   293  * Read Tag Id from temp-file
       
   294  */
       
   295 void CGpxConverterAO::ReadTagIdL()
       
   296 	{
       
   297 	LOG("CGpxConverterAO::ReadTagIdL");
       
   298 	TUint32 low( 0 );
       
   299 	TUint32 high( 0 );	
       
   300 
       
   301 	low = iReader.ReadUint32L();
       
   302 	high = iReader.ReadUint32L();
       
   303 
       
   304 	iTagId = MAKE_TINT64( high, low );
       
   305 	}
       
   306 
       
   307 /**
       
   308  * Calculate min and max coordinates for tracklog
       
   309  */
       
   310 void CGpxConverterAO::CalculateBoundaries()
       
   311 	{
       
   312 	LOG("CGpxConverterAO::CalculateBoundaries start");
       
   313 	const TInt KMaxLat = 90;
       
   314 	const TInt KMinLat = -90;
       
   315 	const TInt KMaxLon = 180;
       
   316 	const TInt KMinLon = -180;
       
   317 	if ( !iBoundaries )
       
   318 		{
       
   319 		iBoundaries = new TBoundaries;	
       
   320 		iBoundaries->minLatitude = KMaxLat;
       
   321 		iBoundaries->maxLatitude = KMinLat;
       
   322 		iBoundaries->minLongitude = KMaxLon;
       
   323 		iBoundaries->maxLongitude = KMinLon;
       
   324 		iBoundaries->distance = 0;
       
   325 		}
       
   326 	
       
   327 	if( !Math::IsNaN( iTempItem.iLatitude ) && !Math::IsNaN( iTempItem.iLongitude ))
       
   328 		{
       
   329 		TReal32 distance;
       
   330 		if ( !iLastCoords ) 
       
   331 			{
       
   332 			iLastCoords = new TCoordinate( iTempItem.iLatitude, iTempItem.iLongitude );
       
   333 			}
       
   334 		else
       
   335 			{
       
   336 			TCoordinate tempCoord( iTempItem.iLatitude, iTempItem.iLongitude );
       
   337 			TLocality newCoords( tempCoord, iTempItem.iHdop );
       
   338 			TInt err = newCoords.Distance(*iLastCoords, distance);
       
   339 			if ( err == KErrNone )
       
   340 				{
       
   341 				delete iLastCoords;
       
   342 				iLastCoords = new TCoordinate( tempCoord );
       
   343 				iBoundaries->distance += distance;
       
   344 				}
       
   345 			}		
       
   346 		iBoundaries->maxLatitude = Max( iBoundaries->maxLatitude, iTempItem.iLatitude );
       
   347 		iBoundaries->minLatitude = Min( iBoundaries->minLatitude, iTempItem.iLatitude );
       
   348 		iBoundaries->maxLongitude = Max( iBoundaries->maxLongitude, iTempItem.iLongitude );
       
   349 		iBoundaries->minLongitude = Min( iBoundaries->minLongitude, iTempItem.iLongitude );
       
   350 		}
       
   351 	LOG("CGpxConverterAO::CalculateBoundaries end");
       
   352 	}
       
   353 
       
   354 /**
       
   355  * Writes header tags for GPX file
       
   356  */
       
   357 void CGpxConverterAO::WriteStartingTags()
       
   358 	{
       
   359 	TPtr8 writePtr = iWriteBuf->Des();
       
   360 	TPtr formatter = iFormatBuf->Des();
       
   361 	
       
   362 	// write starting tags
       
   363 	writePtr.Copy( KTagXml );
       
   364 	writePtr.Append( KTagGpxStart );
       
   365 	iGpxFile.Write( writePtr );
       
   366 	
       
   367 	writePtr.Copy( KTagMetaStart );
       
   368 	formatter.Format( KTagName, &iGpxFileName );
       
   369 	writePtr.Append( formatter );
       
   370 	iGpxFile.Write( writePtr );
       
   371 	
       
   372 	TTime timeStamp( 0 );
       
   373 	timeStamp.UniversalTime();
       
   374 	TDateTime datetime = timeStamp.DateTime();
       
   375 	
       
   376 	formatter.Format( KTagTimeStamp, datetime.Year(), datetime.Month() + 1, datetime.Day() + 1,
       
   377 			datetime.Hour(), datetime.Minute(), datetime.Second() );
       
   378 	writePtr.Copy( formatter );
       
   379 	iGpxFile.Write( writePtr );
       
   380 	
       
   381 	if ( iBoundaries )
       
   382 		{
       
   383 		formatter.Format( KTagBounds, iBoundaries->minLatitude, iBoundaries->minLongitude, 
       
   384 				iBoundaries->maxLatitude, iBoundaries->maxLongitude );
       
   385 		writePtr.Copy( formatter );
       
   386 		iGpxFile.Write( writePtr );
       
   387 		}
       
   388 	writePtr.Copy( KTagMetaEnd );
       
   389 	iGpxFile.Write( writePtr );
       
   390 	
       
   391 	writePtr.Copy( KTagTrackStart );
       
   392 	iGpxFile.Write( writePtr );
       
   393 	}
       
   394 
       
   395 /**
       
   396  * Writes single trackpoint to GPX file
       
   397  */
       
   398 void CGpxConverterAO::WriteItemToFile()
       
   399 	{
       
   400 	TTime timeStamp;
       
   401 	
       
   402 	TPtr8 writePtr = iWriteBuf->Des();
       
   403 	TPtr formatter = iFormatBuf->Des();
       
   404 	
       
   405 	if ( Math::IsNaN(iTempItem.iLatitude) || Math::IsNaN(iTempItem.iLongitude) )
       
   406 		{
       
   407 		if ( !iFixLost )
       
   408 			{
       
   409 			writePtr.Copy( KTagSegmentEnd );
       
   410 			iGpxFile.Write( writePtr );
       
   411 			iFixLost = ETrue;
       
   412 			}
       
   413 		}
       
   414 	else
       
   415 		{
       
   416 		if ( iFixLost )
       
   417 			{
       
   418 			writePtr.Copy( KTagSegmentStart );
       
   419 			iGpxFile.Write( writePtr );
       
   420 			iFixLost = EFalse;
       
   421 			}
       
   422 		
       
   423 		// write single track point
       
   424 		// coordinates
       
   425 		formatter.Format( KTagTrkPointStart, iTempItem.iLatitude, iTempItem.iLongitude );
       
   426 		writePtr.Copy( formatter );
       
   427 		iGpxFile.Write( writePtr );
       
   428 		// elevation
       
   429 		if ( !Math::IsNaN( iTempItem.iAltitude ))
       
   430 			{
       
   431 			formatter.Format( KTagElevation, iTempItem.iAltitude );
       
   432 			writePtr.Copy( formatter );
       
   433 			iGpxFile.Write( writePtr );
       
   434 			}
       
   435 		// course
       
   436 		if ( !Math::IsNaN( iTempItem.iCourse ))
       
   437 			{
       
   438 			formatter.Format( KTagCourse, iTempItem.iCourse );
       
   439 			writePtr.Copy( formatter );
       
   440 			iGpxFile.Write( writePtr );
       
   441 			}
       
   442 
       
   443 		timeStamp = iTempItem.iTimeStamp;
       
   444 		TDateTime datetime = timeStamp.DateTime();
       
   445 		
       
   446 		formatter.Format( KTagTimeStamp, datetime.Year(), datetime.Month() + 1, datetime.Day() + 1,
       
   447 				datetime.Hour(), datetime.Minute(), datetime.Second() );
       
   448 		writePtr.Copy( formatter );
       
   449 		iGpxFile.Write( writePtr );
       
   450 		
       
   451 		if ( !Math::IsNaN( iTempItem.iAltitude ))
       
   452 			{
       
   453 			writePtr.Copy( KTagFix3D );
       
   454 			iGpxFile.Write( writePtr );
       
   455 			}
       
   456 		else
       
   457 			{
       
   458 			writePtr.Copy( KTagFix2D );
       
   459 			iGpxFile.Write( writePtr );
       
   460 			}
       
   461 
       
   462 		// number of satellites
       
   463 		formatter.Format( KTagSatellites, iTempItem.iNumSatellites );
       
   464 		writePtr.Copy( formatter );
       
   465 		iGpxFile.Write( writePtr );
       
   466 
       
   467 		// accuracy (hdop, vdop)
       
   468 		if ( !Math::IsNaN( iTempItem.iHdop ))
       
   469 			{
       
   470 			formatter.Format( KTagHdop, iTempItem.iHdop );
       
   471 			writePtr.Copy( formatter );
       
   472 			iGpxFile.Write( writePtr );
       
   473 			}
       
   474 		if ( !Math::IsNaN( iTempItem.iVdop ))
       
   475 			{
       
   476 			formatter.Format( KTagVdop, iTempItem.iVdop );
       
   477 			writePtr.Copy( formatter );
       
   478 			iGpxFile.Write( writePtr );
       
   479 			}
       
   480 	
       
   481 		// end track point
       
   482 		writePtr.Copy( KTagTrkPointEnd );
       
   483 		iGpxFile.Write( writePtr );
       
   484 		}
       
   485 	
       
   486 	}
       
   487 
       
   488 /**
       
   489  * Close GPX file 
       
   490  */
       
   491 void CGpxConverterAO::WriteClosingTags()
       
   492 	{
       
   493 	TPtr8 writePtr = iWriteBuf->Des();
       
   494 	
       
   495 	// end segment
       
   496 	if ( !iFixLost )
       
   497 		{
       
   498 		writePtr.Copy( KTagSegmentEnd );	
       
   499 		iGpxFile.Write( writePtr );
       
   500 		}
       
   501 
       
   502 	// closing tags
       
   503 	writePtr.Copy( KTagTrackEnd );
       
   504 	writePtr.Append( KTagGpxEnd );
       
   505 
       
   506 	iGpxFile.Write( writePtr );
       
   507 	}
       
   508 
       
   509 /**
       
   510  * Resolve where to save tracklog file
       
   511  */
       
   512 void CGpxConverterAO::GetTrackLogPathL( TDes& aFileName )
       
   513 	{
       
   514 	LOG("CGpxConverterAO::GetTrackLogPathL start");
       
   515 	_LIT( KPathTrackLog, "TrackLog\\" );
       
   516 	
       
   517 	TFileName* path = new (ELeave) TFileName();
       
   518 	CleanupStack::PushL( path );
       
   519 	
       
   520 	// check for memory card
       
   521 	*path = PathInfo::MemoryCardRootPath();
       
   522 	TLex lex( *path );
       
   523 	TInt drive;
       
   524 	iFs.CharToDrive( lex.Get(), drive );
       
   525 	TVolumeInfo* volumeinfo = new (ELeave) TVolumeInfo;
       
   526 	
       
   527 	TInt err = iFs.Volume( *volumeinfo, drive );
       
   528 	if( err != KErrNone )
       
   529 		{
       
   530 		LOG("CGpxConverterAO::GetTrackLogPathL - MMC not available");
       
   531 		*path = PathInfo::PhoneMemoryRootPath();
       
   532 		}
       
   533 	delete volumeinfo;
       
   534 	
       
   535 	path->Append( KPathTrackLog );
       
   536 	
       
   537 	aFileName.Copy( *path );
       
   538 	CleanupStack::PopAndDestroy( path );
       
   539 	LOG("CGpxConverterAO::GetTrackLogPathL end");
       
   540 	}
       
   541 
       
   542 /**
       
   543  * Adds observer for GPX file creation notifications
       
   544  */
       
   545 void CGpxConverterAO::AddObserver( MGpxConversionObserver* aObserver )
       
   546 	{
       
   547 	iObservers.Append( aObserver );
       
   548 	}
       
   549