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