| Chris@150 | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */ | 
| Chris@150 | 2 | 
| Chris@150 | 3 /* | 
| Chris@150 | 4     Sonic Visualiser | 
| Chris@150 | 5     An audio file viewer and annotation editor. | 
| Chris@150 | 6     Centre for Digital Music, Queen Mary, University of London. | 
| Chris@150 | 7     This file copyright 2006 Chris Cannam. | 
| Chris@150 | 8 | 
| Chris@150 | 9     This program is free software; you can redistribute it and/or | 
| Chris@150 | 10     modify it under the terms of the GNU General Public License as | 
| Chris@150 | 11     published by the Free Software Foundation; either version 2 of the | 
| Chris@150 | 12     License, or (at your option) any later version.  See the file | 
| Chris@150 | 13     COPYING included with this distribution for more information. | 
| Chris@150 | 14 */ | 
| Chris@150 | 15 | 
| Chris@150 | 16 #include "Model.h" | 
| Chris@319 | 17 #include "AlignmentModel.h" | 
| Chris@150 | 18 | 
| Chris@150 | 19 #include <QTextStream> | 
| Chris@150 | 20 | 
| Chris@150 | 21 #include <iostream> | 
| Chris@150 | 22 | 
| Chris@1696 | 23 //#define DEBUG_COMPLETION 1 | 
| Chris@1696 | 24 | 
| Chris@150 | 25 Model::~Model() | 
| Chris@150 | 26 { | 
| Chris@1739 | 27     SVDEBUG << "Model::~Model: " << this << " with id " << getId() << endl; | 
| Chris@150 | 28 } | 
| Chris@150 | 29 | 
| Chris@150 | 30 void | 
| Chris@1735 | 31 Model::setSourceModel(ModelId modelId) | 
| Chris@319 | 32 { | 
| Chris@1798 | 33     QMutexLocker locker(&m_mutex); | 
| Chris@1798 | 34 | 
| Chris@1735 | 35     m_sourceModel = modelId; | 
| Chris@319 | 36 | 
| Chris@1735 | 37     auto model = ModelById::get(m_sourceModel); | 
| Chris@1735 | 38     if (model) { | 
| Chris@1752 | 39         connect(model.get(), SIGNAL(alignmentCompletionChanged(ModelId)), | 
| Chris@1752 | 40                 this, SIGNAL(alignmentCompletionChanged(ModelId))); | 
| Chris@1735 | 41     } | 
| Chris@319 | 42 } | 
| Chris@319 | 43 | 
| Chris@319 | 44 void | 
| Chris@1735 | 45 Model::setAlignment(ModelId alignmentModel) | 
| Chris@319 | 46 { | 
| Chris@1798 | 47     QMutexLocker locker(&m_mutex); | 
| Chris@1798 | 48 | 
| Chris@1668 | 49     SVDEBUG << "Model(" << this << "): accepting alignment model " | 
| Chris@1735 | 50             << alignmentModel << endl; | 
| Chris@1761 | 51 | 
| Chris@1761 | 52     if (auto model = ModelById::get(m_alignmentModel)) { | 
| Chris@1761 | 53         disconnect(model.get(), SIGNAL(completionChanged(ModelId)), | 
| Chris@1767 | 54                    this, SLOT(alignmentModelCompletionChanged(ModelId))); | 
| Chris@319 | 55     } | 
| Chris@1018 | 56 | 
| Chris@1735 | 57     m_alignmentModel = alignmentModel; | 
| Chris@1018 | 58 | 
| Chris@1761 | 59     if (auto model = ModelById::get(m_alignmentModel)) { | 
| Chris@1758 | 60         connect(model.get(), SIGNAL(completionChanged(ModelId)), | 
| Chris@1767 | 61                 this, SLOT(alignmentModelCompletionChanged(ModelId))); | 
| Chris@1018 | 62     } | 
| Chris@319 | 63 } | 
| Chris@319 | 64 | 
| Chris@1767 | 65 void | 
| Chris@1767 | 66 Model::alignmentModelCompletionChanged(ModelId) | 
| Chris@1767 | 67 { | 
| Chris@1767 | 68     emit alignmentCompletionChanged(getId()); | 
| Chris@1767 | 69 } | 
| Chris@1767 | 70 | 
| Chris@1735 | 71 const ModelId | 
| Chris@407 | 72 Model::getAlignment() const | 
| Chris@407 | 73 { | 
| Chris@1798 | 74     QMutexLocker locker(&m_mutex); | 
| Chris@1735 | 75     return m_alignmentModel; | 
| Chris@407 | 76 } | 
| Chris@407 | 77 | 
| Chris@1735 | 78 const ModelId | 
| Chris@319 | 79 Model::getAlignmentReference() const | 
| Chris@319 | 80 { | 
| Chris@1798 | 81     QMutexLocker locker(&m_mutex); | 
| Chris@1735 | 82     auto model = ModelById::getAs<AlignmentModel>(m_alignmentModel); | 
| Chris@1735 | 83     if (model) return model->getReferenceModel(); | 
| Chris@1735 | 84     else return {}; | 
| Chris@319 | 85 } | 
| Chris@319 | 86 | 
| Chris@1038 | 87 sv_frame_t | 
| Chris@1038 | 88 Model::alignToReference(sv_frame_t frame) const | 
| Chris@319 | 89 { | 
| Chris@1798 | 90     ModelId alignmentModelId, sourceModelId; | 
| Chris@1798 | 91     { | 
| Chris@1798 | 92         QMutexLocker locker(&m_mutex); | 
| Chris@1798 | 93         alignmentModelId = m_alignmentModel; | 
| Chris@1798 | 94         sourceModelId = m_sourceModel; | 
| Chris@1798 | 95     } | 
| Chris@1798 | 96 | 
| Chris@1798 | 97     auto alignmentModel = ModelById::getAs<AlignmentModel>(alignmentModelId); | 
| Chris@1739 | 98 | 
| Chris@1739 | 99     if (!alignmentModel) { | 
| Chris@1798 | 100         auto sourceModel = ModelById::get(sourceModelId); | 
| Chris@1739 | 101         if (sourceModel) { | 
| Chris@1739 | 102             return sourceModel->alignToReference(frame); | 
| Chris@1739 | 103         } | 
| Chris@1739 | 104         return frame; | 
| Chris@333 | 105     } | 
| Chris@1739 | 106 | 
| Chris@1739 | 107     sv_frame_t refFrame = alignmentModel->toReference(frame); | 
| Chris@1739 | 108     auto refModel = ModelById::get(alignmentModel->getReferenceModel()); | 
| Chris@1739 | 109     if (refModel && refFrame > refModel->getEndFrame()) { | 
| Chris@1739 | 110         refFrame = refModel->getEndFrame(); | 
| Chris@1739 | 111     } | 
| Chris@333 | 112     return refFrame; | 
| Chris@319 | 113 } | 
| Chris@319 | 114 | 
| Chris@1038 | 115 sv_frame_t | 
| Chris@1038 | 116 Model::alignFromReference(sv_frame_t refFrame) const | 
| Chris@319 | 117 { | 
| Chris@1798 | 118     ModelId alignmentModelId, sourceModelId; | 
| Chris@1798 | 119     { | 
| Chris@1798 | 120         QMutexLocker locker(&m_mutex); | 
| Chris@1798 | 121         alignmentModelId = m_alignmentModel; | 
| Chris@1798 | 122         sourceModelId = m_sourceModel; | 
| Chris@1798 | 123     } | 
| Chris@1798 | 124 | 
| Chris@1798 | 125     auto alignmentModel = ModelById::getAs<AlignmentModel>(alignmentModelId); | 
| Chris@1798 | 126 | 
| Chris@1739 | 127     if (!alignmentModel) { | 
| Chris@1798 | 128         auto sourceModel = ModelById::get(sourceModelId); | 
| Chris@1739 | 129         if (sourceModel) { | 
| Chris@1739 | 130             return sourceModel->alignFromReference(refFrame); | 
| Chris@1739 | 131         } | 
| Chris@1739 | 132         return refFrame; | 
| Chris@333 | 133     } | 
| Chris@1739 | 134 | 
| Chris@1739 | 135     sv_frame_t frame = alignmentModel->fromReference(refFrame); | 
| Chris@340 | 136     if (frame > getEndFrame()) frame = getEndFrame(); | 
| Chris@333 | 137     return frame; | 
| Chris@319 | 138 } | 
| Chris@319 | 139 | 
| Chris@319 | 140 int | 
| Chris@319 | 141 Model::getAlignmentCompletion() const | 
| Chris@319 | 142 { | 
| Chris@1798 | 143     ModelId alignmentModelId, sourceModelId; | 
| Chris@1798 | 144     { | 
| Chris@1798 | 145         QMutexLocker locker(&m_mutex); | 
| Chris@1798 | 146         alignmentModelId = m_alignmentModel; | 
| Chris@1798 | 147         sourceModelId = m_sourceModel; | 
| Chris@1798 | 148     } | 
| Chris@1798 | 149 | 
| Chris@1696 | 150 #ifdef DEBUG_COMPLETION | 
| Chris@1739 | 151     SVCERR << "Model(" << this | 
| Chris@1739 | 152            << ")::getAlignmentCompletion: m_alignmentModel = " | 
| Chris@1739 | 153            << m_alignmentModel << endl; | 
| Chris@1696 | 154 #endif | 
| Chris@1739 | 155 | 
| Chris@1798 | 156     auto alignmentModel = ModelById::getAs<AlignmentModel>(alignmentModelId); | 
| Chris@1739 | 157 | 
| Chris@1739 | 158     if (!alignmentModel) { | 
| Chris@1798 | 159         auto sourceModel = ModelById::get(sourceModelId); | 
| Chris@1739 | 160         if (sourceModel) { | 
| Chris@1739 | 161             return sourceModel->getAlignmentCompletion(); | 
| Chris@1739 | 162         } | 
| Chris@1739 | 163         return 100; | 
| Chris@333 | 164     } | 
| Chris@1739 | 165 | 
| Chris@319 | 166     int completion = 0; | 
| Chris@1739 | 167     (void)alignmentModel->isReady(&completion); | 
| Chris@1696 | 168 #ifdef DEBUG_COMPLETION | 
| Chris@1739 | 169     SVCERR << "Model(" << this | 
| Chris@1739 | 170            << ")::getAlignmentCompletion: completion = " << completion | 
| Chris@1696 | 171            << endl; | 
| Chris@1696 | 172 #endif | 
| Chris@319 | 173     return completion; | 
| Chris@319 | 174 } | 
| Chris@319 | 175 | 
| Chris@333 | 176 QString | 
| Chris@333 | 177 Model::getTitle() const | 
| Chris@333 | 178 { | 
| Chris@1798 | 179     QMutexLocker locker(&m_mutex); | 
| Chris@1739 | 180     auto source = ModelById::get(m_sourceModel); | 
| Chris@1739 | 181     if (source) return source->getTitle(); | 
| Chris@345 | 182     else return ""; | 
| Chris@333 | 183 } | 
| Chris@333 | 184 | 
| Chris@333 | 185 QString | 
| Chris@333 | 186 Model::getMaker() const | 
| Chris@333 | 187 { | 
| Chris@1798 | 188     QMutexLocker locker(&m_mutex); | 
| Chris@1739 | 189     auto source = ModelById::get(m_sourceModel); | 
| Chris@1739 | 190     if (source) return source->getMaker(); | 
| Chris@345 | 191     else return ""; | 
| Chris@345 | 192 } | 
| Chris@345 | 193 | 
| Chris@345 | 194 QString | 
| Chris@345 | 195 Model::getLocation() const | 
| Chris@345 | 196 { | 
| Chris@1798 | 197     QMutexLocker locker(&m_mutex); | 
| Chris@1739 | 198     auto source = ModelById::get(m_sourceModel); | 
| Chris@1739 | 199     if (source) return source->getLocation(); | 
| Chris@345 | 200     else return ""; | 
| Chris@333 | 201 } | 
| Chris@333 | 202 | 
| Chris@319 | 203 void | 
| Chris@150 | 204 Model::toXml(QTextStream &stream, QString indent, | 
| Chris@150 | 205              QString extraAttributes) const | 
| Chris@150 | 206 { | 
| Chris@150 | 207     stream << indent; | 
| Chris@150 | 208     stream << QString("<model id=\"%1\" name=\"%2\" sampleRate=\"%3\" start=\"%4\" end=\"%5\" %6/>\n") | 
| Chris@1677 | 209         .arg(getExportId()) | 
| Chris@1429 | 210         .arg(encodeEntities(objectName())) | 
| Chris@1429 | 211         .arg(getSampleRate()) | 
| Chris@1429 | 212         .arg(getStartFrame()) | 
| Chris@1429 | 213         .arg(getEndFrame()) | 
| Chris@1429 | 214         .arg(extraAttributes); | 
| Chris@150 | 215 } | 
| Chris@150 | 216 | 
| Chris@150 | 217 |