Changeset 61157 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- May 24, 2016 11:47:09 AM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 107442
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
r61091 r61157 144 144 #ifdef DEBUG 145 145 static uint64_t s_cSamplesMixedTotal = 0; 146 static inline void audioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf); 147 #endif 148 149 /* Can return VINF_TRY_AGAIN for getting next pointer at beginning (circular) */ 146 #endif 147 150 148 151 149 /** … … 155 153 ** @todo Protect the buffer's data? 156 154 * 157 * @return IPRT status code. 155 * @return IPRT status code. VINF_TRY_AGAIN for getting next pointer at beginning (circular). 158 156 * @param pMixBuf Mixing buffer to acquire audio samples from. 159 157 * @param cSamplesToRead Number of audio samples to read. … … 203 201 204 202 /** 205 * Returns available number of samples for reading.203 * Returns available number of samples for processing. 206 204 * 207 205 * @return uint32_t Number of samples available for reading. … … 428 426 \ 429 427 AUDMIXBUF_MACRO_FN uint32_t audioMixBufConvFrom##_aName##Stereo(PPDMAUDIOSAMPLE paDst, const void *pvSrc, uint32_t cbSrc, \ 430 const P AUDMIXBUF_CONVOPTS pOpts) \428 const PPDMAUDMIXBUF_CONVOPTS pOpts) \ 431 429 { \ 432 430 _aType *pSrc = (_aType *)pvSrc; \ … … 447 445 \ 448 446 AUDMIXBUF_MACRO_FN uint32_t audioMixBufConvFrom##_aName##Mono(PPDMAUDIOSAMPLE paDst, const void *pvSrc, uint32_t cbSrc, \ 449 const P AUDMIXBUF_CONVOPTS pOpts) \447 const PPDMAUDMIXBUF_CONVOPTS pOpts) \ 450 448 { \ 451 449 _aType *pSrc = (_aType *)pvSrc; \ … … 466 464 \ 467 465 AUDMIXBUF_MACRO_FN void audioMixBufConvTo##_aName##Stereo(void *pvDst, const PPDMAUDIOSAMPLE paSrc, \ 468 const P AUDMIXBUF_CONVOPTS pOpts) \466 const PPDMAUDMIXBUF_CONVOPTS pOpts) \ 469 467 { \ 470 468 PPDMAUDIOSAMPLE pSrc = paSrc; \ … … 485 483 \ 486 484 AUDMIXBUF_MACRO_FN void audioMixBufConvTo##_aName##Mono(void *pvDst, const PPDMAUDIOSAMPLE paSrc, \ 487 const P AUDMIXBUF_CONVOPTS pOpts) \485 const PPDMAUDMIXBUF_CONVOPTS pOpts) \ 488 486 { \ 489 487 PPDMAUDIOSAMPLE pSrc = paSrc; \ … … 614 612 /** Dummy conversion used when the source is muted. */ 615 613 AUDMIXBUF_MACRO_FN uint32_t audioMixBufConvFromSilence(PPDMAUDIOSAMPLE paDst, const void *pvSrc, 616 uint32_t cbSrc, const P AUDMIXBUF_CONVOPTS pOpts)614 uint32_t cbSrc, const PPDMAUDMIXBUF_CONVOPTS pOpts) 617 615 { 618 616 /* Internally zero always corresponds to silence. */ … … 630 628 * @param enmFmt Audio format to lookup conversion macro for. 631 629 */ 632 static inline PAUDMIXBUF_FN_CONVFROM audioMixBufConvFromLookup(PDMAUDIOMIXBUFFMT enmFmt)630 static PPDMAUDMIXBUF_FN_CONVFROM audioMixBufConvFromLookup(PDMAUDIOMIXBUFFMT enmFmt) 633 631 { 634 632 if (AUDMIXBUF_FMT_SIGNED(enmFmt)) … … 691 689 * @param enmFmt Audio format to lookup conversion macro for. 692 690 */ 693 static inline PAUDMIXBUF_FN_CONVTO audioMixBufConvToLookup(PDMAUDIOMIXBUFFMT enmFmt)691 static PPDMAUDMIXBUF_FN_CONVTO audioMixBufConvToLookup(PDMAUDIOMIXBUFFMT enmFmt) 694 692 { 695 693 if (AUDMIXBUF_FMT_SIGNED(enmFmt)) … … 1150 1148 { 1151 1149 audioMixBufDbgPrintIndent(uIdtLvl, 1152 "[%s] %s (%RU32): offReadWrite=%RU32, cProcessed=%RU32, cMixed=%RU32 (BpS=%RU32)\n", 1153 fIsParent ? "PARENT" : "CHILD", 1154 pMixBuf->pszName, pMixBuf->cSamples, 1155 pMixBuf->offReadWrite, pMixBuf->cProcessed, pMixBuf->cMixed, 1156 AUDIOMIXBUF_S2B(pMixBuf, 1)); 1150 "[%s] %s: offReadWrite=%RU32, cProc=%RU32, cMixed=%RU32 / %RU32)\n", 1151 fIsParent ? "PARENT" : "CHILD", 1152 pMixBuf->pszName, pMixBuf->offReadWrite, pMixBuf->cProcessed, pMixBuf->cMixed, pMixBuf->cSamples); 1157 1153 } 1158 1154 … … 1172 1168 { 1173 1169 audioMixBufDbgPrintSingle(pIter, false /* ifIsParent */, uIdtLvl + 1); 1170 *pcChildren++; 1174 1171 audioMixBufDbgPrintChainHelper(pIter, uIdtLvl + 1, pcChildren); 1175 1172 } 1173 } 1174 1175 static void audioMixBufDbgPrintChainInternal(PPDMAUDIOMIXBUF pMixBuf) 1176 { 1177 PPDMAUDIOMIXBUF pParent = pMixBuf->pParent; 1178 while (pParent) 1179 { 1180 if (!pParent->pParent) 1181 break; 1182 1183 pParent = pParent->pParent; 1184 } 1185 1186 if (!pParent) 1187 pParent = pMixBuf; 1188 1189 AUDMIXBUF_LOG(("********************************************\n")); 1190 1191 audioMixBufDbgPrintSingle(pParent, true /* fIsParent */, 0 /* uIdtLvl */); 1192 1193 /* Recursively iterate children. */ 1194 size_t cChildren = 0; 1195 audioMixBufDbgPrintChainHelper(pParent, 0 /* uIdtLvl */, &cChildren); 1196 1197 AUDMIXBUF_LOG(("Children: %zu - Total samples mixed: %RU64\n", cChildren, s_cSamplesMixedTotal)); 1198 AUDMIXBUF_LOG(("********************************************\n")); 1176 1199 } 1177 1200 … … 1186 1209 void AudioMixBufDbgPrintChain(PPDMAUDIOMIXBUF pMixBuf) 1187 1210 { 1188 PPDMAUDIOMIXBUF pParent = pMixBuf->pParent; 1189 while (pParent) 1190 { 1191 if (!pParent->pParent) 1192 break; 1193 1194 pParent = pParent->pParent; 1195 } 1196 1197 if (!pParent) 1198 pParent = pMixBuf; 1199 1200 AUDMIXBUF_LOG(("********************************************\n")); 1201 1202 audioMixBufDbgPrintSingle(pParent, true /* fIsParent */, 0 /* uIdtLvl */); 1203 1204 /* Recursively iterate children. */ 1205 size_t cChildren = 0; 1206 audioMixBufDbgPrintChainHelper(pParent, 0 /* uIdtLvl */, &cChildren); 1207 1208 AUDMIXBUF_LOG(("Children: %zu - Total samples mixed: %RU64\n", cChildren, s_cSamplesMixedTotal)); 1209 AUDMIXBUF_LOG(("********************************************\n")); 1211 audioMixBufDbgPrintChainInternal(pMixBuf); 1210 1212 } 1211 1213 … … 1225 1227 AUDMIXBUF_LOG(("********************************************\n")); 1226 1228 1227 audioMixBufDbgPrintSingle(pMixBuf, true/* fIsParent */, 0 /* iIdtLevel */);1229 audioMixBufDbgPrintSingle(pMixBuf, pParent == pMixBuf /* fIsParent */, 0 /* iIdtLevel */); 1228 1230 1229 1231 PPDMAUDIOMIXBUF pIter; 1230 1232 RTListForEach(&pParent->lstBuffers, pIter, PDMAUDIOMIXBUF, Node) 1231 audioMixBufDbgPrintSingle(pMixBuf, false /* fIsParent */, 1 /* iIdtLevel */); 1233 { 1234 if (pIter == pMixBuf) 1235 continue; 1236 audioMixBufDbgPrintSingle(pIter, false /* fIsParent */, 1 /* iIdtLevel */); 1237 } 1238 1239 AUDMIXBUF_LOG(("********************************************\n")); 1232 1240 } 1233 1241 #endif … … 1301 1309 if (cToProcess) 1302 1310 { 1303 P AUDMIXBUF_FN_CONVTO pConv;1311 PPDMAUDMIXBUF_FN_CONVTO pConv; 1304 1312 if (pMixBuf->AudioFmt != enmFmt) 1305 1313 pConv = audioMixBufConvToLookup(enmFmt); … … 1309 1317 if (pConv) 1310 1318 { 1311 AUDMIXBUF_CONVOPTS convOpts = { cToProcess, pMixBuf->Volume };1319 PDMAUDMIXBUF_CONVOPTS convOpts = { cToProcess, pMixBuf->Volume }; 1312 1320 1313 1321 AssertPtr(pConv); … … 1388 1396 } 1389 1397 1390 P AUDMIXBUF_FN_CONVTO pConv = audioMixBufConvToLookup(enmFmt);1398 PPDMAUDMIXBUF_FN_CONVTO pConv = audioMixBufConvToLookup(enmFmt); 1391 1399 if (!pConv) /* Audio format not supported. */ 1392 1400 return VERR_NOT_SUPPORTED; … … 1418 1426 } 1419 1427 1420 AUDMIXBUF_CONVOPTS convOpts;1428 PDMAUDMIXBUF_CONVOPTS convOpts; 1421 1429 convOpts.Volume = pMixBuf->Volume; 1422 1430 … … 1637 1645 return VERR_BUFFER_OVERFLOW; 1638 1646 1639 P AUDMIXBUF_FN_CONVFROM pConv;1647 PPDMAUDMIXBUF_FN_CONVFROM pConv; 1640 1648 if (pMixBuf->AudioFmt != enmFmt) 1641 1649 pConv = audioMixBufConvFromLookup(enmFmt); … … 1665 1673 if (cToProcess) 1666 1674 { 1667 AUDMIXBUF_CONVOPTS convOpts = { cToProcess, pMixBuf->Volume };1675 PDMAUDMIXBUF_CONVOPTS convOpts = { cToProcess, pMixBuf->Volume }; 1668 1676 1669 1677 cWritten = pConv(pMixBuf->pSamples + offSamples, pvBuf, cbBuf, &convOpts); … … 1693 1701 * format of the mixing buffer. 1694 1702 * 1695 * @return IPRT status code. 1703 * @return IPRT status code, or VINF_BUFFER_OVERFLOW if samples which not have 1704 * been processed yet have been overwritten (due to cyclic buffer). 1696 1705 * @param pMixBuf Pointer to mixing buffer to write to. 1697 1706 * @param pvBuf Pointer to audio buffer to be written. … … 1709 1718 * Writes audio samples of a specific format. 1710 1719 * 1711 * @return IPRT status code. 1720 * @return IPRT status code, or VINF_BUFFER_OVERFLOW if samples which not have 1721 * been processed yet have been overwritten (due to cyclic buffer). 1712 1722 * @param pMixBuf Pointer to mixing buffer to write to. 1713 1723 * @param enmFmt Audio format supplied in the buffer. … … 1721 1731 { 1722 1732 AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER); 1723 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);1733 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 1724 1734 /* pcbWritten is optional. */ 1725 1735 … … 1731 1741 } 1732 1742 1733 PPDMAUDIOMIXBUF pParent = pMixBuf->pParent; 1734 1735 AUDMIXBUF_LOG(("%s: enmFmt=%ld, pBuf=%p, cbBuf=%zu, pParent=%p (%RU32)\n", 1736 pMixBuf->pszName, enmFmt, pvBuf, cbBuf, pParent, pParent ? pParent->cSamples : 0)); 1737 1738 if ( pParent 1739 && pParent->cSamples <= pMixBuf->cMixed) 1740 { 1741 if (pcWritten) 1742 *pcWritten = 0; 1743 1744 AUDMIXBUF_LOG(("%s: Parent buffer %s is full\n", 1745 pMixBuf->pszName, pMixBuf->pParent->pszName)); 1746 1747 return VINF_SUCCESS; 1748 } 1749 1750 PAUDMIXBUF_FN_CONVFROM pConv; 1743 AUDMIXBUF_LOG(("%s: enmFmt=%ld, pvBuf=%p, cbBuf=%RU32 (%RU32 samples)\n", 1744 pMixBuf->pszName, enmFmt, pvBuf, cbBuf, AUDIOMIXBUF_B2S(pMixBuf, cbBuf))); 1745 1746 PPDMAUDMIXBUF_FN_CONVFROM pCnvFrm; 1751 1747 if (pMixBuf->AudioFmt != enmFmt) 1752 pC onv= audioMixBufConvFromLookup(enmFmt);1748 pCnvFrm = audioMixBufConvFromLookup(enmFmt); 1753 1749 else 1754 1750 { 1755 pC onv= pMixBuf->Volume.fMuted1756 ? &audioMixBufConvFromSilence : pMixBuf->pConvFrom;1757 } 1758 1759 if (!pC onv)1751 pCnvFrm = pMixBuf->Volume.fMuted 1752 ? &audioMixBufConvFromSilence : pMixBuf->pConvFrom; 1753 } 1754 1755 if (!pCnvFrm) 1760 1756 return VERR_NOT_SUPPORTED; 1761 1757 … … 1771 1767 uint32_t cLenDst2 = 0; 1772 1768 1773 uint32_t offWrite = pMixBuf->offReadWrite + cToWrite;1769 uint32_t cOffWrite = pMixBuf->offReadWrite + cToWrite; 1774 1770 1775 1771 /* … … 1778 1774 * be the optional second part to do. 1779 1775 */ 1780 if ( offWrite >= pMixBuf->cSamples)1776 if (cOffWrite >= pMixBuf->cSamples) 1781 1777 { 1782 1778 Assert(pMixBuf->offReadWrite <= pMixBuf->cSamples); … … 1788 1784 1789 1785 /* Save new read offset. */ 1790 offWrite = cLenDst2; 1791 } 1792 1793 uint32_t cWrittenTotal = 0; 1794 1795 AUDMIXBUF_CONVOPTS convOpts; 1786 cOffWrite = cLenDst2; 1787 } 1788 1789 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1790 RTFILE fh; 1791 RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writecirc_ex-32bit-float.pcm", 1792 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 1793 #endif 1794 1795 uint32_t cWritten; 1796 1797 PDMAUDMIXBUF_CONVOPTS convOpts; 1796 1798 convOpts.Volume = pMixBuf->Volume; 1797 1799 … … 1800 1802 { 1801 1803 convOpts.cSamples = cLenDst1; 1802 cWrittenTotal = pConv(pSamplesDst1, pvBuf, cbBuf, &convOpts); 1804 cWritten = pCnvFrm(pSamplesDst1, pvBuf, cbBuf, &convOpts); 1805 Assert(cWritten == cLenDst1); 1806 1807 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1808 RTFileWrite(fh, pSamplesDst1, cWritten * sizeof(PDMAUDIOSAMPLE), NULL); 1809 #endif 1803 1810 } 1804 1811 … … 1810 1817 1811 1818 convOpts.cSamples = cLenDst2; 1812 cWritten Total += pConv(pSamplesDst2, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), cbBuf, &convOpts);1813 }1819 cWritten = pCnvFrm(pSamplesDst2, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), cbBuf, &convOpts); 1820 Assert(cWritten == cLenDst2); 1814 1821 1815 1822 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1816 RTFILE fh; 1817 RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writeex.pcm", 1818 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 1819 RTFileWrite(fh, pSamplesDst1, AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), NULL); 1820 RTFileClose(fh); 1821 #endif 1822 1823 AUDMIXBUF_LOG(("cLenDst1=%RU32, cLenDst2=%RU32, offWrite=%RU32\n", 1824 cLenDst1, cLenDst2, offWrite)); 1823 RTFileWrite(fh, pSamplesDst2, cWritten * sizeof(PDMAUDIOSAMPLE), NULL); 1824 #endif 1825 } 1826 1827 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1828 RTFileClose(fh); 1829 #endif 1825 1830 1826 1831 if (RT_SUCCESS(rc)) 1827 1832 { 1828 pMixBuf->offReadWrite = offWrite % pMixBuf->cSamples; 1829 pMixBuf->cProcessed = RT_MIN(pMixBuf->cProcessed + cLenDst1 + cLenDst2, 1830 pMixBuf->cSamples /* Max */); 1833 pMixBuf->offReadWrite = cOffWrite % pMixBuf->cSamples; 1834 1835 uint32_t cProcessedTotal = pMixBuf->cProcessed + cLenDst1 + cLenDst2; 1836 if (cProcessedTotal > pMixBuf->cSamples) 1837 { 1838 AUDMIXBUF_LOG(("Warning: %RU32 unprocessed samples overwritten\n", cProcessedTotal - pMixBuf->cSamples)); 1839 pMixBuf->cProcessed = pMixBuf->cSamples; 1840 1841 rc = VINF_BUFFER_OVERFLOW; 1842 } 1843 1831 1844 if (pcWritten) 1832 1845 *pcWritten = cLenDst1 + cLenDst2; … … 1837 1850 #endif 1838 1851 1839 AUDMIXBUF_LOG((" cWritten=%RU32 (%zu bytes), rc=%Rrc\n",1840 cLenDst1 + cLenDst2,1852 AUDMIXBUF_LOG(("offReadWrite=%RU32, cLenDst1=%RU32, cLenDst2=%RU32, cTotal=%RU32 (%zu bytes), rc=%Rrc\n", 1853 pMixBuf->offReadWrite, cLenDst1, cLenDst2, cLenDst1 + cLenDst2, 1841 1854 AUDIOMIXBUF_S2B(pMixBuf, cLenDst1 + cLenDst2), rc)); 1855 1842 1856 return rc; 1843 1857 } -
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r61079 r61157 49 49 #include <iprt/string.h> 50 50 51 static int audioMixerRemoveSinkInternal(PAUDIOMIXER pMixer, PAUDMIXSINK pSink); 52 51 53 static void audioMixerSinkDestroyInternal(PAUDMIXSINK pSink); 52 54 static int audioMixerSinkUpdateVolume(PAUDMIXSINK pSink, const PPDMAUDIOVOLUME pVolMaster); 53 static void audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream); 55 static void audioMixerSinkRemoveAllStreamsInternal(PAUDMIXSINK pSink); 56 static int audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream); 54 57 static int audioMixerSinkUpdateInternal(PAUDMIXSINK pSink); 55 58 56 59 static void audioMixerStreamDestroyInternal(PAUDMIXSTREAM pStream); 57 static void audioMixerStreamFree(PAUDMIXSTREAM pStream); 60 58 61 59 62 int AudioMixerCreateSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PAUDMIXSINK *ppSink) … … 125 128 pMixer->pszName, fFlags, pCfg->enmDir, DrvAudioAudFmtToStr(pCfg->enmFormat), pCfg->cChannels, pCfg->uHz)); 126 129 127 int rc; 128 if (pCfg->enmDir == PDMAUDIODIR_IN) 129 { 130 PPDMAUDIOGSTSTRMIN pGstStrm; 131 rc = pConn->pfnCreateIn(pConn, pCfg, &pGstStrm); 132 if (RT_SUCCESS(rc)) 133 { 134 pMixStream->InOut.pIn = pGstStrm; 135 136 /* Increase the stream's reference count to let others know 137 * we're reyling on it to be around now. */ 138 pConn->pfnAddRefIn(pConn, pGstStrm); 139 } 140 } 141 else if (pCfg->enmDir == PDMAUDIODIR_OUT) 142 { 143 PPDMAUDIOGSTSTRMOUT pGstStrm; 144 rc = pConn->pfnCreateOut(pConn, pCfg, &pGstStrm); 145 if (RT_SUCCESS(rc)) 146 { 147 pMixStream->InOut.pOut = pGstStrm; 148 149 /* Increase the stream's reference count to let others know 150 * we're reyling on it to be around now. */ 151 pConn->pfnAddRefOut(pConn, pGstStrm); 152 } 153 } 154 else 155 { 156 AssertMsgFailed(("Direction not implemented\n")); 157 rc = VERR_NOT_IMPLEMENTED; 158 } 159 130 PPDMAUDIOSTREAM pStream; 131 int rc = pConn->pfnStreamCreate(pConn, pCfg, &pStream); 160 132 if (RT_SUCCESS(rc)) 161 133 { 134 /* Save the audio stream pointer to this mixing stream. */ 135 pMixStream->pStream = pStream; 136 137 /* Increase the stream's reference count to let others know 138 * we're reyling on it to be around now. */ 139 pConn->pfnStreamAddRef(pConn, pStream); 140 } 141 142 if (RT_SUCCESS(rc)) 143 { 162 144 pMixStream->fFlags = fFlags; 163 pMixStream->enmDir = pCfg->enmDir;164 145 pMixStream->pConn = pConn; 165 146 … … 203 184 pMixer->VolMaster.uRight = UINT32_MAX; 204 185 205 LogFlowFunc(("Created %p ...\n", pMixer));186 LogFlowFunc(("Created mixer '%s'\n", pMixer->pszName)); 206 187 207 188 *ppMixer = pMixer; … … 242 223 PAUDMIXSINK pSink, pSinkNext; 243 224 RTListForEachSafe(&pMixer->lstSinks, pSink, pSinkNext, AUDMIXSINK, Node) 244 audioMixerSinkDestroyInternal(pSink); 225 { 226 /* Save a pointer to the sink to remove, as pSink 227 * will not be valid anymore after calling audioMixerRemoveSinkInternal(). */ 228 PAUDMIXSINK pSinkToRemove = pSink; 229 230 audioMixerRemoveSinkInternal(pMixer, pSinkToRemove); 231 audioMixerSinkDestroyInternal(pSinkToRemove); 232 } 233 234 pMixer->cSinks = 0; 245 235 246 236 if (pMixer->pszName) … … 280 270 } 281 271 282 void AudioMixerRemoveSink(PAUDIOMIXER pMixer, PAUDMIXSINK pSink)283 { 284 AssertPtrReturn Void(pMixer);272 static int audioMixerRemoveSinkInternal(PAUDIOMIXER pMixer, PAUDMIXSINK pSink) 273 { 274 AssertPtrReturn(pMixer, VERR_INVALID_PARAMETER); 285 275 if (!pSink) 286 return; 287 288 /** @todo Check if pSink is part of pMixer. */ 289 290 AudioMixerSinkRemoveAllStreams(pSink); 291 292 Assert(pSink->cStreams == 0); 293 276 return VERR_NOT_FOUND; 277 278 AssertMsgReturn(pSink->pParent == pMixer, ("Sink '%s' is not part of mixer '%s'\n", 279 pSink->pszName, pMixer->pszName), VERR_NOT_FOUND); 280 281 LogFlowFunc(("[%s]: pSink=%s, cSinks=%RU8\n", 282 pMixer->pszName, pSink->pszName, pMixer->cSinks)); 283 284 /* Remove sink from mixer. */ 294 285 RTListNodeRemove(&pSink->Node); 295 296 286 Assert(pMixer->cSinks); 297 287 pMixer->cSinks--; 298 288 299 LogFlowFunc(("[%s]: pSink=%s, cSinks=%RU8\n", 300 pMixer->pszName, pSink->pszName, pMixer->cSinks)); 289 /* Set mixer to NULL so that we know we're not part of any mixer anymore. */ 290 pSink->pParent = NULL; 291 292 return VINF_SUCCESS; 293 } 294 295 void AudioMixerRemoveSink(PAUDIOMIXER pMixer, PAUDMIXSINK pSink) 296 { 297 audioMixerSinkRemoveAllStreamsInternal(pSink); 298 audioMixerRemoveSinkInternal(pMixer, pSink); 301 299 } 302 300 … … 346 344 return VERR_NO_MORE_HANDLES; 347 345 348 /** @todo Check if stream already is assigned to (another) sink. */ 349 350 RTListAppend(&pSink->lstStreams, &pStream->Node); 351 pSink->cStreams++; 352 353 LogFlowFunc(("[%s]: cStreams=%RU8\n", pSink->pszName, pSink->cStreams)); 354 355 return VINF_SUCCESS; 346 int rc; 347 348 LogFlowFuncEnter(); 349 350 #ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF 351 /* Make sure only compatible streams are added. */ 352 if (pStream->enmDir == PDMAUDIODIR_IN) 353 { 354 if (DrvAudioPCMPropsAreEqual(&pSink->PCMProps, &pStream->InOut.pIn->Props)) 355 { 356 #ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF 357 /* Chain: Stream (Child) -> Sink (Child) -> Guest (Parent). */ 358 PPDMAUDIOMIXBUF pHstIn = &pStream->InOut.pIn->pHstStrmIn->MixBuf; 359 PPDMAUDIOMIXBUF pGstIn = &pStream->InOut.pIn->MixBuf; 360 361 /* Unlink any former parent from host input. */ 362 AudioMixBufUnlink(pHstIn); 363 364 /* Link host input to this sink as a parent. */ 365 rc = AudioMixBufLinkTo(pHstIn, &pSink->MixBuf); 366 AssertRC(rc); 367 368 /* Unlink any former parent from this sink. */ 369 AudioMixBufUnlink(&pSink->MixBuf); 370 371 /* Link guest input to this sink as a parent. */ 372 rc = AudioMixBufLinkTo(&pSink->MixBuf, pGstIn); 373 AssertRC(rc); 374 # ifdef DEBUG 375 AudioMixBufDbgPrintChain(&pStream->InOut.pIn->MixBuf); 376 # endif 377 #endif /* VBOX_AUDIO_MIXER_WITH_MIXBUF */ 378 } 379 else 380 rc = VERR_WRONG_TYPE; 381 } 382 else if (pStream->enmDir == PDMAUDIODIR_OUT) 383 { 384 if (DrvAudioPCMPropsAreEqual(&pSink->PCMProps, &pStream->InOut.pOut->Props)) 385 { 386 #ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF 387 /* Chain: Guest (Child) -> Sink (Child) -> Stream (Parent). */ 388 rc = AudioMixBufLinkTo(&pStream->InOut.pOut->pHstStrmOut->MixBuf, &pSink->MixBuf); 389 # ifdef DEBUG 390 AudioMixBufDbgPrintChain(&pSink->MixBuf); 391 # endif 392 #endif /* VBOX_AUDIO_MIXER_WITH_MIXBUF */ 393 } 394 else 395 rc = VERR_WRONG_TYPE; 396 } 397 else 398 { 399 AssertMsgFailed(("Direction not implemented\n")); 400 rc = VERR_NOT_IMPLEMENTED; 401 } 402 #else 403 rc = VINF_SUCCESS; 404 #endif 405 406 if (RT_SUCCESS(rc)) 407 { 408 /** @todo Check if stream already is assigned to (another) sink. */ 409 410 /* Save pointer to sink the stream is attached to. */ 411 pStream->pSink = pSink; 412 413 /* Append stream to sink's list. */ 414 RTListAppend(&pSink->lstStreams, &pStream->Node); 415 pSink->cStreams++; 416 } 417 418 LogFlowFunc(("[%s]: cStreams=%RU8, rc=%Rrc\n", pSink->pszName, pSink->cStreams, rc)); 419 return rc; 356 420 } 357 421 … … 396 460 void AudioMixerSinkDestroy(PAUDMIXSINK pSink) 397 461 { 398 audioMixerSinkDestroyInternal(pSink);399 }400 401 static void audioMixerSinkDestroyInternal(PAUDMIXSINK pSink)402 {403 AssertPtrReturnVoid(pSink);404 462 if (!pSink) 405 463 return; 406 464 465 if (pSink->pParent) 466 { 467 /* Save sink pointer, as after audioMixerRemoveSinkInternal() the 468 * pointer will be gone from the stream. */ 469 PAUDIOMIXER pMixer = pSink->pParent; 470 471 audioMixerRemoveSinkInternal(pMixer, pSink); 472 473 Assert(pMixer->cSinks); 474 pMixer->cSinks--; 475 } 476 477 audioMixerSinkDestroyInternal(pSink); 478 } 479 480 static void audioMixerSinkDestroyInternal(PAUDMIXSINK pSink) 481 { 482 AssertPtrReturnVoid(pSink); 483 407 484 LogFunc(("%s\n", pSink->pszName)); 408 485 … … 410 487 RTListForEachSafe(&pSink->lstStreams, pStream, pStreamNext, AUDMIXSTREAM, Node) 411 488 { 412 audioMixerSinkRemoveStreamInternal(pSink, pStream); 413 audioMixerStreamDestroyInternal(pStream); 414 } 415 416 Assert(pSink->cStreams == 0); 489 /* Save a pointer to the stream to remove, as pStream 490 * will not be valid anymore after calling audioMixerSinkRemoveStreamInternal(). */ 491 PAUDMIXSTREAM pStreamToRemove = pStream; 492 493 audioMixerSinkRemoveStreamInternal(pSink, pStreamToRemove); 494 audioMixerStreamDestroyInternal(pStreamToRemove); 495 } 417 496 418 497 if (pSink->pszName) 498 { 419 499 RTStrFree(pSink->pszName); 500 pSink->pszName = NULL; 501 } 420 502 421 503 RTMemFree(pSink); 504 pSink = NULL; 422 505 } 423 506 … … 466 549 if (!pSink) 467 550 return false; 551 552 LogFlowFunc(("[%s]: %RTbool\n", pSink->pszName, (pSink->fFlags & AUDMIXSINK_FLAG_DIRTY))); 468 553 469 554 /* If the dirty flag is set, there is unprocessed data in the sink. */ … … 487 572 uint32_t cbRead = 0; 488 573 489 PAUDMIXSTREAM p Stream;490 RTListForEach(&pSink->lstStreams, p Stream, AUDMIXSTREAM, Node)491 { 492 if (! pStream->pConn->pfnIsActiveIn(pStream->pConn, pStream->InOut.pIn))574 PAUDMIXSTREAM pMixStream; 575 RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node) 576 { 577 if (!(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 493 578 continue; 494 579 … … 499 584 { 500 585 uint32_t cbReadStrm; 501 AssertPtr(p Stream->pConn);502 rc = p Stream->pConn->pfnRead(pStream->pConn, pStream->InOut.pIn,503 (uint8_t *)pvMixBuf + cbTotalRead, cbToRead, &cbReadStrm);586 AssertPtr(pMixStream->pConn); 587 rc = pMixStream->pConn->pfnStreamRead(pMixStream->pConn, pMixStream->pStream, 588 (uint8_t *)pvMixBuf + cbTotalRead, cbToRead, &cbReadStrm); 504 589 if ( RT_FAILURE(rc) 505 590 || !cbReadStrm) … … 533 618 } 534 619 535 static voidaudioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream)536 { 537 AssertPtrReturn Void(pSink);620 static int audioMixerSinkRemoveStreamInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream) 621 { 622 AssertPtrReturn(pSink, VERR_INVALID_PARAMETER); 538 623 if (!pStream) 539 return; 540 541 /** @todo Check if pStream is part of pSink. */ 542 543 Assert(pSink->cStreams); 544 545 #ifdef DEBUG 546 const char *pszStream = pSink->enmDir == AUDMIXSINKDIR_INPUT 547 ? pStream->InOut.pIn->MixBuf.pszName : pStream->InOut.pOut->MixBuf.pszName; 624 return VERR_NOT_FOUND; 625 626 AssertMsgReturn(pStream->pSink == pSink, ("Stream '%s' is not part of sink '%s'\n", 627 pStream->pszName, pSink->pszName), VERR_NOT_FOUND); 548 628 549 629 LogFlowFunc(("[%s]: (Stream = %s), cStreams=%RU8\n", 550 pSink->pszName, pszStream ? pszStream : "<Unnamed>", pSink->cStreams)); 630 pSink->pszName, pStream->pStream->szName, pSink->cStreams)); 631 632 #ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF 633 /* Unlink mixing buffer. */ 634 AudioMixBufUnlink(&pStream->pStream->MixBuf); 551 635 #endif 552 636 553 637 /* Remove stream from sink. */ 554 638 RTListNodeRemove(&pStream->Node); 555 556 639 Assert(pSink->cStreams); 557 640 pSink->cStreams--; 641 642 /* Set sink to NULL so that we know we're not part of any sink anymore. */ 643 pStream->pSink = NULL; 644 645 return VINF_SUCCESS; 558 646 } 559 647 … … 561 649 { 562 650 audioMixerSinkRemoveStreamInternal(pSink, pStream); 651 } 652 653 /** 654 * Removes all attached streams from a given sink. 655 * 656 * @param pSink Sink to remove attached streams from. 657 */ 658 static void audioMixerSinkRemoveAllStreamsInternal(PAUDMIXSINK pSink) 659 { 660 if (!pSink) 661 return; 662 663 LogFunc(("%s\n", pSink->pszName)); 664 665 PAUDMIXSTREAM pStream, pStreamNext; 666 RTListForEachSafe(&pSink->lstStreams, pStream, pStreamNext, AUDMIXSTREAM, Node) 667 audioMixerSinkRemoveStreamInternal(pSink, pStream); 563 668 } 564 669 … … 573 678 return; 574 679 575 LogFunc(("%s\n", pSink->pszName)); 576 577 PAUDMIXSTREAM pStream, pStreamNext; 578 RTListForEachSafe(&pSink->lstStreams, pStream, pStreamNext, AUDMIXSTREAM, Node) 579 audioMixerSinkRemoveStreamInternal(pSink, pStream); 580 581 Assert(pSink->cStreams == 0); 680 audioMixerSinkRemoveAllStreamsInternal(pSink); 681 682 pSink->cStreams = 0; 582 683 } 583 684 … … 599 700 pSink->pszName, pSink->PCMProps.cBits, pSink->PCMProps.cChannels, pSink->PCMProps.uHz)); 600 701 601 #if 0 602 PAUDMIXSTREAM pStream; 603 RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node) 604 { 605 /** @todo Invalidate mix buffers! */ 606 } 607 #endif 608 609 return VINF_SUCCESS; 702 int rc = VINF_SUCCESS; 703 704 #ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF 705 /* Also update the sink's mixing buffer format. */ 706 AudioMixBufDestroy(&pSink->MixBuf); 707 rc = AudioMixBufInit(&pSink->MixBuf, pSink->pszName, pPCMProps, _4K /** @todo Make configurable? */); 708 if (RT_SUCCESS(rc)) 709 { 710 PAUDMIXSTREAM pStream; 711 RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node) 712 { 713 /** @todo Invalidate mix buffers! */ 714 } 715 } 716 #endif /* VBOX_AUDIO_MIXER_WITH_MIXBUF */ 717 718 LogFlowFuncLeaveRC(rc); 719 return rc; 610 720 } 611 721 … … 639 749 LogFlowFunc(("[%s]: cTimerTicks=%RU64, cTicksElapsed=%RU64\n", pSink->pszName, cTimerTicks, cTicksElapsed)); 640 750 641 //uint32_t cSamplesMin = (uint32_t)((2 * cTicksElapsed * pSink->PCMProps.uHz + cTimerTicks) / cTimerTicks / 2); 642 uint32_t cSamplesMin = (cTicksElapsed / pSink->PCMProps.uHz) * pSink->PCMProps.cChannels; 643 uint32_t cbSamplesMin = cSamplesMin << pSink->PCMProps.cShift; 644 645 Assert((cbSamplesMin % 2 == 0)); 646 647 LogFlowFunc(("[%s]: cSamplesMin=%RU32 (%RU32 bytes, %RU32Hz)\n", pSink->pszName, cSamplesMin, cbSamplesMin, pSink->PCMProps.uHz)); 751 // uint32_t cSamplesMin = (uint32_t)((2 * cTicksElapsed * pSink->PCMProps.uHz + cTimerTicks) / cTimerTicks / 2); 752 uint32_t cSamplesMin = (cTicksElapsed / pSink->PCMProps.uHz) * pSink->PCMProps.cChannels; 753 // cSamplesMin = (uint32_t)((2 * cTicksElapsed * 44100 + cTimerTicks) / cTimerTicks / 2); 754 uint32_t cbSamplesMin = _4K; //cSamplesMin << pSink->PCMProps.cShift; 755 756 //Assert((cbSamplesMin % 2 == 0)); 757 758 //LogFlowFunc(("[%s]: cSamplesMin=%RU32 (%RU32 bytes, %RU32Hz)\n", pSink->pszName, cSamplesMin, cbSamplesMin, pSink->PCMProps.uHz)); 759 760 uint32_t cbData = cbSamplesMin; 761 762 if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT) 763 { 764 // uint32_t cSinkSamplesLive = AudioMixBufAvail(&pSink->MixBuf); 765 // if (!cSinkSamplesLive) 766 // cbData = AUDIOMIXBUF_S2B_RATIO(&pSink->MixBuf, AudioMixBufFree(&pSink->MixBufGuest)); 767 } 648 768 649 769 audioMixerSinkUpdateInternal(pSink); 650 770 651 771 if (pcbData) 652 *pcbData = cb SamplesMin;772 *pcbData = cbData; 653 773 } 654 774 … … 659 779 int rc = VINF_SUCCESS; 660 780 661 PAUDMIXSTREAM pStream; 662 RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node) 663 { 664 if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT) 781 PAUDMIXSTREAM pMixStream; 782 RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node) 783 { 784 PPDMAUDIOSTREAM pStream = pMixStream->pStream; 785 AssertPtr(pStream); 786 787 uint32_t cSamplesAvail; 788 uint32_t cSamplesProcessed = 0; 789 790 rc = pMixStream->pConn->pfnStreamGetData(pMixStream->pConn, pStream, &cSamplesAvail); 791 if ( RT_SUCCESS(rc) 792 && cSamplesAvail) 665 793 { 666 uint32_t cSamplesLive; 667 uint32_t cSamplesPlayed = 0; 668 rc = pStream->pConn->pfnGetDataOut(pStream->pConn, NULL /* cbOut */, &cSamplesLive); 669 if ( RT_SUCCESS(rc) 670 && cSamplesLive) 671 { 672 rc = pStream->pConn->pfnPlayOut(pStream->pConn, &cSamplesPlayed); 673 } 674 675 if (RT_SUCCESS(rc)) 676 { 677 Assert(cSamplesLive >= cSamplesPlayed); 678 if (cSamplesLive - cSamplesPlayed) /* Some live samples left? */ 679 pSink->fFlags |= AUDMIXSINK_FLAG_DIRTY; 680 else 681 pSink->fFlags &= ~AUDMIXSINK_FLAG_DIRTY; 682 } 683 684 Log3Func(("[%s]: fFlags=0x%x, cSamplesLive=%RU32, rc=%Rrc\n", pSink->pszName, pSink->fFlags, cSamplesLive, rc)); 685 } 686 else if (pSink->enmDir == AUDMIXSINKDIR_INPUT) 687 { 688 uint32_t cbIn; 689 rc = pStream->pConn->pfnGetDataIn(pStream->pConn, &cbIn); 690 if ( RT_SUCCESS(rc) 691 && cbIn) 794 if (pStream->enmDir == PDMAUDIODIR_IN) 692 795 { 693 796 /** @todo Implement this! */ 694 // int rc2 = pStream->pConn->pfnCaptureIn(pStream->pConn, NULL /* pcSamplesCaptured */); 695 // Log3Func(("rc2=%Rrc\n", rc2)); 797 // rc = pStream->pConn->pfnCapture(pStream->pConn, NULL /* pcSamplesCaptured */); 696 798 } 697 698 if (RT_SUCCESS(rc)) 799 else 699 800 { 700 if (cbIn) /* Some inpput data available? */ 701 pSink->fFlags |= AUDMIXSINK_FLAG_DIRTY; 702 else 703 pSink->fFlags &= ~AUDMIXSINK_FLAG_DIRTY; 801 rc = pMixStream->pConn->pfnStreamPlay(pMixStream->pConn, pStream, &cSamplesProcessed); 704 802 } 705 803 706 Log3Func(("[%s]: fFlags=0x%x, cbIn=%RU32, rc=%Rrc\n", pSink->pszName, pSink->fFlags, cbIn, rc));804 pSink->fFlags |= AUDMIXSINK_FLAG_DIRTY; 707 805 } 708 else 709 {710 rc = VERR_NOT_IMPLEMENTED; 711 AssertMsgFailed(("Direction not implemented\n"));712 }806 else if (!cSamplesAvail) 807 pSink->fFlags &= ~AUDMIXSINK_FLAG_DIRTY; 808 809 Log3Func(("[%s]: fFlags=0x%x, %RU32/%RU32 samples, rc=%Rrc\n", 810 pSink->pszName, pSink->fFlags, cSamplesProcessed, cSamplesAvail, rc)); 713 811 } 714 812 … … 744 842 745 843 /* Propagate new sink volume to all streams in the sink. */ 746 PAUDMIXSTREAM p Stream;747 RTListForEach(&pSink->lstStreams, p Stream, AUDMIXSTREAM, Node)844 PAUDMIXSTREAM pMixStream; 845 RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node) 748 846 { 749 847 if (fOut) 750 AudioMixBufSetVolume(&p Stream->InOut.pOut->MixBuf, &volSink);848 AudioMixBufSetVolume(&pMixStream->pStream->MixBuf, &volSink); 751 849 else 752 AudioMixBufSetVolume(&p Stream->InOut.pIn->MixBuf,&volSink);850 AudioMixBufSetVolume(&pMixStream->pStream->MixBuf, &volSink); 753 851 } 754 852 … … 770 868 uint32_t cbProcessed = 0; 771 869 772 PAUDMIXSTREAM pStream; 773 RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node) 774 { 775 int rc2 = pStream->pConn->pfnWrite(pStream->pConn, pStream->InOut.pOut, pvBuf, cbBuf, &cbProcessed); 870 PAUDMIXSTREAM pMixStream; 871 RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node) 872 { 873 if (!(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 874 continue; 875 876 int rc2 = pMixStream->pConn->pfnStreamWrite(pMixStream->pConn, pMixStream->pStream, pvBuf, cbBuf, &cbProcessed); 776 877 if ( RT_FAILURE(rc2) 777 878 || cbProcessed < cbBuf) … … 791 892 ********************************************************************************************************************************/ 792 893 793 int AudioMixerStreamCtl(PAUDMIXSTREAM p Stream, PDMAUDIOSTREAMCMD enmCmd, uint32_t fCtl)794 { 795 AssertPtrReturn(p Stream, VERR_INVALID_POINTER);894 int AudioMixerStreamCtl(PAUDMIXSTREAM pMixStream, PDMAUDIOSTREAMCMD enmCmd, uint32_t fCtl) 895 { 896 AssertPtrReturn(pMixStream, VERR_INVALID_POINTER); 796 897 /** @todo Validate fCtl. */ 797 898 899 int rc = pMixStream->pConn->pfnStreamControl(pMixStream->pConn, pMixStream->pStream, enmCmd); 900 901 return rc; 902 } 903 904 static void audioMixerStreamDestroyInternal(PAUDMIXSTREAM pMixStream) 905 { 906 AssertPtrReturnVoid(pMixStream); 907 908 LogFunc(("%s\n", pMixStream->pszName)); 909 910 if (pMixStream->pConn) /* Stream has a connector interface present? */ 911 { 912 if (pMixStream->pStream) 913 { 914 pMixStream->pConn->pfnStreamRelease(pMixStream->pConn, pMixStream->pStream); 915 pMixStream->pConn->pfnStreamDestroy(pMixStream->pConn, pMixStream->pStream); 916 917 pMixStream->pStream = NULL; 918 } 919 920 pMixStream->pConn = NULL; 921 } 922 923 if (pMixStream->pszName) 924 { 925 RTStrFree(pMixStream->pszName); 926 pMixStream->pszName = NULL; 927 } 928 929 RTMemFree(pMixStream); 930 pMixStream = NULL; 931 } 932 933 void AudioMixerStreamDestroy(PAUDMIXSTREAM pMixStream) 934 { 935 if (!pMixStream) 936 return; 937 938 LogFunc(("%s\n", pMixStream->pszName)); 939 798 940 int rc; 799 switch (pStream->enmDir) 800 { 801 case PDMAUDIODIR_IN: 941 942 if (pMixStream->pSink) 943 { 944 /* Save sink pointer, as after audioMixerSinkRemoveStreamInternal() the 945 * pointer will be gone from the stream. */ 946 PAUDMIXSINK pSink = pMixStream->pSink; 947 948 rc = audioMixerSinkRemoveStreamInternal(pMixStream->pSink, pMixStream); 949 if (RT_SUCCESS(rc)) 802 950 { 803 if ( enmCmd == PDMAUDIOSTREAMCMD_ENABLE 804 || enmCmd == PDMAUDIOSTREAMCMD_DISABLE) 805 { 806 rc = pStream->pConn->pfnEnableIn(pStream->pConn, pStream->InOut.pIn, 807 enmCmd == PDMAUDIOSTREAMCMD_ENABLE); 808 } 809 else 810 { 811 AssertFailed(); 812 rc = VERR_INVALID_PARAMETER; 813 } 814 break; 951 AssertPtr(pSink); 952 Assert(pSink->cStreams); 953 pSink->cStreams--; 815 954 } 816 817 case PDMAUDIODIR_OUT: 818 { 819 if ( enmCmd == PDMAUDIOSTREAMCMD_ENABLE 820 || enmCmd == PDMAUDIOSTREAMCMD_DISABLE) 821 { 822 rc = pStream->pConn->pfnEnableOut(pStream->pConn, pStream->InOut.pOut, 823 enmCmd == PDMAUDIOSTREAMCMD_ENABLE); 824 } 825 else 826 { 827 AssertFailed(); 828 rc = VERR_INVALID_PARAMETER; 829 } 830 break; 831 } 832 833 default: 834 AssertMsgFailed(("Not implemented\n")); 835 rc = VERR_INVALID_PARAMETER; 836 break; 837 } 838 839 return rc; 840 } 841 842 static void audioMixerStreamDestroyInternal(PAUDMIXSTREAM pStream) 843 { 844 if (!pStream) 845 return; 846 847 LogFunc(("%s\n", pStream->pszName)); 848 849 if (pStream->pConn) /* Stream has a connector interface present? */ 850 { 851 if ( pStream->enmDir == PDMAUDIODIR_IN 852 && pStream->pConn->pfnDestroyIn) 853 { 854 if (pStream->InOut.pIn) 855 { 856 pStream->pConn->pfnReleaseIn(pStream->pConn, pStream->InOut.pIn); 857 pStream->pConn->pfnDestroyIn(pStream->pConn, pStream->InOut.pIn); 858 } 859 } 860 else if ( pStream->enmDir == PDMAUDIODIR_OUT 861 && pStream->pConn->pfnDestroyOut) 862 { 863 if (pStream->InOut.pOut) 864 { 865 pStream->pConn->pfnReleaseOut(pStream->pConn, pStream->InOut.pOut); 866 pStream->pConn->pfnDestroyOut(pStream->pConn, pStream->InOut.pOut); 867 } 868 } 869 else 870 AssertFailed(); 871 } 872 873 audioMixerStreamFree(pStream); 874 } 875 876 void AudioMixerStreamDestroy(PAUDMIXSTREAM pStream) 877 { 878 audioMixerStreamDestroyInternal(pStream); 879 } 880 881 static void audioMixerStreamFree(PAUDMIXSTREAM pStream) 882 { 883 if (pStream) 884 { 885 LogFunc(("%s\n", pStream->pszName)); 886 887 if (pStream->pszName) 888 { 889 RTStrFree(pStream->pszName); 890 pStream->pszName = NULL; 891 } 892 893 RTMemFree(pStream); 894 pStream = NULL; 895 } 896 } 897 898 bool AudioMixerStreamIsActive(PAUDMIXSTREAM pStream) 899 { 900 if (!pStream) 955 } 956 else 957 rc = VINF_SUCCESS; 958 959 if (RT_SUCCESS(rc)) 960 audioMixerStreamDestroyInternal(pMixStream); 961 } 962 963 bool AudioMixerStreamIsActive(PAUDMIXSTREAM pMixStream) 964 { 965 if (!pMixStream) 901 966 return false; 902 967 903 bool fIsActive; 904 switch (pStream->enmDir) 905 { 906 case PDMAUDIODIR_IN: 907 { 908 fIsActive = pStream->pConn->pfnIsActiveIn(pStream->pConn, pStream->InOut.pIn); 909 break; 910 } 911 912 case PDMAUDIODIR_OUT: 913 { 914 fIsActive = pStream->pConn->pfnIsActiveOut(pStream->pConn, pStream->InOut.pOut); 915 break; 916 } 917 918 default: 919 fIsActive = false; 920 AssertMsgFailed(("Not implemented\n")); 921 break; 922 } 923 924 return fIsActive; 925 } 926 927 bool AudioMixerStreamIsValid(PAUDMIXSTREAM pStream) 928 { 929 if (!pStream) 968 return (pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED); 969 } 970 971 bool AudioMixerStreamIsValid(PAUDMIXSTREAM pMixStream) 972 { 973 if (!pMixStream) 930 974 return false; 931 975 932 bool fIsValid; 933 switch (pStream->enmDir) 934 { 935 case PDMAUDIODIR_IN: 936 { 937 fIsValid = pStream->pConn->pfnIsValidIn(pStream->pConn, pStream->InOut.pIn); 938 break; 939 } 940 941 case PDMAUDIODIR_OUT: 942 { 943 fIsValid = pStream->pConn->pfnIsValidOut(pStream->pConn, pStream->InOut.pOut); 944 break; 945 } 946 947 default: 948 fIsValid = false; 949 AssertMsgFailed(("Not implemented\n")); 950 break; 951 } 952 953 return fIsValid; 954 } 955 976 uint32_t fStatus = pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream); 977 978 return (fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED); 979 } 980 -
trunk/src/VBox/Devices/Audio/AudioMixer.h
r61050 r61157 46 46 #define AUDMIXSTREAM_FLAG_NONE 0 47 47 48 /** Prototype needed for AUDMIXSTREAM struct definition. */ 49 typedef struct AUDMIXSINK *PAUDMIXSINK; 50 48 51 /** 49 52 * Structure for maintaining an audio mixer stream. … … 55 58 /** Name of this stream. */ 56 59 char *pszName; 60 /** Sink this stream is attached to. */ 61 PAUDMIXSINK pSink; 57 62 /** Stream flags of type AUDMIXSTREAM_FLAG_. */ 58 63 uint32_t fFlags; 59 64 /** Pointer to audio connector being used. */ 60 65 PPDMIAUDIOCONNECTOR pConn; 61 /** Audio direction of this stream. */ 62 PDMAUDIODIR enmDir; 63 /** Union of PDM input/output streams for this stream. */ 64 union 65 { 66 PPDMAUDIOGSTSTRMIN pIn; 67 PPDMAUDIOGSTSTRMOUT pOut; 68 } InOut; 66 /** Pointer to PDM audio stream this mixer stream handles. */ 67 PPDMAUDIOSTREAM pStream; 69 68 } AUDMIXSTREAM, *PAUDMIXSTREAM; 70 69 … … 124 123 /** Number of streams assigned. */ 125 124 uint8_t cStreams; 126 /** List of assigned streams. */ 125 /** List of assigned streams. 126 * Note: All streams have the same PCM properties, so the 127 * mixer does not do any conversion. */ 127 128 /** @todo Use something faster -- vector maybe? */ 128 129 RTLISTANCHOR lstStreams; 129 /** This sink's mixing buffer. */ 130 #ifdef VBOX_AUDIO_MIXER_WITH_MIXBUF 131 /** This sink's mixing buffer, acting as 132 * a parent buffer for all streams this sink owns. */ 130 133 PDMAUDIOMIXBUF MixBuf; 134 #endif 131 135 /** The volume of this sink. The volume always will 132 136 * be combined with the mixer's master volume. */ -
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r61050 r61157 303 303 { 304 304 /** PCM line input stream. */ 305 R3PTRTYPE(PPDMAUDIO GSTSTRMIN) pStrmIn;305 R3PTRTYPE(PPDMAUDIOSTREAM) pStream; 306 306 /** Mixer handle for line input stream. */ 307 307 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm; … … 311 311 { 312 312 /** PCM output stream. */ 313 R3PTRTYPE(PPDMAUDIO GSTSTRMOUT) pStrmOut;313 R3PTRTYPE(PPDMAUDIOSTREAM) pStream; 314 314 /** Mixer handle for output stream. */ 315 315 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm; … … 417 417 #ifndef VBOX_DEVICE_STRUCT_TESTCASE 418 418 419 static void ichac97 CloseIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource);420 static void ichac97 CloseOut(PAC97STATE pThis);419 static void ichac97DestroyIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource); 420 static void ichac97DestroyOut(PAC97STATE pThis); 421 421 DECLINLINE(PAC97STREAM) ichac97GetStreamFromID(PAC97STATE pThis, uint32_t uID); 422 422 static int ichac97StreamInit(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8Strm); … … 556 556 fActive ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE); 557 557 558 LogFlowFunc((" u8Strm=%RU8, fActive=%RTbool, cStreamsActive=%RU8, rc=%Rrc\n",558 LogFlowFunc(("SD=%RU8, fActive=%RTbool, cStreamsActive=%RU8, rc=%Rrc\n", 559 559 pStream->u8Strm, fActive, pThis->cStreamsActive, rc)); 560 if (rc == VERR_AUDIO_STREAM_PENDING_DISABLE)561 {562 LogFlowFunc(("On pending disable\n"));563 rc = VINF_SUCCESS;564 }565 560 566 561 return rc; … … 587 582 pRegs->bd_valid = 0; 588 583 589 int rc = ichac97StreamSetActive(pThis, pStream, false /* fActive */); 590 AssertRC(rc); 584 ichac97StreamSetActive(pThis, pStream, false /* fActive */); 591 585 592 586 RT_ZERO(pThis->silence); … … 595 589 static void ichac97StreamDestroy(PAC97STREAM pStream) 596 590 { 591 LogFlowFunc(("SD=%RU8\n", pStream->u8Strm)); 592 597 593 if (pStream->State.au8FIFOW) 598 594 { … … 610 606 LogFlowFuncEnter(); 611 607 612 ichac97 CloseIn(pThis, PDMAUDIORECSOURCE_LINE);613 ichac97 CloseIn(pThis, PDMAUDIORECSOURCE_MIC);614 ichac97 CloseOut(pThis);608 ichac97DestroyIn(pThis, PDMAUDIORECSOURCE_LINE); 609 ichac97DestroyIn(pThis, PDMAUDIORECSOURCE_MIC); 610 ichac97DestroyOut(pThis); 615 611 616 612 ichac97StreamDestroy(&pThis->StreamLineIn); … … 657 653 } 658 654 659 static void ichac97 CloseIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource)655 static void ichac97DestroyIn(PAC97STATE pThis, PDMAUDIORECSOURCE enmRecSource) 660 656 { 661 657 AssertPtrReturnVoid(pThis); … … 680 676 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 681 677 { 682 PAC97INPUTSTREAM pStr mIn;678 PAC97INPUTSTREAM pStream; 683 679 if (enmRecSource == PDMAUDIORECSOURCE_MIC) /** @todo Refine this once we have more streams. */ 684 pStr mIn= &pDrv->MicIn;680 pStream = &pDrv->MicIn; 685 681 else 686 pStrmIn = &pDrv->LineIn; 687 688 AudioMixerSinkRemoveStream(pSink, pStrmIn->pMixStrm); 689 AudioMixerStreamDestroy(pStrmIn->pMixStrm); 690 pStrmIn->pMixStrm = NULL; 691 } 692 } 693 694 static void ichac97CloseOut(PAC97STATE pThis) 682 pStream = &pDrv->LineIn; 683 684 if (pStream->pMixStrm) 685 { 686 AudioMixerSinkRemoveStream(pSink, pStream->pMixStrm); 687 AudioMixerStreamDestroy(pStream->pMixStrm); 688 } 689 pStream->pMixStrm = NULL; 690 } 691 } 692 693 static void ichac97DestroyOut(PAC97STATE pThis) 695 694 { 696 695 AssertPtrReturnVoid(pThis); … … 701 700 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 702 701 { 703 AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm); 704 AudioMixerStreamDestroy(pDrv->Out.pMixStrm); 705 pDrv->Out.pMixStrm = NULL; 706 } 707 } 708 709 static int ichac97OpenIn(PAC97STATE pThis, 710 const char *pszName, PDMAUDIORECSOURCE enmRecSource, PPDMAUDIOSTREAMCFG pCfg) 702 if (pDrv->Out.pMixStrm) 703 { 704 AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm); 705 AudioMixerStreamDestroy(pDrv->Out.pMixStrm); 706 707 pDrv->Out.pMixStrm = NULL; 708 } 709 } 710 } 711 712 static int ichac97CreateIn(PAC97STATE pThis, 713 const char *pszName, PDMAUDIORECSOURCE enmRecSource, PPDMAUDIOSTREAMCFG pCfg) 711 714 { 712 715 AssertPtrReturn(pThis, VERR_INVALID_POINTER); … … 746 749 } 747 750 748 PAC97INPUTSTREAM pStr mIn;751 PAC97INPUTSTREAM pStream; 749 752 if (enmRecSource == PDMAUDIORECSOURCE_MIC) /** @todo Refine this once we have more streams. */ 750 pStr mIn= &pDrv->MicIn;753 pStream = &pDrv->MicIn; 751 754 else 752 pStr mIn= &pDrv->LineIn;753 754 AudioMixerSinkRemoveStream(pSink, pStr mIn->pMixStrm);755 756 AudioMixerStreamDestroy(pStr mIn->pMixStrm);757 pStr mIn->pMixStrm = NULL;758 759 int rc2 = AudioMixerCreateStream(pThis->pMixer, pDrv->pConnector, pCfg, 0 /* fFlags */ , &pStr mIn->pMixStrm);755 pStream = &pDrv->LineIn; 756 757 AudioMixerSinkRemoveStream(pSink, pStream->pMixStrm); 758 759 AudioMixerStreamDestroy(pStream->pMixStrm); 760 pStream->pMixStrm = NULL; 761 762 int rc2 = AudioMixerCreateStream(pThis->pMixer, pDrv->pConnector, pCfg, 0 /* fFlags */ , &pStream->pMixStrm); 760 763 if (RT_SUCCESS(rc2)) 761 764 { 762 rc2 = AudioMixerSinkAddStream(pSink, pStr mIn->pMixStrm);765 rc2 = AudioMixerSinkAddStream(pSink, pStream->pMixStrm); 763 766 LogFlowFunc(("LUN#%RU8: Created input \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2)); 764 767 } … … 772 775 } 773 776 774 static int ichac97 OpenOut(PAC97STATE pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg)777 static int ichac97CreateOut(PAC97STATE pThis, const char *pszName, PPDMAUDIOSTREAMCFG pCfg) 775 778 { 776 779 AssertPtrReturn(pThis, VERR_INVALID_POINTER); … … 833 836 { 834 837 case PI_INDEX: 835 rc = ichac97 OpenIn(pThis, "ac97.pi", PDMAUDIORECSOURCE_LINE, pCfg);838 rc = ichac97CreateIn(pThis, "ac97.pi", PDMAUDIORECSOURCE_LINE, pCfg); 836 839 break; 837 840 838 841 case MC_INDEX: 839 rc = ichac97 OpenIn(pThis, "ac97.mc", PDMAUDIORECSOURCE_MIC, pCfg);842 rc = ichac97CreateIn(pThis, "ac97.mc", PDMAUDIORECSOURCE_MIC, pCfg); 840 843 break; 841 844 842 845 case PO_INDEX: 843 rc = ichac97 OpenOut(pThis, "ac97.po", pCfg);846 rc = ichac97CreateOut(pThis, "ac97.po", pCfg); 844 847 break; 845 848 … … 914 917 } 915 918 916 LogFlowFunc((" Index=%RU8, rc=%Rrc\n", u8Strm, rc));919 LogFlowFunc(("SD=%RU8, rc=%Rrc\n", u8Strm, rc)); 917 920 return rc; 918 921 } … … 928 931 AssertPtrReturnVoid(pStrm); 929 932 933 LogFlowFunc(("SD=%RU8\n", pStrm->u8Strm)); 934 930 935 if (pStrm->State.au8FIFOW) 931 936 { … … 935 940 936 941 pStrm->State.offFIFOW = 0; 937 938 LogFlowFunc(("uStrm=%RU8\n", pStrm->u8Strm));939 942 } 940 943 … … 1248 1251 RTListForEach(&pThis->lstDrv, pDrv, AC97DRIVER, Node) 1249 1252 { 1250 if (pDrv->pConnector->pfn IsActiveOut(pDrv->pConnector, pDrv->Out.pStrmOut))1253 if (pDrv->pConnector->pfnStreamGetStatus(pDrv->pConnector, pDrv->Out.pStream) == PDMAUDIOSTRMSTS_FLAG_ENABLED) 1251 1254 { 1252 rc2 = pDrv->pConnector->pfn Write(pDrv->pConnector, pDrv->Out.pStrmOut,1253 pThis->silence, cbToWrite, &cbWrittenToStream);1255 rc2 = pDrv->pConnector->pfnStreamWrite(pDrv->pConnector, pDrv->Out.pStream, 1256 pThis->silence, cbToWrite, &cbWrittenToStream); 1254 1257 if (RT_SUCCESS(rc2)) 1255 1258 { … … 1368 1371 uint64_t cTicksNow = TMTimerGet(pTimer); 1369 1372 uint64_t cTicksElapsed = cTicksNow - pThis->uTimerTS; 1373 uint64_t cTicksPerSec = TMTimerGetFreq(pTimer); 1370 1374 1371 1375 /* Update current time timestamp. */ … … 1373 1377 1374 1378 uint32_t cbLineIn; 1375 AudioMixerSinkTimerUpdate(pThis->pSinkLineIn, pThis->cTimerTicks, cTicks Elapsed, &cbLineIn);1379 AudioMixerSinkTimerUpdate(pThis->pSinkLineIn, pThis->cTimerTicks, cTicksPerSec, &cbLineIn); 1376 1380 if (cbLineIn) 1377 1381 ichac97TransferAudio(pThis, &pThis->StreamLineIn, cbLineIn); 1378 1382 1379 1383 uint32_t cbMicIn; 1380 AudioMixerSinkTimerUpdate(pThis->pSinkMicIn , pThis->cTimerTicks, cTicks Elapsed, &cbMicIn);1384 AudioMixerSinkTimerUpdate(pThis->pSinkMicIn , pThis->cTimerTicks, cTicksPerSec, &cbMicIn); 1381 1385 if (cbMicIn) 1382 1386 ichac97TransferAudio(pThis, &pThis->StreamMicIn, cbMicIn); 1383 1387 1384 1388 uint32_t cbOut; 1385 AudioMixerSinkTimerUpdate(pThis->pSinkOutput, pThis->cTimerTicks, cTicks Elapsed, &cbOut);1389 AudioMixerSinkTimerUpdate(pThis->pSinkOutput, pThis->cTimerTicks, cTicksPerSec, &cbOut); 1386 1390 if (cbOut) 1387 1391 ichac97TransferAudio(pThis, &pThis->StreamOut, cbOut); … … 2105 2109 PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector; 2106 2110 AssertPtr(pCon); 2107 active[PI_INDEX] = pCon->pfnIsActiveIn (pCon, pDrv->LineIn.pStrmIn) ? 1 : 0;2108 active[PO_INDEX] = pCon->pfnIsActiveOut(pCon, pDrv->Out.pStrmOut)? 1 : 0;2109 active[MC_INDEX] = pCon->pfnIsActiveIn (pCon, pDrv->MicIn.pStrmIn)? 1 : 0;2111 active[PI_INDEX] = (pCon->pfnStreamGetStatus(pCon, pDrv->LineIn.pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED) ? 1 : 0; 2112 active[PO_INDEX] = (pCon->pfnStreamGetStatus(pCon, pDrv->Out.pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED) ? 1 : 0; 2113 active[MC_INDEX] = (pCon->pfnStreamGetStatus(pCon, pDrv->MicIn.pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED) ? 1 : 0; 2110 2114 } 2111 2115 … … 2281 2285 LogFlowFuncEnter(); 2282 2286 2283 PAC97DRIVER pDrv; 2284 while (!RTListIsEmpty(&pThis->lstDrv)) 2285 { 2286 pDrv = RTListGetFirst(&pThis->lstDrv, AC97DRIVER, Node); 2287 2287 ichac97StreamDestroy(&pThis->StreamLineIn); 2288 ichac97StreamDestroy(&pThis->StreamMicIn); 2289 ichac97StreamDestroy(&pThis->StreamOut); 2290 2291 PAC97DRIVER pDrv, pDrvNext; 2292 RTListForEachSafe(&pThis->lstDrv, pDrv, pDrvNext, AC97DRIVER, Node) 2293 { 2288 2294 RTListNodeRemove(&pDrv->Node); 2289 2295 RTMemFree(pDrv); 2290 2296 } 2291 2297 2292 ichac97StreamsDestroy(pThis); 2298 /* Sanity. */ 2299 Assert(RTListIsEmpty(&pThis->lstDrv)); 2293 2300 2294 2301 LogFlowFuncLeave(); -
trunk/src/VBox/Devices/Audio/DevIchHda.cpp
r61126 r61157 4145 4145 { 4146 4146 uint32_t cSamplesPlayed; 4147 int rc2 = pDrv->pConnector->pfnPlay Out(pDrv->pConnector, &cSamplesPlayed);4147 int rc2 = pDrv->pConnector->pfnPlay(pDrv->pConnector, &cSamplesPlayed); 4148 4148 LogFlowFunc(("LUN#%RU8: cSamplesPlayed=%RU32, rc=%Rrc\n", pDrv->uLUN, cSamplesPlayed, rc2)); 4149 4149 } … … 5216 5216 { 5217 5217 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE); 5218 int iHdaStr mIndex = hdaDbgLookupStrmIdx(pThis, pszArgs);5219 if (iHdaStr mIndex != -1)5220 hdaDbgPrintStream(pThis, pHlp, iHdaStr mIndex);5218 int iHdaStreamdex = hdaDbgLookupStrmIdx(pThis, pszArgs); 5219 if (iHdaStreamdex != -1) 5220 hdaDbgPrintStream(pThis, pHlp, iHdaStreamdex); 5221 5221 else 5222 for(iHdaStr mIndex = 0; iHdaStrmIndex < HDA_MAX_STREAMS; ++iHdaStrmIndex)5223 hdaDbgPrintStream(pThis, pHlp, iHdaStr mIndex);5222 for(iHdaStreamdex = 0; iHdaStreamdex < HDA_MAX_STREAMS; ++iHdaStreamdex) 5223 hdaDbgPrintStream(pThis, pHlp, iHdaStreamdex); 5224 5224 } 5225 5225 … … 5230 5230 { 5231 5231 PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE); 5232 int iHdaStr mIndex = hdaDbgLookupStrmIdx(pThis, pszArgs);5233 if (iHdaStr mIndex != -1)5234 hdaDbgPrintBDLE(pThis, pHlp, iHdaStr mIndex);5232 int iHdaStreamdex = hdaDbgLookupStrmIdx(pThis, pszArgs); 5233 if (iHdaStreamdex != -1) 5234 hdaDbgPrintBDLE(pThis, pHlp, iHdaStreamdex); 5235 5235 else 5236 for(iHdaStr mIndex = 0; iHdaStrmIndex < HDA_MAX_STREAMS; ++iHdaStrmIndex)5237 hdaDbgPrintBDLE(pThis, pHlp, iHdaStr mIndex);5236 for(iHdaStreamdex = 0; iHdaStreamdex < HDA_MAX_STREAMS; ++iHdaStreamdex) 5237 hdaDbgPrintBDLE(pThis, pHlp, iHdaStreamdex); 5238 5238 } 5239 5239 … … 5650 5650 #ifndef VBOX_WITH_AUDIO_CALLBACKS 5651 5651 uint16_t uTimerHz; 5652 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 200 /* Hz */);5652 rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 100 /* Hz */); 5653 5653 if (RT_FAILURE(rc)) 5654 5654 return PDMDEV_SET_ERROR(pDevIns, rc, -
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r61050 r61157 77 77 { 78 78 /** PCM output stream. */ 79 R3PTRTYPE(PPDMAUDIO GSTSTRMOUT) pStrmOut;79 R3PTRTYPE(PPDMAUDIOSTREAM) pStream; 80 80 /** Mixer handle for output stream. */ 81 81 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm; … … 1685 1685 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1686 1686 { 1687 int rc2 = pDrv->pConnector->pfn GetDataOut(pDrv->pConnector, &cbOut, NULL /* pcSamplesLive */);1687 int rc2 = pDrv->pConnector->pfnStreamGetData(pDrv->pConnector, pDrv->Out.pStream, &cbOut); 1688 1688 if (RT_SUCCESS(rc2)) 1689 1689 cbOutMin = RT_MIN(cbOutMin, cbOut); … … 1920 1920 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1921 1921 { 1922 if (pDrv->Out.pStr mOut)1922 if (pDrv->Out.pStream) 1923 1923 { 1924 pDrv->pConnector->pfnCloseOut(pThis->pDrv, pDrv->Out.pStr mOut);1925 pDrv->Out.pStr mOut= NULL;1924 pDrv->pConnector->pfnCloseOut(pThis->pDrv, pDrv->Out.pStream); 1925 pDrv->Out.pStream = NULL; 1926 1926 } 1927 1927 } -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r61050 r61157 65 65 #include "AudioMixBuffer.h" 66 66 67 static int drvAudioAllocHstIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMIN *ppHstStrmIn); 68 static int drvAudioAllocHstOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut); 69 static int drvAudioCreateStreamPairIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn); 70 static int drvAudioDestroyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn); 71 static int drvAudioDestroyGstIn(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMIN pGstStrmIn); 72 static int drvAudioDestroyGstOut(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMOUT pGstStrmOut); 73 static PPDMAUDIOHSTSTRMIN drvAudioFindAnyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn); 74 static PPDMAUDIOHSTSTRMOUT drvAudioFindAnyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut); 75 static PPDMAUDIOHSTSTRMOUT drvAudioFindSpecificOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg); 76 77 static int drvAudioGstInInit(PPDMAUDIOGSTSTRMIN pGstStrmIn, PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg); 78 79 static void drvAudioHstInFreeRes(PPDMAUDIOHSTSTRMIN pHstStrmIn); 80 static void drvAudioHstOutFreeRes(PPDMAUDIOHSTSTRMOUT pHstStrmOut); 81 82 83 int drvAudioAddHstOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut) 84 { 85 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 86 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 87 88 int rc; 89 90 PPDMAUDIOHSTSTRMOUT pHstStrmOut = drvAudioFindSpecificOut(pThis, NULL, pCfg); 91 if (!pHstStrmOut) 92 { 93 rc = drvAudioAllocHstOut(pThis, pCfg, &pHstStrmOut); 94 if (RT_FAILURE(rc)) 95 pHstStrmOut = drvAudioFindAnyHstOut(pThis, NULL /* pHstStrmOut */); 96 } 97 98 rc = pHstStrmOut ? VINF_SUCCESS : rc; 99 100 if (RT_SUCCESS(rc)) 101 *ppHstStrmOut = pHstStrmOut; 102 103 return rc; 104 } 67 static DECLCALLBACK(int) drvAudioStreamDestroy(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream); 68 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd); 69 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream); 70 static int drvAudioStreamDestroyInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 105 71 106 72 #ifndef VBOX_AUDIO_TESTCASE … … 178 144 *pfDefault = false; 179 145 return pszValue; 146 } 147 148 inline PPDMAUDIOSTREAM drvAudioGetHostStream(PPDMAUDIOSTREAM pStream) 149 { 150 AssertPtrReturn(pStream, NULL); 151 152 PPDMAUDIOSTREAM pStreamHst = pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST 153 ? pStream 154 : pStream->pPair; 155 AssertPtr(pStreamHst); 156 return pStreamHst; 180 157 } 181 158 … … 273 250 #endif /* !VBOX_AUDIO_TESTCASE */ 274 251 275 static bool drvAudioStreamCfgIsValid(PPDMAUDIOSTREAMCFG pCfg) 276 { 277 bool fValid = ( pCfg->cChannels == 1 278 || pCfg->cChannels == 2); /* Either stereo (2) or mono (1), per stream. */ 279 280 fValid |= ( pCfg->enmEndianness == PDMAUDIOENDIANNESS_LITTLE 281 || pCfg->enmEndianness == PDMAUDIOENDIANNESS_BIG); 282 283 if (fValid) 284 { 285 switch (pCfg->enmFormat) 286 { 287 case PDMAUDIOFMT_S8: 288 case PDMAUDIOFMT_U8: 289 case PDMAUDIOFMT_S16: 290 case PDMAUDIOFMT_U16: 291 case PDMAUDIOFMT_S32: 292 case PDMAUDIOFMT_U32: 293 break; 294 default: 295 fValid = false; 296 break; 297 } 298 } 299 300 /** @todo Check for defined frequencies supported. */ 301 fValid |= pCfg->uHz > 0; 302 303 return fValid; 304 } 305 306 static int drvAudioControlHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn, PDMAUDIOSTREAMCMD enmStreamCmd) 307 { 308 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 309 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 310 311 int rc = RTCritSectEnter(&pHstStrmIn->CritSect); 252 static DECLCALLBACK(int) drvAudioStreamControl(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd) 253 { 254 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 255 256 return drvAudioStreamControlInternal(pThis, pStream, enmStreamCmd); 257 } 258 259 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd) 260 { 261 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 262 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 263 264 int rc = RTCritSectEnter(&pThis->CritSect); 312 265 if (RT_FAILURE(rc)) 313 266 return rc; 314 267 315 LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd)); 268 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 269 270 LogFlowFunc(("%s: enmStreamCmd=%ld\n", pHstStream->szName, enmStreamCmd)); 316 271 317 272 switch (enmStreamCmd) … … 319 274 case PDMAUDIOSTREAMCMD_ENABLE: 320 275 { 321 if (!(pHstStr mIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED))322 { 323 rc = pThis->pHostDrvAudio->pfn ControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_ENABLE);276 if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 277 { 278 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_ENABLE); 324 279 if (RT_SUCCESS(rc)) 325 pHstStrmIn->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED; 280 { 281 Assert(!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)); 282 pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED; 283 } 326 284 } 327 285 else … … 333 291 case PDMAUDIOSTREAMCMD_DISABLE: 334 292 { 335 if (pHstStr mIn->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)336 { 337 rc = pThis->pHostDrvAudio->pfn ControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_DISABLE);293 if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED) 294 { 295 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 338 296 if (RT_SUCCESS(rc)) 339 297 { 340 pHstStr mIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED;341 AudioMixBufClear(&pHstStr mIn->MixBuf);298 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED; 299 AudioMixBufClear(&pHstStream->MixBuf); 342 300 } 343 301 } … … 350 308 case PDMAUDIOSTREAMCMD_PAUSE: 351 309 { 352 if (!(pHstStr mIn->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED))353 { 354 rc = pThis->pHostDrvAudio->pfn ControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_PAUSE);310 if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)) 311 { 312 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_PAUSE); 355 313 if (RT_SUCCESS(rc)) 356 pHstStr mIn->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED;314 pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED; 357 315 } 358 316 else … … 364 322 case PDMAUDIOSTREAMCMD_RESUME: 365 323 { 366 if (pHstStr mIn->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)367 { 368 rc = pThis->pHostDrvAudio->pfn ControlIn(pThis->pHostDrvAudio, pHstStrmIn, PDMAUDIOSTREAMCMD_RESUME);324 if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED) 325 { 326 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_RESUME); 369 327 if (RT_SUCCESS(rc)) 370 pHstStr mIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED;328 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED; 371 329 } 372 330 else … … 382 340 } 383 341 384 LogFunc(("[%s] Returned %Rrc\n", pHstStrmIn->MixBuf.pszName, rc)); 385 386 int rc2 = RTCritSectLeave(&pHstStrmIn->CritSect); 342 if (RT_FAILURE(rc)) 343 LogFunc(("%s: Failed with %Rrc\n", pHstStream->szName, rc)); 344 345 int rc2 = RTCritSectLeave(&pThis->CritSect); 387 346 if (RT_SUCCESS(rc)) 388 347 rc = rc2; … … 391 350 } 392 351 393 static int drvAudioControlHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd) 394 { 395 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 396 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 397 398 int rc = RTCritSectEnter(&pHstStrmOut->CritSect); 399 if (RT_FAILURE(rc)) 400 return rc; 401 402 LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd)); 403 404 switch (enmStreamCmd) 405 { 406 case PDMAUDIOSTREAMCMD_ENABLE: 407 { 408 if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 409 { 410 rc = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_ENABLE); 411 if (RT_SUCCESS(rc)) 412 { 413 Assert(!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)); 414 pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED; 415 } 416 } 417 else 418 rc = VINF_SUCCESS; 419 420 break; 421 } 422 423 case PDMAUDIOSTREAMCMD_DISABLE: 424 { 425 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED) 426 { 427 rc = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_DISABLE); 428 if (RT_SUCCESS(rc)) 429 { 430 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED; 431 AudioMixBufClear(&pHstStrmOut->MixBuf); 432 } 433 } 434 else 435 rc = VINF_SUCCESS; 436 437 break; 438 } 439 440 case PDMAUDIOSTREAMCMD_PAUSE: 441 { 442 if (!(pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)) 443 { 444 rc = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_PAUSE); 445 if (RT_SUCCESS(rc)) 446 pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED; 447 } 448 else 449 rc = VINF_SUCCESS; 450 451 break; 452 } 453 454 case PDMAUDIOSTREAMCMD_RESUME: 455 { 456 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED) 457 { 458 rc = pThis->pHostDrvAudio->pfnControlOut(pThis->pHostDrvAudio, pHstStrmOut, PDMAUDIOSTREAMCMD_RESUME); 459 if (RT_SUCCESS(rc)) 460 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED; 461 } 462 else 463 rc = VINF_SUCCESS; 464 465 break; 466 } 467 468 default: 469 AssertMsgFailed(("Command %ld not implemented\n", enmStreamCmd)); 470 rc = VERR_NOT_IMPLEMENTED; 471 break; 472 } 473 474 LogFunc(("[%s] Returned %Rrc\n", pHstStrmOut->MixBuf.pszName, rc)); 475 476 int rc2 = RTCritSectLeave(&pHstStrmOut->CritSect); 477 if (RT_SUCCESS(rc)) 478 rc = rc2; 479 480 return rc; 481 } 482 483 static int drvAudioDestroyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut) 484 { 485 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 486 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 487 488 LogFlowFunc(("%s\n", pHstStrmOut->MixBuf.pszName)); 489 490 int rc = VINF_SUCCESS; 491 492 if (RTListIsEmpty(&pHstStrmOut->lstGstStrmOut)) 493 { 494 drvAudioHstOutFreeRes(pHstStrmOut); 495 496 /* Remove from driver instance list. */ 497 RTListNodeRemove(&pHstStrmOut->Node); 498 499 if (RTCritSectIsInitialized(&pHstStrmOut->CritSect)) 500 { 501 int rc2 = RTCritSectDelete(&pHstStrmOut->CritSect); 502 AssertRC(rc2); 503 } 504 505 RTMemFree(pHstStrmOut); 506 pHstStrmOut = NULL; 507 508 pThis->cStreamsFreeOut++; 509 } 510 else 511 { 512 rc = VERR_WRONG_ORDER; 513 LogFlowFunc(("[%s] Still is being used, skipping\n", pHstStrmOut->MixBuf.pszName)); 514 } 515 516 LogFlowFuncLeaveRC(rc); 517 return rc; 518 } 519 520 static int drvAudioDestroyGstOut(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMOUT pGstStrmOut) 521 { 522 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 523 524 if (!pGstStrmOut) 525 return VINF_SUCCESS; 526 527 LogFlowFunc(("%s\n", pGstStrmOut->MixBuf.pszName)); 528 529 if (pGstStrmOut->State.cRefs > 1) /* Do other objects still have a reference to it? Bail out. */ 530 return VERR_WRONG_ORDER; 531 532 AudioMixBufDestroy(&pGstStrmOut->MixBuf); 533 534 /* Is this guest stream associate to a host stream? */ 535 if (pGstStrmOut->pHstStrmOut) 536 { 537 /* Unregister from parent first. */ 538 RTListNodeRemove(&pGstStrmOut->Node); 539 } 540 541 RTMemFree(pGstStrmOut); 542 pGstStrmOut = NULL; 543 544 return VINF_SUCCESS; 545 } 546 547 static PPDMAUDIOHSTSTRMIN drvAudioFindAnyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn) 548 { 549 if (pHstStrmIn) 550 { 551 if (RTListNodeIsLast(&pThis->lstHstStrmIn, &pHstStrmIn->Node)) 552 return NULL; 553 554 return RTListNodeGetNext(&pHstStrmIn->Node, PDMAUDIOHSTSTRMIN, Node); 555 } 556 557 return RTListGetFirst(&pThis->lstHstStrmIn, PDMAUDIOHSTSTRMIN, Node); 558 } 559 560 static int drvAudioHstInAdd(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMIN *ppHstStrmIn) 561 { 562 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 563 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 564 AssertPtrReturn(ppHstStrmIn, VERR_INVALID_POINTER); 565 566 PPDMAUDIOHSTSTRMIN pHstStrmIn; 567 int rc = drvAudioAllocHstIn(pThis, pCfg, &pHstStrmIn); 568 if (RT_SUCCESS(rc)) 569 *ppHstStrmIn = pHstStrmIn; 570 571 LogFlowFuncLeaveRC(rc); 572 return rc; 573 } 574 575 static void drvAudioHstInFreeRes(PPDMAUDIOHSTSTRMIN pHstStrmIn) 576 { 577 if (!pHstStrmIn) 578 return; 579 580 AudioMixBufDestroy(&pHstStrmIn->MixBuf); 581 } 582 583 static int drvAudioGstOutInit(PPDMAUDIOGSTSTRMOUT pGstStrmOut, PPDMAUDIOHSTSTRMOUT pHostStrmOut, PPDMAUDIOSTREAMCFG pCfg) 584 { 585 AssertPtrReturn(pGstStrmOut, VERR_INVALID_POINTER); 586 AssertPtrReturn(pHostStrmOut, VERR_INVALID_POINTER); 587 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 588 589 int rc = DrvAudioStreamCfgToProps(pCfg, &pGstStrmOut->Props); 590 if (RT_SUCCESS(rc)) 591 { 592 char *pszName; 593 if (RTStrAPrintf(&pszName, "%s (Guest)", pCfg->szName) <= 0) 594 return VERR_NO_MEMORY; 595 596 rc = AudioMixBufInit(&pGstStrmOut->MixBuf, pszName, &pGstStrmOut->Props, AudioMixBufSize(&pHostStrmOut->MixBuf)); 597 if (RT_SUCCESS(rc)) 598 rc = AudioMixBufLinkTo(&pGstStrmOut->MixBuf, &pHostStrmOut->MixBuf); 599 600 if (RT_SUCCESS(rc)) 601 { 602 pGstStrmOut->State.cRefs = 1; 603 pGstStrmOut->State.fActive = false; 604 pGstStrmOut->State.fEmpty = true; 605 606 RTStrPrintf(pGstStrmOut->State.szName, RT_ELEMENTS(pGstStrmOut->State.szName), 607 "%s", pszName); 608 609 pGstStrmOut->pHstStrmOut = pHostStrmOut; 610 } 611 612 RTStrFree(pszName); 613 } 614 615 LogFlowFunc(("pszName=%s, rc=%Rrc\n", pCfg->szName, rc)); 616 return rc; 617 } 618 619 static int drvAudioAllocHstOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMOUT *ppHstStrmOut) 620 { 621 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 622 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 623 624 if (!pThis->cStreamsFreeOut) 625 { 626 LogFlowFunc(("Maximum number of host output streams reached\n")); 627 return VERR_NO_MORE_HANDLES; 628 } 629 630 /* Validate backend configuration. */ 631 if (!pThis->BackendCfg.cbStreamOut) 632 { 633 LogFlowFunc(("Backend output configuration not valid, bailing out\n")); 634 return VERR_INVALID_PARAMETER; 635 } 636 637 PPDMAUDIOHSTSTRMOUT pHstStrmOut = (PPDMAUDIOHSTSTRMOUT)RTMemAllocZ(pThis->BackendCfg.cbStreamOut); 638 if (!pHstStrmOut) 639 { 640 LogFlowFunc(("Error allocating host output stream with %zu bytes\n", 641 pThis->BackendCfg.cbStreamOut)); 642 return VERR_NO_MEMORY; 643 } 644 645 int rc; 646 647 do 648 { 649 RTListInit(&pHstStrmOut->lstGstStrmOut); 650 651 uint32_t cSamples = 0; 652 rc = pThis->pHostDrvAudio->pfnInitOut 653 ? pThis->pHostDrvAudio->pfnInitOut(pThis->pHostDrvAudio, pHstStrmOut, pCfg, &cSamples) : VINF_SUCCESS; 654 655 if (RT_FAILURE(rc)) 656 { 657 LogFlowFunc(("Initializing host backend failed with rc=%Rrc\n", rc)); 658 break; 659 } 660 661 pHstStrmOut->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 662 663 char *pszName; 664 if (RTStrAPrintf(&pszName, "%s (Host)", pCfg->szName) <= 0) 665 { 666 rc = VERR_NO_MEMORY; 667 break; 668 } 669 670 rc = AudioMixBufInit(&pHstStrmOut->MixBuf, pszName, &pHstStrmOut->Props, cSamples); 671 if (RT_SUCCESS(rc)) 672 rc = RTCritSectInit(&pHstStrmOut->CritSect); 673 674 if (RT_SUCCESS(rc)) 675 { 676 RTListPrepend(&pThis->lstHstStrmOut, &pHstStrmOut->Node); 677 pThis->cStreamsFreeOut--; 678 } 679 680 RTStrFree(pszName); 681 682 } while (0); 683 684 if (RT_FAILURE(rc)) 685 { 686 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 687 { 688 int rc2 = pThis->pHostDrvAudio->pfnFiniOut 689 ? pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut) : VINF_SUCCESS; 690 if (RT_SUCCESS(rc2)) 691 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 692 } 693 694 drvAudioHstOutFreeRes(pHstStrmOut); 695 RTMemFree(pHstStrmOut); 696 } 697 else 698 *ppHstStrmOut = pHstStrmOut; 699 700 LogFlowFuncLeaveRC(rc); 701 return rc; 702 } 703 704 static int drvAudioCreateStreamPairOut(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut) 705 { 706 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 707 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 708 709 PPDMAUDIOGSTSTRMOUT pGstStrmOut = 710 (PPDMAUDIOGSTSTRMOUT)RTMemAllocZ(sizeof(PDMAUDIOGSTSTRMOUT)); 711 if (!pGstStrmOut) 712 { 713 LogFlowFunc(("Failed to allocate memory for guest output stream \"%s\"\n", pCfg->szName)); 714 return VERR_NO_MEMORY; 715 } 716 717 /* 718 * The host stream always will get the backend audio stream configuration. 719 */ 720 PPDMAUDIOHSTSTRMOUT pHstStrmOut; 721 int rc = drvAudioAddHstOut(pThis, pCfg, &pHstStrmOut); 722 if (RT_FAILURE(rc)) 723 { 724 LogFlowFunc(("Error adding host output stream \"%s\", rc=%Rrc\n", pCfg->szName, rc)); 725 726 RTMemFree(pGstStrmOut); 727 return rc; 728 } 729 730 /* 731 * The guest stream always will get the audio stream configuration told 732 * by the device emulation (which in turn was/could be set by the guest OS). 733 */ 734 rc = drvAudioGstOutInit(pGstStrmOut, pHstStrmOut, pCfg); 735 if (RT_SUCCESS(rc)) 736 { 737 RTListPrepend(&pHstStrmOut->lstGstStrmOut, &pGstStrmOut->Node); 738 739 if (ppGstStrmOut) 740 *ppGstStrmOut = pGstStrmOut; 741 } 742 743 if (RT_FAILURE(rc)) 744 drvAudioDestroyGstOut(pThis, pGstStrmOut); 745 746 LogFlowFuncLeaveRC(rc); 747 return rc; 748 } 749 750 static int drvAudioCreateStreamPairIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMIN *ppGstStrmIn) 751 { 752 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 753 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 754 755 PPDMAUDIOGSTSTRMIN pGstStrmIn = (PPDMAUDIOGSTSTRMIN)RTMemAllocZ(sizeof(PDMAUDIOGSTSTRMIN)); 756 if (!pGstStrmIn) 757 return VERR_NO_MEMORY; 758 759 /* 760 * The host stream always will get the backend audio stream configuration. 761 */ 762 PPDMAUDIOHSTSTRMIN pHstStrmIn; 763 int rc = drvAudioHstInAdd(pThis, pCfg, &pHstStrmIn); 764 if (RT_FAILURE(rc)) 765 { 766 LogFunc(("Failed to add host audio input stream \"%s\", rc=%Rrc\n", pCfg->szName, rc)); 767 768 RTMemFree(pGstStrmIn); 769 return rc; 770 } 771 772 /* 773 * The guest stream always will get the audio stream configuration told 774 * by the device emulation (which in turn was/could be set by the guest OS). 775 */ 776 rc = drvAudioGstInInit(pGstStrmIn, pHstStrmIn, pCfg); 777 if (RT_SUCCESS(rc)) 778 { 779 pHstStrmIn->pGstStrmIn = pGstStrmIn; 780 781 if (ppGstStrmIn) 782 *ppGstStrmIn = pGstStrmIn; 783 } 784 else 785 drvAudioDestroyGstIn(pThis, pGstStrmIn); 786 787 LogFlowFuncLeaveRC(rc); 788 return rc; 789 } 790 791 /** 792 * Initializes a guest input stream. 793 * 794 * @return IPRT status code. 795 * @param pGstStrmIn Pointer to guest stream to initialize. 796 * @param pHstStrmIn Pointer to host input stream to associate this guest 797 * stream with. 798 * @param pCfg Pointer to stream configuration to use. 799 */ 800 static int drvAudioGstInInit(PPDMAUDIOGSTSTRMIN pGstStrmIn, PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg) 801 { 802 AssertPtrReturn(pGstStrmIn, VERR_INVALID_POINTER); 803 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 804 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 805 806 int rc = DrvAudioStreamCfgToProps(pCfg, &pGstStrmIn->Props); 807 if (RT_SUCCESS(rc)) 808 { 809 char *pszName; 810 if (RTStrAPrintf(&pszName, "%s (Guest)", 811 strlen(pCfg->szName) ? pCfg->szName : "<Untitled>") <= 0) 812 { 813 return VERR_NO_MEMORY; 814 } 815 816 rc = AudioMixBufInit(&pGstStrmIn->MixBuf, pszName, &pGstStrmIn->Props, AudioMixBufSize(&pHstStrmIn->MixBuf)); 817 if (RT_SUCCESS(rc)) 818 rc = AudioMixBufLinkTo(&pHstStrmIn->MixBuf, &pGstStrmIn->MixBuf); 819 820 if (RT_SUCCESS(rc)) 821 { 822 #ifdef DEBUG 823 DrvAudioStreamCfgPrint(pCfg); 824 #endif 825 pGstStrmIn->State.cRefs = 1; 826 pGstStrmIn->State.fActive = false; 827 pGstStrmIn->State.fEmpty = true; 828 829 RTStrPrintf(pGstStrmIn->State.szName, RT_ELEMENTS(pGstStrmIn->State.szName), 830 "%s", pszName); 831 832 pGstStrmIn->pHstStrmIn = pHstStrmIn; 833 } 834 835 RTStrFree(pszName); 836 } 837 838 LogFlowFunc(("pszName=%s, rc=%Rrc\n", pCfg->szName, rc)); 839 return rc; 840 } 841 842 static int drvAudioAllocHstIn(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOHSTSTRMIN *ppHstStrmIn) 843 { 844 if (!pThis->cStreamsFreeIn) 845 { 846 LogFlowFunc(("No more input streams free to use, bailing out\n")); 847 return VERR_AUDIO_NO_FREE_INPUT_STREAMS; 848 } 849 850 /* Validate backend configuration. */ 851 if (!pThis->BackendCfg.cbStreamIn) 852 { 853 LogFlowFunc(("Backend input configuration not valid, bailing out\n")); 854 return VERR_INVALID_PARAMETER; 855 } 856 857 PPDMAUDIOHSTSTRMIN pHstStrmIn = 858 (PPDMAUDIOHSTSTRMIN)RTMemAllocZ(pThis->BackendCfg.cbStreamIn); 859 if (!pHstStrmIn) 860 { 861 LogFlowFunc(("Error allocating host innput stream with %RU32 bytes\n", 862 pThis->BackendCfg.cbStreamOut)); 863 return VERR_NO_MEMORY; 864 } 865 866 int rc; 867 868 do /* goto avoidance */ 869 { 870 uint32_t cSamples = 0; 871 rc = pThis->pHostDrvAudio->pfnInitIn 872 ? pThis->pHostDrvAudio->pfnInitIn(pThis->pHostDrvAudio, pHstStrmIn, 873 pCfg, pCfg->DestSource.Source, &cSamples) 874 : VINF_SUCCESS; 875 if (RT_FAILURE(rc)) 876 { 877 LogFlowFunc(("Initializing host backend failed with rc=%Rrc\n", rc)); 878 break; 879 } 880 881 pHstStrmIn->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 882 883 char *pszName; 884 if (RTStrAPrintf(&pszName, "%s (Host)", pCfg->szName) <= 0) 885 { 886 rc = VERR_NO_MEMORY; 887 break; 888 } 889 890 rc = AudioMixBufInit(&pHstStrmIn->MixBuf, pszName, &pHstStrmIn->Props, cSamples); 891 if (RT_SUCCESS(rc)) 892 rc = RTCritSectInit(&pHstStrmIn->CritSect); 893 894 if (RT_SUCCESS(rc)) 895 { 896 RTListPrepend(&pThis->lstHstStrmIn, &pHstStrmIn->Node); 897 pThis->cStreamsFreeIn--; 898 } 899 900 RTStrFree(pszName); 901 902 } while (0); 903 904 if (RT_FAILURE(rc)) 905 { 906 if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 907 { 908 int rc2 = pThis->pHostDrvAudio->pfnFiniIn 909 ? pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio, pHstStrmIn) : VINF_SUCCESS; 910 if (RT_SUCCESS(rc2)) 911 pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 912 } 913 914 drvAudioHstInFreeRes(pHstStrmIn); 915 RTMemFree(pHstStrmIn); 916 } 917 else 918 *ppHstStrmIn = pHstStrmIn; 919 920 LogFlowFuncLeaveRC(rc); 921 return rc; 922 } 923 352 #if 1 924 353 /** 925 354 * Writes VM audio output data from the guest stream into the host stream. … … 935 364 * @param pcbWritten 936 365 */ 937 static DECLCALLBACK(int) drvAudioWrite(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut, 938 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten) 939 { 366 static DECLCALLBACK(int) drvAudioStreamWrite(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, 367 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten) 368 { 369 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 370 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 371 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 372 /* pcbWritten is optional. */ 373 940 374 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 941 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 942 943 AssertPtrReturn(pGstStrmOut, VERR_INVALID_POINTER); 944 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 945 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 946 /* pcbWritten is optional. */ 375 376 if (!cbBuf) 377 { 378 if (pcbWritten) 379 *pcbWritten = 0; 380 return VINF_SUCCESS; 381 } 947 382 948 383 int rc = RTCritSectEnter(&pThis->CritSect); … … 950 385 return rc; 951 386 952 if (!pThis->pHostDrvAudio->pfn IsEnabled(pThis->pHostDrvAudio, PDMAUDIODIR_OUT))387 if (!pThis->pHostDrvAudio->pfnGetStatus(pThis->pHostDrvAudio, PDMAUDIODIR_OUT)) 953 388 { 954 389 rc = RTCritSectLeave(&pThis->CritSect); … … 958 393 } 959 394 960 PPDMAUDIOHSTSTRMOUT pHstStrmOut = pGstStrmOut->pHstStrmOut; 961 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 962 963 AssertMsg(pGstStrmOut->pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED, 964 ("Writing to disabled host output stream \"%s\" not possible\n", 965 pHstStrmOut->MixBuf.pszName)); 966 967 if (!AudioMixBufFreeBytes(&pGstStrmOut->MixBuf)) 395 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 396 PPDMAUDIOSTREAM pGstStream = pHstStream->pPair; 397 398 AssertMsg(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED, 399 ("Writing to disabled host output stream \"%s\" not possible\n", pHstStream->szName)); 400 401 if (!AudioMixBufFreeBytes(&pHstStream->MixBuf)) 968 402 { 969 403 if (pcbWritten) … … 978 412 */ 979 413 uint32_t cWritten; 980 rc = AudioMixBufWriteAt(&pGstStrmOut->MixBuf, 0 /* Offset in samples */, pvBuf, cbBuf, &cWritten); 981 414 rc = AudioMixBufWriteCirc(&pGstStream->MixBuf, pvBuf, cbBuf, &cWritten); 415 if (rc == VINF_BUFFER_OVERFLOW) 416 LogRelMax(32, ("Audio: Lost audio samples from guest, expect stuttering audio output\n")); 417 418 /* Host stream currently has no samples to play? */ 419 if (AudioMixBufAvail(&pHstStream->MixBuf) == 0) 420 { 421 /* Mix just written guest stream samples to the host immediately. */ 422 uint32_t cMixed; 423 rc = AudioMixBufMixToParent(&pGstStream->MixBuf, cWritten, &cMixed); 424 LogFlowFunc(("cMixed=%RU32\n", cMixed)); 425 } 426 427 #ifdef DEBUG_andy 428 AssertRC(rc); 429 #endif 430 431 #if 0 982 432 /* 983 433 * Second, mix the guest mixing buffer with the host mixing … … 988 438 && cWritten) 989 439 { 440 rc = AudioMixBufMixToParent(&pGstStream->MixBuf, cWritten, &cMixed); 441 } 442 else 443 cMixed = 0; 444 445 if (RT_SUCCESS(rc)) 446 { 447 /* 448 * Return the number of samples which actually have been mixed 449 * down to the parent, regardless how much samples were written 450 * into the children buffer. 451 */ 452 if (pcbWritten) 453 *pcbWritten = AUDIOMIXBUF_S2B(&pGstStream->MixBuf, cMixed); 454 } 455 #else 456 if (RT_SUCCESS(rc)) 457 { 458 if (pcbWritten) 459 *pcbWritten = AUDIOMIXBUF_S2B(&pGstStream->MixBuf, cWritten); 460 } 461 #endif 462 463 LogFlowFunc(("%s -> %s: cbBuf=%RU32, cWritten=%RU32 (%RU32 bytes), rc=%Rrc\n", 464 pGstStream->szName, pHstStream->szName, cbBuf, 465 cWritten, AUDIOMIXBUF_S2B(&pHstStream->MixBuf, cWritten), rc)); 466 467 int rc2 = RTCritSectLeave(&pThis->CritSect); 468 if (RT_SUCCESS(rc)) 469 rc = rc2; 470 471 return rc; 472 } 473 #else 474 static DECLCALLBACK(int) drvAudioWrite(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut, 475 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten) 476 { 477 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 478 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 479 480 AssertPtrReturn(pGstStrmOut, VERR_INVALID_POINTER); 481 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 482 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 483 /* pcbWritten is optional. */ 484 485 int rc = RTCritSectEnter(&pThis->CritSect); 486 if (RT_FAILURE(rc)) 487 return rc; 488 489 if (!pThis->pHostDrvAudio->pfnIsEnabled(pThis->pHostDrvAudio, PDMAUDIODIR_OUT)) 490 { 491 rc = RTCritSectLeave(&pThis->CritSect); 492 AssertRC(rc); 493 494 return VERR_NOT_AVAILABLE; 495 } 496 497 PPDMAUDIOHSTSTRMOUT pHstStrmOut = pGstStrmOut->pHstStrmOut; 498 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 499 500 AssertMsg(pGstStrmOut->pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED, 501 ("Writing to disabled host output stream \"%s\" not possible\n", 502 pHstStrmOut->MixBuf.pszName)); 503 504 if (!AudioMixBufFreeBytes(&pGstStrmOut->MixBuf)) 505 { 506 if (pcbWritten) 507 *pcbWritten = 0; 508 509 return RTCritSectLeave(&pThis->CritSect); 510 } 511 512 /* 513 * First, write data from the device emulation into our 514 * guest mixing buffer. 515 */ 516 uint32_t cWritten; 517 //rc = AudioMixBufWriteAt(&pGstStrmOut->MixBuf, 0 /* Offset in samples */, pvBuf, cbBuf, &cWritten); 518 rc = AudioMixBufWriteCirc(&pGstStrmOut->MixBuf, pvBuf, cbBuf, &cWritten); 519 if (rc == VINF_BUFFER_OVERFLOW) 520 LogRel(("Audio: Lost audio samples from guest, expect stuttering audio output\n")); 521 522 /* 523 * Second, mix the guest mixing buffer with the host mixing 524 * buffer so that the host backend can play the data lateron. 525 */ 526 uint32_t cMixed; 527 if ( RT_SUCCESS(rc) 528 && cWritten) 529 { 990 530 rc = AudioMixBufMixToParent(&pGstStrmOut->MixBuf, cWritten, &cMixed); 991 531 } … … 1014 554 return rc; 1015 555 } 1016 1017 static PPDMAUDIOHSTSTRMOUT drvAudioFindAnyHstOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut) 1018 { 1019 if (pHstStrmOut) 1020 { 1021 if (RTListNodeIsLast(&pThis->lstHstStrmOut, &pHstStrmOut->Node)) 1022 return NULL; 1023 1024 return RTListNodeGetNext(&pHstStrmOut->Node, PDMAUDIOHSTSTRMOUT, Node); 1025 } 1026 1027 return RTListGetFirst(&pThis->lstHstStrmOut, PDMAUDIOHSTSTRMOUT, Node); 1028 } 1029 1030 static PPDMAUDIOHSTSTRMOUT drvAudioHstFindAnyEnabledOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHostStrmOut) 1031 { 1032 while ((pHostStrmOut = drvAudioFindAnyHstOut(pThis, pHostStrmOut))) 1033 { 1034 if (pHostStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED) 1035 return pHostStrmOut; 1036 } 1037 1038 return NULL; 1039 } 1040 1041 static PPDMAUDIOHSTSTRMOUT drvAudioFindSpecificOut(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMOUT pHstStrmOut, 1042 PPDMAUDIOSTREAMCFG pCfg) 1043 { 1044 while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut))) 1045 { 1046 if (DrvAudioPCMPropsAreEqual(&pHstStrmOut->Props, pCfg)) 1047 return pHstStrmOut; 1048 } 1049 1050 return NULL; 1051 } 1052 1053 int drvAudioDestroyHstIn(PDRVAUDIO pThis, PPDMAUDIOHSTSTRMIN pHstStrmIn) 1054 { 1055 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1056 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 1057 1058 LogFlowFunc(("%s\n", pHstStrmIn->MixBuf.pszName)); 1059 1060 int rc = VINF_SUCCESS; 1061 1062 if (!pHstStrmIn->pGstStrmIn) 1063 { 1064 drvAudioHstInFreeRes(pHstStrmIn); 1065 1066 if (RTCritSectIsInitialized(&pHstStrmIn->CritSect)) 1067 { 1068 int rc2 = RTCritSectDelete(&pHstStrmIn->CritSect); 1069 AssertRC(rc2); 1070 } 1071 1072 /* Remove from driver instance list. */ 1073 RTListNodeRemove(&pHstStrmIn->Node); 1074 1075 RTMemFree(pHstStrmIn); 1076 pThis->cStreamsFreeIn++; 1077 } 1078 else 1079 { 1080 rc = VERR_WRONG_ORDER; 1081 LogFlowFunc(("[%s] Still is being used, skipping\n", pHstStrmIn->MixBuf.pszName)); 1082 } 1083 1084 LogFlowFuncLeaveRC(rc); 556 #endif 557 558 static DECLCALLBACK(uint32_t) drvAudioStreamAddRef(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream) 559 { 560 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 561 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 562 563 NOREF(pInterface); 564 565 return ++pStream->cRefs; 566 } 567 568 static DECLCALLBACK(uint32_t) drvAudioStreamRelease(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream) 569 { 570 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 571 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 572 573 NOREF(pInterface); 574 575 Assert(pStream->cRefs); 576 if (pStream->cRefs) 577 pStream->cRefs--; 578 579 return pStream->cRefs; 580 } 581 582 #if 1 583 static DECLCALLBACK(int) drvAudioStreamGetData(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, uint32_t *pcData) 584 { 585 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 586 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 587 /* pcData is optional. */ 588 589 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 590 591 int rc = RTCritSectEnter(&pThis->CritSect); 592 if (RT_FAILURE(rc)) 593 return rc; 594 595 uint32_t cData = 0; 596 597 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 598 PPDMAUDIOSTREAM pGstStream = pHstStream->pPair; 599 600 do 601 { 602 if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 603 break; 604 605 if (pHstStream->enmDir == PDMAUDIODIR_IN) 606 { 607 /* Call the host backend to capture the audio input data. */ 608 rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pHstStream, &cData); 609 if (RT_FAILURE(rc)) 610 break; 611 612 //cbData = AUDIOMIXBUF_S2B(&pStream->MixBuf, AudioMixBufMixed(&pStream->MixBuf))); 613 614 } 615 else /* Out */ 616 { 617 uint32_t cSamplesMixed = 0; 618 uint32_t cSamplesToMix = 0; 619 620 uint32_t cSamplesLive = AudioMixBufAvail(&pHstStream->MixBuf); 621 if (!cSamplesLive) 622 { 623 624 } 625 626 cSamplesToMix = AudioMixBufAvail(&pGstStream->MixBuf); 627 if (cSamplesToMix) 628 rc = AudioMixBufMixToParent(&pGstStream->MixBuf, cSamplesToMix, &cSamplesMixed); 629 630 /* Has this stream marked as disabled but there still were guest streams relying 631 * on it? CheckpHstStreamif this stream now can be closed and do so, if possible. */ 632 if ( (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE) 633 && !cSamplesToMix) 634 { 635 /* Stop playing the current (pending) stream. */ 636 int rc2 = drvAudioStreamControlInternal(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 637 if (RT_SUCCESS(rc2)) 638 { 639 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE; 640 641 LogFunc(("%s: Disabling stream\n", pHstStream->szName)); 642 } 643 else 644 LogFunc(("%s: Backend vetoed against closing output stream, rc=%Rrc\n", pHstStream->szName, rc2)); 645 646 break; 647 } 648 649 LogFlowFunc(("%s: cSamplesLive=%RU32, cSamplesToMix=%RU32, cSamplesMixed=%RU32\n", 650 pHstStream->szName, cSamplesLive, cSamplesToMix, cSamplesMixed)); 651 652 /* Return live samples to play. */ 653 cData = cSamplesLive; 654 } 655 656 } while (0); 657 658 #ifdef DEBUG_andy 659 LogFlowFunc(("%s: cData=%RU32\n", pHstStream->szName, cData)); 660 #endif 661 662 if (pcData) 663 *pcData = cData; 664 665 int rc2 = RTCritSectLeave(&pThis->CritSect); 666 if (RT_SUCCESS(rc)) 667 rc = rc2; 668 669 if (RT_FAILURE(rc)) 670 LogFlowFuncLeaveRC(rc); 671 1085 672 return rc; 1086 673 } 1087 1088 static int drvAudioDestroyGstIn(PDRVAUDIO pThis, PPDMAUDIOGSTSTRMIN pGstStrmIn) 1089 { 1090 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1091 1092 if (!pGstStrmIn) 1093 return VINF_SUCCESS; 1094 1095 LogFlowFunc(("%s\n", pGstStrmIn->MixBuf.pszName)); 1096 1097 if (pGstStrmIn->State.cRefs > 1) /* Do other objects still have a reference to it? Bail out. */ 1098 return VERR_WRONG_ORDER; 1099 1100 AudioMixBufDestroy(&pGstStrmIn->MixBuf); 1101 1102 /* Is this guest stream associate to a host stream? */ 1103 if (pGstStrmIn->pHstStrmIn) 1104 { 1105 /* Unlink child. */ 1106 pGstStrmIn->pHstStrmIn->pGstStrmIn = NULL; 1107 } 1108 1109 RTMemFree(pGstStrmIn); 1110 pGstStrmIn = NULL; 1111 1112 return VINF_SUCCESS; 1113 } 1114 1115 static DECLCALLBACK(uint32_t) drvAudioAddRefIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrm) 1116 { 1117 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1118 AssertPtrReturn(pGstStrm, VERR_INVALID_POINTER); 1119 1120 NOREF(pInterface); 1121 1122 return ++pGstStrm->State.cRefs; 1123 } 1124 1125 static DECLCALLBACK(uint32_t) drvAudioAddRefOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrm) 1126 { 1127 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1128 AssertPtrReturn(pGstStrm, VERR_INVALID_POINTER); 1129 1130 NOREF(pInterface); 1131 1132 return ++pGstStrm->State.cRefs; 1133 } 1134 1135 static DECLCALLBACK(uint32_t) drvAudioReleaseIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrm) 1136 { 1137 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1138 AssertPtrReturn(pGstStrm, VERR_INVALID_POINTER); 1139 1140 NOREF(pInterface); 1141 1142 Assert(pGstStrm->State.cRefs); 1143 if (pGstStrm->State.cRefs) 1144 pGstStrm->State.cRefs--; 1145 1146 return pGstStrm->State.cRefs; 1147 } 1148 1149 static DECLCALLBACK(uint32_t) drvAudioReleaseOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrm) 1150 { 1151 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1152 AssertPtrReturn(pGstStrm, VERR_INVALID_POINTER); 1153 1154 NOREF(pInterface); 1155 1156 Assert(pGstStrm->State.cRefs); 1157 if (pGstStrm->State.cRefs) 1158 pGstStrm->State.cRefs--; 1159 1160 return pGstStrm->State.cRefs; 1161 } 1162 674 #else 1163 675 static DECLCALLBACK(int) drvAudioGetDataIn(PPDMIAUDIOCONNECTOR pInterface, uint32_t *pcbAvailIn) 1164 676 { … … 1228 740 if (RT_FAILURE(rc)) 1229 741 return rc; 742 743 static uint64_t s_tsLast = 0; 744 745 746 uint64_t s_tsDelta = RTTimeNanoTS() - s_tsLast; 747 LogFlowFunc(("delta=%RU64 (%RU64ms) -> ", s_tsDelta, s_tsDelta / 1000 / 1000)); 748 749 #if 0 750 PPDMAUDIOHSTSTRMOUT pHstStrmOut = drvAudioHstFindAnyEnabledOut(pThis, NULL); 751 uint64_t ns = s_tsDelta / pHstStrmOut->Props.uHz; 752 753 754 755 uint32_t cSamplesMin = (cTicksElapsed / pSink->PCMProps.uHz) * pSink->PCMProps.cChannels; 756 #endif 757 758 s_tsLast = RTTimeNanoTS(); 1230 759 1231 760 /* … … 1308 837 return rc; 1309 838 } 1310 839 #endif 840 841 #if 1 842 static DECLCALLBACK(int) drvAudioStreamPlay(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, uint32_t *pcSamplesPlayed) 843 { 844 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 845 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 846 /* pcSamplesPlayed is optional. */ 847 848 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 849 850 int rc = RTCritSectEnter(&pThis->CritSect); 851 if (RT_FAILURE(rc)) 852 return rc; 853 854 /* Backend output (temporarily) disabled / unavailable? */ 855 if (pThis->pHostDrvAudio->pfnGetStatus(pThis->pHostDrvAudio, PDMAUDIODIR_OUT) != PDMAUDIOBACKENDSTS_RUNNING) 856 { 857 rc = pThis->pHostDrvAudio->pfnGetConfig(pThis->pHostDrvAudio, &pThis->BackendCfg); 858 AssertRC(rc); 859 860 if ( !pThis->BackendCfg.cSinks 861 || !pThis->BackendCfg.cMaxStreamsOut) 862 { 863 int rc2 = RTCritSectLeave(&pThis->CritSect); 864 AssertRC(rc2); 865 866 return VERR_NOT_AVAILABLE; 867 } 868 } 869 870 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 871 872 uint32_t cSamplesPlayed = 0; 873 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream, &cSamplesPlayed); 874 if (RT_FAILURE(rc)) 875 { 876 int rc3 = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 877 AssertRC(rc3); 878 } 879 880 LogFlowFunc(("[%s] cSamplesPlayed=%RU32, rc=%Rrc\n", pStream->szName, cSamplesPlayed, rc)); 881 882 PPDMAUDIOSTREAM pGstStream = pHstStream->pPair; 883 if (pGstStream) 884 { 885 bool fIsEmpty = AudioMixBufIsEmpty(&pGstStream->MixBuf); 886 887 888 } 889 890 #if 0 891 if (pStream->pPair) 892 { 893 bool fIsEmpty = AudioMixBufIsEmpty(&pStream->pPair->MixBuf); 894 895 if ( !pPair->State.fActive 896 && fIsEmpty) 897 continue; 898 899 if () 900 { 901 pGstStrmOut->State.fEmpty = true; 902 fNeedsCleanup |= !pGstStrmOut->State.fActive; 903 } 904 } 905 906 if (fNeedsCleanup) 907 { 908 RTListForEach(&pHstStrmOut->lstGstStrmOut, pGstStrmOut, PDMAUDIOGSTSTRMOUT, Node) 909 { 910 if (!pGstStrmOut->State.fActive) 911 drvAudioDestroyGstOut(pThis, pGstStrmOut); 912 } 913 } 914 #endif 915 916 if (RT_SUCCESS(rc)) 917 { 918 if (pcSamplesPlayed) 919 *pcSamplesPlayed = cSamplesPlayed; 920 } 921 922 int rc2 = RTCritSectLeave(&pThis->CritSect); 923 if (RT_SUCCESS(rc)) 924 rc = rc2; 925 926 if (RT_FAILURE(rc)) 927 LogFlowFuncLeaveRC(rc); 928 929 return rc; 930 } 931 #else 1311 932 static DECLCALLBACK(int) drvAudioPlayOut(PPDMIAUDIOCONNECTOR pInterface, uint32_t *pcSamplesPlayed) 1312 933 { … … 1371 992 } 1372 993 #endif 1373 1374 994 uint32_t cSamplesPlayed = 0; 1375 995 int rc2 = pThis->pHostDrvAudio->pfnPlayOut(pThis->pHostDrvAudio, pHstStrmOut, &cSamplesPlayed); … … 1426 1046 return rc; 1427 1047 } 1048 #endif 1428 1049 1429 1050 #ifdef VBOX_WITH_AUDIO_CALLBACKS … … 1567 1188 1568 1189 /* Get the configuration data from backend. */ 1569 rc = pThis->pHostDrvAudio->pfnGetConf (pThis->pHostDrvAudio, &pThis->BackendCfg);1190 rc = pThis->pHostDrvAudio->pfnGetConfig(pThis->pHostDrvAudio, &pThis->BackendCfg); 1570 1191 if (RT_FAILURE(rc)) 1571 1192 { … … 1611 1232 return; 1612 1233 1613 PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL; 1614 while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut))) 1615 drvAudioControlHstOut(pThis, pHstStrmOut, enmCmd); 1616 1617 PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL; 1618 while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn))) 1619 drvAudioControlHstIn(pThis, pHstStrmIn, enmCmd); 1234 PPDMAUDIOSTREAM pStream; 1235 RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node) 1236 drvAudioStreamControlInternal(pThis, pStream, enmCmd); 1620 1237 } 1621 1238 … … 1628 1245 LogFlowFunc(("pThis=%p, pDrvIns=%p\n", pThis, pDrvIns)); 1629 1246 1630 RTListInit(&pThis->lstHstStrmIn); 1631 RTListInit(&pThis->lstHstStrmOut); 1247 RTListInit(&pThis->lstStreams); 1632 1248 #ifdef VBOX_WITH_AUDIO_CALLBACKS 1633 1249 RTListInit(&pThis->lstCBIn); … … 1649 1265 } 1650 1266 1267 #if 1 1268 static DECLCALLBACK(int) drvAudioStreamRead(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, 1269 void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead) 1270 { 1271 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 1272 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1273 1274 if (!pStream) 1275 return VERR_NOT_AVAILABLE; 1276 1277 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 1278 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 1279 /* pcbWritten is optional. */ 1280 1281 int rc = RTCritSectEnter(&pThis->CritSect); 1282 if (RT_FAILURE(rc)) 1283 return rc; 1284 1285 if (pThis->pHostDrvAudio->pfnGetStatus(pThis->pHostDrvAudio, PDMAUDIODIR_IN) != PDMAUDIOBACKENDSTS_RUNNING) 1286 { 1287 if (pcbRead) 1288 *pcbRead = 0; 1289 1290 return RTCritSectLeave(&pThis->CritSect); 1291 } 1292 1293 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 1294 1295 AssertMsg(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED, 1296 ("Reading from disabled host input stream '%s' not possible\n", pHstStream->szName)); 1297 1298 /* 1299 * Read from the parent buffer (that is, the guest buffer) which 1300 * should have the audio data in the format the guest needs. 1301 */ 1302 uint32_t cRead; 1303 rc = AudioMixBufReadCirc(&pStream->MixBuf, pvBuf, cbBuf, &cRead); 1304 if (RT_SUCCESS(rc)) 1305 { 1306 AudioMixBufFinish(&pStream->MixBuf, cRead); 1307 1308 if (pcbRead) 1309 *pcbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead); 1310 } 1311 1312 LogFlowFunc(("cRead=%RU32 (%RU32 bytes), rc=%Rrc\n", 1313 cRead, AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead), rc)); 1314 1315 int rc2 = RTCritSectLeave(&pThis->CritSect); 1316 if (RT_SUCCESS(rc)) 1317 rc = rc2; 1318 1319 return rc; 1320 } 1321 #else 1651 1322 static DECLCALLBACK(int) drvAudioRead(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrmIn, 1652 1323 void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead) … … 1703 1374 return rc; 1704 1375 } 1705 1376 #endif 1377 1378 #if 0 1706 1379 static DECLCALLBACK(int) drvAudioEnableOut(PPDMIAUDIOCONNECTOR pInterface, 1707 1380 PPDMAUDIOGSTSTRMOUT pGstStrmOut, bool fEnable) … … 1780 1453 return rc; 1781 1454 } 1782 1783 static DECLCALLBACK(int) drvAudioEnableIn(PPDMIAUDIOCONNECTOR pInterface, 1784 PPDMAUDIOGSTSTRMIN pGstStrmIn, bool fEnable) 1455 #endif 1456 1457 static DECLCALLBACK(int) drvAudioStreamCreate(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg, 1458 PPDMAUDIOSTREAM *ppStream) 1785 1459 { 1786 1460 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1787 1788 if (!pGstStrmIn) 1789 return VERR_NOT_AVAILABLE; 1461 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1462 AssertPtrReturn(ppStream, VERR_INVALID_POINTER); 1790 1463 1791 1464 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 1792 1465 1793 int rc = VINF_SUCCESS;1794 1795 PPDMAUDIOHSTSTRMIN pHstStrmIn = pGstStrmIn->pHstStrmIn;1796 AssertPtr(pHstStrmIn);1797 1798 rc = drvAudioControlHstIn(pThis, pHstStrmIn,1799 fEnable ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE);1800 if (RT_SUCCESS(rc))1801 pGstStrmIn->State.fActive = fEnable;1802 1803 LogFlowFunc(("%s: fEnable=%RTbool, rc=%Rrc\n", pGstStrmIn->MixBuf.pszName, fEnable, rc));1804 1805 return rc;1806 }1807 1808 static DECLCALLBACK(bool) drvAudioIsValidIn(PPDMIAUDIOCONNECTOR pInterface,1809 PPDMAUDIOGSTSTRMIN pGstStrmIn)1810 {1811 return (pGstStrmIn != NULL);1812 }1813 1814 static DECLCALLBACK(bool) drvAudioIsValidOut(PPDMIAUDIOCONNECTOR pInterface,1815 PPDMAUDIOGSTSTRMOUT pGstStrmOut)1816 {1817 return (pGstStrmOut != NULL);1818 }1819 1820 static DECLCALLBACK(int) drvAudioCreateIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg,1821 PPDMAUDIOGSTSTRMIN *ppGstStrmIn)1822 {1823 AssertPtrReturn(pInterface, VERR_INVALID_POINTER);1824 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);1825 AssertPtrReturn(ppGstStrmIn, VERR_INVALID_POINTER);1826 1827 Assert(pCfg->enmDir == PDMAUDIODIR_IN);1828 1829 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);1830 1831 1466 int rc = RTCritSectEnter(&pThis->CritSect); 1832 1467 if (RT_FAILURE(rc)) … … 1834 1469 1835 1470 LogFlowFunc(("szName=%s\n", pCfg->szName)); 1836 1837 if (!drvAudioStreamCfgIsValid(pCfg)) 1838 { 1839 LogFunc(("Input stream configuration is not valid, bailing out\n")); 1840 rc = VERR_INVALID_PARAMETER; 1841 } 1842 1843 if (RT_SUCCESS(rc)) 1844 { 1845 PPDMAUDIOGSTSTRMIN pGstStrmIn; 1846 rc = drvAudioCreateStreamPairIn(pThis, pCfg, &pGstStrmIn); 1471 #ifdef DEBUG 1472 DrvAudioStreamCfgPrint(pCfg); 1473 #endif 1474 1475 /* 1476 * The guest stream always will get the audio stream configuration told 1477 * by the device emulation (which in turn was/could be set by the guest OS). 1478 */ 1479 PPDMAUDIOSTREAM pGstStrm = NULL; 1480 1481 /** @todo Docs! */ 1482 PPDMAUDIOSTREAM pHstStrm = NULL; 1483 1484 #define RC_BREAK(x) { rc = x; break; } 1485 1486 do 1487 { 1488 if (!DrvAudioStreamCfgIsValid(pCfg)) 1489 RC_BREAK(VERR_INVALID_PARAMETER); 1490 1491 /* Note: cbHstStrm will contain sizeof(PDMAUDIOSTREAM) + additional data 1492 * which the host backend will need. */ 1493 size_t cbHstStrm; 1494 if (pCfg->enmDir == PDMAUDIODIR_IN) 1495 { 1496 if (!pThis->cStreamsFreeIn) 1497 { 1498 LogFlowFunc(("No more input streams free to use, bailing out\n")); 1499 RC_BREAK(VERR_AUDIO_NO_FREE_INPUT_STREAMS); 1500 } 1501 1502 /* Validate backend configuration. */ 1503 if (!pThis->BackendCfg.cbStreamIn) 1504 { 1505 LogFlowFunc(("Backend input configuration not valid, bailing out\n")); 1506 RC_BREAK(VERR_INVALID_PARAMETER); 1507 } 1508 1509 cbHstStrm = pThis->BackendCfg.cbStreamIn; 1510 } 1511 else /* Out */ 1512 { 1513 if (!pThis->cStreamsFreeOut) 1514 { 1515 LogFlowFunc(("Maximum number of host output streams reached\n")); 1516 RC_BREAK(VERR_NO_MORE_HANDLES); /** @todo Fudge! */ 1517 } 1518 1519 /* Validate backend configuration. */ 1520 if (!pThis->BackendCfg.cbStreamOut) 1521 { 1522 LogFlowFunc(("Backend output configuration invalid, bailing out\n")); 1523 RC_BREAK(VERR_INVALID_PARAMETER); 1524 } 1525 1526 cbHstStrm = pThis->BackendCfg.cbStreamOut; 1527 } 1528 1529 pHstStrm = (PPDMAUDIOSTREAM)RTMemAllocZ(cbHstStrm); 1530 AssertPtrBreakStmt(pHstStrm, rc = VERR_NO_MEMORY); 1531 1532 RTListAppend(&pThis->lstStreams, &pHstStrm->Node); 1533 1534 pGstStrm = (PPDMAUDIOSTREAM)RTMemAllocZ(sizeof(PDMAUDIOSTREAM)); 1535 AssertPtrBreakStmt(pGstStrm, rc = VERR_NO_MEMORY); 1536 1537 RTListAppend(&pThis->lstStreams, &pGstStrm->Node); 1538 1539 /* 1540 * Create host stream. 1541 */ 1542 1543 RTStrPrintf(pHstStrm->szName, RT_ELEMENTS(pHstStrm->szName), "%s (Host)", 1544 strlen(pCfg->szName) ? pCfg->szName : "<Untitled>"); 1545 1546 /* Note: Direction is always from child -> parent. */ 1547 uint32_t cSamples = 0; 1548 rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pHstStrm, pCfg, &cSamples); 1549 if (RT_FAILURE(rc)) 1550 { 1551 LogFlowFunc(("Initializing host backend failed with rc=%Rrc\n", rc)); 1552 break; 1553 } 1554 1555 pHstStrm->enmCtx = PDMAUDIOSTREAMCTX_HOST; 1556 pHstStrm->enmDir = pCfg->enmDir; 1557 pHstStrm->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 1558 pHstStrm->pPair = pGstStrm; 1559 1560 rc = DrvAudioStreamCfgToProps(pCfg, &pHstStrm->Props); 1561 AssertRCBreak(rc); 1562 1563 rc = AudioMixBufInit(&pHstStrm->MixBuf, pHstStrm->szName, &pHstStrm->Props, cSamples); 1564 AssertRCBreak(rc); 1565 1566 /* 1567 * Create guest stream. 1568 */ 1569 1570 RTStrPrintf(pGstStrm->szName, RT_ELEMENTS(pGstStrm->szName), "%s (Guest)", 1571 strlen(pCfg->szName) ? pCfg->szName : "<Untitled>"); 1572 1573 rc = DrvAudioStreamCfgToProps(pCfg, &pGstStrm->Props); 1574 AssertRCBreak(rc); 1575 1576 rc = AudioMixBufInit(&pGstStrm->MixBuf, pGstStrm->szName, &pGstStrm->Props, AudioMixBufSize(&pHstStrm->MixBuf)); 1847 1577 if (RT_SUCCESS(rc)) 1848 *ppGstStrmIn = pGstStrmIn; 1578 { 1579 if (pCfg->enmDir == PDMAUDIODIR_IN) 1580 { 1581 rc = AudioMixBufLinkTo(&pHstStrm->MixBuf, &pGstStrm->MixBuf); 1582 } 1583 else 1584 { 1585 rc = AudioMixBufLinkTo(&pGstStrm->MixBuf, &pHstStrm->MixBuf); 1586 } 1587 } 1588 1589 pGstStrm->enmCtx = PDMAUDIOSTREAMCTX_GUEST; 1590 pGstStrm->enmDir = pCfg->enmDir; 1591 pGstStrm->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 1592 pGstStrm->pPair = pHstStrm; 1593 1594 AssertRCBreak(rc); 1595 1596 } while (0); 1597 1598 #undef RC_BREAK 1599 1600 if (RT_FAILURE(rc)) 1601 { 1602 if (pHstStrm->enmCtx == PDMAUDIOSTREAMCTX_HOST) 1603 { 1604 if (pHstStrm->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 1605 { 1606 rc = drvAudioStreamControlInternal(pThis, pHstStrm, PDMAUDIOSTREAMCMD_DISABLE); 1607 if (RT_SUCCESS(rc)) 1608 { 1609 rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pHstStrm); 1610 if (RT_SUCCESS(rc)) 1611 pHstStrm->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 1612 } 1613 } 1614 1615 AssertMsgRC(rc, ("Host stream '%s' failed to uninit in backend: %Rrc\n", pHstStrm->szName, rc)); 1616 } 1617 1618 drvAudioStreamDestroyInternal(pThis, pGstStrm); 1619 pGstStrm = NULL; 1620 1621 drvAudioStreamDestroyInternal(pThis, pHstStrm); 1622 pHstStrm = NULL; 1623 } 1624 else 1625 { 1626 /* Set initial reference counts. */ 1627 pGstStrm->cRefs = 1; 1628 pHstStrm->cRefs = 1; 1629 1630 if (pCfg->enmDir == PDMAUDIODIR_IN) 1631 { 1632 Assert(pThis->cStreamsFreeIn); 1633 pThis->cStreamsFreeIn--; 1634 } 1635 else /* Out */ 1636 { 1637 Assert(pThis->cStreamsFreeOut); 1638 pThis->cStreamsFreeOut--; 1639 } 1640 1641 *ppStream = pGstStrm; 1849 1642 } 1850 1643 … … 1857 1650 } 1858 1651 1859 static DECLCALLBACK(int) drvAudioCreateOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg, 1860 PPDMAUDIOGSTSTRMOUT *ppGstStrmOut) 1861 { 1862 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1863 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1864 AssertPtrReturn(ppGstStrmOut, VERR_INVALID_POINTER); 1865 1866 Assert(pCfg->enmDir == PDMAUDIODIR_OUT); 1652 #if 1 1653 static DECLCALLBACK(int) drvAudioGetConfig(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg) 1654 { 1655 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1656 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1867 1657 1868 1658 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); … … 1872 1662 return rc; 1873 1663 1874 LogFlowFunc(("pszName=%s\n", pCfg->szName)); 1875 1876 if (!drvAudioStreamCfgIsValid(pCfg)) 1877 { 1878 LogFunc(("Output stream configuration is not valid, bailing out\n")); 1879 rc = VERR_INVALID_PARAMETER; 1880 } 1881 1882 if (RT_SUCCESS(rc)) 1883 { 1884 PPDMAUDIOGSTSTRMOUT pGstStrmOut; 1885 rc = drvAudioCreateStreamPairOut(pThis, pCfg, &pGstStrmOut); 1886 if (RT_SUCCESS(rc)) 1887 *ppGstStrmOut = pGstStrmOut; 1888 } 1664 rc = pThis->pHostDrvAudio->pfnGetConfig(pThis->pHostDrvAudio, pCfg); 1889 1665 1890 1666 int rc2 = RTCritSectLeave(&pThis->CritSect); … … 1896 1672 } 1897 1673 1898 static DECLCALLBACK(int) drvAudioGetConfig(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg) 1899 { 1900 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1901 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1902 1903 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 1904 1905 int rc = RTCritSectEnter(&pThis->CritSect); 1906 if (RT_FAILURE(rc)) 1907 return rc; 1908 1909 rc = pThis->pHostDrvAudio->pfnGetConf(pThis->pHostDrvAudio, pCfg); 1910 1911 int rc2 = RTCritSectLeave(&pThis->CritSect); 1912 if (RT_SUCCESS(rc)) 1913 rc = rc2; 1914 1915 LogFlowFuncLeaveRC(rc); 1916 return rc; 1917 } 1918 1919 static DECLCALLBACK(bool) drvAudioIsActiveIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrmIn) 1674 static DECLCALLBACK(PDMAUDIOSTRMSTS) drvAudioStreamGetStatus(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream) 1920 1675 { 1921 1676 AssertPtrReturn(pInterface, false); 1922 /* pGstStrmIn is optional. */ 1677 /* pStream is optional. */ 1678 1679 if (!pStream) 1680 return PDMAUDIOSTRMSTS_FLAG_NONE; 1923 1681 1924 1682 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); … … 1927 1685 AssertRC(rc2); 1928 1686 1929 bool fRet = pGstStrmIn ? pGstStrmIn->State.fActive : false; 1687 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 1688 PDMAUDIOSTRMSTS strmSts = pHstStream->fStatus; 1689 1690 LogFlowFunc(("%s: strmSts=%0x%x\n", pHstStream->szName, strmSts)); 1930 1691 1931 1692 rc2 = RTCritSectLeave(&pThis->CritSect); 1932 1693 AssertRC(rc2); 1933 1694 1934 return fRet; 1935 } 1936 1937 static DECLCALLBACK(bool) drvAudioIsActiveOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut) 1938 { 1939 AssertPtrReturn(pInterface, false); 1940 /* pGstStrmOut is optional. */ 1941 1695 return strmSts; 1696 } 1697 #endif 1698 1699 static DECLCALLBACK(int) drvAudioStreamDestroy(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream) 1700 { 1942 1701 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 1943 1702 1944 int rc2 = RTCritSectEnter(&pThis->CritSect); 1945 AssertRC(rc2); 1946 1947 bool fRet = pGstStrmOut ? pGstStrmOut->State.fActive : false; 1948 1949 rc2 = RTCritSectLeave(&pThis->CritSect); 1950 AssertRC(rc2); 1951 1952 return fRet; 1953 } 1954 1955 static DECLCALLBACK(void) drvAudioDestroyIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrmIn) 1956 { 1957 AssertPtrReturnVoid(pInterface); 1958 /* pGstStrmIn is optional. */ 1959 1960 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 1961 1962 if (!pGstStrmIn) 1963 return; 1964 1965 int rc2 = RTCritSectEnter(&pThis->CritSect); 1966 AssertRC(rc2); 1967 1968 rc2 = drvAudioDestroyGstIn(pThis, pGstStrmIn); 1969 AssertRC(rc2); 1970 1971 rc2 = RTCritSectLeave(&pThis->CritSect); 1972 AssertRC(rc2); 1973 } 1974 1975 static DECLCALLBACK(void) drvAudioDestroyOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut) 1976 { 1977 AssertPtrReturnVoid(pInterface); 1978 /* pGstStrmOut is optional. */ 1979 1980 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 1981 1982 if (!pGstStrmOut) 1983 return; 1984 1985 int rc2 = RTCritSectEnter(&pThis->CritSect); 1986 AssertRC(rc2); 1987 1988 rc2 = drvAudioDestroyGstOut(pThis, pGstStrmOut); 1989 AssertRC(rc2); 1990 1991 rc2 = RTCritSectLeave(&pThis->CritSect); 1992 AssertRC(rc2); 1993 } 1994 1995 void drvAudioHstOutFreeRes(PPDMAUDIOHSTSTRMOUT pHstStrmOut) 1996 { 1997 AssertPtrReturnVoid(pHstStrmOut); 1998 AudioMixBufDestroy(&pHstStrmOut->MixBuf); 1703 int rc = RTCritSectEnter(&pThis->CritSect); 1704 AssertRC(rc); 1705 1706 PDMAUDIODIR enmDir = pStream->enmDir; 1707 1708 LogFlowFunc(("%s: cRefs=%RU32\n", pStream->szName, pStream->cRefs)); 1709 if (pStream->cRefs > 1) 1710 rc = VERR_WRONG_ORDER; 1711 1712 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 1713 if ( RT_SUCCESS(rc) 1714 && pHstStream->cRefs == 1) 1715 { 1716 rc = drvAudioStreamDestroyInternalBackend(pThis, pHstStream); 1717 if (RT_SUCCESS(rc)) 1718 { 1719 if (pStream->pPair) 1720 { 1721 rc = drvAudioStreamDestroyInternal(pThis, pStream->pPair); 1722 pStream->pPair = NULL; 1723 } 1724 1725 if (RT_SUCCESS(rc)) 1726 rc = drvAudioStreamDestroyInternal(pThis, pStream); 1727 1728 if (RT_SUCCESS(rc)) 1729 { 1730 if (enmDir == PDMAUDIODIR_IN) 1731 { 1732 pThis->cStreamsFreeIn++; 1733 } 1734 else /* Out */ 1735 { 1736 pThis->cStreamsFreeOut++; 1737 } 1738 } 1739 } 1740 } 1741 else 1742 rc = VERR_WRONG_ORDER; 1743 1744 int rc2 = RTCritSectLeave(&pThis->CritSect); 1745 if (RT_SUCCESS(rc)) 1746 rc = rc2; 1747 1748 if (RT_FAILURE(rc)) 1749 LogFlowFunc(("Failed with %Rrc\n", rc)); 1750 1751 return rc; 1752 } 1753 1754 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream) 1755 { 1756 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1757 AssertPtrReturn(pHstStream, VERR_INVALID_POINTER); 1758 1759 int rc = VINF_SUCCESS; 1760 1761 LogFlowFunc(("%s: fStatus=0x%x\n", pHstStream->szName, pHstStream->fStatus)); 1762 1763 AssertMsg(pHstStream->enmCtx == PDMAUDIOSTREAMCTX_HOST, 1764 ("Stream '%s' is not a host stream and therefore has no backend\n", pHstStream->szName)); 1765 1766 if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 1767 { 1768 rc = drvAudioStreamControlInternal(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 1769 if (RT_SUCCESS(rc)) 1770 { 1771 rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pHstStream); 1772 if (RT_SUCCESS(rc)) 1773 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 1774 } 1775 1776 AssertMsgRC(rc, ("Host stream '%s' failed to uninit in backend: %Rrc\n", pHstStream->szName, rc)); 1777 } 1778 else 1779 rc = VINF_SUCCESS; 1780 1781 LogFlowFunc(("%s: Returning %Rrc\n", pHstStream->szName, rc)); 1782 return rc; 1783 } 1784 1785 static int drvAudioStreamDestroyInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream) 1786 { 1787 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1788 /* pStream is optional. */ 1789 1790 if (!pStream) 1791 return VINF_SUCCESS; 1792 1793 LogFlowFunc(("%s: cRefs=%RU32\n", pStream->szName, pStream->cRefs)); 1794 1795 int rc = VINF_SUCCESS; 1796 1797 if (pStream->cRefs <= 1) 1798 { 1799 /* Unlink from pair. */ 1800 if (pStream->pPair) 1801 { 1802 pStream->pPair->pPair = NULL; 1803 pStream->pPair = NULL; 1804 } 1805 1806 /* Destroy mixing buffer. */ 1807 AudioMixBufDestroy(&pStream->MixBuf); 1808 1809 /* Remove from list. */ 1810 RTListNodeRemove(&pStream->Node); 1811 1812 RTMemFree(pStream); 1813 pStream = NULL; 1814 } 1815 else /* More than our own reference left? Bail out. */ 1816 rc = VERR_WRONG_ORDER; 1817 1818 if (RT_FAILURE(rc)) 1819 LogFunc(("Failed with %Rrc\n", rc)); 1820 1821 return rc; 1999 1822 } 2000 1823 … … 2028 1851 LogFlowFuncEnter(); 2029 1852 2030 /* First, disable all streams. */ 2031 drvAudioStateHandler(pDrvIns, PDMAUDIOSTREAMCMD_DISABLE); 2032 2033 int rc2; 2034 2035 PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL; 2036 while ((pHstStrmOut = drvAudioFindAnyHstOut(pThis, pHstStrmOut))) 2037 { 2038 if (pHstStrmOut->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 2039 { 2040 rc2 = pThis->pHostDrvAudio->pfnFiniOut 2041 ? pThis->pHostDrvAudio->pfnFiniOut(pThis->pHostDrvAudio, pHstStrmOut) : VINF_SUCCESS; 2042 if (RT_SUCCESS(rc2)) 2043 pHstStrmOut->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 2044 } 2045 else 2046 rc2 = VINF_SUCCESS; 2047 2048 AssertMsgRC(rc2, ("Host output stream %p failed to uninit: %Rrc\n", pHstStrmOut, rc2)); 2049 } 2050 2051 PPDMAUDIOHSTSTRMIN pHstStrmIn = NULL; 2052 while ((pHstStrmIn = drvAudioFindAnyHstIn(pThis, pHstStrmIn))) 2053 { 2054 if (pHstStrmIn->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 2055 { 2056 rc2 = pThis->pHostDrvAudio->pfnFiniIn 2057 ? pThis->pHostDrvAudio->pfnFiniIn(pThis->pHostDrvAudio, pHstStrmIn) : VINF_SUCCESS; 2058 if (RT_SUCCESS(rc2)) 2059 pHstStrmIn->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 2060 } 2061 else 2062 rc2 = VINF_SUCCESS; 2063 2064 AssertMsgRC(rc2, ("Host input stream %p failed to uninit: %Rrc\n", pHstStrmIn, rc2)); 1853 /* 1854 * Second, destroy all audio streams. 1855 */ 1856 PPDMAUDIOSTREAM pStream; 1857 RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node) 1858 { 1859 if (pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST) 1860 drvAudioStreamDestroyInternalBackend(pThis, pStream); 2065 1861 } 2066 1862 … … 2092 1888 * Init the static parts. 2093 1889 */ 2094 pThis->pDrvIns 1890 pThis->pDrvIns = pDrvIns; 2095 1891 /* IBase. */ 2096 pDrvIns->IBase.pfnQueryInterface 1892 pDrvIns->IBase.pfnQueryInterface = drvAudioQueryInterface; 2097 1893 /* IAudioConnector. */ 2098 pThis->IAudioConnector.pfnAddRefIn = drvAudioAddRefIn; 2099 pThis->IAudioConnector.pfnAddRefOut = drvAudioAddRefOut; 2100 pThis->IAudioConnector.pfnReleaseIn = drvAudioReleaseIn; 2101 pThis->IAudioConnector.pfnReleaseOut = drvAudioReleaseOut; 2102 pThis->IAudioConnector.pfnRead = drvAudioRead; 2103 pThis->IAudioConnector.pfnWrite = drvAudioWrite; 2104 pThis->IAudioConnector.pfnGetConfig = drvAudioGetConfig; 2105 pThis->IAudioConnector.pfnGetDataIn = drvAudioGetDataIn; 2106 pThis->IAudioConnector.pfnGetDataOut = drvAudioGetDataOut; 2107 pThis->IAudioConnector.pfnIsActiveIn = drvAudioIsActiveIn; 2108 pThis->IAudioConnector.pfnIsActiveOut = drvAudioIsActiveOut; 2109 pThis->IAudioConnector.pfnIsValidIn = drvAudioIsValidIn; 2110 pThis->IAudioConnector.pfnIsValidOut = drvAudioIsValidOut; 2111 pThis->IAudioConnector.pfnEnableOut = drvAudioEnableOut; 2112 pThis->IAudioConnector.pfnEnableIn = drvAudioEnableIn; 2113 pThis->IAudioConnector.pfnDestroyIn = drvAudioDestroyIn; 2114 pThis->IAudioConnector.pfnDestroyOut = drvAudioDestroyOut; 2115 pThis->IAudioConnector.pfnCreateIn = drvAudioCreateIn; 2116 pThis->IAudioConnector.pfnCreateOut = drvAudioCreateOut; 2117 pThis->IAudioConnector.pfnPlayOut = drvAudioPlayOut; 1894 pThis->IAudioConnector.pfnGetConfig = drvAudioGetConfig; 1895 pThis->IAudioConnector.pfnStreamCreate = drvAudioStreamCreate; 1896 pThis->IAudioConnector.pfnStreamDestroy = drvAudioStreamDestroy; 1897 pThis->IAudioConnector.pfnStreamAddRef = drvAudioStreamAddRef; 1898 pThis->IAudioConnector.pfnStreamRelease = drvAudioStreamRelease; 1899 pThis->IAudioConnector.pfnStreamControl = drvAudioStreamControl; 1900 pThis->IAudioConnector.pfnStreamRead = drvAudioStreamRead; 1901 pThis->IAudioConnector.pfnStreamWrite = drvAudioStreamWrite; 1902 pThis->IAudioConnector.pfnStreamGetData = drvAudioStreamGetData; 1903 pThis->IAudioConnector.pfnStreamGetStatus = drvAudioStreamGetStatus; 1904 pThis->IAudioConnector.pfnStreamPlay = drvAudioStreamPlay; 2118 1905 #ifdef VBOX_WITH_AUDIO_CALLBACKS 2119 pThis->IAudioConnector.pfnRegisterCallbacks 2120 pThis->IAudioConnector.pfnCallback 1906 pThis->IAudioConnector.pfnRegisterCallbacks = drvAudioRegisterCallbacks; 1907 pThis->IAudioConnector.pfnCallback = drvAudioCallback; 2121 1908 #endif 2122 1909 … … 2159 1946 static DECLCALLBACK(void) drvAudioDestruct(PPDMDRVINS pDrvIns) 2160 1947 { 2161 LogFlowFuncEnter();2162 2163 1948 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns); 2164 1949 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 1950 1951 LogFlowFuncEnter(); 2165 1952 2166 1953 int rc2 = RTCritSectEnter(&pThis->CritSect); … … 2173 1960 * do this in drvAudioPowerOff() instead. 2174 1961 */ 2175 2176 /* 2177 * Destroy all host input streams. 2178 */ 2179 PPDMAUDIOHSTSTRMIN pHstStrmIn, pHstStrmInNext; 2180 RTListForEachSafe(&pThis->lstHstStrmIn, pHstStrmIn, pHstStrmInNext, PDMAUDIOHSTSTRMIN, Node) 2181 { 2182 rc2 = drvAudioDestroyHstIn(pThis, pHstStrmIn); 2183 AssertRC(rc2); 2184 } 2185 2186 /* 2187 * Destroy all host input streams. 2188 */ 2189 PPDMAUDIOHSTSTRMOUT pHstStrmOut, pHstStrmOutNext; 2190 RTListForEachSafe(&pThis->lstHstStrmOut, pHstStrmOut, pHstStrmOutNext, PDMAUDIOHSTSTRMOUT, Node) 2191 { 2192 rc2 = drvAudioDestroyHstOut(pThis, pHstStrmOut); 2193 AssertRC(rc2); 2194 } 1962 PPDMAUDIOSTREAM pStream, pStreamNext; 1963 RTListForEachSafe(&pThis->lstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, Node) 1964 drvAudioStreamDestroyInternal(pThis, pStream); 2195 1965 2196 1966 /* Sanity. */ 2197 Assert(RTListIsEmpty(&pThis->lstHstStrmIn)); 2198 Assert(RTListIsEmpty(&pThis->lstHstStrmOut)); 1967 Assert(RTListIsEmpty(&pThis->lstStreams)); 2199 1968 2200 1969 #ifdef VBOX_WITH_AUDIO_CALLBACKS -
trunk/src/VBox/Devices/Audio/DrvAudio.h
r61050 r61157 90 90 /** Pointer to audio driver below us. */ 91 91 PPDMIHOSTAUDIO pHostDrvAudio; 92 /** List of host input streams. */ 93 RTLISTANCHOR lstHstStrmIn; 94 /** List of host output streams. */ 95 RTLISTANCHOR lstHstStrmOut; 92 /** List of input/output audio streams. */ 93 RTLISTANCHOR lstStreams; 96 94 /** Max. number of free input streams. 97 95 * UINT32_MAX for unlimited streams. */ … … 119 117 const char *DrvAudRecSrcToStr(PDMAUDIORECSOURCE enmRecSource); 120 118 void DrvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg); 119 bool DrvAudioStreamCfgIsValid(PPDMAUDIOSTREAMCFG pCfg); 121 120 int DrvAudioStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMPCMPROPS pProps); 122 121 PDMAUDIOFMT DrvAudioStrToAudFmt(const char *pszFmt); -
trunk/src/VBox/Devices/Audio/DrvAudioCommon.cpp
r61050 r61157 205 205 bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg) 206 206 { 207 AssertPtrReturn(pProps, VERR_INVALID_POINTER);208 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);207 AssertPtrReturn(pProps, false); 208 AssertPtrReturn(pCfg, false); 209 209 210 210 int cBits = 8; … … 245 245 bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps1, PPDMPCMPROPS pProps2) 246 246 { 247 AssertPtrReturn(pProps1, VERR_INVALID_POINTER);248 AssertPtrReturn(pProps2, VERR_INVALID_POINTER);247 AssertPtrReturn(pProps1, false); 248 AssertPtrReturn(pProps2, false); 249 249 250 250 return pProps1->uHz == pProps2->uHz … … 253 253 && pProps1->cBits == pProps2->cBits 254 254 && pProps1->fSwapEndian == pProps2->fSwapEndian; 255 } 256 257 bool DrvAudioStreamCfgIsValid(PPDMAUDIOSTREAMCFG pCfg) 258 { 259 bool fValid = ( pCfg->cChannels == 1 260 || pCfg->cChannels == 2); /* Either stereo (2) or mono (1), per stream. */ 261 262 fValid |= ( pCfg->enmEndianness == PDMAUDIOENDIANNESS_LITTLE 263 || pCfg->enmEndianness == PDMAUDIOENDIANNESS_BIG); 264 265 fValid |= ( pCfg->enmDir == PDMAUDIODIR_IN 266 || pCfg->enmDir == PDMAUDIODIR_OUT); 267 268 if (fValid) 269 { 270 switch (pCfg->enmFormat) 271 { 272 case PDMAUDIOFMT_S8: 273 case PDMAUDIOFMT_U8: 274 case PDMAUDIOFMT_S16: 275 case PDMAUDIOFMT_U16: 276 case PDMAUDIOFMT_S32: 277 case PDMAUDIOFMT_U32: 278 break; 279 default: 280 fValid = false; 281 break; 282 } 283 } 284 285 /** @todo Check for defined frequencies supported. */ 286 fValid |= pCfg->uHz > 0; 287 288 return fValid; 255 289 } 256 290 -
trunk/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp
r60925 r61157 78 78 typedef struct ALSAAUDIOSTREAMIN 79 79 { 80 PDMAUDIOHSTSTRMIN pStreamIn; 80 /** Associated host input stream. 81 * Note: Always must come first! */ 82 PDMAUDIOSTREAM Stream; 81 83 snd_pcm_t *phPCM; 82 84 void *pvBuf; … … 86 88 typedef struct ALSAAUDIOSTREAMOUT 87 89 { 88 PDMAUDIOHSTSTRMOUT pStreamOut; 90 /** Associated host output stream. 91 * Note: Always must come first! */ 92 PDMAUDIOSTREAM Stream; 89 93 snd_pcm_t *phPCM; 90 94 void *pvBuf; … … 778 782 } 779 783 780 static DECLCALLBACK(int) drvHostALSAAudio CaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,781 uint32_t *pcSamplesCaptured)784 static DECLCALLBACK(int) drvHostALSAAudioStreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 785 uint32_t *pcSamplesCaptured) 782 786 { 783 787 NOREF(pInterface); 784 AssertPtrReturn(p HstStrmIn, VERR_INVALID_POINTER);785 786 PALSAAUDIOSTREAMIN pThisStr mIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;788 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 789 790 PALSAAUDIOSTREAMIN pThisStream = (PALSAAUDIOSTREAMIN)pStream; 787 791 788 792 snd_pcm_sframes_t cAvail; 789 int rc = alsaStreamGetAvail(pThisStr mIn->phPCM, &cAvail);793 int rc = alsaStreamGetAvail(pThisStream->phPCM, &cAvail); 790 794 if (RT_FAILURE(rc)) 791 795 { … … 796 800 if (!cAvail) /* No data yet? */ 797 801 { 798 snd_pcm_state_t state = snd_pcm_state(pThisStr mIn->phPCM);802 snd_pcm_state_t state = snd_pcm_state(pThisStream->phPCM); 799 803 switch (state) 800 804 { 801 805 case SND_PCM_STATE_PREPARED: 802 cAvail = AudioMixBufFree(&p HstStrmIn->MixBuf);806 cAvail = AudioMixBufFree(&pStream->MixBuf); 803 807 break; 804 808 805 809 case SND_PCM_STATE_SUSPENDED: 806 810 { 807 rc = alsaStreamResume(pThisStr mIn->phPCM);811 rc = alsaStreamResume(pThisStream->phPCM); 808 812 if (RT_FAILURE(rc)) 809 813 break; … … 831 835 */ 832 836 Assert(cAvail); 833 size_t cbMixFree = AudioMixBufFreeBytes(&p HstStrmIn->MixBuf);834 size_t cbToRead = RT_MIN((size_t)AUDIOMIXBUF_S2B(&p HstStrmIn->MixBuf, cAvail), cbMixFree);837 size_t cbMixFree = AudioMixBufFreeBytes(&pStream->MixBuf); 838 size_t cbToRead = RT_MIN((size_t)AUDIOMIXBUF_S2B(&pStream->MixBuf, cAvail), cbMixFree); 835 839 836 840 LogFlowFunc(("cbToRead=%zu, cAvail=%RI32\n", cbToRead, cAvail)); … … 843 847 && RT_SUCCESS(rc)) 844 848 { 845 cToRead = RT_MIN(AUDIOMIXBUF_B2S(&p HstStrmIn->MixBuf, cbToRead),846 AUDIOMIXBUF_B2S(&p HstStrmIn->MixBuf, pThisStrmIn->cbBuf));849 cToRead = RT_MIN(AUDIOMIXBUF_B2S(&pStream->MixBuf, cbToRead), 850 AUDIOMIXBUF_B2S(&pStream->MixBuf, pThisStream->cbBuf)); 847 851 AssertBreakStmt(cToRead, rc = VERR_NO_DATA); 848 cRead = snd_pcm_readi(pThisStr mIn->phPCM, pThisStrmIn->pvBuf, cToRead);852 cRead = snd_pcm_readi(pThisStream->phPCM, pThisStream->pvBuf, cToRead); 849 853 if (cRead <= 0) 850 854 { … … 871 875 case -EPIPE: 872 876 { 873 rc = alsaStreamRecover(pThisStr mIn->phPCM);877 rc = alsaStreamRecover(pThisStream->phPCM); 874 878 if (RT_FAILURE(rc)) 875 879 break; … … 890 894 { 891 895 uint32_t cWritten; 892 rc = AudioMixBufWriteCirc(&p HstStrmIn->MixBuf,893 pThisStr mIn->pvBuf, AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cRead),896 rc = AudioMixBufWriteCirc(&pStream->MixBuf, 897 pThisStream->pvBuf, AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead), 894 898 &cWritten); 895 899 if (RT_FAILURE(rc)) … … 903 907 AssertLogRelMsgBreakStmt(cWritten > 0, ("Mixer buffer shouldn't be full at this point!\n"), 904 908 rc = VERR_INTERNAL_ERROR); 905 uint32_t cbWritten = AUDIOMIXBUF_S2B(&p HstStrmIn->MixBuf, cWritten);909 uint32_t cbWritten = AUDIOMIXBUF_S2B(&pStream->MixBuf, cWritten); 906 910 907 911 Assert(cbToRead >= cbWritten); … … 915 919 uint32_t cProcessed = 0; 916 920 if (cWrittenTotal) 917 rc = AudioMixBufMixToParent(&p HstStrmIn->MixBuf, cWrittenTotal,921 rc = AudioMixBufMixToParent(&pStream->MixBuf, cWrittenTotal, 918 922 &cProcessed); 919 923 … … 929 933 } 930 934 931 static DECLCALLBACK(int) drvHostALSAAudio PlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,932 uint32_t *pcSamplesPlayed)935 static DECLCALLBACK(int) drvHostALSAAudioStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 936 uint32_t *pcSamplesPlayed) 933 937 { 934 938 NOREF(pInterface); 935 AssertPtrReturn(p HstStrmOut, VERR_INVALID_POINTER);936 937 PALSAAUDIOSTREAMOUT pThisStr mOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;939 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 940 941 PALSAAUDIOSTREAMOUT pThisStream = (PALSAAUDIOSTREAMOUT)pStream; 938 942 939 943 int rc = VINF_SUCCESS; … … 943 947 { 944 948 snd_pcm_sframes_t cAvail; 945 rc = alsaStreamGetAvail(pThisStr mOut->phPCM, &cAvail);949 rc = alsaStreamGetAvail(pThisStream->phPCM, &cAvail); 946 950 if (RT_FAILURE(rc)) 947 951 { … … 950 954 } 951 955 952 size_t cbToRead = RT_MIN(AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf,956 size_t cbToRead = RT_MIN(AUDIOMIXBUF_S2B(&pStream->MixBuf, 953 957 (uint32_t)cAvail), /* cAvail is always >= 0 */ 954 AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf,955 AudioMixBufAvail(&p HstStrmOut->MixBuf)));958 AUDIOMIXBUF_S2B(&pStream->MixBuf, 959 AudioMixBufAvail(&pStream->MixBuf))); 956 960 LogFlowFunc(("cbToRead=%zu, cbAvail=%zu\n", 957 cbToRead, AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, cAvail)));961 cbToRead, AUDIOMIXBUF_S2B(&pStream->MixBuf, cAvail))); 958 962 959 963 uint32_t cRead, cbRead; … … 961 965 while (cbToRead) 962 966 { 963 rc = AudioMixBufReadCirc(&p HstStrmOut->MixBuf, pThisStrmOut->pvBuf, cbToRead, &cRead);967 rc = AudioMixBufReadCirc(&pStream->MixBuf, pThisStream->pvBuf, cbToRead, &cRead); 964 968 if (RT_FAILURE(rc)) 965 969 break; 966 970 967 cbRead = AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, cRead);971 cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead); 968 972 AssertBreak(cbRead); 969 973 … … 972 976 for (iTry = 0; iTry < ALSA_RECOVERY_TRIES_MAX; iTry++) 973 977 { 974 cWritten = snd_pcm_writei(pThisStr mOut->phPCM, pThisStrmOut->pvBuf, cRead);978 cWritten = snd_pcm_writei(pThisStream->phPCM, pThisStream->pvBuf, cRead); 975 979 if (cWritten <= 0) 976 980 { … … 986 990 case -EPIPE: 987 991 { 988 rc = alsaStreamRecover(pThisStr mOut->phPCM);992 rc = alsaStreamRecover(pThisStream->phPCM); 989 993 if (RT_FAILURE(rc)) 990 994 break; … … 997 1001 { 998 1002 /* Stream was suspended and waiting for a recovery. */ 999 rc = alsaStreamResume(pThisStr mOut->phPCM);1003 rc = alsaStreamResume(pThisStream->phPCM); 1000 1004 if (RT_FAILURE(rc)) 1001 1005 { … … 1035 1039 if (RT_SUCCESS(rc)) 1036 1040 { 1037 uint32_t cReadTotal = AUDIOMIXBUF_B2S(&p HstStrmOut->MixBuf, cbReadTotal);1041 uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pStream->MixBuf, cbReadTotal); 1038 1042 if (cReadTotal) 1039 AudioMixBufFinish(&p HstStrmOut->MixBuf, cReadTotal);1043 AudioMixBufFinish(&pStream->MixBuf, cReadTotal); 1040 1044 1041 1045 if (pcSamplesPlayed) … … 1050 1054 } 1051 1055 1052 static DECLCALLBACK(int) drvHostALSAAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)1056 static int alsaDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1053 1057 { 1054 1058 NOREF(pInterface); 1055 AssertPtrReturn(p HstStrmIn, VERR_INVALID_POINTER);1056 1057 PALSAAUDIOSTREAMIN pThisStr mIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;1058 1059 alsaStreamClose(&pThisStr mIn->phPCM);1060 1061 if (pThisStr mIn->pvBuf)1062 { 1063 RTMemFree(pThisStr mIn->pvBuf);1064 pThisStr mIn->pvBuf = NULL;1059 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1060 1061 PALSAAUDIOSTREAMIN pThisStream = (PALSAAUDIOSTREAMIN)pStream; 1062 1063 alsaStreamClose(&pThisStream->phPCM); 1064 1065 if (pThisStream->pvBuf) 1066 { 1067 RTMemFree(pThisStream->pvBuf); 1068 pThisStream->pvBuf = NULL; 1065 1069 } 1066 1070 … … 1068 1072 } 1069 1073 1070 static DECLCALLBACK(int) drvHostALSAAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)1074 static int alsaDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1071 1075 { 1072 1076 NOREF(pInterface); 1073 AssertPtrReturn(p HstStrmOut, VERR_INVALID_POINTER);1074 1075 PALSAAUDIOSTREAMOUT pThisStr mOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;1076 1077 alsaStreamClose(&pThisStr mOut->phPCM);1078 1079 if (pThisStr mOut->pvBuf)1080 { 1081 RTMemFree(pThisStr mOut->pvBuf);1082 pThisStr mOut->pvBuf = NULL;1077 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1078 1079 PALSAAUDIOSTREAMOUT pThisStream = (PALSAAUDIOSTREAMOUT)pStream; 1080 1081 alsaStreamClose(&pThisStream->phPCM); 1082 1083 if (pThisStream->pvBuf) 1084 { 1085 RTMemFree(pThisStream->pvBuf); 1086 pThisStream->pvBuf = NULL; 1083 1087 } 1084 1088 … … 1086 1090 } 1087 1091 1088 static DECLCALLBACK(int) drvHostALSAAudioInitOut(PPDMIHOSTAUDIO pInterface,1089 PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,1090 1092 static int alsaCreateStreamOut(PPDMIHOSTAUDIO pInterface, 1093 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, 1094 uint32_t *pcSamples) 1091 1095 { 1092 1096 NOREF(pInterface); 1093 AssertPtrReturn(p HstStrmOut, VERR_INVALID_POINTER);1097 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1094 1098 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1095 1099 1096 PALSAAUDIOSTREAMOUT pThisStr mOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;1100 PALSAAUDIOSTREAMOUT pThisStream = (PALSAAUDIOSTREAMOUT)pStream; 1097 1101 snd_pcm_t *phPCM = NULL; 1098 1102 … … 1125 1129 streamCfg.enmEndianness = enmEnd; 1126 1130 1127 rc = DrvAudioStreamCfgToProps(&streamCfg, &p HstStrmOut->Props);1131 rc = DrvAudioStreamCfgToProps(&streamCfg, &pStream->Props); 1128 1132 if (RT_FAILURE(rc)) 1129 1133 break; 1130 1134 1131 1135 AssertBreakStmt(obt.samples, rc = VERR_INVALID_PARAMETER); 1132 size_t cbBuf = obt.samples * (1 << p HstStrmOut->Props.cShift);1136 size_t cbBuf = obt.samples * (1 << pStream->Props.cShift); 1133 1137 AssertBreakStmt(cbBuf, rc = VERR_INVALID_PARAMETER); 1134 pThisStr mOut->pvBuf = RTMemAlloc(cbBuf);1135 if (!pThisStr mOut->pvBuf)1138 pThisStream->pvBuf = RTMemAlloc(cbBuf); 1139 if (!pThisStream->pvBuf) 1136 1140 { 1137 1141 LogRel(("ALSA: Not enough memory for output DAC buffer (%RU32 samples, each %d bytes)\n", 1138 obt.samples, 1 << p HstStrmOut->Props.cShift));1142 obt.samples, 1 << pStream->Props.cShift)); 1139 1143 rc = VERR_NO_MEMORY; 1140 1144 break; 1141 1145 } 1142 1146 1143 pThisStr mOut->cbBuf = cbBuf;1144 pThisStr mOut->phPCM = phPCM;1147 pThisStream->cbBuf = cbBuf; 1148 pThisStream->phPCM = phPCM; 1145 1149 1146 1150 if (pcSamples) … … 1156 1160 } 1157 1161 1158 static DECLCALLBACK(int) drvHostALSAAudioInitIn(PPDMIHOSTAUDIO pInterface, 1159 PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg, 1160 PDMAUDIORECSOURCE enmRecSource, 1161 uint32_t *pcSamples) 1162 static int alsaCreateStreamIn(PPDMIHOSTAUDIO pInterface, 1163 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 1162 1164 { 1163 1165 NOREF(pInterface); 1164 AssertPtrReturn(p HstStrmIn, VERR_INVALID_POINTER);1166 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1165 1167 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1166 1168 1167 1169 int rc; 1168 1170 1169 PALSAAUDIOSTREAMIN pThisStr mIn = (PALSAAUDIOSTREAMIN)pHstStrmIn;1171 PALSAAUDIOSTREAMIN pThisStream = (PALSAAUDIOSTREAMIN)pStream; 1170 1172 snd_pcm_t *phPCM = NULL; 1171 1173 … … 1196 1198 streamCfg.enmEndianness = enmEnd; 1197 1199 1198 rc = DrvAudioStreamCfgToProps(&streamCfg, &p HstStrmIn->Props);1200 rc = DrvAudioStreamCfgToProps(&streamCfg, &pStream->Props); 1199 1201 if (RT_FAILURE(rc)) 1200 1202 break; 1201 1203 1202 1204 AssertBreakStmt(obt.samples, rc = VERR_INVALID_PARAMETER); 1203 size_t cbBuf = obt.samples * (1 << p HstStrmIn->Props.cShift);1205 size_t cbBuf = obt.samples * (1 << pStream->Props.cShift); 1204 1206 AssertBreakStmt(cbBuf, rc = VERR_INVALID_PARAMETER); 1205 pThisStr mIn->pvBuf = RTMemAlloc(cbBuf);1206 if (!pThisStr mIn->pvBuf)1207 pThisStream->pvBuf = RTMemAlloc(cbBuf); 1208 if (!pThisStream->pvBuf) 1207 1209 { 1208 1210 LogRel(("ALSA: Not enough memory for input ADC buffer (%RU32 samples, each %d bytes)\n", 1209 obt.samples, 1 << p HstStrmIn->Props.cShift));1211 obt.samples, 1 << pStream->Props.cShift)); 1210 1212 rc = VERR_NO_MEMORY; 1211 1213 break; 1212 1214 } 1213 1215 1214 pThisStr mIn->cbBuf = cbBuf;1215 pThisStr mIn->phPCM = phPCM;1216 pThisStream->cbBuf = cbBuf; 1217 pThisStream->phPCM = phPCM; 1216 1218 1217 1219 if (pcSamples) … … 1227 1229 } 1228 1230 1229 static DECLCALLBACK(bool) drvHostALSAAudioIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir) 1231 static int alsaControlStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 1232 PDMAUDIOSTREAMCMD enmStreamCmd) 1230 1233 { 1231 1234 NOREF(pInterface); 1232 NOREF(enmDir); 1233 return true; /* Always all enabled. */ 1234 } 1235 1236 static DECLCALLBACK(int) drvHostALSAAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn, 1237 PDMAUDIOSTREAMCMD enmStreamCmd) 1238 { 1239 NOREF(pInterface); 1240 AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); 1241 PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn; 1235 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1236 PALSAAUDIOSTREAMIN pThisStream = (PALSAAUDIOSTREAMIN)pStream; 1242 1237 1243 1238 LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd)); … … 1248 1243 case PDMAUDIOSTREAMCMD_ENABLE: 1249 1244 case PDMAUDIOSTREAMCMD_RESUME: 1250 rc = drvHostALSAAudioStreamCtl(pThisStr mIn->phPCM, false /* fStop */);1245 rc = drvHostALSAAudioStreamCtl(pThisStream->phPCM, false /* fStop */); 1251 1246 break; 1252 1247 1253 1248 case PDMAUDIOSTREAMCMD_DISABLE: 1254 1249 case PDMAUDIOSTREAMCMD_PAUSE: 1255 rc = drvHostALSAAudioStreamCtl(pThisStr mIn->phPCM, true /* fStop */);1250 rc = drvHostALSAAudioStreamCtl(pThisStream->phPCM, true /* fStop */); 1256 1251 break; 1257 1252 … … 1265 1260 } 1266 1261 1267 static DECLCALLBACK(int) drvHostALSAAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,1268 1262 static int alsaControlStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 1263 PDMAUDIOSTREAMCMD enmStreamCmd) 1269 1264 { 1270 1265 NOREF(pInterface); 1271 AssertPtrReturn(p HstStrmOut, VERR_INVALID_POINTER);1272 PALSAAUDIOSTREAMOUT pThisStr mOut = (PALSAAUDIOSTREAMOUT)pHstStrmOut;1266 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1267 PALSAAUDIOSTREAMOUT pThisStream = (PALSAAUDIOSTREAMOUT)pStream; 1273 1268 1274 1269 LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd)); … … 1279 1274 case PDMAUDIOSTREAMCMD_ENABLE: 1280 1275 case PDMAUDIOSTREAMCMD_RESUME: 1281 rc = drvHostALSAAudioStreamCtl(pThisStr mOut->phPCM, false /* fStop */);1276 rc = drvHostALSAAudioStreamCtl(pThisStream->phPCM, false /* fStop */); 1282 1277 break; 1283 1278 1284 1279 case PDMAUDIOSTREAMCMD_DISABLE: 1285 1280 case PDMAUDIOSTREAMCMD_PAUSE: 1286 rc = drvHostALSAAudioStreamCtl(pThisStr mOut->phPCM, true /* fStop */);1281 rc = drvHostALSAAudioStreamCtl(pThisStream->phPCM, true /* fStop */); 1287 1282 break; 1288 1283 … … 1296 1291 } 1297 1292 1298 static DECLCALLBACK(int) drvHostALSAAudioGetConf (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)1293 static DECLCALLBACK(int) drvHostALSAAudioGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg) 1299 1294 { 1300 1295 NOREF(pInterface); … … 1342 1337 LogRel2(("ALSA: Found %s device: %s\n", pszIOID ? RTStrToLower(pszIOID) : "bidirectional", pszDev)); 1343 1338 1344 /* Special case for PulseAudio. */1339 /* Special case for ALSAAudio. */ 1345 1340 if ( pszDev 1346 1341 && RTStrIStr("pulse", pszDev) != NULL) 1347 LogRel2(("ALSA: PulseAudio plugin in use\n"));1342 LogRel2(("ALSA: ALSAAudio plugin in use\n")); 1348 1343 1349 1344 if (pszIOID) … … 1375 1370 { 1376 1371 NOREF(pInterface); 1372 } 1373 1374 static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostALSAAudioGetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir) 1375 { 1376 AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN); 1377 1378 return PDMAUDIOBACKENDSTS_RUNNING; 1379 } 1380 1381 static DECLCALLBACK(int) drvHostALSAAudioStreamCreate(PPDMIHOSTAUDIO pInterface, 1382 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 1383 { 1384 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1385 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1386 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1387 1388 int rc; 1389 if (pCfg->enmDir == PDMAUDIODIR_IN) 1390 rc = alsaCreateStreamIn(pInterface, pStream, pCfg, pcSamples); 1391 else 1392 rc = alsaCreateStreamOut(pInterface, pStream, pCfg, pcSamples); 1393 1394 LogFlowFunc(("%s: rc=%Rrc\n", pStream->szName, rc)); 1395 return rc; 1396 } 1397 1398 static DECLCALLBACK(int) drvHostALSAAudioStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1399 { 1400 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1401 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1402 1403 int rc; 1404 if (pStream->enmDir == PDMAUDIODIR_IN) 1405 rc = alsaDestroyStreamIn(pInterface, pStream); 1406 else 1407 rc = alsaDestroyStreamOut(pInterface, pStream); 1408 1409 return rc; 1410 } 1411 1412 static DECLCALLBACK(int) drvHostALSAAudioStreamControl(PPDMIHOSTAUDIO pInterface, 1413 PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd) 1414 { 1415 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1416 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1417 1418 Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST); 1419 1420 int rc; 1421 if (pStream->enmDir == PDMAUDIODIR_IN) 1422 rc = alsaControlStreamIn(pInterface, pStream, enmStreamCmd); 1423 else 1424 rc = alsaControlStreamOut(pInterface, pStream, enmStreamCmd); 1425 1426 return rc; 1427 } 1428 1429 static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostALSAAudioStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1430 { 1431 NOREF(pInterface); 1432 NOREF(pStream); 1433 1434 return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED); 1377 1435 } 1378 1436 … … 1382 1440 static DECLCALLBACK(void *) drvHostALSAAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID) 1383 1441 { 1384 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);1385 PDRVHOSTALSAAUDIO 1442 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 1443 PDRVHOSTALSAAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTALSAAUDIO); 1386 1444 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase); 1387 1445 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio); -
trunk/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp
r60306 r61157 17 17 #define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO 18 18 #include <VBox/log.h> 19 #include <VBox/vmm/pdmaudioifs.h> 19 20 20 21 #include "DrvAudio.h" … … 66 67 ******************************************************************************/ 67 68 68 static void drvHostCoreAudioPrintASBDesc(const char *pszDesc, const AudioStreamBasicDescription *pStreamDesc)69 static void coreAudioPrintASBDesc(const char *pszDesc, const AudioStreamBasicDescription *pStreamDesc) 69 70 { 70 71 char pszSampleRate[32]; … … 100 101 } 101 102 102 static void drvHostCoreAudioPCMInfoToASBDesc(PDMPCMPROPS *pPcmProperties, AudioStreamBasicDescription *pStreamDesc)103 static void coreAudioPCMInfoToASBDesc(PDMPCMPROPS *pPcmProperties, AudioStreamBasicDescription *pStreamDesc) 103 104 { 104 105 pStreamDesc->mFormatID = kAudioFormatLinearPCM; … … 114 115 } 115 116 116 static OSStatus drvHostCoreAudioSetFrameBufferSize(AudioDeviceID deviceID, bool fInput, UInt32 cReqSize, UInt32 *pcActSize)117 static OSStatus coreAudioSetFrameBufferSize(AudioDeviceID deviceID, bool fInput, UInt32 cReqSize, UInt32 *pcActSize) 117 118 { 118 119 AudioObjectPropertyScope propScope = fInput … … 187 188 } 188 189 189 DECL_FORCE_INLINE(bool) drvHostCoreAudioIsRunning(AudioDeviceID deviceID)190 DECL_FORCE_INLINE(bool) coreAudioIsRunning(AudioDeviceID deviceID) 190 191 { 191 192 AudioObjectPropertyAddress propAdr = { kAudioDevicePropertyDeviceIsRunning, kAudioObjectPropertyScopeGlobal, … … 200 201 } 201 202 202 static int drvHostCoreAudioCFStringToCString(const CFStringRef pCFString, char **ppszString)203 static int coreAudioCFStringToCString(const CFStringRef pCFString, char **ppszString) 203 204 { 204 205 CFIndex cLen = CFStringGetLength(pCFString) + 1; … … 214 215 } 215 216 216 static AudioDeviceID drvHostCoreAudioDeviceUIDtoID(const char* pszUID)217 static AudioDeviceID coreAudioDeviceUIDtoID(const char* pszUID) 217 218 { 218 219 /* Create a CFString out of our CString. */ … … 263 264 typedef struct COREAUDIOSTREAMOUT 264 265 { 265 /** Host stream out. */ 266 PDMAUDIOHSTSTRMOUT streamOut; 266 /** Host output stream. 267 * Note: Always must come first in this structure! */ 268 PDMAUDIOSTREAM Stream; 267 269 /** Stream description which is default on the device. */ 268 270 AudioStreamBasicDescription deviceFormat; … … 284 286 typedef struct COREAUDIOSTREAMIN 285 287 { 286 /** Host stream in. */ 287 PDMAUDIOHSTSTRMIN streamIn; 288 /** Host input stream. 289 * Note: Always must come first in this structure! */ 290 PDMAUDIOSTREAM Stream; 288 291 /** Stream description which is default on the device. */ 289 292 AudioStreamBasicDescription deviceFormat; … … 312 315 313 316 314 static int coreAudioInitIn(PPDMAUDIO HSTSTRMIN pHstStrmIn, uint32_t *pcSamples);315 static int coreAudioReinitIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIO HSTSTRMIN pHstStrmIn);316 static int coreAudioInitOut(PPDMAUDIO HSTSTRMOUT pHstStrmOut, uint32_t *pcSamples);317 static int coreAudioReinitOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIO HSTSTRMOUT pHstStrmOut);317 static int coreAudioInitIn(PPDMAUDIOSTREAM pStream, uint32_t *pcSamples); 318 static int coreAudioReinitIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream); 319 static int coreAudioInitOut(PPDMAUDIOSTREAM pStream, uint32_t *pcSamples); 320 static int coreAudioReinitOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream); 318 321 static OSStatus coreAudioPlaybackAudioDevicePropertyChanged(AudioObjectID propertyID, UInt32 nAddresses, const AudioObjectPropertyAddress properties[], void *pvUser); 319 322 static OSStatus coreAudioPlaybackCb(void *pvUser, AudioUnitRenderActionFlags *pActionFlags, const AudioTimeStamp *pAudioTS, UInt32 uBusID, UInt32 cFrames, AudioBufferList* pBufData); 320 323 321 static int drvHostCoreAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn, PDMAUDIOSTREAMCMD enmStreamCmd);322 static int drvHostCoreAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd);323 static int drvHostCoreAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn);324 static int drvHostCoreAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut);324 static int coreAudioControlStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd); 325 static int coreAudioControlStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd); 326 static int coreAudioDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream); 327 static int coreAudioDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream); 325 328 326 329 /* Callback for getting notified when the default input/output device has been changed. */ … … 404 407 } 405 408 406 static int coreAudioReinitIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIO HSTSTRMIN pHstStrmIn)409 static int coreAudioReinitIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 407 410 { 408 411 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 409 412 PDRVHOSTCOREAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTCOREAUDIO); 410 413 411 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)p HstStrmIn;412 413 int rc = drvHostCoreAudioFiniIn(pInterface, &pStreamIn->streamIn);414 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream; 415 416 int rc = coreAudioDestroyStreamIn(pInterface, &pStreamIn->Stream); 414 417 if (RT_SUCCESS(rc)) 415 418 { 416 rc = coreAudioInitIn(&pStreamIn-> streamIn, NULL /* pcSamples */);419 rc = coreAudioInitIn(&pStreamIn->Stream, NULL /* pcSamples */); 417 420 if (RT_SUCCESS(rc)) 418 rc = drvHostCoreAudioControlIn(pInterface, &pStreamIn->streamIn, PDMAUDIOSTREAMCMD_ENABLE);421 rc = coreAudioControlStreamIn(pInterface, &pStreamIn->Stream, PDMAUDIOSTREAMCMD_ENABLE); 419 422 } 420 423 … … 425 428 } 426 429 427 static int coreAudioReinitOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIO HSTSTRMOUT pHstStrmOut)430 static int coreAudioReinitOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 428 431 { 429 432 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 430 433 PDRVHOSTCOREAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTCOREAUDIO); 431 434 432 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)p HstStrmOut;433 434 int rc = drvHostCoreAudioFiniOut(pInterface, &pStreamOut->streamOut);435 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream; 436 437 int rc = coreAudioDestroyStreamOut(pInterface, &pStreamOut->Stream); 435 438 if (RT_SUCCESS(rc)) 436 439 { 437 rc = coreAudioInitOut(&pStreamOut-> streamOut, NULL /* pcSamples */);440 rc = coreAudioInitOut(&pStreamOut->Stream, NULL /* pcSamples */); 438 441 if (RT_SUCCESS(rc)) 439 rc = drvHostCoreAudioControlOut(pInterface, &pStreamOut->streamOut, PDMAUDIOSTREAMCMD_ENABLE);442 rc = coreAudioControlStreamOut(pInterface, &pStreamOut->Stream, PDMAUDIOSTREAMCMD_ENABLE); 440 443 } 441 444 … … 545 548 { 546 549 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pvUser; 547 PPDMAUDIO HSTSTRMIN pHstStrmIN = &pStreamIn->streamIn;550 PPDMAUDIOSTREAM pStream = &pStreamIn->Stream; 548 551 549 552 if (ASMAtomicReadU32(&pStreamIn->status) != CA_STATUS_INIT) … … 708 711 709 712 /** @todo Eventually split up this function, as this already is huge! */ 710 static int coreAudioInitIn(PPDMAUDIO HSTSTRMIN pHstStrmIn, uint32_t *pcSamples)713 static int coreAudioInitIn(PPDMAUDIOSTREAM pStream, uint32_t *pcSamples) 711 714 { 712 715 OSStatus err = noErr; 713 716 714 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)p HstStrmIn;717 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream; 715 718 716 719 ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_IN_INIT); … … 743 746 { 744 747 char *pszDevName = NULL; 745 err = drvHostCoreAudioCFStringToCString(strTemp, &pszDevName);748 err = coreAudioCFStringToCString(strTemp, &pszDevName); 746 749 if (err == noErr) 747 750 { … … 754 757 { 755 758 char *pszUID = NULL; 756 err = drvHostCoreAudioCFStringToCString(strTemp, &pszUID);759 err = coreAudioCFStringToCString(strTemp, &pszUID); 757 760 if (err == noErr) 758 761 { … … 783 786 784 787 /* Set the frame buffer size and honor any minimum/maximum restrictions on the device. */ 785 err = drvHostCoreAudioSetFrameBufferSize(pStreamIn->deviceID, true /* fInput */, cFrames, &cFrames);788 err = coreAudioSetFrameBufferSize(pStreamIn->deviceID, true /* fInput */, cFrames, &cFrames); 786 789 if (err != noErr) 787 790 { … … 871 874 872 875 /* Create an AudioStreamBasicDescription based on our required audio settings. */ 873 drvHostCoreAudioPCMInfoToASBDesc(&pStreamIn->streamIn.Props, &pStreamIn->streamFormat);874 875 drvHostCoreAudioPrintASBDesc("CoreAudio: Input device", &pStreamIn->deviceFormat);876 drvHostCoreAudioPrintASBDesc("CoreAudio: Input stream", &pStreamIn->streamFormat);876 coreAudioPCMInfoToASBDesc(&pStreamIn->Stream.Props, &pStreamIn->streamFormat); 877 878 coreAudioPrintASBDesc("CoreAudio: Input device", &pStreamIn->deviceFormat); 879 coreAudioPrintASBDesc("CoreAudio: Input stream", &pStreamIn->streamFormat); 877 880 878 881 /* If the frequency of the device is different from the requested one we … … 1037 1040 /* Create the internal ring buffer. */ 1038 1041 if (RT_SUCCESS(rc)) 1039 rc = RTCircBufCreate(&pStreamIn->pBuf, cSamples << p HstStrmIn->Props.cShift);1042 rc = RTCircBufCreate(&pStreamIn->pBuf, cSamples << pStream->Props.cShift); 1040 1043 if (RT_SUCCESS(rc)) 1041 1044 { … … 1080 1083 1081 1084 /** @todo Eventually split up this function, as this already is huge! */ 1082 static int coreAudioInitOut(PPDMAUDIO HSTSTRMOUT pHstStrmOut, uint32_t *pcSamples)1083 { 1084 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)p HstStrmOut;1085 static int coreAudioInitOut(PPDMAUDIOSTREAM pStream, uint32_t *pcSamples) 1086 { 1087 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream; 1085 1088 1086 1089 ASMAtomicXchgU32(&pStreamOut->status, CA_STATUS_IN_INIT); … … 1115 1118 { 1116 1119 char *pszDevName = NULL; 1117 err = drvHostCoreAudioCFStringToCString(strTemp, &pszDevName);1120 err = coreAudioCFStringToCString(strTemp, &pszDevName); 1118 1121 if (err == noErr) 1119 1122 { … … 1126 1129 { 1127 1130 char *pszUID = NULL; 1128 err = drvHostCoreAudioCFStringToCString(strTemp, &pszUID);1131 err = coreAudioCFStringToCString(strTemp, &pszUID); 1129 1132 if (err == noErr) 1130 1133 { … … 1155 1158 1156 1159 /* Set the frame buffer size and honor any minimum/maximum restrictions on the device. */ 1157 err = drvHostCoreAudioSetFrameBufferSize(pStreamOut->deviceID, false /* fInput */, cFrames, &cFrames);1160 err = coreAudioSetFrameBufferSize(pStreamOut->deviceID, false /* fInput */, cFrames, &cFrames); 1158 1161 if (err != noErr) 1159 1162 { … … 1231 1234 1232 1235 /* Create an AudioStreamBasicDescription based on our required audio settings. */ 1233 drvHostCoreAudioPCMInfoToASBDesc(&pStreamOut->streamOut.Props, &pStreamOut->streamFormat);1234 1235 drvHostCoreAudioPrintASBDesc("CoreAudio: Output device", &pStreamOut->deviceFormat);1236 drvHostCoreAudioPrintASBDesc("CoreAudio: Output format", &pStreamOut->streamFormat);1236 coreAudioPCMInfoToASBDesc(&pStreamOut->Stream.Props, &pStreamOut->streamFormat); 1237 1238 coreAudioPrintASBDesc("CoreAudio: Output device", &pStreamOut->deviceFormat); 1239 coreAudioPrintASBDesc("CoreAudio: Output format", &pStreamOut->streamFormat); 1237 1240 1238 1241 /* Set the new output format description for the stream. */ … … 1315 1318 1316 1319 /* Create the internal ring buffer. */ 1317 rc = RTCircBufCreate(&pStreamOut->pBuf, cSamples << p HstStrmOut->Props.cShift);1320 rc = RTCircBufCreate(&pStreamOut->pBuf, cSamples << pStream->Props.cShift); 1318 1321 if (RT_SUCCESS(rc)) 1319 1322 { … … 1393 1396 { 1394 1397 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pvUser; 1395 PPDMAUDIO HSTSTRMOUT pHstStrmOut = &pStreamOut->streamOut;1398 PPDMAUDIOSTREAM pStream = &pStreamOut->Stream; 1396 1399 1397 1400 if (ASMAtomicReadU32(&pStreamOut->status) != CA_STATUS_INIT) … … 1452 1455 } 1453 1456 1454 static DECLCALLBACK(int) drvHostCoreAudioCapture In(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,1455 1457 static DECLCALLBACK(int) drvHostCoreAudioCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 1458 uint32_t *pcSamplesCaptured) 1456 1459 { 1457 1460 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 1458 1461 PDRVHOSTCOREAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTCOREAUDIO); 1459 1462 1460 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)p HstStrmIn;1463 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream; 1461 1464 1462 1465 size_t csReads = 0; … … 1466 1469 /* Check if the audio device should be reinitialized. If so do it. */ 1467 1470 if (ASMAtomicReadU32(&pStreamIn->status) == CA_STATUS_REINIT) 1468 coreAudioReinitIn(pInterface, &pStreamIn-> streamIn);1471 coreAudioReinitIn(pInterface, &pStreamIn->Stream); 1469 1472 1470 1473 if (ASMAtomicReadU32(&pStreamIn->status) != CA_STATUS_INIT) … … 1480 1483 do 1481 1484 { 1482 size_t cbBuf = AudioMixBufSizeBytes(&p HstStrmIn->MixBuf);1485 size_t cbBuf = AudioMixBufSizeBytes(&pStream->MixBuf); 1483 1486 size_t cbToWrite = RT_MIN(cbBuf, RTCircBufUsed(pStreamIn->pBuf)); 1484 1487 … … 1499 1502 } 1500 1503 1501 rc = AudioMixBufWriteCirc(&p HstStrmIn->MixBuf, puBuf, cbToRead, &cWritten);1504 rc = AudioMixBufWriteCirc(&pStream->MixBuf, puBuf, cbToRead, &cWritten); 1502 1505 if ( RT_FAILURE(rc) 1503 1506 || !cWritten) … … 1507 1510 } 1508 1511 1509 cbWritten = AUDIOMIXBUF_S2B(&p HstStrmIn->MixBuf, cWritten);1512 cbWritten = AUDIOMIXBUF_S2B(&pStream->MixBuf, cWritten); 1510 1513 1511 1514 /* Release the read buffer, so it could be used for new data. */ … … 1524 1527 { 1525 1528 uint32_t cCaptured = 0; 1526 uint32_t cWrittenTotal = AUDIOMIXBUF_B2S(&p HstStrmIn->MixBuf, cbWrittenTotal);1529 uint32_t cWrittenTotal = AUDIOMIXBUF_B2S(&pStream->MixBuf, cbWrittenTotal); 1527 1530 if (cWrittenTotal) 1528 rc = AudioMixBufMixToParent(&p HstStrmIn->MixBuf, cWrittenTotal, &cCaptured);1531 rc = AudioMixBufMixToParent(&pStream->MixBuf, cWrittenTotal, &cCaptured); 1529 1532 1530 1533 LogFlowFunc(("cWrittenTotal=%RU32 (%RU32 bytes), cCaptured=%RU32, rc=%Rrc\n", cWrittenTotal, cbWrittenTotal, cCaptured, rc)); … … 1538 1541 } 1539 1542 1540 static DECLCALLBACK(int) drvHostCoreAudioPlay Out(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,1541 1543 static DECLCALLBACK(int) drvHostCoreAudioPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 1544 uint32_t *pcSamplesPlayed) 1542 1545 { 1543 1546 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 1544 1547 PDRVHOSTCOREAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTCOREAUDIO); 1545 1548 1546 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)p HstStrmOut;1549 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream; 1547 1550 1548 1551 int rc = VINF_SUCCESS; … … 1551 1554 if (ASMAtomicReadU32(&pStreamOut->status) == CA_STATUS_REINIT) 1552 1555 { 1553 rc = coreAudioReinitOut(pInterface, &pStreamOut-> streamOut);1556 rc = coreAudioReinitOut(pInterface, &pStreamOut->Stream); 1554 1557 if (RT_FAILURE(rc)) 1555 1558 return rc; … … 1558 1561 /* Not much else to do here. */ 1559 1562 1560 uint32_t cLive = AudioMixBufAvail(&p HstStrmOut->MixBuf);;1563 uint32_t cLive = AudioMixBufAvail(&pStream->MixBuf);; 1561 1564 if (!cLive) /* Not samples to play? Bail out. */ 1562 1565 { … … 1567 1570 1568 1571 uint32_t cbReadTotal = 0; 1569 uint32_t cAvail = AudioMixBufAvail(&p HstStrmOut->MixBuf);1570 size_t cbAvail = AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, cAvail);1572 uint32_t cAvail = AudioMixBufAvail(&pStream->MixBuf); 1573 size_t cbAvail = AUDIOMIXBUF_S2B(&pStream->MixBuf, cAvail); 1571 1574 size_t cbToRead = RT_MIN(cbAvail, RTCircBufFree(pStreamOut->pBuf)); 1572 1575 LogFlowFunc(("cbToRead=%zu\n", cbToRead)); … … 1588 1591 Assert(cbCopy <= cbToRead); 1589 1592 1590 rc = AudioMixBufReadCirc(&p HstStrmOut->MixBuf,1593 rc = AudioMixBufReadCirc(&pStream->MixBuf, 1591 1594 puBuf, cbCopy, &cRead); 1592 1595 … … 1598 1601 } 1599 1602 1600 cbRead = AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, cRead);1603 cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead); 1601 1604 1602 1605 /* Release the ring buffer, so the read thread could start reading this data. */ … … 1610 1613 if (RT_SUCCESS(rc)) 1611 1614 { 1612 uint32_t cReadTotal = AUDIOMIXBUF_B2S(&p HstStrmOut->MixBuf, cbReadTotal);1615 uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pStream->MixBuf, cbReadTotal); 1613 1616 if (cReadTotal) 1614 AudioMixBufFinish(&p HstStrmOut->MixBuf, cReadTotal);1617 AudioMixBufFinish(&pStream->MixBuf, cReadTotal); 1615 1618 1616 1619 LogFlowFunc(("cReadTotal=%RU32 (%RU32 bytes)\n", cReadTotal, cbReadTotal)); … … 1623 1626 } 1624 1627 1625 static DECLCALLBACK(int) drvHostCoreAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,1626 1627 { 1628 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)p HstStrmOut;1628 static DECLCALLBACK(int) coreAudioControlStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 1629 PDMAUDIOSTREAMCMD enmStreamCmd) 1630 { 1631 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream; 1629 1632 1630 1633 LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd)); … … 1646 1649 { 1647 1650 /* Only start the device if it is actually stopped */ 1648 if (! drvHostCoreAudioIsRunning(pStreamOut->deviceID))1651 if (!coreAudioIsRunning(pStreamOut->deviceID)) 1649 1652 { 1650 1653 err = AudioUnitReset(pStreamOut->audioUnit, kAudioUnitScope_Input, 0); … … 1670 1673 { 1671 1674 /* Only stop the device if it is actually running */ 1672 if ( drvHostCoreAudioIsRunning(pStreamOut->deviceID))1675 if (coreAudioIsRunning(pStreamOut->deviceID)) 1673 1676 { 1674 1677 err = AudioOutputUnitStop(pStreamOut->audioUnit); … … 1699 1702 } 1700 1703 1701 static DECLCALLBACK(int) drvHostCoreAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,1702 1703 { 1704 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)p HstStrmIn;1704 static int coreAudioControlStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 1705 PDMAUDIOSTREAMCMD enmStreamCmd) 1706 { 1707 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream; 1705 1708 1706 1709 LogFlowFunc(("enmStreamCmd=%ld\n", enmStreamCmd)); … … 1722 1725 { 1723 1726 /* Only start the device if it is actually stopped */ 1724 if (! drvHostCoreAudioIsRunning(pStreamIn->deviceID))1727 if (!coreAudioIsRunning(pStreamIn->deviceID)) 1725 1728 { 1726 1729 RTCircBufReset(pStreamIn->pBuf); … … 1746 1749 { 1747 1750 /* Only stop the device if it is actually running */ 1748 if ( drvHostCoreAudioIsRunning(pStreamIn->deviceID))1751 if (coreAudioIsRunning(pStreamIn->deviceID)) 1749 1752 { 1750 1753 err = AudioOutputUnitStop(pStreamIn->audioUnit); … … 1776 1779 } 1777 1780 1778 static DECLCALLBACK(int) drvHostCoreAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)1779 { 1780 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN) p HstStrmIn;1781 static int coreAudioDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1782 { 1783 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN) pStream; 1781 1784 1782 1785 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); … … 1794 1797 OSStatus err = noErr; 1795 1798 1796 int rc = drvHostCoreAudioControlIn(pInterface, &pStreamIn->streamIn, PDMAUDIOSTREAMCMD_DISABLE);1799 int rc = coreAudioControlStreamIn(pInterface, &pStreamIn->Stream, PDMAUDIOSTREAMCMD_DISABLE); 1797 1800 if (RT_SUCCESS(rc)) 1798 1801 { … … 1878 1881 } 1879 1882 1880 static DECLCALLBACK(int) drvHostCoreAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)1883 static int coreAudioDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1881 1884 { 1882 1885 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 1883 1886 PDRVHOSTCOREAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTCOREAUDIO); 1884 1887 1885 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)p HstStrmOut;1888 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream; 1886 1889 1887 1890 LogFlowFuncEnter(); … … 1894 1897 } 1895 1898 1896 int rc = drvHostCoreAudioControlOut(pInterface, &pStreamOut->streamOut, PDMAUDIOSTREAMCMD_DISABLE);1899 int rc = coreAudioControlStreamOut(pInterface, &pStreamOut->Stream, PDMAUDIOSTREAMCMD_DISABLE); 1897 1900 if (RT_SUCCESS(rc)) 1898 1901 { … … 1965 1968 } 1966 1969 1967 static DECLCALLBACK(int) drvHostCoreAudioInitIn(PPDMIHOSTAUDIO pInterface, 1968 PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg, 1969 PDMAUDIORECSOURCE enmRecSource, 1970 uint32_t *pcSamples) 1971 { 1972 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pHstStrmIn; 1970 static int coreAudioCreateStreamIn(PPDMIHOSTAUDIO pInterface, 1971 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 1972 { 1973 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream; 1973 1974 1974 1975 LogFlowFunc(("enmRecSource=%ld\n", enmRecSource)); … … 1987 1988 1988 1989 /* Initialize the hardware info section with the audio settings */ 1989 int rc = DrvAudioStreamCfgToProps(pCfg, &pStreamIn-> streamIn.Props);1990 int rc = DrvAudioStreamCfgToProps(pCfg, &pStreamIn->Stream.Props); 1990 1991 if (RT_SUCCESS(rc)) 1991 1992 { … … 2002 2003 } 2003 2004 #endif 2004 rc = coreAudioInitIn(&pStreamIn-> streamIn, pcSamples);2005 rc = coreAudioInitIn(&pStreamIn->Stream, pcSamples); 2005 2006 } 2006 2007 … … 2028 2029 } 2029 2030 2030 static DECLCALLBACK(int) drvHostCoreAudioInitOut(PPDMIHOSTAUDIO pInterface,2031 PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,2032 2033 { 2034 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)p HstStrmOut;2031 static int coreAudioCreateStreamOut(PPDMIHOSTAUDIO pInterface, 2032 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, 2033 uint32_t *pcSamples) 2034 { 2035 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream; 2035 2036 2036 2037 LogFlowFuncEnter(); … … 2045 2046 2046 2047 /* Initialize the hardware info section with the audio settings */ 2047 int rc = DrvAudioStreamCfgToProps(pCfg, &pStreamOut-> streamOut.Props);2048 int rc = DrvAudioStreamCfgToProps(pCfg, &pStreamOut->Stream.Props); 2048 2049 if (RT_SUCCESS(rc)) 2049 2050 { … … 2062 2063 } 2063 2064 #endif 2064 rc = coreAudioInitOut(p HstStrmOut, pcSamples);2065 rc = coreAudioInitOut(pStream, pcSamples); 2065 2066 } 2066 2067 … … 2088 2089 } 2089 2090 2090 static DECLCALLBACK(bool) drvHostCoreAudioIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir) 2091 { 2092 NOREF(pInterface); 2093 NOREF(enmDir); 2094 return true; /* Always all enabled. */ 2095 } 2096 2097 static DECLCALLBACK(int) drvHostCoreAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg) 2091 static DECLCALLBACK(int) drvHostCoreAudioGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg) 2098 2092 { 2099 2093 NOREF(pInterface); … … 2112 2106 2113 2107 return VINF_SUCCESS; 2108 } 2109 2110 static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostCoreAudioGetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir) 2111 { 2112 AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN); 2113 2114 return PDMAUDIOBACKENDSTS_RUNNING; 2115 } 2116 2117 static DECLCALLBACK(int) drvHostCoreAudioStreamCreate(PPDMIHOSTAUDIO pInterface, 2118 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 2119 { 2120 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 2121 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 2122 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 2123 2124 int rc; 2125 if (pCfg->enmDir == PDMAUDIODIR_IN) 2126 rc = coreAudioCreateStreamIn(pInterface, pStream, pCfg, pcSamples); 2127 else 2128 rc = coreAudioCreateStreamOut(pInterface, pStream, pCfg, pcSamples); 2129 2130 LogFlowFunc(("%s: rc=%Rrc\n", pStream->szName, rc)); 2131 return rc; 2132 } 2133 2134 static DECLCALLBACK(int) drvHostCoreAudioStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 2135 { 2136 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 2137 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 2138 2139 int rc; 2140 if (pStream->enmDir == PDMAUDIODIR_IN) 2141 rc = coreAudioDestroyStreamIn(pInterface, pStream); 2142 else 2143 rc = coreAudioDestroyStreamOut(pInterface, pStream); 2144 2145 return rc; 2146 } 2147 2148 static DECLCALLBACK(int) drvHostCoreAudioStreamControl(PPDMIHOSTAUDIO pInterface, 2149 PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd) 2150 { 2151 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 2152 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 2153 2154 Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST); 2155 2156 int rc; 2157 if (pStream->enmDir == PDMAUDIODIR_IN) 2158 rc = coreAudioControlStreamIn(pInterface, pStream, enmStreamCmd); 2159 else 2160 rc = coreAudioControlStreamOut(pInterface, pStream, enmStreamCmd); 2161 2162 return rc; 2163 } 2164 2165 static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostCoreAudioStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 2166 { 2167 NOREF(pInterface); 2168 NOREF(pStream); 2169 2170 return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED); 2114 2171 } 2115 2172 -
trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp
r60925 r61157 90 90 typedef struct DSOUNDSTREAMOUT 91 91 { 92 PDMAUDIOHSTSTRMOUT strmOut; /* Always must come first! */ 92 /** Associated host output stream. 93 * Note: Always must come first! */ 94 PDMAUDIOSTREAM Stream; 93 95 LPDIRECTSOUND8 pDS; /** @todo Move this out of this structure! Not required per-stream (e.g. for multi-channel). */ 94 96 LPDIRECTSOUNDBUFFER8 pDSB; … … 102 104 typedef struct DSOUNDSTREAMIN 103 105 { 104 PDMAUDIOHSTSTRMIN strmIn; /* Always must come first! */ 106 /** Associated host input stream. 107 * Note: Always must come first! */ 108 PDMAUDIOSTREAM Stream; 105 109 LPDIRECTSOUNDCAPTURE8 pDSC; 106 110 LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB; 107 111 DWORD csCaptureReadPos; 108 112 DWORD csCaptureBufferSize; 109 HRESULT hrLastCapture In;113 HRESULT hrLastCapture; 110 114 PDMAUDIORECSOURCE enmRecSource; 111 115 bool fEnabled; … … 249 253 250 254 static int dsoundGetPosOut(PDRVHOSTDSOUND pThis, 251 PDSOUNDSTREAMOUT pDSoundStr mOut, DWORD *pdwBuffer, DWORD *pdwFree, DWORD *pdwPlayPos)252 { 253 AssertPtrReturn(pThis, 254 AssertPtrReturn(pDSoundStr mOut, VERR_INVALID_POINTER);255 256 LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStr mOut->pDSB;255 PDSOUNDSTREAMOUT pDSoundStream, DWORD *pdwBuffer, DWORD *pdwFree, DWORD *pdwPlayPos) 256 { 257 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 258 AssertPtrReturn(pDSoundStream, VERR_INVALID_POINTER); 259 260 LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStream->pDSB; 257 261 if (!pDSB) 258 262 return VERR_INVALID_POINTER; 259 263 260 DWORD cbBuffer = AUDIOMIXBUF_S2B(&pDSoundStr mOut->strmOut.MixBuf, pDSoundStrmOut->csPlaybackBufferSize);264 DWORD cbBuffer = AUDIOMIXBUF_S2B(&pDSoundStream->Stream.MixBuf, pDSoundStream->csPlaybackBufferSize); 261 265 262 266 /* Get the current play position which is used for calculating the free space in the buffer. */ … … 295 299 296 300 if (pdwFree) 297 *pdwFree = cbBuffer - dsoundRingDistance(pDSoundStr mOut->cbPlayWritePos, cbPlayPos, cbBuffer);301 *pdwFree = cbBuffer - dsoundRingDistance(pDSoundStream->cbPlayWritePos, cbPlayPos, cbBuffer); 298 302 299 303 if (pdwPlayPos) … … 465 469 */ 466 470 467 static void directSoundPlayInterfaceRelease(PDSOUNDSTREAMOUT pDSoundStr mOut)468 { 469 if (pDSoundStr mOut->pDS)470 { 471 IDirectSound8_Release(pDSoundStr mOut->pDS);472 pDSoundStr mOut->pDS = NULL;473 } 474 } 475 476 static HRESULT directSoundPlayInterfaceCreate(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStr mOut)477 { 478 if (pDSoundStr mOut->pDS != NULL)471 static void directSoundPlayInterfaceRelease(PDSOUNDSTREAMOUT pDSoundStream) 472 { 473 if (pDSoundStream->pDS) 474 { 475 IDirectSound8_Release(pDSoundStream->pDS); 476 pDSoundStream->pDS = NULL; 477 } 478 } 479 480 static HRESULT directSoundPlayInterfaceCreate(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStream) 481 { 482 if (pDSoundStream->pDS != NULL) 479 483 { 480 484 DSLOG(("DSound: DirectSound instance already exists\n")); … … 483 487 484 488 HRESULT hr = CoCreateInstance(CLSID_DirectSound8, NULL, CLSCTX_ALL, 485 IID_IDirectSound8, (void **)&pDSoundStr mOut->pDS);489 IID_IDirectSound8, (void **)&pDSoundStream->pDS); 486 490 if (FAILED(hr)) 487 491 { … … 490 494 else 491 495 { 492 hr = IDirectSound8_Initialize(pDSoundStr mOut->pDS, pThis->cfg.pGuidPlay);496 hr = IDirectSound8_Initialize(pDSoundStream->pDS, pThis->cfg.pGuidPlay); 493 497 if (SUCCEEDED(hr)) 494 498 { 495 499 HWND hWnd = GetDesktopWindow(); 496 hr = IDirectSound8_SetCooperativeLevel(pDSoundStr mOut->pDS, hWnd, DSSCL_PRIORITY);500 hr = IDirectSound8_SetCooperativeLevel(pDSoundStream->pDS, hWnd, DSSCL_PRIORITY); 497 501 if (FAILED(hr)) 498 502 DSLOGREL(("DSound: Setting cooperative level for window %p failed with %Rhrc\n", hWnd, hr)); … … 506 510 DSLOGREL(("DSound: DirectSound playback initialization failed with %Rhrc\n", hr)); 507 511 508 directSoundPlayInterfaceRelease(pDSoundStr mOut);512 directSoundPlayInterfaceRelease(pDSoundStream); 509 513 } 510 514 } … … 513 517 } 514 518 515 static HRESULT directSoundPlayClose(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStr mOut)519 static HRESULT directSoundPlayClose(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStream) 516 520 { 517 521 AssertPtrReturn(pThis, E_POINTER); 518 AssertPtrReturn(pDSoundStr mOut, E_POINTER);519 520 DSLOG(("DSound: Closing playback stream %p, buffer %p\n", pDSoundStr mOut, pDSoundStrmOut->pDSB));522 AssertPtrReturn(pDSoundStream, E_POINTER); 523 524 DSLOG(("DSound: Closing playback stream %p, buffer %p\n", pDSoundStream, pDSoundStream->pDSB)); 521 525 522 526 HRESULT hr = S_OK; 523 527 524 if (pDSoundStr mOut->pDSB)525 { 526 hr = IDirectSoundBuffer8_Stop(pDSoundStr mOut->pDSB);528 if (pDSoundStream->pDSB) 529 { 530 hr = IDirectSoundBuffer8_Stop(pDSoundStream->pDSB); 527 531 if (SUCCEEDED(hr)) 528 532 { … … 536 540 pThis->cEvents--; 537 541 538 pThis->pDSStr mOut= NULL;542 pThis->pDSStream = NULL; 539 543 } 540 544 … … 542 546 AssertRC(rc2); 543 547 #endif 544 IDirectSoundBuffer8_Release(pDSoundStr mOut->pDSB);545 pDSoundStr mOut->pDSB = NULL;548 IDirectSoundBuffer8_Release(pDSoundStream->pDSB); 549 pDSoundStream->pDSB = NULL; 546 550 } 547 551 else 548 DSLOGREL(("DSound: Stop playback stream %p when closing %Rhrc\n", pDSoundStr mOut, hr));552 DSLOGREL(("DSound: Stop playback stream %p when closing %Rhrc\n", pDSoundStream, hr)); 549 553 } 550 554 551 555 if (SUCCEEDED(hr)) 552 directSoundPlayInterfaceRelease(pDSoundStr mOut);556 directSoundPlayInterfaceRelease(pDSoundStream); 553 557 554 558 return hr; 555 559 } 556 560 557 static HRESULT directSoundPlayOpen(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStr mOut)561 static HRESULT directSoundPlayOpen(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStream) 558 562 { 559 563 AssertPtrReturn(pThis, E_POINTER); 560 AssertPtrReturn(pDSoundStr mOut, E_POINTER);561 562 DSLOG(("DSound: pDSoundStr mOut=%p, cbBufferOut=%ld, uHz=%RU32, cChannels=%RU8, cBits=%RU8, fSigned=%RTbool\n",563 pDSoundStr mOut,564 AssertPtrReturn(pDSoundStream, E_POINTER); 565 566 DSLOG(("DSound: pDSoundStream=%p, cbBufferOut=%ld, uHz=%RU32, cChannels=%RU8, cBits=%RU8, fSigned=%RTbool\n", 567 pDSoundStream, 564 568 pThis->cfg.cbBufferOut, 565 pDSoundStr mOut->strmOut.Props.uHz,566 pDSoundStr mOut->strmOut.Props.cChannels,567 pDSoundStr mOut->strmOut.Props.cBits,568 pDSoundStr mOut->strmOut.Props.fSigned));569 570 if (pDSoundStr mOut->pDSB != NULL)569 pDSoundStream->Stream.Props.uHz, 570 pDSoundStream->Stream.Props.cChannels, 571 pDSoundStream->Stream.Props.cBits, 572 pDSoundStream->Stream.Props.fSigned)); 573 574 if (pDSoundStream->pDSB != NULL) 571 575 { 572 576 /* Should not happen but be forgiving. */ 573 577 DSLOGREL(("DSound: Playback buffer already exists\n")); 574 directSoundPlayClose(pThis, pDSoundStr mOut);578 directSoundPlayClose(pThis, pDSoundStream); 575 579 } 576 580 577 581 WAVEFORMATEX wfx; 578 int rc = dsoundWaveFmtFromCfg(&pDSoundStr mOut->streamCfg, &wfx);582 int rc = dsoundWaveFmtFromCfg(&pDSoundStream->streamCfg, &wfx); 579 583 if (RT_FAILURE(rc)) 580 584 return E_INVALIDARG; 581 585 582 HRESULT hr = directSoundPlayInterfaceCreate(pThis, pDSoundStr mOut);586 HRESULT hr = directSoundPlayInterfaceCreate(pThis, pDSoundStream); 583 587 if (FAILED(hr)) 584 588 return hr; … … 610 614 bd.dwBufferBytes = pThis->cfg.cbBufferOut; 611 615 612 hr = IDirectSound8_CreateSoundBuffer(pDSoundStr mOut->pDS, &bd, &pDSB, NULL);616 hr = IDirectSound8_CreateSoundBuffer(pDSoundStream->pDS, &bd, &pDSB, NULL); 613 617 if (FAILED(hr)) 614 618 { … … 618 622 619 623 /* "Upgrade" to IDirectSoundBuffer8 interface. */ 620 hr = IDirectSoundBuffer_QueryInterface(pDSB, IID_IDirectSoundBuffer8, (LPVOID *)&pDSoundStr mOut->pDSB);624 hr = IDirectSoundBuffer_QueryInterface(pDSB, IID_IDirectSoundBuffer8, (LPVOID *)&pDSoundStream->pDSB); 621 625 IDirectSoundBuffer_Release(pDSB); 622 626 if (FAILED(hr)) … … 629 633 * Query the actual parameters. 630 634 */ 631 hr = IDirectSoundBuffer8_GetFormat(pDSoundStr mOut->pDSB, &wfx, sizeof(wfx), NULL);635 hr = IDirectSoundBuffer8_GetFormat(pDSoundStream->pDSB, &wfx, sizeof(wfx), NULL); 632 636 if (FAILED(hr)) 633 637 { … … 639 643 RT_ZERO(bc); 640 644 bc.dwSize = sizeof(bc); 641 hr = IDirectSoundBuffer8_GetCaps(pDSoundStr mOut->pDSB, &bc);645 hr = IDirectSoundBuffer8_GetCaps(pDSoundStream->pDSB, &bc); 642 646 if (FAILED(hr)) 643 647 { … … 666 670 wfx.cbSize)); 667 671 668 if (bc.dwBufferBytes & pDSoundStr mOut->strmOut.Props.uAlign)672 if (bc.dwBufferBytes & pDSoundStream->Stream.Props.uAlign) 669 673 DSLOGREL(("DSound: Playback capabilities returned misaligned buffer: size %RU32, alignment %RU32\n", 670 bc.dwBufferBytes, pDSoundStr mOut->strmOut.Props.uAlign + 1));674 bc.dwBufferBytes, pDSoundStream->Stream.Props.uAlign + 1)); 671 675 672 676 if (bc.dwBufferBytes != pThis->cfg.cbBufferOut) … … 679 683 * playback buffer position. 680 684 */ 681 pDSoundStr mOut->csPlaybackBufferSize = bc.dwBufferBytes >> pDSoundStrmOut->strmOut.Props.cShift;682 DSLOG(("DSound: csPlaybackBufferSize=%RU32\n", pDSoundStr mOut->csPlaybackBufferSize));685 pDSoundStream->csPlaybackBufferSize = bc.dwBufferBytes >> pDSoundStream->Stream.Props.cShift; 686 DSLOG(("DSound: csPlaybackBufferSize=%RU32\n", pDSoundStream->csPlaybackBufferSize)); 683 687 684 688 #ifdef VBOX_WITH_AUDIO_CALLBACKS … … 697 701 698 702 LPDIRECTSOUNDNOTIFY8 pNotify; 699 hr = IDirectSoundNotify_QueryInterface(pDSoundStr mOut->pDSB, IID_IDirectSoundNotify8, (LPVOID *)&pNotify);703 hr = IDirectSoundNotify_QueryInterface(pDSoundStream->pDSB, IID_IDirectSoundNotify8, (LPVOID *)&pNotify); 700 704 if (SUCCEEDED(hr)) 701 705 { … … 717 721 break; 718 722 719 pThis->pDSStr mOut = pDSoundStrmOut;723 pThis->pDSStreamOut = pDSoundStream; 720 724 721 725 Assert(pThis->cEvents < VBOX_DSOUND_MAX_EVENTS); … … 726 730 727 731 /* Trigger the just installed output notification. */ 728 hr = IDirectSoundBuffer8_Play(pDSoundStr mOut->pDSB, 0, 0, 0);732 hr = IDirectSoundBuffer8_Play(pDSoundStream->pDSB, 0, 0, 0); 729 733 730 734 #endif /* VBOX_WITH_AUDIO_CALLBACKS */ … … 733 737 734 738 if (FAILED(hr)) 735 directSoundPlayClose(pThis, pDSoundStr mOut);739 directSoundPlayClose(pThis, pDSoundStream); 736 740 737 741 return hr; 738 742 } 739 743 740 static void dsoundPlayClearSamples(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStr mOut)741 { 742 AssertPtrReturnVoid(pDSoundStr mOut);743 744 PPDMAUDIO HSTSTRMOUT pStrmOut = &pDSoundStrmOut->strmOut;744 static void dsoundPlayClearSamples(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStream) 745 { 746 AssertPtrReturnVoid(pDSoundStream); 747 748 PPDMAUDIOSTREAM pStream = &pDSoundStream->Stream; 745 749 746 750 LPVOID pv1, pv2; 747 751 DWORD cb1, cb2; 748 HRESULT hr = directSoundPlayLock(pThis, pDSoundStr mOut->pDSB, &pDSoundStrmOut->strmOut.Props,749 0 /* dwOffset */, AUDIOMIXBUF_S2B(&pStr mOut->MixBuf, pDSoundStrmOut->csPlaybackBufferSize),752 HRESULT hr = directSoundPlayLock(pThis, pDSoundStream->pDSB, &pDSoundStream->Stream.Props, 753 0 /* dwOffset */, AUDIOMIXBUF_S2B(&pStream->MixBuf, pDSoundStream->csPlaybackBufferSize), 750 754 &pv1, &pv2, &cb1, &cb2, DSBLOCK_ENTIREBUFFER); 751 755 if (SUCCEEDED(hr)) 752 756 { 753 DWORD len1 = AUDIOMIXBUF_B2S(&pStr mOut->MixBuf, cb1);754 DWORD len2 = AUDIOMIXBUF_B2S(&pStr mOut->MixBuf, cb2);757 DWORD len1 = AUDIOMIXBUF_B2S(&pStream->MixBuf, cb1); 758 DWORD len2 = AUDIOMIXBUF_B2S(&pStream->MixBuf, cb2); 755 759 756 760 if (pv1 && len1) 757 DrvAudioClearBuf(&pDSoundStr mOut->strmOut.Props, pv1, cb1, len1);761 DrvAudioClearBuf(&pDSoundStream->Stream.Props, pv1, cb1, len1); 758 762 759 763 if (pv2 && len2) 760 DrvAudioClearBuf(&pDSoundStr mOut->strmOut.Props, pv2, cb2, len2);761 762 directSoundPlayUnlock(pThis, pDSoundStr mOut->pDSB, pv1, pv2, cb1, cb2);764 DrvAudioClearBuf(&pDSoundStream->Stream.Props, pv2, cb2, len2); 765 766 directSoundPlayUnlock(pThis, pDSoundStream->pDSB, pv1, pv2, cb1, cb2); 763 767 } 764 768 } … … 798 802 } 799 803 800 static HRESULT directSoundPlayStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStr mOut)801 { 802 AssertPtrReturn(pThis, 803 AssertPtrReturn(pDSoundStr mOut, E_POINTER);804 static HRESULT directSoundPlayStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStream) 805 { 806 AssertPtrReturn(pThis, E_POINTER); 807 AssertPtrReturn(pDSoundStream, E_POINTER); 804 808 805 809 HRESULT hr; 806 810 807 if (pDSoundStr mOut->pDSB != NULL)811 if (pDSoundStream->pDSB != NULL) 808 812 { 809 813 DSLOG(("DSound: Stopping playback\n")); 810 814 811 HRESULT hr2 = IDirectSoundBuffer8_Stop(pDSoundStr mOut->pDSB);815 HRESULT hr2 = IDirectSoundBuffer8_Stop(pDSoundStream->pDSB); 812 816 if (FAILED(hr2)) 813 817 { 814 hr2 = directSoundPlayRestore(pThis, pDSoundStr mOut->pDSB);818 hr2 = directSoundPlayRestore(pThis, pDSoundStream->pDSB); 815 819 if (FAILED(hr2)) 816 hr2 = IDirectSoundBuffer8_Stop(pDSoundStr mOut->pDSB);820 hr2 = IDirectSoundBuffer8_Stop(pDSoundStream->pDSB); 817 821 } 818 822 … … 827 831 if (SUCCEEDED(hr)) 828 832 { 829 dsoundPlayClearSamples(pThis, pDSoundStr mOut);830 pDSoundStr mOut->fEnabled = false;833 dsoundPlayClearSamples(pThis, pDSoundStream); 834 pDSoundStream->fEnabled = false; 831 835 } 832 836 else … … 836 840 } 837 841 838 static HRESULT directSoundPlayStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStr mOut)839 { 840 AssertPtrReturn(pThis, 841 AssertPtrReturn(pDSoundStr mOut, E_POINTER);842 static HRESULT directSoundPlayStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMOUT pDSoundStream) 843 { 844 AssertPtrReturn(pThis, E_POINTER); 845 AssertPtrReturn(pDSoundStream, E_POINTER); 842 846 843 847 HRESULT hr; 844 if (pDSoundStr mOut->pDSB != NULL)848 if (pDSoundStream->pDSB != NULL) 845 849 { 846 850 DWORD dwStatus; 847 hr = directSoundPlayGetStatus(pThis, pDSoundStr mOut->pDSB, &dwStatus);851 hr = directSoundPlayGetStatus(pThis, pDSoundStream->pDSB, &dwStatus); 848 852 if (SUCCEEDED(hr)) 849 853 { … … 854 858 else 855 859 { 856 dsoundPlayClearSamples(pThis, pDSoundStr mOut);857 858 pDSoundStr mOut->fRestartPlayback = true;859 pDSoundStr mOut->fEnabled = true;860 dsoundPlayClearSamples(pThis, pDSoundStream); 861 862 pDSoundStream->fRestartPlayback = true; 863 pDSoundStream->fEnabled = true; 860 864 861 865 DSLOG(("DSound: Playback started\n")); 862 866 863 867 /* 864 * The actual IDirectSoundBuffer8_Play call will be made in drvHostDSoundPlay Out,868 * The actual IDirectSoundBuffer8_Play call will be made in drvHostDSoundPlay, 865 869 * because it is necessary to put some samples into the buffer first. 866 870 */ … … 881 885 */ 882 886 883 static LPCGUID dsoundCaptureSelectDevice(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStr mIn)887 static LPCGUID dsoundCaptureSelectDevice(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStream) 884 888 { 885 889 AssertPtrReturn(pThis, NULL); 886 AssertPtrReturn(pDSoundStr mIn, NULL);890 AssertPtrReturn(pDSoundStream, NULL); 887 891 888 892 LPCGUID pGUID = pThis->cfg.pGuidCapture; … … 892 896 PDSOUNDDEV pDev = NULL; 893 897 894 switch (pDSoundStr mIn->enmRecSource)898 switch (pDSoundStream->enmRecSource) 895 899 { 896 900 case PDMAUDIORECSOURCE_MIC: … … 916 920 { 917 921 DSLOG(("DSound: Guest \"%s\" is using host \"%s\"\n", 918 DrvAudRecSrcToStr(pDSoundStr mIn->enmRecSource), pDev->pszName));922 DrvAudRecSrcToStr(pDSoundStream->enmRecSource), pDev->pszName)); 919 923 920 924 pGUID = &pDev->Guid; … … 925 929 /* This always has to be in the release log. */ 926 930 LogRel(("DSound: Guest \"%s\" is using host device with GUID: %s\n", 927 DrvAudRecSrcToStr(pDSoundStr mIn->enmRecSource), pszGUID? pszGUID: "{?}"));931 DrvAudRecSrcToStr(pDSoundStream->enmRecSource), pszGUID? pszGUID: "{?}")); 928 932 RTStrFree(pszGUID); 929 933 … … 931 935 } 932 936 933 static void directSoundCaptureInterfaceRelease(PDSOUNDSTREAMIN pDSoundStr mIn)934 { 935 if (pDSoundStr mIn->pDSC)937 static void directSoundCaptureInterfaceRelease(PDSOUNDSTREAMIN pDSoundStream) 938 { 939 if (pDSoundStream->pDSC) 936 940 { 937 941 LogFlowFuncEnter(); 938 IDirectSoundCapture_Release(pDSoundStr mIn->pDSC);939 pDSoundStr mIn->pDSC = NULL;940 } 941 } 942 943 static HRESULT directSoundCaptureInterfaceCreate(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStr mIn)944 { 945 if (pDSoundStr mIn->pDSC != NULL)942 IDirectSoundCapture_Release(pDSoundStream->pDSC); 943 pDSoundStream->pDSC = NULL; 944 } 945 } 946 947 static HRESULT directSoundCaptureInterfaceCreate(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStream) 948 { 949 if (pDSoundStream->pDSC != NULL) 946 950 { 947 951 DSLOG(("DSound: DirectSoundCapture instance already exists\n")); … … 950 954 951 955 HRESULT hr = CoCreateInstance(CLSID_DirectSoundCapture8, NULL, CLSCTX_ALL, 952 IID_IDirectSoundCapture8, (void **)&pDSoundStr mIn->pDSC);956 IID_IDirectSoundCapture8, (void **)&pDSoundStream->pDSC); 953 957 if (FAILED(hr)) 954 958 { … … 957 961 else 958 962 { 959 LPCGUID pGUID = dsoundCaptureSelectDevice(pThis, pDSoundStr mIn);960 hr = IDirectSoundCapture_Initialize(pDSoundStr mIn->pDSC, pGUID);963 LPCGUID pGUID = dsoundCaptureSelectDevice(pThis, pDSoundStream); 964 hr = IDirectSoundCapture_Initialize(pDSoundStream->pDSC, pGUID); 961 965 if (FAILED(hr)) 962 966 { … … 966 970 DSLOGREL(("DSound: Initializing capturing device failed with %Rhrc\n", hr)); 967 971 968 directSoundCaptureInterfaceRelease(pDSoundStr mIn);972 directSoundCaptureInterfaceRelease(pDSoundStream); 969 973 } 970 974 } … … 974 978 } 975 979 976 static HRESULT directSoundCaptureClose(PDSOUNDSTREAMIN pDSoundStr mIn)977 { 978 AssertPtrReturn(pDSoundStr mIn, E_POINTER);979 980 DSLOG(("DSound: pDSoundStr mIn=%p, pDSCB=%p\n", pDSoundStrmIn, pDSoundStrmIn->pDSCB));980 static HRESULT directSoundCaptureClose(PDSOUNDSTREAMIN pDSoundStream) 981 { 982 AssertPtrReturn(pDSoundStream, E_POINTER); 983 984 DSLOG(("DSound: pDSoundStream=%p, pDSCB=%p\n", pDSoundStream, pDSoundStream->pDSCB)); 981 985 982 986 HRESULT hr = S_OK; 983 987 984 if (pDSoundStr mIn->pDSCB)985 { 986 hr = IDirectSoundCaptureBuffer_Stop(pDSoundStr mIn->pDSCB);988 if (pDSoundStream->pDSCB) 989 { 990 hr = IDirectSoundCaptureBuffer_Stop(pDSoundStream->pDSCB); 987 991 if (SUCCEEDED(hr)) 988 992 { 989 IDirectSoundCaptureBuffer8_Release(pDSoundStr mIn->pDSCB);990 pDSoundStr mIn->pDSCB = NULL;993 IDirectSoundCaptureBuffer8_Release(pDSoundStream->pDSCB); 994 pDSoundStream->pDSCB = NULL; 991 995 } 992 996 else … … 995 999 996 1000 if (SUCCEEDED(hr)) 997 directSoundCaptureInterfaceRelease(pDSoundStr mIn);1001 directSoundCaptureInterfaceRelease(pDSoundStream); 998 1002 999 1003 LogFlowFunc(("Returning %Rhrc\n", hr)); … … 1001 1005 } 1002 1006 1003 static HRESULT directSoundCaptureOpen(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStr mIn)1007 static HRESULT directSoundCaptureOpen(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStream) 1004 1008 { 1005 1009 AssertPtrReturn(pThis, E_POINTER); 1006 AssertPtrReturn(pDSoundStr mIn, E_POINTER);1007 1008 DSLOG(("DSound: pDSoundStr mIn=%p, cbBufferIn=%ld, uHz=%RU32, cChannels=%RU8, cBits=%RU8, fSigned=%RTbool\n",1009 pDSoundStr mIn,1010 AssertPtrReturn(pDSoundStream, E_POINTER); 1011 1012 DSLOG(("DSound: pDSoundStream=%p, cbBufferIn=%ld, uHz=%RU32, cChannels=%RU8, cBits=%RU8, fSigned=%RTbool\n", 1013 pDSoundStream, 1010 1014 pThis->cfg.cbBufferIn, 1011 pDSoundStr mIn->strmIn.Props.uHz,1012 pDSoundStr mIn->strmIn.Props.cChannels,1013 pDSoundStr mIn->strmIn.Props.cBits,1014 pDSoundStr mIn->strmIn.Props.fSigned));1015 1016 if (pDSoundStr mIn->pDSCB != NULL)1015 pDSoundStream->Stream.Props.uHz, 1016 pDSoundStream->Stream.Props.cChannels, 1017 pDSoundStream->Stream.Props.cBits, 1018 pDSoundStream->Stream.Props.fSigned)); 1019 1020 if (pDSoundStream->pDSCB != NULL) 1017 1021 { 1018 1022 /* Should not happen but be forgiving. */ 1019 1023 DSLOGREL(("DSound: DirectSoundCaptureBuffer already exists\n")); 1020 directSoundCaptureClose(pDSoundStr mIn);1024 directSoundCaptureClose(pDSoundStream); 1021 1025 } 1022 1026 1023 1027 WAVEFORMATEX wfx; 1024 int rc = dsoundWaveFmtFromCfg(&pDSoundStr mIn->streamCfg, &wfx);1028 int rc = dsoundWaveFmtFromCfg(&pDSoundStream->streamCfg, &wfx); 1025 1029 if (RT_FAILURE(rc)) 1026 1030 return E_INVALIDARG; 1027 1031 1028 HRESULT hr = directSoundCaptureInterfaceCreate(pThis, pDSoundStr mIn);1032 HRESULT hr = directSoundCaptureInterfaceCreate(pThis, pDSoundStream); 1029 1033 if (FAILED(hr)) 1030 1034 return hr; … … 1038 1042 bd.lpwfxFormat = &wfx; 1039 1043 bd.dwBufferBytes = pThis->cfg.cbBufferIn; 1040 hr = IDirectSoundCapture_CreateCaptureBuffer(pDSoundStr mIn->pDSC,1044 hr = IDirectSoundCapture_CreateCaptureBuffer(pDSoundStream->pDSC, 1041 1045 &bd, &pDSCB, NULL); 1042 1046 if (FAILED(hr)) … … 1051 1055 } 1052 1056 1053 hr = IDirectSoundCaptureBuffer_QueryInterface(pDSCB, IID_IDirectSoundCaptureBuffer8, (void **)&pDSoundStr mIn->pDSCB);1057 hr = IDirectSoundCaptureBuffer_QueryInterface(pDSCB, IID_IDirectSoundCaptureBuffer8, (void **)&pDSoundStream->pDSCB); 1054 1058 IDirectSoundCaptureBuffer_Release(pDSCB); 1055 1059 if (FAILED(hr)) … … 1063 1067 */ 1064 1068 DWORD cbReadPos = 0; 1065 hr = IDirectSoundCaptureBuffer8_GetCurrentPosition(pDSoundStr mIn->pDSCB, NULL, &cbReadPos);1069 hr = IDirectSoundCaptureBuffer8_GetCurrentPosition(pDSoundStream->pDSCB, NULL, &cbReadPos); 1066 1070 if (FAILED(hr)) 1067 1071 { … … 1071 1075 1072 1076 RT_ZERO(wfx); 1073 hr = IDirectSoundCaptureBuffer8_GetFormat(pDSoundStr mIn->pDSCB, &wfx, sizeof(wfx), NULL);1077 hr = IDirectSoundCaptureBuffer8_GetFormat(pDSoundStream->pDSCB, &wfx, sizeof(wfx), NULL); 1074 1078 if (FAILED(hr)) 1075 1079 { … … 1081 1085 RT_ZERO(bc); 1082 1086 bc.dwSize = sizeof(bc); 1083 hr = IDirectSoundCaptureBuffer8_GetCaps(pDSoundStr mIn->pDSCB, &bc);1087 hr = IDirectSoundCaptureBuffer8_GetCaps(pDSoundStream->pDSCB, &bc); 1084 1088 if (FAILED(hr)) 1085 1089 { … … 1108 1112 wfx.cbSize)); 1109 1113 1110 if (bc.dwBufferBytes & pDSoundStr mIn->strmIn.Props.uAlign)1114 if (bc.dwBufferBytes & pDSoundStream->Stream.Props.uAlign) 1111 1115 DSLOGREL(("DSound: Capture GetCaps returned misaligned buffer: size %RU32, alignment %RU32\n", 1112 bc.dwBufferBytes, pDSoundStr mIn->strmIn.Props.uAlign + 1));1116 bc.dwBufferBytes, pDSoundStream->Stream.Props.uAlign + 1)); 1113 1117 1114 1118 if (bc.dwBufferBytes != pThis->cfg.cbBufferIn) … … 1117 1121 1118 1122 /* Initial state: reading at the initial capture position, no error. */ 1119 pDSoundStr mIn->csCaptureReadPos = cbReadPos >> pDSoundStrmIn->strmIn.Props.cShift;1120 pDSoundStr mIn->csCaptureBufferSize = bc.dwBufferBytes >> pDSoundStrmIn->strmIn.Props.cShift;1121 pDSoundStr mIn->hrLastCaptureIn= S_OK;1123 pDSoundStream->csCaptureReadPos = cbReadPos >> pDSoundStream->Stream.Props.cShift; 1124 pDSoundStream->csCaptureBufferSize = bc.dwBufferBytes >> pDSoundStream->Stream.Props.cShift; 1125 pDSoundStream->hrLastCapture = S_OK; 1122 1126 1123 1127 DSLOG(("DSound: csCaptureReadPos=%RU32, csCaptureBufferSize=%RU32\n", 1124 pDSoundStr mIn->csCaptureReadPos, pDSoundStrmIn->csCaptureBufferSize));1128 pDSoundStream->csCaptureReadPos, pDSoundStream->csCaptureBufferSize)); 1125 1129 1126 1130 } while (0); 1127 1131 1128 1132 if (FAILED(hr)) 1129 directSoundCaptureClose(pDSoundStr mIn);1133 directSoundCaptureClose(pDSoundStream); 1130 1134 1131 1135 LogFlowFunc(("Returning %Rhrc\n", hr)); … … 1133 1137 } 1134 1138 1135 static HRESULT directSoundCaptureStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStr mIn)1139 static HRESULT directSoundCaptureStop(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStream) 1136 1140 { 1137 1141 AssertPtrReturn(pThis , E_POINTER); 1138 AssertPtrReturn(pDSoundStr mIn, E_POINTER);1142 AssertPtrReturn(pDSoundStream, E_POINTER); 1139 1143 1140 1144 NOREF(pThis); … … 1142 1146 HRESULT hr; 1143 1147 1144 if (pDSoundStr mIn->pDSCB)1148 if (pDSoundStream->pDSCB) 1145 1149 { 1146 1150 DSLOG(("DSound: Stopping capture\n")); 1147 1151 1148 hr = IDirectSoundCaptureBuffer_Stop(pDSoundStr mIn->pDSCB);1152 hr = IDirectSoundCaptureBuffer_Stop(pDSoundStream->pDSCB); 1149 1153 if (FAILED(hr)) 1150 1154 DSLOGREL(("DSound: Stopping capture buffer failed with %Rhrc\n", hr)); … … 1154 1158 1155 1159 if (SUCCEEDED(hr)) 1156 pDSoundStr mIn->fEnabled = false;1160 pDSoundStream->fEnabled = false; 1157 1161 1158 1162 LogFlowFunc(("Returning %Rhrc\n", hr)); … … 1160 1164 } 1161 1165 1162 static HRESULT directSoundCaptureStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStr mIn)1163 { 1164 AssertPtrReturn(pThis, VERR_INVALID_POINTER);1165 AssertPtrReturn(pDSoundStr mIn, VERR_INVALID_POINTER);1166 static HRESULT directSoundCaptureStart(PDRVHOSTDSOUND pThis, PDSOUNDSTREAMIN pDSoundStream) 1167 { 1168 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1169 AssertPtrReturn(pDSoundStream, VERR_INVALID_POINTER); 1166 1170 1167 1171 HRESULT hr; 1168 if (pDSoundStr mIn->pDSCB != NULL)1172 if (pDSoundStream->pDSCB != NULL) 1169 1173 { 1170 1174 DWORD dwStatus; 1171 hr = IDirectSoundCaptureBuffer8_GetStatus(pDSoundStr mIn->pDSCB, &dwStatus);1175 hr = IDirectSoundCaptureBuffer8_GetStatus(pDSoundStream->pDSCB, &dwStatus); 1172 1176 if (FAILED(hr)) 1173 1177 { … … 1187 1191 #endif 1188 1192 DSLOG(("DSound: Starting to capture\n")); 1189 hr = IDirectSoundCaptureBuffer8_Start(pDSoundStr mIn->pDSCB, fFlags);1193 hr = IDirectSoundCaptureBuffer8_Start(pDSoundStream->pDSCB, fFlags); 1190 1194 if (FAILED(hr)) 1191 1195 DSLOGREL(("DSound: Starting to capture failed with %Rhrc\n", hr)); … … 1197 1201 1198 1202 if (SUCCEEDED(hr)) 1199 pDSoundStr mIn->fEnabled = true;1203 pDSoundStream->fEnabled = true; 1200 1204 1201 1205 LogFlowFunc(("Returning %Rhrc\n", hr)); … … 1405 1409 } 1406 1410 1407 /* 1408 * PDMIHOSTAUDIO 1409 */ 1410 1411 static DECLCALLBACK(int) drvHostDSoundInitOut(PPDMIHOSTAUDIO pInterface, 1412 PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg, 1413 uint32_t *pcSamples) 1411 static int dsoundCreateStreamOut(PPDMIHOSTAUDIO pInterface, 1412 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 1414 1413 { 1415 1414 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1416 AssertPtrReturn(p HstStrmOut,VERR_INVALID_POINTER);1417 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);1415 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1416 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1418 1417 /* pcSamples is optional. */ 1419 1418 1420 LogFlowFunc(("p HstStrmOut=%p, pCfg=%p\n", pHstStrmOut, pCfg));1419 LogFlowFunc(("pStream=%p, pCfg=%p\n", pStream, pCfg)); 1421 1420 1422 1421 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1423 PDSOUNDSTREAMOUT pDSoundStr mOut = (PDSOUNDSTREAMOUT)pHstStrmOut;1424 1425 pDSoundStr mOut->streamCfg = *pCfg;1426 pDSoundStr mOut->streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;1427 1428 int rc = DrvAudioStreamCfgToProps(&pDSoundStr mOut->streamCfg, &pDSoundStrmOut->strmOut.Props);1422 PDSOUNDSTREAMOUT pDSoundStream = (PDSOUNDSTREAMOUT)pStream; 1423 1424 pDSoundStream->streamCfg = *pCfg; 1425 pDSoundStream->streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 1426 1427 int rc = DrvAudioStreamCfgToProps(&pDSoundStream->streamCfg, &pDSoundStream->Stream.Props); 1429 1428 if (RT_SUCCESS(rc)) 1430 1429 { 1431 pDSoundStr mOut->pDS = NULL;1432 pDSoundStr mOut->pDSB = NULL;1433 pDSoundStr mOut->cbPlayWritePos = 0;1434 pDSoundStr mOut->fRestartPlayback = true;1435 pDSoundStr mOut->csPlaybackBufferSize = 0;1430 pDSoundStream->pDS = NULL; 1431 pDSoundStream->pDSB = NULL; 1432 pDSoundStream->cbPlayWritePos = 0; 1433 pDSoundStream->fRestartPlayback = true; 1434 pDSoundStream->csPlaybackBufferSize = 0; 1436 1435 1437 1436 if (pcSamples) 1438 *pcSamples = pThis->cfg.cbBufferOut >> p HstStrmOut->Props.cShift;1437 *pcSamples = pThis->cfg.cbBufferOut >> pStream->Props.cShift; 1439 1438 1440 1439 /* Try to open playback in case the device is already there. */ 1441 directSoundPlayOpen(pThis, pDSoundStr mOut);1440 directSoundPlayOpen(pThis, pDSoundStream); 1442 1441 } 1443 1442 else 1444 1443 { 1445 RT_ZERO(pDSoundStr mOut->streamCfg);1444 RT_ZERO(pDSoundStream->streamCfg); 1446 1445 } 1447 1446 … … 1450 1449 } 1451 1450 1452 static DECLCALLBACK(int) drvHostDSoundControlOut(PPDMIHOSTAUDIO pInterface,1453 PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd)1451 static int dsoundControlStreamOut(PPDMIHOSTAUDIO pInterface, 1452 PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd) 1454 1453 { 1455 1454 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1456 AssertPtrReturn(p HstStrmOut,VERR_INVALID_POINTER);1457 1458 LogFlowFunc(("p HstStrmOut=%p, cmd=%d\n", pHstStrmOut, enmStreamCmd));1455 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1456 1457 LogFlowFunc(("pStream=%p, cmd=%d\n", pStream, enmStreamCmd)); 1459 1458 1460 1459 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1461 PDSOUNDSTREAMOUT pDSoundStr mOut = (PDSOUNDSTREAMOUT)pHstStrmOut;1460 PDSOUNDSTREAMOUT pDSoundStream = (PDSOUNDSTREAMOUT)pStream; 1462 1461 1463 1462 int rc = VINF_SUCCESS; … … 1471 1470 DSLOG(("DSound: Playback PDMAUDIOSTREAMCMD_ENABLE\n")); 1472 1471 /* Try to start playback. If it fails, then reopen and try again. */ 1473 hr = directSoundPlayStart(pThis, pDSoundStr mOut);1472 hr = directSoundPlayStart(pThis, pDSoundStream); 1474 1473 if (FAILED(hr)) 1475 1474 { 1476 hr = directSoundPlayClose(pThis, pDSoundStr mOut);1475 hr = directSoundPlayClose(pThis, pDSoundStream); 1477 1476 if (SUCCEEDED(hr)) 1478 hr = directSoundPlayOpen(pThis, pDSoundStr mOut);1477 hr = directSoundPlayOpen(pThis, pDSoundStream); 1479 1478 if (SUCCEEDED(hr)) 1480 hr = directSoundPlayStart(pThis, pDSoundStr mOut);1479 hr = directSoundPlayStart(pThis, pDSoundStream); 1481 1480 } 1482 1481 … … 1490 1489 { 1491 1490 DSLOG(("DSound: Playback PDMAUDIOSTREAMCMD_DISABLE\n")); 1492 hr = directSoundPlayStop(pThis, pDSoundStr mOut);1491 hr = directSoundPlayStop(pThis, pDSoundStream); 1493 1492 if (FAILED(hr)) 1494 1493 rc = VERR_NOT_SUPPORTED; … … 1508 1507 } 1509 1508 1510 static DECLCALLBACK(int) drvHostDSound PlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,1511 uint32_t *pcSamplesPlayed)1509 static DECLCALLBACK(int) drvHostDSoundStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 1510 uint32_t *pcSamplesPlayed) 1512 1511 { 1513 1512 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1514 AssertPtrReturn(p HstStrmOut,VERR_INVALID_POINTER);1513 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1515 1514 /* pcSamplesPlayed is optional. */ 1516 1515 1517 1516 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1518 PDSOUNDSTREAMOUT pDSoundStr mOut = (PDSOUNDSTREAMOUT)pHstStrmOut;1517 PDSOUNDSTREAMOUT pDSoundStream = (PDSOUNDSTREAMOUT)pStream; 1519 1518 1520 1519 int rc = VINF_SUCCESS; … … 1528 1527 { 1529 1528 DWORD cbBuffer, cbFree, cbPlayPos; 1530 rc = dsoundGetPosOut(pThis, pDSoundStr mOut, &cbBuffer, &cbFree, &cbPlayPos);1529 rc = dsoundGetPosOut(pThis, pDSoundStream, &cbBuffer, &cbFree, &cbPlayPos); 1531 1530 if (RT_FAILURE(rc)) 1532 1531 break; … … 1536 1535 * i.e. always leave a free space for 1 audio sample. 1537 1536 */ 1538 const DWORD cbSample = AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, 1);1537 const DWORD cbSample = AUDIOMIXBUF_S2B(&pStream->MixBuf, 1); 1539 1538 if (cbFree <= cbSample) 1540 1539 break; 1541 1540 cbFree -= cbSample; 1542 1541 1543 uint32_t csLive = AudioMixBufAvail(&p HstStrmOut->MixBuf);1544 uint32_t cbLive = AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, csLive);1542 uint32_t csLive = AudioMixBufAvail(&pStream->MixBuf); 1543 uint32_t cbLive = AUDIOMIXBUF_S2B(&pStream->MixBuf, csLive); 1545 1544 1546 1545 /* Do not write more than available space in the DirectSound playback buffer. */ 1547 1546 cbLive = RT_MIN(cbFree, cbLive); 1548 1547 1549 cbLive &= ~p HstStrmOut->Props.uAlign;1548 cbLive &= ~pStream->Props.uAlign; 1550 1549 if (cbLive == 0 || cbLive > cbBuffer) 1551 1550 { 1552 1551 DSLOG(("DSound: cbLive=%RU32, cbBuffer=%ld, cbPlayWritePos=%ld, cbPlayPos=%ld\n", 1553 cbLive, cbBuffer, pDSoundStr mOut->cbPlayWritePos, cbPlayPos));1554 break; 1555 } 1556 1557 LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStr mOut->pDSB;1552 cbLive, cbBuffer, pDSoundStream->cbPlayWritePos, cbPlayPos)); 1553 break; 1554 } 1555 1556 LPDIRECTSOUNDBUFFER8 pDSB = pDSoundStream->pDSB; 1558 1557 AssertPtr(pDSB); 1559 1558 1560 1559 LPVOID pv1, pv2; 1561 1560 DWORD cb1, cb2; 1562 HRESULT hr = directSoundPlayLock(pThis, pDSB, &p HstStrmOut->Props, pDSoundStrmOut->cbPlayWritePos, cbLive,1561 HRESULT hr = directSoundPlayLock(pThis, pDSB, &pStream->Props, pDSoundStream->cbPlayWritePos, cbLive, 1563 1562 &pv1, &pv2, &cb1, &cb2, 0 /* dwFlags */); 1564 1563 if (FAILED(hr)) … … 1568 1567 } 1569 1568 1570 DWORD len1 = AUDIOMIXBUF_B2S(&p HstStrmOut->MixBuf, cb1);1571 DWORD len2 = AUDIOMIXBUF_B2S(&p HstStrmOut->MixBuf, cb2);1569 DWORD len1 = AUDIOMIXBUF_B2S(&pStream->MixBuf, cb1); 1570 DWORD len2 = AUDIOMIXBUF_B2S(&pStream->MixBuf, cb2); 1572 1571 1573 1572 uint32_t cRead = 0; … … 1575 1574 if (pv1 && cb1) 1576 1575 { 1577 rc = AudioMixBufReadCirc(&p HstStrmOut->MixBuf, pv1, cb1, &cRead);1576 rc = AudioMixBufReadCirc(&pStream->MixBuf, pv1, cb1, &cRead); 1578 1577 if (RT_SUCCESS(rc)) 1579 1578 cReadTotal += cRead; … … 1584 1583 && pv2 && cb2) 1585 1584 { 1586 rc = AudioMixBufReadCirc(&p HstStrmOut->MixBuf, pv2, cb2, &cRead);1585 rc = AudioMixBufReadCirc(&pStream->MixBuf, pv2, cb2, &cRead); 1587 1586 if (RT_SUCCESS(rc)) 1588 1587 cReadTotal += cRead; … … 1591 1590 directSoundPlayUnlock(pThis, pDSB, pv1, pv2, cb1, cb2); 1592 1591 1593 pDSoundStr mOut->cbPlayWritePos =1594 (pDSoundStr mOut->cbPlayWritePos + AUDIOMIXBUF_S2B(&pHstStrmOut->MixBuf, cReadTotal)) % cbBuffer;1592 pDSoundStream->cbPlayWritePos = 1593 (pDSoundStream->cbPlayWritePos + AUDIOMIXBUF_S2B(&pStream->MixBuf, cReadTotal)) % cbBuffer; 1595 1594 1596 1595 DSLOGF(("DSound: %RU32 (%RU32 samples) out of %RU32%s, buffer write pos %ld, rc=%Rrc\n", 1597 AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, cReadTotal), cReadTotal, cbLive,1598 cbLive != AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, cReadTotal) ? " !!!": "",1599 pDSoundStr mOut->cbPlayWritePos, rc));1596 AUDIOMIXBUF_S2B(&pStream->MixBuf, cReadTotal), cReadTotal, cbLive, 1597 cbLive != AUDIOMIXBUF_S2B(&pStream->MixBuf, cReadTotal) ? " !!!": "", 1598 pDSoundStream->cbPlayWritePos, rc)); 1600 1599 1601 1600 if (cReadTotal) 1602 1601 { 1603 AudioMixBufFinish(&p HstStrmOut->MixBuf, cReadTotal);1602 AudioMixBufFinish(&pStream->MixBuf, cReadTotal); 1604 1603 rc = VINF_SUCCESS; /* Played something. */ 1605 1604 } … … 1608 1607 break; 1609 1608 1610 if (pDSoundStr mOut->fRestartPlayback)1609 if (pDSoundStream->fRestartPlayback) 1611 1610 { 1612 1611 /* … … 1615 1614 * and it can start playing. 1616 1615 */ 1617 pDSoundStr mOut->fRestartPlayback = false;1616 pDSoundStream->fRestartPlayback = false; 1618 1617 1619 1618 DWORD fFlags = 0; … … 1623 1622 for (unsigned i = 0; i < DRV_DSOUND_RESTORE_ATTEMPTS_MAX; i++) 1624 1623 { 1625 hr = IDirectSoundBuffer8_Play(pDSoundStr mOut->pDSB, 0, 0, fFlags);1624 hr = IDirectSoundBuffer8_Play(pDSoundStream->pDSB, 0, 0, fFlags); 1626 1625 if ( SUCCEEDED(hr) 1627 1626 || hr != DSERR_BUFFERLOST) … … 1630 1629 { 1631 1630 LogFlowFunc(("Restarting playback failed due to lost buffer, restoring ...\n")); 1632 directSoundPlayRestore(pThis, pDSoundStr mOut->pDSB);1631 directSoundPlayRestore(pThis, pDSoundStream->pDSB); 1633 1632 } 1634 1633 } … … 1658 1657 } 1659 1658 1660 static DECLCALLBACK(int) drvHostDSoundFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)1659 static int dsoundDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1661 1660 { 1662 1661 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1663 PDSOUNDSTREAMOUT pDSoundStr mOut = (PDSOUNDSTREAMOUT)pHstStrmOut;1664 1665 directSoundPlayClose(pThis, pDSoundStr mOut);1666 1667 pDSoundStr mOut->cbPlayWritePos = 0;1668 pDSoundStr mOut->fRestartPlayback = true;1669 pDSoundStr mOut->csPlaybackBufferSize = 0;1670 1671 RT_ZERO(pDSoundStr mOut->streamCfg);1662 PDSOUNDSTREAMOUT pDSoundStream = (PDSOUNDSTREAMOUT)pStream; 1663 1664 directSoundPlayClose(pThis, pDSoundStream); 1665 1666 pDSoundStream->cbPlayWritePos = 0; 1667 pDSoundStream->fRestartPlayback = true; 1668 pDSoundStream->csPlaybackBufferSize = 0; 1669 1670 RT_ZERO(pDSoundStream->streamCfg); 1672 1671 1673 1672 return VINF_SUCCESS; 1674 1673 } 1675 1674 1676 static DECLCALLBACK(int) drvHostDSoundInitIn(PPDMIHOSTAUDIO pInterface, 1677 PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg, 1678 PDMAUDIORECSOURCE enmRecSource, 1679 uint32_t *pcSamples) 1675 static int dsoundCreateStreamIn(PPDMIHOSTAUDIO pInterface, 1676 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 1680 1677 { 1681 1678 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1682 PDSOUNDSTREAMIN pDSoundStr mIn = (PDSOUNDSTREAMIN)pHstStrmIn;1683 1684 LogFlowFunc(("p HstStrmIn=%p, pAudioSettings=%p, enmRecSource=%ld\n",1685 p HstStrmIn, pCfg, enmRecSource));1686 1687 pDSoundStr mIn->streamCfg = *pCfg;1688 pDSoundStr mIn->streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;1679 PDSOUNDSTREAMIN pDSoundStream = (PDSOUNDSTREAMIN)pStream; 1680 1681 LogFlowFunc(("pStream=%p, pAudioSettings=%p, enmRecSource=%ld\n", 1682 pStream, pCfg, pCfg->DestSource.Source)); 1683 1684 pDSoundStream->streamCfg = *pCfg; 1685 pDSoundStream->streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 1689 1686 1690 1687 /** @todo caller should already init Props? */ 1691 int rc = DrvAudioStreamCfgToProps(&pDSoundStr mIn->streamCfg, &pHstStrmIn->Props);1688 int rc = DrvAudioStreamCfgToProps(&pDSoundStream->streamCfg, &pStream->Props); 1692 1689 if (RT_SUCCESS(rc)) 1693 1690 { 1694 1691 /* Init the stream structure and save relevant information to it. */ 1695 pDSoundStr mIn->csCaptureReadPos= 0;1696 pDSoundStr mIn->csCaptureBufferSize = 0;1697 pDSoundStr mIn->pDSC= NULL;1698 pDSoundStr mIn->pDSCB= NULL;1699 pDSoundStr mIn->enmRecSource = enmRecSource;1700 pDSoundStr mIn->hrLastCaptureIn= S_OK;1692 pDSoundStream->csCaptureReadPos = 0; 1693 pDSoundStream->csCaptureBufferSize = 0; 1694 pDSoundStream->pDSC = NULL; 1695 pDSoundStream->pDSCB = NULL; 1696 pDSoundStream->enmRecSource = pCfg->DestSource.Source; 1697 pDSoundStream->hrLastCapture = S_OK; 1701 1698 1702 1699 if (pcSamples) 1703 *pcSamples = pThis->cfg.cbBufferIn >> p HstStrmIn->Props.cShift;1700 *pcSamples = pThis->cfg.cbBufferIn >> pStream->Props.cShift; 1704 1701 1705 1702 /* Try to open capture in case the device is already there. */ 1706 directSoundCaptureOpen(pThis, pDSoundStr mIn);1703 directSoundCaptureOpen(pThis, pDSoundStream); 1707 1704 } 1708 1705 else 1709 1706 { 1710 RT_ZERO(pDSoundStr mIn->streamCfg);1707 RT_ZERO(pDSoundStream->streamCfg); 1711 1708 } 1712 1709 … … 1715 1712 } 1716 1713 1717 static DECLCALLBACK(int) drvHostDSoundControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,1718 1714 static int dsoundControlStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 1715 PDMAUDIOSTREAMCMD enmStreamCmd) 1719 1716 { 1720 1717 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1721 AssertPtrReturn(p HstStrmIn, VERR_INVALID_POINTER);1722 1723 LogFlowFunc(("p HstStrmIn=%p, enmStreamCmd=%ld\n", pHstStrmIn, enmStreamCmd));1718 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1719 1720 LogFlowFunc(("pStream=%p, enmStreamCmd=%ld\n", pStream, enmStreamCmd)); 1724 1721 1725 1722 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1726 PDSOUNDSTREAMIN pDSoundStr mIn = (PDSOUNDSTREAMIN)pHstStrmIn;1723 PDSOUNDSTREAMIN pDSoundStream = (PDSOUNDSTREAMIN)pStream; 1727 1724 1728 1725 int rc = VINF_SUCCESS; … … 1735 1732 { 1736 1733 /* Try to start capture. If it fails, then reopen and try again. */ 1737 hr = directSoundCaptureStart(pThis, pDSoundStr mIn);1734 hr = directSoundCaptureStart(pThis, pDSoundStream); 1738 1735 if (FAILED(hr)) 1739 1736 { 1740 hr = directSoundCaptureClose(pDSoundStr mIn);1737 hr = directSoundCaptureClose(pDSoundStream); 1741 1738 if (SUCCEEDED(hr)) 1742 1739 { 1743 hr = directSoundCaptureOpen(pThis, pDSoundStr mIn);1740 hr = directSoundCaptureOpen(pThis, pDSoundStream); 1744 1741 if (SUCCEEDED(hr)) 1745 hr = directSoundCaptureStart(pThis, pDSoundStr mIn);1742 hr = directSoundCaptureStart(pThis, pDSoundStream); 1746 1743 } 1747 1744 } … … 1755 1752 case PDMAUDIOSTREAMCMD_PAUSE: 1756 1753 { 1757 hr = directSoundCaptureStop(pThis, pDSoundStr mIn);1754 hr = directSoundCaptureStop(pThis, pDSoundStream); 1758 1755 if (FAILED(hr)) 1759 1756 rc = VERR_NOT_SUPPORTED; … … 1772 1769 } 1773 1770 1774 static DECLCALLBACK(int) drvHostDSound CaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,1775 uint32_t *pcSamplesCaptured)1771 static DECLCALLBACK(int) drvHostDSoundStreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 1772 uint32_t *pcSamplesCaptured) 1776 1773 { 1777 1774 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1778 1775 1779 PDSOUNDSTREAMIN pDSoundStr mIn = (PDSOUNDSTREAMIN)pHstStrmIn;1780 LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB = pDSoundStr mIn->pDSCB;1776 PDSOUNDSTREAMIN pDSoundStream = (PDSOUNDSTREAMIN)pStream; 1777 LPDIRECTSOUNDCAPTUREBUFFER8 pDSCB = pDSoundStream->pDSCB; 1781 1778 1782 1779 int rc = VINF_SUCCESS; … … 1797 1794 if (FAILED(hr)) 1798 1795 { 1799 if (hr != pDSoundStr mIn->hrLastCaptureIn)1796 if (hr != pDSoundStream->hrLastCapture) 1800 1797 { 1801 1798 DSLOGREL(("DSound: Getting capture position failed with %Rhrc\n", hr)); 1802 pDSoundStr mIn->hrLastCaptureIn= hr;1799 pDSoundStream->hrLastCapture = hr; 1803 1800 } 1804 1801 … … 1807 1804 } 1808 1805 1809 pDSoundStr mIn->hrLastCaptureIn= hr;1810 1811 if (cbReadPos & p HstStrmIn->Props.uAlign)1812 DSLOGF(("DSound: Misaligned capture read position %ld (alignment: %RU32)\n", cbReadPos, p HstStrmIn->Props.uAlign));1806 pDSoundStream->hrLastCapture = hr; 1807 1808 if (cbReadPos & pStream->Props.uAlign) 1809 DSLOGF(("DSound: Misaligned capture read position %ld (alignment: %RU32)\n", cbReadPos, pStream->Props.uAlign)); 1813 1810 1814 1811 /* Capture position in samples. */ 1815 DWORD csReadPos = cbReadPos >> p HstStrmIn->Props.cShift;1812 DWORD csReadPos = cbReadPos >> pStream->Props.cShift; 1816 1813 1817 1814 /* Number of samples available in the DirectSound capture buffer. */ 1818 DWORD csCaptured = dsoundRingDistance(csReadPos, pDSoundStr mIn->csCaptureReadPos, pDSoundStrmIn->csCaptureBufferSize);1815 DWORD csCaptured = dsoundRingDistance(csReadPos, pDSoundStream->csCaptureReadPos, pDSoundStream->csCaptureBufferSize); 1819 1816 if (csCaptured == 0) 1820 1817 break; 1821 1818 1822 1819 /* Using as an intermediate not circular buffer. */ 1823 AudioMixBufReset(&p HstStrmIn->MixBuf);1820 AudioMixBufReset(&pStream->MixBuf); 1824 1821 1825 1822 /* Get number of free samples in the mix buffer and check that is has free space */ 1826 uint32_t csMixFree = AudioMixBufFree(&p HstStrmIn->MixBuf);1823 uint32_t csMixFree = AudioMixBufFree(&pStream->MixBuf); 1827 1824 if (csMixFree == 0) 1828 1825 { … … 1832 1829 1833 1830 DSLOGF(("DSound: Capture csMixFree=%RU32, csReadPos=%ld, csCaptureReadPos=%ld, csCaptured=%ld\n", 1834 csMixFree, csReadPos, pDSoundStr mIn->csCaptureReadPos, csCaptured));1831 csMixFree, csReadPos, pDSoundStream->csCaptureReadPos, csCaptured)); 1835 1832 1836 1833 /* No need to fetch more samples than mix buffer can receive. */ … … 1840 1837 LPVOID pv1, pv2; 1841 1838 DWORD cb1, cb2; 1842 hr = directSoundCaptureLock(pDSCB, &p HstStrmIn->Props,1843 AUDIOMIXBUF_S2B(&p HstStrmIn->MixBuf, pDSoundStrmIn->csCaptureReadPos), /* dwOffset */1844 AUDIOMIXBUF_S2B(&p HstStrmIn->MixBuf, csCaptured), /* dwBytes */1839 hr = directSoundCaptureLock(pDSCB, &pStream->Props, 1840 AUDIOMIXBUF_S2B(&pStream->MixBuf, pDSoundStream->csCaptureReadPos), /* dwOffset */ 1841 AUDIOMIXBUF_S2B(&pStream->MixBuf, csCaptured), /* dwBytes */ 1845 1842 &pv1, &pv2, &cb1, &cb2, 1846 1843 0 /* dwFlags */); … … 1851 1848 } 1852 1849 1853 DWORD len1 = AUDIOMIXBUF_B2S(&p HstStrmIn->MixBuf, cb1);1854 DWORD len2 = AUDIOMIXBUF_B2S(&p HstStrmIn->MixBuf, cb2);1850 DWORD len1 = AUDIOMIXBUF_B2S(&pStream->MixBuf, cb1); 1851 DWORD len2 = AUDIOMIXBUF_B2S(&pStream->MixBuf, cb2); 1855 1852 1856 1853 uint32_t csWrittenTotal = 0; … … 1858 1855 if (pv1 && len1) 1859 1856 { 1860 rc = AudioMixBufWriteAt(&p HstStrmIn->MixBuf, 0 /* offWrite */,1857 rc = AudioMixBufWriteAt(&pStream->MixBuf, 0 /* offWrite */, 1861 1858 pv1, cb1, &csWritten); 1862 1859 if (RT_SUCCESS(rc)) … … 1868 1865 && pv2 && len2) 1869 1866 { 1870 rc = AudioMixBufWriteAt(&p HstStrmIn->MixBuf, csWrittenTotal,1867 rc = AudioMixBufWriteAt(&pStream->MixBuf, csWrittenTotal, 1871 1868 pv2, cb2, &csWritten); 1872 1869 if (RT_SUCCESS(rc)) … … 1877 1874 1878 1875 if (csWrittenTotal) /* Captured something? */ 1879 rc = AudioMixBufMixToParent(&p HstStrmIn->MixBuf, csWrittenTotal, &cCaptured);1876 rc = AudioMixBufMixToParent(&pStream->MixBuf, csWrittenTotal, &cCaptured); 1880 1877 1881 1878 if (RT_SUCCESS(rc)) 1882 1879 { 1883 pDSoundStr mIn->csCaptureReadPos = (pDSoundStrmIn->csCaptureReadPos + cCaptured) % pDSoundStrmIn->csCaptureBufferSize;1880 pDSoundStream->csCaptureReadPos = (pDSoundStream->csCaptureReadPos + cCaptured) % pDSoundStream->csCaptureBufferSize; 1884 1881 DSLOGF(("DSound: Capture %ld (%ld+%ld), processed %RU32/%RU32\n", 1885 1882 csCaptured, len1, len2, cCaptured, csWrittenTotal)); … … 1902 1899 } 1903 1900 1904 static DECLCALLBACK(int) drvHostDSoundFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)1901 static int dsoundDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1905 1902 { 1906 1903 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1907 PDSOUNDSTREAMIN pDSoundStr mIn = (PDSOUNDSTREAMIN)pHstStrmIn;1908 1909 directSoundCaptureClose(pDSoundStr mIn);1910 1911 pDSoundStr mIn->csCaptureReadPos = 0;1912 pDSoundStr mIn->csCaptureBufferSize = 0;1913 RT_ZERO(pDSoundStr mIn->streamCfg);1904 PDSOUNDSTREAMIN pDSoundStream = (PDSOUNDSTREAMIN)pStream; 1905 1906 directSoundCaptureClose(pDSoundStream); 1907 1908 pDSoundStream->csCaptureReadPos = 0; 1909 pDSoundStream->csCaptureBufferSize = 0; 1910 RT_ZERO(pDSoundStream->streamCfg); 1914 1911 1915 1912 return VINF_SUCCESS; 1916 1913 } 1917 1914 1918 /** @todo Replace PDMAUDIODIR with a (registered? unique) channel ID to provide multi-channel input/output. */ 1919 static DECLCALLBACK(bool) drvHostDSoundIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir) 1920 { 1921 AssertPtrReturn(pInterface, false); 1922 1923 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 1924 1925 if (enmDir == PDMAUDIODIR_IN) 1926 return pThis->fEnabledIn; 1927 1928 return pThis->fEnabledOut; 1929 } 1930 1931 static DECLCALLBACK(int) drvHostDSoundGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg) 1915 static DECLCALLBACK(int) drvHostDSoundGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg) 1932 1916 { 1933 1917 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); … … 1959 1943 } 1960 1944 1961 static DECLCALLBACK(int) d rvHostDSoundThread(RTTHREAD hThreadSelf, void *pvUser)1945 static DECLCALLBACK(int) dsoundNotificationThread(RTTHREAD hThreadSelf, void *pvUser) 1962 1946 { 1963 1947 PDRVHOSTDSOUND pThis = (PDRVHOSTDSOUND)pvUser; … … 2012 1996 { 2013 1997 DWORD cbBuffer, cbFree, cbPlayPos; 2014 rc = dsoundGetPosOut(pThis->pDSStr mOut, &cbBuffer, &cbFree, &cbPlayPos);1998 rc = dsoundGetPosOut(pThis->pDSStream, &cbBuffer, &cbFree, &cbPlayPos); 2015 1999 if ( RT_SUCCESS(rc) 2016 2000 && cbFree) … … 2099 2083 2100 2084 /* Start notification thread. */ 2101 rc = RTThreadCreate(&pThis->Thread, d rvHostDSoundThread,2085 rc = RTThreadCreate(&pThis->Thread, dsoundNotificationThread, 2102 2086 pThis /*pvUser*/, 0 /*cbStack*/, 2103 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "d SoundNtfy");2087 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "dsoundNtfy"); 2104 2088 if (RT_SUCCESS(rc)) 2105 2089 { … … 2157 2141 } 2158 2142 2159 static void d SoundConfigInit(PDRVHOSTDSOUND pThis, PCFGMNODE pCfg)2143 static void dsoundConfigInit(PDRVHOSTDSOUND pThis, PCFGMNODE pCfg) 2160 2144 { 2161 2145 unsigned int uBufsizeOut, uBufsizeIn; … … 2174 2158 &pThis->cfg.uuidPlay, 2175 2159 &pThis->cfg.uuidCapture)); 2160 } 2161 2162 /* 2163 * PDMIHOSTAUDIO 2164 */ 2165 2166 static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostDSoundGetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir) 2167 { 2168 AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN); 2169 2170 return PDMAUDIOBACKENDSTS_RUNNING; 2171 } 2172 2173 static DECLCALLBACK(int) drvHostDSoundStreamCreate(PPDMIHOSTAUDIO pInterface, 2174 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 2175 { 2176 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 2177 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 2178 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 2179 2180 int rc; 2181 if (pCfg->enmDir == PDMAUDIODIR_IN) 2182 rc = dsoundCreateStreamIn(pInterface, pStream, pCfg, pcSamples); 2183 else 2184 rc = dsoundCreateStreamOut(pInterface, pStream, pCfg, pcSamples); 2185 2186 LogFlowFunc(("%s: rc=%Rrc\n", pStream->szName, rc)); 2187 return rc; 2188 } 2189 2190 static DECLCALLBACK(int) drvHostDSoundStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 2191 { 2192 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 2193 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 2194 2195 int rc; 2196 if (pStream->enmDir == PDMAUDIODIR_IN) 2197 rc = dsoundDestroyStreamIn(pInterface, pStream); 2198 else 2199 rc = dsoundDestroyStreamOut(pInterface, pStream); 2200 2201 return rc; 2202 } 2203 2204 static DECLCALLBACK(int) drvHostDSoundStreamControl(PPDMIHOSTAUDIO pInterface, 2205 PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd) 2206 { 2207 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 2208 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 2209 2210 Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST); 2211 2212 int rc; 2213 if (pStream->enmDir == PDMAUDIODIR_IN) 2214 rc = dsoundControlStreamIn(pInterface, pStream, enmStreamCmd); 2215 else 2216 rc = dsoundControlStreamOut(pInterface, pStream, enmStreamCmd); 2217 2218 return rc; 2219 } 2220 2221 static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostDSoundStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 2222 { 2223 AssertPtrReturn(pInterface, PDMAUDIOSTRMSTS_FLAG_NONE); 2224 AssertPtrReturn(pStream, PDMAUDIOSTRMSTS_FLAG_NONE); 2225 2226 PDRVHOSTDSOUND pThis = PDMIHOSTAUDIO_2_DRVHOSTDSOUND(pInterface); 2227 2228 PDMAUDIOSTRMSTS strmSts = PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 2229 if (pStream->enmDir == PDMAUDIODIR_IN) 2230 { 2231 PDSOUNDSTREAMIN pDSoundStream = (PDSOUNDSTREAMIN)pStream; 2232 strmSts |= pDSoundStream->fEnabled ? PDMAUDIOSTRMSTS_FLAG_ENABLED : 0; 2233 } 2234 else 2235 { 2236 PDSOUNDSTREAMOUT pDSoundStream = (PDSOUNDSTREAMOUT)pStream; 2237 strmSts |= pDSoundStream->fEnabled ? PDMAUDIOSTRMSTS_FLAG_ENABLED : 0; 2238 } 2239 2240 return strmSts; 2176 2241 } 2177 2242 … … 2248 2313 * Initialize configuration values. 2249 2314 */ 2250 d SoundConfigInit(pThis, pCfg);2315 dsoundConfigInit(pThis, pCfg); 2251 2316 2252 2317 return VINF_SUCCESS; -
trunk/src/VBox/Devices/Audio/DrvHostNullAudio.cpp
r60925 r61157 41 41 * THE SOFTWARE. 42 42 */ 43 #include <iprt/alloc.h> 44 #include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */ 45 43 46 #define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO 44 47 #include <VBox/log.h> 48 #include <VBox/vmm/pdmaudioifs.h> 49 45 50 #include "DrvAudio.h" 46 51 #include "AudioMixBuffer.h" 47 48 52 #include "VBoxDD.h" 49 53 50 #include <iprt/alloc.h>51 #include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */52 #include <VBox/vmm/pdmaudioifs.h>53 54 54 55 typedef struct NULLAUDIOSTREAMOUT 55 56 { 56 57 /** Note: Always must come first! */ 57 PDMAUDIO HSTSTRMOUT streamOut;58 PDMAUDIOSTREAM Stream; 58 59 uint64_t u64TicksLast; 59 60 uint64_t csPlayBuffer; … … 64 65 { 65 66 /** Note: Always must come first! */ 66 PDMAUDIO HSTSTRMIN streamIn;67 PDMAUDIOSTREAM Stream; 67 68 } NULLAUDIOSTREAMIN, *PNULLAUDIOSTREAMIN; 68 69 … … 82 83 83 84 84 static DECLCALLBACK(int) drvHostNullAudioGetConf (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)85 static DECLCALLBACK(int) drvHostNullAudioGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg) 85 86 { 86 87 NOREF(pInterface); … … 100 101 } 101 102 102 static DECLCALLBACK(int)drvHostNullAudioInit(PPDMIHOSTAUDIO pInterface)103 static int drvHostNullAudioInit(PPDMIHOSTAUDIO pInterface) 103 104 { 104 105 NOREF(pInterface); … … 108 109 } 109 110 110 static DECLCALLBACK(int) drvHostNullAudioInitIn(PPDMIHOSTAUDIO pInterface, 111 PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg, 112 PDMAUDIORECSOURCE enmRecSource, 113 uint32_t *pcSamples) 114 { 115 NOREF(pInterface); 116 NOREF(enmRecSource); 111 static int nullCreateStreamIn(PPDMIHOSTAUDIO pInterface, 112 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 113 { 114 NOREF(pInterface); 117 115 118 116 /* Just adopt the wanted stream configuration. */ 119 int rc = DrvAudioStreamCfgToProps(pCfg, &p HstStrmIn->Props);117 int rc = DrvAudioStreamCfgToProps(pCfg, &pStream->Props); 120 118 if (RT_SUCCESS(rc)) 121 119 { … … 128 126 } 129 127 130 static DECLCALLBACK(int) drvHostNullAudioInitOut(PPDMIHOSTAUDIO pInterface,131 PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,132 128 static int nullCreateStreamOut(PPDMIHOSTAUDIO pInterface, 129 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, 130 uint32_t *pcSamples) 133 131 { 134 132 NOREF(pInterface); 135 133 136 134 /* Just adopt the wanted stream configuration. */ 137 int rc = DrvAudioStreamCfgToProps(pCfg, &p HstStrmOut->Props);135 int rc = DrvAudioStreamCfgToProps(pCfg, &pStream->Props); 138 136 if (RT_SUCCESS(rc)) 139 137 { 140 PNULLAUDIOSTREAMOUT pNullStr mOut = (PNULLAUDIOSTREAMOUT)pHstStrmOut;141 pNullStr mOut->u64TicksLast = 0;142 pNullStr mOut->csPlayBuffer = _1K;143 pNullStr mOut->pu8PlayBuffer = (uint8_t *)RTMemAlloc(_1K << pHstStrmOut->Props.cShift);144 if (pNullStr mOut->pu8PlayBuffer)138 PNULLAUDIOSTREAMOUT pNullStream = (PNULLAUDIOSTREAMOUT)pStream; 139 pNullStream->u64TicksLast = 0; 140 pNullStream->csPlayBuffer = _1K; 141 pNullStream->pu8PlayBuffer = (uint8_t *)RTMemAlloc(_1K << pStream->Props.cShift); 142 if (pNullStream->pu8PlayBuffer) 145 143 { 146 144 if (pcSamples) 147 *pcSamples = pNullStr mOut->csPlayBuffer;145 *pcSamples = pNullStream->csPlayBuffer; 148 146 } 149 147 else … … 155 153 } 156 154 157 static DECLCALLBACK(bool) drvHostNullAudioIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir) 158 { 159 NOREF(pInterface); 160 NOREF(enmDir); 161 return true; /* Always all enabled. */ 162 } 163 164 static DECLCALLBACK(int) drvHostNullAudioPlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut, 165 uint32_t *pcSamplesPlayed) 155 static DECLCALLBACK(int) drvHostNullAudioStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 156 uint32_t *pcSamplesPlayed) 166 157 { 167 158 PDRVHOSTNULLAUDIO pDrv = RT_FROM_MEMBER(pInterface, DRVHOSTNULLAUDIO, IHostAudio); 168 PNULLAUDIOSTREAMOUT pNullStr mOut = (PNULLAUDIOSTREAMOUT)pHstStrmOut;159 PNULLAUDIOSTREAMOUT pNullStream = (PNULLAUDIOSTREAMOUT)pStream; 169 160 170 161 /* Consume as many samples as would be played at the current frequency since last call. */ 171 uint32_t csLive = AudioMixBufAvail(&p HstStrmOut->MixBuf);162 uint32_t csLive = AudioMixBufAvail(&pStream->MixBuf); 172 163 uint64_t u64TicksNow = PDMDrvHlpTMGetVirtualTime(pDrv->pDrvIns); 173 uint64_t u64TicksElapsed = u64TicksNow - pNullStr mOut->u64TicksLast;164 uint64_t u64TicksElapsed = u64TicksNow - pNullStream->u64TicksLast; 174 165 uint64_t u64TicksFreq = PDMDrvHlpTMGetVirtualFreq(pDrv->pDrvIns); 175 166 176 167 /* Remember when samples were consumed. */ 177 pNullStr mOut->u64TicksLast = u64TicksNow;168 pNullStream->u64TicksLast = u64TicksNow; 178 169 179 170 /* … … 181 172 * If rounding is not taken into account then the playback rate will be consistently lower that expected. 182 173 */ 183 uint64_t cSamplesPlayed = (2 * u64TicksElapsed * p HstStrmOut->Props.uHz + u64TicksFreq) / u64TicksFreq / 2;174 uint64_t cSamplesPlayed = (2 * u64TicksElapsed * pStream->Props.uHz + u64TicksFreq) / u64TicksFreq / 2; 184 175 185 176 /* Don't play more than available. */ … … 187 178 cSamplesPlayed = csLive; 188 179 189 cSamplesPlayed = RT_MIN(cSamplesPlayed, pNullStr mOut->csPlayBuffer);180 cSamplesPlayed = RT_MIN(cSamplesPlayed, pNullStream->csPlayBuffer); 190 181 191 182 uint32_t csRead = 0; 192 AudioMixBufReadCirc(&p HstStrmOut->MixBuf, pNullStrmOut->pu8PlayBuffer,193 AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, cSamplesPlayed), &csRead);194 AudioMixBufFinish(&p HstStrmOut->MixBuf, csRead);183 AudioMixBufReadCirc(&pStream->MixBuf, pNullStream->pu8PlayBuffer, 184 AUDIOMIXBUF_S2B(&pStream->MixBuf, cSamplesPlayed), &csRead); 185 AudioMixBufFinish(&pStream->MixBuf, csRead); 195 186 196 187 if (pcSamplesPlayed) … … 200 191 } 201 192 202 static DECLCALLBACK(int) drvHostNullAudio CaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,203 uint32_t *pcSamplesCaptured)193 static DECLCALLBACK(int) drvHostNullAudioStreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 194 uint32_t *pcSamplesCaptured) 204 195 { 205 196 /* Never capture anything. */ … … 210 201 } 211 202 212 static DECLCALLBACK(int) drvHostNullAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn, 213 PDMAUDIOSTREAMCMD enmStreamCmd) 214 { 215 NOREF(pInterface); 216 NOREF(pHstStrmIn); 217 NOREF(enmStreamCmd); 218 219 return VINF_SUCCESS; 220 } 221 222 static DECLCALLBACK(int) drvHostNullAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut, 223 PDMAUDIOSTREAMCMD enmStreamCmd) 224 { 225 NOREF(pInterface); 226 NOREF(pHstStrmOut); 227 NOREF(enmStreamCmd); 228 229 return VINF_SUCCESS; 230 } 231 232 static DECLCALLBACK(int) drvHostNullAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn) 203 static int nullDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 233 204 { 234 205 LogFlowFuncLeaveRC(VINF_SUCCESS); … … 236 207 } 237 208 238 static DECLCALLBACK(int) drvHostNullAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)209 static int nullDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 239 210 { 240 211 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 241 212 242 PNULLAUDIOSTREAMOUT pNullStr mOut = (PNULLAUDIOSTREAMOUT)pHstStrmOut;243 if ( pNullStr mOut244 && pNullStr mOut->pu8PlayBuffer)213 PNULLAUDIOSTREAMOUT pNullStream = (PNULLAUDIOSTREAMOUT)pStream; 214 if ( pNullStream 215 && pNullStream->pu8PlayBuffer) 245 216 { 246 RTMemFree(pNullStr mOut->pu8PlayBuffer);247 pNullStr mOut->pu8PlayBuffer = NULL;217 RTMemFree(pNullStream->pu8PlayBuffer); 218 pNullStream->pu8PlayBuffer = NULL; 248 219 } 249 220 250 221 LogFlowFuncLeaveRC(VINF_SUCCESS); 251 222 return VINF_SUCCESS; 223 } 224 225 static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostNullAudioGetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir) 226 { 227 AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN); 228 229 return PDMAUDIOBACKENDSTS_RUNNING; 230 } 231 232 static DECLCALLBACK(int) drvHostNullAudioStreamCreate(PPDMIHOSTAUDIO pInterface, 233 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 234 { 235 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 236 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 237 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 238 239 int rc; 240 if (pCfg->enmDir == PDMAUDIODIR_IN) 241 rc = nullCreateStreamIn(pInterface, pStream, pCfg, pcSamples); 242 else 243 rc = nullCreateStreamOut(pInterface, pStream, pCfg, pcSamples); 244 245 LogFlowFunc(("%s: rc=%Rrc\n", pStream->szName, rc)); 246 return rc; 247 } 248 249 static DECLCALLBACK(int) drvHostNullAudioStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 250 { 251 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 252 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 253 254 int rc; 255 if (pStream->enmDir == PDMAUDIODIR_IN) 256 rc = nullDestroyStreamIn(pInterface, pStream); 257 else 258 rc = nullDestroyStreamOut(pInterface, pStream); 259 260 return rc; 261 } 262 263 static DECLCALLBACK(int) drvHostNullAudioStreamControl(PPDMIHOSTAUDIO pInterface, 264 PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd) 265 { 266 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 267 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 268 269 Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST); 270 271 return VINF_SUCCESS; 272 } 273 274 static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostNullAudioStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 275 { 276 NOREF(pInterface); 277 NOREF(pStream); 278 279 return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED); 252 280 } 253 281 -
trunk/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp
r60925 r61157 16 16 * -------------------------------------------------------------------- 17 17 */ 18 #define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO19 #include <VBox/log.h>20 #include "DrvAudio.h"21 #include "AudioMixBuffer.h"22 23 #include "VBoxDD.h"24 25 18 #include <errno.h> 26 19 #include <fcntl.h> … … 32 25 #include <iprt/alloc.h> 33 26 #include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */ 27 28 #define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO 29 #include <VBox/log.h> 34 30 #include <VBox/vmm/pdmaudioifs.h> 31 32 #include "DrvAudio.h" 33 #include "AudioMixBuffer.h" 34 35 #include "VBoxDD.h" 35 36 36 37 /********************************************************************************************************************************* … … 80 81 { 81 82 /** Note: Always must come first! */ 82 PDMAUDIO HSTSTRMINpStreamIn;83 PDMAUDIOSTREAM pStreamIn; 83 84 int hFile; 84 85 int cFragments; … … 94 95 { 95 96 /** Note: Always must come first! */ 96 PDMAUDIO HSTSTRMOUTpStreamOut;97 PDMAUDIOSTREAM pStreamOut; 97 98 int hFile; 98 99 int cFragments; … … 333 334 } 334 335 335 static DECLCALLBACK(int) drvHostOSSAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,336 336 static int ossControlStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 337 PDMAUDIOSTREAMCMD enmStreamCmd) 337 338 { 338 339 NOREF(pInterface); 339 NOREF(p HstStrmIn);340 NOREF(pStream); 340 341 NOREF(enmStreamCmd); 341 342 … … 345 346 } 346 347 347 static DECLCALLBACK(int) drvHostOSSAudioControlOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,348 348 static int ossControlStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 349 PDMAUDIOSTREAMCMD enmStreamCmd) 349 350 { 350 351 NOREF(pInterface); 351 AssertPtrReturn(p HstStrmOut, VERR_INVALID_POINTER);352 353 POSSAUDIOSTREAMOUT pThisStr mOut = (POSSAUDIOSTREAMOUT)pHstStrmOut;352 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 353 354 POSSAUDIOSTREAMOUT pThisStream = (POSSAUDIOSTREAMOUT)pStream; 354 355 355 356 #ifdef RT_OS_L4 356 357 return VINF_SUCCESS; 357 358 #else 358 if (!pThisStr mOut->fMemMapped)359 if (!pThisStream->fMemMapped) 359 360 return VINF_SUCCESS; 360 361 #endif … … 367 368 case PDMAUDIOSTREAMCMD_RESUME: 368 369 { 369 DrvAudioClearBuf(&p HstStrmOut->Props,370 pThisStr mOut->pvBuf, pThisStrmOut->cbBuf, AudioMixBufSize(&pHstStrmOut->MixBuf));370 DrvAudioClearBuf(&pStream->Props, 371 pThisStream->pvBuf, pThisStream->cbBuf, AudioMixBufSize(&pStream->MixBuf)); 371 372 372 373 mask = PCM_ENABLE_OUTPUT; 373 if (ioctl(pThisStr mOut->hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0)374 if (ioctl(pThisStream->hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0) 374 375 { 375 376 LogRel(("OSS: Failed to enable output stream: %s\n", strerror(errno))); … … 384 385 { 385 386 mask = 0; 386 if (ioctl(pThisStr mOut->hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0)387 if (ioctl(pThisStream->hFile, SNDCTL_DSP_SETTRIGGER, &mask) < 0) 387 388 { 388 389 LogRel(("OSS: Failed to disable output stream: %s\n", strerror(errno))); … … 412 413 } 413 414 414 static DECLCALLBACK(int) drvHostOSSAudio CaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,415 uint32_t *pcSamplesCaptured)415 static DECLCALLBACK(int) drvHostOSSAudioStreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 416 uint32_t *pcSamplesCaptured) 416 417 { 417 418 NOREF(pInterface); 418 AssertPtrReturn(p HstStrmIn, VERR_INVALID_POINTER);419 420 POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)p HstStrmIn;419 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 420 421 POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pStream; 421 422 422 423 int rc = VINF_SUCCESS; 423 424 size_t cbToRead = RT_MIN(pStrm->cbBuf, 424 AudioMixBufFreeBytes(&p HstStrmIn->MixBuf));425 AudioMixBufFreeBytes(&pStream->MixBuf)); 425 426 426 427 LogFlowFunc(("cbToRead=%zu\n", cbToRead)); … … 467 468 { 468 469 uint32_t cWritten; 469 rc = AudioMixBufWriteCirc(&p HstStrmIn->MixBuf, pStrm->pvBuf, cbRead, &cWritten);470 rc = AudioMixBufWriteCirc(&pStream->MixBuf, pStrm->pvBuf, cbRead, &cWritten); 470 471 if (RT_FAILURE(rc)) 471 472 break; 472 473 473 uint32_t cbWritten = AUDIOMIXBUF_S2B(&p HstStrmIn->MixBuf, cWritten);474 uint32_t cbWritten = AUDIOMIXBUF_S2B(&pStream->MixBuf, cWritten); 474 475 475 476 Assert(cbToRead >= cbWritten); … … 489 490 uint32_t cProcessed = 0; 490 491 if (cWrittenTotal) 491 rc = AudioMixBufMixToParent(&p HstStrmIn->MixBuf, cWrittenTotal, &cProcessed);492 rc = AudioMixBufMixToParent(&pStream->MixBuf, cWrittenTotal, &cProcessed); 492 493 493 494 if (pcSamplesCaptured) … … 502 503 } 503 504 504 static DECLCALLBACK(int) drvHostOSSAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)505 static int ossDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 505 506 { 506 507 NOREF(pInterface); 507 AssertPtrReturn(p HstStrmIn, VERR_INVALID_POINTER);508 509 POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)p HstStrmIn;508 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 509 510 POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pStream; 510 511 511 512 LogFlowFuncEnter(); … … 526 527 } 527 528 528 static DECLCALLBACK(int) drvHostOSSAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)529 static int ossDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 529 530 { 530 531 NOREF(pInterface); 531 AssertPtrReturn(p HstStrmOut, VERR_INVALID_POINTER);532 533 POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)p HstStrmOut;532 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 533 534 POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pStream; 534 535 535 536 LogFlowFuncEnter(); … … 575 576 } 576 577 577 static DECLCALLBACK(int) drvHostOSSAudioGetConf (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)578 static DECLCALLBACK(int) drvHostOSSAudioGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg) 578 579 { 579 580 NOREF(pInterface); … … 645 646 } 646 647 647 static DECLCALLBACK(int) drvHostOSSAudioInitIn(PPDMIHOSTAUDIO pInterface, 648 PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg, 649 PDMAUDIORECSOURCE enmRecSource, 650 uint32_t *pcSamples) 648 static int ossCreateStreamIn(PPDMIHOSTAUDIO pInterface, 649 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 651 650 { 652 651 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 653 AssertPtrReturn(p HstStrmIn, VERR_INVALID_POINTER);652 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 654 653 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 655 654 656 655 PDRVHOSTOSSAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTOSSAUDIO(pInterface); 657 POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)p HstStrmIn;656 POSSAUDIOSTREAMIN pStrm = (POSSAUDIOSTREAMIN)pStream; 658 657 659 658 int rc; … … 674 673 if (RT_SUCCESS(rc)) 675 674 { 676 if (obtStream.cFragments * obtStream.cbFragmentSize & p HstStrmIn->Props.uAlign)675 if (obtStream.cFragments * obtStream.cbFragmentSize & pStream->Props.uAlign) 677 676 LogRel(("OSS: Warning: Misaligned capturing buffer: Size = %zu, Alignment = %u\n", 678 677 obtStream.cFragments * obtStream.cbFragmentSize, 679 p HstStrmIn->Props.uAlign + 1));678 pStream->Props.uAlign + 1)); 680 679 681 680 PDMAUDIOSTREAMCFG streamCfg; … … 685 684 streamCfg.enmEndianness = obtStream.enmENDIANNESS; 686 685 687 rc = DrvAudioStreamCfgToProps(&streamCfg, &p HstStrmIn->Props);686 rc = DrvAudioStreamCfgToProps(&streamCfg, &pStream->Props); 688 687 if (RT_SUCCESS(rc)) 689 688 { 690 689 cSamples = (obtStream.cFragments * obtStream.cbFragmentSize) 691 >> p HstStrmIn->Props.cShift;690 >> pStream->Props.cShift; 692 691 if (!cSamples) 693 692 rc = VERR_INVALID_PARAMETER; … … 697 696 if (RT_SUCCESS(rc)) 698 697 { 699 size_t cbSample = (1 << p HstStrmIn->Props.cShift);698 size_t cbSample = (1 << pStream->Props.cShift); 700 699 701 700 size_t cbBuf = cSamples * cbSample; … … 726 725 } 727 726 728 static DECLCALLBACK(int) drvHostOSSAudioInitOut(PPDMIHOSTAUDIO pInterface,729 PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg,730 727 static int ossCreateStreamOut(PPDMIHOSTAUDIO pInterface, 728 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, 729 uint32_t *pcSamples) 731 730 { 732 731 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 733 AssertPtrReturn(p HstStrmOut, VERR_INVALID_POINTER);732 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 734 733 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 735 734 736 735 PDRVHOSTOSSAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTOSSAUDIO(pInterface); 737 POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)p HstStrmOut;736 POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pStream; 738 737 739 738 int rc; … … 754 753 if (RT_SUCCESS(rc)) 755 754 { 756 if (obtStream.cFragments * obtStream.cbFragmentSize & p HstStrmOut->Props.uAlign)755 if (obtStream.cFragments * obtStream.cbFragmentSize & pStream->Props.uAlign) 757 756 LogRel(("OSS: Warning: Misaligned playback buffer: Size = %zu, Alignment = %u\n", 758 757 obtStream.cFragments * obtStream.cbFragmentSize, 759 p HstStrmOut->Props.uAlign + 1));758 pStream->Props.uAlign + 1)); 760 759 761 760 PDMAUDIOSTREAMCFG streamCfg; … … 765 764 streamCfg.enmEndianness = obtStream.enmENDIANNESS; 766 765 767 rc = DrvAudioStreamCfgToProps(&streamCfg, &p HstStrmOut->Props);766 rc = DrvAudioStreamCfgToProps(&streamCfg, &pStream->Props); 768 767 if (RT_SUCCESS(rc)) 769 768 cSamples = (obtStream.cFragments * obtStream.cbFragmentSize) 770 >> p HstStrmOut->Props.cShift;769 >> pStream->Props.cShift; 771 770 } 772 771 … … 775 774 pStrm->fMemMapped = false; 776 775 777 size_t cbSamples = cSamples << p HstStrmOut->Props.cShift;776 size_t cbSamples = cSamples << pStream->Props.cShift; 778 777 Assert(cbSamples); 779 778 … … 860 859 } 861 860 862 static DECLCALLBACK(int) drvHostOSSAudio PlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,863 uint32_t *pcSamplesPlayed)861 static DECLCALLBACK(int) drvHostOSSAudioStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 862 uint32_t *pcSamplesPlayed) 864 863 { 865 864 NOREF(pInterface); 866 AssertPtrReturn(p HstStrmOut, VERR_INVALID_POINTER);867 868 POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)p HstStrmOut;865 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 866 867 POSSAUDIOSTREAMOUT pStrm = (POSSAUDIOSTREAMOUT)pStream; 869 868 870 869 int rc = VINF_SUCCESS; … … 874 873 do 875 874 { 876 size_t cbBuf = AudioMixBufSizeBytes(&p HstStrmOut->MixBuf);877 878 uint32_t cLive = AudioMixBufAvail(&p HstStrmOut->MixBuf);875 size_t cbBuf = AudioMixBufSizeBytes(&pStream->MixBuf); 876 877 uint32_t cLive = AudioMixBufAvail(&pStream->MixBuf); 879 878 uint32_t cToRead; 880 879 … … 903 902 Assert(cbData); 904 903 905 cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&p HstStrmOut->MixBuf, cbData),904 cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pStream->MixBuf, cbData), 906 905 cLive); 907 906 } … … 932 931 } 933 932 934 cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&p HstStrmOut->MixBuf, abinfo.bytes), cLive);933 cToRead = RT_MIN((uint32_t)AUDIOMIXBUF_B2S(&pStream->MixBuf, abinfo.bytes), cLive); 935 934 if (!cToRead) 936 935 break; … … 938 937 } 939 938 #endif 940 size_t cbToRead = AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, cToRead);939 size_t cbToRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cToRead); 941 940 LogFlowFunc(("cbToRead=%zu\n", cbToRead)); 942 941 … … 944 943 while (cbToRead) 945 944 { 946 rc = AudioMixBufReadCirc(&p HstStrmOut->MixBuf, pStrm->pvBuf, cbToRead, &cRead);945 rc = AudioMixBufReadCirc(&pStream->MixBuf, pStrm->pvBuf, cbToRead, &cRead); 947 946 if (RT_FAILURE(rc)) 948 947 break; 949 948 950 cbRead = AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, cRead);949 cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead); 951 950 ssize_t cbWritten = write(pStrm->hFile, pStrm->pvBuf, cbRead); 952 951 if (cbWritten == -1) … … 972 971 if (RT_SUCCESS(rc)) 973 972 { 974 uint32_t cReadTotal = AUDIOMIXBUF_B2S(&p HstStrmOut->MixBuf, cbReadTotal);973 uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pStream->MixBuf, cbReadTotal); 975 974 if (cReadTotal) 976 AudioMixBufFinish(&p HstStrmOut->MixBuf, cReadTotal);975 AudioMixBufFinish(&pStream->MixBuf, cReadTotal); 977 976 978 977 if (pcSamplesPlayed) … … 989 988 { 990 989 NOREF(pInterface); 990 } 991 992 static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostOSSAudioGetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir) 993 { 994 AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN); 995 996 return PDMAUDIOBACKENDSTS_RUNNING; 997 } 998 999 static DECLCALLBACK(int) drvHostOSSAudioStreamCreate(PPDMIHOSTAUDIO pInterface, 1000 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 1001 { 1002 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1003 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1004 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1005 1006 int rc; 1007 if (pCfg->enmDir == PDMAUDIODIR_IN) 1008 rc = ossCreateStreamIn(pInterface, pStream, pCfg, pcSamples); 1009 else 1010 rc = ossCreateStreamOut(pInterface, pStream, pCfg, pcSamples); 1011 1012 LogFlowFunc(("%s: rc=%Rrc\n", pStream->szName, rc)); 1013 return rc; 1014 } 1015 1016 static DECLCALLBACK(int) drvHostOSSAudioStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1017 { 1018 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1019 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1020 1021 int rc; 1022 if (pStream->enmDir == PDMAUDIODIR_IN) 1023 rc = ossDestroyStreamIn(pInterface, pStream); 1024 else 1025 rc = ossDestroyStreamOut(pInterface, pStream); 1026 1027 return rc; 1028 } 1029 1030 static DECLCALLBACK(int) drvHostOSSAudioStreamControl(PPDMIHOSTAUDIO pInterface, 1031 PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd) 1032 { 1033 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1034 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1035 1036 Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST); 1037 1038 int rc; 1039 if (pStream->enmDir == PDMAUDIODIR_IN) 1040 rc = ossControlStreamIn(pInterface, pStream, enmStreamCmd); 1041 else 1042 rc = ossControlStreamOut(pInterface, pStream, enmStreamCmd); 1043 1044 return rc; 1045 } 1046 1047 static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostOSSAudioStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1048 { 1049 NOREF(pInterface); 1050 NOREF(pStream); 1051 1052 return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED); 991 1053 } 992 1054 -
trunk/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp
r61050 r61157 21 21 #define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO 22 22 #include <VBox/log.h> 23 #include <VBox/vmm/pdmaudioifs.h> 23 24 24 25 #include <stdio.h> … … 90 91 * Specify UINT32_MAX for unlimited logging. */ 91 92 uint32_t cLogErrors; 92 /** Configuration option: stream name. Optional. */93 char *pszStreamName;94 93 } DRVHOSTPULSEAUDIO, *PDRVHOSTPULSEAUDIO; 95 94 96 95 typedef struct PULSEAUDIOSTREAM 97 96 { 98 /** Must come first, as this struct might be 99 * casted to one of these structs. */ 100 union 101 { 102 PDMAUDIOHSTSTRMIN In; 103 PDMAUDIOHSTSTRMOUT Out; 104 }; 97 /** Associated host input/output stream. 98 * Note: Always must come first! */ 99 PDMAUDIOSTREAM Stream; 105 100 /** Pointer to driver instance. */ 106 101 PDRVHOSTPULSEAUDIO pDrv; … … 398 393 do 399 394 { 395 /** @todo r=andy Use pa_stream_new_with_proplist instead. */ 400 396 if (!(pStream = pa_stream_new(pThis->pContext, pszName, pSampleSpec, 401 397 NULL /* pa_channel_map */))) … … 610 606 } 611 607 612 static DECLCALLBACK(int) drvHostPulseAudioInitOut(PPDMIHOSTAUDIO pInterface, 613 PPDMAUDIOHSTSTRMOUT pHstStrmOut, PPDMAUDIOSTREAMCFG pCfg, 614 uint32_t *pcSamples) 615 { 616 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 617 AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER); 618 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 608 static int paCreateStreamOut(PPDMIHOSTAUDIO pInterface, 609 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 610 { 611 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 612 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 613 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 619 614 /* pcSamples is optional. */ 620 615 621 616 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 622 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)p HstStrmOut;617 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pStream; 623 618 624 619 LogFlowFuncEnter(); … … 641 636 642 637 /* Note that the struct BufAttr is updated to the obtained values after this call! */ 643 char achName[64]; 644 RTStrPrintf(achName, sizeof(achName), "%.32s (out)", pThis->pszStreamName); 645 646 int rc = paStreamOpen(pThis, false /* fIn */, achName, &pStrm->SampleSpec, &pStrm->BufAttr, &pStrm->pStream); 638 int rc = paStreamOpen(pThis, false /* fIn */, "PulseAudio (Out)", &pStrm->SampleSpec, &pStrm->BufAttr, &pStrm->pStream); 647 639 if (RT_FAILURE(rc)) 648 640 return rc; … … 660 652 streamCfg.cChannels = pStrm->SampleSpec.channels; 661 653 662 rc = DrvAudioStreamCfgToProps(&streamCfg, &p HstStrmOut->Props);654 rc = DrvAudioStreamCfgToProps(&streamCfg, &pStream->Props); 663 655 if (RT_SUCCESS(rc)) 664 656 { … … 672 664 pStrm->cbPCMBuf = cbBuf; 673 665 674 uint32_t cSamples = cbBuf >> p HstStrmOut->Props.cShift;666 uint32_t cSamples = cbBuf >> pStream->Props.cShift; 675 667 if (pcSamples) 676 668 *pcSamples = cSamples; … … 692 684 } 693 685 694 static DECLCALLBACK(bool) drvHostPulseAudioIsEnabled(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir) 695 { 696 NOREF(pInterface); 697 NOREF(enmDir); 698 return true; /* Always all enabled. */ 699 } 700 701 static DECLCALLBACK(int) drvHostPulseAudioInitIn(PPDMIHOSTAUDIO pInterface, 702 PPDMAUDIOHSTSTRMIN pHstStrmIn, PPDMAUDIOSTREAMCFG pCfg, 703 PDMAUDIORECSOURCE enmRecSource, 704 uint32_t *pcSamples) 686 static int paCreateStreamIn(PPDMIHOSTAUDIO pInterface, 687 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 705 688 { 706 689 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 707 AssertPtrReturn(p HstStrmIn, VERR_INVALID_POINTER);708 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);690 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 691 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 709 692 /* pcSamples is optional. */ 710 693 711 694 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 712 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pHstStrmIn; 713 714 LogFunc(("enmRecSrc=%ld\n", enmRecSource)); 695 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pStream; 715 696 716 697 pStrm->SampleSpec.format = paFmtToPulse(pCfg->enmFormat); … … 722 703 * s_pulseCfg.buffer_msecs_in) / 1000; 723 704 pStrm->BufAttr.maxlength = (pStrm->BufAttr.fragsize * 3) / 2; 724 /* Note: Other members of pa_buffer_attr are ignored for record streams. */ 725 726 char achName[64]; 727 RTStrPrintf(achName, sizeof(achName), "%.32s (in)", pThis->pszStreamName); 728 729 int rc = paStreamOpen(pThis, true /* fIn */, achName, &pStrm->SampleSpec, &pStrm->BufAttr, 705 706 /* Note: Other members of BufAttr are ignored for record streams. */ 707 int rc = paStreamOpen(pThis, true /* fIn */, "PulseAudio (In)", &pStrm->SampleSpec, &pStrm->BufAttr, 730 708 &pStrm->pStream); 731 709 if (RT_FAILURE(rc)) … … 744 722 streamCfg.cChannels = pStrm->SampleSpec.channels; 745 723 746 rc = DrvAudioStreamCfgToProps(&streamCfg, &p HstStrmIn->Props);724 rc = DrvAudioStreamCfgToProps(&streamCfg, &pStream->Props); 747 725 if (RT_SUCCESS(rc)) 748 726 { 749 727 uint32_t cSamples = RT_MIN(pStrm->BufAttr.fragsize * 10, pStrm->BufAttr.maxlength) 750 >> pHstStrmIn->Props.cShift; 751 LogFunc(("cShift=%RU8, cSamples=%RU32\n", pHstStrmIn->Props.cShift, cSamples)); 728 >> pStream->Props.cShift; 729 730 LogFunc(("uHz=%RU32, cChannels=%RU8, cShift=%RU8, cSamples=%RU32\n", 731 pStream->Props.uHz, pStream->Props.cChannels, pStream->Props.cShift, cSamples)); 752 732 753 733 if (pcSamples) … … 764 744 } 765 745 766 static DECLCALLBACK(int) drvHostPulseAudio CaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,767 uint32_t *pcSamplesCaptured)746 static DECLCALLBACK(int) drvHostPulseAudioStreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 747 uint32_t *pcSamplesCaptured) 768 748 { 769 749 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 770 AssertPtrReturn(p HstStrmIn,VERR_INVALID_POINTER);750 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 771 751 /* pcSamplesPlayed is optional. */ 772 752 773 753 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 774 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)p HstStrmIn;754 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pStream; 775 755 776 756 /* We should only call pa_stream_readable_size() once and trust the first value. */ … … 798 778 int rc = VINF_SUCCESS; 799 779 800 size_t cbToRead = RT_MIN(cbAvail, AudioMixBufFreeBytes(&p HstStrmIn->MixBuf));780 size_t cbToRead = RT_MIN(cbAvail, AudioMixBufFreeBytes(&pStream->MixBuf)); 801 781 802 782 LogFlowFunc(("cbToRead=%zu, cbAvail=%zu, offPeekBuf=%zu, cbPeekBuf=%zu\n", … … 838 818 { 839 819 uint32_t cWritten; 840 rc = AudioMixBufWriteCirc(&p HstStrmIn->MixBuf,820 rc = AudioMixBufWriteCirc(&pStream->MixBuf, 841 821 pStrm->pu8PeekBuf + pStrm->offPeekBuf, 842 822 cbToWrite, &cWritten); … … 844 824 break; 845 825 846 uint32_t cbWritten = AUDIOMIXBUF_S2B(&p HstStrmIn->MixBuf, cWritten);826 uint32_t cbWritten = AUDIOMIXBUF_S2B(&pStream->MixBuf, cWritten); 847 827 848 828 Assert(cbToRead >= cbWritten); … … 871 851 uint32_t cProcessed = 0; 872 852 if (cWrittenTotal) 873 rc = AudioMixBufMixToParent(&p HstStrmIn->MixBuf, cWrittenTotal,853 rc = AudioMixBufMixToParent(&pStream->MixBuf, cWrittenTotal, 874 854 &cProcessed); 875 855 … … 885 865 } 886 866 887 static DECLCALLBACK(int) drvHostPulseAudio PlayOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut,888 uint32_t *pcSamplesPlayed)867 static DECLCALLBACK(int) drvHostPulseAudioStreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 868 uint32_t *pcSamplesPlayed) 889 869 { 890 870 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 891 AssertPtrReturn(p HstStrmOut, VERR_INVALID_POINTER);871 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 892 872 /* pcSamplesPlayed is optional. */ 893 873 894 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);895 PPULSEAUDIOSTREAM p Strm = (PPULSEAUDIOSTREAM)pHstStrmOut;874 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 875 PPULSEAUDIOSTREAM pPAStream = (PPULSEAUDIOSTREAM)pStream; 896 876 897 877 int rc = VINF_SUCCESS; 898 878 uint32_t cbReadTotal = 0; 899 879 900 uint32_t cLive = AudioMixBufAvail(&p HstStrmOut->MixBuf);880 uint32_t cLive = AudioMixBufAvail(&pStream->MixBuf); 901 881 if (!cLive) 902 882 { 903 #if 0904 883 LogFlowFunc(("No live samples, skipping\n")); 905 #endif906 884 if (pcSamplesPlayed) 907 885 *pcSamplesPlayed = 0; … … 913 891 do 914 892 { 915 size_t cbWriteable = pa_stream_writable_size(p Strm->pStream);893 size_t cbWriteable = pa_stream_writable_size(pPAStream->pStream); 916 894 if (cbWriteable == (size_t)-1) 917 895 { 918 rc = paError(p Strm->pDrv, "Failed to determine output data size");919 break; 920 } 921 922 size_t cbLive = AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, cLive);896 rc = paError(pPAStream->pDrv, "Failed to determine output data size"); 897 break; 898 } 899 900 size_t cbLive = AUDIOMIXBUF_S2B(&pStream->MixBuf, cLive); 923 901 size_t cbToRead = RT_MIN(cbWriteable, cbLive); 924 902 … … 929 907 while (cbToRead) 930 908 { 931 rc = AudioMixBufReadCirc(&p HstStrmOut->MixBuf, pStrm->pvPCMBuf,932 RT_MIN(cbToRead, p Strm->cbPCMBuf), &cRead);909 rc = AudioMixBufReadCirc(&pStream->MixBuf, pPAStream->pvPCMBuf, 910 RT_MIN(cbToRead, pPAStream->cbPCMBuf), &cRead); 933 911 if ( !cRead 934 912 || RT_FAILURE(rc)) … … 937 915 } 938 916 939 cbRead = AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, cRead);940 if (pa_stream_write(p Strm->pStream, pStrm->pvPCMBuf, cbRead, NULL /* Cleanup callback */,917 cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead); 918 if (pa_stream_write(pPAStream->pStream, pPAStream->pvPCMBuf, cbRead, NULL /* Cleanup callback */, 941 919 0, PA_SEEK_RELATIVE) < 0) 942 920 { 943 rc = paError(p Strm->pDrv, "Failed to write to output stream");921 rc = paError(pPAStream->pDrv, "Failed to write to output stream"); 944 922 break; 945 923 } … … 950 928 951 929 LogFlowFunc(("\tcRead=%RU32 (%zu bytes) cbReadTotal=%RU32, cbToRead=%RU32\n", 952 cRead, AUDIOMIXBUF_S2B(&p HstStrmOut->MixBuf, cRead), cbReadTotal, cbToRead));930 cRead, AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead), cbReadTotal, cbToRead)); 953 931 } 954 932 … … 959 937 if (RT_SUCCESS(rc)) 960 938 { 961 uint32_t cReadTotal = AUDIOMIXBUF_B2S(&p HstStrmOut->MixBuf, cbReadTotal);939 uint32_t cReadTotal = AUDIOMIXBUF_B2S(&pStream->MixBuf, cbReadTotal); 962 940 if (cReadTotal) 963 AudioMixBufFinish(&p HstStrmOut->MixBuf, cReadTotal);941 AudioMixBufFinish(&pStream->MixBuf, cReadTotal); 964 942 965 943 if (pcSamplesPlayed) … … 1148 1126 } 1149 1127 1150 static DECLCALLBACK(int) drvHostPulseAudioFiniIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn)1128 static int paDestroyStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1151 1129 { 1152 1130 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1153 AssertPtrReturn(p HstStrmIn, VERR_INVALID_POINTER);1131 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1154 1132 1155 1133 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1156 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)p HstStrmIn;1134 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pStream; 1157 1135 1158 1136 LogFlowFuncEnter(); … … 1161 1139 { 1162 1140 pa_threaded_mainloop_lock(pThis->pMainLoop); 1141 1163 1142 pa_stream_disconnect(pStrm->pStream); 1164 1143 pa_stream_unref(pStrm->pStream); 1144 1165 1145 pa_threaded_mainloop_unlock(pThis->pMainLoop); 1166 1146 … … 1171 1151 } 1172 1152 1173 static DECLCALLBACK(int) drvHostPulseAudioFiniOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMOUT pHstStrmOut)1153 static int paDestroyStreamOut(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1174 1154 { 1175 1155 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1176 AssertPtrReturn(p HstStrmOut, VERR_INVALID_POINTER);1156 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1177 1157 1178 1158 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1179 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)p HstStrmOut;1159 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pStream; 1180 1160 1181 1161 LogFlowFuncEnter(); … … 1184 1164 { 1185 1165 pa_threaded_mainloop_lock(pThis->pMainLoop); 1166 1186 1167 pa_stream_disconnect(pStrm->pStream); 1187 1168 pa_stream_unref(pStrm->pStream); 1169 1188 1170 pa_threaded_mainloop_unlock(pThis->pMainLoop); 1189 1171 … … 1201 1183 } 1202 1184 1203 static DECLCALLBACK(int) drvHostPulseAudioControlOut(PPDMIHOSTAUDIO pInterface,1204 PPDMAUDIOHSTSTRMOUT pHstStrmOut, PDMAUDIOSTREAMCMD enmStreamCmd)1185 static int paControlStreamOut(PPDMIHOSTAUDIO pInterface, 1186 PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd) 1205 1187 { 1206 1188 AssertPtrReturn(pInterface , VERR_INVALID_POINTER); 1207 AssertPtrReturn(p HstStrmOut, VERR_INVALID_POINTER);1189 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1208 1190 1209 1191 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1210 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)p HstStrmOut;1192 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pStream; 1211 1193 1212 1194 int rc = VINF_SUCCESS; … … 1264 1246 } 1265 1247 1266 static DECLCALLBACK(int) drvHostPulseAudioControlIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn,1267 1248 static int paControlStreamIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream, 1249 PDMAUDIOSTREAMCMD enmStreamCmd) 1268 1250 { 1269 1251 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1270 AssertPtrReturn(p HstStrmIn, VERR_INVALID_POINTER);1252 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1271 1253 1272 1254 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1273 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)p HstStrmIn;1255 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pStream; 1274 1256 1275 1257 int rc = VINF_SUCCESS; … … 1312 1294 } 1313 1295 1314 static DECLCALLBACK(int) drvHostPulseAudioGetConf(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg)1315 {1316 AssertPtrReturn(pInterface, VERR_INVALID_POINTER);1317 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);1318 1319 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface);1320 1321 return paEnumerate(pThis, pCfg, PULSEAUDIOENUMCBFLAGS_LOG /* fEnum */);1322 }1323 1324 1296 static DECLCALLBACK(void) drvHostPulseAudioShutdown(PPDMIHOSTAUDIO pInterface) 1325 1297 { … … 1347 1319 1348 1320 LogFlowFuncLeave(); 1321 } 1322 1323 static DECLCALLBACK(int) drvHostPulseAudioGetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pCfg) 1324 { 1325 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1326 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1327 1328 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1329 1330 return paEnumerate(pThis, pCfg, PULSEAUDIOENUMCBFLAGS_LOG /* fEnum */); 1331 } 1332 1333 static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHostPulseAudioGetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir) 1334 { 1335 AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN); 1336 1337 return PDMAUDIOBACKENDSTS_RUNNING; 1338 } 1339 1340 static DECLCALLBACK(int) drvHostPulseAudioStreamCreate(PPDMIHOSTAUDIO pInterface, 1341 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples) 1342 { 1343 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1344 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1345 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 1346 1347 int rc; 1348 if (pCfg->enmDir == PDMAUDIODIR_IN) 1349 rc = paCreateStreamIn(pInterface, pStream, pCfg, pcSamples); 1350 else 1351 rc = paCreateStreamOut(pInterface, pStream, pCfg, pcSamples); 1352 1353 LogFlowFunc(("%s: rc=%Rrc\n", pStream->szName, rc)); 1354 return rc; 1355 } 1356 1357 static DECLCALLBACK(int) drvHostPulseAudioStreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1358 { 1359 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1360 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1361 1362 int rc; 1363 if (pStream->enmDir == PDMAUDIODIR_IN) 1364 rc = paDestroyStreamIn(pInterface, pStream); 1365 else 1366 rc = paDestroyStreamOut(pInterface, pStream); 1367 1368 return rc; 1369 } 1370 1371 static DECLCALLBACK(int) drvHostPulseAudioStreamControl(PPDMIHOSTAUDIO pInterface, 1372 PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd) 1373 { 1374 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1375 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1376 1377 Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST); 1378 1379 int rc; 1380 if (pStream->enmDir == PDMAUDIODIR_IN) 1381 rc = paControlStreamIn(pInterface, pStream, enmStreamCmd); 1382 else 1383 rc = paControlStreamOut(pInterface, pStream, enmStreamCmd); 1384 1385 return rc; 1386 } 1387 1388 static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostPulseAudioStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1389 { 1390 NOREF(pInterface); 1391 NOREF(pStream); 1392 1393 return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED); 1349 1394 } 1350 1395 … … 1377 1422 LogRel(("Audio: Initializing PulseAudio driver\n")); 1378 1423 1379 CFGMR3QueryStringAlloc(pCfg, "StreamName", &pThis->pszStreamName);1380 1381 1424 pThis->pDrvIns = pDrvIns; 1382 1425 /* IBase */ … … 1397 1440 PDRVHOSTPULSEAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPULSEAUDIO); 1398 1441 LogFlowFuncEnter(); 1399 if (pThis->pszStreamName)1400 {1401 MMR3HeapFree(pThis->pszStreamName);1402 pThis->pszStreamName = NULL;1403 }1404 1442 } 1405 1443
Note:
See TracChangeset
for help on using the changeset viewer.