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