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