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