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