Mercurial > hg > vampy
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 |