Changeset 88556 in vbox
- Timestamp:
- Apr 16, 2021 12:08:40 AM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 143851
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvHostAudioDSound.cpp
r88555 r88556 227 227 *********************************************************************************************************************************/ 228 228 static 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); 229 static int drvHostDSoundStreamStopPlayback(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fReset); 232 230 233 231 static int dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PDMAUDIOHOSTENUM pDevEnm, uint32_t fEnum); 234 232 235 static int dsoundStreamEnable(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fEnable);236 233 static void dsoundUpdateStatusInternal(PDRVHOSTDSOUND pThis); 237 234 … … 1598 1595 if (pStreamDS->In.pDSCB) 1599 1596 { 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); 1601 1602 1602 1603 IDirectSoundCaptureBuffer8_Release(pStreamDS->In.pDSCB); … … 1611 1612 if (pStreamDS->Out.pDSB) 1612 1613 { 1613 d irectSoundPlayStop(pThis, pStreamDS, true /* fFlush*/);1614 drvHostDSoundStreamStopPlayback(pThis, pStreamDS, true /*fReset*/); 1614 1615 1615 1616 IDirectSoundBuffer8_Release(pStreamDS->Out.pDSB); … … 1626 1627 1627 1628 /** 1628 * Enables or disables a stream.1629 * Worker for drvHostDSoundHA_StreamEnable and drvHostDSoundHA_StreamResume. 1629 1630 * 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. 1654 1632 * 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 */ 1637 static 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 */ 1710 static 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 */ 1746 static int drvHostDSoundStreamStopPlayback(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fReset) 1681 1747 { 1682 1748 if (!pStreamDS->Out.pDSB) 1683 return S_OK;1749 return VINF_SUCCESS; 1684 1750 1685 1751 LogRel2(("DSound: Stopping playback of '%s'...\n", pStreamDS->Cfg.szName)); … … 1691 1757 hrc = IDirectSoundBuffer8_Stop(pStreamDS->Out.pDSB); 1692 1758 if (FAILED(hrc)) 1693 LogRelMax(64, ("DSound: %s playback of '%s' failed: %Rhrc\n", f Flush? "Stopping" : "Pausing",1759 LogRelMax(64, ("DSound: %s playback of '%s' failed: %Rhrc\n", fReset ? "Stopping" : "Pausing", 1694 1760 pStreamDS->Cfg.szName, hrc)); 1695 1761 } 1696 1762 LogRel2(("DSound: Stopped playback of '%s': %Rhrc\n", pStreamDS->Cfg.szName, hrc)); 1697 1763 1698 if (f Flush)1764 if (fReset) 1699 1765 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 */ 1773 static 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)); 1818 1795 else 1819 1796 { 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. */ 1826 1799 } 1800 1801 /* This isn't strictly speaking necessary since StreamEnable does it too... */ 1802 drvHostDSoundStreamReset(pThis, pStreamDS); 1827 1803 } 1828 1804 } 1829 1805 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 */ 1833 static 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 */ 1882 1842 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 1895 1851 { 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. */ 1913 1854 } 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)); 1940 1876 return rc; 1941 1877 } 1942 1878 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 */ 1888 static 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 */ 1916 static 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 */ 1944 static 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 } 1943 1986 1944 1987 /** … … 1948 1991 PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd) 1949 1992 { 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; 1961 2017 } 1962 2018 … … 2231 2287 { 2232 2288 *pcbWritten = cbWritten; 2233 hrc = directSoundPlayStart(pThis, pStreamDS);2234 Assert MsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), VERR_ACCESS_DENIED); /** @todo translate these status codes already! */2289 rc = directSoundPlayStart(pThis, pStreamDS); 2290 AssertRCReturn(rc, rc); 2235 2291 pStreamDS->Out.fFirstTransfer = false; 2236 2292 }
Note:
See TracChangeset
for help on using the changeset viewer.