Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #pragma once
24 :
25 : #include "engraving/types/types.h"
26 :
27 : #include "modularity/ioc.h"
28 : #include "imeiconfiguration.h"
29 : #include "io/ifilesystem.h"
30 : #include "io/path.h"
31 :
32 : #include "meiconverter.h"
33 :
34 : #include "thirdparty/libmei/cmn.h"
35 : #include "thirdparty/libmei/element.h"
36 : #include "thirdparty/libmei/shared.h"
37 :
38 : #include "pugixml.hpp"
39 :
40 : namespace mu::engraving {
41 : class Chord;
42 : class ChordRest;
43 : class EngravingItem;
44 : class Lyrics;
45 : class Measure;
46 : class Note;
47 : class Part;
48 : class Score;
49 : class Spanner;
50 : class Tuplet;
51 : class VBox;
52 : enum class NoteType : unsigned char;
53 : enum class TimeSigType : unsigned char;
54 : struct ClefTypeList;
55 : }
56 :
57 : namespace mu::iex::mei {
58 : class UIDRegister;
59 :
60 : struct ControlElementPosition {
61 : engraving::Measure* measure = nullptr;
62 : engraving::Fraction tick;
63 : engraving::track_idx_t track = 0;
64 : engraving::ChordRest* chordRest = nullptr;
65 : };
66 :
67 : enum GraceReading {
68 : GraceNone = 0,
69 : GraceAsGrp,
70 : GraceAsNote
71 : };
72 :
73 : /**
74 : * Class of importing Music Encoding Initiative (MEI) files
75 : */
76 :
77 : class MeiImporter
78 : {
79 : muse::GlobalInject<mu::iex::mei::IMeiConfiguration> configuration;
80 : muse::GlobalInject<muse::io::IFileSystem> fileSystem;
81 :
82 : public:
83 64 : MeiImporter(engraving::Score* s) { m_score = s; }
84 : bool read(const muse::io::path_t& path);
85 :
86 : private:
87 : /**
88 : * Methods for parsing the MEI tree and converting data
89 : */
90 : bool readMeiHead(pugi::xml_node root);
91 : bool readScore(pugi::xml_node root);
92 : bool readScoreDef(pugi::xml_node scoreDefNode, bool isInitial);
93 : bool readPgHead(pugi::xml_node pgHeadNode);
94 : bool readLines(pugi::xml_node parentNode, muse::StringList& lines, size_t& line);
95 : bool readLinesWithSmufl(pugi::xml_node parentNode, muse::StringList& lines);
96 : bool readStaffDefs(pugi::xml_node parentNode);
97 : bool readStaffGrps(pugi::xml_node parentNode, int& staffSpan, int column, size_t& idx);
98 : bool readInstrDef(pugi::xml_node instrDefNode, engraving::Part* part);
99 : bool readSectionElements(pugi::xml_node parentNode);
100 : bool readEnding(pugi::xml_node endingNode);
101 : bool readMeasure(pugi::xml_node measureNode);
102 : bool readPb(pugi::xml_node pbNode);
103 : bool readSb(pugi::xml_node sbNode);
104 : bool readStaves(pugi::xml_node parentNode, engraving::Measure* measure, engraving::Fraction& measureTicks);
105 : bool readLayers(pugi::xml_node parentNode, engraving::Measure* measure, int staffIdx, engraving::Fraction& measureTicks);
106 :
107 : /**
108 : * Methods for parsing MEI elements within a <layer>
109 : */
110 : bool readElements(pugi::xml_node parentNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
111 : bool readArtics(pugi::xml_node parentNode, engraving::Chord* chord);
112 : bool readArtic(pugi::xml_node articNode, engraving::Chord* chord);
113 : bool readArtic(pugi::xml_node articNode, engraving::Note* note);
114 : bool readBeam(pugi::xml_node beamNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
115 : bool readBTrem(pugi::xml_node bTremNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
116 : bool readClef(pugi::xml_node clefNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
117 : bool readChord(pugi::xml_node chordNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
118 : bool readFTrem(pugi::xml_node fTremNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
119 : bool readGraceGrp(pugi::xml_node graceGrpNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
120 : bool readMRest(pugi::xml_node mRestNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
121 : bool readMRpt(pugi::xml_node mRptNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
122 : bool readNote(pugi::xml_node noteNode, engraving::Measure* measure, int track, engraving::Fraction& ticks,
123 : engraving::Chord* chord = nullptr);
124 : bool readRest(pugi::xml_node restNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
125 : bool readSpace(pugi::xml_node spaceNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
126 : bool readSyl(pugi::xml_node sylNode, engraving::Lyrics* lyrics, Convert::textWithSmufl& textBlocks, ElisionType elision);
127 : bool readTuplet(pugi::xml_node tupletNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
128 : bool readVerses(pugi::xml_node parentNode, engraving::Chord* chord);
129 : bool readVerse(pugi::xml_node verseNode, engraving::Chord* chord);
130 :
131 : /**
132 : * Methods for parsing MEI control events (within <measure>)
133 : */
134 : bool readControlEvents(pugi::xml_node parentNode, engraving::Measure* measure);
135 : bool readArpeg(pugi::xml_node arpegNode, engraving::Measure* measure);
136 : bool readBreath(pugi::xml_node breathNode, engraving::Measure* measure);
137 : bool readCaesura(pugi::xml_node caesuraNode, engraving::Measure* measure);
138 : bool readDir(pugi::xml_node dirNote, engraving::Measure* measure);
139 : bool readDynam(pugi::xml_node dynamNode, engraving::Measure* measure);
140 : bool readF(pugi::xml_node fNode, engraving::FiguredBass* figuredBass);
141 : bool readFb(pugi::xml_node harmNode, engraving::Measure* measure);
142 : bool readFermata(pugi::xml_node fermataNode, engraving::Measure* measure);
143 : bool readFing(pugi::xml_node fingNode, engraving::Measure* measure);
144 : bool readGliss(pugi::xml_node glissNode, engraving::Measure* measure);
145 : bool readHairpin(pugi::xml_node hairpinNode, engraving::Measure* measure);
146 : bool readHarm(pugi::xml_node harmNode, engraving::Measure* measure);
147 : bool readHarpPedal(pugi::xml_node harpPedalNode, engraving::Measure* measure);
148 : bool readLv(pugi::xml_node lvNode, engraving::Measure* measure);
149 : bool readMordent(pugi::xml_node mordentNode, engraving::Measure* measure);
150 : bool readOctave(pugi::xml_node octaveNode, engraving::Measure* measure);
151 : bool readOrnam(pugi::xml_node ornamNode, engraving::Measure* measure);
152 : bool readPedal(pugi::xml_node pedalNode, engraving::Measure* measure);
153 : bool readReh(pugi::xml_node rehNode, engraving::Measure* measure);
154 : bool readRepeatMark(pugi::xml_node repeatMarkNode, engraving::Measure* measure);
155 : bool readSlur(pugi::xml_node slurNode, engraving::Measure* measure);
156 : bool readTempo(pugi::xml_node tempoNode, engraving::Measure* measure);
157 : bool readTie(pugi::xml_node tieNode, engraving::Measure* measure);
158 : bool readTrill(pugi::xml_node trillNode, engraving::Measure* measure);
159 : bool readTurn(pugi::xml_node turnNode, engraving::Measure* measure);
160 :
161 : /**
162 : * Methods for parsing specific MEI attribute classes within elements
163 : */
164 : bool readGracedAtt(libmei::AttGraced& gracedAtt);
165 : bool readStemsAtt(engraving::Chord* chord, libmei::AttStems& stemsAtt);
166 :
167 : /**
168 : * Methods for extracting content from the MEI
169 : */
170 : bool buildIdMap(pugi::xml_node scoreNode);
171 : bool buildStaffLayerMap(pugi::xml_node root);
172 : bool buildTextFrame();
173 : bool buildScoreParts(pugi::xml_node scoreDefNode);
174 :
175 : /**
176 : * Helper methods for content creation
177 : */
178 : void addEndBarLineToMeasure(engraving::Measure* measure, engraving::BarLineType barLineType);
179 : void addLayoutBreakToMeasure(engraving::Measure* measure, engraving::LayoutBreakType layoutBreakType);
180 : void addTextToTitleFrame(engraving::VBox*& vBox, const muse::String& str, engraving::TextStyleType textStyleType);
181 : void addSpannerEnds();
182 :
183 : /**
184 : * Helper methods
185 : */
186 : int getStaffIndex(int staffN);
187 : int getVoiceIndex(int staffIdx, int layerN);
188 : void addLog(const std::string& msg, pugi::xml_node node);
189 : bool isNode(pugi::xml_node node, const muse::String& name);
190 : engraving::ChordRest* addChordRest(pugi::xml_node node, engraving::Measure* measure, int track, const libmei::Element& meiElement,
191 : engraving::Fraction& ticks, bool isRest);
192 : bool addGraceNotesToChord(engraving::ChordRest* chordRest, bool isAfter = false);
193 : engraving::EngravingItem* addAnnotation(const libmei::Element& meiElement, engraving::Measure* measure);
194 : engraving::Spanner* addSpanner(const libmei::Element& meiElement, engraving::Measure* measure, pugi::xml_node node);
195 : engraving::EngravingItem* addToChordRest(const libmei::Element& meiElement, engraving::Measure* measure,
196 : engraving::Chord* chord = nullptr);
197 : std::string xmlIdFrom(std::string dataURI);
198 : ControlElementPosition findStart(const libmei::Element& meiElement, engraving::Measure* measure);
199 : ControlElementPosition findEnd(pugi::xml_node controlNode, engraving::Spanner* spanner);
200 : engraving::Note* findStartNote(const libmei::Element& meiElement);
201 : engraving::Note* findEndNote(pugi::xml_node controlNode);
202 : const std::vector<engraving::ChordRest*> findPlistChordRests(pugi::xml_node controlNode);
203 : void clearGraceNotes();
204 : bool hasLyricsToExtend(engraving::track_idx_t track, int no);
205 : const std::pair<engraving::Lyrics*, engraving::ChordRest*>& getLyricsToExtend(engraving::track_idx_t track, int no);
206 : void addChordtoLyricsToExtend(engraving::ChordRest* chordRest);
207 : void extendLyrics(const std::pair<engraving::Lyrics*, engraving::ChordRest*>& lyricsToExtend);
208 : void extendLyrics();
209 : void setOrnamentAccid(engraving::Ornament* ornament, const Convert::OrnamStruct& ornamSt);
210 :
211 : /** Read the xmlId and process it appropriately */
212 : void readXmlId(engraving::EngravingItem* item, const std::string& meiUID);
213 :
214 : /** The Score pointer */
215 : engraving::Score* m_score = nullptr;
216 :
217 : /** The uid register */
218 : UIDRegister* m_uids;
219 :
220 : /** A flag indicating the file has MuseScore EIDs as xml:ids */
221 : bool m_hasMuseScoreIds;
222 :
223 : engraving::Fraction m_ticks;
224 : int m_lastMeasureN;
225 : engraving::Measure* m_lastMeasure;
226 :
227 : /** map of MuseScore indexes and clef, timesig and keysig */
228 : std::map<int, engraving::ClefTypeList> m_clefs;
229 : std::map<int, std::pair<engraving::Fraction, engraving::TimeSigType> > m_timeSigs;
230 : std::map<int, engraving::Key> m_keySigs;
231 : /** the current time signature */
232 : engraving::Fraction m_currentTimeSig = engraving::Fraction(4, 4);
233 :
234 : /* Set for mapping between MEI staff@n and MuseScore staff indexes */
235 : std::set<int> m_staffNs;
236 : /* A map of sets for mapping between MEI layer@ in MuseScore voice indexes */
237 : std::map<int, std::set<int> > m_staffLayerNs;
238 : /* A map for original staffN and MuseScore parts */
239 : std::map<int, engraving::Part*> m_staffParts;
240 :
241 : /* A map for startId and corresponding engraving::ChordRest */
242 : std::map<std::string, engraving::ChordRest*> m_startIdChordRests;
243 : /* A map for endId and corresponding engraving::ChordRest */
244 : std::map<std::string, engraving::ChordRest*> m_endIdChordRests;
245 : /* A map for startId and corresponding engraving::Note */
246 : std::map<std::string, engraving::Note*> m_startIdNotes;
247 : /* A map for endId and corresponding engraving::Note */
248 : std::map<std::string, engraving::Note*> m_endIdNotes;
249 : /* A map for plist values and corresponding engraving::ChordRest */
250 : std::map<std::string, engraving::ChordRest*> m_plistValueChordRests;
251 : /* A map for open spanners that needs to be ended */
252 : std::map<engraving::Spanner*, pugi::xml_node> m_openSpannerMap;
253 : /* A map for open arpeg that needs to be spanned */
254 : std::map<engraving::Arpeggio*, pugi::xml_node> m_openArpegMap;
255 :
256 : /** A map of a map for lyrics with extender that needs to be extended */
257 : std::map<engraving::track_idx_t, std::map<int, std::pair<engraving::Lyrics*, engraving::ChordRest*> > > m_lyricExtenders;
258 :
259 : engraving::Tuplet* m_tuplet;
260 : engraving::BeamMode m_beamBeginMode;
261 : engraving::BeamMode m_graceBeamBeginMode;
262 : engraving::Chord* m_lastChord;
263 : std::string m_tremoloId;
264 : engraving::TremoloType m_tremoloType;
265 :
266 : std::list<engraving::Chord*> m_graceNotes;
267 : GraceReading m_readingGraceNotes;
268 : engraving::NoteType m_graceNoteType;
269 :
270 : bool m_readingEnding;
271 : engraving::Measure* m_endingStart;
272 : engraving::Measure* m_endingEnd;
273 : };
274 : } // namespace
|