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