--- /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