VirtualBox

Changeset 73467 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Aug 3, 2018 9:49:55 AM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
124094
Message:

DrvAudio: Cleaned up the internal stream organization by not duplicating stuff like the status and the like by having two PDMAUDIOSTREAMs (on for the guest side and one for the host side). Instead, only use PDMAUDIOSTREAM and keep the guest and host specifics in PDMAUDIOSTREAMCTX. Should help simplifying things a lot.

Location:
trunk/src/VBox/Devices/Audio
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r73432 r73467  
    4848static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd);
    4949static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd);
    50 static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq);
    51 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream);
     50static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq);
     51static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
    5252static void drvAudioStreamFree(PPDMAUDIOSTREAM pStream);
    5353static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
     
    5555static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
    5656static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
    57 static int drvAudioStreamLinkToInternal(PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAM pPair);
     57static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
    5858
    5959#ifndef VBOX_AUDIO_TESTCASE
     
    191191#endif /* defined(VBOX_STRICT) || defined(LOG_ENABLED) */
    192192
    193 /**
    194  * Returns the host stream part of an audio stream pair, or NULL
    195  * 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_HOST
    208                                ? pStream
    209                                : 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     else
    220         LogRel(("Audio: Warning: Stream '%s' does not have a host stream (anymore)\n", pStream->szName));
    221 
    222     return pHstStream;
    223 }
    224 
    225193# if 0 /* unused */
    226194static int drvAudioProcessOptions(PCFGMNODE pCfgHandle, const char *pszPrefix, audio_option *paOpts, size_t cOpts)
     
    361329    LogFunc(("[%s] enmStreamCmd=%s\n", pStream->szName, DrvAudioHlpStreamCmdToStr(enmStreamCmd)));
    362330
    363     PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
    364     PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : pStream;
    365     AssertPtr(pGstStream);
    366 
    367331#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);
    373335#endif /* LOG_ENABLED */
    374336
     
    379341        case PDMAUDIOSTREAMCMD_ENABLE:
    380342        {
    381             if (!(pGstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED))
     343            if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED))
    382344            {
    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);
    392348
    393349                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;
    395354            }
    396355            break;
     
    399358        case PDMAUDIOSTREAMCMD_DISABLE:
    400359        {
    401             if (pGstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED)
     360            if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED)
    402361            {
    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)
    404368                {
    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;
    419371                }
    420372
    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                }
    423380            }
    424381            break;
     
    427384        case PDMAUDIOSTREAMCMD_PAUSE:
    428385        {
    429             if (!(pGstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED))
     386            if (!(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED))
    430387            {
    431                 if (pHstStream)
    432                     rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_PAUSE);
    433 
     388                rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_PAUSE);
    434389                if (RT_SUCCESS(rc))
    435                     pGstStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_PAUSED;
     390                    pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_PAUSED;
    436391            }
    437392            break;
     
    440395        case PDMAUDIOSTREAMCMD_RESUME:
    441396        {
    442             if (pGstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED)
     397            if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED)
    443398            {
    444                 if (pHstStream)
    445                     rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_RESUME);
    446 
     399                rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_RESUME);
    447400                if (RT_SUCCESS(rc))
    448                     pGstStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_PAUSED;
     401                    pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_PAUSED;
    449402            }
    450403            break;
     
    477430    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    478431
    479     PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
    480     if (!pHstStream) /* Stream does not have a host backend? Bail out. */
    481         return VERR_NOT_FOUND;
    482 
    483432#ifdef LOG_ENABLED
    484     char *pszHstSts = dbgAudioStreamStatusToStr(pHstStream->fStatus);
    485     LogFlowFunc(("[%s] enmStreamCmd=%s, fStatus=%s\n", pHstStream->szName, DrvAudioHlpStreamCmdToStr(enmStreamCmd), pszHstSts));
    486     RTStrFree(pszHstSts);
     433    char *pszStreamSts = dbgAudioStreamStatusToStr(pStream->fStatus);
     434    LogFlowFunc(("[%s] enmStreamCmd=%s, fStatus=%s\n", pStream->szName, DrvAudioHlpStreamCmdToStr(enmStreamCmd), pszStreamSts));
     435    RTStrFree(pszStreamSts);
    487436#endif /* LOG_ENABLED */
    488437
    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));
    492442
    493443    int rc = VINF_SUCCESS;
     
    497447        case PDMAUDIOSTREAMCMD_ENABLE:
    498448        {
    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)
    500457            {
    501                 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream->pvBackend,
    502                                                             PDMAUDIOSTREAMCMD_ENABLE);
     458                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_DISABLE);
    503459                if (RT_SUCCESS(rc))
    504                 {
    505                     pHstStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_ENABLED;
    506                 }
     460                    AudioMixBufReset(&pStream->Host.MixBuf);
    507461            }
    508462            break;
    509463        }
    510464
    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);
    523473            break;
    524474        }
    525475
    526         case PDMAUDIOSTREAMCMD_PAUSE:
    527         {
    528             /* Only pause if the stream is enabled. */
    529             if (!(pHstStream->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))
    530480                break;
    531481
    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);
    541484            break;
    542485        }
    543486
    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 
    562487        case PDMAUDIOSTREAMCMD_DRAIN:
    563488        {
    564             rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream->pvBackend, PDMAUDIOSTREAMCMD_DRAIN);
     489            rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream->pvBackend, PDMAUDIOSTREAMCMD_DRAIN);
    565490            break;
    566491        }
     
    578503        if (   rc != VERR_NOT_IMPLEMENTED
    579504            && rc != VERR_NOT_SUPPORTED)
    580             LogRel(("Audio: %s stream '%s' failed with %Rrc\n", DrvAudioHlpStreamCmdToStr(enmStreamCmd), pHstStream->szName, rc));
     505            LogRel(("Audio: %s stream '%s' failed with %Rrc\n", DrvAudioHlpStreamCmdToStr(enmStreamCmd), pStream->szName, rc));
    581506
    582507        LogFunc(("[%s] %s failed with %Rrc\n", pStream->szName, DrvAudioHlpStreamCmdToStr(enmStreamCmd), rc));
     
    603528    AssertPtrReturn(pCfgGuest, VERR_INVALID_POINTER);
    604529
    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_IN
    611                                                        ? pThis->In.msLatencyHost : pThis->Out.msLatencyHost);*/
    612     /* Latency can be 0 if not configured. */
    613 
    614530    /*
    615531     * Init host stream.
     
    620536
    621537#ifdef DEBUG
    622     LogFunc(("[%s] Requested host format:\n", pHstStream->szName));
     538    LogFunc(("[%s] Requested host format:\n", pStream->szName));
    623539    DrvAudioHlpStreamCfgPrint(pCfgHost);
    624540#endif
    625541
    626     LogRel2(("Audio: Creating stream '%s'\n", pHstStream->szName));
     542    LogRel2(("Audio: Creating stream '%s'\n", pStream->szName));
    627543    LogRel2(("Audio: Guest %s format for '%s': %RU32Hz, %RU8%s, %RU8 %s\n",
    628              pCfgGuest->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pGstStream->szName,
     544             pCfgGuest->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStream->szName,
    629545             pCfgGuest->Props.uHz, pCfgGuest->Props.cBits, pCfgGuest->Props.fSigned ? "S" : "U",
    630546             pCfgGuest->Props.cChannels, pCfgGuest->Props.cChannels == 1 ? "Channel" : "Channels"));
    631547    LogRel2(("Audio: Requested host %s format for '%s': %RU32Hz, %RU8%s, %RU8 %s\n",
    632              pCfgHost->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pHstStream->szName,
     548             pCfgHost->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStream->szName,
    633549             pCfgHost->Props.uHz, pCfgHost->Props.cBits, pCfgHost->Props.fSigned ? "S" : "U",
    634550             pCfgHost->Props.cChannels, pCfgHost->Props.cChannels == 1 ? "Channel" : "Channels"));
    635551
    636552    PDMAUDIOSTREAMCFG CfgHostAcq;
    637     int rc = drvAudioStreamCreateInternalBackend(pThis, pHstStream, pCfgHost, &CfgHostAcq);
     553    int rc = drvAudioStreamCreateInternalBackend(pThis, pStream, pCfgHost, &CfgHostAcq);
    638554    if (RT_FAILURE(rc))
    639555        return rc;
    640556
    641557#ifdef DEBUG
    642     LogFunc(("[%s] Acquired host format:\n",  pHstStream->szName));
     558    LogFunc(("[%s] Acquired host format:\n",  pStream->szName));
    643559    DrvAudioHlpStreamCfgPrint(&CfgHostAcq);
    644560#endif
     
    672588        LogRel2(("Audio: Warning: Pre-buffering size (%RU32 frames) of stream '%s' does not match buffer size (%RU32 frames), "
    673589                 "setting pre-buffering size to %RU32 frames\n",
    674                  CfgHostAcq.Backend.cfPreBuf, pHstStream->szName, CfgHostAcq.Backend.cfBufferSize, CfgHostAcq.Backend.cfBufferSize));
     590                 CfgHostAcq.Backend.cfPreBuf, pStream->szName, CfgHostAcq.Backend.cfBufferSize, CfgHostAcq.Backend.cfBufferSize));
    675591        CfgHostAcq.Backend.cfPreBuf = CfgHostAcq.Backend.cfBufferSize;
    676592    }
     
    679595    {
    680596        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, pHstStream->szName, CfgHostAcq.Backend.cfBufferSize, CfgHostAcq.Backend.cfBufferSize));
     597                 CfgHostAcq.Backend.cfPeriod, pStream->szName, CfgHostAcq.Backend.cfBufferSize, CfgHostAcq.Backend.cfBufferSize));
    682598        CfgHostAcq.Backend.cfPeriod = CfgHostAcq.Backend.cfBufferSize;
    683599    }
     
    686602
    687603    LogRel2(("Audio: Buffer size of stream '%s' is %RU32ms (%RU32 frames)\n",
    688              pHstStream->szName, msBufferSize, CfgHostAcq.Backend.cfBufferSize));
     604             pStream->szName, msBufferSize, CfgHostAcq.Backend.cfBufferSize));
    689605
    690606    /* If no own pre-buffer is set, let the backend choose. */
    691607    uint32_t msPreBuf = DrvAudioHlpFramesToMilli(CfgHostAcq.Backend.cfPreBuf, &pCfgHost->Props);
    692608    LogRel2(("Audio: Pre-buffering size of stream '%s' is %RU32ms (%RU32 frames)\n",
    693              pHstStream->szName, msPreBuf, CfgHostAcq.Backend.cfPreBuf));
     609             pStream->szName, msPreBuf, CfgHostAcq.Backend.cfPreBuf));
    694610
    695611    /* Make sure the configured buffer size by the backend at least can hold the configured latency. */
     
    697613
    698614    LogRel2(("Audio: Period size of stream '%s' is %RU32ms (%RU32 frames)\n",
    699              pHstStream->szName, msPeriod, CfgHostAcq.Backend.cfPeriod));
     615             pStream->szName, msPeriod, CfgHostAcq.Backend.cfPeriod));
    700616
    701617    /* Set set host buffer size multiplicator. */
     
    703619
    704620    /* Destroy any former mixing buffer. */
    705     AudioMixBufDestroy(&pHstStream->MixBuf);
     621    AudioMixBufDestroy(&pStream->Host.MixBuf);
    706622
    707623    /* Make sure to (re-)set the host buffer's shift size. */
    708624    CfgHostAcq.Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(CfgHostAcq.Props.cBits, CfgHostAcq.Props.cChannels);
    709625
    710     int rc2 = AudioMixBufInit(&pHstStream->MixBuf, pHstStream->szName, &CfgHostAcq.Props,
    711                               CfgHostAcq.Backend.cfBufferSize * cHstBufferFactor);
    712     AssertRC(rc2);
     626    rc = AudioMixBufInit(&pStream->Host.MixBuf, pStream->szName, &CfgHostAcq.Props,
     627                        CfgHostAcq.Backend.cfBufferSize * cHstBufferFactor);
     628    AssertRC(rc);
    713629
    714630    /* Make a copy of the acquired host stream configuration. */
    715     rc2 = DrvAudioHlpStreamCfgCopy(&pHstStream->Cfg, &CfgHostAcq);
    716     AssertRC(rc2);
     631    rc = DrvAudioHlpStreamCfgCopy(&pStream->Host.Cfg, &CfgHostAcq);
     632    AssertRC(rc);
    717633
    718634    /*
     
    721637
    722638    if (pCfgGuest->Device.uSchedulingHintMs)
    723         LogRel2(("Audio: Stream '%s' got a scheduling hint of %RU32ms\n", pGstStream->szName, pCfgGuest->Device.uSchedulingHintMs));
     639        LogRel2(("Audio: Stream '%s' got a scheduling hint of %RU32ms\n", pStream->szName, pCfgGuest->Device.uSchedulingHintMs));
    724640
    725641    /* Destroy any former mixing buffer. */
    726     AudioMixBufDestroy(&pGstStream->MixBuf);
     642    AudioMixBufDestroy(&pStream->Guest.MixBuf);
    727643
    728644    /* Set the guests's default audio data layout. */
     
    735651    const unsigned cGstBufferFactor = 4; /** @todo Make this configurable. */
    736652
    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);
    753656
    754657    /* Make a copy of the guest stream configuration. */
    755     rc2 = DrvAudioHlpStreamCfgCopy(&pGstStream->Cfg, pCfgGuest);
    756     AssertRC(rc2);
     658    rc = DrvAudioHlpStreamCfgCopy(&pStream->Guest.Cfg, pCfgGuest);
     659    AssertRC(rc);
    757660
    758661    if (RT_FAILURE(rc))
    759662        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
    760711
    761712    LogFlowFunc(("[%s] Returning %Rrc\n", pStream->szName, rc));
     
    800751
    801752    /* Mark all host streams to re-initialize. */
    802     PPDMAUDIOSTREAM pHstStream;
    803     RTListForEach(&pThis->lstHstStreams, pHstStream, PDMAUDIOSTREAM, Node)
    804         pHstStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_PENDING_REINIT;
     753    PPDMAUDIOSTREAM pStream;
     754    RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node)
     755        pStream->fStatus |= PDMAUDIOSTREAMSTS_FLAG_PENDING_REINIT;
    805756
    806757# ifdef VBOX_WITH_AUDIO_ENUM
     
    829780    LogFlowFunc(("[%s]\n", pStream->szName));
    830781
    831     PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
    832     AssertPtr(pHstStream);
    833 
    834782    /*
    835783     * Gather current stream status.
    836784     */
    837     bool fIsEnabled = RT_BOOL(pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED); /* Stream is enabled? */
     785    bool fIsEnabled = RT_BOOL(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED); /* Stream is enabled? */
    838786
    839787    /*
    840788     * Destroy and re-create stream on backend side.
    841789     */
    842     int rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     790    int rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
    843791    if (RT_SUCCESS(rc))
    844792    {
    845         rc = drvAudioStreamDestroyInternalBackend(pThis, pHstStream);
     793        rc = drvAudioStreamDestroyInternalBackend(pThis, pStream);
    846794        if (RT_SUCCESS(rc))
    847795        {
    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);
    852803
    853804    /*
    854805     * Restore previous stream state.
    855806     */
    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);
    914809
    915810    if (RT_FAILURE(rc))
     
    918813    LogFunc(("[%s] Returning %Rrc\n", pStream->szName, rc));
    919814    return rc;
     815}
     816
     817static 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
    920843}
    921844
     
    949872
    950873#ifdef LOG_ENABLED
    951     char *pszGstSts = NULL;
    952     char *pszHstSts = NULL;
     874    char *pszStreamSts = NULL;
    953875#endif
    954876
     
    969891        }
    970892
    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));
    977895
    978896#ifdef LOG_ENABLED
    979         pszHstSts = dbgAudioStreamStatusToStr(pHstStream->fStatus);
    980         AssertPtr(pszHstSts);
     897        pszStreamSts = dbgAudioStreamStatusToStr(pStream->fStatus);
     898        AssertPtr(pszStreamSts);
    981899#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));
    997904#ifdef DEBUG_andy
    998905            AssertFailed();
     
    1002909        }
    1003910
    1004         const uint32_t cbFree = AudioMixBufFreeBytes(&pHstStream->MixBuf);
     911        const uint32_t cbFree = AudioMixBufFreeBytes(&pStream->Host.MixBuf);
    1005912        if (cbFree < cbBuf)
    1006913            LogRel2(("Audio: Lost audio output (%RU64ms, %RU32 free but needs %RU32) due to full host stream buffer '%s'\n",
    1007                      DrvAudioHlpBytesToMilli(cbBuf - cbFree, &pHstStream->Cfg.Props), cbFree, cbBuf, pHstStream->szName));
     914                     DrvAudioHlpBytesToMilli(cbBuf - cbFree, &pStream->Host.Cfg.Props), cbFree, cbBuf, pStream->szName));
    1008915
    1009916        uint32_t cbToWrite = RT_MIN(cbBuf, cbFree);
     
    1017924         * (first) processing (if needed), so always write the incoming data at offset 0. */
    1018925        uint32_t cfGstWritten = 0;
    1019         rc = AudioMixBufWriteAt(&pGstStream->MixBuf, 0 /* offFrames */, pvBuf, cbToWrite, &cfGstWritten);
     926        rc = AudioMixBufWriteAt(&pStream->Guest.MixBuf, 0 /* offFrames */, pvBuf, cbToWrite, &cfGstWritten);
    1020927        if (   RT_FAILURE(rc)
    1021928            || !cfGstWritten)
    1022929        {
    1023930            AssertMsgFailed(("[%s] Write failed: cbToWrite=%RU32, cfWritten=%RU32, rc=%Rrc\n",
    1024                              pGstStream->szName, cbToWrite, cfGstWritten, rc));
     931                             pStream->szName, cbToWrite, cfGstWritten, rc));
    1025932            break;
    1026933        }
    1027934
    1028935        if (pThis->Out.Cfg.Dbg.fEnabled)
    1029             DrvAudioHlpFileWrite(pHstStream->Out.Dbg.pFileStreamWrite, pvBuf, cbToWrite, 0 /* fFlags */);
     936            DrvAudioHlpFileWrite(pStream->Out.Dbg.pFileStreamWrite, pvBuf, cbToWrite, 0 /* fFlags */);
    1030937
    1031938#ifdef VBOX_WITH_STATISTICS
     
    1035942        if (cfGstWritten)
    1036943        {
    1037             int rc2 = AudioMixBufMixToParentEx(&pGstStream->MixBuf, 0 /* cSrcOffset */, cfGstWritten /* cSrcFrames */,
     944            int rc2 = AudioMixBufMixToParentEx(&pStream->Guest.MixBuf, 0 /* cSrcOffset */, cfGstWritten /* cSrcFrames */,
    1038945                                               &cfGstMixed /* pcSrcMixed */);
    1039946            if (RT_FAILURE(rc2))
    1040947            {
    1041948                AssertMsgFailed(("[%s] Mixing failed: cbToWrite=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n",
    1042                                  pGstStream->szName, cbToWrite, cfGstWritten, cfGstMixed, rc2));
     949                                 pStream->szName, cbToWrite, cfGstWritten, cfGstMixed, rc2));
    1043950            }
    1044951            else
    1045952            {
    1046953                Log3Func(("[%s] Buffer: Writing %RU32 frames (%RU64ms), now filled with %RU64ms -- %RU8%%\n",
    1047                           pHstStream->szName, cfGstWritten, DrvAudioHlpFramesToMilli(cfGstWritten, &pHstStream->Cfg.Props),
    1048                           DrvAudioHlpFramesToMilli(AudioMixBufUsed(&pHstStream->MixBuf), &pHstStream->Cfg.Props),
    1049                           AudioMixBufUsed(&pHstStream->MixBuf) * 100 / AudioMixBufSize(&pHstStream->MixBuf)));
    1050 
    1051                 pHstStream->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();
    1052959
    1053960                /* Keep going. */
     
    1057964                rc = rc2;
    1058965
    1059             cbWrittenTotal = AUDIOMIXBUF_F2B(&pGstStream->MixBuf, cfGstWritten);
     966            cbWrittenTotal = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfGstWritten);
    1060967#ifdef DEBUG
    1061             if (pHstStream->fThresholdReached)
    1062                 pHstStream->Out.Dbg.cbJitterWrittenPlayed += cbWrittenTotal;
     968            if (pStream->fThresholdReached)
     969                pStream->Out.Dbg.cbJitterWrittenPlayed += cbWrittenTotal;
    1063970#endif
    1064971
    1065972#ifdef VBOX_WITH_STATISTICS
    1066             STAM_COUNTER_ADD(&pThis->Stats.TotalFramesMixedOut,      cfGstMixed);
     973            STAM_COUNTER_ADD(&pThis->Stats.TotalFramesMixedOut,     cfGstMixed);
    1067974            Assert(cfGstWritten >= cfGstMixed);
    1068             STAM_COUNTER_ADD(&pThis->Stats.TotalFramesLostOut,       cfGstWritten - cfGstMixed);
    1069             STAM_COUNTER_ADD(&pThis->Stats.TotalBytesWritten,        cbWrittenTotal);
    1070             STAM_COUNTER_ADD(&pGstStream->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);
    1071978#endif
    1072979        }
    1073980
    1074         Log3Func(("[%s] cbToWrite=%RU32, cfUsed=%RU32, cfLive=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n",
    1075                   pGstStream->szName, cbToWrite, AudioMixBufUsed(&pGstStream->MixBuf),
    1076                   AudioMixBufLive(&pGstStream->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));
    1077984
    1078985    } while (0);
    1079986
    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));
    1081989
    1082990#ifdef LOG_ENABLED
    1083     RTStrFree(pszHstSts);
    1084     RTStrFree(pszGstSts);
     991    RTStrFree(pszStreamSts);
    1085992#endif
    1086993
     
    11721079        return VINF_SUCCESS;
    11731080
    1174     PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
    1175     AssertPtr(pHstStream);
    1176     PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : NULL;
    1177     AssertPtr(pGstStream);
    1178 
    11791081    int rc;
    11801082
    11811083    /* Is the stream scheduled for re-initialization? Do so now. */
    1182     if (pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_REINIT)
     1084    if (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_REINIT)
    11831085    {
    11841086#ifdef VBOX_WITH_AUDIO_ENUM
     
    11941096        /* Remove the pending re-init flag in any case, regardless whether the actual re-initialization succeeded
    11951097         * or not. If it failed, the backend needs to notify us again to try again at some later point in time. */
    1196         pHstStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_PENDING_REINIT;
     1098        pStream->fStatus &= ~PDMAUDIOSTREAMSTS_FLAG_PENDING_REINIT;
    11971099
    11981100        rc = drvAudioStreamReInitInternal(pThis, pStream);
     
    12021104
    12031105#ifdef LOG_ENABLED
    1204     char *pszHstSts = dbgAudioStreamStatusToStr(pHstStream->fStatus);
    1205     Log3Func(("[%s] fStatus=%s\n", pHstStream->szName, pszHstSts));
    1206     RTStrFree(pszHstSts);
     1106    char *pszStreamSts = dbgAudioStreamStatusToStr(pStream->fStatus);
     1107    Log3Func(("[%s] fStatus=%s\n", pStream->szName, pszStreamSts));
     1108    RTStrFree(pszStreamSts);
    12071109#endif /* LOG_ENABLED */
    12081110
    12091111    /* Not enabled or paused? Skip iteration. */
    1210     if (   !(pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED)
    1211         ||  (pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED))
     1112    if (   !(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_ENABLED)
     1113        ||  (pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PAUSED))
    12121114    {
    12131115        return VINF_SUCCESS;
     
    12211123        uint32_t cfMixed = 0;
    12221124
    1223         rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, pHstStream->pvBackend);
     1125        rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, pStream->pvBackend);
    12241126        if (RT_FAILURE(rc))
    12251127            break;
    12261128
    1227         if (pHstStream->enmDir == PDMAUDIODIR_IN)
     1129        if (pStream->enmDir == PDMAUDIODIR_IN)
    12281130        {
    12291131            /* Has the host captured any frames which were not mixed to the guest side yet? */
    1230             uint32_t cfCaptured = AudioMixBufUsed(&pHstStream->MixBuf);
     1132            uint32_t cfCaptured = AudioMixBufUsed(&pStream->Host.MixBuf);
    12311133            if (cfCaptured)
    12321134            {
    12331135                /* When capturing frames, the guest is the parent while the host is the child.
    12341136                 * So try mixing not yet mixed host-side frames to the guest-side buffer. */
    1235                 rc = AudioMixBufMixToParent(&pHstStream->MixBuf, cfCaptured, &cfMixed);
     1137                rc = AudioMixBufMixToParent(&pStream->Host.MixBuf, cfCaptured, &cfMixed);
    12361138                if (RT_FAILURE(rc))
    12371139                {
    12381140                    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));
    12401142                    else
    1241                         LogRel2(("Audio: Mixing to guest input stream '%s' failed: %Rrc\n", pGstStream->szName, rc));
     1143                        LogRel2(("Audio: Mixing to guest input stream '%s' failed: %Rrc\n", pStream->szName, rc));
    12421144#ifdef DEBUG_andy_disabled
    12431145                    AssertFailed();
     
    12501152                STAM_COUNTER_ADD(&pThis->Stats.TotalFramesLostIn,  cfCaptured - cfMixed);
    12511153#endif
    1252                 Log3Func(("[%s] %RU32/%RU32 input frames mixed, rc=%Rrc\n", pHstStream->szName, cfMixed, cfCaptured, rc));
     1154                Log3Func(("[%s] %RU32/%RU32 input frames mixed, rc=%Rrc\n", pStream->szName, cfMixed, cfCaptured, rc));
    12531155            }
    12541156            else
     
    12591161            }
    12601162        }
    1261         else if (pHstStream->enmDir == PDMAUDIODIR_OUT)
     1163        else if (pStream->enmDir == PDMAUDIODIR_OUT)
    12621164        {
    12631165            /* No audio frames to transfer from guest to host (anymore)?
    12641166             * Then try closing this stream if marked so in the next block. */
    1265             const uint32_t cfLive = AudioMixBufLive(&pHstStream->MixBuf);
     1167            const uint32_t cfLive = AudioMixBufLive(&pStream->Host.MixBuf);
    12661168            fTryClosePending = cfLive == 0;
    1267             Log3Func(("[%s] fTryClosePending=%RTbool, cfLive=%RU32\n", pHstStream->szName, fTryClosePending, cfLive));
     1169            Log3Func(("[%s] fTryClosePending=%RTbool, cfLive=%RU32\n", pStream->szName, fTryClosePending, cfLive));
    12681170        }
    12691171        else
     
    12721174        /* Has the host stream marked as pending to disable?
    12731175         * Try disabling the stream then. */
    1274         if (   pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE
     1176        if (   pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE
    12751177            && fTryClosePending)
    12761178        {
    12771179            /* Tell the backend to drain the stream, that is, play the remaining (buffered) data
    12781180             * on the backend side. */
    1279             rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DRAIN);
     1181            rc = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DRAIN);
    12801182            if (rc == VERR_NOT_SUPPORTED) /* Not all backends support draining. */
    12811183                rc = VINF_SUCCESS;
     
    12851187                if (pThis->pHostDrvAudio->pfnStreamGetPending) /* Optional to implement. */
    12861188                {
    1287                     const uint32_t cxPending = pThis->pHostDrvAudio->pfnStreamGetPending(pThis->pHostDrvAudio, pHstStream->pvBackend);
    1288                     Log3Func(("[%s] cxPending=%RU32\n", pHstStream->szName, cxPending));
     1189                    const uint32_t cxPending = pThis->pHostDrvAudio->pfnStreamGetPending(pThis->pHostDrvAudio, pStream->pvBackend);
     1190                    Log3Func(("[%s] cxPending=%RU32\n", pStream->szName, cxPending));
    12891191
    12901192                    /* Only try close pending if no audio data is pending on the backend-side anymore. */
     
    12941196                if (fTryClosePending)
    12951197                {
    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));
    13001206                }
    13011207            }
     
    13051211
    13061212    /* Update timestamps. */
    1307     pGstStream->tsLastIteratedNs = RTTimeNanoTS();
     1213    pStream->tsLastIteratedNs = RTTimeNanoTS();
    13081214
    13091215    if (RT_FAILURE(rc))
    1310         LogFunc(("[%s] Failed with %Rrc\n",  pHstStream->szName, rc));
     1216        LogFunc(("[%s] Failed with %Rrc\n",  pStream->szName, rc));
    13111217
    13121218    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;
    13471219}
    13481220
     
    13521224 * @return  IPRT status code.
    13531225 * @param   pThis               Pointer to driver instance.
    1354  * @param   pHstStream          Host stream to play.
     1226 * @param   pStream             Stream to play.
    13551227 * @param   cfToPlay            Number of audio frames to play.
    13561228 * @param   pcfPlayed           Returns number of audio frames played. Optional.
    13571229 */
    13581230static int drvAudioStreamPlayNonInterleaved(PDRVAUDIO pThis,
    1359                                             PPDMAUDIOSTREAM pHstStream, uint32_t cfToPlay, uint32_t *pcfPlayed)
    1360 {
    1361     AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
    1362     AssertPtrReturn(pHstStream, 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);
    13631235    /* 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);
    13691236
    13701237    if (!cfToPlay)
     
    13751242    }
    13761243
     1244    /* Sanity. */
     1245    Assert(pStream->enmDir == PDMAUDIODIR_OUT);
     1246    Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED);
     1247
    13771248    int rc = VINF_SUCCESS;
    13781249
     
    13801251
    13811252    AssertPtr(pThis->pHostDrvAudio->pfnStreamGetWritable);
    1382     uint32_t cfWritable = AUDIOMIXBUF_B2F(&pHstStream->MixBuf,
    1383                                           pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pHstStream->pvBackend));
    1384 
    1385     Log3Func(("[%s] cfToPlay=%RU32 (%RU64ms), cfWritable=%RU32 (%RU64ms)\n", pHstStream->szName,
    1386               cfToPlay, DrvAudioHlpFramesToMilli(cfToPlay, &pHstStream->Cfg.Props),
    1387               cfWritable, DrvAudioHlpFramesToMilli(cfWritable, &pHstStream->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)));
    13881259
    13891260    if (cfWritable)
     
    14021273            {
    14031274                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);
    14051278                if (RT_FAILURE(rc))
    14061279                    break;
    14071280
    1408                 uint32_t cbRead = AUDIOMIXBUF_F2B(&pHstStream->MixBuf, cfRead);
     1281                uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cfRead);
    14091282                Assert(cbRead <= cbChunk);
    14101283
    14111284                uint32_t cfPlayed = 0;
    14121285                uint32_t cbPlayed = 0;
    1413                 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream->pvBackend,
     1286                rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend,
    14141287                                                         auBuf, cbRead, &cbPlayed);
    14151288                if (   RT_SUCCESS(rc)
     
    14171290                {
    14181291                    if (pThis->Out.Cfg.Dbg.fEnabled)
    1419                         DrvAudioHlpFileWrite(pHstStream->Out.Dbg.pFilePlayNonInterleaved, auBuf, cbPlayed, 0 /* fFlags */);
     1292                        DrvAudioHlpFileWrite(pStream->Out.Dbg.pFilePlayNonInterleaved, auBuf, cbPlayed, 0 /* fFlags */);
    14201293
    14211294                    if (cbRead != cbPlayed)
    14221295                        LogRel2(("Audio: Host stream '%s' played wrong amount (%RU32 bytes read but played %RU32)\n",
    1423                                  pHstStream->szName, cbRead, cbPlayed));
    1424 
    1425                     cfPlayed       = AUDIOMIXBUF_B2F(&pHstStream->MixBuf, cbPlayed);
     1296                                 pStream->szName, cbRead, cbPlayed));
     1297
     1298                    cfPlayed       = AUDIOMIXBUF_B2F(&pStream->Host.MixBuf, cbPlayed);
    14261299                    cfPlayedTotal += cfPlayed;
    14271300
     
    14301303                }
    14311304
    1432                 AudioMixBufReleaseReadBlock(&pHstStream->MixBuf, cfPlayed);
     1305                AudioMixBufReleaseReadBlock(&pStream->Host.MixBuf, cfPlayed);
    14331306
    14341307                if (RT_FAILURE(rc))
     
    14381311    }
    14391312
    1440     Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pHstStream->szName, cfPlayedTotal, cfToPlay, rc));
     1313    Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cfPlayedTotal, cfToPlay, rc));
    14411314
    14421315    if (RT_SUCCESS(rc))
     
    14541327 * @return  IPRT status code.
    14551328 * @param   pThis               Pointer to driver instance.
    1456  * @param   pHstStream          Host stream to play.
     1329 * @param   pStream             Stream to play.
    14571330 * @param   cfToPlay            Number of audio frames to play.
    14581331 * @param   pcfPlayed           Returns number of audio frames played. Optional.
    14591332 */
    14601333static int drvAudioStreamPlayRaw(PDRVAUDIO pThis,
    1461                                  PPDMAUDIOSTREAM pHstStream, uint32_t cfToPlay, uint32_t *pcfPlayed)
     1334                                 PPDMAUDIOSTREAM pStream, uint32_t cfToPlay, uint32_t *pcfPlayed)
    14621335{
    14631336    AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
    1464     AssertPtrReturn(pHstStream, VERR_INVALID_POINTER);
     1337    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    14651338    /* pcfPlayed is optional. */
    14661339
    14671340    /* 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);
    14711343
    14721344    if (!cfToPlay)
     
    14821354
    14831355    AssertPtr(pThis->pHostDrvAudio->pfnStreamGetWritable);
    1484     uint32_t cfWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pHstStream->pvBackend);
     1356    uint32_t cfWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream->pvBackend);
    14851357    if (cfWritable)
    14861358    {
     
    14941366        {
    14951367            uint32_t cfRead = 0;
    1496             rc = AudioMixBufPeek(&pHstStream->MixBuf, cfLeft, aFrameBuf,
     1368            rc = AudioMixBufPeek(&pStream->Host.MixBuf, cfLeft, aFrameBuf,
    14971369                                 RT_MIN(cfLeft, RT_ELEMENTS(aFrameBuf)), &cfRead);
    14981370
     
    15061378                     *       rather on bytes. */
    15071379                    Assert(cfRead <= RT_ELEMENTS(aFrameBuf));
    1508                     rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream->pvBackend,
     1380                    rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream->pvBackend,
    15091381                                                             aFrameBuf, cfRead, &cfPlayed);
    15101382                    if (   RT_FAILURE(rc)
     
    15331405    }
    15341406
    1535     Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pHstStream->szName, cfPlayedTotal, cfToPlay, rc));
     1407    Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream->szName, cfPlayedTotal, cfToPlay, rc));
    15361408
    15371409    if (RT_SUCCESS(rc))
     
    15701442        return VINF_SUCCESS;
    15711443
    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;
    15871445#ifdef LOG_ENABLED
    1588     char *pszStreamSts = dbgAudioStreamStatusToStr(stsHstStream);
    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));
    15901448    RTStrFree(pszStreamSts);
    15911449#endif /* LOG_ENABLED */
     
    15961454         * Check if the backend is ready to operate.
    15971455         */
    1598         if (!(stsHstStream & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) /* Stream disabled? Bail out. */
     1456        if (!(stsStream & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) /* Stream disabled? Bail out. */
    15991457            break;
    16001458
    1601               uint32_t cfLive       = AudioMixBufLive(&pHstStream->MixBuf);
    1602         const uint8_t  uLivePercent = (100 * cfLive) / AudioMixBufSize(&pHstStream->MixBuf);
    1603 
    1604         const uint64_t tsDeltaPlayedCapturedNs = RTTimeNanoTS() - pHstStream->tsLastPlayedCapturedNs;
    1605 
    1606         pHstStream->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();
    16071465
    16081466        Log3Func(("[%s] Buffer: Last played %RU64ns (%RU64ms), filled with %RU64ms (%RU8%%) total, "
    16091467                  "(cfLive=%RU32, fThresholdReached=%RTbool)\n",
    1610                   pHstStream->szName, tsDeltaPlayedCapturedNs, tsDeltaPlayedCapturedNs / RT_NS_1MS_64,
    1611                   DrvAudioHlpFramesToMilli(cfLive, &pHstStream->Cfg.Props),
    1612                   uLivePercent, cfLive, pHstStream->fThresholdReached));
    1613 
    1614         bool fDoPlay      = pHstStream->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;
    16151473        bool fJustStarted = false;
    16161474        if (!fDoPlay)
    16171475        {
    16181476            /* Did we reach the backend's playback (pre-buffering) threshold? Can be 0 if no threshold set. */
    1619             if (cfLive >= pHstStream->Cfg.Backend.cfPreBuf)
     1477            if (cfLive >= pStream->Host.Cfg.Backend.cfPreBuf)
    16201478            {
    1621                 LogRel2(("Audio: Stream '%s' buffering complete\n", pHstStream->szName));
     1479                LogRel2(("Audio: Stream '%s' buffering complete\n", pStream->szName));
    16221480                fDoPlay = true;
    16231481            }
     
    16281486             * To reproduce, use "Windows Navigation Start.wav" on Windows 7 (2824 samples). */
    16291487            else if (   cfLive
    1630                      && pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE)
     1488                     && pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE)
    16311489            {
    1632                 LogRel2(("Audio: Stream '%s' buffering complete (short sound)\n", pHstStream->szName));
     1490                LogRel2(("Audio: Stream '%s' buffering complete (short sound)\n", pStream->szName));
    16331491                fDoPlay = true;
    16341492            }
     
    16361494            if (fDoPlay)
    16371495            {
    1638                 pHstStream->fThresholdReached = true;
     1496                pStream->fThresholdReached = true;
    16391497                fJustStarted = true;
    1640                 LogRel2(("Audio: Stream '%s' started playing\n", pHstStream->szName));
     1498                LogRel2(("Audio: Stream '%s' started playing\n", pStream->szName));
    16411499            }
    16421500            else /* Not yet, so still buffering audio data. */
    16431501                LogRel2(("Audio: Stream '%s' is buffering (%RU8%% complete)\n",
    1644                          pHstStream->szName, (100 * cfLive) / pHstStream->Cfg.Backend.cfPreBuf));
     1502                         pStream->szName, (100 * cfLive) / pStream->Host.Cfg.Backend.cfPreBuf));
    16451503        }
    16461504
     
    16491507            uint32_t cfToPlay = 0;
    16501508            if (fJustStarted)
    1651                 cfToPlay = pHstStream->Cfg.Backend.cfPeriod; /* cfPeriod can be 0. */
     1509                cfToPlay = pStream->Host.Cfg.Backend.cfPeriod; /* cfPeriod can be 0. */
    16521510
    16531511            if (!cfToPlay)
    16541512            {
    1655                 cfToPlay = DrvAudioHlpNanoToFrames(tsDeltaPlayedCapturedNs, &pHstStream->Cfg.Props);
    1656                 if (pHstStream->Cfg.Device.uSchedulingHintMs)
    1657                     cfToPlay = RT_MIN(cfToPlay, DrvAudioHlpMilliToFrames(pHstStream->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));
    16581516            }
    16591517
    16601518            Log3Func(("[%s] Buffer: fJustStarted=%RTbool, cfLive=%RU32, cfToPlay=%RU32\n",
    1661                       pHstStream->szName, fJustStarted, cfLive, cfToPlay));
     1519                      pStream->szName, fJustStarted, cfLive, cfToPlay));
    16621520
    16631521            /* Did we reach a buffer underrun? Do pre-buffering again.
    16641522             * If we're in pending disabled mode, try to play (drain) the remaining audio data. */
    1665             if (   !(pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE)
     1523            if (   !(pStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_PENDING_DISABLE)
    16661524                && !fJustStarted)
    16671525            {
    16681526                if (cfLive < cfToPlay)
    16691527                {
    1670                     pHstStream->fThresholdReached = false;
    1671                     Log3Func(("[%s] Buffer: Underrun (cfLive=%RU32, cfToPlay=%RU32)\n", pHstStream->szName, cfLive, cfToPlay));
     1528                    pStream->fThresholdReached = false;
     1529                    Log3Func(("[%s] Buffer: Underrun (cfLive=%RU32, cfToPlay=%RU32)\n", pStream->szName, cfLive, cfToPlay));
    16721530                    LogRel2(("Audio: Stream '%s' buffer underrun (total %RU8%%, which is %RU8%% of a period), buffering ...\n",
    1673                              pHstStream->szName, uLivePercent, (100 * cfLive) / pHstStream->Cfg.Backend.cfPeriod));
     1531                             pStream->szName, uLivePercent, (100 * cfLive) / pStream->Host.Cfg.Backend.cfPeriod));
    16741532                    break;
    16751533                }
     
    16831541#ifdef DEBUG
    16841542            if (!fJustStarted)
    1685                 pHstStream->Out.Dbg.cbJitterWrittenPlayed -= AUDIOMIXBUF_F2B(&pHstStream->MixBuf, cfToPlay);
     1543                pStream->Out.Dbg.cbJitterWrittenPlayed -= AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, cfToPlay);
    16861544            Log3Func(("[%s] Buffer: Playing %RU32 frames (%RU64ms), now filled with %RU64ms -- %RU8%% (cbJitterWrittenPlayed=%RI64)\n",
    1687                       pHstStream->szName, cfToPlay, DrvAudioHlpFramesToMilli(cfToPlay, &pHstStream->Cfg.Props),
    1688                       DrvAudioHlpFramesToMilli(AudioMixBufUsed(&pHstStream->MixBuf), &pHstStream->Cfg.Props),
    1689                       AudioMixBufUsed(&pHstStream->MixBuf) * 100 / AudioMixBufSize(&pHstStream->MixBuf),
    1690                       pHstStream->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));
    16911549#endif
    16921550            if (pThis->pHostDrvAudio->pfnStreamPlayBegin)
    1693                 pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, pHstStream->pvBackend);
    1694 
    1695             if (RT_LIKELY(pHstStream->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))
    16961554            {
    1697                 rc = drvAudioStreamPlayNonInterleaved(pThis, pHstStream, cfToPlay, &cfPlayedTotal);
     1555                rc = drvAudioStreamPlayNonInterleaved(pThis, pStream, cfToPlay, &cfPlayedTotal);
    16981556            }
    1699             else if (pHstStream->Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW)
     1557            else if (pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW)
    17001558            {
    1701                 rc = drvAudioStreamPlayRaw(pThis, pHstStream, cfToPlay, &cfPlayedTotal);
     1559                rc = drvAudioStreamPlayRaw(pThis, pStream, cfToPlay, &cfPlayedTotal);
    17021560            }
    17031561            else
     
    17051563
    17061564            if (pThis->pHostDrvAudio->pfnStreamPlayEnd)
    1707                 pThis->pHostDrvAudio->pfnStreamPlayEnd(pThis->pHostDrvAudio, pHstStream->pvBackend);
     1565                pThis->pHostDrvAudio->pfnStreamPlayEnd(pThis->pHostDrvAudio, pStream->pvBackend);
    17081566        }
    17091567
    17101568        if (RT_SUCCESS(rc))
    17111569        {
    1712             AudioMixBufFinish(&pHstStream->MixBuf, cfPlayedTotal);
     1570            AudioMixBufFinish(&pStream->Host.MixBuf, cfPlayedTotal);
    17131571
    17141572#ifdef VBOX_WITH_STATISTICS
    17151573            STAM_COUNTER_ADD     (&pThis->Stats.TotalFramesOut, cfPlayedTotal);
    17161574            STAM_PROFILE_ADV_STOP(&pThis->Stats.DelayOut, out);
    1717             STAM_COUNTER_ADD     (&pHstStream->Out.Stats.FramesPlayed, cfPlayedTotal);
     1575            STAM_COUNTER_ADD     (&pStream->Out.Stats.FramesPlayed, cfPlayedTotal);
    17181576#endif
    17191577        }
     
    17221580
    17231581#ifdef LOG_ENABLED
    1724     uint32_t cfLive = AudioMixBufLive(&pHstStream->MixBuf);
    1725     pszStreamSts  = dbgAudioStreamStatusToStr(stsHstStream);
    1726     Log3Func(("[%s] Buffer: End stsHstStream=%s, cfLive=%RU32, cfPlayedTotal=%RU32, rc=%Rrc\n",
    1727               pHstStream->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));
    17281586    RTStrFree(pszStreamSts);
    17291587#endif /* LOG_ENABLED */
     
    17501608 * @returns IPRT status code.
    17511609 * @param   pThis               Driver instance.
    1752  * @param   pHstStream          Host stream to capture from.
     1610 * @param   pStream             Stream to capture from.
    17531611 * @param   pcfCaptured         Number of (host) audio frames captured. Optional.
    17541612 */
    1755 static int drvAudioStreamCaptureNonInterleaved(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream, uint32_t *pcfCaptured)
    1756 {
    1757     AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
    1758     AssertPtrReturn(pHstStream, VERR_INVALID_POINTER);
     1613static int drvAudioStreamCaptureNonInterleaved(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcfCaptured)
     1614{
     1615    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     1616    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    17591617    /* pcfCaptured is optional. */
    17601618
    17611619    /* 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);
    17651622
    17661623    int rc = VINF_SUCCESS;
     
    17751632    for (;;)
    17761633    {
    1777         uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pHstStream->pvBackend);
     1634        uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream->pvBackend);
    17781635        if (!cbReadable)
    17791636        {
    1780             Log2Func(("[%s] No readable data available, skipping\n", pHstStream->szName));
     1637            Log2Func(("[%s] No readable data available, skipping\n", pStream->szName));
    17811638            break;
    17821639        }
    17831640
    1784         uint32_t cbFree = AUDIOMIXBUF_F2B(&pHstStream->MixBuf, AudioMixBufFree(&pHstStream->MixBuf));
     1641        uint32_t cbFree = AUDIOMIXBUF_F2B(&pStream->Host.MixBuf, AudioMixBufFree(&pStream->Host.MixBuf));
    17851642        if (!cbFree)
    17861643        {
    1787             Log2Func(("[%s] Host buffer full, skipping\n", pHstStream->szName));
     1644            Log2Func(("[%s] Host buffer full, skipping\n", pStream->szName));
    17881645            break;
    17891646        }
     
    17981655
    17991656        uint32_t cbCaptured;
    1800         rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pHstStream->pvBackend,
     1657        rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStream->pvBackend,
    18011658                                                    auBuf, cbFree, &cbCaptured);
    18021659        if (RT_FAILURE(rc))
    18031660        {
    1804             int rc2 = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     1661            int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
    18051662            AssertRC(rc2);
    18061663        }
     
    18081665        {
    18091666            if (pThis->In.Cfg.Dbg.fEnabled)
    1810                 DrvAudioHlpFileWrite(pHstStream->In.Dbg.pFileCaptureNonInterleaved, auBuf, cbCaptured, 0 /* fFlags */);
     1667                DrvAudioHlpFileWrite(pStream->In.Dbg.pFileCaptureNonInterleaved, auBuf, cbCaptured, 0 /* fFlags */);
    18111668
    18121669            Assert(cbCaptured <= cbBuf);
     
    18151672
    18161673            uint32_t cfCaptured = 0;
    1817             rc = AudioMixBufWriteCirc(&pHstStream->MixBuf, auBuf, cbCaptured, &cfCaptured);
     1674            rc = AudioMixBufWriteCirc(&pStream->Host.MixBuf, auBuf, cbCaptured, &cfCaptured);
    18181675            if (RT_SUCCESS(rc))
    18191676                cfCapturedTotal += cfCaptured;
     
    18291686    {
    18301687        if (cfCapturedTotal)
    1831             Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pHstStream->szName, cfCapturedTotal, rc));
     1688            Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCapturedTotal, rc));
    18321689    }
    18331690    else
    1834         LogFunc(("[%s] Capturing failed with rc=%Rrc\n", pHstStream->szName, rc));
     1691        LogFunc(("[%s] Capturing failed with rc=%Rrc\n", pStream->szName, rc));
    18351692
    18361693    if (pcfCaptured)
     
    18491706 * @returns IPRT status code.
    18501707 * @param   pThis               Driver instance.
    1851  * @param   pHstStream          Host stream to capture from.
     1708 * @param   pStream             Stream to capture from.
    18521709 * @param   pcfCaptured         Number of (host) audio frames captured. Optional.
    18531710 */
    1854 static int drvAudioStreamCaptureRaw(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream, uint32_t *pcfCaptured)
    1855 {
    1856     AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
    1857     AssertPtrReturn(pHstStream, VERR_INVALID_POINTER);
     1711static int drvAudioStreamCaptureRaw(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcfCaptured)
     1712{
     1713    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     1714    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    18581715    /* pcfCaptured is optional. */
    18591716
    18601717    /* 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);
    18641720
    18651721    int rc = VINF_SUCCESS;
     
    18711727    for (;;)
    18721728    {
    1873         uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pHstStream->pvBackend);
     1729        uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream->pvBackend);
    18741730        if (!cbReadable) /* Nothing to read on the backend side? Bail out. */
    18751731            break;
    18761732
    1877         const uint32_t cbFree = AudioMixBufFreeBytes(&pHstStream->MixBuf);
     1733        const uint32_t cbFree = AudioMixBufFreeBytes(&pStream->Host.MixBuf);
    18781734        if (!cbFree) /* No space left in the host stream? */
    18791735            break;
     
    18841740        PPDMAUDIOFRAME paFrames;
    18851741        uint32_t cfWritable;
    1886         rc = AudioMixBufPeekMutable(&pHstStream->MixBuf, AUDIOMIXBUF_B2F(&pHstStream->MixBuf, cbReadable),
     1742        rc = AudioMixBufPeekMutable(&pStream->Host.MixBuf, AUDIOMIXBUF_B2F(&pStream->Host.MixBuf, cbReadable),
    18871743                                    &paFrames, &cfWritable);
    18881744        if (   RT_FAILURE(rc)
     
    18931749
    18941750        uint32_t cfCaptured;
    1895         rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pHstStream->pvBackend,
     1751        rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStream->pvBackend,
    18961752                                                    paFrames, cfWritable, &cfCaptured);
    18971753        if (RT_FAILURE(rc))
    18981754        {
    1899             int rc2 = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     1755            int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
    19001756            AssertRC(rc2);
    19011757        }
     
    19151771    }
    19161772
    1917     Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pHstStream->szName, cfCapturedTotal, rc));
     1773    Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCapturedTotal, rc));
    19181774
    19191775    if (pcfCaptured)
     
    19461802            break;
    19471803
    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 
    19621804        /*
    19631805         * Check if the backend is ready to operate.
    19641806         */
    19651807
    1966         PDMAUDIOSTREAMSTS stsHstStream = pHstStream->fStatus;
     1808        PDMAUDIOSTREAMSTS stsStream = pStream->fStatus;
    19671809#ifdef LOG_ENABLED
    1968         char *pszStreamSts = dbgAudioStreamStatusToStr(stsHstStream);
    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));
    19701812        RTStrFree(pszStreamSts);
    19711813#endif /* LOG_ENABLED */
    1972         if (!(stsHstStream & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) /* Stream disabled? Bail out. */
     1814        if (!(stsStream & PDMAUDIOSTREAMSTS_FLAG_ENABLED)) /* Stream disabled? Bail out. */
    19731815            break;
    19741816
     
    19781820
    19791821        if (pThis->pHostDrvAudio->pfnStreamCaptureBegin)
    1980             pThis->pHostDrvAudio->pfnStreamCaptureBegin(pThis->pHostDrvAudio, pHstStream->pvBackend);
    1981 
    1982         if (RT_LIKELY(pHstStream->Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED))
    1983         {
    1984             rc = drvAudioStreamCaptureNonInterleaved(pThis, pHstStream, &cfCaptured);
    1985         }
    1986         else if (pHstStream->Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW)
    1987         {
    1988             rc = drvAudioStreamCaptureRaw(pThis, pHstStream, &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);
    19891831        }
    19901832        else
     
    19921834
    19931835        if (pThis->pHostDrvAudio->pfnStreamCaptureEnd)
    1994             pThis->pHostDrvAudio->pfnStreamCaptureEnd(pThis->pHostDrvAudio, pHstStream->pvBackend);
     1836            pThis->pHostDrvAudio->pfnStreamCaptureEnd(pThis->pHostDrvAudio, pStream->pvBackend);
    19951837
    19961838#ifdef LOG_ENABLED
    1997         pszStreamSts = dbgAudioStreamStatusToStr(stsHstStream);
    1998         Log3Func(("[%s] End: stsHstStream=%s, cfCaptured=%RU32, rc=%Rrc\n",
    1999                   pHstStream->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));
    20001842        RTStrFree(pszStreamSts);
    20011843#endif /* LOG_ENABLED */
     
    20031845        if (RT_SUCCESS(rc))
    20041846        {
    2005             Log3Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pHstStream->szName, cfCaptured, rc));
     1847            Log3Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCaptured, rc));
    20061848
    20071849#ifdef VBOX_WITH_STATISTICS
    20081850            STAM_COUNTER_ADD(&pThis->Stats.TotalFramesIn,        cfCaptured);
    2009             STAM_COUNTER_ADD(&pHstStream->In.Stats.FramesCaptured, cfCaptured);
     1851            STAM_COUNTER_ADD(&pStream->In.Stats.FramesCaptured, cfCaptured);
    20101852#endif
    20111853        }
    20121854        else if (RT_UNLIKELY(RT_FAILURE(rc)))
    20131855        {
    2014             LogRel(("Audio: Capturing stream '%s' failed with %Rrc\n", pHstStream->szName, rc));
     1856            LogRel(("Audio: Capturing stream '%s' failed with %Rrc\n", pStream->szName, rc));
    20151857        }
    20161858
     
    23532195    if (pThis->pHostDrvAudio)
    23542196    {
    2355         PPDMAUDIOSTREAM pHstStream;
    2356         RTListForEach(&pThis->lstHstStreams, pHstStream, PDMAUDIOSTREAM, Node)
    2357             drvAudioStreamControlInternalBackend(pThis, pHstStream, enmCmd);
     2197        PPDMAUDIOSTREAM pStream;
     2198        RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node)
     2199            drvAudioStreamControlInternalBackend(pThis, pStream, enmCmd);
    23582200    }
    23592201
     
    24892331        }
    24902332
    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 
    25012333        /*
    25022334         * Read from the parent buffer (that is, the guest buffer) which
     
    25052337        uint32_t cReadTotal = 0;
    25062338
    2507         uint32_t cToRead = RT_MIN(AUDIOMIXBUF_B2F(&pGstStream->MixBuf, cbBuf), AudioMixBufUsed(&pGstStream->MixBuf));
    2508         while (cToRead)
     2339        uint32_t cfToRead = RT_MIN(AUDIOMIXBUF_B2F(&pStream->Guest.MixBuf, cbBuf), AudioMixBufUsed(&pStream->Guest.MixBuf));
     2340        while (cfToRead)
    25092341        {
    25102342            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);
    25132346            if (RT_FAILURE(rc))
    25142347                break;
    25152348
    25162349#ifdef VBOX_WITH_STATISTICS
    2517             const uint32_t cbRead = AUDIOMIXBUF_F2B(&pGstStream->MixBuf, cRead);
    2518 
    2519             STAM_COUNTER_ADD(&pThis->Stats.TotalBytesRead,       cbRead);
    2520             STAM_COUNTER_ADD(&pGstStream->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);
    25212354#endif
    2522             Assert(cToRead >= cRead);
    2523             cToRead -= cRead;
     2355            Assert(cfToRead >= cRead);
     2356            cfToRead -= cRead;
    25242357
    25252358            cReadTotal += cRead;
    25262359
    2527             AudioMixBufReleaseReadBlock(&pGstStream->MixBuf, cRead);
     2360            AudioMixBufReleaseReadBlock(&pStream->Guest.MixBuf, cRead);
    25282361        }
    25292362
     
    25312364        {
    25322365            if (pThis->In.Cfg.Dbg.fEnabled)
    2533                 DrvAudioHlpFileWrite(pHstStream->In.Dbg.pFileStreamRead,
    2534                                      pvBuf, AUDIOMIXBUF_F2B(&pGstStream->MixBuf, cReadTotal), 0 /* fFlags */);
    2535 
    2536             AudioMixBufFinish(&pGstStream->MixBuf, cReadTotal);
    2537 
    2538             cbReadTotal = AUDIOMIXBUF_F2B(&pGstStream->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);
    25392372        }
    25402373
     
    25802413#endif
    25812414
    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;
    25902416
    25912417#define RC_BREAK(x) { rc = x; break; }
     
    26262452        }
    26272453
    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);
    26472460
    26482461        /* Retrieve host driver name for easier identification. */
     
    26602473        }
    26612474
     2475        RTStrPrintf(pStream->szName, RT_ELEMENTS(pStream->szName), "[%s] %s",
     2476                    szDriver, strlen(pCfgHost->szName) ? pCfgHost->szName : "<Untitled>");
     2477        pStream->enmDir = pCfgHost->enmDir;
     2478
    26622479        /*
    2663          * Init host stream.
     2480         * Allocate and init backend-specific data.
    26642481         */
    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        }
    26812490
    26822491        /*
    26832492         * Try to init the rest.
    26842493         */
    2685         rc = drvAudioStreamInitInternal(pThis, pHstStrm, pCfgHost, pCfgGuest);
     2494
     2495        rc = drvAudioStreamInitInternal(pThis, pStream, pCfgHost, pCfgGuest);
    26862496        if (RT_FAILURE(rc))
    26872497            break;
    26882498
    2689 #ifdef VBOX_WITH_STATISTICS
    2690         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         else
    2721             AssertFailed();
    2722 #endif
    2723 
    27242499    } while (0);
    27252500
     
    27282503    if (RT_FAILURE(rc))
    27292504    {
    2730         if (pGstStrm)
    2731         {
    2732             int rc2 = drvAudioStreamUninitInternal(pThis, pGstStrm);
     2505        if (pStream)
     2506        {
     2507            int rc2 = drvAudioStreamUninitInternal(pThis, pStream);
    27332508            if (RT_SUCCESS(rc2))
    27342509            {
    2735                 RTMemFree(pGstStrm);
    2736                 pGstStrm = NULL;
     2510                drvAudioStreamFree(pStream);
     2511                pStream = NULL;
    27372512            }
    27382513        }
    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         }
    27492514    }
    27502515    else
    27512516    {
     2517        /* Append the stream to our stream list. */
     2518        RTListAppend(&pThis->lstStreams, &pStream->Node);
     2519
    27522520        /* 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;
    27582522
    27592523        if (pCfgHost->enmDir == PDMAUDIODIR_IN)
     
    27682532                {
    27692533                    rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szFile, PDMAUDIOFILE_FLAG_NONE,
    2770                                                 &pHstStrm->In.Dbg.pFileCaptureNonInterleaved);
     2534                                                &pStream->In.Dbg.pFileCaptureNonInterleaved);
    27712535                    if (RT_SUCCESS(rc2))
    2772                         rc2 = DrvAudioHlpFileOpen(pHstStrm->In.Dbg.pFileCaptureNonInterleaved, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
    2773                                                   &pHstStrm->Cfg.Props);
     2536                        rc2 = DrvAudioHlpFileOpen(pStream->In.Dbg.pFileCaptureNonInterleaved, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
     2537                                                  &pStream->Host.Cfg.Props);
    27742538                }
    27752539
     
    27812545                    {
    27822546                        rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szFile, PDMAUDIOFILE_FLAG_NONE,
    2783                                                     &pHstStrm->In.Dbg.pFileStreamRead);
     2547                                                    &pStream->In.Dbg.pFileStreamRead);
    27842548                        if (RT_SUCCESS(rc2))
    2785                             rc2 = DrvAudioHlpFileOpen(pHstStrm->In.Dbg.pFileStreamRead, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
    2786                                                       &pHstStrm->Cfg.Props);
     2549                            rc2 = DrvAudioHlpFileOpen(pStream->In.Dbg.pFileStreamRead, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
     2550                                                      &pStream->Host.Cfg.Props);
    27872551                    }
    27882552                }
     
    28032567                {
    28042568                    rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szFile, PDMAUDIOFILE_FLAG_NONE,
    2805                                                 &pHstStrm->Out.Dbg.pFilePlayNonInterleaved);
     2569                                                &pStream->Out.Dbg.pFilePlayNonInterleaved);
    28062570                    if (RT_SUCCESS(rc2))
    2807                         rc = DrvAudioHlpFileOpen(pHstStrm->Out.Dbg.pFilePlayNonInterleaved, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
    2808                                                  &pHstStrm->Cfg.Props);
     2571                        rc = DrvAudioHlpFileOpen(pStream->Out.Dbg.pFilePlayNonInterleaved, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
     2572                                                 &pStream->Host.Cfg.Props);
    28092573                }
    28102574
     
    28162580                    {
    28172581                        rc2 = DrvAudioHlpFileCreate(PDMAUDIOFILETYPE_WAV, szFile, PDMAUDIOFILE_FLAG_NONE,
    2818                                                     &pHstStrm->Out.Dbg.pFileStreamWrite);
     2582                                                    &pStream->Out.Dbg.pFileStreamWrite);
    28192583                        if (RT_SUCCESS(rc2))
    2820                             rc2 = DrvAudioHlpFileOpen(pHstStrm->Out.Dbg.pFileStreamWrite, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
    2821                                                       &pHstStrm->Cfg.Props);
     2584                            rc2 = DrvAudioHlpFileOpen(pStream->Out.Dbg.pFileStreamWrite, PDMAUDIOFILE_DEFAULT_OPEN_FLAGS,
     2585                                                      &pStream->Host.Cfg.Props);
    28222586                    }
    28232587                }
     
    28312595        STAM_COUNTER_ADD(&pThis->Stats.TotalStreamsCreated, 1);
    28322596#endif
    2833         /* Always return the guest-side part to the device emulation. */
    2834         *ppStream = pGstStrm;
     2597        *ppStream = pStream;
    28352598    }
    28362599
     
    28702633
    28712634        PPDMAUDIOSTREAM pStream;
    2872         RTListForEach(&pThis->lstHstStreams, pStream, PDMAUDIOSTREAM, Node)
     2635        RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node)
    28732636        {
    28742637            if (pStream->enmDir != enmDir) /* Skip unwanted streams. */
     
    30052768    AssertMsg(pStream->enmDir == PDMAUDIODIR_IN, ("Can't read from a non-input stream\n"));
    30062769
    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);
    30282776
    30292777    rc2 = RTCritSectLeave(&pThis->CritSect);
     
    30492797    AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT, ("Can't write to a non-output stream\n"));
    30502798
    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 
    30612799    /* As the host side sets the overall pace, return the writable bytes from that side. */
    3062     const uint64_t deltaLastReadWriteNs = RTTimeNanoTS() - pHstStream->tsLastReadWrittenNs;
     2800    const uint64_t deltaLastReadWriteNs = RTTimeNanoTS() - pStream->tsLastReadWrittenNs;
    30632801
    30642802    uint32_t cbWritable = 0;
    30652803
    3066     if (DrvAudioHlpStreamStatusCanWrite(pHstStream->fStatus))
    3067     {
    3068         cbWritable = DrvAudioHlpNanoToBytes(deltaLastReadWriteNs, &pHstStream->Cfg.Props);
    3069 
    3070         /* Make sure to align the writable size to the stream's frame size. */
    3071         cbWritable = DrvAudioHlpBytesAlign(cbWritable, &pHstStream->Cfg.Props);
    3072     }
    3073 
    3074     Log3Func(("[%s] cbWritable=%RU32 (%RU64ms)\n", pHstStream->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));
    30752813
    30762814    rc2 = RTCritSectLeave(&pThis->CritSect);
     
    30952833    AssertRC(rc2);
    30962834
    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);
    31062839
    31072840#ifdef LOG_ENABLED
    3108         char *pszStreamSts = dbgAudioStreamStatusToStr(stsStream);
    3109         Log3Func(("[%s] %s\n", pHstStream->szName, pszStreamSts));
    3110         RTStrFree(pszStreamSts);
     2841    char *pszStreamSts = dbgAudioStreamStatusToStr(stsStream);
     2842    Log3Func(("[%s] %s\n", pStream->szName, pszStreamSts));
     2843    RTStrFree(pszStreamSts);
    31112844#endif
    3112     }
    31132845
    31142846    rc2 = RTCritSectLeave(&pThis->CritSect);
     
    31292861    LogFlowFunc(("[%s] volL=%RU32, volR=%RU32, fMute=%RTbool\n", pStream->szName, pVol->uLeft, pVol->uRight, pVol->fMuted));
    31302862
    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
    31362866    return VINF_SUCCESS;
    31372867}
     
    31502880    AssertRC(rc);
    31512881
    3152     PDMAUDIODIR enmDir = pStream->enmDir;
     2882    LogRel2(("Audio: Destroying stream '%s'\n", pStream->szName));
    31532883
    31542884    LogFlowFunc(("[%s] cRefs=%RU32\n", pStream->szName, pStream->cRefs));
     
    31582888    if (RT_SUCCESS(rc))
    31592889    {
    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));
    32392893    }
    32402894
    32412895    if (RT_SUCCESS(rc))
    32422896    {
    3243         if (enmDir == PDMAUDIODIR_IN)
     2897        if (pStream->enmDir == PDMAUDIODIR_IN)
    32442898        {
    32452899            pThis->In.cStreamsFree++;
     
    32492903            pThis->Out.cStreamsFree++;
    32502904        }
     2905
     2906        RTListNodeRemove(&pStream->Node);
     2907
     2908        drvAudioStreamFree(pStream);
     2909        pStream = NULL;
    32512910    }
    32522911
     
    32642923 * @returns IPRT status code.
    32652924 * @param   pThis               Pointer to driver instance.
    3266  * @param   pHstStream          (Host) audio stream to use for creating the stream on the backend side.
     2925 * @param   pStream             Audio stream to create the backend side for.
    32672926 * @param   pCfgReq             Requested audio stream configuration to use for stream creation.
    32682927 * @param   pCfgAcq             Acquired audio stream configuration returned by the backend.
    32692928 */
    32702929static 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));
    32832939
    32842940    /* Get the right configuration for the stream to be created. */
     
    32982954    LogRel2(("Audio: Using %s period size (%RU32ms, %RU32 frames) for stream '%s'\n",
    32992955             pDrvCfg->uPeriodMs ? "custom" : "default", DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfPeriod, &pCfgReq->Props),
    3300              pCfgReq->Backend.cfPeriod, pHstStream->szName));
     2956             pCfgReq->Backend.cfPeriod, pStream->szName));
    33012957
    33022958    /*
     
    33102966    LogRel2(("Audio: Using %s buffer size (%RU32ms, %RU32 frames) for stream '%s'\n",
    33112967             pDrvCfg->uBufferSizeMs ? "custom" : "default", DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfBufferSize, &pCfgReq->Props),
    3312              pCfgReq->Backend.cfBufferSize, pHstStream->szName));
     2968             pCfgReq->Backend.cfBufferSize, pStream->szName));
    33132969
    33142970    /*
     
    33182974    {
    33192975        if (!pDrvCfg->uPreBufMs) /* Pre-buffering is set to disabled. */
    3320             LogRel2(("Audio: Using custom pre-buffering (disabled) for stream '%s'\n", pHstStream->szName));
     2976            LogRel2(("Audio: Using custom pre-buffering (disabled) for stream '%s'\n", pStream->szName));
    33212977        pCfgReq->Backend.cfPreBuf = DrvAudioHlpMilliToFrames(pDrvCfg->uPreBufMs, &pCfgReq->Props);
    33222978    }
     
    33262982    LogRel2(("Audio: Using %s pre-buffering size (%RU32ms, %RU32 frames) for stream '%s'\n",
    33272983             pDrvCfg->uPreBufMs != UINT32_MAX ? "custom" : "default", DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfPreBuf, &pCfgReq->Props),
    3328              pCfgReq->Backend.cfPreBuf, pHstStream->szName));
     2984             pCfgReq->Backend.cfPreBuf, pStream->szName));
    33292985
    33302986    /*
     
    33342990    {
    33352991        LogRel(("Audio: Error for stream '%s': Buffer size (%RU32ms) must not be smaller than the period size (%RU32ms)\n",
    3336                 pHstStream->szName, DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfBufferSize, &pCfgReq->Props),
     2992                pStream->szName, DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfBufferSize, &pCfgReq->Props),
    33372993                DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfPeriod, &pCfgReq->Props)));
    33382994        return VERR_INVALID_PARAMETER;
     
    33453001        {
    33463002            LogRel(("Audio: Error for stream '%s': Pre-buffering size (%RU32ms) must not be bigger than the buffer size (%RU32ms)\n",
    3347                     pHstStream->szName, DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfPreBuf, &pCfgReq->Props),
     3003                    pStream->szName, DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfPreBuf, &pCfgReq->Props),
    33483004                    DrvAudioHlpFramesToMilli(pCfgReq->Backend.cfBufferSize, &pCfgReq->Props)));
    33493005            return VERR_INVALID_PARAMETER;
     
    33573013    {
    33583014        LogRel(("Audio: Creating stream '%s' with an invalid backend configuration not possible, skipping\n",
    3359                 pHstStream->szName));
     3015                pStream->szName));
    33603016        return rc;
    33613017    }
    33623018
    3363     rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pHstStream->pvBackend, pCfgReq, pCfgAcq);
     3019    rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pStream->pvBackend, pCfgReq, pCfgAcq);
    33643020    if (RT_FAILURE(rc))
    33653021    {
    33663022        if (rc == VERR_NOT_SUPPORTED)
    3367             LogRel2(("Audio: Creating stream '%s' in backend not supported, skipping\n", pHstStream->szName));
     3023            LogRel2(("Audio: Creating stream '%s' in backend not supported, skipping\n", pStream->szName));
    33683024        else
    3369             LogRel(("Audio: Creating stream '%s' in backend failed with %Rrc\n", pHstStream->szName, rc));
     3025            LogRel(("Audio: Creating stream '%s' in backend failed with %Rrc\n", pStream->szName, rc));
    33703026
    33713027        return rc;
     
    33753031    if (!DrvAudioHlpStreamCfgIsValid(pCfgAcq))
    33763032    {
    3377         LogRel(("Audio: Creating stream '%s' returned an invalid backend configuration, skipping\n", pHstStream->szName));
     3033        LogRel(("Audio: Creating stream '%s' returned an invalid backend configuration, skipping\n", pStream->szName));
    33783034        return VERR_INVALID_PARAMETER;
    33793035    }
     
    33843040    {
    33853041        LogRel2(("Audio: Custom buffer size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n",
    3386                  pHstStream->szName, DrvAudioHlpFramesToMilli(pCfgAcq->Backend.cfBufferSize, &pCfgAcq->Props), pCfgAcq->Backend.cfBufferSize));
     3042                 pStream->szName, DrvAudioHlpFramesToMilli(pCfgAcq->Backend.cfBufferSize, &pCfgAcq->Props), pCfgAcq->Backend.cfBufferSize));
    33873043    }
    33883044
     
    33913047    {
    33923048        LogRel2(("Audio: Custom period size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n",
    3393                  pHstStream->szName, DrvAudioHlpFramesToMilli(pCfgAcq->Backend.cfPeriod, &pCfgAcq->Props), pCfgAcq->Backend.cfPeriod));
     3049                 pStream->szName, DrvAudioHlpFramesToMilli(pCfgAcq->Backend.cfPeriod, &pCfgAcq->Props), pCfgAcq->Backend.cfPeriod));
    33943050    }
    33953051
     
    33983054    {
    33993055        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;
    34073060
    34083061    return VINF_SUCCESS;
     
    34143067 * @returns IPRT status code.
    34153068 * @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 */
     3071static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
     3072{
     3073    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     3074    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    34253075
    34263076    int rc = VINF_SUCCESS;
    34273077
    34283078#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));
    34323081#endif
    34333082
    3434     if (pHstStream->fStatus & PDMAUDIOSTREAMSTS_FLAG_INITIALIZED)
     3083    if (pStream->pvBackend)
    34353084    {
    34363085        /* Check if the pointer to  the host audio driver is still valid.
    34373086         * It can be NULL if we were called in drvAudioDestruct, for example. */
    34383087        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    }
    34433093
    34443094#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);
    34493096#endif
    3450         }
    3451     }
    3452 
    3453     LogFlowFunc(("[%s] Returning %Rrc\n", pHstStream->szName, rc));
     3097
     3098    LogFlowFunc(("[%s] Returning %Rrc\n", pStream->szName, rc));
    34543099    return rc;
    34553100}
     
    34723117        return VERR_WRONG_ORDER;
    34733118
    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))
    34903121        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        }
    34913174    }
    34923175    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();
    35073177
    35083178    LogFlowFunc(("Returning %Rrc\n", rc));
     
    35873257     * in drvAudioDestruct(). */
    35883258    PPDMAUDIOSTREAM pStream;
    3589     RTListForEach(&pThis->lstHstStreams, pStream, PDMAUDIOSTREAM, Node)
     3259    RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node)
    35903260    {
    35913261        drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
     
    36173287    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
    36183288
    3619     RTListInit(&pThis->lstHstStreams);
    3620     RTListInit(&pThis->lstGstStreams);
     3289    RTListInit(&pThis->lstStreams);
    36213290#ifdef VBOX_WITH_AUDIO_CALLBACKS
    36223291    RTListInit(&pThis->In.lstCB);
     
    37333402
    37343403    PPDMAUDIOSTREAM pStream, pStreamNext;
    3735     RTListForEachSafe(&pThis->lstHstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, Node)
     3404    RTListForEachSafe(&pThis->lstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, Node)
    37363405    {
    37373406        rc2 = drvAudioStreamUninitInternal(pThis, pStream);
     
    37463415
    37473416    /* 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));
    37643418
    37653419#ifdef VBOX_WITH_AUDIO_CALLBACKS
  • trunk/src/VBox/Devices/Audio/DrvAudio.h

    r73429 r73467  
    123123    /** Pointer to CFGM configuration node of this driver. */
    124124    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;
    129127#ifdef VBOX_WITH_AUDIO_ENUM
    130128    /** Flag indicating to perform an (re-)enumeration of the host audio devices. */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette