comparison align/ExternalProgramAligner.cpp @ 761:6429a164b7e1 pitch-align

Schedule alignments with a small delay to avoid too much UI unresponsiveness. Also overhaul error reporting to use signals throughout.
author Chris Cannam
date Wed, 06 May 2020 11:45:27 +0100
parents 32654e402f8b
children a316cb6fed81
comparison
equal deleted inserted replaced
757:f32df46d0c84 761:6429a164b7e1
47 { 47 {
48 QFileInfo file(program); 48 QFileInfo file(program);
49 return file.exists() && file.isExecutable(); 49 return file.exists() && file.isExecutable();
50 } 50 }
51 51
52 bool 52 void
53 ExternalProgramAligner::begin(QString &error) 53 ExternalProgramAligner::begin()
54 { 54 {
55 // Run an external program, passing to it paths to the main 55 // Run an external program, passing to it paths to the main
56 // model's audio file and the new model's audio file. It returns 56 // model's audio file and the new model's audio file. It returns
57 // the path in CSV form through stdout. 57 // the path in CSV form through stdout.
58 58
59 auto reference = ModelById::getAs<ReadOnlyWaveFileModel>(m_reference); 59 auto reference = ModelById::getAs<ReadOnlyWaveFileModel>(m_reference);
60 auto other = ModelById::getAs<ReadOnlyWaveFileModel>(m_toAlign); 60 auto other = ModelById::getAs<ReadOnlyWaveFileModel>(m_toAlign);
61 if (!reference || !other) { 61 if (!reference || !other) {
62 SVCERR << "ERROR: ExternalProgramAligner: Can't align non-read-only models via program (no local filename available)" << endl; 62 SVCERR << "ERROR: ExternalProgramAligner: Can't align non-read-only models via program (no local filename available)" << endl;
63 return false; 63 return;
64 } 64 }
65 65
66 while (!reference->isReady(nullptr) || !other->isReady(nullptr)) { 66 while (!reference->isReady(nullptr) || !other->isReady(nullptr)) {
67 qApp->processEvents(); 67 qApp->processEvents();
68 } 68 }
76 if (otherPath == "") { 76 if (otherPath == "") {
77 otherPath = FileSource(other->getLocation()).getLocalFilename(); 77 otherPath = FileSource(other->getLocation()).getLocalFilename();
78 } 78 }
79 79
80 if (refPath == "" || otherPath == "") { 80 if (refPath == "" || otherPath == "") {
81 error = "Failed to find local filepath for wave-file model"; 81 emit failed(m_toAlign,
82 return false; 82 tr("Failed to find local filepath for wave-file model"));
83 return;
83 } 84 }
84 85
85 auto alignmentModel = 86 auto alignmentModel =
86 std::make_shared<AlignmentModel>(m_reference, m_toAlign, ModelId()); 87 std::make_shared<AlignmentModel>(m_reference, m_toAlign, ModelId());
87 88
111 bool success = m_process->waitForStarted(); 112 bool success = m_process->waitForStarted();
112 113
113 if (!success) { 114 if (!success) {
114 115
115 SVCERR << "ERROR: ExternalProgramAligner: Program did not start" << endl; 116 SVCERR << "ERROR: ExternalProgramAligner: Program did not start" << endl;
116 error = "Alignment program \"" + m_program + "\" did not start"; 117 emit failed(m_toAlign,
118 tr("Alignment program \"%1\" did not start")
119 .arg(m_program));
117 120
118 other->setAlignment({}); 121 other->setAlignment({});
119 ModelById::release(m_alignmentModel); 122 ModelById::release(m_alignmentModel);
120 delete m_process; 123 delete m_process;
121 m_process = nullptr; 124 m_process = nullptr;
122 125
123 } else { 126 } else {
124 m_document->addNonDerivedModel(m_alignmentModel); 127 m_document->addNonDerivedModel(m_alignmentModel);
125 } 128 }
126
127 return success;
128 } 129 }
129 130
130 void 131 void
131 ExternalProgramAligner::programFinished(int exitCode, QProcess::ExitStatus status) 132 ExternalProgramAligner::programFinished(int exitCode, QProcess::ExitStatus status)
132 { 133 {
167 168
168 CSVFileReader reader(process, format, alignmentModel->getSampleRate()); 169 CSVFileReader reader(process, format, alignmentModel->getSampleRate());
169 if (!reader.isOK()) { 170 if (!reader.isOK()) {
170 SVCERR << "ERROR: ExternalProgramAligner: Failed to parse output" 171 SVCERR << "ERROR: ExternalProgramAligner: Failed to parse output"
171 << endl; 172 << endl;
172 alignmentModel->setError 173 QString error = tr("Failed to parse output of program: %1")
173 (QString("Failed to parse output of program: %1") 174 .arg(reader.getError());
174 .arg(reader.getError())); 175 alignmentModel->setError(error);
176 emit failed(m_toAlign, error);
175 goto done; 177 goto done;
176 } 178 }
177 179
178 //!!! to use ById? 180 //!!! to use ById?
179 181
182 SparseTimeValueModel *path = 184 SparseTimeValueModel *path =
183 qobject_cast<SparseTimeValueModel *>(csvOutput); 185 qobject_cast<SparseTimeValueModel *>(csvOutput);
184 if (!path) { 186 if (!path) {
185 SVCERR << "ERROR: ExternalProgramAligner: Output did not convert to sparse time-value model" 187 SVCERR << "ERROR: ExternalProgramAligner: Output did not convert to sparse time-value model"
186 << endl; 188 << endl;
187 alignmentModel->setError 189 QString error =
188 ("Output of program did not produce sparse time-value model"); 190 tr("Output of alignment program was not in the proper format");
191 alignmentModel->setError(error);
189 delete csvOutput; 192 delete csvOutput;
193 emit failed(m_toAlign, error);
190 goto done; 194 goto done;
191 } 195 }
192 196
193 if (path->isEmpty()) { 197 if (path->isEmpty()) {
194 SVCERR << "ERROR: ExternalProgramAligner: Output contained no mappings" 198 SVCERR << "ERROR: ExternalProgramAligner: Output contained no mappings"
195 << endl; 199 << endl;
196 alignmentModel->setError 200 QString error =
197 ("Output of alignment program contained no mappings"); 201 tr("Output of alignment program contained no mappings");
202 alignmentModel->setError(error);
198 delete path; 203 delete path;
204 emit failed(m_toAlign, error);
199 goto done; 205 goto done;
200 } 206 }
201 207
202 SVCERR << "ExternalProgramAligner: Setting alignment path (" 208 SVCERR << "ExternalProgramAligner: Setting alignment path ("
203 << path->getEventCount() << " point(s))" << endl; 209 << path->getEventCount() << " point(s))" << endl;
212 218
213 } else { 219 } else {
214 SVCERR << "ERROR: ExternalProgramAligner: Aligner program " 220 SVCERR << "ERROR: ExternalProgramAligner: Aligner program "
215 << "failed: exit code " << exitCode << ", status " << status 221 << "failed: exit code " << exitCode << ", status " << status
216 << endl; 222 << endl;
217 alignmentModel->setError 223 QString error = tr("Aligner process returned non-zero exit status");
218 ("Aligner process returned non-zero exit status"); 224 alignmentModel->setError(error);
225 emit failed(m_toAlign, error);
219 } 226 }
220 227
221 done: 228 done:
222 delete m_process; 229 delete m_process;
223 m_process = nullptr; 230 m_process = nullptr;