VirtualBox

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


Ignore:
Timestamp:
Apr 22, 2021 8:32:12 AM (4 years ago)
Author:
vboxsync
Message:

Audio/SB16: Now also is using our internal software mixer.

File:
1 edited

Legend:

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

    r88561 r88645  
    9595typedef struct SB16DRIVERSTREAM
    9696{
    97     /** Associated PDM audio stream. */
    98     R3PTRTYPE(PPDMAUDIOSTREAM)         pStream;
     97    /** Associated mixer stream handle. */
     98    R3PTRTYPE(PAUDMIXSTREAM)        pMixStrm;
    9999    /** The stream's current configuration. */
    100100} SB16DRIVERSTREAM, *PSB16DRIVERSTREAM;
     
    206206    /** The base interface for LUN\#0. */
    207207    PDMIBASE            IBase;
     208
    208209    /** Output stream. */
    209     SB16STREAM          Out;
     210    SB16STREAM             StreamOut;
     211    /** The device's software mixer. */
     212    R3PTRTYPE(PAUDIOMIXER) pMixer;
     213    /** Audio sink for PCM output. */
     214    R3PTRTYPE(PAUDMIXSINK) pSinkOut;
    210215
    211216    /** The timer for pumping data thru the attached LUN drivers. */
     
    232237} SB16STATE;
    233238
    234 
    235239/*********************************************************************************************************************************
    236240*   Internal Functions                                                                                                           *
    237241*********************************************************************************************************************************/
    238242static int  sb16CheckAndReOpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis);
    239 static int  sb16OpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg);
    240 static void sb16CloseOut(PSB16STATE pThis);
     243static int  sb16StreamOpen(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream, PPDMAUDIOSTREAMCFG pCfg);
     244static void sb16StreamClose(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream);
    241245static void sb16TimerMaybeStart(PPDMDEVINS pDevIns, PSB16STATE pThis);
    242246static void sb16TimerMaybeStop(PSB16STATE pThis);
     
    273277    PDMDevHlpDMASetDREQ(pThis->pDevInsR3, dma, hold);
    274278
    275     PSB16DRIVER pDrv;
    276     RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    277     {
    278         if (!pDrv->Out.pStream)
    279             continue;
    280 
    281         int rc2 = pDrv->pConnector->pfnStreamControl(pDrv->pConnector, pDrv->Out.pStream,
    282                                                      hold == 1 ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE);
    283         LogFlowFunc(("%s: rc=%Rrc\n", pDrv->Out.pStream->szName, rc2)); NOREF(rc2);
    284     }
     279    int rc2 = AudioMixerSinkCtl(pThis->pSinkOut,
     280                                hold == 1 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE);
     281    AssertRC(rc2);
    285282
    286283    if (hold)
     
    895892}
    896893
    897 static void sb16CmdResetLegacy(PSB16STATE pThis)
     894static void sb16CmdResetLegacy(PPDMDEVINS pDevIns, PSB16STATE pThis)
    898895{
    899896    LogFlowFuncEnter();
     
    905902
    906903    /* At the moment we only have one stream, the output stream. */
    907     PPDMAUDIOSTREAMCFG pCfg = &pThis->Out.Cfg;
    908 
    909     pCfg->enmDir          = PDMAUDIODIR_OUT;
    910     pCfg->u.enmDst        = PDMAUDIOPLAYBACKDST_FRONT;
    911     pCfg->enmLayout       = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
    912     PDMAudioPropsInit(&pCfg->Props, 1 /*8-bit*/, false /*fSigned*/, 1 /*mono*/, pThis->freq);
    913 
    914     AssertCompile(sizeof(pCfg->szName) >= sizeof("Output"));
    915     memcpy(pCfg->szName, "Output", sizeof("Output"));
    916 
    917     sb16CloseOut(pThis);
     904    PSB16STREAM pStream = &pThis->StreamOut;
     905
     906    pStream->Cfg.enmDir    = PDMAUDIODIR_OUT;
     907    pStream->Cfg.u.enmDst  = PDMAUDIOPLAYBACKDST_FRONT;
     908    pStream->Cfg.enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
     909
     910    PDMAudioPropsInit(&pStream->Cfg.Props, 1 /* 8-bit */, false /* fSigned */, 1 /* Mono */, pThis->freq);
     911    RTStrCopy(pStream->Cfg.szName, sizeof(pStream->Cfg.szName), "Output");
     912
     913    sb16StreamClose(pDevIns, pThis, pStream);
    918914}
    919915
     
    943939
    944940    sb16Control(pDevIns, pThis, 0);
    945     sb16CmdResetLegacy(pThis);
     941    sb16CmdResetLegacy(pDevIns, pThis);
    946942}
    947943
     
    11921188    }
    11931189
    1194     PSB16DRIVER pDrv;
    1195     RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    1196     {
    1197         PPDMAUDIOSTREAM pStream = pDrv->Out.pStream;
    1198         if (pStream)
    1199         {
    1200             int rc2 = pDrv->pConnector->pfnStreamSetVolume(pDrv->pConnector, pStream, &VolCombined);
    1201             AssertRC(rc2);
    1202         }
    1203     }
     1190    int rc2 = AudioMixerSinkSetVolume(pThis->pSinkOut, &VolCombined);
     1191    AssertRC(rc2);
    12041192}
    12051193
     
    15171505 * Worker for sb16DMARead.
    15181506 */
    1519 static int sb16WriteAudio(PSB16STATE pThis, int nchan, uint32_t dma_pos, uint32_t dma_len, int len)
    1520 {
    1521     uint8_t  abBuf[_4K]; /** @todo Have a buffer on the heap. */
    1522     uint32_t cbToWrite = len;
     1507static int sb16WriteAudio(PSB16STATE pThis, int nchan, uint32_t dma_pos, uint32_t dma_len, uint32_t len, uint32_t *pcbWritten)
     1508{
     1509    uint8_t abBuf[_4K]; /** @todo Have a buffer on the heap. */
     1510
     1511    uint32_t cbToWrite      = len;
    15231512    uint32_t cbWrittenTotal = 0;
    15241513
     1514    PAUDMIXSINK pDstMixSink = pThis->pSinkOut;
     1515    AssertPtrReturn(pDstMixSink, VERR_INVALID_POINTER);
     1516
     1517    int rc = VINF_SUCCESS;
     1518
    15251519    while (cbToWrite)
    15261520    {
    15271521        uint32_t cbToRead = RT_MIN(dma_len - dma_pos, cbToWrite);
    1528         if (cbToRead > sizeof(abBuf))
    1529             cbToRead = sizeof(abBuf);
     1522        if (cbToRead > (int)sizeof(abBuf)) /** @todo BUGBUG Clean this up. */
     1523            cbToRead = (int)sizeof(abBuf);
    15301524
    15311525        uint32_t cbRead = 0;
    1532         int rc2 = PDMDevHlpDMAReadMemory(pThis->pDevInsR3, nchan, abBuf, dma_pos, cbToRead, &cbRead);
    1533         AssertMsgRC(rc2, (" from DMA failed: %Rrc\n", rc2));
     1526        rc = PDMDevHlpDMAReadMemory(pThis->pDevInsR3, nchan, abBuf, dma_pos, cbToRead, &cbRead);
     1527        AssertMsgRCReturn(rc, ("Reading from DMA failed, rc=%Rrc\n", rc), rc);
    15341528
    15351529#ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA
     
    15471541         */
    15481542        uint32_t cbWritten = 0;
    1549 
    1550         /* Just multiplex the output to the connected backends.
    1551          * No need to utilize the virtual mixer here (yet). */
    1552         PSB16DRIVER pDrv;
    1553         RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    1554         {
    1555             if (   pDrv->Out.pStream
    1556                 && PDMAudioStrmStatusCanWrite(pDrv->pConnector->pfnStreamGetStatus(pDrv->pConnector, pDrv->Out.pStream)))
    1557             {
    1558                 uint32_t cbWrittenToStream = 0;
    1559                 rc2 = pDrv->pConnector->pfnStreamWrite(pDrv->pConnector, pDrv->Out.pStream, abBuf, cbRead, &cbWrittenToStream);
    1560 
    1561                 LogFlowFunc(("\tLUN#%RU8: rc=%Rrc, cbWrittenToStream=%RU32\n", pDrv->uLUN, rc2, cbWrittenToStream));
    1562             }
    1563         }
    1564 
    1565         cbWritten = cbRead; /* Always report everything written, as the backends need to keep up themselves. */
    1566 
    1567         LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbWritten=%RU32, cbLeft=%RU32\n",
    1568                      cbToRead, cbToWrite, cbWritten, cbToWrite - cbWrittenTotal));
    1569 
    1570         if (!cbWritten)
     1543        rc = AudioMixerSinkWrite(pDstMixSink, AUDMIXOP_COPY, abBuf, cbRead, &cbWritten);
     1544        if (   !cbWritten /* Nothing written? */
     1545            || RT_FAILURE(rc))
    15711546            break;
    15721547
     
    15771552    }
    15781553
    1579     return cbWrittenTotal;
     1554    if (pcbWritten)
     1555        *pcbWritten = cbWrittenTotal;
     1556
     1557    return rc;
    15801558}
    15811559
     
    15891567    RT_NOREF(pDevIns);
    15901568    PSB16STATE pThis = (PSB16STATE)pvUser;
    1591     int till, copy, written, free;
     1569    int till, copy, free;
    15921570
    15931571    if (pThis->block_size <= 0)
     
    16221600    }
    16231601
    1624     written = sb16WriteAudio(pThis, uChannel, off, cb, copy);
    1625     off = (off + written) % cb;
    1626     pThis->left_till_irq -= written;
     1602    uint32_t cbWritten;
     1603    int rc = sb16WriteAudio(pThis, uChannel, off, cb, copy, &cbWritten);
     1604    AssertRC(rc);
     1605
     1606    /** @todo Convert the rest to uin32_t / size_t. */
     1607    off = (off + (int)cbWritten) % cb;
     1608    pThis->left_till_irq -= (int)cbWritten;
    16271609
    16281610    if (pThis->left_till_irq <= 0)
     
    16371619    }
    16381620
    1639     Log3Func(("pos %d/%d free %5d till %5d copy %5d written %5d block_size %5d\n",
    1640               off, cb, free, pThis->left_till_irq, copy, written, pThis->block_size));
     1621    Log3Func(("pos %d/%d, free=%5d, till=%5d, copy=%5d, written=%RU32, block_size=%5d\n",
     1622              off, cb, free, pThis->left_till_irq, copy, cbWritten, pThis->block_size));
    16411623
    16421624    while (pThis->left_till_irq <= 0)
     
    16911673
    16921674    uint64_t cTicksNow     = PDMDevHlpTimerGet(pDevIns, hTimer);
    1693     bool     fIsPlaying    = false; /* Whether one or more streams are still playing. */
    1694     bool     fDoTransfer   = false;
    16951675
    16961676    pThis->tsTimerIO = cTicksNow;
    16971677
    1698     PSB16DRIVER pDrv;
    1699     RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    1700     {
    1701         PPDMAUDIOSTREAM     const pStream = pDrv->Out.pStream;
    1702         PPDMIAUDIOCONNECTOR const pConn   = pDrv->pConnector;
    1703         if (pStream && pConn)
    1704         {
    1705             int rc2 = pConn->pfnStreamIterate(pConn, pStream);
    1706             if (RT_SUCCESS(rc2))
    1707             {
    1708                 rc2 = pConn->pfnStreamPlay(pConn, pStream, NULL /* cPlayed */);
    1709                 if (RT_FAILURE(rc2))
    1710                 {
    1711                     LogFlowFunc(("%s: Failed playing stream, rc=%Rrc\n", pStream->szName, rc2));
    1712                     continue;
    1713                 }
    1714 
    1715                 /* Only do the next DMA transfer if we're able to write the remaining data block. */
    1716                 fDoTransfer = pConn->pfnStreamGetWritable(pConn, pStream) > (unsigned)pThis->left_till_irq;
    1717             }
    1718 
    1719             PDMAUDIOSTREAMSTS fStrmSts = pConn->pfnStreamGetStatus(pConn, pStream);
    1720             fIsPlaying |= RT_BOOL(fStrmSts & (PDMAUDIOSTREAMSTS_FLAGS_ENABLED | PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE));
    1721         }
    1722     }
     1678    int rc2 = AudioMixerSinkUpdate(pThis->pSinkOut);
     1679    AssertRC(rc2);
    17231680
    17241681    bool fTimerActive = ASMAtomicReadBool(&pThis->fTimerActive);
    1725     bool fArmTimer    = fTimerActive || fIsPlaying;
    1726     LogFlowFunc(("fTimerActive=%RTbool, fIsPlaying=%RTbool\n", fTimerActive, fIsPlaying));
    1727 
    1728     if (fDoTransfer)
    1729     {
    1730         /* Schedule the next transfer. */
    1731         PDMDevHlpDMASchedule(pDevIns);
    1732 
    1733         /* Arm the timer at least one more time. */
    1734         fArmTimer = true;
    1735     }
     1682    bool fArmTimer    = fTimerActive;
     1683
     1684    /* Schedule the next transfer. */
     1685    PDMDevHlpDMASchedule(pDevIns);
     1686
     1687    /* Arm the timer at least one more time. */
     1688    fArmTimer = true;
    17361689
    17371690    /*
     
    17531706
    17541707/**
    1755  * Creates the output PDM audio stream for a specific driver.
     1708 * Retrieves a specific driver stream of a SB16 driver.
     1709 *
     1710 * @returns Pointer to driver stream if found, or NULL if not found.
     1711 * @param   pDrv                Driver to retrieve driver stream for.
     1712 * @param   enmDir              Stream direction to retrieve.
     1713 * @param   dstSrc              Stream destination / source to retrieve.
     1714 */
     1715static PSB16DRIVERSTREAM sb16GetDrvStream(PSB16DRIVER pDrv, PDMAUDIODIR enmDir, PDMAUDIODSTSRCUNION dstSrc)
     1716{
     1717    PSB16DRIVERSTREAM pDrvStream = NULL;
     1718
     1719    if (enmDir == PDMAUDIODIR_IN)
     1720    {
     1721        return NULL; /** @todo Recording not implemented yet. */
     1722    }
     1723    else if (enmDir == PDMAUDIODIR_OUT)
     1724    {
     1725        LogFunc(("enmDst=%RU32\n", dstSrc.enmDst));
     1726
     1727        switch (dstSrc.enmDst)
     1728        {
     1729            case PDMAUDIOPLAYBACKDST_FRONT:
     1730                pDrvStream = &pDrv->Out;
     1731                break;
     1732            default:
     1733                AssertFailed();
     1734                break;
     1735        }
     1736    }
     1737    else
     1738        AssertFailed();
     1739
     1740    return pDrvStream;
     1741}
     1742
     1743/**
     1744 * Adds a driver stream to a specific mixer sink.
    17561745 *
    17571746 * @returns VBox status code.
    1758  * @param   pCfg                Stream configuration to use.
    1759  * @param   pDrv                Driver stream to create PDM stream for.
    1760  */
    1761 static int sb16CreateDrvStream(PPDMAUDIOSTREAMCFG pCfg, PSB16DRIVER pDrv)
    1762 {
    1763     AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER);
    1764     Assert(AudioHlpStreamCfgIsValid(pCfg));
    1765 
    1766     PPDMAUDIOSTREAMCFG pCfgHost = PDMAudioStrmCfgDup(pCfg);
    1767     if (!pCfgHost)
     1747 * @param   pDevIns     The device instance.
     1748 * @param   pMixSink    Mixer sink to add driver stream to.
     1749 * @param   pCfg        Stream configuration to use.
     1750 * @param   pDrv        Driver stream to add.
     1751 */
     1752static int sb16AddDrvStream(PPDMDEVINS pDevIns, PAUDMIXSINK pMixSink, PPDMAUDIOSTREAMCFG pCfg, PSB16DRIVER pDrv)
     1753{
     1754    AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_NOT_IMPLEMENTED); /* We don't support recording for SB16 so far. */
     1755
     1756    PPDMAUDIOSTREAMCFG pStreamCfg = PDMAudioStrmCfgDup(pCfg);
     1757    if (!pStreamCfg)
    17681758        return VERR_NO_MEMORY;
    17691759
    1770     LogFunc(("[LUN#%RU8] %s\n", pDrv->uLUN, pCfgHost->szName));
    1771 
    1772     AssertMsg(pDrv->Out.pStream == NULL, ("[LUN#%RU8] Driver stream already present when it must not\n", pDrv->uLUN));
    1773 
    1774     /* Disable pre-buffering for SB16; not needed for that bit of data. */
    1775     pCfgHost->Backend.cFramesPreBuffering = 0;
    1776 
    1777     int rc = pDrv->pConnector->pfnStreamCreate(pDrv->pConnector, 0 /*fFlags*/, pCfgHost, pCfg /* pCfgGuest */, &pDrv->Out.pStream);
    1778     if (RT_SUCCESS(rc))
    1779     {
    1780         pDrv->pConnector->pfnStreamRetain(pDrv->pConnector, pDrv->Out.pStream);
    1781         LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc));
    1782     }
    1783 
    1784     PDMAudioStrmCfgFree(pCfgHost);
    1785 
     1760    if (!RTStrPrintf(pStreamCfg->szName, sizeof(pStreamCfg->szName), "%s", pCfg->szName))
     1761    {
     1762        PDMAudioStrmCfgFree(pStreamCfg);
     1763        return VERR_BUFFER_OVERFLOW;
     1764    }
     1765
     1766    LogFunc(("[LUN#%RU8] %s\n", pDrv->uLUN, pStreamCfg->szName));
     1767
     1768    int rc;
     1769
     1770    PSB16DRIVERSTREAM pDrvStream = sb16GetDrvStream(pDrv, pStreamCfg->enmDir, pStreamCfg->u);
     1771    if (pDrvStream)
     1772    {
     1773        AssertMsg(pDrvStream->pMixStrm == NULL, ("[LUN#%RU8] Driver stream already present when it must not\n", pDrv->uLUN));
     1774
     1775        PAUDMIXSTREAM pMixStrm;
     1776        rc = AudioMixerSinkCreateStream(pMixSink, pDrv->pConnector, pStreamCfg, 0 /* fFlags */, pDevIns, &pMixStrm);
     1777        LogFlowFunc(("LUN#%RU8: Created stream \"%s\" for sink, rc=%Rrc\n", pDrv->uLUN, pStreamCfg->szName, rc));
     1778        if (RT_SUCCESS(rc))
     1779        {
     1780            rc = AudioMixerSinkAddStream(pMixSink, pMixStrm);
     1781            LogFlowFunc(("LUN#%RU8: Added stream \"%s\" to sink, rc=%Rrc\n", pDrv->uLUN, pStreamCfg->szName, rc));
     1782
     1783            if (RT_SUCCESS(rc))
     1784            {
     1785                pDrvStream->pMixStrm = pMixStrm;
     1786            }
     1787            else
     1788                AudioMixerStreamDestroy(pMixStrm, pDevIns);
     1789        }
     1790    }
     1791    else
     1792        rc = VERR_INVALID_PARAMETER;
     1793
     1794    PDMAudioStrmCfgFree(pStreamCfg);
     1795
     1796    LogFlowFuncLeaveRC(rc);
    17861797    return rc;
    17871798}
    17881799
    17891800/**
    1790  * Destroys the output PDM audio stream of a specific driver.
     1801 * Adds all current driver streams to a specific mixer sink.
    17911802 *
    1792  * @param   pDrv                Driver stream to destroy PDM stream for.
    1793  */
    1794 static void sb16DestroyDrvStreamOut(PSB16DRIVER pDrv)
    1795 {
    1796     AssertPtr(pDrv);
    1797 
    1798     if (pDrv->Out.pStream)
    1799     {
    1800         pDrv->pConnector->pfnStreamRelease(pDrv->pConnector, pDrv->Out.pStream);
    1801 
    1802         int rc2 = pDrv->pConnector->pfnStreamControl(pDrv->pConnector, pDrv->Out.pStream, PDMAUDIOSTREAMCMD_DISABLE);
    1803         AssertRC(rc2);
    1804 
    1805         rc2 = pDrv->pConnector->pfnStreamDestroy(pDrv->pConnector, pDrv->Out.pStream);
    1806         AssertRC(rc2);
    1807 
    1808         pDrv->Out.pStream = NULL;
    1809     }
     1803 * @returns VBox status code.
     1804 * @param   pDevIns     The device instance.
     1805 * @param   pThis       The SB16 state.
     1806 * @param   pMixSink    Mixer sink to add stream to.
     1807 * @param   pCfg        Stream configuration to use.
     1808 */
     1809static int sb16AddDrvStreams(PPDMDEVINS pDevIns, PSB16STATE pThis, PAUDMIXSINK pMixSink, PPDMAUDIOSTREAMCFG pCfg)
     1810{
     1811    AssertPtrReturn(pMixSink, VERR_INVALID_POINTER);
     1812
     1813    if (!AudioHlpStreamCfgIsValid(pCfg))
     1814        return VERR_INVALID_PARAMETER;
     1815
     1816    int rc = AudioMixerSinkSetFormat(pMixSink, &pCfg->Props);
     1817    if (RT_FAILURE(rc))
     1818        return rc;
     1819
     1820    PSB16DRIVER pDrv;
     1821    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
     1822    {
     1823        int rc2 = sb16AddDrvStream(pDevIns, pMixSink, pCfg, pDrv);
     1824        if (RT_FAILURE(rc2))
     1825            LogFunc(("Attaching stream failed with %Rrc\n", rc2));
     1826
     1827        /* Do not pass failure to rc here, as there might be drivers which aren't
     1828         * configured / ready yet. */
     1829    }
     1830
     1831    LogFlowFuncLeaveRC(rc);
     1832    return rc;
     1833}
     1834
     1835/**
     1836 * Removes a driver stream from a specific mixer sink.
     1837 *
     1838 * @param   pDevIns     The device instance.
     1839 * @param   pMixSink    Mixer sink to remove audio streams from.
     1840 * @param   enmDir      Stream direction to remove.
     1841 * @param   dstSrc      Stream destination / source to remove.
     1842 * @param   pDrv        Driver stream to remove.
     1843 */
     1844static void sb16RemoveDrvStream(PPDMDEVINS pDevIns, PAUDMIXSINK pMixSink, PDMAUDIODIR enmDir,
     1845                                PDMAUDIODSTSRCUNION dstSrc, PSB16DRIVER pDrv)
     1846{
     1847    PSB16DRIVERSTREAM pDrvStream = sb16GetDrvStream(pDrv, enmDir, dstSrc);
     1848    if (pDrvStream)
     1849    {
     1850        if (pDrvStream->pMixStrm)
     1851        {
     1852            LogFlowFunc(("[LUN#%RU8]\n", pDrv));
     1853
     1854            AudioMixerSinkRemoveStream(pMixSink, pDrvStream->pMixStrm);
     1855
     1856            AudioMixerStreamDestroy(pDrvStream->pMixStrm, pDevIns);
     1857            pDrvStream->pMixStrm = NULL;
     1858        }
     1859    }
     1860}
     1861
     1862/**
     1863 * Removes all driver streams from a specific mixer sink.
     1864 *
     1865 * @param   pDevIns     The device instance.
     1866 * @param   pThisCC     The SB16 state.
     1867 * @param   pMixSink    Mixer sink to remove audio streams from.
     1868 * @param   enmDir      Stream direction to remove.
     1869 * @param   dstSrc      Stream destination / source to remove.
     1870 */
     1871static void sb16RemoveDrvStreams(PPDMDEVINS pDevIns, PSB16STATE pThis, PAUDMIXSINK pMixSink,
     1872                                 PDMAUDIODIR enmDir, PDMAUDIODSTSRCUNION dstSrc)
     1873{
     1874    AssertPtrReturnVoid(pMixSink);
     1875
     1876    PSB16DRIVER pDrv;
     1877    RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
     1878        sb16RemoveDrvStream(pDevIns, pMixSink, enmDir, dstSrc, pDrv);
     1879}
     1880
     1881/**
     1882 * Adds a specific SB16 driver to the driver chain.
     1883 *
     1884 * @returns VBox status code.
     1885 * @param   pDevIns     The device instance.
     1886 * @param   pThis       The SB16 device state.
     1887 * @param   pDrv        The SB16 driver to add.
     1888 */
     1889static int sb16AddDrv(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16DRIVER pDrv)
     1890{
     1891    int rc = VINF_SUCCESS;
     1892
     1893    if (AudioHlpStreamCfgIsValid(&pThis->StreamOut.Cfg))
     1894        rc = sb16AddDrvStream(pDevIns, pThis->pSinkOut, &pThis->StreamOut.Cfg, pDrv);
     1895
     1896    return rc;
     1897}
     1898
     1899/**
     1900 * Removes a specific SB16 driver from the driver chain and destroys its
     1901 * associated streams.
     1902 *
     1903 * @param   pDevIns     The device instance.
     1904 * @param   pThis       The SB16 device state.
     1905 * @param   pDrv        SB16 driver to remove.
     1906 */
     1907static void sb16RemoveDrv(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16DRIVER pDrv)
     1908{
     1909    RT_NOREF(pDevIns);
     1910
     1911    /** @todo We only implement one single output (playback) stream at the moment. */
     1912
     1913    if (pDrv->Out.pMixStrm)
     1914    {
     1915        AudioMixerSinkRemoveStream(pThis->pSinkOut, pDrv->Out.pMixStrm);
     1916        AudioMixerStreamDestroy(pDrv->Out.pMixStrm, pDevIns);
     1917        pDrv->Out.pMixStrm = NULL;
     1918    }
     1919
     1920    RTListNodeRemove(&pDrv->Node);
    18101921}
    18111922
     
    18231934    int rc = VINF_SUCCESS;
    18241935
     1936    PSB16STREAM pStream = &pThis->StreamOut;
     1937
    18251938    if (pThis->freq > 0)
    18261939    {
     
    18301943        PDMAudioPropsInit(&Cfg.Props, pThis->fmt_bits / 8, pThis->fmt_signed != 0, 1 << pThis->fmt_stereo, pThis->freq);
    18311944
    1832         if (!PDMAudioStrmCfgMatchesProps(&Cfg, &pThis->Out.Cfg.Props))
     1945        if (!PDMAudioStrmCfgMatchesProps(&Cfg, &pStream->Cfg.Props))
    18331946        {
    18341947            Cfg.enmDir      = PDMAUDIODIR_OUT;
     
    18361949            Cfg.enmLayout   = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED;
    18371950
    1838             strcpy(Cfg.szName, "Output");
    1839 
    1840             sb16CloseOut(pThis);
    1841 
    1842             rc = sb16OpenOut(pDevIns, pThis, &Cfg);
     1951            RTStrCopy(Cfg.szName, sizeof(Cfg.szName), "Output");
     1952
     1953            sb16StreamClose(pDevIns, pThis, pStream);
     1954
     1955            rc = sb16StreamOpen(pDevIns, pThis, pStream, &Cfg);
    18431956            AssertRC(rc);
    18441957        }
    18451958    }
    18461959    else
    1847         sb16CloseOut(pThis);
     1960        sb16StreamClose(pDevIns, pThis, pStream);
    18481961
    18491962    LogFlowFuncLeaveRC(rc);
     
    18511964}
    18521965
    1853 static int sb16OpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg)
     1966/**
     1967 * Opens a SB16 stream with its current mixer settings.
     1968 *
     1969 * @returns VBox status code.
     1970 * @param   pDevIns     The device instance.
     1971 * @param   pThis       The SB16 device state.
     1972 * @param   pStream     The SB16 stream to open.
     1973 * @param   pCfg        Stream configuration to use for opening the stream.
     1974 *
     1975 * @note    This currently only supports the one and only output stream.
     1976 */
     1977static int sb16StreamOpen(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream, PPDMAUDIOSTREAMCFG pCfg)
    18541978{
    18551979    LogFlowFuncEnter();
    1856     AssertPtr(pThis);
    1857     AssertPtr(pCfg);
    18581980
    18591981    if (!AudioHlpStreamCfgIsValid(pCfg))
    18601982        return VERR_INVALID_PARAMETER;
    18611983
    1862     int rc = PDMAudioStrmCfgCopy(&pThis->Out.Cfg, pCfg);
     1984    /** @todo Implement mixer sink selection (and it's in/out + destination mapping) here once we add more streams. */
     1985    PAUDMIXSINK pMixerSink = pThis->pSinkOut;
     1986    AssertPtr(pMixerSink);
     1987
     1988    PDMAUDIODSTSRCUNION dstSrc;
     1989    dstSrc.enmDst = PDMAUDIOPLAYBACKDST_FRONT;
     1990
     1991    PDMAUDIODIR enmDir = PDMAUDIODIR_OUT;
     1992
     1993    int rc = PDMAudioStrmCfgCopy(&pStream->Cfg, pCfg);
    18631994    if (RT_SUCCESS(rc))
    18641995    {
    18651996        /* Set scheduling hint (if available). */
    18661997        if (pThis->cTicksTimerIOInterval)
    1867             pThis->Out.Cfg.Device.cMsSchedulingHint = 1000 /* ms */
    1868                                                     / (  PDMDevHlpTimerGetFreq(pDevIns, pThis->hTimerIO)
    1869                                                        / RT_MIN(pThis->cTicksTimerIOInterval, 1));
    1870 
    1871         PSB16DRIVER pDrv;
    1872         RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    1873         {
    1874             int rc2 = sb16CreateDrvStream(&pThis->Out.Cfg, pDrv);
    1875             if (RT_FAILURE(rc2))
    1876                 LogFunc(("Attaching stream failed with %Rrc\n", rc2));
    1877 
    1878             /* Do not pass failure to rc here, as there might be drivers which aren't
    1879              * configured / ready yet. */
    1880         }
    1881 
    1882         sb16UpdateVolume(pThis);
     1998            pStream->Cfg.Device.cMsSchedulingHint = 1000 /* ms */
     1999                                                  / (  PDMDevHlpTimerGetFreq(pDevIns, pThis->hTimerIO)
     2000                                                  / RT_MIN(pThis->cTicksTimerIOInterval, 1));
     2001
     2002        sb16RemoveDrvStreams(pDevIns, pThis, pMixerSink, enmDir, dstSrc);
     2003
     2004        rc = sb16AddDrvStreams(pDevIns, pThis, pMixerSink, &pStream->Cfg);
     2005        if (RT_SUCCESS(rc))
     2006            sb16UpdateVolume(pThis);
    18832007    }
    18842008
     
    18872011}
    18882012
    1889 static void sb16CloseOut(PSB16STATE pThis)
     2013/**
     2014 * Closes a SB16 stream.
     2015 *
     2016 * @param   pDevIns         The device instance.
     2017 * @param   pThis           SB16 state.
     2018 * @param   pStream         The SB16 stream to close.
     2019 */
     2020static void sb16StreamClose(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream)
    18902021{
    18912022    LogFlowFuncEnter();
    1892     AssertPtr(pThis);
    1893 
    1894     PSB16DRIVER pDrv;
    1895     RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    1896     {
    1897         sb16DestroyDrvStreamOut(pDrv);
    1898     }
     2023
     2024    /** @todo Implement mixer sink selection (and it's in/out + destination mapping) here once we add more streams. */
     2025    RT_NOREF(pStream);
     2026    PAUDMIXSINK pMixerSink = pThis->pSinkOut;
     2027    AssertPtr(pMixerSink);
     2028
     2029    PDMAUDIODSTSRCUNION dstSrc;
     2030    dstSrc.enmDst = PDMAUDIOPLAYBACKDST_FRONT;
     2031
     2032    PDMAUDIODIR enmDir = PDMAUDIODIR_OUT;
     2033
     2034    sb16RemoveDrvStreams(pDevIns, pThis, pMixerSink, enmDir, dstSrc);
    18992035
    19002036    LogFlowFuncLeave();
     
    22002336 *
    22012337 * @returns VBox status code.
    2202  * @param   pDrv        Driver to detach device from.
    2203  */
    2204 static int sb16DetachInternal(PSB16DRIVER pDrv)
    2205 {
    2206     sb16DestroyDrvStreamOut(pDrv);
    2207     RTListNodeRemove(&pDrv->Node);
    2208     LogFunc(("uLUN=%u\n", pDrv->uLUN));
     2338 * @param   pDevIns     The device instance.
     2339 * @param   pThis       The SB16 device state.
     2340 * @param   pDrv        Driver to detach from device.
     2341 * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
     2342 */
     2343static int sb16DetachInternal(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16DRIVER pDrv, uint32_t fFlags)
     2344{
     2345    RT_NOREF(fFlags);
     2346
     2347    /** @todo r=andy Any locking required here? */
     2348
     2349    sb16RemoveDrv(pDevIns, pThis, pDrv);
     2350
     2351    LogFunc(("uLUN=%u, fFlags=0x%x\n", pDrv->uLUN, fFlags));
    22092352    return VINF_SUCCESS;
    22102353}
     
    22182361
    22192362    LogFunc(("iLUN=%u, fFlags=0x%x\n", iLUN, fFlags));
     2363
     2364    /** @todo r=andy Any locking required here? */
    22202365
    22212366    PSB16DRIVER pDrv;
    22222367    int rc2 = sb16AttachInternal(pThis, iLUN, fFlags, &pDrv);
    22232368    if (RT_SUCCESS(rc2))
    2224         rc2 = sb16CreateDrvStream(&pThis->Out.Cfg, pDrv);
     2369        rc2 = sb16AddDrv(pDevIns, pThis, pDrv);
     2370
     2371    if (RT_FAILURE(rc2))
     2372        LogFunc(("Failed with %Rrc\n", rc2));
    22252373
    22262374    return VINF_SUCCESS;
     
    22422390        if (pDrv->uLUN == iLUN)
    22432391        {
    2244             int rc2 = sb16DetachInternal(pDrv);
     2392            int rc2 = sb16DetachInternal(pDevIns, pThis, pDrv, fFlags);
    22452393            if (RT_SUCCESS(rc2))
    22462394            {
     
    23032451    sb16SpeakerControl(pThis, 0);
    23042452    sb16Control(pDevIns, pThis, 0);
    2305     sb16CmdResetLegacy(pThis);
     2453    sb16CmdResetLegacy(pDevIns, pThis);
    23062454}
    23072455
     
    23172465    LogRel2(("SB16: Powering off ...\n"));
    23182466
    2319     PSB16DRIVER pDrv;
    2320     RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)
    2321     {
    2322         sb16DestroyDrvStreamOut(pDrv);
     2467    /*
     2468     * Destroy all streams.
     2469     */
     2470    sb16StreamClose(pDevIns, pThis, &pThis->StreamOut);
     2471
     2472    /*
     2473     * Destroy all sinks.
     2474     */
     2475    if (pThis->pSinkOut)
     2476    {
     2477        AudioMixerSinkDestroy(pThis->pSinkOut, pDevIns);
     2478        pThis->pSinkOut = NULL;
     2479    }
     2480
     2481    /** @todo Add removal + destruction of other streams here once we support them. */
     2482
     2483    /*
     2484     * Note: Destroy the mixer while powering off and *not* in sb16Destruct,
     2485     *       giving the mixer the chance to release any references held to
     2486     *       PDM audio streams it maintains.
     2487     */
     2488    if (pThis->pMixer)
     2489    {
     2490        AudioMixerDestroy(pThis->pMixer, pDevIns);
     2491        pThis->pMixer = NULL;
    23232492    }
    23242493}
     
    24112580    if (uTimerHz > 2048)
    24122581        return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: Max TimerHz value is 2048."));
     2582
     2583    /*
     2584     * Create internal software mixer.
     2585     * Must come before we do the device's mixer reset.
     2586     */
     2587    rc = AudioMixerCreate("SB16 Mixer", 0 /* uFlags */, &pThis->pMixer);
     2588    AssertRCReturn(rc, rc);
     2589
     2590    AssertRCReturn(rc, rc);
     2591    rc = AudioMixerCreateSink(pThis->pMixer, "PCM Output",
     2592                              AUDMIXSINKDIR_OUTPUT, pDevIns, &pThis->pSinkOut);
     2593    AssertRCReturn(rc, rc);
    24132594
    24142595    /*
     
    25012682    }
    25022683
    2503     sb16CmdResetLegacy(pThis);
     2684    sb16CmdResetLegacy(pDevIns, pThis);
    25042685
    25052686#ifdef VBOX_WITH_AUDIO_SB16_ONETIME_INIT
Note: See TracChangeset for help on using the changeset viewer.

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