FreeWRL / FreeX3D 4.3.0
options.c
1/*
2
3 FreeWRL command line arguments.
4
5*/
6
7/****************************************************************************
8 This file is part of the FreeWRL/FreeX3D Distribution.
9
10 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
11
12 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
13 it under the terms of the GNU Lesser Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
16
17 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
24****************************************************************************/
25
26
27#include <config.h>
28#include <system.h>
29//#include <internal.h>
30#define ERROR_MSG
31#define DEBUG_MSG
32#define TRACE_MSG
33#include <libFreeWRL.h>
34
35#include "main.h"
36#include "options.h"
37#include "../sound/internal.h"
38#include "../lib/ui/common.h"
39
40#if HAVE_GETOPT_H
41#include <getopt.h>
42#endif
43
44#if !defined(min)
45 #define min(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __a : __b; })
46#endif
47
48#if !defined(max)
49 #define max(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; })
50#endif
51
52void fv_print_version()
53{
54 const char *libver, *progver;
55
56 libver = libFreeWRL_get_version();
57 progver = freewrl_get_version();
58
59 printf("Program version: %s\nLibrary version: %s\n", progver, libver);
60 printf("\nFreeWRL VRML/X3D browser from (http://freewrl.sf.net)\n");
61 printf(" type \"man freewrl\" to view man pages\n\n");
62}
63
64void fv_usage()
65{
66 printf( "usage: freewrl [options] <VRML or X3D file|URL>\n\n"
67 " -h|--help This help.\n"
68 " -v|--version Print version.\n"
69 "\nWindow options:\n"
70 " -c|--fullscreen Set window fullscreen\n"
71 " -g|--geometry <WxH> Set window geometry (W width, H height).\n"
72 " -b|--big Set window size to 800x600.\n"
73 "\nGeneral options:\n"
74 " -e|--eai Enable EAI.\n"
75 // " -f|--fast Set global texture size to -256 (fast).\n"
76 " -W|--linewidth <float> Set line width.\n"
77 //" -Q|--nocollision Disable collision management.\n"
78 "\nSnapshot options:\n"
79 " -p|--gif Set file format to GIF (default is PNG).\n"
80 " -n|--snapfile <string> Set output file name pattern with <string>,\n"
81 " (use %%n for iteration number).\n"
82 " -o|--snaptmp <string> Set output directory for snap files.\n"
83 "\nMisc options:\n"
84 " -V|--eaiverbose Set EAI subsystem messages.\n"
85 " -r|--screendist <float> Set screen distance.\n"
86 " -y|--eyedist <float> Set eye distance.\n"
87 " -u|--shutter Set shutter glasses.\n"
88 " -t|--stereo <float> Set stereo parameter (angle factor).\n"
89 " -A|--anaglyph <string> Set anaglyph color pair ie: RB for left red, right blue. any of RGBCAM.\n"
90 " -B|--sidebyside Set side-by-side stereo.\n"
91 " -U|--updown Set updown stereo.\n"
92 " -q|--cardboard set cardboard stereo \n"
93 " -Q|--quadrant set quadrant view \n"
94 " -O|--screenorient set screen orientation degrees {0 90 180 270} \n"
95 " -T|--touchtype set pointing device touch type {0=single 1=emulate multitouch 2=multitouch 3=gesture \n"
96 " -K|--keypress <string> Set immediate key pressed when ready.\n"
97 " -R|--record Record to /recording/<scene>.fwplay.\n"
98 " -P|--playback Playback from /recording/<scene>.fwplay to /playback\n"
99 " -I|--pin TF Pin statusbar(T/F) menubar(T/F)\n"
100 " -w|--want TF Want statusbar(T/F) menubar(T/F)\n"
101 " -E|--FPS <int> Target Maximum Frames Per Second\n"
102 " =^|--shadingStyle <int> 0=Flat 1=gouraud 2=phong 3=wire\n"
103 " -D|--DIS Allow Distributed Interactive Simulation\n"
104 " --DISaddress <string> DIS default ipv4 address or localhost \n"
105 " --DISport <int> DIS default port 1000 - 99999\n"
106 " --DISsite <int> DIS default site ID (facility / room ID) 1-255\n"
107 " --DISapp <int> DIS application instance ID 1-255\n"
108 " --DISverbose DIS console display of received pdus\n"
109 " -S|--set <int> testing set default 0, added to port number for DIS\n"
110 " -J|--javascript <string> SM spidermonkey, DUK duktape, NONE stubs\n"
111 " -x|--boxes Draw bounding boxes\n"
112 " -X|--viewpoints Show viewpointss\n"
113 " -l|--rig Draw HAnim rig\n"
114 " -M|--midi <int> choose MIDI transport 1=msg 2=ump\n"
115 "\nInternal options:\n"
116 " -i|--plugin <string> Called from plugin.\n"
117 " -j|--fd <number> Pipe to command the program.\n"
118 " -k|--instance <number> Instance of plugin.\n"
119 " -L|--logfile <filename> Log file where all messages should go.\n"
120 " --skinGPU TF for HAnim T= GPU skinning F= CPU skinning .\n"
121#ifdef HAVE_LIBCURL
122 " -C|--curl Use libcurl instead of wget.\n"
123#endif
124 "\n\n"
125 );
126 //" -G|--colorscheme <string> UI colorscheme by builtin name: {original,angry,\n"
127 // " aqua,favicon,midnight,neon:lime,neon:yellow,neon:cyan,neon:pink}\n"
128 // " -H|--colors <string> UI colorscheme by 4 html colors in order: \n"
129 // " panel,menuIcon,statusText,messageText ie \"#3D4557,#00FFFF,#00FFFF.#00FFFF\" \n"
130
131}
132
133const char * fv_validate_string_arg(const char *optarg)
134{
135 return NULL; /* TODO: implement validate_* functions */
136}
137 static struct option long_options[] = {
138
139/* { const char *name, int has_arg, int *flag, int val }, */
140
141 {"help", no_argument, 0, 'h'},
142 {"version", no_argument, 0, 'v'},
143
144 {"fullscreen", no_argument, 0, 'c'},
145 {"FPS", required_argument, 0, 'E'},
146 {"pin", required_argument, 0, 'I'},
147 {"want", required_argument, 0, 'w'},
148 {"geometry", required_argument, 0, 'g'},
149 {"big", no_argument, 0, 'b'},
150
151 {"eai", no_argument, 0, 'e'},
152 //{"fast", no_argument, 0, 'f'},
153 {"linewidth", required_argument, 0, 'W'},
154 //{"nocollision", no_argument, 0, 'Q'},
155 {"rig",no_argument,0,'l'},
156
157 {"gif", no_argument, 0, 'p'},
158 {"snapfile", required_argument, 0, 'n'},
159 {"snaptmp", required_argument, 0, 'o'},
160
161 {"eaiverbose", no_argument, 0, 'V'},
162 {"screendist", required_argument, 0, 'r'},
163 {"eyedist", required_argument, 0, 'y'},
164 {"shutter", no_argument, 0, 'u'},
165 {"stereo", required_argument, 0, 't'},
166 {"anaglyph", required_argument, 0, 'A'},
167 {"sidebyside", no_argument, 0, 'B'},
168 {"cardboard", no_argument, 0, 'q'},
169 {"quadrant", no_argument, 0, 'Q'},
170 {"screenorient", required_argument, 0, 'O'},
171 {"touchtype", required_argument, 0, 'T'},
172 {"updown", no_argument, 0, 'U'},
173 {"keypress", required_argument, 0, 'K'},
174 {"plugin", required_argument, 0, 'i'},
175 {"fd", required_argument, 0, 'j'},
176 {"instance", required_argument, 0, 'k'},
177 {"logfile", required_argument, 0, 'L'},
178
179 {"curl", no_argument, 0, 'C'},
180
181 {"display", required_argument, 0, 'd'}, /* Roberto Gerson */
182 {"record", no_argument, 0, 'R'},
183 {"playback", no_argument, 0, 'P'},
184 {"colorscheme", required_argument, 0, 'G'},
185 {"colors", required_argument, 0, 'H'},
186 {"shadingStyle",required_argument,0,'^'},
187 {"set",required_argument,0,'S'},
188 {"javascript",required_argument,0,'J'},
189 {"boxes",no_argument,0,'x'},
190 {"viewpoints",no_argument,0,'X'},
191 {"midi",required_argument,0,'M'},
192 {"DIS",no_argument,0,'D'},
193 {"DISaddress",required_argument,0,128},
194 {"DISport",required_argument,0,129},
195 {"DISsite",required_argument,0,130},
196 {"DISapp",required_argument,0,131},
197 {"skinGPU",required_argument,0,132},
198 {"DISverbose",no_argument,0,133},
199 {0, 0, 0, 0}
200 };
201
202int fv_find_opt_for_optopt(char c) {
203 int i;
204 struct option *p;
205
206 /* initialization */
207 i = 0;
208 p = &(long_options[i]);
209
210 while (p->name) {
211 if (!p->flag) {
212 if (p->val == c) {
213 return i;
214 }
215 }
216 p = &(long_options[++i]);
217 }
218 return -1;
219}
220
221//freewrl_params_t *fv_params = NULL;
222
223int fv_parseCommandLine (int argc, char **argv, freewrl_params_t *fv_params, int *url_index)
224{
225 int c, itmp;
226 float ftmp;
227 long* ldtmp;
228 int option_index = 0;
229 int real_option_index;
230 const char *real_option_name;
231 //char *logFileName = NULL;
232 //FILE *fp;
233
234 static const char optstring[] = "efg:hi:j:k:vVpn:o:O:bsQqW:K:Xcr:y:utCL:d:RT:FPN:Y:DS:J:xM:l"; //':' means the preceding option requires an arguement
235
236
237 *url_index = -1;
238#if defined(_DEBUG) || defined(DEBUG)
239 for(c=0;c<argc;c++)
240 printf("argv[%d]=%s\n",c,argv[c]);
241#endif //DEBUG
242 optind = 1;
243 while (1) {
244
245 /* Do we want getopt to print errors by itself ? */
246 opterr = 0;
247
248# if HAVE_GETOPT_LONG
249
250#if defined(_MSC_VER)
251#define strncasecmp _strnicmp
252 c = _getopt_internal (argc, argv, optstring, long_options, &option_index, 0);
253#else //_MSC_VERF
254 c = getopt_long(argc, argv, optstring, long_options, &option_index);
255#endif
256# else //HAVE_GETOPT_LONG
257 c = getopt(argc, argv, optstring);
258
259# endif //HAVE_GETOPT_LONG
260//#define _DEBUG 1
261#if defined(_DEBUG) || defined(DEBUG)
262 printf("c=%c argv[%d]=%s\n",c,optind,argv[optind]);
263#define DEBUG_ARGS printf
264#else
265#define DEBUG_ARGS
266#endif //DEBUG
267
268 if (c == -1)
269 break;
270
271
272 if ((c == '?')) {
273 real_option_index = fv_find_opt_for_optopt(optopt);
274 } else {
275 real_option_index = fv_find_opt_for_optopt(c);
276 }
277 if (real_option_index < 0) {
278 real_option_name = argv[optind-1];
279 } else {
280 real_option_name = long_options[real_option_index].name;
281 }
282 DEBUG_ARGS("option_index=%d optopt=%c option=%s\n", real_option_index, c,
283 real_option_name);
284
285 switch (c) {
286
287 /* Error handling */
288
289 case '?': /* getopt error: unknown option or missing argument */
290 printf("ERROR: unknown option or missing argument to option: %c (%s)\n",
291 c, real_option_name);
292 //fwExit(1);
293 //return TRUE;
294 break;
295
296 /* Options handling */
297
298 case 'h': /* --help, no argument */
299 fv_usage();
300 //fwExit(0);
301 return FALSE;
302 break;
303
304 case 'v': /* --version, no argument */
305 fv_print_version();
306 //fwExit(0);
307 return FALSE;
308 break;
309
310/* Window options */
311
312 case 'c': /* --fullscreen, no argument */
313
314// OLD_IPHONE_AQUA #if !defined(TARGET_AQUA)
315#ifdef _MSC_VER
316 fv_params->fullscreen = TRUE; //win32 will look at this in its internal code
317#else
318#if defined(HAVE_XF86_VMODE)
319 fv_params->fullscreen = TRUE;
320#else
321 printf("\nFullscreen mode is only available when xf86vmode extension is\n"
322 "supported by your X11 server: i.e. XFree86 version 4 or later,\n"
323 "Xorg version 1.0 or later.\n"
324 "Configure should autodetect it for you. If not please report"
325 "this problem to\n\t " PACKAGE_BUGREPORT "\n");
326 fv_params->fullscreen = FALSE;
327#endif /* HAVE_XF86_VMODE */
328#endif
329
330// OLD_IPHONE_AQUA #endif /* TARGET_AQUA */
331
332
333 break;
334
335 case 'g': /* --geometry, required argument: string (ex: 1024x768+100+50) */
336 if (!optarg) {
337 ERROR_MSG("Argument missing for option -g/--geometry\n");
338 //fwExit(1);
339 return FALSE;
340 } else {
341 if (!fwl_parse_geometry_string(optarg,
342 &fv_params->width, &fv_params->height,
343 &fv_params->xpos, &fv_params->ypos, &fv_params->wnum)) {
344 ERROR_MSG("Malformed geometry string: %s\n", optarg);
345 return FALSE;
346 }
347 }
348 break;
349
350 case 'b': /* --big, no argument */
351 fv_params->width = 800;
352 fv_params->height = 600;
353 break;
354
355 case 'd': /* --display, required argument int */
356 printf ("Parameter --display = %s\n", optarg);
357 sscanf(optarg,"%zu", (size_t*)&ldtmp);
358 fv_params->winToEmbedInto = ldtmp;
359 break;
360
361
362
363/* General options */
364
365 case 'e': /* --eai, no argument */
366 fv_params->enableEAI = TRUE;
367 break;
368
369 //case 'f': /* --fast, no argument */
370 // /* does nothing right now */
371 // break;
372
373 case 'W': /* --linewidth, required argument: float */
374 sscanf(optarg,"%g", &ftmp);
375 fwl_set_LineWidth(ftmp);
376 break;
377
378 //case 'Q': /* --nocollision, no argument */
379 // //fv_params->collision = FALSE; //this is the default
380 // ConsoleMessage ("ignoring collision off mode on command line");
381 // break;
382
383/* Snapshot options */
384#ifndef FRONTEND_DOES_SNAPSHOTS
385 case 'p': /* --gif, no argument */
386 fwl_init_SnapGif();
387 break;
388
389 case 'n': /* --snapfile, required argument: string */
390 fwl_set_SnapFile(optarg);
391 break;
392
393 case 'o': /* --snaptmp, required argument: string */
394 fwl_set_SnapTmp(optarg);
395 break;
396#endif
397
398/* Misc options */
399
400 case 'V': /* --eaiverbose, no argument */
401 fwl_init_EaiVerbose();
402 fv_params->verbose = TRUE;
403 break;
404
405 case 'r': /* --screendist, required argument: float */
406 fwl_set_ScreenDist(optarg);
407 break;
408
409 case 'y': /* --eyedist, required argument: float */
410 fwl_set_EyeDist(optarg);
411 break;
412
413 case 'u': /* --shutter, no argument */
414 fwl_init_Shutter();
415 /*setXEventStereo();*/
416 break;
417
418 case 'x': /* bounding boxes */
419 fwl_setDrawBoundingBoxes(1);
420 break;
421 case 'X': /* viewpoints */
422 fwl_setShowViewpoints(1);
423 break;
424
425 case 't': /* --stereo, required argument: float */
426 fwl_set_StereoParameter(optarg);
427 break;
428 case 'A': /* --anaglyph, required argument: string */
429 fwl_set_AnaglyphParameter(optarg);
430 break;
431
432 case 'B': /* --sidebyside, no argument */
433 fwl_init_SideBySide();
434 break;
435 case 'D': /* --DIS, no argument */
436 fwl_init_DIS();
437 break;
438 case 128: /* --DISaddress <string> */
439 fwl_set_DISaddress(optarg);
440 break;
441 case 129: /* --DISport <integer 1000-99999> */
442 sscanf(optarg, "%d", &itmp);
443 fwl_set_DISport(itmp);
444 break;
445 case 130: /* --DISsite <int 1-255> */
446 sscanf(optarg, "%d", &itmp);
447 fwl_set_DISsite(itmp);
448 break;
449 case 131: /* --DISapp <int 1-255> */
450 sscanf(optarg, "%d", &itmp);
451 fwl_set_DISapplication(itmp);
452 break;
453
454 case 133: /* --DISverbose no param */
455 fwl_set_DISverbose(TRUE);
456 break;
457
458 case 132: /* --skinGPU T/F */
459 fwl_set_skinning(optarg[0]);
460 break;
461
462
463 case 'S': /* --set, required argument: int */
464 sscanf(optarg, "%d", &itmp);
465 fwl_set_testset(itmp);
466 break;
467
468 case 'U': /* --updown, no argument */
469 fwl_init_UpDown();
470 break;
471 case 'q': /* --cardboard, no argument */
472 fwl_init_cardboard();
473 break;
474 case 'Q': /* --quadrant, no argument */
475 fwl_init_quadrant();
476 break;
477 case 'O': /* --screenorient {0,90,180,270} */
478 {
479 int degrees;
480 sscanf(optarg,"%d",&degrees);
481 if(degrees != 0 && degrees != 90 && degrees != 180 && degrees != 270 ) degrees = 0;
482 fwl_setOrientation2(degrees);
483 }
484 break;
485 case 'T': /* --touchtype {0=single/mouse 1=emulate multitouch 2=multitouch 3=gesture */
486 {
487 int ttype;
488 sscanf(optarg,"%d",&ttype);
489 if(ttype < 0 || ttype > 3) ttype = 0;
490 fwl_set_touchtype(ttype);
491 //ms windows: gestures are default, need to register window for touches if desired
492 fv_params->touchtype = ttype;
493
494 }
495 break;
496 case 'K': /* --keypress, required argument: string */
497 /* initial string of keypresses once main url is loaded */
498 fwl_set_KeyString(optarg);
499 break;
500
501 //case 'G': /* --colorscheme string */
502 // fwl_set_ui_colorscheme(optarg);
503 // break;
504 //case 'H': /* --colors string */
505 // fwl_set_ui_colors(optarg);
506 // break;
507
508 case 'I': /* --pin TF */
509 fwl_set_sbh_pin_option(optarg);
510 break;
511 case 'w': /* --want TF */
512 fwl_set_sbh_want_option(optarg);
513 break;
514 case '^': /* --shadingStyle 0=Flat 1=Gouraud 2=Phong 3=wire */
515 {
516 int ival = optarg[0] - '0';
517 fwl_setShadingStyle(max(min(ival,3),0));
518 }
519 break;
520 case 'E': /* --FPS, required argument: int */
521 sscanf(optarg,"%d", &itmp);
522 fwl_set_target_fps(itmp);
523 break;
524
525/* Internal options */
526
527 case 'i': /* --plugin, required argument: number */
528 sscanf(optarg,"pipe:%d",&_fw_pipe);
529 isBrowserPlugin = TRUE;
530 break;
531
532 case 'j': /* --fd, required argument: number */
533 sscanf(optarg,"%d",&_fw_browser_plugin);
534 break;
535
536 case 'k': /* --instance, required argument: number */
537 sscanf(optarg,"%u",(unsigned int *)(void *)(&_fw_instance));
538 break;
539
540 case 'l': /* --rig no arg*/
541 fwl_setDrawRig(TRUE);
542 break;
543
544 case 'L': /* --logfile, required argument: log filename */
545 if (optarg) {
546 //logFileName = strdup(optarg);
547 fwl_set_logfile(optarg);
548 } else {
549 ERROR_MSG("Option -L|--logfile: log filename required\n");
550 return FALSE;
551 }
552 break;
553 case 'J': /* --javascript, required argument: string */
554 fwl_setJsEngine(optarg);
555 break;
556 case 'R': /* --record, no arg */
557 fwl_set_modeRecord();
558 break;
559 case 'P': /* --playback, no arg */
560 fwl_set_modePlayback();
561 break;
562#ifdef HAVE_LIBREMIDI
563 case 'M': /* --midi, int 1 or 2 for midi transport */
564 {
565 int ival = 2;
566 sscanf(optarg, "%d", &ival);
567 set_MIDITransport(ival);
568 }
569 break;
570#endif
571
572
573#ifdef HAVE_LIBCURL
574 case 'C': /* --curl, no argument */
575 with_libcurl = TRUE;
576 break;
577#endif
578
579 default:
580 ERROR_MSG("ERROR: getopt returned character code 0%o, unknown error.\n", c);
581 //fwExit(1);
582 //return FALSE;
583 break;
584 }
585 }
586
587 // moved to fwl_set_logfile(char*)/* Quick hack: redirect stdout and stderr to logFileName if supplied */
588 // if (logFileName) {
589 //if (strncasecmp(logFileName, "-", 1) == 0) {
590 // printf("FreeWRL: output to stdout/stderr\n");
591 //} else {
592 // printf ("FreeWRL: redirect stdout and stderr to %s\n", logFileName);
593 // fp = freopen(logFileName, "a", stdout);
594 // if (NULL == fp) {
595 // WARN_MSG("WARNING: Unable to reopen stdout to %s\n", logFileName) ;
596 // }
597 // fp = freopen(logFileName, "a", stderr);
598 // if (NULL == fp) {
599 // WARN_MSG("WARNING: Unable to reopen stderr to %s\n", logFileName) ;
600 // }
601 //}
602 // }
603
604 if (optind < argc) {
605 if (optind != (argc-1)) {
606 ERROR_MSG("FreeWRL accepts only one argument: we have %d\n", (argc-optind));
607 return FALSE;
608 }
609 DEBUG_MSG("Start url: %s\n", argv[optind]);
610 //start_url = STRDUP(argv[optind]);
611 *url_index = optind;
612 }
613
614 return TRUE;
615}
616
617void fv_parseEnvVars()
618{
619 /* Check environment */
620 fwl_set_strictParsing (getenv("FREEWRL_STRICT_PARSING") != NULL);
621 fwl_set_plugin_print (getenv("FREEWRL_DO_PLUGIN_PRINT") != NULL);
622 fwl_set_occlusion_disable (getenv("FREEWRL_NO_GL_ARB_OCCLUSION_QUERY") != NULL);
623 fwl_set_print_opengl_errors (getenv("FREEWRL_PRINT_OPENGL_ERRORS") != NULL);
624 fwl_set_trace_threads (getenv("FREEWRL_TRACE_THREADS") != NULL);
625 {
626 char *env_texture_size = getenv("FREEWRL_TEXTURE_SIZE");
627 if (env_texture_size) {
628 unsigned int local_texture_size ;
629 sscanf(env_texture_size, "%u", &local_texture_size);
630 TRACE_MSG("Env: TEXTURE SIZE %u.\n", local_texture_size);
631 fwl_set_texture_size(local_texture_size);
632 }
633 }
634}