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