annotate vampyhost.cpp @ 12:d0d91312e5a2

Prepare attempt to build using VamPy structures
author Chris Cannam
date Thu, 20 Nov 2014 13:03:50 +0000
parents d29c25695f5e
children 8565ec421f9c
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@0 3 //include for python extension module: must be first
Chris@0 4 #include <Python.h>
Chris@0 5 #include <vampyhost.h>
Chris@12 6
Chris@12 7 #include <PyRealTime.h>
Chris@0 8
Chris@4 9 //!!! NB all our NumPy stuff is currently using the deprecated API --
Chris@4 10 //!!! need to work out how to update this
Chris@12 11 //#include "numpy/arrayobject.h"
Chris@12 12
Chris@12 13 #define HAVE_NUMPY 1 // Required
Chris@12 14
Chris@12 15 #include "PyTypeConversions.h"
Chris@4 16
Chris@0 17 //includes for vamp host
Chris@1 18 #include "vamp-hostsdk/Plugin.h"
Chris@1 19 #include "vamp-hostsdk/PluginHostAdapter.h"
Chris@1 20 #include "vamp-hostsdk/PluginChannelAdapter.h"
Chris@1 21 #include "vamp-hostsdk/PluginInputDomainAdapter.h"
Chris@1 22 #include "vamp-hostsdk/PluginLoader.h"
Chris@0 23 //#include "vamp/vamp.h"
Chris@0 24
Chris@0 25 #include <iostream>
Chris@0 26 #include <fstream>
Chris@0 27 #include <set>
Chris@0 28 #include <sndfile.h>
Chris@0 29
Chris@0 30 #include <cstring>
Chris@0 31 #include <cstdlib>
Chris@0 32 #include <string>
Chris@0 33
Chris@0 34 #include "system.h"
Chris@0 35
Chris@0 36 #include <cmath>
Chris@0 37
Chris@0 38
Chris@0 39 using namespace std;
Chris@0 40 using namespace Vamp;
Chris@0 41
Chris@0 42 using Vamp::Plugin;
Chris@0 43 using Vamp::PluginHostAdapter;
Chris@0 44 using Vamp::RealTime;
Chris@0 45 using Vamp::HostExt::PluginLoader;
Chris@0 46
Chris@0 47 #define HOST_VERSION "1.1"
Chris@0 48
Chris@0 49
Chris@0 50 /* MODULE HELPER FUNCTIONS */
Chris@2 51 PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!!
Chris@0 52
Chris@0 53 /*obtain C plugin handle and key from pyCobject */
luis@7 54 bool getPluginHandle
Chris@0 55 (PyObject *pyPluginHandle, Plugin **plugin, string **pKey=NULL) {
Chris@0 56
Chris@0 57 //char errormsg[]="Wrong input argument: Plugin Handle required.";
Chris@0 58
Chris@0 59 *plugin = NULL;
Chris@2 60 if (!PyCObject_Check(pyPluginHandle)) return false;
Chris@0 61
Chris@0 62 //try to convert to Plugin pointer
Chris@0 63 Plugin *p = (Plugin*) PyCObject_AsVoidPtr(pyPluginHandle);
luis@7 64 if (!p) return false;
Chris@0 65
Chris@0 66 string pId;
Chris@0 67
Chris@0 68 if (pKey) {
Chris@0 69 *pKey = (string*) PyCObject_GetDesc(pyPluginHandle);
Chris@2 70 if (!*pKey) return false;
Chris@0 71 pId = *(string*) *pKey;
Chris@0 72
Chris@0 73 } else {
Chris@0 74
Chris@0 75 void *pKey = PyCObject_GetDesc(pyPluginHandle);
Chris@2 76 if (!pKey) return false;
Chris@0 77 pId = *(string*) pKey;
Chris@0 78 }
luis@7 79
Chris@0 80 string::size_type pos = pId.find(':');
Chris@2 81 if (pos == string::npos) return false;
Chris@0 82
Chris@0 83 pId = pId.substr(pId.rfind(':')+1);
luis@7 84 string identifier = p->getIdentifier();
luis@7 85
Chris@2 86 if (pId.compare(identifier)) return false;
Chris@0 87
Chris@0 88 *plugin = p;
Chris@0 89 return true;
Chris@0 90 }
Chris@0 91
Chris@0 92 /*
Chris@0 93 ----------------------------------------------------------------
Chris@0 94 */
Chris@0 95
Chris@0 96
Chris@0 97
Chris@0 98 /*
luis@7 99 VAMPYHOST MAIN
luis@7 100 ---------------------------------------------------------------------
Chris@0 101 */
Chris@0 102
Chris@0 103 /* ENUMERATE PLUGINS*/
Chris@0 104
Chris@0 105 static PyObject *
Chris@0 106 vampyhost_enumeratePlugins(PyObject *self, PyObject *args)
Chris@0 107 {
Chris@0 108 string retType;
luis@7 109
Chris@0 110 if (!PyArg_ParseTuple(args, "|s:enumeratePlugins", &retType))
Chris@0 111 return NULL;
Chris@0 112
Chris@0 113 //list available plugins
Chris@0 114 PluginLoader *loader = PluginLoader::getInstance();
Chris@0 115 vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
Chris@0 116
Chris@0 117 //library Map
Chris@0 118 typedef multimap<string, PluginLoader::PluginKey> LibraryMap;
Chris@0 119 LibraryMap libraryMap;
Chris@0 120
Chris@0 121 //New list object
Chris@0 122 PyObject *pyList = PyList_New(plugins.size());
Chris@0 123
Chris@0 124 for (size_t i = 0; i < plugins.size(); ++i) {
Chris@0 125 string path = loader->getLibraryPathForPlugin(plugins[i]);
Chris@0 126 libraryMap.insert(LibraryMap::value_type(path, plugins[i]));
Chris@0 127
Chris@0 128 PyObject *pyPluginKey = PyString_FromString(plugins[i].c_str());
Chris@0 129 PyList_SET_ITEM(pyList,i,pyPluginKey);
luis@7 130
Chris@0 131 }
Chris@0 132
Chris@0 133 PyList_Sort(pyList);
Chris@0 134 return pyList;
Chris@0 135 }
Chris@0 136
Chris@0 137
Chris@0 138 /* GET PLUGIN LIBRARY PATH*/
Chris@0 139
Chris@0 140 static PyObject *
Chris@0 141 vampyhost_getLibraryPath(PyObject *self, PyObject *args)
Chris@0 142 {
Chris@0 143 PyObject *pyPluginKey;
Chris@0 144
Chris@0 145 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
Chris@0 146 PyErr_SetString(PyExc_TypeError,
Chris@0 147 "String input argument required: pluginKey");
Chris@0 148 return NULL; }
Chris@0 149
Chris@0 150 //convert to stl string
Chris@0 151 string pluginKey(PyString_AS_STRING(pyPluginKey));
Chris@0 152
Chris@0 153 //check pluginKey Validity
Chris@0 154 string::size_type ki = pluginKey.find(':');
Chris@0 155 if (ki == string::npos) {
Chris@0 156 PyErr_SetString(PyExc_TypeError,
luis@7 157 "String input argument required: pluginLibrary:Identifier");
Chris@0 158 return NULL;
Chris@0 159 }
Chris@0 160
Chris@0 161 PluginLoader *loader = PluginLoader::getInstance();
Chris@0 162 string path = loader->getLibraryPathForPlugin(pluginKey);
Chris@0 163 PyObject *pyPath = PyString_FromString(path.c_str());
Chris@0 164 return pyPath;
Chris@0 165 }
Chris@0 166
Chris@0 167
Chris@0 168 /* GET PLUGIN CATEGORY*/
Chris@0 169
Chris@0 170 static PyObject *
Chris@0 171 vampyhost_getPluginCategory(PyObject *self, PyObject *args)
Chris@0 172 {
Chris@0 173 PyObject *pyPluginKey;
Chris@0 174
Chris@0 175 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
Chris@0 176 PyErr_SetString(PyExc_TypeError,
Chris@0 177 "String input argument required: pluginKey");
Chris@0 178 return NULL; }
Chris@0 179
Chris@0 180 //convert to stl string
Chris@0 181 string pluginKey(PyString_AS_STRING(pyPluginKey));
Chris@0 182
Chris@0 183 //check pluginKey Validity
Chris@0 184 string::size_type ki = pluginKey.find(':');
Chris@0 185 if (ki == string::npos) {
Chris@0 186 PyErr_SetString(PyExc_TypeError,
luis@7 187 "String input argument required: pluginLibrary:Identifier");
Chris@0 188 return NULL;
Chris@0 189 }
Chris@0 190
Chris@0 191 PluginLoader *loader = PluginLoader::getInstance();
luis@7 192 PluginLoader::PluginCategoryHierarchy
Chris@0 193 category = loader->getPluginCategory(pluginKey);
Chris@0 194 string catstring;
Chris@0 195
Chris@0 196 if (!category.empty()) {
Chris@0 197 catstring = "";
Chris@0 198 for (size_t ci = 0; ci < category.size(); ++ci) {
Chris@0 199 catstring.append(category[ci]);
Chris@0 200 catstring.append(" ");
Chris@0 201 }
Chris@0 202 PyObject *pyCat = PyString_FromString(catstring.c_str());
Chris@0 203 return pyCat;
Chris@0 204 }
Chris@0 205 PyObject *pyCat = PyString_FromString("");
Chris@0 206 return pyCat;
Chris@0 207 }
Chris@0 208
Chris@0 209
Chris@0 210
Chris@0 211 /* GET PLUGIN OUTPUT LIST*/
Chris@0 212
Chris@0 213 static PyObject *
Chris@0 214 vampyhost_getOutputList(PyObject *self, PyObject *args)
Chris@0 215 {
Chris@0 216 PyObject *pyPluginHandle;
Chris@0 217 string pluginKey;
Chris@0 218
Chris@0 219 if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) {
Chris@0 220 PyErr_SetString(PyExc_TypeError,
Chris@0 221 "Invalid argument: plugin handle or plugin key required.");
luis@7 222 return NULL;
Chris@0 223 }
Chris@0 224
Chris@0 225 //check if we have a plugin key string or a handle object
Chris@0 226 if (PyString_Check(pyPluginHandle) ) {
Chris@0 227
Chris@0 228 pluginKey.assign(PyString_AS_STRING(pyPluginHandle));
Chris@0 229 //check pluginKey Validity
Chris@0 230 string::size_type ki = pluginKey.find(':');
Chris@0 231 if (ki == string::npos) {
Chris@0 232 PyErr_SetString(PyExc_TypeError,
luis@7 233 "String input argument required: pluginLibrary:Identifier");
Chris@0 234 return NULL;
Chris@0 235 }
Chris@0 236
Chris@0 237 } else {
luis@7 238
luis@7 239 string *key;
luis@7 240 Plugin *plugin;
Chris@0 241
Chris@0 242 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
Chris@0 243 PyErr_SetString(PyExc_TypeError,
Chris@0 244 "Invalid or deleted plugin handle.");
Chris@0 245 return NULL; }
Chris@0 246 pluginKey.assign(*key);
luis@7 247 }
luis@7 248
Chris@0 249 //This code creates new instance of the plugin anyway
Chris@0 250 PluginLoader *loader = PluginLoader::getInstance();
luis@7 251
Chris@0 252 //load plugin
Chris@3 253 Plugin *plugin = loader->loadPlugin
Chris@3 254 (pluginKey, 48000, PluginLoader::ADAPT_ALL_SAFE);
luis@7 255 if (!plugin) {
Chris@0 256 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
luis@7 257 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@0 258 return NULL;
luis@7 259 }
Chris@0 260
Chris@0 261 Plugin::OutputList outputs = plugin->getOutputDescriptors();
Chris@0 262 //Plugin::OutputDescriptor od;
Chris@0 263
Chris@0 264 if (outputs.size()<1) {
Chris@0 265 string pyerr("Plugin has no output: "); pyerr += pluginKey;
luis@7 266 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@0 267 return NULL;
Chris@0 268 }
Chris@0 269
Chris@0 270 //New list object
Chris@0 271 PyObject *pyList = PyList_New(outputs.size());
Chris@0 272
Chris@0 273 for (size_t i = 0; i < outputs.size(); ++i) {
luis@7 274 PyObject *pyOutputId =
Chris@0 275 PyString_FromString(outputs[i].identifier.c_str());
luis@7 276 PyList_SET_ITEM(pyList,i,pyOutputId);
Chris@0 277 }
Chris@0 278
Chris@0 279 delete plugin;
Chris@0 280 return pyList;
Chris@0 281 }
Chris@0 282
Chris@0 283
Chris@0 284
Chris@0 285 /* LOAD PLUGIN */
Chris@0 286
Chris@0 287 static PyObject *
Chris@0 288 vampyhost_loadPlugin(PyObject *self, PyObject *args)
Chris@0 289 {
Chris@0 290 PyObject *pyPluginKey;
Chris@0 291 float inputSampleRate;
Chris@0 292
luis@7 293 if (!PyArg_ParseTuple(args, "Sf",
Chris@0 294 &pyPluginKey,
Chris@0 295 &inputSampleRate)) {
Chris@0 296 PyErr_SetString(PyExc_TypeError,
Chris@0 297 "String input argument required: pluginKey");
Chris@0 298 return NULL; }
Chris@0 299
Chris@0 300 //convert to stl string
Chris@0 301 string pluginKey(PyString_AS_STRING(pyPluginKey));
Chris@0 302
Chris@0 303 //check pluginKey Validity
Chris@0 304 string::size_type ki = pluginKey.find(':');
Chris@0 305 if (ki == string::npos) {
Chris@0 306 PyErr_SetString(PyExc_TypeError,
luis@7 307 "String input argument required: pluginLibrary:Identifier");
Chris@0 308 return NULL;
Chris@0 309 }
Chris@0 310
Chris@0 311 PluginLoader *loader = PluginLoader::getInstance();
luis@7 312
Chris@0 313 //load plugin
luis@7 314 Plugin *plugin = loader->loadPlugin (pluginKey, inputSampleRate,
Chris@6 315 PluginLoader::ADAPT_ALL_SAFE);
luis@7 316 if (!plugin) {
Chris@0 317 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
luis@7 318 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@0 319 return NULL;
luis@7 320 }
Chris@0 321 //void *identifier = (void*) new string(pluginKey);
Chris@0 322 PyPluginDescriptor *pd = new PyPluginDescriptor;
luis@7 323
Chris@0 324 pd->key = pluginKey;
Chris@0 325 pd->isInitialised = false;
Chris@0 326 pd->inputSampleRate = inputSampleRate;
luis@7 327
Chris@0 328 //New PyCObject
luis@7 329 //PyObject *pyPluginHandle = PyCObject_FromVoidPtrAndDesc(
luis@7 330 //(void*) plugin, identifier, NULL);
Chris@0 331
luis@7 332 PyObject *pyPluginHandle = PyCObject_FromVoidPtrAndDesc(
luis@7 333 (void*) plugin, (void*) pd, NULL);
luis@7 334
Chris@0 335 return pyPluginHandle;
Chris@0 336 }
Chris@0 337
Chris@0 338
Chris@0 339
Chris@0 340 /* UNLOAD PLUGIN */
Chris@0 341
Chris@0 342 static PyObject *
Chris@0 343 vampyhost_unloadPlugin(PyObject *self, PyObject *args)
Chris@0 344 {
Chris@0 345 PyObject *pyPluginHandle;
Chris@0 346
Chris@0 347 if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) {
Chris@0 348 PyErr_SetString(PyExc_TypeError,
Chris@0 349 "Wrong input argument: Plugin Handle required.");
Chris@0 350 return NULL; }
Chris@0 351
luis@7 352 string *key;
luis@7 353 Plugin *plugin;
Chris@0 354
Chris@0 355 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
Chris@0 356 PyErr_SetString(PyExc_TypeError,
Chris@0 357 "Invalid or already deleted plugin handle.");
Chris@0 358 return NULL; }
Chris@0 359
Chris@0 360 /* Prevent repeated calls from causing segfault
Chris@0 361 sice it will fail type checking the 2nd time: */
Chris@0 362 PyCObject_SetVoidPtr(pyPluginHandle,NULL);
luis@7 363
Chris@0 364 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
luis@7 365
Chris@0 366 delete plugin;
Chris@0 367 delete pd;
Chris@0 368 return pyPluginHandle;
Chris@0 369
Chris@0 370 }
Chris@0 371
Chris@0 372
Chris@0 373 /* INITIALISE PLUGIN */
Chris@0 374
Chris@0 375 static PyObject *
Chris@0 376 vampyhost_initialise(PyObject *self, PyObject *args)
Chris@0 377 {
Chris@0 378 PyObject *pyPluginHandle;
luis@7 379 size_t channels, blockSize, stepSize;
Chris@0 380
luis@7 381 if (!PyArg_ParseTuple (args, "Onnn", &pyPluginHandle,
luis@7 382 (size_t) &channels,
luis@7 383 (size_t) &stepSize,
luis@7 384 (size_t) &blockSize))
Chris@0 385 {
Chris@0 386 PyErr_SetString(PyExc_TypeError,
Chris@0 387 "Wrong input arguments: requires a valid plugin handle,channels,stepSize,blockSize.");
luis@7 388 return NULL;
Chris@0 389 }
Chris@0 390
luis@7 391 Plugin *plugin;
luis@7 392 string *key;
Chris@0 393
Chris@0 394 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
Chris@0 395 PyErr_SetString(PyExc_TypeError,
Chris@0 396 "Invalid plugin handle.");
Chris@0 397 return NULL; }
Chris@0 398
Chris@0 399 // here we cast the void pointer as PyPluginDescriptor instead of string
luis@7 400 PyPluginDescriptor *plugDesc = (PyPluginDescriptor*) key;
Chris@0 401
Chris@0 402 plugDesc->channels = channels;
Chris@0 403 plugDesc->stepSize = stepSize;
Chris@0 404 plugDesc->blockSize = blockSize;
Chris@3 405
Chris@0 406 if (!plugin->initialise(channels, stepSize, blockSize)) {
Chris@6 407 std::cerr << "Failed to initialise native plugin adapter with channels = " << channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << " and ADAPT_ALL_SAFE set" << std::endl;
Chris@0 408 PyErr_SetString(PyExc_TypeError,
Chris@0 409 "Plugin initialization failed.");
Chris@6 410 return NULL;
Chris@6 411 }
Chris@0 412
luis@7 413 plugDesc->identifier =
Chris@0 414 plugDesc->key.substr(plugDesc->key.rfind(':')+1);
Chris@0 415 plugDesc->isInitialised = true;
luis@7 416
Chris@0 417 return Py_True;
Chris@0 418 }
Chris@0 419
Chris@0 420 /* RUN PROCESS */
Chris@0 421
Chris@0 422 static PyObject *
Chris@0 423 vampyhost_process(PyObject *self, PyObject *args)
Chris@0 424 {
Chris@0 425 PyObject *pyPluginHandle;
Chris@0 426 PyObject *pyBuffer;
Chris@0 427 PyObject *pyRealTime;
Chris@0 428
luis@7 429 if (!PyArg_ParseTuple(args, "OOO",
Chris@0 430 &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor
Chris@0 431 &pyBuffer, // Audio data
Chris@0 432 &pyRealTime)) { // TimeStamp
Chris@0 433 PyErr_SetString(PyExc_TypeError,
Chris@0 434 "Required: plugin handle, buffer, timestmap.");
Chris@0 435 return NULL; }
Chris@0 436
Chris@0 437 if (!PyRealTime_Check(pyRealTime)) {
Chris@0 438 PyErr_SetString(PyExc_TypeError,"Valid timestamp required.");
Chris@0 439 return NULL; }
Chris@0 440
Chris@4 441 string *key;
luis@7 442 Plugin *plugin;
Chris@0 443
Chris@4 444 if (!getPluginHandle(pyPluginHandle, &plugin, &key)) {
Chris@0 445 PyErr_SetString(PyExc_AttributeError,
Chris@0 446 "Invalid or already deleted plugin handle.");
Chris@4 447 return NULL;
Chris@4 448 }
Chris@0 449
Chris@0 450 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
Chris@0 451
Chris@0 452 if (!pd->isInitialised) {
Chris@0 453 PyErr_SetString(PyExc_StandardError,
Chris@0 454 "Plugin has not been initialised.");
Chris@0 455 return NULL; }
Chris@0 456
Chris@12 457 int channels = pd->channels;
Chris@12 458 // int blockSize = pd->blockSize;
Chris@0 459
Chris@4 460 if (!PyList_Check(pyBuffer)) {
Chris@4 461 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input.");
Chris@4 462 return NULL;
Chris@0 463 }
Chris@0 464
Chris@4 465 if (PyList_GET_SIZE(pyBuffer) != channels) {
Chris@6 466 std::cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << std::endl;
Chris@4 467 PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
Chris@4 468 return NULL;
Chris@4 469 }
Chris@0 470
Chris@4 471 float **inbuf = new float *[channels];
Chris@0 472
Chris@12 473 PyTypeConversions typeConv;
Chris@12 474 typeConv.setNumpyInstalled(true);
Chris@12 475
Chris@12 476 vector<vector<float> > data;
Chris@4 477 for (int c = 0; c < channels; ++c) {
Chris@4 478 PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
Chris@12 479 data.push_back(typeConv.PyArray_To_FloatVector(cbuf));
Chris@12 480 }
Chris@12 481
Chris@12 482 for (int c = 0; c < channels; ++c) {
Chris@12 483 inbuf[c] = &data[c][0];
Chris@4 484 }
Chris@0 485
Chris@12 486 RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
Chris@0 487
Chris@0 488 //Call process and store the output
Chris@4 489 pd->output = plugin->process(inbuf, timeStamp);
Chris@0 490
Chris@0 491 /* TODO: DO SOMETHONG WITH THE FEATURE SET HERE */
Chris@0 492 /// convert to appropriate python objects, reuse types and conversion utilities from Vampy ...
Chris@0 493
Chris@4 494 delete[] inbuf;
Chris@0 495
Chris@4 496 return NULL; //!!! Need to return actual features!
Chris@0 497
Chris@0 498 }
Chris@0 499
Chris@0 500 /* GET / SET OUTPUT */
Chris@0 501
Chris@0 502 //getOutput(plugin,outputNo)
Chris@0 503 static PyObject *
Chris@0 504 vampyhost_getOutput(PyObject *self, PyObject *args) {
Chris@0 505
Chris@0 506 PyObject *pyPluginHandle;
Chris@0 507 // PyObject *pyBuffer;
Chris@0 508 // PyObject *pyRealTime;
Chris@0 509 PyObject *pyOutput;
Chris@0 510
luis@7 511 if (!PyArg_ParseTuple(args, "OO",
Chris@0 512 &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor
Chris@0 513 &pyOutput)) { // Output reference
Chris@0 514 PyErr_SetString(PyExc_TypeError,
Chris@0 515 "Required: plugin handle, buffer, timestmap.");
Chris@0 516 return NULL; }
Chris@0 517
luis@7 518 string *key;
luis@7 519 Plugin *plugin;
Chris@0 520
Chris@0 521 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
Chris@0 522 PyErr_SetString(PyExc_AttributeError,
Chris@0 523 "Invalid or already deleted plugin handle.");
Chris@0 524 return NULL; }
Chris@0 525
Chris@0 526 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
Chris@0 527
Chris@0 528 unsigned int outputNo = (unsigned int) PyInt_AS_LONG(pyOutput);
Chris@0 529
Chris@0 530 //Get output list: but we don't need it
Chris@0 531 //Plugin::FeatureList features = pd->output[outputNo];
Chris@0 532
Chris@0 533 size_t outLength = pd->output[outputNo].size();
Chris@0 534
Chris@0 535 //New PyList for the featurelist
Chris@0 536 PyObject *pyFeatureList = PyList_New(outLength);
Chris@0 537
Chris@0 538 for (size_t i = 0; i < outLength; ++i) {
Chris@0 539 // Test:
Chris@0 540 /*
luis@7 541 XxoObject *pyFeature = PyObject_New(XxoObject, &Xxo_Type);
Chris@0 542 if (pyFeature == NULL) break; //return NULL;
Chris@0 543
Chris@0 544 pyFeature->x_attr = NULL;
Chris@0 545 pyFeature->feature = &pd->output[outputNo][i];
Chris@0 546
luis@7 547 PyList_SET_ITEM(pyFeatureList,i,(PyObject*)pyFeature);
Chris@0 548 */
Chris@0 549 }
Chris@0 550
Chris@0 551 Py_INCREF(pyFeatureList);
Chris@0 552 return pyFeatureList;
Chris@0 553
Chris@0 554 // EXPLAIN WHAT WE NEED TO DO HERE:
Chris@0 555 // We have the block output in pd->output
luis@7 556 // FeatureSet[output] -> [Feature[x]] -> Feature.hasTimestamp = v
luis@7 557 // Vamp::Plugin::FeatureSet output; = pd->output
Chris@0 558 // typedef std::vector<Feature> FeatureList;
Chris@0 559 // typedef std::map<int, FeatureList> FeatureSet; // key is output no
Chris@0 560
luis@7 561 // THIS IS FOR OUTPUT id LOOKUP LATER
Chris@0 562 // Plugin::OutputList outputs = plugin->getOutputDescriptors();
luis@7 563 //
Chris@0 564 // if (outputs.size()<1) {
Chris@0 565 // string pyerr("Plugin has no output: "); pyerr += pluginKey;
luis@7 566 // PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@0 567 // return NULL;
Chris@0 568 // }
luis@7 569 //
Chris@0 570 // //New list object
Chris@0 571 // PyObject *pyList = PyList_New(outputs.size());
luis@7 572 //
Chris@0 573 // for (size_t i = 0; i < outputs.size(); ++i) {
luis@7 574 // PyObject *pyOutputId =
Chris@0 575 // PyString_FromString(outputs[i].identifier.c_str());
luis@7 576 // PyList_SET_ITEM(pyList,i,pyOutputId);
Chris@0 577 // }
luis@7 578
Chris@0 579 }
Chris@0 580
Chris@0 581
Chris@0 582
Chris@0 583
Chris@0 584 /* List of functions defined in this module */
Chris@0 585 //module methods table
Chris@0 586 static PyMethodDef vampyhost_methods[] = {
Chris@0 587
Chris@0 588 {"enumeratePlugins", vampyhost_enumeratePlugins, METH_VARARGS,
Chris@0 589 xx_foo_doc},
Chris@0 590
Chris@0 591 {"getLibraryPath", vampyhost_getLibraryPath, METH_VARARGS,
Chris@0 592 xx_foo_doc},
Chris@0 593
Chris@0 594 {"getPluginCategory", vampyhost_getPluginCategory, METH_VARARGS,
Chris@0 595 xx_foo_doc},
Chris@0 596
Chris@0 597 {"getOutputList", vampyhost_getOutputList, METH_VARARGS,
Chris@0 598 xx_foo_doc},
Chris@0 599
Chris@0 600 {"loadPlugin", vampyhost_loadPlugin, METH_VARARGS,
Chris@0 601 xx_foo_doc},
Chris@0 602
Chris@0 603 {"process", vampyhost_process, METH_VARARGS,
Chris@0 604 xx_foo_doc},
Chris@0 605
Chris@0 606 {"unloadPlugin", vampyhost_unloadPlugin, METH_VARARGS,
Chris@0 607 xx_foo_doc},
Chris@0 608
Chris@0 609 {"initialise", vampyhost_initialise, METH_VARARGS,
Chris@0 610 xx_foo_doc},
Chris@0 611
Chris@0 612 {"getOutput", vampyhost_getOutput, METH_VARARGS,
Chris@0 613 xx_foo_doc},
Chris@0 614
Chris@0 615 /* Add RealTime Module Methods */
Chris@12 616 /*
Chris@0 617 {"frame2RealTime", (PyCFunction)RealTime_frame2RealTime, METH_VARARGS,
Chris@0 618 PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")},
Chris@0 619
Chris@0 620 {"realtime", (PyCFunction)RealTime_new, METH_VARARGS,
Chris@0 621 PyDoc_STR("realtime() -> returns new RealTime object")},
Chris@12 622 */
Chris@0 623 {NULL, NULL} /* sentinel */
Chris@0 624 };
Chris@0 625
Chris@0 626 //Documentation for our new module
Chris@0 627 PyDoc_STRVAR(module_doc, "This is a template module just for instruction.");
Chris@0 628
Chris@0 629 /* Initialization function for the module (*must* be called initxx) */
Chris@0 630
Chris@0 631 //module initialization (includes extern C {...} as necessary)
Chris@0 632 PyMODINIT_FUNC
Chris@0 633 initvampyhost(void)
Chris@0 634 {
Chris@0 635 PyObject *m;
Chris@0 636
Chris@0 637 /* Finalize the type object including setting type of the new type
luis@7 638 * object; doing it here is required for portability to Windows
Chris@0 639 * without requiring C++. */
Chris@0 640
Chris@0 641 if (PyType_Ready(&RealTime_Type) < 0)
Chris@0 642 return;
Chris@0 643 // PyModule_AddObject(m, "Real_Time", (PyObject *)&RealTime_Type);
Chris@0 644
Chris@0 645 /* Create the module and add the functions */
Chris@0 646 m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc);
Chris@0 647 if (m == NULL) return;
Chris@0 648
Chris@0 649 // PyModule_AddObject(m, "realtime", (PyObject *)&RealTime_Type);
Chris@0 650
Chris@0 651 }