os/mm/devsound/devsoundrefplugin/src/platsec/server/AudioServer/MmfDevSoundSessionBody.cpp
Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
17 #ifdef SYMBIAN_MULTIMEDIA_CODEC_API
19 #endif // SYMBIAN_MULTIMEDIA_CODEC_API
20 #include "MmfDevSoundSessionBody.h"
21 #include "MmfDevSoundSessionXtnd.h"
22 #include "MmfDevSoundServer.h"
23 #include <mdaaudiotoneplayer.h>
24 #include <mmf/server/mmfdatabuffer.h>
25 #include <mmffourcc.h>
26 #include <mmfhwdeviceimplementationuids.hrh>
27 #include <mmf/server/mmfswcodecwrappercustominterfacesuids.hrh> // KUidRefDevSoundTaskConfig & KMmfUidEmptyBuffersCustomInterface
28 #include <mmf/server/mmfdevsoundcustominterfacesupport.h>
30 const TUid KEmptyBuffersCustomInterfaceTypeUid = {KMmfUidEmptyBuffersCustomInterface};
34 * Default Constructor.
36 * No default implementation. CMMFDevSoundProxy implements 2-phase construction.
39 CMMFDevSoundSvrImp::CMMFDevSoundSvrImp(CMMFDevSoundSessionXtnd* aParent)
42 iMode= EMMFDevSoundStateIdle;
43 //Set reasonable default values for DTMF
44 iDTMFGen.SetToneDurations(250000,50000,250000);
51 * Deletes all objects and releases all resource owned by this
55 CMMFDevSoundSvrImp::~CMMFDevSoundSvrImp()
59 delete iDevSoundEventHandler;
60 if( iAudioPolicyProxy != NULL)
62 iAudioPolicyProxy->Close();
63 delete iAudioPolicyProxy;
66 delete iFixedSequences;
68 #ifdef SYMBIAN_MULTIMEDIA_CODEC_API
70 #endif // SYMBIAN_MULTIMEDIA_CODEC_API
75 * Constructs, and returns a pointer to, a new CMMFDevSoundSvrImp object.
80 CMMFDevSoundSvrImp* CMMFDevSoundSvrImp::NewL(CMMFDevSoundSessionXtnd* aParent)
82 CMMFDevSoundSvrImp* self = new (ELeave) CMMFDevSoundSvrImp(aParent);
88 * 3rd phase constructor - assumes that iParent has already been set up properly
89 * (During ConstructL() it has yet to be
92 void CMMFDevSoundSvrImp::Construct3L(RServer2& aPolicyServerHandle)
94 // all these data properties should be NULL, but add ASSERTs to verity
95 ASSERT(iAudioPolicyProxy==NULL);
96 iAudioPolicyProxy = new (ELeave) RMMFAudioPolicyProxy();
97 ASSERT(iDevSoundEventHandler==NULL);
98 iDevSoundEventHandler = CMMFDevSoundEventHandler::NewL(iAudioPolicyProxy);
99 User::LeaveIfError(iAudioPolicyProxy->Open(aPolicyServerHandle));
100 iDevSoundEventHandler->SetDevSoundInfo(&iParent);
102 iDevSoundUtil = CMMFDevSoundUtility::NewL();
103 // Initialize Fixed sequence related
104 iDevSoundUtil->InitializeFixedSequenceL(&iFixedSequences);
106 #ifdef SYMBIAN_MULTIMEDIA_CODEC_API
108 #endif // SYMBIAN_MULTIMEDIA_CODEC_API
113 * internal procedure to perform all initialization prior to setting the
116 void CMMFDevSoundSvrImp::PreInitializeL()
118 // Set default values for priority settings: Note: Client must
119 // over ride default settings by calling SetPrioirtySettings
120 iAudioPolicyPrioritySettings.iState = EMMFStateStopped;
121 iAudioPolicyPrioritySettings.iPref = EMdaPriorityPreferenceNone;
122 iAudioPolicyPrioritySettings.iPriority = 0;
124 // Get device capabilities and current settings from Audio Policy:
125 User::LeaveIfError(iAudioPolicyProxy->GetPlayFormatsSupported(iPlayFormatsSupported));
126 User::LeaveIfError(iAudioPolicyProxy->GetPlayFormat(iPlayFormat));
127 User::LeaveIfError(iAudioPolicyProxy->GetRecordFormatsSupported(iRecordFormatsSupported));
128 User::LeaveIfError(iAudioPolicyProxy->GetRecordFormat(iRecordFormat));
130 //default to play until we know we are recording
131 User::LeaveIfError(InitializeFormat(iPlayFormatsSupported, iPlayFormat));
136 * Initializes CMMFDevSoundProxy object to play and record PCM16 raw audio data
137 * with sampling rate of 8 KHz.
139 * On completion of Initialization, calls InitializeComplete() on
144 * @param "MDevSoundObserver& aDevSoundObserver"
145 * A reference to DevSound Observer instance.
147 * @param "TMMFState aMode"
148 * Mode for which this object will be used.
151 void CMMFDevSoundSvrImp::InitializeL(MDevSoundObserver& aDevSoundObserver, TMMFState aMode)
154 // if no HwDevice id specified, load default null implementation
155 TUid rawUid = {KMmfUidHwDevicePCM16ToPCM16};
156 InitializeL(aDevSoundObserver, rawUid, aMode);
157 __ASSERT_DEBUG(!(iHasPolicy&&(iMode == EMMFDevSoundStatePlaying)), Panic(TMMFDevSoundSessionPolicyNotInvalidated));
162 * Configure CMMFDevSoundProxy object for the settings in aConfig.
164 * Use this to set sampling rate, Encoding and Mono/Stereo.
166 * @param "TMMFCapabilities& aConfig"
167 * Attribute values to which CMMFDevSoundProxy object will be configured to.
169 * As part of defect 20796, the iRecordFormat has been set under the iPlayFormat,
170 * before it was not set at all.
173 void CMMFDevSoundSvrImp::SetConfigL(const TMMFCapabilities& aConfig)
175 TUint attributeValue = aConfig.iRate;
176 // WINS supports from 8000 Hz to 96000 Hz
177 // The ToneGenerator currently supports sample rate of 8000Hz only.
178 if(iMode == EMMFDevSoundStateTonePlaying && (attributeValue != EMMFSampleRate8000Hz ))
180 User::Leave(KErrNotSupported);
183 if (attributeValue & EMMFSampleRate96000Hz)
185 iPlayFormat().iRate = 96000;
186 iRecordFormat().iRate = 96000;
187 iDeviceConfig.iRate = EMMFSampleRate96000Hz;
189 else if (attributeValue & EMMFSampleRate88200Hz)
191 iPlayFormat().iRate = 88200;
192 iRecordFormat().iRate = 88200;
193 iDeviceConfig.iRate = EMMFSampleRate88200Hz;
195 else if (attributeValue & EMMFSampleRate64000Hz)
197 iPlayFormat().iRate = 64000;
198 iRecordFormat().iRate = 64000;
199 iDeviceConfig.iRate = EMMFSampleRate64000Hz;
201 else if (attributeValue & EMMFSampleRate48000Hz)
203 iPlayFormat().iRate = 48000;
204 iRecordFormat().iRate = 48000;
205 iDeviceConfig.iRate = EMMFSampleRate48000Hz;
207 else if (attributeValue & EMMFSampleRate44100Hz)
209 iPlayFormat().iRate = 44100;
210 iRecordFormat().iRate = 44100;
211 iDeviceConfig.iRate = EMMFSampleRate44100Hz;
213 else if (attributeValue & EMMFSampleRate32000Hz)
215 iPlayFormat().iRate = 32000;
216 iRecordFormat().iRate = 32000;
217 iDeviceConfig.iRate = EMMFSampleRate32000Hz;
219 else if (attributeValue & EMMFSampleRate24000Hz)
221 iPlayFormat().iRate =
222 iRecordFormat().iRate = 24000;
223 iDeviceConfig.iRate = EMMFSampleRate24000Hz;
225 else if (attributeValue & EMMFSampleRate22050Hz)
227 iPlayFormat().iRate = 22050;
228 iRecordFormat().iRate = 22050;
229 iDeviceConfig.iRate = EMMFSampleRate22050Hz;
231 else if (attributeValue & EMMFSampleRate16000Hz)
233 iPlayFormat().iRate = 16000;
234 iRecordFormat().iRate = 16000;
235 iDeviceConfig.iRate = EMMFSampleRate16000Hz;
237 else if (attributeValue & EMMFSampleRate12000Hz)
239 iPlayFormat().iRate =
240 iRecordFormat().iRate = 12000;
241 iDeviceConfig.iRate = EMMFSampleRate12000Hz;
243 else if (attributeValue & EMMFSampleRate11025Hz)
245 iPlayFormat().iRate = 11025;
246 iRecordFormat().iRate = 11025;
247 iDeviceConfig.iRate = EMMFSampleRate11025Hz;
249 else if (attributeValue & EMMFSampleRate8000Hz)
251 iPlayFormat().iRate = 8000;
252 iRecordFormat().iRate = 8000;
253 iDeviceConfig.iRate = EMMFSampleRate8000Hz;
255 else if (attributeValue)
256 { //if no attribute value assume its not set
257 User::Leave(KErrNotSupported);
260 attributeValue = aConfig.iEncoding;
261 // Map from MMF Encoding enums to RMdaDevSound enum
262 if(attributeValue & EMMFSoundEncoding8BitPCM)
264 iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
265 iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
266 iDeviceConfig.iEncoding = EMMFSoundEncoding8BitPCM;
268 else if(attributeValue & EMMFSoundEncoding8BitALaw)
270 iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
271 iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
272 iDeviceConfig.iEncoding = EMMFSoundEncoding8BitALaw;
274 else if(attributeValue & EMMFSoundEncoding8BitMuLaw)
276 iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
277 iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
278 iDeviceConfig.iEncoding = EMMFSoundEncoding8BitMuLaw;
280 else if(attributeValue & EMMFSoundEncoding16BitPCM)
282 iPlayFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
283 iRecordFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
284 iDeviceConfig.iEncoding = EMMFSoundEncoding16BitPCM;
286 else if (attributeValue)
287 { //if no attribute value assume its not set
288 User::Leave(KErrNotSupported);
291 // Mono/Stereo settings
292 attributeValue = aConfig.iChannels;
293 if(iMode == EMMFDevSoundStateTonePlaying && (attributeValue != EMMFMono ))
295 User::Leave(KErrNotSupported);
297 if(attributeValue & EMMFStereo)
299 iPlayFormat().iChannels = 2;
300 iRecordFormat().iChannels = 2;
301 iDeviceConfig.iChannels = EMMFStereo;
303 else if(attributeValue & EMMFMono)
305 iPlayFormat().iChannels = 1;
306 iRecordFormat().iChannels = 1;
307 iDeviceConfig.iChannels = EMMFMono;
309 else if (attributeValue)
310 { //if no attribute value assume its not set
311 User::Leave(KErrNotSupported);
317 * Changes the current playback volume to a specified value.
319 * The volume can be changed before or during playback and is effective
322 * @param "TInt aVolume"
323 * The volume setting. This can be any value from zero to the value
324 * returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
325 * volume is not within this range, the volume is automatically set to
326 * minimum or maximum value based on the value that is being passed.
327 * Setting a zero value mutes the sound. Setting the maximum value
328 * results in the loudest possible sound.
331 void CMMFDevSoundSvrImp::SetVolume(TInt aVolume)
334 // Check and make sure that the volume is in valid range
338 if (aVolume > MaxVolume())
339 aVolume = MaxVolume();
343 SetDeviceVolume(iVolume);
348 * Changes the current recording gain to a specified value.
350 * The gain can be changed before or during recording and is effective
353 * @param "TInt aGain"
354 * The volume setting. This can be any value from zero to the value
355 * returned by a call to CMdaAudioPlayerUtility::MaxVolume(). If the
356 * volume is not within this range, the gain is automatically set to
357 * minimum or maximum value based on the value that is being passed.
358 * Setting a zero value mutes the sound. Setting the maximum value
359 * results in the loudest possible sound.
362 void CMMFDevSoundSvrImp::SetGain(TInt aGain)
364 // make sure it falls with the correct range
365 TInt maxGain = iRecordFormatsSupported().iMaxVolume;
371 SetDeviceRecordLevel(iGain);
376 * Sets the speaker balance for playing.
378 * The speaker balance can be changed before or during playback and is
379 * effective immediately.
381 * @param "TInt& aLeftPercentage"
382 * On return contains left speaker volume perecentage. This can be any
383 * value from zero to 100. Setting a zero value mutes the sound on left
386 * @param "TInt& aRightPercentage"
387 * On return contains right speaker volume perecentage. This can be any
388 * value from zero to 100. Setting a zero value mutes the sound on
392 void CMMFDevSoundSvrImp::SetPlayBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
394 if (aLeftPercentage < 0)
396 else if (aLeftPercentage > 100)
397 aLeftPercentage = 100;
398 if (aRightPercentage < 0)
399 aRightPercentage = 0;
400 else if (aRightPercentage > 100)
401 aRightPercentage = 100;
402 iLeftPlayBalance = aLeftPercentage;
403 iRightPlayBalance = aRightPercentage;
408 * Sets the microphone gain balance for recording.
410 * The microphone gain balance can be changed before or during recording and
411 * is effective immediately.
413 * @param "TInt aLeftPercentage"
414 * Left microphone gain precentage. This can be any value from zero to
415 * 100. Setting a zero value mutes the gain on left microphone.
417 * @param "TInt aRightPercentage"
418 * Right microphone gain precentage. This can be any value from zero to
419 * 100. Setting a zero value mutes the gain on right microphone.
422 void CMMFDevSoundSvrImp::SetRecordBalanceL(TInt aLeftPercentage, TInt aRightPercentage)
424 if (aLeftPercentage < 0)
426 else if (aLeftPercentage > 100)
427 aLeftPercentage = 100;
428 if (aRightPercentage < 0)
429 aRightPercentage = 0;
430 else if (aRightPercentage > 100)
431 aRightPercentage = 100;
432 iLeftRecordBalance = aLeftPercentage;
433 iRightRecordBalance = aRightPercentage;
438 * Initializes audio device and start play process. This method queries and
439 * acquires the audio policy before initializing audio device. If there was an
440 * error during policy initialization, PlayError() method will be called on
441 * the observer with error code KErrAccessDenied, otherwise BufferToBeFilled()
442 * method will be called with a buffer reference. After reading data into the
443 * buffer reference passed, the client should call PlayData() to play data.
445 * The amount of data that can be played is specified in
446 * CMMFBuffer::RequestSize(). Any data that is read into buffer beyond this
447 * size will be ignored.
452 void CMMFDevSoundSvrImp::PlayInitL()
454 if (!iDevSoundObserver)
455 User::Leave(KErrNotReady);
457 if (iAudioPolicyPrioritySettings.iState == EMMFStatePlayData)
459 // If policy has not been obtaing then ignore the request.
460 // If it has then do a stop and start action on HW device
461 // without informing policy.
467 TInt err = iCMMFHwDevice->Stop();
470 err = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);
483 iAudioPolicyPrioritySettings.iState = EMMFStatePlayData;
489 * Initializes audio device and start record process.
491 * 1. Queries and acquires the audio policy before initializing audio device.
492 * If there was an error during policy initialization, RecordError() method will
493 * be called on the observer with error code KErrAccessDenied, otherwise BufferToBeEmptied()
494 * method will be called with a buffer reference. This buffer contains recorded
495 * or encoded data. After processing data in the buffer reference passed, the
496 * client should call RecordData() to continue recording process.
498 * 2. Checks if the requesting client process has a UserEnvironment capability.
499 * If it does not, the audio device will not be initialized and an error
500 * code KErrAccessDenied will be sent to the client.
502 * The amount of data that is available is specified in
503 * CMMFBuffer::RequestSize().
508 void CMMFDevSoundSvrImp::RecordInitL(const RMmfIpcMessage& aMessage)
510 if (!iDevSoundObserver)
511 User::Leave(KErrNotReady);
513 // Checkes if the client has the UserEnvironment capability
514 if (!aMessage.HasCapability(ECapabilityUserEnvironment))
516 User::Leave(KErrPermissionDenied);
519 if (iAudioPolicyPrioritySettings.iState == EMMFStateRecordData)
525 TInt err = iCMMFHwDevice->Stop();
528 err = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);
538 iHwDeviceBuffer->SetLastBuffer(EFalse);
547 iAudioPolicyPrioritySettings.iState = EMMFStateRecordData;
553 * Plays data in the buffer at the current volume. The client should fill
554 * the buffer with audio data before calling this method. The Observer gets
555 * reference to buffer along with callback BufferToBeFilled(). When playing of
556 * the audio sample is complete, successfully or otherwise, the method
557 * PlayError() on observer is called.
560 TBool CMMFDevSoundSvrImp::PlayData(const RMmfIpcMessage& aMessage)
562 ASSERT(iDevSoundObserver);
564 if (iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
566 // Initialisation has been successful but an error (possibly underflow) has occurred
567 // which the controller has yet to respond to and that has changed the state to stopped.
568 // Allow the call to complete and processing to continue...
572 if((iAudioPolicyPrioritySettings.iState != EMMFStatePlayData) && (iAudioPolicyPrioritySettings.iState != EMMFStatePaused))
574 PanicClient(aMessage, EMMFDevSoundPlayDataWithoutInitialize);
577 if (iMode== EMMFDevSoundStateIdle)
581 TInt error = KErrNone;
587 //note PlayData does not leave or return an error code so the Start() fails we cannot
588 //report the error back at this point
589 error = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);//restart hw device after pause
591 else if ((iMode == EMMFDevSoundStatePlaying) && iHasPolicy)
593 TInt len = iHwDeviceBuffer->Data().Length();
594 if (iHwDeviceBuffer->LastBuffer())
596 iLastBufferReceived = ETrue;
598 // Pass the data buffer to HwDevice
599 error = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
602 if (error != KErrNone)
607 iCMMFHwDevice->Stop();
616 * Stops the ongoing operation (Play, Record, TonePlay, Convert)
619 void CMMFDevSoundSvrImp::Stop()
625 UpdatePolicyState(EMMFStateStopped);
629 // Stop the hw device first - this unloads sound drivers
632 iCMMFHwDevice->Stop();
635 iDevSoundEventHandler->CancelReceiveEvents();
637 UpdatePolicyState(EMMFStateStopped);
638 __ASSERT_DEBUG(!(iHasPolicy&&(iMode == EMMFDevSoundStatePlaying)), Panic(TMMFDevSoundSessionPolicyNotInvalidated));
643 * Temporarily Stops the ongoing operation (Play, Record, TonePlay, Convert)
646 void CMMFDevSoundSvrImp::Pause()
655 // Pause the HW device first
658 iCMMFHwDevice->Pause();
664 * Returns the sample recorded so far.
667 * Returns the samples recorded.
670 TInt CMMFDevSoundSvrImp::SamplesRecorded()
674 if(iRecordCustomInterface)
676 samples = iRecordCustomInterface->BytesRecorded();
677 if(NumberOfChannels() > 1)
679 samples /= NumberOfChannels();
681 if(BytesPerAudioSample() > 1)
683 samples /= BytesPerAudioSample();
692 * Returns the sample played so far.
695 * Returns the samples recorded.
698 TInt CMMFDevSoundSvrImp::SamplesPlayed()
701 if(iPlayCustomInterface)
703 TUint bytesPlayed = iPlayCustomInterface->BytesPlayed();
705 iPlayedBytesCount = bytesPlayed;
707 samples = iPlayedBytesCount;
708 if(NumberOfChannels() > 1)
709 samples /= NumberOfChannels();
711 if(BytesPerAudioSample() > 1)
712 samples /= BytesPerAudioSample();
714 //note always pcm16 becuase the iPlayedBytesCount originates from
715 //RMdaDevSound which is always pcm16
716 return samples; //each sample is 2 bytes
722 * Initializes audio device and start playing tone. Tone is played with
723 * frequency and for duration specified.
727 * @param "TInt aFrequency"
728 * Frequency at with the tone will be played.
730 * @param "TTimeIntervalMicroSeconds& aDuration"
731 * The period over which the tone will be played. A zero value causes
732 * the no tone to be played (Verify this with test app).
735 void CMMFDevSoundSvrImp::PlayToneL(TInt aFrequency, const TTimeIntervalMicroSeconds& aDuration)
737 if (iMode != EMMFDevSoundStateTonePlaying)
739 User::Leave(KErrNotSupported); //tone playing only supported in tone play state
742 // Check whether frequency and duration is valid or not
744 if ((aFrequency<0) || (aDuration.Int64() < zeroInt64))
746 User::Leave(KErrArgument);
749 if (!iDevSoundObserver)
751 User::Leave(KErrNotReady);
754 iToneGen.SetFrequencyAndDuration(aFrequency,aDuration);
757 iAudioPolicyPrioritySettings.iState = EMMFStatePlayTone;
762 * Initializes audio device and start playing a dual tone.
763 * The tone consists of two sine waves of different frequencies summed together
764 * Dual Tone is played with specified frequencies and for specified duration.
766 * @param "aFrequencyOne"
767 * First frequency of dual tone
769 * @param "aFrequencyTwo"
770 * Second frequency of dual tone
773 * The period over which the tone will be played. A zero value causes
774 * the no tone to be played (Verify this with test app).
776 void CMMFDevSoundSvrImp::PlayDualToneL(TInt aFrequencyOne, TInt aFrequencyTwo, const TTimeIntervalMicroSeconds& aDuration)
778 if (!iDevSoundObserver)
780 User::Leave(KErrNotReady);
783 // Check whether frequencies and duration are valid or not
785 if ((aFrequencyOne<0) || (aFrequencyTwo<0) || (aDuration.Int64() < zeroInt64))
787 iDevSoundObserver->ToneFinished(KErrArgument);
792 iDualToneGen.SetFrequencyAndDuration(aFrequencyOne, aFrequencyTwo, aDuration);
795 iAudioPolicyPrioritySettings.iState = EMMFStatePlayDualTone;
801 * Initializes audio device and start playing DTMF string aDTMFString.
805 * @param "TDesC& aDTMFString"
806 * DTMF sequence in a descriptor.
809 void CMMFDevSoundSvrImp::PlayDTMFStringL(const TDesC& aDTMFString)
811 if (!iDevSoundObserver)
812 User::Leave(KErrNotReady);
814 if (iMode!= EMMFDevSoundStateTonePlaying)
815 User::Leave(KErrNotSupported); //tone playing only supported in tone play state
817 iDTMFGen.SetString(aDTMFString);
820 iAudioPolicyPrioritySettings.iState = EMMFStatePlayDTMFString;
826 * Initializes audio device and start playing tone sequence.
830 * @param "TDesC8& aData"
831 * Tone sequence in a descriptor.
834 void CMMFDevSoundSvrImp::PlayToneSequenceL(const TDesC8& aData)
836 if (!iDevSoundObserver)
837 User::Leave(KErrNotReady);
839 if (iMode!= EMMFDevSoundStateTonePlaying)
840 User::Leave(KErrNotSupported); //tone playing only supported in tone play state
842 // Check whether the sequence is valid or not
843 if (!iDevSoundUtil->RecognizeSequence(aData))
844 User::Leave(KErrCorrupt);
846 iSequenceGen.SetSequenceData(aData);
849 iAudioPolicyPrioritySettings.iState = EMMFStatePlayToneSequence;
855 * Initializes audio device and start playing the specified pre-defined tone
860 * @param "TInt aSequenceNumber"
861 * The index identifying the specific pre-defined tone sequence. Index
862 * values are relative to zero.
863 * This can be any value from zero to the value returned by a call to
864 * FixedSequenceCount() - 1.
865 * The function raises a panic if sequence number is not within this
868 * @see FixesSequenceCount()
871 void CMMFDevSoundSvrImp::PlayFixedSequenceL(TInt aSequenceNumber)
873 if (!iDevSoundObserver)
874 User::Leave(KErrNotReady);
876 if (iMode!= EMMFDevSoundStateTonePlaying)
877 User::Leave(KErrNotSupported); //tone playing only supported in tone play state
879 ASSERT((aSequenceNumber >= 0)&&(aSequenceNumber < iFixedSequences->Count()));
881 iFixedSequence.Set(iFixedSequences->MdcaPoint(aSequenceNumber));
882 iSequenceGen.SetSequenceData(iFixedSequence);
885 iAudioPolicyPrioritySettings.iState = EMMFStatePlayToneSequence;
891 * Defines the duration of tone on, tone off and tone pause to be used during the
892 * DTMF tone playback operation.
894 * Supported only during tone playing.
896 * @param "TTimeIntervalMicroSeconds32& aToneOnLength"
897 * The period over which the tone will be played. If this is set to
898 * zero, then the tone is not played.
900 * @param "TTimeIntervalMicroSeconds32& aToneOffLength"
901 * The period over which the no tone will be played.
903 * @param "TTimeIntervalMicroSeconds32& aPauseLength"
904 * The period over which the tone playing will be paused.
907 void CMMFDevSoundSvrImp::SetDTMFLengths(TTimeIntervalMicroSeconds32& aToneOnLength,
908 TTimeIntervalMicroSeconds32& aToneOffLength,
909 TTimeIntervalMicroSeconds32& aPauseLength)
912 if(aToneOnLength.Int() < KMdaInfiniteDurationDTMFToneOnLength)
913 aToneOnLength = TTimeIntervalMicroSeconds32(0);
914 if(aToneOffLength.Int() < 0)
915 aToneOffLength = TTimeIntervalMicroSeconds32(0);
916 if(aPauseLength.Int() < 0)
917 aPauseLength = TTimeIntervalMicroSeconds32(0);
919 iDTMFGen.SetToneDurations(aToneOnLength,aToneOffLength,aPauseLength);
924 * Defines the period over which the volume level is to rise smoothly from
925 * nothing to the normal volume level.
927 * @param "TTimeIntervalMicroSeconds& aRampDuration"
928 * The period over which the volume is to rise. A zero value causes
929 * the tone sample to be played at the normal level for the full
930 * duration of the playback. A value, which is longer than the duration
931 * of the tone sample, that the sample never reaches its normal
936 void CMMFDevSoundSvrImp::SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)
938 // save ramp duration for tone generator
939 iRampDuration = aRampDuration;
941 SetDeviceVolumeRamp(iRampDuration);
945 * Sets volume ramp on HwDevice.
947 TInt CMMFDevSoundSvrImp::SetDeviceVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)
949 TInt error = KErrNone;
950 if (iPlayCustomInterface)
951 iPlayCustomInterface->SetVolumeRamp(aRampDuration);
953 error = KErrNotReady;
960 void CMMFDevSoundSvrImp::GetSupportedInputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& /*aPrioritySettings*/) const
962 //aPrioritySettings not used on ref DevSound
963 //search for playing datatypes
964 iDevSoundUtil->SeekHwDevicePluginsL(aSupportedDataTypes, EMMFStatePlaying);
965 #ifdef SYMBIAN_MULTIMEDIA_CODEC_API
966 // append list of codec plugins
967 iDevSoundUtil->SeekCodecPluginsL(aSupportedDataTypes, EMMFStatePlaying, ETrue);
968 #endif // SYMBIAN_MULTIMEDIA_CODEC_API
974 void CMMFDevSoundSvrImp::GetSupportedOutputDataTypesL(RArray<TFourCC>& aSupportedDataTypes, const TMMFPrioritySettings& /*aPrioritySettings*/) const
976 //aPrioritySettings not used on ref DevSound
977 // search for recording datatypes
978 iDevSoundUtil->SeekHwDevicePluginsL(aSupportedDataTypes, EMMFStateRecording);
979 #ifdef SYMBIAN_MULTIMEDIA_CODEC_API
980 // append list of codec plugins
981 iDevSoundUtil->SeekCodecPluginsL(aSupportedDataTypes, EMMFStateRecording, ETrue);
982 #endif // SYMBIAN_MULTIMEDIA_CODEC_API
985 TInt CMMFDevSoundSvrImp::RegisterAsClient(TUid aEventType, const TDesC8& aNotificationRegistrationData)
987 return iAudioPolicyProxy->RequestResourceNotification(aEventType,aNotificationRegistrationData);
990 TInt CMMFDevSoundSvrImp::CancelRegisterAsClient(TUid aEventType)
992 return iAudioPolicyProxy->CancelRequestResourceNotification(aEventType);
995 TInt CMMFDevSoundSvrImp::GetResourceNotificationData(TUid aEventType, TDes8& aNotificationData)
998 err = iAudioPolicyProxy->IsRegisteredResourceNotification(aEventType);
1001 TMMFTimeIntervalMicroSecondsPckg pckg = TTimeIntervalMicroSeconds(SamplesPlayed());
1002 aNotificationData.Copy(pckg);
1007 TInt CMMFDevSoundSvrImp::WillResumePlay()
1009 return iAudioPolicyProxy->StopNotification();
1012 TInt CMMFDevSoundSvrImp::EmptyBuffers()
1014 TInt err = KErrNone;
1015 if (iMode != EMMFStatePlaying)
1017 return KErrNotSupported;
1021 return KErrNotReady;
1023 MEmptyBuffersCustomInterface* emptybuffers = reinterpret_cast<MEmptyBuffersCustomInterface*>(iCMMFHwDevice->CustomInterface(KEmptyBuffersCustomInterfaceTypeUid));
1026 err = emptybuffers->EmptyBuffers();
1030 err = KErrNotSupported;
1035 TInt CMMFDevSoundSvrImp::GetTimePlayed(TTimeIntervalMicroSeconds& aTime)
1037 TInt err = KErrNone;
1038 TTimeIntervalMicroSeconds time(0);
1041 if(!iTimePlayedCustomInterface)
1043 iTimePlayedCustomInterface = reinterpret_cast<MTimePlayedCustomInterface*>(iCMMFHwDevice->CustomInterface(KTimePlayedCustomInterfaceTypeUid));
1044 if(iTimePlayedCustomInterface == NULL)
1046 return KErrNotSupported;
1049 err = iTimePlayedCustomInterface->GetTimePlayed(time);
1050 if(err == KErrNone && time.Int64() > 0)
1052 iTimePlayed = time.Int64();
1055 aTime = iTimePlayed.Int64();
1059 /********************************************************************************
1060 * Implementations of Non Exported public functions begins here *
1061 ********************************************************************************/
1064 // Audio Policy specific implementation begins here //
1069 * Called by Audio Policy Server when a request to play is approved by the
1070 * Audio Policy Server.
1072 * Leaves on failure??.
1075 void CMMFDevSoundSvrImp::StartPlayDataL()
1077 ASSERT(iMode== EMMFDevSoundStatePlaying);
1078 if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
1084 TInt error = KErrNone;
1088 UpdatePolicyState(EMMFStatePlayData);
1089 // Set volume and play format values
1090 error = SetPlayFormat(iPlayFormat);
1091 if (error == KErrNone)
1092 error = SetDeviceVolume(iVolume);
1093 if (error == KErrNone)
1094 error = SetDeviceVolumeRamp(iRampDuration);
1096 // Initialize attribute values
1097 iPlayedBytesCount = 0;
1099 iLastBufferReceived = EFalse;
1102 if (error == KErrNone)
1103 error = iCMMFHwDevice->Start(EDevDecode, EDevOutFlow);
1106 error = KErrNotReady;
1108 if (error != KErrNone)
1117 * Called by Audio Policy Server when a request to record is approved by the
1118 * Audio Policy Server.
1120 * Leaves on failure.
1123 void CMMFDevSoundSvrImp::StartRecordDataL()
1125 ASSERT(iMode== EMMFDevSoundStateRecording);
1126 if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
1134 UpdatePolicyState(EMMFStateRecordData);
1135 TInt error = KErrNone;
1136 error = SetRecordFormat(iRecordFormat);
1137 if (error != KErrNone)
1143 error = SetDeviceRecordLevel(iGain);
1144 if (error != KErrNone)
1150 error = iCMMFHwDevice->Start(EDevEncode, EDevInFlow);
1151 if (iHwDeviceBuffer)
1152 iHwDeviceBuffer->SetLastBuffer(EFalse);
1154 if (error != KErrNone)
1161 iDevSoundObserver->RecordError(KErrNotReady);
1166 * Called by Audio Policy Server when a request to play tone is approved by
1167 * the Audio Policy Server.
1169 * Leaves on failure.
1172 void CMMFDevSoundSvrImp::StartPlayToneL()
1174 ASSERT(iMode == EMMFDevSoundStateTonePlaying);
1175 if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
1183 UpdatePolicyState(EMMFStatePlayTone);
1184 TInt error = KErrNone;
1185 // Set volume and play format values
1186 error = SetPlayFormat(iPlayFormat);
1187 if (error != KErrNone)
1193 if (iHwDeviceID.iUid == KMmfUidHwDevicePCM16ToPCM16)
1194 error = SetDeviceVolume(iVolume);
1196 error = KErrGeneral;//hw device should always be pcm16 for tone
1198 // turn off volume ramping - this is done in software below
1199 if (error == KErrNone)
1200 error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
1202 if (error != KErrNone)
1209 // Initialize attribute values
1210 iPlayedBytesCount = 0;
1212 // Configure tone generator
1214 iPlayFormat().iRate,
1215 iPlayFormat().iChannels,
1217 I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
1218 I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
1221 iCurrentGenerator = &iToneGen;
1227 iDevSoundObserver->ToneFinished(KErrNotReady);
1232 * Called by Audio Policy Server when a request to play a dual tone is approved by
1233 * the Audio Policy Server.
1236 void CMMFDevSoundSvrImp::StartPlayDualToneL()
1238 ASSERT(iMode == EMMFDevSoundStateTonePlaying);
1239 if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
1247 UpdatePolicyState(EMMFStatePlayDualTone);
1248 TInt error = KErrNone;
1249 // Set volume and play format values
1250 error = SetPlayFormat(iPlayFormat);
1251 if (error != KErrNone)
1256 if (iHwDeviceID.iUid == KMmfUidHwDevicePCM16ToPCM16)
1257 error = SetDeviceVolume(iVolume);
1259 error = KErrGeneral;//hw device should always be pcm16 for tone
1261 // turn off volume ramping - this is done in software below
1262 if (error == KErrNone)
1263 error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
1265 if (error != KErrNone)
1272 // Initialize attribute values
1273 iPlayedBytesCount = 0;
1275 // Configure dual tone generator
1276 iDualToneGen.Configure(
1277 iPlayFormat().iRate,
1278 iPlayFormat().iChannels,
1280 I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/KOneMillionMicroSeconds),
1281 I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/KOneMillionMicroSeconds)
1284 iCurrentGenerator = &iDualToneGen;
1290 iDevSoundObserver->ToneFinished(KErrNotReady);
1295 * Called by Audio Policy Server when a request to play DTMF String is approved
1296 * by the Audio Policy Server.
1298 * Leaves on failure.
1301 void CMMFDevSoundSvrImp::StartPlayDTMFStringL()
1303 ASSERT(iMode == EMMFDevSoundStateTonePlaying);
1304 if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
1312 UpdatePolicyState(EMMFStatePlayDTMFString);
1313 TInt error = KErrNone;
1314 // Set volume and play format values
1315 error = SetPlayFormat(iPlayFormat);
1316 if (error != KErrNone)
1322 error = SetDeviceVolume(iVolume);
1324 // turn off volume ramping - this is done in software below
1325 if (error == KErrNone)
1326 error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
1328 if (error != KErrNone)
1334 // Initialize attribute values
1335 iPlayedBytesCount = 0;
1338 iPlayFormat().iRate,
1339 iPlayFormat().iChannels,
1341 I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
1342 I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
1345 iCurrentGenerator = &iDTMFGen;
1348 //need to trap this as we can leave with KErrUnderflow
1349 //if there was no data to play - the error has already
1350 //been sent to the observer and we don't want to call RunError
1351 TRAP(error,DoPlayL());
1352 if ((error != KErrUnderflow)&&(error != KErrNone))
1358 iDevSoundObserver->ToneFinished(KErrNotReady);
1363 * Called by Audio Policy Server when a request to play tone sequence is
1364 * approved by the Audio Policy Server.
1366 * Leaves on failure.
1369 void CMMFDevSoundSvrImp::StartPlayToneSequenceL()
1371 ASSERT(iMode == EMMFDevSoundStateTonePlaying);
1372 if(iAudioPolicyPrioritySettings.iState == EMMFStateStopped)
1380 UpdatePolicyState(EMMFStatePlayToneSequence);
1381 TInt error = KErrNone;
1382 // Set volume and play format values
1383 if (iHwDeviceID.iUid == KMmfUidHwDevicePCM16ToPCM16)
1384 error = SetPlayFormat(iPlayFormat);
1385 else error = KErrGeneral;//hw device should always be pcm16 for tone
1386 if (error != KErrNone)
1392 if (iHwDeviceID.iUid == KMmfUidHwDevicePCM16ToPCM16)
1393 error = SetDeviceVolume(iVolume);
1395 error = KErrGeneral;//hw device should always be pcm16 for tone
1397 // turn off volume ramping - this is done in software below
1398 if (error == KErrNone)
1399 error = SetDeviceVolumeRamp(TTimeIntervalMicroSeconds(0));
1401 if (error != KErrNone)
1407 // Initialize attribute values
1408 iPlayedBytesCount = 0;
1410 iSequenceGen.Configure(
1411 iPlayFormat().iRate,
1412 iPlayFormat().iChannels,
1414 I64LOW((iRepeatTrailingSilence.Int64()*iPlayFormat().iRate)/1000000),
1415 I64LOW((iRampDuration.Int64()*iPlayFormat().iRate)/1000000)
1418 iCurrentGenerator = &iSequenceGen;
1424 iDevSoundObserver->ToneFinished(KErrNotReady);
1429 * Called by Audio Policy Server when the current DevSound instance looses the
1430 * policy because of another instance with a higher priority wants the device.
1433 void CMMFDevSoundSvrImp::SendEventToClient(const TMMFEvent& aEvent)
1435 if (aEvent.iErrorCode != KErrNone)
1437 iHasPolicy = EFalse;
1438 if (iMode == EMMFDevSoundStatePlaying)
1440 UpdateBytesPlayed();
1441 iDevSoundObserver->PlayError(aEvent.iErrorCode);
1442 UpdatePolicyState(EMMFStateStopped);
1444 else if (iMode == EMMFDevSoundStateRecording)
1446 iDevSoundObserver->RecordError(aEvent.iErrorCode);
1447 UpdatePolicyState(EMMFStateStopped);
1449 else if (iMode == EMMFDevSoundStateTonePlaying)
1451 iDevSoundObserver->ToneFinished(aEvent.iErrorCode);
1453 iCMMFHwDevice->Stop();//unloads sound device
1454 // Have audio Policy launch higher priority request
1455 iAudioPolicyProxy->LaunchRequests();
1460 iDevSoundObserver->SendEventToClient(aEvent);
1467 * Sets volume on HwDevice.
1470 * Error value returned by HwDevice.
1473 TInt CMMFDevSoundSvrImp::SetDeviceVolume(TInt aVolume)
1475 TInt error = KErrNone;
1476 if (iPlayCustomInterface)
1477 iPlayCustomInterface->SetVolume(aVolume);
1478 else error = KErrNotReady;
1484 * Sets PlayFormat on HwDevice.
1488 * Error value returned by HwDevice.
1491 TInt CMMFDevSoundSvrImp::SetPlayFormat(RMdaDevSound::TCurrentSoundFormatBuf& aPlayFormat)
1493 TInt error = KErrNone;
1496 TTaskConfig taskConfig;
1497 taskConfig.iUid = KUidRefDevSoundTaskConfig;
1498 taskConfig.iRate = aPlayFormat().iRate;
1500 if (aPlayFormat().iChannels == 1)
1502 taskConfig.iStereoMode = ETaskMono;
1504 else if (aPlayFormat().iChannels == 2)
1506 taskConfig.iStereoMode = ETaskInterleaved;
1510 return KErrArgument;
1513 error = iCMMFHwDevice->SetConfig(taskConfig);
1514 //note the iEncoding and iBufferSize are already determined by the
1515 //CMMFHwDevice plugin and so are not set.
1519 error = KErrNotReady;
1527 * Sets RecordFormat on HwDevice.
1531 * Error value returned by HwDevice.
1534 TInt CMMFDevSoundSvrImp::SetRecordFormat(RMdaDevSound::TCurrentSoundFormatBuf& aRecordFormat)
1536 TInt error = KErrNone;
1539 TTaskConfig taskConfig;
1540 taskConfig.iUid = KUidRefDevSoundTaskConfig;
1541 taskConfig.iRate = aRecordFormat().iRate;
1543 if (aRecordFormat().iChannels == 1)
1545 taskConfig.iStereoMode = ETaskMono;
1547 else if (aRecordFormat().iChannels == 2)
1549 taskConfig.iStereoMode = ETaskInterleaved;
1553 return KErrArgument;
1556 error = iCMMFHwDevice->SetConfig(taskConfig);
1557 //note the iEncoding and iBufferSize are already determined by the
1558 //CMMFHwDevice plugin and so are not set.
1562 error = KErrNotReady;
1570 * Sets record level on HwDevice.
1574 * Error value returned by HwDevice.
1577 TInt CMMFDevSoundSvrImp::SetDeviceRecordLevel(TInt aGain)
1579 TInt error = KErrNone;
1580 if (iRecordCustomInterface)
1581 iRecordCustomInterface->SetGain(aGain);
1582 else error = KErrNotReady;
1590 * MMMFHwDeviceObserver mixin implementation.
1592 * The CMMFHwDevice implementation object calls this method during decoding
1593 * (playing), when it needs the encoded data in the buffer
1597 * Error code. KErrNone if success.
1600 TInt CMMFDevSoundSvrImp::FillThisHwBuffer(CMMFBuffer& aHwDataBuffer)
1602 TInt err = KErrNone;
1603 // Keep a reference to this Hw data Buffer. We need to send the
1604 // reference back to HwDevice implementation
1605 iHwDeviceBuffer = static_cast<CMMFDataBuffer*> (&aHwDataBuffer);
1606 // Set the request length, From HwDevice this comes with buffer
1608 TInt len = iHwDeviceBuffer->Data().MaxLength();
1609 // Ignore error. since buffer size = Buffer Length
1610 TRAP(err, iHwDeviceBuffer->SetRequestSizeL(len));
1612 if (iMode== EMMFDevSoundStatePlaying) // Get Data from Observer
1614 if (iLastBufferReceived)
1616 iHwDeviceBuffer->Data().SetLength(0);
1617 // Pass the buffer to the he device
1618 err = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
1621 // Pass the buffer to the observer
1622 iDevSoundObserver->BufferToBeFilled(&aHwDataBuffer);
1624 else if (iMode == EMMFDevSoundStateTonePlaying)
1626 // Hw device will call this method right after its Start was called.
1627 // When it calls this for the first time it hasn't played one single
1628 // buffer yet so check that.
1629 // In this case there's no need to set the active buffer as it's already
1630 // waiting to be played.
1631 if (!iFirstCallFromHwDevice)
1632 SetActiveToneBuffer();
1634 // If there is no data in the active buffer, tone play is finished.
1635 // DevSound just have to wait for completion event from audio device.
1636 if (iActiveToneBuffer->Data().Length() > 0)
1638 TInt tonelen = iActiveToneBuffer->Data().Length();
1640 // don't enter more data than can be handled by the receiving buffer
1641 if (len >= tonelen) len = tonelen;
1643 // Copy data from tone buffer to hw device buffer
1644 Mem::Copy((TAny*)(iHwDeviceBuffer->Data().Ptr()), (TAny*)(iActiveToneBuffer->Data().Ptr()), len);
1646 iHwDeviceBuffer->Data().SetLength(len);
1647 // Play data and try to generate next data block
1648 err = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
1649 if (err != KErrNone)
1651 // Check again whether this is the first call from Hw device.
1652 // FillFreeToneBuffer assumes the iActiveToneBuffer has already
1654 if (!iFirstCallFromHwDevice)
1655 err = FillFreeToneBuffer();
1657 iFirstCallFromHwDevice = EFalse; // Reset flag
1660 else if (iFirstCallFromHwDevice)
1661 {//we have no data in the tone buffer and thus have no
1662 //outstanding requests to play
1663 err = KErrUnderflow; //simulate underrun
1667 iHwDeviceBuffer->Data().SetLength(0);
1668 iHwDeviceBuffer->SetLastBuffer(ETrue);
1669 // Send an empty last buffer to HwDevice to get a play completion event with KErrUnderflow
1670 err = iCMMFHwDevice->ThisHwBufferFilled(*iHwDeviceBuffer);
1673 // If there was an error filling the buffer could be corrupt data
1674 // notify the client and stop playing.Set err to KErrNone.
1675 if (err != KErrNone)
1677 Error(err);//Updates Bytes played informs client
1679 iCMMFHwDevice->Stop();//unloads sound device
1686 iCMMFHwDevice->Stop();//unloads sound device
1695 * MMMFHwDeviceObserver mixin implementation.
1697 * The CMMFHwDevice implementation object calls this method during encoding
1698 * (recording), when it fills the buffer aHwDataBuffer with
1702 * Error code. KErrNone if success.
1705 TInt CMMFDevSoundSvrImp::EmptyThisHwBuffer(CMMFBuffer& aHwDataBuffer)
1707 TInt err = KErrNone;
1708 if(iMode== EMMFDevSoundStateRecording)
1710 // Keep a reference to this Hw data Buffer. We need to send the
1711 // reference back to HwDevice implementation
1712 iHwDeviceBuffer = static_cast<CMMFDataBuffer*>(&aHwDataBuffer);
1714 // Set the request length, From HwDevice this comes with buffer
1715 // length. MMF will use RequestSize attribute of the buffer.
1716 // We can avoid this by setting in HwDevice implemenation
1717 TInt len = iHwDeviceBuffer->Data().Length();
1718 TRAP(err, iHwDeviceBuffer->SetRequestSizeL(len));
1720 // if we're pausing (i.e. flushing) set the last buffer flag
1721 // when we get an empty buffer from the logical driver
1722 if(iPaused && iHwDeviceBuffer->Data().Length() == 0)
1726 iHwDeviceBuffer->SetLastBuffer(ETrue);
1728 iDevSoundEventHandler->CancelReceiveEvents();
1732 // Send Data from Observer
1733 iDevSoundObserver->BufferToBeEmptied(iHwDeviceBuffer);
1739 iCMMFHwDevice->Stop();//unloads sound device
1749 * MMMFHwDeviceObserver mixin implementation.
1751 * The CMMFHwDevice implementation object calls this method when a message from
1752 * the hardware device implementation is received.
1755 * Error code. KErrNone if success.
1758 TInt CMMFDevSoundSvrImp::MsgFromHwDevice(TUid aMessageType, const TDesC8& /*aMsg*/)
1760 TInt result = KErrNotSupported;
1761 if (aMessageType.iUid == KMmfHwDeviceObserverUpdateBytesPlayed)
1762 {//this is used by sw codec wrapper to request a bytes played update
1763 //bytes played won't be updated in Stopped() or Error() on sw cdoec wrapper
1764 //as the sound device is closed. Non swCodec wrapper Hw device plugins
1765 //can get there bytes updated on Stopped() and/or Error()
1766 UpdateBytesPlayed();
1774 * MMMFHwDeviceObserver mixin implementation.
1776 * The CMMFHwDevice implementation object calls this method when the current
1777 * encode or decode task is finished or stopped. The policy state is updated
1780 void CMMFDevSoundSvrImp::Stopped()
1782 //for swcodec wrap hw devices bytes played updated in MsgFromHwDevice
1783 //but non Swcodec wrappers hw devices may do it differently
1784 //also don't know if non Swcodec wrap hw device will call Stopped or Error first
1785 UpdateBytesPlayed();
1787 iLastBufferReceived = EFalse;
1788 UpdatePolicyState(EMMFStateCompleted);
1792 * MMMFHwDeviceObserver mixin implementation
1793 * Processes error from hw device
1795 void CMMFDevSoundSvrImp::Error(TInt aError)
1797 if (iMode== EMMFDevSoundStatePlaying)
1799 //for swcodec wrap hw devices bytes played updated in MsgFromHwDevice
1800 //but non Swcodec wrappers hw devices may do it differently
1801 //also don't know if non Swcodec wrap hw device will call Stopped or Error first
1802 UpdateBytesPlayed();
1804 iDevSoundObserver->PlayError(aError);
1805 UpdatePolicyState(EMMFStateStopped);
1807 else if (iMode== EMMFDevSoundStateRecording)
1809 iDevSoundObserver->RecordError(aError);
1810 UpdatePolicyState(EMMFStateStopped);
1812 else if (iMode== EMMFDevSoundStateTonePlaying)
1814 iDevSoundObserver->ToneFinished(aError);
1815 UpdatePolicyState(EMMFStateStopped);
1817 //else can't handle error
1821 /********************************************************************************
1822 * Non Exported public functions ends here *
1823 ********************************************************************************/
1826 /********************************************************************************
1827 * Private functions begins here *
1828 ********************************************************************************/
1830 TInt CMMFDevSoundSvrImp::InitializeFormat(RMdaDevSound::TSoundFormatsSupportedBuf& aSupportedFormat,
1831 RMdaDevSound::TCurrentSoundFormatBuf& aFormat)
1833 // Choose an encoding
1834 TUint32 enc = aSupportedFormat().iEncodings;
1835 // Always defaults to this
1836 if (enc & RMdaDevSound::EMdaSoundEncoding16BitPCM)
1837 aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
1838 else if (enc & RMdaDevSound::EMdaSoundEncoding8BitALaw)
1839 aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitALaw;
1840 else if (enc & RMdaDevSound::EMdaSoundEncoding8BitMuLaw)
1841 aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitMuLaw;
1842 else if (enc & RMdaDevSound::EMdaSoundEncoding8BitPCM)
1843 aFormat().iEncoding = RMdaDevSound::EMdaSoundEncoding8BitPCM;
1845 // default to Monophonic playback:
1846 aFormat().iChannels=1;
1848 // Store the device capabilities (WINS supports from 8000 Hz to 44100 Hz)
1849 if ((aSupportedFormat().iMinRate <= 8000) && (8000 <= aSupportedFormat().iMaxRate))
1850 iDeviceCapabilities.iRate = EMMFSampleRate8000Hz;
1851 if ((aSupportedFormat().iMinRate <= 11025) && (11025 <= aSupportedFormat().iMaxRate))
1852 iDeviceCapabilities.iRate |= EMMFSampleRate11025Hz;
1853 if ((aSupportedFormat().iMinRate <= 12000) && (12000 <= aSupportedFormat().iMaxRate))
1854 iDeviceCapabilities.iRate |= EMMFSampleRate12000Hz;
1855 if ((aSupportedFormat().iMinRate <= 16000) && (16000 <= aSupportedFormat().iMaxRate))
1856 iDeviceCapabilities.iRate |= EMMFSampleRate16000Hz;
1857 if ((aSupportedFormat().iMinRate <= 22050) && (22050 <= aSupportedFormat().iMaxRate))
1858 iDeviceCapabilities.iRate |= EMMFSampleRate22050Hz;
1859 if ((aSupportedFormat().iMinRate <= 24000) && (24000 <= aSupportedFormat().iMaxRate))
1860 iDeviceCapabilities.iRate |= EMMFSampleRate24000Hz;
1861 if ((aSupportedFormat().iMinRate <= 32000) && (32000 <= aSupportedFormat().iMaxRate))
1862 iDeviceCapabilities.iRate |= EMMFSampleRate32000Hz;
1863 if ((aSupportedFormat().iMinRate <= 44100) && (44100 <= aSupportedFormat().iMaxRate))
1864 iDeviceCapabilities.iRate |= EMMFSampleRate44100Hz;
1865 if ((aSupportedFormat().iMinRate <= 48000) && (48000 <= aSupportedFormat().iMaxRate))
1866 iDeviceCapabilities.iRate |= EMMFSampleRate48000Hz;
1867 if ((aSupportedFormat().iMinRate <= 64000) && (64000 <= aSupportedFormat().iMaxRate))
1868 iDeviceCapabilities.iRate |= EMMFSampleRate64000Hz;
1869 if ((aSupportedFormat().iMinRate <= 88200) && (88200 <= aSupportedFormat().iMaxRate))
1870 iDeviceCapabilities.iRate |= EMMFSampleRate88200Hz;
1871 if ((aSupportedFormat().iMinRate <= 96000) && (96000 <= aSupportedFormat().iMaxRate))
1872 iDeviceCapabilities.iRate |= EMMFSampleRate96000Hz;
1874 // Store the encodings supported
1875 iDeviceCapabilities.iEncoding = 0;
1876 if (enc & RMdaDevSound::EMdaSoundEncoding16BitPCM)
1877 iDeviceCapabilities.iEncoding |= EMMFSoundEncoding16BitPCM;
1878 if (enc & RMdaDevSound::EMdaSoundEncoding8BitALaw)
1879 iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitALaw;
1880 if (enc & RMdaDevSound::EMdaSoundEncoding8BitMuLaw)
1881 iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitMuLaw;
1882 if (enc & RMdaDevSound::EMdaSoundEncoding8BitPCM)
1883 iDeviceCapabilities.iEncoding |= EMMFSoundEncoding8BitPCM;
1885 // Mono and Stereo support
1886 if (aSupportedFormat().iChannels == 2)
1887 iDeviceCapabilities.iChannels = EMMFStereo;
1888 iDeviceCapabilities.iChannels |= EMMFMono;
1890 iDeviceCapabilities.iBufferSize = aSupportedFormat().iMaxBufferSize;
1892 iDeviceConfig.iRate = EMMFSampleRate8000Hz;
1893 iDeviceConfig.iEncoding = EMMFSoundEncoding16BitPCM;
1894 iDeviceConfig.iChannels = EMMFMono;
1901 * Makes request to Policy Server (asynchronous call)
1904 void CMMFDevSoundSvrImp::RequestPolicy()
1906 iDevSoundEventHandler->CancelReceiveEvents();
1907 iDevSoundEventHandler->ReceiveEvents();
1908 iAudioPolicyPrioritySettings.iCapabilities = iParent.CheckClientCapabilities();
1909 iAudioPolicyProxy->MakeRequest(iAudioPolicyPrioritySettings);
1914 * Creates buffer and begin playback using the specified tone generator.
1917 void CMMFDevSoundSvrImp::DoPlayL()
1919 // Delete any buffer from previous call and try to create maximum buffer
1920 // size. Double Buffer the Tone data.
1923 delete iToneBuffer1;
1924 iToneBuffer1 = NULL;
1926 //note the tone buffer needs to be the same as the pcm16->pcm16 'null'
1928 // Buffer size = (SampleRate * BytesPerSample * Channels) / 4
1929 TInt useBufferOfSize = ((SamplingFrequency() * 2 * NumberOfChannels())/KDevSoundFramesPerSecond + (KDevSoundDeltaFrameSize-1)) &~ (KDevSoundDeltaFrameSize-1);
1930 //clamp buffer to desired limits
1931 if(useBufferOfSize < KDevSoundMinFrameSize)
1932 useBufferOfSize = KDevSoundMinFrameSize;
1933 else if(useBufferOfSize > KDevSoundMaxFrameSize)
1934 useBufferOfSize = KDevSoundMaxFrameSize;
1936 //clamp buffer to limits of hardware
1937 if(useBufferOfSize < Max(iPlayFormatsSupported().iMinBufferSize, iRecordFormatsSupported().iMinBufferSize))
1938 useBufferOfSize = Max(iPlayFormatsSupported().iMinBufferSize, iRecordFormatsSupported().iMinBufferSize);
1939 else if(useBufferOfSize > Min(iPlayFormatsSupported().iMaxBufferSize, iRecordFormatsSupported().iMaxBufferSize))
1940 useBufferOfSize = Min(iPlayFormatsSupported().iMaxBufferSize, iRecordFormatsSupported().iMaxBufferSize);
1942 iToneBuffer1 = CMMFDataBuffer::NewL(useBufferOfSize);
1943 User::LeaveIfError(iCurrentGenerator->FillBuffer(iToneBuffer1->Data()));
1947 delete iToneBuffer2;
1948 iToneBuffer2 = NULL;
1950 iToneBuffer2 = CMMFDataBuffer::NewL(useBufferOfSize);
1951 User::LeaveIfError(iCurrentGenerator->FillBuffer(iToneBuffer2->Data()));
1953 // Assign active buffer
1954 iActiveToneBuffer = iToneBuffer1;
1956 // Hw device hasn't played anything yet so don't change
1957 // active buffer. This is checked in FillThisHwBuffer.
1958 iFirstCallFromHwDevice = ETrue;
1960 // Start HwDevice to play data
1961 User::LeaveIfError(iCMMFHwDevice->Start(EDevDecode, EDevOutFlow));
1967 * This method assigns the other buffer as active buffer. The tone audio
1968 * generator should fill data in the other buffer by now.
1971 void CMMFDevSoundSvrImp::SetActiveToneBuffer()
1973 if (iActiveToneBuffer == iToneBuffer1)
1974 iActiveToneBuffer = iToneBuffer2;
1975 else if (iActiveToneBuffer == iToneBuffer2)
1976 iActiveToneBuffer = iToneBuffer1;
1981 * This method fills data into the free buffer.
1984 * Error code. KErrNone if success.
1987 TInt CMMFDevSoundSvrImp::FillFreeToneBuffer()
1990 if (iActiveToneBuffer == iToneBuffer1)
1991 err = iCurrentGenerator->FillBuffer(iToneBuffer2->Data());
1992 else if (iActiveToneBuffer == iToneBuffer2)
1993 err = iCurrentGenerator->FillBuffer(iToneBuffer1->Data());
1999 * Updates the policy state based on Audio policy settings of this devsound instance
2002 TInt CMMFDevSoundSvrImp::UpdatePolicyState(TMMFAudioPolicyState aNewState)
2004 iAudioPolicyPrioritySettings.iState = aNewState;
2005 TInt error = iAudioPolicyProxy->UpdateState(iAudioPolicyPrioritySettings);
2006 if ((error == KErrNone) && (aNewState == EMMFStateStopped))
2008 iHasPolicy = EFalse;
2016 * Initializes audio device node by setting volume, and sampling rate.
2019 * Error Code. KErrNone if success.
2022 TInt CMMFDevSoundSvrImp::InitTask()
2024 // No Implementation
2032 * Returns an integer representing Sampling Frequency the device is currently
2036 * Sampling Frequency.
2039 TInt CMMFDevSoundSvrImp::SamplingFrequency()
2041 if(iDeviceConfig.iRate == EMMFSampleRate8000Hz)
2043 else if(iDeviceConfig.iRate == EMMFSampleRate11025Hz)
2045 else if(iDeviceConfig.iRate == EMMFSampleRate12000Hz)
2047 else if(iDeviceConfig.iRate == EMMFSampleRate16000Hz)
2049 else if(iDeviceConfig.iRate == EMMFSampleRate22050Hz)
2051 else if(iDeviceConfig.iRate == EMMFSampleRate24000Hz)
2053 else if(iDeviceConfig.iRate == EMMFSampleRate32000Hz)
2055 else if(iDeviceConfig.iRate == EMMFSampleRate44100Hz)
2057 else if(iDeviceConfig.iRate == EMMFSampleRate48000Hz)
2059 else if(iDeviceConfig.iRate == EMMFSampleRate88200Hz)
2061 else if(iDeviceConfig.iRate == EMMFSampleRate96000Hz)
2064 return 8000; //default
2069 * Returns an integer representing number of channels the device is currently
2073 * Number of audio channels 1 if mono, 2 if stereo.
2076 TInt CMMFDevSoundSvrImp::NumberOfChannels()
2078 if(iDeviceConfig.iChannels == EMMFMono)
2086 * Returns an integer representing number of bytes in each audio sample
2090 * Number of of bytes in each audio sample.
2093 TInt CMMFDevSoundSvrImp::BytesPerAudioSample()
2096 switch (iDeviceConfig.iEncoding)
2098 case EMMFSoundEncoding8BitPCM:
2099 case EMMFSoundEncoding8BitALaw:
2100 case EMMFSoundEncoding8BitMuLaw:
2105 case EMMFSoundEncoding16BitPCM:
2115 /********************************************************************************
2116 * Private functions ends here *
2117 ********************************************************************************/
2120 // CustomCommand* implementation:
2121 // The following come through from the parent object intact - currently it seems
2122 // easier to pass this through with an RMessage, as the result parameter (at least)
2123 // is easier to deal with that way. This might change in the future.
2124 // [TODO - if we extended this to CMMFHwDevice, it might be easier to use some sort
2125 // of TMMFCustomCommandParamBlock throughout, which as well as the uid, in params etc
2126 // by value, also provided a virtual(?) function to set output param. Could then
2127 // use in both plat sec and original code
2129 void CMMFDevSoundSvrImp::DoSyncCustomCommandL(const RMmfIpcMessage& aMessage)
2131 TInt command = aMessage.Int0();
2133 // we don't support any commands at the momment
2134 User::Leave(KErrNotSupported);
2137 void CMMFDevSoundSvrImp::DoSyncCustomCommandResultL(const RMmfIpcMessage& aMessage)
2139 TInt command = aMessage.Int0();
2141 // we don't support any commands at the momment
2142 User::Leave(KErrNotSupported);
2145 void CMMFDevSoundSvrImp::DoAsyncCustomCommandL(const RMmfIpcMessage& aMessage)
2147 TInt command = aMessage.Int0();
2149 // we don't support any commands at the momment
2150 User::Leave(KErrNotSupported); // this will still complete for an async message
2153 void CMMFDevSoundSvrImp::DoAsyncCustomCommandResultL(const RMmfIpcMessage& aMessage)
2155 TInt command = aMessage.Int0();
2157 // we don't support any commands at the moment
2158 User::Leave(KErrNotSupported); // this will still complete for an async message