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