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