Line data Source code
1 : #include "gp7dombuilder.h"
2 :
3 : #include <vector>
4 :
5 : #include "global/log.h"
6 :
7 : using namespace muse;
8 :
9 : namespace mu::iex::guitarpro {
10 157 : std::pair<int, std::unique_ptr<GPTrack> > GP7DomBuilder::createGPTrack(XmlDomNode* trackNode, XmlDomNode* versionNode)
11 : {
12 : static const std::set<String> sUnused = {
13 : u"Color", u"SystemsDefautLayout", u"SystemsLayout", u"AutoBrush",
14 : u"PalmMute", u"AutoAccentuation", u"PlayingStyle",
15 : u"UseOneChannelPerString", u"IconId", u"InstrumentSet",
16 : u"ForcedSound", u"PlaybackState", u"AudioEngineState",
17 : u"Automations"
18 157 : };
19 :
20 157 : int trackIdx = trackNode->toElement().attribute("id").value().toInt();
21 157 : auto track = std::make_unique<GPTrack>(trackIdx);
22 157 : XmlDomNode trackChildNode = trackNode->firstChild();
23 157 : String version = versionNode->toElement().text();
24 :
25 3350 : while (!trackChildNode.isNull()) {
26 3193 : String nodeName = trackChildNode.nodeName();
27 3193 : if (nodeName == u"Name") {
28 157 : track->setName(trackChildNode.toElement().text());
29 3036 : } else if (nodeName == u"RSE") {
30 156 : GPTrack::RSE rse = readTrackRSE(&trackChildNode);
31 156 : track->setRSE(rse);
32 2880 : } else if (nodeName == u"MidiConnection") {
33 157 : int midiChannel = readMidiChannel(&trackChildNode);
34 157 : track->setMidiChannel(midiChannel);
35 2723 : } else if (nodeName == u"ShortName") {
36 157 : track->setShortName(trackChildNode.toElement().text());
37 2566 : } else if (nodeName == u"Sounds") {
38 157 : int programm = readMidiProgramm(&trackChildNode);
39 157 : auto soundNode = trackChildNode.firstChild();
40 317 : while (!soundNode.isNull()) {
41 160 : GPTrack::Sound sound = readSounds(&soundNode);
42 160 : track->addSound(sound);
43 :
44 160 : soundNode = soundNode.nextSibling();
45 160 : }
46 157 : track->setProgramm(programm);
47 2566 : } else if (nodeName == u"Staves") {
48 157 : auto staffNode = trackChildNode.firstChild();
49 157 : int staffCount = 0;
50 316 : while (!staffNode.isNull()) {
51 159 : auto propertyNode = staffNode.firstChild();
52 : // there is a bug in gp v 7.0.0
53 : // All parts marked to use flat for tuning string,
54 : // but in real world gp uses tuning presets
55 : // so we have to ignore <Flats/> and <TuningFlat> props
56 159 : readTrackProperties(&propertyNode, track.get(), version == "7");
57 159 : staffNode = staffNode.nextSibling();
58 159 : staffCount++;
59 159 : }
60 157 : track->setStaffCount(staffCount);
61 2409 : } else if (nodeName == u"NotationPatch") {
62 3 : auto innerNode = trackChildNode.firstChildElement("LineCount");
63 3 : if (!innerNode.isNull()) {
64 3 : track->setLineCount(innerNode.toElement().text().toInt());
65 : }
66 2252 : } else if (nodeName == u"Transpose") {
67 157 : auto octaveNode = trackChildNode.firstChildElement("Octave");
68 157 : int octave = octaveNode.toElement().text().toInt();
69 157 : auto chromaticNode = trackChildNode.firstChildElement("Chromatic");
70 157 : int chromatic = chromaticNode.toElement().text().toInt();
71 157 : int transpose = 12 * octave + chromatic;
72 157 : track->setTranspose(transpose);
73 2249 : } else if (nodeName == u"Lyrics") {
74 156 : readLyrics(trackChildNode, track.get());
75 1936 : } else if (nodeName == u"Automations") {
76 115 : auto automationNode = trackChildNode.firstChild();
77 238 : while (!automationNode.isNull()) {
78 123 : GPTrack::SoundAutomation automation = readTrackAutomation(&automationNode);
79 123 : if (!automation.type.isEmpty()) {
80 123 : track->addSoundAutomation(automation);
81 : }
82 123 : automationNode = automationNode.nextSibling();
83 123 : }
84 1936 : } else if (sUnused.find(nodeName) != sUnused.end()) {
85 : // Ignored nodes
86 : }
87 :
88 3193 : trackChildNode = trackChildNode.nextSibling();
89 3193 : }
90 :
91 314 : return std::make_pair(trackIdx, std::move(track));
92 157 : }
93 :
94 157 : int GP7DomBuilder::readMidiChannel(XmlDomNode* trackChildNode) const
95 : {
96 : int channel
97 314 : =trackChildNode->firstChildElement("PrimaryChannel")
98 157 : .text().toInt();
99 :
100 157 : return channel;
101 : }
102 :
103 157 : int GP7DomBuilder::readMidiProgramm(XmlDomNode* trackChildNode) const
104 : {
105 314 : int programm = trackChildNode->firstChild()
106 314 : .firstChildElement("MIDI")
107 314 : .firstChildElement("Program")
108 157 : .text().toInt();
109 :
110 157 : return programm;
111 : }
112 :
113 160 : GPTrack::Sound GP7DomBuilder::readSounds(XmlDomNode* soundNode) const
114 : {
115 160 : GPTrack::Sound result;
116 :
117 320 : result.programm = soundNode->firstChildElement("MIDI")
118 320 : .firstChildElement("Program")
119 160 : .text().toInt();
120 160 : result.name = soundNode->firstChildElement("Name").text();
121 160 : result.label = soundNode->firstChildElement("Label").text();
122 160 : result.path = soundNode->firstChildElement("Path").text();
123 160 : result.role = soundNode->firstChildElement("Role").text();
124 :
125 160 : return result;
126 0 : }
127 :
128 123 : GPTrack::SoundAutomation GP7DomBuilder::readTrackAutomation(XmlDomNode* automationNode) const
129 : {
130 123 : GPTrack::SoundAutomation result;
131 :
132 123 : String type = automationNode->firstChildElement("Type").text();
133 123 : if (type != u"Sound") {
134 0 : return result;
135 : }
136 :
137 123 : result.type = type;
138 123 : result.linear = automationNode->firstChildElement("Linear").text() == u"true";
139 123 : result.bar = automationNode->firstChildElement("Bar").text().toInt();
140 123 : result.value = automationNode->firstChildElement("Value").text();
141 123 : result.position = automationNode->firstChildElement("Position").text().toFloat();
142 :
143 123 : return result;
144 123 : }
145 : } // namespace mu::iex::guitarpro
|