annotate vampyhost.cpp @ 1:cb0d3af1be4d

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