Mercurial > hg > vampy
diff PyPlugin.h @ 31:4f1894c7591b vampy2
Created Vampy2 branch
author | fazekasgy |
---|---|
date | Sun, 20 Sep 2009 17:31:20 +0000 |
parents | 7d28bed0864e |
children |
line wrap: on
line diff
--- a/PyPlugin.h Tue Aug 25 08:49:22 2009 +0000 +++ b/PyPlugin.h Sun Sep 20 17:31:20 2009 +0000 @@ -33,71 +33,26 @@ authorization. */ - /** - * This plugin abstracts appropriate Python Scripts as a Vamp plugin. - */ - #ifndef _PYTHON_WRAPPER_PLUGIN_H_ #define _PYTHON_WRAPPER_PLUGIN_H_ +#define _CLASS_METHOD_ m_class << "::" << method +#define PLUGIN_ERROR "ERROR: In Vampy plugin [" << _CLASS_METHOD_ << "]" << endl << "Cause: " +#define DEBUG_NAME "[Vampy::call] " << _CLASS_METHOD_ << " " +#define DEAFULT_RETURN "Method [" << _CLASS_METHOD_ << "] is not implemented." << endl << "Returning default value: " << rValue +#define FLAG_VALUE "Flag: " << flagName << ": " << ((rValue==0)?"False":"True") + #include "vamp-sdk/Plugin.h" #include <Python.h> +// #include <typeinfo> +// #include <stdarg.h> +#include "PyTypeInterface.h" #include "Mutex.h" -//fields in OutputDescriptor -namespace o { -enum eOutDescriptors { - not_found, - identifier, - name, - description, - unit, - hasFixedBinCount, - binCount, - binNames, - hasKnownExtents, - minValue, - maxValue, - isQuantized, - quantizeStep, - sampleType, - sampleRate, - hasDuration, - endNode - }; -} - -namespace p { -enum eParmDescriptors { - not_found, - identifier, - name, - description, - unit, - minValue, - maxValue, - defaultValue, - isQuantized, - quantizeStep - }; -} - -enum eSampleTypes { - OneSamplePerStep, - FixedSampleRate, - VariableSampleRate - }; - -enum eFeatureFields { - unknown, - hasTimestamp, - timeStamp, - hasDuration, - duration, - values, - label - }; +using std::string; +using std::cerr; +using std::endl; enum eProcessType { not_implemented, @@ -108,7 +63,7 @@ class PyPlugin : public Vamp::Plugin { public: - PyPlugin(std::string plugin,float inputSampleRate, PyObject *pyClass); + PyPlugin(std::string plugin,float inputSampleRate, PyObject *pyClass, int &instcount); virtual ~PyPlugin(); bool initialise(size_t channels, size_t stepSize, size_t blockSize); @@ -136,10 +91,12 @@ Vamp::RealTime timestamp); FeatureSet getRemainingFeatures(); - + protected: + static Mutex m_pythonInterpreterMutex; PyObject *m_pyClass; PyObject *m_pyInstance; + int &m_instcount; size_t m_stepSize; size_t m_blockSize; size_t m_channels; @@ -149,12 +106,204 @@ int m_processType; PyObject *m_pyProcess; InputDomain m_inputDomain; + PyTypeInterface m_ti; + bool m_quitOnErrorFlag; + bool m_debugFlag; + + void setProcessType(); - bool initMaps() const; - std::vector<std::string> PyList_To_StringVector (PyObject *inputList) const; - std::vector<float> PyList_As_FloatVector (PyObject *inputList) const; + PyObject* numpyProcessCall(const float *const *inputBuffers, Vamp::RealTime timestamp); + PyObject* legacyProcessCall(const float *const *inputBuffers, Vamp::RealTime timestamp); + + bool getBooleanFlag(char flagName[],bool) const; +/* + Flags may be used to control the behaviour of the interface. + Flags can be set in any Vampy plugin's __init__() function. + Their scope is limited to an instance. + Default values for all flags are False. + Python Example: + def __init__(self,inputSampleRate): + self.use_strict_type_conversion = True + self.vampy_debug_messages = True + self.use_realtime_timestamp = False + self.use_numpy_interface = False + self.quit_on_type_error = False + +*/ + + void genericMethodCall(char *method) const + { + if (m_debugFlag) cerr << DEBUG_NAME << endl; + if ( PyObject_HasAttrString(m_pyInstance,method) ) + { + PyObject *pyValue = PyObject_CallMethod(m_pyInstance, method, NULL); + if (!pyValue) { + cerr << PLUGIN_ERROR << "Failed to call method." << endl; + if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();} + } + } + } + + template<typename RET> + RET &genericMethodCall(char *method, RET &rValue) const + { + if (m_debugFlag) cerr << DEBUG_NAME << endl; + if ( PyObject_HasAttrString(m_pyInstance,method) ) + { + PyObject *pyValue = PyObject_CallMethod(m_pyInstance, method, NULL); + if (pyValue) { + m_ti.PyValue_To_rValue(pyValue,rValue); + if (!m_ti.error) { + Py_DECREF(pyValue); + return rValue; + } else { + cerr << PLUGIN_ERROR << m_ti.lastError().message << endl; + Py_CLEAR(pyValue); + if (m_quitOnErrorFlag) exit(EXIT_FAILURE); + return rValue; + } + } else { + cerr << PLUGIN_ERROR << "Failed to call method." << endl; + if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();} + return rValue; + } + } + // TODO: this fails to generalise because the << operator + // doesn't accept all types. + // if (m_debugFlag) cerr << DEAFULT_RETURN << endl; + return rValue; + } - static Mutex m_pythonInterpreterMutex; + template<typename RET,typename A1> + RET genericMethodCallArgs(char *method, A1 arg1) const + { + RET rValue = RET(); + if (m_debugFlag) cerr << DEBUG_NAME << endl; + if (!PyObject_HasAttrString(m_pyInstance,method)) { + // if (m_debugFlag) cerr << DEAFULT_RETURN << endl; + return rValue; + } + + // These functions always return valid PyObjects + PyObject *pyMethod = m_ti.PyValue_From_CValue(method); + PyObject* pyTuple = PyTuple_New(3); + if (!pyTuple) return rValue; + + PyObject *pyArg1 = m_ti.PyValue_From_CValue(arg1); + + PyObject *pyValue = PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyArg1,NULL); + if (!pyValue) + { + cerr << PLUGIN_ERROR << "Failed to call method." << endl; + if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();} + } + + Py_DECREF(pyMethod); + Py_DECREF(pyArg1); + + m_ti.PyValue_To_rValue(pyValue,rValue); + if (!m_ti.error) { + Py_DECREF(pyValue); + } else { + cerr << PLUGIN_ERROR << m_ti.lastError().message << endl; + Py_CLEAR(pyValue); + if (m_quitOnErrorFlag) exit(EXIT_FAILURE); + } + return rValue; + } + + template<typename RET,typename A1,typename A2> + RET genericMethodCallArgs(char *method, A1 arg1, A2 arg2) + { + RET rValue = RET(); + if (m_debugFlag) cerr << DEBUG_NAME << endl; + if (!PyObject_HasAttrString(m_pyInstance,method)) { + // if (m_debugFlag) cerr << DEAFULT_RETURN << endl; + return rValue; + } + + // These functions always return valid PyObjects + PyObject *pyMethod = m_ti.PyValue_From_CValue(method); + PyObject* pyTuple = PyTuple_New(3); + if (!pyTuple) return rValue; + + PyObject *pyArg1 = m_ti.PyValue_From_CValue(arg1); + PyObject *pyArg2 = m_ti.PyValue_From_CValue(arg2); + + PyObject *pyValue = PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyArg1,pyArg2,NULL); + if (!pyValue) + { + cerr << PLUGIN_ERROR << "Failed to call method." << endl; + if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();} + } + + Py_DECREF(pyMethod); + Py_DECREF(pyArg1); + Py_DECREF(pyArg2); + + m_ti.PyValue_To_rValue(pyValue,rValue); + if (!m_ti.error) { + Py_DECREF(pyValue); + } else { + cerr << PLUGIN_ERROR << m_ti.lastError().message << endl; + Py_CLEAR(pyValue); + if (m_quitOnErrorFlag) exit(EXIT_FAILURE); + } + return rValue; + } + + + template<typename RET,typename A1,typename A2,typename A3> + RET genericMethodCallArgs(char *method, A1 arg1, A2 arg2, A3 arg3) + { + RET rValue = RET(); + if (m_debugFlag) cerr << DEBUG_NAME << endl; + if (!PyObject_HasAttrString(m_pyInstance,method)) { + if (m_debugFlag) cerr << DEAFULT_RETURN << endl; + return rValue; + } + + // These functions always return valid PyObjects + PyObject *pyMethod = m_ti.PyValue_From_CValue(method); + PyObject* pyTuple = PyTuple_New(3); + if (!pyTuple) return rValue; + + PyObject *pyArg1 = m_ti.PyValue_From_CValue(arg1); + PyObject *pyArg2 = m_ti.PyValue_From_CValue(arg2); + PyObject *pyArg3 = m_ti.PyValue_From_CValue(arg3); + + // TODO: Pack it in a tuple to avoid va_list parsing! + + // callable = PyObject_GetAttr(callable, name); + // if (callable == NULL) + // return NULL; + // PyObject* args; // pyTuple of input arguments + //tmp = PyObject_Call(callable, args, NULL); + + + PyObject *pyValue = PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyArg1,pyArg2,pyArg3,NULL); + if (!pyValue) + { + cerr << PLUGIN_ERROR << "Failed to call method." << endl; + if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();} + } + + Py_DECREF(pyMethod); + Py_DECREF(pyArg1); + Py_DECREF(pyArg2); + Py_DECREF(pyArg3); + + m_ti.PyValue_To_rValue(pyValue,rValue); + if (!m_ti.error) { + Py_DECREF(pyValue); + } else { + cerr << PLUGIN_ERROR << m_ti.lastError().message << endl; + Py_CLEAR(pyValue); + if (m_quitOnErrorFlag) exit(EXIT_FAILURE); + } + return rValue; + } + };