sl@0: //audiostream.cpp
sl@0: 
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: 
sl@0: #include <a3f/a3fbase.h>
sl@0: #include <a3f/audioprocessingunittypeuids.h>
sl@0: #include <a3f/a3ffourcclookup.h>
sl@0: 
sl@0: #include "audiostream.h"
sl@0: 
sl@0: // PHYSICAL COMPONENTS
sl@0: #include "audiocodec.h"
sl@0: #include "audiostream.h"
sl@0: #include "buffersource.h"
sl@0: #include "buffersink.h"
sl@0: #include "audiodevicesource.h"
sl@0: #include "audiodevicesink.h"
sl@0: #include "audiogaincontrol.h"
sl@0: #include "maudiostreamadaptationobserver.h"
sl@0: 
sl@0: #include <a3f/maudiodatasupplier.h>
sl@0: #include <a3f/maudiodataconsumer.h>
sl@0: 
sl@0: #include "minputport.h"
sl@0: #include "moutputport.h"
sl@0: #include "audiocontext.h"
sl@0: 
sl@0: #include <ecom/implementationproxy.h>
sl@0: 
sl@0: 
sl@0: 
sl@0: const TInt KSampleRate8000Hz = 8000;
sl@0: 
sl@0: // Map the interface implementation UIDs to implementation factory functions
sl@0: const TImplementationProxy ImplementationTable[] =
sl@0: 	{
sl@0: 	IMPLEMENTATION_PROXY_ENTRY(0x10283461,  CAudioStream::NewL),
sl@0: 	};
sl@0: 
sl@0: 
sl@0: EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
sl@0: 	{
sl@0: 	aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
sl@0: 	return ImplementationTable;
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // Constructor
sl@0: // ---------------------------------------------------------------------------
sl@0: //
sl@0: CAudioStream::CAudioStream()
sl@0: 	: iCurrentStreamState(EUninitialized), 
sl@0: 	iDesiredStreamState(EUninitialized)
sl@0: 	{
sl@0: 	TRACE_CREATE();
sl@0: 	DP_CONTEXT(CAudioStream::CAudioStream *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	// Some init config values
sl@0: 	iSampleRateConfig = KSampleRate8000Hz;
sl@0: 	iModeConfig = KA3FModeMono;
sl@0: 	
sl@0: 	DP_OUT();
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // Factory method
sl@0: // ---------------------------------------------------------------------------
sl@0: //
sl@0: CAudioStream* CAudioStream::NewL()
sl@0: 	{
sl@0: 	DP_STATIC_CONTEXT(CAudioStream::NewL *CD0*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	CAudioStream* self = new(ELeave)CAudioStream();
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL();
sl@0: 	CleanupStack::Pop(self);
sl@0: 	DP0_RET(self, "0x%x");
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // Second phase constructor
sl@0: // ---------------------------------------------------------------------------
sl@0: //
sl@0: void CAudioStream::ConstructL()
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::ConstructL *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	DP_OUT();
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // Destructor
sl@0: // ---------------------------------------------------------------------------
sl@0: //
sl@0: CAudioStream::~CAudioStream()
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::~CAudioStream *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 
sl@0: 	iAudioStreamObservers.Close();
sl@0: 	iAudioCodecObservers.Close();
sl@0: 	// Just for now
sl@0: 	DeletePhysicalComponents();
sl@0: 	REComSession::FinalClose();
sl@0: 	DP_OUT();
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::RegisterAudioStreamObserver
sl@0: // ---------------------------------------------------------------------------
sl@0: //
sl@0: TInt CAudioStream::RegisterAudioStreamObserver(MAudioStreamAdaptationObserver& aObserver)
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::RegisterAudioStreamObserver *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	TInt err = iAudioStreamObservers.Find(&aObserver);
sl@0: 	if(err == KErrNotFound)
sl@0: 		{
sl@0: 		err = iAudioStreamObservers.Append(&aObserver);
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		err = KErrAlreadyExists;
sl@0: 		}
sl@0: 	DP0_RET(err, "%d");
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::UnregisterAudioStreamObserver
sl@0: // ---------------------------------------------------------------------------
sl@0: //
sl@0: void CAudioStream::UnregisterAudioStreamObserver(MAudioStreamAdaptationObserver& aObserver)
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::UnregisterAudioStreamObserver *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	TInt idxOrErr = iAudioStreamObservers.Find(&aObserver);
sl@0: 	if( idxOrErr != KErrNotFound )
sl@0: 		{
sl@0: 		iAudioStreamObservers.Remove(idxOrErr);
sl@0: 		}
sl@0: 	DP_OUT();
sl@0: 	}
sl@0: 
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::SetFourCC
sl@0: // ---------------------------------------------------------------------------
sl@0: //
sl@0: void CAudioStream::SetFourCC(const CFourCCConvertor& aFourCCConvertor)
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::SetFourCC *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	CFourCCConvertor& ref = const_cast<CFourCCConvertor&>(aFourCCConvertor);
sl@0: 	iFourCCConvertor = static_cast<CFourCCConvertor*>(static_cast<TAny*>(&ref));
sl@0: 	DP_OUT();
sl@0: 	}
sl@0: 
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::UnregisterAudioStreamObserver
sl@0: // ---------------------------------------------------------------------------
sl@0: //
sl@0: void CAudioStream::UnregisterAllAudioStreamObserver()
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::UnregisterAudioStreamObserver *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	
sl@0: 	iAudioStreamObservers.Reset();
sl@0: 	
sl@0: 	DP_OUT();
sl@0: 	}
sl@0: 
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // MMRC extension mechanism
sl@0: // ---------------------------------------------------------------------------
sl@0: TAny* CAudioStream::GetComponent(TUid aType)
sl@0: 	{
sl@0: 	TAny* ptr = NULL;
sl@0: 	MLogicalChain* clientDesiredChain = NULL;
sl@0: 	CAudioContext* context = static_cast<CAudioContext*>(iAudioContext);
sl@0: 	if(context)
sl@0: 		{
sl@0: 		clientDesiredChain = context->GetLogicalChain(0);	
sl@0: 		}
sl@0: 	if (clientDesiredChain)
sl@0: 		{
sl@0: 		ptr = clientDesiredChain->GetComponent(aType);
sl@0: 		}
sl@0: 	return ptr;
sl@0: 	}
sl@0: 	
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::Message
sl@0: // ---------------------------------------------------------------------------
sl@0: TInt CAudioStream::Message(MLogicalChain& aCurrentChain, MLogicalChain& aDesiredChain, MAudioContext& aContext, TInt aFlags)
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::Message *CD0*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	TInt err = KErrNone;
sl@0: 
sl@0: 	iCurrentChain = &aCurrentChain;
sl@0: 	iDesiredChain = &aDesiredChain;
sl@0: 
sl@0: 	TUint messageType = aDesiredChain.MessageType();
sl@0: 
sl@0: 	iAudioContext = &aContext;
sl@0: 
sl@0: 	CAudioContext* audioContext = static_cast<CAudioContext*> (iAudioContext);
sl@0: 	// TO NOTIFY DIRECTLY CONTEXT
sl@0: 	MMultimediaResourceControlObserver* mmrcObserver = static_cast<MMultimediaResourceControlObserver*>(audioContext);
sl@0: 
sl@0: 	// Register stream observer
sl@0: 	if (messageType & ERegisterStreamObserver != 0)
sl@0: 		{
sl@0: 		// Use MMRC extension mechanism
sl@0: 		TAny* ptr = GetComponent(KUidAudioStreamAdaptationObserver);	
sl@0: 		MAudioStreamAdaptationObserver* observer = static_cast<MAudioStreamAdaptationObserver*>(ptr);
sl@0: 		if(observer)
sl@0: 			{
sl@0: 			err = RegisterAudioStreamObserver(*observer);	
sl@0: 			}
sl@0: 		}
sl@0: 	
sl@0: 	// Register codec observer
sl@0: 	if (messageType & ERegisterCodecObserver != 0)
sl@0: 		{
sl@0: 		// Use MMRC extension mechanism
sl@0: 		TAny* ptr = GetComponent(KUidAudioCodecObserver);
sl@0: 		MAudioCodecObserver* observer = static_cast<MAudioCodecObserver*>(ptr);
sl@0: 		if (observer) 
sl@0: 			{
sl@0: 			err = RegisterAudioCodecObserver(*observer);	
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	// Component creation
sl@0: 	TUint bit = messageType & EComponentCreation;
sl@0: 	if( (err == KErrNone) && (bit != 0) )
sl@0: 		{
sl@0: 		CAudioContext* context = static_cast<CAudioContext*>(iAudioContext);
sl@0: 		MLogicalChain* clientDesiredChain = context->GetLogicalChain(0);	
sl@0: 		err = CreatePhysicalComponents(*clientDesiredChain);
sl@0: 
sl@0: 		// For Configuration
sl@0: 		if (err==KErrNone)
sl@0: 			{
sl@0: 			clientDesiredChain->SetAdaptationStream(*this);
sl@0: 			clientDesiredChain->SetStreamBufferControl(*this);
sl@0: 			}
sl@0: 		}
sl@0: 	
sl@0: 	// Component alteration
sl@0: 	// Changes that must be applied before stream state transition
sl@0: 	TBool configCodec = EFalse;
sl@0: 	bit = messageType & EComponentAlterationCodec;
sl@0: 	if( (err == KErrNone) && (bit != 0) )
sl@0: 		{
sl@0: 		// Set Format
sl@0: 		if(iCodec)
sl@0: 			{
sl@0: 			TUid desiredCodecFormat  = iDesiredChain->CodecFormat();
sl@0: 			err = iCodec->SetFormat( desiredCodecFormat );
sl@0: 			} 
sl@0: 		
sl@0: 		if(err == KErrNone)
sl@0: 			{
sl@0: 			//if samplerate or mode has changed, update value and trigger callbacks at appropriate point
sl@0: 			if ((iDesiredChain->GetSampleRate() > 0) && (iDesiredChain->GetSampleRate() != iSampleRateConfig))
sl@0: 				{
sl@0: 				iSampleRateConfig = iDesiredChain->GetSampleRate();
sl@0: 				configCodec = ETrue;
sl@0: 				}
sl@0: 			if ((iDesiredChain->GetMode() != KNullUid) && (iDesiredChain->GetMode() != iModeConfig))
sl@0: 				{
sl@0: 				iModeConfig  = iDesiredChain->GetMode();
sl@0: 				configCodec = ETrue;
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 
sl@0: 	bit = messageType & EComponentAlterationGain;
sl@0: 	if( (err == KErrNone) && (bit != 0) )
sl@0: 		{
sl@0: 		// Apply volume ramp
sl@0: 		// Note that ramp operation and gain now are applied separately because current tone arquitecture 
sl@0: 		// need the volume ramp to be set before start the tonehwdevice 
sl@0: 		TTimeIntervalMicroSeconds currentRampTimeValue = 0; 
sl@0: 		TUid currentRampTimeOperation(KNullUid);
sl@0: 		TTimeIntervalMicroSeconds desiredRampTimeValue = 0; 
sl@0: 		TUid desiredRampTimeOperation(KNullUid);
sl@0: 		iCurrentChain->GetVolumeRampParameters(currentRampTimeOperation, currentRampTimeValue);
sl@0: 		iDesiredChain->GetVolumeRampParameters(desiredRampTimeOperation, desiredRampTimeValue);
sl@0: 		
sl@0: 		if(currentRampTimeOperation != desiredRampTimeOperation ||
sl@0: 		currentRampTimeValue.Int64() != desiredRampTimeValue.Int64() )
sl@0: 			{
sl@0: 			if (iGainControl)
sl@0: 				{
sl@0: 				err = iGainControl->ConfigureRamp(desiredRampTimeOperation, desiredRampTimeValue);
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	//Configuration request
sl@0: 	// Stream state
sl@0: 	TBool invokeStateEventCallback = EFalse;
sl@0: 	iDesiredStreamState = iDesiredChain->StreamState();
sl@0: 	if( (err == KErrNone) && (iCurrentStreamState != iDesiredStreamState) )
sl@0: 		{
sl@0: 		err = ChangeState(iCurrentStreamState, iDesiredStreamState);
sl@0: 		if (err == KErrNone)
sl@0: 			{
sl@0: 			iCurrentStreamState = iDesiredStreamState;
sl@0: 			}
sl@0: 		invokeStateEventCallback = ETrue;
sl@0: 		}
sl@0: 
sl@0: 	// Component alteration
sl@0: 	// Changes that must be applied after stream state transition
sl@0: 	TBool gainUpdated = EFalse;
sl@0: 	bit = messageType & EComponentAlterationGain;
sl@0: 	if( (err == KErrNone) && (bit != 0) )
sl@0: 		{
sl@0: 		TAny* ptr = GetComponent(KUidAudioGainControl);
sl@0: 		MAudioGainControl* gaincontrol = static_cast<MAudioGainControl*>(ptr);
sl@0: 		if (iGainControl && gaincontrol)
sl@0: 			{
sl@0: 			RArray<TAudioChannelGain> channels;
sl@0: 			TInt err = gaincontrol->GetGain(channels);
sl@0: 			if (channels.Count() != 0 )
sl@0: 				{
sl@0: 				err = iGainControl->SetGain(channels);
sl@0: 				gainUpdated = ETrue;
sl@0: 				}
sl@0: 			channels.Close();
sl@0: 			}
sl@0: 		}
sl@0: 	
sl@0: 	TBool invokeCodecCallbacks = EFalse;
sl@0: 	bit = messageType & EComponentAlterationCodec;
sl@0: 	if ( (err == KErrNone) && (bit != 0) && configCodec && (iCurrentStreamState == EInitialized) )
sl@0: 		{
sl@0: 		//codec loading actually configures sample rate and mode
sl@0: 		ASSERT(iCodec);
sl@0: 		err = iCodec->Load(iSampleRateConfig, iModeConfig);
sl@0: 		iIsCodecConfig = (err == KErrNone);
sl@0: 		invokeCodecCallbacks = ETrue;
sl@0: 		if ( err != KErrNone )
sl@0: 			{
sl@0: 			//get back to previous values in case of error
sl@0: 			iSampleRateConfig = iCurrentChain->GetSampleRate();
sl@0: 			iModeConfig = iCurrentChain->GetMode();
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	// Component destruction
sl@0: 	bit = messageType & EComponentDestruction;
sl@0: 	if( (err == KErrNone) && (bit != 0) )
sl@0: 		{
sl@0: 		DeletePhysicalComponents();
sl@0: 		}
sl@0: 
sl@0: 	TUint isStopping = aFlags & KServerStopping;
sl@0: 	TUint preemptionRequest = aFlags & KPreemptionRequest;
sl@0: 
sl@0: 	// HERE WE CAN GUARANTEE THAT THE REQUEST IS SUCCESFUL
sl@0: 	// Notify context 
sl@0: 	// 1ST CALLBACK
sl@0: 	if(!preemptionRequest) 
sl@0: 		{
sl@0: 		mmrcObserver->ReceiveResourceUpdate(&aDesiredChain, KErrNone);
sl@0: 		}
sl@0: 	else 
sl@0: 		{
sl@0: 		mmrcObserver->ReceivePreemptionUpdate(&aDesiredChain, err);
sl@0: 		}
sl@0: 
sl@0: 	// Processing unit callbacks
sl@0: 	// Gain control
sl@0: 	// Note that due to error checking before applying any change 
sl@0: 	// this callback always returned the error obtained by calling SetGain
sl@0: 	// or KErrNone
sl@0: 	if(gainUpdated)
sl@0: 		{
sl@0: 		if (iGainControl)
sl@0: 			{
sl@0: 			iGainControl->IssueGainChangedCallBack(err);
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	// Stream 
sl@0: 	if(invokeStateEventCallback)
sl@0: 		{
sl@0: 		invokeStateEventCallback = EFalse;
sl@0: 		for ( TUint idx(0); idx < iAudioStreamObservers.Count(); idx++ )
sl@0: 			{
sl@0: 			if ( !isStopping )
sl@0: 				{
sl@0: 				iAudioStreamObservers[idx]->StateEvent(err, iCurrentStreamState);
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 	if( invokeCodecCallbacks && (iCurrentStreamState == EInitialized) )
sl@0: 		{
sl@0: 		TInt count = iAudioCodecObservers.Count();
sl@0: 		for ( TInt idx = 0; idx < count; idx++ )
sl@0: 			{
sl@0: 			//TODO replace this functionality with the new mmrc
sl@0: 			iAudioCodecObservers[idx]->SampleRateSet(err);
sl@0: 			iAudioCodecObservers[idx]->ModeSet(err);
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	// Now has no effect on context
sl@0: 	// But it's needed to let the MMRC know about the operation being completed
sl@0: 	// and in such way let it to know that 
sl@0: 	for ( TUint idx(0); idx < iAudioStreamObservers.Count(); idx++ )
sl@0: 		{
sl@0: 		if ( !isStopping )
sl@0: 			{
sl@0: 			iAudioStreamObservers[idx]->PhysicalAdaptationEvent(EOperationComplete, err);
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	// Don't need to send last callback sync
sl@0: 	// Let MMRC do it
sl@0: 
sl@0: 	DP0_RET(err, "%d");
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::DeletePhysicalComponents
sl@0: // ---------------------------------------------------------------------------
sl@0: void CAudioStream::DeletePhysicalComponents()
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::DeletePhysicalComponents *CD0*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	if(iBufferSource)
sl@0: 		{
sl@0: 		delete iBufferSource;
sl@0: 		iBufferSource = NULL;
sl@0: 		}
sl@0: 	if(iBufferSink)
sl@0: 		{
sl@0: 		delete iBufferSink;
sl@0: 		iBufferSink = NULL;
sl@0: 		}
sl@0: 	if(iCodec)
sl@0: 		{
sl@0: 		delete iCodec;
sl@0: 		iCodec = NULL;
sl@0: 		iIsCodecConfig = EFalse;
sl@0: 		}
sl@0: 	if(iGainControl)
sl@0: 		{
sl@0: 		delete iGainControl;
sl@0: 		iGainControl = NULL;
sl@0: 		}
sl@0: 	if(iDeviceSource)
sl@0: 		{
sl@0: 		delete iDeviceSource;
sl@0: 		iDeviceSource = NULL;
sl@0: 		}
sl@0: 	if(iDeviceSink)
sl@0: 		{
sl@0: 		delete iDeviceSink;
sl@0: 		iDeviceSink= NULL;
sl@0: 		}
sl@0: 	DP_OUT();
sl@0: 	}
sl@0: 
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::CreatePhysicalComponents
sl@0: // ---------------------------------------------------------------------------
sl@0: TInt CAudioStream::CreatePhysicalComponents(MLogicalChain& aDesiredChain)
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::CreatePhysicalComponents *CD0*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	
sl@0: 	TInt err = KErrNone;
sl@0: 	TInt units = aDesiredChain.AudioProcessingUnitsCount();
sl@0: 	TInt index=0;
sl@0: 	TUid typeId;
sl@0: 
sl@0: 	for (index=0; index < units ; index++)
sl@0: 		{
sl@0: 		typeId = aDesiredChain.AudioProcessingUnitUid(index);
sl@0: 
sl@0: 		// By the moment all components 
sl@0: 		if (err == KErrNone)
sl@0: 			{
sl@0: 			if (typeId == KUidAudioDecoder || typeId == KUidAudioEncoder )
sl@0: 				{
sl@0: 				if(!iCodec)
sl@0: 					{
sl@0: 					TRAP(err, iCodec = CAudioCodec::NewL(typeId, *iFourCCConvertor ));
sl@0: 					iIsCodecConfig = EFalse;
sl@0: 					iCodec->RegisterAudioCodecObserver(*this);
sl@0: 					TAny* ptr = GetComponent(KUidAudioCodecAdaptationObserver);
sl@0: 					MAudioCodecAdaptationObserver* observer = static_cast<MAudioCodecAdaptationObserver*>(ptr);
sl@0: 					if(observer)
sl@0: 						{
sl@0: 						iCodec->RegisterAudioCodecObserver(*observer);
sl@0: 						}
sl@0: 					// For HW custom interface
sl@0: 					aDesiredChain.SetCustomInterfaceProvider(*iCodec);
sl@0: 					}
sl@0: 				if(iGainControl)
sl@0: 					{
sl@0: 					iGainControl->SetHelper(*iCodec);
sl@0: 					}
sl@0: 				// This mechanism is temporary and must  be replaced
sl@0: 				// with the Extension mechanism when the MMRC server
sl@0: 				aDesiredChain.SetStreamPositionControl(*iCodec);
sl@0: 				}
sl@0: 			else if (typeId == KUidMmfBufferSource)
sl@0: 				{
sl@0: 				if(!iBufferSource)
sl@0: 					{
sl@0: 					TRAP(err,iBufferSource = CBufferSource::NewL());
sl@0: 					// This mechanism is temporary and must  be replaced
sl@0: 					// with the Extension mechanism when the MMRC server
sl@0: 					aDesiredChain.SetAdaptationSource(*iBufferSource);
sl@0: 					/*
sl@0: 					TAny* ptr = aDesiredChain.GetComponent(KUidMmfBufferSource);
sl@0: 					MMMFAudioDataSupplier* supplier = static_cast<MMMFAudioDataSupplier*>(ptr);
sl@0: 					if(supplier)
sl@0: 						{
sl@0: 						iBufferSource->SetDataSupplier(*supplier);
sl@0: 						}
sl@0: 					*/
sl@0: 					}
sl@0: 				}
sl@0: 			else if (typeId == KUidMmfBufferSink)
sl@0: 				{
sl@0: 				if(!iBufferSink)
sl@0: 					{
sl@0: 					TRAP(err, iBufferSink = CBufferSink::NewL());
sl@0: 					// This mechanism is temporary and must  be replaced
sl@0: 					// with the Extension mechanism when the MMRC server
sl@0: 					aDesiredChain.SetAdaptationSink(*iBufferSink);
sl@0: 					}
sl@0: 				}
sl@0: 			else if (typeId == KUidAudioGainControl)
sl@0: 				{
sl@0: 				if(!iGainControl)
sl@0: 					{
sl@0: 					// This mechanism is temporary and must  be replaced
sl@0: 					// with the Extension mechanism when the MMRC server
sl@0: 					TRAP(err, iGainControl = CAudioGainControl::NewL());
sl@0: 					aDesiredChain.SetAdaptationGainControl(*iGainControl);
sl@0: 					}
sl@0: 				}
sl@0: 			else if (typeId == KUidAudioDeviceSink)
sl@0: 				{
sl@0: 				if(!iDeviceSink)
sl@0: 					{
sl@0: 					TRAP(err, iDeviceSink = CAudioDeviceSink::NewL());
sl@0: 					}
sl@0: 				}
sl@0: 			else if (typeId == KUidAudioDeviceSource)
sl@0: 				{
sl@0: 				if(!iDeviceSource)
sl@0: 					{
sl@0: 					TRAP(err, iDeviceSource = CAudioDeviceSource::NewL());
sl@0: 					}
sl@0: 				}
sl@0: 			else
sl@0: 				{
sl@0: 				err = KErrNotSupported;
sl@0: 				}
sl@0: 			}
sl@0: 		
sl@0: 		// Notify the observers
sl@0: 		for ( TUint idx(0); idx < iAudioStreamObservers.Count(); idx++ )
sl@0: 			{
sl@0: 			iAudioStreamObservers[idx]->AddProcessingUnitComplete(typeId, err);
sl@0: 			}
sl@0: 		}
sl@0: 	DP0_RET(err, "%d");
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::CreateDataPath
sl@0: // ---------------------------------------------------------------------------
sl@0: TInt CAudioStream::CreateDataPath()
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::CreateDataPath *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	TInt err(KErrNotReady);
sl@0: 
sl@0: 	if(iBufferSource && iCodec) // && iSink && iGain)
sl@0: 		{
sl@0: 		// TMode == Decode
sl@0: 		if(KErrNone == iBufferSource->GetOutputPort(iOutputport) && KErrNone == iCodec->GetInputPort(iInputport))
sl@0: 			{
sl@0: 			iOutputport->SetInput(iInputport);
sl@0: 			iInputport->SetOutput(iOutputport);
sl@0: 			err = KErrNone;
sl@0: 			}
sl@0: 		}
sl@0: 	else if(iBufferSink && iCodec) // && iSink && iGain)
sl@0: 		{
sl@0: 		//TMode == Encode
sl@0: 		if(KErrNone == iCodec->GetOutputPort(iOutputport)  && KErrNone == iBufferSink->GetInputPort(iInputport))
sl@0: 			{
sl@0: 			iOutputport->SetInput(iInputport);
sl@0: 			iInputport->SetOutput(iOutputport);
sl@0: 			err = KErrNone;
sl@0: 			}
sl@0: 		}
sl@0: 	DP0_RET(err, "%d");
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::DemolishDataPath
sl@0: // ---------------------------------------------------------------------------
sl@0: //
sl@0: TInt CAudioStream::DemolishDataPath()
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::DemolishDataPath *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	iOutputport->RemoveInput(iInputport);
sl@0: 	iInputport->RemoveOutput(iOutputport);
sl@0: 	DP0_RET(KErrNone, "%d");
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::ChangeState
sl@0: // ---------------------------------------------------------------------------	
sl@0: TInt CAudioStream::ChangeState(TAudioState aPreviousState, TAudioState aDesiredState)
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::ChangeState *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	TInt err(KErrNone);
sl@0: 	iCurrentStreamState = aPreviousState;
sl@0: 	iDesiredStreamState = aDesiredState;
sl@0: 
sl@0: 	// Ensure that there is no dereference of a NULL pointer
sl@0: 	ASSERT(iDesiredStreamState < EInitialized || iDesiredStreamState > EActive || iCodec);
sl@0: 	
sl@0: 	switch (iDesiredStreamState)
sl@0: 		{
sl@0: 		case EInitialized:
sl@0: 			{
sl@0: 			if (iCurrentStreamState == EUninitialized) //Initialize
sl@0: 				{
sl@0: 				err = CreateDataPath();
sl@0: 				if(err == KErrNone)
sl@0: 					{
sl@0: 					err = iCodec->Initialize();
sl@0: 					}
sl@0: 				}
sl@0: 			else if( iCurrentStreamState == EIdle ) //codec unload (actually, unconfig)
sl@0: 				{
sl@0: 				iIsCodecConfig = EFalse;
sl@0: 				err = KErrNone;
sl@0: 				}
sl@0: 			// Preemption 
sl@0: 			// This A3F adaptation allows going from Active/Primed directly to initialised
sl@0: 			// otherwise reference MMRC would need to handle those transitions separately 
sl@0: 			else if(iCurrentStreamState == EActive || iCurrentStreamState == EPrimed) 
sl@0: 				{
sl@0: 				// To Idle 
sl@0: 				err = iCodec->Stop();
sl@0: 				// To Initilised
sl@0: 				iIsCodecConfig = EFalse;
sl@0: 				}
sl@0: 				
sl@0: 			if(err == KErrNone)
sl@0: 				{
sl@0: 				iCurrentStreamState = EInitialized;
sl@0: 				}
sl@0: 			break;
sl@0: 			}
sl@0: 		case EIdle:
sl@0: 			{
sl@0: 			if ( (iCurrentStreamState == EInitialized) && !iIsCodecConfig )
sl@0: 				{
sl@0: 				//codec loading actually configures sample rate and mode
sl@0: 				err = iCodec->Load(iSampleRateConfig, iModeConfig);
sl@0: 				iIsCodecConfig = (err == KErrNone);
sl@0: 				}
sl@0: 			else if (iCurrentStreamState == EActive)
sl@0: 				{
sl@0: 				err = iCodec->Stop();
sl@0: 				}
sl@0: 			else if (iCurrentStreamState == EPrimed)
sl@0: 				{
sl@0: 				err = iCodec->Stop();
sl@0: 				}
sl@0: 
sl@0: 			if(err == KErrNone)
sl@0: 				{
sl@0: 				iTimeProcessed = 0;
sl@0: 				iCurrentStreamState = EIdle;
sl@0: 				}
sl@0: 			break;
sl@0: 			}
sl@0: 		case EPrimed:
sl@0: 			{
sl@0: 			if (iCurrentStreamState == EIdle)
sl@0: 				{
sl@0: 				DP0(DLINFO,"==============  Stream is going from EIdle -> PRIMED");
sl@0: 				DP0(DLINFO,"Nothing to be done");
sl@0: 				}
sl@0: 			else if (iCurrentStreamState == EActive)
sl@0: 				{
sl@0: 				DP0(DLINFO,"============== Stream is going from EActive -> PRIMED");
sl@0: 				err = iCodec->Pause();
sl@0: 				}
sl@0: 			if(err == KErrNone)
sl@0: 				{
sl@0: 				iCurrentStreamState = EPrimed;
sl@0: 				}
sl@0: 			break;
sl@0: 			}
sl@0: 		case EActive:
sl@0: 			{
sl@0: 			if (iCurrentStreamState == EPrimed) //Activate from Primed
sl@0: 				{
sl@0: 				// Reusing AudioCodec::Start for resuming
sl@0: 				DP0(DLINFO,"==============  Stream is going from EPrimed -> ACTIVE");
sl@0: 				err = iCodec->Start();
sl@0: 				}
sl@0: 			else if(iCurrentStreamState == EIdle) //Activate from Idle
sl@0: 				{
sl@0: 				DP0(DLINFO,"==============  Stream is going from EIdle -> ACTIVATE");
sl@0: 				err = iCodec->Start();
sl@0: 				}
sl@0: 
sl@0: 			if(err == KErrNone)
sl@0: 				{
sl@0: 				iCurrentStreamState = EActive;
sl@0: 				}
sl@0: 			break;
sl@0: 			}
sl@0: 		case EUninitialized:
sl@0: 			{
sl@0: 			err = DemolishDataPath();
sl@0: 			if(err == KErrNone)
sl@0: 				{
sl@0: 				iCurrentStreamState = EUninitialized;
sl@0: 				}
sl@0: 			break;
sl@0: 			}
sl@0: 		case EDead:
sl@0: 			{
sl@0: 			err = DemolishDataPath();
sl@0: 			if(err == KErrNone)
sl@0: 				{
sl@0: 				iCurrentStreamState = EDead;
sl@0: 				}
sl@0: 			break;
sl@0: 			}
sl@0: 		default:
sl@0: 			err = KErrNotSupported;
sl@0: 			DP1(DLINFO,"CAudioStream::ChangeState Unknown state! %d", iDesiredStreamState);
sl@0: 			break;
sl@0: 		}
sl@0: 	DP0_RET(err, "%d");
sl@0: 	}
sl@0: 
sl@0: TInt CAudioStream::FlushBuffers()
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::FlushBuffers *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	
sl@0: 	TInt err = KErrNone;
sl@0: 
sl@0: 	MOutputPort* outPort= static_cast<MOutputPort*>(iCodec);
sl@0: 	if(outPort)
sl@0: 		{
sl@0: 		outPort->FlushBuffer(this);
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		err = KErrNotReady;
sl@0: 		}
sl@0: 	err = KErrNone;
sl@0: 	DP0_RET(err, "%d");
sl@0: 	}
sl@0: 
sl@0: 
sl@0: void CAudioStream::FlushComplete(TInt aError)
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::FlushComplete *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	TUint count = iAudioStreamObservers.Count();
sl@0: 	for ( TUint i(0); i < count; i++ )
sl@0: 		{
sl@0: 		iAudioStreamObservers[i]->FlushComplete(aError);
sl@0: 		}
sl@0: 	DP_OUT();
sl@0: 	}
sl@0: 
sl@0: void CAudioStream::AllBuffersProcessed()
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::AllBuffersProcessed *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	TUint count = iAudioStreamObservers.Count();
sl@0: 	for ( TUint i(0); i < count; i++ )
sl@0: 		{
sl@0: 		iAudioStreamObservers[i]->ProcessingFinished();
sl@0: 		}
sl@0: 	DP_OUT();
sl@0: 	}
sl@0: 
sl@0: void CAudioStream::ProcessingUnitError(TInt /*aError*/)
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::ProcessingUnitError *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	DP_OUT();
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::RegisterAudioCodecObserver
sl@0: // ---------------------------------------------------------------------------
sl@0: TInt CAudioStream::RegisterAudioCodecObserver(MAudioCodecObserver& aObserver)
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::RegisterAudioCodecObserver *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	TInt err = iAudioCodecObservers.Find(&aObserver);
sl@0: 	if(err == KErrNotFound)
sl@0: 		{
sl@0: 		err = iAudioCodecObservers.Append(&aObserver);
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		err = KErrAlreadyExists;
sl@0: 		}
sl@0: 	DP0_RET(err, "%d");
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::UnregisterAudioCodecObserver
sl@0: // ---------------------------------------------------------------------------
sl@0: void CAudioStream::UnregisterAudioCodecObserver(MAudioCodecObserver& aObserver)
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::UnregisterAudioCodecObserver *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	TInt idxOrErr = iAudioCodecObservers.Find(&aObserver);
sl@0: 	if( idxOrErr != KErrNotFound )
sl@0: 		{
sl@0: 		iAudioCodecObservers.Remove(idxOrErr);
sl@0: 		}
sl@0: 	DP_OUT();
sl@0: 	}
sl@0: 
sl@0: void CAudioStream::GetSupportedAModesComplete(TInt /*aError*/)
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::GetSupportedAModesComplete *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	DP_OUT();
sl@0: 	}
sl@0: 
sl@0: void CAudioStream::GetSupportedARatesComplete(TInt /*aError*/)
sl@0: 	{
sl@0: 	DP_CONTEXT(CAudioStream::GetSupportedARatesComplete *CD1*, CtxDevSound, DPLOCAL);
sl@0: 	DP_IN();
sl@0: 	DP_OUT();
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::GetSupportedSampleRates
sl@0: // ---------------------------------------------------------------------------
sl@0: TInt CAudioStream::GetSupportedSampleRates(RArray<TInt>& aSupportedRates)
sl@0: 	{
sl@0: 	TInt err = (KErrNotReady);
sl@0: 	err = iCodec->SupportedRates(aSupportedRates);
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: // ---------------------------------------------------------------------------
sl@0: // CAudioStream::GetSupportedModes
sl@0: // ---------------------------------------------------------------------------
sl@0: TInt CAudioStream::GetSupportedModes(RArray<TUid>& aSupportedModes)
sl@0: 	{
sl@0: 	TInt err = (KErrNotReady);
sl@0: 	err = iCodec->SupportedModes(aSupportedModes);
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: // end of file