VirtualBox

Changeset 77028 in vbox


Ignore:
Timestamp:
Jan 29, 2019 12:26:30 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
128461
Message:

Audio/DrvHostDSound: Implemented support for the generic audio device enumeration and fixed a bug using non-default input/output devices (if available).

File:
1 edited

Legend:

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

    r76992 r77028  
    177177} DSOUNDSTREAM, *PDSOUNDSTREAM;
    178178
     179/**
     180 * Structure for keeping a DirectSound-specific device entry.
     181 * This is then bound to the PDMAUDIODEVICE's pvData area.
     182 */
     183typedef struct DSOUNDDEV
     184{
     185    GUID Guid;
     186} DSOUNDDEV, *PDSOUNDDEV;
     187
     188/**
     189 * Structure for holding a device enumeration context.
     190 */
     191typedef struct DSOUNDENUMCBCTX
     192{
     193    /** Enumeration flags. */
     194    uint32_t            fFlags;
     195    /** Pointer to device list to populate. */
     196    PPDMAUDIODEVICEENUM pDevEnm;
     197} DSOUNDENUMCBCTX, *PDSOUNDENUMCBCTX;
     198
    179199typedef struct DRVHOSTDSOUND
    180200{
     
    185205    /** Critical section to serialize access. */
    186206    RTCRITSECT                  CritSect;
    187     /** List of found host input devices. */
    188     RTLISTANCHOR                lstDevInput;
    189     /** List of found host output devices. */
    190     RTLISTANCHOR                lstDevOutput;
    191207    /** DirectSound configuration options. */
    192208    DSOUNDHOSTCFG               Cfg;
     209    /** List of devices of last enumeration. */
     210    PDMAUDIODEVICEENUM          DeviceEnum;
    193211    /** Whether this backend supports any audio input. */
    194212    bool                        fEnabledIn;
     
    213231} DRVHOSTDSOUND, *PDRVHOSTDSOUND;
    214232
    215 /** No flags specified. */
    216 #define DSOUNDENUMCBFLAGS_NONE          0
    217 /** (Release) log found devices. */
    218 #define DSOUNDENUMCBFLAGS_LOG           RT_BIT(0)
    219 
    220 /**
    221  * Callback context for enumeration callbacks
    222  */
    223 typedef struct DSOUNDENUMCBCTX
    224 {
    225     /** Pointer to host backend driver. */
    226     PDRVHOSTDSOUND      pDrv;
    227     /** Enumeration flags. */
    228     uint32_t            fFlags;
    229     /** Number of found input devices. */
    230     uint8_t             cDevIn;
    231     /** Number of found output devices. */
    232     uint8_t             cDevOut;
    233 } DSOUNDENUMCBCTX, *PDSOUNDENUMCBCTX;
    234 
    235 typedef struct DSOUNDDEV
    236 {
    237     RTLISTNODE  Node;
    238     char       *pszName;
    239     GUID        Guid;
    240 } DSOUNDDEV, *PDSOUNDDEV;
    241 
    242 
    243233/*********************************************************************************************************************************
    244234*   Internal Functions                                                                                                           *
     
    249239static HRESULT  directSoundCaptureStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fFlush);
    250240
    251 static void     dsoundDeviceRemove(PDSOUNDDEV pDev);
    252 static int      dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PPDMAUDIOBACKENDCFG pCfg);
     241static int      dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PDMAUDIODEVICEENUM pDevEnm, uint32_t fEnum);
    253242
    254243static int      dsoundStreamEnable(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fEnable);
    255244static void     dsoundStreamReset(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS);
    256245static void     dsoundUpdateStatusInternal(PDRVHOSTDSOUND pThis);
    257 static void     dsoundUpdateStatusInternalEx(PDRVHOSTDSOUND pThis, PPDMAUDIOBACKENDCFG pCfg, uint32_t fEnum);
    258246
    259247
     
    379367
    380368    return RTStrDup("{Default device}");
    381 }
    382 
    383 /**
    384  * Clears the list of the host's playback + capturing devices.
    385  *
    386  * @param   pThis               Host audio driver instance.
    387  */
    388 static void dsoundDevicesClear(PDRVHOSTDSOUND pThis)
    389 {
    390     AssertPtrReturnVoid(pThis);
    391 
    392     PDSOUNDDEV pDev, pDevNext;
    393     RTListForEachSafe(&pThis->lstDevInput, pDev, pDevNext, DSOUNDDEV, Node)
    394         dsoundDeviceRemove(pDev);
    395 
    396     Assert(RTListIsEmpty(&pThis->lstDevInput));
    397 
    398     RTListForEachSafe(&pThis->lstDevOutput, pDev, pDevNext, DSOUNDDEV, Node)
    399         dsoundDeviceRemove(pDev);
    400 
    401     Assert(RTListIsEmpty(&pThis->lstDevOutput));
    402369}
    403370
     
    522489 */
    523490
    524 static void directSoundPlayInterfaceDestroy(PDRVHOSTDSOUND pThis)
    525 {
    526     if (pThis->pDS)
     491/**
     492 * Destroys a DirectSound playback interface.
     493 *
     494 * @param   pDS                 Playback interface to destroy.
     495 */
     496static void directSoundPlayInterfaceDestroy(LPDIRECTSOUND8 pDS)
     497{
     498    if (pDS)
    527499    {
    528500        LogFlowFuncEnter();
    529501
    530         IDirectSound8_Release(pThis->pDS);
    531         pThis->pDS = NULL;
    532     }
    533 }
    534 
    535 static HRESULT directSoundPlayInterfaceCreate(PDRVHOSTDSOUND pThis)
    536 {
    537     if (pThis->pDS != NULL)
    538         return S_OK;
     502        IDirectSound8_Release(pDS);
     503        pDS = NULL;
     504    }
     505}
     506
     507/**
     508 * Creates a DirectSound playback interface.
     509 *
     510 * @return  HRESULT
     511 * @param   pThis               GUID of device to create the playback interface for.
     512 * @param   ppDSC               Where to store the created interface. Optional.
     513 */
     514static HRESULT directSoundPlayInterfaceCreate(LPCGUID pGUID, LPDIRECTSOUND8 *ppDS)
     515{
     516    /* pGUID can be NULL, if this is the default device. */
     517    /* ppDS is optional. */
    539518
    540519    LogFlowFuncEnter();
    541520
     521    LPDIRECTSOUND8 pDS;
    542522    HRESULT hr = CoCreateInstance(CLSID_DirectSound8, NULL, CLSCTX_ALL,
    543                                   IID_IDirectSound8, (void **)&pThis->pDS);
     523                                  IID_IDirectSound8, (void **)&pDS);
    544524    if (FAILED(hr))
    545525    {
     
    548528    else
    549529    {
    550         hr = IDirectSound8_Initialize(pThis->pDS, pThis->Cfg.pGuidPlay);
     530        hr = IDirectSound8_Initialize(pDS, pGUID);
    551531        if (SUCCEEDED(hr))
    552532        {
    553533            HWND hWnd = GetDesktopWindow();
    554             hr = IDirectSound8_SetCooperativeLevel(pThis->pDS, hWnd, DSSCL_PRIORITY);
     534            hr = IDirectSound8_SetCooperativeLevel(pDS, hWnd, DSSCL_PRIORITY);
    555535            if (FAILED(hr))
    556536                DSLOGREL(("DSound: Setting cooperative level for window %p failed with %Rhrc\n", hWnd, hr));
     
    564544                DSLOGREL(("DSound: DirectSound playback initialization failed with %Rhrc\n", hr));
    565545
    566             directSoundPlayInterfaceDestroy(pThis);
     546            directSoundPlayInterfaceDestroy(pDS);
     547        }
     548        else if (ppDS)
     549        {
     550            *ppDS = pDS;
    567551        }
    568552    }
     
    656640    dsoundUpdateStatusInternal(pThis);
    657641
    658     HRESULT hr = directSoundPlayInterfaceCreate(pThis);
     642    HRESULT hr = directSoundPlayInterfaceCreate(pThis->Cfg.pGuidPlay, &pThis->pDS);
    659643    if (FAILED(hr))
    660644        return hr;
     
    11531137    if (!pGUID)
    11541138    {
    1155         PDSOUNDDEV pDev = NULL;
     1139        PPDMAUDIODEVICE pDev = NULL;
    11561140
    11571141        switch (pCfg->DestSource.Source)
     
    11671151            case PDMAUDIORECSOURCE_MIC:
    11681152            {
    1169                 RTListForEach(&pThis->lstDevInput, pDev, DSOUNDDEV, Node)
    1170                 {
    1171                     if (RTStrIStr(pDev->pszName, "Mic")) /** @todo What is with non en_us windows versions? */
    1172                         break;
    1173                 }
    1174 
    1175                 if (RTListNodeIsDummy(&pThis->lstDevInput, pDev, DSOUNDDEV, Node))
    1176                     pDev = NULL; /* Found nothing. */
    1177 
     1153                pDev = DrvAudioHlpDeviceEnumGetDefaultDevice(&pThis->DeviceEnum, PDMAUDIODIR_IN);
    11781154                break;
    11791155            }
     
    11881164        {
    11891165            DSLOG(("DSound: Guest source '%s' is using host recording device '%s'\n",
    1190                    DrvAudioHlpRecSrcToStr(pCfg->DestSource.Source), pDev->pszName));
    1191 
    1192             pGUID = &pDev->Guid;
     1166                   DrvAudioHlpRecSrcToStr(pCfg->DestSource.Source), pDev->szName));
     1167
     1168            PDSOUNDDEV pDSoundDev = (PDSOUNDDEV )pDev->pvData;
     1169            AssertPtr(pDSoundDev);
     1170
     1171            pGUID = &pDSoundDev->Guid;
    11931172        }
    11941173    }
     
    13061285
    13071286/**
    1308  * Destroys the DirectSound capturing interface.
     1287 * Destroys a DirectSound capture interface.
    13091288 *
    1310  * @return  IPRT status code.
    1311  * @param   pThis               Driver instance to destroy capturing interface for.
    1312  */
    1313 static void directSoundCaptureInterfaceDestroy(PDRVHOSTDSOUND pThis)
    1314 {
    1315     if (pThis->pDSC)
     1289 * @param   pDSC                Capture interface to destroy.
     1290 */
     1291static void directSoundCaptureInterfaceDestroy(LPDIRECTSOUNDCAPTURE8 pDSC)
     1292{
     1293    if (pDSC)
    13161294    {
    13171295        LogFlowFuncEnter();
    13181296
    1319         IDirectSoundCapture_Release(pThis->pDSC);
    1320         pThis->pDSC = NULL;
    1321     }
    1322 }
    1323 
    1324 /**
    1325  * Creates the DirectSound capturing interface.
     1297        IDirectSoundCapture_Release(pDSC);
     1298        pDSC = NULL;
     1299    }
     1300}
     1301
     1302/**
     1303 * Creates a DirectSound capture interface.
    13261304 *
    1327  * @return  IPRT status code.
    1328  * @param   pThis               Driver instance to create the capturing interface for.
    1329  * @param   pCfg                Audio stream to use for creating the capturing interface.
    1330  */
    1331 static HRESULT directSoundCaptureInterfaceCreate(PDRVHOSTDSOUND pThis, PPDMAUDIOSTREAMCFG pCfg)
    1332 {
    1333     AssertPtrReturn(pThis,     E_POINTER);
    1334     AssertPtrReturn(pCfg,      E_POINTER);
    1335 
    1336     if (pThis->pDSC)
    1337         return S_OK;
     1305 * @return  HRESULT
     1306 * @param   pGUID               GUID of device to create the capture interface for.
     1307 * @param   ppDSC               Where to store the created interface. Optional.
     1308 */
     1309static HRESULT directSoundCaptureInterfaceCreate(LPCGUID pGUID, LPDIRECTSOUNDCAPTURE8 *ppDSC)
     1310{
     1311    /* pGUID can be NULL, if this is the default device. */
     1312    /* ppDSC is optional. */
    13381313
    13391314    LogFlowFuncEnter();
    13401315
     1316    LPDIRECTSOUNDCAPTURE8 pDSC;
    13411317    HRESULT hr = CoCreateInstance(CLSID_DirectSoundCapture8, NULL, CLSCTX_ALL,
    1342                                   IID_IDirectSoundCapture8, (void **)&pThis->pDSC);
     1318                                  IID_IDirectSoundCapture8, (void **)&pDSC);
    13431319    if (FAILED(hr))
    13441320    {
     
    13471323    else
    13481324    {
    1349         LPCGUID pGUID = dsoundCaptureSelectDevice(pThis, pCfg);
    1350         /* pGUID can be NULL when using the default device. */
    1351 
    1352         hr = IDirectSoundCapture_Initialize(pThis->pDSC, pGUID);
     1325        hr = IDirectSoundCapture_Initialize(pDSC, pGUID);
    13531326        if (FAILED(hr))
    13541327        {
     
    13581331                DSLOGREL(("DSound: Initializing capturing device failed with %Rhrc\n", hr));
    13591332
    1360             directSoundCaptureInterfaceDestroy(pThis);
     1333            directSoundCaptureInterfaceDestroy(pDSC);
     1334        }
     1335        else if (ppDSC)
     1336        {
     1337            *ppDSC = pDSC;
    13611338        }
    13621339    }
     
    14131390        return E_INVALIDARG;
    14141391
    1415     dsoundUpdateStatusInternalEx(pThis, NULL /* Cfg */, DSOUNDENUMCBFLAGS_LOG /* fEnum */);
    1416 
    1417     HRESULT hr = directSoundCaptureInterfaceCreate(pThis, pCfgReq);
     1392    dsoundUpdateStatusInternal(pThis);
     1393
     1394    HRESULT hr = directSoundCaptureInterfaceCreate(pThis->Cfg.pGuidCapture, &pThis->pDSC);
    14181395    if (FAILED(hr))
    14191396        return hr;
     
    15931570}
    15941571
    1595 static int dsoundDevAdd(PRTLISTANCHOR pList, LPGUID pGUID, LPCWSTR pwszDescription, PDSOUNDDEV *ppDev)
    1596 {
    1597     AssertPtrReturn(pList, VERR_INVALID_POINTER);
    1598     AssertPtrReturn(pGUID, VERR_INVALID_POINTER);
    1599     AssertPtrReturn(pwszDescription, VERR_INVALID_POINTER);
    1600 
    1601     PDSOUNDDEV pDev = (PDSOUNDDEV)RTMemAlloc(sizeof(DSOUNDDEV));
    1602     if (!pDev)
    1603         return VERR_NO_MEMORY;
    1604 
    1605     int rc = RTUtf16ToUtf8(pwszDescription, &pDev->pszName);
    1606     if (   RT_SUCCESS(rc)
    1607         && pGUID)
    1608     {
    1609         memcpy(&pDev->Guid, pGUID, sizeof(GUID));
    1610     }
    1611 
    1612     if (RT_SUCCESS(rc))
    1613         RTListAppend(pList, &pDev->Node);
    1614 
    1615     if (ppDev)
    1616         *ppDev = pDev;
    1617 
    1618     return rc;
    1619 }
    1620 
    1621 static void dsoundDeviceRemove(PDSOUNDDEV pDev)
    1622 {
    1623     if (pDev)
    1624     {
    1625         if (pDev->pszName)
    1626         {
    1627             RTStrFree(pDev->pszName);
    1628             pDev->pszName = NULL;
    1629         }
    1630 
    1631         RTListNodeRemove(&pDev->Node);
    1632 
    1633         RTMemFree(pDev);
    1634         pDev = NULL;
    1635     }
    1636 }
    1637 
    1638 static void dsoundLogDevice(const char *pszType, LPGUID pGUID, LPCWSTR pwszDescription, LPCWSTR pwszModule)
    1639 {
    1640     char *pszGUID = dsoundGUIDToUtf8StrA(pGUID);
    1641     /* This always has to be in the release log.
    1642      * Only print this when we're running in verbose (audio debug) mode, as this can generate a lot of content. */
    1643     LogRel2(("DSound: %s: GUID: %s [%ls] (Module: %ls)\n", pszType, pszGUID ? pszGUID : "{?}", pwszDescription, pwszModule));
    1644     RTStrFree(pszGUID);
    1645 }
    1646 
     1572/**
     1573 * Callback for the playback device enumeration.
     1574 *
     1575 * @return  TRUE if continuing enumeration, FALSE if not.
     1576 * @param   pGUID               Pointer to GUID of enumerated device. Can be NULL.
     1577 * @param   pwszDescription     Pointer to (friendly) description of enumerated device.
     1578 * @param   pwszModule          Pointer to module name of enumerated device.
     1579 * @param   lpContext           Pointer to PDSOUNDENUMCBCTX context for storing the enumerated information.
     1580 */
    16471581static BOOL CALLBACK dsoundDevicesEnumCbPlayback(LPGUID pGUID, LPCWSTR pwszDescription, LPCWSTR pwszModule, PVOID lpContext)
    16481582{
    1649     PDSOUNDENUMCBCTX pCtx = (PDSOUNDENUMCBCTX)lpContext;
    1650     AssertPtrReturn(pCtx, FALSE);
    1651     AssertPtrReturn(pCtx->pDrv, FALSE);
    1652 
    1653     if (!pGUID)
    1654         return TRUE;
    1655 
     1583    RT_NOREF(pwszModule);
     1584
     1585    PDSOUNDENUMCBCTX pEnumCtx = (PDSOUNDENUMCBCTX)lpContext;
     1586    AssertPtrReturn(pEnumCtx , FALSE);
     1587
     1588    PPDMAUDIODEVICEENUM pDevEnm = pEnumCtx->pDevEnm;
     1589    AssertPtrReturn(pDevEnm, FALSE);
     1590
     1591    /* pGUID can be NULL for default device(s). */
    16561592    AssertPtrReturn(pwszDescription, FALSE);
    16571593    /* Do not care about pwszModule. */
    16581594
    1659     if (pCtx->fFlags & DSOUNDENUMCBFLAGS_LOG)
    1660         dsoundLogDevice("Output", pGUID, pwszDescription, pwszModule);
    1661 
    1662     int rc = dsoundDevAdd(&pCtx->pDrv->lstDevOutput,
    1663                           pGUID, pwszDescription, NULL /* ppDev */);
     1595    int rc;
     1596
     1597    PPDMAUDIODEVICE pDev = DrvAudioHlpDeviceAlloc(sizeof(DSOUNDDEV));
     1598    if (pDev)
     1599    {
     1600        pDev->enmUsage = PDMAUDIODIR_OUT;
     1601        pDev->enmType  = PDMAUDIODEVICETYPE_BUILTIN;
     1602
     1603        if (pGUID == NULL)
     1604            pDev->fFlags = PDMAUDIODEV_FLAGS_DEFAULT;
     1605
     1606        char *pszName;
     1607        rc = RTUtf16ToUtf8(pwszDescription, &pszName);
     1608        if (RT_SUCCESS(rc))
     1609        {
     1610            RTStrCopy(pDev->szName, sizeof(pDev->szName), pszName);
     1611            RTStrFree(pszName);
     1612
     1613            PDSOUNDDEV pDSoundDev = (PDSOUNDDEV)pDev->pvData;
     1614
     1615            if (pGUID)
     1616                memcpy(&pDSoundDev->Guid, pGUID, sizeof(GUID));
     1617
     1618            LPDIRECTSOUND8 pDS;
     1619            HRESULT hr = directSoundPlayInterfaceCreate(pGUID, &pDS);
     1620            if (SUCCEEDED(hr))
     1621            {
     1622                do
     1623                {
     1624                    DSCAPS DSCaps;
     1625                    RT_ZERO(DSCaps);
     1626                    DSCaps.dwSize = sizeof(DSCAPS);
     1627                    hr = IDirectSound_GetCaps(pDS, &DSCaps);
     1628                    if (FAILED(hr))
     1629                        break;
     1630
     1631                    pDev->cMaxOutputChannels = DSCaps.dwFlags & DSCAPS_PRIMARYSTEREO ? 2 : 1;
     1632
     1633                    DWORD dwSpeakerCfg;
     1634                    hr = IDirectSound_GetSpeakerConfig(pDS, &dwSpeakerCfg);
     1635                    if (FAILED(hr))
     1636                        break;
     1637
     1638                    unsigned uSpeakerCount = 0;
     1639                    switch (DSSPEAKER_CONFIG(dwSpeakerCfg))
     1640                    {
     1641                        case DSSPEAKER_MONO:             uSpeakerCount = 1; break;
     1642                        case DSSPEAKER_HEADPHONE:        uSpeakerCount = 2; break;
     1643                        case DSSPEAKER_STEREO:           uSpeakerCount = 2; break;
     1644                        case DSSPEAKER_QUAD:             uSpeakerCount = 4; break;
     1645                        case DSSPEAKER_SURROUND:         uSpeakerCount = 4; break;
     1646                        case DSSPEAKER_5POINT1:          uSpeakerCount = 6; break;
     1647                        case DSSPEAKER_5POINT1_SURROUND: uSpeakerCount = 6; break;
     1648                        case DSSPEAKER_7POINT1:          uSpeakerCount = 8; break;
     1649                        case DSSPEAKER_7POINT1_SURROUND: uSpeakerCount = 8; break;
     1650                        default:                                            break;
     1651                    }
     1652
     1653                    if (uSpeakerCount) /* Do we need to update the channel count? */
     1654                        pDev->cMaxOutputChannels = uSpeakerCount;
     1655
     1656                } while (0);
     1657
     1658                directSoundPlayInterfaceDestroy(pDS);
     1659
     1660                rc = VINF_SUCCESS;
     1661            }
     1662            else
     1663                rc = VERR_GENERAL_FAILURE;
     1664
     1665            if (RT_SUCCESS(rc))
     1666                rc = DrvAudioHlpDeviceEnumAdd(pDevEnm, pDev);
     1667        }
     1668    }
     1669    else
     1670        rc = VERR_NO_MEMORY;
     1671
    16641672    if (RT_FAILURE(rc))
     1673    {
     1674        LogRel(("DSound: Error enumeration playback device '%ls', rc=%Rrc\n", pwszDescription, rc));
    16651675        return FALSE; /* Abort enumeration. */
    1666 
    1667     pCtx->cDevOut++;
     1676    }
    16681677
    16691678    return TRUE;
    16701679}
    16711680
     1681/**
     1682 * Callback for the capture device enumeration.
     1683 *
     1684 * @return  TRUE if continuing enumeration, FALSE if not.
     1685 * @param   pGUID               Pointer to GUID of enumerated device. Can be NULL.
     1686 * @param   pwszDescription     Pointer to (friendly) description of enumerated device.
     1687 * @param   pwszModule          Pointer to module name of enumerated device.
     1688 * @param   lpContext           Pointer to PDSOUNDENUMCBCTX context for storing the enumerated information.
     1689 */
    16721690static BOOL CALLBACK dsoundDevicesEnumCbCapture(LPGUID pGUID, LPCWSTR pwszDescription, LPCWSTR pwszModule, PVOID lpContext)
    16731691{
    1674     PDSOUNDENUMCBCTX pCtx = (PDSOUNDENUMCBCTX)lpContext;
    1675     AssertPtrReturn(pCtx, FALSE);
    1676     AssertPtrReturn(pCtx->pDrv, FALSE);
    1677 
    1678     if (!pGUID)
    1679         return TRUE;
    1680 
    1681     if (pCtx->fFlags & DSOUNDENUMCBFLAGS_LOG)
    1682         dsoundLogDevice("Input", pGUID, pwszDescription, pwszModule);
    1683 
    1684     int rc = dsoundDevAdd(&pCtx->pDrv->lstDevInput,
    1685                           pGUID, pwszDescription, NULL /* ppDev */);
     1692    RT_NOREF(pwszModule);
     1693
     1694    PDSOUNDENUMCBCTX pEnumCtx = (PDSOUNDENUMCBCTX )lpContext;
     1695    AssertPtrReturn(pEnumCtx , FALSE);
     1696
     1697    PPDMAUDIODEVICEENUM pDevEnm = pEnumCtx->pDevEnm;
     1698    AssertPtrReturn(pDevEnm, FALSE);
     1699
     1700    /* pGUID can be NULL for default device(s). */
     1701    AssertPtrReturn(pwszDescription, FALSE);
     1702    /* Do not care about pwszModule. */
     1703
     1704    int rc;
     1705
     1706    PPDMAUDIODEVICE pDev = DrvAudioHlpDeviceAlloc(sizeof(DSOUNDDEV));
     1707    if (pDev)
     1708    {
     1709        pDev->enmUsage = PDMAUDIODIR_IN;
     1710        pDev->enmType  = PDMAUDIODEVICETYPE_BUILTIN;
     1711
     1712        char *pszName;
     1713        rc = RTUtf16ToUtf8(pwszDescription, &pszName);
     1714        if (RT_SUCCESS(rc))
     1715        {
     1716            RTStrCopy(pDev->szName, sizeof(pDev->szName), pszName);
     1717            RTStrFree(pszName);
     1718
     1719            PDSOUNDDEV pDSoundDev = (PDSOUNDDEV)pDev->pvData;
     1720
     1721            if (pGUID)
     1722                memcpy(&pDSoundDev->Guid, pGUID, sizeof(GUID));
     1723
     1724            LPDIRECTSOUNDCAPTURE8 pDSC;
     1725            HRESULT hr = directSoundCaptureInterfaceCreate(pGUID, &pDSC);
     1726            if (SUCCEEDED(hr))
     1727            {
     1728                do
     1729                {
     1730                    DSCCAPS DSCCaps;
     1731                    RT_ZERO(DSCCaps);
     1732                    DSCCaps.dwSize = sizeof(DSCCAPS);
     1733                    hr = IDirectSoundCapture_GetCaps(pDSC, &DSCCaps);
     1734                    if (FAILED(hr))
     1735                        break;
     1736
     1737                    pDev->cMaxInputChannels = DSCCaps.dwChannels;
     1738
     1739                } while (0);
     1740
     1741                directSoundCaptureInterfaceDestroy(pDSC);
     1742
     1743                rc = VINF_SUCCESS;
     1744            }
     1745            else
     1746                rc = VERR_GENERAL_FAILURE;
     1747
     1748            if (RT_SUCCESS(rc))
     1749                rc = DrvAudioHlpDeviceEnumAdd(pDevEnm, pDev);
     1750        }
     1751    }
     1752    else
     1753        rc = VERR_NO_MEMORY;
     1754
    16861755    if (RT_FAILURE(rc))
     1756    {
     1757        LogRel(("DSound: Error enumeration capture device '%ls', rc=%Rrc\n", pwszDescription, rc));
    16871758        return FALSE; /* Abort enumeration. */
    1688 
    1689     pCtx->cDevIn++;
     1759    }
    16901760
    16911761    return TRUE;
     
    16971767 * @return  IPRT status code.
    16981768 * @param   pThis               Host audio driver instance.
    1699  * @param   pEnmCtx             Enumeration context to use.
    1700  * @param   fEnum               Enumeration flags.
    1701  */
    1702 static int dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PDSOUNDENUMCBCTX pEnmCtx, uint32_t fEnum)
    1703 {
    1704     AssertPtrReturn(pThis,   VERR_INVALID_POINTER);
    1705     AssertPtrReturn(pEnmCtx, VERR_INVALID_POINTER);
    1706 
    1707     dsoundDevicesClear(pThis);
     1769 * @param   pDevEnm             Where to store the enumerated devices.
     1770 */
     1771static int dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PPDMAUDIODEVICEENUM pDevEnm)
     1772{
     1773    AssertPtrReturn(pThis,    VERR_INVALID_POINTER);
     1774
     1775    DSLOG(("DSound: Enumerating devices ...\n"));
    17081776
    17091777    RTLDRMOD hDSound = NULL;
     
    17111779    if (RT_SUCCESS(rc))
    17121780    {
     1781        DSOUNDENUMCBCTX EnumCtx;
     1782        EnumCtx.fFlags  = 0;
     1783        EnumCtx.pDevEnm = pDevEnm;
     1784
    17131785        PFNDIRECTSOUNDENUMERATEW pfnDirectSoundEnumerateW = NULL;
    1714         PFNDIRECTSOUNDCAPTUREENUMERATEW pfnDirectSoundCaptureEnumerateW = NULL;
    1715 
    17161786        rc = RTLdrGetSymbol(hDSound, "DirectSoundEnumerateW", (void**)&pfnDirectSoundEnumerateW);
    17171787        if (RT_SUCCESS(rc))
    1718             rc = RTLdrGetSymbol(hDSound, "DirectSoundCaptureEnumerateW", (void**)&pfnDirectSoundCaptureEnumerateW);
    1719 
     1788        {
     1789            HRESULT hr = pfnDirectSoundEnumerateW(&dsoundDevicesEnumCbPlayback, &EnumCtx);
     1790            if (FAILED(hr))
     1791                LogRel(("DSound: Error enumerating host playback devices: %Rhrc\n", hr));
     1792        }
     1793        else
     1794            LogRel(("DSound: Error starting to enumerate host playback devices: %Rrc\n", rc));
     1795
     1796        PFNDIRECTSOUNDCAPTUREENUMERATEW pfnDirectSoundCaptureEnumerateW = NULL;
     1797        rc = RTLdrGetSymbol(hDSound, "DirectSoundCaptureEnumerateW", (void**)&pfnDirectSoundCaptureEnumerateW);
    17201798        if (RT_SUCCESS(rc))
    17211799        {
    1722             HRESULT hr = pfnDirectSoundEnumerateW(&dsoundDevicesEnumCbPlayback, pEnmCtx);
     1800            HRESULT hr = pfnDirectSoundCaptureEnumerateW(&dsoundDevicesEnumCbCapture, &EnumCtx);
    17231801            if (FAILED(hr))
    1724                 LogRel2(("DSound: Error enumerating host playback devices: %Rhrc\n", hr));
    1725 
    1726             hr = pfnDirectSoundCaptureEnumerateW(&dsoundDevicesEnumCbCapture, pEnmCtx);
    1727             if (FAILED(hr))
    1728                 LogRel2(("DSound: Error enumerating host capturing devices: %Rhrc\n", hr));
    1729 
    1730             if (fEnum & DSOUNDENUMCBFLAGS_LOG)
    1731             {
    1732                 LogRel2(("DSound: Found %RU8 host playback devices\n",  pEnmCtx->cDevOut));
    1733                 LogRel2(("DSound: Found %RU8 host capturing devices\n", pEnmCtx->cDevIn));
    1734             }
    1735         }
     1802                LogRel(("DSound: Error enumerating host capture devices: %Rhrc\n", hr));
     1803        }
     1804        else
     1805            LogRel(("DSound: Error starting to enumerate host capture devices: %Rrc\n", rc));
    17361806
    17371807        RTLdrClose(hDSound);
     
    17401810    {
    17411811        /* No dsound.dll on this system. */
    1742         LogRel2(("DSound: Could not load dsound.dll: %Rrc\n", rc));
    1743     }
     1812        LogRel(("DSound: Could not load dsound.dll: %Rrc\n", rc));
     1813    }
     1814
     1815    DSLOG(("DSound: Enumerating devices done\n"));
    17441816
    17451817    return rc;
     
    17511823 *
    17521824 * @param   pThis               Host audio driver instance.
    1753  * @param   pCfg                Where to store the backend configuration. Optional.
    1754  * @param   fEnum               Enumeration flags.
    1755  */
    1756 static void dsoundUpdateStatusInternalEx(PDRVHOSTDSOUND pThis, PPDMAUDIOBACKENDCFG pCfg, uint32_t fEnum)
     1825 */
     1826static void dsoundUpdateStatusInternal(PDRVHOSTDSOUND pThis)
    17571827{
    17581828    AssertPtrReturnVoid(pThis);
    17591829    /* pCfg is optional. */
    17601830
    1761     PDMAUDIOBACKENDCFG Cfg;
    1762     RT_ZERO(Cfg);
    1763 
    1764     Cfg.cbStreamOut = sizeof(DSOUNDSTREAM);
    1765     Cfg.cbStreamIn  = sizeof(DSOUNDSTREAM);
    1766 
    1767     DSOUNDENUMCBCTX cbCtx = { pThis, fEnum, 0, 0 };
    1768 
    1769     int rc = dsoundDevicesEnumerate(pThis, &cbCtx, fEnum);
     1831    LogFlowFuncEnter();
     1832
     1833    int rc = dsoundDevicesEnumerate(pThis, &pThis->DeviceEnum);
    17701834    if (RT_SUCCESS(rc))
    17711835    {
     
    17781842        }
    17791843#endif
    1780         pThis->fEnabledOut = RT_BOOL(cbCtx.cDevOut);
    1781         pThis->fEnabledIn  = RT_BOOL(cbCtx.cDevIn);
    1782 
    1783         RTStrPrintf2(Cfg.szName, sizeof(Cfg.szName), "DirectSound audio driver");
    1784 
    1785         Cfg.cMaxStreamsIn  = UINT32_MAX;
    1786         Cfg.cMaxStreamsOut = UINT32_MAX;
    1787 
    1788         if (pCfg)
    1789             memcpy(pCfg, &Cfg, sizeof(PDMAUDIOBACKENDCFG));
     1844        pThis->fEnabledIn  = RT_BOOL(DrvAudioHlpDeviceEnumGetDeviceCount(&pThis->DeviceEnum, PDMAUDIODIR_IN));
     1845        pThis->fEnabledOut = RT_BOOL(DrvAudioHlpDeviceEnumGetDeviceCount(&pThis->DeviceEnum, PDMAUDIODIR_OUT));
    17901846    }
    17911847
    17921848    LogFlowFuncLeaveRC(rc);
    1793 }
    1794 
    1795 static void dsoundUpdateStatusInternal(PDRVHOSTDSOUND pThis)
    1796 {
    1797     dsoundUpdateStatusInternalEx(pThis, NULL /* pCfg */, 0 /* fEnum */);
    17981849}
    17991850
     
    21252176int drvHostDSoundGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg)
    21262177{
     2178    RT_NOREF(pInterface);
    21272179    AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
    21282180    AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER);
    21292181
     2182    RT_BZERO(pBackendCfg, sizeof(PPDMAUDIOBACKENDCFG));
     2183
     2184    pBackendCfg->cbStreamOut = sizeof(DSOUNDSTREAM);
     2185    pBackendCfg->cbStreamIn  = sizeof(DSOUNDSTREAM);
     2186
     2187    RTStrPrintf2(pBackendCfg->szName, sizeof(pBackendCfg->szName), "DirectSound audio driver");
     2188
     2189    pBackendCfg->cMaxStreamsIn  = UINT32_MAX;
     2190    pBackendCfg->cMaxStreamsOut = UINT32_MAX;
     2191
     2192    return VINF_SUCCESS;
     2193}
     2194
     2195/**
     2196 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetDevices}
     2197 */
     2198static DECLCALLBACK(int) drvHostDSoundGetDevices(PPDMIHOSTAUDIO pInterface, PPDMAUDIODEVICEENUM pDeviceEnum)
     2199{
     2200    AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
     2201    AssertPtrReturn(pDeviceEnum, VERR_INVALID_POINTER);
     2202
    21302203    PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);
    21312204
    2132     dsoundUpdateStatusInternalEx(pThis, pBackendCfg, 0 /* fEnum */);
    2133 
    2134     return VINF_SUCCESS;
     2205    int rc = RTCritSectEnter(&pThis->CritSect);
     2206    if (RT_SUCCESS(rc))
     2207    {
     2208        rc = DrvAudioHlpDeviceEnumInit(pDeviceEnum);
     2209        if (RT_SUCCESS(rc))
     2210        {
     2211            rc = dsoundDevicesEnumerate(pThis, pDeviceEnum);
     2212            if (RT_FAILURE(rc))
     2213                DrvAudioHlpDeviceEnumFree(pDeviceEnum);
     2214        }
     2215
     2216        int rc2 = RTCritSectLeave(&pThis->CritSect);
     2217        AssertRC(rc2);
     2218    }
     2219
     2220    LogFlowFunc(("Returning %Rrc\n", rc));
     2221    return rc;
    21352222}
    21362223
     
    21682255        rc = VINF_SUCCESS;
    21692256
    2170         dsoundUpdateStatusInternalEx(pThis, NULL /* pCfg */, DSOUNDENUMCBFLAGS_LOG /* fEnum */);
     2257        dsoundUpdateStatusInternal(pThis);
    21712258    }
    21722259    else
     
    25042591    }
    25052592#endif
     2593
     2594    DrvAudioHlpDeviceEnumFree(&pThis->DeviceEnum);
    25062595
    25072596    if (pThis->pDrvIns)
     
    25442633    pThis->IHostAudio.pfnStreamGetPending  = drvHostDSoundStreamGetPending;
    25452634
     2635    /* This backend supports device enumeration. */
     2636    pThis->IHostAudio.pfnGetDevices  = drvHostDSoundGetDevices;
     2637
    25462638#ifdef VBOX_WITH_AUDIO_CALLBACKS
    25472639    /* This backend supports host audio callbacks. */
     
    25532645     * Init the static parts.
    25542646     */
    2555     RTListInit(&pThis->lstDevInput);
    2556     RTListInit(&pThis->lstDevOutput);
     2647    DrvAudioHlpDeviceEnumInit(&pThis->DeviceEnum);
    25572648
    25582649    pThis->fEnabledIn  = false;
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