--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/photosgallery/collectionframework/thumbnailcreator/thumbnailcomposerplugin/glxthumbnailcomposerplugin.cpp Thu Dec 17 08:45:44 2009 +0200
@@ -0,0 +1,684 @@
+/*
+* 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 ; //( iState == EStateIdle );
+ }
+
+#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;
+ }
+ }