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 592