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@14
|
13 #include "PyTypeConversions.h"
|
Chris@14
|
14 #include "PyRealTime.h"
|
Chris@0
|
15
|
Chris@4
|
16 //!!! NB all our NumPy stuff is currently using the deprecated API --
|
Chris@4
|
17 //!!! need to work out how to update this
|
Chris@12
|
18 //#include "numpy/arrayobject.h"
|
Chris@12
|
19
|
Chris@12
|
20 #define HAVE_NUMPY 1 // Required
|
Chris@12
|
21
|
Chris@0
|
22 //includes for vamp host
|
Chris@1
|
23 #include "vamp-hostsdk/Plugin.h"
|
Chris@1
|
24 #include "vamp-hostsdk/PluginHostAdapter.h"
|
Chris@1
|
25 #include "vamp-hostsdk/PluginChannelAdapter.h"
|
Chris@1
|
26 #include "vamp-hostsdk/PluginInputDomainAdapter.h"
|
Chris@1
|
27 #include "vamp-hostsdk/PluginLoader.h"
|
Chris@0
|
28 //#include "vamp/vamp.h"
|
Chris@0
|
29
|
Chris@0
|
30 #include <iostream>
|
Chris@0
|
31 #include <fstream>
|
Chris@0
|
32 #include <set>
|
Chris@0
|
33 #include <sndfile.h>
|
Chris@0
|
34
|
Chris@0
|
35 #include <cstring>
|
Chris@0
|
36 #include <cstdlib>
|
Chris@0
|
37 #include <string>
|
Chris@0
|
38
|
Chris@0
|
39 #include "system.h"
|
Chris@0
|
40
|
Chris@0
|
41 #include <cmath>
|
Chris@0
|
42
|
Chris@0
|
43
|
Chris@0
|
44 using namespace std;
|
Chris@0
|
45 using namespace Vamp;
|
Chris@0
|
46
|
Chris@0
|
47 using Vamp::Plugin;
|
Chris@0
|
48 using Vamp::PluginHostAdapter;
|
Chris@0
|
49 using Vamp::RealTime;
|
Chris@0
|
50 using Vamp::HostExt::PluginLoader;
|
Chris@0
|
51
|
Chris@0
|
52 #define HOST_VERSION "1.1"
|
Chris@0
|
53
|
Chris@0
|
54
|
Chris@0
|
55 /* MODULE HELPER FUNCTIONS */
|
Chris@2
|
56 PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!!
|
Chris@0
|
57
|
Chris@0
|
58 /*obtain C plugin handle and key from pyCobject */
|
luis@7
|
59 bool getPluginHandle
|
Chris@0
|
60 (PyObject *pyPluginHandle, Plugin **plugin, string **pKey=NULL) {
|
Chris@0
|
61
|
Chris@0
|
62 //char errormsg[]="Wrong input argument: Plugin Handle required.";
|
Chris@0
|
63
|
Chris@0
|
64 *plugin = NULL;
|
Chris@2
|
65 if (!PyCObject_Check(pyPluginHandle)) return false;
|
Chris@0
|
66
|
Chris@0
|
67 //try to convert to Plugin pointer
|
Chris@0
|
68 Plugin *p = (Plugin*) PyCObject_AsVoidPtr(pyPluginHandle);
|
luis@7
|
69 if (!p) return false;
|
Chris@0
|
70
|
Chris@0
|
71 string pId;
|
Chris@0
|
72
|
Chris@0
|
73 if (pKey) {
|
Chris@0
|
74 *pKey = (string*) PyCObject_GetDesc(pyPluginHandle);
|
Chris@2
|
75 if (!*pKey) return false;
|
Chris@0
|
76 pId = *(string*) *pKey;
|
Chris@0
|
77
|
Chris@0
|
78 } else {
|
Chris@0
|
79
|
Chris@0
|
80 void *pKey = PyCObject_GetDesc(pyPluginHandle);
|
Chris@2
|
81 if (!pKey) return false;
|
Chris@0
|
82 pId = *(string*) pKey;
|
Chris@0
|
83 }
|
luis@7
|
84
|
Chris@0
|
85 string::size_type pos = pId.find(':');
|
Chris@2
|
86 if (pos == string::npos) return false;
|
Chris@0
|
87
|
Chris@0
|
88 pId = pId.substr(pId.rfind(':')+1);
|
luis@7
|
89 string identifier = p->getIdentifier();
|
luis@7
|
90
|
Chris@2
|
91 if (pId.compare(identifier)) return false;
|
Chris@0
|
92
|
Chris@0
|
93 *plugin = p;
|
Chris@0
|
94 return true;
|
Chris@0
|
95 }
|
Chris@0
|
96
|
Chris@0
|
97 /*
|
Chris@0
|
98 ----------------------------------------------------------------
|
Chris@0
|
99 */
|
Chris@0
|
100
|
Chris@0
|
101
|
Chris@0
|
102
|
Chris@0
|
103 /*
|
luis@7
|
104 VAMPYHOST MAIN
|
luis@7
|
105 ---------------------------------------------------------------------
|
Chris@0
|
106 */
|
Chris@0
|
107
|
Chris@0
|
108 /* ENUMERATE PLUGINS*/
|
Chris@0
|
109
|
Chris@0
|
110 static PyObject *
|
Chris@0
|
111 vampyhost_enumeratePlugins(PyObject *self, PyObject *args)
|
Chris@0
|
112 {
|
Chris@0
|
113 string retType;
|
luis@7
|
114
|
Chris@0
|
115 if (!PyArg_ParseTuple(args, "|s:enumeratePlugins", &retType))
|
Chris@0
|
116 return NULL;
|
Chris@0
|
117
|
Chris@0
|
118 //list available plugins
|
Chris@0
|
119 PluginLoader *loader = PluginLoader::getInstance();
|
Chris@0
|
120 vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
|
Chris@0
|
121
|
Chris@0
|
122 //library Map
|
Chris@0
|
123 typedef multimap<string, PluginLoader::PluginKey> LibraryMap;
|
Chris@0
|
124 LibraryMap libraryMap;
|
Chris@0
|
125
|
Chris@0
|
126 //New list object
|
Chris@0
|
127 PyObject *pyList = PyList_New(plugins.size());
|
Chris@0
|
128
|
Chris@0
|
129 for (size_t i = 0; i < plugins.size(); ++i) {
|
Chris@0
|
130 string path = loader->getLibraryPathForPlugin(plugins[i]);
|
Chris@0
|
131 libraryMap.insert(LibraryMap::value_type(path, plugins[i]));
|
Chris@0
|
132
|
Chris@0
|
133 PyObject *pyPluginKey = PyString_FromString(plugins[i].c_str());
|
Chris@0
|
134 PyList_SET_ITEM(pyList,i,pyPluginKey);
|
luis@7
|
135
|
Chris@0
|
136 }
|
Chris@0
|
137
|
Chris@0
|
138 PyList_Sort(pyList);
|
Chris@0
|
139 return pyList;
|
Chris@0
|
140 }
|
Chris@0
|
141
|
Chris@0
|
142
|
Chris@0
|
143 /* GET PLUGIN LIBRARY PATH*/
|
Chris@0
|
144
|
Chris@0
|
145 static PyObject *
|
Chris@0
|
146 vampyhost_getLibraryPath(PyObject *self, PyObject *args)
|
Chris@0
|
147 {
|
Chris@0
|
148 PyObject *pyPluginKey;
|
Chris@0
|
149
|
Chris@0
|
150 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
|
Chris@0
|
151 PyErr_SetString(PyExc_TypeError,
|
Chris@0
|
152 "String input argument required: pluginKey");
|
Chris@0
|
153 return NULL; }
|
Chris@0
|
154
|
Chris@0
|
155 //convert to stl string
|
Chris@0
|
156 string pluginKey(PyString_AS_STRING(pyPluginKey));
|
Chris@0
|
157
|
Chris@0
|
158 //check pluginKey Validity
|
Chris@0
|
159 string::size_type ki = pluginKey.find(':');
|
Chris@0
|
160 if (ki == string::npos) {
|
Chris@0
|
161 PyErr_SetString(PyExc_TypeError,
|
luis@7
|
162 "String input argument required: pluginLibrary:Identifier");
|
Chris@0
|
163 return NULL;
|
Chris@0
|
164 }
|
Chris@0
|
165
|
Chris@0
|
166 PluginLoader *loader = PluginLoader::getInstance();
|
Chris@0
|
167 string path = loader->getLibraryPathForPlugin(pluginKey);
|
Chris@0
|
168 PyObject *pyPath = PyString_FromString(path.c_str());
|
Chris@0
|
169 return pyPath;
|
Chris@0
|
170 }
|
Chris@0
|
171
|
Chris@0
|
172
|
Chris@0
|
173 /* GET PLUGIN CATEGORY*/
|
Chris@0
|
174
|
Chris@0
|
175 static PyObject *
|
Chris@0
|
176 vampyhost_getPluginCategory(PyObject *self, PyObject *args)
|
Chris@0
|
177 {
|
Chris@0
|
178 PyObject *pyPluginKey;
|
Chris@0
|
179
|
Chris@0
|
180 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
|
Chris@0
|
181 PyErr_SetString(PyExc_TypeError,
|
Chris@0
|
182 "String input argument required: pluginKey");
|
Chris@0
|
183 return NULL; }
|
Chris@0
|
184
|
Chris@0
|
185 //convert to stl string
|
Chris@0
|
186 string pluginKey(PyString_AS_STRING(pyPluginKey));
|
Chris@0
|
187
|
Chris@0
|
188 //check pluginKey Validity
|
Chris@0
|
189 string::size_type ki = pluginKey.find(':');
|
Chris@0
|
190 if (ki == string::npos) {
|
Chris@0
|
191 PyErr_SetString(PyExc_TypeError,
|
luis@7
|
192 "String input argument required: pluginLibrary:Identifier");
|
Chris@0
|
193 return NULL;
|
Chris@0
|
194 }
|
Chris@0
|
195
|
Chris@0
|
196 PluginLoader *loader = PluginLoader::getInstance();
|
luis@7
|
197 PluginLoader::PluginCategoryHierarchy
|
Chris@0
|
198 category = loader->getPluginCategory(pluginKey);
|
Chris@0
|
199 string catstring;
|
Chris@0
|
200
|
Chris@0
|
201 if (!category.empty()) {
|
Chris@0
|
202 catstring = "";
|
Chris@0
|
203 for (size_t ci = 0; ci < category.size(); ++ci) {
|
Chris@0
|
204 catstring.append(category[ci]);
|
Chris@0
|
205 catstring.append(" ");
|
Chris@0
|
206 }
|
Chris@0
|
207 PyObject *pyCat = PyString_FromString(catstring.c_str());
|
Chris@0
|
208 return pyCat;
|
Chris@0
|
209 }
|
Chris@0
|
210 PyObject *pyCat = PyString_FromString("");
|
Chris@0
|
211 return pyCat;
|
Chris@0
|
212 }
|
Chris@0
|
213
|
Chris@0
|
214
|
Chris@0
|
215
|
Chris@0
|
216 /* GET PLUGIN OUTPUT LIST*/
|
Chris@0
|
217
|
Chris@0
|
218 static PyObject *
|
Chris@0
|
219 vampyhost_getOutputList(PyObject *self, PyObject *args)
|
Chris@0
|
220 {
|
Chris@0
|
221 PyObject *pyPluginHandle;
|
Chris@0
|
222 string pluginKey;
|
Chris@0
|
223
|
Chris@0
|
224 if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) {
|
Chris@0
|
225 PyErr_SetString(PyExc_TypeError,
|
Chris@0
|
226 "Invalid argument: plugin handle or plugin key required.");
|
luis@7
|
227 return NULL;
|
Chris@0
|
228 }
|
Chris@0
|
229
|
Chris@0
|
230 //check if we have a plugin key string or a handle object
|
Chris@0
|
231 if (PyString_Check(pyPluginHandle) ) {
|
Chris@0
|
232
|
Chris@0
|
233 pluginKey.assign(PyString_AS_STRING(pyPluginHandle));
|
Chris@0
|
234 //check pluginKey Validity
|
Chris@0
|
235 string::size_type ki = pluginKey.find(':');
|
Chris@0
|
236 if (ki == string::npos) {
|
Chris@0
|
237 PyErr_SetString(PyExc_TypeError,
|
luis@7
|
238 "String input argument required: pluginLibrary:Identifier");
|
Chris@0
|
239 return NULL;
|
Chris@0
|
240 }
|
Chris@0
|
241
|
Chris@0
|
242 } else {
|
luis@7
|
243
|
luis@7
|
244 string *key;
|
luis@7
|
245 Plugin *plugin;
|
Chris@0
|
246
|
Chris@0
|
247 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
|
Chris@0
|
248 PyErr_SetString(PyExc_TypeError,
|
Chris@0
|
249 "Invalid or deleted plugin handle.");
|
Chris@0
|
250 return NULL; }
|
Chris@0
|
251 pluginKey.assign(*key);
|
luis@7
|
252 }
|
luis@7
|
253
|
Chris@0
|
254 //This code creates new instance of the plugin anyway
|
Chris@0
|
255 PluginLoader *loader = PluginLoader::getInstance();
|
luis@7
|
256
|
Chris@0
|
257 //load plugin
|
Chris@3
|
258 Plugin *plugin = loader->loadPlugin
|
Chris@3
|
259 (pluginKey, 48000, PluginLoader::ADAPT_ALL_SAFE);
|
luis@7
|
260 if (!plugin) {
|
Chris@0
|
261 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
|
luis@7
|
262 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
|
Chris@0
|
263 return NULL;
|
luis@7
|
264 }
|
Chris@0
|
265
|
Chris@0
|
266 Plugin::OutputList outputs = plugin->getOutputDescriptors();
|
Chris@0
|
267 //Plugin::OutputDescriptor od;
|
Chris@0
|
268
|
Chris@0
|
269 if (outputs.size()<1) {
|
Chris@0
|
270 string pyerr("Plugin has no output: "); pyerr += pluginKey;
|
luis@7
|
271 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
|
Chris@0
|
272 return NULL;
|
Chris@0
|
273 }
|
Chris@0
|
274
|
Chris@0
|
275 //New list object
|
Chris@0
|
276 PyObject *pyList = PyList_New(outputs.size());
|
Chris@0
|
277
|
Chris@0
|
278 for (size_t i = 0; i < outputs.size(); ++i) {
|
luis@7
|
279 PyObject *pyOutputId =
|
Chris@0
|
280 PyString_FromString(outputs[i].identifier.c_str());
|
luis@7
|
281 PyList_SET_ITEM(pyList,i,pyOutputId);
|
Chris@0
|
282 }
|
Chris@0
|
283
|
Chris@0
|
284 delete plugin;
|
Chris@0
|
285 return pyList;
|
Chris@0
|
286 }
|
Chris@0
|
287
|
Chris@0
|
288
|
Chris@0
|
289
|
Chris@0
|
290 /* LOAD PLUGIN */
|
Chris@0
|
291
|
Chris@0
|
292 static PyObject *
|
Chris@0
|
293 vampyhost_loadPlugin(PyObject *self, PyObject *args)
|
Chris@0
|
294 {
|
Chris@0
|
295 PyObject *pyPluginKey;
|
Chris@0
|
296 float inputSampleRate;
|
Chris@0
|
297
|
luis@7
|
298 if (!PyArg_ParseTuple(args, "Sf",
|
Chris@0
|
299 &pyPluginKey,
|
Chris@0
|
300 &inputSampleRate)) {
|
Chris@0
|
301 PyErr_SetString(PyExc_TypeError,
|
Chris@0
|
302 "String input argument required: pluginKey");
|
Chris@0
|
303 return NULL; }
|
Chris@0
|
304
|
Chris@0
|
305 //convert to stl string
|
Chris@0
|
306 string pluginKey(PyString_AS_STRING(pyPluginKey));
|
Chris@0
|
307
|
Chris@0
|
308 //check pluginKey Validity
|
Chris@0
|
309 string::size_type ki = pluginKey.find(':');
|
Chris@0
|
310 if (ki == string::npos) {
|
Chris@0
|
311 PyErr_SetString(PyExc_TypeError,
|
luis@7
|
312 "String input argument required: pluginLibrary:Identifier");
|
Chris@0
|
313 return NULL;
|
Chris@0
|
314 }
|
Chris@0
|
315
|
Chris@0
|
316 PluginLoader *loader = PluginLoader::getInstance();
|
luis@7
|
317
|
Chris@0
|
318 //load plugin
|
luis@7
|
319 Plugin *plugin = loader->loadPlugin (pluginKey, inputSampleRate,
|
Chris@6
|
320 PluginLoader::ADAPT_ALL_SAFE);
|
luis@7
|
321 if (!plugin) {
|
Chris@0
|
322 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
|
luis@7
|
323 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
|
Chris@0
|
324 return NULL;
|
luis@7
|
325 }
|
Chris@0
|
326 //void *identifier = (void*) new string(pluginKey);
|
Chris@0
|
327 PyPluginDescriptor *pd = new PyPluginDescriptor;
|
luis@7
|
328
|
Chris@0
|
329 pd->key = pluginKey;
|
Chris@0
|
330 pd->isInitialised = false;
|
Chris@0
|
331 pd->inputSampleRate = inputSampleRate;
|
luis@7
|
332
|
Chris@0
|
333 //New PyCObject
|
luis@7
|
334 //PyObject *pyPluginHandle = PyCObject_FromVoidPtrAndDesc(
|
luis@7
|
335 //(void*) plugin, identifier, NULL);
|
Chris@0
|
336
|
luis@7
|
337 PyObject *pyPluginHandle = PyCObject_FromVoidPtrAndDesc(
|
luis@7
|
338 (void*) plugin, (void*) pd, NULL);
|
luis@7
|
339
|
Chris@0
|
340 return pyPluginHandle;
|
Chris@0
|
341 }
|
Chris@0
|
342
|
Chris@0
|
343
|
Chris@0
|
344
|
Chris@0
|
345 /* UNLOAD PLUGIN */
|
Chris@0
|
346
|
Chris@0
|
347 static PyObject *
|
Chris@0
|
348 vampyhost_unloadPlugin(PyObject *self, PyObject *args)
|
Chris@0
|
349 {
|
Chris@0
|
350 PyObject *pyPluginHandle;
|
Chris@0
|
351
|
Chris@0
|
352 if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) {
|
Chris@0
|
353 PyErr_SetString(PyExc_TypeError,
|
Chris@0
|
354 "Wrong input argument: Plugin Handle required.");
|
Chris@0
|
355 return NULL; }
|
Chris@0
|
356
|
luis@7
|
357 string *key;
|
luis@7
|
358 Plugin *plugin;
|
Chris@0
|
359
|
Chris@0
|
360 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
|
Chris@0
|
361 PyErr_SetString(PyExc_TypeError,
|
Chris@0
|
362 "Invalid or already deleted plugin handle.");
|
Chris@0
|
363 return NULL; }
|
Chris@0
|
364
|
Chris@0
|
365 /* Prevent repeated calls from causing segfault
|
Chris@0
|
366 sice it will fail type checking the 2nd time: */
|
Chris@0
|
367 PyCObject_SetVoidPtr(pyPluginHandle,NULL);
|
luis@7
|
368
|
Chris@0
|
369 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
|
luis@7
|
370
|
Chris@0
|
371 delete plugin;
|
Chris@0
|
372 delete pd;
|
Chris@0
|
373 return pyPluginHandle;
|
Chris@0
|
374
|
Chris@0
|
375 }
|
Chris@0
|
376
|
Chris@0
|
377
|
Chris@0
|
378 /* INITIALISE PLUGIN */
|
Chris@0
|
379
|
Chris@0
|
380 static PyObject *
|
Chris@0
|
381 vampyhost_initialise(PyObject *self, PyObject *args)
|
Chris@0
|
382 {
|
Chris@0
|
383 PyObject *pyPluginHandle;
|
luis@7
|
384 size_t channels, blockSize, stepSize;
|
Chris@0
|
385
|
luis@7
|
386 if (!PyArg_ParseTuple (args, "Onnn", &pyPluginHandle,
|
luis@7
|
387 (size_t) &channels,
|
luis@7
|
388 (size_t) &stepSize,
|
luis@7
|
389 (size_t) &blockSize))
|
Chris@0
|
390 {
|
Chris@0
|
391 PyErr_SetString(PyExc_TypeError,
|
Chris@0
|
392 "Wrong input arguments: requires a valid plugin handle,channels,stepSize,blockSize.");
|
luis@7
|
393 return NULL;
|
Chris@0
|
394 }
|
Chris@0
|
395
|
luis@7
|
396 Plugin *plugin;
|
luis@7
|
397 string *key;
|
Chris@0
|
398
|
Chris@0
|
399 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
|
Chris@0
|
400 PyErr_SetString(PyExc_TypeError,
|
Chris@0
|
401 "Invalid plugin handle.");
|
Chris@0
|
402 return NULL; }
|
Chris@0
|
403
|
Chris@0
|
404 // here we cast the void pointer as PyPluginDescriptor instead of string
|
luis@7
|
405 PyPluginDescriptor *plugDesc = (PyPluginDescriptor*) key;
|
Chris@0
|
406
|
Chris@0
|
407 plugDesc->channels = channels;
|
Chris@0
|
408 plugDesc->stepSize = stepSize;
|
Chris@0
|
409 plugDesc->blockSize = blockSize;
|
Chris@3
|
410
|
Chris@0
|
411 if (!plugin->initialise(channels, stepSize, blockSize)) {
|
Chris@6
|
412 std::cerr << "Failed to initialise native plugin adapter with channels = " << channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << " and ADAPT_ALL_SAFE set" << std::endl;
|
Chris@0
|
413 PyErr_SetString(PyExc_TypeError,
|
Chris@0
|
414 "Plugin initialization failed.");
|
Chris@6
|
415 return NULL;
|
Chris@6
|
416 }
|
Chris@0
|
417
|
luis@7
|
418 plugDesc->identifier =
|
Chris@0
|
419 plugDesc->key.substr(plugDesc->key.rfind(':')+1);
|
Chris@0
|
420 plugDesc->isInitialised = true;
|
luis@7
|
421
|
Chris@0
|
422 return Py_True;
|
Chris@0
|
423 }
|
Chris@0
|
424
|
Chris@0
|
425 /* RUN PROCESS */
|
Chris@0
|
426
|
Chris@0
|
427 static PyObject *
|
Chris@0
|
428 vampyhost_process(PyObject *self, PyObject *args)
|
Chris@0
|
429 {
|
Chris@0
|
430 PyObject *pyPluginHandle;
|
Chris@0
|
431 PyObject *pyBuffer;
|
Chris@0
|
432 PyObject *pyRealTime;
|
Chris@0
|
433
|
luis@7
|
434 if (!PyArg_ParseTuple(args, "OOO",
|
Chris@0
|
435 &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor
|
Chris@0
|
436 &pyBuffer, // Audio data
|
Chris@0
|
437 &pyRealTime)) { // TimeStamp
|
Chris@0
|
438 PyErr_SetString(PyExc_TypeError,
|
Chris@0
|
439 "Required: plugin handle, buffer, timestmap.");
|
Chris@0
|
440 return NULL; }
|
Chris@0
|
441
|
Chris@0
|
442 if (!PyRealTime_Check(pyRealTime)) {
|
Chris@0
|
443 PyErr_SetString(PyExc_TypeError,"Valid timestamp required.");
|
Chris@0
|
444 return NULL; }
|
Chris@0
|
445
|
Chris@4
|
446 string *key;
|
luis@7
|
447 Plugin *plugin;
|
Chris@0
|
448
|
Chris@4
|
449 if (!getPluginHandle(pyPluginHandle, &plugin, &key)) {
|
Chris@0
|
450 PyErr_SetString(PyExc_AttributeError,
|
Chris@0
|
451 "Invalid or already deleted plugin handle.");
|
Chris@4
|
452 return NULL;
|
Chris@4
|
453 }
|
Chris@0
|
454
|
Chris@0
|
455 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
|
Chris@0
|
456
|
Chris@0
|
457 if (!pd->isInitialised) {
|
Chris@0
|
458 PyErr_SetString(PyExc_StandardError,
|
Chris@0
|
459 "Plugin has not been initialised.");
|
Chris@0
|
460 return NULL; }
|
Chris@0
|
461
|
Chris@12
|
462 int channels = pd->channels;
|
Chris@12
|
463 // int blockSize = pd->blockSize;
|
Chris@0
|
464
|
Chris@4
|
465 if (!PyList_Check(pyBuffer)) {
|
Chris@4
|
466 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input.");
|
Chris@4
|
467 return NULL;
|
Chris@0
|
468 }
|
Chris@0
|
469
|
Chris@4
|
470 if (PyList_GET_SIZE(pyBuffer) != channels) {
|
Chris@6
|
471 std::cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << std::endl;
|
Chris@4
|
472 PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
|
Chris@4
|
473 return NULL;
|
Chris@4
|
474 }
|
Chris@0
|
475
|
Chris@4
|
476 float **inbuf = new float *[channels];
|
Chris@0
|
477
|
Chris@12
|
478 PyTypeConversions typeConv;
|
Chris@12
|
479 typeConv.setNumpyInstalled(true);
|
Chris@12
|
480
|
Chris@12
|
481 vector<vector<float> > data;
|
Chris@4
|
482 for (int c = 0; c < channels; ++c) {
|
Chris@4
|
483 PyObject *cbuf = PyList_GET_ITEM(pyBuffer, c);
|
Chris@12
|
484 data.push_back(typeConv.PyArray_To_FloatVector(cbuf));
|
Chris@12
|
485 }
|
Chris@12
|
486
|
Chris@12
|
487 for (int c = 0; c < channels; ++c) {
|
Chris@12
|
488 inbuf[c] = &data[c][0];
|
Chris@4
|
489 }
|
Chris@0
|
490
|
Chris@12
|
491 RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
|
Chris@0
|
492
|
Chris@0
|
493 //Call process and store the output
|
Chris@4
|
494 pd->output = plugin->process(inbuf, timeStamp);
|
Chris@0
|
495
|
Chris@0
|
496 /* TODO: DO SOMETHONG WITH THE FEATURE SET HERE */
|
Chris@0
|
497 /// convert to appropriate python objects, reuse types and conversion utilities from Vampy ...
|
Chris@0
|
498
|
Chris@4
|
499 delete[] inbuf;
|
Chris@0
|
500
|
Chris@4
|
501 return NULL; //!!! Need to return actual features!
|
Chris@0
|
502
|
Chris@0
|
503 }
|
Chris@0
|
504
|
Chris@0
|
505 /* GET / SET OUTPUT */
|
Chris@0
|
506
|
Chris@0
|
507 //getOutput(plugin,outputNo)
|
Chris@0
|
508 static PyObject *
|
Chris@0
|
509 vampyhost_getOutput(PyObject *self, PyObject *args) {
|
Chris@0
|
510
|
Chris@0
|
511 PyObject *pyPluginHandle;
|
Chris@0
|
512 // PyObject *pyBuffer;
|
Chris@0
|
513 // PyObject *pyRealTime;
|
Chris@0
|
514 PyObject *pyOutput;
|
Chris@0
|
515
|
luis@7
|
516 if (!PyArg_ParseTuple(args, "OO",
|
Chris@0
|
517 &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor
|
Chris@0
|
518 &pyOutput)) { // Output reference
|
Chris@0
|
519 PyErr_SetString(PyExc_TypeError,
|
Chris@0
|
520 "Required: plugin handle, buffer, timestmap.");
|
Chris@0
|
521 return NULL; }
|
Chris@0
|
522
|
luis@7
|
523 string *key;
|
luis@7
|
524 Plugin *plugin;
|
Chris@0
|
525
|
Chris@0
|
526 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
|
Chris@0
|
527 PyErr_SetString(PyExc_AttributeError,
|
Chris@0
|
528 "Invalid or already deleted plugin handle.");
|
Chris@0
|
529 return NULL; }
|
Chris@0
|
530
|
Chris@0
|
531 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
|
Chris@0
|
532
|
Chris@0
|
533 unsigned int outputNo = (unsigned int) PyInt_AS_LONG(pyOutput);
|
Chris@0
|
534
|
Chris@0
|
535 //Get output list: but we don't need it
|
Chris@0
|
536 //Plugin::FeatureList features = pd->output[outputNo];
|
Chris@0
|
537
|
Chris@0
|
538 size_t outLength = pd->output[outputNo].size();
|
Chris@0
|
539
|
Chris@0
|
540 //New PyList for the featurelist
|
Chris@0
|
541 PyObject *pyFeatureList = PyList_New(outLength);
|
Chris@0
|
542
|
Chris@0
|
543 for (size_t i = 0; i < outLength; ++i) {
|
Chris@0
|
544 // Test:
|
Chris@0
|
545 /*
|
luis@7
|
546 XxoObject *pyFeature = PyObject_New(XxoObject, &Xxo_Type);
|
Chris@0
|
547 if (pyFeature == NULL) break; //return NULL;
|
Chris@0
|
548
|
Chris@0
|
549 pyFeature->x_attr = NULL;
|
Chris@0
|
550 pyFeature->feature = &pd->output[outputNo][i];
|
Chris@0
|
551
|
luis@7
|
552 PyList_SET_ITEM(pyFeatureList,i,(PyObject*)pyFeature);
|
Chris@0
|
553 */
|
Chris@0
|
554 }
|
Chris@0
|
555
|
Chris@0
|
556 Py_INCREF(pyFeatureList);
|
Chris@0
|
557 return pyFeatureList;
|
Chris@0
|
558
|
Chris@0
|
559 // EXPLAIN WHAT WE NEED TO DO HERE:
|
Chris@0
|
560 // We have the block output in pd->output
|
luis@7
|
561 // FeatureSet[output] -> [Feature[x]] -> Feature.hasTimestamp = v
|
luis@7
|
562 // Vamp::Plugin::FeatureSet output; = pd->output
|
Chris@0
|
563 // typedef std::vector<Feature> FeatureList;
|
Chris@0
|
564 // typedef std::map<int, FeatureList> FeatureSet; // key is output no
|
Chris@0
|
565
|
luis@7
|
566 // THIS IS FOR OUTPUT id LOOKUP LATER
|
Chris@0
|
567 // Plugin::OutputList outputs = plugin->getOutputDescriptors();
|
luis@7
|
568 //
|
Chris@0
|
569 // if (outputs.size()<1) {
|
Chris@0
|
570 // string pyerr("Plugin has no output: "); pyerr += pluginKey;
|
luis@7
|
571 // PyErr_SetString(PyExc_TypeError,pyerr.c_str());
|
Chris@0
|
572 // return NULL;
|
Chris@0
|
573 // }
|
luis@7
|
574 //
|
Chris@0
|
575 // //New list object
|
Chris@0
|
576 // PyObject *pyList = PyList_New(outputs.size());
|
luis@7
|
577 //
|
Chris@0
|
578 // for (size_t i = 0; i < outputs.size(); ++i) {
|
luis@7
|
579 // PyObject *pyOutputId =
|
Chris@0
|
580 // PyString_FromString(outputs[i].identifier.c_str());
|
luis@7
|
581 // PyList_SET_ITEM(pyList,i,pyOutputId);
|
Chris@0
|
582 // }
|
luis@7
|
583
|
Chris@0
|
584 }
|
Chris@0
|
585
|
Chris@0
|
586
|
Chris@0
|
587
|
Chris@0
|
588
|
Chris@0
|
589 /* List of functions defined in this module */
|
Chris@0
|
590 //module methods table
|
Chris@0
|
591 static PyMethodDef vampyhost_methods[] = {
|
Chris@0
|
592
|
Chris@0
|
593 {"enumeratePlugins", vampyhost_enumeratePlugins, METH_VARARGS,
|
Chris@0
|
594 xx_foo_doc},
|
Chris@0
|
595
|
Chris@0
|
596 {"getLibraryPath", vampyhost_getLibraryPath, METH_VARARGS,
|
Chris@0
|
597 xx_foo_doc},
|
Chris@0
|
598
|
Chris@0
|
599 {"getPluginCategory", vampyhost_getPluginCategory, METH_VARARGS,
|
Chris@0
|
600 xx_foo_doc},
|
Chris@0
|
601
|
Chris@0
|
602 {"getOutputList", vampyhost_getOutputList, METH_VARARGS,
|
Chris@0
|
603 xx_foo_doc},
|
Chris@0
|
604
|
Chris@0
|
605 {"loadPlugin", vampyhost_loadPlugin, METH_VARARGS,
|
Chris@0
|
606 xx_foo_doc},
|
Chris@0
|
607
|
Chris@0
|
608 {"process", vampyhost_process, METH_VARARGS,
|
Chris@0
|
609 xx_foo_doc},
|
Chris@0
|
610
|
Chris@0
|
611 {"unloadPlugin", vampyhost_unloadPlugin, METH_VARARGS,
|
Chris@0
|
612 xx_foo_doc},
|
Chris@0
|
613
|
Chris@0
|
614 {"initialise", vampyhost_initialise, METH_VARARGS,
|
Chris@0
|
615 xx_foo_doc},
|
Chris@0
|
616
|
Chris@0
|
617 {"getOutput", vampyhost_getOutput, METH_VARARGS,
|
Chris@0
|
618 xx_foo_doc},
|
Chris@0
|
619
|
Chris@0
|
620 /* Add RealTime Module Methods */
|
Chris@12
|
621 /*
|
Chris@0
|
622 {"frame2RealTime", (PyCFunction)RealTime_frame2RealTime, METH_VARARGS,
|
Chris@0
|
623 PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")},
|
Chris@0
|
624
|
Chris@0
|
625 {"realtime", (PyCFunction)RealTime_new, METH_VARARGS,
|
Chris@0
|
626 PyDoc_STR("realtime() -> returns new RealTime object")},
|
Chris@12
|
627 */
|
Chris@0
|
628 {NULL, NULL} /* sentinel */
|
Chris@0
|
629 };
|
Chris@0
|
630
|
Chris@0
|
631 //Documentation for our new module
|
Chris@0
|
632 PyDoc_STRVAR(module_doc, "This is a template module just for instruction.");
|
Chris@0
|
633
|
Chris@14
|
634
|
Chris@14
|
635
|
Chris@0
|
636 /* Initialization function for the module (*must* be called initxx) */
|
Chris@0
|
637
|
Chris@0
|
638 //module initialization (includes extern C {...} as necessary)
|
Chris@0
|
639 PyMODINIT_FUNC
|
Chris@0
|
640 initvampyhost(void)
|
Chris@0
|
641 {
|
Chris@0
|
642 PyObject *m;
|
Chris@0
|
643
|
Chris@0
|
644 /* Finalize the type object including setting type of the new type
|
luis@7
|
645 * object; doing it here is required for portability to Windows
|
Chris@0
|
646 * without requiring C++. */
|
Chris@0
|
647
|
Chris@0
|
648 if (PyType_Ready(&RealTime_Type) < 0)
|
Chris@0
|
649 return;
|
Chris@0
|
650 // PyModule_AddObject(m, "Real_Time", (PyObject *)&RealTime_Type);
|
Chris@0
|
651
|
Chris@0
|
652 /* Create the module and add the functions */
|
Chris@0
|
653 m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc);
|
Chris@0
|
654 if (m == NULL) return;
|
Chris@0
|
655
|
Chris@14
|
656 import_array();
|
Chris@14
|
657
|
Chris@0
|
658 // PyModule_AddObject(m, "realtime", (PyObject *)&RealTime_Type);
|
Chris@0
|
659
|
Chris@0
|
660 }
|