Mercurial > hg > easaier-soundaccess
view data/fileio/ModelReader.cpp @ 66:429cfea499ad
layers for all panes, are ok.
author | benoitrigolleau |
---|---|
date | Tue, 12 Jun 2007 16:21:30 +0000 |
parents | 4eb9c7e4acf6 |
children | e006f4a57f86 |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Sound Access EASAIER client application. Silogic 2007. Laure Bajard. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include "ModelReader.h" #include "document/Document.h" #include "layer/Layer.h" #include "data/model/EditableDenseThreeDimensionalModel.h" #include "data/model/SparseOneDimensionalModel.h" #include "data/model/SparseTimeValueModel.h" #include "data/model/NoteModel.h" #include "data/model/TextModel.h" #include "data/model/IntervalModel.h" #include "view/Pane.h" #include <iostream> ModelReader::ModelReader(Document *document, Layer * layer, Pane * pane) : m_document(document), m_layer(layer), m_pane(pane) {} bool ModelReader::parse(const QString & filename) { ModelHandler handler(m_document, m_layer, m_pane); QXmlSimpleReader reader; reader.setContentHandler(&handler); reader.setErrorHandler(&handler); QFile file(filename); if (!file.open(QFile::ReadOnly | QFile::Text)) { return false; } QXmlInputSource xmlInputSource(&file); if (reader.parse(xmlInputSource)) { return true; } return false; } ModelHandler::ModelHandler(Document *document, Layer * layer, Pane* pane) : QXmlDefaultHandler(), m_document(document), m_layer(layer), m_pane(pane), m_model(0), m_datasetSeparator(" "), m_inData(false), m_inRow(false), m_rowNumber(0) {} bool ModelHandler::startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &attributes) { QString name = qName.toLower(); bool ok = false; // Valid element names: // // easaier // data // dataset // model // point // row // interval if (name == "easaier") { // nothing needed ok = true; } else if (name == "data") { m_inData = true; if (m_layer == 0) { ok = readLayer(attributes); } else { ok = true; } } else if (name == "model") { ok = readModel(attributes); } else if (name == "dataset") { ok = readDatasetStart(attributes); } else if (name == "bin") { ok = addBinToDataset(attributes); } else if (name == "point") { ok = addPointToDataset(attributes); } else if (name == "row") { ok = addRowToDataset(attributes); } else if (name == "interval") { ok = addIntervalToDataset(attributes); } if (!ok) { std::cerr << "WARNING: ModelReader-XML: Failed to completely process element \"" << name.toLocal8Bit().data() << "\"" << std::endl; } return true; } bool ModelHandler::endElement(const QString &namespaceURI, const QString &localName, const QString &qName) { QString name = qName.toLower(); if (name == "dataset") { if ((m_model) && (m_layer)) { m_document->addImportedModel(m_model); m_document->setModel(m_layer, m_model); } } else if (name == "data") { m_inData = false; if (m_pane && m_layer) { m_document->addLayerToView(m_pane, m_layer); } } else if (name == "row") { m_inRow = false; } return true; } bool ModelHandler::characters(const QString &str) { bool ok = false; if (m_inRow) { ok = readRowData(str); if (!ok) { std::cerr << "WARNING: ModelReader-XML: Failed to read row data content for row " << m_rowNumber << std::endl; } } return true; } bool ModelHandler::error(const QXmlParseException &exception) { QString errorString; errorString += QString("ERROR: ModelReader-XML: %1 at line %2, column %3") .arg(exception.message()) .arg(exception.lineNumber()) .arg(exception.columnNumber()); std::cerr << errorString.toLocal8Bit().data() << std::endl; return QXmlDefaultHandler::error(exception); } bool ModelHandler::fatalError(const QXmlParseException &exception) { QString errorString; errorString += QString("FATAL ERROR: ModelReader-XML: %1 at line %2, column %3") .arg(exception.message()) .arg(exception.lineNumber()) .arg(exception.columnNumber()); std::cerr << errorString.toLocal8Bit().data() << std::endl; return QXmlDefaultHandler::fatalError(exception); } #define READ_MANDATORY(TYPE, NAME, CONVERSION) \ TYPE NAME = attributes.value(#NAME).trimmed().CONVERSION(&ok); \ if (!ok) { \ std::cerr << "WARNING: ModelReader-XML: Missing or invalid mandatory " #TYPE " attribute \"" #NAME "\"" << std::endl; \ return false; \ } bool ModelHandler::readModel(const QXmlAttributes &attributes) { bool ok = false; READ_MANDATORY(int, id, toInt); QString name = attributes.value("name"); if (m_layer->getModelName() == "") { m_layer->setModelName(name); m_layer->setModelId(id); } READ_MANDATORY(int, sampleRate, toInt); QString type = attributes.value("type").trimmed(); bool mainModel = (attributes.value("mainModel").trimmed() == "true"); if (type == "dense") { READ_MANDATORY(int, dimensions, toInt); // Currently the only dense model we support here // is the dense 3d model. Dense time-value models // are always file-backed waveform data, at this // point, and they come in as the wavefile model // type above. if (dimensions == 3) { READ_MANDATORY(int, windowSize, toInt); READ_MANDATORY(int, yBinCount, toInt); EditableDenseThreeDimensionalModel *model = new EditableDenseThreeDimensionalModel(sampleRate, windowSize, yBinCount); float minimum = attributes.value("minimum").trimmed().toFloat(&ok); if (ok) model->setMinimumLevel(minimum); float maximum = attributes.value("maximum").trimmed().toFloat(&ok); if (ok) model->setMaximumLevel(maximum); m_model = model; return true; } else { std::cerr << "WARNING: ModelReader-XML: Unexpected dense model dimension (" << dimensions << ")" << std::endl; } } else if (type == "sparse") { READ_MANDATORY(int, dimensions, toInt); if (dimensions == 1) { READ_MANDATORY(int, resolution, toInt); SparseOneDimensionalModel *model = new SparseOneDimensionalModel(sampleRate, resolution); m_model = model; return true; } else if (dimensions == 2 || dimensions == 3) { READ_MANDATORY(int, resolution, toInt); float minimum = attributes.value("minimum").trimmed().toFloat(&ok); float maximum = attributes.value("maximum").trimmed().toFloat(&ok); float valueQuantization = attributes.value("valueQuantization").trimmed().toFloat(&ok); bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true"); QString units = attributes.value("units"); if (dimensions == 2) { if (attributes.value("subtype") == "text") { TextModel *model = new TextModel(sampleRate, resolution, notifyOnAdd); m_model = model; } else { SparseTimeValueModel *model = new SparseTimeValueModel(sampleRate, resolution, minimum, maximum, notifyOnAdd); model->setScaleUnits(units); m_model = model; } } else { NoteModel *model = new NoteModel(sampleRate, resolution, minimum, maximum, notifyOnAdd); model->setValueQuantization(valueQuantization); model->setScaleUnits(units); m_model = model; } return true; } else { std::cerr << "WARNING: ModelReader-XML: Unexpected sparse model dimension (" << dimensions << ")" << std::endl; } } else if (type == "interval") { READ_MANDATORY(int, dimensions, toInt); READ_MANDATORY(int, resolution, toInt); bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true"); IntervalModel * model = new IntervalModel(sampleRate, resolution, notifyOnAdd); m_model = model; return true; } else { std::cerr << "WARNING: ModelReader-XML: Unexpected model type \"" << type.toLocal8Bit().data() << "\" for model id" << id << std::endl; } return false; } bool ModelHandler::readDatasetStart(const QXmlAttributes &attributes) { bool ok = false; READ_MANDATORY(int, id, toInt); READ_MANDATORY(int, dimensions, toInt); Model *model = m_model; bool good = false; switch (dimensions) { case 1: if (dynamic_cast<SparseOneDimensionalModel *>(model)) good = true; break; case 2: if (dynamic_cast<SparseTimeValueModel *>(model)) good = true; else if (dynamic_cast<TextModel *>(model)) good = true; break; case 3: if (dynamic_cast<NoteModel *>(model)) good = true; else if (dynamic_cast<EditableDenseThreeDimensionalModel *>(model)) { m_datasetSeparator = attributes.value("separator"); good = true; } else if (dynamic_cast<IntervalModel *>(model)) good = true; break; default: break; } if (!good) { std::cerr << "WARNING: ModelReader-XML: Model id " << /*modelId <<*/ " has wrong number of dimensions for " << dimensions << "-D dataset " << id << std::endl; m_model = 0; return false; } return true; } bool ModelHandler::addPointToDataset(const QXmlAttributes &attributes) { bool ok = false; READ_MANDATORY(int, frame, toInt); SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *> (m_model); if (sodm) { QString label = attributes.value("label"); sodm->addPoint(SparseOneDimensionalModel::Point(frame, label)); return true; } SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *> (m_model); if (stvm) { float value = 0.0; value = attributes.value("value").trimmed().toFloat(&ok); QString label = attributes.value("label"); stvm->addPoint(SparseTimeValueModel::Point(frame, value, label)); return ok; } NoteModel *nm = dynamic_cast<NoteModel *>(m_model); if (nm) { float value = 0.0; value = attributes.value("value").trimmed().toFloat(&ok); float duration = 0.0; duration = attributes.value("duration").trimmed().toFloat(&ok); QString label = attributes.value("label"); nm->addPoint(NoteModel::Point(frame, value, duration, label)); return ok; } TextModel *tm = dynamic_cast<TextModel *>(m_model); if (tm) { float height = 0.0; height = attributes.value("height").trimmed().toFloat(&ok); QString label = attributes.value("label"); tm->addPoint(TextModel::Point(frame, height, label)); return ok; } std::cerr << "WARNING: ModelReader-XML: Point element found in non-point dataset" << std::endl; return false; } bool ModelHandler::addBinToDataset(const QXmlAttributes &attributes) { EditableDenseThreeDimensionalModel *dtdm = dynamic_cast<EditableDenseThreeDimensionalModel *>(m_model); if (dtdm) { bool ok = false; int n = attributes.value("number").trimmed().toInt(&ok); if (!ok) { std::cerr << "WARNING: ModelReader-XML: Missing or invalid bin number" << std::endl; return false; } QString name = attributes.value("name"); dtdm->setBinName(n, name); return true; } std::cerr << "WARNING: ModelReader-XML: Bin definition found in incompatible dataset" << std::endl; return false; } bool ModelHandler::addRowToDataset(const QXmlAttributes &attributes) { m_inRow = false; bool ok = false; m_rowNumber = attributes.value("n").trimmed().toInt(&ok); if (!ok) { std::cerr << "WARNING: ModelReader-XML: Missing or invalid row number" << std::endl; return false; } m_inRow = true; return true; } bool ModelHandler::addIntervalToDataset(const QXmlAttributes &attributes) { bool ok = false; IntervalModel *im = dynamic_cast<IntervalModel*> (m_model); if (im) { READ_MANDATORY(int, start, toInt); READ_MANDATORY(int, end, toInt); QString label = attributes.value("label"); float value = 0.0; value = attributes.value("value").trimmed().toFloat(&ok); im->addInterval(start, end, label, value); ok = true; } return ok; } bool ModelHandler::readRowData(const QString &text) { EditableDenseThreeDimensionalModel *dtdm = dynamic_cast<EditableDenseThreeDimensionalModel *>(m_model); bool warned = false; if (dtdm) { QStringList data = text.split(m_datasetSeparator); DenseThreeDimensionalModel::Column values; for (QStringList::iterator i = data.begin(); i != data.end(); ++i) { if (values.size() == dtdm->getHeight()) { if (!warned) { std::cerr << "WARNING: ModelReader-XML: Too many y-bins in 3-D dataset row " << m_rowNumber << std::endl; warned = true; } } bool ok; float value = i->toFloat(&ok); if (!ok) { std::cerr << "WARNING: ModelReader-XML: Bad floating-point value " << i->toLocal8Bit().data() << " in row data" << std::endl; } else { values.push_back(value); } } dtdm->setColumn(m_rowNumber, values); return true; } std::cerr << "WARNING: ModelReader-XML: Row data found in non-row dataset" << std::endl; return false; } bool ModelHandler::readLayer(const QXmlAttributes &attributes) { QString type = attributes.value("type"); m_layer = m_document->createLayer(LayerFactory::getInstance()->getLayerTypeForName(type)); if (!m_layer) { std::cerr << "WARNING: modelreader-XML: Failed to add layer of type \"" << type.toLocal8Bit().data() << "\"" << std::endl; return false; } QString name = attributes.value("name"); m_layer->setObjectName(name); return true; }