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