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