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