fazekasgy@31
|
1 /*
|
fazekasgy@31
|
2 */
|
fazekasgy@31
|
3
|
fazekasgy@31
|
4 #include <Python.h>
|
fazekasgy@31
|
5 #include "PyTypeInterface.h"
|
fazekasgy@31
|
6 #include "PyRealTime.h"
|
fazekasgy@31
|
7 #include "PyExtensionModule.h"
|
fazekasgy@31
|
8 #include <math.h>
|
fazekasgy@31
|
9 #include <float.h>
|
fazekasgy@31
|
10 #include <limits.h>
|
fazekasgy@31
|
11 #ifndef SIZE_T_MAX
|
fazekasgy@31
|
12 #define (SIZE_T_MAX (size_t) -1)
|
fazekasgy@31
|
13 #endif
|
fazekasgy@31
|
14
|
fazekasgy@31
|
15 using std::string;
|
fazekasgy@31
|
16 using std::vector;
|
fazekasgy@31
|
17 using std::cerr;
|
fazekasgy@31
|
18 using std::endl;
|
fazekasgy@31
|
19 using std::map;
|
fazekasgy@31
|
20
|
fazekasgy@31
|
21 static std::map<std::string, o::eOutDescriptors> outKeys;
|
fazekasgy@31
|
22 static std::map<std::string, p::eParmDescriptors> parmKeys;
|
fazekasgy@31
|
23 static std::map<std::string, eSampleTypes> sampleKeys;
|
fazekasgy@31
|
24 static std::map<std::string, eFeatureFields> ffKeys;
|
fazekasgy@31
|
25 static bool isMapInitialised = false;
|
fazekasgy@31
|
26
|
fazekasgy@31
|
27 /* Note: NO FUNCTION IN THIS CLASS SHOULD ALTER REFERENCE COUNTS
|
fazekasgy@31
|
28 (EXCEPT FOR TEMPORARY PYOBJECTS)! */
|
fazekasgy@31
|
29
|
fazekasgy@31
|
30 PyTypeInterface::PyTypeInterface() :
|
fazekasgy@31
|
31 m_strict(false),
|
fazekasgy@31
|
32 m_error(false),
|
fazekasgy@31
|
33 m_lastError(m_noError),
|
fazekasgy@31
|
34 error(m_error)
|
fazekasgy@31
|
35 {
|
fazekasgy@31
|
36 }
|
fazekasgy@31
|
37
|
fazekasgy@31
|
38 PyTypeInterface::~PyTypeInterface()
|
fazekasgy@31
|
39 {
|
fazekasgy@31
|
40 }
|
fazekasgy@31
|
41
|
fazekasgy@31
|
42 /// floating point numbers (TODO: check numpy.float128)
|
fazekasgy@31
|
43 float
|
fazekasgy@31
|
44 PyTypeInterface::PyValue_To_Float(PyObject* pyValue) const
|
fazekasgy@31
|
45 {
|
fazekasgy@31
|
46 // convert float
|
fazekasgy@31
|
47 if (PyFloat_Check(pyValue))
|
fazekasgy@31
|
48 {
|
fazekasgy@31
|
49 float rValue = (float) PyFloat_AS_DOUBLE(pyValue);
|
fazekasgy@31
|
50 if (PyErr_Occurred())
|
fazekasgy@31
|
51 {
|
fazekasgy@31
|
52 PyErr_Print(); PyErr_Clear();
|
fazekasgy@31
|
53 setValueError("Error while converting float object.",m_strict);
|
fazekasgy@31
|
54 return 0.0;
|
fazekasgy@31
|
55 }
|
fazekasgy@31
|
56 return rValue;
|
fazekasgy@31
|
57 }
|
fazekasgy@31
|
58
|
fazekasgy@31
|
59 // in strict mode we will not try harder
|
fazekasgy@31
|
60 if (m_strict) {
|
fazekasgy@31
|
61 setValueError("Strict conversion error: object is not float.",m_strict);
|
fazekasgy@31
|
62 return 0.0;
|
fazekasgy@31
|
63 }
|
fazekasgy@31
|
64
|
fazekasgy@31
|
65 // convert other objects supporting the number protocol
|
fazekasgy@31
|
66 if (PyNumber_Check(pyValue))
|
fazekasgy@31
|
67 {
|
fazekasgy@31
|
68 // PEP353: Py_ssize_t is size_t but signed !
|
fazekasgy@31
|
69 // This will work up to numpy.float64
|
fazekasgy@31
|
70 Py_ssize_t rValue = PyNumber_AsSsize_t(pyValue,NULL);
|
fazekasgy@31
|
71 if (PyErr_Occurred())
|
fazekasgy@31
|
72 {
|
fazekasgy@31
|
73 PyErr_Print(); PyErr_Clear();
|
fazekasgy@31
|
74 setValueError("Error while converting integer object.",m_strict);
|
fazekasgy@31
|
75 return 0.0;
|
fazekasgy@31
|
76 }
|
fazekasgy@31
|
77 if (rValue > FLT_MAX || rValue < FLT_MIN)
|
fazekasgy@31
|
78 {
|
fazekasgy@31
|
79 setValueError("Overflow error. Object can not be converted to float.",m_strict);
|
fazekasgy@31
|
80 return 0.0;
|
fazekasgy@31
|
81 }
|
fazekasgy@31
|
82 return (float) rValue;
|
fazekasgy@31
|
83 }
|
fazekasgy@31
|
84
|
fazekasgy@31
|
85 // convert string
|
fazekasgy@31
|
86 if (PyString_Check(pyValue))
|
fazekasgy@31
|
87 {
|
fazekasgy@31
|
88 PyObject* pyFloat = PyFloat_FromString(pyValue,NULL);
|
fazekasgy@31
|
89 if (!pyFloat)
|
fazekasgy@31
|
90 {
|
fazekasgy@31
|
91 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@31
|
92 setValueError("String value can not be converted to float.",m_strict);
|
fazekasgy@31
|
93 return 0.0;
|
fazekasgy@31
|
94 }
|
fazekasgy@31
|
95 float rValue = (float) PyFloat_AS_DOUBLE(pyFloat);
|
fazekasgy@31
|
96 if (PyErr_Occurred())
|
fazekasgy@31
|
97 {
|
fazekasgy@31
|
98 PyErr_Print(); PyErr_Clear();
|
fazekasgy@31
|
99 Py_CLEAR(pyFloat);
|
fazekasgy@31
|
100 setValueError("Error while converting float object.",m_strict);
|
fazekasgy@31
|
101 return 0.0;
|
fazekasgy@31
|
102 }
|
fazekasgy@31
|
103 Py_DECREF(pyFloat);
|
fazekasgy@31
|
104 return rValue;
|
fazekasgy@31
|
105 }
|
fazekasgy@31
|
106
|
fazekasgy@31
|
107 // convert the first element of any iterable sequence (for convenience and backwards compatibility)
|
fazekasgy@31
|
108 if (PySequence_Check(pyValue) and PySequence_Size(pyValue) > 0)
|
fazekasgy@31
|
109 {
|
fazekasgy@31
|
110 PyObject* item = PySequence_GetItem(pyValue,0);
|
fazekasgy@31
|
111 if (item)
|
fazekasgy@31
|
112 {
|
fazekasgy@31
|
113 float rValue = this->PyValue_To_Float(item);
|
fazekasgy@31
|
114 if (!m_error) {
|
fazekasgy@31
|
115 Py_DECREF(item);
|
fazekasgy@31
|
116 return rValue;
|
fazekasgy@31
|
117 } else {
|
fazekasgy@31
|
118 Py_CLEAR(item);
|
fazekasgy@31
|
119 std::string msg = "Could not convert sequence element. " + lastError().message;
|
fazekasgy@31
|
120 setValueError(msg,m_strict);
|
fazekasgy@31
|
121 return 0.0;
|
fazekasgy@31
|
122 }
|
fazekasgy@31
|
123 }
|
fazekasgy@31
|
124 }
|
fazekasgy@31
|
125
|
fazekasgy@31
|
126 // give up
|
fazekasgy@31
|
127 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@31
|
128 std::string msg = "Conversion from " + PyValue_Get_TypeName(pyValue) + " to float is not possible.";
|
fazekasgy@31
|
129 setValueError(msg,m_strict);
|
fazekasgy@31
|
130 return 0.0;
|
fazekasgy@31
|
131 }
|
fazekasgy@31
|
132
|
fazekasgy@31
|
133 /// size_t (unsigned integer types)
|
fazekasgy@31
|
134 size_t
|
fazekasgy@31
|
135 PyTypeInterface::PyValue_To_Size_t(PyObject* pyValue) const
|
fazekasgy@31
|
136 {
|
fazekasgy@31
|
137 // convert objects supporting the number protocol
|
fazekasgy@31
|
138 if (PyNumber_Check(pyValue))
|
fazekasgy@31
|
139 {
|
fazekasgy@31
|
140 if (m_strict && !PyInt_Check(pyValue) && !PyLong_Check(pyValue))
|
fazekasgy@31
|
141 setValueError("Strict conversion error: object is not integer type.",m_strict);
|
fazekasgy@31
|
142 // Note: this function handles Bool,Int,Long,Float
|
fazekasgy@31
|
143 // PEP353: Py_ssize_t is size_t but signed !
|
fazekasgy@31
|
144 Py_ssize_t rValue = PyInt_AsSsize_t(pyValue);
|
fazekasgy@31
|
145 if (PyErr_Occurred())
|
fazekasgy@31
|
146 {
|
fazekasgy@31
|
147 PyErr_Print(); PyErr_Clear();
|
fazekasgy@31
|
148 setValueError("Error while converting integer object.",m_strict);
|
fazekasgy@31
|
149 return 0;
|
fazekasgy@31
|
150 }
|
fazekasgy@31
|
151 if ((unsigned long)rValue > SIZE_T_MAX || (unsigned long)rValue < 0)
|
fazekasgy@31
|
152 {
|
fazekasgy@31
|
153 setValueError("Overflow error. Object can not be converted to size_t.",m_strict);
|
fazekasgy@31
|
154 return 0;
|
fazekasgy@31
|
155 }
|
fazekasgy@31
|
156 return (size_t) rValue;
|
fazekasgy@31
|
157 }
|
fazekasgy@31
|
158
|
fazekasgy@31
|
159 // in strict mode we will not try harder and throw an exception
|
fazekasgy@31
|
160 // then the caller should decide what to do with it
|
fazekasgy@31
|
161 if (m_strict) {
|
fazekasgy@31
|
162 setValueError("Strict conversion error: object is not integer.",m_strict);
|
fazekasgy@31
|
163 return 0;
|
fazekasgy@31
|
164 }
|
fazekasgy@31
|
165
|
fazekasgy@31
|
166 // convert string
|
fazekasgy@31
|
167 if (PyString_Check(pyValue))
|
fazekasgy@31
|
168 {
|
fazekasgy@31
|
169 PyObject* pyLong = PyNumber_Long(pyValue);
|
fazekasgy@31
|
170 if (!pyLong)
|
fazekasgy@31
|
171 {
|
fazekasgy@31
|
172 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@31
|
173 setValueError("String object can not be converted to size_t.",m_strict);
|
fazekasgy@31
|
174 return 0;
|
fazekasgy@31
|
175 }
|
fazekasgy@31
|
176 size_t rValue = this->PyValue_To_Size_t(pyLong);
|
fazekasgy@31
|
177 if (!m_error) {
|
fazekasgy@31
|
178 Py_DECREF(pyLong);
|
fazekasgy@31
|
179 return rValue;
|
fazekasgy@31
|
180 } else {
|
fazekasgy@31
|
181 Py_CLEAR(pyLong);
|
fazekasgy@31
|
182 setValueError (lastError().message,m_strict);
|
fazekasgy@31
|
183 return 0;
|
fazekasgy@31
|
184 }
|
fazekasgy@31
|
185 }
|
fazekasgy@31
|
186
|
fazekasgy@31
|
187 // convert the first element of iterable sequences
|
fazekasgy@31
|
188 if (PySequence_Check(pyValue) and PySequence_Size(pyValue) > 0)
|
fazekasgy@31
|
189 {
|
fazekasgy@31
|
190 PyObject* item = PySequence_GetItem(pyValue,0);
|
fazekasgy@31
|
191 if (item)
|
fazekasgy@31
|
192 {
|
fazekasgy@31
|
193 size_t rValue = this->PyValue_To_Size_t(item);
|
fazekasgy@31
|
194 if (!m_error) {
|
fazekasgy@31
|
195 Py_DECREF(item);
|
fazekasgy@31
|
196 return rValue;
|
fazekasgy@31
|
197 } else {
|
fazekasgy@31
|
198 Py_CLEAR(item);
|
fazekasgy@31
|
199 std::string msg = "Could not convert sequence element. " + lastError().message;
|
fazekasgy@31
|
200 setValueError(msg,m_strict);
|
fazekasgy@31
|
201 return 0;
|
fazekasgy@31
|
202 }
|
fazekasgy@31
|
203 }
|
fazekasgy@31
|
204 }
|
fazekasgy@31
|
205
|
fazekasgy@31
|
206 // give up
|
fazekasgy@31
|
207 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@31
|
208 std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to size_t is not possible.";
|
fazekasgy@31
|
209 setValueError(msg,m_strict);
|
fazekasgy@31
|
210 return 0;
|
fazekasgy@31
|
211 }
|
fazekasgy@31
|
212
|
fazekasgy@31
|
213 bool
|
fazekasgy@31
|
214 PyTypeInterface::PyValue_To_Bool(PyObject* pyValue) const
|
fazekasgy@31
|
215 {
|
fazekasgy@31
|
216 // convert objects supporting the number protocol
|
fazekasgy@31
|
217 // Note: PyBool is a subclass of PyInt
|
fazekasgy@31
|
218 if (PyNumber_Check(pyValue))
|
fazekasgy@31
|
219 {
|
fazekasgy@31
|
220 if (m_strict && !PyBool_Check(pyValue))
|
fazekasgy@31
|
221 setValueError
|
fazekasgy@31
|
222 ("Strict conversion error: object is not boolean type.",m_strict);
|
fazekasgy@31
|
223
|
fazekasgy@31
|
224 // Note: this function handles Bool,Int,Long,Float
|
fazekasgy@31
|
225 Py_ssize_t rValue = PyInt_AsSsize_t(pyValue);
|
fazekasgy@31
|
226 if (PyErr_Occurred())
|
fazekasgy@31
|
227 {
|
fazekasgy@31
|
228 PyErr_Print(); PyErr_Clear();
|
fazekasgy@31
|
229 setValueError ("Error while converting boolean object.",m_strict);
|
fazekasgy@31
|
230 }
|
fazekasgy@31
|
231 if (rValue != 1 && rValue != 0)
|
fazekasgy@31
|
232 {
|
fazekasgy@31
|
233 setValueError ("Overflow error. Object can not be converted to boolean.",m_strict);
|
fazekasgy@31
|
234 }
|
fazekasgy@31
|
235 return (bool) rValue;
|
fazekasgy@31
|
236 }
|
fazekasgy@31
|
237
|
fazekasgy@31
|
238 if (m_strict) {
|
fazekasgy@31
|
239 setValueError ("Strict conversion error: object is not numerical type.",m_strict);
|
fazekasgy@31
|
240 return false;
|
fazekasgy@31
|
241 }
|
fazekasgy@31
|
242
|
fazekasgy@31
|
243 // convert iterables: the rule is the same as of the interpreter:
|
fazekasgy@31
|
244 // empty sequence evaluates to False, anything else is True
|
fazekasgy@31
|
245 if (PySequence_Check(pyValue))
|
fazekasgy@31
|
246 {
|
fazekasgy@31
|
247 return PySequence_Size(pyValue)?true:false;
|
fazekasgy@31
|
248 }
|
fazekasgy@31
|
249
|
fazekasgy@31
|
250 // give up
|
fazekasgy@31
|
251 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@31
|
252 std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to boolean is not possible.";
|
fazekasgy@31
|
253 setValueError(msg,m_strict);
|
fazekasgy@31
|
254 return false;
|
fazekasgy@31
|
255 }
|
fazekasgy@31
|
256
|
fazekasgy@31
|
257 /// string and objects that support .__str__() (TODO: check unicode objects)
|
fazekasgy@31
|
258 std::string
|
fazekasgy@31
|
259 PyTypeInterface::PyValue_To_String(PyObject* pyValue) const
|
fazekasgy@31
|
260 {
|
fazekasgy@31
|
261 // convert string
|
fazekasgy@31
|
262 if (PyString_Check(pyValue))
|
fazekasgy@31
|
263 {
|
fazekasgy@31
|
264 char *cstr = PyString_AS_STRING(pyValue);
|
fazekasgy@31
|
265 if (!cstr)
|
fazekasgy@31
|
266 {
|
fazekasgy@31
|
267 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@31
|
268 setValueError("Error while converting string object.",m_strict);
|
fazekasgy@31
|
269 return std::string();
|
fazekasgy@31
|
270 }
|
fazekasgy@31
|
271 return std::string(cstr);
|
fazekasgy@31
|
272 }
|
fazekasgy@31
|
273 // TODO: deal with unicode here (argh!)
|
fazekasgy@31
|
274
|
fazekasgy@31
|
275 // in strict mode we will not try harder
|
fazekasgy@31
|
276 if (m_strict) {
|
fazekasgy@31
|
277 setValueError("Strict conversion error: object is not string.",m_strict);
|
fazekasgy@31
|
278 return std::string();
|
fazekasgy@31
|
279 }
|
fazekasgy@31
|
280
|
fazekasgy@31
|
281 // convert list or tuple: empty lists are turned into empty strings
|
fazekasgy@31
|
282 if (PyList_Check(pyValue) || PyTuple_Check(pyValue))
|
fazekasgy@31
|
283 {
|
fazekasgy@31
|
284 if (!PySequence_Size(pyValue)) return std::string();
|
fazekasgy@31
|
285 PyObject* item = PySequence_GetItem(pyValue,0);
|
fazekasgy@31
|
286 if (item)
|
fazekasgy@31
|
287 {
|
fazekasgy@31
|
288 std::string rValue = this->PyValue_To_String(item);
|
fazekasgy@31
|
289 if (m_error) {
|
fazekasgy@31
|
290 Py_DECREF(item);
|
fazekasgy@31
|
291 return rValue;
|
fazekasgy@31
|
292 } else {
|
fazekasgy@31
|
293 Py_CLEAR(item);
|
fazekasgy@31
|
294 std::string msg = "Could not convert sequence element. " + lastError().message;
|
fazekasgy@31
|
295 setValueError(msg,m_strict);
|
fazekasgy@31
|
296 return std::string();
|
fazekasgy@31
|
297 }
|
fazekasgy@31
|
298 }
|
fazekasgy@31
|
299 }
|
fazekasgy@31
|
300
|
fazekasgy@31
|
301 // convert any other object that has .__str__() or .__repr__()
|
fazekasgy@31
|
302 PyObject* pyString = PyObject_Str(pyValue);
|
fazekasgy@31
|
303 if (pyString && !PyErr_Occurred())
|
fazekasgy@31
|
304 {
|
fazekasgy@31
|
305 std::string rValue = this->PyValue_To_String(pyString);
|
fazekasgy@31
|
306 if (m_error) {
|
fazekasgy@31
|
307 Py_DECREF(pyString);
|
fazekasgy@31
|
308 return rValue;
|
fazekasgy@31
|
309 } else {
|
fazekasgy@31
|
310 Py_CLEAR(pyString);
|
fazekasgy@31
|
311 std::string msg = "Object " + this->PyValue_Get_TypeName(pyValue) +" can not be represented as string. " + lastError().message;
|
fazekasgy@31
|
312 setValueError (msg,m_strict);
|
fazekasgy@31
|
313 return std::string();
|
fazekasgy@31
|
314 }
|
fazekasgy@31
|
315 }
|
fazekasgy@31
|
316
|
fazekasgy@31
|
317 // give up
|
fazekasgy@31
|
318 PyErr_Print(); PyErr_Clear();
|
fazekasgy@31
|
319 std::string msg = "Conversion from " + this->PyValue_Get_TypeName(pyValue) + " to string is not possible.";
|
fazekasgy@31
|
320 setValueError(msg,m_strict);
|
fazekasgy@31
|
321 return std::string();
|
fazekasgy@31
|
322 }
|
fazekasgy@31
|
323
|
fazekasgy@31
|
324 /* C Values to Py Values */
|
fazekasgy@31
|
325
|
fazekasgy@31
|
326
|
fazekasgy@31
|
327 PyObject*
|
fazekasgy@31
|
328 PyTypeInterface::PyValue_From_CValue(const char* cValue) const
|
fazekasgy@31
|
329 {
|
fazekasgy@31
|
330 // returns new reference
|
fazekasgy@31
|
331 if (!cValue)
|
fazekasgy@31
|
332 setValueError("Invalid pointer encountered while converting from char* .",m_strict);
|
fazekasgy@31
|
333 PyObject *pyValue = PyString_FromString(cValue);
|
fazekasgy@31
|
334 if (!pyValue)
|
fazekasgy@31
|
335 {
|
fazekasgy@31
|
336 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@31
|
337 setValueError("Error while converting from char* or string.",m_strict);
|
fazekasgy@31
|
338 return NULL;
|
fazekasgy@31
|
339 }
|
fazekasgy@31
|
340 return pyValue;
|
fazekasgy@31
|
341 }
|
fazekasgy@31
|
342
|
fazekasgy@31
|
343 PyObject*
|
fazekasgy@31
|
344 PyTypeInterface::PyValue_From_CValue(size_t cValue) const
|
fazekasgy@31
|
345 {
|
fazekasgy@31
|
346 // returns new reference
|
fazekasgy@31
|
347 PyObject *pyValue = PyInt_FromSsize_t((Py_ssize_t)cValue);
|
fazekasgy@31
|
348 if (!pyValue)
|
fazekasgy@31
|
349 {
|
fazekasgy@31
|
350 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@31
|
351 setValueError("Error while converting from size_t.",m_strict);
|
fazekasgy@31
|
352 return NULL;
|
fazekasgy@31
|
353 }
|
fazekasgy@31
|
354 return pyValue;
|
fazekasgy@31
|
355 }
|
fazekasgy@31
|
356
|
fazekasgy@31
|
357 PyObject*
|
fazekasgy@31
|
358 PyTypeInterface::PyValue_From_CValue(double cValue) const
|
fazekasgy@31
|
359 {
|
fazekasgy@31
|
360 // returns new reference
|
fazekasgy@31
|
361 PyObject *pyValue = PyFloat_FromDouble(cValue);
|
fazekasgy@31
|
362 if (!pyValue)
|
fazekasgy@31
|
363 {
|
fazekasgy@31
|
364 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@31
|
365 setValueError("Error while converting from float or double.",m_strict);
|
fazekasgy@31
|
366 return NULL;
|
fazekasgy@31
|
367 }
|
fazekasgy@31
|
368 return pyValue;
|
fazekasgy@31
|
369 }
|
fazekasgy@31
|
370
|
fazekasgy@31
|
371 PyObject*
|
fazekasgy@31
|
372 PyTypeInterface::PyValue_From_CValue(bool cValue) const
|
fazekasgy@31
|
373 {
|
fazekasgy@31
|
374 // returns new reference
|
fazekasgy@31
|
375 PyObject *pyValue = PyBool_FromLong((long)cValue);
|
fazekasgy@31
|
376 if (!pyValue)
|
fazekasgy@31
|
377 {
|
fazekasgy@31
|
378 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@31
|
379 setValueError("Error while converting from bool.",m_strict);
|
fazekasgy@31
|
380 return NULL;
|
fazekasgy@31
|
381 }
|
fazekasgy@31
|
382 return pyValue;
|
fazekasgy@31
|
383 }
|
fazekasgy@31
|
384
|
fazekasgy@31
|
385
|
fazekasgy@31
|
386 /* Sequence Types to C++ Types */
|
fazekasgy@31
|
387
|
fazekasgy@31
|
388 //convert Python list to C++ vector of strings
|
fazekasgy@31
|
389 std::vector<std::string>
|
fazekasgy@31
|
390 PyTypeInterface::PyValue_To_StringVector (PyObject *inputList) const
|
fazekasgy@31
|
391 {
|
fazekasgy@31
|
392
|
fazekasgy@31
|
393 std::vector<std::string> Output;
|
fazekasgy@31
|
394 std::string ListElement;
|
fazekasgy@31
|
395 PyObject *pyString = NULL;
|
fazekasgy@31
|
396
|
fazekasgy@31
|
397 if (!PyList_Check(inputList)) return Output;
|
fazekasgy@31
|
398
|
fazekasgy@31
|
399 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(inputList); ++i) {
|
fazekasgy@31
|
400 //Get next list item (Borrowed Reference)
|
fazekasgy@31
|
401 pyString = PyList_GET_ITEM(inputList,i);
|
fazekasgy@31
|
402 ListElement = (string) PyString_AsString(PyObject_Str(pyString));
|
fazekasgy@31
|
403 Output.push_back(ListElement);
|
fazekasgy@31
|
404 }
|
fazekasgy@31
|
405 return Output;
|
fazekasgy@31
|
406 }
|
fazekasgy@31
|
407
|
fazekasgy@31
|
408 //convert Python list to C++ vector of floats
|
fazekasgy@31
|
409 std::vector<float>
|
fazekasgy@31
|
410 PyTypeInterface::PyValue_To_FloatVector (PyObject *inputList) const
|
fazekasgy@31
|
411 {
|
fazekasgy@31
|
412 typedef std::vector<float> floatVector;
|
fazekasgy@31
|
413 std::vector<float> Output;
|
fazekasgy@31
|
414
|
fazekasgy@31
|
415 /// Check for NumPy Array
|
fazekasgy@31
|
416 if (PyObject_HasAttrString(inputList,"__array_struct__")) {
|
fazekasgy@31
|
417 int vectorLength;
|
fazekasgy@31
|
418 float *dataptr = getNumPyObjectData(inputList,vectorLength);
|
fazekasgy@31
|
419 if (dataptr != 0) cerr << "Numpy array found: " << vectorLength << endl;
|
fazekasgy@31
|
420 // Output = *dataptr;
|
fazekasgy@31
|
421 }
|
fazekasgy@31
|
422
|
fazekasgy@31
|
423 float ListElement;
|
fazekasgy@31
|
424 PyObject *pyFloat = NULL;
|
fazekasgy@31
|
425
|
fazekasgy@31
|
426 if (!PyList_Check(inputList)) return Output;
|
fazekasgy@31
|
427
|
fazekasgy@31
|
428 for (Py_ssize_t k = 0; k < PyList_GET_SIZE(inputList); ++k) {
|
fazekasgy@31
|
429 //Get next list item (Borrowed Reference)
|
fazekasgy@31
|
430 pyFloat = PyList_GET_ITEM(inputList,k);
|
fazekasgy@31
|
431 ListElement = (float) PyFloat_AS_DOUBLE(pyFloat);
|
fazekasgy@31
|
432 #ifdef _DEBUG
|
fazekasgy@31
|
433 cerr << "value: " << ListElement << endl;
|
fazekasgy@31
|
434 #endif
|
fazekasgy@31
|
435 Output.push_back(ListElement);
|
fazekasgy@31
|
436 }
|
fazekasgy@31
|
437
|
fazekasgy@31
|
438 return Output;
|
fazekasgy@31
|
439 }
|
fazekasgy@31
|
440
|
fazekasgy@31
|
441
|
fazekasgy@31
|
442 /* Vamp API Specific Types
|
fazekasgy@31
|
443
|
fazekasgy@31
|
444 Vamp::Plugin::OutputList
|
fazekasgy@31
|
445 PyTypeInterface::PyValue_To_OutputList(PyObject* pyList) const
|
fazekasgy@31
|
446 {
|
fazekasgy@31
|
447 Vamp::Plugin::OutputList list;
|
fazekasgy@31
|
448 Vamp::Plugin::OutputDescriptor od;
|
fazekasgy@31
|
449
|
fazekasgy@31
|
450 // Type checking
|
fazekasgy@31
|
451 if (! PyList_Check(pyList) ) {
|
fazekasgy@31
|
452 Py_CLEAR(pyList);
|
fazekasgy@31
|
453 // cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@31
|
454 // << "] Expected List return type." << endl;
|
fazekasgy@31
|
455 return list;
|
fazekasgy@31
|
456 }
|
fazekasgy@31
|
457
|
fazekasgy@31
|
458 //These will all be borrowed references (no need to DECREF)
|
fazekasgy@31
|
459 PyObject *pyDict;
|
fazekasgy@31
|
460
|
fazekasgy@31
|
461 //Parse Output List
|
fazekasgy@31
|
462 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(pyList); ++i) {
|
fazekasgy@31
|
463 //Get i-th Vamp output descriptor (Borrowed Reference)
|
fazekasgy@31
|
464 pyDict = PyList_GET_ITEM(pyList,i);
|
fazekasgy@31
|
465 od = PyValue_To_OutputDescriptor(pyDict);
|
fazekasgy@31
|
466 list.push_back(od);
|
fazekasgy@31
|
467 }
|
fazekasgy@31
|
468 return list;
|
fazekasgy@31
|
469 }
|
fazekasgy@31
|
470
|
fazekasgy@31
|
471 Vamp::Plugin::ParameterList
|
fazekasgy@31
|
472 PyTypeInterface::PyValue_To_ParameterList(PyObject* pyList) const
|
fazekasgy@31
|
473 {
|
fazekasgy@31
|
474 Vamp::Plugin::ParameterList list;
|
fazekasgy@31
|
475 Vamp::Plugin::ParameterDescriptor pd;
|
fazekasgy@31
|
476
|
fazekasgy@31
|
477 // Type checking
|
fazekasgy@31
|
478 if (! PyList_Check(pyList) ) {
|
fazekasgy@31
|
479 Py_CLEAR(pyList);
|
fazekasgy@31
|
480 // cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@31
|
481 // << "] Expected List return type." << endl;
|
fazekasgy@31
|
482 return list;
|
fazekasgy@31
|
483 }
|
fazekasgy@31
|
484
|
fazekasgy@31
|
485 //These will all be borrowed references (no need to DECREF)
|
fazekasgy@31
|
486 PyObject *pyDict;
|
fazekasgy@31
|
487
|
fazekasgy@31
|
488 //Parse Output List
|
fazekasgy@31
|
489 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(pyList); ++i) {
|
fazekasgy@31
|
490 //Get i-th Vamp output descriptor (Borrowed Reference)
|
fazekasgy@31
|
491 pyDict = PyList_GET_ITEM(pyList,i);
|
fazekasgy@31
|
492 pd = PyValue_To_ParameterDescriptor(pyDict);
|
fazekasgy@31
|
493 list.push_back(pd);
|
fazekasgy@31
|
494 }
|
fazekasgy@31
|
495 return list;
|
fazekasgy@31
|
496 }
|
fazekasgy@31
|
497
|
fazekasgy@31
|
498 Vamp::Plugin::OutputDescriptor
|
fazekasgy@31
|
499 PyTypeInterface::PyValue_To_OutputDescriptor(PyObject* pyDict) const
|
fazekasgy@31
|
500 {
|
fazekasgy@31
|
501 //We only care about dictionaries holding output descriptors
|
fazekasgy@31
|
502 if (!PyDict_Check(pyDict))
|
fazekasgy@31
|
503 return Vamp::Plugin::OutputDescriptor();
|
fazekasgy@31
|
504
|
fazekasgy@31
|
505 Py_ssize_t pyPos = 0;
|
fazekasgy@31
|
506 PyObject *pyKey, *pyValue;
|
fazekasgy@31
|
507 initMaps();
|
fazekasgy@31
|
508 Vamp::Plugin::OutputDescriptor od;
|
fazekasgy@31
|
509
|
fazekasgy@31
|
510 //Python Dictionary Iterator:
|
fazekasgy@31
|
511 while (PyDict_Next(pyDict, &pyPos, &pyKey, &pyValue))
|
fazekasgy@31
|
512 {
|
fazekasgy@31
|
513 std::string key = PyValue_To_String(pyKey);
|
fazekasgy@31
|
514 SetValue(od,key,pyValue);
|
fazekasgy@31
|
515 if (m_error) {
|
fazekasgy@31
|
516 _lastError().location += "parameter: '"
|
fazekasgy@31
|
517 + key +"' descriptor: '" + od.identifier + "'";
|
fazekasgy@31
|
518 }
|
fazekasgy@31
|
519 }
|
fazekasgy@31
|
520 if (!m_errorQueue.empty()) m_error = true;
|
fazekasgy@31
|
521 return od;
|
fazekasgy@31
|
522 }
|
fazekasgy@31
|
523
|
fazekasgy@31
|
524 Vamp::Plugin::ParameterDescriptor
|
fazekasgy@31
|
525 PyTypeInterface::PyValue_To_ParameterDescriptor(PyObject* pyDict) const
|
fazekasgy@31
|
526 {
|
fazekasgy@31
|
527 //We only care about dictionaries holding output descriptors
|
fazekasgy@31
|
528 if (!PyDict_Check(pyDict))
|
fazekasgy@31
|
529 return Vamp::Plugin::ParameterDescriptor();
|
fazekasgy@31
|
530
|
fazekasgy@31
|
531 Py_ssize_t pyPos = 0;
|
fazekasgy@31
|
532 PyObject *pyKey, *pyValue;
|
fazekasgy@31
|
533 initMaps();
|
fazekasgy@31
|
534 Vamp::Plugin::ParameterDescriptor pd;
|
fazekasgy@31
|
535
|
fazekasgy@31
|
536 //Python Dictionary Iterator:
|
fazekasgy@31
|
537 while (PyDict_Next(pyDict, &pyPos, &pyKey, &pyValue))
|
fazekasgy@31
|
538 {
|
fazekasgy@31
|
539 std::string key = PyValue_To_String(pyKey);
|
fazekasgy@31
|
540 SetValue(pd,key,pyValue);
|
fazekasgy@31
|
541 if (m_error) {
|
fazekasgy@31
|
542 _lastError().location += "parameter: '"
|
fazekasgy@31
|
543 + key +"' descriptor: '" + pd.identifier + "'";
|
fazekasgy@31
|
544 }
|
fazekasgy@31
|
545 }
|
fazekasgy@31
|
546 if (!m_errorQueue.empty()) m_error = true;
|
fazekasgy@31
|
547 return pd;
|
fazekasgy@31
|
548 }
|
fazekasgy@31
|
549
|
fazekasgy@31
|
550 Vamp::Plugin::Feature
|
fazekasgy@31
|
551 PyTypeInterface::PyValue_To_Feature(PyObject* pyDict) const
|
fazekasgy@31
|
552 {
|
fazekasgy@31
|
553 //We only care about dictionaries holding output descriptors
|
fazekasgy@31
|
554 if (!PyDict_Check(pyDict))
|
fazekasgy@31
|
555 return Vamp::Plugin::Feature();
|
fazekasgy@31
|
556
|
fazekasgy@31
|
557 Py_ssize_t pyPos = 0;
|
fazekasgy@31
|
558 PyObject *pyKey, *pyValue;
|
fazekasgy@31
|
559 initMaps();
|
fazekasgy@31
|
560 Vamp::Plugin::Feature feature;
|
fazekasgy@31
|
561
|
fazekasgy@31
|
562 //Python Dictionary Iterator:
|
fazekasgy@31
|
563 while (PyDict_Next(pyDict, &pyPos, &pyKey, &pyValue))
|
fazekasgy@31
|
564 {
|
fazekasgy@31
|
565 std::string key = PyValue_To_String(pyKey);
|
fazekasgy@31
|
566 float isr = 22050.0;
|
fazekasgy@31
|
567 Feature_SetValue(feature,key,pyValue,isr);
|
fazekasgy@31
|
568 if (m_error) {
|
fazekasgy@31
|
569 _lastError().location += "key: '" + key + "'";
|
fazekasgy@31
|
570 // _lastError().location += "parameter: '"
|
fazekasgy@31
|
571 // + key +"' descriptor: '" + pd.identifier + "'";
|
fazekasgy@31
|
572 }
|
fazekasgy@31
|
573 }
|
fazekasgy@31
|
574 if (!m_errorQueue.empty()) m_error = true;
|
fazekasgy@31
|
575 return feature;
|
fazekasgy@31
|
576 }
|
fazekasgy@31
|
577 */
|
fazekasgy@31
|
578
|
fazekasgy@31
|
579 /// FeatureSet (an int map of OutputLists)
|
fazekasgy@31
|
580 Vamp::Plugin::FeatureSet
|
fazekasgy@31
|
581 PyTypeInterface::PyValue_To_FeatureSet(PyObject* pyValue) const
|
fazekasgy@31
|
582 {
|
fazekasgy@31
|
583 Vamp::Plugin::FeatureSet rFeatureSet; /// PyFeatureSet is an int map
|
fazekasgy@31
|
584 if (pyValue == NULL) {
|
fazekasgy@31
|
585 cerr << "NULL FeatureSet" << endl;
|
fazekasgy@31
|
586 return rFeatureSet;
|
fazekasgy@31
|
587 }
|
fazekasgy@31
|
588
|
fazekasgy@31
|
589 cerr << "PyValue_To_FeatureSet" << endl;
|
fazekasgy@31
|
590 //Convert PyFeatureSet
|
fazekasgy@31
|
591 if (PyFeatureSet_CheckExact(pyValue)) {
|
fazekasgy@31
|
592 cerr << "FeatureSet Return type" << endl;
|
fazekasgy@31
|
593 Py_ssize_t pyPos = 0;
|
fazekasgy@31
|
594 //Borrowed References
|
fazekasgy@31
|
595 PyObject *pyKey, *pyDictValue;
|
fazekasgy@31
|
596 int key;
|
fazekasgy@31
|
597
|
fazekasgy@31
|
598 //Python Dictionary Iterator:
|
fazekasgy@31
|
599 while (PyDict_Next(pyValue, &pyPos, &pyKey, &pyDictValue))
|
fazekasgy@31
|
600 {
|
fazekasgy@31
|
601 /// DictValue -> Vamp::FeatureList
|
fazekasgy@31
|
602 key = (int) PyInt_AS_LONG(pyKey);
|
fazekasgy@31
|
603 cerr << "FeatureSet key = " << key << endl;
|
fazekasgy@31
|
604 /// Error checking is done at value assignment
|
fazekasgy@31
|
605 PyValue_To_rValue(pyDictValue,rFeatureSet[key]);
|
fazekasgy@31
|
606 }
|
fazekasgy@31
|
607 if (!m_errorQueue.empty()) m_error = true;
|
fazekasgy@31
|
608 return rFeatureSet;
|
fazekasgy@31
|
609 }
|
fazekasgy@31
|
610 cerr << "not FeatureSet Return type" << endl;
|
fazekasgy@31
|
611
|
fazekasgy@31
|
612
|
fazekasgy@31
|
613 //Check return type
|
fazekasgy@31
|
614 if (pyValue == NULL || !PyList_Check(pyValue) ) {
|
fazekasgy@31
|
615 if (pyValue == NULL) {
|
fazekasgy@31
|
616 // cerr << "ERROR: In Python plugin [" << m_class << "::" << method << "] Unexpected result." << endl;
|
fazekasgy@31
|
617 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@31
|
618 } else {
|
fazekasgy@31
|
619 // cerr << "ERROR: In Python plugin [" << m_class << "::" << method << "] Expected List return type." << endl;
|
fazekasgy@31
|
620 }
|
fazekasgy@31
|
621 Py_CLEAR(pyValue);
|
fazekasgy@31
|
622 return Vamp::Plugin::FeatureSet();
|
fazekasgy@31
|
623 }
|
fazekasgy@31
|
624
|
fazekasgy@31
|
625 // This will be borrowed reference
|
fazekasgy@31
|
626 PyObject *pyFeatureList;
|
fazekasgy@31
|
627
|
fazekasgy@31
|
628 //Parse Output List for each element (FeatureSet)
|
fazekasgy@31
|
629 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(pyValue); ++i) {
|
fazekasgy@31
|
630 //Get i-th FeatureList (Borrowed Reference)
|
fazekasgy@31
|
631 pyFeatureList = PyList_GET_ITEM(pyValue,i);
|
fazekasgy@31
|
632 PyValue_To_rValue(pyFeatureList,rFeatureSet[i]);
|
fazekasgy@31
|
633 }
|
fazekasgy@31
|
634 // Py_CLEAR(pyOutputList);
|
fazekasgy@31
|
635 return rFeatureSet;
|
fazekasgy@31
|
636 }
|
fazekasgy@31
|
637
|
fazekasgy@31
|
638 Vamp::RealTime::RealTime
|
fazekasgy@31
|
639 PyTypeInterface::PyValue_To_RealTime(PyObject* pyValue) const
|
fazekasgy@31
|
640 {
|
fazekasgy@31
|
641 // We accept integer sample counts (for backwards compatibility)
|
fazekasgy@31
|
642 // or PyRealTime objects and convert them to Vamp::RealTime
|
fazekasgy@31
|
643
|
fazekasgy@31
|
644 if (PyRealTime_CheckExact(pyValue))
|
fazekasgy@31
|
645 {
|
fazekasgy@31
|
646 #ifdef _DEBUG
|
fazekasgy@31
|
647 cerr << "Converting from PyRealTime" << endl;
|
fazekasgy@31
|
648 #endif
|
fazekasgy@31
|
649 /// just create a copy of the wrapped object
|
fazekasgy@31
|
650 return Vamp::RealTime::RealTime(
|
fazekasgy@31
|
651 *PyRealTime_AS_REALTIME(pyValue));
|
fazekasgy@31
|
652 }
|
fazekasgy@31
|
653 // assume integer sample count
|
fazekasgy@31
|
654 long sampleCount = PyLong_AsLong(pyValue);
|
fazekasgy@31
|
655 if (PyErr_Occurred())
|
fazekasgy@31
|
656 {
|
fazekasgy@31
|
657 PyErr_Print(); PyErr_Clear();
|
fazekasgy@31
|
658 setValueError("Error while converting integer to RealTime.",m_strict);
|
fazekasgy@31
|
659 return Vamp::RealTime::RealTime();
|
fazekasgy@31
|
660 }
|
fazekasgy@31
|
661 #ifdef _DEBUG
|
fazekasgy@31
|
662 Vamp::RealTime::RealTime rt =
|
fazekasgy@31
|
663 Vamp::RealTime::frame2RealTime(sampleCount,m_inputSampleRate );
|
fazekasgy@31
|
664 cerr << "RealTime: " << (long)sampleCount << ", ->" << rt.toString() << endl;
|
fazekasgy@31
|
665 return rt;
|
fazekasgy@31
|
666 #else
|
fazekasgy@31
|
667 return Vamp::RealTime::frame2RealTime(sampleCount,m_inputSampleRate );
|
fazekasgy@31
|
668 #endif
|
fazekasgy@31
|
669
|
fazekasgy@31
|
670 }
|
fazekasgy@31
|
671
|
fazekasgy@31
|
672
|
fazekasgy@31
|
673 /// OutputDescriptor
|
fazekasgy@31
|
674 void
|
fazekasgy@31
|
675 PyTypeInterface::SetValue(Vamp::Plugin::OutputDescriptor& od, std::string& key, PyObject* pyValue) const
|
fazekasgy@31
|
676 {
|
fazekasgy@31
|
677 switch (outKeys[key])
|
fazekasgy@31
|
678 {
|
fazekasgy@31
|
679 case o::not_found:
|
fazekasgy@31
|
680 cerr << "Unknown key in Vamp OutputDescriptor: " << key << endl;
|
fazekasgy@31
|
681 break;
|
fazekasgy@31
|
682 case o::identifier:
|
fazekasgy@31
|
683 _convert(pyValue,od.identifier);
|
fazekasgy@31
|
684 break;
|
fazekasgy@31
|
685 case o::name:
|
fazekasgy@31
|
686 _convert(pyValue,od.name);
|
fazekasgy@31
|
687 break;
|
fazekasgy@31
|
688 case o::description:
|
fazekasgy@31
|
689 _convert(pyValue,od.description);
|
fazekasgy@31
|
690 break;
|
fazekasgy@31
|
691 case o::unit:
|
fazekasgy@31
|
692 _convert(pyValue,od.unit);
|
fazekasgy@31
|
693 break;
|
fazekasgy@31
|
694 case o::hasFixedBinCount:
|
fazekasgy@31
|
695 _convert(pyValue,od.hasFixedBinCount);
|
fazekasgy@31
|
696 break;
|
fazekasgy@31
|
697 case o::binCount:
|
fazekasgy@31
|
698 _convert(pyValue,od.binCount);
|
fazekasgy@31
|
699 break;
|
fazekasgy@31
|
700 case o::binNames:
|
fazekasgy@31
|
701 _convert(pyValue,od.binNames);
|
fazekasgy@31
|
702 break;
|
fazekasgy@31
|
703 case o::hasKnownExtents:
|
fazekasgy@31
|
704 _convert(pyValue,od.hasKnownExtents);
|
fazekasgy@31
|
705 break;
|
fazekasgy@31
|
706 case o::minValue:
|
fazekasgy@31
|
707 _convert(pyValue,od.minValue);
|
fazekasgy@31
|
708 break;
|
fazekasgy@31
|
709 case o::maxValue:
|
fazekasgy@31
|
710 _convert(pyValue,od.maxValue);
|
fazekasgy@31
|
711 break;
|
fazekasgy@31
|
712 case o::isQuantized:
|
fazekasgy@31
|
713 _convert(pyValue,od.isQuantized);
|
fazekasgy@31
|
714 break;
|
fazekasgy@31
|
715 case o::quantizeStep:
|
fazekasgy@31
|
716 _convert(pyValue,od.quantizeStep);
|
fazekasgy@31
|
717 break;
|
fazekasgy@31
|
718 case o::sampleType:
|
fazekasgy@31
|
719 // implements specific conversion!
|
fazekasgy@31
|
720 od.sampleType = (Vamp::Plugin::OutputDescriptor::SampleType) sampleKeys[PyValue_To_String(pyValue)];
|
fazekasgy@31
|
721 break;
|
fazekasgy@31
|
722 case o::sampleRate:
|
fazekasgy@31
|
723 _convert(pyValue,od.sampleRate);
|
fazekasgy@31
|
724 break;
|
fazekasgy@31
|
725 case o::hasDuration:
|
fazekasgy@31
|
726 _convert(pyValue,od.hasDuration);
|
fazekasgy@31
|
727 break;
|
fazekasgy@31
|
728 default:
|
fazekasgy@31
|
729 cerr << "Invalid key in Vamp OutputDescriptor: " << key << endl;
|
fazekasgy@31
|
730 }
|
fazekasgy@31
|
731 }
|
fazekasgy@31
|
732
|
fazekasgy@31
|
733 /// ParameterDescriptor
|
fazekasgy@31
|
734 void
|
fazekasgy@31
|
735 PyTypeInterface::SetValue(Vamp::Plugin::ParameterDescriptor& pd, std::string& key, PyObject* pyValue) const
|
fazekasgy@31
|
736 {
|
fazekasgy@31
|
737 switch (parmKeys[key])
|
fazekasgy@31
|
738 {
|
fazekasgy@31
|
739 case p::not_found :
|
fazekasgy@31
|
740 cerr << "Unknown key in Vamp ParameterDescriptor: " << key << endl;
|
fazekasgy@31
|
741 break;
|
fazekasgy@31
|
742 case p::identifier:
|
fazekasgy@31
|
743 _convert(pyValue,pd.identifier);
|
fazekasgy@31
|
744 break;
|
fazekasgy@31
|
745 case p::name:
|
fazekasgy@31
|
746 _convert(pyValue,pd.name);
|
fazekasgy@31
|
747 break;
|
fazekasgy@31
|
748 case p::description:
|
fazekasgy@31
|
749 _convert(pyValue,pd.description);
|
fazekasgy@31
|
750 break;
|
fazekasgy@31
|
751 case p::unit:
|
fazekasgy@31
|
752 _convert(pyValue,pd.unit);
|
fazekasgy@31
|
753 break;
|
fazekasgy@31
|
754 case p::minValue:
|
fazekasgy@31
|
755 _convert(pyValue,pd.minValue);
|
fazekasgy@31
|
756 break;
|
fazekasgy@31
|
757 case p::maxValue:
|
fazekasgy@31
|
758 _convert(pyValue,pd.maxValue);
|
fazekasgy@31
|
759 break;
|
fazekasgy@31
|
760 case p::defaultValue:
|
fazekasgy@31
|
761 _convert(pyValue,pd.defaultValue);
|
fazekasgy@31
|
762 break;
|
fazekasgy@31
|
763 case p::isQuantized:
|
fazekasgy@31
|
764 _convert(pyValue,pd.isQuantized);
|
fazekasgy@31
|
765 break;
|
fazekasgy@31
|
766 case p::quantizeStep:
|
fazekasgy@31
|
767 _convert(pyValue,pd.quantizeStep);
|
fazekasgy@31
|
768 break;
|
fazekasgy@31
|
769 default :
|
fazekasgy@31
|
770 cerr << "Invalid key in Vamp ParameterDescriptor: " << key << endl;
|
fazekasgy@31
|
771 }
|
fazekasgy@31
|
772 }
|
fazekasgy@31
|
773
|
fazekasgy@31
|
774 /// Feature (it's like a Descriptor)
|
fazekasgy@31
|
775 bool
|
fazekasgy@31
|
776 PyTypeInterface::SetValue(Vamp::Plugin::Feature& feature, std::string& key, PyObject* pyValue) const
|
fazekasgy@31
|
777 {
|
fazekasgy@31
|
778 bool found = true;
|
fazekasgy@31
|
779 switch (ffKeys[key])
|
fazekasgy@31
|
780 {
|
fazekasgy@31
|
781 case unknown :
|
fazekasgy@31
|
782 cerr << "Unknown key in Vamp Feature: " << key << endl;
|
fazekasgy@31
|
783 found = false;
|
fazekasgy@31
|
784 break;
|
fazekasgy@31
|
785 case hasTimestamp:
|
fazekasgy@31
|
786 _convert(pyValue,feature.hasTimestamp);
|
fazekasgy@31
|
787 break;
|
fazekasgy@31
|
788 case timeStamp:
|
fazekasgy@31
|
789 _convert(pyValue,feature.timestamp);
|
fazekasgy@31
|
790 break;
|
fazekasgy@31
|
791 case hasDuration:
|
fazekasgy@31
|
792 _convert(pyValue,feature.hasDuration);
|
fazekasgy@31
|
793 break;
|
fazekasgy@31
|
794 case duration:
|
fazekasgy@31
|
795 _convert(pyValue,feature.duration);
|
fazekasgy@31
|
796 break;
|
fazekasgy@31
|
797 case values:
|
fazekasgy@31
|
798 _convert(pyValue,feature.values);
|
fazekasgy@31
|
799 break;
|
fazekasgy@31
|
800 case label:
|
fazekasgy@31
|
801 _convert(pyValue,feature.label);
|
fazekasgy@31
|
802 break;
|
fazekasgy@31
|
803 default:
|
fazekasgy@31
|
804 found = false;
|
fazekasgy@31
|
805 }
|
fazekasgy@31
|
806 return found;
|
fazekasgy@31
|
807 }
|
fazekasgy@31
|
808
|
fazekasgy@31
|
809 /*
|
fazekasgy@31
|
810 /// Feature (it's like a Descriptor)
|
fazekasgy@31
|
811 bool
|
fazekasgy@31
|
812 PyTypeInterface::GetValue(Vamp::Plugin::Feature& feature, std::string& key, PyObject* pyValue) const
|
fazekasgy@31
|
813 {
|
fazekasgy@31
|
814 bool found = true;
|
fazekasgy@31
|
815 switch (ffKeys[key])
|
fazekasgy@31
|
816 {
|
fazekasgy@31
|
817 case unknown :
|
fazekasgy@31
|
818 cerr << "Unknown key in Vamp Feature: " << key << endl;
|
fazekasgy@31
|
819 found = false;
|
fazekasgy@31
|
820 break;
|
fazekasgy@31
|
821 case hasTimestamp:
|
fazekasgy@31
|
822 _convert(pyValue,feature.hasTimestamp);
|
fazekasgy@31
|
823 // pyValue = PyValue_From_CValue(feature.hasTimestamp)
|
fazekasgy@31
|
824 break;
|
fazekasgy@31
|
825 case timeStamp:
|
fazekasgy@31
|
826 _convert(pyValue,feature.timestamp);
|
fazekasgy@31
|
827 break;
|
fazekasgy@31
|
828 case hasDuration:
|
fazekasgy@31
|
829 _convert(pyValue,feature.hasDuration);
|
fazekasgy@31
|
830 break;
|
fazekasgy@31
|
831 case duration:
|
fazekasgy@31
|
832 _convert(pyValue,feature.duration);
|
fazekasgy@31
|
833 break;
|
fazekasgy@31
|
834 case values:
|
fazekasgy@31
|
835 _convert(pyValue,feature.values);
|
fazekasgy@31
|
836 break;
|
fazekasgy@31
|
837 case label:
|
fazekasgy@31
|
838 _convert(pyValue,feature.label); //vector<string>
|
fazekasgy@31
|
839 break;
|
fazekasgy@31
|
840 default:
|
fazekasgy@31
|
841 found = false;
|
fazekasgy@31
|
842 }
|
fazekasgy@31
|
843 return found;
|
fazekasgy@31
|
844 }
|
fazekasgy@31
|
845 */
|
fazekasgy@31
|
846
|
fazekasgy@31
|
847 /* Error handling */
|
fazekasgy@31
|
848
|
fazekasgy@31
|
849 void
|
fazekasgy@31
|
850 PyTypeInterface::setValueError (std::string message, bool strict) const
|
fazekasgy@31
|
851 {
|
fazekasgy@31
|
852 m_error = true;
|
fazekasgy@31
|
853 m_errorQueue.push(ValueError(message,strict));
|
fazekasgy@31
|
854 }
|
fazekasgy@31
|
855
|
fazekasgy@31
|
856 /// return a reference to the last error or creates a new one.
|
fazekasgy@31
|
857 PyTypeInterface::ValueError&
|
fazekasgy@31
|
858 PyTypeInterface::_lastError() const
|
fazekasgy@31
|
859 {
|
fazekasgy@31
|
860 m_error = false;
|
fazekasgy@31
|
861 if (!m_errorQueue.empty()) return m_errorQueue.back();
|
fazekasgy@31
|
862 else {
|
fazekasgy@31
|
863 m_errorQueue.push(ValueError("Type conversion error.",m_strict));
|
fazekasgy@31
|
864 return m_errorQueue.back();
|
fazekasgy@31
|
865 }
|
fazekasgy@31
|
866 }
|
fazekasgy@31
|
867
|
fazekasgy@31
|
868 /// return the last error message and clear the error flag
|
fazekasgy@31
|
869 const PyTypeInterface::ValueError&
|
fazekasgy@31
|
870 PyTypeInterface::lastError() const
|
fazekasgy@31
|
871 {
|
fazekasgy@31
|
872 // PyTypeInterface *self = const_cast<PyTypeInterface*> (this);
|
fazekasgy@31
|
873 m_error = false;
|
fazekasgy@31
|
874 if (!m_errorQueue.empty()) return m_errorQueue.back();
|
fazekasgy@31
|
875 else return m_noError;
|
fazekasgy@31
|
876 }
|
fazekasgy@31
|
877
|
fazekasgy@31
|
878 /// iterate over the error message queue and pop the oldest item
|
fazekasgy@31
|
879 PyTypeInterface::ValueError
|
fazekasgy@31
|
880 PyTypeInterface::getError() const
|
fazekasgy@31
|
881 {
|
fazekasgy@31
|
882 if (!m_errorQueue.empty()) {
|
fazekasgy@31
|
883 PyTypeInterface::ValueError e = m_errorQueue.front();
|
fazekasgy@31
|
884 m_errorQueue.pop();
|
fazekasgy@31
|
885 if (m_errorQueue.empty()) m_error = false;
|
fazekasgy@31
|
886 return e;
|
fazekasgy@31
|
887 }
|
fazekasgy@31
|
888 else {
|
fazekasgy@31
|
889 m_error = false;
|
fazekasgy@31
|
890 return PyTypeInterface::ValueError();
|
fazekasgy@31
|
891 }
|
fazekasgy@31
|
892 }
|
fazekasgy@31
|
893
|
fazekasgy@31
|
894 /* Utilities */
|
fazekasgy@31
|
895
|
fazekasgy@31
|
896 //return a pointer to the data in the numPy array
|
fazekasgy@31
|
897 float*
|
fazekasgy@31
|
898 PyTypeInterface::getNumPyObjectData(PyObject *object, int &length) const
|
fazekasgy@31
|
899 {
|
fazekasgy@31
|
900
|
fazekasgy@31
|
901 char attr_name[]="__array_struct__";
|
fazekasgy@31
|
902
|
fazekasgy@31
|
903 //check if we passed in a NumPy array object
|
fazekasgy@31
|
904 if (!PyObject_HasAttrString(object,attr_name)) {
|
fazekasgy@31
|
905 // PyErr_SetString(PyExc_TypeError,
|
fazekasgy@31
|
906 // "Input object has no __array_struct__ attribute. NumPy array required.");
|
fazekasgy@31
|
907 return NULL;
|
fazekasgy@31
|
908 }
|
fazekasgy@31
|
909
|
fazekasgy@31
|
910 //retrieve __array_struct__ interface
|
fazekasgy@31
|
911 object = PyObject_GetAttrString(object,attr_name);
|
fazekasgy@31
|
912
|
fazekasgy@31
|
913 //check whether we found CObjects
|
fazekasgy@31
|
914 if (!PyCObject_Check(object)) {
|
fazekasgy@31
|
915 PyErr_SetString(PyExc_TypeError,
|
fazekasgy@31
|
916 "The passed __array_struct__ interface is not a valid C Object.");
|
fazekasgy@31
|
917 return NULL;
|
fazekasgy@31
|
918 }
|
fazekasgy@31
|
919
|
fazekasgy@31
|
920
|
fazekasgy@31
|
921 //check if the pointers directed to the integer '2'
|
fazekasgy@31
|
922 int *check = (int *) PyCObject_AsVoidPtr (object);
|
fazekasgy@31
|
923
|
fazekasgy@31
|
924 if (*check != 2 ) {
|
fazekasgy@31
|
925 PyErr_SetString(PyExc_TypeError,
|
fazekasgy@31
|
926 "A C Object __array_struct__ required as inputs");
|
fazekasgy@31
|
927 return NULL;
|
fazekasgy@31
|
928 }
|
fazekasgy@31
|
929
|
fazekasgy@31
|
930 //convert CObjects to Array interfaces
|
fazekasgy@31
|
931 PyArrayInterface *arrayInterface =
|
fazekasgy@31
|
932 (PyArrayInterface *) PyCObject_AsVoidPtr (object);
|
fazekasgy@31
|
933
|
fazekasgy@31
|
934 //check array dimension: should be 1
|
fazekasgy@31
|
935 int inputDim = arrayInterface->nd;
|
fazekasgy@31
|
936
|
fazekasgy@31
|
937 if (inputDim > 1 ) {
|
fazekasgy@31
|
938 PyErr_SetString(PyExc_TypeError,
|
fazekasgy@31
|
939 "Array dimensions must not exceed one.");
|
fazekasgy@31
|
940 return NULL;
|
fazekasgy@31
|
941 }
|
fazekasgy@31
|
942
|
fazekasgy@31
|
943 // check if vector size is sane
|
fazekasgy@31
|
944 Py_intptr_t arrayLength = arrayInterface->shape[0];
|
fazekasgy@31
|
945 length = (int) arrayLength;
|
fazekasgy@31
|
946
|
fazekasgy@31
|
947 // if (arrayLength < 8 || arrayLength > 65536 ) {
|
fazekasgy@31
|
948 // PyErr_SetString(PyExc_TypeError,
|
fazekasgy@31
|
949 // "Array length is out of bounds.");
|
fazekasgy@31
|
950 // return NULL;
|
fazekasgy@31
|
951 // }
|
fazekasgy@31
|
952
|
fazekasgy@31
|
953 //check type; must be float32
|
fazekasgy@31
|
954 char arrayType = arrayInterface->typekind;
|
fazekasgy@31
|
955
|
fazekasgy@31
|
956 if (arrayType != 'f' ) {
|
fazekasgy@31
|
957 PyErr_SetString(PyExc_TypeError,
|
fazekasgy@31
|
958 "Floating point arrays required.");
|
fazekasgy@31
|
959 return NULL;
|
fazekasgy@31
|
960 }
|
fazekasgy@31
|
961
|
fazekasgy@31
|
962 //return data vector address
|
fazekasgy@31
|
963 return (float*) arrayInterface->data;
|
fazekasgy@31
|
964
|
fazekasgy@31
|
965 }
|
fazekasgy@31
|
966
|
fazekasgy@31
|
967 /// get the type name of an object
|
fazekasgy@31
|
968 std::string
|
fazekasgy@31
|
969 PyTypeInterface::PyValue_Get_TypeName(PyObject* pyValue) const
|
fazekasgy@31
|
970 {
|
fazekasgy@31
|
971 PyObject *pyType = PyObject_Type(pyValue);
|
fazekasgy@31
|
972 if (!pyType) return std::string ("< unknown type >");
|
fazekasgy@31
|
973 PyObject *pyString = PyObject_Str(pyType);
|
fazekasgy@31
|
974 if (!pyString)
|
fazekasgy@31
|
975 {
|
fazekasgy@31
|
976 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@31
|
977 Py_CLEAR(pyType);
|
fazekasgy@31
|
978 return std::string ("< unknown type >");
|
fazekasgy@31
|
979 }
|
fazekasgy@31
|
980 char *cstr = PyString_AS_STRING(pyString);
|
fazekasgy@31
|
981 if (!cstr)
|
fazekasgy@31
|
982 {
|
fazekasgy@31
|
983 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
|
fazekasgy@31
|
984 Py_DECREF(pyType);
|
fazekasgy@31
|
985 Py_CLEAR(pyString);
|
fazekasgy@31
|
986 cerr << "Warning: Object type name could not be found." << endl;
|
fazekasgy@31
|
987 return std::string("< unknown type >");
|
fazekasgy@31
|
988 }
|
fazekasgy@31
|
989 Py_DECREF(pyType);
|
fazekasgy@31
|
990 Py_DECREF(pyString);
|
fazekasgy@31
|
991 return std::string(cstr);
|
fazekasgy@31
|
992 }
|
fazekasgy@31
|
993
|
fazekasgy@31
|
994 bool
|
fazekasgy@31
|
995 PyTypeInterface::initMaps() const
|
fazekasgy@31
|
996 {
|
fazekasgy@31
|
997
|
fazekasgy@31
|
998 if (isMapInitialised) return true;
|
fazekasgy@31
|
999
|
fazekasgy@31
|
1000 outKeys["identifier"] = o::identifier;
|
fazekasgy@31
|
1001 outKeys["name"] = o::name;
|
fazekasgy@31
|
1002 outKeys["description"] = o::description;
|
fazekasgy@31
|
1003 outKeys["unit"] = o::unit;
|
fazekasgy@31
|
1004 outKeys["hasFixedBinCount"] = o::hasFixedBinCount;
|
fazekasgy@31
|
1005 outKeys["binCount"] = o::binCount;
|
fazekasgy@31
|
1006 outKeys["binNames"] = o::binNames;
|
fazekasgy@31
|
1007 outKeys["hasKnownExtents"] = o::hasKnownExtents;
|
fazekasgy@31
|
1008 outKeys["minValue"] = o::minValue;
|
fazekasgy@31
|
1009 outKeys["maxValue"] = o::maxValue;
|
fazekasgy@31
|
1010 outKeys["isQuantized"] = o::isQuantized;
|
fazekasgy@31
|
1011 outKeys["quantizeStep"] = o::quantizeStep;
|
fazekasgy@31
|
1012 outKeys["sampleType"] = o::sampleType;
|
fazekasgy@31
|
1013 outKeys["sampleRate"] = o::sampleRate;
|
fazekasgy@31
|
1014 outKeys["hasDuration"] = o::hasDuration;
|
fazekasgy@31
|
1015
|
fazekasgy@31
|
1016 sampleKeys["OneSamplePerStep"] = OneSamplePerStep;
|
fazekasgy@31
|
1017 sampleKeys["FixedSampleRate"] = FixedSampleRate;
|
fazekasgy@31
|
1018 sampleKeys["VariableSampleRate"] = VariableSampleRate;
|
fazekasgy@31
|
1019
|
fazekasgy@31
|
1020 ffKeys["hasTimestamp"] = hasTimestamp;
|
fazekasgy@31
|
1021 ffKeys["timeStamp"] = timeStamp;
|
fazekasgy@31
|
1022 ffKeys["hasDuration"] = hasDuration;
|
fazekasgy@31
|
1023 ffKeys["duration"] = duration;
|
fazekasgy@31
|
1024 ffKeys["values"] = values;
|
fazekasgy@31
|
1025 ffKeys["label"] = label;
|
fazekasgy@31
|
1026
|
fazekasgy@31
|
1027 parmKeys["identifier"] = p::identifier;
|
fazekasgy@31
|
1028 parmKeys["name"] = p::name;
|
fazekasgy@31
|
1029 parmKeys["description"] = p::description;
|
fazekasgy@31
|
1030 parmKeys["unit"] = p::unit;
|
fazekasgy@31
|
1031 parmKeys["minValue"] = p::minValue;
|
fazekasgy@31
|
1032 parmKeys["maxValue"] = p::maxValue;
|
fazekasgy@31
|
1033 parmKeys["defaultValue"] = p::defaultValue;
|
fazekasgy@31
|
1034 parmKeys["isQuantized"] = p::isQuantized;
|
fazekasgy@31
|
1035 parmKeys["quantizeStep"] = p::quantizeStep;
|
fazekasgy@31
|
1036
|
fazekasgy@31
|
1037 isMapInitialised = true;
|
fazekasgy@31
|
1038 return true;
|
fazekasgy@31
|
1039 }
|