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