changeset 769:a316cb6fed81 pitch-align

Fixes to notification and completion in aligners
author Chris Cannam
date Thu, 28 May 2020 17:04:36 +0100
parents 1b1960009be6
children 486add472c3f
files align/Aligner.h align/ExternalProgramAligner.cpp align/TransformAligner.cpp align/TransformDTWAligner.cpp
diffstat 4 files changed, 77 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/align/Aligner.h	Fri May 22 17:17:44 2020 +0100
+++ b/align/Aligner.h	Thu May 28 17:04:36 2020 +0100
@@ -32,12 +32,16 @@
 signals:
     /**
      * Emitted when alignment is successfully completed. The reference
-     * and toAlign models can be queried from the alignment model.
+     * and toAlign models can be queried from the alignment
+     * model. This should be emitted as the last thing the aligner
+     * does, as the recipient may delete the aligner during the call.
      */
     void complete(ModelId alignmentModel); // an AlignmentModel
 
     /**
-     * Emitted when alignment fails.
+     * Emitted when alignment fails. This should be emitted as the
+     * last thing the aligner does, as the recipient may delete the
+     * aligner during the call.
      */
     void failed(ModelId toAlign, QString errorText); // the toAlign model
 };
--- a/align/ExternalProgramAligner.cpp	Fri May 22 17:17:44 2020 +0100
+++ b/align/ExternalProgramAligner.cpp	Thu May 28 17:04:36 2020 +0100
@@ -63,6 +63,11 @@
         return;
     }
 
+    if (m_program == "") {
+        emit failed(m_toAlign, tr("No external program specified"));
+        return;
+    }
+
     while (!reference->isReady(nullptr) || !other->isReady(nullptr)) {
         qApp->processEvents();
     }
@@ -114,22 +119,25 @@
     if (!success) {
         
         SVCERR << "ERROR: ExternalProgramAligner: Program did not start" << endl;
+
+        other->setAlignment({});
+        ModelById::release(m_alignmentModel);
+        delete m_process;
+        m_process = nullptr;
+
         emit failed(m_toAlign,
                     tr("Alignment program \"%1\" did not start")
                     .arg(m_program));
         
-        other->setAlignment({});
-        ModelById::release(m_alignmentModel);
-        delete m_process;
-        m_process = nullptr;
-        
     } else {
+        alignmentModel->setCompletion(10);
         m_document->addNonDerivedModel(m_alignmentModel);
     }
 }
 
 void
-ExternalProgramAligner::programFinished(int  exitCode, QProcess::ExitStatus status)
+ExternalProgramAligner::programFinished(int exitCode,
+                                        QProcess::ExitStatus status)
 {
     SVCERR << "ExternalProgramAligner::programFinished" << endl;
     
@@ -147,6 +155,8 @@
                << endl;
         return;
     }
+
+    QString errorText;
     
     if (exitCode == 0 && status == 0) {
 
@@ -170,10 +180,9 @@
         if (!reader.isOK()) {
             SVCERR << "ERROR: ExternalProgramAligner: Failed to parse output"
                    << endl;
-            QString error = tr("Failed to parse output of program: %1")
+            errorText = tr("Failed to parse output of program: %1")
                 .arg(reader.getError());
-            alignmentModel->setError(error);
-            emit failed(m_toAlign, error);
+            alignmentModel->setError(errorText);
             goto done;
         }
 
@@ -186,22 +195,20 @@
         if (!path) {
             SVCERR << "ERROR: ExternalProgramAligner: Output did not convert to sparse time-value model"
                    << endl;
-            QString error =
+            errorText =
                 tr("Output of alignment program was not in the proper format");
-            alignmentModel->setError(error);
+            alignmentModel->setError(errorText);
             delete csvOutput;
-            emit failed(m_toAlign, error);
             goto done;
         }
                        
         if (path->isEmpty()) {
             SVCERR << "ERROR: ExternalProgramAligner: Output contained no mappings"
                    << endl;
-            QString error = 
+            errorText = 
                 tr("Output of alignment program contained no mappings");
-            alignmentModel->setError(error);
+            alignmentModel->setError(errorText);
             delete path;
-            emit failed(m_toAlign, error);
             goto done;
         }
 
@@ -211,8 +218,7 @@
         auto pathId =
             ModelById::add(std::shared_ptr<SparseTimeValueModel>(path));
         alignmentModel->setPathFrom(pathId);
-
-        emit complete(m_alignmentModel);
+        alignmentModel->setCompletion(100);
 
         ModelById::release(pathId);
         
@@ -220,12 +226,19 @@
         SVCERR << "ERROR: ExternalProgramAligner: Aligner program "
                << "failed: exit code " << exitCode << ", status " << status
                << endl;
-        QString error = tr("Aligner process returned non-zero exit status");
-        alignmentModel->setError(error);
-        emit failed(m_toAlign, error);
+        errorText = tr("Aligner process returned non-zero exit status");
+        alignmentModel->setError(errorText);
     }
 
 done:
     delete m_process;
     m_process = nullptr;
+
+    // "This should be emitted as the last thing the aligner does, as
+    // the recipient may delete the aligner during the call."
+    if (errorText == "") {
+        emit complete(m_alignmentModel);
+    } else {
+        emit failed(m_toAlign, errorText);
+    }
 }
--- a/align/TransformAligner.cpp	Fri May 22 17:17:44 2020 +0100
+++ b/align/TransformAligner.cpp	Thu May 28 17:04:36 2020 +0100
@@ -244,11 +244,8 @@
     
     if (!done) {
         // This will be the completion the alignment model reports,
-        // before the alignment actually begins. It goes up from 0 to
-        // 99 (not 100!) and then back to 0 again when we start
-        // calculating the actual path in the following phase
-        int clamped = (completion == 100 ? 99 : completion);
-        alignmentModel->setCompletion(clamped);
+        // before the alignment actually begins
+        alignmentModel->setCompletion(completion / 2);
         return;
     }
 
@@ -344,35 +341,55 @@
     pathOutputModel->setCompletion(0);
     alignmentModel->setPathFrom(m_pathOutputModel);
 
-    connect(alignmentModel.get(), SIGNAL(completionChanged(ModelId)),
+    connect(pathOutputModel.get(), SIGNAL(completionChanged(ModelId)),
             this, SLOT(alignmentCompletionChanged(ModelId)));
 
     return true;
 }
 
 void
-TransformAligner::alignmentCompletionChanged(ModelId alignmentModelId)
+TransformAligner::alignmentCompletionChanged(ModelId pathOutputModelId)
 {
-    if (alignmentModelId != m_alignmentModel) {
+    if (pathOutputModelId != m_pathOutputModel) {
         SVCERR << "WARNING: TransformAligner::alignmentCompletionChanged: Model "
-               << alignmentModelId
+               << pathOutputModelId
                << " is not ours! (ours is "
-               << m_alignmentModel << ")" << endl;
+               << m_pathOutputModel << ")" << endl;
         return;
     }
 
-    auto alignmentModel = ModelById::getAs<AlignmentModel>(m_alignmentModel);
+    auto pathOutputModel =
+        ModelById::getAs<SparseTimeValueModel>(m_pathOutputModel);
+    if (!pathOutputModel) {
+        SVCERR << "WARNING: TransformAligner::alignmentCompletionChanged: Path output model "
+               << m_pathOutputModel << " no longer exists" << endl;
+        return;
+    }
+        
+    int completion = 0;
+    bool done = pathOutputModel->isReady(&completion);
 
-    if (alignmentModel && alignmentModel->isReady()) {
+    if (m_withTuningDifference) {
+        if (auto alignmentModel =
+            ModelById::getAs<AlignmentModel>(m_alignmentModel)) {
+            if (!done) {
+                int adjustedCompletion = 50 + completion/2;
+                if (adjustedCompletion > 99) {
+                    adjustedCompletion = 99;
+                }
+                alignmentModel->setCompletion(adjustedCompletion);
+            } else {
+                alignmentModel->setCompletion(100);
+            }
+        }
+    }
 
+    if (done) {
         m_incomplete = false;
         
         ModelById::release(m_pathOutputModel);
         m_pathOutputModel = {};
 
-        disconnect(alignmentModel.get(),
-                   SIGNAL(completionChanged(ModelId)),
-                   this, SLOT(alignmentCompletionChanged(ModelId)));
         emit complete(m_alignmentModel);
     }
 }
--- a/align/TransformDTWAligner.cpp	Fri May 22 17:17:44 2020 +0100
+++ b/align/TransformDTWAligner.cpp	Thu May 28 17:04:36 2020 +0100
@@ -241,7 +241,7 @@
         }
     }
 
-    SVCERR << "TransformDTWAligner[" << this << "]: performAlignment: "
+    SVCERR << "TransformDTWAligner[" << this << "]: performAlignmentMagnitude: "
            << "Have " << s1.size() << " events from reference, "
            << s2.size() << " from toAlign" << endl;
 
@@ -257,7 +257,7 @@
         alignment = dtw.alignSeries(s1, s2);
     }
 
-    SVCERR << "TransformDTWAligner[" << this << "]: performAlignment: "
+    SVCERR << "TransformDTWAligner[" << this << "]: performAlignmentMagnitude: "
            << "DTW produced " << alignment.size() << " points:" << endl;
     for (int i = 0; i < alignment.size() && i < 100; ++i) {
         SVCERR << alignment[i] << " ";
@@ -278,7 +278,7 @@
 
     alignmentModel->setPath(path);
 
-    SVCERR << "TransformDTWAligner[" << this << "]: performAlignment: Done"
+    SVCERR << "TransformDTWAligner[" << this << "]: performAlignmentMagnitude: Done"
            << endl;
 
     m_incomplete = false;
@@ -327,7 +327,7 @@
     vector<RiseFallDTW::Value> s2 =
         convertEvents(toAlignOutputSTVM->getAllEvents());
 
-    SVCERR << "TransformDTWAligner[" << this << "]: performAlignment: "
+    SVCERR << "TransformDTWAligner[" << this << "]: performAlignmentRiseFall: "
            << "Have " << s1.size() << " events from reference, "
            << s2.size() << " from toAlign" << endl;
 
@@ -344,7 +344,7 @@
         alignment = dtw.alignSeries(s1, s2);
     }
 
-    SVCERR << "TransformDTWAligner[" << this << "]: performAlignment: "
+    SVCERR << "TransformDTWAligner[" << this << "]: performAlignmentRiseFall: "
            << "DTW produced " << alignment.size() << " points:" << endl;
     for (int i = 0; i < alignment.size() && i < 100; ++i) {
         SVCERR << alignment[i] << " ";
@@ -365,7 +365,7 @@
 
     alignmentModel->setPath(path);
 
-    SVCERR << "TransformDTWAligner[" << this << "]: performAlignment: Done"
+    SVCERR << "TransformDTWAligner[" << this << "]: performAlignmentRiseFall: Done"
            << endl;
 
     m_incomplete = false;