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