31 #include "vamp-client/qt/PiperAutoPlugin.h" 32 #include "vamp-client/qt/ProcessQtTransport.h" 33 #include "vamp-client/CapnpRRClient.h" 38 #include <QTextStream> 39 #include <QCoreApplication> 50 class PiperVampPluginFactory::Logger :
public piper_vamp::client::LogCallback {
52 void log(std::string message)
const override {
53 SVDEBUG <<
"PiperVampPluginFactory: " << message << endl;
57 PiperVampPluginFactory::PiperVampPluginFactory() :
60 QString serverName =
"piper-vamp-simple-server";
61 float minimumVersion = 2.0;
65 auto servers = hep.getHelperExecutables(serverName);
67 for (
auto n: servers) {
68 SVDEBUG <<
"NOTE: PiperVampPluginFactory: Found server: " 69 << n.executable << endl;
70 if (serverMeetsMinimumVersion(n, minimumVersion)) {
71 m_servers.push_back(n);
73 SVCERR <<
"WARNING: PiperVampPluginFactory: Server at " 75 <<
" does not meet minimum version requirement (version >= " 76 << minimumVersion <<
")" << endl;
80 if (m_servers.empty()) {
81 SVDEBUG <<
"NOTE: No Piper Vamp servers found in installation;" 82 <<
" the following paths are either absent or fail " 83 <<
"minimum-version check:" << endl;
84 for (
auto d: hep.getHelperCandidatePaths(serverName)) {
85 SVDEBUG <<
"NOTE: " << d << endl;
90 PiperVampPluginFactory::~PiperVampPluginFactory()
101 process.setReadChannel(QProcess::StandardOutput);
102 process.setProcessChannelMode(QProcess::ForwardedErrorChannel);
103 process.start(executable, {
"--version" });
105 if (!process.waitForStarted()) {
106 QProcess::ProcessError err = process.error();
107 if (err == QProcess::FailedToStart) {
108 SVCERR <<
"WARNING: Unable to start server " << executable
109 <<
" for version check" << endl;
110 }
else if (err == QProcess::Crashed) {
111 SVCERR <<
"WARNING: Server " << executable
112 <<
" crashed on version check" << endl;
114 SVCERR <<
"WARNING: Server " << executable
115 <<
" failed on version check with error code " 120 process.waitForFinished();
122 QByteArray output = process.readAllStandardOutput();
123 while (output.endsWith(
'\n') || output.endsWith(
'\r')) {
127 QString outputString(output);
129 float version = outputString.toFloat(&ok);
131 SVCERR <<
"WARNING: Failed to convert server version response \"" 132 << outputString <<
"\" into one- or two-part version number" 136 SVDEBUG <<
"Server " << executable <<
" reports version number " 140 return (version >= minimumVersion ||
141 fabsf(version - minimumVersion) < eps);
145 PiperVampPluginFactory::getPluginIdentifiers(QString &errorMessage)
147 Profiler profiler(
"PiperVampPluginFactory::getPluginIdentifiers");
149 QMutexLocker locker(&m_mutex);
151 if (m_servers.empty()) {
152 errorMessage = QObject::tr(
"External plugin host executable does not appear to be installed");
156 if (m_pluginData.empty()) {
157 populate(errorMessage);
162 for (
const auto &d: m_pluginData) {
163 rv.push_back(QString(
"vamp:") + QString::fromStdString(d.second.pluginKey));
169 std::shared_ptr<Vamp::Plugin>
170 PiperVampPluginFactory::instantiatePlugin(QString identifier,
173 Profiler profiler(
"PiperVampPluginFactory::instantiatePlugin");
175 if (m_origins.find(identifier) == m_origins.end()) {
176 SVCERR <<
"ERROR: No known server for identifier " << identifier << endl;
180 auto psd = getPluginStaticData(identifier);
181 if (psd.pluginKey ==
"") {
185 SVDEBUG <<
"PiperVampPluginFactory: Creating PiperAutoPlugin for server " 186 << m_origins[identifier] <<
", identifier " << identifier << endl;
188 auto ap =
new piper_vamp::client::PiperAutoPlugin
189 (m_origins[identifier].toStdString(),
191 float(inputSampleRate),
200 return std::shared_ptr<Vamp::Plugin>(ap);
203 piper_vamp::PluginStaticData
204 PiperVampPluginFactory::getPluginStaticData(QString identifier)
206 if (m_pluginData.find(identifier) != m_pluginData.end()) {
207 return m_pluginData[identifier];
214 PiperVampPluginFactory::getPluginCategory(QString identifier)
216 if (m_taxonomy.find(identifier) != m_taxonomy.end()) {
217 return m_taxonomy[identifier];
224 PiperVampPluginFactory::getPluginLibraryPath(QString identifier)
233 QStringList bits = identifier.split(
':');
234 if (bits.size() > 1) {
235 QString soname = bits[bits.size() - 2];
236 auto i = m_libraries.find(soname);
237 if (i != m_libraries.end()) {
245 PiperVampPluginFactory::populate(QString &errorMessage)
249 for (
auto s: m_servers) {
251 populateFrom(s, someError);
253 if (someError !=
"" && errorMessage ==
"") {
254 errorMessage = someError;
261 QString &errorMessage)
263 QString tag = server.
tag;
264 string executable = server.
executable.toStdString();
267 auto candidateLibraries =
270 SVDEBUG <<
"PiperVampPluginFactory: Populating from " << executable << endl;
271 SVDEBUG <<
"INFO: Have " << candidateLibraries.size()
272 <<
" candidate Vamp plugin libraries from scanner" << endl;
275 for (
const auto &c: candidateLibraries) {
276 if (c.helperTag == tag) {
277 string soname = QFileInfo(c.libraryPath).baseName().toStdString();
278 SVDEBUG <<
"INFO: For tag \"" << tag <<
"\" giving library " << soname << endl;
279 from.push_back(soname);
280 QString qsoname = QString::fromStdString(soname);
281 if (m_libraries.find(qsoname) == m_libraries.end()) {
282 m_libraries[qsoname] = c.libraryPath;
288 SVDEBUG <<
"PiperVampPluginFactory: No candidate libraries for tag \"" 294 SVDEBUG <<
", skipping" << endl;
297 SVDEBUG <<
", but it seems the scan failed, so bumbling on anyway" << endl;
301 piper_vamp::client::ProcessQtTransport transport(executable,
"capnp", m_logger);
302 if (!transport.isOK()) {
303 SVDEBUG <<
"PiperVampPluginFactory: Failed to start Piper process transport" << endl;
304 errorMessage = QObject::tr(
"Could not start external plugin host");
308 piper_vamp::client::CapnpRRClient client(&transport, m_logger);
310 piper_vamp::ListRequest req;
313 piper_vamp::ListResponse resp;
316 resp = client.list(req);
317 }
catch (
const piper_vamp::client::ServerCrashed &) {
318 SVDEBUG <<
"PiperVampPluginFactory: Piper server crashed" << endl;
319 errorMessage = QObject::tr
320 (
"External plugin host exited unexpectedly while listing plugins");
322 }
catch (
const std::exception &e) {
323 SVDEBUG <<
"PiperVampPluginFactory: Exception caught: " << e.what() << endl;
324 errorMessage = QObject::tr(
"External plugin host invocation failed: %1")
329 SVDEBUG <<
"PiperVampPluginFactory: server \"" << executable <<
"\" lists " 330 << resp.available.size() <<
" plugin(s)" << endl;
332 for (
const auto &pd: resp.available) {
335 QString(
"vamp:") + QString::fromStdString(pd.pluginKey);
337 if (m_origins.find(identifier) != m_origins.end()) {
345 m_pluginData[identifier] = pd;
348 for (
const auto &cs: pd.category) {
349 catlist.push_back(QString::fromStdString(cs));
352 m_taxonomy[identifier] = catlist.join(
" > ");
double sv_samplerate_t
Sample rate.
QList< Candidate > getCandidateLibrariesFor(PluginType) const
Return the candidate plugin libraries of the given type that were found by helpers during the startup...
static PluginScan * getInstance()
Class to find helper executables that have been installed alongside the application.
bool scanSucceeded() const
Return true if scan() completed successfully.
Profile point instance class.