Chris@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@26: /* Chris@26: VampyHost Chris@26: Chris@26: Use Vamp audio analysis plugins in Python Chris@26: Chris@26: Gyorgy Fazekas and Chris Cannam Chris@26: Centre for Digital Music, Queen Mary, University of London Chris@26: Copyright 2008-2014 Queen Mary, University of London Chris@26: Chris@26: Permission is hereby granted, free of charge, to any person Chris@26: obtaining a copy of this software and associated documentation Chris@26: files (the "Software"), to deal in the Software without Chris@26: restriction, including without limitation the rights to use, copy, Chris@26: modify, merge, publish, distribute, sublicense, and/or sell copies Chris@26: of the Software, and to permit persons to whom the Software is Chris@26: furnished to do so, subject to the following conditions: Chris@26: Chris@26: The above copyright notice and this permission notice shall be Chris@26: included in all copies or substantial portions of the Software. Chris@26: Chris@26: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, Chris@26: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF Chris@26: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND Chris@26: NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR Chris@26: ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF Chris@26: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION Chris@26: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Chris@26: Chris@26: Except as contained in this notice, the names of the Centre for Chris@26: Digital Music; Queen Mary, University of London; and the authors Chris@26: shall not be used in advertising or otherwise to promote the sale, Chris@26: use or other dealings in this Software without prior written Chris@26: authorization. Chris@26: */ Chris@26: Chris@26: #include "PyRealTime.h" Chris@26: Chris@0: //include for python extension module: must be first Chris@0: #include Chris@14: Chris@14: // define a unique API pointer Chris@27: #define PY_ARRAY_UNIQUE_SYMBOL VAMPYHOST_ARRAY_API Chris@14: #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION Chris@14: #include "numpy/arrayobject.h" Chris@14: Chris@0: #include Chris@12: Chris@12: #define HAVE_NUMPY 1 // Required Chris@12: 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@16: Chris@29: #include "VectorConversion.h" Chris@16: #include "PyRealTime.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 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@16: // structure for holding plugin instance data Chris@21: struct PyPluginObject Chris@16: { Chris@21: PyObject_HEAD Chris@21: string *key; Chris@16: Plugin *plugin; Chris@16: float inputSampleRate; Chris@16: bool isInitialised; Chris@16: size_t channels; Chris@16: size_t blockSize; Chris@16: size_t stepSize; Chris@21: static PyPluginObject *create_internal(); Chris@16: }; Chris@0: Chris@21: PyAPI_DATA(PyTypeObject) Plugin_Type; Chris@21: #define PyPlugin_Check(v) PyObject_TypeCheck(v, &Plugin_Type) Chris@21: Chris@21: static void Chris@21: PyPluginObject_dealloc(PyPluginObject *self) Chris@21: { Chris@21: cerr << "PyPluginObject_dealloc" << endl; Chris@21: delete self->key; Chris@21: delete self->plugin; Chris@21: PyObject_Del(self); Chris@21: } Chris@21: Chris@2: PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!! Chris@0: Chris@28: //!!! todo: conv errors Chris@28: Chris@21: PyPluginObject * Chris@21: getPluginObject(PyObject *pyPluginHandle) Chris@21: { Chris@21: cerr << "getPluginObject" << endl; Chris@0: Chris@21: PyPluginObject *pd = 0; Chris@21: if (PyPlugin_Check(pyPluginHandle)) { Chris@21: pd = (PyPluginObject *)pyPluginHandle; Chris@16: } Chris@16: if (!pd || !pd->plugin) { Chris@16: PyErr_SetString(PyExc_AttributeError, Chris@16: "Invalid or already deleted plugin handle."); Chris@16: return 0; Chris@0: } else { Chris@16: return pd; Chris@0: } Chris@0: } Chris@0: Chris@0: static PyObject * Chris@23: vampyhost_enumeratePlugins(PyObject *self, PyObject *) Chris@0: { Chris@21: cerr << "vampyhost_enumeratePlugins" << endl; Chris@21: Chris@0: PluginLoader *loader = PluginLoader::getInstance(); Chris@0: vector plugins = loader->listPlugins(); Chris@29: VectorConversion conv; Chris@15: return conv.PyValue_From_StringVector(plugins); Chris@0: } Chris@0: Chris@15: static PyObject * Chris@23: vampyhost_getPluginPath(PyObject *self, PyObject *) Chris@15: { Chris@21: cerr << "vampyhost_getPluginPath" << endl; Chris@21: Chris@15: vector path = PluginHostAdapter::getPluginPath(); Chris@29: VectorConversion conv; Chris@15: return conv.PyValue_From_StringVector(path); Chris@15: } Chris@0: Chris@15: static string toPluginKey(PyObject *pyPluginKey) Chris@0: { Chris@21: cerr << "toPluginKey" << endl; Chris@21: 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, Chris@15: "Plugin key must be of the form library:identifier"); Chris@15: return ""; Chris@0: } Chris@0: Chris@15: return pluginKey; Chris@15: } Chris@15: Chris@15: static PyObject * Chris@15: vampyhost_getLibraryFor(PyObject *self, PyObject *args) Chris@15: { Chris@21: cerr << "vampyhost_getLibraryFor" << endl; Chris@21: Chris@15: PyObject *pyPluginKey; Chris@15: Chris@15: if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) { Chris@15: PyErr_SetString(PyExc_TypeError, Chris@15: "getLibraryPathForPlugin() takes plugin key (string) argument"); Chris@16: return 0; } Chris@15: Chris@15: string pluginKey = toPluginKey(pyPluginKey); Chris@16: if (pluginKey == "") return 0; Chris@15: 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: static PyObject * Chris@0: vampyhost_getPluginCategory(PyObject *self, PyObject *args) Chris@0: { Chris@21: cerr << "vampyhost_getPluginCategory" << endl; Chris@21: Chris@0: PyObject *pyPluginKey; Chris@0: Chris@0: if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) { Chris@0: PyErr_SetString(PyExc_TypeError, Chris@15: "getPluginCategory() takes plugin key (string) argument"); Chris@16: return 0; } Chris@0: Chris@15: string pluginKey = toPluginKey(pyPluginKey); Chris@16: if (pluginKey == "") return 0; Chris@0: Chris@0: PluginLoader *loader = PluginLoader::getInstance(); luis@7: PluginLoader::PluginCategoryHierarchy Chris@0: category = loader->getPluginCategory(pluginKey); Chris@0: Chris@29: VectorConversion conv; Chris@15: return conv.PyValue_From_StringVector(category); Chris@0: } Chris@0: Chris@0: static PyObject * Chris@0: vampyhost_getOutputList(PyObject *self, PyObject *args) Chris@0: { Chris@21: cerr << "vampyhost_getOutputList" << endl; Chris@21: Chris@16: PyObject *keyOrHandle; Chris@15: Plugin::OutputList outputs; Chris@0: Chris@16: if (!PyArg_ParseTuple(args, "O", &keyOrHandle)) { Chris@0: PyErr_SetString(PyExc_TypeError, Chris@15: "getOutputList() takes plugin handle (object) or plugin key (string) argument"); Chris@16: return 0; Chris@0: } Chris@0: Chris@16: if (PyString_Check(keyOrHandle) ) { Chris@0: Chris@15: // we have a plugin key Chris@0: Chris@16: string pluginKey = toPluginKey(keyOrHandle); Chris@16: if (pluginKey == "") return 0; Chris@15: Chris@15: PluginLoader *loader = PluginLoader::getInstance(); Chris@15: Chris@15: Plugin *plugin = loader->loadPlugin Chris@15: (pluginKey, 48000, PluginLoader::ADAPT_ALL_SAFE); Chris@15: if (!plugin) { Chris@15: string pyerr("Failed to load plugin: "); pyerr += pluginKey; Chris@15: PyErr_SetString(PyExc_TypeError,pyerr.c_str()); Chris@16: return 0; Chris@15: } Chris@15: Chris@15: outputs = plugin->getOutputDescriptors(); Chris@15: Chris@15: delete plugin; Chris@15: Chris@0: } else { luis@7: Chris@15: // we have a loaded plugin handle Chris@15: Chris@21: PyPluginObject *pd = getPluginObject(keyOrHandle); Chris@16: if (!pd) return 0; Chris@0: Chris@16: outputs = pd->plugin->getOutputDescriptors(); luis@7: } luis@7: 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()); Chris@15: PyList_SET_ITEM(pyList, i, pyOutputId); Chris@0: } Chris@0: Chris@0: return pyList; Chris@0: } Chris@0: Chris@0: static PyObject * Chris@0: vampyhost_loadPlugin(PyObject *self, PyObject *args) Chris@0: { Chris@21: cerr << "vampyhost_loadPlugin" << endl; Chris@21: 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@20: "loadPlugin() takes plugin key (string) and sample rate (float) arguments"); Chris@16: return 0; } Chris@0: Chris@15: string pluginKey = toPluginKey(pyPluginKey); Chris@16: if (pluginKey == "") return 0; Chris@0: Chris@0: PluginLoader *loader = PluginLoader::getInstance(); luis@7: Chris@15: Plugin *plugin = loader->loadPlugin(pluginKey, inputSampleRate, Chris@15: 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@16: return 0; luis@7: } Chris@15: Chris@21: PyPluginObject *pd = PyPluginObject::create_internal(); Chris@21: pd->key = new string(pluginKey); Chris@21: pd->plugin = plugin; Chris@21: pd->inputSampleRate = inputSampleRate; Chris@21: pd->isInitialised = false; Chris@21: pd->channels = 0; Chris@21: pd->blockSize = 0; Chris@21: pd->stepSize = 0; Chris@21: return (PyObject *)pd; Chris@0: } Chris@0: Chris@0: static PyObject * Chris@0: vampyhost_initialise(PyObject *self, PyObject *args) Chris@0: { Chris@21: cerr << "vampyhost_initialise" << endl; Chris@21: luis@7: size_t channels, blockSize, stepSize; Chris@0: Chris@23: if (!PyArg_ParseTuple (args, "nnn", luis@7: (size_t) &channels, luis@7: (size_t) &stepSize, Chris@23: (size_t) &blockSize)) { Chris@0: PyErr_SetString(PyExc_TypeError, Chris@23: "initialise() takes channel count, step size, and block size arguments"); Chris@16: return 0; Chris@0: } Chris@0: Chris@23: PyPluginObject *pd = getPluginObject(self); Chris@16: if (!pd) return 0; Chris@0: Chris@16: pd->channels = channels; Chris@16: pd->stepSize = stepSize; Chris@16: pd->blockSize = blockSize; Chris@0: Chris@16: if (!pd->plugin->initialise(channels, stepSize, blockSize)) { Chris@17: cerr << "Failed to initialise native plugin adapter with channels = " << channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << " and ADAPT_ALL_SAFE set" << endl; Chris@0: PyErr_SetString(PyExc_TypeError, Chris@17: "Plugin initialization failed"); Chris@16: return 0; Chris@6: } Chris@0: Chris@16: pd->isInitialised = true; luis@7: Chris@0: return Py_True; Chris@0: } Chris@0: Chris@0: static PyObject * Chris@23: vampyhost_reset(PyObject *self, PyObject *) Chris@18: { Chris@21: cerr << "vampyhost_reset" << endl; Chris@21: Chris@23: PyPluginObject *pd = getPluginObject(self); Chris@18: if (!pd) return 0; Chris@18: Chris@18: if (!pd->isInitialised) { Chris@18: PyErr_SetString(PyExc_StandardError, Chris@18: "Plugin has not been initialised"); Chris@18: return 0; Chris@18: } Chris@18: Chris@18: pd->plugin->reset(); Chris@18: return Py_True; Chris@18: } Chris@18: Chris@18: static PyObject * Chris@20: vampyhost_getParameter(PyObject *self, PyObject *args) Chris@20: { Chris@21: cerr << "vampyhost_getParameter" << endl; Chris@21: Chris@20: PyObject *pyParam; Chris@20: Chris@23: if (!PyArg_ParseTuple(args, "S", &pyParam)) { Chris@20: PyErr_SetString(PyExc_TypeError, Chris@23: "getParameter() takes parameter id (string) argument"); Chris@20: return 0; } Chris@20: Chris@23: PyPluginObject *pd = getPluginObject(self); Chris@20: if (!pd) return 0; Chris@20: Chris@20: float value = pd->plugin->getParameter(PyString_AS_STRING(pyParam)); Chris@20: return PyFloat_FromDouble(double(value)); Chris@20: } Chris@20: Chris@20: static PyObject * Chris@20: vampyhost_setParameter(PyObject *self, PyObject *args) Chris@20: { Chris@21: cerr << "vampyhost_setParameter" << endl; Chris@21: Chris@20: PyObject *pyParam; Chris@20: float value; Chris@20: Chris@23: if (!PyArg_ParseTuple(args, "Sf", &pyParam, &value)) { Chris@20: PyErr_SetString(PyExc_TypeError, Chris@23: "setParameter() takes parameter id (string), and value (float) arguments"); Chris@20: return 0; } Chris@20: Chris@23: PyPluginObject *pd = getPluginObject(self); Chris@20: if (!pd) return 0; Chris@20: Chris@20: pd->plugin->setParameter(PyString_AS_STRING(pyParam), value); Chris@20: return Py_True; Chris@20: } Chris@20: Chris@20: static PyObject * Chris@0: vampyhost_process(PyObject *self, PyObject *args) Chris@0: { Chris@21: cerr << "vampyhost_process" << endl; Chris@21: Chris@0: PyObject *pyBuffer; Chris@0: PyObject *pyRealTime; Chris@0: Chris@23: if (!PyArg_ParseTuple(args, "OO", Chris@0: &pyBuffer, // Audio data Chris@0: &pyRealTime)) { // TimeStamp Chris@0: PyErr_SetString(PyExc_TypeError, Chris@17: "process() takes plugin handle (object), buffer (2D array of channels * samples floats) and timestamp (RealTime) arguments"); Chris@16: return 0; } Chris@0: Chris@0: if (!PyRealTime_Check(pyRealTime)) { Chris@0: PyErr_SetString(PyExc_TypeError,"Valid timestamp required."); Chris@16: return 0; } Chris@0: Chris@17: if (!PyList_Check(pyBuffer)) { Chris@17: PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input."); Chris@17: return 0; Chris@17: } Chris@17: Chris@23: PyPluginObject *pd = getPluginObject(self); Chris@16: if (!pd) return 0; Chris@0: Chris@0: if (!pd->isInitialised) { Chris@0: PyErr_SetString(PyExc_StandardError, Chris@0: "Plugin has not been initialised."); Chris@16: return 0; Chris@16: } Chris@0: Chris@12: int channels = pd->channels; Chris@0: Chris@4: if (PyList_GET_SIZE(pyBuffer) != channels) { Chris@17: cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << endl; Chris@4: PyErr_SetString(PyExc_TypeError, "Wrong number of channels"); Chris@16: return 0; Chris@4: } Chris@0: Chris@4: float **inbuf = new float *[channels]; Chris@0: Chris@29: VectorConversion typeConv; Chris@17: Chris@17: cerr << "here!" << endl; Chris@12: Chris@12: vector > data; Chris@4: for (int c = 0; c < channels; ++c) { Chris@4: PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c); Chris@17: data.push_back(typeConv.PyValue_To_FloatVector(cbuf)); Chris@12: } Chris@12: Chris@12: for (int c = 0; c < channels; ++c) { Chris@17: if (data[c].size() != pd->blockSize) { Chris@17: cerr << "Wrong number of samples on channel " << c << ": expected " << pd->blockSize << " (plugin's block size), got " << data[c].size() << endl; Chris@17: PyErr_SetString(PyExc_TypeError, "Wrong number of samples"); Chris@17: return 0; Chris@17: } Chris@12: inbuf[c] = &data[c][0]; Chris@4: } Chris@0: Chris@17: cerr << "no, here!" << endl; Chris@17: Chris@12: RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime); Chris@0: Chris@18: cerr << "no no, here!" << endl; Chris@0: Chris@18: Plugin::FeatureSet fs = pd->plugin->process(inbuf, timeStamp); Chris@0: Chris@4: delete[] inbuf; Chris@0: Chris@18: cerr << "no no no, here!" << endl; Chris@18: Chris@29: VectorConversion conv; Chris@18: Chris@18: PyObject *pyFs = PyDict_New(); Chris@0: Chris@18: for (Plugin::FeatureSet::const_iterator fsi = fs.begin(); Chris@18: fsi != fs.end(); ++fsi) { Chris@18: Chris@18: int fno = fsi->first; Chris@18: const Plugin::FeatureList &fl = fsi->second; Chris@18: Chris@18: if (!fl.empty()) { Chris@18: Chris@18: PyObject *pyFl = PyList_New(fl.size()); Chris@18: Chris@18: for (int fli = 0; fli < (int)fl.size(); ++fli) { Chris@18: Chris@18: const Plugin::Feature &f = fl[fli]; Chris@18: PyObject *pyF = PyDict_New(); Chris@18: Chris@18: if (f.hasTimestamp) { Chris@18: PyDict_SetItemString Chris@18: (pyF, "timestamp", PyRealTime_FromRealTime(f.timestamp)); Chris@18: } Chris@18: if (f.hasDuration) { Chris@18: PyDict_SetItemString Chris@18: (pyF, "duration", PyRealTime_FromRealTime(f.duration)); Chris@18: } Chris@18: Chris@18: PyDict_SetItemString Chris@18: (pyF, "label", PyString_FromString(f.label.c_str())); Chris@18: Chris@18: if (!f.values.empty()) { Chris@18: PyDict_SetItemString Chris@28: (pyF, "values", conv.PyArray_From_FloatVector(f.values)); Chris@18: } Chris@18: Chris@18: PyList_SET_ITEM(pyFl, fli, pyF); Chris@18: } Chris@18: Chris@18: PyObject *pyN = PyInt_FromLong(fno); Chris@18: PyDict_SetItem(pyFs, pyN, pyFl); Chris@18: } Chris@18: } Chris@18: Chris@18: cerr << "no you fool, here!" << endl; Chris@18: Chris@18: return pyFs; Chris@0: } Chris@0: Chris@23: static PyObject * Chris@23: vampyhost_unload(PyObject *self, PyObject *) Chris@23: { Chris@23: cerr << "vampyhost_unloadPlugin" << endl; Chris@23: Chris@23: PyPluginObject *pd = getPluginObject(self); Chris@23: if (!pd) return 0; Chris@23: Chris@23: delete pd->plugin; Chris@23: pd->plugin = 0; // This is checked by getPluginObject, so we Chris@23: // attempt to avoid repeated calls from blowing up Chris@23: Chris@23: return Py_True; Chris@23: } Chris@23: Chris@21: static PyMethodDef PyPluginObject_methods[] = Chris@21: { Chris@23: {"getParameter", vampyhost_getParameter, METH_VARARGS, Chris@23: xx_foo_doc}, //!!! fix all these! Chris@23: Chris@23: {"setParameter", vampyhost_setParameter, METH_VARARGS, Chris@23: xx_foo_doc}, Chris@23: Chris@23: {"initialise", vampyhost_initialise, METH_VARARGS, Chris@23: xx_foo_doc}, Chris@23: Chris@23: {"reset", vampyhost_reset, METH_NOARGS, Chris@23: xx_foo_doc}, Chris@23: Chris@23: {"process", vampyhost_process, METH_VARARGS, Chris@23: xx_foo_doc}, Chris@23: Chris@23: {"unload", vampyhost_unload, METH_NOARGS, Chris@23: xx_foo_doc}, Chris@23: Chris@21: {0, 0} Chris@21: }; Chris@21: Chris@23: static int Chris@23: PyPluginObject_setattr(PyPluginObject *self, char *name, PyObject *value) Chris@23: { Chris@23: return -1; Chris@23: } Chris@23: Chris@23: static PyObject * Chris@23: PyPluginObject_getattr(PyPluginObject *self, char *name) Chris@23: { Chris@23: return Py_FindMethod(PyPluginObject_methods, (PyObject *)self, name); Chris@23: } Chris@23: Chris@21: /* Doc:: 10.3 Type Objects */ /* static */ Chris@21: PyTypeObject Plugin_Type = Chris@21: { Chris@21: PyObject_HEAD_INIT(NULL) Chris@21: 0, /*ob_size*/ Chris@21: "vampyhost.Plugin", /*tp_name*/ Chris@21: sizeof(PyPluginObject), /*tp_basicsize*/ Chris@21: 0, /*tp_itemsize*/ Chris@21: (destructor)PyPluginObject_dealloc, /*tp_dealloc*/ Chris@21: 0, /*tp_print*/ Chris@23: (getattrfunc)PyPluginObject_getattr, /*tp_getattr*/ Chris@23: (setattrfunc)PyPluginObject_setattr, /*tp_setattr*/ Chris@21: 0, /*tp_compare*/ Chris@21: 0, /*tp_repr*/ Chris@21: 0, /*tp_as_number*/ Chris@21: 0, /*tp_as_sequence*/ Chris@21: 0, /*tp_as_mapping*/ Chris@21: 0, /*tp_hash*/ Chris@21: 0, /*tp_call*/ Chris@21: 0, /*tp_str*/ Chris@21: 0, /*tp_getattro*/ Chris@21: 0, /*tp_setattro*/ Chris@21: 0, /*tp_as_buffer*/ Chris@21: Py_TPFLAGS_DEFAULT, /*tp_flags*/ Chris@21: "Plugin Object", /*tp_doc*/ Chris@21: 0, /*tp_traverse*/ Chris@21: 0, /*tp_clear*/ Chris@21: 0, /*tp_richcompare*/ Chris@21: 0, /*tp_weaklistoffset*/ Chris@21: 0, /*tp_iter*/ Chris@21: 0, /*tp_iternext*/ Chris@21: PyPluginObject_methods, /*tp_methods*/ Chris@21: 0, /*tp_members*/ Chris@21: 0, /*tp_getset*/ Chris@21: 0, /*tp_base*/ Chris@21: 0, /*tp_dict*/ Chris@21: 0, /*tp_descr_get*/ Chris@21: 0, /*tp_descr_set*/ Chris@21: 0, /*tp_dictoffset*/ Chris@21: 0, /*tp_init*/ Chris@21: PyType_GenericAlloc, /*tp_alloc*/ Chris@21: 0, /*tp_new*/ Chris@21: PyObject_Del, /*tp_free*/ Chris@21: 0, /*tp_is_gc*/ Chris@21: }; Chris@0: Chris@18: // module methods table Chris@0: static PyMethodDef vampyhost_methods[] = { Chris@0: Chris@18: {"listPlugins", vampyhost_enumeratePlugins, METH_NOARGS, Chris@0: xx_foo_doc}, Chris@0: Chris@15: {"getPluginPath", vampyhost_getPluginPath, METH_NOARGS, Chris@15: xx_foo_doc}, Chris@15: Chris@18: {"getCategoryOf", vampyhost_getPluginCategory, METH_VARARGS, Chris@0: xx_foo_doc}, Chris@0: Chris@18: {"getLibraryFor", vampyhost_getLibraryFor, METH_VARARGS, Chris@0: xx_foo_doc}, Chris@0: Chris@18: {"getOutputsOf", 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@16: {0, 0} /* sentinel */ Chris@0: }; Chris@0: Chris@21: PyPluginObject * Chris@21: PyPluginObject::create_internal() Chris@21: { Chris@21: return (PyPluginObject *)PyType_GenericAlloc(&Plugin_Type, 0); Chris@21: } Chris@21: Chris@0: //Documentation for our new module Chris@0: PyDoc_STRVAR(module_doc, "This is a template module just for instruction."); Chris@0: Chris@25: static int Chris@25: setint(PyObject *d, const char *name, int value) Chris@25: { Chris@25: PyObject *v; Chris@25: int err; Chris@25: v = PyInt_FromLong((long)value); Chris@25: err = PyDict_SetItemString(d, name, v); Chris@25: Py_XDECREF(v); Chris@25: return err; Chris@25: } Chris@14: Chris@0: /* Initialization function for the module (*must* be called initxx) */ Chris@0: Chris@25: // module initialization (includes extern C {...} as necessary) Chris@0: PyMODINIT_FUNC Chris@0: initvampyhost(void) Chris@0: { Chris@0: PyObject *m; Chris@0: Chris@25: if (PyType_Ready(&RealTime_Type) < 0) return; Chris@25: if (PyType_Ready(&Plugin_Type) < 0) return; Chris@0: Chris@0: m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc); Chris@25: if (!m) { Chris@25: cerr << "ERROR: initvampyhost: Failed to initialise module" << endl; Chris@25: return; Chris@25: } Chris@0: Chris@14: import_array(); Chris@14: Chris@17: PyModule_AddObject(m, "RealTime", (PyObject *)&RealTime_Type); Chris@25: PyModule_AddObject(m, "Plugin", (PyObject *)&Plugin_Type); Chris@25: Chris@25: // Some enum types Chris@25: PyObject *dict = PyModule_GetDict(m); Chris@25: if (!dict) { Chris@25: cerr << "ERROR: initvampyhost: Failed to obtain module dictionary" << endl; Chris@25: return; Chris@25: } Chris@25: Chris@25: if (setint(dict, "OneSamplePerStep", Chris@25: Plugin::OutputDescriptor::OneSamplePerStep) < 0 || Chris@25: setint(dict, "FixedSampleRate", Chris@25: Plugin::OutputDescriptor::FixedSampleRate) < 0 || Chris@25: setint(dict, "VariableSampleRate", Chris@25: Plugin::OutputDescriptor::VariableSampleRate) < 0 || Chris@25: setint(dict, "TimeDomain", Chris@25: Plugin::TimeDomain) < 0 || Chris@25: setint(dict, "FrequencyDomain", Chris@25: Plugin::FrequencyDomain) < 0) { Chris@25: cerr << "ERROR: initvampyhost: Failed to add enums to module dictionary" << endl; Chris@25: return; Chris@25: } Chris@0: }