devsound/a3fdevsound/src/devsoundadaptor/cdevaudiocontrol.cpp
changeset 0 b8ed18f6c07b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/devsound/a3fdevsound/src/devsoundadaptor/cdevaudiocontrol.cpp	Thu Oct 07 22:34:12 2010 +0100
@@ -0,0 +1,1234 @@
+// Copyright (c) 2006-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:
+//
+
+
+
+#include "cdevaudiocontrol.h"
+
+#include <a3f/audioprocessingunittypeuids.h>
+#include <a3f/maudiocontext.h>
+#include <a3f/maudiostream.h>
+#include <a3f/maudiocodec.h>
+#include <a3f/maudiogaincontrol.h>
+
+
+const TInt KMicroSecondsInSecond = 1000000;
+const TInt KDefaultBufferSize = 4096;
+
+const TUint KMaxCallbacksExpected = 2;
+const TUint KDefaultSampleRate = 8000;
+const TUid KDefaultMode = {KA3FModeMonoValue};
+
+class TSampleRateTableEntry
+	{
+public:
+	TInt		iSampleRateValue;
+	TMMFSampleRate iSampleRate;
+	};
+
+const TSampleRateTableEntry KRateTableLookup[] = { 
+							{ 8000, EMMFSampleRate8000Hz },
+							{ 11025, EMMFSampleRate11025Hz },
+							{ 12000, EMMFSampleRate12000Hz },
+							{ 16000, EMMFSampleRate16000Hz },
+							{ 22050, EMMFSampleRate22050Hz },
+							{ 24000, EMMFSampleRate24000Hz },
+							{ 32000, EMMFSampleRate32000Hz },
+							{ 44100, EMMFSampleRate44100Hz },
+							{ 48000, EMMFSampleRate48000Hz },
+							{ 64000, EMMFSampleRate64000Hz },
+							{ 88200, EMMFSampleRate88200Hz },
+							{ 96000, EMMFSampleRate96000Hz },
+						};
+const TInt KMaxSampleRateIndex = 11; // must agree with length of table
+
+class TAudioModeTableEntry
+	{
+public:
+	TMMFMonoStereo	iAudioModeValue;
+	TUid			iAudioMode;
+	};
+
+const TAudioModeTableEntry KModeTableLookup[] = {
+							{ EMMFMono, {KA3FModeMonoValue} },
+							{ EMMFStereo, {KA3FModeStereoNonInterleavedValue} },
+							};
+
+const TInt KMaxModeIndex = 1; // must agree with length of table
+
+// ---------------------------------------------------------------------------
+// Default constructor
+// ---------------------------------------------------------------------------
+//
+CDevAudioControl::CDevAudioControl()
+	{
+	TRACE_CREATE();
+	DP_CONTEXT(CDevAudioControl::CDevAudioControl *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	// Local cache default values
+	iCurrentSampleRate = KDefaultSampleRate;
+	iCurrentMode = KDefaultMode; 
+	iOutstandingCallbacks = KMaxCallbacksExpected; //by default we expect 2 callbacks for capabilities.
+	iCallbackFromAdaptor = KCallbackNone;
+	
+	DP_OUT();
+	}
+
+
+void CDevAudioControl::ConstructL(CDevAudio* aDevAudio, MDevSoundAdaptationObserver& aDevSoundObserver)
+	{
+	TRACE_CREATE();
+	DP_CONTEXT(CDevAudioControl::ConstructL *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	iDevAudio = aDevAudio; 
+	iAdaptationObserver = &aDevSoundObserver;
+	
+	iObserverRegistered = EFalse;
+
+	TAudioChannelGain left;
+	TAudioChannelGain right;
+	
+	left.iLocation = TAudioChannelGain::ELeft;
+	right.iLocation = TAudioChannelGain::ERight;
+		
+	User::LeaveIfError(iChannelGains.Append(left)); // assumed element 0 in rest of code
+	User::LeaveIfError(iChannelGains.Append(right)); // assumed element 1 in rest of code
+
+	// Note this could be delayed now (volume is internal to adaptor until later in cycle)
+	// Needed to allow CMMFDevSound::MaxVolume and similar calls before CMMFDevSound::InitializeL
+	TAny* interface(NULL);
+	interface = iDevAudio->iGainControl->Interface(KUidAudioGainControl);
+	iGainControl = static_cast<MAudioGainControl*>(interface);
+	DP_OUT();
+	}
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CDevAudioControl::~CDevAudioControl()
+	{
+	DP_CONTEXT(CDevAudioControl::~CDevAudioControl *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	iChannelGains.Close();
+	iSupportedRates.Close();
+	iSupportedModes.Close();
+	DP_OUT();
+	}
+	
+// -----------------------------------------------------------------------------
+// CacheAudioCodecIf
+//
+TInt CDevAudioControl::CacheAudioCodecIf()
+	{
+	DP_CONTEXT(CDevAudioControl::CacheAudioCodecIf *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	if (iDevAudio->iAudioCodec==NULL)
+		{
+		DP0_RET(KErrNotReady,"%d");
+		}
+	TInt err = KErrNone;
+	if (iAudioCodecIf==NULL)
+		{
+		MAudioCodec* codecInterface = static_cast<MAudioCodec*>(iDevAudio->iAudioCodec->Interface(KUidAudioCodec));
+		__ASSERT_ALWAYS (codecInterface, CDevAudioControl::Panic(EAudioCodecIsNull));
+		iAudioCodecIf = codecInterface; 
+		}
+	DP0_RET(err,"%d");
+	}
+
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::Initialize
+// -----------------------------------------------------------------------------
+//
+TInt CDevAudioControl::Initialize(TUid /*aFormat*/)
+	{
+	DP_CONTEXT(CDevAudioControl::Initialize *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	ASSERT(EFalse);
+	iObserverRegistered = EFalse;
+	DP0_RET(KErrNone,"%d");
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::Uninitialize
+// -----------------------------------------------------------------------------
+//
+TInt CDevAudioControl::Uninitialize()
+	{
+	DP_CONTEXT(CDevAudioControl::Uninitialize *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	// Remove pUnits only allowed when stream is uninitialized
+	TInt err = iDevAudio->iAudioStream->Uninitialize();
+
+	if (err == KErrNone)
+		{
+		err = iDevAudio->CommitAudioContext();
+		}
+	if (err == KErrNone)
+		{
+		iDevAudio->iActiveState = EDevSoundAdaptorUninitialising;
+		}
+
+	DP0_RET(err,"%d");
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::Unload
+// -----------------------------------------------------------------------------
+//
+TInt CDevAudioControl::Unload()
+	{
+	DP_CONTEXT(CDevAudioControl::Unload *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	TInt err = iDevAudio->iAudioStream->Unload();
+	if (err == KErrNone)
+		{
+		err = iDevAudio->CommitAudioContext();
+		}
+	if (err == KErrNone)
+		{
+		iDevAudio->iActiveState = EDevSoundAdaptorUnloading;
+		}
+
+	DP0_RET(err,"%d");
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::GetCapabilities
+// -----------------------------------------------------------------------------
+//
+TInt CDevAudioControl::GetCapabilities(TMMFCapabilities& aCap)
+	{
+	DP_CONTEXT(CDevAudioControl::GetCapabilities *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	// At this phase of CAP, we only care about current codec capabilities. 
+	// This will be supported as soon as the A3F API changes to support this are ready
+	TInt err = KErrNone;
+		
+	if (iDevAudio->iActiveState != EDevSoundAdaptorCreated_Uninitialised)
+		{
+		err = CacheAudioCodecIf();
+		if (err != KErrNone)
+			{
+			DP0_RET(err, "%d");			
+			}
+			
+		if (err == KErrNone)
+			{
+			err = iAudioCodecIf->GetSupportedModes(iSupportedModes);
+			if (err == KErrNone)
+				{
+				aCap.iChannels = GetModes(iSupportedModes);
+				err = iAudioCodecIf->GetSupportedSamplesRates(iSupportedRates);
+				
+				if (err == KErrNone)
+					{
+					aCap.iRate = GetSampleRates(iSupportedRates);
+					}
+				else
+					{
+					//If was a problem getting sampleRates we donīt expect callbacks and return
+					iOutstandingCallbacks = 0;
+					}
+					
+				}
+			else
+				{
+				//If was a problem getting modes we donīt expect callbacks and return
+				iOutstandingCallbacks = 0;
+				}
+			}
+		}
+	else
+		{
+		err = KErrNotReady;
+		}
+	DP0_RET(err, "%d");
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::GetConfig
+// -----------------------------------------------------------------------------
+//
+TInt CDevAudioControl::GetConfig(TMMFCapabilities& aConfig)
+	{
+	DP_CONTEXT(CDevAudioControl::GetConfig *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	TInt err(KErrNone);
+
+	//TODO add a return error code if the sample rate or the channels are not found
+	//We need to transform the local values to a supported value for the client
+	aConfig.iRate = static_cast<TMMFSampleRate>(GetSampleRate(iCurrentSampleRate));
+	aConfig.iChannels = static_cast<TMMFMonoStereo>(GetMode(iCurrentMode));
+	aConfig.iBufferSize = KDefaultBufferSize;
+	
+	DP2(DLINFO, "rate 0x%x, channels 0x%x", aConfig.iRate, aConfig.iChannels);
+
+	DP0_RET(err, "%d");
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::SetConfig
+// -----------------------------------------------------------------------------
+//
+TInt CDevAudioControl::SetConfig(const TMMFCapabilities& aConfig)
+	{
+	DP_CONTEXT(CDevAudioControl::SetConfig *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	
+	// TODO need to ensure if iChannels or iSampleRate is outside known values, then
+	// the code handles that gracefully and returns the appropriate error code
+	
+	TInt err(KErrNone);
+	TUid mode = KNullUid;
+	//Reset the desired values
+	iDesiredSampleRate = 0;
+	iDesiredMode = KNullUid;
+
+	err = ResolveMode(aConfig.iChannels, mode);
+	if (err != KErrNone)
+		{
+		DP0_RET(err, "%d");
+		}
+
+	err = ResolveSampleRate(aConfig.iRate, iDesiredSampleRate);
+	if (err != KErrNone)
+		{
+		DP0_RET(err, "%d");
+		}
+
+	// At this phase of CAP, we only care about codec, which checks config against
+	// its own capabilities. Verification against stream specific capabilities
+	// should be added later on.
+	
+	err = CacheAudioCodecIf();
+	if (err != KErrNone)
+		{
+		DP0_RET(err, "%d");
+		}
+	
+	err = iAudioCodecIf->SetSampleRate(iDesiredSampleRate);
+		
+	
+	if(err == KErrNone)
+		{
+		err = iAudioCodecIf->SetMode(mode);
+		}
+	
+	if(err == KErrNone)
+		{
+		err = iDevAudio->CommitAudioContext();
+		if (err == KErrNone)
+			{
+			iDesiredMode = mode;
+			}
+		}
+
+	DP0_RET(err, "%d");
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::ProcessInit
+// -----------------------------------------------------------------------------
+//
+TInt CDevAudioControl::ProcessInit()
+	{
+	DP_CONTEXT(CDevAudioControl::ProcessInit *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	ASSERT(EFalse);
+	DP0_RET(KErrNone,"%d");
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::ProcessData
+// -----------------------------------------------------------------------------
+//
+void CDevAudioControl::ProcessData()
+	{
+	DP_CONTEXT(CDevAudioControl::ProcessData *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	ASSERT(EFalse);
+	DP_OUT();
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::GetSamples
+// -----------------------------------------------------------------------------
+//
+TInt CDevAudioControl::GetSamples()
+	{
+	DP_CONTEXT(CDevAudioControl::GetSamples *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	TInt err(KErrNone);
+	TInt samplesplayed(0);
+	
+	TTimeIntervalMicroSeconds timeProcessed(0);
+	err = iDevAudio->iAudioStream->GetStreamTime(timeProcessed);
+
+	DP1(DLINFO,"CDevAudioControl::GetSamples iCurrentSampleRate %d",iCurrentSampleRate);
+	
+	if(err == KErrNone)
+		{
+		samplesplayed = (timeProcessed.Int64() * iCurrentSampleRate + KMicroSecondsInSecond/2) / TInt64(KMicroSecondsInSecond);
+		}
+	//TODO manage the error
+
+	DP0_RET(samplesplayed, "%d");
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::Stop
+// -----------------------------------------------------------------------------
+//
+TInt CDevAudioControl::Stop()
+	{
+	DP_CONTEXT(CDevAudioControl::Stop *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	ASSERT(EFalse);
+	DP0_RET(KErrNone, "%d");
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::Pause
+// -----------------------------------------------------------------------------
+//
+TInt CDevAudioControl::Pause()
+	{
+	DP_CONTEXT(CDevAudioControl::Pause *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	ASSERT(EFalse);
+	DP0_RET(KErrNone, "%d");
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::CustomInterface
+// -----------------------------------------------------------------------------
+//
+TAny* CDevAudioControl::CustomInterface(TUid aInterfaceId)
+	{
+	DP_CONTEXT(CDevAudioControl::CustomInterface *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	TAny* ciPtr(NULL);
+	TInt err = KErrNone;
+	if(iDevAudio->iAudioStream)
+		{
+		TAny* ptr = iDevAudio->iAudioStream->Interface(KUidExtensionInferface);
+		if(ptr)
+			{
+			MCustomInterfaceSupport* ciSupport  = static_cast<MCustomInterfaceSupport*>(ptr);
+			if(!iObserverRegistered)
+				{
+				err = ciSupport->RegisterObserver(*this);
+				if(err == KErrNone)
+					{
+					iObserverRegistered = ETrue;
+					}
+				}
+			err = ciSupport->RequestCustomInterface(aInterfaceId, ciPtr);
+			if( err != KErrNone)
+				{
+				ciPtr = NULL;
+				}
+			}
+		}
+	DP0_RET(ciPtr, "0x%x");
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::SetGain
+// -----------------------------------------------------------------------------
+TInt CDevAudioControl::SetGains(TInt aDevSoundGain, TInt aDevSoundMaxGain, TInt aBalance[2], const TTimeIntervalMicroSeconds& aRampDuration, TBool aBecomingActive)
+	{
+	DP_CONTEXT(CDevAudioControl::SetGains *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	ASSERT(aDevSoundGain>=0 && aDevSoundGain<=aDevSoundMaxGain); // higher layer assumed to scale
+	ASSERT(aBalance[ELeftCh]>=0 && aBalance[ELeftCh]<=100);
+	ASSERT(aBalance[ERightCh]>=0 && aBalance[ERightCh]<=100);
+	ASSERT(aDevSoundMaxGain>0); // assumed max gain is positive
+	TInt a3fMaxGain;
+	TInt err = iGainControl->GetMaxGain(a3fMaxGain);
+	if (err==KErrNone)
+		{
+		iLegacyGain = TInt(TReal(aDevSoundGain)*TReal(a3fMaxGain)/TReal(aDevSoundMaxGain)+0.5);
+		ASSERT(iLegacyGain>=0 && iLegacyGain<=a3fMaxGain);
+		iLegacyLeft = aBalance[ELeftCh];
+		iLegacyRight = aBalance[ERightCh];
+
+		MapGains();
+
+		// VolumeRamp is only applied when DevSound is becoming active
+		if(err == KErrNone)
+			{
+			if (aRampDuration > 0 && aBecomingActive)
+				{
+				err = iGainControl->SetGain(iChannelGains, KUidGainSawTooth, aRampDuration);
+				}
+			else
+				{
+				err = iGainControl->SetGain(iChannelGains);
+				}
+			}
+
+		// This call will result on commit only when we are already active
+		// otherwise the changes will be commited by the DevAudioControl 
+		// It means we're here due to RequestGainAndBalance call
+		if(err == KErrNone && !aBecomingActive)
+			{
+			err = iDevAudio->CommitAudioContext();
+			}		
+		}
+	DP0_RET(err,"%d");
+	}
+
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::MapAndSetGains
+// -----------------------------------------------------------------------------
+//
+void CDevAudioControl::MapGains()
+	{
+	DP_CONTEXT(CDevAudioControl::MapGains *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	// Map legacy values to CAP channel array.
+	if ( iLegacyLeft == iLegacyRight )
+		{
+		iChannelGains[ELeftCh].iGain = iLegacyGain;
+		iChannelGains[ERightCh].iGain = iLegacyGain;
+		}
+	else if ( iLegacyLeft > iLegacyRight )
+		{
+		iChannelGains[ELeftCh].iGain = iLegacyGain;
+		iChannelGains[ERightCh].iGain =
+						static_cast<TUint>((iLegacyGain*iLegacyRight)/iLegacyLeft);
+		}
+	else
+		{
+		iChannelGains[ERightCh].iGain = iLegacyGain;
+		iChannelGains[ELeftCh].iGain =
+						static_cast<TUint>((iLegacyGain*iLegacyLeft)/iLegacyRight);
+		}
+
+	DP_OUT();
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::DestroyChain
+// -----------------------------------------------------------------------------
+//
+TBool CDevAudioControl::DestroyChain()
+	{
+	DP_CONTEXT(CDevAudioControl::DestroyChain *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	TInt err = KErrNone;
+	TBool readyToDestroy = EFalse;
+	switch(iDevAudio->iActiveState)
+		{
+		case EDevSoundAdaptorActive_Active:
+		case EDevSoundAdaptorPaused_Primed:
+			{
+			err = iDevAudio->iAudioStream->Stop();
+			if(err == KErrNone)
+				{
+				err = iDevAudio->CommitAudioContext();
+				}
+			if (err == KErrNone)
+				{
+				iDevAudio->iActiveState = EDevSoundAdaptorStopping;
+				}
+			}
+			break;
+		case EDevSoundAdaptorInitialised_Idle:
+			{
+			err = iDevAudio->iAudioStream->Unload();
+			if(err == KErrNone)
+				{
+				err = iDevAudio->CommitAudioContext();
+				}
+			if (err == KErrNone)
+				{
+				iDevAudio->iActiveState = EDevSoundAdaptorUnloading;
+				}
+			}
+			break;
+		case EDevSoundAdaptorInitialised_Initialised:
+			{
+			err = iDevAudio->iAudioStream->Uninitialize();
+			if(err == KErrNone)
+				{
+				err = iDevAudio->CommitAudioContext();
+				}
+			if (err == KErrNone)
+				{
+				iDevAudio->iActiveState = EDevSoundAdaptorUninitialising;
+				}
+			}
+			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;
+		}
+	
+	// Destroy sequence fail!
+	if(err != KErrNone)
+		{
+		DP0(DLINFO, "================ Destroy sequence fail! ================");
+		readyToDestroy = ETrue;
+		}
+	// Set the flag only when needed
+	iDevAudio->iClosing = !readyToDestroy;
+	DP0_RET(readyToDestroy,"%d");
+	}
+
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::RemoveProcessingUnits
+// -----------------------------------------------------------------------------
+//
+TInt CDevAudioControl::RemoveProcessingUnits()
+	{
+	DP_CONTEXT(CDevAudioControl::RemoveProcessingUnits *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	// Remove pUnits only allowed when stream is uninitialized
+	TInt err = iDevAudio->iAudioStream->RemoveProcessingUnit(iDevAudio->iAudioSource);
+		
+	if(err == KErrNone)
+		{
+		err = iDevAudio->iAudioStream->RemoveProcessingUnit(iDevAudio->iAudioSink);	
+		}
+	if(err == KErrNone)
+		{
+		err = iDevAudio->iAudioStream->RemoveProcessingUnit(iDevAudio->iAudioCodec);
+		}
+
+	if (err == KErrNone)
+		{
+		err = iDevAudio->CommitAudioContext();
+		}
+		
+	if(err == KErrNone)
+		{
+		iDevAudio->iActiveState = EDevSoundAdaptorRemovingProcessingUnits;		
+		}
+	DP0_RET(err,"%d");
+	}
+
+// -----------------------------------------------------------------------------
+// From class MAudioStreamObserver
+// CDevAudioControl::StateEvent
+// -----------------------------------------------------------------------------
+//
+void CDevAudioControl::StateEvent(MAudioStream& /*aStream*/, 
+									TInt /*aReason*/, 
+									TAudioState /*aNewState*/)
+	{
+	DP_CONTEXT(CDevAudio::StateEvent *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	ASSERT(EFalse);
+	DP_OUT();
+	}
+
+// -----------------------------------------------------------------------------
+// From class MAudioStreamObserver
+// CDevAudioControl::AddProcessingUnitComplete
+// -----------------------------------------------------------------------------
+//
+void CDevAudioControl::AddProcessingUnitComplete(MAudioStream& /*aStream*/, 
+												MAudioProcessingUnit* /*aInstance*/,
+												TInt /*aError*/)
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// From class MAudioStreamObserver
+// CDevAudioControl::RemoveProcessingUnitComplete
+// -----------------------------------------------------------------------------
+//
+void CDevAudioControl::RemoveProcessingUnitComplete(MAudioStream& /*aStream*/,
+													MAudioProcessingUnit* /*aInstance*/,
+													TInt /*aError*/)
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// From class MAudioStreamObserver
+// CDevAudioControl::ProcessingFinished
+// -----------------------------------------------------------------------------
+//
+void CDevAudioControl::ProcessingFinished(MAudioStream& /*aStream*/)
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// From class MAudioStreamObserver
+// CDevAudioControl::FlushComplete
+// -----------------------------------------------------------------------------
+//
+void CDevAudioControl::FlushComplete (MAudioStream& /*aStream*/, TInt aError)
+	{
+	// no action needed - should complete as part of the ContextEvent.
+	// otherwise could callback.
+	TInt err = KErrNone;
+	
+	if(iPauseResumeSequenceDueToEmptyBuffers)
+		{
+		// Flush operation failed
+		if(aError != KErrNone)
+			{
+			iPauseResumeSequenceDueToEmptyBuffers = EFalse;
+			iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackFlushComplete, aError);
+			}
+		// Handle throw-off scenarios, resume is not possible from here
+		// 1. ProcessingFinished has occurred
+		// 2. Preemption occurred 
+		else if(iCallbackFromAdaptor != KCallbackNone || 
+			iDevAudio->iActiveState != EDevSoundAdaptorPaused_Primed)
+			{
+			iPauseResumeSequenceDueToEmptyBuffers = EFalse;
+			iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackFlushComplete, KErrNone);
+			
+			}
+		else
+			{
+			err = Resume();
+			if(err != KErrNone)
+				{
+				iPauseResumeSequenceDueToEmptyBuffers = EFalse;
+				iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackFlushComplete, aError);
+				}
+			// Once ContextEvent be received 
+			// EmptyBuffers can be considered completed
+			}
+		}
+	// EmptyBuffers operation has concluded here
+	// we didn't go through pause - resume sequence
+	else
+		{
+		iAdaptationObserver->CallbackFromAdaptorReceived(KCallbackFlushComplete, aError);
+		}
+	}
+	
+// -----------------------------------------------------------------------------
+// From class MAudioGainControlObserver
+// CDevAudioControl::MaxRampTimeChanged
+// -----------------------------------------------------------------------------
+//
+void CDevAudioControl::MaxRampTimeChanged(MAudioGainControl& /*aGain*/)
+	{
+	DP_CONTEXT(CDevAudioControl::MaxRampTimeChanged *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	// this is not cached, no actions needed
+	DP_OUT();
+	}
+
+// -----------------------------------------------------------------------------
+// From class MAudioGainControlObserver
+// CDevAudioControl::MaxGainChanged
+// -----------------------------------------------------------------------------
+//
+void CDevAudioControl::MaxGainChanged(MAudioGainControl& /*aGain*/)
+	{
+	DP_CONTEXT(CDevAudioControl::MaxGainChanged *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	// this is not cached, no actions needed
+	DP_OUT();
+	}
+
+// -----------------------------------------------------------------------------
+// From class MAudioGainControlObserver
+// CDevAudioControl::GainChanged
+// -----------------------------------------------------------------------------
+//
+void CDevAudioControl::GainChanged(MAudioGainControl& aGain, TInt aError)
+	{
+	DP_CONTEXT(CDevAudioControl::GainChanged *CD1*, CtxDevSound, DPLOCAL);
+	DP1_IN("aError=%d", aError);
+
+	if(aError != KErrNone)
+		{
+		// Either our request failed, or MMRC has forced some values, and we
+		// have to update local values.
+		aGain.GetGain(iChannelGains);
+		ASSERT(iChannelGains.Count()==2);
+		// Map CAP channel array to legacy values. 
+		// assumption: left%+right%=100
+		if ( iChannelGains[ELeftCh].iGain == iChannelGains[ERightCh].iGain )
+			{
+			iLegacyGain = iChannelGains[ELeftCh].iGain;
+			iLegacyLeft = 50;
+			iLegacyRight = 50;
+			}
+		else if ( iChannelGains[ELeftCh].iGain > iChannelGains[ERightCh].iGain )
+			{
+			iLegacyGain = iChannelGains[ELeftCh].iGain;
+			iLegacyLeft = static_cast<TUint>
+				((100*iLegacyGain)/(iLegacyGain+iChannelGains[ERightCh].iGain));
+			iLegacyRight = 100 - iLegacyLeft;
+			//(not that accurate, but sufficient for now)
+			}
+		else
+			{
+			iLegacyGain = iChannelGains[ERightCh].iGain;
+			iLegacyRight = static_cast<TUint>
+				((100*iLegacyGain)/(iLegacyGain+iChannelGains[ELeftCh].iGain));
+			iLegacyLeft = 100 - iLegacyRight;
+			}
+
+		DP3(DLINFO,"New values :iLegacyGain %d, iLegacyLeft %d, iLegacyRight %d",
+				iLegacyGain,iLegacyLeft,iLegacyRight);
+		}
+	else
+		{
+		// our request completed succesfully, no need to update cached values
+		// just print values in debug version
+		#ifdef _DEBUG
+		RArray<TAudioChannelGain> gains;
+		TUint left;
+		TUint right;
+		TUint gain;
+		aGain.GetGain(gains);
+		ASSERT(gains.Count()==2);
+		if ( iChannelGains[ELeftCh].iGain == iChannelGains[ERightCh].iGain )
+			{
+			gain = iChannelGains[ELeftCh].iGain;
+			left = 50;
+			right = 50;
+			}
+		else if ( iChannelGains[ELeftCh].iGain > iChannelGains[ERightCh].iGain )
+			{
+			gain = iChannelGains[ELeftCh].iGain;
+			left = 
+				static_cast<TUint>((100*gain)/(gain+iChannelGains[ERightCh].iGain));
+			right = 100 - left;
+			}
+		else
+			{
+			gain = iChannelGains[ERightCh].iGain;
+			right = 
+				static_cast<TUint>((100*gain)/(gain+iChannelGains[ELeftCh].iGain));
+			left = 100 - right;
+			}
+		gains.Close();
+		DP3(DLINFO,"KErrNone (gain %d, left %d, right %d)", gain,left,right);
+		#endif
+		}
+
+	DP_OUT();
+	}
+
+// -----------------------------------------------------------------------------
+// From class MAudioCodecObserver
+// CDevAudioControl::SampleRateSet
+// -----------------------------------------------------------------------------
+void CDevAudioControl::SampleRateSet(TInt aError)
+	{
+	if(aError==KErrNone)
+		{
+		//Review if we call SetConfig or is only the first time that we load the codec
+		if (iDesiredSampleRate > 0)
+			{
+			iCurrentSampleRate = iDesiredSampleRate;
+			}
+		}
+	else
+	    {
+        iAdaptationObserver->NotifyError(aError);
+	    }
+    iDesiredSampleRate = 0;
+	}
+
+// -----------------------------------------------------------------------------
+// From class MAudioCodecObserver
+// CDevAudioControl::ModeSet
+// -----------------------------------------------------------------------------
+void CDevAudioControl::ModeSet(TInt aError)
+	{
+	if(aError==KErrNone)
+		{
+		//Review if we call SetConfig or is only the first time that we load the codec
+		if (iDesiredMode != KNullUid)
+			{
+			iCurrentMode = iDesiredMode;
+			}
+		}
+    else
+        {
+        iAdaptationObserver->NotifyError(aError);
+        }
+    iDesiredMode = KNullUid;
+	}
+
+// -----------------------------------------------------------------------------
+// From class MAudioCodecObserver
+// CDevAudioControl::GetSupportedSampleRatesComplete
+// -----------------------------------------------------------------------------
+void CDevAudioControl::GetSupportedSampleRatesComplete(TInt aError)
+	{
+	iSupportedRates.Reset();
+	CompleteMessageCap(aError);
+	}
+
+// -----------------------------------------------------------------------------
+// From class MAudioCodecObserver
+// CDevAudioControl::GetSupportedModesComplete
+// -----------------------------------------------------------------------------
+void CDevAudioControl::GetSupportedModesComplete(TInt aError)
+	{
+	iSupportedModes.Reset();
+	CompleteMessageCap(aError);
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::CompleteMessageCap
+// -----------------------------------------------------------------------------
+void CDevAudioControl::CompleteMessageCap(TInt aError)
+	{
+	if (iOutstandingCallbacks > 1) //waiting until the 2 outstanding callbacks arrival.
+		{
+		iOutstandingCallbacks--;
+		iError = aError; //keeping the error.
+		}
+	else
+		{
+		if (iError == KErrNone)
+			{
+			iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
+			}
+		else
+			{
+			iAdaptationObserver->AsynchronousOperationComplete(iError, ETrue);
+			}
+		iError = KErrNone;
+		iOutstandingCallbacks = KMaxCallbacksExpected;
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::SetToneData
+// -----------------------------------------------------------------------------
+//
+TInt CDevAudioControl::SetToneData(TToneData& /*aToneData*/)
+	{
+	DP_CONTEXT(CDevAudioControl::SetToneData *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	DP0_RET(KErrNotSupported, "%d");
+	}
+
+
+// -----------------------------------------------------------------------------
+// From class MAudioContextObserver
+// CDevAudio::ContextEvent
+// -----------------------------------------------------------------------------
+//
+void CDevAudioControl::ContextEvent(TUid aEvent, TInt aError)
+	{
+	DP_CONTEXT(CDevAudioControl::ContextEvent *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+    if(!(iAdaptationObserver->AdaptorControlsContext()))
+        {
+        iIgnoreAsyncOpComplete = ETrue;
+        }
+    
+	if (aEvent == KUidA3FContextUpdateComplete)
+		{
+	    if(iIgnoreAsyncOpComplete)
+			{
+            iAdaptationObserver->PreemptionFinishedCallbackReceived(ETrue);
+		    iIgnoreAsyncOpComplete = EFalse;
+   	    	}
+        else
+            {
+            iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue);
+           	}
+		}
+	else if(aEvent == KUidA3FContextPreEmption)
+		{
+		//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();
+	}
+
+
+// -----------------------------------------------------------------------------
+// From class MCustomInterfaceSupportObserver
+// CDevAudio::CustomInterfaceRemoval
+// -----------------------------------------------------------------------------
+//
+void CDevAudioControl::CustomInterfaceRemoval(TUid aUid, TAny* /*aPtr*/)
+	{
+	DP_CONTEXT(CDevAudioControl::CustomInterfaceRemoval *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	// TODO: Review this functionality
+	iAdaptationObserver->InterfaceDeleted(aUid);
+	DP_OUT();
+	}
+
+// ---------------------------------------------------------------------------
+// CDevAudioControl::ResolveSampleRate
+// ---------------------------------------------------------------------------
+TInt CDevAudioControl::ResolveSampleRate(TInt aSampleRate, TInt& aSampleRateValue)
+	{
+	DP_CONTEXT(CDevAudioControl::ResolveSampleRate, CtxDevSound, DPLOCAL);
+	DP_IN();
+	TInt err(KErrArgument);
+
+	for (TUint i=0; i<=KMaxSampleRateIndex; i++)
+		{
+		if(KRateTableLookup[i].iSampleRate == aSampleRate)
+			{
+			aSampleRateValue = KRateTableLookup[i].iSampleRateValue;
+			err = KErrNone;
+			break;
+			}
+		}
+
+	//To avoid the value return a non desired value.
+	if (err != KErrNone)
+		{
+		aSampleRateValue = 0;
+		}
+
+	DP0_RET(err, "%d");
+	}
+
+
+// ---------------------------------------------------------------------------
+// CDevAudioControl::ResolveMode
+// ---------------------------------------------------------------------------
+TInt CDevAudioControl::ResolveMode(TUint aModeValue, TUid& aMode)
+	{
+	DP_CONTEXT(CDevAudioControl::ResolveMode *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	TInt err(KErrArgument);
+
+	
+	for (TInt i=0; i<=KMaxModeIndex; i++)
+		{
+		const TAudioModeTableEntry& entry = KModeTableLookup[i];
+		if (entry.iAudioModeValue == aModeValue)
+			{
+			aMode = entry.iAudioMode;
+			err = KErrNone;
+			break;
+			}
+		}
+	
+	DP0_RET(err,"%d");
+	}
+
+// ---------------------------------------------------------------------------
+// CDevAudioControl::GetModes
+// ---------------------------------------------------------------------------
+TUint CDevAudioControl::GetModes(const RArray<TUid>& aMode)
+	{
+	DP_CONTEXT(CDevAudioControl::GetModes *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	TUint result = 0;
+	TInt count = aMode.Count();
+
+	for (TInt i=0; i<count; i++)
+		{
+		result |= GetMode(aMode[i]);
+		}
+	DP0_RET(result,"%d");
+	}
+
+
+// ---------------------------------------------------------------------------
+// CDevAudioControl::GetMode
+// ---------------------------------------------------------------------------
+TUint CDevAudioControl::GetMode(TUid aMode)
+	{
+	DP_CONTEXT(CDevAudioControl::GetMode *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	
+	TUint result = 0;
+	
+	for (TInt e=0; e<=KMaxModeIndex; e++)
+		{
+		if(KModeTableLookup[e].iAudioMode == aMode)
+			{
+			result = KModeTableLookup[e].iAudioModeValue;
+			break;
+			}
+		}
+	DP0_RET(result,"%d");
+	}
+
+// ---------------------------------------------------------------------------
+// CDevAudioControl::GetSampleRates
+// ---------------------------------------------------------------------------
+TUint CDevAudioControl::GetSampleRates(const RArray<TInt>& aSampleRates)
+	{
+	DP_CONTEXT(CDevAudioControl::GetSampleRates *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	
+	TUint result = 0;
+	TInt count = aSampleRates.Count();
+	
+	for (TInt i=0; i<count; i++)
+		{
+		result |= GetSampleRate(aSampleRates[i]);
+		}
+	DP0_RET(result,"%d");
+	}
+
+// ---------------------------------------------------------------------------
+// CDevAudioControl::GetSampleRate
+// ---------------------------------------------------------------------------
+TUint CDevAudioControl::GetSampleRate(TInt aSampleRates)
+	{
+	DP_CONTEXT(CDevAudioControl::GetSampleRate *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	TUint result = 0;
+	TInt position = 0;
+	TInt lowerbound = 0;
+	TInt upperbound = KMaxSampleRateIndex;
+
+	if ((aSampleRates < KRateTableLookup[lowerbound].iSampleRateValue) || (aSampleRates > KRateTableLookup[upperbound].iSampleRateValue)) 
+		{
+		//value request not found in the array.
+		DP0_RET(result,"%d");
+		}
+
+	//Binary Search
+	position = ( lowerbound + upperbound) / 2;
+
+	while((KRateTableLookup[position].iSampleRateValue != aSampleRates) && (lowerbound <= upperbound))
+		{
+		if (KRateTableLookup[position].iSampleRateValue > aSampleRates)
+			{
+			upperbound = position - 1;
+			}
+		else
+			{
+			lowerbound = position + 1;
+			}
+		position = (lowerbound + upperbound) / 2;
+		}
+
+	result = KRateTableLookup[position].iSampleRate;
+
+	DP0_RET(result,"%d");
+	}
+
+// ---------------------------------------------------------------------------
+// CDevAudioControl::ProcessingFinishedReceived
+// ---------------------------------------------------------------------------
+TInt CDevAudioControl::ProcessingFinishedReceived(TBool& /*aAyncOperation*/)
+	{
+	return KErrNone;
+	}
+	
+// ---------------------------------------------------------------------------
+// CDevAudioControl::ProcessingError
+// ---------------------------------------------------------------------------
+TInt CDevAudioControl::ProcessingError(TBool& /*aAyncOperation*/)
+    {
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------------------------
+// CDevAudioControl::RequestEmptyBuffers
+// ---------------------------------------------------------------------------	
+TInt CDevAudioControl::RequestEmptyBuffers()
+	{
+	DP_CONTEXT(CDevAudioControl::RequestEmptyBuffers *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+
+	TInt err(KErrNotReady);
+
+	if(iDevAudio)
+		{
+		if(iDevAudio->iActiveState == EDevSoundAdaptorPaused_Primed)
+			{
+			err = iDevAudio->iAudioStream->Flush();
+			}
+		else if (iDevAudio->iActiveState == EDevSoundAdaptorActive_Active)
+			{
+			err = Pause();
+			if(err == KErrNone)
+				{
+				iPauseResumeSequenceDueToEmptyBuffers = ETrue;
+				}
+			
+			}
+		}
+	DP0_RET(err,"%d");
+	};
+
+void CDevAudioControl::Panic(TDevSoundAdaptorPanicCode aCode)
+	{
+	_LIT(KMMFDevSoundAdaptorPanicCategory, "DevSoundAdaptor");
+	User::Panic(KMMFDevSoundAdaptorPanicCategory, aCode);
+	}
+
+// ---------------------------------------------------------------------------
+// CDevAudioControl::GetTimePlayed
+// ---------------------------------------------------------------------------
+TInt CDevAudioControl::GetTimePlayed(TTimeIntervalMicroSeconds& aTime)
+	{
+	DP_CONTEXT(CDevAudioControl::GetTimePlayed *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	TInt err = iDevAudio->iAudioStream->GetStreamTime(aTime);
+	DP0_RET(err,"%d");
+	}
+
+// ---------------------------------------------------------------------------
+// CDevAudioControl::Resume
+// ---------------------------------------------------------------------------
+TBool CDevAudioControl::Resume()
+	{
+	DP_CONTEXT(CDevAudioControl::Stop *CD1*, CtxDevSound, DPLOCAL);
+	DP_IN();
+	ASSERT(EFalse);
+	DP0_RET(KErrNone, "%d");
+	}
+
+// -----------------------------------------------------------------------------
+// CDevAudioControl::BufferErrorEvent
+// -----------------------------------------------------------------------------
+//
+void CDevAudioControl::BufferErrorEvent()
+	{
+	ASSERT(EFalse); //This should never happen
+	}
+// End of file