1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: lib/drivers/sound/mmixer/wave.c 5 * PURPOSE: Wave Handling Functions 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "precomp.h" 10 11 // #define NDEBUG 12 #include <debug.h> 13 14 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 15 const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}}; 16 const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; 17 const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; 18 const GUID KSINTERFACESETID_Standard = {0x1A8766A0L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 19 const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 20 21 typedef struct 22 { 23 ULONG SampleRate; 24 ULONG Bit8Mono; 25 ULONG Bit8Stereo; 26 ULONG Bit16Mono; 27 ULONG Bit16Stereo; 28 }AUDIO_RANGE; 29 30 #define AUDIO_TEST_RANGE (5) 31 32 static AUDIO_RANGE TestRange[AUDIO_TEST_RANGE] = 33 { 34 { 35 11025, 36 WAVE_FORMAT_1M08, 37 WAVE_FORMAT_1S08, 38 WAVE_FORMAT_1M16, 39 WAVE_FORMAT_1S16 40 }, 41 { 42 22050, 43 WAVE_FORMAT_2M08, 44 WAVE_FORMAT_2S08, 45 WAVE_FORMAT_2M16, 46 WAVE_FORMAT_2S16 47 }, 48 { 49 44100, 50 WAVE_FORMAT_4M08, 51 WAVE_FORMAT_4S08, 52 WAVE_FORMAT_4M16, 53 WAVE_FORMAT_4S16 54 }, 55 { 56 48000, 57 WAVE_FORMAT_48M08, 58 WAVE_FORMAT_48S08, 59 WAVE_FORMAT_48M16, 60 WAVE_FORMAT_48S16 61 }, 62 { 63 96000, 64 WAVE_FORMAT_96M08, 65 WAVE_FORMAT_96S08, 66 WAVE_FORMAT_96M16, 67 WAVE_FORMAT_96S16 68 } 69 }; 70 71 PKSPIN_CONNECT 72 MMixerAllocatePinConnect( 73 IN PMIXER_CONTEXT MixerContext, 74 ULONG DataFormatSize) 75 { 76 return MixerContext->Alloc(sizeof(KSPIN_CONNECT) + DataFormatSize); 77 } 78 79 MIXER_STATUS 80 MMixerGetWaveInfoByIndexAndType( 81 IN PMIXER_LIST MixerList, 82 IN ULONG DeviceIndex, 83 IN ULONG bWaveInType, 84 OUT LPWAVE_INFO *OutWaveInfo) 85 { 86 ULONG Index = 0; 87 PLIST_ENTRY Entry, ListHead; 88 LPWAVE_INFO WaveInfo; 89 90 if (bWaveInType) 91 ListHead = &MixerList->WaveInList; 92 else 93 ListHead = &MixerList->WaveOutList; 94 95 /* get first entry */ 96 Entry = ListHead->Flink; 97 98 while(Entry != ListHead) 99 { 100 WaveInfo = (LPWAVE_INFO)CONTAINING_RECORD(Entry, WAVE_INFO, Entry); 101 102 if (Index == DeviceIndex) 103 { 104 *OutWaveInfo = WaveInfo; 105 return MM_STATUS_SUCCESS; 106 } 107 Index++; 108 Entry = Entry->Flink; 109 } 110 111 return MM_STATUS_INVALID_PARAMETER; 112 } 113 114 VOID 115 MMixerInitializeDataFormat( 116 IN PKSDATAFORMAT_WAVEFORMATEX DataFormat, 117 LPWAVEFORMATEX WaveFormatEx) 118 { 119 120 DataFormat->WaveFormatEx.wFormatTag = WaveFormatEx->wFormatTag; 121 DataFormat->WaveFormatEx.nChannels = WaveFormatEx->nChannels; 122 DataFormat->WaveFormatEx.nSamplesPerSec = WaveFormatEx->nSamplesPerSec; 123 DataFormat->WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign; 124 DataFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormatEx->nAvgBytesPerSec; 125 DataFormat->WaveFormatEx.wBitsPerSample = WaveFormatEx->wBitsPerSample; 126 DataFormat->WaveFormatEx.cbSize = 0; 127 DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX); 128 DataFormat->DataFormat.Flags = 0; 129 DataFormat->DataFormat.Reserved = 0; 130 DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; 131 132 DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 133 DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; 134 DataFormat->DataFormat.SampleSize = 4; 135 } 136 137 MIXER_STATUS 138 MMixerGetAudioPinDataRanges( 139 IN PMIXER_CONTEXT MixerContext, 140 IN HANDLE hDevice, 141 IN ULONG PinId, 142 IN OUT PKSMULTIPLE_ITEM * OutMultipleItem) 143 { 144 KSP_PIN PinProperty; 145 ULONG BytesReturned = 0; 146 MIXER_STATUS Status; 147 PKSMULTIPLE_ITEM MultipleItem; 148 149 /* retrieve size of data ranges buffer */ 150 PinProperty.Reserved = 0; 151 PinProperty.PinId = PinId; 152 PinProperty.Property.Set = KSPROPSETID_Pin; 153 PinProperty.Property.Id = KSPROPERTY_PIN_DATARANGES; 154 PinProperty.Property.Flags = KSPROPERTY_TYPE_GET; 155 156 Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)NULL, 0, &BytesReturned); 157 if (Status != MM_STATUS_MORE_ENTRIES) 158 { 159 return Status; 160 } 161 162 MultipleItem = MixerContext->Alloc(BytesReturned); 163 if (!MultipleItem) 164 { 165 /* not enough memory */ 166 return MM_STATUS_NO_MEMORY; 167 } 168 169 Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned); 170 if (Status != MM_STATUS_SUCCESS) 171 { 172 /* failed */ 173 MixerContext->Free(MultipleItem); 174 return Status; 175 } 176 177 /* save result */ 178 *OutMultipleItem = MultipleItem; 179 return Status; 180 } 181 182 MIXER_STATUS 183 MMixerFindAudioDataRange( 184 PKSMULTIPLE_ITEM MultipleItem, 185 PKSDATARANGE_AUDIO * OutDataRangeAudio) 186 { 187 ULONG Index; 188 PKSDATARANGE_AUDIO DataRangeAudio; 189 PKSDATARANGE DataRange; 190 191 DataRange = (PKSDATARANGE) (MultipleItem + 1); 192 for(Index = 0; Index < MultipleItem->Count; Index++) 193 { 194 if (DataRange->FormatSize == sizeof(KSDATARANGE_AUDIO)) 195 { 196 DataRangeAudio = (PKSDATARANGE_AUDIO)DataRange; 197 if (IsEqualGUIDAligned(&DataRangeAudio->DataRange.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO) && 198 IsEqualGUIDAligned(&DataRangeAudio->DataRange.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) && 199 IsEqualGUIDAligned(&DataRangeAudio->DataRange.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)) 200 { 201 DPRINT("Min Sample %u Max Sample %u Min Bits %u Max Bits %u Max Channel %u\n", DataRangeAudio->MinimumSampleFrequency, DataRangeAudio->MaximumSampleFrequency, 202 DataRangeAudio->MinimumBitsPerSample, DataRangeAudio->MaximumBitsPerSample, DataRangeAudio->MaximumChannels); 203 *OutDataRangeAudio = DataRangeAudio; 204 return MM_STATUS_SUCCESS; 205 } 206 } 207 DataRange = (PKSDATARANGE)((ULONG_PTR)DataRange + DataRange->FormatSize); 208 } 209 return MM_STATUS_UNSUCCESSFUL; 210 } 211 212 MIXER_STATUS 213 MMixerOpenWavePin( 214 IN PMIXER_CONTEXT MixerContext, 215 IN PMIXER_LIST MixerList, 216 IN ULONG DeviceId, 217 IN ULONG PinId, 218 IN LPWAVEFORMATEX WaveFormatEx, 219 IN ACCESS_MASK DesiredAccess, 220 IN PIN_CREATE_CALLBACK CreateCallback, 221 IN PVOID Context, 222 OUT PHANDLE PinHandle) 223 { 224 PKSPIN_CONNECT PinConnect; 225 PKSDATAFORMAT_WAVEFORMATEX DataFormat; 226 LPMIXER_DATA MixerData; 227 NTSTATUS Status; 228 MIXER_STATUS MixerStatus; 229 230 MixerData = MMixerGetDataByDeviceId(MixerList, DeviceId); 231 if (!MixerData) 232 return MM_STATUS_INVALID_PARAMETER; 233 234 /* allocate pin connect */ 235 PinConnect = MMixerAllocatePinConnect(MixerContext, sizeof(KSDATAFORMAT_WAVEFORMATEX)); 236 if (!PinConnect) 237 { 238 /* no memory */ 239 return MM_STATUS_NO_MEMORY; 240 } 241 242 /* initialize pin connect struct */ 243 MMixerInitializePinConnect(PinConnect, PinId); 244 245 /* get offset to dataformat */ 246 DataFormat = (PKSDATAFORMAT_WAVEFORMATEX) (PinConnect + 1); 247 /* initialize with requested wave format */ 248 MMixerInitializeDataFormat(DataFormat, WaveFormatEx); 249 250 if (CreateCallback) 251 { 252 /* let the callback handle the creation */ 253 MixerStatus = CreateCallback(Context, DeviceId, PinId, MixerData->hDevice, PinConnect, DesiredAccess, PinHandle); 254 } 255 else 256 { 257 /* now create the pin */ 258 Status = KsCreatePin(MixerData->hDevice, PinConnect, DesiredAccess, PinHandle); 259 260 /* normalize status */ 261 if (Status == STATUS_SUCCESS) 262 MixerStatus = MM_STATUS_SUCCESS; 263 else 264 MixerStatus = MM_STATUS_UNSUCCESSFUL; 265 } 266 267 /* free create info */ 268 MixerContext->Free(PinConnect); 269 270 /* done */ 271 return MixerStatus; 272 } 273 274 VOID 275 MMixerCheckFormat( 276 IN PKSDATARANGE_AUDIO DataRangeAudio, 277 IN LPWAVE_INFO WaveInfo, 278 IN ULONG bInput) 279 { 280 ULONG Index, SampleFrequency; 281 ULONG Result = 0; 282 283 for(Index = 0; Index < AUDIO_TEST_RANGE; Index++) 284 { 285 SampleFrequency = TestRange[Index].SampleRate; 286 287 if (DataRangeAudio->MinimumSampleFrequency <= SampleFrequency && DataRangeAudio->MaximumSampleFrequency >= SampleFrequency) 288 { 289 /* the audio adapter supports the sample frequency */ 290 if (DataRangeAudio->MinimumBitsPerSample <= 8 && DataRangeAudio->MaximumBitsPerSample >= 8) 291 { 292 Result |= TestRange[Index].Bit8Mono; 293 294 if (DataRangeAudio->MaximumChannels > 1) 295 { 296 /* check if pin supports the sample rate in 8-Bit Stereo */ 297 Result |= TestRange[Index].Bit8Stereo; 298 } 299 } 300 301 if (DataRangeAudio->MinimumBitsPerSample <= 16 && DataRangeAudio->MaximumBitsPerSample >= 16) 302 { 303 /* check if pin supports the sample rate in 16-Bit Mono */ 304 Result |= TestRange[Index].Bit16Mono; 305 306 if (DataRangeAudio->MaximumChannels > 1) 307 { 308 /* check if pin supports the sample rate in 16-Bit Stereo */ 309 Result |= TestRange[Index].Bit16Stereo; 310 } 311 } 312 } 313 } 314 315 if (bInput) 316 WaveInfo->u.InCaps.dwFormats = Result; 317 else 318 WaveInfo->u.OutCaps.dwFormats = Result; 319 320 DPRINT("Format %lx bInput %u\n", Result, bInput); 321 } 322 323 MIXER_STATUS 324 MMixerInitializeWaveInfo( 325 IN PMIXER_CONTEXT MixerContext, 326 IN PMIXER_LIST MixerList, 327 IN LPMIXER_DATA MixerData, 328 IN LPWSTR DeviceName, 329 IN ULONG bWaveIn, 330 IN ULONG PinCount, 331 IN PULONG Pins) 332 { 333 MIXER_STATUS Status; 334 PKSMULTIPLE_ITEM MultipleItem; 335 PKSDATARANGE_AUDIO DataRangeAudio; 336 LPWAVE_INFO WaveInfo; 337 338 WaveInfo = (LPWAVE_INFO)MixerContext->Alloc(sizeof(WAVE_INFO)); 339 if (!WaveInfo) 340 return MM_STATUS_NO_MEMORY; 341 342 if (PinCount > 1) 343 { 344 /* FIXME support multiple pins for wave device */ 345 DPRINT1("Implement support for multiple pins\n"); 346 //ASSERT(PinCount == 1); 347 } 348 349 /* initialize wave info */ 350 WaveInfo->DeviceId = MixerData->DeviceId; 351 WaveInfo->PinId = Pins[0]; 352 353 /* sanity check */ 354 ASSERT(wcslen(DeviceName) < MAXPNAMELEN); 355 356 /* copy device name */ 357 if (bWaveIn) 358 { 359 wcscpy(WaveInfo->u.InCaps.szPname, DeviceName); 360 } 361 else 362 { 363 wcscpy(WaveInfo->u.OutCaps.szPname, DeviceName); 364 } 365 366 /* FIXME determine manufacturer / product id */ 367 if (bWaveIn) 368 { 369 WaveInfo->u.InCaps.wMid = MM_MICROSOFT; 370 WaveInfo->u.InCaps.wPid = MM_PID_UNMAPPED; 371 WaveInfo->u.InCaps.vDriverVersion = 1; 372 } 373 else 374 { 375 WaveInfo->u.OutCaps.wMid = MM_MICROSOFT; 376 WaveInfo->u.OutCaps.wPid = MM_PID_UNMAPPED; 377 WaveInfo->u.OutCaps.vDriverVersion = 1; 378 } 379 380 /* get audio pin data ranges */ 381 Status = MMixerGetAudioPinDataRanges(MixerContext, MixerData->hDevice, Pins[0], &MultipleItem); 382 if (Status != MM_STATUS_SUCCESS) 383 { 384 /* failed to get audio pin data ranges */ 385 MixerContext->Free(WaveInfo); 386 return MM_STATUS_UNSUCCESSFUL; 387 } 388 389 /* find an KSDATARANGE_AUDIO range */ 390 Status = MMixerFindAudioDataRange(MultipleItem, &DataRangeAudio); 391 if (Status != MM_STATUS_SUCCESS) 392 { 393 /* failed to find audio pin data range */ 394 MixerContext->Free(MultipleItem); 395 MixerContext->Free(WaveInfo); 396 return MM_STATUS_UNSUCCESSFUL; 397 } 398 399 /* store channel count */ 400 if (bWaveIn) 401 { 402 WaveInfo->u.InCaps.wChannels = DataRangeAudio->MaximumChannels; 403 } 404 else 405 { 406 WaveInfo->u.OutCaps.wChannels = DataRangeAudio->MaximumChannels; 407 } 408 409 /* get all supported formats */ 410 MMixerCheckFormat(DataRangeAudio, WaveInfo, bWaveIn); 411 412 /* free dataranges buffer */ 413 MixerContext->Free(MultipleItem); 414 415 if (bWaveIn) 416 { 417 InsertTailList(&MixerList->WaveInList, &WaveInfo->Entry); 418 MixerList->WaveInListCount++; 419 } 420 else 421 { 422 InsertTailList(&MixerList->WaveOutList, &WaveInfo->Entry); 423 MixerList->WaveOutListCount++; 424 } 425 426 return MM_STATUS_SUCCESS; 427 } 428 429 MIXER_STATUS 430 MMixerOpenWave( 431 IN PMIXER_CONTEXT MixerContext, 432 IN ULONG DeviceIndex, 433 IN ULONG bWaveIn, 434 IN LPWAVEFORMATEX WaveFormat, 435 IN PIN_CREATE_CALLBACK CreateCallback, 436 IN PVOID Context, 437 OUT PHANDLE PinHandle) 438 { 439 PMIXER_LIST MixerList; 440 MIXER_STATUS Status; 441 LPWAVE_INFO WaveInfo; 442 ACCESS_MASK DesiredAccess = 0; 443 444 /* verify mixer context */ 445 Status = MMixerVerifyContext(MixerContext); 446 447 if (Status != MM_STATUS_SUCCESS) 448 { 449 /* invalid context passed */ 450 return Status; 451 } 452 453 /* grab mixer list */ 454 MixerList = (PMIXER_LIST)MixerContext->MixerContext; 455 456 if (WaveFormat->wFormatTag != WAVE_FORMAT_PCM) 457 { 458 /* not implemented */ 459 return MM_STATUS_NOT_IMPLEMENTED; 460 } 461 462 /* find destination wave */ 463 Status = MMixerGetWaveInfoByIndexAndType(MixerList, DeviceIndex, bWaveIn, &WaveInfo); 464 if (Status != MM_STATUS_SUCCESS) 465 { 466 /* failed to find wave info */ 467 return MM_STATUS_INVALID_PARAMETER; 468 } 469 470 /* get desired access */ 471 if (bWaveIn) 472 { 473 DesiredAccess |= GENERIC_READ; 474 } 475 else 476 { 477 DesiredAccess |= GENERIC_WRITE; 478 } 479 480 /* now try open the pin */ 481 return MMixerOpenWavePin(MixerContext, MixerList, WaveInfo->DeviceId, WaveInfo->PinId, WaveFormat, DesiredAccess, CreateCallback, Context, PinHandle); 482 } 483 484 MIXER_STATUS 485 MMixerWaveInCapabilities( 486 IN PMIXER_CONTEXT MixerContext, 487 IN ULONG DeviceIndex, 488 OUT LPWAVEINCAPSW Caps) 489 { 490 PMIXER_LIST MixerList; 491 MIXER_STATUS Status; 492 LPWAVE_INFO WaveInfo; 493 494 /* verify mixer context */ 495 Status = MMixerVerifyContext(MixerContext); 496 497 if (Status != MM_STATUS_SUCCESS) 498 { 499 /* invalid context passed */ 500 return Status; 501 } 502 503 /* grab mixer list */ 504 MixerList = (PMIXER_LIST)MixerContext->MixerContext; 505 506 /* find destination wave */ 507 Status = MMixerGetWaveInfoByIndexAndType(MixerList, DeviceIndex, TRUE, &WaveInfo); 508 if (Status != MM_STATUS_SUCCESS) 509 { 510 /* failed to find wave info */ 511 return MM_STATUS_UNSUCCESSFUL; 512 } 513 514 /* copy capabilities */ 515 MixerContext->Copy(Caps, &WaveInfo->u.InCaps, sizeof(WAVEINCAPSW)); 516 517 return MM_STATUS_SUCCESS; 518 } 519 520 MIXER_STATUS 521 MMixerWaveOutCapabilities( 522 IN PMIXER_CONTEXT MixerContext, 523 IN ULONG DeviceIndex, 524 OUT LPWAVEOUTCAPSW Caps) 525 { 526 PMIXER_LIST MixerList; 527 MIXER_STATUS Status; 528 LPWAVE_INFO WaveInfo; 529 530 /* verify mixer context */ 531 Status = MMixerVerifyContext(MixerContext); 532 533 if (Status != MM_STATUS_SUCCESS) 534 { 535 /* invalid context passed */ 536 return Status; 537 } 538 539 /* grab mixer list */ 540 MixerList = (PMIXER_LIST)MixerContext->MixerContext; 541 542 /* find destination wave */ 543 Status = MMixerGetWaveInfoByIndexAndType(MixerList, DeviceIndex, FALSE, &WaveInfo); 544 if (Status != MM_STATUS_SUCCESS) 545 { 546 /* failed to find wave info */ 547 return MM_STATUS_UNSUCCESSFUL; 548 } 549 550 /* copy capabilities */ 551 MixerContext->Copy(Caps, &WaveInfo->u.OutCaps, sizeof(WAVEOUTCAPSW)); 552 553 return MM_STATUS_SUCCESS; 554 } 555 556 ULONG 557 MMixerGetWaveInCount( 558 IN PMIXER_CONTEXT MixerContext) 559 { 560 PMIXER_LIST MixerList; 561 MIXER_STATUS Status; 562 563 /* verify mixer context */ 564 Status = MMixerVerifyContext(MixerContext); 565 566 if (Status != MM_STATUS_SUCCESS) 567 { 568 /* invalid context passed */ 569 return Status; 570 } 571 572 /* grab mixer list */ 573 MixerList = (PMIXER_LIST)MixerContext->MixerContext; 574 575 return MixerList->WaveInListCount; 576 } 577 578 ULONG 579 MMixerGetWaveOutCount( 580 IN PMIXER_CONTEXT MixerContext) 581 { 582 PMIXER_LIST MixerList; 583 MIXER_STATUS Status; 584 585 /* verify mixer context */ 586 Status = MMixerVerifyContext(MixerContext); 587 588 if (Status != MM_STATUS_SUCCESS) 589 { 590 /* invalid context passed */ 591 return Status; 592 } 593 594 /* grab mixer list */ 595 MixerList = (PMIXER_LIST)MixerContext->MixerContext; 596 597 return MixerList->WaveOutListCount; 598 } 599 600 MIXER_STATUS 601 MMixerSetWaveStatus( 602 IN PMIXER_CONTEXT MixerContext, 603 IN HANDLE PinHandle, 604 IN KSSTATE State) 605 { 606 KSPROPERTY Property; 607 ULONG Length; 608 MIXER_STATUS Status; 609 610 /* verify mixer context */ 611 Status = MMixerVerifyContext(MixerContext); 612 613 if (Status != MM_STATUS_SUCCESS) 614 { 615 /* invalid context passed */ 616 return Status; 617 } 618 619 /* setup property request */ 620 Property.Set = KSPROPSETID_Connection; 621 Property.Id = KSPROPERTY_CONNECTION_STATE; 622 Property.Flags = KSPROPERTY_TYPE_SET; 623 624 return MixerContext->Control(PinHandle, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &State, sizeof(KSSTATE), &Length); 625 } 626 627 MIXER_STATUS 628 MMixerSetWaveResetState( 629 IN PMIXER_CONTEXT MixerContext, 630 IN HANDLE PinHandle, 631 IN ULONG bBegin) 632 { 633 ULONG Length; 634 MIXER_STATUS Status; 635 KSRESET Reset; 636 637 /* verify mixer context */ 638 Status = MMixerVerifyContext(MixerContext); 639 640 if (Status != MM_STATUS_SUCCESS) 641 { 642 /* invalid context passed */ 643 return Status; 644 } 645 646 /* begin / stop reset */ 647 Reset = (bBegin ? KSRESET_BEGIN : KSRESET_END); 648 649 return MixerContext->Control(PinHandle, IOCTL_KS_RESET_STATE, &Reset, sizeof(KSRESET), NULL, 0, &Length); 650 } 651 652 MIXER_STATUS 653 MMixerGetWaveDevicePath( 654 IN PMIXER_CONTEXT MixerContext, 655 IN ULONG bWaveIn, 656 IN ULONG DeviceId, 657 OUT LPWSTR * DevicePath) 658 { 659 PMIXER_LIST MixerList; 660 LPMIXER_DATA MixerData; 661 LPWAVE_INFO WaveInfo; 662 SIZE_T Length; 663 MIXER_STATUS Status; 664 665 /* verify mixer context */ 666 Status = MMixerVerifyContext(MixerContext); 667 668 if (Status != MM_STATUS_SUCCESS) 669 { 670 /* invalid context passed */ 671 return Status; 672 } 673 674 /* grab mixer list */ 675 MixerList = (PMIXER_LIST)MixerContext->MixerContext; 676 677 /* find destination wave */ 678 Status = MMixerGetWaveInfoByIndexAndType(MixerList, DeviceId, bWaveIn, &WaveInfo); 679 if (Status != MM_STATUS_SUCCESS) 680 { 681 /* failed to find wave info */ 682 return MM_STATUS_INVALID_PARAMETER; 683 } 684 685 /* get associated device id */ 686 MixerData = MMixerGetDataByDeviceId(MixerList, WaveInfo->DeviceId); 687 if (!MixerData) 688 return MM_STATUS_INVALID_PARAMETER; 689 690 /* calculate length */ 691 Length = wcslen(MixerData->DeviceName)+1; 692 693 /* allocate destination buffer */ 694 *DevicePath = MixerContext->Alloc(Length * sizeof(WCHAR)); 695 696 if (!*DevicePath) 697 { 698 /* no memory */ 699 return MM_STATUS_NO_MEMORY; 700 } 701 702 /* copy device path */ 703 MixerContext->Copy(*DevicePath, MixerData->DeviceName, Length * sizeof(WCHAR)); 704 705 /* done */ 706 return MM_STATUS_SUCCESS; 707 } 708