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