VirtualBox

Ignore:
Timestamp:
Mar 4, 2008 9:11:57 AM (17 years ago)
Author:
vboxsync
Message:

Frontends/VBoxHeadless: RTGetOpt-ified the command-line parameters and added parameters for controlling mpeg output (as preferred alternatives to the environment variables which are used now)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp

    r6285 r7263  
    3737#include <iprt/stream.h>
    3838#include <iprt/ldr.h>
     39#include <iprt/getopt.h>
    3940
    4041#ifdef VBOX_FFMPEG
     
    5455
    5556#define LogError(m,rc) \
    56     if (1) { \
     57    do { \
    5758        Log (("VBoxHeadless: ERROR: " m " [rc=0x%08X]\n", rc)); \
    5859        RTPrintf (m " (rc = 0x%08X)\n", rc); \
    59     }
     60    } while (0)
    6061
    6162////////////////////////////////////////////////////////////////////////////////
     
    267268{
    268269    RTPrintf("Usage:\n"
    269              "   -startvm <name|uuid>     Start given VM (required argument)\n"
     270             "   -s, -startvm, --startvm <name|uuid>   Start given VM (required argument)\n"
    270271#ifdef VBOX_WITH_VRDP
    271              "   -vrdpport <port>         Port number the VRDP server will bind to\n"
    272              "   -vrdpaddress <ip>        Interface IP the VRDP will bind to \n"
    273 #endif
    274 #ifdef VBOX_FFMPEG
    275              "   -capture                 Record the VM screen output to a file\n"
    276              "\n"
    277              "When recording, the following optional environment variables are also\n"
    278              "recognized:\n"
    279              "\n"
    280              "   VBOX_CAPTUREWIDTH        Frame width\n"
    281              "   VBOX_CAPTUREHEIGHT       Frame height\n"
    282              "   VBOX_CAPTUREBITRATE      Recording bit rate\n"
    283              "   VBOX_CAPTUREBITRATE      Recording bit rate\n"
    284              "   VBOX_CAPTUREFILE         Specify a file name\n"
     272             "   -p, -vrdpport, --vrdpport <port>      Port number the VRDP server will bind\n"
     273             "                                         to\n"
     274             "   -a, -vrdpaddress, --vrdpaddress <ip>  Interface IP the VRDP will bind to \n"
     275#endif
     276#ifdef VBOX_FFMPEG
     277             "   -c, -capture, --capture               Record the VM screen output to a file\n"
     278             "   -w, --width                           Frame width when recording\n"
     279             "   -h, --height                          Frame height when recording\n"
     280             "   -r, --bitrate                         Recording bit rate when recording\n"
     281             "   -f, --filename                        File name when recording.  The codec\n"
     282             "                                         used will be chosen based on the\n"
     283             "                                         file extension\n"
    285284#endif
    286285             "\n");
    287286}
     287
     288#ifdef VBOX_FFMPEG
     289/**
     290 * Parse the environment for variables which can influence the FFMPEG settings.
     291 * purely for backwards compatibility.
     292 * @param pulFrameWidth may be updated with a desired frame width
     293 * @param pulFrameHeight may be updated with a desired frame height
     294 * @param pulBitRate may be updated with a desired bit rate
     295 * @param ppszFileName may be updated with a desired file name
     296 */
     297static void parse_environ(unsigned long *pulFrameWidth, unsigned long *pulFrameHeight,
     298                          unsigned long *pulBitRate, const char **ppszFileName)
     299{
     300    const char *pszEnvTemp;
     301
     302    if ((pszEnvTemp = RTEnvGet("VBOX_CAPTUREWIDTH")) != 0)
     303    {
     304        errno = 0;
     305        unsigned long ulFrameWidth = strtoul(pszEnvTemp, 0, 10);
     306        if (errno != 0)
     307            LogError("VBoxHeadless: ERROR: invalid VBOX_CAPTUREWIDTH environment variable", 0);
     308        else
     309            *pulFrameWidth = ulFrameWidth;
     310    }
     311    if ((pszEnvTemp = RTEnvGet("VBOX_CAPTUREHEIGHT")) != 0)
     312    {
     313        errno = 0;
     314        unsigned long ulFrameHeight = strtoul(pszEnvTemp, 0, 10);
     315        if (errno != 0)
     316            LogError("VBoxHeadless: ERROR: invalid VBOX_CAPTUREHEIGHT environment variable", 0);
     317        else
     318            *pulFrameHeight = ulFrameHeight;
     319    }
     320    if ((pszEnvTemp = RTEnvGet("VBOX_CAPTUREBITRATE")) != 0)
     321    {
     322        errno = 0;
     323        unsigned long ulBitRate = strtoul(pszEnvTemp, 0, 10);
     324        if (errno != 0)
     325            LogError("VBoxHeadless: ERROR: invalid VBOX_CAPTUREBITRATE environment variable", 0);
     326        else
     327            *pulBitRate = ulBitRate;
     328    }
     329    if ((pszEnvTemp = RTEnvGet("VBOX_CAPTUREFILE")) != 0)
     330        *ppszFileName = pszEnvTemp;
     331}
     332#endif /* VBOX_FFMPEG defined */
    288333
    289334/**
     
    302347#ifdef VBOX_FFMPEG
    303348    unsigned fFFMPEG = 0;
    304     unsigned ulFrameWidth = 800;
    305     unsigned ulFrameHeight = 600;
    306     unsigned ulBitRate = 300000;
     349    unsigned long ulFrameWidth = 800;
     350    unsigned long ulFrameHeight = 600;
     351    unsigned long ulBitRate = 300000;
    307352    char pszMPEGFile[RTPATH_MAX];
     353    const char *pszFileNameParam = "VBox-%d.vob";
    308354#endif /* VBOX_FFMPEG */
    309355
     
    321367    const char *name = NULL;
    322368
     369#ifdef VBOX_FFMPEG
     370    /* Parse the environment */
     371    parse_environ(&ulFrameWidth, &ulFrameHeight, &ulBitRate, &pszFileNameParam);
     372#endif
     373
     374    enum eHeadlessOptions
     375    {
     376        OPT_RAW_R0 = 0x100,
     377        OPT_NO_RAW_R0,
     378        OPT_RAW_R3,
     379        OPT_NO_RAW_R3,
     380        OPT_PATM,
     381        OPT_NO_PATM,
     382        OPT_CSAM,
     383        OPT_NO_CSAM,
     384        OPT_COMMENT
     385    };
     386
     387    static const RTOPTIONDEF g_aOptions[] =
     388    {
     389        { "-startvm", 's', RTGETOPT_REQ_STRING },
     390        { "--startvm", 's', RTGETOPT_REQ_STRING },
     391#ifdef VBOX_WITH_VRDP
     392        { "-vrdpport", 'p', RTGETOPT_REQ_UINT32 },
     393        { "--vrdpport", 'p', RTGETOPT_REQ_UINT32 },
     394        { "-vrdaddress", 'a', RTGETOPT_REQ_STRING },
     395        { "--vrdaddress", 'a', RTGETOPT_REQ_STRING },
     396#endif /* VBOX_WITH_VRDP defined */
     397        { "-rawr0", OPT_RAW_R0, 0 },
     398        { "--rawr0", OPT_RAW_R0, 0 },
     399        { "-norawr0", OPT_NO_RAW_R0, 0 },
     400        { "--norawr0", OPT_NO_RAW_R0, 0 },
     401        { "-rawr3", OPT_RAW_R3, 0 },
     402        { "--rawr3", OPT_RAW_R3, 0 },
     403        { "-norawr3", OPT_NO_RAW_R3, 0 },
     404        { "--norawr3", OPT_NO_RAW_R3, 0 },
     405        { "-patm", OPT_PATM, 0 },
     406        { "--patm", OPT_PATM, 0 },
     407        { "-nopatm", OPT_NO_PATM, 0 },
     408        { "--nopatm", OPT_NO_PATM, 0 },
     409        { "-csam", OPT_CSAM, 0 },
     410        { "--csam", OPT_CSAM, 0 },
     411        { "-nocsam", OPT_NO_CSAM, 0 },
     412        { "--nocsam", OPT_NO_CSAM, 0 },
     413#ifdef VBOX_FFMPEG
     414        { "-capture", 'c', 0 },
     415        { "--capture", 'c', 0 },
     416        { "--width", 'w', RTGETOPT_REQ_UINT32 },
     417        { "--height", 'h', RTGETOPT_REQ_UINT32 },
     418        { "--bitrate", 'r', RTGETOPT_REQ_UINT32 },
     419        { "--filename", 'f', RTGETOPT_REQ_STRING },
     420#endif /* VBOX_FFMPEG defined */
     421        { "-comment", OPT_COMMENT, RTGETOPT_REQ_STRING },
     422        { "--comment", OPT_COMMENT, RTGETOPT_REQ_STRING }
     423    };
     424
    323425    // parse the command line
    324     for (int curArg = 1; curArg < argc; curArg++)
    325     {
    326         if (strcmp(argv[curArg], "-startvm") == 0)
    327         {
    328             if (++curArg >= argc)
    329             {
    330                 LogError("VBoxHeadless: ERROR: missing VM identifier!", 0);
    331                 return -1;
    332             }
    333             id = argv[curArg];
    334             /* If the argument was not a UUID, then it must be a name. */
    335             if (!id)
    336             {
    337                 name = argv[curArg];
    338             }
    339         }
     426    int ch;
     427    int i = 1;
     428    RTOPTIONUNION ValueUnion;
     429    while ((ch = RTGetOpt(argc, argv, g_aOptions, RT_ELEMENTS(g_aOptions), &i, &ValueUnion)))
     430    {
     431        if (ch < 0)
     432        {
     433            show_usage();
     434            exit(-1);
     435        }
     436        switch(ch)
     437        {
     438            case 's':
     439                id = ValueUnion.psz;
     440                /* If the argument was not a UUID, then it must be a name. */
     441                if (!id)
     442                    name = ValueUnion.psz;
     443                break;
    340444#ifdef VBOX_WITH_VRDP
    341         else if (strcmp(argv[curArg], "-vrdpport") == 0)
    342         {
    343             if (++curArg >= argc)
    344             {
    345                 LogError("VBoxHeadless: ERROR: missing VRDP port value!", 0);
    346                 return -1;
    347             }
    348             vrdpPort = atoi(argv[curArg]);
    349         }
    350         else if (strcmp(argv[curArg], "-vrdpaddress") == 0)
    351         {
    352             if (++curArg >= argc)
    353             {
    354                 LogError("VBoxHeadless: ERROR: missing VRDP address value!", 0);
    355                 return -1;
    356             }
    357             vrdpAddress = argv[curArg];
    358         }
    359 #endif
    360         else if (strcmp(argv[curArg], "-rawr0") == 0)
    361         {
    362             fRawR0 = true;
    363         }
    364         else if (strcmp(argv[curArg], "-norawr0") == 0)
    365         {
    366             fRawR0 = false;
    367         }
    368         else if (strcmp(argv[curArg], "-rawr3") == 0)
    369         {
    370             fRawR3 = true;
    371         }
    372         else if (strcmp(argv[curArg], "-norawr3") == 0)
    373         {
    374             fRawR3 = false;
    375         }
    376         else if (strcmp(argv[curArg], "-patm") == 0)
    377         {
    378             fPATM = true;
    379         }
    380         else if (strcmp(argv[curArg], "-nopatm") == 0)
    381         {
    382             fPATM = false;
    383         }
    384         else if (strcmp(argv[curArg], "-csam") == 0)
    385         {
    386             fCSAM = true;
    387         }
    388         else if (strcmp(argv[curArg], "-nocsam") == 0)
    389         {
    390             fCSAM = false;
    391         }
    392 #ifdef VBOX_FFMPEG
    393         else if (strcmp(argv[curArg], "-capture") == 0)
    394         {
    395             fFFMPEG = true;
    396         }
    397 #endif
    398         else if (strcmp(argv[curArg], "-comment") == 0)
    399         {
    400             /* We could just ignore this, but check the syntax for consistency... */
    401             if (++curArg >= argc)
    402             {
    403                 LogError("VBoxHeadless: ERROR: missing comment!", 0);
    404                 return -1;
    405             }
    406         }
    407         else
    408         {
    409             LogError("VBoxHeadless: ERROR: unknown option '%s'", argv[curArg]);
    410             show_usage();
    411             return -1;
    412         }
    413     }
    414 
    415 #ifdef VBOX_FFMPEG
    416     const char *pszEnvTemp;
    417     if ((pszEnvTemp = RTEnvGet("VBOX_CAPTUREWIDTH")) != 0)
    418     {
    419         errno = 0;
    420         ulFrameWidth = strtoul(pszEnvTemp, 0, 10);
    421         if (errno != 0)
    422         {
    423             LogError("VBoxHeadless: ERROR: invalid VBOX_CAPTUREWIDTH environment variable", 0);
    424             return -1;
    425         }
    426         if (ulFrameWidth < 512 || ulFrameWidth > 2048 || ulFrameWidth % 2)
    427         {
    428             LogError("VBoxHeadless: ERROR: please specify an even VBOX_CAPTUREWIDTH variable between 512 and 2048", 0);
    429             return -1;
    430         }
    431     }
    432 
    433     if ((pszEnvTemp = RTEnvGet("VBOX_CAPTUREHEIGHT")) != 0)
    434     {
    435         errno = 0;
    436         ulFrameHeight = strtoul(pszEnvTemp, 0, 10);
    437         if (errno != 0)
    438         {
    439             LogError("VBoxHeadless: ERROR: invalid VBOX_CAPTUREHEIGHT environment variable", 0);
    440             return -1;
    441         }
    442         if (ulFrameHeight < 384 || ulFrameHeight > 1536 || ulFrameHeight % 2)
    443         {
    444             LogError("VBoxHeadless: ERROR: please specify an even VBOX_CAPTUREHEIGHT variable between 384 and 1536", 0);
    445             return -1;
    446         }
    447     }
    448 
    449     if ((pszEnvTemp = RTEnvGet("VBOX_CAPTUREBITRATE")) != 0)
    450     {
    451         errno = 0;
    452         ulBitRate = strtoul(pszEnvTemp, 0, 10);
    453         if (errno != 0)
    454         {
    455             LogError("VBoxHeadless: ERROR: invalid VBOX_CAPTUREBITRATE environment variable", 0);
    456             return -1;
    457         }
    458         if (ulBitRate < 300000 || ulBitRate > 1000000)
    459         {
    460             LogError("VBoxHeadless: ERROR: please specify an even VBOX_CAPTUREHEIGHT variable between 300000 and 1000000", 0);
    461             return -1;
    462         }
    463     }
    464 
    465     if ((pszEnvTemp = RTEnvGet("VBOX_CAPTUREFILE")) == 0)
    466         /* Standard base name */
    467         pszEnvTemp = "VBox-%d.vob";
    468 
    469     /* Make sure we only have %d or %u (or none) */
    470     char *pcPercent = (char*)strchr(pszEnvTemp, '%');
     445            case 'p':
     446                vrdpPort = ValueUnion.u32;
     447                break;
     448            case 'a':
     449                vrdpAddress = ValueUnion.psz;
     450                break;
     451#endif /* VBOX_WITH_VRDP defined */
     452            case OPT_RAW_R0:
     453                fRawR0 = true;
     454                break;
     455            case OPT_NO_RAW_R0:
     456                fRawR0 = false;
     457                break;
     458            case OPT_RAW_R3:
     459                fRawR3 = true;
     460                break;
     461            case OPT_NO_RAW_R3:
     462                fRawR3 = false;
     463                break;
     464            case OPT_PATM:
     465                fPATM = true;
     466                break;
     467            case OPT_NO_PATM:
     468                fPATM = false;
     469                break;
     470            case OPT_CSAM:
     471                fCSAM = true;
     472                break;
     473            case OPT_NO_CSAM:
     474                fCSAM = false;
     475                break;
     476#ifdef VBOX_FFMPEG
     477            case 'c':
     478                fFFMPEG = true;
     479                break;
     480            case 'w':
     481                ulFrameWidth = ValueUnion.u32;
     482                break;
     483            case 'h':
     484                ulFrameHeight = ValueUnion.u32;
     485                break;
     486            case 'r':
     487                ulBitRate = ValueUnion.u32;
     488                break;
     489            case 'f':
     490                pszFileNameParam = ValueUnion.psz;
     491                break;
     492#endif /* VBOX_FFMPEG defined */
     493            default: /* comment */
     494                break;
     495        }
     496    }
     497
     498#ifdef VBOX_FFMPEG
     499    if (ulFrameWidth < 512 || ulFrameWidth > 2048 || ulFrameWidth % 2)
     500    {
     501        LogError("VBoxHeadless: ERROR: please specify an even frame width between 512 and 2048", 0);
     502        return -1;
     503    }
     504    if (ulFrameHeight < 384 || ulFrameHeight > 1536 || ulFrameHeight % 2)
     505    {
     506        LogError("VBoxHeadless: ERROR: please specify an even frame height between 384 and 1536", 0);
     507        return -1;
     508    }
     509    if (ulBitRate < 300000 || ulBitRate > 1000000)
     510    {
     511        LogError("VBoxHeadless: ERROR: please specify an even bitrate between 300000 and 1000000", 0);
     512        return -1;
     513    }
     514    /* Make sure we only have %d or %u (or none) in the file name specified */
     515    char *pcPercent = (char*)strchr(pszFileNameParam, '%');
    471516    if (pcPercent != 0 && *(pcPercent + 1) != 'd' && *(pcPercent + 1) != 'u')
    472517    {
    473         LogError("VBoxHeadless: ERROR: Only %%d and %%u are allowed in the VBOX_CAPTUREFILE parameter.", -1);
     518        LogError("VBoxHeadless: ERROR: Only %%d and %%u are allowed in the capture file name.", -1);
    474519        return -1;
    475520    }
    476 
    477521    /* And no more than one % in the name */
    478522    if (pcPercent != 0 && strchr(pcPercent + 1, '%') != 0)
    479523    {
    480         LogError("VBoxHeadless: ERROR: Only one format modifier is allowed in the VBOX_CAPTUREFILE parameter.", -1);
     524        LogError("VBoxHeadless: ERROR: Only one format modifier is allowed in the capture file name.", -1);
    481525        return -1;
    482526    }
    483     RTStrPrintf(&pszMPEGFile[0], RTPATH_MAX, pszEnvTemp, RTProcSelf());
     527    RTStrPrintf(&pszMPEGFile[0], RTPATH_MAX, pszFileNameParam, RTProcSelf());
    484528#endif /* defined VBOX_FFMPEG */
    485529
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