fazekasgy@37
|
1 /*
|
fazekasgy@37
|
2
|
fazekasgy@37
|
3 * Vampy : This plugin is a wrapper around the Vamp plugin API.
|
fazekasgy@37
|
4 * It allows for writing Vamp plugins in Python.
|
fazekasgy@37
|
5
|
fazekasgy@37
|
6 * Centre for Digital Music, Queen Mary University of London.
|
fazekasgy@37
|
7 * Copyright (C) 2008-2009 Gyorgy Fazekas, QMUL. (See Vamp sources
|
fazekasgy@37
|
8 * for licence information.)
|
fazekasgy@37
|
9
|
fazekasgy@37
|
10 */
|
fazekasgy@37
|
11
|
fazekasgy@37
|
12 #include <Python.h>
|
fazekasgy@37
|
13
|
fazekasgy@37
|
14 #ifdef HAVE_NUMPY
|
fazekasgy@37
|
15 #define PY_ARRAY_UNIQUE_SYMBOL VAMPY_ARRAY_API
|
fazekasgy@37
|
16 #define NO_IMPORT_ARRAY
|
fazekasgy@37
|
17 #include "numpy/arrayobject.h"
|
fazekasgy@37
|
18 #endif
|
fazekasgy@37
|
19
|
fazekasgy@37
|
20 #include "PyTypeInterface.h"
|
fazekasgy@37
|
21 #include "PyRealTime.h"
|
fazekasgy@37
|
22 #include "PyExtensionModule.h"
|
fazekasgy@37
|
23 #include <math.h>
|
fazekasgy@37
|
24 #include <float.h>
|
fazekasgy@37
|
25 #include <limits.h>
|
fazekasgy@37
|
26 #ifndef SIZE_T_MAX
|
fazekasgy@37
|
27 #define SIZE_T_MAX ((size_t) -1)
|
fazekasgy@37
|
28 #endif
|
fazekasgy@37
|
29
|
fazekasgy@37
|
30 using std::string;
|
fazekasgy@37
|
31 using std::vector;
|
fazekasgy@37
|
32 using std::cerr;
|
fazekasgy@37
|
33 using std::endl;
|
fazekasgy@37
|
34 using std::map;
|
fazekasgy@37
|
35
|
fazekasgy@37
|
36 static std::map<std::string, o::eOutDescriptors> outKeys;
|
fazekasgy@37
|
37 static std::map<std::string, p::eParmDescriptors> parmKeys;
|
fazekasgy@37
|
38 static std::map<std::string, eSampleTypes> sampleKeys;
|
fazekasgy@37
|
39 static std::map<std::string, eFeatureFields> ffKeys;
|
fazekasgy@37
|
40 static bool isMapInitialised = false;
|
fazekasgy@37
|
41
|
fazekasgy@37
|
42 /* Note: NO FUNCTION IN THIS CLASS SHOULD ALTER REFERENCE COUNTS
|
fazekasgy@37
|
43 (EXCEPT FOR TEMPORARY PYTHON OBJECTS)! */
|
fazekasgy@37
|
44
|
fazekasgy@37
|
45 PyTypeInterface::PyTypeInterface() :
|
fazekasgy@37
|
46 m_strict(false),
|
fazekasgy@37
|
47 m_error(false),
|
fazekasgy@51
|
48 m_numpyInstalled(false),
|
fazekasgy@37
|
49 error(m_error) // const public reference for easy access
|
fazekasgy@37
|
50 {
|
fazekasgy@37
|
51 }
|
fazekasgy@37
|
52
|
fazekasgy@37
|
53 PyTypeInterface::~PyTypeInterface()
|
fazekasgy@37
|
54 {
|
fazekasgy@37
|
55 }
|
fazekasgy@37
|
56
|
fazekasgy@37
|
57 /// floating point numbers (TODO: check numpy.float128)
|
fazekasgy@37
|
58 float
|
fazekasgy@37
|
59 PyTypeInterface::PyValue_To_Float(PyObject* pyValue) const
|
fazekasgy@37
|
60 {
|
fazekasgy@37
|
61 // convert float
|
fazekasgy@37
|
62 if (pyValue && PyFloat_Check(pyValue))
|
fazekasgy@37
|
63 //TODO: check for limits here (same on most systems)
|
fazekasgy@37
|
64 return (float) PyFloat_AS_DOUBLE(pyValue);
|
fazekasgy@37
|
65
|
fazekasgy@37
|
66 if (pyValue == NULL)
|
fazekasgy@37
|
67 {
|
fazekasgy@51
|
68 setValueError("Error while converting object " + PyValue_Get_TypeName(pyValue) + " to float. ",m_strict);
|
fazekasgy@37
|
69 return 0.0;
|
fazekasgy@37
|
70 }
|
fazekasgy@37
|
71
|
fazekasgy@37
|
72 // in strict mode we will not try harder
|
fazekasgy@37
|
73 if (m_strict) {
|
fazekasgy@51
|
74 setValueError("Strict conversion error: object" + PyValue_Get_TypeName(pyValue) +" is not float.",m_strict);
|
fazekasgy@37
|
75 return 0.0;
|
fazekasgy@37
|
76 }
|
fazekasgy@37
|
77
|
fazekasgy@37
|
78 // convert other objects supporting the number protocol
|
fazekasgy@37
|
79 if (PyNumber_Check(pyValue))
|
fazekasgy@37
|
80 {
|
fazekasgy@37
|
81 PyObject* pyFloat = PyNumber_Float(pyValue); // new ref
|
fazekasgy@37
|
82 if (!pyFloat)
|
fazekasgy@37
|
83 {
|
fazekasgy@37
|
84 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
85 setValueError("Error while converting " + PyValue_Get_TypeName(pyValue) + " object to float.",m_strict);
|
fazekasgy@37
|
86 return 0.0;
|
fazekasgy@37
|
87 }
|
fazekasgy@37
|
88 float rValue = (float) PyFloat_AS_DOUBLE(pyFloat);
|
fazekasgy@37
|
89 Py_DECREF(pyFloat);
|
fazekasgy@37
|
90 return rValue;
|
fazekasgy@37
|
91 }
|
fazekasgy@37
|
92 /*
|
fazekasgy@37
|
93 // convert other objects supporting the number protocol
|
fazekasgy@37
|
94 if (PyNumber_Check(pyValue))
|
fazekasgy@37
|
95 {
|
fazekasgy@37
|
96 // PEP353: Py_ssize_t is size_t but signed !
|
fazekasgy@37
|
97 // This will work up to numpy.float64
|
fazekasgy@37
|
98 Py_ssize_t rValue = PyNumber_AsSsize_t(pyValue,NULL);
|
fazekasgy@37
|
99 if (PyErr_Occurred())
|
fazekasgy@37
|
100 {
|
fazekasgy@37
|
101 PyErr_Print(); PyErr_Clear();
|
fazekasgy@37
|
102 setValueError("Error while converting integer object.",m_strict);
|
fazekasgy@37
|
103 return 0.0;
|
fazekasgy@37
|
104 }
|
fazekasgy@37
|
105 if (rValue > (Py_ssize_t)FLT_MAX || rValue < (Py_ssize_t)FLT_MIN)
|
fazekasgy@37
|
106 {
|
fazekasgy@37
|
107 setValueError("Overflow error. Object can not be converted to float.",m_strict);
|
fazekasgy@37
|
108 return 0.0;
|
fazekasgy@37
|
109 }
|
fazekasgy@37
|
110 return (float) rValue;
|
fazekasgy@37
|
111 }
|
fazekasgy@37
|
112 */
|
fazekasgy@37
|
113 // convert string
|
fazekasgy@37
|
114 if (PyString_Check(pyValue))
|
fazekasgy@37
|
115 {
|
fazekasgy@37
|
116 PyObject* pyFloat = PyFloat_FromString(pyValue,NULL);
|
fazekasgy@37
|
117 if (!pyFloat)
|
fazekasgy@37
|
118 {
|
fazekasgy@37
|
119 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@37
|
120 setValueError("String value can not be converted to float.",m_strict);
|
fazekasgy@37
|
121 return 0.0;
|
fazekasgy@37
|
122 }
|
fazekasgy@37
|
123 float rValue = (float) PyFloat_AS_DOUBLE(pyFloat);
|
fazekasgy@37
|
124 if (PyErr_Occurred())
|
fazekasgy@37
|
125 {
|
fazekasgy@37
|
126 PyErr_Print(); PyErr_Clear();
|
fazekasgy@37
|
127 Py_CLEAR(pyFloat);
|
fazekasgy@37
|
128 setValueError("Error while converting float object.",m_strict);
|
fazekasgy@37
|
129 return 0.0;
|
fazekasgy@37
|
130 }
|
fazekasgy@37
|
131 Py_DECREF(pyFloat);
|
fazekasgy@37
|
132 return rValue;
|
fazekasgy@37
|
133 }
|
fazekasgy@37
|
134
|
fazekasgy@37
|
135 // convert the first element of any iterable sequence (for convenience and backwards compatibility)
|
cannam@41
|
136 if (PySequence_Check(pyValue) && PySequence_Size(pyValue) > 0)
|
fazekasgy@37
|
137 {
|
fazekasgy@37
|
138 PyObject* item = PySequence_GetItem(pyValue,0);
|
fazekasgy@37
|
139 if (item)
|
fazekasgy@37
|
140 {
|
fazekasgy@37
|
141 float rValue = this->PyValue_To_Float(item);
|
fazekasgy@37
|
142 if (!m_error) {
|
fazekasgy@37
|
143 Py_DECREF(item);
|
fazekasgy@37
|
144 return rValue;
|
fazekasgy@37
|
145 } else {
|
fazekasgy@37
|
146 Py_CLEAR(item);
|
fazekasgy@37
|
147 std::string msg = "Could not convert sequence element to float. ";
|
fazekasgy@37
|
148 setValueError(msg,m_strict);
|
fazekasgy@37
|
149 return 0.0;
|
fazekasgy@37
|
150 }
|
fazekasgy@37
|
151 }
|
fazekasgy@37
|
152 }
|
fazekasgy@37
|
153
|
fazekasgy@37
|
154 // give up
|
fazekasgy@37
|
155 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@37
|
156 std::string msg = "Conversion from " + PyValue_Get_TypeName(pyValue) + " to float is not possible.";
|
fazekasgy@37
|
157 setValueError(msg,m_strict);
|
fazekasgy@37
|
158 #ifdef _DEBUG
|
fazekasgy@37
|
159 cerr << "PyTypeInterface::PyValue_To_Float failed. " << msg << endl;
|
fazekasgy@37
|
160 #endif
|
fazekasgy@37
|
161 return 0.0;
|
fazekasgy@37
|
162 }
|
fazekasgy@37
|
163
|
fazekasgy@37
|
164 /// size_t (unsigned integer types)
|
fazekasgy@37
|
165 size_t
|
fazekasgy@37
|
166 PyTypeInterface::PyValue_To_Size_t(PyObject* pyValue) const
|
fazekasgy@37
|
167 {
|
fazekasgy@37
|
168 // convert objects supporting the number protocol
|
fazekasgy@37
|
169 if (PyNumber_Check(pyValue))
|
fazekasgy@37
|
170 {
|
fazekasgy@37
|
171 if (m_strict && !PyInt_Check(pyValue) && !PyLong_Check(pyValue))
|
fazekasgy@37
|
172 setValueError("Strict conversion error: object is not integer type.",m_strict);
|
fazekasgy@37
|
173 // Note: this function handles Bool,Int,Long,Float
|
fazekasgy@37
|
174 // speed is not critical in the use of this type by Vamp
|
fazekasgy@37
|
175 // PEP353: Py_ssize_t is size_t but signed !
|
fazekasgy@37
|
176 Py_ssize_t rValue = PyInt_AsSsize_t(pyValue);
|
fazekasgy@37
|
177 if (PyErr_Occurred())
|
fazekasgy@37
|
178 {
|
fazekasgy@37
|
179 PyErr_Print(); PyErr_Clear();
|
fazekasgy@37
|
180 setValueError("Error while converting integer object.",m_strict);
|
fazekasgy@37
|
181 return 0;
|
fazekasgy@37
|
182 }
|
fazekasgy@37
|
183 if ((unsigned long)rValue > SIZE_T_MAX || (unsigned long)rValue < 0)
|
fazekasgy@37
|
184 {
|
fazekasgy@37
|
185 setValueError("Overflow error. Object can not be converted to size_t.",m_strict);
|
fazekasgy@37
|
186 return 0;
|
fazekasgy@37
|
187 }
|
fazekasgy@37
|
188 return (size_t) rValue;
|
fazekasgy@37
|
189 }
|
fazekasgy@37
|
190
|
fazekasgy@37
|
191 // in strict mode we will not try harder and throw an exception
|
fazekasgy@37
|
192 // then the caller should decide what to do with it
|
fazekasgy@37
|
193 if (m_strict) {
|
fazekasgy@37
|
194 setValueError("Strict conversion error: object is not integer.",m_strict);
|
fazekasgy@37
|
195 return 0;
|
fazekasgy@37
|
196 }
|
fazekasgy@37
|
197
|
fazekasgy@37
|
198 // convert string
|
fazekasgy@37
|
199 if (PyString_Check(pyValue))
|
fazekasgy@37
|
200 {
|
fazekasgy@37
|
201 PyObject* pyLong = PyNumber_Long(pyValue);
|
fazekasgy@37
|
202 if (!pyLong)
|
fazekasgy@37
|
203 {
|
fazekasgy@37
|
204 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@37
|
205 setValueError("String object can not be converted to size_t.",m_strict);
|
fazekasgy@37
|
206 return 0;
|
fazekasgy@37
|
207 }
|
fazekasgy@37
|
208 size_t rValue = this->PyValue_To_Size_t(pyLong);
|
fazekasgy@37
|
209 if (!m_error) {
|
fazekasgy@37
|
210 Py_DECREF(pyLong);
|
fazekasgy@37
|
211 return rValue;
|
fazekasgy@37
|
212 } else {
|
fazekasgy@37
|
213 Py_CLEAR(pyLong);
|
fazekasgy@37
|
214 setValueError ("Error converting string to size_t.",m_strict);
|
fazekasgy@37
|
215 return 0;
|
fazekasgy@37
|
216 }
|
fazekasgy@37
|
217 }
|
fazekasgy@37
|
218
|
fazekasgy@37
|
219 // convert the first element of iterable sequences
|
cannam@41
|
220 if (PySequence_Check(pyValue) && PySequence_Size(pyValue) > 0)
|
fazekasgy@37
|
221 {
|
fazekasgy@37
|
222 PyObject* item = PySequence_GetItem(pyValue,0);
|
fazekasgy@37
|
223 if (item)
|
fazekasgy@37
|
224 {
|
fazekasgy@37
|
225 size_t rValue = this->PyValue_To_Size_t(item);
|
fazekasgy@37
|
226 if (!m_error) {
|
fazekasgy@37
|
227 Py_DECREF(item);
|
fazekasgy@37
|
228 return rValue;
|
fazekasgy@37
|
229 } else {
|
fazekasgy@37
|
230 Py_CLEAR(item);
|
fazekasgy@37
|
231 setValueError("Could not convert sequence element to size_t. ",m_strict);
|
fazekasgy@37
|
232 return 0;
|
fazekasgy@37
|
233 }
|
fazekasgy@37
|
234 }
|
fazekasgy@37
|
235 }
|
fazekasgy@37
|
236
|
fazekasgy@37
|
237 // give up
|
fazekasgy@37
|
238 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@37
|
239 std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to size_t is not possible.";
|
fazekasgy@37
|
240 setValueError(msg,m_strict);
|
fazekasgy@37
|
241 #ifdef _DEBUG
|
fazekasgy@37
|
242 cerr << "PyTypeInterface::PyValue_To_Size_t failed. " << msg << endl;
|
fazekasgy@37
|
243 #endif
|
fazekasgy@37
|
244 return 0;
|
fazekasgy@37
|
245 }
|
fazekasgy@37
|
246
|
fazekasgy@37
|
247 /// long and int
|
fazekasgy@37
|
248 long
|
fazekasgy@37
|
249 PyTypeInterface::PyValue_To_Long(PyObject* pyValue) const
|
fazekasgy@37
|
250 {
|
fazekasgy@37
|
251 // most common case: convert int (faster)
|
fazekasgy@37
|
252 if (pyValue && PyInt_Check(pyValue)) {
|
fazekasgy@37
|
253 // if the object is not NULL and verified, this macro just extracts the value.
|
fazekasgy@37
|
254 return PyInt_AS_LONG(pyValue);
|
fazekasgy@37
|
255 }
|
fazekasgy@37
|
256
|
fazekasgy@37
|
257 // long
|
fazekasgy@37
|
258 if (PyLong_Check(pyValue)) {
|
fazekasgy@37
|
259 long rValue = PyLong_AsLong(pyValue);
|
fazekasgy@37
|
260 if (PyErr_Occurred()) {
|
fazekasgy@37
|
261 PyErr_Print(); PyErr_Clear();
|
fazekasgy@37
|
262 setValueError("Error while converting long object.",m_strict);
|
fazekasgy@37
|
263 return 0;
|
fazekasgy@37
|
264 }
|
fazekasgy@37
|
265 return rValue;
|
fazekasgy@37
|
266 }
|
fazekasgy@37
|
267
|
fazekasgy@37
|
268 if (m_strict) {
|
fazekasgy@37
|
269 setValueError("Strict conversion error: object is not integer or long integer.",m_strict);
|
fazekasgy@37
|
270 return 0;
|
fazekasgy@37
|
271 }
|
fazekasgy@37
|
272
|
fazekasgy@37
|
273 // convert all objects supporting the number protocol
|
fazekasgy@37
|
274 if (PyNumber_Check(pyValue))
|
fazekasgy@37
|
275 {
|
fazekasgy@37
|
276 // Note: this function handles Bool,Int,Long,Float
|
fazekasgy@37
|
277 // PEP353: Py_ssize_t is size_t but signed !
|
fazekasgy@37
|
278 Py_ssize_t rValue = PyInt_AsSsize_t(pyValue);
|
fazekasgy@37
|
279 if (PyErr_Occurred())
|
fazekasgy@37
|
280 {
|
fazekasgy@37
|
281 PyErr_Print(); PyErr_Clear();
|
fazekasgy@37
|
282 setValueError("Error while converting integer object.",m_strict);
|
fazekasgy@37
|
283 return 0;
|
fazekasgy@37
|
284 }
|
fazekasgy@37
|
285 if (rValue > LONG_MAX || rValue < LONG_MIN)
|
fazekasgy@37
|
286 {
|
fazekasgy@37
|
287 setValueError("Overflow error. Object can not be converted to size_t.",m_strict);
|
fazekasgy@37
|
288 return 0;
|
fazekasgy@37
|
289 }
|
fazekasgy@37
|
290 return (long) rValue;
|
fazekasgy@37
|
291 }
|
fazekasgy@37
|
292
|
fazekasgy@37
|
293 // convert string
|
fazekasgy@37
|
294 if (PyString_Check(pyValue))
|
fazekasgy@37
|
295 {
|
fazekasgy@37
|
296 PyObject* pyLong = PyNumber_Long(pyValue);
|
fazekasgy@37
|
297 if (!pyLong)
|
fazekasgy@37
|
298 {
|
fazekasgy@37
|
299 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@37
|
300 setValueError("String object can not be converted to long.",m_strict);
|
fazekasgy@37
|
301 return 0;
|
fazekasgy@37
|
302 }
|
fazekasgy@37
|
303 long rValue = this->PyValue_To_Long(pyLong);
|
fazekasgy@37
|
304 if (!m_error) {
|
fazekasgy@37
|
305 Py_DECREF(pyLong);
|
fazekasgy@37
|
306 return rValue;
|
fazekasgy@37
|
307 } else {
|
fazekasgy@37
|
308 Py_CLEAR(pyLong);
|
fazekasgy@37
|
309 setValueError ("Error converting string to long.",m_strict);
|
fazekasgy@37
|
310 return 0;
|
fazekasgy@37
|
311 }
|
fazekasgy@37
|
312 }
|
fazekasgy@37
|
313
|
fazekasgy@37
|
314 // convert the first element of iterable sequences
|
cannam@46
|
315 if (PySequence_Check(pyValue) && PySequence_Size(pyValue) > 0)
|
fazekasgy@37
|
316 {
|
fazekasgy@37
|
317 PyObject* item = PySequence_GetItem(pyValue,0);
|
fazekasgy@37
|
318 if (item)
|
fazekasgy@37
|
319 {
|
fazekasgy@37
|
320 size_t rValue = this->PyValue_To_Long(item);
|
fazekasgy@37
|
321 if (!m_error) {
|
fazekasgy@37
|
322 Py_DECREF(item);
|
fazekasgy@37
|
323 return rValue;
|
fazekasgy@37
|
324 } else {
|
fazekasgy@37
|
325 Py_CLEAR(item);
|
fazekasgy@37
|
326 setValueError("Could not convert sequence element to long. ",m_strict);
|
fazekasgy@37
|
327 return 0;
|
fazekasgy@37
|
328 }
|
fazekasgy@37
|
329 }
|
fazekasgy@37
|
330 }
|
fazekasgy@37
|
331
|
fazekasgy@37
|
332 // give up
|
fazekasgy@37
|
333 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@37
|
334 std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to long is not possible.";
|
fazekasgy@37
|
335 setValueError(msg,m_strict);
|
fazekasgy@37
|
336 #ifdef _DEBUG
|
fazekasgy@37
|
337 cerr << "PyTypeInterface::PyValue_To_Long failed. " << msg << endl;
|
fazekasgy@37
|
338 #endif
|
fazekasgy@37
|
339 return 0;
|
fazekasgy@37
|
340 }
|
fazekasgy@37
|
341
|
fazekasgy@37
|
342
|
fazekasgy@37
|
343 bool
|
fazekasgy@37
|
344 PyTypeInterface::PyValue_To_Bool(PyObject* pyValue) const
|
fazekasgy@37
|
345 {
|
fazekasgy@37
|
346 // convert objects supporting the number protocol
|
fazekasgy@37
|
347 // Note: PyBool is a subclass of PyInt
|
fazekasgy@37
|
348 if (PyNumber_Check(pyValue))
|
fazekasgy@37
|
349 {
|
fazekasgy@37
|
350 if (m_strict && !PyBool_Check(pyValue))
|
fazekasgy@37
|
351 setValueError
|
fazekasgy@37
|
352 ("Strict conversion error: object is not boolean type.",m_strict);
|
fazekasgy@37
|
353
|
fazekasgy@37
|
354 // Note: this function handles Bool,Int,Long,Float
|
fazekasgy@37
|
355 Py_ssize_t rValue = PyInt_AsSsize_t(pyValue);
|
fazekasgy@37
|
356 if (PyErr_Occurred())
|
fazekasgy@37
|
357 {
|
fazekasgy@37
|
358 PyErr_Print(); PyErr_Clear();
|
fazekasgy@37
|
359 setValueError ("Error while converting boolean object.",m_strict);
|
fazekasgy@37
|
360 }
|
fazekasgy@37
|
361 if (rValue != 1 && rValue != 0)
|
fazekasgy@37
|
362 {
|
fazekasgy@37
|
363 setValueError ("Overflow error. Object can not be converted to boolean.",m_strict);
|
fazekasgy@37
|
364 }
|
fazekasgy@37
|
365 return (bool) rValue;
|
fazekasgy@37
|
366 }
|
fazekasgy@37
|
367
|
fazekasgy@37
|
368 if (m_strict) {
|
fazekasgy@37
|
369 setValueError ("Strict conversion error: object is not numerical type.",m_strict);
|
fazekasgy@37
|
370 return false;
|
fazekasgy@37
|
371 }
|
fazekasgy@37
|
372
|
fazekasgy@37
|
373 // convert iterables: the rule is the same as in the interpreter:
|
fazekasgy@37
|
374 // empty sequence evaluates to False, anything else is True
|
fazekasgy@37
|
375 if (PySequence_Check(pyValue))
|
fazekasgy@37
|
376 {
|
fazekasgy@37
|
377 return PySequence_Size(pyValue)?true:false;
|
fazekasgy@37
|
378 }
|
fazekasgy@37
|
379
|
fazekasgy@37
|
380 // give up
|
fazekasgy@37
|
381 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@37
|
382 std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to boolean is not possible.";
|
fazekasgy@37
|
383 setValueError(msg,m_strict);
|
fazekasgy@37
|
384 #ifdef _DEBUG
|
fazekasgy@37
|
385 cerr << "PyTypeInterface::PyValue_To_Bool failed. " << msg << endl;
|
fazekasgy@37
|
386 #endif
|
fazekasgy@37
|
387 return false;
|
fazekasgy@37
|
388 }
|
fazekasgy@37
|
389
|
fazekasgy@37
|
390 /// string and objects that support .__str__()
|
fazekasgy@37
|
391 /// TODO: check unicode objects
|
fazekasgy@37
|
392 std::string
|
fazekasgy@37
|
393 PyTypeInterface::PyValue_To_String(PyObject* pyValue) const
|
fazekasgy@37
|
394 {
|
fazekasgy@37
|
395 // convert string
|
fazekasgy@37
|
396 if (PyString_Check(pyValue))
|
fazekasgy@37
|
397 {
|
fazekasgy@37
|
398 char *cstr = PyString_AS_STRING(pyValue);
|
fazekasgy@37
|
399 if (!cstr)
|
fazekasgy@37
|
400 {
|
fazekasgy@37
|
401 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
402 setValueError("Error while converting string object.",m_strict);
|
fazekasgy@37
|
403 return std::string();
|
fazekasgy@37
|
404 }
|
fazekasgy@37
|
405 return std::string(cstr);
|
fazekasgy@37
|
406 }
|
fazekasgy@37
|
407 // TODO: deal with unicode here (argh!)
|
fazekasgy@37
|
408
|
fazekasgy@37
|
409 // in strict mode we will not try harder
|
fazekasgy@37
|
410 if (m_strict) {
|
fazekasgy@37
|
411 setValueError("Strict conversion error: object is not string.",m_strict);
|
fazekasgy@37
|
412 return std::string();
|
fazekasgy@37
|
413 }
|
fazekasgy@37
|
414
|
fazekasgy@37
|
415 // accept None as empty string
|
fazekasgy@37
|
416 if (pyValue == Py_None) return std::string();
|
fazekasgy@37
|
417
|
fazekasgy@37
|
418 // convert list or tuple: empties are turned into empty strings conventionally
|
fazekasgy@37
|
419 if (PyList_Check(pyValue) || PyTuple_Check(pyValue))
|
fazekasgy@37
|
420 {
|
fazekasgy@37
|
421 if (!PySequence_Size(pyValue)) return std::string();
|
fazekasgy@37
|
422 PyObject* item = PySequence_GetItem(pyValue,0);
|
fazekasgy@37
|
423 if (item)
|
fazekasgy@37
|
424 {
|
fazekasgy@37
|
425 std::string rValue = this->PyValue_To_String(item);
|
fazekasgy@37
|
426 if (!m_error) {
|
fazekasgy@37
|
427 Py_DECREF(item);
|
fazekasgy@37
|
428 return rValue;
|
fazekasgy@37
|
429 } else {
|
fazekasgy@37
|
430 Py_CLEAR(item);
|
fazekasgy@37
|
431 setValueError("Could not convert sequence element to string.",m_strict);
|
fazekasgy@37
|
432 return std::string();
|
fazekasgy@37
|
433 }
|
fazekasgy@37
|
434 }
|
fazekasgy@37
|
435 }
|
fazekasgy@37
|
436
|
fazekasgy@37
|
437 // convert any other object that has .__str__() or .__repr__()
|
fazekasgy@37
|
438 PyObject* pyString = PyObject_Str(pyValue);
|
fazekasgy@37
|
439 if (pyString && !PyErr_Occurred())
|
fazekasgy@37
|
440 {
|
fazekasgy@37
|
441 std::string rValue = this->PyValue_To_String(pyString);
|
fazekasgy@37
|
442 if (!m_error) {
|
fazekasgy@37
|
443 Py_DECREF(pyString);
|
fazekasgy@37
|
444 return rValue;
|
fazekasgy@37
|
445 } else {
|
fazekasgy@37
|
446 Py_CLEAR(pyString);
|
fazekasgy@37
|
447 std::string msg = "Object " + this->PyValue_Get_TypeName(pyValue) +" can not be represented as string. ";
|
fazekasgy@37
|
448 setValueError (msg,m_strict);
|
fazekasgy@37
|
449 return std::string();
|
fazekasgy@37
|
450 }
|
fazekasgy@37
|
451 }
|
fazekasgy@37
|
452
|
fazekasgy@37
|
453 // give up
|
fazekasgy@37
|
454 PyErr_Print(); PyErr_Clear();
|
fazekasgy@37
|
455 std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to string is not possible.";
|
fazekasgy@37
|
456 setValueError(msg,m_strict);
|
fazekasgy@37
|
457 #ifdef _DEBUG
|
fazekasgy@37
|
458 cerr << "PyTypeInterface::PyValue_To_String failed. " << msg << endl;
|
fazekasgy@37
|
459 #endif
|
fazekasgy@37
|
460 return std::string();
|
fazekasgy@37
|
461 }
|
fazekasgy@37
|
462
|
fazekasgy@37
|
463 /* C Values to Py Values */
|
fazekasgy@37
|
464
|
fazekasgy@37
|
465
|
fazekasgy@37
|
466 PyObject*
|
fazekasgy@37
|
467 PyTypeInterface::PyValue_From_CValue(const char* cValue) const
|
fazekasgy@37
|
468 {
|
fazekasgy@37
|
469 // returns new reference
|
fazekasgy@37
|
470 #ifdef _DEBUG
|
fazekasgy@37
|
471 if (!cValue) {
|
fazekasgy@37
|
472 std::string msg = "PyTypeInterface::PyValue_From_CValue: Null pointer encountered while converting from const char* .";
|
fazekasgy@37
|
473 cerr << msg << endl;
|
fazekasgy@37
|
474 setValueError(msg,m_strict);
|
fazekasgy@37
|
475 return NULL;
|
fazekasgy@37
|
476 }
|
fazekasgy@37
|
477 #endif
|
fazekasgy@37
|
478 PyObject *pyValue = PyString_FromString(cValue);
|
fazekasgy@37
|
479 if (!pyValue)
|
fazekasgy@37
|
480 {
|
fazekasgy@37
|
481 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
482 setValueError("Error while converting from char* or string.",m_strict);
|
fazekasgy@37
|
483 #ifdef _DEBUG
|
fazekasgy@37
|
484 cerr << "PyTypeInterface::PyValue_From_CValue: Interpreter failed to convert from const char*" << endl;
|
fazekasgy@37
|
485 #endif
|
fazekasgy@37
|
486 return NULL;
|
fazekasgy@37
|
487 }
|
fazekasgy@37
|
488 return pyValue;
|
fazekasgy@37
|
489 }
|
fazekasgy@37
|
490
|
fazekasgy@37
|
491 PyObject*
|
fazekasgy@37
|
492 PyTypeInterface::PyValue_From_CValue(size_t cValue) const
|
fazekasgy@37
|
493 {
|
fazekasgy@37
|
494 // returns new reference
|
fazekasgy@37
|
495 PyObject *pyValue = PyInt_FromSsize_t((Py_ssize_t)cValue);
|
fazekasgy@37
|
496 if (!pyValue)
|
fazekasgy@37
|
497 {
|
fazekasgy@37
|
498 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
499 setValueError("Error while converting from size_t.",m_strict);
|
fazekasgy@37
|
500 #ifdef _DEBUG
|
fazekasgy@37
|
501 cerr << "PyTypeInterface::PyValue_From_CValue: Interpreter failed to convert from size_t" << endl;
|
fazekasgy@37
|
502 #endif
|
fazekasgy@37
|
503 return NULL;
|
fazekasgy@37
|
504 }
|
fazekasgy@37
|
505 return pyValue;
|
fazekasgy@37
|
506 }
|
fazekasgy@37
|
507
|
fazekasgy@37
|
508 PyObject*
|
fazekasgy@37
|
509 PyTypeInterface::PyValue_From_CValue(double cValue) const
|
fazekasgy@37
|
510 {
|
fazekasgy@37
|
511 // returns new reference
|
fazekasgy@37
|
512 PyObject *pyValue = PyFloat_FromDouble(cValue);
|
fazekasgy@37
|
513 if (!pyValue)
|
fazekasgy@37
|
514 {
|
fazekasgy@37
|
515 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
516 setValueError("Error while converting from float or double.",m_strict);
|
fazekasgy@37
|
517 #ifdef _DEBUG
|
fazekasgy@37
|
518 cerr << "PyTypeInterface::PyValue_From_CValue: Interpreter failed to convert from float or double" << endl;
|
fazekasgy@37
|
519 #endif
|
fazekasgy@37
|
520 return NULL;
|
fazekasgy@37
|
521 }
|
fazekasgy@37
|
522 return pyValue;
|
fazekasgy@37
|
523 }
|
fazekasgy@37
|
524
|
fazekasgy@37
|
525 PyObject*
|
fazekasgy@37
|
526 PyTypeInterface::PyValue_From_CValue(bool cValue) const
|
fazekasgy@37
|
527 {
|
fazekasgy@37
|
528 // returns new reference
|
fazekasgy@37
|
529 PyObject *pyValue = PyBool_FromLong((long)cValue);
|
fazekasgy@37
|
530 if (!pyValue)
|
fazekasgy@37
|
531 {
|
fazekasgy@37
|
532 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
533 setValueError("Error while converting from bool.",m_strict);
|
fazekasgy@37
|
534 #ifdef _DEBUG
|
fazekasgy@37
|
535 cerr << "PyTypeInterface::PyValue_From_CValue: Interpreter failed to convert from bool" << endl;
|
fazekasgy@37
|
536 #endif
|
fazekasgy@37
|
537 return NULL;
|
fazekasgy@37
|
538 }
|
fazekasgy@37
|
539 return pyValue;
|
fazekasgy@37
|
540 }
|
fazekasgy@37
|
541
|
fazekasgy@37
|
542
|
fazekasgy@37
|
543 /* Sequence Types to C++ Types */
|
fazekasgy@37
|
544
|
fazekasgy@37
|
545 //convert Python list to C++ vector of strings
|
fazekasgy@37
|
546 std::vector<std::string>
|
fazekasgy@37
|
547 PyTypeInterface::PyValue_To_StringVector (PyObject *pyList) const
|
fazekasgy@37
|
548 {
|
fazekasgy@37
|
549
|
fazekasgy@37
|
550 std::vector<std::string> Output;
|
fazekasgy@37
|
551 std::string ListElement;
|
fazekasgy@37
|
552 PyObject *pyString = NULL;
|
fazekasgy@37
|
553
|
fazekasgy@37
|
554 if (PyList_Check(pyList)) {
|
fazekasgy@37
|
555
|
fazekasgy@37
|
556 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(pyList); ++i) {
|
fazekasgy@37
|
557 //Get next list item (Borrowed Reference)
|
fazekasgy@37
|
558 pyString = PyList_GET_ITEM(pyList,i);
|
fazekasgy@37
|
559 ListElement = (string) PyString_AsString(PyObject_Str(pyString));
|
fazekasgy@37
|
560 Output.push_back(ListElement);
|
fazekasgy@37
|
561 }
|
fazekasgy@37
|
562 return Output;
|
fazekasgy@37
|
563 }
|
fazekasgy@51
|
564
|
fazekasgy@51
|
565 // #ifdef _DEBUG
|
fazekasgy@51
|
566 // cerr << "PyTypeInterface::PyValue_To_StringVector: Warning: Value is not list of strings." << endl;
|
fazekasgy@51
|
567 // #endif
|
fazekasgy@37
|
568
|
fazekasgy@37
|
569 /// Assume a single value that can be casted as string
|
fazekasgy@37
|
570 /// this allows to write e.g. Feature.label = 5.2 instead of ['5.2']
|
fazekasgy@37
|
571 Output.push_back(PyValue_To_String(pyList));
|
fazekasgy@37
|
572 if (m_error) {
|
fazekasgy@37
|
573 std::string msg = "Value is not list of strings nor can be casted as string. ";
|
fazekasgy@37
|
574 setValueError(msg,m_strict);
|
fazekasgy@37
|
575 #ifdef _DEBUG
|
fazekasgy@37
|
576 cerr << "PyTypeInterface::PyValue_To_StringVector failed. " << msg << endl;
|
fazekasgy@37
|
577 #endif
|
fazekasgy@37
|
578 }
|
fazekasgy@37
|
579 return Output;
|
fazekasgy@37
|
580 }
|
fazekasgy@37
|
581
|
fazekasgy@37
|
582 //convert PyFeature.value (typically a list or numpy array) to C++ vector of floats
|
fazekasgy@37
|
583 std::vector<float>
|
fazekasgy@37
|
584 PyTypeInterface::PyValue_To_FloatVector (PyObject *pyValue) const
|
fazekasgy@37
|
585 {
|
fazekasgy@37
|
586
|
fazekasgy@37
|
587 #ifdef HAVE_NUMPY
|
fazekasgy@51
|
588 if (m_numpyInstalled)
|
fazekasgy@51
|
589 {
|
fazekasgy@37
|
590 // there are four types of values we may receive from a numpy process:
|
fazekasgy@37
|
591 // * a python scalar,
|
fazekasgy@37
|
592 // * an array scalar, (e.g. numpy.float32)
|
fazekasgy@37
|
593 // * an array with nd = 0 (0D array)
|
fazekasgy@37
|
594 // * an array with nd > 0
|
fazekasgy@37
|
595
|
fazekasgy@37
|
596 /// check for scalars
|
fazekasgy@37
|
597 if (PyArray_CheckScalar(pyValue) || PyFloat_Check(pyValue)) {
|
fazekasgy@37
|
598
|
fazekasgy@37
|
599 std::vector<float> Output;
|
fazekasgy@37
|
600
|
fazekasgy@37
|
601 // we rely on the behaviour the scalars are either floats
|
fazekasgy@37
|
602 // or support the number protocol
|
fazekasgy@37
|
603 // TODO: a potential optimisation is to handle them directly
|
fazekasgy@37
|
604 Output.push_back(PyValue_To_Float(pyValue));
|
fazekasgy@37
|
605 return Output;
|
fazekasgy@37
|
606 }
|
fazekasgy@37
|
607
|
fazekasgy@37
|
608 /// numpy array
|
fazekasgy@37
|
609 if (PyArray_CheckExact(pyValue))
|
fazekasgy@37
|
610 return PyArray_To_FloatVector(pyValue);
|
fazekasgy@51
|
611 }
|
fazekasgy@37
|
612 #endif
|
fazekasgy@37
|
613
|
fazekasgy@37
|
614 /// python list of floats (backward compatible)
|
fazekasgy@37
|
615 if (PyList_Check(pyValue)) {
|
fazekasgy@37
|
616 return PyList_To_FloatVector(pyValue);
|
fazekasgy@37
|
617 }
|
fazekasgy@37
|
618
|
fazekasgy@37
|
619 std::vector<float> Output;
|
fazekasgy@37
|
620
|
fazekasgy@37
|
621 /// finally assume a single value supporting the number protocol
|
fazekasgy@37
|
622 /// this allows to write e.g. Feature.values = 5 instead of [5.00]
|
fazekasgy@37
|
623 Output.push_back(PyValue_To_Float(pyValue));
|
fazekasgy@37
|
624 if (m_error) {
|
fazekasgy@37
|
625 std::string msg = "Value is not list or array of floats nor can be casted as float. ";
|
fazekasgy@37
|
626 setValueError(msg,m_strict);
|
fazekasgy@37
|
627 #ifdef _DEBUG
|
fazekasgy@51
|
628 cerr << "PyTypeInterface::PyValue_To_FloatVector failed. " << msg << endl;
|
fazekasgy@37
|
629 #endif
|
fazekasgy@37
|
630 }
|
fazekasgy@37
|
631 return Output;
|
fazekasgy@37
|
632 }
|
fazekasgy@37
|
633
|
fazekasgy@37
|
634 //convert a list of python floats
|
fazekasgy@37
|
635 std::vector<float>
|
fazekasgy@37
|
636 PyTypeInterface::PyList_To_FloatVector (PyObject *inputList) const
|
fazekasgy@37
|
637 {
|
fazekasgy@37
|
638 std::vector<float> Output;
|
fazekasgy@37
|
639
|
fazekasgy@37
|
640 #ifdef _DEBUG
|
fazekasgy@37
|
641 // This is a low level function normally called from
|
fazekasgy@37
|
642 // PyValue_To_FloatVector(). Checking for list is not required.
|
fazekasgy@37
|
643 if (!PyList_Check(inputList)) {
|
fazekasgy@37
|
644 std::string msg = "Value is not list.";
|
fazekasgy@37
|
645 setValueError(msg,true);
|
fazekasgy@37
|
646 cerr << "PyTypeInterface::PyList_To_FloatVector failed. " << msg << endl;
|
fazekasgy@37
|
647 return Output;
|
fazekasgy@37
|
648 }
|
fazekasgy@37
|
649 #endif
|
fazekasgy@37
|
650
|
fazekasgy@37
|
651 float ListElement;
|
fazekasgy@37
|
652 PyObject *pyFloat = NULL;
|
fazekasgy@37
|
653 PyObject **pyObjectArray = PySequence_Fast_ITEMS(inputList);
|
fazekasgy@37
|
654
|
fazekasgy@37
|
655 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(inputList); ++i) {
|
fazekasgy@37
|
656
|
fazekasgy@37
|
657 // pyFloat = PyList_GET_ITEM(inputList,i);
|
fazekasgy@37
|
658 pyFloat = pyObjectArray[i];
|
fazekasgy@37
|
659
|
fazekasgy@37
|
660 #ifdef _DEBUG
|
fazekasgy@37
|
661 if (!pyFloat) {
|
fazekasgy@37
|
662 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
663 cerr << "PyTypeInterface::PyList_To_FloatVector: Could not obtain list element: "
|
fazekasgy@37
|
664 << i << " PyList_GetItem returned NULL! Skipping value." << endl;
|
fazekasgy@37
|
665 continue;
|
fazekasgy@37
|
666 }
|
fazekasgy@37
|
667 #endif
|
fazekasgy@37
|
668
|
fazekasgy@37
|
669 // ListElement = (float) PyFloat_AS_DOUBLE(pyFloat);
|
fazekasgy@37
|
670 ListElement = PyValue_To_Float(pyFloat);
|
fazekasgy@37
|
671
|
fazekasgy@37
|
672
|
fazekasgy@37
|
673 #ifdef _DEBUG_VALUES
|
fazekasgy@37
|
674 cerr << "value: " << ListElement << endl;
|
fazekasgy@37
|
675 #endif
|
fazekasgy@37
|
676 Output.push_back(ListElement);
|
fazekasgy@37
|
677 }
|
fazekasgy@37
|
678 return Output;
|
fazekasgy@37
|
679 }
|
fazekasgy@37
|
680
|
fazekasgy@51
|
681 // if numpy is not installed this will not be called,
|
fazekasgy@51
|
682 // therefor we do not check again
|
fazekasgy@51
|
683 #ifdef HAVE_NUMPY
|
fazekasgy@37
|
684 std::vector<float>
|
fazekasgy@37
|
685 PyTypeInterface::PyArray_To_FloatVector (PyObject *pyValue) const
|
fazekasgy@37
|
686 {
|
fazekasgy@37
|
687 std::vector<float> Output;
|
fazekasgy@37
|
688
|
fazekasgy@37
|
689 #ifdef _DEBUG
|
fazekasgy@37
|
690 // This is a low level function, normally called from
|
fazekasgy@37
|
691 // PyValue_To_FloatVector(). Checking the array here is not required.
|
fazekasgy@37
|
692 if (!PyArray_Check(pyValue)) {
|
fazekasgy@37
|
693 std::string msg = "Object has no array interface.";
|
fazekasgy@37
|
694 setValueError(msg,true);
|
fazekasgy@37
|
695 cerr << "PyTypeInterface::PyArray_To_FloatVector failed. " << msg << endl;
|
fazekasgy@37
|
696 return Output;
|
fazekasgy@37
|
697 }
|
fazekasgy@37
|
698 #endif
|
fazekasgy@37
|
699
|
fazekasgy@37
|
700 PyArrayObject* pyArray = (PyArrayObject*) pyValue;
|
fazekasgy@37
|
701 PyArray_Descr* descr = pyArray->descr;
|
fazekasgy@37
|
702
|
fazekasgy@37
|
703 /// check raw data and descriptor pointers
|
fazekasgy@37
|
704 if (pyArray->data == 0 || descr == 0) {
|
fazekasgy@37
|
705 std::string msg = "NumPy array with NULL data or descriptor pointer encountered.";
|
fazekasgy@37
|
706 setValueError(msg,m_strict);
|
fazekasgy@37
|
707 #ifdef _DEBUG
|
fazekasgy@37
|
708 cerr << "PyTypeInterface::PyArray_To_FloatVector failed. Error: " << msg << endl;
|
fazekasgy@37
|
709 #endif
|
fazekasgy@37
|
710 return Output;
|
fazekasgy@37
|
711 }
|
fazekasgy@37
|
712
|
fazekasgy@37
|
713 /// check dimensions
|
fazekasgy@37
|
714 if (pyArray->nd != 1) {
|
fazekasgy@37
|
715 std::string msg = "NumPy array must be a one dimensional vector.";
|
fazekasgy@37
|
716 setValueError(msg,m_strict);
|
fazekasgy@37
|
717 #ifdef _DEBUG
|
fazekasgy@37
|
718 cerr << "PyTypeInterface::PyArray_To_FloatVector failed. Error: " << msg << " Dims: " << (int) pyArray->nd << endl;
|
fazekasgy@37
|
719 #endif
|
fazekasgy@37
|
720 return Output;
|
fazekasgy@37
|
721 }
|
fazekasgy@37
|
722
|
fazekasgy@37
|
723 #ifdef _DEBUG_VALUES
|
fazekasgy@37
|
724 cerr << "PyTypeInterface::PyArray_To_FloatVector: Numpy array verified." << endl;
|
fazekasgy@37
|
725 #endif
|
fazekasgy@37
|
726
|
fazekasgy@37
|
727 /// check strides (useful if array is not continuous)
|
fazekasgy@37
|
728 size_t strides = *((size_t*) pyArray->strides);
|
fazekasgy@37
|
729
|
fazekasgy@37
|
730 /// convert the array
|
fazekasgy@37
|
731 switch (descr->type_num)
|
fazekasgy@37
|
732 {
|
fazekasgy@37
|
733 case NPY_FLOAT : // dtype='float32'
|
fazekasgy@37
|
734 return PyArray_Convert<float,float>(pyArray->data,pyArray->dimensions[0],strides);
|
fazekasgy@37
|
735 case NPY_DOUBLE : // dtype='float64'
|
fazekasgy@37
|
736 return PyArray_Convert<float,double>(pyArray->data,pyArray->dimensions[0],strides);
|
fazekasgy@37
|
737 case NPY_INT : // dtype='int'
|
fazekasgy@37
|
738 return PyArray_Convert<float,int>(pyArray->data,pyArray->dimensions[0],strides);
|
fazekasgy@37
|
739 case NPY_LONG : // dtype='long'
|
fazekasgy@37
|
740 return PyArray_Convert<float,long>(pyArray->data,pyArray->dimensions[0],strides);
|
fazekasgy@37
|
741 default :
|
fazekasgy@37
|
742 std::string msg = "Unsupported value type in NumPy array object.";
|
fazekasgy@37
|
743 setValueError(msg,m_strict);
|
fazekasgy@37
|
744 #ifdef _DEBUG
|
fazekasgy@37
|
745 cerr << "PyTypeInterface::PyArray_To_FloatVector failed. Error: " << msg << endl;
|
fazekasgy@37
|
746 #endif
|
fazekasgy@37
|
747 return Output;
|
fazekasgy@37
|
748 }
|
fazekasgy@37
|
749 }
|
fazekasgy@37
|
750 #endif
|
fazekasgy@37
|
751
|
fazekasgy@37
|
752
|
fazekasgy@51
|
753 /// FeatureSet (an integer map of FeatureLists)
|
fazekasgy@37
|
754 Vamp::Plugin::FeatureSet
|
fazekasgy@37
|
755 PyTypeInterface::PyValue_To_FeatureSet(PyObject* pyValue) const
|
fazekasgy@37
|
756 {
|
fazekasgy@37
|
757 Vamp::Plugin::FeatureSet rFeatureSet;
|
fazekasgy@37
|
758
|
fazekasgy@37
|
759 /// Convert PyFeatureSet
|
fazekasgy@37
|
760 if (PyFeatureSet_CheckExact(pyValue)) {
|
fazekasgy@37
|
761
|
fazekasgy@37
|
762 Py_ssize_t pyPos = 0;
|
fazekasgy@37
|
763 PyObject *pyKey, *pyDictValue; // Borrowed References
|
fazekasgy@37
|
764 int key;
|
fazekasgy@37
|
765 // bool it_error = false;
|
fazekasgy@37
|
766
|
fazekasgy@37
|
767 m_error = false;
|
fazekasgy@37
|
768 while (PyDict_Next(pyValue, &pyPos, &pyKey, &pyDictValue))
|
fazekasgy@37
|
769 {
|
fazekasgy@37
|
770 key = (int) PyInt_AS_LONG(pyKey);
|
fazekasgy@37
|
771 #ifdef _DEBUG_VALUES
|
fazekasgy@37
|
772 cerr << "key: '" << key << "' value: '" << PyValue_To_String(pyDictValue) << "' " << endl;
|
fazekasgy@37
|
773 #endif
|
fazekasgy@37
|
774 // DictValue -> Vamp::FeatureList
|
fazekasgy@37
|
775 PyValue_To_rValue(pyDictValue,rFeatureSet[key]);
|
fazekasgy@37
|
776 if (m_error) {
|
fazekasgy@37
|
777 // it_error = true;
|
fazekasgy@37
|
778 lastError() << " in output number: " << key;
|
fazekasgy@37
|
779 }
|
fazekasgy@37
|
780 }
|
fazekasgy@37
|
781 // if (it_error) m_error = true;
|
fazekasgy@37
|
782 if (!m_errorQueue.empty()) {
|
fazekasgy@37
|
783 setValueError("Error while converting FeatureSet.",m_strict);
|
fazekasgy@37
|
784 }
|
fazekasgy@37
|
785 return rFeatureSet;
|
fazekasgy@37
|
786 }
|
fazekasgy@37
|
787
|
fazekasgy@37
|
788 /// Convert Python list (backward compatibility)
|
fazekasgy@37
|
789 if (PyList_Check(pyValue)) {
|
fazekasgy@37
|
790
|
fazekasgy@37
|
791 PyObject *pyFeatureList; // This will be borrowed reference
|
fazekasgy@37
|
792
|
fazekasgy@37
|
793 //Parse Output List for each element (FeatureSet)
|
fazekasgy@37
|
794 m_error = false;
|
fazekasgy@37
|
795 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(pyValue); ++i) {
|
fazekasgy@37
|
796 //Get i-th FeatureList (Borrowed Reference)
|
fazekasgy@37
|
797 pyFeatureList = PyList_GET_ITEM(pyValue,i);
|
fazekasgy@37
|
798 PyValue_To_rValue(pyFeatureList,rFeatureSet[i]);
|
fazekasgy@37
|
799 if (m_error) {
|
fazekasgy@37
|
800 lastError() << " in output number: " << i;
|
fazekasgy@37
|
801 }
|
fazekasgy@37
|
802 }
|
fazekasgy@37
|
803 if (!m_errorQueue.empty()) m_error = true;
|
fazekasgy@37
|
804 return rFeatureSet;
|
fazekasgy@37
|
805 }
|
fazekasgy@37
|
806
|
fazekasgy@51
|
807 /// accept None return values
|
fazekasgy@37
|
808 if (pyValue == Py_None) return rFeatureSet;
|
fazekasgy@37
|
809
|
fazekasgy@37
|
810 /// give up
|
fazekasgy@37
|
811 std::string msg = "Unsupported return type. Expected list or vampy.FeatureSet(). ";
|
fazekasgy@37
|
812 setValueError(msg,m_strict);
|
fazekasgy@37
|
813 #ifdef _DEBUG
|
fazekasgy@37
|
814 cerr << "PyTypeInterface::PyValue_To_FeatureSet failed. Error: " << msg << endl;
|
fazekasgy@37
|
815 #endif
|
fazekasgy@37
|
816 return rFeatureSet;
|
fazekasgy@37
|
817 }
|
fazekasgy@37
|
818
|
fazekasgy@37
|
819 Vamp::RealTime
|
fazekasgy@37
|
820 PyTypeInterface::PyValue_To_RealTime(PyObject* pyValue) const
|
fazekasgy@37
|
821 {
|
fazekasgy@37
|
822 // We accept integer sample counts (for backward compatibility)
|
fazekasgy@37
|
823 // or PyRealTime objects and convert them to Vamp::RealTime
|
fazekasgy@37
|
824
|
fazekasgy@37
|
825 if (PyRealTime_CheckExact(pyValue))
|
fazekasgy@37
|
826 {
|
fazekasgy@37
|
827 /// just create a copy of the wrapped object
|
fazekasgy@37
|
828 return Vamp::RealTime(*PyRealTime_AS_REALTIME(pyValue));
|
fazekasgy@37
|
829 }
|
fazekasgy@37
|
830
|
fazekasgy@37
|
831 // assume integer sample count
|
fazekasgy@37
|
832 long sampleCount = PyValue_To_Long(pyValue);
|
fazekasgy@37
|
833 if (m_error) {
|
fazekasgy@37
|
834 std::string msg = "Unexpected value passed as RealTime.\nMust be vampy.RealTime type or integer sample count.";
|
fazekasgy@37
|
835 setValueError(msg,m_strict);
|
fazekasgy@37
|
836 #ifdef _DEBUG
|
fazekasgy@37
|
837 cerr << "PyTypeInterface::PyValue_To_RealTime failed. " << msg << endl;
|
fazekasgy@37
|
838 #endif
|
fazekasgy@37
|
839 return Vamp::RealTime();
|
fazekasgy@37
|
840 }
|
fazekasgy@37
|
841
|
fazekasgy@37
|
842 #ifdef _DEBUG_VALUES
|
fazekasgy@37
|
843 Vamp::RealTime rt =
|
fazekasgy@37
|
844 Vamp::RealTime::frame2RealTime(sampleCount,m_inputSampleRate );
|
fazekasgy@37
|
845 cerr << "RealTime: " << (long)sampleCount << ", ->" << rt.toString() << endl;
|
fazekasgy@37
|
846 return rt;
|
fazekasgy@37
|
847 #else
|
fazekasgy@37
|
848 return Vamp::RealTime::frame2RealTime(sampleCount,m_inputSampleRate );
|
fazekasgy@37
|
849 #endif
|
fazekasgy@37
|
850
|
fazekasgy@37
|
851 }
|
fazekasgy@37
|
852
|
fazekasgy@37
|
853 Vamp::Plugin::OutputDescriptor::SampleType
|
fazekasgy@37
|
854 PyTypeInterface::PyValue_To_SampleType(PyObject* pyValue) const
|
fazekasgy@37
|
855 {
|
fazekasgy@37
|
856 /// convert simulated enum values
|
fazekasgy@37
|
857 /// { OneSamplePerStep,FixedSampleRate,VariableSampleRate }
|
fazekasgy@37
|
858 if (PyInt_CheckExact(pyValue)) {
|
fazekasgy@37
|
859 long lst = PyInt_AS_LONG(pyValue);
|
fazekasgy@37
|
860 if (lst<0 || lst>2) {
|
fazekasgy@37
|
861 setValueError("Overflow error. SampleType has to be one of { OneSamplePerStep,FixedSampleRate,VariableSampleRate }\n(an integer in the range of 0..2) or a string value naming the type.",m_strict);
|
fazekasgy@37
|
862 return Vamp::Plugin::OutputDescriptor::SampleType();
|
fazekasgy@37
|
863 }
|
fazekasgy@37
|
864 return (Vamp::Plugin::OutputDescriptor::SampleType) lst;
|
fazekasgy@37
|
865 }
|
fazekasgy@37
|
866
|
fazekasgy@37
|
867 /// convert string (backward compatible)
|
fazekasgy@37
|
868 if (PyString_CheckExact(pyValue)) {
|
fazekasgy@37
|
869 Vamp::Plugin::OutputDescriptor::SampleType st;
|
fazekasgy@37
|
870 st = (Vamp::Plugin::OutputDescriptor::SampleType) sampleKeys[PyValue_To_String(pyValue)];
|
fazekasgy@37
|
871 if (m_error) {
|
fazekasgy@37
|
872 std::string msg = "Unexpected value passed as SampleType. Must be one of { OneSamplePerStep,FixedSampleRate,VariableSampleRate }\n(an integer in the range of 0..2) or a string value naming the type.";
|
fazekasgy@37
|
873 setValueError(msg,m_strict);
|
fazekasgy@37
|
874 return Vamp::Plugin::OutputDescriptor::SampleType();
|
fazekasgy@37
|
875 }
|
fazekasgy@37
|
876 return st;
|
fazekasgy@37
|
877 }
|
fazekasgy@37
|
878
|
fazekasgy@37
|
879 /// give up
|
fazekasgy@37
|
880 std::string msg = "Unsupported return type. Expected one of { OneSamplePerStep,FixedSampleRate,VariableSampleRate }\n(an integer in the range of 0..2) or a string value naming the type.";
|
fazekasgy@37
|
881 setValueError(msg,m_strict);
|
fazekasgy@37
|
882 #ifdef _DEBUG
|
fazekasgy@37
|
883 cerr << "PyTypeInterface::PyValue_To_SampleType failed. Error: " << msg << endl;
|
fazekasgy@37
|
884 #endif
|
fazekasgy@37
|
885 return Vamp::Plugin::OutputDescriptor::SampleType();
|
fazekasgy@37
|
886 }
|
fazekasgy@37
|
887
|
fazekasgy@37
|
888 Vamp::Plugin::InputDomain
|
fazekasgy@37
|
889 PyTypeInterface::PyValue_To_InputDomain(PyObject* pyValue) const
|
fazekasgy@37
|
890 {
|
fazekasgy@37
|
891 /// convert simulated enum values { TimeDomain,FrequencyDomain }
|
fazekasgy@37
|
892 if (PyInt_CheckExact(pyValue)) {
|
fazekasgy@37
|
893 long lst = PyInt_AS_LONG(pyValue);
|
fazekasgy@37
|
894 if (lst!=0 && lst!=1) {
|
fazekasgy@37
|
895 setValueError("Overflow error. InputDomain has to be one of { TimeDomain,FrequencyDomain }\n(an integer in the range of 0..1) or a string value naming the type.",m_strict);
|
fazekasgy@37
|
896 return Vamp::Plugin::InputDomain();
|
fazekasgy@37
|
897 }
|
fazekasgy@37
|
898 return (Vamp::Plugin::InputDomain) lst;
|
fazekasgy@37
|
899 }
|
fazekasgy@37
|
900
|
fazekasgy@37
|
901 /// convert string (backward compatible)
|
fazekasgy@37
|
902 if (PyString_CheckExact(pyValue)) {
|
fazekasgy@37
|
903 Vamp::Plugin::InputDomain id;
|
fazekasgy@37
|
904 id = (PyValue_To_String(pyValue) == "FrequencyDomain")?Vamp::Plugin::FrequencyDomain:Vamp::Plugin::TimeDomain;
|
fazekasgy@37
|
905 if (m_error)
|
fazekasgy@37
|
906 {
|
fazekasgy@37
|
907 std::string msg = "Unexpected value passed as SampleType. Must be one of { TimeDomain,FrequencyDomain }\n(an integer in the range of 0..1) or a string value naming the type.";
|
fazekasgy@37
|
908 setValueError(msg,m_strict);
|
fazekasgy@37
|
909 return Vamp::Plugin::InputDomain();
|
fazekasgy@37
|
910 }
|
fazekasgy@37
|
911 return id;
|
fazekasgy@37
|
912 }
|
fazekasgy@37
|
913
|
fazekasgy@37
|
914 /// give up
|
fazekasgy@37
|
915 std::string msg = "Unsupported return type. Expected one of { TimeDomain,FrequencyDomain }\n(an integer in the range of 0..1) or a string value naming the type.";
|
fazekasgy@37
|
916 setValueError(msg,m_strict);
|
fazekasgy@37
|
917 #ifdef _DEBUG
|
fazekasgy@37
|
918 cerr << "PyTypeInterface::PyValue_To_InputDomain failed. Error: " << msg << endl;
|
fazekasgy@37
|
919 #endif
|
fazekasgy@37
|
920 return Vamp::Plugin::InputDomain();
|
fazekasgy@37
|
921 }
|
fazekasgy@37
|
922
|
fazekasgy@37
|
923
|
fazekasgy@37
|
924 /// OutputDescriptor
|
fazekasgy@37
|
925 void
|
fazekasgy@37
|
926 PyTypeInterface::SetValue(Vamp::Plugin::OutputDescriptor& od, std::string& key, PyObject* pyValue) const
|
fazekasgy@37
|
927 {
|
fazekasgy@37
|
928 switch (outKeys[key])
|
fazekasgy@37
|
929 {
|
fazekasgy@37
|
930 case o::not_found:
|
fazekasgy@37
|
931 setValueError("Unknown key in Vamp OutputDescriptor",m_strict);
|
fazekasgy@37
|
932 cerr << "Unknown key in Vamp OutputDescriptor: " << key << endl;
|
fazekasgy@37
|
933 break;
|
fazekasgy@37
|
934 case o::identifier:
|
fazekasgy@37
|
935 _convert(pyValue,od.identifier);
|
fazekasgy@37
|
936 break;
|
fazekasgy@37
|
937 case o::name:
|
fazekasgy@37
|
938 _convert(pyValue,od.name);
|
fazekasgy@37
|
939 break;
|
fazekasgy@37
|
940 case o::description:
|
fazekasgy@37
|
941 _convert(pyValue,od.description);
|
fazekasgy@37
|
942 break;
|
fazekasgy@37
|
943 case o::unit:
|
fazekasgy@37
|
944 _convert(pyValue,od.unit);
|
fazekasgy@37
|
945 break;
|
fazekasgy@37
|
946 case o::hasFixedBinCount:
|
fazekasgy@37
|
947 _convert(pyValue,od.hasFixedBinCount);
|
fazekasgy@37
|
948 break;
|
fazekasgy@37
|
949 case o::binCount:
|
fazekasgy@37
|
950 _convert(pyValue,od.binCount);
|
fazekasgy@37
|
951 break;
|
fazekasgy@37
|
952 case o::binNames:
|
fazekasgy@37
|
953 _convert(pyValue,od.binNames);
|
fazekasgy@37
|
954 break;
|
fazekasgy@37
|
955 case o::hasKnownExtents:
|
fazekasgy@37
|
956 _convert(pyValue,od.hasKnownExtents);
|
fazekasgy@37
|
957 break;
|
fazekasgy@37
|
958 case o::minValue:
|
fazekasgy@37
|
959 _convert(pyValue,od.minValue);
|
fazekasgy@37
|
960 break;
|
fazekasgy@37
|
961 case o::maxValue:
|
fazekasgy@37
|
962 _convert(pyValue,od.maxValue);
|
fazekasgy@37
|
963 break;
|
fazekasgy@37
|
964 case o::isQuantized:
|
fazekasgy@37
|
965 _convert(pyValue,od.isQuantized);
|
fazekasgy@37
|
966 break;
|
fazekasgy@37
|
967 case o::quantizeStep:
|
fazekasgy@37
|
968 _convert(pyValue,od.quantizeStep);
|
fazekasgy@37
|
969 break;
|
fazekasgy@37
|
970 case o::sampleType:
|
fazekasgy@37
|
971 _convert(pyValue,od.sampleType);
|
fazekasgy@37
|
972 break;
|
fazekasgy@37
|
973 case o::sampleRate:
|
fazekasgy@37
|
974 _convert(pyValue,od.sampleRate);
|
fazekasgy@37
|
975 break;
|
fazekasgy@37
|
976 case o::hasDuration:
|
fazekasgy@37
|
977 _convert(pyValue,od.hasDuration);
|
fazekasgy@37
|
978 break;
|
fazekasgy@37
|
979 default:
|
fazekasgy@37
|
980 setValueError("Unknown key in Vamp OutputDescriptor",m_strict);
|
fazekasgy@37
|
981 cerr << "Invalid key in Vamp OutputDescriptor: " << key << endl;
|
fazekasgy@37
|
982 }
|
fazekasgy@37
|
983 }
|
fazekasgy@37
|
984
|
fazekasgy@37
|
985 /// ParameterDescriptor
|
fazekasgy@37
|
986 void
|
fazekasgy@37
|
987 PyTypeInterface::SetValue(Vamp::Plugin::ParameterDescriptor& pd, std::string& key, PyObject* pyValue) const
|
fazekasgy@37
|
988 {
|
fazekasgy@37
|
989 switch (parmKeys[key])
|
fazekasgy@37
|
990 {
|
fazekasgy@37
|
991 case p::not_found :
|
fazekasgy@37
|
992 setValueError("Unknown key in Vamp ParameterDescriptor",m_strict);
|
fazekasgy@37
|
993 cerr << "Unknown key in Vamp ParameterDescriptor: " << key << endl;
|
fazekasgy@37
|
994 break;
|
fazekasgy@37
|
995 case p::identifier:
|
fazekasgy@37
|
996 _convert(pyValue,pd.identifier);
|
fazekasgy@37
|
997 break;
|
fazekasgy@37
|
998 case p::name:
|
fazekasgy@37
|
999 _convert(pyValue,pd.name);
|
fazekasgy@37
|
1000 break;
|
fazekasgy@37
|
1001 case p::description:
|
fazekasgy@37
|
1002 _convert(pyValue,pd.description);
|
fazekasgy@37
|
1003 break;
|
fazekasgy@37
|
1004 case p::unit:
|
fazekasgy@37
|
1005 _convert(pyValue,pd.unit);
|
fazekasgy@37
|
1006 break;
|
fazekasgy@37
|
1007 case p::minValue:
|
fazekasgy@37
|
1008 _convert(pyValue,pd.minValue);
|
fazekasgy@37
|
1009 break;
|
fazekasgy@37
|
1010 case p::maxValue:
|
fazekasgy@37
|
1011 _convert(pyValue,pd.maxValue);
|
fazekasgy@37
|
1012 break;
|
fazekasgy@37
|
1013 case p::defaultValue:
|
fazekasgy@37
|
1014 _convert(pyValue,pd.defaultValue);
|
fazekasgy@37
|
1015 break;
|
fazekasgy@37
|
1016 case p::isQuantized:
|
fazekasgy@37
|
1017 _convert(pyValue,pd.isQuantized);
|
fazekasgy@37
|
1018 break;
|
fazekasgy@37
|
1019 case p::quantizeStep:
|
fazekasgy@37
|
1020 _convert(pyValue,pd.quantizeStep);
|
fazekasgy@37
|
1021 break;
|
gyorgyf@62
|
1022 case p::valueNames:
|
gyorgyf@62
|
1023 _convert(pyValue,pd.valueNames);
|
gyorgyf@62
|
1024 break;
|
fazekasgy@37
|
1025 default :
|
fazekasgy@37
|
1026 setValueError("Unknown key in Vamp ParameterDescriptor",m_strict);
|
fazekasgy@37
|
1027 cerr << "Invalid key in Vamp ParameterDescriptor: " << key << endl;
|
fazekasgy@37
|
1028 }
|
fazekasgy@37
|
1029 }
|
fazekasgy@37
|
1030
|
fazekasgy@37
|
1031 /// Feature (it's like a Descriptor)
|
fazekasgy@37
|
1032 bool
|
fazekasgy@37
|
1033 PyTypeInterface::SetValue(Vamp::Plugin::Feature& feature, std::string& key, PyObject* pyValue) const
|
fazekasgy@37
|
1034 {
|
fazekasgy@37
|
1035 bool found = true;
|
fazekasgy@37
|
1036 switch (ffKeys[key])
|
fazekasgy@37
|
1037 {
|
fazekasgy@37
|
1038 case unknown :
|
fazekasgy@37
|
1039 setValueError("Unknown key in Vamp Feature",m_strict);
|
fazekasgy@37
|
1040 cerr << "Unknown key in Vamp Feature: " << key << endl;
|
fazekasgy@37
|
1041 found = false;
|
fazekasgy@37
|
1042 break;
|
fazekasgy@37
|
1043 case hasTimestamp:
|
fazekasgy@37
|
1044 _convert(pyValue,feature.hasTimestamp);
|
fazekasgy@37
|
1045 break;
|
fazekasgy@37
|
1046 case timestamp:
|
fazekasgy@37
|
1047 _convert(pyValue,feature.timestamp);
|
fazekasgy@37
|
1048 break;
|
fazekasgy@37
|
1049 case hasDuration:
|
fazekasgy@37
|
1050 _convert(pyValue,feature.hasDuration);
|
fazekasgy@37
|
1051 break;
|
fazekasgy@37
|
1052 case duration:
|
fazekasgy@37
|
1053 _convert(pyValue,feature.duration);
|
fazekasgy@37
|
1054 break;
|
fazekasgy@37
|
1055 case values:
|
fazekasgy@37
|
1056 _convert(pyValue,feature.values);
|
fazekasgy@37
|
1057 break;
|
fazekasgy@37
|
1058 case label:
|
fazekasgy@37
|
1059 _convert(pyValue,feature.label);
|
fazekasgy@37
|
1060 break;
|
fazekasgy@37
|
1061 default:
|
fazekasgy@37
|
1062 setValueError("Unknown key in Vamp Feature",m_strict);
|
fazekasgy@37
|
1063 found = false;
|
fazekasgy@37
|
1064 }
|
fazekasgy@37
|
1065 return found;
|
fazekasgy@37
|
1066 }
|
fazekasgy@37
|
1067
|
fazekasgy@37
|
1068
|
fazekasgy@37
|
1069 /* Error handling */
|
fazekasgy@37
|
1070
|
fazekasgy@37
|
1071 void
|
fazekasgy@37
|
1072 PyTypeInterface::setValueError (std::string message, bool strict) const
|
fazekasgy@37
|
1073 {
|
fazekasgy@37
|
1074 m_error = true;
|
fazekasgy@37
|
1075 m_errorQueue.push(ValueError(message,strict));
|
fazekasgy@37
|
1076 }
|
fazekasgy@37
|
1077
|
fazekasgy@37
|
1078 /// return a reference to the last error or creates a new one.
|
fazekasgy@37
|
1079 PyTypeInterface::ValueError&
|
fazekasgy@37
|
1080 PyTypeInterface::lastError() const
|
fazekasgy@37
|
1081 {
|
fazekasgy@37
|
1082 m_error = false;
|
fazekasgy@37
|
1083 if (!m_errorQueue.empty()) return m_errorQueue.back();
|
fazekasgy@37
|
1084 else {
|
fazekasgy@37
|
1085 m_errorQueue.push(ValueError("Type conversion error.",m_strict));
|
fazekasgy@37
|
1086 return m_errorQueue.back();
|
fazekasgy@37
|
1087 }
|
fazekasgy@37
|
1088 }
|
fazekasgy@37
|
1089
|
fazekasgy@37
|
1090 /// helper function to iterate over the error message queue:
|
fazekasgy@37
|
1091 /// pops the oldest item
|
fazekasgy@37
|
1092 PyTypeInterface::ValueError
|
fazekasgy@37
|
1093 PyTypeInterface::getError() const
|
fazekasgy@37
|
1094 {
|
fazekasgy@37
|
1095 if (!m_errorQueue.empty()) {
|
fazekasgy@37
|
1096 PyTypeInterface::ValueError e = m_errorQueue.front();
|
fazekasgy@37
|
1097 m_errorQueue.pop();
|
fazekasgy@37
|
1098 if (m_errorQueue.empty()) m_error = false;
|
fazekasgy@37
|
1099 return e;
|
fazekasgy@37
|
1100 }
|
fazekasgy@37
|
1101 else {
|
fazekasgy@37
|
1102 m_error = false;
|
fazekasgy@37
|
1103 return PyTypeInterface::ValueError();
|
fazekasgy@37
|
1104 }
|
fazekasgy@37
|
1105 }
|
fazekasgy@37
|
1106
|
fazekasgy@37
|
1107 /* Utilities */
|
fazekasgy@37
|
1108
|
fazekasgy@37
|
1109 /// get the type name of an object
|
fazekasgy@37
|
1110 std::string
|
fazekasgy@37
|
1111 PyTypeInterface::PyValue_Get_TypeName(PyObject* pyValue) const
|
fazekasgy@37
|
1112 {
|
fazekasgy@37
|
1113 PyObject *pyType = PyObject_Type(pyValue);
|
fazekasgy@37
|
1114 if (!pyType)
|
fazekasgy@37
|
1115 {
|
fazekasgy@37
|
1116 cerr << "Warning: Object type name could not be found." << endl;
|
fazekasgy@37
|
1117 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
1118 return std::string ("< unknown type >");
|
fazekasgy@37
|
1119 }
|
fazekasgy@37
|
1120 PyObject *pyString = PyObject_Str(pyType);
|
fazekasgy@37
|
1121 if (!pyString)
|
fazekasgy@37
|
1122 {
|
fazekasgy@37
|
1123 cerr << "Warning: Object type name could not be found." << endl;
|
fazekasgy@37
|
1124 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
1125 Py_CLEAR(pyType);
|
fazekasgy@37
|
1126 return std::string ("< unknown type >");
|
fazekasgy@37
|
1127 }
|
fazekasgy@37
|
1128 char *cstr = PyString_AS_STRING(pyString);
|
fazekasgy@37
|
1129 if (!cstr)
|
fazekasgy@37
|
1130 {
|
fazekasgy@37
|
1131 cerr << "Warning: Object type name could not be found." << endl;
|
fazekasgy@37
|
1132 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@37
|
1133 Py_DECREF(pyType);
|
fazekasgy@37
|
1134 Py_CLEAR(pyString);
|
fazekasgy@37
|
1135 return std::string("< unknown type >");
|
fazekasgy@37
|
1136 }
|
fazekasgy@37
|
1137 Py_DECREF(pyType);
|
fazekasgy@37
|
1138 Py_DECREF(pyString);
|
fazekasgy@37
|
1139 return std::string(cstr);
|
fazekasgy@37
|
1140
|
fazekasgy@37
|
1141 }
|
fazekasgy@37
|
1142
|
fazekasgy@37
|
1143 bool
|
fazekasgy@37
|
1144 PyTypeInterface::initMaps() const
|
fazekasgy@37
|
1145 {
|
fazekasgy@37
|
1146
|
fazekasgy@37
|
1147 if (isMapInitialised) return true;
|
fazekasgy@37
|
1148
|
fazekasgy@37
|
1149 outKeys["identifier"] = o::identifier;
|
fazekasgy@37
|
1150 outKeys["name"] = o::name;
|
fazekasgy@37
|
1151 outKeys["description"] = o::description;
|
fazekasgy@37
|
1152 outKeys["unit"] = o::unit;
|
fazekasgy@37
|
1153 outKeys["hasFixedBinCount"] = o::hasFixedBinCount;
|
fazekasgy@37
|
1154 outKeys["binCount"] = o::binCount;
|
fazekasgy@37
|
1155 outKeys["binNames"] = o::binNames;
|
fazekasgy@37
|
1156 outKeys["hasKnownExtents"] = o::hasKnownExtents;
|
fazekasgy@37
|
1157 outKeys["minValue"] = o::minValue;
|
fazekasgy@37
|
1158 outKeys["maxValue"] = o::maxValue;
|
fazekasgy@37
|
1159 outKeys["isQuantized"] = o::isQuantized;
|
fazekasgy@37
|
1160 outKeys["quantizeStep"] = o::quantizeStep;
|
fazekasgy@37
|
1161 outKeys["sampleType"] = o::sampleType;
|
fazekasgy@37
|
1162 outKeys["sampleRate"] = o::sampleRate;
|
fazekasgy@37
|
1163 outKeys["hasDuration"] = o::hasDuration;
|
fazekasgy@37
|
1164
|
fazekasgy@37
|
1165 sampleKeys["OneSamplePerStep"] = OneSamplePerStep;
|
fazekasgy@37
|
1166 sampleKeys["FixedSampleRate"] = FixedSampleRate;
|
fazekasgy@37
|
1167 sampleKeys["VariableSampleRate"] = VariableSampleRate;
|
fazekasgy@37
|
1168
|
fazekasgy@37
|
1169 ffKeys["hasTimestamp"] = hasTimestamp;
|
fazekasgy@37
|
1170 ffKeys["timestamp"] = timestamp; // this is the correct one
|
fazekasgy@37
|
1171 ffKeys["timeStamp"] = timestamp; // backward compatible
|
fazekasgy@37
|
1172 ffKeys["hasDuration"] = hasDuration;
|
fazekasgy@37
|
1173 ffKeys["duration"] = duration;
|
fazekasgy@37
|
1174 ffKeys["values"] = values;
|
fazekasgy@37
|
1175 ffKeys["label"] = label;
|
fazekasgy@37
|
1176
|
fazekasgy@37
|
1177 parmKeys["identifier"] = p::identifier;
|
fazekasgy@37
|
1178 parmKeys["name"] = p::name;
|
fazekasgy@37
|
1179 parmKeys["description"] = p::description;
|
fazekasgy@37
|
1180 parmKeys["unit"] = p::unit;
|
fazekasgy@37
|
1181 parmKeys["minValue"] = p::minValue;
|
fazekasgy@37
|
1182 parmKeys["maxValue"] = p::maxValue;
|
fazekasgy@37
|
1183 parmKeys["defaultValue"] = p::defaultValue;
|
fazekasgy@37
|
1184 parmKeys["isQuantized"] = p::isQuantized;
|
fazekasgy@37
|
1185 parmKeys["quantizeStep"] = p::quantizeStep;
|
gyorgyf@62
|
1186 parmKeys["valueNames"] = p::valueNames;
|
fazekasgy@37
|
1187
|
fazekasgy@37
|
1188 isMapInitialised = true;
|
fazekasgy@37
|
1189 return true;
|
fazekasgy@37
|
1190 }
|