diff -r 000000000000 -r bde4ae8d615e os/mm/devsound/devsoundrefplugin/src/platsec/SoundDevice/SoundDeviceBody.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/mm/devsound/devsoundrefplugin/src/platsec/SoundDevice/SoundDeviceBody.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,698 @@ +// Copyright (c) 2001-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 +#include "SoundDeviceBody.h" +#include // KUidRefDevSoundTaskConfig + +const TInt KMaxMessageQueueItems = 8; + +/* + * + * Default Constructor. + * + * No default implementation. CMMFDevSound implements 2-phase construction. + * + */ +CMMFDevSoundClientImp::CMMFDevSoundClientImp() + { + } + +/* + * + * Destructor. + * + * Deletes all objects and releases all resource owned by this + * instance. + * + */ +CMMFDevSoundClientImp::~CMMFDevSoundClientImp() + { + // clear the array of custom interfaces + for (TInt i = 0; i < iCustomInterfaceArray.Count(); i++) + { + iCustomInterfaceArray[i].iInterface->Release(); + } + iCustomInterfaceArray.Reset(); + iCustomInterfaceArray.Close(); + + // delete the MUX utility + delete iMuxUtility; + + if (iMsgQueueHandler && iMsgQueueHandler->IsActive()) + { + iMsgQueueHandler->Cancel(); + } + delete iMsgQueueHandler; + + iMsgQueue.Close(); + + if( iDevSoundProxy != NULL) + { + iDevSoundProxy->Close(); + delete iDevSoundProxy; + } + } + +/* + * + * Constructs, and returns a pointer to, a new CMMFDevSound object. + * + * Leaves on failure. + * + */ +CMMFDevSoundClientImp* CMMFDevSoundClientImp::NewL() + { + CMMFDevSoundClientImp* self = new (ELeave) CMMFDevSoundClientImp(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +/* + * + * 2nd phase constructor - assumes that iParent has already been set up properly. + * + */ +void CMMFDevSoundClientImp::ConstructL() + { + // all these data properties should be NULL, but add ASSERTs to verify + + ASSERT(iDevSoundProxy==NULL); + iDevSoundProxy = new (ELeave) RMMFDevSoundProxy(); + + TInt err = iMsgQueue.CreateGlobal(KNullDesC, KMaxMessageQueueItems); // global, accessible to all that have its handle + User::LeaveIfError(err); + err = iDevSoundProxy->Open(iMsgQueue); + if(err) + { + delete iDevSoundProxy; + iDevSoundProxy = NULL; + } + + User::LeaveIfError(err); + + // create MUX utility + iMuxUtility = CMMFDevSoundCIMuxUtility::NewL(this); + } + + +/* + * + * Initializes CMMFDevSound object to play and record PCM16 raw audio data + * with sampling rate of 8 KHz. + * + * On completion of Initialization, calls InitializeComplete() on + * aDevSoundObserver. + * + * Leaves on failure. + * + * @param "MDevSoundObserver& aDevSoundObserver" + * A reference to DevSound Observer instance. + * + * @param "TMMFState aMode" + * Mode for which this object will be used. + * + */ +void CMMFDevSoundClientImp::InitializeL(MDevSoundObserver& aDevSoundObserver, TMMFState aMode) + + { + TInt initError = KErrNone; + iDevSoundObserver = &aDevSoundObserver; + initError = iDevSoundProxy->InitializeL(aMode); + + if (initError) + { + User::Leave(initError); + } + + if (iMsgQueueHandler) + { + iMsgQueueHandler->Cancel(); + iMsgQueueHandler->SetObserver(*iDevSoundObserver); + } + else + { + iMsgQueueHandler = CMsgQueueHandler::NewL(iDevSoundProxy, *iDevSoundObserver, &iMsgQueue, *this); + } + + iMsgQueueHandler->ReceiveEvents(); + } + +/* + * + * Configure CMMFDevSound object for the settings in aConfig. + * + * Use this to set sampling rate, Encoding and Mono/Stereo. + * + * @param "TMMFCapabilities& aConfig" + * Attribute values to which CMMFDevSound object will be configured to. + * + * As part of defect 20796, the iRecordFormat has been set under the iPlayFormat, + * before it was not set at all. + * + */ +void CMMFDevSoundClientImp::SetConfigL(const TMMFCapabilities& aConfig) + { + iDevSoundProxy->SetConfigL(aConfig); + } + +/* + * + * Changes the current playback volume to a specified value. + * + * The volume can be changed before or during playback and is effective + * immediately. + * + * @param "TInt aVolume" + * The volume setting. This can be any value from zero to the value + * returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the + * volume is not within this range, the volume is automatically set to + * minimum or maximum value based on the value that is being passed. + * Setting a zero value mutes the sound. Setting the maximum value + * results in the loudest possible sound. + * + */ +void CMMFDevSoundClientImp::SetVolume(TInt aVolume) + { + iDevSoundProxy->SetVolume(aVolume); + } + +/* + * + * Changes the current recording gain to a specified value. + * + * The gain can be changed before or during recording and is effective + * immediately. + * + * @param "TInt aGain" + * The volume setting. This can be any value from zero to the value + * returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the + * volume is not within this range, the gain is automatically set to + * minimum or maximum value based on the value that is being passed. + * Setting a zero value mutes the sound. Setting the maximum value + * results in the loudest possible sound. + * + */ +void CMMFDevSoundClientImp::SetGain(TInt aGain) + { + iDevSoundProxy->SetGain(aGain); + } + +/* + * + * Sets the speaker balance for playing. + * + * The speaker balance can be changed before or during playback and is + * effective immediately. + * + * @param "TInt& aLeftPercentage" + * On return contains left speaker volume perecentage. This can be any + * value from zero to 100. Setting a zero value mutes the sound on left + * speaker. + * + * @param "TInt& aRightPercentage" + * On return contains right speaker volume perecentage. This can be any + * value from zero to 100. Setting a zero value mutes the sound on + * right speaker. + * + */ +void CMMFDevSoundClientImp::SetPlayBalanceL(TInt aLeftPercentage, TInt aRightPercentage) + { + iDevSoundProxy->SetPlayBalanceL(aLeftPercentage, aRightPercentage); + } + +/* + * + * Sets the microphone gain balance for recording. + * + * The microphone gain balance can be changed before or during recording and + * is effective immediately. + * + * @param "TInt aLeftPercentage" + * Left microphone gain precentage. This can be any value from zero to + * 100. Setting a zero value mutes the gain on left microphone. + * + * @param "TInt aRightPercentage" + * Right microphone gain precentage. This can be any value from zero to + * 100. Setting a zero value mutes the gain on right microphone. + * + */ +void CMMFDevSoundClientImp::SetRecordBalanceL(TInt aLeftPercentage, TInt aRightPercentage) + { + iDevSoundProxy->SetRecordBalanceL(aLeftPercentage, aRightPercentage); + } + +/* + * + * Initializes audio device and start play process. This method queries and + * acquires the audio policy before initializing audio device. If there was an + * error during policy initialization, PlayError() method will be called on + * the observer with error code KErrAccessDenied, otherwise BufferToBeFilled() + * method will be called with a buffer reference. After reading data into the + * buffer reference passed, the client should call PlayData() to play data. + * + * The amount of data that can be played is specified in + * CMMFBuffer::RequestSize(). Any data that is read into buffer beyond this + * size will be ignored. + * + * Leaves on failure. + * + */ +void CMMFDevSoundClientImp::PlayInitL() + { + if (!iDevSoundObserver) + User::Leave(KErrNotReady); + iDevSoundProxy->PlayInitL(); + } + +/* + * + * Initializes audio device and start record process. This method queries and + * acquires the audio policy before initializing audio device. If there was an + * error during policy initialization, RecordError() method will be called on + * the observer with error code KErrAccessDenied, otherwise BufferToBeEmptied() + * method will be called with a buffer reference. This buffer contains recorded + * or encoded data. After processing data in the buffer reference passed, the + * client should call RecordData() to continue recording process. + * + * The amount of data that is available is specified in + * CMMFBuffer::RequestSize(). + * + * Leaves on failure. + * + */ +void CMMFDevSoundClientImp::RecordInitL() + { + + if (!iDevSoundObserver) + User::Leave(KErrNotReady); + iDevSoundProxy->RecordInitL(); + } + +/* + * + * Plays data in the buffer at the current volume. The client should fill + * the buffer with audio data before calling this method. The Observer gets + * reference to buffer along with callback BufferToBeFilled(). When playing of + * the audio sample is complete, successfully or otherwise, the method + * PlayError() on observer is called. + * + */ +void CMMFDevSoundClientImp::PlayData() + { + ASSERT(iDevSoundObserver); + iDevSoundProxy->PlayData(); + } + +/* + * + * Stops the ongoing operation (Play, Record, TonePlay, Convert) + * + */ +void CMMFDevSoundClientImp::Stop() + { + iDevSoundProxy->Stop(); + } + +/* + * + * Temporarily Stops the ongoing operation (Play, Record, TonePlay, Convert) + * + */ +void CMMFDevSoundClientImp::Pause() + { + iDevSoundProxy->Pause(); + } + +/* + * + * Returns the sample recorded so far. + * + * @return "TInt" + * Returns the samples recorded. + * + */ +TInt CMMFDevSoundClientImp::SamplesRecorded() + { + return iDevSoundProxy->SamplesRecorded(); + } + +/* + * + * Returns the sample played so far. + * + * @return "TInt" + * Returns the samples recorded. + * + */ +TInt CMMFDevSoundClientImp::SamplesPlayed() + { + return iDevSoundProxy->SamplesPlayed(); + } + + +/* + * + * Initializes audio device and start playing tone. Tone is played with + * frequency and for duration specified. + * + * Leaves on failure. + * + * @param "TInt aFrequency" + * Frequency at with the tone will be played. + * + * @param "TTimeIntervalMicroSeconds& aDuration" + * The period over which the tone will be played. A zero value causes + * the no tone to be played (Verify this with test app). + * + */ +void CMMFDevSoundClientImp::PlayToneL(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration) + { + iDevSoundProxy->PlayToneL(aFrequency, aDuration); + } + +/* + * Initializes audio device and start playing a dual tone. + * The tone consists of two sine waves of different frequencies summed together + * Dual Tone is played with specified frequencies and for specified duration. + * + * @param "aFrequencyOne" + * First frequency of dual tone + * + * @param "aFrequencyTwo" + * Second frequency of dual tone + * + * @param "aDuration" + * The period over which the tone will be played. A zero value causes + * the no tone to be played (Verify this with test app). + */ +void CMMFDevSoundClientImp::PlayDualToneL(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration) + { + iDevSoundProxy->PlayDualToneL(aFrequencyOne, aFrequencyTwo, aDuration); + } + +/* + * + * Initializes audio device and start playing DTMF string aDTMFString. + * + * Leaves on failure. + * + * @param "TDesC& aDTMFString" + * DTMF sequence in a descriptor. + * + */ +void CMMFDevSoundClientImp::PlayDTMFStringL(const TDesC& aDTMFString) + { + if (!iDevSoundObserver) + User::Leave(KErrNotReady); + + iDevSoundProxy->PlayDTMFStringL(aDTMFString); + } + +/* + * + * Initializes audio device and start playing tone sequence. + * + * Leaves on failure. + * + * @param "TDesC8& aData" + * Tone sequence in a descriptor. + * + */ +void CMMFDevSoundClientImp::PlayToneSequenceL(const TDesC8& aData) + { + if (!iDevSoundObserver) + User::Leave(KErrNotReady); + + iDevSoundProxy->PlayToneSequenceL(aData); + } + +/* + * + * Initializes audio device and start playing the specified pre-defined tone + * sequence. + * + * Leaves on failure. + * + * @param "TInt aSequenceNumber" + * The index identifying the specific pre-defined tone sequence. Index + * values are relative to zero. + * This can be any value from zero to the value returned by a call to + * CMdaAudioPlayerUtility::FixedSequenceCount() - 1. + * The function raises a panic if sequence number is not within this + * range. + * + */ +void CMMFDevSoundClientImp::PlayFixedSequenceL(TInt aSequenceNumber) + { + if (!iDevSoundObserver) + User::Leave(KErrNotReady); + + iDevSoundProxy->PlayFixedSequenceL(aSequenceNumber); + } + +/* + * + * Defines the duration of tone on, tone off and tone pause to be used during the + * DTMF tone playback operation. + * + * Supported only during tone playing. + * + * @param "TTimeIntervalMicroSeconds32& aToneOnLength" + * The period over which the tone will be played. If this is set to + * zero, then the tone is not played. + * + * @param "TTimeIntervalMicroSeconds32& aToneOffLength" + * The period over which the no tone will be played. + * + * @param "TTimeIntervalMicroSeconds32& aPauseLength" + * The period over which the tone playing will be paused. + * + */ +void CMMFDevSoundClientImp::SetDTMFLengths(TTimeIntervalMicroSeconds32& aToneOnLength, + TTimeIntervalMicroSeconds32& aToneOffLength, + TTimeIntervalMicroSeconds32& aPauseLength) + { + iDevSoundProxy->SetDTMFLengths(aToneOnLength, aToneOffLength, aPauseLength); + } + +/* + * + * Defines the period over which the volume level is to rise smoothly from + * nothing to the normal volume level. + * + * @param "TTimeIntervalMicroSeconds& aRampDuration" + * The period over which the volume is to rise. A zero value causes + * the tone sample to be played at the normal level for the full + * duration of the playback. A value, which is longer than the duration + * of the tone sample, that the sample never reaches its normal + * volume level. + * + * + */ +void CMMFDevSoundClientImp::SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration) + { + iDevSoundProxy->SetVolumeRamp(aRampDuration); + } + + +/** + * @see sounddevice.h + */ +void CMMFDevSoundClientImp::GetSupportedInputDataTypesL(RArray& aSupportedDataTypes, const TMMFPrioritySettings& aPrioritySettings) const + { + iDevSoundProxy->GetSupportedInputDataTypesL(aSupportedDataTypes, aPrioritySettings); + } + +/** + * @see sounddevice.h + */ +void CMMFDevSoundClientImp::GetSupportedOutputDataTypesL(RArray& aSupportedDataTypes, const TMMFPrioritySettings& aPrioritySettings) const + { + iDevSoundProxy->GetSupportedOutputDataTypesL(aSupportedDataTypes, aPrioritySettings); + } + +/** + * @see sounddevice.h + */ +TInt CMMFDevSoundClientImp::SetClientThreadInfo(TThreadId aTid) + { + return iDevSoundProxy->SetClientThreadInfo(aTid); + } + + +TInt CMMFDevSoundClientImp::RegisterAsClient(TUid aEventType, const TDesC8& aNotificationRegistrationData) + { + return iDevSoundProxy->RegisterAsClient(aEventType,aNotificationRegistrationData); + } + +TInt CMMFDevSoundClientImp::CancelRegisterAsClient(TUid aEventType) + { + return iDevSoundProxy->CancelRegisterAsClient(aEventType); + } + +TInt CMMFDevSoundClientImp::GetResourceNotificationData(TUid aEventType,TDes8& aNotificationData) + { + return iDevSoundProxy->GetResourceNotificationData(aEventType,aNotificationData); + } + +TInt CMMFDevSoundClientImp::WillResumePlay() + { + return iDevSoundProxy->WillResumePlay(); + } + +TInt CMMFDevSoundClientImp::EmptyBuffers() + { + return iDevSoundProxy->EmptyBuffers(); + } + +TInt CMMFDevSoundClientImp::GetTimePlayed(TTimeIntervalMicroSeconds& aTime) + { + return iDevSoundProxy->GetTimePlayed(aTime); + } +/* + * + * Returns a given Custom Interface on the DevSound based on the UID + * If this is not recognised then the custominterface is created by + * a pair of ECOM plugins. + * + * @released + * @param "TUid aInterfaceId" + * The UID of the required Custom Interface + * @return a pointer to the custom interface + * + */ +TAny* CMMFDevSoundClientImp::CustomInterface(TUid aInterfaceId) + { + // check if this UID refers to auto/pause/resume + if (aInterfaceId == KMmfUidDevSoundAudioResourceCustomInterface) + { + MAutoPauseResumeSupport* result = this; + return result; + } + if (aInterfaceId == KMmfUidDevSoundEmptyBuffersCustomInterface) + { + MMMFDevSoundEmptyBuffers* result = this; + return result; + } + if (aInterfaceId == KMmfUidDevSoundAudioClientThreadInfoCustomInterface) + { + MAudioClientThreadInfo* result = this; + return result; + } + + if (aInterfaceId == KMmfUidDevSoundTimePlayedCustomInterface) + { + MMMFDevSoundTimePlayed* result = this; + return result; + } + + // we are being asked for a Custom Interface not natively supported + // by the DevSound plugin. + + // first check if we already have resolved a custom interface of this type + TInt index = FindCustomInterface(aInterfaceId); + + MMMFDevSoundCustomInterfaceMuxPlugin* ptr = NULL; + + // if we found the interface, take a copy of this instead + if (index != KNullHandle) + { + // check our index is valid + ptr = iCustomInterfaceArray[index-1].iInterface; + if (ptr) + { + return ptr->CustomInterface(aInterfaceId); + } + else + { + // we may not need this code because this + // *should* be impossible to reach + return NULL; + } + } + else + { + // else try and instantiate a plugin tunnelling + // pair to support this Custom Interface + TRAPD(err, ptr = iMuxUtility->CreateCustomInterfaceMuxL(aInterfaceId)); + + if (ptr && (err == KErrNone)) + { + TMMFDevSoundCustomInterfaceData data; + data.iInterface = ptr; + data.iId = aInterfaceId; + + // attempt to open remote demux + // this will store a handle in the mux plugin if successful + // and also return it here - invalid handle = -1 + data.iHandle = ptr->OpenInterface(aInterfaceId); + + // if the handle is greater than zero then we know we have + // successfully opened the interface + if (data.iHandle > KNullHandle) + { + // append this to the current interface list + TInt err = KErrNone; + err = iCustomInterfaceArray.Append(data); + if (err == KErrNone) + { + // return the custom interface on the ptr + return ptr->CustomInterface(aInterfaceId); + } + } + + // no memory or other problem so shut down interface + ptr->Release(); + ptr = NULL; + } + } + + // if code gets here then we don't support the interface + // so we can pass it onto the DevSound proxy so that we + // can attempt to resolve the interface externally + return iDevSoundProxy->CustomInterface(aInterfaceId); + } + +TInt CMMFDevSoundClientImp::FindCustomInterface(TUid aInterfaceId) + { + TInt index = KNullHandle; + + for (TInt i = 0; i < iCustomInterfaceArray.Count(); i++) + { + if (iCustomInterfaceArray[i].iId == aInterfaceId) + { + index = i+1; // use index+1 as the handle, so 0 is undefined/not-found + break; + } + } + + return index; + } + +void CMMFDevSoundClientImp::CloseCustomInterface(TInt aIndex) + { + for (TInt i = 0; i < iCustomInterfaceArray.Count(); i++) + { + if(iCustomInterfaceArray[i].iHandle == aIndex) + { + iCustomInterfaceArray[i].iInterface->Release(); + iCustomInterfaceArray.Remove(i); + break; + } + } + }