Mercurial > hg > vampy
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 |