Update contrib.
1 // Copyright (c) 2007-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.
16 #ifndef MDASOUNDADAPTERBODY_H
17 #define MDASOUNDADAPTERBODY_H
19 #include "mdasoundadapter.h"
20 #include <d32soundsc.h>
25 Panic category and codes for the mdasoundadapter
27 _LIT(KSoundAdapterPanicCategory, "mdasoundadapter");
28 enum TSoundAdapterPanicCodes
31 EPanicPartialBufferConverterNotSupported,
38 //Structure used to map samples per second to the corresponding enums in RSoundSc
39 struct TSampleRateEnumTable
46 //Table that maps given samples per second to the corresponding enums in RSoundSc
47 const TSampleRateEnumTable KRateEnumLookup[] =
49 {48000,ESoundRate48000Hz,KSoundRate48000Hz},
50 {44100,ESoundRate44100Hz,KSoundRate44100Hz},
51 {32000,ESoundRate32000Hz,KSoundRate32000Hz},
52 {24000,ESoundRate24000Hz,KSoundRate24000Hz},
53 {22050,ESoundRate22050Hz,KSoundRate22050Hz},
54 {16000,ESoundRate16000Hz,KSoundRate16000Hz},
55 {12000,ESoundRate12000Hz,KSoundRate12000Hz},
56 {11025,ESoundRate11025Hz,KSoundRate11025Hz},
57 {8000, ESoundRate8000Hz, KSoundRate8000Hz}
59 //Structure used to map linear value of the volume to the decibel value.
60 struct TLinearToDbTable
67 //Table that maps given linear value of volume to the corresponding decibel value.
68 const TLinearToDbTable KLinerToDbConstantLookup[] =
328 // Total Number of sample rates
329 const TUint KNumSampleRates = 9;
330 // Number of shared chunk buffers used for playing
331 // Each buffer is permanently mapped, via an index number, to a particular buffer in the chunk
332 // The esoundsc.ldd can only handle a max of 8 pending play requests, therefore no point in having
333 // more than 8 play buffers...
334 const TUint KPlaySharedChunkBuffers = 8;
335 // Size of RSoundSc play buffers
336 const TUint KPlaySharedChunkBufferSize = 4096;
338 //Number of shared chunk buffers used for recording
339 const TUint KRecordMaxSharedChunkBuffers = 8;
340 // Size of RSoundSc record buffers
341 const TUint KRecordSharedChunkBufferSize = 4096;
343 //Shared chunk driver does not support max. buffer size. 16K is given in order to simulate the old driver behavior.
344 const TUint KMaxBufferSize = 0x4000;
346 class TPlaySharedChunkBufConfig : public TSharedChunkBufConfigBase
349 TInt iBufferOffsetList[KPlaySharedChunkBuffers];
352 class TRecordSharedChunkBufConfig : public TSharedChunkBufConfigBase
355 TInt iBufferOffsetList[KRecordMaxSharedChunkBuffers];
358 class CChannelAndSampleRateConverter; // forward dec
360 GLDEF_C void Panic(TSoundAdapterPanicCodes aPanicCode);//forward declaration
362 // RFifo class which manages a fifo of up to COUNT items of type T
363 template<typename T, TUint32 COUNT> class RFifo
367 : iWriteIndex(0), iReadIndex(0)
369 TBool IsEmpty() const
371 return iWriteIndex == iReadIndex;
375 // Full if writing one more item would make iWriteIndex equal to iReadIndex
376 TUint32 next = NextIndex(iWriteIndex);
377 return next == iReadIndex;
379 /// Push item into FIFO. Does not take ownership. Will PANIC with EFifoFull if full.
380 void Push(const T &aItem)
386 iFifo[iWriteIndex] = aItem;
387 iWriteIndex = NextIndex(iWriteIndex);
389 /// Pop item from FIFO. Will PANIC with EFifoEmpty if empty
396 TUint32 tmp = iReadIndex;
397 iReadIndex = NextIndex(iReadIndex);
401 /// Peek first item from FIFO. Will PANIC with EFifoEmpty if empty
408 return iFifo[iReadIndex];
413 if(iWriteIndex >= iReadIndex)
415 len = iWriteIndex - iReadIndex;
419 len = COUNT+1 - (iReadIndex - iWriteIndex);
424 TUint32 NextIndex(TUint32 aIndex) const
437 //Body class for the adapter
438 NONSHARABLE_CLASS( RMdaDevSound::CBody ): public CBase
441 //This class handles the play/record completions from the new sound driver
442 NONSHARABLE_CLASS( CPlayer ) : public CActive
445 explicit CPlayer(TInt aPriority, RMdaDevSound::CBody& aParent, TInt aIndex);
448 TInt RunError(TInt aError);
450 void PlayData(TUint aChunkOffset, TInt aLength);
452 TUint GetPlayerIndex() const;
455 RMdaDevSound::CBody& iParent;
456 const TUint iIndex; // index of this object in parent
463 NONSHARABLE_CLASS( CRecorder ) : public CActive
466 explicit CRecorder(TInt aPriority, RMdaDevSound::CBody& aParent);
469 TInt RunError(TInt aError);
471 void RecordData(TInt& aLength);
474 RMdaDevSound::CBody& iParent;
485 ERecordingPausedInHw,
486 ERecordingPausedInSw,
488 EPlayingPausedInHw, // ie. Play request pending on h/w and paused
489 EPlayingPausedInSw, // ie. Driver not playing or paused
493 NONSHARABLE_CLASS( TState )
496 TState(TStateEnum aState) : iState(aState) {}
497 const TText8 *Name() const;
498 TState &operator=(TStateEnum aNewState);
499 operator TStateEnum() const { return iState; }
507 inline TFormatData():
508 iSampleRate(8000), iRequestedChannels(1) // default
512 CChannelAndSampleRateConverter* iConverter;
515 TInt iRequestedChannels;
516 TInt iActualChannels;
521 static CBody* NewL();
522 TInt Open(TInt aUnit=KNullUnit);
523 TVersion VersionRequired() const;
525 void PlayFormatsSupported(TSoundFormatsSupportedBuf& aFormatsSupported);
526 void GetPlayFormat(TCurrentSoundFormatBuf& aFormat);
527 TInt SetPlayFormat(const TCurrentSoundFormatBuf& aFormat);
529 void SetPlayVolume(TInt aVolume);
530 void SetVolume(TInt aLogarithmicVolume);
531 void CancelPlayData();
532 void RecordFormatsSupported(TSoundFormatsSupportedBuf& aFormatsSupported);
533 void GetRecordFormat(TCurrentSoundFormatBuf& aFormat);
534 TInt SetRecordFormat(const TCurrentSoundFormatBuf& aFormat);
536 void SetRecordLevel(TInt aLevel);
537 void CancelRecordData();
538 void FlushRecordBuffer();
540 void ResetBytesPlayed();
541 void PausePlayBuffer();
542 void ResumePlaying();
543 void PauseRecordBuffer();
544 void ResumeRecording();
545 TInt GetTimePlayed(TTimeIntervalMicroSeconds& aTimePlayed);
548 void PlayData(TRequestStatus& aStatus,const TDesC8& aData);
549 void RecordData(TRequestStatus& aStatus,TDes8& aData);
550 void NotifyRecordError(TRequestStatus& aStatus);
551 void NotifyPlayError(TRequestStatus& aStatus);
552 void CancelNotifyPlayError();
553 void CancelNotifyRecordError();
554 void FlushPlayBuffer();
555 //internal methods added to reduce the code
556 void FormatsSupported(TSoundFormatsSupportedBuf& aFormatsSupported, RSoundSc& aDevice);
557 void GetFormat(TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, const TFormatData &aFormatData);
558 TInt SetFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData);
561 void SoundDeviceError(TInt aError);
562 RSoundSc& PlaySoundDevice();
563 RSoundSc& RecordSoundDevice();
564 const TState &State() const;
565 void BufferFilled(TInt aError);
567 // Called whenever a player becomes inactive.
568 // This includes driver request ok, driver request failed, CPlayer:::RunError invoked.
569 void PlayRequestHasCompleted(CPlayer *aPlayer, TInt aStatus, TBool aDueToCancelCommand);
575 TInt NegotiateFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData);
577 void StartPlayersAndUpdateState();
578 void StartRecordRequest();
580 const char *StateName() const;
582 TBool InRecordMode() const;
583 TBool InPlayMode() const;
585 TUint32 CurrentTimeInMsec() const;
586 TUint64 BytesPlayed64();
589 RSoundSc iPlaySoundDevice;
590 RChunk iPlayChunk;//handle to the shared chunk
591 RSoundSc iRecordSoundDevice;
592 RChunk iRecordChunk;//handle to the shared chunk
596 TPlaySharedChunkBufConfig iPlayBufferConfig;
597 TInt iDeviceBufferLength;
599 //Stores the status of CDataPathPlayer
600 TRequestStatus* iClientPlayStatus;
601 TPtrC8 iClientPlayData;
602 //Stores the status of CSoundDevPlayErrorReceiver
603 TRequestStatus* iClientPlayErrorStatus;
604 RBuf8 iConvertedPlayData;
605 RBuf8 iSavedTrailingData;
607 CPlayer* iPlayers[KPlaySharedChunkBuffers];
608 RFifo<CPlayer *, KPlaySharedChunkBuffers> iFreePlayers;
609 RFifo<TUint32, KPlaySharedChunkBuffers> iActivePlayRequestSizes;
611 TInt iRequestMinSize;
612 TUint iRequestMinMask;
614 //Recording Properties
615 TRecordSharedChunkBufConfig iRecordBufferConfig;
619 //Stores the status of CDataPathRecorder
620 TRequestStatus* iClientRecordStatus;
621 //Stores the status of CSoundDevRecordErrorReceiver
622 TRequestStatus* iClientRecordErrorStatus;
623 TDes8* iClientRecordData;//stores the data pointer from datapath recorder
624 RBuf8 iBufferedRecordData; // Used if RSoundSc returns more data than current client request requires.
626 CRecorder* iRecorder; // We only need one recorder. The driver will buffer data for us.
628 TBool iUnderFlowReportedSinceLastPlayOrRecordRequest;
630 TUint64 iBytesPlayed;
631 TUint32 iNTickPeriodInUsec;
632 TUint32 iStartTime; // Time when previous driver PlayData completed (or first was issued) in msec
633 TUint32 iPauseTime; // Time when pause started in msec
634 TUint64 iPausedBytesPlayed;
636 TFormatData iPlayFormatData;
637 TFormatData iRecordFormatData;