# HG changeset patch # User Chris Cannam # Date 1417015436 0 # Node ID 13dcfe8c7ed794b2c7d303a0d58d810ce10600d1 # Parent e881d77da368fe19b2a51bbb9cb026229c4e44d3 Docs and tidying diff -r e881d77da368 -r 13dcfe8c7ed7 PyPluginObject.cpp --- a/PyPluginObject.cpp Wed Nov 26 14:27:56 2014 +0000 +++ b/PyPluginObject.cpp Wed Nov 26 15:23:56 2014 +0000 @@ -55,8 +55,6 @@ using namespace std; using namespace Vamp; -PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!! - //!!! todo: conv errors static @@ -69,7 +67,7 @@ } if (!pd || !pd->plugin) { PyErr_SetString(PyExc_AttributeError, - "Invalid or already deleted plugin handle."); + "Invalid or already deleted plugin handle."); return 0; } else { return pd; @@ -152,6 +150,15 @@ } pd->parameters = params; + + Plugin::ProgramList prl = plugin->getPrograms(); + PyObject *progs = PyList_New(prl.size()); + + for (int i = 0; i < (int)prl.size(); ++i) { + PyList_SET_ITEM(progs, i, pystr(prl[i])); + } + + pd->programs = progs; return (PyObject *)pd; } @@ -218,17 +225,17 @@ } static PyObject * -vampyhost_initialise(PyObject *self, PyObject *args) +initialise(PyObject *self, PyObject *args) { size_t channels, blockSize, stepSize; if (!PyArg_ParseTuple (args, "nnn", - (size_t) &channels, - (size_t) &stepSize, - (size_t) &blockSize)) { - PyErr_SetString(PyExc_TypeError, - "initialise() takes channel count, step size, and block size arguments"); - return 0; + (size_t) &channels, + (size_t) &stepSize, + (size_t) &blockSize)) { + PyErr_SetString(PyExc_TypeError, + "initialise() takes channel count, step size, and block size arguments"); + return 0; } PyPluginObject *pd = getPluginObject(self); @@ -239,10 +246,10 @@ pd->blockSize = blockSize; if (!pd->plugin->initialise(channels, stepSize, blockSize)) { - cerr << "Failed to initialise native plugin adapter with channels = " << channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << " and ADAPT_ALL_SAFE set" << endl; - PyErr_SetString(PyExc_TypeError, - "Plugin initialization failed"); - return 0; + cerr << "Failed to initialise native plugin adapter with channels = " << channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << endl; + PyErr_SetString(PyExc_TypeError, + "Plugin initialization failed"); + return 0; } pd->isInitialised = true; @@ -251,7 +258,7 @@ } static PyObject * -vampyhost_reset(PyObject *self, PyObject *) +reset(PyObject *self, PyObject *) { PyPluginObject *pd = getPluginObject(self); if (!pd) return 0; @@ -267,14 +274,14 @@ } static PyObject * -vampyhost_getParameter(PyObject *self, PyObject *args) +getParameter(PyObject *self, PyObject *args) { PyObject *pyParam; if (!PyArg_ParseTuple(args, "S", &pyParam)) { - PyErr_SetString(PyExc_TypeError, - "getParameter() takes parameter id (string) argument"); - return 0; } + PyErr_SetString(PyExc_TypeError, + "getParameter() takes parameter id (string) argument"); + return 0; } PyPluginObject *pd = getPluginObject(self); if (!pd) return 0; @@ -284,15 +291,15 @@ } static PyObject * -vampyhost_setParameter(PyObject *self, PyObject *args) +setParameter(PyObject *self, PyObject *args) { PyObject *pyParam; float value; if (!PyArg_ParseTuple(args, "Sf", &pyParam, &value)) { - PyErr_SetString(PyExc_TypeError, - "setParameter() takes parameter id (string), and value (float) arguments"); - return 0; } + PyErr_SetString(PyExc_TypeError, + "setParameter() takes parameter id (string), and value (float) arguments"); + return 0; } PyPluginObject *pd = getPluginObject(self); if (!pd) return 0; @@ -301,6 +308,23 @@ return Py_True; } +static PyObject * +selectProgram(PyObject *self, PyObject *args) +{ + PyObject *pyParam; + + if (!PyArg_ParseTuple(args, "S", &pyParam)) { + PyErr_SetString(PyExc_TypeError, + "selectProgram() takes parameter id (string) argument"); + return 0; } + + PyPluginObject *pd = getPluginObject(self); + if (!pd) return 0; + + pd->plugin->selectProgram(PyString_AS_STRING(pyParam)); + return Py_True; +} + static PyObject * convertFeatureSet(const Plugin::FeatureSet &fs) @@ -353,24 +377,24 @@ } static PyObject * -vampyhost_process(PyObject *self, PyObject *args) +process(PyObject *self, PyObject *args) { PyObject *pyBuffer; PyObject *pyRealTime; if (!PyArg_ParseTuple(args, "OO", - &pyBuffer, // Audio data - &pyRealTime)) { // TimeStamp - PyErr_SetString(PyExc_TypeError, - "process() takes plugin handle (object), buffer (2D array of channels * samples floats) and timestamp (RealTime) arguments"); - return 0; } + &pyBuffer, // Audio data + &pyRealTime)) { // TimeStamp + PyErr_SetString(PyExc_TypeError, + "process() takes plugin handle (object), buffer (2D array of channels * samples floats) and timestamp (RealTime) arguments"); + return 0; } if (!PyRealTime_Check(pyRealTime)) { - PyErr_SetString(PyExc_TypeError,"Valid timestamp required."); - return 0; } + PyErr_SetString(PyExc_TypeError,"Valid timestamp required."); + return 0; } if (!PyList_Check(pyBuffer)) { - PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input."); + PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input."); return 0; } @@ -378,16 +402,16 @@ if (!pd) return 0; if (!pd->isInitialised) { - PyErr_SetString(PyExc_StandardError, - "Plugin has not been initialised."); - return 0; + PyErr_SetString(PyExc_StandardError, + "Plugin has not been initialised."); + return 0; } int channels = pd->channels; if (PyList_GET_SIZE(pyBuffer) != channels) { cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << endl; - PyErr_SetString(PyExc_TypeError, "Wrong number of channels"); + PyErr_SetString(PyExc_TypeError, "Wrong number of channels"); return 0; } @@ -420,15 +444,15 @@ } static PyObject * -vampyhost_getRemainingFeatures(PyObject *self, PyObject *) +getRemainingFeatures(PyObject *self, PyObject *) { PyPluginObject *pd = getPluginObject(self); if (!pd) return 0; if (!pd->isInitialised) { - PyErr_SetString(PyExc_StandardError, - "Plugin has not been initialised."); - return 0; + PyErr_SetString(PyExc_StandardError, + "Plugin has not been initialised."); + return 0; } Plugin::FeatureSet fs = pd->plugin->getRemainingFeatures(); @@ -437,7 +461,7 @@ } static PyObject * -vampyhost_getPreferredBlockSize(PyObject *self, PyObject *) +getPreferredBlockSize(PyObject *self, PyObject *) { PyPluginObject *pd = getPluginObject(self); if (!pd) return 0; @@ -445,7 +469,7 @@ } static PyObject * -vampyhost_getPreferredStepSize(PyObject *self, PyObject *) +getPreferredStepSize(PyObject *self, PyObject *) { PyPluginObject *pd = getPluginObject(self); if (!pd) return 0; @@ -453,7 +477,7 @@ } static PyObject * -vampyhost_getMinChannelCount(PyObject *self, PyObject *) +getMinChannelCount(PyObject *self, PyObject *) { PyPluginObject *pd = getPluginObject(self); if (!pd) return 0; @@ -461,7 +485,7 @@ } static PyObject * -vampyhost_getMaxChannelCount(PyObject *self, PyObject *) +getMaxChannelCount(PyObject *self, PyObject *) { PyPluginObject *pd = getPluginObject(self); if (!pd) return 0; @@ -469,7 +493,7 @@ } static PyObject * -vampyhost_unload(PyObject *self, PyObject *) +unload(PyObject *self, PyObject *) { PyPluginObject *pd = getPluginObject(self); if (!pd) return 0; @@ -484,13 +508,16 @@ static PyMemberDef PyPluginObject_members[] = { {(char *)"info", T_OBJECT, offsetof(PyPluginObject, info), READONLY, - xx_foo_doc}, + (char *)"info -> A read-only dictionary of plugin metadata."}, {(char *)"inputDomain", T_INT, offsetof(PyPluginObject, inputDomain), READONLY, - xx_foo_doc}, + (char *)"inputDomain -> The format of input audio required by the plugin, either vampyhost.TimeDomain or vampyhost.FrequencyDomain."}, {(char *)"parameters", T_OBJECT, offsetof(PyPluginObject, parameters), READONLY, - xx_foo_doc}, + (char *)"parameters -> A list of metadata dictionaries describing the plugin's configurable parameters."}, + + {(char *)"programs", T_OBJECT, offsetof(PyPluginObject, programs), READONLY, + (char *)"programs -> A list of the programs available for this plugin, if any."}, {0, 0} }; @@ -498,40 +525,43 @@ static PyMethodDef PyPluginObject_methods[] = { {"getOutputs", getOutputs, METH_NOARGS, - xx_foo_doc}, + "getOutputs() -> Obtain the output descriptors for all of the plugin's outputs."}, - {"getParameterValue", vampyhost_getParameter, METH_VARARGS, - xx_foo_doc}, //!!! fix all these! + {"getParameterValue", getParameter, METH_VARARGS, + "getParameterValue(identifier) -> Return the value of the parameter with the given identifier."}, - {"setParameterValue", vampyhost_setParameter, METH_VARARGS, - xx_foo_doc}, + {"setParameterValue", setParameter, METH_VARARGS, + "setParameterValue(identifier, value) -> Set the parameter with the given identifier to the given value."}, - {"getPreferredBlockSize", vampyhost_getPreferredBlockSize, METH_VARARGS, - xx_foo_doc}, //!!! fix all these! + {"selectProgram", selectProgram, METH_VARARGS, + "selectProgram(name) -> Select the processing program with the given name."}, + + {"getPreferredBlockSize", getPreferredBlockSize, METH_VARARGS, + "getPreferredBlockSize() -> Return the plugin's preferred processing block size, or 0 if the plugin accepts any block size."}, - {"getPreferredStepSize", vampyhost_getPreferredStepSize, METH_VARARGS, - xx_foo_doc}, + {"getPreferredStepSize", getPreferredStepSize, METH_VARARGS, + "getPreferredStepSize() -> Return the plugin's preferred processing step size, or 0 if the plugin allows the host to select. If this is 0, the host should normally choose the same step as block size for time-domain plugins, or half the block size for frequency-domain plugins."}, - {"getMinChannelCount", vampyhost_getMinChannelCount, METH_VARARGS, - xx_foo_doc}, //!!! fix all these! + {"getMinChannelCount", getMinChannelCount, METH_VARARGS, + "getMinChannelCount() -> Return the minimum number of channels of audio data the plugin accepts as input."}, - {"getMaxChannelCount", vampyhost_getMaxChannelCount, METH_VARARGS, - xx_foo_doc}, + {"getMaxChannelCount", getMaxChannelCount, METH_VARARGS, + "getMaxChannelCount() -> Return the maximum number of channels of audio data the plugin accepts as input."}, - {"initialise", vampyhost_initialise, METH_VARARGS, - xx_foo_doc}, + {"initialise", initialise, METH_VARARGS, + "initialise(channels, stepSize, blockSize) -> Initialise the plugin for the given number of channels and processing frame sizes. This must be called before process() can be used."}, - {"reset", vampyhost_reset, METH_NOARGS, - xx_foo_doc}, + {"reset", reset, METH_NOARGS, + "reset() -> Reset the plugin after processing, to prepare for another processing run with the same parameters."}, - {"process", vampyhost_process, METH_VARARGS, - xx_foo_doc}, + {"process", process, METH_VARARGS, + "process(block, timestamp) -> Provide one processing frame to the plugin, with its timestamp, and obtain any features that were extracted immediately from this frame."}, - {"getRemainingFeatures", vampyhost_getRemainingFeatures, METH_NOARGS, - xx_foo_doc}, + {"getRemainingFeatures", getRemainingFeatures, METH_NOARGS, + "getRemainingFeatures() -> Obtain any features extracted at the end of processing."}, - {"unload", vampyhost_unload, METH_NOARGS, - xx_foo_doc}, + {"unload", unload, METH_NOARGS, + "unload() -> Dispose of the plugin. You cannot use the plugin object again after calling this. Note that unloading also happens automatically when the plugin object's reference count reaches zero; this function is only necessary if you wish to ensure the native part of the plugin is disposed of before then."}, {0, 0} }; @@ -540,45 +570,45 @@ PyTypeObject Plugin_Type = { PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "vampyhost.Plugin", /*tp_name*/ - sizeof(PyPluginObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ + 0, /*ob_size*/ + "vampyhost.Plugin", /*tp_name*/ + sizeof(PyPluginObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ (destructor)PyPluginObject_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - PyObject_GenericGetAttr, /*tp_getattro*/ - PyObject_GenericSetAttr, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "Plugin Object", /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - PyPluginObject_methods, /*tp_methods*/ - PyPluginObject_members, /*tp_members*/ - 0, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ - PyType_GenericAlloc, /*tp_alloc*/ - 0, /*tp_new*/ - PyObject_Del, /*tp_free*/ - 0, /*tp_is_gc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + PyObject_GenericGetAttr, /*tp_getattro*/ + PyObject_GenericSetAttr, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + "Vamp plugin object.", /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + PyPluginObject_methods, /*tp_methods*/ + PyPluginObject_members, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + 0, /*tp_init*/ + PyType_GenericAlloc, /*tp_alloc*/ + 0, /*tp_new*/ + PyObject_Del, /*tp_free*/ + 0, /*tp_is_gc*/ }; diff -r e881d77da368 -r 13dcfe8c7ed7 PyPluginObject.h --- a/PyPluginObject.h Wed Nov 26 14:27:56 2014 +0000 +++ b/PyPluginObject.h Wed Nov 26 15:23:56 2014 +0000 @@ -54,6 +54,7 @@ PyObject *info; int inputDomain; PyObject *parameters; + PyObject *programs; }; PyAPI_DATA(PyTypeObject) Plugin_Type; diff -r e881d77da368 -r 13dcfe8c7ed7 PyRealTime.cpp --- a/PyRealTime.cpp Wed Nov 26 14:27:56 2014 +0000 +++ b/PyRealTime.cpp Wed Nov 26 15:23:56 2014 +0000 @@ -52,51 +52,51 @@ const char *fmt = NULL; if ( - /// new RealTime from ('format',float) e.g. ('seconds',2.34123) - !PyArg_ParseTuple(args, "|sd:RealTime.new ", - (const char *) &fmt, - (double *) &unary) && + /// new RealTime from ('format',float) e.g. ('seconds',2.34123) + !PyArg_ParseTuple(args, "|sd:RealTime.new ", + (const char *) &fmt, + (double *) &unary) && - /// new RealTime from (sec{int},nsec{int}) e.g. (2,34) - !PyArg_ParseTuple(args, "|II:RealTime.new ", - (unsigned int*) &sec, - (unsigned int*) &nsec) - - ) { - PyErr_SetString(PyExc_TypeError, - "RealTime initialised with wrong arguments."); - return NULL; + /// new RealTime from (sec{int},nsec{int}) e.g. (2,34) + !PyArg_ParseTuple(args, "|II:RealTime.new ", + (unsigned int*) &sec, + (unsigned int*) &nsec) + + ) { + PyErr_SetString(PyExc_TypeError, + "RealTime initialised with wrong arguments."); + return NULL; } // PyErr_Clear(); // RealTimeObject *self = PyObject_New(RealTimeObject, &RealTime_Type); RealTimeObject *self = (RealTimeObject*)type->tp_alloc(type, 0); - + if (self == NULL) return NULL; self->rt = NULL; if (sec == 0 && nsec == 0 && fmt == 0) - self->rt = new RealTime(); + self->rt = new RealTime(); else if (fmt == 0) - self->rt = new RealTime(sec,nsec); + self->rt = new RealTime(sec,nsec); else { /// new RealTime from seconds or milliseconds: i.e. >>>RealTime('seconds',12.3) - if (!string(fmt).compare("float") || - !string(fmt).compare("seconds")) - self->rt = new RealTime( - RealTime::fromSeconds((double) unary)); + if (!string(fmt).compare("float") || + !string(fmt).compare("seconds")) + self->rt = new RealTime( + RealTime::fromSeconds((double) unary)); - if (!string(fmt).compare("milliseconds")) { - self->rt = new RealTime( - RealTime::fromSeconds((double) unary / 1000.0)); } + if (!string(fmt).compare("milliseconds")) { + self->rt = new RealTime( + RealTime::fromSeconds((double) unary / 1000.0)); } } if (!self->rt) { - PyErr_SetString(PyExc_TypeError, - "RealTime initialised with wrong arguments."); - return NULL; + PyErr_SetString(PyExc_TypeError, + "RealTime initialised with wrong arguments."); + return NULL; } return (PyObject *) self; @@ -106,7 +106,7 @@ static void RealTimeObject_dealloc(RealTimeObject *self) { - if (self->rt) delete self->rt; //delete the C object + if (self->rt) delete self->rt; //delete the C object PyObject_Del(self); //delete the Python object (original) /// this requires PyType_Ready() which fills ob_type // self->ob_type->tp_free((PyObject*)self); @@ -134,17 +134,17 @@ RealTime_toFrame(PyObject *self, PyObject *args) { unsigned int samplerate; - + if ( !PyArg_ParseTuple(args, "I:realtime.toFrame object ", - (unsigned int *) &samplerate )) { - PyErr_SetString(PyExc_ValueError,"Integer Sample Rate Required."); - return NULL; + (unsigned int *) &samplerate )) { + PyErr_SetString(PyExc_ValueError,"Integer Sample Rate Required."); + return NULL; } - + return Py_BuildValue("k", - RealTime::realTime2Frame( - *(const RealTime*) ((RealTimeObject*)self)->rt, - (unsigned int) samplerate)); + RealTime::realTime2Frame( + *(const RealTime*) ((RealTimeObject*)self)->rt, + (unsigned int) samplerate)); } /* Conversion of realtime to a double precision floating point value */ @@ -153,27 +153,27 @@ RealTime_float(PyObject *s) { double drt = ((double) ((RealTimeObject*)s)->rt->sec + - (double)((double) ((RealTimeObject*)s)->rt->nsec)/1000000000); - return PyFloat_FromDouble(drt); + (double)((double) ((RealTimeObject*)s)->rt->nsec)/1000000000); + return PyFloat_FromDouble(drt); } /* Type object's (RealTime) methods table */ static PyMethodDef RealTime_methods[] = { - {"values", (PyCFunction)RealTime_values, METH_NOARGS, + {"values", (PyCFunction)RealTime_values, METH_NOARGS, PyDoc_STR("values() -> Tuple of sec,nsec representation.")}, - {"toString", (PyCFunction)RealTime_toString, METH_NOARGS, + {"toString", (PyCFunction)RealTime_toString, METH_NOARGS, PyDoc_STR("toString() -> Return a user-readable string to the nearest millisecond in a form like HH:MM:SS.mmm")}, - {"toFrame", (PyCFunction)RealTime_toFrame, METH_VARARGS, + {"toFrame", (PyCFunction)RealTime_toFrame, METH_VARARGS, PyDoc_STR("toFrame(samplerate) -> Sample count for given sample rate.")}, - {"toFloat", (PyCFunction)RealTime_float, METH_NOARGS, + {"toFloat", (PyCFunction)RealTime_float, METH_NOARGS, PyDoc_STR("toFloat() -> Floating point representation.")}, - - {NULL, NULL} /* sentinel */ + + {NULL, NULL} /* sentinel */ }; @@ -187,13 +187,13 @@ { if ( !string(name).compare("sec")) { - self->rt->sec= (int) PyInt_AS_LONG(value); - return 0; + self->rt->sec= (int) PyInt_AS_LONG(value); + return 0; } if ( !string(name).compare("nsec")) { - self->rt->nsec= (int) PyInt_AS_LONG(value); - return 0; + self->rt->nsec= (int) PyInt_AS_LONG(value); + return 0; } return -1; @@ -204,17 +204,17 @@ { if ( !string(name).compare("sec") ) { - return PyInt_FromSsize_t( - (Py_ssize_t) self->rt->sec); + return PyInt_FromSsize_t( + (Py_ssize_t) self->rt->sec); } if ( !string(name).compare("nsec") ) { - return PyInt_FromSsize_t( - (Py_ssize_t) self->rt->nsec); + return PyInt_FromSsize_t( + (Py_ssize_t) self->rt->nsec); } return Py_FindMethod(RealTime_methods, - (PyObject *)self, name); + (PyObject *)self, name); } /* String representation called by e.g. str(realtime), print realtime*/ @@ -222,7 +222,7 @@ RealTime_repr(PyObject *self) { return Py_BuildValue("s", - ((RealTimeObject*)self)->rt->toString().c_str()); + ((RealTimeObject*)self)->rt->toString().c_str()); } @@ -233,11 +233,11 @@ RealTime_add(PyObject *s, PyObject *w) { RealTimeObject *result = - PyObject_New(RealTimeObject, &RealTime_Type); + PyObject_New(RealTimeObject, &RealTime_Type); if (result == NULL) return NULL; result->rt = new RealTime( - *((RealTimeObject*)s)->rt + *((RealTimeObject*)w)->rt); + *((RealTimeObject*)s)->rt + *((RealTimeObject*)w)->rt); return (PyObject*)result; } @@ -245,39 +245,39 @@ RealTime_subtract(PyObject *s, PyObject *w) { RealTimeObject *result = - PyObject_New(RealTimeObject, &RealTime_Type); + PyObject_New(RealTimeObject, &RealTime_Type); if (result == NULL) return NULL; result->rt = new RealTime( - *((RealTimeObject*)s)->rt - *((RealTimeObject*)w)->rt); + *((RealTimeObject*)s)->rt - *((RealTimeObject*)w)->rt); return (PyObject*)result; } static PyNumberMethods realtime_as_number = { - RealTime_add, /*nb_add*/ - RealTime_subtract, /*nb_subtract*/ - 0, /*nb_multiply*/ - 0, /*nb_divide*/ - 0, /*nb_remainder*/ - 0, /*nb_divmod*/ - 0, /*nb_power*/ - 0, /*nb_neg*/ - 0, /*nb_pos*/ - 0, /*(unaryfunc)array_abs,*/ - 0, /*nb_nonzero*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ + RealTime_add, /*nb_add*/ + RealTime_subtract, /*nb_subtract*/ + 0, /*nb_multiply*/ + 0, /*nb_divide*/ + 0, /*nb_remainder*/ + 0, /*nb_divmod*/ + 0, /*nb_power*/ + 0, /*nb_neg*/ + 0, /*nb_pos*/ + 0, /*(unaryfunc)array_abs,*/ + 0, /*nb_nonzero*/ + 0, /*nb_invert*/ + 0, /*nb_lshift*/ + 0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ 0, /*nb_coerce*/ - 0, /*nb_int*/ - 0, /*nb_long*/ + 0, /*nb_int*/ + 0, /*nb_long*/ (unaryfunc)RealTime_float,/*nb_float*/ - 0, /*nb_oct*/ - 0, /*nb_hex*/ + 0, /*nb_oct*/ + 0, /*nb_hex*/ }; /* REAL-TIME TYPE OBJECT */ @@ -289,28 +289,28 @@ PyTypeObject RealTime_Type = { PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "vampy.RealTime", /*tp_name*/ - sizeof(RealTimeObject), /*tp_basicsize*/ - 0,//sizeof(RealTime), /*tp_itemsize*/ - /* methods */ + 0, /*ob_size*/ + "vampy.RealTime", /*tp_name*/ + sizeof(RealTimeObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ (destructor)RealTimeObject_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ + 0, /*tp_print*/ (getattrfunc)RealTime_getattr, /*tp_getattr*/ (setattrfunc)RealTime_setattr, /*tp_setattr*/ - 0, /*tp_compare*/ - RealTime_repr, /*tp_repr*/ - &realtime_as_number, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0,//(ternaryfunc)RealTime_new, /*tp_call*/ + 0, /*tp_compare*/ + RealTime_repr, /*tp_repr*/ + &realtime_as_number, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "RealTime Object", /*tp_doc*/ + "RealTime object, used for Vamp plugin timestamps.", /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ @@ -328,7 +328,7 @@ 0, /*tp_init*/ RealTime_alloc, /*tp_alloc*/ RealTime_new, /*tp_new*/ - RealTime_free, /*tp_free*/ + RealTime_free, /*tp_free*/ 0, /*tp_is_gc*/ }; @@ -341,7 +341,7 @@ PyRealTime_FromRealTime(const Vamp::RealTime& rt) { RealTimeObject *self = - PyObject_New(RealTimeObject, &RealTime_Type); + PyObject_New(RealTimeObject, &RealTime_Type); if (self == NULL) return NULL; self->rt = new RealTime(rt); @@ -355,9 +355,9 @@ RealTimeObject *s = (RealTimeObject*) self; if (!PyRealTime_Check(s)) { - PyErr_SetString(PyExc_TypeError, "RealTime Object Expected."); - cerr << "in call PyRealTime_AsPointer(): RealTime Object Expected. " << endl; - return NULL; } + PyErr_SetString(PyExc_TypeError, "RealTime Object Expected."); + cerr << "in call PyRealTime_AsPointer(): RealTime Object Expected. " << endl; + return NULL; } return s->rt; }; diff -r e881d77da368 -r 13dcfe8c7ed7 test_metadata.py --- a/test_metadata.py Wed Nov 26 14:27:56 2014 +0000 +++ b/test_metadata.py Wed Nov 26 15:23:56 2014 +0000 @@ -17,7 +17,14 @@ def test_getlibrary(): lib = vh.getLibraryFor(testPluginKey) - assert lib != "" + assert lib.find("vamp-test-plugin") >= 0 + try: + lib = vh.getLibraryFor("not a well-formatted plugin key") + assert False + except TypeError: + pass + lib = vh.getLibraryFor("nonexistent-library:nonexistent-plugin") + assert lib == "" def test_getoutputlist(): outputs = vh.getOutputsOf(testPluginKey) diff -r e881d77da368 -r 13dcfe8c7ed7 test_plugin_metadata.py --- a/test_plugin_metadata.py Wed Nov 26 14:27:56 2014 +0000 +++ b/test_plugin_metadata.py Wed Nov 26 15:23:56 2014 +0000 @@ -7,14 +7,14 @@ def test_inputdomain(): plug = vh.loadPlugin(testPluginKey, rate) - assert(plug.inputDomain == vh.TimeDomain) + assert plug.inputDomain == vh.TimeDomain def test_info(): plug = vh.loadPlugin(testPluginKey, rate) - assert(plug.info["identifier"] == "vamp-test-plugin") + assert plug.info["identifier"] == "vamp-test-plugin" def test_parameterdescriptors(): plug = vh.loadPlugin(testPluginKey, rate) - assert(plug.parameters[0]["identifier"] == "produce_output") + assert plug.parameters[0]["identifier"] == "produce_output" diff -r e881d77da368 -r 13dcfe8c7ed7 vampyhost.cpp --- a/vampyhost.cpp Wed Nov 26 14:27:56 2014 +0000 +++ b/vampyhost.cpp Wed Nov 26 15:23:56 2014 +0000 @@ -35,7 +35,7 @@ authorization. */ -//include for python extension module: must be first +// include for python extension module: must be first #include // define a unique API pointer @@ -63,12 +63,10 @@ using namespace Vamp; using namespace Vamp::HostExt; -PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!! - //!!! todo: conv errors static PyObject * -vampyhost_enumeratePlugins(PyObject *self, PyObject *) +enumeratePlugins(PyObject *self, PyObject *) { PluginLoader *loader = PluginLoader::getInstance(); vector plugins = loader->listPlugins(); @@ -77,7 +75,7 @@ } static PyObject * -vampyhost_getPluginPath(PyObject *self, PyObject *) +getPluginPath(PyObject *self, PyObject *) { vector path = PluginHostAdapter::getPluginPath(); VectorConversion conv; @@ -92,23 +90,23 @@ // check pluginKey validity string::size_type ki = pluginKey.find(':'); if (ki == string::npos) { - PyErr_SetString(PyExc_TypeError, - "Plugin key must be of the form library:identifier"); - return ""; + PyErr_SetString(PyExc_TypeError, + "Plugin key must be of the form library:identifier"); + return ""; } return pluginKey; } static PyObject * -vampyhost_getLibraryFor(PyObject *self, PyObject *args) +getLibraryFor(PyObject *self, PyObject *args) { PyObject *pyPluginKey; if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) { - PyErr_SetString(PyExc_TypeError, - "getLibraryPathForPlugin() takes plugin key (string) argument"); - return 0; } + PyErr_SetString(PyExc_TypeError, + "getLibraryPathForPlugin() takes plugin key (string) argument"); + return 0; } string pluginKey = toPluginKey(pyPluginKey); if (pluginKey == "") return 0; @@ -120,35 +118,35 @@ } static PyObject * -vampyhost_getPluginCategory(PyObject *self, PyObject *args) +getPluginCategory(PyObject *self, PyObject *args) { PyObject *pyPluginKey; if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) { - PyErr_SetString(PyExc_TypeError, - "getPluginCategory() takes plugin key (string) argument"); - return 0; } + PyErr_SetString(PyExc_TypeError, + "getPluginCategory() takes plugin key (string) argument"); + return 0; } string pluginKey = toPluginKey(pyPluginKey); if (pluginKey == "") return 0; PluginLoader *loader = PluginLoader::getInstance(); PluginLoader::PluginCategoryHierarchy - category = loader->getPluginCategory(pluginKey); + category = loader->getPluginCategory(pluginKey); VectorConversion conv; return conv.PyValue_From_StringVector(category); } static PyObject * -vampyhost_getOutputList(PyObject *self, PyObject *args) +getOutputList(PyObject *self, PyObject *args) { PyObject *pyPluginKey; if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) { - PyErr_SetString(PyExc_TypeError, - "getOutputList() takes plugin key (string) argument"); - return 0; } + PyErr_SetString(PyExc_TypeError, + "getOutputList() takes plugin key (string) argument"); + return 0; } Plugin::OutputList outputs; @@ -170,26 +168,26 @@ PyObject *pyList = PyList_New(outputs.size()); for (size_t i = 0; i < outputs.size(); ++i) { - PyObject *pyOutputId = - PyString_FromString(outputs[i].identifier.c_str()); - PyList_SET_ITEM(pyList, i, pyOutputId); + PyObject *pyOutputId = + PyString_FromString(outputs[i].identifier.c_str()); + PyList_SET_ITEM(pyList, i, pyOutputId); } return pyList; } static PyObject * -vampyhost_loadPlugin(PyObject *self, PyObject *args) +loadPlugin(PyObject *self, PyObject *args) { PyObject *pyPluginKey; float inputSampleRate; if (!PyArg_ParseTuple(args, "Sf", - &pyPluginKey, - &inputSampleRate)) { - PyErr_SetString(PyExc_TypeError, - "loadPlugin() takes plugin key (string) and sample rate (float) arguments"); - return 0; } + &pyPluginKey, + &inputSampleRate)) { + PyErr_SetString(PyExc_TypeError, + "loadPlugin() takes plugin key (string) and sample rate (float) arguments"); + return 0; } string pluginKey = toPluginKey(pyPluginKey); if (pluginKey == "") return 0; @@ -199,9 +197,9 @@ Plugin *plugin = loader->loadPlugin(pluginKey, inputSampleRate, PluginLoader::ADAPT_ALL_SAFE); if (!plugin) { - string pyerr("Failed to load plugin: "); pyerr += pluginKey; - PyErr_SetString(PyExc_TypeError,pyerr.c_str()); - return 0; + string pyerr("Failed to load plugin: "); pyerr += pluginKey; + PyErr_SetString(PyExc_TypeError,pyerr.c_str()); + return 0; } return PyPluginObject_From_Plugin(plugin); @@ -210,29 +208,28 @@ // module methods table static PyMethodDef vampyhost_methods[] = { - {"listPlugins", vampyhost_enumeratePlugins, METH_NOARGS, - xx_foo_doc}, + {"listPlugins", enumeratePlugins, METH_NOARGS, + "listPlugins() -> Return a list of the plugin keys of all installed Vamp plugins." }, - {"getPluginPath", vampyhost_getPluginPath, METH_NOARGS, - xx_foo_doc}, + {"getPluginPath", getPluginPath, METH_NOARGS, + "getPluginPath() -> Return a list of directories which will be searched for Vamp plugins. This may be changed by setting the VAMP_PATH environment variable."}, - {"getCategoryOf", vampyhost_getPluginCategory, METH_VARARGS, - xx_foo_doc}, + {"getCategoryOf", getPluginCategory, METH_VARARGS, + "getCategoryOf(pluginKey) -> Return the category of a Vamp plugin given its key, if known. The category is expressed as a list of nested types from least to most specific."}, - {"getLibraryFor", vampyhost_getLibraryFor, METH_VARARGS, - xx_foo_doc}, + {"getLibraryFor", getLibraryFor, METH_VARARGS, + "getLibraryFor(pluginKey) -> Return the file path of the Vamp plugin library in which the given plugin key is found, or an empty string if the plugin is not installed."}, - {"getOutputsOf", vampyhost_getOutputList, METH_VARARGS, - xx_foo_doc}, + {"getOutputsOf", getOutputList, METH_VARARGS, + "getOutputsOf(pluginKey) -> Return a list of the output identifiers of the plugin with the given key, if installed."}, - {"loadPlugin", vampyhost_loadPlugin, METH_VARARGS, - xx_foo_doc}, + {"loadPlugin", loadPlugin, METH_VARARGS, + "loadPlugin(pluginKey, samplerate) -> Load the plugin that has the given key, if installed, and return the plugin object."}, - {0, 0} /* sentinel */ + {0, 0} /* sentinel */ }; -//Documentation for our new module -PyDoc_STRVAR(module_doc, "This is a template module just for instruction."); +PyDoc_STRVAR(module_doc, "Load and run Vamp audio analysis plugins."); static int setint(PyObject *d, const char *name, int value)