Changeset 88213 in vbox
- Timestamp:
- Mar 19, 2021 6:13:35 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r88181 r88213 3464 3464 } 3465 3465 3466 3467 /********************************************************************************************************************************* 3468 * PDMIBASE interface implementation. * 3469 *********************************************************************************************************************************/ 3470 3471 /** 3472 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 3473 */ 3474 static DECLCALLBACK(void *) drvAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID) 3475 { 3476 LogFlowFunc(("pInterface=%p, pszIID=%s\n", pInterface, pszIID)); 3477 3478 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 3479 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 3480 3481 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase); 3482 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIAUDIOCONNECTOR, &pThis->IAudioConnector); 3483 3484 return NULL; 3485 } 3486 3487 3488 /********************************************************************************************************************************* 3489 * PDMDRVREG interface implementation. * 3490 *********************************************************************************************************************************/ 3491 3492 /** 3493 * Power Off notification. 3494 * 3495 * @param pDrvIns The driver instance data. 3496 */ 3497 static DECLCALLBACK(void) drvAudioPowerOff(PPDMDRVINS pDrvIns) 3498 { 3499 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 3500 3501 LogFlowFuncEnter(); 3502 3503 if (!pThis->pHostDrvAudio) /* If not lower driver is configured, bail out. */ 3504 return; 3505 3506 /* Just destroy the host stream on the backend side. 3507 * The rest will either be destructed by the device emulation or 3508 * in drvAudioDestruct(). */ 3509 PPDMAUDIOSTREAM pStream; 3510 RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry) 3511 { 3512 drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); 3513 drvAudioStreamDestroyInternalBackend(pThis, pStream); 3514 } 3515 3516 /* 3517 * Last call for the driver below us. 3518 * Let it know that we reached end of life. 3519 */ 3520 if (pThis->pHostDrvAudio->pfnShutdown) 3521 pThis->pHostDrvAudio->pfnShutdown(pThis->pHostDrvAudio); 3522 3523 pThis->pHostDrvAudio = NULL; 3524 3525 LogFlowFuncLeave(); 3526 } 3527 3528 3529 /** 3530 * Detach notification. 3531 * 3532 * @param pDrvIns The driver instance data. 3533 * @param fFlags Detach flags. 3534 */ 3535 static DECLCALLBACK(void) drvAudioDetach(PPDMDRVINS pDrvIns, uint32_t fFlags) 3536 { 3537 RT_NOREF(fFlags); 3538 3539 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns); 3540 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 3541 3542 int rc2 = RTCritSectEnter(&pThis->CritSect); 3543 AssertRC(rc2); 3544 3545 pThis->pHostDrvAudio = NULL; 3546 3547 LogFunc(("%s\n", pThis->szName)); 3548 3549 rc2 = RTCritSectLeave(&pThis->CritSect); 3550 AssertRC(rc2); 3551 } 3552 3553 3466 3554 /** 3467 3555 * Does the actual backend driver attaching and queries the backend's interface. 3556 * 3557 * This is a worker for both drvAudioAttach and drvAudioConstruct. 3468 3558 * 3469 3559 * @return VBox status code. … … 3505 3595 3506 3596 3507 /********************************************************************/ 3508 3509 /** 3510 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 3511 */ 3512 static DECLCALLBACK(void *) drvAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID) 3513 { 3514 LogFlowFunc(("pInterface=%p, pszIID=%s\n", pInterface, pszIID)); 3515 3516 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 3517 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 3518 3519 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase); 3520 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIAUDIOCONNECTOR, &pThis->IAudioConnector); 3521 3522 return NULL; 3523 } 3524 3525 /** 3526 * Power Off notification. 3597 /** 3598 * Attach notification. 3527 3599 * 3528 3600 * @param pDrvIns The driver instance data. 3529 */ 3530 static DECLCALLBACK(void) drvAudioPowerOff(PPDMDRVINS pDrvIns) 3531 { 3601 * @param fFlags Attach flags. 3602 */ 3603 static DECLCALLBACK(int) drvAudioAttach(PPDMDRVINS pDrvIns, uint32_t fFlags) 3604 { 3605 RT_NOREF(fFlags); 3606 3607 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); 3532 3608 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 3533 3609 3610 int rc2 = RTCritSectEnter(&pThis->CritSect); 3611 AssertRC(rc2); 3612 3613 LogFunc(("%s\n", pThis->szName)); 3614 3615 int rc = drvAudioDoAttachInternal(pThis, fFlags); 3616 3617 rc2 = RTCritSectLeave(&pThis->CritSect); 3618 if (RT_SUCCESS(rc)) 3619 rc = rc2; 3620 3621 return rc; 3622 } 3623 3624 3625 /** 3626 * Resume notification. 3627 * 3628 * @param pDrvIns The driver instance data. 3629 */ 3630 static DECLCALLBACK(void) drvAudioResume(PPDMDRVINS pDrvIns) 3631 { 3632 drvAudioStateHandler(pDrvIns, PDMAUDIOSTREAMCMD_RESUME); 3633 } 3634 3635 3636 /** 3637 * Suspend notification. 3638 * 3639 * @param pDrvIns The driver instance data. 3640 */ 3641 static DECLCALLBACK(void) drvAudioSuspend(PPDMDRVINS pDrvIns) 3642 { 3643 drvAudioStateHandler(pDrvIns, PDMAUDIOSTREAMCMD_PAUSE); 3644 } 3645 3646 3647 /** 3648 * Destructs an audio driver instance. 3649 * 3650 * @copydoc FNPDMDRVDESTRUCT 3651 */ 3652 static DECLCALLBACK(void) drvAudioDestruct(PPDMDRVINS pDrvIns) 3653 { 3654 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns); 3655 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 3656 3534 3657 LogFlowFuncEnter(); 3535 3658 3536 if (!pThis->pHostDrvAudio) /* If not lower driver is configured, bail out. */ 3537 return; 3538 3539 /* Just destroy the host stream on the backend side. 3540 * The rest will either be destructed by the device emulation or 3541 * in drvAudioDestruct(). */ 3542 PPDMAUDIOSTREAM pStream; 3543 RTListForEach(&pThis->lstStreams, pStream, PDMAUDIOSTREAM, ListEntry) 3544 { 3545 drvAudioStreamControlInternalBackend(pThis, pStream, PDMAUDIOSTREAMCMD_DISABLE); 3546 drvAudioStreamDestroyInternalBackend(pThis, pStream); 3659 int rc2; 3660 3661 if (RTCritSectIsInitialized(&pThis->CritSect)) 3662 { 3663 rc2 = RTCritSectEnter(&pThis->CritSect); 3664 AssertRC(rc2); 3547 3665 } 3548 3666 3549 3667 /* 3550 * Last call for the driver below us. 3551 * Let it know that we reached end of life. 3668 * Note: No calls here to the driver below us anymore, 3669 * as PDM already has destroyed it. 3670 * If you need to call something from the host driver, 3671 * do this in drvAudioPowerOff() instead. 3552 3672 */ 3553 if (pThis->pHostDrvAudio->pfnShutdown) 3554 pThis->pHostDrvAudio->pfnShutdown(pThis->pHostDrvAudio);3555 3673 3674 /* Thus, NULL the pointer to the host audio driver first, 3675 * so that routines like drvAudioStreamDestroyInternal() don't call the driver(s) below us anymore. */ 3556 3676 pThis->pHostDrvAudio = NULL; 3557 3677 3678 PPDMAUDIOSTREAM pStream, pStreamNext; 3679 RTListForEachSafe(&pThis->lstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, ListEntry) 3680 { 3681 rc2 = drvAudioStreamUninitInternal(pThis, pStream); 3682 if (RT_SUCCESS(rc2)) 3683 { 3684 RTListNodeRemove(&pStream->ListEntry); 3685 3686 drvAudioStreamFree(pStream); 3687 pStream = NULL; 3688 } 3689 } 3690 3691 /* Sanity. */ 3692 Assert(RTListIsEmpty(&pThis->lstStreams)); 3693 3694 #ifdef VBOX_WITH_AUDIO_CALLBACKS 3695 /* 3696 * Destroy callbacks, if any. 3697 */ 3698 PPDMAUDIOCBRECORD pCB, pCBNext; 3699 RTListForEachSafe(&pThis->In.lstCB, pCB, pCBNext, PDMAUDIOCBRECORD, Node) 3700 drvAudioCallbackDestroy(pCB); 3701 3702 RTListForEachSafe(&pThis->Out.lstCB, pCB, pCBNext, PDMAUDIOCBRECORD, Node) 3703 drvAudioCallbackDestroy(pCB); 3704 #endif 3705 3706 if (pThis->pvScratchBuf) 3707 { 3708 Assert(pThis->cbScratchBuf); 3709 3710 RTMemFree(pThis->pvScratchBuf); 3711 pThis->pvScratchBuf = NULL; 3712 } 3713 3714 if (RTCritSectIsInitialized(&pThis->CritSect)) 3715 { 3716 rc2 = RTCritSectLeave(&pThis->CritSect); 3717 AssertRC(rc2); 3718 3719 rc2 = RTCritSectDelete(&pThis->CritSect); 3720 AssertRC(rc2); 3721 } 3722 3723 #ifdef VBOX_WITH_STATISTICS 3724 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalStreamsActive); 3725 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalStreamsCreated); 3726 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesRead); 3727 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesWritten); 3728 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesMixedIn); 3729 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesMixedOut); 3730 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesLostIn); 3731 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesLostOut); 3732 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesOut); 3733 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesIn); 3734 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalBytesRead); 3735 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalBytesWritten); 3736 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.DelayIn); 3737 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.DelayOut); 3738 #endif 3739 3558 3740 LogFlowFuncLeave(); 3559 3741 } 3560 3742 3743 3561 3744 /** 3562 3745 * Constructs an audio driver instance. … … 3566 3749 static DECLCALLBACK(int) drvAudioConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) 3567 3750 { 3751 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); 3752 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 3568 3753 LogFlowFunc(("pDrvIns=%#p, pCfgHandle=%#p, fFlags=%x\n", pDrvIns, pCfg, fFlags)); 3569 3754 3570 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);3571 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);3572 3755 /* 3756 * Basic instance init. 3757 */ 3573 3758 RTListInit(&pThis->lstStreams); 3574 3759 #ifdef VBOX_WITH_AUDIO_CALLBACKS … … 3577 3762 #endif 3578 3763 3579 /*3580 * Init the static parts.3581 */3582 3764 pThis->pDrvIns = pDrvIns; 3583 3765 /* IBase. */ … … 3642 3824 } 3643 3825 3826 /** @todo r=bird: you're overwriting rc here. sigh. Just return immediately on 3827 * failure, don't try make it to the end of the function! GRRR! */ 3644 3828 rc = drvAudioDoAttachInternal(pThis, fFlags); 3645 3829 if (RT_FAILURE(rc)) … … 3652 3836 LogFlowFuncLeaveRC(rc); 3653 3837 return rc; 3654 }3655 3656 /**3657 * Destructs an audio driver instance.3658 *3659 * @copydoc FNPDMDRVDESTRUCT3660 */3661 static DECLCALLBACK(void) drvAudioDestruct(PPDMDRVINS pDrvIns)3662 {3663 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);3664 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);3665 3666 LogFlowFuncEnter();3667 3668 int rc2;3669 3670 if (RTCritSectIsInitialized(&pThis->CritSect))3671 {3672 rc2 = RTCritSectEnter(&pThis->CritSect);3673 AssertRC(rc2);3674 }3675 3676 /*3677 * Note: No calls here to the driver below us anymore,3678 * as PDM already has destroyed it.3679 * If you need to call something from the host driver,3680 * do this in drvAudioPowerOff() instead.3681 */3682 3683 /* Thus, NULL the pointer to the host audio driver first,3684 * so that routines like drvAudioStreamDestroyInternal() don't call the driver(s) below us anymore. */3685 pThis->pHostDrvAudio = NULL;3686 3687 PPDMAUDIOSTREAM pStream, pStreamNext;3688 RTListForEachSafe(&pThis->lstStreams, pStream, pStreamNext, PDMAUDIOSTREAM, ListEntry)3689 {3690 rc2 = drvAudioStreamUninitInternal(pThis, pStream);3691 if (RT_SUCCESS(rc2))3692 {3693 RTListNodeRemove(&pStream->ListEntry);3694 3695 drvAudioStreamFree(pStream);3696 pStream = NULL;3697 }3698 }3699 3700 /* Sanity. */3701 Assert(RTListIsEmpty(&pThis->lstStreams));3702 3703 #ifdef VBOX_WITH_AUDIO_CALLBACKS3704 /*3705 * Destroy callbacks, if any.3706 */3707 PPDMAUDIOCBRECORD pCB, pCBNext;3708 RTListForEachSafe(&pThis->In.lstCB, pCB, pCBNext, PDMAUDIOCBRECORD, Node)3709 drvAudioCallbackDestroy(pCB);3710 3711 RTListForEachSafe(&pThis->Out.lstCB, pCB, pCBNext, PDMAUDIOCBRECORD, Node)3712 drvAudioCallbackDestroy(pCB);3713 #endif3714 3715 if (pThis->pvScratchBuf)3716 {3717 Assert(pThis->cbScratchBuf);3718 3719 RTMemFree(pThis->pvScratchBuf);3720 pThis->pvScratchBuf = NULL;3721 }3722 3723 if (RTCritSectIsInitialized(&pThis->CritSect))3724 {3725 rc2 = RTCritSectLeave(&pThis->CritSect);3726 AssertRC(rc2);3727 3728 rc2 = RTCritSectDelete(&pThis->CritSect);3729 AssertRC(rc2);3730 }3731 3732 #ifdef VBOX_WITH_STATISTICS3733 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalStreamsActive);3734 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalStreamsCreated);3735 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesRead);3736 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesWritten);3737 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesMixedIn);3738 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesMixedOut);3739 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesLostIn);3740 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesLostOut);3741 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesOut);3742 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalFramesIn);3743 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalBytesRead);3744 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.TotalBytesWritten);3745 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.DelayIn);3746 PDMDrvHlpSTAMDeregister(pThis->pDrvIns, &pThis->Stats.DelayOut);3747 #endif3748 3749 LogFlowFuncLeave();3750 }3751 3752 /**3753 * Suspend notification.3754 *3755 * @param pDrvIns The driver instance data.3756 */3757 static DECLCALLBACK(void) drvAudioSuspend(PPDMDRVINS pDrvIns)3758 {3759 drvAudioStateHandler(pDrvIns, PDMAUDIOSTREAMCMD_PAUSE);3760 }3761 3762 /**3763 * Resume notification.3764 *3765 * @param pDrvIns The driver instance data.3766 */3767 static DECLCALLBACK(void) drvAudioResume(PPDMDRVINS pDrvIns)3768 {3769 drvAudioStateHandler(pDrvIns, PDMAUDIOSTREAMCMD_RESUME);3770 }3771 3772 /**3773 * Attach notification.3774 *3775 * @param pDrvIns The driver instance data.3776 * @param fFlags Attach flags.3777 */3778 static DECLCALLBACK(int) drvAudioAttach(PPDMDRVINS pDrvIns, uint32_t fFlags)3779 {3780 RT_NOREF(fFlags);3781 3782 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);3783 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);3784 3785 int rc2 = RTCritSectEnter(&pThis->CritSect);3786 AssertRC(rc2);3787 3788 LogFunc(("%s\n", pThis->szName));3789 3790 int rc = drvAudioDoAttachInternal(pThis, fFlags);3791 3792 rc2 = RTCritSectLeave(&pThis->CritSect);3793 if (RT_SUCCESS(rc))3794 rc = rc2;3795 3796 return rc;3797 }3798 3799 /**3800 * Detach notification.3801 *3802 * @param pDrvIns The driver instance data.3803 * @param fFlags Detach flags.3804 */3805 static DECLCALLBACK(void) drvAudioDetach(PPDMDRVINS pDrvIns, uint32_t fFlags)3806 {3807 RT_NOREF(fFlags);3808 3809 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);3810 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);3811 3812 int rc2 = RTCritSectEnter(&pThis->CritSect);3813 AssertRC(rc2);3814 3815 pThis->pHostDrvAudio = NULL;3816 3817 LogFunc(("%s\n", pThis->szName));3818 3819 rc2 = RTCritSectLeave(&pThis->CritSect);3820 AssertRC(rc2);3821 3838 } 3822 3839
Note:
See TracChangeset
for help on using the changeset viewer.