Changeset 88909 in vbox
- Timestamp:
- May 6, 2021 4:37:24 PM (4 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r88907 r88909 105 105 static int audioMixerSinkSetRecSourceInternal(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream); 106 106 107 static int audioMixerStreamCtlInternal(PAUDMIXSTREAM pMixStream, PDMAUDIOSTREAMCMD enmCmd , uint32_t fCtl);107 static int audioMixerStreamCtlInternal(PAUDMIXSTREAM pMixStream, PDMAUDIOSTREAMCMD enmCmd); 108 108 static void audioMixerStreamDestroyInternal(PAUDMIXSTREAM pStream, PPDMDEVINS pDevIns); 109 109 static int audioMixerStreamUpdateStatus(PAUDMIXSTREAM pMixStream); … … 484 484 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 485 485 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 486 AssertPtrReturn(pStream->pConn, VERR_AUDIO_STREAM_NOT_READY); 487 AssertReturn(pStream->pSink == NULL, VERR_ALREADY_EXISTS); 486 488 487 489 int rc = RTCritSectEnter(&pSink->CritSect); 488 490 AssertRCReturn(rc, rc); 491 489 492 AssertLogRelMsgReturnStmt(pSink->cStreams < UINT8_MAX, ("too many streams!\n"), RTCritSectLeave(&pSink->CritSect), 490 493 VERR_TOO_MANY_OPEN_FILES); 491 494 492 493 /** @todo Check if stream already is assigned to (another) sink. */ 494 495 /* If the sink is running and not in pending disable mode, 496 * make sure that the added stream also is enabled. */ 495 /* 496 * If the sink is running and not in pending disable mode, make sure that 497 * the added stream also is enabled. Ignore any failure to enable it. 498 */ 497 499 if ( (pSink->fStatus & AUDMIXSINK_STS_RUNNING) 498 500 && !(pSink->fStatus & AUDMIXSINK_STS_PENDING_DISABLE)) 499 501 { 500 rc = audioMixerStreamCtlInternal(pStream, PDMAUDIOSTREAMCMD_ENABLE, AUDMIXSTRMCTL_F_NONE); 501 if (rc == VERR_AUDIO_STREAM_NOT_READY) 502 rc = VINF_SUCCESS; /* Not fatal here, stream can become available at some later point in time. */ 503 } 504 505 if (RT_SUCCESS(rc) && pSink->enmDir != AUDMIXSINKDIR_OUTPUT) 502 audioMixerStreamCtlInternal(pStream, PDMAUDIOSTREAMCMD_ENABLE); 503 } 504 505 if (pSink->enmDir != AUDMIXSINKDIR_OUTPUT) 506 506 { 507 507 /* Apply the sink's combined volume to the stream. */ 508 rc = pStream->pConn->pfnStreamSetVolume(pStream->pConn, pStream->pStream, &pSink->VolumeCombined); 509 AssertRC(rc); 510 } 511 512 if (RT_SUCCESS(rc)) 513 { 514 /* Save pointer to sink the stream is attached to. */ 515 pStream->pSink = pSink; 516 517 /* Append stream to sink's list. */ 518 RTListAppend(&pSink->lstStreams, &pStream->Node); 519 pSink->cStreams++; 520 } 508 int rc2 = pStream->pConn->pfnStreamSetVolume(pStream->pConn, pStream->pStream, &pSink->VolumeCombined); 509 AssertRC(rc2); 510 } 511 512 /* Save pointer to sink the stream is attached to. */ 513 pStream->pSink = pSink; 514 515 /* Append stream to sink's list. */ 516 RTListAppend(&pSink->lstStreams, &pStream->Node); 517 pSink->cStreams++; 521 518 522 519 LogFlowFunc(("[%s] cStreams=%RU8, rc=%Rrc\n", pSink->pszName, pSink->cStreams, rc)); 523 524 int rc2 = RTCritSectLeave(&pSink->CritSect); 525 AssertRC(rc2); 526 520 RTCritSectLeave(&pSink->CritSect); 527 521 return rc; 528 522 } … … 671 665 672 666 /** 673 * Static helper function to translate a sink command674 * to a PDM audio stream command.675 *676 * @returns PDM audio stream command, or PDMAUDIOSTREAMCMD_UNKNOWN if not found.677 * @param enmCmd Mixer sink command to translate.678 */679 static PDMAUDIOSTREAMCMD audioMixerSinkToStreamCmd(AUDMIXSINKCMD enmCmd)680 {681 switch (enmCmd)682 {683 case AUDMIXSINKCMD_ENABLE: return PDMAUDIOSTREAMCMD_ENABLE;684 case AUDMIXSINKCMD_DISABLE: return PDMAUDIOSTREAMCMD_DISABLE;685 case AUDMIXSINKCMD_PAUSE: return PDMAUDIOSTREAMCMD_PAUSE;686 case AUDMIXSINKCMD_RESUME: return PDMAUDIOSTREAMCMD_RESUME;687 default: break;688 }689 690 AssertMsgFailed(("Unsupported sink command %d\n", enmCmd));691 return PDMAUDIOSTREAMCMD_INVALID;692 }693 694 /**695 667 * Controls a mixer sink. 696 668 * 697 669 * @returns VBox status code. 670 * Generally always VINF_SUCCESS unless the input is invalid. 671 * Individual driver errors are suppressed and ignored. 698 672 * @param pSink Mixer sink to control. 699 673 * @param enmSinkCmd Sink command to set. … … 703 677 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 704 678 705 PDMAUDIOSTREAMCMD enmCmdStream = audioMixerSinkToStreamCmd(enmSinkCmd); 706 if (enmCmdStream == PDMAUDIOSTREAMCMD_INVALID) 707 return VERR_NOT_SUPPORTED; 679 /* Only ENABLE/DISABLE is implemented. */ 680 AssertMsgReturn( enmSinkCmd == AUDMIXSINKCMD_ENABLE 681 || enmSinkCmd == AUDMIXSINKCMD_DISABLE, 682 ("enmSinkCmd=%d\n", enmSinkCmd), 683 VERR_INVALID_FUNCTION); 684 PDMAUDIOSTREAMCMD const enmCmdStream = enmSinkCmd == AUDMIXSINKCMD_ENABLE 685 ? PDMAUDIOSTREAMCMD_ENABLE : PDMAUDIOSTREAMCMD_DISABLE; 708 686 709 687 int rc = RTCritSectEnter(&pSink->CritSect); 710 if (RT_FAILURE(rc)) 711 return rc; 712 713 /* Input sink and no recording source set? Bail out early. */ 688 AssertRCReturn(rc, rc); 689 690 /* 691 * Input sink and no recording source set? Return early without updating the stream status... 692 */ 714 693 if ( pSink->enmDir == AUDMIXSINKDIR_INPUT 715 694 && pSink->In.pStreamRecSource == NULL) 716 695 { 717 int rc2 = RTCritSectLeave(&pSink->CritSect); 718 AssertRC(rc2); 719 720 return rc; 721 } 722 723 /** @todo r=bird: There almost serious issue here. One stupid/buggy audio 724 * driver chain will mess up the whole thing. Either we or DrvAudio 725 * need to take note of this and somehow gloss over it... DevHDA with a 726 * linux guest completely freezes up the audio in the guest if we fail 727 * here. (Buggy VRDE code, see r144223.) */ 728 PAUDMIXSTREAM pStream; 729 if ( pSink->enmDir == AUDMIXSINKDIR_INPUT 730 && pSink->In.pStreamRecSource) /* Any recording source set? */ 731 { 732 RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node) 733 { 734 if (pStream == pSink->In.pStreamRecSource) 696 /** @todo r=bird: will the cause trouble for the stream status management? */ 697 } 698 else 699 { 700 /* 701 * Send the command to the streams. 702 */ 703 if (pSink->enmDir == AUDMIXSINKDIR_INPUT) 704 { 705 /** @todo r=bird: we already check this. duh. */ 706 if (pSink->In.pStreamRecSource) /* Any recording source set? */ 735 707 { 736 int rc2 = audioMixerStreamCtlInternal(pStream, enmCmdStream, AUDMIXSTRMCTL_F_NONE); 737 if (rc2 == VERR_NOT_SUPPORTED) 738 rc2 = VINF_SUCCESS; 739 740 if (RT_SUCCESS(rc)) 741 rc = rc2; 742 /* Keep going. Flag? */ 708 PAUDMIXSTREAM pStream; 709 RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node) 710 { 711 if (pStream == pSink->In.pStreamRecSource) 712 { 713 audioMixerStreamCtlInternal(pStream, enmCmdStream); 714 break; 715 } 716 } 743 717 } 744 718 } 745 } 746 else if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT) 747 { 748 RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node) 749 { 750 int rc2 = audioMixerStreamCtlInternal(pStream, enmCmdStream, AUDMIXSTRMCTL_F_NONE); 751 if (rc2 == VERR_NOT_SUPPORTED) 752 rc2 = VINF_SUCCESS; 753 754 if (RT_SUCCESS(rc)) 755 rc = rc2; 756 /* Keep going. Flag? */ 757 } 758 } 759 760 switch (enmSinkCmd) 761 { 762 case AUDMIXSINKCMD_ENABLE: 763 { 764 /* Make sure to clear any other former flags again by assigning AUDMIXSINK_STS_RUNNING directly. */ 765 pSink->fStatus = AUDMIXSINK_STS_RUNNING; 766 break; 767 } 768 769 case AUDMIXSINKCMD_DISABLE: 770 { 771 if (pSink->fStatus & AUDMIXSINK_STS_RUNNING) 719 else if (pSink->enmDir == AUDMIXSINKDIR_OUTPUT) 720 { 721 PAUDMIXSTREAM pStream; 722 RTListForEach(&pSink->lstStreams, pStream, AUDMIXSTREAM, Node) 772 723 { 773 /* Set the sink in a pending disable state first. 774 * The final status (disabled) will be set in the sink's iteration. */ 775 pSink->fStatus |= AUDMIXSINK_STS_PENDING_DISABLE; 724 audioMixerStreamCtlInternal(pStream, enmCmdStream); 776 725 } 777 break; 778 } 779 780 default: 781 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED); 782 break; 783 } 784 785 #if defined(RTLOG_REL_ENABLED) || defined(LOG_ENABLED) 726 } 727 728 /* 729 * Update the sink status. 730 */ 731 switch (enmSinkCmd) 732 { 733 case AUDMIXSINKCMD_ENABLE: 734 /* Make sure to clear any other former flags again by assigning AUDMIXSINK_STS_RUNNING directly. */ 735 pSink->fStatus = AUDMIXSINK_STS_RUNNING; 736 break; 737 738 case AUDMIXSINKCMD_DISABLE: 739 if (pSink->fStatus & AUDMIXSINK_STS_RUNNING) 740 { 741 /* Set the sink in a pending disable state first. 742 * The final status (disabled) will be set in the sink's iteration. */ 743 pSink->fStatus |= AUDMIXSINK_STS_PENDING_DISABLE; 744 } 745 break; 746 747 default: 748 AssertFailed(/*impossible!*/); 749 } 750 } 751 786 752 char szStatus[AUDIOMIXERSINK_STATUS_STR_MAX]; 787 #endif 788 LogRel2(("Audio Mixer: Set new status of sink '%s': %s (enmCmd=%RU32 rc=%Rrc)\n", 789 pSink->pszName, dbgAudioMixerSinkStatusToStr(pSink->fStatus, szStatus), enmSinkCmd, rc)); 790 791 int rc2 = RTCritSectLeave(&pSink->CritSect); 792 AssertRC(rc2); 793 794 return rc; 753 LogRel2(("Audio Mixer: Set new status of sink '%s': %s (enmCmd=%RU32)\n", 754 pSink->pszName, dbgAudioMixerSinkStatusToStr(pSink->fStatus, szStatus), enmSinkCmd)); 755 756 RTCritSectLeave(&pSink->CritSect); 757 return VINF_SUCCESS; 795 758 } 796 759 … … 1963 1926 * Controls a mixer stream, internal version. 1964 1927 * 1965 * @returns VBox status code .1928 * @returns VBox status code (generally ignored). 1966 1929 * @param pMixStream Mixer stream to control. 1967 1930 * @param enmCmd Mixer stream command to use. 1968 * @param fCtl Additional control flags. Pass 0. 1969 */ 1970 static int audioMixerStreamCtlInternal(PAUDMIXSTREAM pMixStream, PDMAUDIOSTREAMCMD enmCmd, uint32_t fCtl) 1971 { 1972 AssertPtr(pMixStream->pConn); 1973 AssertPtr(pMixStream->pStream); 1974 1975 RT_NOREF(fCtl); 1931 */ 1932 static int audioMixerStreamCtlInternal(PAUDMIXSTREAM pMixStream, PDMAUDIOSTREAMCMD enmCmd) 1933 { 1934 AssertPtrReturn(pMixStream->pConn, VERR_AUDIO_STREAM_NOT_READY); 1935 AssertPtrReturn(pMixStream->pStream, VERR_AUDIO_STREAM_NOT_READY); 1976 1936 1977 1937 int rc = pMixStream->pConn->pfnStreamControl(pMixStream->pConn, pMixStream->pStream, enmCmd); 1978 1938 1979 LogFlowFunc(("[%s] enmCmd=% ld, rc=%Rrc\n", pMixStream->pszName, enmCmd, rc));1939 LogFlowFunc(("[%s] enmCmd=%d, rc=%Rrc\n", pMixStream->pszName, enmCmd, rc)); 1980 1940 1981 1941 return rc; -
trunk/src/VBox/Devices/Audio/AudioMixer.h
r88907 r88909 255 255 } AUDMIXOP; 256 256 257 /** No flags specified. */258 #define AUDMIXSTRMCTL_F_NONE 0259 260 257 /** No mixer flags specified. */ 261 258 #define AUDMIXER_FLAGS_NONE 0 … … 273 270 void AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs); 274 271 275 int AudioMixerSinkAddStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);272 int AudioMixerSinkAddStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream); 276 273 int AudioMixerSinkCreateStream(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOSTREAMCFG pCfg, 277 274 AUDMIXSTREAMFLAGS fFlags, PPDMDEVINS pDevIns, PAUDMIXSTREAM *ppStream);
Note:
See TracChangeset
for help on using the changeset viewer.