diff PyExtensionManager.cpp @ 37:27bab3a16c9a vampy2final

new branch Vampy2final
author fazekasgy
date Mon, 05 Oct 2009 11:28:00 +0000
parents
children 5664fe298af2
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PyExtensionManager.cpp	Mon Oct 05 11:28:00 2009 +0000
@@ -0,0 +1,248 @@
+/*
+
+ * Vampy : This plugin is a wrapper around the Vamp plugin API.
+ * It allows for writing Vamp plugins in Python.
+
+ * Centre for Digital Music, Queen Mary University of London.
+ * Copyright (C) 2008-2009 Gyorgy Fazekas, QMUL. (See Vamp sources 
+ * for licence information.)
+
+*/
+
+#include <Python.h>
+#include "vamp/vamp.h"
+#include "PyExtensionModule.h"
+#include "PyExtensionManager.h"
+#include <algorithm>
+
+using std::cerr;
+using std::endl;
+using std::string;
+using std::vector;
+using std::find;
+
+//static
+char* PyExtensionManager::m_exposedNames[] = {
+		"ParameterDescriptor",
+		"OutputDescriptor",
+		"ParameterList",
+		"OutputList",
+	    "FeatureList",
+		"FeatureSet",
+		"Feature",
+		"RealTime",
+		"frame2RealTime",
+/* 		//using builtin objects:
+		"OneSamplePerStep",
+		"FixedSampleRate",
+		"VariableSampleRate",
+		"TimeDomain",
+		"FrequencyDomain",
+*/
+		NULL
+};
+
+PyExtensionManager::PyExtensionManager()
+{
+#ifdef _DEBUG	
+	cerr << "Creating extension manager." << endl;
+#endif
+}
+
+bool 
+PyExtensionManager::initExtension() 
+{
+	cerr << "Initialising extension module." << endl; 
+
+	/// call the module initialiser first
+	initvampy();
+
+	/// these references are all borrowed
+	m_pyGlobalNamespace = PyImport_GetModuleDict();
+	if (!m_pyGlobalNamespace) 
+		{cerr << "Vampy::PyExtensionManager::initExtension: GlobalNamespace failed." << endl; return false;}
+	PyObject *pyVampyModule = PyDict_GetItemString(m_pyGlobalNamespace,"vampy");
+	if (!pyVampyModule) 
+		{cerr << "Vampy::PyExtensionManager::initExtension: VampyModule failed." << endl; return false;}
+	m_pyVampyNamespace = PyModule_GetDict(pyVampyModule);
+	if (!m_pyVampyNamespace) 
+		{cerr << "Vampy::PyExtensionManager::initExtension: VampyNamespace failed." << endl; return false;}
+    
+	/// initialise local namespaces
+	updateAllLocals();
+#ifdef _DEBUG
+	cerr << "Vampy: Extension namespaces updated." << endl; 
+#endif	
+	return true;
+}
+
+
+PyExtensionManager::~PyExtensionManager()
+{
+#ifdef _DEBUG	
+	cerr << "Cleaning locals..." << endl;
+#endif	
+
+	cleanAllLocals(); 
+
+#ifdef _DEBUG	
+	cerr << "Cleaning module..." << endl;
+#endif	
+
+	if (!cleanModule()) 
+		cerr << "Vampy::~PyExtensionManager: failed to clean extension module." << endl;
+	cerr << "Vampy::~PyExtensionManager: Extension module cleaned." << endl;
+}
+
+
+
+void
+PyExtensionManager::setPlugModuleNames(vector<string> pyPlugs)
+{
+	for (size_t i = 0; i < pyPlugs.size(); ++i) {
+		string modName = pyPlugs[i];
+		string tmp = modName.substr(modName.rfind(':')+1,modName.size()-1);
+		m_plugModuleNames.push_back(tmp);
+
+#ifdef _DEBUG_VALUES		
+		cerr << "Inserted module name: " << tmp << endl;
+#endif		
+
+	}
+}
+
+void
+PyExtensionManager::deleteModuleName(string plugKey)
+{
+	string name = plugKey.substr(plugKey.rfind(':')+1,plugKey.size()-1);
+	vector<string>::iterator it = 
+		find (m_plugModuleNames.begin(), m_plugModuleNames.end(), name);
+	if (it != m_plugModuleNames.end()) m_plugModuleNames.erase(it);
+#ifdef _DEBUG_VALUES		
+	cerr << "PyExtensionManager::deleteModuleName: Deleted module name: " << name << endl;
+#endif	
+}
+
+
+void 
+PyExtensionManager::cleanAllLocals() const
+{
+	for (size_t i = 0; i < m_plugModuleNames.size(); ++i) {
+	    cleanLocalNamespace(m_plugModuleNames[i].c_str());
+	}
+}
+
+void 
+PyExtensionManager::updateAllLocals() const
+{
+	for (size_t i = 0; i < m_plugModuleNames.size(); ++i) {
+		updateLocalNamespace(m_plugModuleNames[i].c_str());
+	}
+}
+
+void 
+PyExtensionManager::cleanLocalNamespace(const char* plugModuleName) const
+{
+	
+	/// these references are all borrowed
+	PyObject *pyPlugModule = PyDict_GetItemString(m_pyGlobalNamespace,plugModuleName);
+	if (!pyPlugModule) return;
+	PyObject *pyPlugDict = PyModule_GetDict(pyPlugModule);
+	if (!pyPlugDict) return;
+	
+	int i = 0;
+	while (PyExtensionManager::m_exposedNames[i]) {
+		char* name = PyExtensionManager::m_exposedNames[i];
+		i++;
+		PyObject *key = PyString_FromString(name);
+		if (!key) break;
+		if (PyDict_Contains(pyPlugDict,key)) {
+			if (PyDict_SetItem(pyPlugDict,key,Py_None) != 0)
+				cerr << "Vampy::PyExtensionManager::cleanLocalNamespace: Failed: " 
+				<< name << " of "<< plugModuleName << endl;
+#ifdef _DEBUG_VALUES
+			else cerr << "Cleaned local name: " << name << endl;
+#endif			
+		}
+		Py_DECREF(key);
+	}
+}
+
+void 
+PyExtensionManager::updateLocalNamespace(const char* plugModuleName) const
+{
+	/// this allows the use of common syntax like:
+	/// from vampy import * 
+	/// even after several unload/reload cycles
+		
+	/// these references are all borrowed
+	PyObject *pyPlugModule = PyDict_GetItemString(m_pyGlobalNamespace,plugModuleName);
+	if (!pyPlugModule) return;
+	PyObject *pyPlugDict = PyModule_GetDict(pyPlugModule);
+	if (!pyPlugDict) return;
+	
+	int i = 0;
+	while (PyExtensionManager::m_exposedNames[i]) {
+		const char* name = PyExtensionManager::m_exposedNames[i];
+		i++;
+		PyObject *key = PyString_FromString(name);
+		if (!key) break;
+		if (PyDict_Contains(pyPlugDict,key)) {
+			PyObject* item = PyDict_GetItem(m_pyVampyNamespace,key);
+			if (PyDict_SetItem(pyPlugDict,key,item) != 0)
+				cerr << "Vampy::PyExtensionManager::updateLocalNamespace: Failed: " 
+				<< name << " of "<< plugModuleName << endl;
+#ifdef _DEBUG_VALUES
+			else cerr << "Updated local name: " << name << endl;
+#endif			
+		}
+		Py_DECREF(key);
+	}
+}
+
+
+bool 
+PyExtensionManager::cleanModule(void) const
+{
+		
+	PyObject *m = PyImport_AddModule("vampy");
+	if (!m) {
+		if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
+		cerr << "Vampy::PyExtensionManager::cleanModule: PyImport_AddModule returned NULL!" << endl;
+		return false;
+	} else {
+		PyObject *dict = PyModule_GetDict(m);
+#ifdef _DEBUG		
+		Py_ssize_t ln = PyDict_Size(dict);
+		cerr << "Vampy::PyExtensionManager::cleanModule: Size of module dict = " << (int) ln << endl;
+#endif		
+		/// Clean the module dictionary.
+		// printDict(dict);
+		PyDict_Clear(dict);
+		if (PyErr_Occurred()) 
+			{ PyErr_Print(); PyErr_Clear(); return false; }
+		PyObject *name = PyString_FromString("vampy");
+		if (name) PyDict_SetItemString(dict,"__name__",name);
+		Py_XDECREF(name);
+#ifdef _DEBUG		
+	    ln = PyDict_Size(dict);
+		cerr << "Vampy::PyExtensionManager::cleanModule: Size of module dict (cleaned) = " << (int) ln << endl;
+#endif
+		return true;
+	}
+}
+
+void 
+PyExtensionManager::printDict(PyObject* inDict) const
+{
+	Py_ssize_t pyPos = 0;
+	PyObject *pyKey, *pyDictValue;
+	cerr << endl << endl << "Module dictionary contents: " << endl;
+	while (PyDict_Next(inDict, &pyPos, &pyKey, &pyDictValue))
+	{ 
+		char *key = PyString_AS_STRING(pyKey);
+		char *val = PyString_AS_STRING(PyObject_Str(pyDictValue));
+		cerr << "key: [ '" << key << "' ] value: " << val << endl;
+	}
+}
+