annotate plugin/PiperVampPluginFactory.cpp @ 1241:c6bdf247016a 3.0-integration

Support multiple plugin checker helpers, as for multiple piper servers
author Chris Cannam
date Tue, 01 Nov 2016 14:06:47 +0000
parents 42a4b058f8ba
children 604b0b2a58e1
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@52 4 Sonic Visualiser
Chris@52 5 An audio file viewer and annotation editor.
Chris@52 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1241 7 This file copyright 2006-2016 Chris Cannam and QMUL.
Chris@0 8
Chris@52 9 This program is free software; you can redistribute it and/or
Chris@52 10 modify it under the terms of the GNU General Public License as
Chris@52 11 published by the Free Software Foundation; either version 2 of the
Chris@52 12 License, or (at your option) any later version. See the file
Chris@52 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@1225 16 #include "PiperVampPluginFactory.h"
Chris@0 17 #include "PluginIdentifier.h"
Chris@0 18
Chris@150 19 #include "system/System.h"
Chris@66 20
Chris@1179 21 #include "PluginScan.h"
Chris@1179 22
Chris@1224 23 #ifdef _WIN32
Chris@1224 24 #undef VOID
Chris@1224 25 #undef ERROR
Chris@1224 26 #define CAPNP_LITE 1
Chris@1224 27 #endif
Chris@1225 28
Chris@1210 29 #include "vamp-client/AutoPlugin.h"
Chris@1210 30
Chris@66 31 #include <QDir>
Chris@66 32 #include <QFile>
Chris@66 33 #include <QFileInfo>
Chris@165 34 #include <QTextStream>
Chris@1227 35 #include <QCoreApplication>
Chris@66 36
Chris@0 37 #include <iostream>
Chris@0 38
Chris@408 39 #include "base/Profiler.h"
Chris@1241 40 #include "base/HelperExecPath.h"
Chris@408 41
Chris@1223 42 #include "vamp-client/ProcessQtTransport.h"
Chris@1223 43 #include "vamp-client/CapnpRRClient.h"
Chris@1223 44
Chris@1164 45 using namespace std;
Chris@1164 46
Chris@249 47 //#define DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 1
Chris@249 48
Chris@1240 49 PiperVampPluginFactory::PiperVampPluginFactory()
Chris@66 50 {
Chris@1241 51 QString serverName = "piper-vamp-simple-server";
Chris@1240 52
Chris@1241 53 m_servers = HelperExecPath::getHelperExecutables(serverName);
Chris@1240 54
Chris@1240 55 if (m_servers.empty()) {
Chris@1241 56 cerr << "NOTE: No Piper Vamp servers found in installation;"
Chris@1241 57 << " found none of the following:" << endl;
Chris@1241 58 for (auto d: HelperExecPath::getHelperCandidatePaths(serverName)) {
Chris@1241 59 cerr << "NOTE: " << d << endl;
Chris@1241 60 }
Chris@1240 61 }
Chris@1240 62 }
Chris@1240 63
Chris@1240 64 QStringList
Chris@1240 65 PiperVampPluginFactory::getServerSuffixes()
Chris@1240 66 {
Chris@1240 67 if (sizeof(void *) == 8) {
Chris@1240 68 return { "-64", "", "-32" };
Chris@1227 69 } else {
Chris@1240 70 return { "", "-32" };
Chris@1227 71 }
Chris@66 72 }
Chris@66 73
Chris@1164 74 vector<QString>
Chris@1227 75 PiperVampPluginFactory::getPluginIdentifiers(QString &errorMessage)
Chris@0 76 {
Chris@1225 77 Profiler profiler("PiperVampPluginFactory::getPluginIdentifiers");
Chris@408 78
Chris@1209 79 QMutexLocker locker(&m_mutex);
Chris@1209 80
Chris@1240 81 if (m_servers.empty()) {
Chris@1227 82 errorMessage = QObject::tr("External plugin host executable does not appear to be installed");
Chris@1227 83 return {};
Chris@1227 84 }
Chris@1227 85
Chris@1209 86 if (m_pluginData.empty()) {
Chris@1227 87 populate(errorMessage);
Chris@1209 88 }
Chris@1209 89
Chris@1164 90 vector<QString> rv;
Chris@1179 91
Chris@1209 92 for (const auto &d: m_pluginData) {
Chris@1225 93 rv.push_back(QString("vamp:") + QString::fromStdString(d.second.pluginKey));
Chris@66 94 }
Chris@66 95
Chris@0 96 return rv;
Chris@0 97 }
Chris@0 98
Chris@66 99 Vamp::Plugin *
Chris@1225 100 PiperVampPluginFactory::instantiatePlugin(QString identifier,
Chris@1225 101 sv_samplerate_t inputSampleRate)
Chris@0 102 {
Chris@1225 103 Profiler profiler("PiperVampPluginFactory::instantiatePlugin");
Chris@1225 104
Chris@1240 105 if (m_origins.find(identifier) == m_origins.end()) {
Chris@1240 106 cerr << "ERROR: No known server for identifier " << identifier << endl;
Chris@1240 107 return 0;
Chris@1240 108 }
Chris@1240 109
Chris@1225 110 auto psd = getPluginStaticData(identifier);
Chris@1225 111 if (psd.pluginKey == "") {
Chris@1225 112 return 0;
Chris@1225 113 }
Chris@1210 114
Chris@1210 115 auto ap = new piper_vamp::client::AutoPlugin
Chris@1240 116 (m_origins[identifier].toStdString(),
Chris@1240 117 psd.pluginKey, float(inputSampleRate), 0);
Chris@1240 118
Chris@1210 119 if (!ap->isOK()) {
Chris@1210 120 delete ap;
Chris@1210 121 return 0;
Chris@1225 122 }
Chris@1225 123
Chris@1225 124 return ap;
Chris@1225 125 }
Chris@1225 126
Chris@1225 127 piper_vamp::PluginStaticData
Chris@1225 128 PiperVampPluginFactory::getPluginStaticData(QString identifier)
Chris@1225 129 {
Chris@1225 130 if (m_pluginData.find(identifier) != m_pluginData.end()) {
Chris@1225 131 return m_pluginData[identifier];
Chris@1210 132 } else {
Chris@1225 133 return {};
Chris@1210 134 }
Chris@298 135 }
Chris@298 136
Chris@165 137 QString
Chris@1225 138 PiperVampPluginFactory::getPluginCategory(QString identifier)
Chris@165 139 {
Chris@1223 140 if (m_taxonomy.find(identifier) != m_taxonomy.end()) {
Chris@1223 141 return m_taxonomy[identifier];
Chris@1223 142 } else {
Chris@1223 143 return {};
Chris@1223 144 }
Chris@165 145 }
Chris@165 146
Chris@165 147 void
Chris@1227 148 PiperVampPluginFactory::populate(QString &errorMessage)
Chris@165 149 {
Chris@1240 150 QString someError;
Chris@1227 151
Chris@1240 152 for (QString s: m_servers) {
Chris@1240 153
Chris@1240 154 populateFrom(s, someError);
Chris@1240 155
Chris@1240 156 if (someError != "" && errorMessage == "") {
Chris@1240 157 errorMessage = someError;
Chris@1240 158 }
Chris@1240 159 }
Chris@1240 160 }
Chris@1240 161
Chris@1240 162 void
Chris@1240 163 PiperVampPluginFactory::populateFrom(QString server, QString &errorMessage)
Chris@1240 164 {
Chris@1240 165 piper_vamp::client::ProcessQtTransport transport(server.toStdString(),
Chris@1240 166 "capnp");
Chris@1227 167 if (!transport.isOK()) {
Chris@1227 168 errorMessage = QObject::tr("Could not start external plugin host");
Chris@1227 169 return;
Chris@1227 170 }
Chris@1234 171
Chris@1223 172 piper_vamp::client::CapnpRRClient client(&transport);
Chris@1234 173 piper_vamp::ListResponse lr;
Chris@1234 174
Chris@1234 175 try {
Chris@1234 176 lr = client.listPluginData();
Chris@1234 177 } catch (piper_vamp::client::ServerCrashed) {
Chris@1234 178 errorMessage = QObject::tr
Chris@1234 179 ("External plugin host exited unexpectedly while listing plugins");
Chris@1234 180 return;
Chris@1235 181 } catch (const std::exception &e) {
Chris@1235 182 errorMessage = QObject::tr("External plugin host invocation failed: %1")
Chris@1235 183 .arg(e.what());
Chris@1235 184 return;
Chris@1234 185 }
Chris@1213 186
Chris@1225 187 for (const auto &pd: lr.available) {
Chris@1240 188
Chris@1213 189 QString identifier =
Chris@1213 190 QString("vamp:") + QString::fromStdString(pd.pluginKey);
Chris@1213 191
Chris@1240 192 if (m_origins.find(identifier) != m_origins.end()) {
Chris@1240 193 // have it already, from a higher-priority server
Chris@1240 194 // (e.g. 64-bit instead of 32-bit)
Chris@1240 195 continue;
Chris@1240 196 }
Chris@1240 197
Chris@1240 198 m_origins[identifier] = server;
Chris@1240 199
Chris@1225 200 m_pluginData[identifier] = pd;
Chris@1225 201
Chris@1213 202 QStringList catlist;
Chris@1213 203 for (const auto &cs: pd.category) {
Chris@1213 204 catlist.push_back(QString::fromStdString(cs));
Chris@1213 205 }
Chris@1223 206
Chris@1213 207 m_taxonomy[identifier] = catlist.join(" > ");
Chris@1213 208 }
Chris@1209 209 }
Chris@165 210