ReactOS 0.4.16-dev-300-g2aadf2e
streaming.c File Reference
#include "precomp.h"
Include dependency graph for streaming.c:

Go to the source code of this file.

Functions

VOID DoWaveStreaming (IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
 
VOID CALLBACK CompleteIO (IN DWORD dwErrorCode, IN DWORD dwNumberOfBytesTransferred, IN LPOVERLAPPED lpOverlapped)
 
MMRESULT WriteFileEx_Committer (IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN PVOID OffsetPtr, IN DWORD Length, IN PSOUND_OVERLAPPED Overlap, IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
 
MMRESULT StopStreamingInSoundThread (IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN PVOID Parameter)
 
MMRESULT StopStreaming (IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
 
MMRESULT PerformWaveStreaming (IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN PVOID Parameter)
 
DWORD WINAPI WaveActivateSoundStreaming (IN PVOID lpParameter)
 
VOID InitiateSoundStreaming (IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
 

Function Documentation

◆ CompleteIO()

VOID CALLBACK CompleteIO ( IN DWORD  dwErrorCode,
IN DWORD  dwNumberOfBytesTransferred,
IN LPOVERLAPPED  lpOverlapped 
)

Definition at line 168 of file streaming.c.

172{
174 PSOUND_DEVICE SoundDevice;
175 PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
177 PWAVEHDR WaveHdr;
178 PWAVEHDR_EXTENSION HdrExtension;
180 DWORD Bytes;
181
182 WaveHdr = (PWAVEHDR) SoundOverlapped->Header;
183 SND_ASSERT( WaveHdr );
184
185 HdrExtension = (PWAVEHDR_EXTENSION) WaveHdr->reserved;
186 SND_ASSERT( HdrExtension );
187
188 SoundDeviceInstance = SoundOverlapped->SoundDeviceInstance;
189
190 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
192
193 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
195
196 do
197 {
198
199 /* We have an available buffer now */
200 -- SoundDeviceInstance->OutstandingBuffers;
201
202 /* Did we finish a WAVEHDR and aren't looping? */
203 if (HdrExtension->BytesCompleted + dwNumberOfBytesTransferred >= WaveHdr->dwBufferLength &&
204 SoundDeviceInstance->LoopsRemaining == 0)
205 {
206 /* Wave buffer fully completed */
207 Bytes = WaveHdr->dwBufferLength - HdrExtension->BytesCompleted;
208
209 HdrExtension->BytesCompleted += Bytes;
210 dwNumberOfBytesTransferred -= Bytes;
211
212 CompleteWaveHeader(SoundDeviceInstance, WaveHdr);
213 SND_TRACE(L"%d/%d bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength);
214 }
215 else
216 {
217 /* Do we loop a header? */
218 if (HdrExtension->BytesCommitted == WaveHdr->dwBufferLength &&
219 SoundDeviceInstance->LoopsRemaining != 0)
220 {
221 /* Reset amount of bytes and decrement loop count, to play next iteration */
222 HdrExtension->BytesCommitted = 0;
223
224 if (SoundDeviceInstance->LoopsRemaining != INFINITE)
225 --SoundDeviceInstance->LoopsRemaining;
226 SND_TRACE(L"Looping the header, remaining loops %u\n", SoundDeviceInstance->LoopsRemaining);
227 }
228 else
229 {
230 /* Partially completed */
231 HdrExtension->BytesCompleted += dwNumberOfBytesTransferred;
232 SND_TRACE(L"%u/%u bytes of wavehdr completed\n", HdrExtension->BytesCompleted, WaveHdr->dwBufferLength);
233 }
234
235 break;
236 }
237
238 /* Move to next wave header */
239 WaveHdr = WaveHdr->lpNext;
240
241 if (!WaveHdr)
242 {
243 /* No following WaveHdr */
244 SND_ASSERT(dwNumberOfBytesTransferred == 0);
245 break;
246 }
247
248 HdrExtension = (PWAVEHDR_EXTENSION) WaveHdr->reserved;
249 SND_ASSERT( HdrExtension );
250
251
252 }while(dwNumberOfBytesTransferred);
253
254 // AUDIO-BRANCH DIFF
255 // completion callback is performed in a thread
256 DoWaveStreaming(SoundDeviceInstance);
257
258 //CompleteWavePortion(SoundDeviceInstance, dwNumberOfBytesTransferred);
259
261}
static VOID FreeMemory(PCREATE_DATA Data)
Definition: create.c:134
#define INFINITE
Definition: serial.h:102
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_ UINT Bytes
Definition: mmcopy.h:9
DeviceType
Definition: mmdrv.h:42
struct _WAVEHDR_EXTENSION * PWAVEHDR_EXTENSION
struct _SOUND_OVERLAPPED * PSOUND_OVERLAPPED
UCHAR MMDEVICE_TYPE
Definition: mmebuddy.h:88
MMRESULT GetSoundDeviceFromInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, OUT PSOUND_DEVICE *SoundDevice)
MMRESULT GetSoundDeviceType(IN PSOUND_DEVICE SoundDevice, OUT PMMDEVICE_TYPE DeviceType)
Definition: devicelist.c:346
VOID CompleteWaveHeader(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN PWAVEHDR Header)
Definition: header.c:274
#define MMSUCCESS(result)
Definition: mmebuddy.h:80
#define SND_TRACE(...)
#define SND_ASSERT(condition)
UINT MMRESULT
Definition: mmsystem.h:962
struct wavehdr_tag * PWAVEHDR
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED lpOverlapped
Definition: mswsock.h:93
#define L(x)
Definition: ntvdm.h:50
VOID DoWaveStreaming(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
Definition: streaming.c:19
PWAVEHDR Header
Definition: mmebuddy.h:122
struct _SOUND_DEVICE_INSTANCE * SoundDeviceInstance
Definition: mmebuddy.h:121
DWORD BytesCommitted
Definition: mmebuddy.h:324
DWORD BytesCompleted
Definition: mmebuddy.h:325
DWORD dwBufferLength
Definition: mmsystem.h:1015
DWORD_PTR reserved
Definition: mmsystem.h:1021
struct wavehdr_tag * lpNext
Definition: mmsystem.h:1020
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409

Referenced by DoWaveStreaming().

◆ DoWaveStreaming()

VOID DoWaveStreaming ( IN PSOUND_DEVICE_INSTANCE  SoundDeviceInstance)

Definition at line 19 of file streaming.c.

21{
24 PSOUND_DEVICE SoundDevice;
27 PWAVEHDR_EXTENSION HeaderExtension;
28
29 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
31
32 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
34
38 SND_ASSERT( FunctionTable->CommitWaveBuffer );
39
40 /* No point in doing anything if no resources available to use */
41 if ( SoundDeviceInstance->OutstandingBuffers >= SoundDeviceInstance->BufferCount )
42 {
43 SND_TRACE(L"DoWaveStreaming: No available buffers to stream with - doing nothing\n");
44 return;
45 }
46
47 /* Is there any work to do? */
48 Header = SoundDeviceInstance->HeadWaveHeader;
49
50 if ( ! Header )
51 {
52 SND_TRACE(L"DoWaveStreaming: No work to do - doing nothing\n");
53 return;
54 }
55
56 /* Do we need to loop a header? */
58 {
59 if ((Header->dwFlags & WHDR_ENDLOOP))
60 {
61 /* Get loop count */
62 SoundDeviceInstance->LoopsRemaining = Header->dwLoops;
63 }
64 else
65 {
66 /* Report and help notice such a case */
67 SND_WARN(L"Looping multiple headers is UNIMPLEMENTED. Will play once only\n");
69 }
70 }
71
72 while ( ( SoundDeviceInstance->OutstandingBuffers < SoundDeviceInstance->BufferCount ) &&
73 ( Header ) && SoundDeviceInstance->ResetInProgress == FALSE)
74 {
75 HeaderExtension = (PWAVEHDR_EXTENSION) Header->reserved;
76 SND_ASSERT( HeaderExtension );
77
78 /* Saniy checks */
80 SND_ASSERT(Header->dwFlags & WHDR_INQUEUE);
81
82 /* Can never be *above* the length */
83 SND_ASSERT( HeaderExtension->BytesCommitted <= Header->dwBufferLength );
84
85 /* Is this header entirely committed? */
86 if ( HeaderExtension->BytesCommitted == Header->dwBufferLength )
87 {
88 {
89 /* Move on to the next header */
90 SND_ASSERT(Header != Header->lpNext);
91 Header = Header->lpNext;
92 }
93 }
94 else
95 {
96 PSOUND_OVERLAPPED Overlap;
97 LPVOID OffsetPtr;
98 DWORD BytesRemaining, BytesToCommit;
99 BOOL OK;
100
101 /* Where within the header buffer to stream from */
102 OffsetPtr = Header->lpData + HeaderExtension->BytesCommitted;
103
104 /* How much of this header has not been committed */
105 BytesRemaining = Header->dwBufferLength - HeaderExtension->BytesCommitted;
106
107 /* We can commit anything up to the buffer size limit */
108 BytesToCommit = BytesRemaining > SoundDeviceInstance->FrameSize ?
109 SoundDeviceInstance->FrameSize :
110 BytesRemaining;
111
112 /* Should always have something to commit by this point */
113 SND_ASSERT( BytesToCommit > 0 );
114
115 /* We need a new overlapped info structure for each buffer */
117
118 if ( Overlap )
119 {
120 ZeroMemory(Overlap, sizeof(SOUND_OVERLAPPED));
121 Overlap->SoundDeviceInstance = SoundDeviceInstance;
122 Overlap->Header = Header;
123
124 /* Adjust the commit-related counters */
125 HeaderExtension->BytesCommitted += BytesToCommit;
126 ++ SoundDeviceInstance->OutstandingBuffers;
127
128 OK = MMSUCCESS(FunctionTable->CommitWaveBuffer(SoundDeviceInstance,
129 OffsetPtr,
130 BytesToCommit,
131 Overlap,
132 CompleteIO));
133
134 if ( ! OK )
135 {
136 /* Clean-up and try again on the next iteration (is this OK?) */
137 SND_WARN(L"FAILED\n");
138
139 FreeMemory(Overlap);
140 HeaderExtension->BytesCommitted -= BytesToCommit;
141 -- SoundDeviceInstance->OutstandingBuffers;
142 }
143 }
144 }
145 }
146}
Definition: Header.h:9
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
#define AllocateStruct(thing)
Definition: mmebuddy.h:27
MMRESULT GetSoundDeviceFunctionTable(IN PSOUND_DEVICE SoundDevice, OUT PMMFUNCTION_TABLE *FunctionTable)
Definition: functiontable.c:47
#define SND_WARN(...)
#define WHDR_ENDLOOP
Definition: mmsystem.h:196
#define WHDR_INQUEUE
Definition: mmsystem.h:197
#define WHDR_BEGINLOOP
Definition: mmsystem.h:195
#define WHDR_PREPARED
Definition: mmsystem.h:194
@ WAVE_OUT_DEVICE_TYPE
Definition: sndtypes.h:29
VOID CALLBACK CompleteIO(IN DWORD dwErrorCode, IN DWORD dwNumberOfBytesTransferred, IN LPOVERLAPPED lpOverlapped)
Definition: streaming.c:168
#define OK(condition, fail_message,...)
#define ZeroMemory
Definition: winbase.h:1737
static WLX_DISPATCH_VERSION_1_4 FunctionTable
Definition: wlx.c:722

Referenced by CompleteIO(), EnqueueWaveHeader(), and PerformWaveStreaming().

◆ InitiateSoundStreaming()

VOID InitiateSoundStreaming ( IN PSOUND_DEVICE_INSTANCE  SoundDeviceInstance)

Definition at line 409 of file streaming.c.

411{
413
414 hThread = CreateThread(NULL, 0, WaveActivateSoundStreaming, (PVOID)SoundDeviceInstance, 0, NULL);
415
416 if (hThread != NULL)
418}
#define NULL
Definition: types.h:112
#define CloseHandle
Definition: compat.h:739
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
HANDLE hThread
Definition: wizard.c:28
DWORD WINAPI WaveActivateSoundStreaming(IN PVOID lpParameter)
Definition: streaming.c:398

Referenced by MmeSetState().

◆ PerformWaveStreaming()

MMRESULT PerformWaveStreaming ( IN PSOUND_DEVICE_INSTANCE  SoundDeviceInstance,
IN PVOID  Parameter 
)

Definition at line 387 of file streaming.c.

390{
391 DoWaveStreaming(SoundDeviceInstance);
392
393 return MMSYSERR_NOERROR;
394}
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96

Referenced by WaveActivateSoundStreaming().

◆ StopStreaming()

MMRESULT StopStreaming ( IN PSOUND_DEVICE_INSTANCE  SoundDeviceInstance)

Definition at line 360 of file streaming.c.

362{
364 PSOUND_DEVICE SoundDevice;
366
367 if ( ! IsValidSoundDeviceInstance(SoundDeviceInstance) )
369
370 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
371 if ( ! MMSUCCESS(Result) )
373
374 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
375 if ( ! MMSUCCESS(Result) )
377
380
381 return CallSoundThread(SoundDeviceInstance,
383 NULL);
384}
MMRESULT CallSoundThread(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN SOUND_THREAD_REQUEST_HANDLER RequestHandler, IN PVOID Parameter OPTIONAL)
Definition: thread.c:71
MMRESULT TranslateInternalMmResult(IN MMRESULT Result)
Definition: utility.c:132
BOOLEAN IsValidSoundDeviceInstance(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance)
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
#define MMSYSERR_INVALHANDLE
Definition: mmsystem.h:101
@ WAVE_IN_DEVICE_TYPE
Definition: sndtypes.h:28
MMRESULT StopStreamingInSoundThread(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN PVOID Parameter)
Definition: streaming.c:297

Referenced by MmeResetWavePlayback().

◆ StopStreamingInSoundThread()

MMRESULT StopStreamingInSoundThread ( IN PSOUND_DEVICE_INSTANCE  SoundDeviceInstance,
IN PVOID  Parameter 
)

Definition at line 297 of file streaming.c.

300{
304 PSOUND_DEVICE SoundDevice;
305
306 /* set state reset in progress */
307 SoundDeviceInstance->ResetInProgress = TRUE;
308
309 /* Get sound device */
310 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
312
313 /* Obtain the function table */
316
317 /* Obtain device instance type */
318 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
320
321 /* Check if reset function is supported */
322 if (FunctionTable->ResetStream)
323 {
324 /* cancel all current audio buffers */
325 FunctionTable->ResetStream(SoundDeviceInstance, DeviceType, TRUE);
326 }
327 while(SoundDeviceInstance->OutstandingBuffers)
328 {
329 SND_TRACE(L"StopStreamingInSoundThread OutStandingBufferCount %lu\n", SoundDeviceInstance->OutstandingBuffers);
330 /* wait until pending i/o has completed */
331 SleepEx(10, TRUE);
332 }
333
334 /* complete all current headers */
335 while( SoundDeviceInstance->HeadWaveHeader )
336 {
337 SND_TRACE(L"StopStreamingInSoundThread: Completing Header %p\n", SoundDeviceInstance->HeadWaveHeader);
338 CompleteWaveHeader( SoundDeviceInstance, SoundDeviceInstance->HeadWaveHeader );
339 }
340
341 /* there should be no oustanding buffers now */
342 SND_ASSERT(SoundDeviceInstance->OutstandingBuffers == 0);
343
344
345 /* Check if reset function is supported */
346 if (FunctionTable->ResetStream)
347 {
348 /* finish the reset */
349 FunctionTable->ResetStream(SoundDeviceInstance, DeviceType, FALSE);
350 }
351
352 /* clear state reset in progress */
353 SoundDeviceInstance->ResetInProgress = FALSE;
354
355
356 return MMSYSERR_NOERROR;
357}
#define TRUE
Definition: types.h:120
DWORD WINAPI SleepEx(IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:802

Referenced by StopStreaming().

◆ WaveActivateSoundStreaming()

DWORD WINAPI WaveActivateSoundStreaming ( IN PVOID  lpParameter)

Definition at line 398 of file streaming.c.

400{
403 NULL);
404
405 ExitThread(0);
406}
VOID WINAPI ExitThread(IN DWORD uExitCode)
Definition: thread.c:365
MMRESULT PerformWaveStreaming(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN PVOID Parameter)
Definition: streaming.c:387

Referenced by InitiateSoundStreaming().

◆ WriteFileEx_Committer()

MMRESULT WriteFileEx_Committer ( IN PSOUND_DEVICE_INSTANCE  SoundDeviceInstance,
IN PVOID  OffsetPtr,
IN DWORD  Length,
IN PSOUND_OVERLAPPED  Overlap,
IN LPOVERLAPPED_COMPLETION_ROUTINE  CompletionRoutine 
)

Definition at line 264 of file streaming.c.

270{
272
273 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
274 VALIDATE_MMSYS_PARAMETER( OffsetPtr );
275 VALIDATE_MMSYS_PARAMETER( Overlap );
277
278 GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
279
280 if ( ! WriteFileEx(Handle, OffsetPtr, Length, (LPOVERLAPPED)Overlap, CompletionRoutine) )
281 {
282 // TODO
283 }
284
285 return MMSYSERR_NOERROR;
286}
BOOL WINAPI WriteFileEx(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, IN LPOVERLAPPED lpOverlapped, IN LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
Definition: rw.c:262
ULONG Handle
Definition: gdb_input.c:15
#define VALIDATE_MMSYS_PARAMETER(parameter_condition)
Definition: mmebuddy.h:71
MMRESULT GetSoundDeviceInstanceHandle(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, OUT PVOID *Handle)
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine
Definition: wdfrequest.h:895

Referenced by FoundDevice().