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