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