Mercurial > hg > vampy
diff vampy-main.cpp @ 31:4f1894c7591b vampy2
Created Vampy2 branch
author | fazekasgy |
---|---|
date | Sun, 20 Sep 2009 17:31:20 +0000 |
parents | |
children | c905122f79e7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vampy-main.cpp Sun Sep 20 17:31:20 2009 +0000 @@ -0,0 +1,248 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/** + * This Vamp plugin is a wrapper for Python Scripts. (VamPy) + * Centre for Digital Music, Queen Mary, University of London. + * Copyright 2008, George Fazekas. + */ + +#include <Python.h> +#include "vamp/vamp.h" +#include "vamp-sdk/PluginAdapter.h" +#include "PyPlugScanner.h" +#include "PyPlugin.h" +// #include "host/pyRealTime.h" +#include "PyExtensionModule.h" + + +#ifdef _WIN32 +#define pathsep ('\\') +#include <windows.h> +#include <tchar.h> +#else +#define pathsep ('/') +#include <dirent.h> +#include <dlfcn.h> +#endif + +using std::cerr; +using std::endl; +using std::string; +using std::vector; + + +//volatile bool mutex = false; +static int adinstcount; +static int totinstcount; + +class PyPluginAdapter : public Vamp::PluginAdapterBase +{ +public: + PyPluginAdapter(std::string pyPlugId, PyObject* pyClass) : + PluginAdapterBase(), + m_plug(pyPlugId), + m_pyClass(pyClass) + { + cerr << "PyPluginAdapter:ctor:"<< adinstcount << ": " << m_plug << endl; + adinstcount++; + m_instanceCount = 0; + } + + ~PyPluginAdapter() + { + } + +protected: + Vamp::Plugin *createPlugin(float inputSampleRate) + { + try { + PyPlugin *plugin = new PyPlugin(m_plug, inputSampleRate, m_pyClass, totinstcount); + // m_instanceCount++; /// do this in the ctors + return plugin; + } catch (...) { + cerr << "PyPluginAdapter::createPlugin: Failed to construct PyPlugin" << endl; + return 0; + } + } + + std::string m_plug; + bool m_haveInitialized; + PyObject *m_pyClass; + int m_instanceCount; +}; + + +static std::vector<PyPluginAdapter *> adapters; +static bool haveScannedPlugins = false; +static bool haveVampyInitialised = false; + +static bool tryPreload(string name) +{ + cerr << "Trying to load Python interpreter library \"" << name << "\"..."; +#ifdef _WIN32 + void *lib = LoadLibrary(name.c_str()); + if (!lib) { + cerr << " failed" << endl; + return false; + } +#else + void *lib = dlopen(name.c_str(), RTLD_NOW | RTLD_GLOBAL); + if (!lib) { + cerr << " failed" << endl; + return false; + } +#endif + cerr << " succeeded" << endl; + return true; +} + +static bool preloadPython() +{ +#ifdef _WIN32 + // this doesn't seem to be necessary at all on Windows + return true; +#endif + + string pyver = Py_GetVersion(); + int dots = 2; + string shortver; + for (size_t i = 0; i < pyver.length(); ++i) { + if (pyver[i] == '.') { + if (--dots == 0) { + shortver = pyver.substr(0, i); + break; + } + } + } + cerr << "Short version: " << shortver << endl; + + vector<string> pfxs; + pfxs.push_back(""); + pfxs.push_back(string(Py_GetExecPrefix()) + "/lib/"); + pfxs.push_back(string(Py_GetExecPrefix()) + "/"); + pfxs.push_back("/usr/lib/"); + pfxs.push_back("/usr/local/lib/"); + char buffer[5]; + + // hahaha! grossness is like a brother to us +#ifdef __APPLE__ + for (size_t pfxidx = 0; pfxidx < pfxs.size(); ++pfxidx) { + for (int minor = 8; minor >= 0; --minor) { + sprintf(buffer, "%d", minor); + if (tryPreload(pfxs[pfxidx] + string("libpython") + shortver + ".dylib." + buffer)) return true; + } + if (tryPreload(pfxs[pfxidx] + string("libpython") + shortver + ".dylib")) return true; + if (tryPreload(pfxs[pfxidx] + string("libpython.dylib"))) return true; + } +#else + for (size_t pfxidx = 0; pfxidx < pfxs.size(); ++pfxidx) { + for (int minor = 8; minor >= 0; --minor) { + sprintf(buffer, "%d", minor); + if (tryPreload(pfxs[pfxidx] + string("libpython") + shortver + ".so." + buffer)) return true; + } + if (tryPreload(pfxs[pfxidx] + string("libpython") + shortver + ".so")) return true; + if (tryPreload(pfxs[pfxidx] + string("libpython.so"))) return true; + } +#endif + + return false; +} + +/* This doesn't work: don't try it again. +static bool initPython() +{ + // preloadPython(); + Py_Initialize(); +#ifndef _WIN32 + //set dlopen flags form Python + string pyCmd = "from sys import setdlopenflags\nimport dl\nsetdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL)\n"; + if (PyRun_SimpleString(pyCmd.c_str()) == -1) + { + cerr << "Warning: Could not set dlopen flasgs. Dynamic loading in scripts will fail." << endl; + return false; + } +#endif + PyEval_InitThreads(); + return Py_IsInitialized(); +} +*/ + +const VampPluginDescriptor +*vampGetPluginDescriptor(unsigned int version,unsigned int index) +{ + if (version < 1) return 0; + + int isPythonInitialized = Py_IsInitialized(); + cerr << "# isPythonInitialized: " << isPythonInitialized << endl; + cerr << "# haveScannedPlugins: " << haveScannedPlugins << endl; + + if (!haveScannedPlugins) { + + if (!isPythonInitialized){ + + if (!preloadPython()) + cerr << "Warning: Could not preload Python. Dynamic loading in scripts will fail." << endl; + + int ext = PyImport_AppendInittab("vampy",initvampy); + if (ext == -1) cerr << "Extension unsuccessful." << endl; + else cerr << "Extension successful." << endl; + Py_Initialize(); + initvampy(); + // if (!PyImport_ImportModule("vampy")) + // cerr << "Could not import extension." << endl; + + // Py_InitModule("vampy", VampyMethods); + + // initpyRealTime(); + cerr << "# isPythonInitialized after initialize: " << Py_IsInitialized() << endl; + // PyEval_InitThreads(); //not sure why this was needed + } + + vector<string> pyPlugs; + vector<string> pyPath; + vector<PyObject *> pyClasses; + static PyPlugScanner *scanner; + + //Scanning Plugins + cerr << "Scanning PyPlugins" << endl; + scanner = PyPlugScanner::getInstance(); + pyPath=scanner->getAllValidPath(); + //add this as extra path for development + //pyPath.push_back("/Users/Shared/Development/vamp-experiments"); + scanner->setPath(pyPath); + pyPlugs = scanner->getPyPlugs(); + cerr << "Found " << pyPlugs.size() << " Scripts ...OK" << endl; + //TODO: this should support multiple classes per script (?) + pyClasses = scanner->getPyClasses(); + cerr << "Found " << pyClasses.size() << " Classes ...OK" << endl; + + for (size_t i = 0; i < pyPlugs.size(); ++i) { + adapters.push_back( new PyPluginAdapter(pyPlugs[i],pyClasses[i])); + } + haveScannedPlugins=true; + // if (!haveVampyInitialised) { + // // PyImport_AddModule("vampy"); + // // if (!PyImport_ImportModule("vampy")) + // cerr << "Could not import extension." << endl; + // initvampy(); + // haveVampyInitialised = true; + // cerr << "Extension initialised from main." << endl; + // } + } + + cerr << "Accessing adapter index: " << index << " (adapters: " << adapters.size() << ")" << endl; + if (index<adapters.size()) { + const VampPluginDescriptor *tmp = adapters[index]->getDescriptor(); + return tmp; + } else return 0; + + +} + + + + + + + +