script to create a man page from blenders --help text, replaced the hand edited man...
[blender.git] / source / creator / creator.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #if defined(__linux__) && defined(__GNUC__)
31 #define _GNU_SOURCE
32 #include <fenv.h>
33 #endif
34
35 #define OSX_SSE_FPE (defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__)))
36
37 #if OSX_SSE_FPE
38 #include <xmmintrin.h>
39 #endif
40
41 #include <stdlib.h>
42 #include <string.h>
43
44 /* for setuid / getuid */
45 #ifdef __sgi
46 #include <sys/types.h>
47 #include <unistd.h>
48 #endif
49
50 /* This little block needed for linking to Blender... */
51
52 #include "MEM_guardedalloc.h"
53
54 #ifdef WIN32
55 #include "BLI_winstuff.h"
56 #endif
57
58 #include "BLI_args.h"
59 #include "BLI_threads.h"
60
61 #include "GEN_messaging.h"
62
63 #include "DNA_ID.h"
64 #include "DNA_scene_types.h"
65
66 #include "BLI_blenlib.h"
67
68 #include "BKE_utildefines.h"
69 #include "BKE_blender.h"
70 #include "BKE_context.h"
71 #include "BKE_font.h"
72 #include "BKE_global.h"
73 #include "BKE_main.h"
74 #include "BKE_material.h"
75 #include "BKE_packedFile.h"
76 #include "BKE_scene.h"
77 #include "BKE_node.h"
78 #include "BKE_report.h"
79 #include "BKE_sound.h"
80
81 #include "IMB_imbuf.h"  // for IMB_init
82
83 #ifndef DISABLE_PYTHON
84 #include "BPY_extern.h"
85 #endif
86
87 #include "RE_pipeline.h"
88
89 //XXX #include "playanim_ext.h"
90 #include "ED_datafiles.h"
91
92 #include "WM_api.h"
93
94 #include "RNA_define.h"
95
96 #include "GPU_draw.h"
97 #include "GPU_extensions.h"
98
99 /* for passing information between creator and gameengine */
100 #include "SYS_System.h"
101
102 #include <signal.h>
103
104 #ifdef __FreeBSD__
105 # include <sys/types.h>
106 # include <floatingpoint.h>
107 # include <sys/rtprio.h>
108 #endif
109
110 #ifdef WITH_BINRELOC
111 #include "binreloc.h"
112 #endif
113
114 // from buildinfo.c
115 #ifdef BUILD_DATE
116 extern char build_date[];
117 extern char build_time[];
118 extern char build_rev[];
119 extern char build_platform[];
120 extern char build_type[];
121 #endif
122
123 /*      Local Function prototypes */
124 static int print_help(int argc, char **argv, void *data);
125 static int print_version(int argc, char **argv, void *data);
126
127 /* for the callbacks: */
128
129 extern int pluginapi_force_ref(void);  /* from blenpluginapi:pluginapi.c */
130
131 char bprogname[FILE_MAXDIR+FILE_MAXFILE]; /* from blenpluginapi:pluginapi.c */
132 char btempdir[FILE_MAXDIR+FILE_MAXFILE];
133
134 /* unix path support.
135  * defined by the compiler. eg "/usr/share/blender/2.5" "/opt/blender/2.5" */
136 #ifndef BLENDERPATH
137 #define BLENDERPATH ""
138 #endif
139  
140 char blender_path[FILE_MAXDIR+FILE_MAXFILE] = BLENDERPATH;
141
142 /* Initialise callbacks for the modules that need them */
143 static void setCallbacks(void); 
144
145 /* set breakpoints here when running in debug mode, useful to catch floating point errors */
146 #if defined(__sgi) || defined(__linux__) || defined(_WIN32) || OSX_SSE_FPE
147 static void fpe_handler(int sig)
148 {
149         // printf("SIGFPE trapped\n");
150 }
151 #endif
152
153 /* handling ctrl-c event in console */
154 static void blender_esc(int sig)
155 {
156         static int count = 0;
157         
158         G.afbreek = 1;  /* forces render loop to read queue, not sure if its needed */
159         
160         if (sig == 2) {
161                 if (count) {
162                         printf("\nBlender killed\n");
163                         exit(2);
164                 }
165                 printf("\nSent an internal break event. Press ^C again to kill Blender\n");
166                 count++;
167         }
168 }
169
170 /* buildinfo can have quotes */
171 #ifdef BUILD_DATE
172 static void strip_quotes(char *str)
173 {
174     if(str[0] == '"') {
175         int len= strlen(str) - 1;
176         memmove(str, str+1, len);
177         if(str[len-1] == '"') {
178             str[len-1]= '\0';
179         }
180     }
181 }
182 #endif
183
184 static int print_version(int argc, char **argv, void *data)
185 {
186 #ifdef BUILD_DATE
187         printf ("Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
188         printf ("\tbuild date: %s\n", build_date);
189         printf ("\tbuild time: %s\n", build_time);
190         printf ("\tbuild revision: %s\n", build_rev);
191         printf ("\tbuild platform: %s\n", build_platform);
192         printf ("\tbuild type: %s\n", build_type);
193 #else
194         printf ("Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
195 #endif
196
197         exit(0);
198
199         return 0;
200 }
201
202 static int print_help(int argc, char **argv, void *data)
203 {
204         bArgs *ba = (bArgs*)data;
205
206         printf ("Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
207         printf ("Usage: blender [args ...] [file] [args ...]\n\n");
208
209         printf ("Render Options:\n");
210         BLI_argsPrintArgDoc(ba, "--background");
211         BLI_argsPrintArgDoc(ba, "--render-anim");
212         BLI_argsPrintArgDoc(ba, "--scene");
213         BLI_argsPrintArgDoc(ba, "--render-frame");
214         BLI_argsPrintArgDoc(ba, "--frame-start");
215         BLI_argsPrintArgDoc(ba, "--frame-end");
216         BLI_argsPrintArgDoc(ba, "--frame-jump");
217         BLI_argsPrintArgDoc(ba, "--render-output");
218         BLI_argsPrintArgDoc(ba, "--engine");
219         
220         printf("\n");
221         printf ("Format Options:\n");
222         BLI_argsPrintArgDoc(ba, "--render-format");
223         BLI_argsPrintArgDoc(ba, "--use-extension");
224         BLI_argsPrintArgDoc(ba, "--threads");
225
226         printf("\n");
227         printf ("Animation Playback Options:\n");
228         BLI_argsPrintArgDoc(ba, "-a");
229                                 
230         printf("\n");
231         printf ("Window Options:\n");
232         BLI_argsPrintArgDoc(ba, "--window-border");
233         BLI_argsPrintArgDoc(ba, "--window-borderless");
234         BLI_argsPrintArgDoc(ba, "--window-geometry");
235
236         printf("\n");
237         printf ("Game Engine Specific Options:\n");
238         BLI_argsPrintArgDoc(ba, "-g");
239
240         printf("\n");
241         printf ("Misc Options:\n");
242         BLI_argsPrintArgDoc(ba, "--debug");
243         BLI_argsPrintArgDoc(ba, "--debug-fpe");
244
245         printf("\n");
246
247         BLI_argsPrintArgDoc(ba, "-nojoystick");
248         BLI_argsPrintArgDoc(ba, "-noglsl");
249         BLI_argsPrintArgDoc(ba, "-noaudio");
250         BLI_argsPrintArgDoc(ba, "-setaudio");
251
252         printf("\n");
253
254         BLI_argsPrintArgDoc(ba, "--help");
255
256         printf("\n");
257
258         BLI_argsPrintArgDoc(ba, "--enable-autoexec");
259         BLI_argsPrintArgDoc(ba, "--disable-autoexec");
260
261         printf("\n");
262
263         BLI_argsPrintArgDoc(ba, "--python");
264         BLI_argsPrintArgDoc(ba, "--python-console");
265
266 #ifdef WIN32
267         BLI_argsPrintArgDoc(ba, "-R");
268 #endif
269         BLI_argsPrintArgDoc(ba, "--version");
270
271         BLI_argsPrintArgDoc(ba, "--");
272
273         printf ("Other Options:\n");
274         BLI_argsPrintOtherDoc(ba);
275
276         printf ("Argument Parsing:\n");
277         printf ("\targuments must be separated by white space. eg\n");
278         printf ("\t\t\"blender -ba test.blend\"\n");
279         printf ("\t...will ignore the 'a'\n");
280         printf ("\t\t\"blender -b test.blend -f8\"\n");
281         printf ("\t...will ignore 8 because there is no space between the -f and the frame value\n\n");
282
283         printf ("Argument Order:\n");
284         printf ("Arguments are executed in the order they are given. eg\n");
285         printf ("\t\t\"blender --background test.blend --render-frame 1 --render-output /tmp\"\n");
286         printf ("\t...will not render to /tmp because '--render-frame 1' renders before the output path is set\n");
287         printf ("\t\t\"blender --background --render-output /tmp test.blend --render-frame 1\"\n");
288         printf ("\t...will not render to /tmp because loading the blend file overwrites the render output that was set\n");
289         printf ("\t\t\"blender --background test.blend --render-output /tmp --render-frame 1\" works as expected.\n\n");
290
291         printf ("\nEnvironment Variables:\n");
292         printf ("  $HOME\t\t\tStore files such as .blender/ .B.blend .Bfs .Blog here.\n");
293         printf ("  $BLENDERPATH  System directory to use for data files and scripts.\n");
294         printf ("                For this build of blender the default $BLENDERPATH is...\n");
295         printf ("                \"%s\"\n", blender_path);
296         printf ("                setting the $BLENDERPATH will override this\n");
297 #ifdef WIN32
298         printf ("  $TEMP         Store temporary files here.\n");
299 #else
300         printf ("  $TMP or $TMPDIR  Store temporary files here.\n");
301 #endif
302 #ifndef DISABLE_SDL
303         printf ("  $SDL_AUDIODRIVER  LibSDL audio driver - alsa, esd, alsa, dma.\n");
304 #endif
305         printf ("  $PYTHONHOME   Path to the python directory, eg. /usr/lib/python.\n\n");
306
307         exit(0);
308
309         return 0;
310 }
311
312
313 double PIL_check_seconds_timer(void);
314
315 /* XXX This was here to fix a crash when running python scripts
316  * with -P that used the screen.
317  *
318  * static void main_init_screen( void )
319 {
320         setscreen(G.curscreen);
321         
322         if(G.main->scene.first==0) {
323                 set_scene( add_scene("1") );
324         }
325 }*/
326
327 static int end_arguments(int argc, char **argv, void *data)
328 {
329         return -1;
330 }
331
332 static int enable_python(int argc, char **argv, void *data)
333 {
334         G.f |= G_SCRIPT_AUTOEXEC;
335         return 0;
336 }
337
338 static int disable_python(int argc, char **argv, void *data)
339 {
340         G.f &= ~G_SCRIPT_AUTOEXEC;
341         return 0;
342 }
343
344 static int background_mode(int argc, char **argv, void *data)
345 {
346         G.background = 1;
347         return 0;
348 }
349
350 static int debug_mode(int argc, char **argv, void *data)
351 {
352         G.f |= G_DEBUG;         /* std output printf's */
353         printf ("Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
354         MEM_set_memory_debug();
355
356 #ifdef NAN_BUILDINFO
357         printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
358 #endif // NAN_BUILDINFO
359
360         BLI_argsPrint(data);
361         return 0;
362 }
363
364 static int set_fpe(int argc, char **argv, void *data)
365 {
366 #if defined(__sgi) || defined(__linux__) || defined(_WIN32) || OSX_SSE_FPE
367         /* zealous but makes float issues a heck of a lot easier to find!
368          * set breakpoints on fpe_handler */
369         signal(SIGFPE, fpe_handler);
370
371 # if defined(__linux__) && defined(__GNUC__)
372         feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );
373 # endif /* defined(__linux__) && defined(__GNUC__) */
374 # if OSX_SSE_FPE
375         /* OSX uses SSE for floating point by default, so here 
376          * use SSE instructions to throw floating point exceptions */
377         _MM_SET_EXCEPTION_MASK(_MM_MASK_MASK &~
378                                                    (_MM_MASK_OVERFLOW|_MM_MASK_INVALID|_MM_MASK_DIV_ZERO));
379 # endif /* OSX_SSE_FPE */
380 # if defined(_WIN32) && defined(_MSC_VER)
381         _controlfp_s(NULL, 0, _MCW_EM); /* enables all fp exceptions */
382         _controlfp_s(NULL, _EM_DENORMAL | _EM_UNDERFLOW | _EM_INEXACT, _MCW_EM); /* hide the ones we don't care about */
383 # endif /* _WIN32 && _MSC_VER */
384 #endif
385
386         return 0;
387 }
388
389 static int playback_mode(int argc, char **argv, void *data)
390 {
391         /* not if -b was given first */
392         if (G.background == 0) {
393
394 // XXX                          playanim(argc, argv); /* not the same argc and argv as before */
395                 exit(0);
396         }
397
398         return -2;
399 }
400
401 static int prefsize(int argc, char **argv, void *data)
402 {
403         int stax, stay, sizx, sizy;
404
405         if (argc < 5) {
406                 printf ("-p requires four arguments\n");
407                 exit(1);
408         }
409
410         stax= atoi(argv[1]);
411         stay= atoi(argv[2]);
412         sizx= atoi(argv[3]);
413         sizy= atoi(argv[4]);
414
415         WM_setprefsize(stax, stay, sizx, sizy);
416
417         return 4;
418 }
419
420 static int with_borders(int argc, char **argv, void *data)
421 {
422         /* with borders XXX OLD CRUFT!*/
423
424         return 0;
425 }
426
427 static int without_borders(int argc, char **argv, void *data)
428 {
429         /* borderless, win + linux XXX OLD CRUFT */
430         /* XXX, fixme mein, borderless on OSX */
431
432         return 0;
433 }
434
435 static int register_extension(int argc, char **argv, void *data)
436 {
437 #ifdef WIN32
438         char *path = BLI_argsArgv(data)[0];
439         RegisterBlendExtension(path);
440 #endif
441
442         return 0;
443 }
444
445 static int no_joystick(int argc, char **argv, void *data)
446 {
447         SYS_SystemHandle *syshandle = data;
448
449         /**
450                 don't initialize joysticks if user doesn't want to use joysticks
451                 failed joystick initialization delays over 5 seconds, before game engine start
452         */
453         SYS_WriteCommandLineInt(*syshandle, "nojoystick",1);
454         if (G.f & G_DEBUG) printf("disabling nojoystick\n");
455
456         return 0;
457 }
458
459 static int no_glsl(int argc, char **argv, void *data)
460 {
461         GPU_extensions_disable();
462         return 0;
463 }
464
465 static int no_audio(int argc, char **argv, void *data)
466 {
467         sound_force_device(0);
468         return 0;
469 }
470
471 static int set_audio(int argc, char **argv, void *data)
472 {
473         if (argc < 1) {
474                 printf("-setaudio require one argument\n");
475                 exit(1);
476         }
477
478         sound_force_device(sound_define_from_str(argv[1]));
479         return 1;
480 }
481
482 static int set_output(int argc, char **argv, void *data)
483 {
484         bContext *C = data;
485         if (argc >= 1){
486                 if (CTX_data_scene(C)) {
487                         Scene *scene= CTX_data_scene(C);
488                         BLI_strncpy(scene->r.pic, argv[1], FILE_MAXDIR);
489                 } else {
490                         printf("\nError: no blend loaded. cannot use '-o / --render-output'.\n");
491                 }
492                 return 1;
493         } else {
494                 printf("\nError: you must specify a path after '-o  / --render-output'.\n");
495                 return 0;
496         }
497 }
498
499 static int set_engine(int argc, char **argv, void *data)
500 {
501         bContext *C = data;
502         if (argc >= 1)
503         {
504                 if (!strcmp(argv[1],"help"))
505                 {
506                         RenderEngineType *type = NULL;
507
508                         for( type = R_engines.first; type; type = type->next )
509                         {
510                                 printf("\t%s\n", type->idname);
511                         }
512                         exit(0);
513                 }
514                 else
515                 {
516                         if (CTX_data_scene(C)==NULL)
517                         {
518                                 printf("\nError: no blend loaded. order the arguments so '-E  / --engine ' is after a blend is loaded.\n");
519                         }
520                         else
521                         {
522                                 Scene *scene= CTX_data_scene(C);
523                                 RenderData *rd = &scene->r;
524                                 RenderEngineType *type = NULL;
525
526                                 for( type = R_engines.first; type; type = type->next )
527                                 {
528                                         if (!strcmp(argv[1],type->idname))
529                                         {
530                                                 BLI_strncpy(rd->engine, type->idname, sizeof(rd->engine));
531                                         }
532                                 }
533                         }
534                 }
535
536                 return 1;
537         }
538         else
539         {
540                 printf("\nEngine not specified.\n");
541                 return 0;
542         }
543 }
544
545 static int set_image_type(int argc, char **argv, void *data)
546 {
547         bContext *C = data;
548         if (argc >= 1){
549                 char *imtype = argv[1];
550                 if (CTX_data_scene(C)==NULL) {
551                         printf("\nError: no blend loaded. order the arguments so '-F  / --render-format' is after the blend is loaded.\n");
552                 } else {
553                         Scene *scene= CTX_data_scene(C);
554                         if      (!strcmp(imtype,"TGA")) scene->r.imtype = R_TARGA;
555                         else if (!strcmp(imtype,"IRIS")) scene->r.imtype = R_IRIS;
556 #ifdef WITH_DDS
557                         else if (!strcmp(imtype,"DDS")) scene->r.imtype = R_DDS;
558 #endif
559                         else if (!strcmp(imtype,"JPEG")) scene->r.imtype = R_JPEG90;
560                         else if (!strcmp(imtype,"IRIZ")) scene->r.imtype = R_IRIZ;
561                         else if (!strcmp(imtype,"RAWTGA")) scene->r.imtype = R_RAWTGA;
562                         else if (!strcmp(imtype,"AVIRAW")) scene->r.imtype = R_AVIRAW;
563                         else if (!strcmp(imtype,"AVIJPEG")) scene->r.imtype = R_AVIJPEG;
564                         else if (!strcmp(imtype,"PNG")) scene->r.imtype = R_PNG;
565                         else if (!strcmp(imtype,"AVICODEC")) scene->r.imtype = R_AVICODEC;
566                         else if (!strcmp(imtype,"QUICKTIME")) scene->r.imtype = R_QUICKTIME;
567                         else if (!strcmp(imtype,"BMP")) scene->r.imtype = R_BMP;
568                         else if (!strcmp(imtype,"HDR")) scene->r.imtype = R_RADHDR;
569 #ifdef WITH_TIFF
570                         else if (!strcmp(imtype,"TIFF")) scene->r.imtype = R_TIFF;
571 #endif
572 #ifdef WITH_OPENEXR
573                         else if (!strcmp(imtype,"EXR")) scene->r.imtype = R_OPENEXR;
574                         else if (!strcmp(imtype,"MULTILAYER")) scene->r.imtype = R_MULTILAYER;
575 #endif
576                         else if (!strcmp(imtype,"MPEG")) scene->r.imtype = R_FFMPEG;
577                         else if (!strcmp(imtype,"FRAMESERVER")) scene->r.imtype = R_FRAMESERVER;
578                         else if (!strcmp(imtype,"CINEON")) scene->r.imtype = R_CINEON;
579                         else if (!strcmp(imtype,"DPX")) scene->r.imtype = R_DPX;
580 #if WITH_OPENJPEG
581                         else if (!strcmp(imtype,"JP2")) scene->r.imtype = R_JP2;
582 #endif
583                         else printf("\nError: Format from '-F / --render-format' not known or not compiled in this release.\n");
584                 }
585                 return 1;
586         } else {
587                 printf("\nError: you must specify a format after '-F  / --render-foramt'.\n");
588                 return 0;
589         }
590 }
591
592 static int set_threads(int argc, char **argv, void *data)
593 {
594         if (argc >= 1) {
595                 if(G.background) {
596                         RE_set_max_threads(atoi(argv[1]));
597                 } else {
598                         printf("Warning: threads can only be set in background mode\n");
599                 }
600                 return 1;
601         } else {
602                 printf("\nError: you must specify a number of threads between 0 and 8 '-t  / --threads'.\n");
603                 return 0;
604         }
605 }
606
607 static int set_extension(int argc, char **argv, void *data)
608 {
609         bContext *C = data;
610         if (argc >= 1) {
611                 if (CTX_data_scene(C)) {
612                         Scene *scene= CTX_data_scene(C);
613                         if (argv[1][0] == '0') {
614                                 scene->r.scemode &= ~R_EXTENSION;
615                         } else if (argv[1][0] == '1') {
616                                 scene->r.scemode |= R_EXTENSION;
617                         } else {
618                                 printf("\nError: Use '-x 1 / -x 0' To set the extension option or '--use-extension'\n");
619                         }
620                 } else {
621                         printf("\nError: no blend loaded. order the arguments so '-o ' is after '-x '.\n");
622                 }
623                 return 1;
624         } else {
625                 printf("\nError: you must specify a path after '- '.\n");
626                 return 0;
627         }
628 }
629
630 static int set_ge_parameters(int argc, char **argv, void *data)
631 {
632         SYS_SystemHandle syshandle = *(SYS_SystemHandle*)data;
633         int a = 0;
634 /**
635 gameengine parameters are automaticly put into system
636 -g [paramname = value]
637 -g [boolparamname]
638 example:
639 -g novertexarrays
640 -g maxvertexarraysize = 512
641 */
642
643         if(argc >= 1)
644         {
645                 char* paramname = argv[a];
646                 /* check for single value versus assignment */
647                 if (a+1 < argc && (*(argv[a+1]) == '='))
648                 {
649                         a++;
650                         if (a+1 < argc)
651                         {
652                                 a++;
653                                 /* assignment */
654                                 SYS_WriteCommandLineString(syshandle,paramname,argv[a]);
655                         }  else
656                         {
657                                 printf("error: argument assignment (%s) without value.\n",paramname);
658                                 return 0;
659                         }
660                         /* name arg eaten */
661
662                 } else {
663                         SYS_WriteCommandLineInt(syshandle,argv[a],1);
664
665                         /* doMipMap */
666                         if (!strcmp(argv[a],"nomipmap"))
667                         {
668                                 GPU_set_mipmap(0); //doMipMap = 0;
669                         }
670                         /* linearMipMap */
671                         if (!strcmp(argv[a],"linearmipmap"))
672                         {
673                                 GPU_set_linear_mipmap(1); //linearMipMap = 1;
674                         }
675
676
677                 } /* if (*(argv[a+1]) == '=') */
678         }
679
680         return a;
681 }
682
683 static int render_frame(int argc, char **argv, void *data)
684 {
685         bContext *C = data;
686         if (CTX_data_scene(C)) {
687                 Scene *scene= CTX_data_scene(C);
688
689                 if (argc > 1) {
690                         Render *re = RE_NewRender(scene->id.name);
691                         int frame;
692                         ReportList reports;
693
694                         switch(*argv[1]) {
695                         case '+':
696                                 frame= scene->r.sfra + atoi(argv[1]+1);
697                                 break;
698                         case '-':
699                                 frame= (scene->r.efra - atoi(argv[1]+1)) + 1;
700                                 break;
701                         default:
702                                 frame= atoi(argv[1]);
703                                 break;
704                         }
705
706                         BKE_reports_init(&reports, RPT_PRINT);
707
708                         frame = MIN2(MAXFRAME, MAX2(MINAFRAME, frame));
709
710                         RE_BlenderAnim(re, scene, scene->lay, frame, frame, scene->r.frame_step, &reports);
711                         return 1;
712                 } else {
713                         printf("\nError: frame number must follow '-f / --render-frame'.\n");
714                         return 0;
715                 }
716         } else {
717                 printf("\nError: no blend loaded. cannot use '-f / --render-frame'.\n");
718                 return 0;
719         }
720 }
721
722 static int render_animation(int argc, char **argv, void *data)
723 {
724         bContext *C = data;
725         if (CTX_data_scene(C)) {
726                 Scene *scene= CTX_data_scene(C);
727                 Render *re= RE_NewRender(scene->id.name);
728                 ReportList reports;
729                 BKE_reports_init(&reports, RPT_PRINT);
730                 RE_BlenderAnim(re, scene, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step, &reports);
731         } else {
732                 printf("\nError: no blend loaded. cannot use '-a'.\n");
733         }
734         return 0;
735 }
736
737 static int set_scene(int argc, char **argv, void *data)
738 {
739         if(argc > 1) {
740                 set_scene_name(argv[1]);
741                 return 1;
742         } else {
743                 printf("\nError: Scene name must follow '-S / --scene'.\n");
744                 return 0;
745         }
746 }
747
748 static int set_start_frame(int argc, char **argv, void *data)
749 {
750         bContext *C = data;
751         if (CTX_data_scene(C)) {
752                 Scene *scene= CTX_data_scene(C);
753                 if (argc > 1) {
754                         int frame = atoi(argv[1]);
755                         (scene->r.sfra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
756                         return 1;
757                 } else {
758                         printf("\nError: frame number must follow '-s / --frame-start'.\n");
759                         return 0;
760                 }
761         } else {
762                 printf("\nError: no blend loaded. cannot use '-s / --frame-start'.\n");
763                 return 0;
764         }
765 }
766
767 static int set_end_frame(int argc, char **argv, void *data)
768 {
769         bContext *C = data;
770         if (CTX_data_scene(C)) {
771                 Scene *scene= CTX_data_scene(C);
772                 if (argc > 1) {
773                         int frame = atoi(argv[1]);
774                         (scene->r.efra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
775                         return 1;
776                 } else {
777                         printf("\nError: frame number must follow '-e / --frame-end'.\n");
778                         return 0;
779                 }
780         } else {
781                 printf("\nError: no blend loaded. cannot use '-e / --frame-end'.\n");
782                 return 0;
783         }
784 }
785
786 static int set_skip_frame(int argc, char **argv, void *data)
787 {
788         bContext *C = data;
789         if (CTX_data_scene(C)) {
790                 Scene *scene= CTX_data_scene(C);
791                 if (argc > 1) {
792                         int frame = atoi(argv[1]);
793                         (scene->r.frame_step) = CLAMPIS(frame, 1, MAXFRAME);
794                         return 1;
795                 } else {
796                         printf("\nError: number of frames to step must follow '-j / --frame-jump'.\n");
797                         return 0;
798                 }
799         } else {
800                 printf("\nError: no blend loaded. cannot use '-j / --frame-jump'.\n");
801                 return 0;
802         }
803 }
804
805 /* macro for ugly context setup/reset */
806 #ifndef DISABLE_PYTHON
807 #define BPY_CTX_SETUP(_cmd) \
808 { \
809         wmWindowManager *wm= CTX_wm_manager(C); \
810         wmWindow *prevwin= CTX_wm_window(C); \
811         Scene *prevscene= CTX_data_scene(C); \
812         if(wm->windows.first) { \
813                 CTX_wm_window_set(C, wm->windows.first); \
814                 _cmd; \
815                 CTX_wm_window_set(C, prevwin); \
816         } \
817         else { \
818                 fprintf(stderr, "Python script \"%s\" running with missing context data.\n", argv[1]); \
819                 _cmd; \
820         } \
821         CTX_data_scene_set(C, prevscene); \
822 } \
823
824 #endif /* DISABLE_PYTHON */
825
826 static int run_python(int argc, char **argv, void *data)
827 {
828 #ifndef DISABLE_PYTHON
829         bContext *C = data;
830
831         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
832         if (argc > 1) {
833                 /* Make the path absolute because its needed for relative linked blends to be found */
834                 char filename[FILE_MAXDIR + FILE_MAXFILE];
835                 BLI_strncpy(filename, argv[1], sizeof(filename));
836                 BLI_path_cwd(filename);
837
838                 BPY_CTX_SETUP( BPY_run_python_script(C, filename, NULL, NULL) )
839
840                 return 1;
841         } else {
842                 printf("\nError: you must specify a Python script after '-P / --python'.\n");
843                 return 0;
844         }
845 #else
846         printf("This blender was built without python support\n");
847         return 0;
848 #endif /* DISABLE_PYTHON */
849 }
850
851 static int run_python_console(int argc, char **argv, void *data)
852 {
853 #ifndef DISABLE_PYTHON
854         bContext *C = data;     
855         const char *expr= "__import__('code').interact()";
856
857         BPY_CTX_SETUP( BPY_eval_string(C, expr) )
858
859         return 0;
860 #else
861         printf("This blender was built without python support\n");
862         return 0;
863 #endif /* DISABLE_PYTHON */
864 }
865
866 static int load_file(int argc, char **argv, void *data)
867 {
868         bContext *C = data;
869
870         /* Make the path absolute because its needed for relative linked blends to be found */
871         char filename[FILE_MAXDIR + FILE_MAXFILE];
872         BLI_strncpy(filename, argv[0], sizeof(filename));
873         BLI_path_cwd(filename);
874
875         if (G.background) {
876                 int retval = BKE_read_file(C, filename, NULL, NULL);
877
878                 /*we successfully loaded a blend file, get sure that
879                 pointcache works */
880                 if (retval!=0) {
881                         wmWindowManager *wm= CTX_wm_manager(C);
882                         CTX_wm_manager_set(C, NULL); /* remove wm to force check */
883                         WM_check(C);
884                         G.relbase_valid = 1;
885                         if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm); /* reset wm */
886                 }
887
888                 /* WM_read_file() runs normally but since we're in background mode do here */
889 #ifndef DISABLE_PYTHON
890                 /* run any texts that were loaded in and flagged as modules */
891                 BPY_load_user_modules(C);
892 #endif
893
894                 /* happens for the UI on file reading too (huh? (ton))*/
895         // XXX                  BKE_reset_undo();
896         //                              BKE_write_undo("original");     /* save current state */
897         } else {
898                 /* we are not running in background mode here, but start blender in UI mode with
899                    a file - this should do everything a 'load file' does */
900                 WM_read_file(C, filename, NULL);
901         }
902
903         G.file_loaded = 1;
904
905         return 0;
906 }
907
908 void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
909 {
910         static char output_doc[] = "<path>"
911                 "\n\tSet the render path and file name."
912                 "\n\tUse // at the start of the path to"
913                 "\n\t\trender relative to the blend file."
914                 "\n\tThe # characters are replaced by the frame number, and used to define zero padding."
915                 "\n\t\tani_##_test.png becomes ani_01_test.png"
916                 "\n\t\ttest-######.png becomes test-000001.png"
917                 "\n\t\tWhen the filename does not contain #, The suffix #### is added to the filename"
918                 "\n\tThe frame number will be added at the end of the filename."
919                 "\n\t\teg: blender -b foobar.blend -o //render_ -F PNG -x 1 -a"
920                 "\n\t\t//render_ becomes //render_####, writing frames as //render_0001.png//";
921
922         static char format_doc[] = "<format>"
923                 "\n\tSet the render format, Valid options are..."
924                 "\n\t\tTGA IRIS JPEG MOVIE IRIZ RAWTGA"
925                 "\n\t\tAVIRAW AVIJPEG PNG BMP FRAMESERVER"
926                 "\n\t(formats that can be compiled into blender, not available on all systems)"
927                 "\n\t\tHDR TIFF EXR MULTILAYER MPEG AVICODEC QUICKTIME CINEON DPX DDS";
928
929         static char playback_doc[] = "<options> <file(s)>"
930                 "\n\tPlayback <file(s)>, only operates this way when not running in background."
931                 "\n\t\t-p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>"
932                 "\n\t\t-m\t\tRead from disk (Don't buffer)"
933                 "\n\t\t-f <fps> <fps-base>\t\tSpecify FPS to start with"
934                 "\n\t\t-j <frame>\tSet frame step to <frame>";
935
936         static char game_doc[] = "Game Engine specific options"
937                 "\n\t-g fixedtime\t\tRun on 50 hertz without dropping frames"
938                 "\n\t-g vertexarrays\tUse Vertex Arrays for rendering (usually faster)"
939                 "\n\t-g nomipmap\t\tNo Texture Mipmapping"
940                 "\n\t-g linearmipmap\tLinear Texture Mipmapping instead of Nearest (default)";
941
942         static char debug_doc[] = "\n\tTurn debugging on\n"
943                 "\n\t* Prints every operator call and their arguments"
944                 "\n\t* Disables mouse grab (to interact with a debugger in some cases)"
945                 "\n\t* Keeps python sys.stdin rather then setting it to None";
946
947         //BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
948
949         /* end argument processing after -- */
950         BLI_argsAdd(ba, -1, "--", NULL, "\n\tEnds option processing, following arguments passed unchanged. Access via python's sys.argv", end_arguments, NULL);
951
952         /* first pass: background mode, disable python and commands that exit after usage */
953         BLI_argsAdd(ba, 1, "-h", "--help", "\n\tPrint this help text and exit", print_help, ba);
954         /* Windows only */
955         BLI_argsAdd(ba, 1, "/?", NULL, "\n\tPrint this help text and exit (windows only)", print_help, ba);
956
957         BLI_argsAdd(ba, 1, "-v", "--version", "\n\tPrint Blender version and exit", print_version, NULL);
958
959         BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", "\n\tEnable automatic python script execution (default)", enable_python, NULL);
960         BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", "\n\tDisable automatic python script execution (pydrivers, pyconstraints, pynodes)", disable_python, NULL);
961
962         BLI_argsAdd(ba, 1, "-b", "--background", "<file>\n\tLoad <file> in background (often used for UI-less rendering)", background_mode, NULL);
963
964         BLI_argsAdd(ba, 1, "-a", NULL, playback_doc, playback_mode, NULL);
965
966         BLI_argsAdd(ba, 1, "-d", "--debug", debug_doc, debug_mode, ba);
967     BLI_argsAdd(ba, 1, NULL, "--debug-fpe", "\n\tEnable floating point exceptions", set_fpe, NULL);
968
969         /* second pass: custom window stuff */
970         BLI_argsAdd(ba, 2, "-p", "--window-geometry", "<sx> <sy> <w> <h>\n\tOpen with lower left corner at <sx>, <sy> and width and height as <w>, <h>", prefsize, NULL);
971         BLI_argsAdd(ba, 2, "-w", "--window-border", "\n\tForce opening with borders (default)", with_borders, NULL);
972         BLI_argsAdd(ba, 2, "-W", "--window-borderless", "\n\tForce opening with without borders", without_borders, NULL);
973         BLI_argsAdd(ba, 2, "-R", NULL, "\n\tRegister .blend extension (windows only)", register_extension, ba);
974
975         /* third pass: disabling things and forcing settings */
976         BLI_argsAddCase(ba, 3, "-nojoystick", 1, NULL, 0, "\n\tDisable joystick support", no_joystick, syshandle);
977         BLI_argsAddCase(ba, 3, "-noglsl", 1, NULL, 0, "\n\tDisable GLSL shading", no_glsl, NULL);
978         BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, "\n\tForce sound system to None", no_audio, NULL);
979         BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, "\n\tForce sound system to a specific device\n\tNULL SDL OPENAL JACK", set_audio, NULL);
980
981         /* fourth pass: processing arguments */
982         BLI_argsAdd(ba, 4, "-g", NULL, game_doc, set_ge_parameters, syshandle);
983         BLI_argsAdd(ba, 4, "-f", "--render-frame", "<frame>\n\tRender frame <frame> and save it.\n\t+<frame> start frame relative, -<frame> end frame relative.", render_frame, C);
984         BLI_argsAdd(ba, 4, "-a", "--render-anim", "\n\tRender frames from start to end (inclusive)", render_animation, C);
985         BLI_argsAdd(ba, 4, "-S", "--scene", "<name>\n\tSet the active scene <name> for rendering", set_scene, NULL);
986         BLI_argsAdd(ba, 4, "-s", "--frame-start", "<frame>\n\tSet start to frame <frame> (use before the -a argument)", set_start_frame, C);
987         BLI_argsAdd(ba, 4, "-e", "--frame-end", "<frame>\n\tSet end to frame <frame> (use before the -a argument)", set_end_frame, C);
988         BLI_argsAdd(ba, 4, "-j", "--frame-jump", "<frames>\n\tSet number of frames to step forward after each rendered frame", set_skip_frame, C);
989         BLI_argsAdd(ba, 4, "-P", "--python", "<filename>\n\tRun the given Python script (filename or Blender Text)", run_python, C);
990         BLI_argsAdd(ba, 4, NULL, "--python-console", "\n\tRun blender with an interactive console", run_python_console, C);
991
992         BLI_argsAdd(ba, 4, "-o", "--render-output", output_doc, set_output, C);
993         BLI_argsAdd(ba, 4, "-E", "--engine", "<engine>\n\tSpecify the render engine\n\tuse -E help to list available engines", set_engine, C);
994
995         BLI_argsAdd(ba, 4, "-F", "--render-format", format_doc, set_image_type, C);
996         BLI_argsAdd(ba, 4, "-t", "--threads", "<threads>\n\tUse amount of <threads> for rendering in background\n\t[1-" QUOTE(BLENDER_MAX_THREADS) "], 0 for systems processor count.", set_threads, NULL);
997         BLI_argsAdd(ba, 4, "-x", "--use-extension", "<bool>\n\tSet option to add the file extension to the end of the file", set_extension, C);
998
999 }
1000
1001 int main(int argc, char **argv)
1002 {
1003         SYS_SystemHandle syshandle;
1004         bContext *C= CTX_create();
1005         bArgs *ba;
1006
1007 #ifdef WITH_BINRELOC
1008         br_init( NULL );
1009 #endif
1010
1011         setCallbacks();
1012 #ifdef __APPLE__
1013                 /* patch to ignore argument finder gives us (pid?) */
1014         if (argc==2 && strncmp(argv[1], "-psn_", 5)==0) {
1015                 extern int GHOST_HACK_getFirstFile(char buf[]);
1016                 static char firstfilebuf[512];
1017
1018                 argc= 1;
1019
1020                 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
1021                         argc= 2;
1022                         argv[1]= firstfilebuf;
1023                 }
1024         }
1025
1026 #endif
1027
1028 #ifdef __FreeBSD__
1029         fpsetmask(0);
1030 #endif
1031
1032         // copy path to executable in bprogname. playanim and creting runtimes
1033         // need this.
1034
1035         BLI_where_am_i(bprogname, argv[0]);
1036         
1037         {       /* override the hard coded blender path */
1038                 char *blender_path_env = getenv("BLENDERPATH");
1039                 if(blender_path_env)
1040                         BLI_strncpy(blender_path, blender_path_env, sizeof(blender_path));
1041         }
1042
1043 #ifdef BUILD_DATE       
1044     strip_quotes(build_date);
1045     strip_quotes(build_time);
1046     strip_quotes(build_rev);
1047     strip_quotes(build_platform);
1048     strip_quotes(build_type);
1049 #endif
1050
1051         BLI_threadapi_init();
1052
1053         RNA_init();
1054         RE_engines_init();
1055
1056                 /* Hack - force inclusion of the plugin api functions,
1057                  * see blenpluginapi:pluginapi.c
1058                  */
1059         pluginapi_force_ref();
1060
1061         init_nodesystem();
1062         
1063         initglobals();  /* blender.c */
1064
1065         IMB_init();
1066
1067         syshandle = SYS_GetSystem();
1068         GEN_init_messaging_system();
1069
1070         /* first test for background */
1071         ba = BLI_argsInit(argc, argv); /* skip binary path */
1072         setupArguments(C, ba, &syshandle);
1073
1074         BLI_argsParse(ba, 1, NULL, NULL);
1075
1076 #ifdef __sgi
1077         setuid(getuid()); /* end superuser */
1078 #endif
1079
1080
1081         /* for all platforms, even windos has it! */
1082         if(G.background) signal(SIGINT, blender_esc);   /* ctrl c out bg render */
1083         
1084         /* background render uses this font too */
1085         BKE_font_register_builtin(datatoc_Bfont, datatoc_Bfont_size);
1086
1087         /* Initialiaze ffmpeg if built in, also needed for bg mode if videos are
1088            rendered via ffmpeg */
1089         sound_init_once();
1090         
1091         init_def_material();
1092
1093         if(G.background==0) {
1094                 BLI_argsParse(ba, 2, NULL, NULL);
1095                 BLI_argsParse(ba, 3, NULL, NULL);
1096
1097                 WM_init(C, argc, argv);
1098                 
1099                 /* this is properly initialized with user defs, but this is default */
1100                 BLI_where_is_temp( btempdir, 1 ); /* call after loading the .B.blend so we can read U.tempdir */
1101
1102 #ifndef DISABLE_SDL
1103         BLI_setenv("SDL_VIDEODRIVER", "dummy");
1104 /* I think this is not necessary anymore (04-24-2010 neXyon)
1105 #ifdef __linux__
1106         // On linux the default SDL driver dma often would not play
1107         // use alsa if none is set
1108         setenv("SDL_AUDIODRIVER", "alsa", 0);
1109 #endif
1110 */
1111 #endif
1112         }
1113         else {
1114                 BLI_argsParse(ba, 3, NULL, NULL);
1115
1116                 WM_init(C, argc, argv);
1117
1118                 BLI_where_is_temp( btempdir, 0 ); /* call after loading the .B.blend so we can read U.tempdir */
1119         }
1120 #ifndef DISABLE_PYTHON
1121         /**
1122          * NOTE: the U.pythondir string is NULL until WM_init() is executed,
1123          * so we provide the BPY_ function below to append the user defined
1124          * pythondir to Python's sys.path at this point.  Simply putting
1125          * WM_init() before BPY_start_python() crashes Blender at startup.
1126          * Update: now this function also inits the bpymenus, which also depend
1127          * on U.pythondir.
1128          */
1129
1130         // TODO - U.pythondir
1131
1132 #endif
1133         
1134         CTX_py_init_set(C, 1);
1135         WM_keymap_init(C);
1136
1137         /* OK we are ready for it */
1138         BLI_argsParse(ba, 4, load_file, C);
1139
1140         BLI_argsFree(ba);
1141
1142         if(G.background) {
1143                 /* actually incorrect, but works for now (ton) */
1144                 WM_exit(C);
1145         }
1146
1147         else {
1148                 if((G.fileflags & G_FILE_AUTOPLAY) && (G.f & G_SCRIPT_AUTOEXEC))
1149                         WM_init_game(C);
1150
1151                 else if(!G.file_loaded)
1152                         WM_init_splash(C);
1153         }
1154
1155         WM_main(C);
1156
1157
1158         /*XXX if (scr_init==0) {
1159                 main_init_screen();
1160         }
1161         
1162         screenmain();*/ /* main display loop */
1163
1164         return 0;
1165 } /* end of int main(argc,argv) */
1166
1167 static void error_cb(char *err)
1168 {
1169         
1170         printf("%s\n", err);    /* XXX do this in WM too */
1171 }
1172
1173 static void mem_error_cb(const char *errorStr)
1174 {
1175         fputs(errorStr, stderr);
1176         fflush(stderr);
1177 }
1178
1179 static void setCallbacks(void)
1180 {
1181         /* Error output from the alloc routines: */
1182         MEM_set_error_callback(mem_error_cb);
1183
1184
1185         /* BLI_blenlib: */
1186
1187         BLI_setErrorCallBack(error_cb); /* */
1188 // XXX  BLI_setInterruptCallBack(blender_test_break);
1189
1190 }