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