319 {253,254}, |
323 {253,254}, |
320 {254,254}, |
324 {254,254}, |
321 {255,254} |
325 {255,254} |
322 }; |
326 }; |
323 |
327 |
324 //Total Number of sample rates |
328 // Total Number of sample rates |
325 const TInt KNumSampleRates = 9; |
329 const TUint KNumSampleRates = 9; |
326 //Number of shared chunk buffers used for playing |
330 // Number of shared chunk buffers used for playing |
327 const TInt KPlayMaxSharedChunkBuffers = 2; |
331 // Each buffer is permanently mapped, via an index number, to a particular buffer in the chunk |
328 const TInt KPlayMaxSharedChunkBuffersMask = KPlayMaxSharedChunkBuffers-1; // use for % KPlayMaxSharedChunkBuffers |
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; |
|
337 |
329 //Number of shared chunk buffers used for recording |
338 //Number of shared chunk buffers used for recording |
330 const TInt KRecordMaxSharedChunkBuffers = 3; |
339 const TUint KRecordMaxSharedChunkBuffers = 8; |
331 //we need to two players for playing and one is sufficient for recording |
340 // Size of RSoundSc record buffers |
332 const TInt KNumPlayers = 2; |
341 const TUint KRecordSharedChunkBufferSize = 4096; |
333 const TInt KNumPlayersMask = KNumPlayers-1; // & KNumPlayersMask is equiv to % KNumPlayers |
342 |
334 //Shared chunk driver does not support max. buffer size. 16K is given in order to simulate the old driver behavior. |
343 //Shared chunk driver does not support max. buffer size. 16K is given in order to simulate the old driver behavior. |
335 const TInt KMaxBufferSize = 0x4000; |
344 const TUint KMaxBufferSize = 0x4000; |
336 |
345 |
337 class TPlaySharedChunkBufConfig : public TSharedChunkBufConfigBase |
346 class TPlaySharedChunkBufConfig : public TSharedChunkBufConfigBase |
338 { |
347 { |
339 public: |
348 public: |
340 TInt iBufferOffsetList[KPlayMaxSharedChunkBuffers]; |
349 TInt iBufferOffsetList[KPlaySharedChunkBuffers]; |
341 }; |
350 }; |
342 |
351 |
343 class TRecordSharedChunkBufConfig : public TSharedChunkBufConfigBase |
352 class TRecordSharedChunkBufConfig : public TSharedChunkBufConfigBase |
344 { |
353 { |
345 public: |
354 public: |
346 TInt iBufferOffsetList[KRecordMaxSharedChunkBuffers]; |
355 TInt iBufferOffsetList[KRecordMaxSharedChunkBuffers]; |
347 }; |
356 }; |
348 |
357 |
349 class CChannelAndSampleRateConverter; // forward dec |
358 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 |
350 |
436 |
351 //Body class for the adapter |
437 //Body class for the adapter |
352 NONSHARABLE_CLASS( RMdaDevSound::CBody ): public CBase |
438 NONSHARABLE_CLASS( RMdaDevSound::CBody ): public CBase |
353 { |
439 { |
354 public: |
440 public: |
359 explicit CPlayer(TInt aPriority, RMdaDevSound::CBody& aParent, TInt aIndex); |
445 explicit CPlayer(TInt aPriority, RMdaDevSound::CBody& aParent, TInt aIndex); |
360 ~CPlayer(); |
446 ~CPlayer(); |
361 void RunL(); |
447 void RunL(); |
362 TInt RunError(TInt aError); |
448 TInt RunError(TInt aError); |
363 void DoCancel(); |
449 void DoCancel(); |
364 void RecordData(TInt& aLength); |
450 void PlayData(TUint aChunkOffset, TInt aLength); |
365 void PlayData(TInt aBufferOffset, TInt aBufferLength); |
451 |
366 void Stop(); |
452 TUint GetPlayerIndex() const; |
367 void ResetPlayer(); |
453 |
368 void PlaySoundDevice(); |
454 private: |
369 private: |
|
370 RMdaDevSound::CBody& iParent; |
455 RMdaDevSound::CBody& iParent; |
371 const TInt iIndex; // index of this object in parent |
456 const TUint iIndex; // index of this object in parent |
372 TBool iRequestPending; |
457 |
373 TInt iBufferOffset; |
458 TInt iBufferOffset; |
374 TInt iBufferLength; |
459 TInt iBufferLength; |
375 }; |
460 }; |
376 |
461 |
377 enum TState |
462 |
|
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 |
378 { |
481 { |
379 ENotReady, |
482 ENotReady, |
380 EOpened, |
483 EStopped, |
|
484 ERecording, |
|
485 ERecordingPausedInHw, |
|
486 ERecordingPausedInSw, |
381 EPlaying, |
487 EPlaying, |
382 ERecording, |
488 EPlayingPausedInHw, // ie. Play request pending on h/w and paused |
383 EPlayBuffersFlushed, |
489 EPlayingPausedInSw, // ie. Driver not playing or paused |
384 EPaused |
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; |
385 }; |
502 }; |
386 |
503 |
387 class TFormatData |
504 class TFormatData |
388 { |
505 { |
389 public: |
506 public: |
440 void GetFormat(TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, const TFormatData &aFormatData); |
557 void GetFormat(TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, const TFormatData &aFormatData); |
441 TInt SetFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData); |
558 TInt SetFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData); |
442 |
559 |
443 //for players |
560 //for players |
444 void SoundDeviceError(TInt aError); |
561 void SoundDeviceError(TInt aError); |
445 void SoundDeviceError(TInt aError, TInt aPlayerIndex); |
|
446 RSoundSc& PlaySoundDevice(); |
562 RSoundSc& PlaySoundDevice(); |
447 RSoundSc& RecordSoundDevice(); |
563 RSoundSc& RecordSoundDevice(); |
448 TState State(); |
564 const TState &State() const; |
449 void BufferFilled(TInt aError); |
565 void BufferFilled(TInt aError); |
450 void BufferEmptied(); |
566 |
451 void PlayCancelled(); |
567 // Called whenever a player becomes inactive. |
452 void UpdateTimeAndBytesPlayed(); |
568 // This includes driver request ok, driver request failed, CPlayer:::RunError invoked. |
453 TBool TimerActive(); |
569 void PlayRequestHasCompleted(CPlayer *aPlayer, TInt aStatus, TBool aDueToCancelCommand); |
454 TBool FlushCalledDuringPause(); |
|
455 |
570 |
456 private: |
571 private: |
457 CBody(); |
572 CBody(); |
458 void ConstructL(); |
573 void ConstructL(); |
459 |
574 |
460 TInt NegotiateFormat(const TCurrentSoundFormatBuf& aFormat, RSoundSc& aDevice, TFormatData &aFormatData); |
575 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 |
461 private: |
588 private: |
462 RSoundSc iPlaySoundDevice; |
589 RSoundSc iPlaySoundDevice; |
|
590 RChunk iPlayChunk;//handle to the shared chunk |
463 RSoundSc iRecordSoundDevice; |
591 RSoundSc iRecordSoundDevice; |
464 RChunk iChunk;//handle to the shared chunk |
592 RChunk iRecordChunk;//handle to the shared chunk |
465 TState iState; |
593 TState iState; |
466 CPlayer* iPlayers[KNumPlayers];//we need atleast two players for playing and one for recording |
594 |
467 |
|
468 //Playing Properties |
595 //Playing Properties |
469 TPlaySharedChunkBufConfig iBufferConfig; |
596 TPlaySharedChunkBufConfig iPlayBufferConfig; |
470 TInt iBufferIndex; |
|
471 TInt iCurrentPlayer; |
|
472 TInt iDeviceBufferLength; |
597 TInt iDeviceBufferLength; |
|
598 |
473 //Stores the status of CDataPathPlayer |
599 //Stores the status of CDataPathPlayer |
474 TRequestStatus* iPlayerStatus; |
600 TRequestStatus* iClientPlayStatus; |
|
601 TPtrC8 iClientPlayData; |
475 //Stores the status of CSoundDevPlayErrorReceiver |
602 //Stores the status of CSoundDevPlayErrorReceiver |
476 TRequestStatus* iPlayErrorStatus; |
603 TRequestStatus* iClientPlayErrorStatus; |
477 RBuf8 iBufferRemaining; |
604 RBuf8 iConvertedPlayData; |
478 TBool iHaveSecondPhaseData; |
605 RBuf8 iSavedTrailingData; |
|
606 |
|
607 CPlayer* iPlayers[KPlaySharedChunkBuffers]; |
|
608 RFifo<CPlayer *, KPlaySharedChunkBuffers> iFreePlayers; |
|
609 RFifo<TUint32, KPlaySharedChunkBuffers> iActivePlayRequestSizes; |
|
610 |
479 TInt iRequestMinSize; |
611 TInt iRequestMinSize; |
480 TUint iRequestMinMask; |
612 TUint iRequestMinMask; |
481 |
613 |
482 //Recording Properties |
614 //Recording Properties |
483 TRecordSharedChunkBufConfig iRecordBufferConfig; |
615 TRecordSharedChunkBufConfig iRecordBufferConfig; |
484 TInt iBufferOffset; |
616 TInt iBufferOffset; |
485 TInt iBufferLength; |
617 TInt iBufferLength; |
486 TPtrC8 iSecondPhaseData; |
618 |
487 //Stores the status of CDataPathRecorder |
619 //Stores the status of CDataPathRecorder |
488 TRequestStatus* iRecorderStatus; |
620 TRequestStatus* iClientRecordStatus; |
489 //Stores the status of CSoundDevRecordErrorReceiver |
621 //Stores the status of CSoundDevRecordErrorReceiver |
490 TRequestStatus* iRecordErrorStatus; |
622 TRequestStatus* iClientRecordErrorStatus; |
491 TDes8* iData;//stores the data pointer from datapath recorder |
623 TDes8* iClientRecordData;//stores the data pointer from datapath recorder |
492 TInt iBytesPlayed; |
624 RBuf8 iBufferedRecordData; // Used if RSoundSc returns more data than current client request requires. |
493 #ifdef SYMBIAN_SOUNDADAPTER_BYTESPLAYED |
625 |
494 TInt iFCFrequency; |
626 CRecorder* iRecorder; // We only need one recorder. The driver will buffer data for us. |
|
627 |
|
628 TBool iUnderFlowReportedSinceLastPlayOrRecordRequest; |
|
629 |
|
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; |
|
635 |
|
636 TFormatData iPlayFormatData; |
|
637 TFormatData iRecordFormatData; |
|
638 }; |
495 #endif |
639 #endif |
496 TUint32 iStartTime; |
|
497 TBool iTimerActive; |
|
498 TBool iFlushCalledDuringPause; |
|
499 TBool iPauseDeviceDriverOnNewData; |
|
500 |
|
501 TFormatData iPlayData; |
|
502 TFormatData iRecordData; |
|
503 }; |
|
504 GLDEF_C void Panic(TSoundAdapterPanicCodes aPanicCode);//forward declaration |
|
505 #endif |
|