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