* Enable compile and link flags to build info also on Windows and in SCons.
[blender-staging.git] / source / blender / python / intern / bpy_app.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * Contributor(s): Campbell Barton
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 #include "bpy_app.h"
26
27 #include "BLI_path_util.h"
28
29 #include "BKE_utildefines.h"
30 #include "BKE_blender.h"
31 #include "BKE_global.h"
32 #include "structseq.h"
33
34 #include "../generic/py_capi_utils.h"
35
36 #ifdef BUILD_DATE
37 extern char build_date[];
38 extern char build_time[];
39 extern char build_rev[];
40 extern char build_platform[];
41 extern char build_type[];
42 extern char build_cflags[];
43 extern char build_cxxflags[];
44 extern char build_linkflags[];
45 extern char build_system[];
46 #endif
47
48 static PyTypeObject BlenderAppType;
49
50 static PyStructSequence_Field app_info_fields[] = {
51         {"version", "The Blender version as a tuple of 3 numbers. eg. (2, 50, 11)"},
52         {"version_string", "The Blender version formatted as a string"},
53         {"binary_path", "The location of blenders executable, useful for utilities that spawn new instances"},
54         {"background", "Boolean, True when blender is running without a user interface (started with -b)"},
55
56         /* buildinfo */
57         {"build_date", "The date this blender instance was built"},
58         {"build_time", "The time this blender instance was built"},
59         {"build_revision", "The subversion revision this blender instance was built with"},
60         {"build_platform", "The platform this blender instance was built for"},
61         {"build_type", "The type of build (Release, Debug)"},
62         {"build_cflags", ""},
63         {"build_cxxflags", ""},
64         {"build_linkflags", ""},
65         {"build_system", ""},
66         {0}
67 };
68
69 static PyStructSequence_Desc app_info_desc = {
70         "bpy.app",     /* name */
71         "This module contains application values that remain unchanged during runtime.",    /* doc */
72         app_info_fields,    /* fields */
73         (sizeof(app_info_fields)/sizeof(PyStructSequence_Field)) - 1
74 };
75
76 static PyObject *make_app_info(void)
77 {
78         extern char bprogname[]; /* argv[0] from creator.c */
79
80         PyObject *app_info;
81         int pos = 0;
82
83         app_info = PyStructSequence_New(&BlenderAppType);
84         if (app_info == NULL) {
85                 return NULL;
86         }
87
88 #define SetIntItem(flag) \
89         PyStructSequence_SET_ITEM(app_info, pos++, PyLong_FromLong(flag))
90 #define SetStrItem(str) \
91         PyStructSequence_SET_ITEM(app_info, pos++, PyUnicode_FromString(str))
92 #define SetObjItem(obj) \
93         PyStructSequence_SET_ITEM(app_info, pos++, obj)
94
95         SetObjItem(Py_BuildValue("(iii)", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION));
96         SetObjItem(PyUnicode_FromFormat("%d.%02d (sub %d)", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION));
97         SetStrItem(bprogname);
98         SetObjItem(PyBool_FromLong(G.background));
99
100         /* build info */
101 #ifdef BUILD_DATE
102         SetStrItem(build_date);
103         SetStrItem(build_time);
104         SetStrItem(build_rev);
105         SetStrItem(build_platform);
106         SetStrItem(build_type);
107         SetStrItem(build_cflags);
108         SetStrItem(build_cxxflags);
109         SetStrItem(build_linkflags);
110         SetStrItem(build_system);
111 #else
112         SetStrItem("Unknown");
113         SetStrItem("Unknown");
114         SetStrItem("Unknown");
115         SetStrItem("Unknown");
116         SetStrItem("Unknown");
117         SetStrItem("Unknown");
118         SetStrItem("Unknown");
119         SetStrItem("Unknown");
120         SetStrItem("Unknown");
121 #endif
122
123 #undef SetIntItem
124 #undef SetStrItem
125 #undef SetObjItem
126
127         if (PyErr_Occurred()) {
128                 Py_CLEAR(app_info);
129                 return NULL;
130         }
131         return app_info;
132 }
133
134 /* a few getsets because it makes sense for them to be in bpy.app even though
135  * they are not static */
136 static PyObject *bpy_app_debug_get(PyObject *UNUSED(self), void *UNUSED(closure))
137 {
138         return PyBool_FromLong(G.f & G_DEBUG);
139 }
140
141 static int bpy_app_debug_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure))
142 {
143         int param= PyObject_IsTrue(value);
144
145         if(param < 0) {
146                 PyErr_SetString(PyExc_TypeError, "bpy.app.debug can only be True/False");
147                 return -1;
148         }
149         
150         if(param)       G.f |=  G_DEBUG;
151         else            G.f &= ~G_DEBUG;
152         
153         return 0;
154 }
155
156 static PyObject *bpy_app_tempdir_get(PyObject *UNUSED(self), void *UNUSED(closure))
157 {
158         extern char btempdir[];
159         return PyC_UnicodeFromByte(btempdir);
160 }
161
162 PyGetSetDef bpy_app_debug_getset= {"debug", bpy_app_debug_get, bpy_app_debug_set, "Boolean, set when blender is running in debug mode (started with -d)", NULL};
163 PyGetSetDef bpy_app_tempdir_getset= {"tempdir", bpy_app_tempdir_get, NULL, "String, the temp directory used by blender (read-only)", NULL};
164
165 static void py_struct_seq_getset_init(void)
166 {
167         /* tricky dynamic members, not to py-spec! */
168         
169         PyDict_SetItemString(BlenderAppType.tp_dict, bpy_app_debug_getset.name, PyDescr_NewGetSet(&BlenderAppType, &bpy_app_debug_getset));
170         PyDict_SetItemString(BlenderAppType.tp_dict, bpy_app_tempdir_getset.name, PyDescr_NewGetSet(&BlenderAppType, &bpy_app_tempdir_getset));
171 }
172 /* end dynamic bpy.app */
173
174
175 PyObject *BPY_app_struct(void)
176 {
177         PyObject *ret;
178         
179         PyStructSequence_InitType(&BlenderAppType, &app_info_desc);
180
181         ret= make_app_info();
182
183         /* prevent user from creating new instances */
184         BlenderAppType.tp_init = NULL;
185         BlenderAppType.tp_new = NULL;
186
187         /* kindof a hack ontop of PyStructSequence */
188         py_struct_seq_getset_init();
189
190         return ret;
191 }
192