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