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
|