1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/boardsupport/emulator/emulatorbsp/specific/winssoundsc.h Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,402 @@
1.4 +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// wins\specific\winssoundsc.h
1.18 +// Definitions for the emulator shared chunk sound driver PDD.
1.19 +//
1.20 +//
1.21 +
1.22 +/**
1.23 + @file
1.24 + @internalTechnology
1.25 + @prototype
1.26 +*/
1.27 +
1.28 +#ifndef __WINSSOUNDSC_H__
1.29 +#define __WINSSOUNDSC_H__
1.30 +
1.31 +#include <drivers/soundsc.h>
1.32 +#include "nk_priv.h"
1.33 +#include <emulator.h>
1.34 +#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
1.35 +#include <mmsystem.h>
1.36 +#include <mmreg.h>
1.37 +#pragma warning(default : 4201)
1.38 +#include <property.h>
1.39 +
1.40 +//#define FORCE_NO_HARDWARE
1.41 +
1.42 +//#define __KTRACE_SND(s) s;
1.43 +#define __KTRACE_SND(s)
1.44 +
1.45 +#define PANIC() Kern::Fault("WinsSoundScPdd", __LINE__)
1.46 +
1.47 +const TInt KMMTimerRes = 5; // Minimum timer resolution (5mS). Timer used only when no audio hardware present.
1.48 +const TInt KWinsMaxAudioTransferLen=0x8000; // The maximum transfer length this PDD will accept (32K).
1.49 +const TInt KMinWaveHdrBufCount=8; // The minimum number of record or playback waveform audio buffers.
1.50 +
1.51 +GLREF_C TInt RateInSamplesPerSecond(TSoundRate aRate);
1.52 +GLREF_C DWORD WaitForSingleObjectDualThread(HANDLE hHandle,DWORD dwMilliseconds);
1.53 +GLREF_C WAVEHDR* RemoveFromPendingList(WAVEHDR** aList);
1.54 +GLREF_C void AddToPendingList(WAVEHDR* aBuffer,WAVEHDR** aList);
1.55 +
1.56 +// Utility class used to lock the kernel for a short period while windows
1.57 +// API calls are made. This is to stop a possible deadlock from occurring when
1.58 +// a windows thread is suspended while a (windows) synchronization object is held
1.59 +// and a second thread tries to gain access to that object. Typically this object
1.60 +// is declared on the stack - when the constructor is called, the kernel is locked;
1.61 +// when the object goes out of scope, the destructor unlocks the kernel.
1.62 +// Used by the __HOST_LOCK macro.
1.63 +class THostLock
1.64 + {
1.65 +public:
1.66 + THostLock();
1.67 + ~THostLock();
1.68 + void Lock();
1.69 + void Unlock();
1.70 +protected:
1.71 + THostLock(TBool aLock);
1.72 +private:
1.73 + TBool iLocked;
1.74 + };
1.75 +
1.76 +// Utility class used to lock the kernel for a short period while windows
1.77 +// API calls are made. This is used instead of THostLock for functions
1.78 +// which are used by both the driver thread and the play thread -
1.79 +// if the thread is a windows thread, then the kernel is not locked.
1.80 +// Used by the __COND_HOST_LOCK macro.
1.81 +class TCondHostLock : public THostLock
1.82 + {
1.83 +public:
1.84 + TCondHostLock();
1.85 + void Lock();
1.86 + void Unlock();
1.87 +private:
1.88 + TBool iEpocThread;
1.89 + };
1.90 +
1.91 +// Forward declarations
1.92 +class TWaveformBufMgr;
1.93 +
1.94 +/**
1.95 +This the abstraction for a windows waveform audio buffer.
1.96 +*/
1.97 +class TWaveformAudioBuf
1.98 + {
1.99 +public:
1.100 + TWaveformAudioBuf();
1.101 + inline void SetWaveformBufMgr(TWaveformBufMgr* aWaveformBufMgr)
1.102 + {iWaveformBufMgr=aWaveformBufMgr;}
1.103 + inline void SetBufNum(TInt aBufNum)
1.104 + {iBufNum=aBufNum;}
1.105 + void Prepare(char* aBufAddr,TInt aBufLength,TInt aDeviceHandle);
1.106 + void Unprepare(TInt aDeviceHandle);
1.107 +private:
1.108 + void DoPrepareOut(HWAVEOUT aPlayDeviceHandle);
1.109 + void DoUnprepareOut(HWAVEOUT aPlayDeviceHandle);
1.110 + void DoPrepareIn(HWAVEIN aRecordDeviceHandle);
1.111 + void DoUnprepareIn(HWAVEIN aRecordDeviceHandle);
1.112 +public:
1.113 + /** The owning waveform audio buffer manager. */
1.114 + TWaveformBufMgr* iWaveformBufMgr;
1.115 + /** Set when the waveform audio buffer is currently prepared. */
1.116 + TBool iIsPrepared;
1.117 + /** Set when the waveform audio buffer is involved in an active transfer. */
1.118 + TBool iIsInUse;
1.119 + /** The header used by windows to identify the waveform audio buffer. */
1.120 + WAVEHDR iBufHdr;
1.121 + /** A value used to identify a particular waveform audio buffer within an array of these objects. */
1.122 + TInt iBufNum;
1.123 + /** The transfer ID supplied by the LDD when the buffer is involved in an active transfer. */
1.124 + TUint iTransferID;
1.125 + friend class TWaveformBufMgr;
1.126 + };
1.127 +
1.128 +/**
1.129 +The waveform audio buffer manager. This owns and maintains a set of windows waveform audio buffers which it makes
1.130 +available to the PDD for data block transfers.
1.131 +*/
1.132 +class TWaveformBufMgr
1.133 + {
1.134 +public:
1.135 + TWaveformBufMgr(TSoundDirection aDirection,TBool aIsHardware);
1.136 + ~TWaveformBufMgr();
1.137 + TInt ReAllocAndUpdate(TSoundSharedChunkBufConfig* aBufConfig,TLinAddr aChunkBase,TInt aDeviceHandle);
1.138 + TWaveformAudioBuf* AcquireBuf(char* aStartAddress,TInt aBufLength,TInt aDeviceHandle);
1.139 +public:
1.140 + /** The array of windows waveform audio buffer objects. There is at least one buffer object per buffer within the
1.141 + LDD shared chunk. */
1.142 + TWaveformAudioBuf* iWaveformAudioBuf;
1.143 + /** The count of the number of audio play buffers in the waveform buffer array. */
1.144 + TInt iNumWaveformBufs;
1.145 + /** The default size of each audio buffer in the waveform buffer array. */
1.146 + TInt iWaveformBufSize;
1.147 + /** List of waveform audio buffer objects waiting to be played/recorded - in FIFO order. Used only when
1.148 + no audio hardware is present.*/
1.149 + WAVEHDR** iPendingBufList;
1.150 + /** Set when no audio hardware is present. */
1.151 + TBool iIsHardware;
1.152 + /** The direction of the windows waveform audio buffer, record or playback. */
1.153 + TSoundDirection iDirection;
1.154 + };
1.155 +
1.156 +/**
1.157 +The WINS physical device (factory class) for the shared chunk sound driver.
1.158 +*/
1.159 +class DWinsSoundScPddFactory : public DPhysicalDevice
1.160 + {
1.161 +public:
1.162 + DWinsSoundScPddFactory();
1.163 + ~DWinsSoundScPddFactory();
1.164 + virtual TInt Install();
1.165 + virtual void GetCaps(TDes8 &aDes) const;
1.166 + virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion &aVer);
1.167 + virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer);
1.168 +private:
1.169 + /** The DFC queue (used also by the LDD). */
1.170 + TDynamicDfcQue* iDfcQ;
1.171 + /** DFC for terminating the DFC thread. */
1.172 + static TDfc ExitDfc;
1.173 + friend class DWinsSoundScTxPdd;
1.174 + friend class DWinsSoundScRxPdd;
1.175 + };
1.176 +
1.177 +/**
1.178 +The WINS physical device driver (PDD) for the playback shared chunk sound driver.
1.179 +*/
1.180 +class DWinsSoundScTxPdd : public DSoundScPdd
1.181 + {
1.182 +private:
1.183 + enum TThreadCommand {ESendData, EStop, EExit, EPause, EResume};
1.184 + enum TCreatePlayDeviceMode {EInit,ESetConfig,EStartTransfer};
1.185 +public:
1.186 + DWinsSoundScTxPdd();
1.187 + ~DWinsSoundScTxPdd();
1.188 + TInt DoCreate(DWinsSoundScPddFactory* aPhysicalDevice);
1.189 + // Implementations of the pure virtual functions inherited from DSoundScPdd.
1.190 + virtual TDfcQue* DfcQ(TInt aUnit);
1.191 + virtual void GetChunkCreateInfo(TChunkCreateInfo& aChunkCreateInfo);
1.192 + virtual void Caps(TDes8& aCapsBuf) const;
1.193 + virtual TInt MaxTransferLen() const;
1.194 + virtual TInt SetConfig(const TDesC8& aConfigBuf);
1.195 + virtual TInt SetVolume(TInt aVolume);
1.196 + virtual TInt StartTransfer();
1.197 + virtual TInt TransferData(TUint aTransferID,TLinAddr aLinAddr,TPhysAddr aPhysAddr,TInt aNumBytes);
1.198 + virtual void StopTransfer();
1.199 + virtual TInt PauseTransfer();
1.200 + virtual TInt ResumeTransfer();
1.201 + virtual TInt PowerUp();
1.202 + virtual void PowerDown();
1.203 + virtual TInt CustomConfig(TInt aFunction,TAny* aParam);
1.204 + virtual TInt TimeTransferred(TInt64& aTime, TInt aState);
1.205 +public:
1.206 + void WaveOutProc(WAVEHDR* aHdr);
1.207 + void PlayThread();
1.208 +private:
1.209 + void SetCaps();
1.210 + TInt OpenWaveOutDevice();
1.211 + TInt CreatePlayDevice(TCreatePlayDeviceMode aMode);
1.212 + void ClosePlayDevice();
1.213 + void PlayThreadCommand(TThreadCommand aCommand,TInt aArg0=0,TInt aArg1=0,TInt aArg2=0);
1.214 + TInt ProcessPlayCommand(TThreadCommand aCommand,TInt aArg0,TInt aArg1,TInt aArg2);
1.215 + void HandlePlayTimerEvent();
1.216 + void HandleTransferComplete();
1.217 + void PlayThreadNotifyDriver(TInt aError);
1.218 + void StartTimer(WAVEHDR* aBuffer);
1.219 + void StopTimer(TBool aCancelAll);
1.220 + static void PlayDfc(TAny* aPtr);
1.221 +private:
1.222 + /** A pointer to the PDD factory. */
1.223 + DWinsSoundScPddFactory* iPhysicalDevice;
1.224 + /** The capabilities of this device. */
1.225 + TSoundFormatsSupportedV02 iCaps;
1.226 + /** The current audio configuration of this device. */
1.227 + TCurrentSoundFormatV02 iSoundConfig;
1.228 + /** The current setting for the play volume - a value in the range 0 to 0xFFFF. */
1.229 + TInt iVolume;
1.230 + /** The driver thread semaphore - used by the windows thread to signal the driver thread. */
1.231 + HANDLE iDriverThreadSem;
1.232 + /** The handle for the play windows thread. */
1.233 + HANDLE iPlayThread;
1.234 + /** ETrue if the Windows thread is running, else EFalse. Used when shutting down to decide whether to
1.235 + signal the thread to exit. */
1.236 + TBool iPlayThreadRunning;
1.237 + /** The play thread mutuex - to serialise acccess to the play thread creation and destruction routines. */
1.238 + HANDLE iPlayThreadMutex;
1.239 + /** The play thread semaphore - indicates to the windows thread that the driver thread has issued a command. */
1.240 + HANDLE iPlayThreadSem;
1.241 + /** Semaphore to synchronise between driver thread and windows thread when closing the output device. */
1.242 + HANDLE iStopSemaphore;
1.243 + /** Semaphore to synchronise between driver thread and windows thread when closing the PDD. */
1.244 + HANDLE iDeathSemaphore;
1.245 + /** The handle on the waveform output device. */
1.246 + HWAVEOUT iPlayDeviceHandle;
1.247 + /** Used to transfer commands between the driver thread and the windows thread. */
1.248 + TThreadCommand iPlayCommand;
1.249 + /** Used to transfer commands between the driver thread and the windows thread. */
1.250 + TInt iPlayCommandArg0;
1.251 + /** Used to transfer commands between the driver thread and the windows thread. */
1.252 + TInt iPlayCommandArg1;
1.253 + /** Used to transfer commands between the driver thread and the windows thread. */
1.254 + TInt iPlayCommandArg2;
1.255 + // The number of outstanding data transfers on the waveform output device. */
1.256 + TInt iPendingPlay;
1.257 + /** DFC which handes data block play completion. */
1.258 + TDfc iDfc;
1.259 + /** A variable used to pass a value from the windows thread to the driver thread. */
1.260 + TInt iPlayThreadError;
1.261 + /** The windows waveform audio buffer manager. */
1.262 + TWaveformBufMgr* iWaveformBufMgr;
1.263 + /** A mask used to pass information on transfers that have just completed between the window thread and the
1.264 + driver thread. Updates to this variable typically need to happen atomically. Bit positions are converted
1.265 + into windows waveform audio buffer IDs. */
1.266 + TUint32 iCompletedPlayBufHdrMask;
1.267 + /** Set when no audio hardware is present. */
1.268 + TBool iNoHardware;
1.269 + /** The timer event object - indicates the 'no-hardware' timer has gone off. */
1.270 + HANDLE iPlayTimerEvent;
1.271 + /** The identifier for the current 'no-hardware' timer event. */
1.272 + UINT iTimerID;
1.273 + /** Indicates whether the 'no-hardware' timer is currently active. */
1.274 + TBool iTimerActive;
1.275 + /** A variable used to save the play volume setting of the waveform output device at the point when this driver was opened. */
1.276 + DWORD iWinWaveVolume;
1.277 + /** The number of bytes (not samples) that will be played back per second, at the current sample rate. */
1.278 + TUint iBytesPerSecond;
1.279 + /** The simulated (ie. no hardware) microseconds played. */
1.280 + TInt64 iSimulatedUSecPlayed;
1.281 + /** The # of milliseconds that pass per block of data that is played. */
1.282 + UINT iSimulatedMsecDuration;
1.283 + /** The Windows system timer time at which the last block of data was played. */
1.284 + DWORD iLastTimerEventTime;
1.285 + /** The Windows system timer time at which playback was paused. */
1.286 + DWORD iPauseTime;
1.287 + };
1.288 +
1.289 +/**
1.290 +The WINS physical device driver (PDD) for the record shared chunk sound driver.
1.291 +*/
1.292 +class DWinsSoundScRxPdd : public DSoundScPdd
1.293 + {
1.294 +private:
1.295 + enum TThreadCommand {ERecData, EStop, EExit, EPause, EResume};
1.296 +public:
1.297 + DWinsSoundScRxPdd();
1.298 + ~DWinsSoundScRxPdd();
1.299 + TInt DoCreate(DWinsSoundScPddFactory* aPhysicalDevice);
1.300 + // Implementations of the pure virtual functions inherited from DSoundScPdd.
1.301 + virtual TDfcQue* DfcQ(TInt aUnit);
1.302 + virtual void GetChunkCreateInfo(TChunkCreateInfo& aChunkCreateInfo);
1.303 + virtual void Caps(TDes8& aCapsBuf) const;
1.304 + virtual TInt MaxTransferLen() const;
1.305 + virtual TInt SetConfig(const TDesC8& aConfigBuf);
1.306 + virtual TInt SetVolume(TInt aVolume);
1.307 + virtual TInt StartTransfer();
1.308 + virtual TInt TransferData(TUint aTransferID,TLinAddr aLinAddr,TPhysAddr aPhysAddr,TInt aNumBytes);
1.309 + virtual void StopTransfer();
1.310 + virtual TInt PauseTransfer();
1.311 + virtual TInt ResumeTransfer();
1.312 + virtual TInt PowerUp();
1.313 + virtual void PowerDown();
1.314 + virtual TInt CustomConfig(TInt aFunction,TAny* aParam);
1.315 + virtual TInt TimeTransferred(TInt64& aTime, TInt aState);
1.316 +public:
1.317 + void WaveInProc(WAVEHDR* aHdr);
1.318 + void RecordThread();
1.319 +private:
1.320 + void SetCaps();
1.321 + TInt OpenWaveInDevice();
1.322 + TInt CreateRecordDevice(TBool aCheckDevice=EFalse);
1.323 + void CloseRecordDevice();
1.324 + void RecordThreadCommand(TThreadCommand aCommand,TInt aArg0=0,TInt aArg1=0,TInt aArg2=0);
1.325 + TInt ProcessRecordCommand(TThreadCommand aCommand,TInt aArg0,TInt aArg1,TInt aArg2);
1.326 + void HandleRecordTimerEvent();
1.327 + void HandleTransferComplete();
1.328 + void RecordThreadNotifyDriver(TInt aError);
1.329 + void StartTimer(WAVEHDR* aBuffer);
1.330 + void StopTimer(TBool aCancelAll);
1.331 + static void RecordDfc(TAny* aPtr);
1.332 +private:
1.333 + /** A pointer to the PDD factory. */
1.334 + DWinsSoundScPddFactory* iPhysicalDevice;
1.335 + /** The capabilities of this device. */
1.336 + TSoundFormatsSupportedV02 iCaps;
1.337 + /** The current audio configuration of this device. */
1.338 + TCurrentSoundFormatV02 iSoundConfig;
1.339 + /** The driver thread semaphore - used by the windows thread to signal the driver thread. */
1.340 + HANDLE iDriverThreadSem;
1.341 + /** The handle for the record windows thread. */
1.342 + HANDLE iRecordThread;
1.343 + /** ETrue if the Windows thread is running, else EFalse. Used when shutting down to decide whether to
1.344 + signal the thread to exit. */
1.345 + TBool iRecordThreadRunning;
1.346 + /** The record thread mutuex - to serialise acccess to the record thread creation and destruction routines. */
1.347 + HANDLE iRecordThreadMutex;
1.348 + /** The record thread semaphore - indicates to the windows thread that the driver thread has issued a command. */
1.349 + HANDLE iRecordThreadSem;
1.350 + /** Semaphore to synchronise between driver thread and windows thread when closing the input device. */
1.351 + HANDLE iStopSemaphore;
1.352 + /** Semaphore to synchronise between driver thread and windows thread when closing the PDD. */
1.353 + HANDLE iDeathSemaphore;
1.354 + /** The handle on the waveform input device. */
1.355 + HWAVEIN iRecordDeviceHandle;
1.356 + /** Used to transfer commands between the driver thread and the windows thread. */
1.357 + TThreadCommand iRecordCommand;
1.358 + /** Used to transfer commands between the driver thread and the windows thread. */
1.359 + TInt iRecordCommandArg0;
1.360 + /** Used to transfer commands between the driver thread and the windows thread. */
1.361 + TInt iRecordCommandArg1;
1.362 + /** Used to transfer commands between the driver thread and the windows thread. */
1.363 + TInt iRecordCommandArg2;
1.364 + // The number of outstanding data transfers on the waveform input device. */
1.365 + TInt iPendingRecord;
1.366 + /** DFC which handes data block record completion. */
1.367 + TDfc iDfc;
1.368 + /** A variable used to pass a value from the windows thread to the driver thread. */
1.369 + TInt iRecordThreadError;
1.370 + /** The windows waveform audio buffer manager. */
1.371 + TWaveformBufMgr* iWaveformBufMgr;
1.372 + /** A mask used to pass information on transfers that have just completed between the window thread and the
1.373 + driver thread. Updates to this variable typically need to happen atomically. Bit positions are converted
1.374 + into windows waveform audio buffer IDs. */
1.375 + TUint32 iCompletedRecordBufHdrMask;
1.376 + /** Indicates when record mode is enabled. */
1.377 + TBool iRecordEnabled;
1.378 + /** Set when no audio hardware is present. */
1.379 + TBool iNoHardware;
1.380 + /** The timer event object - indicates the 'no-hardware' timer has gone off. */
1.381 + HANDLE iRecordTimerEvent;
1.382 + /** The identifier for the current 'no-hardware' timer event. */
1.383 + UINT iTimerID;
1.384 + /** Indicates whether the 'no-hardware' timer is currently active. */
1.385 + TBool iTimerActive;
1.386 + /** The number of bytes (not samples) that will be recorded back per second, at the current sample rate. */
1.387 + TUint iBytesPerSecond;
1.388 + /** The number of bytes recorded before the last pause command (when we pause the windows byte
1.389 + count is reset so we need to add this on for the TimeRecorded API). */
1.390 + TUint iBytesRecordedBeforeLastPause;
1.391 + /** The number of recorded bytes reported to the LDD. Subtracted from the windows recorded byte count
1.392 + to calculate the last, partial buffer, transfer size */
1.393 + TUint iBytesSincePauseReportedToLdd;
1.394 + /** The # of milliseconds that pass per block of data that is recorded. */
1.395 + UINT iSimulatedMsecDuration;
1.396 + /** The Windows system timer time at which the last block of data was recorded. */
1.397 + DWORD iLastTimerEventTime;
1.398 + };
1.399 +
1.400 +#define __HOST_LOCK THostLock lock
1.401 +#define __HOST_LOCK_ON lock.Lock();
1.402 +#define __HOST_LOCK_OFF lock.Unlock();
1.403 +#define __COND_HOST_LOCK TCondHostLock lock
1.404 +
1.405 +#endif /* __WINSSOUNDSC_H__ */