diff -r 000000000000 -r 40261b775718 devsound/a3fdevsound/src/devsoundadaptor/cdevaudiocontrol.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/devsound/a3fdevsound/src/devsoundadaptor/cdevaudiocontrol.cpp Tue Feb 02 01:56:55 2010 +0200 @@ -0,0 +1,1204 @@ +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + + + +#include "cdevaudiocontrol.h" + +#include +#include +#include +#include +#include +#include + + +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(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(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) + { + iDevAudio->iActiveState = EDevSoundAdaptorUninitialising; + err = iDevAudio->iAudioContext->Commit(); + } + + 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->iAudioContext->Commit(); + } + 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(GetSampleRate(iCurrentSampleRate)); + aConfig.iChannels = static_cast(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->iAudioContext->Commit(); + 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(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->iAudioContext->Commit(); + } + } + 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((iLegacyGain*iLegacyRight)/iLegacyLeft); + } + else + { + iChannelGains[ERightCh].iGain = iLegacyGain; + iChannelGains[ELeftCh].iGain = + static_cast((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->iAudioContext->Commit(); + } + if (err == KErrNone) + { + iDevAudio->iActiveState = EDevSoundAdaptorStopping; + } + } + break; + case EDevSoundAdaptorInitialised_Idle: + { + err = iDevAudio->iAudioStream->Unload(); + if(err == KErrNone) + { + err = iDevAudio->iAudioContext->Commit(); + } + if (err == KErrNone) + { + iDevAudio->iActiveState = EDevSoundAdaptorUnloading; + } + } + break; + case EDevSoundAdaptorInitialised_Initialised: + { + err = iDevAudio->iAudioStream->Uninitialize(); + if(err == KErrNone) + { + err = iDevAudio->iAudioContext->Commit(); + } + if (err == KErrNone) + { + iDevAudio->iActiveState = EDevSoundAdaptorUninitialising; + } + } + break; + case EDevSoundAdaptorCreated_Uninitialised: + readyToDestroy = ETrue; + 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->iAudioContext->Commit(); + } + + 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 + ((100*iLegacyGain)/(iLegacyGain+iChannelGains[ERightCh].iGain)); + iLegacyRight = 100 - iLegacyLeft; + //(not that accurate, but sufficient for now) + } + else + { + iLegacyGain = iChannelGains[ERightCh].iGain; + iLegacyRight = static_cast + ((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 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((100*gain)/(gain+iChannelGains[ERightCh].iGain)); + right = 100 - left; + } + else + { + gain = iChannelGains[ERightCh].iGain; + right = + static_cast((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; + } + 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; + } + 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 (aEvent == KUidA3FContextUpdateComplete) + { + iAdaptationObserver->AsynchronousOperationComplete(aError, ETrue); + } + else if(aEvent == KUidA3FContextPreEmption || aEvent == KUidA3FContextPreEmptedCommit) + { + + //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(); + } + } + 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& aMode) + { + DP_CONTEXT(CDevAudioControl::GetModes *CD1*, CtxDevSound, DPLOCAL); + DP_IN(); + + TUint result = 0; + TInt count = aMode.Count(); + + for (TInt i=0; i& aSampleRates) + { + DP_CONTEXT(CDevAudioControl::GetSampleRates *CD1*, CtxDevSound, DPLOCAL); + DP_IN(); + + TUint result = 0; + TInt count = aSampleRates.Count(); + + for (TInt i=0; i 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