annotate transform/ModelTransformerFactory.cpp @ 661:a4faa1840384

* If a FileSource URL won't convert at all in strict mode, try again in tolerant mode (necessary for e.g. filenames with square brackets in them)
author Chris Cannam
date Tue, 19 Oct 2010 21:47:55 +0100
parents 12578237b99c
children b4a8d8221eaf
rev   line source
Chris@320 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@320 2
Chris@320 3 /*
Chris@320 4 Sonic Visualiser
Chris@320 5 An audio file viewer and annotation editor.
Chris@320 6 Centre for Digital Music, Queen Mary, University of London.
Chris@320 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@320 8
Chris@320 9 This program is free software; you can redistribute it and/or
Chris@320 10 modify it under the terms of the GNU General Public License as
Chris@320 11 published by the Free Software Foundation; either version 2 of the
Chris@320 12 License, or (at your option) any later version. See the file
Chris@320 13 COPYING included with this distribution for more information.
Chris@320 14 */
Chris@320 15
Chris@331 16 #include "ModelTransformerFactory.h"
Chris@320 17
Chris@331 18 #include "FeatureExtractionModelTransformer.h"
Chris@331 19 #include "RealTimeEffectModelTransformer.h"
Chris@320 20
Chris@332 21 #include "TransformFactory.h"
Chris@332 22
Chris@389 23 #include "base/AudioPlaySource.h"
Chris@389 24
Chris@320 25 #include "plugin/FeatureExtractionPluginFactory.h"
Chris@320 26 #include "plugin/RealTimePluginFactory.h"
Chris@320 27 #include "plugin/PluginXml.h"
Chris@320 28
Chris@320 29 #include "data/model/DenseTimeValueModel.h"
Chris@320 30
Chris@475 31 #include <vamp-hostsdk/PluginHostAdapter.h>
Chris@320 32
Chris@320 33 #include <iostream>
Chris@320 34 #include <set>
Chris@320 35
Chris@320 36 #include <QRegExp>
Chris@320 37
Chris@331 38 ModelTransformerFactory *
Chris@331 39 ModelTransformerFactory::m_instance = new ModelTransformerFactory;
Chris@320 40
Chris@331 41 ModelTransformerFactory *
Chris@331 42 ModelTransformerFactory::getInstance()
Chris@320 43 {
Chris@320 44 return m_instance;
Chris@320 45 }
Chris@320 46
Chris@331 47 ModelTransformerFactory::~ModelTransformerFactory()
Chris@320 48 {
Chris@320 49 }
Chris@320 50
Chris@350 51 ModelTransformer::Input
Chris@350 52 ModelTransformerFactory::getConfigurationForTransform(Transform &transform,
Chris@350 53 const std::vector<Model *> &candidateInputModels,
Chris@350 54 Model *defaultInputModel,
Chris@389 55 AudioPlaySource *source,
Chris@350 56 size_t startFrame,
Chris@653 57 size_t duration,
Chris@653 58 UserConfigurator *configurator)
Chris@320 59 {
Chris@350 60 ModelTransformer::Input input(0);
Chris@350 61
Chris@350 62 if (candidateInputModels.empty()) return input;
Chris@320 63
Chris@320 64 //!!! This will need revision -- we'll have to have a callback
Chris@320 65 //from the dialog for when the candidate input model is changed,
Chris@320 66 //as we'll need to reinitialise the channel settings in the dialog
Chris@345 67 Model *inputModel = candidateInputModels[0];
Chris@320 68 QStringList candidateModelNames;
Chris@345 69 QString defaultModelName;
Chris@653 70 QMap<QString, Model *> modelMap;
Chris@320 71 for (size_t i = 0; i < candidateInputModels.size(); ++i) {
Chris@320 72 QString modelName = candidateInputModels[i]->objectName();
Chris@320 73 QString origModelName = modelName;
Chris@320 74 int dupcount = 1;
Chris@653 75 while (modelMap.contains(modelName)) {
Chris@320 76 modelName = tr("%1 <%2>").arg(origModelName).arg(++dupcount);
Chris@320 77 }
Chris@320 78 modelMap[modelName] = candidateInputModels[i];
Chris@320 79 candidateModelNames.push_back(modelName);
Chris@345 80 if (candidateInputModels[i] == defaultInputModel) {
Chris@345 81 defaultModelName = modelName;
Chris@345 82 }
Chris@320 83 }
Chris@320 84
Chris@350 85 QString id = transform.getPluginIdentifier();
Chris@320 86
Chris@653 87 bool ok = true;
Chris@350 88 QString configurationXml = m_lastConfigurations[transform.getIdentifier()];
Chris@320 89
Chris@350 90 std::cerr << "last configuration: " << configurationXml.toStdString() << std::endl;
Chris@320 91
Chris@320 92 Vamp::PluginBase *plugin = 0;
Chris@320 93
Chris@320 94 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@320 95
Chris@350 96 std::cerr << "getConfigurationForTransform: instantiating Vamp plugin" << std::endl;
Chris@320 97
Chris@320 98 Vamp::Plugin *vp =
Chris@320 99 FeatureExtractionPluginFactory::instanceFor(id)->instantiatePlugin
Chris@320 100 (id, inputModel->getSampleRate());
Chris@320 101
Chris@653 102 plugin = vp;
Chris@320 103
Chris@320 104 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@320 105
Chris@320 106 RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id);
Chris@320 107 const RealTimePluginDescriptor *desc = factory->getPluginDescriptor(id);
Chris@320 108
Chris@320 109 size_t sampleRate = inputModel->getSampleRate();
Chris@320 110 size_t blockSize = 1024;
Chris@320 111 size_t channels = 1;
Chris@653 112 if (source) {
Chris@320 113 sampleRate = source->getTargetSampleRate();
Chris@320 114 blockSize = source->getTargetBlockSize();
Chris@320 115 channels = source->getTargetChannelCount();
Chris@320 116 }
Chris@320 117
Chris@320 118 RealTimePluginInstance *rtp = factory->instantiatePlugin
Chris@320 119 (id, 0, 0, sampleRate, blockSize, channels);
Chris@320 120
Chris@320 121 plugin = rtp;
Chris@320 122 }
Chris@320 123
Chris@320 124 if (plugin) {
Chris@320 125
Chris@350 126 // Ensure block size etc are valid
Chris@350 127 TransformFactory::getInstance()->
Chris@350 128 makeContextConsistentWithPlugin(transform, plugin);
Chris@320 129
Chris@350 130 // Prepare the plugin with any existing parameters already
Chris@350 131 // found in the transform
Chris@350 132 TransformFactory::getInstance()->
Chris@350 133 setPluginParameters(transform, plugin);
Chris@350 134
Chris@350 135 // For this interactive usage, we want to override those with
Chris@350 136 // whatever the user chose last time around
Chris@350 137 PluginXml(plugin).setParametersFromXml(configurationXml);
Chris@320 138
Chris@653 139 if (configurator) {
Chris@653 140 ok = configurator->configure(input, transform, plugin,
Chris@653 141 inputModel, source,
Chris@653 142 startFrame, duration,
Chris@653 143 modelMap,
Chris@653 144 candidateModelNames,
Chris@653 145 defaultModelName);
Chris@320 146 }
Chris@320 147
Chris@516 148
Chris@350 149 TransformFactory::getInstance()->
Chris@350 150 makeContextConsistentWithPlugin(transform, plugin);
Chris@350 151
Chris@350 152 configurationXml = PluginXml(plugin).toXmlString();
Chris@320 153
Chris@653 154 delete plugin;
Chris@320 155 }
Chris@320 156
Chris@350 157 if (ok) {
Chris@350 158 m_lastConfigurations[transform.getIdentifier()] = configurationXml;
Chris@350 159 input.setModel(inputModel);
Chris@350 160 }
Chris@320 161
Chris@350 162 return input;
Chris@320 163 }
Chris@320 164
Chris@331 165 ModelTransformer *
Chris@350 166 ModelTransformerFactory::createTransformer(const Transform &transform,
Chris@350 167 const ModelTransformer::Input &input)
Chris@320 168 {
Chris@331 169 ModelTransformer *transformer = 0;
Chris@320 170
Chris@350 171 QString id = transform.getPluginIdentifier();
Chris@320 172
Chris@320 173 if (FeatureExtractionPluginFactory::instanceFor(id)) {
Chris@350 174
Chris@350 175 transformer =
Chris@350 176 new FeatureExtractionModelTransformer(input, transform);
Chris@350 177
Chris@331 178 } else if (RealTimePluginFactory::instanceFor(id)) {
Chris@350 179
Chris@350 180 transformer =
Chris@350 181 new RealTimeEffectModelTransformer(input, transform);
Chris@350 182
Chris@320 183 } else {
Chris@331 184 std::cerr << "ModelTransformerFactory::createTransformer: Unknown transform \""
Chris@350 185 << transform.getIdentifier().toStdString() << "\"" << std::endl;
Chris@331 186 return transformer;
Chris@320 187 }
Chris@320 188
Chris@350 189 if (transformer) transformer->setObjectName(transform.getIdentifier());
Chris@331 190 return transformer;
Chris@320 191 }
Chris@320 192
Chris@320 193 Model *
Chris@350 194 ModelTransformerFactory::transform(const Transform &transform,
Chris@361 195 const ModelTransformer::Input &input,
Chris@361 196 QString &message)
Chris@320 197 {
Chris@408 198 std::cerr << "ModelTransformerFactory::transform: Constructing transformer with input model " << input.getModel() << std::endl;
Chris@408 199
Chris@350 200 ModelTransformer *t = createTransformer(transform, input);
Chris@320 201 if (!t) return 0;
Chris@320 202
Chris@331 203 connect(t, SIGNAL(finished()), this, SLOT(transformerFinished()));
Chris@320 204
Chris@328 205 m_runningTransformers.insert(t);
Chris@320 206
Chris@320 207 t->start();
Chris@320 208 Model *model = t->detachOutputModel();
Chris@320 209
Chris@320 210 if (model) {
Chris@350 211 QString imn = input.getModel()->objectName();
Chris@332 212 QString trn =
Chris@332 213 TransformFactory::getInstance()->getTransformFriendlyName
Chris@350 214 (transform.getIdentifier());
Chris@320 215 if (imn != "") {
Chris@320 216 if (trn != "") {
Chris@320 217 model->setObjectName(tr("%1: %2").arg(imn).arg(trn));
Chris@320 218 } else {
Chris@320 219 model->setObjectName(imn);
Chris@320 220 }
Chris@320 221 } else if (trn != "") {
Chris@320 222 model->setObjectName(trn);
Chris@320 223 }
Chris@320 224 } else {
Chris@320 225 t->wait();
Chris@320 226 }
Chris@320 227
Chris@361 228 message = t->getMessage();
Chris@361 229
Chris@320 230 return model;
Chris@320 231 }
Chris@320 232
Chris@320 233 void
Chris@331 234 ModelTransformerFactory::transformerFinished()
Chris@320 235 {
Chris@320 236 QObject *s = sender();
Chris@331 237 ModelTransformer *transformer = dynamic_cast<ModelTransformer *>(s);
Chris@320 238
Chris@436 239 // std::cerr << "ModelTransformerFactory::transformerFinished(" << transformer << ")" << std::endl;
Chris@320 240
Chris@331 241 if (!transformer) {
Chris@331 242 std::cerr << "WARNING: ModelTransformerFactory::transformerFinished: sender is not a transformer" << std::endl;
Chris@320 243 return;
Chris@320 244 }
Chris@320 245
Chris@331 246 if (m_runningTransformers.find(transformer) == m_runningTransformers.end()) {
Chris@331 247 std::cerr << "WARNING: ModelTransformerFactory::transformerFinished("
Chris@331 248 << transformer
Chris@331 249 << "): I have no record of this transformer running!"
Chris@320 250 << std::endl;
Chris@320 251 }
Chris@320 252
Chris@331 253 m_runningTransformers.erase(transformer);
Chris@320 254
Chris@331 255 transformer->wait(); // unnecessary but reassuring
Chris@331 256 delete transformer;
Chris@320 257 }
Chris@320 258
Chris@320 259 void
Chris@331 260 ModelTransformerFactory::modelAboutToBeDeleted(Model *m)
Chris@320 261 {
Chris@328 262 TransformerSet affected;
Chris@320 263
Chris@328 264 for (TransformerSet::iterator i = m_runningTransformers.begin();
Chris@328 265 i != m_runningTransformers.end(); ++i) {
Chris@320 266
Chris@331 267 ModelTransformer *t = *i;
Chris@320 268
Chris@320 269 if (t->getInputModel() == m || t->getOutputModel() == m) {
Chris@320 270 affected.insert(t);
Chris@320 271 }
Chris@320 272 }
Chris@320 273
Chris@328 274 for (TransformerSet::iterator i = affected.begin();
Chris@320 275 i != affected.end(); ++i) {
Chris@320 276
Chris@331 277 ModelTransformer *t = *i;
Chris@320 278
Chris@320 279 t->abandon();
Chris@320 280
Chris@320 281 t->wait(); // this should eventually call back on
Chris@331 282 // transformerFinished, which will remove from
Chris@328 283 // m_runningTransformers and delete.
Chris@320 284 }
Chris@320 285 }
Chris@320 286