- Timestamp:
- May 31, 2016 8:43:19 AM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 107614
- Location:
- trunk
- Files:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Config.kmk
r61312 r61320 430 430 # Enable new PS/2 mouse emulation. 431 431 VBOX_WITH_NEW_PS2M = 1 432 # Enable ALSA support for Linux. 432 # Enable OSS audio support. 433 VBOX_WITH_OSS = 1 434 # Enable ALSA audio support. 433 435 VBOX_WITH_ALSA = 1 434 # Enable Pulse support for Linux.436 # Enable PulseAudio audio support. 435 437 VBOX_WITH_PULSE = 1 436 438 # Enable PCI passthrough support. -
trunk/include/VBox/vmm/pdmaudioifs.h
r61166 r61320 381 381 /** Size of the sample buffer (in samples). */ 382 382 uint32_t cSamples; 383 #if 1 384 /** The current read/write position (in samples)385 * in the samples buffer. */386 uint32_t off ReadWrite;383 /** The current read position (in samples). */ 384 uint32_t offRead; 385 /** The current write position (in samples). */ 386 uint32_t offWrite; 387 387 /** 388 388 * Total samples already mixed down to the parent buffer (if any). Always starting at 389 * the parent's offRead Writeposition.389 * the parent's offRead position. 390 390 * 391 391 * Note: Count always is specified in parent samples, as the sample count can differ between parent … … 393 393 */ 394 394 uint32_t cMixed; 395 uint32_t cProcessed; 396 #else 397 /** The current read position in the buffer. */ 398 uint32_t offRead; 399 /** Is a read block acquired currently? */ 400 bool fReading; 401 /** Is a write block acquired currently? */ 402 bool fWriting; 403 /** The current write position in the buffer. */ 404 uint32_t offWrite; 405 /** How much space of the buffer is currently in use. */ 406 volatile uint32_t cUsed; 407 uint32_t cMixed; 408 #endif 395 /** How much audio samples are currently being used 396 * in this buffer. 397 * Note: This also is known as the distance in ring buffer terms. */ 398 uint32_t cUsed; 409 399 /** Pointer to parent buffer (if any). */ 410 400 PPDMAUDIOMIXBUF pParent; 411 401 /** List of children mix buffers to keep in sync with (if being a parent buffer). */ 412 RTLISTANCHOR lst Buffers;402 RTLISTANCHOR lstChildren; 413 403 /** Intermediate structure for buffer conversion tasks. */ 414 404 PPDMAUDIOSTRMRATE pRate; … … 453 443 * which rely on its data. */ 454 444 #define PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE RT_BIT_32(3) 445 /** Data can be read from the stream. */ 446 #define PDMAUDIOSTRMSTS_FLAG_DATA_READABLE RT_BIT_32(4) 447 /** Data can be written to the stream. */ 448 #define PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE RT_BIT_32(5) 455 449 /** Validation mask. */ 456 #define PDMAUDIOSTRMSTS_VALID_MASK UINT32_C(0x000000 0F)450 #define PDMAUDIOSTRMSTS_VALID_MASK UINT32_C(0x0000003F) 457 451 458 452 /** … … 581 575 { 582 576 /** 577 * Retrieves the current configuration of the host audio backend. 578 * 579 * @returns VBox status code. 580 * 581 * @param pInterface Pointer to the interface structure containing the called function pointer. 582 * @param pCfg Where to store the host audio backend configuration data. 583 */ 584 DECLR3CALLBACKMEMBER(int, pfnGetConfig, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg)); 585 586 /** 587 * @todo Docs! 588 */ 589 DECLR3CALLBACKMEMBER(PDMAUDIOBACKENDSTS, pfnGetStatus, (PPDMIAUDIOCONNECTOR pInterface, PDMAUDIODIR enmDir)); 590 591 /** 592 * Creates an audio stream. 593 * 594 * @returns VBox status code. 595 * @param pInterface Pointer to the interface structure containing the called function pointer. 596 * @param pCfgHost Stream configuration for host side. 597 * @param pCfgGuest Stream configuration for guest side. 598 * @param ppStream Pointer where to return the created audio stream on success. 599 */ 600 DECLR3CALLBACKMEMBER(int, pfnStreamCreate, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfgHost, PPDMAUDIOSTREAMCFG pCfgGuest, PPDMAUDIOSTREAM *ppStream)); 601 602 /** 603 * Destroys an audio stream. 604 * 605 * @param pInterface Pointer to the interface structure containing the called function pointer. 606 * @param pStream Pointer to audio stream. 607 */ 608 DECLR3CALLBACKMEMBER(int, pfnStreamDestroy, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream)); 609 610 /** 583 611 * Adds a reference to the specified audio stream. 584 612 * … … 623 651 624 652 /** 625 * Retrieves the current configuration of the host audio backend.626 *627 * @returns VBox status code.628 *629 * @param pInterface Pointer to the interface structure containing the called function pointer.630 * @param pCfg Where to store the host audio backend configuration data.631 */632 DECLR3CALLBACKMEMBER(int, pfnGetConfig, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg));633 634 /**635 * Creates an audio stream.636 *637 * @returns VBox status code.638 * @param pInterface Pointer to the interface structure containing the called function pointer.639 * @param pCfgHost Stream configuration for host side.640 * @param pCfgGuest Stream configuration for guest side.641 * @param ppStream Pointer where to return the created audio stream on success.642 */643 DECLR3CALLBACKMEMBER(int, pfnStreamCreate, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfgHost, PPDMAUDIOSTREAMCFG pCfgGuest, PPDMAUDIOSTREAM *ppStream));644 645 /**646 * Destroys an audio stream.647 *648 * @param pInterface Pointer to the interface structure containing the called function pointer.649 * @param pStream Pointer to audio stream.650 */651 DECLR3CALLBACKMEMBER(int, pfnStreamDestroy, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream));652 653 /**654 653 * Controls a specific audio stream. 655 654 * … … 662 661 663 662 /** 664 * Processes stream data and optionally returns its current status.663 * Processes stream data. 665 664 * 666 665 * @param pInterface Pointer to the interface structure containing the called function pointer. 666 * @param pStream Pointer to audio stream. 667 667 * @param pcData Data (in audio samples) available. Optional. 668 668 */ 669 DECLR3CALLBACKMEMBER(int, pfnStream GetData, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, uint32_t *pcData));669 DECLR3CALLBACKMEMBER(int, pfnStreamIterate, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream)); 670 670 671 671 /** … … 695 695 696 696 /** PDMIAUDIOCONNECTOR interface ID. */ 697 #define PDMIAUDIOCONNECTOR_IID "9 CDE2581-41B1-838E-24A5-448B2D0C822E"697 #define PDMIAUDIOCONNECTOR_IID "9E03C980-64E9-42EC-9C70-316995990BE3" 698 698 699 699 … … 714 714 pThis->IHostAudio.pfnStreamControl = RT_CONCAT(a_NamePrefix,StreamControl); \ 715 715 pThis->IHostAudio.pfnStreamGetStatus = RT_CONCAT(a_NamePrefix,StreamGetStatus); \ 716 pThis->IHostAudio.pfnStreamIterate = RT_CONCAT(a_NamePrefix,StreamIterate); \ 716 717 pThis->IHostAudio.pfnStreamPlay = RT_CONCAT(a_NamePrefix,StreamPlay); \ 717 718 pThis->IHostAudio.pfnStreamCapture = RT_CONCAT(a_NamePrefix,StreamCapture); \ … … 798 799 799 800 /** 801 ** @todo Docs! 802 */ 803 DECLR3CALLBACKMEMBER(int, pfnStreamIterate, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream)); 804 805 /** 800 806 * Plays an audio (output) stream. 801 807 * … … 820 826 821 827 /** PDMIHOSTAUDIO interface ID. */ 822 #define PDMIHOSTAUDIO_IID "9 46441D4-7C82-4654-90DD-443BEF796E21"828 #define PDMIHOSTAUDIO_IID "96AC69D0-F301-42AC-8F1D-1E19BA808887" 823 829 824 830 /** @} */ -
trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
r61187 r61320 61 61 #endif 62 62 63 DECLINLINE(void) audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf); 63 64 64 65 /* … … 177 178 178 179 uint32_t cSamplesRead; 179 if (pMixBuf->offRead Write+ cSamplesToRead > pMixBuf->cSamples)180 { 181 cSamplesRead = pMixBuf->cSamples - pMixBuf->offRead Write;180 if (pMixBuf->offRead + cSamplesToRead > pMixBuf->cSamples) 181 { 182 cSamplesRead = pMixBuf->cSamples - pMixBuf->offRead; 182 183 rc = VINF_TRY_AGAIN; 183 184 } … … 188 189 } 189 190 190 *ppvSamples = &pMixBuf->pSamples[pMixBuf->offRead Write];191 *ppvSamples = &pMixBuf->pSamples[pMixBuf->offRead]; 191 192 AssertPtr(ppvSamples); 192 193 193 pMixBuf->offRead Write = (pMixBuf->offReadWrite+ cSamplesRead) % pMixBuf->cSamples;194 Assert(pMixBuf->offRead Write<= pMixBuf->cSamples);195 pMixBuf->c Processed -= RT_MIN(cSamplesRead, pMixBuf->cProcessed);194 pMixBuf->offRead = (pMixBuf->offRead + cSamplesRead) % pMixBuf->cSamples; 195 Assert(pMixBuf->offRead <= pMixBuf->cSamples); 196 pMixBuf->cUsed -= RT_MIN(cSamplesRead, pMixBuf->cUsed); 196 197 197 198 *pcSamplesRead = cSamplesRead; … … 214 215 cAvail = pMixBuf->cMixed; 215 216 else 216 cAvail = pMixBuf->c Processed;217 cAvail = pMixBuf->cUsed; 217 218 218 219 Assert(cAvail <= pMixBuf->cSamples); … … 235 236 236 237 /** 237 * Clears (zeroes) the buffer by a certain amount of ( processed) samples and238 * Clears (zeroes) the buffer by a certain amount of (used) samples and 238 239 * keeps track to eventually assigned children buffers. 239 240 * … … 243 244 void AudioMixBufFinish(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToClear) 244 245 { 245 AUDMIXBUF_LOG(("cSamples =%RU32\n", cSamplesToClear));246 AUDMIXBUF_LOG(("%s: offRead Write=%RU32, cProcessed=%RU32\n",247 pMixBuf->pszName, pMixBuf->offRead Write, pMixBuf->cProcessed));246 AUDMIXBUF_LOG(("cSamplesToClear=%RU32\n", cSamplesToClear)); 247 AUDMIXBUF_LOG(("%s: offRead=%RU32, cUsed=%RU32\n", 248 pMixBuf->pszName, pMixBuf->offRead, pMixBuf->cUsed)); 248 249 249 250 PPDMAUDIOMIXBUF pIter; 250 RTListForEach(&pMixBuf->lst Buffers, pIter, PDMAUDIOMIXBUF, Node)251 RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node) 251 252 { 252 253 AUDMIXBUF_LOG(("\t%s: cMixed=%RU32 -> %RU32\n", 253 254 pIter->pszName, pIter->cMixed, pIter->cMixed - cSamplesToClear)); 254 255 256 Assert(cSamplesToClear <= pIter->cMixed); 255 257 pIter->cMixed -= RT_MIN(pIter->cMixed, cSamplesToClear); 256 pIter->offReadWrite = 0; 257 } 258 259 uint32_t cLeft = RT_MIN(cSamplesToClear, pMixBuf->cSamples); 260 uint32_t offClear; 261 262 if (cLeft > pMixBuf->offReadWrite) /* Zero end of buffer first (wrap-around). */ 263 { 264 AUDMIXBUF_LOG(("Clearing1: %RU32 - %RU32\n", 265 (pMixBuf->cSamples - (cLeft - pMixBuf->offReadWrite)), 266 pMixBuf->cSamples)); 267 268 RT_BZERO(pMixBuf->pSamples + (pMixBuf->cSamples - (cLeft - pMixBuf->offReadWrite)), 269 (cLeft - pMixBuf->offReadWrite) * sizeof(PDMAUDIOSAMPLE)); 270 271 cLeft -= cLeft - pMixBuf->offReadWrite; 272 offClear = 0; 273 } 274 else 275 offClear = pMixBuf->offReadWrite - cLeft; 276 277 if (cLeft) 278 { 279 AUDMIXBUF_LOG(("Clearing2: %RU32 - %RU32\n", 280 offClear, offClear + cLeft)); 281 RT_BZERO(pMixBuf->pSamples + offClear, cLeft * sizeof(PDMAUDIOSAMPLE)); 258 } 259 260 Assert(cSamplesToClear <= pMixBuf->cSamples); 261 262 uint32_t cClearOff; 263 uint32_t cClearLen; 264 265 /* Clear end of buffer (wrap around). */ 266 if (cSamplesToClear > pMixBuf->offRead) 267 { 268 cClearOff = pMixBuf->cSamples - (cSamplesToClear - pMixBuf->offRead); 269 cClearLen = pMixBuf->cSamples - cClearOff; 270 271 AUDMIXBUF_LOG(("Clearing1: %RU32 - %RU32\n", cClearOff, cClearOff + cClearLen)); 272 273 RT_BZERO(pMixBuf->pSamples + cClearOff, cClearLen * sizeof(PDMAUDIOSAMPLE)); 274 275 Assert(cSamplesToClear >= cClearLen); 276 cSamplesToClear -= cClearLen; 277 } 278 279 /* Clear beginning of buffer. */ 280 if ( cSamplesToClear 281 && pMixBuf->offRead) 282 { 283 Assert(pMixBuf->offRead >= cSamplesToClear); 284 285 cClearOff = pMixBuf->offRead - cSamplesToClear; 286 cClearLen = cSamplesToClear; 287 288 AUDMIXBUF_LOG(("Clearing2: %RU32 - %RU32\n", cClearOff, cClearOff + cClearLen)); 289 290 RT_BZERO(pMixBuf->pSamples + cClearOff, cClearLen * sizeof(PDMAUDIOSAMPLE)); 282 291 } 283 292 } … … 342 351 else /* As a parent. */ 343 352 { 344 Assert(pMixBuf->cSamples >= pMixBuf->c Processed);345 cSamplesFree = pMixBuf->cSamples - pMixBuf->c Processed;353 Assert(pMixBuf->cSamples >= pMixBuf->cUsed); 354 cSamplesFree = pMixBuf->cSamples - pMixBuf->cUsed; 346 355 } 347 356 … … 757 766 758 767 pMixBuf->pParent = NULL; 759 RTListInit(&pMixBuf->lst Buffers);768 RTListInit(&pMixBuf->lstChildren); 760 769 761 770 pMixBuf->pSamples = NULL; 762 771 pMixBuf->cSamples = 0; 763 772 764 pMixBuf->offReadWrite = 0; 765 pMixBuf->cMixed = 0; 766 pMixBuf->cProcessed = 0; 773 pMixBuf->offRead = 0; 774 pMixBuf->offWrite = 0; 775 pMixBuf->cMixed = 0; 776 pMixBuf->cUsed = 0; 767 777 768 778 /* Set initial volume to max. */ … … 813 823 if (pMixBuf->pParent) 814 824 return (pMixBuf->cMixed == 0); 815 return (pMixBuf->c Processed == 0);825 return (pMixBuf->cUsed == 0); 816 826 } 817 827 … … 855 865 } 856 866 857 RTListAppend(&pParent->lst Buffers, &pMixBuf->Node);867 RTListAppend(&pParent->lstChildren, &pMixBuf->Node); 858 868 pMixBuf->pParent = pParent; 859 869 … … 865 875 pMixBuf->iFreqRatio = 1 << 20; /* Do a 1:1 conversion instead. */ 866 876 877 int rc = VINF_SUCCESS; 878 #if 0 867 879 uint32_t cSamples = (uint32_t)RT_MIN( ((uint64_t)pParent->cSamples << 32) 868 880 / pMixBuf->iFreqRatio, _64K /* 64K samples max. */); … … 892 904 } 893 905 } 906 #endif 894 907 895 908 if (RT_SUCCESS(rc)) … … 955 968 AssertPtrReturn(pDst, VERR_INVALID_POINTER); 956 969 AssertPtrReturn(pSrc, VERR_INVALID_POINTER); 957 AssertReturn(cSamples, VERR_INVALID_PARAMETER);958 970 /* pcProcessed is optional. */ 959 971 960 /* Live samples indicate how many samples there are in the source buffer 961 * which have not been processed yet by the destination buffer. */ 962 uint32_t cLive = pSrc->cMixed; 963 if (cLive >= pDst->cSamples) 964 AUDMIXBUF_LOG(("Destination buffer \"%s\" full (%RU32 samples max), live samples = %RU32\n", 965 pDst->pszName, pDst->cSamples, cLive)); 966 967 /* Dead samples are the number of samples in the destination buffer which 968 * will not be needed, that is, are not needed in order to process the live 969 * samples of the source buffer. */ 970 uint32_t cDead = pDst->cSamples - cLive; 971 972 uint32_t cToReadTotal = (uint32_t)RT_MIN(cSamples, AUDIOMIXBUF_S2S_RATIO(pSrc, cDead)); 973 uint32_t offRead = 0; 974 972 AssertMsgReturn(pDst == pSrc->pParent, ("Source buffer '%s' is not a child of destination '%s'\n", 973 pSrc->pszName, pDst->pszName), VERR_INVALID_PARAMETER); 975 974 uint32_t cReadTotal = 0; 976 975 uint32_t cWrittenTotal = 0; 977 uint32_t offWrite = (pDst->offReadWrite + cLive) % pDst->cSamples; 978 979 AUDMIXBUF_LOG(("pSrc=%s (%RU32 samples, %RU8 chan), pDst=%s (%RU32 samples, %RU8 chan), " \ 980 "cLive=%RU32, cDead=%RU32, cToReadTotal=%RU32, offWrite=%RU32\n", 981 pSrc->pszName, pSrc->cSamples, AUDMIXBUF_FMT_CHANNELS(pSrc->AudioFmt), 982 pDst->pszName, pDst->cSamples, AUDMIXBUF_FMT_CHANNELS(pDst->AudioFmt), 983 cLive, cDead, cToReadTotal, offWrite)); 984 985 uint32_t cToRead, cToWrite; 986 uint32_t cWritten, cRead; 987 988 while (cToReadTotal) 989 { 990 cDead = pDst->cSamples - cLive; 991 992 cToRead = cToReadTotal; 993 cToWrite = RT_MIN(cDead, pDst->cSamples - offWrite); 994 if (!cToWrite) 995 { 996 AUDMIXBUF_LOG(("Warning: Destination buffer \"%s\" full\n", pDst->pszName)); 997 break; 998 } 999 1000 Assert(offWrite + cToWrite <= pDst->cSamples); 1001 Assert(offRead + cToRead <= pSrc->cSamples); 1002 1003 AUDMIXBUF_LOG(("\t%RU32Hz -> %RU32Hz\n", AUDMIXBUF_FMT_SAMPLE_FREQ(pSrc->AudioFmt), AUDMIXBUF_FMT_SAMPLE_FREQ(pDst->AudioFmt))); 1004 AUDMIXBUF_LOG(("\tcDead=%RU32, offWrite=%RU32, cToWrite=%RU32, offRead=%RU32, cToRead=%RU32\n", 1005 cDead, offWrite, cToWrite, offRead, cToRead)); 1006 1007 audioMixBufOpAssign(pDst->pSamples + offWrite, cToWrite, 1008 pSrc->pSamples + offRead, cToRead, 1009 pSrc->pRate, &cWritten, &cRead); 1010 1011 AUDMIXBUF_LOG(("\t\tcWritten=%RU32, cRead=%RU32\n", cWritten, cRead)); 1012 1013 cReadTotal += cRead; 1014 cWrittenTotal += cWritten; 1015 1016 offRead += cRead; 1017 Assert(cToReadTotal >= cRead); 1018 cToReadTotal -= cRead; 1019 1020 offWrite = (offWrite + cWritten) % pDst->cSamples; 1021 1022 cLive += cWritten; 1023 } 1024 1025 pSrc->cMixed += cWrittenTotal; 1026 1027 pDst->cProcessed += cWrittenTotal; 1028 1029 #if 0 1030 /** 1031 * Note: pDst->cProcessed can be bigger than pDst->cSamples if there 1032 * was a wrap-around. In that case samples were lost, 1033 * e.g. not consumed (yet). 1034 * 1035 * So adjust the current read/write offset to match the current 1036 * position, minus the dropped samples. */ 1037 if (pDst->cProcessed > pDst->cSamples) 1038 { 1039 LogFlowFunc(("%s: %RU32 / %RU32\n", pDst->pszName, pDst->cProcessed, pDst->cSamples)); 1040 pSrc->cMixed = pDst->cSamples; 1041 pDst->offReadWrite = 0; 1042 pDst->cProcessed = pDst->cSamples; 1043 } 1044 #endif 1045 1046 #ifdef DEBUG 1047 s_cSamplesMixedTotal += cWrittenTotal; 1048 AudioMixBufDbgPrint(pDst); 1049 #endif 1050 1051 if (pcProcessed) 1052 *pcProcessed = cReadTotal; 1053 1054 AUDMIXBUF_LOG(("cReadTotal=%RU32 (pcProcessed), cWrittenTotal=%RU32, cSrcMixed=%RU32, cDstProc=%RU32\n", 1055 cReadTotal, cWrittenTotal, pSrc->cMixed, pDst->cProcessed)); 1056 return VINF_SUCCESS; 1057 } 1058 1059 /** 1060 * Mixes (multiplexes) audio samples to all connected mixing buffer children. 1061 * 1062 * @return IPRT status code. 1063 * @param pMixBuf Mixing buffer to use. 1064 * @param cSamples Number of audio samples to mix to children. 1065 * @param pcProcessed Maximum number of audio samples successfully mixed 1066 * to all children. Optional. 1067 */ 1068 int AudioMixBufMixToChildren(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples, 1069 uint32_t *pcProcessed) 1070 { 1071 AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER); 1072 1073 if (!cSamples) 1074 { 976 977 if (pSrc->cMixed >= pDst->cSamples) 978 { 979 AUDMIXBUF_LOG(("Warning: Destination buffer '%s' full (%RU32 samples max), got %RU32 mixed samples\n", 980 pDst->pszName, pDst->cSamples, pSrc->cMixed)); 1075 981 if (pcProcessed) 1076 982 *pcProcessed = 0; … … 1078 984 } 1079 985 986 Assert(pSrc->cUsed >= pDst->cMixed); 987 988 uint32_t cSrcAvail = RT_MIN(cSamples, pSrc->cUsed - pDst->cMixed); 989 uint32_t offSrcRead = pSrc->offRead; 990 uint32_t cDstMixed = pSrc->cMixed; 991 992 Assert(pDst->cUsed <= pDst->cSamples); 993 uint32_t cDstAvail = pDst->cSamples - pDst->cUsed; 994 uint32_t offDstWrite = pDst->offWrite; 995 996 if ( !cSrcAvail 997 || !cDstAvail) 998 { 999 if (pcProcessed) 1000 *pcProcessed = 0; 1001 return VINF_SUCCESS; 1002 } 1003 1004 AUDMIXBUF_LOG(("cSamples=%RU32, cSrcAvail=%RU32 -> cDstAvail=%RU32\n", cSamples, cSrcAvail, cDstAvail)); 1005 1006 #ifdef DEBUG 1007 audioMixBufDbgPrintInternal(pDst); 1008 #endif 1009 1010 uint32_t cSrcToRead; 1011 uint32_t cSrcRead; 1012 1013 uint32_t cDstToWrite; 1014 uint32_t cDstWritten; 1015 1080 1016 int rc = VINF_SUCCESS; 1081 1017 1082 uint32_t cProcessed; 1083 uint32_t cProcessedMax = 0; 1084 1085 PPDMAUDIOMIXBUF pIter; 1086 RTListForEach(&pMixBuf->lstBuffers, pIter, PDMAUDIOMIXBUF, Node) 1087 { 1088 rc = audioMixBufMixTo(pIter, pMixBuf, cSamples, &cProcessed); 1089 if (RT_FAILURE(rc)) 1090 break; 1091 1092 cProcessedMax = RT_MAX(cProcessedMax, cProcessed); 1093 } 1018 while ( cSrcAvail 1019 && cDstAvail) 1020 { 1021 cSrcToRead = RT_MIN(cSrcAvail, pSrc->cSamples - offSrcRead); 1022 cDstToWrite = RT_MIN(cDstAvail, pDst->cSamples - offDstWrite); 1023 1024 AUDMIXBUF_LOG(("\tSource: %RU32 samples available, %RU32 @ %RU32 -> reading %RU32\n", cSrcAvail, offSrcRead, pSrc->cSamples, cSrcToRead)); 1025 AUDMIXBUF_LOG(("\tDest : %RU32 samples available, %RU32 @ %RU32 -> writing %RU32\n", cDstAvail, offDstWrite, pDst->cSamples, cDstToWrite)); 1026 1027 cDstWritten = cSrcRead = 0; 1028 1029 if ( cDstToWrite 1030 && cSrcToRead) 1031 { 1032 Assert(offSrcRead < pSrc->cSamples); 1033 Assert(offSrcRead + cSrcToRead <= pSrc->cSamples); 1034 1035 Assert(offDstWrite < pDst->cSamples); 1036 Assert(offDstWrite + cDstToWrite <= pDst->cSamples); 1037 1038 audioMixBufOpAssign(pDst->pSamples + offDstWrite, cDstToWrite, 1039 pSrc->pSamples + offSrcRead, cSrcToRead, 1040 pSrc->pRate, &cDstWritten, &cSrcRead); 1041 } 1042 1043 cReadTotal += cSrcRead; 1044 cWrittenTotal += cDstWritten; 1045 1046 offSrcRead = (offSrcRead + cSrcRead) % pSrc->cSamples; 1047 offDstWrite = (offDstWrite + cDstWritten) % pDst->cSamples; 1048 1049 cDstMixed += cDstWritten; 1050 1051 Assert(cSrcAvail >= cSrcRead); 1052 cSrcAvail -= cSrcRead; 1053 Assert(cDstAvail >= cDstWritten); 1054 cDstAvail -= cDstWritten; 1055 1056 AUDMIXBUF_LOG(("\t%RU32 read (%RU32 left), %RU32 written (%RU32 left)\n", cSrcRead, cSrcAvail, cDstWritten, cDstAvail)); 1057 } 1058 1059 pSrc->offRead = offSrcRead; 1060 Assert(pSrc->cUsed >= cReadTotal); 1061 pSrc->cUsed -= cReadTotal; 1062 1063 /* Note: Always count in parent samples, as the rate can differ! */ 1064 pSrc->cMixed = cDstMixed; 1065 Assert(pSrc->cMixed <= pDst->cSamples); 1066 1067 pDst->offWrite = offDstWrite; 1068 Assert(pDst->offWrite <= pDst->cSamples); 1069 Assert((pDst->cUsed + cWrittenTotal) <= pDst->cSamples); 1070 pDst->cUsed += cWrittenTotal; 1071 1072 /* If there are more used samples than fitting in the destination buffer, 1073 * adjust the values accordingly. 1074 * 1075 * This can happen if this routine has been called too often without 1076 * actually processing the destination buffer in between. */ 1077 if (pDst->cUsed > pDst->cSamples) 1078 { 1079 LogFlowFunc(("Warning: Destination buffer used %RU32 / %RU32 samples\n", pDst->cUsed, pDst->cSamples)); 1080 pDst->offWrite = 0; 1081 pDst->cUsed = pDst->cSamples; 1082 1083 rc = VERR_BUFFER_OVERFLOW; 1084 } 1085 else if (!cSrcToRead && cDstAvail) 1086 { 1087 AUDMIXBUF_LOG(("Warning: Source buffer '%s' ran out of data\n", pSrc->pszName)); 1088 rc = VERR_BUFFER_UNDERFLOW; 1089 } 1090 else if (cSrcAvail && !cDstAvail) 1091 { 1092 AUDMIXBUF_LOG(("Warning: Destination buffer '%s' full (%RU32 source samples left)\n", pDst->pszName, cSrcAvail)); 1093 rc = VERR_BUFFER_OVERFLOW; 1094 } 1095 1096 #ifdef DEBUG 1097 s_cSamplesMixedTotal += cWrittenTotal; 1098 audioMixBufDbgPrintInternal(pDst); 1099 #endif 1094 1100 1095 1101 if (pcProcessed) 1096 *pcProcessed = cProcessedMax; 1097 1098 return rc; 1102 *pcProcessed = cReadTotal; 1103 1104 AUDMIXBUF_LOG(("cReadTotal=%RU32 (pcProcessed), cWrittenTotal=%RU32, cSrcMixed=%RU32, cDstUsed=%RU32, rc=%Rrc\n", 1105 cReadTotal, cWrittenTotal, pSrc->cMixed, pDst->cUsed, rc)); 1106 return VINF_SUCCESS; 1099 1107 } 1100 1108 … … 1118 1126 1119 1127 #ifdef DEBUG 1120 static void audioMixBufDbgBufPrintIndentV(uint16_t uIndent, const char *pszFormat, va_list va)1121 {1122 char *pszValueFormat;1123 if (RTStrAPrintfV(&pszValueFormat, pszFormat, va))1124 {1125 AUDMIXBUF_LOG(("%*s%s", uIndent, "", pszValueFormat));1126 RTStrFree(pszValueFormat);1127 }1128 }1129 1130 static void audioMixBufDbgPrintIndent(uint16_t uIdtLvl, const char *pszFormat, ...)1131 {1132 va_list va;1133 va_start(va, pszFormat);1134 audioMixBufDbgBufPrintIndentV(uIdtLvl * 4, pszFormat, va);1135 va_end(va);1136 }1137 1138 1128 /** 1139 1129 * Prints a single mixing buffer. … … 1145 1135 * @param uIdtLvl Indention level to use. 1146 1136 */ 1147 static void audioMixBufDbgPrintSingle(PPDMAUDIOMIXBUF pMixBuf, bool fIsParent, uint16_t uIdtLvl) 1148 { 1149 audioMixBufDbgPrintIndent(uIdtLvl, 1150 "[%s] %s: offReadWrite=%RU32, cProc=%RU32, cMixed=%RU32 / %RU32)\n", 1151 fIsParent ? "PARENT" : "CHILD", 1152 pMixBuf->pszName, pMixBuf->offReadWrite, pMixBuf->cProcessed, pMixBuf->cMixed, pMixBuf->cSamples); 1137 DECL_FORCE_INLINE(void) audioMixBufDbgPrintSingle(PPDMAUDIOMIXBUF pMixBuf, bool fIsParent, uint16_t uIdtLvl) 1138 { 1139 AUDMIXBUF_LOG(("%*s[%s] %s: offRead=%RU32, offWrite=%RU32, cMixed=%RU32 -> %RU32/%RU32\n", 1140 uIdtLvl * 4, "", fIsParent ? "PARENT" : "CHILD", 1141 pMixBuf->pszName, pMixBuf->offRead, pMixBuf->offWrite, pMixBuf->cMixed, pMixBuf->cUsed, pMixBuf->cSamples)); 1153 1142 } 1154 1143 … … 1162 1151 * @param pcChildren Pointer to children counter. 1163 1152 */ 1164 static voidaudioMixBufDbgPrintChainHelper(PPDMAUDIOMIXBUF pMixBuf, uint16_t uIdtLvl, size_t *pcChildren)1153 DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainHelper(PPDMAUDIOMIXBUF pMixBuf, uint16_t uIdtLvl, size_t *pcChildren) 1165 1154 { 1166 1155 PPDMAUDIOMIXBUF pIter; 1167 RTListForEach(&pMixBuf->lst Buffers, pIter, PDMAUDIOMIXBUF, Node)1156 RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node) 1168 1157 { 1169 1158 audioMixBufDbgPrintSingle(pIter, false /* ifIsParent */, uIdtLvl + 1); 1170 1159 *pcChildren++; 1171 audioMixBufDbgPrintChainHelper(pIter, uIdtLvl + 1, pcChildren); 1172 } 1173 } 1174 1175 static void audioMixBufDbgPrintChainInternal(PPDMAUDIOMIXBUF pMixBuf) 1160 } 1161 } 1162 1163 DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainInternal(PPDMAUDIOMIXBUF pMixBuf) 1176 1164 { 1177 1165 PPDMAUDIOMIXBUF pParent = pMixBuf->pParent; … … 1212 1200 } 1213 1201 1214 /** 1215 * Prints statistics and status of a mixing buffer to the logger. 1216 * For debug versions only. 1217 * 1218 * @return IPRT status code. 1219 * @param pMixBuf Mixing buffer to print. 1220 */ 1221 void AudioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf) 1202 DECL_FORCE_INLINE(void) audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf) 1222 1203 { 1223 1204 PPDMAUDIOMIXBUF pParent = pMixBuf; … … 1225 1206 pParent = pMixBuf->pParent; 1226 1207 1227 AUDMIXBUF_LOG(("******************************************** \n"));1208 AUDMIXBUF_LOG(("***************************************************************************************\n")); 1228 1209 1229 1210 audioMixBufDbgPrintSingle(pMixBuf, pParent == pMixBuf /* fIsParent */, 0 /* iIdtLevel */); 1230 1211 1231 1212 PPDMAUDIOMIXBUF pIter; 1232 RTListForEach(&pParent->lst Buffers, pIter, PDMAUDIOMIXBUF, Node)1213 RTListForEach(&pParent->lstChildren, pIter, PDMAUDIOMIXBUF, Node) 1233 1214 { 1234 1215 if (pIter == pMixBuf) … … 1237 1218 } 1238 1219 1239 AUDMIXBUF_LOG(("********************************************\n")); 1240 } 1241 #endif 1242 1243 /** 1244 * Returns the total number of samples processed. 1220 AUDMIXBUF_LOG(("***************************************************************************************\n")); 1221 } 1222 1223 /** 1224 * Prints statistics and status of a mixing buffer to the logger. 1225 * For debug versions only. 1226 * 1227 * @return IPRT status code. 1228 * @param pMixBuf Mixing buffer to print. 1229 */ 1230 void AudioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf) 1231 { 1232 audioMixBufDbgPrintInternal(pMixBuf); 1233 } 1234 #endif 1235 1236 /** 1237 * Returns the total number of samples used. 1245 1238 * 1246 1239 * @return uint32_t 1247 1240 * @param pMixBuf 1248 1241 */ 1249 uint32_t AudioMixBuf Processed(PPDMAUDIOMIXBUF pMixBuf)1242 uint32_t AudioMixBufUsed(PPDMAUDIOMIXBUF pMixBuf) 1250 1243 { 1251 1244 AssertPtrReturn(pMixBuf, 0); 1252 1245 1253 AUDMIXBUF_LOG(("%s: c Processed=%RU32\n", pMixBuf->pszName, pMixBuf->cProcessed));1254 return pMixBuf->c Processed;1246 AUDMIXBUF_LOG(("%s: cUsed=%RU32\n", pMixBuf->pszName, pMixBuf->cUsed)); 1247 return pMixBuf->cUsed; 1255 1248 } 1256 1249 … … 1297 1290 1298 1291 uint32_t cDstSamples = pMixBuf->cSamples; 1299 uint32_t cLive = pMixBuf->c Processed;1292 uint32_t cLive = pMixBuf->cUsed; 1300 1293 1301 1294 uint32_t cDead = cDstSamples - cLive; … … 1381 1374 return VINF_SUCCESS; 1382 1375 1383 uint32_t cToRead = RT_MIN(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), pMixBuf->cProcessed); 1376 Assert(AUDIOMIXBUF_B2S(pMixBuf, cbBuf) <= pMixBuf->cSamples); 1377 1378 uint32_t cToRead = RT_MIN(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), pMixBuf->cUsed); 1384 1379 1385 1380 AUDMIXBUF_LOG(("%s: pvBuf=%p, cbBuf=%zu (%RU32 samples), cToRead=%RU32\n", … … 1389 1384 { 1390 1385 #ifdef DEBUG 1391 AudioMixBufDbgPrint(pMixBuf);1386 audioMixBufDbgPrintInternal(pMixBuf); 1392 1387 #endif 1393 1388 if (pcRead) … … 1400 1395 return VERR_NOT_SUPPORTED; 1401 1396 1402 PPDMAUDIOSAMPLE pSamplesSrc1 = pMixBuf->pSamples + pMixBuf->offRead Write;1397 PPDMAUDIOSAMPLE pSamplesSrc1 = pMixBuf->pSamples + pMixBuf->offRead; 1403 1398 uint32_t cLenSrc1 = cToRead; 1404 1399 1405 1400 PPDMAUDIOSAMPLE pSamplesSrc2 = NULL; 1406 1401 uint32_t cLenSrc2 = 0; 1407 1408 uint32_t offRead = pMixBuf->offReadWrite + cToRead;1409 1402 1410 1403 /* … … 1413 1406 * be the optional second part to do. 1414 1407 */ 1415 if ( offRead >=pMixBuf->cSamples)1416 { 1417 Assert(pMixBuf->offRead Write<= pMixBuf->cSamples);1418 cLenSrc1 = pMixBuf->cSamples - pMixBuf->offRead Write;1408 if ((pMixBuf->offRead + cToRead) > pMixBuf->cSamples) 1409 { 1410 Assert(pMixBuf->offRead <= pMixBuf->cSamples); 1411 cLenSrc1 = pMixBuf->cSamples - pMixBuf->offRead; 1419 1412 1420 1413 pSamplesSrc2 = pMixBuf->pSamples; 1421 1414 Assert(cToRead >= cLenSrc1); 1422 1415 cLenSrc2 = RT_MIN(cToRead - cLenSrc1, pMixBuf->cSamples); 1423 1424 /* Save new read offset. */1425 offRead = cLenSrc2;1426 1416 } 1427 1417 … … 1435 1425 convOpts.cSamples = cLenSrc1; 1436 1426 1437 AUDMIXBUF_LOG(("P1: offRead=%RU32, cToRead=%RU32\n", pMixBuf->offRead Write, cLenSrc1));1427 AUDMIXBUF_LOG(("P1: offRead=%RU32, cToRead=%RU32\n", pMixBuf->offRead, cLenSrc1)); 1438 1428 pConv(pvBuf, pSamplesSrc1, &convOpts); 1439 1429 } … … 1464 1454 } 1465 1455 #endif 1466 pMixBuf->offReadWrite = offRead % pMixBuf->cSamples; 1467 pMixBuf->cProcessed -= RT_MIN(cLenSrc1 + cLenSrc2, pMixBuf->cProcessed); 1456 pMixBuf->offRead = (pMixBuf->offRead + cToRead) % pMixBuf->cSamples; 1457 Assert(cToRead <= pMixBuf->cUsed); 1458 pMixBuf->cUsed -= RT_MIN(cToRead, pMixBuf->cUsed); 1468 1459 1469 1460 if (pcRead) 1470 *pcRead = c LenSrc1 + cLenSrc2;1461 *pcRead = cToRead; 1471 1462 } 1472 1463 1473 1464 #ifdef DEBUG 1474 AudioMixBufDbgPrint(pMixBuf); 1475 #endif 1476 1477 AUDMIXBUF_LOG(("cRead=%RU32 (%zu bytes), rc=%Rrc\n", 1478 cLenSrc1 + cLenSrc2, 1479 AUDIOMIXBUF_S2B(pMixBuf, cLenSrc1 + cLenSrc2), rc)); 1465 audioMixBufDbgPrintInternal(pMixBuf); 1466 #endif 1467 1468 AUDMIXBUF_LOG(("cRead=%RU32 (%zu bytes), rc=%Rrc\n", cToRead, AUDIOMIXBUF_S2B(pMixBuf, cToRead), rc)); 1480 1469 return rc; 1481 1470 } … … 1492 1481 AUDMIXBUF_LOG(("%s\n", pMixBuf->pszName)); 1493 1482 1494 pMixBuf->offReadWrite = 0; 1495 pMixBuf->cMixed = 0; 1496 pMixBuf->cProcessed = 0; 1483 pMixBuf->offRead = 0; 1484 pMixBuf->offWrite = 0; 1485 pMixBuf->cMixed = 0; 1486 pMixBuf->cUsed = 0; 1497 1487 1498 1488 AudioMixBufClear(pMixBuf); … … 1571 1561 1572 1562 PPDMAUDIOMIXBUF pIter; 1573 while (!RTListIsEmpty(&pMixBuf->lst Buffers))1574 { 1575 pIter = RTListGetFirst(&pMixBuf->lst Buffers, PDMAUDIOMIXBUF, Node);1563 while (!RTListIsEmpty(&pMixBuf->lstChildren)) 1564 { 1565 pIter = RTListGetFirst(&pMixBuf->lstChildren, PDMAUDIOMIXBUF, Node); 1576 1566 1577 1567 AUDMIXBUF_LOG(("\tUnlinking \"%s\"\n", pIter->pszName)); … … 1633 1623 uint32_t cDstSamples = pMixBuf->pParent 1634 1624 ? pMixBuf->pParent->cSamples : pMixBuf->cSamples; 1635 uint32_t cLive = pMixBuf->c Processed;1625 uint32_t cLive = pMixBuf->cUsed; 1636 1626 1637 1627 uint32_t cDead = cDstSamples - cLive; … … 1677 1667 cWritten = pConv(pMixBuf->pSamples + offSamples, pvBuf, cbBuf, &convOpts); 1678 1668 #ifdef DEBUG 1679 AudioMixBufDbgPrint(pMixBuf);1669 audioMixBufDbgPrintInternal(pMixBuf); 1680 1670 #endif 1681 1671 rc = cWritten ? VINF_SUCCESS : VERR_GENERAL_FAILURE; /** @todo Fudge! */ … … 1727 1717 */ 1728 1718 int AudioMixBufWriteCircEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, 1729 const void *pvBuf, uint32_t cbBuf, 1730 uint32_t *pcWritten) 1719 const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten) 1731 1720 { 1732 1721 AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER); … … 1747 1736 1748 1737 if ( pParent 1749 && pParent->cSamples < =pMixBuf->cMixed)1738 && pParent->cSamples < pMixBuf->cMixed) 1750 1739 { 1751 1740 if (pcWritten) … … 1775 1764 AssertMsg(cToWrite, ("cToWrite is 0 (cbBuf=%zu)\n", cbBuf)); 1776 1765 1777 PPDMAUDIOSAMPLE pSamplesDst1 = pMixBuf->pSamples + pMixBuf->off ReadWrite;1766 PPDMAUDIOSAMPLE pSamplesDst1 = pMixBuf->pSamples + pMixBuf->offWrite; 1778 1767 uint32_t cLenDst1 = cToWrite; 1779 1768 … … 1781 1770 uint32_t cLenDst2 = 0; 1782 1771 1783 uint32_t cOffWrite = pMixBuf->off ReadWrite + cToWrite;1772 uint32_t cOffWrite = pMixBuf->offWrite + cToWrite; 1784 1773 1785 1774 /* … … 1790 1779 if (cOffWrite >= pMixBuf->cSamples) 1791 1780 { 1792 Assert(pMixBuf->off ReadWrite <= pMixBuf->cSamples);1793 cLenDst1 = pMixBuf->cSamples - pMixBuf->off ReadWrite;1781 Assert(pMixBuf->offWrite <= pMixBuf->cSamples); 1782 cLenDst1 = pMixBuf->cSamples - pMixBuf->offWrite; 1794 1783 1795 1784 pSamplesDst2 = pMixBuf->pSamples; … … 1803 1792 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1804 1793 RTFILE fh; 1805 RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writecirc_ex -32bit-float.pcm",1794 RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writecirc_ex.pcm", 1806 1795 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 1807 1796 #endif … … 1816 1805 { 1817 1806 convOpts.cSamples = cLenDst1; 1818 cWrittenTotal = pCnvFrm(pSamplesDst1, pvBuf, cbBuf, &convOpts);1807 cWrittenTotal = pCnvFrm(pSamplesDst1, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), &convOpts); 1819 1808 Assert(cWrittenTotal == cLenDst1); 1820 1809 1821 1810 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1822 RTFileWrite(fh, pvBuf, cbBuf, NULL);1811 RTFileWrite(fh, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), NULL); 1823 1812 #endif 1824 1813 } … … 1831 1820 1832 1821 convOpts.cSamples = cLenDst2; 1833 cWrittenTotal += pCnvFrm(pSamplesDst2, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), cbBuf, &convOpts); 1822 cWrittenTotal += pCnvFrm(pSamplesDst2, 1823 (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), 1824 cbBuf - AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), 1825 &convOpts); 1834 1826 Assert(cWrittenTotal == (cLenDst1 + cLenDst2)); 1835 1827 1836 1828 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1837 RTFileWrite(fh, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), cbBuf, NULL); 1829 RTFileWrite(fh, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), 1830 cbBuf - AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), NULL); 1838 1831 #endif 1839 1832 } … … 1845 1838 if (RT_SUCCESS(rc)) 1846 1839 { 1847 pMixBuf->off ReadWrite = cOffWrite% pMixBuf->cSamples;1848 pMixBuf->c Processed = RT_MIN(pMixBuf->cProcessed + cLenDst1 + cLenDst2,1849 1850 1851 uint32_t cProcessedTotal = pMixBuf->c Processed + cLenDst1 + cLenDst2;1840 pMixBuf->offWrite = (pMixBuf->offWrite + cWrittenTotal) % pMixBuf->cSamples; 1841 pMixBuf->cUsed = RT_MIN(pMixBuf->cUsed + cWrittenTotal, 1842 pMixBuf->cSamples /* Max */); 1843 1844 uint32_t cProcessedTotal = pMixBuf->cUsed + cWrittenTotal; 1852 1845 if (cProcessedTotal > pMixBuf->cSamples) 1853 1846 { 1854 1847 AUDMIXBUF_LOG(("Warning: %RU32 unprocessed samples overwritten\n", cProcessedTotal - pMixBuf->cSamples)); 1855 pMixBuf->c Processed = pMixBuf->cSamples;1848 pMixBuf->cUsed = pMixBuf->cSamples; 1856 1849 1857 1850 rc = VINF_BUFFER_OVERFLOW; … … 1859 1852 1860 1853 if (pcWritten) 1861 *pcWritten = c LenDst1 + cLenDst2;1854 *pcWritten = cWrittenTotal; 1862 1855 } 1863 1856 1864 1857 #ifdef DEBUG 1865 AudioMixBufDbgPrint(pMixBuf);1866 #endif 1867 1868 AUDMIXBUF_LOG(("off ReadWrite=%RU32, cLenDst1=%RU32, cLenDst2=%RU32, cTotal=%RU32 (%zu bytes), rc=%Rrc\n",1869 pMixBuf->off ReadWrite, cLenDst1, cLenDst2, cLenDst1 + cLenDst2,1858 audioMixBufDbgPrintInternal(pMixBuf); 1859 #endif 1860 1861 AUDMIXBUF_LOG(("offWrite=%RU32, cLenDst1=%RU32, cLenDst2=%RU32, cTotal=%RU32 (%zu bytes), rc=%Rrc\n", 1862 pMixBuf->offWrite, cLenDst1, cLenDst2, cLenDst1 + cLenDst2, 1870 1863 AUDIOMIXBUF_S2B(pMixBuf, cLenDst1 + cLenDst2), rc)); 1871 1864 -
trunk/src/VBox/Devices/Audio/AudioMixBuffer.h
r61089 r61320 62 62 int AudioMixBufLinkTo(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent); 63 63 uint32_t AudioMixBufMixed(PPDMAUDIOMIXBUF pMixBuf); 64 int AudioMixBufMixToChildren(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples, uint32_t *pcProcessed);65 64 int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples, uint32_t *pcProcessed); 66 uint32_t AudioMixBuf Processed(PPDMAUDIOMIXBUF pMixBuf);65 uint32_t AudioMixBufUsed(PPDMAUDIOMIXBUF pMixBuf); 67 66 int AudioMixBufReadAt(PPDMAUDIOMIXBUF pMixBuf, uint32_t offSamples, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead); 68 67 int AudioMixBufReadAtEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, uint32_t offSamples, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead); -
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r61178 r61320 405 405 } 406 406 407 RTStrPrintf(CfgSink.szName, sizeof(CfgSink.szName), "%s", pCfg->szName); 408 407 409 /* Always use the sink's PCM audio format as the host side when creating a stream for it. */ 408 410 PPDMAUDIOSTREAM pStream; … … 583 585 /** @todo Handle mixing operation enmOp! */ 584 586 587 AssertMsg(pSink->enmDir == AUDMIXSINKDIR_INPUT, 588 ("Can't read from a sink which is not an input sink\n")); 589 585 590 uint8_t *pvMixBuf = (uint8_t *)RTMemAlloc(cbBuf); 586 591 if (!pvMixBuf) … … 797 802 int rc = VINF_SUCCESS; 798 803 804 Log3Func(("[%s]\n", pSink->pszName)); 805 799 806 PAUDMIXSTREAM pMixStream; 800 807 RTListForEach(&pSink->lstStreams, pMixStream, AUDMIXSTREAM, Node) … … 803 810 AssertPtr(pStream); 804 811 805 uint32_t cSamplesAvail; 806 uint32_t cSamplesProcessed = 0; 807 808 rc = pMixStream->pConn->pfnStreamGetData(pMixStream->pConn, pStream, &cSamplesAvail); 809 if ( RT_SUCCESS(rc) 810 && cSamplesAvail) 812 uint32_t cPlayed = 0; 813 814 rc = pMixStream->pConn->pfnStreamIterate(pMixStream->pConn, pStream); 815 if (RT_SUCCESS(rc)) 811 816 { 812 817 if (pStream->enmDir == PDMAUDIODIR_IN) 813 818 { 814 819 /** @todo Implement this! */ 815 // rc = pStream->pConn->pfnCapture(pStream->pConn, NULL /* pcSamplesCaptured */); 820 #if 0 821 rc = pStream->pConn->pfnStreamCapture(pStream->pConn, NULL /* pcSamplesCaptured */); 822 #endif 816 823 } 817 824 else 818 825 { 819 rc = pMixStream->pConn->pfnStreamPlay(pMixStream->pConn, pStream, &cSamplesProcessed); 826 rc = pMixStream->pConn->pfnStreamPlay(pMixStream->pConn, pMixStream->pStream, &cPlayed); 827 if (RT_FAILURE(rc)) 828 LogFlowFunc(("%s: Failed playing stream '%s': %Rrc\n", pSink->pszName, pMixStream->pStream->szName, rc)); 820 829 } 821 822 pSink->fFlags |= AUDMIXSINK_FLAG_DIRTY;823 830 } 824 else if (!cSamplesAvail) 825 pSink->fFlags &= ~AUDMIXSINK_FLAG_DIRTY; 826 827 Log3Func(("[%s]: fFlags=0x%x, %RU32/%RU32 samples, rc=%Rrc\n", 828 pSink->pszName, pSink->fFlags, cSamplesProcessed, cSamplesAvail, rc)); 831 832 Log3Func(("\t%s: cPlayed=%RU32, rc=%Rrc\n", pMixStream->pStream->szName, cPlayed, rc)); 829 833 } 830 834 … … 884 888 } 885 889 886 uint32_t cbProcessed = 0; 890 AssertMsg(pSink->enmDir == AUDMIXSINKDIR_OUTPUT, 891 ("Can't write to a sink which is not an output sink\n")); 892 893 LogFlowFunc(("%s: enmOp=%ld, cbBuf=%RU32\n", pSink->pszName, enmOp, cbBuf)); 894 895 uint32_t cPlayed; 896 uint32_t cbProcessed; 887 897 888 898 PAUDMIXSTREAM pMixStream; … … 893 903 894 904 int rc2 = pMixStream->pConn->pfnStreamWrite(pMixStream->pConn, pMixStream->pStream, pvBuf, cbBuf, &cbProcessed); 895 if ( RT_FAILURE(rc2) 896 || cbProcessed < cbBuf) 897 { 898 LogFlowFunc(("rc=%Rrc, cbBuf=%RU32, cbProcessed=%RU32\n", rc2, cbBuf, cbProcessed)); 899 } 900 } 905 if (RT_FAILURE(rc2)) 906 LogFlowFunc(("%s: Failed writing to stream '%s': %Rrc\n", pSink->pszName, pMixStream->pStream->szName, rc2)); 907 908 if (cbProcessed < cbBuf) 909 LogFlowFunc(("%s: Only written %RU32/%RU32 bytes\n", pSink->pszName, pMixStream->pStream->szName, cbProcessed, cbBuf)); 910 } 911 912 /* Set dirty bit. */ 913 pSink->fFlags |= AUDMIXSINK_FLAG_DIRTY; 901 914 902 915 if (pcbWritten) -
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r61167 r61320 55 55 #define AC97_SSM_VERSION 1 56 56 57 #define AC97_TIMER_HZ 10057 #define AC97_TIMER_HZ 50 58 58 59 59 #ifdef VBOX -
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r61167 r61320 78 78 /** PCM output stream. */ 79 79 R3PTRTYPE(PPDMAUDIOSTREAM) pStream; 80 /** Mixer handle for output stream. */81 R3PTRTYPE(PAUDMIXSTREAM) pMixStrm;82 80 } SB16OUTPUTSTREAM, *PSB16OUTPUTSTREAM; 83 81 … … 169 167 170 168 RTLISTANCHOR lstDrv; 171 /** The device' software mixer. */172 R3PTRTYPE(PAUDIOMIXER) pMixer;173 /** Audio sink for PCM output. */174 R3PTRTYPE(PAUDMIXSINK) pSinkOutput;175 169 /** Number of active (running) SDn streams. */ 176 170 uint8_t cStreamsActive; … … 178 172 /** The timer for pumping data thru the attached LUN drivers. */ 179 173 PTMTIMERR3 pTimerIO; 174 /** Flag indicating whether the timer is active or not. */ 175 bool fTimerActive; 176 uint8_t u8Padding1[7]; 180 177 /** The timer interval for pumping data thru the LUN drivers in timer ticks. */ 181 178 uint64_t cTimerTicksIO; … … 194 191 195 192 static int sb16OpenOut(PSB16STATE pThis, PPDMAUDIOSTREAMCFG pCfg); 193 static void sb16CloseOut(PSB16STATE pThis); 196 194 #ifndef VBOX_WITH_AUDIO_CALLBACKS 197 195 static void sb16TimerMaybeStart(PSB16STATE pThis); … … 451 449 #endif 452 450 453 AudioMixerSinkCtl(pThis->pSinkOutput, 454 hold == 1 ? AUDMIXSINKCMD_ENABLE : AUDMIXSINKCMD_DISABLE); 451 PSB16DRIVER pDrv; 452 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 453 { 454 int rc2 = pDrv->pConnector->pfnStreamControl(pDrv->pConnector, pDrv->Out.pStream, 455 hold == 1 ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE); 456 LogFlowFunc(("%s: rc=%Rrc\n", pDrv->Out.pStream->szName, rc2)); 457 } 455 458 } 456 459 … … 471 474 PDMAUDIOSTREAMCFG streamCfg; 472 475 RT_ZERO(streamCfg); 473 streamCfg.enmDir = PDMAUDIODIR_OUT; 474 streamCfg.uHz = pThis->freq; 475 streamCfg.cChannels = 1 << pThis->fmt_stereo; 476 streamCfg.enmFormat = pThis->fmt; 477 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 476 streamCfg.enmDir = PDMAUDIODIR_OUT; 477 streamCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT; 478 streamCfg.uHz = pThis->freq; 479 streamCfg.cChannels = 1 << pThis->fmt_stereo; 480 streamCfg.enmFormat = pThis->fmt; 481 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 478 482 479 483 int rc = sb16OpenOut(pThis, &streamCfg); … … 608 612 PDMAUDIOSTREAMCFG streamCfg; 609 613 RT_ZERO(streamCfg); 610 streamCfg.enmDir = PDMAUDIODIR_OUT; 611 streamCfg.uHz = pThis->freq; 612 streamCfg.cChannels = 1 << pThis->fmt_stereo; 613 streamCfg.enmFormat = pThis->fmt; 614 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 614 streamCfg.enmDir = PDMAUDIODIR_OUT; 615 streamCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT; 616 streamCfg.uHz = pThis->freq; 617 streamCfg.cChannels = 1 << pThis->fmt_stereo; 618 streamCfg.enmFormat = pThis->fmt; 619 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 615 620 616 621 int rc = sb16OpenOut(pThis, &streamCfg); … … 1101 1106 uint8_t rvol = sb16MixRegToVol(pThis, 0x31); 1102 1107 PDMAUDIOVOLUME vol = { false, lvol, rvol }; 1103 AudioMixerSetMasterVolume(pThis->pMixer, &vol); 1108 1109 // AudioMixerSetMasterVolume(pThis->pMixer, &vol); 1104 1110 } 1105 1111 … … 1110 1116 uint8_t rvol = sb16MixRegToVol(pThis, 0x33); 1111 1117 PDMAUDIOVOLUME vol = { false, lvol, rvol }; 1112 AudioMixerSinkSetVolume(pThis->pSinkOutput, &vol); 1118 1119 // AudioMixerSinkSetVolume(pThis->pSinkOutput, &vol); 1113 1120 } 1114 1121 1115 1122 static void sb16ResetLegacy(PSB16STATE pThis) 1116 1123 { 1124 sb16CloseOut(pThis); 1125 1117 1126 pThis->freq = 11025; 1118 1127 pThis->fmt_signed = 0; … … 1122 1131 PDMAUDIOSTREAMCFG streamCfg; 1123 1132 RT_ZERO(streamCfg); 1124 streamCfg.enmDir = PDMAUDIODIR_OUT; 1125 streamCfg.uHz = pThis->freq; 1126 streamCfg.cChannels = 1; /* Mono */ 1127 streamCfg.enmFormat = PDMAUDIOFMT_U8; 1128 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 1133 streamCfg.enmDir = PDMAUDIODIR_OUT; 1134 streamCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT; 1135 streamCfg.uHz = pThis->freq; 1136 streamCfg.cChannels = 1; /* Mono */ 1137 streamCfg.enmFormat = PDMAUDIOFMT_U8; 1138 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 1129 1139 1130 1140 int rc2 = sb16OpenOut(pThis, &streamCfg); … … 1332 1342 static void sb16MixerReset(PSB16STATE pThis) 1333 1343 { 1334 PSB16DRIVER pDrv;1335 1336 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node)1337 pDrv->Out.pMixStrm = NULL;1338 1339 pThis->pSinkOutput = NULL;1340 1341 if (pThis->pMixer)1342 {1343 AudioMixerDestroy(pThis->pMixer);1344 pThis->pMixer = NULL;1345 }1346 1347 1344 memset(pThis->mixer_regs, 0xff, 0x7f); 1348 1345 memset(pThis->mixer_regs + 0x83, 0xff, sizeof (pThis->mixer_regs) - 0x83); … … 1373 1370 for (int i = 0x44; i < 0x48; i++) 1374 1371 pThis->mixer_regs[i] = 0x80; 1375 1376 int rc2 = AudioMixerCreate("SB16 Mixer", 0 /* uFlags */, &pThis->pMixer);1377 if (RT_SUCCESS(rc2))1378 {1379 /* Set a default audio format for our mixer. */1380 PDMAUDIOSTREAMCFG streamCfg;1381 streamCfg.uHz = 44100;1382 streamCfg.cChannels = 2;1383 streamCfg.enmFormat = PDMAUDIOFMT_S16;1384 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS;1385 1386 rc2 = AudioMixerSetDeviceFormat(pThis->pMixer, &streamCfg);1387 AssertRC(rc2);1388 1389 /* Add all required audio sinks. */1390 rc2 = AudioMixerCreateSink(pThis->pMixer, "[Playback] PCM Output", AUDMIXSINKDIR_OUTPUT, &pThis->pSinkOutput);1391 AssertRC(rc2);1392 }1393 1372 1394 1373 /* Update the master (mixer) and PCM out volumes. */ … … 1642 1621 1643 1622 /* 1644 * Write data to the mixer sink.1623 * Write data to the backends. 1645 1624 */ 1646 uint32_t cbWritten; 1647 rc = AudioMixerSinkWrite(pThis->pSinkOutput, AUDMIXOP_COPY, tmpbuf, cbToRead, &cbWritten); 1648 if (RT_FAILURE(rc)) 1649 break; 1625 uint32_t cbWritten = 0; 1626 1627 PSB16DRIVER pDrv; 1628 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1629 { 1630 int rc2 = pDrv->pConnector->pfnStreamWrite(pDrv->pConnector, pDrv->Out.pStream, tmpbuf, cbToRead, &cbWritten); 1631 if (RT_FAILURE(rc2)) 1632 LogFlowFunc(("Failed writing to stream '%s': %Rrc\n", &pDrv->Out.pStream->szName, rc2)); 1633 } 1650 1634 1651 1635 LogFlowFunc(("\tcbToRead=%RU32, cbToWrite=%RU32, cbWritten=%RU32, cbLeft=%RU32, rc=%Rrc\n", … … 1680 1664 1681 1665 PSB16DRIVER pDrv; 1682 1683 uint32_t cbOutMin = UINT32_MAX;1684 uint32_t cbOut;1685 1666 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1686 { 1687 int rc2 = pDrv->pConnector->pfnStreamGetData(pDrv->pConnector, pDrv->Out.pStream, &cbOut); 1688 if (RT_SUCCESS(rc2)) 1689 cbOutMin = RT_MIN(cbOutMin, cbOut); 1690 } 1691 1692 LogFlowFunc(("cbOutMin=%RU32\n", cbOutMin)); 1693 if (cbOutMin == UINT32_MAX) 1694 { 1695 free = dma_len; 1696 } 1697 else 1698 { 1699 free = cbOutMin & ~pThis->align; /** @todo int vs. uint32. */ 1700 if ((free <= 0) || !dma_len) 1701 return dma_pos; 1702 } 1667 pDrv->pConnector->pfnStreamIterate(pDrv->pConnector, pDrv->Out.pStream); 1668 1669 free = dma_len; 1670 1671 if (free <= 0) 1672 return dma_pos; 1703 1673 1704 1674 copy = free; … … 1761 1731 return; 1762 1732 1733 /* Set timer flag. */ 1734 ASMAtomicXchgBool(&pThis->fTimerActive, true); 1735 1763 1736 /* Update current time timestamp. */ 1764 1737 pThis->uTimerTSIO = TMTimerGet(pThis->pTimerIO); … … 1778 1751 return; 1779 1752 1780 int rc2 = TMTimerStop(pThis->pTimerIO);1781 A ssertRC(rc2);1753 /* Set timer flag. */ 1754 ASMAtomicXchgBool(&pThis->fTimerActive, false); 1782 1755 } 1783 1756 … … 1794 1767 pThis->uTimerTSIO = cTicksNow; 1795 1768 1796 uint32_t cbOut; 1797 AudioMixerSinkTimerUpdate(pThis->pSinkOutput, cTicksPerSec, cTicksElapsed, &cbOut); 1798 if (cbOut) 1799 { 1800 /* New space available, see if we can transfer more. */ 1769 bool fIsPlaying = false; 1770 1771 LogFlowFuncEnter(); 1772 1773 PSB16DRIVER pDrv; 1774 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 1775 { 1776 PPDMAUDIOSTREAM pStream = pDrv->Out.pStream; 1777 1778 PDMAUDIOSTRMSTS strmSts = pDrv->pConnector->pfnStreamGetStatus(pDrv->pConnector, pStream); 1779 fIsPlaying |= ( (strmSts & PDMAUDIOSTRMSTS_FLAG_ENABLED) 1780 || (strmSts & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE)); 1781 1782 LogFlowFunc(("%s: strmSts=0x%x -> fIsPlaying=%RTbool\n", pStream->szName, strmSts, fIsPlaying)); 1783 1784 int rc2 = pDrv->pConnector->pfnStreamIterate(pDrv->pConnector, pStream); 1785 if (RT_SUCCESS(rc2)) 1786 { 1787 if (pStream->enmDir == PDMAUDIODIR_IN) 1788 { 1789 /** @todo Implement this! */ 1790 } 1791 else 1792 { 1793 rc2 = pDrv->pConnector->pfnStreamPlay(pDrv->pConnector, pStream, NULL /* cPlayed */); 1794 if (RT_FAILURE(rc2)) 1795 LogFlowFunc(("%s: Failed playing stream '%s': %Rrc\n", pStream->szName, rc2)); 1796 } 1797 } 1798 } 1799 1800 if ( ASMAtomicReadBool(&pThis->fTimerActive) 1801 || fIsPlaying) 1802 { 1803 /* Schedule the next transfer. */ 1801 1804 PDMDevHlpDMASchedule(pThis->pDevInsR3); 1802 } 1803 1804 /* Kick the timer again. */1805 uint64_t cTicks = pThis->cTimerTicksIO;1806 /** @todo adjust cTicks down by now much cbOutMin represents. */1807 TMTimerSet(pThis->pTimerIO, cTicksNow + cTicks);1805 1806 /* Kick the timer again. */ 1807 uint64_t cTicks = pThis->cTimerTicksIO; 1808 /** @todo adjust cTicks down by now much cbOutMin represents. */ 1809 TMTimerSet(pThis->pTimerIO, cTicksNow + cTicks); 1810 } 1808 1811 } 1809 1812 … … 1934 1937 PDMAUDIOSTREAMCFG streamCfg; 1935 1938 RT_ZERO(streamCfg); 1936 streamCfg.enmDir = PDMAUDIODIR_OUT; 1937 streamCfg.uHz = pThis->freq; 1938 streamCfg.cChannels = 1 << pThis->fmt_stereo; 1939 streamCfg.enmFormat = pThis->fmt; 1940 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 1939 streamCfg.enmDir = PDMAUDIODIR_OUT; 1940 streamCfg.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT; 1941 streamCfg.uHz = pThis->freq; 1942 streamCfg.cChannels = 1 << pThis->fmt_stereo; 1943 streamCfg.enmFormat = pThis->fmt; 1944 streamCfg.enmEndianness = PDMAUDIOHOSTENDIANNESS; 1941 1945 1942 1946 int rc = sb16OpenOut(pThis, &streamCfg); … … 2028 2032 AssertReturn(pCfg->enmDir == PDMAUDIODIR_OUT, VERR_INVALID_PARAMETER); 2029 2033 2030 /* Update the sink's format. */ 2031 PDMPCMPROPS PCMProps; 2032 int rc = DrvAudioHlpStreamCfgToProps(pCfg, &PCMProps); 2033 if (RT_SUCCESS(rc)) 2034 rc = AudioMixerSinkSetFormat(pThis->pSinkOutput, &PCMProps); 2035 2036 if (RT_FAILURE(rc)) 2037 return rc; 2034 int rc = VINF_SUCCESS; 2035 2036 /* Set a default audio format for the host. */ 2037 PDMAUDIOSTREAMCFG CfgHost; 2038 CfgHost.enmDir = PDMAUDIODIR_OUT; 2039 CfgHost.DestSource.Dest = PDMAUDIOPLAYBACKDEST_FRONT; 2040 CfgHost.uHz = 44100; 2041 CfgHost.cChannels = 2; 2042 CfgHost.enmFormat = PDMAUDIOFMT_S16; 2043 CfgHost.enmEndianness = PDMAUDIOHOSTENDIANNESS; 2044 2045 RTStrPrintf(CfgHost.szName, sizeof(CfgHost.szName), "sb16.po"); 2046 2047 uint8_t uLUN = 0; 2038 2048 2039 2049 PSB16DRIVER pDrv; 2040 uint8_t uLUN = 0;2041 2042 2050 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 2043 2051 { … … 2049 2057 } 2050 2058 2051 AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm); 2052 2053 AudioMixerStreamDestroy(pDrv->Out.pMixStrm); 2054 pDrv->Out.pMixStrm = NULL; 2055 2056 int rc2 = AudioMixerSinkCreateStream(pThis->pSinkOutput, pDrv->pConnector, pCfg, 0 /* fFlags */, &pDrv->Out.pMixStrm); 2057 if (RT_SUCCESS(rc2)) 2059 if (pDrv->Out.pStream) 2058 2060 { 2059 rc2 = AudioMixerSinkAddStream(pThis->pSinkOutput, pDrv->Out.pMixStrm); 2060 LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2)); 2061 int rc3 = pDrv->pConnector->pfnStreamDestroy(pDrv->pConnector, pDrv->Out.pStream); 2062 AssertRC(rc3); 2063 2064 pDrv->Out.pStream = NULL; 2061 2065 } 2062 2066 2063 if (RT_FAILURE(rc2)) 2064 { 2065 if (RT_SUCCESS(rc)) 2066 rc = rc2; 2067 break; 2068 } 2067 int rc2 = pDrv->pConnector->pfnStreamCreate(pDrv->pConnector, &CfgHost, pCfg, &pDrv->Out.pStream); 2068 LogFlowFunc(("LUN#%RU8: Created output \"%s\", rc=%Rrc\n", pDrv->uLUN, pCfg->szName, rc2)); 2069 2069 2070 2070 uLUN++; 2071 2071 } 2072 2073 /* Ensure volume gets propagated. */2074 AudioMixerInvalidate(pThis->pMixer);2075 2072 2076 2073 return rc; … … 2086 2083 RTListForEach(&pThis->lstDrv, pDrv, SB16DRIVER, Node) 2087 2084 { 2088 AudioMixerSinkRemoveStream(pThis->pSinkOutput, pDrv->Out.pMixStrm); 2089 AudioMixerStreamDestroy(pDrv->Out.pMixStrm); 2090 pDrv->Out.pMixStrm = NULL; 2085 if (pDrv->Out.pStream) 2086 { 2087 pDrv->pConnector->pfnStreamDestroy(pDrv->pConnector, pDrv->Out.pStream); 2088 pDrv->Out.pStream = NULL; 2089 } 2091 2090 } 2092 2091 } … … 2148 2147 LogRel2(("SB16: Powering off ...\n")); 2149 2148 2150 /** 2151 * Note: Destroy the mixer while powering off and *not* in sb16Destruct, 2152 * giving the mixer the chance to release any references held to 2153 * PDM audio streams it maintains. 2154 */ 2155 if (pThis->pMixer) 2156 { 2157 AudioMixerDestroy(pThis->pMixer); 2158 pThis->pMixer = NULL; 2159 } 2149 sb16CloseOut(pThis); 2160 2150 } 2161 2151 … … 2177 2167 RTMemFree(pDrv); 2178 2168 } 2179 2180 sb16CloseOut(pThis);2181 2169 2182 2170 return VINF_SUCCESS; … … 2339 2327 2340 2328 /** @todo No input streams available for SB16 yet. */ 2341 bool fValidOut = AudioMixerStreamIsValid(pDrv->Out.pMixStrm); 2329 /* Note: Only query the whole backend status here, as we don't have multiple streams to check for. */ 2330 bool fValidOut = pCon->pfnGetStatus(pCon, PDMAUDIODIR_OUT) == PDMAUDIOBACKENDSTS_RUNNING; 2342 2331 if (!fValidOut) 2343 2332 { -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r61177 r61320 67 67 static DECLCALLBACK(int) drvAudioStreamDestroy(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream); 68 68 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd); 69 static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd); 69 70 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream); 70 71 static int drvAudioStreamDestroyInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); … … 252 253 static DECLCALLBACK(int) drvAudioStreamControl(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd) 253 254 { 255 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 256 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 257 254 258 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 255 259 256 return drvAudioStreamControlInternal(pThis, pStream, enmStreamCmd);257 }258 259 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd)260 {261 AssertPtrReturn(pThis, VERR_INVALID_POINTER);262 AssertPtrReturn(pStream, VERR_INVALID_POINTER);263 264 260 int rc = RTCritSectEnter(&pThis->CritSect); 265 261 if (RT_FAILURE(rc)) 266 262 return rc; 267 263 264 LogFlowFunc(("%s\n", pStream->szName)); 265 268 266 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 267 PPDMAUDIOSTREAM pGstStream = pHstStream->pPair; 268 269 /* Note: Call the host (backend) first to see if there is any pending disable 270 * actions in progress. */ 271 rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, enmStreamCmd); 272 if ( RT_SUCCESS(rc) 273 || rc == VERR_AUDIO_STREAM_PENDING_DISABLE) 274 { 275 int rc3 = drvAudioStreamControlInternal(pThis, pStream, enmStreamCmd); 276 if (RT_SUCCESS(rc)) 277 rc = rc3; 278 } 279 280 int rc2 = RTCritSectLeave(&pThis->CritSect); 281 if (RT_SUCCESS(rc)) 282 rc = rc2; 283 284 return rc; 285 } 286 287 static int drvAudioStreamControlInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pGstStream, PDMAUDIOSTREAMCMD enmStreamCmd) 288 { 289 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 290 291 if (!pGstStream) 292 return VINF_SUCCESS; 293 294 int rc = VINF_SUCCESS; 295 296 switch (enmStreamCmd) 297 { 298 case PDMAUDIOSTREAMCMD_ENABLE: 299 { 300 pGstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED; 301 break; 302 } 303 304 case PDMAUDIOSTREAMCMD_DISABLE: 305 { 306 pGstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED; 307 break; 308 } 309 310 case PDMAUDIOSTREAMCMD_PAUSE: 311 { 312 pGstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED; 313 break; 314 } 315 316 case PDMAUDIOSTREAMCMD_RESUME: 317 { 318 pGstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED; 319 break; 320 } 321 322 default: 323 AssertMsgFailed(("Command %ld not implemented\n", enmStreamCmd)); 324 rc = VERR_NOT_IMPLEMENTED; 325 break; 326 } 327 328 LogFlowFunc(("%s: enmStreamCmd=%ld, rc=%Rrc\n", pGstStream->szName, enmStreamCmd, rc)); 329 return rc; 330 } 331 332 static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream, PDMAUDIOSTREAMCMD enmStreamCmd) 333 { 334 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 335 336 if (!pHstStream) 337 return VINF_SUCCESS; 338 339 AssertMsg(pHstStream->enmCtx == PDMAUDIOSTREAMCTX_HOST, 340 ("Stream '%s' is not a host stream and therefore has no backend\n", pHstStream->szName)); 269 341 270 342 LogFlowFunc(("%s: enmStreamCmd=%ld\n", pHstStream->szName, enmStreamCmd)); 343 344 int rc = VINF_SUCCESS; 345 346 PPDMAUDIOSTREAM pGstStream = pHstStream->pPair; /* Can be NULL. */ 271 347 272 348 switch (enmStreamCmd) … … 278 354 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_ENABLE); 279 355 if (RT_SUCCESS(rc)) 280 {281 Assert(!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE));282 356 pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED; 283 } 284 } 285 else 286 rc = VINF_SUCCESS; 287 357 } 288 358 break; 289 359 } … … 291 361 case PDMAUDIOSTREAMCMD_DISABLE: 292 362 { 363 /* Is the guest side stream still active? 364 * Mark the host stream as pending disable and bail out. */ 365 if ( pGstStream 366 && (pGstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 367 { 368 LogFlowFunc(("%s: Pending disable\n", pHstStream->szName)); 369 pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE; 370 rc = VERR_AUDIO_STREAM_PENDING_DISABLE; 371 break; 372 } 373 374 /* Clear pending disable bit. */ 375 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE; 376 293 377 if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED) 294 378 { … … 297 381 { 298 382 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED; 299 AudioMixBuf Clear(&pHstStream->MixBuf);383 AudioMixBufReset(&pHstStream->MixBuf); 300 384 } 301 385 } 302 else303 rc = VINF_SUCCESS;304 305 386 break; 306 387 } … … 308 389 case PDMAUDIOSTREAMCMD_PAUSE: 309 390 { 391 /* Is the guest side stream still active? 392 * Mark the host stream as pending disable and bail out. */ 393 if ( pGstStream 394 && (pGstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 395 { 396 LogFlowFunc(("%s: Pending pause\n", pHstStream->szName)); 397 pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE; 398 rc = VERR_AUDIO_STREAM_PENDING_DISABLE; 399 break; 400 } 401 310 402 if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)) 311 403 { … … 314 406 pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED; 315 407 } 316 else317 rc = VINF_SUCCESS;318 319 408 break; 320 409 } … … 328 417 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED; 329 418 } 330 else331 rc = VINF_SUCCESS;332 333 419 break; 334 420 } … … 342 428 if (RT_FAILURE(rc)) 343 429 LogFunc(("%s: Failed with %Rrc\n", pHstStream->szName, rc)); 344 345 int rc2 = RTCritSectLeave(&pThis->CritSect);346 if (RT_SUCCESS(rc))347 rc = rc2;348 430 349 431 return rc; … … 381 463 } 382 464 465 LogFlowFunc(("[%s]: cbBuf=%RU32\n", pStream->szName, cbBuf)); 466 383 467 int rc = RTCritSectEnter(&pThis->CritSect); 384 468 if (RT_FAILURE(rc)) … … 396 480 PPDMAUDIOSTREAM pGstStream = pHstStream->pPair; 397 481 398 AssertMsg(p HstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED,399 ("Writing to disabled host output stream \"%s\" not possible\n", pHstStream->szName));400 401 if (!AudioMixBufFreeBytes(&p HstStream->MixBuf))482 AssertMsg(pGstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED, 483 ("Writing to disabled guest output stream \"%s\" not possible\n", pGstStream->szName)); 484 485 if (!AudioMixBufFreeBytes(&pGstStream->MixBuf)) 402 486 { 403 487 if (pcbWritten) … … 407 491 } 408 492 409 /* 410 * First, write data from the device emulation into our 411 * guest mixing buffer. 412 */ 413 uint32_t cWritten; 493 uint32_t cWritten = 0; 414 494 rc = AudioMixBufWriteCirc(&pGstStream->MixBuf, pvBuf, cbBuf, &cWritten); 415 495 if (rc == VINF_BUFFER_OVERFLOW) 496 { 416 497 LogRelMax(32, ("Audio: Lost audio samples from guest, expect stuttering audio output\n")); 417 418 /* Host stream currently has no samples to play? */ 419 if (AudioMixBufAvail(&pHstStream->MixBuf) == 0) 498 rc = VINF_SUCCESS; 499 } 500 501 #if 0 502 uint32_t cMixed = 0; 503 if (RT_SUCCESS(rc)) 420 504 { 421 505 /* Mix just written guest stream samples to the host immediately. */ 422 uint32_t cMixed;423 506 rc = AudioMixBufMixToParent(&pGstStream->MixBuf, cWritten, &cMixed); 424 LogFlowFunc(("cMixed=%RU32\n", cMixed)); 425 } 507 } 508 #endif 509 510 #if 0 511 uint32_t cPlayed = 0; 512 if (RT_SUCCESS(rc)) 513 { 514 PDMAUDIOSTRMSTS strmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream); 515 if (strmSts & PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE) 516 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream, &cPlayed); 517 } 518 #endif 426 519 427 520 #ifdef DEBUG_andy … … 461 554 #endif 462 555 463 LogFlowFunc(("%s -> %s: cbBuf=%RU32, cWritten=%RU32 (%RU32 bytes), rc=%Rrc\n", 464 pGstStream->szName, pHstStream->szName, cbBuf, 465 cWritten, AUDIOMIXBUF_S2B(&pHstStream->MixBuf, cWritten), rc)); 556 LogFlowFunc(("cWritten=%RU32 (%RU32 bytes), cMixed=%RU32, rc=%Rrc\n", 557 cWritten, AUDIOMIXBUF_S2B(&pHstStream->MixBuf, cWritten), 0, rc)); 466 558 467 559 int rc2 = RTCritSectLeave(&pThis->CritSect); … … 581 673 582 674 #if 1 583 static DECLCALLBACK(int) drvAudioStream GetData(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, uint32_t *pcData)675 static DECLCALLBACK(int) drvAudioStreamIterate(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream) 584 676 { 585 677 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); … … 593 685 return rc; 594 686 595 uint32_t cData = 0;687 LogFlowFunc(("[%s]\n", pStream->szName)); 596 688 597 689 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); … … 600 692 do 601 693 { 602 if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 603 break; 694 /*if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 695 break;*/ 696 697 PDMAUDIOSTRMSTS hstStrmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream); 604 698 605 699 if (pHstStream->enmDir == PDMAUDIODIR_IN) 606 700 { 607 701 /* Call the host backend to capture the audio input data. */ 608 rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pHstStream, &cData); 702 uint32_t cSamplesCaptured; 703 rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pHstStream, &cSamplesCaptured); 609 704 if (RT_FAILURE(rc)) 610 705 break; … … 613 708 614 709 } 615 else /* Out*/710 else /* PDMAUDIODIR_OUT */ 616 711 { 617 712 uint32_t cSamplesMixed = 0; 618 uint32_t cSamplesToMix = 0; 619 620 uint32_t cSamplesLive = AudioMixBufAvail(&pHstStream->MixBuf); 621 if (!cSamplesLive) 622 { 623 624 } 625 626 cSamplesToMix = AudioMixBufAvail(&pGstStream->MixBuf); 627 if (cSamplesToMix) 628 rc = AudioMixBufMixToParent(&pGstStream->MixBuf, cSamplesToMix, &cSamplesMixed); 713 uint32_t cSamplesToMix = AudioMixBufUsed(&pGstStream->MixBuf); 629 714 630 715 /* Has this stream marked as disabled but there still were guest streams relying … … 633 718 && !cSamplesToMix) 634 719 { 635 /* Stop playing the current (pending) stream. */ 636 int rc2 = drvAudioStreamControlInternal(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 637 if (RT_SUCCESS(rc2)) 638 { 639 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE; 640 641 LogFunc(("%s: Disabling stream\n", pHstStream->szName)); 642 } 643 else 644 LogFunc(("%s: Backend vetoed against closing output stream, rc=%Rrc\n", pHstStream->szName, rc2)); 720 rc = drvAudioStreamControlInternal(pThis, pGstStream, PDMAUDIOSTREAMCMD_DISABLE); 721 if (RT_SUCCESS(rc)) 722 rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 723 724 if (RT_FAILURE(rc)) 725 LogFunc(("%s: Backend vetoed against closing output stream, rc=%Rrc\n", pHstStream->szName, rc)); 645 726 646 727 break; 647 728 } 648 729 649 LogFlowFunc(("%s: cSamplesLive=%RU32, cSamplesToMix=%RU32, cSamplesMixed=%RU32\n", 650 pHstStream->szName, cSamplesLive, cSamplesToMix, cSamplesMixed)); 651 652 /* Return live samples to play. */ 653 cData = cSamplesLive; 654 } 730 uint32_t cSamplesPlayed = 0; 731 if (hstStrmSts & PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE) 732 { 733 /* int rc2 = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream, &cSamplesPlayed); 734 if (RT_SUCCESS(rc)) 735 rc = rc2; 736 }*/ 737 738 if (cSamplesToMix) 739 rc = AudioMixBufMixToParent(&pGstStream->MixBuf, cSamplesToMix, &cSamplesMixed); 740 } 741 742 LogFlowFunc(("%s: %RU32/%RU32 samples mixed, %RU32 played\n", 743 pHstStream->szName, cSamplesMixed, cSamplesToMix, cSamplesPlayed)); 744 } 745 746 if (RT_SUCCESS(rc)) 747 rc = pThis->pHostDrvAudio->pfnStreamIterate(pThis->pHostDrvAudio, pHstStream); 655 748 656 749 } while (0); 657 658 #ifdef DEBUG_andy659 LogFlowFunc(("%s: cData=%RU32\n", pHstStream->szName, cData));660 #endif661 662 if (pcData)663 *pcData = cData;664 750 665 751 int rc2 = RTCritSectLeave(&pThis->CritSect); … … 846 932 /* pcSamplesPlayed is optional. */ 847 933 934 AssertMsg(pStream->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED, 935 ("Unable to play stream '%s' (status is 0x%x)\n", pStream->szName, pStream->fStatus)); 936 848 937 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 849 938 … … 852 941 return rc; 853 942 854 /* Backend output (temporarily) disabled / unavailable? */ 855 if (pThis->pHostDrvAudio->pfnGetStatus(pThis->pHostDrvAudio, PDMAUDIODIR_OUT) != PDMAUDIOBACKENDSTS_RUNNING) 856 { 857 rc = pThis->pHostDrvAudio->pfnGetConfig(pThis->pHostDrvAudio, &pThis->BackendCfg); 858 AssertRC(rc); 859 860 if ( !pThis->BackendCfg.cSinks 861 || !pThis->BackendCfg.cMaxStreamsOut) 862 { 863 int rc2 = RTCritSectLeave(&pThis->CritSect); 864 AssertRC(rc2); 865 866 return VERR_NOT_AVAILABLE; 867 } 868 } 869 870 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 943 LogFlowFunc(("[%s]\n", pStream->szName)); 871 944 872 945 uint32_t cSamplesPlayed = 0; 873 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream, &cSamplesPlayed); 874 if (RT_FAILURE(rc)) 875 { 876 int rc3 = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 877 AssertRC(rc3); 878 } 879 880 LogFlowFunc(("[%s] cSamplesPlayed=%RU32, rc=%Rrc\n", pStream->szName, cSamplesPlayed, rc)); 881 882 PPDMAUDIOSTREAM pGstStream = pHstStream->pPair; 883 if (pGstStream) 884 { 885 bool fIsEmpty = AudioMixBufIsEmpty(&pGstStream->MixBuf); 886 887 888 } 889 890 #if 0 891 if (pStream->pPair) 892 { 893 bool fIsEmpty = AudioMixBufIsEmpty(&pStream->pPair->MixBuf); 894 895 if ( !pPair->State.fActive 896 && fIsEmpty) 897 continue; 898 899 if () 900 { 901 pGstStrmOut->State.fEmpty = true; 902 fNeedsCleanup |= !pGstStrmOut->State.fActive; 903 } 904 } 905 906 if (fNeedsCleanup) 907 { 908 RTListForEach(&pHstStrmOut->lstGstStrmOut, pGstStrmOut, PDMAUDIOGSTSTRMOUT, Node) 909 { 910 if (!pGstStrmOut->State.fActive) 911 drvAudioDestroyGstOut(pThis, pGstStrmOut); 912 } 913 } 914 #endif 946 947 do 948 { 949 /* Backend output (temporarily) disabled / unavailable? */ 950 if (pThis->pHostDrvAudio->pfnGetStatus(pThis->pHostDrvAudio, PDMAUDIODIR_OUT) != PDMAUDIOBACKENDSTS_RUNNING) 951 { 952 rc = pThis->pHostDrvAudio->pfnGetConfig(pThis->pHostDrvAudio, &pThis->BackendCfg); 953 AssertRC(rc); 954 955 if ( !pThis->BackendCfg.cSinks 956 || !pThis->BackendCfg.cMaxStreamsOut) 957 { 958 rc = VERR_NOT_AVAILABLE; 959 break; 960 } 961 } 962 963 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 964 PPDMAUDIOSTREAM pGstStream = pHstStream->pPair; 965 AssertPtr(pGstStream); 966 967 PDMAUDIOSTRMSTS strmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream); 968 969 if (strmSts & PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE) 970 { 971 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream, &cSamplesPlayed); 972 if (RT_FAILURE(rc)) 973 { 974 int rc3 = drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); 975 AssertRC(rc3); 976 } 977 } 978 979 LogFlowFunc(("[%s] strmSts=0x%x, cSamplesPlayed=%RU32, rc=%Rrc\n", pStream->szName, strmSts, cSamplesPlayed, rc)); 980 981 #if 0 982 if (pStream->pPair) 983 { 984 bool fIsEmpty = AudioMixBufIsEmpty(&pStream->pPair->MixBuf); 985 986 if ( !pPair->State.fActive 987 && fIsEmpty) 988 continue; 989 990 if () 991 { 992 pGstStrmOut->State.fEmpty = true; 993 fNeedsCleanup |= !pGstStrmOut->State.fActive; 994 } 995 } 996 997 if (fNeedsCleanup) 998 { 999 RTListForEach(&pHstStrmOut->lstGstStrmOut, pGstStrmOut, PDMAUDIOGSTSTRMOUT, Node) 1000 { 1001 if (!pGstStrmOut->State.fActive) 1002 drvAudioDestroyGstOut(pThis, pGstStrmOut); 1003 } 1004 } 1005 #endif 1006 } while (0); 915 1007 916 1008 if (RT_SUCCESS(rc)) … … 1574 1666 AssertRCBreak(rc); 1575 1667 1576 rc = AudioMixBufInit(&pHstStrm->MixBuf, pHstStrm->szName, &pHstStrm->Props, cSamples );1668 rc = AudioMixBufInit(&pHstStrm->MixBuf, pHstStrm->szName, &pHstStrm->Props, cSamples * 4); 1577 1669 AssertRCBreak(rc); 1578 1670 … … 1587 1679 AssertRCBreak(rc); 1588 1680 1589 rc = AudioMixBufInit(&pGstStrm->MixBuf, pGstStrm->szName, &pGstStrm->Props, AudioMixBufSize(&pHstStrm->MixBuf));1681 rc = AudioMixBufInit(&pGstStrm->MixBuf, pGstStrm->szName, &pGstStrm->Props, cSamples * 2); 1590 1682 if (RT_SUCCESS(rc)) 1591 1683 { 1592 1684 if (pCfgGuest->enmDir == PDMAUDIODIR_IN) 1593 1685 { 1686 /* Host (Parent) -> Guest (Child). */ 1594 1687 rc = AudioMixBufLinkTo(&pHstStrm->MixBuf, &pGstStrm->MixBuf); 1595 1688 } 1596 1689 else 1597 1690 { 1691 /* Guest (Parent) -> Host (Child). */ 1598 1692 rc = AudioMixBufLinkTo(&pGstStrm->MixBuf, &pHstStrm->MixBuf); 1599 1693 } … … 1618 1712 if (pHstStrm->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 1619 1713 { 1620 rc = drvAudioStreamControlInternal (pThis, pHstStrm, PDMAUDIOSTREAMCMD_DISABLE);1714 rc = drvAudioStreamControlInternalBackend(pThis, pHstStrm, PDMAUDIOSTREAMCMD_DISABLE); 1621 1715 if (RT_SUCCESS(rc)) 1622 1716 { … … 1686 1780 } 1687 1781 1782 static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvAudioGetStatus(PPDMIAUDIOCONNECTOR pInterface, PDMAUDIODIR enmDir) 1783 { 1784 AssertPtrReturn(pInterface, PDMAUDIOBACKENDSTS_UNKNOWN); 1785 1786 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 1787 1788 int rc = RTCritSectEnter(&pThis->CritSect); 1789 if (RT_FAILURE(rc)) 1790 return PDMAUDIOBACKENDSTS_UNKNOWN; 1791 1792 PDMAUDIOBACKENDSTS backendSts = pThis->pHostDrvAudio->pfnGetStatus(pThis->pHostDrvAudio, enmDir); 1793 1794 int rc2 = RTCritSectLeave(&pThis->CritSect); 1795 if (RT_SUCCESS(rc)) 1796 rc = rc2; 1797 1798 LogFlowFuncLeaveRC(rc); 1799 return backendSts; 1800 } 1801 1688 1802 static DECLCALLBACK(PDMAUDIOSTRMSTS) drvAudioStreamGetStatus(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream) 1689 1803 { … … 1723 1837 rc = VERR_WRONG_ORDER; 1724 1838 1725 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 1726 if ( RT_SUCCESS(rc) 1727 && pHstStream->cRefs == 1) 1728 { 1729 rc = drvAudioStreamDestroyInternalBackend(pThis, pHstStream); 1839 if (RT_SUCCESS(rc)) 1840 { 1841 rc = drvAudioStreamDestroyInternal(pThis, pStream); 1730 1842 if (RT_SUCCESS(rc)) 1731 { 1732 if (pStream->pPair) 1733 { 1734 rc = drvAudioStreamDestroyInternal(pThis, pStream->pPair); 1735 pStream->pPair = NULL; 1736 } 1737 1738 if (RT_SUCCESS(rc)) 1739 rc = drvAudioStreamDestroyInternal(pThis, pStream); 1740 1741 if (RT_SUCCESS(rc)) 1742 { 1743 if (enmDir == PDMAUDIODIR_IN) 1744 { 1745 pThis->cStreamsFreeIn++; 1746 } 1747 else /* Out */ 1748 { 1749 pThis->cStreamsFreeOut++; 1750 } 1751 } 1752 } 1753 } 1754 else 1755 rc = VERR_WRONG_ORDER; 1843 pStream = NULL; 1844 } 1845 1846 if (RT_SUCCESS(rc)) 1847 { 1848 if (enmDir == PDMAUDIODIR_IN) 1849 { 1850 pThis->cStreamsFreeIn++; 1851 } 1852 else /* Out */ 1853 { 1854 pThis->cStreamsFreeOut++; 1855 } 1856 } 1756 1857 1757 1858 int rc2 = RTCritSectLeave(&pThis->CritSect); … … 1767 1868 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream) 1768 1869 { 1769 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1770 AssertPtrReturn(pHstStream, VERR_INVALID_POINTER); 1870 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 1871 1872 if (!pHstStream) 1873 return VINF_SUCCESS; 1771 1874 1772 1875 int rc = VINF_SUCCESS; … … 1779 1882 if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 1780 1883 { 1781 rc = drvAudioStreamControlInternal (pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE);1884 rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 1782 1885 if (RT_SUCCESS(rc)) 1783 1886 { … … 1786 1889 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 1787 1890 } 1788 1789 AssertMsgRC(rc, ("Host stream '%s' failed to uninit in backend: %Rrc\n", pHstStream->szName, rc));1790 1891 } 1791 1892 else … … 1806 1907 LogFlowFunc(("%s: cRefs=%RU32\n", pStream->szName, pStream->cRefs)); 1807 1908 1808 int rc = VINF_SUCCESS; 1809 1810 if (pStream->cRefs <= 1) 1909 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 1910 PPDMAUDIOSTREAM pGstStream = pHstStream->pPair; 1911 1912 if ( ( pHstStream 1913 && pHstStream->cRefs > 1) 1914 || ( pGstStream 1915 && pGstStream->cRefs > 1) 1916 ) 1917 { 1918 return VERR_WRONG_ORDER; 1919 } 1920 1921 int rc = drvAudioStreamControlInternal(pThis, pGstStream, PDMAUDIOSTREAMCMD_DISABLE); 1922 if (RT_SUCCESS(rc)) 1923 rc = drvAudioStreamControlInternalBackend(pThis, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 1924 1925 if (RT_SUCCESS(rc)) 1811 1926 { 1812 1927 /* Unlink from pair. */ … … 1826 1941 pStream = NULL; 1827 1942 } 1828 else /* More than our own reference left? Bail out. */1829 rc = VERR_WRONG_ORDER;1830 1943 1831 1944 if (RT_FAILURE(rc)) … … 1864 1977 LogFlowFuncEnter(); 1865 1978 1866 /* 1867 * Second, destroy all audio streams. 1868 */ 1869 PPDMAUDIOSTREAM pStream; 1870 RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, Node) 1871 { 1872 if (pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST) 1873 drvAudioStreamDestroyInternalBackend(pThis, pStream); 1874 } 1979 PPDMAUDIOSTREAM pStream, pStreamNext; 1980 RTListForEachSafe(&pThis->lstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, Node) 1981 drvAudioStreamDestroyInternal(pThis, pStream); 1875 1982 1876 1983 /* … … 1906 2013 /* IAudioConnector. */ 1907 2014 pThis->IAudioConnector.pfnGetConfig = drvAudioGetConfig; 2015 pThis->IAudioConnector.pfnGetStatus = drvAudioGetStatus; 1908 2016 pThis->IAudioConnector.pfnStreamCreate = drvAudioStreamCreate; 1909 2017 pThis->IAudioConnector.pfnStreamDestroy = drvAudioStreamDestroy; … … 1913 2021 pThis->IAudioConnector.pfnStreamRead = drvAudioStreamRead; 1914 2022 pThis->IAudioConnector.pfnStreamWrite = drvAudioStreamWrite; 1915 pThis->IAudioConnector.pfnStream GetData = drvAudioStreamGetData;2023 pThis->IAudioConnector.pfnStreamIterate = drvAudioStreamIterate; 1916 2024 pThis->IAudioConnector.pfnStreamGetStatus = drvAudioStreamGetStatus; 1917 2025 pThis->IAudioConnector.pfnStreamPlay = drvAudioStreamPlay; -
trunk/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp
r61167 r61320 1433 1433 1434 1434 return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED); 1435 } 1436 1437 static DECLCALLBACK(int) drvHostALSAAudioStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1438 { 1439 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1440 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1441 1442 LogFlowFuncEnter(); 1443 1444 /* Nothing to do here for ALSA. */ 1445 return VINF_SUCCESS; 1435 1446 } 1436 1447 -
trunk/src/VBox/Devices/Audio/DrvHostNullAudio.cpp
r61167 r61320 278 278 279 279 return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED); 280 } 281 282 static DECLCALLBACK(int) drvHostNullAudioStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 283 { 284 NOREF(pInterface); 285 NOREF(pStream); 286 287 return VINF_SUCCESS; 280 288 } 281 289 -
trunk/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp
r61167 r61320 1043 1043 1044 1044 return rc; 1045 } 1046 1047 static DECLCALLBACK(int) drvHostOSSAudioStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1048 { 1049 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1050 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1051 1052 LogFlowFuncEnter(); 1053 1054 /* Nothing to do here for OSS. */ 1055 return VINF_SUCCESS; 1045 1056 } 1046 1057 -
trunk/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp
r61167 r61320 105 105 uint32_t cbPCMBuf; 106 106 /** Pointer to opaque PulseAudio stream. */ 107 pa_stream *p Stream;107 pa_stream *pPAStream; 108 108 /** Pulse sample format and attribute specification. */ 109 109 pa_sample_spec SampleSpec; … … 321 321 paError(pStrm->pDrv, "Failed to drain stream"); 322 322 323 pa_operation_unref(pStrm->pDrainOp); 324 pStrm->pDrainOp = NULL; 323 if (pStrm->pDrainOp) 324 { 325 pa_operation_unref(pStrm->pDrainOp); 326 pStrm->pDrainOp = NULL; 327 } 325 328 } 326 329 … … 631 634 pStrm->BufAttr.maxlength = (pStrm->BufAttr.tlength * 3) / 2; 632 635 pStrm->BufAttr.prebuf = -1; /* Same as tlength */ 633 634 /* Set minreq to 0, as we want to control ourselves when to start/stop the stream. */ 635 pStrm->BufAttr.minreq = 0; 636 pStrm->BufAttr.minreq = -1; 636 637 637 638 /* Note that the struct BufAttr is updated to the obtained values after this call! */ 638 int rc = paStreamOpen(pThis, false /* fIn */, "PulseAudio (Out)", &pStrm->SampleSpec, &pStrm->BufAttr, &pStrm->p Stream);639 int rc = paStreamOpen(pThis, false /* fIn */, "PulseAudio (Out)", &pStrm->SampleSpec, &pStrm->BufAttr, &pStrm->pPAStream); 639 640 if (RT_FAILURE(rc)) 640 641 return rc; … … 706 707 /* Note: Other members of BufAttr are ignored for record streams. */ 707 708 int rc = paStreamOpen(pThis, true /* fIn */, "PulseAudio (In)", &pStrm->SampleSpec, &pStrm->BufAttr, 708 &pStrm->p Stream);709 &pStrm->pPAStream); 709 710 if (RT_FAILURE(rc)) 710 711 return rc; … … 731 732 pStream->Props.uHz, pStream->Props.cChannels, pStream->Props.cShift, cSamples)); 732 733 734 /* Save pointer to driver instance. */ 735 pStrm->pDrv = pThis; 736 pStrm->pu8PeekBuf = NULL; 737 733 738 if (pcSamples) 734 739 *pcSamples = cSamples; 735 736 /* Save pointer to driver instance. */737 pStrm->pDrv = pThis;738 739 pStrm->pu8PeekBuf = NULL;740 740 } 741 741 … … 756 756 /* We should only call pa_stream_readable_size() once and trust the first value. */ 757 757 pa_threaded_mainloop_lock(pThis->pMainLoop); 758 size_t cbAvail = pa_stream_readable_size(pStrm->p Stream);758 size_t cbAvail = pa_stream_readable_size(pStrm->pPAStream); 759 759 pa_threaded_mainloop_unlock(pThis->pMainLoop); 760 760 … … 792 792 { 793 793 pa_threaded_mainloop_lock(pThis->pMainLoop); 794 pa_stream_peek(pStrm->p Stream,794 pa_stream_peek(pStrm->pPAStream, 795 795 (const void**)&pStrm->pu8PeekBuf, &pStrm->cbPeekBuf); 796 796 pa_threaded_mainloop_unlock(pThis->pMainLoop); … … 840 840 { 841 841 pa_threaded_mainloop_lock(pThis->pMainLoop); 842 pa_stream_drop(pStrm->p Stream);842 pa_stream_drop(pStrm->pPAStream); 843 843 pa_threaded_mainloop_unlock(pThis->pMainLoop); 844 844 … … 878 878 uint32_t cbReadTotal = 0; 879 879 880 uint32_t cLive = AudioMixBuf Avail(&pStream->MixBuf);880 uint32_t cLive = AudioMixBufUsed(&pStream->MixBuf); 881 881 if (!cLive) 882 882 { … … 891 891 do 892 892 { 893 size_t cbWriteable = pa_stream_writable_size(pPAStream->p Stream);893 size_t cbWriteable = pa_stream_writable_size(pPAStream->pPAStream); 894 894 if (cbWriteable == (size_t)-1) 895 895 { … … 916 916 917 917 cbRead = AUDIOMIXBUF_S2B(&pStream->MixBuf, cRead); 918 if (pa_stream_write(pPAStream->p Stream, pPAStream->pvPCMBuf, cbRead, NULL /* Cleanup callback */,918 if (pa_stream_write(pPAStream->pPAStream, pPAStream->pvPCMBuf, cbRead, NULL /* Cleanup callback */, 919 919 0, PA_SEEK_RELATIVE) < 0) 920 920 { … … 960 960 { 961 961 int rc2 = pa_context_errno(pThis->pContext); 962 LogRel (("PulseAudio: %s: %s\n", szMsg, pa_strerror(rc2)));962 LogRel2(("PulseAudio: %s: %s\n", szMsg, pa_strerror(rc2))); 963 963 } 964 964 … … 1136 1136 LogFlowFuncEnter(); 1137 1137 1138 if (pStrm->p Stream)1138 if (pStrm->pPAStream) 1139 1139 { 1140 1140 pa_threaded_mainloop_lock(pThis->pMainLoop); 1141 1141 1142 pa_stream_disconnect(pStrm->p Stream);1143 pa_stream_unref(pStrm->p Stream);1142 pa_stream_disconnect(pStrm->pPAStream); 1143 pa_stream_unref(pStrm->pPAStream); 1144 1144 1145 1145 pa_threaded_mainloop_unlock(pThis->pMainLoop); 1146 1146 1147 pStrm->p Stream = NULL;1147 pStrm->pPAStream = NULL; 1148 1148 } 1149 1149 … … 1161 1161 LogFlowFuncEnter(); 1162 1162 1163 if (pStrm->p Stream)1163 if (pStrm->pPAStream) 1164 1164 { 1165 1165 pa_threaded_mainloop_lock(pThis->pMainLoop); 1166 1166 1167 pa_stream_disconnect(pStrm->pStream); 1168 pa_stream_unref(pStrm->pStream); 1167 /* Make sure to cancel a pending draining operation, if any. */ 1168 if (pStrm->pDrainOp) 1169 { 1170 pa_operation_cancel(pStrm->pDrainOp); 1171 pStrm->pDrainOp = NULL; 1172 } 1173 1174 pa_stream_disconnect(pStrm->pPAStream); 1175 pa_stream_unref(pStrm->pPAStream); 1169 1176 1170 1177 pa_threaded_mainloop_unlock(pThis->pMainLoop); 1171 1178 1172 pStrm->p Stream = NULL;1179 pStrm->pPAStream = NULL; 1173 1180 } 1174 1181 … … 1213 1220 else 1214 1221 { 1215 rc = paWaitFor(pThis, pa_stream_cork(pStrm->p Stream, 0, paStreamCbSuccess, pStrm));1222 rc = paWaitFor(pThis, pa_stream_cork(pStrm->pPAStream, 0, paStreamCbSuccess, pStrm)); 1216 1223 } 1217 1224 … … 1228 1235 if (!pStrm->pDrainOp) 1229 1236 { 1230 rc = paWaitFor(pThis, pa_stream_trigger(pStrm->p Stream, paStreamCbSuccess, pStrm));1237 rc = paWaitFor(pThis, pa_stream_trigger(pStrm->pPAStream, paStreamCbSuccess, pStrm)); 1231 1238 if (RT_LIKELY(RT_SUCCESS(rc))) 1232 pStrm->pDrainOp = pa_stream_drain(pStrm->p Stream, paStreamCbDrain, pStrm);1239 pStrm->pDrainOp = pa_stream_drain(pStrm->pPAStream, paStreamCbDrain, pStrm); 1233 1240 } 1234 1241 pa_threaded_mainloop_unlock(pThis->pMainLoop); … … 1265 1272 { 1266 1273 pa_threaded_mainloop_lock(pThis->pMainLoop); 1267 rc = paWaitFor(pThis, pa_stream_cork(pStrm->p Stream, 0 /* Play / resume */, paStreamCbSuccess, pStrm));1274 rc = paWaitFor(pThis, pa_stream_cork(pStrm->pPAStream, 0 /* Play / resume */, paStreamCbSuccess, pStrm)); 1268 1275 pa_threaded_mainloop_unlock(pThis->pMainLoop); 1269 1276 break; … … 1276 1283 if (pStrm->pu8PeekBuf) /* Do we need to drop the peek buffer?*/ 1277 1284 { 1278 pa_stream_drop(pStrm->p Stream);1285 pa_stream_drop(pStrm->pPAStream); 1279 1286 pStrm->pu8PeekBuf = NULL; 1280 1287 } 1281 1288 1282 rc = paWaitFor(pThis, pa_stream_cork(pStrm->p Stream, 1 /* Stop / pause */, paStreamCbSuccess, pStrm));1289 rc = paWaitFor(pThis, pa_stream_cork(pStrm->pPAStream, 1 /* Stop / pause */, paStreamCbSuccess, pStrm)); 1283 1290 pa_threaded_mainloop_unlock(pThis->pMainLoop); 1284 1291 break; … … 1388 1395 static DECLCALLBACK(PDMAUDIOSTRMSTS) drvHostPulseAudioStreamGetStatus(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1389 1396 { 1390 NOREF(pInterface); 1391 NOREF(pStream); 1392 1393 return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED); 1397 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1398 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1399 1400 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1401 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pStream; 1402 1403 PDMAUDIOSTRMSTS strmSts = PDMAUDIOSTRMSTS_FLAG_INITIALIZED 1404 | PDMAUDIOSTRMSTS_FLAG_ENABLED; 1405 1406 pa_context_state_t ctxState = pa_context_get_state(pThis->pContext); 1407 1408 if ( pa_context_get_state(pThis->pContext) == PA_CONTEXT_READY 1409 && pa_stream_get_state(pStrm->pPAStream) == PA_STREAM_READY) 1410 { 1411 if (pStream->enmDir == PDMAUDIODIR_IN) 1412 { 1413 1414 } 1415 else 1416 { 1417 size_t cbSize = pa_stream_writable_size(pStrm->pPAStream); 1418 LogFlowFunc(("cbSize=%zu\n", cbSize)); 1419 1420 if (cbSize >= pStrm->BufAttr.minreq) 1421 { 1422 strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE; 1423 } 1424 } 1425 } 1426 1427 return strmSts; 1428 } 1429 1430 static DECLCALLBACK(int) drvHostPulseAudioStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 1431 { 1432 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1433 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1434 1435 PDRVHOSTPULSEAUDIO pThis = PDMIHOSTAUDIO_2_DRVHOSTPULSEAUDIO(pInterface); 1436 PPULSEAUDIOSTREAM pStrm = (PPULSEAUDIOSTREAM)pStream; 1437 1438 LogFlowFuncEnter(); 1439 1440 /* Nothing to do here for PulseAudio. */ 1441 return VINF_SUCCESS; 1394 1442 } 1395 1443 -
trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp
r61167 r61320 5 5 6 6 /* 7 * Copyright (C) 2014-201 5Oracle Corporation7 * Copyright (C) 2014-2016 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 48 48 44100, /* Hz */ 49 49 2 /* Channels */, 50 PDMAUDIOFMT_S16 50 PDMAUDIOFMT_S16 /* Format */, 51 51 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ 52 52 }; … … 104 104 RTTESTI_CHECK(AudioMixBufFree(&mb) == 1); 105 105 RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, 1U)); 106 RTTESTI_CHECK(AudioMixBuf Processed(&mb) == cToWrite + written_abs /* + last absolute write */);106 RTTESTI_CHECK(AudioMixBufUsed(&mb) == cToWrite + written_abs /* + last absolute write */); 107 107 108 108 RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&mb, &samples16, sizeof(samples16), &written)); … … 110 110 RTTESTI_CHECK(AudioMixBufFree(&mb) == 0); 111 111 RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, 0)); 112 RTTESTI_CHECK(AudioMixBuf Processed(&mb) == cBufSize);112 RTTESTI_CHECK(AudioMixBufUsed(&mb) == cBufSize); 113 113 114 114 /* Circular reads. */ … … 123 123 RTTESTI_CHECK(AudioMixBufFree(&mb) == AudioMixBufSize(&mb) - written_abs - 1); 124 124 RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, cBufSize - written_abs - 1)); 125 RTTESTI_CHECK(AudioMixBuf Processed(&mb) == cBufSize - cToRead + written_abs);125 RTTESTI_CHECK(AudioMixBufUsed(&mb) == cBufSize - cToRead + written_abs); 126 126 127 127 RTTESTI_CHECK_RC_OK(AudioMixBufReadCirc(&mb, &samples16, sizeof(samples16), &read)); … … 130 130 RTTESTI_CHECK(AudioMixBufFree(&mb) == cBufSize - written_abs); 131 131 RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_S2B(&mb, cBufSize - written_abs)); 132 RTTESTI_CHECK(AudioMixBuf Processed(&mb) == written_abs);132 RTTESTI_CHECK(AudioMixBufUsed(&mb) == written_abs); 133 133 134 134 AudioMixBufDestroy(&mb); … … 139 139 static int tstParentChild(RTTEST hTest) 140 140 { 141 RTTestSubF(hTest, "2 Children -> Parent"); 142 143 uint32_t cBufSize = _1K; 141 uint32_t cBufSize = RTRandU32() % 256; 144 142 145 143 PDMAUDIOSTREAMCFG cfg_p = … … 150 148 44100, /* Hz */ 151 149 2 /* Channels */, 152 PDMAUDIOFMT_S16 150 PDMAUDIOFMT_S16 /* Format */, 153 151 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ 154 152 }; … … 168 166 22050, /* Hz */ 169 167 2 /* Channels */, 170 PDMAUDIOFMT_S16 168 PDMAUDIOFMT_S16 /* Format */, 171 169 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ 172 170 }; … … 186 184 48000, /* Hz */ 187 185 2 /* Channels */, 188 PDMAUDIOFMT_S16 186 PDMAUDIOFMT_S16 /* Format */, 189 187 PDMAUDIOENDIANNESS_LITTLE /* ENDIANNESS */ 190 188 }; … … 215 213 uint32_t cSamplesChild2 = 16; 216 214 217 uint32_t t = RTRandU32() % 64; 215 uint32_t t = RTRandU32() % 1024; 216 217 RTTestPrintf(hTest, RTTESTLVL_DEBUG, "%RU32 iterations total\n", t); 218 219 /* 220 * Using AudioMixBufWriteAt for writing to children. 221 */ 222 RTTestSubF(hTest, "2 Children -> Parent (AudioMixBufWriteAt)"); 218 223 219 224 for (uint32_t i = 0; i < t; i++) … … 223 228 RTTESTI_CHECK_MSG_BREAK(written == cSamplesChild1, ("Child1: Expected %RU32 written samples, got %RU32\n", cSamplesChild1, written)); 224 229 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child1, written, &mixed)); 225 temp = AudioMixBufProcessed(&parent) - AudioMixBufMixed(&child2); 226 RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child1) == temp, ("Child1: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child1), temp)); 230 RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child1) == mixed, ("Child1: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child1), mixed)); 231 RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child1) == AUDIOMIXBUF_S2S_RATIO(&parent, mixed), ("Child1: Expected %RU32 used samples, got %RU32\n", AudioMixBufMixed(&child1), AUDIOMIXBUF_S2S_RATIO(&parent, mixed))); 232 RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&parent) == 0, ("Parent: Expected 0 used samples, got %RU32\n", AudioMixBufUsed(&parent))); 227 233 228 234 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteAt(&child2, 0, &samples, sizeof(samples), &written)); 229 235 RTTESTI_CHECK_MSG_BREAK(written == cSamplesChild2, ("Child2: Expected %RU32 written samples, got %RU32\n", cSamplesChild2, written)); 230 236 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufMixToParent(&child2, written, &mixed)); 231 temp = AudioMixBufProcessed(&parent) - AudioMixBufMixed(&child1); 232 RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child2) == temp, ("Child2: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child2), temp)); 233 } 234 235 RTTESTI_CHECK(AudioMixBufProcessed(&parent) == AudioMixBufMixed(&child1) + AudioMixBufMixed(&child2)); 237 RTTESTI_CHECK_MSG_BREAK(AudioMixBufMixed(&child2) == mixed, ("Child2: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child2), temp)); 238 RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&child2) == AUDIOMIXBUF_S2S_RATIO(&parent, mixed), ("Child2: Expected %RU32 used samples, got %RU32\n", AudioMixBufMixed(&child2), AUDIOMIXBUF_S2S_RATIO(&parent, mixed))); 239 RTTESTI_CHECK_MSG_BREAK(AudioMixBufUsed(&parent) == 0, ("Parent2: Expected 0 used samples, got %RU32\n", AudioMixBufUsed(&parent))); 240 } 241 242 RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufMixed(&child1) + AudioMixBufMixed(&child2)); 236 243 237 244 for (;;) … … 243 250 } 244 251 245 RTTESTI_CHECK(AudioMixBuf Processed(&parent) == 0);252 RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0); 246 253 RTTESTI_CHECK(AudioMixBufMixed(&child1) == 0); 247 254 RTTESTI_CHECK(AudioMixBufMixed(&child2) == 0); … … 328 335 RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written)); 329 336 RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed)); 330 temp = AudioMixBuf Processed(&parent);337 temp = AudioMixBufUsed(&parent); 331 338 RTTESTI_CHECK_MSG(AudioMixBufMixed(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child), temp)); 332 339 333 RTTESTI_CHECK(AudioMixBuf Processed(&parent) == AudioMixBufMixed(&child));340 RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufMixed(&child)); 334 341 335 342 for (;;) … … 355 362 } 356 363 357 RTTESTI_CHECK(AudioMixBuf Processed(&parent) == 0);364 RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0); 358 365 RTTESTI_CHECK(AudioMixBufMixed(&child) == 0); 359 366 … … 431 438 RTTESTI_CHECK_MSG(written == cSamplesChild, ("Child: Expected %RU32 written samples, got %RU32\n", cSamplesChild, written)); 432 439 RTTESTI_CHECK_RC_OK(AudioMixBufMixToParent(&child, written, &mixed)); 433 temp = AudioMixBuf Processed(&parent);440 temp = AudioMixBufUsed(&parent); 434 441 RTTESTI_CHECK_MSG(AudioMixBufMixed(&child) == temp, ("Child: Expected %RU32 mixed samples, got %RU32\n", AudioMixBufMixed(&child), temp)); 435 442 436 RTTESTI_CHECK(AudioMixBuf Processed(&parent) == AudioMixBufMixed(&child));443 RTTESTI_CHECK(AudioMixBufUsed(&parent) == AudioMixBufMixed(&child)); 437 444 438 445 for (;;) … … 458 465 } 459 466 460 RTTESTI_CHECK(AudioMixBuf Processed(&parent) == 0);467 RTTESTI_CHECK(AudioMixBufUsed(&parent) == 0); 461 468 RTTESTI_CHECK(AudioMixBufMixed(&child) == 0); 462 469 -
trunk/src/VBox/Devices/Makefile.kmk
r61157 r61320 5 5 6 6 # 7 # Copyright (C) 2006-201 5Oracle Corporation7 # Copyright (C) 2006-2016 Oracle Corporation 8 8 # 9 9 # This file is part of VirtualBox Open Source Edition (OSE), as … … 565 565 566 566 ifeq ($(KBUILD_TARGET),linux) 567 VBoxDD_SOURCES += \ 568 Audio/DrvHostOSSAudio.cpp 567 ifdef VBOX_WITH_OSS 568 VBoxDD_DEFS += VBOX_WITH_OSS 569 VBoxDD_SOURCES += \ 570 Audio/DrvHostOSSAudio.cpp 571 endif 569 572 570 573 ifdef VBOX_WITH_PULSE … … 584 587 585 588 ifeq ($(KBUILD_TARGET),freebsd) 586 VBoxDD_SOURCES += \ 587 Audio/DrvHostOSSAudio.cpp 589 ifdef VBOX_WITH_OSS 590 VBoxDD_DEFS += VBOX_WITH_OSS 591 VBoxDD_SOURCES += \ 592 Audio/DrvHostOSSAudio.cpp 593 endif 588 594 ifdef VBOX_WITH_PULSE 589 595 VBoxDD_DEFS += VBOX_WITH_PULSE … … 595 601 596 602 ifeq ($(KBUILD_TARGET),solaris) 597 ifdef VBOX_WITH_ SOLARIS_OSS603 ifdef VBOX_WITH_OSS 598 604 VBoxDD_SOURCES += Audio/DrvHostOSSAudio.cpp 599 VBoxDD_DEFS += VBOX_WITH_ SOLARIS_OSS605 VBoxDD_DEFS += VBOX_WITH_OSS 600 606 endif 601 607 endif -
trunk/src/VBox/Devices/build/VBoxDD.cpp
r59248 r61320 289 289 return rc; 290 290 # endif 291 # ifdef VBOX_WITH_OSS 291 292 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostOSSAudio); 292 293 if (RT_FAILURE(rc)) 293 294 return rc; 295 # endif 294 296 #endif /* RT_OS_LINUX */ 295 297 #if defined(RT_OS_FREEBSD) 298 # ifdef VBOX_WITH_OSS 296 299 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostOSSAudio); 297 300 if (RT_FAILURE(rc)) 298 301 return rc; 302 # endif 299 303 #endif 300 304 #if defined(RT_OS_DARWIN) … … 304 308 #endif 305 309 #if defined(RT_OS_SOLARIS) 310 # ifdef VBOX_WITH_OSS 306 311 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostOSSAudio); 307 312 if (RT_FAILURE(rc)) 308 313 return rc; 314 # endif 309 315 #endif 310 316 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvACPI); -
trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
r61157 r61320 2889 2889 } 2890 2890 #endif 2891 #if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(VBOX_WITH_SOLARIS_OSS)2891 #ifdef VBOX_WITH_OSS 2892 2892 case AudioDriverType_OSS: 2893 2893 { -
trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp
r61167 r61320 424 424 425 425 return (PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED); 426 } 427 428 static DECLCALLBACK(int) drvAudioVRDEStreamIterate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAM pStream) 429 { 430 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 431 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 432 433 LogFlowFuncEnter(); 434 435 /* Nothing to do here for VRDE. */ 436 return VINF_SUCCESS; 426 437 } 427 438
Note:
See TracChangeset
for help on using the changeset viewer.