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