annotate vampyhost.cpp @ 27:fb6519598734

Some pruning
author Chris Cannam
date Wed, 26 Nov 2014 10:01:04 +0000
parents 014c48d6f360
children 1175e814954e
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@27 44 #define PY_ARRAY_UNIQUE_SYMBOL VAMPYHOST_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@17 443
Chris@17 444 cerr << "here!" << endl;
Chris@12 445
Chris@12 446 vector<vector<float> > data;
Chris@4 447 for (int c = 0; c < channels; ++c) {
Chris@4 448 PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
Chris@17 449 data.push_back(typeConv.PyValue_To_FloatVector(cbuf));
Chris@12 450 }
Chris@12 451
Chris@12 452 for (int c = 0; c < channels; ++c) {
Chris@17 453 if (data[c].size() != pd->blockSize) {
Chris@17 454 cerr << "Wrong number of samples on channel " << c << ": expected " << pd->blockSize << " (plugin's block size), got " << data[c].size() << endl;
Chris@17 455 PyErr_SetString(PyExc_TypeError, "Wrong number of samples");
Chris@17 456 return 0;
Chris@17 457 }
Chris@12 458 inbuf[c] = &data[c][0];
Chris@4 459 }
Chris@0 460
Chris@17 461 cerr << "no, here!" << endl;
Chris@17 462
Chris@12 463 RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
Chris@0 464
Chris@18 465 cerr << "no no, here!" << endl;
Chris@0 466
Chris@18 467 Plugin::FeatureSet fs = pd->plugin->process(inbuf, timeStamp);
Chris@0 468
Chris@4 469 delete[] inbuf;
Chris@0 470
Chris@18 471 cerr << "no no no, here!" << endl;
Chris@18 472
Chris@18 473 PyTypeConversions conv;
Chris@18 474
Chris@18 475 PyObject *pyFs = PyDict_New();
Chris@0 476
Chris@18 477 for (Plugin::FeatureSet::const_iterator fsi = fs.begin();
Chris@18 478 fsi != fs.end(); ++fsi) {
Chris@18 479
Chris@18 480 int fno = fsi->first;
Chris@18 481 const Plugin::FeatureList &fl = fsi->second;
Chris@18 482
Chris@18 483 if (!fl.empty()) {
Chris@18 484
Chris@18 485 PyObject *pyFl = PyList_New(fl.size());
Chris@18 486
Chris@18 487 for (int fli = 0; fli < (int)fl.size(); ++fli) {
Chris@18 488
Chris@18 489 const Plugin::Feature &f = fl[fli];
Chris@18 490 PyObject *pyF = PyDict_New();
Chris@18 491
Chris@18 492 if (f.hasTimestamp) {
Chris@18 493 PyDict_SetItemString
Chris@18 494 (pyF, "timestamp", PyRealTime_FromRealTime(f.timestamp));
Chris@18 495 }
Chris@18 496 if (f.hasDuration) {
Chris@18 497 PyDict_SetItemString
Chris@18 498 (pyF, "duration", PyRealTime_FromRealTime(f.duration));
Chris@18 499 }
Chris@18 500
Chris@18 501 PyDict_SetItemString
Chris@18 502 (pyF, "label", PyString_FromString(f.label.c_str()));
Chris@18 503
Chris@18 504 if (!f.values.empty()) {
Chris@18 505 PyDict_SetItemString
Chris@18 506 (pyF, "values", conv.FloatVector_To_PyArray(f.values));
Chris@18 507 }
Chris@18 508
Chris@18 509 PyList_SET_ITEM(pyFl, fli, pyF);
Chris@18 510 }
Chris@18 511
Chris@18 512 PyObject *pyN = PyInt_FromLong(fno);
Chris@18 513 PyDict_SetItem(pyFs, pyN, pyFl);
Chris@18 514 }
Chris@18 515 }
Chris@18 516
Chris@18 517 cerr << "no you fool, here!" << endl;
Chris@18 518
Chris@18 519 return pyFs;
Chris@0 520 }
Chris@0 521
Chris@23 522 static PyObject *
Chris@23 523 vampyhost_unload(PyObject *self, PyObject *)
Chris@23 524 {
Chris@23 525 cerr << "vampyhost_unloadPlugin" << endl;
Chris@23 526
Chris@23 527 PyPluginObject *pd = getPluginObject(self);
Chris@23 528 if (!pd) return 0;
Chris@23 529
Chris@23 530 delete pd->plugin;
Chris@23 531 pd->plugin = 0; // This is checked by getPluginObject, so we
Chris@23 532 // attempt to avoid repeated calls from blowing up
Chris@23 533
Chris@23 534 return Py_True;
Chris@23 535 }
Chris@23 536
Chris@21 537 static PyMethodDef PyPluginObject_methods[] =
Chris@21 538 {
Chris@23 539 {"getParameter", vampyhost_getParameter, METH_VARARGS,
Chris@23 540 xx_foo_doc}, //!!! fix all these!
Chris@23 541
Chris@23 542 {"setParameter", vampyhost_setParameter, METH_VARARGS,
Chris@23 543 xx_foo_doc},
Chris@23 544
Chris@23 545 {"initialise", vampyhost_initialise, METH_VARARGS,
Chris@23 546 xx_foo_doc},
Chris@23 547
Chris@23 548 {"reset", vampyhost_reset, METH_NOARGS,
Chris@23 549 xx_foo_doc},
Chris@23 550
Chris@23 551 {"process", vampyhost_process, METH_VARARGS,
Chris@23 552 xx_foo_doc},
Chris@23 553
Chris@23 554 {"unload", vampyhost_unload, METH_NOARGS,
Chris@23 555 xx_foo_doc},
Chris@23 556
Chris@21 557 {0, 0}
Chris@21 558 };
Chris@21 559
Chris@23 560 static int
Chris@23 561 PyPluginObject_setattr(PyPluginObject *self, char *name, PyObject *value)
Chris@23 562 {
Chris@23 563 return -1;
Chris@23 564 }
Chris@23 565
Chris@23 566 static PyObject *
Chris@23 567 PyPluginObject_getattr(PyPluginObject *self, char *name)
Chris@23 568 {
Chris@23 569 return Py_FindMethod(PyPluginObject_methods, (PyObject *)self, name);
Chris@23 570 }
Chris@23 571
Chris@21 572 /* Doc:: 10.3 Type Objects */ /* static */
Chris@21 573 PyTypeObject Plugin_Type =
Chris@21 574 {
Chris@21 575 PyObject_HEAD_INIT(NULL)
Chris@21 576 0, /*ob_size*/
Chris@21 577 "vampyhost.Plugin", /*tp_name*/
Chris@21 578 sizeof(PyPluginObject), /*tp_basicsize*/
Chris@21 579 0, /*tp_itemsize*/
Chris@21 580 (destructor)PyPluginObject_dealloc, /*tp_dealloc*/
Chris@21 581 0, /*tp_print*/
Chris@23 582 (getattrfunc)PyPluginObject_getattr, /*tp_getattr*/
Chris@23 583 (setattrfunc)PyPluginObject_setattr, /*tp_setattr*/
Chris@21 584 0, /*tp_compare*/
Chris@21 585 0, /*tp_repr*/
Chris@21 586 0, /*tp_as_number*/
Chris@21 587 0, /*tp_as_sequence*/
Chris@21 588 0, /*tp_as_mapping*/
Chris@21 589 0, /*tp_hash*/
Chris@21 590 0, /*tp_call*/
Chris@21 591 0, /*tp_str*/
Chris@21 592 0, /*tp_getattro*/
Chris@21 593 0, /*tp_setattro*/
Chris@21 594 0, /*tp_as_buffer*/
Chris@21 595 Py_TPFLAGS_DEFAULT, /*tp_flags*/
Chris@21 596 "Plugin Object", /*tp_doc*/
Chris@21 597 0, /*tp_traverse*/
Chris@21 598 0, /*tp_clear*/
Chris@21 599 0, /*tp_richcompare*/
Chris@21 600 0, /*tp_weaklistoffset*/
Chris@21 601 0, /*tp_iter*/
Chris@21 602 0, /*tp_iternext*/
Chris@21 603 PyPluginObject_methods, /*tp_methods*/
Chris@21 604 0, /*tp_members*/
Chris@21 605 0, /*tp_getset*/
Chris@21 606 0, /*tp_base*/
Chris@21 607 0, /*tp_dict*/
Chris@21 608 0, /*tp_descr_get*/
Chris@21 609 0, /*tp_descr_set*/
Chris@21 610 0, /*tp_dictoffset*/
Chris@21 611 0, /*tp_init*/
Chris@21 612 PyType_GenericAlloc, /*tp_alloc*/
Chris@21 613 0, /*tp_new*/
Chris@21 614 PyObject_Del, /*tp_free*/
Chris@21 615 0, /*tp_is_gc*/
Chris@21 616 };
Chris@0 617
Chris@18 618 // module methods table
Chris@0 619 static PyMethodDef vampyhost_methods[] = {
Chris@0 620
Chris@18 621 {"listPlugins", vampyhost_enumeratePlugins, METH_NOARGS,
Chris@0 622 xx_foo_doc},
Chris@0 623
Chris@15 624 {"getPluginPath", vampyhost_getPluginPath, METH_NOARGS,
Chris@15 625 xx_foo_doc},
Chris@15 626
Chris@18 627 {"getCategoryOf", vampyhost_getPluginCategory, METH_VARARGS,
Chris@0 628 xx_foo_doc},
Chris@0 629
Chris@18 630 {"getLibraryFor", vampyhost_getLibraryFor, METH_VARARGS,
Chris@0 631 xx_foo_doc},
Chris@0 632
Chris@18 633 {"getOutputsOf", vampyhost_getOutputList, METH_VARARGS,
Chris@0 634 xx_foo_doc},
Chris@0 635
Chris@0 636 {"loadPlugin", vampyhost_loadPlugin, METH_VARARGS,
Chris@0 637 xx_foo_doc},
Chris@0 638
Chris@16 639 {0, 0} /* sentinel */
Chris@0 640 };
Chris@0 641
Chris@21 642 PyPluginObject *
Chris@21 643 PyPluginObject::create_internal()
Chris@21 644 {
Chris@21 645 return (PyPluginObject *)PyType_GenericAlloc(&Plugin_Type, 0);
Chris@21 646 }
Chris@21 647
Chris@0 648 //Documentation for our new module
Chris@0 649 PyDoc_STRVAR(module_doc, "This is a template module just for instruction.");
Chris@0 650
Chris@25 651 static int
Chris@25 652 setint(PyObject *d, const char *name, int value)
Chris@25 653 {
Chris@25 654 PyObject *v;
Chris@25 655 int err;
Chris@25 656 v = PyInt_FromLong((long)value);
Chris@25 657 err = PyDict_SetItemString(d, name, v);
Chris@25 658 Py_XDECREF(v);
Chris@25 659 return err;
Chris@25 660 }
Chris@14 661
Chris@0 662 /* Initialization function for the module (*must* be called initxx) */
Chris@0 663
Chris@25 664 // module initialization (includes extern C {...} as necessary)
Chris@0 665 PyMODINIT_FUNC
Chris@0 666 initvampyhost(void)
Chris@0 667 {
Chris@0 668 PyObject *m;
Chris@0 669
Chris@25 670 if (PyType_Ready(&RealTime_Type) < 0) return;
Chris@25 671 if (PyType_Ready(&Plugin_Type) < 0) return;
Chris@0 672
Chris@0 673 m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc);
Chris@25 674 if (!m) {
Chris@25 675 cerr << "ERROR: initvampyhost: Failed to initialise module" << endl;
Chris@25 676 return;
Chris@25 677 }
Chris@0 678
Chris@14 679 import_array();
Chris@14 680
Chris@17 681 PyModule_AddObject(m, "RealTime", (PyObject *)&RealTime_Type);
Chris@25 682 PyModule_AddObject(m, "Plugin", (PyObject *)&Plugin_Type);
Chris@25 683
Chris@25 684 // Some enum types
Chris@25 685 PyObject *dict = PyModule_GetDict(m);
Chris@25 686 if (!dict) {
Chris@25 687 cerr << "ERROR: initvampyhost: Failed to obtain module dictionary" << endl;
Chris@25 688 return;
Chris@25 689 }
Chris@25 690
Chris@25 691 if (setint(dict, "OneSamplePerStep",
Chris@25 692 Plugin::OutputDescriptor::OneSamplePerStep) < 0 ||
Chris@25 693 setint(dict, "FixedSampleRate",
Chris@25 694 Plugin::OutputDescriptor::FixedSampleRate) < 0 ||
Chris@25 695 setint(dict, "VariableSampleRate",
Chris@25 696 Plugin::OutputDescriptor::VariableSampleRate) < 0 ||
Chris@25 697 setint(dict, "TimeDomain",
Chris@25 698 Plugin::TimeDomain) < 0 ||
Chris@25 699 setint(dict, "FrequencyDomain",
Chris@25 700 Plugin::FrequencyDomain) < 0) {
Chris@25 701 cerr << "ERROR: initvampyhost: Failed to add enums to module dictionary" << endl;
Chris@25 702 return;
Chris@25 703 }
Chris@0 704 }