comparison vampyhost.cpp @ 16:7987e3123909

Rationalise plugin handle management
author Chris Cannam
date Mon, 24 Nov 2014 14:39:56 +0000
parents 8b264cabbc28
children 3893b76daf80
comparison
equal deleted inserted replaced
15:8b264cabbc28 16:7987e3123909
7 #define PY_ARRAY_UNIQUE_SYMBOL VAMPY_ARRAY_API 7 #define PY_ARRAY_UNIQUE_SYMBOL VAMPY_ARRAY_API
8 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION 8 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
9 #include "numpy/arrayobject.h" 9 #include "numpy/arrayobject.h"
10 10
11 #include <vampyhost.h> 11 #include <vampyhost.h>
12
13 #include "PyTypeConversions.h"
14 #include "PyRealTime.h"
15
16 //!!! NB all our NumPy stuff is currently using the deprecated API --
17 //!!! need to work out how to update this
18 //#include "numpy/arrayobject.h"
19 12
20 #define HAVE_NUMPY 1 // Required 13 #define HAVE_NUMPY 1 // Required
21 14
22 //includes for vamp host 15 //includes for vamp host
23 #include "vamp-hostsdk/Plugin.h" 16 #include "vamp-hostsdk/Plugin.h"
24 #include "vamp-hostsdk/PluginHostAdapter.h" 17 #include "vamp-hostsdk/PluginHostAdapter.h"
25 #include "vamp-hostsdk/PluginChannelAdapter.h" 18 #include "vamp-hostsdk/PluginChannelAdapter.h"
26 #include "vamp-hostsdk/PluginInputDomainAdapter.h" 19 #include "vamp-hostsdk/PluginInputDomainAdapter.h"
27 #include "vamp-hostsdk/PluginLoader.h" 20 #include "vamp-hostsdk/PluginLoader.h"
28 //#include "vamp/vamp.h" 21
22 #include "PyTypeConversions.h"
23 #include "PyRealTime.h"
29 24
30 #include <iostream> 25 #include <iostream>
31 #include <fstream> 26 #include <fstream>
32 #include <set> 27 #include <set>
33 #include <sndfile.h> 28 #include <sndfile.h>
34 29
35 #include <cstring> 30 #include <cstring>
36 #include <cstdlib> 31 #include <cstdlib>
37 #include <string> 32 #include <string>
38 33
39 #include "system.h"
40
41 #include <cmath> 34 #include <cmath>
42
43 35
44 using namespace std; 36 using namespace std;
45 using namespace Vamp; 37 using namespace Vamp;
46 38
47 using Vamp::Plugin; 39 using Vamp::Plugin;
49 using Vamp::RealTime; 41 using Vamp::RealTime;
50 using Vamp::HostExt::PluginLoader; 42 using Vamp::HostExt::PluginLoader;
51 43
52 #define HOST_VERSION "1.1" 44 #define HOST_VERSION "1.1"
53 45
46 // structure for holding plugin instance data
47 struct PyPluginData
48 {
49 PyPluginData(string k, Plugin *p, float rate) :
50 key(k),
51 plugin(p),
52 inputSampleRate(rate),
53 isInitialised(false),
54 channels(0),
55 blockSize(0),
56 stepSize(0) {
57 }
58
59 string key;
60 Plugin *plugin;
61 float inputSampleRate;
62 bool isInitialised;
63 size_t channels;
64 size_t blockSize;
65 size_t stepSize;
66 Vamp::Plugin::FeatureSet output;
67 };
54 68
55 /* MODULE HELPER FUNCTIONS */ 69 /* MODULE HELPER FUNCTIONS */
56 PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!! 70 PyDoc_STRVAR(xx_foo_doc, "Some description"); //!!!
57 71
58 /*obtain C plugin handle and key from pyCobject */ 72 //!!! nb "The CObject API is deprecated" https://docs.python.org/2/c-api/cobject.html
59 bool getPluginHandle 73
60 (PyObject *pyPluginHandle, Plugin **plugin, string **pKey=NULL) { 74 PyPluginData *
61 75 getPluginData(PyObject *pyPluginHandle)
62 //char errormsg[]="Wrong input argument: Plugin Handle required."; 76 {
63 77 PyPluginData *pd = 0;
64 *plugin = NULL; 78 if (PyCObject_Check(pyPluginHandle)) {
65 if (!PyCObject_Check(pyPluginHandle)) return false; 79 pd = (PyPluginData *)PyCObject_AsVoidPtr(pyPluginHandle);
66 80 }
67 //try to convert to Plugin pointer 81 if (!pd || !pd->plugin) {
68 Plugin *p = (Plugin*) PyCObject_AsVoidPtr(pyPluginHandle); 82 PyErr_SetString(PyExc_AttributeError,
69 if (!p) return false; 83 "Invalid or already deleted plugin handle.");
70 84 return 0;
71 string pId;
72
73 if (pKey) {
74 *pKey = (string*) PyCObject_GetDesc(pyPluginHandle);
75 if (!*pKey) return false;
76 pId = *(string*) *pKey;
77
78 } else { 85 } else {
79 86 return pd;
80 void *pKey = PyCObject_GetDesc(pyPluginHandle); 87 }
81 if (!pKey) return false; 88 }
82 pId = *(string*) pKey;
83 }
84
85 string::size_type pos = pId.find(':');
86 if (pos == string::npos) return false;
87
88 pId = pId.substr(pId.rfind(':')+1);
89 string identifier = p->getIdentifier();
90
91 if (pId.compare(identifier)) return false;
92
93 *plugin = p;
94 return true;
95 }
96
97 /*
98 ----------------------------------------------------------------
99 */
100
101
102
103 /*
104 VAMPYHOST MAIN
105 ---------------------------------------------------------------------
106 */
107 89
108 static PyObject * 90 static PyObject *
109 vampyhost_enumeratePlugins(PyObject *self, PyObject *args) 91 vampyhost_enumeratePlugins(PyObject *self, PyObject *args)
110 { 92 {
111 PluginLoader *loader = PluginLoader::getInstance(); 93 PluginLoader *loader = PluginLoader::getInstance();
144 PyObject *pyPluginKey; 126 PyObject *pyPluginKey;
145 127
146 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) { 128 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
147 PyErr_SetString(PyExc_TypeError, 129 PyErr_SetString(PyExc_TypeError,
148 "getLibraryPathForPlugin() takes plugin key (string) argument"); 130 "getLibraryPathForPlugin() takes plugin key (string) argument");
149 return NULL; } 131 return 0; }
150 132
151 string pluginKey = toPluginKey(pyPluginKey); 133 string pluginKey = toPluginKey(pyPluginKey);
152 if (pluginKey == "") return NULL; 134 if (pluginKey == "") return 0;
153 135
154 PluginLoader *loader = PluginLoader::getInstance(); 136 PluginLoader *loader = PluginLoader::getInstance();
155 string path = loader->getLibraryPathForPlugin(pluginKey); 137 string path = loader->getLibraryPathForPlugin(pluginKey);
156 PyObject *pyPath = PyString_FromString(path.c_str()); 138 PyObject *pyPath = PyString_FromString(path.c_str());
157 return pyPath; 139 return pyPath;
163 PyObject *pyPluginKey; 145 PyObject *pyPluginKey;
164 146
165 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) { 147 if (!PyArg_ParseTuple(args, "S", &pyPluginKey)) {
166 PyErr_SetString(PyExc_TypeError, 148 PyErr_SetString(PyExc_TypeError,
167 "getPluginCategory() takes plugin key (string) argument"); 149 "getPluginCategory() takes plugin key (string) argument");
168 return NULL; } 150 return 0; }
169 151
170 string pluginKey = toPluginKey(pyPluginKey); 152 string pluginKey = toPluginKey(pyPluginKey);
171 if (pluginKey == "") return NULL; 153 if (pluginKey == "") return 0;
172 154
173 PluginLoader *loader = PluginLoader::getInstance(); 155 PluginLoader *loader = PluginLoader::getInstance();
174 PluginLoader::PluginCategoryHierarchy 156 PluginLoader::PluginCategoryHierarchy
175 category = loader->getPluginCategory(pluginKey); 157 category = loader->getPluginCategory(pluginKey);
176 158
179 } 161 }
180 162
181 static PyObject * 163 static PyObject *
182 vampyhost_getOutputList(PyObject *self, PyObject *args) 164 vampyhost_getOutputList(PyObject *self, PyObject *args)
183 { 165 {
184 PyObject *pyPluginHandle; 166 PyObject *keyOrHandle;
185 Plugin::OutputList outputs; 167 Plugin::OutputList outputs;
186 168
187 if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) { 169 if (!PyArg_ParseTuple(args, "O", &keyOrHandle)) {
188 PyErr_SetString(PyExc_TypeError, 170 PyErr_SetString(PyExc_TypeError,
189 "getOutputList() takes plugin handle (object) or plugin key (string) argument"); 171 "getOutputList() takes plugin handle (object) or plugin key (string) argument");
190 return NULL; 172 return 0;
191 } 173 }
192 174
193 if (PyString_Check(pyPluginHandle) ) { 175 if (PyString_Check(keyOrHandle) ) {
194 176
195 // we have a plugin key 177 // we have a plugin key
196 178
197 string pluginKey = toPluginKey(pyPluginHandle); 179 string pluginKey = toPluginKey(keyOrHandle);
198 if (pluginKey == "") return NULL; 180 if (pluginKey == "") return 0;
199 181
200 PluginLoader *loader = PluginLoader::getInstance(); 182 PluginLoader *loader = PluginLoader::getInstance();
201 183
202 Plugin *plugin = loader->loadPlugin 184 Plugin *plugin = loader->loadPlugin
203 (pluginKey, 48000, PluginLoader::ADAPT_ALL_SAFE); 185 (pluginKey, 48000, PluginLoader::ADAPT_ALL_SAFE);
204 if (!plugin) { 186 if (!plugin) {
205 string pyerr("Failed to load plugin: "); pyerr += pluginKey; 187 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
206 PyErr_SetString(PyExc_TypeError,pyerr.c_str()); 188 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
207 return NULL; 189 return 0;
208 } 190 }
209 191
210 outputs = plugin->getOutputDescriptors(); 192 outputs = plugin->getOutputDescriptors();
211 193
212 delete plugin; 194 delete plugin;
213 195
214 } else { 196 } else {
215 197
216 // we have a loaded plugin handle 198 // we have a loaded plugin handle
217 199
218 string *key; 200 PyPluginData *pd = getPluginData(keyOrHandle);
219 Plugin *plugin; 201 if (!pd) return 0;
220 202
221 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) { 203 outputs = pd->plugin->getOutputDescriptors();
222 PyErr_SetString(PyExc_TypeError,
223 "Invalid or deleted plugin handle.");
224 return NULL; }
225
226 outputs = plugin->getOutputDescriptors();
227 } 204 }
228 205
229 PyObject *pyList = PyList_New(outputs.size()); 206 PyObject *pyList = PyList_New(outputs.size());
230 207
231 for (size_t i = 0; i < outputs.size(); ++i) { 208 for (size_t i = 0; i < outputs.size(); ++i) {
246 if (!PyArg_ParseTuple(args, "Sf", 223 if (!PyArg_ParseTuple(args, "Sf",
247 &pyPluginKey, 224 &pyPluginKey,
248 &inputSampleRate)) { 225 &inputSampleRate)) {
249 PyErr_SetString(PyExc_TypeError, 226 PyErr_SetString(PyExc_TypeError,
250 "loadPlugin() takes plugin key (string) and sample rate (number) arguments"); 227 "loadPlugin() takes plugin key (string) and sample rate (number) arguments");
251 return NULL; } 228 return 0; }
252 229
253 string pluginKey = toPluginKey(pyPluginKey); 230 string pluginKey = toPluginKey(pyPluginKey);
254 if (pluginKey == "") return NULL; 231 if (pluginKey == "") return 0;
255 232
256 PluginLoader *loader = PluginLoader::getInstance(); 233 PluginLoader *loader = PluginLoader::getInstance();
257 234
258 Plugin *plugin = loader->loadPlugin(pluginKey, inputSampleRate, 235 Plugin *plugin = loader->loadPlugin(pluginKey, inputSampleRate,
259 PluginLoader::ADAPT_ALL_SAFE); 236 PluginLoader::ADAPT_ALL_SAFE);
260 if (!plugin) { 237 if (!plugin) {
261 string pyerr("Failed to load plugin: "); pyerr += pluginKey; 238 string pyerr("Failed to load plugin: "); pyerr += pluginKey;
262 PyErr_SetString(PyExc_TypeError,pyerr.c_str()); 239 PyErr_SetString(PyExc_TypeError,pyerr.c_str());
263 return NULL; 240 return 0;
264 } 241 }
265 242
266 PyPluginDescriptor *pd = new PyPluginDescriptor; 243 PyPluginData *pd = new PyPluginData(pluginKey, plugin, inputSampleRate);
267 244 return PyCObject_FromVoidPtr(pd, 0);
268 pd->key = pluginKey; 245 }
269 pd->isInitialised = false;
270 pd->inputSampleRate = inputSampleRate;
271
272 PyObject *pyPluginHandle = PyCObject_FromVoidPtrAndDesc(
273 (void*) plugin, (void*) pd, NULL);
274
275 return pyPluginHandle;
276 }
277
278
279
280 /* UNLOAD PLUGIN */
281 246
282 static PyObject * 247 static PyObject *
283 vampyhost_unloadPlugin(PyObject *self, PyObject *args) 248 vampyhost_unloadPlugin(PyObject *self, PyObject *args)
284 { 249 {
285 PyObject *pyPluginHandle; 250 PyObject *pyPluginHandle;
286 251
287 if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) { 252 if (!PyArg_ParseTuple(args, "O", &pyPluginHandle)) {
288 PyErr_SetString(PyExc_TypeError, 253 PyErr_SetString(PyExc_TypeError,
289 "Wrong input argument: Plugin Handle required."); 254 "unloadPlugin() takes plugin handle (object) argument");
290 return NULL; } 255 return 0;
291 256 }
292 string *key; 257
293 Plugin *plugin; 258 PyPluginData *pd = getPluginData(pyPluginHandle);
294 259 if (!pd) return 0;
295 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) { 260
296 PyErr_SetString(PyExc_TypeError, 261 /* Prevent repeated calls from causing segfault since it will fail
297 "Invalid or already deleted plugin handle."); 262 * type checking the 2nd time: */
298 return NULL; } 263 PyCObject_SetVoidPtr(pyPluginHandle, 0);
299 264
300 /* Prevent repeated calls from causing segfault 265 delete pd->plugin;
301 sice it will fail type checking the 2nd time: */
302 PyCObject_SetVoidPtr(pyPluginHandle,NULL);
303
304 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
305
306 delete plugin;
307 delete pd; 266 delete pd;
308 return pyPluginHandle; 267 return pyPluginHandle;
309
310 } 268 }
311 269
312 270
313 /* INITIALISE PLUGIN */ 271 /* INITIALISE PLUGIN */
314 272
323 (size_t) &stepSize, 281 (size_t) &stepSize,
324 (size_t) &blockSize)) 282 (size_t) &blockSize))
325 { 283 {
326 PyErr_SetString(PyExc_TypeError, 284 PyErr_SetString(PyExc_TypeError,
327 "Wrong input arguments: requires a valid plugin handle,channels,stepSize,blockSize."); 285 "Wrong input arguments: requires a valid plugin handle,channels,stepSize,blockSize.");
328 return NULL; 286 return 0;
329 } 287 }
330 288
331 Plugin *plugin; 289 PyPluginData *pd = getPluginData(pyPluginHandle);
332 string *key; 290 if (!pd) return 0;
333 291
334 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) { 292 pd->channels = channels;
335 PyErr_SetString(PyExc_TypeError, 293 pd->stepSize = stepSize;
336 "Invalid plugin handle."); 294 pd->blockSize = blockSize;
337 return NULL; } 295
338 296 if (!pd->plugin->initialise(channels, stepSize, blockSize)) {
339 // here we cast the void pointer as PyPluginDescriptor instead of string
340 PyPluginDescriptor *plugDesc = (PyPluginDescriptor*) key;
341
342 plugDesc->channels = channels;
343 plugDesc->stepSize = stepSize;
344 plugDesc->blockSize = blockSize;
345
346 if (!plugin->initialise(channels, stepSize, blockSize)) {
347 std::cerr << "Failed to initialise native plugin adapter with channels = " << channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << " and ADAPT_ALL_SAFE set" << std::endl; 297 std::cerr << "Failed to initialise native plugin adapter with channels = " << channels << ", stepSize = " << stepSize << ", blockSize = " << blockSize << " and ADAPT_ALL_SAFE set" << std::endl;
348 PyErr_SetString(PyExc_TypeError, 298 PyErr_SetString(PyExc_TypeError,
349 "Plugin initialization failed."); 299 "Plugin initialization failed.");
350 return NULL; 300 return 0;
351 } 301 }
352 302
353 plugDesc->identifier = 303 pd->isInitialised = true;
354 plugDesc->key.substr(plugDesc->key.rfind(':')+1);
355 plugDesc->isInitialised = true;
356 304
357 return Py_True; 305 return Py_True;
358 } 306 }
359 307
360 /* RUN PROCESS */ 308 /* RUN PROCESS */
370 &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor 318 &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor
371 &pyBuffer, // Audio data 319 &pyBuffer, // Audio data
372 &pyRealTime)) { // TimeStamp 320 &pyRealTime)) { // TimeStamp
373 PyErr_SetString(PyExc_TypeError, 321 PyErr_SetString(PyExc_TypeError,
374 "Required: plugin handle, buffer, timestmap."); 322 "Required: plugin handle, buffer, timestmap.");
375 return NULL; } 323 return 0; }
376 324
377 if (!PyRealTime_Check(pyRealTime)) { 325 if (!PyRealTime_Check(pyRealTime)) {
378 PyErr_SetString(PyExc_TypeError,"Valid timestamp required."); 326 PyErr_SetString(PyExc_TypeError,"Valid timestamp required.");
379 return NULL; } 327 return 0; }
380 328
381 string *key; 329 PyPluginData *pd = getPluginData(pyPluginHandle);
382 Plugin *plugin; 330 if (!pd) return 0;
383
384 if (!getPluginHandle(pyPluginHandle, &plugin, &key)) {
385 PyErr_SetString(PyExc_AttributeError,
386 "Invalid or already deleted plugin handle.");
387 return NULL;
388 }
389
390 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
391 331
392 if (!pd->isInitialised) { 332 if (!pd->isInitialised) {
393 PyErr_SetString(PyExc_StandardError, 333 PyErr_SetString(PyExc_StandardError,
394 "Plugin has not been initialised."); 334 "Plugin has not been initialised.");
395 return NULL; } 335 return 0;
336 }
396 337
397 int channels = pd->channels; 338 int channels = pd->channels;
398 // int blockSize = pd->blockSize; 339 // int blockSize = pd->blockSize;
399 340
400 if (!PyList_Check(pyBuffer)) { 341 if (!PyList_Check(pyBuffer)) {
401 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input."); 342 PyErr_SetString(PyExc_TypeError, "List of NumPy Array required for process input.");
402 return NULL; 343 return 0;
403 } 344 }
404 345
405 if (PyList_GET_SIZE(pyBuffer) != channels) { 346 if (PyList_GET_SIZE(pyBuffer) != channels) {
406 std::cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << std::endl; 347 std::cerr << "Wrong number of channels: got " << PyList_GET_SIZE(pyBuffer) << ", expected " << channels << std::endl;
407 PyErr_SetString(PyExc_TypeError, "Wrong number of channels"); 348 PyErr_SetString(PyExc_TypeError, "Wrong number of channels");
408 return NULL; 349 return 0;
409 } 350 }
410 351
411 float **inbuf = new float *[channels]; 352 float **inbuf = new float *[channels];
412 353
413 PyTypeConversions typeConv; 354 PyTypeConversions typeConv;
424 } 365 }
425 366
426 RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime); 367 RealTime timeStamp = *PyRealTime_AsRealTime(pyRealTime);
427 368
428 //Call process and store the output 369 //Call process and store the output
429 pd->output = plugin->process(inbuf, timeStamp); 370 pd->output = pd->plugin->process(inbuf, timeStamp);
430 371
431 /* TODO: DO SOMETHONG WITH THE FEATURE SET HERE */ 372 /* TODO: DO SOMETHONG WITH THE FEATURE SET HERE */
432 /// convert to appropriate python objects, reuse types and conversion utilities from Vampy ... 373 /// convert to appropriate python objects, reuse types and conversion utilities from Vampy ...
433 374
434 delete[] inbuf; 375 delete[] inbuf;
435 376
436 return NULL; //!!! Need to return actual features! 377 return 0; //!!! Need to return actual features!
437 378
438 } 379 }
439 380
440 /* GET / SET OUTPUT */ 381 /* GET / SET OUTPUT */
441 382
451 if (!PyArg_ParseTuple(args, "OO", 392 if (!PyArg_ParseTuple(args, "OO",
452 &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor 393 &pyPluginHandle, // C object holding a pointer to a plugin and its descriptor
453 &pyOutput)) { // Output reference 394 &pyOutput)) { // Output reference
454 PyErr_SetString(PyExc_TypeError, 395 PyErr_SetString(PyExc_TypeError,
455 "Required: plugin handle, buffer, timestmap."); 396 "Required: plugin handle, buffer, timestmap.");
456 return NULL; } 397 return 0; }
457 398
458 string *key; 399 PyPluginData *pd = getPluginData(pyPluginHandle);
459 Plugin *plugin; 400 if (!pd) return 0;
460
461 if ( !getPluginHandle(pyPluginHandle, &plugin, &key) ) {
462 PyErr_SetString(PyExc_AttributeError,
463 "Invalid or already deleted plugin handle.");
464 return NULL; }
465
466 PyPluginDescriptor *pd = (PyPluginDescriptor*) key;
467 401
468 unsigned int outputNo = (unsigned int) PyInt_AS_LONG(pyOutput); 402 unsigned int outputNo = (unsigned int) PyInt_AS_LONG(pyOutput);
469 403
470 //Get output list: but we don't need it 404 //Get output list: but we don't need it
471 //Plugin::FeatureList features = pd->output[outputNo]; 405 //Plugin::FeatureList features = pd->output[outputNo];
477 411
478 for (size_t i = 0; i < outLength; ++i) { 412 for (size_t i = 0; i < outLength; ++i) {
479 // Test: 413 // Test:
480 /* 414 /*
481 XxoObject *pyFeature = PyObject_New(XxoObject, &Xxo_Type); 415 XxoObject *pyFeature = PyObject_New(XxoObject, &Xxo_Type);
482 if (pyFeature == NULL) break; //return NULL; 416 if (pyFeature == 0) break; //return 0;
483 417
484 pyFeature->x_attr = NULL; 418 pyFeature->x_attr = 0;
485 pyFeature->feature = &pd->output[outputNo][i]; 419 pyFeature->feature = &pd->output[outputNo][i];
486 420
487 PyList_SET_ITEM(pyFeatureList,i,(PyObject*)pyFeature); 421 PyList_SET_ITEM(pyFeatureList,i,(PyObject*)pyFeature);
488 */ 422 */
489 } 423 }
502 // Plugin::OutputList outputs = plugin->getOutputDescriptors(); 436 // Plugin::OutputList outputs = plugin->getOutputDescriptors();
503 // 437 //
504 // if (outputs.size()<1) { 438 // if (outputs.size()<1) {
505 // string pyerr("Plugin has no output: "); pyerr += pluginKey; 439 // string pyerr("Plugin has no output: "); pyerr += pluginKey;
506 // PyErr_SetString(PyExc_TypeError,pyerr.c_str()); 440 // PyErr_SetString(PyExc_TypeError,pyerr.c_str());
507 // return NULL; 441 // return 0;
508 // } 442 // }
509 // 443 //
510 // //New list object 444 // //New list object
511 // PyObject *pyList = PyList_New(outputs.size()); 445 // PyObject *pyList = PyList_New(outputs.size());
512 // 446 //
561 PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")}, 495 PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")},
562 496
563 {"realtime", (PyCFunction)RealTime_new, METH_VARARGS, 497 {"realtime", (PyCFunction)RealTime_new, METH_VARARGS,
564 PyDoc_STR("realtime() -> returns new RealTime object")}, 498 PyDoc_STR("realtime() -> returns new RealTime object")},
565 */ 499 */
566 {NULL, NULL} /* sentinel */ 500 {0, 0} /* sentinel */
567 }; 501 };
568 502
569 //Documentation for our new module 503 //Documentation for our new module
570 PyDoc_STRVAR(module_doc, "This is a template module just for instruction."); 504 PyDoc_STRVAR(module_doc, "This is a template module just for instruction.");
571 505
587 return; 521 return;
588 // PyModule_AddObject(m, "Real_Time", (PyObject *)&RealTime_Type); 522 // PyModule_AddObject(m, "Real_Time", (PyObject *)&RealTime_Type);
589 523
590 /* Create the module and add the functions */ 524 /* Create the module and add the functions */
591 m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc); 525 m = Py_InitModule3("vampyhost", vampyhost_methods, module_doc);
592 if (m == NULL) return; 526 if (!m) return;
593 527
594 import_array(); 528 import_array();
595 529
596 // PyModule_AddObject(m, "realtime", (PyObject *)&RealTime_Type); 530 // PyModule_AddObject(m, "realtime", (PyObject *)&RealTime_Type);
597 531