svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006 Chris Cannam and QMUL. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "ModelTransformerFactory.h" 00017 00018 #include "FeatureExtractionModelTransformer.h" 00019 #include "RealTimeEffectModelTransformer.h" 00020 00021 #include "TransformFactory.h" 00022 00023 #include "base/AudioPlaySource.h" 00024 00025 #include "plugin/FeatureExtractionPluginFactory.h" 00026 #include "plugin/RealTimePluginFactory.h" 00027 #include "plugin/PluginXml.h" 00028 00029 #include "data/model/DenseTimeValueModel.h" 00030 00031 #include <vamp-hostsdk/PluginHostAdapter.h> 00032 00033 #include <iostream> 00034 #include <set> 00035 00036 #include <QRegExp> 00037 00038 using std::vector; 00039 00040 ModelTransformerFactory * 00041 ModelTransformerFactory::m_instance = new ModelTransformerFactory; 00042 00043 ModelTransformerFactory * 00044 ModelTransformerFactory::getInstance() 00045 { 00046 return m_instance; 00047 } 00048 00049 ModelTransformerFactory::~ModelTransformerFactory() 00050 { 00051 } 00052 00053 ModelTransformer::Input 00054 ModelTransformerFactory::getConfigurationForTransform(Transform &transform, 00055 const std::vector<Model *> &candidateInputModels, 00056 Model *defaultInputModel, 00057 AudioPlaySource *source, 00058 int startFrame, 00059 int duration, 00060 UserConfigurator *configurator) 00061 { 00062 ModelTransformer::Input input(0); 00063 00064 if (candidateInputModels.empty()) return input; 00065 00067 //from the dialog for when the candidate input model is changed, 00068 //as we'll need to reinitialise the channel settings in the dialog 00069 Model *inputModel = candidateInputModels[0]; 00070 QStringList candidateModelNames; 00071 QString defaultModelName; 00072 QMap<QString, Model *> modelMap; 00073 for (int i = 0; i < (int)candidateInputModels.size(); ++i) { 00074 QString modelName = candidateInputModels[i]->objectName(); 00075 QString origModelName = modelName; 00076 int dupcount = 1; 00077 while (modelMap.contains(modelName)) { 00078 modelName = tr("%1 <%2>").arg(origModelName).arg(++dupcount); 00079 } 00080 modelMap[modelName] = candidateInputModels[i]; 00081 candidateModelNames.push_back(modelName); 00082 if (candidateInputModels[i] == defaultInputModel) { 00083 defaultModelName = modelName; 00084 } 00085 } 00086 00087 QString id = transform.getPluginIdentifier(); 00088 00089 bool ok = true; 00090 QString configurationXml = m_lastConfigurations[transform.getIdentifier()]; 00091 00092 cerr << "last configuration: " << configurationXml << endl; 00093 00094 Vamp::PluginBase *plugin = 0; 00095 00096 if (FeatureExtractionPluginFactory::instanceFor(id)) { 00097 00098 cerr << "getConfigurationForTransform: instantiating Vamp plugin" << endl; 00099 00100 Vamp::Plugin *vp = 00101 FeatureExtractionPluginFactory::instanceFor(id)->instantiatePlugin 00102 (id, inputModel->getSampleRate()); 00103 00104 plugin = vp; 00105 00106 } else if (RealTimePluginFactory::instanceFor(id)) { 00107 00108 RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id); 00109 00110 int sampleRate = inputModel->getSampleRate(); 00111 int blockSize = 1024; 00112 int channels = 1; 00113 if (source) { 00114 sampleRate = source->getTargetSampleRate(); 00115 blockSize = source->getTargetBlockSize(); 00116 channels = source->getTargetChannelCount(); 00117 } 00118 00119 RealTimePluginInstance *rtp = factory->instantiatePlugin 00120 (id, 0, 0, sampleRate, blockSize, channels); 00121 00122 plugin = rtp; 00123 } 00124 00125 if (plugin) { 00126 00127 // Ensure block size etc are valid 00128 TransformFactory::getInstance()-> 00129 makeContextConsistentWithPlugin(transform, plugin); 00130 00131 // Prepare the plugin with any existing parameters already 00132 // found in the transform 00133 TransformFactory::getInstance()-> 00134 setPluginParameters(transform, plugin); 00135 00136 // For this interactive usage, we want to override those with 00137 // whatever the user chose last time around 00138 PluginXml(plugin).setParametersFromXml(configurationXml); 00139 00140 if (configurator) { 00141 ok = configurator->configure(input, transform, plugin, 00142 inputModel, source, 00143 startFrame, duration, 00144 modelMap, 00145 candidateModelNames, 00146 defaultModelName); 00147 } 00148 00149 00150 TransformFactory::getInstance()-> 00151 makeContextConsistentWithPlugin(transform, plugin); 00152 00153 configurationXml = PluginXml(plugin).toXmlString(); 00154 00155 delete plugin; 00156 } 00157 00158 if (ok) { 00159 m_lastConfigurations[transform.getIdentifier()] = configurationXml; 00160 input.setModel(inputModel); 00161 } 00162 00163 return input; 00164 } 00165 00166 ModelTransformer * 00167 ModelTransformerFactory::createTransformer(const Transforms &transforms, 00168 const ModelTransformer::Input &input) 00169 { 00170 ModelTransformer *transformer = 0; 00171 00172 QString id = transforms[0].getPluginIdentifier(); 00173 00174 if (FeatureExtractionPluginFactory::instanceFor(id)) { 00175 00176 transformer = 00177 new FeatureExtractionModelTransformer(input, transforms); 00178 00179 } else if (RealTimePluginFactory::instanceFor(id)) { 00180 00181 transformer = 00182 new RealTimeEffectModelTransformer(input, transforms[0]); 00183 00184 } else { 00185 SVDEBUG << "ModelTransformerFactory::createTransformer: Unknown transform \"" 00186 << transforms[0].getIdentifier() << "\"" << endl; 00187 return transformer; 00188 } 00189 00190 if (transformer) transformer->setObjectName(transforms[0].getIdentifier()); 00191 return transformer; 00192 } 00193 00194 Model * 00195 ModelTransformerFactory::transform(const Transform &transform, 00196 const ModelTransformer::Input &input, 00197 QString &message, 00198 AdditionalModelHandler *handler) 00199 { 00200 SVDEBUG << "ModelTransformerFactory::transform: Constructing transformer with input model " << input.getModel() << endl; 00201 00202 Transforms transforms; 00203 transforms.push_back(transform); 00204 vector<Model *> mm = transformMultiple(transforms, input, message, handler); 00205 if (mm.empty()) return 0; 00206 else return mm[0]; 00207 } 00208 00209 vector<Model *> 00210 ModelTransformerFactory::transformMultiple(const Transforms &transforms, 00211 const ModelTransformer::Input &input, 00212 QString &message, 00213 AdditionalModelHandler *handler) 00214 { 00215 SVDEBUG << "ModelTransformerFactory::transformMultiple: Constructing transformer with input model " << input.getModel() << endl; 00216 00217 ModelTransformer *t = createTransformer(transforms, input); 00218 if (!t) return vector<Model *>(); 00219 00220 if (handler) { 00221 m_handlers[t] = handler; 00222 } 00223 00224 m_runningTransformers.insert(t); 00225 00226 connect(t, SIGNAL(finished()), this, SLOT(transformerFinished())); 00227 00228 t->start(); 00229 vector<Model *> models = t->detachOutputModels(); 00230 00231 if (!models.empty()) { 00232 QString imn = input.getModel()->objectName(); 00233 QString trn = 00234 TransformFactory::getInstance()->getTransformFriendlyName 00235 (transforms[0].getIdentifier()); 00236 for (int i = 0; i < (int)models.size(); ++i) { 00237 if (imn != "") { 00238 if (trn != "") { 00239 models[i]->setObjectName(tr("%1: %2").arg(imn).arg(trn)); 00240 } else { 00241 models[i]->setObjectName(imn); 00242 } 00243 } else if (trn != "") { 00244 models[i]->setObjectName(trn); 00245 } 00246 } 00247 } else { 00248 t->wait(); 00249 } 00250 00251 message = t->getMessage(); 00252 00253 return models; 00254 } 00255 00256 void 00257 ModelTransformerFactory::transformerFinished() 00258 { 00259 QObject *s = sender(); 00260 ModelTransformer *transformer = dynamic_cast<ModelTransformer *>(s); 00261 00262 // SVDEBUG << "ModelTransformerFactory::transformerFinished(" << transformer << ")" << endl; 00263 00264 if (!transformer) { 00265 cerr << "WARNING: ModelTransformerFactory::transformerFinished: sender is not a transformer" << endl; 00266 return; 00267 } 00268 00269 if (m_runningTransformers.find(transformer) == m_runningTransformers.end()) { 00270 cerr << "WARNING: ModelTransformerFactory::transformerFinished(" 00271 << transformer 00272 << "): I have no record of this transformer running!" 00273 << endl; 00274 } 00275 00276 m_runningTransformers.erase(transformer); 00277 00278 if (m_handlers.find(transformer) != m_handlers.end()) { 00279 if (transformer->willHaveAdditionalOutputModels()) { 00280 vector<Model *> mm = transformer->detachAdditionalOutputModels(); 00281 m_handlers[transformer]->moreModelsAvailable(mm); 00282 } else { 00283 m_handlers[transformer]->noMoreModelsAvailable(); 00284 } 00285 m_handlers.erase(transformer); 00286 } 00287 00288 transformer->wait(); // unnecessary but reassuring 00289 delete transformer; 00290 } 00291 00292 void 00293 ModelTransformerFactory::modelAboutToBeDeleted(Model *m) 00294 { 00295 TransformerSet affected; 00296 00297 for (TransformerSet::iterator i = m_runningTransformers.begin(); 00298 i != m_runningTransformers.end(); ++i) { 00299 00300 ModelTransformer *t = *i; 00301 00302 if (t->getInputModel() == m) { 00303 affected.insert(t); 00304 } else { 00305 vector<Model *> mm = t->getOutputModels(); 00306 for (int i = 0; i < (int)mm.size(); ++i) { 00307 if (mm[i] == m) affected.insert(t); 00308 } 00309 } 00310 } 00311 00312 for (TransformerSet::iterator i = affected.begin(); 00313 i != affected.end(); ++i) { 00314 00315 ModelTransformer *t = *i; 00316 00317 t->abandon(); 00318 00319 t->wait(); // this should eventually call back on 00320 // transformerFinished, which will remove from 00321 // m_runningTransformers and delete. 00322 } 00323 } 00324