- Start rewrite of DirectSound
[reactos.git] / reactos / dll / directx / dsound_new / misc.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Configuration of network devices
4 * FILE: dll/directx/dsound_new/misc.c
5 * PURPOSE: Misc support routines
6 *
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
8 */
9
10 #include "precomp.h"
11
12 const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
13 const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
14 const GUID KSPROPSETID_Audio = {0x45FFAAA0L, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
15
16 DWORD
17 OpenPin(
18 HANDLE hFilter,
19 ULONG PinId,
20 LPWAVEFORMATEX WaveFormatEx,
21 PHANDLE hPin,
22 BOOL bLoop)
23 {
24 DWORD Size, Result;
25 PKSPIN_CONNECT PinConnect;
26 PKSDATAFORMAT_WAVEFORMATEX DataFormat;
27
28 /* calculate request size */
29 Size = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX);
30
31 PinConnect = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
32 if (!PinConnect)
33 {
34 /* not enough memory */
35 return DSERR_OUTOFMEMORY;
36 }
37 /* build pin request */
38 PinConnect->Interface.Set = KSINTERFACESETID_Standard;
39
40 if (bLoop)
41 PinConnect->Interface.Id = KSINTERFACE_STANDARD_LOOPED_STREAMING;
42 else
43 PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING;
44
45 PinConnect->Interface.Flags = 0;
46 PinConnect->Medium.Set = KSMEDIUMSETID_Standard;
47 PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;
48 PinConnect->Medium.Flags = 0;
49 PinConnect->PinToHandle = NULL;
50 PinConnect->PinId = PinId;
51 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
52 PinConnect->Priority.PrioritySubClass = 1;
53
54 DataFormat = (PKSDATAFORMAT_WAVEFORMATEX) (PinConnect + 1);
55
56 /* initialize data format */
57 DataFormat->WaveFormatEx.wFormatTag = WaveFormatEx->wFormatTag;
58 DataFormat->WaveFormatEx.nChannels = WaveFormatEx->nChannels;
59 DataFormat->WaveFormatEx.nSamplesPerSec = WaveFormatEx->nSamplesPerSec;
60 DataFormat->WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign;
61 DataFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormatEx->nAvgBytesPerSec;
62 DataFormat->WaveFormatEx.wBitsPerSample = WaveFormatEx->wBitsPerSample;
63 DataFormat->WaveFormatEx.cbSize = 0;
64 DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
65 DataFormat->DataFormat.Flags = 0;
66 DataFormat->DataFormat.Reserved = 0;
67 DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
68
69 DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
70 DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
71 DataFormat->DataFormat.SampleSize = 4;
72
73 Result = KsCreatePin(hFilter, PinConnect, GENERIC_READ | GENERIC_WRITE, hPin);
74
75 HeapFree(GetProcessHeap(), 0, PinConnect);
76
77 return Result;
78 }
79
80
81 DWORD
82 OpenFilter(
83 IN LPCWSTR lpFileName,
84 IN PHANDLE OutHandle)
85 {
86 HANDLE Handle;
87
88 /* open the filter */
89 Handle = CreateFileW(lpFileName, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
90
91 /* check for success */
92 if (Handle == INVALID_HANDLE_VALUE)
93 {
94 DPRINT("Failed to open Filter %ws\n", lpFileName);
95 return GetLastError();
96 }
97
98 *OutHandle = Handle;
99 return ERROR_SUCCESS;
100 }
101
102 DWORD
103 SyncOverlappedDeviceIoControl(
104 IN HANDLE Handle,
105 IN DWORD IoControlCode,
106 IN LPVOID InBuffer,
107 IN DWORD InBufferSize,
108 OUT LPVOID OutBuffer,
109 IN DWORD OutBufferSize,
110 OUT LPDWORD BytesTransferred OPTIONAL)
111 {
112 OVERLAPPED Overlapped;
113 BOOLEAN IoResult;
114 DWORD Transferred;
115
116 /* Overlapped I/O is done here - this is used for waiting for completion */
117 ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
118 Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
119
120 if (!Overlapped.hEvent)
121 return GetLastError();
122
123 /* Talk to the device */
124 IoResult = DeviceIoControl(Handle,
125 IoControlCode,
126 InBuffer,
127 InBufferSize,
128 OutBuffer,
129 OutBufferSize,
130 BytesTransferred,
131 &Overlapped);
132
133 /* If failure occurs, make sure it's not just due to the overlapped I/O */
134 if (!IoResult)
135 {
136 if ( GetLastError() != ERROR_IO_PENDING )
137 {
138 CloseHandle(Overlapped.hEvent);
139 return GetLastError();
140 }
141 }
142
143 /* Wait for the I/O to complete */
144 IoResult = GetOverlappedResult(Handle,
145 &Overlapped,
146 &Transferred,
147 TRUE);
148
149 /* Don't need this any more */
150 CloseHandle(Overlapped.hEvent);
151
152 if (!IoResult)
153 return GetLastError();
154
155 if ( BytesTransferred )
156 *BytesTransferred = Transferred;
157
158 return ERROR_SUCCESS;
159 }
160
161 DWORD
162 GetFilterPinCount(
163 IN HANDLE hFilter,
164 OUT PULONG NumPins)
165 {
166 KSPROPERTY Pin;
167
168 *NumPins = 0;
169
170 /* setup the pin request */
171 Pin.Flags = KSPROPERTY_TYPE_GET;
172 Pin.Set = KSPROPSETID_Pin;
173 Pin.Id = KSPROPERTY_PIN_CTYPES;
174
175 /* query the device */
176 return SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Pin, sizeof(KSPROPERTY), (PVOID)NumPins, sizeof(ULONG), NULL);
177 }
178
179 DWORD
180 GetFilterNodeProperty(
181 IN HANDLE hFilter,
182 IN ULONG PropertyId,
183 OUT PKSMULTIPLE_ITEM *OutMultipleItem)
184 {
185 DWORD Status, BytesReturned;
186 PKSMULTIPLE_ITEM MultipleItem;
187 KSPROPERTY Property;
188
189 /* setup query request */
190 Property.Id = PropertyId;
191 Property.Flags = KSPROPERTY_TYPE_GET;
192 Property.Set = KSPROPSETID_Topology;
193
194 /* query the size */
195 Status = SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &BytesReturned);
196
197 if (Status != ERROR_MORE_DATA)
198 {
199 /* failed */
200 DPRINT("Failed to query PropertyId %lu ErrorCode %lx\n", PropertyId, Status);
201 return Status;
202 }
203
204 MultipleItem = HeapAlloc(GetProcessHeap(), 0, BytesReturned);
205 if (!MultipleItem)
206 {
207 /* not enough memory */
208 DPRINT("Failed to allocate %u Bytes\n", BytesReturned);
209 return ERROR_OUTOFMEMORY;
210 }
211
212 /* retrieve data ranges */
213 Status = SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSP_PIN), (LPVOID)MultipleItem, BytesReturned, &BytesReturned);
214
215
216 if (Status != ERROR_SUCCESS)
217 {
218 /* failed to get data ranges */
219 DPRINT("SyncOverlappedDeviceIoControl failed with %lx\n", Status);
220
221 HeapFree(GetProcessHeap(), 0, MultipleItem);
222 return Status;
223 }
224
225 /* save result */
226 *OutMultipleItem = MultipleItem;
227 return Status;
228
229 }
230
231 DWORD
232 GetFilterPinCommunication(
233 IN HANDLE hFilter,
234 IN ULONG PinId,
235 OUT PKSPIN_COMMUNICATION Communication)
236 {
237 KSP_PIN Property;
238
239 Property.Property.Flags = KSPROPERTY_TYPE_GET;
240 Property.Property.Set = KSPROPSETID_Pin;
241 Property.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
242 Property.PinId = PinId;
243 Property.Reserved = 0;
244
245 return SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSP_PIN), (LPVOID)Communication, sizeof(KSPIN_COMMUNICATION), NULL);
246 }
247
248 DWORD
249 GetFilterPinDataFlow(
250 IN HANDLE hFilter,
251 IN ULONG PinId,
252 OUT PKSPIN_DATAFLOW DataFlow)
253 {
254 KSP_PIN Property;
255
256 Property.Property.Flags = KSPROPERTY_TYPE_GET;
257 Property.Property.Set = KSPROPSETID_Pin;
258 Property.Property.Id = KSPROPERTY_PIN_DATAFLOW;
259 Property.PinId = PinId;
260 Property.Reserved = 0;
261
262 return SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSP_PIN), (LPVOID)DataFlow, sizeof(KSPIN_DATAFLOW), NULL);
263 }
264
265 DWORD
266 GetFilterPinDataRanges(
267 IN HANDLE hFilter,
268 IN ULONG PinId,
269 IN OUT PKSMULTIPLE_ITEM * OutMultipleItem)
270 {
271 KSP_PIN Property;
272 ULONG BytesReturned = 0;
273 DWORD Status;
274 PKSMULTIPLE_ITEM MultipleItem;
275
276 /* prepare request */
277 Property.Reserved = 0;
278 Property.PinId = PinId;
279 Property.Property.Set = KSPROPSETID_Pin;
280 Property.Property.Id = KSPROPERTY_PIN_DATARANGES;
281 Property.Property.Flags = KSPROPERTY_TYPE_GET;
282
283 /* retrieve size of data ranges buffer */
284 Status = SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
285
286 if (Status != ERROR_MORE_DATA)
287 {
288 DPRINT("SyncOverlappedDeviceIoControl failed with %lx\n", Status);
289 return Status;
290 }
291
292 MultipleItem = HeapAlloc(GetProcessHeap(), 0, BytesReturned);
293 if (!MultipleItem)
294 {
295 /* not enough memory */
296 DPRINT("Failed to allocate %u Bytes\n", BytesReturned);
297 return ERROR_OUTOFMEMORY;
298 }
299
300 /* retrieve data ranges */
301 Status = SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSP_PIN), (LPVOID)MultipleItem, BytesReturned, &BytesReturned);
302
303
304 if (Status != ERROR_SUCCESS)
305 {
306 /* failed to get data ranges */
307 DPRINT("SyncOverlappedDeviceIoControl failed with %lx\n", Status);
308
309 HeapFree(GetProcessHeap(), 0, MultipleItem);
310 return Status;
311 }
312
313 /* save result */
314 *OutMultipleItem = MultipleItem;
315 return Status;
316 }