annotate vampyhost.cpp @ 3:f12ab1553882

Use plugin adapter flags; don't need to concern ourselves with mixdown
author Chris Cannam
date Thu, 31 Jan 2013 13:31:52 +0000
parents e30eda0b5e2d
children 825d787f12df
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@2 42 PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!!
Chris@0 43
Chris@0 44 /*obtain C plugin handle and key from pyCobject */
Chris@2 45 bool 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@2 51 if (!PyCObject_Check(pyPluginHandle)) return false;
Chris@0 52
Chris@0 53 //try to convert to Plugin pointer
Chris@0 54 Plugin *p = (Plugin*) PyCObject_AsVoidPtr(pyPluginHandle);
Chris@2 55 if (!p) return false;
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@2 61 if (!*pKey) return false;
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@2 67 if (!pKey) return false;
Chris@0 68 pId = *(string*) pKey;
Chris@0 69 }
Chris@0 70
Chris@0 71 string::size_type pos = pId.find(':');
Chris@2 72 if (pos == string::npos) return false;
Chris@0 73
Chris@0 74 pId = pId.substr(pId.rfind(':')+1);
Chris@0 75 string identifier = p->getIdentifier();
Chris@0 76
Chris@2 77 if (pId.compare(identifier)) return false;
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@3 244 Plugin *plugin = loader->loadPlugin
Chris@3 245 (pluginKey, 48000, PluginLoader::ADAPT_ALL_SAFE);
Chris@0 246 if (!plugin) {
Chris@0 247 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
Chris@0 248 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@0 249 return NULL;
Chris@0 250 }
Chris@0 251
Chris@0 252 Plugin::OutputList outputs = plugin->getOutputDescriptors();
Chris@0 253 //Plugin::OutputDescriptor od;
Chris@0 254
Chris@0 255 if (outputs.size()<1) {
Chris@0 256 string pyerr("Plugin has no output: "); pyerr += pluginKey;
Chris@0 257 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@0 258 return NULL;
Chris@0 259 }
Chris@0 260
Chris@0 261 //New list object
Chris@0 262 PyObject *pyList = PyList_New(outputs.size());
Chris@0 263
Chris@0 264 for (size_t i = 0; i < outputs.size(); ++i) {
Chris@0 265 PyObject *pyOutputId =
Chris@0 266 PyString_FromString(outputs[i].identifier.c_str());
Chris@0 267 PyList_SET_ITEM(pyList,i,pyOutputId);
Chris@0 268 }
Chris@0 269
Chris@0 270 delete plugin;
Chris@0 271 return pyList;
Chris@0 272 }
Chris@0 273
Chris@0 274
Chris@0 275
Chris@0 276 /* LOAD PLUGIN */
Chris@0 277
Chris@0 278 static PyObject *
Chris@0 279 vampyhost_loadPlugin(PyObject *self, PyObject *args)
Chris@0 280 {
Chris@0 281 PyObject *pyPluginKey;
Chris@0 282 float inputSampleRate;
Chris@0 283
Chris@0 284 if (!PyArg_ParseTuple(args, "Sf",
Chris@0 285 &pyPluginKey,
Chris@0 286 &inputSampleRate)) {
Chris@0 287 PyErr_SetString(PyExc_TypeError,
Chris@0 288 "String input argument required: pluginKey");
Chris@0 289 return NULL; }
Chris@0 290
Chris@0 291 //convert to stl string
Chris@0 292 string pluginKey(PyString_AS_STRING(pyPluginKey));
Chris@0 293
Chris@0 294 //check pluginKey Validity
Chris@0 295 string::size_type ki = pluginKey.find(':');
Chris@0 296 if (ki == string::npos) {
Chris@0 297 PyErr_SetString(PyExc_TypeError,
Chris@0 298 "String input argument required: pluginLibrary:Identifier");
Chris@0 299 return NULL;
Chris@0 300 }
Chris@0 301
Chris@0 302 PluginLoader *loader = PluginLoader::getInstance();
Chris@0 303
Chris@0 304 //load plugin
Chris@0 305 Plugin *plugin = loader->loadPlugin (pluginKey, inputSampleRate);
Chris@0 306 if (!plugin) {
Chris@0 307 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
Chris@0 308 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@0 309 return NULL;
Chris@0 310 }
Chris@0 311 //void *identifier = (void*) new string(pluginKey);
Chris@0 312 PyPluginDescriptor *pd = new PyPluginDescriptor;
Chris@0 313
Chris@0 314 pd->key = pluginKey;
Chris@0 315 pd->isInitialised = false;
Chris@0 316 pd->inputSampleRate = inputSampleRate;
Chris@0 317
Chris@0 318 //New PyCObject
Chris@0 319 //PyObject *pyPluginHandle = PyCObject_FromVoidPtrAndDesc(
Chris@0 320 //(void*) plugin, identifier, NULL);
Chris@0 321
Chris@0 322 PyObject *pyPluginHandle = PyCObject_FromVoidPtrAndDesc(
Chris@0 323 (void*) plugin, (void*) pd, NULL);
Chris@0 324
Chris@0 325 return pyPluginHandle;
Chris@0 326 }
Chris@0 327
Chris@0 328
Chris@0 329
Chris@0 330 /* UNLOAD PLUGIN */
Chris@0 331
Chris@0 332 static PyObject *
Chris@0 333 vampyhost_unloadPlugin(PyObject *self, PyObject *args)
Chris@0 334 {
Chris@0 335 PyObject *pyPluginHandle;
Chris@0 336
Chris@0 337 if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) {
Chris@0 338 PyErr_SetString(PyExc_TypeError,
Chris@0 339 "Wrong input argument: Plugin Handle required.");
Chris@0 340 return NULL; }
Chris@0 341
Chris@0 342 string *key;
Chris@0 343 Plugin *plugin;
Chris@0 344
Chris@0 345 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
Chris@0 346 PyErr_SetString(PyExc_TypeError,
Chris@0 347 "Invalid or already deleted plugin handle.");
Chris@0 348 return NULL; }
Chris@0 349
Chris@0 350 /* Prevent repeated calls from causing segfault
Chris@0 351 sice it will fail type checking the 2nd time: */
Chris@0 352 PyCObject_SetVoidPtr(pyPluginHandle,NULL);
Chris@0 353
Chris@0 354 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
Chris@0 355
Chris@0 356 delete plugin;
Chris@0 357 delete pd;
Chris@0 358 return pyPluginHandle;
Chris@0 359
Chris@0 360 }
Chris@0 361
Chris@0 362
Chris@0 363 /* INITIALISE PLUGIN */
Chris@0 364
Chris@0 365 static PyObject *
Chris@0 366 vampyhost_initialise(PyObject *self, PyObject *args)
Chris@0 367 {
Chris@0 368 PyObject *pyPluginHandle;
Chris@0 369 size_t channels,blockSize,stepSize;
Chris@0 370 //PyObject pyInputSampleType;
Chris@0 371 bool mixChannels = false;
Chris@0 372
Chris@0 373 if (!PyArg_ParseTuple (args, "Oiii", &pyPluginHandle,
Chris@0 374 (size_t) &channels,
Chris@0 375 (size_t) &stepSize,
Chris@0 376 (size_t) &blockSize))
Chris@0 377 {
Chris@0 378 PyErr_SetString(PyExc_TypeError,
Chris@0 379 "Wrong input arguments: requires a valid plugin handle,channels,stepSize,blockSize.");
Chris@0 380 return NULL;
Chris@0 381 }
Chris@0 382
Chris@0 383 Plugin *plugin;
Chris@0 384 string *key;
Chris@0 385
Chris@0 386 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
Chris@0 387 PyErr_SetString(PyExc_TypeError,
Chris@0 388 "Invalid plugin handle.");
Chris@0 389 return NULL; }
Chris@0 390
Chris@0 391 // here we cast the void pointer as PyPluginDescriptor instead of string
Chris@0 392 PyPluginDescriptor *plugDesc = (PyPluginDescriptor*) key;
Chris@0 393
Chris@0 394 plugDesc->channels = channels;
Chris@0 395 plugDesc->stepSize = stepSize;
Chris@0 396 plugDesc->blockSize = blockSize;
Chris@0 397 plugDesc->inputSampleType = PyPluginDescriptor::int16;
Chris@0 398 plugDesc->sampleSize = 2;
Chris@3 399
Chris@3 400 /*!!! not a problem with plugin loader adapter
Chris@0 401 plugDesc->mixChannels = mixChannels;
Chris@3 402
Chris@0 403 size_t minch = plugin->getMinChannelCount();
Chris@0 404 size_t maxch = plugin->getMaxChannelCount();
Chris@0 405 if (mixChannels) channels = 1;
Chris@3 406 */
Chris@0 407 /* TODO: DO WE WANT TO MIX IT DOWN? */
Chris@3 408 /*
Chris@0 409 if (maxch < channels || channels < minch) {
Chris@0 410 PyErr_SetString(PyExc_TypeError,
Chris@0 411 "Invalid number of channels.");
Chris@0 412 return NULL; }
Chris@3 413 */
Chris@0 414 if (!plugin->initialise(channels, stepSize, blockSize)) {
Chris@0 415 PyErr_SetString(PyExc_TypeError,
Chris@0 416 "Plugin initialization failed.");
Chris@0 417 return NULL; }
Chris@0 418
Chris@0 419 plugDesc->identifier =
Chris@0 420 plugDesc->key.substr(plugDesc->key.rfind(':')+1);
Chris@0 421 plugDesc->isInitialised = true;
Chris@0 422
Chris@0 423 return Py_True;
Chris@0 424 }
Chris@0 425
Chris@0 426
Chris@0 427 /* RUN PROCESS */
Chris@0 428
Chris@0 429 static PyObject *
Chris@0 430 vampyhost_process(PyObject *self, PyObject *args)
Chris@0 431 {
Chris@0 432 PyObject *pyPluginHandle;
Chris@0 433 PyObject *pyBuffer;
Chris@0 434 PyObject *pyRealTime;
Chris@0 435
Chris@0 436 if (!PyArg_ParseTuple(args, "OOO",
Chris@0 437 &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor
Chris@0 438 &pyBuffer, // Audio data
Chris@0 439 &pyRealTime)) { // TimeStamp
Chris@0 440 PyErr_SetString(PyExc_TypeError,
Chris@0 441 "Required: plugin handle, buffer, timestmap.");
Chris@0 442 return NULL; }
Chris@0 443
Chris@0 444 if (!PyRealTime_Check(pyRealTime)) {
Chris@0 445 PyErr_SetString(PyExc_TypeError,"Valid timestamp required.");
Chris@0 446 return NULL; }
Chris@0 447
Chris@0 448 // RealTime *rt = PyRealTime_AsPointer(pyRealTime);
Chris@0 449 // if (!rt) return NULL;
Chris@0 450 // cerr << ">>>sec: " << rt->sec << " nsec: " << rt->nsec << endl;
Chris@0 451 //
Chris@0 452 // PyObject *rrt = PyRealTime_FromRealTime (rt);
Chris@0 453
Chris@0 454 string *key;
Chris@0 455 Plugin *plugin;
Chris@0 456
Chris@0 457 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
Chris@0 458 PyErr_SetString(PyExc_AttributeError,
Chris@0 459 "Invalid or already deleted plugin handle.");
Chris@0 460 return NULL; }
Chris@0 461
Chris@0 462 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
Chris@0 463
Chris@0 464 if (!pd->isInitialised) {
Chris@0 465 PyErr_SetString(PyExc_StandardError,
Chris@0 466 "Plugin has not been initialised.");
Chris@0 467 return NULL; }
Chris@0 468
Chris@0 469 size_t channels = pd->channels;
Chris@0 470 size_t blockSize = pd->blockSize;
Chris@0 471
Chris@0 472 /*
Chris@0 473 Handle the case when we get the data as a character buffer
Chris@0 474 Handle SampleFormats: int16, float32
Chris@0 475
Chris@0 476 */
Chris@0 477
Chris@0 478 if (PyString_Check(pyBuffer)) {
Chris@0 479 cerr << ">>> String obj passed in." << endl;
Chris@0 480 }
Chris@0 481
Chris@0 482 size_t sample_size = sizeof(short);
Chris@0 483
Chris@0 484 long buflen = (long) PyString_GET_SIZE(pyBuffer);
Chris@0 485
Chris@0 486 size_t input_length =
Chris@0 487 static_cast <size_t> (buflen/channels/sample_size);
Chris@0 488
Chris@0 489 if (input_length == pd->blockSize) {
Chris@0 490 cerr << ">>> A full block has been passed in." << endl; }
Chris@0 491 short *input =
Chris@0 492 reinterpret_cast <short*> (PyString_AS_STRING(pyBuffer));
Chris@0 493
Chris@0 494 //convert int16 PCM data to 32-bit floats
Chris@0 495 float **plugbuf = new float*[channels];
Chris@0 496 float normfact = 1.0f / static_cast <float> (SHRT_MAX);
Chris@0 497
Chris@0 498 for (size_t c = 0; c < channels; ++c) {
Chris@0 499
Chris@0 500 plugbuf[c] = new float[blockSize+2];
Chris@0 501
Chris@0 502 size_t j = 0;
Chris@0 503 while (j < input_length) {
Chris@0 504 plugbuf[c][j] = normfact *
Chris@0 505 static_cast <float> (input[j * channels + c]);
Chris@0 506 ++j;
Chris@0 507 }
Chris@0 508 while (j < blockSize) {
Chris@0 509 plugbuf[c][j] = 0.0f;
Chris@0 510 ++j;
Chris@0 511 }
Chris@0 512 }
Chris@0 513
Chris@0 514 const char *output = reinterpret_cast <const char*> (plugbuf[0]);
Chris@0 515 Py_ssize_t len = (Py_ssize_t) channels*blockSize*4;
Chris@0 516
Chris@0 517 PyObject* pyReturnBuffer =
Chris@0 518 PyString_FromStringAndSize(output,len);
Chris@0 519
Chris@0 520 // long frame = 1;
Chris@0 521 // unsigned int samplerate = (unsigned int) pd->inputSampleRate;
Chris@0 522
Chris@0 523 RealTime timeStamp = *PyRealTime_AsPointer(pyRealTime);
Chris@0 524
Chris@0 525 //Call process and store the output
Chris@0 526 pd->output = plugin->process(
Chris@0 527 plugbuf,
Chris@0 528 timeStamp);
Chris@0 529
Chris@0 530 /* TODO: DO SOMETHONG WITH THE FEATURE SET HERE */
Chris@0 531 /// convert to appropriate python objects, reuse types and conversion utilities from Vampy ...
Chris@0 532
Chris@0 533
Chris@0 534 //We can safely delete here
Chris@0 535 for(size_t k=0; k<channels; k++){
Chris@0 536 delete[] plugbuf[k];
Chris@0 537 }
Chris@0 538 delete[] plugbuf;
Chris@0 539
Chris@0 540 return pyReturnBuffer;
Chris@0 541
Chris@0 542 }
Chris@0 543
Chris@0 544 /* GET / SET OUTPUT */
Chris@0 545
Chris@0 546 //getOutput(plugin,outputNo)
Chris@0 547 static PyObject *
Chris@0 548 vampyhost_getOutput(PyObject *self, PyObject *args) {
Chris@0 549
Chris@0 550 PyObject *pyPluginHandle;
Chris@0 551 // PyObject *pyBuffer;
Chris@0 552 // PyObject *pyRealTime;
Chris@0 553 PyObject *pyOutput;
Chris@0 554
Chris@0 555 if (!PyArg_ParseTuple(args, "OO",
Chris@0 556 &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor
Chris@0 557 &pyOutput)) { // Output reference
Chris@0 558 PyErr_SetString(PyExc_TypeError,
Chris@0 559 "Required: plugin handle, buffer, timestmap.");
Chris@0 560 return NULL; }
Chris@0 561
Chris@0 562 string *key;
Chris@0 563 Plugin *plugin;
Chris@0 564
Chris@0 565 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
Chris@0 566 PyErr_SetString(PyExc_AttributeError,
Chris@0 567 "Invalid or already deleted plugin handle.");
Chris@0 568 return NULL; }
Chris@0 569
Chris@0 570 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
Chris@0 571
Chris@0 572 unsigned int outputNo = (unsigned int) PyInt_AS_LONG(pyOutput);
Chris@0 573
Chris@0 574 //Get output list: but we don't need it
Chris@0 575 //Plugin::FeatureList features = pd->output[outputNo];
Chris@0 576
Chris@0 577 size_t outLength = pd->output[outputNo].size();
Chris@0 578
Chris@0 579 //New PyList for the featurelist
Chris@0 580 PyObject *pyFeatureList = PyList_New(outLength);
Chris@0 581
Chris@0 582 for (size_t i = 0; i < outLength; ++i) {
Chris@0 583 // Test:
Chris@0 584 /*
Chris@0 585 XxoObject *pyFeature = PyObject_New(XxoObject, &Xxo_Type);
Chris@0 586 if (pyFeature == NULL) break; //return NULL;
Chris@0 587
Chris@0 588 pyFeature->x_attr = NULL;
Chris@0 589 pyFeature->feature = &pd->output[outputNo][i];
Chris@0 590
Chris@0 591 PyList_SET_ITEM(pyFeatureList,i,(PyObject*)pyFeature);
Chris@0 592 */
Chris@0 593 }
Chris@0 594
Chris@0 595 Py_INCREF(pyFeatureList);
Chris@0 596 return pyFeatureList;
Chris@0 597
Chris@0 598 // EXPLAIN WHAT WE NEED TO DO HERE:
Chris@0 599 // We have the block output in pd->output
Chris@0 600 // FeatureSet[output] -> [Feature[x]] -> Feature.hasTimestamp = v
Chris@0 601 // Vamp::Plugin::FeatureSet output; = pd->output
Chris@0 602 // typedef std::vector<Feature> FeatureList;
Chris@0 603 // typedef std::map<int, FeatureList> FeatureSet; // key is output no
Chris@0 604
Chris@0 605 // THIS IS FOR OUTPUT id LOOKUP LATER
Chris@0 606 // Plugin::OutputList outputs = plugin->getOutputDescriptors();
Chris@0 607 //
Chris@0 608 // if (outputs.size()<1) {
Chris@0 609 // string pyerr("Plugin has no output: "); pyerr += pluginKey;
Chris@0 610 // PyErr_SetString(PyExc_TypeError,pyerr.c_str());
Chris@0 611 // return NULL;
Chris@0 612 // }
Chris@0 613 //
Chris@0 614 // //New list object
Chris@0 615 // PyObject *pyList = PyList_New(outputs.size());
Chris@0 616 //
Chris@0 617 // for (size_t i = 0; i < outputs.size(); ++i) {
Chris@0 618 // PyObject *pyOutputId =
Chris@0 619 // PyString_FromString(outputs[i].identifier.c_str());
Chris@0 620 // PyList_SET_ITEM(pyList,i,pyOutputId);
Chris@0 621 // }
Chris@0 622
Chris@0 623 }
Chris@0 624
Chris@0 625
Chris@0 626
Chris@0 627
Chris@0 628 /* List of functions defined in this module */
Chris@0 629 //module methods table
Chris@0 630 static PyMethodDef vampyhost_methods[] = {
Chris@0 631
Chris@0 632 {"enumeratePlugins", vampyhost_enumeratePlugins, METH_VARARGS,
Chris@0 633 xx_foo_doc},
Chris@0 634
Chris@0 635 {"getLibraryPath", vampyhost_getLibraryPath, METH_VARARGS,
Chris@0 636 xx_foo_doc},
Chris@0 637
Chris@0 638 {"getPluginCategory", vampyhost_getPluginCategory, METH_VARARGS,
Chris@0 639 xx_foo_doc},
Chris@0 640
Chris@0 641 {"getOutputList", vampyhost_getOutputList, METH_VARARGS,
Chris@0 642 xx_foo_doc},
Chris@0 643
Chris@0 644 {"loadPlugin", vampyhost_loadPlugin, METH_VARARGS,
Chris@0 645 xx_foo_doc},
Chris@0 646
Chris@0 647 {"process", vampyhost_process, METH_VARARGS,
Chris@0 648 xx_foo_doc},
Chris@0 649
Chris@0 650 {"unloadPlugin", vampyhost_unloadPlugin, METH_VARARGS,
Chris@0 651 xx_foo_doc},
Chris@0 652
Chris@0 653 {"initialise", vampyhost_initialise, METH_VARARGS,
Chris@0 654 xx_foo_doc},
Chris@0 655
Chris@0 656 {"getOutput", vampyhost_getOutput, METH_VARARGS,
Chris@0 657 xx_foo_doc},
Chris@0 658
Chris@0 659 /* Add RealTime Module Methods */
Chris@0 660
Chris@0 661 {"frame2RealTime", (PyCFunction)RealTime_frame2RealTime, METH_VARARGS,
Chris@0 662 PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")},
Chris@0 663
Chris@0 664 {"realtime", (PyCFunction)RealTime_new, METH_VARARGS,
Chris@0 665 PyDoc_STR("realtime() -> returns new RealTime object")},
Chris@0 666
Chris@0 667 {NULL, NULL} /* sentinel */
Chris@0 668 };
Chris@0 669
Chris@0 670 //Documentation for our new module
Chris@0 671 PyDoc_STRVAR(module_doc, "This is a template module just for instruction.");
Chris@0 672
Chris@0 673 /* Initialization function for the module (*must* be called initxx) */
Chris@0 674
Chris@0 675 //module initialization (includes extern C {...} as necessary)
Chris@0 676 PyMODINIT_FUNC
Chris@0 677 initvampyhost(void)
Chris@0 678 {
Chris@0 679 PyObject *m;
Chris@0 680
Chris@0 681 /* Finalize the type object including setting type of the new type
Chris@0 682 * object; doing it here is required for portability to Windows
Chris@0 683 * without requiring C++. */
Chris@0 684
Chris@0 685 if (PyType_Ready(&RealTime_Type) < 0)
Chris@0 686 return;
Chris@0 687 // PyModule_AddObject(m, "Real_Time", (PyObject *)&RealTime_Type);
Chris@0 688
Chris@0 689 /* Create the module and add the functions */
Chris@0 690 m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc);
Chris@0 691 if (m == NULL) return;
Chris@0 692
Chris@0 693 // PyModule_AddObject(m, "realtime", (PyObject *)&RealTime_Type);
Chris@0 694
Chris@0 695 }