--- a/mmdevicefw/mdf/src/audio/mdasoundadapter/mdasoundadapterbody.h Thu Aug 19 11:23:35 2010 +0300
+++ b/mmdevicefw/mdf/src/audio/mdasoundadapter/mdasoundadapterbody.h Tue Aug 31 16:43:06 2010 +0300
@@ -29,6 +29,10 @@
{
EDeviceNotOpened,
EPanicPartialBufferConverterNotSupported,
+ EBadState,
+ ENoClientPlayRequest,
+ EFifoEmpty,
+ EFifoFull
};
//Structure used to map samples per second to the corresponding enums in RSoundSc
@@ -321,23 +325,28 @@
{255,254}
};
-//Total Number of sample rates
-const TInt KNumSampleRates = 9;
-//Number of shared chunk buffers used for playing
-const TInt KPlayMaxSharedChunkBuffers = 2;
-const TInt KPlayMaxSharedChunkBuffersMask = KPlayMaxSharedChunkBuffers-1; // use for % KPlayMaxSharedChunkBuffers
+// Total Number of sample rates
+const TUint KNumSampleRates = 9;
+// Number of shared chunk buffers used for playing
+// Each buffer is permanently mapped, via an index number, to a particular buffer in the chunk
+// The esoundsc.ldd can only handle a max of 8 pending play requests, therefore no point in having
+// more than 8 play buffers...
+const TUint KPlaySharedChunkBuffers = 8;
+// Size of RSoundSc play buffers
+const TUint KPlaySharedChunkBufferSize = 4096;
+
//Number of shared chunk buffers used for recording
-const TInt KRecordMaxSharedChunkBuffers = 3;
-//we need to two players for playing and one is sufficient for recording
-const TInt KNumPlayers = 2;
-const TInt KNumPlayersMask = KNumPlayers-1; // & KNumPlayersMask is equiv to % KNumPlayers
+const TUint KRecordMaxSharedChunkBuffers = 8;
+// Size of RSoundSc record buffers
+const TUint KRecordSharedChunkBufferSize = 4096;
+
//Shared chunk driver does not support max. buffer size. 16K is given in order to simulate the old driver behavior.
-const TInt KMaxBufferSize = 0x4000;
+const TUint KMaxBufferSize = 0x4000;
class TPlaySharedChunkBufConfig : public TSharedChunkBufConfigBase
{
public:
- TInt iBufferOffsetList[KPlayMaxSharedChunkBuffers];
+ TInt iBufferOffsetList[KPlaySharedChunkBuffers];
};
class TRecordSharedChunkBufConfig : public TSharedChunkBufConfigBase
@@ -348,6 +357,83 @@
class CChannelAndSampleRateConverter; // forward dec
+GLDEF_C void Panic(TSoundAdapterPanicCodes aPanicCode);//forward declaration
+
+// RFifo class which manages a fifo of up to COUNT items of type T
+template<typename T, TUint32 COUNT> class RFifo
+ {
+public:
+ RFifo()
+ : iWriteIndex(0), iReadIndex(0)
+ {}
+ TBool IsEmpty() const
+ {
+ return iWriteIndex == iReadIndex;
+ }
+ TBool IsFull() const
+ {
+ // Full if writing one more item would make iWriteIndex equal to iReadIndex
+ TUint32 next = NextIndex(iWriteIndex);
+ return next == iReadIndex;
+ }
+ /// Push item into FIFO. Does not take ownership. Will PANIC with EFifoFull if full.
+ void Push(const T &aItem)
+ {
+ if(IsFull())
+ {
+ Panic(EFifoFull);
+ }
+ iFifo[iWriteIndex] = aItem;
+ iWriteIndex = NextIndex(iWriteIndex);
+ }
+ /// Pop item from FIFO. Will PANIC with EFifoEmpty if empty
+ T Pop()
+ {
+ if(IsEmpty())
+ {
+ Panic(EFifoEmpty);
+ }
+ TUint32 tmp = iReadIndex;
+ iReadIndex = NextIndex(iReadIndex);
+ return iFifo[tmp];
+ }
+
+ /// Peek first item from FIFO. Will PANIC with EFifoEmpty if empty
+ T Peek()
+ {
+ if(IsEmpty())
+ {
+ Panic(EFifoEmpty);
+ }
+ return iFifo[iReadIndex];
+ }
+ TUint Length() const
+ {
+ TUint len;
+ if(iWriteIndex >= iReadIndex)
+ {
+ len = iWriteIndex - iReadIndex;
+ }
+ else
+ {
+ len = COUNT+1 - (iReadIndex - iWriteIndex);
+ }
+ return len;
+ }
+private:
+ TUint32 NextIndex(TUint32 aIndex) const
+ {
+ ++aIndex;
+ aIndex %= (COUNT+1);
+ return aIndex;
+ }
+ T iFifo[COUNT+1];
+ TUint32 iWriteIndex;
+ TUint32 iReadIndex;
+ };
+
+
+
//Body class for the adapter
NONSHARABLE_CLASS( RMdaDevSound::CBody ): public CBase
{
@@ -361,27 +447,58 @@
void RunL();
TInt RunError(TInt aError);
void DoCancel();
+ void PlayData(TUint aChunkOffset, TInt aLength);
+
+ TUint GetPlayerIndex() const;
+
+ private:
+ RMdaDevSound::CBody& iParent;
+ const TUint iIndex; // index of this object in parent
+
+ TInt iBufferOffset;
+ TInt iBufferLength;
+ };
+
+
+ NONSHARABLE_CLASS( CRecorder ) : public CActive
+ {
+ public:
+ explicit CRecorder(TInt aPriority, RMdaDevSound::CBody& aParent);
+ ~CRecorder();
+ void RunL();
+ TInt RunError(TInt aError);
+ void DoCancel();
void RecordData(TInt& aLength);
- void PlayData(TInt aBufferOffset, TInt aBufferLength);
- void Stop();
- void ResetPlayer();
- void PlaySoundDevice();
- private:
+
+ private:
RMdaDevSound::CBody& iParent;
- const TInt iIndex; // index of this object in parent
- TBool iRequestPending;
+
TInt iBufferOffset;
TInt iBufferLength;
};
- enum TState
+ enum TStateEnum
{
ENotReady,
- EOpened,
- EPlaying,
+ EStopped,
ERecording,
- EPlayBuffersFlushed,
- EPaused
+ ERecordingPausedInHw,
+ ERecordingPausedInSw,
+ EPlaying,
+ EPlayingPausedInHw, // ie. Play request pending on h/w and paused
+ EPlayingPausedInSw, // ie. Driver not playing or paused
+ EPlayingUnderrun
+ };
+
+ NONSHARABLE_CLASS( TState )
+ {
+ public:
+ TState(TStateEnum aState) : iState(aState) {}
+ const TText8 *Name() const;
+ TState &operator=(TStateEnum aNewState);
+ operator TStateEnum() const { return iState; }
+ private:
+ TStateEnum iState;
};
class TFormatData
@@ -442,40 +559,55 @@
//for players
void SoundDeviceError(TInt aError);
- void SoundDeviceError(TInt aError, TInt aPlayerIndex);
RSoundSc& PlaySoundDevice();
RSoundSc& RecordSoundDevice();
- TState State();
+ const TState &State() const;
void BufferFilled(TInt aError);
- void BufferEmptied();
- void PlayCancelled();
- void UpdateTimeAndBytesPlayed();
- TBool TimerActive();
- TBool FlushCalledDuringPause();
+
+ // Called whenever a player becomes inactive.
+ // This includes driver request ok, driver request failed, CPlayer:::RunError invoked.
+ void PlayRequestHasCompleted(CPlayer *aPlayer, TInt aStatus, TBool aDueToCancelCommand);
private:
CBody();
void ConstructL();
TInt NegotiateFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData);
+
+ void StartPlayersAndUpdateState();
+ void StartRecordRequest();
+
+ const char *StateName() const;
+
+ TBool InRecordMode() const;
+ TBool InPlayMode() const;
+
+ TUint32 CurrentTimeInMsec() const;
+ TUint64 BytesPlayed64();
+
private:
RSoundSc iPlaySoundDevice;
+ RChunk iPlayChunk;//handle to the shared chunk
RSoundSc iRecordSoundDevice;
- RChunk iChunk;//handle to the shared chunk
+ RChunk iRecordChunk;//handle to the shared chunk
TState iState;
- CPlayer* iPlayers[KNumPlayers];//we need atleast two players for playing and one for recording
-
+
//Playing Properties
- TPlaySharedChunkBufConfig iBufferConfig;
- TInt iBufferIndex;
- TInt iCurrentPlayer;
+ TPlaySharedChunkBufConfig iPlayBufferConfig;
TInt iDeviceBufferLength;
+
//Stores the status of CDataPathPlayer
- TRequestStatus* iPlayerStatus;
+ TRequestStatus* iClientPlayStatus;
+ TPtrC8 iClientPlayData;
//Stores the status of CSoundDevPlayErrorReceiver
- TRequestStatus* iPlayErrorStatus;
- RBuf8 iBufferRemaining;
- TBool iHaveSecondPhaseData;
+ TRequestStatus* iClientPlayErrorStatus;
+ RBuf8 iConvertedPlayData;
+ RBuf8 iSavedTrailingData;
+
+ CPlayer* iPlayers[KPlaySharedChunkBuffers];
+ RFifo<CPlayer *, KPlaySharedChunkBuffers> iFreePlayers;
+ RFifo<TUint32, KPlaySharedChunkBuffers> iActivePlayRequestSizes;
+
TInt iRequestMinSize;
TUint iRequestMinMask;
@@ -483,23 +615,25 @@
TRecordSharedChunkBufConfig iRecordBufferConfig;
TInt iBufferOffset;
TInt iBufferLength;
- TPtrC8 iSecondPhaseData;
+
//Stores the status of CDataPathRecorder
- TRequestStatus* iRecorderStatus;
+ TRequestStatus* iClientRecordStatus;
//Stores the status of CSoundDevRecordErrorReceiver
- TRequestStatus* iRecordErrorStatus;
- TDes8* iData;//stores the data pointer from datapath recorder
- TInt iBytesPlayed;
-#ifdef SYMBIAN_SOUNDADAPTER_BYTESPLAYED
- TInt iFCFrequency;
+ TRequestStatus* iClientRecordErrorStatus;
+ TDes8* iClientRecordData;//stores the data pointer from datapath recorder
+ RBuf8 iBufferedRecordData; // Used if RSoundSc returns more data than current client request requires.
+
+ CRecorder* iRecorder; // We only need one recorder. The driver will buffer data for us.
+
+ TBool iUnderFlowReportedSinceLastPlayOrRecordRequest;
+
+ TUint64 iBytesPlayed;
+ TUint32 iNTickPeriodInUsec;
+ TUint32 iStartTime; // Time when previous driver PlayData completed (or first was issued) in msec
+ TUint32 iPauseTime; // Time when pause started in msec
+ TUint64 iPausedBytesPlayed;
+
+ TFormatData iPlayFormatData;
+ TFormatData iRecordFormatData;
+ };
#endif
- TUint32 iStartTime;
- TBool iTimerActive;
- TBool iFlushCalledDuringPause;
- TBool iPauseDeviceDriverOnNewData;
-
- TFormatData iPlayData;
- TFormatData iRecordData;
- };
-GLDEF_C void Panic(TSoundAdapterPanicCodes aPanicCode);//forward declaration
-#endif