Mercurial > hg > easaier-soundaccess
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 } |