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