Mercurial > hg > svapp
comparison framework/Align.cpp @ 683:0736beb8b852 by-id
Toward updating Document for ModelById
author | Chris Cannam |
---|---|
date | Wed, 03 Jul 2019 13:01:26 +0100 |
parents | c7406ebcd51c |
children | e0b0f3e163ca |
comparison
equal
deleted
inserted
replaced
682:161063152ddd | 683:0736beb8b852 |
---|---|
31 #include <QProcess> | 31 #include <QProcess> |
32 #include <QSettings> | 32 #include <QSettings> |
33 #include <QApplication> | 33 #include <QApplication> |
34 | 34 |
35 bool | 35 bool |
36 Align::alignModel(Document *doc, Model *ref, Model *other, QString &error) | 36 Align::alignModel(Document *doc, ModelId ref, ModelId other, QString &error) |
37 { | 37 { |
38 QSettings settings; | 38 QSettings settings; |
39 settings.beginGroup("Preferences"); | 39 settings.beginGroup("Preferences"); |
40 bool useProgram = settings.value("use-external-alignment", false).toBool(); | 40 bool useProgram = settings.value("use-external-alignment", false).toBool(); |
41 QString program = settings.value("external-alignment-program", "").toString(); | 41 QString program = settings.value("external-alignment-program", "").toString(); |
87 return factory->haveTransform(id) && | 87 return factory->haveTransform(id) && |
88 (tdId == "" || factory->haveTransform(tdId)); | 88 (tdId == "" || factory->haveTransform(tdId)); |
89 } | 89 } |
90 | 90 |
91 bool | 91 bool |
92 Align::alignModelViaTransform(Document *doc, Model *ref, Model *other, | 92 Align::alignModelViaTransform(Document *doc, ModelId ref, ModelId other, |
93 QString &error) | 93 QString &error) |
94 { | 94 { |
95 QMutexLocker locker (&m_mutex); | 95 QMutexLocker locker (&m_mutex); |
96 | 96 |
97 RangeSummarisableTimeValueModel *reference = qobject_cast | 97 auto reference = ModelById::getAs<RangeSummarisableTimeValueModel>(ref); |
98 <RangeSummarisableTimeValueModel *>(ref); | 98 auto rm = ModelById::getAs<RangeSummarisableTimeValueModel>(other); |
99 | 99 if (!reference || !rm) return false; |
100 RangeSummarisableTimeValueModel *rm = qobject_cast | |
101 <RangeSummarisableTimeValueModel *>(other); | |
102 | |
103 if (!reference || !rm) return false; // but this should have been tested already | |
104 | 100 |
105 // This involves creating either three or four new models: | 101 // This involves creating either three or four new models: |
106 // | 102 // |
107 // 1. an AggregateWaveModel to provide the mixdowns of the main | 103 // 1. an AggregateWaveModel to provide the mixdowns of the main |
108 // model and the new model in its two channels, as input to the | 104 // model and the new model in its two channels, as input to the |
128 // deleted by us. The SparseTimeValueModel [2b] is passed to the | 124 // deleted by us. The SparseTimeValueModel [2b] is passed to the |
129 // AlignmentModel, which takes ownership of it. The AlignmentModel | 125 // AlignmentModel, which takes ownership of it. The AlignmentModel |
130 // is attached to the new model we are aligning, which also takes | 126 // is attached to the new model we are aligning, which also takes |
131 // ownership of it. The only one of these models that we need to | 127 // ownership of it. The only one of these models that we need to |
132 // delete here is the SparseTimeValueModel [2a]. | 128 // delete here is the SparseTimeValueModel [2a]. |
129 //!!! todo: review the above, especially management of AlignmentModel | |
133 // | 130 // |
134 // (We also create a sneaky additional SparseTimeValueModel | 131 // (We also create a sneaky additional SparseTimeValueModel |
135 // temporarily so we can attach completion information to it - | 132 // temporarily so we can attach completion information to it - |
136 // this is quite unnecessary from the perspective of simply | 133 // this is quite unnecessary from the perspective of simply |
137 // producing the results.) | 134 // producing the results.) |
142 (reference->getId(), -1)); | 139 (reference->getId(), -1)); |
143 | 140 |
144 components.push_back(AggregateWaveModel::ModelChannelSpec | 141 components.push_back(AggregateWaveModel::ModelChannelSpec |
145 (rm->getId(), -1)); | 142 (rm->getId(), -1)); |
146 | 143 |
147 AggregateWaveModel *aggregateModel = new AggregateWaveModel(components); | 144 auto aggregateModel = std::make_shared<AggregateWaveModel>(components); |
148 doc->addAggregateModel(aggregateModel); | 145 ModelById::add(aggregateModel); |
149 | 146 doc->addAggregateModel(aggregateModel->getId()); |
150 AlignmentModel *alignmentModel = | 147 |
151 new AlignmentModel(reference, other, nullptr); | 148 auto alignmentModel = std::make_shared<AlignmentModel>(ref, other, |
149 ModelId()); | |
150 ModelById::add(alignmentModel); | |
152 | 151 |
153 TransformId tdId = getTuningDifferenceTransformName(); | 152 TransformId tdId = getTuningDifferenceTransformName(); |
154 | 153 |
155 if (tdId == "") { | 154 if (tdId == "") { |
156 | 155 |
157 if (beginTransformDrivenAlignment(aggregateModel, alignmentModel)) { | 156 if (beginTransformDrivenAlignment(aggregateModel->getId(), |
158 rm->setAlignment(alignmentModel); | 157 alignmentModel->getId())) { |
158 rm->setAlignment(alignmentModel->getId()); | |
159 } else { | 159 } else { |
160 error = alignmentModel->getError(); | 160 error = alignmentModel->getError(); |
161 delete alignmentModel; | 161 ModelById::release(alignmentModel); |
162 return false; | 162 return false; |
163 } | 163 } |
164 | 164 |
165 } else { | 165 } else { |
166 | 166 |
179 SVDEBUG << "Align::alignModel: Tuning difference transform step size " << transform.getStepSize() << ", block size " << transform.getBlockSize() << endl; | 179 SVDEBUG << "Align::alignModel: Tuning difference transform step size " << transform.getStepSize() << ", block size " << transform.getBlockSize() << endl; |
180 | 180 |
181 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); | 181 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); |
182 | 182 |
183 QString message; | 183 QString message; |
184 Model *transformOutput = mtf->transform(transform, aggregateModel, message); | 184 ModelId transformOutput = mtf->transform(transform, |
185 | 185 aggregateModel->getId(), |
186 SparseTimeValueModel *tdout = dynamic_cast<SparseTimeValueModel *> | 186 message); |
187 (transformOutput); | 187 |
188 | 188 auto tdout = ModelById::getAs<SparseTimeValueModel>(transformOutput); |
189 if (!tdout) { | 189 if (!tdout) { |
190 SVCERR << "Align::alignModel: ERROR: Failed to create tuning-difference output model (no Tuning Difference plugin?)" << endl; | 190 SVCERR << "Align::alignModel: ERROR: Failed to create tuning-difference output model (no Tuning Difference plugin?)" << endl; |
191 delete tdout; | |
192 error = message; | 191 error = message; |
193 return false; | 192 return false; |
194 } | 193 } |
195 | 194 |
196 rm->setAlignment(alignmentModel); | 195 rm->setAlignment(alignmentModel->getId()); |
197 | 196 |
198 connect(tdout, SIGNAL(completionChanged()), | 197 connect(tdout.get(), SIGNAL(completionChanged()), |
199 this, SLOT(tuningDifferenceCompletionChanged())); | 198 this, SLOT(tuningDifferenceCompletionChanged())); |
200 | 199 |
201 TuningDiffRec rec; | 200 TuningDiffRec rec; |
202 rec.input = aggregateModel; | 201 rec.input = aggregateModel->getId(); |
203 rec.alignment = alignmentModel; | 202 rec.alignment = alignmentModel->getId(); |
204 | |
205 connect(aggregateModel, SIGNAL(aboutToBeDeleted()), | |
206 this, SLOT(aggregateModelAboutToBeDeleted())); | |
207 | 203 |
208 // This model exists only so that the AlignmentModel can get a | 204 // This model exists only so that the AlignmentModel can get a |
209 // completion value from somewhere while the tuning difference | 205 // completion value from somewhere while the tuning difference |
210 // calculation is going on | 206 // calculation is going on |
211 rec.preparatory = new SparseTimeValueModel | 207 auto preparatoryModel = std::make_shared<SparseTimeValueModel> |
212 (aggregateModel->getSampleRate(), 1);; | 208 (aggregateModel->getSampleRate(), 1); |
213 rec.preparatory->setCompletion(0); | 209 ModelById::add(preparatoryModel); |
210 preparatoryModel->setCompletion(0); | |
211 rec.preparatory = preparatoryModel->getId(); | |
214 alignmentModel->setPathFrom(rec.preparatory); | 212 alignmentModel->setPathFrom(rec.preparatory); |
215 | 213 |
216 m_pendingTuningDiffs[tdout] = rec; | 214 m_pendingTuningDiffs[transformOutput] = rec; |
217 } | 215 } |
218 | 216 |
219 return true; | 217 return true; |
220 } | |
221 | |
222 void | |
223 Align::aggregateModelAboutToBeDeleted() | |
224 { | |
225 SVCERR << "Align::aggregateModelAboutToBeDeleted" << endl; | |
226 | |
227 QObject *s = sender(); | |
228 AggregateWaveModel *awm = qobject_cast<AggregateWaveModel *>(s); | |
229 if (!awm) return; | |
230 QMutexLocker locker(&m_mutex); | |
231 | |
232 SVCERR << "Align::aggregateModelAboutToBeDeleted: awm = " << awm | |
233 << endl; | |
234 | |
235 for (const auto &p : m_pendingTuningDiffs) { | |
236 if (p.second.input == awm) { | |
237 SVCERR << "we have a record of this, getting rid of it" << endl; | |
238 m_pendingTuningDiffs.erase(p.first); | |
239 return; | |
240 } | |
241 } | |
242 } | 218 } |
243 | 219 |
244 void | 220 void |
245 Align::tuningDifferenceCompletionChanged() | 221 Align::tuningDifferenceCompletionChanged() |
246 { | 222 { |
247 QMutexLocker locker (&m_mutex); | 223 QMutexLocker locker (&m_mutex); |
248 | 224 |
249 SparseTimeValueModel *td = qobject_cast<SparseTimeValueModel *>(sender()); | 225 ModelId tdId; |
250 if (!td) return; | 226 if (Model *modelPtr = qobject_cast<Model *>(sender())) { |
251 | 227 tdId = modelPtr->getId(); |
252 if (m_pendingTuningDiffs.find(td) == m_pendingTuningDiffs.end()) { | 228 } else { |
229 return; | |
230 } | |
231 | |
232 if (m_pendingTuningDiffs.find(tdId) == m_pendingTuningDiffs.end()) { | |
253 SVCERR << "ERROR: Align::tuningDifferenceCompletionChanged: Model " | 233 SVCERR << "ERROR: Align::tuningDifferenceCompletionChanged: Model " |
254 << td << " not found in pending tuning diff map!" << endl; | 234 << tdId << " not found in pending tuning diff map!" << endl; |
255 return; | 235 return; |
256 } | 236 } |
257 | 237 |
258 TuningDiffRec rec = m_pendingTuningDiffs[td]; | 238 auto td = ModelById::getAs<SparseTimeValueModel>(tdId); |
259 | 239 if (!td) { |
240 SVCERR << "WARNING: Align::tuningDifferenceCompletionChanged: Model " | |
241 << tdId << " not known as SparseTimeValueModel" << endl; | |
242 return; | |
243 } | |
244 | |
245 TuningDiffRec rec = m_pendingTuningDiffs[tdId]; | |
246 | |
247 auto alignment = ModelById::getAs<AlignmentModel>(rec.alignment); | |
248 if (!alignment) { | |
249 SVCERR << "WARNING: Align::tuningDifferenceCompletionChanged:" | |
250 << "alignment model has disappeared" << endl; | |
251 return; | |
252 } | |
253 | |
260 int completion = 0; | 254 int completion = 0; |
261 bool done = td->isReady(&completion); | 255 bool done = td->isReady(&completion); |
262 | 256 |
263 // SVCERR << "Align::tuningDifferenceCompletionChanged: done = " << done << ", completion = " << completion << endl; | 257 // SVCERR << "Align::tuningDifferenceCompletionChanged: done = " << done << ", completion = " << completion << endl; |
264 | 258 |
267 // before the alignment actually begins. It goes up from 0 to | 261 // before the alignment actually begins. It goes up from 0 to |
268 // 99 (not 100!) and then back to 0 again when we start | 262 // 99 (not 100!) and then back to 0 again when we start |
269 // calculating the actual path in the following phase | 263 // calculating the actual path in the following phase |
270 int clamped = (completion == 100 ? 99 : completion); | 264 int clamped = (completion == 100 ? 99 : completion); |
271 // SVCERR << "Align::tuningDifferenceCompletionChanged: setting rec.preparatory completion to " << clamped << endl; | 265 // SVCERR << "Align::tuningDifferenceCompletionChanged: setting rec.preparatory completion to " << clamped << endl; |
272 rec.preparatory->setCompletion(clamped); | 266 auto preparatory = ModelById::getAs<SparseTimeValueModel> |
267 (rec.preparatory); | |
268 if (preparatory) { | |
269 preparatory->setCompletion(clamped); | |
270 } | |
273 return; | 271 return; |
274 } | 272 } |
275 | 273 |
276 float tuningFrequency = 440.f; | 274 float tuningFrequency = 440.f; |
277 | 275 |
280 SVCERR << "Align::tuningDifferenceCompletionChanged: Reported tuning frequency = " << tuningFrequency << endl; | 278 SVCERR << "Align::tuningDifferenceCompletionChanged: Reported tuning frequency = " << tuningFrequency << endl; |
281 } else { | 279 } else { |
282 SVCERR << "Align::tuningDifferenceCompletionChanged: No tuning frequency reported" << endl; | 280 SVCERR << "Align::tuningDifferenceCompletionChanged: No tuning frequency reported" << endl; |
283 } | 281 } |
284 | 282 |
285 m_pendingTuningDiffs.erase(td); | 283 m_pendingTuningDiffs.erase(tdId); |
286 td->aboutToDelete(); | 284 ModelById::release(tdId); |
287 delete td; | 285 |
288 | 286 alignment->setPathFrom({}); |
289 rec.alignment->setPathFrom(nullptr); | |
290 | 287 |
291 beginTransformDrivenAlignment | 288 beginTransformDrivenAlignment |
292 (rec.input, rec.alignment, tuningFrequency); | 289 (rec.input, rec.alignment, tuningFrequency); |
293 } | 290 } |
294 | 291 |
295 bool | 292 bool |
296 Align::beginTransformDrivenAlignment(AggregateWaveModel *aggregateModel, | 293 Align::beginTransformDrivenAlignment(ModelId aggregateModelId, |
297 AlignmentModel *alignmentModel, | 294 ModelId alignmentModelId, |
298 float tuningFrequency) | 295 float tuningFrequency) |
299 { | 296 { |
300 TransformId id = getAlignmentTransformName(); | 297 TransformId id = getAlignmentTransformName(); |
301 | 298 |
302 TransformFactory *tf = TransformFactory::getInstance(); | 299 TransformFactory *tf = TransformFactory::getInstance(); |
303 | 300 |
301 auto aggregateModel = ModelById::getAs<AggregateWaveModel>(aggregateModelId); | |
302 auto alignmentModel = ModelById::getAs<AlignmentModel>(alignmentModelId); | |
303 | |
304 if (!aggregateModel || !alignmentModel) { | |
305 SVCERR << "Align::alignModel: ERROR: One or other of the aggregate & alignment models has disappeared" << endl; | |
306 return false; | |
307 } | |
308 | |
304 Transform transform = tf->getDefaultTransformFor | 309 Transform transform = tf->getDefaultTransformFor |
305 (id, aggregateModel->getSampleRate()); | 310 (id, aggregateModel->getSampleRate()); |
306 | 311 |
307 transform.setStepSize(transform.getBlockSize()/2); | 312 transform.setStepSize(transform.getBlockSize()/2); |
308 transform.setParameter("serialise", 1); | 313 transform.setParameter("serialise", 1); |
315 SVDEBUG << "Align::alignModel: Alignment transform step size " << transform.getStepSize() << ", block size " << transform.getBlockSize() << endl; | 320 SVDEBUG << "Align::alignModel: Alignment transform step size " << transform.getStepSize() << ", block size " << transform.getBlockSize() << endl; |
316 | 321 |
317 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); | 322 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); |
318 | 323 |
319 QString message; | 324 QString message; |
320 Model *transformOutput = mtf->transform | 325 ModelId transformOutput = mtf->transform |
321 (transform, aggregateModel, message); | 326 (transform, aggregateModelId, message); |
322 | 327 |
323 if (!transformOutput) { | 328 if (transformOutput.isNone()) { |
324 transform.setStepSize(0); | 329 transform.setStepSize(0); |
325 transformOutput = mtf->transform | 330 transformOutput = mtf->transform |
326 (transform, aggregateModel, message); | 331 (transform, aggregateModelId, message); |
327 } | 332 } |
328 | 333 |
329 SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *> | 334 auto path = ModelById::getAs<SparseTimeValueModel>(transformOutput); |
330 (transformOutput); | |
331 | 335 |
332 //!!! callers will need to be updated to get error from | 336 //!!! callers will need to be updated to get error from |
333 //!!! alignment model after initial call | 337 //!!! alignment model after initial call |
334 | 338 |
335 if (!path) { | 339 if (!path) { |
336 SVCERR << "Align::alignModel: ERROR: Failed to create alignment path (no MATCH plugin?)" << endl; | 340 SVCERR << "Align::alignModel: ERROR: Failed to create alignment path (no MATCH plugin?)" << endl; |
337 delete transformOutput; | 341 ModelById::release(transformOutput); |
338 alignmentModel->setError(message); | 342 alignmentModel->setError(message); |
339 return false; | 343 return false; |
340 } | 344 } |
341 | 345 |
342 path->setCompletion(0); | 346 path->setCompletion(0); |
343 alignmentModel->setPathFrom(path); | 347 alignmentModel->setPathFrom(transformOutput); //!!! who releases transformOutput? |
344 | 348 |
345 connect(alignmentModel, SIGNAL(completionChanged()), | 349 connect(alignmentModel.get(), SIGNAL(completionChanged()), |
346 this, SLOT(alignmentCompletionChanged())); | 350 this, SLOT(alignmentCompletionChanged())); |
347 | 351 |
348 return true; | 352 return true; |
349 } | 353 } |
350 | 354 |
351 void | 355 void |
352 Align::alignmentCompletionChanged() | 356 Align::alignmentCompletionChanged() |
353 { | 357 { |
354 QMutexLocker locker (&m_mutex); | 358 QMutexLocker locker (&m_mutex); |
355 | 359 |
356 AlignmentModel *am = qobject_cast<AlignmentModel *>(sender()); | 360 if (AlignmentModel *amPtr = qobject_cast<AlignmentModel *>(sender())) { |
357 if (!am) return; | 361 |
358 if (am->isReady()) { | 362 auto am = ModelById::getAs<AlignmentModel>(amPtr->getId()); |
359 disconnect(am, SIGNAL(completionChanged()), | 363 if (am && am->isReady()) { |
360 this, SLOT(alignmentCompletionChanged())); | 364 disconnect(am.get(), SIGNAL(completionChanged()), |
361 emit alignmentComplete(am); | 365 this, SLOT(alignmentCompletionChanged())); |
366 emit alignmentComplete(am->getId()); | |
367 } | |
362 } | 368 } |
363 } | 369 } |
364 | 370 |
365 bool | 371 bool |
366 Align::alignModelViaProgram(Document *, Model *ref, Model *other, | 372 Align::alignModelViaProgram(Document *, ModelId ref, ModelId other, |
367 QString program, QString &error) | 373 QString program, QString &error) |
368 { | 374 { |
369 QMutexLocker locker (&m_mutex); | 375 QMutexLocker locker (&m_mutex); |
370 | 376 |
371 WaveFileModel *reference = qobject_cast<WaveFileModel *>(ref); | 377 auto reference = ModelById::getAs<RangeSummarisableTimeValueModel>(ref); |
372 WaveFileModel *rm = qobject_cast<WaveFileModel *>(other); | 378 auto rm = ModelById::getAs<RangeSummarisableTimeValueModel>(other); |
373 | 379 if (!reference || !rm) return false; |
374 if (!reference || !rm) { | |
375 return false; // but this should have been tested already | |
376 } | |
377 | 380 |
378 while (!reference->isReady(nullptr) || !rm->isReady(nullptr)) { | 381 while (!reference->isReady(nullptr) || !rm->isReady(nullptr)) { |
379 qApp->processEvents(); | 382 qApp->processEvents(); |
380 } | 383 } |
381 | 384 |
382 // Run an external program, passing to it paths to the main | 385 // Run an external program, passing to it paths to the main |
383 // model's audio file and the new model's audio file. It returns | 386 // model's audio file and the new model's audio file. It returns |
384 // the path in CSV form through stdout. | 387 // the path in CSV form through stdout. |
385 | 388 |
386 ReadOnlyWaveFileModel *roref = qobject_cast<ReadOnlyWaveFileModel *>(reference); | 389 auto roref = ModelById::getAs<ReadOnlyWaveFileModel>(ref); |
387 ReadOnlyWaveFileModel *rorm = qobject_cast<ReadOnlyWaveFileModel *>(rm); | 390 auto rorm = ModelById::getAs<ReadOnlyWaveFileModel>(other); |
388 if (!roref || !rorm) { | 391 if (!roref || !rorm) { |
389 SVCERR << "ERROR: Align::alignModelViaProgram: Can't align non-read-only models via program (no local filename available)" << endl; | 392 SVCERR << "ERROR: Align::alignModelViaProgram: Can't align non-read-only models via program (no local filename available)" << endl; |
390 return false; | 393 return false; |
391 } | 394 } |
392 | 395 |
396 if (refPath == "" || otherPath == "") { | 399 if (refPath == "" || otherPath == "") { |
397 error = "Failed to find local filepath for wave-file model"; | 400 error = "Failed to find local filepath for wave-file model"; |
398 return false; | 401 return false; |
399 } | 402 } |
400 | 403 |
401 AlignmentModel *alignmentModel = | 404 auto alignmentModel = std::make_shared<AlignmentModel>(ref, other, |
402 new AlignmentModel(reference, other, nullptr); | 405 ModelId()); |
403 rm->setAlignment(alignmentModel); | 406 ModelById::add(alignmentModel); |
407 rm->setAlignment(alignmentModel->getId()); | |
404 | 408 |
405 QProcess *process = new QProcess; | 409 QProcess *process = new QProcess; |
406 QStringList args; | 410 QStringList args; |
407 args << refPath << otherPath; | 411 args << refPath << otherPath; |
408 | 412 |
409 connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), | 413 connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), |
410 this, SLOT(alignmentProgramFinished(int, QProcess::ExitStatus))); | 414 this, SLOT(alignmentProgramFinished(int, QProcess::ExitStatus))); |
411 | 415 |
412 m_pendingProcesses[process] = alignmentModel; | 416 m_pendingProcesses[process] = alignmentModel->getId(); |
413 process->start(program, args); | 417 process->start(program, args); |
414 | 418 |
415 bool success = process->waitForStarted(); | 419 bool success = process->waitForStarted(); |
416 | 420 |
417 if (!success) { | 421 if (!success) { |
418 SVCERR << "ERROR: Align::alignModelViaProgram: Program did not start" | 422 SVCERR << "ERROR: Align::alignModelViaProgram: Program did not start" |
419 << endl; | 423 << endl; |
420 error = "Alignment program could not be started"; | 424 error = "Alignment program could not be started"; |
421 m_pendingProcesses.erase(process); | 425 m_pendingProcesses.erase(process); |
422 rm->setAlignment(nullptr); // deletes alignmentModel as well | 426 //!!! who releases alignmentModel? does this? review |
427 rm->setAlignment({}); | |
423 delete process; | 428 delete process; |
424 } | 429 } |
425 | 430 |
426 return success; | 431 return success; |
427 } | 432 } |
439 SVCERR << "ERROR: Align::alignmentProgramFinished: Process " << process | 444 SVCERR << "ERROR: Align::alignmentProgramFinished: Process " << process |
440 << " not found in process model map!" << endl; | 445 << " not found in process model map!" << endl; |
441 return; | 446 return; |
442 } | 447 } |
443 | 448 |
444 AlignmentModel *alignmentModel = m_pendingProcesses[process]; | 449 ModelId alignmentModelId = m_pendingProcesses[process]; |
450 auto alignmentModel = ModelById::getAs<AlignmentModel>(alignmentModelId); | |
451 if (!alignmentModel) return; | |
445 | 452 |
446 if (exitCode == 0 && status == 0) { | 453 if (exitCode == 0 && status == 0) { |
447 | 454 |
448 CSVFormat format; | 455 CSVFormat format; |
449 format.setModelType(CSVFormat::TwoDimensionalModel); | 456 format.setModelType(CSVFormat::TwoDimensionalModel); |
469 (QString("Failed to parse output of program: %1") | 476 (QString("Failed to parse output of program: %1") |
470 .arg(reader.getError())); | 477 .arg(reader.getError())); |
471 goto done; | 478 goto done; |
472 } | 479 } |
473 | 480 |
481 //!!! to use ById? | |
482 | |
474 Model *csvOutput = reader.load(); | 483 Model *csvOutput = reader.load(); |
475 | 484 |
476 SparseTimeValueModel *path = qobject_cast<SparseTimeValueModel *>(csvOutput); | 485 SparseTimeValueModel *path = qobject_cast<SparseTimeValueModel *>(csvOutput); |
477 if (!path) { | 486 if (!path) { |
478 SVCERR << "ERROR: Align::alignmentProgramFinished: Output did not convert to sparse time-value model" | 487 SVCERR << "ERROR: Align::alignmentProgramFinished: Output did not convert to sparse time-value model" |
479 << endl; | 488 << endl; |
480 alignmentModel->setError | 489 alignmentModel->setError |
481 ("Output of program did not produce sparse time-value model"); | 490 ("Output of program did not produce sparse time-value model"); |
491 delete csvOutput; | |
482 goto done; | 492 goto done; |
483 } | 493 } |
484 | 494 |
485 if (path->isEmpty()) { | 495 if (path->isEmpty()) { |
486 SVCERR << "ERROR: Align::alignmentProgramFinished: Output contained no mappings" | 496 SVCERR << "ERROR: Align::alignmentProgramFinished: Output contained no mappings" |
487 << endl; | 497 << endl; |
488 alignmentModel->setError | 498 alignmentModel->setError |
489 ("Output of alignment program contained no mappings"); | 499 ("Output of alignment program contained no mappings"); |
500 delete path; | |
490 goto done; | 501 goto done; |
491 } | 502 } |
492 | 503 |
493 SVCERR << "Align::alignmentProgramFinished: Setting alignment path (" | 504 SVCERR << "Align::alignmentProgramFinished: Setting alignment path (" |
494 << path->getEventCount() << " point(s))" << endl; | 505 << path->getEventCount() << " point(s))" << endl; |
495 | 506 |
496 alignmentModel->setPathFrom(path); | 507 ModelById::add(std::shared_ptr<SparseTimeValueModel>(path)); |
497 | 508 alignmentModel->setPathFrom(path->getId()); |
498 emit alignmentComplete(alignmentModel); | 509 |
510 emit alignmentComplete(alignmentModelId); | |
499 | 511 |
500 } else { | 512 } else { |
501 SVCERR << "ERROR: Align::alignmentProgramFinished: Aligner program " | 513 SVCERR << "ERROR: Align::alignmentProgramFinished: Aligner program " |
502 << "failed: exit code " << exitCode << ", status " << status | 514 << "failed: exit code " << exitCode << ", status " << status |
503 << endl; | 515 << endl; |