annotate PyTypeInterface.cpp @ 67:146d14ab15e7

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