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 |