Merge branch 'master' into blender2.8
[blender.git] / source / blender / python / intern / bpy_app.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  * Contributor(s): Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/python/intern/bpy_app.c
24  *  \ingroup pythonintern
25  *
26  * This file defines a 'PyStructSequence' accessed via 'bpy.app', mostly
27  * exposing static applications variables such as version and buildinfo
28  * however some writable variables have been added such as 'debug' and 'tempdir'
29  */
30
31
32 #include <Python.h>
33
34 #include "bpy_app.h"
35
36 #include "bpy_app_alembic.h"
37 #include "bpy_app_ffmpeg.h"
38 #include "bpy_app_ocio.h"
39 #include "bpy_app_oiio.h"
40 #include "bpy_app_opensubdiv.h"
41 #include "bpy_app_openvdb.h"
42 #include "bpy_app_sdl.h"
43 #include "bpy_app_build_options.h"
44
45 #include "bpy_app_translations.h"
46
47 #include "bpy_app_handlers.h"
48 #include "bpy_driver.h"
49
50 /* modules */
51 #include "bpy_app_icons.h"
52
53 #include "BLI_utildefines.h"
54
55 #include "BKE_appdir.h"
56 #include "BKE_blender_version.h"
57 #include "BKE_global.h"
58
59 #include "DNA_ID.h"
60
61 #include "UI_interface_icons.h"
62
63 /* for notifiers */
64 #include "WM_api.h"
65 #include "WM_types.h"
66
67 #include "../generic/py_capi_utils.h"
68 #include "../generic/python_utildefines.h"
69
70 #ifdef BUILD_DATE
71 extern char build_date[];
72 extern char build_time[];
73 extern unsigned long build_commit_timestamp;
74 extern char build_commit_date[];
75 extern char build_commit_time[];
76 extern char build_hash[];
77 extern char build_branch[];
78 extern char build_platform[];
79 extern char build_type[];
80 extern char build_cflags[];
81 extern char build_cxxflags[];
82 extern char build_linkflags[];
83 extern char build_system[];
84 #endif
85
86 static PyTypeObject BlenderAppType;
87
88 static PyStructSequence_Field app_info_fields[] = {
89         {(char *)"version", (char *)"The Blender version as a tuple of 3 numbers. eg. (2, 50, 11)"},
90         {(char *)"version_string", (char *)"The Blender version formatted as a string"},
91         {(char *)"version_char", (char *)"The Blender version character (for minor releases)"},
92         {(char *)"version_cycle", (char *)"The release status of this build alpha/beta/rc/release"},
93         {(char *)"binary_path", (char *)"The location of blenders executable, useful for utilities that spawn new instances"},
94         {(char *)"background", (char *)"Boolean, True when blender is running without a user interface (started with -b)"},
95         {(char *)"factory_startup", (char *)"Boolean, True when blender is running with --factory-startup)"},
96
97         /* buildinfo */
98         {(char *)"build_date", (char *)"The date this blender instance was built"},
99         {(char *)"build_time", (char *)"The time this blender instance was built"},
100         {(char *)"build_commit_timestamp", (char *)"The unix timestamp of commit this blender instance was built"},
101         {(char *)"build_commit_date", (char *)"The date of commit this blender instance was built"},
102         {(char *)"build_commit_time", (char *)"The time of commit this blender instance was built"},
103         {(char *)"build_hash", (char *)"The commit hash this blender instance was built with"},
104         {(char *)"build_branch", (char *)"The branch this blender instance was built from"},
105         {(char *)"build_platform", (char *)"The platform this blender instance was built for"},
106         {(char *)"build_type", (char *)"The type of build (Release, Debug)"},
107         {(char *)"build_cflags", (char *)"C compiler flags"},
108         {(char *)"build_cxxflags", (char *)"C++ compiler flags"},
109         {(char *)"build_linkflags", (char *)"Binary linking flags"},
110         {(char *)"build_system", (char *)"Build system used"},
111
112         /* submodules */
113         {(char *)"alembic", (char *)"Alembic library information backend"},
114         {(char *)"ffmpeg", (char *)"FFmpeg library information backend"},
115         {(char *)"ocio", (char *)"OpenColorIO library information backend"},
116         {(char *)"oiio", (char *)"OpenImageIO library information backend"},
117         {(char *)"opensubdiv", (char *)"OpenSubdiv library information backend"},
118         {(char *)"openvdb", (char *)"OpenVDB library information backend"},
119         {(char *)"sdl", (char *)"SDL library information backend"},
120         {(char *)"build_options", (char *)"A set containing most important enabled optional build features"},
121         {(char *)"handlers", (char *)"Application handler callbacks"},
122         {(char *)"translations", (char *)"Application and addons internationalization API"},
123
124         /* Modules (not struct sequence). */
125         {(char *)"icons", (char *)"Manage custom icons"},
126         {NULL},
127 };
128
129 PyDoc_STRVAR(bpy_app_doc,
130 "This module contains application values that remain unchanged during runtime.\n"
131 "\n"
132 "Submodules:\n"
133 "\n"
134 ".. toctree::\n"
135 "   :maxdepth: 1\n"
136 "\n"
137 "   bpy.app.handlers.rst\n"
138 "   bpy.app.icons.rst\n"
139 "   bpy.app.translations.rst\n"
140 );
141
142 static PyStructSequence_Desc app_info_desc = {
143         (char *)"bpy.app",     /* name */
144         bpy_app_doc,    /* doc */
145         app_info_fields,    /* fields */
146         ARRAY_SIZE(app_info_fields) - 1
147 };
148
149 static PyObject *make_app_info(void)
150 {
151         PyObject *app_info;
152         int pos = 0;
153
154         app_info = PyStructSequence_New(&BlenderAppType);
155         if (app_info == NULL) {
156                 return NULL;
157         }
158 #define SetIntItem(flag) \
159         PyStructSequence_SET_ITEM(app_info, pos++, PyLong_FromLong(flag))
160 #define SetStrItem(str) \
161         PyStructSequence_SET_ITEM(app_info, pos++, PyUnicode_FromString(str))
162 #define SetBytesItem(str) \
163         PyStructSequence_SET_ITEM(app_info, pos++, PyBytes_FromString(str))
164 #define SetObjItem(obj) \
165         PyStructSequence_SET_ITEM(app_info, pos++, obj)
166
167         SetObjItem(PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
168         SetObjItem(PyUnicode_FromFormat("%d.%02d (sub %d)",
169                                         BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
170
171         SetStrItem(STRINGIFY(BLENDER_VERSION_CHAR));
172         SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE));
173         SetStrItem(BKE_appdir_program_path());
174         SetObjItem(PyBool_FromLong(G.background));
175         SetObjItem(PyBool_FromLong(G.factory_startup));
176
177         /* build info, use bytes since we can't assume _any_ encoding:
178          * see patch [#30154] for issue */
179 #ifdef BUILD_DATE
180         SetBytesItem(build_date);
181         SetBytesItem(build_time);
182         SetIntItem(build_commit_timestamp);
183         SetBytesItem(build_commit_date);
184         SetBytesItem(build_commit_time);
185         SetBytesItem(build_hash);
186         SetBytesItem(build_branch);
187         SetBytesItem(build_platform);
188         SetBytesItem(build_type);
189         SetBytesItem(build_cflags);
190         SetBytesItem(build_cxxflags);
191         SetBytesItem(build_linkflags);
192         SetBytesItem(build_system);
193 #else
194         SetBytesItem("Unknown");
195         SetBytesItem("Unknown");
196         SetIntItem(0);
197         SetBytesItem("Unknown");
198         SetBytesItem("Unknown");
199         SetBytesItem("Unknown");
200         SetBytesItem("Unknown");
201         SetBytesItem("Unknown");
202         SetBytesItem("Unknown");
203         SetBytesItem("Unknown");
204         SetBytesItem("Unknown");
205         SetBytesItem("Unknown");
206         SetBytesItem("Unknown");
207 #endif
208
209         SetObjItem(BPY_app_alembic_struct());
210         SetObjItem(BPY_app_ffmpeg_struct());
211         SetObjItem(BPY_app_ocio_struct());
212         SetObjItem(BPY_app_oiio_struct());
213         SetObjItem(BPY_app_opensubdiv_struct());
214         SetObjItem(BPY_app_openvdb_struct());
215         SetObjItem(BPY_app_sdl_struct());
216         SetObjItem(BPY_app_build_options_struct());
217         SetObjItem(BPY_app_handlers_struct());
218         SetObjItem(BPY_app_translations_struct());
219
220         /* modules */
221         SetObjItem(BPY_app_icons_module());
222
223 #undef SetIntItem
224 #undef SetStrItem
225 #undef SetBytesItem
226 #undef SetObjItem
227
228         if (PyErr_Occurred()) {
229                 Py_CLEAR(app_info);
230                 return NULL;
231         }
232         return app_info;
233 }
234
235 /* a few getsets because it makes sense for them to be in bpy.app even though
236  * they are not static */
237
238 PyDoc_STRVAR(bpy_app_debug_doc,
239 "Boolean, for debug info (started with --debug / --debug_* matching this attribute name)"
240 );
241 static PyObject *bpy_app_debug_get(PyObject *UNUSED(self), void *closure)
242 {
243         const int flag = GET_INT_FROM_POINTER(closure);
244         return PyBool_FromLong(G.debug & flag);
245 }
246
247 static int bpy_app_debug_set(PyObject *UNUSED(self), PyObject *value, void *closure)
248 {
249         const int flag = GET_INT_FROM_POINTER(closure);
250         const int param = PyObject_IsTrue(value);
251
252         if (param == -1) {
253                 PyErr_SetString(PyExc_TypeError, "bpy.app.debug can only be True/False");
254                 return -1;
255         }
256
257         if (param)  G.debug |=  flag;
258         else        G.debug &= ~flag;
259
260         return 0;
261 }
262
263 #define BROKEN_BINARY_PATH_PYTHON_HACK
264
265 PyDoc_STRVAR(bpy_app_binary_path_python_doc,
266 "String, the path to the python executable (read-only)"
267 );
268 static PyObject *bpy_app_binary_path_python_get(PyObject *self, void *UNUSED(closure))
269 {
270         /* refcount is held in BlenderAppType.tp_dict */
271         static PyObject *ret = NULL;
272
273         if (ret == NULL) {
274                 /* only run once */
275                 char fullpath[1024];
276                 BKE_appdir_program_python_search(
277                         fullpath, sizeof(fullpath),
278                         PY_MAJOR_VERSION, PY_MINOR_VERSION);
279                 ret = PyC_UnicodeFromByte(fullpath);
280 #ifdef BROKEN_BINARY_PATH_PYTHON_HACK
281                 Py_INCREF(ret);
282                 UNUSED_VARS(self);
283 #else
284                 PyDict_SetItem(BlenderAppType.tp_dict, /* XXX BAAAADDDDDD! self is not a PyDescr at all! it's bpy.app!!! */ PyDescr_NAME(self), ret);
285 #endif
286         }
287         else {
288                 Py_INCREF(ret);
289         }
290
291         return ret;
292 }
293
294 PyDoc_STRVAR(bpy_app_debug_value_doc,
295 "Int, number which can be set to non-zero values for testing purposes"
296 );
297 static PyObject *bpy_app_debug_value_get(PyObject *UNUSED(self), void *UNUSED(closure))
298 {
299         return PyLong_FromLong(G.debug_value);
300 }
301
302 static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure))
303 {
304         int param = PyC_Long_AsI32(value);
305
306         if (param == -1 && PyErr_Occurred()) {
307                 PyErr_SetString(PyExc_TypeError, "bpy.app.debug_value can only be set to a whole number");
308                 return -1;
309         }
310
311         G.debug_value = param;
312
313         WM_main_add_notifier(NC_WINDOW, NULL);
314
315         return 0;
316 }
317
318 static PyObject *bpy_app_global_flag_get(PyObject *UNUSED(self), void *closure)
319 {
320         const int flag = GET_INT_FROM_POINTER(closure);
321         return PyBool_FromLong(G.f & flag);
322 }
323
324 PyDoc_STRVAR(bpy_app_tempdir_doc,
325 "String, the temp directory used by blender (read-only)"
326 );
327 static PyObject *bpy_app_tempdir_get(PyObject *UNUSED(self), void *UNUSED(closure))
328 {
329         return PyC_UnicodeFromByte(BKE_tempdir_session());
330 }
331
332 PyDoc_STRVAR(bpy_app_driver_dict_doc,
333 "Dictionary for drivers namespace, editable in-place, reset on file load (read-only)"
334 );
335 static PyObject *bpy_app_driver_dict_get(PyObject *UNUSED(self), void *UNUSED(closure))
336 {
337         if (bpy_pydriver_Dict == NULL) {
338                 if (bpy_pydriver_create_dict() != 0) {
339                         PyErr_SetString(PyExc_RuntimeError, "bpy.app.driver_namespace failed to create dictionary");
340                         return NULL;
341                 }
342         }
343
344         return Py_INCREF_RET(bpy_pydriver_Dict);
345 }
346
347 PyDoc_STRVAR(bpy_app_preview_render_size_doc,
348 "Reference size for icon/preview renders (read-only)"
349 );
350 static PyObject *bpy_app_preview_render_size_get(PyObject *UNUSED(self), void *closure)
351 {
352         return PyLong_FromLong((long)UI_preview_render_size(GET_INT_FROM_POINTER(closure)));
353 }
354
355 static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void *UNUSED(closure))
356 {
357         return PyC_UnicodeFromByte(G.autoexec_fail);
358 }
359
360
361 static PyGetSetDef bpy_app_getsets[] = {
362         {(char *)"debug",           bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG},
363         {(char *)"debug_ffmpeg",    bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FFMPEG},
364         {(char *)"debug_freestyle", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_FREESTYLE},
365         {(char *)"debug_python",    bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_PYTHON},
366         {(char *)"debug_events",    bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_EVENTS},
367         {(char *)"debug_handlers",  bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_HANDLERS},
368         {(char *)"debug_wm",        bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_WM},
369         {(char *)"debug_depsgraph", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH},
370         {(char *)"debug_depsgraph_build", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_BUILD},
371         {(char *)"debug_depsgraph_eval", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_EVAL},
372         {(char *)"debug_depsgraph_tag", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TAG},
373         {(char *)"debug_depsgraph_time", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_TIME},
374         {(char *)"debug_depsgraph_pretty", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH_PRETTY},
375         {(char *)"debug_simdata",   bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_SIMDATA},
376         {(char *)"debug_gpumem",    bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_GPU_MEM},
377
378         {(char *)"binary_path_python", bpy_app_binary_path_python_get, NULL, (char *)bpy_app_binary_path_python_doc, NULL},
379
380         {(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)bpy_app_debug_value_doc, NULL},
381         {(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL},
382         {(char *)"driver_namespace", bpy_app_driver_dict_get, NULL, (char *)bpy_app_driver_dict_doc, NULL},
383
384         {(char *)"render_icon_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_ICON},
385         {(char *)"render_preview_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_PREVIEW},
386
387         /* security */
388         {(char *)"autoexec_fail", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL},
389         {(char *)"autoexec_fail_quiet", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL_QUIET},
390         {(char *)"autoexec_fail_message", bpy_app_autoexec_fail_message_get, NULL, NULL, NULL},
391         {NULL, NULL, NULL, NULL, NULL}
392 };
393
394 static void py_struct_seq_getset_init(void)
395 {
396         /* tricky dynamic members, not to py-spec! */
397         for (PyGetSetDef *getset = bpy_app_getsets; getset->name; getset++) {
398                 PyObject *item = PyDescr_NewGetSet(&BlenderAppType, getset);
399                 PyDict_SetItem(BlenderAppType.tp_dict, PyDescr_NAME(item), item);
400                 Py_DECREF(item);
401         }
402 }
403 /* end dynamic bpy.app */
404
405
406 PyObject *BPY_app_struct(void)
407 {
408         PyObject *ret;
409
410         PyStructSequence_InitType(&BlenderAppType, &app_info_desc);
411
412         ret = make_app_info();
413
414         /* prevent user from creating new instances */
415         BlenderAppType.tp_init = NULL;
416         BlenderAppType.tp_new = NULL;
417         BlenderAppType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
418
419         /* kindof a hack ontop of PyStructSequence */
420         py_struct_seq_getset_init();
421
422         return ret;
423 }