annotate vampy-main.cpp @ 35:2ba482378038 vampy2

* Fix compile error with VC++. I am totally at a loss to explain why this should have compiled with any other compiler! * Update VC project file. This code does now build with VC++ without HAVE_NUMPY -- I haven't installed Numpy yet
author cannam
date Thu, 24 Sep 2009 08:52:04 +0000
parents c905122f79e7
children
rev   line source
fazekasgy@31 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
fazekasgy@31 2
fazekasgy@31 3 /**
fazekasgy@31 4 * This Vamp plugin is a wrapper for Python Scripts. (VamPy)
fazekasgy@31 5 * Centre for Digital Music, Queen Mary, University of London.
fazekasgy@31 6 * Copyright 2008, George Fazekas.
fazekasgy@31 7 */
fazekasgy@31 8
fazekasgy@31 9 #include <Python.h>
fazekasgy@31 10 #include "vamp/vamp.h"
fazekasgy@31 11 #include "vamp-sdk/PluginAdapter.h"
fazekasgy@31 12 #include "PyPlugScanner.h"
fazekasgy@31 13 #include "PyPlugin.h"
fazekasgy@31 14 // #include "host/pyRealTime.h"
fazekasgy@31 15 #include "PyExtensionModule.h"
fazekasgy@31 16
fazekasgy@31 17
fazekasgy@31 18 #ifdef _WIN32
fazekasgy@31 19 #define pathsep ('\\')
fazekasgy@31 20 #include <windows.h>
fazekasgy@31 21 #include <tchar.h>
fazekasgy@31 22 #else
fazekasgy@31 23 #define pathsep ('/')
fazekasgy@31 24 #include <dirent.h>
fazekasgy@31 25 #include <dlfcn.h>
fazekasgy@31 26 #endif
fazekasgy@31 27
fazekasgy@31 28 using std::cerr;
fazekasgy@31 29 using std::endl;
fazekasgy@31 30 using std::string;
fazekasgy@31 31 using std::vector;
fazekasgy@31 32
fazekasgy@31 33
fazekasgy@31 34 //volatile bool mutex = false;
fazekasgy@31 35 static int adinstcount;
fazekasgy@31 36 static int totinstcount;
fazekasgy@31 37
fazekasgy@31 38 class PyPluginAdapter : public Vamp::PluginAdapterBase
fazekasgy@31 39 {
fazekasgy@31 40 public:
fazekasgy@31 41 PyPluginAdapter(std::string pyPlugId, PyObject* pyClass) :
fazekasgy@31 42 PluginAdapterBase(),
fazekasgy@31 43 m_plug(pyPlugId),
fazekasgy@31 44 m_pyClass(pyClass)
fazekasgy@31 45 {
fazekasgy@31 46 cerr << "PyPluginAdapter:ctor:"<< adinstcount << ": " << m_plug << endl;
fazekasgy@31 47 adinstcount++;
fazekasgy@31 48 m_instanceCount = 0;
fazekasgy@31 49 }
fazekasgy@31 50
fazekasgy@31 51 ~PyPluginAdapter()
fazekasgy@31 52 {
fazekasgy@31 53 }
fazekasgy@31 54
fazekasgy@31 55 protected:
fazekasgy@31 56 Vamp::Plugin *createPlugin(float inputSampleRate)
fazekasgy@31 57 {
fazekasgy@31 58 try {
fazekasgy@31 59 PyPlugin *plugin = new PyPlugin(m_plug, inputSampleRate, m_pyClass, totinstcount);
fazekasgy@31 60 // m_instanceCount++; /// do this in the ctors
fazekasgy@31 61 return plugin;
fazekasgy@31 62 } catch (...) {
fazekasgy@31 63 cerr << "PyPluginAdapter::createPlugin: Failed to construct PyPlugin" << endl;
fazekasgy@31 64 return 0;
fazekasgy@31 65 }
fazekasgy@31 66 }
fazekasgy@31 67
fazekasgy@31 68 std::string m_plug;
fazekasgy@31 69 bool m_haveInitialized;
fazekasgy@31 70 PyObject *m_pyClass;
fazekasgy@31 71 int m_instanceCount;
fazekasgy@31 72 };
fazekasgy@31 73
fazekasgy@31 74
fazekasgy@31 75 static std::vector<PyPluginAdapter *> adapters;
fazekasgy@31 76 static bool haveScannedPlugins = false;
fazekasgy@31 77 static bool haveVampyInitialised = false;
fazekasgy@31 78
fazekasgy@31 79 static bool tryPreload(string name)
fazekasgy@31 80 {
fazekasgy@31 81 #ifdef _WIN32
fazekasgy@31 82 void *lib = LoadLibrary(name.c_str());
fazekasgy@31 83 if (!lib) {
fazekasgy@31 84 return false;
fazekasgy@31 85 }
fazekasgy@31 86 #else
fazekasgy@31 87 void *lib = dlopen(name.c_str(), RTLD_NOW | RTLD_GLOBAL);
fazekasgy@31 88 if (!lib) {
fazekasgy@31 89 return false;
fazekasgy@31 90 }
fazekasgy@31 91 #endif
fazekasgy@31 92 return true;
fazekasgy@31 93 }
fazekasgy@31 94
fazekasgy@31 95 static bool preloadPython()
fazekasgy@31 96 {
fazekasgy@31 97 #ifdef _WIN32
fazekasgy@31 98 // this doesn't seem to be necessary at all on Windows
fazekasgy@31 99 return true;
fazekasgy@31 100 #endif
fazekasgy@31 101
fazekasgy@31 102 string pyver = Py_GetVersion();
fazekasgy@31 103 int dots = 2;
fazekasgy@31 104 string shortver;
fazekasgy@31 105 for (size_t i = 0; i < pyver.length(); ++i) {
fazekasgy@31 106 if (pyver[i] == '.') {
fazekasgy@31 107 if (--dots == 0) {
fazekasgy@31 108 shortver = pyver.substr(0, i);
fazekasgy@31 109 break;
fazekasgy@31 110 }
fazekasgy@31 111 }
fazekasgy@31 112 }
fazekasgy@31 113 cerr << "Short version: " << shortver << endl;
fazekasgy@31 114
fazekasgy@31 115 vector<string> pfxs;
fazekasgy@31 116 pfxs.push_back("");
fazekasgy@31 117 pfxs.push_back(string(Py_GetExecPrefix()) + "/lib/");
fazekasgy@31 118 pfxs.push_back(string(Py_GetExecPrefix()) + "/");
fazekasgy@31 119 pfxs.push_back("/usr/lib/");
fazekasgy@31 120 pfxs.push_back("/usr/local/lib/");
fazekasgy@31 121 char buffer[5];
fazekasgy@31 122
fazekasgy@31 123 // hahaha! grossness is like a brother to us
fazekasgy@31 124 #ifdef __APPLE__
fazekasgy@31 125 for (size_t pfxidx = 0; pfxidx < pfxs.size(); ++pfxidx) {
fazekasgy@31 126 for (int minor = 8; minor >= 0; --minor) {
fazekasgy@31 127 sprintf(buffer, "%d", minor);
fazekasgy@31 128 if (tryPreload(pfxs[pfxidx] + string("libpython") + shortver + ".dylib." + buffer)) return true;
fazekasgy@31 129 }
fazekasgy@31 130 if (tryPreload(pfxs[pfxidx] + string("libpython") + shortver + ".dylib")) return true;
fazekasgy@31 131 if (tryPreload(pfxs[pfxidx] + string("libpython.dylib"))) return true;
fazekasgy@31 132 }
fazekasgy@31 133 #else
fazekasgy@31 134 for (size_t pfxidx = 0; pfxidx < pfxs.size(); ++pfxidx) {
fazekasgy@31 135 for (int minor = 8; minor >= 0; --minor) {
fazekasgy@31 136 sprintf(buffer, "%d", minor);
fazekasgy@31 137 if (tryPreload(pfxs[pfxidx] + string("libpython") + shortver + ".so." + buffer)) return true;
fazekasgy@31 138 }
fazekasgy@31 139 if (tryPreload(pfxs[pfxidx] + string("libpython") + shortver + ".so")) return true;
fazekasgy@31 140 if (tryPreload(pfxs[pfxidx] + string("libpython.so"))) return true;
fazekasgy@31 141 }
fazekasgy@31 142 #endif
fazekasgy@31 143
fazekasgy@31 144 return false;
fazekasgy@31 145 }
fazekasgy@31 146
fazekasgy@31 147 /* This doesn't work: don't try it again.
fazekasgy@31 148 static bool initPython()
fazekasgy@31 149 {
fazekasgy@31 150 // preloadPython();
fazekasgy@31 151 Py_Initialize();
fazekasgy@31 152 #ifndef _WIN32
fazekasgy@31 153 //set dlopen flags form Python
fazekasgy@31 154 string pyCmd = "from sys import setdlopenflags\nimport dl\nsetdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL)\n";
fazekasgy@31 155 if (PyRun_SimpleString(pyCmd.c_str()) == -1)
fazekasgy@31 156 {
fazekasgy@31 157 cerr << "Warning: Could not set dlopen flasgs. Dynamic loading in scripts will fail." << endl;
fazekasgy@31 158 return false;
fazekasgy@31 159 }
fazekasgy@31 160 #endif
fazekasgy@31 161 PyEval_InitThreads();
fazekasgy@31 162 return Py_IsInitialized();
fazekasgy@31 163 }
fazekasgy@31 164 */
fazekasgy@31 165
fazekasgy@31 166 const VampPluginDescriptor
fazekasgy@31 167 *vampGetPluginDescriptor(unsigned int version,unsigned int index)
fazekasgy@31 168 {
fazekasgy@31 169 if (version < 1) return 0;
fazekasgy@31 170
fazekasgy@31 171 int isPythonInitialized = Py_IsInitialized();
fazekasgy@31 172 cerr << "# isPythonInitialized: " << isPythonInitialized << endl;
fazekasgy@31 173 cerr << "# haveScannedPlugins: " << haveScannedPlugins << endl;
fazekasgy@31 174
fazekasgy@31 175 if (!haveScannedPlugins) {
fazekasgy@31 176
fazekasgy@31 177 if (!isPythonInitialized){
fazekasgy@31 178
fazekasgy@31 179 if (!preloadPython())
fazekasgy@31 180 cerr << "Warning: Could not preload Python. Dynamic loading in scripts will fail." << endl;
fazekasgy@31 181
fazekasgy@31 182 int ext = PyImport_AppendInittab("vampy",initvampy);
fazekasgy@31 183 if (ext == -1) cerr << "Extension unsuccessful." << endl;
fazekasgy@31 184 else cerr << "Extension successful." << endl;
fazekasgy@31 185 Py_Initialize();
fazekasgy@31 186 initvampy();
fazekasgy@31 187 // if (!PyImport_ImportModule("vampy"))
fazekasgy@31 188 // cerr << "Could not import extension." << endl;
fazekasgy@31 189
fazekasgy@31 190 // Py_InitModule("vampy", VampyMethods);
fazekasgy@31 191
fazekasgy@31 192 // initpyRealTime();
fazekasgy@31 193 cerr << "# isPythonInitialized after initialize: " << Py_IsInitialized() << endl;
fazekasgy@31 194 // PyEval_InitThreads(); //not sure why this was needed
fazekasgy@31 195 }
fazekasgy@31 196
fazekasgy@31 197 vector<string> pyPlugs;
fazekasgy@31 198 vector<string> pyPath;
fazekasgy@31 199 vector<PyObject *> pyClasses;
fazekasgy@31 200 static PyPlugScanner *scanner;
fazekasgy@31 201
fazekasgy@31 202 //Scanning Plugins
fazekasgy@31 203 cerr << "Scanning PyPlugins" << endl;
fazekasgy@31 204 scanner = PyPlugScanner::getInstance();
fazekasgy@31 205 pyPath=scanner->getAllValidPath();
fazekasgy@31 206 //add this as extra path for development
fazekasgy@31 207 //pyPath.push_back("/Users/Shared/Development/vamp-experiments");
fazekasgy@31 208 scanner->setPath(pyPath);
fazekasgy@31 209 pyPlugs = scanner->getPyPlugs();
fazekasgy@31 210 cerr << "Found " << pyPlugs.size() << " Scripts ...OK" << endl;
fazekasgy@31 211 //TODO: this should support multiple classes per script (?)
fazekasgy@31 212 pyClasses = scanner->getPyClasses();
fazekasgy@31 213 cerr << "Found " << pyClasses.size() << " Classes ...OK" << endl;
fazekasgy@31 214
fazekasgy@31 215 for (size_t i = 0; i < pyPlugs.size(); ++i) {
fazekasgy@31 216 adapters.push_back( new PyPluginAdapter(pyPlugs[i],pyClasses[i]));
fazekasgy@31 217 }
fazekasgy@31 218 haveScannedPlugins=true;
fazekasgy@31 219 // if (!haveVampyInitialised) {
fazekasgy@31 220 // // PyImport_AddModule("vampy");
fazekasgy@31 221 // // if (!PyImport_ImportModule("vampy"))
fazekasgy@31 222 // cerr << "Could not import extension." << endl;
fazekasgy@31 223 // initvampy();
fazekasgy@31 224 // haveVampyInitialised = true;
fazekasgy@31 225 // cerr << "Extension initialised from main." << endl;
fazekasgy@31 226 // }
fazekasgy@31 227 }
fazekasgy@31 228
fazekasgy@31 229 cerr << "Accessing adapter index: " << index << " (adapters: " << adapters.size() << ")" << endl;
fazekasgy@31 230 if (index<adapters.size()) {
fazekasgy@31 231 const VampPluginDescriptor *tmp = adapters[index]->getDescriptor();
fazekasgy@31 232 return tmp;
fazekasgy@31 233 } else return 0;
fazekasgy@31 234
fazekasgy@31 235
fazekasgy@31 236 }
fazekasgy@31 237
fazekasgy@31 238
fazekasgy@31 239
fazekasgy@31 240
fazekasgy@31 241
fazekasgy@31 242
fazekasgy@31 243
fazekasgy@31 244