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