Changeset 98075 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Jan 13, 2023 1:12:57 PM (2 years ago)
- svn:sync-xref-src-repo-rev:
- 155203
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r96407 r98075 99 99 100 100 /** @} */ 101 102 /** 103 * Experimental code for destroying all streams in a disabled direction rather 104 * than just disabling them. 105 106 * Disabled by default for non-Doxygen builds for now. 107 */ 108 #if defined(DOXYGEN_RUNNING) || 0 109 # define DRVAUDIO_WITH_STREAM_DESTRUCTION_IN_DISABLED_DIRECTION 110 #endif 101 111 102 112 … … 432 442 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd); 433 443 static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx); 444 #ifdef DRVAUDIO_WITH_STREAM_DESTRUCTION_IN_DISABLED_DIRECTION 445 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx); 446 static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx); 447 #endif 434 448 static uint32_t drvAudioStreamRetainInternal(PDRVAUDIOSTREAM pStreamEx); 435 449 static uint32_t drvAudioStreamReleaseInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, bool fMayDestroy); … … 597 611 if (pThis->pHostDrvAudio) 598 612 { 599 PDMHOSTAUDIOSTREAMSTATE enmState = pThis->pHostDrvAudio->pfnStreamGetState(pThis->pHostDrvAudio, pStreamEx->pBackend); 600 Log9Func(("%s: %s\n", pStreamEx->Core.Cfg.szName, PDMHostAudioStreamStateGetName(enmState) )); 601 Assert( enmState > PDMHOSTAUDIOSTREAMSTATE_INVALID 602 && enmState < PDMHOSTAUDIOSTREAMSTATE_END 603 && (enmState != PDMHOSTAUDIOSTREAMSTATE_DRAINING || pStreamEx->Core.Cfg.enmDir == PDMAUDIODIR_OUT)); 604 return enmState; 613 /* Don't call if the backend wasn't created for this stream (disabled). */ 614 if (pStreamEx->fStatus & PDMAUDIOSTREAM_STS_BACKEND_CREATED) 615 { 616 AssertPtrReturn(pThis->pHostDrvAudio->pfnStreamGetState, PDMHOSTAUDIOSTREAMSTATE_NOT_WORKING); 617 PDMHOSTAUDIOSTREAMSTATE enmState = pThis->pHostDrvAudio->pfnStreamGetState(pThis->pHostDrvAudio, pStreamEx->pBackend); 618 Log9Func(("%s: %s\n", pStreamEx->Core.Cfg.szName, PDMHostAudioStreamStateGetName(enmState) )); 619 Assert( enmState > PDMHOSTAUDIOSTREAMSTATE_INVALID 620 && enmState < PDMHOSTAUDIOSTREAMSTATE_END 621 && (enmState != PDMHOSTAUDIOSTREAMSTATE_DRAINING || pStreamEx->Core.Cfg.enmDir == PDMAUDIODIR_OUT)); 622 return enmState; 623 } 605 624 } 606 625 Log9Func(("%s: not-working\n", pStreamEx->Core.Cfg.szName)); … … 843 862 { 844 863 LogRel(("Audio: %s %s for driver '%s'\n", 845 fEnable ? "Enabling" : "Disabling", enmDir == PDMAUDIODIR_IN ? "input" : "output", pThis->BackendCfg.szName));864 fEnable ? "Enabling" : "Disabling", PDMAudioDirGetName(enmDir), pThis->BackendCfg.szName)); 846 865 847 866 /* … … 859 878 * only silence. This means pStreamEx->fStatus holds the nominal status 860 879 * and we'll use it to restore the operation. (See also @bugref{9882}.) 880 * 881 * The DRVAUDIO_WITH_STREAM_DESTRUCTION_IN_DISABLED_DIRECTION build time define 882 * controls how this is implemented. 861 883 */ 862 884 PDRVAUDIOSTREAM pStreamEx; 863 885 RTListForEach(&pThis->LstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry) 864 886 { 887 /** @todo duplex streams */ 865 888 if (pStreamEx->Core.Cfg.enmDir == enmDir) 866 889 { … … 873 896 pStreamEx->Core.fWarningsShown &= ~PDMAUDIOSTREAM_WARN_FLAGS_DISABLED; 874 897 898 #ifdef DRVAUDIO_WITH_STREAM_DESTRUCTION_IN_DISABLED_DIRECTION 899 /* 900 * When enabling, we must make sure the stream has been created with the 901 * backend before enabling and maybe pausing it. When disabling we must 902 * destroy the stream. Paused includes enabled, as does draining, but we 903 * only want the former. 904 */ 905 #else 875 906 /* 876 907 * We don't need to do anything unless the stream is enabled. 877 908 * Paused includes enabled, as does draining, but we only want the former. 878 909 */ 910 #endif 879 911 uint32_t const fStatus = pStreamEx->fStatus; 912 913 #ifndef DRVAUDIO_WITH_STREAM_DESTRUCTION_IN_DISABLED_DIRECTION 880 914 if (fStatus & PDMAUDIOSTREAM_STS_ENABLED) 915 #endif 881 916 { 882 917 const char *pszOperation; … … 886 921 if (!(fStatus & PDMAUDIOSTREAM_STS_PENDING_DISABLE)) 887 922 { 888 /** @todo r=bird: We need to redo pre-buffering OR switch to 889 * DRVAUDIOPLAYSTATE_PREBUF_SWITCHING playback mode when disabling 890 * output streams. The former is preferred if associated with 891 * reporting the stream as INACTIVE. */ 892 rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_ENABLE); 893 pszOperation = "enable"; 894 if (RT_SUCCESS(rc2) && (fStatus & PDMAUDIOSTREAM_STS_PAUSED)) 923 #ifdef DRVAUDIO_WITH_STREAM_DESTRUCTION_IN_DISABLED_DIRECTION 924 /* The backend shouldn't have been created, so do that before enabling 925 and possibly pausing the stream. */ 926 if (!(fStatus & PDMAUDIOSTREAM_STS_BACKEND_CREATED)) 927 rc2 = drvAudioStreamReInitInternal(pThis, pStreamEx); 928 else 929 rc2 = VINF_SUCCESS; 930 pszOperation = "re-init"; 931 if (RT_SUCCESS(rc2) && (fStatus & PDMAUDIOSTREAM_STS_ENABLED)) 932 #endif 895 933 { 896 rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_PAUSE); 897 pszOperation = "pause"; 934 /** @todo r=bird: We need to redo pre-buffering OR switch to 935 * DRVAUDIOPLAYSTATE_PREBUF_SWITCHING playback mode when disabling 936 * output streams. The former is preferred if associated with 937 * reporting the stream as INACTIVE. */ 938 rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_ENABLE); 939 pszOperation = "enable"; 940 if (RT_SUCCESS(rc2) && (fStatus & PDMAUDIOSTREAM_STS_PAUSED)) 941 { 942 rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_PAUSE); 943 pszOperation = "pause"; 944 } 898 945 } 899 946 } … … 906 953 else 907 954 { 955 #ifdef DRVAUDIO_WITH_STREAM_DESTRUCTION_IN_DISABLED_DIRECTION 956 if (fStatus & PDMAUDIOSTREAM_STS_BACKEND_CREATED) 957 rc2 = drvAudioStreamDestroyInternalBackend(pThis, pStreamEx); 958 else 959 rc2 = VINF_SUCCESS; 960 pszOperation = "destroy"; 961 #else 908 962 rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE); 909 963 pszOperation = "disable"; 964 #endif 910 965 } 911 966 if (RT_FAILURE(rc2)) 912 967 { 913 968 LogRel(("Audio: Failed to %s %s stream '%s': %Rrc\n", 914 pszOperation, enmDir == PDMAUDIODIR_IN ? "input" : "output", pStreamEx->Core.Cfg.szName, rc2));969 pszOperation, PDMAudioDirGetName(enmDir), pStreamEx->Core.Cfg.szName, rc2)); 915 970 if (RT_SUCCESS(rc)) 916 971 rc = rc2; /** @todo r=bird: This isn't entirely helpful to the caller since we'll update the status … … 1211 1266 1212 1267 /** 1268 * Checks whether a given stream direction is enabled (permitted) or not. 1269 * 1270 * Currently there are only per-direction enabling/disabling of audio streams. 1271 * This lets a user disabling input so it an untrusted VM cannot listen in 1272 * without the user explicitly allowing it, or disable output so it won't 1273 * disturb your and cannot communicate with other VMs or machines 1274 * 1275 * See @bugref{9882}. 1276 * 1277 * @retval true if the stream configuration is enabled/allowed. 1278 * @retval false if not permitted. 1279 * @param pThis Pointer to the DrvAudio instance data. 1280 * @param enmDir The stream direction to check. 1281 */ 1282 DECLINLINE(bool) drvAudioStreamIsDirectionEnabled(PDRVAUDIO pThis, PDMAUDIODIR enmDir) 1283 { 1284 switch (enmDir) 1285 { 1286 case PDMAUDIODIR_IN: 1287 return pThis->In.fEnabled; 1288 case PDMAUDIODIR_OUT: 1289 return pThis->Out.fEnabled; 1290 case PDMAUDIODIR_DUPLEX: 1291 return pThis->Out.fEnabled && pThis->In.fEnabled; 1292 default: 1293 AssertFailedReturn(false); 1294 } 1295 } 1296 1297 1298 /** 1213 1299 * @interface_method_impl{PDMIAUDIOCONNECTOR,pfnStreamConfigHint} 1214 1300 */ … … 1228 1314 && pThis->pHostDrvAudio->pfnStreamConfigHint) 1229 1315 { 1230 if ( pCfg->enmDir == PDMAUDIODIR_OUT ? pThis->Out.fEnabled : pThis->In.fEnabled)1316 if (drvAudioStreamIsDirectionEnabled(pThis, pCfg->enmDir)) 1231 1317 { 1232 1318 /* … … 1434 1520 ("Stream '%s' already initialized in backend\n", pStreamEx->Core.Cfg.szName)); 1435 1521 1522 #ifdef DRVAUDIO_WITH_STREAM_DESTRUCTION_IN_DISABLED_DIRECTION 1523 /* 1524 * Check if the stream direction is enabled (permitted). 1525 */ 1526 if (!drvAudioStreamIsDirectionEnabled(pThis, pStreamEx->Core.Cfg.enmDir)) 1527 { 1528 LogFunc(("Stream direction is disbled, returning w/o doing anything\n")); 1529 return VINF_SUCCESS; 1530 } 1531 #endif 1532 1436 1533 /* 1437 1534 * Adjust the stream config, applying defaults and any overriding settings. … … 1843 1940 if (!pStreamEx->fNeedAsyncInit) 1844 1941 { 1845 pStreamEx->fStatus |= PDMAUDIOSTREAM_STS_BACKEND_READY; 1942 #ifdef DRVAUDIO_WITH_STREAM_DESTRUCTION_IN_DISABLED_DIRECTION 1943 /* drvAudioStreamInitInternal returns success for disable stream directions w/o actually 1944 creating a backend, so we need to check that before marking the backend ready.. */ 1945 if (pStreamEx->fStatus & PDMAUDIOSTREAM_STS_BACKEND_CREATED) 1946 #endif 1947 pStreamEx->fStatus |= PDMAUDIOSTREAM_STS_BACKEND_READY; 1846 1948 PDMAUDIOSTREAM_STS_ASSERT_VALID(pStreamEx->fStatus); 1847 1949 } … … 2497 2599 * finish initializing the stream, we'll update it about the stream state. 2498 2600 */ 2499 bool const fDirEnabled = pStreamEx->Core.Cfg.enmDir == PDMAUDIODIR_IN 2500 ? pThis->In.fEnabled : pThis->Out.fEnabled; 2601 bool const fDirEnabled = drvAudioStreamIsDirectionEnabled(pThis, pStreamEx->Core.Cfg.enmDir); 2501 2602 PDMHOSTAUDIOSTREAMSTATE const enmBackendState = drvAudioStreamGetBackendState(pThis, pStreamEx); 2502 2603 /* ^^^ (checks pThis->pHostDrvAudio != NULL too) */ … … 2620 2721 { 2621 2722 case PDMAUDIOSTREAMCMD_ENABLE: 2723 #ifdef DRVAUDIO_WITH_STREAM_DESTRUCTION_IN_DISABLED_DIRECTION 2724 if (!(pStreamEx->fStatus & PDMAUDIOSTREAM_STS_BACKEND_CREATED)) 2725 { 2726 rc = drvAudioStreamReInitInternal(pThis, pStreamEx); 2727 if (RT_FAILURE(rc)) 2728 break; 2729 } 2730 #endif /* DRVAUDIO_WITH_STREAM_DESTRUCTION_IN_DISABLED_DIRECTION */ 2622 2731 if (!(pStreamEx->fStatus & PDMAUDIOSTREAM_STS_ENABLED)) 2623 2732 { … … 2713 2822 2714 2823 case PDMAUDIOSTREAMCMD_DISABLE: 2824 #ifndef DRVAUDIO_WITH_STREAM_DESTRUCTION_IN_DISABLED_DIRECTION 2715 2825 if (pStreamEx->fStatus & PDMAUDIOSTREAM_STS_ENABLED) 2716 2826 { … … 2720 2830 drvAudioStreamResetOnDisable(pStreamEx); 2721 2831 } 2832 #else 2833 if (pStreamEx->fStatus & PDMAUDIOSTREAM_STS_BACKEND_CREATED) 2834 rc = drvAudioStreamDestroyInternalBackend(pThis, pStreamEx); 2835 #endif /* DRVAUDIO_WITH_STREAM_DESTRUCTION_IN_DISABLED_DIRECTION */ 2722 2836 break; 2723 2837 … … 3254 3368 { 3255 3369 if ( (fStrmStatus & PDMAUDIOSTREAM_STS_ENABLED) 3256 && (enmDir == PDMAUDIODIR_IN ? pThis->In.fEnabled : pThis->Out.fEnabled)3370 && drvAudioStreamIsDirectionEnabled(pThis, pStreamEx->Core.Cfg.enmDir) 3257 3371 && ( enmBackendState == PDMHOSTAUDIOSTREAMSTATE_OKAY 3258 3372 || enmBackendState == PDMHOSTAUDIOSTREAMSTATE_DRAINING … … 3969 4083 PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IHostAudioPort); 3970 4084 AssertReturnVoid(enmDir == PDMAUDIODIR_IN || enmDir == PDMAUDIODIR_OUT); 3971 LogRel(("Audio: The %s device for %s is changing.\n", enmDir == PDMAUDIODIR_IN ? "input" : "output", pThis->BackendCfg.szName));4085 LogRel(("Audio: The %s device for %s is changing.\n", PDMAudioDirGetName(enmDir), pThis->BackendCfg.szName)); 3972 4086 3973 4087 /*
Note:
See TracChangeset
for help on using the changeset viewer.