comparison vampy-main.cpp @ 67:146d14ab15e7

Debug output: off by default, on with VAMPY_VERBOSE environment variable
author Chris Cannam
date Mon, 17 Nov 2014 10:03:44 +0000
parents 5664fe298af2
children 6c755f3e1173
comparison
equal deleted inserted replaced
66:5664fe298af2 67:146d14ab15e7
39 #include "vamp-sdk/PluginAdapter.h" 39 #include "vamp-sdk/PluginAdapter.h"
40 #include "PyPlugScanner.h" 40 #include "PyPlugScanner.h"
41 #include "PyPlugin.h" 41 #include "PyPlugin.h"
42 #include "PyExtensionModule.h" 42 #include "PyExtensionModule.h"
43 #include "PyExtensionManager.h" 43 #include "PyExtensionManager.h"
44 #include "Debug.h"
44 #include <sstream> 45 #include <sstream>
45 46
46 #ifdef _WIN32 47 #ifdef _WIN32
47 #define pathsep ('\\') 48 #define pathsep ('\\')
48 #include <windows.h> 49 #include <windows.h>
70 PluginAdapterBase(), 71 PluginAdapterBase(),
71 m_plug(pyPlugId), 72 m_plug(pyPlugId),
72 m_pyClass(pyClass), 73 m_pyClass(pyClass),
73 m_failed(false) 74 m_failed(false)
74 { 75 {
75 cerr << "PyPluginAdapter:ctor:"<< adinstcount << ": " << m_plug << endl; 76 DSTREAM << "PyPluginAdapter:ctor:"<< adinstcount << ": " << m_plug << endl;
76 adinstcount++; 77 adinstcount++;
77 } 78 }
78 79
79 ~PyPluginAdapter() 80 ~PyPluginAdapter()
80 { 81 {
88 { 89 {
89 try { 90 try {
90 PyPlugin *plugin = new PyPlugin(m_plug, inputSampleRate, m_pyClass, totinstcount, numpyInstalled); 91 PyPlugin *plugin = new PyPlugin(m_plug, inputSampleRate, m_pyClass, totinstcount, numpyInstalled);
91 return plugin; 92 return plugin;
92 } catch (...) { 93 } catch (...) {
93 cerr << "PyPluginAdapter::createPlugin: Failed to construct PyPlugin" << endl; 94 cerr << "ERROR: PyPluginAdapter::createPlugin: Failed to construct PyPlugin" << endl;
94 // any plugin with syntax errors will fail to construct 95 // any plugin with syntax errors will fail to construct
95 m_failed = true; 96 m_failed = true;
96 return 0; 97 return 0;
97 } 98 }
98 } 99 }
99 100
100 std::string m_plug; 101 std::string m_plug;
119 string ver; 120 string ver;
120 std::istringstream verStream; 121 std::istringstream verStream;
121 float numpyVersion; 122 float numpyVersion;
122 123
123 /// attmept to test numpy version before importing the array API 124 /// attmept to test numpy version before importing the array API
124 cerr << "Numpy build information: ABI level: " << NPY_VERSION 125 DSTREAM << "Numpy build information: ABI level: " << NPY_VERSION
125 << " Numpy version: " << NUMPY_SHORTVERSION << endl; 126 << " Numpy version: " << NUMPY_SHORTVERSION << endl;
126 127
127 PyObject *pyModule, *pyDict, *pyVer; 128 PyObject *pyModule, *pyDict, *pyVer;
128 129
129 pyModule = PyImport_ImportModule("numpy"); //numpy.core.multiarray 130 pyModule = PyImport_ImportModule("numpy"); //numpy.core.multiarray
130 if (!pyModule) { 131 if (!pyModule) {
131 cerr << "Vampy was compiled with Numpy support but Numpy does not seem to be installed." << endl; 132 cerr << "ERROR: Vampy was compiled with Numpy support but Numpy does not seem to be installed." << endl;
132 #ifdef __APPLE__ 133 #ifdef __APPLE__
133 cerr << "Hint: Check if Numpy is installed for the particular setup of Python used by Vampy (given by Python exec prefix)." << endl; 134 cerr << "Hint: Check if Numpy is installed for the particular setup of Python used by Vampy (given by Python exec prefix)." << endl;
134 #endif 135 #endif
135 goto numpyFailure; 136 goto numpyFailure;
136 } 137 }
137 138
138 pyDict = PyModule_GetDict(pyModule); // borrowed ref 139 pyDict = PyModule_GetDict(pyModule); // borrowed ref
139 if (!pyDict) { 140 if (!pyDict) {
140 cerr << "Can not access Numpy module dictionary." << endl; 141 cerr << "ERROR: Can not access Numpy module dictionary." << endl;
141 goto numpyFailure; 142 goto numpyFailure;
142 } 143 }
143 144
144 pyVer = PyDict_GetItemString(pyDict,"__version__"); //borrowed ref 145 pyVer = PyDict_GetItemString(pyDict,"__version__"); //borrowed ref
145 if (!pyVer) { 146 if (!pyVer) {
146 cerr << "Can not access Numpy version information." << endl; 147 cerr << "ERROR: Can not access Numpy version information." << endl;
147 goto numpyFailure; 148 goto numpyFailure;
148 } 149 }
149 150
150 ver = PyString_AsString(pyVer); 151 ver = PyString_AsString(pyVer);
151 ver = ver.substr(0,ver.rfind(".")); 152 ver = ver.substr(0,ver.rfind("."));
152 /* 153
153 Applied patch from here: http://vamp-plugins.org/forum/index.php/topic,162.msg387.html#msg387 to replace this:
154 if(EOF == sscanf(ver.c_str(), "%f", &numpyVersion))
155 {
156 cerr << "Could not parse Numpy version information." << endl;
157 goto numpyFailure;
158 }*/
159 // parse version string to float 154 // parse version string to float
160 verStream.str(ver); 155 verStream.str(ver);
161 verStream >> numpyVersion; 156 verStream >> numpyVersion;
162 157
163 cerr << "Numpy runtime version: " << numpyVersion << endl; 158 DSTREAM << "Numpy runtime version: " << numpyVersion << endl;
164 if (numpyVersion < (float) NUMPY_SHORTVERSION) { 159 if (numpyVersion < (float) NUMPY_SHORTVERSION) {
165 cerr << "Incompatible Numpy version found: " << numpyVersion << endl; 160 cerr << "ERROR: Incompatible Numpy version found: " << numpyVersion << endl;
166 goto numpyFailure; 161 goto numpyFailure;
167 } 162 }
168 163
169 Py_DECREF(pyModule); 164 Py_DECREF(pyModule);
170 165
171 // At least we catch import errors, but if binary compatibility 166 // At least we catch import errors, but if binary compatibility
172 // has changed without notice, this would still fail. 167 // has changed without notice, this would still fail.
173 // However, we should never get to this point now anyway. 168 // However, we should never get to this point now anyway.
174 import_array(); 169 import_array();
175 if (PyErr_Occurred()) { 170 if (PyErr_Occurred()) {
176 cerr << "Import error while loading the Numpy Array API." << endl; 171 cerr << "ERROR: Import error while loading the Numpy Array API." << endl;
177 PyErr_Print(); PyErr_Clear(); 172 PyErr_Print(); PyErr_Clear();
178 goto numpyFailure; 173 goto numpyFailure;
179 } 174 }
180 else { 175 else {
181
182 #ifdef _DEBUG
183 if (NPY_VERSION != PyArray_GetNDArrayCVersion()) {
184 // the Import function does this check already.
185 cerr << "Warning: Numpy version mismatch. (Build version: "
186 << NPY_VERSION << " Runtime version: " << PyArray_GetNDArrayCVersion() << ")" << endl;
187 goto numpyFailure;
188 }
189 #endif
190
191 numpyInstalled = true; 176 numpyInstalled = true;
192 arrayApiInitialised = true; 177 arrayApiInitialised = true;
193 return; 178 return;
194 } 179 }
195 180
227 if (!lib) { 212 if (!lib) {
228 //perror("dlopen"); 213 //perror("dlopen");
229 return false; 214 return false;
230 } 215 }
231 #endif 216 #endif
232 cerr << "Preloaded Python from " << name << endl; 217 DSTREAM << "Preloaded Python from " << name << endl;
233 return true; 218 return true;
234 } 219 }
235 220
236 static bool preloadPython() 221 static bool preloadPython()
237 { 222 {
249 shortver = pyver.substr(0, i); 234 shortver = pyver.substr(0, i);
250 break; 235 break;
251 } 236 }
252 } 237 }
253 } 238 }
254 cerr << "Short version: " << shortver << endl; 239 DSTREAM << "Short version: " << shortver << endl;
255 // this is useful to find out where the loaded library might be loaded from 240 // this is useful to find out where the loaded library might be loaded from
256 cerr << "Python exec prefix: " << Py_GetExecPrefix() << endl; 241 DSTREAM << "Python exec prefix: " << Py_GetExecPrefix() << endl;
257 242
258 char *pylib = getenv("VAMPY_PYLIB"); 243 char *pylib = getenv("VAMPY_PYLIB");
259 if (pylib && *pylib) { 244 if (pylib && *pylib) {
260 cerr << "Trying to preload Python from specified location " << pylib 245 DSTREAM << "Trying to preload Python from specified location " << pylib
261 << "..." << endl; 246 << "..." << endl;
262 return tryPreload(string(pylib)); 247 return tryPreload(string(pylib));
263 } 248 }
264 249
265 vector<string> pfxs; 250 vector<string> pfxs;
266 pfxs.push_back(string(Py_GetExecPrefix()) + "/"); 251 pfxs.push_back(string(Py_GetExecPrefix()) + "/");
303 *vampGetPluginDescriptor(unsigned int version,unsigned int index) 288 *vampGetPluginDescriptor(unsigned int version,unsigned int index)
304 { 289 {
305 if (version < 1) return 0; 290 if (version < 1) return 0;
306 291
307 int isPythonInitialized = Py_IsInitialized(); 292 int isPythonInitialized = Py_IsInitialized();
308 cerr << "# isPythonInitialized: " << isPythonInitialized << endl; 293 DSTREAM << "# isPythonInitialized: " << isPythonInitialized << endl;
309 cerr << "# haveScannedPlugins: " << haveScannedPlugins << endl; 294 DSTREAM << "# haveScannedPlugins: " << haveScannedPlugins << endl;
310 295
311 if (!haveScannedPlugins) { 296 if (!haveScannedPlugins) {
312 297
313 if (!isPythonInitialized){ 298 if (!isPythonInitialized){
314 299
317 if (PyImport_AppendInittab("vampy",initvampy) != 0) 302 if (PyImport_AppendInittab("vampy",initvampy) != 0)
318 cerr << "Warning: Extension module could not be added to module inittab." << endl; 303 cerr << "Warning: Extension module could not be added to module inittab." << endl;
319 Py_Initialize(); 304 Py_Initialize();
320 array_API_initialiser(); 305 array_API_initialiser();
321 initvampy(); 306 initvampy();
322 #ifdef _DEBUG 307 DSTREAM << "# isPythonInitialized after initialize: " << Py_IsInitialized() << endl;
323 cerr << "# isPythonInitialized after initialize: " << Py_IsInitialized() << endl;
324 #endif
325 } 308 }
326 309
327 vector<string> pyPlugs; 310 vector<string> pyPlugs;
328 vector<string> pyPath; 311 vector<string> pyPath;
329 vector<PyObject *> pyClasses; 312 vector<PyObject *> pyClasses;
330 static PyPlugScanner *scanner; 313 static PyPlugScanner *scanner;
331 314
332 //Scanning Plugins 315 //Scanning Plugins
333 cerr << "Scanning Vampy Plugins" << endl; 316 DSTREAM << "Scanning Vampy Plugins" << endl;
334 scanner = PyPlugScanner::getInstance(); 317 scanner = PyPlugScanner::getInstance();
335 318
336 // added env. varable support VAMPY_EXTPATH 319 // added env. varable support VAMPY_EXTPATH
337 pyPath=scanner->getAllValidPath(); 320 pyPath=scanner->getAllValidPath();
338 scanner->setPath(pyPath); 321 scanner->setPath(pyPath);
339 322
340 // added env. variable support: 323 // added env. variable support:
341 // VAMPY_COMPILED=1 to recognise .pyc files (default is 1) 324 // VAMPY_COMPILED=1 to recognise .pyc files (default is 1)
342 pyPlugs = scanner->getPyPlugs(); 325 pyPlugs = scanner->getPyPlugs();
343 326
344 cerr << "Found " << pyPlugs.size() << " Scripts." << endl; 327 DSTREAM << "Found " << pyPlugs.size() << " Scripts." << endl;
345 //TODO: should this support multiple classes per script (?) 328 //TODO: should this support multiple classes per script (?)
346 pyClasses = scanner->getPyClasses(); 329 pyClasses = scanner->getPyClasses();
347 cerr << "Found " << pyClasses.size() << " Classes." << endl; 330 DSTREAM << "Found " << pyClasses.size() << " Classes." << endl;
348 331
349 for (size_t i = 0; i < pyPlugs.size(); ++i) { 332 for (size_t i = 0; i < pyPlugs.size(); ++i) {
350 adapters.push_back( new PyPluginAdapter(pyPlugs[i],pyClasses[i])); 333 adapters.push_back( new PyPluginAdapter(pyPlugs[i],pyClasses[i]));
351 } 334 }
352 pyExtensionManager.setPlugModuleNames(pyPlugs); 335 pyExtensionManager.setPlugModuleNames(pyPlugs);
353 pyExtensionManager.initExtension(); 336 pyExtensionManager.initExtension();
354 array_API_initialiser(); 337 array_API_initialiser();
355 haveScannedPlugins=true; 338 haveScannedPlugins=true;
356 } 339 }
357 340
358 #ifdef _DEBUG 341 DSTREAM << "Accessing adapter index: " << index << " (adapters: " << adapters.size() << ")" << endl;
359 cerr << "Accessing adapter index: " << index << " (adapters: " << adapters.size() << ")" << endl;
360 #endif
361 342
362 if (index<adapters.size()) { 343 if (index<adapters.size()) {
363 344
364 const VampPluginDescriptor *tmp = adapters[index]->getDescriptor(); 345 const VampPluginDescriptor *tmp = adapters[index]->getDescriptor();
365 346