Mercurial > hg > svcore
comparison transform/ModelTransformerFactory.cpp @ 1740:fe3f7f8df3a3 by-id
More work on transformers
| author | Chris Cannam |
|---|---|
| date | Wed, 26 Jun 2019 17:25:20 +0100 |
| parents | 8efce64dd85e |
| children | 5f8fbbde08ff |
comparison
equal
deleted
inserted
replaced
| 1739:565575463752 | 1740:fe3f7f8df3a3 |
|---|---|
| 54 { | 54 { |
| 55 } | 55 } |
| 56 | 56 |
| 57 ModelTransformer::Input | 57 ModelTransformer::Input |
| 58 ModelTransformerFactory::getConfigurationForTransform(Transform &transform, | 58 ModelTransformerFactory::getConfigurationForTransform(Transform &transform, |
| 59 const vector<Model *> &candidateInputModels, | 59 vector<ModelId> candidateInputModels, |
| 60 Model *defaultInputModel, | 60 ModelId defaultInputModel, |
| 61 AudioPlaySource *source, | 61 AudioPlaySource *source, |
| 62 sv_frame_t startFrame, | 62 sv_frame_t startFrame, |
| 63 sv_frame_t duration, | 63 sv_frame_t duration, |
| 64 UserConfigurator *configurator) | 64 UserConfigurator *configurator) |
| 65 { | 65 { |
| 66 QMutexLocker locker(&m_mutex); | 66 QMutexLocker locker(&m_mutex); |
| 67 | 67 |
| 68 ModelTransformer::Input input(nullptr); | 68 ModelTransformer::Input input({}); |
| 69 | 69 |
| 70 if (candidateInputModels.empty()) return input; | 70 if (candidateInputModels.empty()) return input; |
| 71 | 71 |
| 72 //!!! This will need revision -- we'll have to have a callback | 72 //!!! This will need revision -- we'll have to have a callback |
| 73 //from the dialog for when the candidate input model is changed, | 73 //from the dialog for when the candidate input model is changed, |
| 74 //as we'll need to reinitialise the channel settings in the dialog | 74 //as we'll need to reinitialise the channel settings in the dialog |
| 75 Model *inputModel = candidateInputModels[0]; | 75 ModelId inputModel = candidateInputModels[0]; |
| 76 QStringList candidateModelNames; | 76 QStringList candidateModelNames; |
| 77 QString defaultModelName; | 77 QString defaultModelName; |
| 78 QMap<QString, Model *> modelMap; | 78 QMap<QString, ModelId> modelMap; |
| 79 for (int i = 0; i < (int)candidateInputModels.size(); ++i) { | 79 |
| 80 QString modelName = candidateInputModels[i]->objectName(); | 80 sv_samplerate_t defaultSampleRate; |
| 81 { auto im = ModelById::get(inputModel); | |
| 82 if (!im) return input; | |
| 83 defaultSampleRate = im->getSampleRate(); | |
| 84 } | |
| 85 | |
| 86 for (int i = 0; in_range_for(candidateInputModels, i); ++i) { | |
| 87 | |
| 88 auto model = ModelById::get(candidateInputModels[i]); | |
| 89 if (!model) return input; | |
| 90 | |
| 91 QString modelName = model->objectName(); | |
| 81 QString origModelName = modelName; | 92 QString origModelName = modelName; |
| 82 int dupcount = 1; | 93 int dupcount = 1; |
| 83 while (modelMap.contains(modelName)) { | 94 while (modelMap.contains(modelName)) { |
| 84 modelName = tr("%1 <%2>").arg(origModelName).arg(++dupcount); | 95 modelName = tr("%1 <%2>").arg(origModelName).arg(++dupcount); |
| 85 } | 96 } |
| 97 | |
| 86 modelMap[modelName] = candidateInputModels[i]; | 98 modelMap[modelName] = candidateInputModels[i]; |
| 87 candidateModelNames.push_back(modelName); | 99 candidateModelNames.push_back(modelName); |
| 100 | |
| 88 if (candidateInputModels[i] == defaultInputModel) { | 101 if (candidateInputModels[i] == defaultInputModel) { |
| 89 defaultModelName = modelName; | 102 defaultModelName = modelName; |
| 90 } | 103 } |
| 91 } | 104 } |
| 92 | 105 |
| 103 | 116 |
| 104 SVDEBUG << "ModelTransformerFactory::getConfigurationForTransform: instantiating real-time plugin" << endl; | 117 SVDEBUG << "ModelTransformerFactory::getConfigurationForTransform: instantiating real-time plugin" << endl; |
| 105 | 118 |
| 106 RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id); | 119 RealTimePluginFactory *factory = RealTimePluginFactory::instanceFor(id); |
| 107 | 120 |
| 108 sv_samplerate_t sampleRate = inputModel->getSampleRate(); | 121 sv_samplerate_t sampleRate = defaultSampleRate; |
| 109 int blockSize = 1024; | 122 int blockSize = 1024; |
| 110 int channels = 1; | 123 int channels = 1; |
| 111 if (source) { | 124 if (source) { |
| 112 sampleRate = source->getSourceSampleRate(); | 125 sampleRate = source->getSourceSampleRate(); |
| 113 blockSize = source->getTargetBlockSize(); | 126 blockSize = source->getTargetBlockSize(); |
| 123 | 136 |
| 124 SVDEBUG << "ModelTransformerFactory::getConfigurationForTransform: instantiating Vamp plugin" << endl; | 137 SVDEBUG << "ModelTransformerFactory::getConfigurationForTransform: instantiating Vamp plugin" << endl; |
| 125 | 138 |
| 126 Vamp::Plugin *vp = | 139 Vamp::Plugin *vp = |
| 127 FeatureExtractionPluginFactory::instance()->instantiatePlugin | 140 FeatureExtractionPluginFactory::instance()->instantiatePlugin |
| 128 (id, float(inputModel->getSampleRate())); | 141 (id, float(defaultSampleRate)); |
| 129 | 142 |
| 130 plugin = vp; | 143 plugin = vp; |
| 131 } | 144 } |
| 132 | 145 |
| 133 if (plugin) { | 146 if (plugin) { |
| 194 | 207 |
| 195 if (transformer) transformer->setObjectName(transforms[0].getIdentifier()); | 208 if (transformer) transformer->setObjectName(transforms[0].getIdentifier()); |
| 196 return transformer; | 209 return transformer; |
| 197 } | 210 } |
| 198 | 211 |
| 199 Model * | 212 ModelId |
| 200 ModelTransformerFactory::transform(const Transform &transform, | 213 ModelTransformerFactory::transform(const Transform &transform, |
| 201 const ModelTransformer::Input &input, | 214 const ModelTransformer::Input &input, |
| 202 QString &message, | 215 QString &message, |
| 203 AdditionalModelHandler *handler) | 216 AdditionalModelHandler *handler) |
| 204 { | 217 { |
| 205 SVDEBUG << "ModelTransformerFactory::transform: Constructing transformer with input model " << input.getModel() << endl; | 218 SVDEBUG << "ModelTransformerFactory::transform: Constructing transformer with input model " << input.getModel() << endl; |
| 206 | 219 |
| 207 Transforms transforms; | 220 Transforms transforms; |
| 208 transforms.push_back(transform); | 221 transforms.push_back(transform); |
| 209 vector<Model *> mm = transformMultiple(transforms, input, message, handler); | 222 vector<ModelId> mm = transformMultiple(transforms, input, message, handler); |
| 210 if (mm.empty()) return nullptr; | 223 if (mm.empty()) return {}; |
| 211 else return mm[0]; | 224 else return mm[0]; |
| 212 } | 225 } |
| 213 | 226 |
| 214 vector<Model *> | 227 vector<ModelId> |
| 215 ModelTransformerFactory::transformMultiple(const Transforms &transforms, | 228 ModelTransformerFactory::transformMultiple(const Transforms &transforms, |
| 216 const ModelTransformer::Input &input, | 229 const ModelTransformer::Input &input, |
| 217 QString &message, | 230 QString &message, |
| 218 AdditionalModelHandler *handler) | 231 AdditionalModelHandler *handler) |
| 219 { | 232 { |
| 220 SVDEBUG << "ModelTransformerFactory::transformMultiple: Constructing transformer with input model " << input.getModel() << endl; | 233 SVDEBUG << "ModelTransformerFactory::transformMultiple: Constructing transformer with input model " << input.getModel() << endl; |
| 221 | 234 |
| 222 QMutexLocker locker(&m_mutex); | 235 QMutexLocker locker(&m_mutex); |
| 236 | |
| 237 auto inputModel = ModelById::get(input.getModel()); | |
| 238 if (!inputModel) return {}; | |
| 223 | 239 |
| 224 ModelTransformer *t = createTransformer(transforms, input); | 240 ModelTransformer *t = createTransformer(transforms, input); |
| 225 if (!t) return vector<Model *>(); | 241 if (!t) return {}; |
| 226 | 242 |
| 227 if (handler) { | 243 if (handler) { |
| 228 m_handlers[t] = handler; | 244 m_handlers[t] = handler; |
| 229 } | 245 } |
| 230 | 246 |
| 231 m_runningTransformers.insert(t); | 247 m_runningTransformers.insert(t); |
| 232 | 248 |
| 233 connect(t, SIGNAL(finished()), this, SLOT(transformerFinished())); | 249 connect(t, SIGNAL(finished()), this, SLOT(transformerFinished())); |
| 234 | 250 |
| 235 t->start(); | 251 t->start(); |
| 236 vector<Model *> models = t->detachOutputModels(); | 252 vector<ModelId> models = t->getOutputModels(); |
| 237 | 253 |
| 238 if (!models.empty()) { | 254 if (!models.empty()) { |
| 239 QString imn = input.getModel()->objectName(); | 255 QString imn = inputModel->objectName(); |
| 240 QString trn = | 256 QString trn = |
| 241 TransformFactory::getInstance()->getTransformFriendlyName | 257 TransformFactory::getInstance()->getTransformFriendlyName |
| 242 (transforms[0].getIdentifier()); | 258 (transforms[0].getIdentifier()); |
| 243 for (int i = 0; i < (int)models.size(); ++i) { | 259 for (int i = 0; in_range_for(models, i); ++i) { |
| 260 auto model = ModelById::get(models[i]); | |
| 261 if (!model) continue; | |
| 244 if (imn != "") { | 262 if (imn != "") { |
| 245 if (trn != "") { | 263 if (trn != "") { |
| 246 models[i]->setObjectName(tr("%1: %2").arg(imn).arg(trn)); | 264 model->setObjectName(tr("%1: %2").arg(imn).arg(trn)); |
| 247 } else { | 265 } else { |
| 248 models[i]->setObjectName(imn); | 266 model->setObjectName(imn); |
| 249 } | 267 } |
| 250 } else if (trn != "") { | 268 } else if (trn != "") { |
| 251 models[i]->setObjectName(trn); | 269 model->setObjectName(trn); |
| 252 } | 270 } |
| 253 } | 271 } |
| 254 } else { | 272 } else { |
| 255 t->wait(); | 273 t->wait(); |
| 256 } | 274 } |
| 282 << endl; | 300 << endl; |
| 283 } | 301 } |
| 284 | 302 |
| 285 m_runningTransformers.erase(transformer); | 303 m_runningTransformers.erase(transformer); |
| 286 | 304 |
| 287 map<AdditionalModelHandler *, vector<Model *>> toNotifyOfMore; | 305 map<AdditionalModelHandler *, vector<ModelId>> toNotifyOfMore; |
| 288 vector<AdditionalModelHandler *> toNotifyOfNoMore; | 306 vector<AdditionalModelHandler *> toNotifyOfNoMore; |
| 289 | 307 |
| 290 if (m_handlers.find(transformer) != m_handlers.end()) { | 308 if (m_handlers.find(transformer) != m_handlers.end()) { |
| 291 if (transformer->willHaveAdditionalOutputModels()) { | 309 if (transformer->willHaveAdditionalOutputModels()) { |
| 292 vector<Model *> mm = transformer->detachAdditionalOutputModels(); | 310 vector<ModelId> mm = transformer->getAdditionalOutputModels(); |
| 293 toNotifyOfMore[m_handlers[transformer]] = mm; | 311 toNotifyOfMore[m_handlers[transformer]] = mm; |
| 294 } else { | 312 } else { |
| 295 toNotifyOfNoMore.push_back(m_handlers[transformer]); | 313 toNotifyOfNoMore.push_back(m_handlers[transformer]); |
| 296 } | 314 } |
| 297 m_handlers.erase(transformer); | 315 m_handlers.erase(transformer); |
| 298 } | 316 } |
| 299 | 317 |
| 300 m_mutex.unlock(); | 318 m_mutex.unlock(); |
| 301 | 319 |
| 302 // These calls have to be made without the mutex held, as they may | 320 // We make these calls without the mutex held, in case they |
| 303 // ultimately call back on us (e.g. we have one baroque situation | 321 // ultimately call back on us - not such a concern as in the old |
| 304 // where this could trigger a command to create a layer, which | 322 // model lifecycle but just in case |
| 305 // triggers the command history to clip the stack, which deletes a | |
| 306 // spare old model, which calls back on our modelAboutToBeDeleted) | |
| 307 | 323 |
| 308 for (const auto &i: toNotifyOfMore) { | 324 for (const auto &i: toNotifyOfMore) { |
| 309 i.first->moreModelsAvailable(i.second); | 325 i.first->moreModelsAvailable(i.second); |
| 310 } | 326 } |
| 311 for (AdditionalModelHandler *handler: toNotifyOfNoMore) { | 327 for (AdditionalModelHandler *handler: toNotifyOfNoMore) { |
| 320 | 336 |
| 321 transformer->wait(); // unnecessary but reassuring | 337 transformer->wait(); // unnecessary but reassuring |
| 322 delete transformer; | 338 delete transformer; |
| 323 } | 339 } |
| 324 | 340 |
| 325 void | |
| 326 ModelTransformerFactory::modelAboutToBeDeleted(Model *m) | |
| 327 { | |
| 328 TransformerSet affected; | |
| 329 | |
| 330 { | |
| 331 QMutexLocker locker(&m_mutex); | |
| 332 | |
| 333 for (TransformerSet::iterator i = m_runningTransformers.begin(); | |
| 334 i != m_runningTransformers.end(); ++i) { | |
| 335 | |
| 336 ModelTransformer *t = *i; | |
| 337 | |
| 338 if (t->getInputModel() == m) { | |
| 339 affected.insert(t); | |
| 340 } else { | |
| 341 vector<Model *> mm = t->getOutputModels(); | |
| 342 for (int i = 0; i < (int)mm.size(); ++i) { | |
| 343 if (mm[i] == m) affected.insert(t); | |
| 344 } | |
| 345 } | |
| 346 } | |
| 347 } | |
| 348 | |
| 349 for (TransformerSet::iterator i = affected.begin(); | |
| 350 i != affected.end(); ++i) { | |
| 351 | |
| 352 ModelTransformer *t = *i; | |
| 353 | |
| 354 t->abandon(); | |
| 355 | |
| 356 t->wait(); // this should eventually call back on | |
| 357 // transformerFinished, which will remove from | |
| 358 // m_runningTransformers and delete. | |
| 359 } | |
| 360 } | |
| 361 | |
| 362 bool | 341 bool |
| 363 ModelTransformerFactory::haveRunningTransformers() const | 342 ModelTransformerFactory::haveRunningTransformers() const |
| 364 { | 343 { |
| 365 QMutexLocker locker(&m_mutex); | 344 QMutexLocker locker(&m_mutex); |
| 366 | 345 |
