annotate PyExtensionManager.cpp @ 99:b9cddb57a7f4

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