annotate vampyhost.cpp @ 26:014c48d6f360

Now we know what we want from Vampy source, bring it in here again and lose the subrepo
author Chris Cannam
date Wed, 26 Nov 2014 09:48:35 +0000
parents 5379af6bef00
children fb6519598734
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@26 3 /*
Chris@26 4 VampyHost
Chris@26 5
Chris@26 6 Use Vamp audio analysis plugins in Python
Chris@26 7
Chris@26 8 Gyorgy Fazekas and Chris Cannam
Chris@26 9 Centre for Digital Music, Queen Mary, University of London
Chris@26 10 Copyright 2008-2014 Queen Mary, University of London
Chris@26 11
Chris@26 12 Permission is hereby granted, free of charge, to any person
Chris@26 13 obtaining a copy of this software and associated documentation
Chris@26 14 files (the "Software"), to deal in the Software without
Chris@26 15 restriction, including without limitation the rights to use, copy,
Chris@26 16 modify, merge, publish, distribute, sublicense, and/or sell copies
Chris@26 17 of the Software, and to permit persons to whom the Software is
Chris@26 18 furnished to do so, subject to the following conditions:
Chris@26 19
Chris@26 20 The above copyright notice and this permission notice shall be
Chris@26 21 included in all copies or substantial portions of the Software.
Chris@26 22
Chris@26 23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Chris@26 24 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Chris@26 25 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Chris@26 26 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
Chris@26 27 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
Chris@26 28 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
Chris@26 29 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Chris@26 30
Chris@26 31 Except as contained in this notice, the names of the Centre for
Chris@26 32 Digital Music; Queen Mary, University of London; and the authors
Chris@26 33 shall not be used in advertising or otherwise to promote the sale,
Chris@26 34 use or other dealings in this Software without prior written
Chris@26 35 authorization.
Chris@26 36 */
Chris@26 37
Chris@26 38 #include "PyRealTime.h"
Chris@26 39
Chris@0 40 //include for python extension module: must be first
Chris@0 41 #include <Python.h>
Chris@14 42
Chris@14 43 // define a unique API pointer
Chris@14 44 #define PY_ARRAY_UNIQUE_SYMBOL VAMPY_ARRAY_API
Chris@14 45 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
Chris@14 46 #include "numpy/arrayobject.h"
Chris@14 47
Chris@0 48 #include <vampyhost.h>
Chris@12 49
Chris@12 50 #define HAVE_NUMPY 1 // Required
Chris@12 51
Chris@0 52 //includes for vamp host
Chris@1 53 #include "vamp-hostsdk/Plugin.h"
Chris@1 54 #include "vamp-hostsdk/PluginHostAdapter.h"
Chris@1 55 #include "vamp-hostsdk/PluginChannelAdapter.h"
Chris@1 56 #include "vamp-hostsdk/PluginInputDomainAdapter.h"
Chris@1 57 #include "vamp-hostsdk/PluginLoader.h"
Chris@16 58
Chris@16 59 #include "PyTypeConversions.h"
Chris@16 60 #include "PyRealTime.h"
Chris@0 61
Chris@0 62 #include <iostream>
Chris@0 63 #include <fstream>
Chris@0 64 #include <set>
Chris@0 65 #include <sndfile.h>
Chris@0 66
Chris@0 67 #include <cstring>
Chris@0 68 #include <cstdlib>
Chris@0 69 #include <string>
Chris@0 70
Chris@0 71 #include <cmath>
Chris@0 72
Chris@0 73 using namespace std;
Chris@0 74 using namespace Vamp;
Chris@0 75
Chris@0 76 using Vamp::Plugin;
Chris@0 77 using Vamp::PluginHostAdapter;
Chris@0 78 using Vamp::RealTime;
Chris@0 79 using Vamp::HostExt::PluginLoader;
Chris@0 80
Chris@0 81 #define HOST_VERSION "1.1"
Chris@0 82
Chris@16 83 // structure for holding plugin instance data
Chris@21 84 struct PyPluginObject
Chris@16 85 {
Chris@21 86 PyObject_HEAD
Chris@21 87 string *key;
Chris@16 88 Plugin *plugin;
Chris@16 89 float inputSampleRate;
Chris@16 90 bool isInitialised;
Chris@16 91 size_t channels;
Chris@16 92 size_t blockSize;
Chris@16 93 size_t stepSize;
Chris@21 94 static PyPluginObject *create_internal();
Chris@16 95 };
Chris@0 96
Chris@21 97 PyAPI_DATA(PyTypeObject) Plugin_Type;
Chris@21 98 #define PyPlugin_Check(v) PyObject_TypeCheck(v, &Plugin_Type)
Chris@21 99
Chris@21 100 static void
Chris@21 101 PyPluginObject_dealloc(PyPluginObject *self)
Chris@21 102 {
Chris@21 103 cerr << "PyPluginObject_dealloc" << endl;
Chris@21 104 delete self->key;
Chris@21 105 delete self->plugin;
Chris@21 106 PyObject_Del(self);
Chris@21 107 }
Chris@21 108
Chris@2 109 PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!!
Chris@0 110
Chris@21 111 PyPluginObject *
Chris@21 112 getPluginObject(PyObject *pyPluginHandle)
Chris@21 113 {
Chris@21 114 cerr << "getPluginObject" << endl;
Chris@0 115
Chris@21 116 PyPluginObject *pd = 0;
Chris@21 117 if (PyPlugin_Check(pyPluginHandle)) {
Chris@21 118 pd = (PyPluginObject *)pyPluginHandle;
Chris@16 119 }
Chris@16 120 if (!pd || !pd->plugin) {
Chris@16 121 PyErr_SetString(PyExc_AttributeError,
Chris@16 122 "Invalid or already deleted plugin handle.");
Chris@16 123 return 0;
Chris@0 124 } else {
Chris@16 125 return pd;
Chris@0 126 }
Chris@0 127 }
Chris@0 128
Chris@0 129 static PyObject *
Chris@23 130 vampyhost_enumeratePlugins(PyObject *self, PyObject *)
Chris@0 131 {
Chris@21 132 cerr << "vampyhost_enumeratePlugins" << endl;
Chris@21 133
Chris@0 134 PluginLoader *loader = PluginLoader::getInstance();
Chris@0 135 vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
Chris@15 136 PyTypeConversions conv;
Chris@15 137 return conv.PyValue_From_StringVector(plugins);
Chris@0 138 }
Chris@0 139
Chris@15 140 static PyObject *
Chris@23 141 vampyhost_getPluginPath(PyObject *self, PyObject *)
Chris@15 142 {
Chris@21 143 cerr << "vampyhost_getPluginPath" << endl;
Chris@21 144
Chris@15 145 vector<string> path = PluginHostAdapter::getPluginPath();
Chris@15 146 PyTypeConversions conv;
Chris@15 147 return conv.PyValue_From_StringVector(path);
Chris@15 148 }
Chris@0 149
Chris@15 150 static string toPluginKey(PyObject *pyPluginKey)
Chris@0 151 {
Chris@21 152 cerr << "toPluginKey" << endl;
Chris@21 153
Chris@0 154 //convert to stl string
Chris@0 155 string pluginKey(PyString_AS_STRING(pyPluginKey));
Chris@0 156
Chris@0 157 //check pluginKey Validity
Chris@0 158 string::size_type ki = pluginKey.find(':');
Chris@0 159 if (ki == string::npos) {
Chris@0 160 PyErr_SetString(PyExc_TypeError,
Chris@15 161 "Plugin key must be of the form library:identifier");
Chris@15 162 return "";
Chris@0 163 }
Chris@0 164
Chris@15 165 return pluginKey;
Chris@15 166 }
Chris@15 167
Chris@15 168 static PyObject *
Chris@15 169 vampyhost_getLibraryFor(PyObject *self, PyObject *args)
Chris@15 170 {
Chris@21 171 cerr << "vampyhost_getLibraryFor" << endl;
Chris@21 172
Chris@15 173 PyObject *pyPluginKey;
Chris@15 174
Chris@15 175 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
Chris@15 176 PyErr_SetString(PyExc_TypeError,
Chris@15 177 "getLibraryPathForPlugin() takes plugin key (string) argument");
Chris@16 178 return 0; }
Chris@15 179
Chris@15 180 string pluginKey = toPluginKey(pyPluginKey);
Chris@16 181 if (pluginKey == "") return 0;
Chris@15 182
Chris@0 183 PluginLoader *loader = PluginLoader::getInstance();
Chris@0 184 string path = loader->getLibraryPathForPlugin(pluginKey);
Chris@0 185 PyObject *pyPath = PyString_FromString(path.c_str());
Chris@0 186 return pyPath;
Chris@0 187 }
Chris@0 188
Chris@0 189 static PyObject *
Chris@0 190 vampyhost_getPluginCategory(PyObject *self, PyObject *args)
Chris@0 191 {
Chris@21 192 cerr << "vampyhost_getPluginCategory" << endl;
Chris@21 193
Chris@0 194 PyObject *pyPluginKey;
Chris@0 195
Chris@0 196 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
Chris@0 197 PyErr_SetString(PyExc_TypeError,
Chris@15 198 "getPluginCategory() takes plugin key (string) argument");
Chris@16 199 return 0; }
Chris@0 200
Chris@15 201 string pluginKey = toPluginKey(pyPluginKey);
Chris@16 202 if (pluginKey == "") return 0;
Chris@0 203
Chris@0 204 PluginLoader *loader = PluginLoader::getInstance();
luis@7 205 PluginLoader::PluginCategoryHierarchy
Chris@0 206 category = loader->getPluginCategory(pluginKey);
Chris@0 207
Chris@15 208 PyTypeConversions conv;
Chris@15 209 return conv.PyValue_From_StringVector(category);
Chris@0 210 }
Chris@0 211
Chris@0 212 static PyObject *
Chris@0 213 vampyhost_getOutputList(PyObject *self, PyObject *args)
Chris@0 214 {
Chris@21 215 cerr << "vampyhost_getOutputList" << endl;
Chris@21 216
Chris@16 217 PyObject *keyOrHandle;
Chris@15 218 Plugin::OutputList outputs;
Chris@0 219
Chris@16 220 if (!PyArg_ParseTuple(args, "O", &keyOrHandle)) {
Chris@0 221 PyErr_SetString(PyExc_TypeError,
Chris@15 222 "getOutputList() takes plugin handle (object) or plugin key (string) argument");
Chris@16 223 return 0;
Chris@0 224 }
Chris@0 225
Chris@16 226 if (PyString_Check(keyOrHandle) ) {
Chris@0 227
Chris@15 228 // we have a plugin key
Chris@0 229
Chris@16 230 string pluginKey = toPluginKey(keyOrHandle);
Chris@16 231 if (pluginKey == "") return 0;
Chris@15 232
Chris@15 233 PluginLoader *loader = PluginLoader::getInstance();
Chris@15 234
Chris@15 235 Plugin *plugin = loader->loadPlugin
Chris@15 236 (pluginKey, 48000, PluginLoader::ADAPT_ALL_SAFE);
Chris@15 237 if (!plugin) {
Chris@15 238 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
Chris@15 239 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@16 240 return 0;
Chris@15 241 }
Chris@15 242
Chris@15 243 outputs = plugin->getOutputDescriptors();
Chris@15 244
Chris@15 245 delete plugin;
Chris@15 246
Chris@0 247 } else {
luis@7 248
Chris@15 249 // we have a loaded plugin handle
Chris@15 250
Chris@21 251 PyPluginObject *pd = getPluginObject(keyOrHandle);
Chris@16 252 if (!pd) return 0;
Chris@0 253
Chris@16 254 outputs = pd->plugin->getOutputDescriptors();
luis@7 255 }
luis@7 256
Chris@0 257 PyObject *pyList = PyList_New(outputs.size());
Chris@0 258
Chris@0 259 for (size_t i = 0; i < outputs.size(); ++i) {
luis@7 260 PyObject *pyOutputId =
Chris@0 261 PyString_FromString(outputs[i].identifier.c_str());
Chris@15 262 PyList_SET_ITEM(pyList, i, pyOutputId);
Chris@0 263 }
Chris@0 264
Chris@0 265 return pyList;
Chris@0 266 }
Chris@0 267
Chris@0 268 static PyObject *
Chris@0 269 vampyhost_loadPlugin(PyObject *self, PyObject *args)
Chris@0 270 {
Chris@21 271 cerr << "vampyhost_loadPlugin" << endl;
Chris@21 272
Chris@0 273 PyObject *pyPluginKey;
Chris@0 274 float inputSampleRate;
Chris@0 275
luis@7 276 if (!PyArg_ParseTuple(args, "Sf",
Chris@0 277 &pyPluginKey,
Chris@0 278 &inputSampleRate)) {
Chris@0 279 PyErr_SetString(PyExc_TypeError,
Chris@20 280 "loadPlugin() takes plugin key (string) and sample rate (float) arguments");
Chris@16 281 return 0; }
Chris@0 282
Chris@15 283 string pluginKey = toPluginKey(pyPluginKey);
Chris@16 284 if (pluginKey == "") return 0;
Chris@0 285
Chris@0 286 PluginLoader *loader = PluginLoader::getInstance();
luis@7 287
Chris@15 288 Plugin *plugin = loader->loadPlugin(pluginKey, inputSampleRate,
Chris@15 289 PluginLoader::ADAPT_ALL_SAFE);
luis@7 290 if (!plugin) {
Chris@0 291 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
luis@7 292 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@16 293 return 0;
luis@7 294 }
Chris@15 295
Chris@21 296 PyPluginObject *pd = PyPluginObject::create_internal();
Chris@21 297 pd->key = new string(pluginKey);
Chris@21 298 pd->plugin = plugin;
Chris@21 299 pd->inputSampleRate = inputSampleRate;
Chris@21 300 pd->isInitialised = false;
Chris@21 301 pd->channels = 0;
Chris@21 302 pd->blockSize = 0;
Chris@21 303 pd->stepSize = 0;
Chris@21 304 return (PyObject *)pd;
Chris@0 305 }
Chris@0 306
Chris@0 307 static PyObject *
Chris@0 308 vampyhost_initialise(PyObject *self, PyObject *args)
Chris@0 309 {
Chris@21 310 cerr << "vampyhost_initialise" << endl;
Chris@21 311
luis@7 312 size_t channels, blockSize, stepSize;
Chris@0 313
Chris@23 314 if (!PyArg_ParseTuple (args, "nnn",
luis@7 315 (size_t) &channels,
luis@7 316 (size_t) &stepSize,
Chris@23 317 (size_t) &blockSize)) {
Chris@0 318 PyErr_SetString(PyExc_TypeError,
Chris@23 319 "initialise() takes channel count, step size, and block size arguments");
Chris@16 320 return 0;
Chris@0 321 }
Chris@0 322
Chris@23 323 PyPluginObject *pd = getPluginObject(self);
Chris@16 324 if (!pd) return 0;
Chris@0 325
Chris@16 326 pd->channels = channels;
Chris@16 327 pd->stepSize = stepSize;
Chris@16 328 pd->blockSize = blockSize;
Chris@0 329
Chris@16 330 if (!pd->plugin->initialise(channels, stepSize, blockSize)) {
Chris@17 331 cerr << "Failed to initialise native plugin adapter with channels = " << channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << " and ADAPT_ALL_SAFE set" << endl;
Chris@0 332 PyErr_SetString(PyExc_TypeError,
Chris@17 333 "Plugin initialization failed");
Chris@16 334 return 0;
Chris@6 335 }
Chris@0 336
Chris@16 337 pd->isInitialised = true;
luis@7 338
Chris@0 339 return Py_True;
Chris@0 340 }
Chris@0 341
Chris@0 342 static PyObject *
Chris@23 343 vampyhost_reset(PyObject *self, PyObject *)
Chris@18 344 {
Chris@21 345 cerr << "vampyhost_reset" << endl;
Chris@21 346
Chris@23 347 PyPluginObject *pd = getPluginObject(self);
Chris@18 348 if (!pd) return 0;
Chris@18 349
Chris@18 350 if (!pd->isInitialised) {
Chris@18 351 PyErr_SetString(PyExc_StandardError,
Chris@18 352 "Plugin has not been initialised");
Chris@18 353 return 0;
Chris@18 354 }
Chris@18 355
Chris@18 356 pd->plugin->reset();
Chris@18 357 return Py_True;
Chris@18 358 }
Chris@18 359
Chris@18 360 static PyObject *
Chris@20 361 vampyhost_getParameter(PyObject *self, PyObject *args)
Chris@20 362 {
Chris@21 363 cerr << "vampyhost_getParameter" << endl;
Chris@21 364
Chris@20 365 PyObject *pyParam;
Chris@20 366
Chris@23 367 if (!PyArg_ParseTuple(args, "S", &pyParam)) {
Chris@20 368 PyErr_SetString(PyExc_TypeError,
Chris@23 369 "getParameter() takes parameter id (string) argument");
Chris@20 370 return 0; }
Chris@20 371
Chris@23 372 PyPluginObject *pd = getPluginObject(self);
Chris@20 373 if (!pd) return 0;
Chris@20 374
Chris@20 375 float value = pd->plugin->getParameter(PyString_AS_STRING(pyParam));
Chris@20 376 return PyFloat_FromDouble(double(value));
Chris@20 377 }
Chris@20 378
Chris@20 379 static PyObject *
Chris@20 380 vampyhost_setParameter(PyObject *self, PyObject *args)
Chris@20 381 {
Chris@21 382 cerr << "vampyhost_setParameter" << endl;
Chris@21 383
Chris@20 384 PyObject *pyParam;
Chris@20 385 float value;
Chris@20 386
Chris@23 387 if (!PyArg_ParseTuple(args, "Sf", &pyParam, &value)) {
Chris@20 388 PyErr_SetString(PyExc_TypeError,
Chris@23 389 "setParameter() takes parameter id (string), and value (float) arguments");
Chris@20 390 return 0; }
Chris@20 391
Chris@23 392 PyPluginObject *pd = getPluginObject(self);
Chris@20 393 if (!pd) return 0;
Chris@20 394
Chris@20 395 pd->plugin->setParameter(PyString_AS_STRING(pyParam), value);
Chris@20 396 return Py_True;
Chris@20 397 }
Chris@20 398
Chris@20 399 static PyObject *
Chris@0 400 vampyhost_process(PyObject *self, PyObject *args)
Chris@0 401 {
Chris@21 402 cerr << "vampyhost_process" << endl;
Chris@21 403
Chris@0 404 PyObject *pyBuffer;
Chris@0 405 PyObject *pyRealTime;
Chris@0 406
Chris@23 407 if (!PyArg_ParseTuple(args, "OO",
Chris@0 408 &pyBuffer, // Audio data
Chris@0 409 &pyRealTime)) { // TimeStamp
Chris@0 410 PyErr_SetString(PyExc_TypeError,
Chris@17 411 "process() takes plugin handle (object), buffer (2D array of channels * samples floats) and timestamp (RealTime) arguments");
Chris@16 412 return 0; }
Chris@0 413
Chris@0 414 if (!PyRealTime_Check(pyRealTime)) {
Chris@0 415 PyErr_SetString(PyExc_TypeError,"Valid timestamp required.");
Chris@16 416 return 0; }
Chris@0 417
Chris@17 418 if (!PyList_Check(pyBuffer)) {
Chris@17 419 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input.");
Chris@17 420 return 0;
Chris@17 421 }
Chris@17 422
Chris@23 423 PyPluginObject *pd = getPluginObject(self);
Chris@16 424 if (!pd) return 0;
Chris@0 425
Chris@0 426 if (!pd->isInitialised) {
Chris@0 427 PyErr_SetString(PyExc_StandardError,
Chris@0 428 "Plugin has not been initialised.");
Chris@16 429 return 0;
Chris@16 430 }
Chris@0 431
Chris@12 432 int channels = pd->channels;
Chris@0 433
Chris@4 434 if (PyList_GET_SIZE(pyBuffer) != channels) {
Chris@17 435 cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << endl;
Chris@4 436 PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
Chris@16 437 return 0;
Chris@4 438 }
Chris@0 439
Chris@4 440 float **inbuf = new float *[channels];
Chris@0 441
Chris@12 442 PyTypeConversions typeConv;
Chris@12 443 typeConv.setNumpyInstalled(true);
Chris@17 444
Chris@17 445 cerr << "here!" << endl;
Chris@12 446
Chris@12 447 vector<vector<float> > data;
Chris@4 448 for (int c = 0; c < channels; ++c) {
Chris@4 449 PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
Chris@17 450 data.push_back(typeConv.PyValue_To_FloatVector(cbuf));
Chris@12 451 }
Chris@12 452
Chris@12 453 for (int c = 0; c < channels; ++c) {
Chris@17 454 if (data[c].size() != pd->blockSize) {
Chris@17 455 cerr << "Wrong number of samples on channel " << c << ": expected " << pd->blockSize << " (plugin's block size), got " << data[c].size() << endl;
Chris@17 456 PyErr_SetString(PyExc_TypeError, "Wrong number of samples");
Chris@17 457 return 0;
Chris@17 458 }
Chris@12 459 inbuf[c] = &data[c][0];
Chris@4 460 }
Chris@0 461
Chris@17 462 cerr << "no, here!" << endl;
Chris@17 463
Chris@12 464 RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
Chris@0 465
Chris@18 466 cerr << "no no, here!" << endl;
Chris@0 467
Chris@18 468 Plugin::FeatureSet fs = pd->plugin->process(inbuf, timeStamp);
Chris@0 469
Chris@4 470 delete[] inbuf;
Chris@0 471
Chris@18 472 cerr << "no no no, here!" << endl;
Chris@18 473
Chris@18 474 PyTypeConversions conv;
Chris@18 475 conv.setNumpyInstalled(true);
Chris@18 476
Chris@18 477 PyObject *pyFs = PyDict_New();
Chris@0 478
Chris@18 479 for (Plugin::FeatureSet::const_iterator fsi = fs.begin();
Chris@18 480 fsi != fs.end(); ++fsi) {
Chris@18 481
Chris@18 482 int fno = fsi->first;
Chris@18 483 const Plugin::FeatureList &fl = fsi->second;
Chris@18 484
Chris@18 485 if (!fl.empty()) {
Chris@18 486
Chris@18 487 PyObject *pyFl = PyList_New(fl.size());
Chris@18 488
Chris@18 489 for (int fli = 0; fli < (int)fl.size(); ++fli) {
Chris@18 490
Chris@18 491 const Plugin::Feature &f = fl[fli];
Chris@18 492 PyObject *pyF = PyDict_New();
Chris@18 493
Chris@18 494 if (f.hasTimestamp) {
Chris@18 495 PyDict_SetItemString
Chris@18 496 (pyF, "timestamp", PyRealTime_FromRealTime(f.timestamp));
Chris@18 497 }
Chris@18 498 if (f.hasDuration) {
Chris@18 499 PyDict_SetItemString
Chris@18 500 (pyF, "duration", PyRealTime_FromRealTime(f.duration));
Chris@18 501 }
Chris@18 502
Chris@18 503 PyDict_SetItemString
Chris@18 504 (pyF, "label", PyString_FromString(f.label.c_str()));
Chris@18 505
Chris@18 506 if (!f.values.empty()) {
Chris@18 507 PyDict_SetItemString
Chris@18 508 (pyF, "values", conv.FloatVector_To_PyArray(f.values));
Chris@18 509 }
Chris@18 510
Chris@18 511 PyList_SET_ITEM(pyFl, fli, pyF);
Chris@18 512 }
Chris@18 513
Chris@18 514 PyObject *pyN = PyInt_FromLong(fno);
Chris@18 515 PyDict_SetItem(pyFs, pyN, pyFl);
Chris@18 516 }
Chris@18 517 }
Chris@18 518
Chris@18 519 cerr << "no you fool, here!" << endl;
Chris@18 520
Chris@18 521 return pyFs;
Chris@0 522 }
Chris@0 523
Chris@23 524 static PyObject *
Chris@23 525 vampyhost_unload(PyObject *self, PyObject *)
Chris@23 526 {
Chris@23 527 cerr << "vampyhost_unloadPlugin" << endl;
Chris@23 528
Chris@23 529 PyPluginObject *pd = getPluginObject(self);
Chris@23 530 if (!pd) return 0;
Chris@23 531
Chris@23 532 delete pd->plugin;
Chris@23 533 pd->plugin = 0; // This is checked by getPluginObject, so we
Chris@23 534 // attempt to avoid repeated calls from blowing up
Chris@23 535
Chris@23 536 return Py_True;
Chris@23 537 }
Chris@23 538
Chris@21 539 static PyMethodDef PyPluginObject_methods[] =
Chris@21 540 {
Chris@23 541 {"getParameter", vampyhost_getParameter, METH_VARARGS,
Chris@23 542 xx_foo_doc}, //!!! fix all these!
Chris@23 543
Chris@23 544 {"setParameter", vampyhost_setParameter, METH_VARARGS,
Chris@23 545 xx_foo_doc},
Chris@23 546
Chris@23 547 {"initialise", vampyhost_initialise, METH_VARARGS,
Chris@23 548 xx_foo_doc},
Chris@23 549
Chris@23 550 {"reset", vampyhost_reset, METH_NOARGS,
Chris@23 551 xx_foo_doc},
Chris@23 552
Chris@23 553 {"process", vampyhost_process, METH_VARARGS,
Chris@23 554 xx_foo_doc},
Chris@23 555
Chris@23 556 {"unload", vampyhost_unload, METH_NOARGS,
Chris@23 557 xx_foo_doc},
Chris@23 558
Chris@21 559 {0, 0}
Chris@21 560 };
Chris@21 561
Chris@23 562 static int
Chris@23 563 PyPluginObject_setattr(PyPluginObject *self, char *name, PyObject *value)
Chris@23 564 {
Chris@23 565 return -1;
Chris@23 566 }
Chris@23 567
Chris@23 568 static PyObject *
Chris@23 569 PyPluginObject_getattr(PyPluginObject *self, char *name)
Chris@23 570 {
Chris@23 571 return Py_FindMethod(PyPluginObject_methods, (PyObject *)self, name);
Chris@23 572 }
Chris@23 573
Chris@21 574 /* Doc:: 10.3 Type Objects */ /* static */
Chris@21 575 PyTypeObject Plugin_Type =
Chris@21 576 {
Chris@21 577 PyObject_HEAD_INIT(NULL)
Chris@21 578 0, /*ob_size*/
Chris@21 579 "vampyhost.Plugin", /*tp_name*/
Chris@21 580 sizeof(PyPluginObject), /*tp_basicsize*/
Chris@21 581 0, /*tp_itemsize*/
Chris@21 582 (destructor)PyPluginObject_dealloc, /*tp_dealloc*/
Chris@21 583 0, /*tp_print*/
Chris@23 584 (getattrfunc)PyPluginObject_getattr, /*tp_getattr*/
Chris@23 585 (setattrfunc)PyPluginObject_setattr, /*tp_setattr*/
Chris@21 586 0, /*tp_compare*/
Chris@21 587 0, /*tp_repr*/
Chris@21 588 0, /*tp_as_number*/
Chris@21 589 0, /*tp_as_sequence*/
Chris@21 590 0, /*tp_as_mapping*/
Chris@21 591 0, /*tp_hash*/
Chris@21 592 0, /*tp_call*/
Chris@21 593 0, /*tp_str*/
Chris@21 594 0, /*tp_getattro*/
Chris@21 595 0, /*tp_setattro*/
Chris@21 596 0, /*tp_as_buffer*/
Chris@21 597 Py_TPFLAGS_DEFAULT, /*tp_flags*/
Chris@21 598 "Plugin Object", /*tp_doc*/
Chris@21 599 0, /*tp_traverse*/
Chris@21 600 0, /*tp_clear*/
Chris@21 601 0, /*tp_richcompare*/
Chris@21 602 0, /*tp_weaklistoffset*/
Chris@21 603 0, /*tp_iter*/
Chris@21 604 0, /*tp_iternext*/
Chris@21 605 PyPluginObject_methods, /*tp_methods*/
Chris@21 606 0, /*tp_members*/
Chris@21 607 0, /*tp_getset*/
Chris@21 608 0, /*tp_base*/
Chris@21 609 0, /*tp_dict*/
Chris@21 610 0, /*tp_descr_get*/
Chris@21 611 0, /*tp_descr_set*/
Chris@21 612 0, /*tp_dictoffset*/
Chris@21 613 0, /*tp_init*/
Chris@21 614 PyType_GenericAlloc, /*tp_alloc*/
Chris@21 615 0, /*tp_new*/
Chris@21 616 PyObject_Del, /*tp_free*/
Chris@21 617 0, /*tp_is_gc*/
Chris@21 618 };
Chris@0 619
Chris@18 620 // module methods table
Chris@0 621 static PyMethodDef vampyhost_methods[] = {
Chris@0 622
Chris@18 623 {"listPlugins", vampyhost_enumeratePlugins, METH_NOARGS,
Chris@0 624 xx_foo_doc},
Chris@0 625
Chris@15 626 {"getPluginPath", vampyhost_getPluginPath, METH_NOARGS,
Chris@15 627 xx_foo_doc},
Chris@15 628
Chris@18 629 {"getCategoryOf", vampyhost_getPluginCategory, METH_VARARGS,
Chris@0 630 xx_foo_doc},
Chris@0 631
Chris@18 632 {"getLibraryFor", vampyhost_getLibraryFor, METH_VARARGS,
Chris@0 633 xx_foo_doc},
Chris@0 634
Chris@18 635 {"getOutputsOf", vampyhost_getOutputList, METH_VARARGS,
Chris@0 636 xx_foo_doc},
Chris@0 637
Chris@0 638 {"loadPlugin", vampyhost_loadPlugin, METH_VARARGS,
Chris@0 639 xx_foo_doc},
Chris@0 640
Chris@16 641 {0, 0} /* sentinel */
Chris@0 642 };
Chris@0 643
Chris@21 644 PyPluginObject *
Chris@21 645 PyPluginObject::create_internal()
Chris@21 646 {
Chris@21 647 return (PyPluginObject *)PyType_GenericAlloc(&Plugin_Type, 0);
Chris@21 648 }
Chris@21 649
Chris@0 650 //Documentation for our new module
Chris@0 651 PyDoc_STRVAR(module_doc, "This is a template module just for instruction.");
Chris@0 652
Chris@25 653 static int
Chris@25 654 setint(PyObject *d, const char *name, int value)
Chris@25 655 {
Chris@25 656 PyObject *v;
Chris@25 657 int err;
Chris@25 658 v = PyInt_FromLong((long)value);
Chris@25 659 err = PyDict_SetItemString(d, name, v);
Chris@25 660 Py_XDECREF(v);
Chris@25 661 return err;
Chris@25 662 }
Chris@14 663
Chris@0 664 /* Initialization function for the module (*must* be called initxx) */
Chris@0 665
Chris@25 666 // module initialization (includes extern C {...} as necessary)
Chris@0 667 PyMODINIT_FUNC
Chris@0 668 initvampyhost(void)
Chris@0 669 {
Chris@0 670 PyObject *m;
Chris@0 671
Chris@25 672 if (PyType_Ready(&RealTime_Type) < 0) return;
Chris@25 673 if (PyType_Ready(&Plugin_Type) < 0) return;
Chris@0 674
Chris@0 675 m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc);
Chris@25 676 if (!m) {
Chris@25 677 cerr << "ERROR: initvampyhost: Failed to initialise module" << endl;
Chris@25 678 return;
Chris@25 679 }
Chris@0 680
Chris@14 681 import_array();
Chris@14 682
Chris@17 683 PyModule_AddObject(m, "RealTime", (PyObject *)&RealTime_Type);
Chris@25 684 PyModule_AddObject(m, "Plugin", (PyObject *)&Plugin_Type);
Chris@25 685
Chris@25 686 // Some enum types
Chris@25 687 PyObject *dict = PyModule_GetDict(m);
Chris@25 688 if (!dict) {
Chris@25 689 cerr << "ERROR: initvampyhost: Failed to obtain module dictionary" << endl;
Chris@25 690 return;
Chris@25 691 }
Chris@25 692
Chris@25 693 if (setint(dict, "OneSamplePerStep",
Chris@25 694 Plugin::OutputDescriptor::OneSamplePerStep) < 0 ||
Chris@25 695 setint(dict, "FixedSampleRate",
Chris@25 696 Plugin::OutputDescriptor::FixedSampleRate) < 0 ||
Chris@25 697 setint(dict, "VariableSampleRate",
Chris@25 698 Plugin::OutputDescriptor::VariableSampleRate) < 0 ||
Chris@25 699 setint(dict, "TimeDomain",
Chris@25 700 Plugin::TimeDomain) < 0 ||
Chris@25 701 setint(dict, "FrequencyDomain",
Chris@25 702 Plugin::FrequencyDomain) < 0) {
Chris@25 703 cerr << "ERROR: initvampyhost: Failed to add enums to module dictionary" << endl;
Chris@25 704 return;
Chris@25 705 }
Chris@0 706 }