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