annotate PyExtensionManager.cpp @ 41:94d09b4027aa

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