Mercurial > hg > svapp
comparison framework/Align.cpp @ 687:e0b0f3e163ca by-id
Update for removal of (public) getId from Model
author | Chris Cannam |
---|---|
date | Fri, 05 Jul 2019 15:35:11 +0100 |
parents | 0736beb8b852 |
children | c8ba09756eff |
comparison
equal
deleted
inserted
replaced
686:610fa108fbcc | 687:e0b0f3e163ca |
---|---|
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, ModelId ref, ModelId other, | 92 Align::alignModelViaTransform(Document *doc, |
93 ModelId referenceId, | |
94 ModelId otherId, | |
93 QString &error) | 95 QString &error) |
94 { | 96 { |
95 QMutexLocker locker (&m_mutex); | 97 QMutexLocker locker (&m_mutex); |
96 | 98 |
97 auto reference = ModelById::getAs<RangeSummarisableTimeValueModel>(ref); | 99 auto reference = |
98 auto rm = ModelById::getAs<RangeSummarisableTimeValueModel>(other); | 100 ModelById::getAs<RangeSummarisableTimeValueModel>(referenceId); |
99 if (!reference || !rm) return false; | 101 auto other = |
102 ModelById::getAs<RangeSummarisableTimeValueModel>(otherId); | |
103 | |
104 if (!reference || !other) return false; | |
100 | 105 |
101 // This involves creating either three or four new models: | 106 // This involves creating either three or four new models: |
102 // | 107 // |
103 // 1. an AggregateWaveModel to provide the mixdowns of the main | 108 // 1. an AggregateWaveModel to provide the mixdowns of the main |
104 // model and the new model in its two channels, as input to the | 109 // model and the new model in its two channels, as input to the |
133 // this is quite unnecessary from the perspective of simply | 138 // this is quite unnecessary from the perspective of simply |
134 // producing the results.) | 139 // producing the results.) |
135 | 140 |
136 AggregateWaveModel::ChannelSpecList components; | 141 AggregateWaveModel::ChannelSpecList components; |
137 | 142 |
138 components.push_back(AggregateWaveModel::ModelChannelSpec | 143 components.push_back |
139 (reference->getId(), -1)); | 144 (AggregateWaveModel::ModelChannelSpec(referenceId, -1)); |
140 | 145 |
141 components.push_back(AggregateWaveModel::ModelChannelSpec | 146 components.push_back |
142 (rm->getId(), -1)); | 147 (AggregateWaveModel::ModelChannelSpec(otherId, -1)); |
143 | 148 |
144 auto aggregateModel = std::make_shared<AggregateWaveModel>(components); | 149 auto aggregateModel = std::make_shared<AggregateWaveModel>(components); |
145 ModelById::add(aggregateModel); | 150 auto aggregateModelId = ModelById::add(aggregateModel); |
146 doc->addAggregateModel(aggregateModel->getId()); | 151 doc->addAggregateModel(aggregateModelId); |
147 | 152 |
148 auto alignmentModel = std::make_shared<AlignmentModel>(ref, other, | 153 auto alignmentModel = std::make_shared<AlignmentModel> |
149 ModelId()); | 154 (referenceId, otherId, ModelId()); |
150 ModelById::add(alignmentModel); | 155 auto alignmentModelId = ModelById::add(alignmentModel); |
151 | 156 |
152 TransformId tdId = getTuningDifferenceTransformName(); | 157 TransformId tdId = getTuningDifferenceTransformName(); |
153 | 158 |
154 if (tdId == "") { | 159 if (tdId == "") { |
155 | 160 |
156 if (beginTransformDrivenAlignment(aggregateModel->getId(), | 161 if (beginTransformDrivenAlignment(aggregateModelId, |
157 alignmentModel->getId())) { | 162 alignmentModelId)) { |
158 rm->setAlignment(alignmentModel->getId()); | 163 other->setAlignment(alignmentModelId); |
159 } else { | 164 } else { |
160 error = alignmentModel->getError(); | 165 error = alignmentModel->getError(); |
161 ModelById::release(alignmentModel); | 166 ModelById::release(alignmentModel); |
162 return false; | 167 return false; |
163 } | 168 } |
180 | 185 |
181 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); | 186 ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); |
182 | 187 |
183 QString message; | 188 QString message; |
184 ModelId transformOutput = mtf->transform(transform, | 189 ModelId transformOutput = mtf->transform(transform, |
185 aggregateModel->getId(), | 190 aggregateModelId, |
186 message); | 191 message); |
187 | 192 |
188 auto tdout = ModelById::getAs<SparseTimeValueModel>(transformOutput); | 193 auto tdout = ModelById::getAs<SparseTimeValueModel>(transformOutput); |
189 if (!tdout) { | 194 if (!tdout) { |
190 SVCERR << "Align::alignModel: ERROR: Failed to create tuning-difference output model (no Tuning Difference plugin?)" << endl; | 195 SVCERR << "Align::alignModel: ERROR: Failed to create tuning-difference output model (no Tuning Difference plugin?)" << endl; |
191 error = message; | 196 error = message; |
192 return false; | 197 return false; |
193 } | 198 } |
194 | 199 |
195 rm->setAlignment(alignmentModel->getId()); | 200 other->setAlignment(alignmentModelId); |
196 | 201 |
197 connect(tdout.get(), SIGNAL(completionChanged()), | 202 connect(tdout.get(), SIGNAL(completionChanged(ModelId)), |
198 this, SLOT(tuningDifferenceCompletionChanged())); | 203 this, SLOT(tuningDifferenceCompletionChanged(ModelId))); |
199 | 204 |
200 TuningDiffRec rec; | 205 TuningDiffRec rec; |
201 rec.input = aggregateModel->getId(); | 206 rec.input = aggregateModelId; |
202 rec.alignment = alignmentModel->getId(); | 207 rec.alignment = alignmentModelId; |
203 | 208 |
204 // This model exists only so that the AlignmentModel can get a | 209 // This model exists only so that the AlignmentModel can get a |
205 // completion value from somewhere while the tuning difference | 210 // completion value from somewhere while the tuning difference |
206 // calculation is going on | 211 // calculation is going on |
207 auto preparatoryModel = std::make_shared<SparseTimeValueModel> | 212 auto preparatoryModel = std::make_shared<SparseTimeValueModel> |
208 (aggregateModel->getSampleRate(), 1); | 213 (aggregateModel->getSampleRate(), 1); |
209 ModelById::add(preparatoryModel); | 214 auto preparatoryModelId = ModelById::add(preparatoryModel); |
210 preparatoryModel->setCompletion(0); | 215 preparatoryModel->setCompletion(0); |
211 rec.preparatory = preparatoryModel->getId(); | 216 rec.preparatory = preparatoryModelId; |
212 alignmentModel->setPathFrom(rec.preparatory); | 217 alignmentModel->setPathFrom(rec.preparatory); |
213 | 218 |
214 m_pendingTuningDiffs[transformOutput] = rec; | 219 m_pendingTuningDiffs[transformOutput] = rec; |
215 } | 220 } |
216 | 221 |
217 return true; | 222 return true; |
218 } | 223 } |
219 | 224 |
220 void | 225 void |
221 Align::tuningDifferenceCompletionChanged() | 226 Align::tuningDifferenceCompletionChanged(ModelId tdId) |
222 { | 227 { |
223 QMutexLocker locker (&m_mutex); | 228 QMutexLocker locker(&m_mutex); |
224 | |
225 ModelId tdId; | |
226 if (Model *modelPtr = qobject_cast<Model *>(sender())) { | |
227 tdId = modelPtr->getId(); | |
228 } else { | |
229 return; | |
230 } | |
231 | 229 |
232 if (m_pendingTuningDiffs.find(tdId) == m_pendingTuningDiffs.end()) { | 230 if (m_pendingTuningDiffs.find(tdId) == m_pendingTuningDiffs.end()) { |
233 SVCERR << "ERROR: Align::tuningDifferenceCompletionChanged: Model " | 231 SVCERR << "ERROR: Align::tuningDifferenceCompletionChanged: Model " |
234 << tdId << " not found in pending tuning diff map!" << endl; | 232 << tdId << " not found in pending tuning diff map!" << endl; |
235 return; | 233 return; |
344 } | 342 } |
345 | 343 |
346 path->setCompletion(0); | 344 path->setCompletion(0); |
347 alignmentModel->setPathFrom(transformOutput); //!!! who releases transformOutput? | 345 alignmentModel->setPathFrom(transformOutput); //!!! who releases transformOutput? |
348 | 346 |
349 connect(alignmentModel.get(), SIGNAL(completionChanged()), | 347 connect(alignmentModel.get(), SIGNAL(completionChanged(ModelId)), |
350 this, SLOT(alignmentCompletionChanged())); | 348 this, SLOT(alignmentCompletionChanged(ModelId))); |
351 | 349 |
352 return true; | 350 return true; |
353 } | 351 } |
354 | 352 |
355 void | 353 void |
356 Align::alignmentCompletionChanged() | 354 Align::alignmentCompletionChanged(ModelId modelId) |
357 { | 355 { |
358 QMutexLocker locker (&m_mutex); | 356 QMutexLocker locker (&m_mutex); |
359 | 357 |
360 if (AlignmentModel *amPtr = qobject_cast<AlignmentModel *>(sender())) { | 358 auto am = ModelById::getAs<AlignmentModel>(modelId); |
361 | 359 if (am && am->isReady()) { |
362 auto am = ModelById::getAs<AlignmentModel>(amPtr->getId()); | 360 disconnect(am.get(), SIGNAL(completionChanged(ModelId)), |
363 if (am && am->isReady()) { | 361 this, SLOT(alignmentCompletionChanged(ModelId))); |
364 disconnect(am.get(), SIGNAL(completionChanged()), | 362 emit alignmentComplete(modelId); |
365 this, SLOT(alignmentCompletionChanged())); | |
366 emit alignmentComplete(am->getId()); | |
367 } | |
368 } | 363 } |
369 } | 364 } |
370 | 365 |
371 bool | 366 bool |
372 Align::alignModelViaProgram(Document *, ModelId ref, ModelId other, | 367 Align::alignModelViaProgram(Document *, |
373 QString program, QString &error) | 368 ModelId referenceId, |
369 ModelId otherId, | |
370 QString program, | |
371 QString &error) | |
374 { | 372 { |
375 QMutexLocker locker (&m_mutex); | 373 QMutexLocker locker (&m_mutex); |
376 | |
377 auto reference = ModelById::getAs<RangeSummarisableTimeValueModel>(ref); | |
378 auto rm = ModelById::getAs<RangeSummarisableTimeValueModel>(other); | |
379 if (!reference || !rm) return false; | |
380 | |
381 while (!reference->isReady(nullptr) || !rm->isReady(nullptr)) { | |
382 qApp->processEvents(); | |
383 } | |
384 | 374 |
385 // Run an external program, passing to it paths to the main | 375 // Run an external program, passing to it paths to the main |
386 // model's audio file and the new model's audio file. It returns | 376 // model's audio file and the new model's audio file. It returns |
387 // the path in CSV form through stdout. | 377 // the path in CSV form through stdout. |
388 | 378 |
389 auto roref = ModelById::getAs<ReadOnlyWaveFileModel>(ref); | 379 auto reference = ModelById::getAs<ReadOnlyWaveFileModel>(referenceId); |
390 auto rorm = ModelById::getAs<ReadOnlyWaveFileModel>(other); | 380 auto other = ModelById::getAs<ReadOnlyWaveFileModel>(otherId); |
391 if (!roref || !rorm) { | 381 if (!reference || !other) { |
392 SVCERR << "ERROR: Align::alignModelViaProgram: Can't align non-read-only models via program (no local filename available)" << endl; | 382 SVCERR << "ERROR: Align::alignModelViaProgram: Can't align non-read-only models via program (no local filename available)" << endl; |
393 return false; | 383 return false; |
394 } | 384 } |
395 | 385 |
396 QString refPath = roref->getLocalFilename(); | 386 while (!reference->isReady(nullptr) || !other->isReady(nullptr)) { |
397 QString otherPath = rorm->getLocalFilename(); | 387 qApp->processEvents(); |
388 } | |
389 | |
390 QString refPath = reference->getLocalFilename(); | |
391 QString otherPath = other->getLocalFilename(); | |
398 | 392 |
399 if (refPath == "" || otherPath == "") { | 393 if (refPath == "" || otherPath == "") { |
400 error = "Failed to find local filepath for wave-file model"; | 394 error = "Failed to find local filepath for wave-file model"; |
401 return false; | 395 return false; |
402 } | 396 } |
403 | 397 |
404 auto alignmentModel = std::make_shared<AlignmentModel>(ref, other, | 398 auto alignmentModel = |
405 ModelId()); | 399 std::make_shared<AlignmentModel>(referenceId, otherId, ModelId()); |
406 ModelById::add(alignmentModel); | 400 auto alignmentModelId = ModelById::add(alignmentModel); |
407 rm->setAlignment(alignmentModel->getId()); | 401 other->setAlignment(alignmentModelId); |
408 | 402 |
409 QProcess *process = new QProcess; | 403 QProcess *process = new QProcess; |
410 QStringList args; | 404 QStringList args; |
411 args << refPath << otherPath; | 405 args << refPath << otherPath; |
412 | 406 |
413 connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), | 407 connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), |
414 this, SLOT(alignmentProgramFinished(int, QProcess::ExitStatus))); | 408 this, SLOT(alignmentProgramFinished(int, QProcess::ExitStatus))); |
415 | 409 |
416 m_pendingProcesses[process] = alignmentModel->getId(); | 410 m_pendingProcesses[process] = alignmentModelId; |
417 process->start(program, args); | 411 process->start(program, args); |
418 | 412 |
419 bool success = process->waitForStarted(); | 413 bool success = process->waitForStarted(); |
420 | 414 |
421 if (!success) { | 415 if (!success) { |
422 SVCERR << "ERROR: Align::alignModelViaProgram: Program did not start" | 416 SVCERR << "ERROR: Align::alignModelViaProgram: Program did not start" |
423 << endl; | 417 << endl; |
424 error = "Alignment program could not be started"; | 418 error = "Alignment program could not be started"; |
425 m_pendingProcesses.erase(process); | 419 m_pendingProcesses.erase(process); |
426 //!!! who releases alignmentModel? does this? review | 420 //!!! who releases alignmentModel? does this? review |
427 rm->setAlignment({}); | 421 other->setAlignment({}); |
428 delete process; | 422 delete process; |
429 } | 423 } |
430 | 424 |
431 return success; | 425 return success; |
432 } | 426 } |
480 | 474 |
481 //!!! to use ById? | 475 //!!! to use ById? |
482 | 476 |
483 Model *csvOutput = reader.load(); | 477 Model *csvOutput = reader.load(); |
484 | 478 |
485 SparseTimeValueModel *path = qobject_cast<SparseTimeValueModel *>(csvOutput); | 479 SparseTimeValueModel *path = |
480 qobject_cast<SparseTimeValueModel *>(csvOutput); | |
486 if (!path) { | 481 if (!path) { |
487 SVCERR << "ERROR: Align::alignmentProgramFinished: Output did not convert to sparse time-value model" | 482 SVCERR << "ERROR: Align::alignmentProgramFinished: Output did not convert to sparse time-value model" |
488 << endl; | 483 << endl; |
489 alignmentModel->setError | 484 alignmentModel->setError |
490 ("Output of program did not produce sparse time-value model"); | 485 ("Output of program did not produce sparse time-value model"); |
502 } | 497 } |
503 | 498 |
504 SVCERR << "Align::alignmentProgramFinished: Setting alignment path (" | 499 SVCERR << "Align::alignmentProgramFinished: Setting alignment path (" |
505 << path->getEventCount() << " point(s))" << endl; | 500 << path->getEventCount() << " point(s))" << endl; |
506 | 501 |
507 ModelById::add(std::shared_ptr<SparseTimeValueModel>(path)); | 502 auto pathId = |
508 alignmentModel->setPathFrom(path->getId()); | 503 ModelById::add(std::shared_ptr<SparseTimeValueModel>(path)); |
504 alignmentModel->setPathFrom(pathId); | |
509 | 505 |
510 emit alignmentComplete(alignmentModelId); | 506 emit alignmentComplete(alignmentModelId); |
507 | |
508 ModelById::release(pathId); | |
511 | 509 |
512 } else { | 510 } else { |
513 SVCERR << "ERROR: Align::alignmentProgramFinished: Aligner program " | 511 SVCERR << "ERROR: Align::alignmentProgramFinished: Aligner program " |
514 << "failed: exit code " << exitCode << ", status " << status | 512 << "failed: exit code " << exitCode << ", status " << status |
515 << endl; | 513 << endl; |