Changeset 88356 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Apr 4, 2021 10:45:13 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 143603
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
r88320 r88356 64 64 65 65 #ifdef DEBUG 66 DECLINLINE(void) audioMixBufDbgPrintInternal(P PDMAUDIOMIXBUF pMixBuf, const char *pszFunc);67 DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(P PDMAUDIOMIXBUF pMixBuf);66 DECLINLINE(void) audioMixBufDbgPrintInternal(PAUDIOMIXBUF pMixBuf, const char *pszFunc); 67 DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PAUDIOMIXBUF pMixBuf); 68 68 #endif 69 69 … … 152 152 /** @todo r=bird: This isn't a 'ing Peek function, it's a Read function! 153 153 * Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaarg!!!!!!!!!!!!!!!!!!! */ 154 int AudioMixBufPeekMutable(P PDMAUDIOMIXBUF pMixBuf, uint32_t cFrames,154 int AudioMixBufPeekMutable(PAUDIOMIXBUF pMixBuf, uint32_t cFrames, 155 155 PPDMAUDIOFRAME *ppvFrames, uint32_t *pcFramesToWrite) 156 156 { … … 197 197 * 198 198 */ 199 void AudioMixBufClear(P PDMAUDIOMIXBUF pMixBuf)199 void AudioMixBufClear(PAUDIOMIXBUF pMixBuf) 200 200 { 201 201 AssertPtrReturnVoid(pMixBuf); … … 212 212 * @param cFramesToClear Number of audio frames to clear. 213 213 */ 214 void AudioMixBufFinish(P PDMAUDIOMIXBUF pMixBuf, uint32_t cFramesToClear)214 void AudioMixBufFinish(PAUDIOMIXBUF pMixBuf, uint32_t cFramesToClear) 215 215 { 216 216 AUDMIXBUF_LOG(("cFramesToClear=%RU32\n", cFramesToClear)); … … 221 221 222 222 /** @todo r=bird: Why isn't this done when reading/releaseing ? */ 223 P PDMAUDIOMIXBUF pIter;224 RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)223 PAUDIOMIXBUF pIter; 224 RTListForEach(&pMixBuf->lstChildren, pIter, AUDIOMIXBUF, Node) 225 225 { 226 226 AUDMIXBUF_LOG(("\t%s: cMixed=%RU32 -> %RU32\n", … … 271 271 * @param pMixBuf Mixing buffer to destroy. 272 272 */ 273 void AudioMixBufDestroy(P PDMAUDIOMIXBUF pMixBuf)273 void AudioMixBufDestroy(PAUDIOMIXBUF pMixBuf) 274 274 { 275 275 if (!pMixBuf) … … 278 278 /* Ignore calls for an uninitialized (zeroed) or already destroyed instance. Happens a lot. */ 279 279 if ( pMixBuf->uMagic == 0 280 || pMixBuf->uMagic == ~ PDMAUDIOMIXBUF_MAGIC)280 || pMixBuf->uMagic == ~AUDIOMIXBUF_MAGIC) 281 281 { 282 282 Assert(!pMixBuf->pszName); … … 287 287 } 288 288 289 Assert(pMixBuf->uMagic == PDMAUDIOMIXBUF_MAGIC);290 pMixBuf->uMagic = ~ PDMAUDIOMIXBUF_MAGIC;289 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC); 290 pMixBuf->uMagic = ~AUDIOMIXBUF_MAGIC; 291 291 292 292 AudioMixBufUnlink(pMixBuf); … … 323 323 * @param pMixBuf Mixing buffer to return free size for. 324 324 */ 325 uint32_t AudioMixBufFree(P PDMAUDIOMIXBUF pMixBuf)325 uint32_t AudioMixBufFree(PAUDIOMIXBUF pMixBuf) 326 326 { 327 327 AssertPtrReturn(pMixBuf, 0); … … 356 356 * @param pMixBuf Mixing buffer to return free size for. 357 357 */ 358 uint32_t AudioMixBufFreeBytes(P PDMAUDIOMIXBUF pMixBuf)358 uint32_t AudioMixBufFreeBytes(PAUDIOMIXBUF pMixBuf) 359 359 { 360 360 return AUDIOMIXBUF_F2B(pMixBuf, AudioMixBufFree(pMixBuf)); … … 368 368 * @param cFrames Number of audio frames to allocate. 369 369 */ 370 static int audioMixBufAlloc(P PDMAUDIOMIXBUF pMixBuf, uint32_t cFrames)370 static int audioMixBufAlloc(PAUDIOMIXBUF pMixBuf, uint32_t cFrames) 371 371 { 372 372 AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER); … … 424 424 \ 425 425 DECLCALLBACK(uint32_t) audioMixBufConvFrom##_aName##Stereo(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, \ 426 PC PDMAUDMIXBUFCONVOPTS pOpts) \426 PCAUDMIXBUFCONVOPTS pOpts) \ 427 427 { \ 428 428 _aType const *pSrc = (_aType const *)pvSrc; \ … … 441 441 \ 442 442 DECLCALLBACK(uint32_t) audioMixBufConvFrom##_aName##Mono(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, \ 443 PC PDMAUDMIXBUFCONVOPTS pOpts) \443 PCAUDMIXBUFCONVOPTS pOpts) \ 444 444 { \ 445 445 _aType const *pSrc = (_aType const *)pvSrc; \ … … 458 458 } \ 459 459 \ 460 DECLCALLBACK(void) audioMixBufConvTo##_aName##Stereo(void *pvDst, PCPDMAUDIOFRAME paSrc, PC PDMAUDMIXBUFCONVOPTS pOpts) \460 DECLCALLBACK(void) audioMixBufConvTo##_aName##Stereo(void *pvDst, PCPDMAUDIOFRAME paSrc, PCAUDMIXBUFCONVOPTS pOpts) \ 461 461 { \ 462 462 PCPDMAUDIOFRAME pSrc = paSrc; \ … … 474 474 } \ 475 475 \ 476 DECLCALLBACK(void) audioMixBufConvTo##_aName##Mono(void *pvDst, PCPDMAUDIOFRAME paSrc, PC PDMAUDMIXBUFCONVOPTS pOpts) \476 DECLCALLBACK(void) audioMixBufConvTo##_aName##Mono(void *pvDst, PCPDMAUDIOFRAME paSrc, PCAUDMIXBUFCONVOPTS pOpts) \ 477 477 { \ 478 478 PCPDMAUDIOFRAME pSrc = paSrc; \ … … 506 506 #if 0 507 507 DECLCALLBACK(uint32_t) audioMixBufConvFromS64Stereo(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, 508 PC PDMAUDMIXBUFCONVOPTS pOpts)508 PCAUDMIXBUFCONVOPTS pOpts) 509 509 { 510 510 _aType const *pSrc = (_aType const *)pvSrc; … … 523 523 #endif 524 524 525 DECLCALLBACK(void) audioMixBufConvToRawS64Stereo(void *pvDst, PCPDMAUDIOFRAME paSrc, PC PDMAUDMIXBUFCONVOPTS pOpts)525 DECLCALLBACK(void) audioMixBufConvToRawS64Stereo(void *pvDst, PCPDMAUDIOFRAME paSrc, PCAUDMIXBUFCONVOPTS pOpts) 526 526 { 527 527 AssertCompile(sizeof(paSrc[0]) == sizeof(int64_t) * 2); … … 535 535 static void audioMixBufOp##_aName(PPDMAUDIOFRAME paDst, uint32_t cDstFrames, \ 536 536 PPDMAUDIOFRAME paSrc, uint32_t cSrcFrames, \ 537 P PDMAUDIOSTREAMRATE pRate, \537 PAUDIOSTREAMRATE pRate, \ 538 538 uint32_t *pcDstWritten, uint32_t *pcSrcRead) \ 539 539 { \ … … 631 631 /** Dummy conversion used when the source is muted. */ 632 632 static DECLCALLBACK(uint32_t) 633 audioMixBufConvFromSilence(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, PC PDMAUDMIXBUFCONVOPTS pOpts)633 audioMixBufConvFromSilence(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, PCAUDMIXBUFCONVOPTS pOpts) 634 634 { 635 635 RT_NOREF(cbSrc, pvSrc); … … 647 647 * @param pProps The audio format to find a "from" converter for. 648 648 */ 649 static PFN PDMAUDIOMIXBUFCONVFROM audioMixBufConvFromLookup(PCPDMAUDIOPCMPROPS pProps)649 static PFNAUDIOMIXBUFCONVFROM audioMixBufConvFromLookup(PCPDMAUDIOPCMPROPS pProps) 650 650 { 651 651 if (PDMAudioPropsIsSigned(pProps)) … … 710 710 * @param pProps The audio format to find a "to" converter for. 711 711 */ 712 static PFN PDMAUDIOMIXBUFCONVTO audioMixBufConvToLookup(PCPDMAUDIOPCMPROPS pProps)712 static PFNAUDIOMIXBUFCONVTO audioMixBufConvToLookup(PCPDMAUDIOPCMPROPS pProps) 713 713 { 714 714 if (PDMAudioPropsIsSigned(pProps)) … … 773 773 * @param pVolSrc Volume to convert. 774 774 */ 775 static int audioMixBufConvVol(P PDMAUDMIXBUFVOL pVolDst, PPDMAUDIOVOLUME pVolSrc)775 static int audioMixBufConvVol(PAUDMIXBUFVOL pVolDst, PPDMAUDIOVOLUME pVolSrc) 776 776 { 777 777 if (!pVolSrc->fMuted) /* Only change/convert the volume value if we're not muted. */ … … 799 799 * @param cFrames Maximum number of audio frames the mixing buffer can hold. 800 800 */ 801 int AudioMixBufInit(P PDMAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)801 int AudioMixBufInit(PAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames) 802 802 { 803 803 AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER); … … 806 806 Assert(PDMAudioPropsAreValid(pProps)); 807 807 808 pMixBuf->uMagic = PDMAUDIOMIXBUF_MAGIC;808 pMixBuf->uMagic = AUDIOMIXBUF_MAGIC; 809 809 pMixBuf->pParent = NULL; 810 810 … … 862 862 * @param pMixBuf Mixing buffer to return value for. 863 863 */ 864 bool AudioMixBufIsEmpty(P PDMAUDIOMIXBUF pMixBuf)864 bool AudioMixBufIsEmpty(PAUDIOMIXBUF pMixBuf) 865 865 { 866 866 AssertPtrReturn(pMixBuf, true); … … 878 878 * @param pMixBufB Second mixing buffer. 879 879 */ 880 static int64_t audioMixBufCalcFreqRatio(P PDMAUDIOMIXBUF pMixBufA, PPDMAUDIOMIXBUF pMixBufB)880 static int64_t audioMixBufCalcFreqRatio(PAUDIOMIXBUF pMixBufA, PAUDIOMIXBUF pMixBufB) 881 881 { 882 882 int64_t iRatio = (int64_t)((uint64_t)PDMAudioPropsHz(&pMixBufA->Props) << 32) / PDMAudioPropsHz(&pMixBufB->Props); … … 906 906 * @remark Circular linking is not allowed. 907 907 */ 908 int AudioMixBufLinkTo(P PDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent)908 int AudioMixBufLinkTo(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUF pParent) 909 909 { 910 910 AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER); … … 969 969 if (!pMixBuf->pRate) 970 970 { 971 pMixBuf->pRate = (P PDMAUDIOSTREAMRATE)RTMemAllocZ(sizeof(PDMAUDIOSTREAMRATE));971 pMixBuf->pRate = (PAUDIOSTREAMRATE)RTMemAllocZ(sizeof(AUDIOSTREAMRATE)); 972 972 AssertReturn(pMixBuf->pRate, VERR_NO_MEMORY); 973 973 } 974 974 else 975 RT_BZERO(pMixBuf->pRate, sizeof( PDMAUDIOSTREAMRATE));975 RT_BZERO(pMixBuf->pRate, sizeof(AUDIOSTREAMRATE)); 976 976 977 977 /* … … 1008 1008 * @param pMixBuf Mixing buffer to return value for. 1009 1009 */ 1010 uint32_t AudioMixBufLive(P PDMAUDIOMIXBUF pMixBuf)1010 uint32_t AudioMixBufLive(PAUDIOMIXBUF pMixBuf) 1011 1011 { 1012 1012 AssertPtrReturn(pMixBuf, 0); … … 1051 1051 * @param pcSrcMixed Number of source audio frames successfully mixed. Optional. 1052 1052 */ 1053 static int audioMixBufMixTo(P PDMAUDIOMIXBUF pDst, PPDMAUDIOMIXBUF pSrc, uint32_t cSrcOff, uint32_t cSrcFrames,1053 static int audioMixBufMixTo(PAUDIOMIXBUF pDst, PAUDIOMIXBUF pSrc, uint32_t cSrcOff, uint32_t cSrcFrames, 1054 1054 uint32_t *pcSrcMixed) 1055 1055 { … … 1189 1189 Assert(cToRead <= pDst->cUsed); 1190 1190 1191 PDMAUDMIXBUFCONVOPTS convOpts;1191 AUDMIXBUFCONVOPTS convOpts; 1192 1192 RT_ZERO(convOpts); 1193 1193 convOpts.cFrames = cToRead; … … 1230 1230 * @param pcSrcMixed Number of source audio frames successfully mixed. Optional. 1231 1231 */ 1232 int AudioMixBufMixToParentEx(P PDMAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcFrames, uint32_t *pcSrcMixed)1232 int AudioMixBufMixToParentEx(PAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcFrames, uint32_t *pcSrcMixed) 1233 1233 { 1234 1234 AssertMsgReturn(VALID_PTR(pMixBuf->pParent), … … 1247 1247 * @param pcSrcMixed Number of source audio frames successfully mixed. Optional. 1248 1248 */ 1249 int AudioMixBufMixToParent(P PDMAUDIOMIXBUF pMixBuf, uint32_t cSrcFrames, uint32_t *pcSrcMixed)1249 int AudioMixBufMixToParent(PAUDIOMIXBUF pMixBuf, uint32_t cSrcFrames, uint32_t *pcSrcMixed) 1250 1250 { 1251 1251 return audioMixBufMixTo(pMixBuf->pParent, pMixBuf, pMixBuf->offRead, cSrcFrames, pcSrcMixed); … … 1263 1263 * @param uIdtLvl Indention level to use. 1264 1264 */ 1265 DECL_FORCE_INLINE(void) audioMixBufDbgPrintSingle(P PDMAUDIOMIXBUF pMixBuf, const char *pszFunc, bool fIsParent, uint16_t uIdtLvl)1265 DECL_FORCE_INLINE(void) audioMixBufDbgPrintSingle(PAUDIOMIXBUF pMixBuf, const char *pszFunc, bool fIsParent, uint16_t uIdtLvl) 1266 1266 { 1267 1267 Log(("%s: %*s[%s] %s: offRead=%RU32, offWrite=%RU32, cMixed=%RU32 -> %RU32/%RU32\n", … … 1276 1276 * @param pMixBuf Mixing buffer to validate. 1277 1277 */ 1278 DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(P PDMAUDIOMIXBUF pMixBuf)1278 DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PAUDIOMIXBUF pMixBuf) 1279 1279 { 1280 1280 //const uint32_t offReadEnd = (pMixBuf->offRead + pMixBuf->cUsed) % pMixBuf->cFrames; … … 1317 1317 * @param pcChildren Pointer to children counter. 1318 1318 */ 1319 DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainHelper(P PDMAUDIOMIXBUF pMixBuf, const char *pszFunc, uint16_t uIdtLvl,1319 DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainHelper(PAUDIOMIXBUF pMixBuf, const char *pszFunc, uint16_t uIdtLvl, 1320 1320 size_t *pcChildren) 1321 1321 { 1322 P PDMAUDIOMIXBUF pIter;1323 RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)1322 PAUDIOMIXBUF pIter; 1323 RTListForEach(&pMixBuf->lstChildren, pIter, AUDIOMIXBUF, Node) 1324 1324 { 1325 1325 audioMixBufDbgPrintSingle(pIter, pszFunc, false /* ifIsParent */, uIdtLvl + 1); … … 1328 1328 } 1329 1329 1330 DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainInternal(P PDMAUDIOMIXBUF pMixBuf, const char *pszFunc)1331 { 1332 P PDMAUDIOMIXBUF pParent = pMixBuf->pParent;1330 DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainInternal(PAUDIOMIXBUF pMixBuf, const char *pszFunc) 1331 { 1332 PAUDIOMIXBUF pParent = pMixBuf->pParent; 1333 1333 while (pParent) 1334 1334 { … … 1359 1359 * @param pMixBuf Mixing buffer to print. 1360 1360 */ 1361 void AudioMixBufDbgPrintChain(P PDMAUDIOMIXBUF pMixBuf)1361 void AudioMixBufDbgPrintChain(PAUDIOMIXBUF pMixBuf) 1362 1362 { 1363 1363 audioMixBufDbgPrintChainInternal(pMixBuf, __FUNCTION__); 1364 1364 } 1365 1365 1366 DECL_FORCE_INLINE(void) audioMixBufDbgPrintInternal(P PDMAUDIOMIXBUF pMixBuf, const char *pszFunc)1367 { 1368 P PDMAUDIOMIXBUF pParent = pMixBuf;1366 DECL_FORCE_INLINE(void) audioMixBufDbgPrintInternal(PAUDIOMIXBUF pMixBuf, const char *pszFunc) 1367 { 1368 PAUDIOMIXBUF pParent = pMixBuf; 1369 1369 if (pMixBuf->pParent) 1370 1370 pParent = pMixBuf->pParent; … … 1372 1372 audioMixBufDbgPrintSingle(pMixBuf, pszFunc, pParent == pMixBuf /* fIsParent */, 0 /* iIdtLevel */); 1373 1373 1374 P PDMAUDIOMIXBUF pIter;1375 RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node)1374 PAUDIOMIXBUF pIter; 1375 RTListForEach(&pMixBuf->lstChildren, pIter, AUDIOMIXBUF, Node) 1376 1376 { 1377 1377 if (pIter == pMixBuf) … … 1388 1388 * @param pMixBuf Mixing buffer to print. 1389 1389 */ 1390 void AudioMixBufDbgPrint(P PDMAUDIOMIXBUF pMixBuf)1390 void AudioMixBufDbgPrint(PAUDIOMIXBUF pMixBuf) 1391 1391 { 1392 1392 audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__); … … 1400 1400 * @param pMixBuf 1401 1401 */ 1402 uint32_t AudioMixBufUsed(P PDMAUDIOMIXBUF pMixBuf)1402 uint32_t AudioMixBufUsed(PAUDIOMIXBUF pMixBuf) 1403 1403 { 1404 1404 AssertPtrReturn(pMixBuf, 0); … … 1412 1412 * @param pMixBuf 1413 1413 */ 1414 uint32_t AudioMixBufUsedBytes(P PDMAUDIOMIXBUF pMixBuf)1414 uint32_t AudioMixBufUsedBytes(PAUDIOMIXBUF pMixBuf) 1415 1415 { 1416 1416 AssertPtrReturn(pMixBuf, 0); … … 1428 1428 * @param pcbRead Size (in bytes) of data read. Optional. 1429 1429 */ 1430 int AudioMixBufReadAt(P PDMAUDIOMIXBUF pMixBuf, uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)1430 int AudioMixBufReadAt(PAUDIOMIXBUF pMixBuf, uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead) 1431 1431 { 1432 1432 return AudioMixBufReadAtEx(pMixBuf, &pMixBuf->Props, offFrames, pvBuf, cbBuf, pcbRead); … … 1446 1446 * @param pcbRead Size (in bytes) of data read. Optional. 1447 1447 */ 1448 int AudioMixBufReadAtEx(P PDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,1448 int AudioMixBufReadAtEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps, 1449 1449 uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead) 1450 1450 { … … 1466 1466 if (cToProcess) 1467 1467 { 1468 PFN PDMAUDIOMIXBUFCONVTO pfnConvTo = NULL;1468 PFNAUDIOMIXBUFCONVTO pfnConvTo = NULL; 1469 1469 if (PDMAudioPropsAreEqual(&pMixBuf->Props, pDstProps)) 1470 1470 pfnConvTo = pMixBuf->pfnConvTo; … … 1473 1473 if (pfnConvTo) 1474 1474 { 1475 PDMAUDMIXBUFCONVOPTS convOpts;1475 AUDMIXBUFCONVOPTS convOpts; 1476 1476 RT_ZERO(convOpts); 1477 1477 /* Note: No volume handling/conversion done in the conversion-to macros (yet). */ … … 1515 1515 * the block that was acquired. 1516 1516 */ 1517 int AudioMixBufAcquireReadBlock(P PDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames)1517 int AudioMixBufAcquireReadBlock(PAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames) 1518 1518 { 1519 1519 return AudioMixBufAcquireReadBlockEx(pMixBuf, &pMixBuf->Props, pvBuf, cbBuf, pcAcquiredFrames); … … 1534 1534 * the block that was acquired. 1535 1535 */ 1536 int AudioMixBufAcquireReadBlockEx(P PDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,1536 int AudioMixBufAcquireReadBlockEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps, 1537 1537 void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames) 1538 1538 { … … 1563 1563 } 1564 1564 1565 PFN PDMAUDIOMIXBUFCONVTO pfnConvTo;1565 PFNAUDIOMIXBUFCONVTO pfnConvTo; 1566 1566 if (PDMAudioPropsAreEqual(&pMixBuf->Props, pDstProps)) 1567 1567 pfnConvTo = pMixBuf->pfnConvTo; … … 1573 1573 if (cFramesToRead) 1574 1574 { 1575 PDMAUDMIXBUFCONVOPTS convOpts;1575 AUDMIXBUFCONVOPTS convOpts; 1576 1576 RT_ZERO(convOpts); 1577 1577 convOpts.cFrames = cFramesToRead; … … 1610 1610 * acquired count.) 1611 1611 */ 1612 void AudioMixBufReleaseReadBlock(P PDMAUDIOMIXBUF pMixBuf, uint32_t cFrames)1612 void AudioMixBufReleaseReadBlock(PAUDIOMIXBUF pMixBuf, uint32_t cFrames) 1613 1613 { 1614 1614 AssertPtrReturnVoid(pMixBuf); … … 1628 1628 * @param pMixBuf Mixing buffer to return position for. 1629 1629 */ 1630 uint32_t AudioMixBufReadPos(P PDMAUDIOMIXBUF pMixBuf)1630 uint32_t AudioMixBufReadPos(PAUDIOMIXBUF pMixBuf) 1631 1631 { 1632 1632 AssertPtrReturn(pMixBuf, 0); … … 1640 1640 * @param pMixBuf Mixing buffer to reset. 1641 1641 */ 1642 void AudioMixBufReset(P PDMAUDIOMIXBUF pMixBuf)1642 void AudioMixBufReset(PAUDIOMIXBUF pMixBuf) 1643 1643 { 1644 1644 AssertPtrReturnVoid(pMixBuf); … … 1660 1660 * @param pVol Pointer to volume structure to set. 1661 1661 */ 1662 void AudioMixBufSetVolume(P PDMAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol)1662 void AudioMixBufSetVolume(PAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol) 1663 1663 { 1664 1664 AssertPtrReturnVoid(pMixBuf); … … 1677 1677 * @param pMixBuf Mixing buffer to retrieve maximum for. 1678 1678 */ 1679 uint32_t AudioMixBufSize(P PDMAUDIOMIXBUF pMixBuf)1679 uint32_t AudioMixBufSize(PAUDIOMIXBUF pMixBuf) 1680 1680 { 1681 1681 AssertPtrReturn(pMixBuf, 0); … … 1689 1689 * @param pMixBuf Mixing buffer to retrieve maximum for. 1690 1690 */ 1691 uint32_t AudioMixBufSizeBytes(P PDMAUDIOMIXBUF pMixBuf)1691 uint32_t AudioMixBufSizeBytes(PAUDIOMIXBUF pMixBuf) 1692 1692 { 1693 1693 AssertPtrReturn(pMixBuf, 0); … … 1701 1701 * @param pMixBuf Mixing buffer to unlink from parent. 1702 1702 */ 1703 void AudioMixBufUnlink(P PDMAUDIOMIXBUF pMixBuf)1703 void AudioMixBufUnlink(PAUDIOMIXBUF pMixBuf) 1704 1704 { 1705 1705 if (!pMixBuf || !pMixBuf->pszName) … … 1725 1725 } 1726 1726 1727 P PDMAUDIOMIXBUF pChild, pChildNext;1728 RTListForEachSafe(&pMixBuf->lstChildren, pChild, pChildNext, PDMAUDIOMIXBUF, Node)1727 PAUDIOMIXBUF pChild, pChildNext; 1728 RTListForEachSafe(&pMixBuf->lstChildren, pChild, pChildNext, AUDIOMIXBUF, Node) 1729 1729 { 1730 1730 AUDMIXBUF_LOG(("\tUnlinking \"%s\"\n", pChild->pszName)); … … 1767 1767 * @param pcWritten Returns number of audio frames written. Optional. 1768 1768 */ 1769 int AudioMixBufWriteAt(P PDMAUDIOMIXBUF pMixBuf, uint32_t offFrames, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)1769 int AudioMixBufWriteAt(PAUDIOMIXBUF pMixBuf, uint32_t offFrames, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten) 1770 1770 { 1771 1771 return AudioMixBufWriteAtEx(pMixBuf, &pMixBuf->Props, offFrames, pvBuf, cbBuf, pcWritten); … … 1789 1789 * @param pcWritten Returns number of audio frames written. Optional. 1790 1790 */ 1791 int AudioMixBufWriteAtEx(P PDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,1791 int AudioMixBufWriteAtEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps, 1792 1792 uint32_t offFrames, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten) 1793 1793 { … … 1826 1826 * Pick the conversion function and do the conversion. 1827 1827 */ 1828 PFN PDMAUDIOMIXBUFCONVFROM pfnConvFrom = NULL;1828 PFNAUDIOMIXBUFCONVFROM pfnConvFrom = NULL; 1829 1829 if (!pMixBuf->Volume.fMuted) 1830 1830 { … … 1843 1843 if (cToWrite) 1844 1844 { 1845 PDMAUDMIXBUFCONVOPTS convOpts;1845 AUDMIXBUFCONVOPTS convOpts; 1846 1846 1847 1847 convOpts.cFrames = cToWrite; … … 1892 1892 * @param pcWritten Returns number of audio frames written. Optional. 1893 1893 */ 1894 int AudioMixBufWriteCirc(P PDMAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)1894 int AudioMixBufWriteCirc(PAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten) 1895 1895 { 1896 1896 return AudioMixBufWriteCircEx(pMixBuf, &pMixBuf->Props, pvBuf, cbBuf, pcWritten); … … 1910 1910 * @param pcWritten Returns number of audio frames written. Optional. 1911 1911 */ 1912 int AudioMixBufWriteCircEx(P PDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,1912 int AudioMixBufWriteCircEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps, 1913 1913 const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten) 1914 1914 { … … 1930 1930 AssertPtr(pMixBuf->pFrames); 1931 1931 1932 PFN PDMAUDIOMIXBUFCONVFROM pfnConvFrom = NULL;1932 PFNAUDIOMIXBUFCONVFROM pfnConvFrom = NULL; 1933 1933 if (!pMixBuf->Volume.fMuted) 1934 1934 { … … 1955 1955 Assert(cToWrite); 1956 1956 1957 PDMAUDMIXBUFCONVOPTS convOpts;1957 AUDMIXBUFCONVOPTS convOpts; 1958 1958 convOpts.From.Volume.fMuted = pMixBuf->Volume.fMuted; 1959 1959 convOpts.From.Volume.uLeft = pMixBuf->Volume.uLeft; … … 2003 2003 * @param pMixBuf Mixing buffer to return position for. 2004 2004 */ 2005 uint32_t AudioMixBufWritePos(P PDMAUDIOMIXBUF pMixBuf)2005 uint32_t AudioMixBufWritePos(PAUDIOMIXBUF pMixBuf) 2006 2006 { 2007 2007 AssertPtrReturn(pMixBuf, 0); -
trunk/src/VBox/Devices/Audio/AudioMixBuffer.h
r88307 r88356 24 24 #include <iprt/cdefs.h> 25 25 #include <VBox/vmm/pdmaudioifs.h> 26 27 28 /** 29 * Rate processing information of a source & destination audio stream. 30 * 31 * This is needed because both streams can differ regarding their rates and 32 * therefore need to be treated accordingly. 33 */ 34 typedef struct AUDIOSTREAMRATE 35 { 36 /** Current (absolute) offset in the output (destination) stream. 37 * @todo r=bird: Please reveal which unit these members are given in. */ 38 uint64_t offDst; 39 /** Increment for moving offDst for the destination stream. 40 * This is needed because the source <-> destination rate might be different. */ 41 uint64_t uDstInc; 42 /** Current (absolute) offset in the input stream. */ 43 uint32_t offSrc; 44 /** Explicit alignment padding. */ 45 uint32_t u32AlignmentPadding; 46 /** Last processed frame of the input stream. 47 * Needed for interpolation. */ 48 PDMAUDIOFRAME SrcFrameLast; 49 } AUDIOSTREAMRATE; 50 /** Pointer to rate processing information of a stream. */ 51 typedef AUDIOSTREAMRATE *PAUDIOSTREAMRATE; 52 53 /** 54 * Mixing buffer volume parameters. 55 * 56 * The volume values are in fixed point style and must be converted to/from 57 * before using with e.g. PDMAUDIOVOLUME. 58 */ 59 typedef struct AUDMIXBUFVOL 60 { 61 /** Set to @c true if this stream is muted, @c false if not. */ 62 bool fMuted; 63 /** Left volume to apply during conversion. 64 * Pass 0 to convert the original values. May not apply to all conversion functions. */ 65 uint32_t uLeft; 66 /** Right volume to apply during conversion. 67 * Pass 0 to convert the original values. May not apply to all conversion functions. */ 68 uint32_t uRight; 69 } AUDMIXBUFVOL; 70 /** Pointer to mixing buffer volument parameters. */ 71 typedef AUDMIXBUFVOL *PAUDMIXBUFVOL; 72 73 /* 74 * Frame conversion parameters for the audioMixBufConvFromXXX / audioMixBufConvToXXX functions. 75 */ 76 typedef struct AUDMIXBUFCONVOPTS 77 { 78 /** Number of audio frames to convert. */ 79 uint32_t cFrames; 80 union 81 { 82 struct 83 { 84 /** Volume to use for conversion. */ 85 AUDMIXBUFVOL Volume; 86 } From; 87 } RT_UNION_NM(u); 88 } AUDMIXBUFCONVOPTS; 89 /** Pointer to conversion parameters for the audio mixer. */ 90 typedef AUDMIXBUFCONVOPTS *PAUDMIXBUFCONVOPTS; 91 /** Pointer to const conversion parameters for the audio mixer. */ 92 typedef AUDMIXBUFCONVOPTS const *PCAUDMIXBUFCONVOPTS; 93 94 /** 95 * @note All internal handling is done in audio frames, not in bytes! 96 * @todo r=bird: What does this note actually apply to? 97 */ 98 typedef uint32_t AUDIOMIXBUFFMT; 99 typedef AUDIOMIXBUFFMT *PAUDIOMIXBUFFMT; 100 101 /** 102 * Convertion-from function used by the audio buffer mixer. 103 * 104 * @returns Number of audio frames returned. 105 * @param paDst Where to return the converted frames. 106 * @param pvSrc The source frame bytes. 107 * @param cbSrc Number of bytes to convert. 108 * @param pOpts Conversion options. 109 * @todo r=bird: The @a paDst size is presumable given in @a pOpts->cFrames? 110 */ 111 typedef DECLCALLBACKTYPE(uint32_t, FNAUDIOMIXBUFCONVFROM,(PPDMAUDIOFRAME paDst, const void *pvSrc, uint32_t cbSrc, 112 PCAUDMIXBUFCONVOPTS pOpts)); 113 /** Pointer to a convertion-from function used by the audio buffer mixer. */ 114 typedef FNAUDIOMIXBUFCONVFROM *PFNAUDIOMIXBUFCONVFROM; 115 116 /** 117 * Convertion-to function used by the audio buffer mixer. 118 * 119 * @param pvDst Output buffer. 120 * @param paSrc The input frames. 121 * @param pOpts Conversion options. 122 * @todo r=bird: The @a paSrc size is presumable given in @a pOpts->cFrames and 123 * this implicitly gives the pvDst size too, right? 124 */ 125 typedef DECLCALLBACKTYPE(void, FNAUDIOMIXBUFCONVTO,(void *pvDst, PCPDMAUDIOFRAME paSrc, PCAUDMIXBUFCONVOPTS pOpts)); 126 /** Pointer to a convertion-to function used by the audio buffer mixer. */ 127 typedef FNAUDIOMIXBUFCONVTO *PFNAUDIOMIXBUFCONVTO; 128 129 /** Pointer to audio mixing buffer. */ 130 typedef struct AUDIOMIXBUF *PAUDIOMIXBUF; 131 132 /** 133 * Audio mixing buffer. 134 */ 135 typedef struct AUDIOMIXBUF 136 { 137 /** Magic value (AUDIOMIXBUF_MAGIC). */ 138 uint32_t uMagic; 139 uint8_t abPadding[4]; 140 /* ???Undocumented??? */ 141 RTLISTNODE Node; 142 /** Name of the buffer. */ 143 char *pszName; 144 /** Frame buffer. */ 145 PPDMAUDIOFRAME pFrames; 146 /** Size of the frame buffer (in audio frames). */ 147 uint32_t cFrames; 148 /** The current read position (in frames). */ 149 uint32_t offRead; 150 /** The current write position (in frames). */ 151 uint32_t offWrite; 152 /** Total frames already mixed down to the parent buffer (if any). 153 * 154 * Always starting at the parent's offRead position. 155 * @note Count always is specified in parent frames, as the sample count can 156 * differ between parent and child. */ 157 uint32_t cMixed; 158 /** How much audio frames are currently being used in this buffer. 159 * @note This also is known as the distance in ring buffer terms. */ 160 uint32_t cUsed; 161 /** Number of children mix buffers kept in lstChildren. */ 162 uint32_t cChildren; 163 /** List of children mix buffers to keep in sync with (if being a parent buffer). */ 164 RTLISTANCHOR lstChildren; 165 /** Pointer to parent buffer (if any). */ 166 PAUDIOMIXBUF pParent; 167 /** Intermediate structure for buffer conversion tasks. */ 168 PAUDIOSTREAMRATE pRate; 169 /** Internal representation of current volume used for mixing. */ 170 AUDMIXBUFVOL Volume; 171 /** This buffer's audio format. 172 * @todo r=bird: This seems to be a value created by AUDMIXBUF_AUDIO_FMT_MAKE(), 173 * which is not define here. Does this structure really belong here at 174 * all? */ 175 AUDIOMIXBUFFMT uAudioFmt; 176 /** Audio input properties. 177 * @note There is only one set of audio properties here because we have one 178 * mixer buffer for the guest side and a separate one for the host side. 179 * @todo r=bird: Why exactly do we need to use separate mixer buffers? 180 * Couldn't we just have different conversion fuctions and save the 181 * extra copying? */ 182 PDMAUDIOPCMPROPS Props; 183 /** Standard conversion-to function for set uAudioFmt. */ 184 PFNAUDIOMIXBUFCONVTO pfnConvTo; 185 /** Standard conversion-from function for set uAudioFmt. */ 186 PFNAUDIOMIXBUFCONVFROM pfnConvFrom; 187 188 /** Ratio of the associated parent stream's frequency by this stream's 189 * frequency (1<<32), represented as a signed 64 bit integer. 190 * 191 * For example, if the parent stream has a frequency of 44 khZ, and this 192 * stream has a frequency of 11 kHz, the ration then would be 193 * (44/11 * (1 << 32)). 194 * 195 * Currently this does not get changed once assigned. */ 196 int64_t iFreqRatio; 197 } AUDIOMIXBUF; 198 199 /** Magic value for AUDIOMIXBUF (Antonio Lucio Vivaldi). */ 200 #define AUDIOMIXBUF_MAGIC UINT32_C(0x16780304) 201 /** Dead mixer buffer magic. */ 202 #define AUDIOMIXBUF_MAGIC_DEAD UINT32_C(0x17410728) 203 26 204 27 205 /** Constructs 32 bit value for given frequency, number of channels, bits per sample and signed bit. … … 54 232 55 233 56 int AudioMixBufInit(P PDMAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames);57 void AudioMixBufDestroy(P PDMAUDIOMIXBUF pMixBuf);58 void AudioMixBufClear(P PDMAUDIOMIXBUF pMixBuf);59 void AudioMixBufFinish(P PDMAUDIOMIXBUF pMixBuf, uint32_t cFramesToClear);60 uint32_t AudioMixBufFree(P PDMAUDIOMIXBUF pMixBuf);61 uint32_t AudioMixBufFreeBytes(P PDMAUDIOMIXBUF pMixBuf);62 bool AudioMixBufIsEmpty(P PDMAUDIOMIXBUF pMixBuf);63 int AudioMixBufLinkTo(P PDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent);64 uint32_t AudioMixBufLive(P PDMAUDIOMIXBUF pMixBuf);65 int AudioMixBufMixToParent(P PDMAUDIOMIXBUF pMixBuf, uint32_t cSrcFrames, uint32_t *pcSrcMixed);66 int AudioMixBufMixToParentEx(P PDMAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcFrames, uint32_t *pcSrcMixed);67 int AudioMixBufPeekMutable(P PDMAUDIOMIXBUF pMixBuf, uint32_t cFramesToRead, PPDMAUDIOFRAME *ppvSamples, uint32_t *pcFramesRead);68 uint32_t AudioMixBufUsed(P PDMAUDIOMIXBUF pMixBuf);69 uint32_t AudioMixBufUsedBytes(P PDMAUDIOMIXBUF pMixBuf);70 int AudioMixBufReadAt(P PDMAUDIOMIXBUF pMixBuf, uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);71 int AudioMixBufReadAtEx(P PDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps, uint32_t offFrames,234 int AudioMixBufInit(PAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames); 235 void AudioMixBufDestroy(PAUDIOMIXBUF pMixBuf); 236 void AudioMixBufClear(PAUDIOMIXBUF pMixBuf); 237 void AudioMixBufFinish(PAUDIOMIXBUF pMixBuf, uint32_t cFramesToClear); 238 uint32_t AudioMixBufFree(PAUDIOMIXBUF pMixBuf); 239 uint32_t AudioMixBufFreeBytes(PAUDIOMIXBUF pMixBuf); 240 bool AudioMixBufIsEmpty(PAUDIOMIXBUF pMixBuf); 241 int AudioMixBufLinkTo(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUF pParent); 242 uint32_t AudioMixBufLive(PAUDIOMIXBUF pMixBuf); 243 int AudioMixBufMixToParent(PAUDIOMIXBUF pMixBuf, uint32_t cSrcFrames, uint32_t *pcSrcMixed); 244 int AudioMixBufMixToParentEx(PAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcFrames, uint32_t *pcSrcMixed); 245 int AudioMixBufPeekMutable(PAUDIOMIXBUF pMixBuf, uint32_t cFramesToRead, PPDMAUDIOFRAME *ppvSamples, uint32_t *pcFramesRead); 246 uint32_t AudioMixBufUsed(PAUDIOMIXBUF pMixBuf); 247 uint32_t AudioMixBufUsedBytes(PAUDIOMIXBUF pMixBuf); 248 int AudioMixBufReadAt(PAUDIOMIXBUF pMixBuf, uint32_t offFrames, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead); 249 int AudioMixBufReadAtEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps, uint32_t offFrames, 72 250 void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead); 73 int AudioMixBufAcquireReadBlock(P PDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames);74 int AudioMixBufAcquireReadBlockEx(P PDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps,251 int AudioMixBufAcquireReadBlock(PAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames); 252 int AudioMixBufAcquireReadBlockEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pDstProps, 75 253 void *pvBuf, uint32_t cbBuf, uint32_t *pcAcquiredFrames); 76 void AudioMixBufReleaseReadBlock(P PDMAUDIOMIXBUF pMixBuf, uint32_t cFrames);77 uint32_t AudioMixBufReadPos(P PDMAUDIOMIXBUF pMixBuf);78 void AudioMixBufReset(P PDMAUDIOMIXBUF pMixBuf);79 void AudioMixBufSetVolume(P PDMAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol);80 uint32_t AudioMixBufSize(P PDMAUDIOMIXBUF pMixBuf);81 uint32_t AudioMixBufSizeBytes(P PDMAUDIOMIXBUF pMixBuf);82 void AudioMixBufUnlink(P PDMAUDIOMIXBUF pMixBuf);83 int AudioMixBufWriteAt(P PDMAUDIOMIXBUF pMixBuf, uint32_t offSamples, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);84 int AudioMixBufWriteAtEx(P PDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps, uint32_t offFrames,254 void AudioMixBufReleaseReadBlock(PAUDIOMIXBUF pMixBuf, uint32_t cFrames); 255 uint32_t AudioMixBufReadPos(PAUDIOMIXBUF pMixBuf); 256 void AudioMixBufReset(PAUDIOMIXBUF pMixBuf); 257 void AudioMixBufSetVolume(PAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol); 258 uint32_t AudioMixBufSize(PAUDIOMIXBUF pMixBuf); 259 uint32_t AudioMixBufSizeBytes(PAUDIOMIXBUF pMixBuf); 260 void AudioMixBufUnlink(PAUDIOMIXBUF pMixBuf); 261 int AudioMixBufWriteAt(PAUDIOMIXBUF pMixBuf, uint32_t offSamples, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten); 262 int AudioMixBufWriteAtEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps, uint32_t offFrames, 85 263 const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten); 86 int AudioMixBufWriteCirc(P PDMAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);87 int AudioMixBufWriteCircEx(P PDMAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,264 int AudioMixBufWriteCirc(PAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten); 265 int AudioMixBufWriteCircEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps, 88 266 const void *pvBuf,uint32_t cbBuf, uint32_t *pcWritten); 89 uint32_t AudioMixBufWritePos(P PDMAUDIOMIXBUF pMixBuf);267 uint32_t AudioMixBufWritePos(PAUDIOMIXBUF pMixBuf); 90 268 91 269 #ifdef DEBUG 92 void AudioMixBufDbgPrint(P PDMAUDIOMIXBUF pMixBuf);93 void AudioMixBufDbgPrintChain(P PDMAUDIOMIXBUF pMixBuf);270 void AudioMixBufDbgPrint(PAUDIOMIXBUF pMixBuf); 271 void AudioMixBufDbgPrintChain(PAUDIOMIXBUF pMixBuf); 94 272 #endif 95 273 -
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r88320 r88356 651 651 */ 652 652 PPDMAUDIOSTREAM pStream; 653 rc = pConn->pfnStreamCreate(pConn, &CfgHost, pCfg, &pStream);653 rc = pConn->pfnStreamCreate(pConn, 0 /*fFlags*/, &CfgHost, pCfg, &pStream); 654 654 if (RT_SUCCESS(rc)) 655 655 { -
trunk/src/VBox/Devices/Audio/AudioMixer.h
r88320 r88356 29 29 30 30 #include <VBox/vmm/pdmaudioifs.h> 31 #include "AudioMixBuffer.h" 31 32 32 33 … … 55 56 /** Pointer to an audio mixer instance. */ 56 57 typedef AUDIOMIXER *PAUDIOMIXER; 58 57 59 58 60 /** Defines an audio mixer stream's flags. */ … … 201 203 /** This sink's mixing buffer, acting as 202 204 * a parent buffer for all streams this sink owns. */ 203 PDMAUDIOMIXBUF MixBuf;205 AUDIOMIXBUF MixBuf; 204 206 /** Scratch buffer for multiplexing / mixing. Might be NULL if not needed. */ 205 207 uint8_t *pabScratchBuf; -
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r88300 r88356 1775 1775 pCfgHost->Backend.cFramesPreBuffering = 0; 1776 1776 1777 int rc = pDrv->pConnector->pfnStreamCreate(pDrv->pConnector, pCfgHost, pCfg /* pCfgGuest */, &pDrv->Out.pStream);1777 int rc = pDrv->pConnector->pfnStreamCreate(pDrv->pConnector, 0 /*fFlags*/, pCfgHost, pCfg /* pCfgGuest */, &pDrv->Out.pStream); 1778 1778 if (RT_SUCCESS(rc)) 1779 1779 { -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r88309 r88356 65 65 int overriden; 66 66 } audio_option; 67 68 /** 69 * Audio stream context. 70 * 71 * Needed for separating data from the guest and host side (per stream). 72 */ 73 typedef struct DRVAUDIOSTREAMCTX 74 { 75 /** The stream's audio configuration. */ 76 PDMAUDIOSTREAMCFG Cfg; 77 /** This stream's mixing buffer. */ 78 AUDIOMIXBUF MixBuf; 79 } DRVAUDIOSTREAMCTX; 80 81 /** 82 * Extended stream structure. 83 */ 84 typedef struct DRVAUDIOSTREAM 85 { 86 /** The publicly visible bit. */ 87 PDMAUDIOSTREAM Core; 88 89 /** Just an extra magic to verify that we allocated the stream rather than some 90 * faked up stuff from the device (DRVAUDIOSTREAM_MAGIC). */ 91 uintptr_t uMagic; 92 93 /** List entry (some DrvAudio internal list). */ 94 RTLISTNODE ListEntry; 95 96 /** Data to backend-specific stream data. 97 * This data block will be casted by the backend to access its backend-dependent data. 98 * 99 * That way the backends do not have access to the audio connector's data. */ 100 void *pvBackend; 101 102 /** For output streams this indicates whether the stream has reached 103 * its playback threshold, e.g. is playing audio. 104 * For input streams this indicates whether the stream has enough input 105 * data to actually start reading audio. */ 106 bool fThresholdReached; 107 /** Do not use the mixing buffers (Guest::MixBuf, Host::MixBuf). */ 108 bool fNoMixBufs; 109 bool afPadding[2]; 110 111 /** Number of (re-)tries while re-initializing the stream. */ 112 uint32_t cTriesReInit; 113 114 /** The guest side of the stream. */ 115 DRVAUDIOSTREAMCTX Guest; 116 /** The host side of the stream. */ 117 DRVAUDIOSTREAMCTX Host; 118 119 120 /** Timestamp (in ns) since last trying to re-initialize. 121 * Might be 0 if has not been tried yet. */ 122 uint64_t nsLastReInit; 123 /** Timestamp (in ns) since last iteration. */ 124 uint64_t nsLastIterated; 125 /** Timestamp (in ns) since last playback / capture. */ 126 uint64_t nsLastPlayedCaptured; 127 /** Timestamp (in ns) since last read (input streams) or 128 * write (output streams). */ 129 uint64_t nsLastReadWritten; 130 131 132 /** Union for input/output specifics depending on enmDir. */ 133 union 134 { 135 /** 136 * The specifics for an audio input stream. 137 */ 138 struct 139 { 140 struct 141 { 142 /** File for writing stream reads. */ 143 PPDMAUDIOFILE pFileStreamRead; 144 /** File for writing non-interleaved captures. */ 145 PPDMAUDIOFILE pFileCaptureNonInterleaved; 146 } Dbg; 147 struct 148 { 149 STAMCOUNTER TotalFramesCaptured; 150 STAMCOUNTER AvgFramesCaptured; 151 STAMCOUNTER TotalTimesCaptured; 152 STAMCOUNTER TotalFramesRead; 153 STAMCOUNTER AvgFramesRead; 154 STAMCOUNTER TotalTimesRead; 155 } Stats; 156 } In; 157 158 /** 159 * The specifics for an audio output stream. 160 */ 161 struct 162 { 163 struct 164 { 165 /** File for writing stream writes. */ 166 PPDMAUDIOFILE pFileStreamWrite; 167 /** File for writing stream playback. */ 168 PPDMAUDIOFILE pFilePlayNonInterleaved; 169 } Dbg; 170 struct 171 { 172 STAMCOUNTER TotalFramesPlayed; 173 STAMCOUNTER AvgFramesPlayed; 174 STAMCOUNTER TotalTimesPlayed; 175 STAMCOUNTER TotalFramesWritten; 176 STAMCOUNTER AvgFramesWritten; 177 STAMCOUNTER TotalTimesWritten; 178 uint32_t cbBackendWritableBefore; 179 uint32_t cbBackendWritableAfter; 180 } Stats; 181 /** Hack alert: Max writable amount reported by the backend. 182 * This is used to aid buffer underrun detection in DrvAudio while playing. 183 * Ideally, the backend should have a method for querying number of buffered 184 * bytes instead. However this will do for now. */ 185 uint32_t cbBackendMaxWritable; 186 } Out; 187 } RT_UNION_NM(u); 188 } DRVAUDIOSTREAM; 189 /** Pointer to an extended stream structure. */ 190 typedef DRVAUDIOSTREAM *PDRVAUDIOSTREAM; 191 192 /** Value for DRVAUDIOSTREAM::uMagic (Johann Sebastian Bach). */ 193 #define DRVAUDIOSTREAM_MAGIC UINT32_C(0x16850331) 194 /** Value for DRVAUDIOSTREAM::uMagic after destruction */ 195 #define DRVAUDIOSTREAM_MAGIC_DEAD UINT32_C(0x17500728) 196 67 197 68 198 #ifdef VBOX_WITH_STATISTICS … … 152 282 /** Pointer to audio driver below us. */ 153 283 PPDMIHOSTAUDIO pHostDrvAudio; 154 /** List of audio streams . */284 /** List of audio streams (DRVAUDIOSTREAM). */ 155 285 RTLISTANCHOR lstStreams; 156 286 /** Audio configuration settings retrieved from the backend. */ … … 202 332 #endif 203 333 204 static DECLCALLBACK(int) drvAudioStreamDestroy(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream); 205 static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd); 206 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd); 207 static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq); 208 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 209 static void drvAudioStreamFree(PPDMAUDIOSTREAM pStream); 210 static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 211 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 212 static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 213 static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 214 static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 334 static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd); 335 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd); 336 static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq); 337 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx); 338 static void drvAudioStreamFree(PDRVAUDIOSTREAM pStream); 339 static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx); 340 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx); 341 static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx); 342 static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx); 215 343 216 344 … … 456 584 if (!pStream) 457 585 return VINF_SUCCESS; 586 PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream; 587 AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER); 588 AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 589 AssertReturn(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 458 590 459 591 int rc = RTCritSectEnter(&pThis->CritSect); … … 462 594 LogFlowFunc(("[%s] enmStreamCmd=%s\n", pStream->szName, PDMAudioStrmCmdGetName(enmStreamCmd))); 463 595 464 rc = drvAudioStreamControlInternal(pThis, pStream , enmStreamCmd);596 rc = drvAudioStreamControlInternal(pThis, pStreamEx, enmStreamCmd); 465 597 466 598 RTCritSectLeave(&pThis->CritSect); … … 472 604 * 473 605 * @returns VBox status code. 474 * @param pThis 475 * @param pStream 476 * @param enmStreamCmd 477 */ 478 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, P PDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)479 { 480 AssertPtr Return(pThis, VERR_INVALID_POINTER);481 AssertPtr Return(pStream, VERR_INVALID_POINTER);606 * @param pThis Pointer to driver instance. 607 * @param pStreamEx Stream to control. 608 * @param enmStreamCmd Control command. 609 */ 610 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd) 611 { 612 AssertPtr(pThis); 613 AssertPtr(pStreamEx); 482 614 483 615 #ifdef LOG_ENABLED 484 616 char szStreamSts[DRVAUDIO_STATUS_STR_MAX]; 485 617 #endif 486 LogFunc(("[%s] enmStreamCmd=%s fStatus=%s\n", pStream ->szName, PDMAudioStrmCmdGetName(enmStreamCmd),487 dbgAudioStreamStatusToStr(szStreamSts, pStream ->fStatus)));618 LogFunc(("[%s] enmStreamCmd=%s fStatus=%s\n", pStreamEx->Core.szName, PDMAudioStrmCmdGetName(enmStreamCmd), 619 dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus))); 488 620 489 621 int rc = VINF_SUCCESS; … … 493 625 case PDMAUDIOSTREAMCMD_ENABLE: 494 626 { 495 if (!(pStream ->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED))627 if (!(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED)) 496 628 { 497 629 /* Is a pending disable outstanding? Then disable first. */ 498 if (pStream ->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE)499 rc = drvAudioStreamControlInternalBackend(pThis, pStream , PDMAUDIOSTREAMCMD_DISABLE);630 if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE) 631 rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE); 500 632 501 633 if (RT_SUCCESS(rc)) 502 rc = drvAudioStreamControlInternalBackend(pThis, pStream , PDMAUDIOSTREAMCMD_ENABLE);634 rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_ENABLE); 503 635 504 636 if (RT_SUCCESS(rc)) 505 pStream ->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_ENABLED;637 pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_ENABLED; 506 638 } 507 639 break; … … 510 642 case PDMAUDIOSTREAMCMD_DISABLE: 511 643 { 512 if (pStream ->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED)644 if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED) 513 645 { 514 646 /* … … 517 649 * closing the stream. 518 650 */ 519 if (pStream ->enmDir == PDMAUDIODIR_OUT)651 if (pStreamEx->Core.enmDir == PDMAUDIODIR_OUT) 520 652 { 521 LogFunc(("[%s] Pending disable/pause\n", pStream ->szName));522 pStream ->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE;653 LogFunc(("[%s] Pending disable/pause\n", pStreamEx->Core.szName)); 654 pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE; 523 655 } 524 656 525 657 /* Can we close the host stream as well (not in pending disable mode)? */ 526 if (!(pStream ->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE))658 if (!(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE)) 527 659 { 528 rc = drvAudioStreamControlInternalBackend(pThis, pStream , PDMAUDIOSTREAMCMD_DISABLE);660 rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE); 529 661 if (RT_SUCCESS(rc)) 530 drvAudioStreamResetInternal(pThis, pStream );662 drvAudioStreamResetInternal(pThis, pStreamEx); 531 663 } 532 664 } … … 536 668 case PDMAUDIOSTREAMCMD_PAUSE: 537 669 { 538 if (!(pStream ->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED))670 if (!(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED)) 539 671 { 540 rc = drvAudioStreamControlInternalBackend(pThis, pStream , PDMAUDIOSTREAMCMD_PAUSE);672 rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_PAUSE); 541 673 if (RT_SUCCESS(rc)) 542 pStream ->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PAUSED;674 pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PAUSED; 543 675 } 544 676 break; … … 547 679 case PDMAUDIOSTREAMCMD_RESUME: 548 680 { 549 if (pStream ->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED)681 if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED) 550 682 { 551 rc = drvAudioStreamControlInternalBackend(pThis, pStream , PDMAUDIOSTREAMCMD_RESUME);683 rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_RESUME); 552 684 if (RT_SUCCESS(rc)) 553 pStream ->fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PAUSED;685 pStreamEx->Core.fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PAUSED; 554 686 } 555 687 break; … … 558 690 case PDMAUDIOSTREAMCMD_DROP: 559 691 { 560 rc = drvAudioStreamControlInternalBackend(pThis, pStream , PDMAUDIOSTREAMCMD_DROP);692 rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DROP); 561 693 if (RT_SUCCESS(rc)) 562 drvAudioStreamDropInternal(pThis, pStream );694 drvAudioStreamDropInternal(pThis, pStreamEx); 563 695 break; 564 696 } … … 570 702 571 703 if (RT_FAILURE(rc)) 572 LogFunc(("[%s] Failed with %Rrc\n", pStream ->szName, rc));704 LogFunc(("[%s] Failed with %Rrc\n", pStreamEx->Core.szName, rc)); 573 705 574 706 return rc; … … 577 709 /** 578 710 * Controls a stream's backend. 579 * If the stream has no backend available, VERR_NOT_FOUND is returned. 711 * 712 * If the stream has no backend available, VERR_NOT_FOUND is returned 713 * (bird: actually the code returns VINF_SUCCESS). 580 714 * 581 715 * @returns VBox status code. 582 * @param pThis 583 * @param pStream 584 * @param enmStreamCmd 585 */ 586 static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, P PDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)587 { 588 AssertPtr Return(pThis, VERR_INVALID_POINTER);589 AssertPtr Return(pStream, VERR_INVALID_POINTER);716 * @param pThis Pointer to driver instance. 717 * @param pStreamEx Stream to control. 718 * @param enmStreamCmd Control command. 719 */ 720 static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd) 721 { 722 AssertPtr(pThis); 723 AssertPtr(pStreamEx); 590 724 591 725 #ifdef LOG_ENABLED 592 726 char szStreamSts[DRVAUDIO_STATUS_STR_MAX]; 593 727 #endif 594 LogFlowFunc(("[%s] enmStreamCmd=%s, fStatus=%s\n", pStream ->szName, PDMAudioStrmCmdGetName(enmStreamCmd),595 dbgAudioStreamStatusToStr(szStreamSts, pStream ->fStatus)));728 LogFlowFunc(("[%s] enmStreamCmd=%s, fStatus=%s\n", pStreamEx->Core.szName, PDMAudioStrmCmdGetName(enmStreamCmd), 729 dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus))); 596 730 597 731 if (!pThis->pHostDrvAudio) /* If not lower driver is configured, bail out. */ … … 613 747 * See @bugref{9882}. 614 748 */ 615 const bool fEnabled = ( pStream ->enmDir == PDMAUDIODIR_IN749 const bool fEnabled = ( pStreamEx->Core.enmDir == PDMAUDIODIR_IN 616 750 && pThis->In.fEnabled) 617 || ( pStream ->enmDir == PDMAUDIODIR_OUT751 || ( pStreamEx->Core.enmDir == PDMAUDIODIR_OUT 618 752 && pThis->Out.fEnabled); 619 753 620 LogRel2(("Audio: %s stream '%s' in backend (%s is %s)\n", PDMAudioStrmCmdGetName(enmStreamCmd), pStream ->szName,621 PDMAudioDirGetName(pStream ->enmDir),754 LogRel2(("Audio: %s stream '%s' in backend (%s is %s)\n", PDMAudioStrmCmdGetName(enmStreamCmd), pStreamEx->Core.szName, 755 PDMAudioDirGetName(pStreamEx->Core.enmDir), 622 756 fEnabled ? "enabled" : "disabled")); 623 757 switch (enmStreamCmd) … … 626 760 { 627 761 if (fEnabled) 628 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream ->pvBackend, PDMAUDIOSTREAMCMD_ENABLE);762 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_ENABLE); 629 763 break; 630 764 } … … 632 766 case PDMAUDIOSTREAMCMD_DISABLE: 633 767 { 634 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream ->pvBackend, PDMAUDIOSTREAMCMD_DISABLE);768 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_DISABLE); 635 769 break; 636 770 } … … 639 773 { 640 774 if (fEnabled) /* Needed, as resume below also is being checked for. */ 641 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream ->pvBackend, PDMAUDIOSTREAMCMD_PAUSE);775 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_PAUSE); 642 776 break; 643 777 } … … 646 780 { 647 781 if (fEnabled) 648 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream ->pvBackend, PDMAUDIOSTREAMCMD_RESUME);782 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_RESUME); 649 783 break; 650 784 } … … 652 786 case PDMAUDIOSTREAMCMD_DRAIN: 653 787 { 654 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream ->pvBackend, PDMAUDIOSTREAMCMD_DRAIN);788 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_DRAIN); 655 789 break; 656 790 } … … 658 792 case PDMAUDIOSTREAMCMD_DROP: 659 793 { 660 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStream ->pvBackend, PDMAUDIOSTREAMCMD_DROP);794 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pStreamEx->pvBackend, PDMAUDIOSTREAMCMD_DROP); 661 795 break; 662 796 } 663 797 664 798 default: 665 { 666 AssertMsgFailed(("Command %RU32 not implemented\n", enmStreamCmd)); 667 rc = VERR_NOT_IMPLEMENTED; 668 break; 669 } 799 AssertMsgFailedReturn(("Command %RU32 not implemented\n", enmStreamCmd), VERR_INTERNAL_ERROR_2); 670 800 } 671 801 … … 676 806 && rc != VERR_AUDIO_STREAM_NOT_READY) 677 807 { 678 LogRel(("Audio: %s stream '%s' failed with %Rrc\n", PDMAudioStrmCmdGetName(enmStreamCmd), pStream ->szName, rc));679 } 680 681 LogFunc(("[%s] %s failed with %Rrc\n", pStream ->szName, PDMAudioStrmCmdGetName(enmStreamCmd), rc));808 LogRel(("Audio: %s stream '%s' failed with %Rrc\n", PDMAudioStrmCmdGetName(enmStreamCmd), pStreamEx->Core.szName, rc)); 809 } 810 811 LogFunc(("[%s] %s failed with %Rrc\n", pStreamEx->Core.szName, PDMAudioStrmCmdGetName(enmStreamCmd), rc)); 682 812 } 683 813 … … 688 818 * Frees an audio stream and its allocated resources. 689 819 * 690 * @param pStream Audio stream to free. 691 * After this call the pointer will not be valid anymore. 692 */ 693 static void drvAudioStreamFree(PPDMAUDIOSTREAM pStream) 694 { 695 if (pStream) 696 { 697 LogFunc(("[%s]\n", pStream->szName)); 698 Assert(pStream->uMagic == PDMAUDIOSTREAM_MAGIC); 699 700 pStream->uMagic = ~PDMAUDIOSTREAM_MAGIC; 701 pStream->pvBackend = NULL; 702 703 RTMemFree(pStream); 820 * @param pStreamEx Audio stream to free. After this call the pointer will 821 * not be valid anymore. 822 */ 823 static void drvAudioStreamFree(PDRVAUDIOSTREAM pStreamEx) 824 { 825 if (pStreamEx) 826 { 827 LogFunc(("[%s]\n", pStreamEx->Core.szName)); 828 Assert(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC); 829 Assert(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC); 830 831 pStreamEx->Core.uMagic = ~PDMAUDIOSTREAM_MAGIC; 832 pStreamEx->pvBackend = NULL; 833 pStreamEx->uMagic = DRVAUDIOSTREAM_MAGIC_DEAD; 834 835 RTMemFree(pStreamEx); 704 836 } 705 837 } … … 720 852 721 853 /* Mark all host streams to re-initialize. */ 722 P PDMAUDIOSTREAM pStream;723 RTListForEach(&pThis->lstStreams, pStream , PDMAUDIOSTREAM, ListEntry)724 { 725 pStream ->fStatus|= PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT;726 pStream ->cTriesReInit= 0;727 pStream ->tsLastReInitNs= 0;854 PDRVAUDIOSTREAM pStreamEx; 855 RTListForEach(&pThis->lstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry) 856 { 857 pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT; 858 pStreamEx->cTriesReInit = 0; 859 pStreamEx->nsLastReInit = 0; 728 860 } 729 861 … … 747 879 * 748 880 * @returns VBox status code. 749 * @param pThis 750 * @param pStream 751 */ 752 static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, P PDMAUDIOSTREAM pStream)753 { 754 AssertPtr Return(pThis, VERR_INVALID_POINTER);755 AssertPtr Return(pStream, VERR_INVALID_POINTER);756 757 LogFlowFunc(("[%s]\n", pStream ->szName));881 * @param pThis Pointer to driver instance. 882 * @param pStreamEx Stream to re-initialize. 883 */ 884 static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx) 885 { 886 AssertPtr(pThis); 887 AssertPtr(pStreamEx); 888 889 LogFlowFunc(("[%s]\n", pStreamEx->Core.szName)); 758 890 759 891 /* 760 892 * Gather current stream status. 761 893 */ 762 const bool fIsEnabled = RT_BOOL(pStream ->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED); /* Stream is enabled? */894 const bool fIsEnabled = RT_BOOL(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED); /* Stream is enabled? */ 763 895 764 896 /* 765 897 * Destroy and re-create stream on backend side. 766 898 */ 767 int rc = drvAudioStreamControlInternalBackend(pThis, pStream , PDMAUDIOSTREAMCMD_DISABLE);899 int rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE); 768 900 if (RT_SUCCESS(rc)) 769 901 { 770 rc = drvAudioStreamDestroyInternalBackend(pThis, pStream );902 rc = drvAudioStreamDestroyInternalBackend(pThis, pStreamEx); 771 903 if (RT_SUCCESS(rc)) 772 904 { 773 905 PDMAUDIOSTREAMCFG CfgHostAcq; 774 rc = drvAudioStreamCreateInternalBackend(pThis, pStream , &pStream->Host.Cfg, &CfgHostAcq);775 /** @todo Validate (re-)acquired configuration with pStream ->Host.Cfg? */906 rc = drvAudioStreamCreateInternalBackend(pThis, pStreamEx, &pStreamEx->Host.Cfg, &CfgHostAcq); 907 /** @todo Validate (re-)acquired configuration with pStreamEx->Core.Host.Cfg? */ 776 908 if (RT_SUCCESS(rc)) 777 909 { 778 910 #ifdef LOG_ENABLED 779 LogFunc(("[%s] Acquired host format:\n", pStream ->szName));911 LogFunc(("[%s] Acquired host format:\n", pStreamEx->Core.szName)); 780 912 PDMAudioStrmCfgLog(&CfgHostAcq); 781 913 #endif … … 785 917 786 918 /* Drop all old data. */ 787 drvAudioStreamDropInternal(pThis, pStream );919 drvAudioStreamDropInternal(pThis, pStreamEx); 788 920 789 921 /* … … 791 923 */ 792 924 if (fIsEnabled) 793 rc = drvAudioStreamControlInternalBackend(pThis, pStream , PDMAUDIOSTREAMCMD_ENABLE);925 rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_ENABLE); 794 926 795 927 if (RT_FAILURE(rc)) 796 LogRel(("Audio: Re-initializing stream '%s' failed with %Rrc\n", pStream ->szName, rc));797 798 LogFunc(("[%s] Returning %Rrc\n", pStream ->szName, rc));928 LogRel(("Audio: Re-initializing stream '%s' failed with %Rrc\n", pStreamEx->Core.szName, rc)); 929 930 LogFunc(("[%s] Returning %Rrc\n", pStreamEx->Core.szName, rc)); 799 931 return rc; 800 932 } … … 803 935 * Drops all audio data (and associated state) of a stream. 804 936 * 805 * @param pThis 806 * @param pStream 807 */ 808 static void drvAudioStreamDropInternal(PDRVAUDIO pThis, P PDMAUDIOSTREAM pStream)937 * @param pThis Pointer to driver instance. 938 * @param pStreamEx Stream to drop data for. 939 */ 940 static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx) 809 941 { 810 942 RT_NOREF(pThis); 811 943 812 LogFunc(("[%s]\n", pStream->szName)); 813 814 AudioMixBufReset(&pStream->Guest.MixBuf); 815 AudioMixBufReset(&pStream->Host.MixBuf); 816 817 pStream->tsLastIteratedNs = 0; 818 pStream->tsLastPlayedCapturedNs = 0; 819 pStream->tsLastReadWrittenNs = 0; 820 821 pStream->fThresholdReached = false; 822 } 823 824 /** 825 * Resets a given audio stream. 826 * 827 * @param pThis Pointer to driver instance. 828 * @param pStream Stream to reset. 829 */ 830 static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream) 831 { 832 drvAudioStreamDropInternal(pThis, pStream); 833 834 LogFunc(("[%s]\n", pStream->szName)); 835 836 pStream->fStatus = PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED; 837 pStream->fWarningsShown = PDMAUDIOSTREAM_WARN_FLAGS_NONE; 944 LogFunc(("[%s]\n", pStreamEx->Core.szName)); 945 946 AudioMixBufReset(&pStreamEx->Guest.MixBuf); 947 AudioMixBufReset(&pStreamEx->Host.MixBuf); 948 949 pStreamEx->fThresholdReached = false; 950 pStreamEx->nsLastIterated = 0; 951 pStreamEx->nsLastPlayedCaptured = 0; 952 pStreamEx->nsLastReadWritten = 0; 953 } 954 955 /** 956 * Resets the given audio stream. 957 * 958 * @param pThis Pointer to driver instance. 959 * @param pStreamEx Stream to reset. 960 */ 961 static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx) 962 { 963 drvAudioStreamDropInternal(pThis, pStreamEx); 964 965 LogFunc(("[%s]\n", pStreamEx->Core.szName)); 966 967 pStreamEx->Core.fStatus = PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED; 968 pStreamEx->Core.fWarningsShown = PDMAUDIOSTREAM_WARN_FLAGS_NONE; 838 969 839 970 #ifdef VBOX_WITH_STATISTICS … … 841 972 * Reset statistics. 842 973 */ 843 if (pStream ->enmDir == PDMAUDIODIR_IN)844 { 845 STAM_COUNTER_RESET(&pStream ->In.Stats.TotalFramesCaptured);846 STAM_COUNTER_RESET(&pStream ->In.Stats.TotalFramesRead);847 STAM_COUNTER_RESET(&pStream ->In.Stats.TotalTimesCaptured);848 STAM_COUNTER_RESET(&pStream ->In.Stats.TotalTimesRead);849 } 850 else if (pStream ->enmDir == PDMAUDIODIR_OUT)851 { 852 STAM_COUNTER_RESET(&pStream ->Out.Stats.TotalFramesPlayed);853 STAM_COUNTER_RESET(&pStream ->Out.Stats.TotalFramesWritten);854 STAM_COUNTER_RESET(&pStream ->Out.Stats.TotalTimesPlayed);855 STAM_COUNTER_RESET(&pStream ->Out.Stats.TotalTimesWritten);974 if (pStreamEx->Core.enmDir == PDMAUDIODIR_IN) 975 { 976 STAM_COUNTER_RESET(&pStreamEx->In.Stats.TotalFramesCaptured); 977 STAM_COUNTER_RESET(&pStreamEx->In.Stats.TotalFramesRead); 978 STAM_COUNTER_RESET(&pStreamEx->In.Stats.TotalTimesCaptured); 979 STAM_COUNTER_RESET(&pStreamEx->In.Stats.TotalTimesRead); 980 } 981 else if (pStreamEx->Core.enmDir == PDMAUDIODIR_OUT) 982 { 983 STAM_COUNTER_RESET(&pStreamEx->Out.Stats.TotalFramesPlayed); 984 STAM_COUNTER_RESET(&pStreamEx->Out.Stats.TotalFramesWritten); 985 STAM_COUNTER_RESET(&pStreamEx->Out.Stats.TotalTimesPlayed); 986 STAM_COUNTER_RESET(&pStreamEx->Out.Stats.TotalTimesWritten); 856 987 } 857 988 else … … 868 999 PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector); 869 1000 AssertPtr(pThis); 1001 1002 /* 1003 * Check input and sanity. 1004 */ 870 1005 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 871 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 872 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 873 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 1006 PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream; 1007 AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER); 1008 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 1009 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 874 1010 AssertPtrNullReturn(pcbWritten, VERR_INVALID_PARAMETER); 875 1011 876 AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT, 1012 AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 1013 AssertReturn(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 1014 AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT, 877 1015 ("Stream '%s' is not an output stream and therefore cannot be written to (direction is '%s')\n", 878 pStream ->szName, PDMAudioDirGetName(pStream->enmDir)));879 880 AssertMsg(PDMAudioPropsIsSizeAligned(&pStream ->Guest.Cfg.Props, cbBuf),881 ("Stream '%s' got a non-frame-aligned write (%RU32 bytes)\n", pStream ->szName, cbBuf));882 883 uint32_t cbWrittenTotal = 0;1016 pStreamEx->Core.szName, PDMAudioDirGetName(pStreamEx->Core.enmDir))); 1017 1018 AssertMsg(PDMAudioPropsIsSizeAligned(&pStreamEx->Guest.Cfg.Props, cbBuf), 1019 ("Stream '%s' got a non-frame-aligned write (%RU32 bytes)\n", pStreamEx->Core.szName, cbBuf)); 1020 1021 STAM_PROFILE_ADV_START(&pThis->Stats.DelayOut, out); /* (stopped in drvAudioStreamPlayLocked) */ 884 1022 885 1023 int rc = RTCritSectEnter(&pThis->CritSect); 886 1024 AssertRCReturn(rc, rc); 887 1025 888 #ifdef VBOX_WITH_STATISTICS 889 STAM_PROFILE_ADV_START(&pThis->Stats.DelayOut, out); 890 #endif 891 892 /* Whether to discard the incoming data or not. */ 893 bool fToBitBucket = false; 894 895 do 896 { 897 if (!PDMAudioStrmStatusIsReady(pStream->fStatus)) 898 { 899 rc = VERR_AUDIO_STREAM_NOT_READY; 900 break; 901 } 902 903 /* If output is disabled on a per-driver level, send data to the bit bucket instead. See @bugref{9882}. */ 904 if (!pThis->Out.fEnabled) 905 { 906 fToBitBucket = true; 907 break; 908 } 909 910 if (pThis->pHostDrvAudio) 911 { 912 /* If the backend's stream is not writable, all written data goes to /dev/null. */ 913 if (!PDMAudioStrmStatusCanWrite( 914 pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStream->pvBackend))) 1026 /* 1027 * First check that we can write to the stream, and if not, 1028 * whether to just drop the input into the bit bucket. 1029 */ 1030 if (PDMAudioStrmStatusIsReady(pStreamEx->Core.fStatus)) 1031 { 1032 if ( !pThis->Out.fEnabled /* (see @bugref{9882}) */ 1033 || pThis->pHostDrvAudio == NULL /* (we used to work this condition differently) */ 1034 || !PDMAudioStrmStatusCanWrite(pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStreamEx->pvBackend))) 1035 { 1036 Log3Func(("[%s] Backend stream %s, discarding the data\n", pStreamEx->Core.szName, 1037 !pThis->Out.fEnabled ? "disabled" : !pThis->pHostDrvAudio ? "not attached" : "not ready yet")); 1038 *pcbWritten = cbBuf; 1039 } 1040 /* 1041 * No-mixing buffer mode: Write the data directly to the backend, unless 1042 * we're prebuffering. There will be no pfnStreamPlay call in this mode. 1043 */ 1044 else if (pStreamEx->fNoMixBufs) 1045 { 1046 rc = VERR_NOT_IMPLEMENTED; 1047 } 1048 /* 1049 * Legacy mode: Here we just dump the data in the guest side mixing buffer 1050 * and then mixes it into the host side buffer. Later the device code will 1051 * make a pfnStreamPlay call which recodes the data from the host side 1052 * buffer and writes it to the host backend. 1053 */ 1054 else 1055 { 1056 uint32_t cbWrittenTotal = 0; 1057 1058 const uint32_t cbFree = AudioMixBufFreeBytes(&pStreamEx->Host.MixBuf); 1059 if (cbFree < cbBuf) 1060 LogRel2(("Audio: Lost audio output (%RU64ms, %RU32 free but needs %RU32) due to full host stream buffer '%s'\n", 1061 PDMAudioPropsBytesToMilli(&pStreamEx->Host.Cfg.Props, cbBuf - cbFree), cbFree, cbBuf, pStreamEx->Core.szName)); 1062 1063 uint32_t cbToWrite = RT_MIN(cbBuf, cbFree); 1064 if (cbToWrite) 915 1065 { 916 fToBitBucket = true; 917 break; 918 } 919 } 920 921 const uint32_t cbFree = AudioMixBufFreeBytes(&pStream->Host.MixBuf); 922 if (cbFree < cbBuf) 923 LogRel2(("Audio: Lost audio output (%RU64ms, %RU32 free but needs %RU32) due to full host stream buffer '%s'\n", 924 PDMAudioPropsBytesToMilli(&pStream->Host.Cfg.Props, cbBuf - cbFree), cbFree, cbBuf, pStream->szName)); 925 926 uint32_t cbToWrite = RT_MIN(cbBuf, cbFree); 927 if (!cbToWrite) 928 { 929 rc = VERR_BUFFER_OVERFLOW; 930 break; 931 } 932 933 /* We use the guest side mixing buffer as an intermediate buffer to do some 934 * (first) processing (if needed), so always write the incoming data at offset 0. */ 935 uint32_t cfGstWritten = 0; 936 rc = AudioMixBufWriteAt(&pStream->Guest.MixBuf, 0 /* offFrames */, pvBuf, cbToWrite, &cfGstWritten); 937 if ( RT_FAILURE(rc) 938 || !cfGstWritten) 939 { 940 AssertMsgFailed(("[%s] Write failed: cbToWrite=%RU32, cfWritten=%RU32, rc=%Rrc\n", 941 pStream->szName, cbToWrite, cfGstWritten, rc)); 942 break; 943 } 944 945 if (pThis->Out.Cfg.Dbg.fEnabled) 946 AudioHlpFileWrite(pStream->Out.Dbg.pFileStreamWrite, pvBuf, cbToWrite, 0 /* fFlags */); 947 948 uint32_t cfGstMixed = 0; 949 if (cfGstWritten) 950 { 951 int rc2 = AudioMixBufMixToParentEx(&pStream->Guest.MixBuf, 0 /* cSrcOffset */, cfGstWritten /* cSrcFrames */, 952 &cfGstMixed /* pcSrcMixed */); 953 if (RT_FAILURE(rc2)) 954 { 955 AssertMsgFailed(("[%s] Mixing failed: cbToWrite=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n", 956 pStream->szName, cbToWrite, cfGstWritten, cfGstMixed, rc2)); 1066 /* We use the guest side mixing buffer as an intermediate buffer to do some 1067 * (first) processing (if needed), so always write the incoming data at offset 0. */ 1068 uint32_t cFramesGstWritten = 0; 1069 rc = AudioMixBufWriteAt(&pStreamEx->Guest.MixBuf, 0 /* offFrames */, pvBuf, cbToWrite, &cFramesGstWritten); 1070 if (RT_SUCCESS(rc) && cFramesGstWritten > 0) 1071 { 1072 if (pThis->Out.Cfg.Dbg.fEnabled) 1073 AudioHlpFileWrite(pStreamEx->Out.Dbg.pFileStreamWrite, pvBuf, cbToWrite, 0 /* fFlags */); 1074 1075 uint32_t cFramesGstMixed = 0; 1076 if (cFramesGstWritten) 1077 { 1078 int rc2 = AudioMixBufMixToParentEx(&pStreamEx->Guest.MixBuf, 0 /* cSrcOffset */, 1079 cFramesGstWritten /* cSrcFrames */, &cFramesGstMixed /* pcSrcMixed */); 1080 if (RT_SUCCESS(rc2)) 1081 { 1082 const uint64_t tsNowNs = RTTimeNanoTS(); 1083 1084 Log3Func(("[%s] Writing %RU32 frames (%RU64ms)\n", 1085 pStreamEx->Core.szName, cFramesGstWritten, PDMAudioPropsFramesToMilli(&pStreamEx->Guest.Cfg.Props, cFramesGstWritten))); 1086 1087 Log3Func(("[%s] Last written %RU64ns (%RU64ms), now filled with %RU64ms -- %RU8%%\n", 1088 pStreamEx->Core.szName, tsNowNs - pStreamEx->nsLastReadWritten, 1089 (tsNowNs - pStreamEx->nsLastReadWritten) / RT_NS_1MS, 1090 PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, AudioMixBufUsed(&pStreamEx->Host.MixBuf)), 1091 AudioMixBufUsed(&pStreamEx->Host.MixBuf) * 100 / AudioMixBufSize(&pStreamEx->Host.MixBuf))); 1092 1093 pStreamEx->nsLastReadWritten = tsNowNs; 1094 /* Keep going. */ 1095 } 1096 else 1097 { 1098 AssertMsgFailed(("[%s] Mixing failed: cbToWrite=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n", 1099 pStreamEx->Core.szName, cbToWrite, cFramesGstWritten, cFramesGstMixed, rc2)); 1100 if (RT_SUCCESS(rc)) 1101 rc = rc2; 1102 } 1103 1104 cbWrittenTotal = AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cFramesGstWritten); 1105 1106 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesWritten, cFramesGstWritten); 1107 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesMixedOut, cFramesGstMixed); 1108 Assert(cFramesGstWritten >= cFramesGstMixed); 1109 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesLostOut, cFramesGstWritten - cFramesGstMixed); 1110 STAM_COUNTER_ADD(&pThis->Stats.TotalBytesWritten, cbWrittenTotal); 1111 1112 STAM_COUNTER_ADD(&pStreamEx->Out.Stats.TotalFramesWritten, cFramesGstWritten); 1113 STAM_COUNTER_INC(&pStreamEx->Out.Stats.TotalTimesWritten); 1114 } 1115 1116 Log3Func(("[%s] Dbg: cbBuf=%RU32, cbToWrite=%RU32, cfHstUsed=%RU32, cfHstfLive=%RU32, cFramesGstWritten=%RU32, " 1117 "cFramesGstMixed=%RU32, cbWrittenTotal=%RU32, rc=%Rrc\n", 1118 pStreamEx->Core.szName, cbBuf, cbToWrite, AudioMixBufUsed(&pStreamEx->Host.MixBuf), 1119 AudioMixBufLive(&pStreamEx->Host.MixBuf), cFramesGstWritten, cFramesGstMixed, cbWrittenTotal, rc)); 1120 } 1121 else 1122 AssertMsgFailed(("[%s] Write failed: cbToWrite=%RU32, cFramesGstWritten=%RU32, rc=%Rrc\n", 1123 pStreamEx->Core.szName, cbToWrite, cFramesGstWritten, rc)); 957 1124 } 958 1125 else 959 { 960 const uint64_t tsNowNs = RTTimeNanoTS(); 961 962 Log3Func(("[%s] Writing %RU32 frames (%RU64ms)\n", 963 pStream->szName, cfGstWritten, PDMAudioPropsFramesToMilli(&pStream->Guest.Cfg.Props, cfGstWritten))); 964 965 Log3Func(("[%s] Last written %RU64ns (%RU64ms), now filled with %RU64ms -- %RU8%%\n", 966 pStream->szName, tsNowNs - pStream->tsLastReadWrittenNs, 967 (tsNowNs - pStream->tsLastReadWrittenNs) / RT_NS_1MS, 968 PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, AudioMixBufUsed(&pStream->Host.MixBuf)), 969 AudioMixBufUsed(&pStream->Host.MixBuf) * 100 / AudioMixBufSize(&pStream->Host.MixBuf))); 970 971 pStream->tsLastReadWrittenNs = tsNowNs; 972 /* Keep going. */ 973 } 974 975 if (RT_SUCCESS(rc)) 976 rc = rc2; 977 978 cbWrittenTotal = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfGstWritten); 979 980 #ifdef VBOX_WITH_STATISTICS 981 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesWritten, cfGstWritten); 982 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesMixedOut, cfGstMixed); 983 Assert(cfGstWritten >= cfGstMixed); 984 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesLostOut, cfGstWritten - cfGstMixed); 985 STAM_COUNTER_ADD(&pThis->Stats.TotalBytesWritten, cbWrittenTotal); 986 987 STAM_COUNTER_ADD(&pStream->Out.Stats.TotalFramesWritten, cfGstWritten); 988 STAM_COUNTER_INC(&pStream->Out.Stats.TotalTimesWritten); 989 #endif 990 } 991 992 Log3Func(("[%s] Dbg: cbBuf=%RU32, cbToWrite=%RU32, cfHstUsed=%RU32, cfHstfLive=%RU32, cfGstWritten=%RU32, " 993 "cfGstMixed=%RU32, cbWrittenTotal=%RU32, rc=%Rrc\n", 994 pStream->szName, cbBuf, cbToWrite, AudioMixBufUsed(&pStream->Host.MixBuf), 995 AudioMixBufLive(&pStream->Host.MixBuf), cfGstWritten, cfGstMixed, cbWrittenTotal, rc)); 996 997 } while (0); 1126 rc = VERR_BUFFER_OVERFLOW; 1127 if (pcbWritten) 1128 *pcbWritten = cbWrittenTotal; 1129 } 1130 } 1131 else 1132 rc = VERR_AUDIO_STREAM_NOT_READY; 998 1133 999 1134 RTCritSectLeave(&pThis->CritSect); 1000 1001 if (RT_SUCCESS(rc))1002 {1003 if (fToBitBucket)1004 {1005 Log3Func(("[%s] Backend stream not ready (yet), discarding written data\n", pStream->szName));1006 cbWrittenTotal = cbBuf; /* Report all data as being written to the caller. */1007 }1008 1009 if (pcbWritten)1010 *pcbWritten = cbWrittenTotal;1011 }1012 1013 1135 return rc; 1014 1136 } … … 1021 1143 AssertPtrReturn(pInterface, UINT32_MAX); 1022 1144 AssertPtrReturn(pStream, UINT32_MAX); 1023 1024 NOREF(pInterface); 1025 1026 return ++pStream->cRefs; 1145 AssertReturn(pStream->uMagic == PDMAUDIOSTREAM_MAGIC, UINT32_MAX); 1146 AssertReturn(((PDRVAUDIOSTREAM)pStream)->uMagic == DRVAUDIOSTREAM_MAGIC, UINT32_MAX); 1147 RT_NOREF(pInterface); 1148 1149 uint32_t const cRefs = ASMAtomicIncU32(&pStream->cRefs); 1150 Assert(cRefs > 1); 1151 Assert(cRefs < _1K); 1152 1153 return cRefs; 1027 1154 } 1028 1155 … … 1034 1161 AssertPtrReturn(pInterface, UINT32_MAX); 1035 1162 AssertPtrReturn(pStream, UINT32_MAX); 1036 1037 NOREF(pInterface); 1038 1039 if (pStream->cRefs > 1) /* 1 reference always is kept by this audio driver. */ 1040 pStream->cRefs--; 1041 1042 return pStream->cRefs; 1163 AssertReturn(pStream->uMagic == PDMAUDIOSTREAM_MAGIC, UINT32_MAX); 1164 AssertReturn(((PDRVAUDIOSTREAM)pStream)->uMagic == DRVAUDIOSTREAM_MAGIC, UINT32_MAX); 1165 RT_NOREF(pInterface); 1166 1167 uint32_t cRefs = ASMAtomicDecU32(&pStream->cRefs); 1168 AssertStmt(cRefs >= 1, cRefs = ASMAtomicIncU32(&pStream->cRefs)); 1169 Assert(cRefs < _1K); 1170 1171 return cRefs; 1043 1172 } 1044 1173 … … 1050 1179 PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector); 1051 1180 AssertPtr(pThis); 1052 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1181 PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream; 1182 AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER); 1183 AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 1184 AssertReturn(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 1053 1185 1054 1186 int rc = RTCritSectEnter(&pThis->CritSect); 1055 1187 AssertRCReturn(rc, rc); 1056 1188 1057 rc = drvAudioStreamIterateInternal(pThis, pStream );1189 rc = drvAudioStreamIterateInternal(pThis, pStreamEx); 1058 1190 1059 1191 RTCritSectLeave(&pThis->CritSect); … … 1070 1202 * needed for the host device (re-)enumeration. 1071 1203 * 1072 * @param pThis 1073 * @param pStream 1074 */ 1075 static void drvAudioStreamMaybeReInit(PDRVAUDIO pThis, P PDMAUDIOSTREAM pStream)1076 { 1077 if (pStream ->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT)1204 * @param pThis Pointer to driver instance. 1205 * @param pStreamEx Stream to check and maybe re-initialize. 1206 */ 1207 static void drvAudioStreamMaybeReInit(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx) 1208 { 1209 if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT) 1078 1210 { 1079 1211 const unsigned cMaxTries = 3; /** @todo Make this configurable? */ … … 1081 1213 1082 1214 /* Throttle re-initializing streams on failure. */ 1083 if ( pStream ->cTriesReInit < cMaxTries1084 && tsNowNs - pStream ->tsLastReInitNs >= RT_NS_1SEC * pStream->cTriesReInit) /** @todo Ditto. */1215 if ( pStreamEx->cTriesReInit < cMaxTries 1216 && tsNowNs - pStreamEx->nsLastReInit >= RT_NS_1SEC * pStreamEx->cTriesReInit) /** @todo Ditto. */ 1085 1217 { 1086 1218 #ifdef VBOX_WITH_AUDIO_ENUM … … 1102 1234 #endif /* VBOX_WITH_AUDIO_ENUM */ 1103 1235 1104 int rc = drvAudioStreamReInitInternal(pThis, pStream );1236 int rc = drvAudioStreamReInitInternal(pThis, pStreamEx); 1105 1237 if (RT_FAILURE(rc)) 1106 1238 { 1107 pStream ->cTriesReInit++;1108 pStream ->tsLastReInitNs= tsNowNs;1239 pStreamEx->cTriesReInit++; 1240 pStreamEx->nsLastReInit = tsNowNs; 1109 1241 } 1110 1242 else 1111 1243 { 1112 1244 /* Remove the pending re-init flag on success. */ 1113 pStream ->fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT;1245 pStreamEx->Core.fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT; 1114 1246 } 1115 1247 } … … 1118 1250 /* Did we exceed our tries re-initializing the stream? 1119 1251 * Then this one is dead-in-the-water, so disable it for further use. */ 1120 if (pStream ->cTriesReInit == cMaxTries)1252 if (pStreamEx->cTriesReInit == cMaxTries) 1121 1253 { 1122 1254 LogRel(("Audio: Re-initializing stream '%s' exceeded maximum retries (%u), leaving as disabled\n", 1123 pStream ->szName, cMaxTries));1255 pStreamEx->Core.szName, cMaxTries)); 1124 1256 1125 1257 /* Don't try to re-initialize anymore and mark as disabled. */ 1126 pStream ->fStatus &= ~(PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT | PDMAUDIOSTREAMSTS_FLAGS_ENABLED);1258 pStreamEx->Core.fStatus &= ~(PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT | PDMAUDIOSTREAMSTS_FLAGS_ENABLED); 1127 1259 1128 1260 /* Note: Further writes to this stream go to / will be read from the bit bucket (/dev/null) from now on. */ … … 1133 1265 char szStreamSts[DRVAUDIO_STATUS_STR_MAX]; 1134 1266 #endif 1135 Log3Func(("[%s] fStatus=%s\n", pStream ->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));1267 Log3Func(("[%s] fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus))); 1136 1268 } 1137 1269 } … … 1143 1275 * 1144 1276 * @returns VBox status code. 1145 * @param pThis 1146 * @param pStream 1147 */ 1148 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, P PDMAUDIOSTREAM pStream)1277 * @param pThis Pointer to driver instance. 1278 * @param pStreamEx Stream to iterate. 1279 */ 1280 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx) 1149 1281 { 1150 1282 AssertPtrReturn(pThis, VERR_INVALID_POINTER); … … 1153 1285 return VINF_SUCCESS; 1154 1286 1155 if (!pStream)1156 return VINF_SUCCESS;1157 1158 1287 /* Is the stream scheduled for re-initialization? Do so now. */ 1159 drvAudioStreamMaybeReInit(pThis, pStream );1288 drvAudioStreamMaybeReInit(pThis, pStreamEx); 1160 1289 1161 1290 #ifdef LOG_ENABLED 1162 1291 char szStreamSts[DRVAUDIO_STATUS_STR_MAX]; 1163 1292 #endif 1164 Log3Func(("[%s] fStatus=%s\n", pStream ->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));1293 Log3Func(("[%s] fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus))); 1165 1294 1166 1295 /* Not enabled or paused? Skip iteration. */ 1167 if ( !(pStream ->fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED)1168 || (pStream ->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED))1296 if ( !(pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED) 1297 || (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED)) 1169 1298 { 1170 1299 return VINF_SUCCESS; … … 1178 1307 do 1179 1308 { 1180 rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, pStream ->pvBackend);1309 rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, pStreamEx->pvBackend); 1181 1310 if (RT_FAILURE(rc)) 1182 1311 break; 1183 1312 1184 if (pStream ->enmDir == PDMAUDIODIR_OUT)1313 if (pStreamEx->Core.enmDir == PDMAUDIODIR_OUT) 1185 1314 { 1186 1315 /* No audio frames to transfer from guest to host (anymore)? 1187 1316 * Then try closing this stream if marked so in the next block. */ 1188 const uint32_t cFramesLive = AudioMixBufLive(&pStream ->Host.MixBuf);1317 const uint32_t cFramesLive = AudioMixBufLive(&pStreamEx->Host.MixBuf); 1189 1318 fTryClosePending = cFramesLive == 0; 1190 Log3Func(("[%s] fTryClosePending=%RTbool, cFramesLive=%RU32\n", pStream ->szName, fTryClosePending, cFramesLive));1319 Log3Func(("[%s] fTryClosePending=%RTbool, cFramesLive=%RU32\n", pStreamEx->Core.szName, fTryClosePending, cFramesLive)); 1191 1320 } 1192 1321 1193 1322 /* Has the host stream marked as pending to disable? 1194 1323 * Try disabling the stream then. */ 1195 if ( pStream ->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE1324 if ( pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE 1196 1325 && fTryClosePending) 1197 1326 { 1198 1327 /* Tell the backend to drain the stream, that is, play the remaining (buffered) data 1199 1328 * on the backend side. */ 1200 rc = drvAudioStreamControlInternalBackend(pThis, pStream , PDMAUDIOSTREAMCMD_DRAIN);1329 rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DRAIN); 1201 1330 if (rc == VERR_NOT_SUPPORTED) /* Not all backends support draining. */ 1202 1331 rc = VINF_SUCCESS; 1203 1204 1332 if (RT_SUCCESS(rc)) 1205 1333 { 1206 1334 if (pThis->pHostDrvAudio->pfnStreamGetPending) /* Optional to implement. */ 1207 1335 { 1208 const uint32_t cxPending = pThis->pHostDrvAudio->pfnStreamGetPending(pThis->pHostDrvAudio, pStream ->pvBackend);1209 Log3Func(("[%s] cxPending=%RU32\n", pStream ->szName, cxPending));1336 const uint32_t cxPending = pThis->pHostDrvAudio->pfnStreamGetPending(pThis->pHostDrvAudio, pStreamEx->pvBackend); 1337 Log3Func(("[%s] cxPending=%RU32\n", pStreamEx->Core.szName, cxPending)); 1210 1338 1211 1339 /* Only try close pending if no audio data is pending on the backend-side anymore. */ … … 1215 1343 if (fTryClosePending) 1216 1344 { 1217 LogFunc(("[%s] Closing pending stream\n", pStream ->szName));1218 rc = drvAudioStreamControlInternalBackend(pThis, pStream , PDMAUDIOSTREAMCMD_DISABLE);1345 LogFunc(("[%s] Closing pending stream\n", pStreamEx->Core.szName)); 1346 rc = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE); 1219 1347 if (RT_SUCCESS(rc)) 1220 1348 { 1221 pStream ->fStatus &= ~(PDMAUDIOSTREAMSTS_FLAGS_ENABLED | PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE);1222 drvAudioStreamDropInternal(pThis, pStream );1349 pStreamEx->Core.fStatus &= ~(PDMAUDIOSTREAMSTS_FLAGS_ENABLED | PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE); 1350 drvAudioStreamDropInternal(pThis, pStreamEx); 1223 1351 } 1224 1352 else 1225 LogFunc(("[%s] Backend vetoed against closing pending input stream, rc=%Rrc\n", pStream ->szName, rc));1353 LogFunc(("[%s] Backend vetoed against closing pending input stream, rc=%Rrc\n", pStreamEx->Core.szName, rc)); 1226 1354 } 1227 1355 } … … 1231 1359 1232 1360 /* Update timestamps. */ 1233 pStream ->tsLastIteratedNs= RTTimeNanoTS();1361 pStreamEx->nsLastIterated = RTTimeNanoTS(); 1234 1362 1235 1363 if (RT_FAILURE(rc)) 1236 LogFunc(("[%s] Failed with %Rrc\n", pStream->szName, rc));1364 LogFunc(("[%s] Failed with %Rrc\n", pStreamEx->Core.szName, rc)); 1237 1365 1238 1366 return rc; … … 1244 1372 * @returns VBox status code. 1245 1373 * @param pThis The audio driver instance data. 1246 * @param pStream 1374 * @param pStreamEx The stream to play. 1247 1375 * @param cFramesToPlay Number of audio frames to play. The backend is 1248 1376 * supposed to have buffer space for this. 1249 1377 * @param pcFramesPlayed Where to return the number of audio frames played. 1250 1378 */ 1251 static int drvAudioStreamPlayDoIt(PDRVAUDIO pThis, P PDMAUDIOSTREAM pStream, uint32_t cFramesToPlay, uint32_t *pcFramesPlayed)1252 { 1253 Assert(pStream ->enmDir == PDMAUDIODIR_OUT);1379 static int drvAudioStreamPlayDoIt(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t cFramesToPlay, uint32_t *pcFramesPlayed) 1380 { 1381 Assert(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT); 1254 1382 1255 1383 /* … … 1265 1393 uint8_t abChunk[_4K]; 1266 1394 uint32_t cFramesRead = 0; 1267 rc = AudioMixBufAcquireReadBlock(&pStream ->Host.MixBuf, abChunk,1268 RT_MIN(sizeof(abChunk), AUDIOMIXBUF_F2B(&pStream ->Host.MixBuf, cFramesLeft)),1395 rc = AudioMixBufAcquireReadBlock(&pStreamEx->Host.MixBuf, abChunk, 1396 RT_MIN(sizeof(abChunk), AUDIOMIXBUF_F2B(&pStreamEx->Host.MixBuf, cFramesLeft)), 1269 1397 &cFramesRead); 1270 1398 AssertRCBreak(rc); 1271 1399 1272 uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream ->Host.MixBuf, cFramesRead);1400 uint32_t cbRead = AUDIOMIXBUF_F2B(&pStreamEx->Host.MixBuf, cFramesRead); 1273 1401 Assert(cbRead <= sizeof(abChunk)); 1274 1402 … … 1278 1406 uint32_t cFramesPlayed = 0; 1279 1407 uint32_t cbPlayed = 0; 1280 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStream ->pvBackend, abChunk, cbRead, &cbPlayed);1408 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pStreamEx->pvBackend, abChunk, cbRead, &cbPlayed); 1281 1409 if (RT_SUCCESS(rc)) 1282 1410 { 1283 1411 if (pThis->Out.Cfg.Dbg.fEnabled) 1284 AudioHlpFileWrite(pStream ->Out.Dbg.pFilePlayNonInterleaved, abChunk, cbPlayed, 0 /* fFlags */);1412 AudioHlpFileWrite(pStreamEx->Out.Dbg.pFilePlayNonInterleaved, abChunk, cbPlayed, 0 /* fFlags */); 1285 1413 1286 1414 if (cbRead != cbPlayed) 1287 1415 LogRel2(("Audio: Host stream '%s' played wrong amount (%RU32 bytes read but played %RU32)\n", 1288 pStream ->szName, cbRead, cbPlayed));1289 1290 cFramesPlayed = AUDIOMIXBUF_B2F(&pStream ->Host.MixBuf, cbPlayed);1416 pStreamEx->Core.szName, cbRead, cbPlayed)); 1417 1418 cFramesPlayed = AUDIOMIXBUF_B2F(&pStreamEx->Host.MixBuf, cbPlayed); 1291 1419 AssertStmt(cFramesLeft >= cFramesPlayed, cFramesPlayed = cFramesLeft); 1292 1420 cFramesLeft -= cFramesPlayed; 1293 1421 } 1294 1422 1295 AudioMixBufReleaseReadBlock(&pStream ->Host.MixBuf, cFramesPlayed);1423 AudioMixBufReleaseReadBlock(&pStreamEx->Host.MixBuf, cFramesPlayed); 1296 1424 1297 1425 AssertRCBreak(rc); /* (this is here for Acquire/Release symmetry - which isn't at all necessary) */ … … 1299 1427 } 1300 1428 1301 Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStream ->szName, cFramesToPlay - cFramesLeft, cFramesToPlay, rc));1429 Log3Func(("[%s] Played %RU32/%RU32 frames, rc=%Rrc\n", pStreamEx->Core.szName, cFramesToPlay - cFramesLeft, cFramesToPlay, rc)); 1302 1430 *pcFramesPlayed = cFramesToPlay - cFramesLeft; 1303 1431 return rc; … … 1307 1435 * Worker for drvAudioStreamPlay. 1308 1436 */ 1309 static int drvAudioStreamPlayLocked(PDRVAUDIO pThis, P PDMAUDIOSTREAM pStream, uint32_t *pcFramesPlayed)1437 static int drvAudioStreamPlayLocked(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t *pcFramesPlayed) 1310 1438 { 1311 1439 /* … … 1314 1442 *pcFramesPlayed = 0; 1315 1443 1316 PDMAUDIOSTREAMSTS fStrmStatus = pStream ->fStatus;1444 PDMAUDIOSTREAMSTS fStrmStatus = pStreamEx->Core.fStatus; 1317 1445 #ifdef LOG_ENABLED 1318 1446 char szStreamSts[DRVAUDIO_STATUS_STR_MAX]; 1319 1447 #endif 1320 Log3Func(("[%s] Start fStatus=%s\n", pStream ->szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus)));1448 Log3Func(("[%s] Start fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus))); 1321 1449 1322 1450 /* … … 1337 1465 * Get number of frames in the mix buffer and do some logging. 1338 1466 */ 1339 uint32_t const cFramesLive = AudioMixBufLive(&pStream ->Host.MixBuf);1467 uint32_t const cFramesLive = AudioMixBufLive(&pStreamEx->Host.MixBuf); 1340 1468 Log3Func(("[%s] Last played %'RI64 ns ago; filled with %u frm / %RU64 ms / %RU8%% total%s\n", 1341 pStream ->szName, pStream->fThresholdReached ? RTTimeNanoTS() - pStream->tsLastPlayedCapturedNs: -1, cFramesLive,1342 PDMAudioPropsFramesToMilli(&pStream ->Host.Cfg.Props, cFramesLive),1343 (100 * cFramesLive) / AudioMixBufSize(&pStream ->Host.MixBuf), pStream->fThresholdReached ? "" : ", pre-buffering"));1469 pStreamEx->Core.szName, pStreamEx->fThresholdReached ? RTTimeNanoTS() - pStreamEx->nsLastPlayedCaptured : -1, cFramesLive, 1470 PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesLive), 1471 (100 * cFramesLive) / AudioMixBufSize(&pStreamEx->Host.MixBuf), pStreamEx->fThresholdReached ? "" : ", pre-buffering")); 1344 1472 1345 1473 /* 1346 1474 * Restart pre-buffering if we're having a buffer-underrun. 1347 1475 */ 1348 if ( cFramesLive != 0 1349 || !pStream ->fThresholdReached/* or still pre-buffering. */)1476 if ( cFramesLive != 0 /* no underrun */ 1477 || !pStreamEx->fThresholdReached /* or still pre-buffering. */) 1350 1478 { /* likely */ } 1351 1479 else … … 1355 1483 some heuristics based on number of writable bytes now compared to when 1356 1484 prebuffering ended the first time around. */ 1357 uint32_t cbBuffered = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream ->pvBackend);1358 if (cbBuffered < pStream ->Out.cbBackendMaxWritable)1359 cbBuffered = pStream ->Out.cbBackendMaxWritable - cbBuffered;1485 uint32_t cbBuffered = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStreamEx->pvBackend); 1486 if (cbBuffered < pStreamEx->Out.cbBackendMaxWritable) 1487 cbBuffered = pStreamEx->Out.cbBackendMaxWritable - cbBuffered; 1360 1488 else 1361 1489 cbBuffered = 0; 1362 uint32_t cbMinBuf = PDMAudioPropsMilliToBytes(&pStream ->Host.Cfg.Props, pStream->Guest.Cfg.Device.cMsSchedulingHint * 2);1490 uint32_t cbMinBuf = PDMAudioPropsMilliToBytes(&pStreamEx->Host.Cfg.Props, pStreamEx->Guest.Cfg.Device.cMsSchedulingHint * 2); 1363 1491 Log3Func(("Potential underrun: cbBuffered=%#x vs cbMinBuf=%#x\n", cbBuffered, cbMinBuf)); 1364 1492 if (cbBuffered < cbMinBuf) 1365 1493 { 1366 1494 LogRel2(("Audio: Buffer underrun for stream '%s' (%RI64 ms since last call, %u buffered)\n", 1367 pStream ->szName, RTTimeNanoTS() - pStream->tsLastPlayedCapturedNs, cbBuffered));1495 pStreamEx->Core.szName, RTTimeNanoTS() - pStreamEx->nsLastPlayedCaptured, cbBuffered)); 1368 1496 1369 1497 /* Re-enter the pre-buffering stage again if enabled. */ 1370 if (pStream ->Host.Cfg.Backend.cFramesPreBuffering > 0)1498 if (pStreamEx->Host.Cfg.Backend.cFramesPreBuffering > 0) 1371 1499 { 1372 pStream ->fThresholdReached = false;1500 pStreamEx->fThresholdReached = false; 1373 1501 STAM_REL_COUNTER_INC(&pThis->Out.StatsReBuffering); 1374 1502 } … … 1383 1511 uint32_t cbWritable; 1384 1512 bool fJustStarted = false; 1385 if (pStream ->fThresholdReached)1513 if (pStreamEx->fThresholdReached) 1386 1514 { 1387 1515 /* not-prebuffering, likely after a while at least */ 1388 cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream ->pvBackend);1516 cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStreamEx->pvBackend); 1389 1517 } 1390 1518 else … … 1394 1522 * Can be 0 if no pre-buffering desired. 1395 1523 */ 1396 if (cFramesLive >= pStream ->Host.Cfg.Backend.cFramesPreBuffering)1397 { 1398 LogRel2(("Audio: Stream '%s' buffering complete!\n", pStream ->szName));1399 pStream ->fThresholdReached = fJustStarted = true;1524 if (cFramesLive >= pStreamEx->Host.Cfg.Backend.cFramesPreBuffering) 1525 { 1526 LogRel2(("Audio: Stream '%s' buffering complete!\n", pStreamEx->Core.szName)); 1527 pStreamEx->fThresholdReached = fJustStarted = true; 1400 1528 } 1401 1529 /* … … 1408 1536 */ 1409 1537 else if ( cFramesLive > 0 1410 && (pStream ->fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE))1411 { 1412 LogRel2(("Audio: Stream '%s' buffering complete (short sound)!\n", pStream ->szName));1413 pStream ->fThresholdReached = fJustStarted = true;1538 && (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE)) 1539 { 1540 LogRel2(("Audio: Stream '%s' buffering complete (short sound)!\n", pStreamEx->Core.szName)); 1541 pStreamEx->fThresholdReached = fJustStarted = true; 1414 1542 } 1415 1543 /* … … 1419 1547 { 1420 1548 LogRel2(("Audio: Stream '%s' is buffering (%RU8%% complete)...\n", 1421 pStream ->szName, (100 * cFramesLive) / pStream->Host.Cfg.Backend.cFramesPreBuffering));1549 pStreamEx->Core.szName, (100 * cFramesLive) / pStreamEx->Host.Cfg.Backend.cFramesPreBuffering)); 1422 1550 return VINF_SUCCESS; 1423 1551 } 1424 1552 1425 1553 /* Hack alert! This is for the underrun detection. */ 1426 cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream ->pvBackend);1427 if (cbWritable > pStream ->Out.cbBackendMaxWritable)1428 pStream ->Out.cbBackendMaxWritable = cbWritable;1429 } 1430 pStream ->Out.Stats.cbBackendWritableBefore = cbWritable;1554 cbWritable = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStreamEx->pvBackend); 1555 if (cbWritable > pStreamEx->Out.cbBackendMaxWritable) 1556 pStreamEx->Out.cbBackendMaxWritable = cbWritable; 1557 } 1558 pStreamEx->Out.Stats.cbBackendWritableBefore = cbWritable; 1431 1559 1432 1560 /* … … 1434 1562 * Easy, as much as the host audio backend will allow us to. 1435 1563 */ 1436 uint32_t cFramesWritable = PDMAUDIOPCMPROPS_B2F(&pStream ->Host.Cfg.Props, cbWritable);1564 uint32_t cFramesWritable = PDMAUDIOPCMPROPS_B2F(&pStreamEx->Host.Cfg.Props, cbWritable); 1437 1565 uint32_t cFramesToPlay = cFramesWritable; 1438 1566 if (cFramesToPlay > cFramesLive) /* Don't try to play more than available, we don't want to block. */ … … 1440 1568 1441 1569 Log3Func(("[%s] Playing %RU32 frames (%RU64 ms), now filled with %RU64 ms -- %RU8%%\n", 1442 pStream ->szName, cFramesToPlay, PDMAudioPropsFramesToMilli(&pStream->Host.Cfg.Props, cFramesToPlay),1443 PDMAudioPropsFramesToMilli(&pStream ->Host.Cfg.Props, AudioMixBufUsed(&pStream->Host.MixBuf)),1444 AudioMixBufUsed(&pStream ->Host.MixBuf) * 100 / AudioMixBufSize(&pStream->Host.MixBuf)));1570 pStreamEx->Core.szName, cFramesToPlay, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesToPlay), 1571 PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, AudioMixBufUsed(&pStreamEx->Host.MixBuf)), 1572 AudioMixBufUsed(&pStreamEx->Host.MixBuf) * 100 / AudioMixBufSize(&pStreamEx->Host.MixBuf))); 1445 1573 1446 1574 /* … … 1451 1579 { 1452 1580 if (pThis->pHostDrvAudio->pfnStreamPlayBegin) 1453 pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, pStream ->pvBackend);1454 1455 rc = drvAudioStreamPlayDoIt(pThis, pStream , cFramesToPlay, pcFramesPlayed);1581 pThis->pHostDrvAudio->pfnStreamPlayBegin(pThis->pHostDrvAudio, pStreamEx->pvBackend); 1582 1583 rc = drvAudioStreamPlayDoIt(pThis, pStreamEx, cFramesToPlay, pcFramesPlayed); 1456 1584 1457 1585 if (pThis->pHostDrvAudio->pfnStreamPlayEnd) 1458 pThis->pHostDrvAudio->pfnStreamPlayEnd(pThis->pHostDrvAudio, pStream ->pvBackend);1459 1460 pStream ->tsLastPlayedCapturedNs= RTTimeNanoTS();1461 pStream ->Out.Stats.cbBackendWritableAfter = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio,1462 pStream->pvBackend);1586 pThis->pHostDrvAudio->pfnStreamPlayEnd(pThis->pHostDrvAudio, pStreamEx->pvBackend); 1587 1588 pStreamEx->nsLastPlayedCaptured = RTTimeNanoTS(); 1589 pStreamEx->Out.Stats.cbBackendWritableAfter = pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, 1590 pStreamEx->pvBackend); 1463 1591 } 1464 1592 else … … 1466 1594 1467 1595 Log3Func(("[%s] Live=%RU32 fr (%RU64 ms) Period=%RU32 fr (%RU64 ms) Writable=%RU32 fr (%RU64 ms) -> ToPlay=%RU32 fr (%RU64 ms) Played=%RU32 fr (%RU64 ms)%s\n", 1468 pStream ->szName,1469 cFramesLive, PDMAudioPropsFramesToMilli(&pStream ->Host.Cfg.Props, cFramesLive),1470 pStream ->Host.Cfg.Backend.cFramesPeriod,1471 PDMAudioPropsFramesToMilli(&pStream ->Host.Cfg.Props, pStream->Host.Cfg.Backend.cFramesPeriod),1472 cFramesWritable, PDMAudioPropsFramesToMilli(&pStream ->Host.Cfg.Props, cFramesWritable),1473 cFramesToPlay, PDMAudioPropsFramesToMilli(&pStream ->Host.Cfg.Props, cFramesToPlay),1474 *pcFramesPlayed, PDMAudioPropsFramesToMilli(&pStream ->Host.Cfg.Props, *pcFramesPlayed),1596 pStreamEx->Core.szName, 1597 cFramesLive, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesLive), 1598 pStreamEx->Host.Cfg.Backend.cFramesPeriod, 1599 PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, pStreamEx->Host.Cfg.Backend.cFramesPeriod), 1600 cFramesWritable, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesWritable), 1601 cFramesToPlay, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, cFramesToPlay), 1602 *pcFramesPlayed, PDMAudioPropsFramesToMilli(&pStreamEx->Host.Cfg.Props, *pcFramesPlayed), 1475 1603 fJustStarted ? "just-started" : "")); 1476 1604 RT_NOREF(fJustStarted); … … 1478 1606 if (RT_SUCCESS(rc)) 1479 1607 { 1480 AudioMixBufFinish(&pStream ->Host.MixBuf, *pcFramesPlayed);1608 AudioMixBufFinish(&pStreamEx->Host.MixBuf, *pcFramesPlayed); 1481 1609 1482 1610 STAM_PROFILE_ADV_STOP(&pThis->Stats.DelayOut, out); 1483 1611 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesOut, *pcFramesPlayed); 1484 STAM_COUNTER_ADD(&pStream ->Out.Stats.TotalFramesPlayed, *pcFramesPlayed);1485 STAM_COUNTER_INC(&pStream ->Out.Stats.TotalTimesPlayed);1612 STAM_COUNTER_ADD(&pStreamEx->Out.Stats.TotalFramesPlayed, *pcFramesPlayed); 1613 STAM_COUNTER_INC(&pStreamEx->Out.Stats.TotalTimesPlayed); 1486 1614 } 1487 1615 return rc; … … 1496 1624 PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector); 1497 1625 AssertPtr(pThis); 1498 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1626 PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream; 1627 AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER); 1499 1628 AssertPtrNullReturn(pcFramesPlayed, VERR_INVALID_POINTER); 1500 AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT, 1629 AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 1630 AssertReturn(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 1631 AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT, 1501 1632 ("Stream '%s' is not an output stream and therefore cannot be played back (direction is 0x%x)\n", 1502 pStream->szName, pStream->enmDir)); 1633 pStreamEx->Core.szName, pStreamEx->Core.enmDir)); 1634 AssertReturn(!pStreamEx->fNoMixBufs, VERR_INVALID_FUNCTION); 1503 1635 1504 1636 int rc = RTCritSectEnter(&pThis->CritSect); … … 1506 1638 1507 1639 uint32_t cFramesPlayed = 0; 1508 rc = drvAudioStreamPlayLocked(pThis, pStream , &cFramesPlayed);1640 rc = drvAudioStreamPlayLocked(pThis, pStreamEx, &cFramesPlayed); 1509 1641 1510 1642 RTCritSectLeave(&pThis->CritSect); … … 1514 1646 1515 1647 if (RT_FAILURE(rc)) 1516 LogFlowFunc(("[%s] Failed with %Rrc\n", pStream ->szName, rc));1648 LogFlowFunc(("[%s] Failed with %Rrc\n", pStreamEx->Core.szName, rc)); 1517 1649 return rc; 1518 1650 } … … 1522 1654 * 1523 1655 * @returns VBox status code. 1524 * @param pThis Driver instance. 1525 * @param pStream Stream to capture from. 1526 * @param pcfCaptured Number of (host) audio frames captured. Optional. 1527 */ 1528 static int drvAudioStreamCaptureNonInterleaved(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcfCaptured) 1529 { 1530 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1531 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1532 AssertPtrNullReturn(pcfCaptured, VERR_INVALID_POINTER); 1533 Assert(pStream->enmDir == PDMAUDIODIR_IN); 1534 Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED); 1656 * @param pThis Driver instance. 1657 * @param pStreamEx Stream to capture from. 1658 * @param pcfCaptured Number of (host) audio frames captured. 1659 */ 1660 static int drvAudioStreamCaptureNonInterleaved(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t *pcfCaptured) 1661 { 1662 Assert(pStreamEx->Core.enmDir == PDMAUDIODIR_IN); 1663 Assert(pStreamEx->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED); 1535 1664 1536 1665 /* … … 1538 1667 */ 1539 1668 AssertPtr(pThis->pHostDrvAudio->pfnStreamGetReadable); 1540 uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream ->pvBackend);1669 uint32_t cbReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStreamEx->pvBackend); 1541 1670 if (!cbReadable) 1542 Log2Func(("[%s] No readable data available\n", pStream ->szName));1543 1544 uint32_t cbFree = AudioMixBufFreeBytes(&pStream ->Guest.MixBuf); /* Parent */1671 Log2Func(("[%s] No readable data available\n", pStreamEx->Core.szName)); 1672 1673 uint32_t cbFree = AudioMixBufFreeBytes(&pStreamEx->Guest.MixBuf); /* Parent */ 1545 1674 if (!cbFree) 1546 Log2Func(("[%s] Buffer full\n", pStream ->szName));1675 Log2Func(("[%s] Buffer full\n", pStreamEx->Core.szName)); 1547 1676 1548 1677 if (cbReadable > cbFree) /* More data readable than we can store at the moment? Limit. */ … … 1558 1687 uint8_t abChunk[_4K]; 1559 1688 uint32_t cbCaptured; 1560 rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStream ->pvBackend,1689 rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStreamEx->pvBackend, 1561 1690 abChunk, RT_MIN(cbReadable, (uint32_t)sizeof(abChunk)), &cbCaptured); 1562 1691 if (RT_FAILURE(rc)) 1563 1692 { 1564 int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream , PDMAUDIOSTREAMCMD_DISABLE);1693 int rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE); 1565 1694 AssertRC(rc2); 1566 1695 break; … … 1577 1706 * (first) processing (if needed), so always write the incoming data at offset 0. */ 1578 1707 uint32_t cfHstWritten = 0; 1579 rc = AudioMixBufWriteAt(&pStream ->Host.MixBuf, 0 /* offFrames */, abChunk, cbCaptured, &cfHstWritten);1708 rc = AudioMixBufWriteAt(&pStreamEx->Host.MixBuf, 0 /* offFrames */, abChunk, cbCaptured, &cfHstWritten); 1580 1709 if ( RT_FAILURE(rc) 1581 1710 || !cfHstWritten) 1582 1711 { 1583 1712 AssertMsgFailed(("[%s] Write failed: cbCaptured=%RU32, cfHstWritten=%RU32, rc=%Rrc\n", 1584 pStream ->szName, cbCaptured, cfHstWritten, rc));1713 pStreamEx->Core.szName, cbCaptured, cfHstWritten, rc)); 1585 1714 break; 1586 1715 } 1587 1716 1588 1717 if (pThis->In.Cfg.Dbg.fEnabled) 1589 AudioHlpFileWrite(pStream ->In.Dbg.pFileCaptureNonInterleaved, abChunk, cbCaptured, 0 /* fFlags */);1718 AudioHlpFileWrite(pStreamEx->In.Dbg.pFileCaptureNonInterleaved, abChunk, cbCaptured, 0 /* fFlags */); 1590 1719 1591 1720 uint32_t cfHstMixed = 0; 1592 1721 if (cfHstWritten) 1593 1722 { 1594 int rc2 = AudioMixBufMixToParentEx(&pStream ->Host.MixBuf, 0 /* cSrcOffset */, cfHstWritten /* cSrcFrames */,1723 int rc2 = AudioMixBufMixToParentEx(&pStreamEx->Host.MixBuf, 0 /* cSrcOffset */, cfHstWritten /* cSrcFrames */, 1595 1724 &cfHstMixed /* pcSrcMixed */); 1596 1725 Log3Func(("[%s] cbCaptured=%RU32, cfWritten=%RU32, cfMixed=%RU32, rc=%Rrc\n", 1597 pStream ->szName, cbCaptured, cfHstWritten, cfHstMixed, rc2));1726 pStreamEx->Core.szName, cbCaptured, cfHstWritten, cfHstMixed, rc2)); 1598 1727 AssertRC(rc2); 1599 1728 } … … 1607 1736 { 1608 1737 if (cfCapturedTotal) 1609 Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream ->szName, cfCapturedTotal, rc));1738 Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStreamEx->Core.szName, cfCapturedTotal, rc)); 1610 1739 } 1611 1740 else 1612 LogFunc(("[%s] Capturing failed with rc=%Rrc\n", pStream ->szName, rc));1741 LogFunc(("[%s] Capturing failed with rc=%Rrc\n", pStreamEx->Core.szName, rc)); 1613 1742 1614 1743 if (pcfCaptured) … … 1626 1755 * 1627 1756 * @returns VBox status code. 1628 * @param pThis Driver instance. 1629 * @param pStream Stream to capture from. 1630 * @param pcfCaptured Number of (host) audio frames captured. Optional. 1631 */ 1632 static int drvAudioStreamCaptureRaw(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcfCaptured) 1633 { 1634 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1635 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1636 AssertPtrNullReturn(pcfCaptured, VERR_INVALID_POINTER); 1637 Assert(pStream->enmDir == PDMAUDIODIR_IN); 1638 Assert(pStream->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW); 1757 * @param pThis Driver instance. 1758 * @param pStreamEx Stream to capture from. 1759 * @param pcfCaptured Number of (host) audio frames captured. 1760 */ 1761 static int drvAudioStreamCaptureRaw(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t *pcfCaptured) 1762 { 1763 Assert(pStreamEx->Core.enmDir == PDMAUDIODIR_IN); 1764 Assert(pStreamEx->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW); 1639 1765 AssertPtr(pThis->pHostDrvAudio->pfnStreamGetReadable); 1640 1766 … … 1643 1769 */ 1644 1770 /* Note: Raw means *audio frames*, not bytes! */ 1645 uint32_t cfReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream ->pvBackend);1771 uint32_t cfReadable = pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStreamEx->pvBackend); 1646 1772 if (!cfReadable) 1647 Log2Func(("[%s] No readable data available\n", pStream ->szName));1648 1649 const uint32_t cfFree = AudioMixBufFree(&pStream ->Guest.MixBuf); /* Parent */1773 Log2Func(("[%s] No readable data available\n", pStreamEx->Core.szName)); 1774 1775 const uint32_t cfFree = AudioMixBufFree(&pStreamEx->Guest.MixBuf); /* Parent */ 1650 1776 if (!cfFree) 1651 Log2Func(("[%s] Buffer full\n", pStream ->szName));1777 Log2Func(("[%s] Buffer full\n", pStreamEx->Core.szName)); 1652 1778 1653 1779 if (cfReadable > cfFree) /* More data readable than we can store at the moment? Limit. */ … … 1663 1789 PPDMAUDIOFRAME paFrames; 1664 1790 uint32_t cfWritable; 1665 rc = AudioMixBufPeekMutable(&pStream ->Host.MixBuf, cfReadable, &paFrames, &cfWritable);1791 rc = AudioMixBufPeekMutable(&pStreamEx->Host.MixBuf, cfReadable, &paFrames, &cfWritable); 1666 1792 if ( RT_FAILURE(rc) 1667 1793 || !cfWritable) … … 1669 1795 1670 1796 uint32_t cfCaptured; 1671 rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStream ->pvBackend,1797 rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pStreamEx->pvBackend, 1672 1798 paFrames, cfWritable, &cfCaptured); 1673 1799 if (RT_FAILURE(rc)) 1674 1800 { 1675 int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream , PDMAUDIOSTREAMCMD_DISABLE);1801 int rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE); 1676 1802 AssertRC(rc2); 1677 1803 break; … … 1689 1815 if (pcfCaptured) 1690 1816 *pcfCaptured = cfCapturedTotal; 1691 Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream ->szName, cfCapturedTotal, rc));1817 Log2Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStreamEx->Core.szName, cfCapturedTotal, rc)); 1692 1818 return rc; 1693 1819 } … … 1701 1827 PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector); 1702 1828 AssertPtr(pThis); 1703 AssertPtr(pStream); 1829 PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream; 1830 AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER); 1704 1831 AssertPtrNull(pcFramesCaptured); 1705 AssertMsg(pStream->enmDir == PDMAUDIODIR_IN, 1832 AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 1833 AssertReturn(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 1834 AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_IN, 1706 1835 ("Stream '%s' is not an input stream and therefore cannot be captured (direction is 0x%x)\n", 1707 pStream ->szName, pStream->enmDir));1836 pStreamEx->Core.szName, pStreamEx->Core.enmDir)); 1708 1837 int rc = RTCritSectEnter(&pThis->CritSect); 1709 1838 AssertRCReturn(rc, rc); … … 1712 1841 char szStreamSts[DRVAUDIO_STATUS_STR_MAX]; 1713 1842 #endif 1714 Log3Func(("[%s] fStatus=%s\n", pStream ->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));1843 Log3Func(("[%s] fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus))); 1715 1844 1716 1845 /* … … 1727 1856 1728 1857 if ( !pThis->In.fEnabled 1729 || !PDMAudioStrmStatusCanRead(pStream ->fStatus))1858 || !PDMAudioStrmStatusCanRead(pStreamEx->Core.fStatus)) 1730 1859 { 1731 1860 rc = VERR_AUDIO_STREAM_NOT_READY; … … 1737 1866 */ 1738 1867 if (pThis->pHostDrvAudio->pfnStreamCaptureBegin) 1739 pThis->pHostDrvAudio->pfnStreamCaptureBegin(pThis->pHostDrvAudio, pStream ->pvBackend);1740 1741 if (RT_LIKELY(pStream ->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED))1742 rc = drvAudioStreamCaptureNonInterleaved(pThis, pStream , &cfCaptured);1743 else if (pStream ->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW)1744 rc = drvAudioStreamCaptureRaw(pThis, pStream , &cfCaptured);1868 pThis->pHostDrvAudio->pfnStreamCaptureBegin(pThis->pHostDrvAudio, pStreamEx->pvBackend); 1869 1870 if (RT_LIKELY(pStreamEx->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED)) 1871 rc = drvAudioStreamCaptureNonInterleaved(pThis, pStreamEx, &cfCaptured); 1872 else if (pStreamEx->Host.Cfg.enmLayout == PDMAUDIOSTREAMLAYOUT_RAW) 1873 rc = drvAudioStreamCaptureRaw(pThis, pStreamEx, &cfCaptured); 1745 1874 else 1746 1875 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED); 1747 1876 1748 1877 if (pThis->pHostDrvAudio->pfnStreamCaptureEnd) 1749 pThis->pHostDrvAudio->pfnStreamCaptureEnd(pThis->pHostDrvAudio, pStream ->pvBackend);1878 pThis->pHostDrvAudio->pfnStreamCaptureEnd(pThis->pHostDrvAudio, pStreamEx->pvBackend); 1750 1879 1751 1880 if (RT_SUCCESS(rc)) 1752 1881 { 1753 Log3Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStream->szName, cfCaptured, rc)); 1754 1755 #ifdef VBOX_WITH_STATISTICS 1756 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesIn, cfCaptured); 1757 1758 STAM_COUNTER_ADD(&pStream->In.Stats.TotalFramesCaptured, cfCaptured); 1759 #endif 1882 Log3Func(("[%s] %RU32 frames captured, rc=%Rrc\n", pStreamEx->Core.szName, cfCaptured, rc)); 1883 1884 STAM_COUNTER_ADD(&pThis->Stats.TotalFramesIn, cfCaptured); 1885 STAM_COUNTER_ADD(&pStreamEx->In.Stats.TotalFramesCaptured, cfCaptured); 1760 1886 } 1761 1887 else if (RT_UNLIKELY(RT_FAILURE(rc))) 1762 LogRel(("Audio: Capturing stream '%s' failed with %Rrc\n", pStream ->szName, rc));1888 LogRel(("Audio: Capturing stream '%s' failed with %Rrc\n", pStreamEx->Core.szName, rc)); 1763 1889 } while (0); 1764 1890 … … 1773 1899 } 1774 1900 1775 #ifdef VBOX_WITH_AUDIO_CALLBACKS 1901 #ifdef VBOX_WITH_AUDIO_CALLBACKS /** @todo r=bird: All this is non-sense that shall be replaced by a PDMIHOSTAUDIO partner interface. */ 1776 1902 1777 1903 /** … … 1890 2016 * callback. Will result in some ugly deadlocks (or at least locking 1891 2017 * order violations) then. 2018 * 2019 * @todo r=bird: The above warning is extremely bogus. You enter the critical 2020 * section of the driver here, if anything, that will be the lock order 2021 * violation. 1892 2022 */ 1893 2023 static DECLCALLBACK(int) drvAudioBackendCallback(PPDMDRVINS pDrvIns, PDMAUDIOBACKENDCBTYPE enmType, void *pvUser, size_t cbUser) … … 1897 2027 /* pvUser and cbUser are optional. */ 1898 2028 1899 /** @todo r=bird: WTF *is* this? Seriously?!? */ 2029 /** @todo r=bird: WTF *is* this? Seriously?!? 2030 * 2031 * DrvAudio will provide the host driver with a "callback" interface 2032 * with methods like pfnNotifyDevicesChanged and pfnNotifyStatusChanged. 2033 * The host drivers that implements callbacks can query the callback 2034 * interface and make use of it. 2035 */ 1900 2036 1901 2037 /* Get the upper driver (PDMIAUDIOCONNECTOR). */ … … 1944 2080 * @param fLog Whether to print the enumerated device to the release log or not. 1945 2081 * @param pDevEnum Where to store the device enumeration. 2082 * 2083 * @remarks This is currently ONLY used for release logging. 1946 2084 */ 1947 2085 static int drvAudioDevicesEnumerateInternal(PDRVAUDIO pThis, bool fLog, PPDMAUDIOHOSTENUM pDevEnum) 1948 2086 { 1949 AssertReturn( RTCritSectIsOwned(&pThis->CritSect) == false, VERR_WRONG_ORDER);2087 AssertReturn(!RTCritSectIsOwner(&pThis->CritSect), VERR_WRONG_ORDER); 1950 2088 1951 2089 int rc; … … 2121 2259 if (pThis->pHostDrvAudio) 2122 2260 { 2123 P PDMAUDIOSTREAM pStream;2124 RTListForEach(&pThis->lstStreams, pStream , PDMAUDIOSTREAM, ListEntry)2125 { 2126 drvAudioStreamControlInternal(pThis, pStream , enmCmd);2261 PDRVAUDIOSTREAM pStreamEx; 2262 RTListForEach(&pThis->lstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry) 2263 { 2264 drvAudioStreamControlInternal(pThis, pStreamEx, enmCmd); 2127 2265 } 2128 2266 } … … 2140 2278 PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector); 2141 2279 AssertPtr(pThis); 2142 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 2143 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 2144 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 2280 PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream; 2281 AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER); 2282 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 2283 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 2145 2284 AssertPtrNullReturn(pcbRead, VERR_INVALID_POINTER); 2146 AssertMsg(pStream->enmDir == PDMAUDIODIR_IN, 2285 AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 2286 AssertReturn(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 2287 AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_IN, 2147 2288 ("Stream '%s' is not an input stream and therefore cannot be read from (direction is 0x%x)\n", 2148 pStream->szName, pStream->enmDir)); 2289 pStreamEx->Core.szName, pStreamEx->Core.enmDir)); 2290 2149 2291 int rc = RTCritSectEnter(&pThis->CritSect); 2150 2292 AssertRCReturn(rc, rc); … … 2159 2301 uint32_t cfReadTotal = 0; 2160 2302 2161 const uint32_t cfBuf = AUDIOMIXBUF_B2F(&pStream ->Guest.MixBuf, cbBuf);2303 const uint32_t cfBuf = AUDIOMIXBUF_B2F(&pStreamEx->Guest.MixBuf, cbBuf); 2162 2304 2163 2305 if (pThis->In.fEnabled) /* Input for this audio driver enabled? See #9822. */ … … 2173 2315 * should have the audio data in the format the guest needs. 2174 2316 */ 2175 uint32_t cfToRead = RT_MIN(cfBuf, AudioMixBufLive(&pStream ->Guest.MixBuf));2317 uint32_t cfToRead = RT_MIN(cfBuf, AudioMixBufLive(&pStreamEx->Guest.MixBuf)); 2176 2318 while (cfToRead) 2177 2319 { 2178 2320 uint32_t cfRead; 2179 rc = AudioMixBufAcquireReadBlock(&pStream ->Guest.MixBuf,2180 (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStream ->Guest.MixBuf, cfReadTotal),2181 AUDIOMIXBUF_F2B(&pStream ->Guest.MixBuf, cfToRead), &cfRead);2321 rc = AudioMixBufAcquireReadBlock(&pStreamEx->Guest.MixBuf, 2322 (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadTotal), 2323 AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfToRead), &cfRead); 2182 2324 if (RT_FAILURE(rc)) 2183 2325 break; 2184 2326 2185 2327 #ifdef VBOX_WITH_STATISTICS 2186 const uint32_t cbRead = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfRead); 2187 2188 STAM_COUNTER_ADD(&pThis->Stats.TotalBytesRead, cbRead); 2189 2190 STAM_COUNTER_ADD(&pStream->In.Stats.TotalFramesRead, cfRead); 2191 STAM_COUNTER_INC(&pStream->In.Stats.TotalTimesRead); 2328 const uint32_t cbRead = AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfRead); 2329 STAM_COUNTER_ADD(&pThis->Stats.TotalBytesRead, cbRead); 2330 STAM_COUNTER_ADD(&pStreamEx->In.Stats.TotalFramesRead, cfRead); 2331 STAM_COUNTER_INC(&pStreamEx->In.Stats.TotalTimesRead); 2192 2332 #endif 2193 2333 Assert(cfToRead >= cfRead); … … 2196 2336 cfReadTotal += cfRead; 2197 2337 2198 AudioMixBufReleaseReadBlock(&pStream ->Guest.MixBuf, cfRead);2338 AudioMixBufReleaseReadBlock(&pStreamEx->Guest.MixBuf, cfRead); 2199 2339 } 2200 2340 … … 2202 2342 { 2203 2343 if (pThis->In.Cfg.Dbg.fEnabled) 2204 AudioHlpFileWrite(pStream ->In.Dbg.pFileStreamRead,2205 pvBuf, AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadTotal), 0 /* fFlags */);2206 2207 AudioMixBufFinish(&pStream ->Guest.MixBuf, cfReadTotal);2344 AudioHlpFileWrite(pStreamEx->In.Dbg.pFileStreamRead, 2345 pvBuf, AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadTotal), 0 /* fFlags */); 2346 2347 AudioMixBufFinish(&pStreamEx->Guest.MixBuf, cfReadTotal); 2208 2348 } 2209 2349 } … … 2216 2356 { 2217 2357 Log3Func(("[%s] Filling in silence (%RU64ms / %RU64ms)\n", pStream->szName, 2218 PDMAudioPropsFramesToMilli(&pStream ->Guest.Cfg.Props, cfBuf - cfReadTotal),2219 PDMAudioPropsFramesToMilli(&pStream ->Guest.Cfg.Props, cfBuf)));2220 2221 PDMAudioPropsClearBuffer(&pStream ->Guest.Cfg.Props,2222 (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStream ->Guest.MixBuf, cfReadTotal),2223 AUDIOMIXBUF_F2B(&pStream ->Guest.MixBuf, cfBuf - cfReadTotal),2358 PDMAudioPropsFramesToMilli(&pStreamEx->Guest.Cfg.Props, cfBuf - cfReadTotal), 2359 PDMAudioPropsFramesToMilli(&pStreamEx->Guest.Cfg.Props, cfBuf))); 2360 2361 PDMAudioPropsClearBuffer(&pStreamEx->Guest.Cfg.Props, 2362 (uint8_t *)pvBuf + AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadTotal), 2363 AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfBuf - cfReadTotal), 2224 2364 cfBuf - cfReadTotal); 2225 2365 … … 2227 2367 } 2228 2368 2229 cbReadTotal = AUDIOMIXBUF_F2B(&pStream ->Guest.MixBuf, cfReadTotal);2230 2231 pStream ->tsLastReadWrittenNs= RTTimeNanoTS();2369 cbReadTotal = AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadTotal); 2370 2371 pStreamEx->nsLastReadWritten = RTTimeNanoTS(); 2232 2372 2233 2373 Log3Func(("[%s] fEnabled=%RTbool, cbReadTotal=%RU32, rc=%Rrc\n", pStream->szName, pThis->In.fEnabled, cbReadTotal, rc)); … … 2247 2387 * 2248 2388 * @returns VBox status code. 2249 * @param pThis Pointer to driver instance. 2250 * @param pStream Audio stream to create the backend side for. 2251 * @param pCfgReq Requested audio stream configuration to use for stream creation. 2252 * @param pCfgAcq Acquired audio stream configuration returned by the backend. 2389 * @param pThis Pointer to driver instance. 2390 * @param pStreamEx Audio stream to create the backend side for. 2391 * @param pCfgReq Requested audio stream configuration to use for 2392 * stream creation. 2393 * @param pCfgAcq Acquired audio stream configuration returned by 2394 * the backend. 2253 2395 * 2254 2396 * @note Configuration precedence for requested audio stream configuration (first has highest priority, if set): … … 2258 2400 * - default value 2259 2401 */ 2260 static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, P PDMAUDIOSTREAM pStream,2402 static int drvAudioStreamCreateInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, 2261 2403 PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq) 2262 2404 { 2263 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 2264 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 2265 AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER); 2266 AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER); 2267 2268 AssertMsg((pStream->fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED) == 0, 2269 ("Stream '%s' already initialized in backend\n", pStream->szName)); 2405 AssertMsg((pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED) == 0, 2406 ("Stream '%s' already initialized in backend\n", pStreamEx->Core.szName)); 2270 2407 2271 2408 /* Get the right configuration for the stream to be created. */ … … 2282 2419 PDMAudioPropsSetSampleSize(&pCfgReq->Props, PDMAudioPropsSampleSize(&pDrvCfg->Props)); 2283 2420 LogRel2(("Audio: Using custom sample size of %RU8 bytes for stream '%s'\n", 2284 PDMAudioPropsSampleSize(&pCfgReq->Props), pStream ->szName));2421 PDMAudioPropsSampleSize(&pCfgReq->Props), pStreamEx->Core.szName)); 2285 2422 } 2286 2423 … … 2288 2425 { 2289 2426 pCfgReq->Props.uHz = pDrvCfg->Props.uHz; 2290 LogRel2(("Audio: Using custom Hz rate %RU32 for stream '%s'\n", pCfgReq->Props.uHz, pStream ->szName));2427 LogRel2(("Audio: Using custom Hz rate %RU32 for stream '%s'\n", pCfgReq->Props.uHz, pStreamEx->Core.szName)); 2291 2428 } 2292 2429 … … 2295 2432 pCfgReq->Props.fSigned = RT_BOOL(pDrvCfg->uSigned); 2296 2433 LogRel2(("Audio: Using custom %s sample format for stream '%s'\n", 2297 pCfgReq->Props.fSigned ? "signed" : "unsigned", pStream ->szName));2434 pCfgReq->Props.fSigned ? "signed" : "unsigned", pStreamEx->Core.szName)); 2298 2435 } 2299 2436 … … 2302 2439 pCfgReq->Props.fSwapEndian = RT_BOOL(pDrvCfg->uSwapEndian); 2303 2440 LogRel2(("Audio: Using custom %s endianess for samples of stream '%s'\n", 2304 pCfgReq->Props.fSwapEndian ? "swapped" : "original", pStream ->szName));2441 pCfgReq->Props.fSwapEndian ? "swapped" : "original", pStreamEx->Core.szName)); 2305 2442 } 2306 2443 … … 2308 2445 { 2309 2446 PDMAudioPropsSetChannels(&pCfgReq->Props, PDMAudioPropsChannels(&pDrvCfg->Props)); 2310 LogRel2(("Audio: Using custom %RU8 channel(s) for stream '%s'\n", PDMAudioPropsChannels(&pDrvCfg->Props), pStream ->szName));2447 LogRel2(("Audio: Using custom %RU8 channel(s) for stream '%s'\n", PDMAudioPropsChannels(&pDrvCfg->Props), pStreamEx->Core.szName)); 2311 2448 } 2312 2449 … … 2314 2451 if (!AudioHlpPcmPropsAreValid(&pCfgReq->Props)) 2315 2452 { 2316 LogRel(("Audio: Invalid custom PCM properties set for stream '%s', cannot create stream\n", pStream ->szName));2453 LogRel(("Audio: Invalid custom PCM properties set for stream '%s', cannot create stream\n", pStreamEx->Core.szName)); 2317 2454 return VERR_INVALID_PARAMETER; 2318 2455 } … … 2336 2473 LogRel2(("Audio: Using %s period size %RU64 ms / %RU32 frames for stream '%s'\n", 2337 2474 pszWhat, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPeriod), 2338 pCfgReq->Backend.cFramesPeriod, pStream ->szName));2475 pCfgReq->Backend.cFramesPeriod, pStreamEx->Core.szName)); 2339 2476 2340 2477 /* … … 2356 2493 LogRel2(("Audio: Using %s buffer size %RU64 ms / %RU32 frames for stream '%s'\n", 2357 2494 pszWhat, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize), 2358 pCfgReq->Backend.cFramesBufferSize, pStream ->szName));2495 pCfgReq->Backend.cFramesBufferSize, pStreamEx->Core.szName)); 2359 2496 2360 2497 /* … … 2379 2516 LogRel2(("Audio: Using %s pre-buffering size %RU64 ms / %RU32 frames for stream '%s'\n", 2380 2517 pszWhat, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPreBuffering), 2381 pCfgReq->Backend.cFramesPreBuffering, pStream ->szName));2518 pCfgReq->Backend.cFramesPreBuffering, pStreamEx->Core.szName)); 2382 2519 2383 2520 /* … … 2387 2524 { 2388 2525 LogRel(("Audio: Error for stream '%s': Buffering size (%RU64ms) must not be smaller than the period size (%RU64ms)\n", 2389 pStream ->szName, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize),2526 pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize), 2390 2527 PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPeriod))); 2391 2528 return VERR_INVALID_PARAMETER; … … 2398 2535 { 2399 2536 LogRel(("Audio: Error for stream '%s': Buffering size (%RU64ms) must not be smaller than the pre-buffering size (%RU64ms)\n", 2400 pStream ->szName, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPreBuffering),2537 pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesPreBuffering), 2401 2538 PDMAudioPropsFramesToMilli(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize))); 2402 2539 return VERR_INVALID_PARAMETER; … … 2413 2550 { 2414 2551 LogRel(("Audio: Creating stream '%s' with an invalid backend configuration not possible, skipping\n", 2415 pStream ->szName));2552 pStreamEx->Core.szName)); 2416 2553 return rc; 2417 2554 } … … 2422 2559 AssertPtr(pThis->pHostDrvAudio); 2423 2560 if (pThis->pHostDrvAudio) 2424 rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pStream ->pvBackend, pCfgReq, pCfgAcq);2561 rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pStreamEx->pvBackend, pCfgReq, pCfgAcq); 2425 2562 else 2426 2563 rc = VERR_PDM_NO_ATTACHED_DRIVER; … … 2428 2565 { 2429 2566 if (rc == VERR_NOT_SUPPORTED) 2430 LogRel2(("Audio: Creating stream '%s' in backend not supported\n", pStream ->szName));2567 LogRel2(("Audio: Creating stream '%s' in backend not supported\n", pStreamEx->Core.szName)); 2431 2568 else if (rc == VERR_AUDIO_STREAM_COULD_NOT_CREATE) 2432 LogRel2(("Audio: Stream '%s' could not be created in backend because of missing hardware / drivers\n", pStream ->szName));2569 LogRel2(("Audio: Stream '%s' could not be created in backend because of missing hardware / drivers\n", pStreamEx->Core.szName)); 2433 2570 else 2434 LogRel(("Audio: Creating stream '%s' in backend failed with %Rrc\n", pStream ->szName, rc));2571 LogRel(("Audio: Creating stream '%s' in backend failed with %Rrc\n", pStreamEx->Core.szName, rc)); 2435 2572 return rc; 2436 2573 } … … 2440 2577 AssertLogRelMsgReturn(AudioHlpStreamCfgIsValid(pCfgAcq), 2441 2578 ("Audio: Creating stream '%s' returned an invalid backend configuration (%s), skipping\n", 2442 pStream ->szName, PDMAudioPropsToString(&pCfgAcq->Props, szTmp, sizeof(szTmp))),2579 pStreamEx->Core.szName, PDMAudioPropsToString(&pCfgAcq->Props, szTmp, sizeof(szTmp))), 2443 2580 VERR_INVALID_PARAMETER); 2444 2581 … … 2446 2583 if (pCfgAcq->Backend.cFramesBufferSize != pCfgReq->Backend.cFramesBufferSize) 2447 2584 LogRel2(("Audio: Buffer size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n", 2448 pStream ->szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesBufferSize), pCfgAcq->Backend.cFramesBufferSize));2585 pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesBufferSize), pCfgAcq->Backend.cFramesBufferSize)); 2449 2586 2450 2587 if (pCfgAcq->Backend.cFramesPeriod != pCfgReq->Backend.cFramesPeriod) 2451 2588 LogRel2(("Audio: Period size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n", 2452 pStream ->szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPeriod), pCfgAcq->Backend.cFramesPeriod));2589 pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPeriod), pCfgAcq->Backend.cFramesPeriod)); 2453 2590 2454 2591 /* Was pre-buffering requested, but the acquired configuration from the backend told us something else? */ … … 2457 2594 if (pCfgAcq->Backend.cFramesPreBuffering != pCfgReq->Backend.cFramesPreBuffering) 2458 2595 LogRel2(("Audio: Pre-buffering size overwritten by backend for stream '%s' (now %RU64ms, %RU32 frames)\n", 2459 pStream ->szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPreBuffering), pCfgAcq->Backend.cFramesPreBuffering));2596 pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPreBuffering), pCfgAcq->Backend.cFramesPreBuffering)); 2460 2597 2461 2598 if (pCfgAcq->Backend.cFramesPreBuffering > pCfgAcq->Backend.cFramesBufferSize) … … 2463 2600 pCfgAcq->Backend.cFramesPreBuffering = pCfgAcq->Backend.cFramesBufferSize; 2464 2601 LogRel2(("Audio: Pre-buffering size bigger than buffer size for stream '%s', adjusting to %RU64ms (%RU32 frames)\n", 2465 pStream ->szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPreBuffering), pCfgAcq->Backend.cFramesPreBuffering));2602 pStreamEx->Core.szName, PDMAudioPropsFramesToMilli(&pCfgAcq->Props, pCfgAcq->Backend.cFramesPreBuffering), pCfgAcq->Backend.cFramesPreBuffering)); 2466 2603 } 2467 2604 } 2468 2605 else if (pCfgReq->Backend.cFramesPreBuffering == 0) /* Was the pre-buffering requested as being disabeld? Tell the users. */ 2469 2606 { 2470 LogRel2(("Audio: Pre-buffering is disabled for stream '%s'\n", pStream ->szName));2607 LogRel2(("Audio: Pre-buffering is disabled for stream '%s'\n", pStreamEx->Core.szName)); 2471 2608 pCfgAcq->Backend.cFramesPreBuffering = 0; 2472 2609 } … … 2480 2617 VERR_INVALID_PARAMETER); 2481 2618 2482 pStream ->fStatus |= PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;2619 pStreamEx->Core.fStatus |= PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED; 2483 2620 2484 2621 return VINF_SUCCESS; … … 2490 2627 * 2491 2628 * @returns VBox status code. 2492 * @param pThis Pointer to driver instance. 2493 * @param pStream Stream to initialize. 2494 * @param pCfgHost Stream configuration to use for the host side (backend). 2495 * @param pCfgGuest Stream configuration to use for the guest side. 2496 */ 2497 static int drvAudioStreamInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, 2629 * @param pThis Pointer to driver instance. 2630 * @param pStreamEx Stream to initialize. 2631 * @param fFlags PDMAUDIOSTREAM_CREATE_F_XXX. 2632 * @param pCfgHost Stream configuration to use for the host side (backend). 2633 * @param pCfgGuest Stream configuration to use for the guest side. 2634 */ 2635 static int drvAudioStreamInitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, uint32_t fFlags, 2498 2636 PPDMAUDIOSTREAMCFG pCfgHost, PPDMAUDIOSTREAMCFG pCfgGuest) 2499 2637 { 2500 AssertPtrReturn(pThis, VERR_INVALID_POINTER);2501 AssertPtrReturn(pStream, VERR_INVALID_POINTER);2502 AssertPtrReturn(pCfgHost, VERR_INVALID_POINTER);2503 AssertPtrReturn(pCfgGuest, VERR_INVALID_POINTER);2504 2505 2638 /* 2506 2639 * Init host stream. 2507 2640 */ 2508 pStream ->uMagic = PDMAUDIOSTREAM_MAGIC;2641 pStreamEx->Core.uMagic = PDMAUDIOSTREAM_MAGIC; 2509 2642 2510 2643 /* Set the host's default audio data layout. */ 2644 /** @todo r=bird: Why, oh why? OTOH, the layout stuff is non-sense anyway. */ 2511 2645 pCfgHost->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED; 2512 2646 2513 2647 #ifdef LOG_ENABLED 2514 LogFunc(("[%s] Requested host format:\n", pStream ->szName));2648 LogFunc(("[%s] Requested host format:\n", pStreamEx->Core.szName)); 2515 2649 PDMAudioStrmCfgLog(pCfgHost); 2516 2650 #endif 2517 2651 2518 LogRel2(("Audio: Creating stream '%s'\n", pStream ->szName));2652 LogRel2(("Audio: Creating stream '%s'\n", pStreamEx->Core.szName)); 2519 2653 LogRel2(("Audio: Guest %s format for '%s': %RU32Hz, %u%s, %RU8 channel%s\n", 2520 pCfgGuest->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStream ->szName,2654 pCfgGuest->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStreamEx->Core.szName, 2521 2655 pCfgGuest->Props.uHz, PDMAudioPropsSampleBits(&pCfgGuest->Props), pCfgGuest->Props.fSigned ? "S" : "U", 2522 2656 PDMAudioPropsChannels(&pCfgGuest->Props), PDMAudioPropsChannels(&pCfgGuest->Props) == 1 ? "" : "s")); 2523 2657 LogRel2(("Audio: Requested host %s format for '%s': %RU32Hz, %u%s, %RU8 channel%s\n", 2524 pCfgHost->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStream ->szName,2658 pCfgHost->enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStreamEx->Core.szName, 2525 2659 pCfgHost->Props.uHz, PDMAudioPropsSampleBits(&pCfgHost->Props), pCfgHost->Props.fSigned ? "S" : "U", 2526 2660 PDMAudioPropsChannels(&pCfgHost->Props), PDMAudioPropsChannels(&pCfgHost->Props) == 1 ? "" : "s")); 2527 2661 2528 2662 PDMAUDIOSTREAMCFG CfgHostAcq; 2529 int rc = drvAudioStreamCreateInternalBackend(pThis, pStream , pCfgHost, &CfgHostAcq);2663 int rc = drvAudioStreamCreateInternalBackend(pThis, pStreamEx, pCfgHost, &CfgHostAcq); 2530 2664 if (RT_FAILURE(rc)) 2531 2665 return rc; 2532 2666 2533 LogFunc(("[%s] Acquired host format:\n", pStream ->szName));2667 LogFunc(("[%s] Acquired host format:\n", pStreamEx->Core.szName)); 2534 2668 PDMAudioStrmCfgLog(&CfgHostAcq); 2535 2669 LogRel2(("Audio: Acquired host %s format for '%s': %RU32Hz, %u%s, %RU8 channel%s\n", 2536 CfgHostAcq.enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStream ->szName,2670 CfgHostAcq.enmDir == PDMAUDIODIR_IN ? "recording" : "playback", pStreamEx->Core.szName, 2537 2671 CfgHostAcq.Props.uHz, PDMAudioPropsSampleBits(&CfgHostAcq.Props), CfgHostAcq.Props.fSigned ? "S" : "U", 2538 2672 PDMAudioPropsChannels(&CfgHostAcq.Props), PDMAudioPropsChannels(&CfgHostAcq.Props) == 1 ? "" : "s")); … … 2565 2699 LogRel2(("Audio: Warning: Pre-buffering size (%RU32 frames) of stream '%s' does not match buffer size (%RU32 frames), " 2566 2700 "setting pre-buffering size to %RU32 frames\n", 2567 CfgHostAcq.Backend.cFramesPreBuffering, pStream ->szName, CfgHostAcq.Backend.cFramesBufferSize, CfgHostAcq.Backend.cFramesBufferSize));2701 CfgHostAcq.Backend.cFramesPreBuffering, pStreamEx->Core.szName, CfgHostAcq.Backend.cFramesBufferSize, CfgHostAcq.Backend.cFramesBufferSize)); 2568 2702 CfgHostAcq.Backend.cFramesPreBuffering = CfgHostAcq.Backend.cFramesBufferSize; 2569 2703 } … … 2572 2706 { 2573 2707 LogRel2(("Audio: Warning: Period size (%RU32 frames) of stream '%s' does not match buffer size (%RU32 frames), setting to %RU32 frames\n", 2574 CfgHostAcq.Backend.cFramesPeriod, pStream ->szName, CfgHostAcq.Backend.cFramesBufferSize, CfgHostAcq.Backend.cFramesBufferSize));2708 CfgHostAcq.Backend.cFramesPeriod, pStreamEx->Core.szName, CfgHostAcq.Backend.cFramesBufferSize, CfgHostAcq.Backend.cFramesBufferSize)); 2575 2709 CfgHostAcq.Backend.cFramesPeriod = CfgHostAcq.Backend.cFramesBufferSize; 2576 2710 } … … 2578 2712 uint64_t msBufferSize = PDMAudioPropsFramesToMilli(&CfgHostAcq.Props, CfgHostAcq.Backend.cFramesBufferSize); 2579 2713 LogRel2(("Audio: Buffer size of stream '%s' is %RU64ms (%RU32 frames)\n", 2580 pStream ->szName, msBufferSize, CfgHostAcq.Backend.cFramesBufferSize));2714 pStreamEx->Core.szName, msBufferSize, CfgHostAcq.Backend.cFramesBufferSize)); 2581 2715 2582 2716 /* If no own pre-buffer is set, let the backend choose. */ 2583 2717 uint64_t msPreBuf = PDMAudioPropsFramesToMilli(&CfgHostAcq.Props, CfgHostAcq.Backend.cFramesPreBuffering); 2584 2718 LogRel2(("Audio: Pre-buffering size of stream '%s' is %RU64ms (%RU32 frames)\n", 2585 pStream ->szName, msPreBuf, CfgHostAcq.Backend.cFramesPreBuffering));2719 pStreamEx->Core.szName, msPreBuf, CfgHostAcq.Backend.cFramesPreBuffering)); 2586 2720 2587 2721 /* Make sure the configured buffer size by the backend at least can hold the configured latency. */ … … 2589 2723 2590 2724 LogRel2(("Audio: Period size of stream '%s' is %RU64ms (%RU32 frames)\n", 2591 pStream ->szName, msPeriod, CfgHostAcq.Backend.cFramesPeriod));2725 pStreamEx->Core.szName, msPeriod, CfgHostAcq.Backend.cFramesPeriod)); 2592 2726 2593 2727 if ( pCfgGuest->Device.cMsSchedulingHint /* Any scheduling hint set? */ … … 2595 2729 { 2596 2730 LogRel(("Audio: Warning: Scheduling hint of stream '%s' is bigger (%RU64ms) than used period size (%RU64ms)\n", 2597 pStream ->szName, pCfgGuest->Device.cMsSchedulingHint, msPeriod));2731 pStreamEx->Core.szName, pCfgGuest->Device.cMsSchedulingHint, msPeriod)); 2598 2732 } 2599 2733 2600 2734 /* Destroy any former mixing buffer. */ 2601 AudioMixBufDestroy(&pStream->Host.MixBuf); 2602 2603 rc = AudioMixBufInit(&pStream->Host.MixBuf, pStream->szName, &CfgHostAcq.Props, CfgHostAcq.Backend.cFramesBufferSize); 2604 AssertRC(rc); 2735 AudioMixBufDestroy(&pStreamEx->Host.MixBuf); 2736 2737 if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF)) 2738 { 2739 rc = AudioMixBufInit(&pStreamEx->Host.MixBuf, pStreamEx->Core.szName, &CfgHostAcq.Props, CfgHostAcq.Backend.cFramesBufferSize); 2740 AssertRCReturn(rc, rc); 2741 } 2605 2742 2606 2743 /* Make a copy of the acquired host stream configuration. */ 2607 rc = PDMAudioStrmCfgCopy(&pStream ->Host.Cfg, &CfgHostAcq);2744 rc = PDMAudioStrmCfgCopy(&pStreamEx->Host.Cfg, &CfgHostAcq); 2608 2745 AssertRC(rc); 2609 2746 … … 2614 2751 if (pCfgGuest->Device.cMsSchedulingHint) 2615 2752 LogRel2(("Audio: Stream '%s' got a scheduling hint of %RU32ms (%RU32 bytes)\n", 2616 pStream ->szName, pCfgGuest->Device.cMsSchedulingHint,2753 pStreamEx->Core.szName, pCfgGuest->Device.cMsSchedulingHint, 2617 2754 PDMAudioPropsMilliToBytes(&pCfgGuest->Props, pCfgGuest->Device.cMsSchedulingHint))); 2618 2755 2619 2756 /* Destroy any former mixing buffer. */ 2620 AudioMixBufDestroy(&pStream ->Guest.MixBuf);2757 AudioMixBufDestroy(&pStreamEx->Guest.MixBuf); 2621 2758 2622 2759 /* Set the guests's default audio data layout. */ 2623 2760 pCfgGuest->enmLayout = PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED; 2624 2761 2625 rc = AudioMixBufInit(&pStream->Guest.MixBuf, pStream->szName, &pCfgGuest->Props, CfgHostAcq.Backend.cFramesBufferSize); 2762 if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF)) 2763 { 2764 rc = AudioMixBufInit(&pStreamEx->Guest.MixBuf, pStreamEx->Core.szName, &pCfgGuest->Props, CfgHostAcq.Backend.cFramesBufferSize); 2765 AssertRCReturn(rc, rc); 2766 } 2767 2768 /* Make a copy of the guest stream configuration. */ 2769 rc = PDMAudioStrmCfgCopy(&pStreamEx->Guest.Cfg, pCfgGuest); 2626 2770 AssertRC(rc); 2627 2771 2628 /* Make a copy of the guest stream configuration. */2629 rc = PDMAudioStrmCfgCopy(&pStream->Guest.Cfg, pCfgGuest);2630 AssertRC(rc);2631 2632 2772 if (RT_FAILURE(rc)) 2633 LogRel(("Audio: Creating stream '%s' failed with %Rrc\n", pStream->szName, rc)); 2634 2635 if (pCfgGuest->enmDir == PDMAUDIODIR_IN) 2636 { 2637 /* Host (Parent) -> Guest (Child). */ 2638 rc = AudioMixBufLinkTo(&pStream->Host.MixBuf, &pStream->Guest.MixBuf); 2639 AssertRC(rc); 2640 } 2641 else 2642 { 2643 /* Guest (Parent) -> Host (Child). */ 2644 rc = AudioMixBufLinkTo(&pStream->Guest.MixBuf, &pStream->Host.MixBuf); 2645 AssertRC(rc); 2773 LogRel(("Audio: Creating stream '%s' failed with %Rrc\n", pStreamEx->Core.szName, rc)); 2774 2775 if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF)) 2776 { 2777 if (pCfgGuest->enmDir == PDMAUDIODIR_IN) 2778 { 2779 /* Host (Parent) -> Guest (Child). */ 2780 rc = AudioMixBufLinkTo(&pStreamEx->Host.MixBuf, &pStreamEx->Guest.MixBuf); 2781 AssertRC(rc); 2782 } 2783 else 2784 { 2785 /* Guest (Parent) -> Host (Child). */ 2786 rc = AudioMixBufLinkTo(&pStreamEx->Guest.MixBuf, &pStreamEx->Host.MixBuf); 2787 AssertRC(rc); 2788 } 2646 2789 } 2647 2790 … … 2651 2794 PPDMDRVINS const pDrvIns = pThis->pDrvIns; 2652 2795 /** @todo expose config and more. */ 2653 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Host.Cfg.Backend.cFramesBufferSize, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2654 "Host side: The size of the backend buffer (in frames)", "%s/0-HostBackendBufSize", pStream->szName); 2655 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Host.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2656 "Host side: The size of the mixer buffer (in frames)", "%s/1-HostMixBufSize", pStream->szName); 2657 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Guest.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2658 "Guest side: The size of the mixer buffer (in frames)", "%s/2-GuestMixBufSize", pStream->szName); 2796 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.Cfg.Backend.cFramesBufferSize, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2797 "Host side: The size of the backend buffer (in frames)", "%s/0-HostBackendBufSize", pStreamEx->Core.szName); 2798 if (!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF)) 2799 { 2800 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2801 "Host side: The size of the mixer buffer (in frames)", "%s/1-HostMixBufSize", pStreamEx->Core.szName); 2802 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Guest.MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2803 "Guest side: The size of the mixer buffer (in frames)", "%s/2-GuestMixBufSize", pStreamEx->Core.szName); 2804 if (pCfgGuest->enmDir == PDMAUDIODIR_IN) 2805 { 2806 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2807 "Host side: Number of frames in the mixer buffer", "%s/1-HostMixBufUsed", pStreamEx->Core.szName); 2808 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Guest.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2809 "Guest side: Number of frames in the mixer buffer", "%s/2-GuestMixBufUsed", pStreamEx->Core.szName); 2810 } 2811 else 2812 { 2813 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Host.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2814 "Host side: Number of frames in the mixer buffer", "%s/1-HostMixBufUsed", pStreamEx->Core.szName); 2815 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Guest.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2816 "Guest side: Number of frames in the mixer buffer", "%s/2-GuestMixBufUsed", pStreamEx->Core.szName); 2817 } 2818 } 2659 2819 if (pCfgGuest->enmDir == PDMAUDIODIR_IN) 2660 2820 { 2661 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Host.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2662 "Host side: Number of frames in the mixer buffer", "%s/1-HostMixBufUsed", pStream->szName); 2663 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Guest.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2664 "Guest side: Number of frames in the mixer buffer", "%s/2-GuestMixBufUsed", pStream->szName); 2821 /** @todo later? */ 2665 2822 } 2666 2823 else 2667 2824 { 2668 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Host.MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2669 "Host side: Number of frames in the mixer buffer", "%s/1-HostMixBufUsed", pStream->szName); 2670 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Guest.MixBuf.cMixed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2671 "Guest side: Number of frames in the mixer buffer", "%s/2-GuestMixBufUsed", pStream->szName); 2672 2673 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Out.Stats.cbBackendWritableBefore, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2674 "Host side: Free space in backend buffer before play", "%s/0-HostBackendBufFreeBefore", pStream->szName); 2675 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStream->Out.Stats.cbBackendWritableAfter, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2676 "Host side: Free space in backend buffer after play", "%s/0-HostBackendBufFreeAfter", pStream->szName); 2825 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Out.Stats.cbBackendWritableBefore, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2826 "Host side: Free space in backend buffer before play", "%s/0-HostBackendBufFreeBefore", pStreamEx->Core.szName); 2827 PDMDrvHlpSTAMRegisterF(pDrvIns, &pStreamEx->Out.Stats.cbBackendWritableAfter, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 2828 "Host side: Free space in backend buffer after play", "%s/0-HostBackendBufFreeAfter", pStreamEx->Core.szName); 2677 2829 } 2678 2830 … … 2681 2833 if (pCfgGuest->enmDir == PDMAUDIODIR_IN) 2682 2834 { 2683 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesCaptured", pStream ->szName);2684 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream ->In.Stats.TotalFramesCaptured,2835 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesCaptured", pStreamEx->Core.szName); 2836 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->In.Stats.TotalFramesCaptured, 2685 2837 szStatName, STAMUNIT_COUNT, "Total frames played."); 2686 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesCaptured", pStream ->szName);2687 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream ->In.Stats.TotalTimesCaptured,2838 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesCaptured", pStreamEx->Core.szName); 2839 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->In.Stats.TotalTimesCaptured, 2688 2840 szStatName, STAMUNIT_COUNT, "Total number of playbacks."); 2689 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesRead", pStream ->szName);2690 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream ->In.Stats.TotalFramesRead,2841 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesRead", pStreamEx->Core.szName); 2842 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->In.Stats.TotalFramesRead, 2691 2843 szStatName, STAMUNIT_COUNT, "Total frames read."); 2692 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesRead", pStream ->szName);2693 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream ->In.Stats.TotalTimesRead,2844 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesRead", pStreamEx->Core.szName); 2845 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->In.Stats.TotalTimesRead, 2694 2846 szStatName, STAMUNIT_COUNT, "Total number of reads."); 2695 2847 } … … 2697 2849 { 2698 2850 Assert(pCfgGuest->enmDir == PDMAUDIODIR_OUT); 2699 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesPlayed", pStream ->szName);2700 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream ->Out.Stats.TotalFramesPlayed,2851 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesPlayed", pStreamEx->Core.szName); 2852 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->Out.Stats.TotalFramesPlayed, 2701 2853 szStatName, STAMUNIT_COUNT, "Total frames played."); 2702 2854 2703 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesPlayed", pStream ->szName);2704 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream ->Out.Stats.TotalTimesPlayed,2855 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesPlayed", pStreamEx->Core.szName); 2856 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->Out.Stats.TotalTimesPlayed, 2705 2857 szStatName, STAMUNIT_COUNT, "Total number of playbacks."); 2706 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesWritten", pStream ->szName);2707 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream ->Out.Stats.TotalFramesWritten,2858 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalFramesWritten", pStreamEx->Core.szName); 2859 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->Out.Stats.TotalFramesWritten, 2708 2860 szStatName, STAMUNIT_COUNT, "Total frames written."); 2709 2861 2710 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesWritten", pStream ->szName);2711 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStream ->Out.Stats.TotalTimesWritten,2862 RTStrPrintf(szStatName, sizeof(szStatName), "Guest/%s/TotalTimesWritten", pStreamEx->Core.szName); 2863 PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pStreamEx->Out.Stats.TotalTimesWritten, 2712 2864 szStatName, STAMUNIT_COUNT, "Total number of writes."); 2713 2865 } 2714 2866 #endif /* VBOX_WITH_STATISTICS */ 2715 2867 2716 LogFlowFunc(("[%s] Returning %Rrc\n", pStream ->szName, rc));2868 LogFlowFunc(("[%s] Returning %Rrc\n", pStreamEx->Core.szName, rc)); 2717 2869 return rc; 2718 2870 } … … 2721 2873 * @interface_method_impl{PDMIAUDIOCONNECTOR,pfnStreamCreate} 2722 2874 */ 2723 static DECLCALLBACK(int) drvAudioStreamCreate(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfgHost,2875 static DECLCALLBACK(int) drvAudioStreamCreate(PPDMIAUDIOCONNECTOR pInterface, uint32_t fFlags, PPDMAUDIOSTREAMCFG pCfgHost, 2724 2876 PPDMAUDIOSTREAMCFG pCfgGuest, PPDMAUDIOSTREAM *ppStream) 2725 2877 { … … 2730 2882 * Assert sanity. 2731 2883 */ 2884 AssertReturn(!(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF), VERR_INVALID_FLAGS); 2732 2885 AssertPtrReturn(pCfgHost, VERR_INVALID_POINTER); 2733 2886 AssertPtrReturn(pCfgGuest, VERR_INVALID_POINTER); … … 2781 2934 * Allocate and initialize common state. 2782 2935 */ 2783 P PDMAUDIOSTREAM pStream = (PPDMAUDIOSTREAM)RTMemAllocZ(sizeof(PDMAUDIOSTREAM) + RT_ALIGN_Z(cbHstStrm, 64));2784 if (pStream )2936 PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)RTMemAllocZ(sizeof(DRVAUDIOSTREAM) + RT_ALIGN_Z(cbHstStrm, 64)); 2937 if (pStreamEx) 2785 2938 { 2786 2939 /* Retrieve host driver name for easier identification. */ 2787 2940 AssertPtr(pThis->pHostDrvAudio); 2788 2941 PPDMDRVINS pDrvAudioInst = PDMIBASE_2_PDMDRV(pThis->pDrvIns->pDownBase); 2789 RTStrPrintf(pStream ->szName, RT_ELEMENTS(pStream->szName), "[%s] %s",2942 RTStrPrintf(pStreamEx->Core.szName, RT_ELEMENTS(pStreamEx->Core.szName), "[%s] %s", 2790 2943 pDrvAudioInst && pDrvAudioInst->pReg && pDrvAudioInst->pReg->szName[0] 2791 2944 ? pDrvAudioInst->pReg->szName : "none", 2792 2945 pCfgHost->szName[0] != '\0' ? pCfgHost->szName : "<Untitled>"); 2793 2946 2794 pStream ->enmDir = pCfgHost->enmDir;2795 pStream ->cbBackend = (uint32_t)cbHstStrm;2947 pStreamEx->Core.enmDir = pCfgHost->enmDir; 2948 pStreamEx->Core.cbBackend = (uint32_t)cbHstStrm; 2796 2949 if (cbHstStrm) 2797 pStream->pvBackend = pStream + 1; 2950 pStreamEx->pvBackend = pStreamEx + 1; 2951 pStreamEx->fNoMixBufs = RT_BOOL(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF); 2952 pStreamEx->uMagic = DRVAUDIOSTREAM_MAGIC; 2798 2953 2799 2954 /* 2800 2955 * Try to init the rest. 2801 2956 */ 2802 rc = drvAudioStreamInitInternal(pThis, pStream , pCfgHost, pCfgGuest);2957 rc = drvAudioStreamInitInternal(pThis, pStreamEx, fFlags, pCfgHost, pCfgGuest); 2803 2958 if (RT_SUCCESS(rc)) 2804 2959 { 2805 2960 /* Set initial reference counts. */ 2806 pStream ->cRefs = 1;2961 pStreamEx->Core.cRefs = 1; 2807 2962 2808 2963 /* Decrement the free stream counter. */ … … 2813 2968 * We're good. 2814 2969 */ 2815 RTListAppend(&pThis->lstStreams, &pStream ->ListEntry);2970 RTListAppend(&pThis->lstStreams, &pStreamEx->ListEntry); 2816 2971 STAM_COUNTER_INC(&pThis->Stats.TotalStreamsCreated); 2817 *ppStream = pStream;2972 *ppStream = &pStreamEx->Core; 2818 2973 2819 2974 /* … … 2824 2979 if (pThis->In.Cfg.Dbg.fEnabled) 2825 2980 { 2826 AudioHlpFileCreateAndOpen(&pStream ->In.Dbg.pFileCaptureNonInterleaved, pThis->In.Cfg.Dbg.szPathOut,2827 "DrvAudioCapNonInt", pThis->pDrvIns->iInstance, &pStream ->Host.Cfg.Props);2828 AudioHlpFileCreateAndOpen(&pStream ->In.Dbg.pFileStreamRead, pThis->In.Cfg.Dbg.szPathOut,2829 "DrvAudioRead", pThis->pDrvIns->iInstance, &pStream ->Host.Cfg.Props);2981 AudioHlpFileCreateAndOpen(&pStreamEx->In.Dbg.pFileCaptureNonInterleaved, pThis->In.Cfg.Dbg.szPathOut, 2982 "DrvAudioCapNonInt", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props); 2983 AudioHlpFileCreateAndOpen(&pStreamEx->In.Dbg.pFileStreamRead, pThis->In.Cfg.Dbg.szPathOut, 2984 "DrvAudioRead", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props); 2830 2985 } 2831 2986 } … … 2834 2989 if (pThis->Out.Cfg.Dbg.fEnabled) 2835 2990 { 2836 AudioHlpFileCreateAndOpen(&pStream ->Out.Dbg.pFilePlayNonInterleaved, pThis->Out.Cfg.Dbg.szPathOut,2837 "DrvAudioPlayNonInt", pThis->pDrvIns->iInstance, &pStream ->Host.Cfg.Props);2838 AudioHlpFileCreateAndOpen(&pStream ->Out.Dbg.pFileStreamWrite, pThis->Out.Cfg.Dbg.szPathOut,2839 "DrvAudioWrite", pThis->pDrvIns->iInstance, &pStream ->Host.Cfg.Props);2991 AudioHlpFileCreateAndOpen(&pStreamEx->Out.Dbg.pFilePlayNonInterleaved, pThis->Out.Cfg.Dbg.szPathOut, 2992 "DrvAudioPlayNonInt", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props); 2993 AudioHlpFileCreateAndOpen(&pStreamEx->Out.Dbg.pFileStreamWrite, pThis->Out.Cfg.Dbg.szPathOut, 2994 "DrvAudioWrite", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props); 2840 2995 } 2841 2996 } … … 2844 2999 { 2845 3000 LogFunc(("drvAudioStreamInitInternal failed: %Rrc\n", rc)); 2846 int rc2 = drvAudioStreamUninitInternal(pThis, pStream );3001 int rc2 = drvAudioStreamUninitInternal(pThis, pStreamEx); 2847 3002 AssertRC(rc2); 2848 drvAudioStreamFree(pStream );3003 drvAudioStreamFree(pStreamEx); 2849 3004 } 2850 3005 } … … 2885 3040 *pfEnabled = fEnable; 2886 3041 2887 P PDMAUDIOSTREAM pStream;2888 RTListForEach(&pThis->lstStreams, pStream , PDMAUDIOSTREAM, ListEntry)2889 { 2890 if (pStream ->enmDir != enmDir) /* Skip unwanted streams. */3042 PDRVAUDIOSTREAM pStreamEx; 3043 RTListForEach(&pThis->lstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry) 3044 { 3045 if (pStreamEx->Core.enmDir != enmDir) /* Skip unwanted streams. */ 2891 3046 continue; 2892 3047 … … 2901 3056 * See @bugref{9882}. 2902 3057 */ 2903 int rc2 = drvAudioStreamControlInternalBackend(pThis, pStream ,3058 int rc2 = drvAudioStreamControlInternalBackend(pThis, pStreamEx, 2904 3059 fEnable ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE); 2905 3060 if (RT_FAILURE(rc2)) 2906 3061 { 2907 3062 if (rc2 == VERR_AUDIO_STREAM_NOT_READY) 2908 { 2909 LogRel(("Audio: Stream '%s' not available\n", pStream->szName)); 2910 } 3063 LogRel(("Audio: Stream '%s' not available\n", pStreamEx->Core.szName)); 2911 3064 else 2912 LogRel(("Audio: Failed to %s %s stream '%s', rc=%Rrc\n", 2913 fEnable ? "enable" : "disable", enmDir == PDMAUDIODIR_IN ? "input" : "output", pStream->szName, rc2));3065 LogRel(("Audio: Failed to %s %s stream '%s', rc=%Rrc\n", fEnable ? "enable" : "disable", 3066 enmDir == PDMAUDIODIR_IN ? "input" : "output", pStreamEx->Core.szName, rc2)); 2914 3067 } 2915 3068 else … … 2917 3070 /* When (re-)enabling a stream, clear the disabled warning bit again. */ 2918 3071 if (fEnable) 2919 pStream ->fWarningsShown &= ~PDMAUDIOSTREAM_WARN_FLAGS_DISABLED;3072 pStreamEx->Core.fWarningsShown &= ~PDMAUDIOSTREAM_WARN_FLAGS_DISABLED; 2920 3073 } 2921 3074 … … 3013 3166 PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector); 3014 3167 AssertPtr(pThis); 3015 AssertPtrReturn(pStream, 0); 3016 AssertMsg(pStream->enmDir == PDMAUDIODIR_IN, ("Can't read from a non-input stream\n")); 3168 PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream; 3169 AssertPtrReturn(pStreamEx, 0); 3170 AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, 0); 3171 AssertReturn(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, 0); 3172 AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_IN, ("Can't read from a non-input stream\n")); 3017 3173 int rc = RTCritSectEnter(&pThis->CritSect); 3018 3174 AssertRCReturn(rc, 0); … … 3027 3183 3028 3184 if ( pThis->pHostDrvAudio 3029 && ( PDMAudioStrmStatusCanRead(pStream ->fStatus)3185 && ( PDMAudioStrmStatusCanRead(pStreamEx->Core.fStatus) 3030 3186 || fDisabled) 3031 3187 ) 3032 3188 { 3033 const uint32_t cfReadable = AudioMixBufLive(&pStream->Guest.MixBuf); 3034 3035 cbReadable = AUDIOMIXBUF_F2B(&pStream->Guest.MixBuf, cfReadable); 3189 if (pStreamEx->fNoMixBufs) 3190 cbReadable = pThis->pHostDrvAudio ? pThis->pHostDrvAudio->pfnStreamGetReadable(pThis->pHostDrvAudio, pStream) : 0; 3191 else 3192 { 3193 const uint32_t cfReadable = AudioMixBufLive(&pStreamEx->Guest.MixBuf); 3194 cbReadable = AUDIOMIXBUF_F2B(&pStreamEx->Guest.MixBuf, cfReadable); 3195 } 3036 3196 3037 3197 if (!cbReadable) … … 3047 3207 PDMAUDIOSTREAMSTS fStatus = PDMAUDIOSTREAMSTS_FLAGS_NONE; 3048 3208 if (pThis->pHostDrvAudio->pfnStreamGetStatus) 3049 fStatus = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStream ->pvBackend);3209 fStatus = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pStreamEx->pvBackend); 3050 3210 if ( !PDMAudioStrmStatusCanRead(fStatus) 3051 3211 || fDisabled) 3052 3212 { 3053 cbReadable = PDMAudioPropsNanoToBytes(&pStream->Host.Cfg.Props, RTTimeNanoTS() - pStream->tsLastReadWrittenNs); 3054 if (!(pStream->fWarningsShown & PDMAUDIOSTREAM_WARN_FLAGS_DISABLED)) 3213 cbReadable = PDMAudioPropsNanoToBytes(&pStreamEx->Host.Cfg.Props, 3214 RTTimeNanoTS() - pStreamEx->nsLastReadWritten); 3215 if (!(pStreamEx->Core.fWarningsShown & PDMAUDIOSTREAM_WARN_FLAGS_DISABLED)) 3055 3216 { 3056 3217 if (fDisabled) … … 3058 3219 else 3059 3220 LogRel(("Audio: Warning: Input for stream '%s' of driver '%s' not ready (current input status is %#x), returning silence\n", 3060 pStream ->szName, pThis->szName, fStatus));3061 3062 pStream ->fWarningsShown |= PDMAUDIOSTREAM_WARN_FLAGS_DISABLED;3221 pStreamEx->Core.szName, pThis->szName, fStatus)); 3222 3223 pStreamEx->Core.fWarningsShown |= PDMAUDIOSTREAM_WARN_FLAGS_DISABLED; 3063 3224 } 3064 3225 } … … 3067 3228 /* Make sure to align the readable size to the guest's frame size. */ 3068 3229 if (cbReadable) 3069 cbReadable = PDMAudioPropsFloorBytesToFrame(&pStream ->Guest.Cfg.Props, cbReadable);3230 cbReadable = PDMAudioPropsFloorBytesToFrame(&pStreamEx->Guest.Cfg.Props, cbReadable); 3070 3231 } 3071 3232 3072 3233 RTCritSectLeave(&pThis->CritSect); 3073 3234 Log3Func(("[%s] cbReadable=%RU32 (%RU64ms)\n", 3074 pStream ->szName, cbReadable, PDMAudioPropsBytesToMilli(&pStream->Host.Cfg.Props, cbReadable)));3235 pStreamEx->Core.szName, cbReadable, PDMAudioPropsBytesToMilli(&pStreamEx->Host.Cfg.Props, cbReadable))); 3075 3236 return cbReadable; 3076 3237 } … … 3083 3244 PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector); 3084 3245 AssertPtr(pThis); 3085 AssertPtrReturn(pStream, 0); 3086 AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT, ("Can't write to a non-output stream\n")); 3246 PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream; 3247 AssertPtrReturn(pStreamEx, 0); 3248 AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, 0); 3249 AssertReturn(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, 0); 3250 AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT, ("Can't write to a non-output stream\n")); 3087 3251 int rc = RTCritSectEnter(&pThis->CritSect); 3088 3252 AssertRCReturn(rc, 0); … … 3095 3259 /* Note: We don't propage the backend stream's status to the outside -- it's the job of this 3096 3260 * audio connector to make sense of it. */ 3097 if (PDMAudioStrmStatusCanWrite(pStream->fStatus)) 3098 { 3099 cbWritable = AudioMixBufFreeBytes(&pStream->Host.MixBuf); 3261 if (PDMAudioStrmStatusCanWrite(pStreamEx->Core.fStatus)) 3262 { 3263 if (pStreamEx->fNoMixBufs) 3264 cbWritable = pThis->pHostDrvAudio ? pThis->pHostDrvAudio->pfnStreamGetWritable(pThis->pHostDrvAudio, pStream) : 0; 3265 else 3266 cbWritable = AudioMixBufFreeBytes(&pStreamEx->Host.MixBuf); 3100 3267 3101 3268 /* Make sure to align the writable size to the host's frame size. */ 3102 cbWritable = PDMAudioPropsFloorBytesToFrame(&pStream ->Host.Cfg.Props, cbWritable);3269 cbWritable = PDMAudioPropsFloorBytesToFrame(&pStreamEx->Host.Cfg.Props, cbWritable); 3103 3270 } 3104 3271 3105 3272 RTCritSectLeave(&pThis->CritSect); 3106 3273 Log3Func(("[%s] cbWritable=%RU32 (%RU64ms)\n", 3107 pStream ->szName, cbWritable, PDMAudioPropsBytesToMilli(&pStream->Host.Cfg.Props, cbWritable)));3274 pStreamEx->Core.szName, cbWritable, PDMAudioPropsBytesToMilli(&pStreamEx->Host.Cfg.Props, cbWritable))); 3108 3275 return cbWritable; 3109 3276 } … … 3117 3284 AssertPtr(pThis); 3118 3285 3286 /** @todo r=bird: It is not documented that we ignore NULL streams... Why is 3287 * this necessary? */ 3119 3288 if (!pStream) 3120 3289 return PDMAUDIOSTREAMSTS_FLAGS_NONE; 3290 PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream; 3291 AssertPtrReturn(pStreamEx, PDMAUDIOSTREAMSTS_FLAGS_NONE); 3292 AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, PDMAUDIOSTREAMSTS_FLAGS_NONE); 3293 AssertReturn(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, PDMAUDIOSTREAMSTS_FLAGS_NONE); 3121 3294 3122 3295 int rc = RTCritSectEnter(&pThis->CritSect); … … 3124 3297 3125 3298 /* Is the stream scheduled for re-initialization? Do so now. */ 3126 drvAudioStreamMaybeReInit(pThis, pStream );3127 3128 PDMAUDIOSTREAMSTS fStrmStatus = pStream ->fStatus;3299 drvAudioStreamMaybeReInit(pThis, pStreamEx); 3300 3301 PDMAUDIOSTREAMSTS fStrmStatus = pStreamEx->Core.fStatus; 3129 3302 3130 3303 RTCritSectLeave(&pThis->CritSect); … … 3132 3305 char szStreamSts[DRVAUDIO_STATUS_STR_MAX]; 3133 3306 #endif 3134 Log3Func(("[%s] %s\n", pStream ->szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus)));3307 Log3Func(("[%s] %s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, fStrmStatus))); 3135 3308 return fStrmStatus; 3136 3309 } … … 3142 3315 { 3143 3316 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 3144 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 3145 AssertPtrReturn(pVol, VERR_INVALID_POINTER); 3146 3147 LogFlowFunc(("[%s] volL=%RU32, volR=%RU32, fMute=%RTbool\n", pStream->szName, pVol->uLeft, pVol->uRight, pVol->fMuted)); 3148 3149 AudioMixBufSetVolume(&pStream->Guest.MixBuf, pVol); 3150 AudioMixBufSetVolume(&pStream->Host.MixBuf, pVol); 3317 PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream; 3318 AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER); 3319 AssertPtrReturn(pVol, VERR_INVALID_POINTER); 3320 AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 3321 AssertReturn(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC); 3322 3323 LogFlowFunc(("[%s] volL=%RU32, volR=%RU32, fMute=%RTbool\n", pStreamEx->Core.szName, pVol->uLeft, pVol->uRight, pVol->fMuted)); 3324 AssertReturn(!pStreamEx->fNoMixBufs, VERR_ACCESS_DENIED); 3325 3326 AudioMixBufSetVolume(&pStreamEx->Guest.MixBuf, pVol); 3327 AudioMixBufSetVolume(&pStreamEx->Host.MixBuf, pVol); 3151 3328 3152 3329 return VINF_SUCCESS; … … 3160 3337 * 3161 3338 * @returns VBox status code. 3162 * @param pThis 3163 * @param pStream 3164 */ 3165 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, P PDMAUDIOSTREAM pStream)3166 { 3167 AssertPtr Return(pThis, VERR_INVALID_POINTER);3168 AssertPtr Return(pStream, VERR_INVALID_POINTER);3339 * @param pThis Pointer to driver instance. 3340 * @param pStreamEx Audio stream destruct backend for. 3341 */ 3342 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx) 3343 { 3344 AssertPtr(pThis); 3345 AssertPtr(pStreamEx); 3169 3346 3170 3347 int rc = VINF_SUCCESS; … … 3173 3350 char szStreamSts[DRVAUDIO_STATUS_STR_MAX]; 3174 3351 #endif 3175 LogFunc(("[%s] fStatus=%s\n", pStream ->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));3176 3177 if (pStream ->fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED)3178 { 3179 AssertPtr(pStream ->pvBackend);3352 LogFunc(("[%s] fStatus=%s\n", pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus))); 3353 3354 if (pStreamEx->Core.fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED) 3355 { 3356 AssertPtr(pStreamEx->pvBackend); 3180 3357 3181 3358 /* Check if the pointer to the host audio driver is still valid. 3182 3359 * It can be NULL if we were called in drvAudioDestruct, for example. */ 3183 3360 if (pThis->pHostDrvAudio) 3184 rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pStream ->pvBackend);3185 3186 pStream ->fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED;3187 } 3188 3189 LogFlowFunc(("[%s] Returning %Rrc\n", pStream ->szName, rc));3361 rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pStreamEx->pvBackend); 3362 3363 pStreamEx->Core.fStatus &= ~PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED; 3364 } 3365 3366 LogFlowFunc(("[%s] Returning %Rrc\n", pStreamEx->Core.szName, rc)); 3190 3367 return rc; 3191 3368 } … … 3196 3373 * 3197 3374 * @returns VBox status code. 3198 * @param pThis 3199 * @param pStream 3375 * @param pThis Pointer to driver instance. 3376 * @param pStreamEx Pointer to audio stream to uninitialize. 3200 3377 * 3201 3378 * @note Caller owns the critical section. 3202 3379 */ 3203 static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, P PDMAUDIOSTREAM pStream)3380 static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx) 3204 3381 { 3205 3382 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 3206 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 3207 AssertMsgReturn(pStream->cRefs <= 1, 3208 ("Stream '%s' still has %RU32 references held when uninitializing\n", pStream->szName, pStream->cRefs), 3383 AssertMsgReturn(pStreamEx->Core.cRefs <= 1, 3384 ("Stream '%s' still has %RU32 references held when uninitializing\n", pStreamEx->Core.szName, pStreamEx->Core.cRefs), 3209 3385 VERR_WRONG_ORDER); 3210 LogFlowFunc(("[%s] cRefs=%RU32\n", pStream ->szName, pStream->cRefs));3386 LogFlowFunc(("[%s] cRefs=%RU32\n", pStreamEx->Core.szName, pStreamEx->Core.cRefs)); 3211 3387 3212 3388 /* 3213 3389 * ... 3214 3390 */ 3215 int rc = drvAudioStreamControlInternal(pThis, pStream , PDMAUDIOSTREAMCMD_DISABLE);3391 int rc = drvAudioStreamControlInternal(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE); 3216 3392 if (RT_SUCCESS(rc)) 3217 rc = drvAudioStreamDestroyInternalBackend(pThis, pStream );3393 rc = drvAudioStreamDestroyInternalBackend(pThis, pStreamEx); 3218 3394 3219 3395 /* Destroy mixing buffers. */ 3220 AudioMixBufDestroy(&pStream ->Guest.MixBuf);3221 AudioMixBufDestroy(&pStream ->Host.MixBuf);3396 AudioMixBufDestroy(&pStreamEx->Guest.MixBuf); 3397 AudioMixBufDestroy(&pStreamEx->Host.MixBuf); 3222 3398 3223 3399 if (RT_SUCCESS(rc)) 3224 3400 { 3225 3401 #ifdef LOG_ENABLED 3226 if (pStream ->fStatus != PDMAUDIOSTREAMSTS_FLAGS_NONE)3402 if (pStreamEx->Core.fStatus != PDMAUDIOSTREAMSTS_FLAGS_NONE) 3227 3403 { 3228 3404 char szStreamSts[DRVAUDIO_STATUS_STR_MAX]; 3229 3405 LogFunc(("[%s] Warning: Still has %s set when uninitializing\n", 3230 pStream ->szName, dbgAudioStreamStatusToStr(szStreamSts, pStream->fStatus)));3406 pStreamEx->Core.szName, dbgAudioStreamStatusToStr(szStreamSts, pStreamEx->Core.fStatus))); 3231 3407 } 3232 3408 #endif 3233 pStream ->fStatus = PDMAUDIOSTREAMSTS_FLAGS_NONE;3409 pStreamEx->Core.fStatus = PDMAUDIOSTREAMSTS_FLAGS_NONE; 3234 3410 } 3235 3411 3236 3412 PPDMDRVINS const pDrvIns = pThis->pDrvIns; 3237 if (pStream ->enmDir == PDMAUDIODIR_IN)3413 if (pStreamEx->Core.enmDir == PDMAUDIODIR_IN) 3238 3414 { 3239 3415 #ifdef VBOX_WITH_STATISTICS 3240 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream ->In.Stats.TotalFramesCaptured);3241 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream ->In.Stats.TotalTimesCaptured);3242 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream ->In.Stats.TotalFramesRead);3243 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream ->In.Stats.TotalTimesRead);3416 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->In.Stats.TotalFramesCaptured); 3417 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->In.Stats.TotalTimesCaptured); 3418 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->In.Stats.TotalFramesRead); 3419 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->In.Stats.TotalTimesRead); 3244 3420 #endif 3245 3421 if (pThis->In.Cfg.Dbg.fEnabled) 3246 3422 { 3247 AudioHlpFileDestroy(pStream->In.Dbg.pFileCaptureNonInterleaved); 3248 pStream->In.Dbg.pFileCaptureNonInterleaved = NULL; 3249 3250 AudioHlpFileDestroy(pStream->In.Dbg.pFileStreamRead); 3251 pStream->In.Dbg.pFileStreamRead = NULL; 3252 } 3253 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Host.MixBuf.cMixed); 3254 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Guest.MixBuf.cUsed); 3423 AudioHlpFileDestroy(pStreamEx->In.Dbg.pFileCaptureNonInterleaved); 3424 pStreamEx->In.Dbg.pFileCaptureNonInterleaved = NULL; 3425 3426 AudioHlpFileDestroy(pStreamEx->In.Dbg.pFileStreamRead); 3427 pStreamEx->In.Dbg.pFileStreamRead = NULL; 3428 } 3429 if (!pStreamEx->fNoMixBufs) 3430 { 3431 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Host.MixBuf.cMixed); 3432 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Guest.MixBuf.cUsed); 3433 } 3255 3434 } 3256 3435 else 3257 3436 { 3258 Assert(pStream ->enmDir == PDMAUDIODIR_OUT);3437 Assert(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT); 3259 3438 #ifdef VBOX_WITH_STATISTICS 3260 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream ->Out.Stats.TotalFramesPlayed);3261 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream ->Out.Stats.TotalTimesPlayed);3262 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream ->Out.Stats.TotalFramesWritten);3263 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream ->Out.Stats.TotalTimesWritten);3439 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.TotalFramesPlayed); 3440 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.TotalTimesPlayed); 3441 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.TotalFramesWritten); 3442 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.TotalTimesWritten); 3264 3443 #endif 3265 3444 if (pThis->Out.Cfg.Dbg.fEnabled) 3266 3445 { 3267 AudioHlpFileDestroy(pStream->Out.Dbg.pFilePlayNonInterleaved); 3268 pStream->Out.Dbg.pFilePlayNonInterleaved = NULL; 3269 3270 AudioHlpFileDestroy(pStream->Out.Dbg.pFileStreamWrite); 3271 pStream->Out.Dbg.pFileStreamWrite = NULL; 3272 } 3273 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.cbBackendWritableAfter); 3274 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Out.Stats.cbBackendWritableBefore); 3275 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Host.MixBuf.cUsed); 3276 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Guest.MixBuf.cMixed); 3277 } 3278 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Host.Cfg.Backend.cFramesBufferSize); 3279 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Host.MixBuf.cFrames); 3280 PDMDrvHlpSTAMDeregister(pDrvIns, &pStream->Guest.MixBuf.cFrames); 3446 AudioHlpFileDestroy(pStreamEx->Out.Dbg.pFilePlayNonInterleaved); 3447 pStreamEx->Out.Dbg.pFilePlayNonInterleaved = NULL; 3448 3449 AudioHlpFileDestroy(pStreamEx->Out.Dbg.pFileStreamWrite); 3450 pStreamEx->Out.Dbg.pFileStreamWrite = NULL; 3451 } 3452 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.cbBackendWritableAfter); 3453 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Out.Stats.cbBackendWritableBefore); 3454 if (!pStreamEx->fNoMixBufs) 3455 { 3456 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Host.MixBuf.cUsed); 3457 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Guest.MixBuf.cMixed); 3458 } 3459 } 3460 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Host.Cfg.Backend.cFramesBufferSize); 3461 if (!pStreamEx->fNoMixBufs) 3462 { 3463 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Host.MixBuf.cFrames); 3464 PDMDrvHlpSTAMDeregister(pDrvIns, &pStreamEx->Guest.MixBuf.cFrames); 3465 } 3281 3466 3282 3467 LogFlowFunc(("Returning %Rrc\n", rc)); … … 3295 3480 return VINF_SUCCESS; 3296 3481 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 3297 Assert(pStream->uMagic == PDMAUDIOSTREAM_MAGIC); 3482 PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream; /* Note! Do not touch pStream after this! */ 3483 Assert(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC); 3484 Assert(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC); 3298 3485 3299 3486 int rc = RTCritSectEnter(&pThis->CritSect); 3300 3487 AssertRCReturn(rc, rc); 3301 3488 3302 LogRel2(("Audio: Destroying stream '%s'\n", pStream ->szName));3303 3304 LogFlowFunc(("[%s] cRefs=%RU32\n", pStream ->szName, pStream->cRefs));3305 AssertMsg(pStream ->cRefs <= 1, ("%u %s\n", pStream->cRefs, pStream->szName));3306 if (pStream ->cRefs <= 1)3307 { 3308 rc = drvAudioStreamUninitInternal(pThis, pStream );3489 LogRel2(("Audio: Destroying stream '%s'\n", pStreamEx->Core.szName)); 3490 3491 LogFlowFunc(("[%s] cRefs=%RU32\n", pStreamEx->Core.szName, pStreamEx->Core.cRefs)); 3492 AssertMsg(pStreamEx->Core.cRefs <= 1, ("%u %s\n", pStreamEx->Core.cRefs, pStreamEx->Core.szName)); 3493 if (pStreamEx->Core.cRefs <= 1) 3494 { 3495 rc = drvAudioStreamUninitInternal(pThis, pStreamEx); 3309 3496 if (RT_SUCCESS(rc)) 3310 3497 { 3311 if (pStream ->enmDir == PDMAUDIODIR_IN)3498 if (pStreamEx->Core.enmDir == PDMAUDIODIR_IN) 3312 3499 pThis->In.cStreamsFree++; 3313 3500 else /* Out */ 3314 3501 pThis->Out.cStreamsFree++; 3315 3502 3316 RTListNodeRemove(&pStream->ListEntry); 3317 3318 drvAudioStreamFree(pStream); 3503 RTListNodeRemove(&pStreamEx->ListEntry); 3504 3505 drvAudioStreamFree(pStreamEx); 3506 pStreamEx = NULL; 3319 3507 pStream = NULL; 3320 3508 } 3321 3509 else 3322 LogRel(("Audio: Uninitializing stream '%s' failed with %Rrc\n", pStream ->szName, rc));3510 LogRel(("Audio: Uninitializing stream '%s' failed with %Rrc\n", pStreamEx->Core.szName, rc)); 3323 3511 } 3324 3512 else … … 3375 3563 * in drvAudioDestruct(). 3376 3564 */ 3377 P PDMAUDIOSTREAM pStream;3378 RTListForEach(&pThis->lstStreams, pStream , PDMAUDIOSTREAM, ListEntry)3379 { 3380 drvAudioStreamControlInternalBackend(pThis, pStream , PDMAUDIOSTREAMCMD_DISABLE);3381 drvAudioStreamDestroyInternalBackend(pThis, pStream );3565 PDRVAUDIOSTREAM pStreamEx; 3566 RTListForEach(&pThis->lstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry) 3567 { 3568 drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE); 3569 drvAudioStreamDestroyInternalBackend(pThis, pStreamEx); 3382 3570 } 3383 3571 … … 3534 3722 pThis->pHostDrvAudio = NULL; 3535 3723 3536 P PDMAUDIOSTREAM pStream, pStreamNext;3537 RTListForEachSafe(&pThis->lstStreams, pStream , pStreamNext, PDMAUDIOSTREAM, ListEntry)3538 { 3539 int rc = drvAudioStreamUninitInternal(pThis, pStream );3724 PDRVAUDIOSTREAM pStreamEx, pStreamExNext; 3725 RTListForEachSafe(&pThis->lstStreams, pStreamEx, pStreamExNext, DRVAUDIOSTREAM, ListEntry) 3726 { 3727 int rc = drvAudioStreamUninitInternal(pThis, pStreamEx); 3540 3728 if (RT_SUCCESS(rc)) 3541 3729 { 3542 RTListNodeRemove(&pStream->ListEntry); 3543 3544 drvAudioStreamFree(pStream); 3545 pStream = NULL; 3730 RTListNodeRemove(&pStreamEx->ListEntry); 3731 drvAudioStreamFree(pStreamEx); 3546 3732 } 3547 3733 } -
trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp
r88314 r88356 206 206 * General stuff. 207 207 */ 208 PDMAUDIOMIXBUF mb;208 AUDIOMIXBUF mb; 209 209 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&mb, "Single", &config, cBufSize)); 210 210 RTTESTI_CHECK(AudioMixBufSize(&mb) == cBufSize); … … 323 323 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p)); 324 324 325 PDMAUDIOMIXBUF parent;325 AUDIOMIXBUF parent; 326 326 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cParentBufSize)); 327 327 … … 340 340 uint32_t cChildBufSize = RTRandU32Ex(cFrames /* Min */, 64 /* Max */); 341 341 342 PDMAUDIOMIXBUF child1;342 AUDIOMIXBUF child1; 343 343 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child1, "Child1", &cfg_c1, cChildBufSize)); 344 344 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child1, &parent)); … … 355 355 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c2)); 356 356 357 PDMAUDIOMIXBUF child2;357 AUDIOMIXBUF child2; 358 358 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child2, "Child2", &cfg_c2, cChildBufSize)); 359 359 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child2, &parent)); … … 460 460 PDMAUDIOPCMPROPS const CfgDst = PDMAUDIOPCMPROPS_INITIALIZER(2 /*cbSample*/, true /*fSigned*/, 2 /*ch*/, uToHz, false /*fSwap*/); 461 461 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&CfgDst)); 462 PDMAUDIOMIXBUF Parent;462 AUDIOMIXBUF Parent; 463 463 RTTESTI_CHECK_RC_OK_RETV(AudioMixBufInit(&Parent, "ParentDownsampling", &CfgDst, cFramesParent)); 464 464 … … 467 467 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&CfgSrc)); 468 468 uint32_t const cFramesChild = RTRandU32Ex(32, RT_ELEMENTS(aSrcFrames)); 469 PDMAUDIOMIXBUF Child;469 AUDIOMIXBUF Child; 470 470 RTTESTI_CHECK_RC_OK_RETV(AudioMixBufInit(&Child, "ChildDownsampling", &CfgSrc, cFramesChild)); 471 471 RTTESTI_CHECK_RC_OK_RETV(AudioMixBufLinkTo(&Child, &Parent)); … … 567 567 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p)); 568 568 569 PDMAUDIOMIXBUF parent;569 AUDIOMIXBUF parent; 570 570 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cBufSize)); 571 571 … … 589 589 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c)); 590 590 591 PDMAUDIOMIXBUF child;591 AUDIOMIXBUF child; 592 592 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg_c, cBufSize)); 593 593 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent)); … … 669 669 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_p)); 670 670 671 PDMAUDIOMIXBUF parent;671 AUDIOMIXBUF parent; 672 672 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg_p, cBufSize)); 673 673 … … 683 683 RTTESTI_CHECK(AudioHlpPcmPropsAreValid(&cfg_c)); 684 684 685 PDMAUDIOMIXBUF child;685 AUDIOMIXBUF child; 686 686 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg_c, cBufSize)); 687 687 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent)); … … 763 763 764 764 PDMAUDIOVOLUME vol = { false, 0, 0 }; /* Not muted. */ 765 PDMAUDIOMIXBUF parent;765 AUDIOMIXBUF parent; 766 766 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&parent, "Parent", &cfg, cBufSize)); 767 767 768 PDMAUDIOMIXBUF child;768 AUDIOMIXBUF child; 769 769 RTTESTI_CHECK_RC_OK(AudioMixBufInit(&child, "Child", &cfg, cBufSize)); 770 770 RTTESTI_CHECK_RC_OK(AudioMixBufLinkTo(&child, &parent));
Note:
See TracChangeset
for help on using the changeset viewer.