--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/devsound/devsoundrefplugin/src/platsec/SoundDevice/SoundDeviceBody.cpp Tue Feb 02 01:56:55 2010 +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 <mmf/plugin/mmfhwdeviceimplementationuids.hrh>
+#include "SoundDeviceBody.h"
+#include <mmf/server/mmfswcodecwrappercustominterfacesuids.hrh> // 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<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& aPrioritySettings) const
+ {
+ iDevSoundProxy->GetSupportedInputDataTypesL(aSupportedDataTypes, aPrioritySettings);
+ }
+
+/**
+ * @see sounddevice.h
+ */
+void CMMFDevSoundClientImp::GetSupportedOutputDataTypesL(RArray<TFourCC>& 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;
+ }
+ }
+ }