annotate PyTypeInterface.cpp @ 32:a8231788216c vampy2

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