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