Changeset 88667 in vbox for trunk/src/VBox
- Timestamp:
- Apr 23, 2021 12:00:17 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvHostAudioWasApi.cpp
r88663 r88667 201 201 PRTUTF16 pwszInputDevId; 202 202 203 /** Pointer to the MM notification client instance. */ 204 DrvHostAudioWasMmNotifyClient *pNotifyClient; 205 /** The input device to use. This can be NULL if there wasn't a suitable one 206 * around when we last looked or if it got removed/disabled/whatever. 207 * All access must be done inside the pNotifyClient critsect. */ 208 IMMDevice *pIDeviceInput; 209 /** The output device to use. This can be NULL if there wasn't a suitable one 210 * around when we last looked or if it got removed/disabled/whatever. 211 * All access must be done inside the pNotifyClient critsect. */ 212 IMMDevice *pIDeviceOutput; 213 203 214 /** A drain stop timer that makes sure a draining stream will be properly 204 215 * stopped (mainly for clean state and to reduce resource usage). */ … … 210 221 RTCRITSECTRW CritSectStreamList; 211 222 212 /** Pointer to the MM notification client instance. */213 DrvHostAudioWasMmNotifyClient *pNotifyClient;214 223 /** List of cached devices (DRVHOSTAUDIOWASCACHEDEV). 215 224 * Protected by CritSectCache */ … … 860 869 } 861 870 871 /** 872 * Enters the notification critsect for getting at the IMMDevice members in 873 * PDMHOSTAUDIOWAS. 874 */ 875 void lockEnter() RT_NOEXCEPT 876 { 877 RTCritSectEnter(&m_CritSect); 878 } 879 880 /** 881 * Leaves the notification critsect. 882 */ 883 void lockLeave() RT_NOEXCEPT 884 { 885 RTCritSectLeave(&m_CritSect); 886 } 887 862 888 /** @name IUnknown interface 863 889 * @{ */ … … 910 936 RT_NOREF(pwszDeviceId); 911 937 Log7Func(("pwszDeviceId=%ls\n", pwszDeviceId)); 938 939 /* 940 * Is this a device we're interested in? Grab the enumerator if it is. 941 */ 942 bool fOutput = false; 943 IMMDeviceEnumerator *pIEnumerator = NULL; 944 RTCritSectEnter(&m_CritSect); 945 if ( m_pDrvWas != NULL 946 && ( (fOutput = RTUtf16ICmp(m_pDrvWas->pwszOutputDevId, pwszDeviceId) == 0) 947 || RTUtf16ICmp(m_pDrvWas->pwszInputDevId, pwszDeviceId) == 0)) 948 { 949 pIEnumerator = m_pDrvWas->pIEnumerator; 950 if (pIEnumerator /* paranoia */) 951 pIEnumerator->AddRef(); 952 } 953 RTCritSectLeave(&m_CritSect); 954 if (pIEnumerator) 955 { 956 /* 957 * Get the device and update it. 958 */ 959 IMMDevice *pIDevice = NULL; 960 HRESULT hrc = pIEnumerator->GetDevice(pwszDeviceId, &pIDevice); 961 if (SUCCEEDED(hrc)) 962 setDevice(fOutput, pIDevice, pwszDeviceId, __PRETTY_FUNCTION__); 963 else 964 LogRelMax(64, ("WasAPI: Failed to get %s device '%ls' (OnDeviceAdded): %Rhrc\n", 965 fOutput ? "output" : "input", pwszDeviceId, hrc)); 966 pIEnumerator->Release(); 967 } 912 968 return S_OK; 913 969 } … … 917 973 RT_NOREF(pwszDeviceId); 918 974 Log7Func(("pwszDeviceId=%ls\n", pwszDeviceId)); 975 976 /* 977 * Is this a device we're interested in? Then set it to NULL. 978 */ 979 bool fOutput = false; 980 RTCritSectEnter(&m_CritSect); 981 if ( m_pDrvWas != NULL 982 && ( (fOutput = RTUtf16ICmp(m_pDrvWas->pwszOutputDevId, pwszDeviceId) == 0) 983 || RTUtf16ICmp(m_pDrvWas->pwszInputDevId, pwszDeviceId) == 0)) 984 setDevice(fOutput, NULL, pwszDeviceId, __PRETTY_FUNCTION__); 985 RTCritSectLeave(&m_CritSect); 919 986 return S_OK; 920 987 } … … 922 989 IFACEMETHODIMP OnDefaultDeviceChanged(EDataFlow enmFlow, ERole enmRole, LPCWSTR pwszDefaultDeviceId) 923 990 { 991 /* 992 * Are we interested in this device? If so grab the enumerator. 993 */ 994 IMMDeviceEnumerator *pIEnumerator = NULL; 995 RTCritSectEnter(&m_CritSect); 996 if ( m_pDrvWas != NULL 997 && ( (enmFlow == eRender && enmRole == eMultimedia && !m_pDrvWas->pwszOutputDevId) 998 || (enmFlow == eCapture && enmRole == eMultimedia && !m_pDrvWas->pwszInputDevId))) 999 { 1000 pIEnumerator = m_pDrvWas->pIEnumerator; 1001 if (pIEnumerator /* paranoia */) 1002 pIEnumerator->AddRef(); 1003 } 1004 RTCritSectLeave(&m_CritSect); 1005 if (pIEnumerator) 1006 { 1007 /* 1008 * Get the device and update it. 1009 */ 1010 IMMDevice *pIDevice = NULL; 1011 HRESULT hrc = pIEnumerator->GetDefaultAudioEndpoint(enmFlow, enmRole, &pIDevice); 1012 if (SUCCEEDED(hrc)) 1013 setDevice(enmFlow == eRender, pIDevice, pwszDefaultDeviceId, __PRETTY_FUNCTION__); 1014 else 1015 LogRelMax(64, ("WasAPI: Failed to get default %s device (OnDefaultDeviceChange): %Rhrc\n", 1016 enmFlow == eRender ? "output" : "input", hrc)); 1017 pIEnumerator->Release(); 1018 } 1019 924 1020 RT_NOREF(enmFlow, enmRole, pwszDefaultDeviceId); 925 1021 Log7Func(("enmFlow=%d enmRole=%d pwszDefaultDeviceId=%ls\n", enmFlow, enmRole, pwszDefaultDeviceId)); … … 934 1030 } 935 1031 /** @} */ 1032 1033 private: 1034 /** 1035 * Sets DRVHOSTAUDIOWAS::pIDeviceOutput or DRVHOSTAUDIOWAS::pIDeviceInput to @a pIDevice. 1036 */ 1037 void setDevice(bool fOutput, IMMDevice *pIDevice, LPCWSTR pwszDeviceId, const char *pszCaller) 1038 { 1039 RT_NOREF(pszCaller, pwszDeviceId); 1040 1041 RTCritSectEnter(&m_CritSect); 1042 if (m_pDrvWas) 1043 { 1044 if (fOutput) 1045 { 1046 Log7((LOG_FN_FMT ": Changing output device from %p to %p (%ls)\n", 1047 pszCaller, m_pDrvWas->pIDeviceOutput, pIDevice, pwszDeviceId)); 1048 if (m_pDrvWas->pIDeviceOutput) 1049 m_pDrvWas->pIDeviceOutput->Release(); 1050 m_pDrvWas->pIDeviceOutput = pIDevice; 1051 } 1052 else 1053 { 1054 Log7((LOG_FN_FMT ": Changing input device from %p to %p (%ls)\n", 1055 pszCaller, m_pDrvWas->pIDeviceInput, pIDevice, pwszDeviceId)); 1056 if (m_pDrvWas->pIDeviceInput) 1057 m_pDrvWas->pIDeviceInput->Release(); 1058 m_pDrvWas->pIDeviceInput = pIDevice; 1059 } 1060 1061 /** @todo Invalid/update in-use streams. */ 1062 } 1063 else if (pIDevice) 1064 pIDevice->Release(); 1065 RTCritSectLeave(&m_CritSect); 1066 } 936 1067 }; 937 1068 … … 1196 1327 /* 1197 1328 * Get the device we're supposed to use. 1198 */ 1199 PRTUTF16 pwszDevId = pCfgReq->enmDir == PDMAUDIODIR_IN ? pThis->pwszInputDevId : pThis->pwszOutputDevId; 1200 IMMDevice *pIDevice = NULL; 1201 HRESULT hrc; 1202 if (pwszDevId) 1203 hrc = pThis->pIEnumerator->GetDevice(pwszDevId, &pIDevice); 1204 else 1205 { 1206 /** @todo this takes about 2ms. Cache it and update it using the 1207 * notification client. */ 1208 hrc = pThis->pIEnumerator->GetDefaultAudioEndpoint(pCfgReq->enmDir == PDMAUDIODIR_IN ? eCapture : eRender, 1209 eMultimedia, &pIDevice); 1210 pwszDevId = pCfgReq->enmDir == PDMAUDIODIR_IN ? L"{Default-In}" : L"{Default-Out}"; 1211 } 1212 LogFlowFunc(("Got device %p (%Rhrc)\n", pIDevice, hrc)); 1213 if (FAILED(hrc)) 1214 { 1215 LogRelMax(64, ("WasAPI: Failed to open audio %s device '%ls': %Rhrc\n", pszStreamType, pwszDevId, hrc)); 1216 return VERR_AUDIO_STREAM_COULD_NOT_CREATE; 1329 * (We cache this as it takes ~2ms to get the default device on a random W10 19042 system.) 1330 */ 1331 pThis->pNotifyClient->lockEnter(); 1332 IMMDevice *pIDevice = pCfgReq->enmDir == PDMAUDIODIR_IN ? pThis->pIDeviceInput : pThis->pIDeviceOutput; 1333 if (pIDevice) 1334 pIDevice->AddRef(); 1335 pThis->pNotifyClient->lockLeave(); 1336 1337 PRTUTF16 pwszDevId = pCfgReq->enmDir == PDMAUDIODIR_IN ? pThis->pwszInputDevId : pThis->pwszOutputDevId; 1338 PRTUTF16 const pwszDevIdDesc = pwszDevId ? pwszDevId : pCfgReq->enmDir == PDMAUDIODIR_IN ? L"{Default-In}" : L"{Default-Out}"; 1339 if (!pIDevice) 1340 { 1341 /** @todo we can eliminate this too... */ 1342 HRESULT hrc; 1343 if (pwszDevId) 1344 hrc = pThis->pIEnumerator->GetDevice(pwszDevId, &pIDevice); 1345 else 1346 hrc = pThis->pIEnumerator->GetDefaultAudioEndpoint(pCfgReq->enmDir == PDMAUDIODIR_IN ? eCapture : eRender, 1347 eMultimedia, &pIDevice); 1348 LogFlowFunc(("Got device %p (%Rhrc)\n", pIDevice, hrc)); 1349 if (FAILED(hrc)) 1350 { 1351 LogRelMax(64, ("WasAPI: Failed to open audio %s device '%ls': %Rhrc\n", pszStreamType, pwszDevIdDesc, hrc)); 1352 return VERR_AUDIO_STREAM_COULD_NOT_CREATE; 1353 } 1217 1354 } 1218 1355 … … 1252 1389 } 1253 1390 1254 LogRelMax(64, ("WasAPI: Failed to create critical section for stream.\n" , hrc));1391 LogRelMax(64, ("WasAPI: Failed to create critical section for stream.\n")); 1255 1392 drvHostAudioWasCachePutBack(pThis, pDevCfg); 1256 1393 pStreamWas->pDevCfg = NULL; 1257 1394 } 1258 1395 else 1259 LogRelMax(64, ("WasAPI: Failed to activate %s audio device '%ls': %Rhrc\n", pszStreamType, pwszDevId, hrc));1396 LogRelMax(64, ("WasAPI: Failed to setup %s on audio device '%ls'.\n", pszStreamType, pwszDevIdDesc)); 1260 1397 1261 1398 LogFlowFunc(("returns %Rrc\n", rc)); … … 2156 2293 } 2157 2294 2295 if (pThis->pIDeviceOutput) 2296 { 2297 pThis->pIDeviceOutput->Release(); 2298 pThis->pIDeviceOutput = NULL; 2299 } 2300 2301 if (pThis->pIDeviceInput) 2302 { 2303 pThis->pIDeviceInput->Release(); 2304 pThis->pIDeviceInput = NULL; 2305 } 2306 2158 2307 if (RTCritSectRwIsInitialized(&pThis->CritSectStreamList)) 2159 2308 RTCritSectRwDelete(&pThis->CritSectStreamList); … … 2268 2417 pThis->pNotifyClient = NULL; 2269 2418 } 2419 2420 /* 2421 * Retrieve the input and output device. 2422 */ 2423 IMMDevice *pIDeviceInput = NULL; 2424 if (pThis->pwszInputDevId) 2425 hrc = pThis->pIEnumerator->GetDevice(pThis->pwszInputDevId, &pIDeviceInput); 2426 else 2427 hrc = pThis->pIEnumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, &pIDeviceInput); 2428 if (SUCCEEDED(hrc)) 2429 LogFlowFunc(("pIDeviceInput=%p\n", pIDeviceInput)); 2430 else 2431 { 2432 LogRel(("WasAPI: Failed to get audio input device '%ls': %Rhrc\n", 2433 pThis->pwszInputDevId ? pThis->pwszInputDevId : L"{Default}", hrc)); 2434 pIDeviceInput = NULL; 2435 } 2436 2437 IMMDevice *pIDeviceOutput = NULL; 2438 if (pThis->pwszOutputDevId) 2439 hrc = pThis->pIEnumerator->GetDevice(pThis->pwszOutputDevId, &pIDeviceOutput); 2440 else 2441 hrc = pThis->pIEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &pIDeviceOutput); 2442 if (SUCCEEDED(hrc)) 2443 LogFlowFunc(("pIDeviceOutput=%p\n", pIDeviceOutput)); 2444 else 2445 { 2446 LogRel(("WasAPI: Failed to get audio output device '%ls': %Rhrc\n", 2447 pThis->pwszOutputDevId ? pThis->pwszOutputDevId : L"{Default}", hrc)); 2448 pIDeviceOutput = NULL; 2449 } 2450 2451 /* Carefully place them in the instance data: */ 2452 pThis->pNotifyClient->lockEnter(); 2453 2454 if (pThis->pIDeviceInput) 2455 pThis->pIDeviceInput->Release(); 2456 pThis->pIDeviceInput = pIDeviceInput; 2457 2458 if (pThis->pIDeviceOutput) 2459 pThis->pIDeviceOutput->Release(); 2460 pThis->pIDeviceOutput = pIDeviceOutput; 2461 2462 pThis->pNotifyClient->lockLeave(); 2270 2463 2271 2464 /*
Note:
See TracChangeset
for help on using the changeset viewer.