comparison data/fileio/ModelReader.cpp @ 15:11e298cdb9e7

add - EasaierSessionManager - Easaier menus - Interval model
author lbajardsilogic
date Mon, 14 May 2007 13:10:49 +0000
parents
children 4eb9c7e4acf6
comparison
equal deleted inserted replaced
14:819ad579459f 15:11e298cdb9e7
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /* Sound Access
4 EASAIER client application.
5 Silogic 2007. Laure Bajard.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version. See the file
11 COPYING included with this distribution for more information.
12 */
13
14 #include "ModelReader.h"
15
16 #include "document/Document.h"
17 #include "layer/Layer.h"
18
19 #include "data/model/EditableDenseThreeDimensionalModel.h"
20 #include "data/model/SparseOneDimensionalModel.h"
21 #include "data/model/SparseTimeValueModel.h"
22 #include "data/model/NoteModel.h"
23 #include "data/model/TextModel.h"
24 #include "data/model/IntervalModel.h"
25 #include "view/Pane.h"
26
27 #include <iostream>
28
29 ModelReader::ModelReader(Document *document, Layer * layer, Pane * pane) :
30 m_document(document),
31 m_layer(layer),
32 m_pane(pane)
33 {}
34
35 bool ModelReader::parse(const QString & filename)
36 {
37 ModelHandler handler(m_document, m_layer, m_pane);
38 QXmlSimpleReader reader;
39 reader.setContentHandler(&handler);
40 reader.setErrorHandler(&handler);
41
42 QFile file(filename);
43
44 if (!file.open(QFile::ReadOnly | QFile::Text)) {
45 return false;
46 }
47
48 QXmlInputSource xmlInputSource(&file);
49 if (reader.parse(xmlInputSource))
50 {
51 return true;
52 }
53
54 return false;
55 }
56
57 ModelHandler::ModelHandler(Document *document, Layer * layer, Pane* pane) : QXmlDefaultHandler(),
58 m_document(document),
59 m_layer(layer),
60 m_pane(pane),
61 m_model(0),
62 m_datasetSeparator(" "),
63 m_inData(false),
64 m_inRow(false),
65 m_rowNumber(0)
66 {}
67
68 bool ModelHandler::startElement(const QString &namespaceURI, const QString &localName,
69 const QString &qName, const QXmlAttributes &attributes)
70 {
71
72 QString name = qName.toLower();
73
74 bool ok = false;
75
76 // Valid element names:
77 //
78 // easaier
79 // data
80 // dataset
81 // model
82 // point
83 // row
84 // interval
85
86 if (name == "easaier") {
87
88 // nothing needed
89 ok = true;
90
91 } else if (name == "data") {
92
93 m_inData = true;
94 if (m_layer == 0)
95 {
96 ok = readLayer(attributes);
97 } else {
98 ok = true;
99 }
100
101 } else if (name == "model") {
102
103 ok = readModel(attributes);
104
105 } else if (name == "dataset") {
106
107 ok = readDatasetStart(attributes);
108
109 } else if (name == "bin") {
110
111 ok = addBinToDataset(attributes);
112
113 } else if (name == "point") {
114
115 ok = addPointToDataset(attributes);
116
117 } else if (name == "row") {
118
119 ok = addRowToDataset(attributes);
120
121 } else if (name == "interval") {
122
123 ok = addIntervalToDataset(attributes);
124
125 }
126
127 if (!ok) {
128 std::cerr << "WARNING: ModelReader-XML: Failed to completely process element \""
129 << name.toLocal8Bit().data() << "\"" << std::endl;
130 }
131
132 return true;
133 }
134
135 bool ModelHandler::endElement(const QString &namespaceURI, const QString &localName,
136 const QString &qName)
137 {
138 QString name = qName.toLower();
139
140 if (name == "dataset")
141 {
142 if ((m_model) && (m_layer))
143 {
144 m_document->addImportedModel(m_model);
145 m_document->setModel(m_layer, m_model);
146 }
147 }
148 else if (name == "data")
149 {
150 m_inData = false;
151 if (m_pane && m_layer)
152 {
153 m_document->addLayerToView(m_pane, m_layer);
154 }
155 }
156 else if (name == "row")
157 {
158 m_inRow = false;
159 }
160
161 return true;
162 }
163
164 bool ModelHandler::characters(const QString &str)
165 {
166 bool ok = false;
167
168 if (m_inRow) {
169 ok = readRowData(str);
170 if (!ok) {
171 std::cerr << "WARNING: ModelReader-XML: Failed to read row data content for row " << m_rowNumber << std::endl;
172 }
173 }
174
175 return true;
176 }
177
178 bool ModelHandler::error(const QXmlParseException &exception)
179 {
180 QString errorString;
181 errorString += QString("ERROR: ModelReader-XML: %1 at line %2, column %3")
182 .arg(exception.message())
183 .arg(exception.lineNumber())
184 .arg(exception.columnNumber());
185 std::cerr << errorString.toLocal8Bit().data() << std::endl;
186 return QXmlDefaultHandler::error(exception);
187 }
188
189 bool ModelHandler::fatalError(const QXmlParseException &exception)
190 {
191 QString errorString;
192 errorString += QString("FATAL ERROR: ModelReader-XML: %1 at line %2, column %3")
193 .arg(exception.message())
194 .arg(exception.lineNumber())
195 .arg(exception.columnNumber());
196 std::cerr << errorString.toLocal8Bit().data() << std::endl;
197 return QXmlDefaultHandler::fatalError(exception);
198 }
199
200 #define READ_MANDATORY(TYPE, NAME, CONVERSION) \
201 TYPE NAME = attributes.value(#NAME).trimmed().CONVERSION(&ok); \
202 if (!ok) { \
203 std::cerr << "WARNING: ModelReader-XML: Missing or invalid mandatory " #TYPE " attribute \"" #NAME "\"" << std::endl; \
204 return false; \
205 }
206
207 bool ModelHandler::readModel(const QXmlAttributes &attributes)
208 {
209 bool ok = false;
210
211 READ_MANDATORY(int, id, toInt);
212
213 QString name = attributes.value("name");
214
215 if (m_layer->getModelName() == "")
216 {
217 m_layer->setModelName(name);
218 m_layer->setModelId(id);
219 }
220
221 READ_MANDATORY(int, sampleRate, toInt);
222
223 QString type = attributes.value("type").trimmed();
224 bool mainModel = (attributes.value("mainModel").trimmed() == "true");
225
226 if (type == "dense")
227 {
228
229 READ_MANDATORY(int, dimensions, toInt);
230
231 // Currently the only dense model we support here
232 // is the dense 3d model. Dense time-value models
233 // are always file-backed waveform data, at this
234 // point, and they come in as the wavefile model
235 // type above.
236
237 if (dimensions == 3)
238 {
239
240 READ_MANDATORY(int, windowSize, toInt);
241 READ_MANDATORY(int, yBinCount, toInt);
242
243 //DenseThreeDimensionalModel *model =
244 //new DenseThreeDimensionalModel(sampleRate, windowSize, yBinCount);
245
246 EditableDenseThreeDimensionalModel *model =
247 new EditableDenseThreeDimensionalModel(sampleRate, windowSize, yBinCount);
248
249 float minimum = attributes.value("minimum").trimmed().toFloat(&ok);
250 if (ok) model->setMinimumLevel(minimum);
251
252 float maximum = attributes.value("maximum").trimmed().toFloat(&ok);
253 if (ok) model->setMaximumLevel(maximum);
254
255 m_model = model;
256 return true;
257
258 } else
259 {
260 std::cerr << "WARNING: ModelReader-XML: Unexpected dense model dimension ("
261 << dimensions << ")" << std::endl;
262 }
263 } else if (type == "sparse")
264 {
265 READ_MANDATORY(int, dimensions, toInt);
266
267 if (dimensions == 1)
268 {
269
270 READ_MANDATORY(int, resolution, toInt);
271 SparseOneDimensionalModel *model = new SparseOneDimensionalModel(sampleRate, resolution);
272 m_model = model;
273
274 return true;
275
276 } else if (dimensions == 2 || dimensions == 3)
277 {
278 READ_MANDATORY(int, resolution, toInt);
279
280 float minimum = attributes.value("minimum").trimmed().toFloat(&ok);
281 float maximum = attributes.value("maximum").trimmed().toFloat(&ok);
282 float valueQuantization = attributes.value("valueQuantization").trimmed().toFloat(&ok);
283
284 bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true");
285
286 QString units = attributes.value("units");
287
288 if (dimensions == 2)
289 {
290 if (attributes.value("subtype") == "text")
291 {
292 TextModel *model = new TextModel(sampleRate, resolution, notifyOnAdd);
293 m_model = model;
294 } else
295 {
296 SparseTimeValueModel *model = new SparseTimeValueModel(sampleRate, resolution, minimum, maximum, notifyOnAdd);
297 model->setScaleUnits(units);
298 m_model = model;
299 }
300 } else
301 {
302 NoteModel *model = new NoteModel(sampleRate, resolution, minimum, maximum, notifyOnAdd);
303 model->setValueQuantization(valueQuantization);
304 model->setScaleUnits(units);
305 m_model = model;
306 }
307 return true;
308
309 } else
310 {
311 std::cerr << "WARNING: ModelReader-XML: Unexpected sparse model dimension ("
312 << dimensions << ")" << std::endl;
313 }
314 } else if (type == "interval")
315 {
316 READ_MANDATORY(int, dimensions, toInt);
317 READ_MANDATORY(int, resolution, toInt);
318 bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true");
319
320 IntervalModel * model = new IntervalModel(sampleRate, resolution, notifyOnAdd);
321 m_model = model;
322 return true;
323
324 } else
325 {
326 std::cerr << "WARNING: ModelReader-XML: Unexpected model type \""
327 << type.toLocal8Bit().data() << "\" for model id" << id << std::endl;
328 }
329
330 return false;
331 }
332
333 bool ModelHandler::readDatasetStart(const QXmlAttributes &attributes)
334 {
335 bool ok = false;
336
337 READ_MANDATORY(int, id, toInt);
338 READ_MANDATORY(int, dimensions, toInt);
339
340 Model *model = m_model;
341
342 bool good = false;
343
344 switch (dimensions) {
345 case 1:
346 if (dynamic_cast<SparseOneDimensionalModel *>(model)) good = true;
347 break;
348
349 case 2:
350 if (dynamic_cast<SparseTimeValueModel *>(model)) good = true;
351 else if (dynamic_cast<TextModel *>(model)) good = true;
352 break;
353
354 case 3:
355 if (dynamic_cast<NoteModel *>(model)) good = true;
356 else if (dynamic_cast<DenseThreeDimensionalModel *>(model)) {
357 m_datasetSeparator = attributes.value("separator");
358 good = true;
359 }
360 else if (dynamic_cast<IntervalModel *>(model)) good = true;
361 break;
362
363 default:
364 break;
365 }
366
367 if (!good) {
368 std::cerr << "WARNING: ModelReader-XML: Model id " << /*modelId <<*/ " has wrong number of dimensions for " << dimensions << "-D dataset " << id << std::endl;
369 m_model = 0;
370 return false;
371 }
372
373 return true;
374 }
375
376 bool ModelHandler::addPointToDataset(const QXmlAttributes &attributes)
377 {
378 bool ok = false;
379
380 READ_MANDATORY(int, frame, toInt);
381
382 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *> (m_model);
383
384 if (sodm)
385 {
386 QString label = attributes.value("label");
387 sodm->addPoint(SparseOneDimensionalModel::Point(frame, label));
388 return true;
389 }
390
391 SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *> (m_model);
392
393 if (stvm)
394 {
395 float value = 0.0;
396 value = attributes.value("value").trimmed().toFloat(&ok);
397 QString label = attributes.value("label");
398 stvm->addPoint(SparseTimeValueModel::Point(frame, value, label));
399 return ok;
400 }
401
402 NoteModel *nm = dynamic_cast<NoteModel *>(m_model);
403
404 if (nm)
405 {
406 float value = 0.0;
407 value = attributes.value("value").trimmed().toFloat(&ok);
408 float duration = 0.0;
409 duration = attributes.value("duration").trimmed().toFloat(&ok);
410 QString label = attributes.value("label");
411 nm->addPoint(NoteModel::Point(frame, value, duration, label));
412 return ok;
413 }
414
415 TextModel *tm = dynamic_cast<TextModel *>(m_model);
416
417 if (tm)
418 {
419 float height = 0.0;
420 height = attributes.value("height").trimmed().toFloat(&ok);
421 QString label = attributes.value("label");
422 tm->addPoint(TextModel::Point(frame, height, label));
423 return ok;
424 }
425
426 std::cerr << "WARNING: ModelReader-XML: Point element found in non-point dataset" << std::endl;
427
428 return false;
429 }
430
431 bool ModelHandler::addBinToDataset(const QXmlAttributes &attributes)
432 {
433 //DenseThreeDimensionalModel *dtdm = dynamic_cast<DenseThreeDimensionalModel *> (m_model);
434 EditableDenseThreeDimensionalModel *dtdm = dynamic_cast<EditableDenseThreeDimensionalModel *>(m_model);
435
436 if (dtdm) {
437
438 bool ok = false;
439 int n = attributes.value("number").trimmed().toInt(&ok);
440 if (!ok) {
441 std::cerr << "WARNING: ModelReader-XML: Missing or invalid bin number"
442 << std::endl;
443 return false;
444 }
445
446 QString name = attributes.value("name");
447
448 dtdm->setBinName(n, name);
449 return true;
450 }
451
452 std::cerr << "WARNING: ModelReader-XML: Bin definition found in incompatible dataset" << std::endl;
453
454 return false;
455 }
456
457
458 bool ModelHandler::addRowToDataset(const QXmlAttributes &attributes)
459 {
460 m_inRow = false;
461
462 bool ok = false;
463 m_rowNumber = attributes.value("n").trimmed().toInt(&ok);
464 if (!ok) {
465 std::cerr << "WARNING: ModelReader-XML: Missing or invalid row number"
466 << std::endl;
467 return false;
468 }
469
470 m_inRow = true;
471
472 return true;
473 }
474
475 bool ModelHandler::addIntervalToDataset(const QXmlAttributes &attributes)
476 {
477 bool ok = false;
478
479 IntervalModel *im = dynamic_cast<IntervalModel*> (m_model);
480 if (im)
481 {
482 READ_MANDATORY(int, start, toInt);
483 READ_MANDATORY(int, end, toInt);
484 QString label = attributes.value("label");
485 float value = 0.0;
486 value = attributes.value("value").trimmed().toFloat(&ok);
487 im->addInterval(start, end, label, value);
488 ok = true;
489 }
490 return ok;
491 }
492
493 bool ModelHandler::readRowData(const QString &text)
494 {
495 EditableDenseThreeDimensionalModel *dtdm = dynamic_cast<EditableDenseThreeDimensionalModel *>(m_model);
496
497 bool warned = false;
498
499 if (dtdm) {
500 QStringList data = text.split(m_datasetSeparator);
501
502 DenseThreeDimensionalModel::Column values;
503
504 for (QStringList::iterator i = data.begin(); i != data.end(); ++i) {
505
506 if (values.size() == dtdm->getHeight()) {
507 if (!warned) {
508 std::cerr << "WARNING: ModelReader-XML: Too many y-bins in 3-D dataset row "
509 << m_rowNumber << std::endl;
510 warned = true;
511 }
512 }
513
514 bool ok;
515 float value = i->toFloat(&ok);
516 if (!ok) {
517 std::cerr << "WARNING: ModelReader-XML: Bad floating-point value "
518 << i->toLocal8Bit().data()
519 << " in row data" << std::endl;
520 } else {
521 values.push_back(value);
522 }
523 }
524
525 dtdm->setColumn(m_rowNumber, values);
526 return true;
527 }
528
529 std::cerr << "WARNING: ModelReader-XML: Row data found in non-row dataset" << std::endl;
530
531 return false;
532 }
533
534 bool ModelHandler::readLayer(const QXmlAttributes &attributes)
535 {
536 QString type = attributes.value("type");
537
538 m_layer = m_document->createLayer(LayerFactory::getInstance()->getLayerTypeForName(type));
539
540 if (!m_layer) {
541 std::cerr << "WARNING: modelreader-XML: Failed to add layer of type \""
542 << type.toLocal8Bit().data()
543 << "\"" << std::endl;
544 return false;
545 }
546
547 QString name = attributes.value("name");
548 m_layer->setObjectName(name);
549
550 return true;
551 }