VirtualBox

Changeset 89431 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jun 1, 2021 12:57:36 PM (4 years ago)
Author:
vboxsync
Message:

Audio/ValKit: More infrastructure code. bugref:10008

Location:
trunk/src/VBox
Files:
8 edited

Legend:

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

    r89389 r89431  
    546546{
    547547    PAUDIOTESTERRORENTRY pEntry = (PAUDIOTESTERRORENTRY)RTMemAlloc(sizeof(AUDIOTESTERRORENTRY));
    548     AssertReturn(pEntry, VERR_NO_MEMORY);
     548    AssertPtrReturn(pEntry, VERR_NO_MEMORY);
    549549
    550550    if (RTStrPrintf2V(pEntry->szDesc, sizeof(pEntry->szDesc), pszDesc, args) < 0)
     
    633633{
    634634    return RTPathJoin(pszPathAbs, cbPathAbs, pSet->szPathAbs, pszObjName);
     635}
     636
     637/**
     638 * Returns the tag of a test set.
     639 *
     640 * @returns Test set tag.
     641 * @param   pSet                Test set to return tag for.
     642 */
     643const char *AudioTestSetGetTag(PAUDIOTESTSET pSet)
     644{
     645    return pSet->szTag;
    635646}
    636647
     
    746757        if (RT_SUCCESS(rc))
    747758        {
     759            PAUDIOTESTOBJMETA pMeta, pMetaNext;
     760            RTListForEachSafe(&pObj->lstMeta, pMeta, pMetaNext, AUDIOTESTOBJMETA, Node)
     761            {
     762                switch (pMeta->enmType)
     763                {
     764                    case AUDIOTESTOBJMETADATATYPE_STRING:
     765                    {
     766                        RTStrFree((char *)pMeta->pvMeta);
     767                        break;
     768                    }
     769
     770                    default:
     771                        AssertFailed();
     772                        break;
     773                }
     774
     775                RTListNodeRemove(&pMeta->Node);
     776                RTMemFree(pMeta);
     777            }
     778
    748779            RTListNodeRemove(&pObj->Node);
    749780            RTMemFree(pObj);
     
    870901        rc = audioTestManifestWrite(pSet, "obj_name=%s\n", pObj->szName);
    871902        AssertRCReturn(rc, rc);
     903
     904        switch (pObj->enmType)
     905        {
     906            case AUDIOTESTOBJTYPE_FILE:
     907            {
     908                rc = audioTestManifestWrite(pSet, "obj_size=%RU64\n", pObj->File.cbSize);
     909                AssertRCReturn(rc, rc);
     910                break;
     911            }
     912
     913            default:
     914                AssertFailed();
     915                break;
     916        }
     917
     918        /*
     919         * Write all meta data.
     920         */
     921        PAUDIOTESTOBJMETA pMeta;
     922        RTListForEach(&pObj->lstMeta, pMeta, AUDIOTESTOBJMETA, Node)
     923        {
     924            switch (pMeta->enmType)
     925            {
     926                case AUDIOTESTOBJMETADATATYPE_STRING:
     927                {
     928                    rc = audioTestManifestWrite(pSet, (const char *)pMeta->pvMeta);
     929                    AssertRCReturn(rc, rc);
     930                    break;
     931                }
     932
     933                default:
     934                    AssertFailed();
     935                    break;
     936            }
     937        }
    872938    }
    873939
     
    9381004    AssertPtrReturn(pObj, VERR_NO_MEMORY);
    9391005
     1006    RTListInit(&pObj->lstMeta);
     1007
    9401008    if (RTStrPrintf2(pObj->szName, sizeof(pObj->szName), "%04RU32-%s", pSet->cObj, pszName) <= 0)
    9411009        AssertFailedReturn(VERR_BUFFER_OVERFLOW);
     
    9961064
    9971065/**
     1066 * Adds meta data to a test object as a string, va_list version.
     1067 *
     1068 * @returns VBox status code.
     1069 * @param   pObj                Test object to add meta data for.
     1070 * @param   pszFormat           Format string to add.
     1071 * @param   va_list             Variable arguments list to use for the format string.
     1072 */
     1073static int audioTestSetObjAddMetadataStrV(PAUDIOTESTOBJ pObj, const char *pszFormat, va_list va)
     1074{
     1075    PAUDIOTESTOBJMETA pMeta = (PAUDIOTESTOBJMETA)RTMemAlloc(sizeof(AUDIOTESTOBJMETA));
     1076    AssertPtrReturn(pMeta, VERR_NO_MEMORY);
     1077
     1078    pMeta->pvMeta = RTStrAPrintf2V(pszFormat, va);
     1079    AssertPtrReturn(pMeta->pvMeta, VERR_BUFFER_OVERFLOW);
     1080    pMeta->cbMeta = RTStrNLen((const char *)pMeta->pvMeta, RTSTR_MAX);
     1081
     1082    pMeta->enmType = AUDIOTESTOBJMETADATATYPE_STRING;
     1083
     1084    RTListAppend(&pObj->lstMeta, &pMeta->Node);
     1085
     1086    return VINF_SUCCESS;
     1087}
     1088
     1089/**
     1090 * Adds meta data to a test object as a string.
     1091 *
     1092 * @returns VBox status code.
     1093 * @param   pObj                Test object to add meta data for.
     1094 * @param   pszFormat           Format string to add.
     1095 * @param   ...                 Variable arguments for the format string.
     1096 */
     1097int AudioTestSetObjAddMetadataStr(PAUDIOTESTOBJ pObj, const char *pszFormat, ...)
     1098{
     1099    va_list va;
     1100
     1101    va_start(va, pszFormat);
     1102    int rc = audioTestSetObjAddMetadataStrV(pObj, pszFormat, va);
     1103    va_end(va);
     1104
     1105    return rc;
     1106}
     1107
     1108/**
    9981109 * Closes an opened audio test object.
    9991110 *
     
    10131124    if (RTFileIsValid(pObj->File.hFile))
    10141125    {
     1126        pObj->File.cbSize = RTFileTell(pObj->File.hFile);
     1127
    10151128        rc = RTFileClose(pObj->File.hFile);
    10161129        pObj->File.hFile = NIL_RTFILE;
     
    10201133}
    10211134
     1135/**
     1136 * Begins a new test of a test set.
     1137 *
     1138 * @returns VBox status code.
     1139 * @param   pSet                Test set to begin new test for.
     1140 * @param   pszDesc             Test description.
     1141 * @param   pParms              Test parameters to use.
     1142 * @param   ppEntry             Where to return the new test handle.
     1143 */
    10221144int AudioTestSetTestBegin(PAUDIOTESTSET pSet, const char *pszDesc, PAUDIOTESTPARMS pParms, PAUDIOTESTENTRY *ppEntry)
    10231145{
     
    10951217}
    10961218
     1219/**
     1220 * Marks a running test as failed.
     1221 *
     1222 * @returns VBox status code.
     1223 * @param   pEntry              Test to mark.
     1224 * @param   rc                  Error code.
     1225 * @param   pszErr              Error description.
     1226 */
    10971227int AudioTestSetTestFailed(PAUDIOTESTENTRY pEntry, int rc, const char *pszErr)
    10981228{
     
    11131243}
    11141244
     1245/**
     1246 * Marks a running test as successfully done.
     1247 *
     1248 * @returns VBox status code.
     1249 * @param   pEntry              Test to mark.
     1250 */
    11151251int AudioTestSetTestDone(PAUDIOTESTENTRY pEntry)
    11161252{
     
    11431279    /** @todo Check and deny if \a pszOutDir is part of the set's path. */
    11441280
     1281    int rc = RTDirCreateFullPath(pszOutDir, 0755);
     1282    if (RT_FAILURE(rc))
     1283        return rc;
     1284
    11451285    char szOutName[RT_ELEMENTS(AUDIOTEST_PATH_PREFIX_STR) + AUDIOTEST_TAG_MAX + 16];
    11461286    if (RTStrPrintf2(szOutName, sizeof(szOutName), "%s-%s%s",
     
    11491289
    11501290    char szOutPath[RTPATH_MAX];
    1151     int rc = RTPathJoin(szOutPath, sizeof(szOutPath), pszOutDir, szOutName);
     1291    rc = RTPathJoin(szOutPath, sizeof(szOutPath), pszOutDir, szOutName);
    11521292    AssertRCReturn(rc, rc);
    11531293
     
    11551295    unsigned    cArgs = 0;
    11561296
    1157     apszArgs[cArgs++] = "AudioTest";
     1297    apszArgs[cArgs++] = "vkat";
    11581298    apszArgs[cArgs++] = "--create";
    11591299    apszArgs[cArgs++] = "--gzip";
     
    12141354    unsigned    cArgs = 0;
    12151355
    1216     apszArgs[cArgs++] = "AudioTest";
     1356    apszArgs[cArgs++] = "vkat";
    12171357    apszArgs[cArgs++] = "--extract";
    12181358    apszArgs[cArgs++] = "--gunzip";
  • trunk/src/VBox/Devices/Audio/AudioTest.h

    r89387 r89431  
    170170typedef struct AUDIOTESTOBJFILE
    171171{
    172     RTFILE hFile;
     172    /** File handle. */
     173    RTFILE              hFile;
     174    /** Total size (in bytes). */
     175    size_t              cbSize;
    173176} AUDIOTESTOBJFILE;
    174177/** Pointer to an audio test object file. */
    175178typedef AUDIOTESTOBJFILE *PAUDIOTESTOBJFILE;
     179
     180/**
     181 * Enumeration for an audio test object meta data type.
     182 */
     183typedef enum AUDIOTESTOBJMETADATATYPE
     184{
     185    /** Unknown / invalid, do not use. */
     186    AUDIOTESTOBJMETADATATYPE_INVALID = 0,
     187    /** Meta data is an UTF-8 string. */
     188    AUDIOTESTOBJMETADATATYPE_STRING,
     189    /** The usual 32-bit hack. */
     190    AUDIOTESTOBJMETADATATYPE_32BIT_HACK = 0x7fffffff
     191} AUDIOTESTOBJMETADATATYPE;
     192
     193/**
     194 * Structure for keeping a meta data block.
     195 */
     196typedef struct AUDIOTESTOBJMETA
     197{
     198    /** List node. */
     199    RTLISTNODE                Node;
     200    /** Meta data type. */
     201    AUDIOTESTOBJMETADATATYPE  enmType;
     202    /** Meta data block. */
     203    void                     *pvMeta;
     204    /** Size (in bytes) of \a pvMeta. */
     205    size_t                    cbMeta;
     206} AUDIOTESTOBJMETA;
     207/** Pointer to an audio test object file. */
     208typedef AUDIOTESTOBJMETA *PAUDIOTESTOBJMETA;
    176209
    177210/**
     
    193226    /** The object type. */
    194227    AUDIOTESTOBJTYPE     enmType;
     228    /** Meta data list. */
     229    RTLISTANCHOR         lstMeta;
    195230    /** Union for holding the object type-specific data. */
    196231    union
     
    323358int    AudioTestSetObjCreateAndRegister(PAUDIOTESTSET pSet, const char *pszName, PAUDIOTESTOBJ *ppObj);
    324359int    AudioTestSetObjWrite(PAUDIOTESTOBJ pObj, void *pvBuf, size_t cbBuf);
     360int    AudioTestSetObjAddMetadataStr(PAUDIOTESTOBJ pObj, const char *pszFormat, ...);
    325361int    AudioTestSetObjClose(PAUDIOTESTOBJ pObj);
    326362
     
    334370int    AudioTestSetClose(PAUDIOTESTSET pSet);
    335371int    AudioTestSetWipe(PAUDIOTESTSET pSet);
     372const char *AudioTestSetGetTag(PAUDIOTESTSET pSet);
    336373bool   AudioTestSetIsPacked(const char *pszPath);
    337374int    AudioTestSetPack(PAUDIOTESTSET pSet, const char *pszOutDir, char *pszFileName, size_t cbFileName);
  • trunk/src/VBox/Devices/Audio/AudioTestService.cpp

    r89228 r89431  
    474474    int rc;
    475475    if (pPktHdr->cb == sizeof(ATSPKTHDR))
     476    {
    476477        rc = atsReplyAck(pThis, pClient, pPktHdr);
     478    }
    477479    else
    478480        rc = atsReplyBadSize(pThis, pClient, pPktHdr, sizeof(ATSPKTHDR));
     
    514516        pClient->enmState = ATSCLIENTSTATE_READY;
    515517    }
     518
     519    return rc;
     520}
     521
     522/**
     523 * Verifies and acknowledges a "TSET BEG" request.
     524 *
     525 * @returns IPRT status code.
     526 * @param   pThis               The ATS instance.
     527 * @param   pClient             The ATS client structure.
     528 * @param   pPktHdr             The test set begin packet.
     529 */
     530static int atsDoTestSetBegin(PATSSERVER pThis, PATSCLIENTINST pClient, PCATSPKTHDR pPktHdr)
     531{
     532    if (pPktHdr->cb != sizeof(ATSPKTREQTSETBEG))
     533        return atsReplyBadSize(pThis, pClient, pPktHdr, sizeof(ATSPKTREQTSETBEG));
     534
     535    PATSPKTREQTSETBEG pReq = (PATSPKTREQTSETBEG)pPktHdr;
     536
     537    int rc = VINF_SUCCESS;
     538
     539    if (pThis->Callbacks.pfnTestSetBegin)
     540    {
     541        rc = pThis->Callbacks.pfnTestSetBegin(pThis->Callbacks.pvUser, pReq->szTag);
     542        if (RT_FAILURE(rc))
     543            return atsReplyRC(pThis, pClient, pPktHdr, rc, "Beginning test set '%s' failed", pReq->szTag);
     544    }
     545
     546    if (RT_SUCCESS(rc))
     547    {
     548        rc = atsReplyAck(pThis, pClient, pPktHdr);
     549    }
     550    else
     551        rc = atsReplyRC(pThis, pClient, pPktHdr, rc, "Beginning test set failed");
     552
     553    return rc;
     554}
     555
     556/**
     557 * Verifies and acknowledges a "TSET END" request.
     558 *
     559 * @returns IPRT status code.
     560 * @param   pThis               The ATS instance.
     561 * @param   pClient             The ATS client structure.
     562 * @param   pPktHdr             The test set end packet.
     563 */
     564static int atsDoTestSetEnd(PATSSERVER pThis, PATSCLIENTINST pClient, PCATSPKTHDR pPktHdr)
     565{
     566    if (pPktHdr->cb != sizeof(ATSPKTREQTSETEND))
     567        return atsReplyBadSize(pThis, pClient, pPktHdr, sizeof(ATSPKTREQTSETEND));
     568
     569    PATSPKTREQTSETEND pReq = (PATSPKTREQTSETEND)pPktHdr;
     570
     571    int rc = VINF_SUCCESS;
     572
     573    if (pThis->Callbacks.pfnTestSetEnd)
     574    {
     575        rc = pThis->Callbacks.pfnTestSetEnd(pThis->Callbacks.pvUser, pReq->szTag);
     576        if (RT_FAILURE(rc))
     577            return atsReplyRC(pThis, pClient, pPktHdr, rc, "Ending test set '%s' failed", pReq->szTag);
     578    }
     579    if (RT_SUCCESS(rc))
     580    {
     581        rc = atsReplyAck(pThis, pClient, pPktHdr);
     582    }
     583    else
     584        rc = atsReplyRC(pThis, pClient, pPktHdr, rc, "Ending test set failed");
    516585
    517586    return rc;
     
    574643    else if (atsIsSameOpcode(pPktHdr, ATSPKT_OPCODE_BYE))
    575644        rc = atsDoBye(pThis, pClient, pPktHdr);
     645    /* Test set handling: */
     646    else if (atsIsSameOpcode(pPktHdr, ATSPKT_OPCODE_TESTSET_BEGIN))
     647        rc = atsDoTestSetBegin(pThis, pClient, pPktHdr);
     648    else if (atsIsSameOpcode(pPktHdr, ATSPKT_OPCODE_TESTSET_END))
     649        rc = atsDoTestSetEnd(pThis, pClient, pPktHdr);
    576650    /* Audio testing: */
    577651    else if (atsIsSameOpcode(pPktHdr, ATSPKT_OPCODE_TONE_PLAY))
  • trunk/src/VBox/Devices/Audio/AudioTestService.h

    r89399 r89431  
    3333typedef struct ATSCALLBACKS
    3434{
     35    /**
     36     * Begins a test set. Optional.
     37     *
     38     * @returns VBox status code.
     39     * @param   pvUser          User-supplied pointer to context data. Optional.
     40     * @param   pszTag          Tag of test set to begin.
     41     */
     42    DECLR3CALLBACKMEMBER(int, pfnTestSetBegin, (void const *pvUser, const char *pszTag));
     43
     44    /**
     45     * Ends the current test set. Optional.
     46     *
     47     * @returns VBox status code.
     48     * @param   pvUser          User-supplied pointer to context data. Optional.
     49     * @param   pszTag          Tag of test set to end.
     50     */
     51    DECLR3CALLBACKMEMBER(int, pfnTestSetEnd,   (void const *pvUser, const char *pszTag));
     52
    3553    /**
    3654     * Plays a test tone.
     
    7997typedef ATSSERVER *PATSSERVER;
    8098
    81 
    8299int AudioTestSvcInit(PATSSERVER pThis, PCATSCALLBACKS pCallbacks);
    83100int AudioTestSvcDestroy(PATSSERVER pThis);
  • trunk/src/VBox/Devices/Audio/AudioTestServiceClient.cpp

    r89399 r89431  
    305305
    306306/**
     307 * Tells the server to begin a new test set.
     308 *
     309 * @returns VBox status code.
     310 * @param   pClient             Client to issue command for.
     311 * @param   pszTag              Tag to use for the test set to begin.
     312 */
     313int AudioTestSvcClientTestSetBegin(PATSCLIENT pClient, const char *pszTag)
     314{
     315    ATSPKTREQTSETBEG Req;
     316
     317    int rc = RTStrCopy(Req.szTag, sizeof(Req.szTag), pszTag);
     318    AssertRCReturn(rc, rc);
     319
     320    audioTestSvcClientReqHdrInit(&Req.Hdr, sizeof(Req), ATSPKT_OPCODE_TESTSET_BEGIN, 0);
     321
     322    rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req), NULL, 0);
     323    if (RT_SUCCESS(rc))
     324        rc = audioTestSvcClientRecvAck(pClient);
     325
     326    return rc;
     327}
     328
     329/**
     330 * Tells the server to end a runing test set.
     331 *
     332 * @returns VBox status code.
     333 * @param   pClient             Client to issue command for.
     334 * @param   pszTag              Tag of test set to end.
     335 */
     336int AudioTestSvcClientTestSetEnd(PATSCLIENT pClient, const char *pszTag)
     337{
     338    ATSPKTREQTSETEND Req;
     339
     340    int rc = RTStrCopy(Req.szTag, sizeof(Req.szTag), pszTag);
     341    AssertRCReturn(rc, rc);
     342
     343    audioTestSvcClientReqHdrInit(&Req.Hdr, sizeof(Req), ATSPKT_OPCODE_TESTSET_END, 0);
     344
     345    rc = audioTestSvcClientSendMsg(pClient, &Req, sizeof(Req), NULL, 0);
     346    if (RT_SUCCESS(rc))
     347        rc = audioTestSvcClientRecvAck(pClient);
     348
     349    return rc;
     350}
     351
     352/**
    307353 * Tells the server to play a (test) tone.
    308354 *
  • trunk/src/VBox/Devices/Audio/AudioTestServiceClient.h

    r89399 r89431  
    3131
    3232int AudioTestSvcClientConnect(PATSCLIENT pClient, const char *pszAddr, uint32_t uPort);
     33int AudioTestSvcClientTestSetBegin(PATSCLIENT pClient, const char *pszTag);
     34int AudioTestSvcClientTestSetEnd(PATSCLIENT pClient, const char *pszTag);
    3335int AudioTestSvcClientTonePlay(PATSCLIENT pClient, PPDMAUDIOSTREAMCFG pStreamCfg, PAUDIOTESTTONEPARMS pToneParms);
    3436int AudioTestSvcClientClose(PATSCLIENT pClient);
  • trunk/src/VBox/Devices/Audio/AudioTestServiceProtocol.h

    r89380 r89431  
    121121/* No additional structures for BYE. */
    122122
     123#define ATSPKT_OPCODE_TESTSET_BEGIN     "TSET BEG"
     124
     125/**
     126 * The TSET BEG request structure.
     127 */
     128typedef struct ATSPKTREQTSETBEG
     129{
     130    /** Embedded packet header. */
     131    ATSPKTHDR          Hdr;
     132    /** Audio test set tag to use. */
     133    char               szTag[AUDIOTEST_TAG_MAX];
     134} ATSPKTREQTSETBEG;
     135AssertCompileSizeAlignment(ATSPKTREQTSETBEG, ATSPKT_ALIGNMENT);
     136/** Pointer to a TSET BEG reply structure. */
     137typedef ATSPKTREQTSETBEG *PATSPKTREQTSETBEG;
     138
     139#define ATSPKT_OPCODE_TESTSET_END       "TSET END"
     140
     141/**
     142 * The TSET END request structure.
     143 */
     144typedef struct ATSPKTREQTSETEND
     145{
     146    /** Embedded packet header. */
     147    ATSPKTHDR          Hdr;
     148    /** Audio test set tag to use. */
     149    char               szTag[AUDIOTEST_TAG_MAX];
     150} ATSPKTREQTSETEND;
     151AssertCompileSizeAlignment(ATSPKTREQTSETEND, ATSPKT_ALIGNMENT);
     152/** Pointer to a TSET STA reply structure. */
     153typedef ATSPKTREQTSETEND *PATSPKTREQTSETEND;
     154
    123155#define ATSPKT_OPCODE_TONE_PLAY         "TNPLY   "
    124156
  • trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp

    r89417 r89431  
    179179    AUDIOTESTMODE           enmMode;
    180180    /** Output path for storing the test environment's final test files. */
     181    char                    szTag[AUDIOTEST_TAG_MAX];
     182    /** Output path for storing the test environment's final test files. */
    181183    char                    szPathOut[RTPATH_MAX];
    182184    /** Temporary path for this test environment. */
     
    235237*********************************************************************************************************************************/
    236238static int audioTestCombineParms(PAUDIOTESTPARMS pBaseParms, PAUDIOTESTPARMS pOverrideParms);
    237 static int audioTestPlayTone(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms);
     239static int audioTestCreateStreamDefaultOut(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PPDMAUDIOPCMPROPS pProps);
    238240static int audioTestStreamDestroy(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream);
     241static int audioTestDevicesEnumerateAndCheck(PAUDIOTESTENV pTstEnv, const char *pszDev, PPDMAUDIOHOSTDEV *ppDev);
     242static int audioTestEnvPrologue(PAUDIOTESTENV pTstEnv);
    239243
    240244static RTEXITCODE audioTestUsage(PRTSTREAM pStrm);
     
    393397
    394398/*********************************************************************************************************************************
     399*   Test Primitives                                                                                                              *
     400*********************************************************************************************************************************/
     401
     402/**
     403 * Plays a test tone on a specific audio test stream.
     404 *
     405 * @returns VBox status code.
     406 * @param   pTstEnv             Test environment to use for running the test.
     407 * @param   pStream             Stream to use for playing the tone.
     408 * @param   pParms              Tone parameters to use.
     409 *
     410 * @note    Blocking function.
     411 */
     412static int audioTestPlayTone(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms)
     413{
     414    AUDIOTESTTONE TstTone;
     415    AudioTestToneInit(&TstTone, &pParms->Props, pParms->dbFreqHz);
     416
     417    const char *pcszPathOut = pTstEnv->Set.szPathAbs;
     418
     419    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Playing test tone (tone frequency is %RU16Hz, %RU32ms)\n", (uint16_t)pParms->dbFreqHz, pParms->msDuration);
     420    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG,  "Writing to '%s'\n", pcszPathOut);
     421
     422    /** @todo Use .WAV here? */
     423    PAUDIOTESTOBJ pObj;
     424    int rc = AudioTestSetObjCreateAndRegister(&pTstEnv->Set, "tone-play.pcm", &pObj);
     425    AssertRCReturn(rc, rc);
     426
     427    if (audioTestDriverStackStreamIsOkay(&pTstEnv->DrvStack, pStream->pStream))
     428    {
     429        uint32_t cbBuf;
     430        uint8_t  abBuf[_4K];
     431
     432        const uint16_t cSchedulingMs = RTRandU32Ex(10, 80); /* Choose a random scheduling (in ms). */
     433        const uint32_t cbPerMs       = PDMAudioPropsMilliToBytes(&pParms->Props, cSchedulingMs);
     434                size_t cbToWrite     = PDMAudioPropsMilliToBytes(&pParms->Props, pParms->msDuration);
     435
     436        AudioTestSetObjAddMetadataStr(pObj, "schedule_ms=%RU16", cSchedulingMs);
     437
     438        while (cbToWrite)
     439        {
     440            uint32_t cbWritten    = 0;
     441            uint32_t cbToGenerate = RT_MIN(cbToWrite, RT_MIN(cbPerMs, sizeof(abBuf)));
     442            Assert(cbToGenerate);
     443
     444            rc = AudioTestToneGenerate(&TstTone, abBuf, cbToGenerate, &cbBuf);
     445            if (RT_SUCCESS(rc))
     446            {
     447                /* Write stuff to disk before trying to play it. Help analysis later. */
     448                rc = AudioTestSetObjWrite(pObj, abBuf, cbBuf);
     449                if (RT_SUCCESS(rc))
     450                    rc = audioTestDriverStackStreamPlay(&pTstEnv->DrvStack, pStream->pStream,
     451                                                        abBuf, cbBuf, &cbWritten);
     452            }
     453
     454            if (RT_FAILURE(rc))
     455                break;
     456
     457            RTThreadSleep(cSchedulingMs);
     458
     459            Assert(cbToWrite >= cbWritten);
     460            cbToWrite -= cbWritten;
     461        }
     462    }
     463    else
     464        rc = VERR_AUDIO_STREAM_NOT_READY;
     465
     466    int rc2 = AudioTestSetObjClose(pObj);
     467    if (RT_SUCCESS(rc))
     468        rc = rc2;
     469
     470    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Play tone done\n");
     471
     472    return rc;
     473}
     474
     475/*********************************************************************************************************************************
    395476*   ATS Callback Implementations                                                                                                 *
    396477*********************************************************************************************************************************/
    397478
    398 /**
    399  * Note: Called within server (client serving) thread.
    400  */
    401 static DECLCALLBACK(int) audioTestSvcTonePlayCallback(void const *pvUser, PPDMAUDIOSTREAMCFG pStreamCfg, PAUDIOTESTTONEPARMS pToneParms)
     479/** @copydoc ATSCALLBACKS::pfnTestSetBegin */
     480static DECLCALLBACK(int) audioTestSvcTestSetBeginCallback(void const *pvUser, const char *pszTag)
    402481{
    403482    PATSCALLBACKCTX pCtx    = (PATSCALLBACKCTX)pvUser;
    404483    PAUDIOTESTENV   pTstEnv = pCtx->pTstEnv;
    405484
     485    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Beginning test set '%s'\n", pszTag);
     486
     487    return AudioTestSetCreate(&pTstEnv->Set, pTstEnv->szPathTemp, pszTag);
     488}
     489
     490/** @copydoc ATSCALLBACKS::pfnTestSetEnd */
     491static DECLCALLBACK(int) audioTestSvcTestSetEndCallback(void const *pvUser, const char *pszTag)
     492{
     493    RT_NOREF(pszTag);
     494
     495    PATSCALLBACKCTX pCtx    = (PATSCALLBACKCTX)pvUser;
     496    PAUDIOTESTENV   pTstEnv = pCtx->pTstEnv;
     497
     498    RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Ending test set '%s'\n", pszTag);
     499
     500    return audioTestEnvPrologue(pTstEnv);
     501}
     502
     503/** @copydoc ATSCALLBACKS::pfnTonePlay */
     504static DECLCALLBACK(int) audioTestSvcTonePlayCallback(void const *pvUser, PPDMAUDIOSTREAMCFG pStreamCfg, PAUDIOTESTTONEPARMS pToneParms)
     505{
     506    PATSCALLBACKCTX pCtx    = (PATSCALLBACKCTX)pvUser;
     507    PAUDIOTESTENV   pTstEnv = pCtx->pTstEnv;
     508
    406509    AUDIOTESTTONE TstTone;
    407510    AudioTestToneInitRandom(&TstTone, &pStreamCfg->Props);
    408511
    409     int rc;
    410 
    411     const PPDMAUDIOSTREAM pStream = pTstEnv->aStreams[0].pStream; /** @todo Make this dynamic. */
    412 
    413     if (audioTestDriverStackStreamIsOkay(&pTstEnv->DrvStack, pStream))
    414     {
    415         uint32_t cbBuf;
    416         uint8_t  abBuf[_4K];
    417 
    418         const uint64_t tsStartMs     = RTTimeMilliTS();
    419         const uint16_t cSchedulingMs = RTRandU32Ex(10, 80); /* Chose a random scheduling (in ms). */
    420         const uint32_t cbPerMs       = PDMAudioPropsMilliToBytes(&pStream->Props, cSchedulingMs);
    421 
    422         do
    423         {
    424             rc = AudioTestToneGenerate(&TstTone, abBuf, RT_MIN(cbPerMs, sizeof(abBuf)), &cbBuf);
     512    const PAUDIOTESTSTREAM pTstStream = &pTstEnv->aStreams[0]; /** @todo Make this dynamic. */
     513
     514    int rc = audioTestCreateStreamDefaultOut(pTstEnv, pTstStream, &pStreamCfg->Props);
     515    if (RT_SUCCESS(rc))
     516    {
     517        AUDIOTESTPARMS TstParms;
     518        RT_ZERO(TstParms);
     519        TstParms.enmType  = AUDIOTESTTYPE_TESTTONE_PLAY;
     520        TstParms.enmDir   = PDMAUDIODIR_OUT;
     521        TstParms.TestTone = *pToneParms;
     522
     523        PAUDIOTESTENTRY pTst;
     524        rc = AudioTestSetTestBegin(&pTstEnv->Set, "Playing test tone", &TstParms, &pTst);
     525        if (RT_SUCCESS(rc))
     526        {
     527            rc = audioTestPlayTone(pTstEnv, pTstStream, pToneParms);
    425528            if (RT_SUCCESS(rc))
    426529            {
    427                 uint32_t cbWritten;
    428                 rc = audioTestDriverStackStreamPlay(&pTstEnv->DrvStack, pStream, abBuf, cbBuf, &cbWritten);
     530                AudioTestSetTestDone(pTst);
    429531            }
    430 
    431             if (RTTimeMilliTS() - tsStartMs >= pToneParms->msDuration)
    432                 break;
    433 
    434             if (RT_FAILURE(rc))
    435                 break;
    436 
    437             RTThreadSleep(cSchedulingMs);
    438 
    439         } while (RT_SUCCESS(rc));
     532            else
     533                AudioTestSetTestFailed(pTst, rc, "Playing tone failed");
     534        }
     535
     536        int rc2 = audioTestStreamDestroy(pTstEnv, pTstStream);
     537        if (RT_SUCCESS(rc))
     538            rc = rc2;
    440539    }
    441540    else
    442         rc = VERR_AUDIO_STREAM_NOT_READY;
     541        RTTestFailed(g_hTest, "Error creating output stream, rc=%Rrc\n", rc);
    443542
    444543    return rc;
     
    464563                            const char *pszTcpAddr, uint32_t uTcpPort)
    465564{
    466     PDMAudioHostEnumInit(&pTstEnv->DevEnum);
    467 
    468     int rc = audioTestDriverStackInit(&pTstEnv->DrvStack, pDrvReg, fWithDrvAudio);
    469     if (RT_FAILURE(rc))
    470         return rc;
    471 
    472565    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test mode is '%s'\n", pTstEnv->enmMode == AUDIOTESTMODE_HOST ? "host" : "guest");
    473566    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Using tag '%s'\n", pszTag);
     
    475568    RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Temp directory is '%s'\n", pTstEnv->szPathTemp);
    476569
     570    int rc = VINF_SUCCESS;
     571
     572    PDMAudioHostEnumInit(&pTstEnv->DevEnum);
     573
     574    /* Only the guest mode needs initializing the driver stack. */
     575    const bool fUseDriverStack = pTstEnv->enmMode == AUDIOTESTMODE_GUEST;
     576    if (fUseDriverStack)
     577    {
     578        rc = audioTestDriverStackInit(&pTstEnv->DrvStack, pDrvReg, fWithDrvAudio);
     579        if (RT_FAILURE(rc))
     580            return rc;
     581
     582        PPDMAUDIOHOSTDEV pDev;
     583        rc = audioTestDevicesEnumerateAndCheck(pTstEnv, NULL /* pszDevice */, &pDev); /** @todo Implement device checking. */
     584        if (RT_FAILURE(rc))
     585            return rc;
     586    }
     587
    477588    char szPathTemp[RTPATH_MAX];
    478589    if (   !strlen(pTstEnv->szPathTemp)
     
    488599        rc = RTPathJoin(pTstEnv->szPathOut, sizeof(pTstEnv->szPathOut), szPathTemp, "vkat");
    489600
    490     if (RT_SUCCESS(rc))
    491         rc = AudioTestSetCreate(&pTstEnv->Set, pTstEnv->szPathTemp, pszTag);
    492 
    493601    if (RT_FAILURE(rc))
    494602        return rc;
     
    501609
    502610        ATSCALLBACKS Callbacks;
    503         Callbacks.pfnTonePlay = audioTestSvcTonePlayCallback;
    504         Callbacks.pvUser      = &Ctx;
     611        Callbacks.pfnTestSetBegin = audioTestSvcTestSetBeginCallback;
     612        Callbacks.pfnTestSetEnd   = audioTestSvcTestSetEndCallback;
     613        Callbacks.pfnTonePlay     = audioTestSvcTonePlayCallback;
     614        Callbacks.pvUser          = &Ctx;
    505615
    506616        RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Starting ATS ...\n");
     
    511621        if (RT_FAILURE(rc))
    512622        {
    513             RTTestFailed(g_hTest, "Initializing ATS failed with %Rrc\n", rc);
     623            RTTestFailed(g_hTest, "Starting ATS failed with %Rrc\n", rc);
    514624            return rc;
    515625        }
    516 
    517         RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "ATS running\n");
    518 
    519         while (!g_fTerminated) /** @todo Implement signal handling. */
    520         {
    521             RTThreadSleep(100);
    522         }
    523 
    524         RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Shutting down ATS ...\n");
    525 
    526         int rc2 = AudioTestSvcShutdown(&pTstEnv->u.Guest.Srv);
    527         if (RT_SUCCESS(rc))
    528             rc = rc2;
    529     }
    530     else
     626    }
     627    else /* Host mode */
    531628    {
    532629        RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Connecting to ATS at %s:%RU32 ...\n", pszTcpAddr, uTcpPort);
     630
    533631        rc = AudioTestSvcClientConnect(&pTstEnv->u.Host.Client, pszTcpAddr, uTcpPort);
    534632        if (RT_FAILURE(rc))
     
    537635            return rc;
    538636        }
    539     }
    540 
    541     audioTestDriverStackDelete(&pTstEnv->DrvStack);
     637
     638        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Connected to ATS\n");
     639    }
     640
     641    if (   RT_FAILURE(rc)
     642        && fUseDriverStack)
     643        audioTestDriverStackDelete(&pTstEnv->DrvStack);
    542644
    543645    return rc;
     
    563665    }
    564666
     667    audioTestDriverStackDelete(&pTstEnv->DrvStack);
     668}
     669
     670/**
     671 * Closes, packs up and destroys a test environment.
     672 *
     673 * @returns VBox status code.
     674 * @param   pTstEnv             Test environment to handle.
     675 */
     676static int audioTestEnvPrologue(PAUDIOTESTENV pTstEnv)
     677{
     678    /* Before destroying the test environment, pack up the test set so
     679     * that it's ready for transmission. */
     680    char szFileOut[RTPATH_MAX];
     681    int rc = AudioTestSetPack(&pTstEnv->Set, pTstEnv->szPathOut, szFileOut, sizeof(szFileOut));
     682    if (RT_SUCCESS(rc))
     683        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test set packed up to '%s'\n", szFileOut);
     684
     685    /* Clean up. */
     686    AudioTestSetClose(&pTstEnv->Set);
     687
     688    int rc2 = AudioTestSetWipe(&pTstEnv->Set);
     689    if (RT_SUCCESS(rc))
     690        rc = rc2;
     691
    565692    AudioTestSetDestroy(&pTstEnv->Set);
    566     audioTestDriverStackDelete(&pTstEnv->DrvStack);
     693
     694    return rc;
    567695}
    568696
     
    812940
    813941/**
    814  * Plays a test tone on a specific audio test stream.
    815  *
    816  * @returns VBox status code.
    817  * @param   pTstEnv             Test environment to use for running the test.
    818  * @param   pStream             Stream to use for playing the tone.
    819  * @param   pParms              Tone parameters to use.
    820  *
    821  * @note    Blocking function.
    822  */
    823 static int audioTestPlayTone(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms)
    824 {
    825     AUDIOTESTTONE TstTone;
    826     AudioTestToneInit(&TstTone, &pParms->Props, pParms->dbFreqHz);
    827 
    828     const char *pcszPathOut = pTstEnv->Set.szPathAbs;
    829 
    830     RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Playing test tone (tone frequency is %RU16Hz, %RU32ms)\n", (uint16_t)pParms->dbFreqHz, pParms->msDuration);
    831     RTTestPrintf(g_hTest, RTTESTLVL_DEBUG,  "Writing to '%s'\n", pcszPathOut);
    832 
    833     /** @todo Use .WAV here? */
    834     PAUDIOTESTOBJ pObj;
    835     int rc = AudioTestSetObjCreateAndRegister(&pTstEnv->Set, "tone-play.pcm", &pObj);
    836     AssertRCReturn(rc, rc);
    837 
    838     if (audioTestDriverStackStreamIsOkay(&pTstEnv->DrvStack, pStream->pStream))
    839     {
    840         uint32_t cbBuf;
    841         uint8_t  abBuf[_4K];
    842 
    843         const uint64_t tsStartMs     = RTTimeMilliTS();
    844         const uint16_t cSchedulingMs = RTRandU32Ex(10, 80); /* Choose a random scheduling (in ms). */
    845         const uint32_t cbPerMs       = PDMAudioPropsMilliToBytes(&pParms->Props, cSchedulingMs);
    846 
    847         do
    848         {
    849             rc = AudioTestToneGenerate(&TstTone, abBuf, RT_MIN(cbPerMs, sizeof(abBuf)), &cbBuf);
    850             if (RT_SUCCESS(rc))
    851             {
    852                 /* Write stuff to disk before trying to play it. Help analysis later. */
    853                 rc = AudioTestSetObjWrite(pObj, abBuf, cbBuf);
    854                 if (RT_SUCCESS(rc))
    855                 {
    856                     uint32_t cbWritten;
    857                     rc = audioTestDriverStackStreamPlay(&pTstEnv->DrvStack, pStream->pStream,
    858                                                         abBuf, cbBuf, &cbWritten);
    859                 }
    860             }
    861 
    862             if (RTTimeMilliTS() - tsStartMs >= pParms->msDuration)
    863                 break;
    864 
    865             if (RT_FAILURE(rc))
    866                 break;
    867 
    868             RTThreadSleep(cSchedulingMs);
    869 
    870         } while (RT_SUCCESS(rc));
    871     }
    872     else
    873         rc = VERR_AUDIO_STREAM_NOT_READY;
    874 
    875     int rc2 = AudioTestSetObjClose(pObj);
    876     if (RT_SUCCESS(rc))
    877         rc = rc2;
    878 
    879     return rc;
    880 }
    881 
    882 /**
    883942 * Overrides audio test base parameters with another set.
    884943 *
     
    933992    int rc = VINF_SUCCESS;
    934993
    935     PAUDIOTESTSTREAM pStream = &pTstEnv->aStreams[0];
    936 
    937994    for (uint32_t i = 0; i < pTstParms->cIterations; i++)
    938995    {
     
    9431000        if (RT_SUCCESS(rc))
    9441001        {
    945             rc = audioTestCreateStreamDefaultOut(pTstEnv, pStream, &pTstParms->TestTone.Props);
    946             if (RT_SUCCESS(rc))
    947             {
    948                 rc = audioTestPlayTone(pTstEnv, pStream, &pTstParms->TestTone);
    949             }
    950 
    951             int rc2 = audioTestStreamDestroy(pTstEnv, pStream);
    952             if (RT_SUCCESS(rc))
    953                 rc = rc2;
    954 
     1002            PDMAUDIOSTREAMCFG Cfg;
     1003            RT_ZERO(Cfg);
     1004            /** @todo Add more parameters here? */
     1005            Cfg.Props = pTstParms->Props;
     1006
     1007            rc = AudioTestSvcClientTonePlay(&pTstEnv->u.Host.Client, &Cfg, &pTstParms->TestTone);
    9551008            if (RT_SUCCESS(rc))
    9561009            {
     
    11451198    int rc = VINF_SUCCESS;
    11461199
    1147     unsigned uSeq = 0;
    1148     for (unsigned i = 0; i < RT_ELEMENTS(g_aTests); i++)
    1149     {
    1150         int rc2 = audioTestOne(pTstEnv, &g_aTests[i], uSeq, pOverrideParms);
     1200    if (pTstEnv->enmMode == AUDIOTESTMODE_GUEST)
     1201    {
     1202        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "ATS running\n");
     1203
     1204        while (!g_fTerminated) /** @todo Implement signal handling. */
     1205        {
     1206            RTThreadSleep(100);
     1207        }
     1208
     1209        RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Shutting down ATS ...\n");
     1210
     1211        int rc2 = AudioTestSvcShutdown(&pTstEnv->u.Guest.Srv);
    11511212        if (RT_SUCCESS(rc))
    11521213            rc = rc2;
    1153 
    1154         if (!g_aTests[i].fExcluded)
    1155             uSeq++;
    1156     }
     1214    }
     1215    else if (pTstEnv->enmMode == AUDIOTESTMODE_HOST)
     1216    {
     1217        /* We have one single test set for all executed tests for now. */
     1218        rc = AudioTestSetCreate(&pTstEnv->Set, pTstEnv->szPathTemp, pTstEnv->szTag);
     1219        if (RT_SUCCESS(rc))
     1220        {
     1221            /* Copy back the (eventually generated) tag to the test environment. */
     1222            rc = RTStrCopy(pTstEnv->szTag, sizeof(pTstEnv->szTag), AudioTestSetGetTag(&pTstEnv->Set));
     1223            AssertRC(rc);
     1224
     1225            rc = AudioTestSvcClientTestSetBegin(&pTstEnv->u.Host.Client, pTstEnv->szTag);
     1226            if (RT_SUCCESS(rc))
     1227            {
     1228                unsigned uSeq = 0;
     1229                for (unsigned i = 0; i < RT_ELEMENTS(g_aTests); i++)
     1230                {
     1231                    int rc2 = audioTestOne(pTstEnv, &g_aTests[i], uSeq, pOverrideParms);
     1232                    if (RT_SUCCESS(rc))
     1233                        rc = rc2;
     1234
     1235                    if (!g_aTests[i].fExcluded)
     1236                        uSeq++;
     1237                }
     1238
     1239                int rc2 = AudioTestSvcClientTestSetEnd(&pTstEnv->u.Host.Client, pTstEnv->szTag);
     1240                if (RT_SUCCESS(rc))
     1241                    rc = rc2;
     1242            }
     1243
     1244            audioTestEnvPrologue(pTstEnv);
     1245        }
     1246    }
     1247    else
     1248        AssertFailed();
     1249
     1250    if (RT_FAILURE(rc))
     1251        RTTestFailed(g_hTest, "Test worker failed with %Rrc", rc);
    11571252
    11581253    return rc;
     
    11641259    switch (pOpt->iShort)
    11651260    {
    1166         case 'd':                 return "Go via DrvAudio instead of directly interfacing with the backend.";
    1167         case VKAT_TEST_OPT_DEV:   return "Use the specified audio device";
    1168         case 'e':                 return "Exclude the given test id from the list";
    1169         case 'a':                 return "Exclude all tests from the list (useful to enable single tests later with --include)";
    1170         case 'i':                 return "Include the given test id in the list";
     1261        case 'd':                    return "Go via DrvAudio instead of directly interfacing with the backend";
     1262        case VKAT_TEST_OPT_DEV:      return "Use the specified audio device";
     1263        case VKAT_TEST_OPT_ATS_ADDR: return "ATS address (hostname or IP) to connect to";
     1264        case VKAT_TEST_OPT_ATS_PORT: return "ATS port to connect to. Defaults to 6052 if not set";
     1265        case VKAT_TEST_OPT_MODE:     return "Specifies the mode this program runs at";
     1266        case 'e':                    return "Exclude the given test id from the list";
     1267        case 'a':                    return "Exclude all tests from the list (useful to enable single tests later with --include)";
     1268        case 'i':                    return "Include the given test id in the list";
    11711269    }
    11721270    return NULL;
     
    13361434    if (RT_SUCCESS(rc))
    13371435    {
    1338         PPDMAUDIOHOSTDEV pDev;
    1339         rc = audioTestDevicesEnumerateAndCheck(&TstEnv, pszDevice, &pDev);
    1340         if (RT_SUCCESS(rc))
    1341             audioTestWorker(&TstEnv, &TstCust);
    1342 
    1343         /* Before destroying the test environment, pack up the test set so
    1344          * that it's ready for transmission. */
    1345         char szFileOut[RTPATH_MAX];
    1346         rc = AudioTestSetPack(&TstEnv.Set, TstEnv.szPathOut, szFileOut, sizeof(szFileOut));
    1347         if (RT_SUCCESS(rc))
    1348             RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Test set packed up to '%s'\n", szFileOut);
    1349 
    1350 #ifndef DEBUG_andy
    1351         /* Clean up. */
    1352         AudioTestSetClose(&TstEnv.Set); /* wipe fails on windows if the manifest file is open*/
    1353 
    1354         int rc2 = AudioTestSetWipe(&TstEnv.Set);
    1355         AssertRC(rc2); /* Annoying, but not test-critical. */
    1356 #endif
     1436        audioTestWorker(&TstEnv, &TstCust);
    13571437        audioTestEnvDestroy(&TstEnv);
    13581438    }
     
    18631943                    rc = AudioTestSvcInit(&Srv, &Callbacks);
    18641944                    if (RT_SUCCESS(rc))
    1865                     {
    18661945                        rc = AudioTestSvcStart(&Srv);
    1867                         if (RT_SUCCESS(rc))
    1868                             RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "ATS running\n");
    1869                     }
    18701946                }
    18711947                else
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