Chris@150: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@150: 
Chris@150: /*
Chris@150:     Sonic Visualiser
Chris@150:     An audio file viewer and annotation editor.
Chris@150:     Centre for Digital Music, Queen Mary, University of London.
Chris@150:     This file copyright 2006 Chris Cannam.
Chris@150:     
Chris@150:     This program is free software; you can redistribute it and/or
Chris@150:     modify it under the terms of the GNU General Public License as
Chris@150:     published by the Free Software Foundation; either version 2 of the
Chris@150:     License, or (at your option) any later version.  See the file
Chris@150:     COPYING included with this distribution for more information.
Chris@150: */
Chris@150: 
Chris@150: #include "Model.h"
Chris@319: #include "AlignmentModel.h"
Chris@150: 
Chris@150: #include <QTextStream>
Chris@150: 
Chris@150: #include <iostream>
Chris@150: 
Chris@150: const int Model::COMPLETION_UNKNOWN = -1;
Chris@150: 
Chris@150: Model::~Model()
Chris@150: {
Chris@690: //    SVDEBUG << "Model::~Model(" << this << ")" << endl;
Chris@150: 
Chris@319:     if (!m_aboutToDelete) {
Chris@690:         SVDEBUG << "NOTE: Model::~Model(" << this << ", \""
Chris@686:                   << objectName() << "\"): Model deleted "
Chris@687:                   << "with no aboutToDelete notification" << endl;
Chris@319:     }
Chris@319: 
Chris@319:     if (m_alignment) {
Chris@319:         m_alignment->aboutToDelete();
Chris@319:         delete m_alignment;
Chris@319:     }
Chris@150: }
Chris@150: 
Chris@150: void
Chris@319: Model::setSourceModel(Model *model)
Chris@319: {
Chris@319:     if (m_sourceModel) {
Chris@319:         disconnect(m_sourceModel, SIGNAL(aboutToBeDeleted()),
Chris@319:                    this, SLOT(sourceModelAboutToBeDeleted()));
Chris@319:     }
Chris@319: 
Chris@319:     m_sourceModel = model;
Chris@319: 
Chris@319:     if (m_sourceModel) {
Chris@333:         connect(m_sourceModel, SIGNAL(alignmentCompletionChanged()),
Chris@333:                 this, SIGNAL(alignmentCompletionChanged()));
Chris@319:         connect(m_sourceModel, SIGNAL(aboutToBeDeleted()),
Chris@319:                 this, SLOT(sourceModelAboutToBeDeleted()));
Chris@319:     }
Chris@319: }
Chris@319: 
Chris@319: void
Chris@319: Model::aboutToDelete()
Chris@319: {
Chris@843: //    cerr << "Model(" << this << ")::aboutToDelete()" << endl;
Chris@360: 
Chris@319:     if (m_aboutToDelete) {
Chris@843:         cerr << "WARNING: Model(" << this << ", \""
Chris@686:                   << objectName() << "\")::aboutToDelete: "
Chris@319:                   << "aboutToDelete called more than once for the same model"
Chris@843:                   << endl;
Chris@319:     }
Chris@319: 
Chris@319:     emit aboutToBeDeleted();
Chris@319:     m_aboutToDelete = true;
Chris@319: }
Chris@319: 
Chris@319: void
Chris@319: Model::sourceModelAboutToBeDeleted()
Chris@319: {
Chris@319:     m_sourceModel = 0;
Chris@319: }
Chris@319: 
Chris@319: void
Chris@319: Model::setAlignment(AlignmentModel *alignment)
Chris@319: {
Chris@319:     if (m_alignment) {
Chris@319:         m_alignment->aboutToDelete();
Chris@319:         delete m_alignment;
Chris@319:     }
Chris@319:     m_alignment = alignment;
Chris@319:     connect(m_alignment, SIGNAL(completionChanged()),
Chris@319:             this, SIGNAL(alignmentCompletionChanged()));
Chris@319: }
Chris@319: 
Chris@407: const AlignmentModel *
Chris@407: Model::getAlignment() const
Chris@407: {
Chris@407:     return m_alignment;
Chris@407: }
Chris@407: 
Chris@319: const Model *
Chris@319: Model::getAlignmentReference() const
Chris@319: {
Chris@333:     if (!m_alignment) {
Chris@333:         if (m_sourceModel) return m_sourceModel->getAlignmentReference();
Chris@371:         return 0;
Chris@333:     }
Chris@319:     return m_alignment->getReferenceModel();
Chris@319: }
Chris@319: 
Chris@929: int
Chris@929: Model::alignToReference(int frame) const
Chris@319: {
Chris@951: //    cerr << "Model(" << this << ")::alignToReference(" << frame << ")" << endl;
Chris@333:     if (!m_alignment) {
Chris@333:         if (m_sourceModel) return m_sourceModel->alignToReference(frame);
Chris@333:         else return frame;
Chris@333:     }
Chris@929:     int refFrame = m_alignment->toReference(frame);
Chris@340:     const Model *m = m_alignment->getReferenceModel();
Chris@340:     if (m && refFrame > m->getEndFrame()) refFrame = m->getEndFrame();
Chris@951: //    cerr << "have alignment, aligned is " << refFrame << endl;
Chris@333:     return refFrame;
Chris@319: }
Chris@319: 
Chris@929: int
Chris@929: Model::alignFromReference(int refFrame) const
Chris@319: {
Chris@951: //    cerr << "Model(" << this << ")::alignFromReference(" << refFrame << ")" << endl;
Chris@333:     if (!m_alignment) {
Chris@333:         if (m_sourceModel) return m_sourceModel->alignFromReference(refFrame);
Chris@333:         else return refFrame;
Chris@333:     }
Chris@929:     int frame = m_alignment->fromReference(refFrame);
Chris@340:     if (frame > getEndFrame()) frame = getEndFrame();
Chris@951: //    cerr << "have alignment, aligned is " << frame << endl;
Chris@333:     return frame;
Chris@319: }
Chris@319: 
Chris@319: int
Chris@319: Model::getAlignmentCompletion() const
Chris@319: {
Chris@690: //    SVDEBUG << "Model::getAlignmentCompletion" << endl;
Chris@333:     if (!m_alignment) {
Chris@333:         if (m_sourceModel) return m_sourceModel->getAlignmentCompletion();
Chris@333:         else return 100;
Chris@333:     }
Chris@319:     int completion = 0;
Chris@319:     (void)m_alignment->isReady(&completion);
Chris@843: //    cerr << " -> " << completion << endl;
Chris@319:     return completion;
Chris@319: }
Chris@319: 
Chris@333: QString
Chris@333: Model::getTitle() const
Chris@333: {
Chris@333:     if (m_sourceModel) return m_sourceModel->getTitle();
Chris@345:     else return "";
Chris@333: }
Chris@333: 
Chris@333: QString
Chris@333: Model::getMaker() const
Chris@333: {
Chris@333:     if (m_sourceModel) return m_sourceModel->getMaker();
Chris@345:     else return "";
Chris@345: }
Chris@345: 
Chris@345: QString
Chris@345: Model::getLocation() const
Chris@345: {
Chris@345:     if (m_sourceModel) return m_sourceModel->getLocation();
Chris@345:     else return "";
Chris@333: }
Chris@333: 
Chris@319: void
Chris@150: Model::toXml(QTextStream &stream, QString indent,
Chris@150:              QString extraAttributes) const
Chris@150: {
Chris@150:     stream << indent;
Chris@150:     stream << QString("<model id=\"%1\" name=\"%2\" sampleRate=\"%3\" start=\"%4\" end=\"%5\" %6/>\n")
Chris@150: 	.arg(getObjectExportId(this))
Chris@150: 	.arg(encodeEntities(objectName()))
Chris@150: 	.arg(getSampleRate())
Chris@150: 	.arg(getStartFrame())
Chris@150: 	.arg(getEndFrame())
Chris@150: 	.arg(extraAttributes);
Chris@150: }
Chris@150: 
Chris@150: