Mercurial > hg > vampy
comparison PyPlugin.cpp @ 51:c1e4f706ca9a
Fix numpy version incompatibility issues and updated some example plugins.
author | fazekasgy |
---|---|
date | Thu, 08 Oct 2009 08:47:28 +0000 |
parents | 27bab3a16c9a |
children | 5664fe298af2 |
comparison
equal
deleted
inserted
replaced
50:3868da185d73 | 51:c1e4f706ca9a |
---|---|
28 using std::endl; | 28 using std::endl; |
29 using std::map; | 29 using std::map; |
30 | 30 |
31 Mutex PyPlugin::m_pythonInterpreterMutex; | 31 Mutex PyPlugin::m_pythonInterpreterMutex; |
32 | 32 |
33 PyPlugin::PyPlugin(std::string pluginKey, float inputSampleRate, PyObject *pyClass, int &instcount) : | 33 PyPlugin::PyPlugin(std::string pluginKey, float inputSampleRate, PyObject *pyClass, int &instcount, bool &numpyInstalled) : |
34 Plugin(inputSampleRate), | 34 Plugin(inputSampleRate), |
35 m_pyClass(pyClass), | 35 m_pyClass(pyClass), |
36 m_instcount(instcount), | 36 m_instcount(instcount), |
37 m_stepSize(0), | 37 m_stepSize(0), |
38 m_blockSize(0), | 38 m_blockSize(0), |
42 m_path((pluginKey.substr(0,pluginKey.rfind(PATHSEP)))), | 42 m_path((pluginKey.substr(0,pluginKey.rfind(PATHSEP)))), |
43 m_processType(not_implemented), | 43 m_processType(not_implemented), |
44 m_pyProcess(NULL), | 44 m_pyProcess(NULL), |
45 m_inputDomain(TimeDomain), | 45 m_inputDomain(TimeDomain), |
46 m_quitOnErrorFlag(false), | 46 m_quitOnErrorFlag(false), |
47 m_debugFlag(false) | 47 m_debugFlag(false), |
48 m_numpyInstalled(numpyInstalled), | |
49 m_processFailure(false) | |
48 { | 50 { |
49 m_ti.setInputSampleRate(inputSampleRate); | 51 m_ti.setInputSampleRate(inputSampleRate); |
50 MutexLocker locker(&m_pythonInterpreterMutex); | 52 MutexLocker locker(&m_pythonInterpreterMutex); |
51 cerr << "Creating instance " << m_instcount << " of " << pluginKey << endl; | 53 cerr << "Creating instance " << m_instcount << " of " << pluginKey << endl; |
52 | 54 |
84 | 86 |
85 if (m_debugFlag && m_quitOnErrorFlag) cerr << "Quit on type error ON for: " << m_class << endl; | 87 if (m_debugFlag && m_quitOnErrorFlag) cerr << "Quit on type error ON for: " << m_class << endl; |
86 | 88 |
87 if (m_debugFlag && st_flag) cerr << "Strict type conversion ON for: " << m_class << endl; | 89 if (m_debugFlag && st_flag) cerr << "Strict type conversion ON for: " << m_class << endl; |
88 m_ti.setStrictTypingFlag(st_flag); | 90 m_ti.setStrictTypingFlag(st_flag); |
91 m_ti.setNumpyInstalled(m_numpyInstalled); | |
89 | 92 |
90 } | 93 } |
91 | 94 |
92 PyPlugin::~PyPlugin() | 95 PyPlugin::~PyPlugin() |
93 { | 96 { |
186 | 189 |
187 void | 190 void |
188 PyPlugin::reset() | 191 PyPlugin::reset() |
189 { | 192 { |
190 MutexLocker locker(&m_pythonInterpreterMutex); | 193 MutexLocker locker(&m_pythonInterpreterMutex); |
194 m_processFailure = false; | |
191 genericMethodCall("reset"); | 195 genericMethodCall("reset"); |
192 } | 196 } |
193 | 197 |
194 PyPlugin::InputDomain | 198 PyPlugin::InputDomain |
195 PyPlugin::getInputDomain() const | 199 PyPlugin::getInputDomain() const |
288 cerr << "ERROR: In Python plugin [" << m_class | 292 cerr << "ERROR: In Python plugin [" << m_class |
289 << "] No process implementation found. Returning empty feature set." << endl; | 293 << "] No process implementation found. Returning empty feature set." << endl; |
290 return FeatureSet(); | 294 return FeatureSet(); |
291 } | 295 } |
292 | 296 |
297 if (m_processFailure) return FeatureSet(); | |
298 | |
293 return processMethodCall(inputBuffers,timestamp); | 299 return processMethodCall(inputBuffers,timestamp); |
294 | 300 |
295 } | 301 } |
296 | 302 |
297 PyPlugin::FeatureSet | 303 PyPlugin::FeatureSet |
298 PyPlugin::getRemainingFeatures() | 304 PyPlugin::getRemainingFeatures() |
299 { | 305 { |
300 MutexLocker locker(&m_pythonInterpreterMutex); | 306 MutexLocker locker(&m_pythonInterpreterMutex); |
307 if (m_processFailure) return FeatureSet(); | |
301 FeatureSet rValue; | 308 FeatureSet rValue; |
302 return genericMethodCall("getRemainingFeatures",rValue); | 309 return genericMethodCall("getRemainingFeatures",rValue); |
303 } | 310 } |
304 | 311 |
305 bool | 312 bool |
353 PyPlugin::setProcessType() | 360 PyPlugin::setProcessType() |
354 { | 361 { |
355 //quering process implementation type | 362 //quering process implementation type |
356 char legacyMethod[]="process"; | 363 char legacyMethod[]="process"; |
357 char numpyMethod[]="processN"; | 364 char numpyMethod[]="processN"; |
365 m_processFailure = false; | |
358 | 366 |
359 if (PyObject_HasAttrString(m_pyInstance,legacyMethod) && | 367 if (PyObject_HasAttrString(m_pyInstance,legacyMethod) && |
360 m_processType == 0) | 368 m_processType == 0) |
361 { | 369 { |
362 m_processType = legacyProcess; | 370 m_processType = legacyProcess; |
382 if (m_debugFlag) cerr << "Process using (numpy) buffer interface." << endl; | 390 if (m_debugFlag) cerr << "Process using (numpy) buffer interface." << endl; |
383 } | 391 } |
384 | 392 |
385 if (m_vampyFlags & vf_ARRAY) { | 393 if (m_vampyFlags & vf_ARRAY) { |
386 #ifdef HAVE_NUMPY | 394 #ifdef HAVE_NUMPY |
387 m_processType = numpy_arrayProcess; | 395 if (m_numpyInstalled) { m_processType = numpy_arrayProcess; |
388 if (m_debugFlag) cerr << "Process using numpy array interface." << endl; | 396 if (m_debugFlag) |
397 cerr << "Process using numpy array interface." << endl; | |
398 } | |
399 else { | |
400 m_processFailure = true; | |
401 char method[]="initialise::setProcessType"; | |
402 cerr << PLUGIN_ERROR | |
403 << "This plugin requests the Numpy array interface by setting " | |
404 << " the vf_ARRAY flag in its __init__() function." << endl | |
405 << "However, we could not found a version of Numpy compatible with this build of Vampy." << endl | |
406 << "If you have a numerical library installed that supports the buffer interface, " << endl | |
407 << "you can request this interface instead by setting the vf_BUFFER flag." << endl; | |
408 } | |
389 #else | 409 #else |
390 cerr << "Error: This version of vampy was compiled without numpy support, " | 410 m_processFailure = true; |
391 << "however the vf_ARRAY flag is set for plugin: " << m_class << endl | 411 char method[]="initialise::setProcessType"; |
392 << "The default behaviour is: passing a python list of samples for each channel in process() " | 412 cerr << PLUGIN_ERROR |
393 << "or a list of memory buffers in processN(). " << endl | 413 << "Error: This version of vampy was compiled without numpy support, " |
394 << "This can be used create numpy arrays using the numpy.frombuffer() command." << endl; | 414 << "however the vf_ARRAY flag is set for plugin: " << m_class << endl |
415 << "The default behaviour is: passing a python list of samples for each channel in process() " | |
416 << "or a list of memory buffers in processN(). " << endl | |
417 << "This can be used create numpy arrays using the numpy.frombuffer() command." << endl; | |
395 #endif | 418 #endif |
396 } | 419 } |
397 | 420 |
398 if (!m_processType) | 421 if (!m_pyProcessCallable) |
399 { | 422 { |
400 m_processType = not_implemented; | 423 m_processType = not_implemented; |
401 m_pyProcess = NULL; | 424 m_pyProcess = NULL; |
402 m_pyProcessCallable = NULL; | |
403 char method[]="initialise::setProcessType"; | 425 char method[]="initialise::setProcessType"; |
404 cerr << PLUGIN_ERROR << " No process implementation found. Plugin will do nothing." << endl; | 426 cerr << PLUGIN_ERROR << " No process implementation found. Plugin will do nothing." << endl; |
427 m_processFailure = true; | |
405 } | 428 } |
406 } | 429 } |
407 | 430 |
408 void | 431 void |
409 PyPlugin::typeErrorHandler(char *method) const | 432 PyPlugin::typeErrorHandler(char *method, bool process) const |
410 { | 433 { |
411 bool strict = false; | 434 bool strict = false; |
412 while (m_ti.error) { | 435 while (m_ti.error) { |
413 PyTypeInterface::ValueError e = m_ti.getError(); | 436 PyTypeInterface::ValueError e = m_ti.getError(); |
437 #ifdef HAVE_NUMPY | |
438 // disable the process completely if numpy types are returned | |
439 // but a compatible version was not loaded. | |
440 // This is required because if an object is returned from | |
441 // the wrong build, malloc complains about its size | |
442 // (i.e. the interpreter doesn't free it properly) | |
443 // and the process may be leaking. | |
444 // Note: this only happens in the obscure situation when | |
445 // someone forces to return wrong numpy types from an | |
446 // incompatible version using the buffer interface. | |
447 // In this case the incampatible library is still usable, | |
448 // but manual conversion to python builtins is required. | |
449 // If the ARRAY interface is set but Numpy is not installed | |
450 // the process will be disabled already at initialisation. | |
451 if (process && !m_numpyInstalled && e.str().find("numpy")!=std::string::npos) | |
452 { | |
453 m_processFailure = true; | |
454 cerr << "Warning: incompatible numpy type encountered. Disabling process." << endl; | |
455 } | |
456 #endif | |
414 cerr << PLUGIN_ERROR << e.str() << endl; | 457 cerr << PLUGIN_ERROR << e.str() << endl; |
415 if (e.strict) strict = true; | 458 if (e.strict) strict = true; |
416 // e.print(); | 459 // e.print(); |
417 } | 460 } |
418 /// quit on hard errors like accessing NULL pointers or strict type conversion | 461 /// quit on hard errors like accessing NULL pointers or strict type conversion |
420 /// Otherwise most errors will go unnoticed apart from | 463 /// Otherwise most errors will go unnoticed apart from |
421 /// a messages in the terminal. | 464 /// a messages in the terminal. |
422 /// It would be best if hosts could catch an exception instead | 465 /// It would be best if hosts could catch an exception instead |
423 /// and display something meaningful to the user. | 466 /// and display something meaningful to the user. |
424 if (strict && m_quitOnErrorFlag) exit(EXIT_FAILURE); | 467 if (strict && m_quitOnErrorFlag) exit(EXIT_FAILURE); |
425 } | 468 |
426 | 469 // this would disable all outputs even if some are valid |
470 // if (process) m_processFailure = true; | |
471 | |
472 } | |
473 |