--- /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 <e32base.h>
+#include <e32debug.h>
+
+#include <mderelation.h>
+#include <mderelationquery.h>
+#include <mdelogiccondition.h>
+
+#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<TItemId>& 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<TItemId>( CImageComposerAO::CompareTItemIds ) );
+ if ( res != KErrNotFound && res >= 0 )
+ {
+ RArray<TItemId> 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<TItemId> 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<TItemId> 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<TItemId>( 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<CMdERelation&>( 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<TDesC&>(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<TItemId>( 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;
+ }
+
+