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