VirtualBox

Changeset 61320 in vbox for trunk


Ignore:
Timestamp:
May 31, 2016 8:43:19 AM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
107614
Message:

Audio: Update.

Location:
trunk
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/Config.kmk

    r61312 r61320  
    430430# Enable new PS/2 mouse emulation.
    431431VBOX_WITH_NEW_PS2M = 1
    432 # Enable ALSA support for Linux.
     432# Enable OSS audio support.
     433VBOX_WITH_OSS = 1
     434# Enable ALSA audio support.
    433435VBOX_WITH_ALSA = 1
    434 # Enable Pulse support for Linux.
     436# Enable PulseAudio audio support.
    435437VBOX_WITH_PULSE = 1
    436438# Enable PCI passthrough support.
  • trunk/include/VBox/vmm/pdmaudioifs.h

    r61166 r61320  
    381381    /** Size of the sample buffer (in samples). */
    382382    uint32_t                  cSamples;
    383 #if 1
    384     /** The current read/write position (in samples)
    385      *  in the samples buffer. */
    386     uint32_t                  offReadWrite;
     383    /** The current read position (in samples). */
     384    uint32_t                  offRead;
     385    /** The current write position (in samples). */
     386    uint32_t                  offWrite;
    387387    /**
    388388     * Total samples already mixed down to the parent buffer (if any). Always starting at
    389      * the parent's offReadWrite position.
     389     * the parent's offRead position.
    390390     *
    391391     * Note: Count always is specified in parent samples, as the sample count can differ between parent
     
    393393     */
    394394    uint32_t                  cMixed;
    395     uint32_t                  cProcessed;
    396 #else
    397     /** The current read position in the buffer. */
    398     uint32_t          offRead;
    399     /** Is a read block acquired currently? */
    400     bool            fReading;
    401     /** Is a write block acquired currently? */
    402     bool            fWriting;
    403     /** The current write position in the buffer. */
    404     uint32_t          offWrite;
    405     /** How much space of the buffer is currently in use. */
    406     volatile uint32_t cUsed;
    407     uint32_t                 cMixed;
    408 #endif
     395    /** How much audio samples are currently being used
     396     *  in this buffer.
     397     *  Note: This also is known as the distance in ring buffer terms. */
     398    uint32_t                  cUsed;
    409399    /** Pointer to parent buffer (if any). */
    410400    PPDMAUDIOMIXBUF           pParent;
    411401    /** List of children mix buffers to keep in sync with (if being a parent buffer). */
    412     RTLISTANCHOR              lstBuffers;
     402    RTLISTANCHOR              lstChildren;
    413403    /** Intermediate structure for buffer conversion tasks. */
    414404    PPDMAUDIOSTRMRATE         pRate;
     
    453443 *  which rely on its data. */
    454444#define PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE RT_BIT_32(3)
     445/** Data can be read from the stream. */
     446#define PDMAUDIOSTRMSTS_FLAG_DATA_READABLE   RT_BIT_32(4)
     447/** Data can be written to the stream. */
     448#define PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE   RT_BIT_32(5)
    455449/** Validation mask. */
    456 #define PDMAUDIOSTRMSTS_VALID_MASK           UINT32_C(0x0000000F)
     450#define PDMAUDIOSTRMSTS_VALID_MASK           UINT32_C(0x0000003F)
    457451
    458452/**
     
    581575{
    582576    /**
     577     * Retrieves the current configuration of the host audio backend.
     578     *
     579     * @returns VBox status code.
     580     *
     581     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     582     * @param   pCfg            Where to store the host audio backend configuration data.
     583     */
     584    DECLR3CALLBACKMEMBER(int, pfnGetConfig, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg));
     585
     586    /**
     587     *  @todo Docs!
     588     */
     589    DECLR3CALLBACKMEMBER(PDMAUDIOBACKENDSTS, pfnGetStatus, (PPDMIAUDIOCONNECTOR pInterface, PDMAUDIODIR enmDir));
     590
     591    /**
     592     * Creates an audio stream.
     593     *
     594     * @returns VBox status code.
     595     * @param   pInterface           Pointer to the interface structure containing the called function pointer.
     596     * @param   pCfgHost             Stream configuration for host side.
     597     * @param   pCfgGuest            Stream configuration for guest side.
     598     * @param   ppStream             Pointer where to return the created audio stream on success.
     599     */
     600    DECLR3CALLBACKMEMBER(int, pfnStreamCreate, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfgHost, PPDMAUDIOSTREAMCFG pCfgGuest, PPDMAUDIOSTREAM *ppStream));
     601
     602    /**
     603     * Destroys an audio stream.
     604     *
     605     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     606     * @param   pStream         Pointer to audio stream.
     607     */
     608    DECLR3CALLBACKMEMBER(int, pfnStreamDestroy, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream));
     609
     610    /**
    583611     * Adds a reference to the specified audio stream.
    584612     *
     
    623651
    624652    /**
    625      * Retrieves the current configuration of the host audio backend.
    626      *
    627      * @returns VBox status code.
    628      *
    629      * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    630      * @param   pCfg            Where to store the host audio backend configuration data.
    631      */
    632     DECLR3CALLBACKMEMBER(int, pfnGetConfig, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg));
    633 
    634     /**
    635      * Creates an audio stream.
    636      *
    637      * @returns VBox status code.
    638      * @param   pInterface           Pointer to the interface structure containing the called function pointer.
    639      * @param   pCfgHost             Stream configuration for host side.
    640      * @param   pCfgGuest            Stream configuration for guest side.
    641      * @param   ppStream             Pointer where to return the created audio stream on success.
    642      */
    643     DECLR3CALLBACKMEMBER(int, pfnStreamCreate, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfgHost, PPDMAUDIOSTREAMCFG pCfgGuest, PPDMAUDIOSTREAM *ppStream));
    644 
    645     /**
    646      * Destroys an audio stream.
    647      *
    648      * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    649      * @param   pStream         Pointer to audio stream.
    650      */
    651     DECLR3CALLBACKMEMBER(int, pfnStreamDestroy, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream));
    652 
    653     /**
    654653     * Controls a specific audio stream.
    655654     *
     
    662661
    663662    /**
    664      * Processes stream data and optionally returns its current status.
     663     * Processes stream data.
    665664     *
    666665     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     666     * @param   pStream         Pointer to audio stream.
    667667     * @param   pcData          Data (in audio samples) available. Optional.
    668668     */
    669     DECLR3CALLBACKMEMBER(int, pfnStreamGetData, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, uint32_t *pcData));
     669    DECLR3CALLBACKMEMBER(int, pfnStreamIterate, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream));
    670670
    671671    /**
     
    695695
    696696/** PDMIAUDIOCONNECTOR interface ID. */
    697 #define PDMIAUDIOCONNECTOR_IID                  "9CDE2581-41B1-838E-24A5-448B2D0C822E"
     697#define PDMIAUDIOCONNECTOR_IID                  "9E03C980-64E9-42EC-9C70-316995990BE3"
    698698
    699699
     
    714714        pThis->IHostAudio.pfnStreamControl   = RT_CONCAT(a_NamePrefix,StreamControl); \
    715715        pThis->IHostAudio.pfnStreamGetStatus = RT_CONCAT(a_NamePrefix,StreamGetStatus); \
     716        pThis->IHostAudio.pfnStreamIterate   = RT_CONCAT(a_NamePrefix,StreamIterate); \
    716717        pThis->IHostAudio.pfnStreamPlay      = RT_CONCAT(a_NamePrefix,StreamPlay); \
    717718        pThis->IHostAudio.pfnStreamCapture   = RT_CONCAT(a_NamePrefix,StreamCapture); \
     
    798799
    799800    /**
     801     ** @todo Docs!
     802     */
     803    DECLR3CALLBACKMEMBER(int, pfnStreamIterate, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream));
     804
     805    /**
    800806     * Plays an audio (output) stream.
    801807     *
     
    820826
    821827/** PDMIHOSTAUDIO interface ID. */
    822 #define PDMIHOSTAUDIO_IID                           "946441D4-7C82-4654-90DD-443BEF796E21"
     828#define PDMIHOSTAUDIO_IID                           "96AC69D0-F301-42AC-8F1D-1E19BA808887"
    823829
    824830/** @} */
  • trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp

    r61187 r61320  
    6161#endif
    6262
     63DECLINLINE(void) audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf);
    6364
    6465/*
     
    177178
    178179    uint32_t cSamplesRead;
    179     if (pMixBuf->offReadWrite + cSamplesToRead > pMixBuf->cSamples)
    180     {
    181         cSamplesRead = pMixBuf->cSamples - pMixBuf->offReadWrite;
     180    if (pMixBuf->offRead + cSamplesToRead > pMixBuf->cSamples)
     181    {
     182        cSamplesRead = pMixBuf->cSamples - pMixBuf->offRead;
    182183        rc = VINF_TRY_AGAIN;
    183184    }
     
    188189    }
    189190
    190     *ppvSamples = &pMixBuf->pSamples[pMixBuf->offReadWrite];
     191    *ppvSamples = &pMixBuf->pSamples[pMixBuf->offRead];
    191192    AssertPtr(ppvSamples);
    192193
    193     pMixBuf->offReadWrite = (pMixBuf->offReadWrite + cSamplesRead) % pMixBuf->cSamples;
    194     Assert(pMixBuf->offReadWrite <= pMixBuf->cSamples);
    195     pMixBuf->cProcessed -= RT_MIN(cSamplesRead, pMixBuf->cProcessed);
     194    pMixBuf->offRead = (pMixBuf->offRead + cSamplesRead) % pMixBuf->cSamples;
     195    Assert(pMixBuf->offRead <= pMixBuf->cSamples);
     196    pMixBuf->cUsed -= RT_MIN(cSamplesRead, pMixBuf->cUsed);
    196197
    197198    *pcSamplesRead = cSamplesRead;
     
    214215        cAvail = pMixBuf->cMixed;
    215216    else
    216         cAvail = pMixBuf->cProcessed;
     217        cAvail = pMixBuf->cUsed;
    217218
    218219    Assert(cAvail <= pMixBuf->cSamples);
     
    235236
    236237/**
    237  * Clears (zeroes) the buffer by a certain amount of (processed) samples and
     238 * Clears (zeroes) the buffer by a certain amount of (used) samples and
    238239 * keeps track to eventually assigned children buffers.
    239240 *
     
    243244void AudioMixBufFinish(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToClear)
    244245{
    245     AUDMIXBUF_LOG(("cSamples=%RU32\n", cSamplesToClear));
    246     AUDMIXBUF_LOG(("%s: offReadWrite=%RU32, cProcessed=%RU32\n",
    247                    pMixBuf->pszName, pMixBuf->offReadWrite, pMixBuf->cProcessed));
     246    AUDMIXBUF_LOG(("cSamplesToClear=%RU32\n", cSamplesToClear));
     247    AUDMIXBUF_LOG(("%s: offRead=%RU32, cUsed=%RU32\n",
     248                   pMixBuf->pszName, pMixBuf->offRead, pMixBuf->cUsed));
    248249
    249250    PPDMAUDIOMIXBUF pIter;
    250     RTListForEach(&pMixBuf->lstBuffers, pIter, PDMAUDIOMIXBUF, Node)
     251    RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)
    251252    {
    252253        AUDMIXBUF_LOG(("\t%s: cMixed=%RU32 -> %RU32\n",
    253254                       pIter->pszName, pIter->cMixed, pIter->cMixed - cSamplesToClear));
    254255
     256        Assert(cSamplesToClear <= pIter->cMixed);
    255257        pIter->cMixed -= RT_MIN(pIter->cMixed, cSamplesToClear);
    256         pIter->offReadWrite = 0;
    257     }
    258 
    259     uint32_t cLeft = RT_MIN(cSamplesToClear, pMixBuf->cSamples);
    260     uint32_t offClear;
    261 
    262     if (cLeft > pMixBuf->offReadWrite) /* Zero end of buffer first (wrap-around). */
    263     {
    264         AUDMIXBUF_LOG(("Clearing1: %RU32 - %RU32\n",
    265                        (pMixBuf->cSamples - (cLeft - pMixBuf->offReadWrite)),
    266                         pMixBuf->cSamples));
    267 
    268         RT_BZERO(pMixBuf->pSamples + (pMixBuf->cSamples - (cLeft - pMixBuf->offReadWrite)),
    269                  (cLeft - pMixBuf->offReadWrite) * sizeof(PDMAUDIOSAMPLE));
    270 
    271         cLeft -= cLeft - pMixBuf->offReadWrite;
    272         offClear = 0;
    273     }
    274     else
    275         offClear = pMixBuf->offReadWrite - cLeft;
    276 
    277     if (cLeft)
    278     {
    279         AUDMIXBUF_LOG(("Clearing2: %RU32 - %RU32\n",
    280                        offClear, offClear + cLeft));
    281         RT_BZERO(pMixBuf->pSamples + offClear, cLeft * sizeof(PDMAUDIOSAMPLE));
     258    }
     259
     260    Assert(cSamplesToClear <= pMixBuf->cSamples);
     261
     262    uint32_t cClearOff;
     263    uint32_t cClearLen;
     264
     265    /* Clear end of buffer (wrap around). */
     266    if (cSamplesToClear > pMixBuf->offRead)
     267    {
     268        cClearOff = pMixBuf->cSamples - (cSamplesToClear - pMixBuf->offRead);
     269        cClearLen = pMixBuf->cSamples - cClearOff;
     270
     271        AUDMIXBUF_LOG(("Clearing1: %RU32 - %RU32\n", cClearOff, cClearOff + cClearLen));
     272
     273        RT_BZERO(pMixBuf->pSamples + cClearOff, cClearLen * sizeof(PDMAUDIOSAMPLE));
     274
     275        Assert(cSamplesToClear >= cClearLen);
     276        cSamplesToClear -= cClearLen;
     277    }
     278
     279    /* Clear beginning of buffer. */
     280    if (   cSamplesToClear
     281        && pMixBuf->offRead)
     282    {
     283        Assert(pMixBuf->offRead >= cSamplesToClear);
     284
     285        cClearOff = pMixBuf->offRead - cSamplesToClear;
     286        cClearLen = cSamplesToClear;
     287
     288        AUDMIXBUF_LOG(("Clearing2: %RU32 - %RU32\n", cClearOff, cClearOff + cClearLen));
     289
     290        RT_BZERO(pMixBuf->pSamples + cClearOff, cClearLen * sizeof(PDMAUDIOSAMPLE));
    282291    }
    283292}
     
    342351    else /* As a parent. */
    343352    {
    344         Assert(pMixBuf->cSamples >= pMixBuf->cProcessed);
    345         cSamplesFree = pMixBuf->cSamples - pMixBuf->cProcessed;
     353        Assert(pMixBuf->cSamples >= pMixBuf->cUsed);
     354        cSamplesFree = pMixBuf->cSamples - pMixBuf->cUsed;
    346355    }
    347356
     
    757766
    758767    pMixBuf->pParent = NULL;
    759     RTListInit(&pMixBuf->lstBuffers);
     768    RTListInit(&pMixBuf->lstChildren);
    760769
    761770    pMixBuf->pSamples = NULL;
    762771    pMixBuf->cSamples = 0;
    763772
    764     pMixBuf->offReadWrite = 0;
    765     pMixBuf->cMixed       = 0;
    766     pMixBuf->cProcessed   = 0;
     773    pMixBuf->offRead  = 0;
     774    pMixBuf->offWrite = 0;
     775    pMixBuf->cMixed   = 0;
     776    pMixBuf->cUsed    = 0;
    767777
    768778    /* Set initial volume to max. */
     
    813823    if (pMixBuf->pParent)
    814824        return (pMixBuf->cMixed == 0);
    815     return (pMixBuf->cProcessed == 0);
     825    return (pMixBuf->cUsed == 0);
    816826}
    817827
     
    855865    }
    856866
    857     RTListAppend(&pParent->lstBuffers, &pMixBuf->Node);
     867    RTListAppend(&pParent->lstChildren, &pMixBuf->Node);
    858868    pMixBuf->pParent = pParent;
    859869
     
    865875        pMixBuf->iFreqRatio = 1 << 20; /* Do a 1:1 conversion instead. */
    866876
     877    int rc = VINF_SUCCESS;
     878#if 0
    867879    uint32_t cSamples = (uint32_t)RT_MIN(  ((uint64_t)pParent->cSamples << 32)
    868880                                         / pMixBuf->iFreqRatio, _64K /* 64K samples max. */);
     
    892904        }
    893905    }
     906#endif
    894907
    895908    if (RT_SUCCESS(rc))
     
    955968    AssertPtrReturn(pDst,  VERR_INVALID_POINTER);
    956969    AssertPtrReturn(pSrc,  VERR_INVALID_POINTER);
    957     AssertReturn(cSamples, VERR_INVALID_PARAMETER);
    958970    /* pcProcessed is optional. */
    959971
    960     /* Live samples indicate how many samples there are in the source buffer
    961      * which have not been processed yet by the destination buffer. */
    962     uint32_t cLive = pSrc->cMixed;
    963     if (cLive >= pDst->cSamples)
    964         AUDMIXBUF_LOG(("Destination buffer \"%s\" full (%RU32 samples max), live samples = %RU32\n",
    965                        pDst->pszName, pDst->cSamples, cLive));
    966 
    967     /* Dead samples are the number of samples in the destination buffer which
    968      * will not be needed, that is, are not needed in order to process the live
    969      * samples of the source buffer. */
    970     uint32_t cDead         = pDst->cSamples - cLive;
    971 
    972     uint32_t cToReadTotal  = (uint32_t)RT_MIN(cSamples, AUDIOMIXBUF_S2S_RATIO(pSrc, cDead));
    973     uint32_t offRead       = 0;
    974 
     972    AssertMsgReturn(pDst == pSrc->pParent, ("Source buffer '%s' is not a child of destination '%s'\n",
     973                                            pSrc->pszName, pDst->pszName), VERR_INVALID_PARAMETER);
    975974    uint32_t cReadTotal    = 0;
    976975    uint32_t cWrittenTotal = 0;
    977     uint32_t offWrite      = (pDst->offReadWrite + cLive) % pDst->cSamples;
    978 
    979     AUDMIXBUF_LOG(("pSrc=%s (%RU32 samples, %RU8 chan), pDst=%s (%RU32 samples, %RU8 chan), " \
    980                    "cLive=%RU32, cDead=%RU32, cToReadTotal=%RU32, offWrite=%RU32\n",
    981                    pSrc->pszName, pSrc->cSamples, AUDMIXBUF_FMT_CHANNELS(pSrc->AudioFmt),
    982                    pDst->pszName, pDst->cSamples, AUDMIXBUF_FMT_CHANNELS(pDst->AudioFmt),
    983                    cLive, cDead, cToReadTotal, offWrite));
    984 
    985     uint32_t cToRead, cToWrite;
    986     uint32_t cWritten, cRead;
    987 
    988     while (cToReadTotal)
    989     {
    990         cDead = pDst->cSamples - cLive;
    991 
    992         cToRead  = cToReadTotal;
    993         cToWrite = RT_MIN(cDead, pDst->cSamples - offWrite);
    994         if (!cToWrite)
    995         {
    996             AUDMIXBUF_LOG(("Warning: Destination buffer \"%s\" full\n", pDst->pszName));
    997             break;
    998         }
    999 
    1000         Assert(offWrite + cToWrite <= pDst->cSamples);
    1001         Assert(offRead  + cToRead  <= pSrc->cSamples);
    1002 
    1003         AUDMIXBUF_LOG(("\t%RU32Hz -> %RU32Hz\n", AUDMIXBUF_FMT_SAMPLE_FREQ(pSrc->AudioFmt), AUDMIXBUF_FMT_SAMPLE_FREQ(pDst->AudioFmt)));
    1004         AUDMIXBUF_LOG(("\tcDead=%RU32, offWrite=%RU32, cToWrite=%RU32, offRead=%RU32, cToRead=%RU32\n",
    1005                        cDead, offWrite, cToWrite, offRead, cToRead));
    1006 
    1007         audioMixBufOpAssign(pDst->pSamples + offWrite, cToWrite,
    1008                             pSrc->pSamples + offRead, cToRead,
    1009                             pSrc->pRate, &cWritten, &cRead);
    1010 
    1011         AUDMIXBUF_LOG(("\t\tcWritten=%RU32, cRead=%RU32\n", cWritten, cRead));
    1012 
    1013         cReadTotal    += cRead;
    1014         cWrittenTotal += cWritten;
    1015 
    1016         offRead += cRead;
    1017         Assert(cToReadTotal >= cRead);
    1018         cToReadTotal -= cRead;
    1019 
    1020         offWrite = (offWrite + cWritten) % pDst->cSamples;
    1021 
    1022         cLive += cWritten;
    1023     }
    1024 
    1025     pSrc->cMixed     += cWrittenTotal;
    1026 
    1027     pDst->cProcessed += cWrittenTotal;
    1028 
    1029 #if 0
    1030     /**
    1031      * Note: pDst->cProcessed can be bigger than pDst->cSamples if there
    1032      *       was a wrap-around. In that case samples were lost,
    1033      *       e.g. not consumed (yet).
    1034      *
    1035      *       So adjust the current read/write offset to match the current
    1036      *       position, minus the dropped samples. */
    1037     if (pDst->cProcessed > pDst->cSamples)
    1038     {
    1039         LogFlowFunc(("%s: %RU32 / %RU32\n", pDst->pszName, pDst->cProcessed, pDst->cSamples));
    1040         pSrc->cMixed       = pDst->cSamples;
    1041         pDst->offReadWrite = 0;
    1042         pDst->cProcessed   = pDst->cSamples;
    1043     }
    1044 #endif
    1045 
    1046 #ifdef DEBUG
    1047     s_cSamplesMixedTotal += cWrittenTotal;
    1048     AudioMixBufDbgPrint(pDst);
    1049 #endif
    1050 
    1051     if (pcProcessed)
    1052         *pcProcessed = cReadTotal;
    1053 
    1054     AUDMIXBUF_LOG(("cReadTotal=%RU32 (pcProcessed), cWrittenTotal=%RU32, cSrcMixed=%RU32, cDstProc=%RU32\n",
    1055                    cReadTotal, cWrittenTotal, pSrc->cMixed, pDst->cProcessed));
    1056     return VINF_SUCCESS;
    1057 }
    1058 
    1059 /**
    1060  * Mixes (multiplexes) audio samples to all connected mixing buffer children.
    1061  *
    1062  * @return  IPRT status code.
    1063  * @param   pMixBuf                 Mixing buffer to use.
    1064  * @param   cSamples                Number of audio samples to mix to children.
    1065  * @param   pcProcessed             Maximum number of audio samples successfully mixed
    1066  *                                  to all children. Optional.
    1067  */
    1068 int AudioMixBufMixToChildren(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples,
    1069                              uint32_t *pcProcessed)
    1070 {
    1071     AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
    1072 
    1073     if (!cSamples)
    1074     {
     976
     977    if (pSrc->cMixed >= pDst->cSamples)
     978    {
     979        AUDMIXBUF_LOG(("Warning: Destination buffer '%s' full (%RU32 samples max), got %RU32 mixed samples\n",
     980                       pDst->pszName, pDst->cSamples, pSrc->cMixed));
    1075981        if (pcProcessed)
    1076982            *pcProcessed = 0;
     
    1078984    }
    1079985
     986    Assert(pSrc->cUsed >= pDst->cMixed);
     987
     988    uint32_t cSrcAvail  = RT_MIN(cSamples, pSrc->cUsed - pDst->cMixed);
     989    uint32_t offSrcRead = pSrc->offRead;
     990    uint32_t cDstMixed  = pSrc->cMixed;
     991
     992    Assert(pDst->cUsed <= pDst->cSamples);
     993    uint32_t cDstAvail    = pDst->cSamples - pDst->cUsed;
     994    uint32_t offDstWrite  = pDst->offWrite;
     995
     996    if (   !cSrcAvail
     997        || !cDstAvail)
     998    {
     999        if (pcProcessed)
     1000            *pcProcessed = 0;
     1001        return VINF_SUCCESS;
     1002    }
     1003
     1004    AUDMIXBUF_LOG(("cSamples=%RU32, cSrcAvail=%RU32 -> cDstAvail=%RU32\n", cSamples,  cSrcAvail, cDstAvail));
     1005
     1006#ifdef DEBUG
     1007    audioMixBufDbgPrintInternal(pDst);
     1008#endif
     1009
     1010    uint32_t cSrcToRead;
     1011    uint32_t cSrcRead;
     1012
     1013    uint32_t cDstToWrite;
     1014    uint32_t cDstWritten;
     1015
    10801016    int rc = VINF_SUCCESS;
    10811017
    1082     uint32_t cProcessed;
    1083     uint32_t cProcessedMax = 0;
    1084 
    1085     PPDMAUDIOMIXBUF pIter;
    1086     RTListForEach(&pMixBuf->lstBuffers, pIter, PDMAUDIOMIXBUF, Node)
    1087     {
    1088         rc = audioMixBufMixTo(pIter, pMixBuf, cSamples, &cProcessed);
    1089         if (RT_FAILURE(rc))
    1090             break;
    1091 
    1092         cProcessedMax = RT_MAX(cProcessedMax, cProcessed);
    1093     }
     1018    while (   cSrcAvail
     1019           && cDstAvail)
     1020    {
     1021        cSrcToRead  = RT_MIN(cSrcAvail, pSrc->cSamples - offSrcRead);
     1022        cDstToWrite = RT_MIN(cDstAvail, pDst->cSamples - offDstWrite);
     1023
     1024        AUDMIXBUF_LOG(("\tSource: %RU32 samples available, %RU32 @ %RU32 -> reading %RU32\n", cSrcAvail, offSrcRead, pSrc->cSamples, cSrcToRead));
     1025        AUDMIXBUF_LOG(("\tDest  : %RU32 samples available, %RU32 @ %RU32 -> writing %RU32\n", cDstAvail, offDstWrite, pDst->cSamples, cDstToWrite));
     1026
     1027        cDstWritten = cSrcRead = 0;
     1028
     1029        if (   cDstToWrite
     1030            && cSrcToRead)
     1031        {
     1032            Assert(offSrcRead < pSrc->cSamples);
     1033            Assert(offSrcRead + cSrcToRead <= pSrc->cSamples);
     1034
     1035            Assert(offDstWrite < pDst->cSamples);
     1036            Assert(offDstWrite + cDstToWrite <= pDst->cSamples);
     1037
     1038            audioMixBufOpAssign(pDst->pSamples + offDstWrite, cDstToWrite,
     1039                                pSrc->pSamples + offSrcRead,  cSrcToRead,
     1040                                pSrc->pRate, &cDstWritten, &cSrcRead);
     1041        }
     1042
     1043        cReadTotal    += cSrcRead;
     1044        cWrittenTotal += cDstWritten;
     1045
     1046        offSrcRead     = (offSrcRead  + cSrcRead)    % pSrc->cSamples;
     1047        offDstWrite    = (offDstWrite + cDstWritten) % pDst->cSamples;
     1048
     1049        cDstMixed     += cDstWritten;
     1050
     1051        Assert(cSrcAvail >= cSrcRead);
     1052        cSrcAvail     -= cSrcRead;
     1053        Assert(cDstAvail >= cDstWritten);
     1054        cDstAvail     -= cDstWritten;
     1055
     1056        AUDMIXBUF_LOG(("\t%RU32 read (%RU32 left), %RU32 written (%RU32 left)\n", cSrcRead, cSrcAvail, cDstWritten, cDstAvail));
     1057    }
     1058
     1059    pSrc->offRead     = offSrcRead;
     1060    Assert(pSrc->cUsed >= cReadTotal);
     1061    pSrc->cUsed      -= cReadTotal;
     1062
     1063    /* Note: Always count in parent samples, as the rate can differ! */
     1064    pSrc->cMixed      = cDstMixed;
     1065    Assert(pSrc->cMixed <= pDst->cSamples);
     1066
     1067    pDst->offWrite    = offDstWrite;
     1068    Assert(pDst->offWrite <= pDst->cSamples);
     1069    Assert((pDst->cUsed + cWrittenTotal) <= pDst->cSamples);
     1070    pDst->cUsed      += cWrittenTotal;
     1071
     1072    /* If there are more used samples than fitting in the destination buffer,
     1073     * adjust the values accordingly.
     1074     *
     1075     * This can happen if this routine has been called too often without
     1076     * actually processing the destination buffer in between. */
     1077    if (pDst->cUsed > pDst->cSamples)
     1078    {
     1079        LogFlowFunc(("Warning: Destination buffer used %RU32 / %RU32 samples\n", pDst->cUsed, pDst->cSamples));
     1080        pDst->offWrite     = 0;
     1081        pDst->cUsed        = pDst->cSamples;
     1082
     1083        rc = VERR_BUFFER_OVERFLOW;
     1084    }
     1085    else if (!cSrcToRead && cDstAvail)
     1086    {
     1087        AUDMIXBUF_LOG(("Warning: Source buffer '%s' ran out of data\n", pSrc->pszName));
     1088        rc = VERR_BUFFER_UNDERFLOW;
     1089    }
     1090    else if (cSrcAvail && !cDstAvail)
     1091    {
     1092        AUDMIXBUF_LOG(("Warning: Destination buffer '%s' full (%RU32 source samples left)\n", pDst->pszName, cSrcAvail));
     1093        rc = VERR_BUFFER_OVERFLOW;
     1094    }
     1095
     1096#ifdef DEBUG
     1097    s_cSamplesMixedTotal += cWrittenTotal;
     1098    audioMixBufDbgPrintInternal(pDst);
     1099#endif
    10941100
    10951101    if (pcProcessed)
    1096         *pcProcessed = cProcessedMax;
    1097 
    1098     return rc;
     1102        *pcProcessed = cReadTotal;
     1103
     1104    AUDMIXBUF_LOG(("cReadTotal=%RU32 (pcProcessed), cWrittenTotal=%RU32, cSrcMixed=%RU32, cDstUsed=%RU32, rc=%Rrc\n",
     1105                   cReadTotal, cWrittenTotal, pSrc->cMixed, pDst->cUsed, rc));
     1106    return VINF_SUCCESS;
    10991107}
    11001108
     
    11181126
    11191127#ifdef DEBUG
    1120 static void audioMixBufDbgBufPrintIndentV(uint16_t uIndent, const char *pszFormat, va_list va)
    1121 {
    1122     char *pszValueFormat;
    1123     if (RTStrAPrintfV(&pszValueFormat, pszFormat, va))
    1124     {
    1125         AUDMIXBUF_LOG(("%*s%s", uIndent, "", pszValueFormat));
    1126         RTStrFree(pszValueFormat);
    1127     }
    1128 }
    1129 
    1130 static void audioMixBufDbgPrintIndent(uint16_t uIdtLvl, const char *pszFormat, ...)
    1131 {
    1132     va_list va;
    1133     va_start(va, pszFormat);
    1134     audioMixBufDbgBufPrintIndentV(uIdtLvl * 4, pszFormat, va);
    1135     va_end(va);
    1136 }
    1137 
    11381128/**
    11391129 * Prints a single mixing buffer.
     
    11451135 * @param   uIdtLvl                 Indention level to use.
    11461136 */
    1147 static void audioMixBufDbgPrintSingle(PPDMAUDIOMIXBUF pMixBuf, bool fIsParent, uint16_t uIdtLvl)
    1148 {
    1149     audioMixBufDbgPrintIndent(uIdtLvl,
    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);
     1137DECL_FORCE_INLINE(void) audioMixBufDbgPrintSingle(PPDMAUDIOMIXBUF pMixBuf, bool fIsParent, uint16_t uIdtLvl)
     1138{
     1139    AUDMIXBUF_LOG(("%*s[%s] %s: offRead=%RU32, offWrite=%RU32, cMixed=%RU32 -> %RU32/%RU32\n",
     1140                   uIdtLvl * 4, "", fIsParent ? "PARENT" : "CHILD",
     1141                   pMixBuf->pszName, pMixBuf->offRead, pMixBuf->offWrite, pMixBuf->cMixed, pMixBuf->cUsed, pMixBuf->cSamples));
    11531142}
    11541143
     
    11621151 * @param   pcChildren              Pointer to children counter.
    11631152 */
    1164 static void audioMixBufDbgPrintChainHelper(PPDMAUDIOMIXBUF pMixBuf, uint16_t uIdtLvl, size_t *pcChildren)
     1153DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainHelper(PPDMAUDIOMIXBUF pMixBuf, uint16_t uIdtLvl, size_t *pcChildren)
    11651154{
    11661155    PPDMAUDIOMIXBUF pIter;
    1167     RTListForEach(&pMixBuf->lstBuffers, pIter, PDMAUDIOMIXBUF, Node)
     1156    RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)
    11681157    {
    11691158        audioMixBufDbgPrintSingle(pIter, false /* ifIsParent */, uIdtLvl + 1);
    11701159        *pcChildren++;
    1171         audioMixBufDbgPrintChainHelper(pIter, uIdtLvl + 1, pcChildren);
    1172     }
    1173 }
    1174 
    1175 static void audioMixBufDbgPrintChainInternal(PPDMAUDIOMIXBUF pMixBuf)
     1160    }
     1161}
     1162
     1163DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainInternal(PPDMAUDIOMIXBUF pMixBuf)
    11761164{
    11771165    PPDMAUDIOMIXBUF pParent = pMixBuf->pParent;
     
    12121200}
    12131201
    1214 /**
    1215  * Prints statistics and status of a mixing buffer to the logger.
    1216  * For debug versions only.
    1217  *
    1218  * @return  IPRT status code.
    1219  * @param   pMixBuf                 Mixing buffer to print.
    1220  */
    1221 void AudioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf)
     1202DECL_FORCE_INLINE(void) audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf)
    12221203{
    12231204    PPDMAUDIOMIXBUF pParent = pMixBuf;
     
    12251206        pParent = pMixBuf->pParent;
    12261207
    1227     AUDMIXBUF_LOG(("********************************************\n"));
     1208    AUDMIXBUF_LOG(("***************************************************************************************\n"));
    12281209
    12291210    audioMixBufDbgPrintSingle(pMixBuf, pParent == pMixBuf /* fIsParent */, 0 /* iIdtLevel */);
    12301211
    12311212    PPDMAUDIOMIXBUF pIter;
    1232     RTListForEach(&pParent->lstBuffers, pIter, PDMAUDIOMIXBUF, Node)
     1213    RTListForEach(&pParent->lstChildren, pIter, PDMAUDIOMIXBUF, Node)
    12331214    {
    12341215        if (pIter == pMixBuf)
     
    12371218    }
    12381219
    1239     AUDMIXBUF_LOG(("********************************************\n"));
    1240 }
    1241 #endif
    1242 
    1243 /**
    1244  * Returns the total number of samples processed.
     1220    AUDMIXBUF_LOG(("***************************************************************************************\n"));
     1221}
     1222
     1223/**
     1224 * Prints statistics and status of a mixing buffer to the logger.
     1225 * For debug versions only.
     1226 *
     1227 * @return  IPRT status code.
     1228 * @param   pMixBuf                 Mixing buffer to print.
     1229 */
     1230void AudioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf)
     1231{
     1232    audioMixBufDbgPrintInternal(pMixBuf);
     1233}
     1234#endif
     1235
     1236/**
     1237 * Returns the total number of samples used.
    12451238 *
    12461239 * @return  uint32_t
    12471240 * @param   pMixBuf
    12481241 */
    1249 uint32_t AudioMixBufProcessed(PPDMAUDIOMIXBUF pMixBuf)
     1242uint32_t AudioMixBufUsed(PPDMAUDIOMIXBUF pMixBuf)
    12501243{
    12511244    AssertPtrReturn(pMixBuf, 0);
    12521245
    1253     AUDMIXBUF_LOG(("%s: cProcessed=%RU32\n", pMixBuf->pszName, pMixBuf->cProcessed));
    1254     return pMixBuf->cProcessed;
     1246    AUDMIXBUF_LOG(("%s: cUsed=%RU32\n", pMixBuf->pszName, pMixBuf->cUsed));
     1247    return pMixBuf->cUsed;
    12551248}
    12561249
     
    12971290
    12981291    uint32_t cDstSamples = pMixBuf->cSamples;
    1299     uint32_t cLive = pMixBuf->cProcessed;
     1292    uint32_t cLive = pMixBuf->cUsed;
    13001293
    13011294    uint32_t cDead = cDstSamples - cLive;
     
    13811374        return VINF_SUCCESS;
    13821375
    1383     uint32_t cToRead = RT_MIN(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), pMixBuf->cProcessed);
     1376    Assert(AUDIOMIXBUF_B2S(pMixBuf, cbBuf) <= pMixBuf->cSamples);
     1377
     1378    uint32_t cToRead = RT_MIN(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), pMixBuf->cUsed);
    13841379
    13851380    AUDMIXBUF_LOG(("%s: pvBuf=%p, cbBuf=%zu (%RU32 samples), cToRead=%RU32\n",
     
    13891384    {
    13901385#ifdef DEBUG
    1391         AudioMixBufDbgPrint(pMixBuf);
     1386        audioMixBufDbgPrintInternal(pMixBuf);
    13921387#endif
    13931388        if (pcRead)
     
    14001395        return VERR_NOT_SUPPORTED;
    14011396
    1402     PPDMAUDIOSAMPLE pSamplesSrc1 = pMixBuf->pSamples + pMixBuf->offReadWrite;
     1397    PPDMAUDIOSAMPLE pSamplesSrc1 = pMixBuf->pSamples + pMixBuf->offRead;
    14031398    uint32_t cLenSrc1 = cToRead;
    14041399
    14051400    PPDMAUDIOSAMPLE pSamplesSrc2 = NULL;
    14061401    uint32_t cLenSrc2 = 0;
    1407 
    1408     uint32_t offRead = pMixBuf->offReadWrite + cToRead;
    14091402
    14101403    /*
     
    14131406     * be the optional second part to do.
    14141407     */
    1415     if (offRead >= pMixBuf->cSamples)
    1416     {
    1417         Assert(pMixBuf->offReadWrite <= pMixBuf->cSamples);
    1418         cLenSrc1 = pMixBuf->cSamples - pMixBuf->offReadWrite;
     1408    if ((pMixBuf->offRead + cToRead) > pMixBuf->cSamples)
     1409    {
     1410        Assert(pMixBuf->offRead <= pMixBuf->cSamples);
     1411        cLenSrc1 = pMixBuf->cSamples - pMixBuf->offRead;
    14191412
    14201413        pSamplesSrc2 = pMixBuf->pSamples;
    14211414        Assert(cToRead >= cLenSrc1);
    14221415        cLenSrc2 = RT_MIN(cToRead - cLenSrc1, pMixBuf->cSamples);
    1423 
    1424         /* Save new read offset. */
    1425         offRead = cLenSrc2;
    14261416    }
    14271417
     
    14351425        convOpts.cSamples = cLenSrc1;
    14361426
    1437         AUDMIXBUF_LOG(("P1: offRead=%RU32, cToRead=%RU32\n", pMixBuf->offReadWrite, cLenSrc1));
     1427        AUDMIXBUF_LOG(("P1: offRead=%RU32, cToRead=%RU32\n", pMixBuf->offRead, cLenSrc1));
    14381428        pConv(pvBuf, pSamplesSrc1, &convOpts);
    14391429    }
     
    14641454        }
    14651455#endif
    1466         pMixBuf->offReadWrite  = offRead % pMixBuf->cSamples;
    1467         pMixBuf->cProcessed   -= RT_MIN(cLenSrc1 + cLenSrc2, pMixBuf->cProcessed);
     1456        pMixBuf->offRead  = (pMixBuf->offRead + cToRead) % pMixBuf->cSamples;
     1457        Assert(cToRead <= pMixBuf->cUsed);
     1458        pMixBuf->cUsed   -= RT_MIN(cToRead, pMixBuf->cUsed);
    14681459
    14691460        if (pcRead)
    1470             *pcRead = cLenSrc1 + cLenSrc2;
     1461            *pcRead = cToRead;
    14711462    }
    14721463
    14731464#ifdef DEBUG
    1474     AudioMixBufDbgPrint(pMixBuf);
    1475 #endif
    1476 
    1477     AUDMIXBUF_LOG(("cRead=%RU32 (%zu bytes), rc=%Rrc\n",
    1478                    cLenSrc1 + cLenSrc2,
    1479                    AUDIOMIXBUF_S2B(pMixBuf, cLenSrc1 + cLenSrc2), rc));
     1465    audioMixBufDbgPrintInternal(pMixBuf);
     1466#endif
     1467
     1468    AUDMIXBUF_LOG(("cRead=%RU32 (%zu bytes), rc=%Rrc\n", cToRead, AUDIOMIXBUF_S2B(pMixBuf, cToRead), rc));
    14801469    return rc;
    14811470}
     
    14921481    AUDMIXBUF_LOG(("%s\n", pMixBuf->pszName));
    14931482
    1494     pMixBuf->offReadWrite = 0;
    1495     pMixBuf->cMixed       = 0;
    1496     pMixBuf->cProcessed   = 0;
     1483    pMixBuf->offRead  = 0;
     1484    pMixBuf->offWrite = 0;
     1485    pMixBuf->cMixed   = 0;
     1486    pMixBuf->cUsed    = 0;
    14971487
    14981488    AudioMixBufClear(pMixBuf);
     
    15711561
    15721562    PPDMAUDIOMIXBUF pIter;
    1573     while (!RTListIsEmpty(&pMixBuf->lstBuffers))
    1574     {
    1575         pIter = RTListGetFirst(&pMixBuf->lstBuffers, PDMAUDIOMIXBUF, Node);
     1563    while (!RTListIsEmpty(&pMixBuf->lstChildren))
     1564    {
     1565        pIter = RTListGetFirst(&pMixBuf->lstChildren, PDMAUDIOMIXBUF, Node);
    15761566
    15771567        AUDMIXBUF_LOG(("\tUnlinking \"%s\"\n", pIter->pszName));
     
    16331623    uint32_t cDstSamples = pMixBuf->pParent
    16341624                         ? pMixBuf->pParent->cSamples : pMixBuf->cSamples;
    1635     uint32_t cLive = pMixBuf->cProcessed;
     1625    uint32_t cLive = pMixBuf->cUsed;
    16361626
    16371627    uint32_t cDead = cDstSamples - cLive;
     
    16771667        cWritten = pConv(pMixBuf->pSamples + offSamples, pvBuf, cbBuf, &convOpts);
    16781668#ifdef DEBUG
    1679         AudioMixBufDbgPrint(pMixBuf);
     1669        audioMixBufDbgPrintInternal(pMixBuf);
    16801670#endif
    16811671        rc = cWritten ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Fudge! */
     
    17271717 */
    17281718int AudioMixBufWriteCircEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt,
    1729                            const void *pvBuf, uint32_t cbBuf,
    1730                            uint32_t *pcWritten)
     1719                           const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)
    17311720{
    17321721    AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
     
    17471736
    17481737    if (   pParent
    1749         && pParent->cSamples <= pMixBuf->cMixed)
     1738        && pParent->cSamples < pMixBuf->cMixed)
    17501739    {
    17511740        if (pcWritten)
     
    17751764    AssertMsg(cToWrite, ("cToWrite is 0 (cbBuf=%zu)\n", cbBuf));
    17761765
    1777     PPDMAUDIOSAMPLE pSamplesDst1 = pMixBuf->pSamples + pMixBuf->offReadWrite;
     1766    PPDMAUDIOSAMPLE pSamplesDst1 = pMixBuf->pSamples + pMixBuf->offWrite;
    17781767    uint32_t cLenDst1 = cToWrite;
    17791768
     
    17811770    uint32_t cLenDst2 = 0;
    17821771
    1783     uint32_t cOffWrite = pMixBuf->offReadWrite + cToWrite;
     1772    uint32_t cOffWrite = pMixBuf->offWrite + cToWrite;
    17841773
    17851774    /*
     
    17901779    if (cOffWrite >= pMixBuf->cSamples)
    17911780    {
    1792         Assert(pMixBuf->offReadWrite <= pMixBuf->cSamples);
    1793         cLenDst1 = pMixBuf->cSamples - pMixBuf->offReadWrite;
     1781        Assert(pMixBuf->offWrite <= pMixBuf->cSamples);
     1782        cLenDst1 = pMixBuf->cSamples - pMixBuf->offWrite;
    17941783
    17951784        pSamplesDst2 = pMixBuf->pSamples;
     
    18031792#ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
    18041793    RTFILE fh;
    1805     RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writecirc_ex-32bit-float.pcm",
     1794    RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writecirc_ex.pcm",
    18061795               RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);
    18071796#endif
     
    18161805    {
    18171806        convOpts.cSamples = cLenDst1;
    1818         cWrittenTotal = pCnvFrm(pSamplesDst1, pvBuf, cbBuf, &convOpts);
     1807        cWrittenTotal = pCnvFrm(pSamplesDst1, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), &convOpts);
    18191808        Assert(cWrittenTotal == cLenDst1);
    18201809
    18211810#ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
    1822         RTFileWrite(fh, pvBuf, cbBuf, NULL);
     1811        RTFileWrite(fh, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), NULL);
    18231812#endif
    18241813    }
     
    18311820
    18321821        convOpts.cSamples = cLenDst2;
    1833         cWrittenTotal += pCnvFrm(pSamplesDst2, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), cbBuf, &convOpts);
     1822        cWrittenTotal += pCnvFrm(pSamplesDst2,
     1823                                 (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1),
     1824                                 cbBuf - AUDIOMIXBUF_S2B(pMixBuf, cLenDst1),
     1825                                 &convOpts);
    18341826        Assert(cWrittenTotal == (cLenDst1 + cLenDst2));
    18351827
    18361828#ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
    1837         RTFileWrite(fh, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), cbBuf, NULL);
     1829        RTFileWrite(fh, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1),
     1830                    cbBuf - AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), NULL);
    18381831#endif
    18391832    }
     
    18451838    if (RT_SUCCESS(rc))
    18461839    {
    1847         pMixBuf->offReadWrite = cOffWrite % pMixBuf->cSamples;
    1848         pMixBuf->cProcessed   = RT_MIN(pMixBuf->cProcessed + cLenDst1 + cLenDst2,
    1849                                        pMixBuf->cSamples /* Max */);
    1850 
    1851         uint32_t cProcessedTotal = pMixBuf->cProcessed + cLenDst1 + cLenDst2;
     1840        pMixBuf->offWrite = (pMixBuf->offWrite + cWrittenTotal) % pMixBuf->cSamples;
     1841        pMixBuf->cUsed    = RT_MIN(pMixBuf->cUsed + cWrittenTotal,
     1842                                   pMixBuf->cSamples /* Max */);
     1843
     1844        uint32_t cProcessedTotal = pMixBuf->cUsed + cWrittenTotal;
    18521845        if (cProcessedTotal > pMixBuf->cSamples)
    18531846        {
    18541847            AUDMIXBUF_LOG(("Warning: %RU32 unprocessed samples overwritten\n", cProcessedTotal - pMixBuf->cSamples));
    1855             pMixBuf->cProcessed = pMixBuf->cSamples;
     1848            pMixBuf->cUsed = pMixBuf->cSamples;
    18561849
    18571850            rc = VINF_BUFFER_OVERFLOW;
     
    18591852
    18601853        if (pcWritten)
    1861             *pcWritten = cLenDst1 + cLenDst2;
     1854            *pcWritten = cWrittenTotal;
    18621855    }
    18631856
    18641857#ifdef DEBUG
    1865     AudioMixBufDbgPrint(pMixBuf);
    1866 #endif
    1867 
    1868     AUDMIXBUF_LOG(("offReadWrite=%RU32, cLenDst1=%RU32, cLenDst2=%RU32, cTotal=%RU32 (%zu bytes), rc=%Rrc\n",
    1869                    pMixBuf->offReadWrite, cLenDst1, cLenDst2, cLenDst1 + cLenDst2,
     1858    audioMixBufDbgPrintInternal(pMixBuf);
     1859#endif
     1860
     1861    AUDMIXBUF_LOG(("offWrite=%RU32, cLenDst1=%RU32, cLenDst2=%RU32, cTotal=%RU32 (%zu bytes), rc=%Rrc\n",
     1862                   pMixBuf->offWrite, cLenDst1, cLenDst2, cLenDst1 + cLenDst2,
    18701863                   AUDIOMIXBUF_S2B(pMixBuf, cLenDst1 + cLenDst2), rc));
    18711864
  • trunk/src/VBox/Devices/Audio/AudioMixBuffer.h

    r61089 r61320  
    6262int AudioMixBufLinkTo(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent);
    6363uint32_t AudioMixBufMixed(PPDMAUDIOMIXBUF pMixBuf);
    64 int AudioMixBufMixToChildren(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples, uint32_t *pcProcessed);
    6564int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples, uint32_t *pcProcessed);
    66 uint32_t AudioMixBufProcessed(PPDMAUDIOMIXBUF pMixBuf);
     65uint32_t AudioMixBufUsed(PPDMAUDIOMIXBUF pMixBuf);
    6766int AudioMixBufReadAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offSamples, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
    6867int AudioMixBufReadAtEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, uint32_t offSamples, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
  • trunk/src/VBox/Devices/Audio/AudioMixer.cpp

    r61178 r61320  
    405405    }
    406406
     407    RTStrPrintf(CfgSink.szName, sizeof(CfgSink.szName), "%s", pCfg->szName);
     408
    407409    /* Always use the sink's PCM audio format as the host side when creating a stream for it. */
    408410    PPDMAUDIOSTREAM pStream;
     
    583585    /** @todo Handle mixing operation enmOp! */
    584586
     587    AssertMsg(pSink->enmDir == AUDMIXSINKDIR_INPUT,
     588              ("Can't read from a sink which is not an input sink\n"));
     589
    585590    uint8_t *pvMixBuf = (uint8_t *)RTMemAlloc(cbBuf);
    586591    if (!pvMixBuf)
     
    797802    int rc = VINF_SUCCESS;
    798803
     804    Log3Func(("[%s]\n", pSink->pszName));
     805
    799806    PAUDMIXSTREAM pMixStream;
    800807    RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node)
     
    803810        AssertPtr(pStream);
    804811
    805         uint32_t cSamplesAvail;
    806         uint32_t cSamplesProcessed = 0;
    807 
    808         rc = pMixStream->pConn->pfnStreamGetData(pMixStream->pConn, pStream, &cSamplesAvail);
    809         if (   RT_SUCCESS(rc)
    810             && cSamplesAvail)
     812        uint32_t cPlayed = 0;
     813
     814        rc = pMixStream->pConn->pfnStreamIterate(pMixStream->pConn, pStream);
     815        if (RT_SUCCESS(rc))
    811816        {
    812817            if (pStream->enmDir == PDMAUDIODIR_IN)
    813818            {
    814819                /** @todo Implement this! */
    815             //  rc = pStream->pConn->pfnCapture(pStream->pConn, NULL /* pcSamplesCaptured */);
     820#if 0
     821                rc = pStream->pConn->pfnStreamCapture(pStream->pConn, NULL /* pcSamplesCaptured */);
     822#endif
    816823            }
    817824            else
    818825            {
    819                 rc = pMixStream->pConn->pfnStreamPlay(pMixStream->pConn, pStream, &cSamplesProcessed);
     826                rc = pMixStream->pConn->pfnStreamPlay(pMixStream->pConn, pMixStream->pStream, &cPlayed);
     827                if (RT_FAILURE(rc))
     828                    LogFlowFunc(("%s: Failed playing stream '%s': %Rrc\n", pSink->pszName, pMixStream->pStream->szName, rc));
    820829            }
    821 
    822             pSink->fFlags |= AUDMIXSINK_FLAG_DIRTY;
    823830        }
    824         else if (!cSamplesAvail)
    825             pSink->fFlags &= ~AUDMIXSINK_FLAG_DIRTY;
    826 
    827         Log3Func(("[%s]: fFlags=0x%x, %RU32/%RU32 samples, rc=%Rrc\n",
    828                   pSink->pszName, pSink->fFlags, cSamplesProcessed, cSamplesAvail, rc));
     831
     832        Log3Func(("\t%s: cPlayed=%RU32, rc=%Rrc\n", pMixStream->pStream->szName, cPlayed, rc));
    829833    }
    830834
     
    884888    }
    885889
    886     uint32_t cbProcessed = 0;
     890    AssertMsg(pSink->enmDir == AUDMIXSINKDIR_OUTPUT,
     891              ("Can't write to a sink which is not an output sink\n"));
     892
     893    LogFlowFunc(("%s: enmOp=%ld, cbBuf=%RU32\n", pSink->pszName, enmOp, cbBuf));
     894
     895    uint32_t cPlayed;
     896    uint32_t cbProcessed;
    887897
    888898    PAUDMIXSTREAM pMixStream;
     
    893903
    894904        int rc2 = pMixStream->pConn->pfnStreamWrite(pMixStream->pConn, pMixStream->pStream, pvBuf, cbBuf, &cbProcessed);
    895         if (   RT_FAILURE(rc2)
    896             || cbProcessed < cbBuf)
    897         {
    898             LogFlowFunc(("rc=%Rrc, cbBuf=%RU32, cbProcessed=%RU32\n", rc2, cbBuf, cbProcessed));
    899         }
    900     }
     905        if (RT_FAILURE(rc2))
     906            LogFlowFunc(("%s: Failed writing to stream '%s': %Rrc\n", pSink->pszName, pMixStream->pStream->szName, rc2));
     907
     908        if (cbProcessed < cbBuf)
     909            LogFlowFunc(("%s: Only written %RU32/%RU32 bytes\n", pSink->pszName, pMixStream->pStream->szName, cbProcessed, cbBuf));
     910    }
     911
     912    /* Set dirty bit. */
     913    pSink->fFlags |= AUDMIXSINK_FLAG_DIRTY;
    901914
    902915    if (pcbWritten)
  • trunk/src/VBox/Devices/Audio/DevIchAc97.cpp

    r61167 r61320  
    5555#define AC97_SSM_VERSION 1
    5656
    57 #define AC97_TIMER_HZ 100
     57#define AC97_TIMER_HZ 50
    5858
    5959#ifdef VBOX
  • trunk/src/VBox/Devices/Audio/DevSB16.cpp

    r61167 r61320  
    7878    /** PCM output stream. */
    7979    R3PTRTYPE(PPDMAUDIOSTREAM)         pStream;
    80     /** Mixer handle for output stream. */
    81     R3PTRTYPE(PAUDMIXSTREAM)           pMixStrm;
    8280} SB16OUTPUTSTREAM, *PSB16OUTPUTSTREAM;
    8381
     
    169167
    170168    RTLISTANCHOR                   lstDrv;
    171     /** The device' software mixer. */
    172     R3PTRTYPE(PAUDIOMIXER)         pMixer;
    173     /** Audio sink for PCM output. */
    174     R3PTRTYPE(PAUDMIXSINK)         pSinkOutput;
    175169    /** Number of active (running) SDn streams. */
    176170    uint8_t                        cStreamsActive;
     
    178172    /** The timer for pumping data thru the attached LUN drivers. */
    179173    PTMTIMERR3                     pTimerIO;
     174    /** Flag indicating whether the timer is active or not. */
     175    bool                           fTimerActive;
     176    uint8_t                        u8Padding1[7];
    180177    /** The timer interval for pumping data thru the LUN drivers in timer ticks. */
    181178    uint64_t                       cTimerTicksIO;
     
    194191
    195192static int sb16OpenOut(PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg);
     193static void sb16CloseOut(PSB16STATE pThis);
    196194#ifndef VBOX_WITH_AUDIO_CALLBACKS
    197195static void sb16TimerMaybeStart(PSB16STATE pThis);
     
    451449#endif
    452450
    453     AudioMixerSinkCtl(pThis->pSinkOutput,
    454                       hold == 1 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE);
     451    PSB16DRIVER pDrv;
     452    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
     453    {
     454        int rc2 = pDrv->pConnector->pfnStreamControl(pDrv->pConnector, pDrv->Out.pStream,
     455                                                     hold == 1 ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE);
     456        LogFlowFunc(("%s: rc=%Rrc\n", pDrv->Out.pStream->szName, rc2));
     457    }
    455458}
    456459
     
    471474        PDMAUDIOSTREAMCFG streamCfg;
    472475        RT_ZERO(streamCfg);
    473         streamCfg.enmDir        = PDMAUDIODIR_OUT;
    474         streamCfg.uHz           = pThis->freq;
    475         streamCfg.cChannels     = 1 << pThis->fmt_stereo;
    476         streamCfg.enmFormat     = pThis->fmt;
    477         streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
     476        streamCfg.enmDir          = PDMAUDIODIR_OUT;
     477        streamCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT;
     478        streamCfg.uHz             = pThis->freq;
     479        streamCfg.cChannels       = 1 << pThis->fmt_stereo;
     480        streamCfg.enmFormat       = pThis->fmt;
     481        streamCfg.enmEndianness   = PDMAUDIOHOSTENDIANNESS;
    478482
    479483        int rc = sb16OpenOut(pThis, &streamCfg);
     
    608612        PDMAUDIOSTREAMCFG streamCfg;
    609613        RT_ZERO(streamCfg);
    610         streamCfg.enmDir        = PDMAUDIODIR_OUT;
    611         streamCfg.uHz           = pThis->freq;
    612         streamCfg.cChannels     = 1 << pThis->fmt_stereo;
    613         streamCfg.enmFormat     = pThis->fmt;
    614         streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
     614        streamCfg.enmDir          = PDMAUDIODIR_OUT;
     615        streamCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT;
     616        streamCfg.uHz             = pThis->freq;
     617        streamCfg.cChannels       = 1 << pThis->fmt_stereo;
     618        streamCfg.enmFormat       = pThis->fmt;
     619        streamCfg.enmEndianness   = PDMAUDIOHOSTENDIANNESS;
    615620
    616621        int rc = sb16OpenOut(pThis, &streamCfg);
     
    11011106    uint8_t rvol = sb16MixRegToVol(pThis, 0x31);
    11021107    PDMAUDIOVOLUME vol = { false, lvol, rvol };
    1103     AudioMixerSetMasterVolume(pThis->pMixer, &vol);
     1108
     1109//    AudioMixerSetMasterVolume(pThis->pMixer, &vol);
    11041110}
    11051111
     
    11101116    uint8_t rvol = sb16MixRegToVol(pThis, 0x33);
    11111117    PDMAUDIOVOLUME vol = { false, lvol, rvol };
    1112     AudioMixerSinkSetVolume(pThis->pSinkOutput, &vol);
     1118
     1119  //  AudioMixerSinkSetVolume(pThis->pSinkOutput, &vol);
    11131120}
    11141121
    11151122static void sb16ResetLegacy(PSB16STATE pThis)
    11161123{
     1124    sb16CloseOut(pThis);
     1125
    11171126    pThis->freq       = 11025;
    11181127    pThis->fmt_signed = 0;
     
    11221131    PDMAUDIOSTREAMCFG streamCfg;
    11231132    RT_ZERO(streamCfg);
    1124     streamCfg.enmDir        = PDMAUDIODIR_OUT;
    1125     streamCfg.uHz           = pThis->freq;
    1126     streamCfg.cChannels     = 1; /* Mono */
    1127     streamCfg.enmFormat     = PDMAUDIOFMT_U8;
    1128     streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
     1133    streamCfg.enmDir          = PDMAUDIODIR_OUT;
     1134    streamCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT;
     1135    streamCfg.uHz             = pThis->freq;
     1136    streamCfg.cChannels       = 1; /* Mono */
     1137    streamCfg.enmFormat       = PDMAUDIOFMT_U8;
     1138    streamCfg.enmEndianness   = PDMAUDIOHOSTENDIANNESS;
    11291139
    11301140    int rc2 = sb16OpenOut(pThis, &streamCfg);
     
    13321342static void sb16MixerReset(PSB16STATE pThis)
    13331343{
    1334     PSB16DRIVER pDrv;
    1335 
    1336     RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    1337         pDrv->Out.pMixStrm = NULL;
    1338 
    1339     pThis->pSinkOutput = NULL;
    1340 
    1341     if (pThis->pMixer)
    1342     {
    1343         AudioMixerDestroy(pThis->pMixer);
    1344         pThis->pMixer = NULL;
    1345     }
    1346 
    13471344    memset(pThis->mixer_regs, 0xff, 0x7f);
    13481345    memset(pThis->mixer_regs + 0x83, 0xff, sizeof (pThis->mixer_regs) - 0x83);
     
    13731370    for (int i = 0x44; i < 0x48; i++)
    13741371        pThis->mixer_regs[i] = 0x80;
    1375 
    1376     int rc2 = AudioMixerCreate("SB16 Mixer", 0 /* uFlags */, &pThis->pMixer);
    1377     if (RT_SUCCESS(rc2))
    1378     {
    1379         /* Set a default audio format for our mixer. */
    1380         PDMAUDIOSTREAMCFG streamCfg;
    1381         streamCfg.uHz           = 44100;
    1382         streamCfg.cChannels     = 2;
    1383         streamCfg.enmFormat     = PDMAUDIOFMT_S16;
    1384         streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
    1385 
    1386         rc2 = AudioMixerSetDeviceFormat(pThis->pMixer, &streamCfg);
    1387         AssertRC(rc2);
    1388 
    1389         /* Add all required audio sinks. */
    1390         rc2 = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput);
    1391         AssertRC(rc2);
    1392     }
    13931372
    13941373    /* Update the master (mixer) and PCM out volumes. */
     
    16421621
    16431622        /*
    1644          * Write data to the mixer sink.
     1623         * Write data to the backends.
    16451624         */
    1646         uint32_t cbWritten;
    1647         rc = AudioMixerSinkWrite(pThis->pSinkOutput, AUDMIXOP_COPY, tmpbuf, cbToRead, &cbWritten);
    1648         if (RT_FAILURE(rc))
    1649             break;
     1625        uint32_t cbWritten = 0;
     1626
     1627        PSB16DRIVER pDrv;
     1628        RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
     1629        {
     1630            int rc2 = pDrv->pConnector->pfnStreamWrite(pDrv->pConnector, pDrv->Out.pStream, tmpbuf, cbToRead, &cbWritten);
     1631            if (RT_FAILURE(rc2))
     1632                LogFlowFunc(("Failed writing to stream '%s': %Rrc\n", &pDrv->Out.pStream->szName, rc2));
     1633        }
    16501634
    16511635        LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbWritten=%RU32, cbLeft=%RU32, rc=%Rrc\n",
     
    16801664
    16811665    PSB16DRIVER pDrv;
    1682 
    1683     uint32_t cbOutMin = UINT32_MAX;
    1684     uint32_t cbOut;
    16851666    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    1686     {
    1687         int rc2 = pDrv->pConnector->pfnStreamGetData(pDrv->pConnector, pDrv->Out.pStream, &cbOut);
    1688         if (RT_SUCCESS(rc2))
    1689             cbOutMin = RT_MIN(cbOutMin, cbOut);
    1690     }
    1691 
    1692     LogFlowFunc(("cbOutMin=%RU32\n", cbOutMin));
    1693     if (cbOutMin == UINT32_MAX)
    1694     {
    1695         free = dma_len;
    1696     }
    1697     else
    1698     {
    1699         free = cbOutMin & ~pThis->align; /** @todo int vs. uint32. */
    1700         if ((free <= 0) || !dma_len)
    1701             return dma_pos;
    1702     }
     1667        pDrv->pConnector->pfnStreamIterate(pDrv->pConnector, pDrv->Out.pStream);
     1668
     1669    free = dma_len;
     1670
     1671    if (free <= 0)
     1672        return dma_pos;
    17031673
    17041674    copy = free;
     
    17611731        return;
    17621732
     1733    /* Set timer flag. */
     1734    ASMAtomicXchgBool(&pThis->fTimerActive, true);
     1735
    17631736    /* Update current time timestamp. */
    17641737    pThis->uTimerTSIO = TMTimerGet(pThis->pTimerIO);
     
    17781751        return;
    17791752
    1780     int rc2 = TMTimerStop(pThis->pTimerIO);
    1781     AssertRC(rc2);
     1753    /* Set timer flag. */
     1754    ASMAtomicXchgBool(&pThis->fTimerActive, false);
    17821755}
    17831756
     
    17941767    pThis->uTimerTSIO = cTicksNow;
    17951768
    1796     uint32_t cbOut;
    1797     AudioMixerSinkTimerUpdate(pThis->pSinkOutput, cTicksPerSec, cTicksElapsed, &cbOut);
    1798     if (cbOut)
    1799     {
    1800         /* New space available, see if we can transfer more. */
     1769    bool fIsPlaying = false;
     1770
     1771    LogFlowFuncEnter();
     1772
     1773    PSB16DRIVER pDrv;
     1774    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
     1775    {
     1776        PPDMAUDIOSTREAM pStream = pDrv->Out.pStream;
     1777
     1778        PDMAUDIOSTRMSTS strmSts = pDrv->pConnector->pfnStreamGetStatus(pDrv->pConnector, pStream);
     1779        fIsPlaying |= (   (strmSts & PDMAUDIOSTRMSTS_FLAG_ENABLED)
     1780                       || (strmSts & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE));
     1781
     1782        LogFlowFunc(("%s: strmSts=0x%x -> fIsPlaying=%RTbool\n", pStream->szName, strmSts, fIsPlaying));
     1783
     1784        int rc2 = pDrv->pConnector->pfnStreamIterate(pDrv->pConnector, pStream);
     1785        if (RT_SUCCESS(rc2))
     1786        {
     1787            if (pStream->enmDir == PDMAUDIODIR_IN)
     1788            {
     1789                /** @todo Implement this! */
     1790            }
     1791            else
     1792            {
     1793                rc2 = pDrv->pConnector->pfnStreamPlay(pDrv->pConnector, pStream, NULL /* cPlayed */);
     1794                if (RT_FAILURE(rc2))
     1795                    LogFlowFunc(("%s: Failed playing stream '%s': %Rrc\n", pStream->szName, rc2));
     1796            }
     1797        }
     1798    }
     1799
     1800    if (   ASMAtomicReadBool(&pThis->fTimerActive)
     1801        || fIsPlaying)
     1802    {
     1803        /* Schedule the next transfer. */
    18011804        PDMDevHlpDMASchedule(pThis->pDevInsR3);
    1802     }
    1803 
    1804     /* Kick the timer again. */
    1805     uint64_t cTicks = pThis->cTimerTicksIO;
    1806     /** @todo adjust cTicks down by now much cbOutMin represents. */
    1807     TMTimerSet(pThis->pTimerIO, cTicksNow + cTicks);
     1805
     1806        /* Kick the timer again. */
     1807        uint64_t cTicks = pThis->cTimerTicksIO;
     1808        /** @todo adjust cTicks down by now much cbOutMin represents. */
     1809        TMTimerSet(pThis->pTimerIO, cTicksNow + cTicks);
     1810    }
    18081811}
    18091812
     
    19341937            PDMAUDIOSTREAMCFG streamCfg;
    19351938            RT_ZERO(streamCfg);
    1936             streamCfg.enmDir        = PDMAUDIODIR_OUT;
    1937             streamCfg.uHz           = pThis->freq;
    1938             streamCfg.cChannels     = 1 << pThis->fmt_stereo;
    1939             streamCfg.enmFormat     = pThis->fmt;
    1940             streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;
     1939            streamCfg.enmDir          = PDMAUDIODIR_OUT;
     1940            streamCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT;
     1941            streamCfg.uHz             = pThis->freq;
     1942            streamCfg.cChannels       = 1 << pThis->fmt_stereo;
     1943            streamCfg.enmFormat       = pThis->fmt;
     1944            streamCfg.enmEndianness   = PDMAUDIOHOSTENDIANNESS;
    19411945
    19421946            int rc = sb16OpenOut(pThis, &streamCfg);
     
    20282032    AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER);
    20292033
    2030     /* Update the sink's format. */
    2031     PDMPCMPROPS PCMProps;
    2032     int rc = DrvAudioHlpStreamCfgToProps(pCfg, &PCMProps);
    2033     if (RT_SUCCESS(rc))
    2034         rc = AudioMixerSinkSetFormat(pThis->pSinkOutput, &PCMProps);
    2035 
    2036     if (RT_FAILURE(rc))
    2037         return rc;
     2034    int rc = VINF_SUCCESS;
     2035
     2036    /* Set a default audio format for the host. */
     2037    PDMAUDIOSTREAMCFG CfgHost;
     2038    CfgHost.enmDir          = PDMAUDIODIR_OUT;
     2039    CfgHost.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT;
     2040    CfgHost.uHz             = 44100;
     2041    CfgHost.cChannels       = 2;
     2042    CfgHost.enmFormat       = PDMAUDIOFMT_S16;
     2043    CfgHost.enmEndianness   = PDMAUDIOHOSTENDIANNESS;
     2044
     2045    RTStrPrintf(CfgHost.szName, sizeof(CfgHost.szName), "sb16.po");
     2046
     2047    uint8_t uLUN = 0;
    20382048
    20392049    PSB16DRIVER pDrv;
    2040     uint8_t uLUN = 0;
    2041 
    20422050    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    20432051    {
     
    20492057        }
    20502058
    2051         AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
    2052 
    2053         AudioMixerStreamDestroy(pDrv->Out.pMixStrm);
    2054         pDrv->Out.pMixStrm = NULL;
    2055 
    2056         int rc2 = AudioMixerSinkCreateStream(pThis->pSinkOutput, pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm);
    2057         if (RT_SUCCESS(rc2))
     2059        if (pDrv->Out.pStream)
    20582060        {
    2059             rc2 = AudioMixerSinkAddStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
    2060             LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2));
     2061            int rc3 = pDrv->pConnector->pfnStreamDestroy(pDrv->pConnector, pDrv->Out.pStream);
     2062            AssertRC(rc3);
     2063
     2064            pDrv->Out.pStream = NULL;
    20612065        }
    20622066
    2063         if (RT_FAILURE(rc2))
    2064         {
    2065             if (RT_SUCCESS(rc))
    2066                 rc = rc2;
    2067             break;
    2068         }
     2067        int rc2 = pDrv->pConnector->pfnStreamCreate(pDrv->pConnector, &CfgHost, pCfg, &pDrv->Out.pStream);
     2068        LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2));
    20692069
    20702070        uLUN++;
    20712071    }
    2072 
    2073     /* Ensure volume gets propagated. */
    2074     AudioMixerInvalidate(pThis->pMixer);
    20752072
    20762073    return rc;
     
    20862083    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    20872084    {
    2088         AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm);
    2089         AudioMixerStreamDestroy(pDrv->Out.pMixStrm);
    2090         pDrv->Out.pMixStrm = NULL;
     2085        if (pDrv->Out.pStream)
     2086        {
     2087            pDrv->pConnector->pfnStreamDestroy(pDrv->pConnector, pDrv->Out.pStream);
     2088            pDrv->Out.pStream = NULL;
     2089        }
    20912090    }
    20922091}
     
    21482147    LogRel2(("SB16: Powering off ...\n"));
    21492148
    2150     /**
    2151      * Note: Destroy the mixer while powering off and *not* in sb16Destruct,
    2152      *       giving the mixer the chance to release any references held to
    2153      *       PDM audio streams it maintains.
    2154      */
    2155     if (pThis->pMixer)
    2156     {
    2157         AudioMixerDestroy(pThis->pMixer);
    2158         pThis->pMixer = NULL;
    2159     }
     2149    sb16CloseOut(pThis);
    21602150}
    21612151
     
    21772167        RTMemFree(pDrv);
    21782168    }
    2179 
    2180     sb16CloseOut(pThis);
    21812169
    21822170    return VINF_SUCCESS;
     
    23392327
    23402328        /** @todo No input streams available for SB16 yet. */
    2341         bool fValidOut = AudioMixerStreamIsValid(pDrv->Out.pMixStrm);
     2329        /* Note: Only query the whole backend status here, as we don't have multiple streams to check for. */
     2330        bool fValidOut = pCon->pfnGetStatus(pCon, PDMAUDIODIR_OUT) == PDMAUDIOBACKENDSTS_RUNNING;
    23422331        if (!fValidOut)
    23432332        {
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r61177 r61320  
    6767static DECLCALLBACK(int) drvAudioStreamDestroy(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream);
    6868static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd);
     69static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd);
    6970static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream);
    7071static int drvAudioStreamDestroyInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream);
     
    252253static DECLCALLBACK(int) drvAudioStreamControl(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    253254{
     255    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     256    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     257
    254258    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
    255259
    256     return drvAudioStreamControlInternal(pThis, pStream, enmStreamCmd);
    257 }
    258 
    259 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    260 {
    261     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    262     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    263 
    264260    int rc = RTCritSectEnter(&pThis->CritSect);
    265261    if (RT_FAILURE(rc))
    266262        return rc;
    267263
     264    LogFlowFunc(("%s\n", pStream->szName));
     265
    268266    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     267    PPDMAUDIOSTREAM pGstStream = pHstStream->pPair;
     268
     269    /* Note: Call the host (backend) first to see if there is any pending disable
     270     *       actions in progress. */
     271    rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, enmStreamCmd);
     272    if (   RT_SUCCESS(rc)
     273        || rc == VERR_AUDIO_STREAM_PENDING_DISABLE)
     274    {
     275        int rc3 = drvAudioStreamControlInternal(pThis, pStream, enmStreamCmd);
     276        if (RT_SUCCESS(rc))
     277            rc = rc3;
     278    }
     279
     280    int rc2 = RTCritSectLeave(&pThis->CritSect);
     281    if (RT_SUCCESS(rc))
     282        rc = rc2;
     283
     284    return rc;
     285}
     286
     287static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pGstStream, PDMAUDIOSTREAMCMD enmStreamCmd)
     288{
     289    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     290
     291    if (!pGstStream)
     292        return VINF_SUCCESS;
     293
     294    int rc = VINF_SUCCESS;
     295
     296    switch (enmStreamCmd)
     297    {
     298        case PDMAUDIOSTREAMCMD_ENABLE:
     299        {
     300            pGstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED;
     301            break;
     302        }
     303
     304        case PDMAUDIOSTREAMCMD_DISABLE:
     305        {
     306            pGstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED;
     307            break;
     308        }
     309
     310        case PDMAUDIOSTREAMCMD_PAUSE:
     311        {
     312            pGstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED;
     313            break;
     314        }
     315
     316        case PDMAUDIOSTREAMCMD_RESUME:
     317        {
     318            pGstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED;
     319            break;
     320        }
     321
     322        default:
     323            AssertMsgFailed(("Command %ld not implemented\n", enmStreamCmd));
     324            rc = VERR_NOT_IMPLEMENTED;
     325            break;
     326    }
     327
     328    LogFlowFunc(("%s: enmStreamCmd=%ld, rc=%Rrc\n", pGstStream->szName, enmStreamCmd, rc));
     329    return rc;
     330}
     331
     332static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream, PDMAUDIOSTREAMCMD enmStreamCmd)
     333{
     334    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     335
     336    if (!pHstStream)
     337        return VINF_SUCCESS;
     338
     339    AssertMsg(pHstStream->enmCtx == PDMAUDIOSTREAMCTX_HOST,
     340              ("Stream '%s' is not a host stream and therefore has no backend\n", pHstStream->szName));
    269341
    270342    LogFlowFunc(("%s: enmStreamCmd=%ld\n", pHstStream->szName, enmStreamCmd));
     343
     344    int rc = VINF_SUCCESS;
     345
     346    PPDMAUDIOSTREAM pGstStream = pHstStream->pPair; /* Can be NULL. */
    271347
    272348    switch (enmStreamCmd)
     
    278354                rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_ENABLE);
    279355                if (RT_SUCCESS(rc))
    280                 {
    281                     Assert(!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE));
    282356                    pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED;
    283                 }
    284             }
    285             else
    286                 rc = VINF_SUCCESS;
    287 
     357            }
    288358            break;
    289359        }
     
    291361        case PDMAUDIOSTREAMCMD_DISABLE:
    292362        {
     363            /* Is the guest side stream still active?
     364             * Mark the host stream as pending disable and bail out. */
     365            if (   pGstStream
     366                && (pGstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
     367            {
     368                LogFlowFunc(("%s: Pending disable\n", pHstStream->szName));
     369                pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
     370                rc = VERR_AUDIO_STREAM_PENDING_DISABLE;
     371                break;
     372            }
     373
     374            /* Clear pending disable bit. */
     375            pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
     376
    293377            if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)
    294378            {
     
    297381                {
    298382                    pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED;
    299                     AudioMixBufClear(&pHstStream->MixBuf);
     383                    AudioMixBufReset(&pHstStream->MixBuf);
    300384                }
    301385            }
    302             else
    303                 rc = VINF_SUCCESS;
    304 
    305386            break;
    306387        }
     
    308389        case PDMAUDIOSTREAMCMD_PAUSE:
    309390        {
     391            /* Is the guest side stream still active?
     392             * Mark the host stream as pending disable and bail out. */
     393            if (   pGstStream
     394                && (pGstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
     395            {
     396                LogFlowFunc(("%s: Pending pause\n", pHstStream->szName));
     397                pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE;
     398                rc = VERR_AUDIO_STREAM_PENDING_DISABLE;
     399                break;
     400            }
     401
    310402            if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED))
    311403            {
     
    314406                    pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED;
    315407            }
    316             else
    317                 rc = VINF_SUCCESS;
    318 
    319408            break;
    320409        }
     
    328417                    pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED;
    329418            }
    330             else
    331                 rc = VINF_SUCCESS;
    332 
    333419            break;
    334420        }
     
    342428    if (RT_FAILURE(rc))
    343429        LogFunc(("%s: Failed with %Rrc\n", pHstStream->szName, rc));
    344 
    345     int rc2 = RTCritSectLeave(&pThis->CritSect);
    346     if (RT_SUCCESS(rc))
    347         rc = rc2;
    348430
    349431    return rc;
     
    381463    }
    382464
     465    LogFlowFunc(("[%s]: cbBuf=%RU32\n", pStream->szName, cbBuf));
     466
    383467    int rc = RTCritSectEnter(&pThis->CritSect);
    384468    if (RT_FAILURE(rc))
     
    396480    PPDMAUDIOSTREAM pGstStream = pHstStream->pPair;
    397481
    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))
     482    AssertMsg(pGstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED,
     483              ("Writing to disabled guest output stream \"%s\" not possible\n", pGstStream->szName));
     484
     485    if (!AudioMixBufFreeBytes(&pGstStream->MixBuf))
    402486    {
    403487        if (pcbWritten)
     
    407491    }
    408492
    409     /*
    410      * First, write data from the device emulation into our
    411      * guest mixing buffer.
    412      */
    413     uint32_t cWritten;
     493    uint32_t cWritten = 0;
    414494    rc = AudioMixBufWriteCirc(&pGstStream->MixBuf, pvBuf, cbBuf, &cWritten);
    415495    if (rc == VINF_BUFFER_OVERFLOW)
     496    {
    416497        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)
     498        rc = VINF_SUCCESS;
     499    }
     500
     501#if 0
     502    uint32_t cMixed = 0;
     503    if (RT_SUCCESS(rc))
    420504    {
    421505        /* Mix just written guest stream samples to the host immediately. */
    422         uint32_t cMixed;
    423506        rc = AudioMixBufMixToParent(&pGstStream->MixBuf, cWritten, &cMixed);
    424         LogFlowFunc(("cMixed=%RU32\n", cMixed));
    425     }
     507    }
     508#endif
     509
     510#if 0
     511    uint32_t cPlayed = 0;
     512    if (RT_SUCCESS(rc))
     513    {
     514        PDMAUDIOSTRMSTS strmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream);
     515        if (strmSts & PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE)
     516            rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream, &cPlayed);
     517    }
     518#endif
    426519
    427520#ifdef DEBUG_andy
     
    461554#endif
    462555
    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));
     556    LogFlowFunc(("cWritten=%RU32 (%RU32 bytes), cMixed=%RU32, rc=%Rrc\n",
     557                 cWritten, AUDIOMIXBUF_S2B(&pHstStream->MixBuf, cWritten), 0, rc));
    466558
    467559    int rc2 = RTCritSectLeave(&pThis->CritSect);
     
    581673
    582674#if 1
    583 static DECLCALLBACK(int) drvAudioStreamGetData(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, uint32_t *pcData)
     675static DECLCALLBACK(int) drvAudioStreamIterate(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream)
    584676{
    585677    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     
    593685        return rc;
    594686
    595     uint32_t cData = 0;
     687    LogFlowFunc(("[%s]\n", pStream->szName));
    596688
    597689    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     
    600692    do
    601693    {
    602         if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
    603             break;
     694        /*if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))
     695            break;*/
     696
     697        PDMAUDIOSTRMSTS hstStrmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream);
    604698
    605699        if (pHstStream->enmDir == PDMAUDIODIR_IN)
    606700        {
    607701            /* Call the host backend to capture the audio input data. */
    608             rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pHstStream, &cData);
     702            uint32_t cSamplesCaptured;
     703            rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pHstStream, &cSamplesCaptured);
    609704            if (RT_FAILURE(rc))
    610705                break;
     
    613708
    614709        }
    615         else /* Out */
     710        else /* PDMAUDIODIR_OUT */
    616711        {
    617712            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);
     713            uint32_t cSamplesToMix = AudioMixBufUsed(&pGstStream->MixBuf);
    629714
    630715            /* Has this stream marked as disabled but there still were guest streams relying
     
    633718                && !cSamplesToMix)
    634719            {
    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));
     720                rc = drvAudioStreamControlInternal(pThis, pGstStream, PDMAUDIOSTREAMCMD_DISABLE);
     721                if (RT_SUCCESS(rc))
     722                    rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     723
     724                if (RT_FAILURE(rc))
     725                    LogFunc(("%s: Backend vetoed against closing output stream, rc=%Rrc\n", pHstStream->szName, rc));
    645726
    646727                break;
    647728            }
    648729
    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         }
     730            uint32_t cSamplesPlayed = 0;
     731            if (hstStrmSts & PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE)
     732            {
     733            /*    int rc2 = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream, &cSamplesPlayed);
     734                if (RT_SUCCESS(rc))
     735                    rc = rc2;
     736            }*/
     737
     738                if (cSamplesToMix)
     739                    rc = AudioMixBufMixToParent(&pGstStream->MixBuf, cSamplesToMix, &cSamplesMixed);
     740            }
     741
     742            LogFlowFunc(("%s: %RU32/%RU32 samples mixed, %RU32 played\n",
     743                         pHstStream->szName, cSamplesMixed, cSamplesToMix, cSamplesPlayed));
     744        }
     745
     746        if (RT_SUCCESS(rc))
     747            rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, pHstStream);
    655748
    656749    } 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;
    664750
    665751    int rc2 = RTCritSectLeave(&pThis->CritSect);
     
    846932    /* pcSamplesPlayed is optional. */
    847933
     934    AssertMsg(pStream->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED,
     935              ("Unable to play stream '%s' (status is 0x%x)\n", pStream->szName, pStream->fStatus));
     936
    848937    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
    849938
     
    852941        return rc;
    853942
    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);
     943    LogFlowFunc(("[%s]\n", pStream->szName));
    871944
    872945    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
     946
     947    do
     948    {
     949        /* Backend output (temporarily) disabled / unavailable? */
     950        if (pThis->pHostDrvAudio->pfnGetStatus(pThis->pHostDrvAudio, PDMAUDIODIR_OUT) != PDMAUDIOBACKENDSTS_RUNNING)
     951        {
     952            rc = pThis->pHostDrvAudio->pfnGetConfig(pThis->pHostDrvAudio, &pThis->BackendCfg);
     953            AssertRC(rc);
     954
     955            if (   !pThis->BackendCfg.cSinks
     956                || !pThis->BackendCfg.cMaxStreamsOut)
     957            {
     958                rc = VERR_NOT_AVAILABLE;
     959                break;
     960            }
     961        }
     962
     963        PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     964        PPDMAUDIOSTREAM pGstStream = pHstStream->pPair;
     965        AssertPtr(pGstStream);
     966
     967        PDMAUDIOSTRMSTS strmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream);
     968
     969        if (strmSts & PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE)
     970        {
     971            rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream, &cSamplesPlayed);
     972            if (RT_FAILURE(rc))
     973            {
     974                int rc3 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
     975                AssertRC(rc3);
     976            }
     977        }
     978
     979        LogFlowFunc(("[%s] strmSts=0x%x, cSamplesPlayed=%RU32, rc=%Rrc\n", pStream->szName, strmSts, cSamplesPlayed, rc));
     980
     981    #if 0
     982            if (pStream->pPair)
     983            {
     984                bool fIsEmpty = AudioMixBufIsEmpty(&pStream->pPair->MixBuf);
     985
     986                if (   !pPair->State.fActive
     987                    && fIsEmpty)
     988                    continue;
     989
     990                if ()
     991                {
     992                    pGstStrmOut->State.fEmpty = true;
     993                    fNeedsCleanup |= !pGstStrmOut->State.fActive;
     994                }
     995            }
     996
     997            if (fNeedsCleanup)
     998            {
     999                RTListForEach(&pHstStrmOut->lstGstStrmOut, pGstStrmOut, PDMAUDIOGSTSTRMOUT, Node)
     1000                {
     1001                    if (!pGstStrmOut->State.fActive)
     1002                        drvAudioDestroyGstOut(pThis, pGstStrmOut);
     1003                }
     1004            }
     1005    #endif
     1006    } while (0);
    9151007
    9161008    if (RT_SUCCESS(rc))
     
    15741666        AssertRCBreak(rc);
    15751667
    1576         rc = AudioMixBufInit(&pHstStrm->MixBuf, pHstStrm->szName, &pHstStrm->Props, cSamples);
     1668        rc = AudioMixBufInit(&pHstStrm->MixBuf, pHstStrm->szName, &pHstStrm->Props, cSamples * 4);
    15771669        AssertRCBreak(rc);
    15781670
     
    15871679        AssertRCBreak(rc);
    15881680
    1589         rc = AudioMixBufInit(&pGstStrm->MixBuf, pGstStrm->szName, &pGstStrm->Props, AudioMixBufSize(&pHstStrm->MixBuf));
     1681        rc = AudioMixBufInit(&pGstStrm->MixBuf, pGstStrm->szName, &pGstStrm->Props, cSamples * 2);
    15901682        if (RT_SUCCESS(rc))
    15911683        {
    15921684            if (pCfgGuest->enmDir == PDMAUDIODIR_IN)
    15931685            {
     1686                /* Host (Parent) -> Guest (Child). */
    15941687                rc = AudioMixBufLinkTo(&pHstStrm->MixBuf, &pGstStrm->MixBuf);
    15951688            }
    15961689            else
    15971690            {
     1691                /* Guest (Parent) -> Host (Child). */
    15981692                rc = AudioMixBufLinkTo(&pGstStrm->MixBuf, &pHstStrm->MixBuf);
    15991693            }
     
    16181712            if (pHstStrm->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
    16191713            {
    1620                 rc = drvAudioStreamControlInternal(pThis, pHstStrm, PDMAUDIOSTREAMCMD_DISABLE);
     1714                rc = drvAudioStreamControlInternalBackend(pThis, pHstStrm, PDMAUDIOSTREAMCMD_DISABLE);
    16211715                if (RT_SUCCESS(rc))
    16221716                {
     
    16861780}
    16871781
     1782static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvAudioGetStatus(PPDMIAUDIOCONNECTOR pInterface, PDMAUDIODIR enmDir)
     1783{
     1784    AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN);
     1785
     1786    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
     1787
     1788    int rc = RTCritSectEnter(&pThis->CritSect);
     1789    if (RT_FAILURE(rc))
     1790        return PDMAUDIOBACKENDSTS_UNKNOWN;
     1791
     1792    PDMAUDIOBACKENDSTS backendSts = pThis->pHostDrvAudio->pfnGetStatus(pThis->pHostDrvAudio, enmDir);
     1793
     1794    int rc2 = RTCritSectLeave(&pThis->CritSect);
     1795    if (RT_SUCCESS(rc))
     1796        rc = rc2;
     1797
     1798    LogFlowFuncLeaveRC(rc);
     1799    return backendSts;
     1800}
     1801
    16881802static DECLCALLBACK(PDMAUDIOSTRMSTS) drvAudioStreamGetStatus(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream)
    16891803{
     
    17231837        rc = VERR_WRONG_ORDER;
    17241838
    1725     PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
    1726     if (   RT_SUCCESS(rc)
    1727         && pHstStream->cRefs == 1)
    1728     {
    1729         rc = drvAudioStreamDestroyInternalBackend(pThis, pHstStream);
     1839    if (RT_SUCCESS(rc))
     1840    {
     1841        rc = drvAudioStreamDestroyInternal(pThis, pStream);
    17301842        if (RT_SUCCESS(rc))
    1731         {
    1732             if (pStream->pPair)
    1733             {
    1734                 rc = drvAudioStreamDestroyInternal(pThis, pStream->pPair);
    1735                 pStream->pPair = NULL;
    1736             }
    1737 
    1738             if (RT_SUCCESS(rc))
    1739                 rc = drvAudioStreamDestroyInternal(pThis, pStream);
    1740 
    1741             if (RT_SUCCESS(rc))
    1742             {
    1743                 if (enmDir == PDMAUDIODIR_IN)
    1744                 {
    1745                     pThis->cStreamsFreeIn++;
    1746                 }
    1747                 else /* Out */
    1748                 {
    1749                     pThis->cStreamsFreeOut++;
    1750                 }
    1751             }
    1752         }
    1753     }
    1754     else
    1755         rc = VERR_WRONG_ORDER;
     1843            pStream = NULL;
     1844    }
     1845
     1846    if (RT_SUCCESS(rc))
     1847    {
     1848        if (enmDir == PDMAUDIODIR_IN)
     1849        {
     1850            pThis->cStreamsFreeIn++;
     1851        }
     1852        else /* Out */
     1853        {
     1854            pThis->cStreamsFreeOut++;
     1855        }
     1856    }
    17561857
    17571858    int rc2 = RTCritSectLeave(&pThis->CritSect);
     
    17671868static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream)
    17681869{
    1769     AssertPtrReturn(pThis,      VERR_INVALID_POINTER);
    1770     AssertPtrReturn(pHstStream, VERR_INVALID_POINTER);
     1870    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1871
     1872    if (!pHstStream)
     1873        return VINF_SUCCESS;
    17711874
    17721875    int rc = VINF_SUCCESS;
     
    17791882    if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)
    17801883    {
    1781         rc = drvAudioStreamControlInternal(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     1884        rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
    17821885        if (RT_SUCCESS(rc))
    17831886        {
     
    17861889                pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED;
    17871890        }
    1788 
    1789         AssertMsgRC(rc, ("Host stream '%s' failed to uninit in backend: %Rrc\n",  pHstStream->szName, rc));
    17901891    }
    17911892    else
     
    18061907    LogFlowFunc(("%s: cRefs=%RU32\n", pStream->szName, pStream->cRefs));
    18071908
    1808     int rc = VINF_SUCCESS;
    1809 
    1810     if (pStream->cRefs <= 1)
     1909    PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream);
     1910    PPDMAUDIOSTREAM pGstStream = pHstStream->pPair;
     1911
     1912    if (   (   pHstStream
     1913            && pHstStream->cRefs > 1)
     1914        || (   pGstStream
     1915            && pGstStream->cRefs > 1)
     1916       )
     1917    {
     1918        return VERR_WRONG_ORDER;
     1919    }
     1920
     1921    int rc = drvAudioStreamControlInternal(pThis, pGstStream, PDMAUDIOSTREAMCMD_DISABLE);
     1922    if (RT_SUCCESS(rc))
     1923        rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);
     1924
     1925    if (RT_SUCCESS(rc))
    18111926    {
    18121927        /* Unlink from pair. */
     
    18261941        pStream = NULL;
    18271942    }
    1828     else /* More than our own reference left? Bail out. */
    1829         rc = VERR_WRONG_ORDER;
    18301943
    18311944    if (RT_FAILURE(rc))
     
    18641977    LogFlowFuncEnter();
    18651978
    1866     /*
    1867      * Second, destroy all audio streams.
    1868      */
    1869     PPDMAUDIOSTREAM pStream;
    1870     RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node)
    1871     {
    1872         if (pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST)
    1873             drvAudioStreamDestroyInternalBackend(pThis, pStream);
    1874     }
     1979    PPDMAUDIOSTREAM pStream, pStreamNext;
     1980    RTListForEachSafe(&pThis->lstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, Node)
     1981        drvAudioStreamDestroyInternal(pThis, pStream);
    18751982
    18761983    /*
     
    19062013    /* IAudioConnector. */
    19072014    pThis->IAudioConnector.pfnGetConfig         = drvAudioGetConfig;
     2015    pThis->IAudioConnector.pfnGetStatus         = drvAudioGetStatus;
    19082016    pThis->IAudioConnector.pfnStreamCreate      = drvAudioStreamCreate;
    19092017    pThis->IAudioConnector.pfnStreamDestroy     = drvAudioStreamDestroy;
     
    19132021    pThis->IAudioConnector.pfnStreamRead        = drvAudioStreamRead;
    19142022    pThis->IAudioConnector.pfnStreamWrite       = drvAudioStreamWrite;
    1915     pThis->IAudioConnector.pfnStreamGetData     = drvAudioStreamGetData;
     2023    pThis->IAudioConnector.pfnStreamIterate     = drvAudioStreamIterate;
    19162024    pThis->IAudioConnector.pfnStreamGetStatus   = drvAudioStreamGetStatus;
    19172025    pThis->IAudioConnector.pfnStreamPlay        = drvAudioStreamPlay;
  • trunk/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp

    r61167 r61320  
    14331433
    14341434    return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED);
     1435}
     1436
     1437static DECLCALLBACK(int) drvHostALSAAudioStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     1438{
     1439    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1440    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1441
     1442    LogFlowFuncEnter();
     1443
     1444    /* Nothing to do here for ALSA. */
     1445    return VINF_SUCCESS;
    14351446}
    14361447
  • trunk/src/VBox/Devices/Audio/DrvHostNullAudio.cpp

    r61167 r61320  
    278278
    279279    return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED);
     280}
     281
     282static DECLCALLBACK(int) drvHostNullAudioStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     283{
     284    NOREF(pInterface);
     285    NOREF(pStream);
     286
     287    return VINF_SUCCESS;
    280288}
    281289
  • trunk/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp

    r61167 r61320  
    10431043
    10441044    return rc;
     1045}
     1046
     1047static DECLCALLBACK(int) drvHostOSSAudioStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     1048{
     1049    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1050    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1051
     1052    LogFlowFuncEnter();
     1053
     1054    /* Nothing to do here for OSS. */
     1055    return VINF_SUCCESS;
    10451056}
    10461057
  • trunk/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp

    r61167 r61320  
    105105    uint32_t               cbPCMBuf;
    106106    /** Pointer to opaque PulseAudio stream. */
    107     pa_stream             *pStream;
     107    pa_stream             *pPAStream;
    108108    /** Pulse sample format and attribute specification. */
    109109    pa_sample_spec         SampleSpec;
     
    321321        paError(pStrm->pDrv, "Failed to drain stream");
    322322
    323     pa_operation_unref(pStrm->pDrainOp);
    324     pStrm->pDrainOp = NULL;
     323    if (pStrm->pDrainOp)
     324    {
     325        pa_operation_unref(pStrm->pDrainOp);
     326        pStrm->pDrainOp = NULL;
     327    }
    325328}
    326329
     
    631634    pStrm->BufAttr.maxlength   = (pStrm->BufAttr.tlength * 3) / 2;
    632635    pStrm->BufAttr.prebuf      = -1; /* Same as tlength */
    633 
    634     /* Set minreq to 0, as we want to control ourselves when to start/stop the stream. */
    635     pStrm->BufAttr.minreq      = 0;
     636    pStrm->BufAttr.minreq      = -1;
    636637
    637638    /* Note that the struct BufAttr is updated to the obtained values after this call! */
    638     int rc = paStreamOpen(pThis, false /* fIn */, "PulseAudio (Out)", &pStrm->SampleSpec, &pStrm->BufAttr, &pStrm->pStream);
     639    int rc = paStreamOpen(pThis, false /* fIn */, "PulseAudio (Out)", &pStrm->SampleSpec, &pStrm->BufAttr, &pStrm->pPAStream);
    639640    if (RT_FAILURE(rc))
    640641        return rc;
     
    706707    /* Note: Other members of BufAttr are ignored for record streams. */
    707708    int rc = paStreamOpen(pThis, true /* fIn */, "PulseAudio (In)", &pStrm->SampleSpec, &pStrm->BufAttr,
    708                           &pStrm->pStream);
     709                          &pStrm->pPAStream);
    709710    if (RT_FAILURE(rc))
    710711        return rc;
     
    731732                 pStream->Props.uHz, pStream->Props.cChannels, pStream->Props.cShift, cSamples));
    732733
     734        /* Save pointer to driver instance. */
     735        pStrm->pDrv       = pThis;
     736        pStrm->pu8PeekBuf = NULL;
     737
    733738        if (pcSamples)
    734739            *pcSamples = cSamples;
    735 
    736         /* Save pointer to driver instance. */
    737         pStrm->pDrv = pThis;
    738 
    739         pStrm->pu8PeekBuf = NULL;
    740740    }
    741741
     
    756756    /* We should only call pa_stream_readable_size() once and trust the first value. */
    757757    pa_threaded_mainloop_lock(pThis->pMainLoop);
    758     size_t cbAvail = pa_stream_readable_size(pStrm->pStream);
     758    size_t cbAvail = pa_stream_readable_size(pStrm->pPAStream);
    759759    pa_threaded_mainloop_unlock(pThis->pMainLoop);
    760760
     
    792792        {
    793793            pa_threaded_mainloop_lock(pThis->pMainLoop);
    794             pa_stream_peek(pStrm->pStream,
     794            pa_stream_peek(pStrm->pPAStream,
    795795                           (const void**)&pStrm->pu8PeekBuf, &pStrm->cbPeekBuf);
    796796            pa_threaded_mainloop_unlock(pThis->pMainLoop);
     
    840840        {
    841841            pa_threaded_mainloop_lock(pThis->pMainLoop);
    842             pa_stream_drop(pStrm->pStream);
     842            pa_stream_drop(pStrm->pPAStream);
    843843            pa_threaded_mainloop_unlock(pThis->pMainLoop);
    844844
     
    878878    uint32_t cbReadTotal = 0;
    879879
    880     uint32_t cLive = AudioMixBufAvail(&pStream->MixBuf);
     880    uint32_t cLive = AudioMixBufUsed(&pStream->MixBuf);
    881881    if (!cLive)
    882882    {
     
    891891    do
    892892    {
    893         size_t cbWriteable = pa_stream_writable_size(pPAStream->pStream);
     893        size_t cbWriteable = pa_stream_writable_size(pPAStream->pPAStream);
    894894        if (cbWriteable == (size_t)-1)
    895895        {
     
    916916
    917917            cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead);
    918             if (pa_stream_write(pPAStream->pStream, pPAStream->pvPCMBuf, cbRead, NULL /* Cleanup callback */,
     918            if (pa_stream_write(pPAStream->pPAStream, pPAStream->pvPCMBuf, cbRead, NULL /* Cleanup callback */,
    919919                                0, PA_SEEK_RELATIVE) < 0)
    920920            {
     
    960960    {
    961961        int rc2 = pa_context_errno(pThis->pContext);
    962         LogRel(("PulseAudio: %s: %s\n", szMsg, pa_strerror(rc2)));
     962        LogRel2(("PulseAudio: %s: %s\n", szMsg, pa_strerror(rc2)));
    963963    }
    964964
     
    11361136    LogFlowFuncEnter();
    11371137
    1138     if (pStrm->pStream)
     1138    if (pStrm->pPAStream)
    11391139    {
    11401140        pa_threaded_mainloop_lock(pThis->pMainLoop);
    11411141
    1142         pa_stream_disconnect(pStrm->pStream);
    1143         pa_stream_unref(pStrm->pStream);
     1142        pa_stream_disconnect(pStrm->pPAStream);
     1143        pa_stream_unref(pStrm->pPAStream);
    11441144
    11451145        pa_threaded_mainloop_unlock(pThis->pMainLoop);
    11461146
    1147         pStrm->pStream = NULL;
     1147        pStrm->pPAStream = NULL;
    11481148    }
    11491149
     
    11611161    LogFlowFuncEnter();
    11621162
    1163     if (pStrm->pStream)
     1163    if (pStrm->pPAStream)
    11641164    {
    11651165        pa_threaded_mainloop_lock(pThis->pMainLoop);
    11661166
    1167         pa_stream_disconnect(pStrm->pStream);
    1168         pa_stream_unref(pStrm->pStream);
     1167        /* Make sure to cancel a pending draining operation, if any. */
     1168        if (pStrm->pDrainOp)
     1169        {
     1170            pa_operation_cancel(pStrm->pDrainOp);
     1171            pStrm->pDrainOp = NULL;
     1172        }
     1173
     1174        pa_stream_disconnect(pStrm->pPAStream);
     1175        pa_stream_unref(pStrm->pPAStream);
    11691176
    11701177        pa_threaded_mainloop_unlock(pThis->pMainLoop);
    11711178
    1172         pStrm->pStream = NULL;
     1179        pStrm->pPAStream = NULL;
    11731180    }
    11741181
     
    12131220            else
    12141221            {
    1215                 rc = paWaitFor(pThis, pa_stream_cork(pStrm->pStream, 0, paStreamCbSuccess, pStrm));
     1222                rc = paWaitFor(pThis, pa_stream_cork(pStrm->pPAStream, 0, paStreamCbSuccess, pStrm));
    12161223            }
    12171224
     
    12281235            if (!pStrm->pDrainOp)
    12291236            {
    1230                 rc = paWaitFor(pThis, pa_stream_trigger(pStrm->pStream, paStreamCbSuccess, pStrm));
     1237                rc = paWaitFor(pThis, pa_stream_trigger(pStrm->pPAStream, paStreamCbSuccess, pStrm));
    12311238                if (RT_LIKELY(RT_SUCCESS(rc)))
    1232                     pStrm->pDrainOp = pa_stream_drain(pStrm->pStream, paStreamCbDrain, pStrm);
     1239                    pStrm->pDrainOp = pa_stream_drain(pStrm->pPAStream, paStreamCbDrain, pStrm);
    12331240            }
    12341241            pa_threaded_mainloop_unlock(pThis->pMainLoop);
     
    12651272        {
    12661273            pa_threaded_mainloop_lock(pThis->pMainLoop);
    1267             rc = paWaitFor(pThis, pa_stream_cork(pStrm->pStream, 0 /* Play / resume */, paStreamCbSuccess, pStrm));
     1274            rc = paWaitFor(pThis, pa_stream_cork(pStrm->pPAStream, 0 /* Play / resume */, paStreamCbSuccess, pStrm));
    12681275            pa_threaded_mainloop_unlock(pThis->pMainLoop);
    12691276            break;
     
    12761283            if (pStrm->pu8PeekBuf) /* Do we need to drop the peek buffer?*/
    12771284            {
    1278                 pa_stream_drop(pStrm->pStream);
     1285                pa_stream_drop(pStrm->pPAStream);
    12791286                pStrm->pu8PeekBuf = NULL;
    12801287            }
    12811288
    1282             rc = paWaitFor(pThis, pa_stream_cork(pStrm->pStream, 1 /* Stop / pause */, paStreamCbSuccess, pStrm));
     1289            rc = paWaitFor(pThis, pa_stream_cork(pStrm->pPAStream, 1 /* Stop / pause */, paStreamCbSuccess, pStrm));
    12831290            pa_threaded_mainloop_unlock(pThis->pMainLoop);
    12841291            break;
     
    13881395static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostPulseAudioStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
    13891396{
    1390     NOREF(pInterface);
    1391     NOREF(pStream);
    1392 
    1393     return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED);
     1397    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1398    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1399
     1400    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     1401    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pStream;
     1402
     1403    PDMAUDIOSTRMSTS strmSts  = PDMAUDIOSTRMSTS_FLAG_INITIALIZED
     1404                             | PDMAUDIOSTRMSTS_FLAG_ENABLED;
     1405
     1406    pa_context_state_t ctxState = pa_context_get_state(pThis->pContext);
     1407
     1408    if (   pa_context_get_state(pThis->pContext) == PA_CONTEXT_READY
     1409        && pa_stream_get_state(pStrm->pPAStream) == PA_STREAM_READY)
     1410    {
     1411        if (pStream->enmDir == PDMAUDIODIR_IN)
     1412        {
     1413
     1414        }
     1415        else
     1416        {
     1417            size_t cbSize = pa_stream_writable_size(pStrm->pPAStream);
     1418            LogFlowFunc(("cbSize=%zu\n", cbSize));
     1419
     1420            if (cbSize >= pStrm->BufAttr.minreq)
     1421            {
     1422                strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE;
     1423            }
     1424        }
     1425    }
     1426
     1427    return strmSts;
     1428}
     1429
     1430static DECLCALLBACK(int) drvHostPulseAudioStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     1431{
     1432    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     1433    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     1434
     1435    PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);
     1436    PPULSEAUDIOSTREAM  pStrm = (PPULSEAUDIOSTREAM)pStream;
     1437
     1438    LogFlowFuncEnter();
     1439
     1440    /* Nothing to do here for PulseAudio. */
     1441    return VINF_SUCCESS;
    13941442}
    13951443
  • trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp

    r61167 r61320  
    55
    66/*
    7  * Copyright (C) 2014-2015 Oracle Corporation
     7 * Copyright (C) 2014-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4848        44100,                    /* Hz */
    4949        2                         /* Channels */,
    50         PDMAUDIOFMT_S16               /* Format */,
     50        PDMAUDIOFMT_S16           /* Format */,
    5151        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
    5252    };
     
    104104    RTTESTI_CHECK(AudioMixBufFree(&mb) == 1);
    105105    RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, 1U));
    106     RTTESTI_CHECK(AudioMixBufProcessed(&mb) == cToWrite + written_abs /* + last absolute write */);
     106    RTTESTI_CHECK(AudioMixBufUsed(&mb) == cToWrite + written_abs /* + last absolute write */);
    107107
    108108    RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&mb, &samples16, sizeof(samples16), &written));
     
    110110    RTTESTI_CHECK(AudioMixBufFree(&mb) == 0);
    111111    RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, 0));
    112     RTTESTI_CHECK(AudioMixBufProcessed(&mb) == cBufSize);
     112    RTTESTI_CHECK(AudioMixBufUsed(&mb) == cBufSize);
    113113
    114114    /* Circular reads. */
     
    123123    RTTESTI_CHECK(AudioMixBufFree(&mb) == AudioMixBufSize(&mb) - written_abs - 1);
    124124    RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, cBufSize - written_abs - 1));
    125     RTTESTI_CHECK(AudioMixBufProcessed(&mb) == cBufSize - cToRead + written_abs);
     125    RTTESTI_CHECK(AudioMixBufUsed(&mb) == cBufSize - cToRead + written_abs);
    126126
    127127    RTTESTI_CHECK_RC_OK(AudioMixBufReadCirc(&mb, &samples16, sizeof(samples16), &read));
     
    130130    RTTESTI_CHECK(AudioMixBufFree(&mb) == cBufSize - written_abs);
    131131    RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, cBufSize - written_abs));
    132     RTTESTI_CHECK(AudioMixBufProcessed(&mb) == written_abs);
     132    RTTESTI_CHECK(AudioMixBufUsed(&mb) == written_abs);
    133133
    134134    AudioMixBufDestroy(&mb);
     
    139139static int tstParentChild(RTTEST hTest)
    140140{
    141     RTTestSubF(hTest, "2 Children -> Parent");
    142 
    143     uint32_t cBufSize = _1K;
     141    uint32_t cBufSize = RTRandU32() % 256;
    144142
    145143    PDMAUDIOSTREAMCFG cfg_p =
     
    150148        44100,                    /* Hz */
    151149        2                         /* Channels */,
    152         PDMAUDIOFMT_S16               /* Format */,
     150        PDMAUDIOFMT_S16           /* Format */,
    153151        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
    154152    };
     
    168166        22050,                    /* Hz */
    169167        2                         /* Channels */,
    170         PDMAUDIOFMT_S16               /* Format */,
     168        PDMAUDIOFMT_S16           /* Format */,
    171169        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
    172170    };
     
    186184        48000,                    /* Hz */
    187185        2                         /* Channels */,
    188         PDMAUDIOFMT_S16               /* Format */,
     186        PDMAUDIOFMT_S16           /* Format */,
    189187        PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */
    190188    };
     
    215213    uint32_t cSamplesChild2  = 16;
    216214
    217     uint32_t t = RTRandU32() % 64;
     215    uint32_t t = RTRandU32() % 1024;
     216
     217    RTTestPrintf(hTest, RTTESTLVL_DEBUG, "%RU32 iterations total\n", t);
     218
     219    /*
     220     * Using AudioMixBufWriteAt for writing to children.
     221     */
     222    RTTestSubF(hTest, "2 Children -> Parent (AudioMixBufWriteAt)");
    218223
    219224    for (uint32_t i = 0; i < t; i++)
     
    223228        RTTESTI_CHECK_MSG_BREAK(written == cSamplesChild1, ("Child1: Expected %RU32 written samples, got %RU32\n", cSamplesChild1, written));
    224229        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child1, written, &mixed));
    225         temp = AudioMixBufProcessed(&parent) - AudioMixBufMixed(&child2);
    226         RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child1) == temp, ("Child1: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child1), temp));
     230        RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child1) == mixed, ("Child1: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child1), mixed));
     231        RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child1) == AUDIOMIXBUF_S2S_RATIO(&parent, mixed), ("Child1: Expected %RU32 used samples, got %RU32\n", AudioMixBufMixed(&child1), AUDIOMIXBUF_S2S_RATIO(&parent, mixed)));
     232        RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&parent) == 0, ("Parent: Expected 0 used samples, got %RU32\n", AudioMixBufUsed(&parent)));
    227233
    228234        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteAt(&child2, 0, &samples, sizeof(samples), &written));
    229235        RTTESTI_CHECK_MSG_BREAK(written == cSamplesChild2, ("Child2: Expected %RU32 written samples, got %RU32\n", cSamplesChild2, written));
    230236        RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child2, written, &mixed));
    231         temp = AudioMixBufProcessed(&parent) - AudioMixBufMixed(&child1);
    232         RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child2) == temp, ("Child2: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child2), temp));
    233     }
    234 
    235     RTTESTI_CHECK(AudioMixBufProcessed(&parent) == AudioMixBufMixed(&child1) + AudioMixBufMixed(&child2));
     237        RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child2) == mixed, ("Child2: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child2), temp));
     238        RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child2) == AUDIOMIXBUF_S2S_RATIO(&parent, mixed), ("Child2: Expected %RU32 used samples, got %RU32\n", AudioMixBufMixed(&child2), AUDIOMIXBUF_S2S_RATIO(&parent, mixed)));
     239        RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&parent) == 0, ("Parent2: Expected 0 used samples, got %RU32\n", AudioMixBufUsed(&parent)));
     240    }
     241
     242    RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufMixed(&child1) + AudioMixBufMixed(&child2));
    236243
    237244    for (;;)
     
    243250    }
    244251
    245     RTTESTI_CHECK(AudioMixBufProcessed(&parent) == 0);
     252    RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);
    246253    RTTESTI_CHECK(AudioMixBufMixed(&child1) == 0);
    247254    RTTESTI_CHECK(AudioMixBufMixed(&child2) == 0);
     
    328335    RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written));
    329336    RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed));
    330     temp = AudioMixBufProcessed(&parent);
     337    temp = AudioMixBufUsed(&parent);
    331338    RTTESTI_CHECK_MSG(AudioMixBufMixed(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child), temp));
    332339
    333     RTTESTI_CHECK(AudioMixBufProcessed(&parent) == AudioMixBufMixed(&child));
     340    RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufMixed(&child));
    334341
    335342    for (;;)
     
    355362    }
    356363
    357     RTTESTI_CHECK(AudioMixBufProcessed(&parent) == 0);
     364    RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);
    358365    RTTESTI_CHECK(AudioMixBufMixed(&child) == 0);
    359366
     
    431438    RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written));
    432439    RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed));
    433     temp = AudioMixBufProcessed(&parent);
     440    temp = AudioMixBufUsed(&parent);
    434441    RTTESTI_CHECK_MSG(AudioMixBufMixed(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child), temp));
    435442
    436     RTTESTI_CHECK(AudioMixBufProcessed(&parent) == AudioMixBufMixed(&child));
     443    RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufMixed(&child));
    437444
    438445    for (;;)
     
    458465    }
    459466
    460     RTTESTI_CHECK(AudioMixBufProcessed(&parent) == 0);
     467    RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0);
    461468    RTTESTI_CHECK(AudioMixBufMixed(&child) == 0);
    462469
  • trunk/src/VBox/Devices/Makefile.kmk

    r61157 r61320  
    55
    66#
    7 # Copyright (C) 2006-2015 Oracle Corporation
     7# Copyright (C) 2006-2016 Oracle Corporation
    88#
    99# This file is part of VirtualBox Open Source Edition (OSE), as
     
    565565
    566566 ifeq ($(KBUILD_TARGET),linux)
    567   VBoxDD_SOURCES += \
    568    Audio/DrvHostOSSAudio.cpp
     567  ifdef VBOX_WITH_OSS
     568   VBoxDD_DEFS    += VBOX_WITH_OSS
     569   VBoxDD_SOURCES += \
     570        Audio/DrvHostOSSAudio.cpp
     571  endif
    569572
    570573  ifdef VBOX_WITH_PULSE
     
    584587
    585588 ifeq ($(KBUILD_TARGET),freebsd)
    586   VBoxDD_SOURCES  += \
    587         Audio/DrvHostOSSAudio.cpp
     589  ifdef VBOX_WITH_OSS
     590   VBoxDD_DEFS    += VBOX_WITH_OSS
     591   VBoxDD_SOURCES  += \
     592        Audio/DrvHostOSSAudio.cpp
     593  endif
    588594  ifdef VBOX_WITH_PULSE
    589595   VBoxDD_DEFS    += VBOX_WITH_PULSE
     
    595601
    596602 ifeq ($(KBUILD_TARGET),solaris)
    597   ifdef VBOX_WITH_SOLARIS_OSS
     603  ifdef VBOX_WITH_OSS
    598604   VBoxDD_SOURCES += Audio/DrvHostOSSAudio.cpp
    599    VBoxDD_DEFS    += VBOX_WITH_SOLARIS_OSS
     605   VBoxDD_DEFS    += VBOX_WITH_OSS
    600606  endif
    601607 endif
  • trunk/src/VBox/Devices/build/VBoxDD.cpp

    r59248 r61320  
    289289        return rc;
    290290# endif
     291# ifdef VBOX_WITH_OSS
    291292    rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostOSSAudio);
    292293    if (RT_FAILURE(rc))
    293294        return rc;
     295# endif
    294296#endif /* RT_OS_LINUX */
    295297#if defined(RT_OS_FREEBSD)
     298# ifdef VBOX_WITH_OSS
    296299    rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostOSSAudio);
    297300    if (RT_FAILURE(rc))
    298301        return rc;
     302# endif
    299303#endif
    300304#if defined(RT_OS_DARWIN)
     
    304308#endif
    305309#if defined(RT_OS_SOLARIS)
     310# ifdef VBOX_WITH_OSS
    306311    rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostOSSAudio);
    307312    if (RT_FAILURE(rc))
    308313        return rc;
     314# endif
    309315#endif
    310316    rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvACPI);
  • trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp

    r61157 r61320  
    28892889                }
    28902890#endif
    2891 #if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(VBOX_WITH_SOLARIS_OSS)
     2891#ifdef VBOX_WITH_OSS
    28922892                case AudioDriverType_OSS:
    28932893                {
  • trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp

    r61167 r61320  
    424424
    425425    return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED);
     426}
     427
     428static DECLCALLBACK(int) drvAudioVRDEStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)
     429{
     430    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
     431    AssertPtrReturn(pStream,    VERR_INVALID_POINTER);
     432
     433    LogFlowFuncEnter();
     434
     435    /* Nothing to do here for VRDE. */
     436    return VINF_SUCCESS;
    426437}
    427438
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