sl@0: // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // wins\specific\winssoundsc.h sl@0: // Definitions for the emulator shared chunk sound driver PDD. sl@0: // sl@0: // sl@0: sl@0: /** sl@0: @file sl@0: @internalTechnology sl@0: @prototype sl@0: */ sl@0: sl@0: #ifndef __WINSSOUNDSC_H__ sl@0: #define __WINSSOUNDSC_H__ sl@0: sl@0: #include sl@0: #include "nk_priv.h" sl@0: #include sl@0: #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union sl@0: #include sl@0: #include sl@0: #pragma warning(default : 4201) sl@0: #include sl@0: sl@0: //#define FORCE_NO_HARDWARE sl@0: sl@0: //#define __KTRACE_SND(s) s; sl@0: #define __KTRACE_SND(s) sl@0: sl@0: #define PANIC() Kern::Fault("WinsSoundScPdd", __LINE__) sl@0: sl@0: const TInt KMMTimerRes = 5; // Minimum timer resolution (5mS). Timer used only when no audio hardware present. sl@0: const TInt KWinsMaxAudioTransferLen=0x8000; // The maximum transfer length this PDD will accept (32K). sl@0: const TInt KMinWaveHdrBufCount=8; // The minimum number of record or playback waveform audio buffers. sl@0: sl@0: GLREF_C TInt RateInSamplesPerSecond(TSoundRate aRate); sl@0: GLREF_C DWORD WaitForSingleObjectDualThread(HANDLE hHandle,DWORD dwMilliseconds); sl@0: GLREF_C WAVEHDR* RemoveFromPendingList(WAVEHDR** aList); sl@0: GLREF_C void AddToPendingList(WAVEHDR* aBuffer,WAVEHDR** aList); sl@0: sl@0: // Utility class used to lock the kernel for a short period while windows sl@0: // API calls are made. This is to stop a possible deadlock from occurring when sl@0: // a windows thread is suspended while a (windows) synchronization object is held sl@0: // and a second thread tries to gain access to that object. Typically this object sl@0: // is declared on the stack - when the constructor is called, the kernel is locked; sl@0: // when the object goes out of scope, the destructor unlocks the kernel. sl@0: // Used by the __HOST_LOCK macro. sl@0: class THostLock sl@0: { sl@0: public: sl@0: THostLock(); sl@0: ~THostLock(); sl@0: void Lock(); sl@0: void Unlock(); sl@0: protected: sl@0: THostLock(TBool aLock); sl@0: private: sl@0: TBool iLocked; sl@0: }; sl@0: sl@0: // Utility class used to lock the kernel for a short period while windows sl@0: // API calls are made. This is used instead of THostLock for functions sl@0: // which are used by both the driver thread and the play thread - sl@0: // if the thread is a windows thread, then the kernel is not locked. sl@0: // Used by the __COND_HOST_LOCK macro. sl@0: class TCondHostLock : public THostLock sl@0: { sl@0: public: sl@0: TCondHostLock(); sl@0: void Lock(); sl@0: void Unlock(); sl@0: private: sl@0: TBool iEpocThread; sl@0: }; sl@0: sl@0: // Forward declarations sl@0: class TWaveformBufMgr; sl@0: sl@0: /** sl@0: This the abstraction for a windows waveform audio buffer. sl@0: */ sl@0: class TWaveformAudioBuf sl@0: { sl@0: public: sl@0: TWaveformAudioBuf(); sl@0: inline void SetWaveformBufMgr(TWaveformBufMgr* aWaveformBufMgr) sl@0: {iWaveformBufMgr=aWaveformBufMgr;} sl@0: inline void SetBufNum(TInt aBufNum) sl@0: {iBufNum=aBufNum;} sl@0: void Prepare(char* aBufAddr,TInt aBufLength,TInt aDeviceHandle); sl@0: void Unprepare(TInt aDeviceHandle); sl@0: private: sl@0: void DoPrepareOut(HWAVEOUT aPlayDeviceHandle); sl@0: void DoUnprepareOut(HWAVEOUT aPlayDeviceHandle); sl@0: void DoPrepareIn(HWAVEIN aRecordDeviceHandle); sl@0: void DoUnprepareIn(HWAVEIN aRecordDeviceHandle); sl@0: public: sl@0: /** The owning waveform audio buffer manager. */ sl@0: TWaveformBufMgr* iWaveformBufMgr; sl@0: /** Set when the waveform audio buffer is currently prepared. */ sl@0: TBool iIsPrepared; sl@0: /** Set when the waveform audio buffer is involved in an active transfer. */ sl@0: TBool iIsInUse; sl@0: /** The header used by windows to identify the waveform audio buffer. */ sl@0: WAVEHDR iBufHdr; sl@0: /** A value used to identify a particular waveform audio buffer within an array of these objects. */ sl@0: TInt iBufNum; sl@0: /** The transfer ID supplied by the LDD when the buffer is involved in an active transfer. */ sl@0: TUint iTransferID; sl@0: friend class TWaveformBufMgr; sl@0: }; sl@0: sl@0: /** sl@0: The waveform audio buffer manager. This owns and maintains a set of windows waveform audio buffers which it makes sl@0: available to the PDD for data block transfers. sl@0: */ sl@0: class TWaveformBufMgr sl@0: { sl@0: public: sl@0: TWaveformBufMgr(TSoundDirection aDirection,TBool aIsHardware); sl@0: ~TWaveformBufMgr(); sl@0: TInt ReAllocAndUpdate(TSoundSharedChunkBufConfig* aBufConfig,TLinAddr aChunkBase,TInt aDeviceHandle); sl@0: TWaveformAudioBuf* AcquireBuf(char* aStartAddress,TInt aBufLength,TInt aDeviceHandle); sl@0: public: sl@0: /** The array of windows waveform audio buffer objects. There is at least one buffer object per buffer within the sl@0: LDD shared chunk. */ sl@0: TWaveformAudioBuf* iWaveformAudioBuf; sl@0: /** The count of the number of audio play buffers in the waveform buffer array. */ sl@0: TInt iNumWaveformBufs; sl@0: /** The default size of each audio buffer in the waveform buffer array. */ sl@0: TInt iWaveformBufSize; sl@0: /** List of waveform audio buffer objects waiting to be played/recorded - in FIFO order. Used only when sl@0: no audio hardware is present.*/ sl@0: WAVEHDR** iPendingBufList; sl@0: /** Set when no audio hardware is present. */ sl@0: TBool iIsHardware; sl@0: /** The direction of the windows waveform audio buffer, record or playback. */ sl@0: TSoundDirection iDirection; sl@0: }; sl@0: sl@0: /** sl@0: The WINS physical device (factory class) for the shared chunk sound driver. sl@0: */ sl@0: class DWinsSoundScPddFactory : public DPhysicalDevice sl@0: { sl@0: public: sl@0: DWinsSoundScPddFactory(); sl@0: ~DWinsSoundScPddFactory(); sl@0: virtual TInt Install(); sl@0: virtual void GetCaps(TDes8 &aDes) const; sl@0: virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion &aVer); sl@0: virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer); sl@0: private: sl@0: /** The DFC queue (used also by the LDD). */ sl@0: TDynamicDfcQue* iDfcQ; sl@0: /** DFC for terminating the DFC thread. */ sl@0: static TDfc ExitDfc; sl@0: friend class DWinsSoundScTxPdd; sl@0: friend class DWinsSoundScRxPdd; sl@0: }; sl@0: sl@0: /** sl@0: The WINS physical device driver (PDD) for the playback shared chunk sound driver. sl@0: */ sl@0: class DWinsSoundScTxPdd : public DSoundScPdd sl@0: { sl@0: private: sl@0: enum TThreadCommand {ESendData, EStop, EExit, EPause, EResume}; sl@0: enum TCreatePlayDeviceMode {EInit,ESetConfig,EStartTransfer}; sl@0: public: sl@0: DWinsSoundScTxPdd(); sl@0: ~DWinsSoundScTxPdd(); sl@0: TInt DoCreate(DWinsSoundScPddFactory* aPhysicalDevice); sl@0: // Implementations of the pure virtual functions inherited from DSoundScPdd. sl@0: virtual TDfcQue* DfcQ(TInt aUnit); sl@0: virtual void GetChunkCreateInfo(TChunkCreateInfo& aChunkCreateInfo); sl@0: virtual void Caps(TDes8& aCapsBuf) const; sl@0: virtual TInt MaxTransferLen() const; sl@0: virtual TInt SetConfig(const TDesC8& aConfigBuf); sl@0: virtual TInt SetVolume(TInt aVolume); sl@0: virtual TInt StartTransfer(); sl@0: virtual TInt TransferData(TUint aTransferID,TLinAddr aLinAddr,TPhysAddr aPhysAddr,TInt aNumBytes); sl@0: virtual void StopTransfer(); sl@0: virtual TInt PauseTransfer(); sl@0: virtual TInt ResumeTransfer(); sl@0: virtual TInt PowerUp(); sl@0: virtual void PowerDown(); sl@0: virtual TInt CustomConfig(TInt aFunction,TAny* aParam); sl@0: virtual TInt TimeTransferred(TInt64& aTime, TInt aState); sl@0: public: sl@0: void WaveOutProc(WAVEHDR* aHdr); sl@0: void PlayThread(); sl@0: private: sl@0: void SetCaps(); sl@0: TInt OpenWaveOutDevice(); sl@0: TInt CreatePlayDevice(TCreatePlayDeviceMode aMode); sl@0: void ClosePlayDevice(); sl@0: void PlayThreadCommand(TThreadCommand aCommand,TInt aArg0=0,TInt aArg1=0,TInt aArg2=0); sl@0: TInt ProcessPlayCommand(TThreadCommand aCommand,TInt aArg0,TInt aArg1,TInt aArg2); sl@0: void HandlePlayTimerEvent(); sl@0: void HandleTransferComplete(); sl@0: void PlayThreadNotifyDriver(TInt aError); sl@0: void StartTimer(WAVEHDR* aBuffer); sl@0: void StopTimer(TBool aCancelAll); sl@0: static void PlayDfc(TAny* aPtr); sl@0: private: sl@0: /** A pointer to the PDD factory. */ sl@0: DWinsSoundScPddFactory* iPhysicalDevice; sl@0: /** The capabilities of this device. */ sl@0: TSoundFormatsSupportedV02 iCaps; sl@0: /** The current audio configuration of this device. */ sl@0: TCurrentSoundFormatV02 iSoundConfig; sl@0: /** The current setting for the play volume - a value in the range 0 to 0xFFFF. */ sl@0: TInt iVolume; sl@0: /** The driver thread semaphore - used by the windows thread to signal the driver thread. */ sl@0: HANDLE iDriverThreadSem; sl@0: /** The handle for the play windows thread. */ sl@0: HANDLE iPlayThread; sl@0: /** ETrue if the Windows thread is running, else EFalse. Used when shutting down to decide whether to sl@0: signal the thread to exit. */ sl@0: TBool iPlayThreadRunning; sl@0: /** The play thread mutuex - to serialise acccess to the play thread creation and destruction routines. */ sl@0: HANDLE iPlayThreadMutex; sl@0: /** The play thread semaphore - indicates to the windows thread that the driver thread has issued a command. */ sl@0: HANDLE iPlayThreadSem; sl@0: /** Semaphore to synchronise between driver thread and windows thread when closing the output device. */ sl@0: HANDLE iStopSemaphore; sl@0: /** Semaphore to synchronise between driver thread and windows thread when closing the PDD. */ sl@0: HANDLE iDeathSemaphore; sl@0: /** The handle on the waveform output device. */ sl@0: HWAVEOUT iPlayDeviceHandle; sl@0: /** Used to transfer commands between the driver thread and the windows thread. */ sl@0: TThreadCommand iPlayCommand; sl@0: /** Used to transfer commands between the driver thread and the windows thread. */ sl@0: TInt iPlayCommandArg0; sl@0: /** Used to transfer commands between the driver thread and the windows thread. */ sl@0: TInt iPlayCommandArg1; sl@0: /** Used to transfer commands between the driver thread and the windows thread. */ sl@0: TInt iPlayCommandArg2; sl@0: // The number of outstanding data transfers on the waveform output device. */ sl@0: TInt iPendingPlay; sl@0: /** DFC which handes data block play completion. */ sl@0: TDfc iDfc; sl@0: /** A variable used to pass a value from the windows thread to the driver thread. */ sl@0: TInt iPlayThreadError; sl@0: /** The windows waveform audio buffer manager. */ sl@0: TWaveformBufMgr* iWaveformBufMgr; sl@0: /** A mask used to pass information on transfers that have just completed between the window thread and the sl@0: driver thread. Updates to this variable typically need to happen atomically. Bit positions are converted sl@0: into windows waveform audio buffer IDs. */ sl@0: TUint32 iCompletedPlayBufHdrMask; sl@0: /** Set when no audio hardware is present. */ sl@0: TBool iNoHardware; sl@0: /** The timer event object - indicates the 'no-hardware' timer has gone off. */ sl@0: HANDLE iPlayTimerEvent; sl@0: /** The identifier for the current 'no-hardware' timer event. */ sl@0: UINT iTimerID; sl@0: /** Indicates whether the 'no-hardware' timer is currently active. */ sl@0: TBool iTimerActive; sl@0: /** A variable used to save the play volume setting of the waveform output device at the point when this driver was opened. */ sl@0: DWORD iWinWaveVolume; sl@0: /** The number of bytes (not samples) that will be played back per second, at the current sample rate. */ sl@0: TUint iBytesPerSecond; sl@0: /** The simulated (ie. no hardware) microseconds played. */ sl@0: TInt64 iSimulatedUSecPlayed; sl@0: /** The # of milliseconds that pass per block of data that is played. */ sl@0: UINT iSimulatedMsecDuration; sl@0: /** The Windows system timer time at which the last block of data was played. */ sl@0: DWORD iLastTimerEventTime; sl@0: /** The Windows system timer time at which playback was paused. */ sl@0: DWORD iPauseTime; sl@0: }; sl@0: sl@0: /** sl@0: The WINS physical device driver (PDD) for the record shared chunk sound driver. sl@0: */ sl@0: class DWinsSoundScRxPdd : public DSoundScPdd sl@0: { sl@0: private: sl@0: enum TThreadCommand {ERecData, EStop, EExit, EPause, EResume}; sl@0: public: sl@0: DWinsSoundScRxPdd(); sl@0: ~DWinsSoundScRxPdd(); sl@0: TInt DoCreate(DWinsSoundScPddFactory* aPhysicalDevice); sl@0: // Implementations of the pure virtual functions inherited from DSoundScPdd. sl@0: virtual TDfcQue* DfcQ(TInt aUnit); sl@0: virtual void GetChunkCreateInfo(TChunkCreateInfo& aChunkCreateInfo); sl@0: virtual void Caps(TDes8& aCapsBuf) const; sl@0: virtual TInt MaxTransferLen() const; sl@0: virtual TInt SetConfig(const TDesC8& aConfigBuf); sl@0: virtual TInt SetVolume(TInt aVolume); sl@0: virtual TInt StartTransfer(); sl@0: virtual TInt TransferData(TUint aTransferID,TLinAddr aLinAddr,TPhysAddr aPhysAddr,TInt aNumBytes); sl@0: virtual void StopTransfer(); sl@0: virtual TInt PauseTransfer(); sl@0: virtual TInt ResumeTransfer(); sl@0: virtual TInt PowerUp(); sl@0: virtual void PowerDown(); sl@0: virtual TInt CustomConfig(TInt aFunction,TAny* aParam); sl@0: virtual TInt TimeTransferred(TInt64& aTime, TInt aState); sl@0: public: sl@0: void WaveInProc(WAVEHDR* aHdr); sl@0: void RecordThread(); sl@0: private: sl@0: void SetCaps(); sl@0: TInt OpenWaveInDevice(); sl@0: TInt CreateRecordDevice(TBool aCheckDevice=EFalse); sl@0: void CloseRecordDevice(); sl@0: void RecordThreadCommand(TThreadCommand aCommand,TInt aArg0=0,TInt aArg1=0,TInt aArg2=0); sl@0: TInt ProcessRecordCommand(TThreadCommand aCommand,TInt aArg0,TInt aArg1,TInt aArg2); sl@0: void HandleRecordTimerEvent(); sl@0: void HandleTransferComplete(); sl@0: void RecordThreadNotifyDriver(TInt aError); sl@0: void StartTimer(WAVEHDR* aBuffer); sl@0: void StopTimer(TBool aCancelAll); sl@0: static void RecordDfc(TAny* aPtr); sl@0: private: sl@0: /** A pointer to the PDD factory. */ sl@0: DWinsSoundScPddFactory* iPhysicalDevice; sl@0: /** The capabilities of this device. */ sl@0: TSoundFormatsSupportedV02 iCaps; sl@0: /** The current audio configuration of this device. */ sl@0: TCurrentSoundFormatV02 iSoundConfig; sl@0: /** The driver thread semaphore - used by the windows thread to signal the driver thread. */ sl@0: HANDLE iDriverThreadSem; sl@0: /** The handle for the record windows thread. */ sl@0: HANDLE iRecordThread; sl@0: /** ETrue if the Windows thread is running, else EFalse. Used when shutting down to decide whether to sl@0: signal the thread to exit. */ sl@0: TBool iRecordThreadRunning; sl@0: /** The record thread mutuex - to serialise acccess to the record thread creation and destruction routines. */ sl@0: HANDLE iRecordThreadMutex; sl@0: /** The record thread semaphore - indicates to the windows thread that the driver thread has issued a command. */ sl@0: HANDLE iRecordThreadSem; sl@0: /** Semaphore to synchronise between driver thread and windows thread when closing the input device. */ sl@0: HANDLE iStopSemaphore; sl@0: /** Semaphore to synchronise between driver thread and windows thread when closing the PDD. */ sl@0: HANDLE iDeathSemaphore; sl@0: /** The handle on the waveform input device. */ sl@0: HWAVEIN iRecordDeviceHandle; sl@0: /** Used to transfer commands between the driver thread and the windows thread. */ sl@0: TThreadCommand iRecordCommand; sl@0: /** Used to transfer commands between the driver thread and the windows thread. */ sl@0: TInt iRecordCommandArg0; sl@0: /** Used to transfer commands between the driver thread and the windows thread. */ sl@0: TInt iRecordCommandArg1; sl@0: /** Used to transfer commands between the driver thread and the windows thread. */ sl@0: TInt iRecordCommandArg2; sl@0: // The number of outstanding data transfers on the waveform input device. */ sl@0: TInt iPendingRecord; sl@0: /** DFC which handes data block record completion. */ sl@0: TDfc iDfc; sl@0: /** A variable used to pass a value from the windows thread to the driver thread. */ sl@0: TInt iRecordThreadError; sl@0: /** The windows waveform audio buffer manager. */ sl@0: TWaveformBufMgr* iWaveformBufMgr; sl@0: /** A mask used to pass information on transfers that have just completed between the window thread and the sl@0: driver thread. Updates to this variable typically need to happen atomically. Bit positions are converted sl@0: into windows waveform audio buffer IDs. */ sl@0: TUint32 iCompletedRecordBufHdrMask; sl@0: /** Indicates when record mode is enabled. */ sl@0: TBool iRecordEnabled; sl@0: /** Set when no audio hardware is present. */ sl@0: TBool iNoHardware; sl@0: /** The timer event object - indicates the 'no-hardware' timer has gone off. */ sl@0: HANDLE iRecordTimerEvent; sl@0: /** The identifier for the current 'no-hardware' timer event. */ sl@0: UINT iTimerID; sl@0: /** Indicates whether the 'no-hardware' timer is currently active. */ sl@0: TBool iTimerActive; sl@0: /** The number of bytes (not samples) that will be recorded back per second, at the current sample rate. */ sl@0: TUint iBytesPerSecond; sl@0: /** The number of bytes recorded before the last pause command (when we pause the windows byte sl@0: count is reset so we need to add this on for the TimeRecorded API). */ sl@0: TUint iBytesRecordedBeforeLastPause; sl@0: /** The number of recorded bytes reported to the LDD. Subtracted from the windows recorded byte count sl@0: to calculate the last, partial buffer, transfer size */ sl@0: TUint iBytesSincePauseReportedToLdd; sl@0: /** The # of milliseconds that pass per block of data that is recorded. */ sl@0: UINT iSimulatedMsecDuration; sl@0: /** The Windows system timer time at which the last block of data was recorded. */ sl@0: DWORD iLastTimerEventTime; sl@0: }; sl@0: sl@0: #define __HOST_LOCK THostLock lock sl@0: #define __HOST_LOCK_ON lock.Lock(); sl@0: #define __HOST_LOCK_OFF lock.Unlock(); sl@0: #define __COND_HOST_LOCK TCondHostLock lock sl@0: sl@0: #endif /* __WINSSOUNDSC_H__ */