lbajardsilogic@19
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
lbajardsilogic@19
|
2
|
lbajardsilogic@19
|
3 /* Sound Access
|
lbajardsilogic@19
|
4 EASAIER client application.
|
lbajardsilogic@19
|
5 Silogic 2007. Laure Bajard.
|
lbajardsilogic@19
|
6
|
lbajardsilogic@19
|
7 This program is free software; you can redistribute it and/or
|
lbajardsilogic@19
|
8 modify it under the terms of the GNU General Public License as
|
lbajardsilogic@19
|
9 published by the Free Software Foundation; either version 2 of the
|
lbajardsilogic@19
|
10 License, or (at your option) any later version. See the file
|
lbajardsilogic@19
|
11 COPYING included with this distribution for more information.
|
lbajardsilogic@19
|
12 */
|
lbajardsilogic@19
|
13
|
lbajardsilogic@19
|
14 #include <QString>
|
lbajardsilogic@19
|
15 #include <QMessageBox>
|
lbajardsilogic@19
|
16 #include <QFileDialog>
|
lbajardsilogic@19
|
17 #include <QUrl>
|
lbajardsilogic@19
|
18
|
lbajardsilogic@19
|
19 #include <iostream>
|
lbajardsilogic@19
|
20
|
lbajardsilogic@19
|
21 #include "ESFileReader.h"
|
lbajardsilogic@19
|
22
|
lbajardsilogic@19
|
23 #include "layer/Layer.h"
|
lbajardsilogic@19
|
24 #include "view/View.h"
|
lbajardsilogic@19
|
25 #include "base/PlayParameters.h"
|
lbajardsilogic@19
|
26 #include "base/PlayParameterRepository.h"
|
lbajardsilogic@19
|
27 #include "base/TempDirectory.h"
|
lbajardsilogic@19
|
28 #include "data/fileio/AudioFileReaderFactory.h"
|
lbajardsilogic@19
|
29 #include "data/model/WaveFileModel.h"
|
lbajardsilogic@19
|
30 #include "data/model/DenseThreeDimensionalModel.h"
|
lbajardsilogic@19
|
31 #include "data/model/SparseOneDimensionalModel.h"
|
lbajardsilogic@19
|
32 #include "data/model/SparseTimeValueModel.h"
|
lbajardsilogic@19
|
33 #include "data/model/NoteModel.h"
|
lbajardsilogic@19
|
34 #include "data/model/TextModel.h"
|
lbajardsilogic@19
|
35 #include "view/Pane.h"
|
lbajardsilogic@19
|
36 #include "document/Document.h"
|
lbajardsilogic@19
|
37
|
lbajardsilogic@19
|
38
|
lbajardsilogic@19
|
39 ESFileReader::ESFileReader(Document *document,
|
lbajardsilogic@19
|
40 ESFileReaderPaneCallback &callback) : QXmlDefaultHandler(),
|
lbajardsilogic@19
|
41 m_document(document),
|
lbajardsilogic@19
|
42 m_paneCallback(callback),
|
lbajardsilogic@19
|
43 m_currentPane(0),
|
lbajardsilogic@19
|
44 m_inView(false),
|
lbajardsilogic@19
|
45 m_inData(false),
|
lbajardsilogic@19
|
46 m_ok(false)
|
lbajardsilogic@19
|
47 {}
|
lbajardsilogic@19
|
48
|
lbajardsilogic@19
|
49 void
|
lbajardsilogic@19
|
50 ESFileReader::parse(const QString &xmlData)
|
lbajardsilogic@19
|
51 {
|
lbajardsilogic@19
|
52 QXmlInputSource inputSource;
|
lbajardsilogic@19
|
53 inputSource.setData(xmlData);
|
lbajardsilogic@19
|
54 parse(inputSource);
|
lbajardsilogic@19
|
55 }
|
lbajardsilogic@19
|
56
|
lbajardsilogic@19
|
57 void
|
lbajardsilogic@19
|
58 ESFileReader::parse(QXmlInputSource &inputSource)
|
lbajardsilogic@19
|
59 {
|
lbajardsilogic@19
|
60 QXmlSimpleReader reader;
|
lbajardsilogic@19
|
61 reader.setContentHandler(this);
|
lbajardsilogic@19
|
62 reader.setErrorHandler(this);
|
lbajardsilogic@19
|
63 m_ok = reader.parse(inputSource);
|
lbajardsilogic@19
|
64 }
|
lbajardsilogic@19
|
65
|
lbajardsilogic@19
|
66 bool
|
lbajardsilogic@19
|
67 ESFileReader::isOK()
|
lbajardsilogic@19
|
68 {
|
lbajardsilogic@19
|
69 return m_ok;
|
lbajardsilogic@19
|
70 }
|
lbajardsilogic@19
|
71
|
lbajardsilogic@19
|
72 ESFileReader::~ESFileReader()
|
lbajardsilogic@19
|
73 {}
|
lbajardsilogic@19
|
74
|
lbajardsilogic@19
|
75 bool
|
lbajardsilogic@19
|
76 ESFileReader::startElement(const QString &, const QString &,
|
lbajardsilogic@19
|
77 const QString &qName,
|
lbajardsilogic@19
|
78 const QXmlAttributes &attributes)
|
lbajardsilogic@19
|
79 {
|
lbajardsilogic@19
|
80 QString name = qName.toLower();
|
lbajardsilogic@19
|
81
|
lbajardsilogic@19
|
82 bool ok = false;
|
lbajardsilogic@19
|
83
|
lbajardsilogic@19
|
84 // Valid element names:
|
lbajardsilogic@19
|
85 //
|
lbajardsilogic@19
|
86 // easaiersession
|
lbajardsilogic@19
|
87 // data
|
lbajardsilogic@19
|
88 // easaierresources
|
lbajardsilogic@19
|
89 // audio
|
lbajardsilogic@19
|
90 // display
|
lbajardsilogic@19
|
91 // window
|
lbajardsilogic@19
|
92 // view
|
lbajardsilogic@19
|
93 // layer
|
lbajardsilogic@19
|
94
|
lbajardsilogic@19
|
95 if (name == "easaiersession") {
|
lbajardsilogic@19
|
96 // nothing needed
|
lbajardsilogic@19
|
97 ok = true;
|
lbajardsilogic@19
|
98
|
lbajardsilogic@19
|
99 } else if (name == "data") {
|
lbajardsilogic@19
|
100 // nothing needed
|
lbajardsilogic@19
|
101 m_inData = true;
|
lbajardsilogic@19
|
102 ok = true;
|
lbajardsilogic@19
|
103
|
lbajardsilogic@19
|
104 } else if (name == "easaierresources") {
|
lbajardsilogic@19
|
105 // nothing needed
|
lbajardsilogic@19
|
106 ok = true;
|
lbajardsilogic@19
|
107
|
lbajardsilogic@19
|
108 } else if (name == "audio") {
|
lbajardsilogic@19
|
109 QString filename = attributes.value("value");
|
lbajardsilogic@19
|
110 m_document->setAudioSourceInfoFileName(filename);
|
lbajardsilogic@19
|
111
|
lbajardsilogic@19
|
112 } else if (name == "display") {
|
lbajardsilogic@19
|
113 // nothing needed
|
lbajardsilogic@19
|
114 ok = true;
|
lbajardsilogic@19
|
115
|
lbajardsilogic@19
|
116 } else if (name == "window") {
|
lbajardsilogic@19
|
117 ok = readWindow(attributes);
|
lbajardsilogic@19
|
118
|
lbajardsilogic@19
|
119 } else if (name == "view") {
|
lbajardsilogic@19
|
120 m_inView = true;
|
lbajardsilogic@19
|
121 ok = readView(attributes);
|
lbajardsilogic@19
|
122
|
lbajardsilogic@19
|
123 } else if (name == "layer") {
|
lbajardsilogic@19
|
124 ok = readLayer(attributes);
|
lbajardsilogic@19
|
125
|
lbajardsilogic@19
|
126 }
|
lbajardsilogic@19
|
127
|
lbajardsilogic@19
|
128 if (!ok) {
|
lbajardsilogic@19
|
129 std::cerr << "WARNING: Easaier Session-XML: Failed to completely process element \""
|
lbajardsilogic@19
|
130 << name.toLocal8Bit().data() << "\"" << std::endl;
|
lbajardsilogic@19
|
131 }
|
lbajardsilogic@19
|
132
|
lbajardsilogic@19
|
133 return true;
|
lbajardsilogic@19
|
134 }
|
lbajardsilogic@19
|
135
|
lbajardsilogic@19
|
136 bool
|
lbajardsilogic@19
|
137 ESFileReader::characters(const QString &text)
|
lbajardsilogic@19
|
138 {
|
lbajardsilogic@19
|
139 return true;
|
lbajardsilogic@19
|
140 }
|
lbajardsilogic@19
|
141
|
lbajardsilogic@19
|
142 bool
|
lbajardsilogic@19
|
143 ESFileReader::endElement(const QString &, const QString &,
|
lbajardsilogic@19
|
144 const QString &qName)
|
lbajardsilogic@19
|
145 {
|
lbajardsilogic@19
|
146 QString name = qName.toLower();
|
lbajardsilogic@19
|
147
|
lbajardsilogic@19
|
148 if (name == "data") {
|
lbajardsilogic@19
|
149
|
lbajardsilogic@19
|
150 m_inData = false;
|
lbajardsilogic@19
|
151
|
lbajardsilogic@19
|
152 } else if (name == "view") {
|
lbajardsilogic@19
|
153 m_inView = false;
|
lbajardsilogic@19
|
154 }
|
lbajardsilogic@19
|
155
|
lbajardsilogic@19
|
156 return true;
|
lbajardsilogic@19
|
157 }
|
lbajardsilogic@19
|
158
|
lbajardsilogic@19
|
159 bool
|
lbajardsilogic@19
|
160 ESFileReader::error(const QXmlParseException &exception)
|
lbajardsilogic@19
|
161 {
|
lbajardsilogic@19
|
162 m_errorString =
|
lbajardsilogic@19
|
163 QString("ERROR: Easaier Session-XML: %1 at line %2, column %3")
|
lbajardsilogic@19
|
164 .arg(exception.message())
|
lbajardsilogic@19
|
165 .arg(exception.lineNumber())
|
lbajardsilogic@19
|
166 .arg(exception.columnNumber());
|
lbajardsilogic@19
|
167 std::cerr << m_errorString.toLocal8Bit().data() << std::endl;
|
lbajardsilogic@19
|
168 return QXmlDefaultHandler::error(exception);
|
lbajardsilogic@19
|
169 }
|
lbajardsilogic@19
|
170
|
lbajardsilogic@19
|
171 bool
|
lbajardsilogic@19
|
172 ESFileReader::fatalError(const QXmlParseException &exception)
|
lbajardsilogic@19
|
173 {
|
lbajardsilogic@19
|
174 m_errorString =
|
lbajardsilogic@19
|
175 QString("FATAL ERROR: Easaier Session-XML: %1 at line %2, column %3")
|
lbajardsilogic@19
|
176 .arg(exception.message())
|
lbajardsilogic@19
|
177 .arg(exception.lineNumber())
|
lbajardsilogic@19
|
178 .arg(exception.columnNumber());
|
lbajardsilogic@19
|
179 std::cerr << m_errorString.toLocal8Bit().data() << std::endl;
|
lbajardsilogic@19
|
180 return QXmlDefaultHandler::fatalError(exception);
|
lbajardsilogic@19
|
181 }
|
lbajardsilogic@19
|
182
|
lbajardsilogic@19
|
183
|
lbajardsilogic@19
|
184 #define READ_MANDATORY(TYPE, NAME, CONVERSION) \
|
lbajardsilogic@19
|
185 TYPE NAME = attributes.value(#NAME).trimmed().CONVERSION(&ok); \
|
lbajardsilogic@19
|
186 if (!ok) { \
|
lbajardsilogic@19
|
187 std::cerr << "WARNING: Easaier Session-XML: Missing or invalid mandatory " #TYPE " attribute \"" #NAME "\"" << std::endl; \
|
lbajardsilogic@19
|
188 return false; \
|
lbajardsilogic@19
|
189 }
|
lbajardsilogic@19
|
190
|
lbajardsilogic@19
|
191 bool
|
lbajardsilogic@19
|
192 ESFileReader::readWindow(const QXmlAttributes &attributes)
|
lbajardsilogic@19
|
193 {
|
lbajardsilogic@19
|
194 bool ok = false;
|
lbajardsilogic@19
|
195
|
lbajardsilogic@19
|
196 READ_MANDATORY(int, width, toInt);
|
lbajardsilogic@19
|
197 READ_MANDATORY(int, height, toInt);
|
lbajardsilogic@19
|
198
|
lbajardsilogic@19
|
199 m_paneCallback.setWindowSize(width, height);
|
lbajardsilogic@19
|
200 return true;
|
lbajardsilogic@19
|
201 }
|
lbajardsilogic@19
|
202
|
lbajardsilogic@19
|
203 bool
|
lbajardsilogic@19
|
204 ESFileReader::readView(const QXmlAttributes &attributes)
|
lbajardsilogic@19
|
205 {
|
lbajardsilogic@19
|
206 QString type = attributes.value("type");
|
lbajardsilogic@19
|
207 m_currentPane = 0;
|
lbajardsilogic@19
|
208
|
lbajardsilogic@19
|
209 if (type != "pane") {
|
lbajardsilogic@19
|
210 std::cerr << "WARNING: Easaier session-XML: Unexpected view type \""
|
lbajardsilogic@19
|
211 << type.toLocal8Bit().data() << "\"" << std::endl;
|
lbajardsilogic@19
|
212 return false;
|
lbajardsilogic@19
|
213 }
|
lbajardsilogic@19
|
214
|
lbajardsilogic@19
|
215 m_currentPane = m_paneCallback.addPane();
|
lbajardsilogic@19
|
216
|
lbajardsilogic@19
|
217 if (!m_currentPane) {
|
lbajardsilogic@19
|
218 std::cerr << "WARNING: Easaier session-XML: Internal error: Failed to add pane!"
|
lbajardsilogic@19
|
219 << std::endl;
|
lbajardsilogic@19
|
220 return false;
|
lbajardsilogic@19
|
221 }
|
lbajardsilogic@19
|
222
|
lbajardsilogic@19
|
223 bool ok = false;
|
lbajardsilogic@19
|
224
|
lbajardsilogic@19
|
225 View *view = m_currentPane;
|
lbajardsilogic@19
|
226
|
lbajardsilogic@19
|
227 // The view properties first
|
lbajardsilogic@19
|
228
|
lbajardsilogic@19
|
229 READ_MANDATORY(size_t, centre, toUInt);
|
lbajardsilogic@19
|
230 READ_MANDATORY(size_t, zoom, toUInt);
|
lbajardsilogic@19
|
231 READ_MANDATORY(int, followPan, toInt);
|
lbajardsilogic@19
|
232 READ_MANDATORY(int, followZoom, toInt);
|
lbajardsilogic@19
|
233 QString tracking = attributes.value("tracking");
|
lbajardsilogic@19
|
234
|
lbajardsilogic@19
|
235 // Specify the follow modes before we set the actual values
|
lbajardsilogic@19
|
236 view->setFollowGlobalPan(followPan);
|
lbajardsilogic@19
|
237 view->setFollowGlobalZoom(followZoom);
|
lbajardsilogic@19
|
238 view->setPlaybackFollow(tracking == "scroll" ? PlaybackScrollContinuous :
|
lbajardsilogic@19
|
239 tracking == "page" ? PlaybackScrollPage
|
lbajardsilogic@19
|
240 : PlaybackIgnore);
|
lbajardsilogic@19
|
241
|
lbajardsilogic@19
|
242 // Then set these values
|
lbajardsilogic@19
|
243 view->setCentreFrame(centre);
|
lbajardsilogic@19
|
244 view->setZoomLevel(zoom);
|
lbajardsilogic@19
|
245
|
lbajardsilogic@19
|
246 // And pane properties
|
lbajardsilogic@19
|
247 READ_MANDATORY(int, centreLineVisible, toInt);
|
lbajardsilogic@19
|
248 m_currentPane->setCentreLineVisible(centreLineVisible);
|
lbajardsilogic@19
|
249
|
lbajardsilogic@19
|
250 int height = attributes.value("height").toInt(&ok);
|
lbajardsilogic@19
|
251 if (ok) {
|
lbajardsilogic@19
|
252 m_currentPane->resize(m_currentPane->width(), height);
|
lbajardsilogic@19
|
253 }
|
lbajardsilogic@19
|
254
|
lbajardsilogic@19
|
255 return true;
|
lbajardsilogic@19
|
256 }
|
lbajardsilogic@19
|
257
|
lbajardsilogic@19
|
258 bool
|
lbajardsilogic@19
|
259 ESFileReader::readLayer(const QXmlAttributes &attributes)
|
lbajardsilogic@19
|
260 {
|
lbajardsilogic@19
|
261 QString type = attributes.value("type");
|
lbajardsilogic@19
|
262
|
lbajardsilogic@19
|
263 int id;
|
lbajardsilogic@19
|
264 bool ok = false;
|
lbajardsilogic@19
|
265 id = attributes.value("id").trimmed().toInt(&ok);
|
lbajardsilogic@19
|
266
|
lbajardsilogic@19
|
267 if (!ok) {
|
lbajardsilogic@19
|
268 std::cerr << "WARNING: Easaier session-XML: No layer id for layer of type \""
|
lbajardsilogic@19
|
269 << type.toLocal8Bit().data()
|
lbajardsilogic@19
|
270 << "\"" << std::endl;
|
lbajardsilogic@19
|
271 return false;
|
lbajardsilogic@19
|
272 }
|
lbajardsilogic@19
|
273
|
lbajardsilogic@19
|
274 Layer *layer = 0;
|
lbajardsilogic@19
|
275 bool isNewLayer = false;
|
lbajardsilogic@19
|
276
|
lbajardsilogic@19
|
277 // Layers are expected to be defined in layer elements in the data
|
lbajardsilogic@19
|
278 // section, and referred to in layer elements in the view
|
lbajardsilogic@19
|
279 // sections. So if we're in the data section, we expect this
|
lbajardsilogic@19
|
280 // layer not to exist already; if we're in the view section, we
|
lbajardsilogic@19
|
281 // expect it to exist.
|
lbajardsilogic@19
|
282
|
lbajardsilogic@19
|
283 if (m_inData) {
|
lbajardsilogic@19
|
284
|
lbajardsilogic@19
|
285 if (m_layers.find(id) != m_layers.end()) {
|
lbajardsilogic@19
|
286 std::cerr << "WARNING: Easaier session-XML: Ignoring duplicate layer id " << id
|
lbajardsilogic@19
|
287 << " in data section" << std::endl;
|
lbajardsilogic@19
|
288 return false;
|
lbajardsilogic@19
|
289 }
|
lbajardsilogic@19
|
290
|
lbajardsilogic@19
|
291 layer = m_layers[id] = m_document->createLayer
|
lbajardsilogic@19
|
292 (LayerFactory::getInstance()->getLayerTypeForName(type));
|
lbajardsilogic@19
|
293
|
lbajardsilogic@19
|
294 if (layer) {
|
lbajardsilogic@19
|
295 m_layers[id] = layer;
|
lbajardsilogic@19
|
296 isNewLayer = true;
|
lbajardsilogic@19
|
297 }
|
lbajardsilogic@19
|
298
|
lbajardsilogic@19
|
299 } else {
|
lbajardsilogic@19
|
300
|
lbajardsilogic@19
|
301 if (!m_currentPane) {
|
lbajardsilogic@19
|
302 std::cerr << "WARNING: Easaier session-XML: No current pane for layer " << id
|
lbajardsilogic@19
|
303 << " in view section" << std::endl;
|
lbajardsilogic@19
|
304 return false;
|
lbajardsilogic@19
|
305 }
|
lbajardsilogic@19
|
306
|
lbajardsilogic@19
|
307 if (m_layers.find(id) != m_layers.end()) {
|
lbajardsilogic@19
|
308
|
lbajardsilogic@19
|
309 layer = m_layers[id];
|
lbajardsilogic@19
|
310
|
lbajardsilogic@19
|
311 } else {
|
lbajardsilogic@19
|
312 layer = m_document->createLayer(LayerFactory::getInstance()->getLayerTypeForName(type));
|
lbajardsilogic@19
|
313
|
lbajardsilogic@19
|
314 if (layer) {
|
lbajardsilogic@19
|
315 m_layers[id] = layer;
|
lbajardsilogic@19
|
316 isNewLayer = true;
|
lbajardsilogic@19
|
317 }
|
lbajardsilogic@19
|
318 }
|
lbajardsilogic@19
|
319 }
|
lbajardsilogic@19
|
320
|
lbajardsilogic@19
|
321 if (!layer) {
|
lbajardsilogic@19
|
322 std::cerr << "WARNING: Easaier session-XML: Failed to add layer of type \""
|
lbajardsilogic@19
|
323 << type.toLocal8Bit().data()
|
lbajardsilogic@19
|
324 << "\"" << std::endl;
|
lbajardsilogic@19
|
325 return false;
|
lbajardsilogic@19
|
326 }
|
lbajardsilogic@19
|
327
|
lbajardsilogic@19
|
328 if (isNewLayer) {
|
lbajardsilogic@19
|
329
|
lbajardsilogic@19
|
330 QString name = attributes.value("name");
|
lbajardsilogic@19
|
331 layer->setObjectName(name);
|
lbajardsilogic@19
|
332
|
lbajardsilogic@19
|
333 QString modelName = attributes.value("model");
|
lbajardsilogic@19
|
334 int modelId = attributes.value("modelId").toInt();
|
lbajardsilogic@19
|
335
|
lbajardsilogic@19
|
336 layer->setModelName(modelName);
|
lbajardsilogic@19
|
337 layer->setModelId(modelId);
|
lbajardsilogic@19
|
338
|
lbajardsilogic@19
|
339 layer->setProperties(attributes);
|
lbajardsilogic@19
|
340 }
|
lbajardsilogic@19
|
341
|
lbajardsilogic@19
|
342 if (!m_inData && m_currentPane) {
|
lbajardsilogic@19
|
343 m_document->addLayerToView(m_currentPane, layer);
|
lbajardsilogic@19
|
344 }
|
lbajardsilogic@19
|
345
|
lbajardsilogic@19
|
346 return true;
|
lbajardsilogic@19
|
347 }
|
lbajardsilogic@19
|
348
|