Chris@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: //include for python extension module: must be first Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: Chris@4: //!!! NB all our NumPy stuff is currently using the deprecated API -- Chris@4: //!!! need to work out how to update this Chris@4: #include "numpy/arrayobject.h" Chris@4: Chris@0: //includes for vamp host Chris@1: #include "vamp-hostsdk/Plugin.h" Chris@1: #include "vamp-hostsdk/PluginHostAdapter.h" Chris@1: #include "vamp-hostsdk/PluginChannelAdapter.h" Chris@1: #include "vamp-hostsdk/PluginInputDomainAdapter.h" Chris@1: #include "vamp-hostsdk/PluginLoader.h" Chris@0: //#include "vamp/vamp.h" Chris@0: Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: Chris@0: #include "system.h" Chris@0: Chris@0: #include Chris@0: Chris@0: Chris@0: using namespace std; Chris@0: using namespace Vamp; Chris@0: Chris@0: using Vamp::Plugin; Chris@0: using Vamp::PluginHostAdapter; Chris@0: using Vamp::RealTime; Chris@0: using Vamp::HostExt::PluginLoader; Chris@0: Chris@0: #define HOST_VERSION "1.1" Chris@0: Chris@0: Chris@0: /* MODULE HELPER FUNCTIONS */ Chris@2: PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!! Chris@0: Chris@0: /*obtain C plugin handle and key from pyCobject */ luis@7: bool getPluginHandle Chris@0: (PyObject *pyPluginHandle, Plugin **plugin, string **pKey=NULL) { Chris@0: Chris@0: //char errormsg[]="Wrong input argument: Plugin Handle required."; Chris@0: Chris@0: *plugin = NULL; Chris@2: if (!PyCObject_Check(pyPluginHandle)) return false; Chris@0: Chris@0: //try to convert to Plugin pointer Chris@0: Plugin *p = (Plugin*) PyCObject_AsVoidPtr(pyPluginHandle); luis@7: if (!p) return false; Chris@0: Chris@0: string pId; Chris@0: Chris@0: if (pKey) { Chris@0: *pKey = (string*) PyCObject_GetDesc(pyPluginHandle); Chris@2: if (!*pKey) return false; Chris@0: pId = *(string*) *pKey; Chris@0: Chris@0: } else { Chris@0: Chris@0: void *pKey = PyCObject_GetDesc(pyPluginHandle); Chris@2: if (!pKey) return false; Chris@0: pId = *(string*) pKey; Chris@0: } luis@7: Chris@0: string::size_type pos = pId.find(':'); Chris@2: if (pos == string::npos) return false; Chris@0: Chris@0: pId = pId.substr(pId.rfind(':')+1); luis@7: string identifier = p->getIdentifier(); luis@7: Chris@2: if (pId.compare(identifier)) return false; Chris@0: Chris@0: *plugin = p; Chris@0: return true; Chris@0: } Chris@0: Chris@0: /* Chris@0: ---------------------------------------------------------------- Chris@0: */ Chris@0: Chris@0: Chris@0: Chris@0: /* luis@7: VAMPYHOST MAIN luis@7: --------------------------------------------------------------------- Chris@0: */ Chris@0: Chris@0: /* ENUMERATE PLUGINS*/ Chris@0: Chris@0: static PyObject * Chris@0: vampyhost_enumeratePlugins(PyObject *self, PyObject *args) Chris@0: { Chris@0: string retType; luis@7: Chris@0: if (!PyArg_ParseTuple(args, "|s:enumeratePlugins", &retType)) Chris@0: return NULL; Chris@0: Chris@0: //list available plugins Chris@0: PluginLoader *loader = PluginLoader::getInstance(); Chris@0: vector plugins = loader->listPlugins(); Chris@0: Chris@0: //library Map Chris@0: typedef multimap LibraryMap; Chris@0: LibraryMap libraryMap; Chris@0: Chris@0: //New list object Chris@0: PyObject *pyList = PyList_New(plugins.size()); Chris@0: Chris@0: for (size_t i = 0; i < plugins.size(); ++i) { Chris@0: string path = loader->getLibraryPathForPlugin(plugins[i]); Chris@0: libraryMap.insert(LibraryMap::value_type(path, plugins[i])); Chris@0: Chris@0: PyObject *pyPluginKey = PyString_FromString(plugins[i].c_str()); Chris@0: PyList_SET_ITEM(pyList,i,pyPluginKey); luis@7: Chris@0: } Chris@0: Chris@0: PyList_Sort(pyList); Chris@0: return pyList; Chris@0: } Chris@0: Chris@0: Chris@0: /* GET PLUGIN LIBRARY PATH*/ Chris@0: Chris@0: static PyObject * Chris@0: vampyhost_getLibraryPath(PyObject *self, PyObject *args) Chris@0: { Chris@0: PyObject *pyPluginKey; Chris@0: Chris@0: if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) { Chris@0: PyErr_SetString(PyExc_TypeError, Chris@0: "String input argument required: pluginKey"); Chris@0: return NULL; } Chris@0: Chris@0: //convert to stl string Chris@0: string pluginKey(PyString_AS_STRING(pyPluginKey)); Chris@0: Chris@0: //check pluginKey Validity Chris@0: string::size_type ki = pluginKey.find(':'); Chris@0: if (ki == string::npos) { Chris@0: PyErr_SetString(PyExc_TypeError, luis@7: "String input argument required: pluginLibrary:Identifier"); Chris@0: return NULL; Chris@0: } Chris@0: Chris@0: PluginLoader *loader = PluginLoader::getInstance(); Chris@0: string path = loader->getLibraryPathForPlugin(pluginKey); Chris@0: PyObject *pyPath = PyString_FromString(path.c_str()); Chris@0: return pyPath; Chris@0: } Chris@0: Chris@0: Chris@0: /* GET PLUGIN CATEGORY*/ Chris@0: Chris@0: static PyObject * Chris@0: vampyhost_getPluginCategory(PyObject *self, PyObject *args) Chris@0: { Chris@0: PyObject *pyPluginKey; Chris@0: Chris@0: if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) { Chris@0: PyErr_SetString(PyExc_TypeError, Chris@0: "String input argument required: pluginKey"); Chris@0: return NULL; } Chris@0: Chris@0: //convert to stl string Chris@0: string pluginKey(PyString_AS_STRING(pyPluginKey)); Chris@0: Chris@0: //check pluginKey Validity Chris@0: string::size_type ki = pluginKey.find(':'); Chris@0: if (ki == string::npos) { Chris@0: PyErr_SetString(PyExc_TypeError, luis@7: "String input argument required: pluginLibrary:Identifier"); Chris@0: return NULL; Chris@0: } Chris@0: Chris@0: PluginLoader *loader = PluginLoader::getInstance(); luis@7: PluginLoader::PluginCategoryHierarchy Chris@0: category = loader->getPluginCategory(pluginKey); Chris@0: string catstring; Chris@0: Chris@0: if (!category.empty()) { Chris@0: catstring = ""; Chris@0: for (size_t ci = 0; ci < category.size(); ++ci) { Chris@0: catstring.append(category[ci]); Chris@0: catstring.append(" "); Chris@0: } Chris@0: PyObject *pyCat = PyString_FromString(catstring.c_str()); Chris@0: return pyCat; Chris@0: } Chris@0: PyObject *pyCat = PyString_FromString(""); Chris@0: return pyCat; Chris@0: } Chris@0: Chris@0: Chris@0: Chris@0: /* GET PLUGIN OUTPUT LIST*/ Chris@0: Chris@0: static PyObject * Chris@0: vampyhost_getOutputList(PyObject *self, PyObject *args) Chris@0: { Chris@0: PyObject *pyPluginHandle; Chris@0: string pluginKey; Chris@0: Chris@0: if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) { Chris@0: PyErr_SetString(PyExc_TypeError, Chris@0: "Invalid argument: plugin handle or plugin key required."); luis@7: return NULL; Chris@0: } Chris@0: Chris@0: //check if we have a plugin key string or a handle object Chris@0: if (PyString_Check(pyPluginHandle) ) { Chris@0: Chris@0: pluginKey.assign(PyString_AS_STRING(pyPluginHandle)); Chris@0: //check pluginKey Validity Chris@0: string::size_type ki = pluginKey.find(':'); Chris@0: if (ki == string::npos) { Chris@0: PyErr_SetString(PyExc_TypeError, luis@7: "String input argument required: pluginLibrary:Identifier"); Chris@0: return NULL; Chris@0: } Chris@0: Chris@0: } else { luis@7: luis@7: string *key; luis@7: Plugin *plugin; Chris@0: Chris@0: if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) { Chris@0: PyErr_SetString(PyExc_TypeError, Chris@0: "Invalid or deleted plugin handle."); Chris@0: return NULL; } Chris@0: pluginKey.assign(*key); luis@7: } luis@7: Chris@0: //This code creates new instance of the plugin anyway Chris@0: PluginLoader *loader = PluginLoader::getInstance(); luis@7: Chris@0: //load plugin Chris@3: Plugin *plugin = loader->loadPlugin Chris@3: (pluginKey, 48000, PluginLoader::ADAPT_ALL_SAFE); luis@7: if (!plugin) { Chris@0: string pyerr("Failed to load plugin: "); pyerr += pluginKey; luis@7: PyErr_SetString(PyExc_TypeError,pyerr.c_str()); Chris@0: return NULL; luis@7: } Chris@0: Chris@0: Plugin::OutputList outputs = plugin->getOutputDescriptors(); Chris@0: //Plugin::OutputDescriptor od; Chris@0: Chris@0: if (outputs.size()<1) { Chris@0: string pyerr("Plugin has no output: "); pyerr += pluginKey; luis@7: PyErr_SetString(PyExc_TypeError,pyerr.c_str()); Chris@0: return NULL; Chris@0: } Chris@0: Chris@0: //New list object Chris@0: PyObject *pyList = PyList_New(outputs.size()); Chris@0: Chris@0: for (size_t i = 0; i < outputs.size(); ++i) { luis@7: PyObject *pyOutputId = Chris@0: PyString_FromString(outputs[i].identifier.c_str()); luis@7: PyList_SET_ITEM(pyList,i,pyOutputId); Chris@0: } Chris@0: Chris@0: delete plugin; Chris@0: return pyList; Chris@0: } Chris@0: Chris@0: Chris@0: Chris@0: /* LOAD PLUGIN */ Chris@0: Chris@0: static PyObject * Chris@0: vampyhost_loadPlugin(PyObject *self, PyObject *args) Chris@0: { Chris@0: PyObject *pyPluginKey; Chris@0: float inputSampleRate; Chris@0: luis@7: if (!PyArg_ParseTuple(args, "Sf", Chris@0: &pyPluginKey, Chris@0: &inputSampleRate)) { Chris@0: PyErr_SetString(PyExc_TypeError, Chris@0: "String input argument required: pluginKey"); Chris@0: return NULL; } Chris@0: Chris@0: //convert to stl string Chris@0: string pluginKey(PyString_AS_STRING(pyPluginKey)); Chris@0: Chris@0: //check pluginKey Validity Chris@0: string::size_type ki = pluginKey.find(':'); Chris@0: if (ki == string::npos) { Chris@0: PyErr_SetString(PyExc_TypeError, luis@7: "String input argument required: pluginLibrary:Identifier"); Chris@0: return NULL; Chris@0: } Chris@0: Chris@0: PluginLoader *loader = PluginLoader::getInstance(); luis@7: Chris@0: //load plugin luis@7: Plugin *plugin = loader->loadPlugin (pluginKey, inputSampleRate, Chris@6: PluginLoader::ADAPT_ALL_SAFE); luis@7: if (!plugin) { Chris@0: string pyerr("Failed to load plugin: "); pyerr += pluginKey; luis@7: PyErr_SetString(PyExc_TypeError,pyerr.c_str()); Chris@0: return NULL; luis@7: } Chris@0: //void *identifier = (void*) new string(pluginKey); Chris@0: PyPluginDescriptor *pd = new PyPluginDescriptor; luis@7: Chris@0: pd->key = pluginKey; Chris@0: pd->isInitialised = false; Chris@0: pd->inputSampleRate = inputSampleRate; luis@7: Chris@0: //New PyCObject luis@7: //PyObject *pyPluginHandle = PyCObject_FromVoidPtrAndDesc( luis@7: //(void*) plugin, identifier, NULL); Chris@0: luis@7: PyObject *pyPluginHandle = PyCObject_FromVoidPtrAndDesc( luis@7: (void*) plugin, (void*) pd, NULL); luis@7: Chris@0: return pyPluginHandle; Chris@0: } Chris@0: Chris@0: Chris@0: Chris@0: /* UNLOAD PLUGIN */ Chris@0: Chris@0: static PyObject * Chris@0: vampyhost_unloadPlugin(PyObject *self, PyObject *args) Chris@0: { Chris@0: PyObject *pyPluginHandle; Chris@0: Chris@0: if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) { Chris@0: PyErr_SetString(PyExc_TypeError, Chris@0: "Wrong input argument: Plugin Handle required."); Chris@0: return NULL; } Chris@0: luis@7: string *key; luis@7: Plugin *plugin; Chris@0: Chris@0: if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) { Chris@0: PyErr_SetString(PyExc_TypeError, Chris@0: "Invalid or already deleted plugin handle."); Chris@0: return NULL; } Chris@0: Chris@0: /* Prevent repeated calls from causing segfault Chris@0: sice it will fail type checking the 2nd time: */ Chris@0: PyCObject_SetVoidPtr(pyPluginHandle,NULL); luis@7: Chris@0: PyPluginDescriptor *pd = (PyPluginDescriptor*) key; luis@7: Chris@0: delete plugin; Chris@0: delete pd; Chris@0: return pyPluginHandle; Chris@0: Chris@0: } Chris@0: Chris@0: Chris@0: /* INITIALISE PLUGIN */ Chris@0: Chris@0: static PyObject * Chris@0: vampyhost_initialise(PyObject *self, PyObject *args) Chris@0: { Chris@0: PyObject *pyPluginHandle; luis@7: size_t channels, blockSize, stepSize; Chris@0: luis@7: if (!PyArg_ParseTuple (args, "Onnn", &pyPluginHandle, luis@7: (size_t) &channels, luis@7: (size_t) &stepSize, luis@7: (size_t) &blockSize)) Chris@0: { Chris@0: PyErr_SetString(PyExc_TypeError, Chris@0: "Wrong input arguments: requires a valid plugin handle,channels,stepSize,blockSize."); luis@7: return NULL; Chris@0: } Chris@0: luis@7: Plugin *plugin; luis@7: string *key; Chris@0: Chris@0: if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) { Chris@0: PyErr_SetString(PyExc_TypeError, Chris@0: "Invalid plugin handle."); Chris@0: return NULL; } Chris@0: Chris@0: // here we cast the void pointer as PyPluginDescriptor instead of string luis@7: PyPluginDescriptor *plugDesc = (PyPluginDescriptor*) key; Chris@0: Chris@0: plugDesc->channels = channels; Chris@0: plugDesc->stepSize = stepSize; Chris@0: plugDesc->blockSize = blockSize; Chris@3: Chris@0: if (!plugin->initialise(channels, stepSize, blockSize)) { Chris@6: std::cerr << "Failed to initialise native plugin adapter with channels = " << channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << " and ADAPT_ALL_SAFE set" << std::endl; Chris@0: PyErr_SetString(PyExc_TypeError, Chris@0: "Plugin initialization failed."); Chris@6: return NULL; Chris@6: } Chris@0: luis@7: plugDesc->identifier = Chris@0: plugDesc->key.substr(plugDesc->key.rfind(':')+1); Chris@0: plugDesc->isInitialised = true; luis@7: Chris@0: return Py_True; Chris@0: } Chris@0: Chris@4: // These conversion functions are borrowed from PyTypeInterface in VamPy Chris@4: Chris@4: template Chris@4: static Chris@4: RET *pyArrayConvert(char* raw_data_ptr, long length, size_t strides) Chris@4: { Chris@4: RET *rValue = new RET[length]; luis@7: Chris@4: /// check if the array is continuous, if not use strides info Chris@4: if (sizeof(DTYPE)!=strides) { Chris@4: char* data = (char*) raw_data_ptr; Chris@4: for (long i = 0; idescr; luis@7: Chris@4: /// check raw data and descriptor pointers Chris@4: if (pyArray->data == 0 || descr == 0) { Chris@4: cerr << "pyArrayToFloatArray: Failed, NumPy array has NULL data or descriptor" << endl; Chris@4: return 0; Chris@4: } Chris@4: Chris@4: /// check dimensions Chris@4: if (pyArray->nd != 1) { Chris@4: cerr << "pyArrayToFloatArray: Failed, NumPy array is multi-dimensional" << endl; Chris@4: return 0; Chris@4: } Chris@4: Chris@4: /// check strides (useful if array is not continuous) Chris@4: size_t strides = *((size_t*) pyArray->strides); luis@7: Chris@4: /// convert the array Chris@4: switch (descr->type_num) { Chris@4: case NPY_FLOAT : // dtype='float32' Chris@4: return pyArrayConvert(pyArray->data,pyArray->dimensions[0],strides); Chris@4: case NPY_DOUBLE : // dtype='float64' Chris@4: return pyArrayConvert(pyArray->data,pyArray->dimensions[0],strides); Chris@4: default: Chris@4: cerr << "pyArrayToFloatArray: Failed: Unsupported value type " << descr->type_num << " in NumPy array object (only float32, float64 supported)" << endl; Chris@4: return 0; Chris@4: } Chris@4: } Chris@4: Chris@0: Chris@0: /* RUN PROCESS */ Chris@0: Chris@0: static PyObject * Chris@0: vampyhost_process(PyObject *self, PyObject *args) Chris@0: { Chris@0: PyObject *pyPluginHandle; luis@8: PyArrayObject *pyBuffer; Chris@0: PyObject *pyRealTime; Chris@0: luis@7: if (!PyArg_ParseTuple(args, "OOO", Chris@0: &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor luis@8: &pyBuffer, // Audio data (NumPy ndim array) Chris@0: &pyRealTime)) { // TimeStamp Chris@0: PyErr_SetString(PyExc_TypeError, Chris@0: "Required: plugin handle, buffer, timestmap."); Chris@0: return NULL; } Chris@0: Chris@0: if (!PyRealTime_Check(pyRealTime)) { Chris@0: PyErr_SetString(PyExc_TypeError,"Valid timestamp required."); Chris@0: return NULL; } Chris@0: Chris@4: string *key; luis@7: Plugin *plugin; Chris@0: Chris@4: if (!getPluginHandle(pyPluginHandle, &plugin, &key)) { luis@8: PyErr_SetString(PyExc_AttributeError, luis@8: "Invalid or already deleted plugin handle."); luis@8: return NULL; Chris@4: } Chris@0: Chris@0: PyPluginDescriptor *pd = (PyPluginDescriptor*) key; Chris@0: Chris@0: if (!pd->isInitialised) { luis@8: PyErr_SetString(PyExc_StandardError, luis@8: "Plugin has not been initialised."); luis@8: return NULL; } Chris@0: luis@7: size_t channels = pd->channels; Chris@0: size_t blockSize = pd->blockSize; Chris@0: luis@8: if (!PyArray_Check(pyBuffer)) { luis@8: PyErr_SetString(PyExc_TypeError, "Argument is not a Numpy array."); Chris@4: return NULL; Chris@0: } Chris@0: luis@8: if (pyBuffer->nd != channels) { luis@8: cerr << "Wrong number of channels: got " << pyBuffer->nd << ", expected " << channels << endl; Chris@4: PyErr_SetString(PyExc_TypeError, "Wrong number of channels"); Chris@4: return NULL; Chris@4: } Chris@0: luis@8: int n = pyBuffer->dimensions[0]; luis@8: int m = pyBuffer->dimensions[1]; luis@8: luis@10: // Domain Type, either Vamp::Plugin::FrequencyDomain luis@10: // or Vamp::Plugin::TimeDomain luis@10: Vamp::Plugin::InputDomain dtype = plugin->getInputDomain(); luis@10: luis@8: cout << "Kind :" << pyBuffer->descr->kind << endl; luis@8: cout << "Strides 0 :" << pyBuffer->strides[0] << endl; luis@8: cout << "Strides 1 :" << pyBuffer->strides[1] << endl; luis@8: cout << "Flags:" << pyBuffer->flags << endl; luis@8: luis@10: cout << "Input Domain" << dtype << endl; luis@10: cout << "Plugin Maker" << plugin->getMaker() << endl; luis@10: Chris@4: float **inbuf = new float *[channels]; luis@8: cout << "Created inbuf with #channels: " << channels << endl; Chris@0: luis@11: luis@11: Chris@4: for (int c = 0; c < channels; ++c) { luis@8: luis@8: // cout << "[Host] Converting channel #" << c << endl; luis@8: // PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c); luis@8: // cout << "Ok1..." << endl; luis@8: // inbuf[c] = pyArrayToFloatArray(cbuf); luis@8: luis@8: inbuf[c] = pyArrayToFloatArray((PyObject*) pyBuffer); luis@8: luis@11: cout << "Converted " << endl; luis@8: Chris@4: if (!inbuf[c]) { Chris@4: PyErr_SetString(PyExc_TypeError,"NumPy Array required for each channel in process input."); Chris@4: return NULL; Chris@0: } luis@8: luis@8: cout << "[Host] Converted channel #" << c << endl; luis@8: Chris@4: } Chris@0: Chris@0: RealTime timeStamp = *PyRealTime_AsPointer(pyRealTime); Chris@0: luis@8: cout << "[Host] Gonna call plugin->process" << endl; luis@8: Chris@0: //Call process and store the output Chris@4: pd->output = plugin->process(inbuf, timeStamp); Chris@0: luis@8: cout << "[Host] Called plugin->process" << endl; luis@8: Chris@0: /* TODO: DO SOMETHONG WITH THE FEATURE SET HERE */ luis@9: /// convert to appropriate python objects, reuse types and conversion utilities from Vampy ... Chris@0: luis@10: luis@10: size_t featListOutLength = pd->output.size(); luis@10: luis@10: //New PyList for the featurelist luis@10: PyObject *pyFeatureList = PyList_New(featListOutLength); luis@10: luis@10: PyArrayObject *aaaa; luis@10: luis@10: npy_intp *dims[2]; luis@10: luis@10: // Plugin::FeatureList features = pd->output[0]; luis@10: luis@9: // Loop FeatureLists luis@9: for(int i = 0; i < pd->output.size(); i++ ){ luis@10: //New PyList for the features luis@10: size_t outLength = pd->output[i].size(); luis@10: PyObject *pyFeatureList = PyList_New(outLength); luis@10: luis@9: cout << "FeatureList #" << i << " has size " << pd->output[i].size() << endl; luis@9: luis@9: // loop Features luis@9: for(int j = 0; j < pd->output[i].size(); j++ ){ luis@10: luis@10: // debug - printing some features luis@9: cout << "Feature #" << j << endl; luis@9: cout << " Label: " << pd->output[i][j].label << endl; luis@9: cout << " hasTimestamp? " << pd->output[i][j].hasTimestamp << endl; luis@9: cout << " hasDuration? " << pd->output[i][j].hasDuration << endl; luis@9: cout << " values.size " << pd->output[i][j].values.size() << endl; luis@9: cout << " values[0] " << pd->output[i][j].values[0] << endl; luis@9: } luis@9: } luis@9: luis@9: luis@10: // Gonna print just one luis@9: luis@10: size_t arraySize = pd->output[0][0].values.size(); luis@10: PyObject *pySampleList = PyList_New((Py_ssize_t) arraySize); luis@10: PyObject **pySampleListArray = PySequence_Fast_ITEMS(pySampleList); luis@10: luis@10: for (size_t idx = 0; idx < arraySize; ++idx) { luis@10: PyObject *pyFloat=PyFloat_FromDouble((double) pd->output[0][0].values[idx]); luis@10: pySampleListArray[idx] = pyFloat; luis@10: } Chris@0: Chris@4: for (int c = 0; c < channels; ++c){ Chris@4: delete[] inbuf[c]; Chris@0: } Chris@4: delete[] inbuf; Chris@0: luis@10: return PyArray_Return((PyArrayObject*) pySampleList); luis@10: // return pySampleList; luis@10: luis@10: // return pyFeatureList; //!!! Need to return actual features! Chris@0: } Chris@0: Chris@0: /* GET / SET OUTPUT */ Chris@0: Chris@0: //getOutput(plugin,outputNo) Chris@0: static PyObject * Chris@0: vampyhost_getOutput(PyObject *self, PyObject *args) { Chris@0: Chris@0: PyObject *pyPluginHandle; Chris@0: // PyObject *pyBuffer; Chris@0: // PyObject *pyRealTime; Chris@0: PyObject *pyOutput; Chris@0: luis@7: if (!PyArg_ParseTuple(args, "OO", Chris@0: &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor Chris@0: &pyOutput)) { // Output reference Chris@0: PyErr_SetString(PyExc_TypeError, Chris@0: "Required: plugin handle, buffer, timestmap."); Chris@0: return NULL; } Chris@0: luis@7: string *key; luis@7: Plugin *plugin; Chris@0: Chris@0: if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) { Chris@0: PyErr_SetString(PyExc_AttributeError, Chris@0: "Invalid or already deleted plugin handle."); Chris@0: return NULL; } Chris@0: Chris@0: PyPluginDescriptor *pd = (PyPluginDescriptor*) key; Chris@0: Chris@0: unsigned int outputNo = (unsigned int) PyInt_AS_LONG(pyOutput); Chris@0: Chris@0: //Get output list: but we don't need it Chris@0: //Plugin::FeatureList features = pd->output[outputNo]; Chris@0: Chris@0: size_t outLength = pd->output[outputNo].size(); Chris@0: Chris@0: //New PyList for the featurelist Chris@0: PyObject *pyFeatureList = PyList_New(outLength); Chris@0: Chris@0: for (size_t i = 0; i < outLength; ++i) { Chris@0: // Test: Chris@0: /* luis@7: XxoObject *pyFeature = PyObject_New(XxoObject, &Xxo_Type); Chris@0: if (pyFeature == NULL) break; //return NULL; Chris@0: Chris@0: pyFeature->x_attr = NULL; Chris@0: pyFeature->feature = &pd->output[outputNo][i]; Chris@0: luis@7: PyList_SET_ITEM(pyFeatureList,i,(PyObject*)pyFeature); Chris@0: */ Chris@0: } Chris@0: Chris@0: Py_INCREF(pyFeatureList); Chris@0: return pyFeatureList; Chris@0: Chris@0: // EXPLAIN WHAT WE NEED TO DO HERE: Chris@0: // We have the block output in pd->output luis@7: // FeatureSet[output] -> [Feature[x]] -> Feature.hasTimestamp = v luis@7: // Vamp::Plugin::FeatureSet output; = pd->output Chris@0: // typedef std::vector FeatureList; Chris@0: // typedef std::map FeatureSet; // key is output no Chris@0: luis@7: // THIS IS FOR OUTPUT id LOOKUP LATER Chris@0: // Plugin::OutputList outputs = plugin->getOutputDescriptors(); luis@7: // Chris@0: // if (outputs.size()<1) { Chris@0: // string pyerr("Plugin has no output: "); pyerr += pluginKey; luis@7: // PyErr_SetString(PyExc_TypeError,pyerr.c_str()); Chris@0: // return NULL; Chris@0: // } luis@7: // Chris@0: // //New list object Chris@0: // PyObject *pyList = PyList_New(outputs.size()); luis@7: // Chris@0: // for (size_t i = 0; i < outputs.size(); ++i) { luis@7: // PyObject *pyOutputId = Chris@0: // PyString_FromString(outputs[i].identifier.c_str()); luis@7: // PyList_SET_ITEM(pyList,i,pyOutputId); Chris@0: // } luis@7: Chris@0: } Chris@0: Chris@0: Chris@0: Chris@0: Chris@0: /* List of functions defined in this module */ Chris@0: //module methods table Chris@0: static PyMethodDef vampyhost_methods[] = { Chris@0: Chris@0: {"enumeratePlugins", vampyhost_enumeratePlugins, METH_VARARGS, Chris@0: xx_foo_doc}, Chris@0: Chris@0: {"getLibraryPath", vampyhost_getLibraryPath, METH_VARARGS, Chris@0: xx_foo_doc}, Chris@0: Chris@0: {"getPluginCategory", vampyhost_getPluginCategory, METH_VARARGS, Chris@0: xx_foo_doc}, Chris@0: Chris@0: {"getOutputList", vampyhost_getOutputList, METH_VARARGS, Chris@0: xx_foo_doc}, Chris@0: Chris@0: {"loadPlugin", vampyhost_loadPlugin, METH_VARARGS, Chris@0: xx_foo_doc}, Chris@0: Chris@0: {"process", vampyhost_process, METH_VARARGS, Chris@0: xx_foo_doc}, Chris@0: Chris@0: {"unloadPlugin", vampyhost_unloadPlugin, METH_VARARGS, Chris@0: xx_foo_doc}, Chris@0: Chris@0: {"initialise", vampyhost_initialise, METH_VARARGS, Chris@0: xx_foo_doc}, Chris@0: Chris@0: {"getOutput", vampyhost_getOutput, METH_VARARGS, Chris@0: xx_foo_doc}, Chris@0: Chris@0: /* Add RealTime Module Methods */ Chris@0: Chris@0: {"frame2RealTime", (PyCFunction)RealTime_frame2RealTime, METH_VARARGS, Chris@0: PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")}, Chris@0: Chris@0: {"realtime", (PyCFunction)RealTime_new, METH_VARARGS, Chris@0: PyDoc_STR("realtime() -> returns new RealTime object")}, luis@7: Chris@0: {NULL, NULL} /* sentinel */ Chris@0: }; Chris@0: Chris@0: //Documentation for our new module Chris@0: PyDoc_STRVAR(module_doc, "This is a template module just for instruction."); Chris@0: Chris@0: /* Initialization function for the module (*must* be called initxx) */ Chris@0: Chris@0: //module initialization (includes extern C {...} as necessary) Chris@0: PyMODINIT_FUNC Chris@0: initvampyhost(void) Chris@0: { Chris@0: PyObject *m; Chris@0: Chris@0: /* Finalize the type object including setting type of the new type luis@7: * object; doing it here is required for portability to Windows Chris@0: * without requiring C++. */ Chris@0: Chris@0: if (PyType_Ready(&RealTime_Type) < 0) Chris@0: return; Chris@0: // PyModule_AddObject(m, "Real_Time", (PyObject *)&RealTime_Type); Chris@0: Chris@0: /* Create the module and add the functions */ Chris@0: m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc); Chris@0: if (m == NULL) return; Chris@0: luis@8: // Numpy array library initialization function luis@8: import_array(); luis@8: Chris@0: // PyModule_AddObject(m, "realtime", (PyObject *)&RealTime_Type); Chris@0: Chris@0: }