comparison vampy-main.cpp @ 31:4f1894c7591b vampy2

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