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