=bmesh= merge from trunk at r36529
[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 int segmentation_handler(int 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         return 0;
377 }
378
379 static int nocrashhandler(int argc, char **argv, void *data)
380 {
381         no_handler = 1;
382
383         return 0;
384 }
385
386
387 static int end_arguments(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
388 {
389         return -1;
390 }
391
392 static int enable_python(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
393 {
394         G.f |= G_SCRIPT_AUTOEXEC;
395         G.f |= G_SCRIPT_OVERRIDE_PREF;
396         return 0;
397 }
398
399 static int disable_python(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
400 {
401         G.f &= ~G_SCRIPT_AUTOEXEC;
402         G.f |= G_SCRIPT_OVERRIDE_PREF;
403         return 0;
404 }
405
406 static int background_mode(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
407 {
408         G.background = 1;
409         return 0;
410 }
411
412 static int debug_mode(int UNUSED(argc), const char **UNUSED(argv), void *data)
413 {
414         G.f |= G_DEBUG;         /* std output printf's */
415         printf(BLEND_VERSION_STRING_FMT);
416         MEM_set_memory_debug();
417
418 #ifdef NAN_BUILDINFO
419         printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
420 #endif // NAN_BUILDINFO
421
422         BLI_argsPrint(data);
423         return 0;
424 }
425
426 static int set_fpe(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
427 {
428 #if defined(__sgi) || defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE)
429         /* zealous but makes float issues a heck of a lot easier to find!
430          * set breakpoints on fpe_handler */
431         signal(SIGFPE, fpe_handler);
432
433 # if defined(__linux__) && defined(__GNUC__)
434         feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );
435 # endif /* defined(__linux__) && defined(__GNUC__) */
436 # if defined(OSX_SSE_FPE)
437         /* OSX uses SSE for floating point by default, so here 
438          * use SSE instructions to throw floating point exceptions */
439         _MM_SET_EXCEPTION_MASK(_MM_MASK_MASK &~
440                         (_MM_MASK_OVERFLOW|_MM_MASK_INVALID|_MM_MASK_DIV_ZERO));
441 # endif /* OSX_SSE_FPE */
442 # if defined(_WIN32) && defined(_MSC_VER)
443         _controlfp_s(NULL, 0, _MCW_EM); /* enables all fp exceptions */
444         _controlfp_s(NULL, _EM_DENORMAL | _EM_UNDERFLOW | _EM_INEXACT, _MCW_EM); /* hide the ones we don't care about */
445 # endif /* _WIN32 && _MSC_VER */
446 #endif
447
448         return 0;
449 }
450
451 static int set_factory_startup(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
452 {
453         G.factory_startup= 1;
454         return 0;
455 }
456
457 static int set_env(int argc, const char **argv, void *UNUSED(data))
458 {
459         /* "--env-system-scripts" --> "BLENDER_SYSTEM_SCRIPTS" */
460
461         char env[64]= "BLENDER";
462         char *ch_dst= env + 7; /* skip BLENDER */
463         const char *ch_src= argv[0] + 5; /* skip --env */
464
465         if (argc < 2) {
466                 printf("%s requires one argument\n", argv[0]);
467                 exit(1);
468         }
469
470         for(; *ch_src; ch_src++, ch_dst++) {
471                 *ch_dst= (*ch_src == '-') ? '_' : (*ch_src)-32; /* toupper() */
472         }
473
474         *ch_dst= '\0';
475         BLI_setenv(env, argv[1]);
476         return 1;
477 }
478
479 static int playback_mode(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
480 {
481         /* not if -b was given first */
482         if (G.background == 0) {
483
484 // XXX                          playanim(argc, argv); /* not the same argc and argv as before */
485                 exit(0);
486         }
487
488         return -2;
489 }
490
491 static int prefsize(int argc, const char **argv, void *UNUSED(data))
492 {
493         int stax, stay, sizx, sizy;
494
495         if (argc < 5) {
496                 printf ("-p requires four arguments\n");
497                 exit(1);
498         }
499
500         stax= atoi(argv[1]);
501         stay= atoi(argv[2]);
502         sizx= atoi(argv[3]);
503         sizy= atoi(argv[4]);
504
505         WM_setprefsize(stax, stay, sizx, sizy);
506
507         return 4;
508 }
509
510 static int with_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
511 {
512         WM_setinitialstate_normal();
513         return 0;
514 }
515
516 static int without_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
517 {
518         WM_setinitialstate_fullscreen();
519         return 0;
520 }
521
522 extern int wm_start_with_console; // blender/windowmanager/intern/wm_init_exit.c
523 static int start_with_console(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
524 {
525         wm_start_with_console = 1;
526         return 0;
527 }
528
529 static int register_extension(int UNUSED(argc), const char **UNUSED(argv), void *data)
530 {
531 #ifdef WIN32
532         if (data)
533                 G.background = 1;
534         RegisterBlendExtension();
535 #else
536         (void)data; /* unused */
537 #endif
538         return 0;
539 }
540
541 static int no_joystick(int UNUSED(argc), const char **UNUSED(argv), void *data)
542 {
543 #ifndef WITH_GAMEENGINE
544         (void)data;
545 #else
546         SYS_SystemHandle *syshandle = data;
547
548         /**
549                 don't initialize joysticks if user doesn't want to use joysticks
550                 failed joystick initialization delays over 5 seconds, before game engine start
551         */
552         SYS_WriteCommandLineInt(*syshandle, "nojoystick",1);
553         if (G.f & G_DEBUG) printf("disabling nojoystick\n");
554 #endif
555
556         return 0;
557 }
558
559 static int no_glsl(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
560 {
561         GPU_extensions_disable();
562         return 0;
563 }
564
565 static int no_audio(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
566 {
567         sound_force_device(0);
568         return 0;
569 }
570
571 static int set_audio(int argc, const char **argv, void *UNUSED(data))
572 {
573         if (argc < 1) {
574                 printf("-setaudio require one argument\n");
575                 exit(1);
576         }
577
578         sound_force_device(sound_define_from_str(argv[1]));
579         return 1;
580 }
581
582 static int set_output(int argc, const char **argv, void *data)
583 {
584         bContext *C = data;
585         if (argc >= 1){
586                 if (CTX_data_scene(C)) {
587                         Scene *scene= CTX_data_scene(C);
588                         BLI_strncpy(scene->r.pic, argv[1], FILE_MAXDIR);
589                 } else {
590                         printf("\nError: no blend loaded. cannot use '-o / --render-output'.\n");
591                 }
592                 return 1;
593         } else {
594                 printf("\nError: you must specify a path after '-o  / --render-output'.\n");
595                 return 0;
596         }
597 }
598
599 static int set_engine(int argc, const char **argv, void *data)
600 {
601         bContext *C = data;
602         if (argc >= 1)
603         {
604                 if (!strcmp(argv[1],"help"))
605                 {
606                         RenderEngineType *type = NULL;
607
608                         for( type = R_engines.first; type; type = type->next )
609                         {
610                                 printf("\t%s\n", type->idname);
611                         }
612                         exit(0);
613                 }
614                 else
615                 {
616                         if (CTX_data_scene(C)==NULL)
617                         {
618                                 printf("\nError: no blend loaded. order the arguments so '-E  / --engine ' is after a blend is loaded.\n");
619                         }
620                         else {
621                                 Scene *scene= CTX_data_scene(C);
622                                 RenderData *rd = &scene->r;
623
624                                 if(BLI_findstring(&R_engines, argv[1], offsetof(RenderEngineType, idname))) {
625                                         BLI_strncpy(rd->engine, argv[1], sizeof(rd->engine));
626                                 }
627                         }
628                 }
629
630                 return 1;
631         }
632         else
633         {
634                 printf("\nEngine not specified.\n");
635                 return 0;
636         }
637 }
638
639 static int set_image_type(int argc, const char **argv, void *data)
640 {
641         bContext *C = data;
642         if (argc >= 1){
643                 const char *imtype = argv[1];
644                 if (CTX_data_scene(C)==NULL) {
645                         printf("\nError: no blend loaded. order the arguments so '-F  / --render-format' is after the blend is loaded.\n");
646                 } else {
647                         Scene *scene= CTX_data_scene(C);
648                         if      (!strcmp(imtype,"TGA")) scene->r.imtype = R_TARGA;
649                         else if (!strcmp(imtype,"IRIS")) scene->r.imtype = R_IRIS;
650 #ifdef WITH_DDS
651                         else if (!strcmp(imtype,"DDS")) scene->r.imtype = R_DDS;
652 #endif
653                         else if (!strcmp(imtype,"JPEG")) scene->r.imtype = R_JPEG90;
654                         else if (!strcmp(imtype,"IRIZ")) scene->r.imtype = R_IRIZ;
655                         else if (!strcmp(imtype,"RAWTGA")) scene->r.imtype = R_RAWTGA;
656                         else if (!strcmp(imtype,"AVIRAW")) scene->r.imtype = R_AVIRAW;
657                         else if (!strcmp(imtype,"AVIJPEG")) scene->r.imtype = R_AVIJPEG;
658                         else if (!strcmp(imtype,"PNG")) scene->r.imtype = R_PNG;
659                         else if (!strcmp(imtype,"AVICODEC")) scene->r.imtype = R_AVICODEC;
660                         else if (!strcmp(imtype,"QUICKTIME")) scene->r.imtype = R_QUICKTIME;
661                         else if (!strcmp(imtype,"BMP")) scene->r.imtype = R_BMP;
662 #ifdef WITH_HDR
663                         else if (!strcmp(imtype,"HDR")) scene->r.imtype = R_RADHDR;
664 #endif
665 #ifdef WITH_TIFF
666                         else if (!strcmp(imtype,"TIFF")) scene->r.imtype = R_TIFF;
667 #endif
668 #ifdef WITH_OPENEXR
669                         else if (!strcmp(imtype,"EXR")) scene->r.imtype = R_OPENEXR;
670                         else if (!strcmp(imtype,"MULTILAYER")) scene->r.imtype = R_MULTILAYER;
671 #endif
672                         else if (!strcmp(imtype,"MPEG")) scene->r.imtype = R_FFMPEG;
673                         else if (!strcmp(imtype,"FRAMESERVER")) scene->r.imtype = R_FRAMESERVER;
674 #ifdef WITH_CINEON
675                         else if (!strcmp(imtype,"CINEON")) scene->r.imtype = R_CINEON;
676                         else if (!strcmp(imtype,"DPX")) scene->r.imtype = R_DPX;
677 #endif
678 #if WITH_OPENJPEG
679                         else if (!strcmp(imtype,"JP2")) scene->r.imtype = R_JP2;
680 #endif
681                         else printf("\nError: Format from '-F / --render-format' not known or not compiled in this release.\n");
682                 }
683                 return 1;
684         } else {
685                 printf("\nError: you must specify a format after '-F  / --render-foramt'.\n");
686                 return 0;
687         }
688 }
689
690 static int set_threads(int argc, const char **argv, void *UNUSED(data))
691 {
692         if (argc >= 1) {
693                 if(G.background) {
694                         RE_set_max_threads(atoi(argv[1]));
695                 } else {
696                         printf("Warning: threads can only be set in background mode\n");
697                 }
698                 return 1;
699         } else {
700                 printf("\nError: you must specify a number of threads between 0 and 8 '-t  / --threads'.\n");
701                 return 0;
702         }
703 }
704
705 static int set_extension(int argc, const char **argv, void *data)
706 {
707         bContext *C = data;
708         if (argc >= 1) {
709                 if (CTX_data_scene(C)) {
710                         Scene *scene= CTX_data_scene(C);
711                         if (argv[1][0] == '0') {
712                                 scene->r.scemode &= ~R_EXTENSION;
713                         } else if (argv[1][0] == '1') {
714                                 scene->r.scemode |= R_EXTENSION;
715                         } else {
716                                 printf("\nError: Use '-x 1 / -x 0' To set the extension option or '--use-extension'\n");
717                         }
718                 } else {
719                         printf("\nError: no blend loaded. order the arguments so '-o ' is after '-x '.\n");
720                 }
721                 return 1;
722         } else {
723                 printf("\nError: you must specify a path after '- '.\n");
724                 return 0;
725         }
726 }
727
728 static int set_ge_parameters(int argc, const char **argv, void *data)
729 {
730         int a = 0;
731 #ifdef WITH_GAMEENGINE
732         SYS_SystemHandle syshandle = *(SYS_SystemHandle*)data;
733 #else
734         (void)data;
735 #endif
736
737 /**
738 gameengine parameters are automaticly put into system
739 -g [paramname = value]
740 -g [boolparamname]
741 example:
742 -g novertexarrays
743 -g maxvertexarraysize = 512
744 */
745
746         if(argc >= 1)
747         {
748                 const char *paramname = argv[a];
749                 /* check for single value versus assignment */
750                 if (a+1 < argc && (*(argv[a+1]) == '='))
751                 {
752                         a++;
753                         if (a+1 < argc)
754                         {
755                                 a++;
756                                 /* assignment */
757 #ifdef WITH_GAMEENGINE
758                                 SYS_WriteCommandLineString(syshandle,paramname,argv[a]);
759 #endif
760                         }  else
761                         {
762                                 printf("error: argument assignment (%s) without value.\n",paramname);
763                                 return 0;
764                         }
765                         /* name arg eaten */
766
767                 } else {
768 #ifdef WITH_GAMEENGINE
769                         SYS_WriteCommandLineInt(syshandle,argv[a],1);
770 #endif
771                         /* doMipMap */
772                         if (!strcmp(argv[a],"nomipmap"))
773                         {
774                                 GPU_set_mipmap(0); //doMipMap = 0;
775                         }
776                         /* linearMipMap */
777                         if (!strcmp(argv[a],"linearmipmap"))
778                         {
779                                 GPU_set_linear_mipmap(1); //linearMipMap = 1;
780                         }
781
782
783                 } /* if (*(argv[a+1]) == '=') */
784         }
785
786         return a;
787 }
788
789 static int render_frame(int argc, const char **argv, void *data)
790 {
791         bContext *C = data;
792         if (CTX_data_scene(C)) {
793                 Main *bmain= CTX_data_main(C);
794                 Scene *scene= CTX_data_scene(C);
795
796                 if (argc > 1) {
797                         Render *re = RE_NewRender(scene->id.name);
798                         int frame;
799                         ReportList reports;
800
801                         switch(*argv[1]) {
802                         case '+':
803                                 frame= scene->r.sfra + atoi(argv[1]+1);
804                                 break;
805                         case '-':
806                                 frame= (scene->r.efra - atoi(argv[1]+1)) + 1;
807                                 break;
808                         default:
809                                 frame= atoi(argv[1]);
810                                 break;
811                         }
812
813                         BKE_reports_init(&reports, RPT_PRINT);
814
815                         frame = MIN2(MAXFRAME, MAX2(MINAFRAME, frame));
816
817                         RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, frame, frame, scene->r.frame_step, &reports);
818                         return 1;
819                 } else {
820                         printf("\nError: frame number must follow '-f / --render-frame'.\n");
821                         return 0;
822                 }
823         } else {
824                 printf("\nError: no blend loaded. cannot use '-f / --render-frame'.\n");
825                 return 0;
826         }
827 }
828
829 static int render_animation(int UNUSED(argc), const char **UNUSED(argv), void *data)
830 {
831         bContext *C = data;
832         if (CTX_data_scene(C)) {
833                 Main *bmain= CTX_data_main(C);
834                 Scene *scene= CTX_data_scene(C);
835                 Render *re= RE_NewRender(scene->id.name);
836                 ReportList reports;
837                 BKE_reports_init(&reports, RPT_PRINT);
838                 RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step, &reports);
839         } else {
840                 printf("\nError: no blend loaded. cannot use '-a'.\n");
841         }
842         return 0;
843 }
844
845 static int set_scene(int argc, const char **argv, void *data)
846 {
847         if(argc > 1) {
848                 bContext *C= data;
849                 Scene *sce= set_scene_name(CTX_data_main(C), argv[1]);
850                 if(sce) {
851                         CTX_data_scene_set(C, sce);
852                 }
853                 return 1;
854         } else {
855                 printf("\nError: Scene name must follow '-S / --scene'.\n");
856                 return 0;
857         }
858 }
859
860 static int set_start_frame(int argc, const char **argv, void *data)
861 {
862         bContext *C = data;
863         if (CTX_data_scene(C)) {
864                 Scene *scene= CTX_data_scene(C);
865                 if (argc > 1) {
866                         int frame = atoi(argv[1]);
867                         (scene->r.sfra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
868                         return 1;
869                 } else {
870                         printf("\nError: frame number must follow '-s / --frame-start'.\n");
871                         return 0;
872                 }
873         } else {
874                 printf("\nError: no blend loaded. cannot use '-s / --frame-start'.\n");
875                 return 0;
876         }
877 }
878
879 #ifdef EVENT_RECORDER
880 static int set_macro_playback(int argc, char **argv, void *data)
881 {
882         bContext *C = data;
883         
884         if (argc < 2)
885                 return 0;
886                 
887         CTX_set_events_path(C, argv[1]);
888         
889         return 0;
890 }
891 #endif
892
893 static int set_end_frame(int argc, const char **argv, void *data)
894 {
895         bContext *C = data;
896         if (CTX_data_scene(C)) {
897                 Scene *scene= CTX_data_scene(C);
898                 if (argc > 1) {
899                         int frame = atoi(argv[1]);
900                         (scene->r.efra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
901                         return 1;
902                 } else {
903                         printf("\nError: frame number must follow '-e / --frame-end'.\n");
904                         return 0;
905                 }
906         } else {
907                 printf("\nError: no blend loaded. cannot use '-e / --frame-end'.\n");
908                 return 0;
909         }
910 }
911
912 static int set_skip_frame(int argc, const char **argv, void *data)
913 {
914         bContext *C = data;
915         if (CTX_data_scene(C)) {
916                 Scene *scene= CTX_data_scene(C);
917                 if (argc > 1) {
918                         int frame = atoi(argv[1]);
919                         (scene->r.frame_step) = CLAMPIS(frame, 1, MAXFRAME);
920                         return 1;
921                 } else {
922                         printf("\nError: number of frames to step must follow '-j / --frame-jump'.\n");
923                         return 0;
924                 }
925         } else {
926                 printf("\nError: no blend loaded. cannot use '-j / --frame-jump'.\n");
927                 return 0;
928         }
929 }
930
931 /* macro for ugly context setup/reset */
932 #ifdef WITH_PYTHON
933 #define BPY_CTX_SETUP(_cmd) \
934 { \
935         wmWindowManager *wm= CTX_wm_manager(C); \
936         wmWindow *prevwin= CTX_wm_window(C); \
937         Scene *prevscene= CTX_data_scene(C); \
938         if(wm->windows.first) { \
939                 CTX_wm_window_set(C, wm->windows.first); \
940                 _cmd; \
941                 CTX_wm_window_set(C, prevwin); \
942         } \
943         else { \
944                 fprintf(stderr, "Python script \"%s\" running with missing context data.\n", argv[1]); \
945                 _cmd; \
946         } \
947         CTX_data_scene_set(C, prevscene); \
948 } \
949
950 #endif /* WITH_PYTHON */
951
952 static int run_python(int argc, const char **argv, void *data)
953 {
954 #ifdef WITH_PYTHON
955         bContext *C = data;
956
957         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
958         if (argc > 1) {
959                 /* Make the path absolute because its needed for relative linked blends to be found */
960                 char filename[FILE_MAXDIR + FILE_MAXFILE];
961                 BLI_strncpy(filename, argv[1], sizeof(filename));
962                 BLI_path_cwd(filename);
963
964                 BPY_CTX_SETUP(BPY_filepath_exec(C, filename, NULL))
965
966                 return 1;
967         } else {
968                 printf("\nError: you must specify a Python script after '-P / --python'.\n");
969                 return 0;
970         }
971 #else
972         (void)argc; (void)argv; (void)data; /* unused */
973         printf("This blender was built without python support\n");
974         return 0;
975 #endif /* WITH_PYTHON */
976 }
977
978 static int run_python_console(int UNUSED(argc), const char **argv, void *data)
979 {
980 #ifdef WITH_PYTHON
981         bContext *C = data;
982
983         BPY_CTX_SETUP(BPY_string_exec(C, "__import__('code').interact()"))
984
985         return 0;
986 #else
987         (void)argv; (void)data; /* unused */
988         printf("This blender was built without python support\n");
989         return 0;
990 #endif /* WITH_PYTHON */
991 }
992
993 static int set_addons(int argc, const char **argv, void *data)
994 {
995         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
996         if (argc > 1) {
997 #ifdef WITH_PYTHON
998                 const int slen= strlen(argv[1]) + 128;
999                 char *str= malloc(slen);
1000                 bContext *C= data;
1001                 BLI_snprintf(str, slen, "[__import__('addon_utils').enable(i, default_set=False) for i in '%s'.split(',')]", argv[1]);
1002                 BPY_CTX_SETUP(BPY_string_exec(C, str));
1003                 free(str);
1004 #else
1005                 (void)argv; (void)data; /* unused */
1006 #endif /* WITH_PYTHON */
1007                 return 1;
1008         }
1009         else {
1010                 printf("\nError: you must specify a comma separated list after '--addons'.\n");
1011                 return 0;
1012         }
1013 }
1014
1015
1016 static int load_file(int UNUSED(argc), const char **argv, void *data)
1017 {
1018         bContext *C = data;
1019
1020         /* Make the path absolute because its needed for relative linked blends to be found */
1021         char filename[FILE_MAXDIR + FILE_MAXFILE];
1022         BLI_strncpy(filename, argv[0], sizeof(filename));
1023         BLI_path_cwd(filename);
1024
1025         if (G.background) {
1026                 int retval = BKE_read_file(C, filename, NULL);
1027
1028                 /*we successfully loaded a blend file, get sure that
1029                 pointcache works */
1030                 if (retval != BKE_READ_FILE_FAIL) {
1031                         wmWindowManager *wm= CTX_wm_manager(C);
1032
1033                         /* special case, 2.4x files */
1034                         if(wm==NULL && CTX_data_main(C)->wm.first==NULL) {
1035                                 extern void wm_add_default(bContext *C);
1036
1037                                 /* wm_add_default() needs the screen to be set. */
1038                                 CTX_wm_screen_set(C, CTX_data_main(C)->screen.first);
1039                                 wm_add_default(C);
1040                         }
1041
1042                         CTX_wm_manager_set(C, NULL); /* remove wm to force check */
1043                         WM_check(C);
1044                         G.relbase_valid = 1;
1045                         if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm); /* reset wm */
1046
1047                         DAG_on_visible_update(CTX_data_main(C), TRUE);
1048                 }
1049
1050                 /* WM_read_file() runs normally but since we're in background mode do here */
1051 #ifdef WITH_PYTHON
1052                 /* run any texts that were loaded in and flagged as modules */
1053                 BPY_driver_reset();
1054                 BPY_modules_load_user(C);
1055 #endif
1056
1057                 /* happens for the UI on file reading too (huh? (ton))*/
1058         // XXX                  BKE_reset_undo();
1059         //                              BKE_write_undo("original");     /* save current state */
1060         } else {
1061                 /* we are not running in background mode here, but start blender in UI mode with
1062                    a file - this should do everything a 'load file' does */
1063                 ReportList reports;
1064                 BKE_reports_init(&reports, RPT_PRINT);
1065                 WM_read_file(C, filename, &reports);
1066                 BKE_reports_clear(&reports);
1067         }
1068
1069         G.file_loaded = 1;
1070
1071         return 0;
1072 }
1073
1074 static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
1075 {
1076         static char output_doc[] = "<path>"
1077                 "\n\tSet the render path and file name."
1078                 "\n\tUse // at the start of the path to"
1079                 "\n\t\trender relative to the blend file."
1080                 "\n\tThe # characters are replaced by the frame number, and used to define zero padding."
1081                 "\n\t\tani_##_test.png becomes ani_01_test.png"
1082                 "\n\t\ttest-######.png becomes test-000001.png"
1083                 "\n\t\tWhen the filename does not contain #, The suffix #### is added to the filename"
1084                 "\n\tThe frame number will be added at the end of the filename."
1085                 "\n\t\teg: blender -b foobar.blend -o //render_ -F PNG -x 1 -a"
1086                 "\n\t\t//render_ becomes //render_####, writing frames as //render_0001.png//";
1087
1088         static char format_doc[] = "<format>"
1089                 "\n\tSet the render format, Valid options are..."
1090                 "\n\t\tTGA IRIS JPEG MOVIE IRIZ RAWTGA"
1091                 "\n\t\tAVIRAW AVIJPEG PNG BMP FRAMESERVER"
1092                 "\n\t(formats that can be compiled into blender, not available on all systems)"
1093                 "\n\t\tHDR TIFF EXR MULTILAYER MPEG AVICODEC QUICKTIME CINEON DPX DDS";
1094
1095         static char playback_doc[] = "<options> <file(s)>"
1096                 "\n\tPlayback <file(s)>, only operates this way when not running in background."
1097                 "\n\t\t-p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>"
1098                 "\n\t\t-m\t\tRead from disk (Don't buffer)"
1099                 "\n\t\t-f <fps> <fps-base>\t\tSpecify FPS to start with"
1100                 "\n\t\t-j <frame>\tSet frame step to <frame>";
1101
1102         static char game_doc[] = "Game Engine specific options"
1103                 "\n\t-g fixedtime\t\tRun on 50 hertz without dropping frames"
1104                 "\n\t-g vertexarrays\t\tUse Vertex Arrays for rendering (usually faster)"
1105                 "\n\t-g nomipmap\t\tNo Texture Mipmapping"
1106                 "\n\t-g linearmipmap\t\tLinear Texture Mipmapping instead of Nearest (default)";
1107
1108         static char debug_doc[] = "\n\tTurn debugging on\n"
1109                 "\n\t* Prints every operator call and their arguments"
1110                 "\n\t* Disables mouse grab (to interact with a debugger in some cases)"
1111                 "\n\t* Keeps python sys.stdin rather then setting it to None";
1112
1113         //BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
1114
1115         /* end argument processing after -- */
1116         BLI_argsAdd(ba, -1, "--", NULL, "\n\tEnds option processing, following arguments passed unchanged. Access via python's sys.argv", end_arguments, NULL);
1117
1118         /* first pass: background mode, disable python and commands that exit after usage */
1119         BLI_argsAdd(ba, 1, "-h", "--help", "\n\tPrint this help text and exit", print_help, ba);
1120         /* Windows only */
1121         BLI_argsAdd(ba, 1, "/?", NULL, "\n\tPrint this help text and exit (windows only)", print_help, ba);
1122
1123         BLI_argsAdd(ba, 1, "-v", "--version", "\n\tPrint Blender version and exit", print_version, NULL);
1124         
1125         /* only to give help message */
1126 #ifndef WITH_PYTHON_SECURITY /* default */
1127 #  define       PY_ENABLE_AUTO ", (default)"
1128 #  define       PY_DISABLE_AUTO ""
1129 #else
1130 #  define       PY_ENABLE_AUTO ""
1131 #  define       PY_DISABLE_AUTO ", (compiled as non-standard default)"
1132 #endif
1133
1134         BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", "\n\tEnable automatic python script execution" PY_ENABLE_AUTO, enable_python, NULL);
1135         BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", "\n\tDisable automatic python script execution (pydrivers, pyconstraints, pynodes)" PY_DISABLE_AUTO, disable_python, NULL);
1136
1137 #undef PY_ENABLE_AUTO
1138 #undef PY_DISABLE_AUTO
1139         
1140         BLI_argsAdd(ba, 1, "-b", "--background", "<file>\n\tLoad <file> in background (often used for UI-less rendering)", background_mode, NULL);
1141
1142         BLI_argsAdd(ba, 1, "-a", NULL, playback_doc, playback_mode, NULL);
1143
1144         BLI_argsAdd(ba, 1, "-d", "--debug", debug_doc, debug_mode, ba);
1145         BLI_argsAdd(ba, 1, NULL, "--debug-fpe", "\n\tEnable floating point exceptions", set_fpe, NULL);
1146
1147         BLI_argsAdd(ba, 1, NULL, "--factory-startup", "\n\tSkip reading the "STRINGIFY(BLENDER_STARTUP_FILE)" in the users home directory", set_factory_startup, NULL);
1148
1149         /* TODO, add user env vars? */
1150         BLI_argsAdd(ba, 1, NULL, "--env-system-config",         "\n\tSet the "STRINGIFY_ARG(BLENDER_SYSTEM_CONFIG)" environment variable", set_env, NULL);
1151         BLI_argsAdd(ba, 1, NULL, "--env-system-datafiles",      "\n\tSet the "STRINGIFY_ARG(BLENDER_SYSTEM_DATAFILES)" environment variable", set_env, NULL);
1152         BLI_argsAdd(ba, 1, NULL, "--env-system-scripts",        "\n\tSet the "STRINGIFY_ARG(BLENDER_SYSTEM_SCRIPTS)" environment variable", set_env, NULL);
1153         BLI_argsAdd(ba, 1, NULL, "--env-system-plugins",        "\n\tSet the "STRINGIFY_ARG(BLENDER_SYSTEM_PLUGINS)" environment variable", set_env, NULL);
1154         BLI_argsAdd(ba, 1, NULL, "--env-system-python",         "\n\tSet the "STRINGIFY_ARG(BLENDER_SYSTEM_PYTHON)" environment variable", set_env, NULL);
1155
1156         /* second pass: custom window stuff */
1157         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);
1158         BLI_argsAdd(ba, 2, "-w", "--window-border", "\n\tForce opening with borders (default)", with_borders, NULL);
1159         BLI_argsAdd(ba, 2, "-W", "--window-borderless", "\n\tForce opening without borders", without_borders, NULL);
1160         BLI_argsAdd(ba, 2, "-con", "--start-console", "\n\tStart with the console window open (ignored if -b is set)", start_with_console, NULL);
1161         BLI_argsAdd(ba, 2, "-R", NULL, "\n\tRegister .blend extension, then exit (Windows only)", register_extension, NULL);
1162         BLI_argsAdd(ba, 2, "-r", NULL, "\n\tSilently register .blend extension, then exit (Windows only)", register_extension, ba);
1163         BLI_argsAdd(ba, 2,  "--no_crash_handler", NULL, "disable crash handler", nocrashhandler, NULL);
1164         
1165         /* third pass: disabling things and forcing settings */
1166         BLI_argsAddCase(ba, 3, "-nojoystick", 1, NULL, 0, "\n\tDisable joystick support", no_joystick, syshandle);
1167         BLI_argsAddCase(ba, 3, "-noglsl", 1, NULL, 0, "\n\tDisable GLSL shading", no_glsl, NULL);
1168         BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, "\n\tForce sound system to None", no_audio, NULL);
1169         BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, "\n\tForce sound system to a specific device\n\tNULL SDL OPENAL JACK", set_audio, NULL);
1170
1171
1172         /* fourth pass: processing arguments */
1173         BLI_argsAdd(ba, 4, "-g", NULL, game_doc, set_ge_parameters, syshandle);
1174         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);
1175         BLI_argsAdd(ba, 4, "-a", "--render-anim", "\n\tRender frames from start to end (inclusive)", render_animation, C);
1176         BLI_argsAdd(ba, 4, "-S", "--scene", "<name>\n\tSet the active scene <name> for rendering", set_scene, C);
1177         BLI_argsAdd(ba, 4, "-s", "--frame-start", "<frame>\n\tSet start to frame <frame> (use before the -a argument)", set_start_frame, C);
1178         BLI_argsAdd(ba, 4, "-e", "--frame-end", "<frame>\n\tSet end to frame <frame> (use before the -a argument)", set_end_frame, C);
1179         BLI_argsAdd(ba, 4, "-j", "--frame-jump", "<frames>\n\tSet number of frames to step forward after each rendered frame", set_skip_frame, C);
1180         BLI_argsAdd(ba, 4, "-P", "--python", "<filename>\n\tRun the given Python script (filename or Blender Text)", run_python, C);
1181         BLI_argsAdd(ba, 4, NULL, "--python-console", "\n\tRun blender with an interactive console", run_python_console, C);
1182         BLI_argsAdd(ba, 4, NULL, "--addons", "\n\tComma separated list of addons (no spaces)", set_addons, C);
1183
1184         BLI_argsAdd(ba, 4, "-o", "--render-output", output_doc, set_output, C);
1185         BLI_argsAdd(ba, 4, "-E", "--engine", "<engine>\n\tSpecify the render engine\n\tuse -E help to list available engines", set_engine, C);
1186
1187         BLI_argsAdd(ba, 4, "-F", "--render-format", format_doc, set_image_type, C);
1188         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);
1189         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);
1190
1191 #ifdef EVENT_RECORDER
1192         BLI_argsAdd(ba, 4, "--eventmacro", NULL, "<file>\n\tevent macro", set_macro_playback, C);
1193 #endif
1194         
1195 }
1196
1197 #ifdef WITH_PYTHON_MODULE
1198 /* allow python module to call main */
1199 #define main main_python
1200 #endif
1201
1202 int main(int argc, const char **argv)
1203 {
1204         SYS_SystemHandle syshandle;
1205         bContext *C= CTX_create();
1206         bArgs *ba;
1207 #ifdef WITH_PYTHON_MODULE
1208 #undef main
1209 #endif
1210
1211 #ifdef WITH_BINRELOC
1212         br_init( NULL );
1213 #endif
1214
1215         setCallbacks();
1216 #ifdef __APPLE__
1217                 /* patch to ignore argument finder gives us (pid?) */
1218         if (argc==2 && strncmp(argv[1], "-psn_", 5)==0) {
1219                 extern int GHOST_HACK_getFirstFile(char buf[]);
1220                 static char firstfilebuf[512];
1221
1222                 argc= 1;
1223
1224                 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
1225                         argc= 2;
1226                         argv[1]= firstfilebuf;
1227                 }
1228         }
1229
1230 #endif
1231
1232 #ifdef __FreeBSD__
1233         fpsetmask(0);
1234 #endif
1235
1236         // copy path to executable in bprogname. playanim and creting runtimes
1237         // need this.
1238
1239         BLI_where_am_i(bprogname, sizeof(bprogname), argv[0]);
1240         
1241 #ifdef BUILD_DATE       
1242         strip_quotes(build_date);
1243         strip_quotes(build_time);
1244         strip_quotes(build_rev);
1245         strip_quotes(build_platform);
1246         strip_quotes(build_type);
1247         strip_quotes(build_cflags);
1248         strip_quotes(build_cxxflags);
1249         strip_quotes(build_linkflags);
1250         strip_quotes(build_system);
1251 #endif
1252
1253         BLI_threadapi_init();
1254
1255         RNA_init();
1256         RE_engines_init();
1257
1258                 /* Hack - force inclusion of the plugin api functions,
1259                  * see blenpluginapi:pluginapi.c
1260                  */
1261         pluginapi_force_ref();
1262
1263         init_nodesystem();
1264         
1265         initglobals();  /* blender.c */
1266
1267         IMB_init();
1268
1269 #ifdef WITH_GAMEENGINE
1270         syshandle = SYS_GetSystem();
1271 #else
1272         syshandle= 0;
1273 #endif
1274
1275         /* first test for background */
1276         ba = BLI_argsInit(argc, argv); /* skip binary path */
1277         setupArguments(C, ba, &syshandle);
1278
1279         BLI_argsParse(ba, 1, NULL, NULL);
1280
1281         if (!no_handler) {
1282                 signal(SIGSEGV, segmentation_handler);
1283                 //signal(SIGFPE, segmentation_handler);
1284         }
1285
1286 #ifdef __sgi
1287         setuid(getuid()); /* end superuser */
1288 #endif
1289
1290 #ifdef WITH_PYTHON_MODULE
1291         G.background= 1; /* python module mode ALWAYS runs in background mode (for now) */
1292 #else
1293         /* for all platforms, even windos has it! */
1294         if(G.background) signal(SIGINT, blender_esc);   /* ctrl c out bg render */
1295 #endif
1296
1297         /* background render uses this font too */
1298         BKE_font_register_builtin(datatoc_Bfont, datatoc_Bfont_size);
1299
1300         /* Initialiaze ffmpeg if built in, also needed for bg mode if videos are
1301            rendered via ffmpeg */
1302         sound_init_once();
1303         
1304         init_def_material();
1305
1306         if(G.background==0) {
1307                 BLI_argsParse(ba, 2, NULL, NULL);
1308                 BLI_argsParse(ba, 3, NULL, NULL);
1309
1310                 WM_init(C, argc, argv);
1311
1312                 /* this is properly initialized with user defs, but this is default */
1313                 BLI_where_is_temp(btempdir, FILE_MAX, 1); /* call after loading the startup.blend so we can read U.tempdir */
1314
1315 #ifndef DISABLE_SDL
1316         BLI_setenv("SDL_VIDEODRIVER", "dummy");
1317 #endif
1318         }
1319         else {
1320                 BLI_argsParse(ba, 3, NULL, NULL);
1321
1322                 WM_init(C, argc, argv);
1323
1324                 BLI_where_is_temp(btempdir, FILE_MAX, 0); /* call after loading the startup.blend so we can read U.tempdir */
1325         }
1326 #ifdef WITH_PYTHON
1327         /**
1328          * NOTE: the U.pythondir string is NULL until WM_init() is executed,
1329          * so we provide the BPY_ function below to append the user defined
1330          * pythondir to Python's sys.path at this point.  Simply putting
1331          * WM_init() before BPY_python_start() crashes Blender at startup.
1332          * Update: now this function also inits the bpymenus, which also depend
1333          * on U.pythondir.
1334          */
1335
1336         // TODO - U.pythondir
1337 #else
1338         printf("\n* WARNING * - Blender compiled without Python!\nthis is not intended for typical usage\n\n");
1339 #endif
1340         
1341         CTX_py_init_set(C, 1);
1342         WM_keymap_init(C);
1343
1344         /* OK we are ready for it */
1345         BLI_argsParse(ba, 4, load_file, C);
1346
1347         BLI_argsFree(ba);
1348
1349 #ifdef WITH_PYTHON_MODULE
1350         return 0; /* keep blender in background mode running */
1351 #endif
1352
1353         if(G.background) {
1354                 /* actually incorrect, but works for now (ton) */
1355                 WM_exit(C);
1356         }
1357
1358         else {
1359                 if((G.fileflags & G_FILE_AUTOPLAY) && (G.f & G_SCRIPT_AUTOEXEC))
1360                 {
1361                         if(WM_init_game(C))
1362                                 return 0;
1363                 }
1364 #ifdef EVENT_RECORDER
1365                 else if(!G.file_loaded && !CTX_play_events(C, NULL))
1366 #else
1367                         else if(!G.file_loaded)
1368 #endif
1369                         WM_init_splash(C);
1370         }
1371
1372         WM_main(C);
1373         
1374
1375         /*XXX if (scr_init==0) {
1376                 main_init_screen();
1377         }
1378         
1379         screenmain();*/ /* main display loop */
1380
1381         return 0;
1382 } /* end of int main(argc,argv) */
1383
1384 static void error_cb(const char *err)
1385 {
1386         
1387         printf("%s\n", err);    /* XXX do this in WM too */
1388 }
1389
1390 static void mem_error_cb(const char *errorStr)
1391 {
1392         fputs(errorStr, stderr);
1393         fflush(stderr);
1394 }
1395
1396 static void setCallbacks(void)
1397 {
1398         /* Error output from the alloc routines: */
1399         MEM_set_error_callback(mem_error_cb);
1400
1401
1402         /* BLI_blenlib: */
1403
1404         BLI_setErrorCallBack(error_cb); /* */
1405 // XXX  BLI_setInterruptCallBack(blender_test_break);
1406
1407 }