annotate plugin/PiperVampPluginFactory.cpp @ 1240:42a4b058f8ba 3.0-integration

Support for multiple servers
author Chris Cannam
date Tue, 01 Nov 2016 12:09:05 +0000
parents fe391a7b8376
children c6bdf247016a
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@202 7 This file copyright 2006 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@408 40
Chris@1223 41 #include "vamp-client/ProcessQtTransport.h"
Chris@1223 42 #include "vamp-client/CapnpRRClient.h"
Chris@1223 43
Chris@1164 44 using namespace std;
Chris@1164 45
Chris@249 46 //#define DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 1
Chris@249 47
Chris@1240 48 PiperVampPluginFactory::PiperVampPluginFactory()
Chris@66 49 {
Chris@1227 50 // Server must exist either in the same directory as this one or
Chris@1227 51 // (preferably) a subdirectory called "piper-bin".
Chris@1227 52 //!!! todo: merge this with plugin scan checker thingy used in main.cpp?
Chris@1240 53
Chris@1227 54 QString myDir = QCoreApplication::applicationDirPath();
Chris@1236 55 QString name = "piper-vamp-simple-server";
Chris@1240 56 QStringList suffixes = getServerSuffixes();
Chris@1240 57 QString extension = "";
Chris@1227 58 #ifdef _WIN32
Chris@1240 59 extension = ".exe";
Chris@1227 60 #endif
Chris@1240 61
Chris@1240 62 for (QString s: suffixes) {
Chris@1240 63
Chris@1240 64 QString path = myDir + "/piper-bin/" + name + s + extension;
Chris@1240 65
Chris@1240 66 if (QFile(path).exists()) {
Chris@1240 67 m_servers.push_back(path);
Chris@1240 68 } else {
Chris@1240 69 cerr << "NOTE: Piper Vamp server " << name << s
Chris@1240 70 << " not found at " << path
Chris@1240 71 << ", trying in my own directory" << endl;
Chris@1240 72 path = myDir + "/" + name + s + extension;
Chris@1240 73
Chris@1240 74 if (QFile(path).exists()) {
Chris@1240 75 m_servers.push_back(path);
Chris@1240 76 } else {
Chris@1240 77 cerr << "NOTE: Piper Vamp server " << name << s
Chris@1240 78 << " not found at " << path << endl;
Chris@1240 79 }
Chris@1240 80 }
Chris@1227 81 }
Chris@1240 82
Chris@1240 83 if (m_servers.empty()) {
Chris@1240 84 cerr << "NOTE: No Piper Vamp servers found" << endl;
Chris@1240 85 }
Chris@1240 86 }
Chris@1240 87
Chris@1240 88 QStringList
Chris@1240 89 PiperVampPluginFactory::getServerSuffixes()
Chris@1240 90 {
Chris@1240 91 if (sizeof(void *) == 8) {
Chris@1240 92 return { "-64", "", "-32" };
Chris@1227 93 } else {
Chris@1240 94 return { "", "-32" };
Chris@1227 95 }
Chris@66 96 }
Chris@66 97
Chris@1164 98 vector<QString>
Chris@1227 99 PiperVampPluginFactory::getPluginIdentifiers(QString &errorMessage)
Chris@0 100 {
Chris@1225 101 Profiler profiler("PiperVampPluginFactory::getPluginIdentifiers");
Chris@408 102
Chris@1209 103 QMutexLocker locker(&m_mutex);
Chris@1209 104
Chris@1240 105 if (m_servers.empty()) {
Chris@1227 106 errorMessage = QObject::tr("External plugin host executable does not appear to be installed");
Chris@1227 107 return {};
Chris@1227 108 }
Chris@1227 109
Chris@1209 110 if (m_pluginData.empty()) {
Chris@1227 111 populate(errorMessage);
Chris@1209 112 }
Chris@1209 113
Chris@1164 114 vector<QString> rv;
Chris@1179 115
Chris@1209 116 for (const auto &d: m_pluginData) {
Chris@1225 117 rv.push_back(QString("vamp:") + QString::fromStdString(d.second.pluginKey));
Chris@66 118 }
Chris@66 119
Chris@0 120 return rv;
Chris@0 121 }
Chris@0 122
Chris@66 123 Vamp::Plugin *
Chris@1225 124 PiperVampPluginFactory::instantiatePlugin(QString identifier,
Chris@1225 125 sv_samplerate_t inputSampleRate)
Chris@0 126 {
Chris@1225 127 Profiler profiler("PiperVampPluginFactory::instantiatePlugin");
Chris@1225 128
Chris@1240 129 if (m_origins.find(identifier) == m_origins.end()) {
Chris@1240 130 cerr << "ERROR: No known server for identifier " << identifier << endl;
Chris@1240 131 return 0;
Chris@1240 132 }
Chris@1240 133
Chris@1225 134 auto psd = getPluginStaticData(identifier);
Chris@1225 135 if (psd.pluginKey == "") {
Chris@1225 136 return 0;
Chris@1225 137 }
Chris@1210 138
Chris@1210 139 auto ap = new piper_vamp::client::AutoPlugin
Chris@1240 140 (m_origins[identifier].toStdString(),
Chris@1240 141 psd.pluginKey, float(inputSampleRate), 0);
Chris@1240 142
Chris@1210 143 if (!ap->isOK()) {
Chris@1210 144 delete ap;
Chris@1210 145 return 0;
Chris@1225 146 }
Chris@1225 147
Chris@1225 148 return ap;
Chris@1225 149 }
Chris@1225 150
Chris@1225 151 piper_vamp::PluginStaticData
Chris@1225 152 PiperVampPluginFactory::getPluginStaticData(QString identifier)
Chris@1225 153 {
Chris@1225 154 if (m_pluginData.find(identifier) != m_pluginData.end()) {
Chris@1225 155 return m_pluginData[identifier];
Chris@1210 156 } else {
Chris@1225 157 return {};
Chris@1210 158 }
Chris@298 159 }
Chris@298 160
Chris@165 161 QString
Chris@1225 162 PiperVampPluginFactory::getPluginCategory(QString identifier)
Chris@165 163 {
Chris@1223 164 if (m_taxonomy.find(identifier) != m_taxonomy.end()) {
Chris@1223 165 return m_taxonomy[identifier];
Chris@1223 166 } else {
Chris@1223 167 return {};
Chris@1223 168 }
Chris@165 169 }
Chris@165 170
Chris@165 171 void
Chris@1227 172 PiperVampPluginFactory::populate(QString &errorMessage)
Chris@165 173 {
Chris@1240 174 QString someError;
Chris@1227 175
Chris@1240 176 for (QString s: m_servers) {
Chris@1240 177
Chris@1240 178 populateFrom(s, someError);
Chris@1240 179
Chris@1240 180 if (someError != "" && errorMessage == "") {
Chris@1240 181 errorMessage = someError;
Chris@1240 182 }
Chris@1240 183 }
Chris@1240 184 }
Chris@1240 185
Chris@1240 186 void
Chris@1240 187 PiperVampPluginFactory::populateFrom(QString server, QString &errorMessage)
Chris@1240 188 {
Chris@1240 189 piper_vamp::client::ProcessQtTransport transport(server.toStdString(),
Chris@1240 190 "capnp");
Chris@1227 191 if (!transport.isOK()) {
Chris@1227 192 errorMessage = QObject::tr("Could not start external plugin host");
Chris@1227 193 return;
Chris@1227 194 }
Chris@1234 195
Chris@1223 196 piper_vamp::client::CapnpRRClient client(&transport);
Chris@1234 197 piper_vamp::ListResponse lr;
Chris@1234 198
Chris@1234 199 try {
Chris@1234 200 lr = client.listPluginData();
Chris@1234 201 } catch (piper_vamp::client::ServerCrashed) {
Chris@1234 202 errorMessage = QObject::tr
Chris@1234 203 ("External plugin host exited unexpectedly while listing plugins");
Chris@1234 204 return;
Chris@1235 205 } catch (const std::exception &e) {
Chris@1235 206 errorMessage = QObject::tr("External plugin host invocation failed: %1")
Chris@1235 207 .arg(e.what());
Chris@1235 208 return;
Chris@1234 209 }
Chris@1213 210
Chris@1225 211 for (const auto &pd: lr.available) {
Chris@1240 212
Chris@1213 213 QString identifier =
Chris@1213 214 QString("vamp:") + QString::fromStdString(pd.pluginKey);
Chris@1213 215
Chris@1240 216 if (m_origins.find(identifier) != m_origins.end()) {
Chris@1240 217 // have it already, from a higher-priority server
Chris@1240 218 // (e.g. 64-bit instead of 32-bit)
Chris@1240 219 continue;
Chris@1240 220 }
Chris@1240 221
Chris@1240 222 m_origins[identifier] = server;
Chris@1240 223
Chris@1225 224 m_pluginData[identifier] = pd;
Chris@1225 225
Chris@1213 226 QStringList catlist;
Chris@1213 227 for (const auto &cs: pd.category) {
Chris@1213 228 catlist.push_back(QString::fromStdString(cs));
Chris@1213 229 }
Chris@1223 230
Chris@1213 231 m_taxonomy[identifier] = catlist.join(" > ");
Chris@1213 232 }
Chris@1209 233 }
Chris@165 234