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