Chris@49: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@52: Sonic Visualiser Chris@52: An audio file viewer and annotation editor. Chris@52: Centre for Digital Music, Queen Mary, University of London. Chris@1241: This file copyright 2006-2016 Chris Cannam and QMUL. Chris@0: Chris@52: This program is free software; you can redistribute it and/or Chris@52: modify it under the terms of the GNU General Public License as Chris@52: published by the Free Software Foundation; either version 2 of the Chris@52: License, or (at your option) any later version. See the file Chris@52: COPYING included with this distribution for more information. Chris@0: */ Chris@0: Chris@1225: #include "PiperVampPluginFactory.h" Chris@0: #include "PluginIdentifier.h" Chris@0: Chris@150: #include "system/System.h" Chris@66: Chris@1179: #include "PluginScan.h" Chris@1179: Chris@1224: #ifdef _WIN32 Chris@1224: #undef VOID Chris@1224: #undef ERROR Chris@1224: #define CAPNP_LITE 1 Chris@1224: #endif Chris@1225: Chris@1210: #include "vamp-client/AutoPlugin.h" Chris@1210: Chris@66: #include Chris@66: #include Chris@66: #include Chris@165: #include Chris@1227: #include Chris@66: Chris@0: #include Chris@0: Chris@408: #include "base/Profiler.h" Chris@1241: #include "base/HelperExecPath.h" Chris@408: Chris@1223: #include "vamp-client/ProcessQtTransport.h" Chris@1223: #include "vamp-client/CapnpRRClient.h" Chris@1223: Chris@1164: using namespace std; Chris@1164: Chris@249: //#define DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 1 Chris@249: Chris@1240: PiperVampPluginFactory::PiperVampPluginFactory() Chris@66: { Chris@1241: QString serverName = "piper-vamp-simple-server"; Chris@1240: Chris@1241: m_servers = HelperExecPath::getHelperExecutables(serverName); Chris@1240: Chris@1240: if (m_servers.empty()) { Chris@1241: cerr << "NOTE: No Piper Vamp servers found in installation;" Chris@1241: << " found none of the following:" << endl; Chris@1241: for (auto d: HelperExecPath::getHelperCandidatePaths(serverName)) { Chris@1241: cerr << "NOTE: " << d << endl; Chris@1241: } Chris@1240: } Chris@1240: } Chris@1240: Chris@1240: QStringList Chris@1240: PiperVampPluginFactory::getServerSuffixes() Chris@1240: { Chris@1240: if (sizeof(void *) == 8) { Chris@1240: return { "-64", "", "-32" }; Chris@1227: } else { Chris@1240: return { "", "-32" }; Chris@1227: } Chris@66: } Chris@66: Chris@1164: vector Chris@1227: PiperVampPluginFactory::getPluginIdentifiers(QString &errorMessage) Chris@0: { Chris@1225: Profiler profiler("PiperVampPluginFactory::getPluginIdentifiers"); Chris@408: Chris@1209: QMutexLocker locker(&m_mutex); Chris@1209: Chris@1240: if (m_servers.empty()) { Chris@1227: errorMessage = QObject::tr("External plugin host executable does not appear to be installed"); Chris@1227: return {}; Chris@1227: } Chris@1227: Chris@1209: if (m_pluginData.empty()) { Chris@1227: populate(errorMessage); Chris@1209: } Chris@1209: Chris@1164: vector rv; Chris@1179: Chris@1209: for (const auto &d: m_pluginData) { Chris@1225: rv.push_back(QString("vamp:") + QString::fromStdString(d.second.pluginKey)); Chris@66: } Chris@66: Chris@0: return rv; Chris@0: } Chris@0: Chris@66: Vamp::Plugin * Chris@1225: PiperVampPluginFactory::instantiatePlugin(QString identifier, Chris@1225: sv_samplerate_t inputSampleRate) Chris@0: { Chris@1225: Profiler profiler("PiperVampPluginFactory::instantiatePlugin"); Chris@1225: Chris@1240: if (m_origins.find(identifier) == m_origins.end()) { Chris@1240: cerr << "ERROR: No known server for identifier " << identifier << endl; Chris@1240: return 0; Chris@1240: } Chris@1240: Chris@1225: auto psd = getPluginStaticData(identifier); Chris@1225: if (psd.pluginKey == "") { Chris@1225: return 0; Chris@1225: } Chris@1210: Chris@1210: auto ap = new piper_vamp::client::AutoPlugin Chris@1240: (m_origins[identifier].toStdString(), Chris@1240: psd.pluginKey, float(inputSampleRate), 0); Chris@1240: Chris@1210: if (!ap->isOK()) { Chris@1210: delete ap; Chris@1210: return 0; Chris@1225: } Chris@1225: Chris@1225: return ap; Chris@1225: } Chris@1225: Chris@1225: piper_vamp::PluginStaticData Chris@1225: PiperVampPluginFactory::getPluginStaticData(QString identifier) Chris@1225: { Chris@1225: if (m_pluginData.find(identifier) != m_pluginData.end()) { Chris@1225: return m_pluginData[identifier]; Chris@1210: } else { Chris@1225: return {}; Chris@1210: } Chris@298: } Chris@298: Chris@165: QString Chris@1225: PiperVampPluginFactory::getPluginCategory(QString identifier) Chris@165: { Chris@1223: if (m_taxonomy.find(identifier) != m_taxonomy.end()) { Chris@1223: return m_taxonomy[identifier]; Chris@1223: } else { Chris@1223: return {}; Chris@1223: } Chris@165: } Chris@165: Chris@165: void Chris@1227: PiperVampPluginFactory::populate(QString &errorMessage) Chris@165: { Chris@1240: QString someError; Chris@1227: Chris@1240: for (QString s: m_servers) { Chris@1240: Chris@1240: populateFrom(s, someError); Chris@1240: Chris@1240: if (someError != "" && errorMessage == "") { Chris@1240: errorMessage = someError; Chris@1240: } Chris@1240: } Chris@1240: } Chris@1240: Chris@1240: void Chris@1240: PiperVampPluginFactory::populateFrom(QString server, QString &errorMessage) Chris@1240: { Chris@1240: piper_vamp::client::ProcessQtTransport transport(server.toStdString(), Chris@1240: "capnp"); Chris@1227: if (!transport.isOK()) { Chris@1227: errorMessage = QObject::tr("Could not start external plugin host"); Chris@1227: return; Chris@1227: } Chris@1234: Chris@1223: piper_vamp::client::CapnpRRClient client(&transport); Chris@1234: piper_vamp::ListResponse lr; Chris@1234: Chris@1234: try { Chris@1234: lr = client.listPluginData(); Chris@1234: } catch (piper_vamp::client::ServerCrashed) { Chris@1234: errorMessage = QObject::tr Chris@1234: ("External plugin host exited unexpectedly while listing plugins"); Chris@1234: return; Chris@1235: } catch (const std::exception &e) { Chris@1235: errorMessage = QObject::tr("External plugin host invocation failed: %1") Chris@1235: .arg(e.what()); Chris@1235: return; Chris@1234: } Chris@1213: Chris@1244: cerr << "PiperVampPluginFactory: server \"" << server << "\" lists " Chris@1244: << lr.available.size() << " plugin(s)" << endl; Chris@1244: Chris@1225: for (const auto &pd: lr.available) { Chris@1240: Chris@1213: QString identifier = Chris@1213: QString("vamp:") + QString::fromStdString(pd.pluginKey); Chris@1213: Chris@1240: if (m_origins.find(identifier) != m_origins.end()) { Chris@1240: // have it already, from a higher-priority server Chris@1240: // (e.g. 64-bit instead of 32-bit) Chris@1240: continue; Chris@1240: } Chris@1240: Chris@1240: m_origins[identifier] = server; Chris@1240: Chris@1225: m_pluginData[identifier] = pd; Chris@1225: Chris@1213: QStringList catlist; Chris@1213: for (const auto &cs: pd.category) { Chris@1213: catlist.push_back(QString::fromStdString(cs)); Chris@1213: } Chris@1223: Chris@1213: m_taxonomy[identifier] = catlist.join(" > "); Chris@1213: } Chris@1209: } Chris@165: