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 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 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 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 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 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 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 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 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 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 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 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 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