annotate data/model/Model.cpp @ 1677:f97d64b8674f single-point

Make XmlExportables store their export IDs and always obtain a new one, avoiding reuse when an object is allocated at the same heap location as a previous one. This makes the ID system stable enough to be used in the export tests.
author Chris Cannam
date Thu, 28 Mar 2019 11:55:02 +0000
parents dfcd05e8bd2f
children 187c76c40c6f
rev   line source
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@150 23 Model::~Model()
Chris@150 24 {
Chris@1668 25 SVDEBUG << "Model::~Model(" << this << ")" << endl;
Chris@150 26
Chris@319 27 if (!m_aboutToDelete) {
Chris@1384 28 SVDEBUG << "NOTE: Model(" << this << ", \""
Chris@1384 29 << objectName() << "\", type uri <"
Chris@1384 30 << m_typeUri << ">)::~Model(): Model deleted "
Chris@1384 31 << "with no aboutToDelete notification"
Chris@1384 32 << endl;
Chris@319 33 }
Chris@319 34
Chris@319 35 if (m_alignment) {
Chris@319 36 m_alignment->aboutToDelete();
Chris@319 37 delete m_alignment;
Chris@319 38 }
Chris@150 39 }
Chris@150 40
Chris@1500 41 int
Chris@1500 42 Model::getNextId()
Chris@1500 43 {
Chris@1500 44 static int nextId = 0;
Chris@1500 45 static QMutex mutex;
Chris@1500 46 QMutexLocker locker(&mutex);
Chris@1500 47 int i = nextId;
Chris@1500 48 if (nextId == INT_MAX) {
Chris@1500 49 nextId = INT_MIN;
Chris@1500 50 }
Chris@1500 51 ++nextId;
Chris@1500 52 return i;
Chris@1500 53 }
Chris@1500 54
Chris@150 55 void
Chris@319 56 Model::setSourceModel(Model *model)
Chris@319 57 {
Chris@319 58 if (m_sourceModel) {
Chris@319 59 disconnect(m_sourceModel, SIGNAL(aboutToBeDeleted()),
Chris@319 60 this, SLOT(sourceModelAboutToBeDeleted()));
Chris@319 61 }
Chris@319 62
Chris@319 63 m_sourceModel = model;
Chris@319 64
Chris@319 65 if (m_sourceModel) {
Chris@333 66 connect(m_sourceModel, SIGNAL(alignmentCompletionChanged()),
Chris@333 67 this, SIGNAL(alignmentCompletionChanged()));
Chris@319 68 connect(m_sourceModel, SIGNAL(aboutToBeDeleted()),
Chris@319 69 this, SLOT(sourceModelAboutToBeDeleted()));
Chris@319 70 }
Chris@319 71 }
Chris@319 72
Chris@319 73 void
Chris@319 74 Model::aboutToDelete()
Chris@319 75 {
Chris@1668 76 SVDEBUG << "Model(" << this << ", \""
Chris@1668 77 << objectName() << "\", type name \""
Chris@1668 78 << getTypeName() << "\", type uri <"
Chris@1668 79 << m_typeUri << ">)::aboutToDelete()" << endl;
Chris@360 80
Chris@319 81 if (m_aboutToDelete) {
Chris@1384 82 SVDEBUG << "WARNING: Model(" << this << ", \""
Chris@1384 83 << objectName() << "\", type uri <"
Chris@1384 84 << m_typeUri << ">)::aboutToDelete: "
Chris@1384 85 << "aboutToDelete called more than once for the same model"
Chris@1384 86 << endl;
Chris@319 87 }
Chris@319 88
Chris@319 89 emit aboutToBeDeleted();
Chris@319 90 m_aboutToDelete = true;
Chris@319 91 }
Chris@319 92
Chris@319 93 void
Chris@319 94 Model::sourceModelAboutToBeDeleted()
Chris@319 95 {
Chris@1582 96 m_sourceModel = nullptr;
Chris@319 97 }
Chris@319 98
Chris@319 99 void
Chris@319 100 Model::setAlignment(AlignmentModel *alignment)
Chris@319 101 {
Chris@1668 102 SVDEBUG << "Model(" << this << "): accepting alignment model "
Chris@1668 103 << alignment << endl;
Chris@1668 104
Chris@319 105 if (m_alignment) {
Chris@319 106 m_alignment->aboutToDelete();
Chris@319 107 delete m_alignment;
Chris@319 108 }
Chris@1018 109
Chris@319 110 m_alignment = alignment;
Chris@1018 111
Chris@1018 112 if (m_alignment) {
Chris@1018 113 connect(m_alignment, SIGNAL(completionChanged()),
Chris@1018 114 this, SIGNAL(alignmentCompletionChanged()));
Chris@1018 115 }
Chris@319 116 }
Chris@319 117
Chris@407 118 const AlignmentModel *
Chris@407 119 Model::getAlignment() const
Chris@407 120 {
Chris@407 121 return m_alignment;
Chris@407 122 }
Chris@407 123
Chris@319 124 const Model *
Chris@319 125 Model::getAlignmentReference() const
Chris@319 126 {
Chris@333 127 if (!m_alignment) {
Chris@333 128 if (m_sourceModel) return m_sourceModel->getAlignmentReference();
Chris@1582 129 return nullptr;
Chris@333 130 }
Chris@319 131 return m_alignment->getReferenceModel();
Chris@319 132 }
Chris@319 133
Chris@1038 134 sv_frame_t
Chris@1038 135 Model::alignToReference(sv_frame_t frame) const
Chris@319 136 {
Chris@951 137 // cerr << "Model(" << this << ")::alignToReference(" << frame << ")" << endl;
Chris@333 138 if (!m_alignment) {
Chris@333 139 if (m_sourceModel) return m_sourceModel->alignToReference(frame);
Chris@333 140 else return frame;
Chris@333 141 }
Chris@1038 142 sv_frame_t refFrame = m_alignment->toReference(frame);
Chris@340 143 const Model *m = m_alignment->getReferenceModel();
Chris@340 144 if (m && refFrame > m->getEndFrame()) refFrame = m->getEndFrame();
Chris@951 145 // cerr << "have alignment, aligned is " << refFrame << endl;
Chris@333 146 return refFrame;
Chris@319 147 }
Chris@319 148
Chris@1038 149 sv_frame_t
Chris@1038 150 Model::alignFromReference(sv_frame_t refFrame) const
Chris@319 151 {
Chris@951 152 // cerr << "Model(" << this << ")::alignFromReference(" << refFrame << ")" << endl;
Chris@333 153 if (!m_alignment) {
Chris@333 154 if (m_sourceModel) return m_sourceModel->alignFromReference(refFrame);
Chris@333 155 else return refFrame;
Chris@333 156 }
Chris@1038 157 sv_frame_t frame = m_alignment->fromReference(refFrame);
Chris@340 158 if (frame > getEndFrame()) frame = getEndFrame();
Chris@951 159 // cerr << "have alignment, aligned is " << frame << endl;
Chris@333 160 return frame;
Chris@319 161 }
Chris@319 162
Chris@319 163 int
Chris@319 164 Model::getAlignmentCompletion() const
Chris@319 165 {
Chris@1561 166 // SVDEBUG << "Model::getAlignmentCompletion: m_alignment = "
Chris@1561 167 // << m_alignment << endl;
Chris@333 168 if (!m_alignment) {
Chris@333 169 if (m_sourceModel) return m_sourceModel->getAlignmentCompletion();
Chris@333 170 else return 100;
Chris@333 171 }
Chris@319 172 int completion = 0;
Chris@319 173 (void)m_alignment->isReady(&completion);
Chris@1561 174 // SVDEBUG << " -> " << completion << endl;
Chris@319 175 return completion;
Chris@319 176 }
Chris@319 177
Chris@333 178 QString
Chris@333 179 Model::getTitle() const
Chris@333 180 {
Chris@333 181 if (m_sourceModel) return m_sourceModel->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@333 188 if (m_sourceModel) return m_sourceModel->getMaker();
Chris@345 189 else return "";
Chris@345 190 }
Chris@345 191
Chris@345 192 QString
Chris@345 193 Model::getLocation() const
Chris@345 194 {
Chris@345 195 if (m_sourceModel) return m_sourceModel->getLocation();
Chris@345 196 else return "";
Chris@333 197 }
Chris@333 198
Chris@319 199 void
Chris@150 200 Model::toXml(QTextStream &stream, QString indent,
Chris@150 201 QString extraAttributes) const
Chris@150 202 {
Chris@150 203 stream << indent;
Chris@150 204 stream << QString("<model id=\"%1\" name=\"%2\" sampleRate=\"%3\" start=\"%4\" end=\"%5\" %6/>\n")
Chris@1677 205 .arg(getExportId())
Chris@1429 206 .arg(encodeEntities(objectName()))
Chris@1429 207 .arg(getSampleRate())
Chris@1429 208 .arg(getStartFrame())
Chris@1429 209 .arg(getEndFrame())
Chris@1429 210 .arg(extraAttributes);
Chris@150 211 }
Chris@150 212
Chris@150 213