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