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