| Chris@45 | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */ | 
| Chris@45 | 2 | 
| Chris@45 | 3 /* | 
| Chris@45 | 4     Sonic Visualiser | 
| Chris@45 | 5     An audio file viewer and annotation editor. | 
| Chris@45 | 6     Centre for Digital Music, Queen Mary, University of London. | 
| Chris@45 | 7     This file copyright 2006 Chris Cannam and QMUL. | 
| Chris@45 | 8 | 
| Chris@45 | 9     This program is free software; you can redistribute it and/or | 
| Chris@45 | 10     modify it under the terms of the GNU General Public License as | 
| Chris@45 | 11     published by the Free Software Foundation; either version 2 of the | 
| Chris@45 | 12     License, or (at your option) any later version.  See the file | 
| Chris@45 | 13     COPYING included with this distribution for more information. | 
| Chris@45 | 14 */ | 
| Chris@45 | 15 | 
| Chris@45 | 16 #ifndef _SV_FILE_READER_H_ | 
| Chris@45 | 17 #define _SV_FILE_READER_H_ | 
| Chris@45 | 18 | 
| Chris@45 | 19 #include "layer/LayerFactory.h" | 
| Chris@106 | 20 #include "transform/Transform.h" | 
| Chris@45 | 21 | 
| Chris@45 | 22 #include <QXmlDefaultHandler> | 
| Chris@45 | 23 | 
| Chris@45 | 24 #include <map> | 
| Chris@45 | 25 | 
| Chris@45 | 26 class Pane; | 
| Chris@45 | 27 class Model; | 
| Chris@45 | 28 class Document; | 
| Chris@45 | 29 class PlayParameters; | 
| Chris@45 | 30 | 
| Chris@45 | 31 class SVFileReaderPaneCallback | 
| Chris@45 | 32 { | 
| Chris@45 | 33 public: | 
| Chris@45 | 34     virtual ~SVFileReaderPaneCallback(); | 
| Chris@45 | 35     virtual Pane *addPane() = 0; | 
| Chris@45 | 36     virtual void setWindowSize(int width, int height) = 0; | 
| Chris@45 | 37     virtual void addSelection(int start, int end) = 0; | 
| Chris@45 | 38 }; | 
| Chris@45 | 39 | 
| Chris@45 | 40 /** | 
| Chris@45 | 41     SVFileReader loads Sonic Visualiser XML files.  (The SV file | 
| Chris@45 | 42     format is bzipped XML.) | 
| Chris@45 | 43 | 
| Chris@45 | 44     Some notes about the SV XML format follow.  We're very lazy with | 
| Chris@45 | 45     our XML: there's no schema or DTD, and we depend heavily on | 
| Chris@45 | 46     elements being in a particular order. | 
| Chris@45 | 47 | 
| Chris@45 | 48 \verbatim | 
| Chris@45 | 49 | 
| Chris@45 | 50     <sv> | 
| Chris@45 | 51 | 
| Chris@45 | 52     <data> | 
| Chris@45 | 53 | 
| Chris@45 | 54       <!-- The data section contains definitions of both models and | 
| Chris@45 | 55            visual layers.  Layers are considered data in the document; | 
| Chris@45 | 56            the structure of views that displays the layers is not. --> | 
| Chris@45 | 57 | 
| Chris@45 | 58       <!-- id numbers are unique within the data type (i.e. no two | 
| Chris@45 | 59            models can have the same id, but a model can have the same | 
| Chris@45 | 60            id as a layer, etc).  SV generates its id numbers just for | 
| Chris@45 | 61            the purpose of cross-referencing within the current file; | 
| Chris@45 | 62            they don't necessarily have any meaning once the file has | 
| Chris@45 | 63            been loaded. --> | 
| Chris@45 | 64 | 
| Chris@45 | 65       <model id="0" name="..." type="..." ... /> | 
| Chris@45 | 66       <model id="1" name="..." type="..." ... /> | 
| Chris@45 | 67 | 
| Chris@45 | 68       <!-- Models that have data associated with them store it | 
| Chris@45 | 69            in a neighbouring dataset element.  The dataset must follow | 
| Chris@45 | 70            the model and precede any derivation or layer elements that | 
| Chris@45 | 71            refer to the model. --> | 
| Chris@45 | 72 | 
| Chris@45 | 73       <model id="2" name="..." type="..." dataset="0" ... /> | 
| Chris@45 | 74 | 
| Chris@45 | 75       <dataset id="0" type="..."> | 
| Chris@45 | 76         <point frame="..." value="..." ... /> | 
| Chris@45 | 77       </dataset> | 
| Chris@45 | 78 | 
| Chris@45 | 79       <!-- Where one model is derived from another via a transform, | 
| Chris@45 | 80            it has an associated derivation element.  This must follow | 
| Chris@45 | 81            both the source and target model elements.  The source and | 
| Chris@45 | 82            model attributes give the source model id and target model | 
| Chris@45 | 83            id respectively.  A model can have both dataset and | 
| Chris@45 | 84            derivation elements; if it does, dataset must appear first. | 
| Chris@45 | 85            If the model's data are not stored, but instead the model | 
| Chris@45 | 86            is to be regenerated completely from the transform when | 
| Chris@45 | 87            the session is reloaded, then the model should have _only_ | 
| Chris@45 | 88            a derivation element, and no model element should appear | 
| Chris@45 | 89            for it at all. --> | 
| Chris@45 | 90 | 
| Chris@72 | 91       <derivation type="transform" source="0" model="2" channel="-1"> | 
| Chris@72 | 92         <transform id="vamp:soname:pluginid:output" ... /> | 
| Chris@72 | 93       </derivation> | 
| Chris@72 | 94 | 
| Chris@72 | 95       <!-- Note that the derivation element just described replaces | 
| Chris@72 | 96            this earlier formulation, which had more attributes in the | 
| Chris@72 | 97            derivation element and a plugin element describing plugin | 
| Chris@72 | 98            parameters and properties.  What we actually read and | 
| Chris@72 | 99            write these days is a horrid composite of the two formats, | 
| Chris@72 | 100            for backward compatibility reasons. --> | 
| Chris@72 | 101 | 
| Chris@72 | 102       <derivation source="0" model="2" transform="vamp:soname:pluginid:output" ...> | 
| Chris@72 | 103         <plugin id="pluginid" ... /> | 
| Chris@45 | 104       </derivation> | 
| Chris@45 | 105 | 
| Chris@45 | 106       <!-- The playparameters element lists playback settings for | 
| Chris@45 | 107            a model. --> | 
| Chris@45 | 108 | 
| Chris@45 | 109       <playparameters mute="false" pan="0" gain="1" model="1" ... /> | 
| Chris@45 | 110 | 
| Chris@45 | 111       <!-- Layer elements.  The models must have already been defined. | 
| Chris@45 | 112            The same model may appear in more than one layer (of more | 
| Chris@45 | 113            than one type). --> | 
| Chris@45 | 114 | 
| Chris@45 | 115       <layer id="1" type="..." name="..." model="0" ... /> | 
| Chris@45 | 116       <layer id="2" type="..." name="..." model="1" ... /> | 
| Chris@45 | 117 | 
| Chris@45 | 118     </data> | 
| Chris@45 | 119 | 
| Chris@45 | 120 | 
| Chris@45 | 121     <display> | 
| Chris@45 | 122 | 
| Chris@45 | 123       <!-- The display element contains visual structure for the | 
| Chris@45 | 124            layers.  It's simpler than the data section. --> | 
| Chris@45 | 125 | 
| Chris@45 | 126       <!-- Overall preferred window size for this session. --> | 
| Chris@45 | 127 | 
| Chris@45 | 128       <window width="..." height="..."/> | 
| Chris@45 | 129 | 
| Chris@45 | 130       <!-- List of view elements to stack up.  Each one contains | 
| Chris@45 | 131            a list of layers in stacking order, back to front. --> | 
| Chris@45 | 132 | 
| Chris@45 | 133       <view type="pane" ...> | 
| Chris@45 | 134         <layer id="1"/> | 
| Chris@45 | 135         <layer id="2"/> | 
| Chris@45 | 136       </view> | 
| Chris@45 | 137 | 
| Chris@45 | 138       <!-- The layer elements just refer to layers defined in the | 
| Chris@45 | 139            data section, so they don't have to have any attributes | 
| Chris@45 | 140            other than the id.  For sort-of-historical reasons SV | 
| Chris@45 | 141            actually does repeat the other attributes here, but | 
| Chris@45 | 142            it doesn't need to. --> | 
| Chris@45 | 143 | 
| Chris@45 | 144       <view type="pane" ...> | 
| Chris@45 | 145         <layer id="2"/> | 
| Chris@45 | 146       <view> | 
| Chris@45 | 147 | 
| Chris@45 | 148     </display> | 
| Chris@45 | 149 | 
| Chris@45 | 150 | 
| Chris@45 | 151     <!-- List of selected regions by audio frame extents. --> | 
| Chris@45 | 152 | 
| Chris@45 | 153     <selections> | 
| Chris@45 | 154       <selection start="..." end="..."/> | 
| Chris@45 | 155     </selections> | 
| Chris@45 | 156 | 
| Chris@45 | 157 | 
| Chris@45 | 158     </sv> | 
| Chris@45 | 159 | 
| Chris@45 | 160 \endverbatim | 
| Chris@45 | 161  */ | 
| Chris@45 | 162 | 
| Chris@45 | 163 | 
| Chris@79 | 164 class SVFileReader : public QObject, QXmlDefaultHandler | 
| Chris@45 | 165 { | 
| Chris@79 | 166     Q_OBJECT | 
| Chris@79 | 167 | 
| Chris@45 | 168 public: | 
| Chris@45 | 169     SVFileReader(Document *document, | 
| Chris@45 | 170 		 SVFileReaderPaneCallback &callback, | 
| Chris@45 | 171                  QString location = ""); // for audio file locate mechanism | 
| Chris@45 | 172     virtual ~SVFileReader(); | 
| Chris@45 | 173 | 
| Chris@45 | 174     void parse(const QString &xmlData); | 
| Chris@45 | 175     void parse(QXmlInputSource &source); | 
| Chris@45 | 176 | 
| Chris@45 | 177     bool isOK(); | 
| Chris@45 | 178     QString getErrorString() const { return m_errorString; } | 
| Chris@45 | 179 | 
| Chris@45 | 180     // For loading a single layer onto an existing pane | 
| Chris@45 | 181     void setCurrentPane(Pane *pane) { m_currentPane = pane; } | 
| Chris@45 | 182 | 
| Chris@45 | 183     virtual bool startElement(const QString &namespaceURI, | 
| Chris@45 | 184 			      const QString &localName, | 
| Chris@45 | 185 			      const QString &qName, | 
| Chris@45 | 186 			      const QXmlAttributes& atts); | 
| Chris@45 | 187 | 
| Chris@45 | 188     virtual bool characters(const QString &); | 
| Chris@45 | 189 | 
| Chris@45 | 190     virtual bool endElement(const QString &namespaceURI, | 
| Chris@45 | 191 			    const QString &localName, | 
| Chris@45 | 192 			    const QString &qName); | 
| Chris@45 | 193 | 
| Chris@45 | 194     bool error(const QXmlParseException &exception); | 
| Chris@45 | 195     bool fatalError(const QXmlParseException &exception); | 
| Chris@45 | 196 | 
| Chris@140 | 197     enum FileType | 
| Chris@140 | 198     { | 
| Chris@140 | 199         SVSessionFile, | 
| Chris@140 | 200         SVLayerFile, | 
| Chris@140 | 201         UnknownFileType | 
| Chris@140 | 202     }; | 
| Chris@140 | 203 | 
| Chris@140 | 204     static FileType identifyXmlFile(QString path); | 
| Chris@140 | 205 | 
| Chris@79 | 206 signals: | 
| Chris@79 | 207     void modelRegenerationFailed(QString layerName, QString transformName, | 
| Chris@79 | 208                                  QString message); | 
| Chris@79 | 209     void modelRegenerationWarning(QString layerName, QString transformName, | 
| Chris@79 | 210                                   QString message); | 
| Chris@79 | 211 | 
| Chris@45 | 212 protected: | 
| Chris@45 | 213     bool readWindow(const QXmlAttributes &); | 
| Chris@45 | 214     bool readModel(const QXmlAttributes &); | 
| Chris@45 | 215     bool readView(const QXmlAttributes &); | 
| Chris@45 | 216     bool readLayer(const QXmlAttributes &); | 
| Chris@45 | 217     bool readDatasetStart(const QXmlAttributes &); | 
| Chris@45 | 218     bool addBinToDataset(const QXmlAttributes &); | 
| Chris@45 | 219     bool addPointToDataset(const QXmlAttributes &); | 
| Chris@45 | 220     bool addRowToDataset(const QXmlAttributes &); | 
| Chris@45 | 221     bool readRowData(const QString &); | 
| Chris@45 | 222     bool readDerivation(const QXmlAttributes &); | 
| Chris@45 | 223     bool readPlayParameters(const QXmlAttributes &); | 
| Chris@45 | 224     bool readPlugin(const QXmlAttributes &); | 
| Chris@72 | 225     bool readTransform(const QXmlAttributes &); | 
| Chris@72 | 226     bool readParameter(const QXmlAttributes &); | 
| Chris@45 | 227     bool readSelection(const QXmlAttributes &); | 
| Chris@45 | 228     bool readMeasurement(const QXmlAttributes &); | 
| Chris@45 | 229     void addUnaddedModels(); | 
| Chris@45 | 230 | 
| Chris@45 | 231     bool haveModel(int id) { | 
| Chris@45 | 232         return (m_models.find(id) != m_models.end()) && m_models[id]; | 
| Chris@45 | 233     } | 
| Chris@45 | 234 | 
| Chris@45 | 235     Document *m_document; | 
| Chris@45 | 236     SVFileReaderPaneCallback &m_paneCallback; | 
| Chris@45 | 237     QString m_location; | 
| Chris@45 | 238     Pane *m_currentPane; | 
| Chris@45 | 239     std::map<int, Layer *> m_layers; | 
| Chris@45 | 240     std::map<int, Model *> m_models; | 
| Chris@45 | 241     std::set<Model *> m_addedModels; | 
| Chris@45 | 242     std::map<int, int> m_awaitingDatasets; // map dataset id -> model id | 
| Chris@45 | 243     Layer *m_currentLayer; | 
| Chris@45 | 244     Model *m_currentDataset; | 
| Chris@45 | 245     Model *m_currentDerivedModel; | 
| Chris@45 | 246     int m_currentDerivedModelId; | 
| Chris@45 | 247     PlayParameters *m_currentPlayParameters; | 
| Chris@72 | 248     Transform m_currentTransform; | 
| Chris@72 | 249     Model *m_currentTransformSource; | 
| Chris@72 | 250     int m_currentTransformChannel; | 
| Chris@72 | 251     bool m_currentTransformIsNewStyle; | 
| Chris@45 | 252     QString m_datasetSeparator; | 
| Chris@45 | 253     bool m_inRow; | 
| Chris@45 | 254     bool m_inLayer; | 
| Chris@45 | 255     bool m_inView; | 
| Chris@45 | 256     bool m_inData; | 
| Chris@45 | 257     bool m_inSelections; | 
| Chris@45 | 258     int m_rowNumber; | 
| Chris@45 | 259     QString m_errorString; | 
| Chris@45 | 260     bool m_ok; | 
| Chris@45 | 261 }; | 
| Chris@45 | 262 | 
| Chris@45 | 263 #endif |