annotate align/Align.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 39808338e771
children dd742e566e60
rev   line source
Chris@420 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@420 2
Chris@420 3 /*
Chris@420 4 Sonic Visualiser
Chris@420 5 An audio file viewer and annotation editor.
Chris@420 6 Centre for Digital Music, Queen Mary, University of London.
Chris@420 7
Chris@420 8 This program is free software; you can redistribute it and/or
Chris@420 9 modify it under the terms of the GNU General Public License as
Chris@420 10 published by the Free Software Foundation; either version 2 of the
Chris@420 11 License, or (at your option) any later version. See the file
Chris@420 12 COPYING included with this distribution for more information.
Chris@420 13 */
Chris@420 14
Chris@420 15 #include "Align.h"
Chris@753 16 #include "TransformAligner.h"
Chris@753 17 #include "ExternalProgramAligner.h"
Chris@744 18 #include "framework/Document.h"
Chris@420 19
Chris@422 20 #include <QSettings>
Chris@761 21 #include <QTimer>
Chris@422 22
Chris@761 23 void
Chris@753 24 Align::alignModel(Document *doc,
Chris@753 25 ModelId reference,
Chris@761 26 ModelId toAlign)
Chris@761 27 {
Chris@761 28 addAligner(doc, reference, toAlign);
Chris@761 29 m_aligners[toAlign]->begin();
Chris@761 30 }
Chris@761 31
Chris@761 32 void
Chris@761 33 Align::scheduleAlignment(Document *doc,
Chris@761 34 ModelId reference,
Chris@761 35 ModelId toAlign)
Chris@761 36 {
Chris@761 37 addAligner(doc, reference, toAlign);
Chris@761 38 int delay = 500 + 500 * int(m_aligners.size());
Chris@761 39 if (delay > 3500) {
Chris@761 40 delay = 3500;
Chris@761 41 }
Chris@761 42 SVCERR << "Align::scheduleAlignment: delaying " << delay << "ms" << endl;
Chris@761 43 QTimer::singleShot(delay, m_aligners[toAlign].get(), SLOT(begin()));
Chris@761 44 }
Chris@761 45
Chris@761 46 void
Chris@761 47 Align::addAligner(Document *doc,
Chris@761 48 ModelId reference,
Chris@761 49 ModelId toAlign)
Chris@753 50 {
Chris@753 51 bool useProgram;
Chris@753 52 QString program;
Chris@753 53 getAlignerPreference(useProgram, program);
Chris@753 54
Chris@753 55 std::shared_ptr<Aligner> aligner;
Chris@753 56
Chris@753 57 {
Chris@753 58 // Replace the aligner with a new one. This also stops any
Chris@753 59 // previously-running alignment, when the old entry is
Chris@753 60 // replaced and its aligner destroyed.
Chris@753 61
Chris@753 62 QMutexLocker locker(&m_mutex);
Chris@753 63
Chris@753 64 if (useProgram && (program != "")) {
Chris@753 65 m_aligners[toAlign] =
Chris@753 66 std::make_shared<ExternalProgramAligner>(doc,
Chris@753 67 reference,
Chris@753 68 toAlign,
Chris@753 69 program);
Chris@753 70 } else {
Chris@753 71 m_aligners[toAlign] =
Chris@753 72 std::make_shared<TransformAligner>(doc,
Chris@753 73 reference,
Chris@753 74 toAlign);
Chris@753 75 }
Chris@753 76
Chris@753 77 aligner = m_aligners[toAlign];
Chris@753 78 }
Chris@753 79
Chris@753 80 connect(aligner.get(), SIGNAL(complete(ModelId)),
Chris@753 81 this, SLOT(alignerComplete(ModelId)));
Chris@761 82
Chris@761 83 connect(aligner.get(), SIGNAL(failed(ModelId, QString)),
Chris@761 84 this, SLOT(alignerFailed(ModelId, QString)));
Chris@753 85 }
Chris@753 86
Chris@753 87 void
Chris@756 88 Align::getAlignerPreference(bool &useProgram, QString &program)
Chris@422 89 {
Chris@422 90 QSettings settings;
Chris@422 91 settings.beginGroup("Preferences");
Chris@753 92 useProgram = settings.value("use-external-alignment", false).toBool();
Chris@753 93 program = settings.value("external-alignment-program", "").toString();
Chris@422 94 settings.endGroup();
Chris@670 95 }
Chris@670 96
Chris@428 97 bool
Chris@428 98 Align::canAlign()
Chris@428 99 {
Chris@753 100 bool useProgram;
Chris@753 101 QString program;
Chris@753 102 getAlignerPreference(useProgram, program);
Chris@753 103
Chris@753 104 if (useProgram) {
Chris@753 105 return ExternalProgramAligner::isAvailable(program);
Chris@753 106 } else {
Chris@753 107 return TransformAligner::isAvailable();
Chris@753 108 }
Chris@428 109 }
Chris@428 110
Chris@702 111 void
Chris@753 112 Align::alignerComplete(ModelId alignmentModel)
Chris@702 113 {
Chris@761 114 removeAligner(sender());
Chris@761 115 emit alignmentComplete(alignmentModel);
Chris@761 116 }
Chris@761 117
Chris@761 118 void
Chris@761 119 Align::alignerFailed(ModelId toAlign, QString error)
Chris@761 120 {
Chris@761 121 removeAligner(sender());
Chris@761 122 emit alignmentFailed(toAlign, error);
Chris@761 123 }
Chris@761 124
Chris@761 125 void
Chris@761 126 Align::removeAligner(QObject *obj)
Chris@761 127 {
Chris@761 128 Aligner *aligner = qobject_cast<Aligner *>(obj);
Chris@753 129 if (!aligner) {
Chris@761 130 SVCERR << "ERROR: Align::removeAligner: Not an Aligner" << endl;
Chris@702 131 return;
Chris@702 132 }
Chris@702 133
Chris@761 134 QMutexLocker locker (&m_mutex);
Chris@702 135
Chris@761 136 for (auto p: m_aligners) {
Chris@761 137 if (aligner == p.second.get()) {
Chris@761 138 m_aligners.erase(p.first);
Chris@761 139 break;
Chris@702 140 }
Chris@702 141 }
Chris@761 142 }
Chris@702 143