[WINHTTP] Sync with Wine Staging 3.9. CORE-14656
[reactos.git] / 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 (johannes.anderwald@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
17 VOID
18 PerformChannelConversion(
19 PUCHAR Buffer,
20 ULONG BufferLength,
21 PULONG BytesRead,
22 ULONG OldChannels,
23 ULONG NewChannels,
24 ULONG BitsPerSample,
25 PUCHAR Result,
26 ULONG ResultLength,
27 PULONG BytesWritten)
28 {
29 DWORD Samples;
30 DWORD NewIndex, OldIndex;
31 DWORD NewLength, Skip;
32
33 Samples = BufferLength / (BitsPerSample / 8) / OldChannels;
34
35 if (NewChannels > OldChannels)
36 {
37 UNIMPLEMENTED
38 ASSERT(0);
39 }
40
41 /* setup index */
42 NewIndex = 0;
43 OldIndex = 0;
44
45 /* calculate offsets */
46 NewLength = NewChannels * (BitsPerSample/8);
47 Skip = OldChannels * (BitsPerSample/8);
48
49 do
50 {
51 if (NewIndex + NewLength>= ResultLength)
52 {
53 NewIndex = ResultLength;
54 break;
55 }
56
57 if (OldIndex + Skip >= BufferLength)
58 {
59 OldIndex = BufferLength;
60 break;
61 }
62
63 /* copy first channel */
64 RtlMoveMemory(&Result[NewIndex], &Buffer[OldIndex], NewLength);
65
66 /* skip other channels */
67 OldIndex += Skip;
68
69 /* increment offset */
70 NewIndex += NewLength;
71
72 }while(TRUE);
73
74 *BytesRead = OldIndex;
75 *BytesWritten = NewIndex;
76 }
77
78
79 BOOL
80 SetPinFormat(
81 IN HANDLE hPin,
82 IN LPWAVEFORMATEX WaveFormatEx)
83 {
84 DWORD dwResult;
85 KSPROPERTY Property;
86 KSDATAFORMAT_WAVEFORMATEX DataFormat;
87
88 /* setup connection request */
89 Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT;
90 Property.Set = KSPROPSETID_Connection;
91 Property.Flags = KSPROPERTY_TYPE_SET;
92
93 /* setup data format */
94 DataFormat.WaveFormatEx.wFormatTag = WaveFormatEx->wFormatTag;
95 DataFormat.WaveFormatEx.nSamplesPerSec = WaveFormatEx->nSamplesPerSec;
96 DataFormat.WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign;
97 DataFormat.WaveFormatEx.cbSize = 0;
98 DataFormat.DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
99 DataFormat.DataFormat.Flags = 0;
100 DataFormat.DataFormat.Reserved = 0;
101 DataFormat.DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
102 DataFormat.DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
103 DataFormat.DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
104 DataFormat.DataFormat.SampleSize = 4;
105 DataFormat.WaveFormatEx.nChannels = WaveFormatEx->nChannels;
106 DataFormat.WaveFormatEx.nAvgBytesPerSec = WaveFormatEx->nAvgBytesPerSec;
107 DataFormat.WaveFormatEx.wBitsPerSample = WaveFormatEx->wBitsPerSample;
108
109 dwResult = SyncOverlappedDeviceIoControl(hPin, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSPROPERTY),(LPVOID)&DataFormat, sizeof(KSDATAFORMAT_WAVEFORMATEX), NULL);
110
111 if (dwResult == ERROR_SUCCESS)
112 return TRUE;
113 else
114 return FALSE;
115 }
116
117
118 BOOL
119 DoDataIntersection(
120 HANDLE hFilter,
121 DWORD PinId,
122 DWORD SampleFrequency,
123 LPWAVEFORMATEX WaveFormatEx,
124 DWORD MinimumBitsPerSample,
125 DWORD MaximumBitsPerSample,
126 DWORD MaximumChannels,
127 LPWAVEFORMATEX WaveFormatOut)
128 {
129 DWORD nChannels, nBitsPerSample;
130 KSDATAFORMAT_WAVEFORMATEX WaveFormat;
131 PKSP_PIN Pin;
132 PKSMULTIPLE_ITEM Item;
133 PKSDATAFORMAT_WAVEFORMATEX DataFormat;
134 DWORD dwResult;
135
136 /* allocate request */
137 Pin = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + sizeof(KSDATAFORMAT_WAVEFORMATEX));
138 if (!Pin)
139 {
140 /* no memory */
141 return FALSE;
142 }
143
144 Item = (PKSMULTIPLE_ITEM)(Pin + 1);
145 DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)(Item + 1);
146
147 /* setup request */
148 Pin->PinId = PinId;
149 Pin->Property.Flags = KSPROPERTY_TYPE_GET;
150 Pin->Property.Set = KSPROPSETID_Pin;
151 Pin->Property.Id = KSPROPERTY_PIN_DATAINTERSECTION;
152 Item->Count = 1;
153 Item->Size = sizeof(KSDATAFORMAT_WAVEFORMATEX);
154
155
156 DataFormat->WaveFormatEx.wFormatTag = WaveFormatEx->wFormatTag;
157 DataFormat->WaveFormatEx.nSamplesPerSec = SampleFrequency;
158 DataFormat->WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign;
159 DataFormat->WaveFormatEx.cbSize = 0;
160 DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
161 DataFormat->DataFormat.Flags = 0;
162 DataFormat->DataFormat.Reserved = 0;
163 DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
164 DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
165 DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
166 DataFormat->DataFormat.SampleSize = 4;
167
168 for(nChannels = 1; nChannels <= 2; nChannels++)
169 {
170 for(nBitsPerSample = MinimumBitsPerSample; nBitsPerSample <= MaximumBitsPerSample; nBitsPerSample += 8)
171 {
172 DataFormat->WaveFormatEx.nChannels = nChannels;
173 DataFormat->WaveFormatEx.nAvgBytesPerSec = (nBitsPerSample / 8) * nChannels * SampleFrequency;
174 DataFormat->WaveFormatEx.wBitsPerSample = nBitsPerSample;
175
176 DPRINT("CurrentFormat: InFormat nChannels %u wBitsPerSample %u nSamplesPerSec %u\n",
177 nChannels, nBitsPerSample, SampleFrequency);
178
179 dwResult = SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)Pin, sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + sizeof(KSDATAFORMAT_WAVEFORMATEX),
180 (LPVOID)&WaveFormat, sizeof(KSDATAFORMAT_WAVEFORMATEX), NULL);
181
182 DPRINT("dwResult %x\n", dwResult);
183
184
185 if (dwResult == ERROR_SUCCESS)
186 {
187 /* found a compatible audio range */
188 WaveFormatOut->cbSize = 0;
189 WaveFormatOut->nBlockAlign = WaveFormatEx->nBlockAlign;
190 WaveFormatOut->wFormatTag = WaveFormatEx->wFormatTag;
191 WaveFormatOut->nAvgBytesPerSec = (nBitsPerSample / 8) * nChannels * SampleFrequency;
192 WaveFormatOut->wBitsPerSample = nBitsPerSample;
193 WaveFormatOut->nSamplesPerSec = SampleFrequency;
194 WaveFormatOut->nChannels = nChannels;
195
196 /* free buffer */
197 HeapFree(GetProcessHeap(), 0, Pin);
198
199 DPRINT("InFormat nChannels %u wBitsPerSample %u nSamplesPerSec %u\nOutFormat nChannels %u nBitsPerSample %u nSamplesPerSec %u\n",
200 WaveFormatEx->nChannels, WaveFormatEx->wBitsPerSample, WaveFormatEx->nSamplesPerSec,
201 WaveFormatOut->nChannels, WaveFormatOut->wBitsPerSample, WaveFormatOut->nSamplesPerSec);
202
203 return TRUE;
204 }
205 }
206 }
207
208 /* free buffer */
209 HeapFree(GetProcessHeap(), 0, Pin);
210 ASSERT(0);
211 return FALSE;
212 }
213
214 DWORD
215 OpenPin(
216 HANDLE hFilter,
217 ULONG PinId,
218 LPWAVEFORMATEX WaveFormatEx,
219 PHANDLE hPin,
220 BOOL bLoop)
221 {
222 DWORD Size, Result;
223 PKSPIN_CONNECT PinConnect;
224 PKSDATAFORMAT_WAVEFORMATEX DataFormat;
225
226 /* calculate request size */
227 Size = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX);
228
229 PinConnect = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
230 if (!PinConnect)
231 {
232 /* not enough memory */
233 return DSERR_OUTOFMEMORY;
234 }
235 /* build pin request */
236 PinConnect->Interface.Set = KSINTERFACESETID_Standard;
237
238 if (bLoop)
239 PinConnect->Interface.Id = KSINTERFACE_STANDARD_LOOPED_STREAMING;
240 else
241 PinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING;
242
243 PinConnect->Interface.Flags = 0;
244 PinConnect->Medium.Set = KSMEDIUMSETID_Standard;
245 PinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;
246 PinConnect->Medium.Flags = 0;
247 PinConnect->PinToHandle = NULL;
248 PinConnect->PinId = PinId;
249 PinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;
250 PinConnect->Priority.PrioritySubClass = 1;
251
252 DataFormat = (PKSDATAFORMAT_WAVEFORMATEX) (PinConnect + 1);
253
254 /* initialize data format */
255 DataFormat->WaveFormatEx.wFormatTag = WaveFormatEx->wFormatTag;
256 DataFormat->WaveFormatEx.nChannels = WaveFormatEx->nChannels;
257 DataFormat->WaveFormatEx.nSamplesPerSec = WaveFormatEx->nSamplesPerSec;
258 DataFormat->WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign;
259 DataFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormatEx->nAvgBytesPerSec;
260 DataFormat->WaveFormatEx.wBitsPerSample = WaveFormatEx->wBitsPerSample;
261 DataFormat->WaveFormatEx.cbSize = 0;
262 DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
263 DataFormat->DataFormat.Flags = 0;
264 DataFormat->DataFormat.Reserved = 0;
265 DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
266
267 DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
268 DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
269 DataFormat->DataFormat.SampleSize = 4;
270
271 Result = KsCreatePin(hFilter, PinConnect, GENERIC_READ | GENERIC_WRITE, hPin);
272
273 HeapFree(GetProcessHeap(), 0, PinConnect);
274
275 return Result;
276 }
277
278
279 DWORD
280 OpenFilter(
281 IN LPCWSTR lpFileName,
282 IN PHANDLE OutHandle)
283 {
284 HANDLE Handle;
285
286 /* open the filter */
287 Handle = CreateFileW(lpFileName, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
288
289 /* check for success */
290 if (Handle == INVALID_HANDLE_VALUE)
291 {
292 DPRINT("Failed to open Filter %ws\n", lpFileName);
293 return GetLastError();
294 }
295
296 *OutHandle = Handle;
297 return ERROR_SUCCESS;
298 }
299
300 DWORD
301 SyncOverlappedDeviceIoControl(
302 IN HANDLE Handle,
303 IN DWORD IoControlCode,
304 IN LPVOID InBuffer,
305 IN DWORD InBufferSize,
306 OUT LPVOID OutBuffer,
307 IN DWORD OutBufferSize,
308 OUT LPDWORD BytesTransferred OPTIONAL)
309 {
310 OVERLAPPED Overlapped;
311 BOOLEAN IoResult;
312 DWORD Transferred = 0;
313
314 /* Overlapped I/O is done here - this is used for waiting for completion */
315 ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
316 Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
317
318 if (!Overlapped.hEvent)
319 return GetLastError();
320
321 /* Talk to the device */
322 IoResult = DeviceIoControl(Handle,
323 IoControlCode,
324 InBuffer,
325 InBufferSize,
326 OutBuffer,
327 OutBufferSize,
328 BytesTransferred,
329 &Overlapped);
330
331 /* If failure occurs, make sure it's not just due to the overlapped I/O */
332 if (!IoResult)
333 {
334 if ( GetLastError() != ERROR_IO_PENDING )
335 {
336 CloseHandle(Overlapped.hEvent);
337 return GetLastError();
338 }
339 }
340
341 /* Wait for the I/O to complete */
342 IoResult = GetOverlappedResult(Handle,
343 &Overlapped,
344 &Transferred,
345 TRUE);
346
347 /* Don't need this any more */
348 CloseHandle(Overlapped.hEvent);
349
350 if (!IoResult)
351 return GetLastError();
352
353 if ( BytesTransferred )
354 *BytesTransferred = Transferred;
355
356 return ERROR_SUCCESS;
357 }
358
359 DWORD
360 GetFilterPinCount(
361 IN HANDLE hFilter,
362 OUT PULONG NumPins)
363 {
364 KSPROPERTY Pin;
365
366 *NumPins = 0;
367
368 /* setup the pin request */
369 Pin.Flags = KSPROPERTY_TYPE_GET;
370 Pin.Set = KSPROPSETID_Pin;
371 Pin.Id = KSPROPERTY_PIN_CTYPES;
372
373 /* query the device */
374 return SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Pin, sizeof(KSPROPERTY), (PVOID)NumPins, sizeof(ULONG), NULL);
375 }
376
377 DWORD
378 GetFilterNodeProperty(
379 IN HANDLE hFilter,
380 IN ULONG PropertyId,
381 OUT PKSMULTIPLE_ITEM *OutMultipleItem)
382 {
383 DWORD Status, BytesReturned;
384 PKSMULTIPLE_ITEM MultipleItem;
385 KSPROPERTY Property;
386
387 /* setup query request */
388 Property.Id = PropertyId;
389 Property.Flags = KSPROPERTY_TYPE_GET;
390 Property.Set = KSPROPSETID_Topology;
391
392 /* query the size */
393 Status = SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &BytesReturned);
394
395 if (Status != ERROR_MORE_DATA)
396 {
397 /* failed */
398 DPRINT("Failed to query PropertyId %lu ErrorCode %lx\n", PropertyId, Status);
399 return Status;
400 }
401
402 MultipleItem = HeapAlloc(GetProcessHeap(), 0, BytesReturned);
403 if (!MultipleItem)
404 {
405 /* not enough memory */
406 DPRINT("Failed to allocate %u Bytes\n", BytesReturned);
407 return ERROR_OUTOFMEMORY;
408 }
409
410 /* retrieve data ranges */
411 Status = SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSP_PIN), (LPVOID)MultipleItem, BytesReturned, &BytesReturned);
412
413
414 if (Status != ERROR_SUCCESS)
415 {
416 /* failed to get data ranges */
417 DPRINT("SyncOverlappedDeviceIoControl failed with %lx\n", Status);
418
419 HeapFree(GetProcessHeap(), 0, MultipleItem);
420 return Status;
421 }
422
423 /* save result */
424 *OutMultipleItem = MultipleItem;
425 return Status;
426
427 }
428
429 DWORD
430 GetFilterPinCommunication(
431 IN HANDLE hFilter,
432 IN ULONG PinId,
433 OUT PKSPIN_COMMUNICATION Communication)
434 {
435 KSP_PIN Property;
436
437 Property.Property.Flags = KSPROPERTY_TYPE_GET;
438 Property.Property.Set = KSPROPSETID_Pin;
439 Property.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
440 Property.PinId = PinId;
441 Property.Reserved = 0;
442
443 return SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSP_PIN), (LPVOID)Communication, sizeof(KSPIN_COMMUNICATION), NULL);
444 }
445
446 DWORD
447 GetFilterPinDataFlow(
448 IN HANDLE hFilter,
449 IN ULONG PinId,
450 OUT PKSPIN_DATAFLOW DataFlow)
451 {
452 KSP_PIN Property;
453
454 Property.Property.Flags = KSPROPERTY_TYPE_GET;
455 Property.Property.Set = KSPROPSETID_Pin;
456 Property.Property.Id = KSPROPERTY_PIN_DATAFLOW;
457 Property.PinId = PinId;
458 Property.Reserved = 0;
459
460 return SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSP_PIN), (LPVOID)DataFlow, sizeof(KSPIN_DATAFLOW), NULL);
461 }
462
463 DWORD
464 GetFilterPinDataRanges(
465 IN HANDLE hFilter,
466 IN ULONG PinId,
467 IN OUT PKSMULTIPLE_ITEM * OutMultipleItem)
468 {
469 KSP_PIN Property;
470 ULONG BytesReturned = 0;
471 DWORD Status;
472 PKSMULTIPLE_ITEM MultipleItem;
473
474 /* prepare request */
475 Property.Reserved = 0;
476 Property.PinId = PinId;
477 Property.Property.Set = KSPROPSETID_Pin;
478 Property.Property.Id = KSPROPERTY_PIN_DATARANGES;
479 Property.Property.Flags = KSPROPERTY_TYPE_GET;
480
481 /* retrieve size of data ranges buffer */
482 Status = SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
483
484 #if 0
485 if (Status != ERROR_MORE_DATA)
486 {
487 DPRINT("SyncOverlappedDeviceIoControl failed with %lx\n", Status);
488 return Status;
489 }
490 #endif
491
492 ASSERT(BytesReturned);
493 MultipleItem = HeapAlloc(GetProcessHeap(), 0, BytesReturned);
494 if (!MultipleItem)
495 {
496 /* not enough memory */
497 DPRINT("Failed to allocate %u Bytes\n", BytesReturned);
498 return ERROR_OUTOFMEMORY;
499 }
500
501 /* retrieve data ranges */
502 Status = SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSP_PIN), (LPVOID)MultipleItem, BytesReturned, &BytesReturned);
503
504
505 if (Status != ERROR_SUCCESS)
506 {
507 /* failed to get data ranges */
508 DPRINT("SyncOverlappedDeviceIoControl failed with %lx\n", Status);
509
510 HeapFree(GetProcessHeap(), 0, MultipleItem);
511 return Status;
512 }
513
514 /* save result */
515 *OutMultipleItem = MultipleItem;
516 return Status;
517 }
518
519 BOOL
520 CreateCompatiblePin(
521 IN HANDLE hFilter,
522 IN DWORD PinId,
523 IN BOOL bLoop,
524 IN LPWAVEFORMATEX WaveFormatEx,
525 OUT LPWAVEFORMATEX WaveFormatOut,
526 OUT PHANDLE hPin)
527 {
528 PKSMULTIPLE_ITEM Item = NULL;
529 PKSDATARANGE_AUDIO AudioRange;
530 DWORD dwResult;
531 DWORD dwIndex, nChannels;
532
533 dwResult = GetFilterPinDataRanges(hFilter, PinId, &Item);
534
535 if (dwResult != ERROR_SUCCESS)
536 {
537 /* failed to get data ranges */
538 return FALSE;
539 }
540
541 CopyMemory(WaveFormatOut, WaveFormatEx, sizeof(WAVEFORMATEX));
542
543 /* iterate through all dataranges */
544 AudioRange = (PKSDATARANGE_AUDIO)(Item + 1);
545 for(dwIndex = 0; dwIndex < Item->Count; dwIndex++)
546 {
547 if (AudioRange->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO))
548 {
549 UNIMPLEMENTED
550 AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize);
551 continue;
552 }
553
554 if (WaveFormatOut->nSamplesPerSec < AudioRange->MinimumSampleFrequency)
555 WaveFormatOut->nSamplesPerSec = AudioRange->MinimumSampleFrequency;
556 else if (WaveFormatOut->nSamplesPerSec > AudioRange->MaximumSampleFrequency)
557 WaveFormatOut->nSamplesPerSec = AudioRange->MaximumSampleFrequency;
558
559 if (WaveFormatOut->wBitsPerSample < AudioRange->MinimumBitsPerSample)
560 WaveFormatOut->wBitsPerSample = AudioRange->MinimumBitsPerSample;
561 else if (WaveFormatOut->wBitsPerSample > AudioRange->MaximumBitsPerSample)
562 WaveFormatOut->wBitsPerSample = AudioRange->MaximumBitsPerSample;
563
564 DPRINT("MinimumBitsPerSample %u MaximumBitsPerSample %u MinimumSampleFrequency %u MaximumSampleFrequency %u\n",
565 AudioRange->MinimumBitsPerSample, AudioRange->MaximumBitsPerSample, AudioRange->MinimumSampleFrequency, AudioRange->MaximumSampleFrequency);
566
567 for(nChannels = 1; nChannels <= AudioRange->MaximumChannels; nChannels++)
568 {
569 WaveFormatOut->nChannels = nChannels;
570
571 dwResult = OpenPin(hFilter, PinId, WaveFormatOut, hPin, TRUE);
572 if (dwResult == ERROR_SUCCESS)
573 {
574 DPRINT("InFormat nChannels %u wBitsPerSample %u nSamplesPerSec %u\nOutFormat nChannels %u nBitsPerSample %u nSamplesPerSec %u\n",
575 WaveFormatEx->nChannels, WaveFormatEx->wBitsPerSample, WaveFormatEx->nSamplesPerSec,
576 WaveFormatOut->nChannels, WaveFormatOut->wBitsPerSample, WaveFormatOut->nSamplesPerSec);
577
578
579 /* free buffer */
580 HeapFree(GetProcessHeap(), 0, Item);
581 return TRUE;
582 }
583 }
584 AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize);
585 }
586
587 /* free buffer */
588 HeapFree(GetProcessHeap(), 0, Item);
589 return FALSE;
590 }
591