Mercurial > hg > svapp
comparison framework/SVFileReader.cpp @ 45:9ea770d93fae
* document -> framework (will not compile, path fixes not in yet)
author | Chris Cannam |
---|---|
date | Wed, 24 Oct 2007 16:37:58 +0000 |
parents | |
children | 73f682a551dc |
comparison
equal
deleted
inserted
replaced
44:9ebe12983f3e | 45:9ea770d93fae |
---|---|
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 and QMUL. | |
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 "layer/Layer.h" | |
19 #include "view/View.h" | |
20 #include "base/PlayParameters.h" | |
21 #include "base/PlayParameterRepository.h" | |
22 | |
23 #include "data/fileio/AudioFileReaderFactory.h" | |
24 #include "data/fileio/FileFinder.h" | |
25 #include "data/fileio/FileSource.h" | |
26 | |
27 #include "data/model/WaveFileModel.h" | |
28 #include "data/model/EditableDenseThreeDimensionalModel.h" | |
29 #include "data/model/SparseOneDimensionalModel.h" | |
30 #include "data/model/SparseTimeValueModel.h" | |
31 #include "data/model/NoteModel.h" | |
32 #include "data/model/TextModel.h" | |
33 #include "data/model/ImageModel.h" | |
34 | |
35 #include "view/Pane.h" | |
36 | |
37 #include "Document.h" | |
38 | |
39 #include <QString> | |
40 #include <QMessageBox> | |
41 #include <QFileDialog> | |
42 | |
43 #include <iostream> | |
44 | |
45 SVFileReader::SVFileReader(Document *document, | |
46 SVFileReaderPaneCallback &callback, | |
47 QString location) : | |
48 m_document(document), | |
49 m_paneCallback(callback), | |
50 m_location(location), | |
51 m_currentPane(0), | |
52 m_currentDataset(0), | |
53 m_currentDerivedModel(0), | |
54 m_currentDerivedModelId(-1), | |
55 m_currentPlayParameters(0), | |
56 m_datasetSeparator(" "), | |
57 m_inRow(false), | |
58 m_inLayer(false), | |
59 m_inView(false), | |
60 m_rowNumber(0), | |
61 m_ok(false) | |
62 { | |
63 } | |
64 | |
65 void | |
66 SVFileReader::parse(const QString &xmlData) | |
67 { | |
68 QXmlInputSource inputSource; | |
69 inputSource.setData(xmlData); | |
70 parse(inputSource); | |
71 } | |
72 | |
73 void | |
74 SVFileReader::parse(QXmlInputSource &inputSource) | |
75 { | |
76 QXmlSimpleReader reader; | |
77 reader.setContentHandler(this); | |
78 reader.setErrorHandler(this); | |
79 m_ok = reader.parse(inputSource); | |
80 } | |
81 | |
82 bool | |
83 SVFileReader::isOK() | |
84 { | |
85 return m_ok; | |
86 } | |
87 | |
88 SVFileReader::~SVFileReader() | |
89 { | |
90 if (!m_awaitingDatasets.empty()) { | |
91 std::cerr << "WARNING: SV-XML: File ended with " | |
92 << m_awaitingDatasets.size() << " unfilled model dataset(s)" | |
93 << std::endl; | |
94 } | |
95 | |
96 std::set<Model *> unaddedModels; | |
97 | |
98 for (std::map<int, Model *>::iterator i = m_models.begin(); | |
99 i != m_models.end(); ++i) { | |
100 if (m_addedModels.find(i->second) == m_addedModels.end()) { | |
101 unaddedModels.insert(i->second); | |
102 } | |
103 } | |
104 | |
105 if (!unaddedModels.empty()) { | |
106 std::cerr << "WARNING: SV-XML: File contained " | |
107 << unaddedModels.size() << " unused models" | |
108 << std::endl; | |
109 while (!unaddedModels.empty()) { | |
110 delete *unaddedModels.begin(); | |
111 unaddedModels.erase(unaddedModels.begin()); | |
112 } | |
113 } | |
114 } | |
115 | |
116 bool | |
117 SVFileReader::startElement(const QString &, const QString &, | |
118 const QString &qName, | |
119 const QXmlAttributes &attributes) | |
120 { | |
121 QString name = qName.toLower(); | |
122 | |
123 bool ok = false; | |
124 | |
125 // Valid element names: | |
126 // | |
127 // sv | |
128 // data | |
129 // dataset | |
130 // display | |
131 // derivation | |
132 // playparameters | |
133 // layer | |
134 // model | |
135 // point | |
136 // row | |
137 // view | |
138 // window | |
139 | |
140 if (name == "sv") { | |
141 | |
142 // nothing needed | |
143 ok = true; | |
144 | |
145 } else if (name == "data") { | |
146 | |
147 // nothing needed | |
148 m_inData = true; | |
149 ok = true; | |
150 | |
151 } else if (name == "display") { | |
152 | |
153 // nothing needed | |
154 ok = true; | |
155 | |
156 } else if (name == "window") { | |
157 | |
158 ok = readWindow(attributes); | |
159 | |
160 } else if (name == "model") { | |
161 | |
162 ok = readModel(attributes); | |
163 | |
164 } else if (name == "dataset") { | |
165 | |
166 ok = readDatasetStart(attributes); | |
167 | |
168 } else if (name == "bin") { | |
169 | |
170 ok = addBinToDataset(attributes); | |
171 | |
172 } else if (name == "point") { | |
173 | |
174 ok = addPointToDataset(attributes); | |
175 | |
176 } else if (name == "row") { | |
177 | |
178 ok = addRowToDataset(attributes); | |
179 | |
180 } else if (name == "layer") { | |
181 | |
182 addUnaddedModels(); // all models must be specified before first layer | |
183 ok = readLayer(attributes); | |
184 | |
185 } else if (name == "view") { | |
186 | |
187 m_inView = true; | |
188 ok = readView(attributes); | |
189 | |
190 } else if (name == "derivation") { | |
191 | |
192 ok = readDerivation(attributes); | |
193 | |
194 } else if (name == "playparameters") { | |
195 | |
196 ok = readPlayParameters(attributes); | |
197 | |
198 } else if (name == "plugin") { | |
199 | |
200 ok = readPlugin(attributes); | |
201 | |
202 } else if (name == "selections") { | |
203 | |
204 m_inSelections = true; | |
205 ok = true; | |
206 | |
207 } else if (name == "selection") { | |
208 | |
209 ok = readSelection(attributes); | |
210 | |
211 } else if (name == "measurement") { | |
212 | |
213 ok = readMeasurement(attributes); | |
214 | |
215 } else { | |
216 std::cerr << "WARNING: SV-XML: Unexpected element \"" | |
217 << name.toLocal8Bit().data() << "\"" << std::endl; | |
218 } | |
219 | |
220 if (!ok) { | |
221 std::cerr << "WARNING: SV-XML: Failed to completely process element \"" | |
222 << name.toLocal8Bit().data() << "\"" << std::endl; | |
223 } | |
224 | |
225 return true; | |
226 } | |
227 | |
228 bool | |
229 SVFileReader::characters(const QString &text) | |
230 { | |
231 bool ok = false; | |
232 | |
233 if (m_inRow) { | |
234 ok = readRowData(text); | |
235 if (!ok) { | |
236 std::cerr << "WARNING: SV-XML: Failed to read row data content for row " << m_rowNumber << std::endl; | |
237 } | |
238 } | |
239 | |
240 return true; | |
241 } | |
242 | |
243 bool | |
244 SVFileReader::endElement(const QString &, const QString &, | |
245 const QString &qName) | |
246 { | |
247 QString name = qName.toLower(); | |
248 | |
249 if (name == "dataset") { | |
250 | |
251 if (m_currentDataset) { | |
252 | |
253 bool foundInAwaiting = false; | |
254 | |
255 for (std::map<int, int>::iterator i = m_awaitingDatasets.begin(); | |
256 i != m_awaitingDatasets.end(); ++i) { | |
257 if (haveModel(i->second) && | |
258 m_models[i->second] == m_currentDataset) { | |
259 m_awaitingDatasets.erase(i); | |
260 foundInAwaiting = true; | |
261 break; | |
262 } | |
263 } | |
264 | |
265 if (!foundInAwaiting) { | |
266 std::cerr << "WARNING: SV-XML: Dataset precedes model, or no model uses dataset" << std::endl; | |
267 } | |
268 } | |
269 | |
270 m_currentDataset = 0; | |
271 | |
272 } else if (name == "data") { | |
273 | |
274 addUnaddedModels(); | |
275 m_inData = false; | |
276 | |
277 } else if (name == "derivation") { | |
278 | |
279 if (!m_currentDerivedModel) { | |
280 if (m_currentDerivedModel < 0) { | |
281 std::cerr << "WARNING: SV-XML: Bad derivation output model id " | |
282 << m_currentDerivedModelId << std::endl; | |
283 } else if (haveModel(m_currentDerivedModelId)) { | |
284 std::cerr << "WARNING: SV-XML: Derivation has existing model " | |
285 << m_currentDerivedModelId | |
286 << " as target, not regenerating" << std::endl; | |
287 } else { | |
288 m_currentDerivedModel = m_models[m_currentDerivedModelId] = | |
289 m_document->addDerivedModel(m_currentTransform, | |
290 m_currentTransformSource, | |
291 m_currentTransformContext, | |
292 m_currentTransformConfiguration); | |
293 } | |
294 } else { | |
295 m_document->addDerivedModel(m_currentTransform, | |
296 m_currentTransformSource, | |
297 m_currentTransformContext, | |
298 m_currentDerivedModel, | |
299 m_currentTransformConfiguration); | |
300 } | |
301 | |
302 m_addedModels.insert(m_currentDerivedModel); | |
303 m_currentDerivedModel = 0; | |
304 m_currentDerivedModelId = -1; | |
305 m_currentTransform = ""; | |
306 m_currentTransformConfiguration = ""; | |
307 | |
308 } else if (name == "row") { | |
309 m_inRow = false; | |
310 } else if (name == "layer") { | |
311 m_inLayer = false; | |
312 } else if (name == "view") { | |
313 m_inView = false; | |
314 } else if (name == "selections") { | |
315 m_inSelections = false; | |
316 } else if (name == "playparameters") { | |
317 m_currentPlayParameters = 0; | |
318 } | |
319 | |
320 return true; | |
321 } | |
322 | |
323 bool | |
324 SVFileReader::error(const QXmlParseException &exception) | |
325 { | |
326 m_errorString = | |
327 QString("ERROR: SV-XML: %1 at line %2, column %3") | |
328 .arg(exception.message()) | |
329 .arg(exception.lineNumber()) | |
330 .arg(exception.columnNumber()); | |
331 std::cerr << m_errorString.toLocal8Bit().data() << std::endl; | |
332 return QXmlDefaultHandler::error(exception); | |
333 } | |
334 | |
335 bool | |
336 SVFileReader::fatalError(const QXmlParseException &exception) | |
337 { | |
338 m_errorString = | |
339 QString("FATAL ERROR: SV-XML: %1 at line %2, column %3") | |
340 .arg(exception.message()) | |
341 .arg(exception.lineNumber()) | |
342 .arg(exception.columnNumber()); | |
343 std::cerr << m_errorString.toLocal8Bit().data() << std::endl; | |
344 return QXmlDefaultHandler::fatalError(exception); | |
345 } | |
346 | |
347 | |
348 #define READ_MANDATORY(TYPE, NAME, CONVERSION) \ | |
349 TYPE NAME = attributes.value(#NAME).trimmed().CONVERSION(&ok); \ | |
350 if (!ok) { \ | |
351 std::cerr << "WARNING: SV-XML: Missing or invalid mandatory " #TYPE " attribute \"" #NAME "\"" << std::endl; \ | |
352 return false; \ | |
353 } | |
354 | |
355 bool | |
356 SVFileReader::readWindow(const QXmlAttributes &attributes) | |
357 { | |
358 bool ok = false; | |
359 | |
360 READ_MANDATORY(int, width, toInt); | |
361 READ_MANDATORY(int, height, toInt); | |
362 | |
363 m_paneCallback.setWindowSize(width, height); | |
364 return true; | |
365 } | |
366 | |
367 void | |
368 SVFileReader::addUnaddedModels() | |
369 { | |
370 std::set<Model *> unaddedModels; | |
371 | |
372 for (std::map<int, Model *>::iterator i = m_models.begin(); | |
373 i != m_models.end(); ++i) { | |
374 if (m_addedModels.find(i->second) == m_addedModels.end()) { | |
375 unaddedModels.insert(i->second); | |
376 } | |
377 } | |
378 | |
379 for (std::set<Model *>::iterator i = unaddedModels.begin(); | |
380 i != unaddedModels.end(); ++i) { | |
381 m_document->addImportedModel(*i); | |
382 m_addedModels.insert(*i); | |
383 } | |
384 } | |
385 | |
386 bool | |
387 SVFileReader::readModel(const QXmlAttributes &attributes) | |
388 { | |
389 bool ok = false; | |
390 | |
391 READ_MANDATORY(int, id, toInt); | |
392 | |
393 if (haveModel(id)) { | |
394 std::cerr << "WARNING: SV-XML: Ignoring duplicate model id " << id | |
395 << std::endl; | |
396 return false; | |
397 } | |
398 | |
399 QString name = attributes.value("name"); | |
400 | |
401 std::cerr << "SVFileReader::readModel: model name \"" << name.toStdString() << "\"" << std::endl; | |
402 | |
403 READ_MANDATORY(int, sampleRate, toInt); | |
404 | |
405 QString type = attributes.value("type").trimmed(); | |
406 bool mainModel = (attributes.value("mainModel").trimmed() == "true"); | |
407 | |
408 if (type == "wavefile") { | |
409 | |
410 WaveFileModel *model = 0; | |
411 FileFinder *ff = FileFinder::getInstance(); | |
412 QString originalPath = attributes.value("file"); | |
413 QString path = ff->find(FileFinder::AudioFile, | |
414 originalPath, m_location); | |
415 | |
416 FileSource file(path); | |
417 file.waitForStatus(); | |
418 | |
419 if (!file.isOK()) { | |
420 std::cerr << "SVFileReader::readModel: Failed to retrieve file \"" << path.toStdString() << "\" for wave file model: " << file.getErrorString().toStdString() << std::endl; | |
421 } else if (!file.isAvailable()) { | |
422 std::cerr << "SVFileReader::readModel: Failed to retrieve file \"" << path.toStdString() << "\" for wave file model: Source unavailable" << std::endl; | |
423 } else { | |
424 | |
425 file.waitForData(); | |
426 model = new WaveFileModel(file); | |
427 if (!model->isOK()) { | |
428 delete model; | |
429 model = 0; | |
430 } | |
431 } | |
432 | |
433 if (!model) return false; | |
434 | |
435 model->setObjectName(name); | |
436 m_models[id] = model; | |
437 if (mainModel) { | |
438 m_document->setMainModel(model); | |
439 m_addedModels.insert(model); | |
440 } | |
441 // Derived models will be added when their derivation | |
442 // is found. | |
443 | |
444 return true; | |
445 | |
446 } else if (type == "dense") { | |
447 | |
448 READ_MANDATORY(int, dimensions, toInt); | |
449 | |
450 // Currently the only dense model we support here is the dense | |
451 // 3d model. Dense time-value models are always file-backed | |
452 // waveform data, at this point, and they come in as wavefile | |
453 // models. | |
454 | |
455 if (dimensions == 3) { | |
456 | |
457 READ_MANDATORY(int, windowSize, toInt); | |
458 READ_MANDATORY(int, yBinCount, toInt); | |
459 | |
460 EditableDenseThreeDimensionalModel *model = | |
461 new EditableDenseThreeDimensionalModel | |
462 (sampleRate, windowSize, yBinCount); | |
463 | |
464 float minimum = attributes.value("minimum").trimmed().toFloat(&ok); | |
465 if (ok) model->setMinimumLevel(minimum); | |
466 | |
467 float maximum = attributes.value("maximum").trimmed().toFloat(&ok); | |
468 if (ok) model->setMaximumLevel(maximum); | |
469 | |
470 int dataset = attributes.value("dataset").trimmed().toInt(&ok); | |
471 if (ok) m_awaitingDatasets[dataset] = id; | |
472 | |
473 model->setObjectName(name); | |
474 m_models[id] = model; | |
475 return true; | |
476 | |
477 } else { | |
478 | |
479 std::cerr << "WARNING: SV-XML: Unexpected dense model dimension (" | |
480 << dimensions << ")" << std::endl; | |
481 } | |
482 } else if (type == "sparse") { | |
483 | |
484 READ_MANDATORY(int, dimensions, toInt); | |
485 | |
486 if (dimensions == 1) { | |
487 | |
488 READ_MANDATORY(int, resolution, toInt); | |
489 | |
490 if (attributes.value("subtype") == "image") { | |
491 | |
492 bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true"); | |
493 ImageModel *model = new ImageModel(sampleRate, resolution, | |
494 notifyOnAdd); | |
495 model->setObjectName(name); | |
496 m_models[id] = model; | |
497 | |
498 } else { | |
499 | |
500 SparseOneDimensionalModel *model = new SparseOneDimensionalModel | |
501 (sampleRate, resolution); | |
502 model->setObjectName(name); | |
503 m_models[id] = model; | |
504 } | |
505 | |
506 int dataset = attributes.value("dataset").trimmed().toInt(&ok); | |
507 if (ok) m_awaitingDatasets[dataset] = id; | |
508 | |
509 return true; | |
510 | |
511 } else if (dimensions == 2 || dimensions == 3) { | |
512 | |
513 READ_MANDATORY(int, resolution, toInt); | |
514 | |
515 bool haveMinMax = true; | |
516 float minimum = attributes.value("minimum").trimmed().toFloat(&ok); | |
517 if (!ok) haveMinMax = false; | |
518 float maximum = attributes.value("maximum").trimmed().toFloat(&ok); | |
519 if (!ok) haveMinMax = false; | |
520 | |
521 float valueQuantization = | |
522 attributes.value("valueQuantization").trimmed().toFloat(&ok); | |
523 | |
524 bool notifyOnAdd = (attributes.value("notifyOnAdd") == "true"); | |
525 | |
526 QString units = attributes.value("units"); | |
527 | |
528 if (dimensions == 2) { | |
529 if (attributes.value("subtype") == "text") { | |
530 TextModel *model = new TextModel | |
531 (sampleRate, resolution, notifyOnAdd); | |
532 model->setObjectName(name); | |
533 m_models[id] = model; | |
534 } else { | |
535 SparseTimeValueModel *model; | |
536 if (haveMinMax) { | |
537 model = new SparseTimeValueModel | |
538 (sampleRate, resolution, minimum, maximum, notifyOnAdd); | |
539 } else { | |
540 model = new SparseTimeValueModel | |
541 (sampleRate, resolution, notifyOnAdd); | |
542 } | |
543 model->setScaleUnits(units); | |
544 model->setObjectName(name); | |
545 m_models[id] = model; | |
546 } | |
547 } else { | |
548 NoteModel *model; | |
549 if (haveMinMax) { | |
550 model = new NoteModel | |
551 (sampleRate, resolution, minimum, maximum, notifyOnAdd); | |
552 } else { | |
553 model = new NoteModel | |
554 (sampleRate, resolution, notifyOnAdd); | |
555 } | |
556 model->setValueQuantization(valueQuantization); | |
557 model->setScaleUnits(units); | |
558 model->setObjectName(name); | |
559 m_models[id] = model; | |
560 } | |
561 | |
562 int dataset = attributes.value("dataset").trimmed().toInt(&ok); | |
563 if (ok) m_awaitingDatasets[dataset] = id; | |
564 | |
565 return true; | |
566 | |
567 } else { | |
568 | |
569 std::cerr << "WARNING: SV-XML: Unexpected sparse model dimension (" | |
570 << dimensions << ")" << std::endl; | |
571 } | |
572 } else { | |
573 | |
574 std::cerr << "WARNING: SV-XML: Unexpected model type \"" | |
575 << type.toLocal8Bit().data() << "\" for model id " << id << std::endl; | |
576 } | |
577 | |
578 return false; | |
579 } | |
580 | |
581 bool | |
582 SVFileReader::readView(const QXmlAttributes &attributes) | |
583 { | |
584 QString type = attributes.value("type"); | |
585 m_currentPane = 0; | |
586 | |
587 if (type != "pane") { | |
588 std::cerr << "WARNING: SV-XML: Unexpected view type \"" | |
589 << type.toLocal8Bit().data() << "\"" << std::endl; | |
590 return false; | |
591 } | |
592 | |
593 m_currentPane = m_paneCallback.addPane(); | |
594 | |
595 if (!m_currentPane) { | |
596 std::cerr << "WARNING: SV-XML: Internal error: Failed to add pane!" | |
597 << std::endl; | |
598 return false; | |
599 } | |
600 | |
601 bool ok = false; | |
602 | |
603 View *view = m_currentPane; | |
604 | |
605 // The view properties first | |
606 | |
607 READ_MANDATORY(size_t, centre, toUInt); | |
608 READ_MANDATORY(size_t, zoom, toUInt); | |
609 READ_MANDATORY(int, followPan, toInt); | |
610 READ_MANDATORY(int, followZoom, toInt); | |
611 QString tracking = attributes.value("tracking"); | |
612 | |
613 // Specify the follow modes before we set the actual values | |
614 view->setFollowGlobalPan(followPan); | |
615 view->setFollowGlobalZoom(followZoom); | |
616 view->setPlaybackFollow(tracking == "scroll" ? PlaybackScrollContinuous : | |
617 tracking == "page" ? PlaybackScrollPage | |
618 : PlaybackIgnore); | |
619 | |
620 // Then set these values | |
621 view->setCentreFrame(centre); | |
622 view->setZoomLevel(zoom); | |
623 | |
624 // And pane properties | |
625 READ_MANDATORY(int, centreLineVisible, toInt); | |
626 m_currentPane->setCentreLineVisible(centreLineVisible); | |
627 | |
628 int height = attributes.value("height").toInt(&ok); | |
629 if (ok) { | |
630 m_currentPane->resize(m_currentPane->width(), height); | |
631 } | |
632 | |
633 return true; | |
634 } | |
635 | |
636 bool | |
637 SVFileReader::readLayer(const QXmlAttributes &attributes) | |
638 { | |
639 QString type = attributes.value("type"); | |
640 | |
641 int id; | |
642 bool ok = false; | |
643 id = attributes.value("id").trimmed().toInt(&ok); | |
644 | |
645 if (!ok) { | |
646 std::cerr << "WARNING: SV-XML: No layer id for layer of type \"" | |
647 << type.toLocal8Bit().data() | |
648 << "\"" << std::endl; | |
649 return false; | |
650 } | |
651 | |
652 Layer *layer = 0; | |
653 bool isNewLayer = false; | |
654 | |
655 // Layers are expected to be defined in layer elements in the data | |
656 // section, and referred to in layer elements in the view | |
657 // sections. So if we're in the data section, we expect this | |
658 // layer not to exist already; if we're in the view section, we | |
659 // expect it to exist. | |
660 | |
661 if (m_inData) { | |
662 | |
663 if (m_layers.find(id) != m_layers.end()) { | |
664 std::cerr << "WARNING: SV-XML: Ignoring duplicate layer id " << id | |
665 << " in data section" << std::endl; | |
666 return false; | |
667 } | |
668 | |
669 layer = m_layers[id] = m_document->createLayer | |
670 (LayerFactory::getInstance()->getLayerTypeForName(type)); | |
671 | |
672 if (layer) { | |
673 m_layers[id] = layer; | |
674 isNewLayer = true; | |
675 } | |
676 | |
677 } else { | |
678 | |
679 if (!m_currentPane) { | |
680 std::cerr << "WARNING: SV-XML: No current pane for layer " << id | |
681 << " in view section" << std::endl; | |
682 return false; | |
683 } | |
684 | |
685 if (m_layers.find(id) != m_layers.end()) { | |
686 | |
687 layer = m_layers[id]; | |
688 | |
689 } else { | |
690 std::cerr << "WARNING: SV-XML: Layer id " << id | |
691 << " in view section has not been defined -- defining it here" | |
692 << std::endl; | |
693 | |
694 layer = m_document->createLayer | |
695 (LayerFactory::getInstance()->getLayerTypeForName(type)); | |
696 | |
697 if (layer) { | |
698 m_layers[id] = layer; | |
699 isNewLayer = true; | |
700 } | |
701 } | |
702 } | |
703 | |
704 if (!layer) { | |
705 std::cerr << "WARNING: SV-XML: Failed to add layer of type \"" | |
706 << type.toLocal8Bit().data() | |
707 << "\"" << std::endl; | |
708 return false; | |
709 } | |
710 | |
711 if (isNewLayer) { | |
712 | |
713 QString name = attributes.value("name"); | |
714 layer->setObjectName(name); | |
715 | |
716 int modelId; | |
717 bool modelOk = false; | |
718 modelId = attributes.value("model").trimmed().toInt(&modelOk); | |
719 | |
720 if (modelOk) { | |
721 if (haveModel(modelId)) { | |
722 Model *model = m_models[modelId]; | |
723 m_document->setModel(layer, model); | |
724 } else { | |
725 std::cerr << "WARNING: SV-XML: Unknown model id " << modelId | |
726 << " in layer definition" << std::endl; | |
727 } | |
728 } | |
729 | |
730 layer->setProperties(attributes); | |
731 } | |
732 | |
733 if (!m_inData && m_currentPane) { | |
734 | |
735 QString visible = attributes.value("visible"); | |
736 bool dormant = (visible == "false"); | |
737 | |
738 // We need to do this both before and after adding the layer | |
739 // to the view -- we need it to be dormant if appropriate | |
740 // before it's actually added to the view so that any property | |
741 // box gets the right state when it's added, but the add layer | |
742 // command sets dormant to false because it assumes it may be | |
743 // restoring a previously dormant layer, so we need to set it | |
744 // again afterwards too. Hm | |
745 layer->setLayerDormant(m_currentPane, dormant); | |
746 | |
747 m_document->addLayerToView(m_currentPane, layer); | |
748 | |
749 layer->setLayerDormant(m_currentPane, dormant); | |
750 } | |
751 | |
752 m_currentLayer = layer; | |
753 m_inLayer = true; | |
754 | |
755 return true; | |
756 } | |
757 | |
758 bool | |
759 SVFileReader::readDatasetStart(const QXmlAttributes &attributes) | |
760 { | |
761 bool ok = false; | |
762 | |
763 READ_MANDATORY(int, id, toInt); | |
764 READ_MANDATORY(int, dimensions, toInt); | |
765 | |
766 if (m_awaitingDatasets.find(id) == m_awaitingDatasets.end()) { | |
767 std::cerr << "WARNING: SV-XML: Unwanted dataset " << id << std::endl; | |
768 return false; | |
769 } | |
770 | |
771 int modelId = m_awaitingDatasets[id]; | |
772 | |
773 Model *model = 0; | |
774 if (haveModel(modelId)) { | |
775 model = m_models[modelId]; | |
776 } else { | |
777 std::cerr << "WARNING: SV-XML: Internal error: Unknown model " << modelId | |
778 << " expecting dataset " << id << std::endl; | |
779 return false; | |
780 } | |
781 | |
782 bool good = false; | |
783 | |
784 switch (dimensions) { | |
785 case 1: | |
786 if (dynamic_cast<SparseOneDimensionalModel *>(model)) good = true; | |
787 else if (dynamic_cast<ImageModel *>(model)) good = true; | |
788 break; | |
789 | |
790 case 2: | |
791 if (dynamic_cast<SparseTimeValueModel *>(model)) good = true; | |
792 else if (dynamic_cast<TextModel *>(model)) good = true; | |
793 break; | |
794 | |
795 case 3: | |
796 if (dynamic_cast<NoteModel *>(model)) good = true; | |
797 else if (dynamic_cast<EditableDenseThreeDimensionalModel *>(model)) { | |
798 m_datasetSeparator = attributes.value("separator"); | |
799 good = true; | |
800 } | |
801 break; | |
802 } | |
803 | |
804 if (!good) { | |
805 std::cerr << "WARNING: SV-XML: Model id " << modelId << " has wrong number of dimensions or inappropriate type for " << dimensions << "-D dataset " << id << std::endl; | |
806 m_currentDataset = 0; | |
807 return false; | |
808 } | |
809 | |
810 m_currentDataset = model; | |
811 return true; | |
812 } | |
813 | |
814 bool | |
815 SVFileReader::addPointToDataset(const QXmlAttributes &attributes) | |
816 { | |
817 bool ok = false; | |
818 | |
819 READ_MANDATORY(int, frame, toInt); | |
820 | |
821 // std::cerr << "SVFileReader::addPointToDataset: frame = " << frame << std::endl; | |
822 | |
823 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *> | |
824 (m_currentDataset); | |
825 | |
826 if (sodm) { | |
827 // std::cerr << "Current dataset is a sparse one dimensional model" << std::endl; | |
828 QString label = attributes.value("label"); | |
829 sodm->addPoint(SparseOneDimensionalModel::Point(frame, label)); | |
830 return true; | |
831 } | |
832 | |
833 SparseTimeValueModel *stvm = dynamic_cast<SparseTimeValueModel *> | |
834 (m_currentDataset); | |
835 | |
836 if (stvm) { | |
837 // std::cerr << "Current dataset is a sparse time-value model" << std::endl; | |
838 float value = 0.0; | |
839 value = attributes.value("value").trimmed().toFloat(&ok); | |
840 QString label = attributes.value("label"); | |
841 stvm->addPoint(SparseTimeValueModel::Point(frame, value, label)); | |
842 return ok; | |
843 } | |
844 | |
845 NoteModel *nm = dynamic_cast<NoteModel *>(m_currentDataset); | |
846 | |
847 if (nm) { | |
848 // std::cerr << "Current dataset is a note model" << std::endl; | |
849 float value = 0.0; | |
850 value = attributes.value("value").trimmed().toFloat(&ok); | |
851 size_t duration = 0; | |
852 duration = attributes.value("duration").trimmed().toUInt(&ok); | |
853 QString label = attributes.value("label"); | |
854 nm->addPoint(NoteModel::Point(frame, value, duration, label)); | |
855 return ok; | |
856 } | |
857 | |
858 TextModel *tm = dynamic_cast<TextModel *>(m_currentDataset); | |
859 | |
860 if (tm) { | |
861 // std::cerr << "Current dataset is a text model" << std::endl; | |
862 float height = 0.0; | |
863 height = attributes.value("height").trimmed().toFloat(&ok); | |
864 QString label = attributes.value("label"); | |
865 // std::cerr << "SVFileReader::addPointToDataset: TextModel: frame = " << frame << ", height = " << height << ", label = " << label.toStdString() << ", ok = " << ok << std::endl; | |
866 tm->addPoint(TextModel::Point(frame, height, label)); | |
867 return ok; | |
868 } | |
869 | |
870 ImageModel *im = dynamic_cast<ImageModel *>(m_currentDataset); | |
871 | |
872 if (im) { | |
873 // std::cerr << "Current dataset is an image model" << std::endl; | |
874 QString image = attributes.value("image"); | |
875 QString label = attributes.value("label"); | |
876 // std::cerr << "SVFileReader::addPointToDataset: ImageModel: frame = " << frame << ", image = " << image.toStdString() << ", label = " << label.toStdString() << ", ok = " << ok << std::endl; | |
877 im->addPoint(ImageModel::Point(frame, image, label)); | |
878 return ok; | |
879 } | |
880 | |
881 std::cerr << "WARNING: SV-XML: Point element found in non-point dataset" << std::endl; | |
882 | |
883 return false; | |
884 } | |
885 | |
886 bool | |
887 SVFileReader::addBinToDataset(const QXmlAttributes &attributes) | |
888 { | |
889 EditableDenseThreeDimensionalModel *dtdm = | |
890 dynamic_cast<EditableDenseThreeDimensionalModel *> | |
891 (m_currentDataset); | |
892 | |
893 if (dtdm) { | |
894 | |
895 bool ok = false; | |
896 int n = attributes.value("number").trimmed().toInt(&ok); | |
897 if (!ok) { | |
898 std::cerr << "WARNING: SV-XML: Missing or invalid bin number" | |
899 << std::endl; | |
900 return false; | |
901 } | |
902 | |
903 QString name = attributes.value("name"); | |
904 | |
905 dtdm->setBinName(n, name); | |
906 return true; | |
907 } | |
908 | |
909 std::cerr << "WARNING: SV-XML: Bin definition found in incompatible dataset" << std::endl; | |
910 | |
911 return false; | |
912 } | |
913 | |
914 | |
915 bool | |
916 SVFileReader::addRowToDataset(const QXmlAttributes &attributes) | |
917 { | |
918 m_inRow = false; | |
919 | |
920 bool ok = false; | |
921 m_rowNumber = attributes.value("n").trimmed().toInt(&ok); | |
922 if (!ok) { | |
923 std::cerr << "WARNING: SV-XML: Missing or invalid row number" | |
924 << std::endl; | |
925 return false; | |
926 } | |
927 | |
928 m_inRow = true; | |
929 | |
930 // std::cerr << "SV-XML: In row " << m_rowNumber << std::endl; | |
931 | |
932 return true; | |
933 } | |
934 | |
935 bool | |
936 SVFileReader::readRowData(const QString &text) | |
937 { | |
938 EditableDenseThreeDimensionalModel *dtdm = | |
939 dynamic_cast<EditableDenseThreeDimensionalModel *> | |
940 (m_currentDataset); | |
941 | |
942 bool warned = false; | |
943 | |
944 if (dtdm) { | |
945 QStringList data = text.split(m_datasetSeparator); | |
946 | |
947 DenseThreeDimensionalModel::Column values; | |
948 | |
949 for (QStringList::iterator i = data.begin(); i != data.end(); ++i) { | |
950 | |
951 if (values.size() == dtdm->getHeight()) { | |
952 if (!warned) { | |
953 std::cerr << "WARNING: SV-XML: Too many y-bins in 3-D dataset row " | |
954 << m_rowNumber << std::endl; | |
955 warned = true; | |
956 } | |
957 } | |
958 | |
959 bool ok; | |
960 float value = i->toFloat(&ok); | |
961 if (!ok) { | |
962 std::cerr << "WARNING: SV-XML: Bad floating-point value " | |
963 << i->toLocal8Bit().data() | |
964 << " in row data" << std::endl; | |
965 } else { | |
966 values.push_back(value); | |
967 } | |
968 } | |
969 | |
970 dtdm->setColumn(m_rowNumber, values); | |
971 return true; | |
972 } | |
973 | |
974 std::cerr << "WARNING: SV-XML: Row data found in non-row dataset" << std::endl; | |
975 | |
976 return false; | |
977 } | |
978 | |
979 bool | |
980 SVFileReader::readDerivation(const QXmlAttributes &attributes) | |
981 { | |
982 int modelId = 0; | |
983 bool modelOk = false; | |
984 modelId = attributes.value("model").trimmed().toInt(&modelOk); | |
985 | |
986 if (!modelOk) { | |
987 std::cerr << "WARNING: SV-XML: No model id specified for derivation" << std::endl; | |
988 return false; | |
989 } | |
990 | |
991 QString transform = attributes.value("transform"); | |
992 | |
993 if (haveModel(modelId)) { | |
994 m_currentDerivedModel = m_models[modelId]; | |
995 } else { | |
996 // we'll regenerate the model when the derivation element ends | |
997 m_currentDerivedModel = 0; | |
998 } | |
999 | |
1000 m_currentDerivedModelId = modelId; | |
1001 | |
1002 int sourceId = 0; | |
1003 bool sourceOk = false; | |
1004 sourceId = attributes.value("source").trimmed().toInt(&sourceOk); | |
1005 | |
1006 if (sourceOk && haveModel(sourceId)) { | |
1007 m_currentTransformSource = m_models[sourceId]; | |
1008 } else { | |
1009 m_currentTransformSource = m_document->getMainModel(); | |
1010 } | |
1011 | |
1012 m_currentTransform = transform; | |
1013 m_currentTransformConfiguration = ""; | |
1014 | |
1015 m_currentTransformContext = PluginTransform::ExecutionContext(); | |
1016 | |
1017 bool ok = false; | |
1018 int channel = attributes.value("channel").trimmed().toInt(&ok); | |
1019 if (ok) m_currentTransformContext.channel = channel; | |
1020 | |
1021 int domain = attributes.value("domain").trimmed().toInt(&ok); | |
1022 if (ok) m_currentTransformContext.domain = Vamp::Plugin::InputDomain(domain); | |
1023 | |
1024 int stepSize = attributes.value("stepSize").trimmed().toInt(&ok); | |
1025 if (ok) m_currentTransformContext.stepSize = stepSize; | |
1026 | |
1027 int blockSize = attributes.value("blockSize").trimmed().toInt(&ok); | |
1028 if (ok) m_currentTransformContext.blockSize = blockSize; | |
1029 | |
1030 int windowType = attributes.value("windowType").trimmed().toInt(&ok); | |
1031 if (ok) m_currentTransformContext.windowType = WindowType(windowType); | |
1032 | |
1033 QString startFrameStr = attributes.value("startFrame"); | |
1034 QString durationStr = attributes.value("duration"); | |
1035 | |
1036 size_t startFrame = 0; | |
1037 size_t duration = 0; | |
1038 | |
1039 if (startFrameStr != "") { | |
1040 startFrame = startFrameStr.trimmed().toInt(&ok); | |
1041 if (!ok) startFrame = 0; | |
1042 } | |
1043 if (durationStr != "") { | |
1044 duration = durationStr.trimmed().toInt(&ok); | |
1045 if (!ok) duration = 0; | |
1046 } | |
1047 | |
1048 m_currentTransformContext.startFrame = startFrame; | |
1049 m_currentTransformContext.duration = duration; | |
1050 | |
1051 return true; | |
1052 } | |
1053 | |
1054 bool | |
1055 SVFileReader::readPlayParameters(const QXmlAttributes &attributes) | |
1056 { | |
1057 m_currentPlayParameters = 0; | |
1058 | |
1059 int modelId = 0; | |
1060 bool modelOk = false; | |
1061 modelId = attributes.value("model").trimmed().toInt(&modelOk); | |
1062 | |
1063 if (!modelOk) { | |
1064 std::cerr << "WARNING: SV-XML: No model id specified for play parameters" << std::endl; | |
1065 return false; | |
1066 } | |
1067 | |
1068 if (haveModel(modelId)) { | |
1069 | |
1070 bool ok = false; | |
1071 | |
1072 PlayParameters *parameters = PlayParameterRepository::getInstance()-> | |
1073 getPlayParameters(m_models[modelId]); | |
1074 | |
1075 if (!parameters) { | |
1076 std::cerr << "WARNING: SV-XML: Play parameters for model " | |
1077 << modelId | |
1078 << " not found - has model been added to document?" | |
1079 << std::endl; | |
1080 return false; | |
1081 } | |
1082 | |
1083 bool muted = (attributes.value("mute").trimmed() == "true"); | |
1084 parameters->setPlayMuted(muted); | |
1085 | |
1086 float pan = attributes.value("pan").toFloat(&ok); | |
1087 if (ok) parameters->setPlayPan(pan); | |
1088 | |
1089 float gain = attributes.value("gain").toFloat(&ok); | |
1090 if (ok) parameters->setPlayGain(gain); | |
1091 | |
1092 QString pluginId = attributes.value("pluginId"); | |
1093 if (pluginId != "") parameters->setPlayPluginId(pluginId); | |
1094 | |
1095 m_currentPlayParameters = parameters; | |
1096 | |
1097 // std::cerr << "Current play parameters for model: " << m_models[modelId] << ": " << m_currentPlayParameters << std::endl; | |
1098 | |
1099 } else { | |
1100 | |
1101 std::cerr << "WARNING: SV-XML: Unknown model " << modelId | |
1102 << " for play parameters" << std::endl; | |
1103 return false; | |
1104 } | |
1105 | |
1106 return true; | |
1107 } | |
1108 | |
1109 bool | |
1110 SVFileReader::readPlugin(const QXmlAttributes &attributes) | |
1111 { | |
1112 if (m_currentDerivedModelId < 0 && !m_currentPlayParameters) { | |
1113 std::cerr << "WARNING: SV-XML: Plugin found outside derivation or play parameters" << std::endl; | |
1114 return false; | |
1115 } | |
1116 | |
1117 QString configurationXml = "<plugin"; | |
1118 | |
1119 for (int i = 0; i < attributes.length(); ++i) { | |
1120 configurationXml += QString(" %1=\"%2\"") | |
1121 .arg(attributes.qName(i)) | |
1122 .arg(XmlExportable::encodeEntities(attributes.value(i))); | |
1123 } | |
1124 | |
1125 configurationXml += "/>"; | |
1126 | |
1127 if (m_currentPlayParameters) { | |
1128 m_currentPlayParameters->setPlayPluginConfiguration(configurationXml); | |
1129 } else { | |
1130 m_currentTransformConfiguration += configurationXml; | |
1131 } | |
1132 | |
1133 return true; | |
1134 } | |
1135 | |
1136 bool | |
1137 SVFileReader::readSelection(const QXmlAttributes &attributes) | |
1138 { | |
1139 bool ok; | |
1140 | |
1141 READ_MANDATORY(int, start, toInt); | |
1142 READ_MANDATORY(int, end, toInt); | |
1143 | |
1144 m_paneCallback.addSelection(start, end); | |
1145 | |
1146 return true; | |
1147 } | |
1148 | |
1149 bool | |
1150 SVFileReader::readMeasurement(const QXmlAttributes &attributes) | |
1151 { | |
1152 std::cerr << "SVFileReader::readMeasurement: inLayer " | |
1153 << m_inLayer << ", layer " << m_currentLayer << std::endl; | |
1154 | |
1155 if (!m_inLayer) { | |
1156 std::cerr << "WARNING: SV-XML: Measurement found outside layer" << std::endl; | |
1157 return false; | |
1158 } | |
1159 | |
1160 m_currentLayer->addMeasurementRect(attributes); | |
1161 return true; | |
1162 } | |
1163 | |
1164 SVFileReaderPaneCallback::~SVFileReaderPaneCallback() | |
1165 { | |
1166 } | |
1167 |