photosgallery/collectionframework/thumbnailcreator/thumbnailcomposerplugin/glxthumbnailcomposerplugin.cpp
author Simon Howkins <simonh@symbian.org>
Mon, 29 Nov 2010 11:47:03 +0000
branchRCL_3
changeset 78 dbcb928abe9c
parent 60 5b3385a43d68
permissions -rw-r--r--
Adjusted to avoid exports, etc, from a top-level bld.inf

/*
* 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:    Thumbnail Composer plugin
*
*/




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

#include <e32base.h>

#include <MdELogicCondition.h>
#include <mdeconstants.h>

#include <mpxcollectionutility.h>
#include <mpxcollectionpath.h>
#include <mpxcollectionmessage.h>
#include <mpxmessagegeneraldefs.h>
#include <mpxcollectionframeworkdefs.h>

#include <glxassert.h>
#include <glxcollectionpluginall.hrh>
#include <glxthumbnailattributeinfo.h>
#include <glxbackgroundtnmessagedefs.h>
#include <glxmediaid.h>
#include <glxthumbnailinfo.h>
#include <glxfilterfactory.h>
#include <glxcommandfactory.h>
#include <glxtracer.h>
#include <hal.h>

#include "glxthumbnailcomposerplugin.h"

// This can be any number other than zero
const TUint KGlxBackgroundThumbnailAttributeId = 1;
const TInt KGlxThumbnailComposerInactivityTimeout = 30; // seconds
const TInt KGlxThumbnailComposerDelay = 10000; // microseconds
const TInt KGlxThumbnailComposerHarvestDelay = 5000000; // microseconds
const TInt KGlxThumbnailComposerLargeDelay = 30000000; // microseconds
const TInt KGlxDisplayStatusTimeOutDelay = 5000000; // 5 secs

// ---------------------------------------------------------------------------
// destructor
// ---------------------------------------------------------------------------
//
CGlxThumbnailCompeserInactivityTimer::~CGlxThumbnailCompeserInactivityTimer()
    {
    // no implementation
    }


// ---------------------------------------------------------------------------
// NewL
// ---------------------------------------------------------------------------
//
CGlxThumbnailCompeserInactivityTimer* CGlxThumbnailCompeserInactivityTimer::NewL(TInt aPriority, CGlxThumbnailComposerPlugin& aCallback)
    {
	TRACER("CGlxThumbnailCompeserInactivityTimer::NewL");
	CGlxThumbnailCompeserInactivityTimer* self = 
	                              new (ELeave) CGlxThumbnailCompeserInactivityTimer(aPriority, aCallback);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	CActiveScheduler::Add(self);
	return self;
    }

// ---------------------------------------------------------------------------
// After
// ---------------------------------------------------------------------------
//
void CGlxThumbnailCompeserInactivityTimer::After( TTimeIntervalMicroSeconds32 aInterval )
    {
    TRACER("CGlxThumbnailCompeserInactivityTimer::After");

    // Fix for ELLZ-7DBBDZ and JPKN-7M2AYJ: to prevent a KERN EXEC 15 panic that occurs 
    // if a timer request is made while one is already outstanding.
    Cancel();
    // Forward the call on to the base class.
    CTimer::After( aInterval );
    }

// ---------------------------------------------------------------------------
// constructor
// ---------------------------------------------------------------------------
//
CGlxThumbnailCompeserInactivityTimer::CGlxThumbnailCompeserInactivityTimer(TInt aPriority, CGlxThumbnailComposerPlugin& aCallback)
         : CTimer(aPriority), iCallback(aCallback)
        {
        // no implementation
        }

// ---------------------------------------------------------------------------
// RunL
// ---------------------------------------------------------------------------
//
void CGlxThumbnailCompeserInactivityTimer::RunL()
    {
	TRACER("CGlxThumbnailCompeserInactivityTimer::RunL");
	
    TInt dispState = KErrNotFound;
    TInt ret = HAL::Get(HALData::EDisplayState, dispState);
    GLX_DEBUG4("CGlxThumbnailCompeserInactivityTimer::RunL iCallback.iState = %d, ret=%d, dispState= %d", 
    																iCallback.iState, ret, dispState );
	if (iCallback.iState && ret == KErrNone && dispState)
		{
		iCallback.DelayDisplayStateCheck();
	    GLX_LOG_INFO("GlxThumbnailCompeser - DISPLAY ON - DO NOT PROCESS" );
		return;
		}

	GLX_LOG_INFO("GlxThumbnailCompeser - DISPLAY OFF - ALLOW TO PROCESS" );
		
	switch (iCallback.iState)
	    {
    	case CGlxThumbnailComposerPlugin::EStateFirstOpening:
    	case CGlxThumbnailComposerPlugin::EStateOpening:
    	    {
            iCallback.DoOpenCollectionL();
            break;
    	    }
        case CGlxThumbnailComposerPlugin::EStateActiveSmall:
        case CGlxThumbnailComposerPlugin::EStateActiveLarge:
            {
        	iCallback.DoRequestItemL();
        	break;
            }
        case CGlxThumbnailComposerPlugin::EStateClosing:
            {
            iCallback.CloseCollection();
            break;
            }
	    }
    }

// ---------------------------------------------------------------------------
// DoCancel
// ---------------------------------------------------------------------------
//
void CGlxThumbnailCompeserInactivityTimer::DoCancel()
    {
    // no implementation
    }

// ---------------------------------------------------------------------------
// RunError
// ---------------------------------------------------------------------------
//
TInt CGlxThumbnailCompeserInactivityTimer::RunError(TInt /*aError*/)
    {
	TRACER("CGlxThumbnailCompeserInactivityTimer::RunError");
    iCallback.ReturnToIdle();
    return KErrNone;
    }



// ---------------------------------------------------------------------------
// NewL
// ---------------------------------------------------------------------------
//
CGlxThumbnailComposerPlugin* CGlxThumbnailComposerPlugin::NewL()
	{
	TRACER("CGlxThumbnailComposerPlugin::NewL");
	CGlxThumbnailComposerPlugin* self = 
	                              new (ELeave) CGlxThumbnailComposerPlugin();
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

// ---------------------------------------------------------------------------
// ~CGlxThumbnailComposerPlugin
// ---------------------------------------------------------------------------
//
CGlxThumbnailComposerPlugin::~CGlxThumbnailComposerPlugin()
	{
	delete iPath;
    if (iCollectionUtility)
        {
        iCollectionUtility->Close();
        }

	if ( iInactivityTimer )
	    {
    	iInactivityTimer->Cancel();
	    }
	delete iInactivityTimer;
	}

// ---------------------------------------------------------------------------
// CGlxThumbnailComposerPlugin
// ---------------------------------------------------------------------------
//
CGlxThumbnailComposerPlugin::CGlxThumbnailComposerPlugin() : iLastError(KErrNone)
	{
	}

// ---------------------------------------------------------------------------
// ConstructL
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::ConstructL()
	{
	TRACER("CGlxThumbnailComposerPlugin::ConstructL");
	iInactivityTimer = CGlxThumbnailCompeserInactivityTimer::NewL(CActive::EPriorityIdle, *this);
	}

// ---------------------------------------------------------------------------
// SetObservers
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::SetObservers()
	{
	TRAPD(err, SetObserversL());
    GLX_ASSERT_ALWAYS( KErrNone == err, Panic( EGlxPanicEnvironment ),
                        "CGlxThumbnailComposerPlugin cannot set observers, reset Harvester server" );
	}

// ---------------------------------------------------------------------------
// SetObserversL
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::SetObserversL()
	{
	TRACER("CGlxThumbnailComposerPlugin::SetObserversL");
	if ( iSession )
		{
		CMdELogicCondition* condition = 
		            CMdELogicCondition::NewLC( ELogicConditionOperatorOr );

#ifdef RD_MDS_2_0

		CMdENamespaceDef* defaultNamespace = 
		               iSession->GetDefaultNamespaceDefL();

    	CMdEObjectDef* imageDef = defaultNamespace->GetObjectDefL(
    	                                MdeConstants::Image::KImageObject );
		condition->AddObjectConditionL( *imageDef );

    	CMdEObjectDef* videoDef = defaultNamespace->GetObjectDefL(
    	                                MdeConstants::Video::KVideoObject );
		condition->AddObjectConditionL( *videoDef );

#else

		CMdENamespaceDef& defaultNamespace = 
		               iSession->GetDefaultNamespaceDefL();

    	CMdEObjectDef& imageDef = defaultNamespace.GetObjectDefL(
    	                                MdeConstants::Image::KImageObject );
		condition->AddObjectConditionL( imageDef );

    	CMdEObjectDef& videoDef = defaultNamespace.GetObjectDefL(
    	                                MdeConstants::Video::KVideoObject );
		condition->AddObjectConditionL( videoDef );

#endif

		iSession->AddObjectObserverL( *this, condition );
    	CleanupStack::Pop( condition );
    	
        if ( iState == EStateIdle )
            {
            iState = EStateFirstOpening;
            iInactivityTimer->After(KGlxThumbnailComposerLargeDelay);
            }
		}
	}

// ---------------------------------------------------------------------------
// RemoveObservers
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::RemoveObservers()
	{
	if ( iSession )
		{
#ifdef RD_MDS_2_0
		iSession->RemoveObjectObserver( *this );
#else
		TRAP_IGNORE(iSession->RemoveObjectObserverL( *this ));
#endif
		}
	}

// ---------------------------------------------------------------------------
// IsComposingComplete
// ---------------------------------------------------------------------------
//
TBool CGlxThumbnailComposerPlugin::IsComposingComplete()
	{
	TRACER("CGlxThumbnailComposerPlugin::IsComposingComplete");
	// Need to stop background thumbnail generation activity
	// when harvester requests to pause. 
	    
	    if (iState != EStateIdle)
	        {
	        iState = EStateClosing;
	        
	        if ( iInactivityTimer )
	            {
	            iInactivityTimer->Cancel();
	            }

	        if (iCollectionUtility)
	            {
	            iCollectionUtility->Close();
	            iCollectionUtility = NULL;
	            }
	            
	        iState = EStateIdle;
	        }
	    
	    return ETrue ;
	}

#ifdef RD_MDS_2_0

// ---------------------------------------------------------------------------
// HandleObjectAdded
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::HandleObjectAdded(
        CMdESession& /*aSession*/, const RArray<TItemId>& /*aObjectIdArray*/ )
	{
	TRACER("CGlxThumbnailComposerPlugin::HandleObjectAdded");
    if ( ( iState == EStateIdle ) || ( iState == EStateFirstOpening ) || ( iState == EStateClosing ) )
        {
        iInactivityTimer->Cancel();
        iState = EStateOpening;
        iInactivityTimer->After(20000000);
        }
    else
        {
        iLastError = 1;
        iState = EStateActiveLarge;
        }
	}

// ---------------------------------------------------------------------------
// HandleObjectModified
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::HandleObjectModified(
                                    CMdESession& /*aSession*/, 
                                    const RArray<TItemId>& /*aObjectIdArray*/)
	{
	//no implemention needed
	}

// ---------------------------------------------------------------------------
// HandleObjectRemoved
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::HandleObjectRemoved(
                                    CMdESession& /*aSession*/, 
                                    const RArray<TItemId>& /*aObjectIdArray*/)
	{
	//no implemention needed
	}

#else

void CGlxThumbnailComposerPlugin::HandleObjectNotification(CMdESession& /*aSession*/, 
					TObserverNotificationType aType,
					const RArray<TItemId>& /*aObjectIdArray*/)
	{
	TRACER("CGlxThumbnailComposerPlugin::HandleObjectNotification");
    if (aType == ENotifyAdd)
    	{
			if ( iState == EStateIdle )
		        {
		        iState = EStateOpening;
		        iInactivityTimer->After(KGlxThumbnailComposerLargeDelay);
		        }
		    else
		        {
		        iLastError = 1;
		        iState = EStateActiveLarge;
		        iInactivityTimer->After(KGlxThumbnailComposerLargeDelay);
		        }
    	}
	}

#endif

// ---------------------------------------------------------------------------
// HandleCollectionMediaL
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::HandleCollectionMediaL(
                                const CMPXMedia& /*aMedia*/, TInt aError )
    {
	TRACER("CGlxThumbnailComposerPlugin::HandleCollectionMediaL");
    if ( iPath && KErrNone != aError )
        {
        GLX_LOG_WARNING1( "Error %d getting media", aError );

        // Error generating thumbnails, try the next item
        iLastError = aError;
        iCurrentIndex++;
        RequestItemL();
        }
    }

// ---------------------------------------------------------------------------
// HandleCollectionMessageL
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::HandleCollectionMessage(
                                        CMPXMessage* aMsg, TInt /*aErr*/ )
    {
	TRACER("CGlxThumbnailComposerPlugin::HandleCollectionMessage");
    if ( iState != EStateIdle && aMsg )
        {
        TRAPD( err, DoHandleCollectionMessageL( *aMsg ) );
        if ( KErrNone != err )
            {
            GLX_LOG_WARNING1( "Error %d handling message", err );
            ReturnToIdle();
            }
        }
    }

// ---------------------------------------------------------------------------
// HandleOpenL
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::HandleOpenL( const CMPXMedia& /*aEntries*/,
                          TInt /*aIndex*/, TBool /*aComplete*/, TInt aError )
    {
	TRACER("CGlxThumbnailComposerPlugin::HandleOpenL");
    if ( KErrNone != aError )
        {
        GLX_LOG_WARNING1( "Error %d opening collection", aError );
        ReturnToIdle();
        }
    }

// ---------------------------------------------------------------------------
// HandleOpenL
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::HandleOpenL(
            const CMPXCollectionPlaylist& /*aPlaylist*/, TInt /*aError*/ )
    {
	// No implemention needed
    }

// ---------------------------------------------------------------------------
// HandleCommandComplete
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::HandleCommandComplete(
                        CMPXCommand* /*aCommandResult*/, TInt /*aError*/ )
    {
	TRACER("CGlxThumbnailComposerPlugin::HandleCommandComplete");
    if( EStateCleanup == iState )
        {
        ReturnToIdle();
        }
    else
        {
        iInactivityTimer->After(0);
        }
    }

// ---------------------------------------------------------------------------
// DoOpenCollectionL
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::DoOpenCollectionL()
    {
	TRACER("CGlxThumbnailComposerPlugin::HandleCollectionMediaL");
    if ( !iCollectionUtility )
        {
        // Open isolated collection utility
        iCollectionUtility = MMPXCollectionUtility::NewL(
                                                this, KMcModeIsolated );
        }

    CMPXFilter* filter = CMPXFilter::NewL();
    CleanupStack::PushL(filter);
    filter->SetTObjectValueL<TGlxFilterSortDirection>(KGlxFilterGeneralSortDirection, EGlxFilterSortDirectionDescending);        
    iCollectionUtility->Collection().SetFilterL(filter);
    CleanupStack::PopAndDestroy(filter);

    CMPXCollectionPath* path = CMPXCollectionPath::NewL();
    CleanupStack::PushL( path );
    // argument  path  all collection id
   	path->AppendL( KGlxCollectionPluginAllImplementationUid );

	iCollectionUtility->Collection().OpenL( *path );
 	CleanupStack::PopAndDestroy( path );

    iState = EStateActiveSmall;                    
    }

// ---------------------------------------------------------------------------
// DoHandleCollectionMessageL
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::DoHandleCollectionMessageL(
                                                 const CMPXMessage& aMsg )
    {
	TRACER("CGlxThumbnailComposerPlugin::DoHandleCollectionMessageL");
    if ( aMsg.IsSupported( KMPXMessageGeneralId ) )
        {
        TInt messageId = aMsg.ValueTObjectL<TInt>( KMPXMessageGeneralId );

	    // Is it a background thumbnail message        
	    if ( KGlxMessageIdBackgroundThumbnail == messageId )
	        {
	        // Is it the item expected
	        TGlxMediaId id( ( TUint32 )
	             aMsg.ValueTObjectL<TMPXItemId>( KGlxBackgroundThumbnailMediaId ) );
	        if ( iPath && id.Value()
	                        == ( TUint32 )iPath->IdOfIndex( iCurrentIndex ) )
	            {
	            TInt error = aMsg.ValueTObjectL<TInt>( KGlxBackgroundThumbnailError );
	            if ( error == KErrCancel )
	                {
	                iState = EStateActiveLarge;
    	            iLastError = error;
	                }
	            else if( KErrNone != error )
	                {
                    GLX_LOG_WARNING1( "Error %d in command", error );
                    error = KErrNone;
	                }
	            // Yes, then request the next item
	            iCurrentIndex++;
	            RequestItemL();
	            }
	        }
        else if ( KMPXMessageGeneral == messageId
                && aMsg.IsSupported( KMPXMessageGeneralEvent ) )
            {
            TInt messageEvent = aMsg.ValueTObjectL<TInt>( KMPXMessageGeneralEvent );

            // Is it a path changed event
            if ( TMPXCollectionMessage::EPathChanged == messageEvent
                && aMsg.IsSupported( KMPXMessageGeneralType ) )
                {
    	        TInt messageType = aMsg.ValueTObjectL<TInt>( KMPXMessageGeneralType );

             	if ( EMcPathChangedByOpen == messageType
             	    && iCollectionUtility && !iPath )
            	    {
         		    iPath = iCollectionUtility->Collection().PathL();

                   	iCurrentIndex = 0;
                    RequestItemL();
            	    }
               }
            }
        }
    }

// ---------------------------------------------------------------------------
// RequestItemL
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::RequestItemL()
    {
	TRACER("CGlxThumbnailComposerPlugin::RequestItemL");
    if ( iLastError == KErrCancel )
        {
        iInactivityTimer->Inactivity(KGlxThumbnailComposerInactivityTimeout);
        }
    else if ( iLastError == 1 )
        {
        iInactivityTimer->After(KGlxThumbnailComposerHarvestDelay);
        }
    else
        {
        iInactivityTimer->After(KGlxThumbnailComposerDelay);
        }
    iLastError = KErrNone;
    }
    
// ---------------------------------------------------------------------------
// DoRequestItemL
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::DoRequestItemL()
    {
	TRACER("CGlxThumbnailComposerPlugin::DoRequestItemL");

    if ( iPath && iCurrentIndex < iPath->Count() )
        {
        GLX_ASSERT_ALWAYS( iCollectionUtility, Panic( EGlxPanicNullPointer ),
                            "No collection utility" );
        // request next item
    	iPath->Set( iCurrentIndex );

        RArray<TMPXAttribute> attrs;
        CleanupClosePushL( attrs );
        // Add thumbnail attribute
        attrs.AppendL( TMPXAttribute(
                KGlxMediaIdThumbnail, KGlxBackgroundThumbnailAttributeId ) );

        // Don't add spec for bitmap handle, to request background thumbnail
        CMPXAttributeSpecs* attrSpecs = NULL;
        
        // Start first task
        iCollectionUtility->Collection().MediaL(
                                    *iPath, attrs.Array(), attrSpecs );
        CleanupStack::PopAndDestroy( &attrs );
        }
    else
        {
        delete iPath;
        iPath = NULL;
        
        if ( iState == EStateActiveLarge )
            {
            // go on to do small thumbnails
            DoOpenCollectionL();
            }
        else
            {
            CMPXCommand* command
                            = TGlxCommandFactory::ThumbnailCleanupCommandLC();
            iCollectionUtility->Collection().CommandL( *command );
            CleanupStack::PopAndDestroy( command );

            iState = EStateCleanup;
            }
        }
    }

// ---------------------------------------------------------------------------
// ReturnToIdle
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::ReturnToIdle()
    {
	TRACER("CGlxThumbnailComposerPlugin::ReturnToIdle");
    iState = EStateClosing;
    iInactivityTimer->After(KGlxThumbnailComposerLargeDelay);
    }

// ---------------------------------------------------------------------------
// DelayDisplayStateCheck
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::DelayDisplayStateCheck()
    {
	TRACER("CGlxThumbnailComposerPlugin::DelayDisplayStateCheck");
    iInactivityTimer->After(KGlxDisplayStatusTimeOutDelay);	
    }

// ---------------------------------------------------------------------------
// CloseCollection
// ---------------------------------------------------------------------------
//
void CGlxThumbnailComposerPlugin::CloseCollection()
    {
	TRACER("CGlxThumbnailComposerPlugin::CloseCollection");
    if ( ( EStateClosing == iState ) && iCollectionUtility )
        {
        iCollectionUtility->Close();
        iCollectionUtility = NULL;
        iState = EStateIdle;
        }
    }