Revision: 201013 RCL_3
authorDremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 14 Apr 2010 17:32:53 +0300
branchRCL_3
changeset 12 b74061f7f3d2
parent 11 d5f04de580b7
child 14 cd271b19d824
Revision: 201013 Kit: 201015
devsound/a3fdevsound/bwins/mmfdevsoundadaptor.def
devsound/a3fdevsound/eabi/mmfdevsoundadaptor.def
devsound/a3fdevsound/src/devsoundadaptor/cdevaudio.cpp
devsound/a3fdevsound/src/devsoundadaptor/cdevaudio.h
devsound/a3fdevsound/src/devsoundadaptor/cdevaudiocontrol.cpp
devsound/a3fdevsound/src/devsoundadaptor/cdevaudiocontrol.h
devsound/a3fdevsound/src/devsoundadaptor/cdevcommoncontrol.cpp
devsound/a3fdevsound/src/devsoundadaptor/cdevcommoncontrol.h
devsound/a3fdevsound/src/devsoundadaptor/cdevplaycontrol.cpp
devsound/a3fdevsound/src/devsoundadaptor/cdevrecordcontrol.cpp
devsound/a3fdevsound/src/devsoundadaptor/cdevtonecontrol.cpp
devsound/a3fdevsound/src/devsoundadaptor/mmfdevsoundadaptation.cpp
devsound/a3fdevsound/src/devsoundadaptor/mmfdevsoundadaptation.h
devsound/a3fdevsound/src/devsoundadaptor/mmfdevsoundadaptationbody.cpp
devsound/a3fdevsound/src/devsoundadaptor/mmfdevsoundadaptationbody.h
devsound/a3fdevsound/src/mmfdevsoundserver/mmfdevsoundsession.cpp
devsound/a3fdevsound/src/mmfdevsoundserver/mmfdevsoundsession.h
devsoundextensions/effects/Loudness/LoudnessEffect/Src/LoudnessBase.cpp
devsoundextensions/effectspresets/rom/EffectsPresets.iby
imagingandcamerafws/imagingunittest/TSU_ICL_COD_03/scripts/TSU_ICL_COD_03.script
imagingandcamerafws/imagingunittest/TSU_ICL_COD_03/src/ICLCodecDefectTestStep.cpp
imagingandcamerafws/imagingunittest/TSU_ICL_COD_03/src/ICLCodecDefectTestStep.h
imagingandcamerafws/imagingunittest/TSU_ICL_COD_03/src/ICLCodecDefectTestSuite.cpp
mdfdevvideoextensions/nga_mdf_postprocessor/data/nga_mdf_postprocessor_stub.pkg
mdfdevvideoextensions/nga_mdf_postprocessor/data/nga_mdf_postprocessor_stub.sis
mdfdevvideoextensions/nga_mdf_postprocessor/inc/NGAPostProcHwDevice.h
mdfdevvideoextensions/nga_mdf_postprocessor/src/NGAPostProcHwDevice.cpp
mm_pub/drm_audio_player_api/tsrc/data/mmc/drm/test3gp.dcf
mm_pub/drm_audio_player_api/tsrc/data/mmc/drm/testmp3.dcf
mmlibs/mmfw/MMPFiles/client/MediaClientVideo.mmp
mmlibs/mmfw/MMPFiles/client/mediaclientvideodisplay.mmp
mmlibs/mmfw/src/Client/Video/VideoPlayerBody.h
mmlibs/mmfw/src/Client/Video/mediaclientvideodisplaybody.cpp
mmlibs/mmfw/src/Client/Video/mediaclientvideodisplaybody.h
mmlibs/mmfw/src/Client/Video/mediaclientvideotrace.h
mmlibs/mmfw/src/Client/Video/mmfclientvideoplayerbody.cpp
mmlibs/mmfw/tsrc/mmfintegrationtest/vclntavi/src/testvideoplayer2.cpp
mmlibs/mmfw/tsrc/mmfunittest/DevSoundTest/a3fcistubextn/a3fcistubextn.cpp
mmlibs/mmfw/tsrc/mmfunittest/DevSoundTest/a3fcistubextn/a3fcistubextn.h
mmlibs/mmfw/tsrc/mmfunittest/DevSoundTest/a3fcistubextn/testsetvol.h
mmlibs/mmfw/tsrc/mmfunittest/DevSoundTest/src/TSU_MMF_DEVSOUND_STEP.cpp
mmplugins/imagingplugins/codecs/TIFFCodec/TIFFCodec.cpp
mmplugins/mmfwplugins/src/Plugin/Format/MmfWAVFormat/mmfwavformat.cpp
mmtestenv/mmtestfw/MMPFiles/TestFrameworkClient.mmp
mmtestenv/mmtestfw/Source/TestFrameworkClient/Log.cpp
mmtestenv/mmtestfw/Source/TestFrameworkClient/TestStep.cpp
mmtestenv/mmtestfw/Source/TestFrameworkClient/testfwclientsession.cpp
mmtestenv/mmtestfw/bwins/TESTFRAMEWORKCLIENTU.DEF
mmtestenv/mmtestfw/eabi/TestFrameworkClientU.DEF
mmtestenv/mmtestfw/include/TestFramework.h
mmtestenv/mmtestfwunittest/MMPFiles/TSU_MmTsth10.mmp
mmtestenv/mmtestfwunittest/MMPFiles/TSU_MmTsth11.mmp
mmtestenv/mmtestfwunittest/MMPFiles/TSU_MmTsth12.mmp
mmtestenv/mmtestfwunittest/MMPFiles/TSU_MmTsth13.mmp
mmtestenv/mmtestfwunittest/eabi/TSU_MmTsth10U.DEF
mmtestenv/mmtestfwunittest/eabi/TSU_MmTsth11U.DEF
mmtestenv/mmtestfwunittest/eabi/TSU_MmTsth12U.DEF
omxil/omxilcore/src/omxilcoreclient/omxilcoreclientsession.cpp
--- a/devsound/a3fdevsound/bwins/mmfdevsoundadaptor.def	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/bwins/mmfdevsoundadaptor.def	Wed Apr 14 17:32:53 2010 +0300
@@ -55,4 +55,5 @@
 	?Resume@CMMFDevSoundAdaptation@@QAEHXZ @ 54 NONAME ; int CMMFDevSoundAdaptation::Resume(void)
 	?BufferErrorEvent@CMMFDevSoundAdaptation@@QAEXXZ @ 55 NONAME ; void CMMFDevSoundAdaptation::BufferErrorEvent(void)
 	?ProcessingError@CMMFDevSoundAdaptation@@QAEHAAH@Z @ 56 NONAME ; int CMMFDevSoundAdaptation::ProcessingError(int &)
+	?RollbackAdaptorActiveStateToBeforeCommit@CMMFDevSoundAdaptation@@QAEXXZ @ 57 NONAME ; void CMMFDevSoundAdaptation::RollbackAdaptorActiveStateToBeforeCommit(void)
 
--- a/devsound/a3fdevsound/eabi/mmfdevsoundadaptor.def	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/eabi/mmfdevsoundadaptor.def	Wed Apr 14 17:32:53 2010 +0300
@@ -62,4 +62,5 @@
 	_ZN22CMMFDevSoundAdaptation6ResumeEv @ 61 NONAME
 	_ZN22CMMFDevSoundAdaptation16BufferErrorEventEv @ 62 NONAME
 	_ZN22CMMFDevSoundAdaptation15ProcessingErrorERi @ 63 NONAME
+	_ZN22CMMFDevSoundAdaptation40RollbackAdaptorActiveStateToBeforeCommitEv @ 64 NONAME
 
--- a/devsound/a3fdevsound/src/devsoundadaptor/cdevaudio.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/devsoundadaptor/cdevaudio.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -349,7 +349,8 @@
 
 	if(iActiveState != EDevSoundAdaptorCreated_Uninitialised &&
 		iActiveState != EDevSoundAdaptorInitialised_Initialised && 
-		iActiveState != EDevSoundAdaptorInitialised_Idle)
+		iActiveState != EDevSoundAdaptorInitialised_Idle &&
+		iActiveState != EDevSoundAdaptorUnitialised_Uninitialised )
 		{
 		DP0_RET(KErrNotReady, "%d");
 		}
@@ -366,8 +367,11 @@
 			err = iAudioStream->Unload();
 			if(err == KErrNone)
 				{
+				err = CommitAudioContext();
+				}
+			if(err == KErrNone)
+				{
 				iActiveState = EDevSoundAdaptorUnloading;
-				err = iAudioContext->Commit();
 				}
 			}
 		else
@@ -377,6 +381,15 @@
 		DP0_RET(err, "%d");
 		}
 
+	// Redo partial initialization after pre-emption clash event in
+	// EDevSoundAdaptorRemovingProcessingUnits state
+	if (iActiveState == EDevSoundAdaptorUnitialised_Uninitialised &&
+			iPreviousState == EDevSoundAdaptorRemovingProcessingUnits)
+		{
+		err = iCurrentAudioControl->RemoveProcessingUnits();
+		DP0_RET(err, "%d");
+		}
+
 	// Delete pUnits if already created
 	if (iAudioSource)
 		{
@@ -486,6 +499,15 @@
 		{
 		DP0_RET(KErrNotReady, "%d");
 		}
+
+	// Redo partial cancelling of initialization after pre-emption clash event in
+	// EDevSoundAdaptorRemovingProcessingUnits state.
+	if (iActiveState == EDevSoundAdaptorUnitialised_Uninitialised &&
+			iPreviousState == EDevSoundAdaptorRemovingProcessingUnits)
+		{
+		err = iCurrentAudioControl->RemoveProcessingUnits();
+		DP0_RET(err, "%d");
+		}
 			
 	err = iCurrentAudioControl->Uninitialize();
 	
@@ -574,6 +596,40 @@
 	DP0_RET(iActiveState, "%d");
 	}
 
+// -----------------------------------------------------------------------------
+// CDevAudio::ActiveState
+// -----------------------------------------------------------------------------
+//
+TDevSoundAdaptorState CDevAudio::PreviousState() const
+	{
+	DP_CONTEXT(CDevAudio::PreviousState *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	DP0_RET(iPreviousState, "%d");
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudio::SetActiveState
+// -----------------------------------------------------------------------------
+//
+void CDevAudio::SetActiveState(TDevSoundAdaptorState aAdaptorState)
+	{
+	DP_CONTEXT(CDevAudio::SetActiveState *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	iActiveState = aAdaptorState;
+	DP_OUT();
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudio::SetPreviousState
+// -----------------------------------------------------------------------------
+//
+void CDevAudio::SetPreviousState(TDevSoundAdaptorState aAdaptorState)
+	{
+	DP_CONTEXT(CDevAudio::SetPreviousState *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	iPreviousState = aAdaptorState;
+	DP_OUT();
+	}
 
 // -----------------------------------------------------------------------------
 // CDevAudio::SetDevSoundVolume
@@ -911,6 +967,34 @@
 	DP_OUT();
 	}
 
+TInt CDevAudio::CommitAudioContext()
+	{
+	DP_CONTEXT(CDevAudio::CommitAudioContext *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	//If we are in mid state then Panic as DevSound server-side session (CMMFDevSoundSession) is not blocking properly
+	__ASSERT_DEBUG(!IsMidState(iActiveState), Panic(EValidStateBeforeCommit));
+
+	TInt err = KErrNone;
+	iPreviousState = iActiveState;
+	err = iAudioContext->Commit();
+
+	DP0_RET(err,"%d");
+	}
+
+TBool CDevAudio::IsMidState(TDevSoundAdaptorState aAdaptorState)
+	{
+	DP_CONTEXT(CDevAudio::IsMidState *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	if (aAdaptorState == EDevSoundAdaptorRemovingProcessingUnits || aAdaptorState == EDevSoundAdaptorUninitialising ||
+			aAdaptorState == EDevSoundAdaptorInitialising || aAdaptorState == EDevSoundAdaptorLoading ||
+			aAdaptorState == EDevSoundAdaptorUnloading || aAdaptorState == EDevSoundAdaptorStopping ||
+			aAdaptorState == EDevSoundAdaptorActivating || aAdaptorState == EDevSoundAdaptorPausing)
+		{
+		DP0_RET(ETrue,"%d");
+		}
+	DP0_RET(EFalse,"%d");
+	}
 
 // -----------------------------------------------------------------------------
 // From MA3FDevSoundAutoPauseResume
@@ -979,5 +1063,9 @@
 	DP_OUT();
 	}
 
+void CDevAudio::Panic(TMMFDevAudioPanicCodes aCode)
+	{
+	User::Panic(KMMFDevAudioPanicCategory, aCode);
+	}
 
 // End of file
--- a/devsound/a3fdevsound/src/devsoundadaptor/cdevaudio.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/devsoundadaptor/cdevaudio.h	Wed Apr 14 17:32:53 2010 +0300
@@ -43,6 +43,15 @@
 class MAudioStream;
 class MGlobalProperties;
 
+/**
+Panic category and codes that CDevAudio raises on the client
+*/
+_LIT(KMMFDevAudioPanicCategory, "CDevAudio");
+
+enum TMMFDevAudioPanicCodes
+	{
+	EValidStateBeforeCommit =1
+	};
 
 enum TDevSoundAdaptorState
 	{
@@ -148,6 +157,24 @@
 	TDevSoundAdaptorState ActiveState() const;
 
 	/**
+	* Retrieve the previous DevSound adaptor state
+	* @return void
+	*/
+	TDevSoundAdaptorState PreviousState() const;
+
+	/**
+	* Set the current DevSound adaptor state
+	* @return void
+	*/
+	void SetActiveState(TDevSoundAdaptorState aAdaptorState);
+
+	/**
+	* Set the previous DevSound adaptor state
+	* @return void
+	*/
+	void SetPreviousState(TDevSoundAdaptorState aAdaptorState);
+
+	/**
 	* SetVolume for DevSound
 	*/
 	TInt SetDevSoundVolume(TInt aVolume, TBool& aAsyncCompletion);
@@ -247,6 +274,9 @@
 	
 	TBool IsPrioritySet();
 	
+	//Panic function
+	void Panic(TMMFDevAudioPanicCodes aCode);
+
 protected:
 
 	CDevAudio(MDevSoundAdaptationObserver& aAdaptationObserver);
@@ -258,6 +288,9 @@
 	TInt CreateAudioProcessingUnits(TUid aSource, TUid aSink, TUid aCodec);
 	void DeleteAudioProcessingUnits();
 
+	TInt CommitAudioContext();
+	TBool IsMidState(TDevSoundAdaptorState aAdaptorState);
+
 /*
 * most of member data is protected for DevAudioControl access
 */
@@ -322,6 +355,11 @@
 	*/
 	TDevSoundAdaptorState iActiveState;
 
+	/**
+	* Previous DevSound Adaptor state
+	*/
+	TDevSoundAdaptorState iPreviousState;
+
 	TAudioState		iActiveStreamState;
 
 	TBool 	iReinitializing;
--- a/devsound/a3fdevsound/src/devsoundadaptor/cdevaudiocontrol.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/devsoundadaptor/cdevaudiocontrol.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -179,8 +179,11 @@
 
 	if (err == KErrNone)
 		{
+		err = iDevAudio->CommitAudioContext();
+		}
+	if (err == KErrNone)
+		{
 		iDevAudio->iActiveState = EDevSoundAdaptorUninitialising;
-		err = iDevAudio->iAudioContext->Commit();
 		}
 
 	DP0_RET(err,"%d");
@@ -198,7 +201,7 @@
 	TInt err = iDevAudio->iAudioStream->Unload();
 	if (err == KErrNone)
 		{
-		err = iDevAudio->iAudioContext->Commit();
+		err = iDevAudio->CommitAudioContext();
 		}
 	if (err == KErrNone)
 		{
@@ -332,7 +335,7 @@
 	
 	if(err == KErrNone)
 		{
-		err = iDevAudio->iAudioContext->Commit();
+		err = iDevAudio->CommitAudioContext();
 		if (err == KErrNone)
 			{
 			iDesiredMode = mode;
@@ -489,7 +492,7 @@
 		// It means we're here due to RequestGainAndBalance call
 		if(err == KErrNone && !aBecomingActive)
 			{
-			err = iDevAudio->iAudioContext->Commit();
+			err = iDevAudio->CommitAudioContext();
 			}		
 		}
 	DP0_RET(err,"%d");
@@ -546,7 +549,7 @@
 			err = iDevAudio->iAudioStream->Stop();
 			if(err == KErrNone)
 				{
-				err = iDevAudio->iAudioContext->Commit();
+				err = iDevAudio->CommitAudioContext();
 				}
 			if (err == KErrNone)
 				{
@@ -559,7 +562,7 @@
 			err = iDevAudio->iAudioStream->Unload();
 			if(err == KErrNone)
 				{
-				err = iDevAudio->iAudioContext->Commit();	
+				err = iDevAudio->CommitAudioContext();
 				}
 			if (err == KErrNone)
 				{
@@ -572,7 +575,7 @@
 			err = iDevAudio->iAudioStream->Uninitialize();
 			if(err == KErrNone)
 				{
-				err = iDevAudio->iAudioContext->Commit();
+				err = iDevAudio->CommitAudioContext();
 				}
 			if (err == KErrNone)
 				{
@@ -582,6 +585,16 @@
 			break;
 		case EDevSoundAdaptorCreated_Uninitialised:
 			readyToDestroy = ETrue;
+			break;
+		case EDevSoundAdaptorUnitialised_Uninitialised:
+			//If following condition is true, then we are here because of a
+			//pre-emption clash in last Commit cycle started from
+			//CDevCommonControl::ContextEventUpdateWithStateEventNoError.
+			if(iDevAudio->iPreviousState == EDevSoundAdaptorRemovingProcessingUnits)
+				{
+				err = RemoveProcessingUnits();
+				break;
+				}
 		default:
 			break;
 		}
@@ -621,7 +634,7 @@
 
 	if (err == KErrNone)
 		{
-		err = iDevAudio->iAudioContext->Commit();
+		err = iDevAudio->CommitAudioContext();
 		}
 		
 	if(err == KErrNone)
@@ -847,8 +860,12 @@
 			{
 			iCurrentSampleRate = iDesiredSampleRate;
 			}
-		iDesiredSampleRate = 0;
 		}
+	else
+	    {
+        iAdaptationObserver->NotifyError(aError);
+	    }
+    iDesiredSampleRate = 0;
 	}
 
 // -----------------------------------------------------------------------------
@@ -864,8 +881,12 @@
 			{
 			iCurrentMode = iDesiredMode;
 			}
-		iDesiredMode = KNullUid;
 		}
+    else
+        {
+        iAdaptationObserver->NotifyError(aError);
+        }
+    iDesiredMode = KNullUid;
 	}
 
 // -----------------------------------------------------------------------------
@@ -935,6 +956,11 @@
 	DP_CONTEXT(CDevAudioControl::ContextEvent *CD1*, CtxDevSound, DPLOCAL);
 	DP_IN();
 
+    if(!(iAdaptationObserver->AdaptorControlsContext()))
+        {
+        iIgnoreAsyncOpComplete = ETrue;
+        }
+    
 	if (aEvent == KUidA3FContextUpdateComplete)
 		{
 	    if(iIgnoreAsyncOpComplete)
@@ -947,18 +973,15 @@
             iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
            	}
 		}
-	else if(aEvent == KUidA3FContextPreEmption || aEvent == KUidA3FContextPreEmptedCommit)
+	else if(aEvent == KUidA3FContextPreEmption)
 		{
-		
-		//Preemption during the below states should complete invoke AsynOperationComplete
-		if(iDevAudio->iActiveState!=EDevSoundAdaptorActivating && iDevAudio->iActiveState!=EDevSoundAdaptorLoading && 
-			iDevAudio->iActiveState!=EDevSoundAdaptorStopping && iDevAudio->iActiveState!=EDevSoundAdaptorUnloading
-			 && iDevAudio->iActiveState!=EDevSoundAdaptorPausing)
-			{
-			iIgnoreAsyncOpComplete = ETrue;
-			iAdaptationObserver->PreemptionStartedCallbackReceived();
-			}
+		//If we are in a normal pre-emption cycle, we should not be in a mid-state.
+		__ASSERT_DEBUG(!iDevAudio->IsMidState(iDevAudio->iActiveState), Panic(EInvalidStateDuringPreemptionCycle));
+		iIgnoreAsyncOpComplete = ETrue;
+		iAdaptationObserver->PreemptionStartedCallbackReceived();
 		}
+	//In a clashing pre-emption cycle we must be in a commit cycle, so do nothing here - CDevCommonControl deals
+	//with this case.
 	DP_OUT();
 	}
 
--- a/devsound/a3fdevsound/src/devsoundadaptor/cdevaudiocontrol.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/devsoundadaptor/cdevaudiocontrol.h	Wed Apr 14 17:32:53 2010 +0300
@@ -45,7 +45,8 @@
 	EStreamBeingDemotedToEIdle,
 	EAudioCodecIsNull,
 	EStreamMismatch,
-	EBufferMismatch
+	EBufferMismatch,
+	EInvalidStateDuringPreemptionCycle
 	};
 
 
--- a/devsound/a3fdevsound/src/devsoundadaptor/cdevcommoncontrol.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/devsoundadaptor/cdevcommoncontrol.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -48,7 +48,7 @@
             err = iDevAudio->iAudioStream->Stop();
             if (err == KErrNone)
                 {
-                err = iDevAudio->iAudioContext->Commit();
+                err = iDevAudio->CommitAudioContext();
                 }
             if (err == KErrNone)
                 {
@@ -58,6 +58,17 @@
         case EDevSoundAdaptorGoingActive:
             iDevAudio->iActiveState = EDevSoundAdaptorStopping;
             break;
+        case EDevSoundAdaptorInitialised_Idle:
+        	{
+        	//If following condition is true, then we are here because of a
+        	//pre-emption clash in last Commit cycle started from
+        	//CDevCommonControl::ContextEventUpdateWithStateEventNoError.
+        	if(iDevAudio->iPreviousState == EDevSoundAdaptorUnloading)
+        		{
+				err = Unload();
+				break;
+        		}
+        	}
         default:
             break;
         }
@@ -79,7 +90,7 @@
     TInt err = iDevAudio->iAudioStream->Prime();
     if ( err == KErrNone)
         {
-        err = iDevAudio->iAudioContext->Commit();
+        err = iDevAudio->CommitAudioContext();
         }
     if (err == KErrNone)
         {
@@ -101,13 +112,28 @@
         err = KErrNotReady;
         }
 
+    //If following condition is true, then we are here because of a
+    //pre-emption clash in last Commit cycle started from
+    //CDevCommonControl::ContextEventUpdateWithStateEventAndError.
+    if(iDevAudio->iActiveState == EDevSoundAdaptorInitialised_Idle &&
+    		iDevAudio->iPreviousState == EDevSoundAdaptorUnloading)
+    	{
+		err = Unload();
+		DP0_RET(err,"%d");
+    	}
+
+    if(err == KErrNone)
+        {
+        // Populate gain and balance values set in the Paused state and being cached
+        err = iDevAudio->RequestGainAndBalance(this);
+        }
     if(err == KErrNone)
         {
         err = iDevAudio->iAudioStream->Activate();
         }
     if ( err == KErrNone)
         {
-        err = iDevAudio->iAudioContext->Commit();
+        err = iDevAudio->CommitAudioContext();
         }
     if (err == KErrNone)
         {
@@ -182,12 +208,26 @@
     // Can't "switch {...}" on UIDs unfortunately:
     if (aEvent == KUidA3FContextUpdateComplete)
         {
-        if(iBeingPreempted && iStateEventReceived)
+        if(iBeingPreempted)
             {
-            //use a sub state pattern to make premtion cycles like other cycles.
-            DP1(DLERR,"Preemption error=%d", aError);
-            iDevAudio->iActiveState = EDevSoundAdaptorBeingPreempted;
-            iBeingPreempted=EFalse;
+			if(iStateEventReceived)
+				{
+				//use a sub state pattern to make pre-emption cycles like other cycles.
+				DP1(DLERR,"Preemption error=%d", aError);
+				iDevAudio->iActiveState = EDevSoundAdaptorBeingPreempted;
+				if(iPreemptionClash)
+					{
+					// remove last request from front of queue without processing it
+					iAdaptationObserver->PreemptionClashWithStateChange();
+					iPreemptionClash=EFalse;
+					}
+				}
+            else if(!iStateEventReceived && iPreemptionClash)
+        		{
+				iIgnoreAsyncOpComplete=ETrue;
+				iPreemptionClash=EFalse;
+        		}
+			iBeingPreempted=EFalse;
             }
 		ContextEventUpdateComplete(aError);
         }
@@ -195,16 +235,18 @@
     else if ((aEvent == KUidA3FContextCommitUpdate))
         {
         iBeingPreempted=EFalse; // clear being preempted
+        iPreemptionClash=EFalse; // clear pre-emption clash flag
         TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext();
         iIgnoreAsyncOpComplete = !adaptorControlsContext;
             // if we don't control context, always send a PreemptionFinishedCallbackReceived()
 		iStateEventReceived=EFalse;
         }
 
-    else if ((aEvent == KUidA3FContextPreEmption) or (aEvent == KUidA3FContextPreEmptedCommit))
+    else if (aEvent == KUidA3FContextPreEmption)
         {
         // clear iBeingPreepted - will be set in ContextEventPreEmption if req
         iBeingPreempted=EFalse;
+        iPreemptionClash=EFalse; // clear pre-emption clash flag
         TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext();
 		iStateEventReceived=EFalse;
         iIgnoreAsyncOpComplete=EFalse; // clear being iIgnoreAsyncOpComplete
@@ -214,6 +256,26 @@
             iIgnoreAsyncOpComplete = ETrue; // if we don't control context never do AsyncOpComplete
             }
         }
+    else if (aEvent == KUidA3FContextPreEmptedCommit)
+        {
+		DP0(DLINFO,"KUidA3FContextPreEmptedCommit event received, thus clash with Pre-emption");
+        // clear iBeingPreepted - will be set in ContextEventPreEmption if req
+        iBeingPreempted=EFalse;
+        TBool adaptorControlsContext = iAdaptationObserver->AdaptorControlsContext();
+        if (adaptorControlsContext)
+        	{
+			// push current request that was being processed onto front of queue.
+        	iAdaptationObserver->PreemptionClash();
+        	iPreemptionClash=ETrue;
+        	}
+		iStateEventReceived=EFalse;
+        iIgnoreAsyncOpComplete=EFalse; // clear being iIgnoreAsyncOpComplete
+        ContextEventPreEmption(aEvent, aError);
+        if (!adaptorControlsContext)
+            {
+            iIgnoreAsyncOpComplete = ETrue; // if we don't control context never do AsyncOpComplete
+            }
+        }
 
     else if (aEvent == KUidA3FContextAbort)
         {
@@ -426,7 +488,7 @@
         return;
         }
     
-    err = iDevAudio->iAudioContext->Commit();
+    err = iDevAudio->CommitAudioContext();
     if (err)
         {
         ContextEventAsynchronousPlayCompletion(err);
@@ -564,6 +626,18 @@
         return;
         }
 
+    //If the Commit cycle when going into EDevSoundAdaptorRemovingProcessingUnits fails due to pre-emption
+    //clash then we re-apply the client request again.
+    if (iDevAudio->iActiveState == EDevSoundAdaptorRemovingProcessingUnits && iIgnoreAsyncOpComplete)
+    	{
+		//Pop front of queue to re-apply the request again via CMMFDevSoundSession::DequeueRequest
+		//from the callback into CMMFDevSoundSession below:
+		iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
+		iIgnoreAsyncOpComplete = EFalse;
+		DP_OUT();
+		return;
+    	}
+
     iDevAudio->iActiveState = EDevSoundAdaptorCreated_Uninitialised;
     
     if (iDevAudio->iReinitializing)
@@ -592,32 +666,78 @@
     {
     DP_CONTEXT(CDevCommonControl::ContextEventUpdateWithoutStateEventButWithError, CtxDevSound, DPLOCAL);
     DP_IN();
-    
-    // NOTE: We shouldn't actually be in any of the states below when calling this function.
-    //       But just in case we are we will rewind the state before dealing with the error. 
-    switch (iDevAudio->iActiveState)
-        {
-    case EDevSoundAdaptorInitialising:
-        iDevAudio->iActiveState = EDevSoundAdaptorCreated_Uninitialised;
-        ContextEventAsynchronousInitializeComplete(aError);
-        break;
-        
-    case EDevSoundAdaptorLoading:
-        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Initialised;
-        ContextEventAsynchronousPlayCompletion(aError);
-        break;
-        
-    case EDevSoundAdaptorActivating:
-        iDevAudio->iActiveState = EDevSoundAdaptorInitialised_Idle;
-        ContextEventAsynchronousPlayCompletion(aError);
-        break;
-        
-    default:
-        if(iBeingPreempted)
-            {
-            iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue); // notify client of end of cycle
-            }
-        }
+
+    //If flag is true below then it must be due to a stateless normal pre-emption or
+    //stateless pre-emption clash scenario.
+    if(iIgnoreAsyncOpComplete)
+    	{
+		//If we are in pre-emption clash then callback below will retry the client request again.
+		iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue); // notify client of end of cycle
+		iIgnoreAsyncOpComplete = EFalse;
+    	}
+    else
+    	{
+        TDevSoundAdaptorState previousState = iDevAudio->iPreviousState;
+
+        DP3(DLINFO,"Error with no state change, state %d, previous %d, error %d during Commit cycle",
+                    iDevAudio->iActiveState, previousState, aError);
+
+        // We can end up here for a number of reasons. For non "mid states", this is
+        // a standard error scenario. For some mid-states (e.g. Activating, Loading etc),
+        // when we try and "promote" the state, this happens when the promotion is rejected
+        // and we handle thus accordingly. For other mid-states the situation is less clear
+        // and we call AsynchronousOperationComplete() with the error assuming the parent
+        // session will deal with it. Whatever we don't want to stay in a mid-state, so
+        // rewind to the previous ("normal") one if we are in one.
+
+        // Longer term TODO. If the code were refactored so that the InitializeComplete(),
+        // PlayError() etc callback came from AsynchronousOperationComplete() then the
+        // following code might be simpler. Most of the time (at least) we get here because
+        // we are doing a session function, and we can use the function to determine what
+        // to do more easily than relying on the state. As it is, for some mid-states we
+        // try and work out what error code to generate. Not clear this covers 100% cases,
+        // although demotion transitions should not fail, so the problem cases might not occur.
+        //
+
+		//If we reach this condition then it is because of rejection/error during Commit cycle.
+		switch (iDevAudio->iActiveState)
+			{
+			case EDevSoundAdaptorInitialising:
+				{
+				iDevAudio->iActiveState = previousState;
+				ContextEventAsynchronousInitializeComplete(aError);
+				break;
+				}
+			case EDevSoundAdaptorLoading:
+				{
+				iDevAudio->iActiveState = previousState;
+				ContextEventAsynchronousPlayCompletion(aError);
+				break;
+				}
+			case EDevSoundAdaptorActivating:
+				{
+				iDevAudio->iActiveState = previousState;
+				ContextEventAsynchronousPlayCompletion(aError);
+				break;
+				}
+			case EDevSoundAdaptorRemovingProcessingUnits:
+			case EDevSoundAdaptorUninitialising:
+			case EDevSoundAdaptorUnloading:
+			case EDevSoundAdaptorStopping:
+			case EDevSoundAdaptorPausing:
+			    {
+                DP2(DLINFO,"Unexpected mid state [%d] when handling error [%d] during Commit cycle, workback", iDevAudio->iActiveState, aError);
+			    iDevAudio->iActiveState = previousState;
+                iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
+			    break;
+			    }
+			default:
+				{
+				DP2(DLINFO,"Unexpected state [%d] when handling error [%d] during Commit cycle", iDevAudio->iActiveState, aError);
+		        iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
+				}
+			}
+    	}
        
     DP_OUT();
     }
@@ -713,12 +833,15 @@
     
     iCallbackFromAdaptor = KCallbackNone;
     
-    if(iIgnoreAsyncOpComplete==EFalse)
+    if(!iIgnoreAsyncOpComplete)
         {
         iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
         }
-    
-    iIgnoreAsyncOpComplete=EFalse;
+    else
+        {
+        iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
+        iIgnoreAsyncOpComplete=EFalse;
+        }
     
     DP_OUT();
     }
--- a/devsound/a3fdevsound/src/devsoundadaptor/cdevcommoncontrol.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/devsoundadaptor/cdevcommoncontrol.h	Wed Apr 14 17:32:53 2010 +0300
@@ -80,6 +80,7 @@
     
 private:
     TBool iBeingPreempted;
+    TBool iPreemptionClash;
 	};
 
 #endif // CDEVCOMMONCONTROL_H
--- a/devsound/a3fdevsound/src/devsoundadaptor/cdevplaycontrol.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/devsoundadaptor/cdevplaycontrol.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -143,7 +143,7 @@
 			err = iDevAudio->iAudioStream->Initialize();
 			if (err == KErrNone)
 				{
-				err = iDevAudio->iAudioContext->Commit();
+				err = iDevAudio->CommitAudioContext();
 				if (err == KErrNone)
 					{
 					iDevAudio->iActiveState = EDevSoundAdaptorInitialising;
@@ -195,7 +195,7 @@
 				}
 			if ( err == KErrNone)
 				{
-				err = iDevAudio->iAudioContext->Commit();
+				err = iDevAudio->CommitAudioContext();
 				}
 			if(err == KErrNone)
 				{
@@ -204,8 +204,29 @@
 			}
 			break;
 
+		case EDevSoundAdaptorGoingActive:
+			{
+			//If following condition is false, then we are here because of a
+			//pre-emption clash in last Commit cycle started from
+			//CDevCommonControl::ContextEventUpdateWithStateEventNoError.
+			if(iDevAudio->iPreviousState != EDevSoundAdaptorActivating)
+				{
+				break;
+				}
+			//Fall through as required
+			}
 		case EDevSoundAdaptorPaused_Primed:
 		case EDevSoundAdaptorInitialised_Idle:
+			{
+			//If following condition is true, then we are here because of a
+			//pre-emption clash in last Commit cycle started from
+			//CDevCommonControl::ContextEventUpdateWithStateEventAndError.
+			if(iDevAudio->iPreviousState == EDevSoundAdaptorUnloading)
+				{
+				err = Unload();
+				break;
+				}
+
 			err = iDevAudio->RequestGainAndBalance(this);
 			if (err==KErrNone)
 				{
@@ -213,13 +234,14 @@
 				}
 			if (err == KErrNone)
 				{
-				err = iDevAudio->iAudioContext->Commit();
+				err = iDevAudio->CommitAudioContext();
 				}
 			if (err == KErrNone)
 				{
 				iDevAudio->iActiveState = EDevSoundAdaptorActivating;
 				}
 			break;
+			}
 		case EDevSoundAdaptorActive_Active:
 			// Deliberate fall through - set err=KErrNotReady for PlayInit when already active
 		default:
@@ -323,7 +345,7 @@
 	TInt err = iDevAudio->iAudioStream->Stop();
 	if ( err == KErrNone)
 		{
-		err = iDevAudio->iAudioContext->Commit();
+		err = iDevAudio->CommitAudioContext();
 		if(err == KErrNone)
 			{
 			iDevAudio->iActiveState = EDevSoundAdaptorStopping;
--- a/devsound/a3fdevsound/src/devsoundadaptor/cdevrecordcontrol.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/devsoundadaptor/cdevrecordcontrol.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -143,7 +143,7 @@
 			err = iDevAudio->iAudioStream->Initialize();
 			if (err == KErrNone)
 				{
-				err = iDevAudio->iAudioContext->Commit();
+				err = iDevAudio->CommitAudioContext();
 				if (err == KErrNone)
 					{
 					iDevAudio->iActiveState = EDevSoundAdaptorInitialising;
@@ -195,7 +195,7 @@
 				}
 			if ( err == KErrNone)
 				{
-				err = iDevAudio->iAudioContext->Commit();
+				err = iDevAudio->CommitAudioContext();
 				}
 			if(err == KErrNone)
 				{
@@ -204,8 +204,28 @@
 			}
 			break;
 
+		case EDevSoundAdaptorGoingActive:
+			{
+			//If following condition is false, then we are here because of a
+			//pre-emption clash in last Commit cycle started from
+			//CDevCommonControl::ContextEventUpdateWithStateEventNoError.
+			if(iDevAudio->iPreviousState != EDevSoundAdaptorActivating)
+				{
+				break;
+				}
+			//Fall through as required
+			}
 		case EDevSoundAdaptorPaused_Primed:
 		case EDevSoundAdaptorInitialised_Idle:
+			{
+			//If following condition is true, then we are here because of a
+			//pre-emption clash in last Commit cycle started from
+			//CDevCommonControl::ContextEventUpdateWithStateEventAndError.
+			if(iDevAudio->iPreviousState == EDevSoundAdaptorUnloading)
+				{
+				err = Unload();
+				break;
+				}
 			err = iDevAudio->RequestGainAndBalance(this);
 			if (err==KErrNone)
 				{
@@ -213,14 +233,14 @@
 				}
 			if (err == KErrNone)
 				{
-				err = iDevAudio->iAudioContext->Commit();
+				err = iDevAudio->CommitAudioContext();
 				}
 			if (err == KErrNone)
 				{
 				iDevAudio->iActiveState = EDevSoundAdaptorActivating;
 				}
 			break;
-
+			}
 		default:
 			err = KErrNotReady;
 			break;
@@ -338,7 +358,7 @@
     TInt err = iDevAudio->iAudioStream->Stop();
     if ( err == KErrNone)
         {
-        err = iDevAudio->iAudioContext->Commit();
+        err = iDevAudio->CommitAudioContext();
         if(err == KErrNone)
             {
             iDevAudio->iActiveState = EDevSoundAdaptorStopping;
--- a/devsound/a3fdevsound/src/devsoundadaptor/cdevtonecontrol.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/devsoundadaptor/cdevtonecontrol.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -156,7 +156,7 @@
 	err = iDevAudio->iAudioStream->Initialize();
 	if (err == KErrNone)
 		{
-		err = iDevAudio->iAudioContext->Commit();
+		err = iDevAudio->CommitAudioContext();
 		}
 	if (err == KErrNone)
 		{
@@ -195,7 +195,7 @@
 				}
 			if ( err == KErrNone)
 				{
-				err = iDevAudio->iAudioContext->Commit();
+				err = iDevAudio->CommitAudioContext();
 				}
 			if(err == KErrNone)
 				{
@@ -204,8 +204,28 @@
 			}
 			break;
 
+		case EDevSoundAdaptorGoingActive:
+			{
+			//If following condition is false, then we are here because of a
+			//pre-emption clash in last Commit cycle started from
+			//CDevCommonControl::ContextEventUpdateWithStateEventNoError.
+			if(iDevAudio->iPreviousState != EDevSoundAdaptorActivating)
+				{
+				break;
+				}
+			//Fall through as required
+			}
 		case EDevSoundAdaptorPaused_Primed:
 		case EDevSoundAdaptorInitialised_Idle:
+			{
+			//If following condition is true, then we are here because of a
+			//pre-emption clash in last Commit cycle started from
+			//CDevCommonControl::ContextEventUpdateWithStateEventAndError.
+			if(iDevAudio->iPreviousState == EDevSoundAdaptorUnloading)
+				{
+				err = Unload();
+				break;
+				}
 			DP0(DLINFO, "Already in loaded state");
 			err = iDevAudio->RequestGainAndBalance(this);
 			if (err==KErrNone)
@@ -214,13 +234,14 @@
 				}
 			if (err == KErrNone)
 				{
-				err = iDevAudio->iAudioContext->Commit();
+				err = iDevAudio->CommitAudioContext();
 				}
 			if (err == KErrNone)
 				{
 				iDevAudio->iActiveState = EDevSoundAdaptorActivating;
 				}
 			break;
+			}
 		case EDevSoundAdaptorActive_Active:
 		default:
 			err = KErrNotReady;
@@ -339,7 +360,7 @@
 	TInt err = iDevAudio->iAudioStream->Stop();
 	if ( err == KErrNone)
 		{
-		err = iDevAudio->iAudioContext->Commit();
+		err = iDevAudio->CommitAudioContext();
 		if(err == KErrNone)
 			{
 			iDevAudio->iActiveState = EDevSoundAdaptorStopping;
--- a/devsound/a3fdevsound/src/devsoundadaptor/mmfdevsoundadaptation.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/devsoundadaptor/mmfdevsoundadaptation.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -923,5 +923,13 @@
 	{
 	iBody->BufferErrorEvent();
 	}
+
+EXPORT_C void CMMFDevSoundAdaptation::RollbackAdaptorActiveStateToBeforeCommit()
+	{
+	DP_CONTEXT(CMMFDevSoundAdaptation::RollbackAdaptorActiveStateToBeforeCommit *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	iBody->RollbackAdaptorActiveStateToBeforeCommit();
+	DP_OUT();
+	}
 	
 // End of file
--- a/devsound/a3fdevsound/src/devsoundadaptor/mmfdevsoundadaptation.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/devsoundadaptor/mmfdevsoundadaptation.h	Wed Apr 14 17:32:53 2010 +0300
@@ -229,6 +229,27 @@
 	 */
 	virtual TBool AdaptorControlsContext() const = 0;
 
+	/*
+	 * Callback indicating that a clash with pre-emption has occurred during the commit cycle
+	 * and to push the current request that was being processed onto front of queue.
+	 */
+
+	virtual void PreemptionClash() = 0;
+
+	/*
+	 * Callback indicating the clash with pre-emption during the commit cycle was with state change,
+	 * so the current request that was previously pushed onto the front of queue should be removed
+	 * without processing.
+	 */
+
+	virtual void PreemptionClashWithStateChange() = 0;
+
+	/*
+	 * Callback to indicate an error has been noticed. This is to be cached until subsequent
+	 * AsynchronousOperationComplete(), and handled then if needs.
+	 */
+	virtual void NotifyError(TInt aError) = 0;
+
 	};
 
 
@@ -883,6 +904,12 @@
 	*/
 	IMPORT_C void BufferErrorEvent();
 	
+	/**
+	* Used rollback the adapror active state to the previous state prior a Commit call
+	* @return void
+	*/
+	IMPORT_C void RollbackAdaptorActiveStateToBeforeCommit();
+
 protected:
 
 	// So that nobody can extend
--- a/devsound/a3fdevsound/src/devsoundadaptor/mmfdevsoundadaptationbody.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/devsoundadaptor/mmfdevsoundadaptationbody.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -1243,3 +1243,15 @@
 	ASSERT(iDevAudio);
 	iDevAudio->GetAudioControl()->BufferErrorEvent();
 	}
+
+void CMMFDevSoundAdaptation::CBody::RollbackAdaptorActiveStateToBeforeCommit()
+	{
+	DP_CONTEXT(CMMFDevSoundAdaptation::CBody::RollbackAdaptorActiveStateToBeforeCommit *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	TDevSoundAdaptorState previousState = iDevAudio->PreviousState();
+	// Set previous state to the active state set after state changing Commit call
+	iDevAudio->SetPreviousState(iDevAudio->ActiveState());
+	// Set active state to the previous state set before state changing Commit call
+	iDevAudio->SetActiveState(previousState);
+	DP_OUT();
+	}
--- a/devsound/a3fdevsound/src/devsoundadaptor/mmfdevsoundadaptationbody.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/devsoundadaptor/mmfdevsoundadaptationbody.h	Wed Apr 14 17:32:53 2010 +0300
@@ -665,6 +665,12 @@
 	*/
 	void BufferErrorEvent();
 
+	/**
+	* Used rollback the adapror active state to the previous state prior a Commit call
+	* @return void
+	*/
+	void RollbackAdaptorActiveStateToBeforeCommit();
+
 private:
 
 	CBody(MDevSoundAdaptationObserver& aDevSoundObserver,
--- a/devsound/a3fdevsound/src/mmfdevsoundserver/mmfdevsoundsession.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/mmfdevsoundserver/mmfdevsoundsession.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -26,15 +26,15 @@
 #define SYMBIAN_DEBPRN0(str)                RDebug::Print(str, this)
 #define SYMBIAN_DEBPRN1(str, val1)          RDebug::Print(str, this, val1)
 #define SYMBIAN_DEBPRN2(str, val1, val2)    RDebug::Print(str, this, val1, val2)
+#define SYMBIAN_DEBPRN3(str, val1, val2, val3)    RDebug::Print(str, this, val1, val2, val3)
 #else
 #define SYMBIAN_DEBPRN0(str)
 #define SYMBIAN_DEBPRN1(str, val1)
 #define SYMBIAN_DEBPRN2(str, val1, val2)
+#define SYMBIAN_DEBPRN3(str, val1, val2, val3)
 #endif //_DEBUG
 
-//Assume that we can have two user request and one callback request
-//at the same time (maximum).
-const TInt KMaxQueueRequest = 3;
+const TInt KMaxQueueRequest = 6;
 
 //	MEMBER FUNCTIONS 
 
@@ -222,15 +222,23 @@
 	}
 
 //
+// NeedToQueue - mid-commit cycle or async queue start AO is active
+//
+TBool CMMFDevSoundSession::NeedToQueue() const
+    {
+    return iOperationCompletePending || iAsyncQueueStart->IsActive();
+    }
+
+//
 // CMMFDevSoundSession::ServiceL
 // (other items were commented in a header).
 //
 void CMMFDevSoundSession::ServiceL(const RMmfIpcMessage& aMessage)
 	{
 	SYMBIAN_DEBPRN2(_L("\nCMMFDevSoundSession[0x%x] NEW REQUEST %02x while pending=%d"),
-	        aMessage.Function(), iOperationCompletePending || iAsyncQueueStart->IsActive());
+	        aMessage.Function(), NeedToQueue());
 	
-	if( iOperationCompletePending || iAsyncQueueStart->IsActive())
+	if(NeedToQueue())
 		{
 		// if not possible to service now, then queue request
 		EnqueueRequest(aMessage);
@@ -257,8 +265,11 @@
 //
 void CMMFDevSoundSession::DoServiceRequestL(const RMmfIpcMessage& aMessage)
 	{
+	iRequestBeingServiced.SetMessage(aMessage);
 	iAsyncQueueStart->Cancel(); // just in case.
-	TMMFMessageDestinationPckg destinationPckg;
+    ResetNotifiedError();
+
+    TMMFMessageDestinationPckg destinationPckg;
 	MmfMessageUtil::ReadL(aMessage, 0, destinationPckg);
 	SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x]::DoServiceRequestL - DestinationHandle [%d] InterfaceId [%d] "), destinationPckg().DestinationHandle(), destinationPckg().InterfaceId());
 	if ((destinationPckg().DestinationHandle() == KMMFObjectHandleDevSound) &&
@@ -440,17 +451,29 @@
 			// Complete the message
 			// Synchronous requests & Pseudo-asynchronous
 			aMessage.Complete(KErrNone);
-			}
-		// Note: There are operations that not complete the message using the following flag
-		// So if the message is not completed, cannot be assumed that there is an operation pending
-		
-		SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoServiceRequestL - iOperationCompletePending [%d]"), iOperationCompletePending);
-		if(iOperationCompletePending)
-			{
-			// Keep a copy of the message for Asynchronous requests & Pseudo-asynchronous
-			iRequestBeingServiced.SetMessage(aMessage);
+
+			// Store function if we need to re-apply it again due to pre-emption clash
+			if(iRequestBeingServiced.Type() == TMMFDevSoundRequest::EAction_PseudoAsynchronous)
+				{
+				iRedoFunction = aMessage.Function();
+				}
 			}
 		}
+	else if (aMessage.Function() == RMessage2::EDisConnect)
+	    {
+        TBool complete = iAdapter->CloseDevSound();
+        if(!complete)
+            {
+            iRequestBeingServiced.SetMessage(aMessage);
+            iOperationCompletePending = ETrue;
+            ResetNotifiedError();
+            }
+        else
+            {
+            // if we get here, iClosing wait will have been started and we'd be waiting
+            iClosingWait->AsyncStop();
+            }
+	    }
 	else
 		{
 		// If there's a CI extension, see if that handles this request
@@ -467,6 +490,7 @@
 				}
 			iOperationCompletePending = EFalse;
 			iHandlingExtdCI = EFalse;
+			SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x]::DoServiceRequestL - CIExtensionRequest[%d] - Exit with Error[%d] "), aMessage.Function(),err);
 			}
 
 		if (err != KErrNone)
@@ -477,6 +501,80 @@
 		}
 	}
 
+void CMMFDevSoundSession::DoServiceAlreadyCompletedRequestL(const TInt aFunction)
+	{
+    ResetNotifiedError();
+
+	switch(aFunction)
+		{
+		case EMMFDevSoundProxyInitialize1:
+			DoAlreadyCompletedInitialize1L();
+			break;
+		case EMMFDevSoundProxyInitialize2:
+			DoAlreadyCompletedInitialize2L();
+			break;
+		case EMMFDevSoundProxyInitialize4:
+			DoAlreadyCompletedInitialize4L();
+			break;
+		case EMMFDevSoundProxyPlayInit:
+			DoAlreadyCompletedPlayInitL();
+			break;
+		case EMMFDevSoundProxyRecordInit:
+			DoAlreadyCompletedRecordInitL();
+			break;
+		case EMMFDevSoundProxyPlayTone:
+			DoAlreadyCompletedPlayToneL();
+			break;
+		case EMMFDevSoundProxyPlayDualTone:
+			DoAlreadyCompletedPlayDualToneL();
+			break;
+		case EMMFDevSoundProxyPlayDTMFString:
+			DoAlreadyCompletedPlayDTMFStringL();
+			break;
+		case EMMFDevSoundProxyPlayToneSequence:
+			DoAlreadyCompletedPlayToneSequenceL();
+			break;
+		case EMMFDevSoundProxyPlayFixedSequence:
+			DoAlreadyCompletedPlayFixedSequenceL();
+			break;
+		default:
+			User::Leave(KErrNotSupported);
+			break;
+		}
+
+	}
+
+void CMMFDevSoundSession::HandleAlreadyCompletedRequest()
+	{
+	TRAPD(err,DoServiceAlreadyCompletedRequestL(iRedoFunction));
+
+	if (err != KErrNone)
+		{
+		switch(iRedoFunction)
+			{
+			case EMMFDevSoundProxyInitialize1:
+			case EMMFDevSoundProxyInitialize2:
+			case EMMFDevSoundProxyInitialize4:
+				InitializeComplete(err);
+				break;
+			case EMMFDevSoundProxyPlayInit:
+				PlayError(err);
+				break;
+			case EMMFDevSoundProxyRecordInit:
+				RecordError(err);
+				break;
+			case EMMFDevSoundProxyPlayTone:
+			case EMMFDevSoundProxyPlayDualTone:
+			case EMMFDevSoundProxyPlayDTMFString:
+			case EMMFDevSoundProxyPlayToneSequence:
+			case EMMFDevSoundProxyPlayFixedSequence:
+				ToneFinished(err);
+				break;
+			default:
+				break;
+			}
+		}
+	}
 
 void CMMFDevSoundSession::EnqueueRequest(const RMmfIpcMessage& aMessage)
 	{
@@ -510,6 +608,7 @@
 	DoSetClientConfigL();// added here instead of the CreateL()
 	TMMFDevSoundProxySettingsPckg devSoundBuf;
 	MmfMessageUtil::ReadL(aMessage,1,devSoundBuf);
+	iCachedClientData = devSoundBuf;
 	TMMFState mode = devSoundBuf().iMode;
 	iAdapter->InitializeL(mode);
 	iBufferPlay = NULL;
@@ -521,6 +620,20 @@
 	}
 
 //
+// CMMFDevSoundSession::DoAlreadyCompletedInitialize1L
+// (other items were commented in a header).
+//
+void CMMFDevSoundSession::DoAlreadyCompletedInitialize1L()
+	{
+	TMMFState mode = iCachedClientData().iMode;
+	iAdapter->InitializeL(mode);
+	iBufferPlay = NULL;
+	iPlayErrorOccured = EFalse;
+	// Flag to queue any further request
+	iOperationCompletePending = ETrue;
+	}
+
+//
 // CMMFDevSoundSession::DoInitialize2L
 // (other items were commented in a header).
 //
@@ -532,6 +645,7 @@
 	DoSetClientConfigL();// added here instead of the CreateL()
 	TMMFDevSoundProxySettingsPckg devSoundBuf;
 	MmfMessageUtil::ReadL(aMessage,1,devSoundBuf);
+	iCachedClientData = devSoundBuf;
 	TUid HWDev = devSoundBuf().iHWDev;
 	TMMFState mode = devSoundBuf().iMode;
 	iAdapter->InitializeL(HWDev, mode);
@@ -541,6 +655,19 @@
 	}
 
 //
+// CMMFDevSoundSession::DoAlreadyCompletedInitialize2L
+// (other items were commented in a header).
+//
+void CMMFDevSoundSession::DoAlreadyCompletedInitialize2L()
+	{
+	TUid HWDev = iCachedClientData().iHWDev;
+	TMMFState mode = iCachedClientData().iMode;
+	iAdapter->InitializeL(HWDev, mode);
+	iBufferPlay = NULL;
+	iPlayErrorOccured = EFalse;
+	}
+
+//
 // CMMFDevSoundSession::DoInitialize4L
 // (other items were commented in a header).
 //
@@ -552,6 +679,7 @@
 	DoSetClientConfigL();// added here instead of the CreateL()
 	TMMFDevSoundProxySettingsPckg devSoundBuf;
 	aMessage.ReadL(TInt(1),devSoundBuf);
+	iCachedClientData = devSoundBuf;
 	TFourCC desiredFourCC = devSoundBuf().iDesiredFourCC;
 	TMMFState mode = devSoundBuf().iMode;
 	iAdapter->InitializeL(desiredFourCC, mode);
@@ -564,6 +692,21 @@
 	}
 
 //
+// CMMFDevSoundSession::DoAlreadyCompletedInitialize4L
+// (other items were commented in a header).
+//
+void CMMFDevSoundSession::DoAlreadyCompletedInitialize4L()
+	{
+	TFourCC desiredFourCC = iCachedClientData().iDesiredFourCC;
+	TMMFState mode = iCachedClientData().iMode;
+	iAdapter->InitializeL(desiredFourCC, mode);
+	iBufferPlay = NULL;
+	iPlayErrorOccured = EFalse;
+	// Flag to queue any further request
+	iOperationCompletePending = ETrue;
+	}
+
+//
 // CMMFDevSoundSession::DoCancelInitialize
 // (other items were commented in a header).
 //
@@ -782,6 +925,16 @@
 	}
 
 //
+// CMMFDevSoundSession::DoAlreadyCompletedPlayInitL
+// (other items were commented in a header).
+//
+void CMMFDevSoundSession::DoAlreadyCompletedPlayInitL()
+	{
+	iAdapter->PlayInitL();
+	iOperationCompletePending = ETrue;
+	}
+
+//
 // CMMFDevSoundSession::DoRecordInitL
 // (other items were commented in a header).
 //
@@ -793,6 +946,16 @@
 	}
 
 //
+// CMMFDevSoundSession::DoAlreadyCompletedRecordInitL
+// (other items were commented in a header).
+//
+void CMMFDevSoundSession::DoAlreadyCompletedRecordInitL()
+	{
+	iAdapter->RecordInitL();
+	iOperationCompletePending = ETrue;
+	}
+
+//
 // CMMFDevSoundSession::DoPlayDataL
 // (other items were commented in a header).
 //
@@ -868,6 +1031,7 @@
     SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoPlayToneL - Enter"));
     TMMFDevSoundProxySettingsPckg devSoundBuf;
 	aMessage.ReadL(TInt(1),devSoundBuf);
+	iCachedClientData = devSoundBuf;
 	TInt frequency = devSoundBuf().iFrequencyOne;
 	TTimeIntervalMicroSeconds duration(devSoundBuf().iDuration);
 	iAdapter->PlayToneL(frequency, duration);
@@ -877,6 +1041,18 @@
 	}
 
 //
+// CMMFDevSoundSession::DoAlreadyCompletedPlayToneL
+// (other items were commented in a header).
+//
+void CMMFDevSoundSession::DoAlreadyCompletedPlayToneL()
+	{
+	TInt frequency = iCachedClientData().iFrequencyOne;
+	TTimeIntervalMicroSeconds duration(iCachedClientData().iDuration);
+	iAdapter->PlayToneL(frequency, duration);
+	iOperationCompletePending = ETrue;
+	}
+
+//
 // CMMFDevSoundSession::DoPlayDualToneL
 // (other items were commented in a header).	
 //
@@ -885,6 +1061,7 @@
     SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoPlayDualToneL - Enter"));
     TMMFDevSoundProxySettingsPckg devSoundBuf;
 	aMessage.ReadL(TInt(1),devSoundBuf);
+	iCachedClientData = devSoundBuf;
 	TInt frequencyOne = devSoundBuf().iFrequencyOne;
 	TInt frequencyTwo = devSoundBuf().iFrequencyTwo;
 	TTimeIntervalMicroSeconds duration(devSoundBuf().iDuration);
@@ -895,6 +1072,19 @@
 	}
 
 //
+// CMMFDevSoundSession::DoAlreadyCompletedPlayDualToneL
+// (other items were commented in a header).
+//
+void CMMFDevSoundSession::DoAlreadyCompletedPlayDualToneL()
+	{
+	TInt frequencyOne = iCachedClientData().iFrequencyOne;
+	TInt frequencyTwo = iCachedClientData().iFrequencyTwo;
+	TTimeIntervalMicroSeconds duration(iCachedClientData().iDuration);
+	iAdapter->PlayDualToneL(frequencyOne, frequencyTwo, duration);
+	iOperationCompletePending = ETrue;
+	}
+
+//
 // CMMFDevSoundSession::DoPlayDTMFStringL
 // (other items were commented in a header).
 //
@@ -920,6 +1110,16 @@
 	}
 
 //
+// CMMFDevSoundSession::DoAlreadyCompletedPlayDTMFStringL
+// (other items were commented in a header).
+//
+void CMMFDevSoundSession::DoAlreadyCompletedPlayDTMFStringL()
+	{
+	iAdapter->PlayDTMFStringL(*iDtmfString);
+	iOperationCompletePending = ETrue;
+	}
+
+//
 // CMMFDevSoundSession::DoPlayToneSequenceL
 // (other items were commented in a header).
 //
@@ -945,6 +1145,16 @@
 	}
 
 //
+// CMMFDevSoundSession::DoAlreadyCompletedPlayToneSequenceL
+// (other items were commented in a header).
+//
+void CMMFDevSoundSession::DoAlreadyCompletedPlayToneSequenceL()
+	{
+	iAdapter->PlayToneSequenceL(*iToneSeqBuf);
+	iOperationCompletePending = ETrue;
+	}
+
+//
 // CMMFDevSoundSession::DoPlayFixedSequenceL
 // (other items were commented in a header).
 //
@@ -954,7 +1164,7 @@
     TPckgBuf<TInt> buf;
 	aMessage.ReadL(TInt(1),buf);
 	TInt seqNum = buf();
-
+	iSeqNum = seqNum;
 	iAdapter->PlayFixedSequenceL(seqNum);
 	iOperationCompletePending = ETrue;
 	SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoPlayFixedSequenceL - Exit. Return value is [%d]"), ETrue);
@@ -962,6 +1172,16 @@
 	}
 
 //
+// CMMFDevSoundSession::DoAlreadyCompletedPlayFixedSequenceL
+// (other items were commented in a header).
+//
+void CMMFDevSoundSession::DoAlreadyCompletedPlayFixedSequenceL()
+	{
+	iAdapter->PlayFixedSequenceL(iSeqNum);
+	iOperationCompletePending = ETrue;
+	}
+
+//
 // CMMFDevSoundSession::DoSetDTMFLengthsL
 // (other items were commented in a header).
 //
@@ -990,7 +1210,7 @@
 	TTimeIntervalMicroSeconds duration = devSoundBuf().iDuration;
 	User::LeaveIfError(iAdapter->SetVolumeRamp(duration));
 	iOperationCompletePending = EFalse; // Volume ramp doesn't result on commit
-    SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoSetVolumeRampL - Exit"));
+    SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoSetVolumeRampL - Exit. Return value is [%d]"), ETrue);
 	return ETrue; // operation complete
 	}
 
@@ -1075,7 +1295,7 @@
 	TPckgBuf<TTimeIntervalMicroSeconds> repeatTS;
 	aMessage.ReadL(TInt(2),repeatTS);
 	User::LeaveIfError(iAdapter->SetToneRepeats(countRepeat(), repeatTS()));
-    SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoSetToneRepeatsL - Exit"));
+    SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoSetToneRepeatsL - Exit. Return value is [%d]"), ETrue);
 	return ETrue;
 	}
 
@@ -1107,7 +1327,7 @@
 	fixSeqCountPckg = fixSeqCount;
 
 	aMessage.WriteL(TInt(2),fixSeqCountPckg);
-    SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::DoFixedSequenceCountL - Exit"));
+    SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::DoFixedSequenceCountL - Exit. Return value is [%d]"), ETrue);
 	return ETrue;
 	}
 
@@ -1420,13 +1640,25 @@
 void CMMFDevSoundSession::Disconnect(const RMessage2& aMessage)
 	{
     SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::Disconnect - Enter"));
-    TBool complete = iAdapter->CloseDevSound();
-	if(!complete)
-		{
-		iRequestBeingServiced.SetMessage(aMessage);
-		iOperationCompletePending = ETrue;
-		iClosingWait->Start();
-		}
+    if (NeedToQueue())
+        {
+        // if we are in the middle of something, enqueue and wait
+        SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::Disconnect - Add to queue"));
+        EnqueueRequest(aMessage);
+        iClosingWait->Start();
+        }
+    else
+        {
+        // else do now. Enter ActiveSchedulerWait to wait for AsyncOpComplete
+        TBool complete = iAdapter->CloseDevSound();
+        if(!complete)
+            {
+            iRequestBeingServiced.SetMessage(aMessage);
+            iOperationCompletePending = ETrue;
+            ResetNotifiedError();
+            iClosingWait->Start();
+            }
+        }
 	CSession2::Disconnect(aMessage);
     SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::Disconnect - Exit"));
 	}
@@ -1683,7 +1915,7 @@
 //
 void CMMFDevSoundSession::CallbackFromAdaptorReceived(TInt aType, TInt aError)
 	{
-    SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x]::CallbackFromAdaptorReceived - Enter. Type [%d ]Error [%d]"), aType, aError);
+    SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x]::CallbackFromAdaptorReceived - Enter. Type[%d] Error[%d]"), aType, aError);
 	if(aType == KCallbackRecordPauseComplete)
 		{
 		TMMFDevSoundQueueItem item;
@@ -1702,12 +1934,17 @@
 		}
 	else if (aType == KCallbackFlushComplete)
 		{
-		iRequestBeingServiced.Complete(aError);
-		iOperationCompletePending = EFalse;
+		if(!iHandlingExtdCI && iRequestBeingServiced.Function()==EMMFDevSoundProxyEmptyBuffers)
+			{
+			//If we come here then it is due to a EMMFDevSoundProxyEmptyBuffers request from client.
+			SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::CallbackFromAdaptorReceived - Calling TMMFDevSoundRequest::Complete on iRequestBeingServiced"));
+		    iRequestBeingServiced.Complete(aError);
+		    iOperationCompletePending = EFalse;
+			}
 		}
 	else
 		{
-		if( iOperationCompletePending )
+		if( NeedToQueue() )
 			{
 			// If not possible to service now, then queue request
 			// Encapsule the request
@@ -1766,6 +2003,33 @@
 	}
 
 //
+// CMMFDevSoundSession::PreemptionClash
+// (other items were commented in a header).
+//
+void CMMFDevSoundSession::PreemptionClash()
+	{
+	//assumes sufficient space in the queue so ignore the return value
+	iQueuedRequests.Insert(iRequestBeingServiced, 0);
+	iPreemptionClash=ETrue;
+	}
+
+//
+// CMMFDevSoundSession::PreemptionClashWithStateChange
+// (other items were commented in a header).
+//
+void CMMFDevSoundSession::PreemptionClashWithStateChange()
+	{
+	#ifdef _DEBUG
+		TMMFDevSoundRequest msg = iQueuedRequests[0];
+		// message being removed should be the one we previously pushed via PreemptionClash()
+		__ASSERT_DEBUG(iRequestBeingServiced==msg, Panic(ERequestBeingServicedMismatch));
+	#endif
+	// remove without processing request with AsynchronousOperationComplete() completing the message
+	iQueuedRequests.Remove(0);
+	iPreemptionClash=EFalse;
+	}
+
+//
 // CMMFDevSoundSession::AdaptorControlsContext()
 //
 
@@ -1812,6 +2076,13 @@
     __ASSERT_DEBUG(!iHandlingExtdCI, Panic(EUnexpectedAsyncOpCompleteHandlingCI));
         // when handling CIs we should not reach here
 
+    TInt error = aError;
+    if (!error)
+        {
+        // if have no error payload, use notified error. It will be KErrNone if not set, so just use.
+        error = NotifiedError();
+        }
+
 	switch (iRequestBeingServiced.Type())
 		{
 		case TMMFDevSoundRequest::ESessionEvents:
@@ -1853,7 +2124,7 @@
 					FlushEventQueue();
 					}
 				
-				iRequestBeingServiced.Complete(aError);
+				iRequestBeingServiced.Complete(error);
 				iOperationCompletePending = EFalse;
 				}
 			}
@@ -1881,9 +2152,19 @@
 		default:
 			break;
 		}
+	
+	if(iRequestBeingServiced.Type() == TMMFDevSoundRequest::ECallBackType )
+	    {	    
+	    SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x] AsynchronousOperationComplete CallbackPF=%d pending=%d"),
+	            iRequestBeingServiced.IsCallBack(), iOperationCompletePending );
+	    }
+	else
+	    {
+	    SYMBIAN_DEBPRN3(_L("CMMFDevSoundSession[0x%x] AsynchronousOperationComplete %x pending=%d Requestype=%d"),
+	            iRequestBeingServiced.Function(), iOperationCompletePending, iRequestBeingServiced.Type() );
+	    }
 
-	SYMBIAN_DEBPRN2(_L("CMMFDevSoundSession[0x%x] AsynchronousOperationComplete %x pending=%d"),iRequestBeingServiced.Function(), iOperationCompletePending );
-
+	    
 	if ( aCanStartNewOperation && iQueuedRequests.Count() != 0 )
 		{
 		DequeueRequest();
@@ -1939,11 +2220,29 @@
 	SYMBIAN_DEBPRN0(_L("\n CMMFDevSoundSession[0x%x]======== Service a queued request\n"));
 	TMMFDevSoundRequest msg = iQueuedRequests[0];
 	iQueuedRequests.Remove(0);
-	TRAPD(err,DoServiceRequestL(msg.Message()));
-    if(err != KErrNone)
-        {
-        msg.Complete(err);      
-        }
+	TInt err = KErrNone;
+	TBool doRequest = ETrue;
+	if(iPreemptionClash)
+		{
+		SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::AsyncQueueStartCallback - Re-applying client request due to Pre-emption clash"));
+		iPreemptionClash=EFalse; // clear flag before reading next request in queue
+		iAdapter->RollbackAdaptorActiveStateToBeforeCommit();
+		if ((iRequestBeingServiced.Type() == TMMFDevSoundRequest::EAction_PseudoAsynchronous))
+			{
+		    doRequest = EFalse;
+		    HandleAlreadyCompletedRequest();
+			}
+		}
+
+	if (doRequest)
+		{
+		TRAP(err,DoServiceRequestL(msg.Message()));
+		if(err != KErrNone)
+			{
+			msg.Complete(err);
+			}
+		}
+
 	if (!iOperationCompletePending && iQueuedRequests.Count() != 0)
 		{
 		//dequeue next
@@ -1972,6 +2271,8 @@
 //
 void CMMFDevSoundSession::DoProcessingFinished()
 	{
+    ResetNotifiedError();
+
 	TBool asyncOperation = EFalse;
 	//ProcessingFinished should never fail
 	__ASSERT_ALWAYS(KErrNone, iAdapter->ProcessingFinishedReceived(asyncOperation));
@@ -1987,6 +2288,8 @@
 //
 void CMMFDevSoundSession::DoProcessingError()
     {
+    ResetNotifiedError();
+
     TBool asyncOperation = EFalse;
     //ProcessingFinished should never fail
     __ASSERT_ALWAYS(KErrNone, iAdapter->ProcessingError(asyncOperation));
@@ -2327,4 +2630,26 @@
 	// this will generate an processing error event and callback
 	iAdapter->BufferErrorEvent();
 	}
+
+void CMMFDevSoundSession::ResetNotifiedError()
+// called at beginning of commit cycle, so any error will be from callbacks
+    {
+    SYMBIAN_DEBPRN0(_L("CMMFDevSoundSession[0x%x]::ResetNotifiedError"));
+    iNotifiedError = KErrNone;
+    }
+
+TInt CMMFDevSoundSession::NotifiedError() const
+// NotifiedError property
+    {
+    SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::NotifiedError(%d)"), iNotifiedError);
+    return iNotifiedError;
+    }
+
+void CMMFDevSoundSession::NotifyError(TInt aError)
+// cache notified error
+    {
+    SYMBIAN_DEBPRN1(_L("CMMFDevSoundSession[0x%x]::NotifyError(%d)"), aError);
+    iNotifiedError = aError;
+    }
+
 // End of file
--- a/devsound/a3fdevsound/src/mmfdevsoundserver/mmfdevsoundsession.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsound/a3fdevsound/src/mmfdevsoundserver/mmfdevsoundsession.h	Wed Apr 14 17:32:53 2010 +0300
@@ -48,7 +48,8 @@
 	{
 	EMsgQueueFailedToSendMsg =1,
 	EQueueRequestsFailedToAppend,
-	EUnexpectedAsyncOpCompleteHandlingCI
+	EUnexpectedAsyncOpCompleteHandlingCI,
+	ERequestBeingServicedMismatch
 	};
 
 // CLASS DECLARATION
@@ -207,6 +208,14 @@
 	TBool DoInitialize1L(const RMmfIpcMessage& aMessage);
 
 	/**
+		Method to service Initialize1L request that has already completed, but
+		not finished due to a pre-emption clash during its commit cycle(s).
+		Leaves on failure.
+		@return void
+	*/
+	void DoAlreadyCompletedInitialize1L();
+
+	/**
 		Method to service Initialize2L request.
 		Leaves on failure.
 		@since 
@@ -217,6 +226,14 @@
 	TBool DoInitialize2L(const RMmfIpcMessage& aMessage);
 
 	/**
+		Method to service Initialize2L request that has already completed, but
+		not finished due to a pre-emption clash during its commit cycle(s).
+		Leaves on failure.
+		@return void
+	*/
+	void DoAlreadyCompletedInitialize2L();
+
+	/**
 		Method to service Initialize3L request.
 		Leaves on failure.
 		@param const RMmfIpcMessage& aMessage A reference to message object
@@ -235,6 +252,14 @@
 	TBool DoInitialize4L(const RMmfIpcMessage& aMessage);
 	
 	/**
+		Method to service Initialize4L request that has already completed, but
+		not finished due to a pre-emption clash during its commit cycle(s).
+		Leaves on failure.
+		@return void
+	*/
+	void DoAlreadyCompletedInitialize4L();
+
+	/**
 		Method to service CancelInitialize request.
 		Leaves on failure.
 		@since 
@@ -388,6 +413,14 @@
 	TBool DoPlayInitL(const RMmfIpcMessage& aMessage);
 
 	/**
+		Method to service initialize DevSound to play request that has already completed,
+		but not finished due to a pre-emption clash during its commit cycle(s).
+		Leaves on failure.
+		@return void
+	*/
+	void DoAlreadyCompletedPlayInitL();
+
+	/**
 		Method to service initialize DevSound to record request.
 		Leaves on failure.
 		@since 
@@ -398,6 +431,14 @@
 	TBool DoRecordInitL(const RMmfIpcMessage& aMessage);
 
 	/**
+		Method to service initialize DevSound to record request that has already completed,
+		but not finished due to a pre-emption clash during its commit cycle(s).
+		Leaves on failure.
+		@return void
+	*/
+	void DoAlreadyCompletedRecordInitL();
+
+	/**
 		Method to service signal DevSound to playing current buffer request.
 		Leaves on failure.
 		@since 
@@ -450,6 +491,15 @@
 	TBool DoPlayToneL(const RMmfIpcMessage& aMessage);
 
 	/**
+		Method to service signal DevSound to play simple tone operation
+		request that has already completed, but not finished due to a
+		pre-emption clash during its commit cycle(s).
+		Leaves on failure.
+		@return void
+	*/
+	void DoAlreadyCompletedPlayToneL();
+
+	/**
 		Method to service signal DevSound to play dual tone  operation
 		request.
 		Leaves on failure.
@@ -461,6 +511,15 @@
 	TBool DoPlayDualToneL(const RMmfIpcMessage& aMessage);
 
 	/**
+		Method to service signal DevSound to play dual tone operation
+		request that has already completed, but not finished due to a
+		pre-emption clash during its commit cycle(s).
+		Leaves on failure.
+		@return void
+	*/
+	void DoAlreadyCompletedPlayDualToneL();
+
+	/**
 		Method to service signal DevSound to play DTMFString operation
 		request.
 		Leaves on failure.
@@ -472,6 +531,15 @@
 	TBool DoPlayDTMFStringL(const RMmfIpcMessage& aMessage);
 
 	/**
+		Method to service signal DevSound to play DTMFString operation
+		request that has already completed, but not finished due to a
+		pre-emption clash during its commit cycle(s).
+		Leaves on failure.
+		@return void
+	*/
+	void DoAlreadyCompletedPlayDTMFStringL();
+
+	/**
 		Method to service signal DevSound to play tone sequence operation
 		request.
 		Leaves on failure.
@@ -483,6 +551,15 @@
 	TBool DoPlayToneSequenceL(const RMmfIpcMessage& aMessage);
 
 	/**
+		Method to service signal DevSound to play tone sequence operation
+		request that has already completed, but not finished due to a
+		pre-emption clash during its commit cycle(s).
+		Leaves on failure.
+		@return void
+	*/
+	void DoAlreadyCompletedPlayToneSequenceL();
+
+	/**
 		Method to service signal DevSound to play fixed sequence operation
 		request.
 		Leaves on failure.
@@ -494,6 +571,15 @@
 	TBool DoPlayFixedSequenceL(const RMmfIpcMessage& aMessage);
 
 	/**
+		Method to service signal DevSound to play fixed sequence operation
+		request that has already completed, but not finished due to a
+		pre-emption clash during its commit cycle(s).
+		Leaves on failure.
+		@return void
+	*/
+	void DoAlreadyCompletedPlayFixedSequenceL();
+
+	/**
 		Method to service signal DevSound to initilize DTMF String operation
 		request.
 		Leaves on failure.
@@ -1313,6 +1399,9 @@
 
 	// from MDevSoundAdaptationObserver
 	TBool AdaptorControlsContext() const;
+	void PreemptionClash();
+	void PreemptionClashWithStateChange();
+    void NotifyError(TInt aError);
 
 	/**
 		MDevSoundAdaptationObserver callback.
@@ -1383,6 +1472,18 @@
 	void DoServiceRequestL(const RMmfIpcMessage& aMessage);
 
 	/*
+	Services the first request of queue for a pseudo asynchronous function that has already completed,
+	but needs to be re-applied again due to pre-emption clash.
+	*/
+	void DoServiceAlreadyCompletedRequestL(const TInt aFunction);
+
+	/*
+	Handles the first request of queue for a pseudo asynchronous function that has already completed,
+	but needs to be re-applied again due to pre-emption clash.
+	*/
+	void HandleAlreadyCompletedRequest();
+
+	/*
 	Services the first request at the FIFO
 	*/
 	void DoServiceNextRequestL();
@@ -1451,6 +1552,11 @@
 	static TInt AsyncQueueStartCallback(TAny* aPtr);
 	void AsyncQueueStartCallback();
 
+	void ResetNotifiedError();
+	TInt NotifiedError() const;
+
+	TBool NeedToQueue() const;
+
 protected:	// Data
 	CMMFDevSoundAdaptation* iAdapter;
 
@@ -1502,6 +1608,13 @@
 	
 	CActiveSchedulerWait*		iClosingWait;
 	CAsyncCallBack*				iAsyncQueueStart;
+
+	TInt iRedoFunction;
+	TMMFDevSoundProxySettingsPckg iCachedClientData;
+	TInt iSeqNum;
+	TBool iPreemptionClash;
+	TInt iNotifiedError;
+
 	};
 
 #endif // MMFDEVSOUNDSESSION_H
--- a/devsoundextensions/effects/Loudness/LoudnessEffect/Src/LoudnessBase.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsoundextensions/effects/Loudness/LoudnessEffect/Src/LoudnessBase.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -78,6 +78,7 @@
 	if ( !loudnessProxy )
 		{
 		DEBPRN1("No Adaptation Support - leaving");
+		CleanupStack::Pop(customInterface);
 		User::Leave(KErrNotSupported);
 		}
 
@@ -156,6 +157,7 @@
 	if ( !loudnessProxy )
 		{
 		DEBPRN1("No Adaptation Support - leaving");
+		CleanupStack::Pop(customInterface);
 		User::Leave(KErrNotSupported);
 		}
 
@@ -187,6 +189,7 @@
 	if ( !loudnessProxy )
 		{
 		DEBPRN1("No Adaptation Support - leaving");
+		CleanupStack::Pop(customInterface);
 		User::Leave(KErrNotSupported);
 		}
 
@@ -273,6 +276,7 @@
 	if ( !loudnessProxy )
 		{
 		DEBPRN1("No Adaptation Support - leaving");
+		CleanupStack::Pop(customInterface);
 		User::Leave(KErrNotSupported);
 		}
 
@@ -330,6 +334,7 @@
 	if ( !loudnessProxy )
 		{
 		DEBPRN1("No Adaptation Support - leaving");
+		CleanupStack::Pop(customInterface);
 		User::Leave(KErrNotSupported);
 		}
 
@@ -361,6 +366,7 @@
 	if ( !loudnessProxy )
 		{
 		DEBPRN1("No Adaptation Support - leaving");
+		CleanupStack::Pop(customInterface);
 		User::Leave(KErrNotSupported);
 		}
 
@@ -392,6 +398,7 @@
 	if ( !loudnessProxy )
 		{
 		DEBPRN1("No Adaptation Support - leaving");
+		CleanupStack::Pop(customInterface);
 		User::Leave(KErrNotSupported);
 		}
 
--- a/devsoundextensions/effectspresets/rom/EffectsPresets.iby	Wed Mar 31 23:56:23 2010 +0300
+++ b/devsoundextensions/effectspresets/rom/EffectsPresets.iby	Wed Apr 14 17:32:53 2010 +0300
@@ -25,9 +25,6 @@
 file=ABI_DIR\BUILD_DIR\EnvironmentalReverbUtility.dll		SHARED_LIB_DIR\EnvironmentalReverbUtility.dll
 file=ABI_DIR\BUILD_DIR\StereoWideningUtility.dll		SHARED_LIB_DIR\StereoWideningUtility.dll
 
-//CenRep Keys Backup for Audio Equalizer Utility
-data=DATAZ_\private\10207A8F\backup_registration.xml	private\10207A8F\backup_registration.xml
-
 // Effect Presets
 data=ZSYSTEM\install\EffectsPresets_Stub.SIS    System\Install\EffectsPresets_Stub.SIS
 
--- a/imagingandcamerafws/imagingunittest/TSU_ICL_COD_03/scripts/TSU_ICL_COD_03.script	Wed Mar 31 23:56:23 2010 +0300
+++ b/imagingandcamerafws/imagingunittest/TSU_ICL_COD_03/scripts/TSU_ICL_COD_03.script	Wed Apr 14 17:32:53 2010 +0300
@@ -529,3 +529,6 @@
 //AKAL-7YHLPR : Crash found in Themes Thread. Memory corruption with Gif image.
 RUN_TEST_STEP -1, TSU_ICL_COD_03, MM-ICL-COD-U-5108-HP
 TEST_COMPLETE
+//DEF144646 : Genius Case #144754: Nokia N97-1: Israel: N97 TIFF files not displayed properly. 
+RUN_TEST_STEP -1, TSU_ICL_COD_03, MM-ICL-COD-U-5109-HP 
+TEST_COMPLETE 
--- a/imagingandcamerafws/imagingunittest/TSU_ICL_COD_03/src/ICLCodecDefectTestStep.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/imagingandcamerafws/imagingunittest/TSU_ICL_COD_03/src/ICLCodecDefectTestStep.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -10326,3 +10326,79 @@
     CleanupStack::PopAndDestroy(3); //listener, bitmap, decoder
     return result;
     }
+
+//DEF144646 : Genius Case #144754: Nokia N97-1: Israel: N97 TIFF files not displayed properly. 
+    RTestStep_5109::RTestStep_5109(CTestSuite* aSuite) 
+        { 
+        iSuite = aSuite; 
+        iTestStepName = _L("MM-ICL-COD-U-5109-HP"); 
+        } 
+      
+    void RTestStep_5109::Close() 
+        { 
+        delete iScheduler; 
+        iScheduler = NULL; 
+        iFs.Close(); 
+        RFbsSession::Disconnect(); 
+        } 
+      
+    RTestStep_5109* RTestStep_5109::NewL(CTestSuite* aSuite) 
+        { 
+        if (!aSuite) 
+            { 
+            User::Leave(KErrArgument);         
+            } 
+        return new(ELeave) RTestStep_5109(aSuite); 
+        } 
+      
+    TVerdict RTestStep_5109::OpenL() 
+        { 
+        User::LeaveIfError(RFbsSession::Connect()); 
+        User::LeaveIfError(iFs.Connect()); 
+      
+        iScheduler = new(ELeave) CActiveScheduler(); 
+        CActiveScheduler::Install(iScheduler); 
+         
+        return EPass; 
+        } 
+      
+    /* 
+     * Test added for PDEF144975: TIFF files not displayed properly 
+     * The test is to check the decoding a test tif image.  
+     */ 
+    TVerdict RTestStep_5109::DoTestStepL() 
+        { 
+        INFO_PRINTF1(_L("PDEF144975: TIFF files not displayed properly")); 
+        INFO_PRINTF1(_L("Test is to check the decoding of below tif image")); 
+        _LIT(KTifImage, "c:\\tsu_icl_cod_03\\3178500m.tif"); 
+        CImageDecoder* decoder = NULL; 
+        //create decoder  
+        decoder = CImageDecoder::FileNewL(iFs, KTifImage, CImageDecoder::EOptionNone); 
+        CleanupStack::PushL(decoder); 
+         
+        //Get frameinformation 
+        TInt frameNo = 0; 
+        const TFrameInfo& frameInfo = decoder->FrameInfo(frameNo); 
+         
+        //Create a destination bitmap 
+        CFbsBitmap* bitmap = new (ELeave) CFbsBitmap; 
+        TInt err = bitmap->Create(frameInfo.iOverallSizeInPixels, frameInfo.iFrameDisplayMode); 
+        User::LeaveIfError(err); 
+        CleanupStack::PushL(bitmap); 
+         
+        CActiveListener* listener = new (ELeave) CActiveListener; 
+        CleanupStack::PushL(listener); 
+        TVerdict result = EPass; 
+         
+        //decode the frame. 
+        listener->InitialiseActiveListener(); 
+        decoder->Convert(&listener->iStatus, *bitmap, frameNo); 
+        CActiveScheduler::Start(); 
+        err = listener->iStatus.Int(); 
+        if(err != KErrNone) 
+          { 
+          result = EFail; //fail if couldn't decode a frame. 
+          } 
+        CleanupStack::PopAndDestroy(3); //listener, bitmap, decoder 
+        return result; 
+        }
--- a/imagingandcamerafws/imagingunittest/TSU_ICL_COD_03/src/ICLCodecDefectTestStep.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/imagingandcamerafws/imagingunittest/TSU_ICL_COD_03/src/ICLCodecDefectTestStep.h	Wed Apr 14 17:32:53 2010 +0300
@@ -2264,4 +2264,21 @@
     CActiveScheduler* iScheduler;
     };
 
+//DEF144646 : Genius Case #144754: Nokia N97-1: Israel: N97 TIFF files not displayed properly. 
+    NONSHARABLE_CLASS(RTestStep_5109): public RICLCodecDefectTestStep 
+        { 
+    public: 
+        static RTestStep_5109* NewL(CTestSuite* aSuite); 
+        // From RICLCodecDefectTestStep 
+        TVerdict OpenL(); 
+        TVerdict DoTestStepL(); 
+        void Close(); 
+             
+    private: 
+        RTestStep_5109(CTestSuite* aSuite); 
+             
+    private: 
+        RFs iFs; 
+        CActiveScheduler* iScheduler; 
+        }; 
 #endif // ICLCODECDEFECTTESTSTEP_H
--- a/imagingandcamerafws/imagingunittest/TSU_ICL_COD_03/src/ICLCodecDefectTestSuite.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/imagingandcamerafws/imagingunittest/TSU_ICL_COD_03/src/ICLCodecDefectTestSuite.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -128,6 +128,7 @@
 	AddTestStepL(RTestStep_5113::NewL(this));
 	AddTestStepL(RTestStep_5114::NewL(this));
 	AddTestStepL(RTestStep_5108::NewL(this));
+        AddTestStepL(RTestStep_5109::NewL(this));
 	}
 
 void CICLCodecDefectTestSuite::InitSystemPath()
--- a/mdfdevvideoextensions/nga_mdf_postprocessor/data/nga_mdf_postprocessor_stub.pkg	Wed Mar 31 23:56:23 2010 +0300
+++ b/mdfdevvideoextensions/nga_mdf_postprocessor/data/nga_mdf_postprocessor_stub.pkg	Wed Apr 14 17:32:53 2010 +0300
@@ -28,8 +28,3 @@
 ; Unique Vendor name
 :"Nokia"
 
-"\epoc32\release\armv5\urel\NGAPostProcHwDevice.dll"-"!:\sys\bin\NGAPostProcHwDevice.dll"
-
-"\epoc32\data\z\resource\plugins\NGAPostProcHwDevice.RSC"-"!:\resource\plugins\NGAPostProcHwDevice.RSC"
-
-
Binary file mdfdevvideoextensions/nga_mdf_postprocessor/data/nga_mdf_postprocessor_stub.sis has changed
--- a/mdfdevvideoextensions/nga_mdf_postprocessor/inc/NGAPostProcHwDevice.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/mdfdevvideoextensions/nga_mdf_postprocessor/inc/NGAPostProcHwDevice.h	Wed Apr 14 17:32:53 2010 +0300
@@ -1062,6 +1062,7 @@
     TInt                                		iOverflowPictureCounter;
     TInt 								    	iVideoFrameBufSize;	
     TBool 										iResourceLost;
+    TBool 										iRedrawDone;
     
     //-- members for buffer management --
     MMmfVideoBufferManagementObserver*  		iVBMObserver;
--- a/mdfdevvideoextensions/nga_mdf_postprocessor/src/NGAPostProcHwDevice.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mdfdevvideoextensions/nga_mdf_postprocessor/src/NGAPostProcHwDevice.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -94,6 +94,7 @@
             iOverflowPictureCounter(0),
             iVideoFrameBufSize(0),
             iResourceLost(EFalse),
+            iRedrawDone(EFalse),
             iVBMObserver(NULL),
             count(0),
             iSurfaceMask(surfaceHints::EAllowAllExternals),
@@ -141,6 +142,10 @@
     {
         TVideoPicture* pic = iVBMBufferReferenceQ[0];
         iVBMBufferReferenceQ.Remove(0);
+        if (iColorConversionQ.Count()>0)
+    	{
+	        iColorConversionQ.Remove(0);
+	    }
 
         if (pic->iHeader) delete pic->iHeader;
         delete pic->iData.iRawData;
@@ -153,6 +158,9 @@
     iVBMBufferReferenceQ.Reset();
     iVBMBufferReferenceQ.Close();
     
+    iColorConversionQ.Reset();
+    iColorConversionQ.Close();
+    
     iVBMBufferQ.Reset();
     iVBMBufferQ.Close();
     
@@ -167,7 +175,10 @@
     	if(!iSurfaceId.IsNull())
     	{
     		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]::UnregisterSurface"), this);
-    		iWsSession.UnregisterSurface(0, iSurfaceId);
+    		for(TInt i=0;i < iWsSession.NumberOfScreens();i++)
+    		{
+    			iWsSession.UnregisterSurface(i, iSurfaceId);
+    		}
         	iSurfaceHandler->DestroySurface(iSurfaceId);
     	}
         delete iSurfaceHandler;
@@ -826,7 +837,7 @@
 { 
 	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Redraw ++"), this);
 	TInt err = KErrNone;
-	if(iResourceLost)
+	if(iResourceLost && !iRedrawDone)
 	{
         err = AddHints();
         if (err != KErrNone)
@@ -836,6 +847,7 @@
             iProxy->MdvppFatalError(this, err);	
             return;   
         }
+        PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Redraw registering the temp surface"), this);
 		err = RegisterSurface(iSurfaceId);
 		if (err != KErrNone)
 		{
@@ -846,10 +858,10 @@
 			iProxy->MdvppFatalError(this, err);	
 			return;   				
 		}
-
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Redraw registering the temp surface done"), this);
         iSessionManager->PostPicture(iSurfaceId, 0, 1, EFalse);
         PublishSurfaceCreated();
-        iResourceLost = EFalse;
+        iRedrawDone = ETrue;
     }
     PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:Redraw --"), this);
 }
@@ -1290,7 +1302,10 @@
 	if(!aSurfaceId.IsNull())
 	{
 		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvssSurfaceRemovedL(): UnregisterSurface ID = 0x%x"), this, aSurfaceId );
-		iWsSession.UnregisterSurface(0, aSurfaceId);
+		for(TInt i=0;i < iWsSession.NumberOfScreens();i++)
+		{
+			iWsSession.UnregisterSurface(i, aSurfaceId);
+		}
 		iSurfaceHandler->DestroySurface(aSurfaceId);
 	}
 		
@@ -1326,12 +1341,30 @@
 void CNGAPostProcHwDevice::MmvroResourcesLost(TUid )
 {
     PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvroResourcesLost ++"), this);
-	iResourceLost = ETrue;
-	Pause();
-	ReleaseInputQ();
-	iSessionManager->CancelUpdate();
-	ReleaseProcessQ();
-	iVideoSurfaceObserver->MmvsoRemoveSurface();
+    if(!iResourceLost)
+    {
+		iResourceLost = ETrue;
+		iRedrawDone = EFalse;
+		Pause();
+		ReleaseInputQ();
+		iSessionManager->CancelUpdate();
+		ReleaseProcessQ();
+		iVideoSurfaceObserver->MmvsoRemoveSurface();
+	}
+	else if(iResourceLost && iRedrawDone)
+	{
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvroResourcesLost ResourceLost happening \
+					while Postprocessor is already in ResourceLoss state"), 
+	   				this);
+		iProxy->MdvppFatalError(this, KErrHardwareNotAvailable);	   				
+	    return;		
+	}
+	else
+	{
+		PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvroResourcesLost Ignoring the \
+					duplicate ResourceLoss call"), 
+	   				this);
+	}
     PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:MmvroResourcesLost --"), this);
 }
 
@@ -1881,7 +1914,12 @@
 TInt CNGAPostProcHwDevice::RegisterSurface(const TSurfaceId& aSurfaceId)
 {
 	PP_DEBUG(_L("CNGAPostProcHwDevice[%x]:RegisterSurface(): RegisterSurface ID = 0x%x"), this, aSurfaceId);
-	return(iWsSession.RegisterSurface(0, aSurfaceId));
+	TInt err = KErrNone;
+	for(TInt i=0; (i < iWsSession.NumberOfScreens() && err == KErrNone); i++)
+	{
+		err = iWsSession.RegisterSurface(i, aSurfaceId);
+	}	
+	return(err);
 }
 
 TInt CNGAPostProcHwDevice::IsGceReady()
@@ -2027,6 +2065,7 @@
 	    pOutPicture    = iColorConversionQ[0];
 	    iColorConversionQ.Remove(0);
 	    ConvertPostProcBuffer(aPicture, pOutPicture);
+	   	pOutPicture->iTimestamp = aPicture->iTimestamp;
 	    ReleasePicture(aPicture);    	    
     }				    
     else
--- a/mmlibs/mmfw/MMPFiles/client/MediaClientVideo.mmp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmlibs/mmfw/MMPFiles/client/MediaClientVideo.mmp	Wed Apr 14 17:32:53 2010 +0300
@@ -94,9 +94,4 @@
 	baseaddress	0x4F2A0000
 end
 
-MACRO __ENABLE_MEDIA_CLIENT_VIDEO_TRACE__
-
-
-                    
-
 SMPSAFE
--- a/mmlibs/mmfw/MMPFiles/client/mediaclientvideodisplay.mmp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmlibs/mmfw/MMPFiles/client/mediaclientvideodisplay.mmp	Wed Apr 14 17:32:53 2010 +0300
@@ -49,8 +49,4 @@
 
 nostrictdef
 
-MACRO __ENABLE_MEDIA_CLIENT_VIDEO_TRACE__
-
 SMPSAFE
-
-                    
--- a/mmlibs/mmfw/src/Client/Video/VideoPlayerBody.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmlibs/mmfw/src/Client/Video/VideoPlayerBody.h	Wed Apr 14 17:32:53 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2002-2010 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"
@@ -203,7 +203,6 @@
 	TInt EnableSubtitles(CMediaClientVideoDisplayBody& aDisplay);
 	TInt AddSubtitleConfig(CMediaClientVideoDisplayBody::TWindowData& aWindowData);
 	void GetSubtitleConfigFromWindowData(CMediaClientVideoDisplayBody::TWindowData& aWindowData, TMMFSubtitleWindowConfig& aConfig);
-	void UpdateSurfaceAndSubtitleConfigL(CMediaClientVideoDisplayBody& aDisplay,CMediaClientVideoDisplayBody::TWindowData& aWindowData, const TRect& aClipRect, TVideoRotation aRotation, const TRect& aCropRegion);
 #endif //SYMBIAN_MULTIMEDIA_SUBTITLE_SUPPORT
 
 private:
@@ -232,7 +231,6 @@
 								const TRect& aClipRect, const TRect& aVideoExtent, RWindow* aWindow2);
 	TInt SurfaceCreated();
 	TInt SurfaceParametersChanged();
-	TInt SetBackgroundSurface(const CMediaClientVideoDisplayBody& aDisplay);
 	TInt RemoveSurface(TBool aControllerEvent);
 	TInt SetAllBackgroundSurfaces();
 
--- a/mmlibs/mmfw/src/Client/Video/mediaclientvideodisplaybody.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmlibs/mmfw/src/Client/Video/mediaclientvideodisplaybody.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -166,6 +166,16 @@
     DEBUG_PRINTF2("CMediaClientVideoDisplayBody::AddDisplayWindowL - aAutoScaleType %d", aAutoScaleType);
     DEBUG_PRINTF3("CMediaClientVideoDisplayBody::AddDisplayWindowL - aHorizPos %d, aVertPos %d", aHorizPos, aVertPos);
 
+	if (!IsRotationValid(aRotation))
+		{
+		User::Leave(KErrArgument);
+		}
+
+	if (!IsAutoScaleTypeValid(aAutoScaleType))
+		{
+		User::Leave(KErrArgument);
+		}
+
 	TInt pos = iClientWindows.Find(aWindow->WsHandle(), TWindowData::CompareByWsHandle);
 	
 	if (pos != KErrNotFound)
@@ -295,7 +305,7 @@
     
     err = RedrawWindows(aCropRegion);
     
-    DEBUG_PRINTF("CMediaClientVideoDisplayBody::SurfaceCreated ---");
+    DEBUG_PRINTF2("CMediaClientVideoDisplayBody::SurfaceCreated --- Return error %d", err);
 	return err;
 	}
 
@@ -354,26 +364,47 @@
 
     if (!IsSurfaceCreated())
 		{
+		DEBUG_PRINTF("CMediaClientVideoDisplayBody::SurfaceParametersChanged --- Return error KErrNotSupproted");
 		return KErrNotSupported;
 		}
 
 	if (iSurfaceId != aSurfaceId)
 		{
+		DEBUG_PRINTF("CMediaClientVideoDisplayBody::SurfaceParametersChanged --- Return error KErrInUse");
 		return KErrInUse;
 		}
-	
-	iCropRect = aCropRect;
-	iAspectRatio = aAspectRatio;
-	
+
 	if (iEventHandler)
 		{
-		iEventHandler->MmsehSurfaceParametersChanged(iSurfaceId, iCropRect, iAspectRatio);
+		iEventHandler->MmsehSurfaceParametersChanged(iSurfaceId, aCropRect, aAspectRatio);
 		}
 
-	RedrawWindows(iCropRegion);
-	
-	DEBUG_PRINTF("CMediaClientVideoDisplayBody::SurfaceParametersChanged ---");
-	return KErrNone;
+	TInt error = KErrNone;
+	if (iCropRect != aCropRect || iAspectRatio != aAspectRatio)
+		{
+		// We only need to redraw if the aspect ratio has changed, or the area of the video to
+		// display (i.e the intersection of client crop region and surface crop rectangle) has changed.
+		TBool redraw = EFalse;
+		if (iAspectRatio != aAspectRatio || SurfaceCropRectChangeRequiresRedraw(iCropRect, aCropRect, iCropRegion))
+			{
+			redraw = ETrue;
+			}
+
+		iCropRect = aCropRect;
+		iAspectRatio = aAspectRatio;
+
+		if (redraw)
+			{
+			error = RedrawWindows(iCropRegion);
+			}
+		}
+	else
+		{
+		DEBUG_PRINTF("CMediaClientVideoDisplayBody::SurfaceParametersChanged - Surface parameters have not changed");
+		}
+
+	DEBUG_PRINTF2("CMediaClientVideoDisplayBody::SurfaceParametersChanged --- Return error %d", error);
+	return error;
 	}
 	
 TInt CMediaClientVideoDisplayBody::RedrawWindows(const TRect& aCropRegion)
@@ -402,7 +433,7 @@
 	return err;
 	}
 
-void CMediaClientVideoDisplayBody::UpdateCropRegionL(const TRect& aCropRegion, TInt aPos)
+void CMediaClientVideoDisplayBody::UpdateCropRegionL(const TRect& aCropRegion, TInt aPos, TBool aRedrawIndividualWindow)
     {
     DEBUG_PRINTF("CMediaClientVideoDisplayBody::UpdateCropRegionL +++");
 
@@ -413,14 +444,19 @@
         {
         if(prevCropRegion == aCropRegion)
             {
-            if(!iSwitchedToExternalDisplay)
+            if(!iSwitchedToExternalDisplay && aRedrawIndividualWindow)
                 {
                 User::LeaveIfError(SetBackgroundSurface(iClientWindows[aPos], aCropRegion));
                 }
             }
         else
             {
-            User::LeaveIfError(RedrawWindows(aCropRegion));
+			// We only need to redraw if the area of the video to display (i.e the
+			// intersection of client crop region and surface crop rectangle) has changed.
+			if (ClientCropRegionChangeRequiresRedraw(prevCropRegion, aCropRegion, iCropRect))
+				{
+				User::LeaveIfError(RedrawWindows(aCropRegion));
+				}
             }
         }
     DEBUG_PRINTF("CMediaClientVideoDisplayBody::UpdateCropRegionL ---");    
@@ -434,15 +470,29 @@
     DEBUG_PRINTF3("CMediaClientVideoDisplayBody::SetAutoScaleL - aHorizPos %d, aVertPos %d", aHorizPos, aVertPos);
     DEBUG_PRINTF5("CMediaClientVideoDisplayBody::SetAutoScaleL - aCropRegion %d,%d - %d,%d", aCropRegion.iTl.iX, aCropRegion.iTl.iY, aCropRegion.iBr.iX, aCropRegion.iBr.iY);
 
+	if (!IsAutoScaleTypeValid(aScaleType))
+		{
+		User::Leave(KErrArgument);
+		}
+
     TInt pos = iClientWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle);
 	User::LeaveIfError(pos);
-	
-	iClientWindows[pos].iAutoScaleType = aScaleType;
-	iClientWindows[pos].iHorizPos = aHorizPos;
-	iClientWindows[pos].iVertPos = aVertPos;
 
-	UpdateCropRegionL(aCropRegion, pos);
-	
+	TBool parameterChanged = EFalse;
+	if (aScaleType != iClientWindows[pos].iAutoScaleType || aHorizPos != iClientWindows[pos].iHorizPos || aVertPos != iClientWindows[pos].iVertPos)
+		{
+		iClientWindows[pos].iAutoScaleType = aScaleType;
+		iClientWindows[pos].iHorizPos = aHorizPos;
+		iClientWindows[pos].iVertPos = aVertPos;
+		parameterChanged = ETrue;
+		}
+	else
+		{
+		DEBUG_PRINTF("CMediaClientVideoDisplayBody::SetAutoScaleL - Scale parameters have not changed");
+		}
+
+	UpdateCropRegionL(aCropRegion, pos, parameterChanged);
+
 	DEBUG_PRINTF("CMediaClientVideoDisplayBody::SetAutoScaleL ---");
 	}
 	
@@ -454,12 +504,26 @@
     DEBUG_PRINTF2("CMediaClientVideoDisplayBody::SetRotationL - aRotation %d", aRotation);
     DEBUG_PRINTF5("CMediaClientVideoDisplayBody::SetRotationL - aCropRegion %d,%d - %d,%d", aCropRegion.iTl.iX, aCropRegion.iTl.iY, aCropRegion.iBr.iX, aCropRegion.iBr.iY);
 
+	if (!IsRotationValid(aRotation))
+		{
+		User::Leave(KErrArgument);
+		}
+
     TInt pos = iClientWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle);
 	User::LeaveIfError(pos);
-	
-	iClientWindows[pos].iRotation = aRotation;
 
-    UpdateCropRegionL(aCropRegion, pos);
+	TBool parameterChanged = EFalse;
+	if (aRotation != iClientWindows[pos].iRotation)
+		{
+		iClientWindows[pos].iRotation = aRotation;
+		parameterChanged = ETrue;
+		}
+	else
+		{
+		DEBUG_PRINTF("CMediaClientVideoDisplayBody::SetRotationL - Rotation has not changed");
+		}
+
+    UpdateCropRegionL(aCropRegion, pos, parameterChanged);
 
 	DEBUG_PRINTF("CMediaClientVideoDisplayBody::SetRotationL ---");
 	}
@@ -489,11 +553,22 @@
 		User::Leave(KErrArgument);
 		}
 
-	iClientWindows[pos].iScaleWidth = aWidthPercentage;
-	iClientWindows[pos].iScaleHeight = aHeightPercentage;
-	iClientWindows[pos].iAutoScaleType = EAutoScaleNone;
-	
-    UpdateCropRegionL(aCropRegion, pos);
+	TBool parameterChanged = EFalse;
+	if (aWidthPercentage != iClientWindows[pos].iScaleWidth ||
+	    aHeightPercentage != iClientWindows[pos].iScaleHeight ||
+		EAutoScaleNone != iClientWindows[pos].iAutoScaleType)
+		{
+		iClientWindows[pos].iScaleWidth = aWidthPercentage;
+		iClientWindows[pos].iScaleHeight = aHeightPercentage;
+		iClientWindows[pos].iAutoScaleType = EAutoScaleNone;
+		parameterChanged = ETrue;
+		}
+	else
+		{
+		DEBUG_PRINTF("CMediaClientVideoDisplayBody::SetScaleFactorL - Scale parameters have not changed");
+		}
+
+    UpdateCropRegionL(aCropRegion, pos, parameterChanged);
 	
     DEBUG_PRINTF("CMediaClientVideoDisplayBody::SetScaleFactorL ---");
 	}
@@ -515,23 +590,44 @@
     DEBUG_PRINTF2("CMediaClientVideoDisplayBody::SetAutoScaleL - aScaleType %d", aScaleType);
     DEBUG_PRINTF3("CMediaClientVideoDisplayBody::SetAutoScaleL - aHorizPos %d, aVertPos %d", aHorizPos, aVertPos);
     DEBUG_PRINTF5("CMediaClientVideoDisplayBody::SetAutoScaleL - aCropRegion %d,%d - %d,%d", aCropRegion.iTl.iX, aCropRegion.iTl.iY, aCropRegion.iBr.iX, aCropRegion.iBr.iY);
-	
+
+	if (!IsAutoScaleTypeValid(aScaleType))
+		{
+		User::Leave(KErrArgument);
+		}
+
     TRect prevCropRegion(iCropRegion);
 	iCropRegion = aCropRegion;
+	
+	TBool parameterChanged;
 	TInt count = iClientWindows.Count();
-	
+
 	for (TInt i = 0; i < count; ++i)
 		{
-		iClientWindows[i].iAutoScaleType = aScaleType;
-		iClientWindows[i].iHorizPos = aHorizPos;
-		iClientWindows[i].iVertPos = aVertPos;
-	    if (IsSurfaceCreated() && !iSwitchedToExternalDisplay)
+		parameterChanged = EFalse;
+		if (aScaleType != iClientWindows[i].iAutoScaleType || aHorizPos != iClientWindows[i].iHorizPos || aVertPos != iClientWindows[i].iVertPos)
+			{
+			iClientWindows[i].iAutoScaleType = aScaleType;
+			iClientWindows[i].iHorizPos = aHorizPos;
+			iClientWindows[i].iVertPos = aVertPos;
+			parameterChanged = ETrue;
+			}
+		else
+			{
+			DEBUG_PRINTF2("CMediaClientVideoDisplayBody::SetAutoScaleL - Scale parameters for window pos %d have not changed", i);
+			}
+
+		// We only need to redraw if the scale parameters have changed, or the area of the video
+		// to display (i.e the intersection of client crop region and surface crop rectangle) has changed.
+		if (IsSurfaceCreated() && !iSwitchedToExternalDisplay && (parameterChanged || ClientCropRegionChangeRequiresRedraw(prevCropRegion, aCropRegion, iCropRect)))
 			{
 			User::LeaveIfError(SetBackgroundSurface(iClientWindows[i], aCropRegion));
 			}
 		}
-	
-	if (IsSurfaceCreated() && iSwitchedToExternalDisplay && (aCropRegion != prevCropRegion))
+
+	// We only need to redraw if the area of the video to display (i.e the
+	// intersection of client crop region and surface crop rectangle) has changed.
+	if (IsSurfaceCreated() && iSwitchedToExternalDisplay && ClientCropRegionChangeRequiresRedraw(prevCropRegion, aCropRegion, iCropRect))
         {
         User::LeaveIfError(RedrawWindows(aCropRegion));
         }
@@ -545,20 +641,41 @@
     DEBUG_PRINTF2("CMediaClientVideoDisplayBody::SetRotationL - aRotation %d", aRotation);
     DEBUG_PRINTF5("CMediaClientVideoDisplayBody::SetRotationL - aCropRegion %d,%d - %d,%d", aCropRegion.iTl.iX, aCropRegion.iTl.iY, aCropRegion.iBr.iX, aCropRegion.iBr.iY);
 
+	if (!IsRotationValid(aRotation))
+		{
+		User::Leave(KErrArgument);
+		}
+
     TRect prevCropRegion(iCropRegion);
     iCropRegion = aCropRegion;
+
+	TBool parameterChanged;
 	TInt count = iClientWindows.Count();
 	
 	for (TInt i = 0; i < count; ++i)
 		{
-		iClientWindows[i].iRotation = aRotation;
-        if (IsSurfaceCreated() && !iSwitchedToExternalDisplay)
+		parameterChanged = EFalse;
+		if (aRotation != iClientWindows[i].iRotation)
+			{
+			iClientWindows[i].iRotation = aRotation;
+			parameterChanged = ETrue;
+			}
+		else
+			{
+			DEBUG_PRINTF2("CMediaClientVideoDisplayBody::SetRotationL - Rotation for window pos %d has not changed", i);
+			}
+
+		// We only need to redraw if the scale parameters have changed, or the area of the video
+		// to display (i.e the intersection of client crop region and surface crop rectangle) has changed.
+		if (IsSurfaceCreated() && !iSwitchedToExternalDisplay && (parameterChanged || ClientCropRegionChangeRequiresRedraw(prevCropRegion, aCropRegion, iCropRect)))
 			{
 			User::LeaveIfError(SetBackgroundSurface(iClientWindows[i], aCropRegion));
 			}
 		}
 	
-    if (IsSurfaceCreated() && iSwitchedToExternalDisplay && (aCropRegion != prevCropRegion))
+	// We only need to redraw if the area of the video to display (i.e the
+	// intersection of client crop region and surface crop rectangle) has changed.
+	if (IsSurfaceCreated() && iSwitchedToExternalDisplay && ClientCropRegionChangeRequiresRedraw(prevCropRegion, aCropRegion, iCropRect))
         {
         User::LeaveIfError(RedrawWindows(aCropRegion));
         }
@@ -579,20 +696,39 @@
 	
     TRect prevCropRegion(iCropRegion);
 	iCropRegion = aCropRegion;
+
+	TBool parameterChanged;
 	TInt count = iClientWindows.Count();
 	
 	for (TInt i = 0; i < count; ++i)
 		{
-		iClientWindows[i].iScaleWidth = aWidthPercentage;
-		iClientWindows[i].iScaleHeight = aHeightPercentage;
-		iClientWindows[i].iAutoScaleType = EAutoScaleNone;
-        if (IsSurfaceCreated() && !iSwitchedToExternalDisplay)
+		parameterChanged = EFalse;
+		
+		if (aWidthPercentage != iClientWindows[i].iScaleWidth ||
+		    aHeightPercentage != iClientWindows[i].iScaleHeight ||
+			EAutoScaleNone != iClientWindows[i].iAutoScaleType)
+			{
+			iClientWindows[i].iScaleWidth = aWidthPercentage;
+			iClientWindows[i].iScaleHeight = aHeightPercentage;
+			iClientWindows[i].iAutoScaleType = EAutoScaleNone;
+			parameterChanged = ETrue;
+			}
+		else
+			{
+			DEBUG_PRINTF2("CMediaClientVideoDisplayBody::SetScaleFactorL - Scale parameters for window pos %d have not changed", i);
+			}
+
+		// We only need to redraw if the scale parameters have changed, or the area of the video to
+		// display (i.e the intersection of client crop region and surface crop rectangle) has changed.
+		if (IsSurfaceCreated() && !iSwitchedToExternalDisplay && (parameterChanged || ClientCropRegionChangeRequiresRedraw(prevCropRegion, aCropRegion, iCropRect)))
 			{
 			User::LeaveIfError(SetBackgroundSurface(iClientWindows[i], aCropRegion));
 			}
 		}
-	
-    if (IsSurfaceCreated() && iSwitchedToExternalDisplay && (aCropRegion != prevCropRegion))
+
+	// We only need to redraw if the area of the video to display (i.e the
+	// intersection of client crop region and surface crop rectangle) has changed.
+	if (IsSurfaceCreated() && iSwitchedToExternalDisplay && ClientCropRegionChangeRequiresRedraw(prevCropRegion, aCropRegion, iCropRect))
         {
         User::LeaveIfError(RedrawWindows(aCropRegion));
         }
@@ -609,10 +745,24 @@
 	
 	TInt pos = iClientWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle);
 	User::LeaveIfError(pos);
-	
-	iClientWindows[pos].iClipRect = aWindowClipRect;
 
-    UpdateCropRegionL(aCropRegion, pos);
+	TBool parameterChanged = EFalse;
+	if (aWindowClipRect != iClientWindows[pos].iClipRect)
+		{
+		// We only want to redraw if the change in the clipping rectangle would result
+		// in a change to the area of the display used for the video.
+		// The video is always displayed in the intersection of the clipping rectangle
+		// and the video extent, so check if this has changed.
+		parameterChanged = IntersectionAreaChanged(iClientWindows[pos].iClipRect, aWindowClipRect, iClientWindows[pos].iVideoExtent);
+
+		iClientWindows[pos].iClipRect = aWindowClipRect;
+		}
+	else
+		{
+		DEBUG_PRINTF("CMediaClientVideoDisplayBody::SetWindowClipRectL - Clip rect parameter has not changed");
+		}
+
+    UpdateCropRegionL(aCropRegion, pos, parameterChanged);
 
     DEBUG_PRINTF("CMediaClientVideoDisplayBody::SetWindowClipRectL ---");
 	}
@@ -626,10 +776,19 @@
 
     TInt pos = iClientWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle);
 	User::LeaveIfError(pos);
-	
-	iClientWindows[pos].iVideoExtent = aVideoExtent;
 
-    UpdateCropRegionL(aCropRegion, pos);
+	TBool parameterChanged = EFalse;
+	if (aVideoExtent != iClientWindows[pos].iVideoExtent)
+		{
+		iClientWindows[pos].iVideoExtent = aVideoExtent;
+		parameterChanged = ETrue;
+		}
+	else
+		{
+		DEBUG_PRINTF("CMediaClientVideoDisplayBody::SetVideoExtentL - Video extent parameter has not changed");
+		}
+
+    UpdateCropRegionL(aCropRegion, pos, parameterChanged);
     
 	DEBUG_PRINTF("CMediaClientVideoDisplayBody::SetVideoExtentL ---");
 	}
@@ -1221,18 +1380,138 @@
         DEBUG_PRINTF2("CMediaClientVideoDisplayBody::SwitchSurface CreateExtDisplayHandlerL error %d", err);
         if(err == KErrNone)
             {
+            // Set background surface for external display window before removing from client windows.
+            // Required for switching of paused video
+            SetWindowArrayPtr2Ext();
+            RedrawWindows(iCropRegion);
+            SetWindowArrayPtr2Client();
             RemoveBackgroundSurface(ETrue);
             SetWindowArrayPtr2Ext();
-            RedrawWindows(iCropRegion);
             }
         }
     else if(iSwitchedToExternalDisplay)
         {
+        // Set background surface for clientwindows before removing from external display window.
+        // Required for switching of paused video
+        SetWindowArrayPtr2Client();
+        RedrawWindows(iCropRegion);
+        SetWindowArrayPtr2Ext();
         RemoveBackgroundSurface(ETrue);
         RemoveExtDisplayHandler();
         SetWindowArrayPtr2Client();
-        RedrawWindows(iCropRegion);
         }
 
     DEBUG_PRINTF("CMediaClientVideoDisplayBody::SwitchSurface ---");
     }
+
+TBool CMediaClientVideoDisplayBody::IsRotationValid(TVideoRotation aVideoRotation)
+	{
+	if (aVideoRotation == EVideoRotationNone ||
+	    aVideoRotation == EVideoRotationClockwise90 ||
+		aVideoRotation == EVideoRotationClockwise180 ||
+		aVideoRotation == EVideoRotationClockwise270)
+		{
+		return ETrue;
+		}
+
+	DEBUG_PRINTF2("CMediaClientVideoDisplayBody::IsRotationValid - Rotation %d not valid", aVideoRotation);
+	return EFalse;
+	}
+
+TBool CMediaClientVideoDisplayBody::IsAutoScaleTypeValid(TAutoScaleType aAutoScaleType)
+	{
+	if (aAutoScaleType == EAutoScaleNone ||
+	    aAutoScaleType == EAutoScaleBestFit ||
+	    aAutoScaleType == EAutoScaleClip ||
+	    aAutoScaleType == EAutoScaleStretch)
+		{
+		return ETrue;
+		}
+
+	DEBUG_PRINTF2("CMediaClientVideoDisplayBody::IsAutoScaleTypeValid - Auto scale %d not valid", aAutoScaleType);
+	return EFalse;
+	}
+
+/**
+Check whether a change in the surface crop rectangle would mean that the surface viewport calculated in SetBackgroundSurface would change.
+The surface viewport is the intersection of the surface crop rectangle and the client crop region
+*/
+TBool CMediaClientVideoDisplayBody::SurfaceCropRectChangeRequiresRedraw(TRect aOldSurfaceCropRect, TRect aNewSurfaceCropRect, TRect aClientCropRegion)
+	{
+	DEBUG_PRINTF("CMediaClientVideoDisplayBody::SurfaceCropRectChangeRequiresRedraw +++");
+	
+	// If aClientCropRegion is empty then it is not currently being used in the SetBackgroundSurface calculations.
+	// This means that only aOldSurfaceCropRect is being used to decide which part of the video is displayed.
+	// By setting aClientCropRect to the same as aOldSurfaceCropRect we ensure that only aOldSurfaceCropRect is
+	// used in the subsequent intersection area checks.
+	if (aClientCropRegion.IsEmpty())
+		{
+		DEBUG_PRINTF("CMediaClientVideoDisplayBody::SurfaceCropRectChangeRequiresRedraw - Client crop region is empty");		
+		aClientCropRegion = aOldSurfaceCropRect;
+		}
+
+	TBool ret = IntersectionAreaChanged(aOldSurfaceCropRect, aNewSurfaceCropRect, aClientCropRegion);
+
+	DEBUG_PRINTF2("CMediaClientVideoDisplayBody::SurfaceCropRectChangeRequiresRedraw --- ret = %d", ret);
+
+	return ret;
+	}
+
+/**
+Check whether a change in the client crop region would mean that the surface viewport calculated in SetBackgroundSurface would change.
+The surface viewport is the intersection of the surface crop rectangle and the client crop region
+*/
+TBool CMediaClientVideoDisplayBody::ClientCropRegionChangeRequiresRedraw(TRect aOldClientCropRegion, TRect aNewClientCropRegion, TRect aSurfaceCropRect)
+	{
+	DEBUG_PRINTF("CMediaClientVideoDisplayBody::ClientCropRegionChangeRequiresRedraw +++");
+
+	// If aOldClientCropRegion is empty then it is not currently being used in the SetBackgroundSurface calculations.
+	// This means that only aSurfaceCropRect is being used to decide which part of the video is displayed. By
+	// setting aOldClientCropRegion to the same as aSurfaceCropRect we ensure that only aSurfaceCropRect is
+	// used in the subsequent intersection area checks.
+	if (aOldClientCropRegion.IsEmpty())
+		{
+		DEBUG_PRINTF("CMediaClientVideoDisplayBody::ClientCropRegionChangeRequiresRedraw - Old client crop region is empty");
+		aOldClientCropRegion = aSurfaceCropRect;
+		}
+
+	// If aNewClientCropRegion is empty then it will not be used in the SetBackgroundSurface calculations.
+	// This means that only aSurfaceCropRect will impact which part of the video is displayed. By
+	// setting aNewClientCropRegion to the same as aSurfaceCropRect we ensure that only aSurfaceCropRect is
+	// used in the subsequent intersection area checks.
+	if (aNewClientCropRegion.IsEmpty())
+		{
+		DEBUG_PRINTF("CMediaClientVideoDisplayBody::ClientCropRegionChangeRequiresRedraw - New client crop region is empty");
+		aNewClientCropRegion = aSurfaceCropRect;
+		}
+
+	TBool ret = IntersectionAreaChanged(aOldClientCropRegion, aNewClientCropRegion, aSurfaceCropRect);
+
+	DEBUG_PRINTF2("CMediaClientVideoDisplayBody::ClientCropRegionChangeRequiresRedraw --- ret = %d", ret);
+
+	return ret;
+	}
+
+/**
+Check whether the change in size of a rectangle means its intersection with another rectangle has changed.
+This is used to check whether changes in things like the surface crop rectangle, client crop region, and window clip rectangle, would mean
+the area of video displayed would change.
+*/
+TBool CMediaClientVideoDisplayBody::IntersectionAreaChanged(TRect aOldRect, TRect aNewRect, TRect aOtherRect)
+	{
+	DEBUG_PRINTF5("CMediaClientVideoDisplayBody::IntersectionAreaChanged - aOldRect %d,%d - %d,%d", aOldRect.iTl.iX, aOldRect.iTl.iY, aOldRect.iBr.iX, aOldRect.iBr.iY);
+	DEBUG_PRINTF5("CMediaClientVideoDisplayBody::IntersectionAreaChanged - aNewRect %d,%d - %d,%d", aNewRect.iTl.iX, aNewRect.iTl.iY, aNewRect.iBr.iX, aNewRect.iBr.iY);
+	DEBUG_PRINTF5("CMediaClientVideoDisplayBody::IntersectionAreaChanged - aOtherRect %d,%d - %d,%d", aOtherRect.iTl.iX, aOtherRect.iTl.iY, aOtherRect.iBr.iX, aOtherRect.iBr.iY);
+
+	aOldRect.Intersection(aOtherRect);
+	aNewRect.Intersection(aOtherRect);
+
+	if (aOldRect != aNewRect)
+		{
+		DEBUG_PRINTF("CMediaClientVideoDisplayBody::IntersectionAreaChanged - Intersection area has changed");
+		return ETrue;
+		}
+
+	DEBUG_PRINTF("CMediaClientVideoDisplayBody::IntersectionAreaChanged - Intersection area has not changed");
+	return EFalse;
+	}
--- a/mmlibs/mmfw/src/Client/Video/mediaclientvideodisplaybody.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmlibs/mmfw/src/Client/Video/mediaclientvideodisplaybody.h	Wed Apr 14 17:32:53 2010 +0300
@@ -146,7 +146,7 @@
 	TInt SetBackgroundSurface(TWindowData& aWindowData, const TRect& aCropRegion);
 	TBool HasWindows() const;
 	
-    void UpdateCropRegionL(const TRect& aCropRegion, TInt aPos);
+    void UpdateCropRegionL(const TRect& aCropRegion, TInt aPos, TBool aRedrawIndividualWindow);
     void CreateExtDisplayPluginL();
     void RemoveExtDisplayPlugin();
     void CreateExtDisplayHandlerL();
@@ -155,6 +155,11 @@
     void SetWindowArrayPtr2Ext();
     void SwitchSurface();
     void UpdateFocus();
+	TBool IsRotationValid(TVideoRotation aVideoRotation);
+	TBool IsAutoScaleTypeValid(TAutoScaleType aAutoScaleType);
+	TBool SurfaceCropRectChangeRequiresRedraw(TRect aOldSurfaceCropRect, TRect aNewSurfaceCropRect, TRect aClientCropRegion);
+	TBool ClientCropRegionChangeRequiresRedraw(TRect aOldClientCropRegion, TRect aNewClientCropRegion, TRect aSurfaceCropRect);
+	TBool IntersectionAreaChanged(TRect aOldRect, TRect aNewRect, TRect aOtherRect);
 
     // MExtDisplayConnectionProviderCallback
     void MedcpcExtDisplayNotifyConnected(TBool aExtDisplayConnected);
--- a/mmlibs/mmfw/src/Client/Video/mediaclientvideotrace.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmlibs/mmfw/src/Client/Video/mediaclientvideotrace.h	Wed Apr 14 17:32:53 2010 +0300
@@ -18,7 +18,7 @@
 #ifndef MEDIACLIENTVIDEOTRACE_H_
 #define MEDIACLIENTVIDEOTRACE_H_
 
-#ifdef __ENABLE_MEDIA_CLIENT_VIDEO_TRACE__
+#ifdef _DEBUG
 
 #include <e32debug.h>
 
@@ -28,7 +28,7 @@
 #define DEBUG_PRINTF4(a,b,c,d) RDebug::Printf(a,b,c,d)
 #define DEBUG_PRINTF5(a, b, c, d, e) RDebug::Printf(a,b,c,d,e)
 
-#else // __ENABLE_MEDIA_CLIENT_VIDEO_TRACE__
+#else // _DEBUG
 
 #define DEBUG_PRINTF(a)
 #define DEBUG_PRINTF2(a, b)
@@ -36,6 +36,6 @@
 #define DEBUG_PRINTF4(a, b, c, d)
 #define DEBUG_PRINTF5(a, b, c, d, e)
 
-#endif // __ENABLE_MEDIA_CLIENT_VIDEO_TRACE__
+#endif // _DEBUG
 
 #endif // MEDIACLIENTVIDEOTRACE_H_
--- a/mmlibs/mmfw/src/Client/Video/mmfclientvideoplayerbody.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmlibs/mmfw/src/Client/Video/mmfclientvideoplayerbody.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -171,6 +171,7 @@
 #ifdef SYMBIAN_BUILD_GCE
 	,iGlobalScaleWidth(100.0f),
 	iGlobalScaleHeight(100.0f),
+	iGlobalAutoScaleType(EAutoScaleBestFit),  // Really need some platform specific way of defining this. Not everyone will want it.
 	iGlobalHorizPos(EHorizontalAlignCenter),
 	iGlobalVertPos(EVerticalAlignCenter)
 #endif
@@ -753,7 +754,15 @@
 				if (window.iRotation != aRotation)
 					{
 					// update config only if setting has actually changed
-					UpdateSurfaceAndSubtitleConfigL(*display, window, window.iClipRect, aRotation, iCropRegion);
+					display->SetRotationL(*window.iWindow, aRotation, iCropRegion);
+
+					if (iSubtitleUtility)
+						{
+						TMMFSubtitleWindowConfig config;
+						GetSubtitleConfigFromWindowData(window, config);
+
+						iSubtitleUtility->UpdateSubtitleConfig(config);
+						}
 					}
 				}
 #else
@@ -857,9 +866,11 @@
 		// Crop region setting is not sent to controller when graphics surfaces are used.
 		// If the surface has been created, perform crop region with the help of graphics surfaces;
 		// otherwise, just store the crop region info.
-		
-		iCropRegion = aCropRegion;
-		User::LeaveIfError(SetAllBackgroundSurfaces());
+		if (aCropRegion != iCropRegion)
+			{
+			iCropRegion = aCropRegion;
+			User::LeaveIfError(SetAllBackgroundSurfaces());
+			}
 		}
 #else
 	User::LeaveIfError(iVideoPlayControllerCustomCommands.SetCropRegion(aCropRegion));
@@ -1245,11 +1256,9 @@
 	TInt error2 = KErrNone;
 	for (TInt i = 0; i < count; ++i)
 		{
-		// ignore error and continue to set parameters
-		iActiveDisplays[i]->SurfaceParametersChanged(surfaceId, cropRect, aspectRatio);
+		error2 = iActiveDisplays[i]->SurfaceParametersChanged(surfaceId, cropRect, aspectRatio);
 		
-		// save the error for the first failure and attempt to redraw remaining displays
-		error2 = iActiveDisplays[i]->RedrawWindows(iCropRegion);
+		// Save the error for the first failure only
 		if ((error2 != KErrNone) && (error == KErrNone))
 			{
 			error = error2;
@@ -1745,7 +1754,15 @@
 	if (currentWin.iClipRect != aWindowClipRect)
 		{
 		// update config only if setting has actually changed
-		UpdateSurfaceAndSubtitleConfigL(*display, currentWin, aWindowClipRect, currentWin.iRotation, iCropRegion);
+		display->SetWindowClipRectL(aWindow, aWindowClipRect, iCropRegion);
+
+		if (iSubtitleUtility)
+			{
+			TMMFSubtitleWindowConfig config;
+			GetSubtitleConfigFromWindowData(currentWin, config);
+
+			iSubtitleUtility->UpdateSubtitleConfig(config);
+			}
 		}
 #else
 	display->SetWindowClipRectL(aWindow, aWindowClipRect, iCropRegion);
@@ -1822,7 +1839,15 @@
 	CMediaClientVideoDisplayBody::TWindowData& currentWin = windows[pos];
 	if (currentWin.iRotation != aRotation)
 		{
-		UpdateSurfaceAndSubtitleConfigL(*display, currentWin, currentWin.iClipRect, aRotation, iCropRegion);
+		display->SetRotationL(aWindow, aRotation, iCropRegion);
+
+		if (iSubtitleUtility)
+			{
+			TMMFSubtitleWindowConfig config;
+			GetSubtitleConfigFromWindowData(currentWin, config);
+
+			iSubtitleUtility->UpdateSubtitleConfig(config);
+			}
 		}
 #else
 	display->SetRotationL(aWindow, aRotation, iCropRegion);
@@ -2172,38 +2197,6 @@
 	return NULL;
 	}
 
-// Update the supplied window with the new clip rect and rotation
-// If updating of surface failed, this function leave after restoring the original aWindowData
-void CVideoPlayerUtility::CBody::UpdateSurfaceAndSubtitleConfigL(CMediaClientVideoDisplayBody& aDisplay,CMediaClientVideoDisplayBody::TWindowData& aWindowData, const TRect& aClipRect, TVideoRotation aRotation, const TRect& aCropRegion)
-	{
-	TRect oldClipRect = aWindowData.iClipRect;
-	TVideoRotation oldRotation = aWindowData.iRotation;
-	
-	aWindowData.iClipRect = aClipRect;
-	aWindowData.iRotation = aRotation;
-	
-	if (aDisplay.IsSurfaceCreated())
-		{
-		TInt err = aDisplay.SetBackgroundSurface(aWindowData, aCropRegion);
-		if (KErrNone != err)
-			{
-			aWindowData.iClipRect = oldClipRect;
-			aWindowData.iRotation = oldRotation;
-			User::Leave(err);
-			}
-		}
-	
-	// Set background was successful or surface was not created, so 
-	// update subtitle config if subtitles are enabled
-	if (iSubtitleUtility)
-		{
-		TMMFSubtitleWindowConfig config;
-		GetSubtitleConfigFromWindowData(aWindowData, config);
-
-		iSubtitleUtility->UpdateSubtitleConfig(config);
-		}
-	}
-
 void CVideoPlayerUtility::CBody::GetSubtitleConfigFromWindowData(CMediaClientVideoDisplayBody::TWindowData& aWindowData, TMMFSubtitleWindowConfig& aConfig)
 	{
 	aConfig.iWindowId = aWindowData.iWindow->WsHandle();
--- a/mmlibs/mmfw/tsrc/mmfintegrationtest/vclntavi/src/testvideoplayer2.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmlibs/mmfw/tsrc/mmfintegrationtest/vclntavi/src/testvideoplayer2.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2007-2010 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"
@@ -265,7 +265,6 @@
     iMediaClientVideoDisplay = CMediaClientVideoDisplay::NewL(displayId);
     
 	TRect videoExtent = clipRect;
-	TVideoRotation rotation = EVideoRotationNone;
 	TReal32 scaleWidth(100.0f);
 	TReal32 scaleHeight(100.0f);
 	TInt horizPos(EHorizontalAlignCenter);
@@ -276,11 +275,102 @@
 	TReal32 widthP; 
 	TReal32 heightP;
 	RWindow newWindow;
-	TVideoRotation videoRotation(EVideoRotationClockwise180);
+	
+	// Check for invalid rotation when adding new window
+	INFO_PRINTF1(_L("Testing invalid rotations for AddDisplayWindowL"));
+	TInt err = KErrNone;
+	TVideoRotation rotation = static_cast<TVideoRotation>(-1);
+	TRAP(err, iMediaClientVideoDisplay->AddDisplayWindowL(iWindow, clipRect, cropRegion, videoExtent, scaleWidth, scaleHeight, rotation, EAutoScaleBestFit, horizPos, vertPos, iWindow));
+	if (err != KErrArgument)
+		{
+		ERR_PRINTF1(_L("iVideoPlayer2->AddDisplayWindowL() did not leave with KErrArgument for negative rotation"));
+    	iTestStepResult = EFail;
+    	CActiveScheduler::Stop();
+    	return;
+		}
+
+	rotation = static_cast<TVideoRotation>(4);
+	TRAP(err, iMediaClientVideoDisplay->AddDisplayWindowL(iWindow, clipRect, cropRegion, videoExtent, scaleWidth, scaleHeight, rotation, EAutoScaleBestFit, horizPos, vertPos, iWindow));
+	if (err != KErrArgument)
+		{
+		ERR_PRINTF1(_L("iVideoPlayer2->AddDisplayWindowL() did not leave with KErrArgument for out of range rotation"));
+    	iTestStepResult = EFail;
+    	CActiveScheduler::Stop();
+    	return;
+		}
+
+	rotation = EVideoRotationNone;
+
+	// Check for invalid autoScaleType when adding new window
+	INFO_PRINTF1(_L("Testing invalid autoScaleType for AddDisplayWindowL"));
+	TAutoScaleType autoScaleType = static_cast<TAutoScaleType>(-1);
+	TRAP(err, iMediaClientVideoDisplay->AddDisplayWindowL(iWindow, clipRect, cropRegion, videoExtent, scaleWidth, scaleHeight, rotation, autoScaleType, horizPos, vertPos, iWindow));
+	if (err != KErrArgument)
+		{
+		ERR_PRINTF1(_L("iVideoPlayer2->AddDisplayWindowL() did not leave with KErrArgument for negative scale"));
+    	iTestStepResult = EFail;
+    	CActiveScheduler::Stop();
+    	return;
+		}
+
+	autoScaleType = static_cast<TAutoScaleType>(4);
+	TRAP(err, iMediaClientVideoDisplay->AddDisplayWindowL(iWindow, clipRect, cropRegion, videoExtent, scaleWidth, scaleHeight, rotation, autoScaleType, horizPos, vertPos, iWindow));
+	if (err != KErrArgument)
+		{
+		ERR_PRINTF1(_L("iVideoPlayer2->AddDisplayWindowL() did not leave with KErrArgument for out of range scale"));
+    	iTestStepResult = EFail;
+    	CActiveScheduler::Stop();
+    	return;
+		}
 	
 	iMediaClientVideoDisplay->AddDisplayWindowL(iWindow, clipRect, cropRegion, videoExtent, scaleWidth, scaleHeight, rotation, EAutoScaleBestFit, horizPos, vertPos, iWindow);
 	INFO_PRINTF1(_L("iMediaClientVideoDisplay->AddDisplayWindowL()"));   
-    
+
+	// Check for invalid rotation when setting rotation for window
+	INFO_PRINTF1(_L("Testing invalid rotation for SetRotationL"));
+	TVideoRotation videoRotation = static_cast<TVideoRotation>(-1);
+	TRAP(err, iMediaClientVideoDisplay->SetRotationL(*iWindow, videoRotation, cropRegion));
+	if (err != KErrArgument)
+		{
+		ERR_PRINTF1(_L("iVideoPlayer2->SetRotationL(window) did not leave with KErrArgument for negative value"));
+    	iTestStepResult = EFail;
+    	CActiveScheduler::Stop();
+    	return;
+		}
+
+	videoRotation = static_cast<TVideoRotation>(4);
+	TRAP(err, iMediaClientVideoDisplay->SetRotationL(*iWindow, videoRotation, cropRegion));
+	if (err != KErrArgument)
+		{
+		ERR_PRINTF1(_L("iVideoPlayer2->SetRotationL(window) did not leave with KErrArgument for out of range value"));
+    	iTestStepResult = EFail;
+    	CActiveScheduler::Stop();
+    	return;
+		}
+
+	// Check for invalid rotation when setting rotation for all windows
+	videoRotation = static_cast<TVideoRotation>(-1);
+	TRAP(err, iMediaClientVideoDisplay->SetRotationL(videoRotation, cropRegion));
+	if (err != KErrArgument)
+		{
+		ERR_PRINTF1(_L("iVideoPlayer2->SetRotationL() did not leave with KErrArgument for negative value"));
+    	iTestStepResult = EFail;
+    	CActiveScheduler::Stop();
+    	return;
+		}
+
+	videoRotation = static_cast<TVideoRotation>(4);
+	TRAP(err, iMediaClientVideoDisplay->SetRotationL(videoRotation, cropRegion));
+	if (err != KErrArgument)
+		{
+		ERR_PRINTF1(_L("iVideoPlayer2->SetRotationL() did not leave with KErrArgument for out of range value"));
+    	iTestStepResult = EFail;
+    	CActiveScheduler::Stop();
+    	return;
+		}
+
+	videoRotation = EVideoRotationClockwise180;
+
     iMediaClientVideoDisplay->SetRotationL(*iWindow, videoRotation, cropRegion);
     INFO_PRINTF1(_L("iMediaClientVideoDisplay->SetRotationL()"));
     
@@ -311,6 +401,49 @@
     
     iMediaClientVideoDisplay->SetWindowClipRectL(*iWindow, clipRect, cropRegion);
     INFO_PRINTF1(_L("iMediaClientVideoDisplay->SetWindowClipRectL()"));
+
+	// Check for invalid autoScaleType when setting autoScaleType for window
+	INFO_PRINTF1(_L("Testing invalid autoScaleType for SetAutoScaleL"));
+	autoScaleType = static_cast<TAutoScaleType>(-1);
+	TRAP(err, iMediaClientVideoDisplay->SetAutoScaleL(*iWindow, autoScaleType, horizPos, vertPos, cropRegion));
+	if (err != KErrArgument)
+		{
+		ERR_PRINTF1(_L("iVideoPlayer2->SetAutoScaleL(window) did not leave with KErrArgument for negative value"));
+    	iTestStepResult = EFail;
+    	CActiveScheduler::Stop();
+    	return;
+		}
+
+	autoScaleType = static_cast<TAutoScaleType>(4);
+	TRAP(err, iMediaClientVideoDisplay->SetAutoScaleL(*iWindow, autoScaleType, horizPos, vertPos, cropRegion));
+	if (err != KErrArgument)
+		{
+		ERR_PRINTF1(_L("iVideoPlayer2->SetAutoScaleL(window) did not leave with KErrArgument for out of range value"));
+    	iTestStepResult = EFail;
+    	CActiveScheduler::Stop();
+    	return;
+		}
+
+	// Check for invalid autoScaleType when setting autoScaleType for all windows
+	autoScaleType = static_cast<TAutoScaleType>(-1);
+	TRAP(err, iMediaClientVideoDisplay->SetAutoScaleL(autoScaleType, horizPos, vertPos, cropRegion));
+	if (err != KErrArgument)
+		{
+		ERR_PRINTF1(_L("iVideoPlayer2->SetAutoScaleL() did not leave with KErrArgument for negative value"));
+    	iTestStepResult = EFail;
+    	CActiveScheduler::Stop();
+    	return;
+		}
+
+	autoScaleType = static_cast<TAutoScaleType>(4);
+	TRAP(err, iMediaClientVideoDisplay->SetAutoScaleL(autoScaleType, horizPos, vertPos, cropRegion));
+	if (err != KErrArgument)
+		{
+		ERR_PRINTF1(_L("iVideoPlayer2->SetAutoScaleL() did not leave with KErrArgument for out of range value"));
+    	iTestStepResult = EFail;
+    	CActiveScheduler::Stop();
+    	return;
+		}
     
     iMediaClientVideoDisplay->SetAutoScaleL(EAutoScaleBestFit, horizPos, vertPos, cropRegion);
     INFO_PRINTF1(_L("iMediaClientVideoDisplay->SetAutoScaleL()"));
--- a/mmlibs/mmfw/tsrc/mmfunittest/DevSoundTest/a3fcistubextn/a3fcistubextn.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmlibs/mmfw/tsrc/mmfunittest/DevSoundTest/a3fcistubextn/a3fcistubextn.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -84,10 +84,19 @@
 	// the rest of the parameters can be ignored
 	TPckgBuf<TInt> volumePkg (aVol);
 	TMMFMessageDestinationPckg setVolDest (TMMFMessageDestination(KUidTestSetVolIf, 0));
-	TInt result = iCommand->CustomCommandSync(setVolDest, 0, volumePkg, KNullDesC8);
+	TInt result = iCommand->CustomCommandSync(setVolDest, ETestSetVolIfSetVolCommand, volumePkg, KNullDesC8);
 	return result;
 	}
 
+TInt CA3fClientCiStubExtn::Vol(TInt aMaxVol)
+    {
+    // again the key is is the destination package
+    TPckgBuf<TInt> maxVolPkg (aMaxVol);
+    TMMFMessageDestinationPckg setVolDest (TMMFMessageDestination(KUidTestSetVolIf, 0));
+    TInt result = iCommand->CustomCommandSync(setVolDest, ETestSetVolIfVolCommand, maxVolPkg, KNullDesC8);
+    return result;
+    }
+
 // __________________________________________________________________________
 // Server-side extension
 
@@ -170,24 +179,41 @@
 	
 TInt CSetVol::HandleMessageL(const RMmfIpcMessage& aMessage)
 	{
-	TPckgBuf<TInt> volPckg;
-	MmfMessageUtil::ReadL(aMessage, 1, volPckg);
-	UpdateA3fPointers(); // grab pointers to context, stream etc
-	SetVolumeL(volPckg());
-	
-	User::LeaveIfError(iContext->RegisterAudioContextObserver(*this));
-	
-	TInt error = iContext->Commit();
-	if (!error)
-		{
-		iError = KErrNone;
-		iWait->Start();
-		error = iError;
-		}
-	(void) iContext->UnregisterAudioContextObserver(*this);
-	
-	aMessage.Complete(error); 
-	return KErrNone; // KErrNone says we've handled the message
+    switch (aMessage.Function())
+        {
+        case ETestSetVolIfSetVolCommand:
+            {
+            TPckgBuf<TInt> volPckg;
+            MmfMessageUtil::ReadL(aMessage, 1, volPckg);
+            UpdateA3fPointers(); // grab pointers to context, stream etc
+            SetVolumeL(volPckg());
+
+            User::LeaveIfError(iContext->RegisterAudioContextObserver(*this));
+
+            TInt error = iContext->Commit();
+            if (!error)
+                {
+                iError = KErrNone;
+                iWait->Start();
+                error = iError;
+                }
+            (void) iContext->UnregisterAudioContextObserver(*this);
+
+            aMessage.Complete(error);
+            return KErrNone; // KErrNone says we've handled the message
+            }
+        case ETestSetVolIfVolCommand:
+            {
+            TPckgBuf<TInt> maxVolPckg;
+            MmfMessageUtil::ReadL(aMessage, 1, maxVolPckg);
+            UpdateA3fPointers(); // grab pointers to context, stream etc
+            TInt result = VolumeL(maxVolPckg());
+            aMessage.Complete(result);
+            return KErrNone; // KErrNone says we've handled the message
+            }
+        default:
+            return KErrArgument;
+        }
 	}
 	
 void CSetVol::UpdateA3fPointers()
@@ -224,6 +250,23 @@
 	User::LeaveIfError(gainControl->SetGain(channelGains));	
 	CleanupStack::PopAndDestroy(&channelGains);
 	}
+
+TInt CSetVol::VolumeL(TInt aMaxVolume)
+    {
+    RArray<TAudioChannelGain>   channelGains;
+    CleanupClosePushL(channelGains);
+    TInt maxGain;
+
+    MAudioGainControl* gainControl = static_cast<MAudioGainControl*>(iGain->Interface(KUidAudioGainControl));
+    User::LeaveIfError(gainControl->GetGain(channelGains));
+    User::LeaveIfError(gainControl->GetMaxGain(maxGain));
+
+    TInt basicVolume = (channelGains[0].iGain + channelGains[1].iGain) / 2;
+    TInt result = basicVolume * aMaxVolume / maxGain; // scale to 0 to maxVolume
+
+    CleanupStack::PopAndDestroy(&channelGains);
+    return result;
+    }
 	
 void CSetVol::ContextEvent(TUid aEvent, TInt aError)
 	{
--- a/mmlibs/mmfw/tsrc/mmfunittest/DevSoundTest/a3fcistubextn/a3fcistubextn.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmlibs/mmfw/tsrc/mmfunittest/DevSoundTest/a3fcistubextn/a3fcistubextn.h	Wed Apr 14 17:32:53 2010 +0300
@@ -26,6 +26,12 @@
 
 class CSetVol;
 
+enum TSetVolCommands
+    {
+    ETestSetVolIfSetVolCommand,
+    ETestSetVolIfVolCommand,
+    };
+
 /**
 *
 * CA3fClientCiStubExtn
@@ -52,6 +58,7 @@
 	
 	// from MTestSetVolIf
 	TInt SetVol(TInt aVolume);
+	TInt Vol(TInt aMaxVolume);
 	
 protected:
 	TUid iKey;
@@ -109,6 +116,7 @@
 	
 	void UpdateA3fPointers();
 	void SetVolumeL(TInt aVol);
+	TInt VolumeL(TInt aMaxVolume);
 	
 	MCustomInterface* iInterface; // not owned
 	MAudioContext* iContext;
--- a/mmlibs/mmfw/tsrc/mmfunittest/DevSoundTest/a3fcistubextn/testsetvol.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmlibs/mmfw/tsrc/mmfunittest/DevSoundTest/a3fcistubextn/testsetvol.h	Wed Apr 14 17:32:53 2010 +0300
@@ -24,6 +24,8 @@
 public:
 	// Backdoor to set volume - support via CIClient/ServerExtension
 	virtual TInt SetVol(TInt aVolume) = 0;
+	// Backdoor to volume - actually the gain value from the context scaled to 0..aMaxVol
+	virtual TInt Vol(TInt aMaxVol) = 0;
 	};
 
 
--- a/mmlibs/mmfw/tsrc/mmfunittest/DevSoundTest/src/TSU_MMF_DEVSOUND_STEP.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmlibs/mmfw/tsrc/mmfunittest/DevSoundTest/src/TSU_MMF_DEVSOUND_STEP.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -675,7 +675,7 @@
 		}
 	else
 		{
-		// Temp addition to check for alternative CI implementation
+		// Check for alternative CI implementation
 		MTestSetVolIf *volIf = static_cast<MTestSetVolIf*>(iMMFDevSound->CustomInterface(KUidTestSetVolIf));
 		if (volIf)
 			{
@@ -4435,9 +4435,16 @@
 			//note test does not make any assumptions as to what the supported datatypes are
 			if (numberOfSupportedDataTypes)
 				{
+				TUint32 testsFourCC = TFourCC(_L8("TST*")).FourCC(); // if any fourCc matches first three chars then we treat as test
 				for (TUint entryNumber = 0; entryNumber < numberOfSupportedDataTypes; entryNumber++)
 					{
 					TUint32 fourCC = supportedDataTypes[entryNumber].FourCC();
+					if ((testsFourCC&0xFFFFFF) == (fourCC&0xFFFFFF))
+						{
+						// comparison ignoring top byte - equates to last digit of fourCC
+						continue;
+						}
+					
 					ResetCallbacks();
 					TRAP(err,iMMFDevSound->InitializeL(*this, fourCC, prioritySettings.iState));
 					if ((err)||(iCallbackError))
@@ -4523,9 +4530,16 @@
 			//note test does not make any assumptions as to what the supported datatypes are
 			if (numberOfSupportedDataTypes)
 				{
+				TUint32 testsFourCC = TFourCC(_L8("TST*")).FourCC(); // if any fourCc matches first three chars then we treat as test
 				for (TUint entryNumber = 0; entryNumber < numberOfSupportedDataTypes; entryNumber++)
 					{
 					TUint32 fourCC = supportedDataTypes[entryNumber].FourCC();
+					if ((testsFourCC&0xFFFFFF) == (fourCC&0xFFFFFF))
+						{
+						// comparison ignoring top byte - equates to last digit of fourCC
+						continue;
+						}
+					
 					ResetCallbacks();
 					TRAP(err,iMMFDevSound->InitializeL(*this, fourCC, prioritySettings.iState));
 					if ((err)||(iCallbackError))
@@ -7561,7 +7575,7 @@
 			iDevSoundObserver1 = CMultiInitTestDevSoundObserver::NewL(this, EObserver1);
 			delete iDevSoundObserver2;
 			iDevSoundObserver2 = NULL;
-			iMMFDevSound->InitializeL(*iDevSoundObserver1, TUid::Uid(KMmfUidHwDevicePCM8ToPCM16), EMMFStatePlaying);
+			iMMFDevSound->InitializeL(*iDevSoundObserver1, KMMFFourCCCodePCM8, EMMFStatePlaying);
 			iTestState = EInit2Observer1;
 			}
 		else
@@ -7576,7 +7590,7 @@
 			iDevSoundObserver2 = CMultiInitTestDevSoundObserver::NewL(this, EObserver2);
 			delete iDevSoundObserver1;
 			iDevSoundObserver1 = NULL;
-			iMMFDevSound->InitializeL(*iDevSoundObserver2, TUid::Uid(KMmfUidHwDevicePCM8ToPCM16), EMMFStatePlaying);
+			iMMFDevSound->InitializeL(*iDevSoundObserver2, KMMFFourCCCodePCM8, EMMFStatePlaying);
 			INFO_PRINTF1(_L("Initialising with Observer2"));
 			iTestState = EInit2Observer2;
 			}
@@ -8682,6 +8696,23 @@
 									StopTest (KErrGeneral);
 									break;
 									}
+						        // Check the low-level a3f volume. Should have been applied by now
+						        MTestSetVolIf *volIf = static_cast<MTestSetVolIf*>(iMMFDevSound->CustomInterface(KUidTestSetVolIf));
+						        if (volIf)
+						            {
+						            TInt vol = volIf->Vol(iMMFDevSound->MaxVolume());
+	                                if (vol == iVolume)
+	                                    {
+	                                    INFO_PRINTF1(_L("Low-level volume returned equal previous set value as expected"));
+	                                    }
+	                                else
+	                                    {
+	                                    ERR_PRINTF3(_L("Low-level volume returned different set value = %d (expect %d)"), vol, iVolume);
+	                                    StopTest (KErrGeneral);
+	                                    break;
+	                                    }
+						            }
+
 								INFO_PRINTF1(_L("Call iMMFDevSound::GetPlayBalanceL for verifying."));
 								TInt getLSpeakerBalance = 0;
 								TInt getRSpeakerBalance = 0;
--- a/mmplugins/imagingplugins/codecs/TIFFCodec/TIFFCodec.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmplugins/imagingplugins/codecs/TIFFCodec/TIFFCodec.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -158,7 +158,7 @@
 		case EFinish:
 			{
 			err = iRecordTable->InsertRecordL(iIfdOffset, iIfdSize);
-			if (err != KErrNone)
+			if (err != KErrNone && err != KErrAlreadyExists)
 				{
 				User::Leave(KErrCorrupt);
 				}
--- a/mmplugins/mmfwplugins/src/Plugin/Format/MmfWAVFormat/mmfwavformat.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmplugins/mmfwplugins/src/Plugin/Format/MmfWAVFormat/mmfwavformat.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -951,12 +951,12 @@
 	//the sink buffer size will be used to determine the frame time.
 	//check media id &pass onto clip
 
+	//[ precondition the buffer is not null ]
+	__ASSERT_DEBUG( aBuffer, Panic( EPreconditionViolation ) );
+	
 	if ((aBuffer != NULL) && (!CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())))
 		User::Leave(KErrNotSupported);
 	
-	//[ precondition the buffer is not null ]
-	__ASSERT_DEBUG( aBuffer, Panic( EPreconditionViolation ) );
-	
 	//[ precondition it must be audio ]
 	if(aMediaId.iMediaType!=KUidMediaTypeAudio)
 		User::Leave(KErrNotSupported);
--- a/mmtestenv/mmtestfw/MMPFiles/TestFrameworkClient.mmp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmtestenv/mmtestfw/MMPFiles/TestFrameworkClient.mmp	Wed Apr 14 17:32:53 2010 +0300
@@ -25,6 +25,7 @@
 
 SOURCEPATH		../Source/TestFrameworkClient
 SOURCE			Log.cpp
+SOURCE			testfwclientsession.cpp
 SOURCE			TestSuite.cpp
 SOURCE			TestStep.cpp
 SOURCE			TestUtils.cpp
--- a/mmtestenv/mmtestfw/Source/TestFrameworkClient/Log.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmtestenv/mmtestfw/Source/TestFrameworkClient/Log.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -47,251 +47,6 @@
 
 /**
  *
- * Global : start a server
- * NOTE. Function is global static as only one server will ever run at any time
- * (there may be multiple client sessions)
- *
- * @return	"TInt"
- *			Error code (KErrNone if successful)
- *
- * @xxxx
- *
- */
-GLDEF_C TInt StartServer()
-// Start the server process/thread which lives in an (EPOC)EXE object
-	{
-	const TUidType serverUid(KNullUid, KNullUid, KTestFrameworkServerUid3);
-
-
-// EPOC is easy, we just create a new server process. Simultaneous launching
-// of two such processes should be detected when the second one attempts to
-// create the server object, failing with KErrAlreadyExists.
-
-	RProcess server;
-	TInt r = server.Create(KTestFrameworkServerImg, KNullDesC, serverUid);
-
-	if (r != KErrNone)
-		return r;
-
-	
-	TRequestStatus rendezvous;
-	server.Rendezvous(rendezvous);
-
-	if (rendezvous!=KRequestPending)
-		{
-		server.Kill(0);
-		}
-	else
-		{
-		server.Resume();
-		}
-
-
-	User::WaitForRequest(rendezvous);		// wait for start or death
-
-	// we can't use the 'exit reason' if the server panicked as this
-	// is the panic 'reason' and may be '0' which cannot be distinguished
-	// from KErrNone
-	if (rendezvous!=KErrNone)
-		{
-		server.Close();
-		}
-
-	// server started (at last). Cancel and consume the death-notification
-	// before reporting success
-	return rendezvous.Int();
-	}
-
-/**
- *
- * Constructor for RTestFrameworkClientSession
- *
- * @xxxx
- *
- */
-RTestFrameworkClientSession::RTestFrameworkClientSession()
-	{
-	}
-
-/**
- *
- * Client session : connect to server.
- * Will start a new server session if no server exists
- *
- * @return	"TInt"
- *			Error code (KErrNone if connect successful)
- *
- * @xxxx
- *
- */
-TInt RTestFrameworkClientSession::Connect()
-	{
-	// NOTE : this loop is ugly and can probably be rewritten to be more graceful
-	const TInt KNumRetries = 2;
-
-	TInt retry = KNumRetries;
-	for (;;)
-		{
-		TInt r = CreateSession(KTestFrameworkServerName, TVersion(KTestFrameworkServerMajorVersionNumber,
-																  KTestFrameworkServerMinorVersionNumber,
-																  KTestFrameworkServerBuildVersionNumber));
-		if (r == KErrNone)
-			{
-#ifdef __IPC_V2_PRESENT__
-			r = ShareAuto();
-#else
-			r = Share(RSessionBase::EAutoAttach);
-#endif
-			if (r!=KErrNone)
-				Close();
-			return r;
-			}
-		if (r != KErrNotFound && r != KErrServerTerminated)
-			{
-			return r;
-			}
-		if (--retry == 0)
-			return r;
-		r = StartServer();
-		if (r != KErrNone && r != KErrAlreadyExists)
-			return r;
-		}
-	}
-
-/**
- *
- * Request creation of an input window.
- * NOTE. For initialisation of input console only - unlikely to
- * be required by user
- *
- * @param	"TRectBuf& aAllocatedWindow"
- *			Window dimensions
- *
- * @param	"TRequestStatus& aReqStat"
- *			Request status
- *
- * @xxxx
- *
- */
-void RTestFrameworkClientSession::CreateInputWindow(TRectBuf& aAllocatedWindow, TRequestStatus& aReqStat)
-	{
-	SendReceiveResult(ECreateInputWindow, aAllocatedWindow, aReqStat);
-	}
-
-/**
- *
- * Request window change notifications
- * NOTE. For initialisation of input console only - unlikely to
- * be required by user
- *
- * @param	"TRectBuf& aNewWindow"
- *			New window dimensions
- *
- * @param	"TRequestStatus& aReqStat"
- *			Request status
- *
- * @xxxx
- *
- */
-void RTestFrameworkClientSession::NotifyIfWindowChange(TRectBuf& aNewWindow, TRequestStatus& aReqStat)
-	{
-	SendReceiveResult(ENotifyIfWindowChange, aNewWindow, aReqStat);
-	}
-
-/**
- *
- * Cancel window change notifications
- * NOTE. For initialisation of input console only - unlikely to
- * be required by user
- *
- * @return	"TInt"
- *			SendReceive error code
- *
- * @xxxx
- *
- */
-TInt RTestFrameworkClientSession::CancelNotifyIfWindowChange()
-	{
-	return SendReceive(ECancelNotifyIfWindowChange);
-	}
-
-
-/**
- *
- * Open a log server session
- *
- * @param	"const TDesC& aLogName"
- *			The log name
- *
- * @param	"TInt aLogMode"
- *			The log mode (a bitmask of TTestFrameworkLogMode)
- *
- * @xxxx
- *
- */
-void RTestFrameworkClientSession::OpenLog(const TDesC& aLogName, TInt aLogMode)
-	{
-	(void) SendReceive(EOpenLog, aLogName, aLogMode);
-	}
-
-/**
- *
- * Write message string to log server session
- *
- * @param	"const TDesC& aMsg"
- *			The message string
- *
- * @param	"TInt aLogMode"
- *			The log mode (a bitmask of TTestFrameworkLogMode)
- *
- * @xxxx
- *
- */
-void RTestFrameworkClientSession::WriteLog(const TDesC& aMsg, TInt aLogMode)
-	{
-	(void) SendReceive(EWriteLog, aMsg, aLogMode);
-	}
-
-/**
- *
- * Send close log message to server
- *
- * @xxxx
- *
- */
-void RTestFrameworkClientSession::CloseLog()
-	{
-	SendReceive(ECloseLog);
-	}
-
-/**
- *
- * Retrieve log status from server
- *
- * @return	"TInt"
- *			The log status (a bitmask of TTestFrameworkLogMode)
- *
- * @xxxx
- *
- */
-TInt RTestFrameworkClientSession::LogStatus()
-	{
-	TInt res = 0;
-	TPckgBuf<TInt> pckg;
-	TInt r = SendReceiveResult(ELogStatus, pckg);
-	if (r != KErrNone)
-	{
-		// RTestFrameworkClientSession does not log - 
-		// we can however return 0 to indicate an error (no outputs)
-		res = 0;
-	}
-	else
-		res = pckg();
-	return res;
-	}
-
-/**
- *
  * Static constructor for CLog.
  *
  *
--- a/mmtestenv/mmtestfw/Source/TestFrameworkClient/TestStep.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmtestenv/mmtestfw/Source/TestFrameworkClient/TestStep.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -183,7 +183,7 @@
  * @xxxx
  *
  */
-void RTestStep::SetSuite(CTestSuite* aSuite)
+EXPORT_C void RTestStep::SetSuite(CTestSuite* aSuite)
 	{
 	iSuite = aSuite;
 	}
@@ -198,7 +198,7 @@
  * @xxxx
  *
  */
-void RTestStep::SetResult(TVerdict aResult)
+EXPORT_C void RTestStep::SetResult(TVerdict aResult)
 	{
 	iTestStepResult = aResult;
 	}
@@ -213,7 +213,7 @@
  * @xxxx
  *
  */
-TPtrC RTestStep::StepName() const
+EXPORT_C TPtrC RTestStep::StepName() const
 	{
 	return iTestStepName;
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmtestenv/mmtestfw/Source/TestFrameworkClient/testfwclientsession.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -0,0 +1,266 @@
+// Copyright (c) 2010 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:
+// Client / server logging for Test Framework
+// NOTE : does NOT include secure API changes in EKA2
+// 
+//
+
+
+// Test system includes
+#include <testframework.h>
+
+/**
+ *
+ * Global : start a server
+ * NOTE. Function is global static as only one server will ever run at any time
+ * (there may be multiple client sessions)
+ *
+ * @return	"TInt"
+ *			Error code (KErrNone if successful)
+ *
+ * @xxxx
+ *
+ */
+GLDEF_C TInt StartServer()
+// Start the server process/thread which lives in an (EPOC)EXE object
+	{
+	const TUidType serverUid(KNullUid, KNullUid, KTestFrameworkServerUid3);
+
+
+// EPOC is easy, we just create a new server process. Simultaneous launching
+// of two such processes should be detected when the second one attempts to
+// create the server object, failing with KErrAlreadyExists.
+
+	RProcess server;
+	TInt r = server.Create(KTestFrameworkServerImg, KNullDesC, serverUid);
+
+	if (r != KErrNone)
+		return r;
+
+	
+	TRequestStatus rendezvous;
+	server.Rendezvous(rendezvous);
+
+	if (rendezvous!=KRequestPending)
+		{
+		server.Kill(0);
+		}
+	else
+		{
+		server.Resume();
+		}
+
+
+	User::WaitForRequest(rendezvous);		// wait for start or death
+
+	// we can't use the 'exit reason' if the server panicked as this
+	// is the panic 'reason' and may be '0' which cannot be distinguished
+	// from KErrNone
+	if (rendezvous!=KErrNone)
+		{
+		server.Close();
+		}
+
+	// server started (at last). Cancel and consume the death-notification
+	// before reporting success
+	return rendezvous.Int();
+	}
+
+/**
+ *
+ * Constructor for RTestFrameworkClientSession
+ *
+ * @xxxx
+ *
+ */
+RTestFrameworkClientSession::RTestFrameworkClientSession()
+	{
+	}
+
+/**
+ *
+ * Client session : connect to server.
+ * Will start a new server session if no server exists
+ *
+ * @return	"TInt"
+ *			Error code (KErrNone if connect successful)
+ *
+ * @xxxx
+ *
+ */
+TInt RTestFrameworkClientSession::Connect()
+	{
+	// NOTE : this loop is ugly and can probably be rewritten to be more graceful
+	const TInt KNumRetries = 2;
+
+	TInt retry = KNumRetries;
+	for (;;)
+		{
+		TInt r = CreateSession(KTestFrameworkServerName, TVersion(KTestFrameworkServerMajorVersionNumber,
+																  KTestFrameworkServerMinorVersionNumber,
+																  KTestFrameworkServerBuildVersionNumber));
+		if (r == KErrNone)
+			{
+#ifdef __IPC_V2_PRESENT__
+			r = ShareAuto();
+#else
+			r = Share(RSessionBase::EAutoAttach);
+#endif
+			if (r!=KErrNone)
+				Close();
+			return r;
+			}
+		if (r != KErrNotFound && r != KErrServerTerminated)
+			{
+			return r;
+			}
+		if (--retry == 0)
+			return r;
+		r = StartServer();
+		if (r != KErrNone && r != KErrAlreadyExists)
+			return r;
+		}
+	}
+
+/**
+ *
+ * Request creation of an input window.
+ * NOTE. For initialisation of input console only - unlikely to
+ * be required by user
+ *
+ * @param	"TRectBuf& aAllocatedWindow"
+ *			Window dimensions
+ *
+ * @param	"TRequestStatus& aReqStat"
+ *			Request status
+ *
+ * @xxxx
+ *
+ */
+void RTestFrameworkClientSession::CreateInputWindow(TRectBuf& aAllocatedWindow, TRequestStatus& aReqStat)
+	{
+	SendReceiveResult(ECreateInputWindow, aAllocatedWindow, aReqStat);
+	}
+
+/**
+ *
+ * Request window change notifications
+ * NOTE. For initialisation of input console only - unlikely to
+ * be required by user
+ *
+ * @param	"TRectBuf& aNewWindow"
+ *			New window dimensions
+ *
+ * @param	"TRequestStatus& aReqStat"
+ *			Request status
+ *
+ * @xxxx
+ *
+ */
+void RTestFrameworkClientSession::NotifyIfWindowChange(TRectBuf& aNewWindow, TRequestStatus& aReqStat)
+	{
+	SendReceiveResult(ENotifyIfWindowChange, aNewWindow, aReqStat);
+	}
+
+/**
+ *
+ * Cancel window change notifications
+ * NOTE. For initialisation of input console only - unlikely to
+ * be required by user
+ *
+ * @return	"TInt"
+ *			SendReceive error code
+ *
+ * @xxxx
+ *
+ */
+TInt RTestFrameworkClientSession::CancelNotifyIfWindowChange()
+	{
+	return SendReceive(ECancelNotifyIfWindowChange);
+	}
+
+
+/**
+ *
+ * Open a log server session
+ *
+ * @param	"const TDesC& aLogName"
+ *			The log name
+ *
+ * @param	"TInt aLogMode"
+ *			The log mode (a bitmask of TTestFrameworkLogMode)
+ *
+ * @xxxx
+ *
+ */
+void RTestFrameworkClientSession::OpenLog(const TDesC& aLogName, TInt aLogMode)
+	{
+	(void) SendReceive(EOpenLog, aLogName, aLogMode);
+	}
+
+/**
+ *
+ * Write message string to log server session
+ *
+ * @param	"const TDesC& aMsg"
+ *			The message string
+ *
+ * @param	"TInt aLogMode"
+ *			The log mode (a bitmask of TTestFrameworkLogMode)
+ *
+ * @xxxx
+ *
+ */
+void RTestFrameworkClientSession::WriteLog(const TDesC& aMsg, TInt aLogMode)
+	{
+	(void) SendReceive(EWriteLog, aMsg, aLogMode);
+	}
+
+/**
+ *
+ * Send close log message to server
+ *
+ * @xxxx
+ *
+ */
+void RTestFrameworkClientSession::CloseLog()
+	{
+	SendReceive(ECloseLog);
+	}
+
+/**
+ *
+ * Retrieve log status from server
+ *
+ * @return	"TInt"
+ *			The log status (a bitmask of TTestFrameworkLogMode)
+ *
+ * @xxxx
+ *
+ */
+TInt RTestFrameworkClientSession::LogStatus()
+	{
+	TInt res = 0;
+	TPckgBuf<TInt> pckg;
+	TInt r = SendReceiveResult(ELogStatus, pckg);
+	if (r != KErrNone)
+	{
+		// RTestFrameworkClientSession does not log - 
+		// we can however return 0 to indicate an error (no outputs)
+		res = 0;
+	}
+	else
+		res = pckg();
+	return res;
+	}
--- a/mmtestenv/mmtestfw/bwins/TESTFRAMEWORKCLIENTU.DEF	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmtestenv/mmtestfw/bwins/TESTFRAMEWORKCLIENTU.DEF	Wed Apr 14 17:32:53 2010 +0300
@@ -102,4 +102,7 @@
 	?Stop@CBusyTestUnit@@QAEXXZ @ 101 NONAME ; void CBusyTestUnit::Stop(void)
 	?Start@CBusyTestUnit@@QAEHVTTimeIntervalMicroSeconds32@@VTTimeIntervalMicroSeconds@@@Z @ 102 NONAME ; int CBusyTestUnit::Start(class TTimeIntervalMicroSeconds32, class TTimeIntervalMicroSeconds)
 	?GetHexFromConfig@RTestStep@@IAEHABVTDesC16@@0AAH@Z @ 103 NONAME ; int RTestStep::GetHexFromConfig(class TDesC16 const &, class TDesC16 const &, int &)
+	?SetResult@RTestStep@@QAEXW4TVerdict@@@Z @ 104 NONAME ; void RTestStep::SetResult(enum TVerdict)
+	?StepName@RTestStep@@QBE?AVTPtrC16@@XZ @ 105 NONAME ; class TPtrC16 RTestStep::StepName(void) const
+	?SetSuite@RTestStep@@QAEXPAVCTestSuite@@@Z @ 106 NONAME ; void RTestStep::SetSuite(class CTestSuite *)
 
--- a/mmtestenv/mmtestfw/eabi/TestFrameworkClientU.DEF	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmtestenv/mmtestfw/eabi/TestFrameworkClientU.DEF	Wed Apr 14 17:32:53 2010 +0300
@@ -137,4 +137,7 @@
 	_ZN9RTestStep16GetHexFromConfigERK7TDesC16S2_Ri @ 136 NONAME
 	_ZNK9RTestStep8HeapSizeEv @ 137 NONAME
 	_ZNK9RTestStep9StackSizeEv @ 138 NONAME
+	_ZN9RTestStep8SetSuiteEP10CTestSuite @ 139 NONAME
+	_ZN9RTestStep9SetResultE8TVerdict @ 140 NONAME
+	_ZNK9RTestStep8StepNameEv @ 141 NONAME
 
--- a/mmtestenv/mmtestfw/include/TestFramework.h	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmtestenv/mmtestfw/include/TestFramework.h	Wed Apr 14 17:32:53 2010 +0300
@@ -28,14 +28,6 @@
 #endif
 #include <testframeworkipc.h>
 
-// do not export if Unit Testing
-#if defined (__TSU_TESTFRAMEWORK__)
-#undef IMPORT_C
-#define IMPORT_C
-#endif
-
-// Common includes
-
 /**
  *
  * Server name
@@ -533,10 +525,9 @@
     IMPORT_C TInt StackSize() const;
     IMPORT_C TInt HeapSize() const;
 
-    // accessors - not required to be exported
-    void SetSuite(CTestSuite* aSuite);
-    void SetResult(TVerdict aResult);
-    TPtrC StepName() const;
+    IMPORT_C void SetSuite(CTestSuite* aSuite);
+    IMPORT_C void SetResult(TVerdict aResult);
+    IMPORT_C TPtrC StepName() const;
     
     // param set - not required to be exported. Note assumes actual param is stable
     void SetDefaultParamSet(const TDesC& aParamSet);
--- a/mmtestenv/mmtestfwunittest/MMPFiles/TSU_MmTsth10.mmp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmtestenv/mmtestfwunittest/MMPFiles/TSU_MmTsth10.mmp	Wed Apr 14 17:32:53 2010 +0300
@@ -38,7 +38,7 @@
 
 // code to be tested
 
-SOURCE			../../mmtestfw/Source/TestFrameworkClient/Log.cpp
+SOURCE			../../mmtestfw/Source/TestFrameworkClient/testfwclientsession.cpp
 
 // required stubs
 
--- a/mmtestenv/mmtestfwunittest/MMPFiles/TSU_MmTsth11.mmp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmtestenv/mmtestfwunittest/MMPFiles/TSU_MmTsth11.mmp	Wed Apr 14 17:32:53 2010 +0300
@@ -35,12 +35,6 @@
 SOURCE			tsu_mmtsth11/TSU_MmTsthStep11.cpp
 SOURCE			tsu_mmtsth11/TSU_MmTsth11.cpp
 
-// code to be tested
-
-SOURCE			../../mmtestfw/Source/TestFrameworkClient/TestStep.cpp
-SOURCE			../../mmtestfw/Source/TestFrameworkClient/asyncscheduler.cpp // to keep previous happy
-SOURCE			../../mmtestfw/Source/TestFrameworkClient/Log.cpp
-
 // required stubs
 
 SOURCE			tsu_stubs/TestStepVirtualStub.cpp
--- a/mmtestenv/mmtestfwunittest/MMPFiles/TSU_MmTsth12.mmp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmtestenv/mmtestfwunittest/MMPFiles/TSU_MmTsth12.mmp	Wed Apr 14 17:32:53 2010 +0300
@@ -35,17 +35,6 @@
 SOURCE			tsu_mmtsth12/TSU_MmTsthStep12.cpp
 SOURCE			tsu_mmtsth12/TSU_MmTsth12.cpp
 
-// code to be tested
-
-SOURCE			../../mmtestfw/Source/TestFrameworkClient/TestSuite.cpp
-SOURCE			../../mmtestfw/Source/TestFrameworkClient/Log.cpp
-
-// required for non-exported functions which need testing
-
-SOURCE			../../mmtestfw/Source/TestFrameworkClient/TestStep.cpp
-SOURCE			../../mmtestfw/Source/TestFrameworkClient/asyncscheduler.cpp // to keep previous happy
-SOURCE			../../mmtestfw/Source/TestFrameworkClient/TestIniData.cpp
-
 // required stubs
 
 SOURCE			tsu_stubs/TestStepVirtualStub.cpp
--- a/mmtestenv/mmtestfwunittest/MMPFiles/TSU_MmTsth13.mmp	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmtestenv/mmtestfwunittest/MMPFiles/TSU_MmTsth13.mmp	Wed Apr 14 17:32:53 2010 +0300
@@ -35,10 +35,6 @@
 SOURCE			tsu_mmtsth13/TSU_MmTsthStep13.cpp
 SOURCE			tsu_mmtsth13/TSU_MmTsth13.cpp
 
-// code to be tested
-
-SOURCE			../../mmtestfw/Source/TestFrameworkClient/TestUtils.cpp
-
 // required stubs
 
 
--- a/mmtestenv/mmtestfwunittest/eabi/TSU_MmTsth10U.DEF	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmtestenv/mmtestfwunittest/eabi/TSU_MmTsth10U.DEF	Wed Apr 14 17:32:53 2010 +0300
@@ -1,17 +1,13 @@
 EXPORTS
 	_Z20NewTSUMmTsthSuite10Lv @ 1 NONAME
-	_ZTI16RTestMmTsthU1001 @ 2 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1011 @ 3 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1012 @ 4 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1013 @ 5 NONAME ; #<TI>#
-	_ZTI17CTSUMmTsthSuite10 @ 6 NONAME ; #<TI>#
-	_ZTI29TIntegrationTestLog16Overflow @ 7 NONAME ; #<TI>#
-	_ZTI4CLog @ 8 NONAME ; #<TI>#
-	_ZTV16RTestMmTsthU1001 @ 9 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1011 @ 10 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1012 @ 11 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1013 @ 12 NONAME ; #<VT>#
-	_ZTV17CTSUMmTsthSuite10 @ 13 NONAME ; #<VT>#
-	_ZTV29TIntegrationTestLog16Overflow @ 14 NONAME ; #<VT>#
-	_ZTV4CLog @ 15 NONAME ; #<VT>#
+	_ZTI16RTestMmTsthU1001 @ 2 NONAME
+	_ZTI16RTestMmTsthU1011 @ 3 NONAME
+	_ZTI16RTestMmTsthU1012 @ 4 NONAME
+	_ZTI16RTestMmTsthU1013 @ 5 NONAME
+	_ZTI17CTSUMmTsthSuite10 @ 6 NONAME
+	_ZTV16RTestMmTsthU1001 @ 7 NONAME
+	_ZTV16RTestMmTsthU1011 @ 8 NONAME
+	_ZTV16RTestMmTsthU1012 @ 9 NONAME
+	_ZTV16RTestMmTsthU1013 @ 10 NONAME
+	_ZTV17CTSUMmTsthSuite10 @ 11 NONAME
 
--- a/mmtestenv/mmtestfwunittest/eabi/TSU_MmTsth11U.DEF	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmtestenv/mmtestfwunittest/eabi/TSU_MmTsth11U.DEF	Wed Apr 14 17:32:53 2010 +0300
@@ -1,35 +1,25 @@
 EXPORTS
 	_Z20NewTSUMmTsthSuite11Lv @ 1 NONAME
-	_ZTI12CTestIniData @ 2 NONAME ; #<TI>#
-	_ZTI16RTSUMmTsthStep11 @ 3 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1101 @ 4 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1102 @ 5 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1103 @ 6 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1104 @ 7 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1105 @ 8 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1111 @ 9 NONAME ; #<TI>#
-	_ZTI17CTSUMmTsthSuite11 @ 10 NONAME ; #<TI>#
-	_ZTI20RTestStepVirtualStub @ 11 NONAME ; #<TI>#
-	_ZTI21CTestSuiteVirtualStub @ 12 NONAME ; #<TI>#
-	_ZTI29TIntegrationTestLog16Overflow @ 13 NONAME ; #<TI>#
-	_ZTI9CTestStep @ 14 NONAME ; #<TI>#
-	_ZTI9RTestStep @ 15 NONAME ; #<TI>#
-	_ZTV12CTestIniData @ 16 NONAME ; #<VT>#
-	_ZTV16RTSUMmTsthStep11 @ 17 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1101 @ 18 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1102 @ 19 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1103 @ 20 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1104 @ 21 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1105 @ 22 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1111 @ 23 NONAME ; #<VT>#
-	_ZTV17CTSUMmTsthSuite11 @ 24 NONAME ; #<VT>#
-	_ZTV20RTestStepVirtualStub @ 25 NONAME ; #<VT>#
-	_ZTV21CTestSuiteVirtualStub @ 26 NONAME ; #<VT>#
-	_ZTV29TIntegrationTestLog16Overflow @ 27 NONAME ; #<VT>#
-	_ZTV9CTestStep @ 28 NONAME ; #<VT>#
-	_ZTV9RTestStep @ 29 NONAME ; #<VT>#
-	_ZTI14RAsyncTestStep @ 30 NONAME
-	_ZTI4CLog @ 31 NONAME
-	_ZTV14RAsyncTestStep @ 32 NONAME
-	_ZTV4CLog @ 33 NONAME
+	_ZTI12CTestIniData @ 2 NONAME
+	_ZTI16RTSUMmTsthStep11 @ 3 NONAME
+	_ZTI16RTestMmTsthU1101 @ 4 NONAME
+	_ZTI16RTestMmTsthU1102 @ 5 NONAME
+	_ZTI16RTestMmTsthU1103 @ 6 NONAME
+	_ZTI16RTestMmTsthU1104 @ 7 NONAME
+	_ZTI16RTestMmTsthU1105 @ 8 NONAME
+	_ZTI16RTestMmTsthU1111 @ 9 NONAME
+	_ZTI17CTSUMmTsthSuite11 @ 10 NONAME
+	_ZTI20RTestStepVirtualStub @ 11 NONAME
+	_ZTI21CTestSuiteVirtualStub @ 12 NONAME
+	_ZTV12CTestIniData @ 13 NONAME
+	_ZTV16RTSUMmTsthStep11 @ 14 NONAME
+	_ZTV16RTestMmTsthU1101 @ 15 NONAME
+	_ZTV16RTestMmTsthU1102 @ 16 NONAME
+	_ZTV16RTestMmTsthU1103 @ 17 NONAME
+	_ZTV16RTestMmTsthU1104 @ 18 NONAME
+	_ZTV16RTestMmTsthU1105 @ 19 NONAME
+	_ZTV16RTestMmTsthU1111 @ 20 NONAME
+	_ZTV17CTSUMmTsthSuite11 @ 21 NONAME
+	_ZTV20RTestStepVirtualStub @ 22 NONAME
+	_ZTV21CTestSuiteVirtualStub @ 23 NONAME
 
--- a/mmtestenv/mmtestfwunittest/eabi/TSU_MmTsth12U.DEF	Wed Mar 31 23:56:23 2010 +0300
+++ b/mmtestenv/mmtestfwunittest/eabi/TSU_MmTsth12U.DEF	Wed Apr 14 17:32:53 2010 +0300
@@ -1,35 +1,21 @@
 EXPORTS
 	_Z20NewTSUMmTsthSuite12Lv @ 1 NONAME
-	_ZTI10CTestSuite @ 2 NONAME ; #<TI>#
-	_ZTI12CTestIniData @ 3 NONAME ; #<TI>#
-	_ZTI16RTSUMmTsthStep12 @ 4 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1201 @ 5 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1202 @ 6 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1203 @ 7 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1221 @ 8 NONAME ; #<TI>#
-	_ZTI16RTestMmTsthU1222 @ 9 NONAME ; #<TI>#
-	_ZTI17CTSUMmTsthSuite12 @ 10 NONAME ; #<TI>#
-	_ZTI20RTestStepVirtualStub @ 11 NONAME ; #<TI>#
-	_ZTI21CTestSuiteVirtualStub @ 12 NONAME ; #<TI>#
-	_ZTI29TIntegrationTestLog16Overflow @ 13 NONAME ; #<TI>#
-	_ZTI9CTestStep @ 14 NONAME ; #<TI>#
-	_ZTI9RTestStep @ 15 NONAME ; #<TI>#
-	_ZTV10CTestSuite @ 16 NONAME ; #<VT>#
-	_ZTV12CTestIniData @ 17 NONAME ; #<VT>#
-	_ZTV16RTSUMmTsthStep12 @ 18 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1201 @ 19 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1202 @ 20 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1203 @ 21 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1221 @ 22 NONAME ; #<VT>#
-	_ZTV16RTestMmTsthU1222 @ 23 NONAME ; #<VT>#
-	_ZTV17CTSUMmTsthSuite12 @ 24 NONAME ; #<VT>#
-	_ZTV20RTestStepVirtualStub @ 25 NONAME ; #<VT>#
-	_ZTV21CTestSuiteVirtualStub @ 26 NONAME ; #<VT>#
-	_ZTV29TIntegrationTestLog16Overflow @ 27 NONAME ; #<VT>#
-	_ZTV9CTestStep @ 28 NONAME ; #<VT>#
-	_ZTV9RTestStep @ 29 NONAME ; #<VT>#
-	_ZTI14RAsyncTestStep @ 30 NONAME
-	_ZTI4CLog @ 31 NONAME
-	_ZTV14RAsyncTestStep @ 32 NONAME
-	_ZTV4CLog @ 33 NONAME
+	_ZTI16RTSUMmTsthStep12 @ 2 NONAME
+	_ZTI16RTestMmTsthU1201 @ 3 NONAME
+	_ZTI16RTestMmTsthU1202 @ 4 NONAME
+	_ZTI16RTestMmTsthU1203 @ 5 NONAME
+	_ZTI16RTestMmTsthU1221 @ 6 NONAME
+	_ZTI16RTestMmTsthU1222 @ 7 NONAME
+	_ZTI17CTSUMmTsthSuite12 @ 8 NONAME
+	_ZTI20RTestStepVirtualStub @ 9 NONAME
+	_ZTI21CTestSuiteVirtualStub @ 10 NONAME
+	_ZTV16RTSUMmTsthStep12 @ 11 NONAME
+	_ZTV16RTestMmTsthU1201 @ 12 NONAME
+	_ZTV16RTestMmTsthU1202 @ 13 NONAME
+	_ZTV16RTestMmTsthU1203 @ 14 NONAME
+	_ZTV16RTestMmTsthU1221 @ 15 NONAME
+	_ZTV16RTestMmTsthU1222 @ 16 NONAME
+	_ZTV17CTSUMmTsthSuite12 @ 17 NONAME
+	_ZTV20RTestStepVirtualStub @ 18 NONAME
+	_ZTV21CTestSuiteVirtualStub @ 19 NONAME
 
--- a/omxil/omxilcore/src/omxilcoreclient/omxilcoreclientsession.cpp	Wed Mar 31 23:56:23 2010 +0300
+++ b/omxil/omxilcore/src/omxilcoreclient/omxilcoreclientsession.cpp	Wed Apr 14 17:32:53 2010 +0300
@@ -293,7 +293,12 @@
 	RHandleBase::Close();
 
 	// Release server handle so it will exit cleanly.
-	XGlobalILCoreCache::IlCoreCache()->SetServerHandle(KNullHandle);
+	XGlobalILCoreCache* pGlobalILCoreCache = XGlobalILCoreCache::IlCoreCache();
+
+	__ASSERT_ALWAYS(pGlobalILCoreCache != NULL,
+					User::Panic(KOmxILCoreClientPanic, KErrNotReady));
+
+	pGlobalILCoreCache->SetServerHandle(KNullHandle);
 	
 	RThread serverThread;
 	TInt ret = serverThread.Open(TThreadId(serverThreadId));