diff -r 000000000000 -r c53acadfccc6 harvester/composerplugins/imagecomposer/src/imagecomposerao.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/harvester/composerplugins/imagecomposer/src/imagecomposerao.cpp Mon Jan 18 20:34:07 2010 +0200 @@ -0,0 +1,903 @@ +/* +* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Composer image active object +* +*/ + + +#include +#include + +#include +#include +#include + +#include "mdeharvestersession.h" +#include "mdeproperty.h" +#include "mdenamespacedef.h" +#include "imagecomposerao.h" +#include "harvesterlog.h" +#include "mdeconstants.h" +#include "mdsutils.h" +#include "mderelationcondition.h" +#include "mdeobjectdef.h" +#include "harvestercommon.h" + +using namespace MdeConstants; + +_LIT( KJpegMimeType, "image/jpeg" ); + +// --------------------------------------------------------------------------- +// NewL +// --------------------------------------------------------------------------- +// +CImageComposerAO* CImageComposerAO::NewL() + { + WRITELOG( "CImageComposerAO::NewL()" ); + + CImageComposerAO* self = new (ELeave) CImageComposerAO(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// ~CImageComposerAO +// --------------------------------------------------------------------------- +// +CImageComposerAO::~CImageComposerAO() // destruct + { + WRITELOG( "CImageComposerAO::~CImageComposerAO()" ); + + Cancel(); + + iItemQueue.Close(); + + iForceObjectIds.Close(); + iNextItemsSkip.Close(); + + if ( iMdeObject ) + { + delete iMdeObject; + } + if ( iExifUtil ) + { + delete iExifUtil; + } + + delete iRelationQuery; + iFs.Close(); + + delete iMdEHarvesterSession; + } + +// --------------------------------------------------------------------------- +// CComposerImagePlugin +// --------------------------------------------------------------------------- +// +CImageComposerAO::CImageComposerAO() : // first-phase C++ constructor + CActive( KHarvesterPriorityComposerPlugin ) + { + WRITELOG( "CImageComposerAO::CImageComposerAO()" ); + } + +// --------------------------------------------------------------------------- +// ConstructL +// --------------------------------------------------------------------------- +// +void CImageComposerAO::ConstructL() // second-phase constructor + { + WRITELOG( "CImageComposerAO::ConstructL()" ); + iMdeObject = NULL; + iNextRequest = ERequestReady; + iDefaultNamespace = NULL; + iImageObjectDef = NULL; + iObjectDef = NULL; + iLocationObjectDef = NULL; + + CActiveScheduler::Add( this ); + + iExifUtil = CHarvesterExifUtil::NewL(); + User::LeaveIfError( iFs.Connect() ); + } + +// --------------------------------------------------------------------------- +// DoCancel +// --------------------------------------------------------------------------- +// +void CImageComposerAO::DoCancel() + { + WRITELOG( "CImageComposerAO::DoCancel()" ); + } + +// --------------------------------------------------------------------------- +// AddToQueue +// --------------------------------------------------------------------------- +// +void CImageComposerAO::AddToQueue( const RArray& aItems, TBool aForce ) + { + WRITELOG( "CImageComposerAO::AddToQueue()" ); + + // check if we should skip some items + const TInt itemsCount = aItems.Count(); + for ( TInt i = 0; i < itemsCount; ++i ) + { + TInt res = iNextItemsSkip.FindInOrder( aItems[i], + TLinearOrder( CImageComposerAO::CompareTItemIds ) ); + if ( res != KErrNotFound && res >= 0 ) + { + RArray objectId; + objectId.Append( aItems[i] ); + TRAP_IGNORE( iMdEHarvesterSession->ResetPendingL( objectId ) ); + iNextItemsSkip.Remove( res ); + + if( iNextItemsSkip.Count() == 0 ) + { + iNextItemsSkip.Compress(); + } + objectId.Close(); + } + else + { + iItemQueue.Append( aItems[i] ); + if ( aForce ) + { + iForceObjectIds.Append( aItems[i] ); + } + } + } + if ( iNextRequest == ERequestReady ) + { + SetNextRequest( ERequestGetObject ); + } + } + +// --------------------------------------------------------------------------- +// IsComposingComplete() +// --------------------------------------------------------------------------- +// +TBool CImageComposerAO::IsComposingComplete() + { + WRITELOG( "CImageComposerAO::IsComposingComplete()" ); + return iNextRequest == ERequestReady; + } + +// --------------------------------------------------------------------------- +// SetSession +// --------------------------------------------------------------------------- +// +void CImageComposerAO::SetSession( CMdESession* aSession ) + { + WRITELOG( "CImageComposerAO::SetSession()" ); + iSession = aSession; + iExifUtil->SetSession(iSession); + if( iSession ) + { + iDefaultNamespace = NULL; + TRAP_IGNORE( iDefaultNamespace = &iSession->GetDefaultNamespaceDefL() ); + + TRAP_IGNORE( iImageObjectDef = &iDefaultNamespace->GetObjectDefL( + Image::KImageObject ) ); + TRAP_IGNORE( iObjectDef = &iDefaultNamespace->GetObjectDefL( + Object::KBaseObject ) ); + TRAP_IGNORE( iLocationObjectDef = &iDefaultNamespace->GetObjectDefL( + Location::KLocationObject ) ); + + + iMdEHarvesterSession = NULL; + TRAP_IGNORE( iMdEHarvesterSession + = CMdEHarvesterSession::NewL ( *iSession )); + } + } + +// --------------------------------------------------------------------------- +// RemoveSession +// --------------------------------------------------------------------------- +// +void CImageComposerAO::RemoveSession() + { + iSession = NULL; + iExifUtil->SetSession( NULL ); + + delete iMdEHarvesterSession; + iMdEHarvesterSession = NULL; + + iDefaultNamespace = NULL; + iImageObjectDef = NULL; + iObjectDef = NULL; + iLocationObjectDef = NULL; + } + +// --------------------------------------------------------------------------- +// RunL +// --------------------------------------------------------------------------- +// +void CImageComposerAO::RunL() + { + WRITELOG( "CImageComposerAO::RunL()" ); + User::LeaveIfError( iStatus.Int() ); + + if ( !iDefaultNamespace && iSession ) + { + iDefaultNamespace = &iSession->GetDefaultNamespaceDefL(); + } + + switch ( iNextRequest ) + { + case ERequestGetObject: + { + if( iItemQueue.Count() <= 0 ) + { + SetNextRequest( ERequestReady ); + } + else + { + TItemId mdeObjectId = KNoId; + TRAPD( err, GetObjectFromMdeL( mdeObjectId ) ); + + if ( err == KErrNone ) + { + SetNextRequest( ERequestCompose ); + } + // if object does not exists, find next + else if ( err == KErrNotFound || err == KErrAbort ) + { + if ( err == KErrAbort && mdeObjectId != KNoId ) + { + RArray objectId; + objectId.Append( mdeObjectId ); + CleanupClosePushL( objectId ); + iMdEHarvesterSession->ResetPendingL( objectId ); + CleanupStack::PopAndDestroy( &objectId ); + } + SetNextRequest( ERequestGetObject ); + } + + // something goes really wrong + else + { + User::Leave( err ); + } + } + + } + break; + + case ERequestCompose: + { + ComposeL(); + + if ( iMdeObject ) + { + RArray objectId; + objectId.Append( iMdeObject->Id() ); + TRAP_IGNORE( iMdEHarvesterSession->ResetPendingL( objectId ) ); + objectId.Close(); + + delete iMdeObject; + iMdeObject = NULL; + } + } + break; + + case ERequestReady: + { + } + break; + + default: + { + User::Leave( KErrUnknown ); + } + break; + } + } + +// --------------------------------------------------------------------------- +// RunError +// --------------------------------------------------------------------------- +// +#ifdef _DEBUG +TInt CImageComposerAO::RunError( TInt aError ) +#else +TInt CImageComposerAO::RunError( TInt ) +#endif + { + WRITELOG1( "CImageComposerAO::RunError() - error code: %d", aError ); + if ( iMdeObject && iSession ) + { + TRAP_IGNORE( iSession->CancelObjectL( *iMdeObject ) ); + } + SetNextRequest( ERequestGetObject ); + + return KErrNone; + } + +// --------------------------------------------------------------------------- +// GetObjectFromMde +// --------------------------------------------------------------------------- +// +void CImageComposerAO::GetObjectFromMdeL(TItemId& aMdEObjectId) + { +#ifdef _DEBUG + _LIT( KPanicCategoryNsd, "NSD=NULL" ); + _LIT( KPanicCategoryOd, "OD=NULL" ); + _LIT( KPanicCategoryId, "ID=NULL" ); + _LIT( KPanicCategoryLd, "LD=NULL" ); + __ASSERT_DEBUG( iDefaultNamespace, User::Panic( KPanicCategoryNsd, KErrBadHandle ) ); + __ASSERT_DEBUG( iObjectDef, User::Panic( KPanicCategoryOd, KErrBadHandle ) ); + __ASSERT_DEBUG( iImageObjectDef, User::Panic( KPanicCategoryId, KErrBadHandle ) ); + __ASSERT_DEBUG( iLocationObjectDef, User::Panic( KPanicCategoryLd, KErrBadHandle ) ); +#endif + + WRITELOG( "CImageComposerAO::GetObjectFromMdeL() - start" ); + + if ( !iSession ) + { + WRITELOG( "CImageComposerAO::GetObjectFromMdeL() - iSession is NULL" ); + User::Leave( KErrSessionClosed ); + } + + TItemId objectId = KNoId; + + // get the object id from queue + if( iItemQueue.Count() > 0 ) + { + objectId = iItemQueue[0]; + aMdEObjectId = objectId; + iItemQueue.Remove( 0 ); + } + else + { + iItemQueue.Compress(); + } + + // get object from db (NULL if not found) + CMdEObject* mdeObject = iSession->GetObjectL( objectId, *iImageObjectDef ); + + CleanupStack::PushL( mdeObject ); + + if ( !mdeObject ) + { + WRITELOG1( "CImageComposerAO::GetObjectFromMdeL() - could not find object id %d", objectId ); + User::Leave( KErrNotFound ); + } + + TInt force; + force = iForceObjectIds.Find( objectId ); + if ( force != KErrNotFound ) + { + iForceObjectIds.Remove( force ); + + if( iForceObjectIds.Count() == 0 ) + { + iForceObjectIds.Compress(); + } + } + else + { + // check if file's and object's last modified dates are equal + CMdEPropertyDef& lastModifiedDatePropDef = mdeObject->Def().GetPropertyDefL( + Object::KLastModifiedDateProperty ); + CMdEProperty* lastModifiedDateProp = NULL; + mdeObject->Property( lastModifiedDatePropDef, lastModifiedDateProp ); + if( lastModifiedDateProp ) + { + TTime time = ((CMdETimeProperty*)lastModifiedDateProp)->Value(); + + TEntry entry; + TInt error = iFs.Entry( mdeObject->Uri(), entry ); + + if( error != KErrNone || entry.iModified == time ) + { + User::Leave( KErrAbort ); + } + } + else + { + User::Leave( KErrNotFound ); + } + } + + CleanupStack::Pop( mdeObject ); + iMdeObject = mdeObject; + + WRITELOG( "CImageComposerAO::GetObjectFromMdeL() - end" ); + } + +// --------------------------------------------------------------------------- +// ComposeL +// --------------------------------------------------------------------------- +// +void CImageComposerAO::ComposeL() + { +#ifdef _DEBUG + _LIT( KPanicCategoryNsd, "NSD=NULL" ); + _LIT( KPanicCategoryOd, "OD=NULL" ); + _LIT( KPanicCategoryId, "ID=NULL" ); + _LIT( KPanicCategoryLd, "LD=NULL" ); + __ASSERT_DEBUG( iDefaultNamespace, User::Panic( KPanicCategoryNsd, KErrBadHandle ) ); + __ASSERT_DEBUG( iObjectDef, User::Panic( KPanicCategoryOd, KErrBadHandle ) ); + __ASSERT_DEBUG( iImageObjectDef, User::Panic( KPanicCategoryId, KErrBadHandle ) ); + __ASSERT_DEBUG( iLocationObjectDef, User::Panic( KPanicCategoryLd, KErrBadHandle ) ); +#endif + +#ifdef _DEBUG + WRITELOG( "CImageComposerAO::ComposeL()" ); + WRITELOG1( "CImageComposerAO::ComposeL() - Compose Start Object ID: %d", iMdeObject->Id() ); +#endif + + if ( !iSession ) + { + WRITELOG( "CImageComposerAO::ComposeL() - iSession is NULL!" ); + User::Leave( KErrSessionClosed ); + } + + // 1. Read Exif image from the file to a buffer... + RFile64 file; + CleanupClosePushL( file ); + WRITELOG( "CImageComposerAO::ComposeL() - open file for reading" ); + User::LeaveIfError( file.Open( iFs, iMdeObject->Uri(), EFileRead ) ); + + TInt64 dataSize = 0; + file.Size( dataSize ); + HBufC8* exif = HBufC8::NewL( dataSize ); + CleanupStack::PushL( exif ); + TPtr8 exifPtr = exif->Des(); + User::LeaveIfError( file.Read( exifPtr ) ); + CleanupStack::Pop( exif ); // exif needs to be popped and pushed again + CleanupStack::PopAndDestroy( &file ); // to get file out of CleanupStack + CleanupStack::PushL( exif ); + + HBufC8* modifiedExif = NULL; + + iExifUtil->ComposeExifDataL(*iMdeObject, exifPtr, modifiedExif); + + // modifiedExif is NULL if no changes were made + if ( modifiedExif ) + { + CleanupStack::PushL( modifiedExif ); + + if ( !iMdeObject->OpenForModifications() ) + { + // we have get version + const TItemId objectId = iMdeObject->Id(); + delete iMdeObject; + iMdeObject = NULL; + iMdeObject = iSession->OpenObjectL( objectId, *iImageObjectDef ); + if ( !iMdeObject ) + { + User::Leave( KErrAccessDenied ); + } + } + + // set position to begin of file + WRITELOG( "CImageComposerAO::ComposeL() - open file for writing" ); + User::LeaveIfError( file.Open( iFs, iMdeObject->Uri(), EFileWrite ) ); + CleanupClosePushL( file ); + + TInt64 pos = 0; + WRITELOG( "CImageComposerAO::ComposeL() - seek to position 0" ); + User::LeaveIfError( file.Seek( ESeekStart, pos ) ); + + WRITELOG( "CImageComposerAO::ComposeL() - write buffer (exif) to file" ); + User::LeaveIfError( file.Write( modifiedExif->Des(), modifiedExif->Des().Length() ) ); + + CleanupStack::PopAndDestroy( 2, modifiedExif ); // file, modifiedExif + TEntry fileEntry; + iFs.Entry( iMdeObject->Uri(), fileEntry ); + + WRITELOG( "CImageComposerAO::ComposeL() - store Size and LastModifiedDate properties to MDE" ); + CMdEPropertyDef& sizePropDef = iImageObjectDef->GetPropertyDefL( Object::KSizeProperty ); + { + CMdEProperty* sizeProp = NULL; + iMdeObject->Property( sizePropDef, sizeProp, 0 ); + + if ( sizeProp ) + { + sizeProp->SetUint32ValueL( fileEntry.iSize ); + } + else + { + iMdeObject->AddUint32PropertyL( sizePropDef, fileEntry.iSize ); + } + } + + CMdEPropertyDef& lastModDatePropDef = iImageObjectDef->GetPropertyDefL( + Object::KLastModifiedDateProperty ); + { + CMdEProperty* lastModDateProp = NULL; + iMdeObject->Property( lastModDatePropDef, lastModDateProp, 0 ); + + if ( lastModDateProp ) + { + lastModDateProp->SetTimeValueL( fileEntry.iModified ); + } + else + { + iMdeObject->AddTimePropertyL( lastModDatePropDef, fileEntry.iModified ); + } + } + iSession->CommitObjectL( *iMdeObject ); + iNextItemsSkip.InsertInOrder( iMdeObject->Id(), + TLinearOrder( CImageComposerAO::CompareTItemIds ) ); + } + + CleanupStack::PopAndDestroy( exif ); + + WRITELOG( "CImageComposerAO::ComposeL() - Start writing GPS tags" ); + + WriteGPSTagsL( iMdeObject->Id() ); + +#ifdef _DEBUG + WRITELOG1( "CImageComposerAO::ComposeL() - Compose End Object ID: %d", iMdeObject->Id() ); +#endif + } + +// --------------------------------------------------------------------------- +// WriteGPSTagsL +// --------------------------------------------------------------------------- +// +void CImageComposerAO::WriteGPSTagsL( TItemId aObjectId ) + { +#ifdef _DEBUG + _LIT( KPanicCategoryNsd, "NSD=NULL" ); + _LIT( KPanicCategoryOd, "OD=NULL" ); + _LIT( KPanicCategoryId, "ID=NULL" ); + _LIT( KPanicCategoryLd, "LD=NULL" ); + __ASSERT_DEBUG( iDefaultNamespace, User::Panic( KPanicCategoryNsd, KErrBadHandle ) ); + __ASSERT_DEBUG( iObjectDef, User::Panic( KPanicCategoryOd, KErrBadHandle ) ); + __ASSERT_DEBUG( iImageObjectDef, User::Panic( KPanicCategoryId, KErrBadHandle ) ); + __ASSERT_DEBUG( iLocationObjectDef, User::Panic( KPanicCategoryLd, KErrBadHandle ) ); +#endif + + delete iRelationQuery; + iRelationQuery = NULL; + + if ( !iSession ) + { + User::Leave( KErrSessionClosed ); + } + + iRelationQuery = iSession->NewRelationQueryL( *iDefaultNamespace, this ); + + iRelationQuery->SetResultMode( EQueryResultModeItem ); + iRelationQuery->Conditions().SetOperator( ELogicConditionOperatorAnd ); + + CMdERelationCondition& filterCond = iRelationQuery->Conditions(). + AddRelationConditionL( ERelationConditionSideRight ); + + // Left object in relation must have this ID. + filterCond.LeftL().AddObjectConditionL( aObjectId ); + + // Right object in relation must be a location object. + filterCond.RightL().AddObjectConditionL( *iLocationObjectDef ); + + iRelationQuery->FindL( 1, 1 ); // results to a call to HandleQueryCompleted() + } + +// --------------------------------------------------------------------------- +// SetNextRequest +// --------------------------------------------------------------------------- +// +void CImageComposerAO::SetNextRequest( TRequestType aNextRequest ) + { + iNextRequest = aNextRequest; + + if ( !IsActive() ) + { + iStatus = KRequestPending; + SetActive(); + TRequestStatus* ptrStatus = &iStatus; + User::RequestComplete( ptrStatus, KErrNone ); + } + } + +// --------------------------------------------------------------------------- +// HandleQueryNewResults +// --------------------------------------------------------------------------- +// +void CImageComposerAO::HandleQueryNewResults( CMdEQuery& /*aQuery*/, + TInt /*aFirstNewItemIndex*/, TInt /*aNewItemCount*/ ) + { + } + +// --------------------------------------------------------------------------- +// HandleQueryNewResults +// --------------------------------------------------------------------------- +// +void CImageComposerAO::HandleQueryNewResults( CMdEQuery& /*aQuery*/, + TInt /*aNewObjectItemCount*/, TInt /*aNewRelationItemCount*/, + TInt /*aNewEventItemCount*/ ) + { + } + +// --------------------------------------------------------------------------- +// HandleQueryCompleted +// --------------------------------------------------------------------------- +// +void CImageComposerAO::HandleQueryCompleted( CMdEQuery& aQuery, TInt aError ) + { + if ( aError != KErrNone ) + { + WRITELOG1( "CImageComposerAO::HandleQueryCompleted() - query error: %d", aError ); + SetNextRequest( ERequestGetObject ); + return; + } + if ( aQuery.Count() == 0 ) + { + WRITELOG( "CImageComposerAO::HandleQueryCompleted() - no gps items found" ); + SetNextRequest( ERequestGetObject ); + return; + } + +#ifdef _DEBUG + TRAPD( error, StartWritingGPSTagsL( aQuery ) ); + WRITELOG1( "CImageComposerAO::HandleQueryCompleted() - error code from StartWritingGPSTagsL: %d", error ); +#else + TRAP_IGNORE( StartWritingGPSTagsL( aQuery ) ); +#endif + + SetNextRequest( ERequestGetObject ); + } + +// --------------------------------------------------------------------------- +// StartWritingGPSTagsL +// --------------------------------------------------------------------------- +// +void CImageComposerAO::StartWritingGPSTagsL( CMdEQuery& aQuery ) + { +#ifdef _DEBUG + _LIT( KPanicCategoryNsd, "NSD=NULL" ); + _LIT( KPanicCategoryOd, "OD=NULL" ); + _LIT( KPanicCategoryId, "ID=NULL" ); + _LIT( KPanicCategoryLd, "LD=NULL" ); + __ASSERT_DEBUG( iDefaultNamespace, User::Panic( KPanicCategoryNsd, KErrBadHandle ) ); + __ASSERT_DEBUG( iObjectDef, User::Panic( KPanicCategoryOd, KErrBadHandle ) ); + __ASSERT_DEBUG( iImageObjectDef, User::Panic( KPanicCategoryId, KErrBadHandle ) ); + __ASSERT_DEBUG( iLocationObjectDef, User::Panic( KPanicCategoryLd, KErrBadHandle ) ); +#endif + + if ( !iSession ) + { + WRITELOG( "CImageComposerAO::StartWritingGPSTagsL - iSession is NULL!" ); + User::Leave( KErrSessionClosed ); + } + + CMdERelation& result = static_cast( aQuery.ResultItem( 0 ) ); + TItemId rightId = result.RightObjectId(); + CMdEObject* location = iSession->GetObjectL( rightId, *iLocationObjectDef ); + CleanupStack::PushL( location ); + + TItemId leftId = result.LeftObjectId(); + CMdEObject* mdeObject = iSession->GetObjectL( leftId, *iObjectDef ); + CleanupStack::PushL( mdeObject ); + + DoWriteExifL( mdeObject, location ); + + CleanupStack::PopAndDestroy( mdeObject ); + CleanupStack::PopAndDestroy( location ); + } + + +// --------------------------------------------------------------------------- +// DoWriteExifL +// --------------------------------------------------------------------------- +// +void CImageComposerAO::DoWriteExifL( CMdEObject* aMdEObject, CMdEObject* aLocationObject ) + { +#ifdef _DEBUG + _LIT( KPanicCategoryNsd, "NSD=NULL" ); + _LIT( KPanicCategoryOd, "OD=NULL" ); + _LIT( KPanicCategoryId, "ID=NULL" ); + _LIT( KPanicCategoryLd, "LD=NULL" ); + __ASSERT_DEBUG( iDefaultNamespace, User::Panic( KPanicCategoryNsd, KErrBadHandle ) ); + __ASSERT_DEBUG( iObjectDef, User::Panic( KPanicCategoryOd, KErrBadHandle ) ); + __ASSERT_DEBUG( iImageObjectDef, User::Panic( KPanicCategoryId, KErrBadHandle ) ); + __ASSERT_DEBUG( iLocationObjectDef, User::Panic( KPanicCategoryLd, KErrBadHandle ) ); +#endif + + WRITELOG( "CImageComposerAO::DoWriteExifL()" ); + if ( !aMdEObject || !aLocationObject ) + { + WRITELOG( "CImageComposerAO::DoWriteExifL() - null parameter(s)!" ); + User::Leave( KErrArgument ); + } + + CMdEProperty* itemTypeProperty = NULL; + CMdEProperty* latitudeProperty = NULL; + CMdEProperty* longitudeProperty = NULL; + CMdEProperty* altitudeProperty = NULL; + CMdEProperty* qualityProperty = NULL; + + aMdEObject->Property( iObjectDef->GetPropertyDefL( + Object::KItemTypeProperty ), itemTypeProperty, 0 ); + aLocationObject->Property( iLocationObjectDef->GetPropertyDefL( + Location::KLatitudeProperty ), latitudeProperty, 0 ); + aLocationObject->Property( iLocationObjectDef->GetPropertyDefL( + Location::KLongitudeProperty ), longitudeProperty, 0 ); + aLocationObject->Property( iLocationObjectDef->GetPropertyDefL( + Location::KAltitudeProperty ), altitudeProperty, 0 ); + aLocationObject->Property( iLocationObjectDef->GetPropertyDefL( + Location::KQualityProperty ), qualityProperty, 0 ); + + if ( !itemTypeProperty ) + { + WRITELOG( "CImageComposerAO::DoWriteExifL() - NULL item type property!" ); + User::Leave( KErrBadHandle ); + } + const TDesC& uri = aMdEObject->Uri(); + + const TDesC& mimeType = itemTypeProperty->TextValueL(); + + if ( !IsJpeg( const_cast(mimeType) ) ) + { + WRITELOG( "CImageComposerAO::DoWriteExifL() - object mimetype is not image/jpeg!" ); + User::Leave( KErrNotSupported ); + } + + // Check whether the file is open + TBool isOpen( EFalse ); + iFs.IsFileOpen( uri, isOpen ); + if ( isOpen ) + { + WRITELOG( "CImageComposerAO::DoWriteExifL() - file handle is open!" ); + User::Leave( KErrInUse ); + } + + TInt64 imageFileSize = 0; + RFile64 file; + User::LeaveIfError( file.Open( iFs, uri, EFileRead ) ); + CleanupClosePushL( file ); + + User::LeaveIfError( file.Size( imageFileSize ) ); + HBufC8* imageData = HBufC8::NewL( imageFileSize ); + CleanupStack::PushL( imageData ); + TPtr8 myImagePtr = imageData->Des(); + + WRITELOG( "CImageComposerAO::DoWriteExifL() - reading IMAGE file" ); + const TInt readError = file.Read( myImagePtr ) ; + if ( readError != KErrNone ) + { + WRITELOG( "CImageComposerAO::DoWriteExifL() - error while reading image file!" ); + User::Leave( KErrGeneral ); + } + + WRITELOG( "CImageComposerAO::DoWriteExifL() - reading IMAGE file - DONE! - closing file" ); + CleanupStack::Pop( imageData ); + CleanupStack::PopAndDestroy( &file ); + CleanupStack::PushL( imageData ); + + HBufC8* modifiedExif = NULL; + iExifUtil->ComposeLocationL( aLocationObject, myImagePtr, modifiedExif ); + + // write the EXIF data to the image + + if ( modifiedExif ) + { + CleanupStack::PushL( modifiedExif ); + + CMdEObject* mdeObject = iSession->OpenObjectL( aMdEObject->Id(), + *iImageObjectDef ); + if ( !mdeObject ) + { + User::Leave( KErrAccessDenied ); + } + CleanupStack::PushL( mdeObject ); + + User::LeaveIfError( file.Open( iFs, mdeObject->Uri(), EFileWrite ) ); + CleanupClosePushL( file ); + + // set position to begin of file + TInt64 pos = 0; + User::LeaveIfError( file.Seek( ESeekStart, pos ) ); + + User::LeaveIfError( file.Write( modifiedExif->Des(), modifiedExif->Des().Length() ) ); + + CleanupStack::PopAndDestroy( &file ); + TEntry fileEntry; + iFs.Entry( mdeObject->Uri(), fileEntry ); + + CMdEPropertyDef& sizePropDef = iImageObjectDef->GetPropertyDefL( Object::KSizeProperty ); + CMdEProperty* sizeProp = NULL; + mdeObject->Property( sizePropDef, sizeProp, 0 ); + + if ( sizeProp ) + { + sizeProp->SetUint32ValueL( fileEntry.iSize ); + } + else + { + mdeObject->AddUint32PropertyL( sizePropDef, fileEntry.iSize ); + } + + CMdEPropertyDef& lastModDatePropDef = iImageObjectDef->GetPropertyDefL( + Object::KLastModifiedDateProperty ); + CMdEProperty* lastModDateProp = NULL; + mdeObject->Property( lastModDatePropDef, lastModDateProp, 0 ); + + if ( lastModDateProp ) + { + lastModDateProp->SetTimeValueL( fileEntry.iModified ); + } + else + { + mdeObject->AddTimePropertyL( lastModDatePropDef, fileEntry.iModified ); + } + + iSession->CommitObjectL( *mdeObject ); + iNextItemsSkip.InsertInOrder( mdeObject->Id(), + TLinearOrder( CImageComposerAO::CompareTItemIds ) ); + CleanupStack::PopAndDestroy( mdeObject ); + CleanupStack::PopAndDestroy( modifiedExif ); + } + + // remove empty (=unneeded) location objects + if ( !latitudeProperty && !longitudeProperty && !altitudeProperty ) // && !satellitesProperty ) // check these first... + { + // get the rest of the properties + CMdEProperty* cellIdProperty = NULL; + CMdEProperty* countryCodeProperty = NULL; + CMdEProperty* networkCodeProperty = NULL; + CMdEProperty* locationAreaCodeProperty = NULL; + CMdEProperty* speedProperty = NULL; + CMdEProperty* directionProperty = NULL; + CMdEProperty* qualityProperty = NULL; + + aLocationObject->Property( iLocationObjectDef->GetPropertyDefL( + Location::KCellIdProperty ), cellIdProperty, 0 ); + aLocationObject->Property( iLocationObjectDef->GetPropertyDefL( + Location::KCountryCodeProperty ), countryCodeProperty, 0 ); + aLocationObject->Property( iLocationObjectDef->GetPropertyDefL( + Location::KNetworkCodeProperty ), networkCodeProperty, 0 ); + aLocationObject->Property( iLocationObjectDef->GetPropertyDefL( + Location::KLocationAreaCodeProperty ), locationAreaCodeProperty, 0 ); + aLocationObject->Property( iLocationObjectDef->GetPropertyDefL( + Location::KSpeedProperty ), speedProperty, 0 ); + aLocationObject->Property( iLocationObjectDef->GetPropertyDefL( + Location::KDirectionProperty ), directionProperty, 0 ); + aLocationObject->Property( iLocationObjectDef->GetPropertyDefL( + Location::KQualityProperty ), qualityProperty, 0 ); + + // if object doesn't contain any properties, remove it + if ( !cellIdProperty && !countryCodeProperty && !networkCodeProperty + && !locationAreaCodeProperty && !speedProperty && !directionProperty && !qualityProperty ) + { + iSession->RemoveObjectL( aLocationObject->Id(), iDefaultNamespace ); + } + } + + CleanupStack::PopAndDestroy( imageData ); + + } + +// --------------------------------------------------------------------------- +// IsJpeg +// --------------------------------------------------------------------------- +// +TBool CImageComposerAO::IsJpeg( const TDesC& aMimeType ) + { + WRITELOG( "CImageComposerAO::IsJpeg()" ); + + if ( MdsUtils::Compare( KJpegMimeType, aMimeType ) == 0 ) + { + WRITELOG( "CImageComposerAO::IsJpeg() - image is Jpeg" ); + return ETrue; + } + + return EFalse; + } + +