VirtualBox

Changeset 86575 in vbox


Ignore:
Timestamp:
Oct 14, 2020 3:07:27 PM (4 years ago)
Author:
vboxsync
Message:

Audio/DSound: Query playback/capture device information outside the actual device enumeration callbacks to prevent DSound hangs. bugref:8658

File:
1 edited

Legend:

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

    r83812 r86575  
    16111611            PDSOUNDDEV pDSoundDev = (PDSOUNDDEV)pDev->pvData;
    16121612
    1613             if (pGUID)
     1613            if (pGUID) /* pGUID == NULL means default device. */
    16141614                memcpy(&pDSoundDev->Guid, pGUID, sizeof(GUID));
    16151615
    1616             LPDIRECTSOUND8 pDS;
    1617             HRESULT hr = directSoundPlayInterfaceCreate(pGUID, &pDS);
     1616            rc = DrvAudioHlpDeviceEnumAdd(pDevEnm, pDev);
     1617
     1618            /* Note: Querying the actual device information will be done at some
     1619             *       later point in time outside this enumeration callback to prevent
     1620             *       DSound hangs. */
     1621        }
     1622    }
     1623    else
     1624        rc = VERR_NO_MEMORY;
     1625
     1626    if (RT_FAILURE(rc))
     1627    {
     1628        LogRel(("DSound: Error enumeration playback device '%ls', rc=%Rrc\n", pwszDescription, rc));
     1629        return FALSE; /* Abort enumeration. */
     1630    }
     1631
     1632    return TRUE;
     1633}
     1634
     1635/**
     1636 * Callback for the capture device enumeration.
     1637 *
     1638 * @return  TRUE if continuing enumeration, FALSE if not.
     1639 * @param   pGUID               Pointer to GUID of enumerated device. Can be NULL.
     1640 * @param   pwszDescription     Pointer to (friendly) description of enumerated device.
     1641 * @param   pwszModule          Pointer to module name of enumerated device.
     1642 * @param   lpContext           Pointer to PDSOUNDENUMCBCTX context for storing the enumerated information.
     1643 */
     1644static BOOL CALLBACK dsoundDevicesEnumCbCapture(LPGUID pGUID, LPCWSTR pwszDescription, LPCWSTR pwszModule, PVOID lpContext)
     1645{
     1646    RT_NOREF(pwszModule);
     1647
     1648    PDSOUNDENUMCBCTX pEnumCtx = (PDSOUNDENUMCBCTX )lpContext;
     1649    AssertPtrReturn(pEnumCtx , FALSE);
     1650
     1651    PPDMAUDIODEVICEENUM pDevEnm = pEnumCtx->pDevEnm;
     1652    AssertPtrReturn(pDevEnm, FALSE);
     1653
     1654    /* pGUID can be NULL for default device(s). */
     1655    AssertPtrReturn(pwszDescription, FALSE);
     1656    /* Do not care about pwszModule. */
     1657
     1658    int rc;
     1659
     1660    PPDMAUDIODEVICE pDev = DrvAudioHlpDeviceAlloc(sizeof(DSOUNDDEV));
     1661    if (pDev)
     1662    {
     1663        pDev->enmUsage = PDMAUDIODIR_IN;
     1664        pDev->enmType  = PDMAUDIODEVICETYPE_BUILTIN;
     1665
     1666        char *pszName;
     1667        rc = RTUtf16ToUtf8(pwszDescription, &pszName);
     1668        if (RT_SUCCESS(rc))
     1669        {
     1670            RTStrCopy(pDev->szName, sizeof(pDev->szName), pszName);
     1671            RTStrFree(pszName);
     1672
     1673            PDSOUNDDEV pDSoundDev = (PDSOUNDDEV)pDev->pvData;
     1674
     1675            if (pGUID) /* pGUID == NULL means default capture device. */
     1676                memcpy(&pDSoundDev->Guid, pGUID, sizeof(GUID));
     1677
     1678            rc = DrvAudioHlpDeviceEnumAdd(pDevEnm, pDev);
     1679
     1680            /* Note: Querying the actual device information will be done at some
     1681             *       later point in time outside this enumeration callback to prevent
     1682             *       DSound hangs. */
     1683        }
     1684    }
     1685    else
     1686        rc = VERR_NO_MEMORY;
     1687
     1688    if (RT_FAILURE(rc))
     1689    {
     1690        LogRel(("DSound: Error enumeration capture device '%ls', rc=%Rrc\n", pwszDescription, rc));
     1691        return FALSE; /* Abort enumeration. */
     1692    }
     1693
     1694    return TRUE;
     1695}
     1696
     1697/**
     1698 * Qqueries information for a given (DirectSound) device.
     1699 *
     1700 * @returns VBox status code.
     1701 * @param   pThis               Host audio driver instance.
     1702 * @param   pDev                Audio device to query information for.
     1703 */
     1704static int dsoundDeviceQueryInfo(PDRVHOSTDSOUND pThis, PPDMAUDIODEVICE pDev)
     1705{
     1706    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1707    AssertPtrReturn(pDev,  VERR_INVALID_POINTER);
     1708
     1709    PDSOUNDDEV pDSoundDev = (PDSOUNDDEV)pDev->pvData;
     1710    AssertPtr(pDSoundDev);
     1711
     1712    int rc;
     1713
     1714    if (pDev->enmUsage == PDMAUDIODIR_OUT)
     1715    {
     1716        LPDIRECTSOUND8 pDS;
     1717        HRESULT hr = directSoundPlayInterfaceCreate(&pDSoundDev->Guid, &pDS);
     1718        if (SUCCEEDED(hr))
     1719        {
     1720            DSCAPS DSCaps;
     1721            RT_ZERO(DSCaps);
     1722            DSCaps.dwSize = sizeof(DSCAPS);
     1723            hr = IDirectSound_GetCaps(pDS, &DSCaps);
    16181724            if (SUCCEEDED(hr))
    16191725            {
    1620                 do
     1726                pDev->cMaxOutputChannels = DSCaps.dwFlags & DSCAPS_PRIMARYSTEREO ? 2 : 1;
     1727
     1728                DWORD dwSpeakerCfg;
     1729                hr = IDirectSound_GetSpeakerConfig(pDS, &dwSpeakerCfg);
     1730                if (SUCCEEDED(hr))
    16211731                {
    1622                     DSCAPS DSCaps;
    1623                     RT_ZERO(DSCaps);
    1624                     DSCaps.dwSize = sizeof(DSCAPS);
    1625                     hr = IDirectSound_GetCaps(pDS, &DSCaps);
    1626                     if (FAILED(hr))
    1627                         break;
    1628 
    1629                     pDev->cMaxOutputChannels = DSCaps.dwFlags & DSCAPS_PRIMARYSTEREO ? 2 : 1;
    1630 
    1631                     DWORD dwSpeakerCfg;
    1632                     hr = IDirectSound_GetSpeakerConfig(pDS, &dwSpeakerCfg);
    1633                     if (FAILED(hr))
    1634                         break;
    1635 
    16361732                    unsigned uSpeakerCount = 0;
    16371733                    switch (DSSPEAKER_CONFIG(dwSpeakerCfg))
     
    16521748                        pDev->cMaxOutputChannels = uSpeakerCount;
    16531749
    1654                 } while (0);
    1655 
    1656                 directSoundPlayInterfaceDestroy(pDS);
    1657 
     1750                    rc = VINF_SUCCESS;
     1751                }
     1752                else
     1753                {
     1754                    LogRel(("DSound: Error retrieving playback device speaker config, hr=%Rhrc\n", hr));
     1755                    rc = VERR_ACCESS_DENIED; /** @todo Fudge! */
     1756                }
     1757            }
     1758            else
     1759            {
     1760                LogRel(("DSound: Error retrieving playback device capabilities, hr=%Rhrc\n", hr));
     1761                rc = VERR_ACCESS_DENIED; /** @todo Fudge! */
     1762            }
     1763
     1764            directSoundPlayInterfaceDestroy(pDS);
     1765        }
     1766        else
     1767            rc = VERR_GENERAL_FAILURE;
     1768    }
     1769    else if (pDev->enmUsage == PDMAUDIODIR_IN)
     1770    {
     1771        LPDIRECTSOUNDCAPTURE8 pDSC;
     1772        HRESULT hr = directSoundCaptureInterfaceCreate(&pDSoundDev->Guid, &pDSC);
     1773        if (SUCCEEDED(hr))
     1774        {
     1775            DSCCAPS DSCCaps;
     1776            RT_ZERO(DSCCaps);
     1777            DSCCaps.dwSize = sizeof(DSCCAPS);
     1778            hr = IDirectSoundCapture_GetCaps(pDSC, &DSCCaps);
     1779            if (SUCCEEDED(hr))
     1780            {
     1781                pDev->cMaxInputChannels = DSCCaps.dwChannels;
    16581782                rc = VINF_SUCCESS;
    16591783            }
    16601784            else
    1661                 rc = VERR_GENERAL_FAILURE;
    1662 
    1663             if (RT_SUCCESS(rc))
    1664                 rc = DrvAudioHlpDeviceEnumAdd(pDevEnm, pDev);
    1665         }
     1785            {
     1786                LogRel(("DSound: Error retrieving capture device capabilities, hr=%Rhrc\n", hr));
     1787                rc = VERR_ACCESS_DENIED; /** @todo Fudge! */
     1788            }
     1789
     1790            directSoundCaptureInterfaceDestroy(pDSC);
     1791        }
     1792        else
     1793            rc = VERR_GENERAL_FAILURE;
    16661794    }
    16671795    else
    1668         rc = VERR_NO_MEMORY;
    1669 
    1670     if (RT_FAILURE(rc))
    1671     {
    1672         LogRel(("DSound: Error enumeration playback device '%ls', rc=%Rrc\n", pwszDescription, rc));
    1673         return FALSE; /* Abort enumeration. */
    1674     }
    1675 
    1676     return TRUE;
    1677 }
    1678 
    1679 /**
    1680  * Callback for the capture device enumeration.
    1681  *
    1682  * @return  TRUE if continuing enumeration, FALSE if not.
    1683  * @param   pGUID               Pointer to GUID of enumerated device. Can be NULL.
    1684  * @param   pwszDescription     Pointer to (friendly) description of enumerated device.
    1685  * @param   pwszModule          Pointer to module name of enumerated device.
    1686  * @param   lpContext           Pointer to PDSOUNDENUMCBCTX context for storing the enumerated information.
    1687  */
    1688 static BOOL CALLBACK dsoundDevicesEnumCbCapture(LPGUID pGUID, LPCWSTR pwszDescription, LPCWSTR pwszModule, PVOID lpContext)
    1689 {
    1690     RT_NOREF(pwszModule);
    1691 
    1692     PDSOUNDENUMCBCTX pEnumCtx = (PDSOUNDENUMCBCTX )lpContext;
    1693     AssertPtrReturn(pEnumCtx , FALSE);
    1694 
    1695     PPDMAUDIODEVICEENUM pDevEnm = pEnumCtx->pDevEnm;
    1696     AssertPtrReturn(pDevEnm, FALSE);
    1697 
    1698     /* pGUID can be NULL for default device(s). */
    1699     AssertPtrReturn(pwszDescription, FALSE);
    1700     /* Do not care about pwszModule. */
    1701 
    1702     int rc;
    1703 
    1704     PPDMAUDIODEVICE pDev = DrvAudioHlpDeviceAlloc(sizeof(DSOUNDDEV));
    1705     if (pDev)
    1706     {
    1707         pDev->enmUsage = PDMAUDIODIR_IN;
    1708         pDev->enmType  = PDMAUDIODEVICETYPE_BUILTIN;
    1709 
    1710         char *pszName;
    1711         rc = RTUtf16ToUtf8(pwszDescription, &pszName);
    1712         if (RT_SUCCESS(rc))
    1713         {
    1714             RTStrCopy(pDev->szName, sizeof(pDev->szName), pszName);
    1715             RTStrFree(pszName);
    1716 
    1717             PDSOUNDDEV pDSoundDev = (PDSOUNDDEV)pDev->pvData;
    1718 
    1719             if (pGUID)
    1720                 memcpy(&pDSoundDev->Guid, pGUID, sizeof(GUID));
    1721 
    1722             LPDIRECTSOUNDCAPTURE8 pDSC;
    1723             HRESULT hr = directSoundCaptureInterfaceCreate(pGUID, &pDSC);
    1724             if (SUCCEEDED(hr))
    1725             {
    1726                 do
    1727                 {
    1728                     DSCCAPS DSCCaps;
    1729                     RT_ZERO(DSCCaps);
    1730                     DSCCaps.dwSize = sizeof(DSCCAPS);
    1731                     hr = IDirectSoundCapture_GetCaps(pDSC, &DSCCaps);
    1732                     if (FAILED(hr))
    1733                         break;
    1734 
    1735                     pDev->cMaxInputChannels = DSCCaps.dwChannels;
    1736 
    1737                 } while (0);
    1738 
    1739                 directSoundCaptureInterfaceDestroy(pDSC);
    1740 
    1741                 rc = VINF_SUCCESS;
    1742             }
    1743             else
    1744                 rc = VERR_GENERAL_FAILURE;
    1745 
    1746             if (RT_SUCCESS(rc))
    1747                 rc = DrvAudioHlpDeviceEnumAdd(pDevEnm, pDev);
    1748         }
    1749     }
    1750     else
    1751         rc = VERR_NO_MEMORY;
    1752 
    1753     if (RT_FAILURE(rc))
    1754     {
    1755         LogRel(("DSound: Error enumeration capture device '%ls', rc=%Rrc\n", pwszDescription, rc));
    1756         return FALSE; /* Abort enumeration. */
    1757     }
    1758 
    1759     return TRUE;
     1796        AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
     1797
     1798    return rc;
    17601799}
    17611800
     
    17691808static int dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PPDMAUDIODEVICEENUM pDevEnm)
    17701809{
    1771     AssertPtrReturn(pThis,    VERR_INVALID_POINTER);
     1810    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     1811    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
    17721812
    17731813    DSLOG(("DSound: Enumerating devices ...\n"));
     
    17811821        EnumCtx.pDevEnm = pDevEnm;
    17821822
     1823        /*
     1824         * Enumerate playback devices.
     1825         */
    17831826        PFNDIRECTSOUNDENUMERATEW pfnDirectSoundEnumerateW = NULL;
    17841827        rc = RTLdrGetSymbol(hDSound, "DirectSoundEnumerateW", (void**)&pfnDirectSoundEnumerateW);
    17851828        if (RT_SUCCESS(rc))
    17861829        {
     1830            DSLOG(("DSound: Enumerating playback devices ...\n"));
     1831
    17871832            HRESULT hr = pfnDirectSoundEnumerateW(&dsoundDevicesEnumCbPlayback, &EnumCtx);
    17881833            if (FAILED(hr))
     
    17921837            LogRel(("DSound: Error starting to enumerate host playback devices: %Rrc\n", rc));
    17931838
     1839        /*
     1840         * Enumerate capture devices.
     1841         */
    17941842        PFNDIRECTSOUNDCAPTUREENUMERATEW pfnDirectSoundCaptureEnumerateW = NULL;
    17951843        rc = RTLdrGetSymbol(hDSound, "DirectSoundCaptureEnumerateW", (void**)&pfnDirectSoundCaptureEnumerateW);
    17961844        if (RT_SUCCESS(rc))
    17971845        {
     1846            DSLOG(("DSound: Enumerating capture devices ...\n"));
     1847
    17981848            HRESULT hr = pfnDirectSoundCaptureEnumerateW(&dsoundDevicesEnumCbCapture, &EnumCtx);
    17991849            if (FAILED(hr))
     
    18031853            LogRel(("DSound: Error starting to enumerate host capture devices: %Rrc\n", rc));
    18041854
     1855        /*
     1856         * Query Information from all enumerated devices.
     1857         */
     1858        PPDMAUDIODEVICE pDev;
     1859        RTListForEach(&pDevEnm->lstDevices, pDev, PDMAUDIODEVICE, Node)
     1860            /* ignore rc */ dsoundDeviceQueryInfo(pThis, pDev);
     1861
    18051862        RTLdrClose(hDSound);
    18061863    }
     
    18081865    {
    18091866        /* No dsound.dll on this system. */
    1810         LogRel(("DSound: Could not load dsound.dll: %Rrc\n", rc));
     1867        LogRel(("DSound: Could not load dsound.dll for enumerating devices: %Rrc\n", rc));
    18111868    }
    18121869
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