annotate PyTypeInterface.cpp @ 31:4f1894c7591b vampy2

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