1 #include "importptb.h"
2 #include "assert.h"
3 
4 #include <libmscore/part.h>
5 #include <libmscore/staff.h>
6 #include <libmscore/measure.h>
7 #include <libmscore/symbol.h>
8 #include <libmscore/tie.h>
9 #include <libmscore/bend.h>
10 #include <libmscore/timesig.h>
11 #include <libmscore/sym.h>
12 #include <libmscore/articulation.h>
13 #include <libmscore/tuplet.h>
14 #include <libmscore/instrument.h>
15 #include <libmscore/clef.h>
16 #include <libmscore/rest.h>
17 #include <libmscore/stafftext.h>
18 #include <libmscore/chord.h>
19 #include <libmscore/tempotext.h>
20 #include <libmscore/excerpt.h>
21 #include <libmscore/rehearsalmark.h>
22 #include <libmscore/bracketItem.h>
23 #include <libmscore/box.h>
24 #include <libmscore/palmmute.h>
25 
26 namespace Ms {
27 
readBoolean()28 bool PowerTab::readBoolean()
29       {
30       return readUChar() != 0;
31       }
32 
readUChar()33 unsigned char PowerTab::readUChar()
34       {
35       unsigned char byte;
36       _file->read((char*)&byte, 1);
37       return byte;
38       }
39 
readShort()40 unsigned short PowerTab::readShort()
41       {
42       uint16_t val;
43       _file->read((char*)&val, 2);
44       return val;
45       }
46 
readChar()47 char PowerTab::readChar()
48       {
49       char byte;
50       _file->read(&byte, 1);
51       return byte;
52       }
53 
54 
readInt()55 int PowerTab::readInt()
56       {
57       int32_t val;
58       _file->read((char*)&val, 4);
59       return val;
60       }
61 
readString(int length)62 std::string PowerTab::readString(int length)
63       {
64       if (length == -1) {
65             length = readUChar();
66             if (length == 0xFF)
67                   length = readShort();
68             }
69       char* p = new char[length];
70       _file->read(p, length);
71 
72       std::string s(p, length);
73       delete[] p;
74       return s;
75       }
76 
readVersion()77 bool PowerTab::readVersion()
78       {
79       std::string version = readString(4);
80       version += std::string("-") + std::to_string(readShort());
81       return version == "ptab-4";
82       }
83 
skip(int len)84 void PowerTab::skip(int len /* = 1 */)
85       {
86       for (int i = 0; i < len; ++i)
87             readChar();
88       }
89 
readSongInfo(ptSongInfo & info)90 void PowerTab::readSongInfo(ptSongInfo& info)
91       {
92       auto classification = readChar();
93       info.classification = classification;
94       if (classification == 0) {
95             skip(1);
96             info.name = readString();
97             info.interpret = readString();
98 
99             auto releaseType = readChar();
100 
101             switch (releaseType) {
102                   case 0: {
103                         /*auto albumType =*/ readChar();
104                         info.album = readString();
105                         info.year = readShort();
106                         info.liverecording = readChar() != 0;
107                         break;
108                         }
109                   case 1: {
110                         info.album = readString();
111                         info.liverecording = readChar() != 0;
112                         break;
113                         }
114                   case 2: {
115                         info.album  = readString();
116                         info.day    = readShort();
117                         info.month  = readShort();
118                         info.year   = readShort();
119                         break;
120                         }
121                   default:
122                         assert(0);
123                   }
124 
125             if (readChar() == 0) {
126                   info.author = readString();
127                   info.lyricist = readString();
128                   }
129 
130             info.arrenger           = readString();
131             info.guitarTranscriber  = readString();
132             info.bassTranscriber    = readString();
133             info.copyright          = readString();
134 
135             info.lyrics             = readString();
136 
137             info.guitarInstructions = readString();
138             info.bassInstructions   = readString();
139 
140             }
141       else if (classification == 1) {
142             info.name         = readString();
143             info.album        = readString();
144             info.style        = readShort();
145             info.level        = readUChar();
146             info.author       = readString();
147             info.instructions = readString();
148             info.copyright    = readString();
149             }
150       }
151 
readHeaderItems()152 int PowerTab::readHeaderItems()
153       {
154       int itemCount = readShort();
155       if (itemCount != 0) {
156             int header = readShort();
157             if (header == 0xFFFF) {
158                   if (readShort() != 1) {
159                         return -1;
160                         }
161                   auto str = readString(readShort()); //section title
162                   }
163             }
164       return itemCount;
165       }
166 
readTrackInfo(ptTrack & info)167 void PowerTab::readTrackInfo(ptTrack& info)
168       {
169       TrackInfo tr;
170 
171       tr.number = readUChar();
172       tr.name = readString();
173       tr.instrument = readUChar();
174       tr.volume = readUChar();
175       tr.balance = readUChar();
176       tr.reverb = readUChar();
177       tr.chorus = readUChar();
178       tr.tremolo = readUChar();
179       tr.phaser = readUChar();
180       tr.capo = readUChar();
181       tr.tuningName = readString();
182       tr.offset = readUChar();
183 
184       int ln = readUChar();
185       for (int i = 0; i < ln; ++i)
186             tr.strings.push_back(readUChar());
187       info.infos.push_back(tr);
188       }
189 
readChord(ptTrack & info)190 void PowerTab::readChord(ptTrack& info)
191       {
192       ptChord ch;
193       ch.key = readShort(); //chord key
194       ch.formula = readUChar();
195       ch.modification = readShort(); //Chord Modification
196       ch.extra = readUChar();
197       ch.top_fret = readUChar();
198       auto stringCount = readUChar();
199       for (int i = 0; i < stringCount; ++i) {
200             ch.frets.push_back(readUChar()); // fret
201             }
202       if (info.diagramMap.find({ {ch.key, ch.formula, ch.modification} }) == info.diagramMap.end())
203             info.diagramMap[ { {ch.key, ch.formula, ch.modification} }] = ch;
204       else {
205             auto a1 = info.diagramMap[ { {ch.key, ch.formula, ch.modification} }];
206             auto a2 = ch;
207 
208 //??            int k = 1;
209             }
210       }
211 
readFontSettings()212 void PowerTab::readFontSettings()
213       {
214       readString(); //font name
215       readInt(); // point size
216       readInt(); // weight
217       readBoolean(); //italic
218       readBoolean(); //underline
219       readBoolean(); //strikeout
220       readInt(); //color
221       }
222 
readFloatingText()223 void PowerTab::readFloatingText()
224       {
225       readString(); //text
226       //rect :
227       readInt(); // left
228       readInt(); // top
229       readInt(); // right
230       readInt(); // bottom
231 
232       readUChar();
233       readFontSettings();
234       }
235 
readDynamic()236 void PowerTab::readDynamic()
237       {
238       readShort();
239       readUChar();
240       readUChar();
241       readShort();
242       }
243 
readKeySignature()244 void PowerTab::readKeySignature()
245       {
246       readUChar();
247       }
248 
readRehearsalSign(ptSection & sec)249 void PowerTab::readRehearsalSign(ptSection& sec)
250       {
251       auto c = readChar();
252       auto str = readString();
253       if (str.size()) {
254             sec.partName = str;
255             sec.partMarker = c;
256             }
257       }
258 
readChordText(ptSection & sec)259 void PowerTab::readChordText(ptSection& sec)
260       {
261       ptChordText cht;
262       cht.position = readUChar();
263       cht.key = readShort();
264       cht.formula = readUChar();
265       cht.formula_mod = readShort();
266       cht.extra = readUChar();
267       //sec.chordTextMap.push_back(cht);
268       sec.chordTextMap.insert({ cht.position, cht });
269       }
270 
readRhytmSlash(ptSection & sec)271 void PowerTab::readRhytmSlash(ptSection& sec)
272       {
273       stRhytmSlash rs;
274       rs.position = readUChar();
275       auto beaming = readUChar();
276       auto data = readInt();
277       auto duration = (data & 0xE00000) >> 21;
278       switch (duration) {
279             case 0:
280                   rs.duration = 1;
281                   break;
282             case 1:
283                   rs.duration = 2;
284                   break;
285             case 2:
286                   rs.duration = 4;
287                   break;
288             case 3:
289                   rs.duration = 8;
290                   break;
291             case 4:
292                   rs.duration = 16;
293             }
294 
295       rs.triplet = beaming & (0x20 | 0x40);
296       rs.tripletend = beaming & 0x80;
297 
298       rs.dotted = data & 0x01;
299       rs.doubleDotted = data & 0x02;
300 
301       rs.is_rest = data & 0x04;
302 
303       sec.rhytm.emplace_back(rs);
304       }
305 
readGuitarIn(ptTrack & info)306 void PowerTab::readGuitarIn(ptTrack& info)
307       {
308       ptGuitarIn gin;
309       gin.section = readShort();
310       gin.staff = readUChar() + staffInc;
311       gin.position = readUChar();
312       gin.rhytmSlash = readUChar();
313       gin.trackinfo = readUChar();
314       info.guitar_ins.push_back(gin);
315       //info.getSection(section).getPosition(position).addComponent(new ptGuitarIn(staff, inf));
316       }
317 
readTempoMarker(ptTrack & info)318 void PowerTab::readTempoMarker(ptTrack& info)
319       {
320       auto section = readShort();
321       /*auto position =*/ readUChar();
322       auto tempo = readShort();
323       /*auto data =*/ readShort();
324       readString(); //description
325 
326 #if 0 // TODO-ws
327       int tripletFeel = 0;
328       if (data & 0x01) {
329             tripletFeel = 8;
330             }
331       else if (data & 0x02) {
332             tripletFeel = 16;
333             }
334 #endif
335       if (tempo > 0) {
336             info.getSection(section).tempo = tempo;//.getPosition(position).addComponent(new ptTempo(tempo));
337             }
338       }
339 
readSectionSymbol(ptTrack & info)340 void PowerTab::readSectionSymbol(ptTrack& info)
341       {
342       int section = readShort();
343       int position = readUChar();
344       int data = readInt();
345 
346       int endNumber = data >> 16;
347       info.getSection(section).getPosition(position).addComponent(new ptSymbol(endNumber));
348       }
349 
readTimeSignature(ptBar * bar)350 void PowerTab::readTimeSignature(ptBar* bar)
351       {
352       skip(3);
353       int data = readUChar();
354       readUChar(); // measure pulses
355 
356       bar->numerator = ((data - (data % 8)) / 8) + 1;
357       bar->denominator = pow(2, data % 8);
358       }
359 
readBarLine(ptSection & sec)360 void PowerTab::readBarLine(ptSection& sec)
361       {
362       auto bar = new ptBar();
363       /*int position =*/ readUChar();
364       auto b_type = readUChar();
365 
366       bar->repeatStart = (b_type >> 5) == 3;
367       bar->repeatClose = (b_type >> 5) == 4 ? b_type - 128 : 0;
368 
369       bar->measureNo = sec.number;
370 
371       readKeySignature();
372       readTimeSignature(bar);
373       readRehearsalSign(sec);
374       //sec.getPosition(position).addComponent(bar);
375       sec.bars.push_back(std::shared_ptr<ptBar>(bar));
376       /*if (bars.empty() || ( bars.back()->measureNo < bar->measureNo ))
377             bars.push_back(bar);*/
378       }
379 
readStaff(int staff,ptSection & sec)380 void PowerTab::readStaff(int staff, ptSection& sec)
381       {
382       skip(5);
383       for (int voice = 0; voice < 2; ++voice) {
384             int itemCount = readHeaderItems();
385             for (int i = 0; i < itemCount; ++i) {
386                   readPosition(staff, voice, sec);
387                   if (i < itemCount - 1) {
388                         readShort();
389                         }
390                   }
391             }
392       }
393 
readNote(ptBeat * beat)394 void PowerTab::readNote(ptBeat* beat)
395       {
396       ptNote note;
397       auto position = readUChar();
398       auto simpleData = readShort();
399       auto symboCount = readUChar();
400       for (int i = 0; i < symboCount; ++i) {
401             skip(2);
402             auto data3 = readUChar();
403             auto data4 = readUChar();
404             note.bend = data4 == 101 ? data3 / 16 + 1 : 0;
405             note.slide = data4 == 100 ? data3 + 1 : 0;
406             }
407       note.value = position & 0x1F;
408       note.str = ((position & 0xE0) >> 5);
409       note.tied = simpleData & 0x01;
410       note.dead = simpleData & 0x02;
411       note.hammer = simpleData & 0x08;
412       beat->notes.emplace_back(note);
413       }
414 
readPosition(int staff,int voice,ptSection & sec)415 void PowerTab::readPosition(int staff, int voice, ptSection& sec)
416       {
417       auto position = readUChar();
418 
419       ptBeat* beat{ nullptr };
420       bool add = false;
421       if (voice == 0 || sec.beats[staff].empty()) {
422             beat = new ptBeat(staff, voice);
423             beat->position = position;
424             add = true;
425             }
426       else {
427             auto pos = sec.beats[staff].begin();
428             auto end = sec.beats[staff].end();
429             while (pos != end && pos->get()->position < position) {
430                   ++pos;
431                   }
432             if (pos == end) {
433                   beat = new ptBeat(staff, voice);
434                   beat->position = position;
435                   add = true;
436                   }
437             else if (pos->get()->position == position) {
438                   beat = pos->get();
439                   }
440             else {
441                   beat = new ptBeat(staff, voice);
442                   beat->position = position;
443                   sec.beats[staff].insert(pos, std::shared_ptr<ptBeat>(beat));
444                   }
445             }
446       auto beaming = readUChar();
447       beaming = (((int)beaming - 128 < 0) ? beaming : beaming - 128);
448 
449       readUChar();
450 
451       auto data1 = readUChar();
452       auto data2 = readUChar(); //32 - palm mute, 4 - accent, 2 - staccato
453       auto data3 = readUChar();
454       auto durationValue = readUChar();
455 
456       int multiBarRest = 1;
457       auto complexCount = readUChar();
458       for (int i = 0; i < complexCount; ++i) {
459             auto count = readShort();
460             readUChar();
461             auto type = readUChar();
462             if (type & 0x08) {
463                   multiBarRest = count;
464                   }
465             }
466 
467       auto itemCount = readHeaderItems();
468       for (int i = 0; i < itemCount; ++i) {
469             readNote(beat);
470             if ( i < itemCount - 1) {
471                   readShort();
472                   }
473             }
474       curTrack->infos[staff].notes_count += itemCount;
475       beat->mmrest = (itemCount == 0) ? multiBarRest : 1;
476       beat->vibrato = (( (data1 & 0x08) != 0) || ( (data1 & 0x10) != 0 ));
477       beat->grace = (data3 & 0x01) != 0;
478       beat->tuplet = (data3 & 0x20) != 0;
479 
480       if (beat->duration != 0) {
481             durationValue = std::max((int)durationValue, beat->duration);
482             }
483 
484       beat->duration = durationValue;//beat->duration == 0 ? durationValue : std::min(beat->duration, (int)durationValue);
485       beat->dotted = (data1 & 0x01);
486       beat->doubleDotted = (data1 & 0x02);
487       beat->arpegioUp = (data1 & 0x20);
488       beat->arpegioDown = (data1 & 0x40);
489       beat->enters = ((beaming - (beaming % 8)) / 8) + 1;
490       beat->times = (beaming % 8) + 1;
491       beat->isRest = (data1 & 0x04);
492       beat->palmMute = data2 & 0x20;
493       beat->accent = data2 & 0x04;
494       beat->staccato = data2 & 0x02;
495 
496       for (int i = int(sec.beats.size()); i < staff + 1; ++i) {
497             sec.beats.push_back({});
498             }
499       if (add) {
500             sec.beats[staff].push_back(std::shared_ptr<ptBeat>(beat));
501             }
502       //sec.getPosition(position).addComponent(beat);
503       }
504 
getStaffMap(ptSection & sec)505 std::vector<int> PowerTab::getStaffMap(ptSection& sec)
506       {
507       std::vector<int> result;
508       std::vector<int> slash;
509       if (!staffInc && curTrack->guitar_ins.size()) {
510             auto first = curTrack->guitar_ins.front();
511             while (first.section == sec.number) {
512                   if (first.trackinfo) {
513                         for (unsigned int i = 0; i < curTrack->infos.size(); ++i) {
514                               if ((1 << i) & first.trackinfo) {
515                                     result.push_back(i);
516                                     }
517                               }
518                         }
519 
520                   if (first.rhytmSlash) {
521                         for (unsigned int i = 0; i < curTrack->infos.size(); ++i) {
522                               if ((i << 1) & first.rhytmSlash) {
523                                     slash.push_back(-1 - i);
524                                     }
525                               }
526                         }
527 
528                   curTrack->guitar_ins.pop_front();
529                   if (curTrack->guitar_ins.empty()) break;
530                   first = curTrack->guitar_ins.front();
531                   }
532             }
533 
534       if (result.empty() || int(result.size()) < sec.staves) {
535             result.clear();
536             if (int(lastStaffMap.size()) < sec.staves) {
537                   for (int i = 0; i < sec.staves; ++i) {
538                         result.push_back(i + staffInc);
539                         }
540                   }
541             else {
542                   result = lastStaffMap;
543                   }
544             }
545 
546       for (auto i : slash) {
547             result.push_back(i);
548             }
549 
550       lastStaffMap = result;
551       return result;
552       }
553 
554 //---------------------------------------------------------
555 //   addPalmMate
556 //---------------------------------------------------------
557 
addPalmMute(Chord * chord)558 void PowerTab::addPalmMute(Chord* chord)
559       {
560       int track = chord->track();
561 	while (int(_palmMutes.size()) < track + 1)
562 		_palmMutes.push_back(0);
563 
564 	if (_palmMutes[track]) {
565 		PalmMute* pm = _palmMutes[track];
566 		Chord* lastChord = toChord(pm->endCR());
567 		if (lastChord == chord)
568 			return;
569             //
570             // extend the current palm mute or start a new one
571             //
572             Fraction tick = chord->segment()->tick();
573 		if (pm->tick2() < tick)
574                   _palmMutes[track] = 0;
575             else {
576                   pm->setTick2(chord->tick() + chord->actualTicks());
577 			pm->setEndElement(chord);
578 		      }
579 
580 	      }
581 	if (!_palmMutes[track]) {
582 		PalmMute* pm = new PalmMute(score);
583 		_palmMutes[track] = pm;
584             Segment* segment = chord->segment();
585             Fraction tick = segment->tick();
586 
587 		pm->setTick(tick);
588 		pm->setTick2(tick + chord->actualTicks());
589 		pm->setTrack(track);
590 		pm->setTrack2(track);
591 		pm->setStartElement(chord);
592 		pm->setEndElement(chord);
593 		score->addElement(pm);
594 	      }
595       }
596 
fillMeasure(tBeatList & elist,Measure * measure,int staff,std::vector<Note * > & tiedNotes)597 void PowerTab::fillMeasure(tBeatList& elist, Measure* measure, int staff, std::vector<Note*>& tiedNotes)
598       {
599       Tuplet* tuple = nullptr;
600       int tupleBeatCounter{ 0 };
601       Fraction tick = measure->tick();
602       Fraction endtick = measure->endTick();
603       Chord*      hammer{ nullptr };
604 
605       while (elist.size() && tick < endtick) {
606             auto beat = elist.front().get();
607             auto segment = measure->getSegment(SegmentType::ChordRest, tick);
608             Fraction l(1, beat->duration);
609             int dots = beat->dotted ? (beat->doubleDotted ? 2 : 1) : (beat->doubleDotted ? 2 : 0);
610             switch (dots) {
611                   case 1:
612                         l = l + (l * Fraction(1,2));
613                         break;
614                   case 2:
615                         l = l + (l * Fraction(3,4));
616                         break;
617                   }
618 
619             TDuration d(l);
620             d.setDots(dots);
621 
622             if (beat->tuplet || tupleBeatCounter) {
623                   Fraction nt = (l * Fraction(1,3) * Fraction(2,1));
624                   tick += nt;
625                   }
626             else {
627                   tick += l;
628                   }
629             ChordRest* cr;
630             if (beat->notes.empty()) {
631                   auto rest = new Rest(score);
632                   cr = rest;
633                   rest->setTrack(staff * VOICES);
634                   rest->setTicks(l);
635                   rest->setDurationType(d);
636                   segment->add(rest);
637 
638                   }
639             else {
640                   Chord* chord = new Chord(score);
641                   cr = chord;
642                   chord->setTrack(staff * VOICES);
643                   chord->setTicks(l);
644                   chord->setDurationType(d);
645                   segment->add(chord);
646 
647                   if (beat->palmMute)
648                         addPalmMute(chord);
649                   if (beat->accent) {
650                         auto accent = new Articulation(score);
651                         accent->setSymId(SymId::articAccentAbove);
652                         chord->add(accent);
653                         }
654                   if (beat->staccato) {
655                         auto st = new Articulation(score);
656                         st->setSymId(SymId::articStaccatoAbove);
657                         chord->add(st);
658                         }
659                   bool has_hammer = false;
660                   for (const auto &n : beat->notes) {
661                         auto note = new Note(score);
662                         chord->add(note);
663                         if (n.dead) {
664                               note->setHeadGroup(NoteHead::Group::HEAD_CROSS);
665                               note->setGhost(true);
666                               }
667 
668                         if (n.hammer) {
669                               has_hammer = true;
670                               }
671 
672                         if (n.tied && tiedNotes[n.str]) {
673                               Tie* tie = new Tie(score);
674                               tie->setEndNote(note);
675                               tiedNotes[n.str]->add(tie);
676                               }
677 
678                         if (n.bend) {
679                               Bend* bend = new Bend(score);
680 //TODO-ws                              bend->setNote(note);
681                               bend->points().append(PitchValue(0, n.bend * 25 - 12));
682                               bend->points().append(PitchValue(50, 0));
683                               note->add(bend);
684                               }
685 
686                         if (false && n.slide) {
687                               Text* st = new Text(score, Tid::HARMONY_A);
688                               st->setXmlText(QString("SLIDE %1").arg(n.slide));
689                               st->setTrack(staff * VOICES);
690                               chord->notes().front()->add(st);
691                               }
692 
693                         tiedNotes[n.str] = note;
694                         note->setFret(n.value);
695                         note->setString(n.str);
696                         const StringData* sd = score->staff(staff)->part()->instrument()->stringData();
697                         int k     = int(curTrack->infos[staff].strings.size()) - n.str - 1;
698                         int pitch = sd->stringList().at(k).pitch + n.value; //getPitch(n.str, n.value, 0);
699                         note->setPitch(pitch);
700                         note->setTpcFromPitch();
701                         }
702 
703                   if (hammer) {
704                         auto cr1 = hammer;
705                         auto cr2 = chord;
706                         hammer = nullptr;
707 
708                         Slur* slur = new Slur(score);
709                         slur->setStartElement(cr1);
710                         slur->setEndElement(cr2);
711                         slur->setTick(cr1->tick());
712                         slur->setTick2(tick);
713                         slur->setTrack(staff * VOICES);
714                         slur->setTrack2(staff  * VOICES);
715                         score->addElement(slur);
716 
717                         Text* st = new Text(score, Tid::HARMONY_A);
718                         st->setXmlText("H");
719                         st->setTrack(staff * VOICES);
720                         cr1->notes().front()->add(st);
721                         }
722                   if (has_hammer) {
723                         hammer = chord;
724                         }
725                   }
726 
727             if (tupleBeatCounter && tuple) {
728                   tupleBeatCounter--;
729                   cr->setTuplet(tuple);
730                   tuple->add(cr);
731                   }
732 
733             if (beat->tuplet && !tuple) {
734                   tuple = new Tuplet(score);
735                   tuple->setParent(measure);
736                   tuple->setTrack(cr->track());
737                   tuple->setBaseLen(l);
738                   tuple->setRatio(Fraction(3, 2));
739                   tuple->setTicks(l * tuple->ratio().denominator());
740                   cr->setTuplet(tuple);
741                   tuple->add(cr);
742                   tupleBeatCounter = 2;
743                   }
744             elist.pop_front();
745             }
746 
747       if (tick == measure->tick()) {
748             auto rest = new Rest(score);
749             rest->setTrack(staff * VOICES);
750             auto ts = measure->timesig();
751             rest->setTicks(ts);
752             rest->setDurationType(TDuration(ts));
753             measure->getSegment(SegmentType::ChordRest, tick)->add(rest);
754             }
755 
756       }
757 
addToScore(ptSection & sec)758 void PowerTab::addToScore(ptSection& sec)
759       {
760       cur_section = &sec;
761       Fraction tick = score->lastMeasure() ? score->lastMeasure()->endTick() : Fraction(0,1);
762 
763       Fraction lastTS(-1, -1);
764       bool firstMeasure = true;
765       if (score->lastMeasure()) {
766             lastTS = score->lastMeasure()->timesig();
767             firstMeasure = false;
768             }
769       if (firstMeasure) {
770             //int lastStaff = sec.staffMap.back() + 1;
771             for (int i = 0; i < staves; ++i) {
772                   Part* part = new Part(score);
773                   Staff* s = new Staff(score);
774                   s->setPart(part);
775                   part->insertStaff(s, -1);
776                   auto info = &curTrack->infos[i];
777                   std::string ss = info->name;
778                   part->setPartName(QString::fromUtf8(ss.data(), int(ss.size())));
779                   part->setPlainLongName(QString::fromUtf8(ss.data(), int(ss.size())));
780 
781                   std::vector<int> reverseStr;
782                   for (auto it = info->strings.rbegin(); it != info->strings.rend(); ++it)
783                         reverseStr.push_back(*it);
784                   StringData stringData(32, int(info->strings.size()), reverseStr.data());
785                   part->instrument()->setStringData(stringData);
786 
787                   part->setMidiProgram(info->instrument);
788 
789                   score->staves().push_back(s);
790                   score->appendPart(part);
791                   }
792             }
793       auto bar1 = sec.bars.front();
794       while (bar1->denominator == 0) {
795             if (sec.bars.size() == 1)
796                   break;
797             sec.bars.pop_front();
798             bar1 = sec.bars.front();
799             }
800       if (bar1->denominator == 0) {
801             bar1->denominator = 4;
802             bar1->numerator = 4;
803             }
804       auto measure = createMeasure(bar1.get(), tick);
805       if (repeatCount) {
806             measure->setRepeatEnd(true);
807             measure->setRepeatCount(repeatCount);
808             }
809       repeatCount = bar1->repeatClose;
810       if (bar1->repeatStart) {
811             measure->setRepeatStart(true);
812             }
813       if (sec.bars.size() > 1) {
814             sec.bars.pop_front();
815             }
816       if (sec.tempo) {
817             TempoText* tt = new TempoText(score);
818             tt->setTempo(double(sec.tempo) / 60.0f);
819             tt->setXmlText(QString("<sym>metNoteQuarterUp</sym> = %1").arg(sec.tempo));
820             tt->setTrack(0);
821             Segment* segment = measure->getSegment(SegmentType::ChordRest, measure->tick());
822             segment->add(tt);
823             score->setTempo(measure->tick(), tt->tempo());
824             }
825       if (!sec.partName.empty() && lastPart != sec.partMarker) {
826             lastPart = sec.partMarker;
827             RehearsalMark* t = new RehearsalMark(score);
828             t->setFrameType(FrameType::SQUARE);
829             t->setPlainText(QString(sec.partMarker));
830             t->setTrack(0);
831             auto seg = measure->getSegment(SegmentType::ChordRest, measure->tick());
832             seg->add(t);
833 
834             t = new RehearsalMark(score);
835             t->setFrameType(FrameType::NO_FRAME);
836             t->setPlainText(QString::fromUtf8(sec.partName.data(), int(sec.partName.size())));
837             t->setOffset(QPointF(10.0, 0.0));
838             t->setTrack(0);
839             seg->add(t);
840             }
841       if (firstMeasure) {
842             for (int staffIdx = 0; staffIdx < staves; ++staffIdx) {
843                   int keysig = staffIdx >= staffInc ? 0 : 1; // Can be parsed int beat section
844                   KeySig* t = new KeySig(score);
845                   t->setKey(Key(keysig));
846                   t->setTrack(staffIdx * VOICES);
847                   Segment* s = measure->getSegment(SegmentType::KeySig, tick);
848                   s->add(t);
849 
850                   ClefType clefId = staffIdx >= staffInc ? ClefType::F8_VB : ClefType::G15_MB;
851                   auto clef = new Clef(score);
852                   clef->setTrack(staffIdx * VOICES);
853                   clef->setClefType(clefId);
854                   s = measure->getSegment(SegmentType::HeaderClef, Fraction(0,1));
855                   s->add(clef);
856                   }
857 
858             }
859 
860       std::vector<std::vector<Note*>> tiedNotes(staves);
861       for (auto& nvec : tiedNotes) {
862             nvec.resize(10);
863             memset(nvec.data(), 0, sizeof(Note*) * 10);
864             }
865       //std::vector<tBeatList>
866       while (true) {
867             bool empty = true;
868             while (int(sec.beats.size()) < staves) {
869                   sec.beats.push_back({});
870                   }
871             for (unsigned int i = 0; i < sec.beats.size(); ++i) {
872                   fillMeasure(sec.beats[i], measure, i, tiedNotes[i]);
873                   if (sec.beats[i].size() && i < unsigned(staffInc))
874                         empty = false;
875                   }
876             if (lastTS != measure->timesig()) {
877                   lastTS = measure->timesig();
878                   for (int staffIdx = 0; staffIdx < staves; ++staffIdx) {
879                         Staff* staff = score->staff(staffIdx);
880                         auto staffType = staff->staffType(Fraction(0,1));
881                         if (staffType->genTimesig()) {
882                               auto t = new TimeSig(score);
883                               t->setTrack(staffIdx * VOICES);
884                               t->setSig(lastTS);
885                               Segment* s = measure->getSegment(SegmentType::TimeSig, measure->tick());
886                               s->add(t);
887                               }
888                         }
889                   }
890             if (empty) {
891                   break;
892                   }
893             auto bar = sec.bars.front();
894             while (bar->denominator == 0) {
895                   if (sec.bars.size() == 1)
896                         break;
897                   sec.bars.pop_front();
898                   bar = sec.bars.front();
899                   }
900             if (bar->denominator == 0) {
901                   bar->denominator = measure->timesig().denominator();
902                   bar->numerator = measure->timesig().numerator();
903                   }
904             measure = createMeasure(bar.get(), measure->endTick());
905             if (repeatCount) {
906                   measure->setRepeatEnd(true);
907                   measure->setRepeatCount(repeatCount);
908                   }
909             repeatCount = bar->repeatClose;
910             if (bar->repeatStart) {
911                   measure->setRepeatStart(true);
912                   }
913             if (sec.bars.size() > 2) {
914                   sec.bars.pop_front();
915                   }
916             }
917       if (sec.bars.size()) {
918             auto bar = sec.bars.back();
919             if (bar->repeatStart) {
920                   measure->setRepeatStart(true);
921                   }
922             if (bar->repeatClose) {
923                   measure->setRepeatEnd(true);
924                   measure->setRepeatCount(bar->repeatClose);
925                   }
926             sec.bars.clear();
927             }
928 
929       }
930 
copyTracks(ptTrack * track)931 void PowerTab::ptSection::copyTracks(ptTrack* track)
932       {
933       //if not found GuitarIn in section or all tracks are read -> return
934       if (staves == int(staffMap.size())) {
935             return;
936             }
937 
938       auto signature = chordTextMap.begin();
939       for (unsigned index = 0; index < staffMap.size(); ++index) {
940             auto staff = (staffMap[index] + 1) * -1;
941             if (staff < 0) {
942                   continue;
943                   }
944 
945             for (const auto &rt : rhytm) {
946                   auto newSig = chordTextMap.find(rt.position);
947                   if (newSig != chordTextMap.end()) {
948                         signature = newSig;
949                         }
950 
951                   ptBeat* beat = new ptBeat(staff, 0);
952                   beat->position = rt.position;
953                   beat->duration = rt.duration;
954                   beat->dotted = rt.dotted;
955                   beat->doubleDotted = rt.doubleDotted;
956                   beat->isRest = rt.is_rest;
957                   beat->tuplet = rt.triplet;
958                   if (!rt.is_rest) {
959                         auto diagram = track->diagramMap.find({ {signature->second.key, signature->second.formula, signature->second.formula_mod} });
960                         for (unsigned int string = 0; string < diagram->second.frets.size(); ++string) {
961                               int fret = diagram->second.frets[string];
962                               if (fret >= 0xFE) {
963                                     continue;
964                                     }
965                               ptNote note;
966                               note.value = fret;
967                               note.str = string;
968                               if (fret == 0xFE) {
969                                     note.dead = true;
970                                     note.value = 0;
971                                     }
972                               beat->notes.emplace_back(note);
973                               }
974                         }
975                   while (int(beats.size()) <= staff) {
976                         beats.push_back({});
977                         }
978                   beats[staff].push_back(std::shared_ptr<ptBeat>(beat));
979                   }
980             }
981       }
982 
readSection(ptSection & sec)983 void PowerTab::readSection(ptSection& sec)
984       {
985       //rect:
986       readInt(); // left
987       readInt(); // top
988       readInt(); // right
989       readInt(); // bottom
990 
991       auto lastBarData = readUChar();
992 
993       skip(4); //spacing from staff
994 
995       readBarLine(sec);
996 
997       int itemCount = readHeaderItems();
998       for (int i = 0; i < itemCount; ++i) {
999             readDirection(sec);
1000             if (i < itemCount - 1) {
1001                   readShort();
1002                   }
1003             }
1004       //ChordText section
1005       itemCount = readHeaderItems();
1006       for (int i = 0; i < itemCount; ++i) {
1007             readChordText(sec);
1008             if (i < itemCount - 1) {
1009                   readShort();
1010                   }
1011             }
1012       //RhytmSlash
1013       itemCount = readHeaderItems();
1014       for (int i = 0; i < itemCount; ++i) {
1015             readRhytmSlash(sec);
1016             if (i < itemCount - 1)
1017                   readShort();
1018             }
1019       // Staff
1020       sec.staves = readHeaderItems();
1021       sec.staffMap = getStaffMap(sec);
1022       for (int i = 0; i < sec.staves; ++i) {
1023             int staff = sec.staffMap[i];
1024             readStaff(staff, sec);
1025             if (i < sec.staves - 1) {
1026                   readShort();
1027                   }
1028             }
1029       sec.copyTracks(curTrack);
1030       // MusicBar section
1031       itemCount = readHeaderItems();
1032       for (int i = 0; i < itemCount; ++i) {
1033             readBarLine(sec);
1034             if (i < itemCount - 1) {
1035                   readShort();
1036                   }
1037             }
1038 
1039       auto bar = new ptBar();
1040       bar->repeatClose = (lastBarData >> 5 == 4) ? lastBarData - 128 : 0;
1041       sec.bars.push_back(std::shared_ptr<ptBar>(bar));
1042       //sec.getPosition(sec.getNextPositionNumber()).addComponent(bar);
1043       }
1044 
readDirection(ptSection & sec)1045 void PowerTab::readDirection(ptSection& sec)
1046       {
1047       int position = readUChar();
1048       int symbolCount = readUChar();
1049       for (int i = 0; i < symbolCount; ++i) {
1050             unsigned int data = readShort();
1051             sec.getPosition(position).addComponent(new ptDirection((data >> 8), ((data & 0xC0) >> 6), (data & 0x1F)));
1052             }
1053       }
1054 
readDataInstruments(ptTrack & info)1055 void PowerTab::readDataInstruments(ptTrack& info)
1056       {
1057       curTrack = &info;
1058       //Guitar section
1059       auto itemCount = readHeaderItems();
1060       for (int i = 0; i < itemCount; ++i) {
1061             readTrackInfo(info);
1062             if (i < itemCount - 1) {
1063                   readShort();
1064                   }
1065             }
1066       // Chord Diagram Section
1067       itemCount = readHeaderItems();
1068       for (int i = 0; i < itemCount; ++i) {
1069             readChord(info);
1070             if (i < itemCount - 1) {
1071                   readShort();
1072                   }
1073             }
1074       //Floating Text section
1075       itemCount = readHeaderItems();
1076       for (int i = 0; i < itemCount; ++i) {
1077             readFloatingText();
1078             if (i < itemCount - 1) {
1079                   readShort();
1080                   }
1081             }
1082       // GuitarIn section
1083       itemCount = readHeaderItems();
1084       for (int i = 0; i < itemCount; ++i) {
1085             readGuitarIn(info);
1086             if (i < itemCount - 1) {
1087                   readShort();
1088                   }
1089             }
1090       // Tempo marker
1091       itemCount = readHeaderItems();
1092       for (int i = 0; i < itemCount; ++i) {
1093             readTempoMarker(info);
1094             if (i < itemCount - 1) {
1095                   readShort();
1096                   }
1097             }
1098       //Dynamic section
1099       itemCount = readHeaderItems();
1100       for (int i = 0; i < itemCount; ++i) {
1101             readDynamic();
1102             if (i < itemCount - 1) {
1103                   readShort();
1104                   }
1105             }
1106       //Symbol section
1107       itemCount = readHeaderItems();
1108       for (int i = 0; i < itemCount; ++i) {
1109             readSectionSymbol(info);
1110             if (i < itemCount - 1) {
1111                   readShort();
1112                   }
1113             }
1114       //Section section
1115       itemCount = readHeaderItems();
1116       for (int i = 0; i < itemCount; ++i) {
1117             readSection(info.getSection(i));
1118             if (i < itemCount - 1) {
1119                   readShort();
1120                   }
1121             }
1122       }
1123 
crTS(int strings,int tuning[])1124 std::string crTS(int strings, int tuning[])
1125       {
1126       const static char* tune[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
1127       std::vector<int> pitch;
1128       for (int i = 0; i < strings; ++i) {
1129             pitch.push_back(tuning[i]);
1130             }
1131       std::string t;
1132       for (auto i : pitch) {
1133             t += tune[i % 12];
1134             t += " ";
1135             }
1136       return t;
1137       }
1138 
1139 
createMeasure(ptBar * bar,const Fraction & tick)1140 Measure* PowerTab::createMeasure(ptBar* bar, const Fraction& tick)
1141       {
1142       auto measure = new Measure(score);
1143       Fraction nts(bar->numerator, bar->denominator);
1144 
1145       measure->setTick(tick);
1146       measure->setTimesig(nts);
1147       measure->setTicks(nts);
1148 
1149       score->measures()->add(measure);
1150 
1151       return measure;
1152       }
1153 
getSection(int ind)1154 PowerTab::ptSection& PowerTab::ptTrack::getSection(int ind)
1155       {
1156       for (int i = (int)sections.size(); i < ind + 1; ++i) {
1157             sections.push_back(ptSection(i));
1158             }
1159       return sections[ind];
1160       }
1161 
ptSection(int num)1162 PowerTab::ptSection::ptSection(int num)
1163       {
1164       number = num;
1165       }
1166 
getPosition(int pos)1167 PowerTab::ptPosition& PowerTab::ptSection::getPosition(int pos)
1168       {
1169       unsigned int i = 0;
1170       while ( i < positions.size() ) {
1171             auto& p = positions[i];
1172             if (p.position == pos) {
1173                   return p;
1174                   }
1175             ++i;
1176             }
1177       ptPosition p;
1178       p.position = pos;
1179       positions.emplace_back(p);
1180       return positions.back();
1181       }
1182 
getNextPositionNumber()1183 int PowerTab::ptSection::getNextPositionNumber()
1184       {
1185       int next = 0;
1186       unsigned int k = 0;
1187       while (k < positions.size()) {
1188             auto p = positions[k];
1189             next = std::max(next, p.position + 1);
1190             ++k;
1191             }
1192       return next;
1193       }
1194 
addComponent(ptComponent * c)1195 void PowerTab::ptPosition::addComponent(ptComponent* c)
1196       {
1197       components.push_back(std::shared_ptr<ptComponent>(c));
1198       }
1199 
1200 
1201 //---------------------------------------------------------
1202 //   read
1203 //---------------------------------------------------------
1204 
read()1205 Score::FileError PowerTab::read()
1206       {
1207       if (!readVersion())
1208             return Score::FileError::FILE_BAD_FORMAT;
1209       ptSong song;
1210 
1211       readSongInfo(song.info);
1212       readDataInstruments(song.track1);
1213       staffInc = int(song.track1.infos.size());
1214       lastStaffMap.clear();
1215       readDataInstruments(song.track1);
1216 
1217       staves = int(song.track1.infos.size());
1218 
1219       std::vector<tBeatList> parts(staves);
1220       for (int i = staffInc; i < staves; ++i) {
1221             for (auto& sec : song.track1.sections) {
1222                   while (int(sec.beats.size()) < staves)
1223                         sec.beats.push_back({});
1224                   parts[i].insert(parts[i].end(), sec.beats[i].begin(), sec.beats[i].end());
1225                   sec.beats[i].clear();
1226                   }
1227             }
1228 
1229       for (auto& sec : song.track1.sections) {
1230             for (int i = 0; i < staves; ++i) {
1231                   if (parts[i].size()) {
1232                         sec.beats[i].insert(sec.beats[i].begin(), parts[i].begin(), parts[i].end());
1233                         parts[i].clear();
1234                         }
1235                   }
1236             addToScore(sec);
1237             for (int i = 0; i < staves; ++i)
1238                   parts[i] = sec.beats[i];
1239             }
1240 
1241       score->style().set(Sid::ArpeggioHiddenInStdIfTab, true);
1242 
1243       MeasureBase* m;
1244       if (!score->measures()->first()) {
1245             m = new VBox(score);
1246             m->setTick(Fraction(0,1));
1247             score->addMeasure(m, 0);
1248             }
1249       else  {
1250             m = score->measures()->first();
1251             if (!m->isVBox()) {
1252                   MeasureBase* mb = new VBox(score);
1253                   mb->setTick(Fraction(0,1));
1254                   score->addMeasure(mb, m);
1255                   m = mb;
1256                   }
1257             }
1258       // create title
1259       std::string name = song.info.name;
1260       if (!name.empty()) {
1261             Text* s = new Text(score, Tid::TITLE);
1262             s->setPlainText(QString::fromUtf8(name.data(), int(name.size())));
1263             m->add(s);
1264             }
1265 
1266 //      static const char* tune[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
1267       int id = 0;
1268       for (Part* part : score->parts()) {
1269             QMultiMap<int, int> tracks;
1270             Score* pscore = new Score(score);
1271 
1272 //TODO-ws            pscore->tuning.clear();
1273             auto& info = song.track1.infos[id++];
1274             for (auto it = info.strings.rbegin(); it != info.strings.rend(); ++it) {
1275 //TODO-ws                  pscore->tuning += tune[*it % 12];
1276 //                  pscore->tuning += " ";
1277                   }
1278 
1279 
1280 //TODO-ws          pscore->showLyrics = score->showLyrics;
1281             pscore->style().set(Sid::createMultiMeasureRests, false);
1282             pscore->style().set(Sid::ArpeggioHiddenInStdIfTab, true);
1283 
1284             QList<int> stavesMap;
1285             Part* p = new Part(pscore);
1286             p->setInstrument(*part->instrument());
1287 
1288             Staff* staff = part->staves()->front();
1289 
1290             Staff* s = new Staff(pscore);
1291             s->setPart(p);
1292             const StaffType* st = staff->staffType(Fraction(0,1));
1293             s->setStaffType(Fraction(0,1), *st);
1294 
1295             s->linkTo(staff);
1296             p->staves()->append(s);
1297             pscore->staves().append(s);
1298             stavesMap.append(staff->idx());
1299             for (int i = staff->idx() * VOICES, j = 0; i < staff->idx() * VOICES + VOICES; i++, j++)
1300                   tracks.insert(i, j);
1301 
1302             Excerpt* excerpt = new Excerpt(score);
1303             excerpt->setTracks(tracks);
1304             excerpt->setPartScore(pscore);
1305             //title?
1306             excerpt->setTitle(part->instrument()->longNames()[0].name());
1307             pscore->setExcerpt(excerpt);
1308             excerpt->parts().append(part);
1309             score->excerpts().append(excerpt);
1310 
1311             Excerpt::cloneStaves(score, pscore, stavesMap, tracks);
1312 
1313             if (staff->part()->instrument()->stringData()->strings() > 0
1314                && part->staves()->front()->staffType(Fraction(0,1))->group() == StaffGroup::STANDARD) {
1315                   p->setStaves(2);
1316                   Staff* s1 = p->staff(1);
1317 
1318                   int lines = staff->part()->instrument()->stringData()->strings();
1319                   StaffTypes sts = StaffTypes::TAB_DEFAULT;
1320                   if (lines == 4)
1321                         sts = StaffTypes::TAB_4COMMON;
1322                   StaffType st1 = *StaffType::preset(sts);
1323                   s1->setStaffType(Fraction(0,1), st1);
1324                   s1->setLines(Fraction(0,1), lines);
1325                   Excerpt::cloneStaff(s, s1);
1326                   BracketItem* bi = new BracketItem(pscore, BracketType::NORMAL, 2);
1327                   p->staves()->front()->addBracket(bi);
1328                   }
1329             pscore->appendPart(p);
1330 
1331             //
1332             // create excerpt title
1333             //
1334             MeasureBase* measure = pscore->first();
1335             if (!measure || (measure->type() != ElementType::VBOX)) {
1336                   MeasureBase* mb = new VBox(pscore);
1337                   mb->setTick(Fraction(0,1));
1338                   pscore->addMeasure(mb, measure);
1339                   measure = mb;
1340                   }
1341             Text* txt = new Text(pscore, Tid::INSTRUMENT_EXCERPT);
1342             txt->setPlainText(part->longName());
1343             measure->add(txt);
1344 
1345             pscore->setPlaylistDirty();
1346             pscore->setLayoutAll();
1347             pscore->addLayoutFlags(LayoutFlag::FIX_PITCH_VELO);
1348             pscore->doLayout();
1349             }
1350       return Score::FileError::FILE_NO_ERROR;
1351       }
1352 
1353 }
1354