Mercurial > hg > sonic-visualiser
comparison document/SVFileReader.cpp @ 55:ca1e3f5657d5
* Simplify maker names in plugin menu
* Make sure derived models have a name (based on the transform)
* Don't start deriving a model from a derived model until the derived model is
ready
* Tidy up completion management in writable wave file model
* Make writable models save/reload correctly from session file (i.e.
regenerating from the original transform)
* Same for dense 3d models -- don't save the data, just the transform details
* Add a comment describing the SV file format
author | Chris Cannam |
---|---|
date | Fri, 13 Oct 2006 12:51:05 +0000 |
parents | 5f9fdca0c7d8 |
children | bedc7517b6e8 |
comparison
equal
deleted
inserted
replaced
54:ec77936c268e | 55:ca1e3f5657d5 |
---|---|
36 #include <QString> | 36 #include <QString> |
37 #include <QMessageBox> | 37 #include <QMessageBox> |
38 #include <QFileDialog> | 38 #include <QFileDialog> |
39 | 39 |
40 #include <iostream> | 40 #include <iostream> |
41 | |
42 /* | |
43 Some notes about the SV XML format. We're very lazy with our XML: | |
44 there's no schema or DTD, and we depend heavily on elements being | |
45 in a particular order. | |
46 | |
47 <sv> | |
48 | |
49 <data> | |
50 | |
51 <!-- The data section contains definitions of both models and | |
52 visual layers. Layers are considered data in the document; | |
53 the structure of views that displays the layers is not. --> | |
54 | |
55 <!-- id numbers are unique within the data type (i.e. no two | |
56 models can have the same id, but a model can have the same | |
57 id as a layer, etc). SV generates its id numbers just for | |
58 the purpose of cross-referencing within the current file; | |
59 they don't necessarily have any meaning once the file has | |
60 been loaded. --> | |
61 | |
62 <model id="0" name="..." type="..." ... /> | |
63 <model id="1" name="..." type="..." ... /> | |
64 | |
65 <!-- Models that have data associated with them store it | |
66 in a neighbouring dataset element. The dataset must follow | |
67 the model and precede any derivation or layer elements that | |
68 refer to the model. --> | |
69 | |
70 <model id="2" name="..." type="..." dataset="0" ... /> | |
71 | |
72 <dataset id="0" type="..."> | |
73 <point frame="..." value="..." ... /> | |
74 </dataset> | |
75 | |
76 <!-- Where one model is derived from another via a transform, | |
77 it has an associated derivation element. This must follow | |
78 both the source and target model elements. The source and | |
79 model attributes give the source model id and target model | |
80 id respectively. A model can have both dataset and | |
81 derivation elements; if it does, dataset must appear first. | |
82 If the model's data are not stored, but instead the model | |
83 is to be regenerated completely from the transform when | |
84 the session is reloaded, then the model should have _only_ | |
85 a derivation element, and no model element should appear | |
86 for it at all. --> | |
87 | |
88 <derivation source="0" model="2" transform="..." ...> | |
89 <plugin id="..." ... /> | |
90 </derivation> | |
91 | |
92 <!-- The playparameters element lists playback settings for | |
93 a model. --> | |
94 | |
95 <playparameters mute="false" pan="0" gain="1" model="1" ... /> | |
96 | |
97 <!-- Layer elements. The models must have already been defined. | |
98 The same model may appear in more than one layer (of more | |
99 than one type). --> | |
100 | |
101 <layer id="1" type="..." name="..." model="0" ... /> | |
102 <layer id="2" type="..." name="..." model="1" ... /> | |
103 | |
104 </data> | |
105 | |
106 | |
107 <display> | |
108 | |
109 <!-- The display element contains visual structure for the | |
110 layers. It's simpler than the data section. --> | |
111 | |
112 <!-- Overall preferred window size for this session. --> | |
113 | |
114 <window width="..." height="..."/> | |
115 | |
116 <!-- List of view elements to stack up. Each one contains | |
117 a list of layers in stacking order, back to front. --> | |
118 | |
119 <view type="pane" ...> | |
120 <layer id="1"/> | |
121 <layer id="2"/> | |
122 </view> | |
123 | |
124 <!-- The layer elements just refer to layers defined in the | |
125 data section, so they don't have to have any attributes | |
126 other than the id. For sort-of-historical reasons SV | |
127 actually does repeat the other attributes here, but | |
128 it doesn't need to. --> | |
129 | |
130 <view type="pane" ...> | |
131 <layer id="2"/> | |
132 <view> | |
133 | |
134 </display> | |
135 | |
136 | |
137 <!-- List of selected regions by audio frame extents. --> | |
138 | |
139 <selections> | |
140 <selection start="..." end="..."/> | |
141 </selections> | |
142 | |
143 | |
144 </sv> | |
145 | |
146 */ | |
147 | |
41 | 148 |
42 SVFileReader::SVFileReader(Document *document, | 149 SVFileReader::SVFileReader(Document *document, |
43 SVFileReaderPaneCallback &callback) : | 150 SVFileReaderPaneCallback &callback) : |
44 m_document(document), | 151 m_document(document), |
45 m_paneCallback(callback), | 152 m_paneCallback(callback), |
46 m_currentPane(0), | 153 m_currentPane(0), |
47 m_currentDataset(0), | 154 m_currentDataset(0), |
48 m_currentDerivedModel(0), | 155 m_currentDerivedModel(0), |
156 m_currentDerivedModelId(-1), | |
49 m_currentPlayParameters(0), | 157 m_currentPlayParameters(0), |
50 m_datasetSeparator(" "), | 158 m_datasetSeparator(" "), |
51 m_inRow(false), | 159 m_inRow(false), |
52 m_rowNumber(0), | 160 m_rowNumber(0), |
53 m_ok(false) | 161 m_ok(false) |
256 | 364 |
257 addUnaddedModels(); | 365 addUnaddedModels(); |
258 m_inData = false; | 366 m_inData = false; |
259 | 367 |
260 } else if (name == "derivation") { | 368 } else if (name == "derivation") { |
261 | 369 |
262 if (m_currentDerivedModel) { | 370 if (!m_currentDerivedModel) { |
371 if (m_currentDerivedModel < 0) { | |
372 std::cerr << "WARNING: SV-XML: Bad derivation output model id " | |
373 << m_currentDerivedModelId << std::endl; | |
374 } else if (m_models[m_currentDerivedModelId]) { | |
375 std::cerr << "WARNING: SV-XML: Derivation has existing model " | |
376 << m_currentDerivedModelId | |
377 << " as target, not regenerating" << std::endl; | |
378 } else { | |
379 m_currentDerivedModel = m_models[m_currentDerivedModelId] = | |
380 m_document->addDerivedModel(m_currentTransform, | |
381 m_currentTransformSource, | |
382 m_currentTransformContext, | |
383 m_currentTransformConfiguration); | |
384 } | |
385 } else { | |
263 m_document->addDerivedModel(m_currentTransform, | 386 m_document->addDerivedModel(m_currentTransform, |
264 m_document->getMainModel(), //!!! | 387 m_currentTransformSource, |
265 m_currentTransformContext, | 388 m_currentTransformContext, |
266 m_currentDerivedModel, | 389 m_currentDerivedModel, |
267 m_currentTransformConfiguration); | 390 m_currentTransformConfiguration); |
268 m_addedModels.insert(m_currentDerivedModel); | |
269 m_currentDerivedModel = 0; | |
270 m_currentTransform = ""; | |
271 m_currentTransformConfiguration = ""; | |
272 } | 391 } |
392 | |
393 m_addedModels.insert(m_currentDerivedModel); | |
394 m_currentDerivedModel = 0; | |
395 m_currentDerivedModelId = -1; | |
396 m_currentTransform = ""; | |
397 m_currentTransformConfiguration = ""; | |
273 | 398 |
274 } else if (name == "row") { | 399 } else if (name == "row") { |
275 m_inRow = false; | 400 m_inRow = false; |
276 } else if (name == "view") { | 401 } else if (name == "view") { |
277 m_inView = false; | 402 m_inView = false; |
364 | 489 |
365 READ_MANDATORY(int, sampleRate, toInt); | 490 READ_MANDATORY(int, sampleRate, toInt); |
366 | 491 |
367 QString type = attributes.value("type").trimmed(); | 492 QString type = attributes.value("type").trimmed(); |
368 bool mainModel = (attributes.value("mainModel").trimmed() == "true"); | 493 bool mainModel = (attributes.value("mainModel").trimmed() == "true"); |
369 | 494 |
370 if (type == "wavefile") { | 495 if (type == "wavefile") { |
371 | 496 |
372 QString file = attributes.value("file"); | 497 QString file = attributes.value("file"); |
373 WaveFileModel *model = new WaveFileModel(file); | 498 WaveFileModel *model = new WaveFileModel(file); |
374 | 499 |
410 | 535 |
411 } else if (type == "dense") { | 536 } else if (type == "dense") { |
412 | 537 |
413 READ_MANDATORY(int, dimensions, toInt); | 538 READ_MANDATORY(int, dimensions, toInt); |
414 | 539 |
415 // Currently the only dense model we support here | 540 // Currently the only dense model we support here is the dense |
416 // is the dense 3d model. Dense time-value models | 541 // 3d model. Dense time-value models are always file-backed |
417 // are always file-backed waveform data, at this | 542 // waveform data, at this point, and they come in as wavefile |
418 // point, and they come in as the wavefile model | 543 // models. |
419 // type above. | |
420 | 544 |
421 if (dimensions == 3) { | 545 if (dimensions == 3) { |
422 | 546 |
423 READ_MANDATORY(int, windowSize, toInt); | 547 READ_MANDATORY(int, windowSize, toInt); |
424 READ_MANDATORY(int, yBinCount, toInt); | 548 READ_MANDATORY(int, yBinCount, toInt); |
884 | 1008 |
885 if (!modelOk) { | 1009 if (!modelOk) { |
886 std::cerr << "WARNING: SV-XML: No model id specified for derivation" << std::endl; | 1010 std::cerr << "WARNING: SV-XML: No model id specified for derivation" << std::endl; |
887 return false; | 1011 return false; |
888 } | 1012 } |
889 | 1013 |
890 QString transform = attributes.value("transform"); | 1014 QString transform = attributes.value("transform"); |
891 | 1015 |
892 if (m_models.find(modelId) != m_models.end()) { | 1016 if (m_models.find(modelId) != m_models.end()) { |
893 | |
894 m_currentDerivedModel = m_models[modelId]; | 1017 m_currentDerivedModel = m_models[modelId]; |
895 m_currentTransform = transform; | |
896 m_currentTransformConfiguration = ""; | |
897 | |
898 m_currentTransformContext = PluginTransform::ExecutionContext(); | |
899 | |
900 bool ok = false; | |
901 int channel = attributes.value("channel").trimmed().toInt(&ok); | |
902 if (ok) m_currentTransformContext.channel = channel; | |
903 | |
904 int domain = attributes.value("domain").trimmed().toInt(&ok); | |
905 if (ok) m_currentTransformContext.domain = Vamp::Plugin::InputDomain(domain); | |
906 | |
907 int stepSize = attributes.value("stepSize").trimmed().toInt(&ok); | |
908 if (ok) m_currentTransformContext.stepSize = stepSize; | |
909 | |
910 int blockSize = attributes.value("blockSize").trimmed().toInt(&ok); | |
911 if (ok) m_currentTransformContext.blockSize = blockSize; | |
912 | |
913 int windowType = attributes.value("windowType").trimmed().toInt(&ok); | |
914 if (ok) m_currentTransformContext.windowType = WindowType(windowType); | |
915 | |
916 } else { | 1018 } else { |
917 std::cerr << "WARNING: SV-XML: Unknown derived model " << modelId | 1019 // we'll regenerate the model when the derivation element ends |
918 << " for transform \"" << transform.toLocal8Bit().data() << "\"" | 1020 m_currentDerivedModel = 0; |
919 << std::endl; | 1021 } |
920 return false; | 1022 |
921 } | 1023 m_currentDerivedModelId = modelId; |
1024 | |
1025 int sourceId = 0; | |
1026 bool sourceOk = false; | |
1027 sourceId = attributes.value("source").trimmed().toInt(&sourceOk); | |
1028 | |
1029 if (sourceOk && m_models[sourceId]) { | |
1030 m_currentTransformSource = m_models[sourceId]; | |
1031 } else { | |
1032 m_currentTransformSource = m_document->getMainModel(); | |
1033 } | |
1034 | |
1035 m_currentTransform = transform; | |
1036 m_currentTransformConfiguration = ""; | |
1037 | |
1038 m_currentTransformContext = PluginTransform::ExecutionContext(); | |
1039 | |
1040 bool ok = false; | |
1041 int channel = attributes.value("channel").trimmed().toInt(&ok); | |
1042 if (ok) m_currentTransformContext.channel = channel; | |
1043 | |
1044 int domain = attributes.value("domain").trimmed().toInt(&ok); | |
1045 if (ok) m_currentTransformContext.domain = Vamp::Plugin::InputDomain(domain); | |
1046 | |
1047 int stepSize = attributes.value("stepSize").trimmed().toInt(&ok); | |
1048 if (ok) m_currentTransformContext.stepSize = stepSize; | |
1049 | |
1050 int blockSize = attributes.value("blockSize").trimmed().toInt(&ok); | |
1051 if (ok) m_currentTransformContext.blockSize = blockSize; | |
1052 | |
1053 int windowType = attributes.value("windowType").trimmed().toInt(&ok); | |
1054 if (ok) m_currentTransformContext.windowType = WindowType(windowType); | |
922 | 1055 |
923 return true; | 1056 return true; |
924 } | 1057 } |
925 | 1058 |
926 bool | 1059 bool |
979 } | 1112 } |
980 | 1113 |
981 bool | 1114 bool |
982 SVFileReader::readPlugin(const QXmlAttributes &attributes) | 1115 SVFileReader::readPlugin(const QXmlAttributes &attributes) |
983 { | 1116 { |
984 if (!m_currentDerivedModel && !m_currentPlayParameters) { | 1117 if (m_currentDerivedModelId < 0 && !m_currentPlayParameters) { |
985 std::cerr << "WARNING: SV-XML: Plugin found outside derivation or play parameters" << std::endl; | 1118 std::cerr << "WARNING: SV-XML: Plugin found outside derivation or play parameters" << std::endl; |
986 return false; | 1119 return false; |
987 } | 1120 } |
988 | 1121 |
989 QString configurationXml = "<plugin"; | 1122 QString configurationXml = "<plugin"; |
990 | 1123 |
991 for (int i = 0; i < attributes.length(); ++i) { | 1124 for (int i = 0; i < attributes.length(); ++i) { |
992 configurationXml += QString(" %1=\"%2\"") | 1125 configurationXml += QString(" %1=\"%2\"") |
993 .arg(attributes.qName(i)).arg(attributes.value(i)); | 1126 .arg(attributes.qName(i)) |
1127 .arg(XmlExportable::encodeEntities(attributes.value(i))); | |
994 } | 1128 } |
995 | 1129 |
996 configurationXml += "/>"; | 1130 configurationXml += "/>"; |
997 | 1131 |
998 if (m_currentPlayParameters) { | 1132 if (m_currentPlayParameters) { |