Merge freeldr from amd64 branch:
[reactos.git] / reactos / lib / drivers / sound / mmebuddy / wave / header.c
1 /*
2 * PROJECT: ReactOS Sound System "MME Buddy" Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/sound/mmebuddy/header.c
5 *
6 * PURPOSE: Wave header preparation routines
7 *
8 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
9 */
10
11 #include <windows.h>
12 #include <mmsystem.h>
13 #include <mmddk.h>
14 #include <ntddsnd.h>
15 #include <mmebuddy.h>
16
17
18 /*
19 This structure gets used locally within functions as a way to shuttle data
20 to the sound thread. It's safe to use locally since CallSoundThread will
21 not return until the operation has been carried out.
22 */
23
24 typedef struct
25 {
26 MMWAVEHEADER_FUNC Function;
27 PWAVEHDR Header;
28 } THREADED_WAVEHEADER_PARAMETERS;
29
30
31 /*
32 Helper routines to simplify the call to the sound thread for the header
33 functions.
34 */
35
36 MMRESULT
37 WaveHeaderOperationInSoundThread(
38 PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
39 IN PVOID Parameter)
40 {
41 THREADED_WAVEHEADER_PARAMETERS* Parameters = (THREADED_WAVEHEADER_PARAMETERS*) Parameter;
42 return Parameters->Function(SoundDeviceInstance, Parameters->Header);
43 }
44
45 MMRESULT
46 WaveHeaderOperation(
47 MMWAVEHEADER_FUNC Function,
48 PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
49 PWAVEHDR Header)
50 {
51 THREADED_WAVEHEADER_PARAMETERS Parameters;
52
53 Parameters.Function = Function;
54 Parameters.Header = Header;
55
56 return CallSoundThread(SoundDeviceInstance,
57 WaveHeaderOperationInSoundThread,
58 &Parameters);
59 }
60
61
62 /*
63 The following routines are basically handlers for:
64 - WODM_PREPARE
65 - WODM_UNPREPARE
66 - WODM_WRITE
67
68 All of these calls are ultimately dealt with in the context of the
69 appropriate sound thread, so the implementation should expect itself to
70 be running in this other thread when any of these operations take place.
71 */
72
73 MMRESULT
74 PrepareWaveHeader(
75 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
76 IN PWAVEHDR Header)
77 {
78 MMRESULT Result;
79 PSOUND_DEVICE SoundDevice;
80 PMMFUNCTION_TABLE FunctionTable;
81
82 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
83 VALIDATE_MMSYS_PARAMETER( Header );
84
85 SND_TRACE(L"Preparing wave header\n");
86
87 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
88 if ( ! MMSUCCESS(Result) )
89 return TranslateInternalMmResult(Result);
90
91 Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
92 if ( ! MMSUCCESS(Result) )
93 return TranslateInternalMmResult(Result);
94
95 if ( ! FunctionTable->PrepareWaveHeader )
96 return MMSYSERR_NOTSUPPORTED;
97
98 return WaveHeaderOperation(FunctionTable->PrepareWaveHeader,
99 SoundDeviceInstance,
100 Header);
101 }
102
103 MMRESULT
104 UnprepareWaveHeader(
105 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
106 IN PWAVEHDR Header)
107 {
108 MMRESULT Result;
109 PSOUND_DEVICE SoundDevice;
110 PMMFUNCTION_TABLE FunctionTable;
111
112 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
113 VALIDATE_MMSYS_PARAMETER( Header );
114
115 SND_TRACE(L"Un-preparing wave header\n");
116
117 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
118 if ( ! MMSUCCESS(Result) )
119 return TranslateInternalMmResult(Result);
120
121 Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
122 if ( ! MMSUCCESS(Result) )
123 return TranslateInternalMmResult(Result);
124
125 if ( ! FunctionTable->UnprepareWaveHeader )
126 return MMSYSERR_NOTSUPPORTED;
127
128 return WaveHeaderOperation(FunctionTable->UnprepareWaveHeader,
129 SoundDeviceInstance,
130 Header);
131 }
132
133 MMRESULT
134 EnqueueWaveHeader(
135 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
136 IN PWAVEHDR Header)
137 {
138 MMRESULT Result;
139 PSOUND_DEVICE SoundDevice;
140 PMMFUNCTION_TABLE FunctionTable;
141
142 VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
143 VALIDATE_MMSYS_PARAMETER( Header );
144
145 SND_TRACE(L"Submitting wave header\n");
146
147 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
148 if ( ! MMSUCCESS(Result) )
149 return TranslateInternalMmResult(Result);
150
151 Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
152 if ( ! MMSUCCESS(Result) )
153 return TranslateInternalMmResult(Result);
154
155 if ( ! FunctionTable->SubmitWaveHeader )
156 return MMSYSERR_NOTSUPPORTED;
157
158 /*
159 A few minor sanity checks - any custom checks should've been carried
160 out during wave header preparation etc.
161 */
162 VALIDATE_MMSYS_PARAMETER( Header->lpData != NULL );
163 VALIDATE_MMSYS_PARAMETER( Header->dwBufferLength > 0 );
164 VALIDATE_MMSYS_PARAMETER( Header->dwFlags & WHDR_PREPARED );
165 VALIDATE_MMSYS_PARAMETER( ! Header->dwFlags & WHDR_INQUEUE );
166
167 /* Clear the "done" flag for the buffer */
168 Header->dwFlags &= ~WHDR_DONE;
169
170 Result = WaveHeaderOperation(FunctionTable->SubmitWaveHeader,
171 SoundDeviceInstance,
172 Header);
173
174 if ( ! MMSUCCESS(Result) )
175 {
176 return Result;
177 }
178
179 /* Set the "in queue" flag if everything was OK */
180 Header->dwFlags |= WHDR_INQUEUE;
181
182 return MMSYSERR_NOERROR;
183 }