1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: lib/drivers/sound/mmixer/mmixer.c 5 * PURPOSE: Mixer Handling Functions 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "precomp.h" 10 11 // #define NDEBUG 12 #include <debug.h> 13 14 ULONG 15 MMixerGetCount( 16 IN PMIXER_CONTEXT MixerContext) 17 { 18 PMIXER_LIST MixerList; 19 MIXER_STATUS Status; 20 21 /* verify mixer context */ 22 Status = MMixerVerifyContext(MixerContext); 23 24 if (Status != MM_STATUS_SUCCESS) 25 { 26 /* invalid context passed */ 27 return Status; 28 } 29 30 /* grab mixer list */ 31 MixerList = (PMIXER_LIST)MixerContext->MixerContext; 32 33 // return number of mixers 34 return MixerList->MixerListCount; 35 } 36 37 MIXER_STATUS 38 MMixerGetCapabilities( 39 IN PMIXER_CONTEXT MixerContext, 40 IN ULONG MixerIndex, 41 OUT LPMIXERCAPSW MixerCaps) 42 { 43 MIXER_STATUS Status; 44 LPMIXER_INFO MixerInfo; 45 46 /* verify mixer context */ 47 Status = MMixerVerifyContext(MixerContext); 48 49 if (Status != MM_STATUS_SUCCESS) 50 { 51 /* invalid context passed */ 52 return Status; 53 } 54 55 /* get mixer info */ 56 MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, MixerIndex); 57 58 if (!MixerInfo) 59 { 60 // invalid device index 61 return MM_STATUS_INVALID_PARAMETER; 62 } 63 64 MixerCaps->wMid = MixerInfo->MixCaps.wMid; 65 MixerCaps->wPid = MixerInfo->MixCaps.wPid; 66 MixerCaps->vDriverVersion = MixerInfo->MixCaps.vDriverVersion; 67 MixerCaps->fdwSupport = MixerInfo->MixCaps.fdwSupport; 68 MixerCaps->cDestinations = MixerInfo->MixCaps.cDestinations; 69 70 ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == 0); 71 wcscpy(MixerCaps->szPname, MixerInfo->MixCaps.szPname); 72 73 return MM_STATUS_SUCCESS; 74 } 75 76 MIXER_STATUS 77 MMixerOpen( 78 IN PMIXER_CONTEXT MixerContext, 79 IN ULONG MixerId, 80 IN PVOID MixerEventContext, 81 IN PMIXER_EVENT MixerEventRoutine, 82 OUT PHANDLE MixerHandle) 83 { 84 MIXER_STATUS Status; 85 LPMIXER_INFO MixerInfo; 86 87 /* verify mixer context */ 88 Status = MMixerVerifyContext(MixerContext); 89 90 if (Status != MM_STATUS_SUCCESS) 91 { 92 /* invalid context passed */ 93 DPRINT1("invalid context\n"); 94 return Status; 95 } 96 97 /* get mixer info */ 98 MixerInfo = (LPMIXER_INFO)MMixerGetMixerInfoByIndex(MixerContext, MixerId); 99 if (!MixerInfo) 100 { 101 /* invalid mixer id */ 102 DPRINT1("invalid mixer id %lu\n", MixerId); 103 return MM_STATUS_INVALID_PARAMETER; 104 } 105 106 /* add the event */ 107 Status = MMixerAddEvent(MixerContext, MixerInfo, MixerEventContext, MixerEventRoutine); 108 109 /* store result */ 110 *MixerHandle = (HANDLE)MixerInfo; 111 return MM_STATUS_SUCCESS; 112 } 113 114 MIXER_STATUS 115 MMixerClose( 116 IN PMIXER_CONTEXT MixerContext, 117 IN ULONG MixerId, 118 IN PVOID MixerEventContext, 119 IN PMIXER_EVENT MixerEventRoutine) 120 { 121 MIXER_STATUS Status; 122 LPMIXER_INFO MixerInfo; 123 124 /* verify mixer context */ 125 Status = MMixerVerifyContext(MixerContext); 126 127 if (Status != MM_STATUS_SUCCESS) 128 { 129 /* invalid context passed */ 130 DPRINT1("invalid context\n"); 131 return Status; 132 } 133 134 /* get mixer info */ 135 MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, MixerId); 136 if (!MixerInfo) 137 { 138 /* invalid mixer id */ 139 DPRINT1("invalid mixer id %lu\n", MixerId); 140 return MM_STATUS_INVALID_PARAMETER; 141 } 142 143 /* remove event from list */ 144 return MMixerRemoveEvent(MixerContext, MixerInfo, MixerEventContext, MixerEventRoutine); 145 } 146 147 MIXER_STATUS 148 MMixerGetLineInfo( 149 IN PMIXER_CONTEXT MixerContext, 150 IN HANDLE MixerHandle, 151 IN ULONG MixerId, 152 IN ULONG Flags, 153 OUT LPMIXERLINEW MixerLine) 154 { 155 MIXER_STATUS Status; 156 LPMIXER_INFO MixerInfo; 157 LPMIXERLINE_EXT MixerLineSrc; 158 ULONG DestinationLineID; 159 160 /* verify mixer context */ 161 Status = MMixerVerifyContext(MixerContext); 162 163 if (Status != MM_STATUS_SUCCESS) 164 { 165 /* invalid context passed */ 166 return Status; 167 } 168 if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER) 169 { 170 /* caller passed mixer id */ 171 MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId); 172 173 if (!MixerHandle) 174 { 175 /* invalid parameter */ 176 return MM_STATUS_INVALID_PARAMETER; 177 } 178 } 179 180 if (MixerLine->cbStruct != sizeof(MIXERLINEW)) 181 { 182 DPRINT1("MixerLine Expected %lu but got %lu\n", sizeof(MIXERLINEW), MixerLine->cbStruct); 183 return MM_STATUS_INVALID_PARAMETER; 184 } 185 186 /* clear hmixer from flags */ 187 Flags &=~MIXER_OBJECTF_HMIXER; 188 189 DPRINT("MMixerGetLineInfo MixerId %lu Flags %lu\n", MixerId, Flags); 190 191 if (Flags == MIXER_GETLINEINFOF_DESTINATION) 192 { 193 /* cast to mixer info */ 194 MixerInfo = (LPMIXER_INFO)MixerHandle; 195 196 /* calculate destination line id */ 197 DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE); 198 199 /* get destination line */ 200 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID); 201 202 if (MixerLineSrc == NULL) 203 { 204 DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations, MixerLine->dwDestination); 205 return MM_STATUS_UNSUCCESSFUL; 206 } 207 /* copy mixer line */ 208 MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW)); 209 210 /* make sure it is null terminated */ 211 MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; 212 MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; 213 MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0'; 214 215 /* done */ 216 return MM_STATUS_SUCCESS; 217 } 218 else if (Flags == MIXER_GETLINEINFOF_SOURCE) 219 { 220 /* cast to mixer info */ 221 MixerInfo = (LPMIXER_INFO)MixerHandle; 222 223 /* calculate destination line id */ 224 DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE); 225 226 /* get destination line */ 227 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID); 228 229 if (MixerLineSrc == NULL) 230 { 231 DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations, MixerLine->dwDestination); 232 return MM_STATUS_UNSUCCESSFUL; 233 } 234 235 /* check if dwSource is out of bounds */ 236 if (MixerLine->dwSource >= MixerLineSrc->Line.cConnections) 237 { 238 DPRINT1("MixerCaps Name %S MixerLineName %S Connections %lu dwSource %lu not found\n", MixerInfo->MixCaps.szPname, MixerLineSrc->Line.szName, MixerLineSrc->Line.cConnections, MixerLine->dwSource); 239 return MM_STATUS_UNSUCCESSFUL; 240 } 241 242 /* calculate destination line id */ 243 DestinationLineID = (MixerLine->dwSource * SOURCE_LINE) + MixerLine->dwDestination; 244 245 DPRINT("MixerName %S cDestinations %lu MixerLineName %S cConnections %lu dwSource %lu dwDestination %lu ID %lx\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations, 246 MixerLineSrc->Line.szName, MixerLineSrc->Line.cConnections, 247 MixerLine->dwSource, MixerLine->dwDestination, 248 DestinationLineID); 249 /* get target destination line id */ 250 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID); 251 252 /* sanity check */ 253 ASSERT(MixerLineSrc); 254 255 DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName); 256 257 /* copy mixer line */ 258 MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW)); 259 260 /* make sure it is null terminated */ 261 MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; 262 MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; 263 MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0'; 264 265 /* done */ 266 return MM_STATUS_SUCCESS; 267 } 268 else if (Flags == MIXER_GETLINEINFOF_LINEID) 269 { 270 /* cast to mixer info */ 271 MixerInfo = (LPMIXER_INFO)MixerHandle; 272 273 /* try to find line */ 274 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwLineID); 275 if (!MixerLineSrc) 276 { 277 /* invalid parameter */ 278 DPRINT1("MMixerGetLineInfo: MixerName %S Line not found 0x%lx\n", MixerInfo->MixCaps.szPname, MixerLine->dwLineID); 279 return MM_STATUS_INVALID_PARAMETER; 280 } 281 282 DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName); 283 284 /* copy mixer line*/ 285 MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW)); 286 287 /* make sure it is null terminated */ 288 MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; 289 MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; 290 MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0'; 291 292 return MM_STATUS_SUCCESS; 293 } 294 else if (Flags == MIXER_GETLINEINFOF_COMPONENTTYPE) 295 { 296 /* cast to mixer info */ 297 MixerInfo = (LPMIXER_INFO)MixerHandle; 298 299 /* find mixer line by component type */ 300 MixerLineSrc = MMixerGetSourceMixerLineByComponentType(MixerInfo, MixerLine->dwComponentType); 301 if (!MixerLineSrc) 302 { 303 DPRINT1("Failed to find component type %x\n", MixerLine->dwComponentType); 304 return MM_STATUS_UNSUCCESSFUL; 305 } 306 307 /* copy mixer line */ 308 MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW)); 309 310 /* make sure it is null terminated */ 311 MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; 312 MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; 313 MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0'; 314 315 /* done */ 316 return MM_STATUS_SUCCESS; 317 } 318 else if (Flags == MIXER_GETLINEINFOF_TARGETTYPE) 319 { 320 DPRINT1("MIXER_GETLINEINFOF_TARGETTYPE handling is unimplemented\n"); 321 } 322 else 323 { 324 DPRINT1("Unknown Flags %lx handling is unimplemented\n", Flags); 325 } 326 327 return MM_STATUS_NOT_IMPLEMENTED; 328 } 329 330 MIXER_STATUS 331 MMixerGetLineControls( 332 IN PMIXER_CONTEXT MixerContext, 333 IN HANDLE MixerHandle, 334 IN ULONG MixerId, 335 IN ULONG Flags, 336 OUT LPMIXERLINECONTROLSW MixerLineControls) 337 { 338 LPMIXER_INFO MixerInfo; 339 LPMIXERLINE_EXT MixerLineSrc; 340 LPMIXERCONTROL_EXT MixerControl; 341 MIXER_STATUS Status; 342 PLIST_ENTRY Entry; 343 ULONG Index; 344 345 /* verify mixer context */ 346 Status = MMixerVerifyContext(MixerContext); 347 348 if (Status != MM_STATUS_SUCCESS) 349 { 350 /* invalid context passed */ 351 return Status; 352 } 353 354 if (MixerLineControls->cbStruct != sizeof(MIXERLINECONTROLSW)) 355 { 356 DPRINT1("Invalid MixerLineControls cbStruct passed %lu expected %lu\n", MixerLineControls->cbStruct, sizeof(MIXERLINECONTROLSW)); 357 /* invalid parameter */ 358 return MM_STATUS_INVALID_PARAMETER; 359 } 360 361 if (MixerLineControls->cbmxctrl != sizeof(MIXERCONTROLW)) 362 { 363 DPRINT1("Invalid MixerLineControls cbmxctrl passed %lu expected %lu\n", MixerLineControls->cbmxctrl, sizeof(MIXERCONTROLW)); 364 /* invalid parameter */ 365 return MM_STATUS_INVALID_PARAMETER; 366 } 367 368 if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER) 369 { 370 /* caller passed mixer id */ 371 MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId); 372 373 if (!MixerHandle) 374 { 375 /* invalid parameter */ 376 return MM_STATUS_INVALID_PARAMETER; 377 } 378 } 379 380 Flags &= ~MIXER_OBJECTF_HMIXER; 381 382 DPRINT("MMixerGetLineControls MixerId %lu Flags %lu\n", MixerId, Flags); 383 384 if (Flags == MIXER_GETLINECONTROLSF_ALL) 385 { 386 /* cast to mixer info */ 387 MixerInfo = (LPMIXER_INFO)MixerHandle; 388 389 /* get mixer line */ 390 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID); 391 392 if (!MixerLineSrc) 393 { 394 /* invalid line id */ 395 DPRINT("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID); 396 return MM_STATUS_INVALID_PARAMETER; 397 } 398 399 if (MixerLineSrc->Line.cControls != MixerLineControls->cControls) 400 { 401 /* invalid parameter */ 402 DPRINT1("Invalid control count %lu expected %lu\n", MixerLineControls->cControls, MixerLineSrc->Line.cControls); 403 return MM_STATUS_INVALID_PARAMETER; 404 } 405 406 /* copy line control(s) */ 407 Entry = MixerLineSrc->ControlsList.Flink; 408 Index = 0; 409 while(Entry != &MixerLineSrc->ControlsList) 410 { 411 /* get mixer control */ 412 MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry); 413 414 /* copy mixer control */ 415 MixerContext->Copy(&MixerLineControls->pamxctrl[Index], &MixerControl->Control, sizeof(MIXERCONTROLW)); 416 417 /* move to next */ 418 Entry = Entry->Flink; 419 420 /* increment mixer control offset */ 421 Index++; 422 } 423 return MM_STATUS_SUCCESS; 424 } 425 else if (Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE) 426 { 427 /* cast to mixer info */ 428 MixerInfo = (LPMIXER_INFO)MixerHandle; 429 430 /* get mixer line */ 431 MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID); 432 433 if (!MixerLineSrc) 434 { 435 /* invalid line id */ 436 DPRINT1("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID); 437 return MM_STATUS_INVALID_PARAMETER; 438 } 439 440 /* sanity checks */ 441 ASSERT(MixerLineControls->cControls == 1); 442 ASSERT(MixerLineControls->cbmxctrl == sizeof(MIXERCONTROLW)); 443 ASSERT(MixerLineControls->pamxctrl != NULL); 444 445 Entry = MixerLineSrc->ControlsList.Flink; 446 while(Entry != &MixerLineSrc->ControlsList) 447 { 448 MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry); 449 if (MixerLineControls->dwControlType == MixerControl->Control.dwControlType) 450 { 451 /* found a control with that type */ 452 MixerContext->Copy(MixerLineControls->pamxctrl, &MixerControl->Control, sizeof(MIXERCONTROLW)); 453 return MM_STATUS_SUCCESS; 454 } 455 456 /* move to next entry */ 457 Entry = Entry->Flink; 458 } 459 460 DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls->dwControlType, MixerLineControls->dwLineID, MixerLineSrc->Line.cControls); 461 return MM_STATUS_UNSUCCESSFUL; 462 } 463 else if (Flags == MIXER_GETLINECONTROLSF_ONEBYID) 464 { 465 /* cast to mixer info */ 466 MixerInfo = (LPMIXER_INFO)MixerHandle; 467 468 Status = MMixerGetMixerControlById(MixerInfo, MixerLineControls->dwControlID, NULL, &MixerControl, NULL); 469 470 if (Status != MM_STATUS_SUCCESS) 471 { 472 /* invalid parameter */ 473 DPRINT("MMixerGetLineControls ControlID not found %lx\n", MixerLineControls->dwLineID); 474 return MM_STATUS_INVALID_PARAMETER; 475 } 476 477 ASSERT(MixerLineControls->cControls == 1); 478 ASSERT(MixerLineControls->cbmxctrl == sizeof(MIXERCONTROLW)); 479 ASSERT(MixerLineControls->pamxctrl != NULL); 480 481 DPRINT("MMixerGetLineControls ControlID %lx ControlType %lx Name %S\n", MixerControl->Control.dwControlID, MixerControl->Control.dwControlType, MixerControl->Control.szName); 482 483 /* copy the controls */ 484 MixerContext->Copy(MixerLineControls->pamxctrl, &MixerControl->Control, sizeof(MIXERCONTROLW)); 485 MixerLineControls->pamxctrl->szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; 486 MixerLineControls->pamxctrl->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; 487 488 return MM_STATUS_SUCCESS; 489 } 490 UNIMPLEMENTED; 491 return MM_STATUS_NOT_IMPLEMENTED; 492 } 493 494 MIXER_STATUS 495 MMixerSetControlDetails( 496 IN PMIXER_CONTEXT MixerContext, 497 IN HANDLE MixerHandle, 498 IN ULONG MixerId, 499 IN ULONG Flags, 500 OUT LPMIXERCONTROLDETAILS MixerControlDetails) 501 { 502 MIXER_STATUS Status; 503 ULONG NodeId; 504 LPMIXER_INFO MixerInfo; 505 LPMIXERLINE_EXT MixerLine; 506 LPMIXERCONTROL_EXT MixerControl; 507 508 /* verify mixer context */ 509 Status = MMixerVerifyContext(MixerContext); 510 511 if (Status != MM_STATUS_SUCCESS) 512 { 513 /* invalid context passed */ 514 DPRINT1("invalid context\n"); 515 return Status; 516 } 517 518 if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER) 519 { 520 /* caller passed mixer id */ 521 MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId); 522 523 if (!MixerHandle) 524 { 525 /* invalid parameter */ 526 DPRINT1("invalid handle\n"); 527 return MM_STATUS_INVALID_PARAMETER; 528 } 529 } 530 531 /* get mixer info */ 532 MixerInfo = (LPMIXER_INFO)MixerHandle; 533 534 /* get mixer control */ 535 Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId); 536 537 /* check for success */ 538 if (Status != MM_STATUS_SUCCESS) 539 { 540 /* failed to find control id */ 541 DPRINT1("invalid control id %lu\n", MixerControlDetails->dwControlID); 542 return MM_STATUS_INVALID_PARAMETER; 543 } 544 545 DPRINT("MMixerSetControlDetails ControlType %lx MixerControlName %S MixerLineName %S NodeID %lu\n", MixerControl->Control.dwControlType, MixerControl->Control.szName, MixerLine->Line.szName, NodeId); 546 switch(MixerControl->Control.dwControlType) 547 { 548 case MIXERCONTROL_CONTROLTYPE_MUTE: 549 Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, MixerControl, MixerLine->Line.dwLineID, MixerControlDetails, TRUE); 550 break; 551 case MIXERCONTROL_CONTROLTYPE_VOLUME: 552 Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, TRUE, MixerControl, MixerControlDetails, MixerLine); 553 break; 554 case MIXERCONTROL_CONTROLTYPE_MUX: 555 Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, TRUE, Flags, MixerControl, MixerControlDetails, MixerLine); 556 break; 557 default: 558 Status = MM_STATUS_NOT_IMPLEMENTED; 559 } 560 561 return Status; 562 } 563 564 MIXER_STATUS 565 MMixerGetControlDetails( 566 IN PMIXER_CONTEXT MixerContext, 567 IN HANDLE MixerHandle, 568 IN ULONG MixerId, 569 IN ULONG Flags, 570 OUT LPMIXERCONTROLDETAILS MixerControlDetails) 571 { 572 MIXER_STATUS Status; 573 ULONG NodeId; 574 LPMIXER_INFO MixerInfo; 575 LPMIXERLINE_EXT MixerLine; 576 LPMIXERCONTROL_EXT MixerControl; 577 578 /* verify mixer context */ 579 Status = MMixerVerifyContext(MixerContext); 580 581 if (Status != MM_STATUS_SUCCESS) 582 { 583 /* invalid context passed */ 584 return Status; 585 } 586 587 if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER) 588 { 589 /* caller passed mixer id */ 590 MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId); 591 592 if (!MixerHandle) 593 { 594 /* invalid parameter */ 595 return MM_STATUS_INVALID_PARAMETER; 596 } 597 } 598 599 /* get mixer info */ 600 MixerInfo = (LPMIXER_INFO)MixerHandle; 601 602 /* get mixer control */ 603 Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId); 604 605 /* check for success */ 606 if (Status != MM_STATUS_SUCCESS) 607 { 608 /* failed to find control id */ 609 return MM_STATUS_INVALID_PARAMETER; 610 } 611 612 switch(MixerControl->Control.dwControlType) 613 { 614 case MIXERCONTROL_CONTROLTYPE_MUTE: 615 Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, MixerControl, MixerLine->Line.dwLineID, MixerControlDetails, FALSE); 616 break; 617 case MIXERCONTROL_CONTROLTYPE_VOLUME: 618 Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, FALSE, MixerControl, MixerControlDetails, MixerLine); 619 break; 620 case MIXERCONTROL_CONTROLTYPE_ONOFF: 621 DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_ONOFF\n"); 622 break; 623 case MIXERCONTROL_CONTROLTYPE_MUX: 624 Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, FALSE, Flags, MixerControl, MixerControlDetails, MixerLine); 625 break; 626 627 default: 628 Status = MM_STATUS_NOT_IMPLEMENTED; 629 DPRINT1("ControlType %lx not implemented\n", MixerControl->Control.dwControlType); 630 } 631 632 return Status; 633 } 634 635 VOID 636 MMixerPrintMixerLineControls( 637 IN LPMIXERLINE_EXT MixerLine) 638 { 639 PLIST_ENTRY Entry; 640 LPMIXERCONTROL_EXT MixerControl; 641 ULONG Index = 0; 642 643 Entry = MixerLine->ControlsList.Flink; 644 while(Entry != &MixerLine->ControlsList) 645 { 646 MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry); 647 648 DPRINT1("\n"); 649 DPRINT1("Control Index: %lu\n", Index); 650 DPRINT("\n"); 651 DPRINT1("cbStruct %u\n", MixerControl->Control.cbStruct); 652 DPRINT1("dwControlID %lu\n", MixerControl->Control.dwControlID); 653 DPRINT1("dwControlType %lx\n", MixerControl->Control.dwControlType); 654 DPRINT1("fdwControl %lu\n", MixerControl->Control.fdwControl); 655 DPRINT1("cMultipleItems %lu\n", MixerControl->Control.cMultipleItems); 656 DPRINT1("szShortName %S\n", MixerControl->Control.szShortName); 657 DPRINT1("szName %S\n", MixerControl->Control.szName); 658 DPRINT1("Bounds.dwMinimum %lu\n", MixerControl->Control.Bounds.dwMinimum); 659 DPRINT1("Bounds.dwMaximum %lu\n", MixerControl->Control.Bounds.dwMaximum); 660 661 DPRINT1("Metrics.Reserved[0] %lu\n", MixerControl->Control.Metrics.dwReserved[0]); 662 DPRINT1("Metrics.Reserved[1] %lu\n", MixerControl->Control.Metrics.dwReserved[1]); 663 DPRINT1("Metrics.Reserved[2] %lu\n", MixerControl->Control.Metrics.dwReserved[2]); 664 DPRINT1("Metrics.Reserved[3] %lu\n", MixerControl->Control.Metrics.dwReserved[3]); 665 DPRINT1("Metrics.Reserved[4] %lu\n", MixerControl->Control.Metrics.dwReserved[4]); 666 DPRINT1("Metrics.Reserved[5] %lu\n", MixerControl->Control.Metrics.dwReserved[5]); 667 668 Entry = Entry->Flink; 669 Index++; 670 } 671 } 672 673 VOID 674 MMixerPrintMixers( 675 IN PMIXER_CONTEXT MixerContext, 676 IN PMIXER_LIST MixerList) 677 { 678 ULONG Index, SubIndex, DestinationLineID, SrcIndex; 679 LPMIXER_INFO MixerInfo; 680 LPMIXERLINE_EXT DstMixerLine, SrcMixerLine; 681 682 DPRINT1("MixerList %p\n", MixerList); 683 DPRINT1("MidiInCount %lu\n", MixerList->MidiInListCount); 684 DPRINT1("MidiOutCount %lu\n", MixerList->MidiOutListCount); 685 DPRINT1("WaveInCount %lu\n", MixerList->WaveInListCount); 686 DPRINT1("WaveOutCount %lu\n", MixerList->WaveOutListCount); 687 DPRINT1("MixerCount %p\n", MixerList->MixerListCount); 688 689 for(Index = 0; Index < MixerList->MixerListCount; Index++) 690 { 691 /* get mixer info */ 692 MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, Index); 693 694 ASSERT(MixerInfo); 695 DPRINT1("\n"); 696 DPRINT1("Name :%S\n", MixerInfo->MixCaps.szPname); 697 DPRINT1("cDestinations: %lu\n", MixerInfo->MixCaps.cDestinations); 698 DPRINT1("fdwSupport %lu\n", MixerInfo->MixCaps.fdwSupport); 699 DPRINT1("vDriverVersion %lx\n", MixerInfo->MixCaps.vDriverVersion); 700 DPRINT1("wMid %lx\n", MixerInfo->MixCaps.wMid); 701 DPRINT1("wPid %lx\n", MixerInfo->MixCaps.wPid); 702 703 for(SubIndex = 0; SubIndex < MixerInfo->MixCaps.cDestinations; SubIndex++) 704 { 705 /* calculate destination line id */ 706 DestinationLineID = (SubIndex + DESTINATION_LINE); 707 708 /* get destination line */ 709 DstMixerLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID); 710 DPRINT1("//----------------------------------------------------------------------------------------------\n"); 711 DPRINT1("\n"); 712 DPRINT1("Destination Index %lu\n", SubIndex); 713 DPRINT1("\n"); 714 DPRINT1("cChannels %lu\n", DstMixerLine->Line.cChannels); 715 DPRINT1("cConnections %lu\n", DstMixerLine->Line.cConnections); 716 DPRINT1("cControls %lu\n", DstMixerLine->Line.cControls); 717 DPRINT1("dwComponentType %lx\n", DstMixerLine->Line.dwComponentType); 718 DPRINT1("dwDestination %lu\n", DstMixerLine->Line.dwDestination); 719 DPRINT1("dwLineID %lx\n", DstMixerLine->Line.dwLineID); 720 DPRINT1("dwSource %lx\n", DstMixerLine->Line.dwSource); 721 DPRINT1("dwUser %lu\n", DstMixerLine->Line.dwUser); 722 DPRINT1("fdwLine %lu\n", DstMixerLine->Line.fdwLine); 723 DPRINT1("szName %S\n", DstMixerLine->Line.szName); 724 DPRINT1("szShortName %S\n", DstMixerLine->Line.szShortName); 725 DPRINT1("Target.dwDeviceId %lu\n", DstMixerLine->Line.Target.dwDeviceID); 726 DPRINT1("Target.dwType %lu\n", DstMixerLine->Line.Target.dwType); 727 DPRINT1("Target.szName %S\n", DstMixerLine->Line.Target.szPname); 728 DPRINT1("Target.vDriverVersion %lx\n", DstMixerLine->Line.Target.vDriverVersion); 729 DPRINT1("Target.wMid %lx\n", DstMixerLine->Line.Target.wMid ); 730 DPRINT1("Target.wPid %lx\n", DstMixerLine->Line.Target.wPid); 731 MMixerPrintMixerLineControls(DstMixerLine); 732 733 for(SrcIndex = 0; SrcIndex < DstMixerLine->Line.cConnections; SrcIndex++) 734 { 735 /* calculate destination line id */ 736 DestinationLineID = (SOURCE_LINE * SrcIndex) + SubIndex; 737 738 /* get source line */ 739 SrcMixerLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID); 740 DPRINT1("//==============================================================================================\n"); 741 DPRINT1("\n"); 742 DPRINT1("SrcLineIndex : %lu\n", SrcIndex); 743 DPRINT1("\n"); 744 DPRINT1("cChannels %lu\n", SrcMixerLine->Line.cChannels); 745 DPRINT1("cConnections %lu\n", SrcMixerLine->Line.cConnections); 746 DPRINT1("cControls %lu\n", SrcMixerLine->Line.cControls); 747 DPRINT1("dwComponentType %lx\n", SrcMixerLine->Line.dwComponentType); 748 DPRINT1("dwDestination %lu\n", SrcMixerLine->Line.dwDestination); 749 DPRINT1("dwLineID %lx\n", SrcMixerLine->Line.dwLineID); 750 DPRINT1("dwSource %lx\n", SrcMixerLine->Line.dwSource); 751 DPRINT1("dwUser %lu\n", SrcMixerLine->Line.dwUser); 752 DPRINT1("fdwLine %lu\n", SrcMixerLine->Line.fdwLine); 753 DPRINT1("szName %S\n", SrcMixerLine->Line.szName); 754 DPRINT1("szShortName %S\n", SrcMixerLine->Line.szShortName); 755 DPRINT1("Target.dwDeviceId %lu\n", SrcMixerLine->Line.Target.dwDeviceID); 756 DPRINT1("Target.dwType %lu\n", SrcMixerLine->Line.Target.dwType); 757 DPRINT1("Target.szName %S\n", SrcMixerLine->Line.Target.szPname); 758 DPRINT1("Target.vDriverVersion %lx\n", SrcMixerLine->Line.Target.vDriverVersion); 759 DPRINT1("Target.wMid %lx\n", SrcMixerLine->Line.Target.wMid ); 760 DPRINT1("Target.wPid %lx\n", SrcMixerLine->Line.Target.wPid); 761 MMixerPrintMixerLineControls(SrcMixerLine); 762 } 763 } 764 } 765 } 766 767 MIXER_STATUS 768 MMixerInitialize( 769 IN PMIXER_CONTEXT MixerContext, 770 IN PMIXER_ENUM EnumFunction, 771 IN PVOID EnumContext) 772 { 773 MIXER_STATUS Status; 774 HANDLE hMixer, hKey; 775 ULONG DeviceIndex, Count; 776 LPWSTR DeviceName; 777 LPMIXER_DATA MixerData; 778 PMIXER_LIST MixerList; 779 PLIST_ENTRY Entry; 780 781 if (!MixerContext || !EnumFunction || !EnumContext) 782 { 783 /* invalid parameter */ 784 return MM_STATUS_INVALID_PARAMETER; 785 } 786 787 if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free || !MixerContext->Open || 788 !MixerContext->AllocEventData || !MixerContext->FreeEventData || 789 !MixerContext->Close || !MixerContext->OpenKey || !MixerContext->QueryKeyValue || !MixerContext->CloseKey) 790 { 791 /* invalid parameter */ 792 return MM_STATUS_INVALID_PARAMETER; 793 } 794 795 /* allocate a mixer list */ 796 MixerList = (PMIXER_LIST)MixerContext->Alloc(sizeof(MIXER_LIST)); 797 if (!MixerList) 798 { 799 /* no memory */ 800 return MM_STATUS_NO_MEMORY; 801 } 802 803 /* initialize mixer list */ 804 MixerList->MixerListCount = 0; 805 MixerList->MixerDataCount = 0; 806 MixerList->WaveInListCount = 0; 807 MixerList->WaveOutListCount = 0; 808 MixerList->MidiInListCount = 0; 809 MixerList->MidiOutListCount = 0; 810 InitializeListHead(&MixerList->MixerList); 811 InitializeListHead(&MixerList->MixerData); 812 InitializeListHead(&MixerList->WaveInList); 813 InitializeListHead(&MixerList->WaveOutList); 814 InitializeListHead(&MixerList->MidiInList); 815 InitializeListHead(&MixerList->MidiOutList); 816 817 /* store mixer list */ 818 MixerContext->MixerContext = (PVOID)MixerList; 819 820 /* start enumerating all available devices */ 821 Count = 0; 822 DeviceIndex = 0; 823 824 do 825 { 826 /* enumerate a device */ 827 Status = EnumFunction(EnumContext, DeviceIndex, &DeviceName, &hMixer, &hKey); 828 829 if (Status != MM_STATUS_SUCCESS) 830 { 831 /* check error code */ 832 if (Status == MM_STATUS_NO_MORE_DEVICES) 833 { 834 /* enumeration has finished */ 835 break; 836 } 837 else 838 { 839 DPRINT1("Failed to enumerate device %lu\n", DeviceIndex); 840 841 /* TODO cleanup */ 842 return Status; 843 } 844 } 845 else 846 { 847 /* create a mixer data entry */ 848 Status = MMixerCreateMixerData(MixerContext, MixerList, DeviceIndex, DeviceName, hMixer, hKey); 849 if (Status != MM_STATUS_SUCCESS) 850 break; 851 } 852 853 /* increment device index */ 854 DeviceIndex++; 855 }while(TRUE); 856 857 /* now all filters have been pre-opened 858 * lets enumerate the filters 859 */ 860 Entry = MixerList->MixerData.Flink; 861 while(Entry != &MixerList->MixerData) 862 { 863 MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry); 864 MMixerSetupFilter(MixerContext, MixerList, MixerData, &Count); 865 Entry = Entry->Flink; 866 } 867 868 Entry = MixerList->MixerData.Flink; 869 while(Entry != &MixerList->MixerData) 870 { 871 MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry); 872 873 /* now handle alternative mixer types */ 874 MMixerHandleAlternativeMixers(MixerContext, MixerList, MixerData, MixerData->Topology); 875 Entry = Entry->Flink; 876 } 877 878 //MMixerPrintMixers(MixerContext, MixerList); 879 880 /* done */ 881 return MM_STATUS_SUCCESS; 882 } 883