VirtualBox

Ignore:
Timestamp:
May 16, 2021 8:00:06 PM (4 years ago)
Author:
vboxsync
Message:

ValKit/Audio: Optionally play via DrvAudio (works on linux). bugref:10008

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp

    r89061 r89063  
    4040#include <iprt/stream.h>
    4141#include <iprt/string.h>
     42#include <iprt/uuid.h>
    4243#include <iprt/test.h>
    4344#include <iprt/formats/riff.h>
     
    205206static int audioTestPlayTone(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms);
    206207static int audioTestStreamDestroy(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream);
     208
     209static int audioTestDrvConstruct(PAUDIOTESTDRVSTACK pDrvStack, PCPDMDRVREG pDrvReg,
     210                                 PPDMDRVINS pParentDrvIns, PPPDMDRVINS ppDrvIns);
    207211
    208212static RTEXITCODE audioTestUsage(PRTSTREAM pStrm);
     
    325329
    326330/*********************************************************************************************************************************
    327 *   Fake PDM driver handling.                                                                                                    *
     331*   Fake PDM Driver Handling.                                                                                                    *
    328332*********************************************************************************************************************************/
    329333
    330 /** @name Driver Helper Fakes / Stubs
     334/** @name Driver Fakes/Stubs
    331335 *
    332336 * @note The VMM functions defined here will turn into driver helpers before
     
    336340 * @{  */
    337341
    338 VMMR3DECL(PCFGMNODE)    CFGMR3GetChild(PCFGMNODE pNode, const char *pszPath)
     342VMMR3DECL(PCFGMNODE) CFGMR3GetChild(PCFGMNODE pNode, const char *pszPath)
    339343{
    340344    RT_NOREF(pNode, pszPath);
     
    372376}
    373377
    374 VMMR3DECL(int)          CFGMR3QueryBoolDef(     PCFGMNODE pNode, const char *pszName, bool *pf, bool fDef)
     378VMMR3DECL(int) CFGMR3QueryBoolDef(PCFGMNODE pNode, const char *pszName, bool *pf, bool fDef)
    375379{
    376380    RT_NOREF(pNode, pszName, pf);
     
    378382}
    379383
    380 VMMR3DECL(int)          CFGMR3QueryU8(          PCFGMNODE pNode, const char *pszName, uint8_t *pu8)
     384VMMR3DECL(int) CFGMR3QueryU8(PCFGMNODE pNode, const char *pszName, uint8_t *pu8)
    381385{
    382386    RT_NOREF(pNode, pszName, pu8);
     
    384388}
    385389
    386 VMMR3DECL(int)          CFGMR3QueryU32(         PCFGMNODE pNode, const char *pszName, uint32_t *pu32)
     390VMMR3DECL(int) CFGMR3QueryU32(PCFGMNODE pNode, const char *pszName, uint32_t *pu32)
    387391{
    388392    RT_NOREF(pNode, pszName, pu32);
     
    399403
    400404/** @} */
     405
     406/** @name Driver Helper Fakes
     407 * @{ */
     408
     409static DECLCALLBACK(int) audioTestDrvHlp_Attach(PPDMDRVINS pDrvIns, uint32_t fFlags, PPDMIBASE *ppBaseInterface)
     410{
     411    /* DrvAudio must be allowed to attach the backend driver (paranoid
     412       backend drivers may call us to check that nothing is attached). */
     413    if (strcmp(pDrvIns->pReg->szName, "AUDIO") == 0)
     414    {
     415        PAUDIOTESTDRVSTACK pDrvStack = pDrvIns->Internal.s.pStack;
     416        AssertReturn(pDrvStack->pDrvBackendIns == NULL, VERR_PDM_DRIVER_ALREADY_ATTACHED);
     417
     418        if (g_uVerbosity > 1)
     419            RTMsgInfo("Attaching backend '%s' to DrvAudio...\n", pDrvStack->pDrvReg->szName);
     420        int rc = audioTestDrvConstruct(pDrvStack, pDrvStack->pDrvReg, pDrvIns, &pDrvStack->pDrvBackendIns);
     421        if (RT_SUCCESS(rc))
     422        {
     423            if (ppBaseInterface)
     424                *ppBaseInterface = &pDrvStack->pDrvBackendIns->IBase;
     425        }
     426        else
     427            RTMsgError("Failed to attach backend: %Rrc", rc);
     428        return rc;
     429    }
     430    RT_NOREF(fFlags);
     431    return VERR_PDM_NO_ATTACHED_DRIVER;
     432}
     433
     434static DECLCALLBACK(void) audioTestDrvHlp_STAMRegisterF(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType,
     435                                                        STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc,
     436                                                        const char *pszName, ...)
     437{
     438    RT_NOREF(pDrvIns, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName);
     439}
     440
     441static DECLCALLBACK(void) audioTestDrvHlp_STAMRegisterV(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType,
     442                                                        STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc,
     443                                                        const char *pszName, va_list args)
     444{
     445    RT_NOREF(pDrvIns, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
     446}
     447
     448static DECLCALLBACK(int) audioTestDrvHlp_STAMDeregister(PPDMDRVINS pDrvIns, void *pvSample)
     449{
     450    RT_NOREF(pDrvIns, pvSample);
     451    return VINF_SUCCESS;
     452}
     453
     454static DECLCALLBACK(int) audioTestDrvHlp_STAMDeregisterByPrefix(PPDMDRVINS pDrvIns, const char *pszPrefix)
     455{
     456    RT_NOREF(pDrvIns, pszPrefix);
     457    return VINF_SUCCESS;
     458}
     459
     460/**
     461 * Get the driver helpers.
     462 */
     463static const PDMDRVHLPR3 *audioTestFakeGetDrvHlp(void)
     464{
     465    /*
     466     * Note! No initializer for s_DrvHlp (also why it's not a file global).
     467     *       We do not want to have to update this code every time PDMDRVHLPR3
     468     *       grows new entries or are otherwise modified.  Only when the
     469     *       entries used by the audio driver changes do we want to change
     470     *       our code.
     471     */
     472    static PDMDRVHLPR3 s_DrvHlp;
     473    if (s_DrvHlp.u32Version != PDM_DRVHLPR3_VERSION)
     474    {
     475        s_DrvHlp.u32Version                     = PDM_DRVHLPR3_VERSION;
     476        s_DrvHlp.u32TheEnd                      = PDM_DRVHLPR3_VERSION;
     477        s_DrvHlp.pfnAttach                      = audioTestDrvHlp_Attach;
     478        s_DrvHlp.pfnSTAMRegisterF               = audioTestDrvHlp_STAMRegisterF;
     479        s_DrvHlp.pfnSTAMRegisterV               = audioTestDrvHlp_STAMRegisterV;
     480        s_DrvHlp.pfnSTAMDeregister              = audioTestDrvHlp_STAMDeregister;
     481        s_DrvHlp.pfnSTAMDeregisterByPrefix      = audioTestDrvHlp_STAMDeregisterByPrefix;
     482    }
     483    return &s_DrvHlp;
     484}
     485
     486/** @} */
     487
     488
     489/**
     490 * Implementation of PDMIBASE::pfnQueryInterface for a fake device above
     491 * DrvAudio.
     492 */
     493static DECLCALLBACK(void *) audioTestFakeDeviceIBaseQueryInterface(PPDMIBASE pInterface, const char *pszIID)
     494{
     495    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, pInterface);
     496    RTMsgWarning("audioTestFakeDeviceIBaseQueryInterface: Unknown interface: %s\n", pszIID);
     497    return NULL;
     498}
     499
     500/** IBase interface for a fake device above DrvAudio. */
     501static PDMIBASE g_AudioTestFakeDeviceIBase =  { audioTestFakeDeviceIBaseQueryInterface };
     502
     503
     504static DECLCALLBACK(int) audioTestIHostAudioPort_DoOnWorkerThread(PPDMIHOSTAUDIOPORT pInterface, PPDMAUDIOBACKENDSTREAM pStream,
     505                                                                  uintptr_t uUser, void *pvUser)
     506{
     507    RT_NOREF(pInterface, pStream, uUser, pvUser);
     508    RTMsgWarning("audioTestIHostAudioPort_DoOnWorkerThread was called\n");
     509    return VERR_NOT_IMPLEMENTED;
     510}
     511
     512DECLCALLBACK(void) audioTestIHostAudioPort_NotifyDeviceChanged(PPDMIHOSTAUDIOPORT pInterface, PDMAUDIODIR enmDir, void *pvUser)
     513{
     514    RT_NOREF(pInterface, enmDir, pvUser);
     515    RTMsgWarning("audioTestIHostAudioPort_NotifyDeviceChanged was called\n");
     516}
     517
     518static DECLCALLBACK(void) audioTestIHostAudioPort_StreamNotifyPreparingDeviceSwitch(PPDMIHOSTAUDIOPORT pInterface,
     519                                                                                    PPDMAUDIOBACKENDSTREAM pStream)
     520{
     521    RT_NOREF(pInterface, pStream);
     522    RTMsgWarning("audioTestIHostAudioPort_StreamNotifyPreparingDeviceSwitch was called\n");
     523}
     524
     525static DECLCALLBACK(void) audioTestIHostAudioPort_StreamNotifyDeviceChanged(PPDMIHOSTAUDIOPORT pInterface,
     526                                                                            PPDMAUDIOBACKENDSTREAM pStream, bool fReInit)
     527{
     528    RT_NOREF(pInterface, pStream, fReInit);
     529    RTMsgWarning("audioTestIHostAudioPort_StreamNotifyDeviceChanged was called\n");
     530}
     531
     532static DECLCALLBACK(void) audioTestIHostAudioPort_NotifyDevicesChanged(PPDMIHOSTAUDIOPORT pInterface)
     533{
     534    RT_NOREF(pInterface);
     535    RTMsgWarning("audioTestIHostAudioPort_NotifyDevicesChanged was called\n");
     536}
     537
     538static PDMIHOSTAUDIOPORT g_AudioTestIHostAudioPort =
     539{
     540    audioTestIHostAudioPort_DoOnWorkerThread,
     541    audioTestIHostAudioPort_NotifyDeviceChanged,
     542    audioTestIHostAudioPort_StreamNotifyPreparingDeviceSwitch,
     543    audioTestIHostAudioPort_StreamNotifyDeviceChanged,
     544    audioTestIHostAudioPort_NotifyDevicesChanged,
     545};
     546
     547/**
     548 * Implementation of PDMIBASE::pfnQueryInterface for a fake DrvAudio above a
     549 * backend.
     550 */
     551static DECLCALLBACK(void *) audioTestFakeDrvAudioIBaseQueryInterface(PPDMIBASE pInterface, const char *pszIID)
     552{
     553    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, pInterface);
     554    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIOPORT, &g_AudioTestIHostAudioPort);
     555    RTMsgWarning("audioTestFakeDrvAudioIBaseQueryInterface: Unknown interface: %s\n", pszIID);
     556    return NULL;
     557}
     558
     559/** IBase interface for a fake DrvAudio above a lonesome backend. */
     560static PDMIBASE g_AudioTestFakeDrvAudioIBase =  { audioTestFakeDrvAudioIBaseQueryInterface };
     561
     562
    401563
    402564/**
     
    420582     */
    421583    AssertPtrReturn(pDrvReg, VERR_INVALID_POINTER);
    422     RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Initializing backend '%s' ...\n", pDrvReg->szName);
     584    RTMsgInfo("Initializing backend '%s' ...\n", pDrvReg->szName);
    423585    AssertPtrReturn(pDrvReg->pfnConstruct, VERR_INVALID_PARAMETER);
    424 
    425     /*
    426      * Initialize the driver helper the first time thru.
    427      */
    428     static PDMDRVHLPR3 s_DrvHlp;
    429     if (s_DrvHlp.u32Version == 0)
    430     {
    431         s_DrvHlp.u32Version = PDM_DRVHLPR3_VERSION;
    432         s_DrvHlp.u32TheEnd  = PDM_DRVHLPR3_VERSION;
    433     }
    434586
    435587    /*
     
    441593    pDrvIns->u32Version         = PDM_DRVINS_VERSION;
    442594    pDrvIns->iInstance          = 0;
    443     pDrvIns->pHlpR3             = &s_DrvHlp;
     595    pDrvIns->pHlpR3             = audioTestFakeGetDrvHlp();
    444596    pDrvIns->pvInstanceDataR3   = &pDrvIns->achInstanceData[0];
    445597    pDrvIns->pReg               = pDrvReg;
     
    454606        pDrvIns->pUpBase         = &pParentDrvIns->IBase;
    455607    }
     608    else if (strcmp(pDrvReg->szName, "AUDIO") == 0)
     609        pDrvIns->pUpBase         = &g_AudioTestFakeDeviceIBase;
     610    else
     611        pDrvIns->pUpBase         = &g_AudioTestFakeDrvAudioIBase;
    456612
    457613    /*
     
    534690/**
    535691 * Initializes a driver stack.
     692 *
    536693 * @returns VBox status code.
    537694 * @param   pDrvStack       The driver stack to initialize.
     
    541698static int audioTestDriverStackInit(PAUDIOTESTDRVSTACK pDrvStack, PCPDMDRVREG pDrvReg, bool fWithDrvAudio)
    542699{
    543     int rc;
    544700    RT_ZERO(*pDrvStack);
    545701    pDrvStack->pDrvReg = pDrvReg;
     702
     703    int rc;
    546704    if (!fWithDrvAudio)
    547705        rc = audioTestDrvConstruct(pDrvStack, pDrvReg, NULL /*pParentDrvIns*/, &pDrvStack->pDrvBackendIns);
    548706    else
    549707    {
    550         rc = VERR_NOT_IMPLEMENTED;
     708        rc = audioTestDrvConstruct(pDrvStack, &g_DrvAUDIO, NULL /*pParentDrvIns*/, &pDrvStack->pDrvAudioIns);
     709        if (RT_SUCCESS(rc))
     710        {
     711            Assert(pDrvStack->pDrvAudioIns);
     712            PPDMIBASE const pIBase = &pDrvStack->pDrvAudioIns->IBase;
     713            pDrvStack->pIAudioConnector = (PPDMIAUDIOCONNECTOR)pIBase->pfnQueryInterface(pIBase, PDMIAUDIOCONNECTOR_IID);
     714            if (pDrvStack->pIAudioConnector)
     715            {
     716                /* Both input and output is disabled by default. Fix that: */
     717                rc = pDrvStack->pIAudioConnector->pfnEnable(pDrvStack->pIAudioConnector, PDMAUDIODIR_OUT, true);
     718                if (RT_SUCCESS(rc))
     719                    rc = pDrvStack->pIAudioConnector->pfnEnable(pDrvStack->pIAudioConnector, PDMAUDIODIR_IN, true);
     720                if (RT_FAILURE(rc))
     721                {
     722                    RTTestFailed(g_hTest, "Failed to enabled input and output: %Rrc", rc);
     723                    audioTestDriverStackDelete(pDrvStack);
     724                }
     725            }
     726            else
     727            {
     728                RTTestFailed(g_hTest, "Failed to query PDMIAUDIOCONNECTOR");
     729                audioTestDriverStackDelete(pDrvStack);
     730                rc = VERR_PDM_MISSING_INTERFACE;
     731            }
     732        }
    551733    }
    552734
     
    556738    if (RT_SUCCESS(rc))
    557739    {
    558         pDrvStack->pIHostAudio
    559             = (PPDMIHOSTAUDIO)pDrvStack->pDrvBackendIns->IBase.pfnQueryInterface(&pDrvStack->pDrvBackendIns->IBase,
    560                                                                                  PDMIHOSTAUDIO_IID);
     740        PPDMIBASE const pIBase = &pDrvStack->pDrvBackendIns->IBase;
     741        pDrvStack->pIHostAudio = (PPDMIHOSTAUDIO)pIBase->pfnQueryInterface(pIBase, PDMIHOSTAUDIO_IID);
    561742        if (pDrvStack->pIHostAudio)
    562743        {
     
    590771                                                  PPDMAUDIOSTREAM *ppStream)
    591772{
     773    char szTmp[PDMAUDIOSTRMCFGTOSTRING_MAX + 16];
    592774    *ppStream = NULL;
    593775
    594     int rc;
     776    /*
     777     * Calculate the stream config.
     778     */
     779    PDMAUDIOSTREAMCFG CfgReq;
     780    int rc = PDMAudioStrmCfgInitWithProps(&CfgReq, pProps);
     781    AssertRC(rc);
     782    CfgReq.enmDir                       = PDMAUDIODIR_OUT;
     783    CfgReq.u.enmDst                     = PDMAUDIOPLAYBACKDST_FRONT;
     784    CfgReq.enmLayout                    = PDMAUDIOSTREAMLAYOUT_INTERLEAVED;
     785    CfgReq.Device.cMsSchedulingHint     = cMsSchedulingHint == UINT32_MAX || cMsSchedulingHint == 0
     786                                        ? 10 : cMsSchedulingHint;
     787    if (pDrvStack->pIAudioConnector && (cMsBufferSize == UINT32_MAX || cMsBufferSize == 0))
     788        CfgReq.Backend.cFramesBufferSize = 0; /* DrvAudio picks the default */
     789    else
     790        CfgReq.Backend.cFramesBufferSize = PDMAudioPropsMilliToFrames(pProps,
     791                                                                      cMsBufferSize == UINT32_MAX || cMsBufferSize == 0
     792                                                                      ? 300 : cMsBufferSize);
     793    if (cMsPreBuffer == UINT32_MAX)
     794        CfgReq.Backend.cFramesPreBuffering = pDrvStack->pIAudioConnector ? UINT32_MAX /*DrvAudo picks the default */
     795                                           : CfgReq.Backend.cFramesBufferSize * 2 / 3;
     796    else
     797        CfgReq.Backend.cFramesPreBuffering = PDMAudioPropsMilliToFrames(pProps, cMsPreBuffer);
     798    if (   CfgReq.Backend.cFramesPreBuffering >= CfgReq.Backend.cFramesBufferSize + 16
     799        && !pDrvStack->pIAudioConnector /*DrvAudio deals with it*/ )
     800    {
     801        RTMsgWarning("Cannot pre-buffer %#x frames with only %#x frames of buffer!",
     802                     CfgReq.Backend.cFramesPreBuffering, CfgReq.Backend.cFramesBufferSize);
     803        CfgReq.Backend.cFramesPreBuffering = CfgReq.Backend.cFramesBufferSize > 16
     804            ? CfgReq.Backend.cFramesBufferSize - 16 : 0;
     805    }
     806
     807    static uint32_t s_idxStream = 0;
     808    uint32_t const idxStream = s_idxStream++;
     809    RTStrPrintf(CfgReq.szName, sizeof(CfgReq.szName), "out-%u", idxStream);
     810
    595811    if (pDrvStack->pIAudioConnector)
    596812    {
    597         rc = VERR_NOT_IMPLEMENTED;
     813        /*
     814         * DrvAudio does most of the work here.
     815         */
     816        PDMAUDIOSTREAMCFG CfgGst = CfgReq;
     817        rc = pDrvStack->pIAudioConnector->pfnStreamCreate(pDrvStack->pIAudioConnector, PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF,
     818                                                          &CfgReq, &CfgGst, ppStream);
     819        if (RT_SUCCESS(rc))
     820        {
     821            RTMsgInfo("Created backend stream: %s\n", PDMAudioStrmCfgToString(&CfgReq, szTmp, sizeof(szTmp)));
     822            return rc;
     823        }
     824        RTTestFailed(g_hTest, "pfnStreamCreate failed: %Rrc", rc);
    598825    }
    599826    else
    600827    {
    601         /*
    602          * Calculate the stream config.
    603          */
    604         PDMAUDIOSTREAMCFG CfgReq;
    605         rc = PDMAudioStrmCfgInitWithProps(&CfgReq, pProps);
    606         AssertRC(rc);
    607         CfgReq.enmDir                       = PDMAUDIODIR_OUT;
    608         CfgReq.u.enmDst                     = PDMAUDIOPLAYBACKDST_UNKNOWN;
    609         CfgReq.enmLayout                    = PDMAUDIOSTREAMLAYOUT_INTERLEAVED;
    610         CfgReq.Device.cMsSchedulingHint     = cMsSchedulingHint == UINT32_MAX || cMsSchedulingHint == 0
    611                                             ? 10 : cMsSchedulingHint;
    612         CfgReq.Backend.cFramesBufferSize    = PDMAudioPropsMilliToFrames(pProps,
    613                                                                          cMsBufferSize == UINT32_MAX || cMsBufferSize == 0
    614                                                                          ? 300 : cMsBufferSize);
    615         if (cMsPreBuffer == UINT32_MAX)
    616             CfgReq.Backend.cFramesPreBuffering = CfgReq.Backend.cFramesBufferSize * 2 / 3;
    617         else
    618             CfgReq.Backend.cFramesPreBuffering = PDMAudioPropsMilliToFrames(pProps, cMsPreBuffer);
    619         if (CfgReq.Backend.cFramesPreBuffering >= CfgReq.Backend.cFramesBufferSize + 16)
    620         {
    621             RTMsgWarning("Cannot pre-buffer %#x frames with only %#x frames of buffer!",
    622                          CfgReq.Backend.cFramesPreBuffering, CfgReq.Backend.cFramesBufferSize);
    623             CfgReq.Backend.cFramesPreBuffering = CfgReq.Backend.cFramesBufferSize > 16
    624                                                ? CfgReq.Backend.cFramesBufferSize - 16 : 0;
    625         }
    626 
    627         static uint32_t s_idxStream = 0;
    628         uint32_t const idxStream = s_idxStream++;
    629         RTStrPrintf(CfgReq.szName, sizeof(CfgReq.szName), "out-%u", idxStream);
    630 
    631828        /*
    632829         * Get the config so we can see how big the PDMAUDIOBACKENDSTREAM
     
    666863                        pStreamAt->Core.Props = pStreamAt->Cfg.Props;
    667864                        if (g_uVerbosity > 1)
    668                         {
    669                             char szTmp[PDMAUDIOSTRMCFGTOSTRING_MAX + 16];
    670865                            RTMsgInfo("Created backend stream: %s\n",
    671866                                      PDMAudioStrmCfgToString(&pStreamAt->Cfg, szTmp, sizeof(szTmp)));
    672                         }
    673867
    674868                        /* Return if stream is ready: */
     
    19412135*   Command: play                                                                                                                *
    19422136*********************************************************************************************************************************/
    1943 /**
    1944  * Command line parameters for test mode.
    1945  */
    1946 static const RTGETOPTDEF g_aCmdPlayOptions[] =
    1947 {
    1948     { "--backend",          'b',                          RTGETOPT_REQ_STRING  },
    1949 };
    1950 
    1951 /** the 'play' command option help. */
    1952 static DECLCALLBACK(const char *) audioTestCmdPlayHelp(PCRTGETOPTDEF pOpt)
    1953 {
    1954     switch (pOpt->iShort)
    1955     {
    1956         case 'b': return "The audio backend to use.";
    1957         default:  return NULL;
    1958     }
    1959 }
    19602137
    19612138/**
     
    19632140 */
    19642141static RTEXITCODE audioTestPlayOne(const char *pszFile, PCPDMDRVREG pDrvReg, uint32_t cMsBufferSize,
    1965                                    uint32_t cMsPreBuffer, uint32_t cMsSchedulingHint)
     2142                                   uint32_t cMsPreBuffer, uint32_t cMsSchedulingHint, bool fWithDrvAudio)
    19662143{
    19672144    /*
     
    19892166    RTEXITCODE          rcExit = RTEXITCODE_FAILURE;
    19902167    AUDIOTESTDRVSTACK   DrvStack;
    1991     rc = audioTestDriverStackInit(&DrvStack, pDrvReg, false /*fWithDrvAudio*/);
     2168    rc = audioTestDriverStackInit(&DrvStack, pDrvReg, fWithDrvAudio);
    19922169    if (RT_SUCCESS(rc))
    19932170    {
     
    20962273
    20972274/**
     2275 * Command line parameters for test mode.
     2276 */
     2277static const RTGETOPTDEF g_aCmdPlayOptions[] =
     2278{
     2279    { "--backend",          'b',                          RTGETOPT_REQ_STRING  },
     2280    { "--with-drv-audio",   'd',                          RTGETOPT_REQ_NOTHING },
     2281};
     2282
     2283/** the 'play' command option help. */
     2284static DECLCALLBACK(const char *) audioTestCmdPlayHelp(PCRTGETOPTDEF pOpt)
     2285{
     2286    switch (pOpt->iShort)
     2287    {
     2288        case 'b': return "The audio backend to use.";
     2289        case 'd': return "Go via DrvAudio instead of directly interfacing with the backend.";
     2290        default:  return NULL;
     2291    }
     2292}
     2293
     2294/**
    20982295 * The 'play' command handler.
    20992296 *
     
    21042301static DECLCALLBACK(RTEXITCODE) audioTestCmdPlayHandler(int argc, char **argv)
    21052302{
    2106     /*
    2107      * Parse arguments.
    2108      */
    21092303    /* Option values: */
    21102304    PCPDMDRVREG pDrvReg           = g_aBackends[0].pDrvReg;
     
    21122306    uint32_t    cMsPreBuffer      = UINT32_MAX;
    21132307    uint32_t    cMsSchedulingHint = UINT32_MAX;
    2114 
     2308    bool        fWithDrvAudio     = false;
     2309
     2310    /* Init option state: */
    21152311    RTGETOPTSTATE GetState;
    21162312    int rc = RTGetOptInit(&GetState, argc, argv, g_aCmdPlayOptions, RT_ELEMENTS(g_aCmdPlayOptions),
     
    21182314    AssertRCReturn(rc, RTEXITCODE_INIT);
    21192315
     2316    /* Argument processing loop: */
    21202317    RTGETOPTUNION ValueUnion;
    21212318    while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0)
     
    21362333                break;
    21372334
     2335            case 'd':
     2336                fWithDrvAudio = true;
     2337                break;
     2338
    21382339            case VINF_GETOPT_NOT_OPTION:
    21392340            {
    2140                 RTEXITCODE rcExit = audioTestPlayOne(ValueUnion.psz, pDrvReg, cMsBufferSize, cMsPreBuffer, cMsSchedulingHint);
     2341                RTEXITCODE rcExit = audioTestPlayOne(ValueUnion.psz, pDrvReg, cMsBufferSize, cMsPreBuffer,
     2342                                                     cMsSchedulingHint, fWithDrvAudio);
    21412343                if (rcExit != RTEXITCODE_SUCCESS)
    21422344                    return rcExit;
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