annotate PyTypeInterface.cpp @ 52:d56f48aafb99

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