cannam@18
|
1 /* -*- c-basic-offset: 8 indent-tabs-mode: t -*- */
|
fazekasgy@0
|
2 /*
|
fazekasgy@0
|
3 Vamp
|
fazekasgy@0
|
4
|
fazekasgy@0
|
5 An API for audio analysis and feature extraction plugins.
|
fazekasgy@0
|
6
|
fazekasgy@0
|
7 Centre for Digital Music, Queen Mary, University of London.
|
fazekasgy@0
|
8 Copyright 2006 Chris Cannam.
|
fazekasgy@0
|
9
|
fazekasgy@0
|
10 Permission is hereby granted, free of charge, to any person
|
fazekasgy@0
|
11 obtaining a copy of this software and associated documentation
|
fazekasgy@0
|
12 files (the "Software"), to deal in the Software without
|
fazekasgy@0
|
13 restriction, including without limitation the rights to use, copy,
|
fazekasgy@0
|
14 modify, merge, publish, distribute, sublicense, and/or sell copies
|
fazekasgy@0
|
15 of the Software, and to permit persons to whom the Software is
|
fazekasgy@0
|
16 furnished to do so, subject to the following conditions:
|
fazekasgy@0
|
17
|
fazekasgy@0
|
18 The above copyright notice and this permission notice shall be
|
fazekasgy@0
|
19 included in all copies or substantial portions of the Software.
|
fazekasgy@0
|
20
|
fazekasgy@0
|
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
fazekasgy@0
|
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
fazekasgy@0
|
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
fazekasgy@0
|
24 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
fazekasgy@0
|
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
fazekasgy@0
|
26 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
fazekasgy@0
|
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
fazekasgy@0
|
28
|
fazekasgy@0
|
29 Except as contained in this notice, the names of the Centre for
|
fazekasgy@0
|
30 Digital Music; Queen Mary, University of London; and Chris Cannam
|
fazekasgy@0
|
31 shall not be used in advertising or otherwise to promote the sale,
|
fazekasgy@0
|
32 use or other dealings in this Software without prior written
|
fazekasgy@0
|
33 authorization.
|
fazekasgy@0
|
34 */
|
fazekasgy@0
|
35
|
fazekasgy@0
|
36
|
fazekasgy@0
|
37
|
fazekasgy@0
|
38 /**
|
fazekasgy@8
|
39 * This Vamp plugin is a wrapper for Python Scripts. (VamPy)
|
fazekasgy@0
|
40 * Centre for Digital Music, Queen Mary, University of London.
|
fazekasgy@0
|
41 * Copyright 2008, George Fazekas.
|
fazekasgy@0
|
42
|
fazekasgy@0
|
43 TODO: needs more complete error checking
|
fazekasgy@0
|
44 needs correct implementation of Python threading
|
fazekasgy@0
|
45 more efficient data conversion using the buffering interface or ctypes
|
cannam@7
|
46 Vamp programs not implemented
|
fazekasgy@0
|
47 support multiple plugins per script in scanner
|
fazekasgy@0
|
48 ensure proper cleanup, host do a good job though
|
fazekasgy@0
|
49
|
fazekasgy@0
|
50 */
|
fazekasgy@0
|
51
|
cannam@3
|
52 #include <Python.h>
|
fazekasgy@0
|
53 #include "PyPlugin.h"
|
fazekasgy@0
|
54
|
fazekasgy@0
|
55 #ifdef _WIN32
|
fazekasgy@0
|
56 #define pathsep ('\\')
|
fazekasgy@0
|
57 #else
|
fazekasgy@0
|
58 #define pathsep ('/')
|
fazekasgy@0
|
59 #endif
|
fazekasgy@0
|
60
|
fazekasgy@6
|
61 //#define _DEBUG
|
fazekasgy@0
|
62
|
fazekasgy@0
|
63 using std::string;
|
fazekasgy@0
|
64 using std::vector;
|
fazekasgy@0
|
65 using std::cerr;
|
fazekasgy@0
|
66 using std::endl;
|
fazekasgy@0
|
67 using std::map;
|
fazekasgy@0
|
68
|
fazekasgy@0
|
69 // Maps to associate strings with enum values
|
cannam@18
|
70 static std::map<std::string, o::eOutDescriptors> outKeys;
|
fazekasgy@0
|
71 static std::map<std::string, eSampleTypes> sampleKeys;
|
fazekasgy@0
|
72 static std::map<std::string, eFeatureFields> ffKeys;
|
fazekasgy@0
|
73 static std::map<std::string, p::eParmDescriptors> parmKeys;
|
fazekasgy@0
|
74
|
cannam@3
|
75 Mutex PyPlugin::m_pythonInterpreterMutex;
|
fazekasgy@6
|
76 static bool isMapInitialised = false;
|
fazekasgy@0
|
77
|
cannam@24
|
78 PyPlugin::PyPlugin(std::string pluginKey, float inputSampleRate, PyObject *pyClass) :
|
cannam@24
|
79 Plugin(inputSampleRate),
|
cannam@24
|
80 m_pyClass(pyClass),
|
fazekasgy@0
|
81 m_stepSize(0),
|
fazekasgy@6
|
82 m_blockSize(0),
|
cannam@24
|
83 m_channels(0),
|
fazekasgy@0
|
84 m_plugin(pluginKey),
|
fazekasgy@0
|
85 m_class(pluginKey.substr(pluginKey.rfind(':')+1,pluginKey.size()-1)),
|
fazekasgy@6
|
86 m_path((pluginKey.substr(0,pluginKey.rfind(pathsep)))),
|
fazekasgy@6
|
87 m_processType(0),
|
fazekasgy@6
|
88 m_pyProcess(NULL),
|
fazekasgy@6
|
89 m_inputDomain(TimeDomain)
|
fazekasgy@0
|
90 {
|
cannam@24
|
91 // Create an instance
|
cannam@24
|
92 PyObject *pyInputSampleRate = PyFloat_FromDouble(inputSampleRate);
|
cannam@24
|
93 PyObject *args = PyTuple_Pack(1, pyInputSampleRate);
|
cannam@24
|
94
|
cannam@24
|
95 m_pyInstance = PyObject_CallObject(m_pyClass, args);
|
cannam@24
|
96
|
cannam@24
|
97 if (!m_pyInstance) {
|
cannam@24
|
98 cerr << "PyPlugin::PyPlugin: Failed to create Python plugin instance for key \"" << pluginKey << "\" (is the 1-arg class constructor from sample rate correctly provided?)" << endl;
|
cannam@24
|
99 throw std::string("Constructor failed");
|
cannam@24
|
100 }
|
cannam@24
|
101
|
cannam@24
|
102 Py_DECREF(args);
|
cannam@24
|
103 Py_DECREF(pyInputSampleRate);
|
fazekasgy@0
|
104 }
|
fazekasgy@0
|
105
|
fazekasgy@0
|
106 PyPlugin::~PyPlugin()
|
fazekasgy@0
|
107 {
|
cannam@24
|
108 if (m_pyInstance) Py_DECREF(m_pyInstance);
|
cannam@24
|
109
|
fazekasgy@6
|
110 Py_CLEAR(m_pyProcess);
|
fazekasgy@6
|
111 #ifdef _DEBUG
|
fazekasgy@0
|
112 cerr << "PyPlugin::PyPlugin:" << m_class
|
cannam@24
|
113 << " Instance deleted." << endl;
|
fazekasgy@6
|
114 #endif
|
fazekasgy@0
|
115 }
|
fazekasgy@0
|
116
|
fazekasgy@0
|
117
|
fazekasgy@0
|
118 string
|
fazekasgy@0
|
119 PyPlugin::getIdentifier() const
|
fazekasgy@0
|
120 {
|
cannam@3
|
121 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
122
|
fazekasgy@0
|
123 char method[]="getIdentifier";
|
fazekasgy@0
|
124 cerr << "[call] " << method << endl;
|
fazekasgy@6
|
125 string rString="vampy-x";
|
fazekasgy@0
|
126
|
fazekasgy@0
|
127 if ( PyObject_HasAttrString(m_pyInstance,method) ) {
|
fazekasgy@0
|
128
|
fazekasgy@0
|
129 //Call the method
|
fazekasgy@0
|
130 PyObject *pyString =
|
fazekasgy@0
|
131 PyObject_CallMethod(m_pyInstance, method, NULL);
|
fazekasgy@0
|
132
|
fazekasgy@0
|
133 //Check return value
|
fazekasgy@0
|
134 if (!PyString_Check(pyString)) {
|
fazekasgy@0
|
135 Py_CLEAR(pyString);
|
fazekasgy@0
|
136 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
137 << "] Expected String return value." << endl;
|
fazekasgy@0
|
138 return rString;
|
fazekasgy@0
|
139 }
|
fazekasgy@0
|
140
|
fazekasgy@0
|
141 rString=PyString_AsString(pyString);
|
fazekasgy@0
|
142 Py_CLEAR(pyString);
|
fazekasgy@6
|
143 return rString;
|
fazekasgy@0
|
144 }
|
fazekasgy@0
|
145 cerr << "Warning: Plugin must return a unique identifier." << endl;
|
fazekasgy@0
|
146 return rString;
|
fazekasgy@0
|
147 }
|
fazekasgy@0
|
148
|
fazekasgy@0
|
149
|
fazekasgy@0
|
150 string
|
fazekasgy@0
|
151 PyPlugin::getName() const
|
fazekasgy@0
|
152 {
|
cannam@3
|
153 MutexLocker locker(&m_pythonInterpreterMutex);
|
fazekasgy@0
|
154
|
fazekasgy@0
|
155 char method[]="getName";
|
fazekasgy@0
|
156 cerr << "[call] " << method << endl;
|
fazekasgy@0
|
157 string rString="VamPy Plugin (Noname)";
|
fazekasgy@0
|
158
|
fazekasgy@0
|
159 if ( PyObject_HasAttrString(m_pyInstance,method) ) {
|
fazekasgy@0
|
160
|
fazekasgy@0
|
161 //Call the method
|
fazekasgy@0
|
162 PyObject *pyString =
|
fazekasgy@0
|
163 PyObject_CallMethod(m_pyInstance, method, NULL);
|
fazekasgy@0
|
164
|
fazekasgy@0
|
165 //Check return value
|
fazekasgy@0
|
166 if (!PyString_Check(pyString)) {
|
fazekasgy@0
|
167 Py_CLEAR(pyString);
|
fazekasgy@0
|
168 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
169 << "] Expected String return value." << endl;
|
fazekasgy@0
|
170 return rString;
|
fazekasgy@0
|
171 }
|
fazekasgy@0
|
172
|
fazekasgy@0
|
173 rString=PyString_AsString(pyString);
|
fazekasgy@0
|
174 Py_CLEAR(pyString);
|
fazekasgy@0
|
175 }
|
fazekasgy@0
|
176 return rString;
|
fazekasgy@0
|
177 }
|
fazekasgy@0
|
178
|
fazekasgy@0
|
179 string
|
fazekasgy@0
|
180 PyPlugin::getDescription() const
|
fazekasgy@0
|
181 {
|
cannam@3
|
182 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
183
|
fazekasgy@0
|
184 char method[]="getDescription";
|
fazekasgy@0
|
185 cerr << "[call] " << method << endl;
|
fazekasgy@0
|
186 string rString="Not given. (Hint: Implement getDescription method.)";
|
fazekasgy@0
|
187
|
fazekasgy@0
|
188 if ( PyObject_HasAttrString(m_pyInstance,method) ) {
|
fazekasgy@0
|
189
|
fazekasgy@0
|
190 //Call the method
|
fazekasgy@0
|
191 PyObject *pyString =
|
fazekasgy@0
|
192 PyObject_CallMethod(m_pyInstance, method, NULL);
|
fazekasgy@0
|
193
|
fazekasgy@0
|
194 //Check return value
|
fazekasgy@0
|
195 if (!PyString_Check(pyString)) {
|
fazekasgy@0
|
196 Py_CLEAR(pyString);
|
fazekasgy@0
|
197 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
198 << "] Expected String return value." << endl;
|
fazekasgy@0
|
199 return rString;
|
fazekasgy@0
|
200 }
|
fazekasgy@0
|
201
|
fazekasgy@0
|
202 rString=PyString_AsString(pyString);
|
fazekasgy@0
|
203 Py_CLEAR(pyString);
|
fazekasgy@0
|
204 }
|
fazekasgy@0
|
205 return rString;
|
fazekasgy@0
|
206 }
|
fazekasgy@0
|
207
|
fazekasgy@0
|
208 string
|
fazekasgy@0
|
209 PyPlugin::getMaker() const
|
fazekasgy@0
|
210 {
|
cannam@3
|
211 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
212
|
fazekasgy@0
|
213 char method[]="getMaker";
|
fazekasgy@0
|
214 cerr << "[call] " << method << endl;
|
fazekasgy@0
|
215 string rString="Generic VamPy Plugin.";
|
fazekasgy@0
|
216
|
fazekasgy@0
|
217 if ( PyObject_HasAttrString(m_pyInstance,method) ) {
|
fazekasgy@0
|
218
|
fazekasgy@0
|
219 //Call the method
|
fazekasgy@0
|
220 PyObject *pyString =
|
fazekasgy@0
|
221 PyObject_CallMethod(m_pyInstance, method, NULL);
|
fazekasgy@0
|
222
|
fazekasgy@0
|
223 //Check return value
|
fazekasgy@0
|
224 if (!PyString_Check(pyString)) {
|
fazekasgy@0
|
225 Py_CLEAR(pyString);
|
fazekasgy@0
|
226 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
227 << "] Expected String return value." << endl;
|
fazekasgy@0
|
228 return rString;
|
fazekasgy@0
|
229 }
|
fazekasgy@0
|
230
|
fazekasgy@0
|
231 rString=PyString_AsString(pyString);
|
fazekasgy@0
|
232 Py_CLEAR(pyString);
|
fazekasgy@0
|
233 }
|
fazekasgy@0
|
234 return rString;
|
fazekasgy@0
|
235 }
|
fazekasgy@0
|
236
|
fazekasgy@0
|
237 int
|
fazekasgy@0
|
238 PyPlugin::getPluginVersion() const
|
fazekasgy@0
|
239 {
|
cannam@24
|
240 //!!! implement
|
cannam@24
|
241
|
cannam@24
|
242 return 2;
|
fazekasgy@0
|
243 }
|
fazekasgy@0
|
244
|
fazekasgy@0
|
245 string
|
fazekasgy@0
|
246 PyPlugin::getCopyright() const
|
fazekasgy@0
|
247 {
|
cannam@3
|
248 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
249
|
fazekasgy@0
|
250 char method[]="getCopyright";
|
fazekasgy@0
|
251 cerr << "[call] " << method << endl;
|
fazekasgy@0
|
252 string rString="BSD License";
|
fazekasgy@0
|
253
|
fazekasgy@0
|
254 if ( PyObject_HasAttrString(m_pyInstance,method) ) {
|
fazekasgy@0
|
255
|
fazekasgy@0
|
256 //Call the method
|
fazekasgy@0
|
257 PyObject *pyString =
|
fazekasgy@0
|
258 PyObject_CallMethod(m_pyInstance, method, NULL);
|
fazekasgy@0
|
259
|
fazekasgy@0
|
260 //Check return value
|
fazekasgy@0
|
261 if (!PyString_Check(pyString)) {
|
fazekasgy@0
|
262 Py_CLEAR(pyString);
|
fazekasgy@0
|
263 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
264 << "] Expected String return value." << endl;
|
fazekasgy@0
|
265 return rString;
|
fazekasgy@0
|
266 }
|
fazekasgy@0
|
267
|
fazekasgy@0
|
268
|
fazekasgy@0
|
269 rString=PyString_AsString(pyString);
|
fazekasgy@0
|
270 Py_CLEAR(pyString);
|
fazekasgy@0
|
271 }
|
cannam@24
|
272
|
cannam@24
|
273 return rString;
|
fazekasgy@0
|
274 }
|
fazekasgy@0
|
275
|
fazekasgy@0
|
276
|
fazekasgy@0
|
277 bool
|
fazekasgy@0
|
278 PyPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
fazekasgy@0
|
279 {
|
fazekasgy@8
|
280 //useful for debugging Python plugins
|
fazekasgy@8
|
281 char method[]="initialise";
|
fazekasgy@8
|
282 cerr << "[call] " << method << endl;
|
fazekasgy@6
|
283
|
fazekasgy@6
|
284 //placing Mutex before these calls causes deadlock
|
cannam@24
|
285 if (channels < getMinChannelCount() ||
|
cannam@24
|
286 channels > getMaxChannelCount()) return false;
|
fazekasgy@6
|
287
|
fazekasgy@6
|
288 m_inputDomain = getInputDomain();
|
fazekasgy@6
|
289
|
cannam@3
|
290 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
291
|
fazekasgy@6
|
292 initMaps();
|
fazekasgy@6
|
293
|
fazekasgy@6
|
294 m_stepSize = stepSize;
|
fazekasgy@6
|
295 m_blockSize = blockSize;
|
fazekasgy@6
|
296 m_channels = channels;
|
fazekasgy@6
|
297
|
fazekasgy@6
|
298 //quering process implementation type
|
fazekasgy@6
|
299 char legacyMethod[]="process";
|
fazekasgy@6
|
300 char numpyMethod[]="processN";
|
fazekasgy@6
|
301
|
cannam@18
|
302 if (PyObject_HasAttrString(m_pyInstance,legacyMethod) &&
|
cannam@18
|
303 m_processType == 0)
|
fazekasgy@6
|
304 {
|
fazekasgy@6
|
305 m_processType = legacyProcess;
|
fazekasgy@6
|
306 m_pyProcess = PyString_FromString(legacyMethod);
|
fazekasgy@6
|
307 }
|
fazekasgy@6
|
308
|
cannam@18
|
309 if (PyObject_HasAttrString(m_pyInstance,numpyMethod) &&
|
cannam@18
|
310 m_processType == 0)
|
fazekasgy@6
|
311 {
|
fazekasgy@6
|
312 m_processType = numpyProcess;
|
fazekasgy@6
|
313 m_pyProcess = PyString_FromString(numpyMethod);
|
fazekasgy@6
|
314 }
|
fazekasgy@6
|
315
|
fazekasgy@6
|
316 if (!m_processType)
|
fazekasgy@6
|
317 {
|
fazekasgy@6
|
318 m_processType = not_implemented;
|
fazekasgy@6
|
319 m_pyProcess = NULL;
|
fazekasgy@6
|
320 cerr << "Warning: Python plugin [" << m_class << "::" << method
|
cannam@24
|
321 << "] No process implementation found. Plugin will do nothing." << endl;
|
fazekasgy@6
|
322 }
|
fazekasgy@6
|
323
|
cannam@24
|
324 //Check if the method is implemented in Python else return false
|
cannam@24
|
325 if (PyObject_HasAttrString(m_pyInstance,method)) {
|
fazekasgy@0
|
326
|
cannam@24
|
327 PyObject *pyMethod = PyString_FromString(method);
|
cannam@24
|
328 PyObject *pyChannels = PyInt_FromSsize_t((Py_ssize_t)channels);
|
cannam@24
|
329 PyObject *pyStepSize = PyInt_FromSsize_t((Py_ssize_t)m_stepSize);
|
cannam@24
|
330 PyObject *pyBlockSize = PyInt_FromSsize_t((Py_ssize_t)blockSize);
|
cannam@24
|
331 //Call the method
|
cannam@24
|
332 PyObject *pyBool =
|
cannam@24
|
333 PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyChannels,pyStepSize,pyBlockSize,NULL);
|
fazekasgy@8
|
334
|
cannam@24
|
335 Py_DECREF(pyMethod);
|
cannam@24
|
336 Py_DECREF(pyChannels);
|
cannam@24
|
337 Py_DECREF(pyStepSize);
|
cannam@24
|
338 Py_DECREF(pyBlockSize);
|
fazekasgy@0
|
339
|
cannam@24
|
340 //Check return value
|
cannam@24
|
341 if (PyErr_Occurred() || !PyBool_Check(pyBool)) {
|
cannam@24
|
342 PyErr_Print(); PyErr_Clear();
|
cannam@24
|
343 Py_CLEAR(pyBool);
|
cannam@24
|
344 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
cannam@24
|
345 << "] Expected Bool return value." << endl;
|
cannam@24
|
346 return false;
|
cannam@24
|
347 }
|
cannam@24
|
348
|
cannam@24
|
349 if (pyBool == Py_True) {
|
cannam@24
|
350 Py_CLEAR(pyBool);
|
cannam@24
|
351 return true;
|
cannam@24
|
352 } else {
|
cannam@24
|
353 Py_CLEAR(pyBool);
|
cannam@24
|
354 return false;
|
cannam@24
|
355 }
|
cannam@24
|
356 }
|
fazekasgy@6
|
357 return false;
|
fazekasgy@0
|
358 }
|
fazekasgy@0
|
359
|
fazekasgy@0
|
360 void
|
fazekasgy@0
|
361 PyPlugin::reset()
|
fazekasgy@0
|
362 {
|
fazekasgy@6
|
363 MutexLocker locker(&m_pythonInterpreterMutex);
|
fazekasgy@6
|
364
|
fazekasgy@6
|
365 char method[]="reset";
|
fazekasgy@6
|
366 cerr << "[call] " << method << endl;
|
fazekasgy@6
|
367
|
fazekasgy@6
|
368 if ( PyObject_HasAttrString(m_pyInstance,method) ) {
|
fazekasgy@6
|
369
|
fazekasgy@6
|
370 PyObject_CallMethod(m_pyInstance, method, NULL);
|
fazekasgy@6
|
371 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@6
|
372
|
fazekasgy@6
|
373 }
|
fazekasgy@0
|
374 }
|
fazekasgy@0
|
375
|
fazekasgy@6
|
376 PyPlugin::InputDomain PyPlugin::getInputDomain() const
|
fazekasgy@0
|
377 {
|
cannam@3
|
378 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
379
|
fazekasgy@0
|
380 char method[]="getInputDomain";
|
fazekasgy@0
|
381 cerr << "[call] " << method << endl;
|
fazekasgy@0
|
382 PyPlugin::InputDomain rValue = TimeDomain; // TimeDomain
|
fazekasgy@0
|
383
|
fazekasgy@0
|
384 if ( PyObject_HasAttrString(m_pyInstance,method) ) {
|
fazekasgy@0
|
385
|
fazekasgy@0
|
386 PyObject *pyString = PyObject_CallMethod(m_pyInstance, method, NULL);
|
fazekasgy@0
|
387
|
fazekasgy@0
|
388 //Check return value
|
fazekasgy@0
|
389 if (!PyString_Check(pyString)) {
|
fazekasgy@0
|
390 Py_CLEAR(pyString);
|
fazekasgy@0
|
391 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
392 << "] Expected String return value." << endl;
|
fazekasgy@0
|
393 return rValue;
|
fazekasgy@0
|
394 }
|
fazekasgy@0
|
395
|
fazekasgy@0
|
396 string domain = (string) PyString_AsString(pyString);
|
fazekasgy@0
|
397 if (domain == "FrequencyDomain") rValue = FrequencyDomain;
|
fazekasgy@0
|
398 Py_CLEAR(pyString);
|
fazekasgy@0
|
399 }
|
fazekasgy@0
|
400 return rValue;
|
fazekasgy@0
|
401 }
|
fazekasgy@0
|
402
|
fazekasgy@6
|
403
|
fazekasgy@0
|
404 size_t PyPlugin::getPreferredBlockSize() const
|
fazekasgy@0
|
405 {
|
cannam@3
|
406 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
407
|
fazekasgy@0
|
408 char method[]="getPreferredBlockSize";
|
fazekasgy@0
|
409 cerr << "[call] " << method << endl;
|
fazekasgy@0
|
410 size_t rValue=0; //not set by default
|
fazekasgy@0
|
411 if ( PyObject_HasAttrString(m_pyInstance,method) ) {
|
fazekasgy@0
|
412 PyObject *pyInt = PyObject_CallMethod(m_pyInstance, method, NULL);
|
fazekasgy@0
|
413
|
fazekasgy@0
|
414 //Check return value
|
fazekasgy@0
|
415 if (!PyInt_Check(pyInt)) {
|
fazekasgy@0
|
416 Py_CLEAR(pyInt);
|
fazekasgy@0
|
417 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
418 << "] Expected Integer return value." << endl;
|
fazekasgy@0
|
419 return rValue;
|
fazekasgy@0
|
420 }
|
fazekasgy@0
|
421
|
fazekasgy@0
|
422 rValue=(size_t)PyInt_AS_LONG(pyInt);
|
fazekasgy@0
|
423 Py_CLEAR(pyInt);
|
fazekasgy@0
|
424 }
|
fazekasgy@0
|
425 return rValue;
|
fazekasgy@0
|
426 }
|
fazekasgy@0
|
427
|
fazekasgy@0
|
428 //size_t PyPlugin::getPreferredStepSize() const { return 0; }
|
fazekasgy@0
|
429 size_t PyPlugin::getPreferredStepSize() const
|
fazekasgy@0
|
430 {
|
cannam@3
|
431 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
432
|
fazekasgy@0
|
433 char method[]="getPreferredStepSize";
|
fazekasgy@0
|
434 cerr << "[call] " << method << endl;
|
fazekasgy@8
|
435 size_t rValue=1024; //not set by default
|
fazekasgy@0
|
436 if ( PyObject_HasAttrString(m_pyInstance,method) ) {
|
fazekasgy@0
|
437 PyObject *pyInt = PyObject_CallMethod(m_pyInstance, method, NULL);
|
fazekasgy@0
|
438
|
fazekasgy@0
|
439 //Check return value
|
fazekasgy@0
|
440 if (!PyInt_Check(pyInt)) {
|
fazekasgy@0
|
441 Py_CLEAR(pyInt);
|
fazekasgy@0
|
442 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
443 << "] Expected Integer return value." << endl;
|
fazekasgy@0
|
444 return rValue;
|
fazekasgy@0
|
445 }
|
fazekasgy@0
|
446
|
fazekasgy@0
|
447 rValue=(size_t)PyInt_AS_LONG(pyInt);
|
fazekasgy@0
|
448 Py_CLEAR(pyInt);
|
fazekasgy@0
|
449 }
|
fazekasgy@0
|
450 return rValue;
|
fazekasgy@0
|
451 }
|
fazekasgy@0
|
452
|
fazekasgy@0
|
453 size_t PyPlugin::getMinChannelCount() const
|
fazekasgy@0
|
454 {
|
cannam@3
|
455 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
456
|
fazekasgy@0
|
457 char method[]="getMinChannelCount";
|
fazekasgy@0
|
458 cerr << "[call] " << method << endl;
|
fazekasgy@0
|
459 size_t rValue=1; //default value
|
fazekasgy@0
|
460 if ( PyObject_HasAttrString(m_pyInstance,method) ) {
|
fazekasgy@0
|
461 PyObject *pyInt = PyObject_CallMethod(m_pyInstance, method, NULL);
|
fazekasgy@0
|
462
|
fazekasgy@0
|
463 //Check return value
|
fazekasgy@0
|
464 if (!PyInt_Check(pyInt)) {
|
fazekasgy@0
|
465 Py_CLEAR(pyInt);
|
fazekasgy@0
|
466 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
467 << "] Expected String return value." << endl;
|
fazekasgy@0
|
468 return rValue;
|
fazekasgy@0
|
469 }
|
fazekasgy@0
|
470
|
fazekasgy@0
|
471 rValue=(size_t)PyInt_AS_LONG(pyInt);
|
fazekasgy@0
|
472 Py_CLEAR(pyInt);
|
fazekasgy@0
|
473 }
|
fazekasgy@0
|
474 return rValue;
|
fazekasgy@0
|
475 }
|
fazekasgy@0
|
476
|
fazekasgy@0
|
477 size_t PyPlugin::getMaxChannelCount() const
|
fazekasgy@0
|
478 {
|
cannam@3
|
479 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
480
|
fazekasgy@0
|
481 char method[]="getMaxChannelCount";
|
fazekasgy@0
|
482 cerr << "[call] " << method << endl;
|
fazekasgy@0
|
483 size_t rValue=1; //default value
|
fazekasgy@0
|
484 if ( PyObject_HasAttrString(m_pyInstance,method) ) {
|
fazekasgy@0
|
485 PyObject *pyInt = PyObject_CallMethod(m_pyInstance, method, NULL);
|
fazekasgy@0
|
486
|
fazekasgy@0
|
487 //Check return value
|
fazekasgy@0
|
488 if (!PyInt_Check(pyInt)) {
|
fazekasgy@0
|
489 Py_CLEAR(pyInt);
|
fazekasgy@0
|
490 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
491 << "] Expected String return value." << endl;
|
fazekasgy@0
|
492 return rValue;
|
fazekasgy@0
|
493 }
|
fazekasgy@0
|
494
|
fazekasgy@0
|
495 rValue=(size_t)PyInt_AS_LONG(pyInt);
|
fazekasgy@0
|
496 Py_CLEAR(pyInt);
|
fazekasgy@0
|
497 }
|
fazekasgy@0
|
498 return rValue;
|
fazekasgy@0
|
499 }
|
fazekasgy@0
|
500
|
fazekasgy@0
|
501
|
fazekasgy@0
|
502 PyPlugin::OutputList
|
fazekasgy@0
|
503 PyPlugin::getOutputDescriptors() const
|
fazekasgy@0
|
504 {
|
fazekasgy@6
|
505
|
cannam@3
|
506 MutexLocker locker(&m_pythonInterpreterMutex);
|
fazekasgy@6
|
507
|
fazekasgy@0
|
508 //PyEval_AcquireThread(newThreadState);
|
fazekasgy@0
|
509 OutputList list;
|
fazekasgy@0
|
510 OutputDescriptor od;
|
fazekasgy@0
|
511 char method[]="getOutputDescriptors";
|
fazekasgy@0
|
512 cerr << "[call] " << method << endl;
|
fazekasgy@0
|
513
|
fazekasgy@0
|
514 //Check if the method is implemented in Python
|
fazekasgy@6
|
515 if ( ! PyObject_HasAttrString(m_pyInstance,method) ) return list;
|
fazekasgy@0
|
516
|
fazekasgy@0
|
517 //Call the method: must return list object (new reference)
|
fazekasgy@0
|
518 PyObject *pyList =
|
fazekasgy@0
|
519 PyObject_CallMethod(m_pyInstance,method, NULL);
|
fazekasgy@0
|
520
|
fazekasgy@0
|
521 //Check return type
|
fazekasgy@0
|
522 if (! PyList_Check(pyList) ) {
|
fazekasgy@0
|
523 Py_CLEAR(pyList);
|
fazekasgy@0
|
524 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
525 << "] Expected List return type." << endl;
|
fazekasgy@0
|
526 return list;
|
fazekasgy@0
|
527 }
|
fazekasgy@0
|
528
|
fazekasgy@0
|
529 //These will all be borrowed references (no need to DECREF)
|
fazekasgy@0
|
530 PyObject *pyDict, *pyKey, *pyValue;
|
fazekasgy@0
|
531
|
fazekasgy@0
|
532 //Parse Output List
|
fazekasgy@0
|
533 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(pyList); ++i) {
|
fazekasgy@0
|
534
|
cannam@18
|
535 //Get i-th Vamp output descriptor (Borrowed Reference)
|
fazekasgy@0
|
536 pyDict = PyList_GET_ITEM(pyList,i);
|
fazekasgy@0
|
537
|
fazekasgy@0
|
538 //We only care about dictionaries holding output descriptors
|
fazekasgy@0
|
539 if ( !PyDict_Check(pyDict) ) continue;
|
fazekasgy@0
|
540
|
fazekasgy@0
|
541 Py_ssize_t pyPos = NULL;
|
fazekasgy@0
|
542 initMaps();
|
fazekasgy@0
|
543
|
fazekasgy@0
|
544 //Python Sequence Iterator
|
fazekasgy@0
|
545 while (PyDict_Next(pyDict, &pyPos, &pyKey, &pyValue))
|
fazekasgy@0
|
546 {
|
fazekasgy@0
|
547 switch (outKeys[PyString_AsString(pyKey)])
|
fazekasgy@0
|
548 {
|
cannam@18
|
549 case o::not_found :
|
cannam@18
|
550 cerr << "Unknown key in Vamp OutputDescriptor: " << PyString_AsString(pyKey) << endl;
|
fazekasgy@0
|
551 break;
|
cannam@18
|
552 case o::identifier:
|
fazekasgy@0
|
553 od.identifier = PyString_AsString(pyValue);
|
fazekasgy@0
|
554 break;
|
cannam@18
|
555 case o::name:
|
fazekasgy@0
|
556 od.name = PyString_AsString(pyValue);
|
fazekasgy@0
|
557 break;
|
cannam@18
|
558 case o::description:
|
fazekasgy@0
|
559 od.description = PyString_AsString(pyValue);
|
fazekasgy@0
|
560 break;
|
cannam@18
|
561 case o::unit:
|
fazekasgy@0
|
562 od.unit = PyString_AsString(pyValue);
|
fazekasgy@0
|
563 break;
|
cannam@18
|
564 case o::hasFixedBinCount:
|
fazekasgy@0
|
565 od.hasFixedBinCount = (bool) PyInt_AS_LONG(pyValue);
|
fazekasgy@0
|
566 break;
|
cannam@18
|
567 case o::binCount:
|
fazekasgy@0
|
568 od.binCount = (size_t) PyInt_AS_LONG(pyValue);
|
fazekasgy@0
|
569 break;
|
cannam@18
|
570 case o::binNames:
|
fazekasgy@0
|
571 od.binNames = PyList_To_StringVector(pyValue);
|
fazekasgy@0
|
572 break;
|
cannam@18
|
573 case o::hasKnownExtents:
|
fazekasgy@0
|
574 od.hasKnownExtents = (bool) PyInt_AS_LONG(pyValue);
|
fazekasgy@0
|
575 break;
|
cannam@18
|
576 case o::minValue:
|
fazekasgy@0
|
577 od.minValue = (float) PyFloat_AS_DOUBLE(pyValue);
|
fazekasgy@0
|
578 break;
|
cannam@18
|
579 case o::maxValue:
|
fazekasgy@0
|
580 od.maxValue = (float) PyFloat_AS_DOUBLE(pyValue);
|
fazekasgy@0
|
581 break;
|
cannam@18
|
582 case o::isQuantized:
|
fazekasgy@0
|
583 od.isQuantized = (bool) PyInt_AS_LONG(pyValue);
|
fazekasgy@0
|
584 break;
|
cannam@18
|
585 case o::quantizeStep:
|
fazekasgy@0
|
586 od.quantizeStep = (float) PyFloat_AS_DOUBLE(pyValue);
|
fazekasgy@0
|
587 break;
|
cannam@18
|
588 case o::sampleType:
|
fazekasgy@0
|
589 od.sampleType = (OutputDescriptor::SampleType) sampleKeys[PyString_AsString(pyValue)];
|
fazekasgy@0
|
590 break;
|
cannam@18
|
591 case o::sampleRate:
|
fazekasgy@0
|
592 od.sampleRate = (float) PyFloat_AS_DOUBLE(pyValue);
|
fazekasgy@8
|
593 // od.sampleRate = m_inputSampleRate / m_stepSize;
|
fazekasgy@8
|
594 cerr << od.sampleRate << endl;
|
fazekasgy@0
|
595 break;
|
cannam@18
|
596 case o::hasDuration:
|
cannam@18
|
597 od.hasDuration = (bool)PyInt_AS_LONG(pyValue);
|
cannam@18
|
598 break;
|
fazekasgy@0
|
599 default :
|
cannam@18
|
600 cerr << "Invalid key in Vamp OutputDescriptor: " << PyString_AsString(pyKey) << endl;
|
fazekasgy@6
|
601 }
|
fazekasgy@6
|
602 } // while dict
|
fazekasgy@0
|
603 list.push_back(od);
|
fazekasgy@6
|
604 } // for list
|
fazekasgy@0
|
605 Py_CLEAR(pyList);
|
fazekasgy@0
|
606 return list;
|
fazekasgy@0
|
607 }
|
fazekasgy@0
|
608
|
fazekasgy@0
|
609 PyPlugin::ParameterList
|
fazekasgy@0
|
610 PyPlugin::getParameterDescriptors() const
|
fazekasgy@0
|
611 {
|
cannam@3
|
612 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
613
|
fazekasgy@0
|
614 ParameterList list;
|
fazekasgy@0
|
615 ParameterDescriptor pd;
|
fazekasgy@0
|
616 char method[]="getParameterDescriptors";
|
fazekasgy@0
|
617 cerr << "[call] " << method << endl;
|
fazekasgy@0
|
618
|
fazekasgy@0
|
619 //Check if the method is implemented in Python
|
fazekasgy@6
|
620 if ( ! PyObject_HasAttrString(m_pyInstance,method) ) return list;
|
fazekasgy@0
|
621
|
fazekasgy@0
|
622 //Call the method: must return list object (new reference)
|
fazekasgy@0
|
623 PyObject *pyList =
|
fazekasgy@0
|
624 PyObject_CallMethod(m_pyInstance,method, NULL);
|
fazekasgy@0
|
625
|
fazekasgy@0
|
626 //Check return type
|
fazekasgy@0
|
627 if (! PyList_Check(pyList) ) {
|
fazekasgy@0
|
628 Py_CLEAR(pyList);
|
fazekasgy@0
|
629 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
630 << "] Expected List return type." << endl;
|
fazekasgy@0
|
631 return list;
|
fazekasgy@0
|
632 }
|
fazekasgy@0
|
633
|
fazekasgy@0
|
634
|
fazekasgy@0
|
635 //These will all be borrowed references (no need to DECREF)
|
fazekasgy@0
|
636 PyObject *pyDict, *pyKey, *pyValue;
|
fazekasgy@0
|
637
|
fazekasgy@0
|
638 //Parse Output List
|
fazekasgy@0
|
639 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(pyList); ++i) {
|
fazekasgy@0
|
640
|
cannam@18
|
641 //Get i-th Vamp output descriptor (Borrowed Reference)
|
fazekasgy@0
|
642 pyDict = PyList_GET_ITEM(pyList,i);
|
fazekasgy@0
|
643
|
fazekasgy@0
|
644 //We only care about dictionaries holding output descriptors
|
fazekasgy@0
|
645 if ( !PyDict_Check(pyDict) ) continue;
|
fazekasgy@0
|
646
|
fazekasgy@0
|
647 Py_ssize_t pyPos = NULL;
|
fazekasgy@0
|
648 initMaps();
|
fazekasgy@0
|
649
|
fazekasgy@0
|
650 //Python Sequence Iterator
|
fazekasgy@0
|
651 while (PyDict_Next(pyDict, &pyPos, &pyKey, &pyValue))
|
fazekasgy@0
|
652 {
|
fazekasgy@0
|
653 switch (parmKeys[PyString_AsString(pyKey)])
|
fazekasgy@0
|
654 {
|
cannam@18
|
655 case p::not_found :
|
cannam@18
|
656 cerr << "Unknown key in Vamp OutputDescriptor: " << PyString_AsString(pyKey) << endl;
|
fazekasgy@0
|
657 break;
|
fazekasgy@0
|
658 case p::identifier:
|
fazekasgy@0
|
659 pd.identifier = PyString_AsString(pyValue);
|
fazekasgy@0
|
660 break;
|
fazekasgy@0
|
661 case p::name:
|
fazekasgy@0
|
662 pd.name = PyString_AsString(pyValue);
|
fazekasgy@0
|
663 break;
|
fazekasgy@0
|
664 case p::description:
|
fazekasgy@0
|
665 pd.description = PyString_AsString(pyValue);
|
fazekasgy@0
|
666 break;
|
fazekasgy@0
|
667 case p::unit:
|
fazekasgy@0
|
668 pd.unit = PyString_AsString(pyValue);
|
fazekasgy@0
|
669 break;
|
fazekasgy@0
|
670 case p::minValue:
|
fazekasgy@0
|
671 pd.minValue = (float) PyFloat_AS_DOUBLE(pyValue);
|
fazekasgy@0
|
672 break;
|
fazekasgy@0
|
673 case p::maxValue:
|
fazekasgy@0
|
674 pd.maxValue = (float) PyFloat_AS_DOUBLE(pyValue);
|
fazekasgy@0
|
675 break;
|
fazekasgy@0
|
676 case p::defaultValue:
|
fazekasgy@0
|
677 pd.defaultValue = (float) PyFloat_AS_DOUBLE(pyValue);
|
fazekasgy@0
|
678 break;
|
fazekasgy@0
|
679 case p::isQuantized:
|
fazekasgy@0
|
680 pd.isQuantized = (bool) PyInt_AS_LONG(pyValue);
|
cannam@22
|
681 break; case p::quantizeStep:
|
cannam@22
|
682 pd.quantizeStep = (float) PyFloat_AS_DOUBLE(pyValue);
|
cannam@22
|
683 break;
|
fazekasgy@0
|
684 default :
|
cannam@18
|
685 cerr << "Invalid key in Vamp OutputDescriptor: " << PyString_AsString(pyKey) << endl;
|
fazekasgy@6
|
686 }
|
fazekasgy@6
|
687 } // while dict
|
fazekasgy@0
|
688 list.push_back(pd);
|
fazekasgy@6
|
689 } // for list
|
fazekasgy@0
|
690 Py_CLEAR(pyList);
|
fazekasgy@0
|
691 return list;
|
fazekasgy@0
|
692 }
|
fazekasgy@0
|
693
|
fazekasgy@0
|
694 void PyPlugin::setParameter(std::string paramid, float newval)
|
fazekasgy@0
|
695 {
|
cannam@3
|
696 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
697
|
fazekasgy@0
|
698 char method[]="setParameter";
|
fazekasgy@0
|
699 cerr << "[call] " << method << endl;
|
fazekasgy@0
|
700
|
fazekasgy@0
|
701 //Check if the method is implemented in Python
|
fazekasgy@0
|
702 if (PyObject_HasAttrString(m_pyInstance,method)) {
|
fazekasgy@0
|
703
|
fazekasgy@0
|
704 PyObject *pyMethod = PyString_FromString(method);
|
fazekasgy@0
|
705 PyObject *pyParamid = PyString_FromString(paramid.c_str());
|
fazekasgy@0
|
706 PyObject *pyNewval = PyFloat_FromDouble((double)newval);
|
fazekasgy@0
|
707
|
fazekasgy@0
|
708 //Call the method
|
fazekasgy@0
|
709 PyObject *pyBool =
|
fazekasgy@0
|
710 PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyParamid,pyNewval,NULL);
|
fazekasgy@0
|
711
|
fazekasgy@0
|
712 //This only happens if there is a syntax error or so
|
fazekasgy@0
|
713 if (pyBool == NULL) {
|
fazekasgy@0
|
714 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
715 << "] Error setting parameter: " << paramid << endl;
|
fazekasgy@0
|
716 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@0
|
717 }
|
fazekasgy@0
|
718
|
fazekasgy@0
|
719 Py_DECREF(pyMethod);
|
fazekasgy@0
|
720 Py_DECREF(pyParamid);
|
fazekasgy@0
|
721 Py_DECREF(pyNewval);
|
fazekasgy@0
|
722 }
|
fazekasgy@0
|
723 }
|
fazekasgy@0
|
724
|
fazekasgy@0
|
725 float PyPlugin::getParameter(std::string paramid) const
|
fazekasgy@0
|
726 {
|
cannam@3
|
727 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
728
|
fazekasgy@0
|
729 char method[]="getParameter";
|
fazekasgy@0
|
730 cerr << "[call] " << method << endl;
|
fazekasgy@0
|
731 float rValue = 0.0f;
|
fazekasgy@0
|
732
|
fazekasgy@0
|
733 //Check if the method is implemented in Python
|
fazekasgy@0
|
734 if (PyObject_HasAttrString(m_pyInstance,method)) {
|
fazekasgy@0
|
735
|
fazekasgy@0
|
736 PyObject *pyMethod = PyString_FromString(method);
|
fazekasgy@0
|
737 PyObject *pyParamid = PyString_FromString(paramid.c_str());
|
fazekasgy@0
|
738
|
fazekasgy@0
|
739 //Call the method
|
fazekasgy@0
|
740 PyObject *pyFloat =
|
fazekasgy@0
|
741 PyObject_CallMethodObjArgs(m_pyInstance,pyMethod,pyParamid,NULL);
|
fazekasgy@0
|
742
|
fazekasgy@0
|
743 //Check return type
|
fazekasgy@0
|
744 if (! PyFloat_Check(pyFloat) ) {
|
fazekasgy@0
|
745 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
746 << "] Expected Float return type." << endl;
|
fazekasgy@0
|
747 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@0
|
748 Py_CLEAR(pyFloat);
|
fazekasgy@0
|
749 return rValue;
|
fazekasgy@0
|
750 }
|
fazekasgy@0
|
751
|
fazekasgy@0
|
752 rValue = (float) PyFloat_AS_DOUBLE(pyFloat);
|
fazekasgy@0
|
753
|
fazekasgy@0
|
754 Py_DECREF(pyMethod);
|
fazekasgy@0
|
755 Py_DECREF(pyParamid);
|
fazekasgy@0
|
756 Py_DECREF(pyFloat);
|
fazekasgy@0
|
757 }
|
fazekasgy@0
|
758
|
fazekasgy@0
|
759 return rValue;
|
fazekasgy@0
|
760 }
|
fazekasgy@0
|
761
|
fazekasgy@0
|
762 #ifdef _DEBUG
|
fazekasgy@0
|
763 static int proccounter = 0;
|
fazekasgy@0
|
764 #endif
|
fazekasgy@0
|
765
|
fazekasgy@0
|
766 PyPlugin::FeatureSet
|
fazekasgy@0
|
767 PyPlugin::process(const float *const *inputBuffers,
|
fazekasgy@0
|
768 Vamp::RealTime timestamp)
|
fazekasgy@0
|
769 {
|
cannam@3
|
770 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
771
|
fazekasgy@6
|
772 #ifdef _DEBUG
|
fazekasgy@6
|
773 cerr << "[call] process, frame:" << proccounter << endl;
|
fazekasgy@6
|
774 proccounter++;
|
fazekasgy@6
|
775 #endif
|
fazekasgy@6
|
776
|
fazekasgy@8
|
777 if (m_blockSize == 0 || m_channels == 0) {
|
fazekasgy@0
|
778 cerr << "ERROR: PyPlugin::process: "
|
fazekasgy@0
|
779 << "Plugin has not been initialised" << endl;
|
fazekasgy@0
|
780 return FeatureSet();
|
fazekasgy@0
|
781 }
|
fazekasgy@0
|
782
|
fazekasgy@6
|
783 if (m_processType == not_implemented) {
|
fazekasgy@6
|
784 cerr << "ERROR: In Python plugin [" << m_class
|
fazekasgy@6
|
785 << "] No process implementation found. Returning empty feature set." << endl;
|
fazekasgy@6
|
786 return FeatureSet();
|
fazekasgy@6
|
787 }
|
fazekasgy@0
|
788
|
fazekasgy@6
|
789 string method=PyString_AsString(m_pyProcess);
|
fazekasgy@6
|
790
|
fazekasgy@6
|
791 PyObject *pyOutputList = NULL;
|
fazekasgy@0
|
792
|
fazekasgy@6
|
793 /*new numPy support*/
|
fazekasgy@6
|
794 if (m_processType == numpyProcess) {
|
fazekasgy@8
|
795
|
fazekasgy@8
|
796 //create a list of buffers
|
fazekasgy@8
|
797 PyObject *pyChannelList = PyList_New((Py_ssize_t) m_channels);
|
fazekasgy@8
|
798 for (size_t i=0; i < m_channels; ++i) {
|
fazekasgy@6
|
799
|
fazekasgy@8
|
800 //Expose memory using the Buffer Interface of C/API
|
fazekasgy@8
|
801 //This will virtually pass a pointer which can be
|
fazekasgy@8
|
802 //recasted in Python code as float or complex array
|
fazekasgy@8
|
803 PyObject *pyBuffer = PyBuffer_FromMemory
|
fazekasgy@8
|
804 ((void *) (float *) inputBuffers[i],
|
fazekasgy@8
|
805 (Py_ssize_t) sizeof(float) * m_blockSize);
|
fazekasgy@6
|
806
|
fazekasgy@8
|
807 PyList_SET_ITEM(pyChannelList, (Py_ssize_t) i, pyBuffer);
|
fazekasgy@8
|
808 }
|
fazekasgy@8
|
809
|
fazekasgy@8
|
810 //pass RealTime as frameCount
|
fazekasgy@8
|
811 PyObject *pyLongSample = PyLong_FromLong (
|
fazekasgy@8
|
812 Vamp::RealTime::realTime2Frame
|
fazekasgy@8
|
813 (timestamp, (unsigned int) m_inputSampleRate));
|
fazekasgy@6
|
814
|
fazekasgy@8
|
815 //Call python process (returns new reference)
|
fazekasgy@8
|
816 pyOutputList = PyObject_CallMethodObjArgs
|
fazekasgy@8
|
817 (m_pyInstance,m_pyProcess,pyChannelList,pyLongSample,NULL);
|
fazekasgy@8
|
818
|
fazekasgy@8
|
819 Py_DECREF(pyChannelList);
|
fazekasgy@8
|
820 Py_DECREF(pyLongSample);
|
fazekasgy@6
|
821
|
fazekasgy@6
|
822 }
|
fazekasgy@6
|
823
|
fazekasgy@6
|
824 if (m_processType == legacyProcess) {
|
fazekasgy@0
|
825
|
fazekasgy@8
|
826 //create a list of lists
|
fazekasgy@8
|
827 PyObject *pyChannelList = PyList_New((Py_ssize_t) m_channels);
|
fazekasgy@8
|
828 for (size_t i=0; i < m_channels; ++i) {
|
fazekasgy@0
|
829
|
fazekasgy@8
|
830 //Declare new list object
|
fazekasgy@8
|
831 PyObject *pyFloat, *pyList;
|
fazekasgy@8
|
832 pyList = PyList_New((Py_ssize_t) m_blockSize);
|
fazekasgy@8
|
833
|
fazekasgy@8
|
834 //Pack samples into a Python List Object
|
fazekasgy@8
|
835 //pyFloat types will always be new references,
|
fazekasgy@8
|
836 //these will be discarded when the list is deallocated
|
fazekasgy@8
|
837 for (size_t j = 0; j < m_blockSize; ++j) {
|
fazekasgy@8
|
838 pyFloat=PyFloat_FromDouble(
|
fazekasgy@8
|
839 (double) inputBuffers[i][j]);
|
fazekasgy@8
|
840 PyList_SET_ITEM(pyList, (Py_ssize_t) j, pyFloat);
|
fazekasgy@8
|
841 }
|
fazekasgy@8
|
842 PyList_SET_ITEM(pyChannelList, (Py_ssize_t) i, pyList);
|
fazekasgy@8
|
843 }
|
fazekasgy@8
|
844
|
fazekasgy@8
|
845 //pass RealTime as frameCount
|
fazekasgy@8
|
846 PyObject *pyLongSample = PyLong_FromLong (
|
fazekasgy@8
|
847 Vamp::RealTime::realTime2Frame
|
fazekasgy@8
|
848 (timestamp, (unsigned int) m_inputSampleRate));
|
fazekasgy@8
|
849
|
fazekasgy@8
|
850 //Call python process (returns new reference)
|
fazekasgy@8
|
851 pyOutputList = PyObject_CallMethodObjArgs
|
fazekasgy@8
|
852 (m_pyInstance,m_pyProcess,pyChannelList,pyLongSample,NULL);
|
fazekasgy@8
|
853
|
fazekasgy@8
|
854 Py_DECREF(pyChannelList);
|
fazekasgy@8
|
855 Py_DECREF(pyLongSample);
|
fazekasgy@8
|
856
|
fazekasgy@0
|
857 }
|
fazekasgy@6
|
858
|
fazekasgy@8
|
859 //return nothing
|
fazekasgy@8
|
860 //Py_CLEAR(pyOutputList);
|
fazekasgy@8
|
861 //return FeatureSet();
|
fazekasgy@0
|
862
|
fazekasgy@0
|
863 //Check return type
|
fazekasgy@0
|
864 if (pyOutputList == NULL || !PyList_Check(pyOutputList) ) {
|
fazekasgy@0
|
865 if (pyOutputList == NULL) {
|
fazekasgy@0
|
866 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
867 << "] Unexpected result." << endl;
|
fazekasgy@0
|
868 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@0
|
869 } else {
|
fazekasgy@0
|
870 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
871 << "] Expected List return type." << endl;
|
fazekasgy@0
|
872 }
|
fazekasgy@0
|
873 Py_CLEAR(pyOutputList);
|
fazekasgy@0
|
874 return FeatureSet();
|
fazekasgy@0
|
875 }
|
fazekasgy@0
|
876
|
fazekasgy@0
|
877 // Py_DECREF(pyList);
|
fazekasgy@0
|
878 // This appears to be tracked by the cyclic garbage collector
|
fazekasgy@0
|
879 // hence decrefing produces GC error
|
fazekasgy@0
|
880 #ifdef _DEBUG
|
fazekasgy@0
|
881 cerr << "Process Returned Features" << endl;
|
fazekasgy@0
|
882 #endif
|
fazekasgy@0
|
883 // These will ALL be borrowed references
|
fazekasgy@0
|
884 PyObject *pyFeatureList, *pyDict, *pyKey, *pyValue;
|
fazekasgy@0
|
885
|
fazekasgy@0
|
886 FeatureSet returnFeatures;
|
fazekasgy@0
|
887
|
fazekasgy@0
|
888 //Parse Output List for each element (FeatureSet)
|
fazekasgy@0
|
889 for (Py_ssize_t i = 0;
|
fazekasgy@0
|
890 i < PyList_GET_SIZE(pyOutputList); ++i) {
|
fazekasgy@0
|
891 //cerr << "output (FeatureSet): " << i << endl;
|
fazekasgy@0
|
892
|
fazekasgy@0
|
893 //Get i-th FeatureList (Borrowed Reference)
|
fazekasgy@0
|
894 pyFeatureList = PyList_GET_ITEM(pyOutputList,i);
|
fazekasgy@0
|
895
|
fazekasgy@0
|
896 //Parse FeatureList for each element (Feature)
|
fazekasgy@0
|
897 for (Py_ssize_t j = 0; j < PyList_GET_SIZE(pyFeatureList); ++j) {
|
fazekasgy@0
|
898 //cerr << "element (FeatureList): " << j << endl;
|
fazekasgy@0
|
899
|
fazekasgy@0
|
900 //Get j-th Feature (Borrowed Reference)
|
fazekasgy@0
|
901 pyDict = PyList_GET_ITEM(pyFeatureList,j);
|
fazekasgy@0
|
902
|
fazekasgy@0
|
903 //We only care about dictionaries holding a Feature struct
|
fazekasgy@0
|
904 if ( !PyDict_Check(pyDict) ) continue;
|
fazekasgy@0
|
905
|
fazekasgy@0
|
906 Py_ssize_t pyPos = NULL;
|
fazekasgy@0
|
907 bool emptyFeature = true;
|
fazekasgy@0
|
908 Feature feature;
|
fazekasgy@0
|
909
|
fazekasgy@0
|
910 //process::Python Sequence Iterator for dictionary
|
fazekasgy@0
|
911 while (PyDict_Next(pyDict, &pyPos, &pyKey, &pyValue))
|
fazekasgy@0
|
912 {
|
fazekasgy@0
|
913 emptyFeature = false;
|
fazekasgy@0
|
914 switch (ffKeys[PyString_AsString(pyKey)])
|
fazekasgy@0
|
915 {
|
cannam@18
|
916 case unknown:
|
cannam@18
|
917 cerr << "Unknown key in Vamp FeatureSet: "
|
fazekasgy@0
|
918 << PyString_AsString(pyKey) << endl;
|
fazekasgy@0
|
919 break;
|
fazekasgy@0
|
920 case hasTimestamp:
|
fazekasgy@0
|
921 feature.hasTimestamp = (bool) PyInt_AS_LONG(pyValue);
|
fazekasgy@0
|
922 break;
|
fazekasgy@0
|
923 case timeStamp:
|
fazekasgy@8
|
924 feature.timestamp =
|
fazekasgy@8
|
925 Vamp::RealTime::frame2RealTime(
|
fazekasgy@8
|
926 PyLong_AsLong(pyValue),
|
fazekasgy@8
|
927 (unsigned int) m_inputSampleRate );
|
fazekasgy@8
|
928 #ifdef _DEBUG
|
fazekasgy@8
|
929 cerr << "Timestamp: "
|
fazekasgy@8
|
930 << (long)PyLong_AsLong(pyValue) << ", ->"
|
fazekasgy@8
|
931 << feature.timestamp.toString() << endl;
|
fazekasgy@8
|
932 #endif
|
fazekasgy@0
|
933 break;
|
cannam@18
|
934 case hasDuration:
|
cannam@18
|
935 feature.hasDuration = (bool) PyInt_AS_LONG(pyValue);
|
cannam@18
|
936 break;
|
cannam@18
|
937 case duration:
|
cannam@18
|
938 feature.duration =
|
cannam@18
|
939 Vamp::RealTime::frame2RealTime(
|
cannam@18
|
940 PyLong_AsLong(pyValue),
|
cannam@18
|
941 (unsigned int) m_inputSampleRate );
|
cannam@18
|
942 #ifdef _DEBUG
|
cannam@18
|
943 cerr << "Duration: "
|
cannam@18
|
944 << (long)PyLong_AsLong(pyValue) << ", ->"
|
cannam@18
|
945 << feature.duration.toString() << endl;
|
cannam@18
|
946 #endif
|
cannam@18
|
947 break;
|
fazekasgy@0
|
948 case values:
|
fazekasgy@0
|
949 feature.values = PyList_As_FloatVector(pyValue);
|
fazekasgy@0
|
950 break;
|
fazekasgy@0
|
951 case label:
|
fazekasgy@0
|
952 feature.label = PyString_AsString(pyValue);
|
fazekasgy@0
|
953 break;
|
fazekasgy@0
|
954 default :
|
cannam@18
|
955 cerr << "Invalid key in Vamp FeatureSet: "
|
fazekasgy@0
|
956 << PyString_AsString(pyKey) << endl;
|
fazekasgy@0
|
957 } // switch
|
fazekasgy@0
|
958
|
fazekasgy@0
|
959 } // while
|
fazekasgy@0
|
960 if (emptyFeature) cerr << "Warning: This feature is empty or badly formatted." << endl;
|
fazekasgy@0
|
961 else returnFeatures[i].push_back(feature);
|
fazekasgy@0
|
962
|
fazekasgy@0
|
963 }// for j = FeatureList
|
fazekasgy@0
|
964
|
fazekasgy@0
|
965 }//for i = FeatureSet
|
fazekasgy@0
|
966 Py_CLEAR(pyOutputList);
|
fazekasgy@0
|
967 return returnFeatures;
|
fazekasgy@0
|
968 }
|
fazekasgy@0
|
969
|
fazekasgy@0
|
970
|
fazekasgy@0
|
971
|
fazekasgy@0
|
972 PyPlugin::FeatureSet
|
fazekasgy@0
|
973 PyPlugin::getRemainingFeatures()
|
fazekasgy@0
|
974 {
|
cannam@3
|
975 MutexLocker locker(&m_pythonInterpreterMutex);
|
cannam@3
|
976
|
fazekasgy@0
|
977 static char method[]="getRemainingFeatures";
|
fazekasgy@0
|
978 cerr << "[call] " << method << endl;
|
fazekasgy@0
|
979
|
fazekasgy@0
|
980 //check if the method is implemented
|
fazekasgy@0
|
981 if ( ! PyObject_HasAttrString(m_pyInstance,method) ) {
|
fazekasgy@0
|
982 return FeatureSet();
|
fazekasgy@0
|
983 }
|
fazekasgy@0
|
984
|
fazekasgy@0
|
985 PyObject *pyMethod = PyString_FromString(method);
|
fazekasgy@0
|
986
|
fazekasgy@0
|
987 PyObject *pyOutputList =
|
fazekasgy@0
|
988 PyObject_CallMethod(m_pyInstance,method, NULL);
|
fazekasgy@0
|
989
|
fazekasgy@0
|
990 //Check return type
|
fazekasgy@0
|
991 if (pyOutputList == NULL || !PyList_Check(pyOutputList) ) {
|
fazekasgy@0
|
992 if (pyOutputList == NULL) {
|
fazekasgy@0
|
993 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
994 << "] Unexpected result." << endl;
|
fazekasgy@0
|
995 if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); }
|
fazekasgy@0
|
996 } else {
|
fazekasgy@0
|
997 cerr << "ERROR: In Python plugin [" << m_class << "::" << method
|
fazekasgy@0
|
998 << "] Expected List return type." << endl;
|
fazekasgy@0
|
999 }
|
fazekasgy@0
|
1000 Py_CLEAR(pyMethod);
|
fazekasgy@0
|
1001 Py_CLEAR(pyOutputList);
|
fazekasgy@0
|
1002 return FeatureSet();
|
fazekasgy@0
|
1003 }
|
fazekasgy@0
|
1004 Py_DECREF(pyMethod);
|
fazekasgy@0
|
1005
|
fazekasgy@0
|
1006 PyObject *pyFeatureList, *pyDict, *pyKey, *pyValue;
|
fazekasgy@0
|
1007 FeatureSet returnFeatures;
|
fazekasgy@8
|
1008
|
fazekasgy@8
|
1009 //iterate through list of outputs
|
fazekasgy@0
|
1010 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(pyOutputList); ++i) {
|
fazekasgy@0
|
1011
|
fazekasgy@0
|
1012 pyFeatureList = PyList_GET_ITEM(pyOutputList,i);
|
fazekasgy@0
|
1013
|
fazekasgy@8
|
1014 //iterate list of Features
|
fazekasgy@0
|
1015 for (Py_ssize_t j = 0; j < PyList_GET_SIZE(pyFeatureList); ++j) {
|
fazekasgy@8
|
1016 #ifdef _DEBUG
|
fazekasgy@8
|
1017 cerr << "feature: " << j << endl;
|
fazekasgy@8
|
1018 #endif
|
fazekasgy@0
|
1019 pyDict = PyList_GET_ITEM(pyFeatureList,j);
|
fazekasgy@0
|
1020
|
fazekasgy@0
|
1021 if ( !PyDict_Check(pyDict) ) continue;
|
fazekasgy@0
|
1022
|
fazekasgy@0
|
1023 Py_ssize_t pyPos = NULL;
|
fazekasgy@0
|
1024 bool emptyFeature = true;
|
fazekasgy@0
|
1025 Feature feature;
|
fazekasgy@0
|
1026
|
fazekasgy@0
|
1027 while (PyDict_Next(pyDict, &pyPos, &pyKey, &pyValue))
|
fazekasgy@0
|
1028 {
|
fazekasgy@0
|
1029 emptyFeature = false;
|
fazekasgy@0
|
1030 switch (ffKeys[PyString_AsString(pyKey)])
|
fazekasgy@0
|
1031 {
|
cannam@18
|
1032 case unknown :
|
cannam@18
|
1033 cerr << "Unknown key in Vamp FeatureSet: "
|
fazekasgy@0
|
1034 << PyString_AsString(pyKey) << endl;
|
fazekasgy@0
|
1035 break;
|
fazekasgy@0
|
1036 case hasTimestamp:
|
fazekasgy@0
|
1037 feature.hasTimestamp = (bool) PyInt_AS_LONG(pyValue);
|
fazekasgy@0
|
1038 break;
|
fazekasgy@0
|
1039 case timeStamp:
|
fazekasgy@0
|
1040 feature.timestamp =
|
fazekasgy@8
|
1041 Vamp::RealTime::frame2RealTime(
|
fazekasgy@8
|
1042 PyLong_AsLong(pyValue),
|
fazekasgy@8
|
1043 (unsigned int) m_inputSampleRate );
|
fazekasgy@8
|
1044 #ifdef _DEBUG
|
fazekasgy@8
|
1045 cerr << "Timestamp: "
|
fazekasgy@8
|
1046 << (long)PyLong_AsLong(pyValue) << ", ->"
|
fazekasgy@8
|
1047 << feature.timestamp.toString() << endl;
|
fazekasgy@8
|
1048 #endif
|
fazekasgy@0
|
1049 break;
|
cannam@18
|
1050 case hasDuration:
|
cannam@18
|
1051 feature.hasDuration = (bool) PyInt_AS_LONG(pyValue);
|
cannam@18
|
1052 break;
|
cannam@18
|
1053 case duration:
|
cannam@18
|
1054 feature.duration =
|
cannam@18
|
1055 Vamp::RealTime::frame2RealTime(
|
cannam@18
|
1056 PyLong_AsLong(pyValue),
|
cannam@18
|
1057 (unsigned int) m_inputSampleRate );
|
cannam@18
|
1058 #ifdef _DEBUG
|
cannam@18
|
1059 cerr << "Duration: "
|
cannam@18
|
1060 << (long)PyLong_AsLong(pyValue) << ", ->"
|
cannam@18
|
1061 << feature.duration.toString() << endl;
|
cannam@18
|
1062 #endif
|
cannam@18
|
1063 break;
|
fazekasgy@0
|
1064 case values:
|
fazekasgy@0
|
1065 feature.values = PyList_As_FloatVector(pyValue);
|
fazekasgy@0
|
1066 break;
|
fazekasgy@0
|
1067 case label:
|
fazekasgy@0
|
1068 feature.label = PyString_AsString(pyValue);
|
fazekasgy@0
|
1069 break;
|
fazekasgy@0
|
1070 } // switch
|
fazekasgy@0
|
1071 } // while
|
fazekasgy@0
|
1072 if (emptyFeature) cerr << "Warning: This feature is empty or badly formatted." << endl;
|
fazekasgy@0
|
1073 else returnFeatures[i].push_back(feature);
|
fazekasgy@0
|
1074 }// for j
|
fazekasgy@0
|
1075 }//for i
|
fazekasgy@0
|
1076 Py_CLEAR(pyOutputList);
|
fazekasgy@0
|
1077 return returnFeatures;
|
fazekasgy@0
|
1078 }
|
fazekasgy@0
|
1079
|
fazekasgy@6
|
1080 bool
|
fazekasgy@6
|
1081 PyPlugin::initMaps() const
|
fazekasgy@6
|
1082 {
|
fazekasgy@6
|
1083
|
fazekasgy@6
|
1084 if (isMapInitialised) return true;
|
fazekasgy@6
|
1085
|
cannam@18
|
1086 outKeys["identifier"] = o::identifier;
|
cannam@18
|
1087 outKeys["name"] = o::name;
|
cannam@18
|
1088 outKeys["description"] = o::description;
|
cannam@18
|
1089 outKeys["unit"] = o::unit;
|
cannam@18
|
1090 outKeys["hasFixedBinCount"] = o::hasFixedBinCount;
|
cannam@18
|
1091 outKeys["binCount"] = o::binCount;
|
cannam@18
|
1092 outKeys["binNames"] = o::binNames;
|
cannam@18
|
1093 outKeys["hasKnownExtents"] = o::hasKnownExtents;
|
cannam@18
|
1094 outKeys["minValue"] = o::minValue;
|
cannam@18
|
1095 outKeys["maxValue"] = o::maxValue;
|
cannam@18
|
1096 outKeys["isQuantized"] = o::isQuantized;
|
cannam@18
|
1097 outKeys["quantizeStep"] = o::quantizeStep;
|
cannam@18
|
1098 outKeys["sampleType"] = o::sampleType;
|
cannam@18
|
1099 outKeys["sampleRate"] = o::sampleRate;
|
cannam@18
|
1100 outKeys["hasDuration"] = o::hasDuration;
|
fazekasgy@6
|
1101
|
fazekasgy@6
|
1102 sampleKeys["OneSamplePerStep"] = OneSamplePerStep;
|
fazekasgy@6
|
1103 sampleKeys["FixedSampleRate"] = FixedSampleRate;
|
fazekasgy@6
|
1104 sampleKeys["VariableSampleRate"] = VariableSampleRate;
|
fazekasgy@6
|
1105
|
fazekasgy@6
|
1106 ffKeys["hasTimestamp"] = hasTimestamp;
|
fazekasgy@6
|
1107 ffKeys["timeStamp"] = timeStamp;
|
cannam@18
|
1108 ffKeys["hasDuration"] = hasDuration;
|
cannam@18
|
1109 ffKeys["duration"] = duration;
|
fazekasgy@6
|
1110 ffKeys["values"] = values;
|
fazekasgy@6
|
1111 ffKeys["label"] = label;
|
fazekasgy@6
|
1112
|
fazekasgy@6
|
1113 parmKeys["identifier"] = p::identifier;
|
fazekasgy@6
|
1114 parmKeys["name"] = p::name;
|
fazekasgy@6
|
1115 parmKeys["description"] = p::description;
|
fazekasgy@6
|
1116 parmKeys["unit"] = p::unit;
|
fazekasgy@6
|
1117 parmKeys["minValue"] = p::minValue;
|
fazekasgy@6
|
1118 parmKeys["maxValue"] = p::maxValue;
|
fazekasgy@6
|
1119 parmKeys["defaultValue"] = p::defaultValue;
|
fazekasgy@6
|
1120 parmKeys["isQuantized"] = p::isQuantized;
|
cannam@22
|
1121 parmKeys["quantizeStep"] = p::quantizeStep;
|
fazekasgy@6
|
1122
|
fazekasgy@6
|
1123 isMapInitialised = true;
|
fazekasgy@6
|
1124 return true;
|
fazekasgy@6
|
1125 }
|
fazekasgy@6
|
1126
|
fazekasgy@6
|
1127
|
fazekasgy@6
|
1128 //missing API helper: convert Python list to C++ vector of strings
|
fazekasgy@6
|
1129 //TODO: these could be templates if we need more of this kind
|
fazekasgy@6
|
1130 std::vector<std::string>
|
fazekasgy@6
|
1131 PyPlugin::PyList_To_StringVector (PyObject *inputList) const {
|
fazekasgy@6
|
1132
|
fazekasgy@6
|
1133 std::vector<std::string> Output;
|
fazekasgy@6
|
1134 std::string ListElement;
|
fazekasgy@6
|
1135 PyObject *pyString = NULL;
|
fazekasgy@6
|
1136
|
fazekasgy@6
|
1137 if (!PyList_Check(inputList)) return Output;
|
fazekasgy@6
|
1138
|
fazekasgy@6
|
1139 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(inputList); ++i) {
|
fazekasgy@6
|
1140 //Get next list item (Borrowed Reference)
|
fazekasgy@6
|
1141 pyString = PyList_GET_ITEM(inputList,i);
|
fazekasgy@6
|
1142 ListElement = (string) PyString_AsString(PyObject_Str(pyString));
|
fazekasgy@6
|
1143 Output.push_back(ListElement);
|
fazekasgy@6
|
1144 }
|
fazekasgy@6
|
1145 return Output;
|
fazekasgy@6
|
1146 }
|
fazekasgy@6
|
1147
|
fazekasgy@6
|
1148 //missing API helper: convert Python list to C++ vector of floats
|
fazekasgy@6
|
1149 std::vector<float>
|
fazekasgy@6
|
1150 PyPlugin::PyList_As_FloatVector (PyObject *inputList) const {
|
fazekasgy@6
|
1151
|
fazekasgy@6
|
1152 std::vector<float> Output;
|
fazekasgy@6
|
1153 float ListElement;
|
fazekasgy@6
|
1154 PyObject *pyFloat = NULL;
|
fazekasgy@6
|
1155
|
fazekasgy@6
|
1156 if (!PyList_Check(inputList)) return Output;
|
fazekasgy@6
|
1157
|
fazekasgy@6
|
1158 for (Py_ssize_t k = 0; k < PyList_GET_SIZE(inputList); ++k) {
|
fazekasgy@6
|
1159 //Get next list item (Borrowed Reference)
|
fazekasgy@6
|
1160 pyFloat = PyList_GET_ITEM(inputList,k);
|
fazekasgy@6
|
1161 ListElement = (float) PyFloat_AS_DOUBLE(pyFloat);
|
fazekasgy@8
|
1162 #ifdef _DEBUG
|
fazekasgy@8
|
1163 cerr << "value: " << ListElement << endl;
|
fazekasgy@8
|
1164 #endif
|
fazekasgy@6
|
1165 Output.push_back(ListElement);
|
fazekasgy@6
|
1166 }
|
fazekasgy@6
|
1167
|
fazekasgy@6
|
1168 return Output;
|
fazekasgy@6
|
1169 }
|
fazekasgy@6
|
1170
|
fazekasgy@6
|
1171 /* TODO: find out why this produces error, also
|
fazekasgy@6
|
1172 do sg more clever about handling RealTime
|
fazekasgy@6
|
1173 Vamp::RealTime
|
fazekasgy@6
|
1174 PyFrame_As_RealTime (PyObject *frameNo,size_t inputSampleRate) {
|
fazekasgy@6
|
1175 Vamp::RealTime result =
|
fazekasgy@6
|
1176 Vamp::RealTime::frame2RealTime((size_t)PyInt_AS_LONG(frameNo), inputSampleRate);
|
fazekasgy@6
|
1177 return result;
|
fazekasgy@6
|
1178 }
|
fazekasgy@6
|
1179 */
|
fazekasgy@6
|
1180
|