mmdevicefw/mdf/src/audio/mdasoundadapter/mdasoundadapterbody.h
branchRCL_3
changeset 50 948c7f65f6d4
parent 49 735348f59235
equal deleted inserted replaced
49:735348f59235 50:948c7f65f6d4
    27 _LIT(KSoundAdapterPanicCategory, "mdasoundadapter");
    27 _LIT(KSoundAdapterPanicCategory, "mdasoundadapter");
    28 enum TSoundAdapterPanicCodes
    28 enum TSoundAdapterPanicCodes
    29 	{
    29 	{
    30 	EDeviceNotOpened,
    30 	EDeviceNotOpened,
    31 	EPanicPartialBufferConverterNotSupported,
    31 	EPanicPartialBufferConverterNotSupported,
    32 	EBadState,
       
    33 	ENoClientPlayRequest,
       
    34 	EFifoEmpty,
       
    35 	EFifoFull
       
    36 	};
    32 	};
    37 	
    33 	
    38 //Structure used to map samples per second to the corresponding enums in RSoundSc
    34 //Structure used to map samples per second to the corresponding enums in RSoundSc
    39 struct TSampleRateEnumTable
    35 struct TSampleRateEnumTable
    40   	{
    36   	{
   323 							{253,254},
   319 							{253,254},
   324 							{254,254},
   320 							{254,254},
   325 							{255,254}
   321 							{255,254}
   326 						};
   322 						};
   327 
   323 
   328 // Total Number of sample rates
   324 //Total Number of sample rates
   329 const TUint KNumSampleRates = 9;
   325 const TInt KNumSampleRates = 9;
   330 // Number of shared chunk buffers used for playing
   326 //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
   327 const TInt KPlayMaxSharedChunkBuffers = 2;
   332 // The esoundsc.ldd can only handle a max of 8 pending play requests, therefore no point in having
   328 const TInt KPlayMaxSharedChunkBuffersMask = KPlayMaxSharedChunkBuffers-1; // use for % KPlayMaxSharedChunkBuffers
   333 // more than 8 play buffers...
       
   334 const TUint KPlaySharedChunkBuffers = 8;
       
   335 // Size of RSoundSc play buffers
       
   336 const TUint KPlaySharedChunkBufferSize = 4096;
       
   337 
       
   338 //Number of shared chunk buffers used for recording
   329 //Number of shared chunk buffers used for recording
   339 const TUint KRecordMaxSharedChunkBuffers = 8;
   330 const TInt KRecordMaxSharedChunkBuffers = 3;
   340 // Size of RSoundSc record buffers
   331 //we need to two players for playing and one is sufficient for recording
   341 const TUint KRecordSharedChunkBufferSize = 4096;
   332 const TInt KNumPlayers = 2;
   342 
   333 const TInt KNumPlayersMask = KNumPlayers-1; // & KNumPlayersMask is equiv to % KNumPlayers
   343 //Shared chunk driver does not support max. buffer size. 16K is given in order to simulate the old driver behavior.
   334 //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;
   335 const TInt KMaxBufferSize = 0x4000;
   345 
   336 
   346 class TPlaySharedChunkBufConfig : public TSharedChunkBufConfigBase
   337 class TPlaySharedChunkBufConfig : public TSharedChunkBufConfigBase
   347 	{
   338 	{
   348 public:
   339 public:
   349 	TInt iBufferOffsetList[KPlaySharedChunkBuffers];
   340 	TInt iBufferOffsetList[KPlayMaxSharedChunkBuffers];
   350 	};
   341 	};
   351 
   342 
   352 class TRecordSharedChunkBufConfig : public TSharedChunkBufConfigBase
   343 class TRecordSharedChunkBufConfig : public TSharedChunkBufConfigBase
   353 	{
   344 	{
   354 public:
   345 public:
   355 	TInt iBufferOffsetList[KRecordMaxSharedChunkBuffers];
   346 	TInt iBufferOffsetList[KRecordMaxSharedChunkBuffers];
   356 	};
   347 	};
   357 	
   348 	
   358 class CChannelAndSampleRateConverter; // forward dec
   349 class CChannelAndSampleRateConverter; // forward dec
   359 
       
   360 GLDEF_C void Panic(TSoundAdapterPanicCodes aPanicCode);//forward declaration
       
   361 
       
   362 // RFifo class which manages a fifo of up to COUNT items of type T
       
   363 template<typename T, TUint32 COUNT> class RFifo
       
   364 	{
       
   365 public:
       
   366 	RFifo()
       
   367 		: iWriteIndex(0), iReadIndex(0)
       
   368 		{}
       
   369 	TBool IsEmpty() const
       
   370 		{
       
   371 		return iWriteIndex == iReadIndex;
       
   372 		}
       
   373 	TBool IsFull() const
       
   374 		{
       
   375 		// Full if writing one more item would make iWriteIndex equal to iReadIndex
       
   376 		TUint32 next = NextIndex(iWriteIndex);
       
   377 		return next == iReadIndex;
       
   378 		}
       
   379 	/// Push item into FIFO. Does not take ownership. Will PANIC with EFifoFull if full.
       
   380 	void Push(const T &aItem)
       
   381 		{
       
   382 		if(IsFull())
       
   383 			{
       
   384 			Panic(EFifoFull);
       
   385 			}
       
   386 		iFifo[iWriteIndex] = aItem;
       
   387 		iWriteIndex = NextIndex(iWriteIndex);
       
   388 		}
       
   389     /// Pop item from FIFO. Will PANIC with EFifoEmpty if empty 
       
   390 	T Pop()
       
   391 		{
       
   392 		if(IsEmpty())
       
   393 			{
       
   394 			Panic(EFifoEmpty);
       
   395 			}
       
   396 		TUint32 tmp = iReadIndex;
       
   397 		iReadIndex = NextIndex(iReadIndex);
       
   398 		return iFifo[tmp];
       
   399 		}
       
   400 
       
   401     /// Peek first item from FIFO. Will PANIC with EFifoEmpty if empty 
       
   402 	T Peek()
       
   403 		{
       
   404 		if(IsEmpty())
       
   405 			{
       
   406 			Panic(EFifoEmpty);
       
   407 			}
       
   408 		return iFifo[iReadIndex];
       
   409 		}
       
   410 	TUint Length() const
       
   411 		{
       
   412 		TUint len;
       
   413 		if(iWriteIndex >= iReadIndex)
       
   414 			{
       
   415 			len = iWriteIndex - iReadIndex;
       
   416 			}
       
   417 		else
       
   418 			{
       
   419 			len =  COUNT+1 - (iReadIndex - iWriteIndex);
       
   420 			}
       
   421 		return len;
       
   422 		}
       
   423 private:
       
   424 	TUint32 NextIndex(TUint32 aIndex) const
       
   425 		{
       
   426 		++aIndex;
       
   427 		aIndex %= (COUNT+1);
       
   428 		return aIndex;
       
   429 		}
       
   430 	T iFifo[COUNT+1];
       
   431 	TUint32 iWriteIndex;
       
   432 	TUint32 iReadIndex;
       
   433 	};
       
   434 
       
   435 
       
   436 
   350 
   437 //Body class for the adapter
   351 //Body class for the adapter
   438 NONSHARABLE_CLASS( RMdaDevSound::CBody ): public CBase
   352 NONSHARABLE_CLASS( RMdaDevSound::CBody ): public CBase
   439 	{
   353 	{
   440 public:
   354 public:
   445 		explicit CPlayer(TInt aPriority, RMdaDevSound::CBody& aParent, TInt aIndex);
   359 		explicit CPlayer(TInt aPriority, RMdaDevSound::CBody& aParent, TInt aIndex);
   446 		~CPlayer();
   360 		~CPlayer();
   447 		void RunL();
   361 		void RunL();
   448 		TInt RunError(TInt aError);
   362 		TInt RunError(TInt aError);
   449 		void DoCancel();
   363 		void DoCancel();
   450 		void PlayData(TUint aChunkOffset, TInt aLength);
   364 		void RecordData(TInt& aLength);
   451 
   365 		void PlayData(TInt aBufferOffset, TInt aBufferLength);
   452 		TUint GetPlayerIndex() const;
   366 		void Stop();
   453 
   367 		void ResetPlayer();
   454 	private:		
   368 		void PlaySoundDevice();
       
   369 	private:
   455 		RMdaDevSound::CBody& iParent;
   370 		RMdaDevSound::CBody& iParent;
   456 		const TUint iIndex; // index of this object in parent
   371 		const TInt iIndex; // index of this object in parent
   457 		
   372 		TBool iRequestPending;
   458 		TInt iBufferOffset;
   373 		TInt iBufferOffset;
   459 		TInt iBufferLength;
   374 		TInt iBufferLength;
   460 		};
   375 		};
   461 
   376 	
   462 	
   377 	enum TState
   463 	NONSHARABLE_CLASS( CRecorder ) : public CActive
       
   464 		{
       
   465 	public:
       
   466 		explicit CRecorder(TInt aPriority, RMdaDevSound::CBody& aParent);
       
   467 		~CRecorder();
       
   468 		void RunL();
       
   469 		TInt RunError(TInt aError);
       
   470 		void DoCancel();
       
   471 		void RecordData(TInt& aLength);
       
   472 
       
   473 	private:		
       
   474 		RMdaDevSound::CBody& iParent;
       
   475 
       
   476 		TInt iBufferOffset;
       
   477 		TInt iBufferLength;
       
   478 		};
       
   479 	
       
   480 	enum TStateEnum
       
   481 		{
   378 		{
   482 		ENotReady,
   379 		ENotReady,
   483 		EStopped,
   380 		EOpened,
       
   381 		EPlaying,
   484 		ERecording,
   382 		ERecording,
   485 		ERecordingPausedInHw,
   383 		EPlayBuffersFlushed,
   486 		ERecordingPausedInSw,
   384 		EPaused
   487 		EPlaying,
       
   488 		EPlayingPausedInHw, // ie. Play request pending on h/w and paused
       
   489 		EPlayingPausedInSw, // ie. Driver not playing or paused
       
   490 		EPlayingUnderrun
       
   491 		};
       
   492 
       
   493 	NONSHARABLE_CLASS( TState )
       
   494 		{
       
   495 		public:
       
   496 			TState(TStateEnum aState) : iState(aState) {}
       
   497 			const TText8 *Name() const;
       
   498 			TState &operator=(TStateEnum aNewState);
       
   499 			operator TStateEnum() const { return iState; }
       
   500 		private:
       
   501 			TStateEnum iState;
       
   502 		};
   385 		};
   503 		
   386 		
   504 	class TFormatData
   387 	class TFormatData
   505 		{
   388 		{
   506 	public:
   389 	public:
   557 	void GetFormat(TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, const TFormatData &aFormatData);
   440 	void GetFormat(TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, const TFormatData &aFormatData);
   558 	TInt SetFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData);
   441 	TInt SetFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData);
   559 	
   442 	
   560 	//for players
   443 	//for players
   561 	void SoundDeviceError(TInt aError);
   444 	void SoundDeviceError(TInt aError);
       
   445 	void SoundDeviceError(TInt aError, TInt aPlayerIndex);
   562 	RSoundSc& PlaySoundDevice();
   446 	RSoundSc& PlaySoundDevice();
   563 	RSoundSc& RecordSoundDevice();
   447 	RSoundSc& RecordSoundDevice();
   564 	const TState &State() const;
   448 	TState State();
   565 	void BufferFilled(TInt aError);
   449 	void BufferFilled(TInt aError);
   566 
   450 	void BufferEmptied();
   567 	// Called whenever a player becomes inactive.
   451 	void PlayCancelled();
   568 	// This includes driver request ok, driver request failed, CPlayer:::RunError invoked.
   452 	void UpdateTimeAndBytesPlayed();
   569 	void PlayRequestHasCompleted(CPlayer *aPlayer, TInt aStatus, TBool aDueToCancelCommand);
   453 	TBool TimerActive();
       
   454 	TBool FlushCalledDuringPause();
   570 
   455 
   571 private:
   456 private:
   572 	CBody();
   457 	CBody();
   573 	void ConstructL();
   458 	void ConstructL();
   574 	
   459 	
   575 	TInt NegotiateFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData);
   460 	TInt NegotiateFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData);
   576 
       
   577 	void StartPlayersAndUpdateState();
       
   578 	void StartRecordRequest();
       
   579 
       
   580 	const char *StateName() const;
       
   581 
       
   582 	TBool InRecordMode() const;
       
   583 	TBool InPlayMode() const;
       
   584 
       
   585 	TUint32 CurrentTimeInMsec() const;
       
   586 	TUint64 BytesPlayed64();
       
   587 
       
   588 private:
   461 private:
   589 	RSoundSc iPlaySoundDevice;
   462 	RSoundSc iPlaySoundDevice;
   590 	RChunk iPlayChunk;//handle to the shared chunk
       
   591 	RSoundSc iRecordSoundDevice;
   463 	RSoundSc iRecordSoundDevice;
   592 	RChunk iRecordChunk;//handle to the shared chunk
   464 	RChunk iChunk;//handle to the shared chunk
   593 	TState iState;
   465 	TState iState;
   594 
   466 	CPlayer* iPlayers[KNumPlayers];//we need atleast two players for playing and one for recording
       
   467 	
   595 	//Playing Properties
   468 	//Playing Properties
   596 	TPlaySharedChunkBufConfig iPlayBufferConfig;
   469 	TPlaySharedChunkBufConfig iBufferConfig;
       
   470 	TInt iBufferIndex;
       
   471 	TInt iCurrentPlayer;
   597 	TInt iDeviceBufferLength;
   472 	TInt iDeviceBufferLength;
   598 	
       
   599 	//Stores the status of CDataPathPlayer
   473 	//Stores the status of CDataPathPlayer
   600 	TRequestStatus* iClientPlayStatus;
   474 	TRequestStatus* iPlayerStatus;
   601 	TPtrC8 iClientPlayData;
       
   602 	//Stores the status of CSoundDevPlayErrorReceiver
   475 	//Stores the status of CSoundDevPlayErrorReceiver
   603 	TRequestStatus* iClientPlayErrorStatus;
   476 	TRequestStatus* iPlayErrorStatus;
   604 	RBuf8 iConvertedPlayData;
   477 	RBuf8 iBufferRemaining;
   605 	RBuf8 iSavedTrailingData;
   478 	TBool iHaveSecondPhaseData;
   606 
       
   607 	CPlayer* iPlayers[KPlaySharedChunkBuffers];
       
   608 	RFifo<CPlayer *, KPlaySharedChunkBuffers> iFreePlayers;
       
   609 	RFifo<TUint32, KPlaySharedChunkBuffers> iActivePlayRequestSizes;
       
   610 	
       
   611 	TInt iRequestMinSize;
   479 	TInt iRequestMinSize;
   612 	TUint iRequestMinMask;
   480 	TUint iRequestMinMask;
   613 	
   481 	
   614 	//Recording Properties
   482 	//Recording Properties
   615 	TRecordSharedChunkBufConfig iRecordBufferConfig;
   483 	TRecordSharedChunkBufConfig iRecordBufferConfig;
   616 	TInt iBufferOffset;
   484 	TInt iBufferOffset;
   617 	TInt iBufferLength;
   485 	TInt iBufferLength;
   618 
   486 	TPtrC8 iSecondPhaseData;
   619 	//Stores the status of CDataPathRecorder
   487 	//Stores the status of CDataPathRecorder
   620 	TRequestStatus* iClientRecordStatus;
   488 	TRequestStatus* iRecorderStatus;
   621 	//Stores the status of CSoundDevRecordErrorReceiver
   489 	//Stores the status of CSoundDevRecordErrorReceiver
   622 	TRequestStatus* iClientRecordErrorStatus;
   490 	TRequestStatus* iRecordErrorStatus;
   623 	TDes8* iClientRecordData;//stores the data pointer from datapath recorder
   491 	TDes8* iData;//stores the data pointer from datapath recorder
   624 	RBuf8 iBufferedRecordData; // Used if RSoundSc returns more data than current client request requires.
   492 	TInt iBytesPlayed;
   625 
   493 #ifdef SYMBIAN_SOUNDADAPTER_BYTESPLAYED
   626 	CRecorder* iRecorder; // We only need one recorder. The driver will buffer data for us.
   494 	TInt iFCFrequency;
   627 
   495 #endif
   628 	TBool iUnderFlowReportedSinceLastPlayOrRecordRequest;
   496 	TUint32 iStartTime;
   629 	
   497 	TBool iTimerActive;
   630 	TUint64 iBytesPlayed;
   498 	TBool iFlushCalledDuringPause;
   631 	TUint32 iNTickPeriodInUsec;
   499 	TBool iPauseDeviceDriverOnNewData;
   632 	TUint32 iStartTime; // Time when previous driver PlayData completed (or first was issued) in msec
   500 
   633 	TUint32 iPauseTime; // Time when pause started in msec
   501 	TFormatData iPlayData;
   634 	TUint64 iPausedBytesPlayed;
   502 	TFormatData iRecordData;
   635 
       
   636 	TFormatData iPlayFormatData;
       
   637 	TFormatData iRecordFormatData;
       
   638 	};
   503 	};
       
   504 GLDEF_C void Panic(TSoundAdapterPanicCodes aPanicCode);//forward declaration
   639 #endif
   505 #endif