1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/devsound/devsoundrefplugin/src/platsec/SoundDevice/SoundDeviceBody.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,698 @@
1.4 +// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include <mmf/plugin/mmfhwdeviceimplementationuids.hrh>
1.20 +#include "SoundDeviceBody.h"
1.21 +#include <mmf/server/mmfswcodecwrappercustominterfacesuids.hrh> // KUidRefDevSoundTaskConfig
1.22 +
1.23 +const TInt KMaxMessageQueueItems = 8;
1.24 +
1.25 +/*
1.26 + *
1.27 + * Default Constructor.
1.28 + *
1.29 + * No default implementation. CMMFDevSound implements 2-phase construction.
1.30 + *
1.31 + */
1.32 +CMMFDevSoundClientImp::CMMFDevSoundClientImp()
1.33 + {
1.34 + }
1.35 +
1.36 +/*
1.37 + *
1.38 + * Destructor.
1.39 + *
1.40 + * Deletes all objects and releases all resource owned by this
1.41 + * instance.
1.42 + *
1.43 + */
1.44 +CMMFDevSoundClientImp::~CMMFDevSoundClientImp()
1.45 + {
1.46 + // clear the array of custom interfaces
1.47 + for (TInt i = 0; i < iCustomInterfaceArray.Count(); i++)
1.48 + {
1.49 + iCustomInterfaceArray[i].iInterface->Release();
1.50 + }
1.51 + iCustomInterfaceArray.Reset();
1.52 + iCustomInterfaceArray.Close();
1.53 +
1.54 + // delete the MUX utility
1.55 + delete iMuxUtility;
1.56 +
1.57 + if (iMsgQueueHandler && iMsgQueueHandler->IsActive())
1.58 + {
1.59 + iMsgQueueHandler->Cancel();
1.60 + }
1.61 + delete iMsgQueueHandler;
1.62 +
1.63 + iMsgQueue.Close();
1.64 +
1.65 + if( iDevSoundProxy != NULL)
1.66 + {
1.67 + iDevSoundProxy->Close();
1.68 + delete iDevSoundProxy;
1.69 + }
1.70 + }
1.71 +
1.72 +/*
1.73 + *
1.74 + * Constructs, and returns a pointer to, a new CMMFDevSound object.
1.75 + *
1.76 + * Leaves on failure.
1.77 + *
1.78 + */
1.79 +CMMFDevSoundClientImp* CMMFDevSoundClientImp::NewL()
1.80 + {
1.81 + CMMFDevSoundClientImp* self = new (ELeave) CMMFDevSoundClientImp();
1.82 + CleanupStack::PushL(self);
1.83 + self->ConstructL();
1.84 + CleanupStack::Pop(self);
1.85 + return self;
1.86 + }
1.87 +
1.88 +/*
1.89 + *
1.90 + * 2nd phase constructor - assumes that iParent has already been set up properly.
1.91 + *
1.92 + */
1.93 +void CMMFDevSoundClientImp::ConstructL()
1.94 + {
1.95 + // all these data properties should be NULL, but add ASSERTs to verify
1.96 +
1.97 + ASSERT(iDevSoundProxy==NULL);
1.98 + iDevSoundProxy = new (ELeave) RMMFDevSoundProxy();
1.99 +
1.100 + TInt err = iMsgQueue.CreateGlobal(KNullDesC, KMaxMessageQueueItems); // global, accessible to all that have its handle
1.101 + User::LeaveIfError(err);
1.102 + err = iDevSoundProxy->Open(iMsgQueue);
1.103 + if(err)
1.104 + {
1.105 + delete iDevSoundProxy;
1.106 + iDevSoundProxy = NULL;
1.107 + }
1.108 +
1.109 + User::LeaveIfError(err);
1.110 +
1.111 + // create MUX utility
1.112 + iMuxUtility = CMMFDevSoundCIMuxUtility::NewL(this);
1.113 + }
1.114 +
1.115 +
1.116 +/*
1.117 + *
1.118 + * Initializes CMMFDevSound object to play and record PCM16 raw audio data
1.119 + * with sampling rate of 8 KHz.
1.120 + *
1.121 + * On completion of Initialization, calls InitializeComplete() on
1.122 + * aDevSoundObserver.
1.123 + *
1.124 + * Leaves on failure.
1.125 + *
1.126 + * @param "MDevSoundObserver& aDevSoundObserver"
1.127 + * A reference to DevSound Observer instance.
1.128 + *
1.129 + * @param "TMMFState aMode"
1.130 + * Mode for which this object will be used.
1.131 + *
1.132 + */
1.133 +void CMMFDevSoundClientImp::InitializeL(MDevSoundObserver& aDevSoundObserver, TMMFState aMode)
1.134 +
1.135 + {
1.136 + TInt initError = KErrNone;
1.137 + iDevSoundObserver = &aDevSoundObserver;
1.138 + initError = iDevSoundProxy->InitializeL(aMode);
1.139 +
1.140 + if (initError)
1.141 + {
1.142 + User::Leave(initError);
1.143 + }
1.144 +
1.145 + if (iMsgQueueHandler)
1.146 + {
1.147 + iMsgQueueHandler->Cancel();
1.148 + iMsgQueueHandler->SetObserver(*iDevSoundObserver);
1.149 + }
1.150 + else
1.151 + {
1.152 + iMsgQueueHandler = CMsgQueueHandler::NewL(iDevSoundProxy, *iDevSoundObserver, &iMsgQueue, *this);
1.153 + }
1.154 +
1.155 + iMsgQueueHandler->ReceiveEvents();
1.156 + }
1.157 +
1.158 +/*
1.159 + *
1.160 + * Configure CMMFDevSound object for the settings in aConfig.
1.161 + *
1.162 + * Use this to set sampling rate, Encoding and Mono/Stereo.
1.163 + *
1.164 + * @param "TMMFCapabilities& aConfig"
1.165 + * Attribute values to which CMMFDevSound object will be configured to.
1.166 + *
1.167 + * As part of defect 20796, the iRecordFormat has been set under the iPlayFormat,
1.168 + * before it was not set at all.
1.169 + *
1.170 + */
1.171 +void CMMFDevSoundClientImp::SetConfigL(const TMMFCapabilities& aConfig)
1.172 + {
1.173 + iDevSoundProxy->SetConfigL(aConfig);
1.174 + }
1.175 +
1.176 +/*
1.177 + *
1.178 + * Changes the current playback volume to a specified value.
1.179 + *
1.180 + * The volume can be changed before or during playback and is effective
1.181 + * immediately.
1.182 + *
1.183 + * @param "TInt aVolume"
1.184 + * The volume setting. This can be any value from zero to the value
1.185 + * returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
1.186 + * volume is not within this range, the volume is automatically set to
1.187 + * minimum or maximum value based on the value that is being passed.
1.188 + * Setting a zero value mutes the sound. Setting the maximum value
1.189 + * results in the loudest possible sound.
1.190 + *
1.191 + */
1.192 +void CMMFDevSoundClientImp::SetVolume(TInt aVolume)
1.193 + {
1.194 + iDevSoundProxy->SetVolume(aVolume);
1.195 + }
1.196 +
1.197 +/*
1.198 + *
1.199 + * Changes the current recording gain to a specified value.
1.200 + *
1.201 + * The gain can be changed before or during recording and is effective
1.202 + * immediately.
1.203 + *
1.204 + * @param "TInt aGain"
1.205 + * The volume setting. This can be any value from zero to the value
1.206 + * returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
1.207 + * volume is not within this range, the gain is automatically set to
1.208 + * minimum or maximum value based on the value that is being passed.
1.209 + * Setting a zero value mutes the sound. Setting the maximum value
1.210 + * results in the loudest possible sound.
1.211 + *
1.212 + */
1.213 +void CMMFDevSoundClientImp::SetGain(TInt aGain)
1.214 + {
1.215 + iDevSoundProxy->SetGain(aGain);
1.216 + }
1.217 +
1.218 +/*
1.219 + *
1.220 + * Sets the speaker balance for playing.
1.221 + *
1.222 + * The speaker balance can be changed before or during playback and is
1.223 + * effective immediately.
1.224 + *
1.225 + * @param "TInt& aLeftPercentage"
1.226 + * On return contains left speaker volume perecentage. This can be any
1.227 + * value from zero to 100. Setting a zero value mutes the sound on left
1.228 + * speaker.
1.229 + *
1.230 + * @param "TInt& aRightPercentage"
1.231 + * On return contains right speaker volume perecentage. This can be any
1.232 + * value from zero to 100. Setting a zero value mutes the sound on
1.233 + * right speaker.
1.234 + *
1.235 + */
1.236 +void CMMFDevSoundClientImp::SetPlayBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
1.237 + {
1.238 + iDevSoundProxy->SetPlayBalanceL(aLeftPercentage, aRightPercentage);
1.239 + }
1.240 +
1.241 +/*
1.242 + *
1.243 + * Sets the microphone gain balance for recording.
1.244 + *
1.245 + * The microphone gain balance can be changed before or during recording and
1.246 + * is effective immediately.
1.247 + *
1.248 + * @param "TInt aLeftPercentage"
1.249 + * Left microphone gain precentage. This can be any value from zero to
1.250 + * 100. Setting a zero value mutes the gain on left microphone.
1.251 + *
1.252 + * @param "TInt aRightPercentage"
1.253 + * Right microphone gain precentage. This can be any value from zero to
1.254 + * 100. Setting a zero value mutes the gain on right microphone.
1.255 + *
1.256 + */
1.257 +void CMMFDevSoundClientImp::SetRecordBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
1.258 + {
1.259 + iDevSoundProxy->SetRecordBalanceL(aLeftPercentage, aRightPercentage);
1.260 + }
1.261 +
1.262 +/*
1.263 + *
1.264 + * Initializes audio device and start play process. This method queries and
1.265 + * acquires the audio policy before initializing audio device. If there was an
1.266 + * error during policy initialization, PlayError() method will be called on
1.267 + * the observer with error code KErrAccessDenied, otherwise BufferToBeFilled()
1.268 + * method will be called with a buffer reference. After reading data into the
1.269 + * buffer reference passed, the client should call PlayData() to play data.
1.270 + *
1.271 + * The amount of data that can be played is specified in
1.272 + * CMMFBuffer::RequestSize(). Any data that is read into buffer beyond this
1.273 + * size will be ignored.
1.274 + *
1.275 + * Leaves on failure.
1.276 + *
1.277 + */
1.278 +void CMMFDevSoundClientImp::PlayInitL()
1.279 + {
1.280 + if (!iDevSoundObserver)
1.281 + User::Leave(KErrNotReady);
1.282 + iDevSoundProxy->PlayInitL();
1.283 + }
1.284 +
1.285 +/*
1.286 + *
1.287 + * Initializes audio device and start record process. This method queries and
1.288 + * acquires the audio policy before initializing audio device. If there was an
1.289 + * error during policy initialization, RecordError() method will be called on
1.290 + * the observer with error code KErrAccessDenied, otherwise BufferToBeEmptied()
1.291 + * method will be called with a buffer reference. This buffer contains recorded
1.292 + * or encoded data. After processing data in the buffer reference passed, the
1.293 + * client should call RecordData() to continue recording process.
1.294 + *
1.295 + * The amount of data that is available is specified in
1.296 + * CMMFBuffer::RequestSize().
1.297 + *
1.298 + * Leaves on failure.
1.299 + *
1.300 + */
1.301 +void CMMFDevSoundClientImp::RecordInitL()
1.302 + {
1.303 +
1.304 + if (!iDevSoundObserver)
1.305 + User::Leave(KErrNotReady);
1.306 + iDevSoundProxy->RecordInitL();
1.307 + }
1.308 +
1.309 +/*
1.310 + *
1.311 + * Plays data in the buffer at the current volume. The client should fill
1.312 + * the buffer with audio data before calling this method. The Observer gets
1.313 + * reference to buffer along with callback BufferToBeFilled(). When playing of
1.314 + * the audio sample is complete, successfully or otherwise, the method
1.315 + * PlayError() on observer is called.
1.316 + *
1.317 + */
1.318 +void CMMFDevSoundClientImp::PlayData()
1.319 + {
1.320 + ASSERT(iDevSoundObserver);
1.321 + iDevSoundProxy->PlayData();
1.322 + }
1.323 +
1.324 +/*
1.325 + *
1.326 + * Stops the ongoing operation (Play, Record, TonePlay, Convert)
1.327 + *
1.328 + */
1.329 +void CMMFDevSoundClientImp::Stop()
1.330 + {
1.331 + iDevSoundProxy->Stop();
1.332 + }
1.333 +
1.334 +/*
1.335 + *
1.336 + * Temporarily Stops the ongoing operation (Play, Record, TonePlay, Convert)
1.337 + *
1.338 + */
1.339 +void CMMFDevSoundClientImp::Pause()
1.340 + {
1.341 + iDevSoundProxy->Pause();
1.342 + }
1.343 +
1.344 +/*
1.345 + *
1.346 + * Returns the sample recorded so far.
1.347 + *
1.348 + * @return "TInt"
1.349 + * Returns the samples recorded.
1.350 + *
1.351 + */
1.352 +TInt CMMFDevSoundClientImp::SamplesRecorded()
1.353 + {
1.354 + return iDevSoundProxy->SamplesRecorded();
1.355 + }
1.356 +
1.357 +/*
1.358 + *
1.359 + * Returns the sample played so far.
1.360 + *
1.361 + * @return "TInt"
1.362 + * Returns the samples recorded.
1.363 + *
1.364 + */
1.365 +TInt CMMFDevSoundClientImp::SamplesPlayed()
1.366 + {
1.367 + return iDevSoundProxy->SamplesPlayed();
1.368 + }
1.369 +
1.370 +
1.371 +/*
1.372 + *
1.373 + * Initializes audio device and start playing tone. Tone is played with
1.374 + * frequency and for duration specified.
1.375 + *
1.376 + * Leaves on failure.
1.377 + *
1.378 + * @param "TInt aFrequency"
1.379 + * Frequency at with the tone will be played.
1.380 + *
1.381 + * @param "TTimeIntervalMicroSeconds& aDuration"
1.382 + * The period over which the tone will be played. A zero value causes
1.383 + * the no tone to be played (Verify this with test app).
1.384 + *
1.385 + */
1.386 +void CMMFDevSoundClientImp::PlayToneL(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration)
1.387 + {
1.388 + iDevSoundProxy->PlayToneL(aFrequency, aDuration);
1.389 + }
1.390 +
1.391 +/*
1.392 + * Initializes audio device and start playing a dual tone.
1.393 + * The tone consists of two sine waves of different frequencies summed together
1.394 + * Dual Tone is played with specified frequencies and for specified duration.
1.395 + *
1.396 + * @param "aFrequencyOne"
1.397 + * First frequency of dual tone
1.398 + *
1.399 + * @param "aFrequencyTwo"
1.400 + * Second frequency of dual tone
1.401 + *
1.402 + * @param "aDuration"
1.403 + * The period over which the tone will be played. A zero value causes
1.404 + * the no tone to be played (Verify this with test app).
1.405 + */
1.406 +void CMMFDevSoundClientImp::PlayDualToneL(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration)
1.407 + {
1.408 + iDevSoundProxy->PlayDualToneL(aFrequencyOne, aFrequencyTwo, aDuration);
1.409 + }
1.410 +
1.411 +/*
1.412 + *
1.413 + * Initializes audio device and start playing DTMF string aDTMFString.
1.414 + *
1.415 + * Leaves on failure.
1.416 + *
1.417 + * @param "TDesC& aDTMFString"
1.418 + * DTMF sequence in a descriptor.
1.419 + *
1.420 + */
1.421 +void CMMFDevSoundClientImp::PlayDTMFStringL(const TDesC& aDTMFString)
1.422 + {
1.423 + if (!iDevSoundObserver)
1.424 + User::Leave(KErrNotReady);
1.425 +
1.426 + iDevSoundProxy->PlayDTMFStringL(aDTMFString);
1.427 + }
1.428 +
1.429 +/*
1.430 + *
1.431 + * Initializes audio device and start playing tone sequence.
1.432 + *
1.433 + * Leaves on failure.
1.434 + *
1.435 + * @param "TDesC8& aData"
1.436 + * Tone sequence in a descriptor.
1.437 + *
1.438 + */
1.439 +void CMMFDevSoundClientImp::PlayToneSequenceL(const TDesC8& aData)
1.440 + {
1.441 + if (!iDevSoundObserver)
1.442 + User::Leave(KErrNotReady);
1.443 +
1.444 + iDevSoundProxy->PlayToneSequenceL(aData);
1.445 + }
1.446 +
1.447 +/*
1.448 + *
1.449 + * Initializes audio device and start playing the specified pre-defined tone
1.450 + * sequence.
1.451 + *
1.452 + * Leaves on failure.
1.453 + *
1.454 + * @param "TInt aSequenceNumber"
1.455 + * The index identifying the specific pre-defined tone sequence. Index
1.456 + * values are relative to zero.
1.457 + * This can be any value from zero to the value returned by a call to
1.458 + * CMdaAudioPlayerUtility::FixedSequenceCount() - 1.
1.459 + * The function raises a panic if sequence number is not within this
1.460 + * range.
1.461 + *
1.462 + */
1.463 +void CMMFDevSoundClientImp::PlayFixedSequenceL(TInt aSequenceNumber)
1.464 + {
1.465 + if (!iDevSoundObserver)
1.466 + User::Leave(KErrNotReady);
1.467 +
1.468 + iDevSoundProxy->PlayFixedSequenceL(aSequenceNumber);
1.469 + }
1.470 +
1.471 +/*
1.472 + *
1.473 + * Defines the duration of tone on, tone off and tone pause to be used during the
1.474 + * DTMF tone playback operation.
1.475 + *
1.476 + * Supported only during tone playing.
1.477 + *
1.478 + * @param "TTimeIntervalMicroSeconds32& aToneOnLength"
1.479 + * The period over which the tone will be played. If this is set to
1.480 + * zero, then the tone is not played.
1.481 + *
1.482 + * @param "TTimeIntervalMicroSeconds32& aToneOffLength"
1.483 + * The period over which the no tone will be played.
1.484 + *
1.485 + * @param "TTimeIntervalMicroSeconds32& aPauseLength"
1.486 + * The period over which the tone playing will be paused.
1.487 + *
1.488 + */
1.489 +void CMMFDevSoundClientImp::SetDTMFLengths(TTimeIntervalMicroSeconds32& aToneOnLength,
1.490 + TTimeIntervalMicroSeconds32& aToneOffLength,
1.491 + TTimeIntervalMicroSeconds32& aPauseLength)
1.492 + {
1.493 + iDevSoundProxy->SetDTMFLengths(aToneOnLength, aToneOffLength, aPauseLength);
1.494 + }
1.495 +
1.496 +/*
1.497 + *
1.498 + * Defines the period over which the volume level is to rise smoothly from
1.499 + * nothing to the normal volume level.
1.500 + *
1.501 + * @param "TTimeIntervalMicroSeconds& aRampDuration"
1.502 + * The period over which the volume is to rise. A zero value causes
1.503 + * the tone sample to be played at the normal level for the full
1.504 + * duration of the playback. A value, which is longer than the duration
1.505 + * of the tone sample, that the sample never reaches its normal
1.506 + * volume level.
1.507 + *
1.508 + *
1.509 + */
1.510 +void CMMFDevSoundClientImp::SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)
1.511 + {
1.512 + iDevSoundProxy->SetVolumeRamp(aRampDuration);
1.513 + }
1.514 +
1.515 +
1.516 +/**
1.517 + * @see sounddevice.h
1.518 + */
1.519 +void CMMFDevSoundClientImp::GetSupportedInputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& aPrioritySettings) const
1.520 + {
1.521 + iDevSoundProxy->GetSupportedInputDataTypesL(aSupportedDataTypes, aPrioritySettings);
1.522 + }
1.523 +
1.524 +/**
1.525 + * @see sounddevice.h
1.526 + */
1.527 +void CMMFDevSoundClientImp::GetSupportedOutputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& aPrioritySettings) const
1.528 + {
1.529 + iDevSoundProxy->GetSupportedOutputDataTypesL(aSupportedDataTypes, aPrioritySettings);
1.530 + }
1.531 +
1.532 +/**
1.533 + * @see sounddevice.h
1.534 + */
1.535 +TInt CMMFDevSoundClientImp::SetClientThreadInfo(TThreadId aTid)
1.536 + {
1.537 + return iDevSoundProxy->SetClientThreadInfo(aTid);
1.538 + }
1.539 +
1.540 +
1.541 +TInt CMMFDevSoundClientImp::RegisterAsClient(TUid aEventType, const TDesC8& aNotificationRegistrationData)
1.542 + {
1.543 + return iDevSoundProxy->RegisterAsClient(aEventType,aNotificationRegistrationData);
1.544 + }
1.545 +
1.546 +TInt CMMFDevSoundClientImp::CancelRegisterAsClient(TUid aEventType)
1.547 + {
1.548 + return iDevSoundProxy->CancelRegisterAsClient(aEventType);
1.549 + }
1.550 +
1.551 +TInt CMMFDevSoundClientImp::GetResourceNotificationData(TUid aEventType,TDes8& aNotificationData)
1.552 + {
1.553 + return iDevSoundProxy->GetResourceNotificationData(aEventType,aNotificationData);
1.554 + }
1.555 +
1.556 +TInt CMMFDevSoundClientImp::WillResumePlay()
1.557 + {
1.558 + return iDevSoundProxy->WillResumePlay();
1.559 + }
1.560 +
1.561 +TInt CMMFDevSoundClientImp::EmptyBuffers()
1.562 + {
1.563 + return iDevSoundProxy->EmptyBuffers();
1.564 + }
1.565 +
1.566 +TInt CMMFDevSoundClientImp::GetTimePlayed(TTimeIntervalMicroSeconds& aTime)
1.567 + {
1.568 + return iDevSoundProxy->GetTimePlayed(aTime);
1.569 + }
1.570 +/*
1.571 + *
1.572 + * Returns a given Custom Interface on the DevSound based on the UID
1.573 + * If this is not recognised then the custominterface is created by
1.574 + * a pair of ECOM plugins.
1.575 + *
1.576 + * @released
1.577 + * @param "TUid aInterfaceId"
1.578 + * The UID of the required Custom Interface
1.579 + * @return a pointer to the custom interface
1.580 + *
1.581 + */
1.582 +TAny* CMMFDevSoundClientImp::CustomInterface(TUid aInterfaceId)
1.583 + {
1.584 + // check if this UID refers to auto/pause/resume
1.585 + if (aInterfaceId == KMmfUidDevSoundAudioResourceCustomInterface)
1.586 + {
1.587 + MAutoPauseResumeSupport* result = this;
1.588 + return result;
1.589 + }
1.590 + if (aInterfaceId == KMmfUidDevSoundEmptyBuffersCustomInterface)
1.591 + {
1.592 + MMMFDevSoundEmptyBuffers* result = this;
1.593 + return result;
1.594 + }
1.595 + if (aInterfaceId == KMmfUidDevSoundAudioClientThreadInfoCustomInterface)
1.596 + {
1.597 + MAudioClientThreadInfo* result = this;
1.598 + return result;
1.599 + }
1.600 +
1.601 + if (aInterfaceId == KMmfUidDevSoundTimePlayedCustomInterface)
1.602 + {
1.603 + MMMFDevSoundTimePlayed* result = this;
1.604 + return result;
1.605 + }
1.606 +
1.607 + // we are being asked for a Custom Interface not natively supported
1.608 + // by the DevSound plugin.
1.609 +
1.610 + // first check if we already have resolved a custom interface of this type
1.611 + TInt index = FindCustomInterface(aInterfaceId);
1.612 +
1.613 + MMMFDevSoundCustomInterfaceMuxPlugin* ptr = NULL;
1.614 +
1.615 + // if we found the interface, take a copy of this instead
1.616 + if (index != KNullHandle)
1.617 + {
1.618 + // check our index is valid
1.619 + ptr = iCustomInterfaceArray[index-1].iInterface;
1.620 + if (ptr)
1.621 + {
1.622 + return ptr->CustomInterface(aInterfaceId);
1.623 + }
1.624 + else
1.625 + {
1.626 + // we may not need this code because this
1.627 + // *should* be impossible to reach
1.628 + return NULL;
1.629 + }
1.630 + }
1.631 + else
1.632 + {
1.633 + // else try and instantiate a plugin tunnelling
1.634 + // pair to support this Custom Interface
1.635 + TRAPD(err, ptr = iMuxUtility->CreateCustomInterfaceMuxL(aInterfaceId));
1.636 +
1.637 + if (ptr && (err == KErrNone))
1.638 + {
1.639 + TMMFDevSoundCustomInterfaceData data;
1.640 + data.iInterface = ptr;
1.641 + data.iId = aInterfaceId;
1.642 +
1.643 + // attempt to open remote demux
1.644 + // this will store a handle in the mux plugin if successful
1.645 + // and also return it here - invalid handle = -1
1.646 + data.iHandle = ptr->OpenInterface(aInterfaceId);
1.647 +
1.648 + // if the handle is greater than zero then we know we have
1.649 + // successfully opened the interface
1.650 + if (data.iHandle > KNullHandle)
1.651 + {
1.652 + // append this to the current interface list
1.653 + TInt err = KErrNone;
1.654 + err = iCustomInterfaceArray.Append(data);
1.655 + if (err == KErrNone)
1.656 + {
1.657 + // return the custom interface on the ptr
1.658 + return ptr->CustomInterface(aInterfaceId);
1.659 + }
1.660 + }
1.661 +
1.662 + // no memory or other problem so shut down interface
1.663 + ptr->Release();
1.664 + ptr = NULL;
1.665 + }
1.666 + }
1.667 +
1.668 + // if code gets here then we don't support the interface
1.669 + // so we can pass it onto the DevSound proxy so that we
1.670 + // can attempt to resolve the interface externally
1.671 + return iDevSoundProxy->CustomInterface(aInterfaceId);
1.672 + }
1.673 +
1.674 +TInt CMMFDevSoundClientImp::FindCustomInterface(TUid aInterfaceId)
1.675 + {
1.676 + TInt index = KNullHandle;
1.677 +
1.678 + for (TInt i = 0; i < iCustomInterfaceArray.Count(); i++)
1.679 + {
1.680 + if (iCustomInterfaceArray[i].iId == aInterfaceId)
1.681 + {
1.682 + index = i+1; // use index+1 as the handle, so 0 is undefined/not-found
1.683 + break;
1.684 + }
1.685 + }
1.686 +
1.687 + return index;
1.688 + }
1.689 +
1.690 +void CMMFDevSoundClientImp::CloseCustomInterface(TInt aIndex)
1.691 + {
1.692 + for (TInt i = 0; i < iCustomInterfaceArray.Count(); i++)
1.693 + {
1.694 + if(iCustomInterfaceArray[i].iHandle == aIndex)
1.695 + {
1.696 + iCustomInterfaceArray[i].iInterface->Release();
1.697 + iCustomInterfaceArray.Remove(i);
1.698 + break;
1.699 + }
1.700 + }
1.701 + }