fix for crash with new buildinfo, when gmtime() returns NULL
[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 unsigned long build_commit_timestamp;
158
159 /* TODO(sergey): ideally size need to be in sync with buildinfo.c */
160 extern char build_commit_date[16];
161 extern char build_commit_time[16];
162
163 extern char build_branch[];
164 extern char build_platform[];
165 extern char build_type[];
166 extern char build_cflags[];
167 extern char build_cxxflags[];
168 extern char build_linkflags[];
169 extern char build_system[];
170 #endif
171
172 /*      Local Function prototypes */
173 #ifdef WITH_PYTHON_MODULE
174 int  main_python_enter(int argc, const char **argv);
175 void main_python_exit(void);
176 #else
177 static int print_help(int argc, const char **argv, void *data);
178 static int print_version(int argc, const char **argv, void *data);
179 #endif
180
181 /* for the callbacks: */
182 #ifndef WITH_PYTHON_MODULE
183 #define BLEND_VERSION_FMT         "Blender %d.%02d (sub %d)"
184 #define BLEND_VERSION_ARG         BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION
185 /* pass directly to printf */
186 #define BLEND_VERSION_STRING_FMT  BLEND_VERSION_FMT "\n", BLEND_VERSION_ARG
187 #endif
188
189 /* Initialize callbacks for the modules that need them */
190 static void setCallbacks(void); 
191
192 #ifndef WITH_PYTHON_MODULE
193
194 static bool use_crash_handler = true;
195
196 /* set breakpoints here when running in debug mode, useful to catch floating point errors */
197 #if defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE)
198 static void fpe_handler(int UNUSED(sig))
199 {
200         // printf("SIGFPE trapped\n");
201 }
202 #endif
203
204 /* handling ctrl-c event in console */
205 #if !(defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS))
206 static void blender_esc(int sig)
207 {
208         static int count = 0;
209         
210         G.is_break = TRUE;  /* forces render loop to read queue, not sure if its needed */
211         
212         if (sig == 2) {
213                 if (count) {
214                         printf("\nBlender killed\n");
215                         exit(2);
216                 }
217                 printf("\nSent an internal break event. Press ^C again to kill Blender\n");
218                 count++;
219         }
220 }
221 #endif
222
223 static int print_version(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
224 {
225         printf(BLEND_VERSION_STRING_FMT);
226 #ifdef BUILD_DATE
227         printf("\tbuild date: %s\n", build_date);
228         printf("\tbuild time: %s\n", build_time);
229         printf("\tbuild commit date: %s\n", build_commit_date);
230         printf("\tbuild commit time: %s\n", build_commit_time);
231         printf("\tbuild hash: %s\n", build_hash);
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         BLI_snprintf(header, sizeof(header), "# " BLEND_VERSION_FMT ", Commit date: %s %s, Hash %s\n",
606                      BLEND_VERSION_ARG, build_commit_date, build_commit_time, build_hash);
607 #endif
608
609         /* open the crash log */
610         errno = 0;
611         fp = BLI_fopen(fname, "wb");
612         if (fp == NULL) {
613                 fprintf(stderr, "Unable to save '%s': %s\n",
614                         fname, errno ? strerror(errno) : "Unknown error opening file");
615         }
616         else {
617                 if (wm) {
618                         BKE_report_write_file_fp(fp, &wm->reports, header);
619                 }
620
621                 blender_crash_handler_backtrace(fp);
622
623                 fclose(fp);
624         }
625
626
627         /* really crash */
628         signal(signum, SIG_DFL);
629 #ifndef WIN32
630         kill(getpid(), signum);
631 #else
632         TerminateProcess(GetCurrentProcess(), signum);
633 #endif
634 }
635
636
637 static int set_factory_startup(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
638 {
639         G.factory_startup = 1;
640         return 0;
641 }
642
643 static int set_env(int argc, const char **argv, void *UNUSED(data))
644 {
645         /* "--env-system-scripts" --> "BLENDER_SYSTEM_SCRIPTS" */
646
647         char env[64] = "BLENDER";
648         char *ch_dst = env + 7; /* skip BLENDER */
649         const char *ch_src = argv[0] + 5; /* skip --env */
650
651         if (argc < 2) {
652                 printf("%s requires one argument\n", argv[0]);
653                 exit(1);
654         }
655
656         for (; *ch_src; ch_src++, ch_dst++) {
657                 *ch_dst = (*ch_src == '-') ? '_' : (*ch_src) - 32; /* toupper() */
658         }
659
660         *ch_dst = '\0';
661         BLI_setenv(env, argv[1]);
662         return 1;
663 }
664
665 static int playback_mode(int argc, const char **argv, void *UNUSED(data))
666 {
667         /* not if -b was given first */
668         if (G.background == 0) {
669 #ifdef WITH_FFMPEG
670                 /* Setup FFmpeg with current debug flags. */
671                 IMB_ffmpeg_init();
672 #endif
673
674                 WM_main_playanim(argc, argv); /* not the same argc and argv as before */
675                 exit(0); /* 2.4x didn't do this */
676         }
677
678         return -2;
679 }
680
681 static int prefsize(int argc, const char **argv, void *UNUSED(data))
682 {
683         int stax, stay, sizx, sizy;
684
685         if (argc < 5) {
686                 fprintf(stderr, "-p requires four arguments\n");
687                 exit(1);
688         }
689
690         stax = atoi(argv[1]);
691         stay = atoi(argv[2]);
692         sizx = atoi(argv[3]);
693         sizy = atoi(argv[4]);
694
695         WM_init_state_size_set(stax, stay, sizx, sizy);
696
697         return 4;
698 }
699
700 static int native_pixels(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
701 {
702         WM_init_native_pixels(false);
703         return 0;
704 }
705
706 static int with_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
707 {
708         WM_init_state_normal_set();
709         return 0;
710 }
711
712 static int without_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
713 {
714         WM_init_state_fullscreen_set();
715         return 0;
716 }
717
718 extern bool wm_start_with_console; /* wm_init_exit.c */
719 static int start_with_console(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
720 {
721         wm_start_with_console = true;
722         return 0;
723 }
724
725 static int register_extension(int UNUSED(argc), const char **UNUSED(argv), void *data)
726 {
727 #ifdef WIN32
728         if (data)
729                 G.background = 1;
730         RegisterBlendExtension();
731 #else
732         (void)data; /* unused */
733 #endif
734         return 0;
735 }
736
737 static int no_joystick(int UNUSED(argc), const char **UNUSED(argv), void *data)
738 {
739 #ifndef WITH_GAMEENGINE
740         (void)data;
741 #else
742         SYS_SystemHandle *syshandle = data;
743
744         /**
745          * don't initialize joysticks if user doesn't want to use joysticks
746          * failed joystick initialization delays over 5 seconds, before game engine start
747          */
748         SYS_WriteCommandLineInt(*syshandle, "nojoystick", 1);
749         if (G.debug & G_DEBUG) printf("disabling nojoystick\n");
750 #endif
751
752         return 0;
753 }
754
755 static int no_glsl(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
756 {
757         GPU_extensions_disable();
758         return 0;
759 }
760
761 static int no_audio(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
762 {
763         sound_force_device(0);
764         return 0;
765 }
766
767 static int set_audio(int argc, const char **argv, void *UNUSED(data))
768 {
769         if (argc < 1) {
770                 fprintf(stderr, "-setaudio require one argument\n");
771                 exit(1);
772         }
773
774         sound_force_device(sound_define_from_str(argv[1]));
775         return 1;
776 }
777
778 static int set_output(int argc, const char **argv, void *data)
779 {
780         bContext *C = data;
781         if (argc >= 1) {
782                 Scene *scene = CTX_data_scene(C);
783                 if (scene) {
784                         BLI_strncpy(scene->r.pic, argv[1], sizeof(scene->r.pic));
785                 }
786                 else {
787                         printf("\nError: no blend loaded. cannot use '-o / --render-output'.\n");
788                 }
789                 return 1;
790         }
791         else {
792                 printf("\nError: you must specify a path after '-o  / --render-output'.\n");
793                 return 0;
794         }
795 }
796
797 static int set_engine(int argc, const char **argv, void *data)
798 {
799         bContext *C = data;
800         if (argc >= 2) {
801                 if (!strcmp(argv[1], "help")) {
802                         RenderEngineType *type = NULL;
803                         printf("Blender Engine Listing:\n");
804                         for (type = R_engines.first; type; type = type->next) {
805                                 printf("\t%s\n", type->idname);
806                         }
807                         exit(0);
808                 }
809                 else {
810                         Scene *scene = CTX_data_scene(C);
811                         if (scene) {
812                                 RenderData *rd = &scene->r;
813
814                                 if (BLI_findstring(&R_engines, argv[1], offsetof(RenderEngineType, idname))) {
815                                         BLI_strncpy_utf8(rd->engine, argv[1], sizeof(rd->engine));
816                                 }
817                         }
818                         else {
819                                 printf("\nError: no blend loaded. order the arguments so '-E  / --engine ' is after a blend is loaded.\n");
820                         }
821                 }
822
823                 return 1;
824         }
825         else {
826                 printf("\nEngine not specified, give 'help' for a list of available engines.\n");
827                 return 0;
828         }
829 }
830
831 static int set_image_type(int argc, const char **argv, void *data)
832 {
833         bContext *C = data;
834         if (argc > 1) {
835                 const char *imtype = argv[1];
836                 Scene *scene = CTX_data_scene(C);
837                 if (scene) {
838                         const char imtype_new = BKE_imtype_from_arg(imtype);
839
840                         if (imtype_new == R_IMF_IMTYPE_INVALID) {
841                                 printf("\nError: Format from '-F / --render-format' not known or not compiled in this release.\n");
842                         }
843                         else {
844                                 scene->r.im_format.imtype = imtype_new;
845                         }
846                 }
847                 else {
848                         printf("\nError: no blend loaded. order the arguments so '-F  / --render-format' is after the blend is loaded.\n");
849                 }
850                 return 1;
851         }
852         else {
853                 printf("\nError: you must specify a format after '-F  / --render-foramt'.\n");
854                 return 0;
855         }
856 }
857
858 static int set_threads(int argc, const char **argv, void *UNUSED(data))
859 {
860         if (argc > 1) {
861                 int threads = atoi(argv[1]);
862
863                 if (threads >= 0 && threads <= BLENDER_MAX_THREADS) {
864                         BLI_system_num_threads_override_set(threads);
865                 }
866                 else {
867                         printf("Error, threads has to be in range 0-%d\n", BLENDER_MAX_THREADS);
868                 }
869                 return 1;
870         }
871         else {
872                 printf("\nError: you must specify a number of threads between 0 and 8 '-t  / --threads'.\n");
873                 return 0;
874         }
875 }
876
877 static int set_verbosity(int argc, const char **argv, void *UNUSED(data))
878 {
879         if (argc > 1) {
880                 int level = atoi(argv[1]);
881
882 #ifdef WITH_LIBMV
883                 libmv_setLoggingVerbosity(level);
884 #else
885                 (void)level;
886 #endif
887
888                 return 1;
889         }
890         else {
891                 printf("\nError: you must specify a verbosity level.\n");
892                 return 0;
893         }
894 }
895
896 static int set_extension(int argc, const char **argv, void *data)
897 {
898         bContext *C = data;
899         if (argc >= 1) {
900                 Scene *scene = CTX_data_scene(C);
901                 if (scene) {
902                         if (argv[1][0] == '0') {
903                                 scene->r.scemode &= ~R_EXTENSION;
904                         }
905                         else if (argv[1][0] == '1') {
906                                 scene->r.scemode |= R_EXTENSION;
907                         }
908                         else {
909                                 printf("\nError: Use '-x 1 / -x 0' To set the extension option or '--use-extension'\n");
910                         }
911                 }
912                 else {
913                         printf("\nError: no blend loaded. order the arguments so '-o ' is after '-x '.\n");
914                 }
915                 return 1;
916         }
917         else {
918                 printf("\nError: you must specify a path after '- '.\n");
919                 return 0;
920         }
921 }
922
923 static int set_ge_parameters(int argc, const char **argv, void *data)
924 {
925         int a = 0;
926 #ifdef WITH_GAMEENGINE
927         SYS_SystemHandle syshandle = *(SYS_SystemHandle *)data;
928 #else
929         (void)data;
930 #endif
931
932         /**
933          * gameengine parameters are automatically put into system
934          * -g [paramname = value]
935          * -g [boolparamname]
936          * example:
937          * -g novertexarrays
938          * -g maxvertexarraysize = 512
939          */
940
941         if (argc >= 1) {
942                 const char *paramname = argv[a];
943                 /* check for single value versus assignment */
944                 if (a + 1 < argc && (*(argv[a + 1]) == '=')) {
945                         a++;
946                         if (a + 1 < argc) {
947                                 a++;
948                                 /* assignment */
949 #ifdef WITH_GAMEENGINE
950                                 SYS_WriteCommandLineString(syshandle, paramname, argv[a]);
951 #endif
952                         }
953                         else {
954                                 printf("error: argument assignment (%s) without value.\n", paramname);
955                                 return 0;
956                         }
957                         /* name arg eaten */
958
959                 }
960                 else {
961 #ifdef WITH_GAMEENGINE
962                         SYS_WriteCommandLineInt(syshandle, argv[a], 1);
963 #endif
964                         /* doMipMap */
965                         if (!strcmp(argv[a], "nomipmap")) {
966                                 GPU_set_mipmap(0); //doMipMap = 0;
967                         }
968                         /* linearMipMap */
969                         if (!strcmp(argv[a], "linearmipmap")) {
970                                 GPU_set_linear_mipmap(1); //linearMipMap = 1;
971                         }
972
973
974                 } /* if (*(argv[a + 1]) == '=') */
975         }
976
977         return a;
978 }
979
980 static int render_frame(int argc, const char **argv, void *data)
981 {
982         bContext *C = data;
983         Scene *scene = CTX_data_scene(C);
984         if (scene) {
985                 Main *bmain = CTX_data_main(C);
986
987                 if (argc > 1) {
988                         Render *re = RE_NewRender(scene->id.name);
989                         int frame;
990                         ReportList reports;
991
992                         switch (*argv[1]) {
993                                 case '+':
994                                         frame = scene->r.sfra + atoi(argv[1] + 1);
995                                         break;
996                                 case '-':
997                                         frame = (scene->r.efra - atoi(argv[1] + 1)) + 1;
998                                         break;
999                                 default:
1000                                         frame = atoi(argv[1]);
1001                                         break;
1002                         }
1003
1004                         BKE_reports_init(&reports, RPT_PRINT);
1005
1006                         frame = CLAMPIS(frame, MINAFRAME, MAXFRAME);
1007
1008                         RE_SetReports(re, &reports);
1009                         RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, frame, frame, scene->r.frame_step);
1010                         RE_SetReports(re, NULL);
1011                         return 1;
1012                 }
1013                 else {
1014                         printf("\nError: frame number must follow '-f / --render-frame'.\n");
1015                         return 0;
1016                 }
1017         }
1018         else {
1019                 printf("\nError: no blend loaded. cannot use '-f / --render-frame'.\n");
1020                 return 0;
1021         }
1022 }
1023
1024 static int render_animation(int UNUSED(argc), const char **UNUSED(argv), void *data)
1025 {
1026         bContext *C = data;
1027         Scene *scene = CTX_data_scene(C);
1028         if (scene) {
1029                 Main *bmain = CTX_data_main(C);
1030                 Render *re = RE_NewRender(scene->id.name);
1031                 ReportList reports;
1032                 BKE_reports_init(&reports, RPT_PRINT);
1033                 RE_SetReports(re, &reports);
1034                 RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step);
1035                 RE_SetReports(re, NULL);
1036         }
1037         else {
1038                 printf("\nError: no blend loaded. cannot use '-a'.\n");
1039         }
1040         return 0;
1041 }
1042
1043 static int set_scene(int argc, const char **argv, void *data)
1044 {
1045         if (argc > 1) {
1046                 bContext *C = data;
1047                 Scene *scene = BKE_scene_set_name(CTX_data_main(C), argv[1]);
1048                 if (scene) {
1049                         CTX_data_scene_set(C, scene);
1050                 }
1051                 return 1;
1052         }
1053         else {
1054                 printf("\nError: Scene name must follow '-S / --scene'.\n");
1055                 return 0;
1056         }
1057 }
1058
1059 static int set_start_frame(int argc, const char **argv, void *data)
1060 {
1061         bContext *C = data;
1062         Scene *scene = CTX_data_scene(C);
1063         if (scene) {
1064                 if (argc > 1) {
1065                         int frame = atoi(argv[1]);
1066                         (scene->r.sfra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
1067                         return 1;
1068                 }
1069                 else {
1070                         printf("\nError: frame number must follow '-s / --frame-start'.\n");
1071                         return 0;
1072                 }
1073         }
1074         else {
1075                 printf("\nError: no blend loaded. cannot use '-s / --frame-start'.\n");
1076                 return 0;
1077         }
1078 }
1079
1080 static int set_end_frame(int argc, const char **argv, void *data)
1081 {
1082         bContext *C = data;
1083         Scene *scene = CTX_data_scene(C);
1084         if (scene) {
1085                 if (argc > 1) {
1086                         int frame = atoi(argv[1]);
1087                         (scene->r.efra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
1088                         return 1;
1089                 }
1090                 else {
1091                         printf("\nError: frame number must follow '-e / --frame-end'.\n");
1092                         return 0;
1093                 }
1094         }
1095         else {
1096                 printf("\nError: no blend loaded. cannot use '-e / --frame-end'.\n");
1097                 return 0;
1098         }
1099 }
1100
1101 static int set_skip_frame(int argc, const char **argv, void *data)
1102 {
1103         bContext *C = data;
1104         Scene *scene = CTX_data_scene(C);
1105         if (scene) {
1106                 if (argc > 1) {
1107                         int frame = atoi(argv[1]);
1108                         (scene->r.frame_step) = CLAMPIS(frame, 1, MAXFRAME);
1109                         return 1;
1110                 }
1111                 else {
1112                         printf("\nError: number of frames to step must follow '-j / --frame-jump'.\n");
1113                         return 0;
1114                 }
1115         }
1116         else {
1117                 printf("\nError: no blend loaded. cannot use '-j / --frame-jump'.\n");
1118                 return 0;
1119         }
1120 }
1121
1122 /* macro for ugly context setup/reset */
1123 #ifdef WITH_PYTHON
1124 #define BPY_CTX_SETUP(_cmd)                                                   \
1125         {                                                                         \
1126                 wmWindowManager *wm = CTX_wm_manager(C);                              \
1127                 wmWindow *prevwin = CTX_wm_window(C);                                 \
1128                 Scene *prevscene = CTX_data_scene(C);                                 \
1129                 if (wm->windows.first) {                                              \
1130                         CTX_wm_window_set(C, wm->windows.first);                          \
1131                         _cmd;                                                             \
1132                         CTX_wm_window_set(C, prevwin);                                    \
1133                 }                                                                     \
1134                 else {                                                                \
1135                         fprintf(stderr, "Python script \"%s\" "                           \
1136                                 "running with missing context data.\n", argv[1]);         \
1137                         _cmd;                                                             \
1138                 }                                                                     \
1139                 CTX_data_scene_set(C, prevscene);                                     \
1140         } (void)0                                                                 \
1141
1142 #endif /* WITH_PYTHON */
1143
1144 static int run_python_file(int argc, const char **argv, void *data)
1145 {
1146 #ifdef WITH_PYTHON
1147         bContext *C = data;
1148
1149         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1150         if (argc > 1) {
1151                 /* Make the path absolute because its needed for relative linked blends to be found */
1152                 char filename[FILE_MAX];
1153                 BLI_strncpy(filename, argv[1], sizeof(filename));
1154                 BLI_path_cwd(filename);
1155
1156                 BPY_CTX_SETUP(BPY_filepath_exec(C, filename, NULL));
1157
1158                 return 1;
1159         }
1160         else {
1161                 printf("\nError: you must specify a filepath after '%s'.\n", argv[0]);
1162                 return 0;
1163         }
1164 #else
1165         (void)argc; (void)argv; (void)data; /* unused */
1166         printf("This blender was built without python support\n");
1167         return 0;
1168 #endif /* WITH_PYTHON */
1169 }
1170
1171 static int run_python_text(int argc, const char **argv, void *data)
1172 {
1173 #ifdef WITH_PYTHON
1174         bContext *C = data;
1175
1176         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1177         if (argc > 1) {
1178                 /* Make the path absolute because its needed for relative linked blends to be found */
1179                 struct Text *text = (struct Text *)BKE_libblock_find_name(ID_TXT, argv[1]);
1180
1181                 if (text) {
1182                         BPY_CTX_SETUP(BPY_text_exec(C, text, NULL, false));
1183                         return 1;
1184                 }
1185                 else {
1186                         printf("\nError: text block not found %s.\n", argv[1]);
1187                         return 1;
1188                 }
1189         }
1190         else {
1191                 printf("\nError: you must specify a text block after '%s'.\n", argv[0]);
1192                 return 0;
1193         }
1194 #else
1195         (void)argc; (void)argv; (void)data; /* unused */
1196         printf("This blender was built without python support\n");
1197         return 0;
1198 #endif /* WITH_PYTHON */
1199 }
1200
1201 static int run_python_console(int UNUSED(argc), const char **argv, void *data)
1202 {
1203 #ifdef WITH_PYTHON
1204         bContext *C = data;
1205
1206         BPY_CTX_SETUP(BPY_string_exec(C, "__import__('code').interact()"));
1207
1208         return 0;
1209 #else
1210         (void)argv; (void)data; /* unused */
1211         printf("This blender was built without python support\n");
1212         return 0;
1213 #endif /* WITH_PYTHON */
1214 }
1215
1216 static int set_addons(int argc, const char **argv, void *data)
1217 {
1218         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1219         if (argc > 1) {
1220 #ifdef WITH_PYTHON
1221                 const int slen = strlen(argv[1]) + 128;
1222                 char *str = malloc(slen);
1223                 bContext *C = data;
1224                 BLI_snprintf(str, slen, "[__import__('addon_utils').enable(i, default_set=False) for i in '%s'.split(',')]", argv[1]);
1225                 BPY_CTX_SETUP(BPY_string_exec(C, str));
1226                 free(str);
1227 #else
1228                 (void)argv; (void)data; /* unused */
1229 #endif /* WITH_PYTHON */
1230                 return 1;
1231         }
1232         else {
1233                 printf("\nError: you must specify a comma separated list after '--addons'.\n");
1234                 return 0;
1235         }
1236 }
1237
1238 static int load_file(int UNUSED(argc), const char **argv, void *data)
1239 {
1240         bContext *C = data;
1241
1242         /* Make the path absolute because its needed for relative linked blends to be found */
1243         char filename[FILE_MAX];
1244
1245         /* note, we could skip these, but so far we always tried to load these files */
1246         if (argv[0][0] == '-') {
1247                 fprintf(stderr, "unknown argument, loading as file: %s\n", argv[0]);
1248         }
1249
1250         BLI_strncpy(filename, argv[0], sizeof(filename));
1251         BLI_path_cwd(filename);
1252
1253         if (G.background) {
1254                 int retval = BKE_read_file(C, filename, NULL);
1255
1256                 /* we successfully loaded a blend file, get sure that
1257                  * pointcache works */
1258                 if (retval != BKE_READ_FILE_FAIL) {
1259                         wmWindowManager *wm = CTX_wm_manager(C);
1260
1261                         /* special case, 2.4x files */
1262                         if (wm == NULL && CTX_data_main(C)->wm.first == NULL) {
1263                                 extern void wm_add_default(bContext *C);
1264
1265                                 /* wm_add_default() needs the screen to be set. */
1266                                 CTX_wm_screen_set(C, CTX_data_main(C)->screen.first);
1267                                 wm_add_default(C);
1268                         }
1269
1270                         CTX_wm_manager_set(C, NULL); /* remove wm to force check */
1271                         WM_check(C);
1272                         G.relbase_valid = 1;
1273                         if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm);  /* reset wm */
1274
1275                         DAG_on_visible_update(CTX_data_main(C), TRUE);
1276                 }
1277                 else {
1278                         /* failed to load file, stop processing arguments */
1279                         return -1;
1280                 }
1281
1282                 /* WM_file_read() runs normally but since we're in background mode do here */
1283 #ifdef WITH_PYTHON
1284                 /* run any texts that were loaded in and flagged as modules */
1285                 BPY_python_reset(C);
1286 #endif
1287
1288                 /* happens for the UI on file reading too (huh? (ton))*/
1289                 // XXX          BKE_reset_undo();
1290                 //                      BKE_write_undo("original");     /* save current state */
1291         }
1292         else {
1293                 /* we are not running in background mode here, but start blender in UI mode with
1294                  * a file - this should do everything a 'load file' does */
1295                 ReportList reports;
1296                 BKE_reports_init(&reports, RPT_PRINT);
1297                 WM_file_autoexec_init(filename);
1298                 WM_file_read(C, filename, &reports);
1299                 BKE_reports_clear(&reports);
1300         }
1301
1302         G.file_loaded = 1;
1303
1304         return 0;
1305 }
1306
1307 static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
1308 {
1309         static char output_doc[] = "<path>"
1310                 "\n\tSet the render path and file name."
1311                 "\n\tUse // at the start of the path to"
1312                 "\n\t\trender relative to the blend file."
1313                 "\n\tThe # characters are replaced by the frame number, and used to define zero padding."
1314                 "\n\t\tani_##_test.png becomes ani_01_test.png"
1315                 "\n\t\ttest-######.png becomes test-000001.png"
1316                 "\n\t\tWhen the filename does not contain #, The suffix #### is added to the filename"
1317                 "\n\tThe frame number will be added at the end of the filename."
1318                 "\n\t\teg: blender -b foobar.blend -o //render_ -F PNG -x 1 -a"
1319                 "\n\t\t//render_ becomes //render_####, writing frames as //render_0001.png//";
1320
1321         static char format_doc[] = "<format>"
1322                 "\n\tSet the render format, Valid options are..."
1323                 "\n\t\tTGA IRIS JPEG MOVIE IRIZ RAWTGA"
1324                 "\n\t\tAVIRAW AVIJPEG PNG BMP FRAMESERVER"
1325                 "\n\t(formats that can be compiled into blender, not available on all systems)"
1326                 "\n\t\tHDR TIFF EXR MULTILAYER MPEG AVICODEC QUICKTIME CINEON DPX DDS";
1327
1328         static char playback_doc[] = "<options> <file(s)>"
1329                 "\n\tPlayback <file(s)>, only operates this way when not running in background."
1330                 "\n\t\t-p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>"
1331                 "\n\t\t-m\t\tRead from disk (Don't buffer)"
1332                 "\n\t\t-f <fps> <fps-base>\t\tSpecify FPS to start with"
1333                 "\n\t\t-j <frame>\tSet frame step to <frame>"
1334                 "\n\t\t-s <frame>\tPlay from <frame>"
1335                 "\n\t\t-e <frame>\tPlay until <frame>";
1336
1337         static char game_doc[] = "Game Engine specific options"
1338                 "\n\t-g fixedtime\t\tRun on 50 hertz without dropping frames"
1339                 "\n\t-g vertexarrays\t\tUse Vertex Arrays for rendering (usually faster)"
1340                 "\n\t-g nomipmap\t\tNo Texture Mipmapping"
1341                 "\n\t-g linearmipmap\t\tLinear Texture Mipmapping instead of Nearest (default)";
1342
1343         static char debug_doc[] = "\n\tTurn debugging on\n"
1344                 "\n\t* Prints every operator call and their arguments"
1345                 "\n\t* Disables mouse grab (to interact with a debugger in some cases)"
1346                 "\n\t* Keeps python sys.stdin rather than setting it to None";
1347
1348         //BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
1349
1350         /* end argument processing after -- */
1351         BLI_argsAdd(ba, -1, "--", NULL, "\n\tEnds option processing, following arguments passed unchanged. Access via python's sys.argv", end_arguments, NULL);
1352
1353         /* first pass: background mode, disable python and commands that exit after usage */
1354         BLI_argsAdd(ba, 1, "-h", "--help", "\n\tPrint this help text and exit", print_help, ba);
1355         /* Windows only */
1356         BLI_argsAdd(ba, 1, "/?", NULL, "\n\tPrint this help text and exit (windows only)", print_help, ba);
1357
1358         BLI_argsAdd(ba, 1, "-v", "--version", "\n\tPrint Blender version and exit", print_version, NULL);
1359         
1360         /* only to give help message */
1361 #ifndef WITH_PYTHON_SECURITY /* default */
1362 #  define   PY_ENABLE_AUTO ", (default)"
1363 #  define   PY_DISABLE_AUTO ""
1364 #else
1365 #  define   PY_ENABLE_AUTO ""
1366 #  define   PY_DISABLE_AUTO ", (compiled as non-standard default)"
1367 #endif
1368
1369         BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", "\n\tEnable automatic python script execution" PY_ENABLE_AUTO, enable_python, NULL);
1370         BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", "\n\tDisable automatic python script execution (pydrivers & startup scripts)" PY_DISABLE_AUTO, disable_python, NULL);
1371
1372         BLI_argsAdd(ba, 1, NULL, "--disable-crash-handler", "\n\tDisable the crash handler", disable_crash_handler, NULL);
1373
1374 #undef PY_ENABLE_AUTO
1375 #undef PY_DISABLE_AUTO
1376         
1377         BLI_argsAdd(ba, 1, "-b", "--background", "<file>\n\tLoad <file> in background (often used for UI-less rendering)", background_mode, NULL);
1378
1379         BLI_argsAdd(ba, 1, "-a", NULL, playback_doc, playback_mode, NULL);
1380
1381         BLI_argsAdd(ba, 1, "-d", "--debug", debug_doc, debug_mode, ba);
1382
1383 #ifdef WITH_FFMPEG
1384         BLI_argsAdd(ba, 1, NULL, "--debug-ffmpeg", "\n\tEnable debug messages from FFmpeg library", debug_mode_generic, (void *)G_DEBUG_FFMPEG);
1385 #endif
1386
1387 #ifdef WITH_FREESTYLE
1388         BLI_argsAdd(ba, 1, NULL, "--debug-freestyle", "\n\tEnable debug/profiling messages from Freestyle rendering", debug_mode_generic, (void *)G_DEBUG_FREESTYLE);
1389 #endif
1390
1391         BLI_argsAdd(ba, 1, NULL, "--debug-python", "\n\tEnable debug messages for python", debug_mode_generic, (void *)G_DEBUG_PYTHON);
1392         BLI_argsAdd(ba, 1, NULL, "--debug-events", "\n\tEnable debug messages for the event system", debug_mode_generic, (void *)G_DEBUG_EVENTS);
1393         BLI_argsAdd(ba, 1, NULL, "--debug-handlers", "\n\tEnable debug messages for event handling", debug_mode_generic, (void *)G_DEBUG_HANDLERS);
1394         BLI_argsAdd(ba, 1, NULL, "--debug-wm",     "\n\tEnable debug messages for the window manager", debug_mode_generic, (void *)G_DEBUG_WM);
1395         BLI_argsAdd(ba, 1, NULL, "--debug-all",    "\n\tEnable all debug messages (excludes libmv)", debug_mode_generic, (void *)G_DEBUG_ALL);
1396
1397         BLI_argsAdd(ba, 1, NULL, "--debug-fpe", "\n\tEnable floating point exceptions", set_fpe, NULL);
1398
1399 #ifdef WITH_LIBMV
1400         BLI_argsAdd(ba, 1, NULL, "--debug-libmv", "\n\tEnable debug messages from libmv library", debug_mode_libmv, NULL);
1401 #endif
1402         BLI_argsAdd(ba, 1, NULL, "--debug-memory", "\n\tEnable fully guarded memory allocation and debugging", debug_mode_memory, NULL);
1403
1404         BLI_argsAdd(ba, 1, NULL, "--debug-value", "<value>\n\tSet debug value of <value> on startup\n", set_debug_value, NULL);
1405         BLI_argsAdd(ba, 1, NULL, "--debug-jobs",  "\n\tEnable time profiling for background jobs.", debug_mode_generic, (void *)G_DEBUG_JOBS);
1406
1407         BLI_argsAdd(ba, 1, NULL, "--verbose", "<verbose>\n\tSet logging verbosity level.", set_verbosity, NULL);
1408
1409         BLI_argsAdd(ba, 1, NULL, "--factory-startup", "\n\tSkip reading the "STRINGIFY (BLENDER_STARTUP_FILE)" in the users home directory", set_factory_startup, NULL);
1410
1411         /* TODO, add user env vars? */
1412         BLI_argsAdd(ba, 1, NULL, "--env-system-datafiles",  "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_DATAFILES)" environment variable", set_env, NULL);
1413         BLI_argsAdd(ba, 1, NULL, "--env-system-scripts",    "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_SCRIPTS)" environment variable", set_env, NULL);
1414         BLI_argsAdd(ba, 1, NULL, "--env-system-python",     "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_PYTHON)" environment variable", set_env, NULL);
1415
1416         /* second pass: custom window stuff */
1417         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);
1418         BLI_argsAdd(ba, 2, "-w", "--window-border", "\n\tForce opening with borders (default)", with_borders, NULL);
1419         BLI_argsAdd(ba, 2, "-W", "--window-borderless", "\n\tForce opening without borders", without_borders, NULL);
1420         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);
1421         BLI_argsAdd(ba, 2, "-R", NULL, "\n\tRegister .blend extension, then exit (Windows only)", register_extension, NULL);
1422         BLI_argsAdd(ba, 2, "-r", NULL, "\n\tSilently register .blend extension, then exit (Windows only)", register_extension, ba);
1423         BLI_argsAdd(ba, 2, NULL, "--no-native-pixels", "\n\tDo not use native pixel size, for high resolution displays (MacBook 'Retina')", native_pixels, ba);
1424
1425         /* third pass: disabling things and forcing settings */
1426         BLI_argsAddCase(ba, 3, "-nojoystick", 1, NULL, 0, "\n\tDisable joystick support", no_joystick, syshandle);
1427         BLI_argsAddCase(ba, 3, "-noglsl", 1, NULL, 0, "\n\tDisable GLSL shading", no_glsl, NULL);
1428         BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, "\n\tForce sound system to None", no_audio, NULL);
1429         BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, "\n\tForce sound system to a specific device\n\tNULL SDL OPENAL JACK", set_audio, NULL);
1430
1431         /* fourth pass: processing arguments */
1432         BLI_argsAdd(ba, 4, "-g", NULL, game_doc, set_ge_parameters, syshandle);
1433         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);
1434         BLI_argsAdd(ba, 4, "-a", "--render-anim", "\n\tRender frames from start to end (inclusive)", render_animation, C);
1435         BLI_argsAdd(ba, 4, "-S", "--scene", "<name>\n\tSet the active scene <name> for rendering", set_scene, C);
1436         BLI_argsAdd(ba, 4, "-s", "--frame-start", "<frame>\n\tSet start to frame <frame> (use before the -a argument)", set_start_frame, C);
1437         BLI_argsAdd(ba, 4, "-e", "--frame-end", "<frame>\n\tSet end to frame <frame> (use before the -a argument)", set_end_frame, C);
1438         BLI_argsAdd(ba, 4, "-j", "--frame-jump", "<frames>\n\tSet number of frames to step forward after each rendered frame", set_skip_frame, C);
1439         BLI_argsAdd(ba, 4, "-P", "--python", "<filename>\n\tRun the given Python script file", run_python_file, C);
1440         BLI_argsAdd(ba, 4, NULL, "--python-text", "<name>\n\tRun the given Python script text block", run_python_text, C);
1441         BLI_argsAdd(ba, 4, NULL, "--python-console", "\n\tRun blender with an interactive console", run_python_console, C);
1442         BLI_argsAdd(ba, 4, NULL, "--addons", "\n\tComma separated list of addons (no spaces)", set_addons, C);
1443
1444         BLI_argsAdd(ba, 4, "-o", "--render-output", output_doc, set_output, C);
1445         BLI_argsAdd(ba, 4, "-E", "--engine", "<engine>\n\tSpecify the render engine\n\tuse -E help to list available engines", set_engine, C);
1446
1447         BLI_argsAdd(ba, 4, "-F", "--render-format", format_doc, set_image_type, C);
1448         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);
1449         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);
1450
1451 }
1452 #endif /* WITH_PYTHON_MODULE */
1453
1454 #ifdef WITH_PYTHON_MODULE
1455 /* allow python module to call main */
1456 #  define main main_python_enter
1457 static void *evil_C = NULL;
1458
1459 #  ifdef __APPLE__
1460      /* environ is not available in mac shared libraries */
1461 #    include <crt_externs.h>
1462 char **environ = NULL;
1463 #  endif
1464 #endif
1465
1466
1467 #ifdef WIN32
1468 int main(int argc, const char **UNUSED(argv_c)) /* Do not mess with const */
1469 #else
1470 int main(int argc, const char **argv)
1471 #endif
1472 {
1473         bContext *C;
1474         SYS_SystemHandle syshandle;
1475
1476 #ifndef WITH_PYTHON_MODULE
1477         bArgs *ba;
1478 #endif
1479
1480 #ifdef WIN32 /* Win32 Unicode Args */
1481         /* NOTE: cannot use guardedalloc malloc here, as it's not yet initialized
1482          *       (it depends on the args passed in, which is what we're getting here!)
1483          */
1484         wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
1485         char **argv = malloc(argc * sizeof(char *));
1486         int argci = 0;
1487         
1488         for (argci = 0; argci < argc; argci++) {
1489                 argv[argci] = alloc_utf_8_from_16(argv_16[argci], 0);
1490         }
1491         
1492         LocalFree(argv_16);
1493 #endif
1494
1495         /* NOTE: Special exception for guarded allocator type switch:
1496          *       we need to perform switch from lock-free to fully
1497          *       guarded allocator before any allocation happened.
1498          */
1499         {
1500                 int i;
1501                 for (i = 0; i < argc; i++) {
1502                         if (STREQ(argv[i], "--debug") || STREQ(argv[i], "-d") ||
1503                             STREQ(argv[i], "--debug-memory"))
1504                         {
1505                                 printf("Switching to fully guarded memory allocator.\n");
1506                                 MEM_use_guarded_allocator();
1507                                 break;
1508                         }
1509                         else if (STREQ(argv[i], "--")) {
1510                                 break;
1511                         }
1512                 }
1513         }
1514
1515 #ifdef BUILD_DATE
1516         {
1517                 time_t temp_time = build_commit_timestamp;
1518                 struct tm *tm = gmtime(&temp_time);
1519                 if (LIKELY(tm)) {
1520                         strftime(build_commit_date, sizeof(build_commit_date), "%Y-%m-%d", tm);
1521                         strftime(build_commit_time, sizeof(build_commit_time), "%H:%M", tm);
1522                 }
1523                 else {
1524                         const char *unknown = "date-unknown";
1525                         BLI_strncpy(build_commit_date, unknown, sizeof(build_commit_date));
1526                         BLI_strncpy(build_commit_time, unknown, sizeof(build_commit_time));
1527                 }
1528         }
1529 #endif
1530
1531         C = CTX_create();
1532
1533 #ifdef WITH_PYTHON_MODULE
1534 #ifdef __APPLE__
1535         environ = *_NSGetEnviron();
1536 #endif
1537
1538 #undef main
1539         evil_C = C;
1540 #endif
1541
1542
1543
1544 #ifdef WITH_BINRELOC
1545         br_init(NULL);
1546 #endif
1547
1548 #ifdef WITH_LIBMV
1549         libmv_initLogging(argv[0]);
1550 #endif
1551
1552         setCallbacks();
1553 #if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE)
1554         /* patch to ignore argument finder gives us (pid?) */
1555         if (argc == 2 && strncmp(argv[1], "-psn_", 5) == 0) {
1556                 extern int GHOST_HACK_getFirstFile(char buf[]);
1557                 static char firstfilebuf[512];
1558
1559                 argc = 1;
1560
1561                 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
1562                         argc = 2;
1563                         argv[1] = firstfilebuf;
1564                 }
1565         }
1566
1567 #endif
1568
1569 #ifdef __FreeBSD__
1570         fpsetmask(0);
1571 #endif
1572
1573         /* initialize path to executable */
1574         BLI_init_program_path(argv[0]);
1575
1576         BLI_threadapi_init();
1577
1578         initglobals();  /* blender.c */
1579
1580         IMB_init();
1581         BKE_images_init();
1582         BKE_modifier_init();
1583
1584         BKE_brush_system_init();
1585
1586         BLI_callback_global_init();
1587
1588 #ifdef WITH_GAMEENGINE
1589         syshandle = SYS_GetSystem();
1590 #else
1591         syshandle = 0;
1592 #endif
1593
1594         /* first test for background */
1595 #ifndef WITH_PYTHON_MODULE
1596         ba = BLI_argsInit(argc, (const char **)argv); /* skip binary path */
1597         setupArguments(C, ba, &syshandle);
1598
1599         BLI_argsParse(ba, 1, NULL, NULL);
1600
1601         if (use_crash_handler) {
1602                 /* after parsing args */
1603                 signal(SIGSEGV, blender_crash_handler);
1604         }
1605 #else
1606         G.factory_startup = true;  /* using preferences or user startup makes no sense for py-as-module */
1607         (void)syshandle;
1608 #endif
1609
1610 #ifdef WITH_FFMPEG
1611         IMB_ffmpeg_init();
1612 #endif
1613
1614         /* after level 1 args, this is so playanim skips RNA init */
1615         RNA_init();
1616
1617         RE_engines_init();
1618         init_nodesystem();
1619         /* end second init */
1620
1621
1622 #if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
1623         G.background = true; /* python module mode ALWAYS runs in background mode (for now) */
1624 #else
1625         /* for all platforms, even windos has it! */
1626         if (G.background) {
1627                 signal(SIGINT, blender_esc);  /* ctrl c out bg render */
1628         }
1629 #endif
1630
1631         /* background render uses this font too */
1632         BKE_vfont_builtin_register(datatoc_bfont_pfb, datatoc_bfont_pfb_size);
1633
1634         /* Initialize ffmpeg if built in, also needed for bg mode if videos are
1635          * rendered via ffmpeg */
1636         sound_init_once();
1637         
1638         init_def_material();
1639
1640         if (G.background == 0) {
1641 #ifndef WITH_PYTHON_MODULE
1642                 BLI_argsParse(ba, 2, NULL, NULL);
1643                 BLI_argsParse(ba, 3, NULL, NULL);
1644 #endif
1645                 WM_init(C, argc, (const char **)argv);
1646
1647                 /* this is properly initialized with user defs, but this is default */
1648                 /* call after loading the startup.blend so we can read U.tempdir */
1649                 BLI_init_temporary_dir(U.tempdir);
1650         }
1651         else {
1652 #ifndef WITH_PYTHON_MODULE
1653                 BLI_argsParse(ba, 3, NULL, NULL);
1654 #endif
1655
1656                 WM_init(C, argc, (const char **)argv);
1657
1658                 /* don't use user preferences temp dir */
1659                 BLI_init_temporary_dir(NULL);
1660         }
1661 #ifdef WITH_PYTHON
1662         /**
1663          * NOTE: the U.pythondir string is NULL until WM_init() is executed,
1664          * so we provide the BPY_ function below to append the user defined
1665          * python-dir to Python's sys.path at this point.  Simply putting
1666          * WM_init() before #BPY_python_start() crashes Blender at startup.
1667          */
1668
1669         /* TODO - U.pythondir */
1670 #else
1671         printf("\n* WARNING * - Blender compiled without Python!\nthis is not intended for typical usage\n\n");
1672 #endif
1673         
1674         CTX_py_init_set(C, 1);
1675         WM_keymap_init(C);
1676
1677 #ifdef WITH_FREESTYLE
1678         /* initialize Freestyle */
1679         FRS_initialize();
1680         FRS_set_context(C);
1681 #endif
1682
1683         /* OK we are ready for it */
1684 #ifndef WITH_PYTHON_MODULE
1685         BLI_argsParse(ba, 4, load_file, C);
1686         
1687         if (G.background == 0) {
1688                 if (!G.file_loaded)
1689                         if (U.uiflag2 & USER_KEEP_SESSION)
1690                                 WM_recover_last_session(C, NULL);
1691         }
1692
1693 #endif
1694
1695 #ifndef WITH_PYTHON_MODULE
1696         BLI_argsFree(ba);
1697 #endif
1698
1699 #ifdef WIN32
1700         while (argci) {
1701                 free(argv[--argci]);
1702         }
1703         free(argv);
1704         argv = NULL;
1705 #endif
1706
1707 #ifdef WITH_PYTHON_MODULE
1708         return 0; /* keep blender in background mode running */
1709 #endif
1710
1711         if (G.background) {
1712                 /* actually incorrect, but works for now (ton) */
1713                 WM_exit(C);
1714         }
1715         else {
1716                 if (G.fileflags & G_FILE_AUTOPLAY) {
1717                         if (G.f & G_SCRIPT_AUTOEXEC) {
1718                                 if (WM_init_game(C)) {
1719                                         return 0;
1720                                 }
1721                         }
1722                         else {
1723                                 if (!(G.f & G_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
1724                                         G.f |= G_SCRIPT_AUTOEXEC_FAIL;
1725                                         BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Game AutoStart");
1726                                 }
1727                         }
1728                 }
1729
1730                 if (!G.file_loaded) {
1731                         WM_init_splash(C);
1732                 }
1733         }
1734
1735         WM_main(C);
1736
1737         return 0;
1738 } /* end of int main(argc, argv)        */
1739
1740 #ifdef WITH_PYTHON_MODULE
1741 void main_python_exit(void)
1742 {
1743         WM_exit((bContext *)evil_C);
1744         evil_C = NULL;
1745 }
1746 #endif
1747
1748 static void mem_error_cb(const char *errorStr)
1749 {
1750         fputs(errorStr, stderr);
1751         fflush(stderr);
1752 }
1753
1754 static void setCallbacks(void)
1755 {
1756         /* Error output from the alloc routines: */
1757         MEM_set_error_callback(mem_error_cb);
1758 }