sl@0: // Copyright (c) 2002-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: #include sl@0: #include "CustomMmfAudioController.h" sl@0: sl@0: #include sl@0: #include "ActrlTestUids.h" sl@0: sl@0: _LIT(KTestWavFile19, "c:\\mm\\mmf\\testfiles\\actrl\\newmail.wav"); sl@0: sl@0: /** sl@0: * sl@0: * NewL sl@0: * sl@0: */ sl@0: CMMFController* CCustomMmfAudioController::NewL() sl@0: { sl@0: CCustomMmfAudioController* self = new(ELeave) CCustomMmfAudioController; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop( self ); sl@0: sl@0: return STATIC_CAST( CMMFController*, self ); sl@0: } sl@0: /** sl@0: * sl@0: * ~CCustomMmfAudioController sl@0: * sl@0: */ sl@0: CCustomMmfAudioController::~CCustomMmfAudioController() sl@0: { sl@0: delete iStoppingMessage; sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * CCustomMmfAudioController sl@0: * sl@0: */ sl@0: CCustomMmfAudioController::CCustomMmfAudioController() sl@0: :CMMFAudioController(), iIsTest(EFalse) sl@0: { sl@0: } sl@0: sl@0: /** sl@0: * PrimeL sl@0: * sl@0: * If Prime fails the client should reset the controller sl@0: * becaused as noted below this code is not transactional. sl@0: * sl@0: */ sl@0: void CCustomMmfAudioController::PrimeL(TMMFMessage& aMessage) sl@0: { sl@0: PrimeL(); sl@0: aMessage.Complete(KErrNone); sl@0: } sl@0: void CCustomMmfAudioController::PlayL(TMMFMessage& aMessage) sl@0: { sl@0: PlayL(); sl@0: aMessage.Complete(KErrNone); sl@0: } sl@0: void CCustomMmfAudioController::PauseL(TMMFMessage& aMessage) sl@0: { sl@0: PauseL(); sl@0: aMessage.Complete(KErrNone); sl@0: } sl@0: sl@0: void CCustomMmfAudioController::PrimeL() sl@0: { sl@0: // apply heap check's here sl@0: // Note if they fail this is the end of the controller sl@0: sl@0: // call the base class functionality sl@0: TRAPD( errorCode, CMMFAudioController::PrimeL()); sl@0: // send an event back to the test framework with sl@0: // the error code sl@0: TMMFEvent aEvent( KPrimeTestId, errorCode ); sl@0: DoSendEventToClient(aEvent); sl@0: //[ we need to preserve the leave semantics for the caller] sl@0: User::LeaveIfError( errorCode ); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * PlayL sl@0: * sl@0: */ sl@0: void CCustomMmfAudioController::PlayL() sl@0: { sl@0: // call the base class functionality sl@0: TRAPD( errorCode, CMMFAudioController::PlayL()); sl@0: // send an event back to the test framework with sl@0: // the error code sl@0: TMMFEvent aEvent( KPlayTestId, errorCode ); sl@0: DoSendEventToClient(aEvent); sl@0: //[ we need to preserve the leave semantics for the caller] sl@0: User::LeaveIfError( errorCode ); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MapdSetVolumeL sl@0: * sl@0: */ sl@0: void CCustomMmfAudioController::MapdSetVolumeL(TInt aVolume) sl@0: { sl@0: //Special return code to test fix for PDEF120609, test case id MM-MMF-ACLNT-U-0277-CP sl@0: if (aVolume == -999) sl@0: { sl@0: User::Leave(-12345); sl@0: } sl@0: CMMFAudioController::MapdSetVolumeL( aVolume ); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MapdGetMaxVolumeL sl@0: * sl@0: */ sl@0: void CCustomMmfAudioController::MapdGetMaxVolumeL(TInt& aMaxVolume) sl@0: { sl@0: CMMFAudioController::MapdGetMaxVolumeL( aMaxVolume ); sl@0: } sl@0: sl@0: /** sl@0: * MapdGetVolumeL sl@0: * sl@0: */ sl@0: void CCustomMmfAudioController::MapdGetVolumeL(TInt& aVolume) sl@0: { sl@0: CMMFAudioController::MapdGetVolumeL( aVolume ); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: *PauseL sl@0: * sl@0: */ sl@0: void CCustomMmfAudioController::PauseL() sl@0: { sl@0: TRAPD( errorCode,CMMFAudioController::PauseL()); sl@0: //[ send pause event ] sl@0: TMMFEvent aEvent( KPauseTestId, errorCode ); sl@0: DoSendEventToClient(aEvent); sl@0: //[ we need to preserve the leave semantics for the caller] sl@0: User::LeaveIfError( errorCode ); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * StopL sl@0: * sl@0: */ sl@0: void CCustomMmfAudioController::StopL() sl@0: { sl@0: TRAPD( errorCode,CMMFAudioController::StopL()); sl@0: //[ send stop event ] sl@0: TMMFEvent aEvent( KStopTestId, errorCode ); sl@0: DoSendEventToClient(aEvent); sl@0: //[ we need to preserve the leave semantics for the caller] sl@0: User::LeaveIfError( errorCode ); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * ResetL sl@0: * sl@0: */ sl@0: void CCustomMmfAudioController::ResetL() sl@0: { sl@0: TRAPD( errorCode,CMMFAudioController::ResetL()); sl@0: //[ send stop event ] sl@0: TMMFEvent aEvent( KResetTestId, errorCode ); sl@0: DoSendEventToClient(aEvent); sl@0: //[ we need to preserve the leave semantics for the caller] sl@0: User::LeaveIfError( errorCode ); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * RemoveDataSourceL sl@0: * sl@0: */ sl@0: void CCustomMmfAudioController::RemoveDataSourceL(MDataSource& aDataSource) sl@0: { sl@0: TRAPD( errorCode,CMMFAudioController::RemoveDataSourceL( aDataSource)); sl@0: //[ send stop event ] sl@0: TMMFEvent aEvent( KRemoveDataSourceTestId, errorCode ); sl@0: DoSendEventToClient(aEvent); sl@0: //[ we need to preserve the leave semantics for the caller] sl@0: User::LeaveIfError( errorCode ); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * RemoveDataSinkL sl@0: * sl@0: */ sl@0: void CCustomMmfAudioController::RemoveDataSinkL(MDataSink& aDataSink) sl@0: { sl@0: TRAPD( errorCode,CMMFAudioController::RemoveDataSinkL( aDataSink)); sl@0: //[ send stop event ] sl@0: TMMFEvent aEvent( KRemoveDataSinkTestId, errorCode ); sl@0: DoSendEventToClient(aEvent); sl@0: //[ we need to preserve the leave semantics for the caller] sl@0: User::LeaveIfError( errorCode ); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MarcSetMaxFileSizeL sl@0: * sl@0: */ sl@0: sl@0: void CCustomMmfAudioController::MarcSetMaxFileSizeL(TInt aFileSize) sl@0: { sl@0: TRAPD( errorCode,CMMFAudioController::MarcSetMaxFileSizeL( aFileSize)); sl@0: //[ send stop event ] sl@0: TMMFEvent aEvent( KMarcSetMaxFileSizeId, errorCode ); sl@0: DoSendEventToClient(aEvent); sl@0: //[ we need to preserve the leave semantics for the caller] sl@0: User::LeaveIfError( errorCode ); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * MarcGetRecordTimeAvailableL sl@0: * @param aTime sl@0: * sl@0: */ sl@0: void CCustomMmfAudioController::MarcGetRecordTimeAvailableL(TTimeIntervalMicroSeconds& aTime) sl@0: { sl@0: TRAPD( errorCode,CMMFAudioController::MarcGetRecordTimeAvailableL( aTime)); sl@0: //[ send stop event ] sl@0: TMMFEvent aEvent( KMarcGetRecordTimeAvailId, errorCode ); sl@0: DoSendEventToClient(aEvent); sl@0: //[ we need to preserve the leave semantics for the caller] sl@0: User::LeaveIfError( errorCode ); sl@0: } sl@0: sl@0: sl@0: /** sl@0: * sl@0: * CustomCommand sl@0: * sl@0: */ sl@0: void CCustomMmfAudioController::CustomCommand(TMMFMessage& aMessage) sl@0: { sl@0: //[ check if the command is for the custom plugin sl@0: // otherwise pass it on to the real audio controller ] sl@0: TRAPD(err, iStoppingMessage = CCustomMMFMessageHolder::NewL(aMessage)); sl@0: if (err != KErrNone) sl@0: { sl@0: aMessage.Complete(err); sl@0: return; sl@0: } sl@0: sl@0: iIsTest = ETrue; sl@0: if( IsMemoryAllocCmd( aMessage ) ) sl@0: { sl@0: //[ it is a alloc memory test command ] sl@0: // [ new algorithm adopted from M&G database ] sl@0: // sl@0: TInt errorCode = KErrNone; sl@0: TInt failCount = 1; sl@0: TBool completed = EFalse; sl@0: TBool badResult = EFalse; sl@0: TBool reachedEnd = EFalse; sl@0: sl@0: for( ; ; ) sl@0: { sl@0: __UHEAP_SETFAIL(RHeap::EFailNext ,failCount); // Leavescan will think __UHEAP_SETFAIL is a leaving function due to the macro ending in 'L'. Does not leave sl@0: sl@0: //NB: Do not use __MM_HEAP_MARK macro's in this test, the cleaning up the CustomMMFAudioController sl@0: //is insufficient to remove all possible allocated memory from the framework. sl@0: //CMMFControllerProxyServer::DoStartThreadL has been updated to do heap checking for sl@0: //the whole server thread. sl@0: sl@0: //[ run a scenario of the major api sl@0: //functions which alloc memory in the controller] sl@0: TRAP( errorCode, AllocMemoryTestL()); sl@0: sl@0: if( errorCode == KErrNone ) sl@0: { sl@0: // [ check we have passed through all allocs in the test] sl@0: TAny* testAlloc = User::Alloc(1); sl@0: if( testAlloc == NULL ) sl@0: { sl@0: reachedEnd = ETrue; sl@0: failCount -= 1; // Failcount of 1 equates to 0 successful allocs, etc. sl@0: } sl@0: else sl@0: { sl@0: User::Free( testAlloc ); sl@0: } sl@0: sl@0: completed = reachedEnd || badResult; sl@0: sl@0: } sl@0: else if( errorCode != KErrNoMemory ) sl@0: { sl@0: // [ we failed for some reason other than memory sl@0: // allocation, so fail the test ] sl@0: completed = ETrue; sl@0: badResult = ETrue; sl@0: } sl@0: sl@0: __UHEAP_SETFAIL(RHeap::ENone ,0); sl@0: sl@0: // [ exit the loop ] sl@0: if( completed ) sl@0: { sl@0: break; sl@0: } sl@0: sl@0: failCount +=1; sl@0: } sl@0: sl@0: //This flag is used by the audio controller to alter its behaviour sl@0: //slightly to allow these tests to work sl@0: iIsTest=EFalse; sl@0: sl@0: if(!badResult) sl@0: { sl@0: aMessage.Complete(KErrNone); sl@0: } sl@0: else sl@0: { sl@0: aMessage.Complete(errorCode); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: //[ let the plugin process the message ] sl@0: CMMFAudioController::CustomCommand(aMessage); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * IsMemoryAllocCmd sl@0: * sl@0: */ sl@0: TBool CCustomMmfAudioController::IsMemoryAllocCmd( TMMFMessage& ) sl@0: { sl@0: return ETrue; sl@0: } sl@0: sl@0: sl@0: static void CleanupController(TAny* ptr) sl@0: { sl@0: CMMFAudioController* controller = STATIC_CAST(CMMFAudioController*, ptr); sl@0: TRAP_IGNORE(controller->CMMFAudioController::ResetL()); sl@0: } sl@0: sl@0: sl@0: /** sl@0: * sl@0: * AllocMemoryTest sl@0: * sl@0: */ sl@0: TInt CCustomMmfAudioController::AllocMemoryTestL() sl@0: { sl@0: TMMFFileConfig fileConfig; // audio file sl@0: sl@0: fileConfig().iPath = KTestWavFile19; sl@0: sl@0: //[ lets manufacture a source and sink ] sl@0: sl@0: //[Create the source] sl@0: MDataSource* source = MDataSource::NewSourceL(KUidMmfFileSource, fileConfig); sl@0: CleanupDeletePushL(source); sl@0: sl@0: //[ Create the sink ] sl@0: MDataSink* sink = MDataSink::NewSinkL(KUidMmfAudioOutput, KNullDesC8); sl@0: CleanupDeletePushL(sink); sl@0: sl@0: // Use a cleanup item to stop & reset the controller and so remove the data sl@0: // sources/sinks automatically when this funtion leaves. This can be done sl@0: // before the sinks/sources are added. sl@0: TCleanupItem cleanupItem(CleanupController, this); sl@0: CleanupStack::PushL(cleanupItem); sl@0: sl@0: sl@0: //[ add the source ] sl@0: CMMFAudioController::AddDataSourceL(*source); sl@0: sl@0: //[ add the sink ] sl@0: CMMFAudioController::AddDataSinkL(*sink); sl@0: sl@0: //[ prime ] sl@0: CMMFAudioController::PrimeL(); sl@0: sl@0: //[ play ] sl@0: CMMFAudioController::PlayL(); sl@0: sl@0: //[ pause ] sl@0: CMMFAudioController::PauseL(); sl@0: sl@0: //[ play ] sl@0: CMMFAudioController::PlayL(); sl@0: sl@0: //[ stop ] sl@0: CMMFAudioController::StopL(iStoppingMessage->iMessage); sl@0: sl@0: // [ prime ] sl@0: CMMFAudioController::PrimeL(); sl@0: sl@0: //[ reset ] sl@0: CMMFAudioController::ResetL(); sl@0: sl@0: CleanupStack::PopAndDestroy(3);// source, sink, cleanupItem sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: //Leaves with KErrNoMemory. sl@0: CMMFController* CMemoryFailAudioController::NewL() sl@0: { sl@0: if(ETrue) //condition used to avoid any warning sl@0: { sl@0: User::Leave(KErrNoMemory); sl@0: } sl@0: return NULL; sl@0: } sl@0: CMemoryFailAudioController::CMemoryFailAudioController():CMMFAudioController() sl@0: { sl@0: } sl@0: CMemoryFailAudioController::~CMemoryFailAudioController() sl@0: { sl@0: if(iSink) sl@0: { sl@0: iSink->SinkThreadLogoff(); sl@0: } sl@0: if(iClip) sl@0: { sl@0: iClip->SourceThreadLogoff(); sl@0: } sl@0: } sl@0: sl@0: void CMemoryFailAudioController::AddDataSourceL(MDataSource& aSource) sl@0: { sl@0: if (iClip) sl@0: { sl@0: User::Leave(KErrAlreadyExists); sl@0: } sl@0: if ((aSource.DataSourceType()==KUidMmfDescriptorSource)|| sl@0: (aSource.DataSourceType()==KUidMmfFileSource)) sl@0: { sl@0: User::LeaveIfError(aSource.SourceThreadLogon(*this)); sl@0: iClip = static_cast(&aSource); sl@0: if(iClip->Size()) sl@0: { sl@0: iClip->SourcePrimeL(); sl@0: } sl@0: else sl@0: { sl@0: iClip->SourceStopL(); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: } sl@0: sl@0: void CMemoryFailAudioController::AddDataSinkL(MDataSink& aSink) sl@0: { sl@0: if(iMMFDevSound) sl@0: { sl@0: User::Leave(KErrAlreadyExists); sl@0: } sl@0: if (aSink.DataSinkType()!=KUidMmfAudioOutput) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: User::LeaveIfError(aSink.SinkThreadLogon(*this)); sl@0: iSink = &aSink; sl@0: MMMFAudioOutput* audioOutput = static_cast(&aSink); sl@0: iMMFDevSound = &(audioOutput->SoundDevice()); sl@0: iMMFDevSound->SetPrioritySettings(iPrioritySettings); sl@0: return; sl@0: } sl@0: sl@0: void CMemoryFailAudioController::SetPrioritySettings(const TMMFPrioritySettings& aSettings) sl@0: { sl@0: iPrioritySettings = aSettings; sl@0: if (iMMFDevSound) sl@0: { sl@0: iMMFDevSound->SetPrioritySettings(aSettings); sl@0: } sl@0: } sl@0: sl@0: //Does not acces files; returns hard-coded value. sl@0: TTimeIntervalMicroSeconds CMemoryFailAudioController::DurationL()const sl@0: { sl@0: return TTimeIntervalMicroSeconds(1000000); //return 1sec sl@0: } sl@0: sl@0: CMMFController* CMemoryPassAudioController::NewL() sl@0: { sl@0: CMemoryPassAudioController* self = new (ELeave) CMemoryPassAudioController(); sl@0: return STATIC_CAST( CMMFController*, self ); sl@0: } sl@0: CMemoryPassAudioController::CMemoryPassAudioController():CMemoryFailAudioController() sl@0: { sl@0: } sl@0: sl@0: //Derived from Audio Controller. Panics the controller thread after the play is started sl@0: CMMFController* CPanicAudioController::NewL() sl@0: { sl@0: CPanicAudioController* self = new(ELeave) CPanicAudioController; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop( self ); sl@0: return static_cast(self); sl@0: } sl@0: sl@0: CPanicAudioController::CPanicAudioController():CMMFAudioController() sl@0: { sl@0: } sl@0: sl@0: CPanicAudioController::~CPanicAudioController() sl@0: { sl@0: delete iPanicTimer; sl@0: } sl@0: sl@0: void CPanicAudioController::AddDataSourceL(MDataSource& aSource) sl@0: { sl@0: TRAP_IGNORE(CMMFAudioController::AddDataSourceL(aSource)); sl@0: } sl@0: sl@0: void CPanicAudioController::AddDataSinkL(MDataSink& aSink) sl@0: { sl@0: TRAP_IGNORE(CMMFAudioController::AddDataSinkL(aSink)); sl@0: } sl@0: sl@0: void CPanicAudioController::PrimeL() sl@0: { sl@0: TRAP_IGNORE(CMMFAudioController::PrimeL()); sl@0: } sl@0: sl@0: void CPanicAudioController::PlayL() sl@0: { sl@0: TRAP_IGNORE(CMMFAudioController::PlayL()); sl@0: //trigger the panic sl@0: iPanicTimer->Start(1000000, 1000000, TCallBack(PanicTimerComplete, this)); sl@0: } sl@0: sl@0: void CPanicAudioController::ConstructL() sl@0: { sl@0: CMMFAudioController::ConstructL(); sl@0: iPanicTimer = CPeriodic::NewL(CActive::EPriorityStandard); sl@0: } sl@0: sl@0: TTimeIntervalMicroSeconds CPanicAudioController::DurationL()const sl@0: { sl@0: return TTimeIntervalMicroSeconds(0); sl@0: } sl@0: sl@0: void CPanicAudioController::SetPositionL(const TTimeIntervalMicroSeconds& aPosition) sl@0: { sl@0: TRAP_IGNORE(CMMFAudioController::SetPositionL(aPosition)); sl@0: } sl@0: sl@0: TInt CPanicAudioController::PanicTimerComplete(TAny* /*aParent*/) sl@0: { sl@0: User::Panic(_L("CustomMmfAudioController"), 0); sl@0: return KErrNone; sl@0: } sl@0: