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