comparison PyPlugin.h @ 31:4f1894c7591b vampy2

Created Vampy2 branch
author fazekasgy
date Sun, 20 Sep 2009 17:31:20 +0000
parents 7d28bed0864e
children
comparison
equal deleted inserted replaced
28:5139bf30f208 31:4f1894c7591b
31 shall not be used in advertising or otherwise to promote the sale, 31 shall not be used in advertising or otherwise to promote the sale,
32 use or other dealings in this Software without prior written 32 use or other dealings in this Software without prior written
33 authorization. 33 authorization.
34 */ 34 */
35 35
36 /**
37 * This plugin abstracts appropriate Python Scripts as a Vamp plugin.
38 */
39
40 #ifndef _PYTHON_WRAPPER_PLUGIN_H_ 36 #ifndef _PYTHON_WRAPPER_PLUGIN_H_
41 #define _PYTHON_WRAPPER_PLUGIN_H_ 37 #define _PYTHON_WRAPPER_PLUGIN_H_
42 38
39 #define _CLASS_METHOD_ m_class << "::" << method
40 #define PLUGIN_ERROR "ERROR: In Vampy plugin [" << _CLASS_METHOD_ << "]" << endl << "Cause: "
41 #define DEBUG_NAME "[Vampy::call] " << _CLASS_METHOD_ << " "
42 #define DEAFULT_RETURN "Method [" << _CLASS_METHOD_ << "] is not implemented." << endl << "Returning default value: " << rValue
43 #define FLAG_VALUE "Flag: " << flagName << ": " << ((rValue==0)?"False":"True")
44
43 #include "vamp-sdk/Plugin.h" 45 #include "vamp-sdk/Plugin.h"
44 #include <Python.h> 46 #include <Python.h>
47 // #include <typeinfo>
48 // #include <stdarg.h>
49 #include "PyTypeInterface.h"
45 50
46 #include "Mutex.h" 51 #include "Mutex.h"
47 52
48 //fields in OutputDescriptor 53 using std::string;
49 namespace o { 54 using std::cerr;
50 enum eOutDescriptors { 55 using std::endl;
51 not_found,
52 identifier,
53 name,
54 description,
55 unit,
56 hasFixedBinCount,
57 binCount,
58 binNames,
59 hasKnownExtents,
60 minValue,
61 maxValue,
62 isQuantized,
63 quantizeStep,
64 sampleType,
65 sampleRate,
66 hasDuration,
67 endNode
68 };
69 }
70
71 namespace p {
72 enum eParmDescriptors {
73 not_found,
74 identifier,
75 name,
76 description,
77 unit,
78 minValue,
79 maxValue,
80 defaultValue,
81 isQuantized,
82 quantizeStep
83 };
84 }
85
86 enum eSampleTypes {
87 OneSamplePerStep,
88 FixedSampleRate,
89 VariableSampleRate
90 };
91
92 enum eFeatureFields {
93 unknown,
94 hasTimestamp,
95 timeStamp,
96 hasDuration,
97 duration,
98 values,
99 label
100 };
101 56
102 enum eProcessType { 57 enum eProcessType {
103 not_implemented, 58 not_implemented,
104 legacyProcess, 59 legacyProcess,
105 numpyProcess 60 numpyProcess
106 }; 61 };
107 62
108 class PyPlugin : public Vamp::Plugin 63 class PyPlugin : public Vamp::Plugin
109 { 64 {
110 public: 65 public:
111 PyPlugin(std::string plugin,float inputSampleRate, PyObject *pyClass); 66 PyPlugin(std::string plugin,float inputSampleRate, PyObject *pyClass, int &instcount);
112 virtual ~PyPlugin(); 67 virtual ~PyPlugin();
113 68
114 bool initialise(size_t channels, size_t stepSize, size_t blockSize); 69 bool initialise(size_t channels, size_t stepSize, size_t blockSize);
115 void reset(); 70 void reset();
116 71
134 89
135 FeatureSet process(const float *const *inputBuffers, 90 FeatureSet process(const float *const *inputBuffers,
136 Vamp::RealTime timestamp); 91 Vamp::RealTime timestamp);
137 92
138 FeatureSet getRemainingFeatures(); 93 FeatureSet getRemainingFeatures();
139 94
140 protected: 95 protected:
96 static Mutex m_pythonInterpreterMutex;
141 PyObject *m_pyClass; 97 PyObject *m_pyClass;
142 PyObject *m_pyInstance; 98 PyObject *m_pyInstance;
99 int &m_instcount;
143 size_t m_stepSize; 100 size_t m_stepSize;
144 size_t m_blockSize; 101 size_t m_blockSize;
145 size_t m_channels; 102 size_t m_channels;
146 std::string m_plugin; 103 std::string m_plugin;
147 std::string m_class; 104 std::string m_class;
148 std::string m_path; 105 std::string m_path;
149 int m_processType; 106 int m_processType;
150 PyObject *m_pyProcess; 107 PyObject *m_pyProcess;
151 InputDomain m_inputDomain; 108 InputDomain m_inputDomain;
152 109 PyTypeInterface m_ti;
153 bool initMaps() const; 110 bool m_quitOnErrorFlag;
154 std::vector<std::string> PyList_To_StringVector (PyObject *inputList) const; 111 bool m_debugFlag;
155 std::vector<float> PyList_As_FloatVector (PyObject *inputList) const; 112
156 113 void setProcessType();
157 static Mutex m_pythonInterpreterMutex; 114
115 PyObject* numpyProcessCall(const float *const *inputBuffers, Vamp::RealTime timestamp);
116 PyObject* legacyProcessCall(const float *const *inputBuffers, Vamp::RealTime timestamp);
117
118 bool getBooleanFlag(char flagName[],bool) const;
119 /*
120 Flags may be used to control the behaviour of the interface.
121 Flags can be set in any Vampy plugin's __init__() function.
122 Their scope is limited to an instance.
123 Default values for all flags are False.
124 Python Example:
125 def __init__(self,inputSampleRate):
126 self.use_strict_type_conversion = True
127 self.vampy_debug_messages = True
128 self.use_realtime_timestamp = False
129 self.use_numpy_interface = False
130 self.quit_on_type_error = False
131
132 */
133
134 void genericMethodCall(char *method) const
135 {
136 if (m_debugFlag) cerr << DEBUG_NAME << endl;
137 if ( PyObject_HasAttrString(m_pyInstance,method) )
138 {
139 PyObject *pyValue = PyObject_CallMethod(m_pyInstance, method, NULL);
140 if (!pyValue) {
141 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
142 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
143 }
144 }
145 }
146
147 template<typename RET>
148 RET &genericMethodCall(char *method, RET &rValue) const
149 {
150 if (m_debugFlag) cerr << DEBUG_NAME << endl;
151 if ( PyObject_HasAttrString(m_pyInstance,method) )
152 {
153 PyObject *pyValue = PyObject_CallMethod(m_pyInstance, method, NULL);
154 if (pyValue) {
155 m_ti.PyValue_To_rValue(pyValue,rValue);
156 if (!m_ti.error) {
157 Py_DECREF(pyValue);
158 return rValue;
159 } else {
160 cerr << PLUGIN_ERROR << m_ti.lastError().message << endl;
161 Py_CLEAR(pyValue);
162 if (m_quitOnErrorFlag) exit(EXIT_FAILURE);
163 return rValue;
164 }
165 } else {
166 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
167 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
168 return rValue;
169 }
170 }
171 // TODO: this fails to generalise because the << operator
172 // doesn't accept all types.
173 // if (m_debugFlag) cerr << DEAFULT_RETURN << endl;
174 return rValue;
175 }
176
177 template<typename RET,typename A1>
178 RET genericMethodCallArgs(char *method, A1 arg1) const
179 {
180 RET rValue = RET();
181 if (m_debugFlag) cerr << DEBUG_NAME << endl;
182 if (!PyObject_HasAttrString(m_pyInstance,method)) {
183 // if (m_debugFlag) cerr << DEAFULT_RETURN << endl;
184 return rValue;
185 }
186
187 // These functions always return valid PyObjects
188 PyObject *pyMethod = m_ti.PyValue_From_CValue(method);
189 PyObject* pyTuple = PyTuple_New(3);
190 if (!pyTuple) return rValue;
191
192 PyObject *pyArg1 = m_ti.PyValue_From_CValue(arg1);
193
194 PyObject *pyValue = PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyArg1,NULL);
195 if (!pyValue)
196 {
197 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
198 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
199 }
200
201 Py_DECREF(pyMethod);
202 Py_DECREF(pyArg1);
203
204 m_ti.PyValue_To_rValue(pyValue,rValue);
205 if (!m_ti.error) {
206 Py_DECREF(pyValue);
207 } else {
208 cerr << PLUGIN_ERROR << m_ti.lastError().message << endl;
209 Py_CLEAR(pyValue);
210 if (m_quitOnErrorFlag) exit(EXIT_FAILURE);
211 }
212 return rValue;
213 }
214
215 template<typename RET,typename A1,typename A2>
216 RET genericMethodCallArgs(char *method, A1 arg1, A2 arg2)
217 {
218 RET rValue = RET();
219 if (m_debugFlag) cerr << DEBUG_NAME << endl;
220 if (!PyObject_HasAttrString(m_pyInstance,method)) {
221 // if (m_debugFlag) cerr << DEAFULT_RETURN << endl;
222 return rValue;
223 }
224
225 // These functions always return valid PyObjects
226 PyObject *pyMethod = m_ti.PyValue_From_CValue(method);
227 PyObject* pyTuple = PyTuple_New(3);
228 if (!pyTuple) return rValue;
229
230 PyObject *pyArg1 = m_ti.PyValue_From_CValue(arg1);
231 PyObject *pyArg2 = m_ti.PyValue_From_CValue(arg2);
232
233 PyObject *pyValue = PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyArg1,pyArg2,NULL);
234 if (!pyValue)
235 {
236 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
237 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
238 }
239
240 Py_DECREF(pyMethod);
241 Py_DECREF(pyArg1);
242 Py_DECREF(pyArg2);
243
244 m_ti.PyValue_To_rValue(pyValue,rValue);
245 if (!m_ti.error) {
246 Py_DECREF(pyValue);
247 } else {
248 cerr << PLUGIN_ERROR << m_ti.lastError().message << endl;
249 Py_CLEAR(pyValue);
250 if (m_quitOnErrorFlag) exit(EXIT_FAILURE);
251 }
252 return rValue;
253 }
254
255
256 template<typename RET,typename A1,typename A2,typename A3>
257 RET genericMethodCallArgs(char *method, A1 arg1, A2 arg2, A3 arg3)
258 {
259 RET rValue = RET();
260 if (m_debugFlag) cerr << DEBUG_NAME << endl;
261 if (!PyObject_HasAttrString(m_pyInstance,method)) {
262 if (m_debugFlag) cerr << DEAFULT_RETURN << endl;
263 return rValue;
264 }
265
266 // These functions always return valid PyObjects
267 PyObject *pyMethod = m_ti.PyValue_From_CValue(method);
268 PyObject* pyTuple = PyTuple_New(3);
269 if (!pyTuple) return rValue;
270
271 PyObject *pyArg1 = m_ti.PyValue_From_CValue(arg1);
272 PyObject *pyArg2 = m_ti.PyValue_From_CValue(arg2);
273 PyObject *pyArg3 = m_ti.PyValue_From_CValue(arg3);
274
275 // TODO: Pack it in a tuple to avoid va_list parsing!
276
277 // callable = PyObject_GetAttr(callable, name);
278 // if (callable == NULL)
279 // return NULL;
280 // PyObject* args; // pyTuple of input arguments
281 //tmp = PyObject_Call(callable, args, NULL);
282
283
284 PyObject *pyValue = PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyArg1,pyArg2,pyArg3,NULL);
285 if (!pyValue)
286 {
287 cerr << PLUGIN_ERROR << "Failed to call method." << endl;
288 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
289 }
290
291 Py_DECREF(pyMethod);
292 Py_DECREF(pyArg1);
293 Py_DECREF(pyArg2);
294 Py_DECREF(pyArg3);
295
296 m_ti.PyValue_To_rValue(pyValue,rValue);
297 if (!m_ti.error) {
298 Py_DECREF(pyValue);
299 } else {
300 cerr << PLUGIN_ERROR << m_ti.lastError().message << endl;
301 Py_CLEAR(pyValue);
302 if (m_quitOnErrorFlag) exit(EXIT_FAILURE);
303 }
304 return rValue;
305 }
306
158 }; 307 };
159 308
160 309
161 #endif 310 #endif