comparison align/ExternalProgramAligner.cpp @ 778:83a7b10b7415

Merge from branch pitch-align
author Chris Cannam
date Fri, 26 Jun 2020 13:48:52 +0100
parents 699b5b130ea2
children 5de2b710cfae
comparison
equal deleted inserted replaced
774:7bded7599874 778:83a7b10b7415
37 { 37 {
38 } 38 }
39 39
40 ExternalProgramAligner::~ExternalProgramAligner() 40 ExternalProgramAligner::~ExternalProgramAligner()
41 { 41 {
42 if (m_process) {
43 disconnect(m_process, nullptr, this, nullptr);
44 }
45
42 delete m_process; 46 delete m_process;
43 } 47 }
44 48
45 bool 49 bool
46 ExternalProgramAligner::isAvailable(QString program) 50 ExternalProgramAligner::isAvailable(QString program)
61 if (!reference || !other) { 65 if (!reference || !other) {
62 SVCERR << "ERROR: ExternalProgramAligner: Can't align non-read-only models via program (no local filename available)" << endl; 66 SVCERR << "ERROR: ExternalProgramAligner: Can't align non-read-only models via program (no local filename available)" << endl;
63 return; 67 return;
64 } 68 }
65 69
70 if (m_program == "") {
71 emit failed(m_toAlign, tr("No external program specified"));
72 return;
73 }
74
66 while (!reference->isReady(nullptr) || !other->isReady(nullptr)) { 75 while (!reference->isReady(nullptr) || !other->isReady(nullptr)) {
67 qApp->processEvents(); 76 qApp->processEvents();
68 } 77 }
69 78
70 QString refPath = reference->getLocalFilename(); 79 QString refPath = reference->getLocalFilename();
112 bool success = m_process->waitForStarted(); 121 bool success = m_process->waitForStarted();
113 122
114 if (!success) { 123 if (!success) {
115 124
116 SVCERR << "ERROR: ExternalProgramAligner: Program did not start" << endl; 125 SVCERR << "ERROR: ExternalProgramAligner: Program did not start" << endl;
117 emit failed(m_toAlign, 126
118 tr("Alignment program \"%1\" did not start")
119 .arg(m_program));
120
121 other->setAlignment({}); 127 other->setAlignment({});
122 ModelById::release(m_alignmentModel); 128 ModelById::release(m_alignmentModel);
123 delete m_process; 129 delete m_process;
124 m_process = nullptr; 130 m_process = nullptr;
131
132 emit failed(m_toAlign,
133 tr("Alignment program \"%1\" did not start")
134 .arg(m_program));
125 135
126 } else { 136 } else {
137 alignmentModel->setCompletion(10);
127 m_document->addNonDerivedModel(m_alignmentModel); 138 m_document->addNonDerivedModel(m_alignmentModel);
128 } 139 }
129 } 140 }
130 141
131 void 142 void
132 ExternalProgramAligner::programFinished(int exitCode, QProcess::ExitStatus status) 143 ExternalProgramAligner::programFinished(int exitCode,
144 QProcess::ExitStatus status)
133 { 145 {
134 SVCERR << "ExternalProgramAligner::programFinished" << endl; 146 SVCERR << "ExternalProgramAligner::programFinished" << endl;
135 147
136 QProcess *process = qobject_cast<QProcess *>(sender()); 148 QProcess *process = qobject_cast<QProcess *>(sender());
137 149
145 if (!alignmentModel) { 157 if (!alignmentModel) {
146 SVCERR << "ExternalProgramAligner: AlignmentModel no longer exists" 158 SVCERR << "ExternalProgramAligner: AlignmentModel no longer exists"
147 << endl; 159 << endl;
148 return; 160 return;
149 } 161 }
162
163 QString errorText;
150 164
151 if (exitCode == 0 && status == 0) { 165 if (exitCode == 0 && status == 0) {
152 166
153 CSVFormat format; 167 CSVFormat format;
154 format.setModelType(CSVFormat::TwoDimensionalModel); 168 format.setModelType(CSVFormat::TwoDimensionalModel);
168 182
169 CSVFileReader reader(process, format, alignmentModel->getSampleRate()); 183 CSVFileReader reader(process, format, alignmentModel->getSampleRate());
170 if (!reader.isOK()) { 184 if (!reader.isOK()) {
171 SVCERR << "ERROR: ExternalProgramAligner: Failed to parse output" 185 SVCERR << "ERROR: ExternalProgramAligner: Failed to parse output"
172 << endl; 186 << endl;
173 QString error = tr("Failed to parse output of program: %1") 187 errorText = tr("Failed to parse output of program: %1")
174 .arg(reader.getError()); 188 .arg(reader.getError());
175 alignmentModel->setError(error); 189 alignmentModel->setError(errorText);
176 emit failed(m_toAlign, error);
177 goto done; 190 goto done;
178 } 191 }
179 192
180 //!!! to use ById? 193 //!!! to use ById?
181 194
184 SparseTimeValueModel *path = 197 SparseTimeValueModel *path =
185 qobject_cast<SparseTimeValueModel *>(csvOutput); 198 qobject_cast<SparseTimeValueModel *>(csvOutput);
186 if (!path) { 199 if (!path) {
187 SVCERR << "ERROR: ExternalProgramAligner: Output did not convert to sparse time-value model" 200 SVCERR << "ERROR: ExternalProgramAligner: Output did not convert to sparse time-value model"
188 << endl; 201 << endl;
189 QString error = 202 errorText =
190 tr("Output of alignment program was not in the proper format"); 203 tr("Output of alignment program was not in the proper format");
191 alignmentModel->setError(error); 204 alignmentModel->setError(errorText);
192 delete csvOutput; 205 delete csvOutput;
193 emit failed(m_toAlign, error);
194 goto done; 206 goto done;
195 } 207 }
196 208
197 if (path->isEmpty()) { 209 if (path->isEmpty()) {
198 SVCERR << "ERROR: ExternalProgramAligner: Output contained no mappings" 210 SVCERR << "ERROR: ExternalProgramAligner: Output contained no mappings"
199 << endl; 211 << endl;
200 QString error = 212 errorText =
201 tr("Output of alignment program contained no mappings"); 213 tr("Output of alignment program contained no mappings");
202 alignmentModel->setError(error); 214 alignmentModel->setError(errorText);
203 delete path; 215 delete path;
204 emit failed(m_toAlign, error);
205 goto done; 216 goto done;
206 } 217 }
207 218
208 SVCERR << "ExternalProgramAligner: Setting alignment path (" 219 SVCERR << "ExternalProgramAligner: Setting alignment path ("
209 << path->getEventCount() << " point(s))" << endl; 220 << path->getEventCount() << " point(s))" << endl;
210 221
211 auto pathId = 222 auto pathId =
212 ModelById::add(std::shared_ptr<SparseTimeValueModel>(path)); 223 ModelById::add(std::shared_ptr<SparseTimeValueModel>(path));
213 alignmentModel->setPathFrom(pathId); 224 alignmentModel->setPathFrom(pathId);
214 225 alignmentModel->setCompletion(100);
215 emit complete(m_alignmentModel);
216 226
217 ModelById::release(pathId); 227 ModelById::release(pathId);
218 228
219 } else { 229 } else {
220 SVCERR << "ERROR: ExternalProgramAligner: Aligner program " 230 SVCERR << "ERROR: ExternalProgramAligner: Aligner program "
221 << "failed: exit code " << exitCode << ", status " << status 231 << "failed: exit code " << exitCode << ", status " << status
222 << endl; 232 << endl;
223 QString error = tr("Aligner process returned non-zero exit status"); 233 errorText = tr("Aligner process returned non-zero exit status");
224 alignmentModel->setError(error); 234 alignmentModel->setError(errorText);
225 emit failed(m_toAlign, error);
226 } 235 }
227 236
228 done: 237 done:
229 delete m_process; 238 delete m_process;
230 m_process = nullptr; 239 m_process = nullptr;
231 } 240
241 // "This should be emitted as the last thing the aligner does, as
242 // the recipient may delete the aligner during the call."
243 if (errorText == "") {
244 emit complete(m_alignmentModel);
245 } else {
246 emit failed(m_toAlign, errorText);
247 }
248 }