|
1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // wins\specific\winssoundsc.h |
|
15 // Definitions for the emulator shared chunk sound driver PDD. |
|
16 // |
|
17 // |
|
18 |
|
19 /** |
|
20 @file |
|
21 @internalTechnology |
|
22 @prototype |
|
23 */ |
|
24 |
|
25 #ifndef __WINSSOUNDSC_H__ |
|
26 #define __WINSSOUNDSC_H__ |
|
27 |
|
28 #include <drivers/soundsc.h> |
|
29 #include "nk_priv.h" |
|
30 #include <emulator.h> |
|
31 #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union |
|
32 #include <mmsystem.h> |
|
33 #include <mmreg.h> |
|
34 #pragma warning(default : 4201) |
|
35 #include <property.h> |
|
36 |
|
37 //#define FORCE_NO_HARDWARE |
|
38 |
|
39 //#define __KTRACE_SND(s) s; |
|
40 #define __KTRACE_SND(s) |
|
41 |
|
42 #define PANIC() Kern::Fault("WinsSoundScPdd", __LINE__) |
|
43 |
|
44 const TInt KMMTimerRes = 5; // Minimum timer resolution (5mS). Timer used only when no audio hardware present. |
|
45 const TInt KWinsMaxAudioTransferLen=0x8000; // The maximum transfer length this PDD will accept (32K). |
|
46 const TInt KMinWaveHdrBufCount=8; // The minimum number of record or playback waveform audio buffers. |
|
47 |
|
48 GLREF_C TInt RateInSamplesPerSecond(TSoundRate aRate); |
|
49 GLREF_C DWORD WaitForSingleObjectDualThread(HANDLE hHandle,DWORD dwMilliseconds); |
|
50 GLREF_C WAVEHDR* RemoveFromPendingList(WAVEHDR** aList); |
|
51 GLREF_C void AddToPendingList(WAVEHDR* aBuffer,WAVEHDR** aList); |
|
52 |
|
53 // Utility class used to lock the kernel for a short period while windows |
|
54 // API calls are made. This is to stop a possible deadlock from occurring when |
|
55 // a windows thread is suspended while a (windows) synchronization object is held |
|
56 // and a second thread tries to gain access to that object. Typically this object |
|
57 // is declared on the stack - when the constructor is called, the kernel is locked; |
|
58 // when the object goes out of scope, the destructor unlocks the kernel. |
|
59 // Used by the __HOST_LOCK macro. |
|
60 class THostLock |
|
61 { |
|
62 public: |
|
63 THostLock(); |
|
64 ~THostLock(); |
|
65 void Lock(); |
|
66 void Unlock(); |
|
67 protected: |
|
68 THostLock(TBool aLock); |
|
69 private: |
|
70 TBool iLocked; |
|
71 }; |
|
72 |
|
73 // Utility class used to lock the kernel for a short period while windows |
|
74 // API calls are made. This is used instead of THostLock for functions |
|
75 // which are used by both the driver thread and the play thread - |
|
76 // if the thread is a windows thread, then the kernel is not locked. |
|
77 // Used by the __COND_HOST_LOCK macro. |
|
78 class TCondHostLock : public THostLock |
|
79 { |
|
80 public: |
|
81 TCondHostLock(); |
|
82 void Lock(); |
|
83 void Unlock(); |
|
84 private: |
|
85 TBool iEpocThread; |
|
86 }; |
|
87 |
|
88 // Forward declarations |
|
89 class TWaveformBufMgr; |
|
90 |
|
91 /** |
|
92 This the abstraction for a windows waveform audio buffer. |
|
93 */ |
|
94 class TWaveformAudioBuf |
|
95 { |
|
96 public: |
|
97 TWaveformAudioBuf(); |
|
98 inline void SetWaveformBufMgr(TWaveformBufMgr* aWaveformBufMgr) |
|
99 {iWaveformBufMgr=aWaveformBufMgr;} |
|
100 inline void SetBufNum(TInt aBufNum) |
|
101 {iBufNum=aBufNum;} |
|
102 void Prepare(char* aBufAddr,TInt aBufLength,TInt aDeviceHandle); |
|
103 void Unprepare(TInt aDeviceHandle); |
|
104 private: |
|
105 void DoPrepareOut(HWAVEOUT aPlayDeviceHandle); |
|
106 void DoUnprepareOut(HWAVEOUT aPlayDeviceHandle); |
|
107 void DoPrepareIn(HWAVEIN aRecordDeviceHandle); |
|
108 void DoUnprepareIn(HWAVEIN aRecordDeviceHandle); |
|
109 public: |
|
110 /** The owning waveform audio buffer manager. */ |
|
111 TWaveformBufMgr* iWaveformBufMgr; |
|
112 /** Set when the waveform audio buffer is currently prepared. */ |
|
113 TBool iIsPrepared; |
|
114 /** Set when the waveform audio buffer is involved in an active transfer. */ |
|
115 TBool iIsInUse; |
|
116 /** The header used by windows to identify the waveform audio buffer. */ |
|
117 WAVEHDR iBufHdr; |
|
118 /** A value used to identify a particular waveform audio buffer within an array of these objects. */ |
|
119 TInt iBufNum; |
|
120 /** The transfer ID supplied by the LDD when the buffer is involved in an active transfer. */ |
|
121 TUint iTransferID; |
|
122 friend class TWaveformBufMgr; |
|
123 }; |
|
124 |
|
125 /** |
|
126 The waveform audio buffer manager. This owns and maintains a set of windows waveform audio buffers which it makes |
|
127 available to the PDD for data block transfers. |
|
128 */ |
|
129 class TWaveformBufMgr |
|
130 { |
|
131 public: |
|
132 TWaveformBufMgr(TSoundDirection aDirection,TBool aIsHardware); |
|
133 ~TWaveformBufMgr(); |
|
134 TInt ReAllocAndUpdate(TSoundSharedChunkBufConfig* aBufConfig,TLinAddr aChunkBase,TInt aDeviceHandle); |
|
135 TWaveformAudioBuf* AcquireBuf(char* aStartAddress,TInt aBufLength,TInt aDeviceHandle); |
|
136 public: |
|
137 /** The array of windows waveform audio buffer objects. There is at least one buffer object per buffer within the |
|
138 LDD shared chunk. */ |
|
139 TWaveformAudioBuf* iWaveformAudioBuf; |
|
140 /** The count of the number of audio play buffers in the waveform buffer array. */ |
|
141 TInt iNumWaveformBufs; |
|
142 /** The default size of each audio buffer in the waveform buffer array. */ |
|
143 TInt iWaveformBufSize; |
|
144 /** List of waveform audio buffer objects waiting to be played/recorded - in FIFO order. Used only when |
|
145 no audio hardware is present.*/ |
|
146 WAVEHDR** iPendingBufList; |
|
147 /** Set when no audio hardware is present. */ |
|
148 TBool iIsHardware; |
|
149 /** The direction of the windows waveform audio buffer, record or playback. */ |
|
150 TSoundDirection iDirection; |
|
151 }; |
|
152 |
|
153 /** |
|
154 The WINS physical device (factory class) for the shared chunk sound driver. |
|
155 */ |
|
156 class DWinsSoundScPddFactory : public DPhysicalDevice |
|
157 { |
|
158 public: |
|
159 DWinsSoundScPddFactory(); |
|
160 ~DWinsSoundScPddFactory(); |
|
161 virtual TInt Install(); |
|
162 virtual void GetCaps(TDes8 &aDes) const; |
|
163 virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion &aVer); |
|
164 virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer); |
|
165 private: |
|
166 /** The DFC queue (used also by the LDD). */ |
|
167 TDynamicDfcQue* iDfcQ; |
|
168 /** DFC for terminating the DFC thread. */ |
|
169 static TDfc ExitDfc; |
|
170 friend class DWinsSoundScTxPdd; |
|
171 friend class DWinsSoundScRxPdd; |
|
172 }; |
|
173 |
|
174 /** |
|
175 The WINS physical device driver (PDD) for the playback shared chunk sound driver. |
|
176 */ |
|
177 class DWinsSoundScTxPdd : public DSoundScPdd |
|
178 { |
|
179 private: |
|
180 enum TThreadCommand {ESendData, EStop, EExit, EPause, EResume}; |
|
181 enum TCreatePlayDeviceMode {EInit,ESetConfig,EStartTransfer}; |
|
182 public: |
|
183 DWinsSoundScTxPdd(); |
|
184 ~DWinsSoundScTxPdd(); |
|
185 TInt DoCreate(DWinsSoundScPddFactory* aPhysicalDevice); |
|
186 // Implementations of the pure virtual functions inherited from DSoundScPdd. |
|
187 virtual TDfcQue* DfcQ(TInt aUnit); |
|
188 virtual void GetChunkCreateInfo(TChunkCreateInfo& aChunkCreateInfo); |
|
189 virtual void Caps(TDes8& aCapsBuf) const; |
|
190 virtual TInt MaxTransferLen() const; |
|
191 virtual TInt SetConfig(const TDesC8& aConfigBuf); |
|
192 virtual TInt SetVolume(TInt aVolume); |
|
193 virtual TInt StartTransfer(); |
|
194 virtual TInt TransferData(TUint aTransferID,TLinAddr aLinAddr,TPhysAddr aPhysAddr,TInt aNumBytes); |
|
195 virtual void StopTransfer(); |
|
196 virtual TInt PauseTransfer(); |
|
197 virtual TInt ResumeTransfer(); |
|
198 virtual TInt PowerUp(); |
|
199 virtual void PowerDown(); |
|
200 virtual TInt CustomConfig(TInt aFunction,TAny* aParam); |
|
201 virtual TInt TimeTransferred(TInt64& aTime, TInt aState); |
|
202 public: |
|
203 void WaveOutProc(WAVEHDR* aHdr); |
|
204 void PlayThread(); |
|
205 private: |
|
206 void SetCaps(); |
|
207 TInt OpenWaveOutDevice(); |
|
208 TInt CreatePlayDevice(TCreatePlayDeviceMode aMode); |
|
209 void ClosePlayDevice(); |
|
210 void PlayThreadCommand(TThreadCommand aCommand,TInt aArg0=0,TInt aArg1=0,TInt aArg2=0); |
|
211 TInt ProcessPlayCommand(TThreadCommand aCommand,TInt aArg0,TInt aArg1,TInt aArg2); |
|
212 void HandlePlayTimerEvent(); |
|
213 void HandleTransferComplete(); |
|
214 void PlayThreadNotifyDriver(TInt aError); |
|
215 void StartTimer(WAVEHDR* aBuffer); |
|
216 void StopTimer(TBool aCancelAll); |
|
217 static void PlayDfc(TAny* aPtr); |
|
218 private: |
|
219 /** A pointer to the PDD factory. */ |
|
220 DWinsSoundScPddFactory* iPhysicalDevice; |
|
221 /** The capabilities of this device. */ |
|
222 TSoundFormatsSupportedV02 iCaps; |
|
223 /** The current audio configuration of this device. */ |
|
224 TCurrentSoundFormatV02 iSoundConfig; |
|
225 /** The current setting for the play volume - a value in the range 0 to 0xFFFF. */ |
|
226 TInt iVolume; |
|
227 /** The driver thread semaphore - used by the windows thread to signal the driver thread. */ |
|
228 HANDLE iDriverThreadSem; |
|
229 /** The handle for the play windows thread. */ |
|
230 HANDLE iPlayThread; |
|
231 /** ETrue if the Windows thread is running, else EFalse. Used when shutting down to decide whether to |
|
232 signal the thread to exit. */ |
|
233 TBool iPlayThreadRunning; |
|
234 /** The play thread mutuex - to serialise acccess to the play thread creation and destruction routines. */ |
|
235 HANDLE iPlayThreadMutex; |
|
236 /** The play thread semaphore - indicates to the windows thread that the driver thread has issued a command. */ |
|
237 HANDLE iPlayThreadSem; |
|
238 /** Semaphore to synchronise between driver thread and windows thread when closing the output device. */ |
|
239 HANDLE iStopSemaphore; |
|
240 /** Semaphore to synchronise between driver thread and windows thread when closing the PDD. */ |
|
241 HANDLE iDeathSemaphore; |
|
242 /** The handle on the waveform output device. */ |
|
243 HWAVEOUT iPlayDeviceHandle; |
|
244 /** Used to transfer commands between the driver thread and the windows thread. */ |
|
245 TThreadCommand iPlayCommand; |
|
246 /** Used to transfer commands between the driver thread and the windows thread. */ |
|
247 TInt iPlayCommandArg0; |
|
248 /** Used to transfer commands between the driver thread and the windows thread. */ |
|
249 TInt iPlayCommandArg1; |
|
250 /** Used to transfer commands between the driver thread and the windows thread. */ |
|
251 TInt iPlayCommandArg2; |
|
252 // The number of outstanding data transfers on the waveform output device. */ |
|
253 TInt iPendingPlay; |
|
254 /** DFC which handes data block play completion. */ |
|
255 TDfc iDfc; |
|
256 /** A variable used to pass a value from the windows thread to the driver thread. */ |
|
257 TInt iPlayThreadError; |
|
258 /** The windows waveform audio buffer manager. */ |
|
259 TWaveformBufMgr* iWaveformBufMgr; |
|
260 /** A mask used to pass information on transfers that have just completed between the window thread and the |
|
261 driver thread. Updates to this variable typically need to happen atomically. Bit positions are converted |
|
262 into windows waveform audio buffer IDs. */ |
|
263 TUint32 iCompletedPlayBufHdrMask; |
|
264 /** Set when no audio hardware is present. */ |
|
265 TBool iNoHardware; |
|
266 /** The timer event object - indicates the 'no-hardware' timer has gone off. */ |
|
267 HANDLE iPlayTimerEvent; |
|
268 /** The identifier for the current 'no-hardware' timer event. */ |
|
269 UINT iTimerID; |
|
270 /** Indicates whether the 'no-hardware' timer is currently active. */ |
|
271 TBool iTimerActive; |
|
272 /** A variable used to save the play volume setting of the waveform output device at the point when this driver was opened. */ |
|
273 DWORD iWinWaveVolume; |
|
274 /** The number of bytes (not samples) that will be played back per second, at the current sample rate. */ |
|
275 TUint iBytesPerSecond; |
|
276 /** The simulated (ie. no hardware) microseconds played. */ |
|
277 TInt64 iSimulatedUSecPlayed; |
|
278 /** The # of milliseconds that pass per block of data that is played. */ |
|
279 UINT iSimulatedMsecDuration; |
|
280 /** The Windows system timer time at which the last block of data was played. */ |
|
281 DWORD iLastTimerEventTime; |
|
282 /** The Windows system timer time at which playback was paused. */ |
|
283 DWORD iPauseTime; |
|
284 }; |
|
285 |
|
286 /** |
|
287 The WINS physical device driver (PDD) for the record shared chunk sound driver. |
|
288 */ |
|
289 class DWinsSoundScRxPdd : public DSoundScPdd |
|
290 { |
|
291 private: |
|
292 enum TThreadCommand {ERecData, EStop, EExit, EPause, EResume}; |
|
293 public: |
|
294 DWinsSoundScRxPdd(); |
|
295 ~DWinsSoundScRxPdd(); |
|
296 TInt DoCreate(DWinsSoundScPddFactory* aPhysicalDevice); |
|
297 // Implementations of the pure virtual functions inherited from DSoundScPdd. |
|
298 virtual TDfcQue* DfcQ(TInt aUnit); |
|
299 virtual void GetChunkCreateInfo(TChunkCreateInfo& aChunkCreateInfo); |
|
300 virtual void Caps(TDes8& aCapsBuf) const; |
|
301 virtual TInt MaxTransferLen() const; |
|
302 virtual TInt SetConfig(const TDesC8& aConfigBuf); |
|
303 virtual TInt SetVolume(TInt aVolume); |
|
304 virtual TInt StartTransfer(); |
|
305 virtual TInt TransferData(TUint aTransferID,TLinAddr aLinAddr,TPhysAddr aPhysAddr,TInt aNumBytes); |
|
306 virtual void StopTransfer(); |
|
307 virtual TInt PauseTransfer(); |
|
308 virtual TInt ResumeTransfer(); |
|
309 virtual TInt PowerUp(); |
|
310 virtual void PowerDown(); |
|
311 virtual TInt CustomConfig(TInt aFunction,TAny* aParam); |
|
312 virtual TInt TimeTransferred(TInt64& aTime, TInt aState); |
|
313 public: |
|
314 void WaveInProc(WAVEHDR* aHdr); |
|
315 void RecordThread(); |
|
316 private: |
|
317 void SetCaps(); |
|
318 TInt OpenWaveInDevice(); |
|
319 TInt CreateRecordDevice(TBool aCheckDevice=EFalse); |
|
320 void CloseRecordDevice(); |
|
321 void RecordThreadCommand(TThreadCommand aCommand,TInt aArg0=0,TInt aArg1=0,TInt aArg2=0); |
|
322 TInt ProcessRecordCommand(TThreadCommand aCommand,TInt aArg0,TInt aArg1,TInt aArg2); |
|
323 void HandleRecordTimerEvent(); |
|
324 void HandleTransferComplete(); |
|
325 void RecordThreadNotifyDriver(TInt aError); |
|
326 void StartTimer(WAVEHDR* aBuffer); |
|
327 void StopTimer(TBool aCancelAll); |
|
328 static void RecordDfc(TAny* aPtr); |
|
329 private: |
|
330 /** A pointer to the PDD factory. */ |
|
331 DWinsSoundScPddFactory* iPhysicalDevice; |
|
332 /** The capabilities of this device. */ |
|
333 TSoundFormatsSupportedV02 iCaps; |
|
334 /** The current audio configuration of this device. */ |
|
335 TCurrentSoundFormatV02 iSoundConfig; |
|
336 /** The driver thread semaphore - used by the windows thread to signal the driver thread. */ |
|
337 HANDLE iDriverThreadSem; |
|
338 /** The handle for the record windows thread. */ |
|
339 HANDLE iRecordThread; |
|
340 /** ETrue if the Windows thread is running, else EFalse. Used when shutting down to decide whether to |
|
341 signal the thread to exit. */ |
|
342 TBool iRecordThreadRunning; |
|
343 /** The record thread mutuex - to serialise acccess to the record thread creation and destruction routines. */ |
|
344 HANDLE iRecordThreadMutex; |
|
345 /** The record thread semaphore - indicates to the windows thread that the driver thread has issued a command. */ |
|
346 HANDLE iRecordThreadSem; |
|
347 /** Semaphore to synchronise between driver thread and windows thread when closing the input device. */ |
|
348 HANDLE iStopSemaphore; |
|
349 /** Semaphore to synchronise between driver thread and windows thread when closing the PDD. */ |
|
350 HANDLE iDeathSemaphore; |
|
351 /** The handle on the waveform input device. */ |
|
352 HWAVEIN iRecordDeviceHandle; |
|
353 /** Used to transfer commands between the driver thread and the windows thread. */ |
|
354 TThreadCommand iRecordCommand; |
|
355 /** Used to transfer commands between the driver thread and the windows thread. */ |
|
356 TInt iRecordCommandArg0; |
|
357 /** Used to transfer commands between the driver thread and the windows thread. */ |
|
358 TInt iRecordCommandArg1; |
|
359 /** Used to transfer commands between the driver thread and the windows thread. */ |
|
360 TInt iRecordCommandArg2; |
|
361 // The number of outstanding data transfers on the waveform input device. */ |
|
362 TInt iPendingRecord; |
|
363 /** DFC which handes data block record completion. */ |
|
364 TDfc iDfc; |
|
365 /** A variable used to pass a value from the windows thread to the driver thread. */ |
|
366 TInt iRecordThreadError; |
|
367 /** The windows waveform audio buffer manager. */ |
|
368 TWaveformBufMgr* iWaveformBufMgr; |
|
369 /** A mask used to pass information on transfers that have just completed between the window thread and the |
|
370 driver thread. Updates to this variable typically need to happen atomically. Bit positions are converted |
|
371 into windows waveform audio buffer IDs. */ |
|
372 TUint32 iCompletedRecordBufHdrMask; |
|
373 /** Indicates when record mode is enabled. */ |
|
374 TBool iRecordEnabled; |
|
375 /** Set when no audio hardware is present. */ |
|
376 TBool iNoHardware; |
|
377 /** The timer event object - indicates the 'no-hardware' timer has gone off. */ |
|
378 HANDLE iRecordTimerEvent; |
|
379 /** The identifier for the current 'no-hardware' timer event. */ |
|
380 UINT iTimerID; |
|
381 /** Indicates whether the 'no-hardware' timer is currently active. */ |
|
382 TBool iTimerActive; |
|
383 /** The number of bytes (not samples) that will be recorded back per second, at the current sample rate. */ |
|
384 TUint iBytesPerSecond; |
|
385 /** The number of bytes recorded before the last pause command (when we pause the windows byte |
|
386 count is reset so we need to add this on for the TimeRecorded API). */ |
|
387 TUint iBytesRecordedBeforeLastPause; |
|
388 /** The number of recorded bytes reported to the LDD. Subtracted from the windows recorded byte count |
|
389 to calculate the last, partial buffer, transfer size */ |
|
390 TUint iBytesSincePauseReportedToLdd; |
|
391 /** The # of milliseconds that pass per block of data that is recorded. */ |
|
392 UINT iSimulatedMsecDuration; |
|
393 /** The Windows system timer time at which the last block of data was recorded. */ |
|
394 DWORD iLastTimerEventTime; |
|
395 }; |
|
396 |
|
397 #define __HOST_LOCK THostLock lock |
|
398 #define __HOST_LOCK_ON lock.Lock(); |
|
399 #define __HOST_LOCK_OFF lock.Unlock(); |
|
400 #define __COND_HOST_LOCK TCondHostLock lock |
|
401 |
|
402 #endif /* __WINSSOUNDSC_H__ */ |