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 }