- Timestamp:
- Mar 1, 2016 5:11:08 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/pdmaudioifs.h
r59470 r59890 68 68 typedef struct PDMAUDIOBACKENDCFG 69 69 { 70 uint32_tcbStreamOut;71 uint32_tcbStreamIn;72 uint32_t 73 uint32_t 70 size_t cbStreamOut; 71 size_t cbStreamIn; 72 uint32_t cMaxHstStrmsOut; 73 uint32_t cMaxHstStrmsIn; 74 74 } PDMAUDIOBACKENDCFG, *PPDMAUDIOBACKENDCFG; 75 75 -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r59470 r59890 1399 1399 rc = rc2; 1400 1400 1401 if (RT_FAILURE(rc)) 1402 LogFlowFuncLeaveRC(rc); 1403 1401 1404 return rc; 1402 1405 } … … 1412 1415 if (RT_FAILURE(rc)) 1413 1416 return rc; 1417 1418 /* Backend output (temporarily) disabled / unavailable? */ 1419 if (!pThis->pHostDrvAudio->pfnIsEnabled(pThis->pHostDrvAudio, PDMAUDIODIR_OUT)) 1420 { 1421 rc = pThis->pHostDrvAudio->pfnGetConf(pThis->pHostDrvAudio, &pThis->BackendCfg); 1422 AssertRC(rc); 1423 1424 if (!pThis->BackendCfg.cMaxHstStrmsOut) 1425 { 1426 int rc2 = RTCritSectLeave(&pThis->CritSect); 1427 AssertRC(rc2); 1428 1429 return VERR_NOT_AVAILABLE; 1430 } 1431 } 1414 1432 1415 1433 /* … … 1450 1468 1451 1469 uint32_t cSamplesPlayed = 0; 1452 int rc2 = pThis->pHostDrvAudio->pfnPlayOut(pThis->pHostDrvAudio, pHstStrmOut, 1453 &cSamplesPlayed); 1454 if (RT_SUCCESS(rc2)) 1470 int rc2 = pThis->pHostDrvAudio->pfnPlayOut(pThis->pHostDrvAudio, pHstStrmOut, &cSamplesPlayed); 1471 if (RT_FAILURE(rc2)) 1472 { 1473 rc2 = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE); 1474 AssertRC(rc2); 1475 } 1476 else 1455 1477 cSamplesPlayedMax = RT_MAX(cSamplesPlayed, cSamplesPlayedMax); 1456 1478 … … 1494 1516 rc = rc2; 1495 1517 1518 if (RT_FAILURE(rc)) 1519 LogFlowFuncLeaveRC(rc); 1520 1496 1521 return rc; 1497 1522 } … … 1628 1653 LogFlowFuncEnter(); 1629 1654 1655 AssertPtr(pThis->pHostDrvAudio); 1630 1656 int rc = pThis->pHostDrvAudio->pfnInit(pThis->pHostDrvAudio); 1631 1657 if (RT_FAILURE(rc)) … … 1635 1661 } 1636 1662 1663 /* Get the configuration data from backend. */ 1664 rc = pThis->pHostDrvAudio->pfnGetConf(pThis->pHostDrvAudio, &pThis->BackendCfg); 1665 if (RT_FAILURE(rc)) 1666 { 1667 LogFlowFunc(("Getting backend configuration failed with rc=%Rrc\n", rc)); 1668 return rc; 1669 } 1670 1637 1671 uint32_t cMaxHstStrmsOut = pThis->BackendCfg.cMaxHstStrmsOut; 1638 uint32_t cbHstStrmsOut= pThis->BackendCfg.cbStreamOut;1672 size_t cbHstStrmsOut = pThis->BackendCfg.cbStreamOut; 1639 1673 1640 1674 if (cbHstStrmsOut) … … 1646 1680 1647 1681 uint32_t cMaxHstStrmsIn = pThis->BackendCfg.cMaxHstStrmsIn; 1648 uint32_t cbHstStrmIn= pThis->BackendCfg.cbStreamIn;1682 size_t cbHstStrmIn = pThis->BackendCfg.cbStreamIn; 1649 1683 1650 1684 if (cbHstStrmIn) … … 1660 1694 pThis->cFreeInputStreams = 0; 1661 1695 1662 LogFlowFunc(("cMaxHstStrmsOut=%RU32 (cb=% RU32), cMaxHstStrmsIn=%RU32 (cb=%RU32)\n",1696 LogFlowFunc(("cMaxHstStrmsOut=%RU32 (cb=%zu), cMaxHstStrmsIn=%RU32 (cb=%zu)\n", 1663 1697 cMaxHstStrmsOut, cbHstStrmsOut, cMaxHstStrmsIn, cbHstStrmIn)); 1664 1698 … … 1753 1787 1754 1788 int rc = RTCritSectInit(&pThis->CritSect); 1755 1756 /* Get the configuration data from the selected backend (if available). */1757 AssertPtr(pThis->pHostDrvAudio);1758 if ( RT_SUCCESS(rc)1759 && RT_LIKELY(pThis->pHostDrvAudio->pfnGetConf))1760 rc = pThis->pHostDrvAudio->pfnGetConf(pThis->pHostDrvAudio, &pThis->BackendCfg);1761 1762 1789 if (RT_SUCCESS(rc)) 1763 1790 { … … 2186 2213 return rc; 2187 2214 2188 memcpy(pCfg, &pThis->BackendCfg, sizeof(PDMAUDIOBACKENDCFG));2215 rc = pThis->pHostDrvAudio->pfnGetConf(pThis->pHostDrvAudio, pCfg); 2189 2216 2190 2217 int rc2 = RTCritSectLeave(&pThis->CritSect); -
trunk/src/VBox/Devices/Audio/DrvAudioCommon.cpp
r58378 r59890 365 365 } 366 366 367 #ifdef DEBUG368 drvAudioStreamCfgPrint(pCfg);369 #endif370 371 LogFlowFunc(("rc=%Rrc\n", rc));372 367 return rc; 373 368 } -
trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp
r59470 r59890 95 95 DWORD cbPlayWritePos; 96 96 DWORD csPlaybackBufferSize; 97 bool fEnabled; 97 98 bool fRestartPlayback; 98 99 PDMAUDIOSTREAMCFG streamCfg; … … 108 109 HRESULT hrLastCaptureIn; 109 110 PDMAUDIORECSOURCE enmRecSource; 111 bool fEnabled; 110 112 PDMAUDIOSTREAMCFG streamCfg; 111 113 } DSOUNDSTREAMIN, *PDSOUNDSTREAMIN; … … 123 125 /** DirectSound configuration options. */ 124 126 DSOUNDHOSTCFG cfg; 125 /** Whether the input currently is in an enabled (working) 126 * state or not. */ 127 /** Whether this backend supports any audio input. */ 127 128 bool fEnabledIn; 128 /** Whether the output currently is in an enabled (working) 129 * state or not. */ 129 /** Whether this backend supports any audio output. */ 130 130 bool fEnabledOut; 131 131 #ifdef VBOX_WITH_AUDIO_CALLBACKS … … 150 150 } DRVHOSTDSOUND, *PDRVHOSTDSOUND; 151 151 152 /** No flags specified. */ 153 #define DSOUNDENUMCBFLAGS_NONE 0 154 /** (Release) log found devices. */ 155 #define DSOUNDENUMCBFLAGS_LOG RT_BIT(0) 156 152 157 /** 153 158 * Callback context for enumeration callbacks … … 157 162 PDRVHOSTDSOUND pDrv; 158 163 PPDMAUDIOBACKENDCFG pCfg; 164 /** Enumeration flags. */ 165 uint32_t fFlags; 159 166 } DSOUNDENUMCBCTX, *PDSOUNDENUMCBCTX; 160 167 … … 166 173 } DSOUNDDEV, *PDSOUNDDEV; 167 174 175 /** Maximum number of attempts to restore the sound buffer before giving up. */ 176 #define DRV_DSOUND_RESTORE_ATTEMPTS_MAX 3 177 168 178 /** Makes DRVHOSTDSOUND out of PDMIHOSTAUDIO. */ 169 179 #define PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface) \ 170 180 ( (PDRVHOSTDSOUND)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTDSOUND, IHostAudio)) ) 171 181 172 static HRESULT directSoundPlayRestore(LPDIRECTSOUNDBUFFER8 pDSB); 173 174 static void dsoundDevRemove(PDSOUNDDEV pDev); 182 static HRESULT directSoundPlayRestore(PDRVHOSTDSOUND pThis, LPDIRECTSOUNDBUFFER8 pDSB); 183 184 static void dsoundDeviceRemove(PDSOUNDDEV pDev); 185 static int dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PPDMAUDIOBACKENDCFG pCfg); 175 186 #ifdef VBOX_WITH_AUDIO_CALLBACKS 176 187 static int dsoundNotifyThread(PDRVHOSTDSOUND pThis, bool fShutdown); … … 225 236 } 226 237 227 static int dsoundGetStatusOut(PDSOUNDSTREAMOUT pDSoundStrmOut, DWORD *pdwBuffer, DWORD *pdwFree, DWORD *pdwPlayPos) 228 { 238 static int dsoundGetPosOut(PDRVHOSTDSOUND pThis, 239 PDSOUNDSTREAMOUT pDSoundStrmOut, DWORD *pdwBuffer, DWORD *pdwFree, DWORD *pdwPlayPos) 240 { 241 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 229 242 AssertPtrReturn(pDSoundStrmOut, VERR_INVALID_POINTER); 230 243 … … 237 250 /* Get the current play position which is used for calculating the free space in the buffer. */ 238 251 DWORD cbPlayPos; 239 HRESULT hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &cbPlayPos, NULL); 240 if (hr == DSERR_BUFFERLOST) 241 { 242 hr = directSoundPlayRestore(pDSB); 243 if (SUCCEEDED(hr)) 244 hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &cbPlayPos, NULL); 245 } 252 253 HRESULT hr; 254 for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++) 255 { 256 hr = IDirectSoundBuffer8_GetCurrentPosition(pDSB, &cbPlayPos, NULL); 257 if ( SUCCEEDED(hr) 258 || hr != DSERR_BUFFERLOST) /** @todo: MSDN doesn't state this error for GetCurrentPosition(). */ 259 { 260 break; 261 } 262 else 263 { 264 LogFlowFunc(("Getting playing position failed due to lost buffer, restoring ...\n")); 265 directSoundPlayRestore(pThis, pDSB); 266 } 267 } 268 269 int rc = VINF_SUCCESS; 246 270 247 271 if (FAILED(hr)) … … 250 274 DSLOGREL(("DSound: Getting current playback position failed with %Rhrc\n", hr)); 251 275 LogFlowFunc(("Failed with %Rhrc\n", hr)); 252 return VERR_NOT_AVAILABLE; 253 } 254 255 if (pdwBuffer) 256 *pdwBuffer = cbBuffer; 257 258 if (pdwFree) 259 *pdwFree = cbBuffer - dsoundRingDistance(pDSoundStrmOut->cbPlayWritePos, cbPlayPos, cbBuffer); 260 261 if (pdwPlayPos) 262 *pdwPlayPos = cbPlayPos; 263 264 return VINF_SUCCESS; 276 277 rc = VERR_NOT_AVAILABLE; 278 } 279 else 280 { 281 if (pdwBuffer) 282 *pdwBuffer = cbBuffer; 283 284 if (pdwFree) 285 *pdwFree = cbBuffer - dsoundRingDistance(pDSoundStrmOut->cbPlayWritePos, cbPlayPos, cbBuffer); 286 287 if (pdwPlayPos) 288 *pdwPlayPos = cbPlayPos; 289 } 290 291 LogFlowFuncLeaveRC(rc); 292 return rc; 265 293 } 266 294 … … 284 312 } 285 313 286 static void dsoundFreeDeviceLists(PDRVHOSTDSOUND pThis) 287 { 314 /** 315 * Clears the list of the host's playback + capturing devices. 316 * 317 * @param pThis Host audio driver instance. 318 */ 319 static void dsoundDevicesClear(PDRVHOSTDSOUND pThis) 320 { 321 AssertPtrReturnVoid(pThis); 322 288 323 PDSOUNDDEV pDev; 289 324 while (!RTListIsEmpty(&pThis->lstDevInput)) 290 325 { 291 326 pDev = RTListGetFirst(&pThis->lstDevInput, DSOUNDDEV, Node); 292 dsoundDev Remove(pDev);327 dsoundDeviceRemove(pDev); 293 328 } 294 329 … … 296 331 { 297 332 pDev = RTListGetFirst(&pThis->lstDevOutput, DSOUNDDEV, Node); 298 dsoundDev Remove(pDev);299 } 300 } 301 302 static HRESULT directSoundPlayRestore( LPDIRECTSOUNDBUFFER8 pDSB)333 dsoundDeviceRemove(pDev); 334 } 335 } 336 337 static HRESULT directSoundPlayRestore(PDRVHOSTDSOUND pThis, LPDIRECTSOUNDBUFFER8 pDSB) 303 338 { 304 339 HRESULT hr = IDirectSoundBuffer8_Restore(pDSB); … … 308 343 } 309 344 310 static HRESULT directSoundPlayUnlock( LPDIRECTSOUNDBUFFER8 pDSB,345 static HRESULT directSoundPlayUnlock(PDRVHOSTDSOUND pThis, LPDIRECTSOUNDBUFFER8 pDSB, 311 346 LPVOID pv1, LPVOID pv2, 312 347 DWORD cb1, DWORD cb2) … … 328 363 } 329 364 330 static HRESULT directSoundPlayLock(LPDIRECTSOUNDBUFFER8 pDSB, PDMPCMPROPS *pProps, 365 static HRESULT directSoundPlayLock(PDRVHOSTDSOUND pThis, 366 LPDIRECTSOUNDBUFFER8 pDSB, PDMPCMPROPS *pProps, 331 367 DWORD dwOffset, DWORD dwBytes, 332 368 LPVOID *ppv1, LPVOID *ppv2, … … 339 375 DWORD cb2 = 0; 340 376 341 HRESULT hr = IDirectSoundBuffer8_Lock(pDSB, dwOffset, dwBytes, &pv1, &cb1, &pv2, &cb2, dwFlags); 342 if (hr == DSERR_BUFFERLOST) 343 { 344 hr = directSoundPlayRestore(pDSB); 345 if (SUCCEEDED(hr)) 346 { 347 hr = IDirectSoundBuffer8_Lock(pDSB, dwOffset, dwBytes, &pv1, &cb1, &pv2, &cb2, dwFlags); 377 HRESULT hr; 378 for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++) 379 { 380 hr = IDirectSoundBuffer8_Lock(pDSB, dwOffset, dwBytes, &pv1, &cb1, &pv2, &cb2, dwFlags); 381 if ( SUCCEEDED(hr) 382 || hr != DSERR_BUFFERLOST) 383 break; 384 else 385 { 386 LogFlowFunc(("Locking failed due to lost buffer, restoring ...\n")); 387 directSoundPlayRestore(pThis, pDSB); 348 388 } 349 389 } … … 360 400 DSLOGREL(("DSound: Locking playback buffer returned misaligned buffer: cb1=%RI32, cb2=%RI32 (alignment: %RU32)\n", 361 401 cb1, cb2, pProps->uAlign)); 362 directSoundPlayUnlock(p DSB, pv1, pv2, cb1, cb2);402 directSoundPlayUnlock(pThis, pDSB, pv1, pv2, cb1, cb2); 363 403 return E_FAIL; 364 404 } … … 686 726 } 687 727 688 static void dsoundPlayClearSamples(PD SOUNDSTREAMOUT pDSoundStrmOut)728 static void dsoundPlayClearSamples(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStrmOut) 689 729 { 690 730 AssertPtrReturnVoid(pDSoundStrmOut); … … 694 734 LPVOID pv1, pv2; 695 735 DWORD cb1, cb2; 696 HRESULT hr = directSoundPlayLock(p DSoundStrmOut->pDSB, &pDSoundStrmOut->strmOut.Props,736 HRESULT hr = directSoundPlayLock(pThis, pDSoundStrmOut->pDSB, &pDSoundStrmOut->strmOut.Props, 697 737 0 /* dwOffset */, AUDIOMIXBUF_S2B(&pStrmOut->MixBuf, pDSoundStrmOut->csPlaybackBufferSize), 698 738 &pv1, &pv2, &cb1, &cb2, DSBLOCK_ENTIREBUFFER); … … 708 748 DrvAudioClearBuf(&pDSoundStrmOut->strmOut.Props, pv2, cb2, len2); 709 749 710 directSoundPlayUnlock(pDSoundStrmOut->pDSB, pv1, pv2, cb1, cb2); 711 } 712 } 713 714 static HRESULT directSoundPlayGetStatus(LPDIRECTSOUNDBUFFER8 pDSB, DWORD *pdwStatus) 715 { 716 AssertPtrReturn(pDSB, E_POINTER); 750 directSoundPlayUnlock(pThis, pDSoundStrmOut->pDSB, pv1, pv2, cb1, cb2); 751 } 752 } 753 754 static HRESULT directSoundPlayGetStatus(PDRVHOSTDSOUND pThis, LPDIRECTSOUNDBUFFER8 pDSB, DWORD *pdwStatus) 755 { 756 AssertPtrReturn(pThis, E_POINTER); 757 AssertPtrReturn(pDSB, E_POINTER); 717 758 /* pdwStatus is optional. */ 718 759 719 bool fRestoreBuffer = false;720 721 760 DWORD dwStatus = 0; 722 HRESULT hr = IDirectSoundBuffer8_GetStatus(pDSB, &dwStatus); 723 if (SUCCEEDED(hr)) 724 { 725 fRestoreBuffer = RT_BOOL(dwStatus & DSBSTATUS_BUFFERLOST); 726 } 727 else if (hr == DSERR_BUFFERLOST) 728 fRestoreBuffer = true; 729 730 if (fRestoreBuffer) 731 { 732 hr = directSoundPlayRestore(pDSB); 733 if (SUCCEEDED(hr)) 734 hr = IDirectSoundBuffer8_GetStatus(pDSB, &dwStatus); 761 762 HRESULT hr; 763 for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++) 764 { 765 hr = IDirectSoundBuffer8_GetStatus(pDSB, &dwStatus); 766 if ( hr == DSERR_BUFFERLOST 767 || ( SUCCEEDED(hr) 768 && (dwStatus & DSBSTATUS_BUFFERLOST))) 769 { 770 LogFlowFunc(("Getting status failed due to lost buffer, restoring ...\n")); 771 directSoundPlayRestore(pThis, pDSB); 772 } 773 else 774 break; 735 775 } 736 776 … … 748 788 static HRESULT directSoundPlayStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStrmOut) 749 789 { 750 AssertPtrReturn(pThis, E_POINTER);790 AssertPtrReturn(pThis, E_POINTER); 751 791 AssertPtrReturn(pDSoundStrmOut, E_POINTER); 752 792 … … 755 795 if (pDSoundStrmOut->pDSB != NULL) 756 796 { 757 /* This performs some restore, so call it anyway and ignore result. */ 758 hr = directSoundPlayGetStatus(pDSoundStrmOut->pDSB, NULL /* pdwStatus */); 759 if (SUCCEEDED(hr)) 760 { 761 DSLOG(("DSound: Stopping playback\n")); 762 763 /** @todo Wait until all data in the buffer has been played. */ 764 hr = IDirectSoundBuffer8_Stop(pDSoundStrmOut->pDSB); 765 if (SUCCEEDED(hr)) 766 dsoundPlayClearSamples(pDSoundStrmOut); 767 } 797 DSLOG(("DSound: Stopping playback\n")); 798 799 HRESULT hr2 = IDirectSoundBuffer8_Stop(pDSoundStrmOut->pDSB); 800 if (FAILED(hr2)) 801 { 802 hr2 = directSoundPlayRestore(pThis, pDSoundStrmOut->pDSB); 803 if (FAILED(hr2)) 804 hr2 = IDirectSoundBuffer8_Stop(pDSoundStrmOut->pDSB); 805 } 806 807 if (FAILED(hr2)) 808 DSLOG(("DSound: Stopping playback failed with %Rhrc\n", hr2)); 809 810 hr = S_OK; /* Always report success here. */ 768 811 } 769 812 else 770 813 hr = E_UNEXPECTED; 771 814 772 if (FAILED(hr)) 815 if (SUCCEEDED(hr)) 816 { 817 dsoundPlayClearSamples(pThis, pDSoundStrmOut); 818 pDSoundStrmOut->fEnabled = false; 819 } 820 else 773 821 DSLOGREL(("DSound: Stopping playback failed with %Rhrc\n", hr)); 774 822 … … 776 824 } 777 825 778 static HRESULT directSoundPlayStart(PDSOUNDSTREAMOUT pDSoundStrmOut) 779 { 826 static HRESULT directSoundPlayStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStrmOut) 827 { 828 AssertPtrReturn(pThis, E_POINTER); 780 829 AssertPtrReturn(pDSoundStrmOut, E_POINTER); 781 830 … … 784 833 { 785 834 DWORD dwStatus; 786 hr = directSoundPlayGetStatus(p DSoundStrmOut->pDSB, &dwStatus);835 hr = directSoundPlayGetStatus(pThis, pDSoundStrmOut->pDSB, &dwStatus); 787 836 if (SUCCEEDED(hr)) 788 837 { … … 793 842 else 794 843 { 795 dsoundPlayClearSamples(p DSoundStrmOut);844 dsoundPlayClearSamples(pThis, pDSoundStrmOut); 796 845 797 846 pDSoundStrmOut->fRestartPlayback = true; 798 799 DSLOG(("DSound: Playback start\n")); 800 801 /* The actual IDirectSoundBuffer8_Play call will be made in drvHostDSoundPlayOut, 847 pDSoundStrmOut->fEnabled = true; 848 849 DSLOG(("DSound: Playback started\n")); 850 851 /* 852 * The actual IDirectSoundBuffer8_Play call will be made in drvHostDSoundPlayOut, 802 853 * because it is necessary to put some samples into the buffer first. 803 854 */ … … 1070 1121 } 1071 1122 1072 static HRESULT directSoundCaptureStop(PDSOUNDSTREAMIN pDSoundStrmIn) 1073 { 1123 static HRESULT directSoundCaptureStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStrmIn) 1124 { 1125 AssertPtrReturn(pThis , E_POINTER); 1074 1126 AssertPtrReturn(pDSoundStrmIn, E_POINTER); 1127 1128 NOREF(pThis); 1075 1129 1076 1130 HRESULT hr; … … 1086 1140 else 1087 1141 hr = E_UNEXPECTED; 1142 1143 if (SUCCEEDED(hr)) 1144 pDSoundStrmIn->fEnabled = false; 1088 1145 1089 1146 LogFlowFunc(("Returning %Rhrc\n", hr)); … … 1127 1184 hr = E_UNEXPECTED; 1128 1185 1186 if (SUCCEEDED(hr)) 1187 pDSoundStrmIn->fEnabled = true; 1188 1129 1189 LogFlowFunc(("Returning %Rhrc\n", hr)); 1130 1190 return hr; … … 1155 1215 } 1156 1216 1157 static void dsoundDev Remove(PDSOUNDDEV pDev)1217 static void dsoundDeviceRemove(PDSOUNDDEV pDev) 1158 1218 { 1159 1219 if (pDev) … … 1177 1237 } 1178 1238 1179 static BOOL CALLBACK dsound EnumCallback(LPGUID lpGUID, LPCWSTR lpwstrDescription,1180 LPCWSTR lpwstrModule, LPVOID lpContext)1239 static BOOL CALLBACK dsoundDevicesEnumCbPlayback(LPGUID lpGUID, LPCWSTR lpwstrDescription, 1240 LPCWSTR lpwstrModule, LPVOID lpContext) 1181 1241 { 1182 1242 PDSOUNDENUMCBCTX pCtx = (PDSOUNDENUMCBCTX)lpContext; … … 1189 1249 1190 1250 AssertPtrReturn(lpwstrDescription, FALSE); 1191 /* Do not care about lpwstrModule */ 1192 1193 dsoundLogDevice("Output", lpGUID, lpwstrDescription, lpwstrModule); 1251 /* Do not care about lpwstrModule. */ 1252 1253 if (pCtx->fFlags & DSOUNDENUMCBFLAGS_LOG) 1254 dsoundLogDevice("Output", lpGUID, lpwstrDescription, lpwstrModule); 1194 1255 1195 1256 int rc = dsoundDevAdd(&pCtx->pDrv->lstDevOutput, … … 1203 1264 } 1204 1265 1205 static BOOL CALLBACK dsound CaptureEnumCallback(LPGUID lpGUID, LPCWSTR lpwstrDescription,1206 LPCWSTR lpwstrModule, LPVOID lpContext)1266 static BOOL CALLBACK dsoundDevicesEnumCbCapture(LPGUID lpGUID, LPCWSTR lpwstrDescription, 1267 LPCWSTR lpwstrModule, LPVOID lpContext) 1207 1268 { 1208 1269 PDSOUNDENUMCBCTX pCtx = (PDSOUNDENUMCBCTX)lpContext; … … 1214 1275 return TRUE; 1215 1276 1216 dsoundLogDevice("Input", lpGUID, lpwstrDescription, lpwstrModule); 1277 if (pCtx->fFlags & DSOUNDENUMCBFLAGS_LOG) 1278 dsoundLogDevice("Input", lpGUID, lpwstrDescription, lpwstrModule); 1217 1279 1218 1280 int rc = dsoundDevAdd(&pCtx->pDrv->lstDevInput, … … 1226 1288 } 1227 1289 1290 /** 1291 * Does a (Re-)enumeration of the host's playback + capturing devices. 1292 * 1293 * @return IPRT status code. 1294 * @param pThis Host audio driver instance. 1295 * @param pCfg Where to store the enumeration results. 1296 * @param fEnum Enumeration flags. 1297 */ 1298 static int dsoundDevicesEnumerate(PDRVHOSTDSOUND pThis, PPDMAUDIOBACKENDCFG pCfg, uint32_t fEnum) 1299 { 1300 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1301 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1302 1303 dsoundDevicesClear(pThis); 1304 1305 pCfg->cMaxHstStrmsOut = 0; 1306 pCfg->cMaxHstStrmsIn = 0; 1307 1308 RTLDRMOD hDSound = NULL; 1309 int rc = RTLdrLoadSystem("dsound.dll", true /*fNoUnload*/, &hDSound); 1310 if (RT_SUCCESS(rc)) 1311 { 1312 PFNDIRECTSOUNDENUMERATEW pfnDirectSoundEnumerateW = NULL; 1313 PFNDIRECTSOUNDCAPTUREENUMERATEW pfnDirectSoundCaptureEnumerateW = NULL; 1314 1315 rc = RTLdrGetSymbol(hDSound, "DirectSoundEnumerateW", (void**)&pfnDirectSoundEnumerateW); 1316 if (RT_SUCCESS(rc)) 1317 rc = RTLdrGetSymbol(hDSound, "DirectSoundCaptureEnumerateW", (void**)&pfnDirectSoundCaptureEnumerateW); 1318 1319 if (RT_SUCCESS(rc)) 1320 { 1321 DSOUNDENUMCBCTX ctx = { pThis, pCfg, fEnum }; 1322 1323 HRESULT hr = pfnDirectSoundEnumerateW(&dsoundDevicesEnumCbPlayback, &ctx); 1324 if (FAILED(hr)) 1325 LogRel2(("DSound: Error enumerating host playback devices: %Rhrc\n", hr)); 1326 1327 hr = pfnDirectSoundCaptureEnumerateW(&dsoundDevicesEnumCbCapture, &ctx); 1328 if (FAILED(hr)) 1329 LogRel2(("DSound: Error enumerating host capturing devices: %Rhrc\n", hr)); 1330 } 1331 1332 RTLdrClose(hDSound); 1333 } 1334 else 1335 { 1336 /* No dsound.dll on this system. */ 1337 LogRel2(("DSound: Could not load dsound.dll: %Rrc\n", rc)); 1338 } 1339 1340 return rc; 1341 } 1342 1343 /** 1344 * Updates this host driver's internal status, according to the global, overall input/output 1345 * state and all connected (native) audio streams. 1346 * 1347 * @param pThis Host audio driver instance. 1348 * @param pCfg Where to store the backend configuration. Optional. 1349 * @param fEnum Enumeration flags. 1350 */ 1351 void dsoundUpdateStatusInternalEx(PDRVHOSTDSOUND pThis, PPDMAUDIOBACKENDCFG pCfg, uint32_t fEnum) 1352 { 1353 AssertPtrReturnVoid(pThis); 1354 /* pCfg is optional. */ 1355 1356 PDMAUDIOBACKENDCFG Cfg; 1357 RT_ZERO(Cfg); 1358 1359 Cfg.cbStreamOut = sizeof(DSOUNDSTREAMOUT); 1360 Cfg.cbStreamIn = sizeof(DSOUNDSTREAMIN); 1361 1362 int rc = dsoundDevicesEnumerate(pThis, &Cfg, fEnum); 1363 AssertRC(rc); 1364 1365 #ifdef VBOX_WITH_AUDIO_CALLBACKS 1366 if ( pThis->fEnabledOut != RT_BOOL(Cfg.cMaxHstStrmsOut) 1367 || pThis->fEnabledIn != RT_BOOL(Cfg.cMaxHstStrmsIn)) 1368 { 1369 /** @todo Use a registered callback to the audio connector (e.g "OnConfigurationChanged") to 1370 * let the connector know that something has changed within the host backend. */ 1371 } 1372 #else 1373 pThis->fEnabledOut = RT_BOOL(Cfg.cMaxHstStrmsOut); 1374 pThis->fEnabledIn = RT_BOOL(Cfg.cMaxHstStrmsIn); 1375 #endif 1376 1377 if (pCfg) 1378 memcpy(pCfg, &Cfg, sizeof(PDMAUDIOBACKENDCFG)); 1379 1380 LogFlowFuncLeaveRC(rc); 1381 } 1382 1383 void dsoundUpdateStatusInternal(PDRVHOSTDSOUND pThis) 1384 { 1385 dsoundUpdateStatusInternalEx(pThis, NULL /* pCfg */, 0 /* fEnum */); 1386 } 1228 1387 1229 1388 /* … … 1280 1439 LogFlowFunc(("pHstStrmOut=%p, cmd=%d\n", pHstStrmOut, enmStreamCmd)); 1281 1440 1282 PDRVHOSTDSOUND pThis= PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);1441 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1283 1442 PDSOUNDSTREAMOUT pDSoundStrmOut = (PDSOUNDSTREAMOUT)pHstStrmOut; 1284 1443 … … 1293 1452 DSLOG(("DSound: Playback PDMAUDIOSTREAMCMD_ENABLE\n")); 1294 1453 /* Try to start playback. If it fails, then reopen and try again. */ 1295 hr = directSoundPlayStart(p DSoundStrmOut);1454 hr = directSoundPlayStart(pThis, pDSoundStrmOut); 1296 1455 if (FAILED(hr)) 1297 1456 { 1298 directSoundPlayClose(pThis, pDSoundStrmOut); 1299 directSoundPlayOpen(pThis, pDSoundStrmOut); 1300 1301 hr = directSoundPlayStart(pDSoundStrmOut); 1457 hr = directSoundPlayClose(pThis, pDSoundStrmOut); 1458 if (SUCCEEDED(hr)) 1459 hr = directSoundPlayOpen(pThis, pDSoundStrmOut); 1460 if (SUCCEEDED(hr)) 1461 hr = directSoundPlayStart(pThis, pDSoundStrmOut); 1302 1462 } 1303 1463 1304 1464 if (FAILED(hr)) 1305 1465 rc = VERR_NOT_SUPPORTED; 1306 1307 pThis->fEnabledOut = RT_SUCCESS(rc);1308 1466 break; 1309 1467 } … … 1314 1472 DSLOG(("DSound: Playback PDMAUDIOSTREAMCMD_DISABLE\n")); 1315 1473 hr = directSoundPlayStop(pThis, pDSoundStrmOut); 1316 if ( SUCCEEDED(hr))1317 pThis->fEnabledOut = false;1474 if (FAILED(hr)) 1475 rc = VERR_NOT_SUPPORTED; 1318 1476 break; 1319 1477 } … … 1344 1502 uint32_t cReadTotal = 0; 1345 1503 1504 #ifdef DEBUG_andy 1505 LogFlowFuncEnter(); 1506 #endif 1507 1346 1508 do /* to use 'break' */ 1347 1509 { 1348 1510 DWORD cbBuffer, cbFree, cbPlayPos; 1349 rc = dsoundGet StatusOut(pDSoundStrmOut, &cbBuffer, &cbFree, &cbPlayPos);1511 rc = dsoundGetPosOut(pThis, pDSoundStrmOut, &cbBuffer, &cbFree, &cbPlayPos); 1350 1512 if (RT_FAILURE(rc)) 1351 { 1352 /* Set the output status to disabled, as we are not able to retrieve the current 1353 * status (anymore). */ 1354 pThis->fEnabledOut = false; 1355 break; 1356 } 1513 break; 1357 1514 1358 1515 /* … … 1384 1541 LPVOID pv1, pv2; 1385 1542 DWORD cb1, cb2; 1386 HRESULT hr = directSoundPlayLock(p DSB, &pHstStrmOut->Props, pDSoundStrmOut->cbPlayWritePos, cbLive,1543 HRESULT hr = directSoundPlayLock(pThis, pDSB, &pHstStrmOut->Props, pDSoundStrmOut->cbPlayWritePos, cbLive, 1387 1544 &pv1, &pv2, &cb1, &cb2, 0 /* dwFlags */); 1388 1545 if (FAILED(hr)) … … 1413 1570 } 1414 1571 1415 directSoundPlayUnlock(p DSB, pv1, pv2, cb1, cb2);1572 directSoundPlayUnlock(pThis, pDSB, pv1, pv2, cb1, cb2); 1416 1573 1417 1574 pDSoundStrmOut->cbPlayWritePos = … … 1445 1602 fFlags |= DSCBSTART_LOOPING; 1446 1603 #endif 1447 hr = IDirectSoundBuffer8_Play(pDSoundStrmOut->pDSB, 0, 0, fFlags); 1604 for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++) 1605 { 1606 hr = IDirectSoundBuffer8_Play(pDSoundStrmOut->pDSB, 0, 0, fFlags); 1607 if ( SUCCEEDED(hr) 1608 || hr != DSERR_BUFFERLOST) 1609 break; 1610 else 1611 { 1612 LogFlowFunc(("Restarting playback failed due to lost buffer, restoring ...\n")); 1613 directSoundPlayRestore(pThis, pDSoundStrmOut->pDSB); 1614 } 1615 } 1616 1448 1617 if (FAILED(hr)) 1449 1618 { … … 1456 1625 } while (0); 1457 1626 1458 if (RT_SUCCESS(rc)) 1627 if (RT_FAILURE(rc)) 1628 { 1629 dsoundUpdateStatusInternal(pThis); 1630 } 1631 else 1459 1632 { 1460 1633 if (pcSamplesPlayed) … … 1462 1635 } 1463 1636 1637 LogFlowFuncLeaveRC(rc); 1464 1638 return rc; 1465 1639 } … … 1530 1704 LogFlowFunc(("pHstStrmIn=%p, enmStreamCmd=%ld\n", pHstStrmIn, enmStreamCmd)); 1531 1705 1532 PDRVHOSTDSOUND pThis= PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface);1706 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1533 1707 PDSOUNDSTREAMIN pDSoundStrmIn = (PDSOUNDSTREAMIN)pHstStrmIn; 1534 1708 … … 1556 1730 if (FAILED(hr)) 1557 1731 rc = VERR_NOT_SUPPORTED; 1558 1559 pThis->fEnabledIn = RT_SUCCESS(rc);1560 1732 break; 1561 1733 } … … 1564 1736 case PDMAUDIOSTREAMCMD_PAUSE: 1565 1737 { 1566 hr = directSoundCaptureStop(p DSoundStrmIn);1567 if ( SUCCEEDED(hr))1568 pThis->fEnabledIn = false;1738 hr = directSoundCaptureStop(pThis, pDSoundStrmIn); 1739 if (FAILED(hr)) 1740 rc = VERR_NOT_SUPPORTED; 1569 1741 break; 1570 1742 } … … 1585 1757 { 1586 1758 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1587 PDSOUNDSTREAMIN pDSoundStrmIn = (PDSOUNDSTREAMIN)pHstStrmIn; 1588 LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB = pDSoundStrmIn->pDSCB; 1759 1760 PDSOUNDSTREAMIN pDSoundStrmIn = (PDSOUNDSTREAMIN)pHstStrmIn; 1761 LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB = pDSoundStrmIn->pDSCB; 1589 1762 1590 1763 int rc = VINF_SUCCESS; … … 1596 1769 if (pDSCB == NULL) 1597 1770 { 1598 pThis->fEnabledIn = false;1599 1600 1771 rc = VERR_NOT_AVAILABLE; 1601 1772 break; … … 1698 1869 } while (0); 1699 1870 1700 if (pcSamplesCaptured) 1701 *pcSamplesCaptured = cCaptured; 1702 1871 if (RT_FAILURE(rc)) 1872 { 1873 dsoundUpdateStatusInternal(pThis); 1874 } 1875 else 1876 { 1877 if (pcSamplesCaptured) 1878 *pcSamplesCaptured = cCaptured; 1879 } 1880 1881 LogFlowFuncLeaveRC(rc); 1703 1882 return rc; 1704 1883 } … … 1738 1917 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1739 1918 1740 dsoundFreeDeviceLists(pThis); 1741 1742 pCfg->cbStreamOut = sizeof(DSOUNDSTREAMOUT); 1743 pCfg->cbStreamIn = sizeof(DSOUNDSTREAMIN); 1744 1745 pCfg->cMaxHstStrmsOut = 0; 1746 pCfg->cMaxHstStrmsIn = 0; 1747 1748 RTLDRMOD hDSound = NULL; 1749 int rc = RTLdrLoadSystem("dsound.dll", true /*fNoUnload*/, &hDSound); 1750 if (RT_SUCCESS(rc)) 1751 { 1752 PFNDIRECTSOUNDENUMERATEW pfnDirectSoundEnumerateW = NULL; 1753 PFNDIRECTSOUNDCAPTUREENUMERATEW pfnDirectSoundCaptureEnumerateW = NULL; 1754 1755 rc = RTLdrGetSymbol(hDSound, "DirectSoundEnumerateW", (void**)&pfnDirectSoundEnumerateW); 1756 if (RT_SUCCESS(rc)) 1757 { 1758 rc = RTLdrGetSymbol(hDSound, "DirectSoundCaptureEnumerateW", (void**)&pfnDirectSoundCaptureEnumerateW); 1759 } 1760 1761 if (RT_SUCCESS(rc)) 1762 { 1763 DSOUNDENUMCBCTX ctx = { pThis, pCfg }; 1764 1765 HRESULT hr = pfnDirectSoundEnumerateW(&dsoundEnumCallback, &ctx); 1766 if (FAILED(hr)) 1767 LogRel(("DSound: Error enumerating host playback devices: %Rhrc\n", hr)); 1768 1769 LogRel(("DSound: Found %RU32 host playback devices\n", pCfg->cMaxHstStrmsOut)); 1770 1771 hr = pfnDirectSoundCaptureEnumerateW(&dsoundCaptureEnumCallback, &ctx); 1772 if (FAILED(hr)) 1773 LogRel(("DSound: Error enumerating host capturing devices: %Rhrc\n", hr)); 1774 1775 LogRel(("DSound: Found %RU32 host capturing devices\n", pCfg->cMaxHstStrmsIn)); 1776 } 1777 1778 RTLdrClose(hDSound); 1779 } 1780 else 1781 { 1782 /* No dsound.dll on this system. */ 1783 LogRel(("DSound: Could not load dsound.dll %Rrc\n", rc)); 1784 } 1785 1786 /* Always return success and at least default values to make the caller happy. */ 1787 if (pCfg->cMaxHstStrmsOut == 0) 1788 { 1789 LogRel(("DSound: Adjusting the number of host playback devices to 1\n")); 1790 pCfg->cMaxHstStrmsOut = 1; /* Support at least one stream. */ 1791 } 1792 1793 if (pCfg->cMaxHstStrmsIn < 2) 1794 { 1795 LogRel(("DSound: Adjusting the number of host capturing devices from %RU32 to 2\n", pCfg->cMaxHstStrmsIn)); 1796 pCfg->cMaxHstStrmsIn = 2; /* Support at least two streams (line in + mic). */ 1797 } 1919 dsoundUpdateStatusInternalEx(pThis, pCfg, 0 /* fEnum */); 1798 1920 1799 1921 return VINF_SUCCESS; … … 1871 1993 { 1872 1994 DWORD cbBuffer, cbFree, cbPlayPos; 1873 rc = dsoundGet StatusOut(pThis->pDSStrmOut, &cbBuffer, &cbFree, &cbPlayPos);1995 rc = dsoundGetPosOut(pThis->pDSStrmOut, &cbBuffer, &cbFree, &cbPlayPos); 1874 1996 if ( RT_SUCCESS(rc) 1875 1997 && cbFree) … … 1973 2095 rc = VINF_SUCCESS; 1974 2096 #endif 2097 2098 PDMAUDIOBACKENDCFG Cfg; 2099 dsoundUpdateStatusInternalEx(pThis, &Cfg, DSOUNDENUMCBFLAGS_LOG /* fEnum */); 2100 2101 DSLOGREL(("DSound: Found %RU32 host playback devices\n", Cfg.cMaxHstStrmsOut)); 2102 DSLOGREL(("DSound: Found %RU32 host capturing devices\n", Cfg.cMaxHstStrmsIn)); 1975 2103 } 1976 2104 else … … 2095 2223 pThis->fEnabledOut = false; 2096 2224 #ifdef VBOX_WITH_AUDIO_CALLBACKS 2097 pThis->fStopped = false;2098 pThis->fShutdown = false;2225 pThis->fStopped = false; 2226 pThis->fShutdown = false; 2099 2227 2100 2228 RT_ZERO(pThis->aEvents);
Note:
See TracChangeset
for help on using the changeset viewer.