imagehandlingutilities/thumbnailmanager/thumbnailserver/src/thumbnailgeneratetask.cpp
changeset 0 2014ca87e772
child 1 235a7fc86938
equal deleted inserted replaced
-1:000000000000 0:2014ca87e772
       
     1 /*
       
     2 * Copyright (c) 2006-2007 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:  Task for generating new thumbnails
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32base.h>
       
    20 #include <fbs.h>
       
    21 
       
    22 #include <thumbnailmanager.h>
       
    23 
       
    24 #include "thumbnailgeneratetask.h"
       
    25 #include "thumbnailscaletask.h"
       
    26 #include "thumbnailprovider.h"
       
    27 #include "thumbnailserver.h"
       
    28 #include "thumbnailtaskprocessor.h"
       
    29 #include "thumbnailmanagerconstants.h"
       
    30 #include "thumbnaillog.h"
       
    31 #include "thumbnailpanic.h"
       
    32 
       
    33 // ======== MEMBER FUNCTIONS ========
       
    34 
       
    35 // ---------------------------------------------------------------------------
       
    36 // CThumbnailGenerateTask::CThumbnailGenerateTask()
       
    37 // C++ default constructor can NOT contain any code, that might leave.
       
    38 // ---------------------------------------------------------------------------
       
    39 //
       
    40 CThumbnailGenerateTask::CThumbnailGenerateTask( CThumbnailTaskProcessor&
       
    41     aProcessor, CThumbnailServer& aServer, RFile64* aFile, TDesC8* aBuffer,
       
    42     const TDataType* aMimeType, CThumbnailManager::TThumbnailFlags aFlags,
       
    43     const TSize& aSize, TDisplayMode aDisplayMode, TInt aPriority,
       
    44     RArray < TThumbnailPersistentSize >* aMissingSizes, const TDesC& aTargetUri,
       
    45     TThumbnailSize aThumbnailSize, const TThumbnailId aThumbnailId, 
       
    46     const CThumbnailManager::TThumbnailQualityPreference aQualityPreference ): 
       
    47     CThumbnailTask( aProcessor, aPriority ), iServer( aServer ), 
       
    48     iFlags( aFlags ), iSize( aSize ), iDisplayMode( aDisplayMode ),
       
    49     iMissingSizes( aMissingSizes ), iTargetUri( aTargetUri ),
       
    50     iThumbnailSize( aThumbnailSize ), iThumbnailId(aThumbnailId),
       
    51     iQualityPreference( aQualityPreference )
       
    52     {
       
    53     TN_DEBUG2( "CThumbnailGenerateTask(0x%08x)::CThumbnailGenerateTask()", this);
       
    54     
       
    55     if ( !aBuffer && aFile)
       
    56         {
       
    57         iFile = *aFile; 
       
    58         iFile.FullName( iFilename );
       
    59         }
       
    60     else if( aBuffer )
       
    61         {
       
    62         iBuffer = aBuffer;
       
    63         }
       
    64     if ( aMimeType )
       
    65         {
       
    66         iMimeType = *aMimeType;
       
    67         }
       
    68     else
       
    69         {
       
    70         iMimeType = TDataType(KNullDesC8);
       
    71         }
       
    72     
       
    73     // scaled bitmaps to pool by default
       
    74     iScaledBitmapToPool = ETrue;
       
    75     }
       
    76 
       
    77 
       
    78 // ---------------------------------------------------------------------------
       
    79 // CThumbnailGenerateTask::~CThumbnailGenerateTask()
       
    80 // Destructor.
       
    81 // ---------------------------------------------------------------------------
       
    82 //
       
    83 CThumbnailGenerateTask::~CThumbnailGenerateTask()
       
    84     {
       
    85     TN_DEBUG2("CThumbnailGenerateTask(0x%08x)::~CThumbnailGenerateTask()", this);
       
    86     
       
    87     if ( iProvider )
       
    88         {
       
    89         iProvider->CancelGetThumbnail();
       
    90         }
       
    91 	
       
    92     if ( iMissingSizes )
       
    93         {
       
    94         iMissingSizes->Reset();
       
    95         delete iMissingSizes;
       
    96         }
       
    97 		
       
    98     if ( iBitmap )
       
    99         {
       
   100         iServer.DeleteBitmapFromPool( iBitmap->Handle());
       
   101         iBitmap = NULL;
       
   102         }
       
   103 		
       
   104     iProvider = NULL;
       
   105     delete iBuffer;
       
   106     iBuffer = NULL;
       
   107     
       
   108     iFile.Close();
       
   109     TN_DEBUG1("CThumbnailGenerateTask::~CThumbnailGenerateTask() - file handle closed");
       
   110     }
       
   111 
       
   112 
       
   113 // ---------------------------------------------------------------------------
       
   114 // CThumbnailGenerateTask::StartL()
       
   115 // ---------------------------------------------------------------------------
       
   116 //
       
   117 void CThumbnailGenerateTask::StartL()
       
   118     {
       
   119     TN_DEBUG2( "CThumbnailGenerateTask(0x%08x)::StartL()", this );
       
   120 
       
   121     CThumbnailTask::StartL();
       
   122     
       
   123 #ifdef _DEBUG
       
   124     aStart.UniversalTime();
       
   125 #endif
       
   126 
       
   127       
       
   128     TParsePtrC parse(iFilename);
       
   129     TPtrC ext(parse.Ext());
       
   130     TBuf8< KMaxDataTypeLength > mimeType;                
       
   131     if  (ext.CompareF(KNonEmbeddedArtExt)== 0) 
       
   132         {       
       
   133         mimeType.Copy( KImageMime );  		
       
   134         }
       
   135     else
       
   136         {
       
   137         mimeType = iMimeType.Des8();
       
   138         }
       
   139     iProvider = iServer.ResolveProviderL(mimeType);
       
   140        	
       
   141     TN_DEBUG3( "CThumbnailGenerateTask(0x%08x) -- provider UID 0x%08x", this,
       
   142         iProvider->Uid());
       
   143 
       
   144     __ASSERT_DEBUG(( iProvider ), ThumbnailPanic( EThumbnailNullPointer ));
       
   145 
       
   146     iProvider->CancelGetThumbnail();
       
   147     iProvider->Reset();
       
   148     iProvider->SetObserver( *this );
       
   149 
       
   150     TSize effectiveTargetSize;
       
   151     TSize croppedTargetSize;
       
   152 
       
   153     CalculateTargetSizesL( effectiveTargetSize, croppedTargetSize );
       
   154 
       
   155     iProvider->SetTargetSize( effectiveTargetSize );
       
   156       
       
   157     if(effectiveTargetSize == TSize())
       
   158         {
       
   159         iProvider->SetTargetSize( croppedTargetSize );
       
   160         }
       
   161 		
       
   162     if ( !iBuffer )
       
   163         {
       
   164         iProvider->GetThumbnailL( iServer.Fs(), iFile, iMimeType, iFlags,
       
   165             iDisplayMode, iQualityPreference );
       
   166         }
       
   167     else
       
   168         {
       
   169         iProvider->GetThumbnailL( iServer.Fs(), iBuffer, iMimeType, iFlags,
       
   170             iDisplayMode, iQualityPreference );
       
   171         }
       
   172     }
       
   173 
       
   174 
       
   175 // ---------------------------------------------------------------------------
       
   176 // CThumbnailGenerateTask::RunL()
       
   177 // ---------------------------------------------------------------------------
       
   178 //
       
   179 void CThumbnailGenerateTask::RunL()
       
   180     {
       
   181     // No implementation required
       
   182     }
       
   183 
       
   184 
       
   185 // ---------------------------------------------------------------------------
       
   186 // CThumbnailGenerateTask::DoCancel()
       
   187 // ---------------------------------------------------------------------------
       
   188 //
       
   189 void CThumbnailGenerateTask::DoCancel()
       
   190     {
       
   191     TN_DEBUG2( "CThumbnailGenerateTask(0x%08x)::DoCancel()", this );
       
   192     if ( iProvider )
       
   193         {
       
   194         iProvider->CancelGetThumbnail();
       
   195         }
       
   196     }
       
   197 
       
   198 
       
   199 // ---------------------------------------------------------------------------
       
   200 // Calculate the largest non-cropped size and largest cropped size and
       
   201 // let the provider plug-in know the values
       
   202 // ---------------------------------------------------------------------------
       
   203 //
       
   204 void CThumbnailGenerateTask::CalculateTargetSizesL( TSize& aEffectiveTargetSize,
       
   205     TSize& aCroppedTargetSize )
       
   206     { 
       
   207     if ( iThumbnailSize == ECustomThumbnailSize )
       
   208         {
       
   209         if ( iFlags& CThumbnailManager::ECropToAspectRatio )
       
   210             {
       
   211             aCroppedTargetSize = iSize;
       
   212             }
       
   213         else
       
   214             {
       
   215             aEffectiveTargetSize = iSize;
       
   216             }       
       
   217         }
       
   218     
       
   219     if ( iThumbnailSize != ECustomThumbnailSize )
       
   220         {
       
   221         RArray < TThumbnailPersistentSize > sizes = iServer.PersistentSizesL();
       
   222         const TInt count = sizes.Count();
       
   223         for ( TInt i = 0; i < count; i++ )
       
   224             {
       
   225             TThumbnailPersistentSize size( sizes[i] );     
       
   226 
       
   227             iSize = size.iSize;
       
   228             if ( size.iCrop )
       
   229                {
       
   230                aCroppedTargetSize.iWidth = Max( aCroppedTargetSize.iWidth,
       
   231                    size.iSize.iWidth );
       
   232                aCroppedTargetSize.iHeight = Max( aCroppedTargetSize.iHeight,
       
   233                    size.iSize.iHeight );
       
   234                if(iBuffer)
       
   235                  {
       
   236                  iFlags = ( CThumbnailManager::TThumbnailFlags ) (iFlags | CThumbnailManager::ECropToAspectRatio);
       
   237                  aEffectiveTargetSize = aCroppedTargetSize;
       
   238                  }
       
   239                }
       
   240             else
       
   241                {
       
   242                 aEffectiveTargetSize.iWidth = Max( aEffectiveTargetSize.iWidth,
       
   243                    size.iSize.iWidth );
       
   244                 aEffectiveTargetSize.iHeight = Max( aEffectiveTargetSize.iHeight,
       
   245                    size.iSize.iHeight );
       
   246                }
       
   247             
       
   248             if(size.iType == iThumbnailSize)
       
   249               {
       
   250               break;
       
   251               }     
       
   252             }
       
   253         }    
       
   254     }
       
   255 
       
   256 // ---------------------------------------------------------------------------
       
   257 // Thumbnail provider observer callback to notify the server when
       
   258 // thumbnail has been generated.
       
   259 // ---------------------------------------------------------------------------
       
   260 //
       
   261 void CThumbnailGenerateTask::ThumbnailProviderReady( const TInt aError,
       
   262     CFbsBitmap* aBitmap, const TSize& aOriginalSize, const TBool aEXIF, const TBool aPortrait )
       
   263     {
       
   264     TN_DEBUG4( 
       
   265         "CThumbnailGenerateTask(0x%08x)::ThumbnailProviderReady(aError=%d, aBitmap=0x%08x)", this, aError, aBitmap );
       
   266 
       
   267     #ifdef _DEBUG
       
   268     aStop.UniversalTime();
       
   269     TN_DEBUG2( "CThumbnailGenerateTask::ThumbnailProviderReady() generate took %d ms", (TInt)aStop.MicroSecondsFrom(aStart).Int64()/1000);
       
   270     #endif
       
   271     
       
   272     iPortrait = aPortrait;
       
   273     iEXIF = aEXIF;
       
   274     iOriginalSize = aOriginalSize;
       
   275 
       
   276     if ( aError )
       
   277         {
       
   278         delete aBitmap;
       
   279         aBitmap = NULL;
       
   280         // Create a temporary bitmap of size 1 for storing blacklisted thumbnail
       
   281         // Because no actual bitmap data is generated, there is no reason to 
       
   282         // add bitmap to server bitmap pool. Completion of client request with
       
   283         // error code just results in applications showing their default bitmap. 
       
   284         if( iFilename != KNullDesC || iTargetUri != KNullDesC )
       
   285             {
       
   286             if ( aError == KErrNotSupported ||
       
   287                     aError == KErrCorrupt ||
       
   288                     aError == KErrCompletion)
       
   289                 {
       
   290                 TRAPD( err, CreateBlackListedL( aOriginalSize ) );
       
   291                 if (err != KErrNone)
       
   292                     {
       
   293                     TN_DEBUG2( "CThumbnailGenerateTask::ThumbnailProviderReady() - blacklisting failed with code %d", err );
       
   294                     }
       
   295                 }
       
   296             }
       
   297         Complete( aError );
       
   298         }
       
   299     else
       
   300         {
       
   301         // CreateScaleTasksL will take ownership of bitmap
       
   302         
       
   303 #ifdef _DEBUG
       
   304         TN_DEBUG2( "CThumbnailGenerateTask::ThumbnailProviderReady() - displaymode is %d", aBitmap->DisplayMode());
       
   305 #endif
       
   306         
       
   307         TRAPD( err, CreateScaleTasksL( aBitmap ));
       
   308         aBitmap = NULL;
       
   309         // If CreateScaleTasksL left, we are responsible for completing
       
   310         // the RMessage. If there was no leave, then this call will not
       
   311         // complete actual the message, just the mark the task as completed.
       
   312         Complete( err );
       
   313         }
       
   314     }
       
   315 
       
   316 
       
   317 // ---------------------------------------------------------------------------
       
   318 // Create tasks to scale the thumbnail to each persistent thumbnail size
       
   319 // and also to the size the client requested
       
   320 // ---------------------------------------------------------------------------
       
   321 //
       
   322 void CThumbnailGenerateTask::CreateScaleTasksL( CFbsBitmap* aBitmap )
       
   323     {
       
   324     __ASSERT_DEBUG(( aBitmap ), ThumbnailPanic( EThumbnailNullPointer ));
       
   325 
       
   326     CleanupStack::PushL( aBitmap );
       
   327     iServer.AddBitmapToPoolL( iRequestId.iSession, aBitmap );
       
   328 
       
   329     // Keep pointer so we can delete bitmap from pool
       
   330     iBitmap = aBitmap;
       
   331     CleanupStack::Pop( aBitmap );
       
   332 
       
   333     // compTask is the scale task which returns the bitmap to the client
       
   334     CThumbnailScaleTask* complTask = NULL;
       
   335 	
       
   336     if ( iMissingSizes )
       
   337         {
       
   338         const TInt count = iMissingSizes->Count();
       
   339         
       
   340         for ( TInt i( 0 ); i < count; i++ )
       
   341             {
       
   342             TThumbnailSize size = (*iMissingSizes)[ i ].iType;
       
   343 #ifdef _DEBUG
       
   344             TN_DEBUG3( "CThumbnailGenerateTask(0x%08x)::CreateScaleTasksL() *iMissingSizes)[ i ].iType == %d", this, size );
       
   345 #endif
       
   346             
       
   347             if ( iPortrait )
       
   348                 {
       
   349                 if ( size == EFullScreenThumbnailSize ||
       
   350                      size == EVideoFullScreenThumbnailSize ||
       
   351                      size == EAudioFullScreenThumbnailSize ||
       
   352                      size == EImageFullScreenThumbnailSize )
       
   353                     {
       
   354                     TN_DEBUG2( "*iMissingSizes)[ i ].iWidth == %d", (*iMissingSizes)[ i ].iSize.iWidth );
       
   355                     TN_DEBUG2( "*iMissingSizes)[ i ].iHeight == %d", (*iMissingSizes)[ i ].iSize.iHeight );
       
   356                     TInt width = (*iMissingSizes)[ i ].iSize.iWidth; 
       
   357                     (*iMissingSizes)[ i ].iSize.iWidth = (*iMissingSizes)[ i ].iSize.iHeight;
       
   358                     (*iMissingSizes)[ i ].iSize.iHeight = width;
       
   359                     TN_DEBUG2( "*iMissingSizes)[ i ].iWidth == %d", (*iMissingSizes)[ i ].iSize.iWidth );
       
   360                     TN_DEBUG2( "*iMissingSizes)[ i ].iHeight == %d", (*iMissingSizes)[ i ].iSize.iHeight );
       
   361                     }
       
   362                 }
       
   363             
       
   364             CThumbnailScaleTask* scaleTask = CThumbnailScaleTask::NewL( iProcessor, iServer, iFilename,
       
   365                 iBitmap, iOriginalSize, (*iMissingSizes)[ i ].iSize, (*iMissingSizes)[ i ].iCrop, iDisplayMode,
       
   366                 KMaxPriority, iTargetUri, (*iMissingSizes)[ i ].iType, iThumbnailId, iScaledBitmapToPool, iEXIF );
       
   367             CleanupStack::PushL( scaleTask );
       
   368             
       
   369             TInt err1 = KErrNone;
       
   370             TInt err2 = KErrNone;
       
   371             if(iFilename != KNullDesC)
       
   372                 {
       
   373                 TRAP(err1, iServer.StoreForPathL(iFilename));
       
   374                 }
       
   375             if(iTargetUri != KNullDesC)
       
   376                 {
       
   377                 TRAP(err2, iServer.StoreForPathL(iTargetUri));
       
   378                 }
       
   379             // if trying to access Z drive, don't try to store
       
   380             // don't want to store custom sizes
       
   381             if( err1 == KErrAccessDenied || err2 == KErrAccessDenied ||
       
   382                     (*iMissingSizes)[ i ].iType == ECustomThumbnailSize )
       
   383                 {
       
   384                 scaleTask->SetDoStore( EFalse );
       
   385                 }
       
   386             else
       
   387                 {
       
   388                 scaleTask->SetDoStore( ETrue );
       
   389                 }
       
   390             
       
   391             iProcessor.AddTaskL( scaleTask );
       
   392             CleanupStack::Pop( scaleTask );
       
   393             
       
   394             // completion to first task, because task processor works like stack
       
   395             if( i == 0 )
       
   396                 {
       
   397                 // compTask is now responsible for completing the RMessage
       
   398                 scaleTask->SetMessageData( iRequestId, iMessage );
       
   399                 ResetMessageData();
       
   400                 }
       
   401             }
       
   402         }
       
   403     else
       
   404         {
       
   405         if( iPortrait )
       
   406             {
       
   407             if ( iThumbnailSize == EFullScreenThumbnailSize ||
       
   408                  iThumbnailSize == EVideoFullScreenThumbnailSize ||
       
   409                  iThumbnailSize == EAudioFullScreenThumbnailSize ||
       
   410                  iThumbnailSize == EImageFullScreenThumbnailSize )
       
   411                       {
       
   412                       TInt width = iSize.iWidth; 
       
   413                       iSize.iWidth = iSize.iHeight;
       
   414                       iSize.iHeight = width;
       
   415                       }
       
   416             }
       
   417         
       
   418         complTask = CThumbnailScaleTask::NewL( iProcessor, iServer, iFilename,
       
   419             iBitmap, iOriginalSize, iSize, iFlags& CThumbnailManager
       
   420             ::ECropToAspectRatio, iDisplayMode, KMaxPriority, iTargetUri,
       
   421             iThumbnailSize, iThumbnailId, iScaledBitmapToPool, iEXIF );
       
   422         CleanupStack::PushL( complTask );
       
   423         
       
   424         TInt err1 = KErrNone;
       
   425         TInt err2 = KErrNone;
       
   426         if(iFilename != KNullDesC)
       
   427             {
       
   428             TRAP(err1, iServer.StoreForPathL(iFilename));
       
   429             }
       
   430         if(iTargetUri != KNullDesC)
       
   431             {
       
   432             TRAP(err2, iServer.StoreForPathL(iTargetUri));
       
   433             }
       
   434         // if trying to access Z drive, don't try to store
       
   435         // don't want to store custom sizes
       
   436         if( err1 == KErrAccessDenied || err2 == KErrAccessDenied ||
       
   437             iThumbnailSize == ECustomThumbnailSize )
       
   438             {
       
   439             complTask->SetDoStore( EFalse );
       
   440             }
       
   441         else
       
   442             {
       
   443             complTask->SetDoStore( ETrue );
       
   444             }
       
   445         
       
   446         iProcessor.AddTaskL( complTask );
       
   447         CleanupStack::Pop( complTask );
       
   448         
       
   449         // compTask is now responsible for completing the RMessage and
       
   450         // returning the bitmap to the client
       
   451         complTask->SetMessageData( iRequestId, iMessage );
       
   452         ResetMessageData();
       
   453         }
       
   454 
       
   455     // Scale tasks now reference the bitmap in the pool
       
   456     iServer.DeleteBitmapFromPool( iBitmap->Handle());
       
   457     iBitmap = NULL;
       
   458     }
       
   459 
       
   460 // ---------------------------------------------------------------------------
       
   461 // Defines if scaled bitmaps need to be added to pool
       
   462 // ---------------------------------------------------------------------------
       
   463 //
       
   464 void CThumbnailGenerateTask::ScaledBitmapToPool( TBool aBool )
       
   465     {
       
   466     iScaledBitmapToPool = aBool;
       
   467     }
       
   468 
       
   469 // ---------------------------------------------------------------------------
       
   470 // Stores a blacklisted thumbnail
       
   471 // ---------------------------------------------------------------------------
       
   472 //
       
   473 void CThumbnailGenerateTask::CreateBlackListedL( const TSize& aOriginalSize )
       
   474     {
       
   475     CFbsBitmap* tempBitmap = 0;
       
   476     tempBitmap = new (ELeave) CFbsBitmap();
       
   477     CleanupStack::PushL( tempBitmap );
       
   478     TSize tempSize( 1, 1 );
       
   479     User::LeaveIfError( tempBitmap->Create( tempSize, iDisplayMode ) );
       
   480     
       
   481     // Instead of creating a blacklisted entry of requested size (iThumbnailSize) in thumbnail db,
       
   482     // consider blacklisting all sizes (hence the changes are needed in thumbnail fetching logic too).
       
   483     // However, decoding of source to thumnail could succeed in other sizes, which makes blacklisting
       
   484     // of requested size only meaningful. 
       
   485     if(iFilename != KNullDesC)
       
   486         {
       
   487         iServer.StoreForPathL( iFilename )->StoreThumbnailL( 
       
   488             iFilename, tempBitmap, aOriginalSize, EFalse, iThumbnailSize, iThumbnailId, EFalse, ETrue );
       
   489         }
       
   490     else if(iTargetUri != KNullDesC)
       
   491         {
       
   492         iServer.StoreForPathL( iTargetUri )->StoreThumbnailL( 
       
   493             iTargetUri, tempBitmap, aOriginalSize, EFalse, iThumbnailSize, iThumbnailId, EFalse, ETrue );
       
   494         }
       
   495 
       
   496     CleanupStack::PopAndDestroy( tempBitmap );
       
   497     }