diff -r 000000000000 -r 40261b775718 devsound/a3fdevsound/src/mmfdevsoundproxy/mmfdevsoundproxy.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/devsound/a3fdevsound/src/mmfdevsoundproxy/mmfdevsoundproxy.cpp Tue Feb 02 01:56:55 2010 +0200 @@ -0,0 +1,1458 @@ +// 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 FILES +#include "mmfdevsoundproxy.h" + +// SYMBIAN_CHECK used to add extra asserts when MACRO is added - helps debugging overall A3F + +#ifdef SYMBIAN_FULL_STATE_CHECK + #define SYMBIAN_CHECK(c,p) __ASSERT_ALWAYS(c,p) +#else + #define SYMBIAN_CHECK(c,p) +#endif + +const TInt KMaxMessageQueueItems = 8; + +const TMMFCapabilities KZeroCapabilities = + { + 0,0,0,0 // all zero's + }; + +// ============================ LOCAL FUNCTIONS ================================ + +// ----------------------------------------------------------------------------- +// This function raises a panic +// +// @param aError +// one of the several panic codes that may be raised by this dll +// +// @panic EMMFDevSoundProxyPlayDataWithoutInitialize is raised when playdata +// is called without initialization +// @panic EMMFDevSoundProxyRecordDataWithoutInitialize is raised when +// recorddata is called without initialization +// +GLDEF_C void Panic(TMMFDevSoundProxyPanicCodes aPanicCode) + { + User::Panic(KMMFDevSoundProxyPanicCategory, aPanicCode); + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// RMMFDevsoundProxy::RMMFDevsoundProxy +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +EXPORT_C RMMFDevSoundProxy::RMMFDevSoundProxy() : + iBuffer(NULL), + iSeqName(NULL), + iDestinationPckg(TMMFMessageDestination(KUidInterfaceMMFDevSound, + KMMFObjectHandleDevSound)), + iState(EIdle), + iAudioServerProxy(NULL), + iDevSoundObserver(NULL), + iMsgQueueHandler(NULL), + iCustIntPckg() + { + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::Close +// Close the server session +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::Close() + { + if (iAudioServerProxy) + { + if (iAudioServerProxy->Handle() != NULL) + { + TMMFDevSoundProxySettings set; + TMMFDevSoundProxySettingsPckg pckg(set); + TInt err = SendReceive(EMMFDevSoundProxyClose, + iDestinationPckg, + pckg); + } + iAudioServerProxy->Close(); + delete iAudioServerProxy; + iAudioServerProxy = NULL; + } + RMmfSessionBase::Close(); + iState = EIdle; + if (iMsgQueueHandler) + { + iMsgQueueHandler->Cancel(); + delete iMsgQueueHandler; + iMsgQueueHandler = NULL; + } + iMsgQueue.Close(); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::Open +// Open a DevSound server session +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::Open() + { + TInt err = iMsgQueue.CreateGlobal(KNullDesC, KMaxMessageQueueItems); + // global, accessible to all that have its handle + + if (err == KErrNone) + { + iAudioServerProxy = NULL; + iMsgQueueHandler = NULL; + iBuffer = NULL; + iAudioServerProxy = new RMMFAudioServerProxy(); + if (iAudioServerProxy == NULL) + { + err = KErrNoMemory; + } + } + if (err == KErrNone) + { + err = iAudioServerProxy->Open(); + } + if (err == KErrNone) + { + err = SetReturnedHandle(iAudioServerProxy->GetDevSoundSessionHandle()); + } + if (err) + { + Close(); + } + return err; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::PostOpen +// Finish opening process +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::PostOpen() + { + return SendReceive(EMMFDevSoundProxyPostOpen, iDestinationPckg); + } + + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::SetDevSoundInfo +// Launch DevSound that might have been waiting for audio policy. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::SetDevSoundInfo() + { + return SendReceive(EMMFAudioLaunchRequests); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::InitializeL +// Initialize DevSound for a specific mode. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::InitializeL( + MDevSoundObserver& aDevSoundObserver, + TMMFState aMode, + MMMFDevSoundCustomInterfaceObserver& aDevSoundCIObserver) + { + TInt err = KErrNone; + iDevSoundObserver = &aDevSoundObserver; + + if (!(iState==EIdle || iState==EInitialized)) + { + err = KErrNotReady; + } + else + { + TMMFDevSoundProxySettings set; + set.iMode = aMode; + TMMFDevSoundProxySettingsPckg pckg(set); + TIpcArgs args(&iDestinationPckg, &pckg, iMsgQueue); + err = RSessionBase::SendReceive(EMMFDevSoundProxyInitialize1, args); + if (err == KErrNone) + { + StartReceivingMsgQueueHandlerEventsL(aDevSoundCIObserver); + iState = EInitializing; + } + } + + User::LeaveIfError(err); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::InitializeL +// Initialize DevSound with specific HwDevice id and mode. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::InitializeL( + MDevSoundObserver& /*aDevSoundObserver*/, + TUid /*aHWDev*/, + TMMFState /*aMode*/, + MMMFDevSoundCustomInterfaceObserver& /*aDevSoundCIObserver*/) + { + TInt err = KErrNotSupported; + User::LeaveIfError(err); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::InitializeL +// Initialize DevSound for the specific FourCC and mode. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::InitializeL( + MDevSoundObserver& aDevSoundObserver, + TFourCC aDesiredFourCC, + TMMFState aMode, + MMMFDevSoundCustomInterfaceObserver& aDevSoundCIObserver) + { + TInt err = KErrNone; + if(aMode == EMMFStateTonePlaying) + { + User::Leave(KErrNotSupported); + } + iDevSoundObserver = &aDevSoundObserver; + if (!(iState==EIdle || iState==EInitialized)) + { + err = KErrNotReady; + } + else + { + TMMFDevSoundProxySettings set; + set.iDesiredFourCC = aDesiredFourCC; + set.iMode = aMode; + TMMFDevSoundProxySettingsPckg pckg(set); + TIpcArgs args(&iDestinationPckg, &pckg, iMsgQueue); + err = RSessionBase::SendReceive(EMMFDevSoundProxyInitialize4, args); + if (err == KErrNone) + { + StartReceivingMsgQueueHandlerEventsL(aDevSoundCIObserver); + iState = EInitializing; + } + } + + User::LeaveIfError(err); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::Capabilities +// Returns the capabilities of the DevSound server. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TMMFCapabilities RMMFDevSoundProxy::Capabilities() + { + // TODO should we use the following ? SYMBIAN_CHECK(iState>=EInitialized, Panic(EMMFDevSoundProxyCapabilitiesInWrongState)); + if (iState < EInitialized) + { + // call has been made before we are initialized. Not much we can do, so return + // dummy values but hit debugger on the emulator + __DEBUGGER() + RDebug::Print(_L("BRDBG:CapabilitiesCalledWhenNotInitialised")); // TODO Remove or redo as trace + return KZeroCapabilities; + } + TMMFDevSoundProxySettings set; + TMMFDevSoundProxySettingsPckg pckg(set); + TInt err = SendReceiveResult(EMMFDevSoundProxyCapabilities, + iDestinationPckg, + KNullDesC8, + pckg); + if (err == KErrNone) + { + return pckg().iCaps; + } + else + { + return KZeroCapabilities; + } + } + +// ----------------------------------------------------------------------------- +// TMMFCapabilities RMMFDevSoundProxy::Config +// Returns the current configuration of the DevSound. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TMMFCapabilities RMMFDevSoundProxy::Config() + { + // TODO should we use the following ? SYMBIAN_CHECK(iState>=EInitialized, Panic(EMMFDevSoundProxyConfigInWrongState)); + if (iState < EInitialized) + { + // call has been made before we are initialized. Not much we can do, so return + // dummy values but hit debugger on the emulator + __DEBUGGER() + RDebug::Print(_L("BRDBG:ConfigCalledWhenNotInitialised")); // TODO Remove or redo as trace + return KZeroCapabilities; + } + TMMFDevSoundProxySettings set; + TMMFDevSoundProxySettingsPckg pckg(set); + SendReceiveResult(EMMFDevSoundProxyConfig, + iDestinationPckg, + KNullDesC8, + pckg); + return pckg().iConfig; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::SetConfigL +// Configures the DevSound server. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::SetConfigL( + const TMMFCapabilities& aConfig ) + { + TInt err = KErrNone; + + if (iState==EInitialized) + { + TMMFDevSoundProxySettings set; + set.iConfig = aConfig; + TMMFDevSoundProxySettingsPckg pckg(set); + TInt err = SendReceive(EMMFDevSoundProxySetConfig, + iDestinationPckg, + pckg); + User::LeaveIfError(err); + } + else + { + RDebug::Print(_L("BRDBG:SetConfigCalledWhenNotInitialised")); // TODO Remove or redo as trace + err = KErrNotReady; + } + + User::LeaveIfError(err); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::MaxVolume +// Returns the maximum volume supported by DevSound server for playing back.. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::MaxVolume() + { + TMMFDevSoundProxySettings set; + TMMFDevSoundProxySettingsPckg pckg(set); + SendReceiveResult(EMMFDevSoundProxyMaxVolume, + iDestinationPckg, + KNullDesC8, + pckg); + return pckg().iMaxVolume; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::Volume +// Returns the current volume. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::Volume() + { + TMMFDevSoundProxySettings set; + TMMFDevSoundProxySettingsPckg pckg(set); + SendReceiveResult(EMMFDevSoundProxyVolume, + iDestinationPckg, + KNullDesC8, + pckg); + return pckg().iVolume; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::SetVolume +// Sets the current volume. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::SetVolume(TInt aVolume ) + { + TMMFDevSoundProxySettings set; + set.iVolume = aVolume; + TMMFDevSoundProxySettingsPckg pckg(set); + return SendReceive(EMMFDevSoundProxySetVolume, + iDestinationPckg, + pckg); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::MaxGain +// Returns maximum gain supported by DevSound server for recording. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::MaxGain() + { + TMMFDevSoundProxySettings set; + TMMFDevSoundProxySettingsPckg pckg(set); + SendReceiveResult(EMMFDevSoundProxyMaxGain, + iDestinationPckg, + KNullDesC8, + pckg); + return pckg().iMaxGain; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::Gain +// Returns the current gain. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::Gain() + { + TMMFDevSoundProxySettings set; + TMMFDevSoundProxySettingsPckg pckg(set); + SendReceiveResult(EMMFDevSoundProxyGain, + iDestinationPckg, + KNullDesC8, + pckg); + return pckg().iGain; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::SetGain +// Sets the current gain. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::SetGain( + TInt aGain ) + { + TMMFDevSoundProxySettings set; + set.iGain = aGain; + TMMFDevSoundProxySettingsPckg pckg(set); + return SendReceive(EMMFDevSoundProxySetGain, + iDestinationPckg, + pckg); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::GetPlayBalanceL +// Returns play balance. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::GetPlayBalanceL( + TInt& aLeftPercentage, + TInt& aRightPercentage ) + { + TMMFDevSoundProxySettings set; + TMMFDevSoundProxySettingsPckg pckg(set); + User::LeaveIfError(SendReceiveResult(EMMFDevSoundProxyPlayBalance, + iDestinationPckg, + KNullDesC8, + pckg)); + aLeftPercentage = pckg().iLeftPercentage; + aRightPercentage = pckg().iRightPercentage; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::SetPlayBalanceL +// Sets playbalance. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::SetPlayBalanceL( + TInt aLeftPercentage, + TInt aRightPercentage ) + { + TMMFDevSoundProxySettings set; + set.iLeftPercentage = aLeftPercentage; + set.iRightPercentage = aRightPercentage; + TMMFDevSoundProxySettingsPckg pckg(set); + User::LeaveIfError(SendReceive(EMMFDevSoundProxySetPlayBalance, + iDestinationPckg, + pckg)); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::GetRecordBalanceL +// Returns record balance. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::GetRecordBalanceL( + TInt& aLeftPercentage, + TInt& aRightPercentage ) + { + TMMFDevSoundProxySettings set; + TMMFDevSoundProxySettingsPckg pckg(set); + User::LeaveIfError(SendReceiveResult(EMMFDevSoundProxyRecordBalance, + iDestinationPckg, + KNullDesC8, + pckg)); + aLeftPercentage = pckg().iLeftPercentage; + aRightPercentage = pckg().iRightPercentage; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::SetRecordBalanceL +// Sets record balance. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::SetRecordBalanceL( + TInt aLeftPercentage, + TInt aRightPercentage ) + { + TMMFDevSoundProxySettings set; + set.iLeftPercentage = aLeftPercentage; + set.iRightPercentage = aRightPercentage; + TMMFDevSoundProxySettingsPckg pckg(set); + User::LeaveIfError(SendReceive(EMMFDevSoundProxySetRecordBalance, + iDestinationPckg, + pckg)); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::PlayInitL +// Initilaizes DevSound to play digital audio and starts the play process. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::PlayInitL() + { + if (!iDevSoundObserver || iState!=EInitialized) + { + if (iState == EPlaying || iState == EPlayingBufferWait) + { + // treat PlayInitL() during play as Resume() + User::LeaveIfError(Resume()); + return; + } + User::Leave(KErrNotReady); + } + + User::LeaveIfError(SendReceive(EMMFDevSoundProxyPlayInit, + iDestinationPckg)); + iState = EPlaying; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::RecordInitL +// Initilaizes DevSound to record digital audio and starts the record process. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::RecordInitL() + { + if (!iDevSoundObserver || iState!=EInitialized) + { + if(iState == ERecording || iState == ERecordingBufferWait || iState == ERecordingInLastBufferCycle + || iState == ERecordingResumingInLastBufferCycle) + { + // treat RecordInitL() during record as Resume() + User::LeaveIfError(Resume()); + return; + } + User::Leave(KErrNotReady); + } + + User::LeaveIfError(SendReceive(EMMFDevSoundProxyRecordInit, + iDestinationPckg)); + iState = ERecording; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::PlayData +// Plays the data in the buffer at the current volume. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::PlayData() + { + __ASSERT_ALWAYS(iState == EPlaying || iState == EPlayingBufferWait, + Panic(EMMFDevSoundProxyPlayDataWithoutInitialize)); + ASSERT(iDevSoundObserver); + SYMBIAN_CHECK( iState == EPlayingBufferWait, + Panic(EMMFDevSoundProxyPlayDataInWrongState)); + TMMFDevSoundProxyHwBuf set; + set.iLastBuffer = iBuffer->LastBuffer(); + set.iBufferSize = iBuffer->Data().Size(); + TMMFDevSoundProxyHwBufPckg pckg(set); + + SendReceive(EMMFDevSoundProxyPlayData, iDestinationPckg, pckg); + iState = EPlaying; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::RecordData +// Signals the device to continue recording. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::RecordData() + { + __ASSERT_ALWAYS(iState == ERecording || iState == ERecordingBufferWait || + iState == ERecordingInLastBufferCycle || iState == ERecordingResumingInLastBufferCycle, + Panic(EMMFDevSoundProxyRecordDataWithoutInitialize)); + ASSERT(iDevSoundObserver); + SYMBIAN_CHECK(iState == ERecordingBufferWait || iState == ERecordingInLastBufferCycle || + iState == ERecordingResumingInLastBufferCycle, + Panic(EMMFDevSoundProxyPlayDataInWrongState)); + switch (iState) + { + case ERecordingBufferWait: + // standard case + SendReceive(EMMFDevSoundProxyRecordData, iDestinationPckg); + iState = ERecording; + break; + case ERecordingInLastBufferCycle: + // ack of the last buffer. Just swallow - the server should not be sent an ack + iState = ERecording; + break; + case ERecordingResumingInLastBufferCycle: + // this is a RecordData() following a Resume() in the last cycle. This is where we do the resume! + SendReceive(EMMFDevSoundProxyResume, iDestinationPckg); // note ignore any error + iState = ERecording; + break; + } + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::Stop +// Stops the ongoing opeartion. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::Stop() + { + if (iState > EInitialized) + { + SendReceive(EMMFDevSoundProxyStop, iDestinationPckg); + iState = EInitialized; + iMsgQueueHandler->Finish(); // will delete the buffer + } + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::Pause +// Temporarily stops the ongoing operation. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::Pause() + { + if(iState > EInitialized) + { + SendReceive(EMMFDevSoundProxyPause, iDestinationPckg); + } + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::PlayToneL +// Plays the simple tone. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::PlayToneL( + TInt aFrequency, + const TTimeIntervalMicroSeconds& aDuration) + { + if(iState==ETonePlaying) + { + return; + } + + if (!iDevSoundObserver || iState!=EInitialized) + { + User::Leave(KErrNotReady); + } + + TMMFDevSoundProxySettings set; + set.iFrequencyOne = aFrequency; + set.iDuration = aDuration; + TMMFDevSoundProxySettingsPckg pckg(set); + User::LeaveIfError(SendReceive(EMMFDevSoundProxyPlayTone, + iDestinationPckg, + pckg)); + iState = ETonePlaying; + iToneMode = ESimple; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::PlayDualToneL +// Plays the dual tone. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::PlayDualToneL( + TInt aFrequencyOne, + TInt aFrequencyTwo, + const TTimeIntervalMicroSeconds& aDuration) + { + if(iState==ETonePlaying) + { + return; + } + + if (!iDevSoundObserver || iState!=EInitialized) + { + User::Leave(KErrNotReady); + } + + TMMFDevSoundProxySettings set; + set.iFrequencyOne = aFrequencyOne; + set.iFrequencyTwo = aFrequencyTwo; + set.iDuration = aDuration; + TMMFDevSoundProxySettingsPckg pckg(set); + User::LeaveIfError(SendReceive(EMMFDevSoundProxyPlayDualTone, iDestinationPckg, pckg)); + iState = ETonePlaying; + iToneMode = EDual; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::PlayDTMFStringL +// Plays the DTMF string. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::PlayDTMFStringL(const TDesC& aDTMFString) + { + if(iState==ETonePlaying) + { + return; + } + + if (!iDevSoundObserver || iState!=EInitialized) + { + User::Leave(KErrNotReady); + } + + TPtr tempPtr(0,0); + tempPtr.Set(CONST_CAST(TUint16*, aDTMFString.Ptr()), + aDTMFString.Length(), + aDTMFString.Length()); + + User::LeaveIfError(SendReceiveResult(EMMFDevSoundProxyPlayDTMFString, + iDestinationPckg, + KNullDesC8, + tempPtr)); + iState = ETonePlaying; + iToneMode = EDTMFString; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::PlayToneSequenceL +// Plays the tone sequence. (NRT/RNG) +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::PlayToneSequenceL(const TDesC8& aData ) + { + if(iState==ETonePlaying) + { + return; + } + + if (!iDevSoundObserver || iState!=EInitialized) + { + User::Leave(KErrNotReady); + } + + User::LeaveIfError(SendReceive(EMMFDevSoundProxyPlayToneSequence, + iDestinationPckg, + aData)); + iState = ETonePlaying; + iToneMode = ESequence; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::PlayFixedSequenceL +// Plays the fixed sequence. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::PlayFixedSequenceL(TInt aSequenceNumber) + { + if(iState==ETonePlaying) + { + return; + } + + if (!iDevSoundObserver || iState!=EInitialized) + { + User::Leave(KErrNotReady); + } + + TPckgBuf seqNum(aSequenceNumber); + User::LeaveIfError(SendReceive(EMMFDevSoundProxyPlayFixedSequence, iDestinationPckg, seqNum)); + iState = ETonePlaying; + iToneMode = EFixedSequence; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::SetDTMFLengths +// Set attributes for playing DTMF String. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::SetDTMFLengths( + TTimeIntervalMicroSeconds32& aToneOnLength, + TTimeIntervalMicroSeconds32& aToneOffLength, + TTimeIntervalMicroSeconds32& aPauseLength ) + { + TMMFDevSoundProxySettings set; + set.iToneOnLength = aToneOnLength; + set.iToneOffLength = aToneOffLength; + set.iPauseLength = aPauseLength; + TMMFDevSoundProxySettingsPckg pckg(set); + SendReceive(EMMFDevSoundProxySetDTMFLengths, iDestinationPckg, pckg); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::SetVolumeRamp +// Sets the volume ramp duration. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::SetVolumeRamp( + const TTimeIntervalMicroSeconds& aRampDuration) + { + TMMFDevSoundProxySettings set; + set.iDuration = aRampDuration; + TMMFDevSoundProxySettingsPckg pckg(set); + SendReceive(EMMFDevSoundProxySetVolumeRamp, iDestinationPckg, pckg); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::GetSupportedInputDataTypesL +// Returns supported datatypes for playing audio. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::GetSupportedInputDataTypesL( + RArray& aSupportedDataTypes, + const TMMFPrioritySettings& aPrioritySettings) + { + aSupportedDataTypes.Reset(); + + TMMFPrioritySettings prioritySet = aPrioritySettings; + TMMFPrioritySettingsPckg pckg(prioritySet); + + TPckgBuf numberOfElementsPckg; + User::LeaveIfError(SendReceiveResult( + EMMFDevSoundProxyGetSupportedInputDataTypes, + iDestinationPckg, + pckg, + numberOfElementsPckg)); + + + HBufC8* buf = HBufC8::NewLC(numberOfElementsPckg()*sizeof(TFourCC)); + TPtr8 ptr = buf->Des(); + + + User::LeaveIfError(SendReceiveResult(EMMFDevSoundProxyCopyFourCCArrayData, + iDestinationPckg, + KNullDesC8, + ptr)); + + RDesReadStream stream(ptr); + CleanupClosePushL(stream); + + + TInt count = numberOfElementsPckg(); + for (TInt i = 0; i < count; i++) + { + TInt err = aSupportedDataTypes.Append(stream.ReadInt32L()); + if (err) + {//note we don't destroy array because we don't own it + //but we do reset it as it is incomplete + aSupportedDataTypes.Reset(); + User::Leave(err); + } + } + CleanupStack::PopAndDestroy(&stream); + CleanupStack::PopAndDestroy(buf); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::GetSupportedOutputDataTypesL +// Returns supported datatypes for recording audio. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::GetSupportedOutputDataTypesL( + RArray& aSupportedDataTypes, + const TMMFPrioritySettings& aPrioritySettings) + { + aSupportedDataTypes.Reset(); + + TMMFPrioritySettings prioritySet = aPrioritySettings; + TMMFPrioritySettingsPckg pckg(prioritySet); + + TPckgBuf numberOfElementsPckg; + User::LeaveIfError(SendReceiveResult( + EMMFDevSoundProxyGetSupportedOutputDataTypes, + iDestinationPckg, + pckg, + numberOfElementsPckg)); + + + HBufC8* buf = HBufC8::NewLC(numberOfElementsPckg()*sizeof(TFourCC)); + TPtr8 ptr = buf->Des(); + + + User::LeaveIfError(SendReceiveResult(EMMFDevSoundProxyCopyFourCCArrayData, + iDestinationPckg, + KNullDesC8, + ptr)); + RDesReadStream stream(ptr); + CleanupClosePushL(stream); + + + TInt count = numberOfElementsPckg(); + for (TInt i = 0; i < count; i++) + { + TInt err = aSupportedDataTypes.Append(stream.ReadInt32L()); + if (err) + {//note we don't destroy array because we don't own it + //but we do reset it as it is incomplete + aSupportedDataTypes.Reset(); + User::Leave(err); + } + } + CleanupStack::PopAndDestroy(&stream); + CleanupStack::PopAndDestroy(buf); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::SamplesRecorded +// Returns samples recorded so far. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::SamplesRecorded() + { + TPckgBuf numSamples; + SendReceiveResult(EMMFDevSoundProxySamplesRecorded, + iDestinationPckg, + KNullDesC8, + numSamples); + + return numSamples(); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::SamplesPlayed +// Returns samples played so far. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::SamplesPlayed() + { + TPckgBuf numSamples; + SendReceiveResult(EMMFDevSoundProxySamplesPlayed, + iDestinationPckg, + KNullDesC8, + numSamples); + return numSamples(); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::SetToneRepeats +// Sets tone repeats +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::SetToneRepeats( + TInt aRepeatCount, + const TTimeIntervalMicroSeconds& + aRepeatTrailingSilence) + { + TPckgBuf countRepeat(aRepeatCount); + TPckgBuf repeatTS(aRepeatTrailingSilence); + SendReceive(EMMFDevSoundProxySetToneRepeats, + iDestinationPckg, + countRepeat, + repeatTS); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::SetPrioritySettings +// Sets priority settings +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::SetPrioritySettings( + const TMMFPrioritySettings& aPrioritySettings) + { + TPckgBuf prioritySet(aPrioritySettings); + SendReceive(EMMFDevSoundProxySetPrioritySettings, + iDestinationPckg, + prioritySet); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::FixedSequenceName +// Returns the name of fixed sequence for a given sequence number. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C const TDesC& RMMFDevSoundProxy::FixedSequenceName(TInt /*aSequenceNumber*/) + { + _LIT(KNullDesC, ""); + return KNullDesC; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::CustomInterface +// Returns a pointer to CustomInterface object. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TAny* RMMFDevSoundProxy::CustomInterface(TUid aInterfaceId) + { + TMMFDevSoundProxySettings set; + set.iInterface = aInterfaceId; + // Added for ask for custom interface + TAny* customInterface = NULL; + if (aInterfaceId == KMmfUidDevSoundCancelInitializeCustomInterface) + { + MMMFDevSoundCancelInitialize* result = this; + return result; + } + TPckgBuf pckg2(customInterface); + + TMMFDevSoundProxySettingsPckg pckg(set); + SendReceiveResult(EMMFDevSoundProxyCustomInterface, + iDestinationPckg, + pckg, pckg2); + return reinterpret_cast (customInterface); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::FixedSequenceCount +// Returns the number of fixed sequences supported by DevSound. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::FixedSequenceCount() + { + TPckgBuf fixSeqCountPckg; + SendReceiveResult(EMMFDevSoundProxyFixedSequenceCount, + iDestinationPckg, + KNullDesC8, + fixSeqCountPckg); + + + return fixSeqCountPckg(); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::BufferToBeFilledData +// Returns data buffer for playback. +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::BufferToBeFilledData( + TBool aRequestChunk, TMMFDevSoundProxyHwBufPckg& aSetPckg) + { + // Note that there will only ever be one of these requests outstanding + // per session + TPckgBuf requestChunkBuf (aRequestChunk); + return SendReceiveResult(EMMFDevSoundProxyBTBFData, + iDestinationPckg, + requestChunkBuf, + aSetPckg); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::BufferToBeEmptiedData +// Returns data buffer for recording. +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::BufferToBeEmptiedData( + TMMFDevSoundProxyHwBufPckg& aSetPckg) + { + // Note that there will only ever be one of these requests outstanding + // per session + return SendReceiveResult(EMMFDevSoundProxyBTBEData, + iDestinationPckg, + KNullDesC8, + aSetPckg); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::RegisterAsClient +// Registers the client for notification of resource avalibility. +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::RegisterAsClient(TUid aEventType, const TDesC8& aNotificationRegistrationData) + { + TMMFDevSoundProxySettings set; + set.iNotificationEventUid = aEventType; + TMMFDevSoundProxySettingsPckg pckg(set); + return SendReceive(EMMFDevSoundProxyRequestResourceNotification, iDestinationPckg, pckg, aNotificationRegistrationData); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::CancelRegisterAsClient +// Cancels the Registered Notification. +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::CancelRegisterAsClient(TUid aEventType) + { + TMMFDevSoundProxySettings set; + set.iNotificationEventUid = aEventType; + TMMFDevSoundProxySettingsPckg pckg(set); + return SendReceiveResult(EMMFDevSoundProxyCancelRequestResourceNotification, iDestinationPckg, KNullDesC8, pckg); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::GetResourceNotificationData +// Returns the Notification data which the client needs to resume playing. +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::GetResourceNotificationData(TUid aEventType, TDes8& aNotificationData) + { + TMMFDevSoundProxySettings set; + set.iNotificationEventUid = aEventType; + TMMFDevSoundProxySettingsPckg pckg(set); + return SendReceiveResult(EMMFDevSoundProxyGetResourceNotificationData, iDestinationPckg, pckg, aNotificationData); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::WillResumePlay +// Wait for the clients to resume play back even after the default timeout +// expires. Unless the client cancels the notification request or completes +// no other client gets notification. +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::WillResumePlay() + { + return SendReceive(EMMFDevSoundProxyWillResumePlay, iDestinationPckg); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::EmptyBuffers +// Empties the play buffers below DevSound without causing the codec +// to be deleted. +// ----------------------------------------------------------------------------- +// + +EXPORT_C TInt RMMFDevSoundProxy::EmptyBuffers() + { + TInt error = SendReceive(EMMFDevSoundProxyEmptyBuffers, iDestinationPckg); + + if(error==KErrNone) + { + if (iState==EPlayingBufferWait) + { + // Empty buffers terminates the buffer cycle + iState = EPlaying; + } + } + return error; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::CancelInitialize +// Cancels the initialization process +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::CancelInitialize() + { + TInt err=KErrNone; + + if (iState==EInitializing) + { + err = SendReceive(EMMFDevSoundProxyCancelInitialize, iDestinationPckg); + iState = EIdle; + } + else + { + err = KErrNotReady; + } + + return err; + } + + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::SetClientThreadInfo +// +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::SetClientThreadInfo(TThreadId& aTid) + { + TPckgBuf threadId(aTid); + return SendReceive(EMMFDevSoundProxySetClientThreadInfo, iDestinationPckg, threadId); + } + + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::CustomCommandSync() +// Send Message synchronously to DevSound server and return the result to client +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::CustomCommandSync( + const TMMFMessageDestinationPckg& aDestination, + TInt aFunction, + const TDesC8& aDataTo1, + const TDesC8& aDataTo2, + TDes8& aDataFrom) + { + return SendReceiveResult(aFunction, + aDestination, + aDataTo1, + aDataTo2, + aDataFrom); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::RMMFDevSoundProxy() +// Send Message synchronously to DevSound server and return the result to client +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt RMMFDevSoundProxy::CustomCommandSync( + const TMMFMessageDestinationPckg& aDestination, + TInt aFunction, + const TDesC8& aDataTo1, + const TDesC8& aDataTo2) + { + return SendReceive(aFunction, aDestination, aDataTo1, aDataTo2); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::RMMFDevSoundProxy() +// Send Message asynchronously to DevSound server +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::CustomCommandAsync( + const TMMFMessageDestinationPckg& aDestination, + TInt aFunction, + const TDesC8& aDataTo1, + const TDesC8& aDataTo2, + TDes8& aDataFrom, + TRequestStatus& aStatus ) + { + SendReceiveResult(aFunction, + aDestination, + aDataTo1, + aDataTo2, + aDataFrom, + aStatus); + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::RMMFDevSoundProxy() +// Send Message asynchronously to DevSound server +// ----------------------------------------------------------------------------- +// +EXPORT_C void RMMFDevSoundProxy::CustomCommandAsync( + const TMMFMessageDestinationPckg& aDestination, + TInt aFunction, + const TDesC8& aDataTo1, + const TDesC8& aDataTo2, + TRequestStatus& aStatus ) + { + SendReceive(aFunction, aDestination, aDataTo1, aDataTo2, aStatus); + } + +// implementation of a simple CustomCommand() scheme +EXPORT_C TInt RMMFDevSoundProxy::SyncCustomCommand(TUid aUid, const TDesC8& aParam1, const TDesC8& aParam2, TDes8* aOutParam) + { + TMMFMessageDestinationPckg dest(TMMFMessageDestination(aUid, KMMFObjectHandleDevSound)); + + if (aOutParam==NULL) + { + return SendReceive(EMMFDevSoundProxySyncCustomCommand, dest, aParam1, aParam2); + } + else + { + return SendReceiveResult(EMMFDevSoundProxySyncCustomCommandResult, dest, aParam1, aParam2, *aOutParam); + } + } + +EXPORT_C void RMMFDevSoundProxy::AsyncCustomCommand(TUid aUid, TRequestStatus& aStatus, const TDesC8& aParam1, const TDesC8& aParam2, TDes8* aOutParam) + { + TMMFMessageDestination dest(aUid, KMMFObjectHandleDevSound); + iCustIntPckg = dest; + if (aOutParam==NULL) + { + SendReceive(EMMFDevSoundProxyAsyncCustomCommand, iCustIntPckg, aParam1, aParam2, aStatus); + } + else + { + SendReceiveResult(EMMFDevSoundProxyAsyncCustomCommandResult, iCustIntPckg, aParam1, aParam2, *aOutParam, aStatus); + } + } + +EXPORT_C TInt RMMFDevSoundProxy::GetTimePlayed(TTimeIntervalMicroSeconds& aTime) + { + TTimeIntervalMicroSeconds time(0); + TPckgBuf timePckg(time); + TInt err = SendReceiveResult(EMMFDevSoundProxyGetTimePlayed, iDestinationPckg, KNullDesC8, timePckg); + if(err==KErrNone) + { + aTime = timePckg(); + } + return err; + } + +EXPORT_C TBool RMMFDevSoundProxy::IsResumeSupported() + { + TPckgBuf isResumeSupported; + TInt err = SendReceiveResult(EMMFDevSoundProxyIsResumeSupported, + iDestinationPckg, + KNullDesC8, + isResumeSupported); + if(err == KErrNone) + { + return isResumeSupported(); + } + else + { + return EFalse; + } + } + +EXPORT_C TInt RMMFDevSoundProxy::Resume() + { + TInt err = KErrNone; + if (!iDevSoundObserver || iState <= EInitialized ) + { + err = KErrNotReady; + } + else if(iState == ETonePlaying && iToneMode != ESequence) + { + return KErrNotSupported; + } + else + { + if (iState==ERecordingInLastBufferCycle) + { + // if we're in a last buffer cycle and get Resume() we have to be careful as the + // server side sent a PausedRecordCompleteEvent and did not actually request a buffer! + // just record the fact we've done this and wait until RecordData() is called + // don't actually resume until then! + iState = ERecordingResumingInLastBufferCycle; + } + else + { + err = SendReceive(EMMFDevSoundProxyResume, + iDestinationPckg); + } + } + return err; + } + +// ----------------------------------------------------------------------------- +// RMMFDevSoundProxy::StartReceivingMsgQueueHandlerEventsL() +// Starts message queue handler (A/O) to monitor client side events +// ----------------------------------------------------------------------------- +// +void RMMFDevSoundProxy::StartReceivingMsgQueueHandlerEventsL(MMMFDevSoundCustomInterfaceObserver& aDevSoundCIObserver) + { + if (iMsgQueueHandler) + { + iMsgQueueHandler->Cancel(); + } + else + { + iMsgQueueHandler = CMsgQueueHandler::NewL(this, + *this, + &iMsgQueue, + aDevSoundCIObserver); + } + + iMsgQueueHandler->ReceiveEvents(); + } + +// MDevSoundObserver +// intercept the calls from the msgQueueHandler going back to the client, so we can track real state + +void RMMFDevSoundProxy::InitializeComplete(TInt aError) + { + SYMBIAN_CHECK(iState==EInitializing, Panic(EMMFDevSoundProxyInitCompleteInWrongState)); + if (aError==KErrNone) + { + iState = EInitialized; + } + else + { + iState = EIdle; + } + iDevSoundObserver->InitializeComplete(aError); + } + +void RMMFDevSoundProxy::ToneFinished(TInt aError) + { + SYMBIAN_CHECK(iState==ETonePlaying, Panic(EMMFDevSoundProxyToneFinishedInWrongState)); + iState = EInitialized; + iDevSoundObserver->ToneFinished(aError); + } + +void RMMFDevSoundProxy::PlayError(TInt aError) + { + SYMBIAN_CHECK(iState==EPlaying||iState==EPlayingBufferWait, Panic(EMMFDevSoundProxyPlayErrorInWrongState)); + iState = EInitialized; + iDevSoundObserver->PlayError(aError); + } + +void RMMFDevSoundProxy::RecordError(TInt aError) + { + SYMBIAN_CHECK(iState==ERecording||iState==ERecordingBufferWait, Panic(EMMFDevSoundProxyRecordErrorInWrongState)); + iState = EInitialized; + iDevSoundObserver->RecordError(aError); + } + +void RMMFDevSoundProxy::BufferToBeFilled(CMMFBuffer* aBuffer) + { + SYMBIAN_CHECK(iState==EPlaying, Panic(EMMFDevSoundProxyBTBFInWrongState)); + iState = EPlayingBufferWait; + iBuffer = static_cast(aBuffer); // cache buffer for use in PlayData() later + iDevSoundObserver->BufferToBeFilled(aBuffer); + } + +void RMMFDevSoundProxy::BufferToBeEmptied(CMMFBuffer* aBuffer) + { + SYMBIAN_CHECK(iState==ERecording, Panic(EMMFDevSoundProxyBTBEInWrongState)); + if (aBuffer->LastBuffer()) + { + // this is end of recording. Assume have an empty buffer. Different state so that Resume() is handled as special case. + iState = ERecordingInLastBufferCycle; + } + else + { + iState = ERecordingBufferWait; + } + iDevSoundObserver->BufferToBeEmptied(aBuffer); + } + +void RMMFDevSoundProxy::ConvertError(TInt /*aError*/) + { + SYMBIAN_CHECK(EFalse, Panic(EMMFDevSoundProxyUnexpectedConvError)); + } + +void RMMFDevSoundProxy::DeviceMessage(TUid aMessageType, const TDesC8& aMsg) + { + iDevSoundObserver->DeviceMessage(aMessageType, aMsg); + } + +void RMMFDevSoundProxy::SendEventToClient(const TMMFEvent& aEvent) + { + iDevSoundObserver->SendEventToClient(aEvent); + } + + +// End of File