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