Chris@330
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@330
|
2
|
Chris@330
|
3 /*
|
Chris@330
|
4 Sonic Visualiser
|
Chris@330
|
5 An audio file viewer and annotation editor.
|
Chris@330
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@330
|
7 This file copyright 2006 Chris Cannam and QMUL.
|
Chris@330
|
8
|
Chris@330
|
9 This program is free software; you can redistribute it and/or
|
Chris@330
|
10 modify it under the terms of the GNU General Public License as
|
Chris@330
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@330
|
12 License, or (at your option) any later version. See the file
|
Chris@330
|
13 COPYING included with this distribution for more information.
|
Chris@330
|
14 */
|
Chris@330
|
15
|
Chris@330
|
16 #include "TransformFactory.h"
|
Chris@330
|
17
|
Chris@330
|
18 #include "plugin/FeatureExtractionPluginFactory.h"
|
Chris@330
|
19 #include "plugin/RealTimePluginFactory.h"
|
Chris@330
|
20 #include "plugin/PluginXml.h"
|
Chris@330
|
21
|
Chris@330
|
22 #include "vamp-sdk/PluginHostAdapter.h"
|
Chris@330
|
23
|
Chris@330
|
24 #include <iostream>
|
Chris@330
|
25 #include <set>
|
Chris@330
|
26
|
Chris@330
|
27 #include <QRegExp>
|
Chris@330
|
28
|
Chris@330
|
29 TransformFactory *
|
Chris@330
|
30 TransformFactory::m_instance = new TransformFactory;
|
Chris@330
|
31
|
Chris@330
|
32 TransformFactory *
|
Chris@330
|
33 TransformFactory::getInstance()
|
Chris@330
|
34 {
|
Chris@330
|
35 return m_instance;
|
Chris@330
|
36 }
|
Chris@330
|
37
|
Chris@330
|
38 TransformFactory::~TransformFactory()
|
Chris@330
|
39 {
|
Chris@330
|
40 }
|
Chris@330
|
41
|
Chris@330
|
42 TransformList
|
Chris@330
|
43 TransformFactory::getAllTransforms()
|
Chris@330
|
44 {
|
Chris@330
|
45 if (m_transforms.empty()) populateTransforms();
|
Chris@330
|
46
|
Chris@330
|
47 std::set<TransformDescription> dset;
|
Chris@330
|
48 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
|
Chris@330
|
49 i != m_transforms.end(); ++i) {
|
Chris@330
|
50 dset.insert(i->second);
|
Chris@330
|
51 }
|
Chris@330
|
52
|
Chris@330
|
53 TransformList list;
|
Chris@330
|
54 for (std::set<TransformDescription>::const_iterator i = dset.begin();
|
Chris@330
|
55 i != dset.end(); ++i) {
|
Chris@330
|
56 list.push_back(*i);
|
Chris@330
|
57 }
|
Chris@330
|
58
|
Chris@330
|
59 return list;
|
Chris@330
|
60 }
|
Chris@330
|
61
|
Chris@330
|
62 std::vector<QString>
|
Chris@330
|
63 TransformFactory::getAllTransformTypes()
|
Chris@330
|
64 {
|
Chris@330
|
65 if (m_transforms.empty()) populateTransforms();
|
Chris@330
|
66
|
Chris@330
|
67 std::set<QString> types;
|
Chris@330
|
68 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
|
Chris@330
|
69 i != m_transforms.end(); ++i) {
|
Chris@330
|
70 types.insert(i->second.type);
|
Chris@330
|
71 }
|
Chris@330
|
72
|
Chris@330
|
73 std::vector<QString> rv;
|
Chris@330
|
74 for (std::set<QString>::iterator i = types.begin(); i != types.end(); ++i) {
|
Chris@330
|
75 rv.push_back(*i);
|
Chris@330
|
76 }
|
Chris@330
|
77
|
Chris@330
|
78 return rv;
|
Chris@330
|
79 }
|
Chris@330
|
80
|
Chris@330
|
81 std::vector<QString>
|
Chris@330
|
82 TransformFactory::getTransformCategories(QString transformType)
|
Chris@330
|
83 {
|
Chris@330
|
84 if (m_transforms.empty()) populateTransforms();
|
Chris@330
|
85
|
Chris@330
|
86 std::set<QString> categories;
|
Chris@330
|
87 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
|
Chris@330
|
88 i != m_transforms.end(); ++i) {
|
Chris@330
|
89 if (i->second.type == transformType) {
|
Chris@330
|
90 categories.insert(i->second.category);
|
Chris@330
|
91 }
|
Chris@330
|
92 }
|
Chris@330
|
93
|
Chris@330
|
94 bool haveEmpty = false;
|
Chris@330
|
95
|
Chris@330
|
96 std::vector<QString> rv;
|
Chris@330
|
97 for (std::set<QString>::iterator i = categories.begin();
|
Chris@330
|
98 i != categories.end(); ++i) {
|
Chris@330
|
99 if (*i != "") rv.push_back(*i);
|
Chris@330
|
100 else haveEmpty = true;
|
Chris@330
|
101 }
|
Chris@330
|
102
|
Chris@330
|
103 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
|
Chris@330
|
104
|
Chris@330
|
105 return rv;
|
Chris@330
|
106 }
|
Chris@330
|
107
|
Chris@330
|
108 std::vector<QString>
|
Chris@330
|
109 TransformFactory::getTransformMakers(QString transformType)
|
Chris@330
|
110 {
|
Chris@330
|
111 if (m_transforms.empty()) populateTransforms();
|
Chris@330
|
112
|
Chris@330
|
113 std::set<QString> makers;
|
Chris@330
|
114 for (TransformDescriptionMap::const_iterator i = m_transforms.begin();
|
Chris@330
|
115 i != m_transforms.end(); ++i) {
|
Chris@330
|
116 if (i->second.type == transformType) {
|
Chris@330
|
117 makers.insert(i->second.maker);
|
Chris@330
|
118 }
|
Chris@330
|
119 }
|
Chris@330
|
120
|
Chris@330
|
121 bool haveEmpty = false;
|
Chris@330
|
122
|
Chris@330
|
123 std::vector<QString> rv;
|
Chris@330
|
124 for (std::set<QString>::iterator i = makers.begin();
|
Chris@330
|
125 i != makers.end(); ++i) {
|
Chris@330
|
126 if (*i != "") rv.push_back(*i);
|
Chris@330
|
127 else haveEmpty = true;
|
Chris@330
|
128 }
|
Chris@330
|
129
|
Chris@330
|
130 if (haveEmpty) rv.push_back(""); // make sure empty category sorts last
|
Chris@330
|
131
|
Chris@330
|
132 return rv;
|
Chris@330
|
133 }
|
Chris@330
|
134
|
Chris@330
|
135 void
|
Chris@330
|
136 TransformFactory::populateTransforms()
|
Chris@330
|
137 {
|
Chris@330
|
138 TransformDescriptionMap transforms;
|
Chris@330
|
139
|
Chris@330
|
140 populateFeatureExtractionPlugins(transforms);
|
Chris@330
|
141 populateRealTimePlugins(transforms);
|
Chris@330
|
142
|
Chris@330
|
143 // disambiguate plugins with similar names
|
Chris@330
|
144
|
Chris@330
|
145 std::map<QString, int> names;
|
Chris@330
|
146 std::map<QString, QString> pluginSources;
|
Chris@330
|
147 std::map<QString, QString> pluginMakers;
|
Chris@330
|
148
|
Chris@330
|
149 for (TransformDescriptionMap::iterator i = transforms.begin();
|
Chris@330
|
150 i != transforms.end(); ++i) {
|
Chris@330
|
151
|
Chris@330
|
152 TransformDescription desc = i->second;
|
Chris@330
|
153
|
Chris@330
|
154 QString td = desc.name;
|
Chris@330
|
155 QString tn = td.section(": ", 0, 0);
|
Chris@330
|
156 QString pn = desc.identifier.section(":", 1, 1);
|
Chris@330
|
157
|
Chris@330
|
158 if (pluginSources.find(tn) != pluginSources.end()) {
|
Chris@330
|
159 if (pluginSources[tn] != pn && pluginMakers[tn] != desc.maker) {
|
Chris@330
|
160 ++names[tn];
|
Chris@330
|
161 }
|
Chris@330
|
162 } else {
|
Chris@330
|
163 ++names[tn];
|
Chris@330
|
164 pluginSources[tn] = pn;
|
Chris@330
|
165 pluginMakers[tn] = desc.maker;
|
Chris@330
|
166 }
|
Chris@330
|
167 }
|
Chris@330
|
168
|
Chris@330
|
169 std::map<QString, int> counts;
|
Chris@330
|
170 m_transforms.clear();
|
Chris@330
|
171
|
Chris@330
|
172 for (TransformDescriptionMap::iterator i = transforms.begin();
|
Chris@330
|
173 i != transforms.end(); ++i) {
|
Chris@330
|
174
|
Chris@330
|
175 TransformDescription desc = i->second;
|
Chris@330
|
176 QString identifier = desc.identifier;
|
Chris@330
|
177 QString maker = desc.maker;
|
Chris@330
|
178
|
Chris@330
|
179 QString td = desc.name;
|
Chris@330
|
180 QString tn = td.section(": ", 0, 0);
|
Chris@330
|
181 QString to = td.section(": ", 1);
|
Chris@330
|
182
|
Chris@330
|
183 if (names[tn] > 1) {
|
Chris@330
|
184 maker.replace(QRegExp(tr(" [\\(<].*$")), "");
|
Chris@330
|
185 tn = QString("%1 [%2]").arg(tn).arg(maker);
|
Chris@330
|
186 }
|
Chris@330
|
187
|
Chris@330
|
188 if (to != "") {
|
Chris@330
|
189 desc.name = QString("%1: %2").arg(tn).arg(to);
|
Chris@330
|
190 } else {
|
Chris@330
|
191 desc.name = tn;
|
Chris@330
|
192 }
|
Chris@330
|
193
|
Chris@330
|
194 m_transforms[identifier] = desc;
|
Chris@330
|
195 }
|
Chris@330
|
196 }
|
Chris@330
|
197
|
Chris@330
|
198 void
|
Chris@330
|
199 TransformFactory::populateFeatureExtractionPlugins(TransformDescriptionMap &transforms)
|
Chris@330
|
200 {
|
Chris@330
|
201 std::vector<QString> plugs =
|
Chris@330
|
202 FeatureExtractionPluginFactory::getAllPluginIdentifiers();
|
Chris@330
|
203
|
Chris@330
|
204 for (size_t i = 0; i < plugs.size(); ++i) {
|
Chris@330
|
205
|
Chris@330
|
206 QString pluginId = plugs[i];
|
Chris@330
|
207
|
Chris@330
|
208 FeatureExtractionPluginFactory *factory =
|
Chris@330
|
209 FeatureExtractionPluginFactory::instanceFor(pluginId);
|
Chris@330
|
210
|
Chris@330
|
211 if (!factory) {
|
Chris@330
|
212 std::cerr << "WARNING: TransformFactory::populateTransforms: No feature extraction plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
|
Chris@330
|
213 continue;
|
Chris@330
|
214 }
|
Chris@330
|
215
|
Chris@330
|
216 Vamp::Plugin *plugin =
|
Chris@330
|
217 factory->instantiatePlugin(pluginId, 48000);
|
Chris@330
|
218
|
Chris@330
|
219 if (!plugin) {
|
Chris@330
|
220 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << std::endl;
|
Chris@330
|
221 continue;
|
Chris@330
|
222 }
|
Chris@330
|
223
|
Chris@330
|
224 QString pluginName = plugin->getName().c_str();
|
Chris@330
|
225 QString category = factory->getPluginCategory(pluginId);
|
Chris@330
|
226
|
Chris@330
|
227 Vamp::Plugin::OutputList outputs =
|
Chris@330
|
228 plugin->getOutputDescriptors();
|
Chris@330
|
229
|
Chris@330
|
230 for (size_t j = 0; j < outputs.size(); ++j) {
|
Chris@330
|
231
|
Chris@330
|
232 QString transformId = QString("%1:%2")
|
Chris@330
|
233 .arg(pluginId).arg(outputs[j].identifier.c_str());
|
Chris@330
|
234
|
Chris@330
|
235 QString userName;
|
Chris@330
|
236 QString friendlyName;
|
Chris@330
|
237 QString units = outputs[j].unit.c_str();
|
Chris@330
|
238 QString description = plugin->getDescription().c_str();
|
Chris@330
|
239 QString maker = plugin->getMaker().c_str();
|
Chris@330
|
240 if (maker == "") maker = tr("<unknown maker>");
|
Chris@330
|
241
|
Chris@330
|
242 if (description == "") {
|
Chris@330
|
243 if (outputs.size() == 1) {
|
Chris@330
|
244 description = tr("Extract features using \"%1\" plugin (from %2)")
|
Chris@330
|
245 .arg(pluginName).arg(maker);
|
Chris@330
|
246 } else {
|
Chris@330
|
247 description = tr("Extract features using \"%1\" output of \"%2\" plugin (from %3)")
|
Chris@330
|
248 .arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
|
Chris@330
|
249 }
|
Chris@330
|
250 } else {
|
Chris@330
|
251 if (outputs.size() == 1) {
|
Chris@330
|
252 description = tr("%1 using \"%2\" plugin (from %3)")
|
Chris@330
|
253 .arg(description).arg(pluginName).arg(maker);
|
Chris@330
|
254 } else {
|
Chris@330
|
255 description = tr("%1 using \"%2\" output of \"%3\" plugin (from %4)")
|
Chris@330
|
256 .arg(description).arg(outputs[j].name.c_str()).arg(pluginName).arg(maker);
|
Chris@330
|
257 }
|
Chris@330
|
258 }
|
Chris@330
|
259
|
Chris@330
|
260 if (outputs.size() == 1) {
|
Chris@330
|
261 userName = pluginName;
|
Chris@330
|
262 friendlyName = pluginName;
|
Chris@330
|
263 } else {
|
Chris@330
|
264 userName = QString("%1: %2")
|
Chris@330
|
265 .arg(pluginName)
|
Chris@330
|
266 .arg(outputs[j].name.c_str());
|
Chris@330
|
267 friendlyName = outputs[j].name.c_str();
|
Chris@330
|
268 }
|
Chris@330
|
269
|
Chris@330
|
270 bool configurable = (!plugin->getPrograms().empty() ||
|
Chris@330
|
271 !plugin->getParameterDescriptors().empty());
|
Chris@330
|
272
|
Chris@330
|
273 // std::cerr << "Feature extraction plugin transform: " << transformId.toStdString() << std::endl;
|
Chris@330
|
274
|
Chris@330
|
275 transforms[transformId] =
|
Chris@330
|
276 TransformDescription(tr("Analysis"),
|
Chris@330
|
277 category,
|
Chris@330
|
278 transformId,
|
Chris@330
|
279 userName,
|
Chris@330
|
280 friendlyName,
|
Chris@330
|
281 description,
|
Chris@330
|
282 maker,
|
Chris@330
|
283 units,
|
Chris@330
|
284 configurable);
|
Chris@330
|
285 }
|
Chris@330
|
286
|
Chris@330
|
287 delete plugin;
|
Chris@330
|
288 }
|
Chris@330
|
289 }
|
Chris@330
|
290
|
Chris@330
|
291 void
|
Chris@330
|
292 TransformFactory::populateRealTimePlugins(TransformDescriptionMap &transforms)
|
Chris@330
|
293 {
|
Chris@330
|
294 std::vector<QString> plugs =
|
Chris@330
|
295 RealTimePluginFactory::getAllPluginIdentifiers();
|
Chris@330
|
296
|
Chris@330
|
297 static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
|
Chris@330
|
298
|
Chris@330
|
299 for (size_t i = 0; i < plugs.size(); ++i) {
|
Chris@330
|
300
|
Chris@330
|
301 QString pluginId = plugs[i];
|
Chris@330
|
302
|
Chris@330
|
303 RealTimePluginFactory *factory =
|
Chris@330
|
304 RealTimePluginFactory::instanceFor(pluginId);
|
Chris@330
|
305
|
Chris@330
|
306 if (!factory) {
|
Chris@330
|
307 std::cerr << "WARNING: TransformFactory::populateTransforms: No real time plugin factory for instance " << pluginId.toLocal8Bit().data() << std::endl;
|
Chris@330
|
308 continue;
|
Chris@330
|
309 }
|
Chris@330
|
310
|
Chris@330
|
311 const RealTimePluginDescriptor *descriptor =
|
Chris@330
|
312 factory->getPluginDescriptor(pluginId);
|
Chris@330
|
313
|
Chris@330
|
314 if (!descriptor) {
|
Chris@330
|
315 std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to query plugin " << pluginId.toLocal8Bit().data() << std::endl;
|
Chris@330
|
316 continue;
|
Chris@330
|
317 }
|
Chris@330
|
318
|
Chris@330
|
319 //!!! if (descriptor->controlOutputPortCount == 0 ||
|
Chris@330
|
320 // descriptor->audioInputPortCount == 0) continue;
|
Chris@330
|
321
|
Chris@330
|
322 // std::cout << "TransformFactory::populateRealTimePlugins: plugin " << pluginId.toStdString() << " has " << descriptor->controlOutputPortCount << " control output ports, " << descriptor->audioOutputPortCount << " audio outputs, " << descriptor->audioInputPortCount << " audio inputs" << std::endl;
|
Chris@330
|
323
|
Chris@330
|
324 QString pluginName = descriptor->name.c_str();
|
Chris@330
|
325 QString category = factory->getPluginCategory(pluginId);
|
Chris@330
|
326 bool configurable = (descriptor->parameterCount > 0);
|
Chris@330
|
327 QString maker = descriptor->maker.c_str();
|
Chris@330
|
328 if (maker == "") maker = tr("<unknown maker>");
|
Chris@330
|
329
|
Chris@330
|
330 if (descriptor->audioInputPortCount > 0) {
|
Chris@330
|
331
|
Chris@330
|
332 for (size_t j = 0; j < descriptor->controlOutputPortCount; ++j) {
|
Chris@330
|
333
|
Chris@330
|
334 QString transformId = QString("%1:%2").arg(pluginId).arg(j);
|
Chris@330
|
335 QString userName;
|
Chris@330
|
336 QString units;
|
Chris@330
|
337 QString portName;
|
Chris@330
|
338
|
Chris@330
|
339 if (j < descriptor->controlOutputPortNames.size() &&
|
Chris@330
|
340 descriptor->controlOutputPortNames[j] != "") {
|
Chris@330
|
341
|
Chris@330
|
342 portName = descriptor->controlOutputPortNames[j].c_str();
|
Chris@330
|
343
|
Chris@330
|
344 userName = tr("%1: %2")
|
Chris@330
|
345 .arg(pluginName)
|
Chris@330
|
346 .arg(portName);
|
Chris@330
|
347
|
Chris@330
|
348 if (unitRE.indexIn(portName) >= 0) {
|
Chris@330
|
349 units = unitRE.cap(1);
|
Chris@330
|
350 }
|
Chris@330
|
351
|
Chris@330
|
352 } else if (descriptor->controlOutputPortCount > 1) {
|
Chris@330
|
353
|
Chris@330
|
354 userName = tr("%1: Output %2")
|
Chris@330
|
355 .arg(pluginName)
|
Chris@330
|
356 .arg(j + 1);
|
Chris@330
|
357
|
Chris@330
|
358 } else {
|
Chris@330
|
359
|
Chris@330
|
360 userName = pluginName;
|
Chris@330
|
361 }
|
Chris@330
|
362
|
Chris@330
|
363 QString description;
|
Chris@330
|
364
|
Chris@330
|
365 if (portName != "") {
|
Chris@330
|
366 description = tr("Extract \"%1\" data output from \"%2\" effect plugin (from %3)")
|
Chris@330
|
367 .arg(portName)
|
Chris@330
|
368 .arg(pluginName)
|
Chris@330
|
369 .arg(maker);
|
Chris@330
|
370 } else {
|
Chris@330
|
371 description = tr("Extract data output %1 from \"%2\" effect plugin (from %3)")
|
Chris@330
|
372 .arg(j + 1)
|
Chris@330
|
373 .arg(pluginName)
|
Chris@330
|
374 .arg(maker);
|
Chris@330
|
375 }
|
Chris@330
|
376
|
Chris@330
|
377 transforms[transformId] =
|
Chris@330
|
378 TransformDescription(tr("Effects Data"),
|
Chris@330
|
379 category,
|
Chris@330
|
380 transformId,
|
Chris@330
|
381 userName,
|
Chris@330
|
382 userName,
|
Chris@330
|
383 description,
|
Chris@330
|
384 maker,
|
Chris@330
|
385 units,
|
Chris@330
|
386 configurable);
|
Chris@330
|
387 }
|
Chris@330
|
388 }
|
Chris@330
|
389
|
Chris@330
|
390 if (!descriptor->isSynth || descriptor->audioInputPortCount > 0) {
|
Chris@330
|
391
|
Chris@330
|
392 if (descriptor->audioOutputPortCount > 0) {
|
Chris@330
|
393
|
Chris@330
|
394 QString transformId = QString("%1:A").arg(pluginId);
|
Chris@330
|
395 QString type = tr("Effects");
|
Chris@330
|
396
|
Chris@330
|
397 QString description = tr("Transform audio signal with \"%1\" effect plugin (from %2)")
|
Chris@330
|
398 .arg(pluginName)
|
Chris@330
|
399 .arg(maker);
|
Chris@330
|
400
|
Chris@330
|
401 if (descriptor->audioInputPortCount == 0) {
|
Chris@330
|
402 type = tr("Generators");
|
Chris@330
|
403 QString description = tr("Generate audio signal using \"%1\" plugin (from %2)")
|
Chris@330
|
404 .arg(pluginName)
|
Chris@330
|
405 .arg(maker);
|
Chris@330
|
406 }
|
Chris@330
|
407
|
Chris@330
|
408 transforms[transformId] =
|
Chris@330
|
409 TransformDescription(type,
|
Chris@330
|
410 category,
|
Chris@330
|
411 transformId,
|
Chris@330
|
412 pluginName,
|
Chris@330
|
413 pluginName,
|
Chris@330
|
414 description,
|
Chris@330
|
415 maker,
|
Chris@330
|
416 "",
|
Chris@330
|
417 configurable);
|
Chris@330
|
418 }
|
Chris@330
|
419 }
|
Chris@330
|
420 }
|
Chris@330
|
421 }
|
Chris@330
|
422
|
Chris@330
|
423 bool
|
Chris@330
|
424 TransformFactory::haveTransform(TransformId identifier)
|
Chris@330
|
425 {
|
Chris@330
|
426 return (m_transforms.find(identifier) != m_transforms.end());
|
Chris@330
|
427 }
|
Chris@330
|
428
|
Chris@330
|
429 QString
|
Chris@330
|
430 TransformFactory::getTransformName(TransformId identifier)
|
Chris@330
|
431 {
|
Chris@330
|
432 if (m_transforms.find(identifier) != m_transforms.end()) {
|
Chris@330
|
433 return m_transforms[identifier].name;
|
Chris@330
|
434 } else return "";
|
Chris@330
|
435 }
|
Chris@330
|
436
|
Chris@330
|
437 QString
|
Chris@330
|
438 TransformFactory::getTransformFriendlyName(TransformId identifier)
|
Chris@330
|
439 {
|
Chris@330
|
440 if (m_transforms.find(identifier) != m_transforms.end()) {
|
Chris@330
|
441 return m_transforms[identifier].friendlyName;
|
Chris@330
|
442 } else return "";
|
Chris@330
|
443 }
|
Chris@330
|
444
|
Chris@330
|
445 QString
|
Chris@330
|
446 TransformFactory::getTransformUnits(TransformId identifier)
|
Chris@330
|
447 {
|
Chris@330
|
448 if (m_transforms.find(identifier) != m_transforms.end()) {
|
Chris@330
|
449 return m_transforms[identifier].units;
|
Chris@330
|
450 } else return "";
|
Chris@330
|
451 }
|
Chris@330
|
452
|
Chris@330
|
453 bool
|
Chris@330
|
454 TransformFactory::isTransformConfigurable(TransformId identifier)
|
Chris@330
|
455 {
|
Chris@330
|
456 if (m_transforms.find(identifier) != m_transforms.end()) {
|
Chris@330
|
457 return m_transforms[identifier].configurable;
|
Chris@330
|
458 } else return false;
|
Chris@330
|
459 }
|
Chris@330
|
460
|
Chris@330
|
461 bool
|
Chris@330
|
462 TransformFactory::getTransformChannelRange(TransformId identifier,
|
Chris@330
|
463 int &min, int &max)
|
Chris@330
|
464 {
|
Chris@330
|
465 QString id = identifier.section(':', 0, 2);
|
Chris@330
|
466
|
Chris@330
|
467 if (FeatureExtractionPluginFactory::instanceFor(id)) {
|
Chris@330
|
468
|
Chris@330
|
469 Vamp::Plugin *plugin =
|
Chris@330
|
470 FeatureExtractionPluginFactory::instanceFor(id)->
|
Chris@330
|
471 instantiatePlugin(id, 48000);
|
Chris@330
|
472 if (!plugin) return false;
|
Chris@330
|
473
|
Chris@330
|
474 min = plugin->getMinChannelCount();
|
Chris@330
|
475 max = plugin->getMaxChannelCount();
|
Chris@330
|
476 delete plugin;
|
Chris@330
|
477
|
Chris@330
|
478 return true;
|
Chris@330
|
479
|
Chris@330
|
480 } else if (RealTimePluginFactory::instanceFor(id)) {
|
Chris@330
|
481
|
Chris@330
|
482 const RealTimePluginDescriptor *descriptor =
|
Chris@330
|
483 RealTimePluginFactory::instanceFor(id)->
|
Chris@330
|
484 getPluginDescriptor(id);
|
Chris@330
|
485 if (!descriptor) return false;
|
Chris@330
|
486
|
Chris@330
|
487 min = descriptor->audioInputPortCount;
|
Chris@330
|
488 max = descriptor->audioInputPortCount;
|
Chris@330
|
489
|
Chris@330
|
490 return true;
|
Chris@330
|
491 }
|
Chris@330
|
492
|
Chris@330
|
493 return false;
|
Chris@330
|
494 }
|