VirtualBox

Changeset 61157 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
May 24, 2016 11:47:09 AM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
107442
Message:

Audio:

  • Unified GPDMAUDIOGSTSTRMIN / PDMAUDIOGSTSTRMOUT / PDMAUDIOHSTSTRMIN / PDMAUDIOHSTSTRMOUT structures to use a single PDMAUDIOSTREAM structure.
  • Cleaned up PDMIAUDIOCONNECTOR / PDMIHOSTAUDIO interfaces.
  • Made the VRDE audio support configurable with VBOX_WITH_VRDE_AUDIO (enabled by default).
  • Updates on mixing buffer handling. Work in progress.
Location:
trunk/src/VBox/Devices/Audio
Files:
15 edited

Legend:

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

    r61091 r61157  
    144144#ifdef DEBUG
    145145static uint64_t s_cSamplesMixedTotal = 0;
    146 static inline void audioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf);
    147 #endif
    148 
    149 /* Can return VINF_TRY_AGAIN for getting next pointer at beginning (circular) */
     146#endif
     147
    150148
    151149/**
     
    155153 ** @todo Protect the buffer's data?
    156154 *
    157  * @return  IPRT status code.
     155 * @return  IPRT status code. VINF_TRY_AGAIN for getting next pointer at beginning (circular).
    158156 * @param   pMixBuf                 Mixing buffer to acquire audio samples from.
    159157 * @param   cSamplesToRead          Number of audio samples to read.
     
    203201
    204202/**
    205  * Returns available number of samples for reading.
     203 * Returns available number of samples for processing.
    206204 *
    207205 * @return  uint32_t                Number of samples available for reading.
     
    428426    \
    429427    AUDMIXBUF_MACRO_FN uint32_t audioMixBufConvFrom##_aName##Stereo(PPDMAUDIOSAMPLE paDst, const void *pvSrc, uint32_t cbSrc, \
    430                                                                     const PAUDMIXBUF_CONVOPTS pOpts) \
     428                                                                    const PPDMAUDMIXBUF_CONVOPTS pOpts) \
    431429    { \
    432430        _aType *pSrc = (_aType *)pvSrc; \
     
    447445    \
    448446    AUDMIXBUF_MACRO_FN uint32_t audioMixBufConvFrom##_aName##Mono(PPDMAUDIOSAMPLE paDst, const void *pvSrc, uint32_t cbSrc, \
    449                                                                   const PAUDMIXBUF_CONVOPTS pOpts) \
     447                                                                  const PPDMAUDMIXBUF_CONVOPTS pOpts) \
    450448    { \
    451449        _aType *pSrc = (_aType *)pvSrc; \
     
    466464    \
    467465    AUDMIXBUF_MACRO_FN void audioMixBufConvTo##_aName##Stereo(void *pvDst, const PPDMAUDIOSAMPLE paSrc, \
    468                                                               const PAUDMIXBUF_CONVOPTS pOpts) \
     466                                                              const PPDMAUDMIXBUF_CONVOPTS pOpts) \
    469467    { \
    470468        PPDMAUDIOSAMPLE pSrc = paSrc; \
     
    485483    \
    486484    AUDMIXBUF_MACRO_FN void audioMixBufConvTo##_aName##Mono(void *pvDst, const PPDMAUDIOSAMPLE paSrc, \
    487                                                             const PAUDMIXBUF_CONVOPTS pOpts) \
     485                                                            const PPDMAUDMIXBUF_CONVOPTS pOpts) \
    488486    { \
    489487        PPDMAUDIOSAMPLE pSrc = paSrc; \
     
    614612/** Dummy conversion used when the source is muted. */
    615613AUDMIXBUF_MACRO_FN uint32_t audioMixBufConvFromSilence(PPDMAUDIOSAMPLE paDst, const void *pvSrc,
    616                                                        uint32_t cbSrc, const PAUDMIXBUF_CONVOPTS pOpts)
     614                                                       uint32_t cbSrc, const PPDMAUDMIXBUF_CONVOPTS pOpts)
    617615{
    618616    /* Internally zero always corresponds to silence. */
     
    630628 * @param   enmFmt                  Audio format to lookup conversion macro for.
    631629 */
    632 static inline PAUDMIXBUF_FN_CONVFROM audioMixBufConvFromLookup(PDMAUDIOMIXBUFFMT enmFmt)
     630static PPDMAUDMIXBUF_FN_CONVFROM audioMixBufConvFromLookup(PDMAUDIOMIXBUFFMT enmFmt)
    633631{
    634632    if (AUDMIXBUF_FMT_SIGNED(enmFmt))
     
    691689 * @param   enmFmt                  Audio format to lookup conversion macro for.
    692690 */
    693 static inline PAUDMIXBUF_FN_CONVTO audioMixBufConvToLookup(PDMAUDIOMIXBUFFMT enmFmt)
     691static PPDMAUDMIXBUF_FN_CONVTO audioMixBufConvToLookup(PDMAUDIOMIXBUFFMT enmFmt)
    694692{
    695693    if (AUDMIXBUF_FMT_SIGNED(enmFmt))
     
    11501148{
    11511149    audioMixBufDbgPrintIndent(uIdtLvl,
    1152                            "[%s] %s (%RU32): offReadWrite=%RU32, cProcessed=%RU32, cMixed=%RU32 (BpS=%RU32)\n",
    1153                            fIsParent ? "PARENT" : "CHILD",
    1154                            pMixBuf->pszName, pMixBuf->cSamples,
    1155                            pMixBuf->offReadWrite, pMixBuf->cProcessed, pMixBuf->cMixed,
    1156                            AUDIOMIXBUF_S2B(pMixBuf, 1));
     1150                              "[%s] %s: offReadWrite=%RU32, cProc=%RU32, cMixed=%RU32 / %RU32)\n",
     1151                              fIsParent ? "PARENT" : "CHILD",
     1152                              pMixBuf->pszName, pMixBuf->offReadWrite, pMixBuf->cProcessed, pMixBuf->cMixed, pMixBuf->cSamples);
    11571153}
    11581154
     
    11721168    {
    11731169        audioMixBufDbgPrintSingle(pIter, false /* ifIsParent */, uIdtLvl + 1);
     1170        *pcChildren++;
    11741171        audioMixBufDbgPrintChainHelper(pIter, uIdtLvl + 1, pcChildren);
    11751172    }
     1173}
     1174
     1175static void audioMixBufDbgPrintChainInternal(PPDMAUDIOMIXBUF pMixBuf)
     1176{
     1177    PPDMAUDIOMIXBUF pParent = pMixBuf->pParent;
     1178    while (pParent)
     1179    {
     1180        if (!pParent->pParent)
     1181            break;
     1182
     1183        pParent = pParent->pParent;
     1184    }
     1185
     1186    if (!pParent)
     1187        pParent = pMixBuf;
     1188
     1189    AUDMIXBUF_LOG(("********************************************\n"));
     1190
     1191    audioMixBufDbgPrintSingle(pParent, true /* fIsParent */, 0 /* uIdtLvl */);
     1192
     1193    /* Recursively iterate children. */
     1194    size_t cChildren = 0;
     1195    audioMixBufDbgPrintChainHelper(pParent, 0 /* uIdtLvl */, &cChildren);
     1196
     1197    AUDMIXBUF_LOG(("Children: %zu - Total samples mixed: %RU64\n", cChildren, s_cSamplesMixedTotal));
     1198    AUDMIXBUF_LOG(("********************************************\n"));
    11761199}
    11771200
     
    11861209void AudioMixBufDbgPrintChain(PPDMAUDIOMIXBUF pMixBuf)
    11871210{
    1188     PPDMAUDIOMIXBUF pParent = pMixBuf->pParent;
    1189     while (pParent)
    1190     {
    1191         if (!pParent->pParent)
    1192             break;
    1193 
    1194         pParent = pParent->pParent;
    1195     }
    1196 
    1197     if (!pParent)
    1198         pParent = pMixBuf;
    1199 
    1200     AUDMIXBUF_LOG(("********************************************\n"));
    1201 
    1202     audioMixBufDbgPrintSingle(pParent, true /* fIsParent */, 0 /* uIdtLvl */);
    1203 
    1204     /* Recursively iterate children. */
    1205     size_t cChildren = 0;
    1206     audioMixBufDbgPrintChainHelper(pParent, 0 /* uIdtLvl */, &cChildren);
    1207 
    1208     AUDMIXBUF_LOG(("Children: %zu - Total samples mixed: %RU64\n", cChildren, s_cSamplesMixedTotal));
    1209     AUDMIXBUF_LOG(("********************************************\n"));
     1211    audioMixBufDbgPrintChainInternal(pMixBuf);
    12101212}
    12111213
     
    12251227    AUDMIXBUF_LOG(("********************************************\n"));
    12261228
    1227     audioMixBufDbgPrintSingle(pMixBuf, true /* fIsParent */, 0 /* iIdtLevel */);
     1229    audioMixBufDbgPrintSingle(pMixBuf, pParent == pMixBuf /* fIsParent */, 0 /* iIdtLevel */);
    12281230
    12291231    PPDMAUDIOMIXBUF pIter;
    12301232    RTListForEach(&pParent->lstBuffers, pIter, PDMAUDIOMIXBUF, Node)
    1231         audioMixBufDbgPrintSingle(pMixBuf, false /* fIsParent */, 1 /* iIdtLevel */);
     1233    {
     1234        if (pIter == pMixBuf)
     1235            continue;
     1236        audioMixBufDbgPrintSingle(pIter, false /* fIsParent */, 1 /* iIdtLevel */);
     1237    }
     1238
     1239    AUDMIXBUF_LOG(("********************************************\n"));
    12321240}
    12331241#endif
     
    13011309    if (cToProcess)
    13021310    {
    1303         PAUDMIXBUF_FN_CONVTO pConv;
     1311        PPDMAUDMIXBUF_FN_CONVTO pConv;
    13041312        if (pMixBuf->AudioFmt != enmFmt)
    13051313            pConv = audioMixBufConvToLookup(enmFmt);
     
    13091317        if (pConv)
    13101318        {
    1311             AUDMIXBUF_CONVOPTS convOpts = { cToProcess, pMixBuf->Volume };
     1319            PDMAUDMIXBUF_CONVOPTS convOpts = { cToProcess, pMixBuf->Volume };
    13121320
    13131321            AssertPtr(pConv);
     
    13881396    }
    13891397
    1390     PAUDMIXBUF_FN_CONVTO pConv = audioMixBufConvToLookup(enmFmt);
     1398    PPDMAUDMIXBUF_FN_CONVTO pConv = audioMixBufConvToLookup(enmFmt);
    13911399    if (!pConv) /* Audio format not supported. */
    13921400        return VERR_NOT_SUPPORTED;
     
    14181426    }
    14191427
    1420     AUDMIXBUF_CONVOPTS convOpts;
     1428    PDMAUDMIXBUF_CONVOPTS convOpts;
    14211429    convOpts.Volume = pMixBuf->Volume;
    14221430
     
    16371645        return VERR_BUFFER_OVERFLOW;
    16381646
    1639     PAUDMIXBUF_FN_CONVFROM pConv;
     1647    PPDMAUDMIXBUF_FN_CONVFROM pConv;
    16401648    if (pMixBuf->AudioFmt != enmFmt)
    16411649        pConv = audioMixBufConvFromLookup(enmFmt);
     
    16651673    if (cToProcess)
    16661674    {
    1667         AUDMIXBUF_CONVOPTS convOpts = { cToProcess, pMixBuf->Volume };
     1675        PDMAUDMIXBUF_CONVOPTS convOpts = { cToProcess, pMixBuf->Volume };
    16681676
    16691677        cWritten = pConv(pMixBuf->pSamples + offSamples, pvBuf, cbBuf, &convOpts);
     
    16931701 * format of the mixing buffer.
    16941702 *
    1695  * @return  IPRT status code.
     1703 * @return  IPRT status code, or VINF_BUFFER_OVERFLOW if samples which not have
     1704 *          been processed yet have been overwritten (due to cyclic buffer).
    16961705 * @param   pMixBuf                 Pointer to mixing buffer to write to.
    16971706 * @param   pvBuf                   Pointer to audio buffer to be written.
     
    17091718 * Writes audio samples of a specific format.
    17101719 *
    1711  * @return  IPRT status code.
     1720 * @return  IPRT status code, or VINF_BUFFER_OVERFLOW if samples which not have
     1721 *          been processed yet have been overwritten (due to cyclic buffer).
    17121722 * @param   pMixBuf                 Pointer to mixing buffer to write to.
    17131723 * @param   enmFmt                  Audio format supplied in the buffer.
     
    17211731{
    17221732    AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
    1723     AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
     1733    AssertPtrReturn(pvBuf,   VERR_INVALID_POINTER);
    17241734    /* pcbWritten is optional. */
    17251735
     
    17311741    }
    17321742
    1733     PPDMAUDIOMIXBUF pParent = pMixBuf->pParent;
    1734 
    1735     AUDMIXBUF_LOG(("%s: enmFmt=%ld, pBuf=%p, cbBuf=%zu, pParent=%p (%RU32)\n",
    1736                    pMixBuf->pszName, enmFmt, pvBuf, cbBuf, pParent, pParent ? pParent->cSamples : 0));
    1737 
    1738     if (   pParent
    1739         && pParent->cSamples <= pMixBuf->cMixed)
    1740     {
    1741         if (pcWritten)
    1742             *pcWritten = 0;
    1743 
    1744         AUDMIXBUF_LOG(("%s: Parent buffer %s is full\n",
    1745                        pMixBuf->pszName, pMixBuf->pParent->pszName));
    1746 
    1747         return VINF_SUCCESS;
    1748     }
    1749 
    1750     PAUDMIXBUF_FN_CONVFROM pConv;
     1743    AUDMIXBUF_LOG(("%s: enmFmt=%ld, pvBuf=%p, cbBuf=%RU32 (%RU32 samples)\n",
     1744                   pMixBuf->pszName, enmFmt, pvBuf, cbBuf, AUDIOMIXBUF_B2S(pMixBuf, cbBuf)));
     1745
     1746    PPDMAUDMIXBUF_FN_CONVFROM pCnvFrm;
    17511747    if (pMixBuf->AudioFmt != enmFmt)
    1752         pConv = audioMixBufConvFromLookup(enmFmt);
     1748        pCnvFrm = audioMixBufConvFromLookup(enmFmt);
    17531749    else
    17541750    {
    1755         pConv = pMixBuf->Volume.fMuted
    1756               ? &audioMixBufConvFromSilence : pMixBuf->pConvFrom;
    1757     }
    1758 
    1759     if (!pConv)
     1751        pCnvFrm = pMixBuf->Volume.fMuted
     1752                ? &audioMixBufConvFromSilence : pMixBuf->pConvFrom;
     1753    }
     1754
     1755    if (!pCnvFrm)
    17601756        return VERR_NOT_SUPPORTED;
    17611757
     
    17711767    uint32_t cLenDst2 = 0;
    17721768
    1773     uint32_t offWrite = pMixBuf->offReadWrite + cToWrite;
     1769    uint32_t cOffWrite = pMixBuf->offReadWrite + cToWrite;
    17741770
    17751771    /*
     
    17781774     * be the optional second part to do.
    17791775     */
    1780     if (offWrite >= pMixBuf->cSamples)
     1776    if (cOffWrite >= pMixBuf->cSamples)
    17811777    {
    17821778        Assert(pMixBuf->offReadWrite <= pMixBuf->cSamples);
     
    17881784
    17891785        /* Save new read offset. */
    1790         offWrite = cLenDst2;
    1791     }
    1792 
    1793     uint32_t cWrittenTotal = 0;
    1794 
    1795     AUDMIXBUF_CONVOPTS convOpts;
     1786        cOffWrite = cLenDst2;
     1787    }
     1788
     1789#ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
     1790    RTFILE fh;
     1791    RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writecirc_ex-32bit-float.pcm",
     1792               RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
     1793#endif
     1794
     1795    uint32_t cWritten;
     1796
     1797    PDMAUDMIXBUF_CONVOPTS convOpts;
    17961798    convOpts.Volume = pMixBuf->Volume;
    17971799
     
    18001802    {
    18011803        convOpts.cSamples = cLenDst1;
    1802         cWrittenTotal = pConv(pSamplesDst1, pvBuf, cbBuf, &convOpts);
     1804        cWritten = pCnvFrm(pSamplesDst1, pvBuf, cbBuf, &convOpts);
     1805        Assert(cWritten == cLenDst1);
     1806
     1807#ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
     1808        RTFileWrite(fh, pSamplesDst1, cWritten * sizeof(PDMAUDIOSAMPLE), NULL);
     1809#endif
    18031810    }
    18041811
     
    18101817
    18111818        convOpts.cSamples = cLenDst2;
    1812         cWrittenTotal += pConv(pSamplesDst2, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), cbBuf, &convOpts);
    1813     }
     1819        cWritten = pCnvFrm(pSamplesDst2, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), cbBuf, &convOpts);
     1820        Assert(cWritten == cLenDst2);
    18141821
    18151822#ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
    1816         RTFILE fh;
    1817         RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writeex.pcm",
    1818                    RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    1819         RTFileWrite(fh, pSamplesDst1, AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), NULL);
    1820         RTFileClose(fh);
    1821 #endif
    1822 
    1823     AUDMIXBUF_LOG(("cLenDst1=%RU32, cLenDst2=%RU32, offWrite=%RU32\n",
    1824                    cLenDst1, cLenDst2, offWrite));
     1823        RTFileWrite(fh, pSamplesDst2, cWritten * sizeof(PDMAUDIOSAMPLE), NULL);
     1824#endif
     1825    }
     1826
     1827#ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
     1828    RTFileClose(fh);
     1829#endif
    18251830
    18261831    if (RT_SUCCESS(rc))
    18271832    {
    1828         pMixBuf->offReadWrite = offWrite % pMixBuf->cSamples;
    1829         pMixBuf->cProcessed = RT_MIN(pMixBuf->cProcessed + cLenDst1 + cLenDst2,
    1830                                      pMixBuf->cSamples /* Max */);
     1833        pMixBuf->offReadWrite = cOffWrite % pMixBuf->cSamples;
     1834
     1835        uint32_t cProcessedTotal = pMixBuf->cProcessed + cLenDst1 + cLenDst2;
     1836        if (cProcessedTotal > pMixBuf->cSamples)
     1837        {
     1838            AUDMIXBUF_LOG(("Warning: %RU32 unprocessed samples overwritten\n", cProcessedTotal - pMixBuf->cSamples));
     1839            pMixBuf->cProcessed = pMixBuf->cSamples;
     1840
     1841            rc = VINF_BUFFER_OVERFLOW;
     1842        }
     1843
    18311844        if (pcWritten)
    18321845            *pcWritten = cLenDst1 + cLenDst2;
     
    18371850#endif
    18381851
    1839     AUDMIXBUF_LOG(("cWritten=%RU32 (%zu bytes), rc=%Rrc\n",
    1840                    cLenDst1 + cLenDst2,
     1852    AUDMIXBUF_LOG(("offReadWrite=%RU32, cLenDst1=%RU32, cLenDst2=%RU32, cTotal=%RU32 (%zu bytes), rc=%Rrc\n",
     1853                   pMixBuf->offReadWrite, cLenDst1, cLenDst2, cLenDst1 + cLenDst2,
    18411854                   AUDIOMIXBUF_S2B(pMixBuf, cLenDst1 + cLenDst2), rc));
     1855
    18421856    return rc;
    18431857}
  • trunk/src/VBox/Devices/Audio/AudioMixer.cpp

    r61079 r61157  
    4949#include <iprt/string.h>
    5050
     51static int audioMixerRemoveSinkInternal(PAUDIOMIXER pMixer, PAUDMIXSINK pSink);
     52
    5153static void audioMixerSinkDestroyInternal(PAUDMIXSINK pSink);
    5254static int audioMixerSinkUpdateVolume(PAUDMIXSINK pSink, const PPDMAUDIOVOLUME pVolMaster);
    53 static void audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
     55static void audioMixerSinkRemoveAllStreamsInternal(PAUDMIXSINK pSink);
     56static int audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
    5457static int audioMixerSinkUpdateInternal(PAUDMIXSINK pSink);
    5558
    5659static void audioMixerStreamDestroyInternal(PAUDMIXSTREAM pStream);
    57 static void audioMixerStreamFree(PAUDMIXSTREAM pStream);
     60
    5861
    5962int AudioMixerCreateSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PAUDMIXSINK *ppSink)
     
    125128                 pMixer->pszName, fFlags, pCfg->enmDir, DrvAudioAudFmtToStr(pCfg->enmFormat), pCfg->cChannels, pCfg->uHz));
    126129
    127     int rc;
    128     if (pCfg->enmDir == PDMAUDIODIR_IN)
    129     {
    130         PPDMAUDIOGSTSTRMIN pGstStrm;
    131         rc = pConn->pfnCreateIn(pConn, pCfg, &pGstStrm);
    132         if (RT_SUCCESS(rc))
    133         {
    134             pMixStream->InOut.pIn = pGstStrm;
    135 
    136             /* Increase the stream's reference count to let others know
    137              * we're reyling on it to be around now. */
    138             pConn->pfnAddRefIn(pConn, pGstStrm);
    139         }
    140     }
    141     else if (pCfg->enmDir == PDMAUDIODIR_OUT)
    142     {
    143         PPDMAUDIOGSTSTRMOUT pGstStrm;
    144         rc = pConn->pfnCreateOut(pConn, pCfg, &pGstStrm);
    145         if (RT_SUCCESS(rc))
    146         {
    147             pMixStream->InOut.pOut = pGstStrm;
    148 
    149             /* Increase the stream's reference count to let others know
    150              * we're reyling on it to be around now. */
    151             pConn->pfnAddRefOut(pConn, pGstStrm);
    152         }
    153     }
    154     else
    155     {
    156         AssertMsgFailed(("Direction not implemented\n"));
    157         rc = VERR_NOT_IMPLEMENTED;
    158     }
    159 
     130    PPDMAUDIOSTREAM pStream;
     131    int rc = pConn->pfnStreamCreate(pConn, pCfg, &pStream);
    160132    if (RT_SUCCESS(rc))
    161133    {
     134        /* Save the audio stream pointer to this mixing stream. */
     135        pMixStream->pStream = pStream;
     136
     137        /* Increase the stream's reference count to let others know
     138         * we're reyling on it to be around now. */
     139        pConn->pfnStreamAddRef(pConn, pStream);
     140    }
     141
     142    if (RT_SUCCESS(rc))
     143    {
    162144        pMixStream->fFlags = fFlags;
    163         pMixStream->enmDir = pCfg->enmDir;
    164145        pMixStream->pConn  = pConn;
    165146
     
    203184            pMixer->VolMaster.uRight = UINT32_MAX;
    204185
    205             LogFlowFunc(("Created %p ...\n", pMixer));
     186            LogFlowFunc(("Created mixer '%s'\n", pMixer->pszName));
    206187
    207188            *ppMixer = pMixer;
     
    242223    PAUDMIXSINK pSink, pSinkNext;
    243224    RTListForEachSafe(&pMixer->lstSinks, pSink, pSinkNext, AUDMIXSINK, Node)
    244         audioMixerSinkDestroyInternal(pSink);
     225    {
     226        /* Save a pointer to the sink to remove, as pSink
     227         * will not be valid anymore after calling audioMixerRemoveSinkInternal(). */
     228        PAUDMIXSINK pSinkToRemove = pSink;
     229
     230        audioMixerRemoveSinkInternal(pMixer, pSinkToRemove);
     231        audioMixerSinkDestroyInternal(pSinkToRemove);
     232    }
     233
     234    pMixer->cSinks = 0;
    245235
    246236    if (pMixer->pszName)
     
    280270}
    281271
    282 void AudioMixerRemoveSink(PAUDIOMIXER pMixer, PAUDMIXSINK pSink)
    283 {
    284     AssertPtrReturnVoid(pMixer);
     272static int audioMixerRemoveSinkInternal(PAUDIOMIXER pMixer, PAUDMIXSINK pSink)
     273{
     274    AssertPtrReturn(pMixer, VERR_INVALID_PARAMETER);
    285275    if (!pSink)
    286         return;
    287 
    288     /** @todo Check if pSink is part of pMixer. */
    289 
    290     AudioMixerSinkRemoveAllStreams(pSink);
    291 
    292     Assert(pSink->cStreams == 0);
    293 
     276        return VERR_NOT_FOUND;
     277
     278    AssertMsgReturn(pSink->pParent == pMixer, ("Sink '%s' is not part of mixer '%s'\n",
     279                                               pSink->pszName, pMixer->pszName), VERR_NOT_FOUND);
     280
     281    LogFlowFunc(("[%s]: pSink=%s, cSinks=%RU8\n",
     282                 pMixer->pszName, pSink->pszName, pMixer->cSinks));
     283
     284    /* Remove sink from mixer. */
    294285    RTListNodeRemove(&pSink->Node);
    295 
    296286    Assert(pMixer->cSinks);
    297287    pMixer->cSinks--;
    298288
    299     LogFlowFunc(("[%s]: pSink=%s, cSinks=%RU8\n",
    300                  pMixer->pszName, pSink->pszName, pMixer->cSinks));
     289    /* Set mixer to NULL so that we know we're not part of any mixer anymore. */
     290    pSink->pParent = NULL;
     291
     292    return VINF_SUCCESS;
     293}
     294
     295void AudioMixerRemoveSink(PAUDIOMIXER pMixer, PAUDMIXSINK pSink)
     296{
     297    audioMixerSinkRemoveAllStreamsInternal(pSink);
     298    audioMixerRemoveSinkInternal(pMixer, pSink);
    301299}
    302300
     
    346344        return VERR_NO_MORE_HANDLES;
    347345
    348     /** @todo Check if stream already is assigned to (another) sink. */
    349 
    350     RTListAppend(&pSink->lstStreams, &pStream->Node);
    351     pSink->cStreams++;
    352 
    353     LogFlowFunc(("[%s]: cStreams=%RU8\n", pSink->pszName, pSink->cStreams));
    354 
    355     return VINF_SUCCESS;
     346    int rc;
     347
     348    LogFlowFuncEnter();
     349
     350#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     351    /* Make sure only compatible streams are added. */
     352    if (pStream->enmDir == PDMAUDIODIR_IN)
     353    {
     354        if (DrvAudioPCMPropsAreEqual(&pSink->PCMProps, &pStream->InOut.pIn->Props))
     355        {
     356#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     357            /* Chain: Stream (Child) -> Sink (Child) -> Guest (Parent). */
     358            PPDMAUDIOMIXBUF pHstIn = &pStream->InOut.pIn->pHstStrmIn->MixBuf;
     359            PPDMAUDIOMIXBUF pGstIn = &pStream->InOut.pIn->MixBuf;
     360
     361            /* Unlink any former parent from host input. */
     362            AudioMixBufUnlink(pHstIn);
     363
     364            /* Link host input to this sink as a parent. */
     365            rc = AudioMixBufLinkTo(pHstIn, &pSink->MixBuf);
     366            AssertRC(rc);
     367
     368            /* Unlink any former parent from this sink. */
     369            AudioMixBufUnlink(&pSink->MixBuf);
     370
     371            /* Link guest input to this sink as a parent. */
     372            rc = AudioMixBufLinkTo(&pSink->MixBuf, pGstIn);
     373            AssertRC(rc);
     374# ifdef DEBUG
     375            AudioMixBufDbgPrintChain(&pStream->InOut.pIn->MixBuf);
     376# endif
     377#endif /* VBOX_AUDIO_MIXER_WITH_MIXBUF */
     378        }
     379        else
     380            rc = VERR_WRONG_TYPE;
     381    }
     382    else if (pStream->enmDir == PDMAUDIODIR_OUT)
     383    {
     384        if (DrvAudioPCMPropsAreEqual(&pSink->PCMProps, &pStream->InOut.pOut->Props))
     385        {
     386#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     387            /* Chain: Guest (Child) -> Sink (Child) -> Stream (Parent). */
     388            rc = AudioMixBufLinkTo(&pStream->InOut.pOut->pHstStrmOut->MixBuf, &pSink->MixBuf);
     389# ifdef DEBUG
     390            AudioMixBufDbgPrintChain(&pSink->MixBuf);
     391# endif
     392#endif /* VBOX_AUDIO_MIXER_WITH_MIXBUF */
     393        }
     394        else
     395            rc = VERR_WRONG_TYPE;
     396    }
     397    else
     398    {
     399        AssertMsgFailed(("Direction not implemented\n"));
     400        rc = VERR_NOT_IMPLEMENTED;
     401    }
     402#else
     403    rc = VINF_SUCCESS;
     404#endif
     405
     406    if (RT_SUCCESS(rc))
     407    {
     408        /** @todo Check if stream already is assigned to (another) sink. */
     409
     410        /* Save pointer to sink the stream is attached to. */
     411        pStream->pSink = pSink;
     412
     413        /* Append stream to sink's list. */
     414        RTListAppend(&pSink->lstStreams, &pStream->Node);
     415        pSink->cStreams++;
     416    }
     417
     418    LogFlowFunc(("[%s]: cStreams=%RU8, rc=%Rrc\n", pSink->pszName, pSink->cStreams, rc));
     419    return rc;
    356420}
    357421
     
    396460void AudioMixerSinkDestroy(PAUDMIXSINK pSink)
    397461{
    398     audioMixerSinkDestroyInternal(pSink);
    399 }
    400 
    401 static void audioMixerSinkDestroyInternal(PAUDMIXSINK pSink)
    402 {
    403     AssertPtrReturnVoid(pSink);
    404462    if (!pSink)
    405463        return;
    406464
     465    if (pSink->pParent)
     466    {
     467        /* Save sink pointer, as after audioMixerRemoveSinkInternal() the
     468         * pointer will be gone from the stream. */
     469        PAUDIOMIXER pMixer = pSink->pParent;
     470
     471        audioMixerRemoveSinkInternal(pMixer, pSink);
     472
     473        Assert(pMixer->cSinks);
     474        pMixer->cSinks--;
     475    }
     476
     477    audioMixerSinkDestroyInternal(pSink);
     478}
     479
     480static void audioMixerSinkDestroyInternal(PAUDMIXSINK pSink)
     481{
     482    AssertPtrReturnVoid(pSink);
     483
    407484    LogFunc(("%s\n", pSink->pszName));
    408485
     
    410487    RTListForEachSafe(&pSink->lstStreams, pStream, pStreamNext, AUDMIXSTREAM, Node)
    411488    {
    412         audioMixerSinkRemoveStreamInternal(pSink, pStream);
    413         audioMixerStreamDestroyInternal(pStream);
    414     }
    415 
    416     Assert(pSink->cStreams == 0);
     489        /* Save a pointer to the stream to remove, as pStream
     490         * will not be valid anymore after calling audioMixerSinkRemoveStreamInternal(). */
     491        PAUDMIXSTREAM pStreamToRemove = pStream;
     492
     493        audioMixerSinkRemoveStreamInternal(pSink, pStreamToRemove);
     494        audioMixerStreamDestroyInternal(pStreamToRemove);
     495    }
    417496
    418497    if (pSink->pszName)
     498    {
    419499        RTStrFree(pSink->pszName);
     500        pSink->pszName = NULL;
     501    }
    420502
    421503    RTMemFree(pSink);
     504    pSink = NULL;
    422505}
    423506
     
    466549    if (!pSink)
    467550        return false;
     551
     552    LogFlowFunc(("[%s]: %RTbool\n", pSink->pszName, (pSink->fFlags & AUDMIXSINK_FLAG_DIRTY)));
    468553
    469554    /* If the dirty flag is set, there is unprocessed data in the sink. */
     
    487572    uint32_t cbRead = 0;
    488573
    489     PAUDMIXSTREAM pStream;
    490     RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
    491     {
    492         if (!pStream->pConn->pfnIsActiveIn(pStream->pConn, pStream->InOut.pIn))
     574    PAUDMIXSTREAM pMixStream;
     575    RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node)
     576    {
     577        if (!(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED))
    493578            continue;
    494579
     
    499584        {
    500585            uint32_t cbReadStrm;
    501             AssertPtr(pStream->pConn);
    502             rc = pStream->pConn->pfnRead(pStream->pConn, pStream->InOut.pIn,
    503                                          (uint8_t *)pvMixBuf + cbTotalRead, cbToRead, &cbReadStrm);
     586            AssertPtr(pMixStream->pConn);
     587            rc = pMixStream->pConn->pfnStreamRead(pMixStream->pConn, pMixStream->pStream,
     588                                                  (uint8_t *)pvMixBuf + cbTotalRead, cbToRead, &cbReadStrm);
    504589            if (   RT_FAILURE(rc)
    505590                || !cbReadStrm)
     
    533618}
    534619
    535 static void audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream)
    536 {
    537     AssertPtrReturnVoid(pSink);
     620static int audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream)
     621{
     622    AssertPtrReturn(pSink, VERR_INVALID_PARAMETER);
    538623    if (!pStream)
    539         return;
    540 
    541     /** @todo Check if pStream is part of pSink. */
    542 
    543     Assert(pSink->cStreams);
    544 
    545 #ifdef DEBUG
    546     const char *pszStream = pSink->enmDir == AUDMIXSINKDIR_INPUT
    547                           ? pStream->InOut.pIn->MixBuf.pszName : pStream->InOut.pOut->MixBuf.pszName;
     624        return VERR_NOT_FOUND;
     625
     626    AssertMsgReturn(pStream->pSink == pSink, ("Stream '%s' is not part of sink '%s'\n",
     627                                               pStream->pszName, pSink->pszName), VERR_NOT_FOUND);
    548628
    549629    LogFlowFunc(("[%s]: (Stream = %s), cStreams=%RU8\n",
    550                  pSink->pszName, pszStream ? pszStream : "<Unnamed>", pSink->cStreams));
     630                 pSink->pszName, pStream->pStream->szName, pSink->cStreams));
     631
     632#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     633    /* Unlink mixing buffer. */
     634    AudioMixBufUnlink(&pStream->pStream->MixBuf);
    551635#endif
    552636
    553637    /* Remove stream from sink. */
    554638    RTListNodeRemove(&pStream->Node);
    555 
    556639    Assert(pSink->cStreams);
    557640    pSink->cStreams--;
     641
     642    /* Set sink to NULL so that we know we're not part of any sink anymore. */
     643    pStream->pSink = NULL;
     644
     645    return VINF_SUCCESS;
    558646}
    559647
     
    561649{
    562650    audioMixerSinkRemoveStreamInternal(pSink, pStream);
     651}
     652
     653/**
     654 * Removes all attached streams from a given sink.
     655 *
     656 * @param pSink         Sink to remove attached streams from.
     657 */
     658static void audioMixerSinkRemoveAllStreamsInternal(PAUDMIXSINK pSink)
     659{
     660    if (!pSink)
     661        return;
     662
     663    LogFunc(("%s\n", pSink->pszName));
     664
     665    PAUDMIXSTREAM pStream, pStreamNext;
     666    RTListForEachSafe(&pSink->lstStreams, pStream, pStreamNext, AUDMIXSTREAM, Node)
     667        audioMixerSinkRemoveStreamInternal(pSink, pStream);
    563668}
    564669
     
    573678        return;
    574679
    575     LogFunc(("%s\n", pSink->pszName));
    576 
    577     PAUDMIXSTREAM pStream, pStreamNext;
    578     RTListForEachSafe(&pSink->lstStreams, pStream, pStreamNext, AUDMIXSTREAM, Node)
    579         audioMixerSinkRemoveStreamInternal(pSink, pStream);
    580 
    581     Assert(pSink->cStreams == 0);
     680    audioMixerSinkRemoveAllStreamsInternal(pSink);
     681
     682    pSink->cStreams = 0;
    582683}
    583684
     
    599700                 pSink->pszName, pSink->PCMProps.cBits, pSink->PCMProps.cChannels, pSink->PCMProps.uHz));
    600701
    601 #if 0
    602     PAUDMIXSTREAM pStream;
    603     RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
    604     {
    605         /** @todo Invalidate mix buffers! */
    606     }
    607 #endif
    608 
    609     return VINF_SUCCESS;
     702    int rc = VINF_SUCCESS;
     703
     704#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     705    /* Also update the sink's mixing buffer format. */
     706    AudioMixBufDestroy(&pSink->MixBuf);
     707    rc = AudioMixBufInit(&pSink->MixBuf, pSink->pszName, pPCMProps, _4K /** @todo Make configurable? */);
     708    if (RT_SUCCESS(rc))
     709    {
     710        PAUDMIXSTREAM pStream;
     711        RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
     712        {
     713            /** @todo Invalidate mix buffers! */
     714        }
     715    }
     716#endif /* VBOX_AUDIO_MIXER_WITH_MIXBUF */
     717
     718    LogFlowFuncLeaveRC(rc);
     719    return rc;
    610720}
    611721
     
    639749    LogFlowFunc(("[%s]: cTimerTicks=%RU64, cTicksElapsed=%RU64\n", pSink->pszName, cTimerTicks, cTicksElapsed));
    640750
    641     //uint32_t cSamplesMin  = (uint32_t)((2 * cTicksElapsed * pSink->PCMProps.uHz + cTimerTicks) / cTimerTicks / 2);
    642     uint32_t cSamplesMin  = (cTicksElapsed / pSink->PCMProps.uHz) * pSink->PCMProps.cChannels;
    643     uint32_t cbSamplesMin = cSamplesMin << pSink->PCMProps.cShift;
    644 
    645     Assert((cbSamplesMin % 2 == 0));
    646 
    647     LogFlowFunc(("[%s]: cSamplesMin=%RU32 (%RU32 bytes, %RU32Hz)\n", pSink->pszName, cSamplesMin, cbSamplesMin, pSink->PCMProps.uHz));
     751//    uint32_t cSamplesMin  = (uint32_t)((2 * cTicksElapsed * pSink->PCMProps.uHz + cTimerTicks) / cTimerTicks / 2);
     752   uint32_t cSamplesMin  = (cTicksElapsed / pSink->PCMProps.uHz) * pSink->PCMProps.cChannels;
     753  //  cSamplesMin = (uint32_t)((2 * cTicksElapsed * 44100 + cTimerTicks) / cTimerTicks / 2);
     754    uint32_t cbSamplesMin = _4K; //cSamplesMin << pSink->PCMProps.cShift;
     755
     756    //Assert((cbSamplesMin % 2 == 0));
     757
     758//LogFlowFunc(("[%s]: cSamplesMin=%RU32 (%RU32 bytes, %RU32Hz)\n", pSink->pszName, cSamplesMin, cbSamplesMin, pSink->PCMProps.uHz));
     759
     760    uint32_t cbData = cbSamplesMin;
     761
     762    if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT)
     763    {
     764//        uint32_t cSinkSamplesLive = AudioMixBufAvail(&pSink->MixBuf);
     765//        if (!cSinkSamplesLive)
     766//            cbData = AUDIOMIXBUF_S2B_RATIO(&pSink->MixBuf, AudioMixBufFree(&pSink->MixBufGuest));
     767    }
    648768
    649769    audioMixerSinkUpdateInternal(pSink);
    650770
    651771    if (pcbData)
    652         *pcbData = cbSamplesMin;
     772        *pcbData = cbData;
    653773}
    654774
     
    659779    int rc = VINF_SUCCESS;
    660780
    661     PAUDMIXSTREAM pStream;
    662     RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
    663     {
    664         if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT)
     781    PAUDMIXSTREAM pMixStream;
     782    RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node)
     783    {
     784        PPDMAUDIOSTREAM pStream = pMixStream->pStream;
     785        AssertPtr(pStream);
     786
     787        uint32_t cSamplesAvail;
     788        uint32_t cSamplesProcessed = 0;
     789
     790        rc = pMixStream->pConn->pfnStreamGetData(pMixStream->pConn, pStream, &cSamplesAvail);
     791        if (   RT_SUCCESS(rc)
     792            && cSamplesAvail)
    665793        {
    666             uint32_t cSamplesLive;
    667             uint32_t cSamplesPlayed = 0;
    668             rc = pStream->pConn->pfnGetDataOut(pStream->pConn, NULL /* cbOut */, &cSamplesLive);
    669             if (   RT_SUCCESS(rc)
    670                 && cSamplesLive)
    671             {
    672                 rc = pStream->pConn->pfnPlayOut(pStream->pConn, &cSamplesPlayed);
    673             }
    674 
    675             if (RT_SUCCESS(rc))
    676             {
    677                 Assert(cSamplesLive >= cSamplesPlayed);
    678                 if (cSamplesLive - cSamplesPlayed) /* Some live samples left? */
    679                     pSink->fFlags |= AUDMIXSINK_FLAG_DIRTY;
    680                 else
    681                     pSink->fFlags &= ~AUDMIXSINK_FLAG_DIRTY;
    682             }
    683 
    684             Log3Func(("[%s]: fFlags=0x%x, cSamplesLive=%RU32, rc=%Rrc\n", pSink->pszName, pSink->fFlags, cSamplesLive, rc));
    685         }
    686         else if (pSink->enmDir == AUDMIXSINKDIR_INPUT)
    687         {
    688             uint32_t cbIn;
    689             rc = pStream->pConn->pfnGetDataIn(pStream->pConn, &cbIn);
    690             if (   RT_SUCCESS(rc)
    691                 && cbIn)
     794            if (pStream->enmDir == PDMAUDIODIR_IN)
    692795            {
    693796                /** @todo Implement this! */
    694                 // int rc2 = pStream->pConn->pfnCaptureIn(pStream->pConn, NULL /* pcSamplesCaptured */);
    695                 // Log3Func(("rc2=%Rrc\n", rc2));
     797            //  rc = pStream->pConn->pfnCapture(pStream->pConn, NULL /* pcSamplesCaptured */);
    696798            }
    697 
    698             if (RT_SUCCESS(rc))
     799            else
    699800            {
    700                 if (cbIn) /* Some inpput data available? */
    701                     pSink->fFlags |= AUDMIXSINK_FLAG_DIRTY;
    702                 else
    703                     pSink->fFlags &= ~AUDMIXSINK_FLAG_DIRTY;
     801                rc = pMixStream->pConn->pfnStreamPlay(pMixStream->pConn, pStream, &cSamplesProcessed);
    704802            }
    705803
    706             Log3Func(("[%s]: fFlags=0x%x, cbIn=%RU32, rc=%Rrc\n", pSink->pszName, pSink->fFlags, cbIn, rc));
     804            pSink->fFlags |= AUDMIXSINK_FLAG_DIRTY;
    707805        }
    708         else
    709         {
    710             rc = VERR_NOT_IMPLEMENTED;
    711             AssertMsgFailed(("Direction not implemented\n"));
    712         }
     806        else if (!cSamplesAvail)
     807            pSink->fFlags &= ~AUDMIXSINK_FLAG_DIRTY;
     808
     809        Log3Func(("[%s]: fFlags=0x%x, %RU32/%RU32 samples, rc=%Rrc\n",
     810                  pSink->pszName, pSink->fFlags, cSamplesProcessed, cSamplesAvail, rc));
    713811    }
    714812
     
    744842
    745843    /* Propagate new sink volume to all streams in the sink. */
    746     PAUDMIXSTREAM pStream;
    747     RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
     844    PAUDMIXSTREAM pMixStream;
     845    RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node)
    748846    {
    749847        if (fOut)
    750             AudioMixBufSetVolume(&pStream->InOut.pOut->MixBuf, &volSink);
     848            AudioMixBufSetVolume(&pMixStream->pStream->MixBuf, &volSink);
    751849        else
    752             AudioMixBufSetVolume(&pStream->InOut.pIn->MixBuf, &volSink);
     850            AudioMixBufSetVolume(&pMixStream->pStream->MixBuf, &volSink);
    753851    }
    754852
     
    770868    uint32_t cbProcessed = 0;
    771869
    772     PAUDMIXSTREAM pStream;
    773     RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node)
    774     {
    775         int rc2 = pStream->pConn->pfnWrite(pStream->pConn, pStream->InOut.pOut, pvBuf, cbBuf, &cbProcessed);
     870    PAUDMIXSTREAM pMixStream;
     871    RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node)
     872    {
     873        if (!(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED))
     874            continue;
     875
     876        int rc2 = pMixStream->pConn->pfnStreamWrite(pMixStream->pConn, pMixStream->pStream, pvBuf, cbBuf, &cbProcessed);
    776877        if (   RT_FAILURE(rc2)
    777878            || cbProcessed < cbBuf)
     
    791892 ********************************************************************************************************************************/
    792893
    793 int AudioMixerStreamCtl(PAUDMIXSTREAM pStream, PDMAUDIOSTREAMCMD enmCmd, uint32_t fCtl)
    794 {
    795     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     894int AudioMixerStreamCtl(PAUDMIXSTREAM pMixStream, PDMAUDIOSTREAMCMD enmCmd, uint32_t fCtl)
     895{
     896    AssertPtrReturn(pMixStream, VERR_INVALID_POINTER);
    796897    /** @todo Validate fCtl. */
    797898
     899    int rc = pMixStream->pConn->pfnStreamControl(pMixStream->pConn, pMixStream->pStream, enmCmd);
     900
     901    return rc;
     902}
     903
     904static void audioMixerStreamDestroyInternal(PAUDMIXSTREAM pMixStream)
     905{
     906    AssertPtrReturnVoid(pMixStream);
     907
     908    LogFunc(("%s\n", pMixStream->pszName));
     909
     910    if (pMixStream->pConn) /* Stream has a connector interface present? */
     911    {
     912        if (pMixStream->pStream)
     913        {
     914            pMixStream->pConn->pfnStreamRelease(pMixStream->pConn, pMixStream->pStream);
     915            pMixStream->pConn->pfnStreamDestroy(pMixStream->pConn, pMixStream->pStream);
     916
     917            pMixStream->pStream = NULL;
     918        }
     919
     920        pMixStream->pConn = NULL;
     921    }
     922
     923    if (pMixStream->pszName)
     924    {
     925        RTStrFree(pMixStream->pszName);
     926        pMixStream->pszName = NULL;
     927    }
     928
     929    RTMemFree(pMixStream);
     930    pMixStream = NULL;
     931}
     932
     933void AudioMixerStreamDestroy(PAUDMIXSTREAM pMixStream)
     934{
     935    if (!pMixStream)
     936        return;
     937
     938    LogFunc(("%s\n", pMixStream->pszName));
     939
    798940    int rc;
    799     switch (pStream->enmDir)
    800     {
    801         case PDMAUDIODIR_IN:
     941
     942    if (pMixStream->pSink)
     943    {
     944        /* Save sink pointer, as after audioMixerSinkRemoveStreamInternal() the
     945         * pointer will be gone from the stream. */
     946        PAUDMIXSINK pSink = pMixStream->pSink;
     947
     948        rc = audioMixerSinkRemoveStreamInternal(pMixStream->pSink, pMixStream);
     949        if (RT_SUCCESS(rc))
    802950        {
    803             if (   enmCmd == PDMAUDIOSTREAMCMD_ENABLE
    804                 || enmCmd == PDMAUDIOSTREAMCMD_DISABLE)
    805             {
    806                 rc = pStream->pConn->pfnEnableIn(pStream->pConn, pStream->InOut.pIn,
    807                                                  enmCmd == PDMAUDIOSTREAMCMD_ENABLE);
    808             }
    809             else
    810             {
    811                 AssertFailed();
    812                 rc = VERR_INVALID_PARAMETER;
    813             }
    814             break;
     951            AssertPtr(pSink);
     952            Assert(pSink->cStreams);
     953            pSink->cStreams--;
    815954        }
    816 
    817         case PDMAUDIODIR_OUT:
    818         {
    819             if (   enmCmd == PDMAUDIOSTREAMCMD_ENABLE
    820                 || enmCmd == PDMAUDIOSTREAMCMD_DISABLE)
    821             {
    822                 rc = pStream->pConn->pfnEnableOut(pStream->pConn, pStream->InOut.pOut,
    823                                                   enmCmd == PDMAUDIOSTREAMCMD_ENABLE);
    824             }
    825             else
    826             {
    827                 AssertFailed();
    828                 rc = VERR_INVALID_PARAMETER;
    829             }
    830             break;
    831         }
    832 
    833         default:
    834             AssertMsgFailed(("Not implemented\n"));
    835             rc = VERR_INVALID_PARAMETER;
    836             break;
    837     }
    838 
    839     return rc;
    840 }
    841 
    842 static void audioMixerStreamDestroyInternal(PAUDMIXSTREAM pStream)
    843 {
    844     if (!pStream)
    845         return;
    846 
    847     LogFunc(("%s\n", pStream->pszName));
    848 
    849     if (pStream->pConn) /* Stream has a connector interface present? */
    850     {
    851         if (   pStream->enmDir == PDMAUDIODIR_IN
    852             && pStream->pConn->pfnDestroyIn)
    853         {
    854             if (pStream->InOut.pIn)
    855             {
    856                 pStream->pConn->pfnReleaseIn(pStream->pConn, pStream->InOut.pIn);
    857                 pStream->pConn->pfnDestroyIn(pStream->pConn, pStream->InOut.pIn);
    858             }
    859         }
    860         else if (   pStream->enmDir == PDMAUDIODIR_OUT
    861                  && pStream->pConn->pfnDestroyOut)
    862         {
    863             if (pStream->InOut.pOut)
    864             {
    865                 pStream->pConn->pfnReleaseOut(pStream->pConn, pStream->InOut.pOut);
    866                 pStream->pConn->pfnDestroyOut(pStream->pConn, pStream->InOut.pOut);
    867             }
    868         }
    869         else
    870             AssertFailed();
    871     }
    872 
    873     audioMixerStreamFree(pStream);
    874 }
    875 
    876 void AudioMixerStreamDestroy(PAUDMIXSTREAM pStream)
    877 {
    878     audioMixerStreamDestroyInternal(pStream);
    879 }
    880 
    881 static void audioMixerStreamFree(PAUDMIXSTREAM pStream)
    882 {
    883     if (pStream)
    884     {
    885         LogFunc(("%s\n", pStream->pszName));
    886 
    887         if (pStream->pszName)
    888         {
    889             RTStrFree(pStream->pszName);
    890             pStream->pszName = NULL;
    891         }
    892 
    893         RTMemFree(pStream);
    894         pStream = NULL;
    895     }
    896 }
    897 
    898 bool AudioMixerStreamIsActive(PAUDMIXSTREAM pStream)
    899 {
    900     if (!pStream)
     955    }
     956    else
     957        rc = VINF_SUCCESS;
     958
     959    if (RT_SUCCESS(rc))
     960        audioMixerStreamDestroyInternal(pMixStream);
     961}
     962
     963bool AudioMixerStreamIsActive(PAUDMIXSTREAM pMixStream)
     964{
     965    if (!pMixStream)
    901966        return false;
    902967
    903     bool fIsActive;
    904     switch (pStream->enmDir)
    905     {
    906         case PDMAUDIODIR_IN:
    907         {
    908             fIsActive = pStream->pConn->pfnIsActiveIn(pStream->pConn, pStream->InOut.pIn);
    909             break;
    910         }
    911 
    912         case PDMAUDIODIR_OUT:
    913         {
    914             fIsActive = pStream->pConn->pfnIsActiveOut(pStream->pConn, pStream->InOut.pOut);
    915             break;
    916         }
    917 
    918         default:
    919             fIsActive = false;
    920             AssertMsgFailed(("Not implemented\n"));
    921             break;
    922     }
    923 
    924     return fIsActive;
    925 }
    926 
    927 bool AudioMixerStreamIsValid(PAUDMIXSTREAM pStream)
    928 {
    929     if (!pStream)
     968    return (pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED);
     969}
     970
     971bool AudioMixerStreamIsValid(PAUDMIXSTREAM pMixStream)
     972{
     973    if (!pMixStream)
    930974        return false;
    931975
    932     bool fIsValid;
    933     switch (pStream->enmDir)
    934     {
    935         case PDMAUDIODIR_IN:
    936         {
    937             fIsValid = pStream->pConn->pfnIsValidIn(pStream->pConn, pStream->InOut.pIn);
    938             break;
    939         }
    940 
    941         case PDMAUDIODIR_OUT:
    942         {
    943             fIsValid = pStream->pConn->pfnIsValidOut(pStream->pConn, pStream->InOut.pOut);
    944             break;
    945         }
    946 
    947         default:
    948             fIsValid = false;
    949             AssertMsgFailed(("Not implemented\n"));
    950             break;
    951     }
    952 
    953     return fIsValid;
    954 }
    955 
     976    uint32_t fStatus = pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream);
     977
     978    return (fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED);
     979}
     980
  • trunk/src/VBox/Devices/Audio/AudioMixer.h

    r61050 r61157  
    4646#define AUDMIXSTREAM_FLAG_NONE                  0
    4747
     48/** Prototype needed for AUDMIXSTREAM struct definition. */
     49typedef struct AUDMIXSINK *PAUDMIXSINK;
     50
    4851/**
    4952 * Structure for maintaining an audio mixer stream.
     
    5558    /** Name of this stream. */
    5659    char                   *pszName;
     60    /** Sink this stream is attached to. */
     61    PAUDMIXSINK             pSink;
    5762    /** Stream flags of type AUDMIXSTREAM_FLAG_. */
    5863    uint32_t                fFlags;
    5964    /** Pointer to audio connector being used. */
    6065    PPDMIAUDIOCONNECTOR     pConn;
    61     /** Audio direction of this stream. */
    62     PDMAUDIODIR             enmDir;
    63     /** Union of PDM input/output streams for this stream. */
    64     union
    65     {
    66         PPDMAUDIOGSTSTRMIN  pIn;
    67         PPDMAUDIOGSTSTRMOUT pOut;
    68     } InOut;
     66    /** Pointer to PDM audio stream this mixer stream handles. */
     67    PPDMAUDIOSTREAM         pStream;
    6968} AUDMIXSTREAM, *PAUDMIXSTREAM;
    7069
     
    124123    /** Number of streams assigned. */
    125124    uint8_t                 cStreams;
    126     /** List of assigned streams. */
     125    /** List of assigned streams.
     126     *  Note: All streams have the same PCM properties, so the
     127     *        mixer does not do any conversion. */
    127128    /** @todo Use something faster -- vector maybe? */
    128129    RTLISTANCHOR            lstStreams;
    129     /** This sink's mixing buffer. */
     130#ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF
     131    /** This sink's mixing buffer, acting as
     132     *  a parent buffer for all streams this sink owns. */
    130133    PDMAUDIOMIXBUF          MixBuf;
     134#endif
    131135    /** The volume of this sink. The volume always will
    132136     *  be combined with the mixer's master volume. */
  • trunk/src/VBox/Devices/Audio/DevIchAc97.cpp

    r61050 r61157  
    303303{
    304304    /** PCM line input stream. */
    305     R3PTRTYPE(PPDMAUDIOGSTSTRMIN) pStrmIn;
     305    R3PTRTYPE(PPDMAUDIOSTREAM)    pStream;
    306306    /** Mixer handle for line input stream. */
    307307    R3PTRTYPE(PAUDMIXSTREAM)      pMixStrm;
     
    311311{
    312312    /** PCM output stream. */
    313     R3PTRTYPE(PPDMAUDIOGSTSTRMOUT) pStrmOut;
     313    R3PTRTYPE(PPDMAUDIOSTREAM)     pStream;
    314314    /** Mixer handle for output stream. */
    315315    R3PTRTYPE(PAUDMIXSTREAM)       pMixStrm;
     
    417417#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    418418
    419 static void ichac97CloseIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource);
    420 static void ichac97CloseOut(PAC97STATE pThis);
     419static void ichac97DestroyIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource);
     420static void ichac97DestroyOut(PAC97STATE pThis);
    421421DECLINLINE(PAC97STREAM) ichac97GetStreamFromID(PAC97STATE pThis, uint32_t uID);
    422422static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8Strm);
     
    556556                               fActive ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE);
    557557
    558     LogFlowFunc(("u8Strm=%RU8, fActive=%RTbool, cStreamsActive=%RU8, rc=%Rrc\n",
     558    LogFlowFunc(("SD=%RU8, fActive=%RTbool, cStreamsActive=%RU8, rc=%Rrc\n",
    559559                 pStream->u8Strm, fActive, pThis->cStreamsActive, rc));
    560     if (rc == VERR_AUDIO_STREAM_PENDING_DISABLE)
    561     {
    562         LogFlowFunc(("On pending disable\n"));
    563         rc = VINF_SUCCESS;
    564     }
    565560
    566561    return rc;
     
    587582    pRegs->bd_valid = 0;
    588583
    589     int rc = ichac97StreamSetActive(pThis, pStream, false /* fActive */);
    590     AssertRC(rc);
     584    ichac97StreamSetActive(pThis, pStream, false /* fActive */);
    591585
    592586    RT_ZERO(pThis->silence);
     
    595589static void ichac97StreamDestroy(PAC97STREAM pStream)
    596590{
     591    LogFlowFunc(("SD=%RU8\n", pStream->u8Strm));
     592
    597593    if (pStream->State.au8FIFOW)
    598594    {
     
    610606    LogFlowFuncEnter();
    611607
    612     ichac97CloseIn(pThis, PDMAUDIORECSOURCE_LINE);
    613     ichac97CloseIn(pThis, PDMAUDIORECSOURCE_MIC);
    614     ichac97CloseOut(pThis);
     608    ichac97DestroyIn(pThis, PDMAUDIORECSOURCE_LINE);
     609    ichac97DestroyIn(pThis, PDMAUDIORECSOURCE_MIC);
     610    ichac97DestroyOut(pThis);
    615611
    616612    ichac97StreamDestroy(&pThis->StreamLineIn);
     
    657653}
    658654
    659 static void ichac97CloseIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource)
     655static void ichac97DestroyIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource)
    660656{
    661657    AssertPtrReturnVoid(pThis);
     
    680676    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    681677    {
    682         PAC97INPUTSTREAM pStrmIn;
     678        PAC97INPUTSTREAM pStream;
    683679        if (enmRecSource == PDMAUDIORECSOURCE_MIC) /** @todo Refine this once we have more streams. */
    684             pStrmIn = &pDrv->MicIn;
     680            pStream = &pDrv->MicIn;
    685681        else
    686             pStrmIn = &pDrv->LineIn;
    687 
    688         AudioMixerSinkRemoveStream(pSink, pStrmIn->pMixStrm);
    689         AudioMixerStreamDestroy(pStrmIn->pMixStrm);
    690         pStrmIn->pMixStrm = NULL;
    691     }
    692 }
    693 
    694 static void ichac97CloseOut(PAC97STATE pThis)
     682            pStream = &pDrv->LineIn;
     683
     684        if (pStream->pMixStrm)
     685        {
     686            AudioMixerSinkRemoveStream(pSink, pStream->pMixStrm);
     687            AudioMixerStreamDestroy(pStream->pMixStrm);
     688        }
     689        pStream->pMixStrm = NULL;
     690    }
     691}
     692
     693static void ichac97DestroyOut(PAC97STATE pThis)
    695694{
    696695    AssertPtrReturnVoid(pThis);
     
    701700    RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    702701    {
    703         AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
    704         AudioMixerStreamDestroy(pDrv->Out.pMixStrm);
    705         pDrv->Out.pMixStrm = NULL;
    706     }
    707 }
    708 
    709 static int ichac97OpenIn(PAC97STATE pThis,
    710                          const char *pszName, PDMAUDIORECSOURCE enmRecSource, PPDMAUDIOSTREAMCFG pCfg)
     702        if (pDrv->Out.pMixStrm)
     703        {
     704            AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
     705            AudioMixerStreamDestroy(pDrv->Out.pMixStrm);
     706
     707            pDrv->Out.pMixStrm = NULL;
     708        }
     709    }
     710}
     711
     712static int ichac97CreateIn(PAC97STATE pThis,
     713                           const char *pszName, PDMAUDIORECSOURCE enmRecSource, PPDMAUDIOSTREAMCFG pCfg)
    711714{
    712715    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     
    746749        }
    747750
    748         PAC97INPUTSTREAM pStrmIn;
     751        PAC97INPUTSTREAM pStream;
    749752        if (enmRecSource == PDMAUDIORECSOURCE_MIC) /** @todo Refine this once we have more streams. */
    750             pStrmIn = &pDrv->MicIn;
     753            pStream = &pDrv->MicIn;
    751754        else
    752             pStrmIn = &pDrv->LineIn;
    753 
    754         AudioMixerSinkRemoveStream(pSink, pStrmIn->pMixStrm);
    755 
    756         AudioMixerStreamDestroy(pStrmIn->pMixStrm);
    757         pStrmIn->pMixStrm = NULL;
    758 
    759         int rc2 = AudioMixerCreateStream(pThis->pMixer, pDrv->pConnector, pCfg, 0 /* fFlags */ , &pStrmIn->pMixStrm);
     755            pStream = &pDrv->LineIn;
     756
     757        AudioMixerSinkRemoveStream(pSink, pStream->pMixStrm);
     758
     759        AudioMixerStreamDestroy(pStream->pMixStrm);
     760        pStream->pMixStrm = NULL;
     761
     762        int rc2 = AudioMixerCreateStream(pThis->pMixer, pDrv->pConnector, pCfg, 0 /* fFlags */ , &pStream->pMixStrm);
    760763        if (RT_SUCCESS(rc2))
    761764        {
    762             rc2 = AudioMixerSinkAddStream(pSink, pStrmIn->pMixStrm);
     765            rc2 = AudioMixerSinkAddStream(pSink, pStream->pMixStrm);
    763766            LogFlowFunc(("LUN#%RU8: Created input \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2));
    764767        }
     
    772775}
    773776
    774 static int ichac97OpenOut(PAC97STATE pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg)
     777static int ichac97CreateOut(PAC97STATE pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg)
    775778{
    776779    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     
    833836    {
    834837        case PI_INDEX:
    835             rc = ichac97OpenIn(pThis, "ac97.pi", PDMAUDIORECSOURCE_LINE, pCfg);
     838            rc = ichac97CreateIn(pThis, "ac97.pi", PDMAUDIORECSOURCE_LINE, pCfg);
    836839            break;
    837840
    838841        case MC_INDEX:
    839             rc = ichac97OpenIn(pThis, "ac97.mc", PDMAUDIORECSOURCE_MIC, pCfg);
     842            rc = ichac97CreateIn(pThis, "ac97.mc", PDMAUDIORECSOURCE_MIC, pCfg);
    840843            break;
    841844
    842845        case PO_INDEX:
    843             rc = ichac97OpenOut(pThis, "ac97.po", pCfg);
     846            rc = ichac97CreateOut(pThis, "ac97.po", pCfg);
    844847            break;
    845848
     
    914917    }
    915918
    916     LogFlowFunc(("Index=%RU8, rc=%Rrc\n", u8Strm, rc));
     919    LogFlowFunc(("SD=%RU8, rc=%Rrc\n", u8Strm, rc));
    917920    return rc;
    918921}
     
    928931    AssertPtrReturnVoid(pStrm);
    929932
     933    LogFlowFunc(("SD=%RU8\n", pStrm->u8Strm));
     934
    930935    if (pStrm->State.au8FIFOW)
    931936    {
     
    935940
    936941    pStrm->State.offFIFOW = 0;
    937 
    938     LogFlowFunc(("uStrm=%RU8\n", pStrm->u8Strm));
    939942}
    940943
     
    12481251        RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node)
    12491252        {
    1250             if (pDrv->pConnector->pfnIsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut))
     1253            if (pDrv->pConnector->pfnStreamGetStatus(pDrv->pConnector, pDrv->Out.pStream) == PDMAUDIOSTRMSTS_FLAG_ENABLED)
    12511254            {
    1252                 rc2 = pDrv->pConnector->pfnWrite(pDrv->pConnector, pDrv->Out.pStrmOut,
    1253                                                  pThis->silence, cbToWrite, &cbWrittenToStream);
     1255                rc2 = pDrv->pConnector->pfnStreamWrite(pDrv->pConnector, pDrv->Out.pStream,
     1256                                                       pThis->silence, cbToWrite, &cbWrittenToStream);
    12541257                if (RT_SUCCESS(rc2))
    12551258                {
     
    13681371    uint64_t cTicksNow     = TMTimerGet(pTimer);
    13691372    uint64_t cTicksElapsed = cTicksNow  - pThis->uTimerTS;
     1373    uint64_t cTicksPerSec  = TMTimerGetFreq(pTimer);
    13701374
    13711375    /* Update current time timestamp. */
     
    13731377
    13741378    uint32_t cbLineIn;
    1375     AudioMixerSinkTimerUpdate(pThis->pSinkLineIn, pThis->cTimerTicks, cTicksElapsed, &cbLineIn);
     1379    AudioMixerSinkTimerUpdate(pThis->pSinkLineIn, pThis->cTimerTicks, cTicksPerSec, &cbLineIn);
    13761380    if (cbLineIn)
    13771381        ichac97TransferAudio(pThis, &pThis->StreamLineIn, cbLineIn);
    13781382
    13791383    uint32_t cbMicIn;
    1380     AudioMixerSinkTimerUpdate(pThis->pSinkMicIn , pThis->cTimerTicks, cTicksElapsed, &cbMicIn);
     1384    AudioMixerSinkTimerUpdate(pThis->pSinkMicIn , pThis->cTimerTicks, cTicksPerSec, &cbMicIn);
    13811385    if (cbMicIn)
    13821386        ichac97TransferAudio(pThis, &pThis->StreamMicIn, cbMicIn);
    13831387
    13841388    uint32_t cbOut;
    1385     AudioMixerSinkTimerUpdate(pThis->pSinkOutput, pThis->cTimerTicks, cTicksElapsed, &cbOut);
     1389    AudioMixerSinkTimerUpdate(pThis->pSinkOutput, pThis->cTimerTicks, cTicksPerSec, &cbOut);
    13861390    if (cbOut)
    13871391        ichac97TransferAudio(pThis, &pThis->StreamOut, cbOut);
     
    21052109        PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
    21062110        AssertPtr(pCon);
    2107         active[PI_INDEX] = pCon->pfnIsActiveIn (pCon, pDrv->LineIn.pStrmIn) ? 1 : 0;
    2108         active[PO_INDEX] = pCon->pfnIsActiveOut(pCon, pDrv->Out.pStrmOut)  ? 1 : 0;
    2109         active[MC_INDEX] = pCon->pfnIsActiveIn (pCon, pDrv->MicIn.pStrmIn) ? 1 : 0;
     2111        active[PI_INDEX] = (pCon->pfnStreamGetStatus(pCon, pDrv->LineIn.pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED) ? 1 : 0;
     2112        active[PO_INDEX] = (pCon->pfnStreamGetStatus(pCon, pDrv->Out.pStream)   & PDMAUDIOSTRMSTS_FLAG_ENABLED) ? 1 : 0;
     2113        active[MC_INDEX] = (pCon->pfnStreamGetStatus(pCon, pDrv->MicIn.pStream)  & PDMAUDIOSTRMSTS_FLAG_ENABLED) ? 1 : 0;
    21102114    }
    21112115
     
    22812285    LogFlowFuncEnter();
    22822286
    2283     PAC97DRIVER pDrv;
    2284     while (!RTListIsEmpty(&pThis->lstDrv))
    2285     {
    2286         pDrv = RTListGetFirst(&pThis->lstDrv, AC97DRIVER, Node);
    2287 
     2287    ichac97StreamDestroy(&pThis->StreamLineIn);
     2288    ichac97StreamDestroy(&pThis->StreamMicIn);
     2289    ichac97StreamDestroy(&pThis->StreamOut);
     2290
     2291    PAC97DRIVER pDrv, pDrvNext;
     2292    RTListForEachSafe(&pThis->lstDrv, pDrv, pDrvNext, AC97DRIVER, Node)
     2293    {
    22882294        RTListNodeRemove(&pDrv->Node);
    22892295        RTMemFree(pDrv);
    22902296    }
    22912297
    2292     ichac97StreamsDestroy(pThis);
     2298    /* Sanity. */
     2299    Assert(RTListIsEmpty(&pThis->lstDrv));
    22932300
    22942301    LogFlowFuncLeave();
  • trunk/src/VBox/Devices/Audio/DevIchHda.cpp

    r61126 r61157  
    41454145        {
    41464146            uint32_t cSamplesPlayed;
    4147             int rc2 = pDrv->pConnector->pfnPlayOut(pDrv->pConnector, &cSamplesPlayed);
     4147            int rc2 = pDrv->pConnector->pfnPlay(pDrv->pConnector, &cSamplesPlayed);
    41484148            LogFlowFunc(("LUN#%RU8: cSamplesPlayed=%RU32, rc=%Rrc\n", pDrv->uLUN, cSamplesPlayed, rc2));
    41494149        }
     
    52165216{
    52175217    PHDASTATE   pThis         = PDMINS_2_DATA(pDevIns, PHDASTATE);
    5218     int         iHdaStrmIndex = hdaDbgLookupStrmIdx(pThis, pszArgs);
    5219     if (iHdaStrmIndex != -1)
    5220         hdaDbgPrintStream(pThis, pHlp, iHdaStrmIndex);
     5218    int         iHdaStreamdex = hdaDbgLookupStrmIdx(pThis, pszArgs);
     5219    if (iHdaStreamdex != -1)
     5220        hdaDbgPrintStream(pThis, pHlp, iHdaStreamdex);
    52215221    else
    5222         for(iHdaStrmIndex = 0; iHdaStrmIndex < HDA_MAX_STREAMS; ++iHdaStrmIndex)
    5223             hdaDbgPrintStream(pThis, pHlp, iHdaStrmIndex);
     5222        for(iHdaStreamdex = 0; iHdaStreamdex < HDA_MAX_STREAMS; ++iHdaStreamdex)
     5223            hdaDbgPrintStream(pThis, pHlp, iHdaStreamdex);
    52245224}
    52255225
     
    52305230{
    52315231    PHDASTATE   pThis         = PDMINS_2_DATA(pDevIns, PHDASTATE);
    5232     int         iHdaStrmIndex = hdaDbgLookupStrmIdx(pThis, pszArgs);
    5233     if (iHdaStrmIndex != -1)
    5234         hdaDbgPrintBDLE(pThis, pHlp, iHdaStrmIndex);
     5232    int         iHdaStreamdex = hdaDbgLookupStrmIdx(pThis, pszArgs);
     5233    if (iHdaStreamdex != -1)
     5234        hdaDbgPrintBDLE(pThis, pHlp, iHdaStreamdex);
    52355235    else
    5236         for(iHdaStrmIndex = 0; iHdaStrmIndex < HDA_MAX_STREAMS; ++iHdaStrmIndex)
    5237             hdaDbgPrintBDLE(pThis, pHlp, iHdaStrmIndex);
     5236        for(iHdaStreamdex = 0; iHdaStreamdex < HDA_MAX_STREAMS; ++iHdaStreamdex)
     5237            hdaDbgPrintBDLE(pThis, pHlp, iHdaStreamdex);
    52385238}
    52395239
     
    56505650#ifndef VBOX_WITH_AUDIO_CALLBACKS
    56515651    uint16_t uTimerHz;
    5652     rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 200 /* Hz */);
     5652    rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 100 /* Hz */);
    56535653    if (RT_FAILURE(rc))
    56545654        return PDMDEV_SET_ERROR(pDevIns, rc,
  • trunk/src/VBox/Devices/Audio/DevSB16.cpp

    r61050 r61157  
    7777{
    7878    /** PCM output stream. */
    79     R3PTRTYPE(PPDMAUDIOGSTSTRMOUT)     pStrmOut;
     79    R3PTRTYPE(PPDMAUDIOSTREAM)         pStream;
    8080    /** Mixer handle for output stream. */
    8181    R3PTRTYPE(PAUDMIXSTREAM)           pMixStrm;
     
    16851685    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    16861686    {
    1687         int rc2 = pDrv->pConnector->pfnGetDataOut(pDrv->pConnector, &cbOut, NULL /* pcSamplesLive */);
     1687        int rc2 = pDrv->pConnector->pfnStreamGetData(pDrv->pConnector, pDrv->Out.pStream, &cbOut);
    16881688        if (RT_SUCCESS(rc2))
    16891689            cbOutMin = RT_MIN(cbOutMin, cbOut);
     
    19201920    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    19211921    {
    1922         if (pDrv->Out.pStrmOut)
     1922        if (pDrv->Out.pStream)
    19231923        {
    1924             pDrv->pConnector->pfnCloseOut(pThis->pDrv, pDrv->Out.pStrmOut);
    1925             pDrv->Out.pStrmOut = NULL;
     1924            pDrv->pConnector->pfnCloseOut(pThis->pDrv, pDrv->Out.pStream);
     1925            pDrv->Out.pStream = NULL;
    19261926        }
    19271927    }
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r61050 r61157  
    6565#include "AudioMixBuffer.h"
    6666
    67 static int drvAudioAllocHstIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMIN *ppHstStrmIn);
    68 static int drvAudioAllocHstOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut);
    69 static int drvAudioCreateStreamPairIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn);
    70 static int drvAudioDestroyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn);
    71 static int drvAudioDestroyGstIn(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMIN pGstStrmIn);
    72 static int drvAudioDestroyGstOut(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMOUT pGstStrmOut);
    73 static PPDMAUDIOHSTSTRMIN drvAudioFindAnyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn);
    74 static PPDMAUDIOHSTSTRMOUT drvAudioFindAnyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut);
    75 static PPDMAUDIOHSTSTRMOUT drvAudioFindSpecificOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg);
    76 
    77 static int drvAudioGstInInit(PPDMAUDIOGSTSTRMIN pGstStrmIn, PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg);
    78 
    79 static void drvAudioHstInFreeRes(PPDMAUDIOHSTSTRMIN pHstStrmIn);
    80 static void drvAudioHstOutFreeRes(PPDMAUDIOHSTSTRMOUT pHstStrmOut);
    81 
    82 
    83 int drvAudioAddHstOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut)
    84 {
    85     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    86     AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
    87 
    88     int rc;
    89 
    90     PPDMAUDIOHSTSTRMOUT pHstStrmOut = drvAudioFindSpecificOut(pThis, NULL, pCfg);
    91     if (!pHstStrmOut)
    92     {
    93         rc = drvAudioAllocHstOut(pThis, pCfg, &pHstStrmOut);
    94         if (RT_FAILURE(rc))
    95             pHstStrmOut = drvAudioFindAnyHstOut(pThis, NULL /* pHstStrmOut */);
    96     }
    97 
    98     rc = pHstStrmOut ? VINF_SUCCESS : rc;
    99 
    100     if (RT_SUCCESS(rc))
    101         *ppHstStrmOut = pHstStrmOut;
    102 
    103     return rc;
    104 }
     67static DECLCALLBACK(int) drvAudioStreamDestroy(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream);
     68static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd);
     69static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream);
     70static int drvAudioStreamDestroyInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
    10571
    10672#ifndef VBOX_AUDIO_TESTCASE
     
    178144    *pfDefault = false;
    179145    return pszValue;
     146}
     147
     148inline PPDMAUDIOSTREAM drvAudioGetHostStream(PPDMAUDIOSTREAM pStream)
     149{
     150    AssertPtrReturn(pStream, NULL);
     151
     152    PPDMAUDIOSTREAM pStreamHst = pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST
     153                               ? pStream
     154                               : pStream->pPair;
     155    AssertPtr(pStreamHst);
     156    return pStreamHst;
    180157}
    181158
     
    273250#endif /* !VBOX_AUDIO_TESTCASE */
    274251
    275 static bool drvAudioStreamCfgIsValid(PPDMAUDIOSTREAMCFG pCfg)
    276 {
    277     bool fValid = (   pCfg->cChannels == 1
    278                    || pCfg->cChannels == 2); /* Either stereo (2) or mono (1), per stream. */
    279 
    280     fValid |= (   pCfg->enmEndianness == PDMAUDIOENDIANNESS_LITTLE
    281                || pCfg->enmEndianness == PDMAUDIOENDIANNESS_BIG);
    282 
    283     if (fValid)
    284     {
    285         switch (pCfg->enmFormat)
    286         {
    287             case PDMAUDIOFMT_S8:
    288             case PDMAUDIOFMT_U8:
    289             case PDMAUDIOFMT_S16:
    290             case PDMAUDIOFMT_U16:
    291             case PDMAUDIOFMT_S32:
    292             case PDMAUDIOFMT_U32:
    293                 break;
    294             default:
    295                 fValid = false;
    296                 break;
    297         }
    298     }
    299 
    300     /** @todo Check for defined frequencies supported. */
    301     fValid |= pCfg->uHz > 0;
    302 
    303     return fValid;
    304 }
    305 
    306 static int drvAudioControlHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn, PDMAUDIOSTREAMCMD enmStreamCmd)
    307 {
    308     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    309     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    310 
    311     int rc = RTCritSectEnter(&pHstStrmIn->CritSect);
     252static DECLCALLBACK(int) drvAudioStreamControl(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
     253{
     254    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     255
     256    return drvAudioStreamControlInternal(pThis, pStream, enmStreamCmd);
     257}
     258
     259static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
     260{
     261    AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
     262    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     263
     264    int rc = RTCritSectEnter(&pThis->CritSect);
    312265    if (RT_FAILURE(rc))
    313266        return rc;
    314267
    315     LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
     268    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     269
     270    LogFlowFunc(("%s: enmStreamCmd=%ld\n", pHstStream->szName, enmStreamCmd));
    316271
    317272    switch (enmStreamCmd)
     
    319274        case PDMAUDIOSTREAMCMD_ENABLE:
    320275        {
    321             if (!(pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
    322             {
    323                 rc = pThis->pHostDrvAudio->pfnControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_ENABLE);
     276            if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
     277            {
     278                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_ENABLE);
    324279                if (RT_SUCCESS(rc))
    325                     pHstStrmIn->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED;
     280                {
     281                    Assert(!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE));
     282                    pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED;
     283                }
    326284            }
    327285            else
     
    333291        case PDMAUDIOSTREAMCMD_DISABLE:
    334292        {
    335             if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)
    336             {
    337                 rc = pThis->pHostDrvAudio->pfnControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_DISABLE);
     293            if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)
     294            {
     295                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
    338296                if (RT_SUCCESS(rc))
    339297                {
    340                     pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED;
    341                     AudioMixBufClear(&pHstStrmIn->MixBuf);
     298                    pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED;
     299                    AudioMixBufClear(&pHstStream->MixBuf);
    342300                }
    343301            }
     
    350308        case PDMAUDIOSTREAMCMD_PAUSE:
    351309        {
    352             if (!(pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED))
    353             {
    354                 rc = pThis->pHostDrvAudio->pfnControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_PAUSE);
     310            if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED))
     311            {
     312                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_PAUSE);
    355313                if (RT_SUCCESS(rc))
    356                     pHstStrmIn->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED;
     314                    pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED;
    357315            }
    358316            else
     
    364322        case PDMAUDIOSTREAMCMD_RESUME:
    365323        {
    366             if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)
    367             {
    368                 rc = pThis->pHostDrvAudio->pfnControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_RESUME);
     324            if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)
     325            {
     326                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_RESUME);
    369327                if (RT_SUCCESS(rc))
    370                     pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED;
     328                    pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED;
    371329            }
    372330            else
     
    382340    }
    383341
    384     LogFunc(("[%s] Returned %Rrc\n", pHstStrmIn->MixBuf.pszName, rc));
    385 
    386     int rc2 = RTCritSectLeave(&pHstStrmIn->CritSect);
     342    if (RT_FAILURE(rc))
     343        LogFunc(("%s: Failed with %Rrc\n", pHstStream->szName, rc));
     344
     345    int rc2 = RTCritSectLeave(&pThis->CritSect);
    387346    if (RT_SUCCESS(rc))
    388347        rc = rc2;
     
    391350}
    392351
    393 static int drvAudioControlHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd)
    394 {
    395     AssertPtrReturn(pThis,       VERR_INVALID_POINTER);
    396     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    397 
    398     int rc = RTCritSectEnter(&pHstStrmOut->CritSect);
    399     if (RT_FAILURE(rc))
    400         return rc;
    401 
    402     LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
    403 
    404     switch (enmStreamCmd)
    405     {
    406         case PDMAUDIOSTREAMCMD_ENABLE:
    407         {
    408             if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
    409             {
    410                 rc = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_ENABLE);
    411                 if (RT_SUCCESS(rc))
    412                 {
    413                     Assert(!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE));
    414                     pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED;
    415                 }
    416             }
    417             else
    418                 rc = VINF_SUCCESS;
    419 
    420             break;
    421         }
    422 
    423         case PDMAUDIOSTREAMCMD_DISABLE:
    424         {
    425             if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)
    426             {
    427                 rc = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE);
    428                 if (RT_SUCCESS(rc))
    429                 {
    430                     pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED;
    431                     AudioMixBufClear(&pHstStrmOut->MixBuf);
    432                 }
    433             }
    434             else
    435                 rc = VINF_SUCCESS;
    436 
    437             break;
    438         }
    439 
    440         case PDMAUDIOSTREAMCMD_PAUSE:
    441         {
    442             if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED))
    443             {
    444                 rc = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_PAUSE);
    445                 if (RT_SUCCESS(rc))
    446                     pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED;
    447             }
    448             else
    449                 rc = VINF_SUCCESS;
    450 
    451             break;
    452         }
    453 
    454         case PDMAUDIOSTREAMCMD_RESUME:
    455         {
    456             if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)
    457             {
    458                 rc = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_RESUME);
    459                 if (RT_SUCCESS(rc))
    460                     pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED;
    461             }
    462             else
    463                 rc = VINF_SUCCESS;
    464 
    465             break;
    466         }
    467 
    468         default:
    469             AssertMsgFailed(("Command %ld not implemented\n", enmStreamCmd));
    470             rc = VERR_NOT_IMPLEMENTED;
    471             break;
    472     }
    473 
    474     LogFunc(("[%s] Returned %Rrc\n", pHstStrmOut->MixBuf.pszName, rc));
    475 
    476     int rc2 = RTCritSectLeave(&pHstStrmOut->CritSect);
    477     if (RT_SUCCESS(rc))
    478         rc = rc2;
    479 
    480     return rc;
    481 }
    482 
    483 static int drvAudioDestroyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
    484 {
    485     AssertPtrReturn(pThis,       VERR_INVALID_POINTER);
    486     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    487 
    488     LogFlowFunc(("%s\n", pHstStrmOut->MixBuf.pszName));
    489 
    490     int rc = VINF_SUCCESS;
    491 
    492     if (RTListIsEmpty(&pHstStrmOut->lstGstStrmOut))
    493     {
    494         drvAudioHstOutFreeRes(pHstStrmOut);
    495 
    496         /* Remove from driver instance list. */
    497         RTListNodeRemove(&pHstStrmOut->Node);
    498 
    499         if (RTCritSectIsInitialized(&pHstStrmOut->CritSect))
    500         {
    501             int rc2 = RTCritSectDelete(&pHstStrmOut->CritSect);
    502             AssertRC(rc2);
    503         }
    504 
    505         RTMemFree(pHstStrmOut);
    506         pHstStrmOut = NULL;
    507 
    508         pThis->cStreamsFreeOut++;
    509     }
    510     else
    511     {
    512         rc = VERR_WRONG_ORDER;
    513         LogFlowFunc(("[%s] Still is being used, skipping\n", pHstStrmOut->MixBuf.pszName));
    514     }
    515 
    516     LogFlowFuncLeaveRC(rc);
    517     return rc;
    518 }
    519 
    520 static int drvAudioDestroyGstOut(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMOUT pGstStrmOut)
    521 {
    522     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    523 
    524     if (!pGstStrmOut)
    525         return VINF_SUCCESS;
    526 
    527     LogFlowFunc(("%s\n", pGstStrmOut->MixBuf.pszName));
    528 
    529     if (pGstStrmOut->State.cRefs > 1) /* Do other objects still have a reference to it? Bail out. */
    530         return VERR_WRONG_ORDER;
    531 
    532     AudioMixBufDestroy(&pGstStrmOut->MixBuf);
    533 
    534     /* Is this guest stream associate to a host stream? */
    535     if (pGstStrmOut->pHstStrmOut)
    536     {
    537         /* Unregister from parent first. */
    538         RTListNodeRemove(&pGstStrmOut->Node);
    539     }
    540 
    541     RTMemFree(pGstStrmOut);
    542     pGstStrmOut = NULL;
    543 
    544     return VINF_SUCCESS;
    545 }
    546 
    547 static PPDMAUDIOHSTSTRMIN drvAudioFindAnyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn)
    548 {
    549     if (pHstStrmIn)
    550     {
    551         if (RTListNodeIsLast(&pThis->lstHstStrmIn, &pHstStrmIn->Node))
    552             return NULL;
    553 
    554         return RTListNodeGetNext(&pHstStrmIn->Node, PDMAUDIOHSTSTRMIN, Node);
    555     }
    556 
    557     return RTListGetFirst(&pThis->lstHstStrmIn, PDMAUDIOHSTSTRMIN, Node);
    558 }
    559 
    560 static int drvAudioHstInAdd(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMIN *ppHstStrmIn)
    561 {
    562     AssertPtrReturn(pThis,       VERR_INVALID_POINTER);
    563     AssertPtrReturn(pCfg,        VERR_INVALID_POINTER);
    564     AssertPtrReturn(ppHstStrmIn, VERR_INVALID_POINTER);
    565 
    566     PPDMAUDIOHSTSTRMIN pHstStrmIn;
    567     int rc = drvAudioAllocHstIn(pThis, pCfg, &pHstStrmIn);
    568     if (RT_SUCCESS(rc))
    569         *ppHstStrmIn = pHstStrmIn;
    570 
    571     LogFlowFuncLeaveRC(rc);
    572     return rc;
    573 }
    574 
    575 static void drvAudioHstInFreeRes(PPDMAUDIOHSTSTRMIN pHstStrmIn)
    576 {
    577     if (!pHstStrmIn)
    578         return;
    579 
    580     AudioMixBufDestroy(&pHstStrmIn->MixBuf);
    581 }
    582 
    583 static int drvAudioGstOutInit(PPDMAUDIOGSTSTRMOUT pGstStrmOut, PPDMAUDIOHSTSTRMOUT pHostStrmOut, PPDMAUDIOSTREAMCFG pCfg)
    584 {
    585     AssertPtrReturn(pGstStrmOut,  VERR_INVALID_POINTER);
    586     AssertPtrReturn(pHostStrmOut, VERR_INVALID_POINTER);
    587     AssertPtrReturn(pCfg,         VERR_INVALID_POINTER);
    588 
    589     int rc = DrvAudioStreamCfgToProps(pCfg, &pGstStrmOut->Props);
    590     if (RT_SUCCESS(rc))
    591     {
    592         char *pszName;
    593         if (RTStrAPrintf(&pszName, "%s (Guest)", pCfg->szName) <= 0)
    594             return VERR_NO_MEMORY;
    595 
    596         rc = AudioMixBufInit(&pGstStrmOut->MixBuf, pszName, &pGstStrmOut->Props, AudioMixBufSize(&pHostStrmOut->MixBuf));
    597         if (RT_SUCCESS(rc))
    598             rc = AudioMixBufLinkTo(&pGstStrmOut->MixBuf, &pHostStrmOut->MixBuf);
    599 
    600         if (RT_SUCCESS(rc))
    601         {
    602             pGstStrmOut->State.cRefs   = 1;
    603             pGstStrmOut->State.fActive = false;
    604             pGstStrmOut->State.fEmpty  = true;
    605 
    606             RTStrPrintf(pGstStrmOut->State.szName, RT_ELEMENTS(pGstStrmOut->State.szName),
    607                         "%s", pszName);
    608 
    609             pGstStrmOut->pHstStrmOut = pHostStrmOut;
    610         }
    611 
    612         RTStrFree(pszName);
    613     }
    614 
    615     LogFlowFunc(("pszName=%s, rc=%Rrc\n", pCfg->szName, rc));
    616     return rc;
    617 }
    618 
    619 static int drvAudioAllocHstOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut)
    620 {
    621     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    622     AssertPtrReturn(pCfg,  VERR_INVALID_POINTER);
    623 
    624     if (!pThis->cStreamsFreeOut)
    625     {
    626         LogFlowFunc(("Maximum number of host output streams reached\n"));
    627         return VERR_NO_MORE_HANDLES;
    628     }
    629 
    630     /* Validate backend configuration. */
    631     if (!pThis->BackendCfg.cbStreamOut)
    632     {
    633         LogFlowFunc(("Backend output configuration not valid, bailing out\n"));
    634         return VERR_INVALID_PARAMETER;
    635     }
    636 
    637     PPDMAUDIOHSTSTRMOUT pHstStrmOut = (PPDMAUDIOHSTSTRMOUT)RTMemAllocZ(pThis->BackendCfg.cbStreamOut);
    638     if (!pHstStrmOut)
    639     {
    640         LogFlowFunc(("Error allocating host output stream with %zu bytes\n",
    641                      pThis->BackendCfg.cbStreamOut));
    642         return VERR_NO_MEMORY;
    643     }
    644 
    645     int rc;
    646 
    647     do
    648     {
    649         RTListInit(&pHstStrmOut->lstGstStrmOut);
    650 
    651         uint32_t cSamples = 0;
    652         rc = pThis->pHostDrvAudio->pfnInitOut
    653            ? pThis->pHostDrvAudio->pfnInitOut(pThis->pHostDrvAudio, pHstStrmOut, pCfg, &cSamples) : VINF_SUCCESS;
    654 
    655         if (RT_FAILURE(rc))
    656         {
    657             LogFlowFunc(("Initializing host backend failed with rc=%Rrc\n", rc));
    658             break;
    659         }
    660 
    661         pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
    662 
    663         char *pszName;
    664         if (RTStrAPrintf(&pszName, "%s (Host)", pCfg->szName) <= 0)
    665         {
    666             rc = VERR_NO_MEMORY;
    667             break;
    668         }
    669 
    670         rc = AudioMixBufInit(&pHstStrmOut->MixBuf, pszName, &pHstStrmOut->Props, cSamples);
    671         if (RT_SUCCESS(rc))
    672             rc = RTCritSectInit(&pHstStrmOut->CritSect);
    673 
    674         if (RT_SUCCESS(rc))
    675         {
    676             RTListPrepend(&pThis->lstHstStrmOut, &pHstStrmOut->Node);
    677             pThis->cStreamsFreeOut--;
    678         }
    679 
    680         RTStrFree(pszName);
    681 
    682     } while (0);
    683 
    684     if (RT_FAILURE(rc))
    685     {
    686         if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
    687         {
    688             int rc2 = pThis->pHostDrvAudio->pfnFiniOut
    689                     ? pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut) : VINF_SUCCESS;
    690             if (RT_SUCCESS(rc2))
    691                 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
    692         }
    693 
    694         drvAudioHstOutFreeRes(pHstStrmOut);
    695         RTMemFree(pHstStrmOut);
    696     }
    697     else
    698         *ppHstStrmOut = pHstStrmOut;
    699 
    700     LogFlowFuncLeaveRC(rc);
    701     return rc;
    702 }
    703 
    704 static int drvAudioCreateStreamPairOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut)
    705 {
    706     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    707     AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
    708 
    709     PPDMAUDIOGSTSTRMOUT pGstStrmOut =
    710         (PPDMAUDIOGSTSTRMOUT)RTMemAllocZ(sizeof(PDMAUDIOGSTSTRMOUT));
    711     if (!pGstStrmOut)
    712     {
    713         LogFlowFunc(("Failed to allocate memory for guest output stream \"%s\"\n", pCfg->szName));
    714         return VERR_NO_MEMORY;
    715     }
    716 
    717     /*
    718      * The host stream always will get the backend audio stream configuration.
    719      */
    720     PPDMAUDIOHSTSTRMOUT pHstStrmOut;
    721     int rc = drvAudioAddHstOut(pThis, pCfg, &pHstStrmOut);
    722     if (RT_FAILURE(rc))
    723     {
    724         LogFlowFunc(("Error adding host output stream \"%s\", rc=%Rrc\n", pCfg->szName, rc));
    725 
    726         RTMemFree(pGstStrmOut);
    727         return rc;
    728     }
    729 
    730     /*
    731      * The guest stream always will get the audio stream configuration told
    732      * by the device emulation (which in turn was/could be set by the guest OS).
    733      */
    734     rc = drvAudioGstOutInit(pGstStrmOut, pHstStrmOut, pCfg);
    735     if (RT_SUCCESS(rc))
    736     {
    737         RTListPrepend(&pHstStrmOut->lstGstStrmOut, &pGstStrmOut->Node);
    738 
    739         if (ppGstStrmOut)
    740             *ppGstStrmOut = pGstStrmOut;
    741     }
    742 
    743     if (RT_FAILURE(rc))
    744         drvAudioDestroyGstOut(pThis, pGstStrmOut);
    745 
    746     LogFlowFuncLeaveRC(rc);
    747     return rc;
    748 }
    749 
    750 static int drvAudioCreateStreamPairIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn)
    751 {
    752     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    753     AssertPtrReturn(pCfg,    VERR_INVALID_POINTER);
    754 
    755     PPDMAUDIOGSTSTRMIN pGstStrmIn = (PPDMAUDIOGSTSTRMIN)RTMemAllocZ(sizeof(PDMAUDIOGSTSTRMIN));
    756     if (!pGstStrmIn)
    757         return VERR_NO_MEMORY;
    758 
    759     /*
    760      * The host stream always will get the backend audio stream configuration.
    761      */
    762     PPDMAUDIOHSTSTRMIN pHstStrmIn;
    763     int rc = drvAudioHstInAdd(pThis, pCfg, &pHstStrmIn);
    764     if (RT_FAILURE(rc))
    765     {
    766         LogFunc(("Failed to add host audio input stream \"%s\", rc=%Rrc\n", pCfg->szName, rc));
    767 
    768         RTMemFree(pGstStrmIn);
    769         return rc;
    770     }
    771 
    772     /*
    773      * The guest stream always will get the audio stream configuration told
    774      * by the device emulation (which in turn was/could be set by the guest OS).
    775      */
    776     rc = drvAudioGstInInit(pGstStrmIn, pHstStrmIn, pCfg);
    777     if (RT_SUCCESS(rc))
    778     {
    779         pHstStrmIn->pGstStrmIn = pGstStrmIn;
    780 
    781         if (ppGstStrmIn)
    782             *ppGstStrmIn = pGstStrmIn;
    783     }
    784     else
    785         drvAudioDestroyGstIn(pThis, pGstStrmIn);
    786 
    787     LogFlowFuncLeaveRC(rc);
    788     return rc;
    789 }
    790 
    791 /**
    792  * Initializes a guest input stream.
    793  *
    794  * @return  IPRT status code.
    795  * @param   pGstStrmIn          Pointer to guest stream to initialize.
    796  * @param   pHstStrmIn          Pointer to host input stream to associate this guest
    797  *                              stream with.
    798  * @param   pCfg                Pointer to stream configuration to use.
    799  */
    800 static int drvAudioGstInInit(PPDMAUDIOGSTSTRMIN pGstStrmIn, PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg)
    801 {
    802     AssertPtrReturn(pGstStrmIn, VERR_INVALID_POINTER);
    803     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    804     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    805 
    806     int rc = DrvAudioStreamCfgToProps(pCfg, &pGstStrmIn->Props);
    807     if (RT_SUCCESS(rc))
    808     {
    809         char *pszName;
    810         if (RTStrAPrintf(&pszName, "%s (Guest)",
    811                          strlen(pCfg->szName) ? pCfg->szName : "<Untitled>") <= 0)
    812         {
    813             return VERR_NO_MEMORY;
    814         }
    815 
    816         rc = AudioMixBufInit(&pGstStrmIn->MixBuf, pszName, &pGstStrmIn->Props, AudioMixBufSize(&pHstStrmIn->MixBuf));
    817         if (RT_SUCCESS(rc))
    818             rc = AudioMixBufLinkTo(&pHstStrmIn->MixBuf, &pGstStrmIn->MixBuf);
    819 
    820         if (RT_SUCCESS(rc))
    821         {
    822 #ifdef DEBUG
    823             DrvAudioStreamCfgPrint(pCfg);
    824 #endif
    825             pGstStrmIn->State.cRefs   = 1;
    826             pGstStrmIn->State.fActive = false;
    827             pGstStrmIn->State.fEmpty  = true;
    828 
    829             RTStrPrintf(pGstStrmIn->State.szName, RT_ELEMENTS(pGstStrmIn->State.szName),
    830                         "%s", pszName);
    831 
    832             pGstStrmIn->pHstStrmIn = pHstStrmIn;
    833         }
    834 
    835         RTStrFree(pszName);
    836     }
    837 
    838     LogFlowFunc(("pszName=%s, rc=%Rrc\n", pCfg->szName, rc));
    839     return rc;
    840 }
    841 
    842 static int drvAudioAllocHstIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMIN *ppHstStrmIn)
    843 {
    844     if (!pThis->cStreamsFreeIn)
    845     {
    846         LogFlowFunc(("No more input streams free to use, bailing out\n"));
    847         return VERR_AUDIO_NO_FREE_INPUT_STREAMS;
    848     }
    849 
    850     /* Validate backend configuration. */
    851     if (!pThis->BackendCfg.cbStreamIn)
    852     {
    853         LogFlowFunc(("Backend input configuration not valid, bailing out\n"));
    854         return VERR_INVALID_PARAMETER;
    855     }
    856 
    857     PPDMAUDIOHSTSTRMIN pHstStrmIn =
    858         (PPDMAUDIOHSTSTRMIN)RTMemAllocZ(pThis->BackendCfg.cbStreamIn);
    859     if (!pHstStrmIn)
    860     {
    861         LogFlowFunc(("Error allocating host innput stream with %RU32 bytes\n",
    862                      pThis->BackendCfg.cbStreamOut));
    863         return VERR_NO_MEMORY;
    864     }
    865 
    866     int rc;
    867 
    868     do /* goto avoidance */
    869     {
    870         uint32_t cSamples = 0;
    871         rc = pThis->pHostDrvAudio->pfnInitIn
    872            ? pThis->pHostDrvAudio->pfnInitIn(pThis->pHostDrvAudio, pHstStrmIn,
    873                                              pCfg, pCfg->DestSource.Source, &cSamples)
    874            : VINF_SUCCESS;
    875         if (RT_FAILURE(rc))
    876         {
    877             LogFlowFunc(("Initializing host backend failed with rc=%Rrc\n", rc));
    878             break;
    879         }
    880 
    881         pHstStrmIn->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
    882 
    883         char *pszName;
    884         if (RTStrAPrintf(&pszName, "%s (Host)", pCfg->szName) <= 0)
    885         {
    886             rc = VERR_NO_MEMORY;
    887             break;
    888         }
    889 
    890         rc = AudioMixBufInit(&pHstStrmIn->MixBuf, pszName, &pHstStrmIn->Props, cSamples);
    891         if (RT_SUCCESS(rc))
    892             rc = RTCritSectInit(&pHstStrmIn->CritSect);
    893 
    894         if (RT_SUCCESS(rc))
    895         {
    896             RTListPrepend(&pThis->lstHstStrmIn, &pHstStrmIn->Node);
    897             pThis->cStreamsFreeIn--;
    898         }
    899 
    900         RTStrFree(pszName);
    901 
    902     } while (0);
    903 
    904     if (RT_FAILURE(rc))
    905     {
    906         if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
    907         {
    908             int rc2 = pThis->pHostDrvAudio->pfnFiniIn
    909                     ? pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio, pHstStrmIn) : VINF_SUCCESS;
    910             if (RT_SUCCESS(rc2))
    911                 pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
    912         }
    913 
    914         drvAudioHstInFreeRes(pHstStrmIn);
    915         RTMemFree(pHstStrmIn);
    916     }
    917     else
    918         *ppHstStrmIn = pHstStrmIn;
    919 
    920     LogFlowFuncLeaveRC(rc);
    921     return rc;
    922 }
    923 
     352#if 1
    924353/**
    925354 * Writes VM audio output data from the guest stream into the host stream.
     
    935364 * @param   pcbWritten
    936365 */
    937 static DECLCALLBACK(int) drvAudioWrite(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut,
    938                                        const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
    939 {
     366static DECLCALLBACK(int) drvAudioStreamWrite(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream,
     367                                             const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
     368{
     369    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     370    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     371    AssertPtrReturn(pvBuf,      VERR_INVALID_POINTER);
     372    /* pcbWritten is optional. */
     373
    940374    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
    941     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    942 
    943     AssertPtrReturn(pGstStrmOut, VERR_INVALID_POINTER);
    944     AssertPtrReturn(pvBuf,       VERR_INVALID_POINTER);
    945     AssertReturn(cbBuf,          VERR_INVALID_PARAMETER);
    946     /* pcbWritten is optional. */
     375
     376    if (!cbBuf)
     377    {
     378        if (pcbWritten)
     379            *pcbWritten = 0;
     380        return VINF_SUCCESS;
     381    }
    947382
    948383    int rc = RTCritSectEnter(&pThis->CritSect);
     
    950385        return rc;
    951386
    952     if (!pThis->pHostDrvAudio->pfnIsEnabled(pThis->pHostDrvAudio, PDMAUDIODIR_OUT))
     387    if (!pThis->pHostDrvAudio->pfnGetStatus(pThis->pHostDrvAudio, PDMAUDIODIR_OUT))
    953388    {
    954389        rc = RTCritSectLeave(&pThis->CritSect);
     
    958393    }
    959394
    960     PPDMAUDIOHSTSTRMOUT pHstStrmOut = pGstStrmOut->pHstStrmOut;
    961     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    962 
    963     AssertMsg(pGstStrmOut->pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED,
    964               ("Writing to disabled host output stream \"%s\" not possible\n",
    965               pHstStrmOut->MixBuf.pszName));
    966 
    967     if (!AudioMixBufFreeBytes(&pGstStrmOut->MixBuf))
     395    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     396    PPDMAUDIOSTREAM pGstStream = pHstStream->pPair;
     397
     398    AssertMsg(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED,
     399              ("Writing to disabled host output stream \"%s\" not possible\n", pHstStream->szName));
     400
     401    if (!AudioMixBufFreeBytes(&pHstStream->MixBuf))
    968402    {
    969403        if (pcbWritten)
     
    978412     */
    979413    uint32_t cWritten;
    980     rc = AudioMixBufWriteAt(&pGstStrmOut->MixBuf, 0 /* Offset in samples */, pvBuf, cbBuf, &cWritten);
    981 
     414    rc = AudioMixBufWriteCirc(&pGstStream->MixBuf, pvBuf, cbBuf, &cWritten);
     415    if (rc == VINF_BUFFER_OVERFLOW)
     416        LogRelMax(32, ("Audio: Lost audio samples from guest, expect stuttering audio output\n"));
     417
     418    /* Host stream currently has no samples to play? */
     419    if (AudioMixBufAvail(&pHstStream->MixBuf) == 0)
     420    {
     421        /* Mix just written guest stream samples to the host immediately. */
     422        uint32_t cMixed;
     423        rc = AudioMixBufMixToParent(&pGstStream->MixBuf, cWritten, &cMixed);
     424        LogFlowFunc(("cMixed=%RU32\n", cMixed));
     425    }
     426
     427#ifdef DEBUG_andy
     428    AssertRC(rc);
     429#endif
     430
     431#if 0
    982432    /*
    983433     * Second, mix the guest mixing buffer with the host mixing
     
    988438        && cWritten)
    989439    {
     440        rc = AudioMixBufMixToParent(&pGstStream->MixBuf, cWritten, &cMixed);
     441    }
     442    else
     443        cMixed = 0;
     444
     445    if (RT_SUCCESS(rc))
     446    {
     447        /*
     448         * Return the number of samples which actually have been mixed
     449         * down to the parent, regardless how much samples were written
     450         * into the children buffer.
     451         */
     452        if (pcbWritten)
     453            *pcbWritten = AUDIOMIXBUF_S2B(&pGstStream->MixBuf, cMixed);
     454    }
     455#else
     456    if (RT_SUCCESS(rc))
     457    {
     458        if (pcbWritten)
     459            *pcbWritten = AUDIOMIXBUF_S2B(&pGstStream->MixBuf, cWritten);
     460    }
     461#endif
     462
     463    LogFlowFunc(("%s -> %s: cbBuf=%RU32, cWritten=%RU32 (%RU32 bytes), rc=%Rrc\n",
     464                 pGstStream->szName, pHstStream->szName, cbBuf,
     465                 cWritten, AUDIOMIXBUF_S2B(&pHstStream->MixBuf, cWritten), rc));
     466
     467    int rc2 = RTCritSectLeave(&pThis->CritSect);
     468    if (RT_SUCCESS(rc))
     469        rc = rc2;
     470
     471    return rc;
     472}
     473#else
     474static DECLCALLBACK(int) drvAudioWrite(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut,
     475                                       const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
     476{
     477    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     478    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     479
     480    AssertPtrReturn(pGstStrmOut, VERR_INVALID_POINTER);
     481    AssertPtrReturn(pvBuf,       VERR_INVALID_POINTER);
     482    AssertReturn(cbBuf,          VERR_INVALID_PARAMETER);
     483    /* pcbWritten is optional. */
     484
     485    int rc = RTCritSectEnter(&pThis->CritSect);
     486    if (RT_FAILURE(rc))
     487        return rc;
     488
     489    if (!pThis->pHostDrvAudio->pfnIsEnabled(pThis->pHostDrvAudio, PDMAUDIODIR_OUT))
     490    {
     491        rc = RTCritSectLeave(&pThis->CritSect);
     492        AssertRC(rc);
     493
     494        return VERR_NOT_AVAILABLE;
     495    }
     496
     497    PPDMAUDIOHSTSTRMOUT pHstStrmOut = pGstStrmOut->pHstStrmOut;
     498    AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
     499
     500    AssertMsg(pGstStrmOut->pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED,
     501              ("Writing to disabled host output stream \"%s\" not possible\n",
     502              pHstStrmOut->MixBuf.pszName));
     503
     504    if (!AudioMixBufFreeBytes(&pGstStrmOut->MixBuf))
     505    {
     506        if (pcbWritten)
     507            *pcbWritten = 0;
     508
     509        return RTCritSectLeave(&pThis->CritSect);
     510    }
     511
     512    /*
     513     * First, write data from the device emulation into our
     514     * guest mixing buffer.
     515     */
     516    uint32_t cWritten;
     517    //rc = AudioMixBufWriteAt(&pGstStrmOut->MixBuf, 0 /* Offset in samples */, pvBuf, cbBuf, &cWritten);
     518    rc = AudioMixBufWriteCirc(&pGstStrmOut->MixBuf, pvBuf, cbBuf, &cWritten);
     519    if (rc == VINF_BUFFER_OVERFLOW)
     520        LogRel(("Audio: Lost audio samples from guest, expect stuttering audio output\n"));
     521
     522    /*
     523     * Second, mix the guest mixing buffer with the host mixing
     524     * buffer so that the host backend can play the data lateron.
     525     */
     526    uint32_t cMixed;
     527    if (   RT_SUCCESS(rc)
     528        && cWritten)
     529    {
    990530        rc = AudioMixBufMixToParent(&pGstStrmOut->MixBuf, cWritten, &cMixed);
    991531    }
     
    1014554    return rc;
    1015555}
    1016 
    1017 static PPDMAUDIOHSTSTRMOUT drvAudioFindAnyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
    1018 {
    1019     if (pHstStrmOut)
    1020     {
    1021         if (RTListNodeIsLast(&pThis->lstHstStrmOut, &pHstStrmOut->Node))
    1022             return NULL;
    1023 
    1024         return RTListNodeGetNext(&pHstStrmOut->Node, PDMAUDIOHSTSTRMOUT, Node);
    1025     }
    1026 
    1027     return RTListGetFirst(&pThis->lstHstStrmOut, PDMAUDIOHSTSTRMOUT, Node);
    1028 }
    1029 
    1030 static PPDMAUDIOHSTSTRMOUT drvAudioHstFindAnyEnabledOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHostStrmOut)
    1031 {
    1032     while ((pHostStrmOut = drvAudioFindAnyHstOut(pThis, pHostStrmOut)))
    1033     {
    1034         if (pHostStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)
    1035             return pHostStrmOut;
    1036     }
    1037 
    1038     return NULL;
    1039 }
    1040 
    1041 static PPDMAUDIOHSTSTRMOUT drvAudioFindSpecificOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
    1042                                                    PPDMAUDIOSTREAMCFG pCfg)
    1043 {
    1044     while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut)))
    1045     {
    1046         if (DrvAudioPCMPropsAreEqual(&pHstStrmOut->Props, pCfg))
    1047             return pHstStrmOut;
    1048     }
    1049 
    1050     return NULL;
    1051 }
    1052 
    1053 int drvAudioDestroyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn)
    1054 {
    1055     AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
    1056     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    1057 
    1058     LogFlowFunc(("%s\n", pHstStrmIn->MixBuf.pszName));
    1059 
    1060     int rc = VINF_SUCCESS;
    1061 
    1062     if (!pHstStrmIn->pGstStrmIn)
    1063     {
    1064         drvAudioHstInFreeRes(pHstStrmIn);
    1065 
    1066         if (RTCritSectIsInitialized(&pHstStrmIn->CritSect))
    1067         {
    1068             int rc2 = RTCritSectDelete(&pHstStrmIn->CritSect);
    1069             AssertRC(rc2);
    1070         }
    1071 
    1072         /* Remove from driver instance list. */
    1073         RTListNodeRemove(&pHstStrmIn->Node);
    1074 
    1075         RTMemFree(pHstStrmIn);
    1076         pThis->cStreamsFreeIn++;
    1077     }
    1078     else
    1079     {
    1080         rc = VERR_WRONG_ORDER;
    1081         LogFlowFunc(("[%s] Still is being used, skipping\n", pHstStrmIn->MixBuf.pszName));
    1082     }
    1083 
    1084     LogFlowFuncLeaveRC(rc);
     556#endif
     557
     558static DECLCALLBACK(uint32_t) drvAudioStreamAddRef(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream)
     559{
     560   AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     561   AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     562
     563   NOREF(pInterface);
     564
     565   return ++pStream->cRefs;
     566}
     567
     568static DECLCALLBACK(uint32_t) drvAudioStreamRelease(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream)
     569{
     570   AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     571   AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     572
     573   NOREF(pInterface);
     574
     575   Assert(pStream->cRefs);
     576   if (pStream->cRefs)
     577       pStream->cRefs--;
     578
     579   return pStream->cRefs;
     580}
     581
     582#if 1
     583static DECLCALLBACK(int) drvAudioStreamGetData(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, uint32_t *pcData)
     584{
     585    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     586    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     587    /* pcData is optional. */
     588
     589    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     590
     591    int rc = RTCritSectEnter(&pThis->CritSect);
     592    if (RT_FAILURE(rc))
     593        return rc;
     594
     595    uint32_t cData = 0;
     596
     597    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     598    PPDMAUDIOSTREAM pGstStream = pHstStream->pPair;
     599
     600    do
     601    {
     602        if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
     603            break;
     604
     605        if (pHstStream->enmDir == PDMAUDIODIR_IN)
     606        {
     607            /* Call the host backend to capture the audio input data. */
     608            rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pHstStream, &cData);
     609            if (RT_FAILURE(rc))
     610                break;
     611
     612            //cbData = AUDIOMIXBUF_S2B(&pStream->MixBuf, AudioMixBufMixed(&pStream->MixBuf)));
     613
     614        }
     615        else /* Out */
     616        {
     617            uint32_t cSamplesMixed = 0;
     618            uint32_t cSamplesToMix = 0;
     619
     620            uint32_t cSamplesLive = AudioMixBufAvail(&pHstStream->MixBuf);
     621            if (!cSamplesLive)
     622            {
     623
     624            }
     625
     626            cSamplesToMix = AudioMixBufAvail(&pGstStream->MixBuf);
     627            if (cSamplesToMix)
     628                rc = AudioMixBufMixToParent(&pGstStream->MixBuf, cSamplesToMix, &cSamplesMixed);
     629
     630            /* Has this stream marked as disabled but there still were guest streams relying
     631             * on it? CheckpHstStreamif this stream now can be closed and do so, if possible. */
     632            if (   (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)
     633                && !cSamplesToMix)
     634            {
     635                /* Stop playing the current (pending) stream. */
     636                int rc2 = drvAudioStreamControlInternal(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     637                if (RT_SUCCESS(rc2))
     638                {
     639                    pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
     640
     641                    LogFunc(("%s: Disabling stream\n", pHstStream->szName));
     642                }
     643                else
     644                    LogFunc(("%s: Backend vetoed against closing output stream, rc=%Rrc\n", pHstStream->szName, rc2));
     645
     646                break;
     647            }
     648
     649            LogFlowFunc(("%s: cSamplesLive=%RU32, cSamplesToMix=%RU32, cSamplesMixed=%RU32\n",
     650                         pHstStream->szName, cSamplesLive, cSamplesToMix, cSamplesMixed));
     651
     652            /* Return live samples to play. */
     653            cData = cSamplesLive;
     654        }
     655
     656    } while (0);
     657
     658#ifdef DEBUG_andy
     659    LogFlowFunc(("%s: cData=%RU32\n", pHstStream->szName, cData));
     660#endif
     661
     662    if (pcData)
     663        *pcData = cData;
     664
     665    int rc2 = RTCritSectLeave(&pThis->CritSect);
     666    if (RT_SUCCESS(rc))
     667        rc = rc2;
     668
     669    if (RT_FAILURE(rc))
     670        LogFlowFuncLeaveRC(rc);
     671
    1085672    return rc;
    1086673}
    1087 
    1088 static int drvAudioDestroyGstIn(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMIN pGstStrmIn)
    1089 {
    1090     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    1091 
    1092     if (!pGstStrmIn)
    1093         return VINF_SUCCESS;
    1094 
    1095     LogFlowFunc(("%s\n", pGstStrmIn->MixBuf.pszName));
    1096 
    1097     if (pGstStrmIn->State.cRefs > 1) /* Do other objects still have a reference to it? Bail out. */
    1098         return VERR_WRONG_ORDER;
    1099 
    1100     AudioMixBufDestroy(&pGstStrmIn->MixBuf);
    1101 
    1102     /* Is this guest stream associate to a host stream? */
    1103     if (pGstStrmIn->pHstStrmIn)
    1104     {
    1105         /* Unlink child. */
    1106         pGstStrmIn->pHstStrmIn->pGstStrmIn = NULL;
    1107     }
    1108 
    1109     RTMemFree(pGstStrmIn);
    1110     pGstStrmIn = NULL;
    1111 
    1112     return VINF_SUCCESS;
    1113 }
    1114 
    1115 static DECLCALLBACK(uint32_t) drvAudioAddRefIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrm)
    1116 {
    1117    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1118    AssertPtrReturn(pGstStrm, VERR_INVALID_POINTER);
    1119 
    1120    NOREF(pInterface);
    1121 
    1122    return ++pGstStrm->State.cRefs;
    1123 }
    1124 
    1125 static DECLCALLBACK(uint32_t) drvAudioAddRefOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrm)
    1126 {
    1127    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1128    AssertPtrReturn(pGstStrm,   VERR_INVALID_POINTER);
    1129 
    1130    NOREF(pInterface);
    1131 
    1132    return ++pGstStrm->State.cRefs;
    1133 }
    1134 
    1135 static DECLCALLBACK(uint32_t) drvAudioReleaseIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrm)
    1136 {
    1137    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1138    AssertPtrReturn(pGstStrm,   VERR_INVALID_POINTER);
    1139 
    1140    NOREF(pInterface);
    1141 
    1142    Assert(pGstStrm->State.cRefs);
    1143    if (pGstStrm->State.cRefs)
    1144        pGstStrm->State.cRefs--;
    1145 
    1146    return pGstStrm->State.cRefs;
    1147 }
    1148 
    1149 static DECLCALLBACK(uint32_t) drvAudioReleaseOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrm)
    1150 {
    1151    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1152    AssertPtrReturn(pGstStrm,   VERR_INVALID_POINTER);
    1153 
    1154    NOREF(pInterface);
    1155 
    1156    Assert(pGstStrm->State.cRefs);
    1157    if (pGstStrm->State.cRefs)
    1158        pGstStrm->State.cRefs--;
    1159 
    1160    return pGstStrm->State.cRefs;
    1161 }
    1162 
     674#else
    1163675static DECLCALLBACK(int) drvAudioGetDataIn(PPDMIAUDIOCONNECTOR pInterface, uint32_t *pcbAvailIn)
    1164676{
     
    1228740    if (RT_FAILURE(rc))
    1229741        return rc;
     742
     743    static uint64_t s_tsLast = 0;
     744
     745
     746    uint64_t s_tsDelta = RTTimeNanoTS() - s_tsLast;
     747    LogFlowFunc(("delta=%RU64 (%RU64ms) -> ", s_tsDelta, s_tsDelta / 1000 / 1000));
     748
     749    #if 0
     750    PPDMAUDIOHSTSTRMOUT pHstStrmOut = drvAudioHstFindAnyEnabledOut(pThis, NULL);
     751    uint64_t ns = s_tsDelta / pHstStrmOut->Props.uHz;
     752
     753
     754
     755    uint32_t cSamplesMin  = (cTicksElapsed / pSink->PCMProps.uHz) * pSink->PCMProps.cChannels;
     756    #endif
     757
     758    s_tsLast = RTTimeNanoTS();
    1230759
    1231760    /*
     
    1308837    return rc;
    1309838}
    1310 
     839#endif
     840
     841#if 1
     842static DECLCALLBACK(int) drvAudioStreamPlay(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, uint32_t *pcSamplesPlayed)
     843{
     844    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     845    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     846    /* pcSamplesPlayed is optional. */
     847
     848    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     849
     850    int rc = RTCritSectEnter(&pThis->CritSect);
     851    if (RT_FAILURE(rc))
     852        return rc;
     853
     854    /* Backend output (temporarily) disabled / unavailable? */
     855    if (pThis->pHostDrvAudio->pfnGetStatus(pThis->pHostDrvAudio, PDMAUDIODIR_OUT) != PDMAUDIOBACKENDSTS_RUNNING)
     856    {
     857        rc = pThis->pHostDrvAudio->pfnGetConfig(pThis->pHostDrvAudio, &pThis->BackendCfg);
     858        AssertRC(rc);
     859
     860        if (   !pThis->BackendCfg.cSinks
     861            || !pThis->BackendCfg.cMaxStreamsOut)
     862        {
     863            int rc2 = RTCritSectLeave(&pThis->CritSect);
     864            AssertRC(rc2);
     865
     866            return VERR_NOT_AVAILABLE;
     867        }
     868    }
     869
     870    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     871
     872    uint32_t cSamplesPlayed = 0;
     873    rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream, &cSamplesPlayed);
     874    if (RT_FAILURE(rc))
     875    {
     876        int rc3 = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     877        AssertRC(rc3);
     878    }
     879
     880    LogFlowFunc(("[%s] cSamplesPlayed=%RU32, rc=%Rrc\n", pStream->szName, cSamplesPlayed, rc));
     881
     882    PPDMAUDIOSTREAM pGstStream = pHstStream->pPair;
     883    if (pGstStream)
     884    {
     885        bool fIsEmpty = AudioMixBufIsEmpty(&pGstStream->MixBuf);
     886
     887
     888    }
     889
     890#if 0
     891        if (pStream->pPair)
     892        {
     893            bool fIsEmpty = AudioMixBufIsEmpty(&pStream->pPair->MixBuf);
     894
     895            if (   !pPair->State.fActive
     896                && fIsEmpty)
     897                continue;
     898
     899            if ()
     900            {
     901                pGstStrmOut->State.fEmpty = true;
     902                fNeedsCleanup |= !pGstStrmOut->State.fActive;
     903            }
     904        }
     905
     906        if (fNeedsCleanup)
     907        {
     908            RTListForEach(&pHstStrmOut->lstGstStrmOut, pGstStrmOut, PDMAUDIOGSTSTRMOUT, Node)
     909            {
     910                if (!pGstStrmOut->State.fActive)
     911                    drvAudioDestroyGstOut(pThis, pGstStrmOut);
     912            }
     913        }
     914#endif
     915
     916    if (RT_SUCCESS(rc))
     917    {
     918        if (pcSamplesPlayed)
     919            *pcSamplesPlayed = cSamplesPlayed;
     920    }
     921
     922    int rc2 = RTCritSectLeave(&pThis->CritSect);
     923    if (RT_SUCCESS(rc))
     924        rc = rc2;
     925
     926    if (RT_FAILURE(rc))
     927        LogFlowFuncLeaveRC(rc);
     928
     929    return rc;
     930}
     931#else
    1311932static DECLCALLBACK(int) drvAudioPlayOut(PPDMIAUDIOCONNECTOR pInterface, uint32_t *pcSamplesPlayed)
    1312933{
     
    1371992        }
    1372993#endif
    1373 
    1374994        uint32_t cSamplesPlayed = 0;
    1375995        int rc2 = pThis->pHostDrvAudio->pfnPlayOut(pThis->pHostDrvAudio, pHstStrmOut, &cSamplesPlayed);
     
    14261046    return rc;
    14271047}
     1048#endif
    14281049
    14291050#ifdef VBOX_WITH_AUDIO_CALLBACKS
     
    15671188
    15681189    /* Get the configuration data from backend. */
    1569     rc = pThis->pHostDrvAudio->pfnGetConf(pThis->pHostDrvAudio, &pThis->BackendCfg);
     1190    rc = pThis->pHostDrvAudio->pfnGetConfig(pThis->pHostDrvAudio, &pThis->BackendCfg);
    15701191    if (RT_FAILURE(rc))
    15711192    {
     
    16111232        return;
    16121233
    1613     PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL;
    1614     while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut)))
    1615         drvAudioControlHstOut(pThis, pHstStrmOut, enmCmd);
    1616 
    1617     PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL;
    1618     while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn)))
    1619         drvAudioControlHstIn(pThis, pHstStrmIn, enmCmd);
     1234    PPDMAUDIOSTREAM pStream;
     1235    RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node)
     1236        drvAudioStreamControlInternal(pThis, pStream, enmCmd);
    16201237}
    16211238
     
    16281245    LogFlowFunc(("pThis=%p, pDrvIns=%p\n", pThis, pDrvIns));
    16291246
    1630     RTListInit(&pThis->lstHstStrmIn);
    1631     RTListInit(&pThis->lstHstStrmOut);
     1247    RTListInit(&pThis->lstStreams);
    16321248#ifdef VBOX_WITH_AUDIO_CALLBACKS
    16331249    RTListInit(&pThis->lstCBIn);
     
    16491265}
    16501266
     1267#if 1
     1268static DECLCALLBACK(int) drvAudioStreamRead(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream,
     1269                                            void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
     1270{
     1271    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     1272    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1273
     1274    if (!pStream)
     1275        return VERR_NOT_AVAILABLE;
     1276
     1277    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
     1278    AssertReturn(cbBuf,    VERR_INVALID_PARAMETER);
     1279    /* pcbWritten is optional. */
     1280
     1281    int rc = RTCritSectEnter(&pThis->CritSect);
     1282    if (RT_FAILURE(rc))
     1283        return rc;
     1284
     1285    if (pThis->pHostDrvAudio->pfnGetStatus(pThis->pHostDrvAudio, PDMAUDIODIR_IN) != PDMAUDIOBACKENDSTS_RUNNING)
     1286    {
     1287        if (pcbRead)
     1288            *pcbRead = 0;
     1289
     1290        return RTCritSectLeave(&pThis->CritSect);
     1291    }
     1292
     1293    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     1294
     1295    AssertMsg(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED,
     1296              ("Reading from disabled host input stream '%s' not possible\n", pHstStream->szName));
     1297
     1298    /*
     1299     * Read from the parent buffer (that is, the guest buffer) which
     1300     * should have the audio data in the format the guest needs.
     1301     */
     1302    uint32_t cRead;
     1303    rc = AudioMixBufReadCirc(&pStream->MixBuf, pvBuf, cbBuf, &cRead);
     1304    if (RT_SUCCESS(rc))
     1305    {
     1306        AudioMixBufFinish(&pStream->MixBuf, cRead);
     1307
     1308        if (pcbRead)
     1309            *pcbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead);
     1310    }
     1311
     1312    LogFlowFunc(("cRead=%RU32 (%RU32 bytes), rc=%Rrc\n",
     1313                 cRead, AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead), rc));
     1314
     1315    int rc2 = RTCritSectLeave(&pThis->CritSect);
     1316    if (RT_SUCCESS(rc))
     1317        rc = rc2;
     1318
     1319    return rc;
     1320}
     1321#else
    16511322static DECLCALLBACK(int) drvAudioRead(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrmIn,
    16521323                                      void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
     
    17031374    return rc;
    17041375}
    1705 
     1376#endif
     1377
     1378#if 0
    17061379static DECLCALLBACK(int) drvAudioEnableOut(PPDMIAUDIOCONNECTOR pInterface,
    17071380                                           PPDMAUDIOGSTSTRMOUT pGstStrmOut, bool fEnable)
     
    17801453    return rc;
    17811454}
    1782 
    1783 static DECLCALLBACK(int) drvAudioEnableIn(PPDMIAUDIOCONNECTOR pInterface,
    1784                                           PPDMAUDIOGSTSTRMIN pGstStrmIn, bool fEnable)
     1455#endif
     1456
     1457static DECLCALLBACK(int) drvAudioStreamCreate(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg,
     1458                                              PPDMAUDIOSTREAM *ppStream)
    17851459{
    17861460    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1787 
    1788     if (!pGstStrmIn)
    1789         return VERR_NOT_AVAILABLE;
     1461    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
     1462    AssertPtrReturn(ppStream,   VERR_INVALID_POINTER);
    17901463
    17911464    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
    17921465
    1793     int rc = VINF_SUCCESS;
    1794 
    1795     PPDMAUDIOHSTSTRMIN pHstStrmIn = pGstStrmIn->pHstStrmIn;
    1796     AssertPtr(pHstStrmIn);
    1797 
    1798     rc = drvAudioControlHstIn(pThis, pHstStrmIn,
    1799                               fEnable ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE);
    1800     if (RT_SUCCESS(rc))
    1801         pGstStrmIn->State.fActive = fEnable;
    1802 
    1803     LogFlowFunc(("%s: fEnable=%RTbool, rc=%Rrc\n", pGstStrmIn->MixBuf.pszName, fEnable, rc));
    1804 
    1805     return rc;
    1806 }
    1807 
    1808 static DECLCALLBACK(bool) drvAudioIsValidIn(PPDMIAUDIOCONNECTOR pInterface,
    1809                                             PPDMAUDIOGSTSTRMIN  pGstStrmIn)
    1810 {
    1811     return (pGstStrmIn != NULL);
    1812 }
    1813 
    1814 static DECLCALLBACK(bool) drvAudioIsValidOut(PPDMIAUDIOCONNECTOR pInterface,
    1815                                              PPDMAUDIOGSTSTRMOUT pGstStrmOut)
    1816 {
    1817     return (pGstStrmOut != NULL);
    1818 }
    1819 
    1820 static DECLCALLBACK(int) drvAudioCreateIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg,
    1821                                           PPDMAUDIOGSTSTRMIN *ppGstStrmIn)
    1822 {
    1823     AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
    1824     AssertPtrReturn(pCfg,        VERR_INVALID_POINTER);
    1825     AssertPtrReturn(ppGstStrmIn, VERR_INVALID_POINTER);
    1826 
    1827     Assert(pCfg->enmDir == PDMAUDIODIR_IN);
    1828 
    1829     PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
    1830 
    18311466    int rc = RTCritSectEnter(&pThis->CritSect);
    18321467    if (RT_FAILURE(rc))
     
    18341469
    18351470    LogFlowFunc(("szName=%s\n", pCfg->szName));
    1836 
    1837     if (!drvAudioStreamCfgIsValid(pCfg))
    1838     {
    1839         LogFunc(("Input stream configuration is not valid, bailing out\n"));
    1840         rc = VERR_INVALID_PARAMETER;
    1841     }
    1842 
    1843     if (RT_SUCCESS(rc))
    1844     {
    1845         PPDMAUDIOGSTSTRMIN pGstStrmIn;
    1846         rc = drvAudioCreateStreamPairIn(pThis, pCfg, &pGstStrmIn);
     1471#ifdef DEBUG
     1472    DrvAudioStreamCfgPrint(pCfg);
     1473#endif
     1474
     1475    /*
     1476     * The guest stream always will get the audio stream configuration told
     1477     * by the device emulation (which in turn was/could be set by the guest OS).
     1478     */
     1479    PPDMAUDIOSTREAM pGstStrm = NULL;
     1480
     1481    /** @todo Docs! */
     1482    PPDMAUDIOSTREAM pHstStrm = NULL;
     1483
     1484#define RC_BREAK(x) { rc = x; break; }
     1485
     1486    do
     1487    {
     1488        if (!DrvAudioStreamCfgIsValid(pCfg))
     1489            RC_BREAK(VERR_INVALID_PARAMETER);
     1490
     1491        /* Note: cbHstStrm will contain sizeof(PDMAUDIOSTREAM) + additional data
     1492         *       which the host backend will need. */
     1493        size_t cbHstStrm;
     1494        if (pCfg->enmDir == PDMAUDIODIR_IN)
     1495        {
     1496            if (!pThis->cStreamsFreeIn)
     1497            {
     1498                LogFlowFunc(("No more input streams free to use, bailing out\n"));
     1499                RC_BREAK(VERR_AUDIO_NO_FREE_INPUT_STREAMS);
     1500            }
     1501
     1502            /* Validate backend configuration. */
     1503            if (!pThis->BackendCfg.cbStreamIn)
     1504            {
     1505                LogFlowFunc(("Backend input configuration not valid, bailing out\n"));
     1506                RC_BREAK(VERR_INVALID_PARAMETER);
     1507            }
     1508
     1509            cbHstStrm = pThis->BackendCfg.cbStreamIn;
     1510        }
     1511        else /* Out */
     1512        {
     1513            if (!pThis->cStreamsFreeOut)
     1514            {
     1515                LogFlowFunc(("Maximum number of host output streams reached\n"));
     1516                RC_BREAK(VERR_NO_MORE_HANDLES); /** @todo Fudge! */
     1517            }
     1518
     1519            /* Validate backend configuration. */
     1520            if (!pThis->BackendCfg.cbStreamOut)
     1521            {
     1522                LogFlowFunc(("Backend output configuration invalid, bailing out\n"));
     1523                RC_BREAK(VERR_INVALID_PARAMETER);
     1524            }
     1525
     1526            cbHstStrm = pThis->BackendCfg.cbStreamOut;
     1527        }
     1528
     1529        pHstStrm = (PPDMAUDIOSTREAM)RTMemAllocZ(cbHstStrm);
     1530        AssertPtrBreakStmt(pHstStrm, rc = VERR_NO_MEMORY);
     1531
     1532        RTListAppend(&pThis->lstStreams, &pHstStrm->Node);
     1533
     1534        pGstStrm = (PPDMAUDIOSTREAM)RTMemAllocZ(sizeof(PDMAUDIOSTREAM));
     1535        AssertPtrBreakStmt(pGstStrm, rc = VERR_NO_MEMORY);
     1536
     1537        RTListAppend(&pThis->lstStreams, &pGstStrm->Node);
     1538
     1539        /*
     1540         * Create host stream.
     1541         */
     1542
     1543        RTStrPrintf(pHstStrm->szName, RT_ELEMENTS(pHstStrm->szName), "%s (Host)",
     1544                    strlen(pCfg->szName) ? pCfg->szName : "<Untitled>");
     1545
     1546        /* Note: Direction is always from child -> parent. */
     1547        uint32_t cSamples = 0;
     1548        rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pHstStrm, pCfg, &cSamples);
     1549        if (RT_FAILURE(rc))
     1550        {
     1551            LogFlowFunc(("Initializing host backend failed with rc=%Rrc\n", rc));
     1552            break;
     1553        }
     1554
     1555        pHstStrm->enmCtx   = PDMAUDIOSTREAMCTX_HOST;
     1556        pHstStrm->enmDir   = pCfg->enmDir;
     1557        pHstStrm->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
     1558        pHstStrm->pPair    = pGstStrm;
     1559
     1560        rc = DrvAudioStreamCfgToProps(pCfg, &pHstStrm->Props);
     1561        AssertRCBreak(rc);
     1562
     1563        rc = AudioMixBufInit(&pHstStrm->MixBuf, pHstStrm->szName, &pHstStrm->Props, cSamples);
     1564        AssertRCBreak(rc);
     1565
     1566        /*
     1567         * Create guest stream.
     1568         */
     1569
     1570        RTStrPrintf(pGstStrm->szName, RT_ELEMENTS(pGstStrm->szName), "%s (Guest)",
     1571                    strlen(pCfg->szName) ? pCfg->szName : "<Untitled>");
     1572
     1573        rc = DrvAudioStreamCfgToProps(pCfg, &pGstStrm->Props);
     1574        AssertRCBreak(rc);
     1575
     1576        rc = AudioMixBufInit(&pGstStrm->MixBuf, pGstStrm->szName, &pGstStrm->Props, AudioMixBufSize(&pHstStrm->MixBuf));
    18471577        if (RT_SUCCESS(rc))
    1848             *ppGstStrmIn = pGstStrmIn;
     1578        {
     1579            if (pCfg->enmDir == PDMAUDIODIR_IN)
     1580            {
     1581                rc = AudioMixBufLinkTo(&pHstStrm->MixBuf, &pGstStrm->MixBuf);
     1582            }
     1583            else
     1584            {
     1585                rc = AudioMixBufLinkTo(&pGstStrm->MixBuf, &pHstStrm->MixBuf);
     1586            }
     1587        }
     1588
     1589        pGstStrm->enmCtx   = PDMAUDIOSTREAMCTX_GUEST;
     1590        pGstStrm->enmDir   = pCfg->enmDir;
     1591        pGstStrm->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
     1592        pGstStrm->pPair    = pHstStrm;
     1593
     1594        AssertRCBreak(rc);
     1595
     1596    } while (0);
     1597
     1598#undef RC_BREAK
     1599
     1600    if (RT_FAILURE(rc))
     1601    {
     1602        if (pHstStrm->enmCtx == PDMAUDIOSTREAMCTX_HOST)
     1603        {
     1604            if (pHstStrm->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
     1605            {
     1606                rc = drvAudioStreamControlInternal(pThis, pHstStrm, PDMAUDIOSTREAMCMD_DISABLE);
     1607                if (RT_SUCCESS(rc))
     1608                {
     1609                    rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pHstStrm);
     1610                    if (RT_SUCCESS(rc))
     1611                        pHstStrm->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
     1612                }
     1613            }
     1614
     1615            AssertMsgRC(rc, ("Host stream '%s' failed to uninit in backend: %Rrc\n",  pHstStrm->szName, rc));
     1616        }
     1617
     1618        drvAudioStreamDestroyInternal(pThis, pGstStrm);
     1619        pGstStrm = NULL;
     1620
     1621        drvAudioStreamDestroyInternal(pThis, pHstStrm);
     1622        pHstStrm = NULL;
     1623    }
     1624    else
     1625    {
     1626        /* Set initial reference counts. */
     1627        pGstStrm->cRefs = 1;
     1628        pHstStrm->cRefs = 1;
     1629
     1630        if (pCfg->enmDir == PDMAUDIODIR_IN)
     1631        {
     1632            Assert(pThis->cStreamsFreeIn);
     1633            pThis->cStreamsFreeIn--;
     1634        }
     1635        else /* Out */
     1636        {
     1637            Assert(pThis->cStreamsFreeOut);
     1638            pThis->cStreamsFreeOut--;
     1639        }
     1640
     1641        *ppStream = pGstStrm;
    18491642    }
    18501643
     
    18571650}
    18581651
    1859 static DECLCALLBACK(int) drvAudioCreateOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg,
    1860                                            PPDMAUDIOGSTSTRMOUT *ppGstStrmOut)
    1861 {
    1862     AssertPtrReturn(pInterface,   VERR_INVALID_POINTER);
    1863     AssertPtrReturn(pCfg,         VERR_INVALID_POINTER);
    1864     AssertPtrReturn(ppGstStrmOut, VERR_INVALID_POINTER);
    1865 
    1866     Assert(pCfg->enmDir == PDMAUDIODIR_OUT);
     1652#if 1
     1653static DECLCALLBACK(int) drvAudioGetConfig(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg)
     1654{
     1655    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1656    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
    18671657
    18681658    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     
    18721662        return rc;
    18731663
    1874     LogFlowFunc(("pszName=%s\n", pCfg->szName));
    1875 
    1876     if (!drvAudioStreamCfgIsValid(pCfg))
    1877     {
    1878         LogFunc(("Output stream configuration is not valid, bailing out\n"));
    1879         rc = VERR_INVALID_PARAMETER;
    1880     }
    1881 
    1882     if (RT_SUCCESS(rc))
    1883     {
    1884         PPDMAUDIOGSTSTRMOUT pGstStrmOut;
    1885         rc = drvAudioCreateStreamPairOut(pThis, pCfg, &pGstStrmOut);
    1886         if (RT_SUCCESS(rc))
    1887             *ppGstStrmOut = pGstStrmOut;
    1888     }
     1664    rc = pThis->pHostDrvAudio->pfnGetConfig(pThis->pHostDrvAudio, pCfg);
    18891665
    18901666    int rc2 = RTCritSectLeave(&pThis->CritSect);
     
    18961672}
    18971673
    1898 static DECLCALLBACK(int) drvAudioGetConfig(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg)
    1899 {
    1900     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1901     AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
    1902 
    1903     PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
    1904 
    1905     int rc = RTCritSectEnter(&pThis->CritSect);
    1906     if (RT_FAILURE(rc))
    1907         return rc;
    1908 
    1909     rc = pThis->pHostDrvAudio->pfnGetConf(pThis->pHostDrvAudio, pCfg);
    1910 
    1911     int rc2 = RTCritSectLeave(&pThis->CritSect);
    1912     if (RT_SUCCESS(rc))
    1913         rc = rc2;
    1914 
    1915     LogFlowFuncLeaveRC(rc);
    1916     return rc;
    1917 }
    1918 
    1919 static DECLCALLBACK(bool) drvAudioIsActiveIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrmIn)
     1674static DECLCALLBACK(PDMAUDIOSTRMSTS) drvAudioStreamGetStatus(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream)
    19201675{
    19211676    AssertPtrReturn(pInterface, false);
    1922     /* pGstStrmIn is optional. */
     1677    /* pStream is optional. */
     1678
     1679    if (!pStream)
     1680        return PDMAUDIOSTRMSTS_FLAG_NONE;
    19231681
    19241682    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     
    19271685    AssertRC(rc2);
    19281686
    1929     bool fRet = pGstStrmIn ? pGstStrmIn->State.fActive : false;
     1687    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     1688    PDMAUDIOSTRMSTS strmSts    = pHstStream->fStatus;
     1689
     1690    LogFlowFunc(("%s: strmSts=%0x%x\n", pHstStream->szName, strmSts));
    19301691
    19311692    rc2 = RTCritSectLeave(&pThis->CritSect);
    19321693    AssertRC(rc2);
    19331694
    1934     return fRet;
    1935 }
    1936 
    1937 static DECLCALLBACK(bool) drvAudioIsActiveOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut)
    1938 {
    1939     AssertPtrReturn(pInterface,  false);
    1940     /* pGstStrmOut is optional. */
    1941 
     1695    return strmSts;
     1696}
     1697#endif
     1698
     1699static DECLCALLBACK(int) drvAudioStreamDestroy(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream)
     1700{
    19421701    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
    19431702
    1944     int rc2 = RTCritSectEnter(&pThis->CritSect);
    1945     AssertRC(rc2);
    1946 
    1947     bool fRet = pGstStrmOut ? pGstStrmOut->State.fActive : false;
    1948 
    1949     rc2 = RTCritSectLeave(&pThis->CritSect);
    1950     AssertRC(rc2);
    1951 
    1952     return fRet;
    1953 }
    1954 
    1955 static DECLCALLBACK(void) drvAudioDestroyIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrmIn)
    1956 {
    1957     AssertPtrReturnVoid(pInterface);
    1958     /* pGstStrmIn is optional. */
    1959 
    1960     PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
    1961 
    1962     if (!pGstStrmIn)
    1963         return;
    1964 
    1965     int rc2 = RTCritSectEnter(&pThis->CritSect);
    1966     AssertRC(rc2);
    1967 
    1968     rc2 = drvAudioDestroyGstIn(pThis, pGstStrmIn);
    1969     AssertRC(rc2);
    1970 
    1971     rc2 = RTCritSectLeave(&pThis->CritSect);
    1972     AssertRC(rc2);
    1973 }
    1974 
    1975 static DECLCALLBACK(void) drvAudioDestroyOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut)
    1976 {
    1977     AssertPtrReturnVoid(pInterface);
    1978     /* pGstStrmOut is optional. */
    1979 
    1980     PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
    1981 
    1982     if (!pGstStrmOut)
    1983         return;
    1984 
    1985     int rc2 = RTCritSectEnter(&pThis->CritSect);
    1986     AssertRC(rc2);
    1987 
    1988     rc2 = drvAudioDestroyGstOut(pThis, pGstStrmOut);
    1989     AssertRC(rc2);
    1990 
    1991     rc2 = RTCritSectLeave(&pThis->CritSect);
    1992     AssertRC(rc2);
    1993 }
    1994 
    1995 void drvAudioHstOutFreeRes(PPDMAUDIOHSTSTRMOUT pHstStrmOut)
    1996 {
    1997     AssertPtrReturnVoid(pHstStrmOut);
    1998     AudioMixBufDestroy(&pHstStrmOut->MixBuf);
     1703    int rc = RTCritSectEnter(&pThis->CritSect);
     1704    AssertRC(rc);
     1705
     1706    PDMAUDIODIR enmDir = pStream->enmDir;
     1707
     1708    LogFlowFunc(("%s: cRefs=%RU32\n", pStream->szName, pStream->cRefs));
     1709    if (pStream->cRefs > 1)
     1710        rc = VERR_WRONG_ORDER;
     1711
     1712    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     1713    if (   RT_SUCCESS(rc)
     1714        && pHstStream->cRefs == 1)
     1715    {
     1716        rc = drvAudioStreamDestroyInternalBackend(pThis, pHstStream);
     1717        if (RT_SUCCESS(rc))
     1718        {
     1719            if (pStream->pPair)
     1720            {
     1721                rc = drvAudioStreamDestroyInternal(pThis, pStream->pPair);
     1722                pStream->pPair = NULL;
     1723            }
     1724
     1725            if (RT_SUCCESS(rc))
     1726                rc = drvAudioStreamDestroyInternal(pThis, pStream);
     1727
     1728            if (RT_SUCCESS(rc))
     1729            {
     1730                if (enmDir == PDMAUDIODIR_IN)
     1731                {
     1732                    pThis->cStreamsFreeIn++;
     1733                }
     1734                else /* Out */
     1735                {
     1736                    pThis->cStreamsFreeOut++;
     1737                }
     1738            }
     1739        }
     1740    }
     1741    else
     1742        rc = VERR_WRONG_ORDER;
     1743
     1744    int rc2 = RTCritSectLeave(&pThis->CritSect);
     1745    if (RT_SUCCESS(rc))
     1746        rc = rc2;
     1747
     1748    if (RT_FAILURE(rc))
     1749        LogFlowFunc(("Failed with %Rrc\n", rc));
     1750
     1751    return rc;
     1752}
     1753
     1754static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream)
     1755{
     1756    AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
     1757    AssertPtrReturn(pHstStream, VERR_INVALID_POINTER);
     1758
     1759    int rc = VINF_SUCCESS;
     1760
     1761    LogFlowFunc(("%s: fStatus=0x%x\n", pHstStream->szName, pHstStream->fStatus));
     1762
     1763    AssertMsg(pHstStream->enmCtx == PDMAUDIOSTREAMCTX_HOST,
     1764              ("Stream '%s' is not a host stream and therefore has no backend\n", pHstStream->szName));
     1765
     1766    if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
     1767    {
     1768        rc = drvAudioStreamControlInternal(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     1769        if (RT_SUCCESS(rc))
     1770        {
     1771            rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pHstStream);
     1772            if (RT_SUCCESS(rc))
     1773                pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
     1774        }
     1775
     1776        AssertMsgRC(rc, ("Host stream '%s' failed to uninit in backend: %Rrc\n",  pHstStream->szName, rc));
     1777    }
     1778    else
     1779        rc = VINF_SUCCESS;
     1780
     1781    LogFlowFunc(("%s: Returning %Rrc\n", pHstStream->szName, rc));
     1782    return rc;
     1783}
     1784
     1785static int drvAudioStreamDestroyInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
     1786{
     1787    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1788    /* pStream is optional. */
     1789
     1790    if (!pStream)
     1791        return VINF_SUCCESS;
     1792
     1793    LogFlowFunc(("%s: cRefs=%RU32\n", pStream->szName, pStream->cRefs));
     1794
     1795    int rc = VINF_SUCCESS;
     1796
     1797    if (pStream->cRefs <= 1)
     1798    {
     1799        /* Unlink from pair. */
     1800        if (pStream->pPair)
     1801        {
     1802            pStream->pPair->pPair = NULL;
     1803            pStream->pPair = NULL;
     1804        }
     1805
     1806        /* Destroy mixing buffer. */
     1807        AudioMixBufDestroy(&pStream->MixBuf);
     1808
     1809        /* Remove from list. */
     1810        RTListNodeRemove(&pStream->Node);
     1811
     1812        RTMemFree(pStream);
     1813        pStream = NULL;
     1814    }
     1815    else /* More than our own reference left? Bail out. */
     1816        rc = VERR_WRONG_ORDER;
     1817
     1818    if (RT_FAILURE(rc))
     1819        LogFunc(("Failed with %Rrc\n", rc));
     1820
     1821    return rc;
    19991822}
    20001823
     
    20281851    LogFlowFuncEnter();
    20291852
    2030     /* First, disable all streams. */
    2031     drvAudioStateHandler(pDrvIns, PDMAUDIOSTREAMCMD_DISABLE);
    2032 
    2033     int rc2;
    2034 
    2035     PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL;
    2036     while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut)))
    2037     {
    2038         if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
    2039         {
    2040             rc2 = pThis->pHostDrvAudio->pfnFiniOut
    2041                 ? pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut) : VINF_SUCCESS;
    2042             if (RT_SUCCESS(rc2))
    2043                 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
    2044         }
    2045         else
    2046             rc2 = VINF_SUCCESS;
    2047 
    2048         AssertMsgRC(rc2, ("Host output stream %p failed to uninit: %Rrc\n",  pHstStrmOut, rc2));
    2049     }
    2050 
    2051     PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL;
    2052     while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn)))
    2053     {
    2054         if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
    2055         {
    2056             rc2 = pThis->pHostDrvAudio->pfnFiniIn
    2057                 ? pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio, pHstStrmIn) : VINF_SUCCESS;
    2058             if (RT_SUCCESS(rc2))
    2059                 pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
    2060         }
    2061         else
    2062             rc2 = VINF_SUCCESS;
    2063 
    2064         AssertMsgRC(rc2, ("Host input stream %p failed to uninit: %Rrc\n",  pHstStrmIn, rc2));
     1853    /*
     1854     * Second, destroy all audio streams.
     1855     */
     1856    PPDMAUDIOSTREAM pStream;
     1857    RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node)
     1858    {
     1859        if (pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST)
     1860            drvAudioStreamDestroyInternalBackend(pThis, pStream);
    20651861    }
    20661862
     
    20921888     * Init the static parts.
    20931889     */
    2094     pThis->pDrvIns                                   = pDrvIns;
     1890    pThis->pDrvIns                              = pDrvIns;
    20951891    /* IBase. */
    2096     pDrvIns->IBase.pfnQueryInterface                 = drvAudioQueryInterface;
     1892    pDrvIns->IBase.pfnQueryInterface            = drvAudioQueryInterface;
    20971893    /* IAudioConnector. */
    2098     pThis->IAudioConnector.pfnAddRefIn               = drvAudioAddRefIn;
    2099     pThis->IAudioConnector.pfnAddRefOut              = drvAudioAddRefOut;
    2100     pThis->IAudioConnector.pfnReleaseIn              = drvAudioReleaseIn;
    2101     pThis->IAudioConnector.pfnReleaseOut             = drvAudioReleaseOut;
    2102     pThis->IAudioConnector.pfnRead                   = drvAudioRead;
    2103     pThis->IAudioConnector.pfnWrite                  = drvAudioWrite;
    2104     pThis->IAudioConnector.pfnGetConfig              = drvAudioGetConfig;
    2105     pThis->IAudioConnector.pfnGetDataIn              = drvAudioGetDataIn;
    2106     pThis->IAudioConnector.pfnGetDataOut             = drvAudioGetDataOut;
    2107     pThis->IAudioConnector.pfnIsActiveIn             = drvAudioIsActiveIn;
    2108     pThis->IAudioConnector.pfnIsActiveOut            = drvAudioIsActiveOut;
    2109     pThis->IAudioConnector.pfnIsValidIn              = drvAudioIsValidIn;
    2110     pThis->IAudioConnector.pfnIsValidOut             = drvAudioIsValidOut;
    2111     pThis->IAudioConnector.pfnEnableOut              = drvAudioEnableOut;
    2112     pThis->IAudioConnector.pfnEnableIn               = drvAudioEnableIn;
    2113     pThis->IAudioConnector.pfnDestroyIn              = drvAudioDestroyIn;
    2114     pThis->IAudioConnector.pfnDestroyOut             = drvAudioDestroyOut;
    2115     pThis->IAudioConnector.pfnCreateIn               = drvAudioCreateIn;
    2116     pThis->IAudioConnector.pfnCreateOut              = drvAudioCreateOut;
    2117     pThis->IAudioConnector.pfnPlayOut                = drvAudioPlayOut;
     1894    pThis->IAudioConnector.pfnGetConfig         = drvAudioGetConfig;
     1895    pThis->IAudioConnector.pfnStreamCreate      = drvAudioStreamCreate;
     1896    pThis->IAudioConnector.pfnStreamDestroy     = drvAudioStreamDestroy;
     1897    pThis->IAudioConnector.pfnStreamAddRef      = drvAudioStreamAddRef;
     1898    pThis->IAudioConnector.pfnStreamRelease     = drvAudioStreamRelease;
     1899    pThis->IAudioConnector.pfnStreamControl     = drvAudioStreamControl;
     1900    pThis->IAudioConnector.pfnStreamRead        = drvAudioStreamRead;
     1901    pThis->IAudioConnector.pfnStreamWrite       = drvAudioStreamWrite;
     1902    pThis->IAudioConnector.pfnStreamGetData     = drvAudioStreamGetData;
     1903    pThis->IAudioConnector.pfnStreamGetStatus   = drvAudioStreamGetStatus;
     1904    pThis->IAudioConnector.pfnStreamPlay        = drvAudioStreamPlay;
    21181905#ifdef VBOX_WITH_AUDIO_CALLBACKS
    2119     pThis->IAudioConnector.pfnRegisterCallbacks      = drvAudioRegisterCallbacks;
    2120     pThis->IAudioConnector.pfnCallback               = drvAudioCallback;
     1906    pThis->IAudioConnector.pfnRegisterCallbacks = drvAudioRegisterCallbacks;
     1907    pThis->IAudioConnector.pfnCallback          = drvAudioCallback;
    21211908#endif
    21221909
     
    21591946static DECLCALLBACK(void) drvAudioDestruct(PPDMDRVINS pDrvIns)
    21601947{
    2161     LogFlowFuncEnter();
    2162 
    21631948    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
    21641949    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
     1950
     1951    LogFlowFuncEnter();
    21651952
    21661953    int rc2 = RTCritSectEnter(&pThis->CritSect);
     
    21731960     *       do this in drvAudioPowerOff() instead.
    21741961     */
    2175 
    2176     /*
    2177      * Destroy all host input streams.
    2178      */
    2179     PPDMAUDIOHSTSTRMIN pHstStrmIn, pHstStrmInNext;
    2180     RTListForEachSafe(&pThis->lstHstStrmIn, pHstStrmIn, pHstStrmInNext, PDMAUDIOHSTSTRMIN, Node)
    2181     {
    2182         rc2 = drvAudioDestroyHstIn(pThis, pHstStrmIn);
    2183         AssertRC(rc2);
    2184     }
    2185 
    2186     /*
    2187      * Destroy all host input streams.
    2188      */
    2189     PPDMAUDIOHSTSTRMOUT pHstStrmOut, pHstStrmOutNext;
    2190     RTListForEachSafe(&pThis->lstHstStrmOut, pHstStrmOut, pHstStrmOutNext, PDMAUDIOHSTSTRMOUT, Node)
    2191     {
    2192         rc2 = drvAudioDestroyHstOut(pThis, pHstStrmOut);
    2193         AssertRC(rc2);
    2194     }
     1962    PPDMAUDIOSTREAM pStream, pStreamNext;
     1963    RTListForEachSafe(&pThis->lstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, Node)
     1964        drvAudioStreamDestroyInternal(pThis, pStream);
    21951965
    21961966    /* Sanity. */
    2197     Assert(RTListIsEmpty(&pThis->lstHstStrmIn));
    2198     Assert(RTListIsEmpty(&pThis->lstHstStrmOut));
     1967    Assert(RTListIsEmpty(&pThis->lstStreams));
    21991968
    22001969#ifdef VBOX_WITH_AUDIO_CALLBACKS
  • trunk/src/VBox/Devices/Audio/DrvAudio.h

    r61050 r61157  
    9090    /** Pointer to audio driver below us. */
    9191    PPDMIHOSTAUDIO          pHostDrvAudio;
    92     /** List of host input streams. */
    93     RTLISTANCHOR            lstHstStrmIn;
    94     /** List of host output streams. */
    95     RTLISTANCHOR            lstHstStrmOut;
     92    /** List of input/output audio streams. */
     93    RTLISTANCHOR            lstStreams;
    9694    /** Max. number of free input streams.
    9795     *  UINT32_MAX for unlimited streams. */
     
    119117const char *DrvAudRecSrcToStr(PDMAUDIORECSOURCE enmRecSource);
    120118void DrvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg);
     119bool DrvAudioStreamCfgIsValid(PPDMAUDIOSTREAMCFG pCfg);
    121120int DrvAudioStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMPCMPROPS pProps);
    122121PDMAUDIOFMT DrvAudioStrToAudFmt(const char *pszFmt);
  • trunk/src/VBox/Devices/Audio/DrvAudioCommon.cpp

    r61050 r61157  
    205205bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg)
    206206{
    207     AssertPtrReturn(pProps, VERR_INVALID_POINTER);
    208     AssertPtrReturn(pCfg,   VERR_INVALID_POINTER);
     207    AssertPtrReturn(pProps, false);
     208    AssertPtrReturn(pCfg,   false);
    209209
    210210    int cBits = 8;
     
    245245bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps1, PPDMPCMPROPS pProps2)
    246246{
    247     AssertPtrReturn(pProps1, VERR_INVALID_POINTER);
    248     AssertPtrReturn(pProps2, VERR_INVALID_POINTER);
     247    AssertPtrReturn(pProps1, false);
     248    AssertPtrReturn(pProps2, false);
    249249
    250250    return    pProps1->uHz         == pProps2->uHz
     
    253253           && pProps1->cBits       == pProps2->cBits
    254254           && pProps1->fSwapEndian == pProps2->fSwapEndian;
     255}
     256
     257bool DrvAudioStreamCfgIsValid(PPDMAUDIOSTREAMCFG pCfg)
     258{
     259    bool fValid = (   pCfg->cChannels == 1
     260                   || pCfg->cChannels == 2); /* Either stereo (2) or mono (1), per stream. */
     261
     262    fValid |= (   pCfg->enmEndianness == PDMAUDIOENDIANNESS_LITTLE
     263               || pCfg->enmEndianness == PDMAUDIOENDIANNESS_BIG);
     264
     265    fValid |= (   pCfg->enmDir == PDMAUDIODIR_IN
     266               || pCfg->enmDir == PDMAUDIODIR_OUT);
     267
     268    if (fValid)
     269    {
     270        switch (pCfg->enmFormat)
     271        {
     272            case PDMAUDIOFMT_S8:
     273            case PDMAUDIOFMT_U8:
     274            case PDMAUDIOFMT_S16:
     275            case PDMAUDIOFMT_U16:
     276            case PDMAUDIOFMT_S32:
     277            case PDMAUDIOFMT_U32:
     278                break;
     279            default:
     280                fValid = false;
     281                break;
     282        }
     283    }
     284
     285    /** @todo Check for defined frequencies supported. */
     286    fValid |= pCfg->uHz > 0;
     287
     288    return fValid;
    255289}
    256290
  • trunk/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp

    r60925 r61157  
    7878typedef struct ALSAAUDIOSTREAMIN
    7979{
    80     PDMAUDIOHSTSTRMIN   pStreamIn;
     80    /** Associated host input stream.
     81     *  Note: Always must come first! */
     82    PDMAUDIOSTREAM      Stream;
    8183    snd_pcm_t          *phPCM;
    8284    void               *pvBuf;
     
    8688typedef struct ALSAAUDIOSTREAMOUT
    8789{
    88     PDMAUDIOHSTSTRMOUT  pStreamOut;
     90    /** Associated host output stream.
     91     *  Note: Always must come first! */
     92    PDMAUDIOSTREAM      Stream;
    8993    snd_pcm_t          *phPCM;
    9094    void               *pvBuf;
     
    778782}
    779783
    780 static DECLCALLBACK(int) drvHostALSAAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    781                                                    uint32_t *pcSamplesCaptured)
     784static DECLCALLBACK(int) drvHostALSAAudioStreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     785                                                       uint32_t *pcSamplesCaptured)
    782786{
    783787    NOREF(pInterface);
    784     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    785 
    786     PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;
     788    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     789
     790    PALSAAUDIOSTREAMIN pThisStream = (PALSAAUDIOSTREAMIN)pStream;
    787791
    788792    snd_pcm_sframes_t cAvail;
    789     int rc = alsaStreamGetAvail(pThisStrmIn->phPCM, &cAvail);
     793    int rc = alsaStreamGetAvail(pThisStream->phPCM, &cAvail);
    790794    if (RT_FAILURE(rc))
    791795    {
     
    796800    if (!cAvail) /* No data yet? */
    797801    {
    798         snd_pcm_state_t state = snd_pcm_state(pThisStrmIn->phPCM);
     802        snd_pcm_state_t state = snd_pcm_state(pThisStream->phPCM);
    799803        switch (state)
    800804        {
    801805            case SND_PCM_STATE_PREPARED:
    802                 cAvail = AudioMixBufFree(&pHstStrmIn->MixBuf);
     806                cAvail = AudioMixBufFree(&pStream->MixBuf);
    803807                break;
    804808
    805809            case SND_PCM_STATE_SUSPENDED:
    806810            {
    807                 rc = alsaStreamResume(pThisStrmIn->phPCM);
     811                rc = alsaStreamResume(pThisStream->phPCM);
    808812                if (RT_FAILURE(rc))
    809813                    break;
     
    831835     */
    832836    Assert(cAvail);
    833     size_t cbMixFree = AudioMixBufFreeBytes(&pHstStrmIn->MixBuf);
    834     size_t cbToRead = RT_MIN((size_t)AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cAvail), cbMixFree);
     837    size_t cbMixFree = AudioMixBufFreeBytes(&pStream->MixBuf);
     838    size_t cbToRead = RT_MIN((size_t)AUDIOMIXBUF_S2B(&pStream->MixBuf, cAvail), cbMixFree);
    835839
    836840    LogFlowFunc(("cbToRead=%zu, cAvail=%RI32\n", cbToRead, cAvail));
     
    843847           && RT_SUCCESS(rc))
    844848    {
    845         cToRead = RT_MIN(AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cbToRead),
    846                          AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, pThisStrmIn->cbBuf));
     849        cToRead = RT_MIN(AUDIOMIXBUF_B2S(&pStream->MixBuf, cbToRead),
     850                         AUDIOMIXBUF_B2S(&pStream->MixBuf, pThisStream->cbBuf));
    847851        AssertBreakStmt(cToRead, rc = VERR_NO_DATA);
    848         cRead = snd_pcm_readi(pThisStrmIn->phPCM, pThisStrmIn->pvBuf, cToRead);
     852        cRead = snd_pcm_readi(pThisStream->phPCM, pThisStream->pvBuf, cToRead);
    849853        if (cRead <= 0)
    850854        {
     
    871875                case -EPIPE:
    872876                {
    873                     rc = alsaStreamRecover(pThisStrmIn->phPCM);
     877                    rc = alsaStreamRecover(pThisStream->phPCM);
    874878                    if (RT_FAILURE(rc))
    875879                        break;
     
    890894        {
    891895            uint32_t cWritten;
    892             rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf,
    893                                       pThisStrmIn->pvBuf, AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cRead),
     896            rc = AudioMixBufWriteCirc(&pStream->MixBuf,
     897                                      pThisStream->pvBuf, AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead),
    894898                                      &cWritten);
    895899            if (RT_FAILURE(rc))
     
    903907            AssertLogRelMsgBreakStmt(cWritten > 0, ("Mixer buffer shouldn't be full at this point!\n"),
    904908                                     rc = VERR_INTERNAL_ERROR);
    905             uint32_t cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cWritten);
     909            uint32_t cbWritten = AUDIOMIXBUF_S2B(&pStream->MixBuf, cWritten);
    906910
    907911            Assert(cbToRead >= cbWritten);
     
    915919        uint32_t cProcessed = 0;
    916920        if (cWrittenTotal)
    917             rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal,
     921            rc = AudioMixBufMixToParent(&pStream->MixBuf, cWrittenTotal,
    918922                                        &cProcessed);
    919923
     
    929933}
    930934
    931 static DECLCALLBACK(int) drvHostALSAAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
    932                                                  uint32_t *pcSamplesPlayed)
     935static DECLCALLBACK(int) drvHostALSAAudioStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     936                                                    uint32_t *pcSamplesPlayed)
    933937{
    934938    NOREF(pInterface);
    935     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    936 
    937     PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;
     939    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     940
     941    PALSAAUDIOSTREAMOUT pThisStream = (PALSAAUDIOSTREAMOUT)pStream;
    938942
    939943    int rc = VINF_SUCCESS;
     
    943947    {
    944948        snd_pcm_sframes_t cAvail;
    945         rc = alsaStreamGetAvail(pThisStrmOut->phPCM, &cAvail);
     949        rc = alsaStreamGetAvail(pThisStream->phPCM, &cAvail);
    946950        if (RT_FAILURE(rc))
    947951        {
     
    950954        }
    951955
    952         size_t cbToRead = RT_MIN(AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf,
     956        size_t cbToRead = RT_MIN(AUDIOMIXBUF_S2B(&pStream->MixBuf,
    953957                                                 (uint32_t)cAvail), /* cAvail is always >= 0 */
    954                                  AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf,
    955                                                  AudioMixBufAvail(&pHstStrmOut->MixBuf)));
     958                                 AUDIOMIXBUF_S2B(&pStream->MixBuf,
     959                                                 AudioMixBufAvail(&pStream->MixBuf)));
    956960        LogFlowFunc(("cbToRead=%zu, cbAvail=%zu\n",
    957                      cbToRead, AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cAvail)));
     961                     cbToRead, AUDIOMIXBUF_S2B(&pStream->MixBuf, cAvail)));
    958962
    959963        uint32_t cRead, cbRead;
     
    961965        while (cbToRead)
    962966        {
    963             rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pThisStrmOut->pvBuf, cbToRead, &cRead);
     967            rc = AudioMixBufReadCirc(&pStream->MixBuf, pThisStream->pvBuf, cbToRead, &cRead);
    964968            if (RT_FAILURE(rc))
    965969                break;
    966970
    967             cbRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead);
     971            cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead);
    968972            AssertBreak(cbRead);
    969973
     
    972976            for (iTry = 0; iTry < ALSA_RECOVERY_TRIES_MAX; iTry++)
    973977            {
    974                 cWritten = snd_pcm_writei(pThisStrmOut->phPCM, pThisStrmOut->pvBuf, cRead);
     978                cWritten = snd_pcm_writei(pThisStream->phPCM, pThisStream->pvBuf, cRead);
    975979                if (cWritten <= 0)
    976980                {
     
    986990                        case -EPIPE:
    987991                        {
    988                             rc = alsaStreamRecover(pThisStrmOut->phPCM);
     992                            rc = alsaStreamRecover(pThisStream->phPCM);
    989993                            if (RT_FAILURE(rc))
    990994                                break;
     
    9971001                        {
    9981002                            /* Stream was suspended and waiting for a recovery. */
    999                             rc = alsaStreamResume(pThisStrmOut->phPCM);
     1003                            rc = alsaStreamResume(pThisStream->phPCM);
    10001004                            if (RT_FAILURE(rc))
    10011005                            {
     
    10351039    if (RT_SUCCESS(rc))
    10361040    {
    1037         uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cbReadTotal);
     1041        uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pStream->MixBuf, cbReadTotal);
    10381042        if (cReadTotal)
    1039             AudioMixBufFinish(&pHstStrmOut->MixBuf, cReadTotal);
     1043            AudioMixBufFinish(&pStream->MixBuf, cReadTotal);
    10401044
    10411045        if (pcSamplesPlayed)
     
    10501054}
    10511055
    1052 static DECLCALLBACK(int) drvHostALSAAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
     1056static int alsaDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    10531057{
    10541058    NOREF(pInterface);
    1055     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    1056 
    1057     PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;
    1058 
    1059     alsaStreamClose(&pThisStrmIn->phPCM);
    1060 
    1061     if (pThisStrmIn->pvBuf)
    1062     {
    1063         RTMemFree(pThisStrmIn->pvBuf);
    1064         pThisStrmIn->pvBuf = NULL;
     1059    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     1060
     1061    PALSAAUDIOSTREAMIN pThisStream = (PALSAAUDIOSTREAMIN)pStream;
     1062
     1063    alsaStreamClose(&pThisStream->phPCM);
     1064
     1065    if (pThisStream->pvBuf)
     1066    {
     1067        RTMemFree(pThisStream->pvBuf);
     1068        pThisStream->pvBuf = NULL;
    10651069    }
    10661070
     
    10681072}
    10691073
    1070 static DECLCALLBACK(int) drvHostALSAAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
     1074static int alsaDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    10711075{
    10721076    NOREF(pInterface);
    1073     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    1074 
    1075     PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;
    1076 
    1077     alsaStreamClose(&pThisStrmOut->phPCM);
    1078 
    1079     if (pThisStrmOut->pvBuf)
    1080     {
    1081         RTMemFree(pThisStrmOut->pvBuf);
    1082         pThisStrmOut->pvBuf = NULL;
     1077    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     1078
     1079    PALSAAUDIOSTREAMOUT pThisStream = (PALSAAUDIOSTREAMOUT)pStream;
     1080
     1081    alsaStreamClose(&pThisStream->phPCM);
     1082
     1083    if (pThisStream->pvBuf)
     1084    {
     1085        RTMemFree(pThisStream->pvBuf);
     1086        pThisStream->pvBuf = NULL;
    10831087    }
    10841088
     
    10861090}
    10871091
    1088 static DECLCALLBACK(int) drvHostALSAAudioInitOut(PPDMIHOSTAUDIO pInterface,
    1089                                                  PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,
    1090                                                  uint32_t *pcSamples)
     1092static int alsaCreateStreamOut(PPDMIHOSTAUDIO pInterface,
     1093                               PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg,
     1094                               uint32_t *pcSamples)
    10911095{
    10921096    NOREF(pInterface);
    1093     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
     1097    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    10941098    AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    10951099
    1096     PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;
     1100    PALSAAUDIOSTREAMOUT pThisStream = (PALSAAUDIOSTREAMOUT)pStream;
    10971101    snd_pcm_t *phPCM = NULL;
    10981102
     
    11251129        streamCfg.enmEndianness = enmEnd;
    11261130
    1127         rc = DrvAudioStreamCfgToProps(&streamCfg, &pHstStrmOut->Props);
     1131        rc = DrvAudioStreamCfgToProps(&streamCfg, &pStream->Props);
    11281132        if (RT_FAILURE(rc))
    11291133            break;
    11301134
    11311135        AssertBreakStmt(obt.samples, rc = VERR_INVALID_PARAMETER);
    1132         size_t cbBuf = obt.samples * (1 << pHstStrmOut->Props.cShift);
     1136        size_t cbBuf = obt.samples * (1 << pStream->Props.cShift);
    11331137        AssertBreakStmt(cbBuf, rc = VERR_INVALID_PARAMETER);
    1134         pThisStrmOut->pvBuf = RTMemAlloc(cbBuf);
    1135         if (!pThisStrmOut->pvBuf)
     1138        pThisStream->pvBuf = RTMemAlloc(cbBuf);
     1139        if (!pThisStream->pvBuf)
    11361140        {
    11371141            LogRel(("ALSA: Not enough memory for output DAC buffer (%RU32 samples, each %d bytes)\n",
    1138                     obt.samples, 1 << pHstStrmOut->Props.cShift));
     1142                    obt.samples, 1 << pStream->Props.cShift));
    11391143            rc = VERR_NO_MEMORY;
    11401144            break;
    11411145        }
    11421146
    1143         pThisStrmOut->cbBuf       = cbBuf;
    1144         pThisStrmOut->phPCM       = phPCM;
     1147        pThisStream->cbBuf       = cbBuf;
     1148        pThisStream->phPCM       = phPCM;
    11451149
    11461150        if (pcSamples)
     
    11561160}
    11571161
    1158 static DECLCALLBACK(int) drvHostALSAAudioInitIn(PPDMIHOSTAUDIO pInterface,
    1159                                                 PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg,
    1160                                                 PDMAUDIORECSOURCE enmRecSource,
    1161                                                 uint32_t *pcSamples)
     1162static int alsaCreateStreamIn(PPDMIHOSTAUDIO pInterface,
     1163                              PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
    11621164{
    11631165    NOREF(pInterface);
    1164     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
     1166    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    11651167    AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    11661168
    11671169    int rc;
    11681170
    1169     PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;
     1171    PALSAAUDIOSTREAMIN pThisStream = (PALSAAUDIOSTREAMIN)pStream;
    11701172    snd_pcm_t *phPCM = NULL;
    11711173
     
    11961198        streamCfg.enmEndianness = enmEnd;
    11971199
    1198         rc = DrvAudioStreamCfgToProps(&streamCfg, &pHstStrmIn->Props);
     1200        rc = DrvAudioStreamCfgToProps(&streamCfg, &pStream->Props);
    11991201        if (RT_FAILURE(rc))
    12001202            break;
    12011203
    12021204        AssertBreakStmt(obt.samples, rc = VERR_INVALID_PARAMETER);
    1203         size_t cbBuf = obt.samples * (1 << pHstStrmIn->Props.cShift);
     1205        size_t cbBuf = obt.samples * (1 << pStream->Props.cShift);
    12041206        AssertBreakStmt(cbBuf, rc = VERR_INVALID_PARAMETER);
    1205         pThisStrmIn->pvBuf = RTMemAlloc(cbBuf);
    1206         if (!pThisStrmIn->pvBuf)
     1207        pThisStream->pvBuf = RTMemAlloc(cbBuf);
     1208        if (!pThisStream->pvBuf)
    12071209        {
    12081210            LogRel(("ALSA: Not enough memory for input ADC buffer (%RU32 samples, each %d bytes)\n",
    1209                     obt.samples, 1 << pHstStrmIn->Props.cShift));
     1211                    obt.samples, 1 << pStream->Props.cShift));
    12101212            rc = VERR_NO_MEMORY;
    12111213            break;
    12121214        }
    12131215
    1214         pThisStrmIn->cbBuf       = cbBuf;
    1215         pThisStrmIn->phPCM       = phPCM;
     1216        pThisStream->cbBuf       = cbBuf;
     1217        pThisStream->phPCM       = phPCM;
    12161218
    12171219        if (pcSamples)
     
    12271229}
    12281230
    1229 static DECLCALLBACK(bool) drvHostALSAAudioIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
     1231static int alsaControlStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     1232                               PDMAUDIOSTREAMCMD enmStreamCmd)
    12301233{
    12311234    NOREF(pInterface);
    1232     NOREF(enmDir);
    1233     return true; /* Always all enabled. */
    1234 }
    1235 
    1236 static DECLCALLBACK(int) drvHostALSAAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    1237                                                    PDMAUDIOSTREAMCMD enmStreamCmd)
    1238 {
    1239     NOREF(pInterface);
    1240     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    1241     PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;
     1235    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     1236    PALSAAUDIOSTREAMIN pThisStream = (PALSAAUDIOSTREAMIN)pStream;
    12421237
    12431238    LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
     
    12481243        case PDMAUDIOSTREAMCMD_ENABLE:
    12491244        case PDMAUDIOSTREAMCMD_RESUME:
    1250             rc = drvHostALSAAudioStreamCtl(pThisStrmIn->phPCM, false /* fStop */);
     1245            rc = drvHostALSAAudioStreamCtl(pThisStream->phPCM, false /* fStop */);
    12511246            break;
    12521247
    12531248        case PDMAUDIOSTREAMCMD_DISABLE:
    12541249        case PDMAUDIOSTREAMCMD_PAUSE:
    1255             rc = drvHostALSAAudioStreamCtl(pThisStrmIn->phPCM, true /* fStop */);
     1250            rc = drvHostALSAAudioStreamCtl(pThisStream->phPCM, true /* fStop */);
    12561251            break;
    12571252
     
    12651260}
    12661261
    1267 static DECLCALLBACK(int) drvHostALSAAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
    1268                                                     PDMAUDIOSTREAMCMD enmStreamCmd)
     1262static int alsaControlStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     1263                                PDMAUDIOSTREAMCMD enmStreamCmd)
    12691264{
    12701265    NOREF(pInterface);
    1271     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    1272     PALSAAUDIOSTREAMOUT pThisStrmOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;
     1266    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     1267    PALSAAUDIOSTREAMOUT pThisStream = (PALSAAUDIOSTREAMOUT)pStream;
    12731268
    12741269    LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
     
    12791274        case PDMAUDIOSTREAMCMD_ENABLE:
    12801275        case PDMAUDIOSTREAMCMD_RESUME:
    1281             rc = drvHostALSAAudioStreamCtl(pThisStrmOut->phPCM, false /* fStop */);
     1276            rc = drvHostALSAAudioStreamCtl(pThisStream->phPCM, false /* fStop */);
    12821277            break;
    12831278
    12841279        case PDMAUDIOSTREAMCMD_DISABLE:
    12851280        case PDMAUDIOSTREAMCMD_PAUSE:
    1286             rc = drvHostALSAAudioStreamCtl(pThisStrmOut->phPCM, true /* fStop */);
     1281            rc = drvHostALSAAudioStreamCtl(pThisStream->phPCM, true /* fStop */);
    12871282            break;
    12881283
     
    12961291}
    12971292
    1298 static DECLCALLBACK(int) drvHostALSAAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
     1293static DECLCALLBACK(int) drvHostALSAAudioGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
    12991294{
    13001295    NOREF(pInterface);
     
    13421337            LogRel2(("ALSA: Found %s device: %s\n", pszIOID ?  RTStrToLower(pszIOID) : "bidirectional", pszDev));
    13431338
    1344             /* Special case for PulseAudio. */
     1339            /* Special case for ALSAAudio. */
    13451340            if (   pszDev
    13461341                && RTStrIStr("pulse", pszDev) != NULL)
    1347                 LogRel2(("ALSA: PulseAudio plugin in use\n"));
     1342                LogRel2(("ALSA: ALSAAudio plugin in use\n"));
    13481343
    13491344            if (pszIOID)
     
    13751370{
    13761371    NOREF(pInterface);
     1372}
     1373
     1374static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostALSAAudioGetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
     1375{
     1376    AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN);
     1377
     1378    return PDMAUDIOBACKENDSTS_RUNNING;
     1379}
     1380
     1381static DECLCALLBACK(int) drvHostALSAAudioStreamCreate(PPDMIHOSTAUDIO pInterface,
     1382                                                      PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
     1383{
     1384    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1385    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1386    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
     1387
     1388    int rc;
     1389    if (pCfg->enmDir == PDMAUDIODIR_IN)
     1390        rc = alsaCreateStreamIn(pInterface,  pStream, pCfg, pcSamples);
     1391    else
     1392        rc = alsaCreateStreamOut(pInterface, pStream, pCfg, pcSamples);
     1393
     1394    LogFlowFunc(("%s: rc=%Rrc\n", pStream->szName, rc));
     1395    return rc;
     1396}
     1397
     1398static DECLCALLBACK(int) drvHostALSAAudioStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     1399{
     1400    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1401    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1402
     1403    int rc;
     1404    if (pStream->enmDir == PDMAUDIODIR_IN)
     1405        rc = alsaDestroyStreamIn(pInterface,  pStream);
     1406    else
     1407        rc = alsaDestroyStreamOut(pInterface, pStream);
     1408
     1409    return rc;
     1410}
     1411
     1412static DECLCALLBACK(int) drvHostALSAAudioStreamControl(PPDMIHOSTAUDIO pInterface,
     1413                                                       PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
     1414{
     1415    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1416    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1417
     1418    Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST);
     1419
     1420    int rc;
     1421    if (pStream->enmDir == PDMAUDIODIR_IN)
     1422        rc = alsaControlStreamIn(pInterface,  pStream, enmStreamCmd);
     1423    else
     1424        rc = alsaControlStreamOut(pInterface, pStream, enmStreamCmd);
     1425
     1426    return rc;
     1427}
     1428
     1429static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostALSAAudioStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     1430{
     1431    NOREF(pInterface);
     1432    NOREF(pStream);
     1433
     1434    return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED);
    13771435}
    13781436
     
    13821440static DECLCALLBACK(void *) drvHostALSAAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    13831441{
    1384     PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    1385     PDRVHOSTALSAAUDIO  pThis   = PDMINS_2_DATA(pDrvIns, PDRVHOSTALSAAUDIO);
     1442    PPDMDRVINS        pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
     1443    PDRVHOSTALSAAUDIO pThis   = PDMINS_2_DATA(pDrvIns, PDRVHOSTALSAAUDIO);
    13861444    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
    13871445    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio);
  • trunk/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp

    r60306 r61157  
    1717#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
    1818#include <VBox/log.h>
     19#include <VBox/vmm/pdmaudioifs.h>
    1920
    2021#include "DrvAudio.h"
     
    6667 ******************************************************************************/
    6768
    68 static void drvHostCoreAudioPrintASBDesc(const char *pszDesc, const AudioStreamBasicDescription *pStreamDesc)
     69static void coreAudioPrintASBDesc(const char *pszDesc, const AudioStreamBasicDescription *pStreamDesc)
    6970{
    7071    char pszSampleRate[32];
     
    100101}
    101102
    102 static void drvHostCoreAudioPCMInfoToASBDesc(PDMPCMPROPS *pPcmProperties, AudioStreamBasicDescription *pStreamDesc)
     103static void coreAudioPCMInfoToASBDesc(PDMPCMPROPS *pPcmProperties, AudioStreamBasicDescription *pStreamDesc)
    103104{
    104105    pStreamDesc->mFormatID         = kAudioFormatLinearPCM;
     
    114115}
    115116
    116 static OSStatus drvHostCoreAudioSetFrameBufferSize(AudioDeviceID deviceID, bool fInput, UInt32 cReqSize, UInt32 *pcActSize)
     117static OSStatus coreAudioSetFrameBufferSize(AudioDeviceID deviceID, bool fInput, UInt32 cReqSize, UInt32 *pcActSize)
    117118{
    118119    AudioObjectPropertyScope propScope = fInput
     
    187188}
    188189
    189 DECL_FORCE_INLINE(bool) drvHostCoreAudioIsRunning(AudioDeviceID deviceID)
     190DECL_FORCE_INLINE(bool) coreAudioIsRunning(AudioDeviceID deviceID)
    190191{
    191192    AudioObjectPropertyAddress propAdr = { kAudioDevicePropertyDeviceIsRunning, kAudioObjectPropertyScopeGlobal,
     
    200201}
    201202
    202 static int drvHostCoreAudioCFStringToCString(const CFStringRef pCFString, char **ppszString)
     203static int coreAudioCFStringToCString(const CFStringRef pCFString, char **ppszString)
    203204{
    204205    CFIndex cLen = CFStringGetLength(pCFString) + 1;
     
    214215}
    215216
    216 static AudioDeviceID drvHostCoreAudioDeviceUIDtoID(const char* pszUID)
     217static AudioDeviceID coreAudioDeviceUIDtoID(const char* pszUID)
    217218{
    218219    /* Create a CFString out of our CString. */
     
    263264typedef struct COREAUDIOSTREAMOUT
    264265{
    265     /** Host stream out. */
    266     PDMAUDIOHSTSTRMOUT          streamOut;
     266    /** Host output stream.
     267     *  Note: Always must come first in this structure! */
     268    PDMAUDIOSTREAM              Stream;
    267269    /** Stream description which is default on the device. */
    268270    AudioStreamBasicDescription deviceFormat;
     
    284286typedef struct COREAUDIOSTREAMIN
    285287{
    286     /** Host stream in. */
    287     PDMAUDIOHSTSTRMIN           streamIn;
     288    /** Host input stream.
     289     *  Note: Always must come first in this structure! */
     290    PDMAUDIOSTREAM              Stream;
    288291    /** Stream description which is default on the device. */
    289292    AudioStreamBasicDescription deviceFormat;
     
    312315
    313316
    314 static int coreAudioInitIn(PPDMAUDIOHSTSTRMIN pHstStrmIn, uint32_t *pcSamples);
    315 static int coreAudioReinitIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn);
    316 static int coreAudioInitOut(PPDMAUDIOHSTSTRMOUT pHstStrmOut, uint32_t *pcSamples);
    317 static int coreAudioReinitOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut);
     317static int coreAudioInitIn(PPDMAUDIOSTREAM pStream, uint32_t *pcSamples);
     318static int coreAudioReinitIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream);
     319static int coreAudioInitOut(PPDMAUDIOSTREAM pStream, uint32_t *pcSamples);
     320static int coreAudioReinitOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream);
    318321static OSStatus coreAudioPlaybackAudioDevicePropertyChanged(AudioObjectID propertyID, UInt32 nAddresses, const AudioObjectPropertyAddress properties[], void *pvUser);
    319322static OSStatus coreAudioPlaybackCb(void *pvUser, AudioUnitRenderActionFlags *pActionFlags, const AudioTimeStamp *pAudioTS, UInt32 uBusID, UInt32 cFrames, AudioBufferList* pBufData);
    320323
    321 static int drvHostCoreAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn, PDMAUDIOSTREAMCMD enmStreamCmd);
    322 static int drvHostCoreAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd);
    323 static int drvHostCoreAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn);
    324 static int drvHostCoreAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut);
     324static int coreAudioControlStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd);
     325static int coreAudioControlStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd);
     326static int coreAudioDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream);
     327static int coreAudioDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream);
    325328
    326329/* Callback for getting notified when the default input/output device has been changed. */
     
    404407}
    405408
    406 static int coreAudioReinitIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
     409static int coreAudioReinitIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    407410{
    408411    PPDMDRVINS pDrvIns      = PDMIBASE_2_PDMDRV(pInterface);
    409412    PDRVHOSTCOREAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTCOREAUDIO);
    410413
    411     PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pHstStrmIn;
    412 
    413     int rc = drvHostCoreAudioFiniIn(pInterface, &pStreamIn->streamIn);
     414    PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream;
     415
     416    int rc = coreAudioDestroyStreamIn(pInterface, &pStreamIn->Stream);
    414417    if (RT_SUCCESS(rc))
    415418    {
    416         rc = coreAudioInitIn(&pStreamIn->streamIn, NULL /* pcSamples */);
     419        rc = coreAudioInitIn(&pStreamIn->Stream, NULL /* pcSamples */);
    417420        if (RT_SUCCESS(rc))
    418             rc = drvHostCoreAudioControlIn(pInterface, &pStreamIn->streamIn, PDMAUDIOSTREAMCMD_ENABLE);
     421            rc = coreAudioControlStreamIn(pInterface, &pStreamIn->Stream, PDMAUDIOSTREAMCMD_ENABLE);
    419422    }
    420423
     
    425428}
    426429
    427 static int coreAudioReinitOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
     430static int coreAudioReinitOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    428431{
    429432    PPDMDRVINS pDrvIns      = PDMIBASE_2_PDMDRV(pInterface);
    430433    PDRVHOSTCOREAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTCOREAUDIO);
    431434
    432     PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pHstStrmOut;
    433 
    434     int rc = drvHostCoreAudioFiniOut(pInterface, &pStreamOut->streamOut);
     435    PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream;
     436
     437    int rc = coreAudioDestroyStreamOut(pInterface, &pStreamOut->Stream);
    435438    if (RT_SUCCESS(rc))
    436439    {
    437         rc = coreAudioInitOut(&pStreamOut->streamOut, NULL /* pcSamples */);
     440        rc = coreAudioInitOut(&pStreamOut->Stream, NULL /* pcSamples */);
    438441        if (RT_SUCCESS(rc))
    439             rc = drvHostCoreAudioControlOut(pInterface, &pStreamOut->streamOut, PDMAUDIOSTREAMCMD_ENABLE);
     442            rc = coreAudioControlStreamOut(pInterface, &pStreamOut->Stream, PDMAUDIOSTREAMCMD_ENABLE);
    440443    }
    441444
     
    545548{
    546549    PCOREAUDIOSTREAMIN pStreamIn  = (PCOREAUDIOSTREAMIN)pvUser;
    547     PPDMAUDIOHSTSTRMIN pHstStrmIN = &pStreamIn->streamIn;
     550    PPDMAUDIOSTREAM pStream = &pStreamIn->Stream;
    548551
    549552    if (ASMAtomicReadU32(&pStreamIn->status) != CA_STATUS_INIT)
     
    708711
    709712/** @todo Eventually split up this function, as this already is huge! */
    710 static int coreAudioInitIn(PPDMAUDIOHSTSTRMIN pHstStrmIn, uint32_t *pcSamples)
     713static int coreAudioInitIn(PPDMAUDIOSTREAM pStream, uint32_t *pcSamples)
    711714{
    712715    OSStatus err = noErr;
    713716
    714     PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pHstStrmIn;
     717    PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream;
    715718
    716719    ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_IN_INIT);
     
    743746    {
    744747        char *pszDevName = NULL;
    745         err = drvHostCoreAudioCFStringToCString(strTemp, &pszDevName);
     748        err = coreAudioCFStringToCString(strTemp, &pszDevName);
    746749        if (err == noErr)
    747750        {
     
    754757            {
    755758                char *pszUID = NULL;
    756                 err = drvHostCoreAudioCFStringToCString(strTemp, &pszUID);
     759                err = coreAudioCFStringToCString(strTemp, &pszUID);
    757760                if (err == noErr)
    758761                {
     
    783786
    784787    /* Set the frame buffer size and honor any minimum/maximum restrictions on the device. */
    785     err = drvHostCoreAudioSetFrameBufferSize(pStreamIn->deviceID, true /* fInput */, cFrames, &cFrames);
     788    err = coreAudioSetFrameBufferSize(pStreamIn->deviceID, true /* fInput */, cFrames, &cFrames);
    786789    if (err != noErr)
    787790    {
     
    871874
    872875    /* Create an AudioStreamBasicDescription based on our required audio settings. */
    873     drvHostCoreAudioPCMInfoToASBDesc(&pStreamIn->streamIn.Props, &pStreamIn->streamFormat);
    874 
    875     drvHostCoreAudioPrintASBDesc("CoreAudio: Input device", &pStreamIn->deviceFormat);
    876     drvHostCoreAudioPrintASBDesc("CoreAudio: Input stream", &pStreamIn->streamFormat);
     876    coreAudioPCMInfoToASBDesc(&pStreamIn->Stream.Props, &pStreamIn->streamFormat);
     877
     878    coreAudioPrintASBDesc("CoreAudio: Input device", &pStreamIn->deviceFormat);
     879    coreAudioPrintASBDesc("CoreAudio: Input stream", &pStreamIn->streamFormat);
    877880
    878881    /* If the frequency of the device is different from the requested one we
     
    10371040    /* Create the internal ring buffer. */
    10381041    if (RT_SUCCESS(rc))
    1039         rc = RTCircBufCreate(&pStreamIn->pBuf, cSamples << pHstStrmIn->Props.cShift);
     1042        rc = RTCircBufCreate(&pStreamIn->pBuf, cSamples << pStream->Props.cShift);
    10401043    if (RT_SUCCESS(rc))
    10411044    {
     
    10801083
    10811084/** @todo Eventually split up this function, as this already is huge! */
    1082 static int coreAudioInitOut(PPDMAUDIOHSTSTRMOUT pHstStrmOut, uint32_t *pcSamples)
    1083 {
    1084     PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pHstStrmOut;
     1085static int coreAudioInitOut(PPDMAUDIOSTREAM pStream, uint32_t *pcSamples)
     1086{
     1087    PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream;
    10851088
    10861089    ASMAtomicXchgU32(&pStreamOut->status, CA_STATUS_IN_INIT);
     
    11151118    {
    11161119        char *pszDevName = NULL;
    1117         err = drvHostCoreAudioCFStringToCString(strTemp, &pszDevName);
     1120        err = coreAudioCFStringToCString(strTemp, &pszDevName);
    11181121        if (err == noErr)
    11191122        {
     
    11261129            {
    11271130                char *pszUID = NULL;
    1128                 err = drvHostCoreAudioCFStringToCString(strTemp, &pszUID);
     1131                err = coreAudioCFStringToCString(strTemp, &pszUID);
    11291132                if (err == noErr)
    11301133                {
     
    11551158
    11561159    /* Set the frame buffer size and honor any minimum/maximum restrictions on the device. */
    1157     err = drvHostCoreAudioSetFrameBufferSize(pStreamOut->deviceID, false /* fInput */, cFrames, &cFrames);
     1160    err = coreAudioSetFrameBufferSize(pStreamOut->deviceID, false /* fInput */, cFrames, &cFrames);
    11581161    if (err != noErr)
    11591162    {
     
    12311234
    12321235    /* Create an AudioStreamBasicDescription based on our required audio settings. */
    1233     drvHostCoreAudioPCMInfoToASBDesc(&pStreamOut->streamOut.Props, &pStreamOut->streamFormat);
    1234 
    1235     drvHostCoreAudioPrintASBDesc("CoreAudio: Output device", &pStreamOut->deviceFormat);
    1236     drvHostCoreAudioPrintASBDesc("CoreAudio: Output format", &pStreamOut->streamFormat);
     1236    coreAudioPCMInfoToASBDesc(&pStreamOut->Stream.Props, &pStreamOut->streamFormat);
     1237
     1238    coreAudioPrintASBDesc("CoreAudio: Output device", &pStreamOut->deviceFormat);
     1239    coreAudioPrintASBDesc("CoreAudio: Output format", &pStreamOut->streamFormat);
    12371240
    12381241    /* Set the new output format description for the stream. */
     
    13151318
    13161319    /* Create the internal ring buffer. */
    1317     rc = RTCircBufCreate(&pStreamOut->pBuf, cSamples << pHstStrmOut->Props.cShift);
     1320    rc = RTCircBufCreate(&pStreamOut->pBuf, cSamples << pStream->Props.cShift);
    13181321    if (RT_SUCCESS(rc))
    13191322    {
     
    13931396{
    13941397    PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pvUser;
    1395     PPDMAUDIOHSTSTRMOUT pHstStrmOut = &pStreamOut->streamOut;
     1398    PPDMAUDIOSTREAM pStream        = &pStreamOut->Stream;
    13961399
    13971400    if (ASMAtomicReadU32(&pStreamOut->status) != CA_STATUS_INIT)
     
    14521455}
    14531456
    1454 static DECLCALLBACK(int) drvHostCoreAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    1455                                                    uint32_t *pcSamplesCaptured)
     1457static DECLCALLBACK(int) drvHostCoreAudioCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     1458                                                 uint32_t *pcSamplesCaptured)
    14561459{
    14571460    PPDMDRVINS pDrvIns      = PDMIBASE_2_PDMDRV(pInterface);
    14581461    PDRVHOSTCOREAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTCOREAUDIO);
    14591462
    1460     PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pHstStrmIn;
     1463    PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream;
    14611464
    14621465    size_t csReads = 0;
     
    14661469    /* Check if the audio device should be reinitialized. If so do it. */
    14671470    if (ASMAtomicReadU32(&pStreamIn->status) == CA_STATUS_REINIT)
    1468         coreAudioReinitIn(pInterface, &pStreamIn->streamIn);
     1471        coreAudioReinitIn(pInterface, &pStreamIn->Stream);
    14691472
    14701473    if (ASMAtomicReadU32(&pStreamIn->status) != CA_STATUS_INIT)
     
    14801483    do
    14811484    {
    1482         size_t cbBuf = AudioMixBufSizeBytes(&pHstStrmIn->MixBuf);
     1485        size_t cbBuf = AudioMixBufSizeBytes(&pStream->MixBuf);
    14831486        size_t cbToWrite = RT_MIN(cbBuf, RTCircBufUsed(pStreamIn->pBuf));
    14841487
     
    14991502            }
    15001503
    1501             rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf, puBuf, cbToRead, &cWritten);
     1504            rc = AudioMixBufWriteCirc(&pStream->MixBuf, puBuf, cbToRead, &cWritten);
    15021505            if (   RT_FAILURE(rc)
    15031506                || !cWritten)
     
    15071510            }
    15081511
    1509             cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cWritten);
     1512            cbWritten = AUDIOMIXBUF_S2B(&pStream->MixBuf, cWritten);
    15101513
    15111514            /* Release the read buffer, so it could be used for new data. */
     
    15241527    {
    15251528        uint32_t cCaptured     = 0;
    1526         uint32_t cWrittenTotal = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cbWrittenTotal);
     1529        uint32_t cWrittenTotal = AUDIOMIXBUF_B2S(&pStream->MixBuf, cbWrittenTotal);
    15271530        if (cWrittenTotal)
    1528             rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal, &cCaptured);
     1531            rc = AudioMixBufMixToParent(&pStream->MixBuf, cWrittenTotal, &cCaptured);
    15291532
    15301533        LogFlowFunc(("cWrittenTotal=%RU32 (%RU32 bytes), cCaptured=%RU32, rc=%Rrc\n", cWrittenTotal, cbWrittenTotal, cCaptured, rc));
     
    15381541}
    15391542
    1540 static DECLCALLBACK(int) drvHostCoreAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
    1541                                                  uint32_t *pcSamplesPlayed)
     1543static DECLCALLBACK(int) drvHostCoreAudioPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     1544                                              uint32_t *pcSamplesPlayed)
    15421545{
    15431546    PPDMDRVINS pDrvIns      = PDMIBASE_2_PDMDRV(pInterface);
    15441547    PDRVHOSTCOREAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTCOREAUDIO);
    15451548
    1546     PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pHstStrmOut;
     1549    PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream;
    15471550
    15481551    int rc = VINF_SUCCESS;
     
    15511554    if (ASMAtomicReadU32(&pStreamOut->status) == CA_STATUS_REINIT)
    15521555    {
    1553         rc = coreAudioReinitOut(pInterface, &pStreamOut->streamOut);
     1556        rc = coreAudioReinitOut(pInterface, &pStreamOut->Stream);
    15541557        if (RT_FAILURE(rc))
    15551558            return rc;
     
    15581561    /* Not much else to do here. */
    15591562
    1560     uint32_t cLive = AudioMixBufAvail(&pHstStrmOut->MixBuf);;
     1563    uint32_t cLive = AudioMixBufAvail(&pStream->MixBuf);;
    15611564    if (!cLive) /* Not samples to play? Bail out. */
    15621565    {
     
    15671570
    15681571    uint32_t cbReadTotal = 0;
    1569     uint32_t cAvail = AudioMixBufAvail(&pHstStrmOut->MixBuf);
    1570     size_t cbAvail  = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cAvail);
     1572    uint32_t cAvail = AudioMixBufAvail(&pStream->MixBuf);
     1573    size_t cbAvail  = AUDIOMIXBUF_S2B(&pStream->MixBuf, cAvail);
    15711574    size_t cbToRead = RT_MIN(cbAvail, RTCircBufFree(pStreamOut->pBuf));
    15721575    LogFlowFunc(("cbToRead=%zu\n", cbToRead));
     
    15881591        Assert(cbCopy <= cbToRead);
    15891592
    1590         rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf,
     1593        rc = AudioMixBufReadCirc(&pStream->MixBuf,
    15911594                                 puBuf, cbCopy, &cRead);
    15921595
     
    15981601        }
    15991602
    1600         cbRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead);
     1603        cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead);
    16011604
    16021605        /* Release the ring buffer, so the read thread could start reading this data. */
     
    16101613    if (RT_SUCCESS(rc))
    16111614    {
    1612         uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cbReadTotal);
     1615        uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pStream->MixBuf, cbReadTotal);
    16131616        if (cReadTotal)
    1614             AudioMixBufFinish(&pHstStrmOut->MixBuf, cReadTotal);
     1617            AudioMixBufFinish(&pStream->MixBuf, cReadTotal);
    16151618
    16161619        LogFlowFunc(("cReadTotal=%RU32 (%RU32 bytes)\n", cReadTotal, cbReadTotal));
     
    16231626}
    16241627
    1625 static DECLCALLBACK(int) drvHostCoreAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
    1626                                                     PDMAUDIOSTREAMCMD enmStreamCmd)
    1627 {
    1628     PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pHstStrmOut;
     1628static DECLCALLBACK(int) coreAudioControlStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     1629                                                   PDMAUDIOSTREAMCMD enmStreamCmd)
     1630{
     1631    PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream;
    16291632
    16301633    LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
     
    16461649        {
    16471650            /* Only start the device if it is actually stopped */
    1648             if (!drvHostCoreAudioIsRunning(pStreamOut->deviceID))
     1651            if (!coreAudioIsRunning(pStreamOut->deviceID))
    16491652            {
    16501653                err = AudioUnitReset(pStreamOut->audioUnit, kAudioUnitScope_Input, 0);
     
    16701673        {
    16711674            /* Only stop the device if it is actually running */
    1672             if (drvHostCoreAudioIsRunning(pStreamOut->deviceID))
     1675            if (coreAudioIsRunning(pStreamOut->deviceID))
    16731676            {
    16741677                err = AudioOutputUnitStop(pStreamOut->audioUnit);
     
    16991702}
    17001703
    1701 static DECLCALLBACK(int) drvHostCoreAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    1702                                                    PDMAUDIOSTREAMCMD enmStreamCmd)
    1703 {
    1704     PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pHstStrmIn;
     1704static int coreAudioControlStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     1705                                     PDMAUDIOSTREAMCMD enmStreamCmd)
     1706{
     1707    PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream;
    17051708
    17061709    LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd));
     
    17221725        {
    17231726            /* Only start the device if it is actually stopped */
    1724             if (!drvHostCoreAudioIsRunning(pStreamIn->deviceID))
     1727            if (!coreAudioIsRunning(pStreamIn->deviceID))
    17251728            {
    17261729                RTCircBufReset(pStreamIn->pBuf);
     
    17461749        {
    17471750            /* Only stop the device if it is actually running */
    1748             if (drvHostCoreAudioIsRunning(pStreamIn->deviceID))
     1751            if (coreAudioIsRunning(pStreamIn->deviceID))
    17491752            {
    17501753                err = AudioOutputUnitStop(pStreamIn->audioUnit);
     
    17761779}
    17771780
    1778 static DECLCALLBACK(int) drvHostCoreAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
    1779 {
    1780     PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN) pHstStrmIn;
     1781static int coreAudioDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     1782{
     1783    PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN) pStream;
    17811784
    17821785    PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
     
    17941797    OSStatus err = noErr;
    17951798
    1796     int rc = drvHostCoreAudioControlIn(pInterface, &pStreamIn->streamIn, PDMAUDIOSTREAMCMD_DISABLE);
     1799    int rc = coreAudioControlStreamIn(pInterface, &pStreamIn->Stream, PDMAUDIOSTREAMCMD_DISABLE);
    17971800    if (RT_SUCCESS(rc))
    17981801    {
     
    18781881}
    18791882
    1880 static DECLCALLBACK(int) drvHostCoreAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
     1883static int coreAudioDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    18811884{
    18821885    PPDMDRVINS pDrvIns      = PDMIBASE_2_PDMDRV(pInterface);
    18831886    PDRVHOSTCOREAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTCOREAUDIO);
    18841887
    1885     PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pHstStrmOut;
     1888    PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream;
    18861889
    18871890    LogFlowFuncEnter();
     
    18941897    }
    18951898
    1896     int rc = drvHostCoreAudioControlOut(pInterface, &pStreamOut->streamOut, PDMAUDIOSTREAMCMD_DISABLE);
     1899    int rc = coreAudioControlStreamOut(pInterface, &pStreamOut->Stream, PDMAUDIOSTREAMCMD_DISABLE);
    18971900    if (RT_SUCCESS(rc))
    18981901    {
     
    19651968}
    19661969
    1967 static DECLCALLBACK(int) drvHostCoreAudioInitIn(PPDMIHOSTAUDIO pInterface,
    1968                                                 PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg,
    1969                                                 PDMAUDIORECSOURCE enmRecSource,
    1970                                                 uint32_t *pcSamples)
    1971 {
    1972     PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pHstStrmIn;
     1970static int coreAudioCreateStreamIn(PPDMIHOSTAUDIO pInterface,
     1971                                   PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
     1972{
     1973    PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream;
    19731974
    19741975    LogFlowFunc(("enmRecSource=%ld\n", enmRecSource));
     
    19871988
    19881989    /* Initialize the hardware info section with the audio settings */
    1989     int rc = DrvAudioStreamCfgToProps(pCfg, &pStreamIn->streamIn.Props);
     1990    int rc = DrvAudioStreamCfgToProps(pCfg, &pStreamIn->Stream.Props);
    19901991    if (RT_SUCCESS(rc))
    19911992    {
     
    20022003        }
    20032004#endif
    2004         rc = coreAudioInitIn(&pStreamIn->streamIn, pcSamples);
     2005        rc = coreAudioInitIn(&pStreamIn->Stream, pcSamples);
    20052006    }
    20062007
     
    20282029}
    20292030
    2030 static DECLCALLBACK(int) drvHostCoreAudioInitOut(PPDMIHOSTAUDIO pInterface,
    2031                                                  PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,
    2032                                                  uint32_t *pcSamples)
    2033 {
    2034     PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pHstStrmOut;
     2031static int coreAudioCreateStreamOut(PPDMIHOSTAUDIO pInterface,
     2032                                    PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg,
     2033                                    uint32_t *pcSamples)
     2034{
     2035    PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream;
    20352036
    20362037    LogFlowFuncEnter();
     
    20452046
    20462047    /* Initialize the hardware info section with the audio settings */
    2047     int rc = DrvAudioStreamCfgToProps(pCfg, &pStreamOut->streamOut.Props);
     2048    int rc = DrvAudioStreamCfgToProps(pCfg, &pStreamOut->Stream.Props);
    20482049    if (RT_SUCCESS(rc))
    20492050    {
     
    20622063        }
    20632064#endif
    2064         rc = coreAudioInitOut(pHstStrmOut, pcSamples);
     2065        rc = coreAudioInitOut(pStream, pcSamples);
    20652066    }
    20662067
     
    20882089}
    20892090
    2090 static DECLCALLBACK(bool) drvHostCoreAudioIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
    2091 {
    2092     NOREF(pInterface);
    2093     NOREF(enmDir);
    2094     return true; /* Always all enabled. */
    2095 }
    2096 
    2097 static DECLCALLBACK(int) drvHostCoreAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
     2091static DECLCALLBACK(int) drvHostCoreAudioGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
    20982092{
    20992093    NOREF(pInterface);
     
    21122106
    21132107    return VINF_SUCCESS;
     2108}
     2109
     2110static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostCoreAudioGetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
     2111{
     2112    AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN);
     2113
     2114    return PDMAUDIOBACKENDSTS_RUNNING;
     2115}
     2116
     2117static DECLCALLBACK(int) drvHostCoreAudioStreamCreate(PPDMIHOSTAUDIO pInterface,
     2118                                                       PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
     2119{
     2120    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     2121    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     2122    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
     2123
     2124    int rc;
     2125    if (pCfg->enmDir == PDMAUDIODIR_IN)
     2126        rc = coreAudioCreateStreamIn(pInterface,  pStream, pCfg, pcSamples);
     2127    else
     2128        rc = coreAudioCreateStreamOut(pInterface, pStream, pCfg, pcSamples);
     2129
     2130    LogFlowFunc(("%s: rc=%Rrc\n", pStream->szName, rc));
     2131    return rc;
     2132}
     2133
     2134static DECLCALLBACK(int) drvHostCoreAudioStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     2135{
     2136    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     2137    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     2138
     2139    int rc;
     2140    if (pStream->enmDir == PDMAUDIODIR_IN)
     2141        rc = coreAudioDestroyStreamIn(pInterface,  pStream);
     2142    else
     2143        rc = coreAudioDestroyStreamOut(pInterface, pStream);
     2144
     2145    return rc;
     2146}
     2147
     2148static DECLCALLBACK(int) drvHostCoreAudioStreamControl(PPDMIHOSTAUDIO pInterface,
     2149                                                       PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
     2150{
     2151    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     2152    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     2153
     2154    Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST);
     2155
     2156    int rc;
     2157    if (pStream->enmDir == PDMAUDIODIR_IN)
     2158        rc = coreAudioControlStreamIn(pInterface,  pStream, enmStreamCmd);
     2159    else
     2160        rc = coreAudioControlStreamOut(pInterface, pStream, enmStreamCmd);
     2161
     2162    return rc;
     2163}
     2164
     2165static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostCoreAudioStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     2166{
     2167    NOREF(pInterface);
     2168    NOREF(pStream);
     2169
     2170    return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED);
    21142171}
    21152172
  • trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp

    r60925 r61157  
    9090typedef struct DSOUNDSTREAMOUT
    9191{
    92     PDMAUDIOHSTSTRMOUT   strmOut; /* Always must come first! */
     92    /** Associated host output stream.
     93     *  Note: Always must come first! */
     94    PDMAUDIOSTREAM       Stream;
    9395    LPDIRECTSOUND8       pDS;     /** @todo Move this out of this structure! Not required per-stream (e.g. for multi-channel). */
    9496    LPDIRECTSOUNDBUFFER8 pDSB;
     
    102104typedef struct DSOUNDSTREAMIN
    103105{
    104     PDMAUDIOHSTSTRMIN           strmIn; /* Always must come first! */
     106    /** Associated host input stream.
     107     *  Note: Always must come first! */
     108    PDMAUDIOSTREAM              Stream;
    105109    LPDIRECTSOUNDCAPTURE8       pDSC;
    106110    LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB;
    107111    DWORD                       csCaptureReadPos;
    108112    DWORD                       csCaptureBufferSize;
    109     HRESULT                     hrLastCaptureIn;
     113    HRESULT                     hrLastCapture;
    110114    PDMAUDIORECSOURCE           enmRecSource;
    111115    bool                        fEnabled;
     
    249253
    250254static int dsoundGetPosOut(PDRVHOSTDSOUND   pThis,
    251                            PDSOUNDSTREAMOUT pDSoundStrmOut, DWORD *pdwBuffer, DWORD *pdwFree, DWORD *pdwPlayPos)
    252 {
    253     AssertPtrReturn(pThis,          VERR_INVALID_POINTER);
    254     AssertPtrReturn(pDSoundStrmOut, VERR_INVALID_POINTER);
    255 
    256     LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStrmOut->pDSB;
     255                           PDSOUNDSTREAMOUT pDSoundStream, DWORD *pdwBuffer, DWORD *pdwFree, DWORD *pdwPlayPos)
     256{
     257    AssertPtrReturn(pThis,         VERR_INVALID_POINTER);
     258    AssertPtrReturn(pDSoundStream, VERR_INVALID_POINTER);
     259
     260    LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStream->pDSB;
    257261    if (!pDSB)
    258262        return VERR_INVALID_POINTER;
    259263
    260     DWORD cbBuffer = AUDIOMIXBUF_S2B(&pDSoundStrmOut->strmOut.MixBuf, pDSoundStrmOut->csPlaybackBufferSize);
     264    DWORD cbBuffer = AUDIOMIXBUF_S2B(&pDSoundStream->Stream.MixBuf, pDSoundStream->csPlaybackBufferSize);
    261265
    262266    /* Get the current play position which is used for calculating the free space in the buffer. */
     
    295299
    296300        if (pdwFree)
    297             *pdwFree = cbBuffer - dsoundRingDistance(pDSoundStrmOut->cbPlayWritePos, cbPlayPos, cbBuffer);
     301            *pdwFree = cbBuffer - dsoundRingDistance(pDSoundStream->cbPlayWritePos, cbPlayPos, cbBuffer);
    298302
    299303        if (pdwPlayPos)
     
    465469 */
    466470
    467 static void directSoundPlayInterfaceRelease(PDSOUNDSTREAMOUT pDSoundStrmOut)
    468 {
    469     if (pDSoundStrmOut->pDS)
    470     {
    471         IDirectSound8_Release(pDSoundStrmOut->pDS);
    472         pDSoundStrmOut->pDS = NULL;
    473     }
    474 }
    475 
    476 static HRESULT directSoundPlayInterfaceCreate(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStrmOut)
    477 {
    478     if (pDSoundStrmOut->pDS != NULL)
     471static void directSoundPlayInterfaceRelease(PDSOUNDSTREAMOUT pDSoundStream)
     472{
     473    if (pDSoundStream->pDS)
     474    {
     475        IDirectSound8_Release(pDSoundStream->pDS);
     476        pDSoundStream->pDS = NULL;
     477    }
     478}
     479
     480static HRESULT directSoundPlayInterfaceCreate(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStream)
     481{
     482    if (pDSoundStream->pDS != NULL)
    479483    {
    480484        DSLOG(("DSound: DirectSound instance already exists\n"));
     
    483487
    484488    HRESULT hr = CoCreateInstance(CLSID_DirectSound8, NULL, CLSCTX_ALL,
    485                                   IID_IDirectSound8, (void **)&pDSoundStrmOut->pDS);
     489                                  IID_IDirectSound8, (void **)&pDSoundStream->pDS);
    486490    if (FAILED(hr))
    487491    {
     
    490494    else
    491495    {
    492         hr = IDirectSound8_Initialize(pDSoundStrmOut->pDS, pThis->cfg.pGuidPlay);
     496        hr = IDirectSound8_Initialize(pDSoundStream->pDS, pThis->cfg.pGuidPlay);
    493497        if (SUCCEEDED(hr))
    494498        {
    495499            HWND hWnd = GetDesktopWindow();
    496             hr = IDirectSound8_SetCooperativeLevel(pDSoundStrmOut->pDS, hWnd, DSSCL_PRIORITY);
     500            hr = IDirectSound8_SetCooperativeLevel(pDSoundStream->pDS, hWnd, DSSCL_PRIORITY);
    497501            if (FAILED(hr))
    498502                DSLOGREL(("DSound: Setting cooperative level for window %p failed with %Rhrc\n", hWnd, hr));
     
    506510                DSLOGREL(("DSound: DirectSound playback initialization failed with %Rhrc\n", hr));
    507511
    508             directSoundPlayInterfaceRelease(pDSoundStrmOut);
     512            directSoundPlayInterfaceRelease(pDSoundStream);
    509513        }
    510514    }
     
    513517}
    514518
    515 static HRESULT directSoundPlayClose(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStrmOut)
     519static HRESULT directSoundPlayClose(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStream)
    516520{
    517521    AssertPtrReturn(pThis, E_POINTER);
    518     AssertPtrReturn(pDSoundStrmOut, E_POINTER);
    519 
    520     DSLOG(("DSound: Closing playback stream %p, buffer %p\n", pDSoundStrmOut, pDSoundStrmOut->pDSB));
     522    AssertPtrReturn(pDSoundStream, E_POINTER);
     523
     524    DSLOG(("DSound: Closing playback stream %p, buffer %p\n", pDSoundStream, pDSoundStream->pDSB));
    521525
    522526    HRESULT hr = S_OK;
    523527
    524     if (pDSoundStrmOut->pDSB)
    525     {
    526         hr = IDirectSoundBuffer8_Stop(pDSoundStrmOut->pDSB);
     528    if (pDSoundStream->pDSB)
     529    {
     530        hr = IDirectSoundBuffer8_Stop(pDSoundStream->pDSB);
    527531        if (SUCCEEDED(hr))
    528532        {
     
    536540                    pThis->cEvents--;
    537541
    538                 pThis->pDSStrmOut = NULL;
     542                pThis->pDSStream = NULL;
    539543            }
    540544
     
    542546            AssertRC(rc2);
    543547#endif
    544             IDirectSoundBuffer8_Release(pDSoundStrmOut->pDSB);
    545             pDSoundStrmOut->pDSB = NULL;
     548            IDirectSoundBuffer8_Release(pDSoundStream->pDSB);
     549            pDSoundStream->pDSB = NULL;
    546550        }
    547551        else
    548             DSLOGREL(("DSound: Stop playback stream %p when closing %Rhrc\n", pDSoundStrmOut, hr));
     552            DSLOGREL(("DSound: Stop playback stream %p when closing %Rhrc\n", pDSoundStream, hr));
    549553    }
    550554
    551555    if (SUCCEEDED(hr))
    552         directSoundPlayInterfaceRelease(pDSoundStrmOut);
     556        directSoundPlayInterfaceRelease(pDSoundStream);
    553557
    554558    return hr;
    555559}
    556560
    557 static HRESULT directSoundPlayOpen(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStrmOut)
     561static HRESULT directSoundPlayOpen(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStream)
    558562{
    559563    AssertPtrReturn(pThis, E_POINTER);
    560     AssertPtrReturn(pDSoundStrmOut, E_POINTER);
    561 
    562     DSLOG(("DSound: pDSoundStrmOut=%p, cbBufferOut=%ld, uHz=%RU32, cChannels=%RU8, cBits=%RU8, fSigned=%RTbool\n",
    563            pDSoundStrmOut,
     564    AssertPtrReturn(pDSoundStream, E_POINTER);
     565
     566    DSLOG(("DSound: pDSoundStream=%p, cbBufferOut=%ld, uHz=%RU32, cChannels=%RU8, cBits=%RU8, fSigned=%RTbool\n",
     567           pDSoundStream,
    564568           pThis->cfg.cbBufferOut,
    565            pDSoundStrmOut->strmOut.Props.uHz,
    566            pDSoundStrmOut->strmOut.Props.cChannels,
    567            pDSoundStrmOut->strmOut.Props.cBits,
    568            pDSoundStrmOut->strmOut.Props.fSigned));
    569 
    570     if (pDSoundStrmOut->pDSB != NULL)
     569           pDSoundStream->Stream.Props.uHz,
     570           pDSoundStream->Stream.Props.cChannels,
     571           pDSoundStream->Stream.Props.cBits,
     572           pDSoundStream->Stream.Props.fSigned));
     573
     574    if (pDSoundStream->pDSB != NULL)
    571575    {
    572576        /* Should not happen but be forgiving. */
    573577        DSLOGREL(("DSound: Playback buffer already exists\n"));
    574         directSoundPlayClose(pThis, pDSoundStrmOut);
     578        directSoundPlayClose(pThis, pDSoundStream);
    575579    }
    576580
    577581    WAVEFORMATEX wfx;
    578     int rc = dsoundWaveFmtFromCfg(&pDSoundStrmOut->streamCfg, &wfx);
     582    int rc = dsoundWaveFmtFromCfg(&pDSoundStream->streamCfg, &wfx);
    579583    if (RT_FAILURE(rc))
    580584        return E_INVALIDARG;
    581585
    582     HRESULT hr = directSoundPlayInterfaceCreate(pThis, pDSoundStrmOut);
     586    HRESULT hr = directSoundPlayInterfaceCreate(pThis, pDSoundStream);
    583587    if (FAILED(hr))
    584588        return hr;
     
    610614        bd.dwBufferBytes = pThis->cfg.cbBufferOut;
    611615
    612         hr = IDirectSound8_CreateSoundBuffer(pDSoundStrmOut->pDS, &bd, &pDSB, NULL);
     616        hr = IDirectSound8_CreateSoundBuffer(pDSoundStream->pDS, &bd, &pDSB, NULL);
    613617        if (FAILED(hr))
    614618        {
     
    618622
    619623        /* "Upgrade" to IDirectSoundBuffer8 interface. */
    620         hr = IDirectSoundBuffer_QueryInterface(pDSB, IID_IDirectSoundBuffer8, (LPVOID *)&pDSoundStrmOut->pDSB);
     624        hr = IDirectSoundBuffer_QueryInterface(pDSB, IID_IDirectSoundBuffer8, (LPVOID *)&pDSoundStream->pDSB);
    621625        IDirectSoundBuffer_Release(pDSB);
    622626        if (FAILED(hr))
     
    629633         * Query the actual parameters.
    630634         */
    631         hr = IDirectSoundBuffer8_GetFormat(pDSoundStrmOut->pDSB, &wfx, sizeof(wfx), NULL);
     635        hr = IDirectSoundBuffer8_GetFormat(pDSoundStream->pDSB, &wfx, sizeof(wfx), NULL);
    632636        if (FAILED(hr))
    633637        {
     
    639643        RT_ZERO(bc);
    640644        bc.dwSize = sizeof(bc);
    641         hr = IDirectSoundBuffer8_GetCaps(pDSoundStrmOut->pDSB, &bc);
     645        hr = IDirectSoundBuffer8_GetCaps(pDSoundStream->pDSB, &bc);
    642646        if (FAILED(hr))
    643647        {
     
    666670               wfx.cbSize));
    667671
    668         if (bc.dwBufferBytes & pDSoundStrmOut->strmOut.Props.uAlign)
     672        if (bc.dwBufferBytes & pDSoundStream->Stream.Props.uAlign)
    669673            DSLOGREL(("DSound: Playback capabilities returned misaligned buffer: size %RU32, alignment %RU32\n",
    670                       bc.dwBufferBytes, pDSoundStrmOut->strmOut.Props.uAlign + 1));
     674                      bc.dwBufferBytes, pDSoundStream->Stream.Props.uAlign + 1));
    671675
    672676        if (bc.dwBufferBytes != pThis->cfg.cbBufferOut)
     
    679683         * playback buffer position.
    680684         */
    681         pDSoundStrmOut->csPlaybackBufferSize = bc.dwBufferBytes >> pDSoundStrmOut->strmOut.Props.cShift;
    682         DSLOG(("DSound: csPlaybackBufferSize=%RU32\n", pDSoundStrmOut->csPlaybackBufferSize));
     685        pDSoundStream->csPlaybackBufferSize = bc.dwBufferBytes >> pDSoundStream->Stream.Props.cShift;
     686        DSLOG(("DSound: csPlaybackBufferSize=%RU32\n", pDSoundStream->csPlaybackBufferSize));
    683687
    684688#ifdef VBOX_WITH_AUDIO_CALLBACKS
     
    697701
    698702        LPDIRECTSOUNDNOTIFY8 pNotify;
    699         hr = IDirectSoundNotify_QueryInterface(pDSoundStrmOut->pDSB, IID_IDirectSoundNotify8, (LPVOID *)&pNotify);
     703        hr = IDirectSoundNotify_QueryInterface(pDSoundStream->pDSB, IID_IDirectSoundNotify8, (LPVOID *)&pNotify);
    700704        if (SUCCEEDED(hr))
    701705        {
     
    717721            break;
    718722
    719         pThis->pDSStrmOut = pDSoundStrmOut;
     723        pThis->pDSStreamOut = pDSoundStream;
    720724
    721725        Assert(pThis->cEvents < VBOX_DSOUND_MAX_EVENTS);
     
    726730
    727731        /* Trigger the just installed output notification. */
    728         hr = IDirectSoundBuffer8_Play(pDSoundStrmOut->pDSB, 0, 0, 0);
     732        hr = IDirectSoundBuffer8_Play(pDSoundStream->pDSB, 0, 0, 0);
    729733
    730734#endif /* VBOX_WITH_AUDIO_CALLBACKS */
     
    733737
    734738    if (FAILED(hr))
    735         directSoundPlayClose(pThis, pDSoundStrmOut);
     739        directSoundPlayClose(pThis, pDSoundStream);
    736740
    737741    return hr;
    738742}
    739743
    740 static void dsoundPlayClearSamples(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStrmOut)
    741 {
    742     AssertPtrReturnVoid(pDSoundStrmOut);
    743 
    744     PPDMAUDIOHSTSTRMOUT pStrmOut = &pDSoundStrmOut->strmOut;
     744static void dsoundPlayClearSamples(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStream)
     745{
     746    AssertPtrReturnVoid(pDSoundStream);
     747
     748    PPDMAUDIOSTREAM pStream = &pDSoundStream->Stream;
    745749
    746750    LPVOID pv1, pv2;
    747751    DWORD cb1, cb2;
    748     HRESULT hr = directSoundPlayLock(pThis, pDSoundStrmOut->pDSB, &pDSoundStrmOut->strmOut.Props,
    749                                      0 /* dwOffset */, AUDIOMIXBUF_S2B(&pStrmOut->MixBuf, pDSoundStrmOut->csPlaybackBufferSize),
     752    HRESULT hr = directSoundPlayLock(pThis, pDSoundStream->pDSB, &pDSoundStream->Stream.Props,
     753                                     0 /* dwOffset */, AUDIOMIXBUF_S2B(&pStream->MixBuf, pDSoundStream->csPlaybackBufferSize),
    750754                                     &pv1, &pv2, &cb1, &cb2, DSBLOCK_ENTIREBUFFER);
    751755    if (SUCCEEDED(hr))
    752756    {
    753         DWORD len1 = AUDIOMIXBUF_B2S(&pStrmOut->MixBuf, cb1);
    754         DWORD len2 = AUDIOMIXBUF_B2S(&pStrmOut->MixBuf, cb2);
     757        DWORD len1 = AUDIOMIXBUF_B2S(&pStream->MixBuf, cb1);
     758        DWORD len2 = AUDIOMIXBUF_B2S(&pStream->MixBuf, cb2);
    755759
    756760        if (pv1 && len1)
    757             DrvAudioClearBuf(&pDSoundStrmOut->strmOut.Props, pv1, cb1, len1);
     761            DrvAudioClearBuf(&pDSoundStream->Stream.Props, pv1, cb1, len1);
    758762
    759763        if (pv2 && len2)
    760             DrvAudioClearBuf(&pDSoundStrmOut->strmOut.Props, pv2, cb2, len2);
    761 
    762         directSoundPlayUnlock(pThis, pDSoundStrmOut->pDSB, pv1, pv2, cb1, cb2);
     764            DrvAudioClearBuf(&pDSoundStream->Stream.Props, pv2, cb2, len2);
     765
     766        directSoundPlayUnlock(pThis, pDSoundStream->pDSB, pv1, pv2, cb1, cb2);
    763767    }
    764768}
     
    798802}
    799803
    800 static HRESULT directSoundPlayStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStrmOut)
    801 {
    802     AssertPtrReturn(pThis,          E_POINTER);
    803     AssertPtrReturn(pDSoundStrmOut, E_POINTER);
     804static HRESULT directSoundPlayStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStream)
     805{
     806    AssertPtrReturn(pThis,         E_POINTER);
     807    AssertPtrReturn(pDSoundStream, E_POINTER);
    804808
    805809    HRESULT hr;
    806810
    807     if (pDSoundStrmOut->pDSB != NULL)
     811    if (pDSoundStream->pDSB != NULL)
    808812    {
    809813        DSLOG(("DSound: Stopping playback\n"));
    810814
    811         HRESULT hr2 = IDirectSoundBuffer8_Stop(pDSoundStrmOut->pDSB);
     815        HRESULT hr2 = IDirectSoundBuffer8_Stop(pDSoundStream->pDSB);
    812816        if (FAILED(hr2))
    813817        {
    814             hr2 = directSoundPlayRestore(pThis, pDSoundStrmOut->pDSB);
     818            hr2 = directSoundPlayRestore(pThis, pDSoundStream->pDSB);
    815819            if (FAILED(hr2))
    816                 hr2 = IDirectSoundBuffer8_Stop(pDSoundStrmOut->pDSB);
     820                hr2 = IDirectSoundBuffer8_Stop(pDSoundStream->pDSB);
    817821        }
    818822
     
    827831    if (SUCCEEDED(hr))
    828832    {
    829         dsoundPlayClearSamples(pThis, pDSoundStrmOut);
    830         pDSoundStrmOut->fEnabled = false;
     833        dsoundPlayClearSamples(pThis, pDSoundStream);
     834        pDSoundStream->fEnabled = false;
    831835    }
    832836    else
     
    836840}
    837841
    838 static HRESULT directSoundPlayStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStrmOut)
    839 {
    840     AssertPtrReturn(pThis,          E_POINTER);
    841     AssertPtrReturn(pDSoundStrmOut, E_POINTER);
     842static HRESULT directSoundPlayStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStream)
     843{
     844    AssertPtrReturn(pThis,         E_POINTER);
     845    AssertPtrReturn(pDSoundStream, E_POINTER);
    842846
    843847    HRESULT hr;
    844     if (pDSoundStrmOut->pDSB != NULL)
     848    if (pDSoundStream->pDSB != NULL)
    845849    {
    846850        DWORD dwStatus;
    847         hr = directSoundPlayGetStatus(pThis, pDSoundStrmOut->pDSB, &dwStatus);
     851        hr = directSoundPlayGetStatus(pThis, pDSoundStream->pDSB, &dwStatus);
    848852        if (SUCCEEDED(hr))
    849853        {
     
    854858            else
    855859            {
    856                 dsoundPlayClearSamples(pThis, pDSoundStrmOut);
    857 
    858                 pDSoundStrmOut->fRestartPlayback = true;
    859                 pDSoundStrmOut->fEnabled         = true;
     860                dsoundPlayClearSamples(pThis, pDSoundStream);
     861
     862                pDSoundStream->fRestartPlayback = true;
     863                pDSoundStream->fEnabled         = true;
    860864
    861865                DSLOG(("DSound: Playback started\n"));
    862866
    863867                /*
    864                  * The actual IDirectSoundBuffer8_Play call will be made in drvHostDSoundPlayOut,
     868                 * The actual IDirectSoundBuffer8_Play call will be made in drvHostDSoundPlay,
    865869                 * because it is necessary to put some samples into the buffer first.
    866870                 */
     
    881885 */
    882886
    883 static LPCGUID dsoundCaptureSelectDevice(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStrmIn)
     887static LPCGUID dsoundCaptureSelectDevice(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStream)
    884888{
    885889    AssertPtrReturn(pThis, NULL);
    886     AssertPtrReturn(pDSoundStrmIn, NULL);
     890    AssertPtrReturn(pDSoundStream, NULL);
    887891
    888892    LPCGUID pGUID = pThis->cfg.pGuidCapture;
     
    892896        PDSOUNDDEV  pDev = NULL;
    893897
    894         switch (pDSoundStrmIn->enmRecSource)
     898        switch (pDSoundStream->enmRecSource)
    895899        {
    896900            case PDMAUDIORECSOURCE_MIC:
     
    916920        {
    917921            DSLOG(("DSound: Guest \"%s\" is using host \"%s\"\n",
    918                    DrvAudRecSrcToStr(pDSoundStrmIn->enmRecSource), pDev->pszName));
     922                   DrvAudRecSrcToStr(pDSoundStream->enmRecSource), pDev->pszName));
    919923
    920924            pGUID = &pDev->Guid;
     
    925929    /* This always has to be in the release log. */
    926930    LogRel(("DSound: Guest \"%s\" is using host device with GUID: %s\n",
    927             DrvAudRecSrcToStr(pDSoundStrmIn->enmRecSource), pszGUID? pszGUID: "{?}"));
     931            DrvAudRecSrcToStr(pDSoundStream->enmRecSource), pszGUID? pszGUID: "{?}"));
    928932    RTStrFree(pszGUID);
    929933
     
    931935}
    932936
    933 static void directSoundCaptureInterfaceRelease(PDSOUNDSTREAMIN pDSoundStrmIn)
    934 {
    935     if (pDSoundStrmIn->pDSC)
     937static void directSoundCaptureInterfaceRelease(PDSOUNDSTREAMIN pDSoundStream)
     938{
     939    if (pDSoundStream->pDSC)
    936940    {
    937941        LogFlowFuncEnter();
    938         IDirectSoundCapture_Release(pDSoundStrmIn->pDSC);
    939         pDSoundStrmIn->pDSC = NULL;
    940     }
    941 }
    942 
    943 static HRESULT directSoundCaptureInterfaceCreate(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStrmIn)
    944 {
    945     if (pDSoundStrmIn->pDSC != NULL)
     942        IDirectSoundCapture_Release(pDSoundStream->pDSC);
     943        pDSoundStream->pDSC = NULL;
     944    }
     945}
     946
     947static HRESULT directSoundCaptureInterfaceCreate(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStream)
     948{
     949    if (pDSoundStream->pDSC != NULL)
    946950    {
    947951        DSLOG(("DSound: DirectSoundCapture instance already exists\n"));
     
    950954
    951955    HRESULT hr = CoCreateInstance(CLSID_DirectSoundCapture8, NULL, CLSCTX_ALL,
    952                                   IID_IDirectSoundCapture8, (void **)&pDSoundStrmIn->pDSC);
     956                                  IID_IDirectSoundCapture8, (void **)&pDSoundStream->pDSC);
    953957    if (FAILED(hr))
    954958    {
     
    957961    else
    958962    {
    959         LPCGUID pGUID = dsoundCaptureSelectDevice(pThis, pDSoundStrmIn);
    960         hr = IDirectSoundCapture_Initialize(pDSoundStrmIn->pDSC, pGUID);
     963        LPCGUID pGUID = dsoundCaptureSelectDevice(pThis, pDSoundStream);
     964        hr = IDirectSoundCapture_Initialize(pDSoundStream->pDSC, pGUID);
    961965        if (FAILED(hr))
    962966        {
     
    966970                DSLOGREL(("DSound: Initializing capturing device failed with %Rhrc\n", hr));
    967971
    968             directSoundCaptureInterfaceRelease(pDSoundStrmIn);
     972            directSoundCaptureInterfaceRelease(pDSoundStream);
    969973        }
    970974    }
     
    974978}
    975979
    976 static HRESULT directSoundCaptureClose(PDSOUNDSTREAMIN pDSoundStrmIn)
    977 {
    978     AssertPtrReturn(pDSoundStrmIn, E_POINTER);
    979 
    980     DSLOG(("DSound: pDSoundStrmIn=%p, pDSCB=%p\n", pDSoundStrmIn, pDSoundStrmIn->pDSCB));
     980static HRESULT directSoundCaptureClose(PDSOUNDSTREAMIN pDSoundStream)
     981{
     982    AssertPtrReturn(pDSoundStream, E_POINTER);
     983
     984    DSLOG(("DSound: pDSoundStream=%p, pDSCB=%p\n", pDSoundStream, pDSoundStream->pDSCB));
    981985
    982986    HRESULT hr = S_OK;
    983987
    984     if (pDSoundStrmIn->pDSCB)
    985     {
    986         hr = IDirectSoundCaptureBuffer_Stop(pDSoundStrmIn->pDSCB);
     988    if (pDSoundStream->pDSCB)
     989    {
     990        hr = IDirectSoundCaptureBuffer_Stop(pDSoundStream->pDSCB);
    987991        if (SUCCEEDED(hr))
    988992        {
    989             IDirectSoundCaptureBuffer8_Release(pDSoundStrmIn->pDSCB);
    990             pDSoundStrmIn->pDSCB = NULL;
     993            IDirectSoundCaptureBuffer8_Release(pDSoundStream->pDSCB);
     994            pDSoundStream->pDSCB = NULL;
    991995        }
    992996        else
     
    995999
    9961000    if (SUCCEEDED(hr))
    997         directSoundCaptureInterfaceRelease(pDSoundStrmIn);
     1001        directSoundCaptureInterfaceRelease(pDSoundStream);
    9981002
    9991003    LogFlowFunc(("Returning %Rhrc\n", hr));
     
    10011005}
    10021006
    1003 static HRESULT directSoundCaptureOpen(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStrmIn)
     1007static HRESULT directSoundCaptureOpen(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStream)
    10041008{
    10051009    AssertPtrReturn(pThis, E_POINTER);
    1006     AssertPtrReturn(pDSoundStrmIn, E_POINTER);
    1007 
    1008     DSLOG(("DSound: pDSoundStrmIn=%p, cbBufferIn=%ld, uHz=%RU32, cChannels=%RU8, cBits=%RU8, fSigned=%RTbool\n",
    1009            pDSoundStrmIn,
     1010    AssertPtrReturn(pDSoundStream, E_POINTER);
     1011
     1012    DSLOG(("DSound: pDSoundStream=%p, cbBufferIn=%ld, uHz=%RU32, cChannels=%RU8, cBits=%RU8, fSigned=%RTbool\n",
     1013           pDSoundStream,
    10101014           pThis->cfg.cbBufferIn,
    1011            pDSoundStrmIn->strmIn.Props.uHz,
    1012            pDSoundStrmIn->strmIn.Props.cChannels,
    1013            pDSoundStrmIn->strmIn.Props.cBits,
    1014            pDSoundStrmIn->strmIn.Props.fSigned));
    1015 
    1016     if (pDSoundStrmIn->pDSCB != NULL)
     1015           pDSoundStream->Stream.Props.uHz,
     1016           pDSoundStream->Stream.Props.cChannels,
     1017           pDSoundStream->Stream.Props.cBits,
     1018           pDSoundStream->Stream.Props.fSigned));
     1019
     1020    if (pDSoundStream->pDSCB != NULL)
    10171021    {
    10181022        /* Should not happen but be forgiving. */
    10191023        DSLOGREL(("DSound: DirectSoundCaptureBuffer already exists\n"));
    1020         directSoundCaptureClose(pDSoundStrmIn);
     1024        directSoundCaptureClose(pDSoundStream);
    10211025    }
    10221026
    10231027    WAVEFORMATEX wfx;
    1024     int rc = dsoundWaveFmtFromCfg(&pDSoundStrmIn->streamCfg, &wfx);
     1028    int rc = dsoundWaveFmtFromCfg(&pDSoundStream->streamCfg, &wfx);
    10251029    if (RT_FAILURE(rc))
    10261030        return E_INVALIDARG;
    10271031
    1028     HRESULT hr = directSoundCaptureInterfaceCreate(pThis, pDSoundStrmIn);
     1032    HRESULT hr = directSoundCaptureInterfaceCreate(pThis, pDSoundStream);
    10291033    if (FAILED(hr))
    10301034        return hr;
     
    10381042        bd.lpwfxFormat = &wfx;
    10391043        bd.dwBufferBytes = pThis->cfg.cbBufferIn;
    1040         hr = IDirectSoundCapture_CreateCaptureBuffer(pDSoundStrmIn->pDSC,
     1044        hr = IDirectSoundCapture_CreateCaptureBuffer(pDSoundStream->pDSC,
    10411045                                                     &bd, &pDSCB, NULL);
    10421046        if (FAILED(hr))
     
    10511055        }
    10521056
    1053         hr = IDirectSoundCaptureBuffer_QueryInterface(pDSCB, IID_IDirectSoundCaptureBuffer8, (void **)&pDSoundStrmIn->pDSCB);
     1057        hr = IDirectSoundCaptureBuffer_QueryInterface(pDSCB, IID_IDirectSoundCaptureBuffer8, (void **)&pDSoundStream->pDSCB);
    10541058        IDirectSoundCaptureBuffer_Release(pDSCB);
    10551059        if (FAILED(hr))
     
    10631067         */
    10641068        DWORD cbReadPos = 0;
    1065         hr = IDirectSoundCaptureBuffer8_GetCurrentPosition(pDSoundStrmIn->pDSCB, NULL, &cbReadPos);
     1069        hr = IDirectSoundCaptureBuffer8_GetCurrentPosition(pDSoundStream->pDSCB, NULL, &cbReadPos);
    10661070        if (FAILED(hr))
    10671071        {
     
    10711075
    10721076        RT_ZERO(wfx);
    1073         hr = IDirectSoundCaptureBuffer8_GetFormat(pDSoundStrmIn->pDSCB, &wfx, sizeof(wfx), NULL);
     1077        hr = IDirectSoundCaptureBuffer8_GetFormat(pDSoundStream->pDSCB, &wfx, sizeof(wfx), NULL);
    10741078        if (FAILED(hr))
    10751079        {
     
    10811085        RT_ZERO(bc);
    10821086        bc.dwSize = sizeof(bc);
    1083         hr = IDirectSoundCaptureBuffer8_GetCaps(pDSoundStrmIn->pDSCB, &bc);
     1087        hr = IDirectSoundCaptureBuffer8_GetCaps(pDSoundStream->pDSCB, &bc);
    10841088        if (FAILED(hr))
    10851089        {
     
    11081112               wfx.cbSize));
    11091113
    1110         if (bc.dwBufferBytes & pDSoundStrmIn->strmIn.Props.uAlign)
     1114        if (bc.dwBufferBytes & pDSoundStream->Stream.Props.uAlign)
    11111115            DSLOGREL(("DSound: Capture GetCaps returned misaligned buffer: size %RU32, alignment %RU32\n",
    1112                       bc.dwBufferBytes, pDSoundStrmIn->strmIn.Props.uAlign + 1));
     1116                      bc.dwBufferBytes, pDSoundStream->Stream.Props.uAlign + 1));
    11131117
    11141118        if (bc.dwBufferBytes != pThis->cfg.cbBufferIn)
     
    11171121
    11181122        /* Initial state: reading at the initial capture position, no error. */
    1119         pDSoundStrmIn->csCaptureReadPos    = cbReadPos >> pDSoundStrmIn->strmIn.Props.cShift;
    1120         pDSoundStrmIn->csCaptureBufferSize = bc.dwBufferBytes >> pDSoundStrmIn->strmIn.Props.cShift;
    1121         pDSoundStrmIn->hrLastCaptureIn = S_OK;
     1123        pDSoundStream->csCaptureReadPos    = cbReadPos >> pDSoundStream->Stream.Props.cShift;
     1124        pDSoundStream->csCaptureBufferSize = bc.dwBufferBytes >> pDSoundStream->Stream.Props.cShift;
     1125        pDSoundStream->hrLastCapture      = S_OK;
    11221126
    11231127        DSLOG(("DSound: csCaptureReadPos=%RU32, csCaptureBufferSize=%RU32\n",
    1124                      pDSoundStrmIn->csCaptureReadPos, pDSoundStrmIn->csCaptureBufferSize));
     1128                     pDSoundStream->csCaptureReadPos, pDSoundStream->csCaptureBufferSize));
    11251129
    11261130    } while (0);
    11271131
    11281132    if (FAILED(hr))
    1129         directSoundCaptureClose(pDSoundStrmIn);
     1133        directSoundCaptureClose(pDSoundStream);
    11301134
    11311135    LogFlowFunc(("Returning %Rhrc\n", hr));
     
    11331137}
    11341138
    1135 static HRESULT directSoundCaptureStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStrmIn)
     1139static HRESULT directSoundCaptureStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStream)
    11361140{
    11371141    AssertPtrReturn(pThis        , E_POINTER);
    1138     AssertPtrReturn(pDSoundStrmIn, E_POINTER);
     1142    AssertPtrReturn(pDSoundStream, E_POINTER);
    11391143
    11401144    NOREF(pThis);
     
    11421146    HRESULT hr;
    11431147
    1144     if (pDSoundStrmIn->pDSCB)
     1148    if (pDSoundStream->pDSCB)
    11451149    {
    11461150        DSLOG(("DSound: Stopping capture\n"));
    11471151
    1148         hr = IDirectSoundCaptureBuffer_Stop(pDSoundStrmIn->pDSCB);
     1152        hr = IDirectSoundCaptureBuffer_Stop(pDSoundStream->pDSCB);
    11491153        if (FAILED(hr))
    11501154            DSLOGREL(("DSound: Stopping capture buffer failed with %Rhrc\n", hr));
     
    11541158
    11551159    if (SUCCEEDED(hr))
    1156         pDSoundStrmIn->fEnabled = false;
     1160        pDSoundStream->fEnabled = false;
    11571161
    11581162    LogFlowFunc(("Returning %Rhrc\n", hr));
     
    11601164}
    11611165
    1162 static HRESULT directSoundCaptureStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStrmIn)
    1163 {
    1164     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    1165     AssertPtrReturn(pDSoundStrmIn, VERR_INVALID_POINTER);
     1166static HRESULT directSoundCaptureStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStream)
     1167{
     1168    AssertPtrReturn(pThis,         VERR_INVALID_POINTER);
     1169    AssertPtrReturn(pDSoundStream, VERR_INVALID_POINTER);
    11661170
    11671171    HRESULT hr;
    1168     if (pDSoundStrmIn->pDSCB != NULL)
     1172    if (pDSoundStream->pDSCB != NULL)
    11691173    {
    11701174        DWORD dwStatus;
    1171         hr = IDirectSoundCaptureBuffer8_GetStatus(pDSoundStrmIn->pDSCB, &dwStatus);
     1175        hr = IDirectSoundCaptureBuffer8_GetStatus(pDSoundStream->pDSCB, &dwStatus);
    11721176        if (FAILED(hr))
    11731177        {
     
    11871191#endif
    11881192                DSLOG(("DSound: Starting to capture\n"));
    1189                 hr = IDirectSoundCaptureBuffer8_Start(pDSoundStrmIn->pDSCB, fFlags);
     1193                hr = IDirectSoundCaptureBuffer8_Start(pDSoundStream->pDSCB, fFlags);
    11901194                if (FAILED(hr))
    11911195                    DSLOGREL(("DSound: Starting to capture failed with %Rhrc\n", hr));
     
    11971201
    11981202    if (SUCCEEDED(hr))
    1199         pDSoundStrmIn->fEnabled = true;
     1203        pDSoundStream->fEnabled = true;
    12001204
    12011205    LogFlowFunc(("Returning %Rhrc\n", hr));
     
    14051409}
    14061410
    1407 /*
    1408  * PDMIHOSTAUDIO
    1409  */
    1410 
    1411 static DECLCALLBACK(int) drvHostDSoundInitOut(PPDMIHOSTAUDIO pInterface,
    1412                                               PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,
    1413                                               uint32_t *pcSamples)
     1411static int dsoundCreateStreamOut(PPDMIHOSTAUDIO pInterface,
     1412                                 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
    14141413{
    14151414    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1416     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    1417     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
     1415    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1416    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
    14181417    /* pcSamples is optional. */
    14191418
    1420     LogFlowFunc(("pHstStrmOut=%p, pCfg=%p\n", pHstStrmOut, pCfg));
     1419    LogFlowFunc(("pStream=%p, pCfg=%p\n", pStream, pCfg));
    14211420
    14221421    PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    1423     PDSOUNDSTREAMOUT pDSoundStrmOut = (PDSOUNDSTREAMOUT)pHstStrmOut;
    1424 
    1425     pDSoundStrmOut->streamCfg = *pCfg;
    1426     pDSoundStrmOut->streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
    1427 
    1428     int rc = DrvAudioStreamCfgToProps(&pDSoundStrmOut->streamCfg, &pDSoundStrmOut->strmOut.Props);
     1422    PDSOUNDSTREAMOUT pDSoundStream = (PDSOUNDSTREAMOUT)pStream;
     1423
     1424    pDSoundStream->streamCfg = *pCfg;
     1425    pDSoundStream->streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
     1426
     1427    int rc = DrvAudioStreamCfgToProps(&pDSoundStream->streamCfg, &pDSoundStream->Stream.Props);
    14291428    if (RT_SUCCESS(rc))
    14301429    {
    1431         pDSoundStrmOut->pDS = NULL;
    1432         pDSoundStrmOut->pDSB = NULL;
    1433         pDSoundStrmOut->cbPlayWritePos = 0;
    1434         pDSoundStrmOut->fRestartPlayback = true;
    1435         pDSoundStrmOut->csPlaybackBufferSize = 0;
     1430        pDSoundStream->pDS = NULL;
     1431        pDSoundStream->pDSB = NULL;
     1432        pDSoundStream->cbPlayWritePos = 0;
     1433        pDSoundStream->fRestartPlayback = true;
     1434        pDSoundStream->csPlaybackBufferSize = 0;
    14361435
    14371436        if (pcSamples)
    1438             *pcSamples = pThis->cfg.cbBufferOut >> pHstStrmOut->Props.cShift;
     1437            *pcSamples = pThis->cfg.cbBufferOut >> pStream->Props.cShift;
    14391438
    14401439        /* Try to open playback in case the device is already there. */
    1441         directSoundPlayOpen(pThis, pDSoundStrmOut);
     1440        directSoundPlayOpen(pThis, pDSoundStream);
    14421441    }
    14431442    else
    14441443    {
    1445         RT_ZERO(pDSoundStrmOut->streamCfg);
     1444        RT_ZERO(pDSoundStream->streamCfg);
    14461445    }
    14471446
     
    14501449}
    14511450
    1452 static DECLCALLBACK(int) drvHostDSoundControlOut(PPDMIHOSTAUDIO pInterface,
    1453                                                  PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd)
     1451static int dsoundControlStreamOut(PPDMIHOSTAUDIO pInterface,
     1452                                  PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    14541453{
    14551454    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1456     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    1457 
    1458     LogFlowFunc(("pHstStrmOut=%p, cmd=%d\n", pHstStrmOut, enmStreamCmd));
     1455    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1456
     1457    LogFlowFunc(("pStream=%p, cmd=%d\n", pStream, enmStreamCmd));
    14591458
    14601459    PDRVHOSTDSOUND   pThis          = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    1461     PDSOUNDSTREAMOUT pDSoundStrmOut = (PDSOUNDSTREAMOUT)pHstStrmOut;
     1460    PDSOUNDSTREAMOUT pDSoundStream = (PDSOUNDSTREAMOUT)pStream;
    14621461
    14631462    int rc = VINF_SUCCESS;
     
    14711470            DSLOG(("DSound: Playback PDMAUDIOSTREAMCMD_ENABLE\n"));
    14721471            /* Try to start playback. If it fails, then reopen and try again. */
    1473             hr = directSoundPlayStart(pThis, pDSoundStrmOut);
     1472            hr = directSoundPlayStart(pThis, pDSoundStream);
    14741473            if (FAILED(hr))
    14751474            {
    1476                 hr = directSoundPlayClose(pThis, pDSoundStrmOut);
     1475                hr = directSoundPlayClose(pThis, pDSoundStream);
    14771476                if (SUCCEEDED(hr))
    1478                     hr = directSoundPlayOpen(pThis, pDSoundStrmOut);
     1477                    hr = directSoundPlayOpen(pThis, pDSoundStream);
    14791478                if (SUCCEEDED(hr))
    1480                     hr = directSoundPlayStart(pThis, pDSoundStrmOut);
     1479                    hr = directSoundPlayStart(pThis, pDSoundStream);
    14811480            }
    14821481
     
    14901489        {
    14911490            DSLOG(("DSound: Playback PDMAUDIOSTREAMCMD_DISABLE\n"));
    1492             hr = directSoundPlayStop(pThis, pDSoundStrmOut);
     1491            hr = directSoundPlayStop(pThis, pDSoundStream);
    14931492            if (FAILED(hr))
    14941493                rc = VERR_NOT_SUPPORTED;
     
    15081507}
    15091508
    1510 static DECLCALLBACK(int) drvHostDSoundPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
    1511                                               uint32_t *pcSamplesPlayed)
     1509static DECLCALLBACK(int) drvHostDSoundStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     1510                                                 uint32_t *pcSamplesPlayed)
    15121511{
    15131512    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1514     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
     1513    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    15151514    /* pcSamplesPlayed is optional. */
    15161515
    15171516    PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    1518     PDSOUNDSTREAMOUT pDSoundStrmOut = (PDSOUNDSTREAMOUT)pHstStrmOut;
     1517    PDSOUNDSTREAMOUT pDSoundStream = (PDSOUNDSTREAMOUT)pStream;
    15191518
    15201519    int rc = VINF_SUCCESS;
     
    15281527    {
    15291528        DWORD cbBuffer, cbFree, cbPlayPos;
    1530         rc = dsoundGetPosOut(pThis, pDSoundStrmOut, &cbBuffer, &cbFree, &cbPlayPos);
     1529        rc = dsoundGetPosOut(pThis, pDSoundStream, &cbBuffer, &cbFree, &cbPlayPos);
    15311530        if (RT_FAILURE(rc))
    15321531            break;
     
    15361535         * i.e. always leave a free space for 1 audio sample.
    15371536         */
    1538         const DWORD cbSample = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, 1);
     1537        const DWORD cbSample = AUDIOMIXBUF_S2B(&pStream->MixBuf, 1);
    15391538        if (cbFree <= cbSample)
    15401539            break;
    15411540        cbFree     -= cbSample;
    15421541
    1543         uint32_t csLive = AudioMixBufAvail(&pHstStrmOut->MixBuf);
    1544         uint32_t cbLive = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, csLive);
     1542        uint32_t csLive = AudioMixBufAvail(&pStream->MixBuf);
     1543        uint32_t cbLive = AUDIOMIXBUF_S2B(&pStream->MixBuf, csLive);
    15451544
    15461545        /* Do not write more than available space in the DirectSound playback buffer. */
    15471546        cbLive = RT_MIN(cbFree, cbLive);
    15481547
    1549         cbLive &= ~pHstStrmOut->Props.uAlign;
     1548        cbLive &= ~pStream->Props.uAlign;
    15501549        if (cbLive == 0 || cbLive > cbBuffer)
    15511550        {
    15521551            DSLOG(("DSound: cbLive=%RU32, cbBuffer=%ld, cbPlayWritePos=%ld, cbPlayPos=%ld\n",
    1553                    cbLive, cbBuffer, pDSoundStrmOut->cbPlayWritePos, cbPlayPos));
    1554             break;
    1555         }
    1556 
    1557         LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStrmOut->pDSB;
     1552                   cbLive, cbBuffer, pDSoundStream->cbPlayWritePos, cbPlayPos));
     1553            break;
     1554        }
     1555
     1556        LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStream->pDSB;
    15581557        AssertPtr(pDSB);
    15591558
    15601559        LPVOID pv1, pv2;
    15611560        DWORD cb1, cb2;
    1562         HRESULT hr = directSoundPlayLock(pThis, pDSB, &pHstStrmOut->Props, pDSoundStrmOut->cbPlayWritePos, cbLive,
     1561        HRESULT hr = directSoundPlayLock(pThis, pDSB, &pStream->Props, pDSoundStream->cbPlayWritePos, cbLive,
    15631562                                         &pv1, &pv2, &cb1, &cb2, 0 /* dwFlags */);
    15641563        if (FAILED(hr))
     
    15681567        }
    15691568
    1570         DWORD len1 = AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cb1);
    1571         DWORD len2 = AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cb2);
     1569        DWORD len1 = AUDIOMIXBUF_B2S(&pStream->MixBuf, cb1);
     1570        DWORD len2 = AUDIOMIXBUF_B2S(&pStream->MixBuf, cb2);
    15721571
    15731572        uint32_t cRead = 0;
     
    15751574        if (pv1 && cb1)
    15761575        {
    1577             rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pv1, cb1, &cRead);
     1576            rc = AudioMixBufReadCirc(&pStream->MixBuf, pv1, cb1, &cRead);
    15781577            if (RT_SUCCESS(rc))
    15791578                cReadTotal += cRead;
     
    15841583            && pv2 && cb2)
    15851584        {
    1586             rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pv2, cb2, &cRead);
     1585            rc = AudioMixBufReadCirc(&pStream->MixBuf, pv2, cb2, &cRead);
    15871586            if (RT_SUCCESS(rc))
    15881587                cReadTotal += cRead;
     
    15911590        directSoundPlayUnlock(pThis, pDSB, pv1, pv2, cb1, cb2);
    15921591
    1593         pDSoundStrmOut->cbPlayWritePos =
    1594             (pDSoundStrmOut->cbPlayWritePos + AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cReadTotal)) % cbBuffer;
     1592        pDSoundStream->cbPlayWritePos =
     1593            (pDSoundStream->cbPlayWritePos + AUDIOMIXBUF_S2B(&pStream->MixBuf, cReadTotal)) % cbBuffer;
    15951594
    15961595        DSLOGF(("DSound: %RU32 (%RU32 samples) out of %RU32%s, buffer write pos %ld, rc=%Rrc\n",
    1597                 AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cReadTotal), cReadTotal, cbLive,
    1598                 cbLive != AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cReadTotal) ? " !!!": "",
    1599                 pDSoundStrmOut->cbPlayWritePos, rc));
     1596                AUDIOMIXBUF_S2B(&pStream->MixBuf, cReadTotal), cReadTotal, cbLive,
     1597                cbLive != AUDIOMIXBUF_S2B(&pStream->MixBuf, cReadTotal) ? " !!!": "",
     1598                pDSoundStream->cbPlayWritePos, rc));
    16001599
    16011600        if (cReadTotal)
    16021601        {
    1603             AudioMixBufFinish(&pHstStrmOut->MixBuf, cReadTotal);
     1602            AudioMixBufFinish(&pStream->MixBuf, cReadTotal);
    16041603            rc = VINF_SUCCESS; /* Played something. */
    16051604        }
     
    16081607            break;
    16091608
    1610         if (pDSoundStrmOut->fRestartPlayback)
     1609        if (pDSoundStream->fRestartPlayback)
    16111610        {
    16121611            /*
     
    16151614             * and it can start playing.
    16161615             */
    1617             pDSoundStrmOut->fRestartPlayback = false;
     1616            pDSoundStream->fRestartPlayback = false;
    16181617
    16191618            DWORD fFlags = 0;
     
    16231622            for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++)
    16241623            {
    1625                 hr = IDirectSoundBuffer8_Play(pDSoundStrmOut->pDSB, 0, 0, fFlags);
     1624                hr = IDirectSoundBuffer8_Play(pDSoundStream->pDSB, 0, 0, fFlags);
    16261625                if (   SUCCEEDED(hr)
    16271626                    || hr != DSERR_BUFFERLOST)
     
    16301629                {
    16311630                    LogFlowFunc(("Restarting playback failed due to lost buffer, restoring ...\n"));
    1632                     directSoundPlayRestore(pThis, pDSoundStrmOut->pDSB);
     1631                    directSoundPlayRestore(pThis, pDSoundStream->pDSB);
    16331632                }
    16341633            }
     
    16581657}
    16591658
    1660 static DECLCALLBACK(int) drvHostDSoundFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
     1659static int dsoundDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    16611660{
    16621661    PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    1663     PDSOUNDSTREAMOUT pDSoundStrmOut = (PDSOUNDSTREAMOUT)pHstStrmOut;
    1664 
    1665     directSoundPlayClose(pThis, pDSoundStrmOut);
    1666 
    1667     pDSoundStrmOut->cbPlayWritePos = 0;
    1668     pDSoundStrmOut->fRestartPlayback = true;
    1669     pDSoundStrmOut->csPlaybackBufferSize = 0;
    1670 
    1671     RT_ZERO(pDSoundStrmOut->streamCfg);
     1662    PDSOUNDSTREAMOUT pDSoundStream = (PDSOUNDSTREAMOUT)pStream;
     1663
     1664    directSoundPlayClose(pThis, pDSoundStream);
     1665
     1666    pDSoundStream->cbPlayWritePos = 0;
     1667    pDSoundStream->fRestartPlayback = true;
     1668    pDSoundStream->csPlaybackBufferSize = 0;
     1669
     1670    RT_ZERO(pDSoundStream->streamCfg);
    16721671
    16731672    return VINF_SUCCESS;
    16741673}
    16751674
    1676 static DECLCALLBACK(int) drvHostDSoundInitIn(PPDMIHOSTAUDIO pInterface,
    1677                                              PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg,
    1678                                              PDMAUDIORECSOURCE enmRecSource,
    1679                                              uint32_t *pcSamples)
     1675static int dsoundCreateStreamIn(PPDMIHOSTAUDIO pInterface,
     1676                                PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
    16801677{
    16811678    PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    1682     PDSOUNDSTREAMIN pDSoundStrmIn = (PDSOUNDSTREAMIN)pHstStrmIn;
    1683 
    1684     LogFlowFunc(("pHstStrmIn=%p, pAudioSettings=%p, enmRecSource=%ld\n",
    1685                  pHstStrmIn, pCfg, enmRecSource));
    1686 
    1687     pDSoundStrmIn->streamCfg = *pCfg;
    1688     pDSoundStrmIn->streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
     1679    PDSOUNDSTREAMIN pDSoundStream = (PDSOUNDSTREAMIN)pStream;
     1680
     1681    LogFlowFunc(("pStream=%p, pAudioSettings=%p, enmRecSource=%ld\n",
     1682                 pStream, pCfg, pCfg->DestSource.Source));
     1683
     1684    pDSoundStream->streamCfg = *pCfg;
     1685    pDSoundStream->streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
    16891686
    16901687    /** @todo caller should already init Props? */
    1691     int rc = DrvAudioStreamCfgToProps(&pDSoundStrmIn->streamCfg, &pHstStrmIn->Props);
     1688    int rc = DrvAudioStreamCfgToProps(&pDSoundStream->streamCfg, &pStream->Props);
    16921689    if (RT_SUCCESS(rc))
    16931690    {
    16941691        /* Init the stream structure and save relevant information to it. */
    1695         pDSoundStrmIn->csCaptureReadPos = 0;
    1696         pDSoundStrmIn->csCaptureBufferSize = 0;
    1697         pDSoundStrmIn->pDSC = NULL;
    1698         pDSoundStrmIn->pDSCB = NULL;
    1699         pDSoundStrmIn->enmRecSource = enmRecSource;
    1700         pDSoundStrmIn->hrLastCaptureIn = S_OK;
     1692        pDSoundStream->csCaptureReadPos    = 0;
     1693        pDSoundStream->csCaptureBufferSize = 0;
     1694        pDSoundStream->pDSC                = NULL;
     1695        pDSoundStream->pDSCB              = NULL;
     1696        pDSoundStream->enmRecSource        = pCfg->DestSource.Source;
     1697        pDSoundStream->hrLastCapture      = S_OK;
    17011698
    17021699        if (pcSamples)
    1703             *pcSamples = pThis->cfg.cbBufferIn >> pHstStrmIn->Props.cShift;
     1700            *pcSamples = pThis->cfg.cbBufferIn >> pStream->Props.cShift;
    17041701
    17051702        /* Try to open capture in case the device is already there. */
    1706         directSoundCaptureOpen(pThis, pDSoundStrmIn);
     1703        directSoundCaptureOpen(pThis, pDSoundStream);
    17071704    }
    17081705    else
    17091706    {
    1710         RT_ZERO(pDSoundStrmIn->streamCfg);
     1707        RT_ZERO(pDSoundStream->streamCfg);
    17111708    }
    17121709
     
    17151712}
    17161713
    1717 static DECLCALLBACK(int) drvHostDSoundControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    1718                                                 PDMAUDIOSTREAMCMD enmStreamCmd)
     1714static int dsoundControlStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     1715                                 PDMAUDIOSTREAMCMD enmStreamCmd)
    17191716{
    17201717    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1721     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    1722 
    1723     LogFlowFunc(("pHstStrmIn=%p, enmStreamCmd=%ld\n", pHstStrmIn, enmStreamCmd));
     1718    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     1719
     1720    LogFlowFunc(("pStream=%p, enmStreamCmd=%ld\n", pStream, enmStreamCmd));
    17241721
    17251722    PDRVHOSTDSOUND  pThis         = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    1726     PDSOUNDSTREAMIN pDSoundStrmIn = (PDSOUNDSTREAMIN)pHstStrmIn;
     1723    PDSOUNDSTREAMIN pDSoundStream = (PDSOUNDSTREAMIN)pStream;
    17271724
    17281725    int rc = VINF_SUCCESS;
     
    17351732        {
    17361733            /* Try to start capture. If it fails, then reopen and try again. */
    1737             hr = directSoundCaptureStart(pThis, pDSoundStrmIn);
     1734            hr = directSoundCaptureStart(pThis, pDSoundStream);
    17381735            if (FAILED(hr))
    17391736            {
    1740                 hr = directSoundCaptureClose(pDSoundStrmIn);
     1737                hr = directSoundCaptureClose(pDSoundStream);
    17411738                if (SUCCEEDED(hr))
    17421739                {
    1743                     hr = directSoundCaptureOpen(pThis, pDSoundStrmIn);
     1740                    hr = directSoundCaptureOpen(pThis, pDSoundStream);
    17441741                    if (SUCCEEDED(hr))
    1745                         hr = directSoundCaptureStart(pThis, pDSoundStrmIn);
     1742                        hr = directSoundCaptureStart(pThis, pDSoundStream);
    17461743                }
    17471744            }
     
    17551752        case PDMAUDIOSTREAMCMD_PAUSE:
    17561753        {
    1757             hr = directSoundCaptureStop(pThis, pDSoundStrmIn);
     1754            hr = directSoundCaptureStop(pThis, pDSoundStream);
    17581755            if (FAILED(hr))
    17591756                rc = VERR_NOT_SUPPORTED;
     
    17721769}
    17731770
    1774 static DECLCALLBACK(int) drvHostDSoundCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    1775                                                 uint32_t *pcSamplesCaptured)
     1771static DECLCALLBACK(int) drvHostDSoundStreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     1772                                                    uint32_t *pcSamplesCaptured)
    17761773{
    17771774    PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    17781775
    1779     PDSOUNDSTREAMIN             pDSoundStrmIn = (PDSOUNDSTREAMIN)pHstStrmIn;
    1780     LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB         = pDSoundStrmIn->pDSCB;
     1776    PDSOUNDSTREAMIN             pDSoundStream = (PDSOUNDSTREAMIN)pStream;
     1777    LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB         = pDSoundStream->pDSCB;
    17811778
    17821779    int rc = VINF_SUCCESS;
     
    17971794        if (FAILED(hr))
    17981795        {
    1799             if (hr != pDSoundStrmIn->hrLastCaptureIn)
     1796            if (hr != pDSoundStream->hrLastCapture)
    18001797            {
    18011798                DSLOGREL(("DSound: Getting capture position failed with %Rhrc\n", hr));
    1802                 pDSoundStrmIn->hrLastCaptureIn = hr;
     1799                pDSoundStream->hrLastCapture = hr;
    18031800            }
    18041801
     
    18071804        }
    18081805
    1809         pDSoundStrmIn->hrLastCaptureIn = hr;
    1810 
    1811         if (cbReadPos & pHstStrmIn->Props.uAlign)
    1812             DSLOGF(("DSound: Misaligned capture read position %ld (alignment: %RU32)\n", cbReadPos, pHstStrmIn->Props.uAlign));
     1806        pDSoundStream->hrLastCapture = hr;
     1807
     1808        if (cbReadPos & pStream->Props.uAlign)
     1809            DSLOGF(("DSound: Misaligned capture read position %ld (alignment: %RU32)\n", cbReadPos, pStream->Props.uAlign));
    18131810
    18141811        /* Capture position in samples. */
    1815         DWORD csReadPos = cbReadPos >> pHstStrmIn->Props.cShift;
     1812        DWORD csReadPos = cbReadPos >> pStream->Props.cShift;
    18161813
    18171814        /* Number of samples available in the DirectSound capture buffer. */
    1818         DWORD csCaptured = dsoundRingDistance(csReadPos, pDSoundStrmIn->csCaptureReadPos, pDSoundStrmIn->csCaptureBufferSize);
     1815        DWORD csCaptured = dsoundRingDistance(csReadPos, pDSoundStream->csCaptureReadPos, pDSoundStream->csCaptureBufferSize);
    18191816        if (csCaptured == 0)
    18201817            break;
    18211818
    18221819        /* Using as an intermediate not circular buffer. */
    1823         AudioMixBufReset(&pHstStrmIn->MixBuf);
     1820        AudioMixBufReset(&pStream->MixBuf);
    18241821
    18251822        /* Get number of free samples in the mix buffer and check that is has free space */
    1826         uint32_t csMixFree = AudioMixBufFree(&pHstStrmIn->MixBuf);
     1823        uint32_t csMixFree = AudioMixBufFree(&pStream->MixBuf);
    18271824        if (csMixFree == 0)
    18281825        {
     
    18321829
    18331830        DSLOGF(("DSound: Capture csMixFree=%RU32, csReadPos=%ld, csCaptureReadPos=%ld, csCaptured=%ld\n",
    1834                 csMixFree, csReadPos, pDSoundStrmIn->csCaptureReadPos, csCaptured));
     1831                csMixFree, csReadPos, pDSoundStream->csCaptureReadPos, csCaptured));
    18351832
    18361833        /* No need to fetch more samples than mix buffer can receive. */
     
    18401837        LPVOID pv1, pv2;
    18411838        DWORD cb1, cb2;
    1842         hr = directSoundCaptureLock(pDSCB, &pHstStrmIn->Props,
    1843                                     AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, pDSoundStrmIn->csCaptureReadPos), /* dwOffset */
    1844                                     AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, csCaptured),                      /* dwBytes */
     1839        hr = directSoundCaptureLock(pDSCB, &pStream->Props,
     1840                                    AUDIOMIXBUF_S2B(&pStream->MixBuf, pDSoundStream->csCaptureReadPos), /* dwOffset */
     1841                                    AUDIOMIXBUF_S2B(&pStream->MixBuf, csCaptured),                      /* dwBytes */
    18451842                                    &pv1, &pv2, &cb1, &cb2,
    18461843                                    0 /* dwFlags */);
     
    18511848        }
    18521849
    1853         DWORD len1 = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cb1);
    1854         DWORD len2 = AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cb2);
     1850        DWORD len1 = AUDIOMIXBUF_B2S(&pStream->MixBuf, cb1);
     1851        DWORD len2 = AUDIOMIXBUF_B2S(&pStream->MixBuf, cb2);
    18551852
    18561853        uint32_t csWrittenTotal = 0;
     
    18581855        if (pv1 && len1)
    18591856        {
    1860             rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, 0 /* offWrite */,
     1857            rc = AudioMixBufWriteAt(&pStream->MixBuf, 0 /* offWrite */,
    18611858                                    pv1, cb1, &csWritten);
    18621859            if (RT_SUCCESS(rc))
     
    18681865            && pv2 && len2)
    18691866        {
    1870             rc = AudioMixBufWriteAt(&pHstStrmIn->MixBuf, csWrittenTotal,
     1867            rc = AudioMixBufWriteAt(&pStream->MixBuf, csWrittenTotal,
    18711868                                    pv2, cb2, &csWritten);
    18721869            if (RT_SUCCESS(rc))
     
    18771874
    18781875        if (csWrittenTotal) /* Captured something? */
    1879             rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, csWrittenTotal, &cCaptured);
     1876            rc = AudioMixBufMixToParent(&pStream->MixBuf, csWrittenTotal, &cCaptured);
    18801877
    18811878        if (RT_SUCCESS(rc))
    18821879        {
    1883             pDSoundStrmIn->csCaptureReadPos = (pDSoundStrmIn->csCaptureReadPos + cCaptured) % pDSoundStrmIn->csCaptureBufferSize;
     1880            pDSoundStream->csCaptureReadPos = (pDSoundStream->csCaptureReadPos + cCaptured) % pDSoundStream->csCaptureBufferSize;
    18841881            DSLOGF(("DSound: Capture %ld (%ld+%ld), processed %RU32/%RU32\n",
    18851882                    csCaptured, len1, len2, cCaptured, csWrittenTotal));
     
    19021899}
    19031900
    1904 static DECLCALLBACK(int) drvHostDSoundFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
     1901static int dsoundDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    19051902{
    19061903    PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    1907     PDSOUNDSTREAMIN pDSoundStrmIn = (PDSOUNDSTREAMIN)pHstStrmIn;
    1908 
    1909     directSoundCaptureClose(pDSoundStrmIn);
    1910 
    1911     pDSoundStrmIn->csCaptureReadPos    = 0;
    1912     pDSoundStrmIn->csCaptureBufferSize = 0;
    1913     RT_ZERO(pDSoundStrmIn->streamCfg);
     1904    PDSOUNDSTREAMIN pDSoundStream = (PDSOUNDSTREAMIN)pStream;
     1905
     1906    directSoundCaptureClose(pDSoundStream);
     1907
     1908    pDSoundStream->csCaptureReadPos    = 0;
     1909    pDSoundStream->csCaptureBufferSize = 0;
     1910    RT_ZERO(pDSoundStream->streamCfg);
    19141911
    19151912    return VINF_SUCCESS;
    19161913}
    19171914
    1918 /** @todo Replace PDMAUDIODIR with a (registered? unique) channel ID to provide multi-channel input/output. */
    1919 static DECLCALLBACK(bool) drvHostDSoundIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
    1920 {
    1921     AssertPtrReturn(pInterface, false);
    1922 
    1923     PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    1924 
    1925     if (enmDir == PDMAUDIODIR_IN)
    1926         return pThis->fEnabledIn;
    1927 
    1928     return pThis->fEnabledOut;
    1929 }
    1930 
    1931 static DECLCALLBACK(int) drvHostDSoundGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
     1915static DECLCALLBACK(int) drvHostDSoundGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
    19321916{
    19331917    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     
    19591943}
    19601944
    1961 static DECLCALLBACK(int) drvHostDSoundThread(RTTHREAD hThreadSelf, void *pvUser)
     1945static DECLCALLBACK(int) dsoundNotificationThread(RTTHREAD hThreadSelf, void *pvUser)
    19621946{
    19631947    PDRVHOSTDSOUND pThis = (PDRVHOSTDSOUND)pvUser;
     
    20121996                {
    20131997                    DWORD cbBuffer, cbFree, cbPlayPos;
    2014                     rc = dsoundGetPosOut(pThis->pDSStrmOut, &cbBuffer, &cbFree, &cbPlayPos);
     1998                    rc = dsoundGetPosOut(pThis->pDSStream, &cbBuffer, &cbFree, &cbPlayPos);
    20151999                    if (   RT_SUCCESS(rc)
    20162000                        && cbFree)
     
    20992083
    21002084        /* Start notification thread. */
    2101         rc = RTThreadCreate(&pThis->Thread, drvHostDSoundThread,
     2085        rc = RTThreadCreate(&pThis->Thread, dsoundNotificationThread,
    21022086                            pThis /*pvUser*/, 0 /*cbStack*/,
    2103                             RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "dSoundNtfy");
     2087                            RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "dsoundNtfy");
    21042088        if (RT_SUCCESS(rc))
    21052089        {
     
    21572141}
    21582142
    2159 static void dSoundConfigInit(PDRVHOSTDSOUND pThis, PCFGMNODE pCfg)
     2143static void dsoundConfigInit(PDRVHOSTDSOUND pThis, PCFGMNODE pCfg)
    21602144{
    21612145    unsigned int uBufsizeOut, uBufsizeIn;
     
    21742158           &pThis->cfg.uuidPlay,
    21752159           &pThis->cfg.uuidCapture));
     2160}
     2161
     2162/*
     2163 * PDMIHOSTAUDIO
     2164 */
     2165
     2166static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostDSoundGetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
     2167{
     2168    AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN);
     2169
     2170    return PDMAUDIOBACKENDSTS_RUNNING;
     2171}
     2172
     2173static DECLCALLBACK(int) drvHostDSoundStreamCreate(PPDMIHOSTAUDIO pInterface,
     2174                                                   PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
     2175{
     2176    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     2177    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     2178    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
     2179
     2180    int rc;
     2181    if (pCfg->enmDir == PDMAUDIODIR_IN)
     2182        rc = dsoundCreateStreamIn(pInterface,  pStream, pCfg, pcSamples);
     2183    else
     2184        rc = dsoundCreateStreamOut(pInterface, pStream, pCfg, pcSamples);
     2185
     2186    LogFlowFunc(("%s: rc=%Rrc\n", pStream->szName, rc));
     2187    return rc;
     2188}
     2189
     2190static DECLCALLBACK(int) drvHostDSoundStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     2191{
     2192    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     2193    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     2194
     2195    int rc;
     2196    if (pStream->enmDir == PDMAUDIODIR_IN)
     2197        rc = dsoundDestroyStreamIn(pInterface,  pStream);
     2198    else
     2199        rc = dsoundDestroyStreamOut(pInterface, pStream);
     2200
     2201    return rc;
     2202}
     2203
     2204static DECLCALLBACK(int) drvHostDSoundStreamControl(PPDMIHOSTAUDIO pInterface,
     2205                                                    PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
     2206{
     2207    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     2208    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     2209
     2210    Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST);
     2211
     2212    int rc;
     2213    if (pStream->enmDir == PDMAUDIODIR_IN)
     2214        rc = dsoundControlStreamIn(pInterface,  pStream, enmStreamCmd);
     2215    else
     2216        rc = dsoundControlStreamOut(pInterface, pStream, enmStreamCmd);
     2217
     2218    return rc;
     2219}
     2220
     2221static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostDSoundStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     2222{
     2223    AssertPtrReturn(pInterface, PDMAUDIOSTRMSTS_FLAG_NONE);
     2224    AssertPtrReturn(pStream,    PDMAUDIOSTRMSTS_FLAG_NONE);
     2225
     2226    PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
     2227
     2228    PDMAUDIOSTRMSTS strmSts = PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
     2229    if (pStream->enmDir == PDMAUDIODIR_IN)
     2230    {
     2231        PDSOUNDSTREAMIN pDSoundStream = (PDSOUNDSTREAMIN)pStream;
     2232        strmSts |= pDSoundStream->fEnabled ? PDMAUDIOSTRMSTS_FLAG_ENABLED : 0;
     2233    }
     2234    else
     2235    {
     2236        PDSOUNDSTREAMOUT pDSoundStream = (PDSOUNDSTREAMOUT)pStream;
     2237        strmSts |= pDSoundStream->fEnabled ? PDMAUDIOSTRMSTS_FLAG_ENABLED : 0;
     2238    }
     2239
     2240    return strmSts;
    21762241}
    21772242
     
    22482313     * Initialize configuration values.
    22492314     */
    2250     dSoundConfigInit(pThis, pCfg);
     2315    dsoundConfigInit(pThis, pCfg);
    22512316
    22522317    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/Audio/DrvHostNullAudio.cpp

    r60925 r61157  
    4141 * THE SOFTWARE.
    4242 */
     43#include <iprt/alloc.h>
     44#include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */
     45
    4346#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
    4447#include <VBox/log.h>
     48#include <VBox/vmm/pdmaudioifs.h>
     49
    4550#include "DrvAudio.h"
    4651#include "AudioMixBuffer.h"
    47 
    4852#include "VBoxDD.h"
    4953
    50 #include <iprt/alloc.h>
    51 #include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */
    52 #include <VBox/vmm/pdmaudioifs.h>
    5354
    5455typedef struct NULLAUDIOSTREAMOUT
    5556{
    5657    /** Note: Always must come first! */
    57     PDMAUDIOHSTSTRMOUT streamOut;
     58    PDMAUDIOSTREAM     Stream;
    5859    uint64_t           u64TicksLast;
    5960    uint64_t           csPlayBuffer;
     
    6465{
    6566    /** Note: Always must come first! */
    66     PDMAUDIOHSTSTRMIN  streamIn;
     67    PDMAUDIOSTREAM     Stream;
    6768} NULLAUDIOSTREAMIN, *PNULLAUDIOSTREAMIN;
    6869
     
    8283
    8384
    84 static DECLCALLBACK(int) drvHostNullAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
     85static DECLCALLBACK(int) drvHostNullAudioGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
    8586{
    8687    NOREF(pInterface);
     
    100101}
    101102
    102 static DECLCALLBACK(int) drvHostNullAudioInit(PPDMIHOSTAUDIO pInterface)
     103static int drvHostNullAudioInit(PPDMIHOSTAUDIO pInterface)
    103104{
    104105    NOREF(pInterface);
     
    108109}
    109110
    110 static DECLCALLBACK(int) drvHostNullAudioInitIn(PPDMIHOSTAUDIO pInterface,
    111                                                 PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg,
    112                                                 PDMAUDIORECSOURCE enmRecSource,
    113                                                 uint32_t *pcSamples)
    114 {
    115     NOREF(pInterface);
    116     NOREF(enmRecSource);
     111static int nullCreateStreamIn(PPDMIHOSTAUDIO pInterface,
     112                              PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
     113{
     114    NOREF(pInterface);
    117115
    118116    /* Just adopt the wanted stream configuration. */
    119     int rc = DrvAudioStreamCfgToProps(pCfg, &pHstStrmIn->Props);
     117    int rc = DrvAudioStreamCfgToProps(pCfg, &pStream->Props);
    120118    if (RT_SUCCESS(rc))
    121119    {
     
    128126}
    129127
    130 static DECLCALLBACK(int) drvHostNullAudioInitOut(PPDMIHOSTAUDIO pInterface,
    131                                                  PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,
    132                                                  uint32_t *pcSamples)
     128static int nullCreateStreamOut(PPDMIHOSTAUDIO pInterface,
     129                               PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg,
     130                               uint32_t *pcSamples)
    133131{
    134132    NOREF(pInterface);
    135133
    136134    /* Just adopt the wanted stream configuration. */
    137     int rc = DrvAudioStreamCfgToProps(pCfg, &pHstStrmOut->Props);
     135    int rc = DrvAudioStreamCfgToProps(pCfg, &pStream->Props);
    138136    if (RT_SUCCESS(rc))
    139137    {
    140         PNULLAUDIOSTREAMOUT pNullStrmOut = (PNULLAUDIOSTREAMOUT)pHstStrmOut;
    141         pNullStrmOut->u64TicksLast  = 0;
    142         pNullStrmOut->csPlayBuffer  = _1K;
    143         pNullStrmOut->pu8PlayBuffer = (uint8_t *)RTMemAlloc(_1K << pHstStrmOut->Props.cShift);
    144         if (pNullStrmOut->pu8PlayBuffer)
     138        PNULLAUDIOSTREAMOUT pNullStream = (PNULLAUDIOSTREAMOUT)pStream;
     139        pNullStream->u64TicksLast  = 0;
     140        pNullStream->csPlayBuffer  = _1K;
     141        pNullStream->pu8PlayBuffer = (uint8_t *)RTMemAlloc(_1K << pStream->Props.cShift);
     142        if (pNullStream->pu8PlayBuffer)
    145143        {
    146144            if (pcSamples)
    147                 *pcSamples = pNullStrmOut->csPlayBuffer;
     145                *pcSamples = pNullStream->csPlayBuffer;
    148146        }
    149147        else
     
    155153}
    156154
    157 static DECLCALLBACK(bool) drvHostNullAudioIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
    158 {
    159     NOREF(pInterface);
    160     NOREF(enmDir);
    161     return true; /* Always all enabled. */
    162 }
    163 
    164 static DECLCALLBACK(int) drvHostNullAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
    165                                                  uint32_t *pcSamplesPlayed)
     155static DECLCALLBACK(int) drvHostNullAudioStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     156                                                    uint32_t *pcSamplesPlayed)
    166157{
    167158    PDRVHOSTNULLAUDIO pDrv = RT_FROM_MEMBER(pInterface, DRVHOSTNULLAUDIO, IHostAudio);
    168     PNULLAUDIOSTREAMOUT pNullStrmOut = (PNULLAUDIOSTREAMOUT)pHstStrmOut;
     159    PNULLAUDIOSTREAMOUT pNullStream = (PNULLAUDIOSTREAMOUT)pStream;
    169160
    170161    /* Consume as many samples as would be played at the current frequency since last call. */
    171     uint32_t csLive          = AudioMixBufAvail(&pHstStrmOut->MixBuf);
     162    uint32_t csLive          = AudioMixBufAvail(&pStream->MixBuf);
    172163    uint64_t u64TicksNow     = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns);
    173     uint64_t u64TicksElapsed = u64TicksNow  - pNullStrmOut->u64TicksLast;
     164    uint64_t u64TicksElapsed = u64TicksNow  - pNullStream->u64TicksLast;
    174165    uint64_t u64TicksFreq    = PDMDrvHlpTMGetVirtualFreq(pDrv->pDrvIns);
    175166
    176167    /* Remember when samples were consumed. */
    177     pNullStrmOut->u64TicksLast = u64TicksNow;
     168    pNullStream->u64TicksLast = u64TicksNow;
    178169
    179170    /*
     
    181172     * If rounding is not taken into account then the playback rate will be consistently lower that expected.
    182173     */
    183     uint64_t cSamplesPlayed = (2 * u64TicksElapsed * pHstStrmOut->Props.uHz + u64TicksFreq) / u64TicksFreq / 2;
     174    uint64_t cSamplesPlayed = (2 * u64TicksElapsed * pStream->Props.uHz + u64TicksFreq) / u64TicksFreq / 2;
    184175
    185176    /* Don't play more than available. */
     
    187178        cSamplesPlayed = csLive;
    188179
    189     cSamplesPlayed = RT_MIN(cSamplesPlayed, pNullStrmOut->csPlayBuffer);
     180    cSamplesPlayed = RT_MIN(cSamplesPlayed, pNullStream->csPlayBuffer);
    190181
    191182    uint32_t csRead = 0;
    192     AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pNullStrmOut->pu8PlayBuffer,
    193                         AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cSamplesPlayed), &csRead);
    194     AudioMixBufFinish(&pHstStrmOut->MixBuf, csRead);
     183    AudioMixBufReadCirc(&pStream->MixBuf, pNullStream->pu8PlayBuffer,
     184                        AUDIOMIXBUF_S2B(&pStream->MixBuf, cSamplesPlayed), &csRead);
     185    AudioMixBufFinish(&pStream->MixBuf, csRead);
    195186
    196187    if (pcSamplesPlayed)
     
    200191}
    201192
    202 static DECLCALLBACK(int) drvHostNullAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    203                                                    uint32_t *pcSamplesCaptured)
     193static DECLCALLBACK(int) drvHostNullAudioStreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     194                                                       uint32_t *pcSamplesCaptured)
    204195{
    205196    /* Never capture anything. */
     
    210201}
    211202
    212 static DECLCALLBACK(int) drvHostNullAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    213                                                    PDMAUDIOSTREAMCMD enmStreamCmd)
    214 {
    215     NOREF(pInterface);
    216     NOREF(pHstStrmIn);
    217     NOREF(enmStreamCmd);
    218 
    219     return VINF_SUCCESS;
    220 }
    221 
    222 static DECLCALLBACK(int) drvHostNullAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
    223                                                     PDMAUDIOSTREAMCMD enmStreamCmd)
    224 {
    225     NOREF(pInterface);
    226     NOREF(pHstStrmOut);
    227     NOREF(enmStreamCmd);
    228 
    229     return VINF_SUCCESS;
    230 }
    231 
    232 static DECLCALLBACK(int) drvHostNullAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
     203static int nullDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    233204{
    234205    LogFlowFuncLeaveRC(VINF_SUCCESS);
     
    236207}
    237208
    238 static DECLCALLBACK(int) drvHostNullAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
     209static int nullDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    239210{
    240211    PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    241212
    242     PNULLAUDIOSTREAMOUT pNullStrmOut = (PNULLAUDIOSTREAMOUT)pHstStrmOut;
    243     if (   pNullStrmOut
    244         && pNullStrmOut->pu8PlayBuffer)
     213    PNULLAUDIOSTREAMOUT pNullStream = (PNULLAUDIOSTREAMOUT)pStream;
     214    if (   pNullStream
     215        && pNullStream->pu8PlayBuffer)
    245216    {
    246         RTMemFree(pNullStrmOut->pu8PlayBuffer);
    247         pNullStrmOut->pu8PlayBuffer = NULL;
     217        RTMemFree(pNullStream->pu8PlayBuffer);
     218        pNullStream->pu8PlayBuffer = NULL;
    248219    }
    249220
    250221    LogFlowFuncLeaveRC(VINF_SUCCESS);
    251222    return VINF_SUCCESS;
     223}
     224
     225static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostNullAudioGetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
     226{
     227    AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN);
     228
     229    return PDMAUDIOBACKENDSTS_RUNNING;
     230}
     231
     232static DECLCALLBACK(int) drvHostNullAudioStreamCreate(PPDMIHOSTAUDIO pInterface,
     233                                                      PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
     234{
     235    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     236    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     237    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
     238
     239    int rc;
     240    if (pCfg->enmDir == PDMAUDIODIR_IN)
     241        rc = nullCreateStreamIn(pInterface,  pStream, pCfg, pcSamples);
     242    else
     243        rc = nullCreateStreamOut(pInterface, pStream, pCfg, pcSamples);
     244
     245    LogFlowFunc(("%s: rc=%Rrc\n", pStream->szName, rc));
     246    return rc;
     247}
     248
     249static DECLCALLBACK(int) drvHostNullAudioStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     250{
     251    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     252    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     253
     254    int rc;
     255    if (pStream->enmDir == PDMAUDIODIR_IN)
     256        rc = nullDestroyStreamIn(pInterface,  pStream);
     257    else
     258        rc = nullDestroyStreamOut(pInterface, pStream);
     259
     260    return rc;
     261}
     262
     263static DECLCALLBACK(int) drvHostNullAudioStreamControl(PPDMIHOSTAUDIO pInterface,
     264                                                       PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
     265{
     266    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     267    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     268
     269    Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST);
     270
     271    return VINF_SUCCESS;
     272}
     273
     274static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostNullAudioStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     275{
     276    NOREF(pInterface);
     277    NOREF(pStream);
     278
     279    return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED);
    252280}
    253281
  • trunk/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp

    r60925 r61157  
    1616 * --------------------------------------------------------------------
    1717 */
    18 #define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
    19 #include <VBox/log.h>
    20 #include "DrvAudio.h"
    21 #include "AudioMixBuffer.h"
    22 
    23 #include "VBoxDD.h"
    24 
    2518#include <errno.h>
    2619#include <fcntl.h>
     
    3225#include <iprt/alloc.h>
    3326#include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */
     27
     28#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
     29#include <VBox/log.h>
    3430#include <VBox/vmm/pdmaudioifs.h>
     31
     32#include "DrvAudio.h"
     33#include "AudioMixBuffer.h"
     34
     35#include "VBoxDD.h"
    3536
    3637/*********************************************************************************************************************************
     
    8081{
    8182    /** Note: Always must come first! */
    82     PDMAUDIOHSTSTRMIN  pStreamIn;
     83    PDMAUDIOSTREAM     pStreamIn;
    8384    int                hFile;
    8485    int                cFragments;
     
    9495{
    9596    /** Note: Always must come first! */
    96     PDMAUDIOHSTSTRMOUT  pStreamOut;
     97    PDMAUDIOSTREAM      pStreamOut;
    9798    int                 hFile;
    9899    int                 cFragments;
     
    333334}
    334335
    335 static DECLCALLBACK(int) drvHostOSSAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    336                                                    PDMAUDIOSTREAMCMD enmStreamCmd)
     336static int ossControlStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     337                              PDMAUDIOSTREAMCMD enmStreamCmd)
    337338{
    338339    NOREF(pInterface);
    339     NOREF(pHstStrmIn);
     340    NOREF(pStream);
    340341    NOREF(enmStreamCmd);
    341342
     
    345346}
    346347
    347 static DECLCALLBACK(int) drvHostOSSAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
    348                                                    PDMAUDIOSTREAMCMD enmStreamCmd)
     348static int ossControlStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     349                               PDMAUDIOSTREAMCMD enmStreamCmd)
    349350{
    350351    NOREF(pInterface);
    351     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    352 
    353     POSSAUDIOSTREAMOUT pThisStrmOut = (POSSAUDIOSTREAMOUT)pHstStrmOut;
     352    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     353
     354    POSSAUDIOSTREAMOUT pThisStream = (POSSAUDIOSTREAMOUT)pStream;
    354355
    355356#ifdef RT_OS_L4
    356357    return VINF_SUCCESS;
    357358#else
    358     if (!pThisStrmOut->fMemMapped)
     359    if (!pThisStream->fMemMapped)
    359360        return VINF_SUCCESS;
    360361#endif
     
    367368        case PDMAUDIOSTREAMCMD_RESUME:
    368369        {
    369             DrvAudioClearBuf(&pHstStrmOut->Props,
    370                              pThisStrmOut->pvBuf, pThisStrmOut->cbBuf, AudioMixBufSize(&pHstStrmOut->MixBuf));
     370            DrvAudioClearBuf(&pStream->Props,
     371                             pThisStream->pvBuf, pThisStream->cbBuf, AudioMixBufSize(&pStream->MixBuf));
    371372
    372373            mask = PCM_ENABLE_OUTPUT;
    373             if (ioctl(pThisStrmOut->hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0)
     374            if (ioctl(pThisStream->hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0)
    374375            {
    375376                LogRel(("OSS: Failed to enable output stream: %s\n", strerror(errno)));
     
    384385        {
    385386            mask = 0;
    386             if (ioctl(pThisStrmOut->hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0)
     387            if (ioctl(pThisStream->hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0)
    387388            {
    388389                LogRel(("OSS: Failed to disable output stream: %s\n", strerror(errno)));
     
    412413}
    413414
    414 static DECLCALLBACK(int) drvHostOSSAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    415                                                   uint32_t *pcSamplesCaptured)
     415static DECLCALLBACK(int) drvHostOSSAudioStreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     416                                                      uint32_t *pcSamplesCaptured)
    416417{
    417418    NOREF(pInterface);
    418     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    419 
    420     POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pHstStrmIn;
     419    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     420
     421    POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pStream;
    421422
    422423    int rc = VINF_SUCCESS;
    423424    size_t cbToRead = RT_MIN(pStrm->cbBuf,
    424                              AudioMixBufFreeBytes(&pHstStrmIn->MixBuf));
     425                             AudioMixBufFreeBytes(&pStream->MixBuf));
    425426
    426427    LogFlowFunc(("cbToRead=%zu\n", cbToRead));
     
    467468        {
    468469            uint32_t cWritten;
    469             rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf, pStrm->pvBuf, cbRead, &cWritten);
     470            rc = AudioMixBufWriteCirc(&pStream->MixBuf, pStrm->pvBuf, cbRead, &cWritten);
    470471            if (RT_FAILURE(rc))
    471472                break;
    472473
    473             uint32_t cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cWritten);
     474            uint32_t cbWritten = AUDIOMIXBUF_S2B(&pStream->MixBuf, cWritten);
    474475
    475476            Assert(cbToRead >= cbWritten);
     
    489490        uint32_t cProcessed = 0;
    490491        if (cWrittenTotal)
    491             rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal, &cProcessed);
     492            rc = AudioMixBufMixToParent(&pStream->MixBuf, cWrittenTotal, &cProcessed);
    492493
    493494        if (pcSamplesCaptured)
     
    502503}
    503504
    504 static DECLCALLBACK(int) drvHostOSSAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
     505static int ossDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    505506{
    506507    NOREF(pInterface);
    507     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    508 
    509     POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pHstStrmIn;
     508    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     509
     510    POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pStream;
    510511
    511512    LogFlowFuncEnter();
     
    526527}
    527528
    528 static DECLCALLBACK(int) drvHostOSSAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
     529static int ossDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    529530{
    530531    NOREF(pInterface);
    531     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    532 
    533     POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pHstStrmOut;
     532    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     533
     534    POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pStream;
    534535
    535536    LogFlowFuncEnter();
     
    575576}
    576577
    577 static DECLCALLBACK(int) drvHostOSSAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
     578static DECLCALLBACK(int) drvHostOSSAudioGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
    578579{
    579580    NOREF(pInterface);
     
    645646}
    646647
    647 static DECLCALLBACK(int) drvHostOSSAudioInitIn(PPDMIHOSTAUDIO pInterface,
    648                                                PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg,
    649                                                PDMAUDIORECSOURCE enmRecSource,
    650                                                uint32_t *pcSamples)
     648static int ossCreateStreamIn(PPDMIHOSTAUDIO pInterface,
     649                             PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
    651650{
    652651    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    653     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
     652    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    654653    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
    655654
    656655    PDRVHOSTOSSAUDIO  pThis = PDMIHOSTAUDIO_2_DRVHOSTOSSAUDIO(pInterface);
    657     POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pHstStrmIn;
     656    POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pStream;
    658657
    659658    int rc;
     
    674673        if (RT_SUCCESS(rc))
    675674        {
    676             if (obtStream.cFragments * obtStream.cbFragmentSize & pHstStrmIn->Props.uAlign)
     675            if (obtStream.cFragments * obtStream.cbFragmentSize & pStream->Props.uAlign)
    677676                LogRel(("OSS: Warning: Misaligned capturing buffer: Size = %zu, Alignment = %u\n",
    678677                        obtStream.cFragments * obtStream.cbFragmentSize,
    679                         pHstStrmIn->Props.uAlign + 1));
     678                        pStream->Props.uAlign + 1));
    680679
    681680            PDMAUDIOSTREAMCFG streamCfg;
     
    685684            streamCfg.enmEndianness = obtStream.enmENDIANNESS;
    686685
    687             rc = DrvAudioStreamCfgToProps(&streamCfg, &pHstStrmIn->Props);
     686            rc = DrvAudioStreamCfgToProps(&streamCfg, &pStream->Props);
    688687            if (RT_SUCCESS(rc))
    689688            {
    690689                cSamples = (obtStream.cFragments * obtStream.cbFragmentSize)
    691                            >> pHstStrmIn->Props.cShift;
     690                           >> pStream->Props.cShift;
    692691                if (!cSamples)
    693692                    rc = VERR_INVALID_PARAMETER;
     
    697696        if (RT_SUCCESS(rc))
    698697        {
    699             size_t cbSample = (1 << pHstStrmIn->Props.cShift);
     698            size_t cbSample = (1 << pStream->Props.cShift);
    700699
    701700            size_t cbBuf = cSamples * cbSample;
     
    726725}
    727726
    728 static DECLCALLBACK(int) drvHostOSSAudioInitOut(PPDMIHOSTAUDIO pInterface,
    729                                                 PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,
    730                                                 uint32_t *pcSamples)
     727static int ossCreateStreamOut(PPDMIHOSTAUDIO pInterface,
     728                              PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg,
     729                              uint32_t *pcSamples)
    731730{
    732731    AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
    733     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
     732    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    734733    AssertPtrReturn(pCfg,        VERR_INVALID_POINTER);
    735734
    736735    PDRVHOSTOSSAUDIO   pThis = PDMIHOSTAUDIO_2_DRVHOSTOSSAUDIO(pInterface);
    737     POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pHstStrmOut;
     736    POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pStream;
    738737
    739738    int rc;
     
    754753        if (RT_SUCCESS(rc))
    755754        {
    756             if (obtStream.cFragments * obtStream.cbFragmentSize & pHstStrmOut->Props.uAlign)
     755            if (obtStream.cFragments * obtStream.cbFragmentSize & pStream->Props.uAlign)
    757756                LogRel(("OSS: Warning: Misaligned playback buffer: Size = %zu, Alignment = %u\n",
    758757                        obtStream.cFragments * obtStream.cbFragmentSize,
    759                         pHstStrmOut->Props.uAlign + 1));
     758                        pStream->Props.uAlign + 1));
    760759
    761760            PDMAUDIOSTREAMCFG streamCfg;
     
    765764            streamCfg.enmEndianness = obtStream.enmENDIANNESS;
    766765
    767             rc = DrvAudioStreamCfgToProps(&streamCfg, &pHstStrmOut->Props);
     766            rc = DrvAudioStreamCfgToProps(&streamCfg, &pStream->Props);
    768767            if (RT_SUCCESS(rc))
    769768                cSamples = (obtStream.cFragments * obtStream.cbFragmentSize)
    770                            >> pHstStrmOut->Props.cShift;
     769                           >> pStream->Props.cShift;
    771770        }
    772771
     
    775774            pStrm->fMemMapped = false;
    776775
    777             size_t cbSamples =  cSamples << pHstStrmOut->Props.cShift;
     776            size_t cbSamples =  cSamples << pStream->Props.cShift;
    778777            Assert(cbSamples);
    779778
     
    860859}
    861860
    862 static DECLCALLBACK(int) drvHostOSSAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
    863                                                 uint32_t *pcSamplesPlayed)
     861static DECLCALLBACK(int) drvHostOSSAudioStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     862                                                   uint32_t *pcSamplesPlayed)
    864863{
    865864    NOREF(pInterface);
    866     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    867 
    868     POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pHstStrmOut;
     865    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     866
     867    POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pStream;
    869868
    870869    int rc = VINF_SUCCESS;
     
    874873    do
    875874    {
    876         size_t cbBuf = AudioMixBufSizeBytes(&pHstStrmOut->MixBuf);
    877 
    878         uint32_t cLive = AudioMixBufAvail(&pHstStrmOut->MixBuf);
     875        size_t cbBuf = AudioMixBufSizeBytes(&pStream->MixBuf);
     876
     877        uint32_t cLive = AudioMixBufAvail(&pStream->MixBuf);
    879878        uint32_t cToRead;
    880879
     
    903902            Assert(cbData);
    904903
    905             cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cbData),
     904            cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pStream->MixBuf, cbData),
    906905                             cLive);
    907906        }
     
    932931            }
    933932
    934             cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, abinfo.bytes), cLive);
     933            cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pStream->MixBuf, abinfo.bytes), cLive);
    935934            if (!cToRead)
    936935                break;
     
    938937        }
    939938#endif
    940         size_t cbToRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cToRead);
     939        size_t cbToRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cToRead);
    941940        LogFlowFunc(("cbToRead=%zu\n", cbToRead));
    942941
     
    944943        while (cbToRead)
    945944        {
    946             rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pStrm->pvBuf, cbToRead, &cRead);
     945            rc = AudioMixBufReadCirc(&pStream->MixBuf, pStrm->pvBuf, cbToRead, &cRead);
    947946            if (RT_FAILURE(rc))
    948947                break;
    949948
    950             cbRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead);
     949            cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead);
    951950            ssize_t cbWritten = write(pStrm->hFile, pStrm->pvBuf, cbRead);
    952951            if (cbWritten == -1)
     
    972971    if (RT_SUCCESS(rc))
    973972    {
    974         uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cbReadTotal);
     973        uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pStream->MixBuf, cbReadTotal);
    975974        if (cReadTotal)
    976             AudioMixBufFinish(&pHstStrmOut->MixBuf, cReadTotal);
     975            AudioMixBufFinish(&pStream->MixBuf, cReadTotal);
    977976
    978977        if (pcSamplesPlayed)
     
    989988{
    990989    NOREF(pInterface);
     990}
     991
     992static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostOSSAudioGetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
     993{
     994    AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN);
     995
     996    return PDMAUDIOBACKENDSTS_RUNNING;
     997}
     998
     999static DECLCALLBACK(int) drvHostOSSAudioStreamCreate(PPDMIHOSTAUDIO pInterface,
     1000                                                     PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
     1001{
     1002    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1003    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1004    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
     1005
     1006    int rc;
     1007    if (pCfg->enmDir == PDMAUDIODIR_IN)
     1008        rc = ossCreateStreamIn(pInterface,  pStream, pCfg, pcSamples);
     1009    else
     1010        rc = ossCreateStreamOut(pInterface, pStream, pCfg, pcSamples);
     1011
     1012    LogFlowFunc(("%s: rc=%Rrc\n", pStream->szName, rc));
     1013    return rc;
     1014}
     1015
     1016static DECLCALLBACK(int) drvHostOSSAudioStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     1017{
     1018    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1019    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1020
     1021    int rc;
     1022    if (pStream->enmDir == PDMAUDIODIR_IN)
     1023        rc = ossDestroyStreamIn(pInterface,  pStream);
     1024    else
     1025        rc = ossDestroyStreamOut(pInterface, pStream);
     1026
     1027    return rc;
     1028}
     1029
     1030static DECLCALLBACK(int) drvHostOSSAudioStreamControl(PPDMIHOSTAUDIO pInterface,
     1031                                                      PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
     1032{
     1033    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1034    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1035
     1036    Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST);
     1037
     1038    int rc;
     1039    if (pStream->enmDir == PDMAUDIODIR_IN)
     1040        rc = ossControlStreamIn(pInterface,  pStream, enmStreamCmd);
     1041    else
     1042        rc = ossControlStreamOut(pInterface, pStream, enmStreamCmd);
     1043
     1044    return rc;
     1045}
     1046
     1047static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostOSSAudioStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     1048{
     1049    NOREF(pInterface);
     1050    NOREF(pStream);
     1051
     1052    return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED);
    9911053}
    9921054
  • trunk/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp

    r61050 r61157  
    2121#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO
    2222#include <VBox/log.h>
     23#include <VBox/vmm/pdmaudioifs.h>
    2324
    2425#include <stdio.h>
     
    9091     *  Specify UINT32_MAX for unlimited logging. */
    9192    uint32_t              cLogErrors;
    92     /** Configuration option: stream name. Optional. */
    93     char                 *pszStreamName;
    9493} DRVHOSTPULSEAUDIO, *PDRVHOSTPULSEAUDIO;
    9594
    9695typedef struct PULSEAUDIOSTREAM
    9796{
    98     /** Must come first, as this struct might be
    99      *  casted to one of these structs. */
    100     union
    101     {
    102         PDMAUDIOHSTSTRMIN  In;
    103         PDMAUDIOHSTSTRMOUT Out;
    104     };
     97    /** Associated host input/output stream.
     98     *  Note: Always must come first! */
     99    PDMAUDIOSTREAM         Stream;
    105100    /** Pointer to driver instance. */
    106101    PDRVHOSTPULSEAUDIO     pDrv;
     
    398393    do
    399394    {
     395        /** @todo r=andy Use pa_stream_new_with_proplist instead. */
    400396        if (!(pStream = pa_stream_new(pThis->pContext, pszName, pSampleSpec,
    401397                                      NULL /* pa_channel_map */)))
     
    610606}
    611607
    612 static DECLCALLBACK(int) drvHostPulseAudioInitOut(PPDMIHOSTAUDIO pInterface,
    613                                                   PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,
    614                                                   uint32_t *pcSamples)
    615 {
    616     AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
    617     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
    618     AssertPtrReturn(pCfg,        VERR_INVALID_POINTER);
     608static int paCreateStreamOut(PPDMIHOSTAUDIO pInterface,
     609                             PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
     610{
     611    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     612    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     613    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
    619614    /* pcSamples is optional. */
    620615
    621616    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    622     PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmOut;
     617    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pStream;
    623618
    624619    LogFlowFuncEnter();
     
    641636
    642637    /* Note that the struct BufAttr is updated to the obtained values after this call! */
    643     char achName[64];
    644     RTStrPrintf(achName, sizeof(achName), "%.32s (out)", pThis->pszStreamName);
    645 
    646     int rc = paStreamOpen(pThis, false /* fIn */, achName, &pStrm->SampleSpec, &pStrm->BufAttr, &pStrm->pStream);
     638    int rc = paStreamOpen(pThis, false /* fIn */, "PulseAudio (Out)", &pStrm->SampleSpec, &pStrm->BufAttr, &pStrm->pStream);
    647639    if (RT_FAILURE(rc))
    648640        return rc;
     
    660652    streamCfg.cChannels = pStrm->SampleSpec.channels;
    661653
    662     rc = DrvAudioStreamCfgToProps(&streamCfg, &pHstStrmOut->Props);
     654    rc = DrvAudioStreamCfgToProps(&streamCfg, &pStream->Props);
    663655    if (RT_SUCCESS(rc))
    664656    {
     
    672664                pStrm->cbPCMBuf = cbBuf;
    673665
    674                 uint32_t cSamples = cbBuf >> pHstStrmOut->Props.cShift;
     666                uint32_t cSamples = cbBuf >> pStream->Props.cShift;
    675667                if (pcSamples)
    676668                    *pcSamples = cSamples;
     
    692684}
    693685
    694 static DECLCALLBACK(bool) drvHostPulseAudioIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
    695 {
    696     NOREF(pInterface);
    697     NOREF(enmDir);
    698     return true; /* Always all enabled. */
    699 }
    700 
    701 static DECLCALLBACK(int) drvHostPulseAudioInitIn(PPDMIHOSTAUDIO pInterface,
    702                                                  PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg,
    703                                                  PDMAUDIORECSOURCE enmRecSource,
    704                                                  uint32_t *pcSamples)
     686static int paCreateStreamIn(PPDMIHOSTAUDIO pInterface,
     687                            PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
    705688{
    706689    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    707     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
    708     AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
     690    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     691    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
    709692    /* pcSamples is optional. */
    710693
    711694    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    712     PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmIn;
    713 
    714     LogFunc(("enmRecSrc=%ld\n", enmRecSource));
     695    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pStream;
    715696
    716697    pStrm->SampleSpec.format   = paFmtToPulse(pCfg->enmFormat);
     
    722703                                   * s_pulseCfg.buffer_msecs_in) / 1000;
    723704    pStrm->BufAttr.maxlength   = (pStrm->BufAttr.fragsize * 3) / 2;
    724     /* Note: Other members of pa_buffer_attr are ignored for record streams. */
    725 
    726     char achName[64];
    727     RTStrPrintf(achName, sizeof(achName), "%.32s (in)", pThis->pszStreamName);
    728 
    729     int rc = paStreamOpen(pThis, true /* fIn */, achName, &pStrm->SampleSpec, &pStrm->BufAttr,
     705
     706    /* Note: Other members of BufAttr are ignored for record streams. */
     707    int rc = paStreamOpen(pThis, true /* fIn */, "PulseAudio (In)", &pStrm->SampleSpec, &pStrm->BufAttr,
    730708                          &pStrm->pStream);
    731709    if (RT_FAILURE(rc))
     
    744722    streamCfg.cChannels = pStrm->SampleSpec.channels;
    745723
    746     rc = DrvAudioStreamCfgToProps(&streamCfg, &pHstStrmIn->Props);
     724    rc = DrvAudioStreamCfgToProps(&streamCfg, &pStream->Props);
    747725    if (RT_SUCCESS(rc))
    748726    {
    749727        uint32_t cSamples = RT_MIN(pStrm->BufAttr.fragsize * 10, pStrm->BufAttr.maxlength)
    750                             >> pHstStrmIn->Props.cShift;
    751         LogFunc(("cShift=%RU8, cSamples=%RU32\n", pHstStrmIn->Props.cShift, cSamples));
     728                            >> pStream->Props.cShift;
     729
     730        LogFunc(("uHz=%RU32, cChannels=%RU8, cShift=%RU8, cSamples=%RU32\n",
     731                 pStream->Props.uHz, pStream->Props.cChannels, pStream->Props.cShift, cSamples));
    752732
    753733        if (pcSamples)
     
    764744}
    765745
    766 static DECLCALLBACK(int) drvHostPulseAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    767                                                     uint32_t *pcSamplesCaptured)
     746static DECLCALLBACK(int) drvHostPulseAudioStreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     747                                                        uint32_t *pcSamplesCaptured)
    768748{
    769749    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    770     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
     750    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
    771751    /* pcSamplesPlayed is optional. */
    772752
    773753    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    774     PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmIn;
     754    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pStream;
    775755
    776756    /* We should only call pa_stream_readable_size() once and trust the first value. */
     
    798778    int rc = VINF_SUCCESS;
    799779
    800     size_t cbToRead = RT_MIN(cbAvail, AudioMixBufFreeBytes(&pHstStrmIn->MixBuf));
     780    size_t cbToRead = RT_MIN(cbAvail, AudioMixBufFreeBytes(&pStream->MixBuf));
    801781
    802782    LogFlowFunc(("cbToRead=%zu, cbAvail=%zu, offPeekBuf=%zu, cbPeekBuf=%zu\n",
     
    838818        {
    839819            uint32_t cWritten;
    840             rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf,
     820            rc = AudioMixBufWriteCirc(&pStream->MixBuf,
    841821                                      pStrm->pu8PeekBuf + pStrm->offPeekBuf,
    842822                                      cbToWrite, &cWritten);
     
    844824                break;
    845825
    846             uint32_t cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cWritten);
     826            uint32_t cbWritten = AUDIOMIXBUF_S2B(&pStream->MixBuf, cWritten);
    847827
    848828            Assert(cbToRead >= cbWritten);
     
    871851        uint32_t cProcessed = 0;
    872852        if (cWrittenTotal)
    873             rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal,
     853            rc = AudioMixBufMixToParent(&pStream->MixBuf, cWrittenTotal,
    874854                                        &cProcessed);
    875855
     
    885865}
    886866
    887 static DECLCALLBACK(int) drvHostPulseAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,
    888                                                   uint32_t *pcSamplesPlayed)
     867static DECLCALLBACK(int) drvHostPulseAudioStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     868                                                     uint32_t *pcSamplesPlayed)
    889869{
    890870    AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
    891     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
     871    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    892872    /* pcSamplesPlayed is optional. */
    893873
    894     PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    895     PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmOut;
     874    PDRVHOSTPULSEAUDIO pThis     = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     875    PPULSEAUDIOSTREAM  pPAStream = (PPULSEAUDIOSTREAM)pStream;
    896876
    897877    int rc = VINF_SUCCESS;
    898878    uint32_t cbReadTotal = 0;
    899879
    900     uint32_t cLive = AudioMixBufAvail(&pHstStrmOut->MixBuf);
     880    uint32_t cLive = AudioMixBufAvail(&pStream->MixBuf);
    901881    if (!cLive)
    902882    {
    903 #if 0
    904883        LogFlowFunc(("No live samples, skipping\n"));
    905 #endif
    906884        if (pcSamplesPlayed)
    907885            *pcSamplesPlayed = 0;
     
    913891    do
    914892    {
    915         size_t cbWriteable = pa_stream_writable_size(pStrm->pStream);
     893        size_t cbWriteable = pa_stream_writable_size(pPAStream->pStream);
    916894        if (cbWriteable == (size_t)-1)
    917895        {
    918             rc = paError(pStrm->pDrv, "Failed to determine output data size");
    919             break;
    920         }
    921 
    922         size_t cbLive   = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cLive);
     896            rc = paError(pPAStream->pDrv, "Failed to determine output data size");
     897            break;
     898        }
     899
     900        size_t cbLive   = AUDIOMIXBUF_S2B(&pStream->MixBuf, cLive);
    923901        size_t cbToRead = RT_MIN(cbWriteable, cbLive);
    924902
     
    929907        while (cbToRead)
    930908        {
    931             rc = AudioMixBufReadCirc(&pHstStrmOut->MixBuf, pStrm->pvPCMBuf,
    932                                      RT_MIN(cbToRead, pStrm->cbPCMBuf), &cRead);
     909            rc = AudioMixBufReadCirc(&pStream->MixBuf, pPAStream->pvPCMBuf,
     910                                     RT_MIN(cbToRead, pPAStream->cbPCMBuf), &cRead);
    933911            if (   !cRead
    934912                || RT_FAILURE(rc))
     
    937915            }
    938916
    939             cbRead = AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead);
    940             if (pa_stream_write(pStrm->pStream, pStrm->pvPCMBuf, cbRead, NULL /* Cleanup callback */,
     917            cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead);
     918            if (pa_stream_write(pPAStream->pStream, pPAStream->pvPCMBuf, cbRead, NULL /* Cleanup callback */,
    941919                                0, PA_SEEK_RELATIVE) < 0)
    942920            {
    943                 rc = paError(pStrm->pDrv, "Failed to write to output stream");
     921                rc = paError(pPAStream->pDrv, "Failed to write to output stream");
    944922                break;
    945923            }
     
    950928
    951929            LogFlowFunc(("\tcRead=%RU32 (%zu bytes) cbReadTotal=%RU32, cbToRead=%RU32\n",
    952                          cRead, AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cRead), cbReadTotal, cbToRead));
     930                         cRead, AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead), cbReadTotal, cbToRead));
    953931        }
    954932
     
    959937    if (RT_SUCCESS(rc))
    960938    {
    961         uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pHstStrmOut->MixBuf, cbReadTotal);
     939        uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pStream->MixBuf, cbReadTotal);
    962940        if (cReadTotal)
    963             AudioMixBufFinish(&pHstStrmOut->MixBuf, cReadTotal);
     941            AudioMixBufFinish(&pStream->MixBuf, cReadTotal);
    964942
    965943        if (pcSamplesPlayed)
     
    11481126}
    11491127
    1150 static DECLCALLBACK(int) drvHostPulseAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)
     1128static int paDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    11511129{
    11521130    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1153     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
     1131    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    11541132
    11551133    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    1156     PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmIn;
     1134    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pStream;
    11571135
    11581136    LogFlowFuncEnter();
     
    11611139    {
    11621140        pa_threaded_mainloop_lock(pThis->pMainLoop);
     1141
    11631142        pa_stream_disconnect(pStrm->pStream);
    11641143        pa_stream_unref(pStrm->pStream);
     1144
    11651145        pa_threaded_mainloop_unlock(pThis->pMainLoop);
    11661146
     
    11711151}
    11721152
    1173 static DECLCALLBACK(int) drvHostPulseAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)
     1153static int paDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    11741154{
    11751155    AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
    1176     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
     1156    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    11771157
    11781158    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    1179     PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmOut;
     1159    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pStream;
    11801160
    11811161    LogFlowFuncEnter();
     
    11841164    {
    11851165        pa_threaded_mainloop_lock(pThis->pMainLoop);
     1166
    11861167        pa_stream_disconnect(pStrm->pStream);
    11871168        pa_stream_unref(pStrm->pStream);
     1169
    11881170        pa_threaded_mainloop_unlock(pThis->pMainLoop);
    11891171
     
    12011183}
    12021184
    1203 static DECLCALLBACK(int) drvHostPulseAudioControlOut(PPDMIHOSTAUDIO pInterface,
    1204                                                      PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd)
     1185static int paControlStreamOut(PPDMIHOSTAUDIO pInterface,
     1186                              PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    12051187{
    12061188    AssertPtrReturn(pInterface , VERR_INVALID_POINTER);
    1207     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
     1189    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    12081190
    12091191    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    1210     PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmOut;
     1192    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pStream;
    12111193
    12121194    int rc = VINF_SUCCESS;
     
    12641246}
    12651247
    1266 static DECLCALLBACK(int) drvHostPulseAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,
    1267                                                     PDMAUDIOSTREAMCMD enmStreamCmd)
     1248static int paControlStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream,
     1249                             PDMAUDIOSTREAMCMD enmStreamCmd)
    12681250{
    12691251    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1270     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
     1252    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    12711253
    12721254    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    1273     PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pHstStrmIn;
     1255    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pStream;
    12741256
    12751257    int rc = VINF_SUCCESS;
     
    13121294}
    13131295
    1314 static DECLCALLBACK(int) drvHostPulseAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
    1315 {
    1316     AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
    1317     AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
    1318 
    1319     PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
    1320 
    1321     return paEnumerate(pThis, pCfg, PULSEAUDIOENUMCBFLAGS_LOG /* fEnum */);
    1322 }
    1323 
    13241296static DECLCALLBACK(void) drvHostPulseAudioShutdown(PPDMIHOSTAUDIO pInterface)
    13251297{
     
    13471319
    13481320    LogFlowFuncLeave();
     1321}
     1322
     1323static DECLCALLBACK(int) drvHostPulseAudioGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)
     1324{
     1325    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1326    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
     1327
     1328    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     1329
     1330    return paEnumerate(pThis, pCfg, PULSEAUDIOENUMCBFLAGS_LOG /* fEnum */);
     1331}
     1332
     1333static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostPulseAudioGetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)
     1334{
     1335    AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN);
     1336
     1337    return PDMAUDIOBACKENDSTS_RUNNING;
     1338}
     1339
     1340static DECLCALLBACK(int) drvHostPulseAudioStreamCreate(PPDMIHOSTAUDIO pInterface,
     1341                                                       PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples)
     1342{
     1343    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1344    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1345    AssertPtrReturn(pCfg,       VERR_INVALID_POINTER);
     1346
     1347    int rc;
     1348    if (pCfg->enmDir == PDMAUDIODIR_IN)
     1349        rc = paCreateStreamIn(pInterface,  pStream, pCfg, pcSamples);
     1350    else
     1351        rc = paCreateStreamOut(pInterface, pStream, pCfg, pcSamples);
     1352
     1353    LogFlowFunc(("%s: rc=%Rrc\n", pStream->szName, rc));
     1354    return rc;
     1355}
     1356
     1357static DECLCALLBACK(int) drvHostPulseAudioStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     1358{
     1359    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1360    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1361
     1362    int rc;
     1363    if (pStream->enmDir == PDMAUDIODIR_IN)
     1364        rc = paDestroyStreamIn(pInterface,  pStream);
     1365    else
     1366        rc = paDestroyStreamOut(pInterface, pStream);
     1367
     1368    return rc;
     1369}
     1370
     1371static DECLCALLBACK(int) drvHostPulseAudioStreamControl(PPDMIHOSTAUDIO pInterface,
     1372                                                        PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
     1373{
     1374    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1375    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1376
     1377    Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST);
     1378
     1379    int rc;
     1380    if (pStream->enmDir == PDMAUDIODIR_IN)
     1381        rc = paControlStreamIn(pInterface,  pStream, enmStreamCmd);
     1382    else
     1383        rc = paControlStreamOut(pInterface, pStream, enmStreamCmd);
     1384
     1385    return rc;
     1386}
     1387
     1388static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostPulseAudioStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     1389{
     1390    NOREF(pInterface);
     1391    NOREF(pStream);
     1392
     1393    return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED);
    13491394}
    13501395
     
    13771422    LogRel(("Audio: Initializing PulseAudio driver\n"));
    13781423
    1379     CFGMR3QueryStringAlloc(pCfg, "StreamName", &pThis->pszStreamName);
    1380 
    13811424    pThis->pDrvIns                   = pDrvIns;
    13821425    /* IBase */
     
    13971440    PDRVHOSTPULSEAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPULSEAUDIO);
    13981441    LogFlowFuncEnter();
    1399     if (pThis->pszStreamName)
    1400     {
    1401         MMR3HeapFree(pThis->pszStreamName);
    1402         pThis->pszStreamName = NULL;
    1403     }
    14041442}
    14051443
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