Changeset 77028 in vbox
- Timestamp:
- Jan 29, 2019 12:26:30 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 128461
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp
r76992 r77028 177 177 } DSOUNDSTREAM, *PDSOUNDSTREAM; 178 178 179 /** 180 * Structure for keeping a DirectSound-specific device entry. 181 * This is then bound to the PDMAUDIODEVICE's pvData area. 182 */ 183 typedef struct DSOUNDDEV 184 { 185 GUID Guid; 186 } DSOUNDDEV, *PDSOUNDDEV; 187 188 /** 189 * Structure for holding a device enumeration context. 190 */ 191 typedef struct DSOUNDENUMCBCTX 192 { 193 /** Enumeration flags. */ 194 uint32_t fFlags; 195 /** Pointer to device list to populate. */ 196 PPDMAUDIODEVICEENUM pDevEnm; 197 } DSOUNDENUMCBCTX, *PDSOUNDENUMCBCTX; 198 179 199 typedef struct DRVHOSTDSOUND 180 200 { … … 185 205 /** Critical section to serialize access. */ 186 206 RTCRITSECT CritSect; 187 /** List of found host input devices. */188 RTLISTANCHOR lstDevInput;189 /** List of found host output devices. */190 RTLISTANCHOR lstDevOutput;191 207 /** DirectSound configuration options. */ 192 208 DSOUNDHOSTCFG Cfg; 209 /** List of devices of last enumeration. */ 210 PDMAUDIODEVICEENUM DeviceEnum; 193 211 /** Whether this backend supports any audio input. */ 194 212 bool fEnabledIn; … … 213 231 } DRVHOSTDSOUND, *PDRVHOSTDSOUND; 214 232 215 /** No flags specified. */216 #define DSOUNDENUMCBFLAGS_NONE 0217 /** (Release) log found devices. */218 #define DSOUNDENUMCBFLAGS_LOG RT_BIT(0)219 220 /**221 * Callback context for enumeration callbacks222 */223 typedef struct DSOUNDENUMCBCTX224 {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 DSOUNDDEV236 {237 RTLISTNODE Node;238 char *pszName;239 GUID Guid;240 } DSOUNDDEV, *PDSOUNDDEV;241 242 243 233 /********************************************************************************************************************************* 244 234 * Internal Functions * … … 249 239 static HRESULT directSoundCaptureStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fFlush); 250 240 251 static void dsoundDeviceRemove(PDSOUNDDEV pDev); 252 static int dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PPDMAUDIOBACKENDCFG pCfg); 241 static int dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PDMAUDIODEVICEENUM pDevEnm, uint32_t fEnum); 253 242 254 243 static int dsoundStreamEnable(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS, bool fEnable); 255 244 static void dsoundStreamReset(PDRVHOSTDSOUND pThis, PDSOUNDSTREAM pStreamDS); 256 245 static void dsoundUpdateStatusInternal(PDRVHOSTDSOUND pThis); 257 static void dsoundUpdateStatusInternalEx(PDRVHOSTDSOUND pThis, PPDMAUDIOBACKENDCFG pCfg, uint32_t fEnum);258 246 259 247 … … 379 367 380 368 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));402 369 } 403 370 … … 522 489 */ 523 490 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 */ 496 static void directSoundPlayInterfaceDestroy(LPDIRECTSOUND8 pDS) 497 { 498 if (pDS) 527 499 { 528 500 LogFlowFuncEnter(); 529 501 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 */ 514 static HRESULT directSoundPlayInterfaceCreate(LPCGUID pGUID, LPDIRECTSOUND8 *ppDS) 515 { 516 /* pGUID can be NULL, if this is the default device. */ 517 /* ppDS is optional. */ 539 518 540 519 LogFlowFuncEnter(); 541 520 521 LPDIRECTSOUND8 pDS; 542 522 HRESULT hr = CoCreateInstance(CLSID_DirectSound8, NULL, CLSCTX_ALL, 543 IID_IDirectSound8, (void **)&p This->pDS);523 IID_IDirectSound8, (void **)&pDS); 544 524 if (FAILED(hr)) 545 525 { … … 548 528 else 549 529 { 550 hr = IDirectSound8_Initialize(p This->pDS, pThis->Cfg.pGuidPlay);530 hr = IDirectSound8_Initialize(pDS, pGUID); 551 531 if (SUCCEEDED(hr)) 552 532 { 553 533 HWND hWnd = GetDesktopWindow(); 554 hr = IDirectSound8_SetCooperativeLevel(p This->pDS, hWnd, DSSCL_PRIORITY);534 hr = IDirectSound8_SetCooperativeLevel(pDS, hWnd, DSSCL_PRIORITY); 555 535 if (FAILED(hr)) 556 536 DSLOGREL(("DSound: Setting cooperative level for window %p failed with %Rhrc\n", hWnd, hr)); … … 564 544 DSLOGREL(("DSound: DirectSound playback initialization failed with %Rhrc\n", hr)); 565 545 566 directSoundPlayInterfaceDestroy(pThis); 546 directSoundPlayInterfaceDestroy(pDS); 547 } 548 else if (ppDS) 549 { 550 *ppDS = pDS; 567 551 } 568 552 } … … 656 640 dsoundUpdateStatusInternal(pThis); 657 641 658 HRESULT hr = directSoundPlayInterfaceCreate(pThis );642 HRESULT hr = directSoundPlayInterfaceCreate(pThis->Cfg.pGuidPlay, &pThis->pDS); 659 643 if (FAILED(hr)) 660 644 return hr; … … 1153 1137 if (!pGUID) 1154 1138 { 1155 P DSOUNDDEVpDev = NULL;1139 PPDMAUDIODEVICE pDev = NULL; 1156 1140 1157 1141 switch (pCfg->DestSource.Source) … … 1167 1151 case PDMAUDIORECSOURCE_MIC: 1168 1152 { 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); 1178 1154 break; 1179 1155 } … … 1188 1164 { 1189 1165 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; 1193 1172 } 1194 1173 } … … 1306 1285 1307 1286 /** 1308 * Destroys the DirectSound capturinginterface.1287 * Destroys a DirectSound capture interface. 1309 1288 * 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 */ 1291 static void directSoundCaptureInterfaceDestroy(LPDIRECTSOUNDCAPTURE8 pDSC) 1292 { 1293 if (pDSC) 1316 1294 { 1317 1295 LogFlowFuncEnter(); 1318 1296 1319 IDirectSoundCapture_Release(p This->pDSC);1320 p This->pDSC = NULL;1321 } 1322 } 1323 1324 /** 1325 * Creates the DirectSound capturinginterface.1297 IDirectSoundCapture_Release(pDSC); 1298 pDSC = NULL; 1299 } 1300 } 1301 1302 /** 1303 * Creates a DirectSound capture interface. 1326 1304 * 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 */ 1309 static HRESULT directSoundCaptureInterfaceCreate(LPCGUID pGUID, LPDIRECTSOUNDCAPTURE8 *ppDSC) 1310 { 1311 /* pGUID can be NULL, if this is the default device. */ 1312 /* ppDSC is optional. */ 1338 1313 1339 1314 LogFlowFuncEnter(); 1340 1315 1316 LPDIRECTSOUNDCAPTURE8 pDSC; 1341 1317 HRESULT hr = CoCreateInstance(CLSID_DirectSoundCapture8, NULL, CLSCTX_ALL, 1342 IID_IDirectSoundCapture8, (void **)&p This->pDSC);1318 IID_IDirectSoundCapture8, (void **)&pDSC); 1343 1319 if (FAILED(hr)) 1344 1320 { … … 1347 1323 else 1348 1324 { 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); 1353 1326 if (FAILED(hr)) 1354 1327 { … … 1358 1331 DSLOGREL(("DSound: Initializing capturing device failed with %Rhrc\n", hr)); 1359 1332 1360 directSoundCaptureInterfaceDestroy(pThis); 1333 directSoundCaptureInterfaceDestroy(pDSC); 1334 } 1335 else if (ppDSC) 1336 { 1337 *ppDSC = pDSC; 1361 1338 } 1362 1339 } … … 1413 1390 return E_INVALIDARG; 1414 1391 1415 dsoundUpdateStatusInternal Ex(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); 1418 1395 if (FAILED(hr)) 1419 1396 return hr; … … 1593 1570 } 1594 1571 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 */ 1647 1581 static BOOL CALLBACK dsoundDevicesEnumCbPlayback(LPGUID pGUID, LPCWSTR pwszDescription, LPCWSTR pwszModule, PVOID lpContext) 1648 1582 { 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). */ 1656 1592 AssertPtrReturn(pwszDescription, FALSE); 1657 1593 /* Do not care about pwszModule. */ 1658 1594 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 1664 1672 if (RT_FAILURE(rc)) 1673 { 1674 LogRel(("DSound: Error enumeration playback device '%ls', rc=%Rrc\n", pwszDescription, rc)); 1665 1675 return FALSE; /* Abort enumeration. */ 1666 1667 pCtx->cDevOut++; 1676 } 1668 1677 1669 1678 return TRUE; 1670 1679 } 1671 1680 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 */ 1672 1690 static BOOL CALLBACK dsoundDevicesEnumCbCapture(LPGUID pGUID, LPCWSTR pwszDescription, LPCWSTR pwszModule, PVOID lpContext) 1673 1691 { 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 1686 1755 if (RT_FAILURE(rc)) 1756 { 1757 LogRel(("DSound: Error enumeration capture device '%ls', rc=%Rrc\n", pwszDescription, rc)); 1687 1758 return FALSE; /* Abort enumeration. */ 1688 1689 pCtx->cDevIn++; 1759 } 1690 1760 1691 1761 return TRUE; … … 1697 1767 * @return IPRT status code. 1698 1768 * @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 */ 1771 static int dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PPDMAUDIODEVICEENUM pDevEnm) 1772 { 1773 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1774 1775 DSLOG(("DSound: Enumerating devices ...\n")); 1708 1776 1709 1777 RTLDRMOD hDSound = NULL; … … 1711 1779 if (RT_SUCCESS(rc)) 1712 1780 { 1781 DSOUNDENUMCBCTX EnumCtx; 1782 EnumCtx.fFlags = 0; 1783 EnumCtx.pDevEnm = pDevEnm; 1784 1713 1785 PFNDIRECTSOUNDENUMERATEW pfnDirectSoundEnumerateW = NULL; 1714 PFNDIRECTSOUNDCAPTUREENUMERATEW pfnDirectSoundCaptureEnumerateW = NULL;1715 1716 1786 rc = RTLdrGetSymbol(hDSound, "DirectSoundEnumerateW", (void**)&pfnDirectSoundEnumerateW); 1717 1787 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); 1720 1798 if (RT_SUCCESS(rc)) 1721 1799 { 1722 HRESULT hr = pfnDirectSound EnumerateW(&dsoundDevicesEnumCbPlayback, pEnmCtx);1800 HRESULT hr = pfnDirectSoundCaptureEnumerateW(&dsoundDevicesEnumCbCapture, &EnumCtx); 1723 1801 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)); 1736 1806 1737 1807 RTLdrClose(hDSound); … … 1740 1810 { 1741 1811 /* 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")); 1744 1816 1745 1817 return rc; … … 1751 1823 * 1752 1824 * @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 */ 1826 static void dsoundUpdateStatusInternal(PDRVHOSTDSOUND pThis) 1757 1827 { 1758 1828 AssertPtrReturnVoid(pThis); 1759 1829 /* pCfg is optional. */ 1760 1830 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); 1770 1834 if (RT_SUCCESS(rc)) 1771 1835 { … … 1778 1842 } 1779 1843 #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)); 1790 1846 } 1791 1847 1792 1848 LogFlowFuncLeaveRC(rc); 1793 }1794 1795 static void dsoundUpdateStatusInternal(PDRVHOSTDSOUND pThis)1796 {1797 dsoundUpdateStatusInternalEx(pThis, NULL /* pCfg */, 0 /* fEnum */);1798 1849 } 1799 1850 … … 2125 2176 int drvHostDSoundGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg) 2126 2177 { 2178 RT_NOREF(pInterface); 2127 2179 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 2128 2180 AssertPtrReturn(pBackendCfg, VERR_INVALID_POINTER); 2129 2181 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 */ 2198 static DECLCALLBACK(int) drvHostDSoundGetDevices(PPDMIHOSTAUDIO pInterface, PPDMAUDIODEVICEENUM pDeviceEnum) 2199 { 2200 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 2201 AssertPtrReturn(pDeviceEnum, VERR_INVALID_POINTER); 2202 2130 2203 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 2131 2204 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; 2135 2222 } 2136 2223 … … 2168 2255 rc = VINF_SUCCESS; 2169 2256 2170 dsoundUpdateStatusInternal Ex(pThis, NULL /* pCfg */, DSOUNDENUMCBFLAGS_LOG /* fEnum */);2257 dsoundUpdateStatusInternal(pThis); 2171 2258 } 2172 2259 else … … 2504 2591 } 2505 2592 #endif 2593 2594 DrvAudioHlpDeviceEnumFree(&pThis->DeviceEnum); 2506 2595 2507 2596 if (pThis->pDrvIns) … … 2544 2633 pThis->IHostAudio.pfnStreamGetPending = drvHostDSoundStreamGetPending; 2545 2634 2635 /* This backend supports device enumeration. */ 2636 pThis->IHostAudio.pfnGetDevices = drvHostDSoundGetDevices; 2637 2546 2638 #ifdef VBOX_WITH_AUDIO_CALLBACKS 2547 2639 /* This backend supports host audio callbacks. */ … … 2553 2645 * Init the static parts. 2554 2646 */ 2555 RTListInit(&pThis->lstDevInput); 2556 RTListInit(&pThis->lstDevOutput); 2647 DrvAudioHlpDeviceEnumInit(&pThis->DeviceEnum); 2557 2648 2558 2649 pThis->fEnabledIn = false;
Note:
See TracChangeset
for help on using the changeset viewer.