annotate PyPlugin.h @ 79:f5c028376bf9

Some old changes that, I think, probably did not help anything
author Chris Cannam
date Wed, 12 Aug 2015 15:25:04 +0100
parents 146d14ab15e7
children
rev   line source
fazekasgy@37 1 /*
fazekasgy@37 2
fazekasgy@37 3 * Vampy : This plugin is a wrapper around the Vamp plugin API.
fazekasgy@37 4 * It allows for writing Vamp plugins in Python.
fazekasgy@37 5
fazekasgy@37 6 * Centre for Digital Music, Queen Mary University of London.
fazekasgy@37 7 * Copyright (C) 2008-2009 Gyorgy Fazekas, QMUL. (See Vamp sources
fazekasgy@37 8 * for licence information.)
fazekasgy@37 9
fazekasgy@37 10 */
fazekasgy@37 11
fazekasgy@37 12 #ifndef _PYTHON_WRAPPER_PLUGIN_H_
fazekasgy@37 13 #define _PYTHON_WRAPPER_PLUGIN_H_
fazekasgy@37 14
fazekasgy@37 15 #define _CLASS_METHOD_ m_class << "::" << method
fazekasgy@37 16 #define PLUGIN_ERROR "ERROR: In Vampy plugin [" << _CLASS_METHOD_ << "]" << endl << "Cause: "
fazekasgy@37 17 #define DEBUG_NAME "[Vampy::call] " << _CLASS_METHOD_ << " "
Chris@67 18 #define DEFAULT_RETURN "Method [" << _CLASS_METHOD_ << "] is not implemented. Returning default value."
fazekasgy@37 19 #define FLAG_VALUE "Flag: " << flagName << ": " << ((rValue==0)?"False":"True")
fazekasgy@37 20
fazekasgy@37 21 #include <Python.h>
fazekasgy@37 22 #include "PyExtensionModule.h"
fazekasgy@37 23 #include "PyTypeInterface.h"
fazekasgy@37 24 #include "vamp-sdk/Plugin.h"
fazekasgy@37 25 #include "Mutex.h"
fazekasgy@37 26
fazekasgy@37 27 using std::string;
fazekasgy@37 28 using std::cerr;
fazekasgy@37 29 using std::endl;
fazekasgy@37 30
fazekasgy@37 31 enum eProcessType {
fazekasgy@37 32 not_implemented,
fazekasgy@37 33 legacyProcess,
fazekasgy@37 34 numpyProcess,
fazekasgy@37 35 numpy_bufferProcess,
fazekasgy@37 36 numpy_arrayProcess
fazekasgy@37 37 };
fazekasgy@37 38
fazekasgy@37 39 class PyPlugin : public Vamp::Plugin
fazekasgy@37 40 {
fazekasgy@37 41 public:
fazekasgy@51 42 PyPlugin(std::string plugin,float inputSampleRate, PyObject *pyClass, int &instcount, bool &numpyInstalled);
fazekasgy@37 43 virtual ~PyPlugin();
fazekasgy@37 44
fazekasgy@37 45 bool initialise(size_t channels, size_t stepSize, size_t blockSize);
fazekasgy@37 46 void reset();
fazekasgy@37 47
fazekasgy@37 48 InputDomain getInputDomain() const;
fazekasgy@37 49 size_t getPreferredBlockSize() const;
fazekasgy@37 50 size_t getPreferredStepSize() const;
fazekasgy@37 51 size_t getMinChannelCount() const;
fazekasgy@37 52 size_t getMaxChannelCount() const;
fazekasgy@37 53
fazekasgy@37 54 std::string getIdentifier() const;
fazekasgy@37 55 std::string getName() const;
fazekasgy@37 56 std::string getDescription() const;
fazekasgy@37 57 std::string getMaker() const;
fazekasgy@37 58 int getPluginVersion() const;
fazekasgy@37 59 std::string getCopyright() const;
fazekasgy@37 60
fazekasgy@37 61 OutputList getOutputDescriptors() const;
fazekasgy@37 62 ParameterList getParameterDescriptors() const;
fazekasgy@37 63 float getParameter(std::string paramid) const;
fazekasgy@37 64 void setParameter(std::string paramid, float newval);
fazekasgy@37 65
fazekasgy@37 66 FeatureSet process(const float *const *inputBuffers,
fazekasgy@37 67 Vamp::RealTime timestamp);
fazekasgy@37 68
fazekasgy@37 69 FeatureSet getRemainingFeatures();
fazekasgy@37 70
fazekasgy@37 71 protected:
fazekasgy@37 72 static Mutex m_pythonInterpreterMutex;
fazekasgy@37 73 PyObject *m_pyClass;
fazekasgy@37 74 PyObject *m_pyInstance;
fazekasgy@37 75 int &m_instcount;
fazekasgy@37 76 size_t m_stepSize;
fazekasgy@37 77 size_t m_blockSize;
fazekasgy@37 78 size_t m_channels;
fazekasgy@37 79 std::string m_plugin;
fazekasgy@37 80 std::string m_class;
fazekasgy@37 81 std::string m_path;
fazekasgy@37 82 eProcessType m_processType;
fazekasgy@37 83 PyObject *m_pyProcess;
fazekasgy@37 84 PyObject *m_pyProcessCallable;
fazekasgy@37 85 mutable InputDomain m_inputDomain;
fazekasgy@37 86 PyTypeInterface m_ti;
fazekasgy@37 87 int m_vampyFlags;
fazekasgy@37 88 bool m_quitOnErrorFlag;
fazekasgy@37 89 bool m_debugFlag;
fazekasgy@37 90 bool m_useRealTimeFlag;
fazekasgy@51 91 bool m_numpyInstalled;
fazekasgy@51 92 mutable bool m_processFailure;
fazekasgy@37 93
fazekasgy@37 94 void setProcessType();
fazekasgy@37 95
fazekasgy@37 96 FeatureSet processMethodCall(const float *const *inputBuffers,Vamp::RealTime timestamp);
fazekasgy@37 97
Chris@66 98 bool getBooleanFlag(const char flagName[],bool) const;
Chris@66 99 int getBinaryFlags(const char flagName[], eVampyFlags) const;
Chris@66 100 void typeErrorHandler(const char *method, bool process = false) const;
fazekasgy@37 101
fazekasgy@37 102 /// simple 'void return' call with no args
Chris@66 103 void genericMethodCall(const char *method) const
fazekasgy@37 104 {
fazekasgy@37 105 if (m_debugFlag) cerr << DEBUG_NAME << endl;
fazekasgy@37 106 if ( PyObject_HasAttrString(m_pyInstance,method) )
fazekasgy@37 107 {
Chris@66 108 PyObject *pyValue = PyObject_CallMethod(m_pyInstance, (char *)method, NULL);
fazekasgy@37 109 if (!pyValue) {
fazekasgy@37 110 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
fazekasgy@37 111 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
fazekasgy@37 112 }
fazekasgy@37 113 }
fazekasgy@37 114 }
fazekasgy@37 115
fazekasgy@37 116 /// 'no arg with default return value' call
fazekasgy@37 117 template<typename RET>
Chris@66 118 RET &genericMethodCall(const char *method, RET &rValue) const
fazekasgy@37 119 {
fazekasgy@37 120 if (m_debugFlag) cerr << DEBUG_NAME << endl;
fazekasgy@37 121 if ( PyObject_HasAttrString(m_pyInstance,method) )
fazekasgy@37 122 {
Chris@66 123 PyObject *pyValue = PyObject_CallMethod(m_pyInstance, (char *)method, NULL);
fazekasgy@37 124 if (!pyValue) {
fazekasgy@37 125 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
fazekasgy@37 126 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
fazekasgy@37 127 return rValue;
fazekasgy@37 128 }
fazekasgy@37 129
fazekasgy@37 130 /// convert the returned value
fazekasgy@37 131 m_ti.PyValue_To_rValue(pyValue,rValue);
fazekasgy@37 132 if (!m_ti.error) {
fazekasgy@37 133 Py_DECREF(pyValue);
fazekasgy@37 134 } else {
fazekasgy@37 135 Py_CLEAR(pyValue);
fazekasgy@37 136 typeErrorHandler(method);
fazekasgy@37 137 }
fazekasgy@37 138 return rValue;
fazekasgy@37 139 }
Chris@67 140 if (m_debugFlag) cerr << DEFAULT_RETURN << endl;
fazekasgy@37 141 return rValue;
fazekasgy@37 142 }
fazekasgy@37 143
fazekasgy@37 144 /// unary call
fazekasgy@37 145 template<typename RET,typename A1>
Chris@66 146 RET genericMethodCallArgs(const char *method, A1 arg1) const
fazekasgy@37 147 {
fazekasgy@37 148 RET rValue = RET();
fazekasgy@37 149 if (m_debugFlag) cerr << DEBUG_NAME << endl;
fazekasgy@37 150 if (!PyObject_HasAttrString(m_pyInstance,method)) {
Chris@67 151 if (m_debugFlag) cerr << DEFAULT_RETURN << endl;
fazekasgy@37 152 return rValue;
fazekasgy@37 153 }
fazekasgy@37 154
fazekasgy@37 155 /// prepare arguments for fast method call
fazekasgy@37 156 PyObject *pyMethod = m_ti.PyValue_From_CValue(method);
fazekasgy@37 157 PyObject *pyCallable = PyObject_GetAttr(m_pyInstance,pyMethod);
fazekasgy@37 158 PyObject* pyArgs = PyTuple_New(1);
fazekasgy@37 159 if (!(pyArgs && pyCallable && pyMethod)) {
fazekasgy@37 160 cerr << PLUGIN_ERROR << "Failed to prepare argument for calling method." << endl;
fazekasgy@37 161 Py_CLEAR(pyMethod);
fazekasgy@37 162 Py_CLEAR(pyCallable);
fazekasgy@37 163 Py_CLEAR(pyArgs);
fazekasgy@37 164 return rValue;
fazekasgy@37 165 }
fazekasgy@37 166
fazekasgy@37 167 PyObject *pyArg1 = m_ti.PyValue_From_CValue(arg1);
fazekasgy@37 168 if (m_ti.error) {
fazekasgy@37 169 cerr << PLUGIN_ERROR << "Failed to convert argument for calling method." << endl;
fazekasgy@37 170 typeErrorHandler(method);
fazekasgy@37 171 Py_CLEAR(pyMethod);
fazekasgy@37 172 Py_CLEAR(pyCallable);
fazekasgy@37 173 Py_CLEAR(pyArg1);
fazekasgy@37 174 Py_CLEAR(pyArgs);
fazekasgy@37 175 return rValue;
fazekasgy@37 176 }
fazekasgy@37 177
fazekasgy@37 178 PyTuple_SET_ITEM(pyArgs, 0, pyArg1);
fazekasgy@37 179 Py_INCREF(pyArg1);
fazekasgy@37 180
fazekasgy@37 181 /// call the method
fazekasgy@37 182 PyObject *pyValue = PyObject_Call(pyCallable,pyArgs,NULL);
fazekasgy@37 183 if (!pyValue)
fazekasgy@37 184 {
fazekasgy@37 185 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
fazekasgy@37 186 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
fazekasgy@37 187 Py_CLEAR(pyMethod);
fazekasgy@37 188 Py_CLEAR(pyCallable);
fazekasgy@37 189 Py_CLEAR(pyArg1);
fazekasgy@37 190 Py_CLEAR(pyArgs);
fazekasgy@37 191 return rValue;
fazekasgy@37 192 }
fazekasgy@37 193
fazekasgy@37 194 Py_DECREF(pyMethod);
fazekasgy@37 195 Py_DECREF(pyCallable);
fazekasgy@37 196 Py_DECREF(pyArg1);
fazekasgy@37 197 Py_DECREF(pyArgs);
fazekasgy@37 198
fazekasgy@37 199 /// convert the returned value
fazekasgy@37 200 m_ti.PyValue_To_rValue(pyValue,rValue);
fazekasgy@37 201 if (!m_ti.error) {
fazekasgy@37 202 Py_DECREF(pyValue);
fazekasgy@37 203 } else {
fazekasgy@37 204 Py_CLEAR(pyValue);
fazekasgy@37 205 typeErrorHandler(method);
fazekasgy@37 206 }
fazekasgy@37 207 return rValue;
fazekasgy@37 208 }
fazekasgy@37 209
fazekasgy@37 210 /// binary call
fazekasgy@37 211 template<typename RET,typename A1,typename A2>
Chris@66 212 RET genericMethodCallArgs(const char *method, A1 arg1, A2 arg2) const
fazekasgy@37 213 {
fazekasgy@37 214 RET rValue = RET();
fazekasgy@37 215 if (m_debugFlag) cerr << DEBUG_NAME << endl;
fazekasgy@37 216 if (!PyObject_HasAttrString(m_pyInstance,method)) {
Chris@67 217 if (m_debugFlag) cerr << DEFAULT_RETURN << endl;
fazekasgy@37 218 return rValue;
fazekasgy@37 219 }
fazekasgy@37 220
fazekasgy@37 221 /// prepare arguments for fast method call
fazekasgy@37 222 PyObject *pyMethod = m_ti.PyValue_From_CValue(method);
fazekasgy@37 223 PyObject *pyCallable = PyObject_GetAttr(m_pyInstance,pyMethod);
fazekasgy@37 224 PyObject* pyArgs = PyTuple_New(2);
fazekasgy@37 225 if (!(pyArgs && pyCallable && pyMethod)) {
fazekasgy@37 226 cerr << PLUGIN_ERROR << "Failed to prepare arguments for calling method." << endl;
fazekasgy@37 227 Py_CLEAR(pyMethod);
fazekasgy@37 228 Py_CLEAR(pyCallable);
fazekasgy@37 229 Py_CLEAR(pyArgs);
fazekasgy@37 230 return rValue;
fazekasgy@37 231 }
fazekasgy@37 232
fazekasgy@37 233 PyObject *pyArg1 = m_ti.PyValue_From_CValue(arg1);
fazekasgy@37 234 PyObject *pyArg2 = m_ti.PyValue_From_CValue(arg2);
fazekasgy@37 235 if (m_ti.error) {
fazekasgy@37 236 cerr << PLUGIN_ERROR << "Failed to convert arguments for calling method." << endl;
fazekasgy@37 237 typeErrorHandler(method);
fazekasgy@37 238 Py_CLEAR(pyMethod);
fazekasgy@37 239 Py_CLEAR(pyCallable);
fazekasgy@37 240 Py_CLEAR(pyArg1);
fazekasgy@37 241 Py_CLEAR(pyArg2);
fazekasgy@37 242 Py_CLEAR(pyArgs);
fazekasgy@37 243 return rValue;
fazekasgy@37 244 }
fazekasgy@37 245
fazekasgy@37 246 PyTuple_SET_ITEM(pyArgs, 0, pyArg1);
fazekasgy@37 247 Py_INCREF(pyArg1);
fazekasgy@37 248 PyTuple_SET_ITEM(pyArgs, 1, pyArg2);
fazekasgy@37 249 Py_INCREF(pyArg2);
fazekasgy@37 250
fazekasgy@37 251 // calls the method
fazekasgy@37 252 PyObject *pyValue = PyObject_Call(pyCallable,pyArgs,NULL);
fazekasgy@37 253 if (!pyValue)
fazekasgy@37 254 {
fazekasgy@37 255 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
fazekasgy@37 256 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
fazekasgy@37 257 Py_CLEAR(pyMethod);
fazekasgy@37 258 Py_CLEAR(pyCallable);
fazekasgy@37 259 Py_CLEAR(pyArg1);
fazekasgy@37 260 Py_CLEAR(pyArg2);
fazekasgy@37 261 Py_CLEAR(pyArgs);
fazekasgy@37 262 return rValue;
fazekasgy@37 263 }
fazekasgy@37 264
fazekasgy@37 265 Py_DECREF(pyMethod);
fazekasgy@37 266 Py_DECREF(pyCallable);
fazekasgy@37 267 Py_DECREF(pyArg1);
fazekasgy@37 268 Py_DECREF(pyArg2);
fazekasgy@37 269 Py_DECREF(pyArgs);
fazekasgy@37 270
fazekasgy@37 271 /// convert the returned value
fazekasgy@37 272 m_ti.PyValue_To_rValue(pyValue,rValue);
fazekasgy@37 273 if (!m_ti.error) {
fazekasgy@37 274 Py_DECREF(pyValue);
fazekasgy@37 275 } else {
fazekasgy@37 276 Py_CLEAR(pyValue);
fazekasgy@37 277 typeErrorHandler(method);
fazekasgy@37 278 }
fazekasgy@37 279 return rValue;
fazekasgy@37 280 }
fazekasgy@37 281
fazekasgy@37 282 /// trenary call
fazekasgy@37 283 template<typename RET,typename A1,typename A2,typename A3>
Chris@66 284 RET genericMethodCallArgs(const char *method, A1 arg1, A2 arg2, A3 arg3) const
fazekasgy@37 285 {
fazekasgy@37 286 RET rValue = RET();
fazekasgy@37 287 if (m_debugFlag) cerr << DEBUG_NAME << endl;
fazekasgy@37 288 if (!PyObject_HasAttrString(m_pyInstance,method)) {
Chris@67 289 if (m_debugFlag) cerr << DEFAULT_RETURN << endl;
fazekasgy@37 290 return rValue;
fazekasgy@37 291 }
fazekasgy@37 292
fazekasgy@37 293 /// prepare arguments for fast method call
fazekasgy@37 294 PyObject *pyMethod = m_ti.PyValue_From_CValue(method);
fazekasgy@37 295 PyObject *pyCallable = PyObject_GetAttr(m_pyInstance,pyMethod);
fazekasgy@37 296 PyObject* pyArgs = PyTuple_New(3);
fazekasgy@37 297 if (!(pyArgs && pyCallable && pyMethod)) {
fazekasgy@37 298 cerr << PLUGIN_ERROR << "Failed to prepare arguments for calling method." << endl;
fazekasgy@37 299 Py_CLEAR(pyMethod);
fazekasgy@37 300 Py_CLEAR(pyCallable);
fazekasgy@37 301 Py_CLEAR(pyArgs);
fazekasgy@37 302 return rValue;
fazekasgy@37 303 }
fazekasgy@37 304
fazekasgy@37 305 PyObject *pyArg1 = m_ti.PyValue_From_CValue(arg1);
fazekasgy@37 306 PyObject *pyArg2 = m_ti.PyValue_From_CValue(arg2);
fazekasgy@37 307 PyObject *pyArg3 = m_ti.PyValue_From_CValue(arg3);
fazekasgy@37 308 if (m_ti.error) {
fazekasgy@37 309 cerr << PLUGIN_ERROR << "Failed to convert arguments for calling method." << endl;
fazekasgy@37 310 typeErrorHandler(method);
fazekasgy@37 311 Py_CLEAR(pyMethod);
fazekasgy@37 312 Py_CLEAR(pyCallable);
fazekasgy@37 313 Py_CLEAR(pyArg1);
fazekasgy@37 314 Py_CLEAR(pyArg2);
fazekasgy@37 315 Py_CLEAR(pyArg3);
fazekasgy@37 316 Py_CLEAR(pyArgs);
fazekasgy@37 317 return rValue;
fazekasgy@37 318 }
fazekasgy@37 319
fazekasgy@37 320 /// Optimization: Pack args in a tuple to avoid va_list parsing.
fazekasgy@37 321 PyTuple_SET_ITEM(pyArgs, 0, pyArg1);
fazekasgy@37 322 Py_INCREF(pyArg1);
fazekasgy@37 323 PyTuple_SET_ITEM(pyArgs, 1, pyArg2);
fazekasgy@37 324 Py_INCREF(pyArg2);
fazekasgy@37 325 PyTuple_SET_ITEM(pyArgs, 2, pyArg3);
fazekasgy@37 326 Py_INCREF(pyArg3);
fazekasgy@37 327
fazekasgy@37 328 // PyObject *pyValue = PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyArg1,pyArg2,pyArg3,NULL);
fazekasgy@37 329 /// fast method call
fazekasgy@37 330 PyObject *pyValue = PyObject_Call(pyCallable,pyArgs,NULL);
fazekasgy@37 331 if (!pyValue)
fazekasgy@37 332 {
fazekasgy@37 333 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
fazekasgy@37 334 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
fazekasgy@37 335 Py_CLEAR(pyMethod);
fazekasgy@37 336 Py_CLEAR(pyCallable);
fazekasgy@37 337 Py_CLEAR(pyArg1);
fazekasgy@37 338 Py_CLEAR(pyArg2);
fazekasgy@37 339 Py_CLEAR(pyArg3);
fazekasgy@37 340 Py_CLEAR(pyArgs);
fazekasgy@37 341 return rValue;
fazekasgy@37 342 }
fazekasgy@37 343
fazekasgy@37 344 Py_DECREF(pyMethod);
fazekasgy@37 345 Py_DECREF(pyCallable);
fazekasgy@37 346 Py_DECREF(pyArg1);
fazekasgy@37 347 Py_DECREF(pyArg2);
fazekasgy@37 348 Py_DECREF(pyArg3);
fazekasgy@37 349 Py_DECREF(pyArgs);
fazekasgy@37 350
fazekasgy@37 351 /// convert the returned value
fazekasgy@37 352 m_ti.PyValue_To_rValue(pyValue,rValue);
fazekasgy@37 353 if (!m_ti.error) {
fazekasgy@37 354 Py_DECREF(pyValue);
fazekasgy@37 355 } else {
fazekasgy@37 356 Py_CLEAR(pyValue);
fazekasgy@37 357 typeErrorHandler(method);
fazekasgy@37 358 }
fazekasgy@37 359 return rValue;
fazekasgy@37 360 }
fazekasgy@37 361
fazekasgy@37 362 };
fazekasgy@37 363
fazekasgy@37 364 /// optimised process call
fazekasgy@37 365 inline PyPlugin::FeatureSet
fazekasgy@37 366 PyPlugin::processMethodCall(const float *const *inputBuffers,Vamp::RealTime timestamp)
fazekasgy@37 367 {
fazekasgy@51 368
fazekasgy@37 369 /// Optimizations: 1) we avoid ...ObjArg functions since we know
fazekasgy@37 370 /// the number of arguments, and we don't like va_list parsing
fazekasgy@37 371 /// in the process. 2) Also: we're supposed to incref args,
fazekasgy@37 372 /// but instead, we let the arguments tuple steal the references
fazekasgy@37 373 /// and decref them when it is deallocated.
fazekasgy@37 374 /// 3) all conversions are now using the fast sequence protocol
fazekasgy@37 375 /// (indexing the underlying object array).
fazekasgy@37 376
fazekasgy@37 377 FeatureSet rFeatureSet;
fazekasgy@37 378 PyObject *pyChannelList = NULL;
fazekasgy@37 379
fazekasgy@37 380 if (m_processType == numpy_bufferProcess) {
fazekasgy@51 381 pyChannelList = m_ti.InputBuffers_As_SharedMemoryList(
fazekasgy@51 382 inputBuffers,m_channels,m_blockSize,m_inputDomain);
fazekasgy@37 383 }
fazekasgy@37 384
fazekasgy@37 385 if (m_processType == legacyProcess) {
fazekasgy@51 386 pyChannelList = m_ti.InputBuffers_As_PythonLists(
fazekasgy@51 387 inputBuffers,m_channels,m_blockSize,m_inputDomain);
fazekasgy@37 388 }
fazekasgy@37 389
fazekasgy@37 390 #ifdef HAVE_NUMPY
fazekasgy@37 391 if (m_processType == numpy_arrayProcess) {
fazekasgy@51 392 pyChannelList = m_ti.InputBuffers_As_NumpyArray(
fazekasgy@51 393 inputBuffers,m_channels,m_blockSize,m_inputDomain);
fazekasgy@37 394 }
fazekasgy@37 395 #endif
fazekasgy@37 396
fazekasgy@37 397 /// we don't expect these to fail unless out of memory (which is very unlikely on modern systems)
fazekasgy@37 398 #ifdef _DEBUG
fazekasgy@37 399 if (!pyChannelList) {
fazekasgy@37 400 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
fazekasgy@37 401 std::string method = PyString_AsString(m_pyProcess);
fazekasgy@37 402 cerr << PLUGIN_ERROR << "Failed to create channel list." << endl;
fazekasgy@37 403 return rFeatureSet;
fazekasgy@37 404 }
fazekasgy@37 405 #endif
fazekasgy@37 406
fazekasgy@37 407 PyObject *pyTimeStamp = NULL;
fazekasgy@37 408
fazekasgy@37 409 if (m_useRealTimeFlag) {
fazekasgy@37 410 //(1) pass TimeStamp as PyRealTime object
fazekasgy@37 411 pyTimeStamp = PyRealTime_FromRealTime(timestamp);
fazekasgy@37 412
fazekasgy@37 413 } else {
fazekasgy@37 414 //(2) pass TimeStamp as frame count (long Sample Count)
fazekasgy@37 415 pyTimeStamp = PyLong_FromLong(Vamp::RealTime::realTime2Frame
fazekasgy@37 416 (timestamp, (unsigned int) m_inputSampleRate));
fazekasgy@37 417 }
fazekasgy@37 418
fazekasgy@37 419
fazekasgy@37 420 #ifdef _DEBUG
fazekasgy@37 421 if (!pyTimeStamp) {
fazekasgy@37 422 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
fazekasgy@37 423 std::string method = PyString_AsString(m_pyProcess);
fazekasgy@37 424 cerr << PLUGIN_ERROR << "Failed to create RealTime time stamp." << endl;
fazekasgy@37 425 Py_DECREF(pyChannelList);
fazekasgy@37 426 return rFeatureSet;
fazekasgy@37 427 }
fazekasgy@37 428 #endif
fazekasgy@37 429
fazekasgy@37 430 /// Old method: Call python process (returns new reference)
fazekasgy@37 431 /// PyObject *pyValue = PyObject_CallMethodObjArgs
fazekasgy@37 432 /// (m_pyInstance,m_pyProcess,pyChannelList,pyTimeStamp,NULL);
fazekasgy@37 433
fazekasgy@37 434 PyObject *pyArgs = PyTuple_New(2);
fazekasgy@37 435 PyTuple_SET_ITEM(pyArgs, 0, pyChannelList);
fazekasgy@37 436 PyTuple_SET_ITEM(pyArgs, 1, pyTimeStamp);
fazekasgy@37 437
fazekasgy@37 438 /// Call python process (returns new reference) {kwArgs = NULL}
fazekasgy@37 439 PyObject *pyValue = PyObject_Call(m_pyProcessCallable,pyArgs,NULL);
fazekasgy@37 440
fazekasgy@37 441 if (!pyValue) {
fazekasgy@37 442 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
fazekasgy@37 443 std::string method = PyString_AsString(m_pyProcess);
fazekasgy@37 444 cerr << PLUGIN_ERROR << "An error occurred while evaluating Python process." << endl;
fazekasgy@37 445 Py_CLEAR(pyValue);
fazekasgy@37 446 Py_CLEAR(pyArgs);
fazekasgy@37 447 return rFeatureSet;
fazekasgy@37 448 }
fazekasgy@37 449
fazekasgy@37 450 rFeatureSet = m_ti.PyValue_To_FeatureSet(pyValue);
fazekasgy@37 451 if (!m_ti.error) {
fazekasgy@37 452 Py_DECREF(pyValue);
fazekasgy@37 453 Py_DECREF(pyArgs);
fazekasgy@37 454 } else {
fazekasgy@51 455 typeErrorHandler(PyString_AsString(m_pyProcess),true);
fazekasgy@37 456 Py_CLEAR(pyValue);
fazekasgy@37 457 Py_CLEAR(pyArgs);
fazekasgy@37 458 }
fazekasgy@37 459 return rFeatureSet;
fazekasgy@37 460 }
fazekasgy@37 461
fazekasgy@37 462 #endif