Make sure we can build without the optional new WITH_PYTHON_MODULE option. Looks...
[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 /* 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, const char **argv, void *data);
135 static int print_version(int argc, const 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_MAX]; /* from blenpluginapi:pluginapi.c */
142 char btempdir[FILE_MAX];
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 #ifndef WITH_PYTHON_MODULE
158 /* handling ctrl-c event in console */
159 static void blender_esc(int sig)
160 {
161         static int count = 0;
162         
163         G.afbreek = 1;  /* forces render loop to read queue, not sure if its needed */
164         
165         if (sig == 2) {
166                 if (count) {
167                         printf("\nBlender killed\n");
168                         exit(2);
169                 }
170                 printf("\nSent an internal break event. Press ^C again to kill Blender\n");
171                 count++;
172         }
173 }
174 #endif
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 #ifdef WITH_PYTHON_MODULE
1117 /* allow python module to call main */
1118 #define main main_python
1119 #endif
1120
1121 int main(int argc, const char **argv)
1122 {
1123         SYS_SystemHandle syshandle;
1124         bContext *C= CTX_create();
1125         bArgs *ba;
1126
1127 #ifdef WITH_PYTHON_MODULE
1128 #undef main
1129 #endif
1130
1131 #ifdef WITH_BINRELOC
1132         br_init( NULL );
1133 #endif
1134
1135         setCallbacks();
1136 #ifdef __APPLE__
1137                 /* patch to ignore argument finder gives us (pid?) */
1138         if (argc==2 && strncmp(argv[1], "-psn_", 5)==0) {
1139                 extern int GHOST_HACK_getFirstFile(char buf[]);
1140                 static char firstfilebuf[512];
1141
1142                 argc= 1;
1143
1144                 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
1145                         argc= 2;
1146                         argv[1]= firstfilebuf;
1147                 }
1148         }
1149
1150 #endif
1151
1152 #ifdef __FreeBSD__
1153         fpsetmask(0);
1154 #endif
1155
1156         // copy path to executable in bprogname. playanim and creting runtimes
1157         // need this.
1158
1159         BLI_where_am_i(bprogname, sizeof(bprogname), argv[0]);
1160         
1161 #ifdef BUILD_DATE       
1162         strip_quotes(build_date);
1163         strip_quotes(build_time);
1164         strip_quotes(build_rev);
1165         strip_quotes(build_platform);
1166         strip_quotes(build_type);
1167         strip_quotes(build_cflags);
1168         strip_quotes(build_cxxflags);
1169         strip_quotes(build_linkflags);
1170         strip_quotes(build_system);
1171 #endif
1172
1173         BLI_threadapi_init();
1174
1175         RNA_init();
1176         RE_engines_init();
1177
1178                 /* Hack - force inclusion of the plugin api functions,
1179                  * see blenpluginapi:pluginapi.c
1180                  */
1181         pluginapi_force_ref();
1182
1183         init_nodesystem();
1184         
1185         initglobals();  /* blender.c */
1186
1187         IMB_init();
1188
1189 #ifdef WITH_GAMEENGINE
1190         syshandle = SYS_GetSystem();
1191         GEN_init_messaging_system();
1192 #else
1193         syshandle= 0;
1194 #endif
1195
1196         /* first test for background */
1197         ba = BLI_argsInit(argc, argv); /* skip binary path */
1198         setupArguments(C, ba, &syshandle);
1199
1200         BLI_argsParse(ba, 1, NULL, NULL);
1201
1202 #ifdef __sgi
1203         setuid(getuid()); /* end superuser */
1204 #endif
1205
1206 #ifdef WITH_PYTHON_MODULE
1207         G.background= 1; /* python module mode ALWAYS runs in background mode (for now) */
1208 #else
1209         /* for all platforms, even windos has it! */
1210         if(G.background) signal(SIGINT, blender_esc);   /* ctrl c out bg render */
1211 #endif
1212
1213         /* background render uses this font too */
1214         BKE_font_register_builtin(datatoc_Bfont, datatoc_Bfont_size);
1215
1216         /* Initialiaze ffmpeg if built in, also needed for bg mode if videos are
1217            rendered via ffmpeg */
1218         sound_init_once();
1219         
1220         init_def_material();
1221
1222         if(G.background==0) {
1223                 BLI_argsParse(ba, 2, NULL, NULL);
1224                 BLI_argsParse(ba, 3, NULL, NULL);
1225
1226                 WM_init(C, argc, argv);
1227
1228                 /* this is properly initialized with user defs, but this is default */
1229                 BLI_where_is_temp(btempdir, FILE_MAX, 1); /* call after loading the startup.blend so we can read U.tempdir */
1230
1231 #ifndef DISABLE_SDL
1232         BLI_setenv("SDL_VIDEODRIVER", "dummy");
1233 #endif
1234         }
1235         else {
1236                 BLI_argsParse(ba, 3, NULL, NULL);
1237
1238                 WM_init(C, argc, argv);
1239
1240                 BLI_where_is_temp(btempdir, FILE_MAX, 0); /* call after loading the startup.blend so we can read U.tempdir */
1241         }
1242 #ifdef WITH_PYTHON
1243         /**
1244          * NOTE: the U.pythondir string is NULL until WM_init() is executed,
1245          * so we provide the BPY_ function below to append the user defined
1246          * pythondir to Python's sys.path at this point.  Simply putting
1247          * WM_init() before BPY_python_start() crashes Blender at startup.
1248          * Update: now this function also inits the bpymenus, which also depend
1249          * on U.pythondir.
1250          */
1251
1252         // TODO - U.pythondir
1253 #else
1254         printf("\n* WARNING * - Blender compiled without Python!\nthis is not intended for typical usage\n\n");
1255 #endif
1256         
1257         CTX_py_init_set(C, 1);
1258         WM_keymap_init(C);
1259
1260         /* OK we are ready for it */
1261         BLI_argsParse(ba, 4, load_file, C);
1262
1263         BLI_argsFree(ba);
1264
1265 #ifdef WITH_PYTHON_MODULE
1266         return 0; /* keep blender in background mode running */
1267 #endif
1268
1269         if(G.background) {
1270                 /* actually incorrect, but works for now (ton) */
1271                 WM_exit(C);
1272         }
1273
1274         else {
1275                 if((G.fileflags & G_FILE_AUTOPLAY) && (G.f & G_SCRIPT_AUTOEXEC))
1276                 {
1277                         if(WM_init_game(C))
1278                                 return 0;
1279                 }
1280                 else if(!G.file_loaded)
1281                         WM_init_splash(C);
1282         }
1283
1284         WM_main(C);
1285
1286
1287         /*XXX if (scr_init==0) {
1288                 main_init_screen();
1289         }
1290         
1291         screenmain();*/ /* main display loop */
1292
1293         return 0;
1294 } /* end of int main(argc,argv) */
1295
1296 static void error_cb(const char *err)
1297 {
1298         
1299         printf("%s\n", err);    /* XXX do this in WM too */
1300 }
1301
1302 static void mem_error_cb(const char *errorStr)
1303 {
1304         fputs(errorStr, stderr);
1305         fflush(stderr);
1306 }
1307
1308 static void setCallbacks(void)
1309 {
1310         /* Error output from the alloc routines: */
1311         MEM_set_error_callback(mem_error_cb);
1312
1313
1314         /* BLI_blenlib: */
1315
1316         BLI_setErrorCallBack(error_cb); /* */
1317 // XXX  BLI_setInterruptCallBack(blender_test_break);
1318
1319 }