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