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