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