T39690: Modifications to Blender's 'temp dir' system.
[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 #  include <windows.h>
45 #  include "utfconv.h"
46 #endif
47
48 /* for backtrace */
49 #if defined(__linux__) || defined(__APPLE__)
50 #  include <execinfo.h>
51 #elif defined(_MSV_VER)
52 #  include <DbgHelp.h>
53 #endif
54
55 #include <stdlib.h>
56 #include <stddef.h>
57 #include <string.h>
58 #include <errno.h>
59 #include <time.h>
60
61 /* This little block needed for linking to Blender... */
62
63 #include "MEM_guardedalloc.h"
64
65 #ifdef WIN32
66 #  include "BLI_winstuff.h"
67 #endif
68
69 #include "BLI_args.h"
70 #include "BLI_threads.h"
71 #include "BLI_utildefines.h"
72 #include "BLI_callbacks.h"
73 #include "BLI_blenlib.h"
74 #include "BLI_mempool.h"
75 #include "BLI_system.h"
76 #include BLI_SYSTEM_PID_H
77
78 #include "DNA_ID.h"
79 #include "DNA_scene_types.h"
80 #include "DNA_userdef_types.h"
81
82 #include "BKE_blender.h"
83 #include "BKE_brush.h"
84 #include "BKE_context.h"
85 #include "BKE_depsgraph.h" /* for DAG_on_visible_update */
86 #include "BKE_font.h"
87 #include "BKE_global.h"
88 #include "BKE_library.h"
89 #include "BKE_main.h"
90 #include "BKE_material.h"
91 #include "BKE_modifier.h"
92 #include "BKE_scene.h"
93 #include "BKE_node.h"
94 #include "BKE_report.h"
95 #include "BKE_sound.h"
96 #include "BKE_image.h"
97 #include "BKE_particle.h"
98
99 #include "IMB_imbuf.h"  /* for IMB_init */
100
101 #ifdef WITH_PYTHON
102 #include "BPY_extern.h"
103 #endif
104
105 #include "RE_engine.h"
106 #include "RE_pipeline.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 /* from buildinfo.c */
150 #ifdef BUILD_DATE
151 extern char build_date[];
152 extern char build_time[];
153 extern char build_hash[];
154 extern unsigned long build_commit_timestamp;
155
156 /* TODO(sergey): ideally size need to be in sync with buildinfo.c */
157 extern char build_commit_date[16];
158 extern char build_commit_time[16];
159
160 extern char build_branch[];
161 extern char build_platform[];
162 extern char build_type[];
163 extern char build_cflags[];
164 extern char build_cxxflags[];
165 extern char build_linkflags[];
166 extern char build_system[];
167 #endif
168
169 /*      Local Function prototypes */
170 #ifdef WITH_PYTHON_MODULE
171 int  main_python_enter(int argc, const char **argv);
172 void main_python_exit(void);
173 #else
174 static int print_help(int argc, const char **argv, void *data);
175 static int print_version(int argc, const char **argv, void *data);
176 #endif
177
178 /* for the callbacks: */
179 #ifndef WITH_PYTHON_MODULE
180 #define BLEND_VERSION_FMT         "Blender %d.%02d (sub %d)"
181 #define BLEND_VERSION_ARG         BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION
182 /* pass directly to printf */
183 #define BLEND_VERSION_STRING_FMT  BLEND_VERSION_FMT "\n", BLEND_VERSION_ARG
184 #endif
185
186 /* Initialize callbacks for the modules that need them */
187 static void setCallbacks(void); 
188
189 #ifndef WITH_PYTHON_MODULE
190
191 static bool use_crash_handler = true;
192
193 /* set breakpoints here when running in debug mode, useful to catch floating point errors */
194 #if defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE)
195 static void fpe_handler(int UNUSED(sig))
196 {
197         // printf("SIGFPE trapped\n");
198 }
199 #endif
200
201 /* handling ctrl-c event in console */
202 #if !(defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS))
203 static void blender_esc(int sig)
204 {
205         static int count = 0;
206         
207         G.is_break = true;  /* forces render loop to read queue, not sure if its needed */
208         
209         if (sig == 2) {
210                 if (count) {
211                         printf("\nBlender killed\n");
212                         exit(2);
213                 }
214                 printf("\nSent an internal break event. Press ^C again to kill Blender\n");
215                 count++;
216         }
217 }
218 #endif
219
220 static int print_version(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
221 {
222         printf(BLEND_VERSION_STRING_FMT);
223 #ifdef BUILD_DATE
224         printf("\tbuild date: %s\n", build_date);
225         printf("\tbuild time: %s\n", build_time);
226         printf("\tbuild commit date: %s\n", build_commit_date);
227         printf("\tbuild commit time: %s\n", build_commit_time);
228         printf("\tbuild hash: %s\n", build_hash);
229         printf("\tbuild platform: %s\n", build_platform);
230         printf("\tbuild type: %s\n", build_type);
231         printf("\tbuild c flags: %s\n", build_cflags);
232         printf("\tbuild c++ flags: %s\n", build_cxxflags);
233         printf("\tbuild link flags: %s\n", build_linkflags);
234         printf("\tbuild system: %s\n", build_system);
235 #endif
236         exit(0);
237
238         return 0;
239 }
240
241 static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
242 {
243         bArgs *ba = (bArgs *)data;
244
245         printf(BLEND_VERSION_STRING_FMT);
246         printf("Usage: blender [args ...] [file] [args ...]\n\n");
247
248         printf("Render Options:\n");
249         BLI_argsPrintArgDoc(ba, "--background");
250         BLI_argsPrintArgDoc(ba, "--render-anim");
251         BLI_argsPrintArgDoc(ba, "--scene");
252         BLI_argsPrintArgDoc(ba, "--render-frame");
253         BLI_argsPrintArgDoc(ba, "--frame-start");
254         BLI_argsPrintArgDoc(ba, "--frame-end");
255         BLI_argsPrintArgDoc(ba, "--frame-jump");
256         BLI_argsPrintArgDoc(ba, "--render-output");
257         BLI_argsPrintArgDoc(ba, "--engine");
258         BLI_argsPrintArgDoc(ba, "--threads");
259         
260         printf("\n");
261         printf("Format Options:\n");
262         BLI_argsPrintArgDoc(ba, "--render-format");
263         BLI_argsPrintArgDoc(ba, "--use-extension");
264
265         printf("\n");
266         printf("Animation Playback Options:\n");
267         BLI_argsPrintArgDoc(ba, "-a");
268                                 
269         printf("\n");
270         printf("Window Options:\n");
271         BLI_argsPrintArgDoc(ba, "--window-border");
272         BLI_argsPrintArgDoc(ba, "--window-borderless");
273         BLI_argsPrintArgDoc(ba, "--window-geometry");
274         BLI_argsPrintArgDoc(ba, "--start-console");
275         BLI_argsPrintArgDoc(ba, "--no-native-pixels");
276
277
278         printf("\n");
279         printf("Game Engine Specific Options:\n");
280         BLI_argsPrintArgDoc(ba, "-g");
281
282         printf("\n");
283         printf("Python Options:\n");
284         BLI_argsPrintArgDoc(ba, "--enable-autoexec");
285         BLI_argsPrintArgDoc(ba, "--disable-autoexec");
286
287         printf("\n");
288
289         BLI_argsPrintArgDoc(ba, "--python");
290         BLI_argsPrintArgDoc(ba, "--python-text");
291         BLI_argsPrintArgDoc(ba, "--python-console");
292         BLI_argsPrintArgDoc(ba, "--addons");
293
294
295         printf("\n");
296         printf("Debug Options:\n");
297         BLI_argsPrintArgDoc(ba, "--debug");
298         BLI_argsPrintArgDoc(ba, "--debug-value");
299
300         printf("\n");
301         BLI_argsPrintArgDoc(ba, "--debug-events");
302 #ifdef WITH_FFMPEG
303         BLI_argsPrintArgDoc(ba, "--debug-ffmpeg");
304 #endif
305         BLI_argsPrintArgDoc(ba, "--debug-handlers");
306 #ifdef WITH_LIBMV
307         BLI_argsPrintArgDoc(ba, "--debug-libmv");
308 #endif
309         BLI_argsPrintArgDoc(ba, "--debug-memory");
310         BLI_argsPrintArgDoc(ba, "--debug-jobs");
311         BLI_argsPrintArgDoc(ba, "--debug-python");
312         BLI_argsPrintArgDoc(ba, "--debug-depsgraph");
313
314         BLI_argsPrintArgDoc(ba, "--debug-wm");
315         BLI_argsPrintArgDoc(ba, "--debug-all");
316
317         printf("\n");
318         BLI_argsPrintArgDoc(ba, "--debug-fpe");
319         BLI_argsPrintArgDoc(ba, "--disable-crash-handler");
320
321         printf("\n");
322         printf("Misc Options:\n");
323         BLI_argsPrintArgDoc(ba, "--factory-startup");
324         printf("\n");
325         BLI_argsPrintArgDoc(ba, "--env-system-config");
326         BLI_argsPrintArgDoc(ba, "--env-system-datafiles");
327         BLI_argsPrintArgDoc(ba, "--env-system-scripts");
328         BLI_argsPrintArgDoc(ba, "--env-system-python");
329         printf("\n");
330         BLI_argsPrintArgDoc(ba, "-nojoystick");
331         BLI_argsPrintArgDoc(ba, "-noglsl");
332         BLI_argsPrintArgDoc(ba, "-noaudio");
333         BLI_argsPrintArgDoc(ba, "-setaudio");
334
335         printf("\n");
336
337         BLI_argsPrintArgDoc(ba, "--help");
338
339 #ifdef WIN32
340         BLI_argsPrintArgDoc(ba, "-R");
341         BLI_argsPrintArgDoc(ba, "-r");
342 #endif
343         BLI_argsPrintArgDoc(ba, "--version");
344
345         BLI_argsPrintArgDoc(ba, "--");
346
347         printf("Other Options:\n");
348         BLI_argsPrintOtherDoc(ba);
349
350         printf("Argument Parsing:\n");
351         printf("\targuments must be separated by white space. eg\n");
352         printf("\t\t\"blender -ba test.blend\"\n");
353         printf("\t...will ignore the 'a'\n");
354         printf("\t\t\"blender -b test.blend -f8\"\n");
355         printf("\t...will ignore 8 because there is no space between the -f and the frame value\n\n");
356
357         printf("Argument Order:\n");
358         printf("\targuments are executed in the order they are given. eg\n");
359         printf("\t\t\"blender --background test.blend --render-frame 1 --render-output /tmp\"\n");
360         printf("\t...will not render to /tmp because '--render-frame 1' renders before the output path is set\n");
361         printf("\t\t\"blender --background --render-output /tmp test.blend --render-frame 1\"\n");
362         printf("\t...will not render to /tmp because loading the blend file overwrites the render output that was set\n");
363         printf("\t\t\"blender --background test.blend --render-output /tmp --render-frame 1\" works as expected.\n\n");
364
365         printf("\nEnvironment Variables:\n");
366         printf("  $BLENDER_USER_CONFIG      Directory for user configuration files.\n");
367         printf("  $BLENDER_USER_SCRIPTS     Directory for user scripts.\n");
368         printf("  $BLENDER_SYSTEM_SCRIPTS   Directory for system wide scripts.\n");
369         printf("  $BLENDER_USER_DATAFILES   Directory for user data files (icons, translations, ..).\n");
370         printf("  $BLENDER_SYSTEM_DATAFILES Directory for system wide data files.\n");
371         printf("  $BLENDER_SYSTEM_PYTHON    Directory for system python libraries.\n");
372 #ifdef WIN32
373         printf("  $TEMP                     Store temporary files here.\n");
374 #else
375         printf("  $TMP or $TMPDIR           Store temporary files here.\n");
376 #endif
377 #ifdef WITH_SDL
378         printf("  $SDL_AUDIODRIVER          LibSDL audio driver - alsa, esd, dma.\n");
379 #endif
380         printf("  $PYTHONHOME               Path to the python directory, eg. /usr/lib/python.\n\n");
381
382         exit(0);
383
384         return 0;
385 }
386
387 static int end_arguments(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
388 {
389         return -1;
390 }
391
392 static int enable_python(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
393 {
394         G.f |= G_SCRIPT_AUTOEXEC;
395         G.f |= G_SCRIPT_OVERRIDE_PREF;
396         return 0;
397 }
398
399 static int disable_python(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
400 {
401         G.f &= ~G_SCRIPT_AUTOEXEC;
402         G.f |= G_SCRIPT_OVERRIDE_PREF;
403         return 0;
404 }
405
406 static int disable_crash_handler(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
407 {
408         use_crash_handler = false;
409         return 0;
410 }
411
412 static int background_mode(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
413 {
414         G.background = 1;
415         return 0;
416 }
417
418 static int debug_mode(int UNUSED(argc), const char **UNUSED(argv), void *data)
419 {
420         G.debug |= G_DEBUG;  /* std output printf's */
421         printf(BLEND_VERSION_STRING_FMT);
422         MEM_set_memory_debug();
423 #ifdef DEBUG
424         BLI_mempool_set_memory_debug();
425 #endif
426
427 #ifdef WITH_BUILDINFO
428         printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
429 #endif
430
431         BLI_argsPrint(data);
432         return 0;
433 }
434
435 static int debug_mode_generic(int UNUSED(argc), const char **UNUSED(argv), void *data)
436 {
437         G.debug |= GET_INT_FROM_POINTER(data);
438         return 0;
439 }
440
441 #ifdef WITH_LIBMV
442 static int debug_mode_libmv(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
443 {
444         libmv_startDebugLogging();
445
446         return 0;
447 }
448 #endif
449
450 static int debug_mode_memory(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
451 {
452         MEM_set_memory_debug();
453         return 0;
454 }
455
456 static int set_debug_value(int argc, const char **argv, void *UNUSED(data))
457 {
458         if (argc > 1) {
459                 G.debug_value = atoi(argv[1]);
460
461                 return 1;
462         }
463         else {
464                 printf("\nError: you must specify debug value to set.\n");
465                 return 0;
466         }
467 }
468
469 static int set_fpe(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
470 {
471 #if defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE)
472         /* zealous but makes float issues a heck of a lot easier to find!
473          * set breakpoints on fpe_handler */
474         signal(SIGFPE, fpe_handler);
475
476 # if defined(__linux__) && defined(__GNUC__)
477         feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
478 # endif /* defined(__linux__) && defined(__GNUC__) */
479 # if defined(OSX_SSE_FPE)
480         /* OSX uses SSE for floating point by default, so here 
481          * use SSE instructions to throw floating point exceptions */
482         _MM_SET_EXCEPTION_MASK(_MM_MASK_MASK & ~
483                                (_MM_MASK_OVERFLOW | _MM_MASK_INVALID | _MM_MASK_DIV_ZERO));
484 # endif /* OSX_SSE_FPE */
485 # if defined(_WIN32) && defined(_MSC_VER)
486         _controlfp_s(NULL, 0, _MCW_EM); /* enables all fp exceptions */
487         _controlfp_s(NULL, _EM_DENORMAL | _EM_UNDERFLOW | _EM_INEXACT, _MCW_EM); /* hide the ones we don't care about */
488 # endif /* _WIN32 && _MSC_VER */
489 #endif
490
491         return 0;
492 }
493
494 #if defined(__linux__) || defined(__APPLE__)
495
496 /* Unix */
497 static void blender_crash_handler_backtrace(FILE *fp)
498 {
499 #define SIZE 100
500         void *buffer[SIZE];
501         int nptrs;
502         char **strings;
503         int i;
504
505         fputs("\n# backtrace\n", fp);
506
507         /* include a backtrace for good measure */
508         nptrs = backtrace(buffer, SIZE);
509         strings = backtrace_symbols(buffer, nptrs);
510         for (i = 0; i < nptrs; i++) {
511                 fputs(strings[i], fp);
512                 fputc('\n', fp);
513         }
514
515         free(strings);
516 #undef SIZE
517 }
518
519 #elif defined(_MSC_VER)
520
521 static void blender_crash_handler_backtrace(FILE *fp)
522 {
523         (void)fp;
524
525 #if 0
526 #define MAXSYMBOL 256
527         unsigned short  i;
528         void *stack[SIZE];
529         unsigned short nframes;
530         SYMBOL_INFO     *symbolinfo;
531         HANDLE process;
532
533         process = GetCurrentProcess();
534
535         SymInitialize(process, NULL, true);
536
537         nframes = CaptureStackBackTrace(0, SIZE, stack, NULL);
538         symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof( char ), "crash Symbol table");
539         symbolinfo->MaxNameLen = MAXSYMBOL - 1;
540         symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO);
541
542         for (i = 0; i < nframes; i++) {
543                 SymFromAddr(process, ( DWORD64 )( stack[ i ] ), 0, symbolinfo);
544
545                 fprintf(fp, "%u: %s - 0x%0X\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address);
546         }
547
548         MEM_freeN(symbolinfo);
549 #endif
550 }
551
552 #else  /* non msvc/osx/linux */
553
554 static void blender_crash_handler_backtrace(FILE *fp)
555 {
556         (void)fp;
557 }
558
559 #endif
560
561 static void blender_crash_handler(int signum)
562 {
563
564 #if 0
565         {
566                 char fname[FILE_MAX];
567
568                 if (!G.main->name[0]) {
569                         BLI_make_file_string("/", fname, BLI_temp_dir_base(), "crash.blend");
570                 }
571                 else {
572                         BLI_strncpy(fname, G.main->name, sizeof(fname));
573                         BLI_replace_extension(fname, sizeof(fname), ".crash.blend");
574                 }
575
576                 printf("Writing: %s\n", fname);
577                 fflush(stdout);
578
579                 BKE_undo_save_file(fname);
580         }
581 #endif
582
583         FILE *fp;
584         char header[512];
585         wmWindowManager *wm = G.main->wm.first;
586
587         char fname[FILE_MAX];
588
589         if (!G.main->name[0]) {
590                 BLI_join_dirfile(fname, sizeof(fname), BLI_temp_dir_base(), "blender.crash.txt");
591         }
592         else {
593                 BLI_join_dirfile(fname, sizeof(fname), BLI_temp_dir_base(), BLI_path_basename(G.main->name));
594                 BLI_replace_extension(fname, sizeof(fname), ".crash.txt");
595         }
596
597         printf("Writing: %s\n", fname);
598         fflush(stdout);
599
600 #ifndef BUILD_DATE
601         BLI_snprintf(header, sizeof(header), "# " BLEND_VERSION_FMT ", Unknown revision\n", BLEND_VERSION_ARG);
602 #else
603         BLI_snprintf(header, sizeof(header), "# " BLEND_VERSION_FMT ", Commit date: %s %s, Hash %s\n",
604                      BLEND_VERSION_ARG, build_commit_date, build_commit_time, build_hash);
605 #endif
606
607         /* open the crash log */
608         errno = 0;
609         fp = BLI_fopen(fname, "wb");
610         if (fp == NULL) {
611                 fprintf(stderr, "Unable to save '%s': %s\n",
612                         fname, errno ? strerror(errno) : "Unknown error opening file");
613         }
614         else {
615                 if (wm) {
616                         BKE_report_write_file_fp(fp, &wm->reports, header);
617                 }
618
619                 blender_crash_handler_backtrace(fp);
620
621                 fclose(fp);
622         }
623
624         /* Delete content of temp dir! */
625         BLI_temp_dir_session_purge();
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 %d '-t / --threads'.\n", BLENDER_MAX_THREADS);
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;
1255
1256                 BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);
1257
1258                 retval = BKE_read_file(C, filename, NULL);
1259
1260                 /* we successfully loaded a blend file, get sure that
1261                  * pointcache works */
1262                 if (retval != BKE_READ_FILE_FAIL) {
1263                         wmWindowManager *wm = CTX_wm_manager(C);
1264                         Main *bmain = CTX_data_main(C);
1265
1266                         /* special case, 2.4x files */
1267                         if (wm == NULL && BLI_listbase_is_empty(&bmain->wm)) {
1268                                 extern void wm_add_default(bContext *C);
1269
1270                                 /* wm_add_default() needs the screen to be set. */
1271                                 CTX_wm_screen_set(C, bmain->screen.first);
1272                                 wm_add_default(C);
1273                         }
1274
1275                         CTX_wm_manager_set(C, NULL); /* remove wm to force check */
1276                         WM_check(C);
1277                         G.relbase_valid = 1;
1278                         if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm);  /* reset wm */
1279
1280                         /* WM_file_read would call normally */
1281                         ED_editors_init(C);
1282                         DAG_on_visible_update(bmain, true);
1283                         BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C));
1284                 }
1285                 else {
1286                         /* failed to load file, stop processing arguments */
1287                         return -1;
1288                 }
1289
1290                 /* WM_file_read() runs normally but since we're in background mode do here */
1291 #ifdef WITH_PYTHON
1292                 /* run any texts that were loaded in and flagged as modules */
1293                 BPY_python_reset(C);
1294 #endif
1295
1296                 BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
1297
1298                 /* happens for the UI on file reading too (huh? (ton))*/
1299                 // XXX          BKE_reset_undo();
1300                 //                      BKE_write_undo("original");     /* save current state */
1301         }
1302         else {
1303                 /* we are not running in background mode here, but start blender in UI mode with
1304                  * a file - this should do everything a 'load file' does */
1305                 ReportList reports;
1306                 BKE_reports_init(&reports, RPT_PRINT);
1307                 WM_file_autoexec_init(filename);
1308                 WM_file_read(C, filename, &reports);
1309                 BKE_reports_clear(&reports);
1310         }
1311
1312         G.file_loaded = 1;
1313
1314         return 0;
1315 }
1316
1317 static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
1318 {
1319         static char output_doc[] = "<path>"
1320                 "\n\tSet the render path and file name."
1321                 "\n\tUse // at the start of the path to"
1322                 "\n\t\trender relative to the blend file."
1323                 "\n\tThe # characters are replaced by the frame number, and used to define zero padding."
1324                 "\n\t\tani_##_test.png becomes ani_01_test.png"
1325                 "\n\t\ttest-######.png becomes test-000001.png"
1326                 "\n\t\tWhen the filename does not contain #, The suffix #### is added to the filename"
1327                 "\n\tThe frame number will be added at the end of the filename."
1328                 "\n\t\teg: blender -b foobar.blend -o //render_ -F PNG -x 1 -a"
1329                 "\n\t\t//render_ becomes //render_####, writing frames as //render_0001.png//";
1330
1331         static char format_doc[] = "<format>"
1332                 "\n\tSet the render format, Valid options are..."
1333                 "\n\t\tTGA IRIS JPEG MOVIE IRIZ RAWTGA"
1334                 "\n\t\tAVIRAW AVIJPEG PNG BMP FRAMESERVER"
1335                 "\n\t(formats that can be compiled into blender, not available on all systems)"
1336                 "\n\t\tHDR TIFF EXR MULTILAYER MPEG AVICODEC QUICKTIME CINEON DPX DDS";
1337
1338         static char playback_doc[] = "<options> <file(s)>"
1339                 "\n\tPlayback <file(s)>, only operates this way when not running in background."
1340                 "\n\t\t-p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>"
1341                 "\n\t\t-m\t\tRead from disk (Don't buffer)"
1342                 "\n\t\t-f <fps> <fps-base>\t\tSpecify FPS to start with"
1343                 "\n\t\t-j <frame>\tSet frame step to <frame>"
1344                 "\n\t\t-s <frame>\tPlay from <frame>"
1345                 "\n\t\t-e <frame>\tPlay until <frame>";
1346
1347         static char game_doc[] = "Game Engine specific options"
1348                 "\n\t-g fixedtime\t\tRun on 50 hertz without dropping frames"
1349                 "\n\t-g vertexarrays\t\tUse Vertex Arrays for rendering (usually faster)"
1350                 "\n\t-g nomipmap\t\tNo Texture Mipmapping"
1351                 "\n\t-g linearmipmap\t\tLinear Texture Mipmapping instead of Nearest (default)";
1352
1353         static char debug_doc[] = "\n\tTurn debugging on\n"
1354                 "\n\t* Prints every operator call and their arguments"
1355                 "\n\t* Disables mouse grab (to interact with a debugger in some cases)"
1356                 "\n\t* Keeps python sys.stdin rather than setting it to None";
1357
1358         //BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
1359
1360         /* end argument processing after -- */
1361         BLI_argsAdd(ba, -1, "--", NULL, "\n\tEnds option processing, following arguments passed unchanged. Access via python's sys.argv", end_arguments, NULL);
1362
1363         /* first pass: background mode, disable python and commands that exit after usage */
1364         BLI_argsAdd(ba, 1, "-h", "--help", "\n\tPrint this help text and exit", print_help, ba);
1365         /* Windows only */
1366         BLI_argsAdd(ba, 1, "/?", NULL, "\n\tPrint this help text and exit (windows only)", print_help, ba);
1367
1368         BLI_argsAdd(ba, 1, "-v", "--version", "\n\tPrint Blender version and exit", print_version, NULL);
1369         
1370         /* only to give help message */
1371 #ifndef WITH_PYTHON_SECURITY /* default */
1372 #  define   PY_ENABLE_AUTO ", (default)"
1373 #  define   PY_DISABLE_AUTO ""
1374 #else
1375 #  define   PY_ENABLE_AUTO ""
1376 #  define   PY_DISABLE_AUTO ", (compiled as non-standard default)"
1377 #endif
1378
1379         BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", "\n\tEnable automatic python script execution" PY_ENABLE_AUTO, enable_python, NULL);
1380         BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", "\n\tDisable automatic python script execution (pydrivers & startup scripts)" PY_DISABLE_AUTO, disable_python, NULL);
1381
1382         BLI_argsAdd(ba, 1, NULL, "--disable-crash-handler", "\n\tDisable the crash handler", disable_crash_handler, NULL);
1383
1384 #undef PY_ENABLE_AUTO
1385 #undef PY_DISABLE_AUTO
1386         
1387         BLI_argsAdd(ba, 1, "-b", "--background", "\n\tRun in background (often used for UI-less rendering)", background_mode, NULL);
1388
1389         BLI_argsAdd(ba, 1, "-a", NULL, playback_doc, playback_mode, NULL);
1390
1391         BLI_argsAdd(ba, 1, "-d", "--debug", debug_doc, debug_mode, ba);
1392
1393 #ifdef WITH_FFMPEG
1394         BLI_argsAdd(ba, 1, NULL, "--debug-ffmpeg", "\n\tEnable debug messages from FFmpeg library", debug_mode_generic, (void *)G_DEBUG_FFMPEG);
1395 #endif
1396
1397 #ifdef WITH_FREESTYLE
1398         BLI_argsAdd(ba, 1, NULL, "--debug-freestyle", "\n\tEnable debug/profiling messages from Freestyle rendering", debug_mode_generic, (void *)G_DEBUG_FREESTYLE);
1399 #endif
1400
1401         BLI_argsAdd(ba, 1, NULL, "--debug-python", "\n\tEnable debug messages for python", debug_mode_generic, (void *)G_DEBUG_PYTHON);
1402         BLI_argsAdd(ba, 1, NULL, "--debug-events", "\n\tEnable debug messages for the event system", debug_mode_generic, (void *)G_DEBUG_EVENTS);
1403         BLI_argsAdd(ba, 1, NULL, "--debug-handlers", "\n\tEnable debug messages for event handling", debug_mode_generic, (void *)G_DEBUG_HANDLERS);
1404         BLI_argsAdd(ba, 1, NULL, "--debug-wm",     "\n\tEnable debug messages for the window manager", debug_mode_generic, (void *)G_DEBUG_WM);
1405         BLI_argsAdd(ba, 1, NULL, "--debug-all",    "\n\tEnable all debug messages (excludes libmv)", debug_mode_generic, (void *)G_DEBUG_ALL);
1406
1407         BLI_argsAdd(ba, 1, NULL, "--debug-fpe", "\n\tEnable floating point exceptions", set_fpe, NULL);
1408
1409 #ifdef WITH_LIBMV
1410         BLI_argsAdd(ba, 1, NULL, "--debug-libmv", "\n\tEnable debug messages from libmv library", debug_mode_libmv, NULL);
1411 #endif
1412         BLI_argsAdd(ba, 1, NULL, "--debug-memory", "\n\tEnable fully guarded memory allocation and debugging", debug_mode_memory, NULL);
1413
1414         BLI_argsAdd(ba, 1, NULL, "--debug-value", "<value>\n\tSet debug value of <value> on startup\n", set_debug_value, NULL);
1415         BLI_argsAdd(ba, 1, NULL, "--debug-jobs",  "\n\tEnable time profiling for background jobs.", debug_mode_generic, (void *)G_DEBUG_JOBS);
1416         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph", "\n\tEnable debug messages from dependency graph", debug_mode_generic, (void *)G_DEBUG_DEPSGRAPH);
1417
1418         BLI_argsAdd(ba, 1, NULL, "--verbose", "<verbose>\n\tSet logging verbosity level.", set_verbosity, NULL);
1419
1420         BLI_argsAdd(ba, 1, NULL, "--factory-startup", "\n\tSkip reading the "STRINGIFY (BLENDER_STARTUP_FILE)" in the users home directory", set_factory_startup, NULL);
1421
1422         /* TODO, add user env vars? */
1423         BLI_argsAdd(ba, 1, NULL, "--env-system-datafiles",  "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_DATAFILES)" environment variable", set_env, NULL);
1424         BLI_argsAdd(ba, 1, NULL, "--env-system-scripts",    "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_SCRIPTS)" environment variable", set_env, NULL);
1425         BLI_argsAdd(ba, 1, NULL, "--env-system-python",     "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_PYTHON)" environment variable", set_env, NULL);
1426
1427         /* second pass: custom window stuff */
1428         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);
1429         BLI_argsAdd(ba, 2, "-w", "--window-border", "\n\tForce opening with borders (default)", with_borders, NULL);
1430         BLI_argsAdd(ba, 2, "-W", "--window-borderless", "\n\tForce opening without borders", without_borders, NULL);
1431         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);
1432         BLI_argsAdd(ba, 2, "-R", NULL, "\n\tRegister .blend extension, then exit (Windows only)", register_extension, NULL);
1433         BLI_argsAdd(ba, 2, "-r", NULL, "\n\tSilently register .blend extension, then exit (Windows only)", register_extension, ba);
1434         BLI_argsAdd(ba, 2, NULL, "--no-native-pixels", "\n\tDo not use native pixel size, for high resolution displays (MacBook 'Retina')", native_pixels, ba);
1435
1436         /* third pass: disabling things and forcing settings */
1437         BLI_argsAddCase(ba, 3, "-nojoystick", 1, NULL, 0, "\n\tDisable joystick support", no_joystick, syshandle);
1438         BLI_argsAddCase(ba, 3, "-noglsl", 1, NULL, 0, "\n\tDisable GLSL shading", no_glsl, NULL);
1439         BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, "\n\tForce sound system to None", no_audio, NULL);
1440         BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, "\n\tForce sound system to a specific device\n\tNULL SDL OPENAL JACK", set_audio, NULL);
1441
1442         /* fourth pass: processing arguments */
1443         BLI_argsAdd(ba, 4, "-g", NULL, game_doc, set_ge_parameters, syshandle);
1444         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);
1445         BLI_argsAdd(ba, 4, "-a", "--render-anim", "\n\tRender frames from start to end (inclusive)", render_animation, C);
1446         BLI_argsAdd(ba, 4, "-S", "--scene", "<name>\n\tSet the active scene <name> for rendering", set_scene, C);
1447         BLI_argsAdd(ba, 4, "-s", "--frame-start", "<frame>\n\tSet start to frame <frame> (use before the -a argument)", set_start_frame, C);
1448         BLI_argsAdd(ba, 4, "-e", "--frame-end", "<frame>\n\tSet end to frame <frame> (use before the -a argument)", set_end_frame, C);
1449         BLI_argsAdd(ba, 4, "-j", "--frame-jump", "<frames>\n\tSet number of frames to step forward after each rendered frame", set_skip_frame, C);
1450         BLI_argsAdd(ba, 4, "-P", "--python", "<filename>\n\tRun the given Python script file", run_python_file, C);
1451         BLI_argsAdd(ba, 4, NULL, "--python-text", "<name>\n\tRun the given Python script text block", run_python_text, C);
1452         BLI_argsAdd(ba, 4, NULL, "--python-console", "\n\tRun blender with an interactive console", run_python_console, C);
1453         BLI_argsAdd(ba, 4, NULL, "--addons", "\n\tComma separated list of addons (no spaces)", set_addons, C);
1454
1455         BLI_argsAdd(ba, 4, "-o", "--render-output", output_doc, set_output, C);
1456         BLI_argsAdd(ba, 4, "-E", "--engine", "<engine>\n\tSpecify the render engine\n\tuse -E help to list available engines", set_engine, C);
1457
1458         BLI_argsAdd(ba, 4, "-F", "--render-format", format_doc, set_image_type, C);
1459         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);
1460         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);
1461
1462 }
1463 #endif /* WITH_PYTHON_MODULE */
1464
1465 #ifdef WITH_PYTHON_MODULE
1466 /* allow python module to call main */
1467 #  define main main_python_enter
1468 static void *evil_C = NULL;
1469
1470 #  ifdef __APPLE__
1471      /* environ is not available in mac shared libraries */
1472 #    include <crt_externs.h>
1473 char **environ = NULL;
1474 #  endif
1475 #endif
1476
1477 /**
1478  * Blender's main function responsabilities are:
1479  * - setup subsystems.
1480  * - handle arguments.
1481  * - run WM_main() event loop,
1482  *   or exit when running in background mode.
1483  */
1484 int main(
1485        int argc,
1486 #ifdef WIN32
1487         const char **UNUSED(argv_c)
1488 #else
1489         const char **argv
1490 #endif
1491          )
1492 {
1493         bContext *C;
1494         SYS_SystemHandle syshandle;
1495
1496 #ifndef WITH_PYTHON_MODULE
1497         bArgs *ba;
1498 #endif
1499
1500 #ifdef WIN32 /* Win32 Unicode Args */
1501         /* NOTE: cannot use guardedalloc malloc here, as it's not yet initialized
1502          *       (it depends on the args passed in, which is what we're getting here!)
1503          */
1504         wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
1505         char **argv = malloc(argc * sizeof(char *));
1506         int argci = 0;
1507         
1508         for (argci = 0; argci < argc; argci++) {
1509                 argv[argci] = alloc_utf_8_from_16(argv_16[argci], 0);
1510         }
1511         
1512         LocalFree(argv_16);
1513 #endif
1514
1515         /* NOTE: Special exception for guarded allocator type switch:
1516          *       we need to perform switch from lock-free to fully
1517          *       guarded allocator before any allocation happened.
1518          */
1519         {
1520                 int i;
1521                 for (i = 0; i < argc; i++) {
1522                         if (STREQ(argv[i], "--debug") || STREQ(argv[i], "-d") ||
1523                             STREQ(argv[i], "--debug-memory"))
1524                         {
1525                                 printf("Switching to fully guarded memory allocator.\n");
1526                                 MEM_use_guarded_allocator();
1527                                 break;
1528                         }
1529                         else if (STREQ(argv[i], "--")) {
1530                                 break;
1531                         }
1532                 }
1533         }
1534
1535 #ifdef BUILD_DATE
1536         {
1537                 time_t temp_time = build_commit_timestamp;
1538                 struct tm *tm = gmtime(&temp_time);
1539                 if (LIKELY(tm)) {
1540                         strftime(build_commit_date, sizeof(build_commit_date), "%Y-%m-%d", tm);
1541                         strftime(build_commit_time, sizeof(build_commit_time), "%H:%M", tm);
1542                 }
1543                 else {
1544                         const char *unknown = "date-unknown";
1545                         BLI_strncpy(build_commit_date, unknown, sizeof(build_commit_date));
1546                         BLI_strncpy(build_commit_time, unknown, sizeof(build_commit_time));
1547                 }
1548         }
1549 #endif
1550
1551         C = CTX_create();
1552
1553 #ifdef WITH_PYTHON_MODULE
1554 #ifdef __APPLE__
1555         environ = *_NSGetEnviron();
1556 #endif
1557
1558 #undef main
1559         evil_C = C;
1560 #endif
1561
1562
1563
1564 #ifdef WITH_BINRELOC
1565         br_init(NULL);
1566 #endif
1567
1568 #ifdef WITH_LIBMV
1569         libmv_initLogging(argv[0]);
1570 #endif
1571
1572         setCallbacks();
1573 #if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE)
1574         /* patch to ignore argument finder gives us (pid?) */
1575         if (argc == 2 && strncmp(argv[1], "-psn_", 5) == 0) {
1576                 extern int GHOST_HACK_getFirstFile(char buf[]);
1577                 static char firstfilebuf[512];
1578
1579                 argc = 1;
1580
1581                 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
1582                         argc = 2;
1583                         argv[1] = firstfilebuf;
1584                 }
1585         }
1586
1587 #endif
1588
1589 #ifdef __FreeBSD__
1590         fpsetmask(0);
1591 #endif
1592
1593         /* initialize path to executable */
1594         BLI_init_program_path(argv[0]);
1595
1596         BLI_threadapi_init();
1597
1598         initglobals();  /* blender.c */
1599
1600         IMB_init();
1601         BKE_images_init();
1602         BKE_modifier_init();
1603         DAG_init();
1604
1605         BKE_brush_system_init();
1606
1607         BLI_callback_global_init();
1608
1609 #ifdef WITH_GAMEENGINE
1610         syshandle = SYS_GetSystem();
1611 #else
1612         syshandle = 0;
1613 #endif
1614
1615         /* first test for background */
1616 #ifndef WITH_PYTHON_MODULE
1617         ba = BLI_argsInit(argc, (const char **)argv); /* skip binary path */
1618         setupArguments(C, ba, &syshandle);
1619
1620         BLI_argsParse(ba, 1, NULL, NULL);
1621
1622         if (use_crash_handler) {
1623                 /* after parsing args */
1624                 signal(SIGSEGV, blender_crash_handler);
1625         }
1626 #else
1627         G.factory_startup = true;  /* using preferences or user startup makes no sense for py-as-module */
1628         (void)syshandle;
1629 #endif
1630
1631 #ifdef WITH_FFMPEG
1632         IMB_ffmpeg_init();
1633 #endif
1634
1635         /* after level 1 args, this is so playanim skips RNA init */
1636         RNA_init();
1637
1638         RE_engines_init();
1639         init_nodesystem();
1640         psys_init_rng();
1641         /* end second init */
1642
1643
1644 #if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
1645         G.background = true; /* python module mode ALWAYS runs in background mode (for now) */
1646 #else
1647         /* for all platforms, even windos has it! */
1648         if (G.background) {
1649                 signal(SIGINT, blender_esc);  /* ctrl c out bg render */
1650         }
1651 #endif
1652
1653         /* background render uses this font too */
1654         BKE_vfont_builtin_register(datatoc_bfont_pfb, datatoc_bfont_pfb_size);
1655
1656         /* Initialize ffmpeg if built in, also needed for bg mode if videos are
1657          * rendered via ffmpeg */
1658         sound_init_once();
1659         
1660         init_def_material();
1661
1662         if (G.background == 0) {
1663 #ifndef WITH_PYTHON_MODULE
1664                 BLI_argsParse(ba, 2, NULL, NULL);
1665                 BLI_argsParse(ba, 3, NULL, NULL);
1666 #endif
1667                 WM_init(C, argc, (const char **)argv);
1668
1669                 /* this is properly initialized with user defs, but this is default */
1670                 /* call after loading the startup.blend so we can read U.tempdir */
1671                 BLI_temp_dir_init(U.tempdir);
1672         }
1673         else {
1674 #ifndef WITH_PYTHON_MODULE
1675                 BLI_argsParse(ba, 3, NULL, NULL);
1676 #endif
1677
1678                 WM_init(C, argc, (const char **)argv);
1679
1680                 /* don't use user preferences temp dir */
1681                 BLI_temp_dir_init(NULL);
1682         }
1683 #ifdef WITH_PYTHON
1684         /**
1685          * NOTE: the U.pythondir string is NULL until WM_init() is executed,
1686          * so we provide the BPY_ function below to append the user defined
1687          * python-dir to Python's sys.path at this point.  Simply putting
1688          * WM_init() before #BPY_python_start() crashes Blender at startup.
1689          */
1690
1691         /* TODO - U.pythondir */
1692 #else
1693         printf("\n* WARNING * - Blender compiled without Python!\nthis is not intended for typical usage\n\n");
1694 #endif
1695         
1696         CTX_py_init_set(C, 1);
1697         WM_keymap_init(C);
1698
1699 #ifdef WITH_FREESTYLE
1700         /* initialize Freestyle */
1701         FRS_initialize();
1702         FRS_set_context(C);
1703 #endif
1704
1705         /* OK we are ready for it */
1706 #ifndef WITH_PYTHON_MODULE
1707         BLI_argsParse(ba, 4, load_file, C);
1708         
1709         if (G.background == 0) {
1710                 if (!G.file_loaded)
1711                         if (U.uiflag2 & USER_KEEP_SESSION)
1712                                 WM_recover_last_session(C, NULL);
1713         }
1714
1715 #endif
1716
1717 #ifndef WITH_PYTHON_MODULE
1718         BLI_argsFree(ba);
1719 #endif
1720
1721 #ifdef WIN32
1722         while (argci) {
1723                 free(argv[--argci]);
1724         }
1725         free(argv);
1726         argv = NULL;
1727 #endif
1728
1729 #ifdef WITH_PYTHON_MODULE
1730         return 0; /* keep blender in background mode running */
1731 #endif
1732
1733         if (G.background) {
1734                 /* actually incorrect, but works for now (ton) */
1735                 WM_exit(C);
1736         }
1737         else {
1738                 if (G.fileflags & G_FILE_AUTOPLAY) {
1739                         if (G.f & G_SCRIPT_AUTOEXEC) {
1740                                 if (WM_init_game(C)) {
1741                                         return 0;
1742                                 }
1743                         }
1744                         else {
1745                                 if (!(G.f & G_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
1746                                         G.f |= G_SCRIPT_AUTOEXEC_FAIL;
1747                                         BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Game AutoStart");
1748                                 }
1749                         }
1750                 }
1751
1752                 if (!G.file_loaded) {
1753                         WM_init_splash(C);
1754                 }
1755         }
1756
1757         WM_main(C);
1758
1759         return 0;
1760 } /* end of int main(argc, argv)        */
1761
1762 #ifdef WITH_PYTHON_MODULE
1763 void main_python_exit(void)
1764 {
1765         WM_exit_ext((bContext *)evil_C, true);
1766         evil_C = NULL;
1767 }
1768 #endif
1769
1770 static void mem_error_cb(const char *errorStr)
1771 {
1772         fputs(errorStr, stderr);
1773         fflush(stderr);
1774 }
1775
1776 static void setCallbacks(void)
1777 {
1778         /* Error output from the alloc routines: */
1779         MEM_set_error_callback(mem_error_cb);
1780 }