photosgallery/slideshow/engine/coresrc/shwthumbnailloader.cpp
changeset 0 4e91876724a2
child 16 0bc0ea26031e
child 18 bcb43dc84c44
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/photosgallery/slideshow/engine/coresrc/shwthumbnailloader.cpp	Thu Dec 17 08:45:44 2009 +0200
@@ -0,0 +1,813 @@
+/*
+* Copyright (c) 2007-2008 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:    Utility that contains HUI related slideshow code
+ *
+*/
+
+
+
+
+// INCLUDES
+#include "shwthumbnailloader.h"
+
+// DEPENDENCIES
+#include <mpxattributespecs.h>
+#include <mpxmediadrmdefs.h>
+#include <glxlog.h>
+#include <glxtracer.h>
+
+#include <glxmedialistiterator.h>
+#include <mglxmedialistobserver.h>
+#include <mglxmedialist.h>
+#include <glxthumbnailcontext.h>
+#include <glxattributecontext.h>
+#include <glxmediageneraldefs.h>
+#include <glxattributeretriever.h>
+
+#include "shwslideshowenginepanic.h"
+#include "shwthumbnailcontext.h"
+#include "shwcallback.h"
+
+#include "shwconstants.h"   // for context priorities
+
+using namespace NShwSlideshow;
+
+/**
+ * CShwThumbnailLoaderImpl
+ * Implementation dependencies for the thumbnail loading
+ */
+NONSHARABLE_CLASS( CShwThumbnailLoader::CShwThumbnailLoaderImpl )
+	: public CBase,
+	public MGlxMediaListObserver
+	{
+	public:
+
+		/**
+		 * Constructor
+		 * inlined as only ever called inside this cpp
+		 * @param aMedialist the media list
+		 */
+		inline CShwThumbnailLoaderImpl( 
+			MGlxMediaList& aMedialist, 
+			MShwThumbnailLoadObserver& aErrorHandler );
+
+		/**
+		 * Destructor. 
+		 * inlined as only ever called inside this cpp
+		 */
+		inline ~CShwThumbnailLoaderImpl();
+
+		/**
+		 * 2nd phase constructor
+		 * inlined as only ever called inside this cpp
+		 */
+		inline void ConstructL();
+		
+		/** 
+		 * @ref CShwThumbnailLoader::LoadAndNotifyL
+		 * inlined as only ever called inside this cpp
+		 */
+		inline void LoadAndNotifyL( TInt aIndex, TSize aSize );
+
+		/** 
+		 * @ref CShwThumbnailLoader::Unload
+		 * inlined as only ever called inside this cpp
+		 */
+		inline void Unload( TInt aIndex );
+
+		/** 
+		 * @ref CShwThumbnailLoader::ImageSizeL
+		 * inlined as only ever called inside this cpp
+		 */
+		inline TSize ImageSizeL( TInt aIndex );
+
+	public: // from MGlxMediaListObserver
+
+		/// @ref MGlxMediaListObserver::HandleItemAddedL
+		void HandleItemAddedL( 
+			TInt aStartIndex, TInt aEndIndex, MGlxMediaList* aList );
+		/// @ref MGlxMediaListObserver::HandleMediaL
+		void HandleMediaL( 
+			TInt aListIndex, MGlxMediaList* aList );
+		/// @ref MGlxMediaListObserver::HandleItemRemovedL
+		void HandleItemRemovedL( 
+			TInt aStartIndex, TInt aEndIndex, MGlxMediaList* aList );
+		/// @ref MGlxMediaListObserver::HandleItemModifiedL
+		void HandleItemModifiedL( 
+			const RArray<TInt>& aItemIndexes, MGlxMediaList* aList );	
+		/// @ref MGlxMediaListObserver::HandleAttributesAvailableL
+		void HandleAttributesAvailableL(
+			TInt aItemIndex, 
+			const RArray<TMPXAttribute>& aAttributes, 
+			MGlxMediaList* aList );
+		/// @ref MGlxMediaListObserver::HandleFocusChangedL
+		void HandleFocusChangedL( 
+			NGlxListDefs::TFocusChangeType aType, 
+			TInt aNewIndex, 
+			TInt aOldIndex, 
+			MGlxMediaList* aList );
+		/// @ref MGlxMediaListObserver::HandleItemSelectedL
+		void HandleItemSelectedL( 
+			TInt aIndex, TBool aSelected, MGlxMediaList* aList );
+		/// @ref MGlxMediaListObserver::HandleMessageL
+		void HandleMessageL( 
+			const CMPXMessage& aMessage, MGlxMediaList* aList );
+		/// @ref MGlxMediaListObserver::HandleError
+		void HandleError( TInt aError );
+
+	private: // Implementation
+
+        // implementation of the error handler
+        inline void DoHandleErrorL();
+		// Helper functions to find an element in the array given an index
+		// used in three places, load, unload and handleattributes available
+		// @param the index of the element to find
+		// @return the index of the element in the array, KErrNotFound otherwise
+		inline TInt Find( TInt aIndex );		
+		// @return the context if found, NULL otherwise
+		inline CShwThumbnailContext* FindContext( TInt aIndex );
+		// Helper function to create the size context
+		inline void AddSizeContextL();
+        /// Helper function to notify client of successfull or failed thumbnail load
+        inline void NofifyClientIfInterestedL( TInt aIndex, TBool aSuccess );
+		// Helper function to remove high quality context from given index
+		inline void RemoveHighQualityContext( TInt aIndex );
+
+	public: // TCallBack API
+
+		// Helper function to notify thumbnail completion asynchronously
+		inline TInt CompletedNotifyL();
+		// Helper function to notify thumbnail failure asynchronously
+		inline TInt ErrorNotifyL();
+		// Helper function to handle the error
+		inline TInt AsyncErrorHandleL();
+
+	private:	// Implementation & Data
+
+		/// Ref: the media list
+		MGlxMediaList& iMedialist;
+		/// Ref: the error handler
+		MShwThumbnailLoadObserver& iThumbnailObserver;
+		/// Own: the array for the thumbnail notifications
+		RArray< TInt > iNotificationIndexes;
+		/// Own: the array for already completed indexes
+		RArray< TInt > iCompletedIndexes;
+		/// Own: the array for already faulty indexes
+		RArray< TInt > iErrorIndexes;
+		/// Own: the array of high quality contexts
+		RPointerArray< CShwThumbnailContext > iHighQualityContexts;
+		/// Own: the size context
+		CGlxDefaultAttributeContext* iSizeContext;
+		/// Own: async callback needed in case image is already loaded
+		CAsyncCallBack* iCompletedCallBack;
+		/// Own: async callback needed in case image had already an error
+		CAsyncCallBack* iErrorCallBack;
+		/// Own: async callback for showing the out of memory system dialog
+		CAsyncCallBack* iErrorHandlerCallBack;
+		/// Own: the error code
+		TInt iError;
+
+	};
+
+// -----------------------------------------------------------------------------
+// C++ Constructor. Save a few bits of rom with inlining
+// -----------------------------------------------------------------------------
+inline CShwThumbnailLoader::CShwThumbnailLoader()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// NewL. Static construction
+// -----------------------------------------------------------------------------
+CShwThumbnailLoader* CShwThumbnailLoader::NewL(
+	MGlxMediaList& aMedialist, MShwThumbnailLoadObserver& aErrorHandler )
+	{
+	TRACER("CShwThumbnailLoader::NewLs");
+	GLX_LOG_INFO( "CShwThumbnailLoader::NewL" );
+	CShwThumbnailLoader* self = new( ELeave ) CShwThumbnailLoader;
+	CleanupStack::PushL( self );
+
+// 2nd phase >>
+	// create implementation
+	self->iImpl = 
+		new( ELeave ) CShwThumbnailLoaderImpl( aMedialist, aErrorHandler );
+	// call 2nd phase
+	self->iImpl->ConstructL();
+// << 2nd phase
+
+	// pop the stack
+	CleanupStack::Pop( self );
+	return self;
+	}
+
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+CShwThumbnailLoader::~CShwThumbnailLoader()
+	{
+	TRACER("CShwThumbnailLoader::~CShwThumbnailLoader");
+	GLX_LOG_INFO( "CShwThumbnailLoader::~CShwThumbnailLoader" );
+	delete iImpl;
+	}
+
+// -----------------------------------------------------------------------------
+// LoadThumbnailAndNotifyL.
+// -----------------------------------------------------------------------------
+void CShwThumbnailLoader::LoadAndNotifyL( TInt aIndex, TSize aSize )
+	{
+	TRACER("CShwThumbnailLoader::LoadAndNotifyL");
+	GLX_LOG_INFO( "CShwThumbnailLoader::LoadAndNotifyL" );
+	// forward
+	iImpl->LoadAndNotifyL( aIndex, aSize );
+	}
+
+// -----------------------------------------------------------------------------
+// Unload.
+// -----------------------------------------------------------------------------
+void CShwThumbnailLoader::Unload( TInt aIndex )
+	{
+	TRACER("CShwThumbnailLoader::Unload");
+	GLX_LOG_INFO( "CShwThumbnailLoader::Unload" );
+	// forward
+	iImpl->Unload( aIndex );
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::ImageSizeL.
+// -----------------------------------------------------------------------------
+TSize CShwThumbnailLoader::ImageSizeL( TInt aIndex )
+	{
+	TRACER("CShwThumbnailLoader::ImageSizeL");
+	GLX_LOG_INFO( "CShwThumbnailLoader::ImageSizeL" );
+	// forward
+	return iImpl->ImageSizeL( aIndex );
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::C++ Constructor. Save a few bits of rom with inlining
+// -----------------------------------------------------------------------------
+inline CShwThumbnailLoader::CShwThumbnailLoaderImpl::CShwThumbnailLoaderImpl(
+	MGlxMediaList& aMedialist, MShwThumbnailLoadObserver& aErrorHandler )
+	: iMedialist( aMedialist ),
+	iThumbnailObserver( aErrorHandler )
+	{
+	TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::CShwThumbnailLoaderImpl()");
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::Destructor.
+// -----------------------------------------------------------------------------
+inline CShwThumbnailLoader::CShwThumbnailLoaderImpl::~CShwThumbnailLoaderImpl()
+    {
+    TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::~CShwThumbnailLoaderImpl()");
+    GLX_LOG_INFO( "CShwThumbnailLoaderImpl::~CShwThumbnailLoaderImpl" );
+    // delete asynch callbacks, delete also cancels them
+    delete iCompletedCallBack;
+    delete iErrorCallBack;
+    delete iErrorHandlerCallBack;
+
+    // size context, remove NULL does nothing
+    iMedialist.RemoveContext( iSizeContext );
+    delete iSizeContext;
+
+    // Remove all contexts from the media list
+    TInt count = iHighQualityContexts.Count();
+    while ( count-- > 0 )
+        {
+        // get the fetch context so that we can remove it from the media list
+        MGlxFetchContext* context = iHighQualityContexts[ count ]->Context();
+        // high quality context, remove NULL does nothing
+        iMedialist.RemoveContext( context );
+        };
+    // delete the contexts array, this deletes the CShwThumbnailContexts
+    iHighQualityContexts.ResetAndDestroy();
+
+    // remove us from media list observers
+    iMedialist.RemoveMediaListObserver( this );
+
+    // close notification indexes array
+    iNotificationIndexes.Close();
+    // close also the already completed indexes array
+    iCompletedIndexes.Close();
+    // close also the errornous indexes array
+    iErrorIndexes.Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::ConstructL
+// -----------------------------------------------------------------------------
+inline void CShwThumbnailLoader::CShwThumbnailLoaderImpl::ConstructL()
+    {
+    TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::ConstructL");
+    GLX_LOG_INFO( "CShwThumbnailLoader::CShwThumbnailLoaderImpl::ConstructL" );
+    // retrieve the size of images with own context
+    AddSizeContextL();
+
+    // add us as media list observer
+    iMedialist.AddMediaListObserverL( this );
+
+    // create async callback object to give 
+    // callbacks once scheduler runs, give this high priority so that it 
+    // is faster than the timers we have
+    iCompletedCallBack = new( ELeave ) CAsyncCallBack( CActive::EPriorityHigh );
+    // set the callback
+    iCompletedCallBack->Set( 
+        TShwCallBack< CShwThumbnailLoaderImpl, CompletedNotifyL >( this ) );
+
+    // create async callback to give error callbacks once scheduler runs
+    iErrorCallBack = new( ELeave ) CAsyncCallBack( CActive::EPriorityHigh );
+    // set the callback
+    iErrorCallBack->Set( 
+        TShwCallBack< CShwThumbnailLoaderImpl, ErrorNotifyL >( this ) );
+        
+    // create async callback to give callback once we run onto errors
+    iErrorHandlerCallBack = new( ELeave ) CAsyncCallBack( CActive::EPriorityHigh );
+    // set the callback
+    iErrorHandlerCallBack->Set( 
+        TShwCallBack< CShwThumbnailLoaderImpl, AsyncErrorHandleL >( this ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::ImageSizeL.
+// -----------------------------------------------------------------------------
+inline TSize CShwThumbnailLoader::CShwThumbnailLoaderImpl::ImageSizeL( 
+	TInt aIndex )
+    {
+    TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::ImageSizeL");
+    GLX_LOG_INFO1( "CShwThumbnailLoader::ImageSizeL for index %d", aIndex );
+
+	// default to KErrNotFound
+	TSize size( KErrNotFound, KErrNotFound );
+
+    // get the media item
+    TGlxMedia item = iMedialist.Item( aIndex );
+    // get its dimensions, if they are not available, size is not modified
+    // if size is not available, GetDimensions returns EFalse
+    if( !item.GetDimensions( size ) )
+        {
+        // size was not available so try to fetch it with attribute retriever
+        (void)GlxAttributeRetriever::RetrieveL(
+            *iSizeContext, iMedialist, 
+            EFalse /*aShowDialog*/ );
+        // get the media item again since its just a copy and the old one
+        // might not have had the CGlxMedia* set
+        item = iMedialist.Item( aIndex );
+        // cast to (void) tells the compiler we ignore
+        // the fetcher error as there is nothing to do if the fetch fails
+        // in that case the size will be (KErrNotFound,KErrNotFound)
+        // try getting the dimensions again
+        (void)item.GetDimensions( size );
+        }
+
+    GLX_LOG_INFO2( 
+        "CShwThumbnailLoader::ImageSizeL (%d,%d)", size.iWidth, size.iHeight );
+
+    return size;
+    }
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::LoadAndNotifyL.
+// -----------------------------------------------------------------------------
+inline void CShwThumbnailLoader::CShwThumbnailLoaderImpl::LoadAndNotifyL( 
+	TInt aIndex, TSize aSize )
+	{
+	TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::LoadAndNotifyL");
+	GLX_LOG_INFO1( "CShwThumbnailLoader::LoadAndNotifyL %d", aIndex );
+
+	// check whether a context already exists for this index
+	CShwThumbnailContext* context = FindContext( aIndex );
+	if( !context )
+		{
+		// create new context for the index with the given size
+		context = CShwThumbnailContext::NewLC( aIndex, aSize );
+		iHighQualityContexts.AppendL( context );
+		CleanupStack::Pop( context );
+		// add the context to the medialist with priority
+		iMedialist.AddContextL( 
+			context->Context(), KHighQualityContextPriority );
+		}
+
+    // add the index to notifications array so that we know to give 
+    // either success or error notification once for the request
+	// Note that we can have multiple requests for same index
+	iNotificationIndexes.InsertInOrderAllowRepeatsL( aIndex );
+
+	// need to check if the thumbnail is already loaded
+	// when request count is zero (KErrNone) the thumbnail is fully loaded
+	TInt requestCount = context->RequestCountL( &iMedialist );
+	if( requestCount == KErrNone )
+		{
+		// thumbnail is already there
+		// we cant give the callback right away as the client is expecting
+		// this method to be always asynchronous
+		GLX_LOG_INFO1( 
+			"CShwThumbnailLoader::Thumbnail already loaded %d", aIndex );
+    	// insert index to completed array
+    	// Note that we can have multiple requests for same index
+    	iCompletedIndexes.InsertInOrderAllowRepeatsL( aIndex );
+		// cancel the old callback
+		iCompletedCallBack->Cancel();
+		// make the callback
+		iCompletedCallBack->CallBack();
+		}
+	else if ( requestCount < KErrNone )
+		{
+		// thumbnail had already and error
+		GLX_LOG_INFO2( 
+			"CShwThumbnailLoader::Thumbnail error %d at index, %d", 
+			    requestCount, aIndex );
+		// we cant give the callback right away as the client is expecting
+		// this method to be always asynchronous
+    	// Note that we can have multiple requests for same index
+    	iErrorIndexes.InsertInOrderAllowRepeatsL( aIndex );
+		// cancel the old callback
+		iErrorCallBack->Cancel();
+		// make the callback
+		iErrorCallBack->CallBack();
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::Unload
+// -----------------------------------------------------------------------------
+inline void CShwThumbnailLoader::CShwThumbnailLoaderImpl::Unload( TInt aIndex )
+	{
+	TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::Unload");
+	GLX_LOG_INFO1( "CShwThumbnailLoader::Unload %d", aIndex );
+    
+    // client is no longer interested on this indes so remove it from the
+    // notifications
+	TInt index;
+	while( ( index = iNotificationIndexes.Find( aIndex ) ) != KErrNotFound )
+		{
+		// remove the index from array
+		iNotificationIndexes.Remove( index );
+		}
+
+    // remove context for this index
+    RemoveHighQualityContext( aIndex );
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::HandleItemAddedL.
+// -----------------------------------------------------------------------------
+void CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleItemAddedL(
+	TInt /*aStartIndex*/, TInt /*aEndIndex*/, MGlxMediaList* /*aList*/ )
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::HandleMediaL.
+// -----------------------------------------------------------------------------
+void CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleMediaL(
+	TInt /*aListIndex*/, MGlxMediaList* /*aList*/ )
+	{
+	}
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::HandleItemRemovedL.
+// -----------------------------------------------------------------------------
+void CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleItemRemovedL(
+	TInt /*aStartIndex*/, TInt /*aEndIndex*/, MGlxMediaList* /*aList*/ )
+	{
+	TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleItemRemovedL");
+	GLX_LOG_INFO( "CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleItemRemovedL" );
+	// check if we still got some items to show
+	if( iMedialist.Count() < 1 )
+	    {
+		// the media list is empty so call our error handler
+		iThumbnailObserver.HandleMediaListEmpty();
+	    }
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::HandleItemModifiedL.
+// -----------------------------------------------------------------------------
+void CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleItemModifiedL( 
+	const RArray<TInt>& /*aItemIndexes*/, MGlxMediaList* /*aList*/ )
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::HandleAttributesAvailableL.
+// -----------------------------------------------------------------------------
+void CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleAttributesAvailableL(
+	TInt aItemIndex, const RArray<TMPXAttribute>& aAttributes/**/, 
+	MGlxMediaList* /*aList*/ )
+	{
+	TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleAttributesAvailableL");
+	GLX_LOG_INFO( "CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleAttributesAvailableL" );
+	//done to verify context availability
+	TInt attributeCount = aAttributes.Count();
+	for(TInt i = 0; i < attributeCount; i++ )
+		{
+		TMPXAttribute attr = aAttributes[i];	
+		}
+		
+	GLX_LOG_INFO1( 
+	    "CShwThumbnailLoader::HandleAttributesAvailableL %d", aItemIndex );
+	// check if the thumbnail was fully loaded, first find the related context
+	CShwThumbnailContext* context = FindContext( aItemIndex );
+	if( context )
+		{
+		// was there an error?
+		TInt requestCount = context->RequestCountL( &iMedialist );
+		if ( requestCount == KErrNone )
+			{
+			// no error, notify client
+			GLX_LOG_INFO1( 
+				"CShwThumbnailLoader::Thumbnail loaded %d", aItemIndex );
+			// notidy client of success if it is interested on this index
+			NofifyClientIfInterestedL( aItemIndex, ETrue );
+			}
+		else if ( requestCount < 0 )
+			{
+			GLX_LOG_INFO1( 
+				"CShwThumbnailLoader::Thumbnail load failed %d", aItemIndex );
+    		// remove the context since there is an error in loading it
+    		// need to remove first as error handler may add new contexts
+    		RemoveHighQualityContext( aItemIndex );
+			// notidy client of error if it is interested on this index
+			NofifyClientIfInterestedL( aItemIndex, EFalse );
+			}
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::HandleFocusChangedL.
+// -----------------------------------------------------------------------------
+void CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleFocusChangedL(
+	NGlxListDefs::TFocusChangeType /*aType*/, TInt /*aNewIndex*/, 
+	TInt /*aOldIndex*/, MGlxMediaList* /*aList*/ )
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::HandleItemSelectedL.
+// -----------------------------------------------------------------------------
+void CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleItemSelectedL(
+	TInt /*aIndex*/, TBool /*aSelected*/, MGlxMediaList* /*aList*/ )
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::HandleMessageL.
+// -----------------------------------------------------------------------------
+void CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleMessageL(
+	const CMPXMessage& /*aMessage*/, MGlxMediaList* /*aList*/ )
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::HandleError.
+// -----------------------------------------------------------------------------
+void CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleError(
+    TInt aError )
+	{
+	TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleError");
+	GLX_LOG_INFO1( "CShwThumbnailLoader::CShwThumbnailLoaderImpl::HandleError %d", aError );
+	// need to remember the error
+	iError = aError;
+	// make asynch callback since we cant leave, this is the perfect way to 
+	// handle error as the real processing will be in RunL so it can leave and
+	// can show a system error note. It is safe to call CallBack even is previous
+	// one did not complete
+    iErrorHandlerCallBack->CallBack();
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::DoHandleErrorL.
+// -----------------------------------------------------------------------------
+void CShwThumbnailLoader::CShwThumbnailLoaderImpl::DoHandleErrorL()
+	{
+	TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::DoHandleErrorL");
+	GLX_LOG_INFO1( "CShwThumbnailLoader::DoHandleError %d", iError );
+	// variable to tell if the error was in some of our fetch contexts
+	TBool errorInHighQualityContexts = EFalse;
+	// check if it was any of our high quality fetch contexts 
+	TInt count = iHighQualityContexts.Count();
+	// ask all high quality contexts
+	while ( count-- > 0 )
+		{
+		CShwThumbnailContext* context = iHighQualityContexts[ count ];
+		// need to TRAP in case RequestCountL leaves, since if it does
+		// we need to tell our observer that there is a problem
+		// requestCount needs to be volatile so that it does get
+		// optimized to a register and get its initial value returned in leave
+		volatile TInt requestCount = KErrNone;
+		TRAPD( error, requestCount = context->RequestCountL( &iMedialist ) );
+		// ask if this context had an error or RequestCountL did leave
+		if( ( requestCount < KErrNone )|| 
+		    ( error != KErrNone ) )
+			{
+			// take the index as cant use context once it is removed
+			TInt index = context->Index();
+			// remove the context since there is an error in loading it
+    		// need to remove first as error handler may add new contexts
+			RemoveHighQualityContext( index );
+			// notidy client of error if it is interested on this index
+			NofifyClientIfInterestedL( index, EFalse );
+			// set the flag to tell that there was an error in context
+			errorInHighQualityContexts = ETrue;
+			}
+		}
+	// check if it was out of memory and in our contexts
+	if( KErrNoMemory == iError && errorInHighQualityContexts )
+	    {
+    	// just leave with KErrNoMemory, system will then show the dialog
+    	User::Leave( KErrNoMemory );
+	    }
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::Find.
+// -----------------------------------------------------------------------------
+inline TInt CShwThumbnailLoader::CShwThumbnailLoaderImpl::Find( TInt aIndex )
+	{
+	TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::Find");
+	GLX_LOG_INFO1( "CShwThumbnailLoader::Find %d", aIndex );
+	// take the count
+	TInt index = iHighQualityContexts.Count();
+	// browse through all indexes ( count-1 -> 0 )
+	while ( index-- > 0 )
+		{
+		// does the index belong to the array?
+		CShwThumbnailContext* context = iHighQualityContexts[ index ];
+		if ( context->Index() == aIndex )
+			{
+			break;
+			}
+		}
+	// if match was not found, index is -1 which is KErrNotFound
+	return index;
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::FindContext.
+// -----------------------------------------------------------------------------
+inline CShwThumbnailContext* 
+	CShwThumbnailLoader::CShwThumbnailLoaderImpl::FindContext( TInt aIndex )
+	{
+	TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::FindContext");
+	GLX_LOG_INFO1( "CShwThumbnailLoader::FindContext %d", aIndex );
+	// by default return NULL
+	CShwThumbnailContext* context = NULL;
+	// reuse the Find
+	TInt index = Find( aIndex );
+	// if it was found
+	if( index != KErrNotFound )
+		{
+		// set the context
+		context = iHighQualityContexts[ index ];
+		}
+	// and return it
+	return context;
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::AddSizeContextL
+// -----------------------------------------------------------------------------
+inline void CShwThumbnailLoader::CShwThumbnailLoaderImpl::AddSizeContextL()
+	{
+	TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::AddSizeContextL");
+	GLX_LOG_INFO( "CShwThumbnailLoader::FindContext ");
+	// Create the fetch context to retrieve the attribute
+	iSizeContext = CGlxDefaultAttributeContext::NewL();
+    // Set the range offsets relative to the focus item
+    // e.g. 0, 1, [2], 3, 4. Focus @ 2 => frontOffset = 2, rearOffset = 2
+	iSizeContext->SetRangeOffsets( KSizeContextOffset, KSizeContextOffset );
+
+	// Add the size attribute to the context
+	iSizeContext->AddAttributeL( KGlxMediaGeneralDimensions );
+
+    // Add Drm attribute to the context, 
+	// By default Drm attrib would be ETrue if not fetched already and 
+	// shall result in reduced thumbnail size request
+	iSizeContext->AddAttributeL(KMPXMediaDrmProtected);
+
+	// add the context with its priority
+	iMedialist.AddContextL( iSizeContext, KSizeContextPriority );
+	}
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::NofifyClientIfInterestedL.
+// -----------------------------------------------------------------------------
+void CShwThumbnailLoader::CShwThumbnailLoaderImpl::NofifyClientIfInterestedL(
+    TInt aIndex, TBool aSuccess )
+    {
+    TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::NofifyClientIfInterestedL");
+    GLX_LOG_INFO1( "CShwThumbnailLoaderImpl::NofifyClientIfInterestedL %d", aIndex );
+	// go through all the notification indexes
+	TInt arrayIndex = iNotificationIndexes.Find( aIndex );
+	if( KErrNotFound != arrayIndex )
+	    {
+	    // need to remove the index first as handle may insert new ones
+		// remove the index from array so we dont call twice
+		iNotificationIndexes.Remove( arrayIndex );
+		if( aSuccess )
+		    {
+    	    // let the client know that the thumbnail is there
+    	    iThumbnailObserver.HandleThumbnailLoadedL( aIndex );
+		    }
+		else
+		    {
+    	    // let the client know that there was an error
+    	    iThumbnailObserver.HandleThumbnailLoadFailureL( aIndex );
+		    }
+	    }
+    }
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::RemoveHighQualityContext
+// -----------------------------------------------------------------------------
+inline void CShwThumbnailLoader::CShwThumbnailLoaderImpl::
+    RemoveHighQualityContext( TInt aIndex )
+    {
+    TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::RemoveHighQualityContext");
+    GLX_LOG_INFO1( "CShwThumbnailLoaderImpl::RemoveHighQualityContext %d", aIndex );
+	// Is there a context for this index?
+	TInt arrayIndex = Find( aIndex );
+	if( KErrNotFound != arrayIndex )
+		{
+		// get the context
+		CShwThumbnailContext* context = iHighQualityContexts[ arrayIndex ];
+		// remove the context from the media list
+		iMedialist.RemoveContext( context->Context() );
+		// and remove the context from the array
+		iHighQualityContexts.Remove( arrayIndex );
+		// finally delete the context
+		delete context;
+		}
+    }
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::CompletedNotifyL
+// -----------------------------------------------------------------------------
+inline TInt CShwThumbnailLoader::CShwThumbnailLoaderImpl::CompletedNotifyL()
+    {
+    TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::CompletedNotifyL");
+	GLX_LOG_INFO( "CShwThumbnailLoader::CompletedNotifyL" );
+    // then we need to also remove all notifications for the given index
+    TInt count = iCompletedIndexes.Count();
+    while( count-- > 0 )
+        {
+        // take the index
+        TInt index = iCompletedIndexes[ count ];
+        // remove the index from array before calling observer as observer
+        // may add new indexes to the array
+        iCompletedIndexes.Remove( count );
+		// notidy client of success if it is interested on this index
+		NofifyClientIfInterestedL( index, ETrue );
+        }
+    // need to return value to please TCallBack API
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::ErrorNotifyL
+// -----------------------------------------------------------------------------
+inline TInt CShwThumbnailLoader::CShwThumbnailLoaderImpl::ErrorNotifyL()
+    {
+    TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::ErrorNotifyL");
+	GLX_LOG_INFO( "CShwThumbnailLoader::ErrorNotifyL" );
+    // then we need to also remove all notifications for the given index
+    TInt count = iErrorIndexes.Count();
+    while( count-- > 0 )
+        {
+        // take the index
+        TInt index = iErrorIndexes[ count ];
+        // remove the index from array before calling observer as observer
+        // may add new indexes to the array
+        iErrorIndexes.Remove( count );
+		// remove the context since there is an error in loading it
+		// need to remove first as error handler may add new contexts
+		RemoveHighQualityContext( index );
+		// notidy client of error if it is interested on this index
+		NofifyClientIfInterestedL( index, EFalse );
+        }
+    // need to return value to please TCallBack API
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CShwThumbnailLoaderImpl::AsyncErrorHandleL
+// -----------------------------------------------------------------------------
+inline TInt CShwThumbnailLoader::CShwThumbnailLoaderImpl::AsyncErrorHandleL()
+    {
+    TRACER("CShwThumbnailLoader::CShwThumbnailLoaderImpl::AsyncErrorHandleL");
+	GLX_LOG_INFO( "CShwThumbnailLoader::AsyncErrorHandleL" );
+    // handle the error
+	DoHandleErrorL();
+    // need to return value to please TCallBack API
+    return KErrNone;
+    }