VirtualBox

Changeset 88897 in vbox for trunk


Ignore:
Timestamp:
May 6, 2021 12:15:56 PM (4 years ago)
Author:
vboxsync
Message:

DrvAudio: Process backend state changes in drvAudioStreamGetState too (not just drvAudioStreamPlay). bugref:9890

File:
1 edited

Legend:

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

    r88896 r88897  
    175175    uint32_t                cTriesReInit;
    176176
    177     /** The backend state at the last play or capture call.
     177    /** The last backend state we saw.
    178178     * This is used to detect state changes (for what that is worth).  */
    179179    PDMHOSTAUDIOSTREAMSTATE enmLastBackendState;
     
    401401static uint32_t drvAudioStreamRetainInternal(PDRVAUDIOSTREAM pStreamEx);
    402402static uint32_t drvAudioStreamReleaseInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, bool fMayDestroy);
     403static void drvAudioStreamResetInternal(PDRVAUDIOSTREAM pStreamEx);
    403404static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
    404405
     
    547548        PDMHOSTAUDIOSTREAMSTATE enmState = pThis->pHostDrvAudio->pfnStreamGetState(pThis->pHostDrvAudio, pStreamEx->pBackend);
    548549        Assert(enmState > PDMHOSTAUDIOSTREAMSTATE_INVALID && enmState < PDMHOSTAUDIOSTREAMSTATE_END);
     550        Log9Func(("%s: %s\n", pStreamEx->Core.szName, PDMHostAudioStreamStateGetName(enmState) ));
    549551        return enmState;
    550552    }
     553    Log9Func(("%s: not-working\n", pStreamEx->Core.szName));
    551554    return PDMHOSTAUDIOSTREAMSTATE_NOT_WORKING;
     555}
     556
     557
     558/**
     559 * Processes backend state change.
     560 *
     561 * @returns the new state value.
     562 */
     563static PDMHOSTAUDIOSTREAMSTATE drvAudioStreamProcessBackendStateChange(PDRVAUDIOSTREAM pStreamEx,
     564                                                                       PDMHOSTAUDIOSTREAMSTATE enmNewState,
     565                                                                       PDMHOSTAUDIOSTREAMSTATE enmOldState)
     566{
     567    PDMAUDIODIR const       enmDir       = pStreamEx->Guest.Cfg.enmDir;
     568#ifdef LOG_ENABLED
     569    DRVAUDIOPLAYSTATE const enmPlayState = enmDir == PDMAUDIODIR_OUT ? pStreamEx->Out.enmPlayState : DRVAUDIOPLAYSTATE_INVALID;
     570#endif
     571    Assert(enmNewState != enmOldState);
     572    Assert(enmOldState > PDMHOSTAUDIOSTREAMSTATE_INVALID && enmOldState < PDMHOSTAUDIOSTREAMSTATE_END);
     573    AssertReturn(enmNewState > PDMHOSTAUDIOSTREAMSTATE_INVALID && enmNewState < PDMHOSTAUDIOSTREAMSTATE_END, enmOldState);
     574
     575    /*
     576     * Figure out what happend and how that reflects on the playback state and stuff.
     577     */
     578    switch (enmNewState)
     579    {
     580        case PDMHOSTAUDIOSTREAMSTATE_INITIALIZING:
     581            /* Guess we're switching device. Nothing to do because the backend will tell us, right? */
     582            break;
     583
     584        case PDMHOSTAUDIOSTREAMSTATE_NOT_WORKING:
     585            /* The stream has stopped working.  Switch to noplay mode. */
     586            if (enmDir == PDMAUDIODIR_OUT)
     587                pStreamEx->Out.enmPlayState = DRVAUDIOPLAYSTATE_NOPLAY;
     588            break;
     589
     590        case PDMHOSTAUDIOSTREAMSTATE_OKAY:
     591            switch (enmOldState)
     592            {
     593                case PDMHOSTAUDIOSTREAMSTATE_INITIALIZING:
     594                    /* Should be taken care of elsewhere, so do nothing. */
     595                    break;
     596
     597                case PDMHOSTAUDIOSTREAMSTATE_NOT_WORKING:
     598                case PDMHOSTAUDIOSTREAMSTATE_INACTIVE:
     599                    /* Go back to pre-buffering/playing depending on whether it is enabled
     600                       or not, resetting the stream state. */
     601                    drvAudioStreamResetInternal(pStreamEx);
     602                    break;
     603
     604                /* no default: */
     605                case PDMHOSTAUDIOSTREAMSTATE_OKAY: /* impossible */
     606                case PDMHOSTAUDIOSTREAMSTATE_INVALID:
     607                case PDMHOSTAUDIOSTREAMSTATE_END:
     608                case PDMHOSTAUDIOSTREAMSTATE_32BIT_HACK:
     609                    break;
     610            }
     611            break;
     612
     613        case PDMHOSTAUDIOSTREAMSTATE_INACTIVE:
     614            /* Stream is now inactive. Switch to noplay mode. */
     615            if (enmDir == PDMAUDIODIR_OUT)
     616                pStreamEx->Out.enmPlayState = DRVAUDIOPLAYSTATE_NOPLAY;
     617            break;
     618
     619        /* no default: */
     620        case PDMHOSTAUDIOSTREAMSTATE_INVALID:
     621        case PDMHOSTAUDIOSTREAMSTATE_END:
     622        case PDMHOSTAUDIOSTREAMSTATE_32BIT_HACK:
     623            break;
     624    }
     625
     626    if (enmDir == PDMAUDIODIR_OUT)
     627        LogFunc(("Output stream '%s': %s/%s -> %s/%s\n", pStreamEx->Core.szName,
     628                 PDMHostAudioStreamStateGetName(enmOldState), drvAudioPlayStateName(enmPlayState),
     629                 PDMHostAudioStreamStateGetName(enmNewState), drvAudioPlayStateName(pStreamEx->Out.enmPlayState) ));
     630    else
     631        LogFunc(("Input stream '%s': %s -> %s\n", pStreamEx->Core.szName,
     632                 PDMHostAudioStreamStateGetName(enmOldState), PDMHostAudioStreamStateGetName(enmNewState) ));
     633
     634    pStreamEx->enmLastBackendState = enmNewState;
     635    return enmNewState;
     636}
     637
     638
     639/**
     640 * This gets the backend state and handles changes compared to
     641 * DRVAUDIOSTREAM::enmLastBackendState (updated).
     642 *
     643 * @returns A PDMHOSTAUDIOSTREAMSTATE value.
     644 * @param   pThis       Pointer to the DrvAudio instance data.
     645 * @param   pStreamEx   The stream to get the backend status for.
     646 */
     647DECLINLINE(PDMHOSTAUDIOSTREAMSTATE) drvAudioStreamGetBackendStateAndProcessChanges(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
     648{
     649    PDMHOSTAUDIOSTREAMSTATE const enmBackendState = drvAudioStreamGetBackendState(pThis, pStreamEx);
     650    if (pStreamEx->enmLastBackendState == enmBackendState)
     651        return enmBackendState;
     652    return drvAudioStreamProcessBackendStateChange(pStreamEx, enmBackendState, pStreamEx->enmLastBackendState);
    552653}
    553654
     
    32343335    AssertRCReturn(rc, PDMAUDIOSTREAMSTATE_INVALID);
    32353336
    3236     PDMHOSTAUDIOSTREAMSTATE const enmBackendState = drvAudioStreamGetBackendState(pThis, pStreamEx);
     3337    PDMHOSTAUDIOSTREAMSTATE const enmBackendState = drvAudioStreamGetBackendStateAndProcessChanges(pThis, pStreamEx);
    32373338    uint32_t const                fStrmStatus     = pStreamEx->fStatus;
    32383339    PDMAUDIODIR const             enmDir          = pStreamEx->Guest.Cfg.enmDir;
     
    32913392
    32923393    return VINF_SUCCESS;
    3293 }
    3294 
    3295 
    3296 /**
    3297  * Processes backend state change.
    3298  */
    3299 static void drvAudioStreamPlayProcessBackendStateChange(PDRVAUDIOSTREAM pStreamEx, PDMHOSTAUDIOSTREAMSTATE enmNewState,
    3300                                                         PDMHOSTAUDIOSTREAMSTATE enmOldState)
    3301 {
    3302 #ifdef LOG_ENABLED
    3303     DRVAUDIOPLAYSTATE const enmPlayState = pStreamEx->Out.enmPlayState;
    3304 #endif
    3305     Assert(enmNewState != enmOldState);
    3306     Assert(enmOldState > PDMHOSTAUDIOSTREAMSTATE_INVALID && enmOldState < PDMHOSTAUDIOSTREAMSTATE_END);
    3307     AssertReturnVoid(enmNewState > PDMHOSTAUDIOSTREAMSTATE_INVALID && enmNewState < PDMHOSTAUDIOSTREAMSTATE_END);
    3308 
    3309     /*
    3310      * Figure out what happend and how that reflects on the playback state and stuff.
    3311      */
    3312     switch (enmNewState)
    3313     {
    3314         case PDMHOSTAUDIOSTREAMSTATE_INITIALIZING:
    3315             /* Guess we're switching device. Nothing to do because the backend will tell us, right? */
    3316             break;
    3317 
    3318         case PDMHOSTAUDIOSTREAMSTATE_NOT_WORKING:
    3319             /* The stream has stopped working.  Switch to noplay mode. */
    3320             pStreamEx->Out.enmPlayState = DRVAUDIOPLAYSTATE_NOPLAY;
    3321             break;
    3322 
    3323         case PDMHOSTAUDIOSTREAMSTATE_OKAY:
    3324             switch (enmOldState)
    3325             {
    3326                 case PDMHOSTAUDIOSTREAMSTATE_INITIALIZING:
    3327                     /* Should be taken care of elsewhere, so do nothing. */
    3328                     break;
    3329 
    3330                 case PDMHOSTAUDIOSTREAMSTATE_NOT_WORKING:
    3331                 case PDMHOSTAUDIOSTREAMSTATE_INACTIVE:
    3332                     /* Go back to pre-buffering/playing depending on whether it is enabled
    3333                        or not, resetting the stream state. */
    3334                     drvAudioStreamResetInternal(pStreamEx);
    3335                     break;
    3336 
    3337                 /* no default: */
    3338                 case PDMHOSTAUDIOSTREAMSTATE_OKAY: /* impossible */
    3339                 case PDMHOSTAUDIOSTREAMSTATE_INVALID:
    3340                 case PDMHOSTAUDIOSTREAMSTATE_END:
    3341                 case PDMHOSTAUDIOSTREAMSTATE_32BIT_HACK:
    3342                     break;
    3343             }
    3344             break;
    3345 
    3346         case PDMHOSTAUDIOSTREAMSTATE_INACTIVE:
    3347             /* Stream is now inactive. Switch to noplay mode. */
    3348             pStreamEx->Out.enmPlayState = DRVAUDIOPLAYSTATE_NOPLAY;
    3349             break;
    3350 
    3351         /* no default: */
    3352         case PDMHOSTAUDIOSTREAMSTATE_INVALID:
    3353         case PDMHOSTAUDIOSTREAMSTATE_END:
    3354         case PDMHOSTAUDIOSTREAMSTATE_32BIT_HACK:
    3355             break;
    3356     }
    3357 
    3358     LogFunc(("Stream '%s': %s/%s -> %s/%s\n", pStreamEx->Guest.Cfg.szName,
    3359              PDMHostAudioStreamStateGetName(enmOldState), drvAudioPlayStateName(enmPlayState),
    3360              PDMHostAudioStreamStateGetName(enmNewState), drvAudioPlayStateName(pStreamEx->Out.enmPlayState) ));
    33613394}
    33623395
     
    34073440        {
    34083441            /*
    3409              * Get the backend state and check if it changed.
     3442             * Get the backend state and process changes to it since last time we checked.
    34103443             */
    3411 /** @todo This is the wrong place for doing this, or we need to do it in more places.  Problem is that if we've
    3412  * entered NOPLAY mode this function won't get called because StreamGetWritable returns zero. A bit difficult to
    3413  * reproduce, though. */
    3414             PDMHOSTAUDIOSTREAMSTATE const enmBackendState = drvAudioStreamGetBackendState(pThis, pStreamEx);
    3415             if (enmBackendState == pStreamEx->enmLastBackendState)
    3416             { /* no relevant change - likely */ }
    3417             else
    3418             {
    3419                 drvAudioStreamPlayProcessBackendStateChange(pStreamEx, enmBackendState, pStreamEx->enmLastBackendState);
    3420                 pStreamEx->enmLastBackendState = enmBackendState;
    3421             }
     3444            PDMHOSTAUDIOSTREAMSTATE const enmBackendState = drvAudioStreamGetBackendStateAndProcessChanges(pThis, pStreamEx);
    34223445
    34233446            /*
     
    40304053    AssertReturnVoid(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC);
    40314054    AssertReturnVoid(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC);
    4032     LogFlowFunc(("pStreamEx=%p '%s'\n", pStreamEx, pStreamEx->Guest.Cfg.szName));
     4055    LogFlowFunc(("pStreamEx=%p '%s'\n", pStreamEx, pStreamEx->Core.szName));
    40334056
    40344057    /*
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