--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imagehandlingutilities/thumbnailmanager/thumbnailserver/src/thumbnailgeneratetask.cpp Tue Jan 26 15:18:05 2010 +0200
@@ -0,0 +1,497 @@
+/*
+* Copyright (c) 2006-2007 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: Task for generating new thumbnails
+ *
+*/
+
+
+#include <e32base.h>
+#include <fbs.h>
+
+#include <thumbnailmanager.h>
+
+#include "thumbnailgeneratetask.h"
+#include "thumbnailscaletask.h"
+#include "thumbnailprovider.h"
+#include "thumbnailserver.h"
+#include "thumbnailtaskprocessor.h"
+#include "thumbnailmanagerconstants.h"
+#include "thumbnaillog.h"
+#include "thumbnailpanic.h"
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CThumbnailGenerateTask::CThumbnailGenerateTask()
+// C++ default constructor can NOT contain any code, that might leave.
+// ---------------------------------------------------------------------------
+//
+CThumbnailGenerateTask::CThumbnailGenerateTask( CThumbnailTaskProcessor&
+ aProcessor, CThumbnailServer& aServer, RFile64* aFile, TDesC8* aBuffer,
+ const TDataType* aMimeType, CThumbnailManager::TThumbnailFlags aFlags,
+ const TSize& aSize, TDisplayMode aDisplayMode, TInt aPriority,
+ RArray < TThumbnailPersistentSize >* aMissingSizes, const TDesC& aTargetUri,
+ TThumbnailSize aThumbnailSize, const TThumbnailId aThumbnailId,
+ const CThumbnailManager::TThumbnailQualityPreference aQualityPreference ):
+ CThumbnailTask( aProcessor, aPriority ), iServer( aServer ),
+ iFlags( aFlags ), iSize( aSize ), iDisplayMode( aDisplayMode ),
+ iMissingSizes( aMissingSizes ), iTargetUri( aTargetUri ),
+ iThumbnailSize( aThumbnailSize ), iThumbnailId(aThumbnailId),
+ iQualityPreference( aQualityPreference )
+ {
+ TN_DEBUG2( "CThumbnailGenerateTask(0x%08x)::CThumbnailGenerateTask()", this);
+
+ if ( !aBuffer && aFile)
+ {
+ iFile = *aFile;
+ iFile.FullName( iFilename );
+ }
+ else if( aBuffer )
+ {
+ iBuffer = aBuffer;
+ }
+ if ( aMimeType )
+ {
+ iMimeType = *aMimeType;
+ }
+ else
+ {
+ iMimeType = TDataType(KNullDesC8);
+ }
+
+ // scaled bitmaps to pool by default
+ iScaledBitmapToPool = ETrue;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CThumbnailGenerateTask::~CThumbnailGenerateTask()
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CThumbnailGenerateTask::~CThumbnailGenerateTask()
+ {
+ TN_DEBUG2("CThumbnailGenerateTask(0x%08x)::~CThumbnailGenerateTask()", this);
+
+ if ( iProvider )
+ {
+ iProvider->CancelGetThumbnail();
+ }
+
+ if ( iMissingSizes )
+ {
+ iMissingSizes->Reset();
+ delete iMissingSizes;
+ }
+
+ if ( iBitmap )
+ {
+ iServer.DeleteBitmapFromPool( iBitmap->Handle());
+ iBitmap = NULL;
+ }
+
+ iProvider = NULL;
+ delete iBuffer;
+ iBuffer = NULL;
+
+ iFile.Close();
+ TN_DEBUG1("CThumbnailGenerateTask::~CThumbnailGenerateTask() - file handle closed");
+ }
+
+
+// ---------------------------------------------------------------------------
+// CThumbnailGenerateTask::StartL()
+// ---------------------------------------------------------------------------
+//
+void CThumbnailGenerateTask::StartL()
+ {
+ TN_DEBUG2( "CThumbnailGenerateTask(0x%08x)::StartL()", this );
+
+ CThumbnailTask::StartL();
+
+#ifdef _DEBUG
+ aStart.UniversalTime();
+#endif
+
+
+ TParsePtrC parse(iFilename);
+ TPtrC ext(parse.Ext());
+ TBuf8< KMaxDataTypeLength > mimeType;
+ if (ext.CompareF(KNonEmbeddedArtExt)== 0)
+ {
+ mimeType.Copy( KImageMime );
+ }
+ else
+ {
+ mimeType = iMimeType.Des8();
+ }
+ iProvider = iServer.ResolveProviderL(mimeType);
+
+ TN_DEBUG3( "CThumbnailGenerateTask(0x%08x) -- provider UID 0x%08x", this,
+ iProvider->Uid());
+
+ __ASSERT_DEBUG(( iProvider ), ThumbnailPanic( EThumbnailNullPointer ));
+
+ iProvider->CancelGetThumbnail();
+ iProvider->Reset();
+ iProvider->SetObserver( *this );
+
+ TSize effectiveTargetSize;
+ TSize croppedTargetSize;
+
+ CalculateTargetSizesL( effectiveTargetSize, croppedTargetSize );
+
+ iProvider->SetTargetSize( effectiveTargetSize );
+
+ if(effectiveTargetSize == TSize())
+ {
+ iProvider->SetTargetSize( croppedTargetSize );
+ }
+
+ if ( !iBuffer )
+ {
+ iProvider->GetThumbnailL( iServer.Fs(), iFile, iMimeType, iFlags,
+ iDisplayMode, iQualityPreference );
+ }
+ else
+ {
+ iProvider->GetThumbnailL( iServer.Fs(), iBuffer, iMimeType, iFlags,
+ iDisplayMode, iQualityPreference );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CThumbnailGenerateTask::RunL()
+// ---------------------------------------------------------------------------
+//
+void CThumbnailGenerateTask::RunL()
+ {
+ // No implementation required
+ }
+
+
+// ---------------------------------------------------------------------------
+// CThumbnailGenerateTask::DoCancel()
+// ---------------------------------------------------------------------------
+//
+void CThumbnailGenerateTask::DoCancel()
+ {
+ TN_DEBUG2( "CThumbnailGenerateTask(0x%08x)::DoCancel()", this );
+ if ( iProvider )
+ {
+ iProvider->CancelGetThumbnail();
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// Calculate the largest non-cropped size and largest cropped size and
+// let the provider plug-in know the values
+// ---------------------------------------------------------------------------
+//
+void CThumbnailGenerateTask::CalculateTargetSizesL( TSize& aEffectiveTargetSize,
+ TSize& aCroppedTargetSize )
+ {
+ if ( iThumbnailSize == ECustomThumbnailSize )
+ {
+ if ( iFlags& CThumbnailManager::ECropToAspectRatio )
+ {
+ aCroppedTargetSize = iSize;
+ }
+ else
+ {
+ aEffectiveTargetSize = iSize;
+ }
+ }
+
+ if ( iThumbnailSize != ECustomThumbnailSize )
+ {
+ RArray < TThumbnailPersistentSize > sizes = iServer.PersistentSizesL();
+ const TInt count = sizes.Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ TThumbnailPersistentSize size( sizes[i] );
+
+ iSize = size.iSize;
+ if ( size.iCrop )
+ {
+ aCroppedTargetSize.iWidth = Max( aCroppedTargetSize.iWidth,
+ size.iSize.iWidth );
+ aCroppedTargetSize.iHeight = Max( aCroppedTargetSize.iHeight,
+ size.iSize.iHeight );
+ if(iBuffer)
+ {
+ iFlags = ( CThumbnailManager::TThumbnailFlags ) (iFlags | CThumbnailManager::ECropToAspectRatio);
+ aEffectiveTargetSize = aCroppedTargetSize;
+ }
+ }
+ else
+ {
+ aEffectiveTargetSize.iWidth = Max( aEffectiveTargetSize.iWidth,
+ size.iSize.iWidth );
+ aEffectiveTargetSize.iHeight = Max( aEffectiveTargetSize.iHeight,
+ size.iSize.iHeight );
+ }
+
+ if(size.iType == iThumbnailSize)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Thumbnail provider observer callback to notify the server when
+// thumbnail has been generated.
+// ---------------------------------------------------------------------------
+//
+void CThumbnailGenerateTask::ThumbnailProviderReady( const TInt aError,
+ CFbsBitmap* aBitmap, const TSize& aOriginalSize, const TBool aEXIF, const TBool aPortrait )
+ {
+ TN_DEBUG4(
+ "CThumbnailGenerateTask(0x%08x)::ThumbnailProviderReady(aError=%d, aBitmap=0x%08x)", this, aError, aBitmap );
+
+ #ifdef _DEBUG
+ aStop.UniversalTime();
+ TN_DEBUG2( "CThumbnailGenerateTask::ThumbnailProviderReady() generate took %d ms", (TInt)aStop.MicroSecondsFrom(aStart).Int64()/1000);
+ #endif
+
+ iPortrait = aPortrait;
+ iEXIF = aEXIF;
+ iOriginalSize = aOriginalSize;
+
+ if ( aError )
+ {
+ delete aBitmap;
+ aBitmap = NULL;
+ // Create a temporary bitmap of size 1 for storing blacklisted thumbnail
+ // Because no actual bitmap data is generated, there is no reason to
+ // add bitmap to server bitmap pool. Completion of client request with
+ // error code just results in applications showing their default bitmap.
+ if( iFilename != KNullDesC || iTargetUri != KNullDesC )
+ {
+ if ( aError == KErrNotSupported ||
+ aError == KErrCorrupt ||
+ aError == KErrCompletion)
+ {
+ TRAPD( err, CreateBlackListedL( aOriginalSize ) );
+ if (err != KErrNone)
+ {
+ TN_DEBUG2( "CThumbnailGenerateTask::ThumbnailProviderReady() - blacklisting failed with code %d", err );
+ }
+ }
+ }
+ Complete( aError );
+ }
+ else
+ {
+ // CreateScaleTasksL will take ownership of bitmap
+
+#ifdef _DEBUG
+ TN_DEBUG2( "CThumbnailGenerateTask::ThumbnailProviderReady() - displaymode is %d", aBitmap->DisplayMode());
+#endif
+
+ TRAPD( err, CreateScaleTasksL( aBitmap ));
+ aBitmap = NULL;
+ // If CreateScaleTasksL left, we are responsible for completing
+ // the RMessage. If there was no leave, then this call will not
+ // complete actual the message, just the mark the task as completed.
+ Complete( err );
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// Create tasks to scale the thumbnail to each persistent thumbnail size
+// and also to the size the client requested
+// ---------------------------------------------------------------------------
+//
+void CThumbnailGenerateTask::CreateScaleTasksL( CFbsBitmap* aBitmap )
+ {
+ __ASSERT_DEBUG(( aBitmap ), ThumbnailPanic( EThumbnailNullPointer ));
+
+ CleanupStack::PushL( aBitmap );
+ iServer.AddBitmapToPoolL( iRequestId.iSession, aBitmap );
+
+ // Keep pointer so we can delete bitmap from pool
+ iBitmap = aBitmap;
+ CleanupStack::Pop( aBitmap );
+
+ // compTask is the scale task which returns the bitmap to the client
+ CThumbnailScaleTask* complTask = NULL;
+
+ if ( iMissingSizes )
+ {
+ const TInt count = iMissingSizes->Count();
+
+ for ( TInt i( 0 ); i < count; i++ )
+ {
+ TThumbnailSize size = (*iMissingSizes)[ i ].iType;
+#ifdef _DEBUG
+ TN_DEBUG3( "CThumbnailGenerateTask(0x%08x)::CreateScaleTasksL() *iMissingSizes)[ i ].iType == %d", this, size );
+#endif
+
+ if ( iPortrait )
+ {
+ if ( size == EFullScreenThumbnailSize ||
+ size == EVideoFullScreenThumbnailSize ||
+ size == EAudioFullScreenThumbnailSize ||
+ size == EImageFullScreenThumbnailSize )
+ {
+ TN_DEBUG2( "*iMissingSizes)[ i ].iWidth == %d", (*iMissingSizes)[ i ].iSize.iWidth );
+ TN_DEBUG2( "*iMissingSizes)[ i ].iHeight == %d", (*iMissingSizes)[ i ].iSize.iHeight );
+ TInt width = (*iMissingSizes)[ i ].iSize.iWidth;
+ (*iMissingSizes)[ i ].iSize.iWidth = (*iMissingSizes)[ i ].iSize.iHeight;
+ (*iMissingSizes)[ i ].iSize.iHeight = width;
+ TN_DEBUG2( "*iMissingSizes)[ i ].iWidth == %d", (*iMissingSizes)[ i ].iSize.iWidth );
+ TN_DEBUG2( "*iMissingSizes)[ i ].iHeight == %d", (*iMissingSizes)[ i ].iSize.iHeight );
+ }
+ }
+
+ CThumbnailScaleTask* scaleTask = CThumbnailScaleTask::NewL( iProcessor, iServer, iFilename,
+ iBitmap, iOriginalSize, (*iMissingSizes)[ i ].iSize, (*iMissingSizes)[ i ].iCrop, iDisplayMode,
+ KMaxPriority, iTargetUri, (*iMissingSizes)[ i ].iType, iThumbnailId, iScaledBitmapToPool, iEXIF );
+ CleanupStack::PushL( scaleTask );
+
+ TInt err1 = KErrNone;
+ TInt err2 = KErrNone;
+ if(iFilename != KNullDesC)
+ {
+ TRAP(err1, iServer.StoreForPathL(iFilename));
+ }
+ if(iTargetUri != KNullDesC)
+ {
+ TRAP(err2, iServer.StoreForPathL(iTargetUri));
+ }
+ // if trying to access Z drive, don't try to store
+ // don't want to store custom sizes
+ if( err1 == KErrAccessDenied || err2 == KErrAccessDenied ||
+ (*iMissingSizes)[ i ].iType == ECustomThumbnailSize )
+ {
+ scaleTask->SetDoStore( EFalse );
+ }
+ else
+ {
+ scaleTask->SetDoStore( ETrue );
+ }
+
+ iProcessor.AddTaskL( scaleTask );
+ CleanupStack::Pop( scaleTask );
+
+ // completion to first task, because task processor works like stack
+ if( i == 0 )
+ {
+ // compTask is now responsible for completing the RMessage
+ scaleTask->SetMessageData( iRequestId, iMessage );
+ ResetMessageData();
+ }
+ }
+ }
+ else
+ {
+ if( iPortrait )
+ {
+ if ( iThumbnailSize == EFullScreenThumbnailSize ||
+ iThumbnailSize == EVideoFullScreenThumbnailSize ||
+ iThumbnailSize == EAudioFullScreenThumbnailSize ||
+ iThumbnailSize == EImageFullScreenThumbnailSize )
+ {
+ TInt width = iSize.iWidth;
+ iSize.iWidth = iSize.iHeight;
+ iSize.iHeight = width;
+ }
+ }
+
+ complTask = CThumbnailScaleTask::NewL( iProcessor, iServer, iFilename,
+ iBitmap, iOriginalSize, iSize, iFlags& CThumbnailManager
+ ::ECropToAspectRatio, iDisplayMode, KMaxPriority, iTargetUri,
+ iThumbnailSize, iThumbnailId, iScaledBitmapToPool, iEXIF );
+ CleanupStack::PushL( complTask );
+
+ TInt err1 = KErrNone;
+ TInt err2 = KErrNone;
+ if(iFilename != KNullDesC)
+ {
+ TRAP(err1, iServer.StoreForPathL(iFilename));
+ }
+ if(iTargetUri != KNullDesC)
+ {
+ TRAP(err2, iServer.StoreForPathL(iTargetUri));
+ }
+ // if trying to access Z drive, don't try to store
+ // don't want to store custom sizes
+ if( err1 == KErrAccessDenied || err2 == KErrAccessDenied ||
+ iThumbnailSize == ECustomThumbnailSize )
+ {
+ complTask->SetDoStore( EFalse );
+ }
+ else
+ {
+ complTask->SetDoStore( ETrue );
+ }
+
+ iProcessor.AddTaskL( complTask );
+ CleanupStack::Pop( complTask );
+
+ // compTask is now responsible for completing the RMessage and
+ // returning the bitmap to the client
+ complTask->SetMessageData( iRequestId, iMessage );
+ ResetMessageData();
+ }
+
+ // Scale tasks now reference the bitmap in the pool
+ iServer.DeleteBitmapFromPool( iBitmap->Handle());
+ iBitmap = NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// Defines if scaled bitmaps need to be added to pool
+// ---------------------------------------------------------------------------
+//
+void CThumbnailGenerateTask::ScaledBitmapToPool( TBool aBool )
+ {
+ iScaledBitmapToPool = aBool;
+ }
+
+// ---------------------------------------------------------------------------
+// Stores a blacklisted thumbnail
+// ---------------------------------------------------------------------------
+//
+void CThumbnailGenerateTask::CreateBlackListedL( const TSize& aOriginalSize )
+ {
+ CFbsBitmap* tempBitmap = 0;
+ tempBitmap = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL( tempBitmap );
+ TSize tempSize( 1, 1 );
+ User::LeaveIfError( tempBitmap->Create( tempSize, iDisplayMode ) );
+
+ // Instead of creating a blacklisted entry of requested size (iThumbnailSize) in thumbnail db,
+ // consider blacklisting all sizes (hence the changes are needed in thumbnail fetching logic too).
+ // However, decoding of source to thumnail could succeed in other sizes, which makes blacklisting
+ // of requested size only meaningful.
+ if(iFilename != KNullDesC)
+ {
+ iServer.StoreForPathL( iFilename )->StoreThumbnailL(
+ iFilename, tempBitmap, aOriginalSize, EFalse, iThumbnailSize, iThumbnailId, EFalse, ETrue );
+ }
+ else if(iTargetUri != KNullDesC)
+ {
+ iServer.StoreForPathL( iTargetUri )->StoreThumbnailL(
+ iTargetUri, tempBitmap, aOriginalSize, EFalse, iThumbnailSize, iThumbnailId, EFalse, ETrue );
+ }
+
+ CleanupStack::PopAndDestroy( tempBitmap );
+ }