Mercurial > hg > svapp
diff 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 |
line wrap: on
line diff
--- a/framework/Align.cpp Tue Jul 02 21:10:25 2019 +0100 +++ b/framework/Align.cpp Wed Jul 03 13:01:26 2019 +0100 @@ -33,7 +33,7 @@ #include <QApplication> bool -Align::alignModel(Document *doc, Model *ref, Model *other, QString &error) +Align::alignModel(Document *doc, ModelId ref, ModelId other, QString &error) { QSettings settings; settings.beginGroup("Preferences"); @@ -89,18 +89,14 @@ } bool -Align::alignModelViaTransform(Document *doc, Model *ref, Model *other, +Align::alignModelViaTransform(Document *doc, ModelId ref, ModelId other, QString &error) { QMutexLocker locker (&m_mutex); - - RangeSummarisableTimeValueModel *reference = qobject_cast - <RangeSummarisableTimeValueModel *>(ref); - - RangeSummarisableTimeValueModel *rm = qobject_cast - <RangeSummarisableTimeValueModel *>(other); - if (!reference || !rm) return false; // but this should have been tested already + auto reference = ModelById::getAs<RangeSummarisableTimeValueModel>(ref); + auto rm = ModelById::getAs<RangeSummarisableTimeValueModel>(other); + if (!reference || !rm) return false; // This involves creating either three or four new models: // @@ -130,6 +126,7 @@ // is attached to the new model we are aligning, which also takes // ownership of it. The only one of these models that we need to // delete here is the SparseTimeValueModel [2a]. + //!!! todo: review the above, especially management of AlignmentModel // // (We also create a sneaky additional SparseTimeValueModel // temporarily so we can attach completion information to it - @@ -144,21 +141,24 @@ components.push_back(AggregateWaveModel::ModelChannelSpec (rm->getId(), -1)); - AggregateWaveModel *aggregateModel = new AggregateWaveModel(components); - doc->addAggregateModel(aggregateModel); + auto aggregateModel = std::make_shared<AggregateWaveModel>(components); + ModelById::add(aggregateModel); + doc->addAggregateModel(aggregateModel->getId()); - AlignmentModel *alignmentModel = - new AlignmentModel(reference, other, nullptr); + auto alignmentModel = std::make_shared<AlignmentModel>(ref, other, + ModelId()); + ModelById::add(alignmentModel); TransformId tdId = getTuningDifferenceTransformName(); if (tdId == "") { - if (beginTransformDrivenAlignment(aggregateModel, alignmentModel)) { - rm->setAlignment(alignmentModel); + if (beginTransformDrivenAlignment(aggregateModel->getId(), + alignmentModel->getId())) { + rm->setAlignment(alignmentModel->getId()); } else { error = alignmentModel->getError(); - delete alignmentModel; + ModelById::release(alignmentModel); return false; } @@ -181,82 +181,76 @@ ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); QString message; - Model *transformOutput = mtf->transform(transform, aggregateModel, message); + ModelId transformOutput = mtf->transform(transform, + aggregateModel->getId(), + message); - SparseTimeValueModel *tdout = dynamic_cast<SparseTimeValueModel *> - (transformOutput); - + auto tdout = ModelById::getAs<SparseTimeValueModel>(transformOutput); if (!tdout) { SVCERR << "Align::alignModel: ERROR: Failed to create tuning-difference output model (no Tuning Difference plugin?)" << endl; - delete tdout; error = message; return false; } - rm->setAlignment(alignmentModel); + rm->setAlignment(alignmentModel->getId()); - connect(tdout, SIGNAL(completionChanged()), + connect(tdout.get(), SIGNAL(completionChanged()), this, SLOT(tuningDifferenceCompletionChanged())); TuningDiffRec rec; - rec.input = aggregateModel; - rec.alignment = alignmentModel; - - connect(aggregateModel, SIGNAL(aboutToBeDeleted()), - this, SLOT(aggregateModelAboutToBeDeleted())); + rec.input = aggregateModel->getId(); + rec.alignment = alignmentModel->getId(); // This model exists only so that the AlignmentModel can get a // completion value from somewhere while the tuning difference // calculation is going on - rec.preparatory = new SparseTimeValueModel - (aggregateModel->getSampleRate(), 1);; - rec.preparatory->setCompletion(0); + auto preparatoryModel = std::make_shared<SparseTimeValueModel> + (aggregateModel->getSampleRate(), 1); + ModelById::add(preparatoryModel); + preparatoryModel->setCompletion(0); + rec.preparatory = preparatoryModel->getId(); alignmentModel->setPathFrom(rec.preparatory); - m_pendingTuningDiffs[tdout] = rec; + m_pendingTuningDiffs[transformOutput] = rec; } return true; } void -Align::aggregateModelAboutToBeDeleted() -{ - SVCERR << "Align::aggregateModelAboutToBeDeleted" << endl; - - QObject *s = sender(); - AggregateWaveModel *awm = qobject_cast<AggregateWaveModel *>(s); - if (!awm) return; - QMutexLocker locker(&m_mutex); - - SVCERR << "Align::aggregateModelAboutToBeDeleted: awm = " << awm - << endl; - - for (const auto &p : m_pendingTuningDiffs) { - if (p.second.input == awm) { - SVCERR << "we have a record of this, getting rid of it" << endl; - m_pendingTuningDiffs.erase(p.first); - return; - } - } -} - -void Align::tuningDifferenceCompletionChanged() { QMutexLocker locker (&m_mutex); - - SparseTimeValueModel *td = qobject_cast<SparseTimeValueModel *>(sender()); - if (!td) return; - if (m_pendingTuningDiffs.find(td) == m_pendingTuningDiffs.end()) { - SVCERR << "ERROR: Align::tuningDifferenceCompletionChanged: Model " - << td << " not found in pending tuning diff map!" << endl; + ModelId tdId; + if (Model *modelPtr = qobject_cast<Model *>(sender())) { + tdId = modelPtr->getId(); + } else { return; } - TuningDiffRec rec = m_pendingTuningDiffs[td]; + if (m_pendingTuningDiffs.find(tdId) == m_pendingTuningDiffs.end()) { + SVCERR << "ERROR: Align::tuningDifferenceCompletionChanged: Model " + << tdId << " not found in pending tuning diff map!" << endl; + return; + } + auto td = ModelById::getAs<SparseTimeValueModel>(tdId); + if (!td) { + SVCERR << "WARNING: Align::tuningDifferenceCompletionChanged: Model " + << tdId << " not known as SparseTimeValueModel" << endl; + return; + } + + TuningDiffRec rec = m_pendingTuningDiffs[tdId]; + + auto alignment = ModelById::getAs<AlignmentModel>(rec.alignment); + if (!alignment) { + SVCERR << "WARNING: Align::tuningDifferenceCompletionChanged:" + << "alignment model has disappeared" << endl; + return; + } + int completion = 0; bool done = td->isReady(&completion); @@ -269,7 +263,11 @@ // calculating the actual path in the following phase int clamped = (completion == 100 ? 99 : completion); // SVCERR << "Align::tuningDifferenceCompletionChanged: setting rec.preparatory completion to " << clamped << endl; - rec.preparatory->setCompletion(clamped); + auto preparatory = ModelById::getAs<SparseTimeValueModel> + (rec.preparatory); + if (preparatory) { + preparatory->setCompletion(clamped); + } return; } @@ -282,25 +280,32 @@ SVCERR << "Align::tuningDifferenceCompletionChanged: No tuning frequency reported" << endl; } - m_pendingTuningDiffs.erase(td); - td->aboutToDelete(); - delete td; - - rec.alignment->setPathFrom(nullptr); + m_pendingTuningDiffs.erase(tdId); + ModelById::release(tdId); + + alignment->setPathFrom({}); beginTransformDrivenAlignment (rec.input, rec.alignment, tuningFrequency); } bool -Align::beginTransformDrivenAlignment(AggregateWaveModel *aggregateModel, - AlignmentModel *alignmentModel, +Align::beginTransformDrivenAlignment(ModelId aggregateModelId, + ModelId alignmentModelId, float tuningFrequency) { TransformId id = getAlignmentTransformName(); TransformFactory *tf = TransformFactory::getInstance(); + auto aggregateModel = ModelById::getAs<AggregateWaveModel>(aggregateModelId); + auto alignmentModel = ModelById::getAs<AlignmentModel>(alignmentModelId); + + if (!aggregateModel || !alignmentModel) { + SVCERR << "Align::alignModel: ERROR: One or other of the aggregate & alignment models has disappeared" << endl; + return false; + } + Transform transform = tf->getDefaultTransformFor (id, aggregateModel->getSampleRate()); @@ -317,32 +322,31 @@ ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); QString message; - Model *transformOutput = mtf->transform - (transform, aggregateModel, message); + ModelId transformOutput = mtf->transform + (transform, aggregateModelId, message); - if (!transformOutput) { + if (transformOutput.isNone()) { transform.setStepSize(0); transformOutput = mtf->transform - (transform, aggregateModel, message); + (transform, aggregateModelId, message); } - SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *> - (transformOutput); + auto path = ModelById::getAs<SparseTimeValueModel>(transformOutput); //!!! callers will need to be updated to get error from //!!! alignment model after initial call if (!path) { SVCERR << "Align::alignModel: ERROR: Failed to create alignment path (no MATCH plugin?)" << endl; - delete transformOutput; + ModelById::release(transformOutput); alignmentModel->setError(message); return false; } path->setCompletion(0); - alignmentModel->setPathFrom(path); + alignmentModel->setPathFrom(transformOutput); //!!! who releases transformOutput? - connect(alignmentModel, SIGNAL(completionChanged()), + connect(alignmentModel.get(), SIGNAL(completionChanged()), this, SLOT(alignmentCompletionChanged())); return true; @@ -352,28 +356,27 @@ Align::alignmentCompletionChanged() { QMutexLocker locker (&m_mutex); - - AlignmentModel *am = qobject_cast<AlignmentModel *>(sender()); - if (!am) return; - if (am->isReady()) { - disconnect(am, SIGNAL(completionChanged()), - this, SLOT(alignmentCompletionChanged())); - emit alignmentComplete(am); + + if (AlignmentModel *amPtr = qobject_cast<AlignmentModel *>(sender())) { + + auto am = ModelById::getAs<AlignmentModel>(amPtr->getId()); + if (am && am->isReady()) { + disconnect(am.get(), SIGNAL(completionChanged()), + this, SLOT(alignmentCompletionChanged())); + emit alignmentComplete(am->getId()); + } } } bool -Align::alignModelViaProgram(Document *, Model *ref, Model *other, +Align::alignModelViaProgram(Document *, ModelId ref, ModelId other, QString program, QString &error) { QMutexLocker locker (&m_mutex); - - WaveFileModel *reference = qobject_cast<WaveFileModel *>(ref); - WaveFileModel *rm = qobject_cast<WaveFileModel *>(other); - if (!reference || !rm) { - return false; // but this should have been tested already - } + auto reference = ModelById::getAs<RangeSummarisableTimeValueModel>(ref); + auto rm = ModelById::getAs<RangeSummarisableTimeValueModel>(other); + if (!reference || !rm) return false; while (!reference->isReady(nullptr) || !rm->isReady(nullptr)) { qApp->processEvents(); @@ -383,8 +386,8 @@ // model's audio file and the new model's audio file. It returns // the path in CSV form through stdout. - ReadOnlyWaveFileModel *roref = qobject_cast<ReadOnlyWaveFileModel *>(reference); - ReadOnlyWaveFileModel *rorm = qobject_cast<ReadOnlyWaveFileModel *>(rm); + auto roref = ModelById::getAs<ReadOnlyWaveFileModel>(ref); + auto rorm = ModelById::getAs<ReadOnlyWaveFileModel>(other); if (!roref || !rorm) { SVCERR << "ERROR: Align::alignModelViaProgram: Can't align non-read-only models via program (no local filename available)" << endl; return false; @@ -398,9 +401,10 @@ return false; } - AlignmentModel *alignmentModel = - new AlignmentModel(reference, other, nullptr); - rm->setAlignment(alignmentModel); + auto alignmentModel = std::make_shared<AlignmentModel>(ref, other, + ModelId()); + ModelById::add(alignmentModel); + rm->setAlignment(alignmentModel->getId()); QProcess *process = new QProcess; QStringList args; @@ -409,7 +413,7 @@ connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(alignmentProgramFinished(int, QProcess::ExitStatus))); - m_pendingProcesses[process] = alignmentModel; + m_pendingProcesses[process] = alignmentModel->getId(); process->start(program, args); bool success = process->waitForStarted(); @@ -419,7 +423,8 @@ << endl; error = "Alignment program could not be started"; m_pendingProcesses.erase(process); - rm->setAlignment(nullptr); // deletes alignmentModel as well + //!!! who releases alignmentModel? does this? review + rm->setAlignment({}); delete process; } @@ -441,7 +446,9 @@ return; } - AlignmentModel *alignmentModel = m_pendingProcesses[process]; + ModelId alignmentModelId = m_pendingProcesses[process]; + auto alignmentModel = ModelById::getAs<AlignmentModel>(alignmentModelId); + if (!alignmentModel) return; if (exitCode == 0 && status == 0) { @@ -471,6 +478,8 @@ goto done; } + //!!! to use ById? + Model *csvOutput = reader.load(); SparseTimeValueModel *path = qobject_cast<SparseTimeValueModel *>(csvOutput); @@ -479,23 +488,26 @@ << endl; alignmentModel->setError ("Output of program did not produce sparse time-value model"); + delete csvOutput; goto done; } - + if (path->isEmpty()) { SVCERR << "ERROR: Align::alignmentProgramFinished: Output contained no mappings" << endl; alignmentModel->setError ("Output of alignment program contained no mappings"); + delete path; goto done; } SVCERR << "Align::alignmentProgramFinished: Setting alignment path (" << path->getEventCount() << " point(s))" << endl; - alignmentModel->setPathFrom(path); + ModelById::add(std::shared_ptr<SparseTimeValueModel>(path)); + alignmentModel->setPathFrom(path->getId()); - emit alignmentComplete(alignmentModel); + emit alignmentComplete(alignmentModelId); } else { SVCERR << "ERROR: Align::alignmentProgramFinished: Aligner program "