VirtualBox

Changeset 89357 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
May 28, 2021 1:25:07 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
144706
Message:

AudioMixer: More cleanups. bugref:9890

Location:
trunk/src/VBox/Devices/Audio
Files:
2 edited

Legend:

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

    r89355 r89357  
    100100*   Internal Functions                                                                                                           *
    101101*********************************************************************************************************************************/
    102 static int audioMixerAddSinkInternal(PAUDIOMIXER pMixer, PAUDMIXSINK pSink);
    103102static int audioMixerRemoveSinkInternal(PAUDIOMIXER pMixer, PAUDMIXSINK pSink);
    104103
    105 static int audioMixerSinkInit(PAUDMIXSINK pSink, PAUDIOMIXER pMixer, const char *pcszName, PDMAUDIODIR enmDir, PPDMDEVINS pDevIns);
    106104static void audioMixerSinkDestroyInternal(PAUDMIXSINK pSink, PPDMDEVINS pDevIns);
    107105static int audioMixerSinkUpdateVolume(PAUDMIXSINK pSink, PCPDMAUDIOVOLUME pVolMaster);
     
    228226    int rc2 = RTCritSectEnter(&pMixer->CritSect);
    229227    AssertRCReturnVoid(rc2);
     228    Assert(pMixer->uMagic == AUDIOMIXER_MAGIC);
    230229
    231230    LogFlowFunc(("Destroying %s ...\n", pMixer->pszName));
     
    260259{
    261260    RT_NOREF(pszArgs);
    262     Assert(pMixer->uMagic == AUDIOMIXER_MAGIC);
     261    AssertReturnVoid(pMixer->uMagic == AUDIOMIXER_MAGIC);
    263262
    264263    int rc2 = RTCritSectEnter(&pMixer->CritSect);
     
    281280}
    282281
    283 /**
    284  * Invalidates all internal data, internal version.
     282
     283/**
     284 * Sets the mixer's master volume.
    285285 *
    286286 * @returns VBox status code.
    287  * @param   pMixer              Mixer to invalidate data for.
    288  */
    289 static int audioMixerInvalidateInternal(PAUDIOMIXER pMixer)
     287 * @param   pMixer              Mixer to set master volume for.
     288 * @param   pVol                Volume to set.
     289 */
     290int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PCPDMAUDIOVOLUME pVol)
    290291{
    291292    AssertPtrReturn(pMixer, VERR_INVALID_POINTER);
    292     LogFlowFunc(("[%s]\n", pMixer->pszName));
    293 
    294     /* Propagate new master volume to all connected sinks. */
     293    AssertReturn(pMixer->uMagic == AUDIOMIXER_MAGIC, VERR_INVALID_MAGIC);
     294    AssertPtrReturn(pVol, VERR_INVALID_POINTER);
     295
     296    int rc = RTCritSectEnter(&pMixer->CritSect);
     297    AssertRCReturn(rc, rc);
     298
     299    /*
     300     * Make a copy.
     301     */
     302    memcpy(&pMixer->VolMaster, pVol, sizeof(PDMAUDIOVOLUME));
     303    LogFlowFunc(("[%s] lVol=%RU32, rVol=%RU32 => fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
     304                 pMixer->pszName, pVol->uLeft, pVol->uRight,
     305                 pMixer->VolMaster.fMuted, pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight));
     306
     307    /*
     308     * Propagate new master volume to all sinks.
     309     */
    295310    PAUDMIXSINK pSink;
    296311    RTListForEach(&pMixer->lstSinks, pSink, AUDMIXSINK, Node)
     
    300315    }
    301316
    302     return VINF_SUCCESS;
    303 }
    304 
    305 #if 0 /* unused */
    306 /**
    307  * Invalidates all internal data.
    308  *
    309  * @returns VBox status code.
    310  * @param   pMixer              Mixer to invalidate data for.
    311  */
    312 void AudioMixerInvalidate(PAUDIOMIXER pMixer)
    313 {
    314     AssertPtrReturnVoid(pMixer);
    315     Assert(pMixer->uMagic == AUDIOMIXER_MAGIC);
    316 
    317     int rc2 = RTCritSectEnter(&pMixer->CritSect);
    318     AssertRC(rc2);
    319 
    320     LogFlowFunc(("[%s]\n", pMixer->pszName));
    321 
    322     rc2 = audioMixerInvalidateInternal(pMixer);
    323     AssertRC(rc2);
    324 
    325     rc2 = RTCritSectLeave(&pMixer->CritSect);
    326     AssertRC(rc2);
    327 }
    328 #endif
    329 
    330 /**
    331  * Adds sink to an existing mixer.
    332  *
    333  * @returns VBox status code.
    334  * @param   pMixer              Mixer to add sink to.
    335  * @param   pSink               Sink to add.
    336  */
    337 static int audioMixerAddSinkInternal(PAUDIOMIXER pMixer, PAUDMIXSINK pSink)
    338 {
    339     AssertPtrReturn(pMixer, VERR_INVALID_POINTER);
    340     AssertPtrReturn(pSink,  VERR_INVALID_POINTER);
    341 
    342     /** @todo Check upper sink limit? */
    343     /** @todo Check for double-inserted sinks? */
    344 
    345     RTListAppend(&pMixer->lstSinks, &pSink->Node);
    346     pMixer->cSinks++;
    347 
    348     LogFlowFunc(("pMixer=%p, pSink=%p, cSinks=%RU8\n",
    349                  pMixer, pSink, pMixer->cSinks));
    350 
    351     return VINF_SUCCESS;
    352 }
    353 
    354 /**
    355  * Removes a formerly attached audio sink for an audio mixer, internal version.
     317    RTCritSectLeave(&pMixer->CritSect);
     318    return rc;
     319}
     320
     321
     322/**
     323 * Removes an audio sink from the given audio mixer, internal version.
     324 *
     325 * Used by AudioMixerDestroy and AudioMixerSinkDestroy.
     326 *
     327 * Caller must hold the mixer lock.
    356328 *
    357329 * @returns VBox status code.
     
    361333static int audioMixerRemoveSinkInternal(PAUDIOMIXER pMixer, PAUDMIXSINK pSink)
    362334{
    363     AssertPtrReturn(pMixer, VERR_INVALID_POINTER);
    364     if (!pSink)
    365         return VERR_NOT_FOUND;
    366 
    367     AssertMsgReturn(pSink->pParent == pMixer, ("%s: Is not part of mixer '%s'\n",
    368                                                pSink->pszName, pMixer->pszName), VERR_NOT_FOUND);
    369 
    370     LogFlowFunc(("[%s] pSink=%s, cSinks=%RU8\n",
    371                  pMixer->pszName, pSink->pszName, pMixer->cSinks));
     335    LogFlowFunc(("[%s] pSink=%s, cSinks=%RU8\n", pMixer->pszName, pSink->pszName, pMixer->cSinks));
     336    Assert(RTCritSectIsOwner(&pMixer->CritSect));
     337    AssertMsgReturn(pSink->pParent == pMixer,
     338                    ("%s: Is not part of mixer '%s'\n", pSink->pszName, pMixer->pszName), VERR_INTERNAL_ERROR_4);
    372339
    373340    /* Remove sink from mixer. */
     
    381348
    382349    return VINF_SUCCESS;
    383 }
    384 
    385 /**
    386  * Sets the mixer's master volume.
    387  *
    388  * @returns VBox status code.
    389  * @param   pMixer              Mixer to set master volume for.
    390  * @param   pVol                Volume to set.
    391  */
    392 int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PPDMAUDIOVOLUME pVol)
    393 {
    394     AssertPtrReturn(pMixer, VERR_INVALID_POINTER);
    395     Assert(pMixer->uMagic == AUDIOMIXER_MAGIC);
    396     AssertPtrReturn(pVol,   VERR_INVALID_POINTER);
    397 
    398     int rc = RTCritSectEnter(&pMixer->CritSect);
    399     AssertRCReturn(rc, rc);
    400 
    401     memcpy(&pMixer->VolMaster, pVol, sizeof(PDMAUDIOVOLUME));
    402 
    403     LogFlowFunc(("[%s] lVol=%RU32, rVol=%RU32 => fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",
    404                  pMixer->pszName, pVol->uLeft, pVol->uRight,
    405                  pMixer->VolMaster.fMuted, pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight));
    406 
    407     rc = audioMixerInvalidateInternal(pMixer);
    408 
    409     int rc2 = RTCritSectLeave(&pMixer->CritSect);
    410     AssertRC(rc2);
    411 
    412     return rc;
    413350}
    414351
     
    432369    AssertPtrReturn(pMixer, VERR_INVALID_POINTER);
    433370    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    434     /* ppSink is optional. */
     371    size_t const cchName = strlen(pszName);
     372    AssertReturn(cchName > 0 && cchName < 64, VERR_INVALID_NAME);
     373    AssertPtrNullReturn(ppSink, VERR_INVALID_POINTER);
    435374
    436375    int rc = RTCritSectEnter(&pMixer->CritSect);
    437376    AssertRCReturn(rc, rc);
    438377
    439     PAUDMIXSINK pSink = (PAUDMIXSINK)RTMemAllocZ(sizeof(AUDMIXSINK));
     378    /** @todo limit the number of sinks? */
     379
     380    /*
     381     * Allocate the data and initialize the critsect.
     382     */
     383    PAUDMIXSINK pSink = (PAUDMIXSINK)RTMemAllocZ(sizeof(AUDMIXSINK) + cchName + 1);
    440384    if (pSink)
    441385    {
    442         rc = audioMixerSinkInit(pSink, pMixer, pszName, enmDir, pDevIns);
     386        rc = RTCritSectInit(&pSink->CritSect);
    443387        if (RT_SUCCESS(rc))
    444388        {
    445             rc = audioMixerAddSinkInternal(pMixer, pSink);
    446             if (RT_SUCCESS(rc))
    447             {
    448                 RTCritSectLeave(&pMixer->CritSect);
    449 
    450                 char szPrefix[128];
    451                 RTStrPrintf(szPrefix, sizeof(szPrefix), "MixerSink-%s/", pSink->pszName);
    452                 PDMDevHlpSTAMRegisterF(pDevIns, &pSink->MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    453                                        "Sink mixer buffer size in frames.",         "%sMixBufSize", szPrefix);
    454                 PDMDevHlpSTAMRegisterF(pDevIns, &pSink->MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
    455                                        "Sink mixer buffer fill size in frames.",    "%sMixBufUsed", szPrefix);
    456                 PDMDevHlpSTAMRegisterF(pDevIns, &pSink->cStreams, STAMTYPE_U8, STAMVISIBILITY_USED, STAMUNIT_NONE,
    457                                        "Number of streams attached to the sink.",   "%sStreams", szPrefix);
    458 
    459                 if (ppSink)
    460                     *ppSink = pSink;
    461                 return VINF_SUCCESS;
    462             }
    463         }
    464 
    465         audioMixerSinkDestroyInternal(pSink, pDevIns);
     389            /*
     390             * Initialize it.
     391             */
     392            pSink->uMagic   = AUDMIXSINK_MAGIC;
     393            pSink->pParent  = NULL;
     394            pSink->enmDir   = enmDir;
     395            pSink->pszName  = (const char *)memcpy(pSink + 1, pszName, cchName + 1);
     396            RTListInit(&pSink->lstStreams);
     397
     398            /* Set initial volume to max. */
     399            pSink->Volume.fMuted = false;
     400            pSink->Volume.uLeft  = PDMAUDIO_VOLUME_MAX;
     401            pSink->Volume.uRight = PDMAUDIO_VOLUME_MAX;
     402
     403            /* Ditto for the combined volume. */
     404            pSink->VolumeCombined.fMuted = false;
     405            pSink->VolumeCombined.uLeft  = PDMAUDIO_VOLUME_MAX;
     406            pSink->VolumeCombined.uRight = PDMAUDIO_VOLUME_MAX;
     407
     408            /* AIO */
     409            AssertPtr(pDevIns);
     410            pSink->AIO.pDevIns     = pDevIns;
     411            pSink->AIO.hThread     = NIL_RTTHREAD;
     412            pSink->AIO.hEvent      = NIL_RTSEMEVENT;
     413            pSink->AIO.fStarted    = false;
     414            pSink->AIO.fShutdown   = false;
     415            pSink->AIO.cUpdateJobs = 0;
     416
     417            /*
     418             * Add it to the mixer.
     419             */
     420            RTListAppend(&pMixer->lstSinks, &pSink->Node);
     421            pMixer->cSinks++;
     422            pSink->pParent = pMixer;
     423
     424            RTCritSectLeave(&pMixer->CritSect);
     425
     426            /*
     427             * Register stats and return.
     428             */
     429            char szPrefix[128];
     430            RTStrPrintf(szPrefix, sizeof(szPrefix), "MixerSink-%s/", pSink->pszName);
     431            PDMDevHlpSTAMRegisterF(pDevIns, &pSink->MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
     432                                   "Sink mixer buffer size in frames.",         "%sMixBufSize", szPrefix);
     433            PDMDevHlpSTAMRegisterF(pDevIns, &pSink->MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE,
     434                                   "Sink mixer buffer fill size in frames.",    "%sMixBufUsed", szPrefix);
     435            PDMDevHlpSTAMRegisterF(pDevIns, &pSink->cStreams, STAMTYPE_U8, STAMVISIBILITY_USED, STAMUNIT_NONE,
     436                                   "Number of streams attached to the sink.",   "%sStreams", szPrefix);
     437
     438            if (ppSink)
     439                *ppSink = pSink;
     440            return VINF_SUCCESS;
     441        }
    466442
    467443        RTMemFree(pSink);
    468         pSink = NULL;
    469444    }
    470445    else
     
    472447
    473448    RTCritSectLeave(&pMixer->CritSect);
     449    if (ppSink)
     450        *ppSink = NULL;
    474451    return rc;
    475452}
     
    858835
    859836
    860 
    861 /**
    862  * Initializes a sink.
    863  *
    864  * @returns VBox status code.
    865  * @param   pSink           Sink to initialize.
    866  * @param   pMixer          Mixer the sink is assigned to.
    867  * @param   pszName         Name of the sink.
    868  * @param   enmDir          Direction of the sink.
    869  * @param   pDevIns         The device instance.
    870  */
    871 static int audioMixerSinkInit(PAUDMIXSINK pSink, PAUDIOMIXER pMixer, const char *pszName, PDMAUDIODIR enmDir, PPDMDEVINS pDevIns)
    872 {
    873     pSink->pszName = RTStrDup(pszName);
    874     if (!pSink->pszName)
    875         return VERR_NO_MEMORY;
    876 
    877     int rc = RTCritSectInit(&pSink->CritSect);
    878     if (RT_SUCCESS(rc))
    879     {
    880         pSink->uMagic   = AUDMIXSINK_MAGIC;
    881         pSink->pParent  = pMixer;
    882         pSink->enmDir   = enmDir;
    883 
    884         RTListInit(&pSink->lstStreams);
    885 
    886         /* Set initial volume to max. */
    887         pSink->Volume.fMuted = false;
    888         pSink->Volume.uLeft  = PDMAUDIO_VOLUME_MAX;
    889         pSink->Volume.uRight = PDMAUDIO_VOLUME_MAX;
    890 
    891         /* Ditto for the combined volume. */
    892         pSink->VolumeCombined.fMuted = false;
    893         pSink->VolumeCombined.uLeft  = PDMAUDIO_VOLUME_MAX;
    894         pSink->VolumeCombined.uRight = PDMAUDIO_VOLUME_MAX;
    895 
    896         /* AIO */
    897         AssertPtr(pDevIns);
    898         pSink->AIO.pDevIns     = pDevIns;
    899         pSink->AIO.hThread     = NIL_RTTHREAD;
    900         pSink->AIO.hEvent      = NIL_RTSEMEVENT;
    901         pSink->AIO.fStarted    = false;
    902         pSink->AIO.fShutdown   = false;
    903         pSink->AIO.cUpdateJobs = 0;
    904     }
    905 
    906     LogFlowFuncLeaveRC(rc);
    907     return rc;
    908 }
    909 
    910 /**
    911  * Destroys a mixer sink and removes it from the attached mixer (if any).
    912  *
    913  * @param   pSink       Mixer sink to destroy.
    914  * @param   pDevIns     The device instance that statistics are registered with.
    915  */
    916 void AudioMixerSinkDestroy(PAUDMIXSINK pSink, PPDMDEVINS pDevIns)
    917 {
    918     if (!pSink)
    919         return;
    920 
    921     /** @todo wrong critsect for audioMixerRemoveSinkInternal...   */
    922     int rc2 = RTCritSectEnter(&pSink->CritSect);
    923     AssertRC(rc2);
    924 
    925     if (pSink->pParent)
    926     {
    927         /* Save mixer pointer, as after audioMixerRemoveSinkInternal() the
    928          * pointer will be gone from the stream. */
    929         PAUDIOMIXER pMixer = pSink->pParent;
    930         AssertPtr(pMixer);
    931         Assert(pMixer->uMagic == AUDIOMIXER_MAGIC);
    932 
    933         audioMixerRemoveSinkInternal(pMixer, pSink);
    934     }
    935 
    936     rc2 = RTCritSectLeave(&pSink->CritSect);
    937     AssertRC(rc2);
    938 
    939     audioMixerSinkDestroyInternal(pSink, pDevIns);
    940 
    941     RTMemFree(pSink);
    942     pSink = NULL;
    943 }
    944 
    945837/**
    946838 * Destroys a mixer sink.
     839 *
     840 * Worker for AudioMixerSinkDestroy(), AudioMixerCreateSink() and
     841 * AudioMixerDestroy().
    947842 *
    948843 * @param   pSink       Mixer sink to destroy.
     
    965860    }
    966861
     862    /** @todo r=bird: this looks wrong for the AudioMixerSinkDestroy case ...   */
    967863    if (   pSink->pParent
    968864        && pSink->pParent->fFlags & AUDMIXER_FLAGS_DEBUG)
     
    997893    }
    998894
    999     RTStrFree(pSink->pszName);
    1000     pSink->pszName = NULL;
    1001 
    1002895    AudioMixBufDestroy(&pSink->MixBuf);
    1003896    RTCritSectDelete(&pSink->CritSect);
     897}
     898
     899
     900/**
     901 * Destroys a mixer sink and removes it from the attached mixer (if any).
     902 *
     903 * @param   pSink       Mixer sink to destroy.
     904 * @param   pDevIns     The device instance that statistics are registered with.
     905 */
     906void AudioMixerSinkDestroy(PAUDMIXSINK pSink, PPDMDEVINS pDevIns)
     907{
     908    if (!pSink)
     909        return;
     910
     911    /*
     912     * Serializing paranoia.
     913     */
     914    int rc = RTCritSectEnter(&pSink->CritSect);
     915    AssertRCReturnVoid(rc);
     916    RTCritSectLeave(&pSink->CritSect);
     917
     918    /*
     919     * Unlink from parent.
     920     */
     921    PAUDIOMIXER pMixer = pSink->pParent;
     922    if (   RT_VALID_PTR(pMixer)
     923        && pMixer->uMagic == AUDIOMIXER_MAGIC)
     924    {
     925        RTCritSectEnter(&pMixer->CritSect);
     926        audioMixerRemoveSinkInternal(pMixer, pSink);
     927        RTCritSectLeave(&pMixer->CritSect);
     928    }
     929    else if (pMixer)
     930        AssertFailed();
     931
     932    audioMixerSinkDestroyInternal(pSink, pDevIns);
     933
     934    RTMemFree(pSink);
     935    pSink = NULL;
    1004936}
    1005937
  • trunk/src/VBox/Devices/Audio/AudioMixer.h

    r89355 r89357  
    161161    /** Pointer to mixer object this sink is bound to. */
    162162    PAUDIOMIXER             pParent;
    163     /** Name of this sink. */
    164     char                   *pszName;
     163    /** Name of this sink (allocated after this structure). */
     164    char const             *pszName;
    165165    /** The sink's PCM format (i.e. the guest device side). */
    166166    PDMAUDIOPCMPROPS        PCMProps;
     
    279279 * @{ */
    280280int         AudioMixerCreate(const char *pszName, uint32_t fFlags, PAUDIOMIXER *ppMixer);
    281 void AudioMixerDestroy(PAUDIOMIXER pMixer, PPDMDEVINS pDevIns);
    282 void AudioMixerInvalidate(PAUDIOMIXER pMixer);
    283 int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PPDMAUDIOVOLUME pVol);
    284 void AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs);
     281void        AudioMixerDestroy(PAUDIOMIXER pMixer, PPDMDEVINS pDevIns);
     282void        AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs);
     283int         AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PCPDMAUDIOVOLUME pVol);
    285284int         AudioMixerCreateSink(PAUDIOMIXER pMixer, const char *pszName, PDMAUDIODIR enmDir, PPDMDEVINS pDevIns, PAUDMIXSINK *ppSink);
    286285/** @} */
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