Mercurial > hg > vampy
comparison PyPlugin.cpp @ 24:7d28bed0864e
* Rearrange Python plugin construction.
Formerly, the PyPluginAdapter has retained a single plugin instance pointer
for each plugin found, and its createPlugin method has simply returned a new
PyPlugin object wrapping the same instance pointer. This has a couple of
negative consequences:
- Because construction of the actual Python instance occurred before the
wrapper was constructed, it was not possible to pass arguments (i.e.
the sample rate) from the wrapper constructor to the Python plugin
instance constructor -- they had to be passed later, to initialise,
disadvantaging those plugins that would like to use the sample rate
for parameter & step/block size calculations etc
- Because there was only a single Python plugin instance, it was not
possible to run more than one instance at once with any isolation
This rework instead stores the Python class pointer (rather than instance
pointer) in the PyPluginAdapter, and each PyPlugin wrapper instance creates
its own Python plugin instance. What could possibly go wrong?
author | cannam |
---|---|
date | Mon, 17 Aug 2009 15:22:06 +0000 |
parents | 1ae350e97f93 |
children | 046ba4183373 |
comparison
equal
deleted
inserted
replaced
23:535d559300dc | 24:7d28bed0864e |
---|---|
73 static std::map<std::string, p::eParmDescriptors> parmKeys; | 73 static std::map<std::string, p::eParmDescriptors> parmKeys; |
74 | 74 |
75 Mutex PyPlugin::m_pythonInterpreterMutex; | 75 Mutex PyPlugin::m_pythonInterpreterMutex; |
76 static bool isMapInitialised = false; | 76 static bool isMapInitialised = false; |
77 | 77 |
78 PyPlugin::PyPlugin(std::string pluginKey,float inputSampleRate, PyObject *pyInstance) : | 78 PyPlugin::PyPlugin(std::string pluginKey, float inputSampleRate, PyObject *pyClass) : |
79 Plugin(inputSampleRate), | 79 Plugin(inputSampleRate), |
80 m_pyInstance(pyInstance), | 80 m_pyClass(pyClass), |
81 m_stepSize(0), | 81 m_stepSize(0), |
82 m_blockSize(0), | 82 m_blockSize(0), |
83 m_channels(0), | 83 m_channels(0), |
84 m_plugin(pluginKey), | 84 m_plugin(pluginKey), |
85 m_class(pluginKey.substr(pluginKey.rfind(':')+1,pluginKey.size()-1)), | 85 m_class(pluginKey.substr(pluginKey.rfind(':')+1,pluginKey.size()-1)), |
86 m_path((pluginKey.substr(0,pluginKey.rfind(pathsep)))), | 86 m_path((pluginKey.substr(0,pluginKey.rfind(pathsep)))), |
87 m_processType(0), | 87 m_processType(0), |
88 m_pyProcess(NULL), | 88 m_pyProcess(NULL), |
89 m_inputDomain(TimeDomain) | 89 m_inputDomain(TimeDomain) |
90 { | 90 { |
91 // Create an instance | |
92 PyObject *pyInputSampleRate = PyFloat_FromDouble(inputSampleRate); | |
93 PyObject *args = PyTuple_Pack(1, pyInputSampleRate); | |
94 | |
95 m_pyInstance = PyObject_CallObject(m_pyClass, args); | |
96 | |
97 if (!m_pyInstance) { | |
98 cerr << "PyPlugin::PyPlugin: Failed to create Python plugin instance for key \"" << pluginKey << "\" (is the 1-arg class constructor from sample rate correctly provided?)" << endl; | |
99 throw std::string("Constructor failed"); | |
100 } | |
101 | |
102 Py_DECREF(args); | |
103 Py_DECREF(pyInputSampleRate); | |
91 } | 104 } |
92 | 105 |
93 PyPlugin::~PyPlugin() | 106 PyPlugin::~PyPlugin() |
94 { | 107 { |
108 if (m_pyInstance) Py_DECREF(m_pyInstance); | |
109 | |
95 Py_CLEAR(m_pyProcess); | 110 Py_CLEAR(m_pyProcess); |
96 #ifdef _DEBUG | 111 #ifdef _DEBUG |
97 cerr << "PyPlugin::PyPlugin:" << m_class | 112 cerr << "PyPlugin::PyPlugin:" << m_class |
98 << " Instance deleted." << endl; | 113 << " Instance deleted." << endl; |
99 #endif | 114 #endif |
100 } | 115 } |
101 | 116 |
102 | 117 |
103 string | 118 string |
220 } | 235 } |
221 | 236 |
222 int | 237 int |
223 PyPlugin::getPluginVersion() const | 238 PyPlugin::getPluginVersion() const |
224 { | 239 { |
225 return 2; | 240 //!!! implement |
241 | |
242 return 2; | |
226 } | 243 } |
227 | 244 |
228 string | 245 string |
229 PyPlugin::getCopyright() const | 246 PyPlugin::getCopyright() const |
230 { | 247 { |
250 | 267 |
251 | 268 |
252 rString=PyString_AsString(pyString); | 269 rString=PyString_AsString(pyString); |
253 Py_CLEAR(pyString); | 270 Py_CLEAR(pyString); |
254 } | 271 } |
255 return rString; | 272 |
273 return rString; | |
256 } | 274 } |
257 | 275 |
258 | 276 |
259 bool | 277 bool |
260 PyPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) | 278 PyPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) |
262 //useful for debugging Python plugins | 280 //useful for debugging Python plugins |
263 char method[]="initialise"; | 281 char method[]="initialise"; |
264 cerr << "[call] " << method << endl; | 282 cerr << "[call] " << method << endl; |
265 | 283 |
266 //placing Mutex before these calls causes deadlock | 284 //placing Mutex before these calls causes deadlock |
267 if (channels < getMinChannelCount() || | 285 if (channels < getMinChannelCount() || |
268 channels > getMaxChannelCount()) return false; | 286 channels > getMaxChannelCount()) return false; |
269 | 287 |
270 m_inputDomain = getInputDomain(); | 288 m_inputDomain = getInputDomain(); |
271 | 289 |
272 MutexLocker locker(&m_pythonInterpreterMutex); | 290 MutexLocker locker(&m_pythonInterpreterMutex); |
273 | 291 |
298 if (!m_processType) | 316 if (!m_processType) |
299 { | 317 { |
300 m_processType = not_implemented; | 318 m_processType = not_implemented; |
301 m_pyProcess = NULL; | 319 m_pyProcess = NULL; |
302 cerr << "Warning: Python plugin [" << m_class << "::" << method | 320 cerr << "Warning: Python plugin [" << m_class << "::" << method |
303 << "] No process implementation found. Plugin will do nothing." << endl; | 321 << "] No process implementation found. Plugin will do nothing." << endl; |
304 } | 322 } |
305 | 323 |
306 | 324 //Check if the method is implemented in Python else return false |
307 //Check if the method is implemented in Python else return false | 325 if (PyObject_HasAttrString(m_pyInstance,method)) { |
308 if (PyObject_HasAttrString(m_pyInstance,method)) { | |
309 | 326 |
310 PyObject *pyMethod = PyString_FromString(method); | 327 PyObject *pyMethod = PyString_FromString(method); |
311 PyObject *pyChannels = PyInt_FromSsize_t((Py_ssize_t)channels); | 328 PyObject *pyChannels = PyInt_FromSsize_t((Py_ssize_t)channels); |
312 PyObject *pyStepSize = PyInt_FromSsize_t((Py_ssize_t)m_stepSize); | 329 PyObject *pyStepSize = PyInt_FromSsize_t((Py_ssize_t)m_stepSize); |
313 PyObject *pyBlockSize = PyInt_FromSsize_t((Py_ssize_t)blockSize); | 330 PyObject *pyBlockSize = PyInt_FromSsize_t((Py_ssize_t)blockSize); |
314 PyObject *pyInputSampleRate = PyFloat_FromDouble((double)m_inputSampleRate); | 331 //Call the method |
315 | 332 PyObject *pyBool = |
316 //Call the method | 333 PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyChannels,pyStepSize,pyBlockSize,NULL); |
317 PyObject *pyBool = | |
318 PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyChannels,pyStepSize,pyBlockSize,pyInputSampleRate,NULL); | |
319 | 334 |
320 Py_DECREF(pyMethod); | 335 Py_DECREF(pyMethod); |
321 Py_DECREF(pyChannels); | 336 Py_DECREF(pyChannels); |
322 Py_DECREF(pyStepSize); | 337 Py_DECREF(pyStepSize); |
323 Py_DECREF(pyBlockSize); | 338 Py_DECREF(pyBlockSize); |
324 Py_DECREF(pyInputSampleRate); | 339 |
325 | 340 //Check return value |
326 //Check return value | 341 if (PyErr_Occurred() || !PyBool_Check(pyBool)) { |
327 if (PyErr_Occurred() || !PyBool_Check(pyBool)) { | 342 PyErr_Print(); PyErr_Clear(); |
328 PyErr_Print(); PyErr_Clear(); | 343 Py_CLEAR(pyBool); |
329 Py_CLEAR(pyBool); | 344 cerr << "ERROR: In Python plugin [" << m_class << "::" << method |
330 cerr << "ERROR: In Python plugin [" << m_class << "::" << method | 345 << "] Expected Bool return value." << endl; |
331 << "] Expected Bool return value." << endl; | 346 return false; |
332 return false; | 347 } |
333 } | 348 |
334 | 349 if (pyBool == Py_True) { |
335 if (pyBool == Py_True) { | 350 Py_CLEAR(pyBool); |
336 Py_CLEAR(pyBool); | 351 return true; |
337 return true; | 352 } else { |
338 } else { | 353 Py_CLEAR(pyBool); |
339 Py_CLEAR(pyBool); | 354 return false; |
340 return false;} | 355 } |
341 } | 356 } |
342 return false; | 357 return false; |
343 } | 358 } |
344 | 359 |
345 void | 360 void |
346 PyPlugin::reset() | 361 PyPlugin::reset() |