Changeset 73467 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Aug 3, 2018 9:49:55 AM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 124094
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r73432 r73467 48 48 static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd); 49 49 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd); 50 static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM p HstStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq);51 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM p HstStream);50 static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq); 51 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 52 52 static void drvAudioStreamFree(PPDMAUDIOSTREAM pStream); 53 53 static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); … … 55 55 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 56 56 static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 57 static int drvAudioStreamLinkToInternal(PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAM pPair);57 static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 58 58 59 59 #ifndef VBOX_AUDIO_TESTCASE … … 191 191 #endif /* defined(VBOX_STRICT) || defined(LOG_ENABLED) */ 192 192 193 /**194 * Returns the host stream part of an audio stream pair, or NULL195 * if no host stream has been assigned / is not available.196 *197 * @returns IPRT status code.198 * @param pStream Audio stream to retrieve host stream part for.199 */200 DECLINLINE(PPDMAUDIOSTREAM) drvAudioGetHostStream(PPDMAUDIOSTREAM pStream)201 {202 AssertPtrReturn(pStream, NULL);203 204 if (!pStream)205 return NULL;206 207 PPDMAUDIOSTREAM pHstStream = pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST208 ? pStream209 : pStream->pPair;210 if (pHstStream)211 {212 AssertReleaseMsg(pHstStream->enmCtx == PDMAUDIOSTREAMCTX_HOST,213 ("Stream '%s' resolved as host part is not marked as such (enmCtx=%RU32)\n",214 pHstStream->szName, pHstStream->enmCtx));215 216 AssertReleaseMsg(pHstStream->pPair != NULL,217 ("Stream '%s' resolved as host part has no guest part (anymore)\n", pHstStream->szName));218 }219 else220 LogRel(("Audio: Warning: Stream '%s' does not have a host stream (anymore)\n", pStream->szName));221 222 return pHstStream;223 }224 225 193 # if 0 /* unused */ 226 194 static int drvAudioProcessOptions(PCFGMNODE pCfgHandle, const char *pszPrefix, audio_option *paOpts, size_t cOpts) … … 361 329 LogFunc(("[%s] enmStreamCmd=%s\n", pStream->szName, DrvAudioHlpStreamCmdToStr(enmStreamCmd))); 362 330 363 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);364 PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : pStream;365 AssertPtr(pGstStream);366 367 331 #ifdef LOG_ENABLED 368 char *pszHstSts = dbgAudioStreamStatusToStr(pHstStream->fStatus); 369 char *pszGstSts = dbgAudioStreamStatusToStr(pHstStream->fStatus); 370 LogFlowFunc(("Status host=%s, guest=%s\n", pszHstSts, pszGstSts)); 371 RTStrFree(pszGstSts); 372 RTStrFree(pszHstSts); 332 char *pszStreamSts = dbgAudioStreamStatusToStr(pStream->fStatus); 333 LogFlowFunc(("fStatus=%s\n", pszStreamSts)); 334 RTStrFree(pszStreamSts); 373 335 #endif /* LOG_ENABLED */ 374 336 … … 379 341 case PDMAUDIOSTREAMCMD_ENABLE: 380 342 { 381 if (!(p GstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED))343 if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) 382 344 { 383 if (pHstStream) 384 { 385 /* Is a pending disable outstanding? Then disable first. */ 386 if (pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE) 387 rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 388 389 if (RT_SUCCESS(rc)) 390 rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_ENABLE); 391 } 345 /* Is a pending disable outstanding? Then disable first. */ 346 if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE) 347 rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); 392 348 393 349 if (RT_SUCCESS(rc)) 394 pGstStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_ENABLED; 350 rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_ENABLE); 351 352 if (RT_SUCCESS(rc)) 353 pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_ENABLED; 395 354 } 396 355 break; … … 399 358 case PDMAUDIOSTREAMCMD_DISABLE: 400 359 { 401 if (p GstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED)360 if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED) 402 361 { 403 if (pHstStream) 362 /* 363 * For playback (output) streams first mark the host stream as pending disable, 364 * so that the rest of the remaining audio data will be played first before 365 * closing the stream. 366 */ 367 if (pStream->enmDir == PDMAUDIODIR_OUT) 404 368 { 405 /* 406 * For playback (output) streams first mark the host stream as pending disable, 407 * so that the rest of the remaining audio data will be played first before 408 * closing the stream. 409 */ 410 if (pHstStream->enmDir == PDMAUDIODIR_OUT) 411 { 412 LogFunc(("[%s] Pending disable/pause\n", pHstStream->szName)); 413 pHstStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE; 414 } 415 416 /* Can we close the host stream as well (not in pending disable mode)? */ 417 if (!(pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE)) 418 rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 369 LogFunc(("[%s] Pending disable/pause\n", pStream->szName)); 370 pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE; 419 371 } 420 372 421 if (RT_SUCCESS(rc)) 422 pGstStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_ENABLED; 373 /* Can we close the host stream as well (not in pending disable mode)? */ 374 if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE)) 375 { 376 rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); 377 if (RT_SUCCESS(rc)) 378 pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_ENABLED; 379 } 423 380 } 424 381 break; … … 427 384 case PDMAUDIOSTREAMCMD_PAUSE: 428 385 { 429 if (!(p GstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED))386 if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED)) 430 387 { 431 if (pHstStream) 432 rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_PAUSE); 433 388 rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_PAUSE); 434 389 if (RT_SUCCESS(rc)) 435 p GstStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_PAUSED;390 pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_PAUSED; 436 391 } 437 392 break; … … 440 395 case PDMAUDIOSTREAMCMD_RESUME: 441 396 { 442 if (p GstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED)397 if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED) 443 398 { 444 if (pHstStream) 445 rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_RESUME); 446 399 rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_RESUME); 447 400 if (RT_SUCCESS(rc)) 448 p GstStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_PAUSED;401 pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_PAUSED; 449 402 } 450 403 break; … … 477 430 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 478 431 479 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);480 if (!pHstStream) /* Stream does not have a host backend? Bail out. */481 return VERR_NOT_FOUND;482 483 432 #ifdef LOG_ENABLED 484 char *psz HstSts = dbgAudioStreamStatusToStr(pHstStream->fStatus);485 LogFlowFunc(("[%s] enmStreamCmd=%s, fStatus=%s\n", p HstStream->szName, DrvAudioHlpStreamCmdToStr(enmStreamCmd), pszHstSts));486 RTStrFree(psz HstSts);433 char *pszStreamSts = dbgAudioStreamStatusToStr(pStream->fStatus); 434 LogFlowFunc(("[%s] enmStreamCmd=%s, fStatus=%s\n", pStream->szName, DrvAudioHlpStreamCmdToStr(enmStreamCmd), pszStreamSts)); 435 RTStrFree(pszStreamSts); 487 436 #endif /* LOG_ENABLED */ 488 437 489 LogRel2(("Audio: %s stream '%s'\n", DrvAudioHlpStreamCmdToStr(enmStreamCmd), pHstStream->szName)); 490 491 AssertPtr(pThis->pHostDrvAudio); 438 if (!pThis->pHostDrvAudio) /* If not lower driver is configured, bail out. */ 439 return VINF_SUCCESS; 440 441 LogRel2(("Audio: %s stream '%s'\n", DrvAudioHlpStreamCmdToStr(enmStreamCmd), pStream->szName)); 492 442 493 443 int rc = VINF_SUCCESS; … … 497 447 case PDMAUDIOSTREAMCMD_ENABLE: 498 448 { 499 if (!(pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) 449 if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) 450 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_ENABLE); 451 break; 452 } 453 454 case PDMAUDIOSTREAMCMD_DISABLE: 455 { 456 if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED) 500 457 { 501 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream->pvBackend, 502 PDMAUDIOSTREAMCMD_ENABLE); 458 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_DISABLE); 503 459 if (RT_SUCCESS(rc)) 504 { 505 pHstStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_ENABLED; 506 } 460 AudioMixBufReset(&pStream->Host.MixBuf); 507 461 } 508 462 break; 509 463 } 510 464 511 case PDMAUDIOSTREAMCMD_DISABLE: 512 { 513 if (pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED) 514 { 515 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream->pvBackend, 516 PDMAUDIOSTREAMCMD_DISABLE); 517 if (RT_SUCCESS(rc)) 518 { 519 pHstStream->fStatus = PDMAUDIOSTREAMSTS_FLAG_INITIALIZED; /* Reset to initialized state. */ 520 AudioMixBufReset(&pHstStream->MixBuf); 521 } 522 } 465 case PDMAUDIOSTREAMCMD_PAUSE: 466 { 467 /* Only pause if the stream is enabled. */ 468 if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) 469 break; 470 471 if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED)) 472 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_PAUSE); 523 473 break; 524 474 } 525 475 526 case PDMAUDIOSTREAMCMD_ PAUSE:527 { 528 /* Only pause if the stream is enabled. */529 if (!(p HstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED))476 case PDMAUDIOSTREAMCMD_RESUME: 477 { 478 /* Only need to resume if the stream is enabled. */ 479 if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) 530 480 break; 531 481 532 if (!(pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED)) 533 { 534 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream->pvBackend, 535 PDMAUDIOSTREAMCMD_PAUSE); 536 if (RT_SUCCESS(rc)) 537 { 538 pHstStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_PAUSED; 539 } 540 } 482 if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED) 483 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_RESUME); 541 484 break; 542 485 } 543 486 544 case PDMAUDIOSTREAMCMD_RESUME:545 {546 /* Only need to resume if the stream is enabled. */547 if (!(pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED))548 break;549 550 if (pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED)551 {552 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream->pvBackend,553 PDMAUDIOSTREAMCMD_RESUME);554 if (RT_SUCCESS(rc))555 {556 pHstStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_PAUSED;557 }558 }559 break;560 }561 562 487 case PDMAUDIOSTREAMCMD_DRAIN: 563 488 { 564 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, p HstStream->pvBackend, PDMAUDIOSTREAMCMD_DRAIN);489 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_DRAIN); 565 490 break; 566 491 } … … 578 503 if ( rc != VERR_NOT_IMPLEMENTED 579 504 && rc != VERR_NOT_SUPPORTED) 580 LogRel(("Audio: %s stream '%s' failed with %Rrc\n", DrvAudioHlpStreamCmdToStr(enmStreamCmd), p HstStream->szName, rc));505 LogRel(("Audio: %s stream '%s' failed with %Rrc\n", DrvAudioHlpStreamCmdToStr(enmStreamCmd), pStream->szName, rc)); 581 506 582 507 LogFunc(("[%s] %s failed with %Rrc\n", pStream->szName, DrvAudioHlpStreamCmdToStr(enmStreamCmd), rc)); … … 603 528 AssertPtrReturn(pCfgGuest, VERR_INVALID_POINTER); 604 529 605 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);606 PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : pStream;607 AssertPtr(pGstStream);608 609 /* pCfgHost->Backend.cfPreBuf = DrvAudioHlpMsToFrames(&pCfgHost->Props,610 pCfgGuest->enmDir == PDMAUDIODIR_IN611 ? pThis->In.msLatencyHost : pThis->Out.msLatencyHost);*/612 /* Latency can be 0 if not configured. */613 614 530 /* 615 531 * Init host stream. … … 620 536 621 537 #ifdef DEBUG 622 LogFunc(("[%s] Requested host format:\n", p HstStream->szName));538 LogFunc(("[%s] Requested host format:\n", pStream->szName)); 623 539 DrvAudioHlpStreamCfgPrint(pCfgHost); 624 540 #endif 625 541 626 LogRel2(("Audio: Creating stream '%s'\n", p HstStream->szName));542 LogRel2(("Audio: Creating stream '%s'\n", pStream->szName)); 627 543 LogRel2(("Audio: Guest %s format for '%s': %RU32Hz, %RU8%s, %RU8 %s\n", 628 pCfgGuest->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", p GstStream->szName,544 pCfgGuest->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStream->szName, 629 545 pCfgGuest->Props.uHz, pCfgGuest->Props.cBits, pCfgGuest->Props.fSigned ? "S" : "U", 630 546 pCfgGuest->Props.cChannels, pCfgGuest->Props.cChannels == 1 ? "Channel" : "Channels")); 631 547 LogRel2(("Audio: Requested host %s format for '%s': %RU32Hz, %RU8%s, %RU8 %s\n", 632 pCfgHost->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", p HstStream->szName,548 pCfgHost->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStream->szName, 633 549 pCfgHost->Props.uHz, pCfgHost->Props.cBits, pCfgHost->Props.fSigned ? "S" : "U", 634 550 pCfgHost->Props.cChannels, pCfgHost->Props.cChannels == 1 ? "Channel" : "Channels")); 635 551 636 552 PDMAUDIOSTREAMCFG CfgHostAcq; 637 int rc = drvAudioStreamCreateInternalBackend(pThis, p HstStream, pCfgHost, &CfgHostAcq);553 int rc = drvAudioStreamCreateInternalBackend(pThis, pStream, pCfgHost, &CfgHostAcq); 638 554 if (RT_FAILURE(rc)) 639 555 return rc; 640 556 641 557 #ifdef DEBUG 642 LogFunc(("[%s] Acquired host format:\n", p HstStream->szName));558 LogFunc(("[%s] Acquired host format:\n", pStream->szName)); 643 559 DrvAudioHlpStreamCfgPrint(&CfgHostAcq); 644 560 #endif … … 672 588 LogRel2(("Audio: Warning: Pre-buffering size (%RU32 frames) of stream '%s' does not match buffer size (%RU32 frames), " 673 589 "setting pre-buffering size to %RU32 frames\n", 674 CfgHostAcq.Backend.cfPreBuf, p HstStream->szName, CfgHostAcq.Backend.cfBufferSize, CfgHostAcq.Backend.cfBufferSize));590 CfgHostAcq.Backend.cfPreBuf, pStream->szName, CfgHostAcq.Backend.cfBufferSize, CfgHostAcq.Backend.cfBufferSize)); 675 591 CfgHostAcq.Backend.cfPreBuf = CfgHostAcq.Backend.cfBufferSize; 676 592 } … … 679 595 { 680 596 LogRel2(("Audio: Warning: Period size (%RU32 frames) of stream '%s' does not match buffer size (%RU32 frames), setting to %RU32 frames\n", 681 CfgHostAcq.Backend.cfPeriod, p HstStream->szName, CfgHostAcq.Backend.cfBufferSize, CfgHostAcq.Backend.cfBufferSize));597 CfgHostAcq.Backend.cfPeriod, pStream->szName, CfgHostAcq.Backend.cfBufferSize, CfgHostAcq.Backend.cfBufferSize)); 682 598 CfgHostAcq.Backend.cfPeriod = CfgHostAcq.Backend.cfBufferSize; 683 599 } … … 686 602 687 603 LogRel2(("Audio: Buffer size of stream '%s' is %RU32ms (%RU32 frames)\n", 688 p HstStream->szName, msBufferSize, CfgHostAcq.Backend.cfBufferSize));604 pStream->szName, msBufferSize, CfgHostAcq.Backend.cfBufferSize)); 689 605 690 606 /* If no own pre-buffer is set, let the backend choose. */ 691 607 uint32_t msPreBuf = DrvAudioHlpFramesToMilli(CfgHostAcq.Backend.cfPreBuf, &pCfgHost->Props); 692 608 LogRel2(("Audio: Pre-buffering size of stream '%s' is %RU32ms (%RU32 frames)\n", 693 p HstStream->szName, msPreBuf, CfgHostAcq.Backend.cfPreBuf));609 pStream->szName, msPreBuf, CfgHostAcq.Backend.cfPreBuf)); 694 610 695 611 /* Make sure the configured buffer size by the backend at least can hold the configured latency. */ … … 697 613 698 614 LogRel2(("Audio: Period size of stream '%s' is %RU32ms (%RU32 frames)\n", 699 p HstStream->szName, msPeriod, CfgHostAcq.Backend.cfPeriod));615 pStream->szName, msPeriod, CfgHostAcq.Backend.cfPeriod)); 700 616 701 617 /* Set set host buffer size multiplicator. */ … … 703 619 704 620 /* Destroy any former mixing buffer. */ 705 AudioMixBufDestroy(&p HstStream->MixBuf);621 AudioMixBufDestroy(&pStream->Host.MixBuf); 706 622 707 623 /* Make sure to (re-)set the host buffer's shift size. */ 708 624 CfgHostAcq.Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(CfgHostAcq.Props.cBits, CfgHostAcq.Props.cChannels); 709 625 710 int rc2 = AudioMixBufInit(&pHstStream->MixBuf, pHstStream->szName, &CfgHostAcq.Props,711 712 AssertRC(rc 2);626 rc = AudioMixBufInit(&pStream->Host.MixBuf, pStream->szName, &CfgHostAcq.Props, 627 CfgHostAcq.Backend.cfBufferSize * cHstBufferFactor); 628 AssertRC(rc); 713 629 714 630 /* Make a copy of the acquired host stream configuration. */ 715 rc 2 = DrvAudioHlpStreamCfgCopy(&pHstStream->Cfg, &CfgHostAcq);716 AssertRC(rc 2);631 rc = DrvAudioHlpStreamCfgCopy(&pStream->Host.Cfg, &CfgHostAcq); 632 AssertRC(rc); 717 633 718 634 /* … … 721 637 722 638 if (pCfgGuest->Device.uSchedulingHintMs) 723 LogRel2(("Audio: Stream '%s' got a scheduling hint of %RU32ms\n", p GstStream->szName, pCfgGuest->Device.uSchedulingHintMs));639 LogRel2(("Audio: Stream '%s' got a scheduling hint of %RU32ms\n", pStream->szName, pCfgGuest->Device.uSchedulingHintMs)); 724 640 725 641 /* Destroy any former mixing buffer. */ 726 AudioMixBufDestroy(&p GstStream->MixBuf);642 AudioMixBufDestroy(&pStream->Guest.MixBuf); 727 643 728 644 /* Set the guests's default audio data layout. */ … … 735 651 const unsigned cGstBufferFactor = 4; /** @todo Make this configurable. */ 736 652 737 rc2 = AudioMixBufInit(&pGstStream->MixBuf, pGstStream->szName, &pCfgGuest->Props, 738 CfgHostAcq.Backend.cfBufferSize * cGstBufferFactor); 739 AssertRC(rc2); 740 741 if (pCfgGuest->enmDir == PDMAUDIODIR_IN) 742 { 743 /* Host (Parent) -> Guest (Child). */ 744 rc2 = AudioMixBufLinkTo(&pHstStream->MixBuf, &pGstStream->MixBuf); 745 AssertRC(rc2); 746 } 747 else 748 { 749 /* Guest (Parent) -> Host (Child). */ 750 rc2 = AudioMixBufLinkTo(&pGstStream->MixBuf, &pHstStream->MixBuf); 751 AssertRC(rc2); 752 } 653 rc = AudioMixBufInit(&pStream->Guest.MixBuf, pStream->szName, &pCfgGuest->Props, 654 CfgHostAcq.Backend.cfBufferSize * cGstBufferFactor); 655 AssertRC(rc); 753 656 754 657 /* Make a copy of the guest stream configuration. */ 755 rc 2 = DrvAudioHlpStreamCfgCopy(&pGstStream->Cfg, pCfgGuest);756 AssertRC(rc 2);658 rc = DrvAudioHlpStreamCfgCopy(&pStream->Guest.Cfg, pCfgGuest); 659 AssertRC(rc); 757 660 758 661 if (RT_FAILURE(rc)) 759 662 LogRel(("Audio: Creating stream '%s' failed with %Rrc\n", pStream->szName, rc)); 663 664 if (pCfgGuest->enmDir == PDMAUDIODIR_IN) 665 { 666 /* Host (Parent) -> Guest (Child). */ 667 rc = AudioMixBufLinkTo(&pStream->Host.MixBuf, &pStream->Guest.MixBuf); 668 AssertRC(rc); 669 } 670 else 671 { 672 /* Guest (Parent) -> Host (Child). */ 673 rc = AudioMixBufLinkTo(&pStream->Guest.MixBuf, &pStream->Host.MixBuf); 674 AssertRC(rc); 675 } 676 677 #ifdef VBOX_WITH_STATISTICS 678 char szStatName[255]; 679 680 if (pCfgGuest->enmDir == PDMAUDIODIR_IN) 681 { 682 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/BytesElapsed", pStream->szName); 683 PDMDrvHlpSTAMRegCounterEx(pThis->pDrvIns, &pStream->In.Stats.BytesElapsed, 684 szStatName, STAMUNIT_BYTES, "Elapsed bytes read."); 685 686 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/BytesRead", pStream->szName); 687 PDMDrvHlpSTAMRegCounterEx(pThis->pDrvIns, &pStream->In.Stats.BytesTotalRead, 688 szStatName, STAMUNIT_BYTES, "Total bytes read."); 689 690 RTStrPrintf(szStatName, sizeof(szStatName), "Host/%s/FramesCaptured", pStream->szName); 691 PDMDrvHlpSTAMRegCounterEx(pThis->pDrvIns, &pStream->In.Stats.FramesCaptured, 692 szStatName, STAMUNIT_COUNT, "Total frames captured."); 693 } 694 else if (pCfgGuest->enmDir == PDMAUDIODIR_OUT) 695 { 696 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/BytesElapsed", pStream->szName); 697 PDMDrvHlpSTAMRegCounterEx(pThis->pDrvIns, &pStream->Out.Stats.BytesElapsed, 698 szStatName, STAMUNIT_BYTES, "Elapsed bytes written."); 699 700 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/BytesWritten", pStream->szName); 701 PDMDrvHlpSTAMRegCounterEx(pThis->pDrvIns, &pStream->Out.Stats.BytesTotalWritten, 702 szStatName, STAMUNIT_BYTES, "Total bytes written."); 703 704 RTStrPrintf(szStatName, sizeof(szStatName), "Host/%s/FramesPlayed", pStream->szName); 705 PDMDrvHlpSTAMRegCounterEx(pThis->pDrvIns, &pStream->Out.Stats.FramesPlayed, 706 szStatName, STAMUNIT_COUNT, "Total frames played."); 707 } 708 else 709 AssertFailed(); 710 #endif 760 711 761 712 LogFlowFunc(("[%s] Returning %Rrc\n", pStream->szName, rc)); … … 800 751 801 752 /* Mark all host streams to re-initialize. */ 802 PPDMAUDIOSTREAM p HstStream;803 RTListForEach(&pThis->lst HstStreams, pHstStream, PDMAUDIOSTREAM, Node)804 p HstStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_PENDING_REINIT;753 PPDMAUDIOSTREAM pStream; 754 RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node) 755 pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_PENDING_REINIT; 805 756 806 757 # ifdef VBOX_WITH_AUDIO_ENUM … … 829 780 LogFlowFunc(("[%s]\n", pStream->szName)); 830 781 831 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);832 AssertPtr(pHstStream);833 834 782 /* 835 783 * Gather current stream status. 836 784 */ 837 bool fIsEnabled = RT_BOOL(p HstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED); /* Stream is enabled? */785 bool fIsEnabled = RT_BOOL(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED); /* Stream is enabled? */ 838 786 839 787 /* 840 788 * Destroy and re-create stream on backend side. 841 789 */ 842 int rc = drvAudioStreamControlInternalBackend(pThis, p HstStream, PDMAUDIOSTREAMCMD_DISABLE);790 int rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); 843 791 if (RT_SUCCESS(rc)) 844 792 { 845 rc = drvAudioStreamDestroyInternalBackend(pThis, p HstStream);793 rc = drvAudioStreamDestroyInternalBackend(pThis, pStream); 846 794 if (RT_SUCCESS(rc)) 847 795 { 848 rc = drvAudioStreamCreateInternalBackend(pThis, pHstStream, &pHstStream->Cfg, NULL /* pCfgAcq */); 849 /** @todo Validate (re-)acquired configuration with pHstStream->Cfg? */ 850 } 851 } 796 rc = drvAudioStreamCreateInternalBackend(pThis, pStream, &pStream->Host.Cfg, NULL /* pCfgAcq */); 797 /** @todo Validate (re-)acquired configuration with pStream->Host.Cfg? */ 798 } 799 } 800 801 /* Do the internal reset. */ 802 drvAudioStreamResetInternal(pThis, pStream); 852 803 853 804 /* 854 805 * Restore previous stream state. 855 806 */ 856 if (RT_SUCCESS(rc)) 857 { 858 PPDMAUDIOSTREAM pGstStream = pHstStream->pPair; 859 860 if (fIsEnabled) 861 { 862 rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_ENABLE); 863 if (RT_SUCCESS(rc)) 864 { 865 if (pGstStream) 866 { 867 /* Also reset the guest stream mixing buffer. */ 868 AudioMixBufReset(&pGstStream->MixBuf); 869 } 870 } 871 } 872 873 #ifdef VBOX_WITH_STATISTICS 874 /* 875 * Reset statistics. 876 */ 877 if (RT_SUCCESS(rc)) 878 { 879 if (pHstStream->enmDir == PDMAUDIODIR_IN) 880 { 881 STAM_COUNTER_RESET(&pHstStream->In.Stats.BytesElapsed); 882 STAM_COUNTER_RESET(&pHstStream->In.Stats.BytesTotalRead); 883 STAM_COUNTER_RESET(&pHstStream->In.Stats.FramesCaptured); 884 885 if (pGstStream) 886 { 887 Assert(pGstStream->enmDir == pHstStream->enmDir); 888 889 STAM_COUNTER_RESET(&pGstStream->In.Stats.BytesElapsed); 890 STAM_COUNTER_RESET(&pGstStream->In.Stats.BytesTotalRead); 891 STAM_COUNTER_RESET(&pGstStream->In.Stats.FramesCaptured); 892 } 893 } 894 else if (pHstStream->enmDir == PDMAUDIODIR_OUT) 895 { 896 STAM_COUNTER_RESET(&pHstStream->Out.Stats.BytesElapsed); 897 STAM_COUNTER_RESET(&pHstStream->Out.Stats.BytesTotalWritten); 898 STAM_COUNTER_RESET(&pHstStream->Out.Stats.FramesPlayed); 899 900 if (pGstStream) 901 { 902 Assert(pGstStream->enmDir == pHstStream->enmDir); 903 904 STAM_COUNTER_RESET(&pGstStream->Out.Stats.BytesElapsed); 905 STAM_COUNTER_RESET(&pGstStream->Out.Stats.BytesTotalWritten); 906 STAM_COUNTER_RESET(&pGstStream->Out.Stats.FramesPlayed); 907 } 908 } 909 else 910 AssertFailed(); 911 } 912 #endif 913 } 807 if (fIsEnabled) 808 rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_ENABLE); 914 809 915 810 if (RT_FAILURE(rc)) … … 918 813 LogFunc(("[%s] Returning %Rrc\n", pStream->szName, rc)); 919 814 return rc; 815 } 816 817 static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream) 818 { 819 RT_NOREF(pThis); 820 821 AudioMixBufReset(&pStream->Guest.MixBuf); 822 AudioMixBufReset(&pStream->Host.MixBuf); 823 824 #ifdef VBOX_WITH_STATISTICS 825 /* 826 * Reset statistics. 827 */ 828 if (pStream->enmDir == PDMAUDIODIR_IN) 829 { 830 STAM_COUNTER_RESET(&pStream->In.Stats.BytesElapsed); 831 STAM_COUNTER_RESET(&pStream->In.Stats.BytesTotalRead); 832 STAM_COUNTER_RESET(&pStream->In.Stats.FramesCaptured); 833 } 834 else if (pStream->enmDir == PDMAUDIODIR_OUT) 835 { 836 STAM_COUNTER_RESET(&pStream->Out.Stats.BytesElapsed); 837 STAM_COUNTER_RESET(&pStream->Out.Stats.BytesTotalWritten); 838 STAM_COUNTER_RESET(&pStream->Out.Stats.FramesPlayed); 839 } 840 else 841 AssertFailed(); 842 #endif 920 843 } 921 844 … … 949 872 950 873 #ifdef LOG_ENABLED 951 char *pszGstSts = NULL; 952 char *pszHstSts = NULL; 874 char *pszStreamSts = NULL; 953 875 #endif 954 876 … … 969 891 } 970 892 971 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 972 if (!pHstStream) 973 { 974 rc = VERR_NOT_AVAILABLE; 975 break; 976 } 893 AssertMsg(DrvAudioHlpBytesIsAligned(cbBuf, &pStream->Guest.Cfg.Props), 894 ("Writing audio data (%RU32 bytes) to stream '%s' is not properly aligned\n", cbBuf, pStream->szName)); 977 895 978 896 #ifdef LOG_ENABLED 979 psz HstSts = dbgAudioStreamStatusToStr(pHstStream->fStatus);980 AssertPtr(psz HstSts);897 pszStreamSts = dbgAudioStreamStatusToStr(pStream->fStatus); 898 AssertPtr(pszStreamSts); 981 899 #endif 982 PPDMAUDIOSTREAM pGstStream = pHstStream->pPair; 983 AssertPtr(pGstStream); 984 985 AssertMsg(DrvAudioHlpBytesIsAligned(cbBuf, &pGstStream->Cfg.Props), 986 ("Writing audio data (%RU32 bytes) to stream '%s' is not properly aligned\n", cbBuf, pGstStream->szName)); 987 988 #ifdef LOG_ENABLED 989 pszGstSts = dbgAudioStreamStatusToStr(pGstStream->fStatus); 990 AssertPtr(pszGstSts); 991 #endif 992 993 if (!(pGstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) 994 { 995 Log3Func(("[%s] Writing to disabled guest output stream not possible (status is %s, host status %s)\n", 996 pGstStream->szName, pszGstSts, pszHstSts)); 900 if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) 901 { 902 Log3Func(("[%s] Writing to disabled guest output stream not possible (status is %s)\n", 903 pStream->szName, pszStreamSts)); 997 904 #ifdef DEBUG_andy 998 905 AssertFailed(); … … 1002 909 } 1003 910 1004 const uint32_t cbFree = AudioMixBufFreeBytes(&p HstStream->MixBuf);911 const uint32_t cbFree = AudioMixBufFreeBytes(&pStream->Host.MixBuf); 1005 912 if (cbFree < cbBuf) 1006 913 LogRel2(("Audio: Lost audio output (%RU64ms, %RU32 free but needs %RU32) due to full host stream buffer '%s'\n", 1007 DrvAudioHlpBytesToMilli(cbBuf - cbFree, &p HstStream->Cfg.Props), cbFree, cbBuf, pHstStream->szName));914 DrvAudioHlpBytesToMilli(cbBuf - cbFree, &pStream->Host.Cfg.Props), cbFree, cbBuf, pStream->szName)); 1008 915 1009 916 uint32_t cbToWrite = RT_MIN(cbBuf, cbFree); … … 1017 924 * (first) processing (if needed), so always write the incoming data at offset 0. */ 1018 925 uint32_t cfGstWritten = 0; 1019 rc = AudioMixBufWriteAt(&p GstStream->MixBuf, 0 /* offFrames */, pvBuf, cbToWrite, &cfGstWritten);926 rc = AudioMixBufWriteAt(&pStream->Guest.MixBuf, 0 /* offFrames */, pvBuf, cbToWrite, &cfGstWritten); 1020 927 if ( RT_FAILURE(rc) 1021 928 || !cfGstWritten) 1022 929 { 1023 930 AssertMsgFailed(("[%s] Write failed: cbToWrite=%RU32, cfWritten=%RU32, rc=%Rrc\n", 1024 p GstStream->szName, cbToWrite, cfGstWritten, rc));931 pStream->szName, cbToWrite, cfGstWritten, rc)); 1025 932 break; 1026 933 } 1027 934 1028 935 if (pThis->Out.Cfg.Dbg.fEnabled) 1029 DrvAudioHlpFileWrite(p HstStream->Out.Dbg.pFileStreamWrite, pvBuf, cbToWrite, 0 /* fFlags */);936 DrvAudioHlpFileWrite(pStream->Out.Dbg.pFileStreamWrite, pvBuf, cbToWrite, 0 /* fFlags */); 1030 937 1031 938 #ifdef VBOX_WITH_STATISTICS … … 1035 942 if (cfGstWritten) 1036 943 { 1037 int rc2 = AudioMixBufMixToParentEx(&p GstStream->MixBuf, 0 /* cSrcOffset */, cfGstWritten /* cSrcFrames */,944 int rc2 = AudioMixBufMixToParentEx(&pStream->Guest.MixBuf, 0 /* cSrcOffset */, cfGstWritten /* cSrcFrames */, 1038 945 &cfGstMixed /* pcSrcMixed */); 1039 946 if (RT_FAILURE(rc2)) 1040 947 { 1041 948 AssertMsgFailed(("[%s] Mixing failed: cbToWrite=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n", 1042 p GstStream->szName, cbToWrite, cfGstWritten, cfGstMixed, rc2));949 pStream->szName, cbToWrite, cfGstWritten, cfGstMixed, rc2)); 1043 950 } 1044 951 else 1045 952 { 1046 953 Log3Func(("[%s] Buffer: Writing %RU32 frames (%RU64ms), now filled with %RU64ms -- %RU8%%\n", 1047 p HstStream->szName, cfGstWritten, DrvAudioHlpFramesToMilli(cfGstWritten, &pHstStream->Cfg.Props),1048 DrvAudioHlpFramesToMilli(AudioMixBufUsed(&p HstStream->MixBuf), &pHstStream->Cfg.Props),1049 AudioMixBufUsed(&p HstStream->MixBuf) * 100 / AudioMixBufSize(&pHstStream->MixBuf)));1050 1051 p HstStream->tsLastReadWrittenNs = RTTimeNanoTS();954 pStream->szName, cfGstWritten, DrvAudioHlpFramesToMilli(cfGstWritten, &pStream->Guest.Cfg.Props), 955 DrvAudioHlpFramesToMilli(AudioMixBufUsed(&pStream->Host.MixBuf), &pStream->Host.Cfg.Props), 956 AudioMixBufUsed(&pStream->Host.MixBuf) * 100 / AudioMixBufSize(&pStream->Host.MixBuf))); 957 958 pStream->tsLastReadWrittenNs = RTTimeNanoTS(); 1052 959 1053 960 /* Keep going. */ … … 1057 964 rc = rc2; 1058 965 1059 cbWrittenTotal = AUDIOMIXBUF_F2B(&p GstStream->MixBuf, cfGstWritten);966 cbWrittenTotal = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfGstWritten); 1060 967 #ifdef DEBUG 1061 if (p HstStream->fThresholdReached)1062 p HstStream->Out.Dbg.cbJitterWrittenPlayed += cbWrittenTotal;968 if (pStream->fThresholdReached) 969 pStream->Out.Dbg.cbJitterWrittenPlayed += cbWrittenTotal; 1063 970 #endif 1064 971 1065 972 #ifdef VBOX_WITH_STATISTICS 1066 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesMixedOut, 973 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesMixedOut, cfGstMixed); 1067 974 Assert(cfGstWritten >= cfGstMixed); 1068 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesLostOut, 1069 STAM_COUNTER_ADD(&pThis->Stats.TotalBytesWritten, 1070 STAM_COUNTER_ADD(&p GstStream->Out.Stats.BytesTotalWritten, cbWrittenTotal);975 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesLostOut, cfGstWritten - cfGstMixed); 976 STAM_COUNTER_ADD(&pThis->Stats.TotalBytesWritten, cbWrittenTotal); 977 STAM_COUNTER_ADD(&pStream->Out.Stats.BytesTotalWritten, cbWrittenTotal); 1071 978 #endif 1072 979 } 1073 980 1074 Log3Func(("[%s] cbToWrite=%RU32, cf Used=%RU32, cfLive=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n",1075 p GstStream->szName, cbToWrite, AudioMixBufUsed(&pGstStream->MixBuf),1076 AudioMixBufLive(&p GstStream->MixBuf), cfGstWritten, cfGstMixed, rc));981 Log3Func(("[%s] cbToWrite=%RU32, cfHstUsed=%RU32, cfHstfLive=%RU32, cfGstWritten=%RU32, cfGstMixed=%RU32, rc=%Rrc\n", 982 pStream->szName, cbToWrite, AudioMixBufUsed(&pStream->Host.MixBuf), 983 AudioMixBufLive(&pStream->Host.MixBuf), cfGstWritten, cfGstMixed, rc)); 1077 984 1078 985 } while (0); 1079 986 1080 Log3Func(("[%s] fEnabled=%RTbool, cbWrittenTotal=%RU32, rc=%Rrc\n", pStream->szName, pThis->Out.fEnabled, cbWrittenTotal, rc)); 987 Log3Func(("[%s] fEnabled=%RTbool, cbWrittenTotal=%RU32, rc=%Rrc\n", 988 pStream->szName, pThis->Out.fEnabled, cbWrittenTotal, rc)); 1081 989 1082 990 #ifdef LOG_ENABLED 1083 RTStrFree(pszHstSts); 1084 RTStrFree(pszGstSts); 991 RTStrFree(pszStreamSts); 1085 992 #endif 1086 993 … … 1172 1079 return VINF_SUCCESS; 1173 1080 1174 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);1175 AssertPtr(pHstStream);1176 PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : NULL;1177 AssertPtr(pGstStream);1178 1179 1081 int rc; 1180 1082 1181 1083 /* Is the stream scheduled for re-initialization? Do so now. */ 1182 if (p HstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_REINIT)1084 if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_REINIT) 1183 1085 { 1184 1086 #ifdef VBOX_WITH_AUDIO_ENUM … … 1194 1096 /* Remove the pending re-init flag in any case, regardless whether the actual re-initialization succeeded 1195 1097 * or not. If it failed, the backend needs to notify us again to try again at some later point in time. */ 1196 p HstStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_PENDING_REINIT;1098 pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_PENDING_REINIT; 1197 1099 1198 1100 rc = drvAudioStreamReInitInternal(pThis, pStream); … … 1202 1104 1203 1105 #ifdef LOG_ENABLED 1204 char *psz HstSts = dbgAudioStreamStatusToStr(pHstStream->fStatus);1205 Log3Func(("[%s] fStatus=%s\n", p HstStream->szName, pszHstSts));1206 RTStrFree(psz HstSts);1106 char *pszStreamSts = dbgAudioStreamStatusToStr(pStream->fStatus); 1107 Log3Func(("[%s] fStatus=%s\n", pStream->szName, pszStreamSts)); 1108 RTStrFree(pszStreamSts); 1207 1109 #endif /* LOG_ENABLED */ 1208 1110 1209 1111 /* Not enabled or paused? Skip iteration. */ 1210 if ( !(p HstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED)1211 || (p HstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED))1112 if ( !(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED) 1113 || (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED)) 1212 1114 { 1213 1115 return VINF_SUCCESS; … … 1221 1123 uint32_t cfMixed = 0; 1222 1124 1223 rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, p HstStream->pvBackend);1125 rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, pStream->pvBackend); 1224 1126 if (RT_FAILURE(rc)) 1225 1127 break; 1226 1128 1227 if (p HstStream->enmDir == PDMAUDIODIR_IN)1129 if (pStream->enmDir == PDMAUDIODIR_IN) 1228 1130 { 1229 1131 /* Has the host captured any frames which were not mixed to the guest side yet? */ 1230 uint32_t cfCaptured = AudioMixBufUsed(&p HstStream->MixBuf);1132 uint32_t cfCaptured = AudioMixBufUsed(&pStream->Host.MixBuf); 1231 1133 if (cfCaptured) 1232 1134 { 1233 1135 /* When capturing frames, the guest is the parent while the host is the child. 1234 1136 * So try mixing not yet mixed host-side frames to the guest-side buffer. */ 1235 rc = AudioMixBufMixToParent(&p HstStream->MixBuf, cfCaptured, &cfMixed);1137 rc = AudioMixBufMixToParent(&pStream->Host.MixBuf, cfCaptured, &cfMixed); 1236 1138 if (RT_FAILURE(rc)) 1237 1139 { 1238 1140 if (rc == VERR_BUFFER_OVERFLOW) 1239 LogRel2(("Audio: Guest input stream '%s' full , expect stuttering audio capture\n", pGstStream->szName));1141 LogRel2(("Audio: Guest input stream '%s' full\n", pStream->szName)); 1240 1142 else 1241 LogRel2(("Audio: Mixing to guest input stream '%s' failed: %Rrc\n", p GstStream->szName, rc));1143 LogRel2(("Audio: Mixing to guest input stream '%s' failed: %Rrc\n", pStream->szName, rc)); 1242 1144 #ifdef DEBUG_andy_disabled 1243 1145 AssertFailed(); … … 1250 1152 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesLostIn, cfCaptured - cfMixed); 1251 1153 #endif 1252 Log3Func(("[%s] %RU32/%RU32 input frames mixed, rc=%Rrc\n", p HstStream->szName, cfMixed, cfCaptured, rc));1154 Log3Func(("[%s] %RU32/%RU32 input frames mixed, rc=%Rrc\n", pStream->szName, cfMixed, cfCaptured, rc)); 1253 1155 } 1254 1156 else … … 1259 1161 } 1260 1162 } 1261 else if (p HstStream->enmDir == PDMAUDIODIR_OUT)1163 else if (pStream->enmDir == PDMAUDIODIR_OUT) 1262 1164 { 1263 1165 /* No audio frames to transfer from guest to host (anymore)? 1264 1166 * Then try closing this stream if marked so in the next block. */ 1265 const uint32_t cfLive = AudioMixBufLive(&p HstStream->MixBuf);1167 const uint32_t cfLive = AudioMixBufLive(&pStream->Host.MixBuf); 1266 1168 fTryClosePending = cfLive == 0; 1267 Log3Func(("[%s] fTryClosePending=%RTbool, cfLive=%RU32\n", p HstStream->szName, fTryClosePending, cfLive));1169 Log3Func(("[%s] fTryClosePending=%RTbool, cfLive=%RU32\n", pStream->szName, fTryClosePending, cfLive)); 1268 1170 } 1269 1171 else … … 1272 1174 /* Has the host stream marked as pending to disable? 1273 1175 * Try disabling the stream then. */ 1274 if ( p HstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE1176 if ( pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE 1275 1177 && fTryClosePending) 1276 1178 { 1277 1179 /* Tell the backend to drain the stream, that is, play the remaining (buffered) data 1278 1180 * on the backend side. */ 1279 rc = drvAudioStreamControlInternalBackend(pThis, p HstStream, PDMAUDIOSTREAMCMD_DRAIN);1181 rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DRAIN); 1280 1182 if (rc == VERR_NOT_SUPPORTED) /* Not all backends support draining. */ 1281 1183 rc = VINF_SUCCESS; … … 1285 1187 if (pThis->pHostDrvAudio->pfnStreamGetPending) /* Optional to implement. */ 1286 1188 { 1287 const uint32_t cxPending = pThis->pHostDrvAudio->pfnStreamGetPending(pThis->pHostDrvAudio, p HstStream->pvBackend);1288 Log3Func(("[%s] cxPending=%RU32\n", p HstStream->szName, cxPending));1189 const uint32_t cxPending = pThis->pHostDrvAudio->pfnStreamGetPending(pThis->pHostDrvAudio, pStream->pvBackend); 1190 Log3Func(("[%s] cxPending=%RU32\n", pStream->szName, cxPending)); 1289 1191 1290 1192 /* Only try close pending if no audio data is pending on the backend-side anymore. */ … … 1294 1196 if (fTryClosePending) 1295 1197 { 1296 LogFunc(("[%s] Closing pending stream\n", pHstStream->szName)); 1297 rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 1298 if (RT_FAILURE(rc)) 1299 LogFunc(("[%s] Backend vetoed against closing pending input stream, rc=%Rrc\n", pHstStream->szName, rc)); 1198 LogFunc(("[%s] Closing pending stream\n", pStream->szName)); 1199 rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); 1200 if (RT_SUCCESS(rc)) 1201 { 1202 pStream->fStatus &= ~(PDMAUDIOSTREAMSTS_FLAG_ENABLED | PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE); 1203 } 1204 else 1205 LogFunc(("[%s] Backend vetoed against closing pending input stream, rc=%Rrc\n", pStream->szName, rc)); 1300 1206 } 1301 1207 } … … 1305 1211 1306 1212 /* Update timestamps. */ 1307 p GstStream->tsLastIteratedNs = RTTimeNanoTS();1213 pStream->tsLastIteratedNs = RTTimeNanoTS(); 1308 1214 1309 1215 if (RT_FAILURE(rc)) 1310 LogFunc(("[%s] Failed with %Rrc\n", p HstStream->szName, rc));1216 LogFunc(("[%s] Failed with %Rrc\n", pStream->szName, rc)); 1311 1217 1312 1218 return rc; 1313 }1314 1315 /**1316 * Links an audio stream to another audio stream (pair).1317 *1318 * @returns IPRT status code.1319 * @param pStream Stream to handle linking for.1320 * @param pPair Stream to link pStream to. Specify NULL to unlink pStream from a former linked stream.1321 */1322 static int drvAudioStreamLinkToInternal(PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAM pPair)1323 {1324 if (pPair) /* Link. */1325 {1326 pStream->pPair = pPair;1327 pPair->pPair = pStream;1328 1329 LogRel2(("Audio: Linked audio stream '%s' to '%s'\n", pStream->szName, pPair->szName));1330 }1331 else /* Unlink. */1332 {1333 if (pStream->pPair)1334 {1335 LogRel2(("Audio: Unlinked pair '%s' from stream '%s'\n", pStream->pPair->szName, pStream->szName));1336 1337 AssertMsg(pStream->pPair->pPair == pStream,1338 ("Pair '%s' is not linked to '%s' (linked to '%s')\n",1339 pStream->pPair->szName, pStream->szName, pStream->pPair->pPair ? pStream->pPair->pPair->szName : "<NONE>"));1340 1341 pStream->pPair->pPair = NULL; /* Also make sure to unlink the pair from pStream */1342 pStream->pPair = NULL;1343 }1344 }1345 1346 return VINF_SUCCESS;1347 1219 } 1348 1220 … … 1352 1224 * @return IPRT status code. 1353 1225 * @param pThis Pointer to driver instance. 1354 * @param p HstStream Host stream to play.1226 * @param pStream Stream to play. 1355 1227 * @param cfToPlay Number of audio frames to play. 1356 1228 * @param pcfPlayed Returns number of audio frames played. Optional. 1357 1229 */ 1358 1230 static int drvAudioStreamPlayNonInterleaved(PDRVAUDIO pThis, 1359 PPDMAUDIOSTREAM p HstStream, uint32_t cfToPlay, uint32_t *pcfPlayed)1360 { 1361 AssertPtrReturn(pThis, 1362 AssertPtrReturn(p HstStream, VERR_INVALID_POINTER);1231 PPDMAUDIOSTREAM pStream, uint32_t cfToPlay, uint32_t *pcfPlayed) 1232 { 1233 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1234 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1363 1235 /* pcfPlayed is optional. */ 1364 1365 /* Sanity. */1366 Assert(pHstStream->enmCtx == PDMAUDIOSTREAMCTX_HOST);1367 Assert(pHstStream->enmDir == PDMAUDIODIR_OUT);1368 Assert(pHstStream->Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED);1369 1236 1370 1237 if (!cfToPlay) … … 1375 1242 } 1376 1243 1244 /* Sanity. */ 1245 Assert(pStream->enmDir == PDMAUDIODIR_OUT); 1246 Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED); 1247 1377 1248 int rc = VINF_SUCCESS; 1378 1249 … … 1380 1251 1381 1252 AssertPtr(pThis->pHostDrvAudio->pfnStreamGetWritable); 1382 uint32_t cfWritable = AUDIOMIXBUF_B2F(&p HstStream->MixBuf,1383 pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, p HstStream->pvBackend));1384 1385 Log3Func(("[%s] cfToPlay=%RU32 (%RU64ms), cfWritable=%RU32 (%RU64ms)\n", p HstStream->szName,1386 cfToPlay, DrvAudioHlpFramesToMilli(cfToPlay, &p HstStream->Cfg.Props),1387 cfWritable, DrvAudioHlpFramesToMilli(cfWritable, &p HstStream->Cfg.Props)));1253 uint32_t cfWritable = AUDIOMIXBUF_B2F(&pStream->Host.MixBuf, 1254 pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend)); 1255 1256 Log3Func(("[%s] cfToPlay=%RU32 (%RU64ms), cfWritable=%RU32 (%RU64ms)\n", pStream->szName, 1257 cfToPlay, DrvAudioHlpFramesToMilli(cfToPlay, &pStream->Host.Cfg.Props), 1258 cfWritable, DrvAudioHlpFramesToMilli(cfWritable, &pStream->Host.Cfg.Props))); 1388 1259 1389 1260 if (cfWritable) … … 1402 1273 { 1403 1274 uint32_t cfRead = 0; 1404 rc = AudioMixBufAcquireReadBlock(&pHstStream->MixBuf, auBuf, RT_MIN(cbChunk, AUDIOMIXBUF_F2B(&pHstStream->MixBuf, cfLeft)), &cfRead); 1275 rc = AudioMixBufAcquireReadBlock(&pStream->Host.MixBuf, 1276 auBuf, RT_MIN(cbChunk, AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cfLeft)), 1277 &cfRead); 1405 1278 if (RT_FAILURE(rc)) 1406 1279 break; 1407 1280 1408 uint32_t cbRead = AUDIOMIXBUF_F2B(&p HstStream->MixBuf, cfRead);1281 uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cfRead); 1409 1282 Assert(cbRead <= cbChunk); 1410 1283 1411 1284 uint32_t cfPlayed = 0; 1412 1285 uint32_t cbPlayed = 0; 1413 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, p HstStream->pvBackend,1286 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend, 1414 1287 auBuf, cbRead, &cbPlayed); 1415 1288 if ( RT_SUCCESS(rc) … … 1417 1290 { 1418 1291 if (pThis->Out.Cfg.Dbg.fEnabled) 1419 DrvAudioHlpFileWrite(p HstStream->Out.Dbg.pFilePlayNonInterleaved, auBuf, cbPlayed, 0 /* fFlags */);1292 DrvAudioHlpFileWrite(pStream->Out.Dbg.pFilePlayNonInterleaved, auBuf, cbPlayed, 0 /* fFlags */); 1420 1293 1421 1294 if (cbRead != cbPlayed) 1422 1295 LogRel2(("Audio: Host stream '%s' played wrong amount (%RU32 bytes read but played %RU32)\n", 1423 p HstStream->szName, cbRead, cbPlayed));1424 1425 cfPlayed = AUDIOMIXBUF_B2F(&p HstStream->MixBuf, cbPlayed);1296 pStream->szName, cbRead, cbPlayed)); 1297 1298 cfPlayed = AUDIOMIXBUF_B2F(&pStream->Host.MixBuf, cbPlayed); 1426 1299 cfPlayedTotal += cfPlayed; 1427 1300 … … 1430 1303 } 1431 1304 1432 AudioMixBufReleaseReadBlock(&p HstStream->MixBuf, cfPlayed);1305 AudioMixBufReleaseReadBlock(&pStream->Host.MixBuf, cfPlayed); 1433 1306 1434 1307 if (RT_FAILURE(rc)) … … 1438 1311 } 1439 1312 1440 Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", p HstStream->szName, cfPlayedTotal, cfToPlay, rc));1313 Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cfPlayedTotal, cfToPlay, rc)); 1441 1314 1442 1315 if (RT_SUCCESS(rc)) … … 1454 1327 * @return IPRT status code. 1455 1328 * @param pThis Pointer to driver instance. 1456 * @param p HstStream Host stream to play.1329 * @param pStream Stream to play. 1457 1330 * @param cfToPlay Number of audio frames to play. 1458 1331 * @param pcfPlayed Returns number of audio frames played. Optional. 1459 1332 */ 1460 1333 static int drvAudioStreamPlayRaw(PDRVAUDIO pThis, 1461 PPDMAUDIOSTREAM p HstStream, uint32_t cfToPlay, uint32_t *pcfPlayed)1334 PPDMAUDIOSTREAM pStream, uint32_t cfToPlay, uint32_t *pcfPlayed) 1462 1335 { 1463 1336 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1464 AssertPtrReturn(p HstStream, VERR_INVALID_POINTER);1337 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1465 1338 /* pcfPlayed is optional. */ 1466 1339 1467 1340 /* Sanity. */ 1468 Assert(pHstStream->enmCtx == PDMAUDIOSTREAMCTX_HOST); 1469 Assert(pHstStream->enmDir == PDMAUDIODIR_OUT); 1470 Assert(pHstStream->Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW); 1341 Assert(pStream->enmDir == PDMAUDIODIR_OUT); 1342 Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW); 1471 1343 1472 1344 if (!cfToPlay) … … 1482 1354 1483 1355 AssertPtr(pThis->pHostDrvAudio->pfnStreamGetWritable); 1484 uint32_t cfWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, p HstStream->pvBackend);1356 uint32_t cfWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend); 1485 1357 if (cfWritable) 1486 1358 { … … 1494 1366 { 1495 1367 uint32_t cfRead = 0; 1496 rc = AudioMixBufPeek(&p HstStream->MixBuf, cfLeft, aFrameBuf,1368 rc = AudioMixBufPeek(&pStream->Host.MixBuf, cfLeft, aFrameBuf, 1497 1369 RT_MIN(cfLeft, RT_ELEMENTS(aFrameBuf)), &cfRead); 1498 1370 … … 1506 1378 * rather on bytes. */ 1507 1379 Assert(cfRead <= RT_ELEMENTS(aFrameBuf)); 1508 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, p HstStream->pvBackend,1380 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend, 1509 1381 aFrameBuf, cfRead, &cfPlayed); 1510 1382 if ( RT_FAILURE(rc) … … 1533 1405 } 1534 1406 1535 Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", p HstStream->szName, cfPlayedTotal, cfToPlay, rc));1407 Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cfPlayedTotal, cfToPlay, rc)); 1536 1408 1537 1409 if (RT_SUCCESS(rc)) … … 1570 1442 return VINF_SUCCESS; 1571 1443 1572 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 1573 AssertPtr(pHstStream); 1574 PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : NULL; 1575 AssertPtr(pGstStream); 1576 1577 AssertReleaseMsgReturn(pHstStream != NULL, 1578 ("[%s] Host stream is NULL (cRefs=%RU32, fStatus=%x, enmCtx=%ld)\n", 1579 pStream->szName, pStream->cRefs, pStream->fStatus, pStream->enmCtx), 1580 VERR_NOT_AVAILABLE); 1581 AssertReleaseMsgReturn(pGstStream != NULL, 1582 ("[%s] Guest stream is NULL (cRefs=%RU32, fStatus=%x, enmCtx=%ld)\n", 1583 pStream->szName, pStream->cRefs, pStream->fStatus, pStream->enmCtx), 1584 VERR_NOT_AVAILABLE); 1585 1586 PDMAUDIOSTREAMSTS stsHstStream = pHstStream->fStatus; 1444 PDMAUDIOSTREAMSTS stsStream = pStream->fStatus; 1587 1445 #ifdef LOG_ENABLED 1588 char *pszStreamSts = dbgAudioStreamStatusToStr(sts HstStream);1589 Log3Func(("[%s] Buffer: Start stsHstStream=%s\n", pHstStream->szName, pszStreamSts));1446 char *pszStreamSts = dbgAudioStreamStatusToStr(stsStream); 1447 Log3Func(("[%s] Buffer: Start fStatus=%s\n", pStream->szName, pszStreamSts)); 1590 1448 RTStrFree(pszStreamSts); 1591 1449 #endif /* LOG_ENABLED */ … … 1596 1454 * Check if the backend is ready to operate. 1597 1455 */ 1598 if (!(sts HstStream & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) /* Stream disabled? Bail out. */1456 if (!(stsStream & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) /* Stream disabled? Bail out. */ 1599 1457 break; 1600 1458 1601 uint32_t cfLive = AudioMixBufLive(&p HstStream->MixBuf);1602 const uint8_t uLivePercent = (100 * cfLive) / AudioMixBufSize(&p HstStream->MixBuf);1603 1604 const uint64_t tsDeltaPlayedCapturedNs = RTTimeNanoTS() - p HstStream->tsLastPlayedCapturedNs;1605 1606 p HstStream->tsLastPlayedCapturedNs = RTTimeNanoTS();1459 uint32_t cfLive = AudioMixBufLive(&pStream->Host.MixBuf); 1460 const uint8_t uLivePercent = (100 * cfLive) / AudioMixBufSize(&pStream->Host.MixBuf); 1461 1462 const uint64_t tsDeltaPlayedCapturedNs = RTTimeNanoTS() - pStream->tsLastPlayedCapturedNs; 1463 1464 pStream->tsLastPlayedCapturedNs = RTTimeNanoTS(); 1607 1465 1608 1466 Log3Func(("[%s] Buffer: Last played %RU64ns (%RU64ms), filled with %RU64ms (%RU8%%) total, " 1609 1467 "(cfLive=%RU32, fThresholdReached=%RTbool)\n", 1610 p HstStream->szName, tsDeltaPlayedCapturedNs, tsDeltaPlayedCapturedNs / RT_NS_1MS_64,1611 DrvAudioHlpFramesToMilli(cfLive, &p HstStream->Cfg.Props),1612 uLivePercent, cfLive, p HstStream->fThresholdReached));1613 1614 bool fDoPlay = p HstStream->fThresholdReached;1468 pStream->szName, tsDeltaPlayedCapturedNs, tsDeltaPlayedCapturedNs / RT_NS_1MS_64, 1469 DrvAudioHlpFramesToMilli(cfLive, &pStream->Host.Cfg.Props), 1470 uLivePercent, cfLive, pStream->fThresholdReached)); 1471 1472 bool fDoPlay = pStream->fThresholdReached; 1615 1473 bool fJustStarted = false; 1616 1474 if (!fDoPlay) 1617 1475 { 1618 1476 /* Did we reach the backend's playback (pre-buffering) threshold? Can be 0 if no threshold set. */ 1619 if (cfLive >= p HstStream->Cfg.Backend.cfPreBuf)1477 if (cfLive >= pStream->Host.Cfg.Backend.cfPreBuf) 1620 1478 { 1621 LogRel2(("Audio: Stream '%s' buffering complete\n", p HstStream->szName));1479 LogRel2(("Audio: Stream '%s' buffering complete\n", pStream->szName)); 1622 1480 fDoPlay = true; 1623 1481 } … … 1628 1486 * To reproduce, use "Windows Navigation Start.wav" on Windows 7 (2824 samples). */ 1629 1487 else if ( cfLive 1630 && p HstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE)1488 && pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE) 1631 1489 { 1632 LogRel2(("Audio: Stream '%s' buffering complete (short sound)\n", p HstStream->szName));1490 LogRel2(("Audio: Stream '%s' buffering complete (short sound)\n", pStream->szName)); 1633 1491 fDoPlay = true; 1634 1492 } … … 1636 1494 if (fDoPlay) 1637 1495 { 1638 p HstStream->fThresholdReached = true;1496 pStream->fThresholdReached = true; 1639 1497 fJustStarted = true; 1640 LogRel2(("Audio: Stream '%s' started playing\n", p HstStream->szName));1498 LogRel2(("Audio: Stream '%s' started playing\n", pStream->szName)); 1641 1499 } 1642 1500 else /* Not yet, so still buffering audio data. */ 1643 1501 LogRel2(("Audio: Stream '%s' is buffering (%RU8%% complete)\n", 1644 p HstStream->szName, (100 * cfLive) / pHstStream->Cfg.Backend.cfPreBuf));1502 pStream->szName, (100 * cfLive) / pStream->Host.Cfg.Backend.cfPreBuf)); 1645 1503 } 1646 1504 … … 1649 1507 uint32_t cfToPlay = 0; 1650 1508 if (fJustStarted) 1651 cfToPlay = p HstStream->Cfg.Backend.cfPeriod; /* cfPeriod can be 0. */1509 cfToPlay = pStream->Host.Cfg.Backend.cfPeriod; /* cfPeriod can be 0. */ 1652 1510 1653 1511 if (!cfToPlay) 1654 1512 { 1655 cfToPlay = DrvAudioHlpNanoToFrames(tsDeltaPlayedCapturedNs, &p HstStream->Cfg.Props);1656 if (p HstStream->Cfg.Device.uSchedulingHintMs)1657 cfToPlay = RT_MIN(cfToPlay, DrvAudioHlpMilliToFrames(p HstStream->Cfg.Device.uSchedulingHintMs, &pHstStream->Cfg.Props));1513 cfToPlay = DrvAudioHlpNanoToFrames(tsDeltaPlayedCapturedNs, &pStream->Host.Cfg.Props); 1514 if (pStream->Host.Cfg.Device.uSchedulingHintMs) 1515 cfToPlay = RT_MIN(cfToPlay, DrvAudioHlpMilliToFrames(pStream->Host.Cfg.Device.uSchedulingHintMs, &pStream->Host.Cfg.Props)); 1658 1516 } 1659 1517 1660 1518 Log3Func(("[%s] Buffer: fJustStarted=%RTbool, cfLive=%RU32, cfToPlay=%RU32\n", 1661 p HstStream->szName, fJustStarted, cfLive, cfToPlay));1519 pStream->szName, fJustStarted, cfLive, cfToPlay)); 1662 1520 1663 1521 /* Did we reach a buffer underrun? Do pre-buffering again. 1664 1522 * If we're in pending disabled mode, try to play (drain) the remaining audio data. */ 1665 if ( !(p HstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE)1523 if ( !(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE) 1666 1524 && !fJustStarted) 1667 1525 { 1668 1526 if (cfLive < cfToPlay) 1669 1527 { 1670 p HstStream->fThresholdReached = false;1671 Log3Func(("[%s] Buffer: Underrun (cfLive=%RU32, cfToPlay=%RU32)\n", p HstStream->szName, cfLive, cfToPlay));1528 pStream->fThresholdReached = false; 1529 Log3Func(("[%s] Buffer: Underrun (cfLive=%RU32, cfToPlay=%RU32)\n", pStream->szName, cfLive, cfToPlay)); 1672 1530 LogRel2(("Audio: Stream '%s' buffer underrun (total %RU8%%, which is %RU8%% of a period), buffering ...\n", 1673 p HstStream->szName, uLivePercent, (100 * cfLive) / pHstStream->Cfg.Backend.cfPeriod));1531 pStream->szName, uLivePercent, (100 * cfLive) / pStream->Host.Cfg.Backend.cfPeriod)); 1674 1532 break; 1675 1533 } … … 1683 1541 #ifdef DEBUG 1684 1542 if (!fJustStarted) 1685 p HstStream->Out.Dbg.cbJitterWrittenPlayed -= AUDIOMIXBUF_F2B(&pHstStream->MixBuf, cfToPlay);1543 pStream->Out.Dbg.cbJitterWrittenPlayed -= AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cfToPlay); 1686 1544 Log3Func(("[%s] Buffer: Playing %RU32 frames (%RU64ms), now filled with %RU64ms -- %RU8%% (cbJitterWrittenPlayed=%RI64)\n", 1687 p HstStream->szName, cfToPlay, DrvAudioHlpFramesToMilli(cfToPlay, &pHstStream->Cfg.Props),1688 DrvAudioHlpFramesToMilli(AudioMixBufUsed(&p HstStream->MixBuf), &pHstStream->Cfg.Props),1689 AudioMixBufUsed(&p HstStream->MixBuf) * 100 / AudioMixBufSize(&pHstStream->MixBuf),1690 p HstStream->Out.Dbg.cbJitterWrittenPlayed));1545 pStream->szName, cfToPlay, DrvAudioHlpFramesToMilli(cfToPlay, &pStream->Host.Cfg.Props), 1546 DrvAudioHlpFramesToMilli(AudioMixBufUsed(&pStream->Host.MixBuf), &pStream->Host.Cfg.Props), 1547 AudioMixBufUsed(&pStream->Host.MixBuf) * 100 / AudioMixBufSize(&pStream->Host.MixBuf), 1548 pStream->Out.Dbg.cbJitterWrittenPlayed)); 1691 1549 #endif 1692 1550 if (pThis->pHostDrvAudio->pfnStreamPlayBegin) 1693 pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, p HstStream->pvBackend);1694 1695 if (RT_LIKELY(p HstStream->Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED))1551 pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, pStream->pvBackend); 1552 1553 if (RT_LIKELY(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED)) 1696 1554 { 1697 rc = drvAudioStreamPlayNonInterleaved(pThis, p HstStream, cfToPlay, &cfPlayedTotal);1555 rc = drvAudioStreamPlayNonInterleaved(pThis, pStream, cfToPlay, &cfPlayedTotal); 1698 1556 } 1699 else if (p HstStream->Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW)1557 else if (pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW) 1700 1558 { 1701 rc = drvAudioStreamPlayRaw(pThis, p HstStream, cfToPlay, &cfPlayedTotal);1559 rc = drvAudioStreamPlayRaw(pThis, pStream, cfToPlay, &cfPlayedTotal); 1702 1560 } 1703 1561 else … … 1705 1563 1706 1564 if (pThis->pHostDrvAudio->pfnStreamPlayEnd) 1707 pThis->pHostDrvAudio->pfnStreamPlayEnd(pThis->pHostDrvAudio, p HstStream->pvBackend);1565 pThis->pHostDrvAudio->pfnStreamPlayEnd(pThis->pHostDrvAudio, pStream->pvBackend); 1708 1566 } 1709 1567 1710 1568 if (RT_SUCCESS(rc)) 1711 1569 { 1712 AudioMixBufFinish(&p HstStream->MixBuf, cfPlayedTotal);1570 AudioMixBufFinish(&pStream->Host.MixBuf, cfPlayedTotal); 1713 1571 1714 1572 #ifdef VBOX_WITH_STATISTICS 1715 1573 STAM_COUNTER_ADD (&pThis->Stats.TotalFramesOut, cfPlayedTotal); 1716 1574 STAM_PROFILE_ADV_STOP(&pThis->Stats.DelayOut, out); 1717 STAM_COUNTER_ADD (&p HstStream->Out.Stats.FramesPlayed, cfPlayedTotal);1575 STAM_COUNTER_ADD (&pStream->Out.Stats.FramesPlayed, cfPlayedTotal); 1718 1576 #endif 1719 1577 } … … 1722 1580 1723 1581 #ifdef LOG_ENABLED 1724 uint32_t cfLive = AudioMixBufLive(&p HstStream->MixBuf);1725 pszStreamSts = dbgAudioStreamStatusToStr(sts HstStream);1726 Log3Func(("[%s] Buffer: End stsHstStream=%s, cfLive=%RU32, cfPlayedTotal=%RU32, rc=%Rrc\n",1727 p HstStream->szName, pszStreamSts, cfLive, cfPlayedTotal, rc));1582 uint32_t cfLive = AudioMixBufLive(&pStream->Host.MixBuf); 1583 pszStreamSts = dbgAudioStreamStatusToStr(stsStream); 1584 Log3Func(("[%s] Buffer: End fStatus=%s, cfLive=%RU32, cfPlayedTotal=%RU32, rc=%Rrc\n", 1585 pStream->szName, pszStreamSts, cfLive, cfPlayedTotal, rc)); 1728 1586 RTStrFree(pszStreamSts); 1729 1587 #endif /* LOG_ENABLED */ … … 1750 1608 * @returns IPRT status code. 1751 1609 * @param pThis Driver instance. 1752 * @param p HstStream Host stream to capture from.1610 * @param pStream Stream to capture from. 1753 1611 * @param pcfCaptured Number of (host) audio frames captured. Optional. 1754 1612 */ 1755 static int drvAudioStreamCaptureNonInterleaved(PDRVAUDIO pThis, PPDMAUDIOSTREAM p HstStream, uint32_t *pcfCaptured)1756 { 1757 AssertPtrReturn(pThis, 1758 AssertPtrReturn(p HstStream, VERR_INVALID_POINTER);1613 static int drvAudioStreamCaptureNonInterleaved(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcfCaptured) 1614 { 1615 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1616 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1759 1617 /* pcfCaptured is optional. */ 1760 1618 1761 1619 /* Sanity. */ 1762 Assert(pHstStream->enmCtx == PDMAUDIOSTREAMCTX_HOST); 1763 Assert(pHstStream->enmDir == PDMAUDIODIR_IN); 1764 Assert(pHstStream->Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED); 1620 Assert(pStream->enmDir == PDMAUDIODIR_IN); 1621 Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED); 1765 1622 1766 1623 int rc = VINF_SUCCESS; … … 1775 1632 for (;;) 1776 1633 { 1777 uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, p HstStream->pvBackend);1634 uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream->pvBackend); 1778 1635 if (!cbReadable) 1779 1636 { 1780 Log2Func(("[%s] No readable data available, skipping\n", p HstStream->szName));1637 Log2Func(("[%s] No readable data available, skipping\n", pStream->szName)); 1781 1638 break; 1782 1639 } 1783 1640 1784 uint32_t cbFree = AUDIOMIXBUF_F2B(&p HstStream->MixBuf, AudioMixBufFree(&pHstStream->MixBuf));1641 uint32_t cbFree = AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, AudioMixBufFree(&pStream->Host.MixBuf)); 1785 1642 if (!cbFree) 1786 1643 { 1787 Log2Func(("[%s] Host buffer full, skipping\n", p HstStream->szName));1644 Log2Func(("[%s] Host buffer full, skipping\n", pStream->szName)); 1788 1645 break; 1789 1646 } … … 1798 1655 1799 1656 uint32_t cbCaptured; 1800 rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, p HstStream->pvBackend,1657 rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStream->pvBackend, 1801 1658 auBuf, cbFree, &cbCaptured); 1802 1659 if (RT_FAILURE(rc)) 1803 1660 { 1804 int rc2 = drvAudioStreamControlInternalBackend(pThis, p HstStream, PDMAUDIOSTREAMCMD_DISABLE);1661 int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); 1805 1662 AssertRC(rc2); 1806 1663 } … … 1808 1665 { 1809 1666 if (pThis->In.Cfg.Dbg.fEnabled) 1810 DrvAudioHlpFileWrite(p HstStream->In.Dbg.pFileCaptureNonInterleaved, auBuf, cbCaptured, 0 /* fFlags */);1667 DrvAudioHlpFileWrite(pStream->In.Dbg.pFileCaptureNonInterleaved, auBuf, cbCaptured, 0 /* fFlags */); 1811 1668 1812 1669 Assert(cbCaptured <= cbBuf); … … 1815 1672 1816 1673 uint32_t cfCaptured = 0; 1817 rc = AudioMixBufWriteCirc(&p HstStream->MixBuf, auBuf, cbCaptured, &cfCaptured);1674 rc = AudioMixBufWriteCirc(&pStream->Host.MixBuf, auBuf, cbCaptured, &cfCaptured); 1818 1675 if (RT_SUCCESS(rc)) 1819 1676 cfCapturedTotal += cfCaptured; … … 1829 1686 { 1830 1687 if (cfCapturedTotal) 1831 Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", p HstStream->szName, cfCapturedTotal, rc));1688 Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCapturedTotal, rc)); 1832 1689 } 1833 1690 else 1834 LogFunc(("[%s] Capturing failed with rc=%Rrc\n", p HstStream->szName, rc));1691 LogFunc(("[%s] Capturing failed with rc=%Rrc\n", pStream->szName, rc)); 1835 1692 1836 1693 if (pcfCaptured) … … 1849 1706 * @returns IPRT status code. 1850 1707 * @param pThis Driver instance. 1851 * @param p HstStream Host stream to capture from.1708 * @param pStream Stream to capture from. 1852 1709 * @param pcfCaptured Number of (host) audio frames captured. Optional. 1853 1710 */ 1854 static int drvAudioStreamCaptureRaw(PDRVAUDIO pThis, PPDMAUDIOSTREAM p HstStream, uint32_t *pcfCaptured)1855 { 1856 AssertPtrReturn(pThis, 1857 AssertPtrReturn(p HstStream, VERR_INVALID_POINTER);1711 static int drvAudioStreamCaptureRaw(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcfCaptured) 1712 { 1713 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1714 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1858 1715 /* pcfCaptured is optional. */ 1859 1716 1860 1717 /* Sanity. */ 1861 Assert(pHstStream->enmCtx == PDMAUDIOSTREAMCTX_HOST); 1862 Assert(pHstStream->enmDir == PDMAUDIODIR_IN); 1863 Assert(pHstStream->Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW); 1718 Assert(pStream->enmDir == PDMAUDIODIR_IN); 1719 Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW); 1864 1720 1865 1721 int rc = VINF_SUCCESS; … … 1871 1727 for (;;) 1872 1728 { 1873 uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, p HstStream->pvBackend);1729 uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream->pvBackend); 1874 1730 if (!cbReadable) /* Nothing to read on the backend side? Bail out. */ 1875 1731 break; 1876 1732 1877 const uint32_t cbFree = AudioMixBufFreeBytes(&p HstStream->MixBuf);1733 const uint32_t cbFree = AudioMixBufFreeBytes(&pStream->Host.MixBuf); 1878 1734 if (!cbFree) /* No space left in the host stream? */ 1879 1735 break; … … 1884 1740 PPDMAUDIOFRAME paFrames; 1885 1741 uint32_t cfWritable; 1886 rc = AudioMixBufPeekMutable(&p HstStream->MixBuf, AUDIOMIXBUF_B2F(&pHstStream->MixBuf, cbReadable),1742 rc = AudioMixBufPeekMutable(&pStream->Host.MixBuf, AUDIOMIXBUF_B2F(&pStream->Host.MixBuf, cbReadable), 1887 1743 &paFrames, &cfWritable); 1888 1744 if ( RT_FAILURE(rc) … … 1893 1749 1894 1750 uint32_t cfCaptured; 1895 rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, p HstStream->pvBackend,1751 rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStream->pvBackend, 1896 1752 paFrames, cfWritable, &cfCaptured); 1897 1753 if (RT_FAILURE(rc)) 1898 1754 { 1899 int rc2 = drvAudioStreamControlInternalBackend(pThis, p HstStream, PDMAUDIOSTREAMCMD_DISABLE);1755 int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); 1900 1756 AssertRC(rc2); 1901 1757 } … … 1915 1771 } 1916 1772 1917 Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", p HstStream->szName, cfCapturedTotal, rc));1773 Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCapturedTotal, rc)); 1918 1774 1919 1775 if (pcfCaptured) … … 1946 1802 break; 1947 1803 1948 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);1949 AssertPtr(pHstStream);1950 PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : NULL;1951 AssertPtr(pGstStream);1952 1953 AssertReleaseMsgBreakStmt(pHstStream != NULL,1954 ("[%s] Host stream is NULL (cRefs=%RU32, fStatus=%x, enmCtx=%ld)\n",1955 pStream->szName, pStream->cRefs, pStream->fStatus, pStream->enmCtx),1956 rc = VERR_NOT_AVAILABLE);1957 AssertReleaseMsgBreakStmt(pGstStream != NULL,1958 ("[%s] Guest stream is NULL (cRefs=%RU32, fStatus=%x, enmCtx=%ld)\n",1959 pStream->szName, pStream->cRefs, pStream->fStatus, pStream->enmCtx),1960 rc = VERR_NOT_AVAILABLE);1961 1962 1804 /* 1963 1805 * Check if the backend is ready to operate. 1964 1806 */ 1965 1807 1966 PDMAUDIOSTREAMSTS sts HstStream = pHstStream->fStatus;1808 PDMAUDIOSTREAMSTS stsStream = pStream->fStatus; 1967 1809 #ifdef LOG_ENABLED 1968 char *pszStreamSts = dbgAudioStreamStatusToStr(sts HstStream);1969 Log3Func(("[%s] Start: stsHstStream=%s\n", pHstStream->szName, pszStreamSts));1810 char *pszStreamSts = dbgAudioStreamStatusToStr(stsStream); 1811 Log3Func(("[%s] Start: fStatus=%s\n", pStream->szName, pszStreamSts)); 1970 1812 RTStrFree(pszStreamSts); 1971 1813 #endif /* LOG_ENABLED */ 1972 if (!(sts HstStream & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) /* Stream disabled? Bail out. */1814 if (!(stsStream & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) /* Stream disabled? Bail out. */ 1973 1815 break; 1974 1816 … … 1978 1820 1979 1821 if (pThis->pHostDrvAudio->pfnStreamCaptureBegin) 1980 pThis->pHostDrvAudio->pfnStreamCaptureBegin(pThis->pHostDrvAudio, p HstStream->pvBackend);1981 1982 if (RT_LIKELY(p HstStream->Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED))1983 { 1984 rc = drvAudioStreamCaptureNonInterleaved(pThis, p HstStream, &cfCaptured);1985 } 1986 else if (p HstStream->Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW)1987 { 1988 rc = drvAudioStreamCaptureRaw(pThis, p HstStream, &cfCaptured);1822 pThis->pHostDrvAudio->pfnStreamCaptureBegin(pThis->pHostDrvAudio, pStream->pvBackend); 1823 1824 if (RT_LIKELY(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED)) 1825 { 1826 rc = drvAudioStreamCaptureNonInterleaved(pThis, pStream, &cfCaptured); 1827 } 1828 else if (pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW) 1829 { 1830 rc = drvAudioStreamCaptureRaw(pThis, pStream, &cfCaptured); 1989 1831 } 1990 1832 else … … 1992 1834 1993 1835 if (pThis->pHostDrvAudio->pfnStreamCaptureEnd) 1994 pThis->pHostDrvAudio->pfnStreamCaptureEnd(pThis->pHostDrvAudio, p HstStream->pvBackend);1836 pThis->pHostDrvAudio->pfnStreamCaptureEnd(pThis->pHostDrvAudio, pStream->pvBackend); 1995 1837 1996 1838 #ifdef LOG_ENABLED 1997 pszStreamSts = dbgAudioStreamStatusToStr(sts HstStream);1998 Log3Func(("[%s] End: stsHstStream=%s, cfCaptured=%RU32, rc=%Rrc\n",1999 p HstStream->szName, pszStreamSts, cfCaptured, rc));1839 pszStreamSts = dbgAudioStreamStatusToStr(stsStream); 1840 Log3Func(("[%s] End: fStatus=%s, cfCaptured=%RU32, rc=%Rrc\n", 1841 pStream->szName, pszStreamSts, cfCaptured, rc)); 2000 1842 RTStrFree(pszStreamSts); 2001 1843 #endif /* LOG_ENABLED */ … … 2003 1845 if (RT_SUCCESS(rc)) 2004 1846 { 2005 Log3Func(("[%s] %RU32 frames captured, rc=%Rrc\n", p HstStream->szName, cfCaptured, rc));1847 Log3Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCaptured, rc)); 2006 1848 2007 1849 #ifdef VBOX_WITH_STATISTICS 2008 1850 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesIn, cfCaptured); 2009 STAM_COUNTER_ADD(&p HstStream->In.Stats.FramesCaptured, cfCaptured);1851 STAM_COUNTER_ADD(&pStream->In.Stats.FramesCaptured, cfCaptured); 2010 1852 #endif 2011 1853 } 2012 1854 else if (RT_UNLIKELY(RT_FAILURE(rc))) 2013 1855 { 2014 LogRel(("Audio: Capturing stream '%s' failed with %Rrc\n", p HstStream->szName, rc));1856 LogRel(("Audio: Capturing stream '%s' failed with %Rrc\n", pStream->szName, rc)); 2015 1857 } 2016 1858 … … 2353 2195 if (pThis->pHostDrvAudio) 2354 2196 { 2355 PPDMAUDIOSTREAM p HstStream;2356 RTListForEach(&pThis->lst HstStreams, pHstStream, PDMAUDIOSTREAM, Node)2357 drvAudioStreamControlInternalBackend(pThis, p HstStream, enmCmd);2197 PPDMAUDIOSTREAM pStream; 2198 RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node) 2199 drvAudioStreamControlInternalBackend(pThis, pStream, enmCmd); 2358 2200 } 2359 2201 … … 2489 2331 } 2490 2332 2491 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);2492 if (!pHstStream)2493 {2494 rc = VERR_NOT_AVAILABLE;2495 break;2496 }2497 2498 PPDMAUDIOSTREAM pGstStream = pHstStream->pPair;2499 AssertPtr(pGstStream);2500 2501 2333 /* 2502 2334 * Read from the parent buffer (that is, the guest buffer) which … … 2505 2337 uint32_t cReadTotal = 0; 2506 2338 2507 uint32_t c ToRead = RT_MIN(AUDIOMIXBUF_B2F(&pGstStream->MixBuf, cbBuf), AudioMixBufUsed(&pGstStream->MixBuf));2508 while (c ToRead)2339 uint32_t cfToRead = RT_MIN(AUDIOMIXBUF_B2F(&pStream->Guest.MixBuf, cbBuf), AudioMixBufUsed(&pStream->Guest.MixBuf)); 2340 while (cfToRead) 2509 2341 { 2510 2342 uint32_t cRead; 2511 rc = AudioMixBufAcquireReadBlock(&pGstStream->MixBuf, (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pGstStream->MixBuf, cReadTotal), 2512 AUDIOMIXBUF_F2B(&pGstStream->MixBuf, cToRead), &cRead); 2343 rc = AudioMixBufAcquireReadBlock(&pStream->Guest.MixBuf, 2344 (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cReadTotal), 2345 AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfToRead), &cRead); 2513 2346 if (RT_FAILURE(rc)) 2514 2347 break; 2515 2348 2516 2349 #ifdef VBOX_WITH_STATISTICS 2517 const uint32_t cbRead = AUDIOMIXBUF_F2B(&p GstStream->MixBuf, cRead);2518 2519 STAM_COUNTER_ADD(&pThis->Stats.TotalBytesRead, 2520 STAM_COUNTER_ADD(&p GstStream->In.Stats.BytesTotalRead, cbRead);2350 const uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cRead); 2351 2352 STAM_COUNTER_ADD(&pThis->Stats.TotalBytesRead, cbRead); 2353 STAM_COUNTER_ADD(&pStream->In.Stats.BytesTotalRead, cbRead); 2521 2354 #endif 2522 Assert(c ToRead >= cRead);2523 c ToRead -= cRead;2355 Assert(cfToRead >= cRead); 2356 cfToRead -= cRead; 2524 2357 2525 2358 cReadTotal += cRead; 2526 2359 2527 AudioMixBufReleaseReadBlock(&p GstStream->MixBuf, cRead);2360 AudioMixBufReleaseReadBlock(&pStream->Guest.MixBuf, cRead); 2528 2361 } 2529 2362 … … 2531 2364 { 2532 2365 if (pThis->In.Cfg.Dbg.fEnabled) 2533 DrvAudioHlpFileWrite(p HstStream->In.Dbg.pFileStreamRead,2534 pvBuf, AUDIOMIXBUF_F2B(&p GstStream->MixBuf, cReadTotal), 0 /* fFlags */);2535 2536 AudioMixBufFinish(&p GstStream->MixBuf, cReadTotal);2537 2538 cbReadTotal = AUDIOMIXBUF_F2B(&p GstStream->MixBuf, cReadTotal);2366 DrvAudioHlpFileWrite(pStream->In.Dbg.pFileStreamRead, 2367 pvBuf, AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cReadTotal), 0 /* fFlags */); 2368 2369 AudioMixBufFinish(&pStream->Guest.MixBuf, cReadTotal); 2370 2371 cbReadTotal = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cReadTotal); 2539 2372 } 2540 2373 … … 2580 2413 #endif 2581 2414 2582 /* 2583 * The guest stream always will get the audio stream configuration told 2584 * by the device emulation (which in turn was/could be set by the guest OS). 2585 */ 2586 PPDMAUDIOSTREAM pGstStrm = NULL; 2587 2588 /** @todo Docs! */ 2589 PPDMAUDIOSTREAM pHstStrm = NULL; 2415 PPDMAUDIOSTREAM pStream = NULL; 2590 2416 2591 2417 #define RC_BREAK(x) { rc = x; break; } … … 2626 2452 } 2627 2453 2628 pHstStrm = (PPDMAUDIOSTREAM)RTMemAllocZ(sizeof(PDMAUDIOSTREAM)); 2629 AssertPtrBreakStmt(pHstStrm, rc = VERR_NO_MEMORY); 2630 2631 if (cbHstStrm) /* High unlikely that backends do not have an own space for data, but better check. */ 2632 { 2633 pHstStrm->pvBackend = RTMemAllocZ(cbHstStrm); 2634 AssertPtrBreakStmt(pHstStrm->pvBackend, rc = VERR_NO_MEMORY); 2635 2636 pHstStrm->cbBackend = cbHstStrm; 2637 } 2638 2639 pHstStrm->enmCtx = PDMAUDIOSTREAMCTX_HOST; 2640 pHstStrm->enmDir = pCfgHost->enmDir; 2641 2642 pGstStrm = (PPDMAUDIOSTREAM)RTMemAllocZ(sizeof(PDMAUDIOSTREAM)); 2643 AssertPtrBreakStmt(pGstStrm, rc = VERR_NO_MEMORY); 2644 2645 pGstStrm->enmCtx = PDMAUDIOSTREAMCTX_GUEST; 2646 pGstStrm->enmDir = pCfgGuest->enmDir; 2454 /* 2455 * Allocate and initialize common state. 2456 */ 2457 2458 pStream = (PPDMAUDIOSTREAM)RTMemAllocZ(sizeof(PDMAUDIOSTREAM)); 2459 AssertPtrBreakStmt(pStream, rc = VERR_NO_MEMORY); 2647 2460 2648 2461 /* Retrieve host driver name for easier identification. */ … … 2660 2473 } 2661 2474 2475 RTStrPrintf(pStream->szName, RT_ELEMENTS(pStream->szName), "[%s] %s", 2476 szDriver, strlen(pCfgHost->szName) ? pCfgHost->szName : "<Untitled>"); 2477 pStream->enmDir = pCfgHost->enmDir; 2478 2662 2479 /* 2663 * Init host stream.2480 * Allocate and init backend-specific data. 2664 2481 */ 2665 RTStrPrintf(pHstStrm->szName, RT_ELEMENTS(pHstStrm->szName), "[%s] %s (Host)", 2666 szDriver, strlen(pCfgHost->szName) ? pCfgHost->szName : "<Untitled>"); 2667 2668 rc = drvAudioStreamLinkToInternal(pHstStrm, pGstStrm); 2669 AssertRCBreak(rc); 2670 2671 /* 2672 * Init guest stream. 2673 */ 2674 RTStrPrintf(pGstStrm->szName, RT_ELEMENTS(pGstStrm->szName), "[%s] %s (Guest)", 2675 szDriver, strlen(pCfgGuest->szName) ? pCfgGuest->szName : "<Untitled>"); 2676 2677 pGstStrm->fStatus = pHstStrm->fStatus; /* Reflect the host stream's status. */ 2678 2679 rc = drvAudioStreamLinkToInternal(pGstStrm, pHstStrm); 2680 AssertRCBreak(rc); 2482 2483 if (cbHstStrm) /* High unlikely that backends do not have an own space for data, but better check. */ 2484 { 2485 pStream->pvBackend = RTMemAllocZ(cbHstStrm); 2486 AssertPtrBreakStmt(pStream->pvBackend, rc = VERR_NO_MEMORY); 2487 2488 pStream->cbBackend = cbHstStrm; 2489 } 2681 2490 2682 2491 /* 2683 2492 * Try to init the rest. 2684 2493 */ 2685 rc = drvAudioStreamInitInternal(pThis, pHstStrm, pCfgHost, pCfgGuest); 2494 2495 rc = drvAudioStreamInitInternal(pThis, pStream, pCfgHost, pCfgGuest); 2686 2496 if (RT_FAILURE(rc)) 2687 2497 break; 2688 2498 2689 #ifdef VBOX_WITH_STATISTICS2690 char szStatName[255];2691 2692 if (pCfgGuest->enmDir == PDMAUDIODIR_IN)2693 {2694 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/BytesElapsed", pGstStrm->szName);2695 PDMDrvHlpSTAMRegCounterEx(pThis->pDrvIns, &pGstStrm->In.Stats.BytesElapsed,2696 szStatName, STAMUNIT_BYTES, "Elapsed bytes read.");2697 2698 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/BytesRead", pGstStrm->szName);2699 PDMDrvHlpSTAMRegCounterEx(pThis->pDrvIns, &pGstStrm->In.Stats.BytesTotalRead,2700 szStatName, STAMUNIT_BYTES, "Total bytes read.");2701 2702 RTStrPrintf(szStatName, sizeof(szStatName), "Host/%s/FramesCaptured", pHstStrm->szName);2703 PDMDrvHlpSTAMRegCounterEx(pThis->pDrvIns, &pHstStrm->In.Stats.FramesCaptured,2704 szStatName, STAMUNIT_COUNT, "Total frames captured.");2705 }2706 else if (pCfgGuest->enmDir == PDMAUDIODIR_OUT)2707 {2708 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/BytesElapsed", pGstStrm->szName);2709 PDMDrvHlpSTAMRegCounterEx(pThis->pDrvIns, &pGstStrm->Out.Stats.BytesElapsed,2710 szStatName, STAMUNIT_BYTES, "Elapsed bytes written.");2711 2712 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/BytesWritten", pGstStrm->szName);2713 PDMDrvHlpSTAMRegCounterEx(pThis->pDrvIns, &pGstStrm->Out.Stats.BytesTotalWritten,2714 szStatName, STAMUNIT_BYTES, "Total bytes written.");2715 2716 RTStrPrintf(szStatName, sizeof(szStatName), "Host/%s/FramesPlayed", pHstStrm->szName);2717 PDMDrvHlpSTAMRegCounterEx(pThis->pDrvIns, &pHstStrm->Out.Stats.FramesPlayed,2718 szStatName, STAMUNIT_COUNT, "Total frames played.");2719 }2720 else2721 AssertFailed();2722 #endif2723 2724 2499 } while (0); 2725 2500 … … 2728 2503 if (RT_FAILURE(rc)) 2729 2504 { 2730 if (p GstStrm)2731 { 2732 int rc2 = drvAudioStreamUninitInternal(pThis, p GstStrm);2505 if (pStream) 2506 { 2507 int rc2 = drvAudioStreamUninitInternal(pThis, pStream); 2733 2508 if (RT_SUCCESS(rc2)) 2734 2509 { 2735 RTMemFree(pGstStrm);2736 p GstStrm = NULL;2510 drvAudioStreamFree(pStream); 2511 pStream = NULL; 2737 2512 } 2738 2513 } 2739 2740 if (pHstStrm)2741 {2742 int rc2 = drvAudioStreamUninitInternal(pThis, pHstStrm);2743 if (RT_SUCCESS(rc2))2744 {2745 drvAudioStreamFree(pHstStrm);2746 pHstStrm = NULL;2747 }2748 }2749 2514 } 2750 2515 else 2751 2516 { 2517 /* Append the stream to our stream list. */ 2518 RTListAppend(&pThis->lstStreams, &pStream->Node); 2519 2752 2520 /* Set initial reference counts. */ 2753 RTListAppend(&pThis->lstGstStreams, &pGstStrm->Node); 2754 pGstStrm->cRefs = 1; 2755 2756 RTListAppend(&pThis->lstHstStreams, &pHstStrm->Node); 2757 pHstStrm->cRefs = 1; 2521 pStream->cRefs = 1; 2758 2522 2759 2523 if (pCfgHost->enmDir == PDMAUDIODIR_IN) … … 2768 2532 { 2769 2533 rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szFile, PDMAUDIOFILE_FLAG_NONE, 2770 &p HstStrm->In.Dbg.pFileCaptureNonInterleaved);2534 &pStream->In.Dbg.pFileCaptureNonInterleaved); 2771 2535 if (RT_SUCCESS(rc2)) 2772 rc2 = DrvAudioHlpFileOpen(p HstStrm->In.Dbg.pFileCaptureNonInterleaved, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,2773 &p HstStrm->Cfg.Props);2536 rc2 = DrvAudioHlpFileOpen(pStream->In.Dbg.pFileCaptureNonInterleaved, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS, 2537 &pStream->Host.Cfg.Props); 2774 2538 } 2775 2539 … … 2781 2545 { 2782 2546 rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szFile, PDMAUDIOFILE_FLAG_NONE, 2783 &p HstStrm->In.Dbg.pFileStreamRead);2547 &pStream->In.Dbg.pFileStreamRead); 2784 2548 if (RT_SUCCESS(rc2)) 2785 rc2 = DrvAudioHlpFileOpen(p HstStrm->In.Dbg.pFileStreamRead, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,2786 &p HstStrm->Cfg.Props);2549 rc2 = DrvAudioHlpFileOpen(pStream->In.Dbg.pFileStreamRead, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS, 2550 &pStream->Host.Cfg.Props); 2787 2551 } 2788 2552 } … … 2803 2567 { 2804 2568 rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szFile, PDMAUDIOFILE_FLAG_NONE, 2805 &p HstStrm->Out.Dbg.pFilePlayNonInterleaved);2569 &pStream->Out.Dbg.pFilePlayNonInterleaved); 2806 2570 if (RT_SUCCESS(rc2)) 2807 rc = DrvAudioHlpFileOpen(p HstStrm->Out.Dbg.pFilePlayNonInterleaved, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,2808 &p HstStrm->Cfg.Props);2571 rc = DrvAudioHlpFileOpen(pStream->Out.Dbg.pFilePlayNonInterleaved, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS, 2572 &pStream->Host.Cfg.Props); 2809 2573 } 2810 2574 … … 2816 2580 { 2817 2581 rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szFile, PDMAUDIOFILE_FLAG_NONE, 2818 &p HstStrm->Out.Dbg.pFileStreamWrite);2582 &pStream->Out.Dbg.pFileStreamWrite); 2819 2583 if (RT_SUCCESS(rc2)) 2820 rc2 = DrvAudioHlpFileOpen(p HstStrm->Out.Dbg.pFileStreamWrite, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,2821 &p HstStrm->Cfg.Props);2584 rc2 = DrvAudioHlpFileOpen(pStream->Out.Dbg.pFileStreamWrite, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS, 2585 &pStream->Host.Cfg.Props); 2822 2586 } 2823 2587 } … … 2831 2595 STAM_COUNTER_ADD(&pThis->Stats.TotalStreamsCreated, 1); 2832 2596 #endif 2833 /* Always return the guest-side part to the device emulation. */ 2834 *ppStream = pGstStrm; 2597 *ppStream = pStream; 2835 2598 } 2836 2599 … … 2870 2633 2871 2634 PPDMAUDIOSTREAM pStream; 2872 RTListForEach(&pThis->lst HstStreams, pStream, PDMAUDIOSTREAM, Node)2635 RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node) 2873 2636 { 2874 2637 if (pStream->enmDir != enmDir) /* Skip unwanted streams. */ … … 3005 2768 AssertMsg(pStream->enmDir == PDMAUDIODIR_IN, ("Can't read from a non-input stream\n")); 3006 2769 3007 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 3008 if (!pHstStream) /* No host stream available? Bail out early. */ 3009 { 3010 rc2 = RTCritSectLeave(&pThis->CritSect); 3011 AssertRC(rc2); 3012 3013 return 0; 3014 } 3015 3016 uint32_t cbReadable = 0; 3017 3018 PPDMAUDIOSTREAM pGstStream = pHstStream->pPair; 3019 if (pGstStream) 3020 { 3021 uint32_t cfReadable = AudioMixBufLive(&pGstStream->MixBuf); 3022 3023 Log3Func(("[%s] cfReadable=%RU32 (%zu bytes)\n", pHstStream->szName, cfReadable, 3024 AUDIOMIXBUF_F2B(&pGstStream->MixBuf, cfReadable))); 3025 3026 cbReadable = AUDIOMIXBUF_F2B(&pGstStream->MixBuf, cfReadable); 3027 } 2770 const uint32_t cfReadable = AudioMixBufLive(&pStream->Guest.MixBuf); 2771 2772 Log3Func(("[%s] cfReadable=%RU32 (%zu bytes)\n", pStream->szName, cfReadable, 2773 AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadable))); 2774 2775 uint32_t cbReadable = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadable); 3028 2776 3029 2777 rc2 = RTCritSectLeave(&pThis->CritSect); … … 3049 2797 AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT, ("Can't write to a non-output stream\n")); 3050 2798 3051 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);3052 if (!pHstStream) /* No host stream available? Bail out early. */3053 {3054 rc2 = RTCritSectLeave(&pThis->CritSect);3055 AssertRC(rc2);3056 3057 AssertMsgFailed(("Guest stream '%s' does not have a host stream attached\n", pStream->szName));3058 return 0;3059 }3060 3061 2799 /* As the host side sets the overall pace, return the writable bytes from that side. */ 3062 const uint64_t deltaLastReadWriteNs = RTTimeNanoTS() - p HstStream->tsLastReadWrittenNs;2800 const uint64_t deltaLastReadWriteNs = RTTimeNanoTS() - pStream->tsLastReadWrittenNs; 3063 2801 3064 2802 uint32_t cbWritable = 0; 3065 2803 3066 if (DrvAudioHlpStreamStatusCanWrite(p HstStream->fStatus))3067 { 3068 cbWritable = DrvAudioHlpNanoToBytes(deltaLastReadWriteNs, &p HstStream->Cfg.Props);3069 3070 /* Make sure to align the writable size to the stream's frame size. */3071 cbWritable = DrvAudioHlpBytesAlign(cbWritable, &p HstStream->Cfg.Props);3072 } 3073 3074 Log3Func(("[%s] cbWritable=%RU32 (%RU64ms)\n", p HstStream->szName, cbWritable, deltaLastReadWriteNs / RT_NS_1MS_64));2804 if (DrvAudioHlpStreamStatusCanWrite(pStream->fStatus)) 2805 { 2806 cbWritable = DrvAudioHlpNanoToBytes(deltaLastReadWriteNs, &pStream->Host.Cfg.Props); 2807 2808 /* Make sure to align the writable size to the guest's frame size. */ 2809 cbWritable = DrvAudioHlpBytesAlign(cbWritable, &pStream->Guest.Cfg.Props); 2810 } 2811 2812 Log3Func(("[%s] cbWritable=%RU32 (%RU64ms)\n", pStream->szName, cbWritable, deltaLastReadWriteNs / RT_NS_1MS_64)); 3075 2813 3076 2814 rc2 = RTCritSectLeave(&pThis->CritSect); … … 3095 2833 AssertRC(rc2); 3096 2834 3097 PDMAUDIOSTREAMSTS stsStream = PDMAUDIOSTREAMSTS_FLAG_NONE; 3098 3099 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 3100 if (pHstStream) 3101 { 3102 /* If the connector is ready to operate, also make sure to ask the backend. */ 3103 stsStream = pHstStream->fStatus; 3104 if (DrvAudioHlpStreamStatusIsReady(stsStream)) 3105 stsStream = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream->pvBackend); 2835 /* If the connector is ready to operate, also make sure to ask the backend. */ 2836 PDMAUDIOSTREAMSTS stsStream = pStream->fStatus; 2837 if (DrvAudioHlpStreamStatusIsReady(stsStream)) 2838 stsStream = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStream->pvBackend); 3106 2839 3107 2840 #ifdef LOG_ENABLED 3108 3109 Log3Func(("[%s] %s\n", pHstStream->szName, pszStreamSts));3110 2841 char *pszStreamSts = dbgAudioStreamStatusToStr(stsStream); 2842 Log3Func(("[%s] %s\n", pStream->szName, pszStreamSts)); 2843 RTStrFree(pszStreamSts); 3111 2844 #endif 3112 }3113 2845 3114 2846 rc2 = RTCritSectLeave(&pThis->CritSect); … … 3129 2861 LogFlowFunc(("[%s] volL=%RU32, volR=%RU32, fMute=%RTbool\n", pStream->szName, pVol->uLeft, pVol->uRight, pVol->fMuted)); 3130 2862 3131 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 3132 PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : pStream; 3133 3134 AudioMixBufSetVolume(&pHstStream->MixBuf, pVol); 3135 AudioMixBufSetVolume(&pGstStream->MixBuf, pVol); 2863 AudioMixBufSetVolume(&pStream->Guest.MixBuf, pVol); 2864 AudioMixBufSetVolume(&pStream->Host.MixBuf, pVol); 2865 3136 2866 return VINF_SUCCESS; 3137 2867 } … … 3150 2880 AssertRC(rc); 3151 2881 3152 PDMAUDIODIR enmDir = pStream->enmDir;2882 LogRel2(("Audio: Destroying stream '%s'\n", pStream->szName)); 3153 2883 3154 2884 LogFlowFunc(("[%s] cRefs=%RU32\n", pStream->szName, pStream->cRefs)); … … 3158 2888 if (RT_SUCCESS(rc)) 3159 2889 { 3160 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 3161 PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : pStream; 3162 3163 LogRel2(("Audio: Destroying host stream '%s' (guest stream '%s')\n", 3164 pHstStream ? pHstStream->szName : "<None>", 3165 pGstStream ? pGstStream->szName : "<None>")); 3166 3167 /* Should prevent double frees. */ 3168 Assert(pHstStream != pGstStream); 3169 3170 if (pHstStream) 3171 { 3172 rc = drvAudioStreamUninitInternal(pThis, pHstStream); 3173 if (RT_SUCCESS(rc)) 3174 { 3175 if (pHstStream->enmDir == PDMAUDIODIR_IN) 3176 { 3177 #ifdef VBOX_WITH_STATISTICS 3178 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pHstStream->In.Stats.FramesCaptured); 3179 #endif 3180 if (pThis->In.Cfg.Dbg.fEnabled) 3181 { 3182 DrvAudioHlpFileDestroy(pHstStream->In.Dbg.pFileCaptureNonInterleaved); 3183 DrvAudioHlpFileDestroy(pHstStream->In.Dbg.pFileStreamRead); 3184 } 3185 } 3186 else if (pHstStream->enmDir == PDMAUDIODIR_OUT) 3187 { 3188 #ifdef VBOX_WITH_STATISTICS 3189 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pHstStream->Out.Stats.FramesPlayed); 3190 #endif 3191 if (pThis->Out.Cfg.Dbg.fEnabled) 3192 { 3193 DrvAudioHlpFileDestroy(pHstStream->Out.Dbg.pFilePlayNonInterleaved); 3194 DrvAudioHlpFileDestroy(pHstStream->Out.Dbg.pFileStreamWrite); 3195 } 3196 } 3197 else 3198 AssertFailed(); 3199 3200 RTListNodeRemove(&pHstStream->Node); 3201 3202 drvAudioStreamFree(pHstStream); 3203 pHstStream = NULL; 3204 } 3205 else 3206 LogRel(("Audio: Uninitializing host stream '%s' failed with %Rrc\n", pHstStream->szName, rc)); 3207 } 3208 3209 if ( RT_SUCCESS(rc) 3210 && pGstStream) 3211 { 3212 rc = drvAudioStreamUninitInternal(pThis, pGstStream); 3213 if (RT_SUCCESS(rc)) 3214 { 3215 #ifdef VBOX_WITH_STATISTICS 3216 if (pGstStream->enmDir == PDMAUDIODIR_IN) 3217 { 3218 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pGstStream->In.Stats.BytesElapsed); 3219 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pGstStream->In.Stats.BytesTotalRead); 3220 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pGstStream->In.Stats.FramesCaptured); 3221 } 3222 else if (pGstStream->enmDir == PDMAUDIODIR_OUT) 3223 { 3224 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pGstStream->Out.Stats.BytesElapsed); 3225 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pGstStream->Out.Stats.BytesTotalWritten); 3226 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pGstStream->Out.Stats.FramesPlayed); 3227 } 3228 else 3229 AssertFailed(); 3230 #endif 3231 RTListNodeRemove(&pGstStream->Node); 3232 3233 RTMemFree(pGstStream); 3234 pGstStream = NULL; 3235 } 3236 else 3237 LogRel(("Audio: Uninitializing guest stream '%s' failed with %Rrc\n", pGstStream->szName, rc)); 3238 } 2890 rc = drvAudioStreamUninitInternal(pThis, pStream); 2891 if (RT_FAILURE(rc)) 2892 LogRel(("Audio: Uninitializing stream '%s' failed with %Rrc\n", pStream->szName, rc)); 3239 2893 } 3240 2894 3241 2895 if (RT_SUCCESS(rc)) 3242 2896 { 3243 if ( enmDir == PDMAUDIODIR_IN)2897 if (pStream->enmDir == PDMAUDIODIR_IN) 3244 2898 { 3245 2899 pThis->In.cStreamsFree++; … … 3249 2903 pThis->Out.cStreamsFree++; 3250 2904 } 2905 2906 RTListNodeRemove(&pStream->Node); 2907 2908 drvAudioStreamFree(pStream); 2909 pStream = NULL; 3251 2910 } 3252 2911 … … 3264 2923 * @returns IPRT status code. 3265 2924 * @param pThis Pointer to driver instance. 3266 * @param p HstStream (Host) audio stream to use for creating the stream on the backend side.2925 * @param pStream Audio stream to create the backend side for. 3267 2926 * @param pCfgReq Requested audio stream configuration to use for stream creation. 3268 2927 * @param pCfgAcq Acquired audio stream configuration returned by the backend. 3269 2928 */ 3270 2929 static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, 3271 PPDMAUDIOSTREAM pHstStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq) 3272 { 3273 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 3274 AssertPtrReturn(pHstStream, VERR_INVALID_POINTER); 3275 AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER); 3276 AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER); 3277 3278 AssertMsg(pHstStream->enmCtx == PDMAUDIOSTREAMCTX_HOST, 3279 ("Stream '%s' is not a host stream and therefore has no backend\n", pHstStream->szName)); 3280 3281 AssertMsg((pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_INITIALIZED) == 0, 3282 ("Stream '%s' already initialized in backend\n", pHstStream->szName)); 2930 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq) 2931 { 2932 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 2933 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 2934 AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER); 2935 AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER); 2936 2937 AssertMsg((pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_INITIALIZED) == 0, 2938 ("Stream '%s' already initialized in backend\n", pStream->szName)); 3283 2939 3284 2940 /* Get the right configuration for the stream to be created. */ … … 3298 2954 LogRel2(("Audio: Using %s period size (%RU32ms, %RU32 frames) for stream '%s'\n", 3299 2955 pDrvCfg->uPeriodMs ? "custom" : "default", DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfPeriod, &pCfgReq->Props), 3300 pCfgReq->Backend.cfPeriod, p HstStream->szName));2956 pCfgReq->Backend.cfPeriod, pStream->szName)); 3301 2957 3302 2958 /* … … 3310 2966 LogRel2(("Audio: Using %s buffer size (%RU32ms, %RU32 frames) for stream '%s'\n", 3311 2967 pDrvCfg->uBufferSizeMs ? "custom" : "default", DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfBufferSize, &pCfgReq->Props), 3312 pCfgReq->Backend.cfBufferSize, p HstStream->szName));2968 pCfgReq->Backend.cfBufferSize, pStream->szName)); 3313 2969 3314 2970 /* … … 3318 2974 { 3319 2975 if (!pDrvCfg->uPreBufMs) /* Pre-buffering is set to disabled. */ 3320 LogRel2(("Audio: Using custom pre-buffering (disabled) for stream '%s'\n", p HstStream->szName));2976 LogRel2(("Audio: Using custom pre-buffering (disabled) for stream '%s'\n", pStream->szName)); 3321 2977 pCfgReq->Backend.cfPreBuf = DrvAudioHlpMilliToFrames(pDrvCfg->uPreBufMs, &pCfgReq->Props); 3322 2978 } … … 3326 2982 LogRel2(("Audio: Using %s pre-buffering size (%RU32ms, %RU32 frames) for stream '%s'\n", 3327 2983 pDrvCfg->uPreBufMs != UINT32_MAX ? "custom" : "default", DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfPreBuf, &pCfgReq->Props), 3328 pCfgReq->Backend.cfPreBuf, p HstStream->szName));2984 pCfgReq->Backend.cfPreBuf, pStream->szName)); 3329 2985 3330 2986 /* … … 3334 2990 { 3335 2991 LogRel(("Audio: Error for stream '%s': Buffer size (%RU32ms) must not be smaller than the period size (%RU32ms)\n", 3336 p HstStream->szName, DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfBufferSize, &pCfgReq->Props),2992 pStream->szName, DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfBufferSize, &pCfgReq->Props), 3337 2993 DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfPeriod, &pCfgReq->Props))); 3338 2994 return VERR_INVALID_PARAMETER; … … 3345 3001 { 3346 3002 LogRel(("Audio: Error for stream '%s': Pre-buffering size (%RU32ms) must not be bigger than the buffer size (%RU32ms)\n", 3347 p HstStream->szName, DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfPreBuf, &pCfgReq->Props),3003 pStream->szName, DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfPreBuf, &pCfgReq->Props), 3348 3004 DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfBufferSize, &pCfgReq->Props))); 3349 3005 return VERR_INVALID_PARAMETER; … … 3357 3013 { 3358 3014 LogRel(("Audio: Creating stream '%s' with an invalid backend configuration not possible, skipping\n", 3359 p HstStream->szName));3015 pStream->szName)); 3360 3016 return rc; 3361 3017 } 3362 3018 3363 rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, p HstStream->pvBackend, pCfgReq, pCfgAcq);3019 rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pStream->pvBackend, pCfgReq, pCfgAcq); 3364 3020 if (RT_FAILURE(rc)) 3365 3021 { 3366 3022 if (rc == VERR_NOT_SUPPORTED) 3367 LogRel2(("Audio: Creating stream '%s' in backend not supported, skipping\n", p HstStream->szName));3023 LogRel2(("Audio: Creating stream '%s' in backend not supported, skipping\n", pStream->szName)); 3368 3024 else 3369 LogRel(("Audio: Creating stream '%s' in backend failed with %Rrc\n", p HstStream->szName, rc));3025 LogRel(("Audio: Creating stream '%s' in backend failed with %Rrc\n", pStream->szName, rc)); 3370 3026 3371 3027 return rc; … … 3375 3031 if (!DrvAudioHlpStreamCfgIsValid(pCfgAcq)) 3376 3032 { 3377 LogRel(("Audio: Creating stream '%s' returned an invalid backend configuration, skipping\n", p HstStream->szName));3033 LogRel(("Audio: Creating stream '%s' returned an invalid backend configuration, skipping\n", pStream->szName)); 3378 3034 return VERR_INVALID_PARAMETER; 3379 3035 } … … 3384 3040 { 3385 3041 LogRel2(("Audio: Custom buffer size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n", 3386 p HstStream->szName, DrvAudioHlpFramesToMilli(pCfgAcq->Backend.cfBufferSize, &pCfgAcq->Props), pCfgAcq->Backend.cfBufferSize));3042 pStream->szName, DrvAudioHlpFramesToMilli(pCfgAcq->Backend.cfBufferSize, &pCfgAcq->Props), pCfgAcq->Backend.cfBufferSize)); 3387 3043 } 3388 3044 … … 3391 3047 { 3392 3048 LogRel2(("Audio: Custom period size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n", 3393 p HstStream->szName, DrvAudioHlpFramesToMilli(pCfgAcq->Backend.cfPeriod, &pCfgAcq->Props), pCfgAcq->Backend.cfPeriod));3049 pStream->szName, DrvAudioHlpFramesToMilli(pCfgAcq->Backend.cfPeriod, &pCfgAcq->Props), pCfgAcq->Backend.cfPeriod)); 3394 3050 } 3395 3051 … … 3398 3054 { 3399 3055 LogRel2(("Audio: Custom pre-buffering size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n", 3400 pHstStream->szName, DrvAudioHlpFramesToMilli(pCfgAcq->Backend.cfPreBuf, &pCfgAcq->Props), pCfgAcq->Backend.cfPreBuf)); 3401 } 3402 3403 /* Only set the host's stream to initialized if we were able create the stream 3404 * in the host backend. This is necessary for trying to re-initialize the stream 3405 * at some later point in time. */ 3406 pHstStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_INITIALIZED; 3056 pStream->szName, DrvAudioHlpFramesToMilli(pCfgAcq->Backend.cfPreBuf, &pCfgAcq->Props), pCfgAcq->Backend.cfPreBuf)); 3057 } 3058 3059 pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_INITIALIZED; 3407 3060 3408 3061 return VINF_SUCCESS; … … 3414 3067 * @returns IPRT status code. 3415 3068 * @param pThis Pointer to driver instance. 3416 * @param pHstStream Host audio stream to call the backend destruction for. 3417 */ 3418 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream) 3419 { 3420 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 3421 AssertPtrReturn(pHstStream, VERR_INVALID_POINTER); 3422 3423 AssertMsg(pHstStream->enmCtx == PDMAUDIOSTREAMCTX_HOST, 3424 ("Stream '%s' is not a host stream and therefore has no backend\n", pHstStream->szName)); 3069 * @param pStream Audio stream destruct backend for. 3070 */ 3071 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream) 3072 { 3073 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 3074 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 3425 3075 3426 3076 int rc = VINF_SUCCESS; 3427 3077 3428 3078 #ifdef LOG_ENABLED 3429 char *pszHstSts = dbgAudioStreamStatusToStr(pHstStream->fStatus); 3430 LogFunc(("[%s] fStatus=%s\n", pHstStream->szName, pszHstSts)); 3431 RTStrFree(pszHstSts); 3079 char *pszStreamSts = dbgAudioStreamStatusToStr(pStream->fStatus); 3080 LogFunc(("[%s] fStatus=%s\n", pStream->szName, pszStreamSts)); 3432 3081 #endif 3433 3082 3434 if (p HstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_INITIALIZED)3083 if (pStream->pvBackend) 3435 3084 { 3436 3085 /* Check if the pointer to the host audio driver is still valid. 3437 3086 * It can be NULL if we were called in drvAudioDestruct, for example. */ 3438 3087 if (pThis->pHostDrvAudio) 3439 rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pHstStream->pvBackend); 3440 if (RT_SUCCESS(rc)) 3441 { 3442 pHstStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_INITIALIZED; 3088 rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pStream->pvBackend); 3089 3090 pStream->pvBackend = NULL; 3091 pStream->cbBackend = 0; 3092 } 3443 3093 3444 3094 #ifdef LOG_ENABLED 3445 /* This is not fatal, but log it anyway. */ 3446 if (pHstStream->fStatus != PDMAUDIOSTREAMSTS_FLAG_NONE) 3447 LogFunc(("[%s] Warning: Stream still has %s set when destroying, must properly drain first\n", 3448 pHstStream->szName, pszHstSts)); 3095 RTStrFree(pszStreamSts); 3449 3096 #endif 3450 } 3451 } 3452 3453 LogFlowFunc(("[%s] Returning %Rrc\n", pHstStream->szName, rc)); 3097 3098 LogFlowFunc(("[%s] Returning %Rrc\n", pStream->szName, rc)); 3454 3099 return rc; 3455 3100 } … … 3472 3117 return VERR_WRONG_ORDER; 3473 3118 3474 int rc = VINF_SUCCESS; 3475 3476 if (pStream->enmCtx == PDMAUDIOSTREAMCTX_GUEST) 3477 { 3478 if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_INITIALIZED) 3479 { 3480 rc = drvAudioStreamControlInternal(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); 3481 if (RT_SUCCESS(rc)) 3482 { 3483 pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_INITIALIZED; 3484 Assert(pStream->fStatus == PDMAUDIOSTREAMSTS_FLAG_NONE); 3485 } 3486 } 3487 } 3488 else if (pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST) 3489 { 3119 int rc = drvAudioStreamControlInternal(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); 3120 if (RT_SUCCESS(rc)) 3490 3121 rc = drvAudioStreamDestroyInternalBackend(pThis, pStream); 3122 3123 /* Destroy mixing buffers. */ 3124 AudioMixBufDestroy(&pStream->Guest.MixBuf); 3125 AudioMixBufDestroy(&pStream->Host.MixBuf); 3126 3127 if (RT_SUCCESS(rc)) 3128 { 3129 /* Reset status. */ 3130 pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_INITIALIZED; 3131 3132 #ifdef VBOX_STRICT 3133 if (pStream->fStatus != PDMAUDIOSTREAMSTS_FLAG_NONE) 3134 { 3135 char *pszStreamSts = dbgAudioStreamStatusToStr(pStream->fStatus); 3136 LogFunc(("[%s] Warning: Still has %s set when uninitializing\n", pStream->szName, pszStreamSts)); 3137 RTStrFree(pszStreamSts); 3138 } 3139 #endif 3140 pStream->fStatus = PDMAUDIOSTREAMSTS_FLAG_NONE; 3141 } 3142 3143 if (pStream->enmDir == PDMAUDIODIR_IN) 3144 { 3145 #ifdef VBOX_WITH_STATISTICS 3146 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pStream->In.Stats.BytesElapsed); 3147 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pStream->In.Stats.BytesTotalRead); 3148 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pStream->In.Stats.FramesCaptured); 3149 #endif 3150 if (pThis->In.Cfg.Dbg.fEnabled) 3151 { 3152 DrvAudioHlpFileDestroy(pStream->In.Dbg.pFileCaptureNonInterleaved); 3153 pStream->In.Dbg.pFileCaptureNonInterleaved = NULL; 3154 3155 DrvAudioHlpFileDestroy(pStream->In.Dbg.pFileStreamRead); 3156 pStream->In.Dbg.pFileStreamRead = NULL; 3157 } 3158 } 3159 else if (pStream->enmDir == PDMAUDIODIR_OUT) 3160 { 3161 #ifdef VBOX_WITH_STATISTICS 3162 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pStream->Out.Stats.BytesElapsed); 3163 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pStream->Out.Stats.BytesTotalWritten); 3164 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pStream->Out.Stats.FramesPlayed); 3165 #endif 3166 if (pThis->Out.Cfg.Dbg.fEnabled) 3167 { 3168 DrvAudioHlpFileDestroy(pStream->Out.Dbg.pFilePlayNonInterleaved); 3169 pStream->Out.Dbg.pFilePlayNonInterleaved = NULL; 3170 3171 DrvAudioHlpFileDestroy(pStream->Out.Dbg.pFileStreamWrite); 3172 pStream->Out.Dbg.pFileStreamWrite = NULL; 3173 } 3491 3174 } 3492 3175 else 3493 AssertFailedReturn(VERR_NOT_IMPLEMENTED); 3494 3495 if (RT_SUCCESS(rc)) 3496 { 3497 /* Make sure that the pair (if any) knows that we're not valid anymore. */ 3498 int rc2 = drvAudioStreamLinkToInternal(pStream, NULL); 3499 AssertRC(rc2); 3500 3501 /* Reset status. */ 3502 pStream->fStatus = PDMAUDIOSTREAMSTS_FLAG_NONE; 3503 3504 /* Destroy mixing buffer. */ 3505 AudioMixBufDestroy(&pStream->MixBuf); 3506 } 3176 AssertFailed(); 3507 3177 3508 3178 LogFlowFunc(("Returning %Rrc\n", rc)); … … 3587 3257 * in drvAudioDestruct(). */ 3588 3258 PPDMAUDIOSTREAM pStream; 3589 RTListForEach(&pThis->lst HstStreams, pStream, PDMAUDIOSTREAM, Node)3259 RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node) 3590 3260 { 3591 3261 drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); … … 3617 3287 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); 3618 3288 3619 RTListInit(&pThis->lstHstStreams); 3620 RTListInit(&pThis->lstGstStreams); 3289 RTListInit(&pThis->lstStreams); 3621 3290 #ifdef VBOX_WITH_AUDIO_CALLBACKS 3622 3291 RTListInit(&pThis->In.lstCB); … … 3733 3402 3734 3403 PPDMAUDIOSTREAM pStream, pStreamNext; 3735 RTListForEachSafe(&pThis->lst HstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, Node)3404 RTListForEachSafe(&pThis->lstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, Node) 3736 3405 { 3737 3406 rc2 = drvAudioStreamUninitInternal(pThis, pStream); … … 3746 3415 3747 3416 /* Sanity. */ 3748 Assert(RTListIsEmpty(&pThis->lstHstStreams)); 3749 3750 RTListForEachSafe(&pThis->lstGstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, Node) 3751 { 3752 rc2 = drvAudioStreamUninitInternal(pThis, pStream); 3753 if (RT_SUCCESS(rc2)) 3754 { 3755 RTListNodeRemove(&pStream->Node); 3756 3757 RTMemFree(pStream); 3758 pStream = NULL; 3759 } 3760 } 3761 3762 /* Sanity. */ 3763 Assert(RTListIsEmpty(&pThis->lstGstStreams)); 3417 Assert(RTListIsEmpty(&pThis->lstStreams)); 3764 3418 3765 3419 #ifdef VBOX_WITH_AUDIO_CALLBACKS -
trunk/src/VBox/Devices/Audio/DrvAudio.h
r73429 r73467 123 123 /** Pointer to CFGM configuration node of this driver. */ 124 124 PCFGMNODE pCFGMNode; 125 /** List of host input/output audio streams. */ 126 RTLISTANCHOR lstHstStreams; 127 /** List of guest input/output audio streams. */ 128 RTLISTANCHOR lstGstStreams; 125 /** List of audio streams. */ 126 RTLISTANCHOR lstStreams; 129 127 #ifdef VBOX_WITH_AUDIO_ENUM 130 128 /** Flag indicating to perform an (re-)enumeration of the host audio devices. */
Note:
See TracChangeset
for help on using the changeset viewer.