Chris@0
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@0
|
2
|
Chris@0
|
3 //include for python extension module: must be first
|
Chris@0
|
4 #include <Python.h>
|
Chris@14
|
5
|
Chris@14
|
6 // define a unique API pointer
|
Chris@14
|
7 #define PY_ARRAY_UNIQUE_SYMBOL VAMPY_ARRAY_API
|
Chris@14
|
8 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
|
Chris@14
|
9 #include "numpy/arrayobject.h"
|
Chris@14
|
10
|
Chris@0
|
11 #include <vampyhost.h>
|
Chris@12
|
12
|
Chris@12
|
13 #define HAVE_NUMPY 1 // Required
|
Chris@12
|
14
|
Chris@0
|
15 //includes for vamp host
|
Chris@1
|
16 #include "vamp-hostsdk/Plugin.h"
|
Chris@1
|
17 #include "vamp-hostsdk/PluginHostAdapter.h"
|
Chris@1
|
18 #include "vamp-hostsdk/PluginChannelAdapter.h"
|
Chris@1
|
19 #include "vamp-hostsdk/PluginInputDomainAdapter.h"
|
Chris@1
|
20 #include "vamp-hostsdk/PluginLoader.h"
|
Chris@16
|
21
|
Chris@16
|
22 #include "PyTypeConversions.h"
|
Chris@16
|
23 #include "PyRealTime.h"
|
Chris@0
|
24
|
Chris@0
|
25 #include <iostream>
|
Chris@0
|
26 #include <fstream>
|
Chris@0
|
27 #include <set>
|
Chris@0
|
28 #include <sndfile.h>
|
Chris@0
|
29
|
Chris@0
|
30 #include <cstring>
|
Chris@0
|
31 #include <cstdlib>
|
Chris@0
|
32 #include <string>
|
Chris@0
|
33
|
Chris@0
|
34 #include <cmath>
|
Chris@0
|
35
|
Chris@0
|
36 using namespace std;
|
Chris@0
|
37 using namespace Vamp;
|
Chris@0
|
38
|
Chris@0
|
39 using Vamp::Plugin;
|
Chris@0
|
40 using Vamp::PluginHostAdapter;
|
Chris@0
|
41 using Vamp::RealTime;
|
Chris@0
|
42 using Vamp::HostExt::PluginLoader;
|
Chris@0
|
43
|
Chris@0
|
44 #define HOST_VERSION "1.1"
|
Chris@0
|
45
|
Chris@16
|
46 // structure for holding plugin instance data
|
Chris@21
|
47 struct PyPluginObject
|
Chris@16
|
48 {
|
Chris@21
|
49 PyObject_HEAD
|
Chris@21
|
50 /*
|
Chris@16
|
51 PyPluginData(string k, Plugin *p, float rate) :
|
Chris@16
|
52 key(k),
|
Chris@16
|
53 plugin(p),
|
Chris@16
|
54 inputSampleRate(rate),
|
Chris@16
|
55 isInitialised(false),
|
Chris@16
|
56 channels(0),
|
Chris@16
|
57 blockSize(0),
|
Chris@16
|
58 stepSize(0) {
|
Chris@16
|
59 }
|
Chris@21
|
60 */
|
Chris@21
|
61 string *key;
|
Chris@16
|
62 Plugin *plugin;
|
Chris@16
|
63 float inputSampleRate;
|
Chris@16
|
64 bool isInitialised;
|
Chris@16
|
65 size_t channels;
|
Chris@16
|
66 size_t blockSize;
|
Chris@16
|
67 size_t stepSize;
|
Chris@21
|
68 static PyPluginObject *create_internal();
|
Chris@16
|
69 };
|
Chris@0
|
70
|
Chris@21
|
71 PyAPI_DATA(PyTypeObject) Plugin_Type;
|
Chris@21
|
72 #define PyPlugin_Check(v) PyObject_TypeCheck(v, &Plugin_Type)
|
Chris@21
|
73
|
Chris@21
|
74 static void
|
Chris@21
|
75 PyPluginObject_dealloc(PyPluginObject *self)
|
Chris@21
|
76 {
|
Chris@21
|
77 cerr << "PyPluginObject_dealloc" << endl;
|
Chris@21
|
78 delete self->key;
|
Chris@21
|
79 delete self->plugin;
|
Chris@21
|
80 PyObject_Del(self);
|
Chris@21
|
81 }
|
Chris@21
|
82
|
Chris@0
|
83 /* MODULE HELPER FUNCTIONS */
|
Chris@2
|
84 PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!!
|
Chris@0
|
85
|
Chris@21
|
86 PyPluginObject *
|
Chris@21
|
87 getPluginObject(PyObject *pyPluginHandle)
|
Chris@21
|
88 {
|
Chris@21
|
89 cerr << "getPluginObject" << endl;
|
Chris@0
|
90
|
Chris@21
|
91 PyPluginObject *pd = 0;
|
Chris@21
|
92 if (PyPlugin_Check(pyPluginHandle)) {
|
Chris@21
|
93 pd = (PyPluginObject *)pyPluginHandle;
|
Chris@16
|
94 }
|
Chris@16
|
95 if (!pd || !pd->plugin) {
|
Chris@16
|
96 PyErr_SetString(PyExc_AttributeError,
|
Chris@16
|
97 "Invalid or already deleted plugin handle.");
|
Chris@16
|
98 return 0;
|
Chris@0
|
99 } else {
|
Chris@16
|
100 return pd;
|
Chris@0
|
101 }
|
Chris@0
|
102 }
|
Chris@0
|
103
|
Chris@0
|
104 static PyObject *
|
Chris@0
|
105 vampyhost_enumeratePlugins(PyObject *self, PyObject *args)
|
Chris@0
|
106 {
|
Chris@21
|
107 cerr << "vampyhost_enumeratePlugins" << endl;
|
Chris@21
|
108
|
Chris@0
|
109 PluginLoader *loader = PluginLoader::getInstance();
|
Chris@0
|
110 vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
|
Chris@15
|
111 PyTypeConversions conv;
|
Chris@15
|
112 return conv.PyValue_From_StringVector(plugins);
|
Chris@0
|
113 }
|
Chris@0
|
114
|
Chris@15
|
115 static PyObject *
|
Chris@15
|
116 vampyhost_getPluginPath(PyObject *self, PyObject *args)
|
Chris@15
|
117 {
|
Chris@21
|
118 cerr << "vampyhost_getPluginPath" << endl;
|
Chris@21
|
119
|
Chris@15
|
120 vector<string> path = PluginHostAdapter::getPluginPath();
|
Chris@15
|
121 PyTypeConversions conv;
|
Chris@15
|
122 return conv.PyValue_From_StringVector(path);
|
Chris@15
|
123 }
|
Chris@0
|
124
|
Chris@15
|
125 static string toPluginKey(PyObject *pyPluginKey)
|
Chris@0
|
126 {
|
Chris@21
|
127 cerr << "toPluginKey" << endl;
|
Chris@21
|
128
|
Chris@0
|
129 //convert to stl string
|
Chris@0
|
130 string pluginKey(PyString_AS_STRING(pyPluginKey));
|
Chris@0
|
131
|
Chris@0
|
132 //check pluginKey Validity
|
Chris@0
|
133 string::size_type ki = pluginKey.find(':');
|
Chris@0
|
134 if (ki == string::npos) {
|
Chris@0
|
135 PyErr_SetString(PyExc_TypeError,
|
Chris@15
|
136 "Plugin key must be of the form library:identifier");
|
Chris@15
|
137 return "";
|
Chris@0
|
138 }
|
Chris@0
|
139
|
Chris@15
|
140 return pluginKey;
|
Chris@15
|
141 }
|
Chris@15
|
142
|
Chris@15
|
143 static PyObject *
|
Chris@15
|
144 vampyhost_getLibraryFor(PyObject *self, PyObject *args)
|
Chris@15
|
145 {
|
Chris@21
|
146 cerr << "vampyhost_getLibraryFor" << endl;
|
Chris@21
|
147
|
Chris@15
|
148 PyObject *pyPluginKey;
|
Chris@15
|
149
|
Chris@15
|
150 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
|
Chris@15
|
151 PyErr_SetString(PyExc_TypeError,
|
Chris@15
|
152 "getLibraryPathForPlugin() takes plugin key (string) argument");
|
Chris@16
|
153 return 0; }
|
Chris@15
|
154
|
Chris@15
|
155 string pluginKey = toPluginKey(pyPluginKey);
|
Chris@16
|
156 if (pluginKey == "") return 0;
|
Chris@15
|
157
|
Chris@0
|
158 PluginLoader *loader = PluginLoader::getInstance();
|
Chris@0
|
159 string path = loader->getLibraryPathForPlugin(pluginKey);
|
Chris@0
|
160 PyObject *pyPath = PyString_FromString(path.c_str());
|
Chris@0
|
161 return pyPath;
|
Chris@0
|
162 }
|
Chris@0
|
163
|
Chris@0
|
164 static PyObject *
|
Chris@0
|
165 vampyhost_getPluginCategory(PyObject *self, PyObject *args)
|
Chris@0
|
166 {
|
Chris@21
|
167 cerr << "vampyhost_getPluginCategory" << endl;
|
Chris@21
|
168
|
Chris@0
|
169 PyObject *pyPluginKey;
|
Chris@0
|
170
|
Chris@0
|
171 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
|
Chris@0
|
172 PyErr_SetString(PyExc_TypeError,
|
Chris@15
|
173 "getPluginCategory() takes plugin key (string) argument");
|
Chris@16
|
174 return 0; }
|
Chris@0
|
175
|
Chris@15
|
176 string pluginKey = toPluginKey(pyPluginKey);
|
Chris@16
|
177 if (pluginKey == "") return 0;
|
Chris@0
|
178
|
Chris@0
|
179 PluginLoader *loader = PluginLoader::getInstance();
|
luis@7
|
180 PluginLoader::PluginCategoryHierarchy
|
Chris@0
|
181 category = loader->getPluginCategory(pluginKey);
|
Chris@0
|
182
|
Chris@15
|
183 PyTypeConversions conv;
|
Chris@15
|
184 return conv.PyValue_From_StringVector(category);
|
Chris@0
|
185 }
|
Chris@0
|
186
|
Chris@0
|
187 static PyObject *
|
Chris@0
|
188 vampyhost_getOutputList(PyObject *self, PyObject *args)
|
Chris@0
|
189 {
|
Chris@21
|
190 cerr << "vampyhost_getOutputList" << endl;
|
Chris@21
|
191
|
Chris@16
|
192 PyObject *keyOrHandle;
|
Chris@15
|
193 Plugin::OutputList outputs;
|
Chris@0
|
194
|
Chris@16
|
195 if (!PyArg_ParseTuple(args, "O", &keyOrHandle)) {
|
Chris@0
|
196 PyErr_SetString(PyExc_TypeError,
|
Chris@15
|
197 "getOutputList() takes plugin handle (object) or plugin key (string) argument");
|
Chris@16
|
198 return 0;
|
Chris@0
|
199 }
|
Chris@0
|
200
|
Chris@16
|
201 if (PyString_Check(keyOrHandle) ) {
|
Chris@0
|
202
|
Chris@15
|
203 // we have a plugin key
|
Chris@0
|
204
|
Chris@16
|
205 string pluginKey = toPluginKey(keyOrHandle);
|
Chris@16
|
206 if (pluginKey == "") return 0;
|
Chris@15
|
207
|
Chris@15
|
208 PluginLoader *loader = PluginLoader::getInstance();
|
Chris@15
|
209
|
Chris@15
|
210 Plugin *plugin = loader->loadPlugin
|
Chris@15
|
211 (pluginKey, 48000, PluginLoader::ADAPT_ALL_SAFE);
|
Chris@15
|
212 if (!plugin) {
|
Chris@15
|
213 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
|
Chris@15
|
214 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
|
Chris@16
|
215 return 0;
|
Chris@15
|
216 }
|
Chris@15
|
217
|
Chris@15
|
218 outputs = plugin->getOutputDescriptors();
|
Chris@15
|
219
|
Chris@15
|
220 delete plugin;
|
Chris@15
|
221
|
Chris@0
|
222 } else {
|
luis@7
|
223
|
Chris@15
|
224 // we have a loaded plugin handle
|
Chris@15
|
225
|
Chris@21
|
226 PyPluginObject *pd = getPluginObject(keyOrHandle);
|
Chris@16
|
227 if (!pd) return 0;
|
Chris@0
|
228
|
Chris@16
|
229 outputs = pd->plugin->getOutputDescriptors();
|
luis@7
|
230 }
|
luis@7
|
231
|
Chris@0
|
232 PyObject *pyList = PyList_New(outputs.size());
|
Chris@0
|
233
|
Chris@0
|
234 for (size_t i = 0; i < outputs.size(); ++i) {
|
luis@7
|
235 PyObject *pyOutputId =
|
Chris@0
|
236 PyString_FromString(outputs[i].identifier.c_str());
|
Chris@15
|
237 PyList_SET_ITEM(pyList, i, pyOutputId);
|
Chris@0
|
238 }
|
Chris@0
|
239
|
Chris@0
|
240 return pyList;
|
Chris@0
|
241 }
|
Chris@0
|
242
|
Chris@0
|
243 static PyObject *
|
Chris@0
|
244 vampyhost_loadPlugin(PyObject *self, PyObject *args)
|
Chris@0
|
245 {
|
Chris@21
|
246 cerr << "vampyhost_loadPlugin" << endl;
|
Chris@21
|
247
|
Chris@0
|
248 PyObject *pyPluginKey;
|
Chris@0
|
249 float inputSampleRate;
|
Chris@0
|
250
|
luis@7
|
251 if (!PyArg_ParseTuple(args, "Sf",
|
Chris@0
|
252 &pyPluginKey,
|
Chris@0
|
253 &inputSampleRate)) {
|
Chris@0
|
254 PyErr_SetString(PyExc_TypeError,
|
Chris@20
|
255 "loadPlugin() takes plugin key (string) and sample rate (float) arguments");
|
Chris@16
|
256 return 0; }
|
Chris@0
|
257
|
Chris@15
|
258 string pluginKey = toPluginKey(pyPluginKey);
|
Chris@16
|
259 if (pluginKey == "") return 0;
|
Chris@0
|
260
|
Chris@0
|
261 PluginLoader *loader = PluginLoader::getInstance();
|
luis@7
|
262
|
Chris@15
|
263 Plugin *plugin = loader->loadPlugin(pluginKey, inputSampleRate,
|
Chris@15
|
264 PluginLoader::ADAPT_ALL_SAFE);
|
luis@7
|
265 if (!plugin) {
|
Chris@0
|
266 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
|
luis@7
|
267 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
|
Chris@16
|
268 return 0;
|
luis@7
|
269 }
|
Chris@15
|
270
|
Chris@21
|
271 PyPluginObject *pd = PyPluginObject::create_internal();
|
Chris@21
|
272 pd->key = new string(pluginKey);
|
Chris@21
|
273 pd->plugin = plugin;
|
Chris@21
|
274 pd->inputSampleRate = inputSampleRate;
|
Chris@21
|
275 pd->isInitialised = false;
|
Chris@21
|
276 pd->channels = 0;
|
Chris@21
|
277 pd->blockSize = 0;
|
Chris@21
|
278 pd->stepSize = 0;
|
Chris@21
|
279 return (PyObject *)pd;
|
Chris@0
|
280 }
|
Chris@0
|
281
|
Chris@0
|
282 static PyObject *
|
Chris@0
|
283 vampyhost_unloadPlugin(PyObject *self, PyObject *args)
|
Chris@0
|
284 {
|
Chris@21
|
285 cerr << "vampyhost_unloadPlugin" << endl;
|
Chris@21
|
286
|
Chris@0
|
287 PyObject *pyPluginHandle;
|
Chris@0
|
288
|
Chris@0
|
289 if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) {
|
Chris@0
|
290 PyErr_SetString(PyExc_TypeError,
|
Chris@16
|
291 "unloadPlugin() takes plugin handle (object) argument");
|
Chris@16
|
292 return 0;
|
Chris@16
|
293 }
|
Chris@0
|
294
|
Chris@21
|
295 PyPluginObject *pd = getPluginObject(pyPluginHandle);
|
Chris@16
|
296 if (!pd) return 0;
|
Chris@0
|
297
|
Chris@21
|
298 delete pd->plugin;
|
Chris@21
|
299 pd->plugin = 0; // This is checked by getPluginObject, so we
|
Chris@21
|
300 // attempt to avoid repeated calls from blowing up
|
Chris@0
|
301
|
Chris@21
|
302 return Py_True;
|
Chris@0
|
303 }
|
Chris@0
|
304
|
Chris@0
|
305 static PyObject *
|
Chris@0
|
306 vampyhost_initialise(PyObject *self, PyObject *args)
|
Chris@0
|
307 {
|
Chris@21
|
308 cerr << "vampyhost_initialise" << endl;
|
Chris@21
|
309
|
Chris@0
|
310 PyObject *pyPluginHandle;
|
luis@7
|
311 size_t channels, blockSize, stepSize;
|
Chris@0
|
312
|
luis@7
|
313 if (!PyArg_ParseTuple (args, "Onnn", &pyPluginHandle,
|
luis@7
|
314 (size_t) &channels,
|
luis@7
|
315 (size_t) &stepSize,
|
luis@7
|
316 (size_t) &blockSize))
|
Chris@0
|
317 {
|
Chris@0
|
318 PyErr_SetString(PyExc_TypeError,
|
Chris@17
|
319 "initialise() takes plugin handle (object), channel count, step size, and block size arguments");
|
Chris@16
|
320 return 0;
|
Chris@0
|
321 }
|
Chris@0
|
322
|
Chris@21
|
323 PyPluginObject *pd = getPluginObject(pyPluginHandle);
|
Chris@16
|
324 if (!pd) return 0;
|
Chris@0
|
325
|
Chris@16
|
326 pd->channels = channels;
|
Chris@16
|
327 pd->stepSize = stepSize;
|
Chris@16
|
328 pd->blockSize = blockSize;
|
Chris@0
|
329
|
Chris@16
|
330 if (!pd->plugin->initialise(channels, stepSize, blockSize)) {
|
Chris@17
|
331 cerr << "Failed to initialise native plugin adapter with channels = " << channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << " and ADAPT_ALL_SAFE set" << endl;
|
Chris@0
|
332 PyErr_SetString(PyExc_TypeError,
|
Chris@17
|
333 "Plugin initialization failed");
|
Chris@16
|
334 return 0;
|
Chris@6
|
335 }
|
Chris@0
|
336
|
Chris@16
|
337 pd->isInitialised = true;
|
luis@7
|
338
|
Chris@0
|
339 return Py_True;
|
Chris@0
|
340 }
|
Chris@0
|
341
|
Chris@0
|
342 static PyObject *
|
Chris@18
|
343 vampyhost_reset(PyObject *self, PyObject *args)
|
Chris@18
|
344 {
|
Chris@21
|
345 cerr << "vampyhost_reset" << endl;
|
Chris@21
|
346
|
Chris@18
|
347 PyObject *pyPluginHandle;
|
Chris@18
|
348
|
Chris@18
|
349 if (!PyArg_ParseTuple (args, "O", &pyPluginHandle))
|
Chris@18
|
350 {
|
Chris@18
|
351 PyErr_SetString(PyExc_TypeError,
|
Chris@18
|
352 "initialise() takes plugin handle (object) argument");
|
Chris@18
|
353 return 0;
|
Chris@18
|
354 }
|
Chris@18
|
355
|
Chris@21
|
356 PyPluginObject *pd = getPluginObject(pyPluginHandle);
|
Chris@18
|
357 if (!pd) return 0;
|
Chris@18
|
358
|
Chris@18
|
359 if (!pd->isInitialised) {
|
Chris@18
|
360 PyErr_SetString(PyExc_StandardError,
|
Chris@18
|
361 "Plugin has not been initialised");
|
Chris@18
|
362 return 0;
|
Chris@18
|
363 }
|
Chris@18
|
364
|
Chris@18
|
365 pd->plugin->reset();
|
Chris@18
|
366 return Py_True;
|
Chris@18
|
367 }
|
Chris@18
|
368
|
Chris@18
|
369 static PyObject *
|
Chris@20
|
370 vampyhost_getParameter(PyObject *self, PyObject *args)
|
Chris@20
|
371 {
|
Chris@21
|
372 cerr << "vampyhost_getParameter" << endl;
|
Chris@21
|
373
|
Chris@20
|
374 PyObject *pyPluginHandle;
|
Chris@20
|
375 PyObject *pyParam;
|
Chris@20
|
376
|
Chris@20
|
377 if (!PyArg_ParseTuple(args, "OS", &pyPluginHandle, &pyParam)) {
|
Chris@20
|
378 PyErr_SetString(PyExc_TypeError,
|
Chris@20
|
379 "getParameter() takes plugin handle (object) and parameter id (string) arguments");
|
Chris@20
|
380 return 0; }
|
Chris@20
|
381
|
Chris@21
|
382 PyPluginObject *pd = getPluginObject(pyPluginHandle);
|
Chris@20
|
383 if (!pd) return 0;
|
Chris@20
|
384
|
Chris@20
|
385 float value = pd->plugin->getParameter(PyString_AS_STRING(pyParam));
|
Chris@20
|
386 return PyFloat_FromDouble(double(value));
|
Chris@20
|
387 }
|
Chris@20
|
388
|
Chris@20
|
389 static PyObject *
|
Chris@20
|
390 vampyhost_setParameter(PyObject *self, PyObject *args)
|
Chris@20
|
391 {
|
Chris@21
|
392 cerr << "vampyhost_setParameter" << endl;
|
Chris@21
|
393
|
Chris@20
|
394 PyObject *pyPluginHandle;
|
Chris@20
|
395 PyObject *pyParam;
|
Chris@20
|
396 float value;
|
Chris@20
|
397
|
Chris@20
|
398 if (!PyArg_ParseTuple(args, "OSf", &pyPluginHandle, &pyParam, &value)) {
|
Chris@20
|
399 PyErr_SetString(PyExc_TypeError,
|
Chris@20
|
400 "setParameter() takes plugin handle (object), parameter id (string), and value (float) arguments");
|
Chris@20
|
401 return 0; }
|
Chris@20
|
402
|
Chris@21
|
403 PyPluginObject *pd = getPluginObject(pyPluginHandle);
|
Chris@20
|
404 if (!pd) return 0;
|
Chris@20
|
405
|
Chris@20
|
406 pd->plugin->setParameter(PyString_AS_STRING(pyParam), value);
|
Chris@20
|
407 return Py_True;
|
Chris@20
|
408 }
|
Chris@20
|
409
|
Chris@20
|
410 static PyObject *
|
Chris@0
|
411 vampyhost_process(PyObject *self, PyObject *args)
|
Chris@0
|
412 {
|
Chris@21
|
413 cerr << "vampyhost_process" << endl;
|
Chris@21
|
414
|
Chris@0
|
415 PyObject *pyPluginHandle;
|
Chris@0
|
416 PyObject *pyBuffer;
|
Chris@0
|
417 PyObject *pyRealTime;
|
Chris@0
|
418
|
luis@7
|
419 if (!PyArg_ParseTuple(args, "OOO",
|
Chris@0
|
420 &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor
|
Chris@0
|
421 &pyBuffer, // Audio data
|
Chris@0
|
422 &pyRealTime)) { // TimeStamp
|
Chris@0
|
423 PyErr_SetString(PyExc_TypeError,
|
Chris@17
|
424 "process() takes plugin handle (object), buffer (2D array of channels * samples floats) and timestamp (RealTime) arguments");
|
Chris@16
|
425 return 0; }
|
Chris@0
|
426
|
Chris@0
|
427 if (!PyRealTime_Check(pyRealTime)) {
|
Chris@0
|
428 PyErr_SetString(PyExc_TypeError,"Valid timestamp required.");
|
Chris@16
|
429 return 0; }
|
Chris@0
|
430
|
Chris@17
|
431 if (!PyList_Check(pyBuffer)) {
|
Chris@17
|
432 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input.");
|
Chris@17
|
433 return 0;
|
Chris@17
|
434 }
|
Chris@17
|
435
|
Chris@21
|
436 PyPluginObject *pd = getPluginObject(pyPluginHandle);
|
Chris@16
|
437 if (!pd) return 0;
|
Chris@0
|
438
|
Chris@0
|
439 if (!pd->isInitialised) {
|
Chris@0
|
440 PyErr_SetString(PyExc_StandardError,
|
Chris@0
|
441 "Plugin has not been initialised.");
|
Chris@16
|
442 return 0;
|
Chris@16
|
443 }
|
Chris@0
|
444
|
Chris@12
|
445 int channels = pd->channels;
|
Chris@0
|
446
|
Chris@4
|
447 if (PyList_GET_SIZE(pyBuffer) != channels) {
|
Chris@17
|
448 cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << endl;
|
Chris@4
|
449 PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
|
Chris@16
|
450 return 0;
|
Chris@4
|
451 }
|
Chris@0
|
452
|
Chris@4
|
453 float **inbuf = new float *[channels];
|
Chris@0
|
454
|
Chris@12
|
455 PyTypeConversions typeConv;
|
Chris@12
|
456 typeConv.setNumpyInstalled(true);
|
Chris@17
|
457
|
Chris@17
|
458 cerr << "here!" << endl;
|
Chris@12
|
459
|
Chris@12
|
460 vector<vector<float> > data;
|
Chris@4
|
461 for (int c = 0; c < channels; ++c) {
|
Chris@4
|
462 PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
|
Chris@17
|
463 data.push_back(typeConv.PyValue_To_FloatVector(cbuf));
|
Chris@12
|
464 }
|
Chris@12
|
465
|
Chris@12
|
466 for (int c = 0; c < channels; ++c) {
|
Chris@17
|
467 if (data[c].size() != pd->blockSize) {
|
Chris@17
|
468 cerr << "Wrong number of samples on channel " << c << ": expected " << pd->blockSize << " (plugin's block size), got " << data[c].size() << endl;
|
Chris@17
|
469 PyErr_SetString(PyExc_TypeError, "Wrong number of samples");
|
Chris@17
|
470 return 0;
|
Chris@17
|
471 }
|
Chris@12
|
472 inbuf[c] = &data[c][0];
|
Chris@4
|
473 }
|
Chris@0
|
474
|
Chris@17
|
475 cerr << "no, here!" << endl;
|
Chris@17
|
476
|
Chris@12
|
477 RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
|
Chris@0
|
478
|
Chris@18
|
479 cerr << "no no, here!" << endl;
|
Chris@0
|
480
|
Chris@18
|
481 Plugin::FeatureSet fs = pd->plugin->process(inbuf, timeStamp);
|
Chris@0
|
482
|
Chris@4
|
483 delete[] inbuf;
|
Chris@0
|
484
|
Chris@18
|
485 cerr << "no no no, here!" << endl;
|
Chris@18
|
486
|
Chris@18
|
487 PyTypeConversions conv;
|
Chris@18
|
488 conv.setNumpyInstalled(true);
|
Chris@18
|
489
|
Chris@18
|
490 PyObject *pyFs = PyDict_New();
|
Chris@0
|
491
|
Chris@18
|
492 for (Plugin::FeatureSet::const_iterator fsi = fs.begin();
|
Chris@18
|
493 fsi != fs.end(); ++fsi) {
|
Chris@18
|
494
|
Chris@18
|
495 int fno = fsi->first;
|
Chris@18
|
496 const Plugin::FeatureList &fl = fsi->second;
|
Chris@18
|
497
|
Chris@18
|
498 if (!fl.empty()) {
|
Chris@18
|
499
|
Chris@18
|
500 PyObject *pyFl = PyList_New(fl.size());
|
Chris@18
|
501
|
Chris@18
|
502 for (int fli = 0; fli < (int)fl.size(); ++fli) {
|
Chris@18
|
503
|
Chris@18
|
504 const Plugin::Feature &f = fl[fli];
|
Chris@18
|
505 PyObject *pyF = PyDict_New();
|
Chris@18
|
506
|
Chris@18
|
507 if (f.hasTimestamp) {
|
Chris@18
|
508 PyDict_SetItemString
|
Chris@18
|
509 (pyF, "timestamp", PyRealTime_FromRealTime(f.timestamp));
|
Chris@18
|
510 }
|
Chris@18
|
511 if (f.hasDuration) {
|
Chris@18
|
512 PyDict_SetItemString
|
Chris@18
|
513 (pyF, "duration", PyRealTime_FromRealTime(f.duration));
|
Chris@18
|
514 }
|
Chris@18
|
515
|
Chris@18
|
516 PyDict_SetItemString
|
Chris@18
|
517 (pyF, "label", PyString_FromString(f.label.c_str()));
|
Chris@18
|
518
|
Chris@18
|
519 if (!f.values.empty()) {
|
Chris@18
|
520 PyDict_SetItemString
|
Chris@18
|
521 (pyF, "values", conv.FloatVector_To_PyArray(f.values));
|
Chris@18
|
522 }
|
Chris@18
|
523
|
Chris@18
|
524 PyList_SET_ITEM(pyFl, fli, pyF);
|
Chris@18
|
525 }
|
Chris@18
|
526
|
Chris@18
|
527 PyObject *pyN = PyInt_FromLong(fno);
|
Chris@18
|
528 PyDict_SetItem(pyFs, pyN, pyFl);
|
Chris@18
|
529 }
|
Chris@18
|
530 }
|
Chris@18
|
531
|
Chris@18
|
532 cerr << "no you fool, here!" << endl;
|
Chris@18
|
533
|
Chris@18
|
534 return pyFs;
|
Chris@0
|
535 }
|
Chris@0
|
536
|
Chris@21
|
537 static PyMethodDef PyPluginObject_methods[] =
|
Chris@21
|
538 {
|
Chris@21
|
539 {0, 0}
|
Chris@21
|
540 };
|
Chris@21
|
541
|
Chris@21
|
542 /* Doc:: 10.3 Type Objects */ /* static */
|
Chris@21
|
543 PyTypeObject Plugin_Type =
|
Chris@21
|
544 {
|
Chris@21
|
545 PyObject_HEAD_INIT(NULL)
|
Chris@21
|
546 0, /*ob_size*/
|
Chris@21
|
547 "vampyhost.Plugin", /*tp_name*/
|
Chris@21
|
548 sizeof(PyPluginObject), /*tp_basicsize*/
|
Chris@21
|
549 0, /*tp_itemsize*/
|
Chris@21
|
550 (destructor)PyPluginObject_dealloc, /*tp_dealloc*/
|
Chris@21
|
551 0, /*tp_print*/
|
Chris@21
|
552 0, /*tp_getattr*/
|
Chris@21
|
553 0, /*tp_setattr*/
|
Chris@21
|
554 0, /*tp_compare*/
|
Chris@21
|
555 0, /*tp_repr*/
|
Chris@21
|
556 0, /*tp_as_number*/
|
Chris@21
|
557 0, /*tp_as_sequence*/
|
Chris@21
|
558 0, /*tp_as_mapping*/
|
Chris@21
|
559 0, /*tp_hash*/
|
Chris@21
|
560 0, /*tp_call*/
|
Chris@21
|
561 0, /*tp_str*/
|
Chris@21
|
562 0, /*tp_getattro*/
|
Chris@21
|
563 0, /*tp_setattro*/
|
Chris@21
|
564 0, /*tp_as_buffer*/
|
Chris@21
|
565 Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
Chris@21
|
566 "Plugin Object", /*tp_doc*/
|
Chris@21
|
567 0, /*tp_traverse*/
|
Chris@21
|
568 0, /*tp_clear*/
|
Chris@21
|
569 0, /*tp_richcompare*/
|
Chris@21
|
570 0, /*tp_weaklistoffset*/
|
Chris@21
|
571 0, /*tp_iter*/
|
Chris@21
|
572 0, /*tp_iternext*/
|
Chris@21
|
573 PyPluginObject_methods, /*tp_methods*/
|
Chris@21
|
574 0, /*tp_members*/
|
Chris@21
|
575 0, /*tp_getset*/
|
Chris@21
|
576 0, /*tp_base*/
|
Chris@21
|
577 0, /*tp_dict*/
|
Chris@21
|
578 0, /*tp_descr_get*/
|
Chris@21
|
579 0, /*tp_descr_set*/
|
Chris@21
|
580 0, /*tp_dictoffset*/
|
Chris@21
|
581 0, /*tp_init*/
|
Chris@21
|
582 PyType_GenericAlloc, /*tp_alloc*/
|
Chris@21
|
583 0, /*tp_new*/
|
Chris@21
|
584 PyObject_Del, /*tp_free*/
|
Chris@21
|
585 0, /*tp_is_gc*/
|
Chris@21
|
586 };
|
Chris@0
|
587
|
Chris@18
|
588 // module methods table
|
Chris@0
|
589 static PyMethodDef vampyhost_methods[] = {
|
Chris@0
|
590
|
Chris@18
|
591 {"listPlugins", vampyhost_enumeratePlugins, METH_NOARGS,
|
Chris@0
|
592 xx_foo_doc},
|
Chris@0
|
593
|
Chris@15
|
594 {"getPluginPath", vampyhost_getPluginPath, METH_NOARGS,
|
Chris@15
|
595 xx_foo_doc},
|
Chris@15
|
596
|
Chris@18
|
597 {"getCategoryOf", vampyhost_getPluginCategory, METH_VARARGS,
|
Chris@0
|
598 xx_foo_doc},
|
Chris@0
|
599
|
Chris@18
|
600 {"getLibraryFor", vampyhost_getLibraryFor, METH_VARARGS,
|
Chris@0
|
601 xx_foo_doc},
|
Chris@0
|
602
|
Chris@18
|
603 {"getOutputsOf", vampyhost_getOutputList, METH_VARARGS,
|
Chris@0
|
604 xx_foo_doc},
|
Chris@0
|
605
|
Chris@0
|
606 {"loadPlugin", vampyhost_loadPlugin, METH_VARARGS,
|
Chris@0
|
607 xx_foo_doc},
|
Chris@0
|
608
|
Chris@20
|
609 {"getParameter", vampyhost_getParameter, METH_VARARGS,
|
Chris@20
|
610 xx_foo_doc},
|
Chris@20
|
611
|
Chris@20
|
612 {"setParameter", vampyhost_setParameter, METH_VARARGS,
|
Chris@20
|
613 xx_foo_doc},
|
Chris@20
|
614
|
Chris@18
|
615 {"initialise", vampyhost_initialise, METH_VARARGS,
|
Chris@18
|
616 xx_foo_doc},
|
Chris@18
|
617
|
Chris@18
|
618 {"reset", vampyhost_reset, METH_VARARGS,
|
Chris@18
|
619 xx_foo_doc},
|
Chris@18
|
620
|
Chris@0
|
621 {"process", vampyhost_process, METH_VARARGS,
|
Chris@0
|
622 xx_foo_doc},
|
Chris@0
|
623
|
Chris@0
|
624 {"unloadPlugin", vampyhost_unloadPlugin, METH_VARARGS,
|
Chris@0
|
625 xx_foo_doc},
|
Chris@0
|
626
|
Chris@16
|
627 {0, 0} /* sentinel */
|
Chris@0
|
628 };
|
Chris@0
|
629
|
Chris@21
|
630 PyPluginObject *
|
Chris@21
|
631 PyPluginObject::create_internal()
|
Chris@21
|
632 {
|
Chris@21
|
633 return (PyPluginObject *)PyType_GenericAlloc(&Plugin_Type, 0);
|
Chris@21
|
634 }
|
Chris@21
|
635
|
Chris@0
|
636 //Documentation for our new module
|
Chris@0
|
637 PyDoc_STRVAR(module_doc, "This is a template module just for instruction.");
|
Chris@0
|
638
|
Chris@14
|
639
|
Chris@14
|
640
|
Chris@0
|
641 /* Initialization function for the module (*must* be called initxx) */
|
Chris@0
|
642
|
Chris@0
|
643 //module initialization (includes extern C {...} as necessary)
|
Chris@0
|
644 PyMODINIT_FUNC
|
Chris@0
|
645 initvampyhost(void)
|
Chris@0
|
646 {
|
Chris@0
|
647 PyObject *m;
|
Chris@0
|
648
|
Chris@0
|
649 /* Finalize the type object including setting type of the new type
|
luis@7
|
650 * object; doing it here is required for portability to Windows
|
Chris@0
|
651 * without requiring C++. */
|
Chris@0
|
652
|
Chris@0
|
653 if (PyType_Ready(&RealTime_Type) < 0)
|
Chris@0
|
654 return;
|
Chris@0
|
655
|
Chris@0
|
656 /* Create the module and add the functions */
|
Chris@0
|
657 m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc);
|
Chris@16
|
658 if (!m) return;
|
Chris@0
|
659
|
Chris@14
|
660 import_array();
|
Chris@14
|
661
|
Chris@17
|
662 PyModule_AddObject(m, "RealTime", (PyObject *)&RealTime_Type);
|
Chris@0
|
663 }
|