VirtualBox

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


Ignore:
Timestamp:
Mar 26, 2021 2:02:35 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143511
Message:

Audio: Check that the backend (host audio driver) implements all the methods we require. Some minor mixer cleanups. bugref:9890

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

Legend:

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

    r88269 r88298  
    105105static int audioMixerSinkSetRecSourceInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
    106106static int audioMixerSinkUpdateInternal(PAUDMIXSINK pSink);
    107 static int audioMixerSinkMultiplexSync(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWrittenMin);
     107static int audioMixerSinkMultiplexSync(PAUDMIXSINK pSink, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
    108108static int audioMixerSinkWriteToStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pMixStream);
    109109static int audioMixerSinkWriteToStreamEx(PAUDMIXSINK pSink, PAUDMIXSTREAM pMixStream, uint32_t cbToWrite, uint32_t *pcbWritten);
     
    114114
    115115
     116/** size of output buffer for dbgAudioMixerSinkStatusToStr.   */
     117#define AUDIOMIXERSINK_STATUS_STR_MAX sizeof("RUNNING PENDING_DISABLE DIRTY 0x12345678")
     118
    116119/**
    117120 * Converts a mixer sink status to a string.
    118121 *
    119  * @returns Stringified mixer sink status flags. Must be free'd with RTStrFree().
    120  *          "NONE" if no flags set.
    121  * @param   fStatus             Mixer sink status to convert.
    122  */
    123 static char *dbgAudioMixerSinkStatusToStr(AUDMIXSINKSTS fStatus)
    124 {
    125 #define APPEND_FLAG_TO_STR(_aFlag)              \
    126     if (fStatus & AUDMIXSINK_STS_##_aFlag)      \
    127     {                                           \
    128         if (pszFlags)                           \
    129         {                                       \
    130             rc2 = RTStrAAppend(&pszFlags, " "); \
    131             if (RT_FAILURE(rc2))                \
    132                 break;                          \
    133         }                                       \
    134                                                 \
    135         rc2 = RTStrAAppend(&pszFlags, #_aFlag); \
    136         if (RT_FAILURE(rc2))                    \
    137             break;                              \
    138     }                                           \
    139 
    140     char *pszFlags = NULL;
    141     int rc2 = VINF_SUCCESS;
    142 
    143     if (fStatus == AUDMIXSINK_STS_NONE) /* This is special, as this is value 0. */
    144     {
    145         rc2 = RTStrAAppend(&pszFlags, "NONE");
    146     }
    147     else
    148     {
    149         do
    150         {
    151             APPEND_FLAG_TO_STR(RUNNING);
    152             APPEND_FLAG_TO_STR(PENDING_DISABLE);
    153             APPEND_FLAG_TO_STR(DIRTY);
    154 
    155         } while (0);
    156     }
    157 
    158     if (   RT_FAILURE(rc2)
    159         && pszFlags)
    160     {
    161         RTStrFree(pszFlags);
    162         pszFlags = NULL;
    163     }
    164 
    165 #undef APPEND_FLAG_TO_STR
    166 
    167     return pszFlags;
     122 * @returns pszDst
     123 * @param   fStatus     The mixer sink status.
     124 * @param   pszDst      The output buffer.  Must be at least
     125 *                      AUDIOMIXERSINK_STATUS_STR_MAX in length.
     126 */
     127static const char *dbgAudioMixerSinkStatusToStr(AUDMIXSINKSTS fStatus, char pszDst[AUDIOMIXERSINK_STATUS_STR_MAX])
     128{
     129    if (!fStatus)
     130        return strcpy(pszDst, "NONE");
     131    static const struct
     132    {
     133        const char *pszMnemonic;
     134        uint32_t    cchMnemonic;
     135        uint32_t    fStatus;
     136    } s_aFlags[] =
     137    {
     138        { RT_STR_TUPLE("RUNNING"),          AUDMIXSINK_STS_RUNNING },
     139        { RT_STR_TUPLE("PENDING_DISABLE"),  AUDMIXSINK_STS_PENDING_DISABLE },
     140        { RT_STR_TUPLE("DIRTY"),            AUDMIXSINK_STS_DIRTY },
     141    };
     142    char *psz = pszDst;
     143    for (size_t i = 0; i < RT_ELEMENTS(s_aFlags); i++)
     144        if (fStatus & s_aFlags[i].fStatus)
     145        {
     146            memcpy(psz, s_aFlags[i].pszMnemonic, s_aFlags[i].cchMnemonic);
     147            psz += s_aFlags[i].cchMnemonic;
     148            fStatus &= ~s_aFlags[i].fStatus;
     149            if (!fStatus)
     150            {
     151                psz[-1] = '\0';
     152                return pszDst;
     153            }
     154        }
     155    RTStrPrintf(psz, AUDIOMIXERSINK_STATUS_STR_MAX - (psz - pszDst), "%#x", fStatus);
     156    return pszDst;
    168157}
    169158
     
    811800    }
    812801
    813     char *pszStatus = dbgAudioMixerSinkStatusToStr(pSink->fStatus);
    814     LogRel2(("Audio Mixer: Set new status of sink '%s' to %s\n", pSink->pszName, pszStatus));
    815     LogFlowFunc(("[%s] enmCmd=%RU32, fStatus=%s, rc=%Rrc\n", pSink->pszName, enmSinkCmd, pszStatus, rc));
    816     RTStrFree(pszStatus);
     802#if defined(RTLOG_REL_ENABLED) || defined(LOG_ENABLED)
     803    char szStatus[AUDIOMIXERSINK_STATUS_STR_MAX];
     804#endif
     805    LogRel2(("Audio Mixer: Set new status of sink '%s': %s (enmCmd=%RU32 rc=%Rrc)\n",
     806             pSink->pszName, dbgAudioMixerSinkStatusToStr(pSink->fStatus, szStatus), enmSinkCmd, rc));
    817807
    818808    int rc2 = RTCritSectLeave(&pSink->CritSect);
     
    12841274
    12851275#ifdef LOG_ENABLED
    1286     char *pszStatus = dbgAudioMixerSinkStatusToStr(pSink->fStatus);
    1287     Log2Func(("[%s] cbRead=%RU32, fClean=%RTbool, fStatus=%s, rc=%Rrc\n", pSink->pszName, cbRead, fClean, pszStatus, rc));
    1288     RTStrFree(pszStatus);
     1276    char szStatus[AUDIOMIXERSINK_STATUS_STR_MAX];
    12891277#endif
     1278    Log2Func(("[%s] cbRead=%RU32, fClean=%RTbool, fStatus=%s, rc=%Rrc\n",
     1279              pSink->pszName, cbRead, fClean, dbgAudioMixerSinkStatusToStr(pSink->fStatus, szStatus), rc));
    12901280
    12911281    if (pcbRead)
     
    16751665    AssertPtrReturn(pSink, VERR_INVALID_POINTER);
    16761666
    1677     int rc = VINF_SUCCESS;
    1678 
    16791667#ifdef LOG_ENABLED
    1680     char *pszStatus = dbgAudioMixerSinkStatusToStr(pSink->fStatus);
    1681     Log3Func(("[%s] fStatus=%s\n", pSink->pszName, pszStatus));
    1682     RTStrFree(pszStatus);
     1668    char szStatus[AUDIOMIXERSINK_STATUS_STR_MAX];
    16831669#endif
     1670    Log3Func(("[%s] fStatus=%s\n", pSink->pszName, dbgAudioMixerSinkStatusToStr(pSink->fStatus, szStatus)));
    16841671
    16851672    /* Sink disabled? Take a shortcut. */
    16861673    if (!(pSink->fStatus & AUDMIXSINK_STS_RUNNING))
    1687         return rc;
     1674        return VINF_SUCCESS;
    16881675
    16891676    /* Input sink and no recording source set? Bail out early. */
    16901677    if (   pSink->enmDir == AUDMIXSINKDIR_INPUT
    16911678        && pSink->In.pStreamRecSource == NULL)
    1692         return rc;
     1679        return VINF_SUCCESS;
    16931680
    16941681    /* Sanity. */
     
    17101697    uint32_t cbToWriteToStreams = AudioMixBufUsedBytes(&pSink->MixBuf);
    17111698
     1699    int rc = VINF_SUCCESS;
    17121700    while (cbToWriteToStreams)
    17131701    {
    17141702        uint32_t cfChunk;
    1715         rc  = AudioMixBufAcquireReadBlock(&pSink->MixBuf, pSink->pabScratchBuf, RT_MIN(cbToWriteToStreams, (uint32_t)pSink->cbScratchBuf),
    1716                                           &cfChunk);
     1703        rc  = AudioMixBufAcquireReadBlock(&pSink->MixBuf, pSink->pabScratchBuf,
     1704                                          RT_MIN(cbToWriteToStreams, (uint32_t)pSink->cbScratchBuf), &cfChunk);
    17171705        if (RT_FAILURE(rc))
    17181706            break;
     
    17231711        /* Multiplex the current chunk in a synchronized fashion to all connected streams. */
    17241712        uint32_t cbChunkWrittenMin = 0;
    1725         rc = audioMixerSinkMultiplexSync(pSink, AUDMIXOP_COPY, pSink->pabScratchBuf, cbChunk, &cbChunkWrittenMin);
     1713        rc = audioMixerSinkMultiplexSync(pSink, pSink->pabScratchBuf, cbChunk, &cbChunkWrittenMin);
    17261714        if (RT_SUCCESS(rc))
    17271715        {
     
    19311919
    19321920    const uint32_t cbWritableStream = pMixStream->pConn->pfnStreamGetWritable(pMixStream->pConn, pMixStream->pStream);
    1933                    cbToWrite        = RT_MIN(cbToWrite, RT_MIN((uint32_t)RTCircBufUsed(pCircBuf), cbWritableStream));
    1934 
    1935     Log3Func(("[%s] cbWritableStream=%RU32, cbToWrite=%RU32\n",
    1936               pMixStream->pszName, cbWritableStream, cbToWrite));
     1921    cbToWrite = RT_MIN(cbToWrite, RT_MIN((uint32_t)RTCircBufUsed(pCircBuf), cbWritableStream));
     1922
     1923    Log3Func(("[%s] cbWritableStream=%RU32, cbToWrite=%RU32\n", pMixStream->pszName, cbWritableStream, cbToWrite));
    19371924
    19381925    uint32_t cbWritten = 0;
     
    19601947                    break;
    19611948                }
    1962                 else if (rc == VERR_AUDIO_STREAM_NOT_READY)
     1949                if (rc == VERR_AUDIO_STREAM_NOT_READY)
    19631950                {
    19641951                    /* Stream is not enabled, just skip. */
     
    20031990 *
    20041991 * @returns IPRT status code.
    2005  * @param   pSink               Sink to write audio output to.
    2006  * @param   enmOp               What mixing operation to use. Currently not implemented.
    2007  * @param   pvBuf               Pointer to audio data to write.
    2008  * @param   cbBuf               Size (in bytes) of audio data to write.
    2009  * @param   pcbWrittenMin       Returns minimum size (in bytes) successfully written to all mixer streams. Optional.
    2010  */
    2011 static int audioMixerSinkMultiplexSync(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf,
    2012                                        uint32_t *pcbWrittenMin)
    2013 {
     1992 * @param   pSink       Sink to write audio output to.
     1993 * @param   pvBuf       Pointer to audio data to write.
     1994 * @param   cbBuf       Size (in bytes) of audio data to write.
     1995 * @param   pcbWritten  Returns the number of bytes written to each of the
     1996 *                      streams.
     1997 */
     1998static int audioMixerSinkMultiplexSync(PAUDMIXSINK pSink, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
     1999{
     2000    Log3Func(("[%s] cbBuf=%RU32\n", pSink->pszName, cbBuf));
    20142001    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
    2015     RT_NOREF(enmOp);
    2016 
    20172002    AssertMsg(pSink->enmDir == AUDMIXSINKDIR_OUTPUT,
    20182003              ("%s: Can't multiplex to a sink which is not an output sink\n", pSink->pszName));
    20192004
    2020     int rc = VINF_SUCCESS;
    2021 
    2022     uint32_t cbToWriteMin = UINT32_MAX;
    2023 
    2024     Log3Func(("[%s] cbBuf=%RU32\n", pSink->pszName, cbBuf));
    2025 
     2005    /*
     2006     * Check all enabled streems for buffer space.
     2007     */
     2008    uint32_t      cbToWrite = UINT32_MAX;
    20262009    PAUDMIXSTREAM pMixStream;
    20272010    RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node)
    20282011    {
    2029         if (!(pMixStream->fStatus & AUDMIXSTREAM_STATUS_ENABLED)) /* Mixing stream not enabled? Skip handling. */
    2030         {
     2012        if (pMixStream->fStatus & AUDMIXSTREAM_STATUS_ENABLED)
     2013        {
     2014            uint32_t const cbCircFree = (uint32_t)RTCircBufFree(pMixStream->pCircBuf);
     2015            cbToWrite = RT_MIN(cbToWrite, cbCircFree);
     2016        }
     2017        else
    20312018            Log3Func(("[%s] Stream '%s' disabled, skipping ...\n", pSink->pszName, pMixStream->pszName));
    2032             continue;
    2033         }
    2034 
    2035         cbToWriteMin = RT_MIN(cbBuf, RT_MIN(cbToWriteMin, (uint32_t)RTCircBufFree(pMixStream->pCircBuf)));
    2036     }
    2037 
    2038     if (cbToWriteMin == UINT32_MAX) /* No space at all? */
    2039         cbToWriteMin = 0;
    2040 
    2041     if (cbToWriteMin)
    2042     {
     2019    }
     2020    if (cbToWrite != UINT32_MAX)
     2021        cbToWrite = RT_MIN(cbBuf, cbToWrite);
     2022    else
     2023        cbToWrite = 0; /* No active streams at all. */
     2024    if (cbToWrite)
     2025    {
     2026        /*
     2027         * Do the copying.
     2028         */
    20432029        RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node)
    20442030        {
    2045             if (!(pMixStream->fStatus & AUDMIXSTREAM_STATUS_ENABLED)) /* Mixing stream not enabled? Skip handling. */
    2046                 continue;
    2047 
    2048             PRTCIRCBUF pCircBuf = pMixStream->pCircBuf;
    2049             void *pvChunk;
    2050             size_t cbChunk;
    2051 
    2052             uint32_t cbWrittenBuf = 0;
    2053             uint32_t cbToWriteBuf = cbToWriteMin;
    2054 
    2055             while (cbToWriteBuf)
     2031            if (pMixStream->fStatus & AUDMIXSTREAM_STATUS_ENABLED)
    20562032            {
    2057                 RTCircBufAcquireWriteBlock(pCircBuf, cbToWriteBuf, &pvChunk, &cbChunk);
    2058 
    2059                 if (cbChunk)
    2060                     memcpy(pvChunk, (uint8_t *)pvBuf + cbWrittenBuf, cbChunk);
    2061 
    2062                 RTCircBufReleaseWriteBlock(pCircBuf, cbChunk);
    2063 
    2064                 cbWrittenBuf += (uint32_t)cbChunk;
    2065                 Assert(cbWrittenBuf <= cbBuf);
    2066 
    2067                 Assert(cbToWriteBuf >= cbChunk);
    2068                 cbToWriteBuf -= (uint32_t)cbChunk;
     2033                PRTCIRCBUF pCircBuf   = pMixStream->pCircBuf;
     2034                size_t     offWritten = 0;
     2035                while (offWritten < cbToWrite)
     2036                {
     2037                    void  *pvChunk = NULL;
     2038                    size_t cbChunk = 0;
     2039                    RTCircBufAcquireWriteBlock(pCircBuf, cbToWrite - offWritten, &pvChunk, &cbChunk);
     2040
     2041                    memcpy(pvChunk, (uint8_t const *)pvBuf + offWritten, cbChunk);
     2042
     2043                    RTCircBufReleaseWriteBlock(pCircBuf, cbChunk);
     2044
     2045                    offWritten += cbChunk;
     2046                }
     2047                Assert(offWritten == cbToWrite);
     2048
     2049                pMixStream->tsLastReadWrittenNs = RTTimeNanoTS();
     2050                Log3Func(("[%s] Mixer stream '%s' -> cbWrittenBuf=%RU32\n", pSink->pszName, pMixStream->pszName, cbToWrite));
    20692051            }
    2070 
    2071             if (cbWrittenBuf) /* Update the mixer stream's last written time stamp. */
    2072                 pMixStream->tsLastReadWrittenNs = RTTimeNanoTS();
    2073 
    2074             Log3Func(("[%s] Mixer stream '%s' -> cbWrittenBuf=%RU32\n", pSink->pszName, pMixStream->pszName, cbWrittenBuf));
    2075         }
    2076     }
    2077 
    2078     Log3Func(("[%s] cbBuf=%RU32, cbToWriteMin=%RU32\n", pSink->pszName, cbBuf, cbToWriteMin));
    2079 
    2080     if (pcbWrittenMin)
    2081         *pcbWrittenMin = cbToWriteMin;
    2082 
    2083     return rc;
     2052        }
     2053    }
     2054
     2055    Log3Func(("[%s] cbBuf=%RU32, cbToWrite=%RU32\n", pSink->pszName, cbBuf, cbToWrite));
     2056
     2057    *pcbWritten = cbToWrite;
     2058    return VINF_SUCCESS;
    20842059}
    20852060
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r88292 r88298  
    471471 * Controls an audio stream.
    472472 *
    473  * @returns IPRT status code.
     473 * @returns VBox status code.
    474474 * @param   pThis               Pointer to driver instance.
    475475 * @param   pStream             Stream to control.
     
    579579 * If the stream has no backend available, VERR_NOT_FOUND is returned.
    580580 *
    581  * @returns IPRT status code.
     581 * @returns VBox status code.
    582582 * @param   pThis               Pointer to driver instance.
    583583 * @param   pStream             Stream to control.
     
    710710 * The actual re-initialization will happen at some later point in time.
    711711 *
    712  * @returns IPRT status code.
     712 * @returns VBox status code.
    713713 * @param   pThis               Pointer to driver instance.
    714714 */
     
    738738
    739739/**
    740  * Re-initializes an audio stream with its existing host and guest stream configuration.
    741  * This might be the case if the backend told us we need to re-initialize because something
    742  * on the host side has changed.
    743  *
    744  * Note: Does not touch the stream's status flags.
    745  *
    746  * @returns IPRT status code.
     740 * Re-initializes an audio stream with its existing host and guest stream
     741 * configuration.
     742 *
     743 * This might be the case if the backend told us we need to re-initialize
     744 * because something on the host side has changed.
     745 *
     746 * @note    Does not touch the stream's status flags.
     747 *
     748 * @returns VBox status code.
    747749 * @param   pThis               Pointer to driver instance.
    748750 * @param   pStream             Stream to re-initialize.
     
    11401142 * does the actual mixing between the guest <-> host mixing buffers.
    11411143 *
    1142  * @returns IPRT status code.
     1144 * @returns VBox status code.
    11431145 * @param   pThis               Pointer to driver instance.
    11441146 * @param   pStream             Stream to iterate.
     
    15161518 * Captures non-interleaved input from a host stream.
    15171519 *
    1518  * @returns IPRT status code.
     1520 * @returns VBox status code.
    15191521 * @param   pThis               Driver instance.
    15201522 * @param   pStream             Stream to capture from.
     
    16201622 * Needed for e.g. the VRDP audio backend (in Main).
    16211623 *
    1622  * @returns IPRT status code.
     1624 * @returns VBox status code.
    16231625 * @param   pThis               Driver instance.
    16241626 * @param   pStream             Stream to capture from.
     
    19351937 * @note Must not hold the driver's critical section!
    19361938 *
    1937  * @returns IPRT status code.
     1939 * @returns VBox status code.
    19381940 * @param   pThis               Driver instance to be called.
    19391941 * @param   fLog                Whether to print the enumerated device to the release log or not.
     
    20122014{
    20132015    LogFlowFuncEnter();
    2014     AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    2015 
     2016
     2017    /*
     2018     * Check the function pointers, make sure the ones we define as
     2019     * mandatory are present.
     2020     */
     2021    PPDMIHOSTAUDIO pHostDrvAudio = pThis->pHostDrvAudio;
     2022    AssertPtrReturn(pHostDrvAudio, VERR_INVALID_POINTER);
     2023    AssertPtrReturn(pHostDrvAudio->pfnInit, VERR_INVALID_POINTER);
     2024    AssertPtrNullReturn(pHostDrvAudio->pfnShutdown, VERR_INVALID_POINTER);
     2025    AssertPtrReturn(pHostDrvAudio->pfnGetConfig, VERR_INVALID_POINTER);
     2026    AssertPtrNullReturn(pHostDrvAudio->pfnGetDevices, VERR_INVALID_POINTER);
     2027    AssertPtrNullReturn(pHostDrvAudio->pfnGetStatus, VERR_INVALID_POINTER);
     2028    AssertPtrNullReturn(pHostDrvAudio->pfnSetCallback, VERR_INVALID_POINTER);
     2029    AssertPtrReturn(pHostDrvAudio->pfnStreamCreate, VERR_INVALID_POINTER);
     2030    AssertPtrReturn(pHostDrvAudio->pfnStreamDestroy, VERR_INVALID_POINTER);
     2031    AssertPtrReturn(pHostDrvAudio->pfnStreamControl, VERR_INVALID_POINTER);
     2032    AssertPtrReturn(pHostDrvAudio->pfnStreamGetReadable, VERR_INVALID_POINTER);
     2033    AssertPtrReturn(pHostDrvAudio->pfnStreamGetWritable, VERR_INVALID_POINTER);
     2034    AssertPtrNullReturn(pHostDrvAudio->pfnStreamGetPending, VERR_INVALID_POINTER);
     2035    AssertPtrReturn(pHostDrvAudio->pfnStreamGetStatus, VERR_INVALID_POINTER);
     2036    AssertPtrReturn(pHostDrvAudio->pfnStreamIterate, VERR_INVALID_POINTER);
     2037    AssertPtrNullReturn(pHostDrvAudio->pfnStreamPlayBegin, VERR_INVALID_POINTER);
     2038    AssertPtrReturn(pHostDrvAudio->pfnStreamPlay, VERR_INVALID_POINTER);
     2039    AssertPtrNullReturn(pHostDrvAudio->pfnStreamPlayEnd, VERR_INVALID_POINTER);
     2040    AssertPtrNullReturn(pHostDrvAudio->pfnStreamCaptureBegin, VERR_INVALID_POINTER);
     2041    AssertPtrReturn(pHostDrvAudio->pfnStreamCapture, VERR_INVALID_POINTER);
     2042    AssertPtrNullReturn(pHostDrvAudio->pfnStreamCaptureEnd, VERR_INVALID_POINTER);
     2043
     2044    /*
     2045     * Call the init method.
     2046     */
     2047    /** @todo r=bird: This is superfluous.  This duplicates the driver
     2048     *        constructor code.  Just get rid of it!! */
    20162049    AssertPtr(pThis->pHostDrvAudio);
    20172050    int rc = pThis->pHostDrvAudio->pfnInit(pThis->pHostDrvAudio);
     
    20372070    LogFlowFunc(("cStreamsFreeIn=%RU8, cStreamsFreeOut=%RU8\n", pThis->In.cStreamsFree, pThis->Out.cStreamsFree));
    20382071
    2039     LogRel2(("Audio: Host driver '%s' supports %RU32 input streams and %RU32 output streams at once\n",
    2040              pThis->szName,
    2041              /* Clamp for logging. Unlimited streams are defined by UINT32_MAX. */
    2042              RT_MIN(64, pThis->In.cStreamsFree), RT_MIN(64, pThis->Out.cStreamsFree)));
     2072    LogRel2(("Audio: Host driver '%s' supports %RU32 input streams and %RU32 output streams at once.\n",
     2073             pThis->szName, pThis->In.cStreamsFree, pThis->Out.cStreamsFree));
    20432074
    20442075#ifdef VBOX_WITH_AUDIO_ENUM
     
    20892120        PPDMAUDIOSTREAM pStream;
    20902121        RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry)
     2122        {
    20912123            drvAudioStreamControlInternal(pThis, pStream, enmCmd);
     2124        }
    20922125    }
    20932126
     
    24532486 * Worker for drvAudioStreamCreate that initializes the audio stream.
    24542487 *
    2455  * @returns IPRT status code.
     2488 * @returns VBox status code.
    24562489 * @param   pThis               Pointer to driver instance.
    24572490 * @param   pStream             Stream to initialize.
     
    30903123
    30913124/**
    3092  * @interface_method_impl{PDMIAUDIOCONNECTOR,pfnStreamDestroy}
    3093  */
    3094 static DECLCALLBACK(int) drvAudioStreamDestroy(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream)
    3095 {
    3096     PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
    3097     AssertPtr(pThis);
    3098 
    3099     if (!pStream)
    3100         return VINF_SUCCESS;
    3101     AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    3102     Assert(pStream->uMagic == PDMAUDIOSTREAM_MAGIC);
    3103 
    3104     int rc = RTCritSectEnter(&pThis->CritSect);
    3105     AssertRCReturn(rc, rc);
    3106 
    3107     LogRel2(("Audio: Destroying stream '%s'\n", pStream->szName));
    3108 
    3109     LogFlowFunc(("[%s] cRefs=%RU32\n", pStream->szName, pStream->cRefs));
    3110     if (pStream->cRefs <= 1)
    3111     {
    3112         rc = drvAudioStreamUninitInternal(pThis, pStream);
    3113         if (RT_SUCCESS(rc))
    3114         {
    3115             if (pStream->enmDir == PDMAUDIODIR_IN)
    3116                 pThis->In.cStreamsFree++;
    3117             else /* Out */
    3118                 pThis->Out.cStreamsFree++;
    3119 
    3120             RTListNodeRemove(&pStream->ListEntry);
    3121 
    3122             drvAudioStreamFree(pStream);
    3123             pStream = NULL;
    3124         }
    3125         else
    3126             LogRel(("Audio: Uninitializing stream '%s' failed with %Rrc\n", pStream->szName, rc));
    3127     }
    3128     else
    3129         rc = VERR_WRONG_ORDER;
    3130 
    3131     RTCritSectLeave(&pThis->CritSect);
    3132     LogFlowFuncLeaveRC(rc);
    3133     return rc;
    3134 }
    3135 
    3136 /**
    31373125 * Calls the backend to give it the chance to destroy its part of the audio stream.
    31383126 *
    3139  * @returns IPRT status code.
     3127 * Called from drvAudioPowerOff, drvAudioStreamUninitInternal and
     3128 * drvAudioStreamReInitInternal.
     3129 *
     3130 * @returns VBox status code.
    31403131 * @param   pThis               Pointer to driver instance.
    31413132 * @param   pStream             Audio stream destruct backend for.
     
    31703161
    31713162/**
    3172  * Uninitializes an audio stream.
    3173  *
    3174  * @returns IPRT status code.
     3163 * Uninitializes an audio stream - worker for drvAudioStreamDestroy,
     3164 * drvAudioDestruct and drvAudioStreamCreate.
     3165 *
     3166 * @returns VBox status code.
    31753167 * @param   pThis               Pointer to driver instance.
    31763168 * @param   pStream             Pointer to audio stream to uninitialize.
     3169 *
     3170 * @note    Caller owns the critical section.
    31773171 */
    31783172static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream)
     
    32263220        }
    32273221    }
    3228     else if (pStream->enmDir == PDMAUDIODIR_OUT)
    3229     {
     3222    else
     3223    {
     3224        Assert(pStream->enmDir == PDMAUDIODIR_OUT);
    32303225#ifdef VBOX_WITH_STATISTICS
    32313226        PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pStream->Out.Stats.TotalFramesPlayed);
     
    32433238        }
    32443239    }
     3240
     3241    LogFlowFunc(("Returning %Rrc\n", rc));
     3242    return rc;
     3243}
     3244
     3245/**
     3246 * @interface_method_impl{PDMIAUDIOCONNECTOR,pfnStreamDestroy}
     3247 */
     3248static DECLCALLBACK(int) drvAudioStreamDestroy(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream)
     3249{
     3250    PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
     3251    AssertPtr(pThis);
     3252
     3253    if (!pStream)
     3254        return VINF_SUCCESS;
     3255    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
     3256    Assert(pStream->uMagic == PDMAUDIOSTREAM_MAGIC);
     3257
     3258    int rc = RTCritSectEnter(&pThis->CritSect);
     3259    AssertRCReturn(rc, rc);
     3260
     3261    LogRel2(("Audio: Destroying stream '%s'\n", pStream->szName));
     3262
     3263    LogFlowFunc(("[%s] cRefs=%RU32\n", pStream->szName, pStream->cRefs));
     3264    AssertMsg(pStream->cRefs <= 1, ("%u %s\n", pStream->cRefs, pStream->szName));
     3265    if (pStream->cRefs <= 1)
     3266    {
     3267        rc = drvAudioStreamUninitInternal(pThis, pStream);
     3268        if (RT_SUCCESS(rc))
     3269        {
     3270            if (pStream->enmDir == PDMAUDIODIR_IN)
     3271                pThis->In.cStreamsFree++;
     3272            else /* Out */
     3273                pThis->Out.cStreamsFree++;
     3274
     3275            RTListNodeRemove(&pStream->ListEntry);
     3276
     3277            drvAudioStreamFree(pStream);
     3278            pStream = NULL;
     3279        }
     3280        else
     3281            LogRel(("Audio: Uninitializing stream '%s' failed with %Rrc\n", pStream->szName, rc));
     3282    }
    32453283    else
    3246         AssertFailed();
    3247 
    3248     LogFlowFunc(("Returning %Rrc\n", rc));
     3284        rc = VERR_WRONG_ORDER;
     3285
     3286    RTCritSectLeave(&pThis->CritSect);
     3287    LogFlowFuncLeaveRC(rc);
    32493288    return rc;
    32503289}
     
    32873326    LogFlowFuncEnter();
    32883327
    3289     if (!pThis->pHostDrvAudio) /* If not lower driver is configured, bail out. */
    3290         return;
    3291 
    3292     /* Just destroy the host stream on the backend side.
    3293      * The rest will either be destructed by the device emulation or
    3294      * in drvAudioDestruct(). */
    3295     PPDMAUDIOSTREAM pStream;
    3296     RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry)
    3297     {
    3298         drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
    3299         drvAudioStreamDestroyInternalBackend(pThis, pStream);
    3300     }
    3301 
    3302     /*
    3303      * Last call for the driver below us.
    3304      * Let it know that we reached end of life.
    3305      */
    3306     if (pThis->pHostDrvAudio->pfnShutdown)
    3307         pThis->pHostDrvAudio->pfnShutdown(pThis->pHostDrvAudio);
    3308 
    3309     pThis->pHostDrvAudio = NULL;
     3328    /** @todo locking?   */
     3329    if (pThis->pHostDrvAudio) /* If not lower driver is configured, bail out. */
     3330    {
     3331        /*
     3332         * Just destroy the host stream on the backend side.
     3333         * The rest will either be destructed by the device emulation or
     3334         * in drvAudioDestruct().
     3335         */
     3336        PPDMAUDIOSTREAM pStream;
     3337        RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry)
     3338        {
     3339            drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE);
     3340            drvAudioStreamDestroyInternalBackend(pThis, pStream);
     3341        }
     3342
     3343        /*
     3344         * Last call for the driver below us.
     3345         * Let it know that we reached end of life.
     3346         */
     3347        if (pThis->pHostDrvAudio->pfnShutdown)
     3348            pThis->pHostDrvAudio->pfnShutdown(pThis->pHostDrvAudio);
     3349
     3350        pThis->pHostDrvAudio = NULL;
     3351    }
    33103352
    33113353    LogFlowFuncLeave();
     
    33623404             */
    33633405            rc = drvAudioHostInit(pThis);
     3406            if (RT_FAILURE(rc))
     3407                pThis->pHostDrvAudio = NULL;
    33643408        }
    33653409        else
     
    33673411            LogRel(("Audio: Failed to query interface for underlying host driver '%s'\n", pThis->szName));
    33683412            rc = PDMDRV_SET_ERROR(pThis->pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW,
    3369                                   N_("Host audio backend missing or invalid"));
     3413                                  N_("The host audio driver does not implement PDMIHOSTAUDIO!"));
    33703414        }
    33713415    }
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