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 |