annotate PyTypeInterface.cpp @ 48:cb207d275e8e

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