1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Sound System "MME Buddy" Library
3c2c66affSColin Finck * LICENSE: GPL - See COPYING in the top level directory
4c2c66affSColin Finck * FILE: lib/drivers/sound/mmebuddy/wave/streaming.c
5c2c66affSColin Finck *
6c2c66affSColin Finck * PURPOSE: Wave streaming
7c2c66affSColin Finck *
8c2c66affSColin Finck * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
9c2c66affSColin Finck */
10c2c66affSColin Finck
11c2c66affSColin Finck #include "precomp.h"
12c2c66affSColin Finck
13c2c66affSColin Finck /*
14c2c66affSColin Finck DoWaveStreaming
15c2c66affSColin Finck Check if there is streaming to be done, and if so, do it.
16c2c66affSColin Finck */
17c2c66affSColin Finck
18c2c66affSColin Finck VOID
DoWaveStreaming(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)19c2c66affSColin Finck DoWaveStreaming(
20c2c66affSColin Finck IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
21c2c66affSColin Finck {
22c2c66affSColin Finck MMRESULT Result;
23c2c66affSColin Finck MMDEVICE_TYPE DeviceType;
24c2c66affSColin Finck PSOUND_DEVICE SoundDevice;
25c2c66affSColin Finck PMMFUNCTION_TABLE FunctionTable;
26c2c66affSColin Finck PWAVEHDR Header;
27c2c66affSColin Finck PWAVEHDR_EXTENSION HeaderExtension;
28c2c66affSColin Finck
29c2c66affSColin Finck Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
30c2c66affSColin Finck SND_ASSERT( MMSUCCESS(Result) );
31c2c66affSColin Finck
32c2c66affSColin Finck Result = GetSoundDeviceType(SoundDevice, &DeviceType);
33c2c66affSColin Finck SND_ASSERT( MMSUCCESS(Result) );
34c2c66affSColin Finck
35c2c66affSColin Finck Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
36c2c66affSColin Finck SND_ASSERT( MMSUCCESS(Result) );
37c2c66affSColin Finck SND_ASSERT( FunctionTable );
38c2c66affSColin Finck SND_ASSERT( FunctionTable->CommitWaveBuffer );
39c2c66affSColin Finck
40c2c66affSColin Finck /* No point in doing anything if no resources available to use */
41c2c66affSColin Finck if ( SoundDeviceInstance->OutstandingBuffers >= SoundDeviceInstance->BufferCount )
42c2c66affSColin Finck {
43c2c66affSColin Finck SND_TRACE(L"DoWaveStreaming: No available buffers to stream with - doing nothing\n");
44c2c66affSColin Finck return;
45c2c66affSColin Finck }
46c2c66affSColin Finck
47c2c66affSColin Finck /* Is there any work to do? */
48c2c66affSColin Finck Header = SoundDeviceInstance->HeadWaveHeader;
49c2c66affSColin Finck
50c2c66affSColin Finck if ( ! Header )
51c2c66affSColin Finck {
52c2c66affSColin Finck SND_TRACE(L"DoWaveStreaming: No work to do - doing nothing\n");
53c2c66affSColin Finck return;
54c2c66affSColin Finck }
55c2c66affSColin Finck
56*24e088daSOleg Dubinskiy /* Do we need to loop a header? */
57*24e088daSOleg Dubinskiy if (DeviceType == WAVE_OUT_DEVICE_TYPE && (Header->dwFlags & WHDR_BEGINLOOP))
58*24e088daSOleg Dubinskiy {
59*24e088daSOleg Dubinskiy if ((Header->dwFlags & WHDR_ENDLOOP))
60*24e088daSOleg Dubinskiy {
61*24e088daSOleg Dubinskiy /* Get loop count */
62*24e088daSOleg Dubinskiy SoundDeviceInstance->LoopsRemaining = Header->dwLoops;
63*24e088daSOleg Dubinskiy }
64*24e088daSOleg Dubinskiy else
65*24e088daSOleg Dubinskiy {
66*24e088daSOleg Dubinskiy /* Report and help notice such a case */
67*24e088daSOleg Dubinskiy SND_WARN(L"Looping multiple headers is UNIMPLEMENTED. Will play once only\n");
68*24e088daSOleg Dubinskiy SND_ASSERT((Header->dwFlags & (WHDR_BEGINLOOP | WHDR_ENDLOOP)) == (WHDR_BEGINLOOP | WHDR_ENDLOOP));
69*24e088daSOleg Dubinskiy }
70*24e088daSOleg Dubinskiy }
71*24e088daSOleg Dubinskiy
72c2c66affSColin Finck while ( ( SoundDeviceInstance->OutstandingBuffers < SoundDeviceInstance->BufferCount ) &&
73c2c66affSColin Finck ( Header ) && SoundDeviceInstance->ResetInProgress == FALSE)
74c2c66affSColin Finck {
75c2c66affSColin Finck HeaderExtension = (PWAVEHDR_EXTENSION) Header->reserved;
76c2c66affSColin Finck SND_ASSERT( HeaderExtension );
77c2c66affSColin Finck
78c2c66affSColin Finck /* Saniy checks */
79c2c66affSColin Finck SND_ASSERT(Header->dwFlags & WHDR_PREPARED);
80c2c66affSColin Finck SND_ASSERT(Header->dwFlags & WHDR_INQUEUE);
81c2c66affSColin Finck
82c2c66affSColin Finck /* Can never be *above* the length */
83c2c66affSColin Finck SND_ASSERT( HeaderExtension->BytesCommitted <= Header->dwBufferLength );
84c2c66affSColin Finck
85c2c66affSColin Finck /* Is this header entirely committed? */
86c2c66affSColin Finck if ( HeaderExtension->BytesCommitted == Header->dwBufferLength )
87c2c66affSColin Finck {
88c2c66affSColin Finck {
89c2c66affSColin Finck /* Move on to the next header */
90c2c66affSColin Finck SND_ASSERT(Header != Header->lpNext);
91c2c66affSColin Finck Header = Header->lpNext;
92c2c66affSColin Finck }
93c2c66affSColin Finck }
94c2c66affSColin Finck else
95c2c66affSColin Finck {
96c2c66affSColin Finck PSOUND_OVERLAPPED Overlap;
97c2c66affSColin Finck LPVOID OffsetPtr;
98c2c66affSColin Finck DWORD BytesRemaining, BytesToCommit;
99c2c66affSColin Finck BOOL OK;
100c2c66affSColin Finck
101c2c66affSColin Finck /* Where within the header buffer to stream from */
102c2c66affSColin Finck OffsetPtr = Header->lpData + HeaderExtension->BytesCommitted;
103c2c66affSColin Finck
104c2c66affSColin Finck /* How much of this header has not been committed */
105c2c66affSColin Finck BytesRemaining = Header->dwBufferLength - HeaderExtension->BytesCommitted;
106c2c66affSColin Finck
107c2c66affSColin Finck /* We can commit anything up to the buffer size limit */
108c2c66affSColin Finck BytesToCommit = BytesRemaining > SoundDeviceInstance->FrameSize ?
109c2c66affSColin Finck SoundDeviceInstance->FrameSize :
110c2c66affSColin Finck BytesRemaining;
111c2c66affSColin Finck
112c2c66affSColin Finck /* Should always have something to commit by this point */
113c2c66affSColin Finck SND_ASSERT( BytesToCommit > 0 );
114c2c66affSColin Finck
115c2c66affSColin Finck /* We need a new overlapped info structure for each buffer */
116c2c66affSColin Finck Overlap = AllocateStruct(SOUND_OVERLAPPED);
117c2c66affSColin Finck
118c2c66affSColin Finck if ( Overlap )
119c2c66affSColin Finck {
120c2c66affSColin Finck ZeroMemory(Overlap, sizeof(SOUND_OVERLAPPED));
121c2c66affSColin Finck Overlap->SoundDeviceInstance = SoundDeviceInstance;
122c2c66affSColin Finck Overlap->Header = Header;
123c2c66affSColin Finck
124c2c66affSColin Finck /* Adjust the commit-related counters */
125c2c66affSColin Finck HeaderExtension->BytesCommitted += BytesToCommit;
126c2c66affSColin Finck ++ SoundDeviceInstance->OutstandingBuffers;
127c2c66affSColin Finck
128c2c66affSColin Finck OK = MMSUCCESS(FunctionTable->CommitWaveBuffer(SoundDeviceInstance,
129c2c66affSColin Finck OffsetPtr,
130c2c66affSColin Finck BytesToCommit,
131c2c66affSColin Finck Overlap,
132c2c66affSColin Finck CompleteIO));
133c2c66affSColin Finck
134c2c66affSColin Finck if ( ! OK )
135c2c66affSColin Finck {
136c2c66affSColin Finck /* Clean-up and try again on the next iteration (is this OK?) */
137c2c66affSColin Finck SND_WARN(L"FAILED\n");
138c2c66affSColin Finck
139c2c66affSColin Finck FreeMemory(Overlap);
140c2c66affSColin Finck HeaderExtension->BytesCommitted -= BytesToCommit;
141c2c66affSColin Finck -- SoundDeviceInstance->OutstandingBuffers;
142c2c66affSColin Finck }
143c2c66affSColin Finck }
144c2c66affSColin Finck }
145c2c66affSColin Finck }
146c2c66affSColin Finck }
147c2c66affSColin Finck
148c2c66affSColin Finck
149c2c66affSColin Finck /*
150c2c66affSColin Finck CompleteIO
151c2c66affSColin Finck An APC called as a result of a call to CommitWaveHeaderToKernelDevice.
152c2c66affSColin Finck This will count up the number of bytes which have been dealt with,
153c2c66affSColin Finck and when the entire wave header has been dealt with, will call
154c2c66affSColin Finck CompleteWaveHeader to have the wave header returned to the client.
155c2c66affSColin Finck
156c2c66affSColin Finck CommitWaveHeaderToKernelDevice
157c2c66affSColin Finck Sends portions of the buffer described by the wave header to a kernel
158c2c66affSColin Finck device. This must only be called from within the context of the sound
159c2c66affSColin Finck thread. The caller supplies either their own commit routine, or uses
160c2c66affSColin Finck WriteFileEx_Committer. The committer is called with portions of the
161c2c66affSColin Finck buffer specified in the wave header.
162c2c66affSColin Finck
163c2c66affSColin Finck WriteFileEx_Committer
164c2c66affSColin Finck Commit buffers using the WriteFileEx API.
165c2c66affSColin Finck */
166c2c66affSColin Finck
167c2c66affSColin Finck VOID CALLBACK
CompleteIO(IN DWORD dwErrorCode,IN DWORD dwNumberOfBytesTransferred,IN LPOVERLAPPED lpOverlapped)168c2c66affSColin Finck CompleteIO(
169c2c66affSColin Finck IN DWORD dwErrorCode,
170c2c66affSColin Finck IN DWORD dwNumberOfBytesTransferred,
171c2c66affSColin Finck IN LPOVERLAPPED lpOverlapped)
172c2c66affSColin Finck {
173c2c66affSColin Finck MMDEVICE_TYPE DeviceType;
174c2c66affSColin Finck PSOUND_DEVICE SoundDevice;
175c2c66affSColin Finck PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
176c2c66affSColin Finck PSOUND_OVERLAPPED SoundOverlapped = (PSOUND_OVERLAPPED) lpOverlapped;
177c2c66affSColin Finck PWAVEHDR WaveHdr;
178c2c66affSColin Finck PWAVEHDR_EXTENSION HdrExtension;
179c2c66affSColin Finck MMRESULT Result;
180c2c66affSColin Finck DWORD Bytes;
181c2c66affSColin Finck
182c2c66affSColin Finck WaveHdr = (PWAVEHDR) SoundOverlapped->Header;
183c2c66affSColin Finck SND_ASSERT( WaveHdr );
184c2c66affSColin Finck
185c2c66affSColin Finck HdrExtension = (PWAVEHDR_EXTENSION) WaveHdr->reserved;
186c2c66affSColin Finck SND_ASSERT( HdrExtension );
187c2c66affSColin Finck
188c2c66affSColin Finck SoundDeviceInstance = SoundOverlapped->SoundDeviceInstance;
189c2c66affSColin Finck
190c2c66affSColin Finck Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
191c2c66affSColin Finck SND_ASSERT( MMSUCCESS(Result) );
192c2c66affSColin Finck
193c2c66affSColin Finck Result = GetSoundDeviceType(SoundDevice, &DeviceType);
194c2c66affSColin Finck SND_ASSERT( MMSUCCESS(Result) );
195c2c66affSColin Finck
196c2c66affSColin Finck do
197c2c66affSColin Finck {
198c2c66affSColin Finck
199c2c66affSColin Finck /* We have an available buffer now */
200c2c66affSColin Finck -- SoundDeviceInstance->OutstandingBuffers;
201c2c66affSColin Finck
202c2c66affSColin Finck /* Did we finish a WAVEHDR and aren't looping? */
203c2c66affSColin Finck if (HdrExtension->BytesCompleted + dwNumberOfBytesTransferred >= WaveHdr->dwBufferLength &&
204*24e088daSOleg Dubinskiy SoundDeviceInstance->LoopsRemaining == 0)
205c2c66affSColin Finck {
206c2c66affSColin Finck /* Wave buffer fully completed */
207c2c66affSColin Finck Bytes = WaveHdr->dwBufferLength - HdrExtension->BytesCompleted;
208c2c66affSColin Finck
209c2c66affSColin Finck HdrExtension->BytesCompleted += Bytes;
210c2c66affSColin Finck dwNumberOfBytesTransferred -= Bytes;
211c2c66affSColin Finck
212c2c66affSColin Finck CompleteWaveHeader(SoundDeviceInstance, WaveHdr);
213c2c66affSColin Finck SND_TRACE(L"%d/%d bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength);
214c2c66affSColin Finck }
215c2c66affSColin Finck else
216c2c66affSColin Finck {
217*24e088daSOleg Dubinskiy /* Do we loop a header? */
218*24e088daSOleg Dubinskiy if (HdrExtension->BytesCommitted == WaveHdr->dwBufferLength &&
219*24e088daSOleg Dubinskiy SoundDeviceInstance->LoopsRemaining != 0)
220*24e088daSOleg Dubinskiy {
221*24e088daSOleg Dubinskiy /* Reset amount of bytes and decrement loop count, to play next iteration */
222*24e088daSOleg Dubinskiy HdrExtension->BytesCommitted = 0;
223*24e088daSOleg Dubinskiy
224*24e088daSOleg Dubinskiy if (SoundDeviceInstance->LoopsRemaining != INFINITE)
225*24e088daSOleg Dubinskiy --SoundDeviceInstance->LoopsRemaining;
226*24e088daSOleg Dubinskiy SND_TRACE(L"Looping the header, remaining loops %u\n", SoundDeviceInstance->LoopsRemaining);
227*24e088daSOleg Dubinskiy }
228*24e088daSOleg Dubinskiy else
229*24e088daSOleg Dubinskiy {
230c2c66affSColin Finck /* Partially completed */
231c2c66affSColin Finck HdrExtension->BytesCompleted += dwNumberOfBytesTransferred;
232*24e088daSOleg Dubinskiy SND_TRACE(L"%u/%u bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength);
233*24e088daSOleg Dubinskiy }
234*24e088daSOleg Dubinskiy
235c2c66affSColin Finck break;
236c2c66affSColin Finck }
237c2c66affSColin Finck
238c2c66affSColin Finck /* Move to next wave header */
239c2c66affSColin Finck WaveHdr = WaveHdr->lpNext;
240c2c66affSColin Finck
241c2c66affSColin Finck if (!WaveHdr)
242c2c66affSColin Finck {
243c2c66affSColin Finck /* No following WaveHdr */
244c2c66affSColin Finck SND_ASSERT(dwNumberOfBytesTransferred == 0);
245c2c66affSColin Finck break;
246c2c66affSColin Finck }
247c2c66affSColin Finck
248c2c66affSColin Finck HdrExtension = (PWAVEHDR_EXTENSION) WaveHdr->reserved;
249c2c66affSColin Finck SND_ASSERT( HdrExtension );
250c2c66affSColin Finck
251c2c66affSColin Finck
252c2c66affSColin Finck }while(dwNumberOfBytesTransferred);
253c2c66affSColin Finck
254c2c66affSColin Finck // AUDIO-BRANCH DIFF
255c2c66affSColin Finck // completion callback is performed in a thread
256c2c66affSColin Finck DoWaveStreaming(SoundDeviceInstance);
257c2c66affSColin Finck
258c2c66affSColin Finck //CompleteWavePortion(SoundDeviceInstance, dwNumberOfBytesTransferred);
259c2c66affSColin Finck
260c2c66affSColin Finck FreeMemory(lpOverlapped);
261c2c66affSColin Finck }
262c2c66affSColin Finck
263c2c66affSColin Finck MMRESULT
WriteFileEx_Committer(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,IN PVOID OffsetPtr,IN DWORD Length,IN PSOUND_OVERLAPPED Overlap,IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)264c2c66affSColin Finck WriteFileEx_Committer(
265c2c66affSColin Finck IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
266c2c66affSColin Finck IN PVOID OffsetPtr,
267c2c66affSColin Finck IN DWORD Length,
268c2c66affSColin Finck IN PSOUND_OVERLAPPED Overlap,
269c2c66affSColin Finck IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
270c2c66affSColin Finck {
271c2c66affSColin Finck HANDLE Handle;
272c2c66affSColin Finck
273c2c66affSColin Finck VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
274c2c66affSColin Finck VALIDATE_MMSYS_PARAMETER( OffsetPtr );
275c2c66affSColin Finck VALIDATE_MMSYS_PARAMETER( Overlap );
276c2c66affSColin Finck VALIDATE_MMSYS_PARAMETER( CompletionRoutine );
277c2c66affSColin Finck
278c2c66affSColin Finck GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
279c2c66affSColin Finck
280c2c66affSColin Finck if ( ! WriteFileEx(Handle, OffsetPtr, Length, (LPOVERLAPPED)Overlap, CompletionRoutine) )
281c2c66affSColin Finck {
282c2c66affSColin Finck // TODO
283c2c66affSColin Finck }
284c2c66affSColin Finck
285c2c66affSColin Finck return MMSYSERR_NOERROR;
286c2c66affSColin Finck }
287c2c66affSColin Finck
288c2c66affSColin Finck
289c2c66affSColin Finck /*
290c2c66affSColin Finck Stream control functions
291c2c66affSColin Finck (External/internal thread pairs)
292c2c66affSColin Finck
293c2c66affSColin Finck TODO - Move elsewhere as these shouldn't be wave specific!
294c2c66affSColin Finck */
295c2c66affSColin Finck
296c2c66affSColin Finck MMRESULT
StopStreamingInSoundThread(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,IN PVOID Parameter)297c2c66affSColin Finck StopStreamingInSoundThread(
298c2c66affSColin Finck IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
299c2c66affSColin Finck IN PVOID Parameter)
300c2c66affSColin Finck {
301c2c66affSColin Finck MMDEVICE_TYPE DeviceType;
302c2c66affSColin Finck PMMFUNCTION_TABLE FunctionTable;
303c2c66affSColin Finck MMRESULT Result;
304c2c66affSColin Finck PSOUND_DEVICE SoundDevice;
305c2c66affSColin Finck
306c2c66affSColin Finck /* set state reset in progress */
307c2c66affSColin Finck SoundDeviceInstance->ResetInProgress = TRUE;
308c2c66affSColin Finck
309c2c66affSColin Finck /* Get sound device */
310c2c66affSColin Finck Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
311c2c66affSColin Finck SND_ASSERT( Result == MMSYSERR_NOERROR );
312c2c66affSColin Finck
313c2c66affSColin Finck /* Obtain the function table */
314c2c66affSColin Finck Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
315c2c66affSColin Finck SND_ASSERT( Result == MMSYSERR_NOERROR );
316c2c66affSColin Finck
317c2c66affSColin Finck /* Obtain device instance type */
318c2c66affSColin Finck Result = GetSoundDeviceType(SoundDevice, &DeviceType);
319c2c66affSColin Finck SND_ASSERT( Result == MMSYSERR_NOERROR );
320c2c66affSColin Finck
321c2c66affSColin Finck /* Check if reset function is supported */
322c2c66affSColin Finck if (FunctionTable->ResetStream)
323c2c66affSColin Finck {
324c2c66affSColin Finck /* cancel all current audio buffers */
325c2c66affSColin Finck FunctionTable->ResetStream(SoundDeviceInstance, DeviceType, TRUE);
326c2c66affSColin Finck }
327c2c66affSColin Finck while(SoundDeviceInstance->OutstandingBuffers)
328c2c66affSColin Finck {
329c2c66affSColin Finck SND_TRACE(L"StopStreamingInSoundThread OutStandingBufferCount %lu\n", SoundDeviceInstance->OutstandingBuffers);
330c2c66affSColin Finck /* wait until pending i/o has completed */
331c2c66affSColin Finck SleepEx(10, TRUE);
332c2c66affSColin Finck }
333c2c66affSColin Finck
334c2c66affSColin Finck /* complete all current headers */
335c2c66affSColin Finck while( SoundDeviceInstance->HeadWaveHeader )
336c2c66affSColin Finck {
337c2c66affSColin Finck SND_TRACE(L"StopStreamingInSoundThread: Completing Header %p\n", SoundDeviceInstance->HeadWaveHeader);
338c2c66affSColin Finck CompleteWaveHeader( SoundDeviceInstance, SoundDeviceInstance->HeadWaveHeader );
339c2c66affSColin Finck }
340c2c66affSColin Finck
341c2c66affSColin Finck /* there should be no oustanding buffers now */
342c2c66affSColin Finck SND_ASSERT(SoundDeviceInstance->OutstandingBuffers == 0);
343c2c66affSColin Finck
344c2c66affSColin Finck
345c2c66affSColin Finck /* Check if reset function is supported */
346c2c66affSColin Finck if (FunctionTable->ResetStream)
347c2c66affSColin Finck {
348c2c66affSColin Finck /* finish the reset */
349c2c66affSColin Finck FunctionTable->ResetStream(SoundDeviceInstance, DeviceType, FALSE);
350c2c66affSColin Finck }
351c2c66affSColin Finck
352c2c66affSColin Finck /* clear state reset in progress */
353c2c66affSColin Finck SoundDeviceInstance->ResetInProgress = FALSE;
354c2c66affSColin Finck
355c2c66affSColin Finck
356c2c66affSColin Finck return MMSYSERR_NOERROR;
357c2c66affSColin Finck }
358c2c66affSColin Finck
359c2c66affSColin Finck MMRESULT
StopStreaming(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)360c2c66affSColin Finck StopStreaming(
361c2c66affSColin Finck IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
362c2c66affSColin Finck {
363c2c66affSColin Finck MMRESULT Result;
364c2c66affSColin Finck PSOUND_DEVICE SoundDevice;
365c2c66affSColin Finck MMDEVICE_TYPE DeviceType;
366c2c66affSColin Finck
367c2c66affSColin Finck if ( ! IsValidSoundDeviceInstance(SoundDeviceInstance) )
368c2c66affSColin Finck return MMSYSERR_INVALHANDLE;
369c2c66affSColin Finck
370c2c66affSColin Finck Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
371c2c66affSColin Finck if ( ! MMSUCCESS(Result) )
372c2c66affSColin Finck return TranslateInternalMmResult(Result);
373c2c66affSColin Finck
374c2c66affSColin Finck Result = GetSoundDeviceType(SoundDevice, &DeviceType);
375c2c66affSColin Finck if ( ! MMSUCCESS(Result) )
376c2c66affSColin Finck return TranslateInternalMmResult(Result);
377c2c66affSColin Finck
378c2c66affSColin Finck if ( DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceType != WAVE_IN_DEVICE_TYPE )
379c2c66affSColin Finck return MMSYSERR_NOTSUPPORTED;
380c2c66affSColin Finck
381c2c66affSColin Finck return CallSoundThread(SoundDeviceInstance,
382c2c66affSColin Finck StopStreamingInSoundThread,
383c2c66affSColin Finck NULL);
384c2c66affSColin Finck }
385c2c66affSColin Finck
386c2c66affSColin Finck MMRESULT
PerformWaveStreaming(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,IN PVOID Parameter)387c2c66affSColin Finck PerformWaveStreaming(
388c2c66affSColin Finck IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
389c2c66affSColin Finck IN PVOID Parameter)
390c2c66affSColin Finck {
391c2c66affSColin Finck DoWaveStreaming(SoundDeviceInstance);
392c2c66affSColin Finck
393c2c66affSColin Finck return MMSYSERR_NOERROR;
394c2c66affSColin Finck }
395c2c66affSColin Finck
396c2c66affSColin Finck DWORD
397c2c66affSColin Finck WINAPI
WaveActivateSoundStreaming(IN PVOID lpParameter)398c2c66affSColin Finck WaveActivateSoundStreaming(
399c2c66affSColin Finck IN PVOID lpParameter)
400c2c66affSColin Finck {
401c2c66affSColin Finck CallSoundThread((PSOUND_DEVICE_INSTANCE)lpParameter,
402c2c66affSColin Finck PerformWaveStreaming,
403c2c66affSColin Finck NULL);
404c2c66affSColin Finck
405c2c66affSColin Finck ExitThread(0);
406c2c66affSColin Finck }
407c2c66affSColin Finck
408c2c66affSColin Finck VOID
InitiateSoundStreaming(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)409c2c66affSColin Finck InitiateSoundStreaming(
410c2c66affSColin Finck IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
411c2c66affSColin Finck {
412c2c66affSColin Finck HANDLE hThread;
413c2c66affSColin Finck
414c2c66affSColin Finck hThread = CreateThread(NULL, 0, WaveActivateSoundStreaming, (PVOID)SoundDeviceInstance, 0, NULL);
415c2c66affSColin Finck
416c2c66affSColin Finck if (hThread != NULL)
417c2c66affSColin Finck CloseHandle(hThread);
418c2c66affSColin Finck }
419