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