# HG changeset patch # User Chris Cannam # Date 1476958774 -3600 # Node ID 771a179255767433678439f2f0315329db136087 # Parent 77320e522253b0e53959db5f73b595b76473e710# Parent a1b97df9962e0c39486748309bee4ad63a226157 Merge from branch 3.0-integration diff -r a1b97df9962e -r 771a17925576 data/model/SparseModel.h --- a/data/model/SparseModel.h Thu Oct 20 11:16:22 2016 +0100 +++ b/data/model/SparseModel.h Thu Oct 20 11:19:34 2016 +0100 @@ -730,8 +730,8 @@ { QMutexLocker locker(&m_mutex); m_resolution = resolution; + m_rows.clear(); } - m_rows.clear(); emit modelChanged(); } @@ -743,8 +743,8 @@ QMutexLocker locker(&m_mutex); m_points.clear(); m_pointCount = 0; + m_rows.clear(); } - m_rows.clear(); emit modelChanged(); } @@ -752,12 +752,11 @@ void SparseModel::addPoint(const PointType &point) { - { - QMutexLocker locker(&m_mutex); - m_points.insert(point); - m_pointCount++; - if (point.getLabel() != "") m_hasTextLabels = true; - } + QMutexLocker locker(&m_mutex); + + m_points.insert(point); + m_pointCount++; + if (point.getLabel() != "") m_hasTextLabels = true; // Even though this model is nominally sparse, there may still be // too many signals going on here (especially as they'll probably @@ -784,18 +783,16 @@ bool SparseModel::containsPoint(const PointType &point) { - { - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutex); - PointListIterator i = m_points.lower_bound(point); - typename PointType::Comparator comparator; - while (i != m_points.end()) { - if (i->frame > point.frame) break; - if (!comparator(*i, point) && !comparator(point, *i)) { - return true; - } - ++i; - } + PointListIterator i = m_points.lower_bound(point); + typename PointType::Comparator comparator; + while (i != m_points.end()) { + if (i->frame > point.frame) break; + if (!comparator(*i, point) && !comparator(point, *i)) { + return true; + } + ++i; } return false; @@ -805,21 +802,20 @@ void SparseModel::deletePoint(const PointType &point) { - { - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutex); - PointListIterator i = m_points.lower_bound(point); - typename PointType::Comparator comparator; - while (i != m_points.end()) { - if (i->frame > point.frame) break; - if (!comparator(*i, point) && !comparator(point, *i)) { - m_points.erase(i); - m_pointCount--; - break; + PointListIterator i = m_points.lower_bound(point); + typename PointType::Comparator comparator; + while (i != m_points.end()) { + if (i->frame > point.frame) break; + if (!comparator(*i, point) && !comparator(point, *i)) { + m_points.erase(i); + m_pointCount--; + break; } - ++i; - } + ++i; } + // std::cout << "SparseOneDimensionalModel: emit modelChanged(" // << point.frame << ")" << std::endl; m_rows.clear(); //!!! inefficient @@ -832,6 +828,8 @@ { // std::cerr << "SparseModel::setCompletion(" << completion << ")" << std::endl; + QMutexLocker locker(&m_mutex); + if (m_completion != completion) { m_completion = completion; diff -r a1b97df9962e -r 771a17925576 plugin/FeatureExtractionPluginFactory.cpp --- a/plugin/FeatureExtractionPluginFactory.cpp Thu Oct 20 11:16:22 2016 +0100 +++ b/plugin/FeatureExtractionPluginFactory.cpp Thu Oct 20 11:19:34 2016 +0100 @@ -16,13 +16,12 @@ #include "FeatureExtractionPluginFactory.h" #include "PluginIdentifier.h" -#include -#include - #include "system/System.h" #include "PluginScan.h" +#include "vamp-client/AutoPlugin.h" + #include #include #include @@ -36,27 +35,6 @@ //#define DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 1 -class PluginDeletionNotifyAdapter : public Vamp::HostExt::PluginWrapper { -public: - PluginDeletionNotifyAdapter(Vamp::Plugin *plugin, - FeatureExtractionPluginFactory *factory) : - PluginWrapper(plugin), m_factory(factory) { } - virtual ~PluginDeletionNotifyAdapter(); -protected: - FeatureExtractionPluginFactory *m_factory; -}; - -PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter() -{ - // see notes in vamp-sdk/hostext/PluginLoader.cpp from which this is drawn - Vamp::Plugin *p = m_plugin; - delete m_plugin; - m_plugin = 0; - // acceptable use after free here, as pluginDeleted uses p only as - // pointer key and does not deref it - if (m_factory) m_factory->pluginDeleted(p); -} - static FeatureExtractionPluginFactory *_nativeInstance = 0; FeatureExtractionPluginFactory * @@ -81,14 +59,11 @@ return instance(type); } -vector -FeatureExtractionPluginFactory::getPluginPath() +FeatureExtractionPluginFactory::FeatureExtractionPluginFactory() : + m_serverName("piper-cpp/bin/piper-vamp-server"), + m_transport(m_serverName), + m_client(&m_transport) { - if (!m_pluginPath.empty()) return m_pluginPath; - - vector p = Vamp::PluginHostAdapter::getPluginPath(); - for (size_t i = 0; i < p.size(); ++i) m_pluginPath.push_back(p[i].c_str()); - return m_pluginPath; } vector @@ -117,269 +92,40 @@ { Profiler profiler("FeatureExtractionPluginFactory::getPluginIdentifiers"); + QMutexLocker locker(&m_mutex); + + if (m_pluginData.empty()) { + populate(); + } + vector rv; - QStringList candidates = PluginScan::getInstance()->getCandidateLibrariesFor - (PluginScan::VampPlugin); - - for (QString soname : candidates) { - - void *libraryHandle = DLOPEN(soname, RTLD_LAZY | RTLD_LOCAL); - - if (!libraryHandle) { - cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to load library " << soname << ": " << DLERROR() << endl; - continue; - } - - VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction) - DLSYM(libraryHandle, "vampGetPluginDescriptor"); - - if (!fn) { - cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: No descriptor function in " << soname << endl; - if (DLCLOSE(libraryHandle) != 0) { - cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname << endl; - } - continue; - } - -#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Vamp descriptor found" << endl; -#endif - - const VampPluginDescriptor *descriptor = 0; - int index = 0; - - map known; - bool ok = true; - - while ((descriptor = fn(VAMP_API_VERSION, index))) { - - if (known.find(descriptor->identifier) != known.end()) { - cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Plugin library " - << soname - << " returns the same plugin identifier \"" - << descriptor->identifier << "\" at indices " - << known[descriptor->identifier] << " and " - << index << endl; - cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Avoiding this library (obsolete API?)" << endl; - ok = false; - break; - } else { - known[descriptor->identifier] = index; - } - - ++index; - } - - if (ok) { - - index = 0; - - while ((descriptor = fn(VAMP_API_VERSION, index))) { - - QString id = PluginIdentifier::createIdentifier - ("vamp", soname, descriptor->identifier); - rv.push_back(id); -#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "FeatureExtractionPluginFactory::getPluginIdentifiers: Found plugin id " << id << " at index " << index << endl; -#endif - ++index; - } - } - - if (DLCLOSE(libraryHandle) != 0) { - cerr << "WARNING: FeatureExtractionPluginFactory::getPluginIdentifiers: Failed to unload library " << soname << endl; - } + for (const auto &d: m_pluginData) { + rv.push_back(QString("vamp:") + QString::fromStdString(d.pluginKey)); } - generateTaxonomy(); - return rv; } -QString -FeatureExtractionPluginFactory::findPluginFile(QString soname, QString inDir) -{ - QString file = ""; - -#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "FeatureExtractionPluginFactory::findPluginFile(\"" - << soname << "\", \"" << inDir << "\")" - << endl; -#endif - - if (inDir != "") { - - QDir dir(inDir, PLUGIN_GLOB, - QDir::Name | QDir::IgnoreCase, - QDir::Files | QDir::Readable); - if (!dir.exists()) return ""; - - file = dir.filePath(QFileInfo(soname).fileName()); - - if (QFileInfo(file).exists() && QFileInfo(file).isFile()) { - -#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "FeatureExtractionPluginFactory::findPluginFile: " - << "found trivially at " << file << endl; -#endif - - return file; - } - - for (unsigned int j = 0; j < dir.count(); ++j) { - file = dir.filePath(dir[j]); - if (QFileInfo(file).baseName() == QFileInfo(soname).baseName()) { - -#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "FeatureExtractionPluginFactory::findPluginFile: " - << "found \"" << soname << "\" at " << file << endl; -#endif - - return file; - } - } - -#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "FeatureExtractionPluginFactory::findPluginFile (with dir): " - << "not found" << endl; -#endif - - return ""; - - } else { - - QFileInfo fi(soname); - - if (fi.isAbsolute() && fi.exists() && fi.isFile()) { -#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "FeatureExtractionPluginFactory::findPluginFile: " - << "found trivially at " << soname << endl; -#endif - return soname; - } - - if (fi.isAbsolute() && fi.absolutePath() != "") { - file = findPluginFile(soname, fi.absolutePath()); - if (file != "") return file; - } - - vector path = getPluginPath(); - for (vector::iterator i = path.begin(); - i != path.end(); ++i) { - if (*i != "") { - file = findPluginFile(soname, *i); - if (file != "") return file; - } - } - -#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "FeatureExtractionPluginFactory::findPluginFile: " - << "not found" << endl; -#endif - - return ""; - } -} - Vamp::Plugin * FeatureExtractionPluginFactory::instantiatePlugin(QString identifier, sv_samplerate_t inputSampleRate) { Profiler profiler("FeatureExtractionPluginFactory::instantiatePlugin"); - - Vamp::Plugin *rv = 0; - Vamp::PluginHostAdapter *plugin = 0; - - const VampPluginDescriptor *descriptor = 0; - int index = 0; - + QString type, soname, label; PluginIdentifier::parseIdentifier(identifier, type, soname, label); - if (type != "vamp") { -#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type << endl; -#endif - return 0; + std::string pluginKey = (soname + ":" + label).toStdString(); + + auto ap = new piper_vamp::client::AutoPlugin + (m_serverName, pluginKey, float(inputSampleRate), 0); + + if (!ap->isOK()) { + delete ap; + return 0; + } else { + return ap; } - - QString found = findPluginFile(soname); - - if (found == "") { - cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find library file " << soname << endl; - return 0; - } else if (found != soname) { - -#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Given library name was " << soname << ", found at " << found << endl; - cerr << soname << " -> " << found << endl; -#endif - - } - - soname = found; - - void *libraryHandle = DLOPEN(soname, RTLD_LAZY | RTLD_LOCAL); - - if (!libraryHandle) { - cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to load library " << soname << ": " << DLERROR() << endl; - return 0; - } - - VampGetPluginDescriptorFunction fn = (VampGetPluginDescriptorFunction) - DLSYM(libraryHandle, "vampGetPluginDescriptor"); - - if (!fn) { - cerr << "FeatureExtractionPluginFactory::instantiatePlugin: No descriptor function in " << soname << endl; - goto done; - } - - while ((descriptor = fn(VAMP_API_VERSION, index))) { - if (label == descriptor->identifier) break; - ++index; - } - - if (!descriptor) { - cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Failed to find plugin \"" << label << "\" in library " << soname << endl; - goto done; - } - - plugin = new Vamp::PluginHostAdapter(descriptor, float(inputSampleRate)); - - if (plugin) { - m_handleMap[plugin] = libraryHandle; - rv = new PluginDeletionNotifyAdapter(plugin, this); - } - -// SVDEBUG << "FeatureExtractionPluginFactory::instantiatePlugin: Constructed Vamp plugin, rv is " << rv << endl; - - //!!! need to dlclose() when plugins from a given library are unloaded - -done: - if (!rv) { - if (DLCLOSE(libraryHandle) != 0) { - cerr << "WARNING: FeatureExtractionPluginFactory::instantiatePlugin: Failed to unload library " << soname << endl; - } - } - -#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "FeatureExtractionPluginFactory::instantiatePlugin: Instantiated plugin " << label << " from library " << soname << ": descriptor " << descriptor << ", rv "<< rv << ", label " << rv->getName() << ", outputs " << rv->getOutputDescriptors().size() << endl; -#endif - - return rv; -} - -void -FeatureExtractionPluginFactory::pluginDeleted(Vamp::Plugin *plugin) -{ - void *handle = m_handleMap[plugin]; - if (handle) { -#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "unloading library " << handle << " for plugin " << plugin << endl; -#endif - DLCLOSE(handle); - } - m_handleMap.erase(plugin); } QString @@ -389,47 +135,21 @@ } void -FeatureExtractionPluginFactory::generateTaxonomy() +FeatureExtractionPluginFactory::populate() { - vector pluginPath = getPluginPath(); - vector path; + piper_vamp::ListResponse lr = m_client.listPluginData(); + m_pluginData = lr.available; - for (size_t i = 0; i < pluginPath.size(); ++i) { - if (pluginPath[i].contains("/lib/")) { - QString p(pluginPath[i]); - path.push_back(p); - p.replace("/lib/", "/share/"); - path.push_back(p); - } - path.push_back(pluginPath[i]); + for (const auto &pd: m_pluginData) { + + QString identifier = + QString("vamp:") + QString::fromStdString(pd.pluginKey); + + QStringList catlist; + for (const auto &cs: pd.category) { + catlist.push_back(QString::fromStdString(cs)); + } + m_taxonomy[identifier] = catlist.join(" > "); } +} - for (size_t i = 0; i < path.size(); ++i) { - - QDir dir(path[i], "*.cat"); - -// SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: directory " << path[i] << " has " << dir.count() << " .cat files" << endl; - for (unsigned int j = 0; j < dir.count(); ++j) { - - QFile file(path[i] + "/" + dir[j]); - -// SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: about to open " << (path[i]+ "/" + dir[j]) << endl; - - if (file.open(QIODevice::ReadOnly)) { -// cerr << "...opened" << endl; - QTextStream stream(&file); - QString line; - - while (!stream.atEnd()) { - line = stream.readLine(); -// cerr << "line is: \"" << line << "\"" << endl; - QString id = PluginIdentifier::canonicalise - (line.section("::", 0, 0)); - QString cat = line.section("::", 1, 1); - m_taxonomy[id] = cat; -// cerr << "FeatureExtractionPluginFactory: set id \"" << id << "\" to cat \"" << cat << "\"" << endl; - } - } - } - } -} diff -r a1b97df9962e -r 771a17925576 plugin/FeatureExtractionPluginFactory.h --- a/plugin/FeatureExtractionPluginFactory.h Thu Oct 20 11:16:22 2016 +0100 +++ b/plugin/FeatureExtractionPluginFactory.h Thu Oct 20 11:19:34 2016 +0100 @@ -17,6 +17,7 @@ #define _FEATURE_EXTRACTION_PLUGIN_FACTORY_H_ #include +#include #include #include @@ -25,20 +26,20 @@ #include "base/Debug.h" #include "base/BaseTypes.h" +#include "vamp-client/ProcessQtTransport.h" +#include "vamp-client/CapnpRRClient.h" + class FeatureExtractionPluginFactory { public: + FeatureExtractionPluginFactory(); virtual ~FeatureExtractionPluginFactory() { } static FeatureExtractionPluginFactory *instance(QString pluginType); static FeatureExtractionPluginFactory *instanceFor(QString identifier); static std::vector getAllPluginIdentifiers(); - virtual std::vector getPluginPath(); - virtual std::vector getPluginIdentifiers(); - - virtual QString findPluginFile(QString soname, QString inDir = ""); // We don't set blockSize or channels on this -- they're // negotiated and handled via initialize() on the plugin @@ -51,14 +52,15 @@ virtual QString getPluginCategory(QString identifier); protected: - std::vector m_pluginPath; + std::string m_serverName; + + piper_vamp::client::ProcessQtTransport m_transport; + piper_vamp::client::CapnpRRClient m_client; + + QMutex m_mutex; + std::vector m_pluginData; std::map m_taxonomy; - - friend class PluginDeletionNotifyAdapter; - void pluginDeleted(Vamp::Plugin *); - std::map m_handleMap; - - void generateTaxonomy(); + void populate(); }; #endif diff -r a1b97df9962e -r 771a17925576 svcore.pro --- a/svcore.pro Thu Oct 20 11:16:22 2016 +0100 +++ b/svcore.pro Thu Oct 20 11:19:34 2016 +0100 @@ -44,8 +44,8 @@ TARGET = svcore -DEPENDPATH += . data plugin plugin/api/alsa -INCLUDEPATH += . data plugin plugin/api/alsa ../dataquay ../checker +DEPENDPATH += . data plugin plugin/api/alsa ../dataquay ../checker ../piper-cpp +INCLUDEPATH += . data plugin plugin/api/alsa ../dataquay ../checker ../piper-cpp OBJECTS_DIR = o MOC_DIR = o diff -r a1b97df9962e -r 771a17925576 transform/FeatureExtractionModelTransformer.cpp --- a/transform/FeatureExtractionModelTransformer.cpp Thu Oct 20 11:16:22 2016 +0100 +++ b/transform/FeatureExtractionModelTransformer.cpp Thu Oct 20 11:19:34 2016 +0100 @@ -42,17 +42,19 @@ FeatureExtractionModelTransformer::FeatureExtractionModelTransformer(Input in, const Transform &transform) : ModelTransformer(in, transform), - m_plugin(0) + m_plugin(0), + m_haveOutputs(false) { SVDEBUG << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: plugin " << m_transforms.begin()->getPluginIdentifier() << ", outputName " << m_transforms.begin()->getOutput() << endl; - initialise(); +// initialise(); } FeatureExtractionModelTransformer::FeatureExtractionModelTransformer(Input in, const Transforms &transforms) : ModelTransformer(in, transforms), - m_plugin(0) + m_plugin(0), + m_haveOutputs(false) { if (m_transforms.empty()) { SVDEBUG << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: " << transforms.size() << " transform(s)" << endl; @@ -60,7 +62,7 @@ SVDEBUG << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: " << transforms.size() << " transform(s), first has plugin " << m_transforms.begin()->getPluginIdentifier() << ", outputName " << m_transforms.begin()->getOutput() << endl; } - initialise(); +// initialise(); } static bool @@ -104,6 +106,9 @@ return false; } + cerr << "instantiating plugin for transform in thread " + << QThread::currentThreadId() << endl; + m_plugin = factory->instantiatePlugin(pluginId, input->getSampleRate()); if (!m_plugin) { m_message = tr("Failed to instantiate plugin \"%1\"").arg(pluginId); @@ -220,6 +225,11 @@ createOutputModels(j); } + m_outputMutex.lock(); + m_haveOutputs = true; + m_outputsCondition.wakeAll(); + m_outputMutex.unlock(); + return true; } @@ -479,6 +489,16 @@ } } +void +FeatureExtractionModelTransformer::awaitOutputModels() +{ + m_outputMutex.lock(); + while (!m_haveOutputs) { + m_outputsCondition.wait(&m_outputMutex); + } + m_outputMutex.unlock(); +} + FeatureExtractionModelTransformer::~FeatureExtractionModelTransformer() { // SVDEBUG << "FeatureExtractionModelTransformer::~FeatureExtractionModelTransformer()" << endl; @@ -566,6 +586,8 @@ void FeatureExtractionModelTransformer::run() { + initialise(); + DenseTimeValueModel *input = getConformingInput(); if (!input) return; @@ -709,6 +731,9 @@ if (m_abandoned) break; + cerr << "calling process() from thread " + << QThread::currentThreadId() << endl; + Vamp::Plugin::FeatureSet features = m_plugin->process (buffers, RealTime::frame2RealTime(blockFrame, sampleRate).toVampRealTime()); diff -r a1b97df9962e -r 771a17925576 transform/FeatureExtractionModelTransformer.h --- a/transform/FeatureExtractionModelTransformer.h Thu Oct 20 11:16:22 2016 +0100 +++ b/transform/FeatureExtractionModelTransformer.h Thu Oct 20 11:19:34 2016 +0100 @@ -19,6 +19,8 @@ #include "ModelTransformer.h" #include +#include +#include #include @@ -74,7 +76,12 @@ void getFrames(int channelCount, sv_frame_t startFrame, sv_frame_t size, float **buffer); - // just casts + bool m_haveOutputs; + QMutex m_outputMutex; + QWaitCondition m_outputsCondition; + void awaitOutputModels(); + + // just casts: DenseTimeValueModel *getConformingInput(); diff -r a1b97df9962e -r 771a17925576 transform/ModelTransformer.h --- a/transform/ModelTransformer.h Thu Oct 20 11:16:22 2016 +0100 +++ b/transform/ModelTransformer.h Thu Oct 20 11:19:34 2016 +0100 @@ -89,16 +89,20 @@ * be initialised; an error message may be available via * getMessage() in this situation. */ - Models getOutputModels() { return m_outputs; } + Models getOutputModels() { + awaitOutputModels(); + return m_outputs; + } /** * Return the set of output models, also detaching them from the * transformer so that they will not be deleted when the * transformer is. The caller takes ownership of the models. */ - Models detachOutputModels() { + Models detachOutputModels() { + awaitOutputModels(); m_detached = true; - return getOutputModels(); + return m_outputs; } /** @@ -138,6 +142,8 @@ ModelTransformer(Input input, const Transform &transform); ModelTransformer(Input input, const Transforms &transforms); + virtual void awaitOutputModels() = 0; + Transforms m_transforms; Input m_input; // I don't own the model in this Models m_outputs; // I own this, unless... diff -r a1b97df9962e -r 771a17925576 transform/RealTimeEffectModelTransformer.h --- a/transform/RealTimeEffectModelTransformer.h Thu Oct 20 11:16:22 2016 +0100 +++ b/transform/RealTimeEffectModelTransformer.h Thu Oct 20 11:19:34 2016 +0100 @@ -31,6 +31,8 @@ protected: virtual void run(); + virtual void awaitOutputModels() { } // they're created synchronously + QString m_units; RealTimePluginInstance *m_plugin; int m_outputNo;