VirtualBox

Ignore:
Timestamp:
Jan 14, 2016 2:48:08 PM (9 years ago)
Author:
vboxsync
Message:

Audio: Implemented dynamic fallback support to NULL audio backends for HDA, AC'97 and SB16 emulation; also did some preparations for audio hotplugging support.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DevIchHda.cpp

    r59343 r59348  
    658658    /** LUN to which this driver has been assigned. */
    659659    uint8_t                            uLUN;
    660     /** Audio connector interface to the underlying
    661      *  host backend. */
     660    /** Pointer to attached driver base interface. */
     661    R3PTRTYPE(PPDMIBASE)               pDrvBase;
     662    /** Audio connector interface to the underlying host backend. */
    662663    R3PTRTYPE(PPDMIAUDIOCONNECTOR)     pConnector;
    663664    /** Stream for line input. */
     
    684685    /** Padding for alignment. */
    685686    uint32_t                           u32Padding;
    686     /** Pointer to the attached audio driver. */
    687     R3PTRTYPE(PPDMIBASE)               pDrvBase;
    688687    /** The base interface for LUN\#0. */
    689688    PDMIBASE                           IBase;
     
    43234322    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
    43244323
    4325     AssertMsgReturn(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
    4326                     ("HDA device does not support hotplugging\n"),
    4327                     VERR_INVALID_PARAMETER);
    4328 
    43294324    /*
    43304325     * Attach driver.
     
    43324327    char *pszDesc = NULL;
    43334328    if (RTStrAPrintf(&pszDesc, "Audio driver port (HDA) for LUN#%u", uLUN) <= 0)
    4334         AssertMsgReturn(pszDesc,
    4335                         ("Not enough memory for HDA driver port description of LUN #%u\n", uLUN),
    4336                         VERR_NO_MEMORY);
    4337 
     4329        AssertReleaseMsgReturn(pszDesc,
     4330                               ("Not enough memory for HDA driver port description of LUN #%u\n", uLUN),
     4331                               VERR_NO_MEMORY);
     4332
     4333    PPDMIBASE pDrvBase;
    43384334    int rc = PDMDevHlpDriverAttach(pDevIns, uLUN,
    4339                                    &pThis->IBase, &pThis->pDrvBase, pszDesc);
     4335                                   &pThis->IBase, &pDrvBase, pszDesc);
    43404336    if (RT_SUCCESS(rc))
    43414337    {
     
    43434339        if (pDrv)
    43444340        {
    4345             pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIAUDIOCONNECTOR);
     4341            pDrv->pDrvBase   = pDrvBase;
     4342            pDrv->pConnector = PDMIBASE_QUERY_INTERFACE(pDrvBase, PDMIAUDIOCONNECTOR);
    43464343            AssertMsg(pDrv->pConnector != NULL, ("Configuration error: LUN#%u has no host audio interface, rc=%Rrc\n", uLUN, rc));
    43474344            pDrv->pHDAState  = pThis;
     
    43634360            rc = VERR_NO_MEMORY;
    43644361    }
    4365     else if (   rc == VERR_PDM_NO_ATTACHED_DRIVER
    4366              || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
     4362    else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
    43674363    {
    43684364        LogFunc(("No attached driver for LUN #%u\n", uLUN));
     
    43724368                        uLUN, pszDesc, rc));
    43734369
    4374     RTStrFree(pszDesc);
     4370    if (RT_FAILURE(rc))
     4371    {
     4372        /* Only free this string on failure;
     4373         * must remain valid for the live of the driver instance. */
     4374        RTStrFree(pszDesc);
     4375    }
    43754376
    43764377    LogFunc(("uLUN=%u, fFlags=0x%x, rc=%Rrc\n", uLUN, fFlags, rc));
     
    43784379}
    43794380
    4380 static DECLCALLBACK(void) hdaDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
    4381 {
    4382     NOREF(pDevIns); NOREF(iLUN); NOREF(fFlags);
    4383 
    4384     LogFlowFuncEnter();
     4381static DECLCALLBACK(void) hdaDetach(PPDMDEVINS pDevIns, unsigned uLUN, uint32_t fFlags)
     4382{
     4383    LogFunc(("iLUN=%u, fFlags=0x%x\n", uLUN, fFlags));
     4384}
     4385
     4386static int hdaReattach(PHDASTATE pThis, PCFGMNODE pCfg, PHDADRIVER pDrv, const char *pszDriver)
     4387{
     4388    AssertPtrReturn(pThis,     VERR_INVALID_POINTER);
     4389    AssertPtrReturn(pCfg,      VERR_INVALID_POINTER);
     4390    AssertPtrReturn(pDrv,      VERR_INVALID_POINTER);
     4391    AssertPtrReturn(pszDriver, VERR_INVALID_POINTER);
     4392
     4393    PVM pVM = PDMDevHlpGetVM(pThis->pDevInsR3);
     4394    PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
     4395    PCFGMNODE pDev0 = CFGMR3GetChild(pRoot, "Devices/hda/0/");
     4396
     4397    /* Remove LUN branch. */
     4398    CFGMR3RemoveNode(CFGMR3GetChildF(pDev0, "LUN#%u/", pDrv->uLUN));
     4399
     4400    int rc = PDMDevHlpDriverDetach(pThis->pDevInsR3, PDMIBASE_2_PDMDRV(pDrv->pDrvBase), 0 /* fFlags */);
     4401    if (RT_FAILURE(rc))
     4402        return rc;
     4403
     4404#define RC_CHECK() if (RT_FAILURE(rc)) { AssertReleaseRC(rc); break; }
     4405
     4406    do
     4407    {
     4408        PCFGMNODE pLunL0;
     4409        rc = CFGMR3InsertNodeF(pDev0, &pLunL0, "LUN#%u/", pDrv->uLUN);  RC_CHECK();
     4410        rc = CFGMR3InsertString(pLunL0, "Driver",       "AUDIO");       RC_CHECK();
     4411        rc = CFGMR3InsertNode(pLunL0,   "Config/",       NULL);         RC_CHECK();
     4412
     4413        PCFGMNODE pLunL1, pLunL2;
     4414        rc = CFGMR3InsertNode  (pLunL0, "AttachedDriver/", &pLunL1);    RC_CHECK();
     4415        rc = CFGMR3InsertNode  (pLunL1,  "Config/",        &pLunL2);    RC_CHECK();
     4416        rc = CFGMR3InsertString(pLunL1,  "Driver",          pszDriver); RC_CHECK();
     4417
     4418        rc = CFGMR3InsertString(pLunL2, "AudioDriver", pszDriver);      RC_CHECK();
     4419
     4420    } while (0);
     4421
     4422    if (RT_SUCCESS(rc))
     4423        rc = hdaAttach(pThis->pDevInsR3, pDrv->uLUN, 0 /* fFlags */);
     4424
     4425    LogFunc(("pThis=%p, uLUN=%u, pszDriver=%s, rc=%Rrc\n", pThis, pDrv->uLUN, pszDriver, rc));
     4426
     4427#undef RC_CHECK
     4428
     4429    return rc;
    43854430}
    43864431
     
    43884433 * @interface_method_impl{PDMDEVREG,pfnConstruct}
    43894434 */
    4390 static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
     4435static DECLCALLBACK(int) hdaConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
    43914436{
    43924437    PHDASTATE pThis = PDMINS_2_DATA(pDevIns, PHDASTATE);
     
    43974442     * Validations.
    43984443     */
    4399     if (!CFGMR3AreValuesValid(pCfgHandle, "R0Enabled\0"
    4400                                           "RCEnabled\0"
    4401                                           "TimerHz\0"))
     4444    if (!CFGMR3AreValuesValid(pCfg, "R0Enabled\0"
     4445                                    "RCEnabled\0"
     4446                                    "TimerHz\0"))
    44024447        return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
    44034448                                N_ ("Invalid configuration for the Intel HDA device"));
    44044449
    4405     int rc = CFGMR3QueryBoolDef(pCfgHandle, "RCEnabled", &pThis->fRCEnabled, false);
     4450    int rc = CFGMR3QueryBoolDef(pCfg, "RCEnabled", &pThis->fRCEnabled, false);
    44064451    if (RT_FAILURE(rc))
    44074452        return PDMDEV_SET_ERROR(pDevIns, rc,
    44084453                                N_("HDA configuration error: failed to read RCEnabled as boolean"));
    4409     rc = CFGMR3QueryBoolDef(pCfgHandle, "R0Enabled", &pThis->fR0Enabled, false);
     4454    rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &pThis->fR0Enabled, false);
    44104455    if (RT_FAILURE(rc))
    44114456        return PDMDEV_SET_ERROR(pDevIns, rc,
     
    44134458#ifndef VBOX_WITH_AUDIO_CALLBACKS
    44144459    uint16_t uTimerHz;
    4415     rc = CFGMR3QueryU16Def(pCfgHandle, "TimerHz", &uTimerHz, 200 /* Hz */);
     4460    rc = CFGMR3QueryU16Def(pCfg, "TimerHz", &uTimerHz, 200 /* Hz */);
    44164461    if (RT_FAILURE(rc))
    44174462        return PDMDEV_SET_ERROR(pDevIns, rc,
     
    45404585    {
    45414586        LogFunc(("Trying to attach driver for LUN #%RU32 ...\n", uLUN));
    4542         rc = hdaAttach(pDevIns, uLUN, PDM_TACH_FLAGS_NOT_HOT_PLUG);
     4587        rc = hdaAttach(pDevIns, uLUN, 0 /* fFlags */);
    45434588        if (RT_FAILURE(rc))
    45444589        {
     
    46074652
    46084653        /* Construct the codec. */
    4609         rc = hdaCodecConstruct(pDevIns, pThis->pCodec, 0 /* Codec index */, pCfgHandle);
     4654        rc = hdaCodecConstruct(pDevIns, pThis->pCodec, 0 /* Codec index */, pCfg);
    46104655        if (RT_FAILURE(rc))
    46114656            AssertRCReturn(rc, rc);
     
    46294674        rc = hdaStreamCreate(&pThis->StrmStOut);
    46304675        AssertRC(rc);
     4676
     4677        PHDADRIVER pDrv;
     4678        RTListForEach(&pThis->lstDrv, pDrv, HDADRIVER, Node)
     4679        {
     4680            /*
     4681             * Only primary drivers are critical for the VM to run. Everything else
     4682             * might not worth showing an own error message box in the GUI.
     4683             */
     4684            if (!(pDrv->Flags & PDMAUDIODRVFLAG_PRIMARY))
     4685                continue;
     4686
     4687            PPDMIAUDIOCONNECTOR pCon = pDrv->pConnector;
     4688            AssertPtr(pCon);
     4689
     4690            uint8_t cFailed = 0;
     4691            if (!pCon->pfnIsValidIn (pCon, pDrv->LineIn.pStrmIn))
     4692                cFailed++;
     4693#ifdef VBOX_WITH_HDA_MIC_IN
     4694            if (!pCon->pfnIsValidIn (pCon, pDrv->MicIn.pStrmIn))
     4695                cFailed++;
     4696#endif
     4697            if (!pCon->pfnIsValidOut(pCon, pDrv->Out.pStrmOut))
     4698                cFailed++;
     4699
     4700#ifdef VBOX_WITH_HDA_MIC_IN
     4701            if (cFailed == 3)
     4702#else
     4703            if (cFailed == 2)
     4704#endif
     4705            {
     4706                LogRel(("HDA: Falling back to NULL backend (no sound audible)\n"));
     4707
     4708                hdaReset(pDevIns);
     4709                hdaReattach(pThis, pCfg, pDrv, "NullAudio");
     4710
     4711                PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
     4712                    N_("No audio devices could be opened. Selecting the NULL audio backend "
     4713                       "with the consequence that no sound is audible"));
     4714            }
     4715            else if (cFailed)
     4716            {
     4717                if (!pDrv->pConnector->pfnIsValidIn (pDrv->pConnector, pDrv->LineIn.pStrmIn))
     4718                    LogRel(("HDA: WARNING: Unable to open PCM line input for LUN #%RU32!\n",       pDrv->uLUN));
     4719#ifdef VBOX_WITH_HDA_MIC_IN
     4720                if (!pDrv->pConnector->pfnIsValidIn (pDrv->pConnector, pDrv->MicIn.pStrmIn))
     4721                    LogRel(("HDA: WARNING: Unable to open PCM microphone input for LUN #%RU32!\n", pDrv->uLUN));
     4722#endif
     4723                if (!pDrv->pConnector->pfnIsValidOut(pDrv->pConnector, pDrv->Out.pStrmOut))
     4724                    LogRel(("HDA: WARNING: Unable to open PCM output for LUN #%RU32!\n",           pDrv->uLUN));
     4725
     4726                char   szMissingStreams[255];
     4727                size_t len = 0;
     4728                if (!pCon->pfnIsValidIn (pCon, pDrv->LineIn.pStrmIn))
     4729                    len = RTStrPrintf(szMissingStreams,
     4730                                      sizeof(szMissingStreams), "PCM Input");
     4731#ifdef VBOX_WITH_HDA_MIC_IN
     4732                if (!pCon->pfnIsValidIn (pCon, pDrv->MicIn.pStrmIn))
     4733                    len += RTStrPrintf(szMissingStreams + len,
     4734                                       sizeof(szMissingStreams) - len, len ? ", PCM Microphone" : "PCM Microphone");
     4735#endif
     4736                if (!pCon->pfnIsValidOut(pCon, pDrv->Out.pStrmOut))
     4737                    len += RTStrPrintf(szMissingStreams + len,
     4738                                       sizeof(szMissingStreams) - len, len ? ", PCM Output" : "PCM Output");
     4739
     4740                PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "HostAudioNotResponding",
     4741                    N_("Some HDA audio streams (%s) could not be opened. Guest applications generating audio "
     4742                    "output or depending on audio input may hang. Make sure your host audio device "
     4743                    "is working properly. Check the logfile for error messages of the audio "
     4744                    "subsystem"), szMissingStreams);
     4745            }
     4746        }
    46314747    }
    46324748
     
    48194935    NULL,
    48204936    /* pfnAttach */
    4821     NULL,
     4937    hdaAttach,
    48224938    /* pfnDetach */
    4823     NULL,
     4939    hdaDetach,
    48244940    /* pfnQueryInterface. */
    48254941    NULL,
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette