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