Mercurial > hg > sonic-visualiser
comparison document/SVFileReader.cpp @ 0:cd5d7ff8ef38
* Reorganising code base. This revision will not compile.
author | Chris Cannam |
---|---|
date | Mon, 31 Jul 2006 12:03:45 +0000 |
parents | |
children | 40116f709d3b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:cd5d7ff8ef38 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2006 Chris Cannam. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #include "SVFileReader.h" | |
17 | |
18 #include "base/Layer.h" | |
19 #include "base/View.h" | |
20 #include "base/PlayParameters.h" | |
21 #include "base/PlayParameterRepository.h" | |
22 | |
23 #include "AudioFileReaderFactory.h" | |
24 | |
25 #include "model/WaveFileModel.h" | |
26 #include "model/DenseThreeDimensionalModel.h" | |
27 #include "model/SparseOneDimensionalModel.h" | |
28 #include "model/SparseTimeValueModel.h" | |
29 #include "model/NoteModel.h" | |
30 #include "model/TextModel.h" | |
31 | |
32 #include "widgets/Pane.h" | |
33 | |
34 #include "main/Document.h" | |
35 | |
36 #include <QString> | |
37 #include <QMessageBox> | |
38 #include <QFileDialog> | |
39 | |
40 #include <iostream> | |
41 | |
42 SVFileReader::SVFileReader(Document *document, | |
43 SVFileReaderPaneCallback &callback) : | |
44 m_document(document), | |
45 m_paneCallback(callback), | |
46 m_currentPane(0), | |
47 m_currentDataset(0), | |
48 m_currentDerivedModel(0), | |
49 m_currentPlayParameters(0), | |
50 m_datasetSeparator(" "), | |
51 m_inRow(false), | |
52 m_rowNumber(0), | |
53 m_ok(false) | |
54 { | |
55 } | |
56 | |
57 void | |
58 SVFileReader::parse(const QString &xmlData) | |
59 { | |
60 QXmlInputSource inputSource; | |
61 inputSource.setData(xmlData); | |
62 parse(inputSource); | |
63 } | |
64 | |
65 void | |
66 SVFileReader::parse(QXmlInputSource &inputSource) | |
67 { | |
68 QXmlSimpleReader reader; | |
69 reader.setContentHandler(this); | |
70 reader.setErrorHandler(this); | |
71 m_ok = reader.parse(inputSource); | |
72 } | |
73 | |
74 bool | |
75 SVFileReader::isOK() | |
76 { | |
77 return m_ok; | |
78 } | |
79 | |
80 SVFileReader::~SVFileReader() | |
81 { | |
82 if (!m_awaitingDatasets.empty()) { | |
83 std::cerr << "WARNING: SV-XML: File ended with " | |
84 << m_awaitingDatasets.size() << " unfilled model dataset(s)" | |
85 << std::endl; | |
86 } | |
87 | |
88 std::set<Model *> unaddedModels; | |
89 | |
90 for (std::map<int, Model *>::iterator i = m_models.begin(); | |
91 i != m_models.end(); ++i) { | |
92 if (m_addedModels.find(i->second) == m_addedModels.end()) { | |
93 unaddedModels.insert(i->second); | |
94 } | |
95 } | |
96 | |
97 if (!unaddedModels.empty()) { | |
98 std::cerr << "WARNING: SV-XML: File contained " | |
99 << unaddedModels.size() << " unused models" | |
100 << std::endl; | |
101 while (!unaddedModels.empty()) { | |
102 delete *unaddedModels.begin(); | |
103 unaddedModels.erase(unaddedModels.begin()); | |
104 } | |
105 } | |
106 } | |
107 | |
108 bool | |
109 SVFileReader::startElement(const QString &, const QString &, | |
110 const QString &qName, | |
111 const QXmlAttributes &attributes) | |
112 { | |
113 QString name = qName.toLower(); | |
114 | |
115 bool ok = false; | |
116 | |
117 // Valid element names: | |
118 // | |
119 // sv | |
120 // data | |
121 // dataset | |
122 // display | |
123 // derivation | |
124 // playparameters | |
125 // layer | |
126 // model | |
127 // point | |
128 // row | |
129 // view | |
130 // window | |
131 | |
132 if (name == "sv") { | |
133 | |
134 // nothing needed | |
135 ok = true; | |
136 | |
137 } else if (name == "data") { | |
138 | |
139 // nothing needed | |
140 m_inData = true; | |
141 ok = true; | |
142 | |
143 } else if (name == "display") { | |
144 | |
145 // nothing needed | |
146 ok = true; | |
147 | |
148 } else if (name == "window") { | |
149 | |
150 ok = readWindow(attributes); | |
151 | |
152 } else if (name == "model") { | |
153 | |
154 ok = readModel(attributes); | |
155 | |
156 } else if (name == "dataset") { | |
157 | |
158 ok = readDatasetStart(attributes); | |
159 | |
160 } else if (name == "bin") { | |
161 | |
162 ok = addBinToDataset(attributes); | |
163 | |
164 } else if (name == "point") { | |
165 | |
166 ok = addPointToDataset(attributes); | |
167 | |
168 } else if (name == "row") { | |
169 | |
170 ok = addRowToDataset(attributes); | |
171 | |
172 } else if (name == "layer") { | |
173 | |
174 addUnaddedModels(); // all models must be specified before first layer | |
175 ok = readLayer(attributes); | |
176 | |
177 } else if (name == "view") { | |
178 | |
179 m_inView = true; | |
180 ok = readView(attributes); | |
181 | |
182 } else if (name == "derivation") { | |
183 | |
184 ok = readDerivation(attributes); | |
185 | |
186 } else if (name == "playparameters") { | |
187 | |
188 ok = readPlayParameters(attributes); | |
189 | |
190 } else if (name == "plugin") { | |
191 | |
192 ok = readPlugin(attributes); | |
193 | |
194 } else if (name == "selections") { | |
195 | |
196 m_inSelections = true; | |
197 ok = true; | |
198 | |
199 } else if (name == "selection") { | |
200 | |
201 ok = readSelection(attributes); | |
202 } | |
203 | |
204 if (!ok) { | |
205 std::cerr << "WARNING: SV-XML: Failed to completely process element \"" | |
206 << name.toLocal8Bit().data() << "\"" << std::endl; | |
207 } | |
208 | |
209 return true; | |
210 } | |
211 | |
212 bool | |
213 SVFileReader::characters(const QString &text) | |
214 { | |
215 bool ok = false; | |
216 | |
217 if (m_inRow) { | |
218 ok = readRowData(text); | |
219 if (!ok) { | |
220 std::cerr << "WARNING: SV-XML: Failed to read row data content for row " << m_rowNumber << std::endl; | |
221 } | |
222 } | |
223 | |
224 return true; | |
225 } | |
226 | |
227 bool | |
228 SVFileReader::endElement(const QString &, const QString &, | |
229 const QString &qName) | |
230 { | |
231 QString name = qName.toLower(); | |
232 | |
233 if (name == "dataset") { | |
234 | |
235 if (m_currentDataset) { | |
236 | |
237 bool foundInAwaiting = false; | |
238 | |
239 for (std::map<int, int>::iterator i = m_awaitingDatasets.begin(); | |
240 i != m_awaitingDatasets.end(); ++i) { | |
241 if (m_models[i->second] == m_currentDataset) { | |
242 m_awaitingDatasets.erase(i); | |
243 foundInAwaiting = true; | |
244 break; | |
245 } | |
246 } | |
247 | |
248 if (!foundInAwaiting) { | |
249 std::cerr << "WARNING: SV-XML: Dataset precedes model, or no model uses dataset" << std::endl; | |
250 } | |
251 } | |
252 | |
253 m_currentDataset = 0; | |
254 | |
255 } else if (name == "data") { | |
256 | |
257 addUnaddedModels(); | |
258 m_inData = false; | |
259 | |
260 } else if (name == "derivation") { | |
261 | |
262 if (m_currentDerivedModel) { | |
263 m_document->addDerivedModel(m_currentTransform, | |
264 m_document->getMainModel(), //!!! | |
265 m_currentTransformChannel, | |
266 m_currentDerivedModel, | |
267 m_currentTransformConfiguration); | |
268 m_addedModels.insert(m_currentDerivedModel); | |
269 m_currentDerivedModel = 0; | |
270 m_currentTransform = ""; | |
271 m_currentTransformConfiguration = ""; | |
272 } | |
273 | |
274 } else if (name == "row") { | |
275 m_inRow = false; | |
276 } else if (name == "view") { | |
277 m_inView = false; | |
278 } else if (name == "selections") { | |
279 m_inSelections = false; | |
280 } else if (name == "playparameters") { | |
281 m_currentPlayParameters = 0; | |
282 } | |
283 | |
284 return true; | |
285 } | |
286 | |
287 bool | |
288 SVFileReader::error(const QXmlParseException &exception) | |
289 { | |
290 m_errorString = | |
291 QString("ERROR: SV-XML: %1 at line %2, column %3") | |
292 .arg(exception.message()) | |
293 .arg(exception.lineNumber()) | |
294 .arg(exception.columnNumber()); | |
295 std::cerr << m_errorString.toLocal8Bit().data() << std::endl; | |
296 return QXmlDefaultHandler::error(exception); | |
297 } | |
298 | |
299 bool | |
300 SVFileReader::fatalError(const QXmlParseException &exception) | |
301 { | |
302 m_errorString = | |
303 QString("FATAL ERROR: SV-XML: %1 at line %2, column %3") | |
304 .arg(exception.message()) | |
305 .arg(exception.lineNumber()) | |
306 .arg(exception.columnNumber()); | |
307 std::cerr << m_errorString.toLocal8Bit().data() << std::endl; | |
308 return QXmlDefaultHandler::fatalError(exception); | |
309 } | |
310 | |
311 | |
312 #define READ_MANDATORY(TYPE, NAME, CONVERSION) \ | |
313 TYPE NAME = attributes.value(#NAME).trimmed().CONVERSION(&ok); \ | |
314 if (!ok) { \ | |
315 std::cerr << "WARNING: SV-XML: Missing or invalid mandatory " #TYPE " attribute \"" #NAME "\"" << std::endl; \ | |
316 return false; \ | |
317 } | |
318 | |
319 bool | |
320 SVFileReader::readWindow(const QXmlAttributes &attributes) | |
321 { | |
322 bool ok = false; | |
323 | |
324 READ_MANDATORY(int, width, toInt); | |
325 READ_MANDATORY(int, height, toInt); | |
326 | |
327 m_paneCallback.setWindowSize(width, height); | |
328 return true; | |
329 } | |
330 | |
331 void | |
332 SVFileReader::addUnaddedModels() | |
333 { | |
334 std::set<Model *> unaddedModels; | |
335 | |
336 for (std::map<int, Model *>::iterator i = m_models.begin(); | |
337 i != m_models.end(); ++i) { | |
338 if (m_addedModels.find(i->second) == m_addedModels.end()) { | |
339 unaddedModels.insert(i->second); | |
340 } | |
341 } | |
342 | |
343 for (std::set<Model *>::iterator i = unaddedModels.begin(); | |
344 i != unaddedModels.end(); ++i) { | |
345 m_document->addImportedModel(*i); | |
346 m_addedModels.insert(*i); | |
347 } | |
348 } | |
349 | |
350 bool | |
351 SVFileReader::readModel(const QXmlAttributes &attributes) | |
352 { | |
353 bool ok = false; | |
354 | |
355 READ_MANDATORY(int, id, toInt); | |
356 | |
357 if (m_models.find(id) != m_models.end()) { | |
358 std::cerr << "WARNING: SV-XML: Ignoring duplicate model id " << id | |
359 << std::endl; | |
360 return false; | |
361 } | |
362 | |
363 QString name = attributes.value("name"); | |
364 | |
365 READ_MANDATORY(int, sampleRate, toInt); | |
366 | |
367 QString type = attributes.value("type").trimmed(); | |
368 bool mainModel = (attributes.value("mainModel").trimmed() == "true"); | |
369 | |
370 if (type == "wavefile") { | |
371 | |
372 QString file = attributes.value("file"); | |
373 WaveFileModel *model = new WaveFileModel(file); | |
374 | |
375 while (!model->isOK()) { | |
376 | |
377 delete model; | |
378 model = 0; | |
379 | |
380 if (QMessageBox::question(0, | |
381 QMessageBox::tr("Failed to open file"), | |
382 QMessageBox::tr("Audio file \"%1\" could not be opened.\nLocate it?").arg(file), | |
383 QMessageBox::Ok, | |
384 QMessageBox::Cancel) == QMessageBox::Ok) { | |
385 | |
386 QString path = QFileDialog::getOpenFileName | |
387 (0, QFileDialog::tr("Locate file \"%1\"").arg(QFileInfo(file).fileName()), file, | |
388 QFileDialog::tr("Audio files (%1)\nAll files (*.*)") | |
389 .arg(AudioFileReaderFactory::getKnownExtensions())); | |
390 | |
391 if (path != "") { | |
392 model = new WaveFileModel(path); | |
393 } else { | |
394 return false; | |
395 } | |
396 } else { | |
397 return false; | |
398 } | |
399 } | |
400 | |
401 m_models[id] = model; | |
402 if (mainModel) { | |
403 m_document->setMainModel(model); | |
404 m_addedModels.insert(model); | |
405 } | |
406 // Derived models will be added when their derivation | |
407 // is found. | |
408 | |
409 return true; | |
410 | |
411 } else if (type == "dense") { | |
412 | |
413 READ_MANDATORY(int, dimensions, toInt); | |
414 | |
415 // Currently the only dense model we support here | |
416 // is the dense 3d model. Dense time-value models | |
417 // are always file-backed waveform data, at this | |
418 // point, and they come in as the wavefile model | |
419 // type above. | |
420 | |
421 if (dimensions == 3) { | |
422 | |
423 READ_MANDATORY(int, windowSize, toInt); | |
424 READ_MANDATORY(int, yBinCount, toInt); | |
425 | |
426 DenseThreeDimensionalModel *model = | |
427 new DenseThreeDimensionalModel(sampleRate, windowSize, yBinCount); | |
428 | |
429 float minimum = attributes.value("minimum").trimmed().toFloat(&ok); | |
430 if (ok) model->setMinimumLevel(minimum); | |
431 | |
432 float maximum = attributes.value("maximum").trimmed().toFloat(&ok); | |
433 if (ok) model->setMaximumLevel(maximum); | |
434 | |
435 int dataset = attributes.value("dataset").trimmed().toInt(&ok); | |
436 if (ok) m_awaitingDatasets[dataset] = id; | |
437 | |
438 m_models[id] = model; | |
439 return true; | |
440 | |
441 } else { | |
442 | |
443 std::cerr << "WARNING: SV-XML: Unexpected dense model dimension (" | |
444 << dimensions << ")" << std::endl; | |
445 } | |
446 } else if (type == "sparse") { | |
447 | |
448 READ_MANDATORY(int, dimensions, toInt); | |
449 | |
450 if (dimensions == 1) { | |
451 | |
452 READ_MANDATORY(int, resolution, toInt); | |
453 | |
454 SparseOneDimensionalModel *model = new SparseOneDimensionalModel | |
455 (sampleRate, resolution); | |
456 m_models[id] = model; | |
457 | |
458 int dataset = attributes.value("dataset").trimmed().toInt(&ok); | |
459 if (ok) m_awaitingDatasets[dataset] = id; | |
460 | |
461 return true; | |
462 | |
463 } else if (dimensions == 2 || dimensions == 3) { | |
464 | |
465 READ_MANDATORY(int, resolution, toInt); | |
466 | |
467 float minimum = attributes.value("minimum").trimmed().toFloat(&ok); | |
468 float maximum = attributes.value("maximum").trimmed().toFloat(&ok); | |
469 float valueQuantization = | |
470 attributes.value("valueQuantization").trimmed().toFloat(&ok); | |
471 | |
472 bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true"); | |
473 | |
474 QString units = attributes.value("units"); | |
475 | |
476 if (dimensions == 2) { | |
477 if (attributes.value("subtype") == "text") { | |
478 TextModel *model = new TextModel | |
479 (sampleRate, resolution, notifyOnAdd); | |
480 m_models[id] = model; | |
481 } else { | |
482 SparseTimeValueModel *model = new SparseTimeValueModel | |
483 (sampleRate, resolution, minimum, maximum, notifyOnAdd); | |
484 model->setScaleUnits(units); | |
485 m_models[id] = model; | |
486 } | |
487 } else { | |
488 NoteModel *model = new NoteModel | |
489 (sampleRate, resolution, minimum, maximum, notifyOnAdd); | |
490 model->setValueQuantization(valueQuantization); | |
491 model->setScaleUnits(units); | |
492 m_models[id] = model; | |
493 } | |
494 | |
495 int dataset = attributes.value("dataset").trimmed().toInt(&ok); | |
496 if (ok) m_awaitingDatasets[dataset] = id; | |
497 | |
498 return true; | |
499 | |
500 } else { | |
501 | |
502 std::cerr << "WARNING: SV-XML: Unexpected sparse model dimension (" | |
503 << dimensions << ")" << std::endl; | |
504 } | |
505 } else { | |
506 | |
507 std::cerr << "WARNING: SV-XML: Unexpected model type \"" | |
508 << type.toLocal8Bit().data() << "\" for model id" << id << std::endl; | |
509 } | |
510 | |
511 return false; | |
512 } | |
513 | |
514 bool | |
515 SVFileReader::readView(const QXmlAttributes &attributes) | |
516 { | |
517 QString type = attributes.value("type"); | |
518 m_currentPane = 0; | |
519 | |
520 if (type != "pane") { | |
521 std::cerr << "WARNING: SV-XML: Unexpected view type \"" | |
522 << type.toLocal8Bit().data() << "\"" << std::endl; | |
523 return false; | |
524 } | |
525 | |
526 m_currentPane = m_paneCallback.addPane(); | |
527 | |
528 if (!m_currentPane) { | |
529 std::cerr << "WARNING: SV-XML: Internal error: Failed to add pane!" | |
530 << std::endl; | |
531 return false; | |
532 } | |
533 | |
534 bool ok = false; | |
535 | |
536 View *view = m_currentPane; | |
537 | |
538 // The view properties first | |
539 | |
540 READ_MANDATORY(size_t, centre, toUInt); | |
541 READ_MANDATORY(size_t, zoom, toUInt); | |
542 READ_MANDATORY(int, followPan, toInt); | |
543 READ_MANDATORY(int, followZoom, toInt); | |
544 READ_MANDATORY(int, light, toInt); | |
545 QString tracking = attributes.value("tracking"); | |
546 | |
547 // Specify the follow modes before we set the actual values | |
548 view->setFollowGlobalPan(followPan); | |
549 view->setFollowGlobalZoom(followZoom); | |
550 view->setPlaybackFollow(tracking == "scroll" ? View::PlaybackScrollContinuous : | |
551 tracking == "page" ? View::PlaybackScrollPage | |
552 : View::PlaybackIgnore); | |
553 | |
554 // Then set these values | |
555 view->setCentreFrame(centre); | |
556 view->setZoomLevel(zoom); | |
557 view->setLightBackground(light); | |
558 | |
559 // And pane properties | |
560 READ_MANDATORY(int, centreLineVisible, toInt); | |
561 m_currentPane->setCentreLineVisible(centreLineVisible); | |
562 | |
563 int height = attributes.value("height").toInt(&ok); | |
564 if (ok) { | |
565 m_currentPane->resize(m_currentPane->width(), height); | |
566 } | |
567 | |
568 return true; | |
569 } | |
570 | |
571 bool | |
572 SVFileReader::readLayer(const QXmlAttributes &attributes) | |
573 { | |
574 QString type = attributes.value("type"); | |
575 | |
576 int id; | |
577 bool ok = false; | |
578 id = attributes.value("id").trimmed().toInt(&ok); | |
579 | |
580 if (!ok) { | |
581 std::cerr << "WARNING: SV-XML: No layer id for layer of type \"" | |
582 << type.toLocal8Bit().data() | |
583 << "\"" << std::endl; | |
584 return false; | |
585 } | |
586 | |
587 Layer *layer = 0; | |
588 bool isNewLayer = false; | |
589 | |
590 // Layers are expected to be defined in layer elements in the data | |
591 // section, and referred to in layer elements in the view | |
592 // sections. So if we're in the data section, we expect this | |
593 // layer not to exist already; if we're in the view section, we | |
594 // expect it to exist. | |
595 | |
596 if (m_inData) { | |
597 | |
598 if (m_layers.find(id) != m_layers.end()) { | |
599 std::cerr << "WARNING: SV-XML: Ignoring duplicate layer id " << id | |
600 << " in data section" << std::endl; | |
601 return false; | |
602 } | |
603 | |
604 layer = m_layers[id] = m_document->createLayer | |
605 (LayerFactory::getInstance()->getLayerTypeForName(type)); | |
606 | |
607 if (layer) { | |
608 m_layers[id] = layer; | |
609 isNewLayer = true; | |
610 } | |
611 | |
612 } else { | |
613 | |
614 if (!m_currentPane) { | |
615 std::cerr << "WARNING: SV-XML: No current pane for layer " << id | |
616 << " in view section" << std::endl; | |
617 return false; | |
618 } | |
619 | |
620 if (m_layers.find(id) != m_layers.end()) { | |
621 | |
622 layer = m_layers[id]; | |
623 | |
624 } else { | |
625 std::cerr << "WARNING: SV-XML: Layer id " << id | |
626 << " in view section has not been defined -- defining it here" | |
627 << std::endl; | |
628 | |
629 layer = m_document->createLayer | |
630 (LayerFactory::getInstance()->getLayerTypeForName(type)); | |
631 | |
632 if (layer) { | |
633 m_layers[id] = layer; | |
634 isNewLayer = true; | |
635 } | |
636 } | |
637 } | |
638 | |
639 if (!layer) { | |
640 std::cerr << "WARNING: SV-XML: Failed to add layer of type \"" | |
641 << type.toLocal8Bit().data() | |
642 << "\"" << std::endl; | |
643 return false; | |
644 } | |
645 | |
646 if (isNewLayer) { | |
647 | |
648 QString name = attributes.value("name"); | |
649 layer->setObjectName(name); | |
650 | |
651 int modelId; | |
652 bool modelOk = false; | |
653 modelId = attributes.value("model").trimmed().toInt(&modelOk); | |
654 | |
655 if (modelOk) { | |
656 if (m_models.find(modelId) != m_models.end()) { | |
657 Model *model = m_models[modelId]; | |
658 m_document->setModel(layer, model); | |
659 } else { | |
660 std::cerr << "WARNING: SV-XML: Unknown model id " << modelId | |
661 << " in layer definition" << std::endl; | |
662 } | |
663 } | |
664 | |
665 layer->setProperties(attributes); | |
666 } | |
667 | |
668 if (!m_inData && m_currentPane) { | |
669 m_document->addLayerToView(m_currentPane, layer); | |
670 } | |
671 | |
672 return true; | |
673 } | |
674 | |
675 bool | |
676 SVFileReader::readDatasetStart(const QXmlAttributes &attributes) | |
677 { | |
678 bool ok = false; | |
679 | |
680 READ_MANDATORY(int, id, toInt); | |
681 READ_MANDATORY(int, dimensions, toInt); | |
682 | |
683 if (m_awaitingDatasets.find(id) == m_awaitingDatasets.end()) { | |
684 std::cerr << "WARNING: SV-XML: Unwanted dataset " << id << std::endl; | |
685 return false; | |
686 } | |
687 | |
688 int modelId = m_awaitingDatasets[id]; | |
689 | |
690 Model *model = 0; | |
691 if (m_models.find(modelId) != m_models.end()) { | |
692 model = m_models[modelId]; | |
693 } else { | |
694 std::cerr << "WARNING: SV-XML: Internal error: Unknown model " << modelId | |
695 << " expecting dataset " << id << std::endl; | |
696 return false; | |
697 } | |
698 | |
699 bool good = false; | |
700 | |
701 switch (dimensions) { | |
702 case 1: | |
703 if (dynamic_cast<SparseOneDimensionalModel *>(model)) good = true; | |
704 break; | |
705 | |
706 case 2: | |
707 if (dynamic_cast<SparseTimeValueModel *>(model)) good = true; | |
708 else if (dynamic_cast<TextModel *>(model)) good = true; | |
709 break; | |
710 | |
711 case 3: | |
712 if (dynamic_cast<NoteModel *>(model)) good = true; | |
713 else if (dynamic_cast<DenseThreeDimensionalModel *>(model)) { | |
714 m_datasetSeparator = attributes.value("separator"); | |
715 good = true; | |
716 } | |
717 break; | |
718 } | |
719 | |
720 if (!good) { | |
721 std::cerr << "WARNING: SV-XML: Model id " << modelId << " has wrong number of dimensions for " << dimensions << "-D dataset " << id << std::endl; | |
722 m_currentDataset = 0; | |
723 return false; | |
724 } | |
725 | |
726 m_currentDataset = model; | |
727 return true; | |
728 } | |
729 | |
730 bool | |
731 SVFileReader::addPointToDataset(const QXmlAttributes &attributes) | |
732 { | |
733 bool ok = false; | |
734 | |
735 READ_MANDATORY(int, frame, toInt); | |
736 | |
737 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *> | |
738 (m_currentDataset); | |
739 | |
740 if (sodm) { | |
741 QString label = attributes.value("label"); | |
742 sodm->addPoint(SparseOneDimensionalModel::Point(frame, label)); | |
743 return true; | |
744 } | |
745 | |
746 SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *> | |
747 (m_currentDataset); | |
748 | |
749 if (stvm) { | |
750 float value = 0.0; | |
751 value = attributes.value("value").trimmed().toFloat(&ok); | |
752 QString label = attributes.value("label"); | |
753 stvm->addPoint(SparseTimeValueModel::Point(frame, value, label)); | |
754 return ok; | |
755 } | |
756 | |
757 NoteModel *nm = dynamic_cast<NoteModel *>(m_currentDataset); | |
758 | |
759 if (nm) { | |
760 float value = 0.0; | |
761 value = attributes.value("value").trimmed().toFloat(&ok); | |
762 float duration = 0.0; | |
763 duration = attributes.value("duration").trimmed().toFloat(&ok); | |
764 QString label = attributes.value("label"); | |
765 nm->addPoint(NoteModel::Point(frame, value, duration, label)); | |
766 return ok; | |
767 } | |
768 | |
769 TextModel *tm = dynamic_cast<TextModel *>(m_currentDataset); | |
770 | |
771 if (tm) { | |
772 float height = 0.0; | |
773 height = attributes.value("height").trimmed().toFloat(&ok); | |
774 QString label = attributes.value("label"); | |
775 tm->addPoint(TextModel::Point(frame, height, label)); | |
776 return ok; | |
777 } | |
778 | |
779 std::cerr << "WARNING: SV-XML: Point element found in non-point dataset" << std::endl; | |
780 | |
781 return false; | |
782 } | |
783 | |
784 bool | |
785 SVFileReader::addBinToDataset(const QXmlAttributes &attributes) | |
786 { | |
787 DenseThreeDimensionalModel *dtdm = dynamic_cast<DenseThreeDimensionalModel *> | |
788 (m_currentDataset); | |
789 | |
790 if (dtdm) { | |
791 | |
792 bool ok = false; | |
793 int n = attributes.value("number").trimmed().toInt(&ok); | |
794 if (!ok) { | |
795 std::cerr << "WARNING: SV-XML: Missing or invalid bin number" | |
796 << std::endl; | |
797 return false; | |
798 } | |
799 | |
800 QString name = attributes.value("name"); | |
801 | |
802 dtdm->setBinName(n, name); | |
803 return true; | |
804 } | |
805 | |
806 std::cerr << "WARNING: SV-XML: Bin definition found in incompatible dataset" << std::endl; | |
807 | |
808 return false; | |
809 } | |
810 | |
811 | |
812 bool | |
813 SVFileReader::addRowToDataset(const QXmlAttributes &attributes) | |
814 { | |
815 m_inRow = false; | |
816 | |
817 bool ok = false; | |
818 m_rowNumber = attributes.value("n").trimmed().toInt(&ok); | |
819 if (!ok) { | |
820 std::cerr << "WARNING: SV-XML: Missing or invalid row number" | |
821 << std::endl; | |
822 return false; | |
823 } | |
824 | |
825 m_inRow = true; | |
826 | |
827 // std::cerr << "SV-XML: In row " << m_rowNumber << std::endl; | |
828 | |
829 return true; | |
830 } | |
831 | |
832 bool | |
833 SVFileReader::readRowData(const QString &text) | |
834 { | |
835 DenseThreeDimensionalModel *dtdm = dynamic_cast<DenseThreeDimensionalModel *> | |
836 (m_currentDataset); | |
837 | |
838 bool warned = false; | |
839 | |
840 if (dtdm) { | |
841 QStringList data = text.split(m_datasetSeparator); | |
842 | |
843 DenseThreeDimensionalModel::BinValueSet values; | |
844 | |
845 for (QStringList::iterator i = data.begin(); i != data.end(); ++i) { | |
846 | |
847 if (values.size() == dtdm->getYBinCount()) { | |
848 if (!warned) { | |
849 std::cerr << "WARNING: SV-XML: Too many y-bins in 3-D dataset row " | |
850 << m_rowNumber << std::endl; | |
851 warned = true; | |
852 } | |
853 } | |
854 | |
855 bool ok; | |
856 float value = i->toFloat(&ok); | |
857 if (!ok) { | |
858 std::cerr << "WARNING: SV-XML: Bad floating-point value " | |
859 << i->toLocal8Bit().data() | |
860 << " in row data" << std::endl; | |
861 } else { | |
862 values.push_back(value); | |
863 } | |
864 } | |
865 | |
866 size_t windowStartFrame = m_rowNumber * dtdm->getWindowSize(); | |
867 | |
868 dtdm->setBinValues(windowStartFrame, values); | |
869 return true; | |
870 } | |
871 | |
872 std::cerr << "WARNING: SV-XML: Row data found in non-row dataset" << std::endl; | |
873 | |
874 return false; | |
875 } | |
876 | |
877 bool | |
878 SVFileReader::readDerivation(const QXmlAttributes &attributes) | |
879 { | |
880 int modelId = 0; | |
881 bool modelOk = false; | |
882 modelId = attributes.value("model").trimmed().toInt(&modelOk); | |
883 | |
884 if (!modelOk) { | |
885 std::cerr << "WARNING: SV-XML: No model id specified for derivation" << std::endl; | |
886 return false; | |
887 } | |
888 | |
889 QString transform = attributes.value("transform"); | |
890 | |
891 if (m_models.find(modelId) != m_models.end()) { | |
892 | |
893 m_currentDerivedModel = m_models[modelId]; | |
894 m_currentTransform = transform; | |
895 m_currentTransformConfiguration = ""; | |
896 | |
897 bool ok = false; | |
898 int channel = attributes.value("channel").trimmed().toInt(&ok); | |
899 if (ok) m_currentTransformChannel = channel; | |
900 else m_currentTransformChannel = -1; | |
901 | |
902 } else { | |
903 std::cerr << "WARNING: SV-XML: Unknown derived model " << modelId | |
904 << " for transform \"" << transform.toLocal8Bit().data() << "\"" | |
905 << std::endl; | |
906 return false; | |
907 } | |
908 | |
909 return true; | |
910 } | |
911 | |
912 bool | |
913 SVFileReader::readPlayParameters(const QXmlAttributes &attributes) | |
914 { | |
915 m_currentPlayParameters = 0; | |
916 | |
917 int modelId = 0; | |
918 bool modelOk = false; | |
919 modelId = attributes.value("model").trimmed().toInt(&modelOk); | |
920 | |
921 if (!modelOk) { | |
922 std::cerr << "WARNING: SV-XML: No model id specified for play parameters" << std::endl; | |
923 return false; | |
924 } | |
925 | |
926 if (m_models.find(modelId) != m_models.end()) { | |
927 | |
928 bool ok = false; | |
929 | |
930 PlayParameters *parameters = PlayParameterRepository::getInstance()-> | |
931 getPlayParameters(m_models[modelId]); | |
932 | |
933 if (!parameters) { | |
934 std::cerr << "WARNING: SV-XML: Play parameters for model " | |
935 << modelId | |
936 << " not found - has model been added to document?" | |
937 << std::endl; | |
938 return false; | |
939 } | |
940 | |
941 bool muted = (attributes.value("mute").trimmed() == "true"); | |
942 if (ok) parameters->setPlayMuted(muted); | |
943 | |
944 float pan = attributes.value("pan").toFloat(&ok); | |
945 if (ok) parameters->setPlayPan(pan); | |
946 | |
947 float gain = attributes.value("gain").toFloat(&ok); | |
948 if (ok) parameters->setPlayGain(gain); | |
949 | |
950 QString pluginId = attributes.value("pluginId"); | |
951 if (pluginId != "") parameters->setPlayPluginId(pluginId); | |
952 | |
953 m_currentPlayParameters = parameters; | |
954 | |
955 // std::cerr << "Current play parameters for model: " << m_models[modelId] << ": " << m_currentPlayParameters << std::endl; | |
956 | |
957 } else { | |
958 | |
959 std::cerr << "WARNING: SV-XML: Unknown model " << modelId | |
960 << " for play parameters" << std::endl; | |
961 return false; | |
962 } | |
963 | |
964 return true; | |
965 } | |
966 | |
967 bool | |
968 SVFileReader::readPlugin(const QXmlAttributes &attributes) | |
969 { | |
970 if (!m_currentDerivedModel && !m_currentPlayParameters) { | |
971 std::cerr << "WARNING: SV-XML: Plugin found outside derivation or play parameters" << std::endl; | |
972 return false; | |
973 } | |
974 | |
975 QString configurationXml = "<plugin"; | |
976 | |
977 for (int i = 0; i < attributes.length(); ++i) { | |
978 configurationXml += QString(" %1=\"%2\"") | |
979 .arg(attributes.qName(i)).arg(attributes.value(i)); | |
980 } | |
981 | |
982 configurationXml += "/>"; | |
983 | |
984 if (m_currentPlayParameters) { | |
985 m_currentPlayParameters->setPlayPluginConfiguration(configurationXml); | |
986 } else { | |
987 m_currentTransformConfiguration += configurationXml; | |
988 } | |
989 | |
990 return true; | |
991 } | |
992 | |
993 bool | |
994 SVFileReader::readSelection(const QXmlAttributes &attributes) | |
995 { | |
996 bool ok; | |
997 | |
998 READ_MANDATORY(int, start, toInt); | |
999 READ_MANDATORY(int, end, toInt); | |
1000 | |
1001 m_paneCallback.addSelection(start, end); | |
1002 | |
1003 return true; | |
1004 } | |
1005 |