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