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