VirtualBox

Changeset 88556 in vbox


Ignore:
Timestamp:
Apr 16, 2021 12:08:40 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143851
Message:

DrvHostAudioDSound: Restructured the stream control code. bugref:9890

File:
1 edited

Legend:

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

    r88555 r88556  
    227227*********************************************************************************************************************************/
    228228static HRESULT  directSoundPlayRestore(PDRVHOSTDSOUND pThis, LPDIRECTSOUNDBUFFER8 pDSB);
    229 static HRESULT  directSoundPlayStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS);
    230 static HRESULT  directSoundPlayStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fFlush);
    231 static HRESULT  directSoundCaptureStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fFlush);
     229static int      drvHostDSoundStreamStopPlayback(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fReset);
    232230
    233231static int      dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PDMAUDIOHOSTENUM pDevEnm, uint32_t fEnum);
    234232
    235 static int      dsoundStreamEnable(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fEnable);
    236233static void     dsoundUpdateStatusInternal(PDRVHOSTDSOUND pThis);
    237234
     
    15981595        if (pStreamDS->In.pDSCB)
    15991596        {
    1600             directSoundCaptureStop(pThis, pStreamDS, true /* fFlush */);
     1597            HRESULT hrc = IDirectSoundCaptureBuffer_Stop(pStreamDS->In.pDSCB);
     1598            if (FAILED(hrc))
     1599                LogFunc(("IDirectSoundCaptureBuffer_Stop failed: %Rhrc\n", hrc));
     1600
     1601            drvHostDSoundStreamReset(pThis, pStreamDS);
    16011602
    16021603            IDirectSoundCaptureBuffer8_Release(pStreamDS->In.pDSCB);
     
    16111612        if (pStreamDS->Out.pDSB)
    16121613        {
    1613             directSoundPlayStop(pThis, pStreamDS, true /* fFlush */);
     1614            drvHostDSoundStreamStopPlayback(pThis, pStreamDS, true /*fReset*/);
    16141615
    16151616            IDirectSoundBuffer8_Release(pStreamDS->Out.pDSB);
     
    16261627
    16271628/**
    1628  * Enables or disables a stream.
     1629 * Worker for drvHostDSoundHA_StreamEnable and drvHostDSoundHA_StreamResume.
    16291630 *
    1630  * @return  VBox status code.
    1631  * @param   pThis               Host audio driver instance.
    1632  * @param   pStreamDS           Stream to enable / disable.
    1633  * @param   fEnable             Whether to enable or disable the stream.
    1634  */
    1635 static int dsoundStreamEnable(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fEnable)
    1636 {
    1637     RT_NOREF(pThis);
    1638 
    1639     LogFunc(("%s %s\n",
    1640              fEnable ? "Enabling" : "Disabling",
    1641              pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN ? "capture" : "playback"));
    1642 
    1643     if (fEnable)
    1644         drvHostDSoundStreamReset(pThis, pStreamDS);
    1645 
    1646     pStreamDS->fEnabled = fEnable;
    1647 
    1648     return VINF_SUCCESS;
    1649 }
    1650 
    1651 
    1652 /**
    1653  * Starts playing a DirectSound stream.
     1631 * This will try re-open the capture device if we're having trouble starting it.
    16541632 *
    1655  * @return  HRESULT
    1656  * @param   pThis               Host audio driver instance.
    1657  * @param   pStreamDS           Stream to start playing.
    1658  */
    1659 static HRESULT directSoundPlayStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
    1660 {
    1661     HRESULT hr = S_OK;
    1662 
    1663     DWORD fFlags = DSCBSTART_LOOPING;
    1664 
    1665     for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++)
    1666     {
    1667         DSLOG(("DSound: Starting playback\n"));
    1668         hr = IDirectSoundBuffer8_Play(pStreamDS->Out.pDSB, 0, 0, fFlags);
    1669         if (   SUCCEEDED(hr)
    1670             || hr != DSERR_BUFFERLOST)
    1671             break;
    1672         LogFunc(("Restarting playback failed due to lost buffer, restoring ...\n"));
    1673         directSoundPlayRestore(pThis, pStreamDS->Out.pDSB);
    1674     }
    1675 
    1676     return hr;
    1677 }
    1678 
    1679 
    1680 static HRESULT directSoundPlayStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fFlush)
     1633 * @returns VBox status code.
     1634 * @param   pThis       The DSound host audio driver instance data.
     1635 * @param   pStreamDS   The stream instance data.
     1636 */
     1637static int drvHostDSoundStreamCaptureStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
     1638{
     1639    /*
     1640     * Check the stream status first.
     1641     */
     1642    int rc = VERR_AUDIO_STREAM_NOT_READY;
     1643    if (pStreamDS->In.pDSCB)
     1644    {
     1645        DWORD   fStatus = 0;
     1646        HRESULT hrc = IDirectSoundCaptureBuffer8_GetStatus(pStreamDS->In.pDSCB, &fStatus);
     1647        if (SUCCEEDED(hrc))
     1648        {
     1649            /*
     1650             * Try start capturing if it's not already doing so.
     1651             */
     1652            if (!(fStatus & DSCBSTATUS_CAPTURING))
     1653            {
     1654                LogRel2(("DSound: Starting capture on '%s' ... \n", pStreamDS->Cfg.szName));
     1655                hrc = IDirectSoundCaptureBuffer8_Start(pStreamDS->In.pDSCB, DSCBSTART_LOOPING);
     1656                if (SUCCEEDED(hrc))
     1657                    rc = VINF_SUCCESS;
     1658                else
     1659                {
     1660                    /*
     1661                     * Failed to start, try re-create the capture buffer.
     1662                     */
     1663                    LogRelMax(64, ("DSound: Starting to capture on '%s' failed: %Rhrc - will try re-open it ...\n",
     1664                                   pStreamDS->Cfg.szName, hrc));
     1665
     1666                    IDirectSoundCaptureBuffer8_Release(pStreamDS->In.pDSCB);
     1667                    pStreamDS->In.pDSCB = NULL;
     1668
     1669                    PDMAUDIOSTREAMCFG   CfgReq = pStreamDS->Cfg;
     1670                    PDMAUDIOSTREAMCFG   CfgAcq = pStreamDS->Cfg;
     1671                    WAVEFORMATEX        WaveFmtX;
     1672                    dsoundWaveFmtFromCfg(&pStreamDS->Cfg, &WaveFmtX);
     1673                    hrc = drvHostDSoundStreamCreateCapture(pThis, pStreamDS, &CfgReq, &CfgAcq, &WaveFmtX);
     1674                    if (SUCCEEDED(hrc))
     1675                    {
     1676                        PDMAudioStrmCfgCopy(&pStreamDS->Cfg, &CfgAcq);
     1677
     1678                        /*
     1679                         * Try starting capture again.
     1680                         */
     1681                        LogRel2(("DSound: Starting capture on re-opened '%s' ... \n", pStreamDS->Cfg.szName));
     1682                        hrc = IDirectSoundCaptureBuffer8_Start(pStreamDS->In.pDSCB, DSCBSTART_LOOPING);
     1683                        if (SUCCEEDED(hrc))
     1684                            rc = VINF_SUCCESS;
     1685                        else
     1686                            LogRelMax(64, ("DSound: Starting to capture on re-opened '%s' failed: %Rhrc\n",
     1687                                           pStreamDS->Cfg.szName, hrc));
     1688                    }
     1689                    else
     1690                        LogRelMax(64, ("DSound: Re-opening '%s' failed: %Rhrc\n", pStreamDS->Cfg.szName, hrc));
     1691                }
     1692            }
     1693            else
     1694            {
     1695                LogRel2(("DSound: Already capturing (%#x)\n", fStatus));
     1696                AssertFailed();
     1697            }
     1698        }
     1699        else
     1700            LogRelMax(64, ("DSound: Retrieving capture status for '%s' failed: %Rhrc\n", pStreamDS->Cfg.szName, hrc));
     1701    }
     1702    LogFlowFunc(("returns %Rrc\n", rc));
     1703    return rc;
     1704}
     1705
     1706
     1707/**
     1708 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamEnable}
     1709 */
     1710static DECLCALLBACK(int) drvHostDSoundHA_StreamEnable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     1711{
     1712    PDRVHOSTDSOUND  pThis     = RT_FROM_MEMBER(pInterface, DRVHOSTDSOUND, IHostAudio);
     1713    PDSOUNDSTREAM   pStreamDS = (PDSOUNDSTREAM)pStream;
     1714    LogFlowFunc(("fEnabled=%d '%s'\n", pStreamDS->fEnabled, pStreamDS->Cfg.szName));
     1715
     1716    /*
     1717     * We always reset the buffer before enabling the stream (normally never necessary).
     1718     */
     1719    drvHostDSoundStreamReset(pThis, pStreamDS);
     1720    pStreamDS->fEnabled = true;
     1721
     1722    /*
     1723     * Input streams will start capturing, while output streams will only start
     1724     * playing once we get some audio data to play.
     1725     */
     1726    int rc = VINF_SUCCESS;
     1727    if (pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN)
     1728        rc = drvHostDSoundStreamCaptureStart(pThis, pStreamDS);
     1729    else
     1730        Assert(pStreamDS->Cfg.enmDir == PDMAUDIODIR_OUT);
     1731
     1732    LogFlowFunc(("returns %Rrc\n", rc));
     1733    return rc;
     1734}
     1735
     1736
     1737/**
     1738 * Worker for drvHostDSoundHA_StreamDestroy, drvHostDSoundHA_StreamDisable and
     1739 * drvHostDSoundHA_StreamPause.
     1740 *
     1741 * @returns VBox status code.
     1742 * @param   pThis       The DSound host audio driver instance data.
     1743 * @param   pStreamDS   The stream instance data.
     1744 * @param   fReset      Whether to reset the buffer and state.
     1745 */
     1746static int drvHostDSoundStreamStopPlayback(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fReset)
    16811747{
    16821748    if (!pStreamDS->Out.pDSB)
    1683         return S_OK;
     1749        return VINF_SUCCESS;
    16841750
    16851751    LogRel2(("DSound: Stopping playback of '%s'...\n", pStreamDS->Cfg.szName));
     
    16911757        hrc = IDirectSoundBuffer8_Stop(pStreamDS->Out.pDSB);
    16921758        if (FAILED(hrc))
    1693             LogRelMax(64, ("DSound: %s playback of '%s' failed: %Rhrc\n", fFlush ? "Stopping" : "Pausing",
     1759            LogRelMax(64, ("DSound: %s playback of '%s' failed: %Rhrc\n", fReset ? "Stopping" : "Pausing",
    16941760                           pStreamDS->Cfg.szName, hrc));
    16951761    }
    16961762    LogRel2(("DSound: Stopped playback of '%s': %Rhrc\n", pStreamDS->Cfg.szName, hrc));
    16971763
    1698     if (fFlush)
     1764    if (fReset)
    16991765        drvHostDSoundStreamReset(pThis, pStreamDS);
    1700     return hrc;
    1701 }
    1702 
    1703 
    1704 static int dsoundControlStreamOut(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, PDMAUDIOSTREAMCMD enmStreamCmd)
    1705 {
    1706     LogFlowFunc(("pStreamDS=%p, cmd=%d\n", pStreamDS, enmStreamCmd));
    1707 
    1708     HRESULT hr;
    1709     int     rc = VINF_SUCCESS;
    1710     switch (enmStreamCmd)
    1711     {
    1712         case PDMAUDIOSTREAMCMD_ENABLE:
    1713         {
    1714             dsoundStreamEnable(pThis, pStreamDS, true /* fEnable */);
    1715             break;
    1716         }
    1717 
    1718         case PDMAUDIOSTREAMCMD_RESUME:
    1719         {
    1720             /* Only resume if the stream is enabled.
    1721                Note! This used to always just resume the stream playback regardless of state,
    1722                      and instead rely on DISABLE filling the buffer with silence. */
    1723             if (pStreamDS->fEnabled)
    1724             {
    1725                 hr = directSoundPlayStart(pThis, pStreamDS);
    1726                 if (FAILED(hr))
    1727                     rc = VERR_NOT_SUPPORTED; /** @todo Fix this. */
    1728             }
    1729             break;
    1730         }
    1731 
    1732         case PDMAUDIOSTREAMCMD_DISABLE:
    1733         {
    1734             dsoundStreamEnable(pThis, pStreamDS, false /* fEnable */);
    1735 
    1736             /* Don't stop draining buffers. They'll stop by themselves. */
    1737             if (pStreamDS->Cfg.enmDir != PDMAUDIODIR_OUT || !pStreamDS->Out.fDrain)
    1738             {
    1739                 hr = directSoundPlayStop(pThis, pStreamDS, true /* fFlush */);
    1740                 if (FAILED(hr))
    1741                     rc = VERR_NOT_SUPPORTED;
    1742             }
    1743             break;
    1744         }
    1745 
    1746         case PDMAUDIOSTREAMCMD_PAUSE:
    1747         {
    1748             hr = directSoundPlayStop(pThis, pStreamDS, false /* fFlush */);
    1749             if (FAILED(hr))
    1750                 rc = VERR_NOT_SUPPORTED;
    1751             break;
    1752         }
    1753 
    1754         case PDMAUDIOSTREAMCMD_DRAIN:
    1755         {
    1756             /* Make sure we transferred everything. */
    1757             pStreamDS->fEnabled = true; /** @todo r=bird: ??? */
    1758 
    1759             /*
    1760              * We've started the buffer in looping mode, try switch to non-looping...
    1761              */
    1762             if (pStreamDS->Out.pDSB)
    1763             {
    1764                 Log2Func(("drain: Switching playback to non-looping mode...\n"));
    1765                 HRESULT hrc = IDirectSoundBuffer8_Stop(pStreamDS->Out.pDSB);
    1766                 if (SUCCEEDED(hrc))
    1767                 {
    1768                     hrc = IDirectSoundBuffer8_Play(pStreamDS->Out.pDSB, 0, 0, 0);
    1769                     if (SUCCEEDED(hrc))
    1770                         pStreamDS->Out.fDrain = true;
    1771                     else
    1772                         Log2Func(("drain: IDirectSoundBuffer8_Play(,,,0) failed: %Rhrc\n", hrc));
    1773                 }
    1774                 else
    1775                 {
    1776                     Log2Func(("drain: IDirectSoundBuffer8_Stop failed: %Rhrc\n", hrc));
    1777                     hrc = directSoundPlayRestore(pThis, pStreamDS->Out.pDSB);
    1778                     if (SUCCEEDED(hrc))
    1779                     {
    1780                         hrc = IDirectSoundBuffer8_Stop(pStreamDS->Out.pDSB);
    1781                         Log2Func(("drain: IDirectSoundBuffer8_Stop failed: %Rhrc\n", hrc));
    1782                     }
    1783                 }
    1784             }
    1785             break;
    1786         }
    1787 
    1788         default:
    1789             rc = VERR_NOT_SUPPORTED;
    1790             break;
    1791     }
    1792 
    1793     LogFlowFuncLeaveRC(rc);
    1794     return rc;
    1795 }
    1796 
    1797 
    1798 static HRESULT directSoundCaptureStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
    1799 {
    1800     AssertPtrReturn(pThis,     E_POINTER);
    1801     AssertPtrReturn(pStreamDS, E_POINTER);
    1802 
    1803     HRESULT hr;
    1804     if (pStreamDS->In.pDSCB)
    1805     {
    1806         DWORD dwStatus;
    1807         hr = IDirectSoundCaptureBuffer8_GetStatus(pStreamDS->In.pDSCB, &dwStatus);
    1808         if (FAILED(hr))
    1809         {
    1810             DSLOGREL(("DSound: Retrieving capture status failed with %Rhrc\n", hr));
    1811         }
    1812         else
    1813         {
    1814             if (dwStatus & DSCBSTATUS_CAPTURING)
    1815             {
    1816                 DSLOG(("DSound: Already capturing\n"));
    1817             }
     1766    return SUCCEEDED(hrc) ? VINF_SUCCESS : VERR_AUDIO_STREAM_NOT_READY;
     1767}
     1768
     1769
     1770/**
     1771 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamDisable}
     1772 */
     1773static DECLCALLBACK(int) drvHostDSoundHA_StreamDisable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     1774{
     1775    PDRVHOSTDSOUND  pThis     = RT_FROM_MEMBER(pInterface, DRVHOSTDSOUND, IHostAudio);
     1776    PDSOUNDSTREAM   pStreamDS = (PDSOUNDSTREAM)pStream;
     1777    LogFlowFunc(("fEnabled=%d '%s'\n", pStreamDS->fEnabled, pStreamDS->Cfg.szName));
     1778
     1779    /*
     1780     * Change the state.
     1781     */
     1782    pStreamDS->fEnabled = false;
     1783
     1784    /*
     1785     * Stop the stream and maybe reset the buffer.
     1786     */
     1787    int rc = VINF_SUCCESS;
     1788    if (pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN)
     1789    {
     1790        if (pStreamDS->In.pDSCB)
     1791        {
     1792            HRESULT hrc = IDirectSoundCaptureBuffer_Stop(pStreamDS->In.pDSCB);
     1793            if (SUCCEEDED(hrc))
     1794                LogRel3(("DSound: Stopped capture on '%s'.\n", pStreamDS->Cfg.szName));
    18181795            else
    18191796            {
    1820                 const DWORD fFlags = DSCBSTART_LOOPING;
    1821 
    1822                 DSLOG(("DSound: Starting to capture\n"));
    1823                 hr = IDirectSoundCaptureBuffer8_Start(pStreamDS->In.pDSCB, fFlags);
    1824                 if (FAILED(hr))
    1825                     DSLOGREL(("DSound: Starting to capture failed with %Rhrc\n", hr));
     1797                LogRelMax(64, ("DSound: Stopping capture on '%s' failed: %Rhrc\n", pStreamDS->Cfg.szName, hrc));
     1798                /* Don't report errors up to the caller, as it might just be a capture device change. */
    18261799            }
     1800
     1801            /* This isn't strictly speaking necessary since StreamEnable does it too... */
     1802            drvHostDSoundStreamReset(pThis, pStreamDS);
    18271803        }
    18281804    }
    18291805    else
    1830         hr = E_UNEXPECTED;
    1831 
    1832     LogFlowFunc(("Returning %Rhrc\n", hr));
    1833     return hr;
    1834 }
    1835 
    1836 
    1837 static HRESULT directSoundCaptureStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fFlush)
    1838 {
    1839     if (!pStreamDS->In.pDSCB)
    1840         return S_OK;
    1841 
    1842     LogRel2(("DSound: Stopping capture (%s)\n", pStreamDS->Cfg.szName));
    1843     HRESULT hrc = IDirectSoundCaptureBuffer_Stop(pStreamDS->In.pDSCB);
    1844     if (FAILED(hrc))
    1845         LogRelMax(64, ("DSound: Stopping capture of stream '%s' failed: %Rhrc\n", pStreamDS->Cfg.szName, hrc));
    1846 
    1847     if (fFlush)
    1848          drvHostDSoundStreamReset(pThis, pStreamDS);
    1849     return hrc;
    1850 }
    1851 
    1852 
    1853 static HRESULT directSoundCaptureClose(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
    1854 {
    1855     AssertPtrReturn(pThis,     E_POINTER);
    1856     AssertPtrReturn(pStreamDS, E_POINTER);
    1857 
    1858     LogFlowFuncEnter();
    1859 
    1860     HRESULT hr = directSoundCaptureStop(pThis, pStreamDS, true /* fFlush */);
    1861     if (FAILED(hr))
    1862         return hr;
    1863 
    1864     if (   pStreamDS
    1865         && pStreamDS->In.pDSCB)
    1866     {
    1867         DSLOG(("DSound: Closing capturing stream\n"));
    1868 
    1869         IDirectSoundCaptureBuffer8_Release(pStreamDS->In.pDSCB);
    1870         pStreamDS->In.pDSCB = NULL;
    1871     }
    1872 
    1873     LogFlowFunc(("Returning %Rhrc\n", hr));
    1874     return hr;
    1875 }
    1876 
    1877 
    1878 static int dsoundControlStreamIn(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, PDMAUDIOSTREAMCMD enmStreamCmd)
    1879 {
    1880     LogFlowFunc(("pStreamDS=%p, enmStreamCmd=%ld\n", pStreamDS, enmStreamCmd));
    1881 
     1806    {
     1807        Assert(pStreamDS->Cfg.enmDir == PDMAUDIODIR_OUT);
     1808        if (pStreamDS->Out.pDSB)
     1809        {
     1810            /* Don't stop draining buffers. They'll stop by themselves. */
     1811            if (pStreamDS->Out.fDrain)
     1812                LogFunc(("Stream '%s' is draining\n", pStreamDS->Cfg.szName));
     1813            else
     1814            {
     1815                rc = drvHostDSoundStreamStopPlayback(pThis, pStreamDS, true /*fReset*/);
     1816                if (RT_SUCCESS(rc))
     1817                    LogRel3(("DSound: Stopped playback on '%s'.\n", pStreamDS->Cfg.szName));
     1818            }
     1819        }
     1820    }
     1821
     1822    LogFlowFunc(("returns %Rrc\n", rc));
     1823    return rc;
     1824}
     1825
     1826
     1827/**
     1828 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamPause}
     1829 *
     1830 * @note    Basically the same as drvHostDSoundHA_StreamDisable, just w/o the
     1831 *          buffer resetting and fEnabled change.
     1832 */
     1833static DECLCALLBACK(int) drvHostDSoundHA_StreamPause(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     1834{
     1835    PDRVHOSTDSOUND  pThis     = RT_FROM_MEMBER(pInterface, DRVHOSTDSOUND, IHostAudio);
     1836    PDSOUNDSTREAM   pStreamDS = (PDSOUNDSTREAM)pStream;
     1837    LogFlowFunc(("fEnabled=%d '%s'\n", pStreamDS->fEnabled, pStreamDS->Cfg.szName));
     1838
     1839    /*
     1840     * Stop the stream and maybe reset the buffer.
     1841     */
    18821842    int rc = VINF_SUCCESS;
    1883 
    1884     HRESULT hr;
    1885     switch (enmStreamCmd)
    1886     {
    1887         case PDMAUDIOSTREAMCMD_ENABLE:
    1888             dsoundStreamEnable(pThis, pStreamDS, true /* fEnable */);
    1889             RT_FALL_THROUGH();
    1890         case PDMAUDIOSTREAMCMD_RESUME:
    1891         {
    1892             /* Try to start capture. If it fails, then reopen and try again. */
    1893             hr = directSoundCaptureStart(pThis, pStreamDS);
    1894             if (FAILED(hr))
     1843    if (pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN)
     1844    {
     1845        if (pStreamDS->In.pDSCB)
     1846        {
     1847            HRESULT hrc = IDirectSoundCaptureBuffer_Stop(pStreamDS->In.pDSCB);
     1848            if (SUCCEEDED(hrc))
     1849                LogRel3(("DSound: Stopped capture on '%s'.\n", pStreamDS->Cfg.szName));
     1850            else
    18951851            {
    1896                 hr = directSoundCaptureClose(pThis, pStreamDS);
    1897                 if (SUCCEEDED(hr))
    1898                 {
    1899 /** @todo r=bird: This isn't working. CfgAcq isn't initialized! */
    1900                     PDMAUDIOSTREAMCFG CfgAcq;
    1901                     WAVEFORMATEX WaveFmtX;
    1902                     dsoundWaveFmtFromCfg(&pStreamDS->Cfg, &WaveFmtX);
    1903                     hr = drvHostDSoundStreamCreateCapture(pThis, pStreamDS, &pStreamDS->Cfg, &CfgAcq, &WaveFmtX);
    1904                     if (SUCCEEDED(hr))
    1905                     {
    1906                         PDMAudioStrmCfgCopy(&pStreamDS->Cfg, &CfgAcq);
    1907 
    1908                         /** @todo What to do if the format has changed? */
    1909 
    1910                         hr = directSoundCaptureStart(pThis, pStreamDS);
    1911                     }
    1912                 }
     1852                LogRelMax(64, ("DSound: Stopping capture on '%s' failed: %Rhrc\n", pStreamDS->Cfg.szName, hrc));
     1853                /* Don't report errors up to the caller, as it might just be a capture device change. */
    19131854            }
    1914 
    1915             if (FAILED(hr))
    1916                 rc = VERR_NOT_SUPPORTED;
    1917             break;
    1918         }
    1919 
    1920         case PDMAUDIOSTREAMCMD_DISABLE:
    1921             dsoundStreamEnable(pThis, pStreamDS, false /* fEnable */);
    1922             RT_FALL_THROUGH();
    1923         case PDMAUDIOSTREAMCMD_PAUSE:
    1924         {
    1925             directSoundCaptureStop(pThis, pStreamDS, enmStreamCmd == PDMAUDIOSTREAMCMD_DISABLE /* fFlush */);
    1926 
    1927             /* Return success in any case, as stopping the capture can fail if
    1928              * the capture buffer is not around anymore.
    1929              *
    1930              * This can happen if the host's capturing device has been changed suddenly. */
    1931             rc = VINF_SUCCESS;
    1932             break;
    1933         }
    1934 
    1935         default:
    1936             rc = VERR_NOT_SUPPORTED;
    1937             break;
    1938     }
    1939 
     1855        }
     1856    }
     1857    else
     1858    {
     1859        Assert(pStreamDS->Cfg.enmDir == PDMAUDIODIR_OUT);
     1860        if (pStreamDS->Out.pDSB)
     1861        {
     1862            /* Don't stop draining buffers, we won't be resuming them right.
     1863               They'll stop by themselves anyway. */
     1864            if (pStreamDS->Out.fDrain)
     1865                LogFunc(("Stream '%s' is draining\n", pStreamDS->Cfg.szName));
     1866            else
     1867            {
     1868                rc = drvHostDSoundStreamStopPlayback(pThis, pStreamDS, false /*fReset*/);
     1869                if (RT_SUCCESS(rc))
     1870                    LogRel3(("DSound: Stopped playback on '%s'.\n", pStreamDS->Cfg.szName));
     1871            }
     1872        }
     1873    }
     1874
     1875    LogFlowFunc(("returns %Rrc\n", rc));
    19401876    return rc;
    19411877}
    19421878
     1879
     1880/**
     1881 * Worker for drvHostDSoundHA_StreamResume and drvHostDSoundHA_StreamPlay that
     1882 * starts playing the DirectSound Buffer.
     1883 *
     1884 * @returns VBox status code.
     1885 * @param   pThis               Host audio driver instance.
     1886 * @param   pStreamDS           Stream to start playing.
     1887 */
     1888static int directSoundPlayStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS)
     1889{
     1890    if (!pStreamDS->Out.pDSB)
     1891        return VERR_AUDIO_STREAM_NOT_READY;
     1892
     1893    LogRel2(("DSound: Starting playback of '%s' ...\n", pStreamDS->Cfg.szName));
     1894    HRESULT hrc = IDirectSoundBuffer8_Play(pStreamDS->Out.pDSB, 0, 0, DSCBSTART_LOOPING);
     1895    if (SUCCEEDED(hrc))
     1896        return VINF_SUCCESS;
     1897
     1898    for (unsigned i = 0; hrc == DSERR_BUFFERLOST && i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++)
     1899    {
     1900        LogFunc(("Restarting playback failed due to lost buffer, restoring ...\n"));
     1901        directSoundPlayRestore(pThis, pStreamDS->Out.pDSB);
     1902
     1903        hrc = IDirectSoundBuffer8_Play(pStreamDS->Out.pDSB, 0, 0, DSCBSTART_LOOPING);
     1904        if (SUCCEEDED(hrc))
     1905            return VINF_SUCCESS;
     1906    }
     1907
     1908    LogRelMax(64, ("DSound: Failed to start playback of '%s': %Rhrc\n", pStreamDS->Cfg.szName, hrc));
     1909    return VERR_AUDIO_STREAM_NOT_READY;
     1910}
     1911
     1912
     1913/**
     1914 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamResume}
     1915 */
     1916static DECLCALLBACK(int) drvHostDSoundHA_StreamResume(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     1917{
     1918    PDRVHOSTDSOUND  pThis     = RT_FROM_MEMBER(pInterface, DRVHOSTDSOUND, IHostAudio);
     1919    PDSOUNDSTREAM   pStreamDS = (PDSOUNDSTREAM)pStream;
     1920    LogFlowFunc(("fEnabled=%d '%s'\n", pStreamDS->fEnabled, pStreamDS->Cfg.szName));
     1921
     1922    /*
     1923     * Input streams will start capturing, while output streams will only start
     1924     * playing if we're past the pre-buffering state.
     1925     */
     1926    int rc = VINF_SUCCESS;
     1927    if (pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN)
     1928        rc = drvHostDSoundStreamCaptureStart(pThis, pStreamDS);
     1929    else
     1930    {
     1931        Assert(pStreamDS->Cfg.enmDir == PDMAUDIODIR_OUT);
     1932        if (!pStreamDS->Out.fFirstTransfer)
     1933            rc = directSoundPlayStart(pThis, pStreamDS);
     1934    }
     1935
     1936    LogFlowFunc(("returns %Rrc\n", rc));
     1937    return rc;
     1938}
     1939
     1940
     1941/**
     1942 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamDrain}
     1943 */
     1944static DECLCALLBACK(int) drvHostDSoundHA_StreamDrain(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)
     1945{
     1946    PDRVHOSTDSOUND  pThis     = RT_FROM_MEMBER(pInterface, DRVHOSTDSOUND, IHostAudio);
     1947    PDSOUNDSTREAM   pStreamDS = (PDSOUNDSTREAM)pStream;
     1948    AssertReturn(pStreamDS->Cfg.enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER);
     1949    LogFlowFunc(("fEnabled=%d fDrain=%d '%s'\n", pStreamDS->fEnabled, pStreamDS->Out.fDrain, pStreamDS->Cfg.szName));
     1950
     1951    /*
     1952     * We've started the buffer in looping mode, try switch to non-looping...
     1953     */
     1954    int rc = VINF_SUCCESS;
     1955    if (pStreamDS->Out.pDSB && !pStreamDS->Out.fDrain)
     1956    {
     1957        LogRel2(("DSound: Switching playback stream '%s' to drain mode...\n", pStreamDS->Cfg.szName));
     1958        HRESULT hrc = IDirectSoundBuffer8_Stop(pStreamDS->Out.pDSB);
     1959        if (SUCCEEDED(hrc))
     1960        {
     1961            hrc = IDirectSoundBuffer8_Play(pStreamDS->Out.pDSB, 0, 0, 0);
     1962            if (SUCCEEDED(hrc))
     1963                pStreamDS->Out.fDrain = true;
     1964            else
     1965                LogRelMax(64, ("DSound: Failed to restart '%s' in drain mode: %Rhrc\n", pStreamDS->Cfg.szName, hrc));
     1966        }
     1967        else
     1968        {
     1969            Log2Func(("drain: IDirectSoundBuffer8_Stop failed: %Rhrc\n", hrc));
     1970            directSoundPlayRestore(pThis, pStreamDS->Out.pDSB);
     1971
     1972            HRESULT hrc2 = IDirectSoundBuffer8_Stop(pStreamDS->Out.pDSB);
     1973            if (SUCCEEDED(hrc2))
     1974                LogFunc(("Successfully stopped the stream after restoring it. (hrc=%Rhrc)\n", hrc));
     1975            else
     1976            {
     1977                LogRelMax(64, ("DSound: Failed to stop playback stream '%s' for putting into drain mode: %Rhrc (initial), %Rhrc (after restore)\n",
     1978                               pStreamDS->Cfg.szName, hrc, hrc2));
     1979                rc = VERR_AUDIO_STREAM_NOT_READY;
     1980            }
     1981        }
     1982    }
     1983    LogFlowFunc(("returns %Rrc\n", rc));
     1984    return rc;
     1985}
    19431986
    19441987/**
     
    19481991                                                       PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)
    19491992{
    1950     PDRVHOSTDSOUND pThis     = RT_FROM_MEMBER(pInterface, DRVHOSTDSOUND, IHostAudio);
    1951     PDSOUNDSTREAM  pStreamDS = (PDSOUNDSTREAM)pStream;
    1952     AssertPtrReturn(pStreamDS, VERR_INVALID_POINTER);
    1953 
    1954     int rc;
    1955     if (pStreamDS->Cfg.enmDir == PDMAUDIODIR_IN)
    1956         rc = dsoundControlStreamIn(pThis,  pStreamDS, enmStreamCmd);
    1957     else
    1958         rc = dsoundControlStreamOut(pThis, pStreamDS, enmStreamCmd);
    1959 
    1960     return rc;
     1993    /** @todo r=bird: I'd like to get rid of this pfnStreamControl method,
     1994     *        replacing it with individual StreamXxxx methods.  That would save us
     1995     *        potentally huge switches and more easily see which drivers implement
     1996     *        which operations (grep for pfnStreamXxxx). */
     1997    switch (enmStreamCmd)
     1998    {
     1999        case PDMAUDIOSTREAMCMD_ENABLE:
     2000            return drvHostDSoundHA_StreamEnable(pInterface, pStream);
     2001        case PDMAUDIOSTREAMCMD_DISABLE:
     2002            return drvHostDSoundHA_StreamDisable(pInterface, pStream);
     2003        case PDMAUDIOSTREAMCMD_PAUSE:
     2004            return drvHostDSoundHA_StreamPause(pInterface, pStream);
     2005        case PDMAUDIOSTREAMCMD_RESUME:
     2006            return drvHostDSoundHA_StreamResume(pInterface, pStream);
     2007        case PDMAUDIOSTREAMCMD_DRAIN:
     2008            return drvHostDSoundHA_StreamDrain(pInterface, pStream);
     2009
     2010        case PDMAUDIOSTREAMCMD_END:
     2011        case PDMAUDIOSTREAMCMD_32BIT_HACK:
     2012        case PDMAUDIOSTREAMCMD_INVALID:
     2013            /* no default*/
     2014            break;
     2015    }
     2016    return VERR_NOT_SUPPORTED;
    19612017}
    19622018
     
    22312287        {
    22322288            *pcbWritten = cbWritten;
    2233             hrc = directSoundPlayStart(pThis, pStreamDS);
    2234             AssertMsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), VERR_ACCESS_DENIED); /** @todo translate these status codes already! */
     2289            rc = directSoundPlayStart(pThis, pStreamDS);
     2290            AssertRCReturn(rc, rc);
    22352291            pStreamDS->Out.fFirstTransfer = false;
    22362292        }
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