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