devsound/devsoundrefplugin/src/platsec/SoundDevice/SoundDeviceBody.cpp
changeset 0 40261b775718
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <mmf/plugin/mmfhwdeviceimplementationuids.hrh>
       
    17 #include "SoundDeviceBody.h"
       
    18 #include <mmf/server/mmfswcodecwrappercustominterfacesuids.hrh> // KUidRefDevSoundTaskConfig
       
    19 
       
    20 const TInt KMaxMessageQueueItems = 8;
       
    21 
       
    22 /*
       
    23  *
       
    24  *	Default Constructor.
       
    25  *
       
    26  *	No default implementation. CMMFDevSound implements 2-phase construction.
       
    27  *
       
    28  */
       
    29 CMMFDevSoundClientImp::CMMFDevSoundClientImp()
       
    30 	{
       
    31 	}
       
    32 
       
    33 /*
       
    34  *
       
    35  *	Destructor.
       
    36  *
       
    37  *	Deletes all objects and releases all resource owned by this
       
    38  *	instance.
       
    39  *
       
    40  */
       
    41 CMMFDevSoundClientImp::~CMMFDevSoundClientImp()
       
    42 	{
       
    43 	// clear the array of custom interfaces
       
    44 	for (TInt i = 0; i < iCustomInterfaceArray.Count(); i++)
       
    45 		{
       
    46 		iCustomInterfaceArray[i].iInterface->Release();
       
    47 		}
       
    48 	iCustomInterfaceArray.Reset();
       
    49 	iCustomInterfaceArray.Close();
       
    50 
       
    51 	// delete the MUX utility
       
    52 	delete iMuxUtility;
       
    53 
       
    54 	if (iMsgQueueHandler && iMsgQueueHandler->IsActive())
       
    55 		{
       
    56 		iMsgQueueHandler->Cancel();
       
    57 		}
       
    58 	delete iMsgQueueHandler;
       
    59 
       
    60 	iMsgQueue.Close();	
       
    61 
       
    62 	if( iDevSoundProxy != NULL)
       
    63 		{
       
    64 		iDevSoundProxy->Close();
       
    65 		delete iDevSoundProxy;
       
    66 		}
       
    67 	}
       
    68 
       
    69 /*
       
    70  *
       
    71  *	Constructs, and returns a pointer to, a new CMMFDevSound object.
       
    72  *
       
    73  *	Leaves on failure.
       
    74  *
       
    75  */
       
    76 CMMFDevSoundClientImp* CMMFDevSoundClientImp::NewL()
       
    77 	{
       
    78 	CMMFDevSoundClientImp* self = new (ELeave) CMMFDevSoundClientImp();
       
    79 	CleanupStack::PushL(self);
       
    80 	self->ConstructL();
       
    81 	CleanupStack::Pop(self);
       
    82 	return self;
       
    83 	}
       
    84 
       
    85 /*
       
    86  *
       
    87  *	2nd phase constructor - assumes that iParent has already been set up properly.
       
    88  *
       
    89  */
       
    90 void CMMFDevSoundClientImp::ConstructL()
       
    91 	{
       
    92 	// all these data properties should be NULL, but add ASSERTs to verify
       
    93 
       
    94 	ASSERT(iDevSoundProxy==NULL);
       
    95 	iDevSoundProxy = new (ELeave) RMMFDevSoundProxy();
       
    96 
       
    97 	TInt err = iMsgQueue.CreateGlobal(KNullDesC, KMaxMessageQueueItems);	// global, accessible to all that have its handle
       
    98 	User::LeaveIfError(err);
       
    99 	err = iDevSoundProxy->Open(iMsgQueue);
       
   100 	if(err)
       
   101 		{
       
   102 		delete iDevSoundProxy;
       
   103 		iDevSoundProxy = NULL;
       
   104 		}
       
   105 
       
   106 	User::LeaveIfError(err);
       
   107 
       
   108 	// create MUX utility
       
   109 	iMuxUtility = CMMFDevSoundCIMuxUtility::NewL(this);
       
   110 	}
       
   111 
       
   112 
       
   113 /*
       
   114  *
       
   115  *	Initializes CMMFDevSound object to play and record PCM16 raw audio data
       
   116  *	with sampling rate of 8 KHz.
       
   117  *
       
   118  *	On completion of Initialization, calls InitializeComplete() on
       
   119  *	aDevSoundObserver.
       
   120  *
       
   121  *	Leaves on failure.
       
   122  *
       
   123  *	@param	"MDevSoundObserver& aDevSoundObserver"
       
   124  *			A reference to DevSound Observer instance.
       
   125  *
       
   126  *	@param	"TMMFState aMode"
       
   127  *			Mode for which this object will be used.
       
   128  *
       
   129  */
       
   130 void CMMFDevSoundClientImp::InitializeL(MDevSoundObserver& aDevSoundObserver, TMMFState aMode)
       
   131 
       
   132 	{
       
   133 	TInt initError = KErrNone;
       
   134 	iDevSoundObserver = &aDevSoundObserver;
       
   135 	initError = iDevSoundProxy->InitializeL(aMode);
       
   136 
       
   137 	if (initError)
       
   138 		{
       
   139 		User::Leave(initError);
       
   140 		}
       
   141 
       
   142 	if (iMsgQueueHandler)
       
   143 		{
       
   144 		iMsgQueueHandler->Cancel();
       
   145 		iMsgQueueHandler->SetObserver(*iDevSoundObserver);
       
   146 		}
       
   147 	else
       
   148 		{
       
   149 		iMsgQueueHandler = CMsgQueueHandler::NewL(iDevSoundProxy, *iDevSoundObserver, &iMsgQueue, *this);
       
   150 		}
       
   151 
       
   152 	iMsgQueueHandler->ReceiveEvents();
       
   153 	}
       
   154 
       
   155 /*
       
   156  *
       
   157  *	Configure CMMFDevSound object for the settings in aConfig.
       
   158  *
       
   159  *	Use this to set sampling rate, Encoding and Mono/Stereo.
       
   160  *
       
   161  *	@param	"TMMFCapabilities& aConfig"
       
   162  *			Attribute values to which CMMFDevSound object will be configured to.
       
   163  *
       
   164  *  As part of defect 20796, the iRecordFormat has been set under the iPlayFormat, 
       
   165  *  before it was not set at all.
       
   166  *
       
   167  */
       
   168 void CMMFDevSoundClientImp::SetConfigL(const TMMFCapabilities& aConfig)
       
   169 	{
       
   170 	iDevSoundProxy->SetConfigL(aConfig);
       
   171 	}
       
   172 
       
   173 /*
       
   174  *
       
   175  *	Changes the current playback volume to a specified value.
       
   176  *
       
   177  *	The volume can be changed before or during playback and is effective
       
   178  *	immediately.
       
   179  *
       
   180  *	@param	"TInt aVolume"
       
   181  *			The volume setting. This can be any value from zero to the value
       
   182  *			returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
       
   183  *			volume is not within this range, the volume is automatically set to
       
   184  *			minimum or maximum value based on the value that is being passed.
       
   185  *			Setting a zero value mutes the sound. Setting the maximum value
       
   186  *			results in the loudest possible sound.
       
   187  *
       
   188  */
       
   189 void CMMFDevSoundClientImp::SetVolume(TInt aVolume)
       
   190 	{
       
   191 	iDevSoundProxy->SetVolume(aVolume);
       
   192 	}
       
   193 
       
   194 /*
       
   195  *
       
   196  *	Changes the current recording gain to a specified value.
       
   197  *
       
   198  *	The gain can be changed before or during recording and is effective
       
   199  *	immediately.
       
   200  *
       
   201  *	@param	"TInt aGain"
       
   202  *			The volume setting. This can be any value from zero to the value
       
   203  *			returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
       
   204  *			volume is not within this range, the gain is automatically set to
       
   205  *			minimum or maximum value based on the value that is being passed.
       
   206  *			Setting a zero value mutes the sound. Setting the maximum value
       
   207  *			results in the loudest possible sound.
       
   208  *
       
   209  */
       
   210 void CMMFDevSoundClientImp::SetGain(TInt aGain)
       
   211 	{
       
   212 	iDevSoundProxy->SetGain(aGain);
       
   213 	}
       
   214 
       
   215 /*
       
   216  *
       
   217  *	Sets the speaker balance for playing.
       
   218  *
       
   219  *	The speaker balance can be changed before or during playback and is
       
   220  *	effective immediately.
       
   221  *
       
   222  *	@param	"TInt& aLeftPercentage"
       
   223  *			On return contains left speaker volume perecentage. This can be any
       
   224  *			value from zero to 100. Setting a zero value mutes the sound on left
       
   225  *			speaker.
       
   226  *
       
   227  *	@param	"TInt& aRightPercentage"
       
   228  *			On return contains right speaker volume perecentage. This can be any
       
   229  *			value from zero to 100. Setting a zero value mutes the sound on
       
   230  *			right speaker.
       
   231  *
       
   232  */
       
   233 void CMMFDevSoundClientImp::SetPlayBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
       
   234 	{
       
   235 	iDevSoundProxy->SetPlayBalanceL(aLeftPercentage, aRightPercentage);
       
   236 	}
       
   237 
       
   238 /*
       
   239  *
       
   240  *	Sets the microphone gain balance for recording.
       
   241  *
       
   242  *	The microphone gain balance can be changed before or during recording and
       
   243  *	is effective immediately.
       
   244  *
       
   245  *	@param	"TInt aLeftPercentage"
       
   246  *			Left microphone gain precentage. This can be any value from zero to
       
   247  *			100. Setting a zero value mutes the gain on left microphone.
       
   248  *
       
   249  *	@param	"TInt aRightPercentage"
       
   250  *			Right microphone gain precentage. This can be any value from zero to
       
   251  *			100. Setting a zero value mutes the gain on right microphone.
       
   252  *
       
   253  */
       
   254 void CMMFDevSoundClientImp::SetRecordBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
       
   255 	{
       
   256 	iDevSoundProxy->SetRecordBalanceL(aLeftPercentage, aRightPercentage);
       
   257 	}
       
   258 
       
   259 /*
       
   260  *
       
   261  *	Initializes audio device and start play process. This method queries and
       
   262  *	acquires the audio policy before initializing audio device. If there was an
       
   263  *	error during policy initialization, PlayError() method will be called on
       
   264  *	the observer with error code KErrAccessDenied, otherwise BufferToBeFilled()
       
   265  *	method will be called with a buffer reference. After reading data into the
       
   266  *	buffer reference passed, the client should call PlayData() to play data.
       
   267  *
       
   268  *	The amount of data that can be played is specified in
       
   269  *	CMMFBuffer::RequestSize(). Any data that is read into buffer beyond this
       
   270  *	size will be ignored.
       
   271  *
       
   272  *	Leaves on failure.
       
   273  *
       
   274  */
       
   275 void CMMFDevSoundClientImp::PlayInitL()
       
   276 	{
       
   277 	if (!iDevSoundObserver)
       
   278 		User::Leave(KErrNotReady);
       
   279 	iDevSoundProxy->PlayInitL();
       
   280 	}
       
   281 
       
   282 /*
       
   283  *
       
   284  *	Initializes audio device and start record process. This method queries and
       
   285  *	acquires the audio policy before initializing audio device. If there was an
       
   286  *	error during policy initialization, RecordError() method will be called on
       
   287  *	the observer with error code KErrAccessDenied, otherwise BufferToBeEmptied()
       
   288  *	method will be called with a buffer reference. This buffer contains recorded
       
   289  *	or encoded data. After processing data in the buffer reference passed, the
       
   290  *	client should call RecordData() to continue recording process.
       
   291  *
       
   292  *	The amount of data that is available is specified in
       
   293  *	CMMFBuffer::RequestSize().
       
   294  *
       
   295  *	Leaves on failure.
       
   296  *
       
   297  */
       
   298 void CMMFDevSoundClientImp::RecordInitL()
       
   299 	{
       
   300 
       
   301 	if (!iDevSoundObserver)
       
   302 		User::Leave(KErrNotReady);
       
   303 	iDevSoundProxy->RecordInitL();
       
   304 	}
       
   305 
       
   306 /*
       
   307  *
       
   308  *	Plays data in the buffer at the current volume. The client should fill
       
   309  *	the buffer with audio data before calling this method. The Observer gets
       
   310  *	reference to buffer along with callback BufferToBeFilled(). When playing of
       
   311  *	the audio sample is complete, successfully or otherwise, the method
       
   312  *	PlayError() on observer is called.
       
   313  *
       
   314  */
       
   315 void CMMFDevSoundClientImp::PlayData()
       
   316 	{
       
   317 	ASSERT(iDevSoundObserver);
       
   318 	iDevSoundProxy->PlayData();
       
   319 	}
       
   320 
       
   321 /*
       
   322  *
       
   323  *	Stops the ongoing operation (Play, Record, TonePlay, Convert)
       
   324  *
       
   325  */
       
   326 void CMMFDevSoundClientImp::Stop()
       
   327 	{
       
   328 	iDevSoundProxy->Stop();
       
   329 	}
       
   330 
       
   331 /*
       
   332  *
       
   333  *	Temporarily Stops the ongoing operation (Play, Record, TonePlay, Convert)
       
   334  *
       
   335  */
       
   336 void CMMFDevSoundClientImp::Pause()
       
   337 	{
       
   338 	iDevSoundProxy->Pause();
       
   339 	}
       
   340 
       
   341 /*
       
   342  *
       
   343  *	Returns the sample recorded so far.
       
   344  *
       
   345  *	@return "TInt"
       
   346  *			Returns the samples recorded.
       
   347  *
       
   348  */
       
   349 TInt CMMFDevSoundClientImp::SamplesRecorded()
       
   350 	{
       
   351 	return iDevSoundProxy->SamplesRecorded();
       
   352 	}
       
   353 
       
   354 /*
       
   355  *
       
   356  *	Returns the sample played so far.
       
   357  *
       
   358  *	@return "TInt"
       
   359  *			Returns the samples recorded.
       
   360  *
       
   361  */
       
   362 TInt CMMFDevSoundClientImp::SamplesPlayed()
       
   363 	{
       
   364 	return iDevSoundProxy->SamplesPlayed();
       
   365 	}
       
   366 
       
   367 
       
   368 /*
       
   369  *
       
   370  *	Initializes audio device and start playing tone. Tone is played with
       
   371  *	frequency and for duration specified.
       
   372  *
       
   373  *	Leaves on failure.
       
   374  *
       
   375  *	@param	"TInt aFrequency"
       
   376  *			Frequency at with the tone will be played.
       
   377  *
       
   378  *	@param	"TTimeIntervalMicroSeconds& aDuration"
       
   379  *			The period over which the tone will be played. A zero value causes
       
   380  *			the no tone to be played (Verify this with test app).
       
   381  *
       
   382  */
       
   383 void CMMFDevSoundClientImp::PlayToneL(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration)
       
   384 	{
       
   385 	iDevSoundProxy->PlayToneL(aFrequency, aDuration);
       
   386 	}
       
   387 
       
   388 /*
       
   389  *	Initializes audio device and start playing a dual tone. 
       
   390  *  The tone consists of two sine waves of different frequencies summed together
       
   391  *  Dual Tone is played with specified frequencies and for specified duration.
       
   392  *
       
   393  *	@param	"aFrequencyOne"
       
   394  *			First frequency of dual tone
       
   395  *
       
   396  *	@param	"aFrequencyTwo"
       
   397  *			Second frequency of dual tone
       
   398  *
       
   399  *	@param	"aDuration"
       
   400  *			The period over which the tone will be played. A zero value causes
       
   401  *			the no tone to be played (Verify this with test app).
       
   402  */
       
   403 void CMMFDevSoundClientImp::PlayDualToneL(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration)
       
   404 	{
       
   405 	iDevSoundProxy->PlayDualToneL(aFrequencyOne, aFrequencyTwo, aDuration);
       
   406 	}
       
   407 
       
   408 /*
       
   409  *
       
   410  *	Initializes audio device and start playing DTMF string aDTMFString.
       
   411  *
       
   412  *	Leaves on failure.
       
   413  *
       
   414  *	@param	"TDesC& aDTMFString"
       
   415  *			DTMF sequence in a descriptor.
       
   416  *
       
   417  */
       
   418 void CMMFDevSoundClientImp::PlayDTMFStringL(const TDesC& aDTMFString)
       
   419 	{
       
   420 	if (!iDevSoundObserver)
       
   421 		User::Leave(KErrNotReady);
       
   422 
       
   423 	iDevSoundProxy->PlayDTMFStringL(aDTMFString);
       
   424 	}
       
   425 
       
   426 /*
       
   427  *
       
   428  *	Initializes audio device and start playing tone sequence.
       
   429  *
       
   430  *	Leaves on failure.
       
   431  *
       
   432  *	@param	"TDesC8& aData"
       
   433  *			Tone sequence in a descriptor.
       
   434  *
       
   435  */
       
   436 void CMMFDevSoundClientImp::PlayToneSequenceL(const TDesC8& aData)
       
   437 	{
       
   438 	if (!iDevSoundObserver)
       
   439 		User::Leave(KErrNotReady);
       
   440 
       
   441 	iDevSoundProxy->PlayToneSequenceL(aData);
       
   442 	}
       
   443 
       
   444 /*
       
   445  *
       
   446  *	Initializes audio device and start playing the specified pre-defined tone
       
   447  *	sequence.
       
   448  *
       
   449  *	Leaves on failure.
       
   450  *
       
   451  *	@param	"TInt aSequenceNumber"
       
   452  *			The index identifying the specific pre-defined tone sequence. Index
       
   453  *			values are relative to zero.
       
   454  *			This can be any value from zero to the value returned by a call to
       
   455  *			CMdaAudioPlayerUtility::FixedSequenceCount() - 1.
       
   456  *			The function raises a panic if sequence number is not within this
       
   457  *			range.
       
   458  *
       
   459  */
       
   460 void CMMFDevSoundClientImp::PlayFixedSequenceL(TInt aSequenceNumber)
       
   461 	{
       
   462 	if (!iDevSoundObserver)
       
   463 		User::Leave(KErrNotReady);
       
   464 
       
   465 	iDevSoundProxy->PlayFixedSequenceL(aSequenceNumber);
       
   466 	}
       
   467 
       
   468 /*
       
   469  *
       
   470  *	Defines the duration of tone on, tone off and tone pause to be used during the
       
   471  *	DTMF tone playback operation.
       
   472  *
       
   473  *	Supported only during tone playing.
       
   474  *
       
   475  *	@param	"TTimeIntervalMicroSeconds32& aToneOnLength"
       
   476  *			The period over which the tone will be played. If this is set to
       
   477  *			zero, then the tone is not played.
       
   478  *
       
   479  *	@param	"TTimeIntervalMicroSeconds32& aToneOffLength"
       
   480  *			The period over which the no tone will be played.
       
   481  *
       
   482  *	@param	"TTimeIntervalMicroSeconds32& aPauseLength"
       
   483  *			The period over which the tone playing will be paused.
       
   484  *
       
   485  */
       
   486 void CMMFDevSoundClientImp::SetDTMFLengths(TTimeIntervalMicroSeconds32& aToneOnLength,
       
   487 								TTimeIntervalMicroSeconds32& aToneOffLength,
       
   488 								TTimeIntervalMicroSeconds32& aPauseLength) 
       
   489 	{
       
   490 	iDevSoundProxy->SetDTMFLengths(aToneOnLength, aToneOffLength, aPauseLength);
       
   491 	}
       
   492 
       
   493 /*
       
   494  *
       
   495  *	Defines the period over which the volume level is to rise smoothly from
       
   496  *	nothing to the normal volume level.
       
   497  *
       
   498  *	@param	"TTimeIntervalMicroSeconds& aRampDuration"
       
   499  *			The period over which the volume is to rise. A zero value causes 
       
   500  *			the tone sample to be played at the normal level for the full
       
   501  *			duration of the playback. A value, which is longer than the duration
       
   502  *			of the tone sample, that the sample never reaches its normal
       
   503  *			volume level.
       
   504  *
       
   505  *
       
   506  */
       
   507 void CMMFDevSoundClientImp::SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)
       
   508 	{
       
   509 	iDevSoundProxy->SetVolumeRamp(aRampDuration);
       
   510 	}
       
   511 
       
   512 
       
   513 /**
       
   514  *	@see sounddevice.h
       
   515  */
       
   516 void CMMFDevSoundClientImp::GetSupportedInputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& aPrioritySettings) const
       
   517 	{
       
   518 	iDevSoundProxy->GetSupportedInputDataTypesL(aSupportedDataTypes, aPrioritySettings);
       
   519 	}
       
   520 
       
   521 /**
       
   522  *	@see sounddevice.h
       
   523  */
       
   524 void CMMFDevSoundClientImp::GetSupportedOutputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& aPrioritySettings) const
       
   525 	{
       
   526 	iDevSoundProxy->GetSupportedOutputDataTypesL(aSupportedDataTypes, aPrioritySettings);
       
   527 	}
       
   528 
       
   529 /**
       
   530  *	@see sounddevice.h
       
   531  */
       
   532 TInt CMMFDevSoundClientImp::SetClientThreadInfo(TThreadId aTid)
       
   533 	{
       
   534 	return iDevSoundProxy->SetClientThreadInfo(aTid);
       
   535 	}
       
   536 
       
   537 
       
   538 TInt CMMFDevSoundClientImp::RegisterAsClient(TUid aEventType, const TDesC8& aNotificationRegistrationData)
       
   539 	{
       
   540 	return iDevSoundProxy->RegisterAsClient(aEventType,aNotificationRegistrationData);
       
   541 	}
       
   542 	
       
   543 TInt CMMFDevSoundClientImp::CancelRegisterAsClient(TUid aEventType)
       
   544 	{
       
   545 	return iDevSoundProxy->CancelRegisterAsClient(aEventType);
       
   546 	}
       
   547 	
       
   548 TInt CMMFDevSoundClientImp::GetResourceNotificationData(TUid aEventType,TDes8& aNotificationData)
       
   549 	{
       
   550 	return iDevSoundProxy->GetResourceNotificationData(aEventType,aNotificationData);
       
   551 	}
       
   552 	
       
   553 TInt CMMFDevSoundClientImp::WillResumePlay()
       
   554 	{
       
   555 	return iDevSoundProxy->WillResumePlay();
       
   556 	}
       
   557 
       
   558 TInt CMMFDevSoundClientImp::EmptyBuffers()
       
   559 	{
       
   560 	return iDevSoundProxy->EmptyBuffers();
       
   561 	}
       
   562 
       
   563 TInt CMMFDevSoundClientImp::GetTimePlayed(TTimeIntervalMicroSeconds& aTime)
       
   564 	{
       
   565 	return iDevSoundProxy->GetTimePlayed(aTime);
       
   566 	}
       
   567 /*
       
   568  *
       
   569  *	Returns a given Custom Interface on the DevSound based on the UID
       
   570  *  If this is not recognised then the custominterface is created by
       
   571  *  a pair of ECOM plugins.
       
   572  *
       
   573  *  @released
       
   574  *  @param	"TUid aInterfaceId"
       
   575  *			The UID of the required Custom Interface
       
   576  *  @return a pointer to the custom interface
       
   577  *
       
   578  */
       
   579 TAny* CMMFDevSoundClientImp::CustomInterface(TUid aInterfaceId)
       
   580 	{
       
   581 	// check if this UID refers to auto/pause/resume
       
   582 	if (aInterfaceId == KMmfUidDevSoundAudioResourceCustomInterface)
       
   583 		{
       
   584 		MAutoPauseResumeSupport* result = this; 
       
   585 		return result;
       
   586 		}
       
   587 	if (aInterfaceId == KMmfUidDevSoundEmptyBuffersCustomInterface)
       
   588 		{
       
   589 		MMMFDevSoundEmptyBuffers* result = this; 
       
   590 		return result;
       
   591 		}		
       
   592 	if (aInterfaceId == KMmfUidDevSoundAudioClientThreadInfoCustomInterface)
       
   593 		{
       
   594 		MAudioClientThreadInfo* result = this;
       
   595 		return result;
       
   596 		}
       
   597 
       
   598 	if (aInterfaceId == KMmfUidDevSoundTimePlayedCustomInterface)
       
   599 		{
       
   600 		MMMFDevSoundTimePlayed* result = this;
       
   601 		return result;
       
   602 		}	
       
   603 		
       
   604 	// we are being asked for a Custom Interface not natively supported 
       
   605 	// by the DevSound plugin.  
       
   606 	
       
   607 	// first check if we already have resolved a custom interface of this type
       
   608 	TInt index = FindCustomInterface(aInterfaceId);
       
   609 	
       
   610 	MMMFDevSoundCustomInterfaceMuxPlugin* ptr = NULL;
       
   611 		
       
   612 	// if we found the interface, take a copy of this instead
       
   613 	if (index != KNullHandle)
       
   614 		{
       
   615 		// check our index is valid
       
   616 		ptr = iCustomInterfaceArray[index-1].iInterface;
       
   617 		if (ptr)		
       
   618 			{
       
   619 			return ptr->CustomInterface(aInterfaceId);
       
   620 			}
       
   621 		else
       
   622 			{
       
   623 			// we may not need this code because this 
       
   624 			// *should* be impossible to reach
       
   625 			return NULL;
       
   626 			}
       
   627 		}
       
   628 	else
       
   629 		{
       
   630 		// else try and instantiate a plugin tunnelling
       
   631 		// pair to support this Custom Interface
       
   632 		TRAPD(err, ptr = iMuxUtility->CreateCustomInterfaceMuxL(aInterfaceId));
       
   633 	
       
   634 		if (ptr && (err == KErrNone))
       
   635 			{
       
   636 			TMMFDevSoundCustomInterfaceData data;
       
   637 			data.iInterface = ptr;
       
   638 			data.iId = aInterfaceId;
       
   639 			
       
   640 			// attempt to open remote demux
       
   641 			// this will store a handle in the mux plugin if successful
       
   642 			// and also return it here - invalid handle = -1
       
   643 			data.iHandle = ptr->OpenInterface(aInterfaceId);
       
   644 			
       
   645 			// if the handle is greater than zero then we know we have
       
   646 			// successfully opened the interface
       
   647 			if (data.iHandle > KNullHandle)
       
   648 				{	
       
   649 				// append this to the current interface list
       
   650 				TInt err = KErrNone;
       
   651 				err = iCustomInterfaceArray.Append(data);
       
   652 				if (err == KErrNone)
       
   653 					{
       
   654 					// return the custom interface on the ptr
       
   655 					return ptr->CustomInterface(aInterfaceId);
       
   656 					}
       
   657 				}
       
   658 					
       
   659 				// no memory or other problem so shut down interface
       
   660 				ptr->Release();
       
   661 				ptr = NULL;
       
   662 			}
       
   663 		}
       
   664 		
       
   665 		// if code gets here then we don't support the interface
       
   666 		// so we can pass it onto the DevSound proxy so that we 
       
   667 		// can attempt to resolve the interface externally
       
   668 		return iDevSoundProxy->CustomInterface(aInterfaceId);	
       
   669 	}
       
   670 
       
   671 TInt CMMFDevSoundClientImp::FindCustomInterface(TUid aInterfaceId)
       
   672 	{
       
   673 	TInt index = KNullHandle;
       
   674 	
       
   675 	for (TInt i = 0; i < iCustomInterfaceArray.Count(); i++)
       
   676 		{
       
   677 		if (iCustomInterfaceArray[i].iId == aInterfaceId)
       
   678 			{
       
   679 			index = i+1; // use index+1 as the handle, so 0 is undefined/not-found
       
   680 			break;
       
   681 			}
       
   682 		}
       
   683 	
       
   684 	return index;
       
   685 	}
       
   686 
       
   687 void CMMFDevSoundClientImp::CloseCustomInterface(TInt aIndex)
       
   688 	{
       
   689 	for (TInt i = 0; i < iCustomInterfaceArray.Count(); i++)
       
   690 		{
       
   691 		if(iCustomInterfaceArray[i].iHandle == aIndex)
       
   692 			{
       
   693 			iCustomInterfaceArray[i].iInterface->Release();	
       
   694 			iCustomInterfaceArray.Remove(i);
       
   695 			break;
       
   696 			}
       
   697 		}
       
   698 	}