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