imagehandlingutilities/thumbnailmanager/thumbnailserver/src/thumbnailgeneratetask.cpp
changeset 0 2014ca87e772
child 1 235a7fc86938
--- /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 );
+    }