1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4     Rosegarden
5     A MIDI and audio sequencer and musical notation editor.
6     Copyright 2000-2021 the Rosegarden development team.
7 
8     Other copyrights also apply to some parts of this work.  Please
9     see the AUTHORS file and individual file headers for details.
10 
11     This program is free software; you can redistribute it and/or
12     modify it under the terms of the GNU General Public License as
13     published by the Free Software Foundation; either version 2 of the
14     License, or (at your option) any later version.  See the file
15     COPYING included with this distribution for more information.
16 */
17 
18 #ifndef RG_ROSEXMLHANDLER_H
19 #define RG_ROSEXMLHANDLER_H
20 
21 #include "base/Device.h"
22 #include "base/MidiProgram.h"
23 #include "base/Event.h"
24 #include "document/io/XMLHandler.h"
25 
26 #include <QString>
27 #include <QtCore/QSharedPointer>
28 #include <QPointer>
29 #include <QProgressDialog>
30 #include <QSharedPointer>
31 
32 #include <map>
33 #include <set>
34 #include <string>
35 
36 
37 namespace Rosegarden
38 {
39 
40 class XmlStorableEvent;
41 class XmlSubHandler;
42 class Studio;
43 class Segment;
44 class SegmentLinker;
45 class RosegardenDocument;
46 class Instrument;
47 class Device;
48 class Composition;
49 class ColourMap;
50 class Buss;
51 class AudioPluginManager;
52 class AudioPluginInstance;
53 class AudioFileManager;
54 
55 
56 /**
57  * Handler for the Rosegarden XML format
58  */
59 class RoseXmlHandler : public QObject, public XMLHandler
60 {
61     //Q_OBJECT
62 public:
63 
64     typedef enum
65     {
66         NoSection,
67         InComposition,
68         InSegment,
69         InStudio,
70         InInstrument,
71         InBuss,
72         InAudioFiles,
73         InPlugin,
74         InAppearance
75     } RosegardenFileSection;
76 
77     /**
78      * Construct a new RoseXmlHandler which will put the data extracted
79      * from the XML file into the specified composition
80      */
81     RoseXmlHandler(RosegardenDocument *doc,
82                    unsigned int elementCount,
83                    QPointer<QProgressDialog> progressDialog,
84                    bool createNewDevicesWhenNeeded);
85 
86     ~RoseXmlHandler() override;
87 
88     /// overloaded handler functions
89     bool startDocument() override;
90     bool startElement(const QString& namespaceURI,
91                               const QString& localName,
92                               const QString& qName,
93                               const QXmlStreamAttributes& atts) override;
94 
95     bool endElement(const QString& namespaceURI,
96                             const QString& localName,
97                             const QString& qName) override;
98 
99     bool characters(const QString& ch) override;
100 
101     bool endDocument() override; // [rwb] - for tempo element catch
102 
isDeprecated()103     bool isDeprecated() { return m_deprecation; }
104 
105     /// Return the error string set during the parsing (if any)
106     QString errorString() const override;
107 
hasActiveAudio()108     bool hasActiveAudio() const { return m_hasActiveAudio; }
pluginsNotFound()109     std::set<QString> &pluginsNotFound() { return m_pluginsNotFound; }
110 
111     bool fatalError(int lineNumber, int columnNumber,
112                     const QString& msg) override;
113 
114 
115 protected:
116 
117     // just for convenience -- just call to the document
118     //
119     Composition& getComposition();
120     Studio& getStudio();
121     AudioFileManager& getAudioFileManager();
122     QSharedPointer<AudioPluginManager> getAudioPluginManager();
123 
124     void setSubHandler(XmlSubHandler* sh);
getSubHandler()125     XmlSubHandler* getSubHandler() { return m_subHandler; }
126 
127     void addMIDIDevice(QString name, bool createAtSequencer, QString dir);  // dir = play|record
128     void setMIDIDeviceConnection(QString connection);
129     void setMIDIDeviceName(QString name);
130     void skipToNextPlayDevice();
131     InstrumentId mapToActualInstrument(InstrumentId id);
132 
133     //--------------- Data members ---------------------------------
134 
135     RosegardenDocument    *m_doc;
136     Segment *m_currentSegment;
137     XmlStorableEvent    *m_currentEvent;
138     typedef std::map<int, SegmentLinker *> SegmentLinkerMap;
139     SegmentLinkerMap m_segmentLinkers;
140 
141     timeT m_currentTime;
142     timeT m_chordDuration;
143     timeT *m_segmentEndMarkerTime;
144 
145     bool m_inChord;
146     bool m_inGroup;
147     bool m_inComposition;
148     bool m_inColourMap;
149     bool m_inMatrix;
150     bool m_inNotation;
151     std::string m_groupType;
152     int m_groupId;
153     int m_groupTupletBase;
154     int m_groupTupledCount;
155     int m_groupUntupledCount;
156     std::map<long, long> m_groupIdMap;
157 
158     bool m_foundTempo;
159 
160     QString m_errorString;
161     std::set<QString> m_pluginsNotFound;
162 
163     RosegardenFileSection             m_section;
164 
165     Device                           *m_device;
166     DeviceId                          m_deviceRunningId;
167     InstrumentId                      m_deviceInstrumentBase;
168     InstrumentId                      m_deviceReadInstrumentBase;
169     std::map<InstrumentId, InstrumentId> m_actualInstrumentIdMap;
170     bool                              m_percussion;
171     bool                              m_sendBankSelect;
172     MidiByte                          m_msb;
173     MidiByte                          m_lsb;
174     Instrument                       *m_instrument;
175 
176     /// Whether a <controlchange> tag was found.  MIDI <instrument> only.
177     bool m_controlChangeEncountered;
178     /// Deprecated <volume> tag encountered.  MIDI <instrument> only.
179     bool m_volumeEncountered;
180     /// Value in the <volume> tag.  MIDI <instrument> only.
181     MidiByte m_volume;
182     /// Deprecated <pan> tag encountered.  MIDI <instrument> only.
183     bool m_panEncountered;
184     /// Value in the <pan> tag.  MIDI <instrument> only.
185     MidiByte m_pan;
186 
187     Buss                             *m_buss;
188     AudioPluginInstance              *m_plugin;
189     bool                              m_pluginInBuss;
190     ColourMap                        *m_colourMap;
191     QSharedPointer<MidiKeyMapping> m_keyMapping;
192     MidiKeyMapping::KeyNameMap        m_keyNameMap;
193     unsigned int                      m_pluginId;
194     unsigned int                      m_totalElements;
195     unsigned int                      m_elementsSoFar;
196 
197     XmlSubHandler                    *m_subHandler;
198     bool                              m_deprecation;
199     bool                              m_createDevices;
200     bool                              m_haveControls;
201     bool                              m_skipAllAudio;
202     bool                              m_hasActiveAudio;
203 
204     // In case we encounter an old solo attribute at the composition level,
205     // hold onto it and use it to set the solo for the proper track.
206     bool m_oldSolo;
207 
208     QPointer<QProgressDialog> m_progressDialog;
209 };
210 
211 
212 }
213 
214 #endif
215