Changeset 89054 in vbox for trunk/src/VBox/ValidationKit
- Timestamp:
- May 15, 2021 2:14:57 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 144394
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp
r89051 r89054 30 30 *********************************************************************************************************************************/ 31 31 #include <iprt/buildconfig.h> 32 #include <iprt/ctype.h> 32 33 #include <iprt/errcore.h> 33 34 #include <iprt/initterm.h> 34 35 #include <iprt/getopt.h> 36 #include <iprt/message.h> 35 37 #include <iprt/path.h> 36 #include <iprt/message.h>37 38 #include <iprt/process.h> 38 39 #include <iprt/rand.h> … … 54 55 55 56 /********************************************************************************************************************************* 56 * Defined Constants And Macros * 57 *********************************************************************************************************************************/ 58 59 60 /********************************************************************************************************************************* 61 * Prototypes * 57 * Structures and Typedefs * 62 58 *********************************************************************************************************************************/ 63 59 struct AUDIOTESTENV; 60 /** Pointer a audio test environment. */ 61 typedef AUDIOTESTENV *PAUDIOTESTENV; 62 64 63 struct AUDIOTESTDESC; 65 struct AUDIOTESTPARMS; 66 67 68 /********************************************************************************************************************************* 69 * Structures and Typedefs * 70 *********************************************************************************************************************************/ 64 /** Pointer a audio test descriptor. */ 65 typedef AUDIOTESTDESC *PAUDIOTESTDESC; 71 66 72 67 /** … … 79 74 * @param pTstParmsAcq The audio test parameters to set up. 80 75 */ 81 typedef DECLCALLBACKTYPE(int, FNAUDIOTESTSETUP,( AUDIOTESTENV *pTstEnv, AUDIOTESTDESC *pTstDesc, PAUDIOTESTPARMS pTstParmsAcq, void **ppvCtx));76 typedef DECLCALLBACKTYPE(int, FNAUDIOTESTSETUP,(PAUDIOTESTENV pTstEnv, PAUDIOTESTDESC pTstDesc, PAUDIOTESTPARMS pTstParmsAcq, void **ppvCtx)); 82 77 /** Pointer to an audio test setup callback. */ 83 78 typedef FNAUDIOTESTSETUP *PFNAUDIOTESTSETUP; 84 79 85 typedef DECLCALLBACKTYPE(int, FNAUDIOTESTEXEC,( AUDIOTESTENV *pTstEnv, void *pvCtx, PAUDIOTESTPARMS pTstParms));80 typedef DECLCALLBACKTYPE(int, FNAUDIOTESTEXEC,(PAUDIOTESTENV pTstEnv, void *pvCtx, PAUDIOTESTPARMS pTstParms)); 86 81 /** Pointer to an audio test exec callback. */ 87 82 typedef FNAUDIOTESTEXEC *PFNAUDIOTESTEXEC; 88 83 89 typedef DECLCALLBACKTYPE(int, FNAUDIOTESTDESTROY,( AUDIOTESTENV *pTstEnv, void *pvCtx));84 typedef DECLCALLBACKTYPE(int, FNAUDIOTESTDESTROY,(PAUDIOTESTENV pTstEnv, void *pvCtx)); 90 85 /** Pointer to an audio test destroy callback. */ 91 86 typedef FNAUDIOTESTDESTROY *PFNAUDIOTESTDESTROY; … … 107 102 PPDMIHOSTAUDIO pDrvAudio; 108 103 /** The current (last) audio device enumeration to use. */ 109 PDMAUDIOHOSTENUM DevEnm; 104 PDMAUDIOHOSTENUM DevEnum; 105 /** Audio stream. */ 110 106 AUDIOTESTSTREAM aStreams[AUDIOTESTENV_MAX_STREAMS]; 111 107 /** The audio test set to use. */ 112 108 AUDIOTESTSET Set; 113 109 } AUDIOTESTENV; 114 /** Pointer a audio test environment. */115 typedef AUDIOTESTENV *PAUDIOTESTENV;116 110 117 111 /** … … 131 125 PFNAUDIOTESTDESTROY pfnDestroy; 132 126 } AUDIOTESTDESC; 133 /** Pointer a audio test descriptor. */134 typedef AUDIOTESTDESC *PAUDIOTESTDESC;135 127 136 128 137 129 /********************************************************************************************************************************* 138 * Forward declarations*130 * Internal Functions * 139 131 *********************************************************************************************************************************/ 140 132 static int audioTestCombineParms(PAUDIOTESTPARMS pBaseParms, PAUDIOTESTPARMS pOverrideParms); 141 133 static int audioTestPlayTone(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms); 142 134 static int audioTestStreamDestroy(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream); 135 static DECLCALLBACK(RTEXITCODE) audioTestMain(int argc, char **argv); 136 static DECLCALLBACK(RTEXITCODE) audioVerifyMain(int argc, char **argv); 143 137 144 138 … … 177 171 static const RTGETOPTDEF g_aCmdCommonOptions[] = 178 172 { 179 { "-- help", 'h', RTGETOPT_REQ_NOTHING },180 { "--verbose", 'v', RTGETOPT_REQ_NOTHING } 173 { "--quiet", 'q', RTGETOPT_REQ_NOTHING }, 174 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, 181 175 }; 182 176 … … 211 205 }; 212 206 207 /** 208 * Commands. 209 */ 210 static struct 211 { 212 const char *pszCommand; 213 DECLCALLBACKMEMBER(RTEXITCODE, pfnHandler,(int argc, char **argv)); 214 PCRTGETOPTDEF paOptions; 215 size_t cOptions; 216 const char *pszDesc; 217 } const g_aCommands[] = 218 { 219 { 220 "test", audioTestMain, g_aCmdTestOptions, RT_ELEMENTS(g_aCmdTestOptions), 221 "Does some kind of testing, I guess..." 222 }, 223 { 224 "verify", audioVerifyMain, g_aCmdVerifyOptions, RT_ELEMENTS(g_aCmdVerifyOptions), 225 "Verfies something, I guess..." 226 }, 227 }; 228 213 229 /** The test handle. */ 214 static RTTEST g_hTest; 230 static RTTEST g_hTest; 231 /** The current verbosity level. */ 232 static unsigned g_uVerbosity = 0; 215 233 /** The driver instance data. */ 216 PDMDRVINS g_DrvIns; 217 /** The current verbosity level. */ 218 unsigned g_uVerbosity = 0; 234 static PDMDRVINS g_DrvIns; 219 235 220 236 … … 235 251 { 236 252 pTstEnv->pDrvAudio = pDrvAudio; 237 PDMAudioHostEnumInit(&pTstEnv->DevEn m);253 PDMAudioHostEnumInit(&pTstEnv->DevEnum); 238 254 239 255 int rc = VINF_SUCCESS; … … 275 291 return; 276 292 277 PDMAudioHostEnumDelete(&pTstEnv->DevEn m);293 PDMAudioHostEnumDelete(&pTstEnv->DevEnum); 278 294 279 295 for (unsigned i = 0; i < RT_ELEMENTS(pTstEnv->aStreams); i++) … … 294 310 static void audioTestParmsInit(PAUDIOTESTPARMS pTstParms) 295 311 { 296 RT_BZERO(pTstParms, sizeof(AUDIOTESTPARMS)); 297 298 return; 312 RT_ZERO(*pTstParms); 299 313 } 300 314 … … 313 327 314 328 /** 315 * Shows the applicationlogo.329 * Shows the logo. 316 330 * 317 331 * @param pStream Output stream to show logo on. 318 332 */ 319 void showLogo(PRTSTREAM pStream) 320 { 321 static bool s_fLogoShown = false; /* Show logo only once. */ 322 323 if (!s_fLogoShown) 324 { 325 RTStrmPrintf(pStream, VBOX_PRODUCT " VKAT (Validation Kit Audio Test) " 326 VBOX_VERSION_STRING " - r%s\n" 327 "(C) " VBOX_C_YEAR " " VBOX_VENDOR "\n" 328 "All rights reserved.\n\n", RTBldCfgRevisionStr()); 329 s_fLogoShown = true; 330 } 333 static void audioTestShowLogo(PRTSTREAM pStream) 334 { 335 RTStrmPrintf(pStream, VBOX_PRODUCT " VKAT (Validation Kit Audio Test) " 336 VBOX_VERSION_STRING " - r%s\n" 337 "(C) " VBOX_C_YEAR " " VBOX_VENDOR "\n" 338 "All rights reserved.\n\n", RTBldCfgRevisionStr()); 331 339 } 332 340 … … 336 344 static void audioTestUsage(PRTSTREAM pStrm) 337 345 { 338 char szExec[RTPATH_MAX]; 339 RTStrmPrintf(pStrm, "usage: %s [options]\n", 340 RTPathFilename(RTProcGetExecutablePath(szExec, sizeof(szExec)))); 341 RTStrmPrintf(pStrm, "\n"); 342 RTStrmPrintf(pStrm, "options: \n"); 343 344 for (unsigned i = 0; i < RT_ELEMENTS(g_aCmdTestOptions); i++) 345 { 346 const char *pszHelp; 347 switch (g_aCmdTestOptions[i].iShort) 346 RTStrmPrintf(pStrm, "usage: %s [global options] <command> [command-options]\n", 347 RTPathFilename(RTProcExecutablePath())); 348 RTStrmPrintf(pStrm, 349 "\n" 350 "Global Options:\n" 351 " -q, --quiet\n" 352 " Sets verbosity to zero.\n" 353 " -v, --verbose\n" 354 " Increase verbosity.\n" 355 " -V, --version\n" 356 " Displays version.\n" 357 " -h, -?, --help\n" 358 " Displays help.\n" 359 ); 360 361 for (uintptr_t iCmd = 0; iCmd < RT_ELEMENTS(g_aCommands); iCmd++) 362 { 363 RTStrmPrintf(pStrm, 364 "\n" 365 "Command '%s':\n" 366 " %s\n" 367 "Options for '%s':\n", 368 g_aCommands[iCmd].pszCommand, g_aCommands[iCmd].pszDesc, g_aCommands[iCmd].pszCommand); 369 PCRTGETOPTDEF const paOptions = g_aCommands[iCmd].paOptions; 370 for (unsigned i = 0; i < g_aCommands[iCmd].cOptions; i++) 348 371 { 349 case 'h': 350 pszHelp = "Displays this help and exit"; 351 break; 352 case 'd': 353 pszHelp = "Use the specified audio device"; 354 break; 355 case 'e': 356 pszHelp = "Exclude the given test id from the list"; 357 break; 358 case 'a': 359 pszHelp = "Exclude all tests from the list (useful to enable single tests later with --include)"; 360 break; 361 case 'i': 362 pszHelp = "Include the given test id in the list"; 363 break; 364 default: 365 pszHelp = "Option undocumented"; 366 break; 372 if (RT_C_IS_PRINT(paOptions[i].iShort)) 373 RTStrmPrintf(pStrm, " -%c, %s\n", g_aCmdTestOptions[i].iShort, g_aCmdTestOptions[i].pszLong); 374 else 375 RTStrmPrintf(pStrm, " %s\n", g_aCmdTestOptions[i].pszLong); 376 377 const char *pszHelp = NULL; 378 if (paOptions == g_aCmdTestOptions) 379 { 380 switch (g_aCmdTestOptions[i].iShort) 381 { 382 case 'd': 383 pszHelp = "Use the specified audio device"; 384 break; 385 case 'e': 386 pszHelp = "Exclude the given test id from the list"; 387 break; 388 case 'a': 389 pszHelp = "Exclude all tests from the list (useful to enable single tests later with --include)"; 390 break; 391 case 'i': 392 pszHelp = "Include the given test id in the list"; 393 break; 394 } 395 } 396 /** @todo Add help text for all options. */ 397 if (pszHelp) 398 RTStrmPrintf(pStrm, " %s\n", pszHelp); 367 399 } 368 char szOpt[256]; 369 RTStrPrintf(szOpt, sizeof(szOpt), "%s, -%c", g_aCmdTestOptions[i].pszLong, g_aCmdTestOptions[i].iShort); 370 RTStrmPrintf(pStrm, " %-30s%s\n", szOpt, pszHelp); 371 } 372 373 /** @todo Add all other options. */ 400 } 401 374 402 } 375 403 … … 452 480 *ppDev = NULL; 453 481 454 int rc = pTstEnv->pDrvAudio->pfnGetDevices(pTstEnv->pDrvAudio, &pTstEnv->DevEn m);482 int rc = pTstEnv->pDrvAudio->pfnGetDevices(pTstEnv->pDrvAudio, &pTstEnv->DevEnum); 455 483 if (RT_SUCCESS(rc)) 456 484 { 457 485 PPDMAUDIOHOSTDEV pDev; 458 RTListForEach(&pTstEnv->DevEn m.LstDevices, pDev, PDMAUDIOHOSTDEV, ListEntry)486 RTListForEach(&pTstEnv->DevEnum.LstDevices, pDev, PDMAUDIOHOSTDEV, ListEntry) 459 487 { 460 488 char szFlags[PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN]; … … 856 884 * @param argv argv arguments. 857 885 */ 858 intaudioTestMain(int argc, char **argv)886 static DECLCALLBACK(RTEXITCODE) audioTestMain(int argc, char **argv) 859 887 { 860 888 AUDIOTESTENV TstEnv; … … 864 892 audioTestParmsInit(&TstCust); 865 893 866 char *pszDevice = NULL; /* Custom device to use. Can be NULL if not being used. */ 867 char *pszTag = NULL; /* Custom tag to use. Can be NULL if not being used. */ 868 869 RT_ZERO(g_DrvIns); 870 const PDMDRVREG *pDrvReg = NULL; 894 const char *pszDevice = NULL; /* Custom device to use. Can be NULL if not being used. */ 895 const char *pszTag = NULL; /* Custom tag to use. Can be NULL if not being used. */ 896 897 /* The backend: */ 898 PDMDRVREG const *pDrvReg; 899 #if defined(RT_OS_WINDOWS) 900 pDrvReg = &g_DrvHostAudioWas; 901 #elif defined(RT_OS_DARWIN) 902 pDrvReg = &g_DrvHostCoreAudio; 903 #elif defined(RT_OS_SOLARIS) 904 pDrvReg = &g_DrvHostOSSAudio; 905 #elif defined(RT_OS_LINUX) && defined(VBOX_WITH_AUDIO_ALSA) 906 pDrvReg = &g_DrvHostALSAAudio; 907 #elif defined(RT_OS_LINUX) && defined(VBOX_WITH_AUDIO_PULSE) 908 pDrvReg = &g_DrvHostPulseAudio; 909 #elif defined(RT_OS_LINUX) && defined(VBOX_WITH_AUDIO_OSS) 910 pDrvReg = &g_DrvHostPulseAudio; 911 #else 912 # error "Port me!" 913 #endif 871 914 872 915 RTGETOPTUNION ValueUnion; 873 916 RTGETOPTSTATE GetState; 874 int rc = RTGetOptInit(&GetState, argc, argv, g_aCmdTestOptions, RT_ELEMENTS(g_aCmdTestOptions), 0, 0 /* fFlags*/);917 int rc = RTGetOptInit(&GetState, argc, argv, g_aCmdTestOptions, RT_ELEMENTS(g_aCmdTestOptions), 1, 0 /*fFlags*/); 875 918 AssertRCReturn(rc, RTEXITCODE_INIT); 876 919 … … 880 923 { 881 924 case 'h': 882 {883 925 audioTestUsage(g_pStdOut); 884 926 return RTEXITCODE_SUCCESS; 885 }886 887 case 'e':888 {889 if (ValueUnion.u32 < RT_ELEMENTS(g_aTests))890 g_aTests[ValueUnion.u32].fExcluded = true;891 else892 {893 RTTestPrintf(g_hTest, RTTESTLVL_FAILURE, "Invalid test number passed to --exclude\n");894 RTTestErrorInc(g_hTest);895 return RTGetOptPrintError(VERR_INVALID_PARAMETER, &ValueUnion);896 }897 break;898 }899 927 900 928 case 'a': 901 {902 929 for (unsigned i = 0; i < RT_ELEMENTS(g_aTests); i++) 903 930 g_aTests[i].fExcluded = true; 904 931 break; 905 }906 932 907 933 case 'b': 908 {934 pDrvReg = NULL; 909 935 #ifdef VBOX_WITH_AUDIO_PULSE 910 if ( ! RTStrICmp(ValueUnion.psz, "pulseaudio")911 || ! RTStrICmp(ValueUnion.psz, "pa"))936 if ( !strcmp(ValueUnion.psz, "pulseaudio") 937 || !strcmp(ValueUnion.psz, "pa")) 912 938 pDrvReg = &g_DrvHostPulseAudio; 913 939 #endif 914 940 #ifdef VBOX_WITH_AUDIO_ALSA 915 if ( ! RTStrICmp(ValueUnion.psz, "alsa"))941 if ( !strcmp(ValueUnion.psz, "alsa")) 916 942 pDrvReg = &g_DrvHostALSAAudio; 917 943 #endif 918 944 #ifdef VBOX_WITH_AUDIO_OSS 919 if ( ! RTStrICmp(ValueUnion.psz, "oss"))945 if ( !strcmp(ValueUnion.psz, "oss")) 920 946 pDrvReg = &g_DrvHostOSSAudio; 921 947 #endif 922 948 #if defined(RT_OS_DARWIN) 923 if ( ! RTStrICmp(ValueUnion.psz, "coreaudio"))949 if ( !strcmp(ValueUnion.psz, "coreaudio")) 924 950 pDrvReg = &g_DrvHostCoreAudio; 925 951 #endif 926 952 #if defined(RT_OS_WINDOWS) 927 if ( ! RTStrICmp(ValueUnion.psz, "wasapi"))953 if ( !strcmp(ValueUnion.psz, "wasapi")) 928 954 pDrvReg = &g_DrvHostAudioWas; 929 else if ( ! RTStrICmp(ValueUnion.psz, "directsound")930 || ! RTStrICmp(ValueUnion.psz, "dsound")955 else if ( !strcmp(ValueUnion.psz, "directsound") 956 || !strcmp(ValueUnion.psz, "dsound") 931 957 pDrvReg = &g_DrvHostDSound; 932 958 #endif 933 959 if (pDrvReg == NULL) 934 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid / unsupported backend '%s' specified\n", ValueUnion.psz); 935 break; 936 } 960 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Unknown backend: '%s'", ValueUnion.psz); 961 break; 962 963 case 'e': 964 if (ValueUnion.u32 >= RT_ELEMENTS(g_aTests)) 965 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid test number %u passed to --exclude", ValueUnion.u32); 966 g_aTests[ValueUnion.u32].fExcluded = true; 967 break; 937 968 938 969 case 'i': 939 { 940 if (ValueUnion.u32 < RT_ELEMENTS(g_aTests)) 941 g_aTests[ValueUnion.u32].fExcluded = false; 942 else 943 { 944 RTTestPrintf(g_hTest, RTTESTLVL_FAILURE, "Invalid test number passed to --include\n"); 945 RTTestErrorInc(g_hTest); 946 return RTGetOptPrintError(VERR_INVALID_PARAMETER, &ValueUnion); 947 } 948 break; 949 } 970 if (ValueUnion.u32 >= RT_ELEMENTS(g_aTests)) 971 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Invalid test number %u passed to --include", ValueUnion.u32); 972 g_aTests[ValueUnion.u32].fExcluded = false; 973 break; 950 974 951 975 case VKAT_TEST_OPT_COUNT: 952 { 953 break; 954 } 976 break; 955 977 956 978 case VKAT_TEST_OPT_DEV: 957 { 958 pszDevice = RTStrDup(ValueUnion.psz); 959 break; 960 } 979 pszDevice = ValueUnion.psz; 980 break; 961 981 962 982 case VKAT_TEST_OPT_PAUSE: 963 { 964 break; 965 } 983 break; 966 984 967 985 case VKAT_TEST_OPT_OUTDIR: 968 {969 986 rc = RTStrCopy(TstEnv.szPathOut, sizeof(TstEnv.szPathOut), ValueUnion.psz); 970 987 if (RT_FAILURE(rc)) 971 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Out dir invalid, rc=%Rrc\n", rc); 972 break; 973 } 988 return RTMsgErrorExitFailure("Failed to copy out directory: %Rrc", rc); 989 break; 974 990 975 991 case VKAT_TEST_OPT_PCM_BIT: 976 {992 /** @todo r=bird: the X suffix means: "fingers off!" */ 977 993 TstCust.TestTone.Props.cbSampleX = ValueUnion.u8 / 8 /* bit */; 978 994 break; 979 }980 995 981 996 case VKAT_TEST_OPT_PCM_CHAN: 982 {997 /** @todo r=bird: the X suffix means: "fingers off!" */ 983 998 TstCust.TestTone.Props.cChannelsX = ValueUnion.u8; 984 999 break; 985 }986 1000 987 1001 case VKAT_TEST_OPT_PCM_HZ: 988 {989 1002 TstCust.TestTone.Props.uHz = ValueUnion.u32; 990 1003 break; 991 }992 1004 993 1005 case VKAT_TEST_OPT_PCM_SIGNED: 994 {995 1006 TstCust.TestTone.Props.fSigned = ValueUnion.f; 996 1007 break; 997 }998 1008 999 1009 case VKAT_TEST_OPT_TAG: 1000 { 1001 pszTag = RTStrDup(ValueUnion.psz); 1002 break; 1003 } 1010 pszTag = ValueUnion.psz; 1011 break; 1004 1012 1005 1013 case VKAT_TEST_OPT_TEMPDIR: 1006 {1007 1014 rc = RTStrCopy(TstEnv.szPathTemp, sizeof(TstEnv.szPathTemp), ValueUnion.psz); 1008 1015 if (RT_FAILURE(rc)) 1009 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Temp dir invalid, rc=%Rrc\n", rc); 1010 break; 1011 } 1016 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Temp dir invalid, rc=%Rrc", rc); 1017 break; 1012 1018 1013 1019 case VKAT_TEST_OPT_VOL: 1014 {1015 1020 TstCust.TestTone.uVolumePercent = ValueUnion.u8; 1016 1021 break; 1017 }1018 1022 1019 1023 default: 1020 break;1024 return RTGetOptPrintError(rc, &ValueUnion); 1021 1025 } 1022 1026 } … … 1027 1031 RTTestBanner(g_hTest); 1028 1032 1029 /* If no backend is specified, go with the default backend for that OS. */1030 if (pDrvReg == NULL)1031 #if defined(RT_OS_WINDOWS)1032 pDrvReg = &g_DrvHostAudioWas;1033 #elif defined(RT_OS_DARWIN)1034 pDrvReg = &g_DrvHostCoreAudio;1035 #elif defined(RT_OS_SOLARIS)1036 pDrvReg = &g_DrvHostOSSAudio;1037 #else1038 pDrvReg = &g_DrvHostALSAAudio;1039 #endif1040 1041 1033 PPDMIHOSTAUDIO pDrvAudio; 1034 RT_ZERO(g_DrvIns); 1042 1035 rc = audioTestDrvConstruct(pDrvReg, &g_DrvIns, &pDrvAudio); 1043 1036 if (RT_SUCCESS(rc)) … … 1069 1062 audioTestParmsDestroy(&TstCust); 1070 1063 1071 RTStrFree(pszDevice);1072 RTStrFree(pszTag);1073 1074 1064 if (RT_FAILURE(rc)) /* Let us know that something went wrong in case we forgot to mention it. */ 1075 1065 RTTestFailed(g_hTest, "Tested failed with %Rrc\n", rc); … … 1088 1078 * @param pszTag Tag of test set to verify. Optional and can be NULL. 1089 1079 */ 1090 int audioVerifyOne(const char *pszPath, const char *pszTag)1080 static int audioVerifyOne(const char *pszPath, const char *pszTag) 1091 1081 { 1092 1082 RTTestSubF(g_hTest, "Verifying test set (tag '%s') ...", pszTag ? pszTag : "default"); … … 1105 1095 PAUDIOTESTERRORENTRY pErrEntry; 1106 1096 RTListForEach(&errDesc.List, pErrEntry, AUDIOTESTERRORENTRY, Node) 1097 { 1107 1098 RTTestFailed(g_hTest, pErrEntry->szDesc); 1099 } 1108 1100 } 1109 1101 else … … 1132 1124 * @param argv argv arguments. 1133 1125 */ 1134 int audioVerifyMain(int argc, char **argv) 1135 { 1136 char *pszTag = NULL; /* Custom tag to use. Can be NULL if not being used. */ 1137 1138 char szDirCur[RTPATH_MAX]; 1139 int rc = RTPathGetCurrent(szDirCur, sizeof(szDirCur)); 1140 if (RT_FAILURE(rc)) 1141 { 1142 RTMsgError("Getting current directory failed, rc=%Rrc\n", rc); 1143 return RTEXITCODE_FAILURE; 1144 } 1126 static DECLCALLBACK(RTEXITCODE) audioVerifyMain(int argc, char **argv) 1127 { 1128 /* 1129 * Parse options and process arguments. 1130 */ 1131 RTGETOPTSTATE GetState; 1132 int rc = RTGetOptInit(&GetState, argc, argv, g_aCmdVerifyOptions, RT_ELEMENTS(g_aCmdVerifyOptions), 1133 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); 1134 AssertRCReturn(rc, RTEXITCODE_INIT); 1135 1136 const char *pszTag = NULL; /* Custom tag to use. Can be NULL if not being used. */ 1137 unsigned iTestSet = 0; 1138 RTGETOPTUNION ValueUnion; 1139 while ((rc = RTGetOpt(&GetState, &ValueUnion))) 1140 { 1141 switch (rc) 1142 { 1143 case VKAT_VERIFY_OPT_TAG: 1144 pszTag = ValueUnion.psz; 1145 if (g_uVerbosity > 0) 1146 RTMsgInfo("Using tag '%s'\n", pszTag); 1147 break; 1148 1149 case VINF_GETOPT_NOT_OPTION: 1150 if (iTestSet == 0) 1151 RTTestBanner(g_hTest); 1152 audioVerifyOne(ValueUnion.psz, pszTag); 1153 iTestSet++; 1154 break; 1155 1156 default: 1157 return RTGetOptPrintError(rc, &ValueUnion); 1158 } 1159 } 1160 1161 /* 1162 * If no paths given, default to the current directory. 1163 */ 1164 if (iTestSet == 0) 1165 { 1166 if (iTestSet == 0) 1167 RTTestBanner(g_hTest); 1168 char szDirCur[RTPATH_MAX]; 1169 rc = RTPathGetCurrent(szDirCur, sizeof(szDirCur)); 1170 audioVerifyOne(RT_SUCCESS(rc) ? szDirCur : ".", pszTag); 1171 } 1172 1173 /* 1174 * Print summary and exit. 1175 */ 1176 return RTTestSummaryAndDestroy(g_hTest); 1177 } 1178 1179 int main(int argc, char **argv) 1180 { 1181 /* 1182 * Init IPRT and globals. 1183 */ 1184 RTEXITCODE rcExit = RTTestInitAndCreate("AudioTest", &g_hTest); 1185 if (rcExit != RTEXITCODE_SUCCESS) 1186 return rcExit; 1145 1187 1146 1188 /* … … 1149 1191 RTGETOPTUNION ValueUnion; 1150 1192 RTGETOPTSTATE GetState; 1151 rc = RTGetOptInit(&GetState, argc, argv, g_aCmdVerifyOptions, RT_ELEMENTS(g_aCmdVerifyOptions),1152 0, RTGETOPTINIT_FLAGS_OPTS_FIRST);1193 int rc = RTGetOptInit(&GetState, argc, argv, g_aCmdCommonOptions, 1194 RT_ELEMENTS(g_aCmdCommonOptions), 1 /*idxFirst*/, 0 /*fFlags - must not sort! */); 1153 1195 AssertRCReturn(rc, RTEXITCODE_INIT); 1154 1196 1155 while ((rc = RTGetOpt(&GetState, &ValueUnion)) )1197 while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0) 1156 1198 { 1157 1199 switch (rc) 1158 1200 { 1159 case VKAT_VERIFY_OPT_TAG: 1160 { 1161 pszTag = RTStrDup(ValueUnion.psz); 1162 break; 1163 } 1201 case 'q': 1202 g_uVerbosity = 0; 1203 break; 1204 1205 case 'v': 1206 g_uVerbosity++; 1207 break; 1208 1209 case 'V': 1210 RTPrintf("v0.0.1\n"); 1211 return RTEXITCODE_SUCCESS; 1212 1213 case 'h': 1214 audioTestShowLogo(g_pStdOut); 1215 audioTestUsage(g_pStdOut); 1216 return RTEXITCODE_SUCCESS; 1164 1217 1165 1218 case VINF_GETOPT_NOT_OPTION: 1166 1219 { 1167 Assert(GetState.iNext); 1168 GetState.iNext--; 1169 break; 1220 for (uintptr_t i = 0; i < RT_ELEMENTS(g_aCommands); i++) 1221 if (strcmp(ValueUnion.psz, g_aCommands[i].pszCommand) == 0) 1222 { 1223 audioTestShowLogo(g_pStdOut); 1224 int32_t iCurArg = GetState.iNext - 1; 1225 return g_aCommands[i].pfnHandler(argc - iCurArg, argv + iCurArg); 1226 } 1227 RTMsgError("Unknown command '%s'!\n", ValueUnion.psz); 1228 audioTestUsage(g_pStdErr); 1229 return RTEXITCODE_SYNTAX; 1170 1230 } 1171 1231 … … 1173 1233 return RTGetOptPrintError(rc, &ValueUnion); 1174 1234 } 1175 1176 /* All flags / options processed? Bail out here. 1177 * Processing the file / directory list comes down below. */ 1178 if (rc == VINF_GETOPT_NOT_OPTION) 1179 break; 1180 } 1181 1182 if (pszTag) 1183 RTMsgInfo("Using tag '%s'\n", pszTag); 1184 1185 /* 1186 * Start testing. 1187 */ 1188 RTTestBanner(g_hTest); 1189 1190 /* 1191 * Deal with test sets. 1192 */ 1193 rc = RTGetOpt(&GetState, &ValueUnion); 1194 do 1195 { 1196 char const *pszPath; 1197 1198 if (rc == 0) /* Use current directory if no element specified. */ 1199 pszPath = szDirCur; 1200 else 1201 pszPath = ValueUnion.psz; 1202 1203 RTFSOBJINFO objInfo; 1204 rc = RTPathQueryInfoEx(pszPath, &objInfo, 1205 RTFSOBJATTRADD_UNIX, RTPATH_F_FOLLOW_LINK); 1206 if (RT_SUCCESS(rc)) 1207 { 1208 rc = audioVerifyOne(pszPath, pszTag); 1209 } 1210 else 1211 RTTestFailed(g_hTest, "Cannot access path '%s', rc=%Rrc\n", pszPath, rc); 1212 1213 } while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0); 1214 1215 RTStrFree(pszTag); 1216 1217 /* 1218 * Print summary and exit. 1219 */ 1220 return RTTestSummaryAndDestroy(g_hTest); 1221 } 1222 1223 int main(int argc, char **argv) 1224 { 1225 /* 1226 * Init IPRT and globals. 1227 */ 1228 int rc = RTTestInitAndCreate("AudioTest", &g_hTest); 1229 if (rc) 1230 return rc; 1231 1232 AssertReturn(argc > 0, false); 1233 1234 /* At least the operation mode must be there. */ 1235 if (argc < 2) 1236 { 1237 audioTestUsage(g_pStdOut); 1238 return RTEXITCODE_SYNTAX; 1239 } 1240 1241 /* 1242 * Process common options. 1243 */ 1244 RTGETOPTUNION ValueUnion; 1245 RTGETOPTSTATE GetState; 1246 rc = RTGetOptInit(&GetState, argc, argv, g_aCmdCommonOptions, RT_ELEMENTS(g_aCmdCommonOptions), 1 /* idxFirst */, 0 /* fFlags */); 1247 AssertRCReturn(rc, RTEXITCODE_INIT); 1248 1249 while ((rc = RTGetOpt(&GetState, &ValueUnion))) 1250 { 1251 switch (rc) 1252 { 1253 case 'h': 1254 { 1255 showLogo(g_pStdOut); 1256 audioTestUsage(g_pStdOut); 1257 return RTEXITCODE_SUCCESS; 1258 } 1259 1260 case 'v': 1261 { 1262 g_uVerbosity++; 1263 break; 1264 } 1265 1266 case VINF_GETOPT_NOT_OPTION: 1267 { 1268 Assert(GetState.iNext); 1269 GetState.iNext--; 1270 } 1271 1272 default: 1273 /* Ignore everything else here. */ 1274 break; 1275 } 1276 1277 /* All flags / options processed? Bail out here. 1278 * Processing the file / directory list comes down below. */ 1279 if (rc == VINF_GETOPT_NOT_OPTION) 1280 break; 1281 } 1282 1283 showLogo(g_pStdOut); 1284 1285 /* Get operation mode. */ 1286 const char *pszMode = argv[GetState.iNext++]; /** @todo Also do it busybox-like? */ 1287 1288 argv += GetState.iNext; 1289 Assert(argc >= GetState.iNext); 1290 argc -= GetState.iNext; 1291 1292 if (!RTStrICmp(pszMode, "test")) 1293 { 1294 return audioTestMain(argc, argv); 1295 } 1296 else if (!RTStrICmp(pszMode, "verify")) 1297 { 1298 return audioVerifyMain(argc, argv); 1299 } 1300 1301 RTStrmPrintf(g_pStdOut, "Must specify a mode first, either 'test' or 'verify'\n\n"); 1302 1303 audioTestUsage(g_pStdOut); 1235 } 1236 1237 RTMsgError("No command specified!\n"); 1238 audioTestUsage(g_pStdErr); 1304 1239 return RTEXITCODE_SYNTAX; 1305 1240 }
Note:
See TracChangeset
for help on using the changeset viewer.