photosgallery/collectionframework/thumbnailcreator/src/glxtngeneratethumbnailtask.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:45:44 +0200
changeset 0 4e91876724a2
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 2008-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:    Classes for thumbnail-related tasks.
*
*/




/**
 * @internal reviewed 31/07/2007 by Simon Brooks
 */

#include "glxtngeneratethumbnailtask.h"

#include <bitdev.h>
#include <fbs.h>
#include <glxassert.h>
#include <glxlog.h>
#include <glxtracer.h>
#include <glxthumbnail.h>

#include "glxtnfileinfo.h"
#include "glxtnfileutility.h"
#include "glxtnimageutility.h"
#include "glxtnsavethumbnailtask.h"
#include "glxtntaskmanager.h"
#include "glxtnthumbnailrequest.h"
#include "glxtnvideoutility.h"
#include "mglxtnthumbnailcreatorclient.h"

// -----------------------------------------------------------------------------
// NewL
// -----------------------------------------------------------------------------
//
CGlxtnGenerateThumbnailTask* CGlxtnGenerateThumbnailTask::NewL(
        const TGlxThumbnailRequest& aRequestInfo,
        CGlxtnFileUtility& aFileUtility, MGlxtnThumbnailCreatorClient& aClient)
    {
    TRACER("CGlxtnGenerateThumbnailTask::NewL()");
    CGlxtnGenerateThumbnailTask* task
                = new (ELeave) CGlxtnGenerateThumbnailTask(
                                        aRequestInfo, aFileUtility, aClient);
    CleanupStack::PushL(task);
    task->ConstructL(aRequestInfo.iBitmapHandle);
    CleanupStack::Pop( task );
    return task;
    }

// -----------------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------
//
CGlxtnGenerateThumbnailTask::CGlxtnGenerateThumbnailTask(
        const TGlxThumbnailRequest& aRequestInfo,
        CGlxtnFileUtility& aFileUtility, MGlxtnThumbnailCreatorClient& aClient) :
    CGlxtnLoadThumbnailTask( KGlxtnTaskIdGenerateThumbnail,
                            aRequestInfo, aFileUtility, aClient )
	{
    TRACER("CGlxtnGenerateThumbnailTask::CGlxtnGenerateThumbnailTask()");
	}

// -----------------------------------------------------------------------------
// ConstructL
// -----------------------------------------------------------------------------
//
void CGlxtnGenerateThumbnailTask::ConstructL(TInt aBitmapHandle)
	{
    TRACER("CGlxtnGenerateThumbnailTask::ConstructL()");
	CGlxtnLoadThumbnailTask::ConstructL( aBitmapHandle );

    iImageUtility = new (ELeave) CGlxtnImageUtility(iFileUtility.FsSession());
	}

// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
//
CGlxtnGenerateThumbnailTask::~CGlxtnGenerateThumbnailTask() 
	{
    TRACER("CGlxtnGenerateThumbnailTask::~CGlxtnGenerateThumbnailTask()");
	delete iImageUtility;
    delete iVideoUtility;
    delete iImage;
	}

// -----------------------------------------------------------------------------
// SetManager
// -----------------------------------------------------------------------------
//
void CGlxtnGenerateThumbnailTask::SetManager(CGlxtnTaskManager* aManager)
    {
    TRACER("void CGlxtnGenerateThumbnailTask::SetManager()");
    iTaskManager = aManager;
    }

// -----------------------------------------------------------------------------
// DoStartL
// -----------------------------------------------------------------------------
//
TBool CGlxtnGenerateThumbnailTask::DoStartL(TRequestStatus& aStatus)
    {
    TRACER("CGlxtnGenerateThumbnailTask::DoStartL()");
    iInfo = new (ELeave) CGlxtnFileInfo;
    Client().FetchFileInfoL(iInfo, ItemId(), &aStatus);
    iState = EStateFetchingUri;

    return ETrue; // Request has been issued
    } 

// -----------------------------------------------------------------------------
// DoCancel
// -----------------------------------------------------------------------------
//
void CGlxtnGenerateThumbnailTask::DoCancel() 
	{
    TRACER("void CGlxtnGenerateThumbnailTask::DoCancel()");
	CGlxtnLoadThumbnailTask::DoCancel();

	iImageUtility->Cancel();

	if ( iVideoUtility ) 
		{
		iVideoUtility->Cancel();
		}

    iFileUtility.ClearBadFileMarker();
	}

// -----------------------------------------------------------------------------
// DoRunL
// -----------------------------------------------------------------------------
//
TBool CGlxtnGenerateThumbnailTask::DoRunL(TRequestStatus& aStatus) 
	{
    TRACER("TBool CGlxtnGenerateThumbnailTask::DoRunL()");
	TInt error = aStatus.Int();

	TBool active = EFalse;

    if ( KErrNone == error )
        {
        switch ( iState )
            {
            case EStateFetchingUri:
                {
                User::LeaveIfNull(iInfo);
                iBadFileMarkerNotNeededFlag = ETrue;

                iInfo->IdentifyFileL(iVideo, iProtected);
                // leave if file is DRM protected and client has no DRM 
                // capablity
                if ( iProtected && !iDrmAllowed )
                    {
                    User::Leave(KErrAccessDenied);
                    }

                if ( !LoadThumbnailL( aStatus ) )
                    {
                    iBadFileMarkerNotNeededFlag = EFalse;
                    iFileUtility.CheckBadFileListL( iInfo->FilePath() );
                    HighQualityDecodeL( aStatus );
                    }
                active = ETrue;
                }
                break;

            case EStateLoading:
                active = HandleLoadedThumbnailL( aStatus );
                break;

            case EStateDecodingThumbnail:
                // Nothing to do
                break;

            case EStateDecodingImage:
                {
                iImageUtility->FreeDecoder();

                // Resize empty bitmap to required size
                TSize targetSize(iRequestedSize);
                iImageUtility->AdjustSize(targetSize, iImage->SizeInPixels());
                User::LeaveIfError(iThumbnail->Resize(targetSize));

                iImageUtility->FilterImageL(&aStatus, iImage, iImage, iThumbnail);
                iState = EStateFiltering;
                active = ETrue;
                }
                break;

            case EStateFiltering:
                {
                TSize targetSize(iRequestedSize);
                const TSize srcSize = iImage->SizeInPixels();
                iImageUtility->AdjustSize(targetSize, iImage->SizeInPixels());
                iImageUtility->ScaleImageL(aStatus, *iImage, srcSize, *iThumbnail, targetSize);
                iState = EStateScaling;
                active = ETrue;
                }
                break;

            case EStateScaling:
            	{
            	User::LeaveIfError(iThumbnail->SetDisplayMode(KGlxThumbnailDisplayMode));
            	           	
                // Create task to save generated thumbnail
                if ( Storage() && !iInfo->iTemporary
                    && !SizeRequiresDrmRights()
                    && iFileUtility.IsPersistentSize(iRequestedSize) )
                    {
                    CGlxtnSaveThumbnailTask* task
                        = CGlxtnSaveThumbnailTask::NewL(ItemId(), iInfo,
                                        iRequestedSize, iThumbnail, Storage());
                    iThumbnail = NULL;  // Task has ownership
                    iInfo = NULL;       // Task has ownership
                    iTaskManager->AddTaskL(task);
                    }
                break;
            	}

            default:
                GLX_ASSERT_ALWAYS( EFalse, Panic( EGlxPanicIllegalState ),
                            "CGlxtnGenerateThumbnailTask: Illegal state" );
                break;
            }
        }
    else
        {
        if ( EStateLoading == iState )
            {
            // Loading failed - generate new thumbnail instead
            HighQualityDecodeL( aStatus );
            active = ETrue;
            }
        }

    if ( !active )
        {
        if ( !iBadFileMarkerNotNeededFlag )
            {
            iFileUtility.ClearBadFileMarker();
            }
        Client().ThumbnailFetchComplete(ItemId(),
                                        EGlxThumbnailQualityHigh, error);
        }

    return active; 
	}

// -----------------------------------------------------------------------------
// DoRunError
// -----------------------------------------------------------------------------
//
TBool CGlxtnGenerateThumbnailTask::DoRunError(TInt aError)
    {
    TRACER("TBool CGlxtnGenerateThumbnailTask::DoRunError(TInt aError)");
    iFileUtility.ClearBadFileMarker();
    Client().ThumbnailFetchComplete(ItemId(), EGlxThumbnailQualityHigh, aError);

    return EFalse;
    }

// ---------------------------------------------------------------------------
// HighQualityDecodeL
// ---------------------------------------------------------------------------
//
void CGlxtnGenerateThumbnailTask::HighQualityDecodeL(
                                                TRequestStatus& aStatus )
    {
    TRACER("void CGlxtnGenerateThumbnailTask::HighQualityDecodeL()");
    RArray<TSize> targetSizes;
    CleanupClosePushL(targetSizes);
    targetSizes.AppendL( TSize(iRequestedSize) );
    if ( iVideo )
        {
        iVideoUtility = new (ELeave) CGlxtnVideoUtility;
        iVideoUtility->GetVideoFrameL( &aStatus, iImage, iInfo->FilePath(), targetSizes, KGlxThumbnailDisplayMode );
        }
    else
        {
        iImage = iImageUtility->DecodeImageL( aStatus, iInfo->FilePath(),
                                    targetSizes, KGlxThumbnailDisplayMode );
        }
    CleanupStack::PopAndDestroy(&targetSizes);
    iState = EStateDecodingImage;
    }

// -----------------------------------------------------------------------------
// SizeRequiresDrmRights
// -----------------------------------------------------------------------------
//
TBool CGlxtnGenerateThumbnailTask::SizeRequiresDrmRights()
    {
    TRACER("TBool CGlxtnGenerateThumbnailTask::SizeRequiresDrmRights()");
    if ( iProtected )
        {
        if ( iVideo )
            {
            return ETrue;
            }

        // Rights are required if thumbnail doesn't fit in KGlxThumbnailDrmWidth
        // by KGlxThumbnailDrmHeight box either portrait or landscape
        if ( (iRequestedSize.iWidth > KGlxThumbnailDrmWidth
                || iRequestedSize.iHeight > KGlxThumbnailDrmHeight)
            && (iRequestedSize.iWidth > KGlxThumbnailDrmHeight
                || iRequestedSize.iHeight > KGlxThumbnailDrmWidth) )
            {
            return ETrue;
            }

        const TSize& imageSize(iImageUtility->OriginalSize());

        // Rights are required if thumbnail is greater than 25% of image size
        // Due to preserving aspect ratio, this will only happen if both width
        // and height are greater than half the image width and height
        if ( iRequestedSize.iWidth > imageSize.iWidth / 2
            && iRequestedSize.iHeight> imageSize.iHeight / 2 )
            {
            return ETrue;
            }
        }

    return EFalse;
    }