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