comparison PyExtensionManager.cpp @ 37:27bab3a16c9a vampy2final

new branch Vampy2final
author fazekasgy
date Mon, 05 Oct 2009 11:28:00 +0000
parents
children 5664fe298af2
comparison
equal deleted inserted replaced
-1:000000000000 37:27bab3a16c9a
1 /*
2
3 * Vampy : This plugin is a wrapper around the Vamp plugin API.
4 * It allows for writing Vamp plugins in Python.
5
6 * Centre for Digital Music, Queen Mary University of London.
7 * Copyright (C) 2008-2009 Gyorgy Fazekas, QMUL. (See Vamp sources
8 * for licence information.)
9
10 */
11
12 #include <Python.h>
13 #include "vamp/vamp.h"
14 #include "PyExtensionModule.h"
15 #include "PyExtensionManager.h"
16 #include <algorithm>
17
18 using std::cerr;
19 using std::endl;
20 using std::string;
21 using std::vector;
22 using std::find;
23
24 //static
25 char* PyExtensionManager::m_exposedNames[] = {
26 "ParameterDescriptor",
27 "OutputDescriptor",
28 "ParameterList",
29 "OutputList",
30 "FeatureList",
31 "FeatureSet",
32 "Feature",
33 "RealTime",
34 "frame2RealTime",
35 /* //using builtin objects:
36 "OneSamplePerStep",
37 "FixedSampleRate",
38 "VariableSampleRate",
39 "TimeDomain",
40 "FrequencyDomain",
41 */
42 NULL
43 };
44
45 PyExtensionManager::PyExtensionManager()
46 {
47 #ifdef _DEBUG
48 cerr << "Creating extension manager." << endl;
49 #endif
50 }
51
52 bool
53 PyExtensionManager::initExtension()
54 {
55 cerr << "Initialising extension module." << endl;
56
57 /// call the module initialiser first
58 initvampy();
59
60 /// these references are all borrowed
61 m_pyGlobalNamespace = PyImport_GetModuleDict();
62 if (!m_pyGlobalNamespace)
63 {cerr << "Vampy::PyExtensionManager::initExtension: GlobalNamespace failed." << endl; return false;}
64 PyObject *pyVampyModule = PyDict_GetItemString(m_pyGlobalNamespace,"vampy");
65 if (!pyVampyModule)
66 {cerr << "Vampy::PyExtensionManager::initExtension: VampyModule failed." << endl; return false;}
67 m_pyVampyNamespace = PyModule_GetDict(pyVampyModule);
68 if (!m_pyVampyNamespace)
69 {cerr << "Vampy::PyExtensionManager::initExtension: VampyNamespace failed." << endl; return false;}
70
71 /// initialise local namespaces
72 updateAllLocals();
73 #ifdef _DEBUG
74 cerr << "Vampy: Extension namespaces updated." << endl;
75 #endif
76 return true;
77 }
78
79
80 PyExtensionManager::~PyExtensionManager()
81 {
82 #ifdef _DEBUG
83 cerr << "Cleaning locals..." << endl;
84 #endif
85
86 cleanAllLocals();
87
88 #ifdef _DEBUG
89 cerr << "Cleaning module..." << endl;
90 #endif
91
92 if (!cleanModule())
93 cerr << "Vampy::~PyExtensionManager: failed to clean extension module." << endl;
94 cerr << "Vampy::~PyExtensionManager: Extension module cleaned." << endl;
95 }
96
97
98
99 void
100 PyExtensionManager::setPlugModuleNames(vector<string> pyPlugs)
101 {
102 for (size_t i = 0; i < pyPlugs.size(); ++i) {
103 string modName = pyPlugs[i];
104 string tmp = modName.substr(modName.rfind(':')+1,modName.size()-1);
105 m_plugModuleNames.push_back(tmp);
106
107 #ifdef _DEBUG_VALUES
108 cerr << "Inserted module name: " << tmp << endl;
109 #endif
110
111 }
112 }
113
114 void
115 PyExtensionManager::deleteModuleName(string plugKey)
116 {
117 string name = plugKey.substr(plugKey.rfind(':')+1,plugKey.size()-1);
118 vector<string>::iterator it =
119 find (m_plugModuleNames.begin(), m_plugModuleNames.end(), name);
120 if (it != m_plugModuleNames.end()) m_plugModuleNames.erase(it);
121 #ifdef _DEBUG_VALUES
122 cerr << "PyExtensionManager::deleteModuleName: Deleted module name: " << name << endl;
123 #endif
124 }
125
126
127 void
128 PyExtensionManager::cleanAllLocals() const
129 {
130 for (size_t i = 0; i < m_plugModuleNames.size(); ++i) {
131 cleanLocalNamespace(m_plugModuleNames[i].c_str());
132 }
133 }
134
135 void
136 PyExtensionManager::updateAllLocals() const
137 {
138 for (size_t i = 0; i < m_plugModuleNames.size(); ++i) {
139 updateLocalNamespace(m_plugModuleNames[i].c_str());
140 }
141 }
142
143 void
144 PyExtensionManager::cleanLocalNamespace(const char* plugModuleName) const
145 {
146
147 /// these references are all borrowed
148 PyObject *pyPlugModule = PyDict_GetItemString(m_pyGlobalNamespace,plugModuleName);
149 if (!pyPlugModule) return;
150 PyObject *pyPlugDict = PyModule_GetDict(pyPlugModule);
151 if (!pyPlugDict) return;
152
153 int i = 0;
154 while (PyExtensionManager::m_exposedNames[i]) {
155 char* name = PyExtensionManager::m_exposedNames[i];
156 i++;
157 PyObject *key = PyString_FromString(name);
158 if (!key) break;
159 if (PyDict_Contains(pyPlugDict,key)) {
160 if (PyDict_SetItem(pyPlugDict,key,Py_None) != 0)
161 cerr << "Vampy::PyExtensionManager::cleanLocalNamespace: Failed: "
162 << name << " of "<< plugModuleName << endl;
163 #ifdef _DEBUG_VALUES
164 else cerr << "Cleaned local name: " << name << endl;
165 #endif
166 }
167 Py_DECREF(key);
168 }
169 }
170
171 void
172 PyExtensionManager::updateLocalNamespace(const char* plugModuleName) const
173 {
174 /// this allows the use of common syntax like:
175 /// from vampy import *
176 /// even after several unload/reload cycles
177
178 /// these references are all borrowed
179 PyObject *pyPlugModule = PyDict_GetItemString(m_pyGlobalNamespace,plugModuleName);
180 if (!pyPlugModule) return;
181 PyObject *pyPlugDict = PyModule_GetDict(pyPlugModule);
182 if (!pyPlugDict) return;
183
184 int i = 0;
185 while (PyExtensionManager::m_exposedNames[i]) {
186 const char* name = PyExtensionManager::m_exposedNames[i];
187 i++;
188 PyObject *key = PyString_FromString(name);
189 if (!key) break;
190 if (PyDict_Contains(pyPlugDict,key)) {
191 PyObject* item = PyDict_GetItem(m_pyVampyNamespace,key);
192 if (PyDict_SetItem(pyPlugDict,key,item) != 0)
193 cerr << "Vampy::PyExtensionManager::updateLocalNamespace: Failed: "
194 << name << " of "<< plugModuleName << endl;
195 #ifdef _DEBUG_VALUES
196 else cerr << "Updated local name: " << name << endl;
197 #endif
198 }
199 Py_DECREF(key);
200 }
201 }
202
203
204 bool
205 PyExtensionManager::cleanModule(void) const
206 {
207
208 PyObject *m = PyImport_AddModule("vampy");
209 if (!m) {
210 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
211 cerr << "Vampy::PyExtensionManager::cleanModule: PyImport_AddModule returned NULL!" << endl;
212 return false;
213 } else {
214 PyObject *dict = PyModule_GetDict(m);
215 #ifdef _DEBUG
216 Py_ssize_t ln = PyDict_Size(dict);
217 cerr << "Vampy::PyExtensionManager::cleanModule: Size of module dict = " << (int) ln << endl;
218 #endif
219 /// Clean the module dictionary.
220 // printDict(dict);
221 PyDict_Clear(dict);
222 if (PyErr_Occurred())
223 { PyErr_Print(); PyErr_Clear(); return false; }
224 PyObject *name = PyString_FromString("vampy");
225 if (name) PyDict_SetItemString(dict,"__name__",name);
226 Py_XDECREF(name);
227 #ifdef _DEBUG
228 ln = PyDict_Size(dict);
229 cerr << "Vampy::PyExtensionManager::cleanModule: Size of module dict (cleaned) = " << (int) ln << endl;
230 #endif
231 return true;
232 }
233 }
234
235 void
236 PyExtensionManager::printDict(PyObject* inDict) const
237 {
238 Py_ssize_t pyPos = 0;
239 PyObject *pyKey, *pyDictValue;
240 cerr << endl << endl << "Module dictionary contents: " << endl;
241 while (PyDict_Next(inDict, &pyPos, &pyKey, &pyDictValue))
242 {
243 char *key = PyString_AS_STRING(pyKey);
244 char *val = PyString_AS_STRING(PyObject_Str(pyDictValue));
245 cerr << "key: [ '" << key << "' ] value: " << val << endl;
246 }
247 }
248