Changeset 88653 in vbox
- Timestamp:
- Apr 22, 2021 2:00:28 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 143967
- Location:
- trunk/src/VBox
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r88646 r88653 128 128 129 129 /** 130 * Runtime configurable debug stuff for a SB16 stream. 131 */ 132 typedef struct SB16STREAMDEBUGRT 133 { 134 /** Whether debugging is enabled or not. */ 135 bool fEnabled; 136 uint8_t Padding[7]; 137 /** File for dumping DMA reads / writes. 138 * For input streams, this dumps data being written to the device DMA, 139 * whereas for output streams this dumps data being read from the device DMA. */ 140 R3PTRTYPE(PAUDIOHLPFILE) pFileDMA; 141 } SB16STREAMDEBUGRT; 142 143 /** 144 * Debug stuff for a SB16 stream. 145 */ 146 typedef struct SB16STREAMDEBUG 147 { 148 /** Runtime debug stuff. */ 149 SB16STREAMDEBUGRT Runtime; 150 } SB16STREAMDEBUG; 151 152 /** 130 153 * Structure for a SB16 stream. 131 154 */ … … 133 156 { 134 157 /** The stream's current configuration. */ 135 PDMAUDIOSTREAMCFG Cfg; 158 PDMAUDIOSTREAMCFG Cfg; 159 /** Debug stuff. */ 160 SB16STREAMDEBUG Dbg; 136 161 } SB16STREAM; 137 162 /** Pointer to a SB16 stream */ 138 163 typedef SB16STREAM *PSB16STREAM; 164 165 /** 166 * SB16 debug settings. 167 */ 168 typedef struct SB16STATEDEBUG 169 { 170 /** Whether debugging is enabled or not. */ 171 bool fEnabled; 172 bool afAlignment[7]; 173 /** Path where to dump the debug output to. 174 * Can be NULL, in which the system's temporary directory will be used then. */ 175 R3PTRTYPE(char *) pszOutPath; 176 } SB16STATEDEBUG; 139 177 140 178 /** … … 232 270 IOMIOPORTHANDLE hIoPortsDsp; 233 271 272 /** Debug settings. */ 273 SB16STATEDEBUG Dbg; 274 234 275 /* mixer state */ 235 276 uint8_t mixer_nreg; … … 242 283 *********************************************************************************************************************************/ 243 284 static int sb16CheckAndReOpenOut(PPDMDEVINS pDevIns, PSB16STATE pThis); 244 static int sb16StreamOpen(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream, PPDMAUDIOSTREAMCFG pCfg); 245 static void sb16StreamClose(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream); 285 static int sb16StreamEnable(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream, bool fEnable); 286 static int sb16StreamOpen(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream); 287 static void sb16StreamClose(PSB16STATE pThis, PSB16STREAM pStream); 288 DECLINLINE(PAUDMIXSINK) sb16StreamToSink(PSB16STATE pThis, PSB16STREAM pStream); 246 289 static void sb16TimerMaybeStart(PPDMDEVINS pDevIns, PSB16STATE pThis); 247 290 static void sb16TimerMaybeStop(PSB16STATE pThis); … … 278 321 PDMDevHlpDMASetDREQ(pThis->pDevInsR3, dma, hold); 279 322 280 int rc2 = AudioMixerSinkCtl(pThis->pSinkOut,281 hold == 1 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE);282 AssertRC(rc2);323 /* We only support one output stream at the moment, so keep things easy here for now. */ 324 PSB16STREAM pStream = &pThis->StreamOut; 325 sb16StreamEnable(pDevIns, pThis, pStream, RT_BOOL(hold)); 283 326 284 327 if (hold) … … 893 936 } 894 937 895 static void sb16CmdResetLegacy(P PDMDEVINS pDevIns, PSB16STATE pThis)938 static void sb16CmdResetLegacy(PSB16STATE pThis) 896 939 { 897 940 LogFlowFuncEnter(); … … 912 955 RTStrCopy(pStream->Cfg.szName, sizeof(pStream->Cfg.szName), "Output"); 913 956 914 sb16StreamClose(p DevIns, pThis, pStream);957 sb16StreamClose(pThis, pStream); 915 958 } 916 959 … … 940 983 941 984 sb16Control(pDevIns, pThis, 0); 942 sb16CmdResetLegacy(p DevIns, pThis);985 sb16CmdResetLegacy(pThis); 943 986 } 944 987 … … 1506 1549 * Worker for sb16DMARead. 1507 1550 */ 1508 static int sb16WriteAudio(PSB16STATE pThis, int nchan, uint32_t dma_pos, uint32_t dma_len, uint32_t len, uint32_t *pcbWritten) 1551 static int sb16WriteAudio(PSB16STATE pThis, 1552 PSB16STREAM pStream, int nchan, uint32_t dma_pos, uint32_t dma_len, uint32_t len, uint32_t *pcbWritten) 1509 1553 { 1510 1554 uint8_t abBuf[_4K]; /** @todo Have a buffer on the heap. */ … … 1528 1572 AssertMsgRCReturn(rc, ("Reading from DMA failed, rc=%Rrc\n", rc), rc); 1529 1573 1530 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA 1531 if (cbRead) 1532 { 1533 RTFILE fh; 1534 RTFileOpen(&fh, VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "sb16WriteAudio.pcm", 1535 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 1536 RTFileWrite(fh, abBuf, cbRead, NULL); 1537 RTFileClose(fh); 1538 } 1539 #endif 1574 if (RT_LIKELY(!pStream->Dbg.Runtime.fEnabled)) 1575 { /* likely */ } 1576 else 1577 AudioHlpFileWrite(pStream->Dbg.Runtime.pFileDMA, abBuf, cbRead, 0 /* fFlags */); 1578 1540 1579 /* 1541 1580 * Write data to the backends. … … 1566 1605 1567 1606 { 1568 RT_NOREF(pDevIns); 1569 PSB16STATE pThis = (PSB16STATE)pvUser; 1607 PSB16STATE pThis = PDMDEVINS_2_DATA(pDevIns, PSB16STATE); 1608 AssertPtr(pThis); 1609 PSB16STREAM pStream = (PSB16STREAM)pvUser; 1610 AssertPtr(pStream); 1611 1570 1612 int till, copy, free; 1571 1613 … … 1602 1644 1603 1645 uint32_t cbWritten; 1604 int rc = sb16WriteAudio(pThis, uChannel, off, cb, copy, &cbWritten);1646 int rc = sb16WriteAudio(pThis, pStream, uChannel, off, cb, copy, &cbWritten); 1605 1647 AssertRC(rc); 1606 1648 … … 1939 1981 if (pThis->freq > 0) 1940 1982 { 1941 /* At the moment we only have one stream, the output stream. */ 1942 PDMAUDIOSTREAMCFG Cfg; 1943 RT_ZERO(Cfg); 1944 PDMAudioPropsInit(&Cfg.Props, pThis->fmt_bits / 8, pThis->fmt_signed != 0, 1 << pThis->fmt_stereo, pThis->freq); 1945 1946 if (!PDMAudioStrmCfgMatchesProps(&Cfg, &pStream->Cfg.Props)) 1947 { 1948 Cfg.enmDir = PDMAUDIODIR_OUT; 1949 Cfg.u.enmDst = PDMAUDIOPLAYBACKDST_FRONT; 1950 Cfg.enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED; 1951 1952 RTStrCopy(Cfg.szName, sizeof(Cfg.szName), "Output"); 1953 1954 sb16StreamClose(pDevIns, pThis, pStream); 1955 1956 rc = sb16StreamOpen(pDevIns, pThis, pStream, &Cfg); 1957 AssertRC(rc); 1958 } 1983 sb16StreamEnable(pDevIns, pThis, pStream, false /* fEnable */); 1984 1985 sb16StreamEnable(pDevIns, pThis, pStream, true /* fEnable */); 1959 1986 } 1960 1987 else 1961 sb16Stream Close(pDevIns, pThis, pStream);1988 sb16StreamEnable(pDevIns, pThis, pStream, false /* fEnable */); 1962 1989 1963 1990 LogFlowFuncLeaveRC(rc); 1964 1991 return rc; 1992 } 1993 1994 /** 1995 * Enables or disables a SB16 audio stream. 1996 * 1997 * @returns VBox status code. 1998 * @param pDevIns The device instance. 1999 * @param pThis The SB16 state. 2000 * @param pStream The SB16 stream to enable or disable. 2001 * @param fEnable Whether to enable or disable the stream. 2002 */ 2003 static int sb16StreamEnable(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream, bool fEnable) 2004 { 2005 int rc = VINF_SUCCESS; 2006 2007 if (fEnable) 2008 { 2009 if (RT_LIKELY(!pStream->Dbg.Runtime.fEnabled)) 2010 { /* likely */ } 2011 else 2012 { 2013 if (!AudioHlpFileIsOpen(pStream->Dbg.Runtime.pFileDMA)) 2014 { 2015 int rc2 = AudioHlpFileOpen(pStream->Dbg.Runtime.pFileDMA, AUDIOHLPFILE_DEFAULT_OPEN_FLAGS, 2016 &pStream->Cfg.Props); 2017 AssertRC(rc2); 2018 } 2019 } 2020 2021 rc = sb16StreamOpen(pDevIns, pThis, pStream); 2022 } 2023 else 2024 sb16StreamClose(pThis, pStream); 2025 2026 if (RT_SUCCESS(rc)) 2027 { 2028 rc = AudioMixerSinkCtl(sb16StreamToSink(pThis, pStream), 2029 fEnable ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE); 2030 } 2031 2032 return rc; 2033 } 2034 2035 /** 2036 * Retrieves the audio mixer sink of a corresponding SB16 stream. 2037 * 2038 * @returns Pointer to audio mixer sink if found, or NULL if not found / invalid. 2039 * @param pThis The SB16 state. 2040 * @param pStream Stream to get audio mixer sink for. 2041 */ 2042 DECLINLINE(PAUDMIXSINK) sb16StreamToSink(PSB16STATE pThis, PSB16STREAM pStream) 2043 { 2044 /* Dead simple for now; make this more sophisticated if we have more stuff to cover. */ 2045 if (pStream->Cfg.enmDir == PDMAUDIODIR_OUT) 2046 return pThis->pSinkOut; /* Can be NULL if not configured / set up yet. */ 2047 2048 AssertFailed(); 2049 return NULL; 2050 } 2051 2052 /** 2053 * Creates a SB16 audio stream. 2054 * 2055 * @returns VBox status code. 2056 * @param pThisCC The SB16 state. 2057 * @param pStream The SB16 stream to create. 2058 * @param fIn Whether this is the input (recording) or output (playback) stream. 2059 */ 2060 static int sb16StreamCreate(PSB16STATE pThis, PSB16STREAM pStream, bool fIn) 2061 { 2062 LogFlowFuncEnter(); 2063 2064 pStream->Dbg.Runtime.fEnabled = pThis->Dbg.fEnabled; 2065 2066 if (RT_LIKELY(!pStream->Dbg.Runtime.fEnabled)) 2067 { /* likely */ } 2068 else 2069 { 2070 char szFile[64]; 2071 RTStrPrintf(szFile, sizeof(szFile), "sb16Stream%s", fIn ? "In" : "Out"); 2072 2073 char szPath[RTPATH_MAX]; 2074 int rc2 = AudioHlpFileNameGet(szPath, sizeof(szPath), pThis->Dbg.pszOutPath, szFile, 2075 0 /* uInst */, AUDIOHLPFILETYPE_WAV, AUDIOHLPFILENAME_FLAGS_NONE); 2076 AssertRC(rc2); 2077 rc2 = AudioHlpFileCreate(AUDIOHLPFILETYPE_WAV, szPath, AUDIOHLPFILE_FLAGS_NONE, &pStream->Dbg.Runtime.pFileDMA); 2078 AssertRC(rc2); 2079 2080 /* Delete stale debugging files from a former run. */ 2081 AudioHlpFileDelete(pStream->Dbg.Runtime.pFileDMA); 2082 } 2083 2084 return VINF_SUCCESS; 2085 } 2086 2087 /** 2088 * Destroys a SB16 audio stream. 2089 * 2090 * @returns VBox status code. 2091 * @param pThis The SB16 state. 2092 * @param pStream The SB16 stream to destroy. 2093 */ 2094 static int sb16StreamDestroy(PSB16STATE pThis, PSB16STREAM pStream) 2095 { 2096 RT_NOREF(pThis); 2097 2098 LogFlowFuncEnter(); 2099 2100 sb16StreamClose(pThis, pStream); 2101 2102 if (RT_LIKELY(!pStream->Dbg.Runtime.fEnabled)) 2103 { /* likely */ } 2104 else 2105 { 2106 AudioHlpFileDestroy(pStream->Dbg.Runtime.pFileDMA); 2107 pStream->Dbg.Runtime.pFileDMA = NULL; 2108 } 2109 2110 return VINF_SUCCESS; 1965 2111 } 1966 2112 … … 1972 2118 * @param pThis The SB16 device state. 1973 2119 * @param pStream The SB16 stream to open. 1974 * @param pCfg Stream configuration to use for opening the stream.1975 2120 * 1976 2121 * @note This currently only supports the one and only output stream. 1977 2122 */ 1978 static int sb16StreamOpen(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream , PPDMAUDIOSTREAMCFG pCfg)2123 static int sb16StreamOpen(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream) 1979 2124 { 1980 2125 LogFlowFuncEnter(); 1981 2126 1982 if (!AudioHlpStreamCfgIsValid(pCfg)) 1983 return VERR_INVALID_PARAMETER; 1984 1985 /** @todo Implement mixer sink selection (and it's in/out + destination mapping) here once we add more streams. */ 1986 PAUDMIXSINK pMixerSink = pThis->pSinkOut; 1987 AssertPtr(pMixerSink); 1988 2127 PAUDMIXSINK pMixerSink; 1989 2128 PDMAUDIODSTSRCUNION dstSrc; 1990 dstSrc.enmDst = PDMAUDIOPLAYBACKDST_FRONT; 1991 1992 PDMAUDIODIR enmDir = PDMAUDIODIR_OUT; 1993 1994 int rc = PDMAudioStrmCfgCopy(&pStream->Cfg, pCfg); 2129 PDMAUDIODIR enmDir; 2130 2131 int rc = VINF_SUCCESS; 2132 2133 { 2134 /** @todo Implement mixer sink selection (and it's in/out + destination mapping) here once we add more streams. */ 2135 PDMAUDIOSTREAMCFG Cfg; 2136 RT_ZERO(Cfg); 2137 PDMAudioPropsInit(&Cfg.Props, pThis->fmt_bits / 8, pThis->fmt_signed != 0, 1 << pThis->fmt_stereo, pThis->freq); 2138 2139 if (!PDMAudioStrmCfgMatchesProps(&Cfg, &pStream->Cfg.Props)) 2140 { 2141 Cfg.enmDir = PDMAUDIODIR_OUT; 2142 Cfg.u.enmDst = PDMAUDIOPLAYBACKDST_FRONT; 2143 Cfg.enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED; 2144 2145 RTStrCopy(Cfg.szName, sizeof(Cfg.szName), "Output"); 2146 2147 rc = PDMAudioStrmCfgCopy(&pStream->Cfg, &Cfg); 2148 } 2149 2150 pMixerSink = pThis->pSinkOut; 2151 dstSrc.enmDst = PDMAUDIOPLAYBACKDST_FRONT; 2152 enmDir = PDMAUDIODIR_OUT; 2153 } 2154 2155 if (RT_FAILURE(rc)) 2156 return rc; 2157 2158 /* Set scheduling hint (if available). */ 2159 if (pThis->cTicksTimerIOInterval) 2160 pStream->Cfg.Device.cMsSchedulingHint = 1000 /* ms */ 2161 / ( PDMDevHlpTimerGetFreq(pDevIns, pThis->hTimerIO) 2162 / RT_MIN(pThis->cTicksTimerIOInterval, 1)); 2163 2164 sb16RemoveDrvStreams(pDevIns, pThis, pMixerSink, enmDir, dstSrc); 2165 2166 rc = sb16AddDrvStreams(pDevIns, pThis, pMixerSink, &pStream->Cfg); 1995 2167 if (RT_SUCCESS(rc)) 1996 { 1997 /* Set scheduling hint (if available). */ 1998 if (pThis->cTicksTimerIOInterval) 1999 pStream->Cfg.Device.cMsSchedulingHint = 1000 /* ms */ 2000 / ( PDMDevHlpTimerGetFreq(pDevIns, pThis->hTimerIO) 2001 / RT_MIN(pThis->cTicksTimerIOInterval, 1)); 2002 2003 sb16RemoveDrvStreams(pDevIns, pThis, pMixerSink, enmDir, dstSrc); 2004 2005 rc = sb16AddDrvStreams(pDevIns, pThis, pMixerSink, &pStream->Cfg); 2006 if (RT_SUCCESS(rc)) 2007 sb16UpdateVolume(pThis); 2008 } 2168 sb16UpdateVolume(pThis); 2009 2169 2010 2170 LogFlowFuncLeaveRC(rc); … … 2015 2175 * Closes a SB16 stream. 2016 2176 * 2017 * @param pDevIns The device instance.2018 2177 * @param pThis SB16 state. 2019 2178 * @param pStream The SB16 stream to close. 2020 2179 */ 2021 static void sb16StreamClose(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream) 2022 { 2180 static void sb16StreamClose(PSB16STATE pThis, PSB16STREAM pStream) 2181 { 2182 RT_NOREF(pThis, pStream); 2183 2023 2184 LogFlowFuncEnter(); 2024 2025 /** @todo Implement mixer sink selection (and it's in/out + destination mapping) here once we add more streams. */2026 RT_NOREF(pStream);2027 PAUDMIXSINK pMixerSink = pThis->pSinkOut;2028 AssertPtr(pMixerSink);2029 2030 PDMAUDIODSTSRCUNION dstSrc;2031 dstSrc.enmDst = PDMAUDIOPLAYBACKDST_FRONT;2032 2033 PDMAUDIODIR enmDir = PDMAUDIODIR_OUT;2034 2035 sb16RemoveDrvStreams(pDevIns, pThis, pMixerSink, enmDir, dstSrc);2036 2185 2037 2186 LogFlowFuncLeave(); … … 2452 2601 sb16SpeakerControl(pThis, 0); 2453 2602 sb16Control(pDevIns, pThis, 0); 2454 sb16CmdResetLegacy(p DevIns, pThis);2603 sb16CmdResetLegacy(pThis); 2455 2604 } 2456 2605 … … 2469 2618 * Destroy all streams. 2470 2619 */ 2471 sb16StreamClose(pDevIns, pThis, &pThis->StreamOut); 2620 sb16StreamClose(pThis, &pThis->StreamOut); 2621 sb16StreamDestroy(pThis, &pThis->StreamOut); 2622 /** @todo Add removal + destruction of other streams here once we support them. */ 2472 2623 2473 2624 /* … … 2479 2630 pThis->pSinkOut = NULL; 2480 2631 } 2481 2482 /** @todo Add removal + destruction of other streams here once we support them. */ 2632 /** @todo Ditto for sinks. */ 2483 2633 2484 2634 /* … … 2543 2693 * Validate and read config data. 2544 2694 */ 2545 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "IRQ|DMA|DMA16|Port|Version|TimerHz ", "");2695 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "IRQ|DMA|DMA16|Port|Version|TimerHz|DebugEnabled|DebugPathOut", ""); 2546 2696 int rc = pHlp->pfnCFGMQuerySIntDef(pCfg, "IRQ", &pThis->irq, 5); 2547 2697 if (RT_FAILURE(rc)) … … 2582 2732 return PDMDEV_SET_ERROR(pDevIns, rc, N_("SB16 configuration error: Max TimerHz value is 2048.")); 2583 2733 2734 rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "DebugEnabled", &pThis->Dbg.fEnabled, false); 2735 if (RT_FAILURE(rc)) 2736 return PDMDEV_SET_ERROR(pDevIns, rc, 2737 N_("SB16 configuration error: failed to read debugging enabled flag as boolean")); 2738 2739 rc = pHlp->pfnCFGMQueryStringAllocDef(pCfg, "DebugPathOut", &pThis->Dbg.pszOutPath, NULL); 2740 if (RT_FAILURE(rc)) 2741 return PDMDEV_SET_ERROR(pDevIns, rc, 2742 N_("SB16 configuration error: failed to read debugging output path flag as string")); 2743 2744 if (pThis->Dbg.fEnabled) 2745 LogRel2(("SB16: Debug output will be saved to '%s'\n", pThis->Dbg.pszOutPath)); 2746 2584 2747 /* 2585 2748 * Create internal software mixer. … … 2592 2755 rc = AudioMixerCreateSink(pThis->pMixer, "PCM Output", 2593 2756 AUDMIXSINKDIR_OUTPUT, pDevIns, &pThis->pSinkOut); 2757 AssertRCReturn(rc, rc); 2758 2759 /* 2760 * Create all hardware streams. 2761 * For now we have one stream only, namely the output (playback) stream. 2762 */ 2763 rc = sb16StreamCreate(pThis, &pThis->StreamOut, false /* fIn */); 2594 2764 AssertRCReturn(rc, rc); 2595 2765 … … 2653 2823 AssertRCReturn(rc, rc); 2654 2824 2655 rc = PDMDevHlpDMARegister(pDevIns, pThis->hdma, sb16DMARead, pThis);2825 rc = PDMDevHlpDMARegister(pDevIns, pThis->hdma, sb16DMARead, &pThis->StreamOut /* pvUser */); 2656 2826 AssertRCReturn(rc, rc); 2657 rc = PDMDevHlpDMARegister(pDevIns, pThis->dma, sb16DMARead, pThis);2827 rc = PDMDevHlpDMARegister(pDevIns, pThis->dma, sb16DMARead, &pThis->StreamOut /* pvUser */); 2658 2828 AssertRCReturn(rc, rc); 2659 2829 … … 2683 2853 } 2684 2854 2685 sb16CmdResetLegacy(p DevIns, pThis);2855 sb16CmdResetLegacy(pThis); 2686 2856 2687 2857 #ifdef VBOX_WITH_AUDIO_SB16_ONETIME_INIT … … 2716 2886 } 2717 2887 } 2718 #endif2719 2720 /*2721 * Delete debug file.2722 */2723 #ifdef VBOX_AUDIO_DEBUG_DUMP_PCM_DATA2724 RTFileDelete(VBOX_AUDIO_DEBUG_DUMP_PCM_DATA_PATH "sb16WriteAudio.pcm");2725 2888 #endif 2726 2889 -
trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
r88490 r88653 3056 3056 if (uTimerHz) 3057 3057 InsertConfigInteger(pCfg, "TimerHz", uTimerHz); 3058 InsertConfigInteger(pCfg, "DebugEnabled", fDebugEnabled); 3059 if (strDebugPathOut.isNotEmpty()) 3060 InsertConfigString(pCfg, "DebugPathOut", strDebugPathOut); 3058 3061 break; 3059 3062 }
Note:
See TracChangeset
for help on using the changeset viewer.