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