Mercurial > hg > vampy-host
comparison vampyhost.cpp @ 21:4b4a7ec1080d
Replace the pointer-holding CObject with a "real" Python object (next up: methods and attributes)
author | Chris Cannam |
---|---|
date | Tue, 25 Nov 2014 17:07:40 +0000 |
parents | 8e5cefa70c99 |
children | ccb5fef13104 |
comparison
equal
deleted
inserted
replaced
20:8e5cefa70c99 | 21:4b4a7ec1080d |
---|---|
42 using Vamp::HostExt::PluginLoader; | 42 using Vamp::HostExt::PluginLoader; |
43 | 43 |
44 #define HOST_VERSION "1.1" | 44 #define HOST_VERSION "1.1" |
45 | 45 |
46 // structure for holding plugin instance data | 46 // structure for holding plugin instance data |
47 struct PyPluginData | 47 struct PyPluginObject |
48 { | 48 { |
49 PyObject_HEAD | |
50 /* | |
49 PyPluginData(string k, Plugin *p, float rate) : | 51 PyPluginData(string k, Plugin *p, float rate) : |
50 key(k), | 52 key(k), |
51 plugin(p), | 53 plugin(p), |
52 inputSampleRate(rate), | 54 inputSampleRate(rate), |
53 isInitialised(false), | 55 isInitialised(false), |
54 channels(0), | 56 channels(0), |
55 blockSize(0), | 57 blockSize(0), |
56 stepSize(0) { | 58 stepSize(0) { |
57 } | 59 } |
58 | 60 */ |
59 string key; | 61 string *key; |
60 Plugin *plugin; | 62 Plugin *plugin; |
61 float inputSampleRate; | 63 float inputSampleRate; |
62 bool isInitialised; | 64 bool isInitialised; |
63 size_t channels; | 65 size_t channels; |
64 size_t blockSize; | 66 size_t blockSize; |
65 size_t stepSize; | 67 size_t stepSize; |
68 static PyPluginObject *create_internal(); | |
66 }; | 69 }; |
70 | |
71 PyAPI_DATA(PyTypeObject) Plugin_Type; | |
72 #define PyPlugin_Check(v) PyObject_TypeCheck(v, &Plugin_Type) | |
73 | |
74 static void | |
75 PyPluginObject_dealloc(PyPluginObject *self) | |
76 { | |
77 cerr << "PyPluginObject_dealloc" << endl; | |
78 delete self->key; | |
79 delete self->plugin; | |
80 PyObject_Del(self); | |
81 } | |
67 | 82 |
68 /* MODULE HELPER FUNCTIONS */ | 83 /* MODULE HELPER FUNCTIONS */ |
69 PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!! | 84 PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!! |
70 | 85 |
71 //!!! nb "The CObject API is deprecated" https://docs.python.org/2/c-api/cobject.html | 86 PyPluginObject * |
72 | 87 getPluginObject(PyObject *pyPluginHandle) |
73 PyPluginData * | 88 { |
74 getPluginData(PyObject *pyPluginHandle) | 89 cerr << "getPluginObject" << endl; |
75 { | 90 |
76 PyPluginData *pd = 0; | 91 PyPluginObject *pd = 0; |
77 if (PyCObject_Check(pyPluginHandle)) { | 92 if (PyPlugin_Check(pyPluginHandle)) { |
78 pd = (PyPluginData *)PyCObject_AsVoidPtr(pyPluginHandle); | 93 pd = (PyPluginObject *)pyPluginHandle; |
79 } | 94 } |
80 if (!pd || !pd->plugin) { | 95 if (!pd || !pd->plugin) { |
81 PyErr_SetString(PyExc_AttributeError, | 96 PyErr_SetString(PyExc_AttributeError, |
82 "Invalid or already deleted plugin handle."); | 97 "Invalid or already deleted plugin handle."); |
83 return 0; | 98 return 0; |
87 } | 102 } |
88 | 103 |
89 static PyObject * | 104 static PyObject * |
90 vampyhost_enumeratePlugins(PyObject *self, PyObject *args) | 105 vampyhost_enumeratePlugins(PyObject *self, PyObject *args) |
91 { | 106 { |
107 cerr << "vampyhost_enumeratePlugins" << endl; | |
108 | |
92 PluginLoader *loader = PluginLoader::getInstance(); | 109 PluginLoader *loader = PluginLoader::getInstance(); |
93 vector<PluginLoader::PluginKey> plugins = loader->listPlugins(); | 110 vector<PluginLoader::PluginKey> plugins = loader->listPlugins(); |
94 PyTypeConversions conv; | 111 PyTypeConversions conv; |
95 return conv.PyValue_From_StringVector(plugins); | 112 return conv.PyValue_From_StringVector(plugins); |
96 } | 113 } |
97 | 114 |
98 static PyObject * | 115 static PyObject * |
99 vampyhost_getPluginPath(PyObject *self, PyObject *args) | 116 vampyhost_getPluginPath(PyObject *self, PyObject *args) |
100 { | 117 { |
118 cerr << "vampyhost_getPluginPath" << endl; | |
119 | |
101 vector<string> path = PluginHostAdapter::getPluginPath(); | 120 vector<string> path = PluginHostAdapter::getPluginPath(); |
102 PyTypeConversions conv; | 121 PyTypeConversions conv; |
103 return conv.PyValue_From_StringVector(path); | 122 return conv.PyValue_From_StringVector(path); |
104 } | 123 } |
105 | 124 |
106 static string toPluginKey(PyObject *pyPluginKey) | 125 static string toPluginKey(PyObject *pyPluginKey) |
107 { | 126 { |
127 cerr << "toPluginKey" << endl; | |
128 | |
108 //convert to stl string | 129 //convert to stl string |
109 string pluginKey(PyString_AS_STRING(pyPluginKey)); | 130 string pluginKey(PyString_AS_STRING(pyPluginKey)); |
110 | 131 |
111 //check pluginKey Validity | 132 //check pluginKey Validity |
112 string::size_type ki = pluginKey.find(':'); | 133 string::size_type ki = pluginKey.find(':'); |
120 } | 141 } |
121 | 142 |
122 static PyObject * | 143 static PyObject * |
123 vampyhost_getLibraryFor(PyObject *self, PyObject *args) | 144 vampyhost_getLibraryFor(PyObject *self, PyObject *args) |
124 { | 145 { |
146 cerr << "vampyhost_getLibraryFor" << endl; | |
147 | |
125 PyObject *pyPluginKey; | 148 PyObject *pyPluginKey; |
126 | 149 |
127 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) { | 150 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) { |
128 PyErr_SetString(PyExc_TypeError, | 151 PyErr_SetString(PyExc_TypeError, |
129 "getLibraryPathForPlugin() takes plugin key (string) argument"); | 152 "getLibraryPathForPlugin() takes plugin key (string) argument"); |
139 } | 162 } |
140 | 163 |
141 static PyObject * | 164 static PyObject * |
142 vampyhost_getPluginCategory(PyObject *self, PyObject *args) | 165 vampyhost_getPluginCategory(PyObject *self, PyObject *args) |
143 { | 166 { |
167 cerr << "vampyhost_getPluginCategory" << endl; | |
168 | |
144 PyObject *pyPluginKey; | 169 PyObject *pyPluginKey; |
145 | 170 |
146 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) { | 171 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) { |
147 PyErr_SetString(PyExc_TypeError, | 172 PyErr_SetString(PyExc_TypeError, |
148 "getPluginCategory() takes plugin key (string) argument"); | 173 "getPluginCategory() takes plugin key (string) argument"); |
160 } | 185 } |
161 | 186 |
162 static PyObject * | 187 static PyObject * |
163 vampyhost_getOutputList(PyObject *self, PyObject *args) | 188 vampyhost_getOutputList(PyObject *self, PyObject *args) |
164 { | 189 { |
190 cerr << "vampyhost_getOutputList" << endl; | |
191 | |
165 PyObject *keyOrHandle; | 192 PyObject *keyOrHandle; |
166 Plugin::OutputList outputs; | 193 Plugin::OutputList outputs; |
167 | 194 |
168 if (!PyArg_ParseTuple(args, "O", &keyOrHandle)) { | 195 if (!PyArg_ParseTuple(args, "O", &keyOrHandle)) { |
169 PyErr_SetString(PyExc_TypeError, | 196 PyErr_SetString(PyExc_TypeError, |
194 | 221 |
195 } else { | 222 } else { |
196 | 223 |
197 // we have a loaded plugin handle | 224 // we have a loaded plugin handle |
198 | 225 |
199 PyPluginData *pd = getPluginData(keyOrHandle); | 226 PyPluginObject *pd = getPluginObject(keyOrHandle); |
200 if (!pd) return 0; | 227 if (!pd) return 0; |
201 | 228 |
202 outputs = pd->plugin->getOutputDescriptors(); | 229 outputs = pd->plugin->getOutputDescriptors(); |
203 } | 230 } |
204 | 231 |
214 } | 241 } |
215 | 242 |
216 static PyObject * | 243 static PyObject * |
217 vampyhost_loadPlugin(PyObject *self, PyObject *args) | 244 vampyhost_loadPlugin(PyObject *self, PyObject *args) |
218 { | 245 { |
246 cerr << "vampyhost_loadPlugin" << endl; | |
247 | |
219 PyObject *pyPluginKey; | 248 PyObject *pyPluginKey; |
220 float inputSampleRate; | 249 float inputSampleRate; |
221 | 250 |
222 if (!PyArg_ParseTuple(args, "Sf", | 251 if (!PyArg_ParseTuple(args, "Sf", |
223 &pyPluginKey, | 252 &pyPluginKey, |
237 string pyerr("Failed to load plugin: "); pyerr += pluginKey; | 266 string pyerr("Failed to load plugin: "); pyerr += pluginKey; |
238 PyErr_SetString(PyExc_TypeError,pyerr.c_str()); | 267 PyErr_SetString(PyExc_TypeError,pyerr.c_str()); |
239 return 0; | 268 return 0; |
240 } | 269 } |
241 | 270 |
242 PyPluginData *pd = new PyPluginData(pluginKey, plugin, inputSampleRate); | 271 PyPluginObject *pd = PyPluginObject::create_internal(); |
243 return PyCObject_FromVoidPtr(pd, 0); | 272 pd->key = new string(pluginKey); |
273 pd->plugin = plugin; | |
274 pd->inputSampleRate = inputSampleRate; | |
275 pd->isInitialised = false; | |
276 pd->channels = 0; | |
277 pd->blockSize = 0; | |
278 pd->stepSize = 0; | |
279 return (PyObject *)pd; | |
244 } | 280 } |
245 | 281 |
246 static PyObject * | 282 static PyObject * |
247 vampyhost_unloadPlugin(PyObject *self, PyObject *args) | 283 vampyhost_unloadPlugin(PyObject *self, PyObject *args) |
248 { | 284 { |
285 cerr << "vampyhost_unloadPlugin" << endl; | |
286 | |
249 PyObject *pyPluginHandle; | 287 PyObject *pyPluginHandle; |
250 | 288 |
251 if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) { | 289 if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) { |
252 PyErr_SetString(PyExc_TypeError, | 290 PyErr_SetString(PyExc_TypeError, |
253 "unloadPlugin() takes plugin handle (object) argument"); | 291 "unloadPlugin() takes plugin handle (object) argument"); |
254 return 0; | 292 return 0; |
255 } | 293 } |
256 | 294 |
257 PyPluginData *pd = getPluginData(pyPluginHandle); | 295 PyPluginObject *pd = getPluginObject(pyPluginHandle); |
258 if (!pd) return 0; | 296 if (!pd) return 0; |
259 | 297 |
260 /* Prevent repeated calls from causing segfault since it will fail | |
261 * type checking the 2nd time: */ | |
262 PyCObject_SetVoidPtr(pyPluginHandle, 0); | |
263 | |
264 delete pd->plugin; | 298 delete pd->plugin; |
265 delete pd; | 299 pd->plugin = 0; // This is checked by getPluginObject, so we |
266 return pyPluginHandle; | 300 // attempt to avoid repeated calls from blowing up |
301 | |
302 return Py_True; | |
267 } | 303 } |
268 | 304 |
269 static PyObject * | 305 static PyObject * |
270 vampyhost_initialise(PyObject *self, PyObject *args) | 306 vampyhost_initialise(PyObject *self, PyObject *args) |
271 { | 307 { |
308 cerr << "vampyhost_initialise" << endl; | |
309 | |
272 PyObject *pyPluginHandle; | 310 PyObject *pyPluginHandle; |
273 size_t channels, blockSize, stepSize; | 311 size_t channels, blockSize, stepSize; |
274 | 312 |
275 if (!PyArg_ParseTuple (args, "Onnn", &pyPluginHandle, | 313 if (!PyArg_ParseTuple (args, "Onnn", &pyPluginHandle, |
276 (size_t) &channels, | 314 (size_t) &channels, |
280 PyErr_SetString(PyExc_TypeError, | 318 PyErr_SetString(PyExc_TypeError, |
281 "initialise() takes plugin handle (object), channel count, step size, and block size arguments"); | 319 "initialise() takes plugin handle (object), channel count, step size, and block size arguments"); |
282 return 0; | 320 return 0; |
283 } | 321 } |
284 | 322 |
285 PyPluginData *pd = getPluginData(pyPluginHandle); | 323 PyPluginObject *pd = getPluginObject(pyPluginHandle); |
286 if (!pd) return 0; | 324 if (!pd) return 0; |
287 | 325 |
288 pd->channels = channels; | 326 pd->channels = channels; |
289 pd->stepSize = stepSize; | 327 pd->stepSize = stepSize; |
290 pd->blockSize = blockSize; | 328 pd->blockSize = blockSize; |
302 } | 340 } |
303 | 341 |
304 static PyObject * | 342 static PyObject * |
305 vampyhost_reset(PyObject *self, PyObject *args) | 343 vampyhost_reset(PyObject *self, PyObject *args) |
306 { | 344 { |
345 cerr << "vampyhost_reset" << endl; | |
346 | |
307 PyObject *pyPluginHandle; | 347 PyObject *pyPluginHandle; |
308 | 348 |
309 if (!PyArg_ParseTuple (args, "O", &pyPluginHandle)) | 349 if (!PyArg_ParseTuple (args, "O", &pyPluginHandle)) |
310 { | 350 { |
311 PyErr_SetString(PyExc_TypeError, | 351 PyErr_SetString(PyExc_TypeError, |
312 "initialise() takes plugin handle (object) argument"); | 352 "initialise() takes plugin handle (object) argument"); |
313 return 0; | 353 return 0; |
314 } | 354 } |
315 | 355 |
316 PyPluginData *pd = getPluginData(pyPluginHandle); | 356 PyPluginObject *pd = getPluginObject(pyPluginHandle); |
317 if (!pd) return 0; | 357 if (!pd) return 0; |
318 | 358 |
319 if (!pd->isInitialised) { | 359 if (!pd->isInitialised) { |
320 PyErr_SetString(PyExc_StandardError, | 360 PyErr_SetString(PyExc_StandardError, |
321 "Plugin has not been initialised"); | 361 "Plugin has not been initialised"); |
327 } | 367 } |
328 | 368 |
329 static PyObject * | 369 static PyObject * |
330 vampyhost_getParameter(PyObject *self, PyObject *args) | 370 vampyhost_getParameter(PyObject *self, PyObject *args) |
331 { | 371 { |
372 cerr << "vampyhost_getParameter" << endl; | |
373 | |
332 PyObject *pyPluginHandle; | 374 PyObject *pyPluginHandle; |
333 PyObject *pyParam; | 375 PyObject *pyParam; |
334 | 376 |
335 if (!PyArg_ParseTuple(args, "OS", &pyPluginHandle, &pyParam)) { | 377 if (!PyArg_ParseTuple(args, "OS", &pyPluginHandle, &pyParam)) { |
336 PyErr_SetString(PyExc_TypeError, | 378 PyErr_SetString(PyExc_TypeError, |
337 "getParameter() takes plugin handle (object) and parameter id (string) arguments"); | 379 "getParameter() takes plugin handle (object) and parameter id (string) arguments"); |
338 return 0; } | 380 return 0; } |
339 | 381 |
340 PyPluginData *pd = getPluginData(pyPluginHandle); | 382 PyPluginObject *pd = getPluginObject(pyPluginHandle); |
341 if (!pd) return 0; | 383 if (!pd) return 0; |
342 | 384 |
343 float value = pd->plugin->getParameter(PyString_AS_STRING(pyParam)); | 385 float value = pd->plugin->getParameter(PyString_AS_STRING(pyParam)); |
344 return PyFloat_FromDouble(double(value)); | 386 return PyFloat_FromDouble(double(value)); |
345 } | 387 } |
346 | 388 |
347 static PyObject * | 389 static PyObject * |
348 vampyhost_setParameter(PyObject *self, PyObject *args) | 390 vampyhost_setParameter(PyObject *self, PyObject *args) |
349 { | 391 { |
392 cerr << "vampyhost_setParameter" << endl; | |
393 | |
350 PyObject *pyPluginHandle; | 394 PyObject *pyPluginHandle; |
351 PyObject *pyParam; | 395 PyObject *pyParam; |
352 float value; | 396 float value; |
353 | 397 |
354 if (!PyArg_ParseTuple(args, "OSf", &pyPluginHandle, &pyParam, &value)) { | 398 if (!PyArg_ParseTuple(args, "OSf", &pyPluginHandle, &pyParam, &value)) { |
355 PyErr_SetString(PyExc_TypeError, | 399 PyErr_SetString(PyExc_TypeError, |
356 "setParameter() takes plugin handle (object), parameter id (string), and value (float) arguments"); | 400 "setParameter() takes plugin handle (object), parameter id (string), and value (float) arguments"); |
357 return 0; } | 401 return 0; } |
358 | 402 |
359 PyPluginData *pd = getPluginData(pyPluginHandle); | 403 PyPluginObject *pd = getPluginObject(pyPluginHandle); |
360 if (!pd) return 0; | 404 if (!pd) return 0; |
361 | 405 |
362 pd->plugin->setParameter(PyString_AS_STRING(pyParam), value); | 406 pd->plugin->setParameter(PyString_AS_STRING(pyParam), value); |
363 return Py_True; | 407 return Py_True; |
364 } | 408 } |
365 | 409 |
366 static PyObject * | 410 static PyObject * |
367 vampyhost_process(PyObject *self, PyObject *args) | 411 vampyhost_process(PyObject *self, PyObject *args) |
368 { | 412 { |
413 cerr << "vampyhost_process" << endl; | |
414 | |
369 PyObject *pyPluginHandle; | 415 PyObject *pyPluginHandle; |
370 PyObject *pyBuffer; | 416 PyObject *pyBuffer; |
371 PyObject *pyRealTime; | 417 PyObject *pyRealTime; |
372 | 418 |
373 if (!PyArg_ParseTuple(args, "OOO", | 419 if (!PyArg_ParseTuple(args, "OOO", |
385 if (!PyList_Check(pyBuffer)) { | 431 if (!PyList_Check(pyBuffer)) { |
386 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input."); | 432 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input."); |
387 return 0; | 433 return 0; |
388 } | 434 } |
389 | 435 |
390 PyPluginData *pd = getPluginData(pyPluginHandle); | 436 PyPluginObject *pd = getPluginObject(pyPluginHandle); |
391 if (!pd) return 0; | 437 if (!pd) return 0; |
392 | 438 |
393 if (!pd->isInitialised) { | 439 if (!pd->isInitialised) { |
394 PyErr_SetString(PyExc_StandardError, | 440 PyErr_SetString(PyExc_StandardError, |
395 "Plugin has not been initialised."); | 441 "Plugin has not been initialised."); |
486 cerr << "no you fool, here!" << endl; | 532 cerr << "no you fool, here!" << endl; |
487 | 533 |
488 return pyFs; | 534 return pyFs; |
489 } | 535 } |
490 | 536 |
537 static PyMethodDef PyPluginObject_methods[] = | |
538 { | |
539 {0, 0} | |
540 }; | |
541 | |
542 /* Doc:: 10.3 Type Objects */ /* static */ | |
543 PyTypeObject Plugin_Type = | |
544 { | |
545 PyObject_HEAD_INIT(NULL) | |
546 0, /*ob_size*/ | |
547 "vampyhost.Plugin", /*tp_name*/ | |
548 sizeof(PyPluginObject), /*tp_basicsize*/ | |
549 0, /*tp_itemsize*/ | |
550 (destructor)PyPluginObject_dealloc, /*tp_dealloc*/ | |
551 0, /*tp_print*/ | |
552 0, /*tp_getattr*/ | |
553 0, /*tp_setattr*/ | |
554 0, /*tp_compare*/ | |
555 0, /*tp_repr*/ | |
556 0, /*tp_as_number*/ | |
557 0, /*tp_as_sequence*/ | |
558 0, /*tp_as_mapping*/ | |
559 0, /*tp_hash*/ | |
560 0, /*tp_call*/ | |
561 0, /*tp_str*/ | |
562 0, /*tp_getattro*/ | |
563 0, /*tp_setattro*/ | |
564 0, /*tp_as_buffer*/ | |
565 Py_TPFLAGS_DEFAULT, /*tp_flags*/ | |
566 "Plugin Object", /*tp_doc*/ | |
567 0, /*tp_traverse*/ | |
568 0, /*tp_clear*/ | |
569 0, /*tp_richcompare*/ | |
570 0, /*tp_weaklistoffset*/ | |
571 0, /*tp_iter*/ | |
572 0, /*tp_iternext*/ | |
573 PyPluginObject_methods, /*tp_methods*/ | |
574 0, /*tp_members*/ | |
575 0, /*tp_getset*/ | |
576 0, /*tp_base*/ | |
577 0, /*tp_dict*/ | |
578 0, /*tp_descr_get*/ | |
579 0, /*tp_descr_set*/ | |
580 0, /*tp_dictoffset*/ | |
581 0, /*tp_init*/ | |
582 PyType_GenericAlloc, /*tp_alloc*/ | |
583 0, /*tp_new*/ | |
584 PyObject_Del, /*tp_free*/ | |
585 0, /*tp_is_gc*/ | |
586 }; | |
491 | 587 |
492 // module methods table | 588 // module methods table |
493 static PyMethodDef vampyhost_methods[] = { | 589 static PyMethodDef vampyhost_methods[] = { |
494 | 590 |
495 {"listPlugins", vampyhost_enumeratePlugins, METH_NOARGS, | 591 {"listPlugins", vampyhost_enumeratePlugins, METH_NOARGS, |
528 {"unloadPlugin", vampyhost_unloadPlugin, METH_VARARGS, | 624 {"unloadPlugin", vampyhost_unloadPlugin, METH_VARARGS, |
529 xx_foo_doc}, | 625 xx_foo_doc}, |
530 | 626 |
531 {0, 0} /* sentinel */ | 627 {0, 0} /* sentinel */ |
532 }; | 628 }; |
629 | |
630 PyPluginObject * | |
631 PyPluginObject::create_internal() | |
632 { | |
633 return (PyPluginObject *)PyType_GenericAlloc(&Plugin_Type, 0); | |
634 } | |
533 | 635 |
534 //Documentation for our new module | 636 //Documentation for our new module |
535 PyDoc_STRVAR(module_doc, "This is a template module just for instruction."); | 637 PyDoc_STRVAR(module_doc, "This is a template module just for instruction."); |
536 | 638 |
537 | 639 |