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;
+	}
+
 };